InvalidKeySpecException:algid解析错误,而不是序列

我正在编写一个从控制台输入的程序 – 一个zip文件的名称,一个zip文件的名称包含从第一个zip生成的(de / en)加密文件和一个包含公钥的文件。 解密时我得到exception:

Exception in thread "main" java.security.spec.InvalidKeySpecException: java.security.InvalidKeyException: IOException : algid parse error, not a sequence at sun.security.rsa.RSAKeyFactory.engineGeneratePrivate(RSAKeyFactory.java:217) at java.security.KeyFactory.generatePrivate(KeyFactory.java:372) at com.Main.makePrivateKey(Main.java:148) at com.Main.decrypt(Main.java:40) at com.Main.main(Main.java:182) Caused by: java.security.InvalidKeyException: IOException : algid parse error, not a sequence at sun.security.pkcs.PKCS8Key.decode(PKCS8Key.java:351) at sun.security.pkcs.PKCS8Key.decode(PKCS8Key.java:356) at sun.security.rsa.RSAPrivateCrtKeyImpl.(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) ... 4 more 

无法弄清楚为什么因为我在makePrivateKey方法中使用了rigth规范。 我正在测试的密钥是(一行代表一个单独的文件中的密钥):

公钥:

 MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCE3pA746UfpC8sFk8ZJp0yupyJqj5jy6cjdxUYoP7mCm7c0mqQDeCcDNBYW2eSozCioPrH/9L+CDQEPLYakoem+jFnUKDH5+pru/0PJTJJF8Xh/ZT9eJlvsYBr1/qSfICf6RTs7kzwq9IuSZBw7/tfNEF9i0A8FVox6HOopXod1QIDAQAB 

私钥:

 MIICXQIBAAKBgQCE3pA746UfpC8sFk8ZJp0yupyJqj5jy6cjdxUYoP7mCm7c0mqQDeCcDNBYW2eSozCioPrH/9L+CDQEPLYakoem+jFnUKDH5+pru/0PJTJJF8Xh/ZT9eJlvsYBr1/qSfICf6RTs7kzwq9IuSZBw7/tfNEF9i0A8FVox6HOopXod1QIDAQABAoGANOFrYBqK5lvu1koOswDWQZFZqcSSzh8IZyoGwGWa7S0r0EECXlDXmuPSq8e9IfRG8ALHrH+ZlrbnFOSgyVSWHfpj3aH+qknoSX5TW2rMQHih8865xuqheMQ+RTZ7+BRDqNsYkzxB/Z8mqzpoJQSYf+H7nWxdDCgAJVYZzxl3DmUCQQD32iEjnwiwUjii8slcmvCEZl+z84DWNdvJOg6Z38sI4AvrfpKc1WAcDg1rNZCKrRgokh54wpLt08cpFcrD04c3AkEAiTzDmc0bdgfg5wj6xHFZpYlBwiGm/bjOR2PS57P0GNU5PsDllRbFqIuzArITutO5lvZZImzuYz7Lf+cQ73pxUwJBAOdEwmdaneDo17A0m2+to3/nhqWDMVSwLMU3RyiNigZeCMFU+bkd4PBMrHi9IoJDwacZsRU9eZwxYEUV8H2Jg0ECQEEkOqRSm2pXKwX/WSjNtQPCNxhy6NUeV6vDUmTxIjh3XYjP/ynZeVEbnoj1BjB0N2/U11Jj6nPpZqb7gyppMEkCQQCoGdVYDipU+hMMnvxa0zOIyQc/a+HE0lESqn+2ZPafYi9Z1RldRMvUXhP8U7s+OuhRwprdw2ivvOFrnWyz9lL2 

