Continuously receiving data

This section shows you how to setup a simple sender and RECEIVER_INITIATED_RECEIVER. We assume that you have completed all steps from the sending_first_data guide.

Note

The following guide assumes basic knowledge of the bash shell. In order to execute the commands, you need to have jq for parsing JSON installed.

Creating a receiver service

  1. Open the Linker Service view in the datalinker console.

  2. Click on Create a new Linker Service.

  3. In the dialog, you can specify the properties of your linker service:

    • Specify the properties as done for the AD_HOC_RECEIVER in the previous guide.
    • Select Receiver-initiated receiver as your linker service type.
  4. Click the save button.

_images/my_new_service.png

Creating a receiver client

In the previous guide we used the datalinker API to create a client for an AD_HOC_RECEIVER service. Now we are using the datalinker console to do the same for a RECEIVER_INITIATED_RECEIVER

Note

Clients for RECEIVER_INITITATED_RECEIVER and SENDER_INITIATED_RECEIVER services can only be created by a datalinker user with access to the respective linker service.

  1. Open a shell window and type the following commands to create a RSA keypair and to show the public key.
openssl genpkey -algorithm RSA -out receiver-initiated.pem -pkeyopt rsa_keygen_bits:4096
openssl rsa -pubout -in receiver-initiated.pem -out receiver-initiated.pub
cat receiver-initiated.pub
  1. Calculate the fingerprint of the public key.
cat receiver-initiated.pub | openssl sha256
  1. Open the Client view in the datalinker console.

  2. Click on Create a new Client.

  3. In the dialog, you can specify the properties of your linker service:

    • Specify a strong password. You will pass it to the script later so you won’t need to remember it.
    • Select My Receiver-Initiated Receiver Service as your linker service.
    • Now a new field is shown for the public key. Paste the key you generated in the first step.
  1. Click the save button.
_images/my_new_client.png

Creating a linker session

  1. We will reuse the code for logging in our client and creating a linker session from the sending_first_data guide.
#!/usr/bin/env bash

BASE_URL='https://developer.datalinker.io/api'
SERVICE_ID='com.myorg.receiver-initiated'
CLIENT_ID='66ab516f-88d2-4692-9c82-bc6bb0837cec'
PASSWORD='somethingverylongandcomplex'
FINGERPRINT='2e49c39deea7209b68b7ff3d86b585314439b97030297c93f3fd3679be5925e7'

JWT=$(curl -X POST -s --header 'Content-Type: application/json' -d "{\"password\": \""${PASSWORD}"\"}" ${BASE_URL}/clients/${CLIENT_ID}/authenticate)
JWT=$(jq -r '.id_token' <<< $JWT)
echo "jwt:\t\t\t$JWT"

SESSION_ID=$(curl -X POST -s -i --header 'Accept: */*' --header "Authorization: Bearer ${JWT}" --header 'Content-Type: application/json' -d "{\"clientId\": \""${CLIENT_ID}"\"}" ${BASE_URL}/linker-sessions | grep Location)
SESSION_ID="${SESSION_ID##*/}"
SESSION_ID="${SESSION_ID//$'\r'/}"
echo "sessionId:\t\t$SESSION_ID"
  1. To give the sending client an out-of-band possibility to verify the authenticity of the public key on the server, we will calculate the fingerprint of our public key. We then print the fingerprint and the session ID as JSON to the console. In production, this could be shown as a QR code.

Joining a linker session

  1. For the client, we also some of the previous code.
#!/usr/bin/env bash

BASE_URL='https://developer.datalinker.io/api'
SERVICE_ID='com.myorg.sender'
PASSWORD='test'
DOCUMENT_TYPE='com.myorg.my-document-type'

CLIENT_ID=$(curl -X POST -s -i --header 'Content-Type: application/json' -d "{\"linkerServiceId\": \""${SERVICE_ID}"\", \"password\": \""${PASSWORD}"\"}" ${BASE_URL}/clients | grep Location)
CLIENT_ID="${CLIENT_ID##*/}"
CLIENT_ID="${CLIENT_ID//$'\r'/}"
echo "clientId:\t\t$CLIENT_ID"

JWT=$(curl -X POST -s --header 'Content-Type: application/json' -d "{\"password\": \""${PASSWORD}"\"}" ${BASE_URL}/clients/${CLIENT_ID}/authenticate)
JWT=$(jq -r '.id_token' <<< $JWT)
echo "jwt:\t\t\t$JWT"
  1. Next, we will prompt for the session ID and fingerprint echoed by the receiver:
echo "Session ID: "
read SESSION_ID
echo "Fingerprint: "
read FINGERPRINT
  1. Now we will update the linker session to set the sender our client ID. Afterwards we can retrieve the public key and verify it.
curl -X PUT -s --header 'Content-Type: application/json' --header "Authorization: Bearer ${JWT}" -d "{\"clientId\": \""${CLIENT_ID}"\"}" ${BASE_URL}/linker-sessions/${SESSION_ID}

