Ejemplo n.º 1
0
  private void validateKeys(PublicKey pubKey, PrivateKey privKey) {

    if (pubKey.getAlgorithm() != privKey.getAlgorithm())
      throw new IllegalArgumentException("Public and private key have different algorithms");

    // No encryption for DSA
    if (pubKey.getAlgorithm() != "RSA") return;

    try {

      String data = "ENCRYPT_DATA";
      SecureRandom random = new SecureRandom();
      Cipher cipher = Cipher.getInstance(pubKey.getAlgorithm());
      cipher.init(Cipher.ENCRYPT_MODE, privKey, random);
      byte[] encryptedData = cipher.doFinal(data.getBytes());

      cipher.init(Cipher.DECRYPT_MODE, pubKey, random);
      String decreptedData = new String(cipher.doFinal(encryptedData));
      if (!decreptedData.equals(data)) throw new IllegalArgumentException("Bad public-private key");

    } catch (BadPaddingException e) {
      throw new IllegalArgumentException("Bad public-private key", e);
    } catch (IllegalBlockSizeException e) {
      throw new IllegalArgumentException("Bad public-private key", e);
    } catch (NoSuchPaddingException e) {
      throw new IllegalArgumentException("Bad public-private key", e);
    } catch (InvalidKeyException e) {
      throw new IllegalArgumentException("Invalid public-private key", e);
    } catch (NoSuchAlgorithmException e) {
      throw new IllegalArgumentException("Invalid algorithm for public-private key", e);
    }
  }
Ejemplo n.º 2
0
  /**
   * Creates a test signature and verifies it.
   *
   * @param privateKey Private key to sign with
   * @param publicKey Public key to verify with
   * @param signatureProvider Name of provider to sign with
   * @throws NoSuchAlgorithmException In case the key or signature algorithm is unknown
   * @throws NoSuchProviderException In case the supplied provider name is unknown or BC is not
   *     installed
   * @throws InvalidKeyException If signature verification failed or the key was invalid
   * @throws SignatureException If the signature could not be made or verified correctly
   */
  public static void testSignAndVerify(
      PrivateKey privateKey, PublicKey publicKey, String signatureProvider)
      throws NoSuchAlgorithmException, NoSuchProviderException, InvalidKeyException,
          SignatureException {
    final byte input[] = "Lillan gick pa vagen ut, motte dar en katt...".getBytes();
    final String sigAlg = suggestSigAlg(publicKey);
    if (sigAlg == null) {
      throw new NoSuchAlgorithmException("Unknown key algorithm: " + publicKey.getAlgorithm());
    }
    if (LOG.isDebugEnabled()) {
      LOG.debug("Testing keys with algorithm: " + publicKey.getAlgorithm());
      LOG.debug("testSigAlg: " + sigAlg);
      LOG.debug("provider: " + signatureProvider);
      LOG.trace("privateKey: " + privateKey);
      LOG.trace("privateKey class: " + privateKey.getClass().getName());
      LOG.trace("publicKey: " + publicKey);
      LOG.trace("publicKey class: " + publicKey.getClass().getName());
    }
    final Signature signSignature = Signature.getInstance(sigAlg, signatureProvider);
    signSignature.initSign(privateKey);
    signSignature.update(input);
    byte[] signBA = signSignature.sign();
    if (LOG.isTraceEnabled()) {
      LOG.trace("Created signature of size: " + signBA.length);
      LOG.trace("Created signature: " + new String(Hex.encode(signBA)));
    }

    final Signature verifySignature = Signature.getInstance(sigAlg, "BC");
    verifySignature.initVerify(publicKey);
    verifySignature.update(input);
    if (!verifySignature.verify(signBA)) {
      throw new InvalidKeyException("Test signature inconsistent");
    }
  }
