I have created mdm.pem,intermediate.pem , root.pem using the reference.
As a vendor action
openssl x509 -inform der -in mdm_identity.cer -out mdm.pem
openssl x509 -inform der -in AppleWWDRCA.cer -out intermediate.pem
openssl x509 -inform der -in AppleIncRootCertificate.cer -out root.pem
As a customer,
created a CSR using openssl :
openssl genrsa -des3 -out customerPrivateKey.pem 2048
openssl req -new -key customerPrivateKey.pem -out customer.csr
then convert customer.csr to der format :
openssl req -inform pem -outform der -in customer.csr -out customer.der
After that using the java sample code downloaded from the same reference ,I was trying to create plist.xml and plist_encoded. But I am getting the null key exception.
private PrivateKey extractPrivateKey(String path2keystore) throws KeyStoreException, NoSuchAlgorithmException, CertificateException, FileNotFoundException, IOException, UnrecoverableKeyException
{
String alias = "test";//Change to your alias
String password = "test";//Change to your password
KeyStore caKs = KeyStore.getInstance("PKCS12");
caKs.load(new FileInputStream(new File(path2keystore)), password.toCharArray());
//----------issue in the below line
Key key = caKs.getKey(alias, password.toCharArray());
//getting null key in the above line for "key" object
return (PrivateKey)key;
}
I am not able to understand what I am doing wrong. If someone else also faced similar type of problem please help me.
I am attaching full Test.java source code below:
package com.softhinker;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileWriter;
import java.io.IOException;
import java.net.URL;
import java.security.Key;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.Signature;
import java.security.UnrecoverableKeyException;
import java.security.cert.CertificateException;
import org.dom4j.Document;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import sun.misc.BASE64Encoder;
/**
* This class is to generate encoded plist for iOS MDM signing request.
* Below files should be in the folder :
* - customer.der
* - intermediate.pem
* - mdm.pem
* - root.pem
* - vendor.p12
*
* Then upload 'plist_encoded' to https://identity.apple.com/pushcert/ to
* generate the certificate for your customer.
*
* [Author Introduction]
* Softhinker.com is a Singapore-based independent software vendor,
* focusing on J2EE, Android, iOS, Google Apps development and consultancy.
* Please visit us at http://www.softhinker.com for more details.
*
* #author Softhinker
*
*/
public class Test {
public static void main(String[] args) throws Exception {
URL dirUrl = Test.class.getResource(".");
URL keyUrl = new URL(dirUrl, "vendor.p12");
String keyPath = keyUrl.getPath().replaceAll("%20", " ");
System.out.println(keyPath);
BASE64Encoder b64en = new BASE64Encoder();
Test test = new Test();
PrivateKey privateKey = test.extractPrivateKey(keyPath);
URL csrUrl = new URL(dirUrl, "customer.der");
String csrPath = csrUrl.getPath().replace("%20", " ");
byte[] csrBytes = test.readCSR(csrPath);
String csr = b64en.encode(csrBytes);
byte[] sigBytes = test.signCSR(privateKey, csrBytes);
String signature = b64en.encode(sigBytes);
URL mdmUrl = new URL(dirUrl, "mdm.pem");
String mdmPath = mdmUrl.getPath().replace("%20", " ");
String mdm = test.readCertChain(mdmPath);
URL intermediateUrl = new URL(dirUrl, "intermediate.pem");
String intermediatePath = intermediateUrl.getPath().replace("%20", " ");
String intermediate = test.readCertChain(intermediatePath);
URL rootUrl = new URL(dirUrl, "root.pem");
String rootPath = rootUrl.getPath().replace("%20", " ");
String root = test.readCertChain(rootPath);
StringBuffer sb = new StringBuffer();
sb.append(mdm);
sb.append(intermediate);
sb.append(root);
test.generatePlist(csr, sb.toString(), signature);
}
private byte[] signCSR(PrivateKey privateKey, byte[] csr) throws Exception {
Signature sig = Signature.getInstance("SHA1WithRSA");
sig.initSign(privateKey);
sig.update(csr);
byte[] signatureBytes = sig.sign();
return signatureBytes;
}
private PrivateKey extractPrivateKey(String path2keystore) throws KeyStoreException, NoSuchAlgorithmException, CertificateException, FileNotFoundException, IOException, UnrecoverableKeyException
{
String alias = "test";//Change to your alias
String password = "test";//Change to your password
KeyStore caKs = KeyStore.getInstance("PKCS12");
caKs.load(new FileInputStream(new File(path2keystore)), password.toCharArray());
Key key = caKs.getKey(alias, password.toCharArray());
return (PrivateKey)key;
}
private byte[] readCSR(String path2csr) throws IOException
{
FileInputStream fis = new FileInputStream(path2csr);
byte[] csrBytes = new byte[fis.available()];
fis.read(csrBytes);
fis.close();
return csrBytes;
}
private String readCertChain(String path2certchain) throws IOException
{
FileInputStream fis = new FileInputStream(path2certchain);
byte[] csrBytes = new byte[fis.available()];
fis.read(csrBytes);
fis.close();
return new String(csrBytes);
}
private void generatePlist(String csr, String chain, String signature) throws IOException
{
Document document = DocumentHelper.createDocument();
document.addDocType("plist", "-//Apple//DTD PLIST 1.0//EN", "http://www.apple.com/DTDs/PropertyList-1.0.dtd");
Element plist = document.addElement("plist");
plist.addAttribute("version", "1.0");
Element dict = plist.addElement("dict");
Element csrKey = dict.addElement("key");
csrKey.addText("PushCertRequestCSR");
Element csrStr = dict.addElement("string");
csrStr.addText(csr);
Element chainKey = dict.addElement("key");
chainKey.addText("PushCertCertificateChain");
Element chainStr = dict.addElement("string");
chainStr.addText(chain);
Element sigKey = dict.addElement("key");
sigKey.addText("PushCertSignature");
Element sigStr = dict.addElement("string");
sigStr.addText(signature);
String plistxml = document.asXML();
BASE64Encoder b64en = new BASE64Encoder();
String encodedplist = b64en.encode(plistxml.getBytes());
FileWriter writer = new FileWriter("plist.xml");
document.write(writer);
writer.flush();
writer.close();
FileWriter out = new FileWriter("plist_encoded");
out.write(encodedplist);
out.flush();
out.close();
System.out.println("File is generated.");
}
}
Now I am able to solve the problem.Problem was wrong alias.I listed out the aliases for the vendor.p12 and I got the correct alias,which I passed in Key key = caKs.getKey(alias, password.toCharArray());
I solved the problem as per Chris' comment above.
Related
when trying to do an encrypt/decrypt roundtrip using the public/private keys of a certificate as stored in the Certificate Manager (Windows-MY): this works on most Windows versions, but it fails on Windows Server 2022
OS Name: Microsoft Windows Server 2022 Standard
OS Version: 10.0.20348 N/A Build 20348
using the java version:
openjdk version "1.8.0_322"
OpenJDK Runtime Environment (Temurin)(build 1.8.0_322-b06)
OpenJDK 64-Bit Server VM (Temurin)(build 25.322-b06, mixed mode)
see full code below.
On most Windows versions, the code/roundtrip works.
However, on Windows Server 2022, encrypting works but when decrypting, I get the following exception:
java.security.ProviderException: java.security.KeyException: The parameter is incorrect.
at sun.security.mscapi.CRSACipher.doFinal(CRSACipher.java:311)
at sun.security.mscapi.CRSACipher.engineDoFinal(CRSACipher.java:335)
at javax.crypto.Cipher.doFinal(Cipher.java:2168)
at com.esko.utl.crypto.ppktest.decrypt(ppktest.java:61)
at com.esko.utl.crypto.ppktest.main(ppktest.java:28)
Caused by: java.security.KeyException: The parameter is incorrect.
at sun.security.mscapi.CRSACipher.encryptDecrypt(Native Method)
at sun.security.mscapi.CRSACipher.doFinal(CRSACipher.java:303)
... 4 more
The certificate is generated using keytool.
When saving the certificate in a JKS Keystore, in a file on disk,
then when loading the certificate from the JKS keystore from disk, decrypting works also on Windows Server 2022.
Question: why can the certificate no be used for decrypting when it is loaded in java from Certificate Manager when running on Windows Server 2022? How could this be solved?
import static java.nio.charset.StandardCharsets.UTF_8;
import java.io.ByteArrayOutputStream;
import java.util.Base64;
import java.security.KeyPair;
import java.security.KeyStore;
import java.security.PrivateKey;
import java.security.Provider;
import java.security.Security;
import java.security.cert.Certificate;
import javax.crypto.Cipher;
import javax.crypto.CipherOutputStream;
public class ppktest
{
public static void main (String[] args2)
{
String inputArg = "ABCDEFGHI";
String alias = "esko-ae";
String pw = "******";
try
{
String encrypted = encrypt (inputArg, alias, pw.toCharArray ());
System.out.println ("Encrypted:" + encrypted);
String decrypted = decrypt (encrypted, alias, pw.toCharArray ());
System.out.println ("Decrypted:" + decrypted);
boolean b = inputArg.equals (decrypted);
System.out.println ("Roundtrip succeeded:" + b);
}
catch (Throwable t)
{
t.printStackTrace ();
}
}
private static String encrypt (String v, String alias, char[] pw) throws Exception
{
Cipher ec = makeCipher (true, alias, pw);
ByteArrayOutputStream bos = new ByteArrayOutputStream (512);
CipherOutputStream cos = new CipherOutputStream (bos, ec);
cos.write (v.getBytes (UTF_8));
cos.close ();
return Base64.getEncoder().encodeToString (bos.toByteArray ());
}
private static String decrypt (String v, String alias, char[] pw) throws Exception
{
byte[] bytes = Base64.getDecoder ().decode (v);
Cipher dc = makeCipher (false, alias, pw);
return new String (dc.doFinal (bytes), UTF_8);
}
private static Cipher makeCipher (boolean encrypt, String alias, char[] pw) throws Exception
{
KeyPair keyPair = getKeyPairFromKeyStore (alias, pw);
Cipher retval = Cipher.getInstance ("RSA/ECB/PKCS1Padding");
if (encrypt)
retval.init (Cipher.ENCRYPT_MODE, keyPair.getPublic ());
else
{
PrivateKey privKey = keyPair.getPrivate ();
retval.init (Cipher.DECRYPT_MODE, privKey);
}
return retval;
}
private static KeyStore loadKeyStore () throws Exception
{
KeyStore keyStore = KeyStore.getInstance ("Windows-MY");
keyStore.load (null, null);
return keyStore;
}
private static KeyPair getKeyPairFromKeyStore (String alias, char[] pw) throws Exception
{
KeyStore keyStore = loadKeyStore ();
Certificate cert = keyStore.getCertificate (alias);
if (cert == null) throw new Exception ("Alias not found in keystore: " + alias);
KeyStore.PasswordProtection keyPassword = new KeyStore.PasswordProtection (pw);
KeyStore.PrivateKeyEntry privateKeyEntry = (KeyStore.PrivateKeyEntry) keyStore.getEntry (alias, keyPassword);
if (privateKeyEntry == null) throw new Exception ("Private key for " + alias + " could not be obtained.");
return new KeyPair (cert.getPublicKey (), privateKeyEntry.getPrivateKey ());
}
}
Given an X509 certificate object of a person. (The object's type is sun.security.x509.X509CertImpl). This person signed a String with his private key. Given the signature that was made by this person, when he signed the above mentioned String object.
My task is to verify this signature, but have difficulties with it.
When I try to verify the signature with the below code:
...
X509Certificate x509Certificate = getCertificate(certificate);
Signature signature = Signature.getInstance("SHA256withECDSA");
signature.initVerify(x509Certificate.getPublicKey());
signature.update(unsignedData);
boolean bool = signature.verify(signatureToVerify);
System.out.println("The signature is " + (bool ? "" : "NOT") + " valid");
I get java.security.SignatureException: Could not verify signature
Do you have an idea, how can I make it working?
Edited:
At the end, I managed to make it working, but do not understand the reason yet:
Before passing the signature to the verify method, i needed to do the following modification on it:
byte[] rBytes = Arrays.copyOfRange(signatureHash, 0, 32);
byte[] sBytes = Arrays.copyOfRange(signatureHash, 32, 64);
BigInteger r = new BigInteger(1, rBytes);
BigInteger s = new BigInteger(1, sBytes);
ASN1Integer asn1R = new ASN1Integer(r);
ASN1Integer asn1S = new ASN1Integer(s);
DERSequence seq = new DERSequence(new ASN1Integer[]{asn1R, asn1S});
byte[] signatureToVerify2 = seq.getEncoded();
// verifying the signatureToVerify2 instead of the original brings success
boolean bool = signature.verify(signatureToVerify2);
Here is a (semi)working app for further reference that verifies a signature, when ECDSA is involved in the story:
import org.bouncycastle.asn1.ASN1Integer;
import org.bouncycastle.asn1.DERSequence;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.Signature;
import java.security.SignatureException;
import java.security.cert.CertificateException;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import java.util.Arrays;
public class SignatureTest {
public static void main(String[] args) throws CertificateException, InvalidKeyException, SignatureException, NoSuchAlgorithmException, IOException {
byte[] certificateAsByteArray = ...;
byte[] dataToVerifyAsByteArray = ...;
byte[] signatureHashAsByteArray = ...;
CertificateFactory certFactory = CertificateFactory.getInstance("X.509");
InputStream in = new ByteArrayInputStream(certificateBytes);
X509Certificate x509Certificate = (X509Certificate) certFactory.generateCertificate(in);
Signature signature = Signature.getInstance("SHA256withECDSA");
signature.initVerify(x509Certificate.getPublicKey());
signature.update(dataToVerifyAsHexaString);
byte[] rBytes = Arrays.copyOfRange(signatureHash, 0, 32);
byte[] sBytes = Arrays.copyOfRange(signatureHash, 32, 64);
ASN1Integer asn1R = new ASN1Integer(rBytes);
ASN1Integer asn1S = new ASN1Integer(sBytes);
DERSequence seq = new DERSequence(new ASN1Integer[] {asn1R, asn1S});
boolean isSignatureOK = signature.verify(seq.getEncoded());
System.out.println("The signature is " + (isSignatureOK ? "" : "NOT ") + "VALID");
}
}
I have a RSA Key and a X.509 Certificate which I use for SSL connections.
The key and certificate are stored in files in PEM format (generated by OpenSSL) and used in an Apache HTTP server environment.
Is there an easy way to validate if the key matches the certificate using only Java code (without executing the openssl binary and parsing the output), for example by using Java security and/or Bouncycastle library methods?
The following code compares the SHA-1 over the modulus within the public and private key. The modulus should be unique for each pair (unless you key pair generation mechanism or random generator is broken of course).
Note that the following code requires the key to be in unencrypted PKCS#8 format. It may be better to use PKCS#12 instead and load the binary PKCS#12 file in a KeyStore (providing the password).
openssl pkcs8 -topk8 -in key.pem -out keypk8.pem -nocrypt
And finally the Java code:
import static org.bouncycastle.util.encoders.Hex.toHexString;
import java.io.ByteArrayInputStream;
import java.io.FileReader;
import java.security.KeyFactory;
import java.security.MessageDigest;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.cert.Certificate;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.KeySpec;
import java.security.spec.PKCS8EncodedKeySpec;
import org.bouncycastle.util.io.pem.PemObject;
import org.bouncycastle.util.io.pem.PemReader;
public class CompareCertAndKey {
/**
* Checks if the certificate and RSA private key match.
*
* #param args the path to the certificate file in args[0] and that of the private key in args[1]
*/
public static void main(String[] args) {
try {
final PemReader certReader = new PemReader(new FileReader(args[0]));
final PemObject certAsPemObject = certReader.readPemObject();
if (!certAsPemObject.getType().equalsIgnoreCase("CERTIFICATE")) {
throw new IllegalArgumentException("Certificate file does not contain a certificate but a " + certAsPemObject.getType());
}
final byte[] x509Data = certAsPemObject.getContent();
final CertificateFactory fact = CertificateFactory.getInstance("X509");
final Certificate cert = fact.generateCertificate(new ByteArrayInputStream(x509Data));
if (!(cert instanceof X509Certificate)) {
throw new IllegalArgumentException("Certificate file does not contain an X509 certificate");
}
final PublicKey publicKey = cert.getPublicKey();
if (!(publicKey instanceof RSAPublicKey)) {
throw new IllegalArgumentException("Certificate file does not contain an RSA public key but a " + publicKey.getClass().getName());
}
final RSAPublicKey rsaPublicKey = (RSAPublicKey) publicKey;
final byte[] certModulusData = rsaPublicKey.getModulus().toByteArray();
final MessageDigest sha1 = MessageDigest.getInstance("SHA-1");
final byte[] certID = sha1.digest(certModulusData);
final String certIDinHex = toHexString(certID);
final PemReader keyReader = new PemReader(new FileReader(args[1]));
final PemObject keyAsPemObject = keyReader.readPemObject();
if (!keyAsPemObject.getType().equalsIgnoreCase("PRIVATE KEY")) {
throw new IllegalArgumentException("Key file does not contain a private key but a " + keyAsPemObject.getType());
}
final byte[] privateKeyData = keyAsPemObject.getContent();
final KeyFactory keyFact = KeyFactory.getInstance("RSA");
final KeySpec keySpec = new PKCS8EncodedKeySpec(privateKeyData);
final PrivateKey privateKey = keyFact.generatePrivate(keySpec);
if (!(privateKey instanceof RSAPrivateKey)) {
throw new IllegalArgumentException("Key file does not contain an X509 encoded private key");
}
final RSAPrivateKey rsaPrivateKey = (RSAPrivateKey) privateKey;
final byte[] keyModulusData = rsaPrivateKey.getModulus().toByteArray();
final byte[] keyID = sha1.digest(keyModulusData);
final String keyIDinHex = toHexString(keyID);
System.out.println(args[0] + " : " + certIDinHex);
System.out.println(args[1] + " : " + keyIDinHex);
if (certIDinHex.equalsIgnoreCase(keyIDinHex)) {
System.out.println("Match");
System.exit(0);
} else {
System.out.println("No match");
System.exit(-1);
}
} catch (Exception e) {
e.printStackTrace(System.err);
System.exit(-2);
}
}
}
Thank you very much for the above code snippet. Its working for me with bouncycastle version 1.51
<bcprov-jdk15on-version>1.51</bcprov-jdk15on-version>
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcprov-jdk15on</artifactId>
<version>${bcprov-jdk15on-version}</version>
</dependency>
Many Thanks for your code snippet.
I need to be able to read in Java a S/MIME file generated from OpenSSL. The openssl command looks like
openssl smime -encrypt -in test_message.txt -out test_out.pem -outform pem certificate.pem
This creates a file that looks like
-----BEGIN PKCS7-----
MIIBkwYJKoZIhvcNAQcDoIIBhDCCAYACAQAxggE+MIIBOgIBADAiMBoxGDAWBgNV
BAMTD0ZvcmRTRE5TZWN1cml0eQIEUw5nyTANBgkqhkiG9w0BAQEFAASCAQBK9wAV
wAXRM7oMWJz113VX7Tb/MslQatHZH2oaX5XJnIJrvnTv9T3irQR9H+pegh1q6OZv
v4Mz/QBFO2iq4tv6xGHE8hl0ZdmNCUdTN41qutZP2+N1YrKi9QLmnuAi3BkEzzeW
YTGvE8xGsjNlTLOjz7P5lZdCWpGJmdPeUDP0IYsOsuMspPcujyOdA5y++y6x90WF
J3ovzPhCRU7303EhdQ1hHse8KTen56XZflL3zhnT2KGtN/Pq3aZ1MVhmLZ+EZuUF
ygxlwCXi3FUx7P35XZAGpTUPFM2sz5p+oSrcxA+fsUgiMb96tfaXZLYE753mA2tZ
WfCRd86nzJsVE/YhMDkGCSqGSIb3DQEHATAaBggqhkiG9w0DAjAOAgIAoAQIqd23
FXgqdaSAEHLeYH0LG9G+UfCBxQOalIE=
-----END PKCS7-----
I am currently using BouncyCastle to try to read in test_out.pem,
....
MimeMessage mimeMessage = new MimeMessage(session, new FileInputStream("test_out.pem"));
SMIMEEnveloped smimeEnveloped = new SMIMEEnveloped(mimeMessage);
...
but I can't figure out how to make it accept a message without the MIME headers, as I get the following error:
java.lang.NullPointerException: null
at org.bouncycastle.cms.CMSEnvelopedData.<init>(Unknown Source) ~[bcpkix-jdk15on-1.50.jar:1.50.0]
at org.bouncycastle.cms.CMSEnvelopedData.<init>(Unknown Source) ~[bcpkix-jdk15on-1.50.jar:1.50.0]
at org.bouncycastle.mail.smime.SMIMEEnveloped.<init>(Unknown Source) ~[bcmail-jdk15on-1.50.jar:1.50.0]
What would be the best way to read a PEM (or DER) formatted file like this in and be able to decrypt it with a java.security.PrivateKey?
Here's how you can do the decryption using BouncyCastle 1.57 (inspired by this article):
import org.bouncycastle.cms.CMSEnvelopedData;
import org.bouncycastle.cms.CMSException;
import org.bouncycastle.cms.KeyTransRecipientInformation;
import org.bouncycastle.cms.RecipientInformation;
import org.bouncycastle.cms.jcajce.JceKeyTransEnvelopedRecipient;
import org.bouncycastle.cms.jcajce.JceKeyTransRecipient;
import org.bouncycastle.util.encoders.Base64;
import java.security.KeyFactory;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;
import java.util.Collection;
public class PKCS7Decryptor {
private PrivateKey privateKey;
public PKCS7Decryptor(String privateKeyStr) {
try {
byte[] privateKeyData = extractRawData(privateKeyStr, "PRIVATE KEY");
PKCS8EncodedKeySpec kspec = new PKCS8EncodedKeySpec(privateKeyData);
KeyFactory kf = KeyFactory.getInstance("RSA");
privateKey = kf.generatePrivate(kspec);
} catch (NoSuchAlgorithmException | InvalidKeySpecException e) {
throw new RuntimeException("Unable to parse private key");
}
}
public String decrypt(String encryptedText) throws CMSException {
byte[] data = extractRawData(encryptedText, "PKCS7");
CMSEnvelopedData envelopedData = new CMSEnvelopedData(data);
Collection<RecipientInformation> recipients = envelopedData.getRecipientInfos().getRecipients();
KeyTransRecipientInformation recipientInfo = (KeyTransRecipientInformation) recipients.iterator().next();
JceKeyTransRecipient recipient = new JceKeyTransEnvelopedRecipient(privateKey);
return new String(recipientInfo.getContent(recipient));
}
private byte[] extractRawData(String text, String dataType) {
return Base64.decode(text
.replace(String.format("-----BEGIN %s-----", dataType), "")
.replace(String.format("-----END %s-----", dataType), ""));
}
}
Some explanation:
In the class constructor the private key is converted to a proper format
Headers and footers (like "-----BEGIN PKCS7-----") are removed and the content is base64-decoded
I'm trying to read a private key from a .pem file in PKCS#8 format, the problem I've faced is that these kind of files have this header
-----BEGIN PRIVATE KEY-----
so there is no information about the algorithm used to instantiate the key, my question is:
is there a method to know the algorithm without decoding the key (which is base64) and see the algorithm modifier, also if there is a way to know the length of the key..
help is appreciated
Using Bouncy Castle and modifying the code from this answer, I came up with this to get your answers.
Note: This code will only work with non-encrypted private keys.
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.security.PrivateKey;
import java.security.Security;
import org.bouncycastle.asn1.pkcs.PrivateKeyInfo;
import org.bouncycastle.jcajce.provider.asymmetric.dsa.BCDSAPrivateKey;
import org.bouncycastle.jcajce.provider.asymmetric.ec.BCECPrivateKey;
import org.bouncycastle.jcajce.provider.asymmetric.rsa.BCRSAPrivateKey;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.bouncycastle.openssl.PEMParser;
import org.bouncycastle.openssl.jcajce.JcaPEMKeyConverter;
public class PemKeyInfo
{
/**
* #param args
* #throws IOException
*/
public static void main(String[] args) throws IOException
{
Security.addProvider(new BouncyCastleProvider());
String privateKeyFileName = "C:\\privkeypk8.pem";
File privateKeyFile = new File(privateKeyFileName); // private key file in PEM format
PEMParser pemParser = new PEMParser(new FileReader(privateKeyFile));
Object object = pemParser.readObject();
pemParser.close();
JcaPEMKeyConverter converter = new JcaPEMKeyConverter().setProvider("BC");
PrivateKey privkey = null;
if (object instanceof PrivateKeyInfo)
{
privkey = converter.getPrivateKey((PrivateKeyInfo) object);
}
if (privkey != null)
{
System.out.println("Algorithm: " + privkey.getAlgorithm()); // ex. RSA
System.out.println("Format: " + privkey.getFormat()); // ex. PKCS#8
}
if (privkey instanceof BCRSAPrivateKey)
{
System.out.println("RSA Key Length: " + ((BCRSAPrivateKey)privkey).getModulus().bitLength()); // ex. 2048
}
if (privkey instanceof BCDSAPrivateKey)
{
System.out.println("DSA Key Length: " + ((BCDSAPrivateKey)privkey).getParams().getP().bitLength()); // ex. 2048
}
if (privkey instanceof BCECPrivateKey)
{
System.out.println("EC Key Length: " + ((BCECPrivateKey)privkey).getParams().getOrder().bitLength()); // ex. 256
}
}
}
Update: I've edited the code above to give key lengths for RSA, DSA, and EC keys.