REST API

The REST API offered by Web Services Option Pack is made up of three parts: crypto for cryptographic operations, km for key management, and a health check endpoint. Full details of the REST API are available in the Web Services Option Pack OpenAPI spec file /opt/nfast/wsop/docs/swagger.yml.

The currently defined set of operations is as follows:

  • Crypto

    • Sign

    • Verify

    • Encrypt

    • Decrypt

  • Key Management

    • List Keys

    • Get Key information

    • Create Key

    • Delete Key

    • List Key Groups

    • List Keys in a Key Group

    • Get Key Group information

    • Get Key Group name

    • Create Protection Domain

    • Delete Protection Domain

    • List Protection Domains

    • Get Protection Domain information

    • Activate a Protection Domain

    • Deactivate a Protection Domain

  • Health check endpoint

Common fields

Several of these fields are common to many cryptographic and key management operations.

Key identifiers

Security World keys are uniquely identified in REST calls through a resource identifier. A key’s resource identifier includes which Key Group it is a member of. An example key identifier is:

km/v1/groups/ee3b7c4b-c6a7-3f2b-9d1c-0fc6c76168bb/keys/f9388a1e-b1c6-3e0e-bb5e-8eb887aab4be

Key Group identifiers

All Security World keys belong to exactly one Key Group. Each Key Group belongs to, and is protected by, a single Protection Domain. An example key group identifier is:

ee3b7c4b-c6a7-3f2b-9d1c-0fc6c76168bb

Protection Domain identifiers

A Protection Domain is either a Softcard or the set of all module keys. An example Protection Domain identifier is:

ee3b7c4b-c6a7-3f2b-9d1c-0fc6c76168bb

Protection Domain types

A Protection Domain is one of the following types:

  • Module

  • Softcard

  • Well-Known

Plaintext, ciphertext, payloads and signatures

Data sent in requests or responses is encoded in base64url format. Base64url encoding is a variation of standard base64 encoding and uses a slightly different character set that are safe for using in URLs without additional escaping of reserved characters, see Base64url Encoding

Data that forms part of cryptographic operations must be sent in a single request. Responses will similarly be sent from Web Services Option Pack as a single response body.

Digest option

Applicable for signing and verification requests, the optional digest Boolean flag indicates whether the provided payload has been hashed prior to sending the request.

When the digest flag is set to true, the server-side hashing of the payload is skipped, and length checking is performed to ensure that the supplied payload is the correct length for the hash that corresponds to the signature or verification algorithm.

The digest flag is not applicable for HMAC signing and verification requests.

Algorithm identifiers

The majority of the algorithms are identified using JSON Web Algorithm identifiers. For example, RS256 specifies RSA signatures with SHA-256 for hashing. For further information, see Supported Algorithms in this User Guide and the Web Services Option Pack OpenAPI Specification.

Key type identifiers

The types of keys that can be created are identified using nCore identifiers. Refer to the Web Services Option Pack OpenAPI Specification for further information.

Elliptic Curve identifiers

Elliptic Curves are identified using defined names from the Digital Signature Standard (DSS). For example, P-256. Refer to Web Services Option Pack OpenAPI Specification for further information.

Examples

Given a client certificate and corresponding key, it is possible to use command line tools such as curl to demonstrate use of the REST API. These examples assume the following:

  • The Web Services Option Pack server’s CA certificate is located in server_ca.pem.

  • A valid client certificate is located in client_crt.pem.

  • The private key corresponding to the client certificate is located in client_key.pem.

List keys

List all keys:

curl --cacert server_ca.pem \
    --cert client_crt.pem --key client_key.pem \
    --header 'Accept: application/json' \
    --request GET \
    "https://wsop.server:18001/km/v1/keys?sort=created"

Result:

{
    "keys": [
        {
            "created": "2017-07-03T13:17:56Z",
            "kid": "/km/v1/groups/366f38ec-64e1-503c-9950-18cc324d67c6/keys/90050af4-9b8c-5731-bbf2-08e3af797e2c",
            "sworldAppname": "simple",
            "sworldIdent": "test-aes"
        },
        {
            "created": "2017-07-06T15:44:12Z",
            "kid": "/km/v1/groups/366f38ec-64e1-503c-9950-18cc324d67c6/keys/e51a13d1-b775-3129-b1f9-b8642a212475",
            "sworldAppname": "simple",
            "sworldIdent": "test-rsa"
        }
        //...
    ]
}

