AWS Security Blog

Build a mobile driver’s license solution based on ISO/IEC 18013-5 using AWS Private CA and AWS KMS

A mobile driver’s license (mDL) is a digital representation of a physical driver’s license that’s stored on a mobile device. An mDL is a significant improvement over physical credentials, which can be lost, stolen, counterfeited, damaged, or contain outdated information, and can expose unconsented personally identifiable information (PII). Organizations are working together to use mDLs across various situations, ranging from validating identity during airplane boarding to sharing information for age-restricted activities.

The trust in the mDL system is based on public-private key cryptography where mDLs are signed by issuing authorities using their private key and verified using the issuing authority’s public key. In this blog post, we show you how to build an mDL issuing authority in Amazon Web Services (AWS) using AWS Private Certificate Authority and AWS Key Management Service (AWS KMS) according to mDL specification ISO/IEC 18013-5:2021. These AWS services align with the cryptographic requirements placed on the issuing authorities by ISO/IEC 18013-5. While we have tailored this post to an mDL use case, the sign and verify mechanism using AWS Private CA and AWS KMS can be used for multiple kinds of digital identity verification.

Solution overview

AWS Private CA provides you with a highly available private certificate authority (CA) service without the initial investment and ongoing maintenance costs of operating your own private CA. CA administrators can use AWS Private CA to create a complete CA hierarchy, including online root and subordinate CAs, without needing external CAs. You can issue, rotate, and revoke certificates that are trusted within your organization using AWS Private CA.

AWS Private CA can issue certificates formatted as required by ISO/IEC 18013-5. You can build a certificate authority (CA) in AWS Private CA—referred to as the issuing authority certificate authority (IACA) in ISO/IEC 18013-5. We create an IACA self-signed root certificate and an mDL document signing certificate in AWS Private CA.

AWS KMS is a managed service that you can use to create and control the cryptographic keys that are used to protect your data. AWS KMS uses FIPS 140-2 Level 3 validated hardware security modules (HSMs) to protect AWS KMS keys, which is a requirement for building an issuing authority as described in ISO/IEC 18013-5. We create an asymmetric key pair in AWS KMS for signing and verification of the mDL document. We programmatically create a certificate signing request (CSR) that’s signed by the asymmetric key pair stored in AWS KMS. The CSR is sent to the AWS Private CA service for issuing the mDL document signing certificate that matches the certificate profile requirement specified for the document signing certificate in ISO/IEC 18013-5.

We sign an mDL document using the private key of the asymmetric key pair created in AWS KMS with a KeyUsage value of SIGN_VERIFY. The signed mDL document is delivered to a mobile device where it’s stored in a digital wallet and produced for verification by mDL readers. The mDL readers are configured with IACA certificates from various issuing authorities that allow them to verify the mDL documents signed by respective issuing authorities. An example of an issuing authority could be a state government agency that issues driver’s licenses.

Least privilege

The solution in this post uses AWS KMS and AWS Private CA services. Before you implement the process described in this post, ensure that the AWS Identity and Access Management (IAM) principal you choose follows the principle of least privilege and that permissions are scoped to the minimum required permissions required. See Security best practices in IAM to learn more.

Solution architecture

A sample solution architecture for building an mDL issuing authority in AWS is shown in Figure 1. The figure shows the step-by-step process starting from setting up a private CA and issuing an mDL document signing certificate to mDL issuance and verification. The infrastructure that’s built using this architecture includes a root certificate authority, which issues a document signer certificate. You can find the certificate requirements in section B.1 Certificate Profile of ISO/IEC 18013-5.

Figure 1: mDL issuing authority architecture and process flow in AWS

Figure 1: mDL issuing authority architecture and process flow in AWS

In this post, we use AWS Command Line Interface (AWS CLI) commands, but these can be replaced by AWS SDK API calls if needed. Along with the AWS CLI steps, a GitHub sample is provided that’s used to programmatically create and sign an mDL document signing CSR using AWS KMS.

See the AWS CLI commands documentation for AWS Private CA and AWS KMS for detailed information on the commands used in this solution.

Solution walkthrough

Use the following steps to create the infrastructure needed for mDL signing and verification.

Step 1: Create IACA CA in AWS Private CA

