is PKCS8EncodedKeySpec capable to read both PKCS1 and PKCS8 private key - java

Although the title is a question but I just managed to do this with the same code, while I am just not sure whether PKCS8EncodedKeySpec is designed to do this job, or my private key is generated by accident to make this work(key generated by openssl).
my code(pemPath is pem type private key file path):
try (BufferedReader bufferedReader = new BufferedReader(new FileReader(pemPath))) {
StringBuilder stringBuilder = new StringBuilder();
String line;
while ((line = bufferedReader.readLine()) != null) {
if (!line.startsWith("--")) {
stringBuilder.append(line);
}
}
PKCS8EncodedKeySpec priPKCS8 = new PKCS8EncodedKeySpec(
Base64.getDecoder().decode(stringBuilder.toString()));
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
PrivateKey key = keyFactory.generatePrivate(priPKCS8);
}
And also I paste PKCS1 file content:
-----BEGIN RSA PRIVATE KEY-----
MIIEpAIBAAKCAQEAoRVeLT5PrbQmFbmbc1zLFJuz5Sx3yTc9IIem13/+gNcrdqqa
QVd/2noPmIm1xUkdQfvRm72k0Mm1s78bcadTsZt4XL2OvAKBA0hyox2re/PLLp05
NP2WKFyF+O2OteZhzQHPxQFBn/Nt1pYbYctV7bbw4RsdQXXz72TY+WBfIg6m/LeG
uPG/4UM5IAw9G2IEOkA/V00rsjOLzRvHyqu473zaFNbaObN9rnakCUFeU07L3Eeo
EBQoZPiIyTAJ8eN/EnaudLrvErOog2E4LcpAOpoUDBdi2XYT0iE0stDoj62zP+gL
ubZQKV81N0qk1KehxeLcHtpXtvlWaITnmIovVQIDAQABAoIBAFw/W2Z3h7PHNgQ8
/cvr+RS9MiFs/NBLhQMLDD3fO8VW87oKazo+PKbGPgYx3tmzTEEMT/ZrfWZgDWF5
cOL+WwycJyqdF4+Ns4pIw/WruRfL/rCcMzWof4Rvr/1lNdPvslRv1CdS190cz+sS
nW28v2HZ4UpYd8GUJfUTgLoXOYPLjYEQx8wri5tOPvAJuCFHCdpx59Fu0xaQP+Uz
3+CSAqdsBL4UKoz0lQ27128BEg/2a6kqhGvC/QHu+Mn0N4wbto8ndfpF8noSAhx2
s38q/E9gVYxKjA1g2yl74irPsPWT+gq97nQJ4jYRog2W4I+KYYDAL9xP3ux+kGis
6h1GWcECgYEA1Bh/EgwlamT+y5oJhZgYEQAFtCZEOjyjWuJRwYTuaKrTJjudk0xZ
KPsGy8+Wi3QYsGUowAsQNws+3hzD1dIqWO92CXgkaJ1iZ3mVMsR+xgdb67jFrzZM
PerqXK3wOlaDe/Mikfyqcp9KERuSVKi/XMv7G/1ZaYk4/SPElqcXy1ECgYEAwm2Z
1Wy/E0uQ8Aj7x1nujCUQjvmTWhkU2aHW/1+STjERfXv5XdaR2N6tFSpWRRHAezHG
5b1NmskNKHCtYAdWFuZC2TXUoCVpnhZnS5gAf1H+konKjeknlLgYIZDB59hzMmCE
uOGEHk/rtZQuB4nR0jYk1eE14IOCQe6j73EsmsUCgYEAoINBd6kVj+WLJw8WcbJf
VE5OAr6LF//YKOnqsagmvbO6RM8NO/Kl72u7AvfBmRxtquGD64Lz7JRoKbRfSSza
u5/OFvCDrWCenmzXSyqGPtxG5qhZg3Z2UM2+PBGvIpdivqWM3ir32/NNHJFfNw7W
dCYzjkU4K7ScGoe9Ob6PNWECgYBrm514sidO1pPxRgeT3gJZLmprt1YGl7sieKA1
1v9yp1W2zdbGSOuPzC6feD8nGxwdEv+yR4OcF4pgx3wtmeHb6rU04sY7nHlINb4V
6Jrd3NO45upkgJaXiQxSB3xKhVG8oA7VBHvLCxC5/rk7Etw+LBlXBr569E4zj5DM
BSdawQKBgQC55RdlSLarKyEF9bMVPQDQ0Qko6pS+pw2kmg2CMXhk7eBsTUAMuVh4
/FNu3h6QiGpHstV1NRmF9oPRTltd8Mh3aCy8JAOY9/hZ7NScxKy2j91jQl+geSOC
FPSvfPlyMwPDvR3urCQKYq3NMJ4jWqcle4YX0w/rG5yY05gpQNVWiQ==
-----END RSA PRIVATE KEY-----
and PKCS8 file content:
-----BEGIN PRIVATE KEY-----
MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQChFV4tPk+ttCYV
uZtzXMsUm7PlLHfJNz0gh6bXf/6A1yt2qppBV3/aeg+YibXFSR1B+9GbvaTQybWz
vxtxp1Oxm3hcvY68AoEDSHKjHat788sunTk0/ZYoXIX47Y615mHNAc/FAUGf823W
lhthy1XttvDhGx1BdfPvZNj5YF8iDqb8t4a48b/hQzkgDD0bYgQ6QD9XTSuyM4vN
G8fKq7jvfNoU1to5s32udqQJQV5TTsvcR6gQFChk+IjJMAnx438Sdq50uu8Ss6iD
YTgtykA6mhQMF2LZdhPSITSy0OiPrbM/6Au5tlApXzU3SqTUp6HF4twe2le2+VZo
hOeYii9VAgMBAAECggEAXD9bZneHs8c2BDz9y+v5FL0yIWz80EuFAwsMPd87xVbz
ugprOj48psY+BjHe2bNMQQxP9mt9ZmANYXlw4v5bDJwnKp0Xj42zikjD9au5F8v+
sJwzNah/hG+v/WU10++yVG/UJ1LX3RzP6xKdbby/YdnhSlh3wZQl9ROAuhc5g8uN
gRDHzCuLm04+8Am4IUcJ2nHn0W7TFpA/5TPf4JICp2wEvhQqjPSVDbvXbwESD/Zr
qSqEa8L9Ae74yfQ3jBu2jyd1+kXyehICHHazfyr8T2BVjEqMDWDbKXviKs+w9ZP6
Cr3udAniNhGiDZbgj4phgMAv3E/e7H6QaKzqHUZZwQKBgQDUGH8SDCVqZP7LmgmF
mBgRAAW0JkQ6PKNa4lHBhO5oqtMmO52TTFko+wbLz5aLdBiwZSjACxA3Cz7eHMPV
0ipY73YJeCRonWJneZUyxH7GB1vruMWvNkw96upcrfA6VoN78yKR/Kpyn0oRG5JU
qL9cy/sb/VlpiTj9I8SWpxfLUQKBgQDCbZnVbL8TS5DwCPvHWe6MJRCO+ZNaGRTZ
odb/X5JOMRF9e/ld1pHY3q0VKlZFEcB7McblvU2ayQ0ocK1gB1YW5kLZNdSgJWme
FmdLmAB/Uf6SicqN6SeUuBghkMHn2HMyYIS44YQeT+u1lC4HidHSNiTV4TXgg4JB
7qPvcSyaxQKBgQCgg0F3qRWP5YsnDxZxsl9UTk4CvosX/9go6eqxqCa9s7pEzw07
8qXva7sC98GZHG2q4YPrgvPslGgptF9JLNq7n84W8IOtYJ6ebNdLKoY+3EbmqFmD
dnZQzb48Ea8il2K+pYzeKvfb800ckV83DtZ0JjOORTgrtJwah705vo81YQKBgGub
nXiyJ07Wk/FGB5PeAlkuamu3VgaXuyJ4oDXW/3KnVbbN1sZI64/MLp94PycbHB0S
/7JHg5wXimDHfC2Z4dvqtTTixjuceUg1vhXomt3c07jm6mSAlpeJDFIHfEqFUbyg
DtUEe8sLELn+uTsS3D4sGVcGvnr0TjOPkMwFJ1rBAoGBALnlF2VItqsrIQX1sxU9
ANDRCSjqlL6nDaSaDYIxeGTt4GxNQAy5WHj8U27eHpCIakey1XU1GYX2g9FOW13w
yHdoLLwkA5j3+Fns1JzErLaP3WNCX6B5I4IU9K98+XIzA8O9He6sJApirc0wniNa
pyV7hhfTD+sbnJjTmClA1VaJ
-----END PRIVATE KEY-----
By the way, both private keys succeed to decrypt the same cipher text.
And the openssl command:
openssl genrsa -out rsa_private_key_2048.pem 2048
openssl pkcs8 -topk8 -in rsa_private_key_2048.pem -out pkcs8_rsa_private_key_2048.pem -nocrypt

