2017-05-09 1 views
1

Je tente de générer une clé RSA CA KeyPair et un certificat et de l'enregistrer dans le fichier de clés. Mon code est:Java enregistrer les clés dans le magasin de clés KeyStoreException

import java.io.FileOutputStream; 
import java.math.BigInteger; 
import java.security.KeyPair; 
import java.security.KeyPairGenerator; 
import java.security.KeyStore; 
import java.security.SecureRandom; 
import java.security.Security; 
import java.security.cert.X509Certificate; 
import java.util.Date; 

import org.bouncycastle.asn1.x500.X500Name; 
import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo; 
import org.bouncycastle.cert.X509CertificateHolder; 
import org.bouncycastle.cert.X509v3CertificateBuilder; 
import org.bouncycastle.cert.jcajce.JcaX509CertificateConverter; 
import org.bouncycastle.jce.provider.BouncyCastleProvider; 
import org.bouncycastle.operator.ContentSigner; 
import org.bouncycastle.operator.jcajce.JcaContentSignerBuilder; 

    private static final String storeType = "PKCS12"; 
     private static final String storePassword = "password"; 
     private static final String storePath = "/usr/lib/java/keystore.ks"; 
     private static final Date startDate = new Date(System.currentTimeMillis());           // time from which certificate is valid 
     private static final Date expiryDate = new Date(System.currentTimeMillis() + 2L * 365L * 24L * 60L * 60L * 1000L); // time after which certificate is not valid (2 years) 
     private static final BigInteger serialNumber = BigInteger.valueOf(System.currentTimeMillis()); 
     private static X500Name issuer; 
     private static X500Name subject; 
     private static KeyPair pair; 

     public static void saveKeys() throws Exception{ 
      Security.addProvider(new BouncyCastleProvider()); 

      KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance("RSA"); 
      keyPairGen.initialize(2048, new SecureRandom()); 
      pair = keyPairGen.generateKeyPair(); 
      byte[] pub = pair.getPublic().getEncoded(); 
      byte[] priv = pair.getPrivate().getEncoded(); 
      SubjectPublicKeyInfo pubInfo = SubjectPublicKeyInfo.getInstance(pub); 

      issuer = new X500Name("CN=CA"); 
      subject = issuer; 

      X509v3CertificateBuilder certBuilder = new X509v3CertificateBuilder(
        issuer,  //issuer (CA) 
        serialNumber, 
        startDate, expiryDate, 
        subject,  //subject 
        pubInfo); 

      //signature for sig 
      ContentSigner sigGen = new JcaContentSignerBuilder("SHA1WithRSA").build(pair.getPrivate()); 
      X509CertificateHolder certHolder = certBuilder.build(sigGen); 
      X509Certificate caCert = new JcaX509CertificateConverter().getCertificate(certHolder); 

      X509Certificate[] chain = new X509Certificate[3]; 
      chain[2] = caCert; 

      KeyStore store; 
      try { 
       store = KeyStore.getInstance(storeType); 
       store.load(null,null); 
      store.setKeyEntry("CA-Key", priv, chain); 
      store.store(new FileOutputStream("public.p12"), null); 

      } catch (Exception e) { 
       e.printStackTrace(); 
      } 

Puis-je obtenir l'erreur:

java.security.KeyStoreException: Private key is not stored as PKCS#8 EncryptedPrivateKeyInfo: java.io.IOException: overrun, bytes = 1194 
    at sun.security.pkcs12.PKCS12KeyStore.engineSetKeyEntry(PKCS12KeyStore.java:687) 
    at java.security.KeyStore.setKeyEntry(KeyStore.java:1174) 
    at storeKeys.saveKeys(storeKeys.java:95) 
    at storeKeys.main(storeKeys.java:146) 
Caused by: java.io.IOException: overrun, bytes = 1194 

Comment puis-je chiffrer la clé privée au format? Et où puis-je donner le chemin à Keystore pour enregistrer les clés?

Répondre

2

Si vous voyez dit le doc java de cette méthode,:

Assigns the given key (that has already been protected) to the given alias.

If the protected key is of type java.security.PrivateKey, it must be accompanied by a certificate chain certifying the corresponding public key. If the underlying keystore implementation is of type jks, key must be encoded as an EncryptedPrivateKeyInfo as defined in the PKCS #8 standard.

Il dit JKS, mais on dirait qu'il attend le format de clé privée cryptée pour PKCS12 également.

Vous ne pouvez donc pas simplement passer dans le tableau d'octets de clé privée.

Pour faciliter les choses, vous pouvez le faire:

PrivateKeyEntry privateKeyEntry = new PrivateKeyEntry(pair.getPrivate(), chain); 
store.setEntry("CA-Key", privateKeyEntry, new KeyStore.PasswordProtection(storePassword.toCharArray())); 

Et dans votre méthode keystore.store(..), le premier argument est le chemin keystore. Et le deuxième argument est le mot de passe du keystore.

Ainsi, vous pouvez faire quelque chose comme ceci:

store.store(new FileOutputStream(new File(storePath)), storePassword.toCharArray()); 
+0

me donne l'Exception dans le thread "principal" java.lang.NullPointerException \t à java.security.KeyStore $ PrivateKeyEntry. (KeyStore.java:532) \t à java.security.KeyStore $ PrivateKeyEntry. (KeyStore.java:491) – nolags

+1

Cela peut être à cause de votre chaîne de certificats. Vous n'avez qu'un seul certificat auto-signé, que vous stockez dans la variable 'chain'. Mais la taille que vous avez définie est 3 et le stockage du certificat auto-signé à la 3ème position du tableau. Donc les 2 premiers sont nuls. Essayez de changer la taille à 1 et mettez le certificat autosigné à l'emplacement zéro et recommencez. –

+0

Oh erreur stupide. Merci ça ça marche. – nolags