Первое шифрование

Итак нам нужно зашифровать запрос. 

Ключи необходимые для шифрования запроса: https://nanokassa.ru/integration/documentation/publichnye-rsa-klyuchi/

Итак нам нужно зашифровать вот такой запрос:

{
    "kassaid": "123456",
    "kassatoken": "3212312312312",
    "cms": "ss7-7.2.13.140",
    "purchase": {
        "products": [{
            "name": "\u041f\u0435\u043d\u043a\u0430 \u043e\u0447\u0438\u0449\u0430\u044e\u0449\u0430\u044f \u043e\u0441\u0432\u0435\u0436\u0430\u044e\u0449\u0430\u044f, \u0440\u043e\u0437\u043e\u0432\u0430\u044f VPROVE \u00ab\u0421\u044d\u043d\u043a\u044c\u044e \u041d\u0435\u0439\u0447\u0430\u00bb (120 \u043c\u043b) (VTNFC0004), VTNFC0004",
            "price": "589",
            "quantity": 2,
            "tax": "vat0",
            "discount": {
                "type": "amount",
                "value": 16.21
            }
        }, {
            "name": "\u041f\u0435\u043d\u043a\u0430 \u043e\u0447\u0438\u0449\u0430\u044e\u0449\u0430\u044f \u043e\u0441\u0432\u0435\u0436\u0430\u044e\u0449\u0430\u044f, \u0444\u0438\u043e\u043b\u0435\u0442\u043e\u0432\u0430\u044f VPROVE \u00ab\u0421\u044d\u043d\u043a\u044c\u044e \u041d\u0435\u0439\u0447\u0430\u00bb (120 \u043c\u043b) (VTNFC0003), VTNFC0003",
            "price": "589",
            "quantity": 3,
            "tax": "vat0",
            "discount": {
                "type": "amount",
                "value": 24.31
            }
        }, {
            "name": "\u041a\u0440\u0435\u043c \u043e\u0447\u0438\u0449\u0430\u044e\u0449\u0438\u0439 \u043e\u0441\u0432\u0435\u0436\u0430\u044e\u0449\u0438\u0439 VPROVE \u00ab\u0421\u044d\u043d\u043a\u044c\u044e \u041d\u0435\u0439\u0447\u0430\u00bb (150 \u043c\u043b) (VTNCC0001), VTNCC0001",
            "price": "689",
            "quantity": 1,
            "tax": "vat0",
            "discount": {
                "type": "amount",
                "value": 9.48
            }
        }, {
            "name": "\u0414\u043e\u0441\u0442\u0430\u0432\u043a\u0430: \u041f\u0443\u043d\u043a\u0442\u044b \u0432\u044b\u0434\u0430\u0447\u0438 \u0437\u0430\u043a\u0430\u0437\u043e\u0432 (\u0421\u0414\u042d\u041a)",
            "price": "350.0000",
            "quantity": 1
        }]
    },
    "type": "payment",
    "test": 0,
    "nalog_type": 2,
    "delivery_nalog_taxid":4,
    "mode": "email",
    "customer_phone": "79050001500",
    "customer_email": "mail@nanokassa.ru",
    "card_amount": 3934
}

Итак вот этот большой запрос после шифрования должен превратиться вот в такой небольшой запросик:

{
    "ab":"GYBhagdYGWgahjGDHASgdjhas...ASDGd", 
    "de":"GYBhagdYGWgahjGDHASgdjhas...ASDGd", 
    "kassaid":"123456", 
    "kassatoken":"3212312312312", 
    "test":"1"
}

Разберем, что здесь что.

Объекты kassaid и kassatoken - данные для авторизации.

Объект test здесь указан как 1 - значит эти данные не будут фискализированы онлайн кассой. Зато они будут видны в личном кабинете nanokassa.ru

В объекте ab находится ключ для дешифровки пакета de. Объект ab зашифрован с помощью шифрования RSA. 

В объекте de находится основной пакет с данными. Объект de зашифрован с помощью AES256-CTR. Ключ каждый раз разный. Ключ можно узнать только расшифровав пакет ab (RSA)

Вот функции (на php) (с учетом, что установлен openssl), чтобы грамотно вам зашифровать пакеты для первого шифрования. (request показан обобщенно). Для шифрования aes256-ctr используется функция openssl_encrypt.

$request = '{
"kassaid": "123456", "kassatoken": "3212312312312", "cms":"xxx", ... "card_amount": 3934
}';
$IVdata = random_bytes(16);
$pw = random_bytes(32);
$mk = 'xxx'; // hmac контроль в формате base64
$dataAES = openssl_encrypt($request, "aes-256-ctr", $pw, OPENSSL_RAW_DATA, $IVdata);
$hmac = hash_hmac('sha512', $IVdata.$dataAES, base64_decode($mk), true);
$returnDataDE = base64_encode($hmac.$IVdata.$dataAES);

То есть строение пакета de должно быть таким. 64 байта hmac, 16 байт IVDATA, и остальные байты самого пакета.

Теперь перейдем к пакету ab. 

Вот функции (на php) (с учетом, что установлен openssl), чтобы грамотно вам зашифровать пакеты для первого шифрования. (pubkey показан обобщенно). Для шифрования RSA используется функция openssl_public_encrypt.

$pubkey = "-----BEGIN PUBLIC KEY-----
HASGDHJASGDASDSAGD .... 
SADGHASDHASJGDAHJS==
-----END PUBLIC KEY-----";
openssl_public_encrypt($pw, $ab_rsa, $pubkey, OPENSSL_PKCS1_OAEP_PADDING)
$ab = base64_encode ($ab_rsa);
$returnDataAB = $ab;

Теперь мы можем уже понять, как получить вот такой пакет. 

{    
    "ab":"GYBhagdYGWgahjGDHASgdjhas...ASDGd",     
    "de":"GYBhagdYGWgahjGDHASgdjhas...ASDGd",     
    "kassaid":"123456",     
    "kassatoken":"3212312312312",     
    "test":"1"
}

Перейдем ко второму шифрованию.