RSA Key를 Android Keystore 사용해서 저장하기

AES키를 기기 내부에 저장하는 것도 했으니 RSA도 해봄.

var privateKey : PrivateKey? = null
var publicKey  : PublicKey? = null
var alias = "linsoo.pe.kr"

Keystore 내부에 저장할때 별칭을 가지고 불러올수 있는데 일단 linsoo.pe.kr로 했음.

var ks : KeyStore = KeyStore.getInstance("AndroidKeyStore").apply {
    load(null)
}

키스토어 인스턴스를 가져옵니다.

if(ks.containsAlias(alias)) {
    val entry: KeyStore.Entry = ks.getEntry(alias, null)
    if (entry is KeyStore.PrivateKeyEntry) {
        privateKey = entry.privateKey
        publicKey = entry.certificate.publicKey
    }
}

키스토어내에 alias가 있는지 검색해보고 있으면 가져와서 개인키와 공개키를 뽑아냅니다.

else{
    val kpg = KeyPairGenerator.getInstance(KeyProperties.KEY_ALGORITHM_RSA,"AndroidKeyStore")
    val parameterSpec = KeyGenParameterSpec.Builder(
        alias,
        KeyProperties.PURPOSE_ENCRYPT or KeyProperties.PURPOSE_DECRYPT
    ).run {
        setAlgorithmParameterSpec(
            RSAKeyGenParameterSpec(
                2048,
                RSAKeyGenParameterSpec.F4
            )
        )
        setBlockModes(KeyProperties.BLOCK_MODE_ECB)
        setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_RSA_OAEP)
        setDigests(KeyProperties.DIGEST_SHA512)
        setUserAuthenticationRequired(false)
        build()
    }
    kpg.initialize(parameterSpec)
    val keys = kpg.generateKeyPair()
    privateKey = keys.private
    publicKey = keys.public
}

키스토어내에 alias가 없으면 새로 키를 생성합니다. 기본적인건 아니고 다양한 옵션이 있으니 기기 지원버전에 맞게 잘 선택하셔야 합니다.

var text = "동해물과 백두산이"

val oappSp = OAEPParameterSpec(
    "SHA-512",
    "MGF1",
    MGF1ParameterSpec.SHA1,
    PSource.PSpecified.DEFAULT
)
val encCipher = Cipher.getInstance("RSA/ECB/OAEPWithSHA-512AndMGF1Padding")
val decCipher = Cipher.getInstance("RSA/ECB/OAEPWithSHA-512AndMGF1Padding")
encCipher.init(Cipher.ENCRYPT_MODE,  publicKey, oappSp)
decCipher.init(Cipher.DECRYPT_MODE,  privateKey, oappSp)
var encryptTextByteArray = encCipher.doFinal(text.toByteArray())
var decryptTextByteArray = decCipher.doFinal(encryptTextByteArray)
Log.d("linsoo","원본텍스트 : "+text)
Log.d("linsoo", "암호화 : \n"+ String(Base64.encode(encryptTextByteArray, Base64.DEFAULT)))
Log.d("linsoo", "복호화 : "+ String(decryptTextByteArray))

암호화 하고 복호화 하는 부분입니다.
여기서 한가지 삽질했던것이 저 OAEPParameterSpec인데 첫번째 인자는 키 생성시 setDigests 랑 같아야 하고 MFG1ParameterSpec에 SHA는 별개인것입니다.

저는 위에 Digest에서 SHA-512로 해서 둘다 512로 해야 하는건줄 알았는데

“Unsupported MGF1 digest: SHA-512, Only SHA-1 supported” 라는 에러가 뜨더군요. 그래서 두개가 별개값이라는걸 알았습니다 -_-;

RSA Android Keystore 간략하게 정리하면 이렇게 되고 입맛대로 쓰면 될듯 싶습니다.

크리에이티브 커먼즈 라이선스 Linsoo 의 저작물인 이 저작물은(는) 크리에이티브 커먼즈 저작자표시-동일조건변경허락 4.0 국제 라이선스에 따라 이용할 수 있습니다.

댓글 2개

  1. 안녕하세요…
    저는 드론관련 종사자입니다.
    기술적인 문제로 문의를 드리고 싶습니다.
    혹시 괜찬으시면 제 메일로 회신주시면 답변 드리겠습니다.
    감사합니다.

댓글 달기

이메일 주소는 공개되지 않습니다.

This site is protected by reCAPTCHA and the Google Privacy Policy and Terms of Service apply.