Skip to content

Commit

Permalink
Release 2.5.0
Browse files Browse the repository at this point in the history
* Parse more certificates from `x5c` in JWS headers
* Kotlin 1.9.23 thanks to updated conventions
* Generate `KnownOIDs` using [KotlinPoet](https://square.github.io/kotlinpoet/)
* Work around KT-65315 thanks to updated conventions
* BigNum as API dependency and iOS export (seems nonsensical,
  but is somehow required when using this inside a compose multiplatform app)
* Rename `BERTags.NULL` to `BERTags.ASN1_NULL` to fix broken ObjC export
  • Loading branch information
JesusMcCloud committed Mar 18, 2024
2 parents a78a967 + 0890f97 commit d4b9500
Show file tree
Hide file tree
Showing 36 changed files with 321 additions and 3,175 deletions.
9 changes: 9 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -67,3 +67,12 @@
* Finally make `CoseKey`'s EC Point compression play nicely with kotlinx.serialization
* Rename `CoseKey.fromKeyId` to `CoseKey.fromDid`
* Rename `JsonWebKey.fromKeyId` to `JsonWebKey.fromDid`

### 2.5.0
* Parse more certificates from `x5c` in JWS headers
* Kotlin 1.9.23 thanks to updated conventions
* Generate `KnownOIDs` using [KotlinPoet](https://square.github.io/kotlinpoet/)
* Work around KT-65315 thanks to updated conventions
* BigNum as API dependency and iOS export (seems nonsensical,
but is somehow required when using this inside a compose multiplatform app)
* Rename `BERTags.NULL` to `BERTags.ASN1_NULL` to fix broken ObjC export
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

[![GitHub license](https://img.shields.io/badge/license-Apache%20License%202.0-brightgreen.svg?style=flat)](http://www.apache.org/licenses/LICENSE-2.0)
[![Kotlin](https://img.shields.io/badge/kotlin-multiplatform-orange.svg?logo=kotlin)](http://kotlinlang.org)
[![Kotlin](https://img.shields.io/badge/kotlin-1.9.22-blue.svg?logo=kotlin)](http://kotlinlang.org)
[![Kotlin](https://img.shields.io/badge/kotlin-1.9.23-blue.svg?logo=kotlin)](http://kotlinlang.org)
[![Java](https://img.shields.io/badge/java-17+-blue.svg?logo=OPENJDK)](https://www.oracle.com/java/technologies/downloads/#java11)
[![Maven Central](https://img.shields.io/maven-central/v/at.asitplus.crypto/datatypes)](https://mvnrepository.com/artifact/at.asitplus.crypto/datatypes/)

Expand Down
2 changes: 1 addition & 1 deletion build.gradle.kts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import org.jetbrains.dokka.gradle.DokkaMultiModuleTask

plugins {
id("at.asitplus.gradle.conventions") version "1.9.10+20240219"
id("at.asitplus.gradle.conventions") version "1.9.23+20240318"
}
group = "at.asitplus.crypto"

Expand Down
12 changes: 3 additions & 9 deletions datatypes-cose/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ kotlin {
languageSettings.optIn("kotlin.ExperimentalUnsignedTypes")
}

val commonMain by getting {
commonMain {
dependencies {
api(project(":datatypes"))
api(serialization("cbor"))
Expand All @@ -35,13 +35,6 @@ kotlin {
implementation(libs.bignum) //Intellij bug work-around
}
}

val commonTest by getting {
dependencies {
implementation(kotlin("reflect"))
}
}
val jvmTest by getting
}
}

Expand All @@ -50,7 +43,8 @@ exportIosFramework(
serialization("cbor"),
datetime(),
kmmresult(),
project(":datatypes")
project(":datatypes"),
libs.bignum
)

val javadocJar = setupDokka(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,6 @@ sealed class CoseKeyParams {
if (this === other) return true
if (other == null || other !is EcKeyParams<*>) return false

other as EcKeyParams<*>

if (curve != other.curve) return false
if (x != null) {
if (other.x == null) return false
Expand Down
13 changes: 4 additions & 9 deletions datatypes-jws/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ kotlin {
languageSettings.optIn("kotlin.ExperimentalUnsignedTypes")
}

val commonMain by getting {
commonMain {
dependencies {
api(project(":datatypes"))
implementation(libs.okio)
Expand All @@ -36,14 +36,8 @@ kotlin {
}
}

val commonTest by getting {
dependencies {
implementation(kotlin("reflect"))
}
}

val jvmMain by getting
val jvmTest by getting {
jvmTest {
dependencies {
implementation(libs.jose)
}
Expand All @@ -56,7 +50,8 @@ exportIosFramework(
serialization("json"),
datetime(),
kmmresult(),
project(":datatypes")
project(":datatypes"),
libs.bignum
)

val javadocJar = setupDokka(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -78,9 +78,9 @@ enum class JwsAlgorithm(val identifier: String, override val oid: ObjectIdentifi

private fun encodePSSParams(bits: Int): Asn1Sequence {
val shaOid = when (bits) {
256 -> KnownOIDs.`sha-256`
384 -> KnownOIDs.`sha-384`
512 -> KnownOIDs.`sha-512`
256 -> KnownOIDs.`sha_256`
384 -> KnownOIDs.`sha_384`
512 -> KnownOIDs.`sha_512`
else -> TODO()
}
return asn1Sequence {
Expand All @@ -94,7 +94,7 @@ enum class JwsAlgorithm(val identifier: String, override val oid: ObjectIdentifi
}
tagged(1.toUByte()) {
sequence {
append(KnownOIDs.`pkcs1-MGF`)
append(KnownOIDs.`pkcs1_MGF`)
sequence {
append(shaOid)
asn1null()
Expand Down Expand Up @@ -142,8 +142,8 @@ enum class JwsAlgorithm(val identifier: String, override val oid: ObjectIdentifi
HS256.oid, HS384.oid, HS512.oid,
-> fromOid(oid).also {
val tag = src.nextChild().tag
if (tag != BERTags.NULL)
throw Asn1TagMismatchException(BERTags.NULL, tag, "RSA Params not allowed.")
if (tag != BERTags.ASN1_NULL)
throw Asn1TagMismatchException(BERTags.ASN1_NULL, tag, "RSA Params not allowed.")
}

PS256.oid, PS384.oid, PS512.oid -> parsePssParams(src)
Expand All @@ -158,17 +158,17 @@ enum class JwsAlgorithm(val identifier: String, override val oid: ObjectIdentifi

val sigAlg = (first.nextChild() as Asn1Primitive).readOid()
val tag = first.nextChild().tag
if (tag != BERTags.NULL)
throw Asn1TagMismatchException(BERTags.NULL, tag, "PSS Params not supported yet")
if (tag != BERTags.ASN1_NULL)
throw Asn1TagMismatchException(BERTags.ASN1_NULL, tag, "PSS Params not supported yet")

val second = (seq.nextChild() as Asn1Tagged).verifyTag(1.toUByte()).single() as Asn1Sequence
val mgf = (second.nextChild() as Asn1Primitive).readOid()
if (mgf != KnownOIDs.`pkcs1-MGF`) throw IllegalArgumentException("Illegal OID: $mgf")
if (mgf != KnownOIDs.`pkcs1_MGF`) throw IllegalArgumentException("Illegal OID: $mgf")
val inner = second.nextChild() as Asn1Sequence
val innerHash = (inner.nextChild() as Asn1Primitive).readOid()
if (innerHash != sigAlg) throw IllegalArgumentException("HashFunction mismatch! Expected: $sigAlg, is: $innerHash")

if (inner.nextChild().tag != BERTags.NULL) throw IllegalArgumentException(
if (inner.nextChild().tag != BERTags.ASN1_NULL) throw IllegalArgumentException(
"PSS Params not supported yet"
)

Expand All @@ -179,9 +179,9 @@ enum class JwsAlgorithm(val identifier: String, override val oid: ObjectIdentifi

return sigAlg.let {
when (it) {
KnownOIDs.`sha-256` -> PS256.also { if (saltLen != 256 / 8) throw IllegalArgumentException("Non-recommended salt length used: $saltLen") }
KnownOIDs.`sha-384` -> PS384.also { if (saltLen != 384 / 8) throw IllegalArgumentException("Non-recommended salt length used: $saltLen") }
KnownOIDs.`sha-512` -> PS512.also { if (saltLen != 512 / 8) throw IllegalArgumentException("Non-recommended salt length used: $saltLen") }
KnownOIDs.`sha_256` -> PS256.also { if (saltLen != 256 / 8) throw IllegalArgumentException("Non-recommended salt length used: $saltLen") }
KnownOIDs.`sha_384` -> PS384.also { if (saltLen != 384 / 8) throw IllegalArgumentException("Non-recommended salt length used: $saltLen") }
KnownOIDs.`sha_512` -> PS512.also { if (saltLen != 512 / 8) throw IllegalArgumentException("Non-recommended salt length used: $saltLen") }

else -> throw IllegalArgumentException("Unsupported OID: $it")
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ import at.asitplus.crypto.datatypes.io.ByteArrayBase64Serializer
import at.asitplus.crypto.datatypes.jws.io.jsonSerializer
import at.asitplus.crypto.datatypes.pki.X509Certificate
import io.github.aakira.napier.Napier
import io.matthewnelson.encoding.base64.Base64
import io.matthewnelson.encoding.core.Decoder.Companion.decodeToByteArray
import kotlinx.datetime.Instant
import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable
Expand Down Expand Up @@ -90,10 +92,19 @@ data class JwsHeader(
?: keyId?.let { runCatching { CryptoPublicKey.fromDid(it) } }?.getOrNull()
?: certificateChain
?.firstNotNullOfOrNull {
runCatching { X509Certificate.decodeFromTlv(Asn1Element.parse(it) as Asn1Sequence).publicKey }.getOrNull()
runCatching {
X509Certificate.decodeFromTlv(Asn1Element.parse(it) as Asn1Sequence).publicKey
}.getOrNull() ?: runCatching {
X509Certificate.decodeFromTlv(Asn1Element.parse(it.decodeX5c()) as Asn1Sequence).publicKey
}.getOrNull()
}
}

private fun ByteArray.decodeX5c() = decodeToString()
.replace("-----BEGIN CERTIFICATE-----\n", "")
.replace("\n-----END CERTIFICATE-----", "")
.decodeToByteArray(Base64())

companion object {
fun deserialize(it: String) = kotlin.runCatching {
jsonSerializer.decodeFromString<JwsHeader>(it)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import at.asitplus.crypto.datatypes.jws.JwsAlgorithm
package at.asitplus.crypto.datatypes.jws

import io.kotest.core.spec.style.FreeSpec
import io.kotest.datatest.withData
import io.kotest.matchers.shouldBe
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
package at.asitplus.crypto.datatypes.jws

import at.asitplus.crypto.datatypes.CryptoPublicKey
import at.asitplus.crypto.datatypes.EcCurve
import at.asitplus.crypto.datatypes.asn1.encodeToByteArray
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
package at.asitplus.crypto.datatypes.jws

import at.asitplus.crypto.datatypes.CryptoPublicKey
import at.asitplus.crypto.datatypes.fromJcaPublicKey
import at.asitplus.crypto.datatypes.io.Base64Strict
import at.asitplus.crypto.datatypes.jws.jwkId
import at.asitplus.crypto.datatypes.jws.toJsonWebKey
import io.kotest.core.spec.style.FreeSpec
import io.kotest.datatest.withData
import io.kotest.matchers.nulls.shouldNotBeNull
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
package at.asitplus.crypto.datatypes.jws

import at.asitplus.crypto.datatypes.CryptoPublicKey
import at.asitplus.crypto.datatypes.getJcaPublicKey
import at.asitplus.crypto.datatypes.jws.JwsSigned
Expand Down
1 change: 1 addition & 0 deletions datatypes/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
generated/
Loading

0 comments on commit d4b9500

Please sign in to comment.