Ejemplo n.º 3
0
  public KeySelectorResult select(
      KeyInfo keyInfo,
      KeySelector.Purpose purpose,
      AlgorithmMethod method,
      XMLCryptoContext context)
      throws KeySelectorException {

    if (keyInfo == null) {
      throw new KeySelectorException("Null KeyInfo object!");
    }
    SignatureMethod sm = (SignatureMethod) method;
    List list = keyInfo.getContent();

    for (int i = 0; i < list.size(); i++) {
      XMLStructure xmlStructure = (XMLStructure) list.get(i);
      if (xmlStructure instanceof KeyValue) {
        PublicKey pk = null;
        try {
          pk = ((KeyValue) xmlStructure).getPublicKey();
        } catch (KeyException ke) {
          throw new KeySelectorException(ke);
        }
        // make sure algorithm is compatible with method
        if (algEquals(sm.getAlgorithm(), pk.getAlgorithm())) {
          curPK = pk;
          //           	System.out.println("Public Key is SOAP: " + getHexString(pk.getEncoded()));
          //            	System.out.println("Public Key is SOAP: " +getHexString(LoadPublicKey("",
          // "RSA").getEncoded()));
          return new SimpleKeySelectorResult(pk);
        }
      }
    }
    throw new KeySelectorException("No KeyValue element found!");
  }
  /**
   * Checks whether the supplied public key matches one of the supplied {@link DEREncodedKeyValue}
   * elements.
   *
   * <p>Matches are performed using Java <code>equals()</code> against {@link PublicKey}s decoded
   * from the KeyInfo data.
   *
   * @param key public key presenter of the assertion
   * @param derEncodedKeyValues candidate DEREncodedKeyValue elements
   * @return true if the public key in the certificate matches one of the DER-encoded key values,
   *     false otherwise
   * @throws AssertionValidationException thrown if there is a problem matching the key value
   */
  protected boolean matchesDEREncodedKeyValue(
      @Nonnull final PublicKey key, @Nullable final List<DEREncodedKeyValue> derEncodedKeyValues) {

    if (derEncodedKeyValues == null || derEncodedKeyValues.isEmpty()) {
      log.debug("KeyInfo contained no DEREncodedKeyValue children");
      return false;
    }

    log.debug(
        "Attempting to match KeyInfo DEREncodedKeyValue to supplied PublicKey param of type: {}",
        key.getAlgorithm());

    for (DEREncodedKeyValue derEncodedKeyValue : derEncodedKeyValues) {
      try {
        PublicKey kiPublicKey = KeyInfoSupport.getKey(derEncodedKeyValue);
        if (Objects.equals(key, kiPublicKey)) {
          log.debug("Matched DEREncodedKeyValue PublicKey");
          return true;
        }
      } catch (KeyException e) {
        log.warn("KeyInfo contained DEREncodedKeyValue that can not be parsed", e);
      }
    }

    log.debug("Failed to match any DEREncodedKeyValue");
    return false;
  }
