que generan certificado X509 con la clave privada usando la utilidad makecertOpenSSL y MS CryptoAPI: diferentes firmas digitales
makecert -n "CN=RootCATest" -r -sv RootCATest.pvk RootCATest.cer
makecert -sk MyKeyName -iv RootCATest.pvk -n "CN=tempCert" -ic RootCATest.cer -sr currentuser -ss my -sky signature —pe
Entonces convertidos RootCATest.pvk a RootCATest.pem con OpenSSL. Y extraje la clave pública: pubRootCATest.pem
Tengo un archivo pequeño llamado 'msg'. Y firmo este archivo usando SHA1.
openssl dgst -sha1 -sign c:\RootCATest.pem -out c:\openssl c:\msg
Luego quiero obtener la misma firma digital usando MS CryptoAPI.
Aquí está mi código (Nota: este es el código para entender los conceptos por lo que no hago memoria asignada libre)
void SwapBytes(BYTE *pv, int n)
{
BYTE *p = pv;
int lo, hi;
for(lo=0, hi=n-1; hi>lo; lo++, hi--)
{
BYTE tmp=p[lo];
p[lo] = p[hi];
p[hi] = tmp;
}
}
void sign()
{
FILE *file;
BYTE *msg;
int msg_size;
HCRYPTPROV hProv;
HCERTSTORE hStore;
PCCERT_CONTEXT pCert;
DWORD dwKeySpec;
BOOL fCallerFreeProv;
BYTE *pSignature;
DWORD sigLen;
// Read message bytes from file
file = fopen("c:\\msg", "r");
fseek(file, 0, SEEK_END);
msg_size = ftell(file);
fseek(file, 0, SEEK_SET);
msg = new BYTE[msg_size];
fread(msg, sizeof(BYTE), msg_size, file);
fclose(file);
hStore = CertOpenSystemStore(NULL, "My");
pCert = CryptUIDlgSelectCertificateFromStore(hStore, NULL, NULL, NULL, 0, 0, NULL);
CryptAcquireCertificatePrivateKey(pCert, CRYPT_ACQUIRE_COMPARE_KEY_FLAG, NULL, &hProv, &dwKeySpec, &fCallerFreeProv);
PrintCryptoProviderName(hProv); // prints Microsoft Strong Cryptographic Provider
ALG_ID hashAlgId = CALG_SHA1;
HCRYPTHASH hHash;
CryptCreateHash(hProv, CALG_SHA1, 0, 0, &hHash);
CryptHashData(hHash, msg, msg_size, 0);
CryptSignHash(hHash, dwKeySpec, NULL, 0, NULL, &sigLen);
pSignature = new BYTE[sigLen];
CryptSignHash(hHash, dwKeySpec, NULL, CRYPT_NOHASHOID, pSignature, &sigLen);
SwapBytes(pSignature, sigLen); // Here i reverse byte order as I read that MS CryptoAPI uses reversed byte order
// Write signature bytes to file
file = fopen("c:\\CryptSignHash", "w");
fwrite(pSignature, sizeof(BYTE), sigLen, file);
fclose(file);
}
medida que la producción llegue la firma absolutamente diferente de la firma hecha por OpenSSL. ¿Cómo puedo obtener la misma firma?
Dado que considero que hay algunos momentos para prestar atención:
- Mi msg_size es el mismo que el tamaño del archivo. Por lo tanto, es el número de bytes a signo. En algunos sitios, vi recomendaciones para agregar un arreglo de bytes nulos a byte . ¿Realmente lo necesito en tal caso?
- La bandera CRYPT_NOHASHOID. Sin él obtengo la firma de tamaño 130 bytes, cuando la firma realizada por OpenSSL es de 128 bytes. Así que creo que CRYPT_NOHASHOID debería estar allí.
- SwapBytes (...) Lo intenté sin él. Y en ambos casos I tienen firmas completamente diferentes a la firma de OpenSSL.
Existen muchos formatos diferentes tanto para los datos que entran en la firma como para la propia firma. Esta es la parte que tendrá que hacer bien. –
Ahora, use RSA_verify para verificar esta firma y si es verificable, entonces es la misma. – doptimusprime