androidkeystoreself-signedspongycastle

Spongey Castle self-signed Certificate vs. Android KeyStore?


I'm trying to create a self-signed certificate. I want to do this in order to store a Spongey Castle KeyPair into "AndroidKeyStore". The signature needs to be ECDSA for P-256 with a SHA-256 digest.

// 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()

When I use the above method genSelfSignedCert() (taken from ProgramCreek.com)

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

I get:

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)

Why does this method create a cert whose algorithm mismatches its keypair?


Solution

  • ok. the bottom line is I'm trying to mix crypto providers (spongy vs. AndroidKeyStore).

    I've decided NOT to do so BUT if you want to mix crypto providers you must switch accordingly like so:

    //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