In this step, the root of trust IACA (issuing authority CA) will be created. The IACA root CA is the root of trust that will be used for verification of the mDL.

  1. Create a local ca_config.txt file with the following content. The contents of this file are derived from the Certificate profiles section (Annex B) within ISO/IEC 18013-5. You can change the Country and CommonName values in the file as needed for your requirements.
    {
      "KeyAlgorithm": "EC_prime256v1",
      "SigningAlgorithm": "SHA256WITHECDSA",
      "Subject": {
        "Country": "US",
        "CommonName": "mDL IACA Root"
      }
    }
  2. The IACA root certificate will be paired with a certificate revocation list (CRL). See Planning a certificate revocation list (CRL) for information about configuring CRLs. Create a local file called revocation_config.txt with the following information to configure a CRL. The values for CustomCname and S3BucketName are examples, update them with the values that you have created within your AWS account. Update ExpirationInDays to fit your requirements. We recommend configuring encryption on the Amazon Simple Storage Service (Amazon S3) bucket containing your CRLs.
    {
      "CrlConfiguration": {
        "CustomCname": "example.com",
        "Enabled": true,
        "S3BucketName": "crlmdlbucket",
        "ExpirationInDays": 5000,  
      }
    }
  3. Invoke an AWS CLI command to create a private certificate authority. Replace the region parameter as needed. Update the file:// paths in the following command to the locations where you’ve stored the ca_config.txt and revocation_config.txt files.
    aws acm-pca create-certificate-authority \ 
        --region us-west-1 \
        --certificate-authority-configuration file://ca_config.txt \
        --revocation-configuration file://revocation_config.txt \
        —-certificate-authority-type "ROOT"
  4. The command should produce the following output. The output contains the Amazon Resource Name (ARN) of the created CA. You will need this ARN in subsequent steps.
    {
        "CertificateAuthorityArn": "arn:aws:acm-pca:us-west-1:123412345678:certificate-authority/0116z123-dv7a-59b1-x7be-1231v7257113"
    }

Step 2: Retrieve the CSR for IACA root certificate

You’ll create an IACA root certificate, which starts with retrieving a CSR. This step retrieves the CSR for the IACA root certificate. The certificate-authority-arn parameter carries the CA ARN that was generated in Step 1.

  1. The following command will output a Privacy-Enhanced Mail (PEM) formatted CSR.
    aws acm-pca get-certificate-authority-csr \
        --region us-west-1 \
        --output text \
        --certificate-authority-arn arn:aws:acm-pca:us-west-1:123412345678:certificate-authority/0116z123-dv7a-59b1-x7be-1231v7257113
  2. The following is the format of the output CSR:
    -----BEGIN CERTIFICATE REQUEST-----
    ..
    -----END CERTIFICATE REQUEST-----
  3. Store the output text in a file called IACA.csr.

Step 3: Generate root certificate

  1. This step issues the IACA root certificate. Create a file named extensions.txt using the following contents, which are derived from the Certificate profiles section of ISO/IEC 18013-5.

    The KeyUsage extension with KeyCertSign and CRLSign should be set to true. A custom extension for the CRL distribution point is set and the validity of the certificate should be set to 9 years or 3285 days (set in the next step). Because the IACA root certificate is only used to issued mDLs, a maximum validity period of 9 years is sufficient, as indicated in Table B.1 of ISO/IEC 18013-5. Additionally, a CRL distribution point extension must be present. In the following example, the CRL URL encoded in the CDP extension is http://example.com/crl/0116z123-dv7a-59b1-x7be-1231v72571136.crl, aligning with both the CA CRL configuration applied to the CA at creation and to the CA ID. For base-64 encoding of the CDP extension, you can refer to this java sample.

    {
      "Extensions": {
        "KeyUsage": {
          "KeyCertSign": true,
          "CRLSign": true
        },
        "CustomExtensions": [
          {
            "ObjectIdentifier": "2.5.29.31",
            "Value": "MEgwRqBEoEKGQGh0dHA6Ly9leGFtcGxlLmNvbS9jcmwvMDExNnoxMjMtZHY3YS01OWIxLXg3YmUtMTIzMXY3MjU3MTEzNi5jcmw="
           }
        ]
      }
    }
  2. Issue the following command to AWS Private CA to create the certificate.
    aws acm-pca issue-certificate \
        --region us-west-1 \
        --certificate-authority-arn arn:aws:acm-pca:us-west-1:123412345678:certificate-authority/0116z123-dv7a-59b1-x7be-1231v7257113 \
        --template-arn "arn:aws:acm-pca:::template/BlankRootCACertificate_PathLen0_APIPassthrough/V1" \
        --signing-algorithm "SHA256WITHECDSA" \
        --csr fileb://IACA.csr \
        --validity Value=3285,Type="DAYS" \
        --api-passthrough file://extensions.txt
  3. The preceding command will produce the following output:
    {
      "CertificateArn": "arn:aws:acm-pca:us-west-1:123412345678:certificate-authority/0116z123-dv7a-59b1-x7be-1231v7257113/certificate/34a1dab03117f0e89c54b1234fe13318"
    }

