Skip to main content

Mea-Secret Header Field Calculation

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) which is provided by MeaWallet to customer.

Encryption algorithm:

  • AES/CBC/PKCS5Padding
  • iv = 00000000000000000000000000000000 (16 bytes of 0x00)
info

Remember to add padding PKCS5. As the input data <Mea-Trace-Id>#<Mea-Api-Key-Id> is always 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

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
info

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);
}
}