Estoy tratando de leer una clave privada PKCS#8 que tiene el siguiente aspecto:
key.k8 --> (Clave de muestra. Frase de contraseña - 123456):
-----BEGIN ENCRYPTED PRIVATE KEY----- MIIFLTBXBgkqhkiG9w0BBQ0wSjApBgkqhkiG9w0BBQwwHAQILbKY9hPxYSoCAggA MAwGCCqGSIb3DQIJBQAwHQYJYIZIAWUDBAEqBBCvaGt2Hmm2NpHpxbLvHKyOBIIE 0IQ7dVrAGXLZl0exYIvyxLAu6zO00jL6b3sb/agTcCFOz8JU6fBanxY0d5aYO4Dn mynQG7BoljU470s0zIwW/wk0MmdUFl4nXWBX/4qnG0sZqZ9KZ7I8R/WrBkmpX8C/ 4pjdVhu8Ht8dfOYbkbjMBTohDJz8vJ0QwDIXi9yFjjef+QjwrFOl6kAeDJFVMGqc s7K/wOnhsL1XxfW9uTulPiZh5YTZKcatMkeGDR7c+cg5I+Mutim92diWuCekhNoa uvhUy1M3cbs7Azp1Mhz+V0CDKklI95EvN4u23WhiJPCjAofC/e45/heOP3Dwm7WZ zHEY1C/X8PsTl6MEEIF3ZJP+4Vr0corAs1L2FqE6oOng8dFFYmF5eRyBx6bxFd05 iYbfOH24/b3qtFKPC689kGEd0gWp1dwES35SNNK+cJqVRTjgI0oKhOai3rhbGnmp tx4+JqploQgTorj4w9asbtZ/qZA2mYSSR/Q64SHv7LfoUCI9bgx73MqRQBgvI5yS b4BoFBnuEgOduZLaGKGjKVW3m5/q8oiDAaspcSLCJMIrdOTYWJB+7mfxX4Xy0vEe 5m2jXpSLQmrfjgpSTpHDKi/3b6OzKOcHjSFBf8IoiHuLc5DVvLECzDUxxaMrTZ71 0YXvEPwl2R9BzEANwwR9ghJvFg1Be/d5W/WA1Efe6cNQNBlmErxD6l+4KDUgGjTr Aaksp9SZAv8uQAsg7C57NFHpTA5Hznr5JctL+WlO+Gk0cAV6i4Py3kA6EcfatsnS PqP2KbxT+rb2ATMUZqgWc20QvDt6j0CTA1BuVD1PNhnAUFvb2ocyEEXOra22DPPS UPu6jirSIyFcjqFjJ9A1FD9L4/UuX2UkDSLqblFlYB1+G55KZp+EKz8SZoN5qXy1 LyMtnacEP5OtRDrOjopzVNiuV1Uv63M9QVi1hZlVLJEomgjWuvuyEuIwDaY2uryW vx+jJEZyySFkb1JwAbrm+p6sCTFnbQ/URKC2cit/FJyKqNim6VQvGL8Sez34qV3z D13QJgTZfsy+BaZoaQ6cJTXtJ8cN0IcQciOiDNBKMW66zO6ujS8G+KNviNQypDm6 h4sOgjMqLaZ4ezPEdNj/gaxV7Y15nVRu0re8dVkaa5t9ft/sh6A+yeTD5tS5hHkf NI7uJPTaTXVoz7xq2PAJUTWujMLMZKtmNOzNqYvxWRy3tCOFobBQkMxqEBEwHd+x SA+gFcJKJ+aNfCGZJ5fFr8rNlhtOF6uMwOAlfiUlP/pCUDUCKPjZVj4K95yNc8Io jSZSPb5tGPe0HqXgc6IAfQarlUZt90oVtzL0OfOfTxe1bEzS2ccNadbx/6vjLBc4 q5UuUBppl3rXpbuZ7J1Rp3n2byF4APxFdT2LHKq+MYMfWUToau/TCMT4lFIM9tM8 7TuuyUT2PKzf/xlsl4iScw96z9xxGPQrXn7IA2W5iL+0eCLztJdjNRX1FisdfIBL PraOVlmF8jHKbFdRZ8Yi8pApbQjvHi24g7dX7u/cq1FH/VE+nJ0O8YVCYVDw13CW h0p7yD7BuB0R+0WnR0yvkp30vK4/rtCB+Ob8bH/+HvAZrAU5X8jq/wsQbLkrLHZV 6A6GGfX8+hy5AoaXsH1BHnMyXkaF6Mv29z8JcslDJxX/ -----END ENCRYPTED PRIVATE KEY-----
El siguiente código se está utilizando para analizar la clave privada:
InputStream privateKeyInputStream = getPrivateKeyInputStream(); // reads the key file from classpath and share as DataStream logger.info("InputStreamExists --> {} ", privateKeyInputStream.available()); PEMParser pemParser = new PEMParser(new InputStreamReader(privateKeyInputStream)); Object pemObject = pemParser.readObject(); if (pemObject instanceof PKCS8EncryptedPrivateKeyInfo) { // Handle the case where the private key is encrypted. PKCS8EncryptedPrivateKeyInfo encryptedPrivateKeyInfo = (PKCS8EncryptedPrivateKeyInfo) pemObject; InputDecryptorProvider pkcs8Prov = new JceOpenSSLPKCS8DecryptorProviderBuilder().build(passphrase.toCharArray()); privateKeyInfo = encryptedPrivateKeyInfo.decryptPrivateKeyInfo(pkcs8Prov); // fails here }
InputStream resourceAsStream = null; if ("local".equals(privateKeyMode)) { resourceAsStream = this.getClass().getResourceAsStream(privateKeyPath); } else { File keyFile = new File(privateKeyPath); logger.info( "Key file found in {} mode. FileName : {}, Exists : {}", privateKeyMode, keyFile.getName(), keyFile.exists()); try { resourceAsStream = new DataInputStream(new FileInputStream(keyFile)); } catch (FileNotFoundException e) { e.printStackTrace(); }
Cuando ejecuto este código a través de intelliJ en Windows, el código funciona bien, pero cuando lo ejecuto a través del contenedor docker obtengo la siguiente excepción:
org.bouncycastle.pkcs.PKCSException: unable to read encrypted data: failed to construct sequence from byte[]: Extra data detected in stream snowflake-report-sync | at org.bouncycastle.pkcs.PKCS8EncryptedPrivateKeyInfo.decryptPrivateKeyInfo(Unknown Source) ~[bcpkix-jdk15on-1.64.jar!/:1.64.00.0] snowflake-report-sync | at com.optum.snowflakereportsync.configuration.SnowFlakeConfig.getPrivateKey(SnowFlakeConfig.java:103) ~[classes!/:na] snowflake-report-sync | at com.optum.snowflakereportsync.configuration.SnowFlakeConfig.getConnectionProperties(SnowFlakeConfig.java:67) ~[classes!/:na]
A continuación se utiliza Dockerfile:
FROM adoptopenjdk/openjdk11-openj9:latest COPY build/libs/snowflake-report-sync-*.jar snowflake-report-sync.jar RUN mkdir /encryption-keys COPY encryption-keys/ /encryption-keys/ #keys are picked from docker filesystem when running in container EXPOSE 8080 CMD java -Dcom.sun.management.jmxremote -noverify ${JAVA_OPTS} -jar snowflake-report-sync.jar
Opciones probadas:
No estoy seguro de lo que estoy haciendo mal, pero cualquier ayuda o sugerencia sería apreciada.
Editar:
Pensándolo bien, al crear JceOpenSSLPKCS8DecryptorProviderBuilder
, no está especificando explícitamente el proveedor:
new JceOpenSSLPKCS8DecryptorProviderBuilder() .setProvider(BouncyCastleProvider.PROVIDER_NAME) // add this line .build(passphrase.toCharArray());
Parece que OpenJ9 usa un mecanismo de selección de proveedor/algo diferente y selecciona la clase SunJCE
de AESCipher
como CipherSpi de forma predeterminada, mientras que Hotspot selecciona la clase AES
de BouncyCastleProvider
.
Especificar explícitamente el proveedor debería funcionar en todos los casos.
Alternativamente, al agregar BouncyCastleProvider
, puede insertarlo en la primera posición preferida (es decir Security.insertProviderAt(new BouncyCastleProvider(), 1)
en lugar de Security.addProvider(new BouncyCastleProvider())
) para que se seleccione.
(Todavía no me queda claro por qué el mecanismo de selección de proveedores difiere entre las diferentes JVM).
Publicación original:
Logré reproducir el problema y, en este punto, diría que es un problema de incompatibilidad con OpenJ9 JVM.
A partir de una imagen base de Hotspot en su lugar, por ejemplo
FROM adoptopenjdk:11-jre-hotspot
hace que el código funcione.
(Aún no estoy completamente seguro de si la falla radica en la imagen de Docker, OpenJ9 JVM o BouncyCastle)