Overview

In our internet connected world, information is the currency that keeps everything moving. Unfortunately there is no easy way to authenticate most of the information that people furnish over the internet. Basic information such as someone's name, age or address cannot be easily authenticated without having an expensive back office operation in place.

Solution

In this document we describe a protocol and API implementation that provides a secure,scalable and inexpensive way to authenticate information on the internet. The API can be used to verify someone's personal information such as name,age or authenticate information such as academic transcript, or for that matter any digital information for which verification is required.

Information Trust Relay

The approach described is predicated on a simple observation; which is that while we cannot readily trust the information someone furnishes to us, there are usually other entities (business or otherwise) who have verified that information and as such have established trust for it. What if that established trust can be leveraged by everyone else who's ever presented that information? This observation forms the basis for the protocol and API solution described herein.

Information Trust Relay Protocol & API

At the core of this solution is a Trust Relay Protocol. This protocol uses modern cryptography and end-to-end encryption to guarantee that trusted information can be relayed in a manner that is secure, private and untampered with. The Trust Relay Protocol is modelled after the widely used internet Transport Layer Security (TLS) protocol, thus inheriting both the security and privacy features of TLS. Below is a diagram and detail description of the relevant components:

  • Furnisher

    The person/party who presents untrusted information. For instance a customer who presents a credit card number or student who comes in to admission with an academic transcript. In the language of federated identity brokerage, the furnisher is the principal.

  • Recipient

    The person/party who is presented with untrusted information by Furnisher. For instance an e-commerce site who receives a credit card number or a college who receives an academic transcript from a student. In the language of federated identity brokerage, the Recipient is the relying party or service provider.

  • Trust Anchor

    The party who can relay established trust for information presented by furnisher to a recipient. Trust anchors make our solution possible. A trust anchor is a party that the furnisher does business with. The range of entities that can serve as trust anchors is extensive, this can be a bank, an insurance company, an employer, a hospital, a university...etc. In the language of federated identity brokerage, the Trust Anchor is the attribute provider.

  • Cipheredtrust

    • Privacy Buffer

      A privacy buffer protects the privacy of the Furnisher while facilitating information exchange between the Recipient and the Trust Anchor. It may at first seem odd to consider privacy as a potential concern given that the Furnisher is volunteering information and willingly engaging these parties.

      Consider a scenario where the furnisher is using a healthcare provider to verify some bit of information. Maybe the information the furnisher wants to present is blood type, that by itself is innocous enough, now suppose the healthcare provider is a cancer treatment center or an HIV treatment center, it is likely that while the Furnisher wishes to share their blood type information, it does not follow that they wish to reveal other information about their health

      Consider a second scenario where the Furnisher uses their employer to verify their age. Maybe the Recipient is a medical (or recreational) marijuana dealer, it is likely the Furnisher does not wish to reveal that information to their employer regardless of the reason they're buying marijuana.

      With these two simple scenarios we can see that there is grounds for a Furnisher to want a buffer between the Recipient and Trust Anchor even while they wish to share information between the two parties.

    • Trust Bridge

      As the diagram illustrates above, there exists a Trust gap between the Furnisher, Receipient and Trust Anchor, our role is to bridge this gap. Our implementation of the relay protocol via our API is the manifestation of this bridge.

      We can see that there is a trust surplus on the side of the trust anchor and there is a trust deficit on the side of the recipient, we brige this divide.

How the protocol works

Below is an outline of the information trust relay protocol and the important steps involved:



What follows is a precise description of the information trust relay protocol. Each step corresponds to a step in the diagram above. An assumption here is that the furnisher has an account with an existing trust anchor.

  1. A furnisher presents information to recipient. This can take many forms, maybe during signing up for a service the furnisher puts in their name or enters a credit card where the recipient is the service provider (ex. social app, e-commerce app).
  2. The recipient generates a request object via the POST /requests API call.
  3. The API generates the request object and returns it to recipient. At this point the recipient would probably want to store elements of this request for further application flow processing.
  4. At this point the recipient would hand the token code to the furnisher of the information. This is also the point where recipient may need to educate furnisher about how to use the token, ie what are they expected to do with it.
  5. The furnisher logs into an account they have with a trust anchor, this could be their bank, insurance company ,university, healthcare provider...etc. Furnisher would present this token to trust anchor, probably through a self-service application interface, via phone, email or even in person.
  6. The trust anchor uses the token to retrieve the request object generated in step 1. via a GET /requests API call.
  7. The furnisher selects the information they wish to verify. This can be through a self-service application interface or via phone, email or even in person.
  8. Trust anchor would then encrypt and sign the selected information and post it via the POST /responses API call. This encrypted and cryptographically signed information is essentially a trust seal for the information presented by the furnisher.
  9. The furnisher may notify the recipient of the verification, this could also be an automated process where the recipient periodically checks the status of the request object. Also a callback webhook can be setup to notify recipient.
  10. Recipient would then retrieve the encrypted trust via GET /responses API call.
  11. Optionally the receipient would confirm that they've retrieved trust for the information presented in step 1, and hence can proceed with remaining application flow. Application for instance may have been a checkout application waiting for credit card ownership verification, so at this point a charge would be made against the card.

At its core, the trust relay protocol is a transport protocol that is primarily concerned with transporting/relaying trusted information in a manner that doesn't compromise the security or privacy of the user. It is possible for other protocols to be wrapped within this protocol, for instance it should be possible to wrap the OAuth and OpenID protocols with some caveats since those protocols have weaker privacy features.

REST API

The information trust relay protocol is implemented via a RESTful API that allows developers to easily integrate information verification into any application. The API and the protocol it implements is transparent and makes no assumptions about the logic of the applications that use it, this means developers can implement any workflow around it.

Methods

Request

A request represents an information verification request by a Recipient. This represents the first step in the information trust relay protocol.

Request object

ATTRIBUTES
token string

This represents a unique identitfier for this request. When not explicitly specified, it would be a hexidecimal code of length 64 representing a sha256 hash of the DiffieHellman public key material described below as the encryption_key property of this request. If the encryption_key property of this request is empty, then it would be set to a random alphanumeric code of length 16.

