我试图在 golang 中编码字符串等同于 javascript cryptoJs 库,但是当使用 golang 和 javascript 加密时结果不一样!
这段代码在 js 中创建了一个 128 位密码
javascript代码:
let message = 'I need encrypt this message with CryptoJS.AES.encrypt and decrypt with Golang AES package';
let key = 'key created dynamically and key.length not in AES length standard';
// convert to word array
message = CryptoJS.enc.Utf8.parse(message)
key = CryptoJS.enc.Utf8.parse(key)
// create hash
const hash = CryptoJS.AES.encrypt(message, key, {
mode: CryptoJS.mode.ECB,
padding: CryptoJS.pad.ZeroPadding
}).ciphertext.toString(CryptoJS.enc.Hex)
在此代码段中,cryptoJs aes 加密函数接受不同大小的密钥字符串,但在 golang aes 包中只接受标准大小,如 16,32。
AES 加密需要 128、192 或 256 位(16、24 或 32 字节)的固定长度密钥。如果要使用任意大小的密钥,可以使用诸如 PBKDF2(基于密码的密钥派生函数 2)的密钥派生函数从可变长度密钥派生出固定长度的密钥。这是一个如何在 Golang 和 Node.js 中执行此操作的示例:
package main
import (
"crypto/aes"
"crypto/cipher"
"crypto/rand"
"crypto/sha256"
"encoding/hex"
"fmt"
"io"
"golang.org/x/crypto/pbkdf2"
)
func encrypt(text string, key []byte) string {
salt := make([]byte, 8)
if _, err := io.ReadFull(rand.Reader, salt); err != nil {
panic(err)
}
derivedKey := pbkdf2.Key(key, salt, 4096, 32, sha256.New)
block, err := aes.NewCipher(derivedKey)
if err != nil {
panic(err.Error())
}
ciphertext := make([]byte, aes.BlockSize+len(text))
iv := ciphertext[:aes.BlockSize]
if _, err := io.ReadFull(rand.Reader, iv); err != nil {
panic(err)
}
stream := cipher.NewCFBEncrypter(block, iv)
stream.XORKeyStream(ciphertext[aes.BlockSize:], []byte(text))
return fmt.Sprintf("%x%x", salt, ciphertext)
}
func main() {
key := []byte("a very secret key")
message := "Hello World!"
encryptedMessage := encrypt(message, key)
fmt.Println(encryptedMessage)
}
const crypto = require('crypto');
function decrypt(encrypted, key) {
const encryptedBuffer = Buffer.from(encrypted, 'hex');
const salt = encryptedBuffer.slice(0, 8);
const iv = encryptedBuffer.slice(8, 24);
const encryptedText = encryptedBuffer.slice(24);
const derivedKey = crypto.pbkdf2Sync(key, salt, 4096, 32, 'sha256');
const decipher = crypto.createDecipheriv('aes-256-cfb', derivedKey, iv);
let decrypted = decipher.update(encryptedText);
decrypted = Buffer.concat([decrypted, decipher.final()]);
return decrypted.toString();
}
const key = 'a very secret key';
const encryptedMessage = '...'; // The encrypted message from the Golang code
const decryptedMessage = decrypt(encryptedMessage, key);
console.log(decryptedMessage);
此代码使用Golang中
pbkdf2
包中的golang.org/x/crypto/pbkdf2
函数和Node.js中pbkdf2Sync
模块中的crypto
方法,使用PBKDF2算法从可变长度密钥中导出固定长度密钥以 SHA-256 作为哈希函数。然后使用派生密钥创建 AES 密码并像以前一样加密/解密消息。