Ejemplo n.º 5
0
  /**
   * Convert a public key to the SSH format.
   *
   * <p>Note that only RSA keys are supported at the moment.
   *
   * @param key the public key to convert
   * @return an array of bytes that can with the representation of the public key
   */
  public static byte[] getKeyBytes(final PublicKey key) {
    // We only support RSA at the moment:
    if (!(key instanceof RSAPublicKey)) {
      log.error(
          "The key algorithm \"" + key.getAlgorithm() + "\" is not supported, will return null.");
      return null;
    }

    // Extract the bytes of the exponent and the modulus
    // of the key:
    final RSAPublicKey rsaKey = (RSAPublicKey) key;
    final byte[] exponentBytes = rsaKey.getPublicExponent().toByteArray();
    final byte[] modulusBytes = rsaKey.getModulus().toByteArray();
    if (log.isDebugEnabled()) {
      log.debug(
          "Exponent is "
              + rsaKey.getPublicExponent()
              + " ("
              + Hex.encodeHexString(exponentBytes)
              + ").");
      log.debug(
          "Modulus is " + rsaKey.getModulus() + " (" + Hex.encodeHexString(exponentBytes) + ").");
    }

    try {
      // Prepare the stream to write the binary SSH key:
      final ByteArrayOutputStream binaryOut = new ByteArrayOutputStream();
      final DataOutputStream dataOut = new DataOutputStream(binaryOut);

      // Write the SSH header (4 bytes for the length of the algorithm
      // name and then the algorithm name):
      dataOut.writeInt(SSH_RSA.length());
      dataOut.writeBytes(SSH_RSA);

      // Write the exponent and modulus bytes (note that it is not
      // necessary to check if the most significative bit is one, as
      // that will never happen with byte arrays created from big
      // integers, unless they are negative, which is not the case
      // for RSA modulus or exponents):
      dataOut.writeInt(exponentBytes.length);
      dataOut.write(exponentBytes);
      dataOut.writeInt(modulusBytes.length);
      dataOut.write(modulusBytes);

      // Done, extract the bytes:
      binaryOut.close();
      final byte[] keyBytes = binaryOut.toByteArray();
      if (log.isDebugEnabled()) {
        log.debug("Key bytes are " + Hex.encodeHexString(keyBytes) + ".");
      }

      return keyBytes;
    } catch (IOException exception) {
      log.error("Error while serializing public key, will return null.", exception);
      return null;
    }
  }
Ejemplo n.º 6
0
  private static JcaContentSignerBuilder makeContentSignerBuilder(PublicKey issPub) {
    JcaContentSignerBuilder contentSignerBuilder;
    if (issPub instanceof RSAPublicKey) {
      contentSignerBuilder = new JcaContentSignerBuilder("SHA1WithRSA");
    } else if (issPub.getAlgorithm().equals("DSA")) {
      contentSignerBuilder = new JcaContentSignerBuilder("SHA1withDSA");
    } else if (issPub.getAlgorithm().equals("ECDSA")) {
      contentSignerBuilder = new JcaContentSignerBuilder("SHA1withECDSA");
    } else if (issPub.getAlgorithm().equals("ECGOST3410")) {
      contentSignerBuilder = new JcaContentSignerBuilder("GOST3411withECGOST3410");
    } else {
      contentSignerBuilder = new JcaContentSignerBuilder("GOST3411WithGOST3410");
    }

    contentSignerBuilder.setProvider(BouncyCastleProvider.PROVIDER_NAME);

    return contentSignerBuilder;
  }
