Reputation: 4727
I have a RSA public key (2048 bit) generated by a HSM, that key has been saved in a file (with a size of 256 byte) and is encoded as DER.
Is it possibile to programmatically create a self-signed certificate using JDK API (without BouncyCastle) starting from that file?
I'm stuck with the first step, because I'm trying to load the key file to create a PublicKey object:
import java.io.FileInputStream;
import java.security.KeyFactory;
import java.security.PublicKey;
import java.security.spec.PKCS8EncodedKeySpec;
import org.apache.commons.io.IOUtils;
public class Crypto {
public static void main(String[] args) throws Exception {
byte[] byteArray = IOUtils.toByteArray(new FileInputStream("/tmp/pub.key"));
PKCS8EncodedKeySpec spec = new PKCS8EncodedKeySpec(byteArray);
KeyFactory kf = KeyFactory.getInstance("RSA");
PublicKey pub = kf.generatePublic(spec);
....
}
}
but I get this exception:
Exception in thread "main" java.security.spec.InvalidKeySpecException: Only RSAPublicKeySpec and X509EncodedKeySpec supported for RSA public keys
at sun.security.rsa.RSAKeyFactory.generatePublic(RSAKeyFactory.java:289)
at sun.security.rsa.RSAKeyFactory.engineGeneratePublic(RSAKeyFactory.java:184)
at java.security.KeyFactory.generatePublic(KeyFactory.java:304)
at org.alex.Crypto.main(Crypto.java:17)
Is there a way to do that?
Upvotes: 1
Views: 3413
Reputation: 94058
Use X509EncodedKeySpec
(which internally actually used PKCS#1 encoding for RSA keys) instead. Keep the rest of the code identical. PKCS#8 is for private keys, not public keys (because it uses the PKCS#8 internal structure required to wrap a key with another key, and wrapping public keys makes no sense).
Upvotes: 2
Reputation: 22376
The exception is telling you the issue! => Only RSAPublicKeySpec and X509EncodedKeySpec supported for RSA public keys
You are trying to use PKCS8EncodedKeySpec
, which is not supported, create RSAPublicKeySpec
or X509EncodedKeySpec
class
Example
Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider());
byte[] input = new byte[] { (byte) 0xbe, (byte) 0xef };
Cipher cipher = Cipher.getInstance("RSA/None/NoPadding", "BC");
KeyFactory keyFactory = KeyFactory.getInstance("RSA", "BC");
RSAPublicKeySpec pubKeySpec = new RSAPublicKeySpec(new BigInteger(
"12345678", 16), new BigInteger("11", 16));
RSAPrivateKeySpec privKeySpec = new RSAPrivateKeySpec(new BigInteger(
"12345678", 16), new BigInteger("12345678",
16));
RSAPublicKey pubKey = (RSAPublicKey) keyFactory.generatePublic(pubKeySpec);
RSAPrivateKey privKey = (RSAPrivateKey) keyFactory.generatePrivate(privKeySpec);
cipher.init(Cipher.ENCRYPT_MODE, pubKey);
Upvotes: 0