# 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](https://docs.sensecrypt.com/sensecrypt-v3.1.3/sensecrypt-server/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](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="https://content.gitbook.com/content/3MaK792MtyPjO8jJjWM7/blobs/YYi5X8DG6fLJbjOQqvWm/swagger-generate-face-cert.png" 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).
