InvalidKeySpecException while trying to generate public key from pem file - java

I am trying to generate a RSAPublicKey from the publickey.pem file but it is throwing me exception .
https://github.com/cerner/cds-hooks-sandbox/blob/master/ecpublickey.pem
Invalid token :::java.security.spec.InvalidKeySpecException: java.security.InvalidKeyException: invalid key format
KeyFactory factory = KeyFactory.getInstance("RSA");
PemReader pemReader = new PemReader(new InputStreamReader(new
FileInputStream(filename)));
PemObject pemObject = pemReader.readPemObject();
byte[] content = pemObject.getContent();
X509EncodedKeySpec pubKeySpec = new X509EncodedKeySpec(content);
RSAPublicKey publicKey = factory.generatePublic(pubKeySpec);
It works fine if I generate and save my own pem file.

Related

Can't load RSA public key from file (Java)

i generated a public key file using puttyGen like this:
Resulting in a file with this content:
---- BEGIN SSH2 PUBLIC KEY ----
Comment: "rsa-key-20200116"
AAAAB3NzaC1yc2EAAAABJQAAAQEA9/jf/WH+pfOHU0j9bVYjaPHp9V1F+Tau9Pwh
Zd30m389u8dCFQqWcAYIIbAFs5eE744bdztMpIC2HbqO9hCa5AAq1U2CD0XzWUFg
H5OC9krVSuhnsU6FAJoS2zz+I4P30cuLY98Kzxt6q8pouT3fIgRAmWaKpkO/ol46
APub5ZdTTTqHwpuzOKEI0iVkd6Lsqrp98kLnwCxUV3zyecZN/YsoRRpQaMbdfCfi
kc0qKjwVRNffLk4aCPB4X0yY/EYaeLmNObCuyHqvAojM5SsoB7xlFVLfoNLtnygj
Akxty2+3MO2rsO+dl++sPMNg3EK8pfT+igB0piR2dG9LpQf9Vw==
---- END SSH2 PUBLIC KEY ----
But trying with no luck at all to load this public key from this method below:
public static PublicKey getPublicKey(String fileName) throws Exception {
FileReader reader = new FileReader(fileName);
PemReader pemReader = new PemReader(reader);
PemObject pemObj = pemReader.readPemObject();
pemReader.close();
X509EncodedKeySpec spec = new X509EncodedKeySpec(pemObj.getContent());
KeyFactory kf = KeyFactory.getInstance("RSA", "BC");
return kf.generatePublic(spec);
}
The PemObject resulting is always null. Followed every tutorial found, somebody help me. PemObject and PemReader are from org.bouncycastle.util.io.pem.*
Am i doing something silly?

java.security.InvalidKeyException: invalid key format while reading from .CRT file

