3

SunMSCAPIプロバイダーでファイルに署名したい。公開鍵と署名は、MS Crypto API を使用してインポートする必要があるためです。

通常、 を使用して署名を生成するとSHA1withRSA、最終的にビッグ エンディアンからリトル エンディアン (バイト オーダー) への変換が行われます。

//generate keystore with java keytool
$Keytool -genkey -alias tsign -keystore c:\test\tsignjks.p12 - keyalg rsa -storetype  pkcs12

Java アプリケーションの場合:

//for signing and getting keystore, assuming windows certificate is installed
..ks = KeyStore.getInstance("Windows-MY","SunMSCAPI"); 
PrivateKey priv = ks.getKey("tsign",password); 
Signature rsa = Signature.getInstance("SHA1withRSA","SunMSCAPI"); 
rsa.initSign(priv);
.. 
rsa.update(buffer, 0, len);
..
byte[] realSig = rsa.sign();

//for writing public key for ms crypto api or exporting it from windows certificate store
Certificate cert = ks.getCertificate("tsign");
byte[] encodedCert = cert.getEncoded();
FileOutputStream certfos = new FileOutputStream("tsigncer.cer");
certfos.write(encodedCert);

//for writing signatures for ms crypto api
FileOutputStream sigfos = new FileOutputStream(targetPath + "/"
                + signatureName);
sigfos.write(realSig);

これでSunMSCAPI問題は解決すると思いますが、MS Crypto API を使用して公開鍵をいつインポートするかはわかりません。最初の段階ではインポートされません (ビッグ エンディアンからリトル エンディアンのバイト オーダーに変更しない限り)。以下は暗号 API のコードです。 .

LPCSTR file = "tsigncer.cer";
//LPCSTR file = "omsign.p12";
BOOL crypt_res = FALSE;

HCRYPTPROV crypt_prov_hndl = NULL;
 crypt_res = CryptAcquireContext(&crypt_prov_hndl, NULL, NULL, PROV_RSA_FULL, 0/*CRYPT_NEWKEYSET*/);
//crypt_res = CryptAcquireContext(&crypt_prov_hndl, NULL, NULL, PROV_DSS, CRYPT_VERIFYCONTEXT/*CRYPT_NEWKEYSET*/);

    if (!crypt_res) {
        HRESULT decode_hr = __HRESULT_FROM_WIN32(GetLastError());
        return decode_hr;
    }

    // Load key file
    HANDLE fileHandle = CreateFile(file, // name of the write
                       GENERIC_READ,          // open for writing
                       0,                      // do not share
                       NULL,                   // default security
                       OPEN_EXISTING,             // create new file only
                       FILE_ATTRIBUTE_NORMAL,  // normal file
                       NULL);                  // no attr. template

    if (fileHandle == INVALID_HANDLE_VALUE)
    {
        DWORD d = GetLastError();
        return -1;
    }

    BYTE buffer[2056];
    DWORD fileSize = 0;
    DWORD fileSizeResult = GetFileSize(fileHandle, &fileSize);

    DWORD numBytesRead = 0;
    BOOL fileLoadResult = ReadFile(fileHandle, (PVOID)buffer, fileSizeResult, &numBytesRead, NULL);

    // Import key
    BOOL result = ImportKey(crypt_prov_hndl, (LPBYTE)buffer, numBytesRead);
//result is always false..
4

1 に答える 1

6

MSCAPI を使用している場合は、キーを Microsoft 証明書ストアに追加したと見なされます。[インターネット プロパティ] > [コンテンツ] > [証明書] に移動すると、利用可能な証明書のリストが表示され、キーが存在するかどうかを確認できます。証明書がない場合は使用できません。そこにある場合は、次のコードが必要です。

SunMSCAPI providerMSCAPI = new SunMSCAPI();
Security.addProvider(providerMSCAPI);
KeyStore ks = KeyStore.getInstance("Windows-MY");
ks.load(null, null);

そこからは、コードはかなり標準的です。詳細については、デジタル署名に関する私の本を参照してください (この本は無料です)。

重要な補足: Java 6 の 64 ビット バージョンには SunMSCAPI が存在しないことを忘れていました (Java 7 については知りません)。これは、32 ビット版をインストールすることで解決できます。

于 2013-04-05T12:47:33.420 に答える