7

Java の暗号化ルーチンに関するヘルプが必要です。

PKCS#7 署名が与えられた場合、そこに含まれるすべての証明書を信頼できるストアに対して検証したいと考えています。署名に含まれるすべての証明書は、有効な証明書パス (またはチェーンなど) を形成する正しい順序になっていると想定しているため、

  • 最上位 (#0) は署名証明書です。
  • 次のもの (#1) は #0 の署名に使用される中間証明書です。
  • 次のもの (#2) は別の中間証明書で、#1 の署名に使用されます。
  • 等々。

最後の証明書 (#N) は CA によって署名されています。

それが私がこれまでハッキングできたものです:

// Exception handling skipped for readability

//byte[] signature = ...
pkcs7 = new PKCS7(signature); // `sun.security.pkcs.PKCS7;`

// *** Checking some PKCS#7 parameters here

X509Certificate prevCert = null; // Previous certificate we've found
X509Certificate[] certs = pkcs7.getCertificates(); // `java.security.cert.X509Certificate`
for (int i = 0; i < certs.length; i++) {
    // *** Checking certificate validity period here

    if (cert != null) {
        // Verify previous certificate in chain against this one
        prevCert.verify(certs[i].getPublicKey());
    }
    prevCert = certs[i];
}

//String keyStorePath = ...
KeyStore keyStore = KeyStore.getInstance("JKS"); // `java.security.KeyStore`
keyStore.load(new FileInputStream(keyStorePath), null);

// Get trusted VeriSign class 1 certificate
Certificate caCert = keyStore.getCertificate("verisignclass1ca"); // `java.security.cert.Certificate`

// Verify last certificate against trusted certificate
cert.verify(caCert.getPublicKey());

問題は、標準の Java クラスのようなものを使用してこれを行うにはどうすればよいかということCertPathです。私は自転車を再発明しているという強い気持ちを持っています。または、誰かが BouncyCastle ライブラリの例を持っていれば、それも問題ありません。

おまけの質問: ルート証明書が自動的に選択されるように、信頼できるストアに対して証明書を検証する方法は?

4

2 に答える 2

14

自分で解決策を見つけました。したがって、信頼できるストアに対して証明書チェーンを抽出して検証する方法は次のとおりです (読みやすくするために例外処理はスキップされます)。

CertificateFactory cf = CertificateFactory.getInstance("X.509");

// Get ContentInfo
//byte[] signature = ... // PKCS#7 signature bytes
InputStream signatureIn = new ByteArrayInputStream(signature);
DERObject obj = new ASN1InputStream(signatureIn).readObject();
ContentInfo contentInfo = ContentInfo.getInstance(obj);

// Extract certificates
SignedData signedData = SignedData.getInstance(contentInfo.getContent());
Enumeration certificates = signedData.getCertificates().getObjects();

// Build certificate path
List certList = new ArrayList();
while (certificates.hasMoreElements()) {
    DERObject certObj = (DERObject) certificates.nextElement();
    InputStream in = new ByteArrayInputStream(certObj.getDEREncoded());
    certList.add(cf.generateCertificate(in));
}
CertPath certPath = cf.generateCertPath(certList);

// Load key store
//String keyStorePath = ...
KeyStore keyStore = KeyStore.getInstance("JKS");
keyStore.load(new FileInputStream(keyStorePath), null);

// Set validation parameters
PKIXParameters params = new PKIXParameters(keyStore);
params.setRevocationEnabled(false); // to avoid exception on empty CRL

// Validate certificate path
CertPathValidator validator = CertPathValidator.getInstance("PKIX");
CertPathValidatorResult result = validator.validate(certPath, params);

validate()検証が失敗した場合、例外がスローされます。

ドキュメント: ASN1Set, ContentInfo, SignedData. 他のすべての風変わりな名前と関連するドキュメントは にありますjava.security.cert

ここでは SUN に依存せず、 BouncyCastle プロバイダー ライブラリのみが必要です。

この質問 (および特に回答) も役立つ場合があります。

于 2010-07-05T14:08:06.200 に答える
2

CertificateFactoryが必要です。javadocs の最後の例は、まさにあなたが望むことを行います。

于 2010-07-02T20:00:36.257 に答える