Ejemplo n.º 7
0
  /**
   * Generate a certificate signing request (PKCS#10).
   *
   * @param info A PKCS10CertReqInfo
   * @param privateKey Private key for signing the request
   * @param signatureProvider Name of provider to sign with
   * @param publicKey Public key to include in the request
   * @param explicitEccParameters True if the EC domain parameters should be included (ie. not a
   *     named curve)
   * @return the certificate request data
   */
  public static ICertReqData genCertificateRequest(
      ISignerCertReqInfo info,
      final PrivateKey privateKey,
      final String signatureProvider,
      PublicKey publicKey,
      final boolean explicitEccParameters)
      throws IllegalArgumentException {
    LOG.debug(">genCertificateRequest");
    final Base64SignerCertReqData retval;
    if (info instanceof PKCS10CertReqInfo) {
      PKCS10CertReqInfo reqInfo = (PKCS10CertReqInfo) info;
      PKCS10CertificationRequest pkcs10;

      if (LOG.isDebugEnabled()) {
        LOG.debug("signatureAlgorithm: " + reqInfo.getSignatureAlgorithm());
        LOG.debug("subjectDN: " + reqInfo.getSubjectDN());
        LOG.debug("explicitEccParameters: " + explicitEccParameters);
      }

      try {
        // Handle ECDSA key with explicit parameters
        if (explicitEccParameters && publicKey.getAlgorithm().contains("EC")) {
          publicKey = ECKeyUtil.publicToExplicitParameters(publicKey, "BC");
        }

        if (LOG.isDebugEnabled()) {
          LOG.debug("Public key SHA1: " + createKeyHash(publicKey));
          LOG.debug("Public key SHA256: " + KeyUsageCounterHash.create(publicKey));
        }

        // Generate request
        final JcaPKCS10CertificationRequestBuilder builder =
            new JcaPKCS10CertificationRequestBuilder(
                new X500Name(CertTools.stringToBCDNString(reqInfo.getSubjectDN())), publicKey);
        final ContentSigner contentSigner =
            new JcaContentSignerBuilder(reqInfo.getSignatureAlgorithm())
                .setProvider(signatureProvider)
                .build(privateKey);
        pkcs10 = builder.build(contentSigner);
        retval = new Base64SignerCertReqData(Base64.encode(pkcs10.getEncoded()));
      } catch (IOException e) {
        throw new IllegalArgumentException("Certificate request error: " + e.getMessage(), e);
      } catch (OperatorCreationException e) {
        throw new IllegalArgumentException("Certificate request error: " + e.getMessage(), e);
      } catch (NoSuchAlgorithmException e) {
        throw new IllegalArgumentException("Certificate request error: " + e.getMessage(), e);
      } catch (NoSuchProviderException e) {
        throw new IllegalArgumentException("Certificate request error: " + e.getMessage(), e);
      }
      LOG.debug("<genCertificateRequest");
      return retval;
    } else {
      throw new IllegalArgumentException(
          "Unsupported certificate request info type: " + info.getClass().getName());
    }
  }
Ejemplo n.º 8
0
 /**
  * Creates a new content verifier using default algorithm.
  *
  * @param key the private key
  * @return a new content verifier
  * @throws OperatorCreationException if the content signer cannot be created
  */
 public static ContentVerifierProvider createDefaultContentVerifier(PublicKey key)
     throws OperatorCreationException {
   if ("RSA" == key.getAlgorithm()) {
     // SunRsaSign supports only RSA signatures but it is (for some reason) about 2x faster
     // than the BC implementation
     return SUN_VERIFICATION_BUILDER.build(key);
   } else {
     return BC_VERIFICATION_BUILDER.build(key);
   }
 }
Ejemplo n.º 9
0
 public KeyValue newKeyValue(PublicKey key) throws KeyException {
   String algorithm = key.getAlgorithm();
   if (algorithm.equals("DSA")) {
     return new DOMKeyValue.DSA(key);
   } else if (algorithm.equals("RSA")) {
     return new DOMKeyValue.RSA(key);
   } else if (algorithm.equals("EC")) {
     return new DOMKeyValue.EC(key);
   } else {
     throw new KeyException("unsupported key algorithm: " + algorithm);
   }
 }
  /**
   * Creates new encrypted credentials
   *
   * <p>Encrypts the message '<code>login</code>:<code>password</code>' using the public key <code>
   * pubKey</code> and <code>cipher</code> and store it in a new Credentials object.
   *
   * @see KeyPairUtil#encrypt(String, String, String, byte[])
   * @param login the login to encrypt
   * @param password the corresponding password to encrypt
   * @param pubKey public key used for encryption
   * @param cipher cipher parameters: combination of transformations
   * @return the Credentials object containing the encrypted data
   * @throws KeyException key generation or encryption failed
   */
  @Deprecated
  public static Credentials createCredentials(
      String login, String password, byte[] datakey, PublicKey pubKey, String cipher)
      throws KeyException {

    CredData cc = new CredData();
    cc.setLogin(CredData.parseLogin(login));
    cc.setDomain(CredData.parseDomain(login));
    cc.setPassword(password);
    cc.setKey(datakey);

    // serialize clear credentials to byte array
    byte[] clearCred = null;
    try {
      clearCred = ObjectToByteConverter.ObjectStream.convert(cc);
    } catch (IOException e1) {
      throw new KeyException(e1.getMessage());
    }

    int size = -1;
    if (pubKey instanceof java.security.interfaces.RSAPublicKey) {
      size = ((RSAPublicKey) pubKey).getModulus().bitLength();
    } else if (pubKey instanceof java.security.interfaces.DSAPublicKey) {
      size = ((DSAPublicKey) pubKey).getParams().getP().bitLength();
    } else if (pubKey instanceof javax.crypto.interfaces.DHPublicKey) {
      size = ((DHPublicKey) pubKey).getParams().getP().bitLength();
    }

    // generate symmetric key
    SecretKey aesKey = KeyUtil.generateKey(AES_ALGO, AES_KEYSIZE);

    byte[] encData = null;
    byte[] encAes = null;

    // encrypt AES key with public RSA key
    try {
      encAes = KeyPairUtil.encrypt(pubKey, size, cipher, aesKey.getEncoded());
    } catch (KeyException e) {
      throw new KeyException("Symmetric key encryption failed", e);
    }

    // encrypt clear credentials with AES key
    try {
      encData = KeyUtil.encrypt(aesKey, AES_CIPHER, clearCred);
    } catch (KeyException e) {
      throw new KeyException("Message encryption failed", e);
    }

    Credentials cred = new Credentials(pubKey.getAlgorithm(), size, cipher, encAes, encData);
    return cred;
  }
