python中的加密-Javascript中的解密

python中的加密-Javascript中的解密,javascript,python,encryption,pycrypto,cryptojs,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(messag

我需要简单地用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中:


var decrypted=CryptoJS.AES.decrypt(“ZF9as5JII5TlqcB5tAd4sxPuBXd5TrgE”,“1234567890123456”);
console.log(decrypted.toString(CryptoJS.enc.Utf8));
但是,它不会生成原始字符串(而是空字符串)。 我做错了什么


专注于AES是一个最好的主意吗?如果我有某种加密技术可以模糊数据,我会很高兴的

Python代码和CryptoJS代码存在许多问题:

  • 在Python中使用随机IV加密一些明文。如果要检索该明文,则需要在解密过程中使用相同的IV。没有IV就无法恢复明文。通常IV只是在密文前面加上前缀,因为它不必是秘密的。因此,您需要在解密过程中读取IV,而不是生成新的IV

  • 在CryptoJS(默认)中使用CBC模式,而不是CFB模式。模式必须相同。另一个棘手的部分是CFB模式用段大小参数化。PyCrypto默认使用8位段(CFB8),但CryptoJS仅针对128位的固定段(CFB128)实现。因为PyCrypto版本是可变的,所以需要更改它

  • CryptoJS
    decrypt()
    函数需要OpenSSL格式的字符串或CipherParams对象作为密文。由于没有OpenSSL格式的字符串,因此必须将密文转换为对象

  • CryptoJS的
    应该是一个字数组而不是字符串

  • 使用相同的填充。如果使用CFB8,PyCrypto不会填充明文,但如果使用CFB128,则需要填充。CryptoJS默认使用PKCS#7填充,因此您只需要在python中实现该填充

Python代码(适用于版本2):

JavaScript代码:


var base64ciphertextFromPython=“…”;
var ciphertext=CryptoJS.enc.Base64.parse(base64ciphertextFromPython);
//拆分iv和密文
var iv=密文.clone();
iv.sigBytes=16;
iv.夹具();
密文.字.拼接(0,4);//删除4个字=16字节
ciphertext.sigBytes-=16;
var key=CryptoJS.enc.Utf8.parse(“1234567890123456”);
//解密
var decrypted=CryptoJS.AES.decrypt({ciphertext:ciphertext},key{
四:四,,
模式:CryptoJS.mode.CFB
});
console.log(decrypted.toString(CryptoJS.enc.Utf8));

其他注意事项:

似乎您希望使用密码短语作为密钥。密码短语通常是人类可读的,但密钥不是。您可以使用PBKDF2、bcrypt或scrypt等函数从密码短语派生密钥

上面的代码不是完全安全的,因为它缺少身份验证。未经验证的密文可能导致可行的攻击和未被注意到的数据操纵。通常情况下,加密后的MAC方案与良好的MAC功能(如HMAC-SHA256)一起使用。

(1年后,但我希望这对某些人有效)

首先,谢谢Artjom B。你的帖子对我帮助很大。和OP一样,Python服务器终结和Javascript客户端解码也有同样的问题。这就是我的解决方案:


Python 3.x(服务器)

我使用了excplicitPKCS7编码作为填充,为什么?因为我想确定我使用的是相同的填充编码和解码,这就是我找到它的链接

然后,就像Artjom B.所说的,确定你的段大小、IV大小和AES模式(我的CBC)

代码如下:

def encrypt_val(clear_text):
    master_key = '1234567890123456' 
    encoder = PKCS7Encoder()
    raw = encoder.encode(clear_text)
    iv = Random.new().read( 16 )
    cipher = AES.new( master_key, AES.MODE_CBC, iv, segment_size=128 )
    return base64.b64encode( iv + cipher.encrypt( raw ) ) 
请注意,您正在base64上遇到IV和加密数据的串联


Javascript(客户端)


我的一个主要问题是要记住所有类型的编码和解码数据,例如,我不知道客户端上的主密钥要用Utf8解析。

//第一次pip安装pycryptodome--(pycrypto已过时,并出现问题) //pip安装pkcs7

from Crypto import Random
from Crypto.Cipher import AES
import base64
from pkcs7 import PKCS7Encoder
from app_settings.views import retrieve_settings # my custom settings

app_secrets = retrieve_settings(file_name='secrets');


def encrypt_data(text_data):
                    #limit to 16 bytes because my encryption key was too long
                    #yours could just be 'abcdefghwhatever' 
    encryption_key = app_secrets['ENCRYPTION_KEY'][:16]; 

    #convert to bytes. same as bytes(encryption_key, 'utf-8')
    encryption_key = str.encode(encryption_key); 
    
    #pad
    encoder = PKCS7Encoder();
    raw = encoder.encode(text_data) # Padding
    iv = Random.new().read(AES.block_size ) #AES.block_size defaults to 16

                                 # no need to set segment_size=BLAH
    cipher = AES.new( encryption_key, AES.MODE_CBC, iv ) 
    encrypted_text = base64.b64encode( iv + cipher.encrypt( str.encode(raw) ) ) 
    return encrypted_text;

我注意到生成的字符串与您试图在JS中解密的字符串不匹配。那是打字错误吗?我想知道CryptoJS.AES.decrypt是否可能引发异常-您的控制台干净吗?您是Base64编码。这看起来像是您需要的:。实际上,这并没有说明如何使用密钥解密,但您很可能仍然需要首先解码Base64字符串。函数
encrypt
返回Base64编码的数据。see to in js.string not matched was type in question code only-fixed when encrypt you Base64 encode
Base64.b64encode(aes.encrypt(message))
。在CryptoJS中解密时,解密方法不采用Base64编码值。您需要首先解码该值。感谢您的响应,但它不起作用-您提到缺少iv-我看不到代码中的用法-需要在哪里使用?我再次扩展了示例-谢谢-但是在执行CryptoJS.AES.decrypt时,我仍然有“未捕获的TypeError:无法读取未定义的属性“0”({ciphertext:ciphertext},密钥);行,我不确定问题在哪里……现在应该可以解决了。事实证明,还有更多不同的东西。你有没有可能为JS添加加密函数?这个答案对我非常有用。对于python,主密钥应该是二进制的。
master\u key=b'123456789012345656'
我认为也应该这样做
cipher.encryPython3.x的pt(原始编码(“utf-8”)
function decryptMsg (data) {
    master_key = '1234567890123456';

    // Decode the base64 data so we can separate iv and crypt text.
    var rawData = atob(data);
    // Split by 16 because my IV size
    var iv = rawData.substring(0, 16);
    var crypttext = rawData.substring(16);

    //Parsers
    crypttext = CryptoJS.enc.Latin1.parse(crypttext);
    iv = CryptoJS.enc.Latin1.parse(iv); 
    key = CryptoJS.enc.Utf8.parse(master_key);

    // Decrypt
    var plaintextArray = CryptoJS.AES.decrypt(
      { ciphertext:  crypttext},
      key,
      {iv: iv, mode: CryptoJS.mode.CBC, padding: CryptoJS.pad.Pkcs7}
    );

    // Can be Utf8 too
    output_plaintext = CryptoJS.enc.Latin1.stringify(plaintextArray);
    console.log("plain text : " + output_plaintext);
}
from Crypto import Random
from Crypto.Cipher import AES
import base64
from pkcs7 import PKCS7Encoder
from app_settings.views import retrieve_settings # my custom settings

app_secrets = retrieve_settings(file_name='secrets');


def encrypt_data(text_data):
                    #limit to 16 bytes because my encryption key was too long
                    #yours could just be 'abcdefghwhatever' 
    encryption_key = app_secrets['ENCRYPTION_KEY'][:16]; 

    #convert to bytes. same as bytes(encryption_key, 'utf-8')
    encryption_key = str.encode(encryption_key); 
    
    #pad
    encoder = PKCS7Encoder();
    raw = encoder.encode(text_data) # Padding
    iv = Random.new().read(AES.block_size ) #AES.block_size defaults to 16

                                 # no need to set segment_size=BLAH
    cipher = AES.new( encryption_key, AES.MODE_CBC, iv ) 
    encrypted_text = base64.b64encode( iv + cipher.encrypt( str.encode(raw) ) ) 
    return encrypted_text;