List one key:

curl --cacert server_ca.pem \
    --cert client_crt.pem --key client_key.pem \
    --header 'Accept: application/json' \
    --request GET \
    "https://wsop.server:18001/km/v1/keys?limit=1"

Result:

{
    "keys": [
        {
            "created": "2017-07-03T13:17:56Z",
            "kid": "/km/v1/groups/366f38ec-64e1-503c-9950-18cc324d67c6/keys/90050af4-9b8c-5731-bbf2-08e3af797e2c",
            "sworldAppname": "simple",
            "sworldIdent": "test-aes"
        }
    ]
}

List keys, with an offset:

curl --cacert server_ca.pem \
    --cert client_crt.pem --key client_key.pem \
    --header 'Accept: application/json' \
    --request GET \
    "https://wsop.server:18001/km/v1/keys?offset=2"

Result:

{
    "keys": [
        {
            "created": "2017-07-06T08:12:51Z",
            "kid": "/km/v1/groups/366f38ec-64e1-503c-9950-18cc324d67c6/keys/69fc1c75-81eb-58ad-83ff-c3fd517c27cf",
            "sworldAppname": "simple",
            "sworldIdent": "test-aes192"
        },
        {
            "created": "2017-07-07T17:24:31Z",
            "kid": "/km/v1/groups/366f38ec-64e1-503c-9950-18cc324d67c6/keys/7f34e38a-be3a-5378-a163-3313ce82ea02",
            "sworldAppname": "simple",
            "sworldIdent": "test-aes256"
        }
        //...
    ]
}

List all keys created since the beginning of the year:

curl --cacert server_ca.pem \
    --cert client_crt.pem --key client_key.pem \
    --header 'Accept: application/json' \
    --request GET \
    -d "filter=created%20ge%20datetime'2017-01-01T00:00:00Z'"
    "https://wsop.server:18001/km/v1/keys"

Result:

{
    "keys": [
        {
            "created": "2017-07-03T13:17:56Z",
            "kid": "/km/v1/groups/366f38ec-64e1-503c-9950-18cc324d67c6/keys/90050af4-9b8c-5731-bbf2-08e3af797e2c",
            "sworldAppname": "simple",
            "sworldIdent": "test-aes"
        },
        {
            "created": "2017-07-06T15:44:12Z",
            "kid": "/km/v1/groups/366f38ec-64e1-503c-9950-18cc324d67c6/keys/e51a13d1-b775-3129-b1f9-b8642a212475",
            "sworldAppname": "simple",
            "sworldIdent": "test-rsa"
        }
    ]
}
The use of %20 to escape spaces in URIs. Date and time stamps are in ISO-8601 format.

List all keys which have a certain name:

curl --cacert server_ca.pem \
    --cert client_crt.pem --key client_key.pem \
    --header 'Accept: application/json' \
    --request GET \
    "https://wsop.server:18001/km/v1/keys?name=engineering"

Result:

{
    "keys": [
        {
            "created": "2021-12-17T16:44:52Z",
            "kid": "/km/v1/groups/19e40e8c-2188-5f9f-a1c8-8007424a4157/keys/589e4486-9da6-53ec-92ff-b2444c61ee02",
            "name": "engineering",
            "sworldAppname": "simple",
            "sworldIdent": "test-aes192"
        },
        {
            "created": "2021-12-17T16:44:52Z",
            "kid": "/km/v1/groups/19e40e8c-2188-5f9f-a1c8-8007424a4157/keys/470d26c7-ad9d-5e49-9910-6e0c4fa9dad5",
            "name": "engineering",
            "sworldAppname": "simple",
            "sworldIdent": "test-aes256"
        },
        {
            "created": "2021-12-17T16:45:08Z",
            "kid": "/km/v1/groups/a8668e0d-ef17-5a36-9dff-12a885dcb738/keys/1afdf157-056a-561e-8280-9b1b8e3aa817",
            "name": "engineering",
            "public": "/km/v1/groups/a8668e0d-ef17-5a36-9dff-12a885dcb738/keys/1afdf157-056a-561e-8280-9b1b8e3aa817/public",
            "sworldAppname": "simple",
            "sworldIdent": "test-rsa"
        }
    ]
}

List all keys with a matching substring of that named.

curl --cacert server_ca.pem \
    --cert client_crt.pem --key client_key.pem \
    --header 'Accept: application/json' \
    --request GET \
    -d "filter=kid%20contains'269f0189'"
    "https://wsop.server:18001/km/v1/keys"

