ehn-dcc-development / hcert-kotlin Goto Github PK
View Code? Open in Web Editor NEWKotlin multiplatform implementation of the HCERT/DCC specification
License: Apache License 2.0
Kotlin multiplatform implementation of the HCERT/DCC specification
License: Apache License 2.0
The JVM target supports it, the JS target lacks it.
Fix it!
Consider relevant changes to the schema: https://github.com/ehn-dcc-development/ehn-dcc-schema/releases
I think there is a bug with DecisionService.
In line 33, this service is verifying that signing certificate's expiration date is not after DGC expiration time. This does not seem ok because the validity of the signing certificate must be greater than the validity off the signed document.
31 verificationResult.expirationTime?.let { expirationTime ->
32 verificationResult.certificateValidUntil?.let { certValidUntil ->
33 if (certValidUntil.isAfter(expirationTime))
34 return VerificationDecision.FAIL
35 }
36 if (expirationTime.isBefore(Instant.now()))
37 return VerificationDecision.FAIL
38 }
https://github.com/eu-digital-green-certificates/dcc-quality-assurance/blob/main/SpecialCaseHandling.md
https://github.com/eu-digital-green-certificates/dcc-quality-assurance/blob/main/NL/1.3.0/specialcases/TEST_EMPTY_DR_FIELD.png
this one is not working due to:
QR Code contains Version 1.3 Schema, but field "dr" is empty string and as optional in the Test QR Code
the quick fix might be
object InstantParser {
fun parseInstant(decoder: Decoder): Instant {
val value = decoder.decodeString()
val fixOffset = value.replace(Regex("\\+(\\d{2})(\\d{2})")) { "+${it.groupValues[1]}:${it.groupValues[2]}" }
val fixZulu = if (fixOffset.contains('Z') || fixOffset.contains("+")) fixOffset else fixOffset + 'Z'
return Instant.parse(fixZulu)
}
}
object LenientInstantParser : KSerializer<Instant> {
override val descriptor: SerialDescriptor = PrimitiveSerialDescriptor("Instant", PrimitiveKind.STRING)
override fun deserialize(decoder: Decoder): Instant {
return InstantParser.parseInstant(decoder)
}
override fun serialize(encoder: Encoder, value: Instant) {
encoder.encodeString(value.toString())
}
}
object NullableLenientInstantParser : KSerializer<Instant?> {
override val descriptor: SerialDescriptor = PrimitiveSerialDescriptor("Instant", PrimitiveKind.STRING)
override fun deserialize(decoder: Decoder): Instant? {
return try {
InstantParser.parseInstant(decoder)
} catch (e: Exception) {
e.printStackTrace()
null
}
}
override fun serialize(encoder: Encoder, value: Instant?) {
encoder.encodeString(value.toString())
}
}
but then there is an action:
Verifiers should remove all date format checks from date-time values/dates
a HCERT with DOB 1988-00-02 is set as valid, which does not conform to DCC specifications.
Hello it seems like there is an issue with the following class, have you encountered the same issues ?
java.lang.NoClassDefFoundError: kotlinx.datetime.Instant
similar to
Edit1:
The fix should be
https://developer.android.com/studio/write/java8-support#library-desugaring
Will try tomorrow, and let you know, it might be good to include it in the readme if it works
The current version 0.3.0-SNAPSHOT is not avaiable in
Downloading from ehd-github: https://maven.pkg.github.com/ehn-digital-green-development/*/ehn/techiop/hcert/hcert-kotlin/0.3.0-SNAPSHOT/hcert-kotlin-0.3.0-SNAPSHOT.pom
[WARNING] The POM for ehn.techiop.hcert:hcert-kotlin:jar:0.3.0-SNAPSHOT is missing, no dependency information available
It seems that the latest published version was 0.2.2-SNAPSHOT.
I've missed, that there is a ZXing Library for JS/TS: https://github.com/zxing-js/library
That one should be used instead of our current one for the JS target. Then, hopefully, encoding and decoding will work.
see #20
Hello,
is this correct? it seems they should be both type of ValueSetEntryAdapter
@SerialName("nm")
val nameNaa: String? = null,
@SerialName("ma")
val nameRat: ValueSetEntryAdapter? = null,
We currently rely on some specifics of the JS Legacy backend. It would be nice to update to IR, because we cannot update kotlinx-serialization and Kotest.
In addition, the current hard dependency on the legacy backend is not future-proof.
feature/update lifted all dependency versions as high as possible with the legacy backend, highlighting the issue of outdated dependencies.
Moreover, generated and hand-crafted glue to include JS libraries needs to be revised to reflect the IR-backend's constraints
Hello there,
I would like to ask you if you are planning to publish the library to a public repository so I dont have to create a github access token to get it. The main reason is becasue I am thinking about using this library in our green pass applications and it seems like the most effective way is to have one good library shared across countries rather than having custom implementations.
Hello @nodh
I just wanted to ask if there is a requirement from EU to throw away the data if the signing is expired. I was searching for it but could not find.
/**
* `exp` claim SHALL hold a timestamp.
* Verifier MUST reject the payload after expiration.
* It MUST not exceed the validity period of the DSC.
*/
var expirationTime: Instant? = null
https://github.com/ehn-dcc-development/hcert-kotlin/tree/feature/encoding-js contains some commits, that add code to encode HCERT data on the JS target.
It works, but one general problem remains though:
This encodes all keys inside the CWT as Strings, but they should be Integers:
This works around this issue on the decoding side:
So we'll need to find a way, to encode the keys of a map as integers.
Not really an issue but a question. Sorry for the utter noobism to write an issue which isn't one.
I am currently trying to integrate any covid SDK into a cordova app to verify certificates. Because we are located in switzerland, it would have been great to support swiss "light" certificates. But because the Swiss government only offers Android and iOS SDKs, which we unsuccessfully tried to wrap into a cordova plugin, I integrated the hcert JavaScript library you are offering.
This works like a charm for all EU test certificates, but unfortunately neither for regular Swiss certificates nor for test ones. Swiss certs should officially be supported by EU implementations since friday (09.07.2021).
So my questions are:
Many thanks in advance
Michel
Currently, both the JVM target and the JS target do not support all JSON schema features.
On JS, schema validation is known to not cover all aspects, on the JVM, further investigation is needed.
if you scan a code with missing test facility, the validation fails. the fix is to define the default value as null
@SerialName("tc")
val testFacility: String? = null,
i think the default values are needed, or kotlinx serialization can enable the null validation/parsing
you can test it here
https://github.com/eu-digital-green-certificates/dcc-quality-assurance/blob/main/SI/1.3.0/specialcases/TEST-AG.png
Hey everyone,
is there a public available trust list ?
Same as:
eu-digital-green-certificates/dgc-participating-countries#10
We would only find an outdated list provided by the TU Graz ?
What lists are you using for your implementation ?
regards
Julian
A minor issue. I currently get something like this with JS:
{
"expirationTime": "2022-08-01",
"issuedAt": "2021-08-06",
"issuer": "AT",
"certificateValidFrom": "2021-06-02",
"certificateValidUntil": "2023-06-02",
"certificateValidContent": [
"TEST",
"VACCINATION",
"RECOVERY"
],
"certificateSubjectCountry": "AT",
"content": [
"VACCINATION"
],
"error": null
}
If I'm not mistaken all the dates are missing the time and timezone information.
Make sure that verifying RSA signatures still works with the updated cose-js
lib.
JS certificate loading still has some issues, like throwing all sorts of ugly exceptions and not correctly handling different key sizes.
The trust anchor was recently updated because the old one will soon expire: Federal-Ministry-of-Health-AT/green-pass-overview@cae10ee
I'm now facing the problem that hcert-kotlin doesn't like the new cert and fails with "KEY_NOT_IN_TRUST_LIST" when loading the official trust data from https://dgc-trust.qr.gv.at/ (can be reproduced using demo.html)
Am I missing something?
thanks
I browse a bit trough the implementations, and I couldn't see where the Kid
gets truncated (at 8 bytes).
Is this implementation following this specs ?
Hello,
saw that you @nodh added some code to store the business rules as Json, is there gonna be an interoperability between this library and https://github.com/ehn-dcc-development/dgc-business-rules ? Since hcert-kotlin already contains data and valueSets, it could technically generate data structure that can be used with the business rules.
Please create new release
The 1.0.0 is not usable because of this bug that seems to be already fixed
85fc859
We use the hcert-kotlin as dependency and can not switch to current release
https://github.com/eu-digital-green-certificates/dgca-issuance-service
1.0.0 should be removed anyway
Implement feature to create random RSA keys (and import them from PEM encoded files), just as the EC part, in JS.
Dear authors & contributors,
I experience problems when including hcert-kotlin into a java spring boot project using maven. As discussed in the readme, I added the dependency to the built maven artifact using:
<dependency>
<groupId>com.github.ehn-dcc-development</groupId>
<artifactId>hcert-kotlin</artifactId>
<version>1.3.2</version>
</dependency>
....
<repository>
<id>jitpack.io</id>
<url>https://jitpack.io</url>
</repository>
Unfortunately, when trying to test the decode example, compiling fails with:
(this is also same for other jvm-examples from the readme page)
The method buildVerificationChain(CertificateRepository, Clock) in the type DefaultChain is not applicable for the arguments (CertificateRepository)
Next, I tried to build the hcert-kotlin.jar (v 1.4.0-SNAPSHOT) locally using gradle and import and use it in my local maven repository. Unfortunately, I could only generate the hcert-kotlin-jvm.jar (maybe wrong gradle use, please advise). Using this import the compile error is resolved, but a java runtime error about missing kotlin libraries is thrown.
For further reference during my troubleshooting I found issue https://youtrack.jetbrains.com/issue/KT-35716, which could explain the missing correct static java method.
On some occasions we are still using inline JS code.
It would be really nice to get rid of
This requires some more effort, since there are certain situations where the generated externals effectively force us to do so, since the externals themselves are faulty, for example.
In addition, some JS functions take JS objects for parameters, therefore we need to make absolutely sure that our type-safe code actually compiles to this very specific object structure. This is especially tricky for higher-order functions edge cases like using numbers for keys…
Hey.
I tried to validate some examples from https://github.com/eu-digital-green-certificates/dgc-testdata/tree/main/AT#ra-test.
Problem/Question
The fourth example should be invalid since its supposed to be expired. Is the test data wrong or something in the implementation?
"isValid": true,
"error": null,
"metaInformation": {
"expirationTime": "2021-11-02",
"issuedAt": "2021-05-06",
"issuer": "AT",
"certificateValidFrom": "2021-05-05",
"certificateValidUntil": "2023-05-05",
"certificateValidContent": ["TEST", "VACCINATION", "RECOVERY"],
"certificateSubjectCountry": "AT",
"content": ["TEST"],
"error": null
},
"greenCertificate": {
"ver": "1.0.0",
"nam": {
"fn": "Musterfrau-Gößinger",
"fnt": "MUSTERFRAU<GOESSINGER",
"gn": "Gabriele",
"gnt": "GABRIELE"
},
"dob": "1998-02-26",
"v": null,
"r": null,
"t": [
{
"tg": "840539006",
"tt": "LP217198-3",
"nm": null,
"ma": "1232",
"sc": "2021-02-20T12:34:56Z",
"dr": null,
"tr": "260415000",
"tc": "Testing center Vienna 1",
"co": "AT",
"is": "Ministry of Health, Austria",
"ci": "URN:UVCI:01:AT:71EE2559DE38C6BF7304FB65A1A451EC#3"
}
]
}
}```
It seem like all decoders (trust list, value,sets rules) check the parsed data against the current clock and fail if they are not longer valid. In combination with the official test data which is only valid for two days this makes it hard to integrate this into unit tests.
Is there any way to fake the current time for testing? (or to disable those checks for testing)
Good Morning,
at the moment im trying to add the hcert-kotlin as a dependencie to my app.
I've tried a lot way to add, server versions and it always its the same.
Current way to add it:
implementation 'com.github.ehn-dcc-development.hcert-kotlin:hcert-kotlin:1.3.0'
This comes from jitpack.io
Kotlin Version 1.3.21
Build Variant: Debug
But its failing with the following error message (Trying to build with android studio)
Execution failed for task ':flave:checkDebugDuplicateClasses'.
Could not resolve all files for configuration ':flave:debugRuntimeClasspath'.
Could not resolve com.github.ehn-dcc-development.hcert-kotlin:hcert-kotlin:1.3.0.
Required by:
project :flave
> Cannot choose between the following variants of com.github.ehn-dcc-development.hcert-kotlin:hcert-kotlin:1.3.0:
- jvmDataGenRuntimeElements-published
- jvmRuntimeElements-published
All of them match the consumer attributes:
- Variant 'jvmDataGenRuntimeElements-published' capability com.github.ehn-dcc-development.hcert-kotlin:hcert-kotlin:1.3.0:
- Unmatched attributes:
- Required com.android.build.api.attributes.BuildTypeAttr 'debug' but no value provided.
- Required com.android.build.gradle.internal.dependency.AndroidTypeAttr 'Aar' but no value provided.
- Found ehn.techiop.hcert.faults 'true' but wasn't required.
- Found org.gradle.libraryelements 'jar' but wasn't required.
- Found org.gradle.status 'release' but wasn't required.
- Compatible attributes:
- Required org.gradle.usage 'java-runtime' and found compatible value 'java-runtime'.
- Required org.jetbrains.kotlin.platform.type 'androidJvm' and found compatible value 'jvm'.
- Variant 'jvmRuntimeElements-published' capability com.github.ehn-dcc-development.hcert-kotlin:hcert-kotlin:1.3.0:
- Unmatched attributes:
- Required com.android.build.api.attributes.BuildTypeAttr 'debug' but no value provided.
- Required com.android.build.gradle.internal.dependency.AndroidTypeAttr 'Aar' but no value provided.
- Found ehn.techiop.hcert.faults 'false' but wasn't required.
- Found org.gradle.libraryelements 'jar' but wasn't required.
- Found org.gradle.status 'release' but wasn't required.
- Compatible attributes:
- Required org.gradle.usage 'java-runtime' and found compatible value 'java-runtime'.
- Required org.jetbrains.kotlin.platform.type 'androidJvm' and found compatible value 'jvm'.
Maybe there is something i'm missing. But this wont go away, even if i change the version.
Thanks for the help in advance.
Bit of an ongoing task: Update the submodule for https://github.com/eu-digital-green-certificates/dgc-testdata/ and make sure, that JS and JVM targets verify all the valid codes.
Hello there,
I wanted to ask if you also tested JSON schema validation if the values are null
for example
{ "t": [ { "ci": "urn:uvci:01:lv:e047f5373a6ea7794a7edd34eb204a12", "co": "LV", "dr": "2021-05-31T19:11:40Z", "is": "Nacionālais veselības dienests", "ma": null, "nm": null, "sc": "2021-05-31T15:44:52Z", "tc": "CENTRĀLĀ LABORATORIJA, SIA", "tg": "840539006", "tr": "260415000", "tt": "LP6464-4" } ], "dob": "1966-10-25", "nam": { "fn": "Darbiņš", "gn": "Aldis", "fnt": "DARBINS", "gnt": "ALDIS" }, "ver": "1.0.0" }
is failing
Originally raised by @jsiwrk in #32 (comment)
Although we removed the errorMessage from the VerificationResult, as such information should be logged, not returned.
I would tend to agree with that in the general sense, if we were talking about an application or a service. However, since this is a reusable library that will presumably be used to build the former, wouldn't it be more appropriate to leave that choice to the library user?
For example, let's consider these scenarios:
If these are deemed valid use cases for this library, then it seems that including an errorMessage (or, generally speaking, detailed information about the error) in the VerificationResult would be the right thing to do. And the library client would be responsible for making a proper use of this field. What do you think?
Hello,
we got a issue with new 3/3 certs (not all but mine) doesnt work, it writes CWT_Expired as an error and returns valid false
Its a new GreenPass (9.11).
On request i can provide the qrcode.
Android 10
implementation 'com.github.ehn-dcc-development.hcert-kotlin:hcert-kotlin-jvm:1.3.0'
Best regards,
Dominik
We use the jvm library in a Java11 project and are missing public constructors for ehn.techiop.hcert.kotlin.chain.impl.TrustListCertificateRepository and ehn.techiop.hcert.kotlin.trust.TrustListDecoderService.
Basically we added kotlin-hcert-jvm-1.3.0.jar to pom as well as its dependencies and thats it.
Are we missing out on some required steps?
Usage (JS)
./gradlew jsBrowserDevelopmentWebpack;
just testing demo.html
everything is okay but the Random or Fixed Generator.
It's "stucking" on QR Code Contents: Generating...
Nothing happen (no code and no qr). I've got this error:
Cose.kt?5e47:24 Uncaught TypeError: sign$Companion.createSync is not a function
at Cose.sign_4mr2q2$ (Cose.kt?5e47:24)
at CoseCreationAdapter.sign_x1bysv$ (CoseCreationAdapter.kt?1914:28)
at DefaultCoseService.encode_fqrh44$ (DefaultCoseService.kt?863c:32)
at Chain.encode (Chain.kt?e7ee:40)
at Generator.encode (JsInterface.kt?35f0:148)
at generateRandom (demo.html:38)
at HTMLButtonElement.onclick (demo.html:312)
for... return sign.createSync(header, Buffer(input.toUint8Array()), signer)
file:
.\src\jsMain\kotlin\ehn\techiop\hcert\kotlin\crypto\Cose.kt
package ehn.techiop.hcert.kotlin.crypto
import Buffer
import cose.Signer
import cose.Verifier
import cose.sign
import ehn.techiop.hcert.kotlin.chain.toByteArray
import ehn.techiop.hcert.kotlin.chain.toUint8Array
internal object Cose {
fun verifySync(signedBitString: ByteArray, pubKey: PubKey): ByteArray {
val key = (pubKey as JsPubKey).toCoseRepresentation()
val verifier = object : Verifier {
override val key = key
}
return sign.verifySync(Buffer.from(signedBitString.toUint8Array()), verifier).toByteArray()
}
fun sign(header: dynamic, input: ByteArray, privKey: PrivKey): Buffer {
val key = (privKey as JsPrivKey).toCoseRepresentation()
val signer = object : Signer {
override val key = key
}
return sign.createSync(header, Buffer(input.toUint8Array()), signer)
}
}
Currently, every time the library is updated, it's very difficult and cumbersome to try and figure out exactly which Snapshot version contains which github code (ie: at what point was the snapshot published?)
May I request that the library is tagged with the exact snapshots, and everytime there are official releases, tags are maintained?
This is more of a heads-up, so feel free to close.
The included cbor library requires BigInt support which is only in Safari 14+
It's not really used when verifying a real HCERT, so I've mocked BigInt during the script import for now, which seems to work fine here and make HCERT validation work with Safari 12.1/13, which is our baseline atm. In case anyone is in a similar situation.
hello,
i need to do verification of greenpass in offline environment. devices will be offline for longer period of time (maybe months). my problem is, that i'll get
ehn.techiop.hcert.kotlin.chain.VerificationException: Expiration<clock.now()
when the trustlist wasn't updated for 2 (?) days.
I'm using the trustlist from a-sit.at
Is there a way to make the verification process accept older data?
In the Swiss DCC repo, it was pointed out that decompressing malicious input data can potentially lead to excessive memory usage.
This repo uses a similar approach, so it suffers the same problem:
https://github.com/ehn-digital-green-development/hcert-kotlin/blob/0e212a730be414e9c41f9920dc8d12f0d4f81fd7/src/jvmMain/kotlin/ehn/techiop/hcert/kotlin/chain/impl/CompressorAdapter.kt#L13
As I mentioned in the linked issue, the impact is negligible if only data from barcodes is ever passed to the library function.
However, you never know in what ways others use your library, so it should be mitigated.
You can find our fix here.
Hello, just curious, are you planning to download the trustList to your greenPass application that regular users with certificates will use ? Or the greenPass app is just a "gallery" for qr codes?
Hi,
i can't find hcert-kotlin.js path and a file. There is no path like this: build/distributions/hcert-kotlin.js. My demo.html file also can't load js data, because there is no javascript file.
Could you publish the JS library on npmjs.com or as GH package?
This would help a lot :).
CC: @mofobo-bit
The README example give various JS examples using SignedDataDownloader
, but that class isn't available in the JS bundle. Am I missing something?
thanks
Think about adding a logging library, e.g. https://github.com/MicroUtils/kotlin-logging, to provide additional information about errors in debug builds.
Implement schema validation on the JVM target.
For Android sdk below 26 (Android 8.0), there will be an exception since java.util.Base64 is unknown.
This can be modified in https://github.com/ehn-dcc-development/hcert-kotlin/blob/main/src/jvmMain/kotlin/ehn/techiop/hcert/kotlin/chain/Extensions.kt
Instead of java.util.Base64.getEncoder().encodeToString(this) and java.util.Base64.getDecoder().decode(this)
org.bouncycastle.util.encoders.Base64.toBase64String(this) et org.bouncycastle.util.encoders.Base64..ecode(this) can be used
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.