코틀린에서 AES 사용하는법 찾아서 해보고 여기 정리 해둠.
fun hashSHA256(msg: String): ByteArray { val hash: ByteArray try { val md = MessageDigest.getInstance("SHA-256") md.update(msg.toByteArray()) hash = md.digest() } catch (e: CloneNotSupportedException) { throw DigestException("couldn't make digest of partial content") } return hash }
hashSHA256 함수는 문자열을 넣으면 32바이트 배열을 리턴해줌.
SHA256 해시를 돌리는것인데 이유는 들어가는 비밀번호의 길이가 16바이트면 AES128, 24바이트면 AES192, 32바이트면 AES256으로 처리되기 때문임.
인터넷 검색해보니 AES 정리해놓은 일부 블로그에선 문자열 뒤에 값 넣어서 16바이트나 32비트를 맞추던데 그냥 해시함수 쓰면 간단하게 해결됨.
(암호를 디비에 저장할때 털리지 말라고 솔트랑 해시를 씀)
var text = "동해물과백두산이" var password = "가나다라" var iv = ByteArray(16) val keySpec = SecretKeySpec(hashSHA256(password), "AES")
iv는 초기화 벡터라고 16바이트 배열인데 이 값에 따라 암호화 결과 값이 달라짐.
외부에 노출되도 (가급적 안되는게 좋겠지만) 암호화 된거 깨는데 큰 영향을 주지 않는다는 글을 봤음. 일단 예제는 0으로 채워진 16바이트로 함.
비밀번호(“가나다라”)를 hashSHA256 함수를 통해 32바이트 바이트배열로 변환해 넣어서 줌.
//암호화 하는 부분 val cipher_enc = Cipher.getInstance("AES/CBC/PKCS7Padding") cipher_enc.init(Cipher.ENCRYPT_MODE, keySpec, IvParameterSpec(iv)) val byteEncryptedText = cipher_enc.doFinal(text.toByteArray())
“AES/CBC/PKCS7PAdding” 이것은 옵션인데 종류가 상당히 많은데 자세한것은 Link 를 참고하면 될듯 싶음 (안드로이드 버전에 따라 지원되는 암호화 옵션이 바뀜)
마지막줄에서 실제적으로 텍스트를 암호화한다.
//복호화 하는 부분 val cipher_dec = Cipher.getInstance("AES/CBC/PKCS7Padding") cipher_dec.init(Cipher.DECRYPT_MODE, keySpec, IvParameterSpec(iv)) val byteDecryptedText = cipher_dec.doFinal(byteEncryptedText) Log.d("linsoo","원본 : "+text) Log.d("linsoo", "암호화 : "+ String(Base64.encode(byteEncryptedText, Base64.DEFAULT))) Log.d("linsoo", "복호화 : "+ String(byteDecryptedText))
복호화 하는 부분도 큰 차이가 없는데 cipher.init 부분에서 DECRYPT_MODE로 바꿔주기만 하면 된다. 인코딩 할때 사용했던 키와 iv를 넣어주는데 각각 1바이트라도 틀리면 인코딩이 안되니 주의하길..
화면에 출력할때 암호화 된 값을 Base64로 인코딩 하는건 바이트 배열 그대로 출력하면 안나오는 값이 있어서 가시화 할때 좋음. 이렇게 하면 맨 위 스샷 처럼 작동하는것을 볼 수 있음.
아래는 전체 소스
var text = "동해물과백두산이" var password = "가나다라" var iv = ByteArray(16) val keySpec = SecretKeySpec(hashSHA256(password), "AES") //암호화 하는 부분 val cipher_enc = Cipher.getInstance("AES/CBC/PKCS7Padding") cipher_enc.init(Cipher.ENCRYPT_MODE, keySpec, IvParameterSpec(iv)) val byteEncryptedText = cipher_enc.doFinal(text.toByteArray()) //복호화 하는 부분 val cipher_dec = Cipher.getInstance("AES/CBC/PKCS7Padding") cipher_dec.init(Cipher.DECRYPT_MODE, keySpec, IvParameterSpec(iv)) val byteDecryptedText = cipher_dec.doFinal(byteEncryptedText) Log.d("linsoo","원본 : "+text) Log.d("linsoo", "암호화 : "+ String(Base64.encode(byteEncryptedText, Base64.DEFAULT))) Log.d("linsoo", "복호화 : "+ String(byteDecryptedText))
답글 남기기