Result:

{
    "keys": [
        {
            "created": "2017-07-03T13:17:56Z",
            "kid": "/km/v1/groups/366f38ec-64e1-503c-9950-18cc324d67c6/keys/90050af4-9b8c-5731-bbf2-08e3af797e2c",
            "sworldAppname": "simple",
            "sworldIdent": "test-aes"
        }
    ]
}

List keys in a group

List all keys belonging to a certain group, for instance 19e40e8c-2188-5f9f-a1c8-8007424a4157 group:

curl --cacert server_ca.pem \
    --cert client_crt.pem --key client_key.pem \
    --header 'Accept: application/json' \
    --request GET \
    "https://wsop.server:18001/km/v1/groups/19e40e8c-2188-5f9f-a1c8-8007424a4157/keys"

Result:

{
    "keys": [
        {
            "created": "2021-12-17T16:44:52Z",
            "kid": "/km/v1/groups/19e40e8c-2188-5f9f-a1c8-8007424a4157/keys/4a59aec6-1cb4-5f27-9546-249b6e241f6f",
            "sworldAppname": "simple",
            "sworldIdent": "test-aes192"
        },
        {
            "created": "2021-12-17T16:44:51Z",
            "kid": "/km/v1/groups/19e40e8c-2188-5f9f-a1c8-8007424a4157/keys/dc2b10ee-dc7b-521f-b732-db252f7c13c2",
            "name": "accounting",
            "sworldAppname": "simple",
            "sworldIdent": "test-hmac256"
        },
        //...
    ]
}
All HTTP queries described in List keys also work when listing the keys of a certain group.

List Key Groups

List all key groups:

curl --cacert server_ca.pem \
    --cert client_crt.pem --key client_key.pem \
    --header 'Accept: application/json' \
    --request GET \
    "https://wsop.server:18001/km/v1/groups"

Result:

{
    "groups": [
        {
            "groupid": "ccba7ee7-9032-5217-9db2-58d07fd4c045",
            "keys": "/km/v1/groups/ccba7ee7-9032-5217-9db2-58d07fd4c045/keys",
            "name": "soft1",
            "protection": "/km/v1/protectiondomains/ccba7ee7-9032-5217-9db2-58d07fd4c045",
            "type": "Softcard"
        },
        {
            "groupid": "366f38ec-64e1-503c-9950-18cc324d67c6",
            "keys": "/km/v1/groups/366f38ec-64e1-503c-9950-18cc324d67c6/keys",
            "name": "Module Protection",
            "protection": "/km/v1/protectiondomains/366f38ec-64e1-503c-9950-18cc324d67c6",
            "type": "Module"
        },
    //...
    ]
}

Public key export

The following example exports the public key from an ECDSA key:

curl --cacert server_ca.pem \
    --cert client_crt.pem --key client_key.pem \
    --header 'Accept: application/json' \
    --request GET \
    "https://wsop.server:18001/km/v1/groups/366f38ec-64e1-503c-9950-18cc324d67c6/keys/6ff3a5ef-c12f-5e82-b1d6-d955caef2730"

Result:

{
    "alg": "ES384",
    "crv": "P-384",
    "kid": "/km/v1/groups/366f38ec-64e1-503c-9950-18cc324d67c6/keys/6ff3a5ef-c12f-5e82-b1d6-d955caef2730”,
    "kty": "EC",
    "x": "JDvhhAqlSpn2xrjq7C1iOYKvPZl1PVARsXlsQc9EyP9dxhcZSJ0bkJcYXuu-3PWx",
    "y": "_B3o_PZx2jsYA4nsKG82sCoEyCzdbeFTtIPrO5Y8PhkRc4owIiO_7BOUu97BkRsZ"
}

Public key import

Public Key import can only be performed in the Well-Known Protection key group.

curl --cacert server_ca.pem \
    --cert client_crt.pem –-key client_key.pem \
    --header 'Content-Type: application/json' \
    --header 'Accept: application/json' \
    --request POST \
-d '{"appname":"simple", "ident":"test-import", "public": {"alg": "ES384","crv": "P-384","kty": "EC","x": "JDvhhAqlSpn2xrjq7C1iOYKvPZl1PVARsXlsQc9EyP9dxhcZSJ0bkJcYXuu-3PWx", "y": "_B3o_PZx2jsYA4nsKG82sCoEyCzdbeFTtIPrO5Y8PhkRc4owIiO_7BOUu97BkRsZ"}}'
    'https://wsop.server:18001/km/v1/groups/2bd40730-85b1-5deb-8417-fb78a7735743/keys'