Note that the IACA root CA created with AWS Private CA currently doesn’t have a CRL distribution point (CDP) extension by default. However, that is a mandatory extension according to the IACA root certificate profile in ISO/IEC 18013-5. To implement this, we use a custom extension passed in using API passthrough, which embeds the CDP extension. The distribution point specified in that extension must be based on the CA ID, which is 0116z123-dv7a-59b1-x7be-1231v7257113 derived from the CA ARN that was created in Step 1.

Step 4: Retrieve root certificate

This step retrieves the IACA root certificate in PEM format.

  1. Use the following code to retrieve the IACA root certificate:
    aws acm-pca get-certificate \
        --region us-west-1 \
        --certificate-authority-arn arn:aws:acm-pca:us-west-1:123412345678:certificate-authority/0116z123-dv7a-59b1-x7be-1231v7257113 \
        --certificate-arn arn:aws:acm-pca:us-west-1:123412345678:certificate-authority/0116z123-dv7a-59b1-x7be-1231v7257113/certificate/34a1dab03117f0e89c54b1234fe13318 \
        --output text
  2. The command output will be a PEM formatted certificate similar to the following:
    -----BEGIN CERTIFICATE-----
    ..
    -----END CERTIFICATE-----
  3. Store the output text in a file named IACA-Root-CA-Cert.pem.

Step 5: Import root certificate

Use the following code to import the root certificate into AWS Private CA and make the certificate authority active and ready to issue certificates.

aws acm-pca import-certificate-authority-certificate \
    --region us-west-1 \
    --certificate-authority-arn arn:aws:acm-pca:us-west-1:123412345678:certificate-authority/0116z123-dv7a-59b1-x7be-1231v7257113 \
    --certificate fileb://IACA-Root-CA-Cert.pem

You should see success after running the command.

Step 6: Create an asymmetric key in AWS KMS

In this step, create an asymmetric signing key in AWS KMS which will be used to sign the mDL document signing CSR.

  1. Use the following command to create an asymmetric key:
    aws kms create-key \
        --region us-west-1 \
        --key-spec ECC_NIST_P256 \
        --key-usage SIGN_VERIFY
  2. The command should produce the following output:
    {
      "KeyMetadata": {
        "AWSAccountId": "123412345678",
        "KeyId": "3ab87971-1fe2-45d9-955a-5dc7f65558zf",
        "Arn": "arn:aws:kms:us-west-1:123412345678:key/3ab87971-1fe2-45d8-955c-5dc7f65558ef",
        "CreationDate": "2024-05-18T19:53:27.318000+00:00",
        "Enabled": true,
        "Description": "",
        "KeyUsage": "SIGN_VERIFY",
        "KeyState": "Enabled",
        "Origin": "AWS_KMS",
        "KeyManager": "CUSTOMER",
        "CustomerMasterKeySpec": "ECC_NIST_P256",
        "KeySpec": "ECC_NIST_P256",
        "SigningAlgorithms": [
          "ECDSA_SHA_256"
        ],
        "MultiRegion": false
      }
    }
  3. Note the Arn value from the output. You will use it in Step 7 to configure the CSR creation utility for the mDL document signing certificate.

Step 7: Use the CSR creation utility to generate the document signing CSR

We published a sample utility in GitHub that creates a CSR signed by an AWS asymmetric key.

  1. Clone the GitHub repository and then follow the instructions in the README file from the repository to configure and run it.
  2. This program will output a PEM formatted CSR similar to the following:
    -----BEGIN CERTIFICATE REQUEST-----
    ..
    -----END CERTIFICATE REQUEST-----
  3. Copy the output and store it in a file named document-signing-kms.csr. You will use the file in Step 8 to create the mDL document signing certificate based on this CSR.

Step 8: Generate an mDL document signing certificate

