使用不正确密钥大小的AES加密示例

时间:2015-03-04 01:28:11

标签: encryption cryptography aes

使用AES加密时,您需要使用128,192或256位的密钥大小。但是在各种加密网站上,您可以使用任何长度为1个字符(8位)的密钥。

http://aesencryption.net/

例如,在该网站上,我可以使用我想要的任何密钥,它可以加密/解密。

这是如何工作的?如何使用甚至没有正确长度的键呢?

3 个答案:

答案 0 :(得分:3)

许多加密工具(和库)允许您提供“密码”,用于导出适当大小的密钥。为了防止歧义,术语加密密钥通常用于表示与加密算法一起使用的N位密钥。

如果你查看你链接的页面上的代码,它会计算你给它的密钥的SHA-1哈希值,并将前16个字节作为128位加密密钥。

答案 1 :(得分:1)

PHP,OpenSSL(及其他)

许多网站专门使用PHP mcrypt_encrypt。 PHP mcrypt用于接受任何大小的密钥和IV。发生的事情是,算法不支持的密钥被扩展到大于给定密钥字节的第一个可用大小。如果密钥太大,则会将密钥减小到最大密钥大小。

对于PHP,这在5.6.0中已更改:

  

不再接受无效的密钥和iv尺寸。 mcrypt_encrypt()现在将抛出警告,如果输入无效,则返回FALSE。之前的键和IV都填充了' \ 0'字节到下一个有效大小。

这可能会打破很多网站。

请注意,这种密钥扩展绝对不是最佳做法,并且不仅仅是密码专家不赞成。而应使用密钥派生函数或KDF。

使用哈希函数哈希

使用密码哈希(如MD5或SHA-1)进行哈希可以用作穷人KDF。它没有提供PBKDF提供的保护(见下文)。如果需要较短大小的密钥,则采用(最左边)字节是相对安全的。如果使用散列,则应该从API或源代码中清楚。

这似乎是问题中示例中使用的方法。

播种随机数生成器

除非从API中非常清楚地使用了什么算法,并且DRBG给定的种子不与先前的种子数据混合(例如,通过操作系统),否则不应使用该方法。通常使用密钥/密码作为随机数生成器的种子将导致灾难性故障。应采用一切可能的方法进行这种方法。随机数生成器不是KDF。不幸的是there are many people following bad examples

密码加密

相反,对于基于密码的加密(PBE),应使用 PBKDF (基于密码的密钥派生函数)。 PBKDF的实例是PBKDF2,bcrypt或scrypt。这通常在API中是明确的,或在源代码中清晰可见。一个好的PBKDF使用盐,可能是胡椒(秘密值)和工作因子或迭代计数。这使得密码 - 通常包含比完整密钥更少的熵 - 更安全一些。尽管如此,它还是不能防止真正的弱键。

密钥派生

如果你的秘密确实包含足够的熵,那么就不需要盐和工作因子(盐可以使你的KDF更加安全)。工作因素只会为您的密钥派生增加一个恒定的时间 - 如果由于熵的数量而导致暴力攻击已经不可行,则工作因素只会减慢目标用户和CPU的速度。可以说最先进的KBKDF目前是HKDF。找到加密库中实现的KDF可能很棘手。

答案 2 :(得分:1)

http://aesencryption.net/算法以字符串形式获取密钥,并将其重新映射到具有Rijndael接受的长度的数组。如果长度超过256位,则将密钥截断为该长度,否则用'\0'个字节填充,直到达到算法的可接受长度之一,即128,160,192,224或256位。

我通过获取密钥,将其转换为数组并最终截断/填充它来重现此站点的行为。

您可以使用以下算法重现网站http://aesencryption.net

的密钥转换
public static byte[] transformKey(String inputKey){ 
    int keySize = Math.min(((((sessionKey.length * 8 - 128) / 32) + 1) * 32) + 128, 256) / 8;
    sessionKey = Arrays.copyOf(sessionKey, keySize);

    for (int i = key.getBytes().length; i < sessionKey.length; i++) {
        sessionKey[i] = '\0';
    }
    return sessionKey;
}

注意for周期没用,因为Arrays.copyOf已经用零填充数组。