# coding: utf-8
# PyGOST -- Pure Python GOST cryptographic functions library
-# Copyright (C) 2015-2016 Sergey Matveev <stargrave@stargrave.org>
+# Copyright (C) 2015-2021 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
-# 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
#
# 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.11-2012 (Streebog) hash function common files
+"""GOST R 34.11-2012 (Streebog) hash function common files
This is implementation of :rfc:`6986`. Most function and variable names are
taken according to specification's terminology.
from pygost.iface import PEP247
from pygost.utils import hexdec
-from pygost.utils import hexenc
from pygost.utils import strxor
from pygost.utils import xrange
))
A = [unpack(">Q", hexdec(s))[0] for s in (
- "8e20faa72ba0b470", "47107ddd9b505a38", "ad08b0e0c3282d1c", "d8045870ef14980e",
- "6c022c38f90a4c07", "3601161cf205268d", "1b8e0b0e798c13c8", "83478b07b2468764",
- "a011d380818e8f40", "5086e740ce47c920", "2843fd2067adea10", "14aff010bdd87508",
- "0ad97808d06cb404", "05e23c0468365a02", "8c711e02341b2d01", "46b60f011a83988e",
- "90dab52a387ae76f", "486dd4151c3dfdb9", "24b86a840e90f0d2", "125c354207487869",
- "092e94218d243cba", "8a174a9ec8121e5d", "4585254f64090fa0", "accc9ca9328a8950",
- "9d4df05d5f661451", "c0a878a0a1330aa6", "60543c50de970553", "302a1e286fc58ca7",
- "18150f14b9ec46dd", "0c84890ad27623e0", "0642ca05693b9f70", "0321658cba93c138",
- "86275df09ce8aaa8", "439da0784e745554", "afc0503c273aa42a", "d960281e9d1d5215",
- "e230140fc0802984", "71180a8960409a42", "b60c05ca30204d21", "5b068c651810a89e",
- "456c34887a3805b9", "ac361a443d1c8cd2", "561b0d22900e4669", "2b838811480723ba",
- "9bcf4486248d9f5d", "c3e9224312c8c1a0", "effa11af0964ee50", "f97d86d98a327728",
- "e4fa2054a80b329c", "727d102a548b194e", "39b008152acb8227", "9258048415eb419d",
- "492c024284fbaec0", "aa16012142f35760", "550b8e9e21f7a530", "a48b474f9ef5dc18",
- "70a6a56e2440598e", "3853dc371220a247", "1ca76e95091051ad", "0edd37c48a08a6d8",
- "07e095624504536c", "8d70c431ac02a736", "c83862965601dd1b", "641c314b2b8ee083",
+ "8e20faa72ba0b470", "47107ddd9b505a38", "ad08b0e0c3282d1c", "d8045870ef14980e",
+ "6c022c38f90a4c07", "3601161cf205268d", "1b8e0b0e798c13c8", "83478b07b2468764",
+ "a011d380818e8f40", "5086e740ce47c920", "2843fd2067adea10", "14aff010bdd87508",
+ "0ad97808d06cb404", "05e23c0468365a02", "8c711e02341b2d01", "46b60f011a83988e",
+ "90dab52a387ae76f", "486dd4151c3dfdb9", "24b86a840e90f0d2", "125c354207487869",
+ "092e94218d243cba", "8a174a9ec8121e5d", "4585254f64090fa0", "accc9ca9328a8950",
+ "9d4df05d5f661451", "c0a878a0a1330aa6", "60543c50de970553", "302a1e286fc58ca7",
+ "18150f14b9ec46dd", "0c84890ad27623e0", "0642ca05693b9f70", "0321658cba93c138",
+ "86275df09ce8aaa8", "439da0784e745554", "afc0503c273aa42a", "d960281e9d1d5215",
+ "e230140fc0802984", "71180a8960409a42", "b60c05ca30204d21", "5b068c651810a89e",
+ "456c34887a3805b9", "ac361a443d1c8cd2", "561b0d22900e4669", "2b838811480723ba",
+ "9bcf4486248d9f5d", "c3e9224312c8c1a0", "effa11af0964ee50", "f97d86d98a327728",
+ "e4fa2054a80b329c", "727d102a548b194e", "39b008152acb8227", "9258048415eb419d",
+ "492c024284fbaec0", "aa16012142f35760", "550b8e9e21f7a530", "a48b474f9ef5dc18",
+ "70a6a56e2440598e", "3853dc371220a247", "1ca76e95091051ad", "0edd37c48a08a6d8",
+ "07e095624504536c", "8d70c431ac02a736", "c83862965601dd1b", "641c314b2b8ee083",
)]
Tau = (
)]
+def _lcache():
+ cache = []
+ for byteN in xrange(8):
+ cache.append([0 for _ in xrange(256)])
+ for byteN in xrange(8):
+ for byteVal in xrange(256):
+ res64 = 0
+ val = byteVal
+ for bitN in xrange(8):
+ if val & 0x80 > 0:
+ res64 ^= A[(7 - byteN) * 8 + bitN]
+ val <<= 1
+ cache[byteN][byteVal] = res64
+ return cache
+
+
+# Trade memory for CPU for part of L() calculations
+LCache = _lcache()
+
+
def add512bit(a, b):
- """ Add two 512 integers
+ """Add two 512 integers
"""
a = bytearray(a)
b = bytearray(b)
def L(data):
res = []
for i in range(8):
- val = unpack("<Q", data[i * 8:i * 8 + 8])[0]
res64 = 0
- for j in range(BLOCKSIZE):
- if val & 0x8000000000000000:
- res64 ^= A[j]
- val <<= 1
+ for j in range(8):
+ res64 ^= LCache[j][data[8 * i + j]]
res.append(pack("<Q", res64))
return b"".join(res)
class GOST34112012(PEP247):
- """ GOST 34.11-2012 big-endian hash
+ """GOST 34.11-2012 big-endian hash
>>> m = GOST34112012(digest_size=32)
>>> m.update("foo")
return self._digest_size
def update(self, data):
- """ Append data that has to be hashed
+ """Append data that has to be hashed
"""
self.data += data
def digest(self):
- """ Get hash of the provided data
+ """Get hash of the provided data
"""
hsh = BLOCKSIZE * (b"\x01" if self.digest_size == 32 else b"\x00")
chk = bytearray(BLOCKSIZE * b"\x00")