使用 python 编码和使用 nodejs 编码时得到不同的结果
getting different results when encoding with python and when encoding with nodejs
我正在尝试使用 pycrypto 使用 python 对特定字符串进行编码,并使用带有 crypto 的 nodejs 对相同的字符串进行编码。
对于相同的输入字符串
,我在两种情况下都得到了不同的结果
python代码:
from Crypto.Cipher import AES
from hashlib import md5
import base64
password = 'aquickbrownfoxjumpsoverthelazydog'
input = 'hello+world'
BLOCK_SIZE = 16
def pad (data):
pad = BLOCK_SIZE - len(data) % BLOCK_SIZE
return data + pad * chr(pad)
def unpad (padded):
pad = ord(padded[-1])
return padded[:-pad]
def text_encrypt(data, nonce, password):
m = md5()
m.update(password)
key = m.hexdigest()
m = md5()
m.update(password + key)
iv = m.hexdigest()
data = pad(data)
aes = AES.new(key, AES.MODE_CBC, iv[:16])
encrypted = aes.encrypt(data)
return base64.urlsafe_b64encode(encrypted)
output = text_encrypt(input, "", password)
print output
而nodejs代码如下:
var crypto = require('crypto');
var password = 'aquickbrownfoxjumpsoverthelazydog';
var input = 'hello+world';
var encrypt = function (input, password, callback) {
var m = crypto.createHash('md5');
m.update(password)
var key = m.digest('hex');
m = crypto.createHash('md5');
m.update(password + key)
var iv = m.digest('hex');
var data = new Buffer(input, 'utf8').toString('binary');
var cipher = crypto.createCipheriv('aes-256-cbc', key, iv.slice(0,16));
var nodev = process.version.match(/^v(\d+)\.(\d+)/);
var encrypted;
if( nodev[1] === '0' && parseInt(nodev[2]) < 10) {
encrypted = cipher.update(data, 'binary') + cipher.final('binary');
} else {
encrypted = cipher.update(data, 'utf8', 'binary') + cipher.final('binary');
}
var encoded = new Buffer(encrypted, 'binary').toString('base64');
callback(encoded);
};
encrypt(input, password, function (encoded) {
console.log(encoded);
});
两种情况的结果不同,但解密后它们都倾向于给出相同的正确结果。
这可能是什么问题?
您没有具体说明您得到的结果有何不同,但这两者应该会产生相同的结果。我看到的唯一区别在于您使用的 base64 字母表。
在 Python 中,您调用 base64.urlsafe_b64encode()
which differs from the standard Base64 时使用的字符是 62
和 63
的值(-
和 _
而不是 +
和 /
)。要获得相同的结果,请在 Python return:
return base64.b64encode(encrypted)
或post-处理Node.js中的base64编码字符串:
encoded = encoded.replace(/_/g, '/').replace(/-/g, '+');
话虽这么说,正如我在评论中提到的那样,永远不要从您的 password/key(或任何其他确定性和不变的)中派生 IV。为它使用 cryptographically secure PRNG。
我正在尝试使用 pycrypto 使用 python 对特定字符串进行编码,并使用带有 crypto 的 nodejs 对相同的字符串进行编码。 对于相同的输入字符串
,我在两种情况下都得到了不同的结果python代码:
from Crypto.Cipher import AES
from hashlib import md5
import base64
password = 'aquickbrownfoxjumpsoverthelazydog'
input = 'hello+world'
BLOCK_SIZE = 16
def pad (data):
pad = BLOCK_SIZE - len(data) % BLOCK_SIZE
return data + pad * chr(pad)
def unpad (padded):
pad = ord(padded[-1])
return padded[:-pad]
def text_encrypt(data, nonce, password):
m = md5()
m.update(password)
key = m.hexdigest()
m = md5()
m.update(password + key)
iv = m.hexdigest()
data = pad(data)
aes = AES.new(key, AES.MODE_CBC, iv[:16])
encrypted = aes.encrypt(data)
return base64.urlsafe_b64encode(encrypted)
output = text_encrypt(input, "", password)
print output
而nodejs代码如下:
var crypto = require('crypto');
var password = 'aquickbrownfoxjumpsoverthelazydog';
var input = 'hello+world';
var encrypt = function (input, password, callback) {
var m = crypto.createHash('md5');
m.update(password)
var key = m.digest('hex');
m = crypto.createHash('md5');
m.update(password + key)
var iv = m.digest('hex');
var data = new Buffer(input, 'utf8').toString('binary');
var cipher = crypto.createCipheriv('aes-256-cbc', key, iv.slice(0,16));
var nodev = process.version.match(/^v(\d+)\.(\d+)/);
var encrypted;
if( nodev[1] === '0' && parseInt(nodev[2]) < 10) {
encrypted = cipher.update(data, 'binary') + cipher.final('binary');
} else {
encrypted = cipher.update(data, 'utf8', 'binary') + cipher.final('binary');
}
var encoded = new Buffer(encrypted, 'binary').toString('base64');
callback(encoded);
};
encrypt(input, password, function (encoded) {
console.log(encoded);
});
两种情况的结果不同,但解密后它们都倾向于给出相同的正确结果。
这可能是什么问题?
您没有具体说明您得到的结果有何不同,但这两者应该会产生相同的结果。我看到的唯一区别在于您使用的 base64 字母表。
在 Python 中,您调用 base64.urlsafe_b64encode()
which differs from the standard Base64 时使用的字符是 62
和 63
的值(-
和 _
而不是 +
和 /
)。要获得相同的结果,请在 Python return:
return base64.b64encode(encrypted)
或post-处理Node.js中的base64编码字符串:
encoded = encoded.replace(/_/g, '/').replace(/-/g, '+');
话虽这么说,正如我在评论中提到的那样,永远不要从您的 password/key(或任何其他确定性和不变的)中派生 IV。为它使用 cryptographically secure PRNG。