This step creates the document signing certificate from the CSR that’s signed using the AWS KMS asymmetric key.

  1. Create a file named extensionSigner.txt with the following contents. The contents of this file are derived from the Certificate profiles section of ISO/IEC 18013-5. The JSON snippet that follows shows the extension structure containing the KeyUsage extension with DigitalSignature field set to true.
    {
         "Extensions": {
             "KeyUsage": {
                 "DigitalSignature": true
             },
             "ExtendedKeyUsage": [
                 {
                     "ExtendedKeyUsageObjectIdentifier": "1.0.18013.5.1.2"
                 }
             ]
         }
    }
  2. Use the following AWS CLI command to create the certificate.
    aws acm-pca issue-certificate \
        --region us-west-1 \
        --certificate-authority-arn arn:aws:acm-pca:us-west-1:123412345678:certificate-authority/0116z123-dv7a-59b1-x7be-1231v7257113 \
        --template-arn "arn:aws:acm-pca:::template/BlankEndEntityCertificate_APIPassthrough/V1" \
        --signing-algorithm "SHA256WITHECDSA" \
        --csr fileb://document-signing-kms.csr \
        --validity Value=1825,Type="DAYS" \
        --api-passthrough file://extensionSigner.txt
  3. Output:
    {
        "CertificateArn": "arn:aws:acm-pca:us-west-1:123412345678:certificate-authority/0116z123-dv7a-59b1-x7be-1231v7257113/certificate/d462fcd3b9h3beb45c7c312241d42fba"
    }
  4. You will use the CertificateArn from the output in Step 9 to retrieve the mDL document signing certificate.

Step 9: Retrieve the mDL document signing certificate

This step retrieves the document signing certificate in PEM format from AWS Private CA.

  1. Use the following command to retrieve the document signing certificate:
    aws acm-pca get-certificate \
        --region us-west-1 \
        --certificate-authority-arn arn:aws:acm-pca:us-west-1:123412345678:certificate-authority/0116z123-dv7a-59b1-x7be-1231v7257113 \
        --certificate-arn arn:aws:acm-pca:us-west-1:123412345678:certificate-authority/0116z123-dv7a-59b1-x7be-1231v7257113/certificate/d462fcd3b9h3beb45c7c312241d42fba \
        --output text
  2. Store the output text in document_signing_cert.pem.

You now have the mDL document signing certificate for packaging later with the Concise Binary Object Representation (CBOR) structure required by ISO/IEC 18013-5.

Step 10: mDL reader ingests issuing authority’s mDL signing certificate chain

An mDL reader can trust the mDL presented by a user after cryptographically verifying the mDL. This verification requires the reader to possess the mDL signing certificate chain of the issuing authority that issued the user the mDL. As required by the decentralized public key infrastructure (PKI) trust model specified in ISO/IEC 18013-5, the mDL reader will ingest the mDL signing certificate chain of the issuing authority.

Step 11: User makes an mDL signing request to the issuing authority

The user makes a request to the issuing authority to sign the mDL.

Step 12: Issuing authority issues signed mDL to the user

The issuing authority will authenticate the user’s identity and issue a signed mDL. The issuing authority provisions mDL data to the user’s device along with a CBOR encoded object known as a mobile security object (MSO). MSOs contain a digest algorithm, individual digests of mDL data elements, and a validity period. After this MSO has been generated and encoded as required by ISO/IEC 18013-5:2021 section 9.1.2.4, the MSO can be signed by the issuing authority. This signature can be generated in AWS KMS as shown in the following command. Generating the encoded MSO is out of scope for this post.

  1. Use the following command to produce the SHA-256 digest of encoded MSO object using the sha256sum utility.
    sha256sum < EncodedMSO > EncodedMSODigest
  2. Sign the digest using the AWS KMS asymmetric key created in Step 6.
    aws kms sign \
     --region us-west-1 \
     --key-id 3ab87971-1fe2-45d8-955c-5dc7f65558ef \
     --message fileb://EncodedMSODigest \
     --message-type DIGEST \
     --signing-algorithm ECDSA_SHA_256 \
     --output text \
     --query Signature | base64 --decode
  3. This signature will be combined with the issuing authority certificate and the MSO to form a CBOR Object Signing and Encryption (COSE) signed message and will be presented with the mDL data elements to readers. Readers can validate this signature to confirm the integrity of the MSO.

Step 13: User presents their mDL to an mDL reader

The user presents their mDL to the mDL reader for identity verification, such as at an airport. This process is called mDL Initialization in ISO/IEC 18013-5:2021 section 6.3.2.2. The mDL is activated during this initialization step.

Step 14: An mDL reader requests mDL data from a user’s mobile device

The mDL reader issues an mDL retrieval request to the user’s mobile device. A key feature of mDLs is that they allow mDL holders to present a subset of their PII. An mDL reader will request specific attributes such as name and date of birth, requiring the mDL holder to consent to the release of this information. The mDL reader’s request contains the list of PII data element identifiers that it is requesting the mDL holder to share.

