Setting Up
Payload Encryption
14min
introduction the contract360 platform's apis strictly comply with industry standard security protocols, ensuring that all exchanges of data are automatically protected through default employment of https, tls, and ssl protocols furthermore, to cater to clients with a priority on enhanced security, we provide payload encryption functionality this feature adds an extra layer of protection to the transmitted data by encrypting its content, thus bolstering the overall security measures of our platform prerequisites to activate payload encryption, the following steps must be completed key exchange the organization and signzy need to exchange keys signzy will provide their public key in cer txt format, and the organization must share its public key in the same format with signzy this exchange is securely conducted via email channels assistance for this process will be provided by the assigned customer success manager (csm) or account manager (am) account specification the organization needs to specify which accounts are authorized to make api calls to signzy this information allows the signzy team to configure the public certificates against the designated accounts steps to use encrypted payloads below are the guidelines for utilizing encrypted payloads with contract360 apis when implementing payload encryption, ensure to include the request header 'x content encoding' with the value 'encrypted' adhere to other headers as per the standard api documentation this header must be included to opt in for payload encryption failure to include this header will result in unencrypted payloads x content encoding encrypted upon opting for payload encryption in the initiate contract api, the responses sent over callbacks will also be encrypted 2\ construct the standard request payload according to the api documentation 3\ generate a 256 bit aes key and initialization vector (iv) employ the aes key to encrypt the api payload prepared in step 2 a 32 byte secret key and a 16 byte initialization vector (iv) are randomly generated the json object is encrypted using these randomly generated keys the encrypted data is then converted to base64 format and sent in the 'data' field 4\ transmission of randomly generated aes key and initialization vector (iv) for decryption at our end, both the randomly generated secret key and iv are required the client encrypts these random values using signzy's public key and converts them to base64 format these base64 encoded random values are then passed in the 'salt' field 5\ decryption process at signzy at signzy, our private key is utilized to decrypt the values passed in the 'salt' parameter this enables retrieval of the random values necessary for decryption with these random values, the actual data is decrypted the client needs to send the encrypted payload in this way { "data" "", "salt" "" } steps to handle encrypted response sent by signzy when signzy needs to send a response back the roles are reversed the client's public keyis utilized data is encrypted by generating an aes key and iv, and then sent in the 'data' field subsequently, the aes key and iv are encrypted using the client's public key the data on the callback would be posted in this way { "data" "", "salt" "" } sample java code for encryption private static void encryptdata(string plaindata, publickey publickey) throws exception { // generate a random aes key and iv byte\[] aeskeybytes = new byte\[32]; // aes 256 byte\[] ivbytes = new byte\[16]; // 16 bytes for aes iv securerandom securerandom = new securerandom(); securerandom nextbytes(aeskeybytes); securerandom nextbytes(ivbytes); // create a secretkeyspec for the aes key secretkeyspec aeskey = new secretkeyspec(aeskeybytes, "aes"); // encrypt the data using the aes key and iv cipher aescipher = cipher getinstance("aes/cbc/pkcs5padding"); aescipher init(cipher encrypt mode, aeskey, new ivparameterspec(ivbytes)); byte\[] encrypteddata = aescipher dofinal(plaindata getbytes("utf 8")); // combine the aes key and iv into a single byte array byte\[] combined = new byte\[aeskeybytes length + ivbytes length]; system arraycopy(aeskeybytes, 0, combined, 0, aeskeybytes length); system arraycopy(ivbytes, 0, combined, aeskeybytes length, ivbytes length); // encrypt the combined aes key and iv using the rsa public key cipher rsacipher = cipher getinstance("rsa/ecb/oaeppadding"); oaepparameterspec oaepparams = new oaepparameterspec("sha 1", "mgf1", new mgf1parameterspec("sha 1"), psource pspecified default); rsacipher init(cipher encrypt mode, publickey, oaepparams); byte\[] encryptedsalt = rsacipher dofinal(combined); // base64 encode the encrypted data and encrypted salt string base64encrypteddata = base64 getencoder() encodetostring(encrypteddata); string base64encryptedsalt = base64 getencoder() encodetostring(encryptedsalt); } sample java code for decryption public static string decryptdata(string base64data, string base64salt, privatekey privatekey) throws exception { // your base64 encoded encrypted data and salt byte\[] encrypteddata = base64 getdecoder() decode(base64data); byte\[] encryptedsalt = base64 getdecoder() decode(base64salt); // decrypt the salt using the rsa private key cipher cipher = cipher getinstance("rsa/ecb/oaeppadding"); oaepparameterspec oaepparams = new oaepparameterspec("sha 1", "mgf1", new mgf1parameterspec("sha 1"), psource pspecified default); cipher init(cipher decrypt mod, privatekey, oaepparams); byte\[] decryptedsalt = cipher dofinal(encryptedsalt); // extract the aes key and iv from the decrypted salt byte\[] aeskeybytes = new byte\[32]; // assuming the first 32 bytes are the aes key byte\[] ivbytes = new byte\[16]; // assuming the next 16 bytes are the iv system arraycopy(decryptedsalt, 0, aeskeybytes, 0, 32); system arraycopy(decryptedsalt, 32, ivbytes, 0, 16); // create a secretkeyspec for the aes key secretkeyspec aeskey = new secretkeyspec(aeskeybytes, "aes"); // decrypt the data using the aes key and iv cipher aescipher = cipher getinstance("aes/cbc/pkcs5padding"); aescipher init(cipher decrypt mode, aeskey, new ivparameterspec(ivbytes)); byte\[] decrypteddata = aescipher dofinal(encrypteddata); // return the decrypted data as a string return new string(decrypteddata, "utf 8"); } sample nodejs code for encryption const encryptdata = (reqobj, publickeybuffer) => { const aeskey = crypto randombytes(32); const iv = crypto randombytes(16); const reqstring = json stringify(reqobj); const cipher = crypto createcipheriv("aes 256 cbc", aeskey, iv); let data = cipher update(reqstring, "utf8", "base64"); data += cipher final("base64"); const combinedbuffer = buffer concat(\[aeskey, iv]); const encryptedbuffer = crypto publicencrypt( { key publickeybuffer, padding crypto constants rsa pkcs1 oaep padding, }, combinedbuffer, ); const salt = encryptedbuffer? tostring("base64"); return {data, salt}; } sample nodejs code for decryption const decryptdata = (encrypteddatabase64, encryptedsaltbase64) => { const decryptedbuffer = crypto privatedecrypt( { key privatekey, padding crypto constants rsa pkcs1 oaep padding, // using rsa pkcs1 oaep padding }, buffer from(encryptedsaltbase64, "base64"), ); const aeskeybuffer = decryptedbuffer? subarray(0, 32); // ? first 32 bytes are the aes key const ivbuffer = decryptedbuffer? subarray(32, 48); // ? next 16 bytes are the iv const decipher = crypto createdecipheriv( "aes 256 cbc", aeskeybuffer, ivbuffer, ); const encryptedbuffer = buffer from(encrypteddatabase64, "base64"); let decrypted = decipher update(encryptedbuffer); decrypted = buffer concat(\[decrypted, decipher final()]); return json parse(decrypted tostring("utf8")); } sample request for initiate contract api preproduction curl location 'https //api preproduction signzy app/api/v3/contract/initiate' \\ \ header 'authorization ' \\ \ header 'content type application/json' \\ \ header 'x content encoding encrypted' \\ \ data '{ "data" "", "salt" "" }' production curl location 'https //api signzy app/api/v3/contract/initiate' \\ \ header 'authorization ' \\ \ header 'content type application/json' \\ \ header 'x content encoding encrypted' \\ \ data '{ "data" "", "salt" "" }' sample response { "data" "", "salt" "" }