Adding items using the Web API
This tutorial describes the process for adding an item to a container on the IRB Exchange.
Data security is one of top priorities. In order to keep your data secure and only accessible to the organizations that you choose, it is important that all information that is stored on the IRB Exchange is encrypted locally before transmitting the information to the IRB Exchange.
The item creation process consists of the following steps.
- Preparing an Item for encryption
- Encrypting the Item header and content
- Encode the encrypted values and hashes
- Creating the HTTP request
- Handling the HTTP response
Preparing an Item for encryption
The preparation step consists of converting your applications representation of an Item header and Item content to an array of bytes.
- Item header should first be converted into a JSON string before converting it into a byte array.
- If the Item content is structured; e.g. one of the IRB data formats. The content should be converted into a JSON string before converting it into a byte array.
- If the Item content is unstructured; e.g. a word or pdf file. Convert the file directly into a byte array.
- Using UTF-8 encoding when converting a JSON string into a byte array.
Pseudocode - Prepare structured message
Header = ToBytes(ToJson(Item.Header), UTF8)
Content = ToBytes(ToJson(Item.Content), UTF8)
Pseudocode - Prepare unstructured message
Header = ToBytes(ToJson(Item.Header), UTF8)
Content = ToBytes(Item.Content)
ToBytes: A function that converts an input string to a byte array using a specified encoding.
ToJson: A function converts an object into a JSON string.
For example, in .NET the ToJson
function could be implemented using Newtonsoft.Json.JsonConvert.SerializeObject
, and the ToBytes
function could be implemented using Encoding.GetBytes
. The implementation of ToBytes
is dependent upon the input type, thus you may have multiple implementations.
Encrypting the Item header and content
This step requires you to use cryptography libraries for the programming language being used to build the IRB Exchange client application.
- Create a new 256 bit symmetric key and iv (initialization vector) to be used with the AES encryption algorithm.
- Load the X.509 certificate for the organization.
- Retrieve the certificate from the IRB Exchange, see Get Organization Certificate
- Retrieve the certificate from a local key store. Refer to the documentation for your programming language and/or operating system.
- Compute the SHA-256 hash of header, content, and symmetric key.
- Encrypt the header, and content using the AES algorithm, key, and iv.
- Use the same symmetric key and iv when encrypting the header and content.
- Encrypt the symmetric key using the public key of the X.509 certificate.
- Be sure to use OAEP during encryption.
Pseudocode
Key = GenerateKey()
IV = GenerateIV()
Certificate = LoadCertificate(Thumbprint)
HeaderHash = Hash(Header)
ContentHash = Hash(Content))
KeyHash = Hash(Key)
EncryptedHeader = SymmetricEncrypt(HeaderBytes, Key, IV)
EncryptedContent = SymmetricEncrypt(Content, Key, IV)
EncryptedKey = AsymmetricEncrypt(Certificate.PublicKey)
GenerateKey: A function that creates a cryptographically random 256 bit key.
GenerateIV: A function that creates a cryptographically random byte array.
LoadCertificate: A function that retrieves an X509 certificate using the certificates thumbprint.
Hash: A function calculates the SHA-256 hash of the input bytes.
SymmetricEncrypt: A function uses the AES algorithm to encrypts the input bytes.
AsymmetricEncrypt: Represents a function that uses the RSA algorithm with OAEP to encrypt the input bytes using its public key of an X509 certificate.
Encode the encrypted values and hashes
In this step, we will encode the values produced in the preceding steps to string so they can be easily added to a JSON message for sending to the IRB Exchange.
Pseudocode
EncodedHeader = Base64Encode(EncryptedHeader)
EncodedHeaderHash = Base16Encode(HeaderHash)
EncodedContent = Base64Encode(EncryptedContent)
EncodedContentHash = Base16Encode(ContentHash)
EncodedKey = Base64Encode(EncryptedKey)
EncodedKeyHash = Base16Encode(KeyHash)
EncodedIV = Base16Encode(IV)
Base16Encode: Represents a function that returns the base-16 encoding of the input bytes.
Base64Encode: Represents a function that returns the base-64 encoding of the input bytes.
Creating the HTTP request
Now that each of the required data elements has been encoded, it is time to construct the HTTP request. There are two endpoints that can be used to add an item to a container, which one you use depends on your specific scenario.
- Adding the item to a logical collection
- Adding the item to a well known location
Adding the item to a logical collection in the container
To add an item to a logical collection within a container, we will construct an HTTP request that uses the Add Item endpoint. Please refer to the HTTP related documentation for the programming language you are using.
- Construct the url
- Construct the payload
- Construct an HTTP POST request
- Sign the request
Pseudocode
Url = "https://api.huronirbexchange.com/containers/{ContainerId}/items/{ItemId}"
Payload = {
header = EncodedHeader
headerHash = EncodedHeaderHash
headerHashAlgorithm = "SHA256"
content = EncodedContent
contentHash = EncodedContentHash
contentHashAlgorithm = "SHA256"
key = EncodedKey
keyHash = EncodedKeyHash
keyHashAlgorithm = "SHA256"
iv = EncodedIV
algorithm = "AES"
}
HttpRequest = Sign(CreateRequest("POST", Url, ToJson(Payload)))
ContainerId: An IRB Exchange identifier for a container.
ItemId: An IRB Exchange identifier that represents a path to a logical collection.
CreateRequest: A function that builds an HTTP request.
Sign: A function that performs the request signing process.
Adding the item to a well known container location
To add an item to a well known location within a container, follow the same steps defined in Adding the item to a logical collection in the container. However, construct a HTTP PUT request instead of an HTTP POST request.
What's the difference?
You may be wondering, what is the difference between these two methods. They appear to be doing the same thing, the both create a new item on the exchange. The difference is subtle, and relates to the location that the item is stored within the IRB Exchange.
Given the following two requests:
POST https://api.huronirbexchange.com/containers/1dcad49ed4b9474c91549c713d358263/items/devices
PUT https://api.huronirbexchange.com/containers/1dcad49ed4b9474c91549c713d358263/items/devices
The POST
request will create a new item that is subordinate to the devices endpoint. For example, the id of the item will set to a unique value like /devices/ef00ad54eee749d3990a5d705f9ddde2
.
The PUT
request will create the item at the specified request url. The id of the item will be set to /devices
.
The POST
request acts as if it is adding a new item to a collection named devices, while the PUT
request creates a new item named devices.
Handling the HTTP response
The final step in adding an item to the IRB Exchange is to send the request and handle the response that is sent back.
Pseudocode
HttpResponse = Send(HttpRequest)
IF HttpResponse.StatusCode >= 200 AND HttpResponse.StatusCode < 300 THEN
Item = FromJson(HttpResponse.Body)
ELSE
HandleError
FromJson: A function that converts a JSON string into object.
HandleError: A function that handles the http response when it was not successful.