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.
VASPs can input, managed and Export IVMS data in Veriscope under 'Manage Organization.'
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"?
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:
-
oVASP needs to send Alice’s user data to bVASP. However, before doing so, oVASP needs to encrypt the data.
-
bVASP needs to send Bobs encrypted user data to oVASP
-
oVASP encrypts Alice’s data with Bobs Shyft user address public key — in this instance Bob is the "corresponding user"
-
bVASP encrypts Bobs data with Alice’s Shyft user address public key — in this instance Alice is the "corresponding user"
-
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:
Continued from above:
-
oVASP decrypts Alice’s data with Alices Shyft user address private key
-
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. |
-
ssh into the machine
-
Load the files to be validated to your Veriscope instance
-
Prepare to POST a JSON file with curl using the curl Validator Syntax below
-
If your file validates successfully, the response will be
Valid IVMS101
. Else, you will seeInvalid 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
Option 2 - Validate using a JSON scheme validator
-
Download the JSON schema file from the Shyft Network repo.
-
Paste the schema into an online, interactive JSON schema validator e.g.: JSON Schema validator
-
Paste the JSON file that you want to be validated, i.e.
INPUT JSON
if using the validator link above -
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. |
Export IVMS data
VASPs can now export their VASP organization data in IVMS format from Veriscope. Data can be exported in either of two formats:
-
Beneficiary VASP and Beneficiary
-
Originating VASP and Originator
In both instances, the Beneficiary and Originator person details are mocked and taken from the Sandbox Environment. Person details are included so that the exported files pass IVMS validation, described above.
To export your IVMS data, go to 'Manage Organization' and click on either of the Export buttons illustrated below.