2 # PyGOST -- Pure Python GOST cryptographic functions library
3 # Copyright (C) 2015-2021 Sergey Matveev <stargrave@stargrave.org>
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU General Public License as published by
7 # the Free Software Foundation, version 3 of the License.
9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 # GNU General Public License for more details.
14 # You should have received a copy of the GNU General Public License
15 # along with this program. If not, see <http://www.gnu.org/licenses/>.
16 """GOST R 34.11-2012 (Streebog) hash function common files
18 This is implementation of :rfc:`6986`. Most function and variable names are
19 taken according to specification's terminology.
23 from struct import pack
24 from struct import unpack
26 from pygost.iface import PEP247
27 from pygost.utils import hexdec
28 from pygost.utils import strxor
29 from pygost.utils import xrange
34 252, 238, 221, 17, 207, 110, 49, 22, 251, 196, 250,
35 218, 35, 197, 4, 77, 233, 119, 240, 219, 147, 46,
36 153, 186, 23, 54, 241, 187, 20, 205, 95, 193, 249,
37 24, 101, 90, 226, 92, 239, 33, 129, 28, 60, 66,
38 139, 1, 142, 79, 5, 132, 2, 174, 227, 106, 143,
39 160, 6, 11, 237, 152, 127, 212, 211, 31, 235, 52,
40 44, 81, 234, 200, 72, 171, 242, 42, 104, 162, 253,
41 58, 206, 204, 181, 112, 14, 86, 8, 12, 118, 18,
42 191, 114, 19, 71, 156, 183, 93, 135, 21, 161, 150,
43 41, 16, 123, 154, 199, 243, 145, 120, 111, 157, 158,
44 178, 177, 50, 117, 25, 61, 255, 53, 138, 126, 109,
45 84, 198, 128, 195, 189, 13, 87, 223, 245, 36, 169,
46 62, 168, 67, 201, 215, 121, 214, 246, 124, 34, 185,
47 3, 224, 15, 236, 222, 122, 148, 176, 188, 220, 232,
48 40, 80, 78, 51, 10, 74, 167, 151, 96, 115, 30,
49 0, 98, 68, 26, 184, 56, 130, 100, 159, 38, 65,
50 173, 69, 70, 146, 39, 94, 85, 47, 140, 163, 165,
51 125, 105, 213, 149, 59, 7, 88, 179, 64, 134, 172,
52 29, 247, 48, 55, 107, 228, 136, 217, 231, 137, 225,
53 27, 131, 73, 76, 63, 248, 254, 141, 83, 170, 144,
54 202, 216, 133, 97, 32, 113, 103, 164, 45, 43, 9,
55 91, 203, 155, 37, 208, 190, 229, 108, 82, 89, 166,
56 116, 210, 230, 244, 180, 192, 209, 102, 175, 194, 57,
60 A = [unpack(">Q", hexdec(s))[0] for s in (
61 "8e20faa72ba0b470", "47107ddd9b505a38", "ad08b0e0c3282d1c", "d8045870ef14980e",
62 "6c022c38f90a4c07", "3601161cf205268d", "1b8e0b0e798c13c8", "83478b07b2468764",
63 "a011d380818e8f40", "5086e740ce47c920", "2843fd2067adea10", "14aff010bdd87508",
64 "0ad97808d06cb404", "05e23c0468365a02", "8c711e02341b2d01", "46b60f011a83988e",
65 "90dab52a387ae76f", "486dd4151c3dfdb9", "24b86a840e90f0d2", "125c354207487869",
66 "092e94218d243cba", "8a174a9ec8121e5d", "4585254f64090fa0", "accc9ca9328a8950",
67 "9d4df05d5f661451", "c0a878a0a1330aa6", "60543c50de970553", "302a1e286fc58ca7",
68 "18150f14b9ec46dd", "0c84890ad27623e0", "0642ca05693b9f70", "0321658cba93c138",
69 "86275df09ce8aaa8", "439da0784e745554", "afc0503c273aa42a", "d960281e9d1d5215",
70 "e230140fc0802984", "71180a8960409a42", "b60c05ca30204d21", "5b068c651810a89e",
71 "456c34887a3805b9", "ac361a443d1c8cd2", "561b0d22900e4669", "2b838811480723ba",
72 "9bcf4486248d9f5d", "c3e9224312c8c1a0", "effa11af0964ee50", "f97d86d98a327728",
73 "e4fa2054a80b329c", "727d102a548b194e", "39b008152acb8227", "9258048415eb419d",
74 "492c024284fbaec0", "aa16012142f35760", "550b8e9e21f7a530", "a48b474f9ef5dc18",
75 "70a6a56e2440598e", "3853dc371220a247", "1ca76e95091051ad", "0edd37c48a08a6d8",
76 "07e095624504536c", "8d70c431ac02a736", "c83862965601dd1b", "641c314b2b8ee083",
80 0, 8, 16, 24, 32, 40, 48, 56,
81 1, 9, 17, 25, 33, 41, 49, 57,
82 2, 10, 18, 26, 34, 42, 50, 58,
83 3, 11, 19, 27, 35, 43, 51, 59,
84 4, 12, 20, 28, 36, 44, 52, 60,
85 5, 13, 21, 29, 37, 45, 53, 61,
86 6, 14, 22, 30, 38, 46, 54, 62,
87 7, 15, 23, 31, 39, 47, 55, 63,
90 C = [hexdec("".join(s))[::-1] for s in (
92 "b1085bda1ecadae9ebcb2f81c0657c1f",
93 "2f6a76432e45d016714eb88d7585c4fc",
94 "4b7ce09192676901a2422a08a460d315",
95 "05767436cc744d23dd806559f2a64507",
98 "6fa3b58aa99d2f1a4fe39d460f70b5d7",
99 "f3feea720a232b9861d55e0f16b50131",
100 "9ab5176b12d699585cb561c2db0aa7ca",
101 "55dda21bd7cbcd56e679047021b19bb7",
104 "f574dcac2bce2fc70a39fc286a3d8435",
105 "06f15e5f529c1f8bf2ea7514b1297b7b",
106 "d3e20fe490359eb1c1c93a376062db09",
107 "c2b6f443867adb31991e96f50aba0ab2",
110 "ef1fdfb3e81566d2f948e1a05d71e4dd",
111 "488e857e335c3c7d9d721cad685e353f",
112 "a9d72c82ed03d675d8b71333935203be",
113 "3453eaa193e837f1220cbebc84e3d12e",
116 "4bea6bacad4747999a3f410c6ca92363",
117 "7f151c1f1686104a359e35d7800fffbd",
118 "bfcd1747253af5a3dfff00b723271a16",
119 "7a56a27ea9ea63f5601758fd7c6cfe57",
122 "ae4faeae1d3ad3d96fa4c33b7a3039c0",
123 "2d66c4f95142a46c187f9ab49af08ec6",
124 "cffaa6b71c9ab7b40af21f66c2bec6b6",
125 "bf71c57236904f35fa68407a46647d6e",
128 "f4c70e16eeaac5ec51ac86febf240954",
129 "399ec6c7e6bf87c9d3473e33197a93c9",
130 "0992abc52d822c3706476983284a0504",
131 "3517454ca23c4af38886564d3a14d493",
134 "9b1f5b424d93c9a703e7aa020c6e4141",
135 "4eb7f8719c36de1e89b4443b4ddbc49a",
136 "f4892bcb929b069069d18d2bd1a5c42f",
137 "36acc2355951a8d9a47f0dd4bf02e71e",
140 "378f5a541631229b944c9ad8ec165fde",
141 "3a7d3a1b258942243cd955b7e00d0984",
142 "800a440bdbb2ceb17b2b8a9aa6079c54",
143 "0e38dc92cb1f2a607261445183235adb",
146 "abbedea680056f52382ae548b2e4f3f3",
147 "8941e71cff8a78db1fffe18a1b336103",
148 "9fe76702af69334b7a1e6c303b7652f4",
149 "3698fad1153bb6c374b4c7fb98459ced",
152 "7bcd9ed0efc889fb3002c6cd635afe94",
153 "d8fa6bbbebab07612001802114846679",
154 "8a1d71efea48b9caefbacd1d7d476e98",
155 "dea2594ac06fd85d6bcaa4cd81f32d1b",
158 "378ee767f11631bad21380b00449b17a",
159 "cda43c32bcdf1d77f82012d430219f9b",
160 "5d80ef9d1891cc86e71da4aa88e12852",
161 "faf417d5d9b21b9948bc924af11bd720",
165 # Trade memory for CPU for part of L() calculations
171 if _Cache is not None:
174 for byteN in xrange(8):
175 cache.append([0 for _ in xrange(256)])
176 for byteN in xrange(8):
177 for byteVal in xrange(256):
180 for bitN in xrange(8):
182 res64 ^= A[(7 - byteN) * 8 + bitN]
184 cache[byteN][byteVal] = res64
189 """Add two 512 integers
196 cb = a[i] + b[i] + (cb >> 8)
202 res = E(LPS(strxor(hsh[:8], pack("<Q", n)) + hsh[8:]), msg)
203 return strxor(strxor(res, hsh), msg)
208 msg = LPS(strxor(k, msg))
209 k = LPS(strxor(k, C[i]))
210 return strxor(k, msg)
214 return L(PS(bytearray(data)))
218 res = bytearray(BLOCKSIZE)
219 for i in range(BLOCKSIZE):
220 res[Tau[i]] = Pi[data[i]]
230 res64 ^= _Cache[j][data[8 * i + j]]
231 res.append(pack("<Q", res64))
235 class GOST34112012(PEP247):
236 """GOST 34.11-2012 big-endian hash
238 >>> m = GOST34112012(digest_size=32)
242 'e3c9fd89226d93b489a9fe27d686806e24a514e3787bca053c698ec4616ceb78'
244 block_size = BLOCKSIZE
246 def __init__(self, data=b"", digest_size=64):
248 :param digest_size: hash digest size to compute
249 :type digest_size: 32 or 64 bytes
252 self._digest_size = digest_size
255 return GOST34112012(copy(self.data), self.digest_size)
258 def digest_size(self):
259 return self._digest_size
261 def update(self, data):
262 """Append data that has to be hashed
267 """Get hash of the provided data
269 hsh = BLOCKSIZE * (b"\x01" if self.digest_size == 32 else b"\x00")
270 chk = bytearray(BLOCKSIZE * b"\x00")
273 for i in xrange(0, len(data) // BLOCKSIZE * BLOCKSIZE, BLOCKSIZE):
274 block = data[i:i + BLOCKSIZE]
275 hsh = g(n, hsh, block)
276 chk = add512bit(chk, block)
280 padblock_size = len(data) * 8 - n
282 padlen = BLOCKSIZE - len(data) % BLOCKSIZE
283 if padlen != BLOCKSIZE:
284 data += b"\x00" * padlen
286 hsh = g(n, hsh, data[-BLOCKSIZE:])
288 chk = add512bit(chk, data[-BLOCKSIZE:])
289 hsh = g(0, hsh, pack("<Q", n) + 56 * b"\x00")
291 return hsh[-self._digest_size:]