If this value is specified when creating a request via a POST /requests API call, a sha256 hash hexidecimal string is computed and used as the token identifier. In other words the actual value supplied in a POST /requests API call will never be stored, instead it is the sha256 hexidecimal string that will be used. Of course any subsequent GET /requests API call must use the sha256 hash.

This token should be given to Furnisher/User to relay to Trust Anchor.
recipient_public_key_fingerprint string This is a sha256 hash of the public key of the recipient who generated the request. This will be null in most cases to protect privacy of furnisher. In cases where it is not null, it will be a hexidecimal string.
payment_mode string This indicates who gets billed for the request, it can be Recipient or Trust Anchor or possibly Furnisher.
payment_status string This would be set to "paid" if someone has been billed for this request. It could also be null if payment has not been made or attempted.
expiration_timestamp string The is the expiration datetime set by the recipient for this request. Consider this the validity period for this request. A Trust Anchor may not want to process a request that has expired. The request may also be deleted after expiration. This must be a UTC timestamp, it will default to 24 hours if it isn't specified by recipient.
proposed_information_mime string The MIME type of the encrypted information, for instance application/json. This is important since it helps recipient automatically process the information after decrypting it. This should not be encrypted. As the name suggests, this is merely a proposal by the recipient about their preference, in other words the trust anchor might not honor it.
proposed_information_schema string This is mainly for JSON and XML data, a schema helps recipients automatically process the information after decrypting it. This should not be encrypted, unless the Trust anchor and recipient have agreed upon it independent of using the API. See section on data processing. As the name suggests, this is merely a proposal by the recipient about their preference, in other words the trust anchor might not honor it.
create_time string Datetime of when request was generated.
cipher_suites string optional

This is a comma seperated list of cipher suites. A recipient specifies their preference for cryptographic algorithms using the cipher suites. The order of listing indicates the recipient's order of preference with the first cipher suite being the most preferred. If a trust anchor can't support any of the suggested cipher suites, it should post an error without cipher data.

If nothing is specified, then the trust anchor should select a preferred cipher suite on our supported list and use it.

See details on Cipher suites.

encryption_key string

This should be the unencrypted public key material for deriving a shared secret via the DiffieHellman algorithm.

The DiffieHellman key exchange is necessary to provide privacy to furnishers by having no direct information linkage between the recipient and the trust anchor as is the case with RSA key exchange where the trust anchor would have the recipient's public key and could easily identify the actual entity.

See DiffieHellman parameters for detail.

The Trust Relay protocol and API do not support RSA key exchange but this can be an encrypted symmetric key, assuming the trust anchor and recipient have agreed upon this method independent of using the API.

It is also possible for this to be the per/user asymmetric (RSA/DSA) public key from the recipient. In such a use case the trust anchor would encrypt a symmetric key using this public key and the recipient can decrypt the key upon the posting of a response.

Trust Anchors should use the token property of this request to verify that this key is not fake. In other words to be sure a man-in-the-middle in the API is not replacing the original key from the Recipient with one that can be used to decrypt information posted to the API.

cipher_engine_specs string This specifies a comma seperated list of encryption/decryption logic supported by the recipient, see section on encryption/decryption for details on cipher engine specification. The items are listed in order of preference with the most preffered listed first. The default value is api and must be assumed if this value is not specified.
api_mode string

This indicates that the request is in live or test mode. test mode requests don't get billed. When not specified it defaults to live mode.

When in test mode, the recipient_public_key_fingerprint of the request for this post must be set and it must be the same as the key used to authenticate this post.

status string This indicates the status of the API call. It will be set to success if the call succeeds, otherwise the value is error. When there is error, there would be a error_message field with a textual description of error. See details of errors.
JSON

Create a Request

When a Recipient wants to receive trusted information, the first step is to generate a new Request.

Definition

Example Request


recipient_public_key_fingerprint should only be used if you are a trust anchor generating a request on behalf of a recipient. For instance an endpoint representing a doctor could generate an Rx request on behalf of a pharmacy without the Rx furnisher (aka patient) first prompting the pharmacy to do so. Many trust transmission use cases will in fact be initiated by the trust anchor. Of course the trust anchor would need a way to know ahead of time the public key fingerprint or verified domain of the recipient, recipients could simply publish that information so trust anchors can get it.

Constructing signature base string


For line 3 above, if a certain parameter is optional and you don't include it in the API call, then just omit it from the signature construction string. The string above on line 3 should be constructed with the unencoded key/value, in other words don't url-encode before forming the string. The Timestamp component in line 4 is the value passed as as the Timestamp header.

Note: Order of the parameters matters, they must remain in lexicographical order.

The authentication should be set with the following header:

Authorization: API Public key fingerprint:Signature

For detail on API authentication please see this section.

Example Response

Retrieve a Request

Retrieves the details of a generated request.

Definition

Example Request

Example Response

Constructing signature base string

Note that there are no parameters so line 3 is just a newline character. The Timestamp component in line 4 is the value passed as as the Timestamp header.

Delete a Request

Removes a request.

Definition

Example Request

Example Response

Constructing signature base string

Note that there are no parameters so line 3 is just a newline character. The Timestamp component in line 4 is the value passed as as the Timestamp header.

Response

A Response object is the information encrypted by a Trust Anchor and posted to our API for a Recipient to retrieve.

Response object

ATTRIBUTES
request_token string This is the request token for the request that initiated this post.
signature_string string The signature string that is signed by the trust anchor and verified by recipient to confirm that request came from a specific trust anchor. This is optional and can be used if the trust anchor and recipient agree to use RSA authentication independent of the API.
signature string Signature of signature string. When supplied, this should be base64 encoded.
encryption_key string

This is the unencrypted DiffieHellman public key derived from its counter part provided as part of the request. See DiffieHellman parameters for detail.

We don't support RSA key exchange but this can be an encrypted symmetric key, assuming the trust anchor and recipient have agreed upon this method independent of using the API.

When supplied, this should be base64 encoded.

ciphered_data string

Encrypted data. This is the trusted information that is being relayed to recipient. See section on Encrypting and Decrypting relayed trust for details on how this should be constructed.

When supplied, this should be base64 encoded.

