Generate your first Face Certificate

Getting started with functional eID

Now that you are familiar with generating foundational eID SensePrints, it is time to learn how to allow verification of foundational eID holders using their face without having their face.

Prerequisites for Face Certificate Generation

To generate a Face Certificate, you must have:

  1. SensePrint - You cannot generate a certificate for a particular pupose without having the foundational eID - i.e. the SensePrint

  2. User's Face - Any key generation operation using a SensePrint is impossible without the user's face.

  3. Purpose ID - A Face Certificate contains a public key derived from a user's face as pertaining to a specific purpose. As an example, the purpose ID could simply be a unique identifier associated to a particular verifier - i.e. the verifier's ID / web site etc.

  4. eID attributes subset (optional) - A Face Certificate can also contain a subset of attributes from the foundational eID as requested by a particular verifier. When included, these are typically encrypted using a specified public key so that only an authorized verifier can read them. The attributes are included as a JSON string. If the SensePrint doesn't contain any of the requested attributes, they are ignored.

  5. Public Key (optional) - When included, the requested attributes JSON string is encrypted using this key.

  6. The server must be configured with a private key as detailed in the Configuration section.

Generating Secp256k1 Key Pairs (for eID attribute encryption) - optional

While most programming languages will provide libraries to generate key pairs, to get you started, you can use the the OpenSSL command line tool. To install OpenSSL:

  1. Windows - FireDaemon provides binary installers for your convenience.

  2. Linux - You can install OpenSSL on linux by using the following commands: sudo apt update sudo apt install openssl

Within OpenSSL installed, from the command line, you can first generate a keypair:

openssl ecparam -name secp256k1 -genkey -noout -out secp256k1-key.pem

The keypair is now stored in a file called secp256k1-key.pem.

To print the Base64 encoded public key that the API will accept:

openssl ec -in secp256k1-key.pem -pubout -conv_form compressed -outform DER | tail -c 33 | openssl base64

Later, during certificate verification, you will also need the private key. You can get this from the same file using:

openssl ec -in secp256k1-key.pem -outform DER | tail -c +8 | head -c 32 | openssl base64

Using the API end-point

As before, on the Swagger Docs page authorize using the API Key you setup earlier.

Expand the /generate-face-certificate section and then click the Try it out button as shown below:

As before, after clicking the Try it out button, the following JSON text will become editable:

{
  "attribute_encryption_secp256k1_public_key_base64": "(optional) A9mSFE03nGlgjOUP77viNqryw2pH8nbOWQOL7wChgitF",
  "check_live_face_before_creation": true,
  "expiration_date_utc": "2034-10-01T00:00:00Z",
  "face_base_64": "face_base_64",
  "liveness_tolerance": "REGULAR",
  "os": "DESKTOP",
  "password": "(optional) password",
  "purpose_id": "login:www.example.com",
  "requested_attributes": "(optional) [\"email\", \"name\"]",
  "senseprint_base_64": "senseprint_base_64",
  "user_subject_name": "user@example.com",
  "verifiers_auth_key": "(optional) verifiers_auth_key"
}

attribute_encryption_secp256k1_public_key_base64 specifies a base64 encoded public key on the Secp256k1 curve. When this key is specified, the server will encrypt the requested_attributes JSON string with this key.

check_live_face_before_creation will check if the face in face_base_64 is live (no spoofing detected) before creating a Face Certificate.

expiration_date_utc is a UTC time stamp of when the Face Ceritificate will expire.

face_base_64 is an image of the eID holder's face represented as a Base64 string. Most programming libraries will provide a way to convert a file to Base64, but for a quick demonstration, you can use this page to convert an image to a Base64 string.

liveness_tolerance is only used when check_live_face_before_creation is set to true and determines the strictness of the liveness algorithm.

os is also used only when check_live_face_before_creation is set to true and finetunes the liveness check. It indicates the operating system the image was captured on. Valid values are ANDROID / IOS / DESKTOP.

password should be specified when the senseprint_base_64 was generated with a password.

purpose_id specifies the purpose of the Face Certificate. It can also be simply a verifiers ID (UUID).

senseprint_base_64 is a base 64 encoded raw SensePrint from which a public key will be generated fo the specified purpose.

requested_attributes when specified, will include the attributes in the Face Certificate. Only matched attribute names will be included. When a attribute_encryption_secp256k1_public_key_base64 is specified, the attributes JSON string will be encypted with the specified public key. If a key is not specified, then the attributes will be included as plain-text JSON.

user_subject_name is the subject name of the use for whom the cerificate is being generated. If the certificate will be stored in a public registry, it is recommended that the subject name is pseudonymized or hashed.

verifiers_auth_key should be specified when a SensePrint was generated with it specified during generation as well.

Understanding a certificate

If all goes well, you should see a response like the following:

{
  "cert_pem": "-----BEGIN CERTIFICATE-----\nMIIBkjCCATmgAwIBAgIQCo5zstpLm+yH4RyZ/zaLezAKBggqhkjOPQQDAjBIMUYw\nRAYDVQQDDD1TZW5zZUNyeXB0IEN1c3RvbWVyIElEIChjNGUzODk5MC1iNWFhLTRh\nOGItOGUyMi1jOTFkZGRjNWNlMGEpMB4XDTcwMDEwMTAwMDAwMFoXDTM0MTAwMTAw\nMDAwMFowGzEZMBcGA1UEAwwQdXNlckBleGFtcGxlLmNvbTBWMBAGByqGSM49AgEG\nBSuBBAAKA0IABB/L2yY5QIAYRROv9DszquN3r8MIOzaeuhGRPkaGRcZxaxR2koJN\n83QYQzbkSyq3Q03HT9SmpaL/P2weJ2HtG8+jNTAzMA4GA1UdDwEB/wQEAwIFoDAh\nBgoqhT4Ah3QBAQAABBN7Im5hbWUiOiJKb2huIERvZSJ9MAoGCCqGSM49BAMCA0cA\nMEQCIFnuHqVfiovbBeDEohGDzf9io8370cGEY3BljV/7owXfAiBOSTLC8uOLhgEb\n/d9GHkrand+z7MnviHjXHLCCtYL8MQ==\n-----END CERTIFICATE-----\n"
}

