【问题标题】:How to find the correct OpenSSL EVP key length for DES3 encryption如何为 DES3 加密找到正确的 OpenSSL EVP 密钥长度
【发布时间】:2012-06-19 13:51:01
【问题描述】:

我正在尝试实现hybrid cryptosystemRSA 用于密钥信封,DES3(带有双密钥选项)用于数据信封)。因此,我首先尝试使用 Openssl 的 EVP 函数来实现 DES3。因为看起来我可以很容易地使用 EVP 来结合 RSA 和 DES3 加密。

我从 Openssl 书中得到了这个示例代码(更改了数据类型以修复 gcc 警告并将 sn-ps 放在一个文件中):

#include <stdio.h>
#include <openssl/ssl.h>
#include <openssl/evp.h>
#include <openssl/rand.h>

unsigned char *encrypt_example(EVP_CIPHER_CTX *ctx, unsigned char *data, int inl, int *rb);
unsigned char *decrypt_example(EVP_CIPHER_CTX *ctx, unsigned char *ct, int inl);
void select_random_key(unsigned char *key, int b);
void select_random_iv(unsigned char *iv, int b);
int seed_prng(int bytes);


int main(int argc, char *argv[])
{
    EVP_CIPHER_CTX ctx;
    EVP_CIPHER_CTX_init(&ctx);

    unsigned char key[EVP_MAX_KEY_LENGTH];
    unsigned char iv[EVP_MAX_IV_LENGTH];
    unsigned char *ct, *out;
    unsigned char final[EVP_MAX_BLOCK_LENGTH];
    unsigned char str[] = "123456789abcdef";
    int i = 0;

    if (!seed_prng(16))
    {
        printf("Fatal Error! Unable to seed the PRNG!\n");
        abort();
    }

    select_random_key(key, EVP_MAX_KEY_LENGTH);
    select_random_iv(iv, EVP_MAX_IV_LENGTH);


    /* EVP_des_ede3()       :three-key DES3 with ECB
     * EVP_des_ede()        :two-key DES3 with ECB
     * EVP_des_ede_cbc()    :two-key DES3 with CBC 
     * EVP_des_ede3_cbc()   :three-key DES3 with CBC */

    EVP_EncryptInit(&ctx, EVP_des_ede_cbc(), key, NULL);
    ct = encrypt_example(&ctx, str, strlen((const char*)str), &i);
    printf("Ciphertext is %d bytes.\n", i);

    EVP_DecryptInit(&ctx, EVP_des_ede_cbc(), key, NULL);
    out = decrypt_example(&ctx, ct, 8);
    printf("Decrypted: >>%s<<\n", out);
    out = decrypt_example(&ctx, ct + 8, 8);
    printf("Decrypted: >>%s<<\n", out);

    if (!EVP_DecryptFinal(&ctx, final, &i))
    {
        printf("Padding incorrect.\n");
        abort();
    }

    final[i] = 0;
    printf("Decrypted: >>%s<<\n", final);
    return 0;
}

int seed_prng(int bytes)
{
    if (!RAND_load_file("/dev/random", bytes))
        return 0;
    return 1;
}

void select_random_key(unsigned char *key, int b)
{
    int i;

    RAND_bytes(key, b);
    for (i = 0; i < b - 1; i++)
        printf("%02X:",key[i]);
    printf("%02X\n\n", key[b - 1]);
}

void select_random_iv (unsigned char *iv, int b)
{
    RAND_pseudo_bytes (iv, b);
}

unsigned char *encrypt_example(EVP_CIPHER_CTX *ctx, unsigned char *data, int inl, int *rb)
{
    unsigned char *ret = (unsigned char *)malloc(inl + EVP_CIPHER_CTX_block_size(ctx));
    int i, tmp, ol;

    ol = 0;
    for (i = 0; i < inl /100; i++)
    {
        EVP_EncryptUpdate(ctx, &ret[ol], &tmp, &data[ol], 100);
        ol += tmp;
    }

    if (inl % 100)
    {
        EVP_EncryptUpdate(ctx, &ret[ol], &tmp, &data[ol], inl%100);
        ol += tmp;
    }

    EVP_EncryptFinal(ctx, &ret[ol], &tmp);
    *rb = ol + tmp;
    return ret;
}

unsigned char *decrypt_example(EVP_CIPHER_CTX *ctx, unsigned char *ct, int inl)
{

    /* We're going to null-terminate the plaintext under the assumption it's
     * non-null terminated ASCII text. The null can be ignored otherwise.
     */
    unsigned char *pt = (unsigned char *)malloc(inl + EVP_CIPHER_CTX_block_size(ctx) + 1);
    int ol;

    EVP_DecryptUpdate(ctx, pt, &ol, ct, inl);
    if (!ol) /* there's no block to decrypt */
    {
        free(pt);
        return NULL;
    }

    pt[ol] = 0;
    return pt;
}

