2017-07-14 163 views
0

我有一個可能需要驗證密碼的應用程序。
此應用程序不處理任何敏感數據,因爲這個「密碼」是由主機選擇,並通過另一個通道(WhatsApp或其他)通知「客戶端」。 所以當一個客戶端想要認證時,主機會生成一個隨機的字符串發送給客戶端。
客戶端隨後使用用戶輸入的密碼加密此隨機字符串。
加密的隨機字符串是發送回主機。
主機使用由相同密碼生成的密鑰來解密此加密的字符串。
如果不加密的,原始的字符串匹配,用戶登錄
這是我想出了這麼遠。僅基於密碼生成AES密鑰

String base64; 
char[] password = "password".toCharArray(); 
String randomString = new BigInteger(130, new SecureRandom()).toString(32); 
try { 
    //Encrypt Client Side 
    SecretKey key = new SecretKeySpec(SecretKeyFactory.getInstance("PBKDF2WithHmacSHA512").generateSecret(new PBEKeySpec(password)).getEncoded(), "AES"); 
    Cipher cipher = Cipher.getInstance("AES"); 
    cipher.init(Cipher.ENCRYPT_MODE, key); 
    base64 = Base64.getEncoder().encodeToString(cipher.doFinal(randomString.getBytes(StandardCharsets.UTF_8))); 
} catch (GeneralSecurityException e) { 
    throw new IllegalStateException(e); 
} 
try { 
    //Decrypt Server Side 
    SecretKey key = new SecretKeySpec(SecretKeyFactory.getInstance("PBKDF2WithHmacSHA512").generateSecret(new PBEKeySpec(password)).getEncoded(), "AES"); 
    Cipher cipher = Cipher.getInstance("AES"); 
    cipher.init(Cipher.DECRYPT_MODE, key); 
    //Check if both strings match 
    System.out.println(Arrays.equals(cipher.doFinal(Base64.getDecoder().decode(base64)), randomString.getBytes(StandardCharsets.UTF_8))); 
} catch (GeneralSecurityException e) { 
    throw new IllegalStateException(e); 
} 

遺憾的是這段代碼會拋出異常:java.security.spec.InvalidKeySpecException: Salt not found
我應該使用不同的算法,還是應該通過散列密碼本身或者完全不同的方法來生成鹽? 我想避免必須隨隨隨機字符串一起發送生成的鹽

回答

1

您應該給PBEKeySpec它需要爲AES密鑰生成足夠的位。你需要雙方對相同的鹽,所以你可以這樣做:

byte[] salt = new byte[8]; 
System.arraycopy(randomString.getBytes("UTF-8"), 0, salt, 0, 8); 

現在你PBEKeySpecnew PBEKeySpec(password, salt, 10, 128)代替,一切都應該工作。