From c9abb42693dfe8288aecb7ef064b907be0561629 Mon Sep 17 00:00:00 2001 From: Sergey Matveev Date: Wed, 29 Jul 2020 21:52:12 +0300 Subject: [PATCH] KDF_*_GOSTR3411_2012_256, KEG --- README | 2 + news.texi | 2 + pygost/kdf.py | 81 +++++++++++++++++++++++++++++++++++++ pygost/stubs/pygost/kdf.pyi | 21 ++++++++++ pygost/test.do | 1 + pygost/test_kdf.py | 58 ++++++++++++++++++++++++++ www.texi | 2 + 7 files changed, 167 insertions(+) create mode 100644 pygost/kdf.py create mode 100644 pygost/stubs/pygost/kdf.pyi create mode 100644 pygost/test_kdf.py diff --git a/README b/README index b9156ca..b82dfaf 100644 --- a/README +++ b/README @@ -26,6 +26,8 @@ GOST is GOvernment STandard of Russian Federation (and Soviet Union). * MGM AEAD mode for 64 and 128 bit ciphers (Р 1323565.1.026–2019) * CTR-ACPKM, OMAC-ACPKM-Master modes of operation (Р 1323565.1.017-2018) * KExp15/KImp15 key export/import functions (Р 1323565.1.017-2018) +* KDF_GOSTR3411_2012_256, KDF_TREE_GOSTR3411_2012_256 (Р 50.1.113-2016) +* KEG export key generation function (Р 1323565.1.020-2018) * PEP247-compatible hash/MAC functions Known problems: low performance and non time-constant calculations. diff --git a/news.texi b/news.texi index 55bd80a..4c8094e 100644 --- a/news.texi +++ b/news.texi @@ -9,6 +9,8 @@ @item CTR-ACPKM mode of operation @item OMAC-ACPKM-Master moder of operation @item KExp15/KImp15 key export/import functions + @item KDF_GOSTR3411_2012_256, KDF_TREE_GOSTR3411_2012_256 + @item KEG export key generation function @end itemize @anchor{Release 4.8} diff --git a/pygost/kdf.py b/pygost/kdf.py new file mode 100644 index 0000000..73d716f --- /dev/null +++ b/pygost/kdf.py @@ -0,0 +1,81 @@ +# coding: utf-8 +# PyGOST -- Pure Python GOST cryptographic functions library +# Copyright (C) 2015-2020 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, 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 +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +"""Key derivation functions, Р 50.1.113-2016, Р 1323565.1.020-2018 +""" + +import hmac + +from pygost.gost3410_vko import kek_34102012256 +from pygost.gost3410_vko import kek_34102012512 +from pygost.gost34112012256 import GOST34112012256 +from pygost.utils import bytes2long +from pygost.utils import long2bytes + + +def kdf_gostr3411_2012_256(key, label, seed): + """KDF_GOSTR3411_2012_256 + + :param bytes key: initial key + :param bytes label: label + :param bytes seed: seed + :returns: 32 bytes + """ + return hmac.new( + key=key, + msg=b"".join((b"\x01", label, b"\x00", seed, b"\x01\x00")), + digestmod=GOST34112012256, + ).digest() + + +def kdf_tree_gostr3411_2012_256(key, label, seed, keys, i_len=1): + """KDF_TREE_GOSTR3411_2012_256 + + :param bytes key: initial key + :param bytes label: label + :param bytes seed: seed + :param int keys: number of generated keys + :param int i_len: length of iterations value (called "R") + :returns: list of 256-bit keys + """ + keymat = [] + _len = long2bytes(keys * 32 * 8, size=1) + for i in range(keys): + keymat.append(hmac.new( + key=key, + msg=b"".join((long2bytes(i + 1, size=i_len), label, b"\x00", seed, _len)), + digestmod=GOST34112012256, + ).digest()) + return keymat + + +def keg(curve, prv, pub, h, mode=2001): + """Export key generation (Р 1323565.1.020-2018) + + :param GOST3410Curve curve: curve to use + :param long prv: private key + :param pub: public key + :type pub: (long, long) + :param bytes h: "h"-value, 32 bytes + """ + if len(h) != 32: + raise ValueError("h must be 32 bytes long") + ukm = bytes2long(h[:16]) + if ukm == 0: + ukm = 1 + if mode == 2012: + return kek_34102012512(curve, prv, pub, ukm) + k_exp = kek_34102012256(curve, prv, pub, ukm, mode=2001) + return b"".join(kdf_tree_gostr3411_2012_256(k_exp, b"kdf tree", h[16:24], 2)) diff --git a/pygost/stubs/pygost/kdf.pyi b/pygost/stubs/pygost/kdf.pyi new file mode 100644 index 0000000..78a82e9 --- /dev/null +++ b/pygost/stubs/pygost/kdf.pyi @@ -0,0 +1,21 @@ +from typing import Sequence + +from pygost.gost3410 import GOST3410Curve + + +PublicKey = Tuple[int, int] + + +def kdf_gostr3411_2012_256(key: bytes, label: bytes, seed: bytes) -> bytes: ... + + +def kdf_tree_gostr3411_2012_256( + key: bytes, + label: bytes, + seed: bytes, + keys: int, + i_len=1, +) -> Sequence[bytes]: ... + + +def keg(curve: GOST3410Curve, prv: int, pub: PublicKey, h: bytes, mode=2001) -> bytes: ... diff --git a/pygost/test.do b/pygost/test.do index 06b9f97..d73b608 100644 --- a/pygost/test.do +++ b/pygost/test.do @@ -9,6 +9,7 @@ wrap gost3412 gost3413 mgm +kdf x509 cms pfx diff --git a/pygost/test_kdf.py b/pygost/test_kdf.py new file mode 100644 index 0000000..8622a42 --- /dev/null +++ b/pygost/test_kdf.py @@ -0,0 +1,58 @@ +# coding: utf-8 +# PyGOST -- Pure Python GOST cryptographic functions library +# Copyright (C) 2015-2020 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, 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 +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +from unittest import TestCase + +from pygost.kdf import kdf_gostr3411_2012_256 +from pygost.kdf import kdf_tree_gostr3411_2012_256 +from pygost.utils import hexdec + + +class TestKDFGOSTR34112012256(TestCase): + def runTest(self): + self.assertEqual( + kdf_gostr3411_2012_256( + hexdec("000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f"), + hexdec("26bdb878"), + hexdec("af21434145656378"), + ), + hexdec("a1aa5f7de402d7b3d323f2991c8d4534013137010a83754fd0af6d7cd4922ed9"), + ) + + +class TestKDFTREEGOSTR34112012256(TestCase): + def runTest(self): + self.assertSequenceEqual( + kdf_tree_gostr3411_2012_256( + hexdec("000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f"), + hexdec("26bdb878"), + hexdec("af21434145656378"), + 1, + ), + (hexdec("a1aa5f7de402d7b3d323f2991c8d4534013137010a83754fd0af6d7cd4922ed9"),), + ) + self.assertSequenceEqual( + kdf_tree_gostr3411_2012_256( + hexdec("000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f"), + hexdec("26bdb878"), + hexdec("af21434145656378"), + 2, + ), + ( + hexdec("22b6837845c6bef65ea71672b265831086d3c76aebe6dae91cad51d83f79d16b"), + hexdec("074c9330599d7f8d712fca54392f4ddde93751206b3584c8f43f9e6dc51531f9"), + ), + ) diff --git a/www.texi b/www.texi index abdff1f..a7b565f 100644 --- a/www.texi +++ b/www.texi @@ -58,6 +58,8 @@ Currently supported algorithms are: @item MGM AEAD mode for 64 and 128 bit ciphers (Р 1323565.1.026–2019) @item CTR-ACPKM, OMAC-ACPKM-Master modes of operation (Р 1323565.1.017-2018) @item KExp15/KImp15 key export/import functions (Р 1323565.1.017-2018) +@item KDF_GOSTR3411_2012_256, KDF_TREE_GOSTR3411_2012_256 (Р 50.1.113-2016) +@item KEG export key generation function (Р 1323565.1.020-2018) @item PEP247-compatible hash/MAC functions @end itemize -- 2.44.0