3

현재이 게시물에서 영감을 얻은 Android의 AES 256을 사용하여 대칭 암호화/복호화를 구현 중입니다. Java 256bit AES Encryption. 구현의 목적은 데이터베이스의 데이터를 암호화하는 것입니다. 나는 문자 [] 암호 소요 다음 생성자 사용 키 생성을 위해모든 메시지에 하나의 키와 임의의 IV를 사용하는 Android AES 비밀번호 기반 암호화

:

public Cryptography(char[] password) throws NoSuchAlgorithmException, 
     InvalidKeySpecException, NoSuchPaddingException { 

    SecretKeyFactory factory = SecretKeyFactory.getInstance("PBEWITHSHA256AND256BITAES-CBC-BC"); 
    KeySpec spec = new PBEKeySpec(password, salt, 1024, 256); 
    secretKey = new SecretKeySpec(factory.generateSecret(spec).getEncoded(), "AES"); 
    cipher = Cipher.getInstance(AES/CBC/PKCS5Padding); 
} 

내가 안드로이드 내 활동을 시작할 때 그래서 난 내 암호화 클래스의 새 인스턴스를 초기화하고 그러므로 생성 된 키를 얻을 수 . 소금은 16 바이트의 고정 된 임의의 바이트 []입니다. 그래서 나는 항상 같은 열쇠를 얻는다는 것을 의미합니다. 나중에 그 이유. 내가 한 활동에서 개체를 얻었다 후

지금 나는 다음과 같은 암호화를 사용하여 항상 같은 키 방식의 암호를 해독 할 수 있습니다 : 당신이 볼 수 있듯이

public byte[] encrypt(String cleartext) throws InvalidKeyException, 
     IllegalBlockSizeException, BadPaddingException, 
     UnsupportedEncodingException, InvalidParameterSpecException { 

    cipher.init(Cipher.ENCRYPT_MODE, secretKey); 

    byte[] encText = cipher.doFinal(cleartext.getBytes(CHARSET_NAME)); 
    byte[] iv = cipher.getParameters() 
      .getParameterSpec(IvParameterSpec.class).getIV(); 

    byte[] enc = new byte[IV_SIZE + encText.length]; 

    for (int i = 0; i < enc.length; i++) { 
     if (i < IV_SIZE) 
      enc[i] = iv[i]; 
     else if (i < enc.length) 
      enc[i] = encText[i - IV_SIZE]; 
    } 

    return enc; 
} 

public String decrypt(byte[] encryptedText) throws InvalidKeyException, 
     InvalidAlgorithmParameterException, UnsupportedEncodingException, 
     IllegalBlockSizeException, BadPaddingException { 

    byte[] iv = new byte[IV_SIZE]; 
    byte[] dec = new byte[encryptedText.length - IV_SIZE]; 

    for (int i = 0; i < encryptedText.length; i++) { 
     if (i < IV_SIZE) 
      iv[i] = encryptedText[i]; 
     else if (i < encryptedText.length) 
      dec[i - IV_SIZE] = encryptedText[i]; 
    } 

    cipher.init(Cipher.DECRYPT_MODE, secretKey, new IvParameterSpec(iv)); 

    return new String(cipher.doFinal(dec), CHARSET_NAME); 
} 

, 나는 암호문과 함께 신선한 새로운 IV를 저장을 매번 메시지를 암호화합니다.

결론 : 데이터베이스 테이블에서 하나의 암호화 키, 하나의 무작위 소금 및 모든 IV 필드를 사용합니다.

처음에는 데이터베이스 테이블에서 하나의 필드를 암호화하고 암호문과 함께 필요한 소금 및 IV 또는 적어도 하나의 테이블 행을 저장할 때마다 새 소금과 새 IV로 새 키를 생성하려고했습니다. 그러나 위에서 언급 한 이유는 Android 기기에서 키를 생성하는 데 많은 시간이 걸리기 때문입니다. 에뮬레이터에서 테스트했지만 키를 생성하는 데 약 2 초가 걸렸습니다. 이것이 Activity가 시작될 때 하나의 키를 생성 한 이유입니다.

마지막으로 내 질문 : 내 접근 방식으로, 하나의 키만 사용하여 충분히 안전하지만 모든 메시지에 대해 임의의 IV를 사용합니까? 현재 성능과 균형을 유지하여 가능한 한 안전하게 만들 수있는 또 다른 방법은 없습니다.

나는 그것이 내가 쓴 것과 누군가가 나에게 그것에 대한 조언을 줄 수 있기를 희망한다.

친절 감사

xoidberg

답변

1

나는 문제는 당신 (xoidberg)와 관련이 없습니다 생각하지만, 그것은 다른 사람들을 위해 관련 될 수 있습니다.

내가 이해 한 바로는 - 소금을 사용하여 암호에서 (안전하게 무작위로) 키를 만듭니다. 모든 사용자가 무작위 (다른) 소금을 가지고 있다면 - 괜찮습니다. 그렇지 않으면 문제가 될 수 있습니다.

나는 이것이 당신이 한 일이라고 믿습니다. 그래서 (나에게) 괜찮을 것 같습니다.

난 그냥 당신이 일반적으로 몇 가지 값 (일반적으로 비밀 번호)의 해시 함수를 저장할 때 소금을 사용하고자하는 언급하고 싶습니다. MD5 나 SHA 같은 해시 함수에는 키가 없으므로이 목적을 위해 임의성을 추가해야합니다. 이것이 바로 소금이 필요한 이유이며,이 경우에는 각 값에 대해 보통 무작위 소금이 필요합니다 (단, 암호 해시를 같은 소금으로 저장하면 가장 일반적인 해시를 감지하고 사용자의 암호를 알아낼 수 있습니다 가장 일반적인 해시는 123456입니다. 귀하의 경우 - 모든 사용자는 독특한 소금이 필요합니다.

IV에 대해 - 매번 무작위로 하나씩 필요합니다 (괜찮습니다).