I have a .pem file that contains the private key in this format:
-----BEGIN RSA PRIVATE KEY-----
MIIEpAIBAAKCAQEA3wVu5KhHVJjc9ri5mWKNDW5xXe08smNeu2GSAdBwEaGBHaWj
...
xqDDtaoYKUvwhuKHboTJMs9CtQyrVNk+TDSdfaEdTEWTNeu2UwaP4QBhA==
-----END RSA PRIVATE KEY-----
If I want to convert it manually using OpenSSL I would use this command:
openssl pkcs8 -topk8 -inform PEM -outform DER -in secret.pem -nocrypt secret.key
However, I want to do that programmatically using java but I couldn't figure out how.
Any help is much appreciated
The OpenSSL statement converts the PEM encoded private key in PKCS#1 format into a DER encoded key in PKCS#8 format.
In Java, importing the PEM encoded PKCS#1 private key can be done with e.g. BouncyCastle's PEMParser and JcaPEMKeyConverter (using the bcprov und bcpkix jars). The export can be accomplished with PrivateKey#getEncoded() which returns the DER encoded PKCS#8 private key:
import java.io.FileOutputStream;
import java.io.FileReader;
import java.security.KeyPair;
import org.bouncycastle.openssl.PEMKeyPair;
import org.bouncycastle.openssl.PEMParser;
import org.bouncycastle.openssl.jcajce.JcaPEMKeyConverter;
...
String inputFile = "<path to PKCS#1 PEM key>";
String outputFile = "<path to PKCS#8 DER key>";
try (FileReader fileReader = new FileReader(inputFile);
PEMParser pemParser = new PEMParser(fileReader);
FileOutputStream outputStream = new FileOutputStream(outputFile)) {
// Import PEM encoded PKCS#1 private key
JcaPEMKeyConverter converter = new JcaPEMKeyConverter();
KeyPair keyPair = converter.getKeyPair((PEMKeyPair)pemParser.readObject());
// Export DER encoded PKCS#8 private key
byte[] privateKey = keyPair.getPrivate().getEncoded();
outputStream.write(privateKey, 0, privateKey.length);
}
You can run the task in a console in the background. Therefor you can use a ProcessBuilder.
//split the command every space and create a process builder
String[] commands = "your command written above...".split(" ");
ProcessBuilder pb = new ProcessBuilder(commands);
// starting the process
Process process = pb.start();
If you need to read the console output (instead of an output file) you can use an input stream:
// for reading the output from stream
BufferedReader stdInput = new BufferedReader(new InputStreamReader(
process.getInputStream()));
String s = null;
while ((s = stdInput.readLine()) != null) {
System.out.println(s);
}
I haven't tested this code in particular. If you need more info feel free to ask or visit this website: Process Builder
Related
So I have an X509Certificate that I encode like this
String base64 = Base64.getEncoder().encodeToString(certificate.getEncoded());
But this returns a string that looks like this (MII....)
Hence why I believe that when I run this part
PEMParser reader= new PEMParser (new StringReader(new String(Base64.getDecoder().decode(base64))));
PemObject object = reader.readPemObject();
The object is equal to null.
I believe that this is because the base64 encoded string is missing the header/footer -----BEGIN CERTIFCATE----- and -----END CERTIFICATE-----.
any idea how I can fix this?
The PEM encoding is derived from the DER encoding by first Base64 encoding the DER data with a line break after every 64 characters and adding a specific header and footer line.
Although this can be easily implemented, BouncyCastle provides convenient support for converting DER to PEM and vice versa. For writing PEM data JcaPEMWriter is used, for parsing PEM data PEMParser.
This applies not only to certificates, but also to public and private keys of various formats (PKCS#8, X.509/SPKI, PKCS#1).
The current question is about the conversion of a certificate. In this case the header line is -----BEGIN CERTIFICATE----- and the footer line is -----END CERTIFICATE-----. The following example shows the use of both classes for the conversion PEM to DER and DER to PEM:
import java.io.StringReader;
import java.io.StringWriter;
import java.util.Base64;
import org.bouncycastle.openssl.PEMParser;
import org.bouncycastle.openssl.jcajce.JcaPEMWriter;
import org.bouncycastle.util.io.pem.PemObject;
import org.bouncycastle.util.io.pem.PemObjectGenerator;
...
// PEM encoded certificate
String cert = "-----BEGIN CERTIFICATE-----\r\n"
+ "MIIFlTCCA32gAwIBAgIJAO4YFLMMLNM2MA0GCSqGSIb3DQEBCwUAMGExCzAJBgNV\r\n"
...
+ "nZSJxV3jloZP3NJDIQOZ8zXBqzVfba9fOOZF1ghIa0wFuvH1Ip1vL1sdBdo4PFsY\r\n"
+ "BQfFgCihe1CeDfY3gNQVQSS/dQ5139+kBQBsYnEeWoz0CLQWhGp3B/8=\r\n"
+ "-----END CERTIFICATE-----";
// Convert PEM to DER
PEMParser pemParser = new PEMParser(new StringReader(cert));
PemObject pemObject = pemParser.readPemObject();
byte[] derCertificate = pemObject.getContent(); // the DER encoded certificate
System.out.println(Base64.getEncoder().encodeToString(derCertificate));
// Convert DER to PEM
StringWriter stringWriter = new StringWriter();
JcaPEMWriter jcaPEMWriter = new JcaPEMWriter(stringWriter);
jcaPEMWriter.writeObject((PemObjectGenerator)new PemObject("CERTIFICATE", pemObject.getContent()));
jcaPEMWriter.close();
String pemCertificate = stringWriter.toString(); // the PEM encoded certificate
System.out.println(pemCertificate);
The code requires the bcprov and bcpkix jar files.
Similarly, private and public keys can be converted, with only the CERTIFICATE string in the PemObject constructor needing to be adjusted:
format string
---------------------------------------
PKCS#8 PRIVATE KEY
X.509/SPKI PUBLIC KEY
PKCS#1, private RSA PRIVATE KEY
PKCS#1, public RSA PUBLIC KEY
How to read EC private key which is in. Pem file using JAVA. While reading I am getting the following exception.
Caused by: java.security.InvalidKeyException: IOException : version mismatch: (supported: 00, parsed: 01
Actually my. Pem file contains private key in the following structure.
----BEGIN EC PRIVATE KEY ------
====+====+===
====+====+===
-----END EC PRIVATE KEY-----
From an EC PRIVATE KEY as requested (ex key.pem), I succeeded to import it in a java.security.KeyStore
transform private key from PEM => PKCS#8 DER
openssl pkcs8 -in key.pem -inform PEM -topk8 -nocrypt -out key-pkcs8.der -outform DER
load it (jvm version java-1.8.0-openjdk-1.8.0.201.b09-2.fc28.x86_64)
void loadPrivateKey(KeyStore ks, X509Certificate cert){
File privKeyFile = new File("key-pkcs8.der");
// read private key DER file
DataInputStream dis = new DataInputStream(new FileInputStream(privKeyFile));
byte[] privKeyBytes = new byte[(int)privKeyFile.length()];
dis.read(privKeyBytes);
dis.close();
KeyFactory kf = KeyFactory.getInstance("EC");
// decode private key
PKCS8EncodedKeySpec privSpec = new PKCS8EncodedKeySpec(privKeyBytes);
PrivateKey privKey = kf.generatePrivate(privSpec);
ks.setKeyEntry("key-alias", privKey, "password".toCharArray(), new Certificate[] {cert});
}
I am trying to generate an encrypted private key and CSR using Java in Matlab. Matlab adds some minor complexity, but this is mostly a Java problem. I start with a private key:
java.security.Security.addProvider(org.bouncycastle.jce.provider.BouncyCastleProvider());
keyGen = java.security.KeyPairGenerator.getInstance('RSA', 'BC');
keyGen.initialize(2048, java.security.SecureRandom());
keypair = keyGen.generateKeyPair();
privateKey = keypair.getPrivate();
If I encrypt the key and output it as PEM:
m=org.bouncycastle.openssl.PKCS8Generator.PBE_SHA1_3DES;
encryptorBuilder = org.bouncycastle.openssl.jcajce.JceOpenSSLPKCS8EncryptorBuilder(m);
encryptorBuilder.setRandom(java.security.SecureRandom());
encryptorBuilder.setPasssword(password);
oe = encryptorBuilder.build();
gen = org.bouncycastle.openssl.jcajce.JcaPKCS8Generator(privateKey,oe);
privKeyObj = gen.generate();
fos = java.io.FileWriter('private.pem');
pem = org.bouncycastle.openssl.jcajce.JcaPEMWriter(fos);
pem.writeObject(privKeyObj);
pem.flush();
fos.close();
I get a perfectly good key. The problem is that I want to use the key with jdbc, so I need a DER formatted pk8 key. I cannot figure out how to get this out of BouncyCastle. A kludge workaround that succeeds:
textWriter = java.io.StringWriter();
pem = org.bouncycastle.openssl.jcajce.JcaPEMWriter(textWriter);
pem.writeObject(privateKey);
pem.flush();
thekey = char(textWriter.toString());
cmd = ['echo "' thekey '"|openssl pkcs8 -topk8 -out private.pk8 -inform PEM -outform DER -passout pass:' password];
system(cmd);
Now, obviously this exposes both the unencrypted private key and the password. I've tried all manner of things to coerce privKeyObj to DER, but they typically leave me with:
$openssl pkcs8 -inform DER -outform PEM -in private.pk8 -out private.pem
Error decrypting key
140735211835472:error:0D0680A8:asn1 encoding routines:ASN1_CHECK_TLEN:wrong tag:tasn_dec.c:1201:
140735211835472:error:0D06C03A:asn1 encoding routines:ASN1_D2I_EX_PRIMITIVE:nested asn1 error:tasn_dec.c:765:
140735211835472:error:0D08303A:asn1 encoding routines:ASN1_TEMPLATE_NOEXP_D2I:nested asn1 error:tasn_dec.c:697:Field=version, Type=PKCS8_PRIV_KEY_INFO
The intent of this code is to generate a CSR on the end user's machine which I then sign, and which is encrypted with MAC address of the machine (and a salt), so that the program will only run on the authorized machine, and only authorized machines will be able to access my PostgreSql database.
Suggestions?
I figured it out. In my original code, I had used BcPKCS12PBEOutputEncryptorBuilder. Wrong! The correct call is to JcePKCSPBEOutputEncryptorBuilder. The correct code (in MATLAB, but converting to Java is simple) is:
java.security.Security.addProvider(org.bouncycastle.jce.provider.BouncyCastleProvider());
keyGen = java.security.KeyPairGenerator.getInstance('RSA', 'BC');
keyGen.initialize(2048, java.security.SecureRandom());
keypair = keyGen.generateKeyPair();
privateKey = keypair.getPrivate();
builder=org.bouncycastle.pkcs.jcajce.JcaPKCS8EncryptedPrivateKeyInfoBuilder(privateKey);
m=org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers.pbeWithSHAAnd3_KeyTripleDES_CBC;
encryptorBuilder = org.bouncycastle.pkcs.jcajce.JcePKCSPBEOutputEncryptorBuilder(m);
password = 'test';
outputBuilder = encryptorBuilder.build(password);
privKeyObj = builder.build(outputBuilder);
fos = java.io.FileOutputStream('testkey.pk8');
fos.write(privKeyObj.getEncoded());
fos.flush();
fos.close();
This generates a DER formatted PCS#8 file.
openssl pkcs8 -inform DER -outform PEM -in testkey.pk8 -out testkey.pem
Now returns the PEM private key. To read the key:
myPath = java.nio.file.Paths.get(pwd,'testkey.pk8');
encodedKey = java.nio.file.Files.readAllBytes(myPath);
privKeyObj =org.bouncycastle.pkcs.PKCS8EncryptedPrivateKeyInfo(encodedKey);
cp=org.bouncycastle.openssl.jcajce.JcaPEMKeyConverter();
cp.setProvider('BC');
decryptorBuilder = org.bouncycastle.pkcs.jcajce.JcePKCSPBEInputDecryptorProviderBuilder();
inputBuilder = decryptorBuilder.build(password);
info = privKeyObj.decryptPrivateKeyInfo(inputBuilder);
decodedKey=cp.getPrivateKey(info);
Note that in MATLAB, you don't need to declare the type of the returned object, and you don't need to put "new" in front of a constructor.
Background
RSA key generation with OpenSSL on Linux using the command,
openssl genrsa -out mykey.pem 1024
created the following:
"-----BEGIN RSA PRIVATE KEY-----
MIICXQIBAAKBgQChs9Fepy5FgeL0gNJ8GHcKRHsYnM2Kkw19zwydDQNyh2hrHWV2
B11wpLFp8d0imcl2Wjb0oV/AxOhb3unQgNzs66LVuXJwS8icp3oIJZtExs6tkxzE
s5mnU68wMeCYtJqHIZOmNblVWvpJMLNAwAVi3oLfnzDDbzjnDapm8M21nQIDAQAB
AoGAZ11P1+acUHgvwMXcRtFIvvp5iYkqZouL00EYOghIjNx75gTbh7A7jbbpZeTi
y6xsuMgAWy4QzGPSeG+tHMhS7+dYQNPuKSv5KtK3V7ubXz/I3ZN1etRVecA56QNw
7HKv6b7srolt08kogGIwpbbfl/mhfJHnv4Jeqd5lNMnK4e0CQQDWFZo4h22OlSaH
ZGd3i4rwLrA0Ux5bkdh7YH0uEeE/nGzpVs1DPhsN8UCyq9LAiKYLlXeeCvwurKwo
OgKlUCkzAkEAwVy2KignoRInFTAaYH8PQRfD835q+oC0Iu21BF68ne06U6wu+wWk
bWiYxTOOb+TGZfA1vA6OAvGVGoXs1bHF7wJBAItGiop0MKYuCl7Sxy1SrxUKir+/
w2Q3QesiHs41+6Byl7hGLEuuv9MWPM0AU5/GRqAKoUNESkPjOi0BcG8z81kCQGGn
OvCreugjzM0skAWv5bpQEExGyixdF5yURFlCpytzBYQAb3Gi9dmze4QMd6EW/wO4
fsrM5vehnlXY0TVTJM0CQQCMPVhub8LSo7T/lCzypvb/cgxJfyITRKcM2asrXud5
r27kbzsXqYum4huHqyFkb3pZammsYA/z89HchylfrD4U
-----END RSA PRIVATE KEY-----"
The following code under Java 6,
KeyPairGenerator keyGen = null;
try {
keyGen = KeyPairGenerator.getInstance("RSA");
} catch (NoSuchAlgorithmException e) {
throw new RuntimeException(e);
}
KeyPair pair = keyGen.generateKeyPair();
privateKey = new Base64Encoder().encode(pair.getPrivate().getEncoded());
publicKey = new Base64Encoder().encode(pair.getPublic().getEncoded());`
output the following:
"MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBAIsJlqFOP+jPyYvrGwh+dff30a3p
uHysMfHYi1MyNSFCsT/2QbOc/k9U/X28WRCMeFwEEnReLULXA9Ywox8GycI/ApMX+DjKBrrLDbpr
ATLiu9+NMK4VSytKFI87P07HAni3RkiO4rFNEINVQ7t38ZmHavuXHjMkLEAK4dyLQO9NAgMBAAEC
gYBN/jv0EmwBUgYSKflJI39TcT263B+0N/fwXXOSYNiy5rF9WstyUP/LSrbEAJLJmLKvk00y391t
4CVz0ma+sdUdAPlS7Nmx9f3BThGOGcDmpjVo1y4e1afWtyu66ba/XDeuf7q5Y/h/pr20/gXl9Gz2
yefQrzU9xXGKZhE/lxJ2IQJBAMELpeAal+Fa+u0InGrowVmV+lge8RZqKRfCDzPPna465E5Qcekb
J0ShsarP5lnUfrNH5g8GLaDGQwYE/UoIpPkCQQC4YRfck5uMlI1K3F9YC3XvmFAJnf9YexoPfNSu
dznOD4rxlwzW/5daPOR0jjlyIRDH/QuUoPIIEn1mt3dnz7X1AkBZciozgl7pPhySA7FmH96mwcUz
W3LdrebIaVRd707iUctDNibxmXFCbaFCwf27laf3LdM9FuHBYtvfSCSMTyERAkEAlNAQsUAVmKZB
T72D2o0Nd/7oAosaD7DzvLJU+idSaWUUEJ+IhnKuFu/0t7oe1WWopLEwypoIHsnFmsTTQ99ajQJA
Scwh3P3RTN4F6Jz1SxRSe6L729xI8xkbco5EsMq5v5BZeoGynqdPUUZdAPcaO2k5UagaSejvzgna
8xIqR7elVQ=="
"MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCLCZahTj/oz8mL6xsIfnX399Gt6bh8rDHx2ItT
MjUhQrE/9kGznP5PVP19vFkQjHhcBBJ0Xi1C1wPWMKMfBsnCPwKTF/g4yga6yw26awEy4rvfjTCu
FUsrShSPOz9OxwJ4t0ZIjuKxTRCDVUO7d/GZh2r7lx4zJCxACuHci0DvTQIDAQAB"
Questions
How do I put "armor" around the private and public keys created through Java code?
Why is each line of the keys generated through Java code longer than those output by OpenSSL?
Does it make any difference? One of the tools, that other team is using, fails while signing a message using private key generated by Java code mentioned above. However, it works just fine that tool uses the private key generated by OpenSSL.
Is there a way I can export a compatible key with Java?
The OpenSSL private key is in a non-standard format, while the Java code is creating a standard, PKCS-#8–encoded private key.
OpenSSL can convert the standard key format to the non-standard form. You can write Java code to do the same, but it requires some third-party libraries and a good knowledge of ASN.1 helps too.
To convert a PKCS #8 key to OpenSSL format, use OpenSSL's pkcs8 utility.
openssl pkcs8 -nocrypt -inform der < pvt.der > pvt.pem
To convert an RSA key stored as a DER-encoded SubjectPublicKeyInfo to PEM format, use OpenSSL's rsa utility.
openssl rsa -pubin -inform der < pub.der > pub.pem
This assumes that the private key is stored in "binary" (DER) format, not Base-64 encoded. The Java code to create and store keys like this would look something like:
KeyPairGenerator gen = KeyPairGenerator.getInstance("RSA");
KeyPair pair = gen.generateKeyPair();
FileOutputStream ospvt = new FileOutputStream("pvt.der");
try {
ospvt.write(pair.getPrivate().getEncoded());
ospvt.flush();
} finally {
ospvt.close();
}
FileOutputStream ospub = new FileOutputStream("pub.der");
try {
ospub.write(pair.getPublic().getEncoded());
ospub.flush();
} finally {
ospub.close();
}
I am working on a test harness for a SAML 1.1 Assertion Consumer Service. The test must generate a signed SAMLResponse and submit it to the ACS encoded in Base64. The ACS must be able to verify the signed message using the X509 public cert.
I am able to build the SAMLResponse, adding the necessary assertions, etc. But when I try to sign the object I am running into problems. Here is a snippet of my current code:
String certPath = "mycert.pem";
File pubCertFile = new File(certPath);
BufferedInputStream bis = null;
try {
bis = new BufferedInputStream(new FileInputStream(pubCertFile));
} catch(FileNotFoundException e) {
throw new Exception("Could not locate certfile at '" + certPath + "'", e);
}
CertificateFactory certFact = null;
Certificate cert = null;
try {
certFact = CertificateFactory.getInstance("X.509");
cert = certFact.generateCertificate(bis);
} catch(CertificateException e) {
throw new Exception("Could not instantiate cert", e);
}
bis.close();
ArrayList<Certificate> certs = new ArrayList<Certificate>();
certs.add(cert);
String keyPath = "mykey.pem";
File privKeyFile = new File(keyPath);
try {
bis = new BufferedInputStream(new FileInputStream(privKeyFile));
} catch(FileNotFoundException e) {
throw new Exception("Could not locate keyfile at '" + keyPath + "'", e);
}
byte[] privKeyBytes = new byte[(int)privKeyFile.length()];
bis.read(privKeyBytes);
bis.close();
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
KeySpec ks = new PKCS8EncodedKeySpec(privKeyBytes);
RSAPrivateKey privKey = (RSAPrivateKey) keyFactory.generatePrivate(ks);
samlResponse.sign(Signature.getInstance("SHA1withRSA").toString(), privKey, certs);
The error occurs on the second-to-last line. I see the following in the console:
java.security.spec.InvalidKeySpecException: java.security.InvalidKeyException: invalid key format
Though not customary or secure, but for sake of this thread, I am providing the public cert and private key that I am using. I of course will re-create new ones once the problem is solved. :)
aj#mmdev0:~/$ cat mykey.pem
-----BEGIN RSA PRIVATE KEY-----
MIICXgIBAAKBgQDnbcLSlDFaDMhalcmQgclTFobpkHQHJtxMVGRlbv7zknttAVbY
1jzGjJ6HVupndzDxA9tbiMjQujmGlS/8g5IEbVsR9o6dmcmbvujtEZ2rHZ82tMYP
VAt2IoS/W/q2Rr1cAZ/zTKEmh0ZZjzCZFueLfrYPm3am5JLcXgVtbKwybQIDAQAB
AoGBAJ441oettYgBUUFNQv8/HGtn7Vjl38277cVptTH8DuZr8WJ3Fe8tmWONZBzX
eW6/eIBuyJvuCo1ZpFa0zJfxQ/Ph6QlQwdN50GNfh9RzSS6lDdfy8BRhc27sypXS
L6c5ljB6ql+pp3DdxFhJMOs3ZmBJdeyWe7uFrkngtnM1nxZBAkEA+1hbV1Q305wa
u8YMF1SlNIAfgLJ7buD43SEXle0egz405PFG8f8yDmvROwDiRceILGVrRbInd7Cb
dvJKr34WOQJBAOu2+reG44rNuiXeGX1MYg6TlWYyABm7PrTrhPZkedodOQB8p7zD
AqtDSK7RnDCoThndPW6kdNAeB+kG4ug5XdUCQHRDU8UajNRSkj8nhjJIkj6twWS7
qsMIR7Wp+An+7C1TWg5I2UNZg2MOVnNPnlseyAuZQjy0AvOnetJTk16IGWkCQQCL
FUbOr8rnhgiGe4yywDVDwJVw3aPtiuyvOCEWeabkqkWOIf+fg7m5cFQcwxXUKBsd
a8vp0yQSAQZN24Bb4i2ZAkEA8xGJFlFDY9HREWZnDey5STgbUeT1wYkyKcDsUrp1
kR/3BliGqSIfje+mSKDIZqaP+gai/8bIABYAsDP/t6+cuA==
-----END RSA PRIVATE KEY-----
aj#mmdev0:~/$ cat mycert.pem
-----BEGIN CERTIFICATE-----
MIID7zCCA1igAwIBAgIJAKrURaAaD6ulMA0GCSqGSIb3DQEBBQUAMIGsMQswCQYD
VQQGEwJVUzERMA8GA1UECBMISWxsaW5vaXMxEDAOBgNVBAcTB0NoaWNhZ28xHDAa
BgNVBAoTE0hvc3R3YXkgQ29ycG9yYXRpb24xITAfBgNVBAsTGFJlc2VhcmNoIGFu
ZCBEZXZlbG9wbWVudDEYMBYGA1UEAxMPd3d3Lmhvc3R3YXkuY29tMR0wGwYJKoZI
hvcNAQkBFg5hakBob3N0d2F5LmNvbTAeFw0xMDA3MTQwMjMyMDhaFw0xMTA3MTQw
MjMyMDhaMIGsMQswCQYDVQQGEwJVUzERMA8GA1UECBMISWxsaW5vaXMxEDAOBgNV
BAcTB0NoaWNhZ28xHDAaBgNVBAoTE0hvc3R3YXkgQ29ycG9yYXRpb24xITAfBgNV
BAsTGFJlc2VhcmNoIGFuZCBEZXZlbG9wbWVudDEYMBYGA1UEAxMPd3d3Lmhvc3R3
YXkuY29tMR0wGwYJKoZIhvcNAQkBFg5hakBob3N0d2F5LmNvbTCBnzANBgkqhkiG
9w0BAQEFAAOBjQAwgYkCgYEA523C0pQxWgzIWpXJkIHJUxaG6ZB0BybcTFRkZW7+
85J7bQFW2NY8xoyeh1bqZ3cw8QPbW4jI0Lo5hpUv/IOSBG1bEfaOnZnJm77o7RGd
qx2fNrTGD1QLdiKEv1v6tka9XAGf80yhJodGWY8wmRbni362D5t2puSS3F4FbWys
Mm0CAwEAAaOCARUwggERMB0GA1UdDgQWBBQI/4Inzs6OH5IquItuKhIrhPb24zCB
4QYDVR0jBIHZMIHWgBQI/4Inzs6OH5IquItuKhIrhPb246GBsqSBrzCBrDELMAkG
A1UEBhMCVVMxETAPBgNVBAgTCElsbGlub2lzMRAwDgYDVQQHEwdDaGljYWdvMRww
GgYDVQQKExNIb3N0d2F5IENvcnBvcmF0aW9uMSEwHwYDVQQLExhSZXNlYXJjaCBh
bmQgRGV2ZWxvcG1lbnQxGDAWBgNVBAMTD3d3dy5ob3N0d2F5LmNvbTEdMBsGCSqG
SIb3DQEJARYOYWpAaG9zdHdheS5jb22CCQCq1EWgGg+rpTAMBgNVHRMEBTADAQH/
MA0GCSqGSIb3DQEBBQUAA4GBAA388zZp6UNryC/6o44hj7wTBQdzFFM5cs3B668A
ylAnnal+J8RMIeCHoMF4S7yFQtYdOiWeScgw3c7KXrhJK1X7fU3I+eb1t3Yp1cTI
htyzw14AoiICFalmlVgTCsn3+uh6AXP02PTkR8osdEpUOlWap4uzSKYNKc7tLOFd
4CkM
-----END CERTIFICATE-----
Thanks!
You need to convert your private key to PKCS8 format using following command:
openssl pkcs8 -topk8 -inform PEM -outform DER -in private_key_file -nocrypt > pkcs8_key
After this your java program can read it.
Two things. First, you must base64 decode the mykey.pem file yourself. Second, the openssl private key format is specified in PKCS#1 as the RSAPrivateKey ASN.1 structure. It is not compatible with java's PKCS8EncodedKeySpec, which is based on the SubjectPublicKeyInfo ASN.1 structure. If you are willing to use the bouncycastle library you can use a few classes in the bouncycastle provider and bouncycastle PKIX libraries to make quick work of this.
import java.io.BufferedReader;
import java.io.FileReader;
import java.security.KeyPair;
import java.security.Security;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.bouncycastle.openssl.PEMKeyPair;
import org.bouncycastle.openssl.PEMParser;
import org.bouncycastle.openssl.jcajce.JcaPEMKeyConverter;
// ...
String keyPath = "mykey.pem";
BufferedReader br = new BufferedReader(new FileReader(keyPath));
Security.addProvider(new BouncyCastleProvider());
PEMParser pp = new PEMParser(br);
PEMKeyPair pemKeyPair = (PEMKeyPair) pp.readObject();
KeyPair kp = new JcaPEMKeyConverter().getKeyPair(pemKeyPair);
pp.close();
samlResponse.sign(Signature.getInstance("SHA1withRSA").toString(), kp.getPrivate(), certs);