]> Cypherpunks.ru repositories - pygost.git/blob - pygost/utils.py
Raise copyright years
[pygost.git] / pygost / utils.py
1 # coding: utf-8
2 # PyGOST -- Pure Python GOST cryptographic functions library
3 # Copyright (C) 2015-2019 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
18 from codecs import getdecoder
19 from codecs import getencoder
20 from sys import version_info
21
22
23 xrange = range if version_info[0] == 3 else xrange  # pylint: disable=redefined-builtin
24
25
26 def strxor(a, b):
27     """ XOR of two strings
28
29     This function will process only shortest length of both strings,
30     ignoring remaining one.
31     """
32     mlen = min(len(a), len(b))
33     a, b, xor = bytearray(a), bytearray(b), bytearray(mlen)
34     for i in xrange(mlen):
35         xor[i] = a[i] ^ b[i]
36     return bytes(xor)
37
38
39 _hexdecoder = getdecoder("hex")
40 _hexencoder = getencoder("hex")
41
42
43 def hexdec(data):
44     """Decode hexadecimal
45     """
46     return _hexdecoder(data)[0]
47
48
49 def hexenc(data):
50     """Encode hexadecimal
51     """
52     return _hexencoder(data)[0].decode("ascii")
53
54
55 def bytes2long(raw):
56     """ Deserialize big-endian bytes into long number
57
58     :param bytes raw: binary string
59     :returns: deserialized long number
60     :rtype: int
61     """
62     return int(hexenc(raw), 16)
63
64
65 def long2bytes(n, size=32):
66     """ Serialize long number into big-endian bytestring
67
68     :param long n: long number
69     :returns: serialized bytestring
70     :rtype: bytes
71     """
72     res = hex(int(n))[2:].rstrip("L")
73     if len(res) % 2 != 0:
74         res = "0" + res
75     s = hexdec(res)
76     if len(s) != size:
77         s = (size - len(s)) * b"\x00" + s
78     return s
79
80
81 def modinvert(a, n):
82     """ Modular multiplicative inverse
83
84     :returns: inverse number. -1 if it does not exist
85
86     Realization is taken from:
87     https://en.wikipedia.org/wiki/Extended_Euclidean_algorithm
88     """
89     if a < 0:
90         # k^-1 = p - (-k)^-1 mod p
91         return n - modinvert(-a, n)
92     t, newt = 0, 1
93     r, newr = n, a
94     while newr != 0:
95         quotinent = r // newr
96         t, newt = newt, t - quotinent * newt
97         r, newr = newr, r - quotinent * newr
98     if r > 1:
99         return -1
100     if t < 0:
101         t = t + n
102     return t