【发布时间】:2018-02-23 10:55:29
【问题描述】:
在命令行中,我可以使用 openssl 加密和解密我的文件,如下所示:
创建密钥:
openssl req -x509 -newkey rsa:2048 -keyout myKey.key -out myKey.crt -pubkey
加密:
cat myText.txt | openssl rsautl -encrypt -inkey myKey.crt -pubin >> encryptedtxt.enc
解密:
openssl rsautl -decrypt -inkey myKey.key -in encryptedtxt.enc > decryptedtxt.txt
我关注了this tutorial
public static void main(String[] args) {
String encryptedData = "..\\encryptedtxt.enc";
File encryptedFIle = new File(encryptedData);
try {
byte[] data = Files.readAllBytes(encryptedFIle.toPath());
PrivateKey privateKey = getPrivateKey();
Cipher cipher = Cipher.getInstance("RSA");
cipher.init(Cipher.DECRYPT_MODE, privateKey);
byte[] decryptedData = cipher.doFinal(data);
System.out.println(">" + new String(decryptedData));
} catch (Exception e) {
e.printStackTrace();
}
}
private static PrivateKey getPrivateKey() {
String privateKeyFilename = "\\myKey.key";
FileInputStream fis = null;
ObjectInputStream ois = null;
File privateKeyFile = new File(privateKeyFilename);
try {
fis = new FileInputStream(privateKeyFile);
ois = new ObjectInputStream(fis);
BigInteger modulus = (BigInteger) ois.readObject();
BigInteger exponent = (BigInteger) ois.readObject();
RSAPrivateKeySpec rsaPrivateKeySpec = new RSAPrivateKeySpec(modulus, exponent);
KeyFactory fact = KeyFactory.getInstance("RSA");
PrivateKey privateKey = fact.generatePrivate(rsaPrivateKeySpec);
return privateKey;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
运行时会出现以下问题:
java.io.StreamCorruptedException: invalid stream header: 2D2D2D2D
at java.io.ObjectInputStream.readStreamHeader(ObjectInputStream.java:857)
at java.io.ObjectInputStream.<init>(ObjectInputStream.java:349)
at Decryptor.getPrivateKey(TestClass.java:38)
at Decryptor.main(TestClass.java:20)
java.security.InvalidKeyException: No installed provider supports this key: (null)
at javax.crypto.Cipher.chooseProvider(Cipher.java:893)
at javax.crypto.Cipher.init(Cipher.java:1249)
at javax.crypto.Cipher.init(Cipher.java:1186)
at Decryptor.main(TestClass.java:22)
请问有什么建议可以解决这个问题吗?
更新:
我修改了获取私钥的方法如下:
private static PrivateKey getPrivateKey() {
String privateKeyFilename = "myKey.key";
FileInputStream fis = null;
ObjectInputStream ois = null;
File privateKeyFile = new File(privateKeyFilename);
try {
String key = readFileAsString(privateKeyFilename);
BASE64Decoder b64 = new BASE64Decoder();
byte[] pkcs8EncodedBytes = b64.decodeBuffer(key);
PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(pkcs8EncodedBytes);
KeyFactory kf = KeyFactory.getInstance("RSA");
PrivateKey privKey = kf.generatePrivate(keySpec);
System.out.println(privKey);
return privKey;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
但是随后抛出以下错误:
java.security.spec.InvalidKeySpecException: java.security.InvalidKeyException: IOException : Short read of DER length
at sun.security.rsa.RSAKeyFactory.engineGeneratePrivate(RSAKeyFactory.java:217)
at java.security.KeyFactory.generatePrivate(KeyFactory.java:372)
at Decryptor.getPrivateKey(TestClass.java:61)
at Decryptor.main(TestClass.java:19)
Caused by: java.security.InvalidKeyException: IOException : Short read of DER length
at sun.security.pkcs.PKCS8Key.decode(PKCS8Key.java:351)
at sun.security.pkcs.PKCS8Key.decode(PKCS8Key.java:356)
at sun.security.rsa.RSAPrivateCrtKeyImpl.<init>(RSAPrivateCrtKeyImpl.java:91)
at sun.security.rsa.RSAPrivateCrtKeyImpl.newKey(RSAPrivateCrtKeyImpl.java:75)
at sun.security.rsa.RSAKeyFactory.generatePrivate(RSAKeyFactory.java:316)
at sun.security.rsa.RSAKeyFactory.engineGeneratePrivate(RSAKeyFactory.java:213)
... 3 more
java.security.InvalidKeyException: No installed provider supports this key: (null)
at javax.crypto.Cipher.chooseProvider(Cipher.java:893)
at javax.crypto.Cipher.init(Cipher.java:1249)
at javax.crypto.Cipher.init(Cipher.java:1186)
at Decryptor.main(TestClass.java:21)
【问题讨论】:
-
如果您不使用 BouncyCastle,标准 jre 需要一个补丁 (jce) 来处理大于 128 位的密钥大小。它通常会抛出不同的异常(表明未安装 jce)。但是为了使用普通的 jre 来做到这一点,如果你还没有安装 jce,你应该安装它。也许它会解决这个问题。
标签: java encryption openssl cryptography