0

我正在尝试创建一个自签名证书。我想这样做是为了将 Spongey Castle KeyPair 存储到“AndroidKeyStore”中。签名需要是带有 SHA-256 摘要的 P-256 的 ECDSA。

// see http://www.programcreek.com/java-api-examples/index.php?class=org.spongycastle.cert.X509v3CertificateBuilder&method=addExtension
X509Certificate genSelfSignedCert(KeyPair kp, String CN){
    X509Certificate certificate;

    try{
        X500Name x500Name = new X500NameBuilder(BCStyle.INSTANCE)
                            .addRDN(BCStyle.CN, CN)
                            .build();

        SecureRandom rand = new SecureRandom();
        PrivateKey privKey = kp.getPrivate();
        PublicKey pubKey = kp.getPublic();

        SubjectPublicKeyInfo subPubKeyInfo = SubjectPublicKeyInfo.getInstance(ASN1Sequence.getInstance(pubKey.getEncoded()));

        Date startDate = new Date(); // now

        Calendar c = Calendar.getInstance();
        c.setTime(startDate);
        c.add(Calendar.YEAR, 1);
        Date endDate = c.getTime();

        X509v3CertificateBuilder v3CertGen = new X509v3CertificateBuilder(
                         x500Name,
                         BigInteger.valueOf(rand.nextLong()),
                         startDate, endDate,
                         x500Name,
                         subPubKeyInfo);


        ContentSigner sigGen = new JcaContentSignerBuilder("SHA256withECDSA").build(privKey);
        X509CertificateHolder certHolder = v3CertGen.build(sigGen);
        certificate = new JcaX509CertificateConverter().getCertificate(certHolder);
    }//try
    catch( OperatorCreationException| CertificateException X ) {;}

    mLog.debug( "kp.getPublic().getAlgorithm(): \t" + kp.getPublic().getAlgorithm() );
    mLog.debug("certificate.getPublicKey().getAlgorithm():\t" + certificate.getPublicKey().getAlgorithm());

    return certificate;
}//genSelfSignedCert()

当我使用上述方法 genSelfSignedCert() (取自 ProgramCreek.com)

X509Certificate[] selfSignedCert = new X509Certificate[1];
selfSignedCert[0] = genSelfSignedCert(keyPair, "MyAwesomeAlias");
KeyStore.Entry privateKey = new PrivateKeyEntry(keyPair.getPrivate(), selfSignedCert );

我得到:

kp.getPrivate().getAlgorithm(): ECDSA
kp.getPublic().getAlgorithm():  ECDSA
certificate.getPublicKey().getAlgorithm(): EC   <--MISMATCH!? Why not ECDSA?

IllegalArgumentException: 
 Algorithm of private key does not match algorithm of public key in end certificate of entry (with index number: 0)

为什么这种方法会创建一个算法与其密钥对不匹配的证书?

4

1 回答 1

0

好的。底线是我正在尝试混合加密提供者(海绵与 AndroidKeyStore)。

我决定不这样做,但是如果你想混合加密提供者,你必须像这样相应地切换:

//Moves provider to first place
static void initSecurity(java.security.Provider provider){
    listProviders();
    java.security.Security.removeProvider(provider.getName());

    int insertProviderAt = java.security.Security.insertProviderAt(provider, 1);
    mLog.debug("insertProviderAt:\t" + Integer.toString(insertProviderAt) ) ;
    listProviders();
}//initSecurity



static public void listProviders(){
    java.security.Provider[] providers = java.security.Security.getProviders();
    StringBuilder list = new StringBuilder().append("Num providers: " + providers.length );
    int i = 0;
    for (java.security.Provider p : providers){
        list.append("\n\tProvider " + ++i + ": " + p.getName() + "\t info: " + p.getInfo());
        java.util.Set<java.security.Provider.Service> services = p.getServices();
        list.append("\tNum services: " + services.size());
        for (java.security.Provider.Service s : services ){
            //list.append("\n\t\tService: " + s.toString() + "\ttype: " + s.getType() + "\talgo: " + s.getAlgorithm());
        }
    }

    mLog.debug(list.toString());
}//listProviders
于 2016-03-08T19:17:23.503 回答