5

makecert ユーティリティを使用して秘密鍵で X509 証明書を生成しました

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 

次に、OpenSSL を使用して RootCATest.pvk を RootCATest.pem に変換しました。そして、公開鍵を抽出しました: pubRootCATest.pem

「msg」という小さなファイルがあります。そして、SHA1 を使用してこのファイルに署名します。

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

次に、MS CryptoAPI を使用して同じデジタル署名を取得したいと考えています。

これが私のコードです(注:これは概念を理解するためのコードなので、割り当てられたメモリを解放しません)

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

出力として、OpenSSL によって作成された署名とはまったく異なる署名を取得します。どうすれば同じ署名を取得できますか?

私が考えるように、注意を払うべきいくつかの瞬間があります:

  • 私のmsg_sizeはファイルサイズと同じです。したがって、署名するバイト数です。一部のサイトでは、null バイトをバイト配列に追加するよう推奨されていました。このような場合、本当に必要ですか?
  • フラグ CRYPT_NOHASHOID。それがなければ、OpenSSL によって作成された署名が 128 バイトの場合、サイズが 130 バイトの署名を取得します。だから私は CRYPT_NOHASHOID がそこにあるべきだと思います。
  • SwapBytes(...) ありとなしで試してみました。どちらの場合も、OpenSSL 署名とはまったく異なる署名があります。
4

1 に答える 1

-1

同じ署名を取得するにはどうすればよいですか?

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

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

この非決定論は、署名スキームのセキュリティのために実際に必要になることがよくあります。

2つの署名アルゴリズムに実際に互換性があるかどうかを確認するには、MS Crypto APIを使用してOpenSSL署名を検証し、OpenSSLを使用してMSCrypto署名を検証してみてください。(次に、ファイルを1バイト変更し、検証されないことを確認します。)

于 2011-12-23T23:05:56.017 に答える