该程序的代码如下。 任何帮助都很受欢迎:)

 package com; import java.io.BufferedReader; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.FileReader; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.security.GeneralSecurityException; import java.security.KeyFactory; import java.security.PrivateKey; import java.security.PublicKey; import java.security.Security; import java.security.spec.PKCS8EncodedKeySpec; import java.security.spec.X509EncodedKeySpec; import java.util.Base64; import java.util.Enumeration; import java.util.Scanner; import java.util.zip.ZipEntry; import java.util.zip.ZipFile; import java.util.zip.ZipOutputStream; import javax.crypto.Cipher; public class Main { public final static int BUFFER_SIZE = 117; public static void decrypt(String originalZipFileName, String newZipFileName, String privateKeyFileName) throws Exception { byte[] buffer = new byte[BUFFER_SIZE]; ZipFile originalZipFile = new ZipFile(originalZipFileName); ZipOutputStream newZipFile = new ZipOutputStream(new FileOutputStream(newZipFileName)); Enumeration zipEntries = originalZipFile.entries(); String privateKey = getKeyString(privateKeyFileName); PrivateKey key = makePrivateKey(privateKey); Cipher cipher = Cipher.getInstance("RSA"); cipher.init(Cipher.DECRYPT_MODE, key); File file = new File("temp.txt"); while(zipEntries.hasMoreElements()){ ZipEntry entry = zipEntries.nextElement(); ZipEntry copy = new ZipEntry(entry.getName()); newZipFile.putNextEntry(copy); int read; InputStream inputEntry = originalZipFile.getInputStream(entry); OutputStream outputFile = new FileOutputStream(file); while((read = inputEntry.read(buffer)) != -1){ outputFile.write(cipher.doFinal(buffer), 0, read); } InputStream inputTempFile = new FileInputStream(file); while((read = inputTempFile.read(buffer)) != -1){ newZipFile.write(buffer, 0, read); } newZipFile.closeEntry(); inputEntry.close(); inputTempFile.close(); outputFile.close(); file.delete(); } newZipFile.close(); } public static void encrypt(String originalZipFileName, String newZipFileName, String publicKeyFileName) throws Exception{ byte[] buffer = new byte[BUFFER_SIZE]; ZipFile originalZipFile = new ZipFile(originalZipFileName); ZipOutputStream newZipFile = new ZipOutputStream(new FileOutputStream(newZipFileName)); Enumeration zipEntries = originalZipFile.entries(); String publicKey = getKeyString(publicKeyFileName); PublicKey key = makePublicKey(publicKey); Cipher cipher = Cipher.getInstance("RSA"); cipher.init(Cipher.ENCRYPT_MODE, key); File file = new File("temp.txt"); while(zipEntries.hasMoreElements()){ ZipEntry entry = zipEntries.nextElement(); ZipEntry copy = new ZipEntry(entry.getName()); newZipFile.putNextEntry(copy); int read; InputStream inputEntry = originalZipFile.getInputStream(entry); OutputStream outputFile = new FileOutputStream(file); while((read = inputEntry.read(buffer)) != -1){ outputFile.write(cipher.doFinal(buffer), 0, read); } InputStream inputTempFile = new FileInputStream(file); while((read = inputTempFile.read(buffer)) != -1){ newZipFile.write(buffer, 0, read); } newZipFile.closeEntry(); inputEntry.close(); inputTempFile.close(); outputFile.close(); file.delete(); } newZipFile.close(); } public static String getKeyString(String fileName){ String key = new String(); try { BufferedReader buf = new BufferedReader(new FileReader(fileName)); key = buf.readLine(); } catch ( IOException e) { e.printStackTrace(); } return key.trim(); } public static PublicKey makePublicKey(String stored) throws GeneralSecurityException { byte[] data = Base64.getDecoder().decode(stored); X509EncodedKeySpec spec = new X509EncodedKeySpec(data); KeyFactory fact = KeyFactory.getInstance("RSA"); return fact.generatePublic(spec); } public static PrivateKey makePrivateKey(String stored) throws GeneralSecurityException { byte[] data = Base64.getDecoder().decode(stored); PKCS8EncodedKeySpec spec = new PKCS8EncodedKeySpec(data); KeyFactory fact = KeyFactory.getInstance("RSA"); return fact.generatePrivate(spec); } public static void main(String[] args) throws Exception { Scanner scan = new Scanner(System.in); System.out.println("Enter type of operation:"); String line = scan.nextLine(); if(line.equals("encrypt")){ System.out.println("Enter name of original ZIP file:"); String originalZipFileName = scan.nextLine(); System.out.println("Enter name of new ZIP file:"); String newZipFileName = scan.nextLine(); System.out.println("Enter name of file containg public key:"); String publicKeyFileName = scan.nextLine(); encrypt(originalZipFileName, newZipFileName, publicKeyFileName); } if(line.equals("decrypt")){ System.out.println("Enter name of original ZIP file:"); String originalZipFileName = scan.nextLine(); System.out.println("Enter name of new ZIP file:"); String newZipFileName = scan.nextLine(); System.out.println("Enter name of file containg private key:"); String privateKeyFileName = scan.nextLine(); decrypt(originalZipFileName, newZipFileName, privateKeyFileName); } } } 

您的私钥不是PKCS#8格式。 您必须向其添加关键算法信息以使其成为PKCS#8,然后它才能工作。

