Open sourced May 2023
Pkcs11 para registro público de Panamá cortesía de Industrias de Firmas Electronicas sa copyright 2020 a 2021. Enter the wu tang!
com.xdv.client.wallet
is a websocket based Spring boot application. It has a signing API and verification API.
To run the websocket, start the spring boot application and in PKCS11Service
call the initialize
method which will detect OS and load SafeSign drivers for Linux, Mac or Windows.
Gets a list of hardware modules with PKCS#11 support
Signs a binary data
Arguments
- tokenIndex: A number with 0 index representing the slot
- pin: Pin for the hardware module
- data: Binary to sign
Returns a SignResponse object
- publicKey: The corresponding public key for the key pair
- signature: The signed binary data
- digest: Hash for the binary data
- type: Signature type
- error: Error message
Sample code
X509PublicKeyCertificate certificate = new X509PublicKeyCertificate();
// If slot found then enable mechanism
if (foundSignatureKeyObjects.length > 0) {
Mechanism signatureMechanism = getSupportedMechanism(token, mechCode);
// 1. Create digest (hash) with SHA 256
MessageDigest md = MessageDigest.getInstance("SHA-256");
byte[] hashValue = md.digest(data);
Key key = (Key) foundSignatureKeyObjects[0];
byte[] pub = ((X509PublicKeyCertificate)certs[0]).getValue().getByteArrayValue();
// 2. Initialize keys and sign digest with session
session.signInit(signatureMechanism, key);
byte[] signature = session.sign(hashValue);
byte[] cer1 = ((X509PublicKeyCertificate)certs[0]).getValue().getByteArrayValue();
byte[] cer2 = ((X509PublicKeyCertificate)certs[1]).getValue().getByteArrayValue();
CertificateFactory certFactory = CertificateFactory.getInstance("X.509");
InputStream inCert1 = new ByteArrayInputStream(cer1);
X509Certificate certificate1 = (X509Certificate)certFactory.generateCertificate(inCert1);
InputStream inCert2 = new ByteArrayInputStream(cer2);
X509Certificate certificate2 = (X509Certificate)certFactory.generateCertificate(inCert2);
String pem = DSSUtils.convertToPEM(new CertificateToken(certificate1));
// 3. Registro Publico has 2 keys, we just return one
// 4. You need to return public key, signature and digest, you'll need these three to be able to verify
SignResponse response = new SignResponse();
response.setPublicKey(pem);
response.setSignature(Base64.getEncoder().encodeToString(signature));
response.setDigest(Base64.getEncoder().encodeToString(hashValue));
return response;
Verification with spring boot uses European Union ESIG DSS java toolkit and is found in VerificationController
.
XDV uses a detached verification
approach, you need to call verifySignature
methods
public String verifySignature(String name, String contentType, byte[] data, byte[] cert) throws CMSException {
return verifySignature(name, contentType, data, cert, null, false );
}
public String verifySignature(String name, String contentType, byte[] data, byte[] cert, byte[] contents, boolean detached) throws CMSException {
...
}
Verifies a PKCS#11 in detached signature mode. It uses the 3 root certificates to match certificate chain of trust.
Note: XDV uses detached signature because it allows for scalability in server side scenarios, where you need to validate documents in batch mode, useful for government entities. Right now, the most common use case used in the Republic of Panama is visual, attached signatures inside PDF documents. Automated tools required to parse the complete PDF file to access the signature, with detached signatures no parsing is required.
Arguments
- name: Filename
- contentType: File content type aka mime type
- data: Signature (aka detached signatured)
- cert: Certificate
- contents: File Content
- detached: True if detached, else false
Returns a string with verification summary
Sample code
String res;
if (payload.getContents() == null) {
res = this.verifySignature(
payload.getFilename(),
null,
payload.getSignature().getBytes(),
Base64.decode(payload.getCertificate())
);
} else {
res = this.verifySignature(
payload.getFilename(),
null,
payload.getSignature().getBytes(),
Base64.decode(payload.getCertificate()),
Base64.decode(payload.getContents()),
true
);
}
- Run
gradle assemble
- Run
native-image -jar wallet-1.0.0.jar
- Package image and done