A library to decode/verify and encode/sign Visible Digital Seals (VDS) as specified 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 draft of ICAO Datastructure for Barcode. The IDB encoder/decoders are at early stadium of and still differs from the VDS parser/encoder but they are already useable. You will find them in the package de.tsenger.vdstools.idb.
VDS can be created with the help of this library or, if you want to try it out quickly, via the web Sealgen tool. There is also the Sealva Android app which scans, verifies and displays all VDS profiles defined in the above specifications.
Here is a quick overview how to use the VDS parser and verifier. When you have the decoded raw string or raw bytes from your favorite datamatrix decoder, just put them to the VDS Tools Dataparser like this:
import de.tsenger.vdstools.Verifier;
import de.tsenger.vdstools.vds.DigitalSeal;
import de.tsenger.vdstools.vds.Feature;
...
DigitalSeal digitalSeal = DigitalSeal.fromByteArray(rawBytes);
String vdsType = digitalSeal.getVdsType();
// getFeature() returns an Optional<Feature> which can be used as follows
String mrz = digitalSeal.getFeature("MRZ").get().valueStr();
String azr = digitalSeal.getFeature("AZR").get().valueStr();
if(digitalSeal.getFeature("FACE_IMAGE").isPresent() ){
byte[] imgBytes = digitalSeal.getFeature("FACE_IMAGE").get().valueBytes();
}
// or get all available Features in one List<Feature>
List<Feature> featureList = digitalSeal.getFeatureList();
for (Feature feature: featureList) {
System.out.println(feature.name() + ", " + feature.coding() + ", " + feature.valueStr());
}
// Get the VDS signer certificate reference
String signerCertRef = digitalSeal.getSignerCertRef();
// Provide for the matching X509 signer certificate
// and use this to verify the VDS signature
Verifier verifier = new Verifier(digitalSeal, x509SignerCert);
Verifier.Result result = verifier.verify();
Also have a look at DigitalSealTest.java and VerifierTest.java for some more examples.
Since version 0.3.0 you can also generate VDS with this library. Here is an example on how to use the DateEncoder and Signer classes:
KeyStore keystore = ...
...
// Here we use a keystore to get the certificate (for the header information)
// and the private key for signing the seals data
X509Certificate cert = (X509Certificate) keystore.getCertificate(keyAlias);
ECPrivateKey ecKey = (ECPrivateKey) keystore.getKey(certAlias, keyStorePassword.toCharArray());
// initialize the Signer
Signer signer = new Signer(ecKey);
// 1. Build a VdsHeader
VdsHeader header = new 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 VdsMessage
String mrz = "MED<<MANNSENS<<MANNY<<<<<<<<<<<<<<<<\n6525845096USA7008038M2201018<<<<<<06";
String azr = "ABC123456DEF";
VdsMessage vdsMessage = new VdsMessage.Builder(header.getVdsType())
.addDocumentFeature("MRZ", mrz)
.addDocumentFeature("AZR", azr)
.build();
// 3. Build a signed DigitalSeal
DigitalSeal digitalSeal = new DigitalSeal(header, vdsMessage, signer);
// The encoded bytes can now be used to build a datamatrix (or other) code - which is not part of this library
byte[] encodedBytes = digitalSeal.getEncodedBytes();
There are many other ways to define the content of the VDS. In the example above, a lot of data such as the signature or issuing date is generated automatically. However, it is also possible to set your own values. There are various ways to encode a DigitalSeal by for this purpose. The VdsHeader and VdsMessage classes offer the option of setting the content in a finely granular manner.
Alternatively, it is also possible to generate many values automatically with as little input as possible or to use default values.
Also have a look at DataEncoderTest.java for some examples how to use the different options. In DataMatrixTest.java you will find an example on how to generated a datamatrix image file from the encoded bytes of the DataEncoder.
Online JavaDoc can be found here: https://javadoc.io/doc/de.tsenger/vdstools
The vdstools library is available on the Maven Central Repository and can be easly integrated in your projects.
To include this library to your Gradle build add this dependency:
dependencies {
implementation 'de.tsenger:vdstools:0.7.0'
}
To include this library to your Maven build add this dependency:
<dependency>
<groupId>de.tsenger</groupId>
<artifactId>vdstools</artifactId>
<version>0.7.0</version>
</dependency>