2017-07-14 7 views
0

私は認証のためのパスワードが必要な場合があります。
この「パスワード」はホストによって選択され、別のチャネル(WhatsAppなど)を介して「クライアント」に伝えられるため、このアプリケーションは機密データを処理しません。 したがって、クライアントが認証を行いたい場合、ホストはクライアントに送信されるランダムなStringを生成します。
クライアントは、ユーザが入力したパスワードでこのランダム文字列を暗号化します。
暗号化されたランダムな文字列は、ホストに送信されます。
ホストは、この暗号化された文字列を同じパスワードによって生成されたキーで復号化します。
暗号化されていないと、元の文字列が一致する場合、ユーザーがログインしている
これは私がこれまでに思い付いたものです:。パスワードのみに基づいて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)と交換し、すべてが動作するはずです。

関連する問題