Skip to content

Commit

Permalink
Certificate revocation (eu-digital-green-certificates#73)
Browse files Browse the repository at this point in the history
  • Loading branch information
oleksandrsarapulovgl authored Feb 14, 2022
1 parent 095b532 commit e4ad73e
Show file tree
Hide file tree
Showing 2 changed files with 70 additions and 17 deletions.
2 changes: 1 addition & 1 deletion decoder/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ android {
compileSdkVersion 30

defaultConfig {
minSdkVersion 21
minSdkVersion 23
targetSdkVersion 30
versionCode 1
versionName "1.0.0"
Expand Down
85 changes: 69 additions & 16 deletions decoder/src/main/java/dgca/verifier/app/decoder/Extensions.kt
Original file line number Diff line number Diff line change
Expand Up @@ -22,18 +22,24 @@

package dgca.verifier.app.decoder

import android.security.keystore.KeyGenParameterSpec
import android.security.keystore.KeyProperties
import android.util.Base64
import com.upokecenter.cbor.CBORObject
import dgca.verifier.app.decoder.model.KeyPairData
import java.io.ByteArrayInputStream
import java.security.KeyPairGenerator
import java.security.MessageDigest
import java.security.*
import java.security.cert.CertificateFactory
import java.security.cert.X509Certificate
import java.security.spec.ECGenParameterSpec

const val ECDSA_256 = -7
const val RSA_PSS_256 = -37

const val ANDROID_KEYSTORE_PROVIDER = "AndroidKeyStore"
const val SHA_256_WITH_ECDSA = "SHA256withECDSA"
const val SHA_256_WITH_RSA = "SHA256WithRSA"

fun ByteArray.toBase64(): String = Base64.encodeToString(this, Base64.NO_WRAP)

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

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

fun String.toBase64(): String = Base64.encodeToString(this.toByteArray(), Base64.NO_WRAP)

fun String.base64ToX509Certificate(): X509Certificate? {
val decoded = Base64.decode(this, Base64.NO_WRAP)
val inputStream = ByteArrayInputStream(decoded)
Expand All @@ -57,23 +65,68 @@ fun ByteArray.toHash(): String {
.toBase64()
}

fun ByteArray.generateKeyPair(): KeyPairData? {
private fun provideEcKeyPairData(alias: String): KeyPairData {
val keyPairGen = KeyPairGenerator.getInstance(KeyProperties.KEY_ALGORITHM_EC, ANDROID_KEYSTORE_PROVIDER)
val keyPairGeneratorSpec = KeyGenParameterSpec.Builder(
alias,
KeyProperties.PURPOSE_SIGN or KeyProperties.PURPOSE_VERIFY
)
.setAlgorithmParameterSpec(ECGenParameterSpec("secp256r1"))
.setDigests(
KeyProperties.DIGEST_SHA256,
KeyProperties.DIGEST_SHA384,
KeyProperties.DIGEST_SHA512
)
.setKeySize(256)
.build()
keyPairGen.initialize(keyPairGeneratorSpec)
return KeyPairData(SHA_256_WITH_ECDSA, keyPairGen.generateKeyPair())
}

private fun provideRsaKeyPairData(alias: String): KeyPairData {
val keyPairGen = KeyPairGenerator.getInstance(KeyProperties.KEY_ALGORITHM_RSA, ANDROID_KEYSTORE_PROVIDER)
val keyGenParameterSpec = KeyGenParameterSpec.Builder(
alias,
KeyProperties.PURPOSE_SIGN or KeyProperties.PURPOSE_VERIFY
)
.setDigests(KeyProperties.DIGEST_SHA256, KeyProperties.DIGEST_SHA512)
.setKeySize(2048)
.setSignaturePaddings(KeyProperties.SIGNATURE_PADDING_RSA_PKCS1)
.build()

keyPairGen.initialize(keyGenParameterSpec)
return KeyPairData(SHA_256_WITH_RSA, keyPairGen.generateKeyPair())
}

fun ByteArray.generateKeyPairFor(alias: String): KeyPairData? {
val messageObject = CBORObject.DecodeFromBytes(this)
val protectedHeader = messageObject[0].GetByteString()

// get algorithm from header
when (CBORObject.DecodeFromBytes(protectedHeader).get(1).AsInt32Value()) {
ECDSA_256 -> {
val keyPairGen = KeyPairGenerator.getInstance("EC")
keyPairGen.initialize(256)
return KeyPairData("SHA256withECDSA", keyPairGen.generateKeyPair())
}
RSA_PSS_256 -> {
val keyPairGen = KeyPairGenerator.getInstance("RSA")
keyPairGen.initialize(2048)
return KeyPairData("SHA256WithRSA", keyPairGen.generateKeyPair())
}
return when (CBORObject.DecodeFromBytes(protectedHeader).get(1).AsInt32Value()) {
ECDSA_256 -> provideEcKeyPairData(alias)
RSA_PSS_256 -> provideRsaKeyPairData(alias)
else -> null
}
}

fun getKeyPairFor(alias: String): KeyPairData {
val ks: KeyStore = KeyStore.getInstance(ANDROID_KEYSTORE_PROVIDER)
ks.load(null)
val entry: KeyStore.Entry = ks.getEntry(alias, null)
val privateKey: PrivateKey = (entry as KeyStore.PrivateKeyEntry).privateKey
val publicKey: PublicKey = ks.getCertificate(alias).publicKey
val keyPair = KeyPair(publicKey, privateKey)
val algo = when (privateKey.algorithm) {
KeyProperties.KEY_ALGORITHM_EC -> SHA_256_WITH_ECDSA
KeyProperties.KEY_ALGORITHM_RSA -> SHA_256_WITH_RSA
else -> throw IllegalArgumentException()
}
return KeyPairData(algo, keyPair)
}

return null
}
fun deleteKeyPairFor(alias: String) {
val ks: KeyStore = KeyStore.getInstance(ANDROID_KEYSTORE_PROVIDER)
ks.load(null)
ks.deleteEntry(alias)
}

0 comments on commit e4ad73e

Please sign in to comment.