/** Read a Key Pair */
  private static KeyPair readKeyPair(
      BufferedReader _in, char[] passwd, String type, String endMarker) throws Exception {
    boolean isEncrypted = false;
    String line = null;
    String dekInfo = null;
    StringBuffer buf = new StringBuffer();

    while ((line = _in.readLine()) != null) {
      if (line.startsWith("Proc-Type: 4,ENCRYPTED")) {
        isEncrypted = true;
      } else if (line.startsWith("DEK-Info:")) {
        dekInfo = line.substring(10);
      } else if (line.indexOf(endMarker) != -1) {
        break;
      } else {
        buf.append(line.trim());
      }
    }
    byte[] keyBytes = null;
    byte[] decoded = Base64.decode(buf.toString());
    if (isEncrypted) {
      keyBytes = decrypt(decoded, dekInfo, passwd);
    } else {
      keyBytes = decoded;
    }
    return org.jruby.ext.openssl.impl.PKey.readPrivateKey(keyBytes, type);
  }
 /** c: PEM_read_PrivateKey + PEM_read_bio_PrivateKey CAUTION: KeyPair#getPublic() may be null. */
 public static KeyPair readPrivateKey(Reader in, char[] password) throws IOException {
   BufferedReader _in = makeBuffered(in);
   String line;
   while ((line = _in.readLine()) != null) {
     if (line.indexOf(BEF_G + PEM_STRING_RSA) != -1) {
       try {
         return readKeyPair(_in, password, "RSA", BEF_E + PEM_STRING_RSA);
       } catch (Exception e) {
         throw new IOException("problem creating RSA private key: " + e.toString());
       }
     } else if (line.indexOf(BEF_G + PEM_STRING_DSA) != -1) {
       try {
         return readKeyPair(_in, password, "DSA", BEF_E + PEM_STRING_DSA);
       } catch (Exception e) {
         throw new IOException("problem creating DSA private key: " + e.toString());
       }
     } else if (line.indexOf(BEF_G + PEM_STRING_ECPRIVATEKEY) != -1) {
       throw new IOException("EC private key not supported");
     } else if (line.indexOf(BEF_G + PEM_STRING_PKCS8INF) != -1) {
       try {
         byte[] bytes = readBytes(_in, BEF_E + PEM_STRING_PKCS8INF);
         PrivateKeyInfo info =
             new PrivateKeyInfo((ASN1Sequence) new ASN1InputStream(bytes).readObject());
         String type = getPrivateKeyTypeFromObjectId(info.getAlgorithmId().getObjectId());
         return org.jruby.ext.openssl.impl.PKey.readPrivateKey(
             info.getPrivateKey().getDEREncoded(), type);
       } catch (Exception e) {
         throw new IOException("problem creating private key: " + e.toString());
       }
     } else if (line.indexOf(BEF_G + PEM_STRING_PKCS8) != -1) {
       try {
         byte[] bytes = readBytes(_in, BEF_E + PEM_STRING_PKCS8);
         org.bouncycastle.asn1.pkcs.EncryptedPrivateKeyInfo eIn =
             new org.bouncycastle.asn1.pkcs.EncryptedPrivateKeyInfo(
                 (ASN1Sequence) new ASN1InputStream(bytes).readObject());
         AlgorithmIdentifier algId = eIn.getEncryptionAlgorithm();
         PrivateKey privKey;
         if (algId.getAlgorithm().toString().equals("1.2.840.113549.1.5.13")) { // PBES2
           privKey = derivePrivateKeyPBES2(eIn, algId, password);
         } else {
           privKey = derivePrivateKeyPBES1(eIn, algId, password);
         }
         return new KeyPair(null, privKey);
       } catch (Exception e) {
         throw new IOException("problem creating private key: " + e.toString());
       }
     }
   }
   return null;
 }