What if the private key in PEM format(PKCS#1 format)string being passed in a json payload input. PKCS8EncodedKeySpec is currently working for both PKCS#1 and PKCS#8. The provider is SunRsaSign.

Related

Convert elliptic curve private key to (unencrypted) PKCS#8 format

I am trying to convert EC private key
-----BEGIN EC PRIVATE KEY-----
MHcCAQEEIE2tzb8O0gBVw2IFOB/B8l1Ztjax3ut4DeNtuC3UMmZ6oAoGCCqGSM49
AwEHoUQDQgAEayT6Tv8zZlpIUOKHEYnmsKZyTaqOHajL0InS4c5tK4fhkHZDSWUa
3tPl1ibIXt0LvaxHk47h0Tc4SGr3Ex8Bhg==
-----END EC PRIVATE KEY-----
to Private Key
-----BEGIN PRIVATE KEY-----
MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgTa3Nvw7SAFXDYgU4
H8HyXVm2NrHe63gN4224LdQyZnqhRANCAARrJPpO/zNmWkhQ4ocRieawpnJNqo4d
qMvQidLhzm0rh+GQdkNJZRre0+XWJshe3Qu9rEeTjuHRNzhIavcTHwGG
-----END PRIVATE KEY-----
It's very easy when you execute openSsl command like this:
openssl pkcs8 -topk8 -nocrypt -in ec1.pem -out ec2.pem
But i want to do this in Java way and didn't find any solution (tried so many from stackoverflow).
So i have for now following class:
ECNamedCurveParameterSpec ecNamedCurveParameterSpec = ECNamedCurveTable.getParameterSpec("prime256v1");
KeyPairGenerator keyPair = KeyPairGenerator.getInstance("ECDSA", "BC");
// Create a secure random number generator using the SHA1PRNG algorithm
SecureRandom secureRandomGenerator = SecureRandom.getInstance("SHA1PRNG");
keyPair.initialize(ecNamedCurveParameterSpec, secureRandomGenerator);
Then i generate KeyPair and get PrivateKey in ECPrivateKey Object:
KeyPair pair =keyPair.generateKeyPair();
ECPrivateKey privateKey = (ECPrivateKey) pair.getPrivate();
StringWriter sw = new StringWriter();
try (JcaPEMWriter jcaPEMWriter = new JcaPEMWriter(sw);) {
jcaPEMWriter.writeObject(privateKey);
}
String pemFormat = sw.toString();
This string pemFormat is actually PEM format that starts with BEGIN EC PRIVATE KEY
How can i convert it just to BEGIN PRIVATE KEY?
I assume that should be a way if openSsl can do it.
A conversion from the SEC1/PEM (-----BEGIN EC PRIVATE KEY-----...) to the PKCS#8/PEM format (-----BEGIN PRIVATE KEY-----...) is not needed at all, because privateKey.getEncoded() returns the key already in PKCS#8 format. So it only needs to be exported as PEM e.g. with a PemWriter:
import org.bouncycastle.util.io.pem.PemWriter;
...
// Your code
Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider());
...
ECPrivateKey privateKey = (ECPrivateKey)pair.getPrivate();
System.out.println(privateKey.getFormat()); // PKCS#8
// Export as PKCS#8 PEM encoded key via PemWriter
StringWriter stringWriter = new StringWriter();
try (PemWriter pemWriter = new PemWriter(stringWriter)){
pemWriter.writeObject((PemObjectGenerator)new PemObject("PRIVATE KEY", privateKey.getEncoded()));
}
String pkcs8PEM = stringWriter.toString();
System.out.println(pkcs8PEM); // -----BEGIN PRIVATE KEY-----MIGTAg...-----END PRIVATE KEY-----
You can check the format in an ASN.1 parser, e.g. https://lapo.it/asn1js.
However, if you are really looking for an explicit conversion of a SEC1/PEM key into a PKCS#8/PEM key, then the import of a SEC1/PEM key is described e.g. here. The imported key can then be exported as a PKCS#8/PEM key using a PemWriter as in the example above.

