Diverse firme durante l’uso di routine C e comandi openssl dgst, rsautl

Sto usando la seguente dichiarazione per creare una chiave pubblica e privata RSA.

openssl genrsa -out ksign_private.pem 1024 openssl rsa -in ksign_private.pem -pubout> ksign_public.pem

Poi ho un programma che usa le funzioni PEM_read_RSAPrivateKey, EVP_PKEY_assign_RSA, EVP_SignInit, EVP_SignUpdate, EVP_SignFinal da openssl libcrypto per generare un file di firma.

Ho anche una routine che verifica che la firma possa essere verificata usando PEM_read_RSA_PUBKEY, EVP_PKEY_assign_RSA, EVP_VerifyInit, EVP_VerifyUpdate, EVP_VerifyFinal. Il codice sorgente per queste routine è allegato sotto.

Quando si utilizzano queste funzioni, è ansible creare la firma SHA1, crittografarla con la chiave privata e decodificarla utilizzando la chiave pubblica.

Tuttavia, ho provato a utilizzare lo stesso file di dati, la stessa chiave pubblica privata che utilizza openssl rsautl e la firma che viene creata da openssl rsautl è molto diversa.

openssl dgst -sha1 -binary  testfile.sha1 openssl rsautl -sign -in testfile.sha1 -inkey ksign_private.pem -keyform PEM -out testfile.sig 

Qualcuno può dirmi quali opzioni sto usando male quando si utilizza il comando openssl rsautl o dgst?

 #include  #include  #include  #include  #include  #include  #include  #include  #include  #include  #include  #include  #include  #include  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  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; } 

Il comando pkeyutl dovrebbe essere preferito a rsautl dato che pkeyutl può gestire qualsiasi algoritmo. Per ottenere la stessa firma sulla riga di comando, è necessario utilizzare quanto segue:

 openssl pkeyutl -sign -in testfile.sha1 -inkey ksign_private.pem -pkeyopt digest:sha1 -outfile testfile.sig 

La parte importante sta dicendo a openssl che stai usando un valore digest. Altrimenti sembra che stia firmando un digest del tuo digest.

Puoi utilizzare direttamente il comando dgst per eseguire l’hash e firmare dati come:

openssl dgst -sha1 -binary -sign privkey.pem < myData > mySignature

vedi i documenti per tutte le opzioni.