2011-12-20 14 views
5

IそしてIは、OpenSSLとRootCATest.pemにRootCATest.pvk変換makecertユーティリティをのOpenSSLとMSのCryptoAPI:異なるデジタル署名

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 

を使用して秘密鍵でX509証明書を生成しました。そして私は公開鍵を抽出しました:pubRootCATest.pem

私は小さなファイル 'msg'を持っています。 そして、SHA1を使ってこのファイルに署名します。

openssl dgst -sha1 -sign c:\RootCATest.pem -out c:\openssl c:\msg 

次に、私はMS CryptoAPIを使用して同じデジタル署名を取得します。出力として、私は、OpenSSLによって行われた署名全く異なる署名を取得

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); 
} 

:(これは私が自由に割り当てられたメモリをしないように、概念を理解するためのコードであることに注意してください)

は、ここに私のコードです。 同じ署名を取得するにはどうすればよいですか?

私は注意を払うためにいくつかの瞬間がある考慮するとして:

  • 私msg_sizeは、ファイルサイズと同じです。したがって、 符号のバイト数です。いくつかのサイトでは、バイト番号 配列にヌルバイトを追加することを勧めました。私は本当にそのような場合にそれを必要としますか?
  • フラグCRYPT_NOHASHOID。それがなければ、OpenSSLによって作られた署名が128バイトであるときに、サイズが130バイトの署名が得られます。だから私はCRYPT_NOHASHOIDがそこにあるはずだと思う。
  • SwapBytes(...)私はそれを試してみました。そして、どちらの場合も、私は がOpenSSL署名とはまったく異なる署名を持っています。
+0

署名に入るデータと署名自体の両方にさまざまな形式があります。これはあなたが正しくなければならない部分です。 –

+0

今、RSA_verifyを使用してこの署名を検証し、検証可能な場合は同じです。 – doptimusprime

答えて

-1

どのように同じ署名を取得できますか?

ここで使用していると思われるRSAを含むほとんどのデジタル署名アルゴリズムは、非決定的です。同じプログラムで同じファイルに2回署名すると、異なる出力が得られます。

これは、同じ入力を同じアルゴリズムで2回実行すると、異なる署名が得られることを意味します。これは、検証アルゴリズムが依然として署名アルゴリズムによって生成されたすべての署名を受け入れるように管理している限り(フィッティングキーを使用して)、問題ではありません。

この非決定論は、実際には、署名方式のセキュリティのためにしばしば必要です。

2つの署名アルゴリズムが実際に互換性があるかどうかを確認するには、MS Crypto APIでOpenSSL署名を検証し、OpenSSLでMS暗号署名を確認してください。 (その後、ファイルを1バイト修正し、それ以上検証しないことを確認してください)

+0

Paulo、私は同じ署名を得ることができました。しかし、私は仕事を変えました。 – Stanislav

+2

MS CryptoAPIで鍵と署名を生成し、OpenSSLで検証しました。およびその逆。そしてその署名はユニークでした!だから私は私のケースでは確定的なRSAを扱っていると思います。 – Stanislav

+0

同じデータが同じ秘密鍵で署名されている場合、署名は常にパディングがランダムではないため同じです。 – doptimusprime