PUBLIC_KEY=$(curl -X GET -s --header 'Content-Type: application/json' --header "Authorization: Bearer ${JWT}" -d "{\"clientId\": \""${CLIENT_ID}"\"}" ${BASE_URL}/linker-sessions/${SESSION_ID}/publickey)
PUBLIC_KEY=$(jq '.publicKey' <<< ${PUBLIC_KEY})
PUBLIC_KEY="${PUBLIC_KEY#\"}"
PUBLIC_KEY="${PUBLIC_KEY%\"}"
echo ${PUBLIC_KEY} > public.pub

CALCULATED_FINGERPRINT=$(cat public.pub | openssl sha256)

if [ ${FINGERPRINT} != ${CALCULATED_FINGERPRINT} ]
then
    echo 'Failed to verify fingerprint.'
    exit
fi

Sending data forever

The last bit of the sender is to generate a random AES128 key and to encrypt it. Reusing the code from the previous guide, we will encrypt the document with the AES128 key and send it together with the encrypted key and the initialization vector:

  1. Generate a AES128 key and encrypt it using the public key retrieved from the server.
RANDOM_PASSWORD=$(openssl rand -base64 32)
KEY_IV=$(openssl enc -nosalt -aes-128-cbc -base64 -k ${RANDOM_PASSWORD} -P)
AES_KEY=$(echo $KEY_IV | sed -e 's/key=\(.*\)/\1/' | sed -e 's/\(.*\) iv\(.*\)/\1/')
AES_KEY="${AES_KEY//$'\r'/}"
echo ${AES_KEY} > aes.key
IV=$(echo ${KEY_IV} | grep iv)
IV="${IV##*=}"
IV="${IV//$'\r'/}"

openssl rsautl -encrypt -inkey public.pub -pubin -in aes.key -out aes.enc
    base64 aes.enc > aes.b64
    ENCRYPTED_KEY=`cat aes.b64`
    echo "encryptedKey:\t\t$ENCRYPTED_KEY"
  1. Create a document, encrypt it and finally send it.
CONTENT="{\"number\":$((RANDOM % 1024))}"
echo "content:\t\t$CONTENT"

echo $CONTENT > document.txt
ENCRYPTED_CONTENT=$(openssl enc -nosalt -aes-128-cbc -in document.txt -base64 -iv ${IV} -K ${AES_KEY})
rm document.txt

DOCUMENT="{\"documentTypeId\": \""${DOCUMENT_TYPE}"\", \"parameters\": {\"key\": \""${ENCRYPTED_KEY}"\", \"iv\": \""${IV}"\"}, \"data\": \""${ENCRYPTED_CONTENT}"\"}"

DOCUMENT_ID=$(curl -X POST -s -i --header 'Content-Type: application/json' --header "Authorization: Bearer ${JWT}" -d "${DOCUMENT}" ${BASE_URL}/linker-sessions/${SESSION_ID}/documents | grep Location)
DOCUMENT_ID="${DOCUMENT_ID##*/}"
DOCUMENT_ID="${DOCUMENT_ID//$'\r'/}"
echo "documentId:\t\t$DOCUMENT_ID"

Polling for data

The receiver now need to poll for data. Have a look at the sample scripts below for the implementation of the loop.

  1. Retrieve all documents.
DOCUMENTS=$(curl -X GET -s --header 'Accept: application/json' --header "Authorization: Bearer ${JWT}" ${BASE_URL}/linker-sessions/${SESSION_ID}/documents)
  1. Retrieve the key and the initialization vector. We assume that $DOCUMENT holds an individual document.
PARAMETERS=$(echo $DOCUMENT | jq -r '.parameters')

ENCRYPTED_KEY=$(echo $PARAMETERS | jq -r '.key')
    echo $ENCRYPTED_KEY > key.b64
    base64 -D key.b64  > key.enc
rm key.b64

AES_KEY=$(openssl rsautl -decrypt -inkey receiver-initiated.pem -in key.enc)
echo "\t\tkey:\t\t\t$AES_KEY"

IV=$(echo $PARAMETERS | jq -r '.iv')
echo "\t\tiv:\t\t\t$IV"
  1. Lastly, we will decrypt the document with the key, similar to the previous example, and delete the document.
ENCRYPTED_CONTENT=$(echo $DOCUMENT | jq -r '.data')

CONTENT=$(echo $ENCRYPTED_CONTENT | openssl aes-128-cbc -K ${AES_KEY} -iv ${IV} -d -base64 -in document.enc)
echo "\t\tcontent:\t\t$CONTENT"

curl -X DELETE -s --header "Authorization: Bearer ${JWT}" ${BASE_URL}/linker-sessions/${SESSION_ID}/documents/${DOCUMENT_ID}

Sample scripts

The following two scripts implement what we’ve just discussed.