2012-07-04 92 views
1

我有以下的代碼塊:解密的字符串不一樣的預加密的字符串

全局

public static PublicKey pubKey; 
public static PrivateKey privKey; 
public static Cipher cip; 

public static void main(String[] args) throws Exception { 
    //Generate the keys 

    KeyPairGenerator kpg = KeyPairGenerator.getInstance("RSA"); 
    kpg.initialize(1024); 
    KeyPair kp = kpg.genKeyPair(); 
    Key publicKey = kp.getPublic(); 
    Key privateKey = kp.getPrivate(); 

    KeyFactory fact = KeyFactory.getInstance("RSA"); 
    cip = Cipher.getInstance("RSA/ECB/NoPadding"); 

    // Store Public Key. 

    X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(
      publicKey.getEncoded()); 
    FileOutputStream fos = new FileOutputStream("public.key"); 
    fos.write(x509EncodedKeySpec.getEncoded()); 
    fos.close(); 

    // Store Private Key. 
    PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(
      privateKey.getEncoded()); 
    fos = new FileOutputStream("private.key"); 
    fos.write(pkcs8EncodedKeySpec.getEncoded()); 
    fos.close(); 

    //Get the public and private keys out of their files 
    getPubAndPrivateKey(); 

    //Check if the keys gotten out of the files are the same as the generated files (this returns truetrue) 
    System.out.print(publicKey.equals(pubKey)); 
    System.out.print(privateKey.equals(privKey)); 


    byte[] text = "This is my super secret secret".getBytes(); 
    encryptToFile("encrypted.txt", text); 
    decryptToFile("encrypted.txt", "decrypted.txt"); 

} 

充分利用鑰匙檔案

private static void getPubAndPrivateKey() throws IOException, Exception { 
    // Read Public Key. 
    File filePublicKey = new File("public.key"); 
    FileInputStream fis = new FileInputStream("public.key"); 
    byte[] encodedPublicKey = new byte[(int) filePublicKey.length()]; 
    fis.read(encodedPublicKey); 
    fis.close(); 

    // Read Private Key. 
    File filePrivateKey = new File("private.key"); 
    fis = new FileInputStream("private.key"); 
    byte[] encodedPrivateKey = new byte[(int) filePrivateKey.length()]; 
    fis.read(encodedPrivateKey); 
    fis.close(); 

    KeyFactory keyFactory = KeyFactory.getInstance("RSA"); 
    X509EncodedKeySpec publicKeySpec = new X509EncodedKeySpec(
      encodedPublicKey); 
    pubKey = keyFactory.generatePublic(publicKeySpec); 

    PKCS8EncodedKeySpec privateKeySpec = new PKCS8EncodedKeySpec(
      encodedPrivateKey); 
    privKey = keyFactory.generatePrivate(privateKeySpec); 

} 

加密

public static void encryptToFile(String fileName, byte[] data) 
     throws IOException { 

    try { 
     cip.init(Cipher.ENCRYPT_MODE, privKey); 
     byte[] cipherData = cip.doFinal(data); 
     String encryptedData = cipherData.toString(); 
     BufferedWriter out = new BufferedWriter(new FileWriter(fileName)); 
     out.write(encryptedData); 
     out.close(); 

    } catch (Exception e) { 
     throw new RuntimeException("Spurious serialisation error", e); 
    } 

} 

解密

private static void decryptToFile(String string, String string2) 
     throws Exception { 

    try { 
     File encryptedFile = new File("encrypted.txt"); 

     byte[] encrypted = getContents(encryptedFile).getBytes(); 

     cip = Cipher.getInstance("RSA/ECB/PKCS1Padding"); 
     cip.init(Cipher.DECRYPT_MODE, pubKey); 

     byte[] cipherData = cip.doFinal(encrypted); 

     String decryptedData = cipherData.toString(); 
     BufferedWriter out = new BufferedWriter(new FileWriter(
       "decrypted.txt")); 
     out.write(decryptedData); 
     out.close(); 

    } catch (Exception e) { 
     throw e; 
    } 
} 

事情我已經籤

  • 個在解密中使用的數據是相同的加密文件
  • 生成的密鑰是相同的從文件
  • 加密和解密得到的那些既沒有給出錯誤

結果
原始字符串:
我的超級祕密的祕密
的加密結果:
[B @ 1747b17 解密結果: [B @ 91a4fb

+0

看看[這裏] [1] - 也許有一些技巧可以幫助你。 [1]:http:// stackoverflow。com/questions/2714327/rsa-badpaddingexception-data-must-start-with-zero –

+0

@zaske我將其更改爲「RSA/ECB/NoPadding」,並且en/decryption工作沒有錯誤。但有兩個問題,爲什麼它會與「RSA/ECB/NoPadding」一起使用,而不是與「RSA/ECB/PKCS1Padding」一起工作(我填充它們的權利?)爲什麼解密不能正常工作? –

+2

此處存在初學Java錯誤。特別是,'(byte [])。toString()'方法不會做你認爲它的作用。 –

回答

2

如果通過toString()方法打印出一個字節數組,您將得到一個完全獨立於內容的值。

因此,值[B @ 1747b17 [B @ 91a4fb只是垃圾,並沒有告訴你任何東西。

如果要打印字節數組的內容,請將其轉換爲Base64或十六進制字符串。

System.out.println(new sun.misc.BASE64Encoder().encode(myByteArray)); 

一個十六進制字符串可通過使用從org.apache.commons.codec.binary.Hex Apache Commons Codec library產生。

+0

你打敗了我的答案,假設toString()在每種情況下都會給出一個有意義的結果是錯誤的。這個結果對我說的是,原始字符串是位置1747b17處的字符串,解密後的字符串位於91a4fb處;換句話說,原始和解密的字符串不是相同的字符串(它們位於不同的位置)。這可能不是解釋這些字符串的正確方法,但它適用於我。 「相同」並不意味着「相等」。如果我創建兩個刺「a」和「a」,它們不是相同的字符串,因爲它們是不同的實例,但它們是相同的。 – Thevenin

+0

非常感謝,自從我編寫了Java以來​​已經有4年了。初學者誤我的壞。 –

1

我同意上面的答案。 我想補充的是,在你的情況,你可以簡單地使用FileOutputStream中,寫字節文件 - 例如:

public static void encryptToFile(String fileName, byte[] data) 
     throws IOException { 

    FileOutputStream out = null; 
    try { 
     cip.init(Cipher.ENCRYPT_MODE, privKey); 
     byte[] cipherData = cip.doFinal(data); 
     out = new FileOutputStream(fileName); 
     out.write(cipherData); 
    } catch (Exception e) { 
     throw new RuntimeException("Spurious serialisation error", e); 
    } finally { 
     if (fos != null) { 
      try { 
       fos.close(); 
      } catch (IOException ex) { 
      } 
     } 
    } 

}