+3.8:
+ * 34.11-2012 based PBKDF2 function added
+
3.7:
Fixed 34.13-2015 OFB bug with IVs longer than 2 blocks.
* GOST R 34.11-94 hash function (RFC 5831)
* GOST R 34.11-94 based PBKDF2 function
* GOST R 34.11-2012 Стрибог (Streebog) hash function (RFC 6986)
+* GOST R 34.11-2012 based PBKDF2 function (Р 50.1.111-2016)
* GOST R 34.10-2001 (RFC 5832) public key signature function
* GOST R 34.10-2012 (RFC 7091) public key signature function
* various 34.10 curve parameters included
"""
from pygost.gost34112012 import GOST34112012
+from pygost.pbkdf2 import pbkdf2 as pbkdf2_base
class GOST34112012512(GOST34112012):
def new(data=b''):
return GOST34112012512(data)
+
+
+def pbkdf2(password, salt, iterations, dklen):
+ return pbkdf2_base(GOST34112012512, password, salt, iterations, dklen)
"""
from copy import copy
+from functools import partial
from struct import pack
from pygost.gost28147 import addmod
from pygost.gost28147 import ns2block
from pygost.gost28147 import validate_sbox
from pygost.iface import PEP247
-from pygost.utils import bytes2long
+from pygost.pbkdf2 import pbkdf2 as pbkdf2_base
from pygost.utils import hexdec
from pygost.utils import hexenc
-from pygost.utils import long2bytes
from pygost.utils import strxor
from pygost.utils import xrange # pylint: disable=redefined-builtin
return GOST341194(data, sbox)
-# This implementation is based on Python 3.5.2 source code's one.
-# PyGOST does not register itself in hashlib anyway, so use it instead.
-def pbkdf2(password, salt, iterations, dklen):
- """PBKDF2 implementation for GOST R 34.11-94
+PBKDF2_HASHER = partial(GOST341194, sbox="GostR3411_94_CryptoProParamSet")
- Based on http://tc26.ru/methods/containers_v1/Addition_to_PKCS5_v1_0.pdf
- """
- inner = GOST341194(sbox="GostR3411_94_CryptoProParamSet")
- outer = GOST341194(sbox="GostR3411_94_CryptoProParamSet")
- password = password + b"\x00" * (inner.block_size - len(password))
- inner.update(strxor(password, len(password) * b"\x36"))
- outer.update(strxor(password, len(password) * b"\x5C"))
-
- def prf(msg):
- icpy = inner.copy()
- ocpy = outer.copy()
- icpy.update(msg)
- ocpy.update(icpy.digest())
- return ocpy.digest()
-
- dkey = b''
- loop = 1
- while len(dkey) < dklen:
- prev = prf(salt + long2bytes(loop, 4))
- rkey = bytes2long(prev)
- for _ in xrange(iterations - 1):
- prev = prf(prev)
- rkey ^= bytes2long(prev)
- loop += 1
- dkey += long2bytes(rkey, inner.digest_size)
- return dkey[:dklen]
+
+def pbkdf2(password, salt, iterations, dklen):
+ return pbkdf2_base(PBKDF2_HASHER, password, salt, iterations, dklen)
--- /dev/null
+# coding: utf-8
+""" PBKDF2 implementation suitable for GOST R 34.11-94/34.11-2012.
+
+This implementation is based on Python 3.5.2 source code's one.
+PyGOST does not register itself in hashlib anyway, so use it instead.
+"""
+
+
+from pygost.utils import bytes2long
+from pygost.utils import long2bytes
+from pygost.utils import strxor
+from pygost.utils import xrange # pylint: disable=redefined-builtin
+
+
+def pbkdf2(hasher, password, salt, iterations, dklen):
+ """PBKDF2 implementation suitable for GOST R 34.11-94/34.11-2012
+ """
+ inner = hasher()
+ outer = hasher()
+ password = password + b"\x00" * (inner.block_size - len(password))
+ inner.update(strxor(password, len(password) * b"\x36"))
+ outer.update(strxor(password, len(password) * b"\x5C"))
+
+ def prf(msg):
+ icpy = inner.copy()
+ ocpy = outer.copy()
+ icpy.update(msg)
+ ocpy.update(icpy.digest())
+ return ocpy.digest()
+
+ dkey = b''
+ loop = 1
+ while len(dkey) < dklen:
+ prev = prf(salt + long2bytes(loop, 4))
+ rkey = bytes2long(prev)
+ for _ in xrange(iterations - 1):
+ prev = prf(prev)
+ rkey ^= bytes2long(prev)
+ loop += 1
+ dkey += long2bytes(rkey, inner.digest_size)
+ return dkey[:dklen]
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
+from unittest import skip
from unittest import TestCase
import hmac
from pygost import gost34112012512
from pygost.gost34112012256 import GOST34112012256
from pygost.gost34112012512 import GOST34112012512
+from pygost.gost34112012512 import pbkdf2
from pygost.utils import hexdec
+from pygost.utils import hexenc
class TestCopy(TestCase):
GOST34112012256(m).digest(),
hexdec("508f7e553c06501d749a66fc28c6cac0b005746d97537fa85d9e40904efed29d")[::-1]
)
+
+
+class TestPBKDF2(TestCase):
+ """http://tc26.ru/.../R_50.1.111-2016.pdf
+ """
+ def test_1(self):
+ self.assertEqual(
+ hexenc(pbkdf2(b"password", b"salt", 1, 64)),
+ "64770af7f748c3b1c9ac831dbcfd85c26111b30a8a657ddc3056b80ca73e040d2854fd36811f6d825cc4ab66ec0a68a490a9e5cf5156b3a2b7eecddbf9a16b47",
+ )
+
+ def test_2(self):
+ self.assertEqual(
+ hexenc(pbkdf2(b"password", b"salt", 2, 64)),
+ "5a585bafdfbb6e8830d6d68aa3b43ac00d2e4aebce01c9b31c2caed56f0236d4d34b2b8fbd2c4e89d54d46f50e47d45bbac301571743119e8d3c42ba66d348de",
+ )
+
+ def test_3(self):
+ self.assertEqual(
+ hexenc(pbkdf2(b"password", b"salt", 4096, 64)),
+ "e52deb9a2d2aaff4e2ac9d47a41f34c20376591c67807f0477e32549dc341bc7867c09841b6d58e29d0347c996301d55df0d34e47cf68f4e3c2cdaf1d9ab86c3",
+ )
+
+ @skip("it takes too long")
+ def test_4(self):
+ self.assertEqual(
+ hexenc(pbkdf2(b"password", b"salt", 1677216, 64)),
+ "49e4843bba76e300afe24c4d23dc7392def12f2c0e244172367cd70a8982ac361adb601c7e2a314e8cb7b1e9df840e36ab5615be5d742b6cf203fb55fdc48071",
+ )
+
+ def test_5(self):
+ self.assertEqual(
+ hexenc(pbkdf2(
+ b"passwordPASSWORDpassword",
+ b"saltSALTsaltSALTsaltSALTsaltSALTsalt",
+ 4096,
+ 100,
+ )),
+ "b2d8f1245fc4d29274802057e4b54e0a0753aa22fc53760b301cf008679e58fe4bee9addcae99ba2b0b20f431a9c5e50f395c89387d0945aedeca6eb4015dfc2bd2421ee9bb71183ba882ceebfef259f33f9e27dc6178cb89dc37428cf9cc52a2baa2d3a",
+ )
+
+ def test_6(self):
+ self.assertEqual(
+ hexenc(pbkdf2(b"pass\x00word", b"sa\x00lt", 4096, 64)),
+ "50df062885b69801a3c10248eb0a27ab6e522ffeb20c991c660f001475d73a4e167f782c18e97e92976d9c1d970831ea78ccb879f67068cdac1910740844e830",
+ )
@item GOST R 34.11-94 based @url{https://en.wikipedia.org/wiki/PBKDF2, PBKDF2} function
@item GOST R 34.11-2012 Стрибог (Streebog) hash function
(@url{https://tools.ietf.org/html/rfc6986.html, RFC 6986})
+@item GOST R 34.11-2012 based PBKDF2 function (Р 50.1.111-2016)
@item GOST R 34.10-2001
(@url{https://tools.ietf.org/html/rfc5832.html, RFC 5832})
public key signature function
@unnumbered News
@table @strong
+@item 3.8
+ @itemize
+ @item 34.11-2012 based PBKDF2 function added
+ @end itemize
+
@item 3.7
Fixed 34.13-2015 OFB bug with IVs longer than 2 blocks.
Preferable way is to download tarball with the signature:
@verbatim
-% wget http://pygost.cypherpunks.ru/pygost-3.7.tar.xz
-% wget http://pygost.cypherpunks.ru/pygost-3.7.tar.xz.sig
-% gpg --verify pygost-3.7.tar.xz.sig pygost-3.7.tar.xz
-% xz -d < pygost-3.7.tar.xz | tar xf -
-% cd pygost-3.7
+% wget http://pygost.cypherpunks.ru/pygost-3.8.tar.xz
+% wget http://pygost.cypherpunks.ru/pygost-3.8.tar.xz.sig
+% gpg --verify pygost-3.8.tar.xz.sig pygost-3.8.tar.xz
+% xz -d < pygost-3.8.tar.xz | tar xf -
+% cd pygost-3.8
% python setup.py install
@end verbatim