Skip to content

Commit e4ad73e

Browse files
Certificate revocation (#73)
1 parent 095b532 commit e4ad73e

File tree

2 files changed

+70
-17
lines changed

2 files changed

+70
-17
lines changed

decoder/build.gradle

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ android {
77
compileSdkVersion 30
88

99
defaultConfig {
10-
minSdkVersion 21
10+
minSdkVersion 23
1111
targetSdkVersion 30
1212
versionCode 1
1313
versionName "1.0.0"

decoder/src/main/java/dgca/verifier/app/decoder/Extensions.kt

Lines changed: 69 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -22,18 +22,24 @@
2222

2323
package dgca.verifier.app.decoder
2424

25+
import android.security.keystore.KeyGenParameterSpec
26+
import android.security.keystore.KeyProperties
2527
import android.util.Base64
2628
import com.upokecenter.cbor.CBORObject
2729
import dgca.verifier.app.decoder.model.KeyPairData
2830
import java.io.ByteArrayInputStream
29-
import java.security.KeyPairGenerator
30-
import java.security.MessageDigest
31+
import java.security.*
3132
import java.security.cert.CertificateFactory
3233
import java.security.cert.X509Certificate
34+
import java.security.spec.ECGenParameterSpec
3335

3436
const val ECDSA_256 = -7
3537
const 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+
3743
fun ByteArray.toBase64(): String = Base64.encodeToString(this, Base64.NO_WRAP)
3844

3945
fun ByteArray.toHexString(): String = joinToString("") { "%02x".format(it) }
@@ -44,6 +50,8 @@ fun String.hexToByteArray(): ByteArray = chunked(2)
4450

4551
fun String.fromBase64(): ByteArray = Base64.decode(this, Base64.NO_WRAP)
4652

53+
fun String.toBase64(): String = Base64.encodeToString(this.toByteArray(), Base64.NO_WRAP)
54+
4755
fun 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

Comments
 (0)