【问题标题】:How come I can't decrypted my AES encrypted message on someone elses AES decryptor?为什么我无法在别人的 AES 解密器上解密我的 AES 加密消息?
【发布时间】:2012-08-31 19:32:39
【问题描述】:
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)

我从我的代码中复制了encryptedTextkey 的打印值并粘贴到以下网站。

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

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

我希望它能够解密我的密码,但事实并非如此。因此我必须使用 pycrypto 错误。我该如何解决?这两个站点都可以相互加密和解密,但我的站点不能。这两个网站都确实使用了 CBC 模式。

【问题讨论】:

  • 你尝试过不同的模式吗?我看不出该网站是使用 XTS、CBC 还是仅使用 ECB。尝试不同的模式。请注意,您使用静脉注射,但该网站不要求静脉注射。
  • 你需要给解密器IV。该网站不接受静脉注射。所以它可能使用的是 ECB,而不是 CBC。
  • 还有,你怎么知道网站把密文作为base64?
  • 是的,我错误地假设该网站将密文作为base64。
  • 其实我的假设是正确的,网站确实将密文作为base64。它甚至在第二个网络链接中明确说明。它不可能在 ascii 或其他东西中。所以我仍然对我在代码中做错了什么感到困惑。我如何让它被网站解密。

标签: python aes pycrypto


【解决方案1】:

如果您查看相关网站的页面源代码,您会发现它使用了gibberish-aes javascript 库。要了解您必须做些什么才能使其发挥作用,您必须研究它的作用。

查看其source code,它似乎使用随机盐进行加密。前面加上字符串 Salted__ 构成密文的开头,然后再进行 base64 编码。

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

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);
    },

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

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;
},

现在缺少的是openSSLkey 函数:

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
    };
},

所以基本上你必须将 openSSLKey 函数翻译成 Python 并输入你的密码和盐。这将创建一个 (key, iv) 元组。使用它们来加密您的数据。在使用 base64 对其进行编码之前,将字符串 Salted__ 和盐添加到密文中。那么它应该可以工作,我想。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-12-04
    • 1970-01-01
    • 2016-09-22
    • 2012-02-24
    • 1970-01-01
    • 1970-01-01
    • 2012-04-08
    相关资源
    最近更新 更多