I am trying to load the key from a .crt file. Below is my code
Path path = Paths.get(filePath);
byte[] bytes;
try {
bytes = Files.readAllBytes(path);
/* Generate public key. */
X509EncodedKeySpec ks = new X509EncodedKeySpec(bytes);
KeyFactory kf = KeyFactory.getInstance("RSA");
PublicKey pubKey = kf.generatePublic(ks);
Exception thrown #kf.generatePublic(ks).
Exception: java.security.InvalidKeyException: invalid key format
Below is the .crt file contents
-----BEGIN CERTIFICATE-----
MIIBpzCCAVECBEqbmP4wDQYJKoZIhvcNAQEEBQAwXTELMAkGA1UEBhMCVVMxDjAMBgNVBAgTBVRF
//trimmed key
-----END CERTIFICATE-----
I could not find what's wrong with my code. This key is used to RSA public encrypt a key (PBKDF2 key) in C code.
//openssl
RSA_public_encrypt(msgLen, msg, encryptedMsg, rsaPubKey, RSA_PKCS1_PADDING)
I am trying to implement it in Java. Am I missing anything? Please guide
UPDATE 1:
Overcame the exception using the below code:
InputStream inStream = null;
try {
inStream = RefundUtil.class.getClassLoader().getResourceAsStream("refund.crt");
CertificateFactory cf = CertificateFactory.getInstance("X.509");
X509Certificate cert = (X509Certificate) cf.generateCertificate(inStream);
PublicKey pubKey = cert.getPublicKey();
Cipher encryptCipher = Cipher.getInstance("RSA");
encryptCipher.init(Cipher.ENCRYPT_MODE, pubKey);
byte[] cipherText = encryptCipher.doFinal(sessionKey);
inStream.close();
return Base64.getEncoder().encodeToString(cipherText);
} catch (IOException e) {
LOGGER.error(e.getMessage());
}

RSA public key generated in Java is not valid in php

I'm creating a RSA key pair in Java and want to use it in PHP. Java code is as follows:
public static boolean keyGen() throws NoSuchAlgorithmException, IOException, OperatorCreationException, InvalidKeySpecException {
KeyPairGenerator kpGen = KeyPairGenerator.getInstance("RSA");
kpGen.initialize(2048, new SecureRandom());
KeyPair keyPair = kpGen.generateKeyPair();
PublicKey pub = keyPair.getPublic();
byte[] pubBytes = pub.getEncoded();
SubjectPublicKeyInfo spkInfo = SubjectPublicKeyInfo.getInstance(pubBytes);
ASN1Primitive primitive = spkInfo.parsePublicKey();
byte[] publicKeyPKCS1 = primitive.getEncoded();
PemObject pemObject = new PemObject("RSA PUBLIC KEY", publicKeyPKCS1);
StringWriter stringWriter = new StringWriter();
PemWriter pemWriter = new PemWriter(stringWriter);
pemWriter.writeObject(pemObject);
pemWriter.close();
String pemString = stringWriter.toString();
FileOutputStream fos2 = new FileOutputStream("pubk.key");
fos2.write(pemString.getBytes());
fos2.flush();
fos2.close();
}
The generated public key looks like follow:
-----BEGIN RSA PUBLIC KEY-----
MIIBCgKCAQEAh8cQcRitRdEIzcWDpgDhGTxU4e/4CnFcCi4pEi8Pitme4+9MlVOQ
EtwpiaH54nbxBLZX6m/Z0EETqE9hJm02L8cgvp6/T08atJ9NAayEkN5TFSgdmh3Y
CwGa0ckHlO1lzN3jghUTxLnYEHOvBXVaY1SpDEUlLUi6WKsyklqHK+r6fPa9X1sY
6847VPTQX8ORC13LEzdZrGSR39473HTBhR6SzyTET47AgHPy2Q+FMIvN7DeuX5dK
XtQUlvAjJ7KVQJIXuFEzNvHQfUzjJj+LO2MHX77KbGg6Ytz06CnsWS2f6YKBY3Bg
BQ2zqjE2ON1jDLUcika+2ihEzpfXFGLY9wIDAQAB
-----END RSA PUBLIC KEY-----
And I'm importing the saved key file using PHP as follows:
$keyString = file_get_contents($filePath);
openssl_pkey_get_public($keyString);
And when try to encrypt using openssl_public_encrypt it gives me the error
openssl_public_encrypt(): key parameter is not a valid public key
However I tried the same with a JavaScript generated key file and it works well. Any help?
The key evidently needs to be in SubjectPublicKeyInfo format, sometimes referred to as "X.509" format -- but not the same thing as an X.509 certificate -- just to add to the general sea of confusion. I got this info not from the documentation but from the user comments below.
Fortunately this takes even fewer lines of Java code to produce, as this little code fragment adapted from your code illustrates:
PublicKey pub = keyPair.getPublic();
byte[] pubBytes = pub.getEncoded();
PemObject pemObject = new PemObject("PUBLIC KEY", pubBytes);
StringWriter stringWriter = new StringWriter();
PemWriter pemWriter = new PemWriter(stringWriter);
pemWriter.writeObject(pemObject);
pemWriter.close();
System.out.println(stringWriter.toString());

How to read DER DSA private key to AsymmetricKeyParameter in bouncy castle (Java)

How to read DER file with private DSA key (4096 bit) into AsymmetricKeyParameter for usage in DSASigner ?
The following code I tried:
byte[] privateKeyBytes = FileUtils.readFileToByteArray(new File(
"sign-key-private.der"));
AsymmetricKeyParameter privateKey = PrivateKeyFactory
.createKey(privateKeyBytes);
Result is an exception:
java.lang.IllegalArgumentException: unknown object in getInstance: org.bouncycastle.asn1.ASN1Integer
at org.bouncycastle.asn1.ASN1Sequence.getInstance(Unknown Source)
at org.bouncycastle.asn1.x509.AlgorithmIdentifier.getInstance(Unknown Source)
at org.bouncycastle.asn1.pkcs.PrivateKeyInfo.<init>(Unknown Source)
at org.bouncycastle.asn1.pkcs.PrivateKeyInfo.getInstance(Unknown Source)
at org.bouncycastle.crypto.util.PrivateKeyFactory.createKey(Unknown Source)
at test.security.core.Program.main(Program.java:41)
byte[] privateKeyBytes = FileUtils.readFileToByteArray(new File("sign-key-private.der"));
KeyFactory kf = KeyFactory.getInstance("RSA", "BC");
PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(privateKeyBytes);
RSAPrivateKey rsaKey = (RSAPrivateKey) kf.generatePrivate(keySpec);
AsymmetricKeyParameter privateKeyParameter = new RSAKeyParameters(true, rsaKey.getModulus(), rsaKey.getPrivateExponent());
The workaround solution I have finally used was to convert key to PEM format and use the following:
#Cleanup
FileReader privateKeyReader = new FileReader(new File("key.pem"));
#Cleanup
PEMParser parser = new PEMParser(privateKeyReader);
PEMKeyPair keyPair = (PEMKeyPair) parser.readObject();
AsymmetricKeyParameter privateKey = PrivateKeyFactory
.createKey(keyPair.getPrivateKeyInfo());
AsymmetricKeyParameter publicKey = PublicKeyFactory
.createKey(keyPair.getPublicKeyInfo());

RSA encryption :InvalidKeyException: invalid key format

I have to read pem key files to get RSA Public key,and then use them to encrypt.
I can do this using openssl and convert pem file to der file.
and then load my key using X509EncodedKeySpec and PKCS8EncodedKeySpec.
But I don't want to do this because pem is the user key exchange format.
user can register it's own key can like this :
--BEGIN PUBLIC KEY-- MIGeMA0GCSqGSIb3DQEBAQUAA4GMADCBiAKBgGi0/vKrSIIQMOm4atiw+2s8tSojOKHsWJU3oPTm
b1a5UQIH7CM3NgtLvUF5DqhsP2jTqgYSsZSl+W2RtqCFTavZTWvmc0UsuK8tTzvnCXETsnpjeL13
Hul9JIpxZVej7b6KxgyxFAhuz2AGscvCXnepElkVh7oGOqkUKL7gZSD7AgMBAAE=
--END PUBLIC KEY--
and this key is store in a database in this format...
Here is the code I have tried..
File pubKeyFile=new File("D:/public_key.pem");
DataInputStream dis = new DataInputStream(new FileInputStream(pubKeyFile));
byte[] pubKeyBytes = new byte[(int)pubKeyFile.length()];
dis.readFully(pubKeyBytes);
dis.close();
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
X509EncodedKeySpec pubSpec = new X509EncodedKeySpec(pubKeyBytes);
RSAPublicKey pubKey = (RSAPublicKey) keyFactory.generatePublic(pubSpec);
I am getting exception as
java.security.spec.InvalidKeySpecException: java.security.InvalidKeyException: invalid key format
As I am completely new to encryption concepts can anyone please help me to solve this exception?
Many thanks.
With bouncycastle, it would be done this way:
CertificateFactory cf = CertificateFactory.getInstance("X509", "BC");
InputStream is = new FileInputStream("D:/public_key.pem");
X509Certificate certificate = (X509Certificate) cf.generateCertificate(is);
is.close();
RSAPublicKey pubKey = (RSAPublicKey)certificate.getPublicKey();
You were almost there, with the standard provider. You just need to strip the header and footer lines:
List<String> lines = Files.readAllLines(Paths.get(path), StandardCharsets.US_ASCII);
if (lines.size() < 2)
throw new IllegalArgumentException("Insufficient input");
if (!lines.remove(0).startsWith("--"))
throw new IllegalArgumentException("Expected header");
if (!lines.remove(lines.size() - 1).startsWith("--"))
throw new IllegalArgumentException("Expected footer");
byte[] raw = Base64.getDecoder().decode(String.join("", lines));
KeyFactory factory = KeyFactory.getInstance("RSA");
PublicKey pub = factory.generatePublic(new X509EncodedKeySpec(raw));
try using bouncycastele's PemReader .
PublicKey getPublicKey(String pubKeyStr) throws IOException, NoSuchAlgorithmException, InvalidKeySpecException {
PemObject pem = new PemReader(new StringReader(pubKeyStr)).readPemObject();
byte[] pubKeyBytes = pem.getContent();
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
X509EncodedKeySpec pubSpec = new X509EncodedKeySpec(pubKeyBytes);
RSAPublicKey pubKey = (RSAPublicKey) keyFactory.generatePublic(pubSpec);
return pubKey;
}

Categories

Resources