Blowfish 结果在 OpenSSL 和 Golang 之间是不同的
Blowfish results are different between OpenSSL and Golang
我想用 Go 读取 VIM 编码的文件。 This code 适用于小文件,所以我决定将其转换为 Go。密钥生成工作正常,但 Blowfish 编码没有。我已经将问题追溯到 BF_encrypt 和 cipher.Encrypt(...).
的不同结果
输入
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;
}
你能看出问题出在哪里吗?
问题出在变量 data
和 encrypted
的字节序上。在 C 代码中,data
(8 字节)从字节数组转换为 unsigned int
(32 位小端),然后就地加密。它影响输入和加密结果的字节顺序。要在 Golang 中获得相同的结果,您必须执行字节序转换,例如
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)
}
我想用 Go 读取 VIM 编码的文件。 This code 适用于小文件,所以我决定将其转换为 Go。密钥生成工作正常,但 Blowfish 编码没有。我已经将问题追溯到 BF_encrypt 和 cipher.Encrypt(...).
的不同结果输入
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;
}
你能看出问题出在哪里吗?
问题出在变量 data
和 encrypted
的字节序上。在 C 代码中,data
(8 字节)从字节数组转换为 unsigned int
(32 位小端),然后就地加密。它影响输入和加密结果的字节顺序。要在 Golang 中获得相同的结果,您必须执行字节序转换,例如
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)
}