Перейти к содержанию

AF_ALG: ГОСТ напрямую через Crypto API ядра

AF_ALG — стандартный сокетный интерфейс Linux к Kernel Crypto API. Через него приложения могут выполнять операции шифрования, расшифрования, хэширования и MAC без прямого обращения к OpenSSL. ГОСТ встроен в ядро НАЙС.ОС и готов к таким вызовам сразу после его запуска.

Проверить доступность без секретных данных

python3 - <<'PY'
import socket
for mode in ('cbc(kuznyechik)','xts(kuznyechik)','cbc(magma)'):
    try:
        with socket.socket(socket.AF_ALG, socket.SOCK_SEQPACKET) as ctl:
            ctl.bind(('skcipher', mode))
        print('OK:',mode)
    except OSError as e:
        print('FAIL:',mode, e)
PY

Обратите внимание: xts(kuznyechik) — это режим шифрования сектора, а не самостоятельный базовый шифр. Регистрация базового алгоритма и возможность создать составной XTS проверяются отдельно.

Реальное шифрование и обратное восстановление: CBC и XTS

Следующий пример выполняет операции в памяти через Linux AF_ALG. Он не создаёт файлы, не изменяет диски и не использует реальные ключи. Для XTS длина общего ключевого материала — 64 байта (два ключа «Кузнечика»), для CBC — 32 байта.

python3 - <<'PY'
import os,socket,hashlib
original=os.urandom(4096)
def check(mode,keylen):
    key=os.urandom(keylen)
    iv=os.urandom(16)
    with socket.socket(socket.AF_ALG,socket.SOCK_SEQPACKET) as alg:
        alg.bind(('skcipher',mode))
        alg.setsockopt(socket.SOL_ALG,socket.ALG_SET_KEY,key)
        def operation(payload,opnum):
            sock,_=alg.accept()
            with sock:
                sock.sendmsg_afalg([payload],op=opnum,iv=iv)
                blocks=[]
                left=len(payload)
                while left:
                    block=sock.recv(left)
                    if not block:
                        raise RuntimeError('Crypto API returned fewer bytes than expected')
                    blocks.append(block)
                    left-=len(block)
                return b''.join(blocks)
        encrypted=operation(original,socket.ALG_OP_ENCRYPT)
        decrypted=operation(encrypted,socket.ALG_OP_DECRYPT)
    assert encrypted!=original
    assert decrypted==original
    print(mode, 'PASS',len(encrypted),'bytes',hashlib.sha256(decrypted).hexdigest())
check('cbc(kuznyechik)',32)
check('xts(kuznyechik)',64)
PY

Этот тест проверяет свойство round-trip: зашифровали, расшифровали и получили исходные данные. Для полной криптографической приёмки дополнительно применяют известные тестовые векторы (KAT) и независимые реализации.

Стрибог через AF_ALG

python3 - <<'PY'
import socket
message=b'NiceOS Linux Crypto API\n'
for name,size in [('streebog256',32),('streebog512',64)]:
    with socket.socket(socket.AF_ALG,socket.SOCK_SEQPACKET) as h:
        h.bind(('hash',name))
        s,_=h.accept()
        with s:
            s.sendall(message)
            out=s.recv(size)
        print(name,out.hex())
PY

Все операции относятся к ядру НАЙС.ОС. Проверка доступности алгоритма не выполняет modprobe: криптографический код уже включён в ядро.

Типичные ошибки

  • ENOENT при bind: неверное имя, отсутствующий алгоритм или шаблон в запущенном ядре.
  • EINVAL: некорректный размер ключа, IV или размер данных.
  • EAFNOSUPPORT: AF_ALG отсутствует в конфигурации или ограничен средой выполнения.
  • EPERM: запрет со стороны прав/политик безопасности.

Для диагностики используйте uname -r, /boot/config-$(uname -r), /proc/crypto и journalctl -k. Не пытайтесь искать несуществующие внешние ГОСТ-модули.