title: EC private key recovery from PEM format with BouncyCastle
body: <p>My application stores private keys in PEM format, the existing code works for RSA keys but I am trying to switch to EC keys and there is a problem. The key recovery seems to work, and the equals method on the recovered key returns true for the original key, but getAlgorithm() on the original key returns "EC" and on the recovered key "ECDSA". The discrepancy in the algorithm later causes problems because it does not match the algorithm for the corresponding public key.</p>
  
  <p>Am I doing something wrong or is this a bug in the PEM parser?</p>
  
  <p>Here is a test program which demonstrates the problem:</p>
  
  <pre><code>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();
          }
      }
  }
  </code></pre>
  
  <p>The output from the test program is:</p>
  
  <pre>
  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
  </pre>