2016-04-24 3 views
0

私はキーストアを使用してAES暗号化の鍵を生成し、それを使用してプレーンテキストを暗号化します。コード。私は別のアクティビティのonCreate()メソッドでcreateKey()メソッドを1回だけ呼び出し、同じkeyAliasと同じ平文でprintCipherText()メソッドを何度も呼び出します。奇妙なことは:私がprintCipherText()メソッドを呼び出すたびに、私は別の結果を得る。私は同じキーエイリアスと同じ平文を使用していますが、毎回異なる暗号テキストを得るのはなぜですか?Android AES(キーストア付き)は、同じプレーンテキストで異なる暗号テキストを生成します

public class KeyCreatorClass { 

    KeyStore keyStore; 
    KeyGenerator keyGenerator; 
    Cipher cipher; 

    public void createKey(String keyAlias) { //I call this method only once in the onCreate() method of another activity, with keyAlias "A" 
     try { 
      keyStore = KeyStore.getInstance("AndroidKeyStore"); 
      keyGenerator = KeyGenerator.getInstance(KeyProperties.KEY_ALGORITHM_AES, "AndroidKeyStore"); 
      cipher = Cipher.getInstance("AES/CBC/PKCS7Padding"); 
      keyStore.load(null); 
      keyGenerator.init(
        new KeyGenParameterSpec.Builder(keyAlias, KeyProperties.PURPOSE_ENCRYPT | KeyProperties.PURPOSE_DECRYPT) 
         .setBlockModes(KeyProperties.BLOCK_MODE_CBC) 
         .setUserAuthenticationRequired(false) 
         .setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_PKCS7) 
         .setRandomizedEncryptionRequired(false) 
         .build()); 
      keyGenerator.generateKey(); 
     } catch (Exception e) { 
      e.printStackTrace(); 
     } 
    } 

    public String printCipherText(String keyAlias, String plainText){ //I call this method many times with the same keyAlias "A" and same plaintext in the same activity 
     try { 
      keyStore.load(null); 
      SecretKey key = (SecretKey) keyStore.getKey(keyAlias, null); 
      cipher.init(Cipher.ENCRYPT_MODE, key); 
      return byteToHex(cipher.doFinal(plainText.getBytes())); 
     }catch(Exception e){ 
      e.printStackTrace(); 
     } 
     return "BUG"; 
    } 

    private String byteToHex(byte[] byteArray){ 
     StringBuilder buf = new StringBuilder(); 
     for (byte b : byteArray) 
      buf.append(String.format("%02X", b)); 
     String hexStr = buf.toString(); 
     return hexStr; 
    } 
} 
+0

これらのすべての機会に、元のテキストを元に戻しますか? – MikeC

+0

私は@Artjom B.は私の問題を解決したと思うありがとうございます –

答えて

3

初期化ベクトル(IV)を使用するCBCモードを使用しています。コードでIVを指定していないので、コードが呼び出されるたびにランダムに生成されます。これは、あなたが再び送ったメッセージがあるかどうかを暗号文のオブザーバが判断できないようにするために重要な特性です。これは、セマンティックセキュリティを実現するために必要です。

IVはランダムに生成されるため、復号化中にも暗号化中に使用されたのと同じIVが必要です。 IVは秘密である必要はありませんが、それは予測不可能である必要があります(それはそれです)。 1つの一般的な方法は、暗号文の前にそれを書き込んで、復号中にそれを読み取ることです。ブロックサイズは常に同じ長さです。そのサイズはAESの場合は16バイトです。

+0

ありがとうございました!ところで、あなたはIVを使用する "共通の方法"の例を挙げることができますか? –

+1

単純な 'return byteToHex(cipher.getIV())+ byteToHex(cipher.doFinal(plainText.getBytes()));は、復号化中に部分文字列を使って別の方法で動作するはずです。大規模なデータに対して暗号化を有効にするには、ストリームを使用する必要があります。 –

関連する問題