X-Git-Url: http://www.git.cypherpunks.ru/?a=blobdiff_plain;f=pygost%2Fgost3413.py;h=27f0c30dc79a75de4e66f8e284455221474fa215;hb=a9f7e3dfc59a987c3d6cce4108f18d9f6b72867b;hp=495a3f9e343826ed430616f88b63c4ead6ca5b60;hpb=4277661e11e63906d923827e5c124877f1dc0c8d;p=pygost.git diff --git a/pygost/gost3413.py b/pygost/gost3413.py index 495a3f9..27f0c30 100644 --- a/pygost/gost3413.py +++ b/pygost/gost3413.py @@ -1,6 +1,6 @@ # coding: utf-8 # PyGOST -- Pure Python GOST cryptographic functions library -# Copyright (C) 2015-2020 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 @@ -13,18 +13,20 @@ # # You should have received a copy of the GNU General Public License # along with this program. If not, see . -""" GOST R 34.13-2015: Modes of operation for block ciphers +"""GOST R 34.13-2015: Modes of operation for block ciphers This module currently includes only padding methods. """ +from os import urandom + from pygost.utils import bytes2long from pygost.utils import long2bytes from pygost.utils import strxor from pygost.utils import xrange -KEY_SIZE = 32 +KEYSIZE = 32 def pad_size(data_size, blocksize): @@ -112,7 +114,7 @@ def acpkm(encrypter, bs): """ return b"".join([ encrypter(bytes(bytearray(range(d, d + bs)))) - for d in range(0x80, 0x80 + bs * (KEY_SIZE // bs), bs) + for d in range(0x80, 0x80 + bs * (KEYSIZE // bs), bs) ]) @@ -274,7 +276,7 @@ Rb128 = 0b10000111 def _mac_ks(encrypter, bs): Rb = Rb128 if bs == 16 else Rb64 - _l = encrypter(bs * b'\x00') + _l = encrypter(bs * b"\x00") k1 = _mac_shift(bs, _l, Rb) if bytearray(_l)[0] & 0x80 > 0 else _mac_shift(bs, _l) k2 = _mac_shift(bs, k1, Rb) if bytearray(k1)[0] & 0x80 > 0 else _mac_shift(bs, k1) return k1, k2 @@ -294,7 +296,7 @@ def mac(encrypter, bs, data): tail_offset = len(data) - bs else: tail_offset = len(data) - (len(data) % bs) - prev = bs * b'\x00' + prev = bs * b"\x00" for i in xrange(0, tail_offset, bs): prev = encrypter(strxor(data[i:i + bs], prev)) tail = data[tail_offset:] @@ -337,7 +339,7 @@ def mac_acpkm_master(algo_class, encrypter, key_section_size, section_size, bs, tail_offset = len(data) - bs else: tail_offset = len(data) - (len(data) % bs) - prev = bs * b'\x00' + prev = bs * b"\x00" sections = len(data) // section_size if len(data) % section_size != 0: sections += 1 @@ -346,17 +348,17 @@ def mac_acpkm_master(algo_class, encrypter, key_section_size, section_size, bs, encrypter, key_section_size, bs, - (KEY_SIZE + bs) * sections, + (KEYSIZE + bs) * sections, ) for i in xrange(0, tail_offset, bs): if i % section_size == 0: - keymat, keymats = keymats[:KEY_SIZE + bs], keymats[KEY_SIZE + bs:] - key, k1 = keymat[:KEY_SIZE], keymat[KEY_SIZE:] + keymat, keymats = keymats[:KEYSIZE + bs], keymats[KEYSIZE + bs:] + key, k1 = keymat[:KEYSIZE], keymat[KEYSIZE:] encrypter = algo_class(key).encrypt prev = encrypter(strxor(data[i:i + bs], prev)) tail = data[tail_offset:] if len(tail) == bs: - key, k1 = keymats[:KEY_SIZE], keymats[KEY_SIZE:] + key, k1 = keymats[:KEYSIZE], keymats[KEYSIZE:] encrypter = algo_class(key).encrypt k2 = long2bytes(bytes2long(k1) << 1, size=bs) if bytearray(k1)[0] & 0x80 != 0: @@ -365,3 +367,26 @@ def mac_acpkm_master(algo_class, encrypter, key_section_size, section_size, bs, strxor(pad3(tail, bs), prev), k1 if len(tail) == bs else k2, )) + + +def pad_iso10126(data, blocksize): + """ISO 10126 padding + + Does not exist in 34.13, but added for convenience. + It uses urandom call for getting the randomness. + """ + pad_len = blocksize - len(data) % blocksize + if pad_len == 0: + pad_len = blocksize + return b"".join((data, urandom(pad_len - 1), bytes((pad_len,)))) + + +def unpad_iso10126(data, blocksize): + """Unpad :py:func:`pygost.gost3413.pad_iso10126` + """ + if len(data) % blocksize != 0: + raise ValueError("Data length is not multiple of blocksize") + pad_len = bytearray(data)[-1] + if pad_len > blocksize: + raise ValueError("Padding length is bigger than blocksize") + return data[:-pad_len]