在OpenSSL和Golang之间,河豚结果有所不同

I want to read VIM encoded files in Go. This code works good enough for small file so I've decided to convert it to Go. Key generation works fine, but Blowfish encoding does not. I've traced the problem to different outcome from BF_encrypt and cipher.Encrypt(...).

Input

key: c904a7a85bbd975324c5083ed96ff022f25e062da1d575b2462c2c98d8d64d9d
data: 538b7759834d3418

Output

Golang: b5cf33144acbc794
C:      90baa70ec3e44867

Golang code:

package main

import (
    "fmt"
    "golang.org/x/crypto/blowfish"
)

func main() {
    key := []byte{0xc9, 0x04, 0xa7, 0xa8, 0x5b, 0xbd, 0x97, 0x53, 0x24, 0xc5, 0x08, 0x3e, 0xd9, 0x6f, 0xf0, 0x22, 0xf2, 0x5e, 0x06, 0x2d, 0xa1, 0xd5, 0x75, 0xb2, 0x46, 0x2c, 0x2c, 0x98, 0xd8, 0xd6, 0x4d, 0x9d}
    data := []byte{0x53, 0x8b, 0x77, 0x59, 0x83, 0x4d, 0x34, 0x18}

    cipher, err := blowfish.NewCipher(key)
    if err != nil {
        panic(err)
    }

    fmt.Printf("key: %x
", key)
    fmt.Printf("data: %x
", data)

    encrypted := make([]byte, 8)
    cipher.Encrypt(encrypted, data)
    fmt.Printf("encrypted: %x
", encrypted)
}

C code:

#include <stdio.h>
#include <string.h>
#include <openssl/blowfish.h>
#include <openssl/sha.h>

/*
clang test1.c -o test1 \
-I/usr/local/Cellar/openssl/1.0.2k/include \
-L/usr/local/Cellar/openssl/1.0.2k/lib \
-lcrypto
./test1
*/

int main(int argc, char *argv[]) {
    unsigned char key[32] = {0xc9, 0x04, 0xa7, 0xa8, 0x5b, 0xbd, 0x97, 0x53, 0x24, 0xc5, 0x08, 0x3e, 0xd9, 0x6f, 0xf0, 0x22, 0xf2, 0x5e, 0x06, 0x2d, 0xa1, 0xd5, 0x75, 0xb2, 0x46, 0x2c, 0x2c, 0x98, 0xd8, 0xd6, 0x4d, 0x9d};
    unsigned char data[8] = {0x53, 0x8b, 0x77, 0x59, 0x83, 0x4d, 0x34, 0x18};

    BF_KEY bf_key;
    BF_set_key(&bf_key, 32, key);

    printf("key: ");
    for (int j = 0; j < 32; j++) printf("%02x", key[j]);
    printf("
");
    printf("data: ");
    for (int j = 0; j < 8; j++) printf("%02x", data[j]);
    printf("
");

    BF_encrypt((unsigned int*)data, &bf_key);

    printf("encrypted: ");
    for (int j = 0; j < 8; j++) printf("%02x", data[j]);
    printf("
");

    return 0;
}

Can you see where the problem is?

douqiang5809
douqiang5809 根据BF_encrypt手册页:“BF_encrypt()和BF_decrypt()是Blowfish加密的最低级别函数。它们使用密钥对数据指向的向量的前64位进行加密/解密。不应使用这些函数。除非您实现Blowfish的“模式”,否则可以使用BF_ecb_encrypt()。如果您仍要使用这些功能,则应注意,它们以主机字节顺序获取每个32位块,即little-endian在little-endian平台上,big-endian在big-endian平台上”。
3 年多之前 回复
dsk95913
dsk95913 您可能应该找到一些河豚测试向量,并查看哪些(如果有)得出正确的结果。
3 年多之前 回复
douqiao6015
douqiao6015 有趣。尝试使用PHP抢七局:)。我使用了一个C++河豚源(JimConger的源代码),其输出的字节顺序与其他人的字节顺序不同,但这不是问题所在。
3 年多之前 回复

1个回答

The problem is in the endianness of variable data and encrypted. In the C code, data (8-bytes) is converted from byte array to unsigned int(32-bit little-endian), then being encrypted in place. It affects the endianness of both input and encrypted result. To get same result in Golang, you must perform endian conversion, e.g.

package main

import (
    "bytes"
    "fmt"

    "encoding/binary"

    "golang.org/x/crypto/blowfish"
)

func convertEndian(in []byte) ([]byte, error) {
    //Read byte array as uint32 (little-endian)
    var v1, v2 uint32
    buf := bytes.NewReader(in)
    if err := binary.Read(buf, binary.LittleEndian, &v1); err != nil {
        return nil, err
    }
    if err := binary.Read(buf, binary.LittleEndian, &v2); err != nil {
        return nil, err
    }

    //convert uint32 to byte array
    out := make([]byte, 8)
    binary.BigEndian.PutUint32(out, v1)
    binary.BigEndian.PutUint32(out[4:], v2)

    return out, nil
}

func main() {
    key := []byte{0xc9, 0x04, 0xa7, 0xa8, 0x5b, 0xbd, 0x97, 0x53, 0x24, 0xc5, 0x08, 0x3e, 0xd9, 0x6f, 0xf0, 0x22, 0xf2, 0x5e, 0x06, 0x2d, 0xa1, 0xd5, 0x75, 0xb2, 0x46, 0x2c, 0x2c, 0x98, 0xd8, 0xd6, 0x4d, 0x9d}
    data := []byte{0x53, 0x8b, 0x77, 0x59, 0x83, 0x4d, 0x34, 0x18}

    //Add: This is equal to: (unsigned int *)data in C
    cdata, _ := convertEndian(data)

    cipher, err := blowfish.NewCipher(key)
    if err != nil {
        panic(err)
    }

    fmt.Printf("key: %x
", key)
    fmt.Printf("data: %x
", cdata)

    encrypted := make([]byte, 8)
    cipher.Encrypt(encrypted, cdata)
    fmt.Printf("encrypted-1: %x
", encrypted)

    //Add: This is equal to {uint32, uint32} --> byte array
    ce, _ := convertEndian(encrypted)
    fmt.Printf("encrypted-2: %02x
", ce)
}
Csdn user default icon
上传中...
上传图片
插入图片
抄袭、复制答案,以达到刷声望分或其他目的的行为,在CSDN问答是严格禁止的,一经发现立刻封号。是时候展现真正的技术了!
立即提问
相关内容推荐