Ejemplo n.º 11
0
 public void putRawPublicKey(PublicKey key) {
   if (key instanceof RSAPublicKey) {
     putString(KeyPairProvider.SSH_RSA);
     putMPInt(((RSAPublicKey) key).getPublicExponent());
     putMPInt(((RSAPublicKey) key).getModulus());
   } else if (key instanceof DSAPublicKey) {
     putString(KeyPairProvider.SSH_DSS);
     putMPInt(((DSAPublicKey) key).getParams().getP());
     putMPInt(((DSAPublicKey) key).getParams().getQ());
     putMPInt(((DSAPublicKey) key).getParams().getG());
     putMPInt(((DSAPublicKey) key).getY());
   } else {
     throw new IllegalStateException("Unsupported algorithm: " + key.getAlgorithm());
   }
 }
Ejemplo n.º 12
0
  private void parseCertificate() throws CertificateException, KeyczarException {
    Certificate certificate =
        CertificateFactory.getInstance("X.509").generateCertificate(certificateStream);
    PublicKey publicKey = certificate.getPublicKey();

    if (publicKey instanceof RSAPublicKey) {
      key = readRsaX509Certificate(publicKey, padding);
    } else if (publicKey instanceof DSAPublicKey) {
      if (padding != null) {
        throw new KeyczarException(Messages.getString("InvalidPadding", padding.name()));
      }
      key = readDsaX509Certificate(publicKey);
    } else {
      throw new KeyczarException(
          "Unrecognized key type " + publicKey.getAlgorithm() + " in certificate");
    }
  }