Result:

{
    "kid": "/km/v1/groups/2bd40730-85b1-5deb-8417-fb78a7735743/keys/170ff5ca-9d46-522c-84d1-84074955b94f"
}

Create keys

The following example creates a key in the Module Protection key group:

curl --cacert server_ca.pem \
    --cert client_crt.pem –-key client_key.pem \
    --header 'Content-Type: application/json' \
    --header 'Accept: application/json' \
    --request POST \
-d '\{"keytype":"ECDSA","curve":"P-256", "appname":"simple","ident":"test-p256"}'
    'https://wsop.server:18001/km/v1/groups/366f38ec-64e1-503c-9950-18cc324d67c6/keys'

Result:

{
    "kid": "/km/v1/groups/366f38ec-64e1-503c-9950-18cc324d67c6/keys/54872032-a16b-5c5e-a1c5-97f2656b7c24"
}

Delete keys

The following example deletes a key:

curl --cacert server_ca.pem \
    --cert client_crt.pem –-key client_key.pem \
    --request DELETE \
    'https://wsop.server:18001/km/v1/groups/366f38ec-64e1-503c-9950-18cc324d67c6/keys/54872032-a16b-5c5e-a1c5-97f2656b7c24'

On successful deletion, 204 No Content is returned.

Create Protection Domains

Create Protection Domain can only be performed with Softcard Protection Domain types. The following example creates a Protection Domain of type Softcard.

curl --cacert server_ca.pem \
    --cert client_crt.pem –-key client_key.pem \
    --header 'Content-Type: application/json' \
    --header 'Accept: application/json' \
    --request POST \
     -d '{"name":"softcard1","passphrase":"passphrase1","type":"Softcard"}' \
     'https://wsop.server:18001/km/v1/protectiondomains' | jq

Result:

{
  "id": "e3307c07-300e-585a-95da-ed4f3d0c226e"
}

Delete Protection Domains

Delete Protection Domain can only be performed with Softcard Protection Domain types. The following example deletes a Protection Domain and all associated keys.

curl --cacert server_ca.pem \
    --cert client_crt.pem –-key client_key.pem \
    --header 'Content-Type: application/json' \
    --header 'Accept: application/json' \
    --request DELETE \
    'https://wsop.server:18001/km/v1/protectiondomains/025ad489-3ec8-5bbc-b251-f0e497f7cd48?cascade=keys' | jq

On successful deletion, 204 No Content is returned.

List Protection Domains

List all Protection Domains:

curl --cacert server_ca.pem \
    --cert client_crt.pem --key client_key.pem \
    --header 'Accept: application/json' \
    --request GET \
    "https://wsop.server:18001/km/v1/protectiondomains"

Result:

{
    "protectiondomains": [
        {
            "active": true,
            "id": "366f38ec-64e1-503c-9950-18cc324d67c6",
            "name": "Module Protection",
            "type": "Module"
        },
        {
            "active": false,
            "id": "ccba7ee7-9032-5217-9db2-58d07fd4c045",
            "name": "soft1",
            "type": "Softcard"
        },
        //...
    ]
}

Activate Protection Domains

Activate a Protection Domain:

    curl --cacert server_ca.pem \
        --cert client_crt.pem –-key client_key.pem \
        --header 'Content-Type: application/json' \
        --header 'Accept: application/json' \
        --request POST \
        -d '\{"passphrase":"passphrase1"}' \
        "https://127.0.0.1:18001/km/v1/protectiondomains/ccba7ee7-9032-5217-9db2-58d07fd4c045/activate"

Result:

{
    "protectiondomain": {
        "active": true,
        "id": "ccba7ee7-9032-5217-9db2-58d07fd4c045",
        "name": "soft1",
        "type": "Softcard"
    }
}

Deactivate Protection Domains

Deactivate a Protection Domain:

curl --cacert server_ca.pem \
    --cert client_crt.pem –-key client_key.pem \
    --header 'Content-Type: application/json' \
    --header 'Accept: application/json' \
    --request POST \
    "https://127.0.0.1:18001/km/v1/protectiondomains/ccba7ee7-9032-5217-9db2-58d07fd4c045/deactivate"

Result:

