Message Level Encryption (MLE)

Any third party connecting to the MFS Cards APIs need to encrypt the payload by using a shared secret key which is provided at the onboarding stage.

Shared Key Cryptography

The shared key is generated and managed on the MFS Cards platform. The steps for implementing this cryptography are:

  • The sender and MFS Cards platform must both have the same key, which must be kept secret all the time
  • The sender uses the shared secret key to encrypt a message(JSON body), and sends the cipher encrypted body to MFS Cards
  • On receipt, the MFS Cards uses the identical key to decrypt the JSON body then does the processing. Then using same key the response JSON body is encrypted and sent to sender
  • Sender then decrypts the response JSON body to get the clear response

Example - Ping Service

The Ping service body is as follows:

{
    "pingID": 100
}

Using a shared encryption key, the clear body is encrypted to get the below encrypted message:

{
    "encryptedBody": "eyJhbGciOiJBMjU2R0NNS1ciLCJlbmMiOiJBMjU2R0NNIiwiaXYiOiJiX3hEejEzNE5WN29fTHBOIiwidGFnIjoiM2Y3TVdrNHNRdmJRaHlrUTRTc05rUSJ9.WZnaZh9LgXQE6ESmSegBv9AJC-w7YUOApw1dKwj14HQ.4_vygU9XW9-vc6Fs.NyEY9Cw6lzaKQYK6wg0NmsA.eHuaLmWBJFQRdkhmxp14cQ"
}

Using above, the Ping is called and below encrypted response is received:

{
    "encryptedBody": "eyJhbGciOiJBMjU2R0NNS1ciLCJlbmMiOiJBMjU2R0NNIiwiaXYiOiJsSl85WGE3bHdrTXRKczQ4IiwidGFnIjoiQnFhQjFMeEtlSHlCU29tc05MbHAxdyJ9.VmplQkXwPaROpRqI5sBoo1YpDy7WMTj6sI6pzCdRJYg.Satj1sTyMpNCibRF.5SkjefPIM34-mFb0Bdmlq4XeOIH6dRWvW7LGj6Qh_cQHKav_qKn1SCP2nulybjltljyUTfO5IN2PfOT1GOzK0dYJ342pjHTKLxc5HXk.-NjOv5KjP7YrtF4y27dn1A"
}

Then using same shared key, the sender decrypted the response to get the clear body:

{
    "pongId": 101,
    "errorCode": "0000",
    "errorMessage": "SUCCESS"
}

Sample Code - Java

package com.utils; 
import java.io.UnsupportedEncodingException; 
import java.security.MessageDigest; 
import java.security.NoSuchAlgorithmException; 
import javax.crypto.spec.SecretKeySpec; 
import org.jose4j.jwe.ContentEncryptionAlgorithmIdentifiers; 
import org.jose4j.jwe.JsonWebEncryption; 
import org.jose4j.jwe.KeyManagementAlgorithmIdentifiers; 
import org.jose4j.lang.JoseException;
public static String encrypt(String sharedSecret, String text)throws NoSuchAlgorithmException, UnsupportedEncodingException, JoseException {
  MessageDigest md = MessageDigest.getInstance("SHA-256"); 
  byte[] digest = md.digest(sharedSecret.getBytes("UTF-8")); 
  JsonWebEncryption jwe = new JsonWebEncryption(); 
  jwe.setAlgorithmHeaderValue(KeyManagementAlgorithmIdentifiers.A256GCMKW); 
  jwe.setEncryptionMethodHeaderParameter(ContentEncryptionAlgorithmIdentifiers.AES_256_GCM); 
  jwe.setKey(new SecretKeySpec(digest, "AES")); 
  // content you want to encrypt 
  jwe.setPayload(text); 
  String serializedJwe = jwe.getCompactSerialization(); 
  return serializedJwe; 
}
public static String decrypt(String sharedSecret, String text) throws NoSuchAlgorithmException, UnsupportedEncodingException, JoseException { 
  MessageDigest md = MessageDigest.getInstance("SHA-256"); 
  byte[] digest = md.digest(sharedSecret.getBytes("UTF-8"));
  JsonWebEncryption receiverJwe = new JsonWebEncryption(); 
  receiverJwe.setCompactSerialization(text); 
  receiverJwe.setKey(new SecretKeySpec(digest, "AES")); 
  String plaintext = receiverJwe.getPlaintextString(); 
  return plaintext; 
}