# coding: utf-8
# PyGOST -- Pure Python GOST cryptographic functions library
-# Copyright (C) 2015-2019 Sergey Matveev <stargrave@stargrave.org>
+# Copyright (C) 2015-2024 Sergey Matveev <stargrave@stargrave.org>
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
:rfc:`4357` key wrapping (28147-89 and CryptoPro).
"""
+from hmac import compare_digest
from struct import pack
from struct import unpack
from pygost.gost28147 import ecb_decrypt
from pygost.gost28147 import ecb_encrypt
from pygost.gost28147_mac import MAC
+from pygost.gost3413 import ctr
+from pygost.gost3413 import mac
def wrap_gost(ukm, kek, cek, sbox=DEFAULT_SBOX):
:returns: wrapped key
:rtype: bytes, 44 bytes
"""
- return wrap_gost(ukm, diversify(kek, bytearray(ukm)), cek, sbox=sbox)
+ return wrap_gost(
+ ukm,
+ diversify(kek, bytearray(ukm), sbox=sbox),
+ cek,
+ sbox=sbox,
+ )
def unwrap_cryptopro(kek, data, sbox=DEFAULT_SBOX):
iv = pack("<I", s1 % 2 ** 32) + pack("<I", s2 % 2 ** 32)
out = cfb_encrypt(out, out, iv=iv, sbox=sbox)
return out
+
+
+def kexp15(encrypter_key, encrypter_mac, bs, key, iv):
+ """KExp15 key exporting
+
+ :param encrypter_key: encrypting function for key encryption,
+ that takes block as an input
+ :param encrypter_mac: encrypting function for key authentication
+ :param int bs: cipher's blocksize, bytes
+ :param bytes key: key to export
+ :param bytes iv: half blocksize-sized initialization vector
+ """
+ key_mac = mac(encrypter_mac, bs, iv + key)
+ return ctr(encrypter_key, bs, key + key_mac, iv)
+
+
+def kimp15(encrypter_key, encrypter_mac, bs, kexp, iv):
+ """KImp15 key importing
+
+ :param encrypter_key: encrypting function for key decryption,
+ that takes block as an input
+ :param encrypter_mac: encrypting function for key authentication
+ :param int bs: cipher's blocksize, bytes
+ :param bytes kexp: key to import
+ :param bytes iv: half blocksize-sized initialization vector
+ """
+ key_and_key_mac = ctr(encrypter_key, bs, kexp, iv)
+ key, key_mac = key_and_key_mac[:-bs], key_and_key_mac[-bs:]
+ if not compare_digest(mac(encrypter_mac, bs, iv + key), key_mac):
+ raise ValueError("Invalid authentication tag")
+ return key