weizhouapache commented on code in PR #11468: URL: https://github.com/apache/cloudstack/pull/11468#discussion_r2291195205
########## server/src/main/java/org/apache/cloudstack/network/ssl/CertServiceImpl.java: ########## @@ -423,19 +432,47 @@ private void validateChain(final List<Certificate> chain, final Certificate cert } - public PrivateKey parsePrivateKey(final String key) throws IOException { + public PrivateKey parsePrivateKey(final String key, String password) throws IOException, OperatorCreationException, PKCSException, NoSuchAlgorithmException, InvalidKeySpecException { Preconditions.checkArgument(StringUtils.isNotEmpty(key)); - try (final PemReader pemReader = new PemReader(new StringReader(key));) { - final PemObject pemObject = pemReader.readPemObject(); - final byte[] content = pemObject.getContent(); - final PKCS8EncodedKeySpec privKeySpec = new PKCS8EncodedKeySpec(content); - final KeyFactory factory = KeyFactory.getInstance("RSA", "BC"); - return factory.generatePrivate(privKeySpec); - } catch (NoSuchAlgorithmException | NoSuchProviderException e) { - throw new IOException("No encryption provider available.", e); - } catch (final InvalidKeySpecException e) { - throw new IOException("Invalid Key format.", e); + PEMParser pemParser = new PEMParser(new StringReader(key)); + Object privateKeyObj = pemParser.readObject(); + if (privateKeyObj == null) { + throw new CloudRuntimeException("Cannot parse private key"); + } + PrivateKey privateKey; + if (privateKeyObj instanceof PKCS8EncryptedPrivateKeyInfo) { + if (password == null) { + throw new CloudRuntimeException("Key is encrypted by PKCS#8 but password is null"); + } + PKCS8EncryptedPrivateKeyInfo encryptedPrivateKeyInfo = (PKCS8EncryptedPrivateKeyInfo)privateKeyObj; + JceOpenSSLPKCS8DecryptorProviderBuilder builder = new JceOpenSSLPKCS8DecryptorProviderBuilder(); + InputDecryptorProvider decryptor = builder.build(password.toCharArray()); + + PrivateKeyInfo privateKeyInfo = encryptedPrivateKeyInfo.decryptPrivateKeyInfo(decryptor); + String algorithm = privateKeyInfo.getPrivateKeyAlgorithm().getAlgorithm().getId(); + KeyFactory keyFactory = KeyFactory.getInstance(algorithm); + PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(privateKeyInfo.getEncoded()); + return keyFactory.generatePrivate(keySpec); + } else if (privateKeyObj instanceof PEMEncryptedKeyPair) { + if (password == null) { + throw new CloudRuntimeException("Key is encrypted but password is null"); + } + PEMEncryptedKeyPair encryptedKeyPair = (PEMEncryptedKeyPair)privateKeyObj; + privateKey = new JcaPEMKeyConverter().getKeyPair( + encryptedKeyPair.decryptKeyPair(new JcePEMDecryptorProviderBuilder().build(password.toCharArray()))).getPrivate(); + } else if (privateKeyObj instanceof PEMKeyPair) { + // Key pair + PEMKeyPair pemKeyPair = (PEMKeyPair) privateKeyObj; + privateKey = new JcaPEMKeyConverter().getKeyPair(pemKeyPair).getPrivate(); + } else if (privateKeyObj instanceof PrivateKeyInfo) { + // Private key only + PrivateKeyInfo privateKeyInfo = (PrivateKeyInfo) privateKeyObj; + privateKey = new JcaPEMKeyConverter().getPrivateKey(privateKeyInfo); + } else { + throw new IllegalArgumentException("Unsupported PEM object: " + privateKeyObj.getClass()); } Review Comment: chatgpt says ``` To get the runtime type: obj.getClass() → works in Java 17 and 21. ``` I guess it is ok ? -- This is an automated message from the Apache Git Service. To respond to the message, please log on to GitHub and use the URL above to go to the specific comment. To unsubscribe, e-mail: commits-unsubscr...@cloudstack.apache.org For queries about this service, please contact Infrastructure at: us...@infra.apache.org