While trying to decrypt encrypted RSA private keys with java runtime is set with property
-Dorg.bouncycastle.fips.approved_only=true is throwing below error
unable to read encrypted data: 1.2.840.113549.1.5.3 not available: requires PBE parameters
Tpl required
bc-fips-1.0.1.jar
bcpkix-fips-1.0.3.jar
Sample code
import java.io.FileReader;
import java.nio.file.Paths;
import java.security.PrivateKey;
import java.security.Security;
import org.bouncycastle.asn1.pkcs.PrivateKeyInfo;
import org.bouncycastle.jcajce.provider.BouncyCastleFipsProvider;
import org.bouncycastle.openssl.PEMParser;
import org.bouncycastle.openssl.jcajce.JcaPEMKeyConverter;
import org.bouncycastle.openssl.jcajce.JceOpenSSLPKCS8DecryptorProviderBuilder;
import org.bouncycastle.operator.InputDecryptorProvider;
import org.bouncycastle.pkcs.PKCS8EncryptedPrivateKeyInfo;
public class TestJdbcEncryptedKey {
// Path to the private key file that you generated earlier.
private static final String PRIVATE_KEY_FILE = "D:\\snowflake\\keypair\\fips\\encrypted\\rsa_key.p8";
public static class PrivateKeyReader {
// If you generated an encrypted private key, implement this method to return
// the passphrase for decrypting your private key.
private static String getPrivateKeyPassphrase() {
return "rks123";
}
public static PrivateKey get(String filename) throws Exception {
String BOUNCY_CASTLE_RNG_HYBRID_MODE = "C:HYBRID;ENABLE{All};";
String JCE_PROVIDER_BOUNCY_CASTLE_FIPS = "BCFIPS";
BouncyCastleFipsProvider bcFipsProvider = new BouncyCastleFipsProvider(BOUNCY_CASTLE_RNG_HYBRID_MODE);
PrivateKeyInfo privateKeyInfo = null;
// Security.removeProvider(JCE_PROVIDER_BOUNCY_CASTLE_FIPS);
Security.insertProviderAt(bcFipsProvider, 1);
// Read an object from the private key file.
PEMParser pemParser = new PEMParser(new FileReader(Paths.get(filename).toFile()));
Object pemObject = pemParser.readObject();
if (pemObject instanceof PKCS8EncryptedPrivateKeyInfo) {
// Handle the case where the private key is encrypted.
PKCS8EncryptedPrivateKeyInfo encryptedPrivateKeyInfo = (PKCS8EncryptedPrivateKeyInfo) pemObject;
String passphrase = getPrivateKeyPassphrase();
InputDecryptorProvider pkcs8Prov = new JceOpenSSLPKCS8DecryptorProviderBuilder()
.build(passphrase.toCharArray());
privateKeyInfo = encryptedPrivateKeyInfo.decryptPrivateKeyInfo(pkcs8Prov);
} else if (pemObject instanceof PrivateKeyInfo) {
// Handle the case where the private key is unencrypted.
privateKeyInfo = (PrivateKeyInfo) pemObject;
}
pemParser.close();
JcaPEMKeyConverter converter = new JcaPEMKeyConverter().setProvider(BouncyCastleFipsProvider.PROVIDER_NAME);
return converter.getPrivateKey(privateKeyInfo);
}
}
public static void main(String[] args) throws Exception {
PrivateKey privateKey = PrivateKeyReader.get(PRIVATE_KEY_FILE);
}
}
1.2.840.113549.1.5.3 is PBEwithMD5andDES-CBC, one of the PBES1 schemes in PKCS5. MD5 is not NIST-approved and cannot generally be used in FIPS mode (there are some specific exceptions like the TLS1.0-1 PRF). (Single/classic) DES was NIST-approved but withdrawn in the early oughties, and anyway it's completely broken.
I'm going to guess you or someone created this PKCS8 with openssl pkcs8 -topk8
in an older version -- it defaulted to this scheme, which was barely reasonable when OpenSSL (then SSLeay) was created in the 1990s but retained past its sell-by date. 1.1.0 (released 2016) up changes the default to PBES2 with hmac-sha256 and aes-256-cbc, and in lower versions you can specify -v2 aes-256-cbc
for PBES2 (but hmac-sha1 for the PRF, which TTBOMK is still FIPS and actually secure even though sha1 signatures or at least certificates are broken and generally prohibited since about 2015).
BouncyCastle can read (and decrypt) PBES2 correctly since more or less forever, but the standard providers in Java versions below 11.0.1 mishandle all PBES2, and even after that they don't handle all cases. If these are concerns, -v1 PBE-SHA1-3DES
(which is actually a PKCS12 scheme not PKCS5v1, but OpenSSL lumps them together) should be good for FIPS and compatible with both BouncyCastle and standard providers.