使用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; }
错误原因分析
- 明文长度计算错误:代码中用
sizeof(plaintext)计算明文长度,但plaintext是指针类型,在64位系统中sizeof(plaintext)的值为8(指针字节数),导致加密时仅处理前8字节数据,解密自然只能得到8字节内容。 - ECC曲线参数错误:创建192位ECC密钥时使用参数
55,对应非标准曲线,可能引发兼容性问题;标准NIST P-192曲线的参数应为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; }
修复说明
- 修正明文长度计算:将
sizeof(plaintext)替换为strlen((char *)plaintext),确保加密完整的字符串内容。 - 更换标准ECC曲线:将
ecc_make_key的曲线参数从55改为3,使用标准NIST P-192曲线。 - 补充头文件:引入
<string.h>以使用strlen函数。 - 修正拼写错误:将所有
unsinged改为unsigned,保证语法正确性。 - 优化代码:移除冗余打印语句,添加密钥清理操作
ecc_free(&mykey)。
内容的提问来源于stack exchange,提问作者Breno Marot
相关产品推荐
相关产品推荐

