2222
2323package dgca.verifier.app.decoder
2424
25+ import android.security.keystore.KeyGenParameterSpec
26+ import android.security.keystore.KeyProperties
2527import android.util.Base64
2628import com.upokecenter.cbor.CBORObject
2729import dgca.verifier.app.decoder.model.KeyPairData
2830import java.io.ByteArrayInputStream
29- import java.security.KeyPairGenerator
30- import java.security.MessageDigest
31+ import java.security.*
3132import java.security.cert.CertificateFactory
3233import java.security.cert.X509Certificate
34+ import java.security.spec.ECGenParameterSpec
3335
3436const val ECDSA_256 = - 7
3537const val RSA_PSS_256 = - 37
3638
39+ const val ANDROID_KEYSTORE_PROVIDER = " AndroidKeyStore"
40+ const val SHA_256_WITH_ECDSA = " SHA256withECDSA"
41+ const val SHA_256_WITH_RSA = " SHA256WithRSA"
42+
3743fun ByteArray.toBase64 (): String = Base64 .encodeToString(this , Base64 .NO_WRAP )
3844
3945fun ByteArray.toHexString (): String = joinToString(" " ) { " %02x" .format(it) }
@@ -44,6 +50,8 @@ fun String.hexToByteArray(): ByteArray = chunked(2)
4450
4551fun String.fromBase64 (): ByteArray = Base64 .decode(this , Base64 .NO_WRAP )
4652
53+ fun String.toBase64 (): String = Base64 .encodeToString(this .toByteArray(), Base64 .NO_WRAP )
54+
4755fun String.base64ToX509Certificate (): X509Certificate ? {
4856 val decoded = Base64 .decode(this , Base64 .NO_WRAP )
4957 val inputStream = ByteArrayInputStream (decoded)
@@ -57,23 +65,68 @@ fun ByteArray.toHash(): String {
5765 .toBase64()
5866}
5967
60- fun ByteArray.generateKeyPair (): KeyPairData ? {
68+ private fun provideEcKeyPairData (alias : String ): KeyPairData {
69+ val keyPairGen = KeyPairGenerator .getInstance(KeyProperties .KEY_ALGORITHM_EC , ANDROID_KEYSTORE_PROVIDER )
70+ val keyPairGeneratorSpec = KeyGenParameterSpec .Builder (
71+ alias,
72+ KeyProperties .PURPOSE_SIGN or KeyProperties .PURPOSE_VERIFY
73+ )
74+ .setAlgorithmParameterSpec(ECGenParameterSpec (" secp256r1" ))
75+ .setDigests(
76+ KeyProperties .DIGEST_SHA256 ,
77+ KeyProperties .DIGEST_SHA384 ,
78+ KeyProperties .DIGEST_SHA512
79+ )
80+ .setKeySize(256 )
81+ .build()
82+ keyPairGen.initialize(keyPairGeneratorSpec)
83+ return KeyPairData (SHA_256_WITH_ECDSA , keyPairGen.generateKeyPair())
84+ }
85+
86+ private fun provideRsaKeyPairData (alias : String ): KeyPairData {
87+ val keyPairGen = KeyPairGenerator .getInstance(KeyProperties .KEY_ALGORITHM_RSA , ANDROID_KEYSTORE_PROVIDER )
88+ val keyGenParameterSpec = KeyGenParameterSpec .Builder (
89+ alias,
90+ KeyProperties .PURPOSE_SIGN or KeyProperties .PURPOSE_VERIFY
91+ )
92+ .setDigests(KeyProperties .DIGEST_SHA256 , KeyProperties .DIGEST_SHA512 )
93+ .setKeySize(2048 )
94+ .setSignaturePaddings(KeyProperties .SIGNATURE_PADDING_RSA_PKCS1 )
95+ .build()
96+
97+ keyPairGen.initialize(keyGenParameterSpec)
98+ return KeyPairData (SHA_256_WITH_RSA , keyPairGen.generateKeyPair())
99+ }
100+
101+ fun ByteArray.generateKeyPairFor (alias : String ): KeyPairData ? {
61102 val messageObject = CBORObject .DecodeFromBytes (this )
62103 val protectedHeader = messageObject[0 ].GetByteString ()
63104
64105 // get algorithm from header
65- when (CBORObject .DecodeFromBytes (protectedHeader).get(1 ).AsInt32Value ()) {
66- ECDSA_256 -> {
67- val keyPairGen = KeyPairGenerator .getInstance(" EC" )
68- keyPairGen.initialize(256 )
69- return KeyPairData (" SHA256withECDSA" , keyPairGen.generateKeyPair())
70- }
71- RSA_PSS_256 -> {
72- val keyPairGen = KeyPairGenerator .getInstance(" RSA" )
73- keyPairGen.initialize(2048 )
74- return KeyPairData (" SHA256WithRSA" , keyPairGen.generateKeyPair())
75- }
106+ return when (CBORObject .DecodeFromBytes (protectedHeader).get(1 ).AsInt32Value ()) {
107+ ECDSA_256 -> provideEcKeyPairData(alias)
108+ RSA_PSS_256 -> provideRsaKeyPairData(alias)
109+ else -> null
110+ }
111+ }
112+
113+ fun getKeyPairFor (alias : String ): KeyPairData {
114+ val ks: KeyStore = KeyStore .getInstance(ANDROID_KEYSTORE_PROVIDER )
115+ ks.load(null )
116+ val entry: KeyStore .Entry = ks.getEntry(alias, null )
117+ val privateKey: PrivateKey = (entry as KeyStore .PrivateKeyEntry ).privateKey
118+ val publicKey: PublicKey = ks.getCertificate(alias).publicKey
119+ val keyPair = KeyPair (publicKey, privateKey)
120+ val algo = when (privateKey.algorithm) {
121+ KeyProperties .KEY_ALGORITHM_EC -> SHA_256_WITH_ECDSA
122+ KeyProperties .KEY_ALGORITHM_RSA -> SHA_256_WITH_RSA
123+ else -> throw IllegalArgumentException ()
76124 }
125+ return KeyPairData (algo, keyPair)
126+ }
77127
78- return null
79- }
128+ fun deleteKeyPairFor (alias : String ) {
129+ val ks: KeyStore = KeyStore .getInstance(ANDROID_KEYSTORE_PROVIDER )
130+ ks.load(null )
131+ ks.deleteEntry(alias)
132+ }
0 commit comments