这里是CryptoJS 3.1.2的一个版本。总是提防以下事(使用相同的两种语言):
- 操作的模式(CBC在这种情况下)
- 填充(零填充在这种情况下,更好地利用PKCS#7填充)
- 密钥(相同的推导函数或清除键)
- 编码(用于密钥,明文,密文相同的编码,...)
- IV(加密过程中产生的,通过了解密)
如果将字符串作为参数传递给CryptoJS encrypt()
函数,则该字符串用于派生用于加密的实际密钥。如果你想使用一个键(有效的大小是16,24和32字节),那么你需要将它作为一个WordArray传递。
CryptoJS加密的结果是OpenSSL格式的密文字符串。要从中获取实际的密文,您需要访问其上的ciphertext
属性。
对于每个加密,IV必须是随机的,以便它在语义上是安全的。那样的话,攻击者无法说出只有在查看密文时,被多次加密的相同明文是否实际上是相同的明文。
的JavaScript:
var key = CryptoJS.enc.Utf8.parse('123456789');
function encrypt(msgString, key) {
// msgString is expected to be Utf8 encoded
var iv = CryptoJS.lib.WordArray.random(16);
var encrypted = Crypto.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"123456789"
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。
你是对的 – ian 2012-07-19 19:23:14