AES키를 기기 내부에 저장하는 것도 했으니 RSA도 해봄.
var privateKey : PrivateKey? = null
var publicKey : PublicKey? = null
var alias = "linsoo.pe.kr"
var privateKey : PrivateKey? = null
var publicKey : PublicKey? = null
var alias = "linsoo.pe.kr"
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)
}
var ks : KeyStore = KeyStore.getInstance("AndroidKeyStore").apply {
load(null)
}
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
}
}
if(ks.containsAlias(alias)) {
val entry: KeyStore.Entry = ks.getEntry(alias, null)
if (entry is KeyStore.PrivateKeyEntry) {
privateKey = entry.privateKey
publicKey = entry.certificate.publicKey
}
}
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
}
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
}
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))
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))
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 간략하게 정리하면 이렇게 되고 입맛대로 쓰면 될듯 싶습니다.
답글 남기기