# Generate your first Face Certificate

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](/sensecrypt-v3.1.1/sensecrypt-server/configuration.md) 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](https://kb.firedaemon.com/support/solutions/articles/4000121705) 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:

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

The keypair is now stored in a file called `secp256k1-key.pem`.&#x20;

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

```batch
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:

```batch
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:

<figure><img src="/files/8q5RC5LiS28rUgP7H6aI" alt=""><figcaption><p>Interacting with the generate-face-certificate end-point</p></figcaption></figure>

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

```json
{
  "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](https://base64.guru/converter/encode/image) 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:

```json
{
  "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:

```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:

```batch
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).&#x20;

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:

1. `1.2.702.0.1012.1.1.0.0` (unencrypted)- [http://www.oid-info.com/cgi-bin/display?oid=1.2.702.0.1012.1.1.0.0](http://www.oid-info.com/cgi-bin/display?oid=1.2.702.0.1012.1.1.0.0\&submit=Display\&action=display)
2. `1.2.702.0.1012.1.1.1.0` (encrypted) - [http://www.oid-info.com/cgi-bin/display?oid=1.2.702.0.1012.1.1.1.0](http://www.oid-info.com/cgi-bin/display?oid=1.2.702.0.1012.1.1.1.0\&a=display)

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).


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.sensecrypt.com/sensecrypt-v3.1.1/sensecrypt-server/sensecrypt-face-pki/generate-your-first-face-certificate.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
