2011-12-20 20 views
5

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.
+0

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. –

+0

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

Trả lời

-1

Tôi làm cách nào để có được chữ ký giống nhau?

Hầu hết các thuật toán chữ ký số - bao gồm RSA, mà tôi cho rằng bạn đã sử dụng ở đây, không xác định. Hãy thử ký cùng một tệp hai lần với cùng một chương trình và bạn sẽ nhận được các kết quả đầu ra khác nhau.

Điều này có nghĩa là, chạy cùng một thuật toán hai lần với cùng một đầu vào sẽ cung cấp cho bạn chữ ký khác nhau. Đây không phải là một vấn đề, miễn là thuật toán xác minh vẫn quản lý để chấp nhận tất cả các chữ ký được tạo ra bởi thuật toán ký (với khóa phù hợp).

Tính không xác định này thường thực sự cần thiết cho bảo mật của lược đồ chữ ký.

Để xem hai thuật toán chữ ký của bạn có thực sự tương thích hay không, hãy thử xác minh chữ ký OpenSSL bằng API MS Crypto và để xác minh chữ ký Crypto MS với OpenSSL. (Sau đó sửa đổi các tập tin bằng một byte và kiểm tra xem họ không xác minh nữa.)

+0

Paulo, tôi đã có được chữ ký giống nhau. Nhưng tôi đã thay đổi nhiệm vụ. – Stanislav

+2

Tôi đã tạo khóa và chữ ký với MS CryptoAPI và xác thực bằng OpenSSL. Và ngược lại. Và chữ ký là duy nhất!Vì vậy, tôi cho rằng tôi đã đối phó với RSA xác định trong trường hợp của tôi. – Stanislav

+0

Nếu cùng một dữ liệu được ký bởi cùng một khóa riêng, chữ ký sẽ luôn giống như đệm không phải là ngẫu nhiên. – doptimusprime

Các vấn đề liên quan