Skip to main content

Sign with an SKA Key

This guide is a step-by-step tutorial for how to use SKA keys for signing, using the Transaction Security Broker (TSB) as the workflow engine.

This tutorial shows how a business application can create the signing request, how approvers poll their pending tasks, how they approve a task, and finally how the business application can fetch the computed signature.

For other types of SKA key usages (decrypt, unwrap, ...) see this tutorial.

Prerequisites

This tutorial assumes that you have already created an SKA key. In the ruleUse part of the SKA policy, you should have specified the approvers who can use the SKA key.

Issue a Signature Request

First, the business application issues a signing request. In the payload, include the message to be signed, encoded with base64. As the signKeyName, specify the label of the SKA key that you want to use.

POST /v1/sign

{
"signRequest": {
"payload": "QXBwcm92ZVNpZ25UYXNrUGF5bG9hZA==",
"payloadType": "UNSPECIFIED",
"signKeyName": "TSB_TUTORIAL_1-RSA",
"signatureAlgorithm": "SHA256_WITH_RSA"
}
}

Response: Status: 201

The response is not the actual signature. Instead, it is the UUID that the business application can use to asynchronously query the signature. The signature will be available once all approvals have been given, that is, once the SKA policy is fulfilled.

{
"signRequestId": "4e8731d8-0ae6-4444-8a8c-b73ab5f0ba18"
}

Internally, the TSB fetches the SKA policy of the SKA key. Then, the TSB creates approval tasks for all approvers listed in the policy.

Fetch the Approval Tasks

Next, the approver applications (such as the Securosys Authorization App) poll the TSB for pending approval tasks. When a task is available, the app shows the tasks to the human approver, and asks them to approve or reject the request.

API Access control

The /v1/filteredSignApprovalTask is not part of the normal TSB API Authentication controls. This is because for mobile apps, it is hard to set up mTLS, and you may not want to give them API keys.

Instead, access control is done by signing a timestamp (see the timestamp and timestampSignature fields). This way, the approver proves that they control the approver private key, and hence that they are authorized to query the pendings tasks for this approver.

Demo Helper

Use this helper script to sign the current timestamp, creating the request body that you need for the request to /v1/filteredSignApprovalTask.

Run it with sh sign_timestamp_rsa.sh approverName

POST /v1/filteredSignApprovalTask

{
"timestamp": "2023-10-30T17:30:24+00:00",
"timestampSignature": "VuZ0f/VEM2iq0zGCAVFTgWWD5zLJGCtUs/Eh3ecz4lYXSU42TwTWjwL6EQ4SHXf2gYZoci5q5nwswxkd0i4gvQ5fKd3lM8RzleDUziWqicrak65guIKynYuOvvYE29yqkwQ20N4FTKHAoseokIch8ByhxTeURFAinWHJZ9Rhf9ShojGn5f5/sP6G8C7WHMOaOB7f5e+FrjRfQs660rVaVjQU6XKmRrtKHsQQcMTz2Npm4/ikBolVSUXV4ZWUofA8ZR3+/aBsINw/CALnNIp+9mU6WEbneRz6nK1/LWV/VMT8A9J4gEo8GIGGSCFWlbq2P6DxTxLSHByEiNelYxOkqA==",
"approverCertificate": "MIIDUTCCAjmgAwIBAgIUVyyrH8t8ldAUzHaYAyavN7mK6lMwDQYJKoZIhvcNAQELBQAwODELMAkGA1UEBhMCQ0gxDTALBgNVBAoMBFRlc3QxGjAYBgNVBAMMEVNLQSBUZXN0IDIwMjMgUlNBMB4XDTIzMTAzMDE1MjIxMFoXDTI0MTAyOTE1MjIxMFowODELMAkGA1UEBhMCQ0gxDTALBgNVBAoMBFRlc3QxGjAYBgNVBAMMEVNLQSBUZXN0IDIwMjMgUlNBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAuUy1tRrrO5xf6576qAJlLHX3HLGP7AKLfHW0TRGXfLP+ngFiSF4qAQdeU7rDtoY0QbjPazqFr8E9wuvjZX4B8xDEPPlECEO+7ixmeb0CX1HtZrES4b9CJuYunBl/ENNujnXH0pE9yw5/SiIxujISyNZmorDIurMsi7JYreq3ZOj8IisMDHVNfJKPV4QMOWKGtUfj/s7EdQ9H6pEvZcmy/Z9PyYWSCDcID4lrMg/FfdZRwvp9OcouypKOoDKf0pK2K0eYZQtnLZzHA+KI3xTjrpRFHtfufnKd9hozndp3OkZv8ZJFfjJ55RXL1K/ZqHSNSsmOxcGzzfNwI0+S/BjYtQIDAQABo1MwUTAdBgNVHQ4EFgQU261gJf0Ta1kqLevzofEU/vqbY9MwHwYDVR0jBBgwFoAU261gJf0Ta1kqLevzofEU/vqbY9MwDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAQEAbjTisq3rwCcomv4BD2j0DFm+pS3uUDFgGkOci93XSq89rJaWw4mUcQDhdU8rXjm5hNT+XoPND80sv/LwnCVUAXmhGiwwjXNcIORje+5z/Wys+jmPfOrfrzOaoOQEFw5ZQY3SgSQaEN+pmQr4HhorGnlY8aWIQ5XEgx7scebRQI6xx8zeQID20IJTElHby5haCdtaAO9BR+E3U6NnPyr9gFDn0YAf/OfadpaI1beu5TBBj5k9e7+Yzidp+BboolWhvPLSoMlmrTlgwl6Tub/ZQdAelUD0sks5hqZbCjO1/FPIrDgRP57pUw3+EKbDwfpaIOdQGMjr4I/+nAPuWd5s1A==",
"timestampDigestAlgorithm": "SHA-256",
"detailLevel": "level1",
"paging": {
"pageNumber": 0,
"pageSize": 1,
"sortOrder": "CREATION_DATE_ASC"
}
}
Request Parameters
ParameterDescription
timestampThe ISO-8601 formatted timestamp that has been signed by the approval client.
timestampSignatureThe signature (base64 encoded) for the timestamp (ISO-8601) that was done using the key of the approver. Format of the signature is depending on the algorithm used and as returned when using a JDK's native Signature.sign() method.