cipher_engine_spec string This specifies the encryption/decryption logic used by the trust anchor, see section on encryption/decryption for details on cipher engine specification.

The default value is api. If a recipient specified a cipher_engine_specs value in the request and cipher_engine_spec is not specified then it must be assumed the trust anchor used the most preffered cipher_engine_spec from the list in cipher_engine_specs.

If a trust anchor cannot support any of the values specified in cipher_engine_specs then an error should be posted.

anonymized_identity_token string This is a HMAC-SHA-256 anonymous identity token. See section on Anonymized identities.
furnisher_public_key string

RSA/DSA public key of furnisher. The trust anchor should give (out-of-band) a SHA-256 hash of this key to the furnisher, which can then be relayed (out-of-band) to recipient so recipient can verify it is authentic. See section on Authenticated End Points for details.

When supplied, this should be base64 encoded.

expiration_timestamp string The is the expiration datetime set by the Trust Anchor, a recipient should consider expired response invalid. The object may also be deleted after the expiration datetime. This should be a UTC timestamp.
cipher_suite string required

The cipher suite used to encrypt and sign this trust request. This can either be a cipher suite selected from a list suggested by the recipient or it can be one choosen by the trust anchor in the absense of a suggestion. If the trust anchor doesn't support any of the suggested cipher suites from a recipient, the trust anchor should post an error and not choose an arbitraty cipher suite.

If nothing is specified (ie empty or null), then the recipient should assume the most preferred cipher suite on the request was selected.

See details on Cipher suites.

information_mime string The MIME type of the encrypted information, for instance application/json. This is important since it helps recipient automatically process the information after decrypting it. This should not be encrypted.
information_schema string

This is mainly for JSON and XML data, a schema helps recipients automatically process the information after decrypting it. This should also be encrypted. See section on data processing.

When supplied, this should be base64 encoded.

api_mode string

This indicates that the request is in live or test mode. test mode requests don't get billed. When not specified it defaults to live mode.

When in test mode, the recipient_public_key_fingerprint of the request for this post must be set and it must be the same as the key used to authenticate this post.

create_time string Datetime of when data was posted.
status string This indicates the status of the API call. It will be set to success if the call succeeds, otherwise the value is error. When there is error, there would be a error_message field with a textual description of error. See details of errors.
JSON

Create a Response

When a furnisher selects the information they wish to share from a Trust Anchor, it is encrypted and posted to the API as a Response object.

Definition

Example Request

Example Response

Constructing signature base string


When constructing the signature base string, the ciphered_data,furnisher_public_key and information_schema parameters are not the actual data but the sha256Hex hash of the data in lower case. The Timestamp component in line 4 is the value passed as as the Timestamp header.

Authenticating encryption

As discussed in the section covering cipher engine specifications, the recipient of the posted response needs to be able to decrypt it for the post to be useful. To ensure the post can be decrypted, the API requires an encrypted token that is encrypted using the cipher engine specification that both sides have agreed upon for this post. This is a way for the API to acertain that the trust anchor is using a correct implementation of the cipher engine specification for this post.

Each response post must authenticate it's encryption via the following procedure:

  • The trust anchor must use as a "secret" the signature used to authenticate this post.
  • The trust anchor must use as a "plaintext" the signature base string used to authenticate this post.
  • The trust anchor must produce an encrypted token using the process decribed in the Encrypt/Decrypt section.
  • The trust anchor must set a header Cipher-Engine-Spec-Auth containing the encrypted output.

If the API fails to decrypt and/or authenticate Cipher-Engine-Spec-Auth, an HTTP response code of 400 would be returned.

Cipher-Engine-Spec-Auth should be base64 encoded.


Retrieve a Response

Retrieves the details of a posted Response.

Definition

Example Request

Example Response

Constructing signature base string

The Timestamp component in line 4 is the value passed as as the Timestamp header.


Delete a Response

Removes a Response. This operation can be performed either by Trust Anchor or Recipient.

Definition

Example Request

Example Response

Constructing signature base string

The Timestamp component in line 4 is the value passed as as the Timestamp header.


Public Key

This is the public key associated with every API account. It is used mainly for API call authentication via signatures. It can also be used for asymmetric key encryption. An API account can have any number of API keys, for instance a large institution may have different application groups, each with their own API key.

Public Key object

ATTRIBUTES
fingerprint string A sha256 digest of the actual public.
key string The actual public key. This is base64 encoded.
cipher_suites string optional

This is a comma seperated list of cipher suites this API account supports, it will be used when none is specified for a request. This is a default that can be overriden per request .

See details on Cipher suites.

last_rotation_datetime string Datetime of when the key was last rotated. This should be done regularly.
domain string Domain name associated with key if one has be validated by the owner, otherwise null.
status string This indicates the status of the API call. It will be set to success if the call succeeds, otherwise the value is error. When there is error, there would be a error_message field with a textual description of error. See details of errors.
JSON

Create or rotate a Public Key

This is a key rotation operation. Whenever you rotate your keys, post a create operation.

Definition

Example Request

Example Response

Constructing signature base string

The Timestamp component in line 4 is the value passed as as the Timestamp header.


Retrieve a Public Key

Retrieves the details of a public key.

Definition

Example Request

Example Response

Constructing signature base string

The Timestamp component in line 4 is the value passed as as the Timestamp header.


Cipher Suites

Cipher suites dictate the type of encryption and signature verification for trust transmission.

Cipher suites should be specified using the standard format as outlined in the TLS Cipher Suite Registry

The following is the set of cipher suites we currently suggest/support:

[TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, TLS_DHE_RSA_WITH_AES_128_GCM_SHA256, TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256, TLS_DHE_RSA_WITH_AES_128_CBC_SHA256, TLS_DHE_RSA_WITH_AES_256_CBC_SHA256]
  

We currently only support SHA256withRSA for signing and verification, including API call authentication.

Retrieve Cipher Suites

These Cipher Suites will be updated occasionally, users should make an API call to retrieve the current values.

Definition

Example Request

Example Response

Diffie-Hellman Parameters