Bouncycastle can't generate private key - Unknown KeySpec type: java.security.spec.X509EncodedKeySpec

I can't generate private key with bouncycastle due to Unknown KeySpec type: java.security.spec.X509EncodedKeySpec. (However doing same for public key doesn't throw exception and works - why?)
java.security.spec.InvalidKeySpecException: Unknown KeySpec type:
java.security.spec.X509EncodedKeySpec at
org.bouncycastle.jcajce.provider.asymmetric.rsa.KeyFactorySpi.engineGeneratePrivate(Unknown
Source) at
java.security.KeyFactory.generatePrivate(KeyFactory.java:366)
PemReader pemReader = new PemReader(new InputStreamReader(new FileInputStream("private_unencrypted.pem")));
PemObject pemObject = pemReader.readPemObject();
pemReader.close();
KeyFactory keyFactory = KeyFactory.getInstance("RSA", "BC");
byte[] privateKeyBytes = pemObject.getContent();
X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(privateKeyBytes);
PrivateKey privateKey = keyFactory.generatePrivate(x509KeySpec);
For RSA private keys you should be using PKCS8EncodedKeySpec if your key is encoded in PKCS8 format. PKCS8 format usually looks like :
-----BEGIN PRIVATE KEY-----
base64 encoded der key
-----END PRIVATE KEY-----
If your key is in PKCS1 format and looks like :
-----BEGIN RSA RIVATE KEY-----
base64 der encoded key
-----END RSA PRIVATE KEY-----
you should first convert it to PKCS8 format and then use the class mentioned above.
However doing same for public key doesn't throw exception and works - why?
Because public keys, which are usually part of Certificates, are encoded in X509 format, however private keys are usually encoded in PKCS format.