TIMESTAMP=$(date -u "+%Y-%m-%dT%H:%M:%S+00:00")
SIGNATURE=$(echo -n $TIMESTAMP | openssl dgst -sha256 -sign $PRIVATE_KEY_NAME | openssl enc -base64 | tr -d '\n')
approverCertificateCertificate of the approver in DER format (base64 encoded). Either the approverPublicKey or the approverCertificate has to be provided if the timestampSigningCertificate is not set.
timestampDigestAlgorithmThe message digest algorithm that was used for computing the timestamp signature. SHA-224, SHA-256, SHA-384, SHA-512, SHA3-224, SHA3-256, SHA3-384, SHA3-512
idIf specified filters for a specific task id.
requestIdIf specified filters for a specific request id by approver Public Key. Request ID is ignored if task ID is set.
detailLevelThe detail level of the response. level1, level2, level3, level4, level5
pageNumberThe number of the pages of results to be returned.
pageSizeThe number of results (approval tasks) to be returned per page
sortOrderSort order of the results. Note: initial value for LAST_FETCHED_DATE is the creation date of the task. LAST_FETCHED_DATE is updated every time a task is returned to the client using the appropriate REST service. CREATION_DATE_ASC, CREATION_DATE_DESC, LAST_FETCHED_DATE_ASC, LAST_FETCHED_DATE_DESC

Response: Status: 200, with detail-level: level1 contains a minimal challenge (approval task)

Body:

{
"tasks": [
{
"detailLevel": "level1",
"id": "6947856a-e3a1-44cf-bb99-bbd2995642ca", # the id of the challenge
"approvalToBeSigned": "4AAAADsABAABAAAAAhASAFRTQl9UVVRPUklBTF8xLVJTQQAAVBBAADwAAABXEBYAQXBwcm92ZVNpZ25UYXNrUGF5bG9hZAAABwEIANcU814AAAAAAhANAHRpbWVzdGFtcC1rZXkAAABWEFkAMFcwDAYIKoZIzj0EAwIFAANHADBEAiADPniQDGELMUTqJCJ17kW3bUInXIf8dy9mwsseJ7voJAIgK3Kh4JjkR+RDugYKlp4x3M6UQIXkyQ5OuavkL0V5b5sAAABXEBYAQXBwcm92ZVNpZ25UYXNrUGF5bG9hZAAA"
# the challenge payload (challenge to be signed)
}
]
}
Response Parameters
ParameterDescription
idThe id of the challenge
approvalToBeSignedThe challenge (payload) to be signed with the approvers private key

Send Approval

