You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用libtomcrypt实现ECC解密时内容截断问题求助

问题:libtomcrypt ECC解密仅返回前8字节内容

我基于libtomcrypt编写了ECC加密解密的C代码,编译命令为gcc -Wall -O0 -g test2.c -ltomcrypt -o test2。代码完成参数初始化、密钥生成、加密和解密操作,预期解密后输出完整原文Hello, this is a secret message!,但实际仅显示Hello, t。排查发现调用ecc_decrypt_key后decrypted_len被固定设为8,无法完整还原内容。

原代码如下:

#define LTM_DESC 
#include <tomcrypt.h>
int main(void)
{
    ecc_key mykey;
    prng_state prng;
    int err, prng_idx , hash_idx;

    ltc_mp = ltm_desc;

    /* register yarrow */
    if (register_prng(&yarrow_desc) == -1) {
    printf("Error registering Yarrow\n");
    return -1;
    }
    
    if (register_hash(&sha1_desc) == -1) {
        printf("Error registering sha1");
        return EXIT_FAILURE;
    }

    prng_idx = find_prng("yarrow");
    hash_idx = find_hash("sha1");
    /* setup the PRNG */
    if ((err = rng_make_prng(128, find_prng("yarrow"), &prng, NULL))
    != CRYPT_OK) {
    printf("Error setting up PRNG, %s\n", error_to_string(err));
    return -1;
    }
    /* make a 192-bit ECC key */
    if ((err = ecc_make_key(&prng, find_prng("yarrow"), 55, &mykey))
        != CRYPT_OK) {
        printf("Error making key: %s\n", error_to_string(err));
    return -1;
    }

        const unsigned char *plaintext = (const unsigned char *)"Hello, this is a secret message!";
        unsigned long ptlen = sizeof(plaintext);
        unsigned char ciphertext[1024];
        unsigned long ctlen = sizeof(ciphertext);

    if ((err = ecc_encrypt_key(plaintext,                       // const unsinged char *in
                                    ptlen,                             //unsinged long inlen
                                    ciphertext,                       // unsinged *out
                                    &ctlen,                           // unsinged long *outlen
                                    &prng,                               // prng_state *prng
                                    prng_idx,                         // int wprng
                                    hash_idx,                         // int hash
                                    &mykey)) != CRYPT_OK) {           // ecc_key *ley
            printf("Erro ao criptografar o texto: %s\n", error_to_string(err));
            return -1;
}

printf("Text after encrypted: ");
    for (unsigned long i = 0; i < ctlen; ++i) {
        printf("%02x", ciphertext[i]);
    }
    printf("\n");

    unsigned char decryptedtext[2048];
    unsigned long decrypted_len = sizeof(decryptedtext);
    if ((err = ecc_decrypt_key(ciphertext, ctlen, decryptedtext, &decrypted_len, &mykey)) != CRYPT_OK) {
        printf("Erro ao descriptografar o texto: %s\n", error_to_string(err));
        return -1;
    }

    decryptedtext[decrypted_len] = '\0';

    printf("%d",decryptedtext == plaintext);
    printf("\n");
    printf("Text after decrypted: %.*s\n", (int)decrypted_len, decryptedtext);
    printf("Text after decrypted: %s\n", plaintext);

    printf("Text after decryptedo: ");
    for (unsigned long i = 0; i < decrypted_len; ++i) {
        printf("%c", decryptedtext[i]);
    }
    printf("\n");

    // Update decrypted_len based on the actual length of the decrypted text
decrypted_len = strlen((char *)decryptedtext);

// Print the decrypted text
printf("Text after decrypted: %s\n", decryptedtext);

printf("Text after decrypted (Hex): ");
for (unsigned long i = 0; i < decrypted_len; ++i) {
    printf("%02x", decryptedtext[i]);
}
printf("\n");


return 0;
}