To use Diffie-Hellman key exchange, a set of parameters have to be agreed upon by both parties who need to arrive at a shared secret key. Below are the parameters for recipients and trust anchors to use and arrive at a shared secret.

      PKCS#3 DH Parameters: (2048 bit)
          prime:
            00:de:f8:aa:31:29:9e:e1:24:4e:ba:dc:76:9a:3b:
            43:e7:0d:75:71:dc:c6:4a:91:38:1b:9b:f8:54:6e:
            40:b8:b3:93:cb:f3:26:67:47:62:be:df:fd:f4:27:
            29:33:f6:80:51:53:3d:c0:8c:7a:08:14:d0:9d:66:
            55:f1:c9:9d:c7:58:bf:04:b3:8b:0f:1a:a0:aa:73:
            07:60:e9:b4:c2:21:55:b9:7f:aa:14:e5:b4:64:7d:
            4b:38:d8:41:07:66:7c:f7:67:9e:75:32:c8:1d:a8:
            21:f6:62:13:70:23:d6:ce:77:f9:d0:09:14:42:d7:
            50:b6:51:d6:d7:77:09:44:c1:9f:45:ef:73:73:66:
            20:4f:a5:52:2b:ec:1f:af:bd:c0:6e:bf:2d:10:e5:
            52:dd:a8:13:07:6e:bb:6e:46:2d:5f:af:ac:2d:56:
            b6:29:3b:6a:15:f2:ca:f6:c8:a8:3c:73:23:51:9a:
            9d:8c:4b:e5:30:7d:6a:0e:13:be:43:71:ff:4e:27:
            f8:b0:ff:e8:56:a9:52:0f:7d:7e:c8:9d:bc:f3:0e:
            47:f6:e5:58:1c:6c:71:77:6a:ba:a9:83:d8:34:2a:
            d5:45:97:90:34:57:e8:5f:cb:45:89:38:1f:c1:2b:
            25:c3:c8:84:9e:56:c1:38:4a:1c:4d:ef:99:97:75:
            3d:9b
          generator: 2
  

Diffie-Hellman Parameters (Elliptical Curve)

Below are the list of recommended elliptical curves when using this method. Recipients are free to use any of the the generally accepted curves.

  	[secp256r1, secp384r1, secp521r1];
  

Retrieve DHParams

These parameters will be rotated occasionally, users should make an API call to retrieve the current values.

Definition

Example Request

Example Response

Definition (Elliptical Curve)

Example Request

Example Response

API Public Key

This is the public key for the API itself, in cases where the API needs to call itself it uses this key. Also if there is a need to send encrypted infomation to the API, this key can be used. If the API needs to sign something, this key can be used to verify it. Specifcally, webhook calls should be verified with this key.

The public key for the API can be retrieved vai the API call below.

Definition

Example Request

Example Response

Note: Don't save this key, it will be rotated regularly.

API Authentication

For API calls that require authentication, basic HTTP authentication is used. Authentication is based on signature verification using the API public and private keys.

Signature base string construction

The purpose of a signature is to help the API verify that the request came from the owner of the API key (public key) and that the API call being processed has not been tampered with in transit. It is important to know that the tampering being discussed here is where someone intercepts your API call and attempts to modify an element, such as a parameter. Unless you use TLS with proper remote server verification, a man-in-the-middle attack can't be prevented with signature verification. Without TLS someone can intercept your API call and return a response of their choice to you.

The signature is a string concatenation of the following components:

  • HTTP METHOD: This can be either GET,POST, DELETE,PUT,PATCH. This should be terminated with the newline character \n.
  • API HOST: This is the full HTTP host url including the protocal scheme part. This should be one of the following: https://api.cipheredtrust.com, http://api.cipheredtrust.com. The port is assumed to be 80 or 443 (for TLS) and should not be explicitly specified. This should be terminated with the newline character \n.
  • CALL PARAMETERS: This is a lexicographically ordered list of name value pairs that represent the parameters for the API call. The exact names and corresponding values would depend on the particular API call. The format for concatenating this list is as follows: name1=value1&name2=value2..This string must be preceeded by ?. If a particular request parameter is absent,the equivalent signature representation is an empty string. If there are no call parameters, this should be omitted completely, including the proceeding ?.

    This string should be constructed with the unencoded key/value, in other words don't url-encode before forming the string.

    This should be terminated with the newline character \n.
  • CALL TIMESTAMP: This is the unix timestamp in UTC for when the API call was made from the client. It must be within 5 minutes of when the API attempts to verify the call.This must be passed as a request header Timestamp for the API call.

Concatenation is performed as follows:

HTTP METHOD+API HOST?+CALL PARAMETERS+CALL TIMESTAMP

Encrypt/Decrypt

In order for the trust anchor to encrypt information that the recipient can decrypt, both parties need to operate their cipher routines with the same settings. This section describes the ways the API facilitates successful encryption and decryption. In general the API models TLS and uses common default settings where applicable.

CBC Mode Cipher

  • block-size- 128-bit.
  • padding-mode- It should be PKCS #7 padding. TLS padding mode should be used, ie the last byte of the cipher text designates the padding length in bytes preceeded by the padding bytes, each with a value of the padding length.
  • iv-length- The byte length of the initialization vector used to encrypt the information. This should be 128-bits.
  • iv- Initialization vector. This should be prepended to the cipher text.
  • hmac-mode- The mode should be Encrypt-then-MAC (EtM) as described here and here.
  • hmac- HMAC-SHA256 hash of cipher text portion of ciphered_data. See section below on key derivation for the key that should be used for HMAC. The is 256-bit in length;
  • ciphered_data format: iv cipher text hmac.

GCM Mode Cipher

  • block-size- 128-bit.
  • padding-mode- Padding not required but if a library demands a padding value then supply PKCS #7 padding.
  • nonce-length- The byte length of the initialization vector used to encrypt the information. This should be 96-bits in length.
  • nonce- Initialization vector. This should be prepended to the cipher text.
  • associated-authentication-data- This is an empty string.
  • auth-tag-length- The byte length of the authentication tag to be used during decryption. This should be 128-bits.
  • auth-tag- The authentication tag to be used during decryption.
  • ciphered_data format: nonce cipher text auth-tag.

Key Size

The key size is determined by the cipher suite used, however 128-bit should be considered the preferred key length. See section covering supported list of cipher suites.

Key Derivation