Ejemplo n.º 13
0
  /**
   * Verify the signature value computed over the supplied input against the supplied signature
   * value.
   *
   * <p>It is up to the caller to ensure that the specified algorithm ID is consistent with the type
   * of verification key supplied.
   *
   * @param verificationKey the key with which to compute and verify the signature
   * @param jcaAlgorithmID the Java JCA algorithm ID to use
   * @param signature the computed signature value received from the signer
   * @param input the input over which the signature is computed and verified
   * @return true if the signature value computed over the input using the supplied key and
   *     algorithm ID is identical to the supplied signature value
   * @throws SecurityException thrown if the signature computation or verification process results
   *     in an error
   */
  public static boolean verify(
      PublicKey verificationKey, String jcaAlgorithmID, byte[] signature, byte[] input)
      throws SecurityException {

    log.debug(
        "Verifying signature over input using public key of type {} and JCA algorithm ID {}",
        verificationKey.getAlgorithm(),
        jcaAlgorithmID);

    try {
      Signature sig = Signature.getInstance(jcaAlgorithmID);
      sig.initVerify(verificationKey);
      sig.update(input);
      return sig.verify(signature);
    } catch (GeneralSecurityException e) {
      log.error("Error during signature verification", e);
      throw new SecurityException("Error during signature verification", e);
    }
  }
 public String toString() {
   StringWriter str = new StringWriter();
   PrintWriter out = new PrintWriter(str);
   out.println(X509CertificateImpl.class.getName() + " {");
   out.println("  TBSCertificate {");
   out.println("    version = " + version + ";");
   out.println("    serialNo = " + serialNo + ";");
   out.println("    signature = {");
   out.println("      algorithm = " + getSigAlgName() + ";");
   out.print("      parameters =");
   if (sigAlgVal != null) {
     out.println();
     out.print(Util.hexDump(sigAlgVal, "        "));
   } else {
     out.println(" null;");
   }
   out.println("    }");
   out.println("    issuer = " + issuer.getName() + ";");
   out.println("    validity = {");
   out.println("      notBefore = " + notBefore + ";");
   out.println("      notAfter  = " + notAfter + ";");
   out.println("    }");
   out.println("    subject = " + subject.getName() + ";");
   out.println("    subjectPublicKeyInfo = {");
   out.println("      algorithm = " + subjectKey.getAlgorithm());
   out.println("      key =");
   out.print(Util.hexDump(subjectKey.getEncoded(), "        "));
   out.println("    };");
   out.println("    issuerUniqueId  = " + issuerUniqueId + ";");
   out.println("    subjectUniqueId = " + subjectUniqueId + ";");
   out.println("    extensions = {");
   for (Iterator it = extensions.values().iterator(); it.hasNext(); ) {
     out.println("      " + it.next());
   }
   out.println("    }");
   out.println("  }");
   out.println("  signatureAlgorithm = " + getSigAlgName() + ";");
   out.println("  signatureValue =");
   out.print(Util.hexDump(signature, "    "));
   out.println("}");
   return str.toString();
 }
Ejemplo n.º 15
0
  @Override
  public KeySelectorResult select(
      final KeyInfo ki, final Purpose p, final AlgorithmMethod m, final XMLCryptoContext c)
      throws KeySelectorException {

    if (ki == null) throw new KeySelectorException("KeyInfo is null");

    final SignatureMethod sm = (SignatureMethod) m;
    @SuppressWarnings("unchecked")
    final List<Object> list = ki.getContent();

    for (final Object l : list) {
      final XMLStructure s = (XMLStructure) l;
      PublicKey pk = null;
      if (s instanceof KeyValue) {
        try {
          pk = ((KeyValue) s).getPublicKey();
        } catch (final KeyException ke) {
          throw new KeySelectorException(ke);
        }

      } else if (s instanceof X509Data) {
        for (final Object d : ((X509Data) s).getContent()) {
          if (d instanceof X509Certificate) {
            pk = ((Certificate) d).getPublicKey();
          }
        }
      }

      if (pk != null) {
        final String sa = sm.getAlgorithm();
        final String ka = pk.getAlgorithm();
        if ("DSA".equalsIgnoreCase(ka) && "http://www.w3.org/2000/09/xmldsig#dsa-sha1".equals(sa)
            || "RSA".equalsIgnoreCase(ka)
                && "http://www.w3.org/2000/09/xmldsig#rsa-sha1".equals(sa)) {
          return new MyKeySelectorResult(pk);
        }
      }
    }

    throw new KeySelectorException("No KeyValue element found");
  }
