Java:写入和读取基于密码的加密私钥

我试图从文件中读取基于密码的加密私钥,但我得到以下exception:

java.io.IOException: DerInputStream.getLength(): lengthTag=109, too big. at sun.security.util.DerInputStream.getLength(DerInputStream.java:561) at sun.security.util.DerValue.init(DerValue.java:365) at sun.security.util.DerValue.(DerValue.java:294) at javax.crypto.EncryptedPrivateKeyInfo.(EncryptedPrivateKeyInfo.java:84) ... 

这是我加密和写入私钥的方式:

 public static void savePrivateKeyToDisk(PrivateKey privateKey, String passord){ try { // unencrypted PKCS#8 private key byte[] encodedPrivateKey = privateKey.getEncoded(); String MYPBEALG = "PBEWithSHA1AndDESede"; int count = 20; SecureRandom random = new SecureRandom(); byte[] salt = new byte[8]; random.nextBytes(salt); // Create PBE parameter set PBEParameterSpec pbeParamSpec = new PBEParameterSpec(salt, count); PBEKeySpec pbeKeySpec = new PBEKeySpec(password.toCharArray()); SecretKeyFactory keyFac = SecretKeyFactory.getInstance(MYPBEALG); SecretKey pbeKey = keyFac.generateSecret(pbeKeySpec); Cipher pbeCipher = Cipher.getInstance(MYPBEALG); // Initialize PBE Cipher with key and parameters pbeCipher.init(Cipher.ENCRYPT_MODE, pbeKey, pbeParamSpec); // Encrypt the encoded Private Key with the PBE key byte[] cipherText = pbeCipher.doFinal(encodedPrivateKey); // Now construct PKCS #8 EncryptedPrivateKeyInfo object AlgorithmParameters algparms = AlgorithmParameters.getInstance(MYPBEALG); algparms.init(pbeParamSpec); EncryptedPrivateKeyInfo encinfo = new EncryptedPrivateKeyInfo(algparms, cipherText); // DER encoded PKCS#8 encrypted key byte[] encryptedPkcs8 = encinfo.getEncoded(); File encryptedPrivate = new File(PRIVATE_KEY_FILE); if (encryptedPrivate.getParentFile() != null) { encryptedPrivate.getParentFile().mkdirs(); } encryptedPrivate.createNewFile(); ObjectOutputStream publicKeyOS = new ObjectOutputStream( new FileOutputStream(encryptedPrivate)); publicKeyOS.writeObject(encryptedPkcs8); publicKeyOS.close(); } catch (Exception e){ e.printStackTrace(); } } 

…这就是我试图读取加密私钥的方式:

 public static PrivateKey getPrivateKey(String passwd){ try { byte[] encodedPrivateKey = getFileBytes(PRIVATE_KEY_FILE); // exception thrown from here EncryptedPrivateKeyInfo encryptPKInfo = new EncryptedPrivateKeyInfo(encodedPrivateKey); Cipher cipher = Cipher.getInstance(encryptPKInfo.getAlgName()); PBEKeySpec pbeKeySpec = new PBEKeySpec(passwd.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(ALGORITHM); return kf.generatePrivate(pkcs8KeySpec); } catch (Exception e){ e.printStackTrace(); return null; } } 

… getFileBytes方法:

  private static byte[] getFileBytes(String infile){ File f = new File(infile) ; int sizecontent = ((int) f.length()); byte[] data = new byte[sizecontent]; try { FileInputStream freader = new FileInputStream(f); freader.read(data, 0, sizecontent) ; freader.close(); return data; } catch(IOException ioe) { System.out.println(ioe.toString()); return null; } } 

看起来加密的私钥格式不正确,但我将其保存为DER PKCS#8格式。 所以,问题是:这段代码中的错误是什么?

我想问题是你写了一个Object ,但是你读了byte[] (不是一个Object )我建议你要么读完整个对象然后直接得到所需的字节,要么直接写byte[] t使用ObjectOutputStream )然后加载这些字节,例如:

 FileOutputStream fos = new FileOutputStream(PRIVATE_KEY_FILE); fos.write(myByteArray); fos.close(); 

然后检索它:

 byte[] bytes = Files.readAllBytes(Paths.get(PRIVATE_KEY_FILE));