HKDF must be used to derive keys. A PRF must be created and used to derive keys. For 128-bit keys the generated HKDF key should be split in half with the first 128 bits used for encryption/decryption and the second 128 bits used for HMAC in CBC mode. For GCM mode the second half of 128 bits should be discarded.

Cipher Engine Specification

All elements of the API together should be sufficient for implementors to construct correct encryption and decryption routines,however, cryptography is complicated. To prevent situations where it is possible for either ends to correctly implement crypto routines that are however incompatible (even in small ways), the API requires precise specifications of the actual software logic that should be used for both encryption and decryption.

A simple example of implementation detail incompatibility stems from the implementation of the HMAC key derivation function. While minor deviations in implementation might not compromise the cryptographic properties of the derived keys, keys derived from such implementations will differ even when derived from the same shared secret.

Precise crypto routine specifications will ensure the software logic used by both ends of the API are compatible. The specifications will be in the form of source code (Java only for now) that can then be implemented in any language. The default spec is named api.

Retrieving engine specs

Example Response

Authenticating cipher engine specs

The API will authenticate cipher engine implementations used for API posts by decrypting a timestamped encrypted token supplied by the trust anchor against the API maintained implementation of the cipher engine spec. This ensures trust anchors are properly implementing cipher engine specs.

The default cipher engine spec named api can be found here.

Attribute Assertion Certification.

Note: This section is merely a set of ideas for future development that isn't yet integrated into the API.

At the moment the way the API certifies trust is to limit trust anchor status to only certain entities deemed to have credible systems in place for protecting the integrity of information they possess. We ask trust anchors to confirm that the information they relay is stored in a way that users cannot unduely tamper with it and also that some due deligence was done before the information was accepted into their system. For instance an employer that allows an employee to change their date of birth without any proofing cannot relay DOB information because the information cannot be considered trust worthy.

At scale however, what constitutes a valid trust anchor requires a more robust notion of a trusted entity with the right to assert a given attribute. In other words trust anchors are attribute providers and in many context there is going to be regulation around who can provide/assert which attribute. For higher levels of attribute assertion certification/assurance, there would need to be an auditing party that certifies that a given trust anchor is authorized to assert a given set of attributes.

Attribute Assertion Certificate.

This is a certificate sent to recipients to assure them that the attributes they're receiving came from an authentic trust anchor who's been certified to assert the attributes. For instances an employer can assert annual income attribute and can issue a certificate for such an assertion.

Attribute Assertion Certificate Authority.

This is an entity that certifies that a given trust anchor has the right to assert a set of attributes. This entity would also provide an authenticated interface that trust anchors can use to dynamically generate and sign assertion certificates.

The general process for facilitating a robust attribute assertion assurance would involve the following steps:

  • To preserve furnisher privacy, a new asymmetric key pair should be generated for each request. Ideally asymmetric key pairs should never be reused between requests, however due to computational concerns this requirement could be relaxed in various ways while still ensuring a high degree of furnisher privacy.
  • Send the public key along with the set of attributes to be asserted to an Attribute Assertion Certificate Authority via an authenticated and secure interface.
  • Attribute Assertion Certificate Authority should confirm that the attributes for which they are being asked to issue a certificate are included in the set of attributes for which they have certified the given trust anchor.
  • Attribute Assertion Certificate Authority should then generate and sign an x.509 certificate that includes the set of attributes being asserted. This certificate should identify the issuer so recipients can verify the certificate. The validity period for such a certificate must be very short to prevent abusive reuse.
  • The trust anchor should include this certificate as part of the encrypted information they relay. The exact format for how this information should be included is still open to discussion. It may be that it can just be included as a field in a JSON/XML object, for ex attribute_assertion_certificate.
  • The recipient should first verify the certificate,ie verify that it was issued by the specified issuer and the issuer is legitimate. The full list of Attribute Assertion Certificate Authorities would be publically published.

The approach outlined above is a much more robust technical approach. It should be possible to accomplish the same goal by simply have an Attribute Assertion Certificate Authority sign a comma seperated list of attributes along with the current UTC timestamp. This signature can then be relayed along with the identifier of the Attribute Assertion Certificate Authority that generated it.

Error Conditions

Below are the error conditions you can expect from the use of various API calls. The core API methods have a status field. The value of status will be success when the operation completes as expected. In the case of error, the status field would contain error and the response would contain an additional field error_message with one of the textual description below as its value.

Errors

HTTP Response Code Message - error_message API Calls Description
401 Signature verification failed, due to stale timestamp All Core API calls. This would happen if the signature fails timestamp verification. Timestamps older than 5 minutes during verification will fail with this error.
401 Public key signature verification failed. All Core API calls. This error would occur if the signature of the API call cannot be verified with the client's RSA public key. It is assumed that all authenticated API calls are signed with an RSA private key and on the API side it will be verified with the corresponding public key.
401 Not a valid Trust Anchor. POST /responses This error would occur if a POST /responses API call is made by a client that is not a trust anchor.
401 Service denied due to lack of payment. GET /responses This error would occur if a billing error occurs. Specifically, if a GET /responses API call is made and the trust anchor had not been billed during the corresponding POST /responses API call, then you'll get this error.
401 Service denied due to account status. GET /responses This error would occur if the API account is not in good standing during a GET /responses API call. Basically if payment has previously failed and there is a pending balance on the account. This would only occur if the trust anchor who posted the transaction has not already been billed for it.
401 Request denied due to overage. GET /responses This error would occur if the API account is over plan limit during a GET /responses API call. This means the API account doesn't have provision for handling overage. This would only occur if the trust anchor who posted the transaction has not already been billed for it.
404 Request not found. GET /requests
GET /responses
This error would occur if a GET /requests API call is made for a request that doesn't exist.
404 No ciphered trust found. GET /responses This error would occur if a GET /responses API call is made for a Response that doesn't exist.
404 None existent key. GET /publickeys This error would occur if a GET /publickeys API call is made for a publickey that doesn't exist.
400 Unsupported Operation. Any This error would occur if an API call is unrecognized, this includes using unsupported HTTP methods.

Trust Anchor Accounts

