我正在使用CryptoJS(v 2.3)在Web应用程序中加密字符串,我需要在Python中在服务器上解密它,所以我正在使用PyCrypto。我觉得我错过了一些东西,因为我无法工作。
这是JS:
Crypto.AES.encrypt('1234567890123456', '1234567890123456',
{mode: new Crypto.mode.CBC(Crypto.pad.ZeroPadding)})
// output: "wRbCMWcWbDTmgXKCjQ3Pd//aRasZ4mQr57DgTfIvRYE="
蟒蛇:
from Crypto.Cipher import AES
import base64
decryptor = AES.new('1234567890123456', AES.MODE_CBC)
decryptor.decrypt(base64.b64decode("wRbCMWcWbDTmgXKCjQ3Pd//aRasZ4mQr57DgTfIvRYE="))
# output: '\xd0\xc2\x1ew\xbb\xf1\xf2\x9a\xb9\xb6\xdc\x15l\xe7\xf3\xfa\xed\xe4\xf5j\x826\xde(m\xdf\xdc_\x9e\xd3\xb1'
这是CryptoJS 3.1.2的一个版本。始终注意以下事项(在两种语言中使用相同的):
如果将字符串作为key
参数传递给CryptoJS encrypt()
函数,则该字符串用于派生用于加密的实际密钥。如果您希望使用密钥(有效大小为16,24和32字节),则需要将其作为WordArray传递。
CryptoJS加密的结果是OpenSSL格式的密文字符串。要从中获取实际的密文,您需要访问它上面的ciphertext
属性。
对于每个加密,IV必须是随机的,以便它在语义上是安全的。这样,攻击者无法说出多次加密的同一明文在仅查看密文时是否实际上是同一个明文。
以下是我所做的一个例子。
JavaScript的:
var key = CryptoJS.enc.Utf8.parse('1234567890123456');
function encrypt(msgString, key) {
// msgString is expected to be Utf8 encoded
var iv = CryptoJS.lib.WordArray.random(16);
var encrypted = CryptoJS.AES.encrypt(msgString, key, {
iv: iv
});
return iv.concat(encrypted.ciphertext).toString(CryptoJS.enc.Base64);
}
function decrypt(ciphertextStr, key) {
var ciphertext = CryptoJS.enc.Base64.parse(ciphertextStr);
// split IV and ciphertext
var iv = ciphertext.clone();
iv.sigBytes = 16;
iv.clamp();
ciphertext.words.splice(0, 4); // delete 4 words = 16 bytes
ciphertext.sigBytes -= 16;
// decryption
var decrypted = CryptoJS.AES.decrypt({ciphertext: ciphertext}, key, {
iv: iv
});
return decrypted.toString(CryptoJS.enc.Utf8);
}
Python代码:
BLOCK_SIZE = 16
key = b"1234567890123456"
def pad(data):
length = BLOCK_SIZE - (len(data) % BLOCK_SIZE)
return data + chr(length)*length
def unpad(data):
return data[:-ord(data[-1])]
def encrypt(message, passphrase):
IV = Random.new().read(BLOCK_SIZE)
aes = AES.new(passphrase, AES.MODE_CBC, IV)
return base64.b64encode(IV + aes.encrypt(pad(message)))
def decrypt(encrypted, passphrase):
encrypted = base64.b64decode(encrypted)
IV = encrypted[:BLOCK_SIZE]
aes = AES.new(passphrase, AES.MODE_CBC, IV)
return unpad(aes.decrypt(encrypted[BLOCK_SIZE:]))
其他考虑:
您似乎想要使用密码作为密钥。密码短语通常是人类可读的,但密钥则不是。您可以使用包含PBKDF2,bcrypt或scrypt等功能的密码来派生密钥。
上面的代码并不完全安全,因为它缺乏身份验证。未经验证的密文可能会导致可行的攻击和未被注意的数据操作。通常,加密然后MAC方案与良好的MAC功能一起使用,例如HMAC-SHA256。