错误原因分析

  1. 明文长度计算错误:代码中用sizeof(plaintext)计算明文长度,但plaintext是指针类型,在64位系统中sizeof(plaintext)的值为8(指针字节数),导致加密时仅处理前8字节数据,解密自然只能得到8字节内容。
  2. ECC曲线参数错误:创建192位ECC密钥时使用参数55,对应非标准曲线,可能引发兼容性问题;标准NIST P-192曲线的参数应为3。
  3. 语法拼写错误:代码中多处出现unsinged的拼写错误,虽不影响编译,但存在潜在风险。

修复后的代码

#define LTM_DESC 
#include <tomcrypt.h>
#include <string.h>  // 引入strlen所需头文件

int main(void)
{
    ecc_key mykey;
    prng_state prng;
    int err, prng_idx , hash_idx;

    ltc_mp = ltm_desc;

    /* register yarrow */
    if (register_prng(&yarrow_desc) == -1) {
        printf("Error registering Yarrow\n");
        return -1;
    }
    
    if (register_hash(&sha1_desc) == -1) {
        printf("Error registering sha1");
        return EXIT_FAILURE;
    }

    prng_idx = find_prng("yarrow");
    hash_idx = find_hash("sha1");
    /* setup the PRNG */
    if ((err = rng_make_prng(128, prng_idx, &prng, NULL)) != CRYPT_OK) {
        printf("Error setting up PRNG, %s\n", error_to_string(err));
        return -1;
    }
    /* 创建192位ECC密钥(使用标准NIST P-192曲线,参数为3) */
    if ((err = ecc_make_key(&prng, prng_idx, 3, &mykey)) != CRYPT_OK) {
        printf("Error making key: %s\n", error_to_string(err));
        return -1;
    }

    const unsigned char *plaintext = (const unsigned char *)"Hello, this is a secret message!";
    // 修正:用strlen获取字符串实际长度
    unsigned long ptlen = strlen((char *)plaintext);
    unsigned char ciphertext[1024];
    unsigned long ctlen = sizeof(ciphertext);

    if ((err = ecc_encrypt_key(plaintext,
                               ptlen,
                               ciphertext,
                               &ctlen,
                               &prng,
                               prng_idx,
                               hash_idx,
                               &mykey)) != CRYPT_OK) {
        printf("Erro ao criptografar o texto: %s\n", error_to_string(err));
        return -1;
    }

    printf("Text after encrypted: ");
    for (unsigned long i = 0; i < ctlen; ++i) {
        printf("%02x", ciphertext[i]);
    }
    printf("\n");

    unsigned char decryptedtext[2048];
    unsigned long decrypted_len = sizeof(decryptedtext);
    if ((err = ecc_decrypt_key(ciphertext, ctlen, decryptedtext, &decrypted_len, &mykey)) != CRYPT_OK) {
        printf("Erro ao descriptografar o texto: %s\n", error_to_string(err));
        return -1;
    }

    decryptedtext[decrypted_len] = '\0';

    printf("Text after decrypted: %s\n", decryptedtext);
    printf("Original text: %s\n", plaintext);

    printf("Text after decrypted (Hex): ");
    for (unsigned long i = 0; i < decrypted_len; ++i) {
        printf("%02x", decryptedtext[i]);
    }
    printf("\n");

    // 清理密钥,避免内存泄漏
    ecc_free(&mykey);
    return 0;
}

修复说明

  1. 修正明文长度计算:将sizeof(plaintext)替换为strlen((char *)plaintext),确保加密完整的字符串内容。
  2. 更换标准ECC曲线:将ecc_make_key的曲线参数从55改为3,使用标准NIST P-192曲线。
  3. 补充头文件:引入<string.h>以使用strlen函数。
  4. 修正拼写错误:将所有unsinged改为unsigned,保证语法正确性。
  5. 优化代码:移除冗余打印语句,添加密钥清理操作ecc_free(&mykey)。

内容的提问来源于stack exchange,提问作者Breno Marot

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.04 18:34:53