Trust anchors are key to the trust relay protocol, they are the holders of trusted information. Only trust anchor accounts can do a POST /responses request. If you already have an API account, becoming a trust anchor is quite simple.

Domain validation

Domain validation is a way to prove that you have sufficient access to an organization's infrastructure in order for an account to be considered a trust anchor. Domain validation requires proving that the API account owner/creator does not only have access but programmatic access to an organization's infrastruture. These are key points to consider for domain validation:

  1. Validated domains are tied to API keys. Every API key created by the API account owner can have a domain associated with it and the domain must be validated at the time of addition of the key. The API console provides the UI for doing this when you login to your API account. Note that domain association is optional for most API keys.

  2. The host portion of the validation url is the domain that'll be validated. In other words a validation url that looks like https://mortgage.bankofworld.com/validate would validate only mortgage.bankofworld.com not the bankofworld.com top domain.

  3. The validation url must be a programmatic end-point, meaning it must sign the validation url along with a validation code that would be added as a query string parameter by the API validation logic. The returned result from doing a GET request to the url should be the signature of the validation url. This url should be signed by the corresponding API private key and would be verified with the public key. Specifically, suppose you want to validate mortgage.bankofworld.com using the validation url https://mortage.bankofworld.com/validate, the string that must be signed would be:

    https://mortgage.bankofworld.com/validate?verificationCode=.... The query string parameter would be added before calling the validation url and can be retrieved to construct the signature string.

Trust anchor validation

  1. Send an email to apisupport@cipheredtrust.com, it should include the fingerprint of the API key that has been domain validated and an email address at the organization (ex. developer_bob@bankofworld.com) that a verification code should be sent to.

  2. Once we verify domain validation, we'll send an email to the email address in step 1 containing a verification code.

  3. Login to your API account (under Account Information), enter the verification code to activate your Trust anchor status.

Note: not everyone can be a trust anchor, only organizations that we deem reputable would be approved as trust anchors.

Trust anchor accounts are required to rotate thier API keys regularly and the accounts would also be audited occasionally to ensure they are associated with specified organization. Basically the steps above would need to be repeated during an audit.

Webhooks

The API supports webhooks for event callback. You can configure webhooks on your account settings for both test and live modes. All webhook calls are signed with the API's private key so the receiving endpoints can verify using the API public key.

The following events are currently supported.

  • ciphereddata_created

    This event is invoked when a POST /responses call is made. The recipient receives the callback.

    event object

    ATTRIBUTES
    event_id string The unique id of the event.
    event_name string The name of the event
    request_token string The request token, use this to retrieve the actual response.
    post_time integer The time the POST /responses call was made.
    retry_count integer The number of times the event webhook would be invoked due to failure before it is abandoned.
    JSON

    The event object is the POST body of the http request that calls the webhook.

Authentication

Webhooks should authenticate events before processing them. Webhooks calls are made with an authorization header similar to what is provided with API calls. Authorization: API Public key fingerprint:Signature

Constructing signature base string

The webhook call is signed using the following signature string:

Webhook in line 2 above is the callback url for the event. The Timestamp component in line 4 is the value passed as the Timestamp header.

If any of the values in line 3 is null in the event object JSON, it must be omitted from the signature string.

Note: Order of the parameters matters, they must remain in lexicographical order.

Data Processing Automation

Once trust has been transmitted, it needs to be processed. In other words if a user verifies their age by encrypting and posting a number, how can the recipient be sure that the value in fact represents an age and how can this determination be made without additional human intervention?

To facilitate automated processing of relayed trust, data needs to be encoded in a manner that can support automated processing, to that end JSON and XML are the two formats supported/recommended for encrypted trust. While the recipient is expected to support either data formats, JSON is highly recommended for all requests unless there is a good reason to use XML.

JSON/XML Schema

When information is posted as a JSON object or XML, it should also be accompanied by a schema that describes the object to facilitate automated processing. The schema should be specified in the POST /responses API call.

In general the recipient would traverse the given schema and retrieve corresponding properties. In most cases it would make sense for the trust anchor to simply provide all data elements in a flat object without creating a complicated object structure in an attempt to maintain any sort of data association relationship.

The schema for the encrypted information should be encrypted and submitted when making a POST /responses API call.

Data Dictionary

While JSON or XML allows for automated processing of the data, the recipient still needs to be able to automatically determine what exactly a particular data element represents. In other words the trust anchor needs to be able to communicate to the recipient the actual meaning of a particular JSON object property or XML element/attribute. We provide a data dictionary API to help with determining the meaning of information.

Data Dictionary Domains

Data elements can be thought of as belonging to various domains/categories, domains generally represent industries,subject matter or object categories. Every data element belongs to a domain, people's name for instance belong to the personal domain, where as RX dose may belong to the healthcare domain. Because general information taxonomy is messy, there are no rules for how information attributes should be mapped to categories.

We maintain a personal data dictionary meant to help recipients automate the processing of information for a wide class of data elements such as personal information attributes (ex. name, age, dob...etc). What this means is that if a data element is annotated by a trust anchor as an item in the dictionary, then the recipient's processing software knows exactly what the data element represents and can process accordingly. For instance an annotation of birth_date, means the the data element represents a birth date without a person having to look at it to verify.

Data Dictionary API

There is an API to retrieve the data dictionary. Simply use the fully qualified path for a particulary dictionary domain or sub-domain.

Definition


${DICTIONARY-PATH} is the fully qualified path for a particular dictionary. Dictionaries can be nested in a hierarchical order as sub-domains starting from a particular domain.

Example Request to retrieve whole dictionary

Response

Example Request for a specific domain dictionary

Response

Annotating Data Elements

When constructing a schema for a given request, the trust anchor should annotate each data element that we have an annotation for in the data dictionary. For instance if a json property in the posted data represents a social security number then it should be annotated with https://api.cipheredtrust.com/v1/data-dictionary/personal.social_security_number, or a BMI value can be annotated with https://api.cipheredtrust.com/v1/data-dictionary/healthcare.bmi.


The dictionary annotation URL should be the first part of the description field in the schema. XML does not have a description attribute by default on the element element/tag, it should be added if XML schema is used.

Crowd Sourcing Data Dictionary

