- Notifications
You must be signed in to change notification settings - Fork2
A library to parse and generate Visible Digital Seals (VDS)
License
tsenger/vdstools
Folders and files
Name | Name | Last commit message | Last commit date | |
---|---|---|---|---|
Repository files navigation
This a Kotlin multiplatform (JVM and iOS) library to decode/verify and encode/sign Visible Digital Seals (VDS) asspecified in
- BSI TR-03137 Part 1
- ICAO Doc 9303 Part 13: Visible Digital Seals
- ICAO TR "VDS for Non-Electronic Documents"
It also supports encoding and decoding Seals defined in the new draftofICAO Datastructure for Barcode.Since release 0.9.0 ICAO IDB barcode encoder/decoders are fully functional.VDS and ICD barcodes can be parsed by a generic interface. An example is given in the following chapter
VDS can be created with the help of this library or, if you want to try it out quickly, via thewebSealgen tool.There is also theSealva Android app which scans,verifies and displays all VDS profiles defined in the above specifications.
Here is a quick overview how to use the generic parser and verifier. In release 0.9.0 a generic interface was introducedto handle VDS and IDB barcode via common function calls.When you have the decoded raw string from your favorite datamatrix decoder, just put used the VDS Tools like this:
importde.tsenger.vdstools.Verifierimportde.tsenger.vdstools.vds.DigitalSealimportde.tsenger.vdstools.vds.Feature//Example for VDS / IDB barcode typeval seal:Seal=Seal.fromString(rawString)val mrz:String?= seal.getMessage("MRZ")?.valueStr// get all available Messages / Features in a Listval messageList:List<Message>= seal.messageListfor (messagein messageList) {println("${message.name},${message.coding},${message.valueStr}")}// SignatureInfo contains all signature relevant dataval signatureInfo:SignatureInfo= seal.signatureInfo// Get the VDS signer certificate referenceval signerCertRef:String= signatureInfo.signerCertificateReference// Since X509 certificate handling is strongly platform-dependent,// the Verfifier is given the plain publicKey (r|s) and the curve name.val publicKeyBytes:ByteArray= byteArrayOf()val verifier:Verifier=Verifier(seal.signedBytes, signatureInfo.plainSignatureBytes, publicKeyBytes,"brainpoolP224r1")val result:Verifier.Result= verifier.verify()
Here is an example on how to use the DateEncoder and Signer classes to build a VDS barcode:
val keystore:KeyStore=...// In this JVM example we use a BouncyCastle keystore to get the certificate (for the header information)// and the private key for signing the seals dataval cert:X509Certificate= keystore.getCertificate(keyAlias)val ecKey:ECPrivateKey= keystore.getKey(certAlias, keyStorePassword.toCharArray())// initialize the Signerval signer:Signer=Signer(ecKey.encoded, curveName)// 1. Build a VdsHeaderval header=VdsHeader.Builder("ARRIVAL_ATTESTATION") .setIssuingCountry("D<<") .setSignerIdentifier("DETS") .setCertificateReference("32") .setIssuingDate(LocalDate.parse("2024-09-27")) .setSigDate(LocalDate.parse("2024-09-27")) .build()// 2. Build a VdsMessageval mrz="MED<<MANNSENS<<MANNY<<<<<<<<<<<<<<<<6525845096USA7008038M2201018<<<<<<06"val azr="ABC123456DEF"val vdsMessage=VdsMessage.Builder(header.vdsType) .addDocumentFeature("MRZ", mrz) .addDocumentFeature("AZR", azr) .build()// 3. Build a signed DigitalSealval digitalSeal=DigitalSeal(header, vdsMessage, signer)// The encoded bytes can now be used to build a datamatrix (or other) code - which is not part of this libraryval encodedSealBytes= digitalSeal.encoded
Here is an example on how to use the DateEncoder and Signer classes to build a IDB barcode:
val keystore:KeyStore=...// In this JVM example we use a BouncyCastle keystore to get the certificate (for the header information)// and the private key for signing the seals dataval cert:X509Certificate= keystore.getCertificate(keyAlias)val ecKey:ECPrivateKey= keystore.getKey(certAlias, keyStorePassword.toCharArray())// initialize the Signerval signer:Signer=Signer(ecKey.encoded, curveName)// 1. Build a IdbHeaderval header=IdbHeader("D<<",IdbSignatureAlgorithm.SHA256_WITH_ECDSA,DataEncoder.buildCertificateReference(cert.encoded),"2025-02-11")// 2. Build a MessageGroupval messageGroup=IdbMessageGroup.Builder() .addMessage(0x02, vdsMessage.encoded) .addMessage(0x80, readBinaryFromResource("face_image_gen.jp2")) .addMessage(0x84,"2026-04-23") .addMessage(0x86,0x02) .build()// 3. Build a signed Icao Barcodeval signature= buildSignature(header.encoded+ messageGroup.encoded)val payload=IdbPayload(header, messageGroup,null, signature)val icb=IcaoBarcode(isSigned=true, isZipped=false, barcodePayload= payload)// The encoded raw string can now be used to build a datamatrix (or other) code - which is not part of this libraryval encodedRawString= icb.rawString
Also have a look at the testcases for more usage inspiration.You will also find an example on how to generate a datamatrix image with the Zxing library in the jvmTests.
Online JavaDoc can be found here:https://javadoc.io/doc/de.tsenger/vdstools
The vdstools library is available ontheMaven Central RepositoryandGitHub Packages to beeasy to integrate in your projects.
To include this library to your Gradle build add this dependency:
dependencies { implementation'de.tsenger:vdstools:0.9.0-SNAPSHOT'}
To include this library to your Maven build add this dependency:
<dependency> <groupId>de.tsenger</groupId> <artifactId>vdstools</artifactId> <version>0.9.0-SNAPSHOT</version></dependency>
About
A library to parse and generate Visible Digital Seals (VDS)