我一直在努力解决RSA_verify的一个奇怪问题。我正在尝试使用C ++使用C和RSA_verify进行RSA_sign。我使用OpenSSL命令生成了私钥和证书。
message = "1.2.0:08:00:27:2c:88:77"
当我使用上面的消息时,生成一个哈希并使用RSA_sign对摘要进行签名,我得到一个长度为256(strlen(signature)
)的签名,并且从RSA_sign返回的长度也是256.我用这个长度来验证和验证成功。
但是当我使用message = "1.2.0:08:00:27:2c:88:08"
时,签名长度为60,RSA_sign返回256.当我使用此长度60来验证它失败时。它也无法验证长度为256。对于某些消息(1.2.0:08:00:27:2c:88:12),生成的签名为零。
我使用SHA256来散列消息,使用NID_SHA256来RSA_sign和RSA_verify这个摘要。我在使用OpenSSL命令生成密钥时使用了-sha256。
我通过解析使用某些字符串操作读取某些标记的XML文件来形成消息。
请建议。
以下是用于签名的代码。
int main(void)
{
int ret;
RSA *prikey;
char *data ;
unsigned char* signature;
int slen = 0;
FILE * fp_priv = NULL;
char* privfilepath = "priv.pem";
unsigned char* sign = NULL;
ERR_load_crypto_strings();
data = generate_hash();
printf("Message after generate hash %s: %d\n", data, strlen(data));
fp_priv = fopen(privfilepath, "r");
if (fp_priv == NULL)
{
printf("Private key path not found..");
return 1;
}
prikey = RSA_new();
prikey = PEM_read_RSAPrivateKey(fp_priv, &prikey, NULL, NULL);
if (prikey == NULL)
{
printf("Private key returned is NULL\n");
return 1;
}
signature = (unsigned char*)malloc(RSA_size(prikey));
if( signature == NULL )
return 1;
if(RSA_sign(NID_sha256, (unsigned char*)data, strlen(data),
signature, &slen, prikey) != 1) {
ERR_print_errors_fp(stdout);
return 1;
}
printf("Signature length while signing... %d : %d : %d ",
strlen(signature), slen, strlen(data));
FILE * sig_bin = fopen("sig_bin", "w");
fprintf(sig_bin, "%s", signature);
fclose(sig_bin);
system("xxd -p -c256 sig_bin sig_hex");
RSA_free(prikey);
if(signature)
free(signature);
return 0;
}
答案 0 :(得分:2)
了解C的一个非常非常重要的事情是它有两个不同类型的同名。
char*
:这表示字符串的开头。你可以做strstr或strlen之类的事情。
char*
:这表示数据blob的开头(也就是字节数组,也就是八位字符串),你不能有意义地将strlen / etc应用于它。RSA_sign使用后者。它返回“数据”,而不是“消息”。所以,在你的代码片段中
printf("Signature length while signing... %d : %d : %d ",
strlen(signature), slen, strlen(data));
FILE * sig_bin = fopen("sig_bin", "w");
fprintf(sig_bin, "%s", signature);
fclose(sig_bin);
data
来自名为generate_hash()
的函数;它可能是非文本的,所以strlen不适用。 signature
肯定是数据,因此strlen不适用。由于同样的原因,fprintf也不适用。这些函数通过第一次出现零字节(0x00,'\ 0'等)来识别字符串的结尾。但是0x00在签名,哈希或大量“数据”中是完全合法的。
RSA_sign输出的长度写入传递给第5个参数的地址。你传递了&slen
(地址为slen),所以一旦函数退出(成功)slen
就是签名的长度。请注意,它很少匹配strlen(签名)。
要将您的签名编写为二进制文件,您应该使用fwrite,例如fwrite(sig_bin, sizeof(char), signature, slen);
。如果您希望将其作为文字,则应Base-64对数据进行编码。