If the human approver decides to allow using the SKA key for signing the given payload, their app uses their approver private key to sign the approvalToBeSigned. This signature represents the approval. The app then sends the signature to the TSB.

Demo Helper

Use this helper script to locally sign the the approvalToBeSigned, creating the request body for /v1/approval.

Run it with sh sign_rsa.sh approverName 6947856a-e3a1-44cf-bb99-bbd2995642ca 4AAAADsA....F5bG9hZAAA

POST /v1/approval

The snippet below shows an example request body. Make sure to replace the id, approvalToBeSigned, and signature values.

{
"id": "6947856a-e3a1-44cf-bb99-bbd2995642ca",
"approvalToBeSigned": "4AAAADsABAABAAAAAhASAFRTQl9UVVRPUklBTF8xLVJTQQAAVBBAADwAAABXEBYAQXBwcm92ZVNpZ25UYXNrUGF5bG9hZAAABwEIANcU814AAAAAAhANAHRpbWVzdGFtcC1rZXkAAABWEFkAMFcwDAYIKoZIzj0EAwIFAANHADBEAiADPniQDGELMUTqJCJ17kW3bUInXIf8dy9mwsseJ7voJAIgK3Kh4JjkR+RDugYKlp4x3M6UQIXkyQ5OuavkL0V5b5sAAABXEBYAQXBwcm92ZVNpZ25UYXNrUGF5bG9hZAAA",
"signature": "Mn/DQgm2yQbmFgcsEB+v3ACJgIbVo6IFSa7bDfMXmQXJZU21lVE0Bv46dTN6D4oWU/LYTuUYcIXmmRMChVgvRQvF254CctvDww99/ZUB+RrJ5LKE4t4gbHMgORntY/u3lM1CtmD5LwxONcB+3FwIyiODGPiDtfabgAucoGQ1X3Gdvn6KuESfFxtQfr3yn/FcMHBCGZDPPCIDDRaql3u9rI81emhyh7Oi1iXEypHAi9jzAUWRjnFCFtbOOs5MERN+54HxZF8wfY58aZLlHPF0GIhpC9+92NS7GRe0oO+gwlYX43NvewHwitTUMBE0ctd5xoNDkhuu8zMPTJJwiHqbmA==",
"approvalDigestAlgorithm": "SHA-256",
"approverCertificate":"MIIDAjCCAeoCCQCcSLgNCjDsRzANBgkqhkiG9w0BAQsFADBDMQswCQYDVQQGEwJDSDEPMA0GA1UECAwGWnVyaWNoMQ8wDQYDVQQHDAZadXJpY2gxEjAQBgNVBAoMCVNlY3Vyb3N5czAeFw0yMDA1MTExNDI5MDdaFw0yMTA1MTExNDI5MDdaMEMxCzAJBgNVBAYTAkNIMQ8wDQYDVQQIDAZadXJpY2gxDzANBgNVBAcMBlp1cmljaDESMBAGA1UECgwJU2VjdXJvc3lzMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEArA0bxSqhL7xfvcHbKKa8wMTMsIeJfYRdIgPxp5cU9JcmV86kyfpyRcSNSi44LVeNmAi94F3OZrXXi6CZvWrFL+VcewUtUSu+kG5oLJ9T4O6R2I5GO2Ev1HJnK3WfHOsFKFxLGzmKyjEkSLGgopY+Nh74K8Q6yxsvQPETOs9TzQiUXFYlfEZnbjUWG4eAgW9WWEopmK/X295ToOuTHFzmzO00btkjAy6vwWOabCE4kaJg+bCNW1snZz84uonr60rB9H0Mj98RbTfbDyMh6cIkaj8WrXeaYh4fxQYXApYu3nzhe3Q1bNCzV5M68rCsgVrmWcK/xUhM9BK6QHSwS/l76wIDAQABMA0GCSqGSIb3DQEBCwUAA4IBAQBNmg+gx2mH+fkU/dtM+tDvMIj2SY4pNU8H144aRY9I5kARN7Uwp+zRfJC+rCxrrYxXmx/OD+mIrTAHxPd5WuUWgULB6DXPho5Tyl4Czt6qOuzl7Qp7n1G9R/evZCPyEHflcGVEko/uCL5N8Ch9YboW5QwTrdftnL+zLLC5nON7KUCqbtVrDSdeMKF+dHKTX4Z90gdbv1C8x1fMWrsaoNw194DNBZCTVe4Di69xz3lHNEWVZ460mqKg0n5010VfEQqA92ceNJhjl4hgNMH9+asdBVAWmt0gk4PJUbqtuOKGKyxqi2k9QX8N2tjlsuMJmwRIw2YsZN4EKqQZ+0NAn1N7"
}
Request Parameters
ParameterDescription
idId of the task for which the approval is being submitted.
approvalToBeSignedThe approval token (base64 encoded) as received from the previous request or constructed by the client using additional data received in the task
signatureThe signature of the approvalToBeSigned (base64 encoded)

