X-Git-Url: http://www.git.cypherpunks.ru/?a=blobdiff_plain;f=pygost%2Fwrap.py;h=eb3855fb8ce3d7f25c18f01ae53c61df610f1783;hb=3374d4b8a5a58941e309b13524067ffa8d410d45;hp=4ab17370d2df7c80f6272c5fe8ac5c266afebd92;hpb=34c9c9a4f95eecfee75fc36d75d2ee45d1054a25;p=pygost.git diff --git a/pygost/wrap.py b/pygost/wrap.py index 4ab1737..eb3855f 100644 --- a/pygost/wrap.py +++ b/pygost/wrap.py @@ -1,11 +1,10 @@ # coding: utf-8 # PyGOST -- Pure Python GOST cryptographic functions library -# Copyright (C) 2015-2016 Sergey Matveev +# Copyright (C) 2015-2022 Sergey Matveev # # 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 -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. +# the Free Software Foundation, version 3 of the License. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -19,16 +18,20 @@ :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 cfb_encrypt +from pygost.gost28147 import DEFAULT_SBOX 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): +def wrap_gost(ukm, kek, cek, sbox=DEFAULT_SBOX): """28147-89 key wrapping :param ukm: UKM @@ -37,34 +40,34 @@ def wrap_gost(ukm, kek, cek): :type kek: bytes, 32 bytes :param cek: content encryption key :type cek: bytes, 32 bytes - :return: wrapped key + :returns: wrapped key :rtype: bytes, 44 bytes """ - cek_mac = MAC(kek, data=cek, iv=ukm).digest()[:4] - cek_enc = ecb_encrypt(kek, cek) + cek_mac = MAC(kek, data=cek, iv=ukm, sbox=sbox).digest()[:4] + cek_enc = ecb_encrypt(kek, cek, sbox=sbox) return ukm + cek_enc + cek_mac -def unwrap_gost(kek, data): +def unwrap_gost(kek, data, sbox=DEFAULT_SBOX): """28147-89 key unwrapping :param kek: key encryption key :type kek: bytes, 32 bytes :param data: wrapped key :type data: bytes, 44 bytes - :return: unwrapped CEK + :returns: unwrapped CEK :rtype: 32 bytes """ if len(data) != 44: raise ValueError("Invalid data length") ukm, cek_enc, cek_mac = data[:8], data[8:8 + 32], data[-4:] - cek = ecb_decrypt(kek, cek_enc) - if MAC(kek, data=cek, iv=ukm).digest()[:4] != cek_mac: + cek = ecb_decrypt(kek, cek_enc, sbox=sbox) + if MAC(kek, data=cek, iv=ukm, sbox=sbox).digest()[:4] != cek_mac: raise ValueError("Invalid MAC") return cek -def wrap_cryptopro(ukm, kek, cek): +def wrap_cryptopro(ukm, kek, cek, sbox=DEFAULT_SBOX): """CryptoPro key wrapping :param ukm: UKM @@ -73,28 +76,37 @@ def wrap_cryptopro(ukm, kek, cek): :type kek: bytes, 32 bytes :param cek: content encryption key :type cek: bytes, 32 bytes - :return: wrapped key + :returns: wrapped key :rtype: bytes, 44 bytes """ - return wrap_gost(ukm, diversify(kek, bytearray(ukm)), cek) + return wrap_gost( + ukm, + diversify(kek, bytearray(ukm), sbox=sbox), + cek, + sbox=sbox, + ) -def unwrap_cryptopro(kek, data): +def unwrap_cryptopro(kek, data, sbox=DEFAULT_SBOX): """CryptoPro key unwrapping :param kek: key encryption key :type kek: bytes, 32 bytes :param data: wrapped key :type data: bytes, 44 bytes - :return: unwrapped CEK + :returns: unwrapped CEK :rtype: 32 bytes """ if len(data) < 8: raise ValueError("Invalid data length") - return unwrap_gost(diversify(kek, bytearray(data[:8])), data) + return unwrap_gost( + diversify(kek, bytearray(data[:8]), sbox=sbox), + data, + sbox=sbox, + ) -def diversify(kek, ukm): +def diversify(kek, ukm, sbox=DEFAULT_SBOX): out = kek for i in range(8): s1, s2 = 0, 0 @@ -105,5 +117,36 @@ def diversify(kek, ukm): else: s2 += k iv = pack("