Converting a string private key to PrivateKey type

I am having below RSA private key in string format.
String privatekey = -----BEGIN RSA PRIVATE KEY-----
MIIEpAIBAAKCAQEAqAKCCMKqboM8ywSuNvmf2zuT0e2elxntdEe5msv22jzT89Xa
1Q/V4CeQdZruIw8eTAMa67Dej+3cPdSrjdDnfxcb9L14U9oFPgOyvxVwb+/S8jqm
F9o7Gvm85X972C8izh+K4ndpPtztxkZ0g7cu7RqrCCBzw5SUfi3pgIpprdiKlVDP
4lF7CTwzRH+oi+BxwOABEiuKOJtjOXX1WJhV6ukEy8K6Fq/QOyt/7vgxkm8I8HMo
SMq2UZNswn5/9SqMWuaTBaQbjZ2f77zaq5X/jOiCThTxFNPjPnzhKhG8ekaqIUpB
y9VuICFgdtVQimnlDykrdJWyeOFWPjYl5vehkwIDAQABAoIBAQCN2Ig2ozvHUA/s
i8gWbAyVyKgVrhueEOrUqJXAZoHEYWTFUgGOru7wcBbb4/E4MlRu8pQw90QAml6+
6SXp9rzsJPOaXrkPelvArtij0ZL7PqyHjBKcwsfyD3V3AXnq3GjzQ9g7OXvm8hnh
s6w9ZFQ/JKvPka6LKo9wNI0W1EVC2tggN0Jt6YJFU7trb5TtiQm/B4NKpflZ7PsC
1WOttz0q+VSzF/p04+33OLXugF1crgMr9KCg0uSPi5zCcM+3RVSWDrcZoh+yV4pK
+g5XKKw/BQD9vrUzsLMDjupp4Is0sSEXwMQeRbUZRnUOWVO7E7jrawzhGXV6v4ZT
3PoxB7CxAoGBANkK9ITnfIr1AlF8S1Ok12AlHLYvCPG4TVBw4WNVUX1y3wBXpOmx
t5S2wGpTmyf3LBpw/0m+5EzoghjSb2QnIRFveAxuhxPCPNqxvyzm2D7ycaGJX41y
RfsxvWVQpzvCVH4yV+tkH107ivR2uFDtbDjqlydPyIxmA1Frlm87CODpAoGBAMYq
gLO5EEKxs1MlCzZkuqsEAq+kZVX7y3Kw9rzCJtRQKfYu0IlNFudPg3KpqcbQsrfR
1Psl6iTLXtLe+92NXDOcc9rfj9crmAKmZA1llXOwxe4FOrLWbxk+i6V3qJ2qrf+I
Dwc9+Xrc6ydcDtTHAi3JeIReEbDMvFc6JRiyjwEbAoGAeH68gYyCeCLNxq9aonVB
nP79kadLL+dCBQamGp+jPiIn6+i8hYFEiitrZ5xC500yDvvsvuRbmtb6Yw1xCgkv
Mp7P5xb1puKPJlrH6AXAyDGRJD0/7ych8vMKUtUUAvlAL0+DwAs13mzQGChQ65zk
GDUk9Y41qLx52xn/yoDbzQECgYEAksM9qF1iPpLPBcAEqtc1LJz+xEiTyHeAOMP5
KNj92vY37ZzEUzulv9AywQQIujcsdVlRTGPLIk8APlpo3K/p3kt7vlkedbRSk3vZ
09YtNo5wOJTk4ThQ9bhNwlF5rrOOxBZnUuzCTQ06l17lmQ5+fZydxiLJJVCsGEn2
2XC82osCgYB9maZnLrSZ3Xq4X256/H+Et8TcgqOZGbLuGkNzheheP/E5LcUhQqbP
oJRB24XoX+yw+Do5q2pHHgbrrHwcdg3Xfw9sb5P2JNbtG57mO7QEilIHfUQzQl/U
XSKgJJZ/9bTPlbZmp9ChM9izUv8DI5vjhDputhlEHP4BpHBN03a85Q==
-----END RSA PRIVATE KEY-----
I am trying to convert this to PrivateKey type using below code snippet-
public PrivateKey generatePrivateKey(String privateKey) throws Exception{
privateKey = privateKey.replace("-----BEGIN RSA PRIVATE KEY-----", "");
privateKey = privateKey.replace("-----END RSA PRIVATE KEY-----", "");
privateKey = privateKey.replaceAll("\\s+", "");
PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(privateKey.getBytes());
KeyFactory kf = KeyFactory.getInstance("RSA");
return kf.generatePrivate(keySpec);
}
I am getting below error -
It is giving me an error on generatePrivate method.
Execution exception[[InvalidKeySpecException: java.security.InvalidKeyException: invalid key format]]
Tried using the answer here Java: Convert DKIM private key from RSA to DER for JavaMail
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Base64;
public class pkcs1ToPkcs8 {
public static void main(String[] args) throws IOException {
String pkcs1 = //privatekey provided above
// b64 now contains the base64 "body" of the PEM-PKCS#1 file
byte[] oldder = Base64.getDecoder().decode(pkcs1.getBytes());
// concatenate the mostly-fixed prefix plus the PKCS#1 data
final byte[] prefix = {0x30,(byte)0x82,0,0, 2,1,0, // SEQUENCE(lenTBD) and version INTEGER
0x30,0x0d, 6,9,0x2a,(byte)0x86,0x48,(byte)0x86,(byte)0xf7,0x0d,1,1,1, 5,0, // AlgID for rsaEncryption,NULL
4,(byte)0x82,0,0 }; // OCTETSTRING(lenTBD)
byte[] newder = new byte [prefix.length + oldder.length];
System.arraycopy (prefix,0, newder,0, prefix.length);
System.arraycopy (oldder,0, newder,prefix.length, oldder.length);
// and patch the (variable) lengths to be correct
int len = oldder.length, loc = prefix.length-2;
newder[loc] = (byte)(len>>8); newder[loc+1] = (byte)len;
len = newder.length-4; loc = 2;
newder[loc] = (byte)(len>>8); newder[loc+1] = (byte)len;
FileOutputStream fo = new FileOutputStream ("pkcs8_file");
fo.write (newder); fo.close();
System.out.println ("converted length " + newder.length);
}
}
BEGIN RSA PRIVATE KEY means your key is pkcs#1 format and not pkcs#8. Reading pkcs#1 keys is not natively supported by Java. You need to use bouncycastle library ( see Read RSA private key of format PKCS1 in JAVA )or use any of these solutions Getting RSA private key from PEM BASE64 Encoded private key file
if your key were pkcs#8, it would have the header BEGIN PRIVATE KEY. In that case, for your code to work correctly you would need additionally decode the key content from base64
To convert a pkcs#1 key to pkcs#8 you can use openssl
openssl pkcs8 -topk8 -inform PEM -outform PEM -nocrypt -in pkcs1.key -out pkcs8.key

