]> Cypherpunks.ru repositories - pygost.git/blob - pygost/gost28147_mac.py
Consistent source code quote symbols
[pygost.git] / pygost / gost28147_mac.py
1 # coding: utf-8
2 # PyGOST -- Pure Python GOST cryptographic functions library
3 # Copyright (C) 2015-2016 Sergey Matveev <stargrave@stargrave.org>
4 #
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, either version 3 of the License, or
8 # (at your option) any later version.
9 #
10 # This program is distributed in the hope that it will be useful,
11 # but WITHOUT ANY WARRANTY; without even the implied warranty of
12 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 # GNU General Public License for more details.
14 #
15 # You should have received a copy of the GNU General Public License
16 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
17 """ GOST 28147-89 MAC
18 """
19
20 from copy import copy
21
22 from pygost.gost28147 import block2ns
23 from pygost.gost28147 import BLOCKSIZE
24 from pygost.gost28147 import DEFAULT_SBOX
25 from pygost.gost28147 import ns2block
26 from pygost.gost28147 import validate_iv
27 from pygost.gost28147 import validate_key
28 from pygost.gost28147 import validate_sbox
29 from pygost.gost28147 import xcrypt
30 from pygost.gost3413 import pad1
31 from pygost.iface import PEP247
32 from pygost.utils import hexenc
33 from pygost.utils import strxor
34 from pygost.utils import xrange
35
36 digest_size = 8
37 SEQ_MAC = (
38     0, 1, 2, 3, 4, 5, 6, 7,
39     0, 1, 2, 3, 4, 5, 6, 7,
40 )
41
42
43 class MAC(PEP247):
44     """ GOST 28147-89 MAC mode of operation
45
46     >>> m = MAC(key=key)
47     >>> m.update("some data")
48     >>> m.update("another data")
49     >>> m.hexdigest()[:8]
50     'a687a08b'
51     """
52     digest_size = digest_size
53
54     def __init__(self, key, data=b"", iv=8 * b"\x00", sbox=DEFAULT_SBOX):
55         """
56         :param key: authentication key
57         :type key: bytes, 32 bytes
58         :param iv: initialization vector
59         :type iv: bytes, BLOCKSIZE length
60         :param sbox: S-box parameters to use
61         :type sbox: str, SBOXES'es key
62         """
63         validate_key(key)
64         validate_iv(iv)
65         validate_sbox(sbox)
66         self.key = key
67         self.data = data
68         self.iv = iv
69         self.sbox = sbox
70
71     def copy(self):
72         return MAC(self.key, copy(self.data), self.iv, self.sbox)
73
74     def update(self, data):
75         """ Append data that has to be authenticated
76         """
77         self.data += data
78
79     def digest(self):
80         """ Get MAC tag of supplied data
81
82         You have to provide at least single byte of data.
83         If you want to produce tag length of 3 bytes, then
84         ``digest()[:3]``.
85         """
86         if not self.data:
87             raise ValueError("No data processed")
88         data = pad1(self.data, BLOCKSIZE)
89         prev = block2ns(self.iv)[::-1]
90         for i in xrange(0, len(data), BLOCKSIZE):
91             prev = xcrypt(
92                 SEQ_MAC, self.sbox, self.key, block2ns(strxor(
93                     data[i:i + BLOCKSIZE],
94                     ns2block(prev),
95                 )),
96             )[::-1]
97         return ns2block(prev)
98
99     def hexdigest(self):
100         return hexenc(self.digest())
101
102
103 def new(key, data=b"", iv=8 * b"\x00", sbox=DEFAULT_SBOX):
104     return MAC(key, data, iv, sbox)