Ejemplo n.º 16
0
  /**
   * Encodes a public key data the same way as the {@link #parsePublicKeyEntry(String)} expects it
   *
   * @param <A> The generic appendable class
   * @param sb The {@link Appendable} instance to encode the data into
   * @param key The {@link PublicKey} - ignored if {@code null}
   * @return The updated appendable instance
   * @throws IOException If failed to append the data
   */
  public static <A extends Appendable> A appendPublicKeyEntry(A sb, PublicKey key)
      throws IOException {
    if (key == null) {
      return sb;
    }

    @SuppressWarnings("unchecked")
    PublicKeyEntryDecoder<PublicKey, ?> decoder =
        (PublicKeyEntryDecoder<PublicKey, ?>) KeyUtils.getPublicKeyEntryDecoder(key);
    if (decoder == null) {
      throw new StreamCorruptedException("Cannot retrieve decoder for key=" + key.getAlgorithm());
    }

    try (ByteArrayOutputStream s = new ByteArrayOutputStream(Byte.MAX_VALUE)) {
      String keyType = decoder.encodePublicKey(s, key);
      byte[] bytes = s.toByteArray();
      String b64Data = Base64.encodeToString(bytes);
      sb.append(keyType).append(' ').append(b64Data);
    }

    return sb;
  }
Ejemplo n.º 17
0
    @JRubyMethod(name = "read", meta = true, required = 1, optional = 1)
    public static IRubyObject read(
        final ThreadContext context, IRubyObject recv, IRubyObject[] args) {
      final Ruby runtime = context.runtime;

      final IRubyObject data;
      final char[] pass;
      switch (args.length) {
        case 1:
          data = args[0];
          pass = null;
          break;
        default:
          data = args[0];
          pass = args[1].isNil() ? null : args[1].toString().toCharArray();
      }

      final byte[] input = OpenSSLImpl.readX509PEM(context, data);
      KeyPair key = null;
      // d2i_PrivateKey_bio
      try {
        key = readPrivateKey(input);
      } catch (IOException ioe) {
        // ignore
      } catch (GeneralSecurityException gse) {
        // ignore
      }
      // PEM_read_bio_PrivateKey
      if (key == null) {
        try {
          key =
              PEMInputOutput.readPrivateKey(
                  new InputStreamReader(new ByteArrayInputStream(input)), pass);
        } catch (IOException ioe) {
          // ignore
        }
      }
      if (key != null) {
        if (key.getPublic().getAlgorithm().equals("RSA")) {
          return new PKeyRSA(
              runtime,
              _PKey(runtime).getClass("RSA"),
              (RSAPrivateCrtKey) key.getPrivate(),
              (RSAPublicKey) key.getPublic());
        } else if (key.getPublic().getAlgorithm().equals("DSA")) {
          return new PKeyDSA(
              runtime,
              _PKey(runtime).getClass("DSA"),
              (DSAPrivateKey) key.getPrivate(),
              (DSAPublicKey) key.getPublic());
        }
      }

      PublicKey pubKey = null;
      // d2i_PUBKEY_bio
      try {
        pubKey = readPublicKey(input);
      } catch (IOException ioe) {
        // ignore
      } catch (GeneralSecurityException gse) {
        // ignore
      }
      // PEM_read_bio_PUBKEY
      if (pubKey == null) {
        try {
          pubKey =
              PEMInputOutput.readPubKey(new InputStreamReader(new ByteArrayInputStream(input)));
        } catch (IOException ioe) {
          // ignore
        }
      }

      if (pubKey != null) {
        if (pubKey.getAlgorithm().equals("RSA")) {
          return new PKeyRSA(runtime, _PKey(runtime).getClass("RSA"), (RSAPublicKey) pubKey);
        } else if (key.getPublic().getAlgorithm().equals("DSA")) {
          return new PKeyDSA(runtime, _PKey(runtime).getClass("DSA"), (DSAPublicKey) pubKey);
        }
      }

      throw runtime.newArgumentError("Could not parse PKey");
    }