Java and Openssl generates different length of public keys for same private key

I used java to generate public key out of private key as follows,
Security.addProvider(new BouncyCastleProvider());
KeyPairGenerator kpg = KeyPairGenerator.getInstance("RSA", "BC");
kpg.initialize(2048);
KeyPair kp = kpg.generateKeyPair();
PrivateKey priv = kp.getPrivate();
RSAPrivateCrtKey rsaCrtKey = (RSAPrivateCrtKey) priv;
RSAPublicKeySpec keyspecPublic = new RSAPublicKeySpec(rsaCrtKey.getModulus(), rsaCrtKey.getPublicExponent());
KeyFactory kf = KeyFactory.getInstance("RSA");
PublicKey publicKey2 = kf.generatePublic(keyspecPublic);
String publicString = Base64.getMimeEncoder().encodeToString(publicKey2.getEncoded());
StringBuilder sb = new StringBuilder("");
sb.append("\"-----BEGIN PUBLIC KEY-----\\n")
.append(publicString)
.append("\\n-----END PUBLIC KEY-----");
And I generate public key using openssl as follows for same private key,
openssl rsa -in private.key -pubout -out public.key
But above two methods generate different lengths of strings as public key. Am I doing something wrong here?
public key from java code:
-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA6UkqbaGp7wOx2vrtqxmX/22ixKZcZPfZ
xXAawIst+AsWyNS+99MxnilstLIBKd6BCzJJsAa2I0ks43mnNZbkx1f1um+tQpXuTMbTh5MRprPn
jmX6aF+JXJbXATKhabTIQcCdpnrMi6scp9nWYkFdxVMfvo1gyThzfPwPgCO4eRFo1IkwZuergkl7
e0+U7WonqzFEb0joy5P78U+K8HebDW7nbS8zliq3DH2FI9yvEK3LeEN+Sa5icMWlERGv+7FCJVIH
CjBYfzaRZD9qqld/AnAEkCVt38SfSqWJECsnJYUW90WuFd8IxUVPS0TMfFMQhJFMT3eGweBOUb/b
pDm/hQIDAQAB
-----END PUBLIC KEY-----
Public key from openssl :
-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA6UkqbaGp7wOx2vrtqxmX
/22ixKZcZPfZxXAawIst+AsWyNS+99MxnilstLIBKd6BCzJJsAa2I0ks43mnNZbk
x1f1um+tQpXuTMbTh5MRprPnjmX6aF+JXJbXATKhabTIQcCdpnrMi6scp9nWYkFd
xVMfvo1gyThzfPwPgCO4eRFo1IkwZuergkl7e0+U7WonqzFEb0joy5P78U+K8Heb
DW7nbS8zliq3DH2FI9yvEK3LeEN+Sa5icMWlERGv+7FCJVIHCjBYfzaRZD9qqld/
AnAEkCVt38SfSqWJECsnJYUW90WuFd8IxUVPS0TMfFMQhJFMT3eGweBOUb/bpDm/
hQIDAQAB
-----END PUBLIC KEY-----
The keys are identical, and will decode to the same byte content.
Formatting-wise, the Java one is wrapped at 76 columns and the OpenSSL one is wrapped at 64 columns.
If you want to make the wrapping consistent, use the Base64.getMimeEncoder(int lineLength, byte[] lineSeparator) overloaded method that lets you specify the line length and pass 64 as the lineLength parameter.
Base64.getMimeEncoder(64, new byte[] {'\r', '\n'});