我正在用这个编译它

gcc -g -O0 -Wall evp_encrypt_decrypt.c  -o evp_encrypt_decrypt -lssl -lcrypto

现在如果我执行这个,我会得到这个输出:

13:98:EB:64:D5:8B:1E:0A:70:1D:28:9D:25:3A:13:40:FE:C1:81:3C:C5:8F:4B:F6:66:1A:07:F8:17:D6:10:B6:4E:BC:45:96:00:A1:9F:59:44:A0:43:D9:9D:DD:C8:A9:0B:22:EC:7B:F2:5F:78:01:D1:58:6D:0B:B4:CB:5F:CD 

Ciphertext is 16 bytes.
Decrypted: >>(null)<<
Decrypted: >>12345678<<
Decrypted: >>9abcdef<<

这里说芯片文本是 16 字节(没关系)。但是密钥本身(上面打印的十六进制代码)是 64 字节长!

但是,带有两个密钥选项的 DES3 的密钥长度应为 128 位(包括奇偶校验位)。但是,EVP_MAX_KEY_LENGTH 定义默认为 64。我还尝试打印芯片密钥长度、变量key 的大小和 ctx 密钥大小,如下所示:

printf("Key length DES3: %d\n", EVP_CIPHER_key_length(EVP_des_ede3_cbc()));
printf("Key size: %d\n", sizeof(key));
printf("Cipher CTX key length: %d\n\n", EVP_CIPHER_CTX_key_length(&ctx));

这将输出:

Key length DES3: 24
Key size: 64
Cipher CTX key length: 16

我在这里有点困惑。 DES3(双键)密钥大小不应该是 128 位吗?为什么 DES3 密钥的长度打印为 24(这是位、字节等)?为什么所有这些密钥长度和大小都不同?

【问题讨论】:

  • 我不明白你的困惑。您打印了EVP_CIPHER_key_length(EVP_des_ede3_cbc()),它是 3 密钥三重密码,所以它应该是 24。您的 key 数组有 64 个字节,因为那是 的大小.
  • @GregS 密钥是64字节的ok,但是为​​什么像DES3一样有192位的密钥长度时EVP_MAX_KEY_LENGTH的长度是64?
  • 这只是 openssl 支持的 any 密码的最大密钥长度。这是一个非常简单的便利常量,允许程序员为键静态分配内存。
  • @GregS 那么对于 DES3 我可以简单地使用 24 而不是 EVP_MAX_KEY_LENGTH?我的意思是我必须使用 EVP_MAX_KEY_LENGTH 吗? DES3 也需要三个密钥,每个 64 位(带奇偶校验),那么如果我用 24 字节为函数播种,它会将它分成三个部分吗?我真的对所有这些键大小以及 Openssl 如何处理它感到困惑。
  • 是的,您可以只使用 24 而不是 EVP_MAX_KEY_LENGTH。在引擎盖下 DES3 创建了 3 个密钥,每个密钥都有 64 位,但是如果您使用 EVP 接口,您不必担心这个细节。所有这些魔法都封装在 EVP_CIPHER_CTX 中。

标签: encryption openssl rsa des


【解决方案1】:

但是,带有两个密钥选项的 DES3 的密钥长度应为 128 位(包括奇偶校验位)

是的。 2-key 3DES 的密钥大小为 64x2 = 128 位; 3-key 3DES 的密钥大小为 64x3 = 192 位(如 Greg S 所述)。

然而,EVP_MAX_KEY_LENGTH 定义默认为 64

这是它可以达到的最大值(对于所有 EVP 对称密码),而不仅仅是 DES/3DES/AES 等。该值甚至可能在未来发生变化。

不应该是 DES3(双密钥)密钥大小 128 位吗?

是的。

为什么 DES3 密钥的长度打印为 24(这是位、字节等)?

谁知道......但它以字节为单位,而不是位。

为什么所有这些密钥长度和大小都不同?

大小取决于算法或密码系统。

2-key 3DES 执行加密-解密-加密并使用两个密钥。所以其中一个键被使用了两次。 3-key 3DES 执行加密-解密-加密并使用三个独立的密钥。他们就是这样设计的。

【讨论】:

  • EVP接口是否会为3des的key1使用key的1-64位,key2使用65-128,key3使用129-192?
猜你喜欢
  • 2021-06-06
  • 2018-09-14
  • 2011-05-06
  • 2021-03-17
  • 1970-01-01
  • 2021-05-11
  • 1970-01-01
  • 2018-06-18
  • 2012-04-28
相关资源
最近更新 更多