{
    "protectiondomain": {
        "active": false,
        "id": "ccba7ee7-9032-5217-9db2-58d07fd4c045",
        "name": "soft1",
        "type": "Softcard"
    }
}

Sign payload

The following example signs a payload:

curl --cacert server_ca.pem \
    --cert client_crt.pem –-key client_key.pem \
    --header 'Content-Type: application/json' \
    --header 'Accept: application/json' \
    --request POST \
    -d '\{"kid":"/km/v1/groups/366f38ec-64e1-503c-9950-18cc324d67c6/keys/e51a13d1-b775-3129-b1f9-b8642a212475",
        "alg":"RS256",
        "payload":"dGVzdCBkYXRhCg"}'
    'https://wsop.server:18001/crypto/v1/sign'

Result:

{
"signature": "<base64url-encoded signature omitted>"
}

Verify signature

The resulting signature can be verified as follows:

curl --cacert server_ca.pem \
    --cert client_crt.pem –-key client_key.pem \
    --header 'Content-Type: application/json' \
    --header 'Accept: application/json' \
    --request POST \
    -d '\{"kid":"/km/v1/groups/366f38ec-64e1-503c-9950-18cc324d67c6/keys/e51a13d1-b775-3129-b1f9-b8642a212475",
        "alg":"RS256",
        "payload":"dGVzdCBkYXRhCg",
        "signature": "<base64url-encoded signature omitted>"}'
    'https://wsop.server:18001/crypto/v1/verify'

Result:

{
"valid":true
}

Encrypt plaintext

The following example encrypts some plaintext:

curl --cacert server_ca.pem \
    --cert client_crt.pem –-key client_key.pem \
    --header 'Content-Type: application/json' \
    --header 'Accept: application/json' \
    --request POST \
    -d '\{"kid":"/km/v1/groups/366f38ec-64e1-503c-9950-18cc324d67c6/keys/90050af4-9b8c-5731-bbf2-08e3af797e2c",
        "alg":"RSA-OAEP-256",
        "plaintext":"dGVzdCBkYXRhCg"}'
    'https://wsop.server:18001/crypto/v1/encrypt'

Result:

{
"ciphertext": "<base64url-encoded ciphertext omitted>",
}

Decrypt ciphertext

The resulting ciphertext can be decrypted as follows:

curl --cacert server_ca.pem \
    --cert client_crt.pem –-key client_key.pem \
    --header 'Content-Type: application/json' \
    --header 'Accept: application/json' \
    --request POST \
    -d '\{"kid":"":"/km/v1/groups/366f38ec-64e1-503c-9950-18cc324d67c6/keys/90050af4-9b8c-5731-bbf2-08e3af797e2c ",
        "alg":"RSA-OAEP-256",
        "ciphertext":"<base64url-encoded ciphertext omitted>"}'
    'https://wsop.server:18001/crypto/v1/decrypt'

Result:

{
"plaintext": "dGVzdCBkYXRhCg"
}

Health check

The health of the system can be checked as follows:

curl --cacert server_ca.pem \
    --cert client_crt.pem –-key client_key.pem \
    --header 'Content-Type: application/json' \
    --header 'Accept: application/json' \
    --request GET \
    'https://wsop.server:18001/health'

Result:

{
    "releaseId": "1.2.0",
    "status": "pass",
    "version": "1"
}
The health check endpoint can be configured to not require TLS mutual authentication while retaining mutual authentication on all other endpoints. For more information, see Configuration.

Error handling

In the event of a failed request, errors are reported to the client by using the HTTP response codes that indicate errors and an appropriate error message and error code in the response body in JSON format.

For example:

{
    "error": "ResourceNotFound",
    "message": "loading key /km/v1/groups/366f38ec-64e1-503c-9950-18cc324d67c6/keys/98487743-2ac4-5fe9-81ba-95eb4a93cae4 failed: unknown key",
    "path": "/crypto/v1/sign",
    "status": "404",
    "timestamp": "2019-12-05T09:58:40Z"
}

Language bindings

An OpenAPIv2-compliant API description is provided (/opt/nfast/wsop/docs/swagger.yml). This represents the Web Services Option Pack REST API, which can be used for generating bindings for a number of programming languages using tools provided as part of Smartbear’s Swagger.

The correctness of the generated bindings from Smartbear’s Swagger tooling cannot be guaranteed due to numerous issues with the generators. For more information, see the documentation provided by Smartbear.