CipherLink
Optional encryption and signing of the whole Connect answer.
Optional. Enable in Connect Settings > Response > Encryption. The entire JSON response is encrypted, for both success and error responses.
Keep in mind
- Payload
- AES-256-CBC with PKCS#7 padding, then Base64.
- Signature
- RSA-SHA256 over the Base64 payload string, then Base64.
- Marked answers
- Encrypted answers carry the
X-CipherLinkheader. - Random field
- The decrypted JSON holds an extra random field at the root. Ignore it.
Envelope
Encrypted answer
{
"sig": "<BASE64_RSA_SIGNATURE>",
"payload": "<BASE64_AES_CIPHERTEXT>"
}
Decoding
- Decode sig from Base64.
- Verify RSA-SHA256 over the payload string.
- Decode payload from Base64.
- Decrypt AES-256-CBC.
- Parse the JSON and ignore the unknown random field at the root.
$envelope = json_decode($body, true);
$signature = base64_decode($envelope['sig']);
if (openssl_verify($envelope['payload'], $signature, RSA_PUBLIC_KEY, OPENSSL_ALGO_SHA256) !== 1) {
throw new RuntimeException('Bad signature');
}
$json = openssl_decrypt($envelope['payload'], 'aes-256-cbc', AES_KEY, 0, AES_IV);
$answer = json_decode($json, true);
import base64, json
from cryptography.hazmat.primitives import hashes, padding, serialization
from cryptography.hazmat.primitives.asymmetric import padding as rsa
from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes
envelope = json.loads(body)
public_key = serialization.load_pem_public_key(RSA_PUBLIC_KEY)
public_key.verify(base64.b64decode(envelope["sig"]), envelope["payload"].encode(), rsa.PKCS1v15(), hashes.SHA256())
decryptor = Cipher(algorithms.AES(AES_KEY), modes.CBC(AES_IV)).decryptor()
padded = decryptor.update(base64.b64decode(envelope["payload"])) + decryptor.finalize()
unpadder = padding.PKCS7(128).unpadder()
answer = json.loads(unpadder.update(padded) + unpadder.finalize())
Client config
Copy these from Connect Settings into the mod. The values below are placeholders.
| Name | Value | Size |
|---|---|---|
aes_key |
<AES_KEY_FROM_CONNECT_SETTINGS> |
32 bytes |
aes_iv |
<AES_IV_FROM_CONNECT_SETTINGS> |
16 bytes |
rsa_public_key |
<RSA_PUBLIC_KEY_FROM_CONNECT_SETTINGS> |
— |
tls_public_key_pin |
<TLS_PIN_IF_CONFIGURED> |
— |
TLS pin
If your settings show a TLS public key pin, check it on every connection before sending the key.