2011-09-27 56 views
0

調用時會生成不同的結果我有一個簡單的java web應用程序,它由apache wicket構建。當我在Web應用程序中註冊用戶時,我使用三合一加密他們輸入的密碼並將其保存到數據庫。在他們輸入相同密碼的登錄頁面中,我將其加密並將加密密碼傳遞給數據庫,以檢查它是否正確。TripleDES算法從Android

現在我正在構建一個具有相同登錄功能的Android應用程序。

在Android應用程序登錄頁面中,我使用相同的加密庫來加密密碼,並且我在兩個平臺上使用相同的密鑰和初始化向量,但是如果我嘗試在android中輸入相同的密碼字符串,TripleDes算法會生成完全不同的加密密碼(更長)。因此登錄失敗從Android設備。我還注意到,android生成的加密密碼無法解密,它會引發異常。

我在想,兩個平臺之間可能存在字符串編碼問題的區別,但無法弄清楚是什麼原因造成的,以及如何解決這個問題。

下面是我用的算法:

public class TripleDES { 
private String key; 
private byte[] initializationVector; 

public TripleDES(String key, byte[] initializationVector) 
{ 
    this.key = key; 
    this.initializationVector = initializationVector; 
} 

public String encryptText(String plainText) throws Exception{ 
//---- Use specified 3DES key and IV from other source ------------------------- 
    byte[] plaintext = plainText.getBytes(); 
    byte[] tdesKeyData = key.getBytes(); 

    System.out.println("plain text length: " + plaintext.length); 
    System.out.println("key length: " + tdesKeyData.length); 


    Cipher c3des = Cipher.getInstance("DESede/CBC/PKCS5Padding"); 
    SecretKeySpec myKey = new SecretKeySpec(tdesKeyData, "DESede"); 
    IvParameterSpec ivspec = new IvParameterSpec(initializationVector); 

    c3des.init(Cipher.ENCRYPT_MODE, myKey, ivspec); 
    byte[] cipherText = c3des.doFinal(plaintext); 

    return Base64Coder.encodeString(new String(cipherText)); 
} 

public String decryptText(String encryptedText) throws Exception{ 
    //---- Use specified 3DES key and IV from other source ------------------- 
     byte[] enctext = Base64Coder.decode(encryptedText); 
     byte[] tdesKeyData = key.getBytes(); 


     Cipher c3des = Cipher.getInstance("DESede/CBC/PKCS5Padding"); 
     SecretKeySpec myKey = new SecretKeySpec(tdesKeyData, "DESede"); 
     IvParameterSpec ivspec = new IvParameterSpec(initializationVector); 

     c3des.init(Cipher.DECRYPT_MODE, myKey, ivspec); 
     byte[] cipherText = c3des.doFinal(enctext); 
     return new String(cipherText); 
    } 

}

+1

你爲什麼要存儲用戶密碼以可逆加密?這通常是進行身份驗證的錯誤方法。 – erickson

+0

我只有一種加密方法,並且我需要對其他一些敏感數據進行可逆加密。我想我應該使用MD5等不可逆轉的密碼加密。 –

+0

如果您的「密鑰」實際上是一個密碼(文本),那麼您應該從中獲取密鑰,而不是直接將其用作加密密鑰。像PBKDF2這樣的好的密鑰派生算法也是一種很好的單向認證功能。 – erickson

回答

2

(編輯:如前所述,存儲密碼可逆是一個壞主意,開始用,但對於獲得加密部分的權利着想...)

這是第一個問題:

byte[] plaintext = plainText.getBytes(); 
byte[] tdesKeyData = key.getBytes(); 

這是ü唱出默認的系統字符編碼。所有Android手機都一樣嗎?我不知道。 Android和您的網絡服務器一樣嗎?我不知道。如果一個平臺使用的是UTF-16,而另一個使用的是UTF-8,而plainText是全部ASCII,那麼肯定會佔據加密數據大小的二分之一差異。

我會推薦總是指定編碼 - 在許多情況下,「UTF-8」是一個不錯的選擇。

編輯:好吧,它看起來像問題是你後來做什麼cipherText。您需要將原始字節轉換爲base64字符串。 Android中內置了base64編碼器,但this public domain code應該可以正常工作。相反,該行:

return Base64Coder.encodeString(new String(cipherText)); 

你會使用

return Base64.encodeBytes(cipherText); 
+0

我已經試過了,它沒有幫助,它仍然生成相同的錯誤加密密碼。 –

+0

@ user967505:那麼你應該仍然明確地解決這個問題,然後你至少可以檢查你是否擁有相同的明文和關鍵數據。 –

+0

我檢查了兩個應用程序的默認字符集,一個是windows-1252,另一個(andorid)是UTF-8,所以絕對是第一個問題,現在我使用UTF-8來獲取加密算法中的字節。在得到字節後,我記錄了兩個應用程序的字節總數和兩個數組的長度,但它們似乎匹配。 –