Calculate Mea-Secret header value

How to calculate request header field Mea-Secret

Mea-Secret value is used to validate if request is authentic. It also protects against Denial-of-Service attacks (attacker is required to use correct key, and MeaWallet can limit total number of requests from one key per second, or to disable the key when needed).

Generation

Secret value is calculated by encrypting Mea-Trace-Id and Mea-Api-Key-Id values concatenated in the following way: <Mea-Trace-Id> | # | <Mea-Api-Key-Id>

Encryption is done using Mea-Api-Key (M11 Key) which is provided by MeaWallet to customer.

  • Encryption algorithm:
    • AES/CBC/PKCS5Padding
    • iv = 00000000000000000000000000000000 (16 bytes of 0x00)
Note

Remember to add padding PKCS5. As the input data (#) will always make up 73 bytes in total, which means it needs to be padded with 7 more bytes up to 80 (padding will always be 07 07 07 07 07 07 07). However, it’s not recommended to hardcode it as the input might be redefined in future and you will forget to update it, and also most of the programming languages encryption libraries already do padding for you if you tell it to do that (like Java).

Sample of Mea-Secret generation

  • Mea-Api-Key AES-128 Key ( M11 key shared with customer out-of-band)
    • HEX 11223344556677889900aabbccddeeff
    • Bytes 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0x00, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff
  • Header values
    • Mea-Api-Key-Id (M11 key ID) 68e05e04-a54d-479c-a85f-b7f6c7531598
    • Mea-Trace-Id e06bd3df-4a75-4cae-baeb-094ef965e129
  • Input for Mea-Secret in ASCII
    e06bd3df-4a75-4cae-baeb-094ef965e129#68e05e04-a54d-479c-a85f-b7f6c7531598
  • Input for Mea-Secret in bytes 65303662643364662d346137352d346361652d626165622d3039346566393635653132392336386530356530342d613534642d343739632d613835662d623766366337353331353938
  • Input for Mea-Secret in bytes AND PKCS5 padding
    65303662643364662d346137352d346361652d626165622d3039346566393635653132392336386530356530342d613534642d343739632d613835662d62376636633735333135393807070707070707
  • Result Mea-Secret
    39F15E671F88008B2023526A4F7A431FFFE83C22F4931D85204EAFE019B8CAF38F8E9542BEFE59CD65D95C0F08BC110C6A2B02576A1EF254879AF167DD2AA11206E088BF8D220CEBEAE1BE407DD57972
Note

Header values (UUIDs) MUST be lower-case. As HTTP headers are not case sensitive, then their values are modified on the way to the server.

				
					import org.apache.commons.codec.DecoderException;
import org.apache.commons.codec.binary.Hex;
import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.StandardCharsets;
import java.security.GeneralSecurityException;
import java.util.UUID;

public class MeaSecretCipherExample {

    private static final byte[] IV = new byte[16];

    public static void main(String[] args) throws Exception {
        MeaSecretCipherExample cipher = new MeaSecretCipherExample();
        System.out.println(cipher.generateSecret());
    }

    public String generateSecret() throws Exception {
        // values from example
        String meaApiKeyHex = "11223344556677889900aabbccddeeff";
        String meaApiKeyId = "68e05e04-a54d-479c-a85f-b7f6c7531598";
        UUID meaTraceId = UUID.fromString("e06bd3df-4a75-4cae-baeb-094ef965e129");
        Cipher cipher = createCipher(meaApiKeyHex);
        byte[] plainData = createDataToEncrypt(meaTraceId, meaApiKeyId);
        byte[] encryptedData = cipher.doFinal(plainData);
        return Hex.encodeHexString(encryptedData);
    }

    private Cipher createCipher(String aesKeyHex) throws GeneralSecurityException, DecoderException {
        byte[] key = Hex.decodeHex(aesKeyHex);
        SecretKeySpec secretKey = new SecretKeySpec(key, "AES");
        Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
        cipher.init(Cipher.ENCRYPT_MODE, secretKey, new IvParameterSpec(IV));
        return cipher;
    }

    private byte[] createDataToEncrypt(UUID meaTraceId, String meaApiKeyId) {
        String data = meaTraceId + "#" + meaApiKeyId;
        return data.getBytes(StandardCharsets.UTF_8);
    }
}
				
			
On this page