This is the JSON representation of you certificate (with line breaks represented as \n. You could use a language of your choice to save the string to a file. In this example, we use Python:

cert = "-----BEGIN CERTIFICATE-----\nMIIBkjCCATmgAwIBAgIQCo5zstpLm+yH4RyZ/zaLezAKBggqhkjOPQQDAjBIMUYw\nRAYDVQQDDD1TZW5zZUNyeXB0IEN1c3RvbWVyIElEIChjNGUzODk5MC1iNWFhLTRh\nOGItOGUyMi1jOTFkZGRjNWNlMGEpMB4XDTcwMDEwMTAwMDAwMFoXDTM0MTAwMTAw\nMDAwMFowGzEZMBcGA1UEAwwQdXNlckBleGFtcGxlLmNvbTBWMBAGByqGSM49AgEG\nBSuBBAAKA0IABB/L2yY5QIAYRROv9DszquN3r8MIOzaeuhGRPkaGRcZxaxR2koJN\n83QYQzbkSyq3Q03HT9SmpaL/P2weJ2HtG8+jNTAzMA4GA1UdDwEB/wQEAwIFoDAh\nBgoqhT4Ah3QBAQAABBN7Im5hbWUiOiJKb2huIERvZSJ9MAoGCCqGSM49BAMCA0cA\nMEQCIFnuHqVfiovbBeDEohGDzf9io8370cGEY3BljV/7owXfAiBOSTLC8uOLhgEb\n/d9GHkrand+z7MnviHjXHLCCtYL8MQ==\n-----END CERTIFICATE-----\n"
with open("example.pem", "w") as my_cert:
    my_cert.write(cert)

Now you will have a file called example.pem which contains your certificate.

Certificate Structure

You can run an OpenSSL command to view the contents of your certificate:

openssl x509 -noout -text -in example.pem

Depending on whether you supplied a verifiers_auth_key or not, the certificate will contain either an X.509v3 extension of 1.2.702.0.1012.1.1.0.0 (for plain text attributes) or 1.2.702.0.1012.1.1.1.0 (for encrypted attributes).

Below we show a certificate where the verifiers_auth_key was not specified and eID attributes are unencrypted - correspondingly the 1.2.702.0.1012.1.1.0.0 extension is included in the certificate:

Certificate:
    Data:
        Version: 3 (0x2)
        Serial Number:
            0a:8e:73:b2:da:4b:9b:ec:87:e1:1c:99:ff:36:8b:7b
        Signature Algorithm: ecdsa-with-SHA256
        Issuer: CN = SenseCrypt Customer ID (c4e38990-b5aa-4a8b-8e22-c91dddc5ce0a)
        Validity
            Not Before: Jan  1 00:00:00 1970 GMT
            Not After : Oct  1 00:00:00 2034 GMT
        Subject: CN = user@example.com
        Subject Public Key Info:
            Public Key Algorithm: id-ecPublicKey
                Public-Key: (256 bit)
                pub:
                    04:1f:cb:db:26:39:40:80:18:45:13:af:f4:3b:33:
                    aa:e3:77:af:c3:08:3b:36:9e:ba:11:91:3e:46:86:
                    45:c6:71:6b:14:76:92:82:4d:f3:74:18:43:36:e4:
                    4b:2a:b7:43:4d:c7:4f:d4:a6:a5:a2:ff:3f:6c:1e:
                    27:61:ed:1b:cf
                ASN1 OID: secp256k1
        X509v3 extensions:
            X509v3 Key Usage: critical
                Digital Signature, Key Encipherment
            1.2.702.0.1012.1.1.0.0: 
                {"name":"John Doe"}
    Signature Algorithm: ecdsa-with-SHA256
    Signature Value:
        30:44:02:20:59:ee:1e:a5:5f:8a:8b:db:05:e0:c4:a2:11:83:
        cd:ff:62:a3:cd:fb:d1:c1:84:63:70:65:8d:5f:fb:a3:05:df:
        02:20:4e:49:32:c2:f2:e3:8b:86:01:1b:fd:df:46:1e:4a:da:
        9d:df:b3:ec:c9:ef:88:78:d7:1c:b0:82:b5:82:fc:31

The meaning of 1.2.702.0.1012.1.1.0.0 (for plain text attributes) or 1.2.702.0.1012.1.1.1.0 (for encrypted attributes) can be seen at the following URLs:

These are globally registered object IDs that are expanded below.

Unencrypted attributes as JSON object identifier:

{iso(1) member-body(2) sg(702) snraoid(0) seventh-sense(1012) sensecrypt(1) user-attributes(1) plain-text(0) json(0)}

Encrypted attributes as JSON object identifier:

{iso(1) member-body(2) sg(702) snraoid(0) seventh-sense(1012) sensecrypt(1) user-attributes(1) encrypted(1) json(0)}

Depending on whether eID attributes were requested, and whether an encryption key was specified, your certificate will contain either no extension, or one of 1.2.702.0.1012.1.1.0.0 (unencrypted), or 1.2.702.0.1012.1.1.1.0 (encrypted).

Last updated