Skip to content

Commit

Permalink
address PR feedback
Browse files Browse the repository at this point in the history
  • Loading branch information
JesusMcCloud committed Oct 29, 2024
1 parent 952710f commit 6b6460a
Show file tree
Hide file tree
Showing 4 changed files with 77 additions and 97 deletions.
69 changes: 21 additions & 48 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,6 @@

### 3.10.0 NEXT (Supreme 0.5.0 NEXT)

The public API remains unchanged, except for some methods migrating from a ByteIterator to kotlinx-io Source
and some newly added. The internals have changed substantially, however.
Be sure to match Signum versions if multiple libraries pull it in as transitive dependency.
Better safe than sorry!

Expand All @@ -32,40 +30,31 @@ Better safe than sorry!
* Add HMAC JCA names, properties used in JSON Web Encryption

### 3.8.2 (Supreme 0.3.2)

* Less destructive Hotfix
for [KT-71650](https://youtrack.jetbrains.com/issue/KT-71650/Invalid-Objective-C-Header-in-XCFramework)
* Less destructive Hotfix for [KT-71650](https://youtrack.jetbrains.com/issue/KT-71650/Invalid-Objective-C-Header-in-XCFramework)
* Re-enables export of `Asn1Element.Tag` class to ObjC.

### 3.8.1 (Supreme 0.3.1)

* Hotfix for [KT-71650](https://youtrack.jetbrains.com/issue/KT-71650/Invalid-Objective-C-Header-in-XCFramework)
* Disables export of `Asn1Element.Tag` class to ObjC. Signum remains usable for KMP projects,
the Tag class just cannot be directly accessed from Swift and ObjC any more.
the Tag class just cannot be directly accessed from Swift and ObjC any more.

### 3.8.0 (Supreme 0.3.0) Breaking Changes Ahead!

* Completely revamped ASN.1 Tag Handling
* Properly handle multi-byte tags
* Introduce a new data structure `TLV.Tag` with an accompanying `TagClass` enum and a `constructed` flag to
accurately represent arbitrary tags up to `ULong.MAX_VALUE`
* Introduce a new data structure `TLV.Tag` with an accompanying `TagClass` enum and a `constructed` flag to accurately represent arbitrary tags up to `ULong.MAX_VALUE`
* Make all `tag` parameters `ULong` to reflect support for multi-byte tags
* Remove `DERTags`
* Revamp implicit tagging (there is still work to be done, but at least it supports CONSTRUCTED ASN.1 elements)
* Refactor `Int.Companion.decodeFromDer` -> `Int.Companion.decodeFromDerValue()`
* Refactor `Long.Companion.decodeFromDer` -> `Long.Companion.decodeFromDerValue()`
* Introduce `ULong.Companion.decodeFromDer` which can handle overlong inputs, as long as they start with a valid ULong
encoding
* Introduce `ULong.Companion.decodeFromDer` which can handle overlong inputs, as long as they start with a valid ULong encoding
* Changed return type of `Verifier::verify` from `KmmResult<Unit>` to `KmmResult<Success>`. Usage is unchanged.
* Add `ConfirmationClaim` to
represent [Proof-of-Possesion Key Semantics for JWTs](https://datatracker.ietf.org/doc/html/rfc7800)
* Add claims to `JsonWebToken` to
implement [Demonstrating Proof of Possession](https://datatracker.ietf.org/doc/html/rfc9449)
* Add `ConfirmationClaim` to represent [Proof-of-Possesion Key Semantics for JWTs](https://datatracker.ietf.org/doc/html/rfc7800)
* Add claims to `JsonWebToken` to implement [Demonstrating Proof of Possession](https://datatracker.ietf.org/doc/html/rfc9449)
* Replace `JsonWebToken.confirmationKey` by `JsonWebToken.confirmationClaim`, the implementation was wrong
* Introduce `ULong.toAsn1VarInt()` to encode ULongs into ASN.1 unsigned VarInts (**not to be confused with
multi^2_base's`UVarInt`!**)
* Introduce `decodeAsn1VarULong()` and `decodeAsn1VarUInt()` which can handle overlong inputs, as long as they start
with a valid unsigned number encoding.
* Introduce `decodeAsn1VarULong()` and `decodeAsn1VarUInt()` which can handle overlong inputs, as long as they start with a valid unsigned number encoding.
* Comes in three ULong flavours:
* `Iterator<Byte>.decodeAsn1VarULong()`
* `Iterable<Byte>.decodeAsn1VarULong()`
Expand All @@ -78,25 +67,21 @@ Better safe than sorry!
* Revamp `Asn1Element.parse()`, introducing new variants. This yields:
* `Asn1Element.parse()` with the same semantics as before
* `Asn1Element.parse()` alternative introduced, which takes a `ByteIterator` instead of a `ByteArray`
* `Asn1Element.parseAll()` introduced, which consumes all bytes and returns a list of all ASN.1 elements (if parsing
works)
* `Asn1Element.parseAll()` introduced, which consumes all bytes and returns a list of all ASN.1 elements (if parsing works)
* Variant 1 takes a `ByteIterator`
* Variant 2 takes a `ByteArray`
* `Asn1Element.parseFirst()` introduced, which tries to only parse a single ASN.1 element from the input and leaves
the rest untouched.
* `Asn1Element.parseFirst()` introduced, which tries to only parse a single ASN.1 element from the input and leaves the rest untouched.
* Variant 1 takes a `ByteIterator` and returns the element; the `ByteIterator` is advanced accordingly
* Variant 2 takes a `ByteArray` and returns a `Pair` of `(element, remainingBytes)`
* More consistent low-level encoding and decoding function names:
* `encodeToAsn1Primitive` to produce an `Asn1Primitive` that can directly be DER-encoded
* `encodeToAsn1ContentBytes` to produce the content bytes of a TLV primitive (the _V_ in TLV)
* `decodeToXXX` to be invoked on an `Asn1Primitive` to decode a DER-encoded primitive into the target type
* `decodeFromAsn1ContentBytes` to be invoked on the companion of the target type to decode the content bytes of a
TLV primitive (the _V_ in TLV)
* `decodeFromAsn1ContentBytes` to be invoked on the companion of the target type to decode the content bytes of a TLV primitive (the _V_ in TLV)
* Update conventions -> Coroutines 1.9.0
* replace `runCatching` with `catching` to be extra-safe

### 3.7.0 (Supreme 0.2.0)

* Remove Swift verifier logic to obtain a general speed-up
* Implement supreme signing capabilities
* Introduce Attestation Data Structure
Expand All @@ -106,11 +91,9 @@ Better safe than sorry!
* kotlinx-datetime 0.6.1

### 3.6.1

* Externalise `UVarInt` to multibase
* Externalise `UVarInt` to multibase

### 3.6.0

* Rebranding to Signum
* maven coordinates: `at.asitplus.signum:$module`
* modules
Expand Down Expand Up @@ -139,6 +122,7 @@ Better safe than sorry!
* `ByteStringWrapper` is not part of upstream snapshot cose serialization anymore,
but implemented as part of `datatypes-cose` in package `at.asitplus.crypto.datatypes.cose.io`


### 3.5.0

**Fixes**
Expand All @@ -156,15 +140,13 @@ Better safe than sorry!
* Externalise multibase implementation

### 3.2.2

* KmmResult 1.7.0
* Bignum 0.3.10 stable
* okio 3.9.0

### 3.2.1

**Fixes**

* Correct serialization of COSE signature structures

### 3.2.0
Expand All @@ -190,8 +172,7 @@ Better safe than sorry!
* Rename `toCryptoAlgorithm` to `toX509SignatureAlgorithm` accordingly
* Rework CryptoSignature to two-dimensional interface:
* CryptoSignature <- {EC <- {IndefiniteLength, DefiniteLength}, RsaOrHmac}
* CryptoSignature <- {RawByteEncodable <- {EC.DefiniteLength, RsaOrHmac}, NotRawByteEncodable <-
EC.IndefiniteLength}
* CryptoSignature <- {RawByteEncodable <- {EC.DefiniteLength, RsaOrHmac}, NotRawByteEncodable <- EC.IndefiniteLength}

### 3.1.0

Expand Down Expand Up @@ -222,6 +203,7 @@ Better safe than sorry!
* Add generic `ECPoint` class
* Implement elliptic-curve arithmetic


### 3.0.0

**Fixes**
Expand All @@ -231,12 +213,11 @@ Better safe than sorry!
* Fix parsing of CryptoSignature when decoding Certificates
* Remove bogus `serialize()` function from `CryptoSignature` **THIS IS A BREAKING CHANGE**


**Features**

* Wrap exceptions during deserialization in `KmmResult`, i.e. changing all `deserialize()` methods in companion objects
**THIS IS A BREAKING CHANGE**
* Move class `JweDecrypted` from package `at.asitplus.wallet.lib.jws` to `at.asitplus.crypto.datatypes.jws` **THIS IS A
BREAKING CHANGE**
* Wrap exceptions during deserialization in `KmmResult`, i.e. changing all `deserialize()` methods in companion objects **THIS IS A BREAKING CHANGE**
* Move class `JweDecrypted` from package `at.asitplus.wallet.lib.jws` to `at.asitplus.crypto.datatypes.jws` **THIS IS A BREAKING CHANGE**
* Support more JWE algorithms, e.g. AES
* Add `header` to constructor parameters of `JweEncrypted`
* Extend properties of `JsonWebKey`
Expand All @@ -249,10 +230,10 @@ Better safe than sorry!
* Expose `TbsCertificate.issuerAltNames` and `TbsCertificte.subjectAltnames`, which contain (somewhat) parsed
`AlternativeNames` structures for easy access to `dnsName`. `iPAddress`, etc.


## 2.0

### 2.6.0

* Pull in `JsonWebKeySet` from `vclib`
* Implement JWK Set Url (`jku`) in JWS headers
* Implement Attestation JWT (`jwt`) in JWS headers
Expand All @@ -262,7 +243,6 @@ Better safe than sorry!
* Certificate to/from JCA certificate conversion functions

### 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/)
Expand All @@ -272,7 +252,6 @@ Better safe than sorry!
* Rename `BERTags.NULL` to `BERTags.ASN1_NULL` to fix broken ObjC export

### 2.4.0

* Add Support for EC Point compression
* Add Support for full Cose-Key Spec
* Correct Multibase Encoding
Expand All @@ -285,22 +264,19 @@ Better safe than sorry!
* Rename `JsonWebKey.fromKeyId` to `JsonWebKey.fromDid`

### 2.3.0

* Change `CryptoPublicKey.toJsonWebKey()` return type from `KmmResult<JsonWebKey>` to `JsonWebKey`
* Add `CryptoSignature.parseFromJca` function
* Refactor `CryptoPublicKey.keyID` to `CryptoPublicKey.didEncoded` to better reflect what it actually is
* Rename `CryptoPublicKey.fromKeyId` to `CryptoPublicKey.fromDid`

### 2.2.1

* Update conventions
* Rename CBOR annotations
* Target Java 17

### 2.2.0

* Dependency Updates
* KmmResult 1.5.4
* KmmResult 1.5.4
* Refactor `MultiBaseHelper` to only handle conversion
* Change `JwsHeader.publicKey` from JsonWebKey to CryptoPublicKey
* Remove `SignatureValueLength` parameters from JWS & COSE Algorithm Enum class
Expand All @@ -312,7 +288,6 @@ Better safe than sorry!
* Remove VcLib-specific constants

### 2.1.0

* Kotlin 1.9.20
* COSE Support
* Full RSA and HMAC Support
Expand All @@ -324,11 +299,10 @@ Better safe than sorry!
* Throw `IllegalArgumentException` for input-related errors
* Add `xxxOrNull()` functions for all encoding/decoding/parsing functions
* Add `xxxSafe()` functions to encapsulate encoding/decoding in `KmmResult`
* Return `KmmResult` for conversions between different key representations ( i.e. `CryptoPublicKey`, `CoseKey` and
`JsonWebKey`)
* Return `KmmResult` for conversions between different key representations ( i.e. `CryptoPublicKey`, `CoseKey` and `JsonWebKey`)

### 2.0.0

### 2.0.0
* JWS Support
* Bugfixes and streamlining all over the place
* Proper BIT STRING
Expand All @@ -341,5 +315,4 @@ Better safe than sorry!
## 1.0

### 1.0.0

First public release
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ private fun Source.doParseExactly(nBytes: Long): List<Asn1Element> = mutableList
list.add(elem)
nBytesRead += read
}
require(nBytesRead == nBytes) { (if (nBytesRead < nBytes) "Less " else "More ") + " bytes read ($nBytesRead) than allowed ($nBytes)" }
require(nBytesRead == nBytes) { "Fewer bytes read ($nBytesRead) than allowed ($nBytes)" }
}

/**
Expand All @@ -114,7 +114,7 @@ fun Source.readFullyToAsn1Elements(): Pair<List<Asn1Element>, Long> = mutableLis
/**
* Reads a [TagAndLength] and the number of consumed bytes from the source without consuming it
*/
fun Source.peekTagAndLen() = peek().readTagAndLength()
private fun Source.peekTagAndLen() = peek().readTagAndLength()

/**
* Decodes a single [Asn1Element] from this source.
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package at.asitplus.signum.indispensable.asn1.encoding

import at.asitplus.catching
import at.asitplus.catchingUnwrapped
import at.asitplus.signum.indispensable.asn1.ObjectIdentifier
import at.asitplus.signum.indispensable.io.appendUnsafe
import at.asitplus.signum.indispensable.io.ensureSize
Expand Down Expand Up @@ -315,7 +316,7 @@ fun Uuid.toBigInteger(): BigInteger = BigInteger.fromByteArray(toByteArray(), Si
*/
@OptIn(ExperimentalUuidApi::class)
fun Uuid.Companion.fromBigintOrNull(bigInteger: BigInteger): Uuid? =
catching { fromByteArray(bigInteger.toByteArray().ensureSize(16)) }.getOrNull()
catchingUnwrapped { fromByteArray(bigInteger.toByteArray().ensureSize(16)) }.getOrNull()


///////////KTX-IO
Expand Down Expand Up @@ -343,23 +344,40 @@ fun Sink.writeAsn1VarInt(number: UInt) = writeAsn1VarInt(number.toULong(), UInt.
* @return the number of bytes written to the sink
*/
private fun Sink.writeAsn1VarInt(number: ULong, bits: Int): Int {
if (number < 128u) return writeByte(number.toByte()).run { 1 } //Fast case
var offset = 0
var result = mutableListOf<Byte>()

var b0 = (number shr offset and UVARINT_MASK_ULONG).toByte()
while ((number shr offset > 0uL) || offset == 0) {
result += b0
offset += 7
if (offset > (bits - 1)) break //End of Fahnenstange
b0 = (number shr offset and UVARINT_MASK_ULONG).toByte()
}
result.forEachIndexed { index, _ ->
writeByte(result.fromBack(index) or result.asn1VarIntByteMask(index))
val numBytes = (number.bitLength + 6) / 7 // division rounding up
(numBytes - 1).downTo(0).forEach { byteIndex ->
writeUByte(
((number shr (byteIndex * 7)).toUByte() and UVARINT_MASK_UBYTE) or
(if (byteIndex > 0) UVARINT_SINGLEBYTE_MAXVALUE_UBYTE else 0u)
)
}
return result.size
//otherwise we won't ever write zero
return if (numBytes == 0) {
writeByte(0)
1
} else numBytes
}

/**
* the number of bits required to represent this number
*/
val ULong.bitLength inline get() = ULong.SIZE_BITS - this.countLeadingZeroBits()

/**
* the number of bits required to represent this number
*/
val Long.bitLength inline get() = Long.SIZE_BITS - this.countLeadingZeroBits()

/**
* the number of bits required to represent this number
*/
val UInt.bitLength inline get() = UInt.SIZE_BITS - this.countLeadingZeroBits()

/**
* the number of bits required to represent this number
*/
val Int.bitLength inline get() = Int.SIZE_BITS - this.countLeadingZeroBits()

/**
* Encodes this number using varint encoding as used within ASN.1: groups of seven bits are encoded into a byte,
* while the highest bit indicates if more bytes are to come
Expand Down
Loading

0 comments on commit 6b6460a

Please sign in to comment.