Read encrypted PKCS8 SpongyCastle Java

I am following the code in: https://stackoverflow.com/a/18161536/1753951 but I am getting an Exception in the following line:
FileInputStream fis = new FileInputStream(priv);
DataInputStream dis = new DataInputStream(fis);
byte[] keyBytes = new byte[(int)priv.length()];
dis.readFully(keyBytes);
dis.close();
javax.crypto.EncryptedPrivateKeyInfo encryptPKInfo = new EncryptedPrivateKeyInfo(keyBytes);
//Exception:
org.apache.harmony.security.asn1.ASN1Exception: Wrong content length
I am trying to read a .key/.pem PKCS8 file which is:
-----BEGIN RSA PRIVATE KEY-----
Proc-Type: 4,ENCRYPTED
DEK Info: AES-256-CBC,8AFF348907C84F2F6370A216DC0D55D9
1VIjJD3dZ5/wYnIm0mtp8d22RC24yGcY9LXgeHUDbyPJQa8PjupubFqKrpOodvQx
dPfE1F3XeY8oVG42ZfR4287X4V16n++BQCeDiuvyrwacLMAuQz6PFLT4b/Py89Cm
761UZpaWnH0PHfJqB9CHqC+pGAGfRF5vj7UtdNchCwBmo+7gvU5iGyYXNRJ/hPnU
V+8QDzro4kFIMOlDzHaJ3KN1Ftbb9LDjDNE/NShbRrAFAWJMZSY/ZjF8mfqggkoZ
%%%%% SKIPPED MOST OF IT %%%%%%%%%%
BMIl0y5XVgPwkApA30EdgV4YAZEJ+wQLnYIZfCklqzvCfyjxHFViVW6d41WNm8bx
wl28v4QJKlnf7KNcmmGwSmjKo7BEASSZ+XVYRu0R6FaE+Job5YzPrtUI+p/kf7et
Y+jUDbZ4BPvB8j2ZscNRs+pJkEXxPt5JKW/oQMQZPlbTtSV5K1IqiuVcRi9TbCzk
nWDSfI/wxt6cK3X9XvyOpOZDCDPchkIhDhCzfitd7fzkM1VBekwsliJwjgc1bwbc
nI4AhQcNb8li7oX1M2osyeR3zF25BDb2A04Zm1lMrWkFrypb24DKkSJxYEH33Gpu
-----END RSA PRIVATE KEY-----
After looking long time for a solution I stumbled with a library that helps me and works on android.
Not-Yet-Commons
http://juliusdavies.ca/commons-ssl/
FileInputStream in = new FileInputStream( "/path/to/pkcs8_private_key.der" );
PKCS8Key pkcs8 = new PKCS8Key( in, "changeit".toCharArray() );
byte[] decrypted = pkcs8.getDecryptedBytes();
PKCS8EncodedKeySpec spec = new PKCS8EncodedKeySpec( decrypted );
// A Java PrivateKey object is born.
PrivateKey pk = null;
if ( pkcs8.isDSA() )
{
pk = KeyFactory.getInstance( "DSA" ).generatePrivate( spec );
}
else if ( pkcs8.isRSA() )
{
pk = KeyFactory.getInstance( "RSA" ).generatePrivate( spec );
}
// For lazier types (like me):
pk = pkcs8.getPrivateKey();
javax.crypto.EncryptedPrivateKeyInfo expects a DER-encoded input, while the contents of your file are obviously in the PEM encoding.
The relation between PEM and DER is this:
The DER is the actual ASN.1-encoded data as a sequence of bytes.
The PEM is text-based with all these -----BEGIN SOMETHING----- and -----END SOMETHING----- headers and Base64-encoded data inside. Basically, PEM is header+Base64(DER)+footer.
You need to convert your key into DER format, for example using the OpenSSL pkey command:
openssl pkey -in key.pem -outform DER -out key.der

Categories

Resources