Ultimately, defining a comprehensive data dictionary that meets most needs is going to require an open process of making proposals/suggestions for an entry, developing consensus for the entry and its meaning and adding it to the API. We have created an online forum for building the data dictionary.

Authenticated End Points

The trust relay protocol does not (and cannot) provide for end-point authentication as is possible with TLS. In other words the API cannot prove to the recipient of cipheredtrust posts that the encrypted information has not been altered, for instance that bits have not been removed from a ciphertext, the API is a man-in-the-middle (a trusted one). The overall risk of this limitation to the integrity of the API is vanishingly small.

It is however entirely possible to have anonymous end-point authentication if a trust anchor maintains a per user asymmetric cryptographic key pair. A trust anchor can generate cryptographic (RSA, DSA) key pairs for their users and the user can use the public key to facilitate endpoint authentication and other symmetric-key cryptography functions over the trust relay protocol.

For instance a user (ie furnisher) could give a recipient their public key for a certain trust anchor to be used for encrypting a secret key that the trust anchor can then use for encrypting information to be posted to the API. Of course the resulting cipheredtrust post can also be signed to prevent undetected tampering.

The main point to note is that maintaining and transmitting public keys happens out-of-band, ie the API does not facilitate direct support for such use cases.

Anonymized Identities

While the trust relay protocol solves the problem of information authentication on the internet, a central point of tension on the internet is between the need of users to maintain their privacy through anonymity and the need of service providers to effectively prevent abuse of their services.

Sticky Anonymized Identities

Anonymized identities solve this problem by enabling service providers to establish sticky identities for their users without the users losing their anonymity. A sticky identity is one that is sticky for a given service provider, meaning it will be difficult or impossible for a user to simply create a new account by using a new email address.

User Tracking

Anonymized identities don't leak information about the user, this means a service provider would not be able to identify a user by linking them to some other anonymized identity. For instance if you establish an anonymized identity on Twitter and Facebook, neither service is able to deduce your true identity purely from the anonymized identity tokens they hold for you, even if each knows both tokens.

This feature prevents user tracking on the internet via anonymized identity tokens alone. Of course if a user reveals additional information about themselves via the use of a service then their true identity could be established through other means. Also service providers could use a user's IP address to establish tracking between services.

Constructing An Anonymized Id

Anonymized identities are represented as a HMAC-SHA-256 hash of a private user identity anchor, a recipient domain, a trust anchor domain.

This hash is produced via:

HMAC-SHA-256( recipient_domain+ HMAC-SHA-256( trust_anchor_domain+private_id_hash)).

The private_id_hash is the part of the anonymized_identity_token property of the response supplied by the trust anchor and should be constructed as:

HMAC-SHA-256(private_id)

The hash components are described below:

  • private_id: This is any immutable unique id token, for instance a social security number or any trust anchor maintained unique user id.
  • recipient_domain: This is the validated domain associated with the recipient of the identity, it will be extracted from their API public key.
  • trust_anchor_domain: This is the validated domain associated with the Trust anchor posting the identity, it will be extracted from their API public key.

Note that the combination of components that are used to produce an anonymized identity token establishes a one-to-one mapping between a trust anchor and a recipient for a given anonymized identity.

In other words a furnisher can have as many anonymized identities as the number of trust anchors they have access to for any given recipient. This should not be a problem however since most furnishers are going to have access only to a limited number of trust anchors.

API Browser Extensions

To jumpstart the use of the API while we accumulate trust anchor integrations, we have implemented browser extentions for certain trust anchors. A browser (chrome/firefox) extension is a bit of code that runs in a users browser to provide additional functionality. In our case the extensions we have developed are simply client proxies. They allow us to intercept certain URLs and reroute the browser requests through the API to provide trust anchor functionality.

API browser extension for the Internal Revenue Service(IRS)

Install (Chrome)

We currently have browser extensions for the Internal Revenue Service (IRS). With this extension installed, a user (furnisher) can login to the IRS Get Transcript ONLINE service and use it to verify identity, income, marital status, name, address, social security number.

With the IRS browser extension, the API will connect to the IRS and retrieve tax information and then allow the user to select the bits of information they wish to share with a recipient. The information will be encrypted and posted to the API. The API does not save or log any of the information from a users transcript.

With the API extension for IRS installed:

  • A user (furnisher) should login to the Get Transcript ONLINE service.
  • Select Record of Account Transcript for any year they wish to share information from.

Note that if IRS implements the API then there would be no need for this extension, we are providing that functionality for now.

More extensions are in development.

Certisfy Overview

Certisfy is a consumer facing PKI based alternative to the Trust Relay Protocol/API. With Certisfy, users can leverage PKI mechanics to facilitate trust on the internet at scale and inexpensively.

Certisfy's implementation is driven by a web app (https://certisfy.com) and the API below.

Certisfy REST API

This is simple API to support the few operations that service providers need to perform when verifying certificates.

Certificate

An x.509 certificate that serves as a cryptograhic container for trusted information. Certisfy repurposes certain elements of the x.509 certificate format.

The SAN field is used to store a JSON encoded payload that is the information that has been verified. The payload itself is a set of name/value pairs. Service providers will request certified information based on their service needs.

This payload information can be either masked or unmasked. See the signature section for details on verification of payload information.

The Issuer Common Name field will contain the issuer sha-1 finger print.

Certificate object

ATTRIBUTES
finger_print string

A sha256 hash hexidecimal string is computed from PEM text that serves as identifier for the certificate.

cert_text string Base64 encoded PEM file.
create_time string Datetime of when certificate was generated.
JSON

Retrieve a Certificate

Retrieves the details of a Certisfy certificate.

Definition

Example Request

Example Response

Signature

This represents the signature object generated by Certisfy app.

Signature object

ATTRIBUTES
signedString string

This is a JSON string with timestamp appended to it. The string contains name/value pairs representing the signed document.

The timestamp represents moment of signature generation, it should be used to validate expiration of signature per service provider requirements.

signedString.plainFields array

This represents the plain unmasked version of the signed JSON document. It is a list of name/value pairs.

signedString.maskedFields array

This represents the masked version of the signed JSON document. It is a list of name/value pairs with an additional hmacKey field. The hmacKey should be used as part of an extended validation of the signature.

