为什么我无法在其他人的AES解密器上解密我的AES加密消息? [英] How come I can't decrypted my AES encrypted message on someone elses AES decryptor?

查看:193
本文介绍了为什么我无法在其他人的AES解密器上解密我的AES加密消息?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

  from Crypto。密码导入AES 
import os

key ='mysecretpassword'
iv = os.urandom(16)
plaintext1 ='机密消息A'
encobj = AES.new(密钥,AES.MODE_CBC,iv)
ciphertext1 = encobj.encrypt(plaintext1)
加密文本= ciphertext1.encode( 'base64')
打印cryptoText
decobj = AES.new(密钥,AES.MODE_CBC,iv)
打印decobj.decrypt(ciphertext1)

我复制了 encryptedText key 从我的代码粘贴到下面的网站。



http://www.everpassword.com/aes-encryptor



http://www.nakov.com/blog/2011/12/26/online-aes-encryptor-我希望它能够解密我的密码,但事实并非如此。

因此,我一定使用pycrypto错误。我该如何解决?这两个站点之间可以互相加密和解密,但是我的站点不能。这两个网站确实都使用CBC模式。

如果您查看有问题的网站的页面源代码,就会看到它使用了 gibberish-aes JavaScript库。要了解如何使它工作,必须研究它的作用。



浏览其源代码,它似乎使用了随机盐进行加密。在字符串以 Salted __ 开头之前,它构成了密文的开始,然后再进行base64编码。

  randArr =函数(num){
var结果= [],i;
for(i = 0; i 结果= result.concat(Math.floor(Math.random()* 256)));
}
返回结果;
},

  enc = function(string,pass,binary){
//字符串,明文密码
var salt = randArr(8),
pbe = openSSLKey(s2a(pass,binary),salt),
key = pbe.key,
iv = pbe.iv,
cipherBlocks,
saltBlock = [[83,97, 108,116,101,100,95,95] .concat(salt)];
string = s2a(字符串,二进制);
cipherBlocks = rawEncrypt(string,key,iv);
//拼出 Salted__
cipherBlocks = saltBlock.concat(cipherBlocks);
返回Base64.encode(cipherBlocks);
},

对于解密,它使用随机抽取盐的一部分base64解码后密文的开头(第一个 slice 运算符):

  dec = function(string,pass,binary){
//字符串,明文密码
var cryptArr = Base64.decode(string),
salt = cryptArr.slice(8,16 ),
pbe = openSSLKey(s2a(pass,binary),salt),
键= pbe.key,
iv = pbe.iv;
cryptArr = cryptArr.slice(16,cryptArr.length);
//取下Salted__ffeeddcc
string = rawDecrypt(cryptArr,key,iv,binary);
返回字符串;
},

现在丢失的部分是 openSSLkey 函数:

  openSSLKey = function(passwordArr,saltArr){
//轮数取决于所使用的AES大小
//密钥为3轮256
//密钥为2轮,IV为
1轮// 128
2轮// 1轮为密钥,1轮为IV
// 3轮为192,因为它没有均匀地除以128位
var rounds = Nr> = 12吗? 3:2,
键= [],
iv = [],
md5_hash = [],
结果= [],
data00 = passwordArr.concat( saltArr),
i;
md5_hash [0] = GibberishAES.Hash.MD5(data00);
结果= md5_hash [0];
for(i = 1; i md5_hash [i] = GibberishAES.Hash.MD5(md5_hash [i-1] .concat(data00));
结果= result.concat(md5_hash [i]);
}
键= result.slice(0,4 * Nk);
iv = result.slice(4 * Nk,4 * Nk + 16);
return {
key:key,
iv:iv
};
},

因此,基本上,您必须翻译 openSSLKey 函数传递给Python,并向其提供您的密码和密码。这将创建一个(键,iv)元组。使用那些来加密您的数据。在使用base64对其进行编码之前,将字符串 Salted __ 和盐添加到密文中。我想那应该可以了。


