Message Level Encryption
Message Level Encryption allows you to store information or to communicate with other parties while helping to prevent uninvolved parties from understanding the stored information or understanding the communication.
Generation of public and private keys
The encryption service is based on JWE and works on top of SSL and requires separate key-pairs for Request and Response. Merchant and KUNA Core share public keys to encrypt and decrypt data from each other.
- Merchant (your) key pair: The merchant (you) encrypts Request (message payload) using the KUNA Core public key and KUNA Core would decrypt the payload using the KUNA Core private key.
- KUNA Core key pair: KUNA Core will encrypt Response (message payload) using the merchant (your) public key and merchant would decrypt the payload using the merchant (your) private key.
Diagram of the interaction between merchant and KUNA Core with MLE
Generating keys with OpenSSL
openssl genrsa -out my-private-key.pem 4096 // generates a private key
nano my-private-key.pem // display private key
openssl rsa -in my-private-key.pem -outform PEM -pubout -out my-public-key.pem // generates a public key
nano my-public-key.pem // display public key
Implementing MLE in API calls
Secure authentication
Detailed description of authentication via JWT token or API key is described in the "Authentication" guide.
Encrypt the request body
Use the public key to encrypt the body of the request and pass it through the token
field:
const nodeJose = require("node-jose");
const email = "YOUR_EMAIL"; // put here your email
const password = "YOUR_PASSWORD"; // put here your password
const merchantId = "YOUR_MERCHANT_ID"; // put here your merchant_id
const publicKey = "YOUR_PUBLIC_KEY"; // put here you public key
async function encryptJwe(publicKey, data) { // encryption function
const key = await nodeJose.JWK.asKey(publicKey, 'pem');
const payload = Buffer.from(JSON.stringify(data));
return nodeJose.JWE.createEncrypt({ format: 'compact', contentAlg: 'A256GCM', fields: { alg: 'RSA-OAEP' } }, key)
.update(payload)
.final();
}
const url = BASE_URL;
const path = "/v2/auth/login";
const body = {
token: email,
password: password,
};
encryptJwe(publicKey, body).then(jwe => {
const options = {
method: "POST",
headers: {
accept: "application/json",
"Content-Type": "application/json",
merchant_id: merchantId,
},
body: JSON.stringify({ token: jwe }),
};
fetch(url + path, options)
.then((response) => response.json())
.then((showResponse) => console.log(showResponse.data));
});
You will receive an encrypted response from KUNA Core:
{
"data": "eyJhbGciOiJSU0EtT0FFUCIsImVuYyI6IkEyNTZHQ00iLCJraWQiOiJ2MnBVZlVVQ3kwY3lRQzFwcGNTdDdoX3o4aVVZX2RkLWxOMld3Z2lfd2VBIn0.A7wMRSak_2JOH_yOUvhIIoq6Qptcr02JrTvjFycW11Hde6mxPUpoGjUZcr9LqaG4gqU8RuLlI76PuQCklP1lmFu_tfpwxqGAdlWQMxrvgYABVFR8O9iG2UxshP5qqGepFrX7O74DRVbdxeDBGMQDwpdH_M1LcnBFZj_49-REUArEGp26wGC4rs3M-Af2mdP_2QJi3yCDRdWTvJ5UONPSUvGCb-3LYao_-RwQJVl_Y6ieYuHWfPA-1qKbVNgz1miQBhl5aUZE7dmtTkRS1vndXhcSM_rMw50sEMzVGy-X3BKm7otBQNpzNupiEUparXSNM_0hdw7P2cfRJl8Atr8PDxQ8_-A1rlUOJtoD8KPP8Z_pmG1uEhjl_XJZvlJPv0iQ6iTk8-vBN81-ufyOAEspbhTcZ1Cbqm_CpY7jH34DOLuAecTmRKq0bp4vkML-dyMUt-cq3AYVv0TPNUUY3-xwXV-D7dqqGGxc2TgejwVCD64isbqR7vcsxJf1xtm1o3QdmDwj6j9GkItY72i8AgCef4TM2R09SiQYuJCDaLySnw-onHzN9Io9Z-merp1Bq9M7fzx6wTrxc1sKrIVNaL_gpYZBOAo7fZ_kxVMbvI7-YQFkfZEdlCBXrO2egkKzKmVQPDUwKGfN_85yCRvf4D3ubgah-kMvj-A7fnD76UeLVO0.UNSN7GCNZ1E-cVqO.aU_gVhnUiwqN1hBunSC6_wrNtaCf3mWfySqpEfUQcFFOpOcOBTqxmYdsWbd3HPBYJ8wi0s3OjzaH0jqn2KlM_6qoinohiPB5P8LZAw1r63kKOnRQ1qd01M3UdpCxB9O-pQvOaaf7NOO-VOT7Pq0KrDd65qgUvIKULlFsmY0Tb48EYaIdChAdJ7UXDsuZznm9VKs_aW4hlrKF75xJvOqUOcanwdu2COhkYP13tLoLw-RrLfU2-gVXQHsSZzCtT6zfCv-zJnJzq9HNOupRftg2UB9xzyMgkSFuOKaW6rgauDIcjP3ssb49C7An5Wf28RbA8-RS-FGwGmRGUsmiW9w1ONfWnpVOpiIEjIz9tSbFaPjQX9syzTDmF7lf2sBc77qJrFtKW73vlV9Pobsekh2rxYuPS09RGxtyF9pwfKWm7dXuMkPrRhVDWvMsKpRrfNktpeZok1V_xxM6_eGF0WGm_Mhpa7r78IBul50tft_Jk_df7vbfCi25AhTWmH1Foc8KFnqX3oP-bsPdgYUOsBYBxKeI52BklfV6OMhcM4e7NMH0Qa_ShU4YNM5sEMlXVWJBr4pnhCTG6q2EF1WODr19BFzxjRn8E2P4MaUjn8yGuZ92LTw8uSdl13szkxiwNszPqZyAR-A2vElSiM9fyBMNzNGc9M2gG7c7gnxCowTEzwz74yhyIcdkoRlVNXV1OaKKPlrFZGUlNxhCpSqMLyb2WdXlKHTN9NiK75pU6W6052zDzUdxlNFp0E-iSp4fTdt_Npfrpx6xMrnVGn8E9f8YAIH7kcofSoXcY7KwDYO55p0AkT7otbSovO-XA7EDAwDHipKN6FxhmjNdO45X9IPWerOjg6aq-iVK8SVlxldUAsOug9_t83c5P4l1cAp1Jab8IvDE7eELUGaDe7TToen_eo09xC8ifnkHRTazgo0zDTPBH9tvrudKJP6WJBOZo4rOFy_oErh8_T4YE27iiOZ4lur92vRaVNHNagMuFftvCJYUfr8rWOqQAxuc2lD2mD6qeYSV3OWEFmm12iYYhRePdEjmSviV0YRObcGZXAwMyPXKeb5B-2GmlOggxVJCL8ry6XU-AxU6g4FoWeOgdJYO2fg1VA7Tk9JqKBt-U4pzMlCv5K0ms0tR-NUpgCU2Pp3uKgouD7FcAEHytuKOSGWDNNY_HHieyTdcBqJwiNXpEQj85kaOCclWw-iQdj_rxus6WkLyjCs3k-OkwcV_nXQ9lWRGJKXuVnGWZRMtxKh8KBOgNjU7DhUqYwImMEt00U1eQpZ18L2ljAxMwg837cSy8uLcdPpLqAbUh5zfrJx2qcSg9svwf7uwgg6MCnNPSdVwaONHKAcDEcQNQzPD0mIhJJckLM4eZqVdf2rxPKRQPn6BOm2KwuW8FQOGhT07lwjVcGYn95ptl37G8tGw6J1YaDWZVK5M53zcnYw0Z4h7uf1Hula97xjLW006KgsS3Mn7MMmnE_tdi4c627MRqzHkjr4Xt_a5unN_n6axeBx7AscC0Slc3vTkJUggQBFUg07rrfR2FiXY_biDcTGZCEByDAIWfIrjS-yy1V5tzVreW8R5CAHP6mhCKYRu0EpSEmVv9WBv9YQWM20qsslYBETziRtWRF_sozPoy5AApCJ16M2ApaVEEliQVLkeX7CtJ5o5rQcxstR5oXzIVhDNZFo5W78_Vpv86BnzNzZz76ZIwvOBEglthV2h2t7w_UuURsQHbxa7Rtq4-kJTYHd4N1-Xy-9k-JGzZP1sjPWf6RDiHW0A4fynI_VO3JAjC-y6WUUjvMyv9ealMZ95ino5rr4-L-_w37DX9jw3GKwq3pUJr6QOBPXKwRrqVt-uSTEFutUTqSC8tuidiCfkAUgSrzR_Ij82wOGofkGAJeE4sH5I9-xeIRmpT-4X7F_AcL2tUj2H4xHuVh32ZkidofKQJGj5YqIZeXJ6kPQrOvfRt4EsNDuP4Im1knnTHtWy21X_TwOr1yWlMJjmajrDY5y7kLPRjdiSqYWDc51mx_2q2Rhlv27wtbaZd-mUVcICLP5xblGjS219pX2vwiWYvjUa_bjn-BMKIY7wSGnsmCm1kWwO4Lc_r95dMN7JqB-H_BPZMxpBsf72zRzdnsU9OTc_c7c160qdarDbNSVlR4QjOYIuKYXKBZtlrQGPjzMpTnltLaY627c5UiSPj5mLNOyyi3JnnlaHSTrjHxPWQ_80Ps5dj2yTAYiMa0njOVhPmZHOXDpSEujBYlApzgMIvAPuyiz_8qtv-_lYdrKfmoQjch8JgV5in0Lo7FbSXFvfMUMmD14gtdJy8rxAZPLI8ybnjXdsQzJScLKl7x33M-jnESrz4tTsSaJpvyPLcn2MFgFOmeukmNjBkytkNlT-a4DjDOsYT2_j123p20C9Nmlvc_zWQPHc71hMDO6IVSa3oEl-YiCmH8tXQifgQ-NNzTvI0lsOtxPzyyiNvOEz__jyiXEBiOIJBLchmBZfNZSaY52nXYYWIECqx2MBURNuxd3Hm8c_IN2IyznGOf6fF38AoPFuA1G6bFvIjaPm4rWw2gxmpnQAnNPbLEPtf3roodZg-r9OVONtpjR1ShIInTNKYa0FBGXp39moglP-2DypYZZ4_VdXwqMdKhi6Yfbep67xy497oQls5A6mDWdwmgnLwpqyQOPskwDRA5IVe0bR6s9QMBvrvIqELzTALlgWeWYBy-HXBd9OS8KOY-E-wM7XzKRyQM_MFSoyN6JTLCsKshUAA7hPb5HS2BaBjUNVmIhOu8_xBs-URhfuSiM9yhB8TCL6g36FexFn9J7cvH1TFJCFXGrFrJTqmiWPW2ghsMi8MhaA4cXMUUHCb4STCDpCEZnOkQerwGFRCKGoUESIXQPooJ2vNnusqqFwyXQSW0Zk-oluNFKY5FCSaxafS-KdHudBd0QESv5-8eUP6zmgVM2pcOT4LglZ9Flua3RY6LeH2JB5VdobG_b3wPT85YunZpqPWh4R7nz8N9nrGpBiqURC1osflun2o97pouMo0DOVlRJHl4ySJJREF60RmcQWjn6wcIR93N_1CQGEbP-KODgBEamhALrXvnfSJnggJExoKQpLvOiumXTPhUvvE7A25qmNGnQPjIvJ3wWnuAyoumYqWpG9yz0_LRHHqGrUBwgPO6U844FeZyWXaXUAd-wDYxCm6hQtPUecRVMpDsfdyy-EKm-rTUxU-gorUVLslBfTPFmb2oNjOHU2B6BzNEaZqvJBM_ybGB55T-UV7uoFFx7KFjKWXlFFd3_ifGo4Pq4J7vTqjQmAk_ElKjf8e4KOIFi8incKSnPd4JsNYl6pgB7U3CHcxte5t4QTci2hPZuZ3wc3WIzRPygJYjS3zZ50xg0crngm81cwqaJziBwhAaAy6JbZjQjoDBAuGAGrTwNQkax5KNe5Duf_HfC8DciyXv9nOy_DyknIRc25NlpNxmCMLXEndG2pBmZ2IUUhlKnFQBuwYeyScszLcGYA-kSinNdVfCcan24Hau8Z7xTnj39JfWvoyQUGx8GLuFN8xRtyjGnBHKE2_4pF0u9_alnUQpvkN9nQvZTTsiG5jf7ZlOxzNPjQOSlay2GW5M1MbGnjcqFlYM7rrPMHlzZDn2OykGq4ZvuJaxQ829ikVfa-E0Hh64dpB4AaCqltc7-hi9DZoHd7zT9ELynraQeHFzTlv06y3VcisvhjByBIN4t4aFztRqvDkGO0oqISB0-XRZfLO8uLBVPucjxlRdc4ggPC_v9DGoO4lYmj4Gf5knDzGY8iUt2b-6DvkNZxOn4_bbFlr9RJPuxH7_6DvNaDuirOqlki_STvFICu3UWt_JHBMCAunlrAoqNN6c4cIyEnaOyKkpZs0WXm3b_e9ApsnAFJB72E.IgGqvLg7GHe9LbuyhVfznA"
}
Decrypt the response
Use a private key that will allow you to decrypt the response from KUNA Core:
const nodeJose = require("node-jose");
const privateKey = "YOUR_PRIVATE_KEY"; // put here you private key
const kunaCoreResponse = showResponse.data; // encrypted response from KUNA Core
async function decryptJwe(privatekey, jwe){ // decryption function
const key = await nodeJose.JWK.asKey(privatekey, 'pem');
const result = await nodeJose.JWE.createDecrypt(key).decrypt(jwe);
return {
headers: result.header,
payload: JSON.parse(result.payload.toString()),
};
}
decryptJwe(privateKey, kunaCoreResponse).then(result => console.log(result));
Example of the decrypted response
{
"accessToken": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6Ijc4YTEyNjQ0LWExMjMtNGMyYi04ZTJmLTIyNWY1NGUyMGI4NCIsImVtYWlsIjoib3duZXJAYWRtaW4uY29tIiwicm9sZSI6Ik93bmVyIiwidXNlcm5hbWUiOiJTRUVEX0lOU1RJVFVUSU9OX09XTkVSX1BST0ZJTEUiLCJ0IjoidSIsIm1lcmNoYW50SWQiOiJiMzQ1NTViNy1kY2E0LTVlYzEtYWRlMy02NGEzYWQ1NDUzMTAiLCJpbnN0aXR1dGlvbiI6eyJpZCI6ImEyNjliYjI1LTk4OTgtNDJiNy1hYTkyLWMwZTdjMWE4ZjQ5MyIsInRpdGxlIjoiQ29vbCBDb21wYW55IiwiZ3JvdXBzIjpbeyJpZCI6ImJhbmsyX2RlcG9zaXQiLCJ0eXBlIjoiRGVwb3NpdCJ9LHsiaWQiOiJiYW5rMl9leGNoYW5nZSIsInR5cGUiOiJFeGNoYW5nZSJ9LHsiaWQiOiJiYW5rMl90cmFuc2ZlciIsInR5cGUiOiJUcmFuc2ZlciJ9LHsiaWQiOiJiYW5rMl93aXRoZHJhdyIsInR5cGUiOiJXaXRoZHJhdyJ9XSwicHVibGljS2V5IjoiLS0tLS1CRUdJTiBQVUJMSUMgS0VZLS0tLS1cbk1JSUNJakFOQmdrcWhraUc5dzBCQVFFRkFBT0NBZzhBTUlJQ0NnS0NBZ0VBNjhSNW9oMUYwdXJEUWZVVGtGQlhcblVSSWt5VklRN1dHeTAzMGJiMHgxMFF4ZElPZlZnVEFNM3N6MTZqOXZVR1ZCd2dxUExjZXF5RFdpTk03MEF1VFdcbjZqSnR1VWF6Z2JjMzhiVTU4Rk5FRU1mNU9SN2o5Q1dEYlVwT2pqbTN3M2tFUisraGxROFZlN1oyUnJoWnphMWhcbkV3anl6M0xxLzFqWmhjVlNPK3doY1Z4SG5mZmcwei9iTS9QUG5hVmdHZGFyTm85a1ZGMll4d205SVR2N0xLVG1cbldEV1JvSlRCUmNqS0RRQ2VSMmNONi9VaVhoNU8xMC9JVHA3S0hOOGlUQlExVnA5VG04Y3l5RVJOdVVSbkJBY1lcbncyaDByT09Yb1Z1L3p3NzErR1RNNVMwYlI5Y0twa2pXQndMdnRHUFlnOTRua0FFNkVKM0hMNHhLVmsvRVhpczRcblRtYlFRWjFlZjMzZzJIVzFHS1BtTDQwTUFwY1BVekdFV1YzeExGY2F0NGd1VW9ZSnp3Yjh5Ny9oTDFnNTFrYVhcbmNoaWRyWjMzLzRKTG9Ya0NBbThBMjUrVDFjNUNuNVBKV05rRTFxcTNBMS9MNkRiTjFROWdJd2lLNm9jVTcwemRcbnYxNlZRUHFsRzIrTnpHN0hOOWluZ3pzNE5IU3ZmcUpHQ0x1MzlKNjJUODFUNUJ1MlZicFV2K0dSN0h5b3lHTEpcbkRnSUpCOFBUeUFNQWlkeUJBRG1IanhjcjJmWHRJdXZKVWVkb20vOW5EZzB1UStnTVp4YnNLMldRVlBRL1JvemVcbldxTmFkdlpuRzVwYnA2L0ZVQ1ozYmZjL3pJeDg3OUhaT3RRdDhPMi9ZeUJ3R0dIdkF4UGFqTTBFQThaSUhJWUZcbnZRMTBVcGhsSmlWK2lZQ1UyNGNieURjQ0F3RUFBUT09XG4tLS0tLUVORCBQVUJMSUMgS0VZLS0tLS0ifSwiZmluZ2VycHJpbnQiOiJkN2I2MDhlZTYzMDQ5MWYwMTE5MDhlZjkzZjU4ZDE0NiIsImp3dElkIjoiYzYzYjE1YzYtY2FhMi00MWJiLTkwMWUtZDUwODk4YzFkMTM1IiwiaWF0IjoxNzExNTQ5MTIwLCJleHAiOjE3MTE1NTA5MjB9.jJI-hXkcpbrxwJ9-G5oZZvb6Ko_xanPxUjQSDcYzGrfSQlrgSZKUCIECQVoH2-0uvQKjkw5Bfy19xddtmLn2CwTQRsXoqGEd5ImJzeuxpEvB0VNhZJ0Vnry36PmLuNk0PYm5L1wEevPAK4iJT-OXUjZm23Nr8ORvCTqPn6hybh6EEL3ey-jojb2I_xMGAwsRAylPDKo0ggx_c3aLM8JuruHsDTxVaVuNVMRyY_PCmkHT_TQQOUAXn_l5SoJnQ9ie5fG5N9F_aPLDPFmL9LIWcct049YDr7sNO0JUJStXYQssgxMf_e6JbMZxCD5Sn8C95MrvUgf3YTAnPaxhNq5Unw",
"expiresIn": 1711550920,
"refreshToken": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6Ijc4YTEyNjQ0LWExMjMtNGMyYi04ZTJmLTIyNWY1NGUyMGI4NCIsImZpbmdlcnByaW50IjoiZDdiNjA4ZWU2MzA0OTFmMDExOTA4ZWY5M2Y1OGQxNDYiLCJzZXNzaW9uQ3JlYXRlZEF0IjoxNzExNTQ5MTIwMTM3LCJpYXQiOjE3MTE1NDkxMjAsImV4cCI6MTcxMTcyMTkyMH0.SUjEQNVrjp8hQ63FGEi9DrVieLSIW_3rjWmWzAbIrra9yo68uk0GpCCzp3NZPdpaIJGKatYYKFQ0OTobceBNWs1NI1I7G_s8IJyt7Ez1w0UW5xrFSSlplB7a2vCh99kdl0uiCnDRIrlNYq6rSF-pPyxF_C0K480M_1_fNTJrSv061feKLTZzgMGCOVFsaPBq0IjcmJ0kaN8ztk5KymEJ6sQXmvxJhZzDo2tJikcsyE3A7L9O3cA75Uhdy4yZl2m-eD6R-NViI8B0QNghd7qHD8U9arr1mFF-x_-evbX6qS1qRbRo5KM1RAzE-7ZpY1cSjLk2U4dersF294UNBT0CdA"
}
MLE is available for all KUNA Core endpoints.
Updated 9 months ago