InterVASP Messaging Standard 101

IVMS101 (the interVASP Messaging Standard) is an internationally recognized standard that helps with language encodings, numeric identification systems, phonetic name pronunciations, and standardized country codes (ISO 3166). For general information about IVMS, please visit InterVASP.org.

Veriscope IVMS Encryption

IVMS data is encrypted with standard encryption algorithms implemented in php. The source code can be found here. Code snippets are included below for reference.

Encrypt Data

IVMS data is encrypted with the corresponding end-users public key. Who’s the "corresponding user"?

Example 1. Example

Let’s say Alice (the originator) wants to send funds to Bob (the beneficiary). Alices' source of funds are held at oVASP. Bob’s destination address is held at bVASP. As part of the travel rule transfer:

  1. oVASP needs to send Alice’s user data to bVASP. However, before doing so, oVASP needs to encrypt the data.

  2. bVASP needs to send Bobs encrypted user data to oVASP

  3. oVASP encrypts Alice’s data with Bobs Shyft user address public key — in this instance Bob is the "corresponding user"

  4. bVASP encrypts Bobs data with Alice’s Shyft user address public key — in this instance Alice is the "corresponding user"

  5. Of course, for the above to happen, oVASP and bVASP must exchange their users public keys beforehand

Encrypt source code
      /**
      * Encrypt Data
      *
      * @param string $publicKey   eth public key (append 04 at the start if not included)
      * @param string $data       string to encrypt
      * @param string $sharedMacData
      *
      * @return string
      */

public static function encryptData($publicKey, $data, $sharedMacData = false){
      $ec = new EC('secp256k1');
      $cipher = "aes-128-ctr";
      $publicKey = self::stripZero($publicKey);


      $bufferData = base64_encode($data);
      $privateKey = $ec->genKeyPair()->getPrivate();
      $key1 = $ec->keyFromPublic($publicKey, 'hex');
      $key2 = $ec->keyFromPrivate($privateKey);

      $x = $key2->derive($key1->getPublic())->toString(16);
      $key = self::concatKDF($x,32);
      $ekey = mb_substr($key, 0, 32);
      $mkey = hash("sha256",self::hexToStr(mb_substr($key, 32, 64)));

      // encrypt
      $ivlen = openssl_cipher_iv_length($cipher);
      $iv = bin2hex(openssl_random_pseudo_bytes($ivlen));
      $encryptedData = openssl_encrypt($data, $cipher, self::hexToStr($ekey), $options=0, self::hexToStr($iv));
      $dataIV = $iv.bin2hex(base64_decode($encryptedData));
      if($sharedMacData){
        $sharedMacData = implode("", $sharedMacData);
      }
      $tag = hash_hmac('sha256',self::hexToStr($dataIV.$sharedMacData), self::hexToStr($mkey));
      $result = $key2->getPublic(false,"hex").$dataIV.$tag;

      return base64_encode(pack('H*',$result));
    }

Decrypt Data

IVMS data is decrypted with the corresponding end-users private key. Expanding on the example above:

Example 2. Example

Continued from above:

  1. oVASP decrypts Alice’s data with Alices Shyft user address private key

  2. oVASP decrypts Bobs data with Bobs Shyft user address private key

Decrypt source code
    /**
      * Decrypt Data
      *
      * @param string $privateKey  eth private key
      * @param string $data       string to decrypt
      * @param string $sharedMacData
      *
      * @return string
      */

    public static function decryptData($privateKey, $data, $sharedMacData = false){
      $ec = new EC('secp256k1');
      $cipher = "aes-128-ctr";

      $unpackedData = implode("",unpack("H*",base64_decode($data)));
      $publicKey = mb_substr($unpackedData,0, 130);
      $dataIV = mb_substr($unpackedData, 130, -64);
      $tag = mb_substr($unpackedData,-64);

      $key1 = $ec->keyFromPublic($publicKey, 'hex');
      $key2 = $ec->keyFromPrivate($privateKey);
      $x = $key2->derive($key1->getPublic())->toString(16);

      $key = self::concatKDF($x,32);
      $ekey = mb_substr($key, 0, 32);
      $mkey = hash("sha256",self::hexToStr(mb_substr($key, 32, 64)));
      if($sharedMacData){
        $sharedMacData = implode("", $sharedMacData);
      }
      $tag = hash_hmac('sha256',self::hexToStr($dataIV.$sharedMacData), self::hexToStr($mkey));

      // decrypt data
      $iv = mb_substr($dataIV,0, 32);
      $encryptedData =  mb_substr($dataIV,32);
      $result = openssl_decrypt(self::hexToStr($encryptedData), $cipher, self::hexToStr($ekey), $options=OPENSSL_RAW_DATA, self::hexToStr($iv));


      if(openssl_error_string() !== false && openssl_error_string() !== "error:0909006C:PEM routines:get_name:no start line"){
        throw new \Exception("Could not Decrypt data", 1);
      }

      return $result;
    }

Veriscope IVMS Validator

Veriscope has built an IVMS validator to assit VASPs in confirming that their IVMS files are correct. Instructions on how to use this are below.

Option 1 - Validate via your Veriscope instance

The following assumes you have Veriscope installed, it’s up & running and you can ssh into the machine it’s running on.
  1. ssh into the machine

  2. Load the files to be validated to your Veriscope instance

  3. Prepare to POST a JSON file with curl using the curl Validator Syntax below

  4. If your file validates successfully, the response will be Valid IVMS101. Else, you will see Invalid IVMS along with an error message.

curl Validator Syntax

curl -X POST -H "Content-Type: application/json" -d @FILENAME_DESTINATION http://localhost:8000/ivms101-validate/@IVMS_TYPE

where @FILENAME_DESTINATION is the path to your file (on your Veriscope machine) and @IVMS_TYPE is the type of IVMS file you want to be validated: can be either orginator or beneficiary or complete (both originator and beneficiary).

Validate an Originator IVMS

curl -X POST -H "Content-Type: application/json" -d @originator-example.json http://localhost:8000/ivms101-validate/originator

Validate an Beneficiary IVMS

curl -X POST -H "Content-Type: application/json" -d @beneficiary-example.json http://localhost:8000/ivms101-validate/beneficiary

Validate an Complete (Originator & Beneficiary) IVMS

curl -X POST -H "Content-Type: application/json" -d @complete-example.json http://localhost:8000/ivms101-validate/complete

Option 2 - Validate using a JSON scheme validator

  1. Download the JSON schema file from the Shyft Network repo.

  2. Paste the schema into an online, interactive JSON schema validator e.g.: JSON Schema validator

  3. Paste the JSON file that you want to be validated, i.e. INPUT JSON if using the validator link above

  4. Check the results. If everything is OK, you should see a message like: No errors found. JSON validates against the schema

Sample IVMS files can be found in the Shyft Network repo.