Java 加载加密私钥
Java load encrypted private key
我花了太长时间寻找可以加载由 openssl 证书创建自动生成的加密私钥的解决方案。
使用密码短语生成证书和新私钥:password
openssl req -newkey rsa:2048 -x509 -keyout test.key -out test.crt -days 365
我已经提取了代码的重要部分
package test;
import lombok.SneakyThrows;
import lombok.extern.log4j.Log4j2;
import org.bouncycastle.util.encoders.Base64;
import org.junit.jupiter.api.BeforeEach;
import javax.crypto.Cipher;
import javax.crypto.EncryptedPrivateKeyInfo;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.PBEKeySpec;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.security.AlgorithmParameters;
import java.security.Key;
import java.security.KeyFactory;
import java.security.PrivateKey;
import java.security.spec.KeySpec;
import java.util.stream.Collectors;
import java.util.stream.Stream;
@Log4j2
class pkShould {
private static final String PASS_PHRASE = "password";
@SneakyThrows
@BeforeEach
public void setup() {
ClassLoader cl = Thread.currentThread().getContextClassLoader();
Path pKPath = Paths.get(cl.getResource("keystore/test.key").toURI());
try(Stream<String> lines = Files.lines(pKPath)) {
String encrypted = lines.collect(Collectors.joining("\n"));
encrypted = encrypted.replace("-----BEGIN ENCRYPTED PRIVATE KEY-----", "");
encrypted = encrypted.replace("-----END ENCRYPTED PRIVATE KEY-----", "");
byte[] content = Base64.decode(encrypted);
EncryptedPrivateKeyInfo encryptPKInfo = new EncryptedPrivateKeyInfo(content);
Cipher cipher = Cipher.getInstance(encryptPKInfo.getAlgName());
PBEKeySpec pbeKeySpec = new PBEKeySpec(PASS_PHRASE.toCharArray());
SecretKeyFactory secFac = SecretKeyFactory.getInstance(encryptPKInfo.getAlgName());
Key pbeKey = secFac.generateSecret(pbeKeySpec);
AlgorithmParameters algParams = encryptPKInfo.getAlgParameters();
cipher.init(Cipher.DECRYPT_MODE, pbeKey, algParams);
KeySpec pkcs8KeySpec = encryptPKInfo.getKeySpec(cipher);
KeyFactory kf = KeyFactory.getInstance("RSA");
PrivateKey expectedPrivateKey = kf.generatePrivate(pkcs8KeySpec);
}
}
}
从未超过 EncryptedPrivateKeyInfo
,据我所知,私钥的格式正确并且在 keyStore 中使用它工作正常。
堆栈跟踪
java.io.IOException: ObjectIdentifier() -- data isn't an object ID (tag = 48)
at sun.security.util.ObjectIdentifier.<init>(ObjectIdentifier.java:285)
at sun.security.util.DerInputStream.getOID(DerInputStream.java:321)
at com.sun.crypto.provider.PBES2Parameters.engineInit(PBES2Parameters.java:267)
at java.security.AlgorithmParameters.init(AlgorithmParameters.java:293)
at sun.security.x509.AlgorithmId.decodeParams(AlgorithmId.java:150)
at sun.security.x509.AlgorithmId.<init>(AlgorithmId.java:132)
at sun.security.x509.AlgorithmId.parse(AlgorithmId.java:416)
at javax.crypto.EncryptedPrivateKeyInfo.<init>(EncryptedPrivateKeyInfo.java:95)
非常感谢任何帮助。
不幸的是,该错误毫无用处。它真正的意思是 'java did not like it'。它几乎可以表示任何内容:密钥受到 java 不喜欢的密码 and/or 位大小的保护,到密钥本身使用 cipher/bitsize java 不喜欢不像,密钥的格式不是 PKCS#8。
看起来您确实生成了 x509 格式的密钥,这可能行不通。也许转换它会起作用;试一试:
openssl pkcs8 -topk8 \
-inform PEM -outform PEM \
-in key.pem -out key-pkcs8.pem
我花了太长时间寻找可以加载由 openssl 证书创建自动生成的加密私钥的解决方案。
使用密码短语生成证书和新私钥:password
openssl req -newkey rsa:2048 -x509 -keyout test.key -out test.crt -days 365
我已经提取了代码的重要部分
package test;
import lombok.SneakyThrows;
import lombok.extern.log4j.Log4j2;
import org.bouncycastle.util.encoders.Base64;
import org.junit.jupiter.api.BeforeEach;
import javax.crypto.Cipher;
import javax.crypto.EncryptedPrivateKeyInfo;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.PBEKeySpec;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.security.AlgorithmParameters;
import java.security.Key;
import java.security.KeyFactory;
import java.security.PrivateKey;
import java.security.spec.KeySpec;
import java.util.stream.Collectors;
import java.util.stream.Stream;
@Log4j2
class pkShould {
private static final String PASS_PHRASE = "password";
@SneakyThrows
@BeforeEach
public void setup() {
ClassLoader cl = Thread.currentThread().getContextClassLoader();
Path pKPath = Paths.get(cl.getResource("keystore/test.key").toURI());
try(Stream<String> lines = Files.lines(pKPath)) {
String encrypted = lines.collect(Collectors.joining("\n"));
encrypted = encrypted.replace("-----BEGIN ENCRYPTED PRIVATE KEY-----", "");
encrypted = encrypted.replace("-----END ENCRYPTED PRIVATE KEY-----", "");
byte[] content = Base64.decode(encrypted);
EncryptedPrivateKeyInfo encryptPKInfo = new EncryptedPrivateKeyInfo(content);
Cipher cipher = Cipher.getInstance(encryptPKInfo.getAlgName());
PBEKeySpec pbeKeySpec = new PBEKeySpec(PASS_PHRASE.toCharArray());
SecretKeyFactory secFac = SecretKeyFactory.getInstance(encryptPKInfo.getAlgName());
Key pbeKey = secFac.generateSecret(pbeKeySpec);
AlgorithmParameters algParams = encryptPKInfo.getAlgParameters();
cipher.init(Cipher.DECRYPT_MODE, pbeKey, algParams);
KeySpec pkcs8KeySpec = encryptPKInfo.getKeySpec(cipher);
KeyFactory kf = KeyFactory.getInstance("RSA");
PrivateKey expectedPrivateKey = kf.generatePrivate(pkcs8KeySpec);
}
}
}
从未超过 EncryptedPrivateKeyInfo
,据我所知,私钥的格式正确并且在 keyStore 中使用它工作正常。
堆栈跟踪
java.io.IOException: ObjectIdentifier() -- data isn't an object ID (tag = 48)
at sun.security.util.ObjectIdentifier.<init>(ObjectIdentifier.java:285)
at sun.security.util.DerInputStream.getOID(DerInputStream.java:321)
at com.sun.crypto.provider.PBES2Parameters.engineInit(PBES2Parameters.java:267)
at java.security.AlgorithmParameters.init(AlgorithmParameters.java:293)
at sun.security.x509.AlgorithmId.decodeParams(AlgorithmId.java:150)
at sun.security.x509.AlgorithmId.<init>(AlgorithmId.java:132)
at sun.security.x509.AlgorithmId.parse(AlgorithmId.java:416)
at javax.crypto.EncryptedPrivateKeyInfo.<init>(EncryptedPrivateKeyInfo.java:95)
非常感谢任何帮助。
不幸的是,该错误毫无用处。它真正的意思是 'java did not like it'。它几乎可以表示任何内容:密钥受到 java 不喜欢的密码 and/or 位大小的保护,到密钥本身使用 cipher/bitsize java 不喜欢不像,密钥的格式不是 PKCS#8。
看起来您确实生成了 x509 格式的密钥,这可能行不通。也许转换它会起作用;试一试:
openssl pkcs8 -topk8 \
-inform PEM -outform PEM \
-in key.pem -out key-pkcs8.pem