Tôi tự tạo chứng chỉ X509 với private key sử dụng tiện ích makecertOpenSSL và MS CryptoAPI: chữ ký kỹ thuật số khác nhau
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
Sau đó, tôi chuyển RootCATest.pvk để RootCATest.pem với OpenSSL. Và tôi trích xuất khóa công khai: pubRootCATest.pem
Tôi có tệp nhỏ có tên là 'msg'. Và tôi ký tệp này bằng SHA1.
openssl dgst -sha1 -sign c:\RootCATest.pem -out c:\openssl c:\msg
Sau đó, tôi muốn nhận được chữ ký số tương tự bằng MS CryptoAPI.
Đây là mã của tôi (Lưu ý: đây là mã để hiểu khái niệm nên tôi không nhớ đã cấp phát miễn phí)
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);
}
Như ra tôi nhận được chữ ký hoàn toàn khác với chữ ký được thực hiện bởi OpenSSL. Tôi làm cách nào để có được chữ ký giống nhau?
Như tôi đã xem xét có một số thời gian để chú ý:
- msg_size của tôi cũng giống như kích thước tập tin. Vì vậy, nó là số byte để ký. Trên một số trang web tôi đã thấy các đề xuất để thêm một byte trống vào byte mảng. Tôi có thực sự cần nó trong trường hợp như vậy không?
- Cờ CRYPT_NOHASHOID. Nếu không có nó, tôi nhận được chữ ký có kích thước 130 byte, khi chữ ký được tạo bởi OpenSSL là 128 byte. Vì vậy, tôi nghĩ CRYPT_NOHASHOID nên ở đó.
- SwapBytes (...) Tôi đã thử với nó và không có nó. Và trong cả hai trường hợp, tôi có chữ ký hoàn toàn khác với chữ ký OpenSSL.
Có nhiều định dạng khác nhau cho cả dữ liệu đi vào chữ ký cũng như chữ ký. Đây là phần bạn sẽ phải làm đúng. –
Bây giờ, hãy sử dụng RSA_verify để xác minh chữ ký này và nếu nó có thể xác minh được, thì nó giống nhau. – doptimusprime