Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

VDX-332 digidentity implementation #1

Open
wants to merge 7 commits into
base: pkcs7
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 11 additions & 11 deletions build.gradle.kts
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
plugins {
id("maven-publish")
kotlin("multiplatform") version "1.7.10"
kotlin("plugin.serialization") version "1.7.10"
kotlin("multiplatform") version "1.9.23"
kotlin("plugin.serialization") version "1.9.23"
id("io.gitlab.arturbosch.detekt") version "1.21.0"
}

group = "com.sphereon.vdx"
version = "1.0.0-SNAPSHOT"
version = "1.2.0-SNAPSHOT"


detekt {
Expand Down Expand Up @@ -63,14 +63,17 @@ kotlin {

val dssVersion = "5.11.1"
val kotlinSerializationVersion = "1.4.0-RC"
val kotlinDateTimeVersion = "0.4.0"
val kotlinDateTimeVersion = "0.5.0"
val bcVersion = "1.71"

val commonMain by getting {
dependencies {
api("org.jetbrains.kotlinx:kotlinx-serialization-json:$kotlinSerializationVersion")
api("org.jetbrains.kotlinx:kotlinx-datetime:$kotlinDateTimeVersion")
api("io.github.microutils:kotlin-logging:3.0.5")
implementation("io.matthewnelson.kotlin-components:encoding-base64:1.1.3")
implementation("com.mayakapps.kache:kache:2.1.0-beta05")
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.8.0")
}
}
val commonTest by getting {
Expand All @@ -95,17 +98,18 @@ kotlin {
implementation("eu.europa.ec.joinup.sd-dss:dss-pades-pdfbox:$dssVersion")
implementation("eu.europa.ec.joinup.sd-dss:dss-crl-parser-x509crl:$dssVersion")
api("org.bouncycastle:bcprov-debug-jdk18on:$bcVersion")
api("javax.cache:cache-api:1.1.1")
implementation("javax.xml.bind:jaxb-api:2.3.0")
api("jakarta.xml.bind:jakarta.xml.bind-api:3.0.1")
implementation("javax.annotation:javax.annotation-api:1.3.2")
implementation("javax.activation:activation:1.1.1")
api("org.glassfish.jaxb:jaxb-runtime:2.3.6")
implementation("com.fasterxml.jackson.module:jackson-module-kotlin:2.13.2")

api("io.github.microutils:kotlin-logging-jvm:2.1.23")

api("io.github.microutils:kotlin-logging-jvm:3.0.5")

// todo separate into separate project probably
api("com.sphereon.vdx:eidas-signature-client-rest-jersey3:1.0.0-SNAPSHOT")
api("com.sphereon.vdx:eidas-signature-client-rest-jersey3:1.1.0-SNAPSHOT")

implementation(project.dependencies.platform("com.azure:azure-sdk-bom:1.2.4"))
implementation("com.azure:azure-identity")
Expand All @@ -122,10 +126,6 @@ kotlin {

implementation("org.bouncycastle:bcpkix-jdk18on:$bcVersion")
implementation("io.mockk:mockk:1.12.4")

// implementation("com.fasterxml.jackson.module:jackson-module-kotlin:2.13.2")

implementation("org.ehcache:ehcache:3.8.1")
/* implementation("org.apache.logging.log4j:log4j-api:${log4jVersion}")
implementation("org.apache.logging.log4j:log4j-core:${log4jVersion}")
implementation("org.apache.logging.log4j:log4j-slf4j-impl:${log4jVersion}")
Expand Down
2 changes: 0 additions & 2 deletions gradle.properties
Original file line number Diff line number Diff line change
@@ -1,4 +1,2 @@
kotlin.code.style=official
kotlin.mpp.enableGranularSourceSetsMetadata=true
kotlin.native.enableDependencyPropagation=false
kotlin.js.generate.executable.default=false
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@ enum class CryptoAlg(val internalName: String, val oid: String, val padding: Str

RSA("RSA", "1.2.840.113549.1.1.1", "RSA/ECB/PKCS1Padding"),

SHA256_WITH_RSA("SHA256withRSA", "1.2.840.113549.1.1.11", "PKCS#1 v1.5 Padding"),

// DSA("DSA", "1.2.840.10040.4.1", "DSA"),

ECDSA("ECDSA", "1.2.840.10045.2.1", "ECDSA"),
Expand All @@ -44,5 +46,11 @@ enum class CryptoAlg(val internalName: String, val oid: String, val padding: Str
ED448("Ed448", "1.3.101.113", "Ed448"),

HMAC("HMAC", "", "");

companion object {
fun from(name: String): CryptoAlg = entries.find { it.internalName == name }
?: throw IllegalArgumentException("Algorithm $name not found")

}
}

Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,5 @@ package com.sphereon.vdx.ades.enums
* The Key Provider Types supported
*/
enum class KeyProviderType {
PKCS11, PKCS12, REST, JKS, AZURE_KEYVAULT
PKCS11, PKCS12, REST, JKS, AZURE_KEYVAULT, DIGIDENTITY
}
77 changes: 77 additions & 0 deletions src/commonMain/kotlin/com/sphereon/vdx/ades/pki/CacheService.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
@file:Suppress("MemberVisibilityCanBePrivate")

package com.sphereon.vdx.ades.pki

import com.mayakapps.kache.InMemoryKache
import com.mayakapps.kache.KacheStrategy
import com.mayakapps.kache.ObjectKache
import kotlinx.coroutines.runBlocking
import mu.KotlinLogging
import kotlin.time.DurationUnit
import kotlin.time.toDuration

private const val MAX_CACHE_SIZE = 1024L
private val logger = KotlinLogging.logger {}

open class CacheService<K : Any, V : Any>(
private val cacheName: String,
private val cacheEnabled: Boolean? = true,
private val cacheTTLInSeconds: Long? = 600,
) {
private var cache: ObjectKache<K, V>? = null

init {
initCache()
}

fun get(key: K): V? {
return runBlocking {
getAsync(key)
}
}

suspend fun getAsync(key: K): V? {
if (!isEnabled()) {
return null
}
val value = cache!!.get(key)
logger.debug { "Cache ${value?.let { "HIT" } ?: "MIS"} for key '$key' in cache '$cacheName'" }
return value
}

fun isEnabled(): Boolean {
return cacheEnabled == true && cache != null
}

fun put(key: K, value: V): V {
return runBlocking {
putAsync(key, value)
}
}

suspend fun putAsync(key: K, value: V): V {
logger.entry(key, value)
if (isEnabled()) {
logger.trace { "Caching value for key $key" }
cache!!.put(key, value)
if (cache!!.get(key) == null) {
throw RuntimeException("Item was not placed in the cache")
}
}
logger.exit(value)
return value
}

private fun initCache() {
logger.info { "Cache '$cacheName' is ${if (cacheEnabled == true) "" else "NOT"} being enabled..." }
if (cacheEnabled == true) {
if (cache == null) {
cache = InMemoryKache(maxSize = MAX_CACHE_SIZE) {
strategy = KacheStrategy.LRU
expireAfterAccessDuration = cacheTTLInSeconds!!.toDuration(DurationUnit.SECONDS)
}
logger.info { "Cache '$cacheName' now is enabled" }
}
}
}
}

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
package com.sphereon.vdx.ades.pki

import AbstractCacheObjectSerializer
import com.sphereon.vdx.ades.enums.CryptoAlg
import com.sphereon.vdx.ades.enums.DigestAlg
import com.sphereon.vdx.ades.enums.MaskGenFunction
Expand All @@ -16,6 +15,10 @@ import com.sphereon.vdx.ades.sign.util.toJavaPublicKey
import eu.europa.esig.dss.enumerations.SignatureAlgorithm
import eu.europa.esig.dss.spi.DSSSecurityProvider
import mu.KotlinLogging
import org.bouncycastle.asn1.ASN1ObjectIdentifier
import org.bouncycastle.asn1.DERNull
import org.bouncycastle.asn1.x509.AlgorithmIdentifier
import org.bouncycastle.asn1.x509.DigestInfo
import java.security.GeneralSecurityException
import java.security.spec.MGF1ParameterSpec
import java.security.spec.PSSParameterSpec
Expand All @@ -29,11 +32,11 @@ private val logger = KotlinLogging.logger {}
*/
abstract class AbstractKeyProviderService(
override val settings: KeyProviderSettings,
cacheObjectSerializer: AbstractCacheObjectSerializer<String, IKeyEntry>?
) : IKeyProviderService {

@Suppress("LeakingThis")
protected val cacheService: CacheService<String, IKeyEntry> =
CacheService("Keys", settings.config.cacheEnabled, settings.config.cacheTTLInSeconds, cacheObjectSerializer)
CacheService("Keys", settings.config.cacheEnabled, settings.config.cacheTTLInSeconds)


override fun createSignature(signInput: SignInput, keyEntry: IKeyEntry): Signature {
Expand Down Expand Up @@ -66,6 +69,7 @@ abstract class AbstractKeyProviderService(
else signature.algorithm.toDSS().jceId,
DSSSecurityProvider.getSecurityProviderName()
)

if (signature.algorithm.maskGenFunction != null) {
val digestJavaName: String = signature.algorithm.digestAlgorithm?.toDSS()!!.javaName
val parameterSpec = PSSParameterSpec(
Expand All @@ -79,12 +83,11 @@ abstract class AbstractKeyProviderService(
}

javaSig.initVerify(publicKey.toJavaPublicKey())
/*val digest = if (signInput.signMode == SignMode.DIGEST || signature.algorithm.digestAlgorithm == null) {
signInput.input
if (signInput.signMode == SignMode.DIGEST && signature.algorithm.digestAlgorithm != null) {
javaSig.update(derEncode(signature.algorithm.digestAlgorithm, signInput))
} else {
DSSUtils.digest(signature.algorithm.digestAlgorithm.toDSS(), signInput.input)
}*/
javaSig.update(signInput.input)
javaSig.update(signInput.input)
}
val verify = javaSig.verify(signature.value)
logger.info { "Signature with date '${signature.date}' and provider '${signature.providerId}' for input '${signInput.name}' was ${if (verify) "VALID" else "INVALID"}" }
logger.exit(verify)
Expand All @@ -95,7 +98,27 @@ abstract class AbstractKeyProviderService(
}
}

protected abstract fun createSignatureImpl(signInput: SignInput, keyEntry: IKeyEntry, mgf: MaskGenFunction? = null): Signature
/*
When we have predigested value instead the content that has yet to be digested, we need to make sure
we DER encode the hash because in RSA_RAW / NONEwithRSA mode BouncyCastle will no longer take care of this,
hence the verification will fail.
*/
private fun derEncode(
digestAlgorithm: DigestAlg,
signInput: SignInput
): ByteArray {
val asN1ObjectIdentifier = ASN1ObjectIdentifier(digestAlgorithm.oid)
val algId = AlgorithmIdentifier(asN1ObjectIdentifier, DERNull.INSTANCE)
val dInfo = DigestInfo(algId, signInput.input)
return dInfo.getEncoded("DER")
}

protected abstract fun createSignatureImpl(
signInput: SignInput,
keyEntry: IKeyEntry,
mgf: MaskGenFunction? = null
): Signature

protected fun isDigestMode(signInput: SignInput) =
signInput.signMode == SignMode.DIGEST && signInput.digestAlgorithm != DigestAlg.NONE
}
77 changes: 0 additions & 77 deletions src/jvmMain/kotlin/com/sphereon/vdx/ades/pki/CacheService.kt

This file was deleted.

Loading
Loading