2011-06-30 113 views
11

我是密碼技術的新手。我發現這個代碼做對稱加密。使用AES 256和128的Java對稱密鑰加密

byte[] key = //... secret sequence of bytes 
byte[] dataToSend = ... 
Cipher c = Cipher.getInstance("AES"); 
SecretKeySpec k = new SecretKeySpec(key, "AES"); 
c.init(Cipher.ENCRYPT_MODE, k); 
byte[] encryptedData = c.doFinal(dataToSend); 

它的工作。在這裏我可以使用我自己的密碼。那就是我所需要的。但我不知道如何做128或256對稱Enctryption。 如何在我的代碼中使用128和256密鑰?

+0

我真的不知道,但我認爲使用一個256字節的密鑰將完成這項工作。 –

+0

實際上只有16個字節(128位)的密鑰在我的代碼中工作。 – Bhuban

+0

更大的按鍵是什麼「不工作」?你有例外嗎?哪一個?它的消息和堆棧跟蹤是什麼? –

回答

13

AES使用128位還是256位模式取決於您的密鑰的大小,它必須是128位或256位長。通常,您不會將密碼用作密鑰,因爲根據需要,密碼很少具有確切的長度。相反,您可以使用某個密鑰派生函數從密碼中導出加密密鑰。

很簡單的例子:取你的密碼的MD5得到128位密鑰。 如果您需要256位密鑰,則可以使用SHA-256獲取密碼的256位散列值。密鑰派生函數通常運行這種散列幾百次,並使用額外的鹽。詳情請查閱http://en.wikipedia.org/wiki/Key_derivation_function

另請注意:要運行比128位更強的加密,您需要從http://www.oracle.com/technetwork/java/javase/downloads/index.html下載並安裝'Java加密擴展(JCE)無限強度管轄策略文件6'。

+5

MD5?今天早上我在1996年醒來了嗎? SHA系列具有產生128,256,348和512位哈希的算法。 –

+4

@Peter:這只是一個簡單的例子,如何獲得從密碼計算出來的128位密鑰。如果你的密碼少於16個字節,你可以將它填充到16個字節。你挑選不重要的細節。 (無論如何,我已經更新了我的答案,說使用SHA-256從密碼獲得256位密鑰) –

+1

@Peter,哈哈哈,是的,我只是討厭看到MD5的任何東西,但遺產代碼,並不認爲它應該是推薦給初學者;它已經破裂很久了。 –

2

您可以使用一個簡單的KeyGenerator對象是這樣的:

KeyGenerator generator = KeyGenerator.getInstance("AES/CTR/PKCS5PADDING"); 
generator.init(128); 
SecretKey key = generator.generateKey(); 
Cipher cipher = Cipher.getInstance("AES"); 
cipher.init(Cipher.ENCRYPT_MODE, key); 
... 
+1

這裏如何使用我自己的密碼? – Bhuban

1

Java's docs for Cipher.init(...)

公衆最終無效的init(INT OPMODE, 鍵鍵)

拋出: InvalidKeyException異常 - 如果給定密鑰不適合初始化 此密碼,或者此密碼爲 初始化爲解密和 要求 不能從給定的 鍵來確定算法參數,或者如果給定的鍵具有密鑰大小 超過最大允許 密鑰大小(如從 配置的仲裁策略文件確定)。

對我來說,這意味着,馬亭Courteaux在他的評論中說,你應該使用256位的密鑰(即含32個字節的字節數組初始化SecretKeySpec)和密碼會接受它,使用它,或拒絕它並拋出一個異常,如果它的大小是不可接受的。

如果您遇到異常,可能是因爲您尚未安裝無限強度的加密文件(默認JDK安裝允許此crypto spec document中記錄的128位密鑰)。下載無限強度加密包here

+0

是的,我的代碼可以只需要16個字節或128位。所以這是我的問題如何使用256位密鑰? – Bhuban

+0

我編輯了我的答案 –

+0

謝謝。它的工作現在。你的回答非常有幫助。 – Bhuban

0
public class CipherUtils 
{ 
    private static byte[] key = { 
      0x74, 0x68, 0x69, 0x73, 0x49, 0x73, 0x41, 0x53, 0x65, 0x63, 0x72, 0x65, 0x74, 0x4b, 0x65, 0x79 
    };//"thisIsASecretKey"; 

    public static String encrypt(String strToEncrypt) 
    { 
     try 
     { 
      Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding"); 
      final SecretKeySpec secretKey = new SecretKeySpec(key, "AES"); 
      cipher.init(Cipher.ENCRYPT_MODE, secretKey); 
      final String encryptedString = Base64.encodeBase64String(cipher.doFinal(strToEncrypt.getBytes())); 
      return encryptedString; 
     } 
     catch (Exception e) 
     { 
      e.printStackTrace(); 
     } 
     return null; 
    } 
} 
+0

我有幾個問題。 1.該密鑰是唯一可用於解密的密鑰,對吧? (可能是這個問題的一個明顯的答案 - 只要確保)2.如果使用相同的密鑰(運行該方法的兩個不同時間)對相同的數據進行加密,它是否會呈現不同的加密字節? – raddevus

+0

好吧,我轉換了這段代碼,並找出了自己的答案。另外,有趣的是,OWASP示例(https://www.owasp.org/index.php/Using_the_Java_Cryptographic_Extensions)直接提到了使用IV(初始化向量),但它並未在此答案的代碼中使用。 Ce la vie。 – raddevus

+0

不要硬編碼密鑰。任何有權訪問編譯代碼的人都可以輕鬆使用它。 – Mike

6

對於128位

下面的方法是加密的字符串(valueEnc)與AES加密的答案:

private static final String ALGORITHM = "AES"; 

public String encrypt(final String valueEnc, final String secKey) { 

    String encryptedVal = null; 

    try { 
     final Key key = generateKeyFromString(secKey); 
     final Cipher c = Cipher.getInstance(ALGORITHM); 
     c.init(Cipher.ENCRYPT_MODE, key); 
     final byte[] encValue = c.doFinal(valueEnc.getBytes()); 
     encryptedVal = new BASE64Encoder().encode(encValue); 
    } catch(Exception ex) { 
     System.out.println("The Exception is=" + ex); 
    } 

    return encryptedVal; 
} 

下一個方法將解密的AES加密字符串(encryptedVal) :

public String decrypt(final String encryptedValue, final String secretKey) { 

    String decryptedValue = null; 

    try { 

     final Key key = generateKeyFromString(secretKey); 
     final Cipher c = Cipher.getInstance(ALGORITHM); 
     c.init(Cipher.DECRYPT_MODE, key); 
     final byte[] decorVal = new BASE64Decoder().decodeBuffer(encryptedValue); 
     final byte[] decValue = c.doFinal(decorVal); 
     decryptedValue = new String(decValue); 
    } catch(Exception ex) { 
     System.out.println("The Exception is=" + ex); 
    } 

    return decryptedValue; 
} 

The secKey是一個128位密鑰,編碼在BASE64Encoder中。在以下方法BASE64Decoder生成一個合適的128位密鑰

private Key generateKeyFromString(final String secKey) throws Exception { 
    final byte[] keyVal = new BASE64Decoder().decodeBuffer(secKey); 
    final Key key = new SecretKeySpec(keyVal, ALGORITHM); 
    return key; 
} 
+1

您已經忘記使用初始化矢量,並且您也沒有指定要使用的AES的模式和填充。雖然這是對問題的回答,但請注意,這不是安全使用加密。 –