When there are masked fields, verifiers should also confirm that each of the plain fields have a match in the list of masked fields.

signerID string This is the certificate finger print of the signer, use it to fetch the certificate for verification.
signature string This is SHA256 signature of the signedString. It should be verified before acceptance.
certisfy-identity object This is the service provider identity of the signer, see details here.
debug_verified string When true, this field means that the signature was tested and successfully verified at the time it was generated.
JSON

Signature Verification object

Certisfy signatures can be verified without using the API. For service providers who don't wish to implement their own verification, this object represents the verification returned from the Certisfy /pki/verify API endpoint.

ATTRIBUTES
signedString string This is the same as the field in the signature object.
signerID string This is the same as the field in the signature object.
signature string This is the same as the field in the signature object.
signatureVerified boolean This is set to true if signature field is successfully verified.
certisfyIdentityVerified boolean This would be present if there was a certisfy-identity field in the signature object. This would be set to true if verification succeeded, false otherwise.
fieldVerification.fields array

This contains fields included in the signature object and each with their verification status.

This is more of a debug helper for verification failures.

fieldVerification.maskVerified boolean

This would only be present if the document verified was masked. When this is present, it would be set to true for successful mask verification and false otherwise. Verification involves checking the hmac of the plain field value against the provided masked fields.

If this field is not present and there are masked fields in signature then assume successful verification.

This is more of a debug helper for verification failures.

certificateVerified boolean

This is set to true if the fields in the signature were successfully verified against the certificate, false otherwise. The would also check masked fields and hmac them to compare against certification.

certChainVerification object

This would contain certificate chain verification result.

See certificate object format for detail.

certChainVerification.certificateVerified boolean

When set to true, it means the certificate chain was successfully verified.

See certificate object format for detail.

certChainVerification.chain array

When present, it means the certificate chain was successfully verified and this would contain the chain of certificate objects with the most immediate issuer listed first.

See certificate object format for detail.

timestamp string

This is the timestamp extracted from the signature

JSON

Verify Signature

Verify a certisfy generated signature.

Definition

Example Request

Example Response

Certificate Trust Anchors

There are certain certificates that serve as trust anchors and can be used to delegate trust as well as sign other intermediate trust delegation certificates.

A good example of such a certificate is one issued to a police department. Such a certificate would further delegate trust to individual officer certificates, which can then be used to issue certificates to ordinary citizens.

Certisfy can sign such trust anchor certificates after sufficient due diligence has been performed. The Certisfy root that would be used to sign trust anchor certificates can be accessed via the following endpoint.

Request

Response


Below is the payload format of a trust anchor certificate.

  • name

    Name of trust anchor.

  • website

    Appropriate website of trust anchor. This should be a page that provides useful information.

  • address

    One line physical address

  • geo-code

    Geo code of physical address

  • labor-code

    Associated labor code. The idea here is to be able use the labor code to determine what the nature of the trust anchor entity is and make verification decisions based on that. Governments have a bunch of such codes, we are working on ways to make them easy to use by service providers.

  • maximum-delegates

    The maximum-delegates states how many levels of trustworthiness delegation this trust anchor can have along any given chain that decends directly from the trust anchor. This would be based on the organizational structure of the the trust anchor. For instance a police department has a hierarchy that can be used to determine how many levels of delegation is valid.

    When this value is present on a trust anchor certificate, it means the issued certificates along any given chain that decends directly from the trust anchor and up to the maximum-delegates could be delegates that can themselve issue trustworthy certificates. These can only be directly linked certificates with the field certisfy-trust-anchor-delegate set to true. In other words an unbroken chain of certificates all with the field certisfy-trust-anchor-delegate set to true, up to maximum-delegates.

    Any gap in the chain between the trust anchor and an issuer without the certisfy-trust-anchor-delegate set to true should be considered invalid from the point of the first gap onwards.

    Note that the delegation limit applies only to "vertical" chains, there is no limit to the number of lateral certificates that can be issued, both with and without delegation.

Identity Anchor Certificates

Certisfy allows users to create anonymous identity anchor certificates. The anonymous identities have similar characteristics as described here.

The elements that currently can be used to anchor user identities can be found at this url:

As more suitable elements are discovered they'll be added.

Service Provider Anonymous Identity

The only way to leverage an identity anchor certificate is to have a user generate a service specific anonymous identity signature from it. When a user signs information from a certificate, they can choose to include a service provider specific anonymous identity token using an identity anchor certificate.

The service provider specific anonymous identity token is issued by an identity anchor certificate, ie a certificate that contains one of the identity anchor elements.

The token is enclosed in the certisfy-identity field of the signature object. This service provider specific anonymous certisfy-identity has the following format:

  • certisfy-sp-identifier

    This is the service identifier (a url for instance) given to a user to identify a service provider. During verification, service providers should confirm this value to acertain that the identity is for their service.

  • certisfy-id-anchor-element

    This is the identity anchor element whose value the certisfy-sp-id-anchor-token is anchored to. See details here.

  • certisfy-sp-id-anchor-token

    This is the anonymous identity token generated via the following hash computation:

    HMAC-SHA-256( certisfy-sp-identifier+ HMAC-SHA-256( certisfy-id-anchor-element-value)).

    The certisfy-id-anchor-element-value is the value of one of the identity anchor elements.

    This token value will remain unchanged for a given service url and a given identity anchor element value combination, regardless of how many individual identity anchor certificates a user provisions for that same identity anchor element value.

  • certisfy-cosignature

    This is the signature that links the enclosing signature object and the certisfy-sp-id-anchor-token signed via the Certisfy root key. Use the Certify root public key to verify it.

    This signature is generated by signing the following construction string:

    certisfy-id-anchor-element + certisfy-sp-id-anchor-token + certisfy-sp-identifier + signature.

    Service providers should verify this signature after verifying the enclosing signature object. Failure to perform this verification means a user could simply be misusing a certificate and doesn't actually own it.

Identity Anchor Certificate Linking

Certisfy doesn't provide any direct linkage to the identity anchor certificate, this protects users privacy and allows users to use the same identity anchor certificate across different services.

Copyright Cipheredtrust, All rights reserved.