Step 15: User consents to share their mDL data

The user receives a prompt notifying them of mDL sharing request. This prompt shows the user the list of PII data elements that are being requested. The user consents to the request and the mDL data that includes the MSO is shared with the reader.

Step 16: Reader validates mDL integrity

The reader receives the mDL data and validates it for integrity. The inclusion of the MSO with the mDL data elements provides mDL readers with a mechanism for validating the integrity of the data they’ve received. The mDL reader can then hash and verify individual mDL data elements presented by the device. If all data elements match their corresponding entries in the MSO, the mDL device reader can attest that the data hasn’t been tampered with.

As an example, assume that the mDL contains the following data elements:

24(<<
  {
    "digestID": 0,
    "random": h'BBA394B98088CAE238D35979F7210E18DFAF70354524D86149CA20046E4321B1',
    "elementIdentifer": "given_name",
    "elementValue": "John"
  }
>>),
24(<<
  {
    "digestID": 1,
    "random": h'901F63FD880A15B30EDCEEFA857201C52FB9EAD1D39C15BB592829D16CB8A368',
    "elementIdentifer": "family_name",
    "elementValue": "Doe"
  }
>>)

And a Mobile Security Object containing the following data element digests:

24(<<
  {
    "version": "1.0",
    "digestAlgorithm": "SHA-256",
    "valueDigests":
    {
      "org.iso.18013.5.1":
      {
        0: h’D6AA81E454036313A9A681809151DDDBDF702289094F18286DDC591C41C6434E',
        1: h'4C3D83940CA8C5DE8060A23EB649C175E79B745B6A7D9939B4D16B3E46BB14D5'
      }
    }
  }
>>)

The MSO’s integrity would first confirm that the validity period of the MSO (not shown) has not expired. It can then verify the signature (not shown) with the issuing authority’s public key. After this has been established, both data elements need to be verified. The CBOR representation of each element (digestID, random, elementIdentifier, and elementValue) is encoded as bytes and then hashed using SHA-256. For example, the following should equal D6AA81E454036313A9A681809151DDDBDF702289094F18286DDC591C41C6434E.

SHA256(CBOR byte representation of 24(<<
    {
      "digestID": 0,
      "random": h'BBA394B98088CAE238D35979F7210E18DFAF70354524D86149CA20046E4321B1',
      "elementIdentifer": "given_name",
      "elementValue": "John"
    }
  >>))
)

Likewise, the following example should equal
4C3D83940CA8C5DE8060A23EB649C175E79B745B6A7D9939B4D16B3E46BB14D5.

SHA256(CBOR byte representation of 24(<<
    {
      "digestID": 1,
      "random": h'901F63FD880A15B30EDCEEFA857201C52FB9EAD1D39C15BB592829D16CB8A368',
      "elementIdentifer": "family_name",
      "elementValue": "Doe"
    }
  >>)))

If all data elements pass this hash verification check, then the presented mDL contents can be trusted by the mDL reader.

Summary

As you saw in this solution, mobile driver’s licenses (mDLs) provide increased security and flexible consent management to preserve privacy for individuals. The principles of cryptographic signing and verification aren’t new and both AWS KMS and AWS Private CA are well suited for supporting digital identity applications, whether it’s a driver’s license or some other kind of identification. To learn more about AWS KMS asymmetric keys and AWS Private CA, see Digital signing with the new asymmetric keys feature of AWS KMS and How to host and manage an entire private certificate infrastructure in AWS.

If you have feedback about this post, submit comments in the Comments section below. If you have questions about this post, start a new thread on the AWS Certificate Manager re:Post and AWS AWS Key Management Service re:Post, or contact AWS Support.

Ram Ramani Ram Ramani
Ram is a Principal Security architect in AWS, responsible for leading the data protection and privacy focus areas. Prior to this role, Ram held software developer positions at various organizations with a focus on applied math and machine learning.
Raj Jain Raj Jain
Raj is a Senior Software Engineer in the Amazon FinTech organization, responsible for developing security and compliance services that underlie the AWS and broader Amazon infrastructure. Raj is a published author in the Bell Labs Technical Journal, has authored IETF standards, AWS security blogs, and holds twelve patents.
Kyle Schultheiss Kyle Schultheiss
Kyle is a Senior Software Engineer on the AWS Cryptography team. He has been working on the ACM Private Certificate Authority service since its inception in 2018. In prior roles, he contributed to other AWS services such as Amazon Virtual Private Cloud, Amazon EC2, and Amazon Route 53.