javascript - 在 python 中加密 - 在 Javascript 中解密

标签 javascript python encryption pycrypto cryptojs

我需要在 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/

相关文章:

Python 提取 URL (`where from` ) 下载图片的信息

php - 解析一个文件并使用该数据解密另一个文件的数据

javascript - 在 javascript 正则表达式中捕获多个变量的更简单方法

javascript - 水平下拉菜单 Umbraco

javascript - 你如何制作一个滚动页面?

python - 如何在 Python 中捕获对列表项的直接引用以提高速度?

python - 一个环境变量可供 python 子进程使用,而另一个则不可用

javascript - Object.keys() 和 Object.values() 方法是否返回保留相同顺序的数组

javascript - 加密数据 SVG URL

java.security.cert.CertificateParsingException : signed fields invalid