CryptoJS和Pycrypto一起工作

ian*_*ian 0 javascript python encryption pycrypto cryptojs

我正在使用CryptoJS(v 2.3)对Web应用程序中的字符串进行加密,并且需要在Python中的服务器上对其进行解密,因此我正在使用PyCrypto。我觉得我缺少了一些东西,因为我无法正常工作。

这是JS:

Crypto.AES.encrypt('1234567890123456', '1234567890123456',
                   {mode: new Crypto.mode.CBC(Crypto.pad.ZeroPadding)})
// output: "wRbCMWcWbDTmgXKCjQ3Pd//aRasZ4mQr57DgTfIvRYE="
Run Code Online (Sandbox Code Playgroud)

python:

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'
Run Code Online (Sandbox Code Playgroud)

Art*_* B. 5

这是CryptoJS 3.1.2的版本。始终注意以下事项(两种语言使用相同的内容):

  • 操作模式(在这种情况下为CBC)
  • 填充(在这种情况下为零填充;最好使用PKCS#7填充)
  • 键(相同的派生功能或清除键)
  • 编码(密钥,明文,密文等的相同编码)
  • IV(加密期间生成,传递给解密)

如果将字符串作为key参数传递给CryptoJS encrypt()函数,则该字符串将用于派生用于加密的实际密钥。如果您希望使用密钥(有效大小为16、24和32字节),则需要将其作为WordArray传递。

CryptoJS加密的结果是一个OpenSSL格式的密文字符串。要从中获取实际的密文,您需要访问其ciphertext上的属性。

IV对于每个加密必须是随机的,以便在语义上是安全的。这样,攻击者仅查看密文就无法说出经过多次加密的同一个明文是否实际上是同一个明文。

以下是我制作的示例。

JavaScript:

var key = CryptoJS.enc.Utf8.parse('1234567890123456'); // TODO change to something with more entropy

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);
}
Run Code Online (Sandbox Code Playgroud)

Python代码:

BLOCK_SIZE = 16
key = b"1234567890123456" # TODO change to something with more entropy

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, key):
    IV = Random.new().read(BLOCK_SIZE)
    aes = AES.new(key, AES.MODE_CBC, IV)
    return base64.b64encode(IV + aes.encrypt(pad(message)))

def decrypt(encrypted, key):
    encrypted = base64.b64decode(encrypted)
    IV = encrypted[:BLOCK_SIZE]
    aes = AES.new(key, AES.MODE_CBC, IV)
    return unpad(aes.decrypt(encrypted[BLOCK_SIZE:]))
Run Code Online (Sandbox Code Playgroud)

其他注意事项:

似乎您想使用密码短语作为密钥。密码短语通常是人类可读的,但密钥却不可读。您可以使用诸如PBKDF2,bcrypt或scrypt之类的功能从密码短语中获取密钥。

上面的代码不是完全安全的,因为它缺少身份验证。未经身份验证的密文可能导致可行的攻击和未经注意的数据处理。通常,先加密再加密(MAC)方案采用良好的MAC功能,例如HMAC-SHA256。