我需要在 python 中简单地加密一些文本并能够在 JavaScrypt 中解密。
到目前为止我在 python 中有:
from Crypto import Random
from Crypto.Cipher import AES
import base64
BLOCK_SIZE = 16
key = "1234567890123456" # want to be 16 chars
textToEncrypt = "This is text to encrypt"
def encrypt(message, passphrase):
# passphrase MUST be 16, 24 or 32 bytes long, how can I do that ?
IV = Random.new().read(BLOCK_SIZE)
aes = AES.new(passphrase, AES.MODE_CFB, IV)
return base64.b64encode(aes.encrypt(message))
def decrypt(encrypted, passphrase):
IV = Random.new().read(BLOCK_SIZE)
aes = AES.new(passphrase, AES.MODE_CFB, IV)
return aes.decrypt(base64.b64decode(encrypted))
print encrypt( textToEncrypt, key )
这是生成文本:ZF9as5JII5TlqcB5tAd4sxPuBXd5TrgE
在 JavaScript 中:
<script src="http://crypto-js.googlecode.com/svn/tags/3.1.2/build/rollups/aes.js"></script>
<script>
var decrypted = CryptoJS.AES.decrypt( "ZF9as5JII5TlqcB5tAd4sxPuBXd5TrgE", "1234567890123456");
console.log ( decrypted.toString( CryptoJS.enc.Utf8 ) );
</script>
但是它不会生成原始字符串(而是空字符串)。 我做错了什么?
它是否专注于 AES 是一个最好的主意 - 如果我有某种会模糊数据的加密,我会很高兴。
最佳答案
你的 Python 代码 和 CryptoJS 代码有很多问题:
您使用随机 IV 在 Python 中加密一些明文。如果您想检索该明文,则需要在解密过程中使用相同的 IV。没有 IV 就无法恢复明文。通常 IV 只是简单地放在密文前面,因为它不必是 secret 的。所以解密时需要读取IV,不能生成新的IV。
您在 CryptoJS(默认)中使用 CBC 模式而不是 CFB 模式。模式必须相同。另一个棘手的部分是 CFB 模式使用分段大小进行参数化。 PyCrypto 默认使用 8 位段 (CFB8),但 CryptoJS 仅针对 128 位 (CFB128) 的固定段实现。由于 PyCrypto 版本是可变的,因此您需要更改它。
CryptoJS
decrypt()
函数需要 OpenSSL 格式的字符串或 CipherParams 对象作为密文。由于您没有 OpenSSL 格式的字符串,因此您必须将密文转换为对象。CryptoJS 的
key
应该是 WordArray 而不是字符串。使用相同的填充。如果使用 CFB8,PyCrypto 不会填充明文,但使用 CFB128 时需要填充。 CryptoJS 默认使用 PKCS#7 填充,因此您只需要在 python 中实现该填充。
Python 代码(版本 2):
def pad(data):
length = 16 - (len(data) % 16)
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_CFB, IV, segment_size=128)
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_CFB, IV, segment_size=128)
return unpad(aes.decrypt(encrypted[BLOCK_SIZE:]))
JavaScript 代码:
<script src="https://cdn.rawgit.com/CryptoStore/crypto-js/3.1.2/build/rollups/aes.js"></script>
<script src="https://cdn.rawgit.com/CryptoStore/crypto-js/3.1.2/build/components/mode-cfb-min.js"></script>
<script>
var base64ciphertextFromPython = "...";
var ciphertext = CryptoJS.enc.Base64.parse(base64ciphertextFromPython);
// 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;
var key = CryptoJS.enc.Utf8.parse("1234567890123456");
// decryption
var decrypted = CryptoJS.AES.decrypt({ciphertext: ciphertext}, key, {
iv: iv,
mode: CryptoJS.mode.CFB
});
console.log ( decrypted.toString(CryptoJS.enc.Utf8));
</script>
其他注意事项:
您似乎想使用密码短语作为 key 。密码短语通常是人类可读的,但 key 不是。您可以使用 PBKDF2、bcrypt 或 scrypt 等函数从密码短语派生 key 。
上面的代码并不完全安全,因为它缺少身份验证。未经身份验证的密文可能会导致可行的攻击和不为人知的数据操纵。通常采用先加密后MAC的方案,具有良好的MAC功能,如HMAC-SHA256。
关于javascript - 在 python 中加密 - 在 Javascript 中解密,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30990129/