可能你应该改变生成密钥的方式,使它们具有PKCS#8格式。 但由于我对此一无所知,我将展示如何使用BouncyCastle库在您的应用程序中更新它的键:

 @Test public void testKey() throws Exception { String privKeyStr = "MIICXQIBAAKBgQCE3pA746UfpC8sFk8ZJp0yupyJqj5jy6cjdxUYoP7mCm7c0mqQDeCcDNBYW2eSozCioPrH/9L+CDQEPLYakoem+jFnUKDH5+pru/0PJTJJF8Xh/ZT9eJlvsYBr1/qSfICf6RTs7kzwq9IuSZBw7/tfNEF9i0A8FVox6HOopXod1QIDAQABAoGANOFrYBqK5lvu1koOswDWQZFZqcSSzh8IZyoGwGWa7S0r0EECXlDXmuPSq8e9IfRG8ALHrH+ZlrbnFOSgyVSWHfpj3aH+qknoSX5TW2rMQHih8865xuqheMQ+RTZ7+BRDqNsYkzxB/Z8mqzpoJQSYf+H7nWxdDCgAJVYZzxl3DmUCQQD32iEjnwiwUjii8slcmvCEZl+z84DWNdvJOg6Z38sI4AvrfpKc1WAcDg1rNZCKrRgokh54wpLt08cpFcrD04c3AkEAiTzDmc0bdgfg5wj6xHFZpYlBwiGm/bjOR2PS57P0GNU5PsDllRbFqIuzArITutO5lvZZImzuYz7Lf+cQ73pxUwJBAOdEwmdaneDo17A0m2+to3/nhqWDMVSwLMU3RyiNigZeCMFU+bkd4PBMrHi9IoJDwacZsRU9eZwxYEUV8H2Jg0ECQEEkOqRSm2pXKwX/WSjNtQPCNxhy6NUeV6vDUmTxIjh3XYjP/ynZeVEbnoj1BjB0N2/U11Jj6nPpZqb7gyppMEkCQQCoGdVYDipU+hMMnvxa0zOIyQc/a+HE0lESqn+2ZPafYi9Z1RldRMvUXhP8U7s+OuhRwprdw2ivvOFrnWyz9lL2"; byte[] data = Base64.getDecoder().decode(privKeyStr); /* Add PKCS#8 formatting */ ASN1EncodableVector v = new ASN1EncodableVector(); v.add(new ASN1Integer(0)); ASN1EncodableVector v2 = new ASN1EncodableVector(); v2.add(new ASN1ObjectIdentifier(PKCSObjectIdentifiers.rsaEncryption.getId())); v2.add(DERNull.INSTANCE); v.add(new DERSequence(v2)); v.add(new DEROctetString(data)); ASN1Sequence seq = new DERSequence(v); byte[] privKey = seq.getEncoded("DER"); PKCS8EncodedKeySpec spec = new PKCS8EncodedKeySpec(privKey); KeyFactory fact = KeyFactory.getInstance("RSA"); PrivateKey key = fact.generatePrivate(spec); Assert.assertNotNull("Failed to generate the private key", key); } 

这个答案是迪瓦诺夫答案的补充。

PKCS#8格式包含一些字段,而不仅仅是最重要的部分private key

私钥信息语法

本节提供私钥信息的语法。

私钥信息应具有ASN.1类型的PrivateKeyInfo:

  PrivateKeyInfo ::= SEQUENCE { version Version, privateKeyAlgorithm PrivateKeyAlgorithmIdentifier, privateKey PrivateKey, attributes [0] IMPLICIT Attributes OPTIONAL } Version ::= INTEGER PrivateKeyAlgorithmIdentifier ::= AlgorithmIdentifier PrivateKey ::= OCTET STRING Attributes ::= SET OF Attribute 

PrivateKeyInfo类型的字段具有以下含义:

version是语法版本号,用于与本文档的未来版本兼容。 对于此版本的文档,它应为0。

privateKeyAlgorithm标识私钥算法。 私钥算法的一个例子是PKCS#1的rsaEncryption [PKCS#1]。

privateKey是一个八位字符串,其内容是私钥的值。 内容的解释在私钥算法的注册中定义。 例如,对于RSA私钥,内容是RSAPrivateKey类型的值的BER编码。

attributes是一组属性。 这些是与私钥信息一起加密的扩展信息。

您可以在私钥信息语法和divanov代码之间找到相应的对应关系。 喜欢:

 v.add(new ASN1Integer(0));//add version part to a PKCS#8 v.add(new DERSequence(v2));//add algorithm part to a PKCS#8 v.add(new DEROctetString(data));//add private key part to a PKCS#8 

更多细节在这里。