2017-05-31 41 views
1

我想在Go中读取VIM编码的文件。 This code适用于小文件,因此我决定将它转换为Go。密钥生成工作正常,但Blowfish编码不会。我将问题追溯到BF_encrypt和cipher.Encrypt(...)的不同结果。OpenSSL和Golang之间的河豚结果不同

输入

key: c904a7a85bbd975324c5083ed96ff022f25e062da1d575b2462c2c98d8d64d9d 
data: 538b7759834d3418 

输出

Golang: b5cf33144acbc794 
C:  90baa70ec3e44867 

Golang代码:

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\n", key) 
    fmt.Printf("data: %x\n", data) 

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

的C代码:

#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("\n"); 
    printf("data: "); 
    for (int j = 0; j < 8; j++) printf("%02x", data[j]); 
    printf("\n"); 

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

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

    return 0; 
} 

你能看到问题在哪里吗?

+0

有趣。试试PHP来打破僵局:)。我使用了一个C++的河豚源(Jim Conger's),它在输出中使用了不同于其他字节的字节顺序,但这不是问题。 –

+1

您应该找到一些[Blowfish测试媒介](https://www.google.com/search?q=blowfish+test+vectors)并查看哪个(如果有的话)到达正确的结果。 – jww

+1

根据['BF_encrypt'手册页](https://linux.die.net/man/3/bf_encrypt):*“BF_encrypt()和BF_decrypt()是Blowfish加密的最低级别函数,它们加密/使用密钥对数据指向的前64位数据进行解密,除非你实现Blowfish的'modes',否则不应该使用这些函数,或者使用BF_ecb_encrypt(),如果你仍然想使用这些函数,你应该知道它们以主机字节顺序取得每个32位块,这在小端平台上是小端的,在大端端是大端的。“*。 – jww

回答

3

问题出在变量dataencrypted的字节顺序上。在C代码中,data(8字节)从字节数组转换为unsigned int(32位小端),然后进行加密。它会影响输入和加密结果的字节顺序。要在Golang中获得相同的结果,您必须执行endian转换,例如

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\n", key) 
    fmt.Printf("data: %x\n", cdata) 

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

    //Add: This is equal to {uint32, uint32} --> byte array 
    ce, _ := convertEndian(encrypted) 
    fmt.Printf("encrypted-2: %02x\n", ce) 
} 
相关问题