OpenSSL的签名区别使用C程序和OpenSSL DGST,rsautl命令行时 [英] Openssl signature difference when using C routines and openssl dgst, rsautl command line
问题描述
我使用下面的语句来创建RSA公钥和私钥。
的OpenSSL genrsa -out ksign_private.pem 1024
OpenSSL的RSA -in ksign_private.pem -pubout> ksign_public.pem
然后我有一个使用,PEM_read_RSAPrivateKey,EVP_PKEY_assign_RSA,EVP_SignInit,EVP_SignUpdate,EVP_SignFinal功能从OpenSSL的libcrypto生成签名文件的程序。
我也有例行程序,验证签名可以使用PEM_read_RSA_PUBKEY,EVP_PKEY_assign_RSA,EVP_VerifyInit,EVP_VerifyUpdate,EVP_VerifyFinal进行验证。
来源$ C $ C这些例程是附在下面。
在使用这些功能,我可以创造SHA1签名,用私钥加密,并使用公钥解密。
不过我试图用相同的数据文件,使用OpenSSL的rsautl那就是过得去的OpenSSL rsautl创建的签名相同的私有,公共密钥是完全不同的。
OpenSSL的DGST -sha1 -binary< myData的> testfile.sha1
OpenSSL的rsautl -sign -in testfile.sha1 -inkey ksign_private.pem -keyform PEM退房手续testfile.sig
任何一个可以告诉我,我在用的选项错误使用OpenSSL的rsautl或DGST命令时?
的#include<&stdio.h中GT;
#包括LT&;&unistd.h中GT;
#包括LT&;&stdlib.h中GT;
#包括LT&;&文件ctype.h GT;
#包括LT&;&unistd.h中GT;
#包括LT&;&string.h中GT;
#包括LT&;的OpenSSL / sha.h>
#包括LT&;&errno.h中GT;
#包括LT&;&getopt.h GT;
#包括LT&; SYS / types.h中>
#包括LT&; SYS / stat.h>
#包括LT&;的OpenSSL / evp.h>
#包括LT&;的OpenSSL / pem.h>
#包括LT&;的OpenSSL / rsa.h>INT ksignEvpSign(FILE * PRIVATE_KEY,FILE * inFileFP,FILE * outFileFP);
INT ksignEvpVerify(FILE * PUBLIC_KEY,FILE * dataFileFP,FILE * signFileFP);INT ksignEvpSign(FILE * privateKeyFP,FILE * inFileFP,FILE * outFileFP)
{
RSA * rsa_pkey = NULL;
EVP_PKEY * p键= EVP_PKEY_new();
EVP_MD_CTX CTX;
无符号字符缓冲区[4096];
为size_t LEN;
无符号字符* SIG;
无符号整型siglen; 如果(PEM_read_RSAPrivateKey(privateKeyFP,&放大器;!rsa_pkey,NULL,NULL)){
fprintf中(标准错误,错误加载RSA私钥文件\\ n);
返回2;
} 如果(!EVP_PKEY_assign_RSA(p键,rsa_pkey)){
fprintf中(标准错误,EVP_PKEY_assign_RSA:失败\\ n);
返回3;
} EVP_MD_CTX_init(安培; CTX); 如果(!EVP_SignInit(安培;环磷酰胺,EVP_sha1())){
fprintf中(标准错误,EVP_SignInit:失败\\ n);
EVP_PKEY_free(p键);
返回3;
} 而((LEN =的fread(缓冲液,1,sizeof的缓冲器,inFileFP))大于0){
如果(EVP_SignUpdate(安培;!CTX,缓冲,LEN)){
fprintf中(标准错误,EVP_SignUpdate:失败\\ n);
EVP_PKEY_free(p键);
返回3;
}
} 如果(FERROR(inFileFP)){
PERROR(输入文件);
EVP_PKEY_free(p键);
返回4;
} SIG =的malloc(EVP_PKEY_size(p键));
如果(EVP_SignFinal(安培;!CTX,SIG,&安培; siglen,p键)){
fprintf中(标准错误,EVP_SignFinal:失败\\ n);
免费(SIG);
EVP_PKEY_free(p键);
返回3;
}
FWRITE(SIG,siglen,1,outFileFP);
免费(SIG);
EVP_PKEY_free(p键);
返回0;
}INT ksignEvpVerify(FILE * publicKeyFP,FILE * dataFileFP,FILE * sigFileFP)
{
RSA * rsa_pkey = NULL;
EVP_PKEY * p键;
EVP_MD_CTX CTX;
无符号字符缓冲区[4096];
为size_t LEN;
无符号字符* SIG;
无符号整型siglen;
结构统计stat_buf; 如果(PEM_read_RSA_PUBKEY(publicKeyFP,&放大器;!rsa_pkey,NULL,NULL)){
fprintf中(标准错误,错误加载RSA公钥文件\\ n);
返回2;
}
p键= EVP_PKEY_new(); 如果(!EVP_PKEY_assign_RSA(p键,rsa_pkey)){
fprintf中(标准错误,EVP_PKEY_assign_RSA:失败\\ n);
返回3;
}
/ *读取签名* /
如果(FSTAT(的fileno(sigFileFP),放大器; stat_buf)== -1){
fprintf中(标准错误,无法读取签名\\ n);
返回4;
}
siglen = stat_buf.st_size;
SIG =(无符号字符*)malloc的(siglen);
如果(SIG == NULL){
fprintf中(标准错误,无法签字\\ n分配%d字节
siglen);
返回5;
}
如果((FREAD(SIG,1,siglen,sigFileFP))!= siglen){
fprintf中(标准错误,无法读取签字\\ n%d字节
siglen);
返回6;
}
/ *
的printf(签名);
对于(i = 0; I< siglen;我++){
fprintf中(标准输出,%02X,SIG [I]);
如果(I%16 == 15)
fprintf中(标准输出,\\ n);
}
fprintf中(标准输出,\\ n);
* / EVP_MD_CTX_init(安培; CTX); 如果(!EVP_VerifyInit(安培;环磷酰胺,EVP_sha1())){
fprintf中(标准错误,EVP_SignInit:失败\\ n);
EVP_PKEY_free(p键);
返回7;
} 而((LEN =的fread(缓冲液,1,sizeof的缓冲器,dataFileFP))大于0){
如果(EVP_VerifyUpdate(安培;!CTX,缓冲,LEN)){
fprintf中(标准错误,EVP_SignUpdate:失败\\ n);
EVP_PKEY_free(p键);
返回8;
}
} 如果(FERROR(dataFileFP)){
PERROR(输入文件);
EVP_PKEY_free(p键);
返回9;
} 如果(EVP_VerifyFinal(安培;!CTX,SIG,siglen,p键)){
fprintf中(标准错误,EVP_VerifyFinal:失败\\ n);
免费(SIG);
EVP_PKEY_free(p键);
返回10;
}
免费(SIG);
EVP_PKEY_free(p键);
返回0;
}
的 pkeyutl
命令应该是pferred至$ P $ rsautl
,因为 pkeyutl
可以处理任何算法。为了获得在命令行上相同的签名,你应该使用下列内容:
OpenSSL的pkeyutl -sign -in testfile.sha1 -inkey ksign_private.pem -pkeyopt摘要:SHA1 -OUTFILE testfile.sig
最重要的部分是告诉的OpenSSL
您使用摘要值。否则,它似乎是你的签名摘要的摘要。
I am using following statement to create a RSA public and private key.
openssl genrsa -out ksign_private.pem 1024 openssl rsa -in ksign_private.pem -pubout > ksign_public.pem
Then I have program that uses, PEM_read_RSAPrivateKey, EVP_PKEY_assign_RSA, EVP_SignInit, EVP_SignUpdate, EVP_SignFinal functions from openssl libcrypto to generate signature file.
I also have routine that verifies that signature can be verified using PEM_read_RSA_PUBKEY, EVP_PKEY_assign_RSA, EVP_VerifyInit, EVP_VerifyUpdate, EVP_VerifyFinal. Source code for these routines is attached below.
When using these functions I can create SHA1 signature, encrypt it with private key, and decrypt it using public key.
However I tried to use the same data file, same private, public key using the openssl rsautl and the signature that is getting created by openssl rsautl is vastly different.
openssl dgst -sha1 -binary < myData > testfile.sha1
openssl rsautl -sign -in testfile.sha1 -inkey ksign_private.pem -keyform PEM -out testfile.sig
Can any one tell me what options I am using wrong when using openssl rsautl or dgst command?
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <ctype.h>
#include <unistd.h>
#include <string.h>
#include <openssl/sha.h>
#include <errno.h>
#include <getopt.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <openssl/evp.h>
#include <openssl/pem.h>
#include <openssl/rsa.h>
int ksignEvpSign(FILE * private_key, FILE * inFileFP, FILE * outFileFP);
int ksignEvpVerify(FILE * public_key, FILE * dataFileFP, FILE * signFileFP);
int ksignEvpSign(FILE * privateKeyFP, FILE * inFileFP, FILE * outFileFP)
{
RSA *rsa_pkey = NULL;
EVP_PKEY *pkey = EVP_PKEY_new();
EVP_MD_CTX ctx;
unsigned char buffer[4096];
size_t len;
unsigned char *sig;
unsigned int siglen;
if (!PEM_read_RSAPrivateKey(privateKeyFP, &rsa_pkey, NULL, NULL)) {
fprintf(stderr, "Error loading RSA Private Key File.\n");
return 2;
}
if (!EVP_PKEY_assign_RSA(pkey, rsa_pkey)) {
fprintf(stderr, "EVP_PKEY_assign_RSA: failed.\n");
return 3;
}
EVP_MD_CTX_init(&ctx);
if (!EVP_SignInit(&ctx, EVP_sha1())) {
fprintf(stderr, "EVP_SignInit: failed.\n");
EVP_PKEY_free(pkey);
return 3;
}
while ((len = fread(buffer, 1, sizeof buffer, inFileFP)) > 0) {
if (!EVP_SignUpdate(&ctx, buffer, len)) {
fprintf(stderr, "EVP_SignUpdate: failed.\n");
EVP_PKEY_free(pkey);
return 3;
}
}
if (ferror(inFileFP)) {
perror("input file");
EVP_PKEY_free(pkey);
return 4;
}
sig = malloc(EVP_PKEY_size(pkey));
if (!EVP_SignFinal(&ctx, sig, &siglen, pkey)) {
fprintf(stderr, "EVP_SignFinal: failed.\n");
free(sig);
EVP_PKEY_free(pkey);
return 3;
}
fwrite(sig, siglen, 1, outFileFP);
free(sig);
EVP_PKEY_free(pkey);
return 0;
}
int ksignEvpVerify(FILE * publicKeyFP, FILE * dataFileFP, FILE * sigFileFP)
{
RSA *rsa_pkey = NULL;
EVP_PKEY *pkey;
EVP_MD_CTX ctx;
unsigned char buffer[4096];
size_t len;
unsigned char *sig;
unsigned int siglen;
struct stat stat_buf;
if (!PEM_read_RSA_PUBKEY(publicKeyFP, &rsa_pkey, NULL, NULL)) {
fprintf(stderr, "Error loading RSA public Key File.\n");
return 2;
}
pkey = EVP_PKEY_new();
if (!EVP_PKEY_assign_RSA(pkey, rsa_pkey)) {
fprintf(stderr, "EVP_PKEY_assign_RSA: failed.\n");
return 3;
}
/* Read the signature */
if (fstat(fileno(sigFileFP), &stat_buf) == -1) {
fprintf(stderr, "Unable to read signature \n");
return 4;
}
siglen = stat_buf.st_size;
sig = (unsigned char *)malloc(siglen);
if (sig == NULL) {
fprintf(stderr, "Unable to allocated %d bytes for signature\n",
siglen);
return 5;
}
if ((fread(sig, 1, siglen, sigFileFP)) != siglen) {
fprintf(stderr, "Unable to read %d bytes for signature\n",
siglen);
return 6;
}
/*
printf("Signature:");
for (i = 0; i < siglen; i++) {
fprintf(stdout, "%02x", sig[i]);
if (i % 16 == 15)
fprintf(stdout, "\n");
}
fprintf(stdout, "\n");
*/
EVP_MD_CTX_init(&ctx);
if (!EVP_VerifyInit(&ctx, EVP_sha1())) {
fprintf(stderr, "EVP_SignInit: failed.\n");
EVP_PKEY_free(pkey);
return 7;
}
while ((len = fread(buffer, 1, sizeof buffer, dataFileFP)) > 0) {
if (!EVP_VerifyUpdate(&ctx, buffer, len)) {
fprintf(stderr, "EVP_SignUpdate: failed.\n");
EVP_PKEY_free(pkey);
return 8;
}
}
if (ferror(dataFileFP)) {
perror("input file");
EVP_PKEY_free(pkey);
return 9;
}
if (!EVP_VerifyFinal(&ctx, sig, siglen, pkey)) {
fprintf(stderr, "EVP_VerifyFinal: failed.\n");
free(sig);
EVP_PKEY_free(pkey);
return 10;
}
free(sig);
EVP_PKEY_free(pkey);
return 0;
}
The pkeyutl
command should be preferred to rsautl
since pkeyutl
can handle any algorithm. To obtain the same signature on the command line, you should use the following:
openssl pkeyutl -sign -in testfile.sha1 -inkey ksign_private.pem -pkeyopt digest:sha1 -outfile testfile.sig
The important part is telling openssl
that you're using a digest value. Otherwise it seems to be signing a digest of your digest.
这篇关于OpenSSL的签名区别使用C程序和OpenSSL DGST,rsautl命令行时的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!