In this guide, we’ll explore how to implement a Public Key Management System for signing QR codes, focusing on the QCAT Signature Algorithms Version 1 and 2.
Key Management Overview
The QR Code signature system relies on cryptographic keys and certificates to ensure the authenticity of the QR codes generated by issuers. The key players in this system are the Certificate Authority (CA) and the QR Code Ticket Issuers.
1. Certificate Authority (CA):
- The CA signs the issuer’s public keys using its private key, creating a public key certificate. This certificate ensures the QR codes can be verified at validation terminals.
- CA uses a 2048-bit RSA key to sign the issuer’s keys, ensuring a high level of security.
- Each issuer generates their own public/private key pairs. The private key is used to sign QR codes, while the public key is included in the certificate signed by the CA.
- Validation terminals use the issuer’s public key to verify the signature on a QR code.
- The CA’s self-signed certificate is installed in all terminals.
- When a QR code is presented, the terminal retrieves the corresponding issuer certificate and verifies it using the CA’s public key.
- The terminal then uses the issuer’s public key to verify the QR code’s signature.
Creating a Certificate Authority Private Key and Public Key Certificate
To generate the CA's key pair and public certificate, we use OpenSSL. Here’s how:
1. Create the OpenSSL configuration file, openssl.cnf:
[ req ]
default_bits = 2048
default_md = sha256
2. Create the CA’s private key and self-signed certificate:
$
openssl req -new -x509 -keyout afpi-ca-key.txt -out afpi-ca-certificate.pem.txt -days 3650 -config openssl.cnf
This command generates a 2048-bit RSA private key and a self-signed public certificate valid for 10 years.
3. The distinguished name (DN) for the CA certificate includes details like the country, organization, and a common name for identification. Here’s an example:
Country Name (2 letter code) []:PH
State or Province Name (full name) []:NCR
Locality Name (eg, city) []:MAKATI
Organization Name (eg, company) []:AF PAYMENTS INC
Organizational Unit Name (eg, section) []:AFPI-0000
Common Name (eg, fully qualified host name) []:QCAT-001
Email Address []:john.doe@afpayments.com
Issuer Key Generation and Certification
Ticket issuers also generate their own private/public key pairs. The public key is signed by the CA to create a certificate that is installed in validation terminals.
1. Generate the issuer’s private key and keystore using Java's keytool:
$
keytool -genkey -alias bank-qr-issuer-key -keyalg RSA -keysize 1024 -validity 1825 -storetype PKCS12 -keystore bank-qr-issuer-keystore.p12
This generates a 1024-bit RSA key pair, stored in a PKCS12 keystore file.
2. The distinguished name (DN) for the key includes details like the country, organization, and a common name for identification. Here’s an example:
Country Name (2 letter code) []:PH
State or Province Name (full name) []:NCR
Locality Name (eg, city) []:MAKATI
Organization Name (eg, company) []:BANK NAME
Organizational Unit Name (eg, section) []:BANK-00123
Common Name (eg, fully qualified host name) []:BANK BACKEND
3. Request signing of issuer's public key to the CA:
$
keytool -certreq -keystore bank-qr-issuer-keystore.p12 -alias bank-qr-issuer-key -keyalg rsa -file bank-qr-issuer.csr
4. The issuer’s certificate is then signed by the CA, allowing validation terminals to trust QR codes signed by the issuer’s private key.
$
openssl x509 -req -CA afpi-ca-certificate.pem.txt -CAkey afpi-ca-key.txt -in bank-qr-issuer.csr -out bank-bank-qr-issuer.cer -days 1825 -CAcreateserial
5. Lastly, the root public key certificate of the CA is then loaded into the issuer's keystore.
$
keytool -import -keystore bank-qr-issuer-keystore.p12 -file afpi-ca-certificate.pem.txt -alias afpi-ca-root
Now, when you try to load the public key certificate of the issuer, the keytool should no longer ask whether the certificate is trusted. This is due to the loading of the root public key certificate of the CA earlier.
$
keytool -import -keystore bank-qr-issuer-keystore.p12 -file afpi-bank-qr-issuer.cer -alias bank-issuer
Summary of the Key and Certificate Created
- bank-qr-issuer-keystore.p12 - the file contains the Issuer’s keystore, which includes the following keys and certificates: the bank-qr-issuer-key, a private key used for generating QR code signatures; the afpi-ca-root, the self-signed root certificate of the CA; and the bank-issuer, a CA-signed issuer certificate used to validate QR code signatures.
- afpi-ca-certificate.pem.txt - the CA’s self-signed public key certificate is used to create new keystores for validation terminals.
- afpi-ca-key.txt - the password-protected private key of the CA is used to generate new public key certificates for additional QCAT Ticket Issuer certificates.
- afpi-bank-qr-issuer.cer - the QCAT Ticket Issuer’s CA-signed public key certificate can be imported into keystores to validate QR code signatures generated by the issuer.
- bank-qr-issuer.csr - can be deleted
Secure QR Code Signing
Once the issuer's keys are generated and certificates distributed to terminals, the issuer can use their private key to sign QR code data. The signature is then attached to the QR code, ensuring that only valid, authorized issuers can create authentic QR codes.
Summary of Steps:
1. Generate CA private/public key pair.
2. Issue and install self-signed CA certificate on validation terminals.
3. Generate issuer’s private/public key pairs.
4. Sign the issuer’s public key with the CA’s private key.
5. Distribute issuer certificates to terminals.
6. Sign QR codes with the issuer’s private key for validation.
Signing QR Codes with the Issuer’s Private Key
To ensure the authenticity and integrity of the QR codes issued, the following steps outline how to sign QR codes using the issuer's private key:
Step 1: Prepare the QR Code Data
1. Define the Data to be Signed: Determine what data will be encoded in the QR code, such as transaction details, issuer information, and any other relevant data.
2. Convert Data to Byte Array: Convert the data into a format suitable for signing (e.g., UTF-8 encoded byte array).
val qrData = "Transaction details here"
val dataToSign = qrData.toByteArray(Charsets.UTF_8)
Step 2: Load the Issuer’s Private Key
1. Load the Keystore: Load the keystore that contains the issuer's private key.
val keystore = KeyStore.getInstance("PKCS12") FileInputStream("bank-qr-issuer-keystore.p12").use { fis -> keystore.load(fis, "keystore-password".toCharArray()) }
2. Retrieve the Private Key: Get the private key from the keystore using its alias.
val privateKey = keystore.getKey("bank-qr-issuer-key", "key-password".toCharArray()) as PrivateKey
Step 3: Sign the Data
1. Initialize the Signature: Create a Signature object and initialize it with the issuer's private key.
val signature = Signature.getInstance("SHA256withRSA")
signature.initSign(privateKey)
2. Update and Sign the Data: Update the signature with the data and sign it.
signature.update(dataToSign)
val signedData: ByteArray = signature.sign()
Conclusion
The Public Key Management System is essential for ensuring the authenticity and integrity of QR codes used in various applications. By following the steps outlined above, issuers can securely sign QR codes, enabling validation and enhancing trust in transactions.
If you’d like to learn more or get involved in the QCAT ecosystem, feel free to check out my guides on QCAT specification below or check out AF Payments Inc.'s GitHub for the latest updates and contribution guidelines.
Don't forget to subscribe to my blog so you never miss out on my latest guides and content!
DISCLAIMER
The information provided in this article is for informational purposes only and does not constitute professional advice. While efforts have been made to ensure accuracy, AF Payments Inc. reserves the right to update or modify the QCAT standard and related materials at any time. Use of the QCAT standard is subject to the terms of its license agreement, and any implementation must adhere to AFPI's guidelines and licensing requirements. For the latest details and official documentation, please refer to AF Payments Inc.'s authorized channels.
Comments
Post a Comment