使用python3和node js加密解密
Encryption and decryption using python3 and node js
我正在尝试创建一个多平台加密解密机制,到目前为止我已经能够在 python 中加密并在 C 中解密,反之亦然,现在我正在尝试使用python 脚本和节点 js 脚本。我能够在节点 js 中加密字符串并在 python 中解密它,但是在节点中使用 python 的加密消息解密没有发生
这是 python 代码:
from Crypto.Cipher import AES
from Crypto.Random import get_random_bytes
from Crypto import Random
from base64 import b64decode
from base64 import b64encode
import json
import random
#iv= get_random_bytes(16)
key=b"aaaaaaaaaaaaaaaa"
iv= b"aaaaaaaaaaaaaaaa"
value = "Hello World"
strValue= str.encode(value)
data =strValue
#Encryption
data = b64encode(data)
pad =data + b"[=11=]" * (AES.block_size - len(data) % AES.block_size)
cipher = AES.new(key, AES.MODE_CBC, iv)
ciphertext= cipher.encrypt(pad)
print (type(ciphertext))
print(b64encode(ciphertext).decode("utf-8"))
# Decryption
cipher = AES.new(key, AES.MODE_CBC, iv)
data = cipher.decrypt(ciphertext)
print(b64decode(data))
这是 Nodejs 代码:
const crypto = require('crypto');
var iv = Buffer.from('aaaaaaaaaaaaaaaa')
var key = Buffer.from('aaaaaaaaaaaaaaaa')
var cipher = crypto.createCipheriv('aes-128-cbc', key, iv);
let enc= cipher.update( "Hello World");
console.log(typeof (enc))
enc += cipher.final('base64');
console.log("enc is :",enc)
var decipher = crypto.createDecipheriv('aes-128-cbc', key,iv);
let decrypted = decipher.update(enc, 'base64');
decrypted += decipher.final('utf8');
console.log("plain text is :",decrypted)
我从中获取了节点部分:
AES - Encryption with Crypto (node-js) / decryption with Pycrypto (python)
我收到错误:06065064:digital envelope routines:EVP_DecryptFinal_ex:bad decrypt
任何帮助将不胜感激,谢谢!
如果有更好的Node js实现方法请告知
在Python代码中,明文在加密前是Base64编码的,在NodeJS代码中不是。此外,Python 代码应用自定义零填充,NodeJS 代码应用默认 PKCS7 填充。
为了让NodeJS代码提供与Python代码相同的密文,明文必须在加密前进行Base64编码。此外,必须禁用默认的 PKCS7 填充,并且必须应用 Python 代码的零填充变体。由于 PyCryptodome 不支持零填充,因此需要自定义实现。
一个可能的 NodeJS 实现可能是:
const crypto = require('crypto')
const buffertrim = require('buffertrim')
function toB64padded(plaintext, blocksize){
var bufPlaintext = Buffer.from(plaintext, 'utf8')
var bufPlaintextB64 = Buffer.from(bufPlaintext.toString('base64'), 'utf8') // Base64 encoding
var bufPadding = Buffer.alloc(blocksize - bufPlaintextB64.length % blocksize)
return Buffer.concat([bufPlaintextB64, bufPadding]) // Zero padding
}
var iv = Buffer.from('aaaaaaaaaaaaaaaa') // Static IV only for testing purposes
var key = Buffer.from('aaaaaaaaaaaaaaaa')
// Encryption
var plaintext = "The quick brown fox jumps over the lazy dog"
var bufPlaintextB64padded = toB64padded(plaintext, 16) // Base64 encoding and Zero padding
var cipher = crypto.createCipheriv('aes-128-cbc', key, iv)
cipher.setAutoPadding(false) // Disable PKCS7 padding
var ciphertextB64 = cipher.update(bufPlaintextB64padded, '', 'base64') // Encryption, Base64 encoding of ciphertext
ciphertextB64 += cipher.final('base64')
console.log("ciphertext is:", ciphertextB64)
// Decryption
var decipher = crypto.createDecipheriv('aes-128-cbc', key, iv)
decipher.setAutoPadding(false) // Disable PKCS7 (un-) padding
var bufPlaintextB64padded = Buffer.concat([ // Base64 decoding of ciphertext, decryption
decipher.update(ciphertextB64, 'base64'),
decipher.final()
]);
var bufPlaintextB64 = buffertrim.trimEnd(bufPlaintextB64padded) // Unpadding (unreliable)
var bufPlaintext = Buffer.from(bufPlaintextB64.toString('utf8'), 'base64') // Base64 decoding
console.log("plaintext is:", bufPlaintext.toString('utf8'))
例如明文 The quick brown fox jumps over the lazy dog 使用 Python 代码和上面的 NodeJS 代码加密。两个代码都使用发布的密钥和 IV 生成相同的密文,即:
IETFUbiTGsKFZWLgjjP5RrKPX+GeVon1Kuy38bPdKXwqUJWUGWMJ9MOL9gEAsF+1U/N0Juwzu24Dju4UMwdZaA==
这意味着可以用一个代码加密并用另一个代码解密。
请注意,在加密之前,无需对明文进行Base64编码。此外,零填充是一种 不可靠 填充,最好用 PKCS7 填充代替。 PyCryptodome 支持使用 Crypto.Util.Padding
模块的 PKCS7 填充,因此填充不需要自定义实现。并且如前所述,NodeJS 的加密模块默认使用 PKCS7 填充。
此外,出于安全原因,每个加密都必须使用 random IV。 IV 不是秘密的,通常与密文连接在一起。在 Python 代码中实现了 IV 的随机生成(但被注释掉,可能出于测试目的)。但是,缺少连接部分。在 NodeJS 代码中,为了与 Python 代码兼容,两者都被省略了。
我正在尝试创建一个多平台加密解密机制,到目前为止我已经能够在 python 中加密并在 C 中解密,反之亦然,现在我正在尝试使用python 脚本和节点 js 脚本。我能够在节点 js 中加密字符串并在 python 中解密它,但是在节点中使用 python 的加密消息解密没有发生 这是 python 代码:
from Crypto.Cipher import AES
from Crypto.Random import get_random_bytes
from Crypto import Random
from base64 import b64decode
from base64 import b64encode
import json
import random
#iv= get_random_bytes(16)
key=b"aaaaaaaaaaaaaaaa"
iv= b"aaaaaaaaaaaaaaaa"
value = "Hello World"
strValue= str.encode(value)
data =strValue
#Encryption
data = b64encode(data)
pad =data + b"[=11=]" * (AES.block_size - len(data) % AES.block_size)
cipher = AES.new(key, AES.MODE_CBC, iv)
ciphertext= cipher.encrypt(pad)
print (type(ciphertext))
print(b64encode(ciphertext).decode("utf-8"))
# Decryption
cipher = AES.new(key, AES.MODE_CBC, iv)
data = cipher.decrypt(ciphertext)
print(b64decode(data))
这是 Nodejs 代码:
const crypto = require('crypto');
var iv = Buffer.from('aaaaaaaaaaaaaaaa')
var key = Buffer.from('aaaaaaaaaaaaaaaa')
var cipher = crypto.createCipheriv('aes-128-cbc', key, iv);
let enc= cipher.update( "Hello World");
console.log(typeof (enc))
enc += cipher.final('base64');
console.log("enc is :",enc)
var decipher = crypto.createDecipheriv('aes-128-cbc', key,iv);
let decrypted = decipher.update(enc, 'base64');
decrypted += decipher.final('utf8');
console.log("plain text is :",decrypted)
我从中获取了节点部分:
AES - Encryption with Crypto (node-js) / decryption with Pycrypto (python)
我收到错误:06065064:digital envelope routines:EVP_DecryptFinal_ex:bad decrypt
任何帮助将不胜感激,谢谢!
如果有更好的Node js实现方法请告知
在Python代码中,明文在加密前是Base64编码的,在NodeJS代码中不是。此外,Python 代码应用自定义零填充,NodeJS 代码应用默认 PKCS7 填充。
为了让NodeJS代码提供与Python代码相同的密文,明文必须在加密前进行Base64编码。此外,必须禁用默认的 PKCS7 填充,并且必须应用 Python 代码的零填充变体。由于 PyCryptodome 不支持零填充,因此需要自定义实现。
一个可能的 NodeJS 实现可能是:
const crypto = require('crypto')
const buffertrim = require('buffertrim')
function toB64padded(plaintext, blocksize){
var bufPlaintext = Buffer.from(plaintext, 'utf8')
var bufPlaintextB64 = Buffer.from(bufPlaintext.toString('base64'), 'utf8') // Base64 encoding
var bufPadding = Buffer.alloc(blocksize - bufPlaintextB64.length % blocksize)
return Buffer.concat([bufPlaintextB64, bufPadding]) // Zero padding
}
var iv = Buffer.from('aaaaaaaaaaaaaaaa') // Static IV only for testing purposes
var key = Buffer.from('aaaaaaaaaaaaaaaa')
// Encryption
var plaintext = "The quick brown fox jumps over the lazy dog"
var bufPlaintextB64padded = toB64padded(plaintext, 16) // Base64 encoding and Zero padding
var cipher = crypto.createCipheriv('aes-128-cbc', key, iv)
cipher.setAutoPadding(false) // Disable PKCS7 padding
var ciphertextB64 = cipher.update(bufPlaintextB64padded, '', 'base64') // Encryption, Base64 encoding of ciphertext
ciphertextB64 += cipher.final('base64')
console.log("ciphertext is:", ciphertextB64)
// Decryption
var decipher = crypto.createDecipheriv('aes-128-cbc', key, iv)
decipher.setAutoPadding(false) // Disable PKCS7 (un-) padding
var bufPlaintextB64padded = Buffer.concat([ // Base64 decoding of ciphertext, decryption
decipher.update(ciphertextB64, 'base64'),
decipher.final()
]);
var bufPlaintextB64 = buffertrim.trimEnd(bufPlaintextB64padded) // Unpadding (unreliable)
var bufPlaintext = Buffer.from(bufPlaintextB64.toString('utf8'), 'base64') // Base64 decoding
console.log("plaintext is:", bufPlaintext.toString('utf8'))
例如明文 The quick brown fox jumps over the lazy dog 使用 Python 代码和上面的 NodeJS 代码加密。两个代码都使用发布的密钥和 IV 生成相同的密文,即:
IETFUbiTGsKFZWLgjjP5RrKPX+GeVon1Kuy38bPdKXwqUJWUGWMJ9MOL9gEAsF+1U/N0Juwzu24Dju4UMwdZaA==
这意味着可以用一个代码加密并用另一个代码解密。
请注意,在加密之前,无需对明文进行Base64编码。此外,零填充是一种 不可靠 填充,最好用 PKCS7 填充代替。 PyCryptodome 支持使用 Crypto.Util.Padding
模块的 PKCS7 填充,因此填充不需要自定义实现。并且如前所述,NodeJS 的加密模块默认使用 PKCS7 填充。
此外,出于安全原因,每个加密都必须使用 random IV。 IV 不是秘密的,通常与密文连接在一起。在 Python 代码中实现了 IV 的随机生成(但被注释掉,可能出于测试目的)。但是,缺少连接部分。在 NodeJS 代码中,为了与 Python 代码兼容,两者都被省略了。