2015-12-20 110 views
1

我想从文件中读取口令加密基于私钥,但我发现以下异常:的Java:写入和读取密码加密基于私钥

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.<init>(DerValue.java:294) 
at javax.crypto.EncryptedPrivateKeyInfo.<init>(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格式。 所以,这个问题:这个代码中的错误是什么?

+0

非对称加密并不意味着对密型数据大于其密钥大小。 – m0skit0

回答

0

我想这个问题是,你写一个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)); 
+0

构造函数EncryptedPrivateKeyInfo仍然引发异常,即java.io.IOException:DerValue.getOc​​tetString,而不是Octet String:3'。现在我正在写'FileOutputStream fos = new FileOutputStream(PRIVATE_KEY_FILE); fos.write(encryptedPkcs8); fos.close();'和读取'byte [] bytes = Files.readAllBytes(Paths.get(PRIVATE_KEY_FILE)); EncryptedPrivateKeyInfo encryptPKInfo = new EncryptedPrivateKeyInfo(bytes);' –

+0

方法'DerValue.getOc​​tetString'需要一个Octet String标记,但它会得到一个Bit String标记。 –

+0

终于工作了! –