2015-01-02 8 views
7

Meine Anwendung speichert private Schlüssel im PEM-Format, der vorhandene Code funktioniert für RSA-Schlüssel, aber ich versuche, auf EC-Schlüssel zu wechseln, und es gibt ein Problem. Die Schlüsselwiederherstellung scheint zu funktionieren, und die equals-Methode für den wiederhergestellten Schlüssel gibt für den ursprünglichen Schlüssel den Wert true zurück, aber getAlgorithm() für den ursprünglichen Schlüssel gibt "EC" und den wiederhergestellten Schlüssel "ECDSA" zurück. Die Diskrepanz im Algorithmus verursacht später Probleme, da sie nicht mit dem Algorithmus für den entsprechenden öffentlichen Schlüssel übereinstimmt.EC privaten Schlüssel Recovery von PEM-Format mit BouncyCastle

Mache ich etwas falsch oder ist das ein Fehler im PEM-Parser?

Hier ist ein Testprogramm, das das Problem veranschaulicht:

import java.io.ByteArrayOutputStream; 
import java.io.IOException; 
import java.io.OutputStreamWriter; 
import java.io.StringReader; 
import java.security.KeyPair; 
import java.security.KeyPairGenerator; 
import java.security.PrivateKey; 
import java.security.SecureRandom; 
import java.security.spec.ECGenParameterSpec; 

import org.bouncycastle.openssl.PEMKeyPair; 
import org.bouncycastle.openssl.PEMParser; 
import org.bouncycastle.openssl.PEMWriter; 
import org.bouncycastle.openssl.jcajce.JcaPEMKeyConverter; 
import org.immutify.janus.keytool.KeyToolUtils; 

public class TestPrivateKeyRecovery 
{ 
    private static final String KEY_ALGORITHM   = "EC"; 
    private static final String SIGNATURE_ALGORITHM  = "SHA512withECDSA"; 
    private static final String PROVIDER    = "BC"; 
    private static final String CURVE_NAME    = "secp521r1"; 
    private static final String WRAPPING_CIPHER_SPEC = "ECIESwithAES"; 

    private ECGenParameterSpec ecGenSpec; 
    private KeyPairGenerator keyGen_; 
    private SecureRandom  rand_; 

    public void run() 
    { 
     try 
     { 
      rand_  = new SecureRandom(); 
      ecGenSpec = new ECGenParameterSpec(CURVE_NAME); 
      keyGen_  = KeyPairGenerator.getInstance(KEY_ALGORITHM, PROVIDER); 

      keyGen_.initialize(ecGenSpec, rand_); 


      PrivateKey privateKey = keyGen_.generateKeyPair().getPrivate(); 





      String der = privateKeyToDER(privateKey); 

      PrivateKey recoveredKey = privateKeyFromDER(der); 

      System.out.println("privateKey=" + privateKey); 
      System.out.println("privateKey.getAlgorithm()=" + privateKey.getAlgorithm()); 
      System.out.println("der=" + der); 
      System.out.println("recoveredKey=" + privateKey); 
      System.out.println("recoveredKey.getAlgorithm()=" + recoveredKey.getAlgorithm()); 
      System.out.println(); 

      if(privateKey.equals(recoveredKey)) 
       System.out.println("Key recovery ok"); 
      else 
       System.err.println("Private key recovery failed"); 

      if(privateKey.getAlgorithm().equals(recoveredKey.getAlgorithm())) 
       System.out.println("Key algorithm ok"); 
      else 
       System.err.println("Key algorithms do not match"); 
     } 
     catch(Exception e) 
     { 
      e.printStackTrace(); 
     } 
    } 

    public static String  privateKeyToDER(PrivateKey key) throws IOException 
    { 
     ByteArrayOutputStream bos = new ByteArrayOutputStream(); 
     PEMWriter    pemWriter = new PEMWriter(new OutputStreamWriter(bos)); 

     pemWriter.writeObject(key); 

     pemWriter.close(); 

     return new String(bos.toByteArray()); 
    } 

    public static PrivateKey  privateKeyFromDER(String der) throws IOException 
    { 
     StringReader   reader = new StringReader(der); 
     PEMParser    pemParser = new PEMParser(reader); 

     try 
     { 
      Object o = pemParser.readObject(); 

      if (o == null || !(o instanceof PEMKeyPair)) 
      { 
       throw new IOException("Not an OpenSSL key"); 
      } 

      KeyPair kp = new JcaPEMKeyConverter().setProvider("BC").getKeyPair((PEMKeyPair)o); 
      return kp.getPrivate(); 
     } 
     finally 
     { 
      pemParser.close(); 
     } 
    } 
} 

Die Ausgabe von dem Testprogramm ist:

 
privateKey=EC Private Key 
      S: 13d19928468d14fabb9235a81fc1ec706ff5413a70a760b63e07d45a5d04a2f18425ef735500190291aacaf58c92306acd87fa01a47d907d5d3fc01531180353146 

privateKey.getAlgorithm()=EC 
der=-----BEGIN EC PRIVATE KEY----- 
MIHcAgEBBEIBPRmShGjRT6u5I1qB/B7HBv9UE6cKdgtj4H1FpdBKLxhCXvc1UAGQ 
KRqsr1jJIwas2H+gGkfZB9XT/AFTEYA1MUagBwYFK4EEACOhgYkDgYYABAFN5ZcE 
zg9fV13u57ffwyN9bm9Wa9Pe0MtL2cd5CW2ku4mWzgS5m8IfNMAw2QMah5Z9fuXW 
1fGJgUx1RsC09R6legFTgymlbqt+CaPhNsJkr12cjyzhT1NxR6uEzMUtBcYxqLHy 
ANkhHmvAk221//YIRIWix7ZlRsRrs+iYrpWw4bMt9A== 
-----END EC PRIVATE KEY----- 

recoveredKey=EC Private Key 
      S: 13d19928468d14fabb9235a81fc1ec706ff5413a70a760b63e07d45a5d04a2f18425ef735500190291aacaf58c92306acd87fa01a47d907d5d3fc01531180353146 

recoveredKey.getAlgorithm()=ECDSA 

Key recovery ok 
Key algorithms do not match 

Antwort

5

Das Problem ist nicht die PEMParser aber JcaPEMKeyConverter ist die EG-Schlüssel als Schlüssel behandelt für ECDSA:

algorithms.put(X9ObjectIdentifiers.id_ecPublicKey, "ECDSA"); 
... 
private KeyFactory getKeyFactory(AlgorithmIdentifier algId) 
throws NoSuchAlgorithmException, NoSuchProviderException 
{ 
    ASN1ObjectIdentifier algorithm = algId.getAlgorithm(); 
    String algName = (String)algorithms.get(algorithm); 
... 

Die Kennung des Algorithmus ist id-ecPublicKey, der auch für ECDSA-Schlüssel verwendet wird, daher ist die Auswahl des Algorithmus hier nicht eindeutig und wahrscheinlich haben die BC-Entwickler ECDSA als die am besten geeignete Wahl gewählt. Sie könnten etwas Ähnliches wie JcaPEMKeyConverter mit Ihrem eigenen KeyFactory tun, aber wählen Sie Ihren korrekten Algorithmus für EC-Schlüssel.

Verwandte Themen