The Gateway Protocol

    #Introduction

    The ZOLOZ service is provided in the form of a collection of WEB APIs which are exposed by our gateway service. The gateway is the key facility for data exchange between the customers and the ZOLOZ service.


    In this document, we introduce the gateway protocol, a set of rules that enables the interaction between the customer and the ZOLOZ service with robustness, reliability and security.


    Topics

    • Message Format
    • Transmission Security
    • Compatibility


    #Message Format

    The request and response of the APIs are carried by HTTP with particular format.

    #Request Message

    image.png

    #Request URL

    The format of the request URL is https://{host}/api/v{majorVersion}/{path} , in which

    • host is the domain of ZOLOZ service;
    • majorVersion is the major version of the interface, typically a positive integer;
    • path is the path of the interface.


    #Request Method

    The ONLY accepted request method is POST .


    #Request Header

    The request header contains information about the client, signature and encryption.


    #Request-Time (Mandatory)

    The request time in rfc3339 format datetime + rfc822 format timezone, e.g., 2019-04-04T12:08:56+0530.

    if you are using java, the date format is yyyy-MM-dd'T'HH:mm:ssZ

    if you are using PHP, the date format is Y-m-d\TH:i:sO


    #Content-Type (Mandatory)

    The media type of the request body sent to the recipient (see rfc2616 for more information). Only two content types is supported:

    • application/json; charset=UTF-8 : accepted when the request is not encrypted.
    • text/plain; charset=UTF-8 : accepted when the request is encrypted.


    #Client-Id (Mandatory)

    The client identifier assigned to the customer, it's guaranteed to be unique for each customer. Typically it's a string composing of 16 digits.


    #Signature (Mandatory)

    The information about the signature of the message, the header value is composed of following 2 key-value pairs, joined with comma:

    • algorithm : indicate the algorithm used for signing, only RSA256 is accepted.
    • signature : base64 encoded string of the signature content.


    Here's a sample header entry:

    copy
    signature: algorithm=RSA256, signature=IpmAgtDqkjOz5sEEVlEq8OkdShXMJyXaK+6gtX/idB3+Hlhqnzdf90redIiJkawUlrY+icf1NhzSISiULGIAih72y/QRg/LlyWIWRE+GHx+k7Wl1wEYazvXRDQWF2TIia7SyyIhtjqIXj4BZ+409X72SOnx21qOU5eKxkgJQ8ZEVg5BFzXe0E//ISxJURBkVC1Q8v+7mnuT+YzgKvD1aMo16sYZih9ueTlj4xDPC8nKEoT+WJGjbdV7Ww/PXP419bGii9e7agLdxudGjD2B9d/IeUj8/w75u6V7PtdS8jCpyZQ0a28PcpvMD7yQ5f0odh7/6xGL6jECx3Y2YiuYCkw==


    Refer to Signature and Validation section for more information.


    #Encrypt (Optional)

    The information about the encryption of the message, the header value is composed of following 3 key-value pairs, joined with comma:

    • algorithm : indicate the algorithm used for signing, only RSA_AES is accepted.
    • symmetricKey : base64 encoded string of the AES key encrypted with RSA.


    Here's a sample header entry:

    copy
    encrypt: algorithm=RSA, symmetricKey=FxE+siNhE2eQsnbui/6llu6TG9CaXFmT8gb2Z5bsvf2WGlAnoXoBrcB1bYodBnRs/CzSeEewFc4HOIqHejTepHehy86M9DUdefjYC783+LGBstQTPlLGsqcsYxPJTMCGYfTD6DSSXwqtKSiqD6q6C96zkp3/Q2ScmCAJprqtcA5SUj+cRmIdtG1OStSdHrQ+SstT74pwMbv1qlHbTeitZMTt5GNFXnhT1B3htS1sFb0BQ2OA+V2BtPW/izEP5ebrkfNQWmQKd6gc/i0j/DGBw4DQaxNfNvy2JHAljL5mP/ES9X0DJS6/MkimfDwXsSsTANWsjFfIoTodRn223HQC0w==


    Refer to Encryption and Decryption section for more information.


    #Request Body

    The request body is the content of the request message, contains the input parameters of the API. Refer to API specifications for more information about the content structure. The encoding of the content is different for non-encrypted request and encrypted request:

    • for non-encrypted request, the content is a JSON string;
    • for encrypted request, the content is the base64 encoded string of the encrypted data.


    #Full HTTP Request Samples

    #Non-encrypted request sample

    copy
    POST https://sg-production-api.zoloz.com/api/v1/zoloz/authentication/test HTTP/1.1
    Content-Type: application/json; charset=UTF-8
    Client-Id: 2089012345678900
    Request-Time: 2020-01-01T12:00:00+08:00
    Signature: algorithm=RSA256, signature=KEhXthj4bJ801Hqw8kaLvEKc0Rii8KsNUazw7kZgjxyGSPuOZ48058UVJUkkR21iD9JkHBGRrWiHPae8ZRPuBagh2H3qu7fxY5GxVDWayJUhUYkr9m
    
    {
      "title": "hello",
      "description": "just for demonstration."
    }


    With cURL we could send the sample request like this:

    copy
    curl -X POST                                         \
    -H 'Content-Type: application/json; charset=UTF-8'   \
    -H 'Client-Id: 2089123456789012'                     \
    -H 'Request-Time: 2019-04-04T12:08:56+05:30'         \
    -H 'Signature: algorithm=RSA256, signature=KEhXthj4bJ801Hqw8kaLvEKc0Rii8KsNUazw7kZgjxyGSPuOZ48058UVJUkkR21iD9JkHBGRrWiHPae8ZRPuBagh2H3qu7fxY5GxVDWayJUhUYkr9m' \
    -d '{
      "title": "hello",
      "description": "just for demonstration."
    }' https://sg-production-api.zoloz.com/api/v1/zoloz/authTest


    #Encrypted request sample

    copy
    POST https://sg-production-api.zoloz.com/api/v1/zoloz/authentication/test HTTP/1.1
    Content-Type: text/plain; charset=UTF-8
    Client-Id: 2089012345678900
    Request-Time: 2020-01-01T12:00:00+08:00
    Signature: algorithm=RSA256, signature=KEhXthj4bJ801Hqw8kaLvEKc0Rii8KsNUazw7kZgjxyGSPuOZ48058UVJUkkR21iD9JkHBGRrWiHPae8ZRPuBagh2H3qu7fxY5GxVDWayJUhUYkr9m
    Encrypt: algorithm=RSA_AES, symmetricKey=FxE+siNhE2eQsnbui/6llu6TG9CaXFmT8gb2Z5bsvf2WGlAnoXoBrcB1bYodBnRs/CzSeEewFc4HOIqHejTepHehy86M9DUdefjYC783+LGBstQTPlLGsqcsYxPJTMCGYfTD6DSSXwqtKSiqD6q6C96zkp3/Q2ScmCAJprqtcA5SUj+cRmIdtG1OStSdHrQ+SstT74pwMbv1qlHbTeitZMTt5GNFXnhT1B3htS1sFb0BQ2OA+V2BtPW/izEP5ebrkfNQWmQKd6gc/i0j/DGBw4DQaxNfNvy2JHAljL5mP/ES9X0DJS6/MkimfDwXsSsTANWsjFfIoTodRn223HQC0w==
    
    r8w8wbc8Nv6sC2meJzArtGjDkbiAzg55UaDiq7TId1a7uzcv18qpOxVkXvqa3q/6TPemDDItZ79oHMzDJyvAngYqfpZZaedArWPCDeddqUl62zU5VwaB1NVhNmjHLNQ6bA1LxpsnMGnb6n8iWAEU4MtJ3TpXerMY6RToSBbI/IBA4MJFbXds0z6XLqQh9XNrLL/J0FUSV0XGFiBRxVMvUP2ytzEKh9HE6fqX/ZqTqadtp89PRTJZM87Rkb3oPdJAlaM7JUaIznGrtKe45UwjtrdYk86QhOmpWXj4L2g0Gww=


    With cURL we could send the sample request like this:

    copy
    curl -X POST                                  \
    -H 'Content-Type: text/plain; charset=UTF-8'   \
    -H 'Client-Id: 2089123456789012'              \
    -H 'Request-Time: 2019-04-04T12:08:56+05:30'  \
    -H 'Encrypt: algorithm=RSA_AES, symmetricKey=FxE+siNhE2eQsnbui/6llu6TG9CaXFmT8gb2Z5bsvf2WGlAnoXoBrcB1bYodBnRs/CzSeEewFc4HOIqHejTepHehy86M9DUdefjYC783+LGBstQTPlLGsqcsYxPJTMCGYfTD6DSSXwqtKSiqD6q6C96zkp3/Q2ScmCAJprqtcA5SUj+cRmIdtG1OStSdHrQ+SstT74pwMbv1qlHbTeitZMTt5GNFXnhT1B3htS1sFb0BQ2OA+V2BtPW/izEP5ebrkfNQWmQKd6gc/i0j/DGBw4DQaxNfNvy2JHAljL5mP/ES9X0DJS6/MkimfDwXsSsTANWsjFfIoTodRn223HQC0w==' \
    -d 'r8w8wbc8Nv6sC2meJzArtGjDkbiAzg55UaDiq7TId1a7uzcv18qpOxVkXvqa3q/6TPemDDItZ79oHMzDJyvAngYqfpZZaedArWPCDeddqUl62zU5VwaB1NVhNmjHLNQ6bA1LxpsnMGnb6n8iWAEU4MtJ3TpXerMY6RToSBbI/IBA4MJFbXds0z6XLqQh9XNrLL/J0FUSV0XGFiBRxVMvUP2ytzEKh9HE6fqX/ZqTqadtp89PRTJZM87Rkb3oPdJAlaM7JUaIznGrtKe45UwjtrdYk86QhOmpWXj4L2g0Gww=' \
    https://sg-production-api.zoloz.com/api/v1/zoloz/authentication/test


    #Response Message

    image.png

    #Response Header

    #Response-Time

    The request time in rfc3339 format datetime + rfc822 format timezone, e.g., 2019-04-04T12:08:56+0530.

    It is the same format as in your request.


    #Content-Type 

    The media type of the response body returned to the customer (see rfc2616 for more information). Only two content types are possible: 

    • application/json; charset=UTF-8 : if the response is not encrypted.
    • text/plain; charset=UTF-8 : if the response is encrypted.


    #Signature 

    Similar with that in request, the signature  header in response contains the information about the signature of the message, the header value is composed of following 2 key-value pairs, joined with comma:

    • algorithm : indicates the algorithm used for signing, only RSA256 is accepted.
    • signature : base64 encoded string of the signature content.


    Here's a sample header entry:

    copy
    signature: algorithm=RSA256, signature=IpmAgtDqkjOz5sEEVlEq8OkdShXMJyXaK+6gtX/idB3+Hlhqnzdf90redIiJkawUlrY+icf1NhzSISiULGIAih72y/QRg/LlyWIWRE+GHx+k7Wl1wEYazvXRDQWF2TIia7SyyIhtjqIXj4BZ+409X72SOnx21qOU5eKxkgJQ8ZEVg5BFzXe0E//ISxJURBkVC1Q8v+7mnuT+YzgKvD1aMo16sYZih9ueTlj4xDPC8nKEoT+WJGjbdV7Ww/PXP419bGii9e7agLdxudGjD2B9d/IeUj8/w75u6V7PtdS8jCpyZQ0a28PcpvMD7yQ5f0odh7/6xGL6jECx3Y2YiuYCkw==


    Refer to Signature and Validation section for more information.


    #Encrypt

    Similar with that in request, the encrypt  header in response contains the encryption information of the message, the header value is composed of following 2 key-value pairs, joined with comma:

    • algorithm : indicates the algorithm used for signing, only RSA_AES is accepted.
    • symmetricKey : base64 encoded string of the AES key encrypted with RSA.


    Here's a sample header entry:

    copy
    encrypt: algorithm=RSA_AES, symmetricKey=FxE+siNhE2eQsnbui/6llu6TG9CaXFmT8gb2Z5bsvf2WGlAnoXoBrcB1bYodBnRs/CzSeEewFc4HOIqHejTepHehy86M9DUdefjYC783+LGBstQTPlLGsqcsYxPJTMCGYfTD6DSSXwqtKSiqD6q6C96zkp3/Q2ScmCAJprqtcA5SUj+cRmIdtG1OStSdHrQ+SstT74pwMbv1qlHbTeitZMTt5GNFXnhT1B3htS1sFb0BQ2OA+V2BtPW/izEP5ebrkfNQWmQKd6gc/i0j/DGBw4DQaxNfNvy2JHAljL5mP/ES9X0DJS6/MkimfDwXsSsTANWsjFfIoTodRn223HQC0w==


    Refer to Encryption and Decryption section for more information.


    #Response Body

    The response body is the content of the returned message, contains the output parameters of the API. Refer to API specifications for more information about the content structure.


    #Content Encoding

    • for non-encrypted response, the content is a JSON string;
    • for encrypted response, the content is the base64 encoded string of the encrypted data.

    #Common Result Structure

    There's a common result structure in the response, i.e.:

    copy
    {
      "api_specified_field1":"value1",
      "api_specified_field2":"value2",
      "result": {
        "resultCode":"SUCCESS",
        "resultStatus":"S",
        "resultMessage":"success"
      }
    }


    The "result" field is intended to show business level and gateway level status. The interface level status are different from one API to another, please refer to the corresponding API specification documents. In this section, we only present the gateway level status.


    The enumeration of the gateway level status codes are listed below:

    No.

    resultCode

    resultStatus

    resultMessage

    http status

    1

    SUCCESS

    S

    success

    200

    2

    PARAM_MISSING

    F

    param missing

    400

    3

    PARAM_ILLEGAL

    F

    param illegal

    400

    4

    SIGNATURE_INVALID

    F

    signature invalid

    401

    5

    KEY_NOT_FOUND

    F

    key not found

    401

    6

    ACCEPTED_SUCCESS

    A

    accepted success

    202

    7

    ACCEPTED_IDEMPOTENT_ERROR

    A

    accepted idempotent error

    202

    8

    NO_INTERFACE_DEF

    F

    API is not defined

    404

    9

    API_IS_INVALID

    F

    api is invalid

    400

    10

    MSG_PARSE_ERROR

    F

    msg format invalid

    400

    11

    OAUTH_FAIL

    F

    oauth fail

    401

    12

    VERIFY_ISV_ACCESS_TOKEN_FAIL

    F

    verify isv access token fail

    401

    13

    PROCESS_FAIL

    F

    process fail

    500

    14

    ACCESS_DENIED

    F

    access denied

    403

    15

    SYSTEM_BUSY

    F

    system busy

    503

    16

    REQUEST_TRAFFIC_EXCEED_LIMIT

    F

    request traffic exceed limit

    429

    17

    UNSUPPORTED_OPERATION

    F

    Unsupported Operation

    500

    18

    SYSTEM_ERROR

    U

    system error

    500

    19

    UNKNOWN_EXCEPTION

    U

    Unknown exception

    500

    20

    PROCESS_TIMEOUT

    F

    process timeout

    500


    #Full HTTP Response Sample

    #Non-encrypted response

    copy
    HTTP/1.1 200 OK
    Content-Type: application/json; charset=UTF-8
    Response-Time: 2019-11-19T21:56:15-0800
    Signature: algorithm=RSA256, signature=xxxxxxxxxxxxxxxxxx
    
    {
      "title": "hello",
      "description": "just for demonstration."
      "result": {
        "resultCode":"SUCCESS",
        "resultStatus":"S",
        "resultMessage":"success"
      }
    }


    #Encrypted response

    copy
    HTTP/1.1 200 OK
    Content-Type: text/plain; charset=UTF-8
    Response-Time: 2019-11-19T21:56:15-0800
    Signature: algorithm=RSA256, signature=xxxxxxxxxxxxxxxxxx
    Encrypt: algorithm=RSA_AES, symmetricKey=xxxxxxxxxxxxxx
    
    xxxxxxxxxx encrypted response string xxxxxxxxxxxx



    #Transmission Security

    #Sequence Overview

    The transmission security is guaranteed with signature validation and message encryption. Message signing and signature validation is mandatory for all requests and response, and message encryption is optional, up to the customer's requirements.


    If encryption is adopted, then the message body should be encrypted before signed, the whole interacting sequence is illustrated below:

    The Gateway Protocol


    #Algorithm Description

    #utf8_encode 

    This method encodes the binary data to text string in UTF-8 encoding.

    #base64urlsafe_encode 

    This method implements the Base64 encoding algorithm as specified in RFC 3548, which encodes arbitrary binary data into text strings that can be safely used as parts of URLs, or included as part of an HTTP POST request.

    #base64urlsafe_decode

    This method implements the Base64 decoding algorithm as specified in RFC 3548, which decodes text string encoded with base64_encode to original binary data.

    #sha256withrsa_sign 

    This method implements the PKCS#1 v1.5 padding and modular exponentiation with the formal name RSASSA-PKCS1-v1_5 after calculating the hash over the data using SHA256.

    #sha256withrsa_verify

    This method validates whether the content string matches the signature generated with sha256withrsa .

    #rsa_encrypt 

    This method encrypts message with RSA/ECB/PKCS1Padding.

    #rsa_decrypt 

    This method decrypts cipher text encrypted with RSA/ECB/PKCS1Padding.

    #aes_encrypt

    This method encrypts message with AES.

    #aes_decrypt 

    This method decrypts cipher text encrypted with AES.


    #Signature and Validation

    To make sure no man-in-the-middle attack is carried out, both the request message and the response message should be signed by sender and be validated by recipient.


    ZOLOZ service forces to validate the signature of each request so the customer needs to sign the request properly; ZOLOZ service also guarantees to sign the response, however, the signature validation to the response is optional for the customer. Even though, it is highly recommended for the customer to validate the signature against all responses.


    #Sign Message

    image.png


    #1. Get the private key

    For request (the customer concerns)

    An RSA 2048 key-pair MUST be generated on the customer's side before hands, of which the private key is the desired key for request message signing.

    For response (ZOLOZ concerns)

    An RSA 2048 key-pair is generated in ZOLOZ's system once the account of the customer is created, it's guaranteed to be unique for each customer. ZOLOZ will use the private key for response message signing.


    #2. Construct the data to be signed

    For request

    The content string that need to be signed for the request is composed by several parts, the format is:

    copy
    <HTTP METHOD> <HTTP URI>
    <Client-Id>.<Request-Time>.<HTTP BODY>


    It could be constructed by sequentially concatenate following strings:

    • The HTTP method (typically "POST")
    • A white space character (" ")
    • The requested URI
    • A new-line character ("\n")
    • The client ID
    • A dot character (".")
    • The request time (declared in the header) in format "yyyy-MM-dd'T'HH:mm:ssZ"
    • A dot character (".")
    • The HTTP body


    Here's an sample content string to be signed:

    copy
    POST /api/v1/zoloz/authentication/test
    2089012345678900.2020-01-01T08:00:00+0800.{
      "title": "hello",
      "description": "just for demonstration."
    }


    For response

    The content string to be signed by ZOLOZ for the response is the same with the content string to be validated by the customer. Please refer to next section for more information.


    #3. Calculate the signature

    copy
    SIGNATURE=base64urlsafe_encode(sha256withrsa_sign($CONTENT_TO_BE_SIGNED, $PRIVATE_KEY))


    The signature is calculated with above formula, in which:

    • sha256withrsa_sign : refer to algorithm description.
    • base64urlsafe_encode : refer to algorithm description.
    • CONTENT_TO_BE_SIGNED : content string to be signed.
    • PRIVATE_KEY : private key fetched in step 1.
    • SIGNATURE : generated signature string.


    #4. Configure signature in header

    Once the signature is generated, put the signature string into the "Signature" field of HTTP request header in the format below:

    copy
    Signature: algorithm=RSA256, signature=<the generated signature string>


    #Validate Message with Signature


    image.png


    #1. Get public key

    For request (ZOLOZ concerns)

    An RSA 2048 key-pair MUST be generated on the customer's side before hands, of which the public key MUST be registered to ZOLOZ's system before any request is sent. ZOLOZ will use the public key registered to validate the signature of each request from the customer.


    For response (the customer concerns)

    An RSA 2048 key-pair is generated in ZOLOZ's system once the account of the customer is created, it's guaranteed to be unique for each customer. The customer needs to acquire the public key of ZOLOZ's before hands and then validate the signature of each response with this public key.


    #2. Construct the content to be validated

    For request (ZOLOZ concerns)

    The content string of the request to be validated by ZOLOZ is the same with the content string being signed by the customer. Please refer to previous section for more information.


    For response (the customer concerns)

    The content string that needs to be validated by the customer is composed by several parts, the format is:

    copy
    <HTTP METHOD> <HTTP URI>
    <clientId>.<responseTime>.<responseBody>


    It could be constructed by sequentially concatenate following strings:

    • The HTTP method (typically "POST")
    • A white space character (" ")
    • The requested URI
    • A new-line character ("\n")
    • The client ID
    • A dot character (".")
    • The response time (declared in the header) in format "yyyy-MM-dd'T'HH:mm:ssZ"
    • A dot character (".")
    • The HTTP body


    Here's an sample content string to be validated:

    copy
    POST /api/v1/zoloz/authentication/test
    2089012345678900.2020-01-01T08:00:01+0800.{
      "title": "hello",
      "description": "just for demonstration."
    }


    #3. Extract signature from header

    The desired signature string could be extracted from "Signature" header:

    copy
    Signature: algorithm=RSA256, signature=<the desired signature string>


    #4. Validate signature

    copy
    IS_SIGNATURE_VALID=sha256withrsa_verify($CONTENT_TO_BE_VALIDATED, base64urlsafe_decode($SIGNATURE), $PUBLIC_KEY))


    The content and the signature is validated with above formula, in which:

    • base64urlsafe_decode : refer to algorithm description.
    • sha256withrsa_verify : refer to algorithm description.
    • CONTENT_TO_BE_VALIDATED : content string to be validated.
    • SIGNATURE : signature string extracted in step 3.
    • PUBLIC_KEY : public key fetched in step 1.
    • IS_SIGNATURE_VALID : whether the signature matches the content.


    #Encryption and Decryption

    If the customer wants their transmitted data to be encrypted, the encryption capability could be turned on. By default, an encrypted request results in an encrypted response, and vice versa.


    #Encrypt Message


    image.png


    #1. Get the public key

    For request (the customer concerns)

    An RSA 2048 key-pair is generated in ZOLOZ's system once the account of the customer is created, it's guaranteed to be unique for each customer. The customer needs to acquire the public key of ZOLOZ's before hands and then encrypt the randomly-generated symmetric key with this public key for each request needs to be encrypted.


    For response (ZOLOZ concerns)

    An RSA 2048 key-pair MUST be generated on the customer's side before hands, of which the public key MUST be registered to ZOLOZ's system before any request is sent. ZOLOZ will use the public key registered to encrypt the randomly-generated symmetric key for each response (needs to be encrypted) returned to the customer.


    #2. Prepare the content to be encrypted

    The content to be encrypted is the plain message of the business request/response, typically a JSON string.


    #3. Generate AES key

    Generate an 128-bits AES key randomly.


    #4. Encrypt the content

    copy
    ENCYRPTED_CONTENT_STRING=base64_encode(aes_encrypt($CONTENT_TO_BE_ENCRYPTED, $AES_KEY))


    The data is encrypted with above formula, in which:

    • base64urlsafe_encode : refer to algorithm description.
    • aes_encrypt : refer to algorithm description.
    • CONTENT_TO_BE_ENCRYPTED : the content string to be encrypted.
    • AES_KEY : the AES key generated in step 3.
    • ENCRYPTED_CONTENT_STRING : string of the encrypted content.


    #5. Encrypt the AES key

    copy
    ENCYRPTED_AES_KEY=base64urlsafe_encode(rsa_encrypt($AES_KEY, $PUBLIC_KEY))


    The signature is calculated with above formula, in which:


    #6. Set the header and body

    6.1 Configure the Encrypt header

    Put the encrypted AES key into the "Encrypt" field of HTTP header in the format below:

    copy
    encrypt: algorithm=RSA_AES, symmetricKey=<the encrypted AES key>
    6.2 Configure the Content-Type header

    Set the content type as text/plain :

    copy
    content-type: text/plain
    6.3 Set the HTTP body

    Set the encrypted content string as the HTTP body.


    #Decrypt Message


    image.png


    #1. Get the private key

    For request (ZOLOZ concerns)

    An RSA 2048 key-pair is generated in ZOLOZ's system once the account of the customer is created, it's guaranteed to be unique for each customer. ZOLOZ will use the private key to decrypt the symmetric key carried with the encrypted request.


    For response (the customer concerns)

    An RSA 2048 key-pair MUST be generated on the customer's side before hands, of which the private key is the desired key to decrypt the symmetric key carried with the encrypted response for the customer.


    #2. Get the content to be decrypted

    The data to be decrypted is the whole HTTP body, for both HTTP request and HTTP response.


    #3. Extract the encrypted AES key

    Extract the encrypted AES key from the Encrypt header, the header is in following format:

    copy
    encrypt: algorithm=RSA_AES, symmetricKey=<the encrypted AES key>


    #4. Decrypt the AES key

    copy
    AES_KEY=rsa_decrypt(base64urlsafe_decode($ENCRYPTED_AES_KEY), $PRIVATE_KEY)


    The AES key could be decrypted with above formula, in which:

    • base64urlsafe_decode : refer to algorithm description.
    • rsa_decrypt : refer to algorithm description.
    • ENCRYPTED_AES_KEY : the encrypted AES key extracted from step 3.
    • PRIVATE_KEY : the private key fetched in step 1.
    • AES_KEY : the original AES key randomly-generated to encrypt the message content.


    #5. Decrypt the content

    copy
    PLAIN_CONTENT_STRING=utf8_encode(aes_decrypt(base64_decode($ENCRYPTED_CONTENT), $AES_KEY))


    The content is decrypted with above formula, in which:


    #API Compatibility

    The version of the API is encoded in url with pattern of v\d+ (e.g., v1 , v2 and etc.). ZOLOZ SaaS service will provide APIs of new version when incompatible changes are introduced. Meanwhile, compatible changes might be introduced at anytime for an existing version of API and the customer MUST properly handle possible compatible changes of the API. 


    Any case of following changes should be considered as compatible change:

    1. New optional field is added to the request.
    2. New valid value is defined for a request field.
    3. Allowed length of a request field increases.
    4. New field is added to the response.
    5. The order of the fields of the request or the response changes.


    ZOLOZ Team