GO解密nodejs已弃用的数据加密方法?
GO decryption nodejs has been deprecated data encryption method?
这是我接手的一个有4年历史的nodejs项目,我被要求使用golang重构它,但在重构中我发现nodejs加密被弃用了。而且,我不知道使用哪种AES模式来加密此代码
哪位高手可以帮我看看如何用golang解密这个nodejs加密?非常感谢!
nodejs的加密代码:
exports.createToken = function (src: string, timestamp: string, key: any) {
var msg = src + '|' + timestamp;
var cipher: any = CryptoJS.createCipher('aes256', key);
var enc: any = cipher.update(msg, 'utf8', 'hex');
enc += cipher.final('hex');
return enc;
};
nodejs解密代码:
exports.parseToken = function (token: string, key: string): any {
let decipher = CryptoJS.createDecipher('aes256', key);
let dec: string;
try {
dec = decipher.update(token, 'hex', 'utf8');
dec += decipher.final('utf8');
} catch (err) {
console.error('[token] fail to decrypt token. %j', token);
return null;
}
var ts = dec.split('|');
if (ts.length !== 2) {
// illegal token
return null;
}
return { src: ts[0], timestamp: Number(ts[1]) };
};
已弃用的方法 crypto.createCipher()
and crypto.createDecipher()
apply the proprietary OpenSSL function EVP_BytesToKey()
从密码派生 32 字节密钥和 16 字节 IV。没有使用盐,摘要MD5和迭代计数为1。这个算法非常不安全,这就是为什么这两种方法都被弃用的原因。
发布的代码应用 aes-256-cbc
(即 CBC 模式下的 AES-256)并且仅此密钥派生来派生 key/IV 对。由于密钥推导不使用盐,因此对于相同的明文和密码,始终会产生相同的密文。例如。对于:
var src = 'The quick brown fox jumps over the lazy dog';
var timestamp = '1616409134831';
var passphrase = 'my secret passphrase';
密文为:
60673700fb64da36b65829ee3c578d1ec675638a95c8dee4e7c026ee72a837c2170c13b7b24125c02871663a64fd646dd9994793943eeb70b3e959cbc4cd423a
因此,对于 Go 中的解密,您需要 EVP_BytesToKey()
的实现,例如here:
package main
import (
"crypto/aes"
"crypto/cipher"
"fmt"
"github.com/walkert/go-evp"
"encoding/hex"
)
func main() {
key, iv := evp.BytesToKeyAES256CBCMD5([]byte(""), []byte("my secret passphrase")) // MD5, no salt, passprase: my secret passphrase
ciphertext, _ := hex.DecodeString("60673700fb64da36b65829ee3c578d1ec675638a95c8dee4e7c026ee72a837c2170c13b7b24125c02871663a64fd646dd9994793943eeb70b3e959cbc4cd423a")
block, err := aes.NewCipher(key)
if err != nil {
panic(err)
}
cbc := cipher.NewCBCDecrypter(block, iv)
plaintextPadded := make([]byte, len(ciphertext))
cbc.CryptBlocks(plaintextPadded , ciphertext)
plaintext := string(PKCS7Unpad(plaintextPadded ))
fmt.Println("Decrypted data: ", string(plaintext))
}
func PKCS7Unpad(src []byte) []byte { // PKCS7 unpadding from
length := len(src)
unpadding := int(src[length-1])
return src[:(length - unpadding)]
}
运行这段代码产生了上面的明文。
这是我接手的一个有4年历史的nodejs项目,我被要求使用golang重构它,但在重构中我发现nodejs加密被弃用了。而且,我不知道使用哪种AES模式来加密此代码
哪位高手可以帮我看看如何用golang解密这个nodejs加密?非常感谢!
nodejs的加密代码:
exports.createToken = function (src: string, timestamp: string, key: any) {
var msg = src + '|' + timestamp;
var cipher: any = CryptoJS.createCipher('aes256', key);
var enc: any = cipher.update(msg, 'utf8', 'hex');
enc += cipher.final('hex');
return enc;
};
nodejs解密代码:
exports.parseToken = function (token: string, key: string): any {
let decipher = CryptoJS.createDecipher('aes256', key);
let dec: string;
try {
dec = decipher.update(token, 'hex', 'utf8');
dec += decipher.final('utf8');
} catch (err) {
console.error('[token] fail to decrypt token. %j', token);
return null;
}
var ts = dec.split('|');
if (ts.length !== 2) {
// illegal token
return null;
}
return { src: ts[0], timestamp: Number(ts[1]) };
};
已弃用的方法 crypto.createCipher()
and crypto.createDecipher()
apply the proprietary OpenSSL function EVP_BytesToKey()
从密码派生 32 字节密钥和 16 字节 IV。没有使用盐,摘要MD5和迭代计数为1。这个算法非常不安全,这就是为什么这两种方法都被弃用的原因。
发布的代码应用 aes-256-cbc
(即 CBC 模式下的 AES-256)并且仅此密钥派生来派生 key/IV 对。由于密钥推导不使用盐,因此对于相同的明文和密码,始终会产生相同的密文。例如。对于:
var src = 'The quick brown fox jumps over the lazy dog';
var timestamp = '1616409134831';
var passphrase = 'my secret passphrase';
密文为:
60673700fb64da36b65829ee3c578d1ec675638a95c8dee4e7c026ee72a837c2170c13b7b24125c02871663a64fd646dd9994793943eeb70b3e959cbc4cd423a
因此,对于 Go 中的解密,您需要 EVP_BytesToKey()
的实现,例如here:
package main
import (
"crypto/aes"
"crypto/cipher"
"fmt"
"github.com/walkert/go-evp"
"encoding/hex"
)
func main() {
key, iv := evp.BytesToKeyAES256CBCMD5([]byte(""), []byte("my secret passphrase")) // MD5, no salt, passprase: my secret passphrase
ciphertext, _ := hex.DecodeString("60673700fb64da36b65829ee3c578d1ec675638a95c8dee4e7c026ee72a837c2170c13b7b24125c02871663a64fd646dd9994793943eeb70b3e959cbc4cd423a")
block, err := aes.NewCipher(key)
if err != nil {
panic(err)
}
cbc := cipher.NewCBCDecrypter(block, iv)
plaintextPadded := make([]byte, len(ciphertext))
cbc.CryptBlocks(plaintextPadded , ciphertext)
plaintext := string(PKCS7Unpad(plaintextPadded ))
fmt.Println("Decrypted data: ", string(plaintext))
}
func PKCS7Unpad(src []byte) []byte { // PKCS7 unpadding from
length := len(src)
unpadding := int(src[length-1])
return src[:(length - unpadding)]
}
运行这段代码产生了上面的明文。