SIGNATURE=$(echo -n $APPROVAL_TO_BE_SIGNED | openssl enc -base64 -d -A | openssl dgst -sha256 -sign rsa-private-key.pem | openssl enc -base64 | tr -d '\n')
approvalDigestAlgorithmThe digest algorithm used for signing the approvalToBeSigned. The signature algorithm is given by the approver's private key. SHA-224, SHA-256, SHA-384, SHA-512, SHA3-224, SHA3-256, SHA3-384, SHA3-512
approverPublicKeyIf approver is public key based: The public key of the approver in the same format as provided during key creation (base64 encoded)
approverCertificateIf approver is certificate based: The certificate of the approver in the same format as provided during key creation (base64 encoded)

Response Status: 200

Once the TSB has received enough signed approvals, it forwards the signing request to the HSM. The HSM verifies the signatures, and verifies that they satisfy the SKA policy. If they do, the HSM signs the payload and returns the signature. The TSB then stores the signature.

Get the Signature

The business application can poll the TSB with the signRequestId that it obtained initially. This is the id property of this request.

Once the signature is ready, the status will switch from PENDING to EXECUTED, and the response will include the base64-encoded signature in the result field. Lastly, the TSB removes the signature from its cache.

GET: /v1/request/{id}

Response Status: 200

{
"id": "4e8731d8-0ae6-4444-8a8c-b73ab5f0ba18",
"status": "EXECUTED",
"executionTime": "2020-06-24T08:54:47Z",
"approvedBy": [
"MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEArA0bxSqhL7xfvcHbKKa8wMTMsIeJfYRdIgPxp5cU9JcmV86kyfpyRcSNSi44LVeNmAi94F3OZrXXi6CZvWrFL+VcewUtUSu+kG5oLJ9T4O6R2I5GO2Ev1HJnK3WfHOsFKFxLGzmKyjEkSLGgopY+Nh74K8Q6yxsvQPETOs9TzQiUXFYlfEZnbjUWG4eAgW9WWEopmK/X295ToOuTHFzmzO00btkjAy6vwWOabCE4kaJg+bCNW1snZz84uonr60rB9H0Mj98RbTfbDyMh6cIkaj8WrXeaYh4fxQYXApYu3nzhe3Q1bNCzV5M68rCsgVrmWcK/xUhM9BK6QHSwS/l76wIDAQAB"
],
"notYetApprovedBy": [],
"rejectedBy": [],
"result": "H3bq8PdgSiAlhB0kt1RSD6a3JYXZoj/dz3Nb/MHlgISnmh6x3TPtnV+9mUnw8PV2Ss1pq8txdMOBg9SF8uaKyUvFtLl/QFHIgllm/Q/uvrjaM205Cdz1uaSLePXaNXeC012l1sqlhnyqGKxKTKejMngzNHAnOpwU7kGCEpKPFWL5ltaBRYd3Q/I/F9IufAsKHj+3ky/p6tYN5VPhJSKiSE2YuVyOzGPHY40ipVo/7deBtUUjZmaZAgVQNC1mC79LOhIHLj8Ce4i41CbFZA+ZSMe+nx5bP/7uPA+kbGAjvNS3KLOFeZJ2OJCkTuThsXVh7rTp9tVqYqHU1LZm8f9bYA=="
}
Response Parameters
ParameterDescription
idId of the task for which the approval is being submitted.
statusThe current status of the request. PENDING, APPROVED, EXECUTED, FAILED, EXPIRED, REJECTED, CANCELLED
executionTimeDate and time when the request is sent to the hsm in ISO-8601 format.
approvedByPublic keys of approvers that have approved the request.
notYetApprovedByPublic keys of approvers that have not yet approved the request but still could approve.
rejectedByPublic keys from approvers that have rejected to approve the request (i.e. they deleted the task related to this request.
resultThe result of the request after the request was executed on the hsm. In case of a sign request this field contains the signature. In case of a decrypt request it contains the decrypted payload. Otherwise this field is empty.
Get started withCloudHSM for free.
Other questions?Ask Sales.
Feedback
Need help?