ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [안드로이드 JAVA] 문자열을 SHA-256로 암호화하기 (AndroidKeyStore 이용)
    Programming/Android 2021. 2. 14. 22:20

    [Android] SharedPreferences 암호화하기 (androidx.security 이용)

     

    [Android] SharedPreferences 암호화하기 (androidx.security 이용)

    안드로이드 앱 개발을 할 때, 사용자 입력 값을 저장하는 방법은 임의의 파일을 생성하거나 SQLite에 저장하는 방법 등 다양한 방법이 있다. 그러나 간단하게 1~2개의 데이터를 사용하기 위해 복잡

    striban.tistory.com

     

    이전 글에서는 사용자 데이터를 간단하게 EncryptedSharedPreferences 를 이용하여 암호화하여 저장하였다.

    이 방식은 AES256 알고리즘이라 양방향 암호화를 통하여 사용자 데이터를 관리할 수 있다는 장점이 있으나,

    비밀번호와 같은 경우에는 개인정보보호법에 따라 무조건 일방향 암호화를 하도록 되어 있어 적용할 수 없다.

     

    안드로이드에서는 일방향 암호화 클래스로 MessageDigest 를 가지고 있다.

    사용법이 어렵지 않아 간단하게 구현할 수 있다.

    String data = "value";
    MessageDigest md = MessageDigest.getInstance("SHA-256");
    md.update(data.getBytes("UTF-8"));
    byte[] bytes = md.digest();
    String hash = String.format("%64x", new BigInteger(1, bytes));
    
    
    >>
    hash : cd42404d52ad55ccfa9aca4adc828aa5800ad9d385a0671fbcbf724118320619

    value 라는 문자열을 받아서 64글자의 해시값으로 바꾸어 준다.

    value 라는 글자가 누구도 알아볼 수 없을 것 같은 문자들로 바뀌게 된 것이다.

    위에서 "%64x" 는 64글자의 16진수(x)를 의미한다.

     

    그러나,

    이 방법은 매우 위험한 방법이다.

     

    주어진 문자열을 단순하게 해시값으로 변경하는 방법이기 때문에,

    모든 안드로이드 기기에서 항상 같은 문자열을 같은 해시값으로 바꾸어 준다.

     

    해커들은 그동안 이 해시값을 모아서 Rainbow Table 이란 것을 만들어 놓았다.

     

    인터넷에서 SHA-256 Rainbow Table 을 찾아서 위의 값을 입력하여보면

    즉시, 원문인 value로 변경되는 것을 확인할 수 있다.

     

     

    문자열 암호화에 MessageDigest를 사용하는 것은 추천하지 않는다.

     

    문자열을 안전하게 일방향 암호화하는 방법으로 추천하는 것은

    문자열을 특별한 암호화키를 이용하여 변환하는 것이다.

     

    안드로이드에서는 안드로이드OS 영역에서 관리하는 AndroidKeyStore 가 있다.앱 영역과 분리된 공간에 관리되기 때문에 이 키를 추출하거나 가공/분석/사용하는 것은 불가능에 가깝다.여기에 특별한 암호화키를 만들어두면 문자열 암호화를 할 때마다 쉽게 적용할 수 있다.

     

    우선, KeyPairGenerator 클래스로 암호화키를 하나 만든다.

    KeyPairGenerator kpg = KeyPairGenerator.getInstance(KeyProperties.KEY_ALGORITHM_EC, "AndroidKeyStore");
    kpg.initialize(new KeyGenParameterSpec.Builder("keyname", KeyProperties.PURPOSE_SIGN).setDigests(KeyProperties.DIGEST_SHA256).build());
    kpg.generateKeyPair();

    키 알고리즘으로는 ECDSA 를 사용하였고, keyname이란 alias로 저장된다.

    용도에 따라 keyname을 다르게 지정하면 여러개의 키를 만들 수 있다.

     

     

    이렇게 만들어진 암호화키는 KeyStore 클래스로 불러와 사용할 수 있다.

    KeyStore ks = KeyStore.getInstance("AndroidKeyStore");
    ks.load(null);
    PrivateKey privateKey = (PrivateKey) ks.getKey("keyname", null);

    불러오고자 하는 암호화키는 keyname으로 지정하면 된다.

     

    이제 이 암호화키를 사용하여 문자열을 SHA-256으로 암호화한다.

    ECDSA 알고리즘은 전자서명용이므로 Signature 클래스를 이용하여 암호화한다.

    String data = "value"
    Signature esign = Signature.getInstance("SHA256withECDSA");
    esign.initSign(privateKey);
    esign.update(data.getBytes("UTF-8"));
    byte[] bytes = esign.sign();
    String hash = String.format("%64x", new BigInteger(1, bytes));
    
    >>
    hash : 3045022071894bfba27a26333e5a4952f0c3d244bbce58b0b597524b49bc8847a056d7cd022100e30c3f4504b178a8ba45a762c1992c64eb9c31f1080f2b6d957cef75778844b8

    Signature 알고리즘으로는 SHA-256 with ECDSA 를 사용하였고, initSign에서 암호화키를 적용하였다.

     

    암호화키를 이용하여 value 라는 문자열을 해시값으로 변경하였고, 

    이 암호화키는 안드로이드 기기마다 다르게 생성되기 때문에 같은 문자열이라고 해도 해시값은 모두 다르게 생성된다.

     

    이렇게 변경된 해시값은 SHA-256 Rainbow Table에서는 절대 찾을 수 없다.

     

     

    AndroidKeyStore에는 RSA, AES1, ECDSA, HMAC-SHA256, DES 이렇게 5가지 알고리즘으로 키를 생성할 수 있다.

    용도에 맞게 암호화키를 생성하여 활용한다면

    비밀번호와 같이 중요한 정보는 보다 안전하게 관리할 수 있을 것이다.

     

     

    댓글

Designed by Tistory.