# coding: utf-8
# PyGOST -- Pure Python GOST cryptographic functions library
-# Copyright (C) 2015-2020 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
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
-""" 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):
"""
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)
])
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
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:]
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
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:
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]