【问题标题】:What is libgcrypt doing different when calling the aes128 cipher with a 256bit key?使用 256 位密钥调用 aes128 密码时,libgcrypt 有何不同?
【发布时间】:2013-07-17 22:56:05
【问题描述】:

这是我上一个问题的延续 (RSA Decryption).

编辑:下面的答案清晰简洁。我在下面添加了一些示例代码,这些代码帮助我验证了我认为正在发生的事情。我今天会测试并回帖。客户端应用程序正在创建一个 256 位密钥,但是当它调用 gcry_cipher_setkey 时,它使用从算法返回的密钥长度。所以我猜测 setkey 正在将 256 位密钥截断为 128 位。很容易测试。

我正在尝试解密使用带有 aes128 / cbc / 无填充的 libgcrypt 加密的文件。有两个不同的应用程序正在执行加密,我无法控制这两个应用程序。一种是使用 128 位 AES 密钥,另一种是使用 256 位密钥。其他所有内部调用都是一样的。

编辑:这是伪加密代码:编辑 2: 为未来用户固定顺序和添加 cmets:

#define AES_KEY_SIZE 32
char AESKey[AES_KEY_SIZE+1];
GenerateAESKey(AESKey);

Error = gcry_cipher_open(AesHandle, GCRY_CIPHER_AES128, GCRY_CIPHER_MODE_CBC, 0);
// this is always 128bits (16 bytes)
BlockLength = gcry_cipher_get_algo_blklen(GCRY_CIPHER_AES128);
// this should return 128bits (16 bytes)
KeyLength = gcry_cipher_get_algo_keylen(GCRY_CIPHER_AES128);
Error = gcry_cipher_setiv(AesHandle, NULL, 0);
// AESKey is a 32byte (256bit) char array & KeyLength is 128bits (16bytes)
// so gcry_cipher_setkey only uses the first 'KeLength' bytes of 'AESKey'
// which in this case is the first 16 bytes of 'AESKey'
Error = gcry_cipher_setkey(*AesHandle, AESKey, KeyLength);
Error = gcry_cipher_encrypt(AesHandle, Encrypted, BlockLength, ToEncrypt, BlockLenth);


void GenerateAESKey( char * AESKey ) {
    int i;

    srand(time(NULL));
    for ( i = 0; i < AES_KEY_SIZE; i++ ) {
        AESKey[i] = (rand() % 93)+33;
    }
    AESKey[AES_KEY_SIZE] = '\0';
}

所以在我的 C# 代码中,在我开始解密之前我会这样做:

var aesKey = DecryptAesKey(s);
if (aesKey.Length == 32)
{
   var tempKey = new byte[16];
   Buffer.BlockCopy(aesKey,0,tempKey,0,16);
   aesKey = tempKey;
}

我正在使用 C# 和 bouncycastle 来解密文件。我成功解密了使用 128 位密钥加密的文件。但是当密钥为 256 位时失败。失败表示输出乱码。

我已验证两个来源的 AES 密钥均已正确解密。

我的问题是当密钥是 256 位时,Libgrypt 有什么不同?或者这甚至是找出我的解密失败原因的正确途径吗? 感谢您提供任何信息或指导。

布赖恩

【问题讨论】:

    标签: c# aes bouncycastle libgcrypt


    【解决方案1】:

    我假设你有

    1. 2 个不同的密钥(128 位和 256 位)
    2. 2 种不同的密文来源(1:AES128 2:AES256 两者:CBC/No Padding
    3. 可以解密128个密文
    4. 以 256 失败(一切都是乱码,明文中没有任何内容被解密)。

    主要区别在于128256位密钥长度。它指定转换输入的转换轮次的重复次数。您可能永远不需要内部实现细节。 AES 使用更大的密钥进行更多轮次。 128 位密钥为 10 个,256 位密钥为 14 个。

    重要的是,对于 128 和 256 CBC AES,块大小始终为 128 位

    AES-128-CBCAES-256-CBC 都使用 128 位 IV

    所以我的疯狂猜测(没有看到您的 AES256 代码)是您的 AES256 代码中的 Block 或 IV 大小的某处可能存在错误。

    如果您只是使用此功能为 128AES 设置密钥,请检查此docs

     gcry_error_t gcry_cipher_setkey (gcry_cipher_hd_t h, const void *k, size_t l)
    

    密钥 k 的长度 l(以字节为单位)必须与 为此上下文设置的算法所需的长度或在 具有可变密钥大小的算法的允许范围。功能 检查这一点并在有问题时返回错误。来电者 应始终检查错误。

    而且您通常不希望将 CBC 与 NoPadding 一起使用(除非您的数据大小始终是 16 字节的倍数),但填充问题只会导致最后 16 字节的纯文本块出现乱码。

    【讨论】:

    • 感谢@varren 的回复! gcry_error_t gcry_cipher_setkey (gcry_cipher_hd_t h, const void *k, size_t l) 被调用,其中 l = 16 并且 k 是一个 32 字节的数组。所以 setkey 只会使用 'k' 的前 'l' 字节。在我的 C# 代码中验证,仅使用 32 字节密钥的前 16 字节解密并取得了巨大成功。再次感谢您!
    猜你喜欢
    • 2014-11-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-09-16
    • 1970-01-01
    • 2015-04-28
    • 1970-01-01
    相关资源
    最近更新 更多