from Crypto.Cipher import AES
import os

key = 'mysecretpassword'
iv = os.urandom(16)
plaintext1 = 'Secret Message A'
encobj = AES.new(key, AES.MODE_CBC, iv)
ciphertext1 = encobj.encrypt(plaintext1) 
encryptedText = ciphertext1.encode('base64')
print encryptedText
decobj = AES.new(key, AES.MODE_CBC, iv)
print decobj.decrypt(ciphertext1)

I copied the printed value of encryptedText and the key from my code and pasted to the websites below.

http://www.everpassword.com/aes-encryptor

http://www.nakov.com/blog/2011/12/26/online-aes-encryptor-decryptor-javascript/

I would expected it to be able to decrypt my cipher, but it doesn't. Thus I must be using pycrypto wrong. How do I fix this? The two sites can both encrypt and decrypt between each other, but mines can't. Both the websites do indeed use CBC mode.

解决方案

If you look at the page source for the website in question, you will see that it uses gibberish-aes javascript library. To see whet you have to do to make it work, you have to study what it does.

Looking through its source code, it seems to use a random salt for encryption. That, prepended by the string Salted__ forms the beginning of the cyphertext before it is base64 encoded.

randArr = function(num) {
    var result = [], i;
    for (i = 0; i < num; i++) {
        result = result.concat(Math.floor(Math.random() * 256));
    }
    return result;
},

and

enc = function(string, pass, binary) {
        // string, password in plaintext
        var salt = randArr(8),
        pbe = openSSLKey(s2a(pass, binary), salt),
        key = pbe.key,
        iv = pbe.iv,
        cipherBlocks,
        saltBlock = [[83, 97, 108, 116, 101, 100, 95, 95].concat(salt)];
        string = s2a(string, binary);
        cipherBlocks = rawEncrypt(string, key, iv);
        // Spells out 'Salted__'
        cipherBlocks = saltBlock.concat(cipherBlocks);
        return Base64.encode(cipherBlocks);
    },

For decryption, it uses picks the random portion of the salt out of the beginning of the cyphertext after base64 decoding (the first slice operator):

dec = function(string, pass, binary) {
    // string, password in plaintext
    var cryptArr = Base64.decode(string),
    salt = cryptArr.slice(8, 16),
    pbe = openSSLKey(s2a(pass, binary), salt),
    key = pbe.key,
    iv = pbe.iv;
    cryptArr = cryptArr.slice(16, cryptArr.length);
    // Take off the Salted__ffeeddcc
    string = rawDecrypt(cryptArr, key, iv, binary);
    return string;
},

The missing piece now is the openSSLkey function:

openSSLKey = function(passwordArr, saltArr) {
    // Number of rounds depends on the size of the AES in use
    // 3 rounds for 256
    // 2 rounds for the key, 1 for the IV
    // 2 rounds for 128
    // 1 round for the key, 1 round for the IV
    // 3 rounds for 192 since it's not evenly divided by 128 bits
    var rounds = Nr >= 12 ? 3: 2,
    key = [],
    iv = [],
    md5_hash = [],
    result = [],
    data00 = passwordArr.concat(saltArr),
    i;
    md5_hash[0] = GibberishAES.Hash.MD5(data00);
    result = md5_hash[0];
    for (i = 1; i < rounds; i++) {
        md5_hash[i] = GibberishAES.Hash.MD5(md5_hash[i - 1].concat(data00));
        result = result.concat(md5_hash[i]);
    }
    key = result.slice(0, 4 * Nk);
    iv = result.slice(4 * Nk, 4 * Nk + 16);
    return {
        key: key,
        iv: iv
    };
},

So basically you have to translate the openSSLKey function to Python and feed it your password and salt. That creates a (key, iv) tuple. Use those to encrypt your data. Prepend the string Salted__ and the salt to the ciphertext before encoding it with base64. Then it should work, I think.

这篇关于为什么我无法在其他人的AES解密器上解密我的AES加密消息?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