aboutsummaryrefslogtreecommitdiff
path: root/frozen_deps
diff options
context:
space:
mode:
authorDeterminant <[email protected]>2020-11-17 18:47:40 -0500
committerDeterminant <[email protected]>2020-11-17 18:47:40 -0500
commit3bef51eec2299403467e621ae660cef3f9256ac8 (patch)
tree9b72aaa95fb6dffacd8b20164699870a32ab6825 /frozen_deps
parent92b8b8e9628cac41d37226416107adc76b10e01b (diff)
update frozen deps
Diffstat (limited to 'frozen_deps')
-rw-r--r--frozen_deps/Crypto/Cipher/AES.py115
-rw-r--r--frozen_deps/Crypto/Cipher/ARC2.py130
-rw-r--r--frozen_deps/Crypto/Cipher/ARC4.py120
-rw-r--r--frozen_deps/Crypto/Cipher/Blowfish.py121
-rw-r--r--frozen_deps/Crypto/Cipher/CAST.py123
-rw-r--r--frozen_deps/Crypto/Cipher/DES.py118
-rw-r--r--frozen_deps/Crypto/Cipher/DES3.py133
-rw-r--r--frozen_deps/Crypto/Cipher/PKCS1_OAEP.py255
-rw-r--r--frozen_deps/Crypto/Cipher/PKCS1_v1_5.py226
-rw-r--r--frozen_deps/Crypto/Cipher/XOR.py86
-rwxr-xr-xfrozen_deps/Crypto/Cipher/_AES.cpython-38-x86_64-linux-gnu.sobin0 -> 43640 bytes
-rwxr-xr-xfrozen_deps/Crypto/Cipher/_ARC2.cpython-38-x86_64-linux-gnu.sobin0 -> 26904 bytes
-rwxr-xr-xfrozen_deps/Crypto/Cipher/_ARC4.cpython-38-x86_64-linux-gnu.sobin0 -> 18064 bytes
-rwxr-xr-xfrozen_deps/Crypto/Cipher/_Blowfish.cpython-38-x86_64-linux-gnu.sobin0 -> 35368 bytes
-rwxr-xr-xfrozen_deps/Crypto/Cipher/_CAST.cpython-38-x86_64-linux-gnu.sobin0 -> 35320 bytes
-rwxr-xr-xfrozen_deps/Crypto/Cipher/_DES.cpython-38-x86_64-linux-gnu.sobin0 -> 68560 bytes
-rwxr-xr-xfrozen_deps/Crypto/Cipher/_DES3.cpython-38-x86_64-linux-gnu.sobin0 -> 68560 bytes
-rwxr-xr-xfrozen_deps/Crypto/Cipher/_XOR.cpython-38-x86_64-linux-gnu.sobin0 -> 18096 bytes
-rw-r--r--frozen_deps/Crypto/Cipher/__init__.py83
-rw-r--r--frozen_deps/Crypto/Cipher/blockalgo.py296
-rw-r--r--frozen_deps/Crypto/Hash/HMAC.py212
-rw-r--r--frozen_deps/Crypto/Hash/MD2.py91
-rw-r--r--frozen_deps/Crypto/Hash/MD4.py91
-rw-r--r--frozen_deps/Crypto/Hash/MD5.py97
-rw-r--r--frozen_deps/Crypto/Hash/RIPEMD.py94
-rw-r--r--frozen_deps/Crypto/Hash/SHA.py98
-rw-r--r--frozen_deps/Crypto/Hash/SHA224.py95
-rw-r--r--frozen_deps/Crypto/Hash/SHA256.py95
-rw-r--r--frozen_deps/Crypto/Hash/SHA384.py96
-rw-r--r--frozen_deps/Crypto/Hash/SHA512.py95
-rwxr-xr-xfrozen_deps/Crypto/Hash/_MD2.cpython-38-x86_64-linux-gnu.sobin0 -> 18464 bytes
-rwxr-xr-xfrozen_deps/Crypto/Hash/_MD4.cpython-38-x86_64-linux-gnu.sobin0 -> 18552 bytes
-rwxr-xr-xfrozen_deps/Crypto/Hash/_RIPEMD160.cpython-38-x86_64-linux-gnu.sobin0 -> 22888 bytes
-rwxr-xr-xfrozen_deps/Crypto/Hash/_SHA224.cpython-38-x86_64-linux-gnu.sobin0 -> 18496 bytes
-rwxr-xr-xfrozen_deps/Crypto/Hash/_SHA256.cpython-38-x86_64-linux-gnu.sobin0 -> 18496 bytes
-rwxr-xr-xfrozen_deps/Crypto/Hash/_SHA384.cpython-38-x86_64-linux-gnu.sobin0 -> 22592 bytes
-rwxr-xr-xfrozen_deps/Crypto/Hash/_SHA512.cpython-38-x86_64-linux-gnu.sobin0 -> 22592 bytes
-rw-r--r--frozen_deps/Crypto/Hash/__init__.py56
-rw-r--r--frozen_deps/Crypto/Hash/hashalgo.py116
-rw-r--r--frozen_deps/Crypto/Protocol/AllOrNothing.py320
-rw-r--r--frozen_deps/Crypto/Protocol/Chaffing.py245
-rw-r--r--frozen_deps/Crypto/Protocol/KDF.py123
-rw-r--r--frozen_deps/Crypto/Protocol/__init__.py41
-rw-r--r--frozen_deps/Crypto/PublicKey/DSA.py379
-rw-r--r--frozen_deps/Crypto/PublicKey/ElGamal.py373
-rw-r--r--frozen_deps/Crypto/PublicKey/RSA.py719
-rw-r--r--frozen_deps/Crypto/PublicKey/_DSA.py115
-rw-r--r--frozen_deps/Crypto/PublicKey/_RSA.py81
-rw-r--r--frozen_deps/Crypto/PublicKey/__init__.py41
-rwxr-xr-xfrozen_deps/Crypto/PublicKey/_fastmath.cpython-38-x86_64-linux-gnu.sobin0 -> 78864 bytes
-rw-r--r--frozen_deps/Crypto/PublicKey/_slowmath.py187
-rw-r--r--frozen_deps/Crypto/PublicKey/pubkey.py240
-rw-r--r--frozen_deps/Crypto/Random/Fortuna/FortunaAccumulator.py171
-rw-r--r--frozen_deps/Crypto/Random/Fortuna/FortunaGenerator.py132
-rw-r--r--frozen_deps/Crypto/Random/Fortuna/SHAd256.py98
-rw-r--r--frozen_deps/Crypto/Random/Fortuna/__init__.py0
-rw-r--r--frozen_deps/Crypto/Random/OSRNG/__init__.py40
-rw-r--r--frozen_deps/Crypto/Random/OSRNG/fallback.py46
-rw-r--r--frozen_deps/Crypto/Random/OSRNG/posix.py86
-rw-r--r--frozen_deps/Crypto/Random/OSRNG/rng_base.py88
-rw-r--r--frozen_deps/Crypto/Random/_UserFriendlyRNG.py230
-rw-r--r--frozen_deps/Crypto/Random/__init__.py43
-rw-r--r--frozen_deps/Crypto/Random/random.py142
-rw-r--r--frozen_deps/Crypto/Signature/PKCS1_PSS.py355
-rw-r--r--frozen_deps/Crypto/Signature/PKCS1_v1_5.py236
-rw-r--r--frozen_deps/Crypto/Signature/__init__.py31
-rw-r--r--frozen_deps/Crypto/Util/Counter.py127
-rw-r--r--frozen_deps/Crypto/Util/RFC1751.py365
-rw-r--r--frozen_deps/Crypto/Util/__init__.py37
-rwxr-xr-xfrozen_deps/Crypto/Util/_counter.cpython-38-x86_64-linux-gnu.sobin0 -> 22856 bytes
-rw-r--r--frozen_deps/Crypto/Util/_number_new.py119
-rw-r--r--frozen_deps/Crypto/Util/asn1.py286
-rw-r--r--frozen_deps/Crypto/Util/number.py1456
-rw-r--r--frozen_deps/Crypto/Util/py3compat.py107
-rw-r--r--frozen_deps/Crypto/Util/randpool.py82
-rwxr-xr-xfrozen_deps/Crypto/Util/strxor.cpython-38-x86_64-linux-gnu.sobin0 -> 16784 bytes
-rw-r--r--frozen_deps/Crypto/Util/winrandom.py28
-rw-r--r--frozen_deps/Crypto/__init__.py51
-rw-r--r--frozen_deps/Crypto/pct_warnings.py60
-rwxr-xr-xfrozen_deps/_pysha3.cpython-38-x86_64-linux-gnu.sobin0 -> 517664 bytes
-rw-r--r--frozen_deps/base58-2.0.1.dist-info/COPYING19
-rw-r--r--frozen_deps/base58-2.0.1.dist-info/INSTALLER1
-rw-r--r--frozen_deps/base58-2.0.1.dist-info/METADATA20
-rw-r--r--frozen_deps/base58-2.0.1.dist-info/RECORD13
-rw-r--r--frozen_deps/base58-2.0.1.dist-info/WHEEL5
-rw-r--r--frozen_deps/base58-2.0.1.dist-info/entry_points.txt3
-rw-r--r--frozen_deps/base58-2.0.1.dist-info/top_level.txt1
-rw-r--r--frozen_deps/base58/__init__.py130
-rw-r--r--frozen_deps/base58/__main__.py47
-rw-r--r--frozen_deps/base58/py.typed1
-rw-r--r--frozen_deps/bech32.py123
-rwxr-xr-xfrozen_deps/bin/base588
-rwxr-xr-xfrozen_deps/bin/keytree.py290
-rw-r--r--frozen_deps/ecdsa-0.16.1.dist-info/INSTALLER1
-rw-r--r--frozen_deps/ecdsa-0.16.1.dist-info/LICENSE24
-rw-r--r--frozen_deps/ecdsa-0.16.1.dist-info/METADATA626
-rw-r--r--frozen_deps/ecdsa-0.16.1.dist-info/RECORD52
-rw-r--r--frozen_deps/ecdsa-0.16.1.dist-info/WHEEL6
-rw-r--r--frozen_deps/ecdsa-0.16.1.dist-info/top_level.txt1
-rw-r--r--frozen_deps/ecdsa/__init__.py76
-rw-r--r--frozen_deps/ecdsa/_compat.py60
-rw-r--r--frozen_deps/ecdsa/_rwlock.py86
-rw-r--r--frozen_deps/ecdsa/_version.py21
-rw-r--r--frozen_deps/ecdsa/curves.py194
-rw-r--r--frozen_deps/ecdsa/der.py409
-rw-r--r--frozen_deps/ecdsa/ecdh.py327
-rw-r--r--frozen_deps/ecdsa/ecdsa.py754
-rw-r--r--frozen_deps/ecdsa/ellipticcurve.py847
-rw-r--r--frozen_deps/ecdsa/keys.py1453
-rw-r--r--frozen_deps/ecdsa/numbertheory.py810
-rw-r--r--frozen_deps/ecdsa/rfc6979.py110
-rw-r--r--frozen_deps/ecdsa/test_der.py397
-rw-r--r--frozen_deps/ecdsa/test_ecdh.py370
-rw-r--r--frozen_deps/ecdsa/test_ecdsa.py538
-rw-r--r--frozen_deps/ecdsa/test_ellipticcurve.py200
-rw-r--r--frozen_deps/ecdsa/test_jacobi.py438
-rw-r--r--frozen_deps/ecdsa/test_keys.py454
-rw-r--r--frozen_deps/ecdsa/test_malformed_sigs.py350
-rw-r--r--frozen_deps/ecdsa/test_numbertheory.py326
-rw-r--r--frozen_deps/ecdsa/test_pyecdsa.py1989
-rw-r--r--frozen_deps/ecdsa/test_rw_lock.py177
-rw-r--r--frozen_deps/ecdsa/util.py435
-rw-r--r--frozen_deps/keytree.py-0.2.dist-info/INSTALLER1
-rw-r--r--frozen_deps/keytree.py-0.2.dist-info/METADATA18
-rw-r--r--frozen_deps/keytree.py-0.2.dist-info/RECORD10
-rw-r--r--frozen_deps/keytree.py-0.2.dist-info/WHEEL5
-rw-r--r--frozen_deps/keytree.py-0.2.dist-info/direct_url.json1
-rw-r--r--frozen_deps/keytree.py-0.2.dist-info/top_level.txt1
-rw-r--r--frozen_deps/mnemonic-0.19.dist-info/AUTHORS2
-rw-r--r--frozen_deps/mnemonic-0.19.dist-info/INSTALLER1
-rw-r--r--frozen_deps/mnemonic-0.19.dist-info/LICENSE21
-rw-r--r--frozen_deps/mnemonic-0.19.dist-info/METADATA42
-rw-r--r--frozen_deps/mnemonic-0.19.dist-info/RECORD19
-rw-r--r--frozen_deps/mnemonic-0.19.dist-info/WHEEL6
-rw-r--r--frozen_deps/mnemonic-0.19.dist-info/top_level.txt1
-rw-r--r--frozen_deps/mnemonic/__init__.py1
-rw-r--r--frozen_deps/mnemonic/mnemonic.py291
-rw-r--r--frozen_deps/mnemonic/wordlist/chinese_simplified.txt2048
-rw-r--r--frozen_deps/mnemonic/wordlist/chinese_traditional.txt2048
-rw-r--r--frozen_deps/mnemonic/wordlist/english.txt2048
-rw-r--r--frozen_deps/mnemonic/wordlist/french.txt2048
-rw-r--r--frozen_deps/mnemonic/wordlist/italian.txt2048
-rw-r--r--frozen_deps/mnemonic/wordlist/japanese.txt2048
-rw-r--r--frozen_deps/mnemonic/wordlist/korean.txt2048
-rw-r--r--frozen_deps/mnemonic/wordlist/spanish.txt2048
-rw-r--r--frozen_deps/pycrypto-2.6.1.dist-info/INSTALLER1
-rw-r--r--frozen_deps/pycrypto-2.6.1.dist-info/METADATA22
-rw-r--r--frozen_deps/pycrypto-2.6.1.dist-info/RECORD261
-rw-r--r--frozen_deps/pycrypto-2.6.1.dist-info/WHEEL5
-rw-r--r--frozen_deps/pycrypto-2.6.1.dist-info/top_level.txt1
-rw-r--r--frozen_deps/pysha3-1.0.2.dist-info/INSTALLER1
-rw-r--r--frozen_deps/pysha3-1.0.2.dist-info/LICENSE49
-rw-r--r--frozen_deps/pysha3-1.0.2.dist-info/METADATA251
-rw-r--r--frozen_deps/pysha3-1.0.2.dist-info/RECORD9
-rw-r--r--frozen_deps/pysha3-1.0.2.dist-info/WHEEL5
-rw-r--r--frozen_deps/pysha3-1.0.2.dist-info/top_level.txt2
-rw-r--r--frozen_deps/sha3.py24
-rw-r--r--frozen_deps/six-1.15.0.dist-info/INSTALLER1
-rw-r--r--frozen_deps/six-1.15.0.dist-info/LICENSE18
-rw-r--r--frozen_deps/six-1.15.0.dist-info/METADATA49
-rw-r--r--frozen_deps/six-1.15.0.dist-info/RECORD8
-rw-r--r--frozen_deps/six-1.15.0.dist-info/WHEEL6
-rw-r--r--frozen_deps/six-1.15.0.dist-info/top_level.txt1
-rw-r--r--frozen_deps/six.py982
164 files changed, 41014 insertions, 0 deletions
diff --git a/frozen_deps/Crypto/Cipher/AES.py b/frozen_deps/Crypto/Cipher/AES.py
new file mode 100644
index 0000000..14f68d8
--- /dev/null
+++ b/frozen_deps/Crypto/Cipher/AES.py
@@ -0,0 +1,115 @@
+# -*- coding: utf-8 -*-
+#
+# Cipher/AES.py : AES
+#
+# ===================================================================
+# The contents of this file are dedicated to the public domain. To
+# the extent that dedication to the public domain is not available,
+# everyone is granted a worldwide, perpetual, royalty-free,
+# non-exclusive license to exercise all rights associated with the
+# contents of this file for any purpose whatsoever.
+# No rights are reserved.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+# SOFTWARE.
+# ===================================================================
+"""AES symmetric cipher
+
+AES `(Advanced Encryption Standard)`__ is a symmetric block cipher standardized
+by NIST_ . It has a fixed data block size of 16 bytes.
+Its keys can be 128, 192, or 256 bits long.
+
+AES is very fast and secure, and it is the de facto standard for symmetric
+encryption.
+
+As an example, encryption can be done as follows:
+
+ >>> from Crypto.Cipher import AES
+ >>> from Crypto import Random
+ >>>
+ >>> key = b'Sixteen byte key'
+ >>> iv = Random.new().read(AES.block_size)
+ >>> cipher = AES.new(key, AES.MODE_CFB, iv)
+ >>> msg = iv + cipher.encrypt(b'Attack at dawn')
+
+.. __: http://en.wikipedia.org/wiki/Advanced_Encryption_Standard
+.. _NIST: http://csrc.nist.gov/publications/fips/fips197/fips-197.pdf
+
+:undocumented: __revision__, __package__
+"""
+
+__revision__ = "$Id$"
+
+from Crypto.Cipher import blockalgo
+from Crypto.Cipher import _AES
+
+class AESCipher (blockalgo.BlockAlgo):
+ """AES cipher object"""
+
+ def __init__(self, key, *args, **kwargs):
+ """Initialize an AES cipher object
+
+ See also `new()` at the module level."""
+ blockalgo.BlockAlgo.__init__(self, _AES, key, *args, **kwargs)
+
+def new(key, *args, **kwargs):
+ """Create a new AES cipher
+
+ :Parameters:
+ key : byte string
+ The secret key to use in the symmetric cipher.
+ It must be 16 (*AES-128*), 24 (*AES-192*), or 32 (*AES-256*) bytes long.
+ :Keywords:
+ mode : a *MODE_** constant
+ The chaining mode to use for encryption or decryption.
+ Default is `MODE_ECB`.
+ IV : byte string
+ The initialization vector to use for encryption or decryption.
+
+ It is ignored for `MODE_ECB` and `MODE_CTR`.
+
+ For `MODE_OPENPGP`, IV must be `block_size` bytes long for encryption
+ and `block_size` +2 bytes for decryption (in the latter case, it is
+ actually the *encrypted* IV which was prefixed to the ciphertext).
+ It is mandatory.
+
+ For all other modes, it must be `block_size` bytes longs. It is optional and
+ when not present it will be given a default value of all zeroes.
+ counter : callable
+ (*Only* `MODE_CTR`). A stateful function that returns the next
+ *counter block*, which is a byte string of `block_size` bytes.
+ For better performance, use `Crypto.Util.Counter`.
+ segment_size : integer
+ (*Only* `MODE_CFB`).The number of bits the plaintext and ciphertext
+ are segmented in.
+ It must be a multiple of 8. If 0 or not specified, it will be assumed to be 8.
+
+ :Return: an `AESCipher` object
+ """
+ return AESCipher(key, *args, **kwargs)
+
+#: Electronic Code Book (ECB). See `blockalgo.MODE_ECB`.
+MODE_ECB = 1
+#: Cipher-Block Chaining (CBC). See `blockalgo.MODE_CBC`.
+MODE_CBC = 2
+#: Cipher FeedBack (CFB). See `blockalgo.MODE_CFB`.
+MODE_CFB = 3
+#: This mode should not be used.
+MODE_PGP = 4
+#: Output FeedBack (OFB). See `blockalgo.MODE_OFB`.
+MODE_OFB = 5
+#: CounTer Mode (CTR). See `blockalgo.MODE_CTR`.
+MODE_CTR = 6
+#: OpenPGP Mode. See `blockalgo.MODE_OPENPGP`.
+MODE_OPENPGP = 7
+#: Size of a data block (in bytes)
+block_size = 16
+#: Size of a key (in bytes)
+key_size = ( 16, 24, 32 )
+
diff --git a/frozen_deps/Crypto/Cipher/ARC2.py b/frozen_deps/Crypto/Cipher/ARC2.py
new file mode 100644
index 0000000..b5234e6
--- /dev/null
+++ b/frozen_deps/Crypto/Cipher/ARC2.py
@@ -0,0 +1,130 @@
+# -*- coding: utf-8 -*-
+#
+# Cipher/ARC2.py : ARC2.py
+#
+# ===================================================================
+# The contents of this file are dedicated to the public domain. To
+# the extent that dedication to the public domain is not available,
+# everyone is granted a worldwide, perpetual, royalty-free,
+# non-exclusive license to exercise all rights associated with the
+# contents of this file for any purpose whatsoever.
+# No rights are reserved.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+# SOFTWARE.
+# ===================================================================
+"""RC2 symmetric cipher
+
+RC2_ (Rivest's Cipher version 2) is a symmetric block cipher designed
+by Ron Rivest in 1987. The cipher started as a proprietary design,
+that was reverse engineered and anonymously posted on Usenet in 1996.
+For this reason, the algorithm was first called *Alleged* RC2 (ARC2),
+since the company that owned RC2 (RSA Data Inc.) did not confirm whether
+the details leaked into public domain were really correct.
+
+The company eventually published its full specification in RFC2268_.
+
+RC2 has a fixed data block size of 8 bytes. Length of its keys can vary from
+8 to 128 bits. One particular property of RC2 is that the actual
+cryptographic strength of the key (*effective key length*) can be reduced
+via a parameter.
+
+Even though RC2 is not cryptographically broken, it has not been analyzed as
+thoroughly as AES, which is also faster than RC2.
+
+New designs should not use RC2.
+
+As an example, encryption can be done as follows:
+
+ >>> from Crypto.Cipher import ARC2
+ >>> from Crypto import Random
+ >>>
+ >>> key = b'Sixteen byte key'
+ >>> iv = Random.new().read(ARC2.block_size)
+ >>> cipher = ARC2.new(key, ARC2.MODE_CFB, iv)
+ >>> msg = iv + cipher.encrypt(b'Attack at dawn')
+
+.. _RC2: http://en.wikipedia.org/wiki/RC2
+.. _RFC2268: http://tools.ietf.org/html/rfc2268
+
+:undocumented: __revision__, __package__
+"""
+
+__revision__ = "$Id$"
+
+from Crypto.Cipher import blockalgo
+from Crypto.Cipher import _ARC2
+
+class RC2Cipher (blockalgo.BlockAlgo):
+ """RC2 cipher object"""
+
+ def __init__(self, key, *args, **kwargs):
+ """Initialize an ARC2 cipher object
+
+ See also `new()` at the module level."""
+ blockalgo.BlockAlgo.__init__(self, _ARC2, key, *args, **kwargs)
+
+def new(key, *args, **kwargs):
+ """Create a new RC2 cipher
+
+ :Parameters:
+ key : byte string
+ The secret key to use in the symmetric cipher.
+ Its length can vary from 1 to 128 bytes.
+ :Keywords:
+ mode : a *MODE_** constant
+ The chaining mode to use for encryption or decryption.
+ Default is `MODE_ECB`.
+ IV : byte string
+ The initialization vector to use for encryption or decryption.
+
+ It is ignored for `MODE_ECB` and `MODE_CTR`.
+
+ For `MODE_OPENPGP`, IV must be `block_size` bytes long for encryption
+ and `block_size` +2 bytes for decryption (in the latter case, it is
+ actually the *encrypted* IV which was prefixed to the ciphertext).
+ It is mandatory.
+
+ For all other modes, it must be `block_size` bytes longs. It is optional and
+ when not present it will be given a default value of all zeroes.
+ counter : callable
+ (*Only* `MODE_CTR`). A stateful function that returns the next
+ *counter block*, which is a byte string of `block_size` bytes.
+ For better performance, use `Crypto.Util.Counter`.
+ segment_size : integer
+ (*Only* `MODE_CFB`).The number of bits the plaintext and ciphertext
+ are segmented in.
+ It must be a multiple of 8. If 0 or not specified, it will be assumed to be 8.
+ effective_keylen : integer
+ Maximum cryptographic strength of the key, in bits.
+ It can vary from 0 to 1024. The default value is 1024.
+
+ :Return: an `RC2Cipher` object
+ """
+ return RC2Cipher(key, *args, **kwargs)
+
+#: Electronic Code Book (ECB). See `blockalgo.MODE_ECB`.
+MODE_ECB = 1
+#: Cipher-Block Chaining (CBC). See `blockalgo.MODE_CBC`.
+MODE_CBC = 2
+#: Cipher FeedBack (CFB). See `blockalgo.MODE_CFB`.
+MODE_CFB = 3
+#: This mode should not be used.
+MODE_PGP = 4
+#: Output FeedBack (OFB). See `blockalgo.MODE_OFB`.
+MODE_OFB = 5
+#: CounTer Mode (CTR). See `blockalgo.MODE_CTR`.
+MODE_CTR = 6
+#: OpenPGP Mode. See `blockalgo.MODE_OPENPGP`.
+MODE_OPENPGP = 7
+#: Size of a data block (in bytes)
+block_size = 8
+#: Size of a key (in bytes)
+key_size = range(1,16+1)
+
diff --git a/frozen_deps/Crypto/Cipher/ARC4.py b/frozen_deps/Crypto/Cipher/ARC4.py
new file mode 100644
index 0000000..d83f75b
--- /dev/null
+++ b/frozen_deps/Crypto/Cipher/ARC4.py
@@ -0,0 +1,120 @@
+# -*- coding: utf-8 -*-
+#
+# Cipher/ARC4.py : ARC4
+#
+# ===================================================================
+# The contents of this file are dedicated to the public domain. To
+# the extent that dedication to the public domain is not available,
+# everyone is granted a worldwide, perpetual, royalty-free,
+# non-exclusive license to exercise all rights associated with the
+# contents of this file for any purpose whatsoever.
+# No rights are reserved.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+# SOFTWARE.
+# ===================================================================
+"""ARC4 symmetric cipher
+
+ARC4_ (Alleged RC4) is an implementation of RC4 (Rivest's Cipher version 4),
+a symmetric stream cipher designed by Ron Rivest in 1987.
+
+The cipher started as a proprietary design, that was reverse engineered and
+anonymously posted on Usenet in 1994. The company that owns RC4 (RSA Data
+Inc.) never confirmed the correctness of the leaked algorithm.
+
+Unlike RC2, the company has never published the full specification of RC4,
+of whom it still holds the trademark.
+
+ARC4 keys can vary in length from 40 to 2048 bits.
+
+One problem of ARC4 is that it does not take a nonce or an IV. If it is required
+to encrypt multiple messages with the same long-term key, a distinct
+independent nonce must be created for each message, and a short-term key must
+be derived from the combination of the long-term key and the nonce.
+Due to the weak key scheduling algorithm of RC2, the combination must be carried
+out with a complex function (e.g. a cryptographic hash) and not by simply
+concatenating key and nonce.
+
+New designs should not use ARC4. A good alternative is AES
+(`Crypto.Cipher.AES`) in any of the modes that turn it into a stream cipher (OFB, CFB, or CTR).
+
+As an example, encryption can be done as follows:
+
+ >>> from Crypto.Cipher import ARC4
+ >>> from Crypto.Hash import SHA
+ >>> from Crypto import Random
+ >>>
+ >>> key = b'Very long and confidential key'
+ >>> nonce = Random.new().read(16)
+ >>> tempkey = SHA.new(key+nonce).digest()
+ >>> cipher = ARC4.new(tempkey)
+ >>> msg = nonce + cipher.encrypt(b'Open the pod bay doors, HAL')
+
+.. _ARC4: http://en.wikipedia.org/wiki/RC4
+
+:undocumented: __revision__, __package__
+"""
+
+__revision__ = "$Id$"
+
+from Crypto.Cipher import _ARC4
+
+class ARC4Cipher:
+ """ARC4 cipher object"""
+
+
+ def __init__(self, key, *args, **kwargs):
+ """Initialize an ARC4 cipher object
+
+ See also `new()` at the module level."""
+
+ self._cipher = _ARC4.new(key, *args, **kwargs)
+ self.block_size = self._cipher.block_size
+ self.key_size = self._cipher.key_size
+
+ def encrypt(self, plaintext):
+ """Encrypt a piece of data.
+
+ :Parameters:
+ plaintext : byte string
+ The piece of data to encrypt. It can be of any size.
+ :Return: the encrypted data (byte string, as long as the
+ plaintext).
+ """
+ return self._cipher.encrypt(plaintext)
+
+ def decrypt(self, ciphertext):
+ """Decrypt a piece of data.
+
+ :Parameters:
+ ciphertext : byte string
+ The piece of data to decrypt. It can be of any size.
+ :Return: the decrypted data (byte string, as long as the
+ ciphertext).
+ """
+ return self._cipher.decrypt(ciphertext)
+
+def new(key, *args, **kwargs):
+ """Create a new ARC4 cipher
+
+ :Parameters:
+ key : byte string
+ The secret key to use in the symmetric cipher.
+ It can have any length, with a minimum of 40 bytes.
+ Its cryptograpic strength is always capped to 2048 bits (256 bytes).
+
+ :Return: an `ARC4Cipher` object
+ """
+ return ARC4Cipher(key, *args, **kwargs)
+
+#: Size of a data block (in bytes)
+block_size = 1
+#: Size of a key (in bytes)
+key_size = range(1,256+1)
+
diff --git a/frozen_deps/Crypto/Cipher/Blowfish.py b/frozen_deps/Crypto/Cipher/Blowfish.py
new file mode 100644
index 0000000..8c81d96
--- /dev/null
+++ b/frozen_deps/Crypto/Cipher/Blowfish.py
@@ -0,0 +1,121 @@
+# -*- coding: utf-8 -*-
+#
+# Cipher/Blowfish.py : Blowfish
+#
+# ===================================================================
+# The contents of this file are dedicated to the public domain. To
+# the extent that dedication to the public domain is not available,
+# everyone is granted a worldwide, perpetual, royalty-free,
+# non-exclusive license to exercise all rights associated with the
+# contents of this file for any purpose whatsoever.
+# No rights are reserved.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+# SOFTWARE.
+# ===================================================================
+"""Blowfish symmetric cipher
+
+Blowfish_ is a symmetric block cipher designed by Bruce Schneier.
+
+It has a fixed data block size of 8 bytes and its keys can vary in length
+from 32 to 448 bits (4 to 56 bytes).
+
+Blowfish is deemed secure and it is fast. However, its keys should be chosen
+to be big enough to withstand a brute force attack (e.g. at least 16 bytes).
+
+As an example, encryption can be done as follows:
+
+ >>> from Crypto.Cipher import Blowfish
+ >>> from Crypto import Random
+ >>> from struct import pack
+ >>>
+ >>> bs = Blowfish.block_size
+ >>> key = b'An arbitrarily long key'
+ >>> iv = Random.new().read(bs)
+ >>> cipher = Blowfish.new(key, Blowfish.MODE_CBC, iv)
+ >>> plaintext = b'docendo discimus '
+ >>> plen = bs - divmod(len(plaintext),bs)[1]
+ >>> padding = [plen]*plen
+ >>> padding = pack('b'*plen, *padding)
+ >>> msg = iv + cipher.encrypt(plaintext + padding)
+
+.. _Blowfish: http://www.schneier.com/blowfish.html
+
+:undocumented: __revision__, __package__
+"""
+
+__revision__ = "$Id$"
+
+from Crypto.Cipher import blockalgo
+from Crypto.Cipher import _Blowfish
+
+class BlowfishCipher (blockalgo.BlockAlgo):
+ """Blowfish cipher object"""
+
+ def __init__(self, key, *args, **kwargs):
+ """Initialize a Blowfish cipher object
+
+ See also `new()` at the module level."""
+ blockalgo.BlockAlgo.__init__(self, _Blowfish, key, *args, **kwargs)
+
+def new(key, *args, **kwargs):
+ """Create a new Blowfish cipher
+
+ :Parameters:
+ key : byte string
+ The secret key to use in the symmetric cipher.
+ Its length can vary from 4 to 56 bytes.
+ :Keywords:
+ mode : a *MODE_** constant
+ The chaining mode to use for encryption or decryption.
+ Default is `MODE_ECB`.
+ IV : byte string
+ The initialization vector to use for encryption or decryption.
+
+ It is ignored for `MODE_ECB` and `MODE_CTR`.
+
+ For `MODE_OPENPGP`, IV must be `block_size` bytes long for encryption
+ and `block_size` +2 bytes for decryption (in the latter case, it is
+ actually the *encrypted* IV which was prefixed to the ciphertext).
+ It is mandatory.
+
+ For all other modes, it must be `block_size` bytes longs. It is optional and
+ when not present it will be given a default value of all zeroes.
+ counter : callable
+ (*Only* `MODE_CTR`). A stateful function that returns the next
+ *counter block*, which is a byte string of `block_size` bytes.
+ For better performance, use `Crypto.Util.Counter`.
+ segment_size : integer
+ (*Only* `MODE_CFB`).The number of bits the plaintext and ciphertext
+ are segmented in.
+ It must be a multiple of 8. If 0 or not specified, it will be assumed to be 8.
+
+ :Return: a `BlowfishCipher` object
+ """
+ return BlowfishCipher(key, *args, **kwargs)
+
+#: Electronic Code Book (ECB). See `blockalgo.MODE_ECB`.
+MODE_ECB = 1
+#: Cipher-Block Chaining (CBC). See `blockalgo.MODE_CBC`.
+MODE_CBC = 2
+#: Cipher FeedBack (CFB). See `blockalgo.MODE_CFB`.
+MODE_CFB = 3
+#: This mode should not be used.
+MODE_PGP = 4
+#: Output FeedBack (OFB). See `blockalgo.MODE_OFB`.
+MODE_OFB = 5
+#: CounTer Mode (CTR). See `blockalgo.MODE_CTR`.
+MODE_CTR = 6
+#: OpenPGP Mode. See `blockalgo.MODE_OPENPGP`.
+MODE_OPENPGP = 7
+#: Size of a data block (in bytes)
+block_size = 8
+#: Size of a key (in bytes)
+key_size = range(4,56+1)
+
diff --git a/frozen_deps/Crypto/Cipher/CAST.py b/frozen_deps/Crypto/Cipher/CAST.py
new file mode 100644
index 0000000..89543b2
--- /dev/null
+++ b/frozen_deps/Crypto/Cipher/CAST.py
@@ -0,0 +1,123 @@
+# -*- coding: utf-8 -*-
+#
+# Cipher/CAST.py : CAST
+#
+# ===================================================================
+# The contents of this file are dedicated to the public domain. To
+# the extent that dedication to the public domain is not available,
+# everyone is granted a worldwide, perpetual, royalty-free,
+# non-exclusive license to exercise all rights associated with the
+# contents of this file for any purpose whatsoever.
+# No rights are reserved.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+# SOFTWARE.
+# ===================================================================
+"""CAST-128 symmetric cipher
+
+CAST-128_ (or CAST5) is a symmetric block cipher specified in RFC2144_.
+
+It has a fixed data block size of 8 bytes. Its key can vary in length
+from 40 to 128 bits.
+
+CAST is deemed to be cryptographically secure, but its usage is not widespread.
+Keys of sufficient length should be used to prevent brute force attacks
+(128 bits are recommended).
+
+As an example, encryption can be done as follows:
+
+ >>> from Crypto.Cipher import CAST
+ >>> from Crypto import Random
+ >>>
+ >>> key = b'Sixteen byte key'
+ >>> iv = Random.new().read(CAST.block_size)
+ >>> cipher = CAST.new(key, CAST.MODE_OPENPGP, iv)
+ >>> plaintext = b'sona si latine loqueris '
+ >>> msg = cipher.encrypt(plaintext)
+ >>>
+ ...
+ >>> eiv = msg[:CAST.block_size+2]
+ >>> ciphertext = msg[CAST.block_size+2:]
+ >>> cipher = CAST.new(key, CAST.MODE_OPENPGP, eiv)
+ >>> print cipher.decrypt(ciphertext)
+
+.. _CAST-128: http://en.wikipedia.org/wiki/CAST-128
+.. _RFC2144: http://tools.ietf.org/html/rfc2144
+
+:undocumented: __revision__, __package__
+"""
+
+__revision__ = "$Id$"
+
+from Crypto.Cipher import blockalgo
+from Crypto.Cipher import _CAST
+
+class CAST128Cipher(blockalgo.BlockAlgo):
+ """CAST-128 cipher object"""
+
+ def __init__(self, key, *args, **kwargs):
+ """Initialize a CAST-128 cipher object
+
+ See also `new()` at the module level."""
+ blockalgo.BlockAlgo.__init__(self, _CAST, key, *args, **kwargs)
+
+def new(key, *args, **kwargs):
+ """Create a new CAST-128 cipher
+
+ :Parameters:
+ key : byte string
+ The secret key to use in the symmetric cipher.
+ Its length may vary from 5 to 16 bytes.
+ :Keywords:
+ mode : a *MODE_** constant
+ The chaining mode to use for encryption or decryption.
+ Default is `MODE_ECB`.
+ IV : byte string
+ The initialization vector to use for encryption or decryption.
+
+ It is ignored for `MODE_ECB` and `MODE_CTR`.
+
+ For `MODE_OPENPGP`, IV must be `block_size` bytes long for encryption
+ and `block_size` +2 bytes for decryption (in the latter case, it is
+ actually the *encrypted* IV which was prefixed to the ciphertext).
+ It is mandatory.
+
+ For all other modes, it must be `block_size` bytes longs. It is optional and
+ when not present it will be given a default value of all zeroes.
+ counter : callable
+ (*Only* `MODE_CTR`). A stateful function that returns the next
+ *counter block*, which is a byte string of `block_size` bytes.
+ For better performance, use `Crypto.Util.Counter`.
+ segment_size : integer
+ (*Only* `MODE_CFB`).The number of bits the plaintext and ciphertext
+ are segmented in.
+ It must be a multiple of 8. If 0 or not specified, it will be assumed to be 8.
+
+ :Return: an `CAST128Cipher` object
+ """
+ return CAST128Cipher(key, *args, **kwargs)
+
+#: Electronic Code Book (ECB). See `blockalgo.MODE_ECB`.
+MODE_ECB = 1
+#: Cipher-Block Chaining (CBC). See `blockalgo.MODE_CBC`.
+MODE_CBC = 2
+#: Cipher FeedBack (CFB). See `blockalgo.MODE_CFB`.
+MODE_CFB = 3
+#: This mode should not be used.
+MODE_PGP = 4
+#: Output FeedBack (OFB). See `blockalgo.MODE_OFB`.
+MODE_OFB = 5
+#: CounTer Mode (CTR). See `blockalgo.MODE_CTR`.
+MODE_CTR = 6
+#: OpenPGP Mode. See `blockalgo.MODE_OPENPGP`.
+MODE_OPENPGP = 7
+#: Size of a data block (in bytes)
+block_size = 8
+#: Size of a key (in bytes)
+key_size = range(5,16+1)
diff --git a/frozen_deps/Crypto/Cipher/DES.py b/frozen_deps/Crypto/Cipher/DES.py
new file mode 100644
index 0000000..2fae42f
--- /dev/null
+++ b/frozen_deps/Crypto/Cipher/DES.py
@@ -0,0 +1,118 @@
+# -*- coding: utf-8 -*-
+#
+# Cipher/DES.py : DES
+#
+# ===================================================================
+# The contents of this file are dedicated to the public domain. To
+# the extent that dedication to the public domain is not available,
+# everyone is granted a worldwide, perpetual, royalty-free,
+# non-exclusive license to exercise all rights associated with the
+# contents of this file for any purpose whatsoever.
+# No rights are reserved.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+# SOFTWARE.
+# ===================================================================
+"""DES symmetric cipher
+
+DES `(Data Encryption Standard)`__ is a symmetric block cipher standardized
+by NIST_ . It has a fixed data block size of 8 bytes.
+Its keys are 64 bits long, even though 8 bits were used for integrity (now they
+are ignored) and do not contribute to securty.
+
+DES is cryptographically secure, but its key length is too short by nowadays
+standards and it could be brute forced with some effort.
+
+DES should not be used for new designs. Use `AES`.
+
+As an example, encryption can be done as follows:
+
+ >>> from Crypto.Cipher import DES3
+ >>> from Crypto import Random
+ >>>
+ >>> key = b'Sixteen byte key'
+ >>> iv = Random.new().read(DES3.block_size)
+ >>> cipher = DES3.new(key, DES3.MODE_OFB, iv)
+ >>> plaintext = b'sona si latine loqueris '
+ >>> msg = iv + cipher.encrypt(plaintext)
+
+.. __: http://en.wikipedia.org/wiki/Data_Encryption_Standard
+.. _NIST: http://csrc.nist.gov/publications/fips/fips46-3/fips46-3.pdf
+
+:undocumented: __revision__, __package__
+"""
+
+__revision__ = "$Id$"
+
+from Crypto.Cipher import blockalgo
+from Crypto.Cipher import _DES
+
+class DESCipher(blockalgo.BlockAlgo):
+ """DES cipher object"""
+
+ def __init__(self, key, *args, **kwargs):
+ """Initialize a DES cipher object
+
+ See also `new()` at the module level."""
+ blockalgo.BlockAlgo.__init__(self, _DES, key, *args, **kwargs)
+
+def new(key, *args, **kwargs):
+ """Create a new DES cipher
+
+ :Parameters:
+ key : byte string
+ The secret key to use in the symmetric cipher.
+ It must be 8 byte long. The parity bits will be ignored.
+ :Keywords:
+ mode : a *MODE_** constant
+ The chaining mode to use for encryption or decryption.
+ Default is `MODE_ECB`.
+ IV : byte string
+ The initialization vector to use for encryption or decryption.
+
+ It is ignored for `MODE_ECB` and `MODE_CTR`.
+
+ For `MODE_OPENPGP`, IV must be `block_size` bytes long for encryption
+ and `block_size` +2 bytes for decryption (in the latter case, it is
+ actually the *encrypted* IV which was prefixed to the ciphertext).
+ It is mandatory.
+
+ For all other modes, it must be `block_size` bytes longs. It is optional and
+ when not present it will be given a default value of all zeroes.
+ counter : callable
+ (*Only* `MODE_CTR`). A stateful function that returns the next
+ *counter block*, which is a byte string of `block_size` bytes.
+ For better performance, use `Crypto.Util.Counter`.
+ segment_size : integer
+ (*Only* `MODE_CFB`).The number of bits the plaintext and ciphertext
+ are segmented in.
+ It must be a multiple of 8. If 0 or not specified, it will be assumed to be 8.
+
+ :Return: an `DESCipher` object
+ """
+ return DESCipher(key, *args, **kwargs)
+
+#: Electronic Code Book (ECB). See `blockalgo.MODE_ECB`.
+MODE_ECB = 1
+#: Cipher-Block Chaining (CBC). See `blockalgo.MODE_CBC`.
+MODE_CBC = 2
+#: Cipher FeedBack (CFB). See `blockalgo.MODE_CFB`.
+MODE_CFB = 3
+#: This mode should not be used.
+MODE_PGP = 4
+#: Output FeedBack (OFB). See `blockalgo.MODE_OFB`.
+MODE_OFB = 5
+#: CounTer Mode (CTR). See `blockalgo.MODE_CTR`.
+MODE_CTR = 6
+#: OpenPGP Mode. See `blockalgo.MODE_OPENPGP`.
+MODE_OPENPGP = 7
+#: Size of a data block (in bytes)
+block_size = 8
+#: Size of a key (in bytes)
+key_size = 8
diff --git a/frozen_deps/Crypto/Cipher/DES3.py b/frozen_deps/Crypto/Cipher/DES3.py
new file mode 100644
index 0000000..7fedac8
--- /dev/null
+++ b/frozen_deps/Crypto/Cipher/DES3.py
@@ -0,0 +1,133 @@
+# -*- coding: utf-8 -*-
+#
+# Cipher/DES3.py : DES3
+#
+# ===================================================================
+# The contents of this file are dedicated to the public domain. To
+# the extent that dedication to the public domain is not available,
+# everyone is granted a worldwide, perpetual, royalty-free,
+# non-exclusive license to exercise all rights associated with the
+# contents of this file for any purpose whatsoever.
+# No rights are reserved.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+# SOFTWARE.
+# ===================================================================
+"""Triple DES symmetric cipher
+
+`Triple DES`__ (or TDES or TDEA or 3DES) is a symmetric block cipher standardized by NIST_.
+It has a fixed data block size of 8 bytes. Its keys are 128 (*Option 1*) or 192
+bits (*Option 2*) long.
+However, 1 out of 8 bits is used for redundancy and do not contribute to
+security. The effective key length is respectively 112 or 168 bits.
+
+TDES consists of the concatenation of 3 simple `DES` ciphers.
+
+The plaintext is first DES encrypted with *K1*, then decrypted with *K2*,
+and finally encrypted again with *K3*. The ciphertext is decrypted in the reverse manner.
+
+The 192 bit key is a bundle of three 64 bit independent subkeys: *K1*, *K2*, and *K3*.
+
+The 128 bit key is split into *K1* and *K2*, whereas *K1=K3*.
+
+It is important that all subkeys are different, otherwise TDES would degrade to
+single `DES`.
+
+TDES is cryptographically secure, even though it is neither as secure nor as fast
+as `AES`.
+
+As an example, encryption can be done as follows:
+
+ >>> from Crypto.Cipher import DES
+ >>> from Crypto import Random
+ >>> from Crypto.Util import Counter
+ >>>
+ >>> key = b'-8B key-'
+ >>> nonce = Random.new().read(DES.block_size/2)
+ >>> ctr = Counter.new(DES.block_size*8/2, prefix=nonce)
+ >>> cipher = DES.new(key, DES.MODE_CTR, counter=ctr)
+ >>> plaintext = b'We are no longer the knights who say ni!'
+ >>> msg = nonce + cipher.encrypt(plaintext)
+
+.. __: http://en.wikipedia.org/wiki/Triple_DES
+.. _NIST: http://csrc.nist.gov/publications/nistpubs/800-67/SP800-67.pdf
+
+:undocumented: __revision__, __package__
+"""
+
+__revision__ = "$Id$"
+
+from Crypto.Cipher import blockalgo
+from Crypto.Cipher import _DES3
+
+class DES3Cipher(blockalgo.BlockAlgo):
+ """TDES cipher object"""
+
+ def __init__(self, key, *args, **kwargs):
+ """Initialize a TDES cipher object
+
+ See also `new()` at the module level."""
+ blockalgo.BlockAlgo.__init__(self, _DES3, key, *args, **kwargs)
+
+def new(key, *args, **kwargs):
+ """Create a new TDES cipher
+
+ :Parameters:
+ key : byte string
+ The secret key to use in the symmetric cipher.
+ It must be 16 or 24 bytes long. The parity bits will be ignored.
+ :Keywords:
+ mode : a *MODE_** constant
+ The chaining mode to use for encryption or decryption.
+ Default is `MODE_ECB`.
+ IV : byte string
+ The initialization vector to use for encryption or decryption.
+
+ It is ignored for `MODE_ECB` and `MODE_CTR`.
+
+ For `MODE_OPENPGP`, IV must be `block_size` bytes long for encryption
+ and `block_size` +2 bytes for decryption (in the latter case, it is
+ actually the *encrypted* IV which was prefixed to the ciphertext).
+ It is mandatory.
+
+ For all other modes, it must be `block_size` bytes longs. It is optional and
+ when not present it will be given a default value of all zeroes.
+ counter : callable
+ (*Only* `MODE_CTR`). A stateful function that returns the next
+ *counter block*, which is a byte string of `block_size` bytes.
+ For better performance, use `Crypto.Util.Counter`.
+ segment_size : integer
+ (*Only* `MODE_CFB`).The number of bits the plaintext and ciphertext
+ are segmented in.
+ It must be a multiple of 8. If 0 or not specified, it will be assumed to be 8.
+
+ :Attention: it is important that all 8 byte subkeys are different,
+ otherwise TDES would degrade to single `DES`.
+ :Return: an `DES3Cipher` object
+ """
+ return DES3Cipher(key, *args, **kwargs)
+
+#: Electronic Code Book (ECB). See `blockalgo.MODE_ECB`.
+MODE_ECB = 1
+#: Cipher-Block Chaining (CBC). See `blockalgo.MODE_CBC`.
+MODE_CBC = 2
+#: Cipher FeedBack (CFB). See `blockalgo.MODE_CFB`.
+MODE_CFB = 3
+#: This mode should not be used.
+MODE_PGP = 4
+#: Output FeedBack (OFB). See `blockalgo.MODE_OFB`.
+MODE_OFB = 5
+#: CounTer Mode (CTR). See `blockalgo.MODE_CTR`.
+MODE_CTR = 6
+#: OpenPGP Mode. See `blockalgo.MODE_OPENPGP`.
+MODE_OPENPGP = 7
+#: Size of a data block (in bytes)
+block_size = 8
+#: Size of a key (in bytes)
+key_size = ( 16, 24 )
diff --git a/frozen_deps/Crypto/Cipher/PKCS1_OAEP.py b/frozen_deps/Crypto/Cipher/PKCS1_OAEP.py
new file mode 100644
index 0000000..2738ce3
--- /dev/null
+++ b/frozen_deps/Crypto/Cipher/PKCS1_OAEP.py
@@ -0,0 +1,255 @@
+# -*- coding: utf-8 -*-
+#
+# Cipher/PKCS1_OAEP.py : PKCS#1 OAEP
+#
+# ===================================================================
+# The contents of this file are dedicated to the public domain. To
+# the extent that dedication to the public domain is not available,
+# everyone is granted a worldwide, perpetual, royalty-free,
+# non-exclusive license to exercise all rights associated with the
+# contents of this file for any purpose whatsoever.
+# No rights are reserved.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+# SOFTWARE.
+# ===================================================================
+
+"""RSA encryption protocol according to PKCS#1 OAEP
+
+See RFC3447__ or the `original RSA Labs specification`__ .
+
+This scheme is more properly called ``RSAES-OAEP``.
+
+As an example, a sender may encrypt a message in this way:
+
+ >>> from Crypto.Cipher import PKCS1_OAEP
+ >>> from Crypto.PublicKey import RSA
+ >>>
+ >>> message = 'To be encrypted'
+ >>> key = RSA.importKey(open('pubkey.der').read())
+ >>> cipher = PKCS1_OAEP.new(key)
+ >>> ciphertext = cipher.encrypt(message)
+
+At the receiver side, decryption can be done using the private part of
+the RSA key:
+
+ >>> key = RSA.importKey(open('privkey.der').read())
+ >>> cipher = PKCS1_OAP.new(key)
+ >>> message = cipher.decrypt(ciphertext)
+
+:undocumented: __revision__, __package__
+
+.. __: http://www.ietf.org/rfc/rfc3447.txt
+.. __: http://www.rsa.com/rsalabs/node.asp?id=2125.
+"""
+
+
+
+__revision__ = "$Id$"
+__all__ = [ 'new', 'PKCS1OAEP_Cipher' ]
+
+import Crypto.Signature.PKCS1_PSS
+import Crypto.Hash.SHA
+
+from Crypto.Util.py3compat import *
+import Crypto.Util.number
+from Crypto.Util.number import ceil_div
+from Crypto.Util.strxor import strxor
+
+class PKCS1OAEP_Cipher:
+ """This cipher can perform PKCS#1 v1.5 OAEP encryption or decryption."""
+
+ def __init__(self, key, hashAlgo, mgfunc, label):
+ """Initialize this PKCS#1 OAEP cipher object.
+
+ :Parameters:
+ key : an RSA key object
+ If a private half is given, both encryption and decryption are possible.
+ If a public half is given, only encryption is possible.
+ hashAlgo : hash object
+ The hash function to use. This can be a module under `Crypto.Hash`
+ or an existing hash object created from any of such modules. If not specified,
+ `Crypto.Hash.SHA` (that is, SHA-1) is used.
+ mgfunc : callable
+ A mask generation function that accepts two parameters: a string to
+ use as seed, and the lenth of the mask to generate, in bytes.
+ If not specified, the standard MGF1 is used (a safe choice).
+ label : string
+ A label to apply to this particular encryption. If not specified,
+ an empty string is used. Specifying a label does not improve
+ security.
+
+ :attention: Modify the mask generation function only if you know what you are doing.
+ Sender and receiver must use the same one.
+ """
+ self._key = key
+
+ if hashAlgo:
+ self._hashObj = hashAlgo
+ else:
+ self._hashObj = Crypto.Hash.SHA
+
+ if mgfunc:
+ self._mgf = mgfunc
+ else:
+ self._mgf = lambda x,y: Crypto.Signature.PKCS1_PSS.MGF1(x,y,self._hashObj)
+
+ self._label = label
+
+ def can_encrypt(self):
+ """Return True/1 if this cipher object can be used for encryption."""
+ return self._key.can_encrypt()
+
+ def can_decrypt(self):
+ """Return True/1 if this cipher object can be used for decryption."""
+ return self._key.can_decrypt()
+
+ def encrypt(self, message):
+ """Produce the PKCS#1 OAEP encryption of a message.
+
+ This function is named ``RSAES-OAEP-ENCRYPT``, and is specified in
+ section 7.1.1 of RFC3447.
+
+ :Parameters:
+ message : string
+ The message to encrypt, also known as plaintext. It can be of
+ variable length, but not longer than the RSA modulus (in bytes)
+ minus 2, minus twice the hash output size.
+
+ :Return: A string, the ciphertext in which the message is encrypted.
+ It is as long as the RSA modulus (in bytes).
+ :Raise ValueError:
+ If the RSA key length is not sufficiently long to deal with the given
+ message.
+ """
+ # TODO: Verify the key is RSA
+
+ randFunc = self._key._randfunc
+
+ # See 7.1.1 in RFC3447
+ modBits = Crypto.Util.number.size(self._key.n)
+ k = ceil_div(modBits,8) # Convert from bits to bytes
+ hLen = self._hashObj.digest_size
+ mLen = len(message)
+
+ # Step 1b
+ ps_len = k-mLen-2*hLen-2
+ if ps_len<0:
+ raise ValueError("Plaintext is too long.")
+ # Step 2a
+ lHash = self._hashObj.new(self._label).digest()
+ # Step 2b
+ ps = bchr(0x00)*ps_len
+ # Step 2c
+ db = lHash + ps + bchr(0x01) + message
+ # Step 2d
+ ros = randFunc(hLen)
+ # Step 2e
+ dbMask = self._mgf(ros, k-hLen-1)
+ # Step 2f
+ maskedDB = strxor(db, dbMask)
+ # Step 2g
+ seedMask = self._mgf(maskedDB, hLen)
+ # Step 2h
+ maskedSeed = strxor(ros, seedMask)
+ # Step 2i
+ em = bchr(0x00) + maskedSeed + maskedDB
+ # Step 3a (OS2IP), step 3b (RSAEP), part of step 3c (I2OSP)
+ m = self._key.encrypt(em, 0)[0]
+ # Complete step 3c (I2OSP)
+ c = bchr(0x00)*(k-len(m)) + m
+ return c
+
+ def decrypt(self, ct):
+ """Decrypt a PKCS#1 OAEP ciphertext.
+
+ This function is named ``RSAES-OAEP-DECRYPT``, and is specified in
+ section 7.1.2 of RFC3447.
+
+ :Parameters:
+ ct : string
+ The ciphertext that contains the message to recover.
+
+ :Return: A string, the original message.
+ :Raise ValueError:
+ If the ciphertext length is incorrect, or if the decryption does not
+ succeed.
+ :Raise TypeError:
+ If the RSA key has no private half.
+ """
+ # TODO: Verify the key is RSA
+
+ # See 7.1.2 in RFC3447
+ modBits = Crypto.Util.number.size(self._key.n)
+ k = ceil_div(modBits,8) # Convert from bits to bytes
+ hLen = self._hashObj.digest_size
+
+ # Step 1b and 1c
+ if len(ct) != k or k<hLen+2:
+ raise ValueError("Ciphertext with incorrect length.")
+ # Step 2a (O2SIP), 2b (RSADP), and part of 2c (I2OSP)
+ m = self._key.decrypt(ct)
+ # Complete step 2c (I2OSP)
+ em = bchr(0x00)*(k-len(m)) + m
+ # Step 3a
+ lHash = self._hashObj.new(self._label).digest()
+ # Step 3b
+ y = em[0]
+ # y must be 0, but we MUST NOT check it here in order not to
+ # allow attacks like Manger's (http://dl.acm.org/citation.cfm?id=704143)
+ maskedSeed = em[1:hLen+1]
+ maskedDB = em[hLen+1:]
+ # Step 3c
+ seedMask = self._mgf(maskedDB, hLen)
+ # Step 3d
+ seed = strxor(maskedSeed, seedMask)
+ # Step 3e
+ dbMask = self._mgf(seed, k-hLen-1)
+ # Step 3f
+ db = strxor(maskedDB, dbMask)
+ # Step 3g
+ valid = 1
+ one = db[hLen:].find(bchr(0x01))
+ lHash1 = db[:hLen]
+ if lHash1!=lHash:
+ valid = 0
+ if one<0:
+ valid = 0
+ if bord(y)!=0:
+ valid = 0
+ if not valid:
+ raise ValueError("Incorrect decryption.")
+ # Step 4
+ return db[hLen+one+1:]
+
+def new(key, hashAlgo=None, mgfunc=None, label=b('')):
+ """Return a cipher object `PKCS1OAEP_Cipher` that can be used to perform PKCS#1 OAEP encryption or decryption.
+
+ :Parameters:
+ key : RSA key object
+ The key to use to encrypt or decrypt the message. This is a `Crypto.PublicKey.RSA` object.
+ Decryption is only possible if *key* is a private RSA key.
+ hashAlgo : hash object
+ The hash function to use. This can be a module under `Crypto.Hash`
+ or an existing hash object created from any of such modules. If not specified,
+ `Crypto.Hash.SHA` (that is, SHA-1) is used.
+ mgfunc : callable
+ A mask generation function that accepts two parameters: a string to
+ use as seed, and the lenth of the mask to generate, in bytes.
+ If not specified, the standard MGF1 is used (a safe choice).
+ label : string
+ A label to apply to this particular encryption. If not specified,
+ an empty string is used. Specifying a label does not improve
+ security.
+
+ :attention: Modify the mask generation function only if you know what you are doing.
+ Sender and receiver must use the same one.
+ """
+ return PKCS1OAEP_Cipher(key, hashAlgo, mgfunc, label)
+
diff --git a/frozen_deps/Crypto/Cipher/PKCS1_v1_5.py b/frozen_deps/Crypto/Cipher/PKCS1_v1_5.py
new file mode 100644
index 0000000..3602cb0
--- /dev/null
+++ b/frozen_deps/Crypto/Cipher/PKCS1_v1_5.py
@@ -0,0 +1,226 @@
+# -*- coding: utf-8 -*-
+#
+# Cipher/PKCS1-v1_5.py : PKCS#1 v1.5
+#
+# ===================================================================
+# The contents of this file are dedicated to the public domain. To
+# the extent that dedication to the public domain is not available,
+# everyone is granted a worldwide, perpetual, royalty-free,
+# non-exclusive license to exercise all rights associated with the
+# contents of this file for any purpose whatsoever.
+# No rights are reserved.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+# SOFTWARE.
+# ===================================================================
+
+"""RSA encryption protocol according to PKCS#1 v1.5
+
+See RFC3447__ or the `original RSA Labs specification`__ .
+
+This scheme is more properly called ``RSAES-PKCS1-v1_5``.
+
+**If you are designing a new protocol, consider using the more robust PKCS#1 OAEP.**
+
+As an example, a sender may encrypt a message in this way:
+
+ >>> from Crypto.Cipher import PKCS1_v1_5
+ >>> from Crypto.PublicKey import RSA
+ >>> from Crypto.Hash import SHA
+ >>>
+ >>> message = 'To be encrypted'
+ >>> h = SHA.new(message)
+ >>>
+ >>> key = RSA.importKey(open('pubkey.der').read())
+ >>> cipher = PKCS1_v1_5.new(key)
+ >>> ciphertext = cipher.encrypt(message+h.digest())
+
+At the receiver side, decryption can be done using the private part of
+the RSA key:
+
+ >>> From Crypto.Hash import SHA
+ >>> from Crypto import Random
+ >>>
+ >>> key = RSA.importKey(open('privkey.der').read())
+ >>>
+ >>> dsize = SHA.digest_size
+ >>> sentinel = Random.new().read(15+dsize) # Let's assume that average data length is 15
+ >>>
+ >>> cipher = PKCS1_v1_5.new(key)
+ >>> message = cipher.decrypt(ciphertext, sentinel)
+ >>>
+ >>> digest = SHA.new(message[:-dsize]).digest()
+ >>> if digest==message[-dsize:]: # Note how we DO NOT look for the sentinel
+ >>> print "Encryption was correct."
+ >>> else:
+ >>> print "Encryption was not correct."
+
+:undocumented: __revision__, __package__
+
+.. __: http://www.ietf.org/rfc/rfc3447.txt
+.. __: http://www.rsa.com/rsalabs/node.asp?id=2125.
+"""
+
+__revision__ = "$Id$"
+__all__ = [ 'new', 'PKCS115_Cipher' ]
+
+from Crypto.Util.number import ceil_div
+from Crypto.Util.py3compat import *
+import Crypto.Util.number
+
+class PKCS115_Cipher:
+ """This cipher can perform PKCS#1 v1.5 RSA encryption or decryption."""
+
+ def __init__(self, key):
+ """Initialize this PKCS#1 v1.5 cipher object.
+
+ :Parameters:
+ key : an RSA key object
+ If a private half is given, both encryption and decryption are possible.
+ If a public half is given, only encryption is possible.
+ """
+ self._key = key
+
+ def can_encrypt(self):
+ """Return True if this cipher object can be used for encryption."""
+ return self._key.can_encrypt()
+
+ def can_decrypt(self):
+ """Return True if this cipher object can be used for decryption."""
+ return self._key.can_decrypt()
+
+ def encrypt(self, message):
+ """Produce the PKCS#1 v1.5 encryption of a message.
+
+ This function is named ``RSAES-PKCS1-V1_5-ENCRYPT``, and is specified in
+ section 7.2.1 of RFC3447.
+ For a complete example see `Crypto.Cipher.PKCS1_v1_5`.
+
+ :Parameters:
+ message : byte string
+ The message to encrypt, also known as plaintext. It can be of
+ variable length, but not longer than the RSA modulus (in bytes) minus 11.
+
+ :Return: A byte string, the ciphertext in which the message is encrypted.
+ It is as long as the RSA modulus (in bytes).
+ :Raise ValueError:
+ If the RSA key length is not sufficiently long to deal with the given
+ message.
+
+ """
+ # TODO: Verify the key is RSA
+
+ randFunc = self._key._randfunc
+
+ # See 7.2.1 in RFC3447
+ modBits = Crypto.Util.number.size(self._key.n)
+ k = ceil_div(modBits,8) # Convert from bits to bytes
+ mLen = len(message)
+
+ # Step 1
+ if mLen > k-11:
+ raise ValueError("Plaintext is too long.")
+ # Step 2a
+ class nonZeroRandByte:
+ def __init__(self, rf): self.rf=rf
+ def __call__(self, c):
+ while bord(c)==0x00: c=self.rf(1)[0]
+ return c
+ ps = tobytes(list(map(nonZeroRandByte(randFunc), randFunc(k-mLen-3))))
+ # Step 2b
+ em = b('\x00\x02') + ps + bchr(0x00) + message
+ # Step 3a (OS2IP), step 3b (RSAEP), part of step 3c (I2OSP)
+ m = self._key.encrypt(em, 0)[0]
+ # Complete step 3c (I2OSP)
+ c = bchr(0x00)*(k-len(m)) + m
+ return c
+
+ def decrypt(self, ct, sentinel):
+ """Decrypt a PKCS#1 v1.5 ciphertext.
+
+ This function is named ``RSAES-PKCS1-V1_5-DECRYPT``, and is specified in
+ section 7.2.2 of RFC3447.
+ For a complete example see `Crypto.Cipher.PKCS1_v1_5`.
+
+ :Parameters:
+ ct : byte string
+ The ciphertext that contains the message to recover.
+ sentinel : any type
+ The object to return to indicate that an error was detected during decryption.
+
+ :Return: A byte string. It is either the original message or the ``sentinel`` (in case of an error).
+ :Raise ValueError:
+ If the ciphertext length is incorrect
+ :Raise TypeError:
+ If the RSA key has no private half.
+
+ :attention:
+ You should **never** let the party who submitted the ciphertext know that
+ this function returned the ``sentinel`` value.
+ Armed with such knowledge (for a fair amount of carefully crafted but invalid ciphertexts),
+ an attacker is able to recontruct the plaintext of any other encryption that were carried out
+ with the same RSA public key (see `Bleichenbacher's`__ attack).
+
+ In general, it should not be possible for the other party to distinguish
+ whether processing at the server side failed because the value returned
+ was a ``sentinel`` as opposed to a random, invalid message.
+
+ In fact, the second option is not that unlikely: encryption done according to PKCS#1 v1.5
+ embeds no good integrity check. There is roughly one chance
+ in 2^16 for a random ciphertext to be returned as a valid message
+ (although random looking).
+
+ It is therefore advisabled to:
+
+ 1. Select as ``sentinel`` a value that resembles a plausable random, invalid message.
+ 2. Not report back an error as soon as you detect a ``sentinel`` value.
+ Put differently, you should not explicitly check if the returned value is the ``sentinel`` or not.
+ 3. Cover all possible errors with a single, generic error indicator.
+ 4. Embed into the definition of ``message`` (at the protocol level) a digest (e.g. ``SHA-1``).
+ It is recommended for it to be the rightmost part ``message``.
+ 5. Where possible, monitor the number of errors due to ciphertexts originating from the same party,
+ and slow down the rate of the requests from such party (or even blacklist it altogether).
+
+ **If you are designing a new protocol, consider using the more robust PKCS#1 OAEP.**
+
+ .. __: http://www.bell-labs.com/user/bleichen/papers/pkcs.ps
+
+ """
+
+ # TODO: Verify the key is RSA
+
+ # See 7.2.1 in RFC3447
+ modBits = Crypto.Util.number.size(self._key.n)
+ k = ceil_div(modBits,8) # Convert from bits to bytes
+
+ # Step 1
+ if len(ct) != k:
+ raise ValueError("Ciphertext with incorrect length.")
+ # Step 2a (O2SIP), 2b (RSADP), and part of 2c (I2OSP)
+ m = self._key.decrypt(ct)
+ # Complete step 2c (I2OSP)
+ em = bchr(0x00)*(k-len(m)) + m
+ # Step 3
+ sep = em.find(bchr(0x00),2)
+ if not em.startswith(b('\x00\x02')) or sep<10:
+ return sentinel
+ # Step 4
+ return em[sep+1:]
+
+def new(key):
+ """Return a cipher object `PKCS115_Cipher` that can be used to perform PKCS#1 v1.5 encryption or decryption.
+
+ :Parameters:
+ key : RSA key object
+ The key to use to encrypt or decrypt the message. This is a `Crypto.PublicKey.RSA` object.
+ Decryption is only possible if *key* is a private RSA key.
+
+ """
+ return PKCS115_Cipher(key)
+
diff --git a/frozen_deps/Crypto/Cipher/XOR.py b/frozen_deps/Crypto/Cipher/XOR.py
new file mode 100644
index 0000000..46b8464
--- /dev/null
+++ b/frozen_deps/Crypto/Cipher/XOR.py
@@ -0,0 +1,86 @@
+# -*- coding: utf-8 -*-
+#
+# Cipher/XOR.py : XOR
+#
+# ===================================================================
+# The contents of this file are dedicated to the public domain. To
+# the extent that dedication to the public domain is not available,
+# everyone is granted a worldwide, perpetual, royalty-free,
+# non-exclusive license to exercise all rights associated with the
+# contents of this file for any purpose whatsoever.
+# No rights are reserved.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+# SOFTWARE.
+# ===================================================================
+"""XOR toy cipher
+
+XOR is one the simplest stream ciphers. Encryption and decryption are
+performed by XOR-ing data with a keystream made by contatenating
+the key.
+
+Do not use it for real applications!
+
+:undocumented: __revision__, __package__
+"""
+
+__revision__ = "$Id$"
+
+from Crypto.Cipher import _XOR
+
+class XORCipher:
+ """XOR cipher object"""
+
+ def __init__(self, key, *args, **kwargs):
+ """Initialize a XOR cipher object
+
+ See also `new()` at the module level."""
+ self._cipher = _XOR.new(key, *args, **kwargs)
+ self.block_size = self._cipher.block_size
+ self.key_size = self._cipher.key_size
+
+ def encrypt(self, plaintext):
+ """Encrypt a piece of data.
+
+ :Parameters:
+ plaintext : byte string
+ The piece of data to encrypt. It can be of any size.
+ :Return: the encrypted data (byte string, as long as the
+ plaintext).
+ """
+ return self._cipher.encrypt(plaintext)
+
+ def decrypt(self, ciphertext):
+ """Decrypt a piece of data.
+
+ :Parameters:
+ ciphertext : byte string
+ The piece of data to decrypt. It can be of any size.
+ :Return: the decrypted data (byte string, as long as the
+ ciphertext).
+ """
+ return self._cipher.decrypt(ciphertext)
+
+def new(key, *args, **kwargs):
+ """Create a new XOR cipher
+
+ :Parameters:
+ key : byte string
+ The secret key to use in the symmetric cipher.
+ Its length may vary from 1 to 32 bytes.
+
+ :Return: an `XORCipher` object
+ """
+ return XORCipher(key, *args, **kwargs)
+
+#: Size of a data block (in bytes)
+block_size = 1
+#: Size of a key (in bytes)
+key_size = range(1,32+1)
+
diff --git a/frozen_deps/Crypto/Cipher/_AES.cpython-38-x86_64-linux-gnu.so b/frozen_deps/Crypto/Cipher/_AES.cpython-38-x86_64-linux-gnu.so
new file mode 100755
index 0000000..e9ffeb9
--- /dev/null
+++ b/frozen_deps/Crypto/Cipher/_AES.cpython-38-x86_64-linux-gnu.so
Binary files differ
diff --git a/frozen_deps/Crypto/Cipher/_ARC2.cpython-38-x86_64-linux-gnu.so b/frozen_deps/Crypto/Cipher/_ARC2.cpython-38-x86_64-linux-gnu.so
new file mode 100755
index 0000000..b325488
--- /dev/null
+++ b/frozen_deps/Crypto/Cipher/_ARC2.cpython-38-x86_64-linux-gnu.so
Binary files differ
diff --git a/frozen_deps/Crypto/Cipher/_ARC4.cpython-38-x86_64-linux-gnu.so b/frozen_deps/Crypto/Cipher/_ARC4.cpython-38-x86_64-linux-gnu.so
new file mode 100755
index 0000000..982a28d
--- /dev/null
+++ b/frozen_deps/Crypto/Cipher/_ARC4.cpython-38-x86_64-linux-gnu.so
Binary files differ
diff --git a/frozen_deps/Crypto/Cipher/_Blowfish.cpython-38-x86_64-linux-gnu.so b/frozen_deps/Crypto/Cipher/_Blowfish.cpython-38-x86_64-linux-gnu.so
new file mode 100755
index 0000000..2648636
--- /dev/null
+++ b/frozen_deps/Crypto/Cipher/_Blowfish.cpython-38-x86_64-linux-gnu.so
Binary files differ
diff --git a/frozen_deps/Crypto/Cipher/_CAST.cpython-38-x86_64-linux-gnu.so b/frozen_deps/Crypto/Cipher/_CAST.cpython-38-x86_64-linux-gnu.so
new file mode 100755
index 0000000..439731a
--- /dev/null
+++ b/frozen_deps/Crypto/Cipher/_CAST.cpython-38-x86_64-linux-gnu.so
Binary files differ
diff --git a/frozen_deps/Crypto/Cipher/_DES.cpython-38-x86_64-linux-gnu.so b/frozen_deps/Crypto/Cipher/_DES.cpython-38-x86_64-linux-gnu.so
new file mode 100755
index 0000000..e025c0d
--- /dev/null
+++ b/frozen_deps/Crypto/Cipher/_DES.cpython-38-x86_64-linux-gnu.so
Binary files differ
diff --git a/frozen_deps/Crypto/Cipher/_DES3.cpython-38-x86_64-linux-gnu.so b/frozen_deps/Crypto/Cipher/_DES3.cpython-38-x86_64-linux-gnu.so
new file mode 100755
index 0000000..faef3f9
--- /dev/null
+++ b/frozen_deps/Crypto/Cipher/_DES3.cpython-38-x86_64-linux-gnu.so
Binary files differ
diff --git a/frozen_deps/Crypto/Cipher/_XOR.cpython-38-x86_64-linux-gnu.so b/frozen_deps/Crypto/Cipher/_XOR.cpython-38-x86_64-linux-gnu.so
new file mode 100755
index 0000000..43f0560
--- /dev/null
+++ b/frozen_deps/Crypto/Cipher/_XOR.cpython-38-x86_64-linux-gnu.so
Binary files differ
diff --git a/frozen_deps/Crypto/Cipher/__init__.py b/frozen_deps/Crypto/Cipher/__init__.py
new file mode 100644
index 0000000..7afed2d
--- /dev/null
+++ b/frozen_deps/Crypto/Cipher/__init__.py
@@ -0,0 +1,83 @@
+# -*- coding: utf-8 -*-
+#
+# ===================================================================
+# The contents of this file are dedicated to the public domain. To
+# the extent that dedication to the public domain is not available,
+# everyone is granted a worldwide, perpetual, royalty-free,
+# non-exclusive license to exercise all rights associated with the
+# contents of this file for any purpose whatsoever.
+# No rights are reserved.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+# SOFTWARE.
+# ===================================================================
+
+"""Symmetric- and asymmetric-key encryption algorithms.
+
+Encryption algorithms transform plaintext in some way that
+is dependent on a key or key pair, producing ciphertext.
+
+Symmetric algorithms
+--------------------
+
+Encryption can easily be reversed, if (and, hopefully, only if)
+one knows the same key.
+In other words, sender and receiver share the same key.
+
+The symmetric encryption modules here all support the interface described in PEP
+272, "API for Block Encryption Algorithms".
+
+If you don't know which algorithm to choose, use AES because it's
+standard and has undergone a fair bit of examination.
+
+======================== ======= ========================
+Module name Type Description
+======================== ======= ========================
+`Crypto.Cipher.AES` Block Advanced Encryption Standard
+`Crypto.Cipher.ARC2` Block Alleged RC2
+`Crypto.Cipher.ARC4` Stream Alleged RC4
+`Crypto.Cipher.Blowfish` Block Blowfish
+`Crypto.Cipher.CAST` Block CAST
+`Crypto.Cipher.DES` Block The Data Encryption Standard.
+ Very commonly used in the past,
+ but today its 56-bit keys are too small.
+`Crypto.Cipher.DES3` Block Triple DES.
+`Crypto.Cipher.XOR` Stream The simple XOR cipher.
+======================== ======= ========================
+
+
+Asymmetric algorithms
+---------------------
+
+For asymmetric algorithms, the key to be used for decryption is totally
+different and cannot be derived in a feasible way from the key used
+for encryption. Put differently, sender and receiver each own one half
+of a key pair. The encryption key is often called ``public`` whereas
+the decryption key is called ``private``.
+
+========================== =======================
+Module name Description
+========================== =======================
+`Crypto.Cipher.PKCS1_v1_5` PKCS#1 v1.5 encryption, based on RSA key pairs
+`Crypto.Cipher.PKCS1_OAEP` PKCS#1 OAEP encryption, based on RSA key pairs
+========================== =======================
+
+:undocumented: __revision__, __package__, _AES, _ARC2, _ARC4, _Blowfish
+ _CAST, _DES, _DES3, _XOR
+"""
+
+__all__ = ['AES', 'ARC2', 'ARC4',
+ 'Blowfish', 'CAST', 'DES', 'DES3',
+ 'XOR',
+ 'PKCS1_v1_5', 'PKCS1_OAEP'
+ ]
+
+__revision__ = "$Id$"
+
+
diff --git a/frozen_deps/Crypto/Cipher/blockalgo.py b/frozen_deps/Crypto/Cipher/blockalgo.py
new file mode 100644
index 0000000..dd183dc
--- /dev/null
+++ b/frozen_deps/Crypto/Cipher/blockalgo.py
@@ -0,0 +1,296 @@
+# -*- coding: utf-8 -*-
+#
+# Cipher/blockalgo.py
+#
+# ===================================================================
+# The contents of this file are dedicated to the public domain. To
+# the extent that dedication to the public domain is not available,
+# everyone is granted a worldwide, perpetual, royalty-free,
+# non-exclusive license to exercise all rights associated with the
+# contents of this file for any purpose whatsoever.
+# No rights are reserved.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+# SOFTWARE.
+# ===================================================================
+"""Module with definitions common to all block ciphers."""
+
+import sys
+if sys.version_info[0] == 2 and sys.version_info[1] == 1:
+ from Crypto.Util.py21compat import *
+from Crypto.Util.py3compat import *
+
+#: *Electronic Code Book (ECB)*.
+#: This is the simplest encryption mode. Each of the plaintext blocks
+#: is directly encrypted into a ciphertext block, independently of
+#: any other block. This mode exposes frequency of symbols
+#: in your plaintext. Other modes (e.g. *CBC*) should be used instead.
+#:
+#: See `NIST SP800-38A`_ , Section 6.1 .
+#:
+#: .. _`NIST SP800-38A` : http://csrc.nist.gov/publications/nistpubs/800-38a/sp800-38a.pdf
+MODE_ECB = 1
+
+#: *Cipher-Block Chaining (CBC)*. Each of the ciphertext blocks depends
+#: on the current and all previous plaintext blocks. An Initialization Vector
+#: (*IV*) is required.
+#:
+#: The *IV* is a data block to be transmitted to the receiver.
+#: The *IV* can be made public, but it must be authenticated by the receiver and
+#: it should be picked randomly.
+#:
+#: See `NIST SP800-38A`_ , Section 6.2 .
+#:
+#: .. _`NIST SP800-38A` : http://csrc.nist.gov/publications/nistpubs/800-38a/sp800-38a.pdf
+MODE_CBC = 2
+
+#: *Cipher FeedBack (CFB)*. This mode is similar to CBC, but it transforms
+#: the underlying block cipher into a stream cipher. Plaintext and ciphertext
+#: are processed in *segments* of **s** bits. The mode is therefore sometimes
+#: labelled **s**-bit CFB. An Initialization Vector (*IV*) is required.
+#:
+#: When encrypting, each ciphertext segment contributes to the encryption of
+#: the next plaintext segment.
+#:
+#: This *IV* is a data block to be transmitted to the receiver.
+#: The *IV* can be made public, but it should be picked randomly.
+#: Reusing the same *IV* for encryptions done with the same key lead to
+#: catastrophic cryptographic failures.
+#:
+#: See `NIST SP800-38A`_ , Section 6.3 .
+#:
+#: .. _`NIST SP800-38A` : http://csrc.nist.gov/publications/nistpubs/800-38a/sp800-38a.pdf
+MODE_CFB = 3
+
+#: This mode should not be used.
+MODE_PGP = 4
+
+#: *Output FeedBack (OFB)*. This mode is very similar to CBC, but it
+#: transforms the underlying block cipher into a stream cipher.
+#: The keystream is the iterated block encryption of an Initialization Vector (*IV*).
+#:
+#: The *IV* is a data block to be transmitted to the receiver.
+#: The *IV* can be made public, but it should be picked randomly.
+#:
+#: Reusing the same *IV* for encryptions done with the same key lead to
+#: catastrophic cryptograhic failures.
+#:
+#: See `NIST SP800-38A`_ , Section 6.4 .
+#:
+#: .. _`NIST SP800-38A` : http://csrc.nist.gov/publications/nistpubs/800-38a/sp800-38a.pdf
+MODE_OFB = 5
+
+#: *CounTeR (CTR)*. This mode is very similar to ECB, in that
+#: encryption of one block is done independently of all other blocks.
+#: Unlike ECB, the block *position* contributes to the encryption and no
+#: information leaks about symbol frequency.
+#:
+#: Each message block is associated to a *counter* which must be unique
+#: across all messages that get encrypted with the same key (not just within
+#: the same message). The counter is as big as the block size.
+#:
+#: Counters can be generated in several ways. The most straightword one is
+#: to choose an *initial counter block* (which can be made public, similarly
+#: to the *IV* for the other modes) and increment its lowest **m** bits by
+#: one (modulo *2^m*) for each block. In most cases, **m** is chosen to be half
+#: the block size.
+#:
+#: Reusing the same *initial counter block* for encryptions done with the same
+#: key lead to catastrophic cryptograhic failures.
+#:
+#: See `NIST SP800-38A`_ , Section 6.5 (for the mode) and Appendix B (for how
+#: to manage the *initial counter block*).
+#:
+#: .. _`NIST SP800-38A` : http://csrc.nist.gov/publications/nistpubs/800-38a/sp800-38a.pdf
+MODE_CTR = 6
+
+#: OpenPGP. This mode is a variant of CFB, and it is only used in PGP and OpenPGP_ applications.
+#: An Initialization Vector (*IV*) is required.
+#:
+#: Unlike CFB, the IV is not transmitted to the receiver. Instead, the *encrypted* IV is.
+#: The IV is a random data block. Two of its bytes are duplicated to act as a checksum
+#: for the correctness of the key. The encrypted IV is therefore 2 bytes longer than
+#: the clean IV.
+#:
+#: .. _OpenPGP: http://tools.ietf.org/html/rfc4880
+MODE_OPENPGP = 7
+
+def _getParameter(name, index, args, kwargs, default=None):
+ """Find a parameter in tuple and dictionary arguments a function receives"""
+ param = kwargs.get(name)
+ if len(args)>index:
+ if param:
+ raise ValueError("Parameter '%s' is specified twice" % name)
+ param = args[index]
+ return param or default
+
+class BlockAlgo:
+ """Class modelling an abstract block cipher."""
+
+ def __init__(self, factory, key, *args, **kwargs):
+ self.mode = _getParameter('mode', 0, args, kwargs, default=MODE_ECB)
+ self.block_size = factory.block_size
+
+ if self.mode != MODE_OPENPGP:
+ self._cipher = factory.new(key, *args, **kwargs)
+ self.IV = self._cipher.IV
+ else:
+ # OPENPGP mode. For details, see 13.9 in RCC4880.
+ #
+ # A few members are specifically created for this mode:
+ # - _encrypted_iv, set in this constructor
+ # - _done_first_block, set to True after the first encryption
+ # - _done_last_block, set to True after a partial block is processed
+
+ self._done_first_block = False
+ self._done_last_block = False
+ self.IV = _getParameter('iv', 1, args, kwargs)
+ if not self.IV:
+ raise ValueError("MODE_OPENPGP requires an IV")
+
+ # Instantiate a temporary cipher to process the IV
+ IV_cipher = factory.new(key, MODE_CFB,
+ b('\x00')*self.block_size, # IV for CFB
+ segment_size=self.block_size*8)
+
+ # The cipher will be used for...
+ if len(self.IV) == self.block_size:
+ # ... encryption
+ self._encrypted_IV = IV_cipher.encrypt(
+ self.IV + self.IV[-2:] + # Plaintext
+ b('\x00')*(self.block_size-2) # Padding
+ )[:self.block_size+2]
+ elif len(self.IV) == self.block_size+2:
+ # ... decryption
+ self._encrypted_IV = self.IV
+ self.IV = IV_cipher.decrypt(self.IV + # Ciphertext
+ b('\x00')*(self.block_size-2) # Padding
+ )[:self.block_size+2]
+ if self.IV[-2:] != self.IV[-4:-2]:
+ raise ValueError("Failed integrity check for OPENPGP IV")
+ self.IV = self.IV[:-2]
+ else:
+ raise ValueError("Length of IV must be %d or %d bytes for MODE_OPENPGP"
+ % (self.block_size, self.block_size+2))
+
+ # Instantiate the cipher for the real PGP data
+ self._cipher = factory.new(key, MODE_CFB,
+ self._encrypted_IV[-self.block_size:],
+ segment_size=self.block_size*8)
+
+ def encrypt(self, plaintext):
+ """Encrypt data with the key and the parameters set at initialization.
+
+ The cipher object is stateful; encryption of a long block
+ of data can be broken up in two or more calls to `encrypt()`.
+ That is, the statement:
+
+ >>> c.encrypt(a) + c.encrypt(b)
+
+ is always equivalent to:
+
+ >>> c.encrypt(a+b)
+
+ That also means that you cannot reuse an object for encrypting
+ or decrypting other data with the same key.
+
+ This function does not perform any padding.
+
+ - For `MODE_ECB`, `MODE_CBC`, and `MODE_OFB`, *plaintext* length
+ (in bytes) must be a multiple of *block_size*.
+
+ - For `MODE_CFB`, *plaintext* length (in bytes) must be a multiple
+ of *segment_size*/8.
+
+ - For `MODE_CTR`, *plaintext* can be of any length.
+
+ - For `MODE_OPENPGP`, *plaintext* must be a multiple of *block_size*,
+ unless it is the last chunk of the message.
+
+ :Parameters:
+ plaintext : byte string
+ The piece of data to encrypt.
+ :Return:
+ the encrypted data, as a byte string. It is as long as
+ *plaintext* with one exception: when encrypting the first message
+ chunk with `MODE_OPENPGP`, the encypted IV is prepended to the
+ returned ciphertext.
+ """
+
+ if self.mode == MODE_OPENPGP:
+ padding_length = (self.block_size - len(plaintext) % self.block_size) % self.block_size
+ if padding_length>0:
+ # CFB mode requires ciphertext to have length multiple of block size,
+ # but PGP mode allows the last block to be shorter
+ if self._done_last_block:
+ raise ValueError("Only the last chunk is allowed to have length not multiple of %d bytes",
+ self.block_size)
+ self._done_last_block = True
+ padded = plaintext + b('\x00')*padding_length
+ res = self._cipher.encrypt(padded)[:len(plaintext)]
+ else:
+ res = self._cipher.encrypt(plaintext)
+ if not self._done_first_block:
+ res = self._encrypted_IV + res
+ self._done_first_block = True
+ return res
+
+ return self._cipher.encrypt(plaintext)
+
+ def decrypt(self, ciphertext):
+ """Decrypt data with the key and the parameters set at initialization.
+
+ The cipher object is stateful; decryption of a long block
+ of data can be broken up in two or more calls to `decrypt()`.
+ That is, the statement:
+
+ >>> c.decrypt(a) + c.decrypt(b)
+
+ is always equivalent to:
+
+ >>> c.decrypt(a+b)
+
+ That also means that you cannot reuse an object for encrypting
+ or decrypting other data with the same key.
+
+ This function does not perform any padding.
+
+ - For `MODE_ECB`, `MODE_CBC`, and `MODE_OFB`, *ciphertext* length
+ (in bytes) must be a multiple of *block_size*.
+
+ - For `MODE_CFB`, *ciphertext* length (in bytes) must be a multiple
+ of *segment_size*/8.
+
+ - For `MODE_CTR`, *ciphertext* can be of any length.
+
+ - For `MODE_OPENPGP`, *plaintext* must be a multiple of *block_size*,
+ unless it is the last chunk of the message.
+
+ :Parameters:
+ ciphertext : byte string
+ The piece of data to decrypt.
+ :Return: the decrypted data (byte string, as long as *ciphertext*).
+ """
+ if self.mode == MODE_OPENPGP:
+ padding_length = (self.block_size - len(ciphertext) % self.block_size) % self.block_size
+ if padding_length>0:
+ # CFB mode requires ciphertext to have length multiple of block size,
+ # but PGP mode allows the last block to be shorter
+ if self._done_last_block:
+ raise ValueError("Only the last chunk is allowed to have length not multiple of %d bytes",
+ self.block_size)
+ self._done_last_block = True
+ padded = ciphertext + b('\x00')*padding_length
+ res = self._cipher.decrypt(padded)[:len(ciphertext)]
+ else:
+ res = self._cipher.decrypt(ciphertext)
+ return res
+
+ return self._cipher.decrypt(ciphertext)
+
diff --git a/frozen_deps/Crypto/Hash/HMAC.py b/frozen_deps/Crypto/Hash/HMAC.py
new file mode 100644
index 0000000..324f534
--- /dev/null
+++ b/frozen_deps/Crypto/Hash/HMAC.py
@@ -0,0 +1,212 @@
+# HMAC.py - Implements the HMAC algorithm as described by RFC 2104.
+#
+# ===================================================================
+# Portions Copyright (c) 2001, 2002, 2003 Python Software Foundation;
+# All Rights Reserved
+#
+# This file contains code from the Python 2.2 hmac.py module (the
+# "Original Code"), with modifications made after it was incorporated
+# into PyCrypto (the "Modifications").
+#
+# To the best of our knowledge, the Python Software Foundation is the
+# copyright holder of the Original Code, and has licensed it under the
+# Python 2.2 license. See the file LEGAL/copy/LICENSE.python-2.2 for
+# details.
+#
+# The Modifications to this file are dedicated to the public domain.
+# To the extent that dedication to the public domain is not available,
+# everyone is granted a worldwide, perpetual, royalty-free,
+# non-exclusive license to exercise all rights associated with the
+# contents of this file for any purpose whatsoever. No rights are
+# reserved.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+# SOFTWARE.
+# ===================================================================
+
+
+"""HMAC (Hash-based Message Authentication Code) algorithm
+
+HMAC is a MAC defined in RFC2104_ and FIPS-198_ and constructed using
+a cryptograpic hash algorithm.
+It is usually named *HMAC-X*, where *X* is the hash algorithm; for
+instance *HMAC-SHA1* or *HMAC-MD5*.
+
+The strength of an HMAC depends on:
+
+ - the strength of the hash algorithm
+ - the length and entropy of the secret key
+
+An example of possible usage is the following:
+
+ >>> from Crypto.Hash import HMAC
+ >>>
+ >>> secret = b'Swordfish'
+ >>> h = HMAC.new(secret)
+ >>> h.update(b'Hello')
+ >>> print h.hexdigest()
+
+.. _RFC2104: http://www.ietf.org/rfc/rfc2104.txt
+.. _FIPS-198: http://csrc.nist.gov/publications/fips/fips198/fips-198a.pdf
+"""
+
+# This is just a copy of the Python 2.2 HMAC module, modified to work when
+# used on versions of Python before 2.2.
+
+__revision__ = "$Id$"
+
+__all__ = ['new', 'digest_size', 'HMAC' ]
+
+from Crypto.Util.strxor import strxor_c
+from Crypto.Util.py3compat import *
+
+#: The size of the authentication tag produced by the MAC.
+#: It matches the digest size on the underlying
+#: hashing module used.
+digest_size = None
+
+class HMAC:
+ """Class that implements HMAC"""
+
+ #: The size of the authentication tag produced by the MAC.
+ #: It matches the digest size on the underlying
+ #: hashing module used.
+ digest_size = None
+
+ def __init__(self, key, msg = None, digestmod = None):
+ """Create a new HMAC object.
+
+ :Parameters:
+ key : byte string
+ secret key for the MAC object.
+ It must be long enough to match the expected security level of the
+ MAC. However, there is no benefit in using keys longer than the
+ `digest_size` of the underlying hash algorithm.
+ msg : byte string
+ The very first chunk of the message to authenticate.
+ It is equivalent to an early call to `update()`. Optional.
+ :Parameter digestmod:
+ The hash algorithm the HMAC is based on.
+ Default is `Crypto.Hash.MD5`.
+ :Type digestmod:
+ A hash module or object instantiated from `Crypto.Hash`
+ """
+ if digestmod is None:
+ from . import MD5
+ digestmod = MD5
+
+ self.digestmod = digestmod
+ self.outer = digestmod.new()
+ self.inner = digestmod.new()
+ try:
+ self.digest_size = digestmod.digest_size
+ except AttributeError:
+ self.digest_size = len(self.outer.digest())
+
+ try:
+ # The block size is 128 bytes for SHA384 and SHA512 and 64 bytes
+ # for the others hash function
+ blocksize = digestmod.block_size
+ except AttributeError:
+ blocksize = 64
+
+ ipad = 0x36
+ opad = 0x5C
+
+ if len(key) > blocksize:
+ key = digestmod.new(key).digest()
+
+ key = key + bchr(0) * (blocksize - len(key))
+ self.outer.update(strxor_c(key, opad))
+ self.inner.update(strxor_c(key, ipad))
+ if (msg):
+ self.update(msg)
+
+ def update(self, msg):
+ """Continue authentication of a message by consuming the next chunk of data.
+
+ Repeated calls are equivalent to a single call with the concatenation
+ of all the arguments. In other words:
+
+ >>> m.update(a); m.update(b)
+
+ is equivalent to:
+
+ >>> m.update(a+b)
+
+ :Parameters:
+ msg : byte string
+ The next chunk of the message being authenticated
+ """
+
+ self.inner.update(msg)
+
+ def copy(self):
+ """Return a copy ("clone") of the MAC object.
+
+ The copy will have the same internal state as the original MAC
+ object.
+ This can be used to efficiently compute the MAC of strings that
+ share a common initial substring.
+
+ :Returns: An `HMAC` object
+ """
+ other = HMAC(b(""))
+ other.digestmod = self.digestmod
+ other.inner = self.inner.copy()
+ other.outer = self.outer.copy()
+ return other
+
+ def digest(self):
+ """Return the **binary** (non-printable) MAC of the message that has
+ been authenticated so far.
+
+ This method does not change the state of the MAC object.
+ You can continue updating the object after calling this function.
+
+ :Return: A byte string of `digest_size` bytes. It may contain non-ASCII
+ characters, including null bytes.
+ """
+ h = self.outer.copy()
+ h.update(self.inner.digest())
+ return h.digest()
+
+ def hexdigest(self):
+ """Return the **printable** MAC of the message that has been
+ authenticated so far.
+
+ This method does not change the state of the MAC object.
+
+ :Return: A string of 2* `digest_size` bytes. It contains only
+ hexadecimal ASCII digits.
+ """
+ return "".join(["%02x" % bord(x)
+ for x in tuple(self.digest())])
+
+def new(key, msg = None, digestmod = None):
+ """Create a new HMAC object.
+
+ :Parameters:
+ key : byte string
+ key for the MAC object.
+ It must be long enough to match the expected security level of the
+ MAC. However, there is no benefit in using keys longer than the
+ `digest_size` of the underlying hash algorithm.
+ msg : byte string
+ The very first chunk of the message to authenticate.
+ It is equivalent to an early call to `HMAC.update()`.
+ Optional.
+ :Parameter digestmod:
+ The hash to use to implement the HMAC. Default is `Crypto.Hash.MD5`.
+ :Type digestmod:
+ A hash module or instantiated object from `Crypto.Hash`
+ :Returns: An `HMAC` object
+ """
+ return HMAC(key, msg, digestmod)
+
diff --git a/frozen_deps/Crypto/Hash/MD2.py b/frozen_deps/Crypto/Hash/MD2.py
new file mode 100644
index 0000000..dac959e
--- /dev/null
+++ b/frozen_deps/Crypto/Hash/MD2.py
@@ -0,0 +1,91 @@
+# -*- coding: utf-8 -*-
+#
+# ===================================================================
+# The contents of this file are dedicated to the public domain. To
+# the extent that dedication to the public domain is not available,
+# everyone is granted a worldwide, perpetual, royalty-free,
+# non-exclusive license to exercise all rights associated with the
+# contents of this file for any purpose whatsoever.
+# No rights are reserved.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+# SOFTWARE.
+# ===================================================================
+
+"""MD2 cryptographic hash algorithm.
+
+MD2 is specified in RFC1319_ and it produces the 128 bit digest of a message.
+
+ >>> from Crypto.Hash import MD2
+ >>>
+ >>> h = MD2.new()
+ >>> h.update(b'Hello')
+ >>> print h.hexdigest()
+
+MD2 stand for Message Digest version 2, and it was invented by Rivest in 1989.
+
+This algorithm is both slow and insecure. Do not use it for new designs.
+
+.. _RFC1319: http://tools.ietf.org/html/rfc1319
+"""
+
+_revision__ = "$Id$"
+
+__all__ = ['new', 'digest_size', 'MD2Hash' ]
+
+from Crypto.Util.py3compat import *
+from Crypto.Hash.hashalgo import HashAlgo
+
+import Crypto.Hash._MD2 as _MD2
+hashFactory = _MD2
+
+class MD2Hash(HashAlgo):
+ """Class that implements an MD2 hash
+
+ :undocumented: block_size
+ """
+
+ #: ASN.1 Object identifier (OID)::
+ #:
+ #: id-md2 OBJECT IDENTIFIER ::= {
+ #: iso(1) member-body(2) us(840) rsadsi(113549)
+ #: digestAlgorithm(2) 2
+ #: }
+ #:
+ #: This value uniquely identifies the MD2 algorithm.
+ oid = b('\x06\x08\x2a\x86\x48\x86\xf7\x0d\x02\x02')
+
+ digest_size = 16
+ block_size = 16
+
+ def __init__(self, data=None):
+ HashAlgo.__init__(self, hashFactory, data)
+
+ def new(self, data=None):
+ return MD2Hash(data)
+
+def new(data=None):
+ """Return a fresh instance of the hash object.
+
+ :Parameters:
+ data : byte string
+ The very first chunk of the message to hash.
+ It is equivalent to an early call to `MD2Hash.update()`.
+ Optional.
+
+ :Return: An `MD2Hash` object
+ """
+ return MD2Hash().new(data)
+
+#: The size of the resulting hash in bytes.
+digest_size = MD2Hash.digest_size
+
+#: The internal block size of the hash algorithm in bytes.
+block_size = MD2Hash.block_size
+
diff --git a/frozen_deps/Crypto/Hash/MD4.py b/frozen_deps/Crypto/Hash/MD4.py
new file mode 100644
index 0000000..e28a201
--- /dev/null
+++ b/frozen_deps/Crypto/Hash/MD4.py
@@ -0,0 +1,91 @@
+# -*- coding: utf-8 -*-
+#
+# ===================================================================
+# The contents of this file are dedicated to the public domain. To
+# the extent that dedication to the public domain is not available,
+# everyone is granted a worldwide, perpetual, royalty-free,
+# non-exclusive license to exercise all rights associated with the
+# contents of this file for any purpose whatsoever.
+# No rights are reserved.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+# SOFTWARE.
+# ===================================================================
+
+"""MD4 cryptographic hash algorithm.
+
+MD4 is specified in RFC1320_ and produces the 128 bit digest of a message.
+
+ >>> from Crypto.Hash import MD4
+ >>>
+ >>> h = MD4.new()
+ >>> h.update(b'Hello')
+ >>> print h.hexdigest()
+
+MD4 stand for Message Digest version 4, and it was invented by Rivest in 1990.
+
+This algorithm is insecure. Do not use it for new designs.
+
+.. _RFC1320: http://tools.ietf.org/html/rfc1320
+"""
+
+_revision__ = "$Id$"
+
+__all__ = ['new', 'digest_size', 'MD4Hash' ]
+
+from Crypto.Util.py3compat import *
+from Crypto.Hash.hashalgo import HashAlgo
+
+import Crypto.Hash._MD4 as _MD4
+hashFactory = _MD4
+
+class MD4Hash(HashAlgo):
+ """Class that implements an MD4 hash
+
+ :undocumented: block_size
+ """
+
+ #: ASN.1 Object identifier (OID)::
+ #:
+ #: id-md2 OBJECT IDENTIFIER ::= {
+ #: iso(1) member-body(2) us(840) rsadsi(113549)
+ #: digestAlgorithm(2) 4
+ #: }
+ #:
+ #: This value uniquely identifies the MD4 algorithm.
+ oid = b('\x06\x08\x2a\x86\x48\x86\xf7\x0d\x02\x04')
+
+ digest_size = 16
+ block_size = 64
+
+ def __init__(self, data=None):
+ HashAlgo.__init__(self, hashFactory, data)
+
+ def new(self, data=None):
+ return MD4Hash(data)
+
+def new(data=None):
+ """Return a fresh instance of the hash object.
+
+ :Parameters:
+ data : byte string
+ The very first chunk of the message to hash.
+ It is equivalent to an early call to `MD4Hash.update()`.
+ Optional.
+
+ :Return: A `MD4Hash` object
+ """
+ return MD4Hash().new(data)
+
+#: The size of the resulting hash in bytes.
+digest_size = MD4Hash.digest_size
+
+#: The internal block size of the hash algorithm in bytes.
+block_size = MD4Hash.block_size
+
diff --git a/frozen_deps/Crypto/Hash/MD5.py b/frozen_deps/Crypto/Hash/MD5.py
new file mode 100644
index 0000000..18e9e7b
--- /dev/null
+++ b/frozen_deps/Crypto/Hash/MD5.py
@@ -0,0 +1,97 @@
+# -*- coding: utf-8 -*-
+#
+# ===================================================================
+# The contents of this file are dedicated to the public domain. To
+# the extent that dedication to the public domain is not available,
+# everyone is granted a worldwide, perpetual, royalty-free,
+# non-exclusive license to exercise all rights associated with the
+# contents of this file for any purpose whatsoever.
+# No rights are reserved.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+# SOFTWARE.
+# ===================================================================
+
+"""MD5 cryptographic hash algorithm.
+
+MD5 is specified in RFC1321_ and produces the 128 bit digest of a message.
+
+ >>> from Crypto.Hash import MD5
+ >>>
+ >>> h = MD5.new()
+ >>> h.update(b'Hello')
+ >>> print h.hexdigest()
+
+MD5 stand for Message Digest version 5, and it was invented by Rivest in 1991.
+
+This algorithm is insecure. Do not use it for new designs.
+
+.. _RFC1321: http://tools.ietf.org/html/rfc1321
+"""
+
+_revision__ = "$Id$"
+
+__all__ = ['new', 'digest_size', 'MD5Hash' ]
+
+from Crypto.Util.py3compat import *
+from Crypto.Hash.hashalgo import HashAlgo
+
+try:
+ # The md5 module is deprecated in Python 2.6, so use hashlib when possible.
+ import hashlib
+ hashFactory = hashlib.md5
+
+except ImportError:
+ import md5
+ hashFactory = md5
+
+class MD5Hash(HashAlgo):
+ """Class that implements an MD5 hash
+
+ :undocumented: block_size
+ """
+
+ #: ASN.1 Object identifier (OID)::
+ #:
+ #: id-md5 OBJECT IDENTIFIER ::= {
+ #: iso(1) member-body(2) us(840) rsadsi(113549)
+ #: digestAlgorithm(2) 5
+ #: }
+ #:
+ #: This value uniquely identifies the MD5 algorithm.
+ oid = b('\x06\x08\x2a\x86\x48\x86\xf7\x0d\x02\x05')
+
+ digest_size = 16
+ block_size = 64
+
+ def __init__(self, data=None):
+ HashAlgo.__init__(self, hashFactory, data)
+
+ def new(self, data=None):
+ return MD5Hash(data)
+
+def new(data=None):
+ """Return a fresh instance of the hash object.
+
+ :Parameters:
+ data : byte string
+ The very first chunk of the message to hash.
+ It is equivalent to an early call to `MD5Hash.update()`.
+ Optional.
+
+ :Return: A `MD5Hash` object
+ """
+ return MD5Hash().new(data)
+
+#: The size of the resulting hash in bytes.
+digest_size = MD5Hash.digest_size
+
+#: The internal block size of the hash algorithm in bytes.
+block_size = MD5Hash.block_size
+
diff --git a/frozen_deps/Crypto/Hash/RIPEMD.py b/frozen_deps/Crypto/Hash/RIPEMD.py
new file mode 100644
index 0000000..33099cb
--- /dev/null
+++ b/frozen_deps/Crypto/Hash/RIPEMD.py
@@ -0,0 +1,94 @@
+# -*- coding: utf-8 -*-
+#
+# ===================================================================
+# The contents of this file are dedicated to the public domain. To
+# the extent that dedication to the public domain is not available,
+# everyone is granted a worldwide, perpetual, royalty-free,
+# non-exclusive license to exercise all rights associated with the
+# contents of this file for any purpose whatsoever.
+# No rights are reserved.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+# SOFTWARE.
+# ===================================================================
+
+"""RIPEMD-160 cryptographic hash algorithm.
+
+RIPEMD-160_ produces the 160 bit digest of a message.
+
+ >>> from Crypto.Hash import RIPEMD
+ >>>
+ >>> h = RIPEMD.new()
+ >>> h.update(b'Hello')
+ >>> print h.hexdigest()
+
+RIPEMD-160 stands for RACE Integrity Primitives Evaluation Message Digest
+with a 160 bit digest. It was invented by Dobbertin, Bosselaers, and Preneel.
+
+This algorithm is considered secure, although it has not been scrutinized as
+extensively as SHA-1. Moreover, it provides an informal security level of just
+80bits.
+
+.. _RIPEMD-160: http://homes.esat.kuleuven.be/~bosselae/ripemd160.html
+"""
+
+_revision__ = "$Id$"
+
+__all__ = ['new', 'digest_size', 'RIPEMD160Hash' ]
+
+from Crypto.Util.py3compat import *
+from Crypto.Hash.hashalgo import HashAlgo
+
+import Crypto.Hash._RIPEMD160 as _RIPEMD160
+hashFactory = _RIPEMD160
+
+class RIPEMD160Hash(HashAlgo):
+ """Class that implements a RIPMD-160 hash
+
+ :undocumented: block_size
+ """
+
+ #: ASN.1 Object identifier (OID)::
+ #:
+ #: id-ripemd160 OBJECT IDENTIFIER ::= {
+ #: iso(1) identified-organization(3) teletrust(36)
+ #: algorithm(3) hashAlgorithm(2) ripemd160(1)
+ #: }
+ #:
+ #: This value uniquely identifies the RIPMD-160 algorithm.
+ oid = b("\x06\x05\x2b\x24\x03\x02\x01")
+
+ digest_size = 20
+ block_size = 64
+
+ def __init__(self, data=None):
+ HashAlgo.__init__(self, hashFactory, data)
+
+ def new(self, data=None):
+ return RIPEMD160Hash(data)
+
+def new(data=None):
+ """Return a fresh instance of the hash object.
+
+ :Parameters:
+ data : byte string
+ The very first chunk of the message to hash.
+ It is equivalent to an early call to `RIPEMD160Hash.update()`.
+ Optional.
+
+ :Return: A `RIPEMD160Hash` object
+ """
+ return RIPEMD160Hash().new(data)
+
+#: The size of the resulting hash in bytes.
+digest_size = RIPEMD160Hash.digest_size
+
+#: The internal block size of the hash algorithm in bytes.
+block_size = RIPEMD160Hash.block_size
+
diff --git a/frozen_deps/Crypto/Hash/SHA.py b/frozen_deps/Crypto/Hash/SHA.py
new file mode 100644
index 0000000..0bc5917
--- /dev/null
+++ b/frozen_deps/Crypto/Hash/SHA.py
@@ -0,0 +1,98 @@
+# -*- coding: utf-8 -*-
+#
+# ===================================================================
+# The contents of this file are dedicated to the public domain. To
+# the extent that dedication to the public domain is not available,
+# everyone is granted a worldwide, perpetual, royalty-free,
+# non-exclusive license to exercise all rights associated with the
+# contents of this file for any purpose whatsoever.
+# No rights are reserved.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+# SOFTWARE.
+# ===================================================================
+
+"""SHA-1 cryptographic hash algorithm.
+
+SHA-1_ produces the 160 bit digest of a message.
+
+ >>> from Crypto.Hash import SHA
+ >>>
+ >>> h = SHA.new()
+ >>> h.update(b'Hello')
+ >>> print h.hexdigest()
+
+*SHA* stands for Secure Hash Algorithm.
+
+This algorithm is not considered secure. Do not use it for new designs.
+
+.. _SHA-1: http://csrc.nist.gov/publications/fips/fips180-2/fips180-2.pdf
+"""
+
+_revision__ = "$Id$"
+
+__all__ = ['new', 'digest_size', 'SHA1Hash' ]
+
+from Crypto.Util.py3compat import *
+from Crypto.Hash.hashalgo import HashAlgo
+
+try:
+ # The sha module is deprecated in Python 2.6, so use hashlib when possible.
+ import hashlib
+ hashFactory = hashlib.sha1
+
+except ImportError:
+ import sha
+ hashFactory = sha
+
+class SHA1Hash(HashAlgo):
+ """Class that implements a SHA-1 hash
+
+ :undocumented: block_size
+ """
+
+ #: ASN.1 Object identifier (OID)::
+ #:
+ #: id-sha1 OBJECT IDENTIFIER ::= {
+ #: iso(1) identified-organization(3) oiw(14) secsig(3)
+ #: algorithms(2) 26
+ #: }
+ #:
+ #: This value uniquely identifies the SHA-1 algorithm.
+ oid = b('\x06\x05\x2b\x0e\x03\x02\x1a')
+
+ digest_size = 20
+ block_size = 64
+
+ def __init__(self, data=None):
+ HashAlgo.__init__(self, hashFactory, data)
+
+ def new(self, data=None):
+ return SHA1Hash(data)
+
+def new(data=None):
+ """Return a fresh instance of the hash object.
+
+ :Parameters:
+ data : byte string
+ The very first chunk of the message to hash.
+ It is equivalent to an early call to `SHA1Hash.update()`.
+ Optional.
+
+ :Return: A `SHA1Hash` object
+ """
+ return SHA1Hash().new(data)
+
+#: The size of the resulting hash in bytes.
+digest_size = SHA1Hash.digest_size
+
+#: The internal block size of the hash algorithm in bytes.
+block_size = SHA1Hash.block_size
+
+
diff --git a/frozen_deps/Crypto/Hash/SHA224.py b/frozen_deps/Crypto/Hash/SHA224.py
new file mode 100644
index 0000000..959b56d
--- /dev/null
+++ b/frozen_deps/Crypto/Hash/SHA224.py
@@ -0,0 +1,95 @@
+# -*- coding: utf-8 -*-
+#
+# ===================================================================
+# The contents of this file are dedicated to the public domain. To
+# the extent that dedication to the public domain is not available,
+# everyone is granted a worldwide, perpetual, royalty-free,
+# non-exclusive license to exercise all rights associated with the
+# contents of this file for any purpose whatsoever.
+# No rights are reserved.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+# SOFTWARE.
+# ===================================================================
+
+"""SHA-224 cryptographic hash algorithm.
+
+SHA-224 belongs to the SHA-2_ family of cryptographic hashes.
+It produces the 224 bit digest of a message.
+
+ >>> from Crypto.Hash import SHA224
+ >>>
+ >>> h = SHA224.new()
+ >>> h.update(b'Hello')
+ >>> print h.hexdigest()
+
+*SHA* stands for Secure Hash Algorithm.
+
+.. _SHA-2: http://csrc.nist.gov/publications/fips/fips180-2/fips180-2.pdf
+"""
+
+_revision__ = "$Id$"
+
+__all__ = ['new', 'digest_size', 'SHA224Hash' ]
+
+from Crypto.Util.py3compat import *
+from Crypto.Hash.hashalgo import HashAlgo
+
+try:
+ import hashlib
+ hashFactory = hashlib.sha224
+
+except ImportError:
+ from Crypto.Hash import _SHA224
+ hashFactory = _SHA224
+
+class SHA224Hash(HashAlgo):
+ """Class that implements a SHA-224 hash
+
+ :undocumented: block_size
+ """
+
+ #: ASN.1 Object identifier (OID)::
+ #:
+ #: id-sha224 OBJECT IDENTIFIER ::= {
+ #: joint-iso-itu-t(2) country(16) us(840) organization(1) gov(101) csor(3)
+ #: nistalgorithm(4) hashalgs(2) 4
+ #: }
+ #:
+ #: This value uniquely identifies the SHA-224 algorithm.
+ oid = b('\x06\x09\x60\x86\x48\x01\x65\x03\x04\x02\x04')
+
+ digest_size = 28
+ block_size = 64
+
+ def __init__(self, data=None):
+ HashAlgo.__init__(self, hashFactory, data)
+
+ def new(self, data=None):
+ return SHA224Hash(data)
+
+def new(data=None):
+ """Return a fresh instance of the hash object.
+
+ :Parameters:
+ data : byte string
+ The very first chunk of the message to hash.
+ It is equivalent to an early call to `SHA224Hash.update()`.
+ Optional.
+
+ :Return: A `SHA224Hash` object
+ """
+ return SHA224Hash().new(data)
+
+#: The size of the resulting hash in bytes.
+digest_size = SHA224Hash.digest_size
+
+#: The internal block size of the hash algorithm in bytes.
+block_size = SHA224Hash.block_size
+
diff --git a/frozen_deps/Crypto/Hash/SHA256.py b/frozen_deps/Crypto/Hash/SHA256.py
new file mode 100644
index 0000000..b0a99b3
--- /dev/null
+++ b/frozen_deps/Crypto/Hash/SHA256.py
@@ -0,0 +1,95 @@
+# -*- coding: utf-8 -*-
+#
+# ===================================================================
+# The contents of this file are dedicated to the public domain. To
+# the extent that dedication to the public domain is not available,
+# everyone is granted a worldwide, perpetual, royalty-free,
+# non-exclusive license to exercise all rights associated with the
+# contents of this file for any purpose whatsoever.
+# No rights are reserved.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+# SOFTWARE.
+# ===================================================================
+
+"""SHA-256 cryptographic hash algorithm.
+
+SHA-256 belongs to the SHA-2_ family of cryptographic hashes.
+It produces the 256 bit digest of a message.
+
+ >>> from Crypto.Hash import SHA256
+ >>>
+ >>> h = SHA256.new()
+ >>> h.update(b'Hello')
+ >>> print h.hexdigest()
+
+*SHA* stands for Secure Hash Algorithm.
+
+.. _SHA-2: http://csrc.nist.gov/publications/fips/fips180-2/fips180-2.pdf
+"""
+
+_revision__ = "$Id$"
+
+__all__ = ['new', 'digest_size', 'SHA256Hash' ]
+
+from Crypto.Util.py3compat import *
+from Crypto.Hash.hashalgo import HashAlgo
+
+try:
+ import hashlib
+ hashFactory = hashlib.sha256
+
+except ImportError:
+ from Crypto.Hash import _SHA256
+ hashFactory = _SHA256
+
+class SHA256Hash(HashAlgo):
+ """Class that implements a SHA-256 hash
+
+ :undocumented: block_size
+ """
+
+ #: ASN.1 Object identifier (OID)::
+ #:
+ #: id-sha256 OBJECT IDENTIFIER ::= {
+ #: joint-iso-itu-t(2) country(16) us(840) organization(1)
+ #: gov(101) csor(3) nistalgorithm(4) hashalgs(2) 1
+ #: }
+ #:
+ #: This value uniquely identifies the SHA-256 algorithm.
+ oid = b('\x06\x09\x60\x86\x48\x01\x65\x03\x04\x02\x01')
+
+ digest_size = 32
+ block_size = 64
+
+ def __init__(self, data=None):
+ HashAlgo.__init__(self, hashFactory, data)
+
+ def new(self, data=None):
+ return SHA256Hash(data)
+
+def new(data=None):
+ """Return a fresh instance of the hash object.
+
+ :Parameters:
+ data : byte string
+ The very first chunk of the message to hash.
+ It is equivalent to an early call to `SHA256Hash.update()`.
+ Optional.
+
+ :Return: A `SHA256Hash` object
+ """
+ return SHA256Hash().new(data)
+
+#: The size of the resulting hash in bytes.
+digest_size = SHA256Hash.digest_size
+
+#: The internal block size of the hash algorithm in bytes.
+block_size = SHA256Hash.block_size
+
diff --git a/frozen_deps/Crypto/Hash/SHA384.py b/frozen_deps/Crypto/Hash/SHA384.py
new file mode 100644
index 0000000..3490b02
--- /dev/null
+++ b/frozen_deps/Crypto/Hash/SHA384.py
@@ -0,0 +1,96 @@
+# -*- coding: utf-8 -*-
+#
+# ===================================================================
+# The contents of this file are dedicated to the public domain. To
+# the extent that dedication to the public domain is not available,
+# everyone is granted a worldwide, perpetual, royalty-free,
+# non-exclusive license to exercise all rights associated with the
+# contents of this file for any purpose whatsoever.
+# No rights are reserved.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+# SOFTWARE.
+# ===================================================================
+
+"""SHA-384 cryptographic hash algorithm.
+
+SHA-384 belongs to the SHA-2_ family of cryptographic hashes.
+It produces the 384 bit digest of a message.
+
+ >>> from Crypto.Hash import SHA384
+ >>>
+ >>> h = SHA384.new()
+ >>> h.update(b'Hello')
+ >>> print h.hexdigest()
+
+*SHA* stands for Secure Hash Algorithm.
+
+.. _SHA-2: http://csrc.nist.gov/publications/fips/fips180-2/fips180-2.pdf
+"""
+
+_revision__ = "$Id$"
+
+__all__ = ['new', 'digest_size', 'SHA384Hash' ]
+
+from Crypto.Util.py3compat import *
+from Crypto.Hash.hashalgo import HashAlgo
+
+try:
+ import hashlib
+ hashFactory = hashlib.sha384
+
+except ImportError:
+ from Crypto.Hash import _SHA384
+ hashFactory = _SHA384
+
+class SHA384Hash(HashAlgo):
+ """Class that implements a SHA-384 hash
+
+ :undocumented: block_size
+ """
+
+ #: ASN.1 Object identifier (OID)::
+ #:
+ #: id-sha384 OBJECT IDENTIFIER ::= {
+ #: joint-iso-itu-t(2) country(16) us(840) organization(1) gov(101) csor(3)
+ #: nistalgorithm(4) hashalgs(2) 2
+ #: }
+ #:
+ #: This value uniquely identifies the SHA-384 algorithm.
+ oid = b('\x06\x09\x60\x86\x48\x01\x65\x03\x04\x02\x02')
+
+ digest_size = 48
+ block_size = 128
+
+ def __init__(self, data=None):
+ HashAlgo.__init__(self, hashFactory, data)
+
+ def new(self, data=None):
+ return SHA384Hash(data)
+
+def new(data=None):
+ """Return a fresh instance of the hash object.
+
+ :Parameters:
+ data : byte string
+ The very first chunk of the message to hash.
+ It is equivalent to an early call to `SHA384Hash.update()`.
+ Optional.
+
+ :Return: A `SHA384Hash` object
+ """
+ return SHA384Hash().new(data)
+
+#: The size of the resulting hash in bytes.
+digest_size = SHA384Hash.digest_size
+
+#: The internal block size of the hash algorithm in bytes.
+block_size = SHA384Hash.block_size
+
+
diff --git a/frozen_deps/Crypto/Hash/SHA512.py b/frozen_deps/Crypto/Hash/SHA512.py
new file mode 100644
index 0000000..d57548d
--- /dev/null
+++ b/frozen_deps/Crypto/Hash/SHA512.py
@@ -0,0 +1,95 @@
+# -*- coding: utf-8 -*-
+#
+# ===================================================================
+# The contents of this file are dedicated to the public domain. To
+# the extent that dedication to the public domain is not available,
+# everyone is granted a worldwide, perpetual, royalty-free,
+# non-exclusive license to exercise all rights associated with the
+# contents of this file for any purpose whatsoever.
+# No rights are reserved.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+# SOFTWARE.
+# ===================================================================
+
+"""SHA-512 cryptographic hash algorithm.
+
+SHA-512 belongs to the SHA-2_ family of cryptographic hashes.
+It produces the 512 bit digest of a message.
+
+ >>> from Crypto.Hash import SHA512
+ >>>
+ >>> h = SHA512.new()
+ >>> h.update(b'Hello')
+ >>> print h.hexdigest()
+
+*SHA* stands for Secure Hash Algorithm.
+
+.. _SHA-2: http://csrc.nist.gov/publications/fips/fips180-2/fips180-2.pdf
+"""
+
+_revision__ = "$Id$"
+
+__all__ = ['new', 'digest_size', 'SHA512Hash' ]
+
+from Crypto.Util.py3compat import *
+from Crypto.Hash.hashalgo import HashAlgo
+
+try:
+ import hashlib
+ hashFactory = hashlib.sha512
+
+except ImportError:
+ from Crypto.Hash import _SHA512
+ hashFactory = _SHA512
+
+class SHA512Hash(HashAlgo):
+ """Class that implements a SHA-512 hash
+
+ :undocumented: block_size
+ """
+
+ #: ASN.1 Object identifier (OID)::
+ #:
+ #: id-sha512 OBJECT IDENTIFIER ::= {
+ #: joint-iso-itu-t(2)
+ #: country(16) us(840) organization(1) gov(101) csor(3) nistalgorithm(4) hashalgs(2) 3
+ #: }
+ #:
+ #: This value uniquely identifies the SHA-512 algorithm.
+ oid = b('\x06\x09\x60\x86\x48\x01\x65\x03\x04\x02\x03')
+
+ digest_size = 64
+ block_size = 128
+
+ def __init__(self, data=None):
+ HashAlgo.__init__(self, hashFactory, data)
+
+ def new(self, data=None):
+ return SHA512Hash(data)
+
+def new(data=None):
+ """Return a fresh instance of the hash object.
+
+ :Parameters:
+ data : byte string
+ The very first chunk of the message to hash.
+ It is equivalent to an early call to `SHA512Hash.update()`.
+ Optional.
+
+ :Return: A `SHA512Hash` object
+ """
+ return SHA512Hash().new(data)
+
+#: The size of the resulting hash in bytes.
+digest_size = SHA512Hash.digest_size
+
+#: The internal block size of the hash algorithm in bytes.
+block_size = SHA512Hash.block_size
+
diff --git a/frozen_deps/Crypto/Hash/_MD2.cpython-38-x86_64-linux-gnu.so b/frozen_deps/Crypto/Hash/_MD2.cpython-38-x86_64-linux-gnu.so
new file mode 100755
index 0000000..6fbfc79
--- /dev/null
+++ b/frozen_deps/Crypto/Hash/_MD2.cpython-38-x86_64-linux-gnu.so
Binary files differ
diff --git a/frozen_deps/Crypto/Hash/_MD4.cpython-38-x86_64-linux-gnu.so b/frozen_deps/Crypto/Hash/_MD4.cpython-38-x86_64-linux-gnu.so
new file mode 100755
index 0000000..286f3ec
--- /dev/null
+++ b/frozen_deps/Crypto/Hash/_MD4.cpython-38-x86_64-linux-gnu.so
Binary files differ
diff --git a/frozen_deps/Crypto/Hash/_RIPEMD160.cpython-38-x86_64-linux-gnu.so b/frozen_deps/Crypto/Hash/_RIPEMD160.cpython-38-x86_64-linux-gnu.so
new file mode 100755
index 0000000..a66d804
--- /dev/null
+++ b/frozen_deps/Crypto/Hash/_RIPEMD160.cpython-38-x86_64-linux-gnu.so
Binary files differ
diff --git a/frozen_deps/Crypto/Hash/_SHA224.cpython-38-x86_64-linux-gnu.so b/frozen_deps/Crypto/Hash/_SHA224.cpython-38-x86_64-linux-gnu.so
new file mode 100755
index 0000000..eac6cae
--- /dev/null
+++ b/frozen_deps/Crypto/Hash/_SHA224.cpython-38-x86_64-linux-gnu.so
Binary files differ
diff --git a/frozen_deps/Crypto/Hash/_SHA256.cpython-38-x86_64-linux-gnu.so b/frozen_deps/Crypto/Hash/_SHA256.cpython-38-x86_64-linux-gnu.so
new file mode 100755
index 0000000..0155f47
--- /dev/null
+++ b/frozen_deps/Crypto/Hash/_SHA256.cpython-38-x86_64-linux-gnu.so
Binary files differ
diff --git a/frozen_deps/Crypto/Hash/_SHA384.cpython-38-x86_64-linux-gnu.so b/frozen_deps/Crypto/Hash/_SHA384.cpython-38-x86_64-linux-gnu.so
new file mode 100755
index 0000000..3d1049b
--- /dev/null
+++ b/frozen_deps/Crypto/Hash/_SHA384.cpython-38-x86_64-linux-gnu.so
Binary files differ
diff --git a/frozen_deps/Crypto/Hash/_SHA512.cpython-38-x86_64-linux-gnu.so b/frozen_deps/Crypto/Hash/_SHA512.cpython-38-x86_64-linux-gnu.so
new file mode 100755
index 0000000..e3c5c5c
--- /dev/null
+++ b/frozen_deps/Crypto/Hash/_SHA512.cpython-38-x86_64-linux-gnu.so
Binary files differ
diff --git a/frozen_deps/Crypto/Hash/__init__.py b/frozen_deps/Crypto/Hash/__init__.py
new file mode 100644
index 0000000..4582c66
--- /dev/null
+++ b/frozen_deps/Crypto/Hash/__init__.py
@@ -0,0 +1,56 @@
+# -*- coding: utf-8 -*-
+#
+# ===================================================================
+# The contents of this file are dedicated to the public domain. To
+# the extent that dedication to the public domain is not available,
+# everyone is granted a worldwide, perpetual, royalty-free,
+# non-exclusive license to exercise all rights associated with the
+# contents of this file for any purpose whatsoever.
+# No rights are reserved.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+# SOFTWARE.
+# ===================================================================
+
+"""Hashing algorithms
+
+Hash functions take arbitrary binary strings as input, and produce a random-like output
+of fixed size that is dependent on the input; it should be practically infeasible
+to derive the original input data given only the hash function's
+output. In other words, the hash function is *one-way*.
+
+It should also not be practically feasible to find a second piece of data
+(a *second pre-image*) whose hash is the same as the original message
+(*weak collision resistance*).
+
+Finally, it should not be feasible to find two arbitrary messages with the
+same hash (*strong collision resistance*).
+
+The output of the hash function is called the *digest* of the input message.
+In general, the security of a hash function is related to the length of the
+digest. If the digest is *n* bits long, its security level is roughly comparable
+to the the one offered by an *n/2* bit encryption algorithm.
+
+Hash functions can be used simply as a integrity check, or, in
+association with a public-key algorithm, can be used to implement
+digital signatures.
+
+The hashing modules here all support the interface described in `PEP
+247`_ , "API for Cryptographic Hash Functions".
+
+.. _`PEP 247` : http://www.python.org/dev/peps/pep-0247/
+
+:undocumented: _MD2, _MD4, _RIPEMD160, _SHA224, _SHA256, _SHA384, _SHA512
+"""
+
+__all__ = ['HMAC', 'MD2', 'MD4', 'MD5', 'RIPEMD', 'SHA',
+ 'SHA224', 'SHA256', 'SHA384', 'SHA512']
+__revision__ = "$Id$"
+
+
diff --git a/frozen_deps/Crypto/Hash/hashalgo.py b/frozen_deps/Crypto/Hash/hashalgo.py
new file mode 100644
index 0000000..b38b3a6
--- /dev/null
+++ b/frozen_deps/Crypto/Hash/hashalgo.py
@@ -0,0 +1,116 @@
+# -*- coding: utf-8 -*-
+#
+# ===================================================================
+# The contents of this file are dedicated to the public domain. To
+# the extent that dedication to the public domain is not available,
+# everyone is granted a worldwide, perpetual, royalty-free,
+# non-exclusive license to exercise all rights associated with the
+# contents of this file for any purpose whatsoever.
+# No rights are reserved.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+# SOFTWARE.
+# ===================================================================
+
+from binascii import hexlify
+
+class HashAlgo:
+ """A generic class for an abstract cryptographic hash algorithm.
+
+ :undocumented: block_size
+ """
+
+ #: The size of the resulting hash in bytes.
+ digest_size = None
+ #: The internal block size of the hash algorithm in bytes.
+ block_size = None
+
+ def __init__(self, hashFactory, data=None):
+ """Initialize the hash object.
+
+ :Parameters:
+ hashFactory : callable
+ An object that will generate the actual hash implementation.
+ *hashFactory* must have a *new()* method, or must be directly
+ callable.
+ data : byte string
+ The very first chunk of the message to hash.
+ It is equivalent to an early call to `update()`.
+ """
+ if hasattr(hashFactory, 'new'):
+ self._hash = hashFactory.new()
+ else:
+ self._hash = hashFactory()
+ if data:
+ self.update(data)
+
+ def update(self, data):
+ """Continue hashing of a message by consuming the next chunk of data.
+
+ Repeated calls are equivalent to a single call with the concatenation
+ of all the arguments. In other words:
+
+ >>> m.update(a); m.update(b)
+
+ is equivalent to:
+
+ >>> m.update(a+b)
+
+ :Parameters:
+ data : byte string
+ The next chunk of the message being hashed.
+ """
+ return self._hash.update(data)
+
+ def digest(self):
+ """Return the **binary** (non-printable) digest of the message that has been hashed so far.
+
+ This method does not change the state of the hash object.
+ You can continue updating the object after calling this function.
+
+ :Return: A byte string of `digest_size` bytes. It may contain non-ASCII
+ characters, including null bytes.
+ """
+ return self._hash.digest()
+
+ def hexdigest(self):
+ """Return the **printable** digest of the message that has been hashed so far.
+
+ This method does not change the state of the hash object.
+
+ :Return: A string of 2* `digest_size` characters. It contains only
+ hexadecimal ASCII digits.
+ """
+ return self._hash.hexdigest()
+
+ def copy(self):
+ """Return a copy ("clone") of the hash object.
+
+ The copy will have the same internal state as the original hash
+ object.
+ This can be used to efficiently compute the digests of strings that
+ share a common initial substring.
+
+ :Return: A hash object of the same type
+ """
+ return self._hash.copy()
+
+ def new(self, data=None):
+ """Return a fresh instance of the hash object.
+
+ Unlike the `copy` method, the internal state of the object is empty.
+
+ :Parameters:
+ data : byte string
+ The next chunk of the message being hashed.
+
+ :Return: A hash object of the same type
+ """
+ pass
+
diff --git a/frozen_deps/Crypto/Protocol/AllOrNothing.py b/frozen_deps/Crypto/Protocol/AllOrNothing.py
new file mode 100644
index 0000000..dd20536
--- /dev/null
+++ b/frozen_deps/Crypto/Protocol/AllOrNothing.py
@@ -0,0 +1,320 @@
+#
+# AllOrNothing.py : all-or-nothing package transformations
+#
+# Part of the Python Cryptography Toolkit
+#
+# Written by Andrew M. Kuchling and others
+#
+# ===================================================================
+# The contents of this file are dedicated to the public domain. To
+# the extent that dedication to the public domain is not available,
+# everyone is granted a worldwide, perpetual, royalty-free,
+# non-exclusive license to exercise all rights associated with the
+# contents of this file for any purpose whatsoever.
+# No rights are reserved.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+# SOFTWARE.
+# ===================================================================
+
+"""This file implements all-or-nothing package transformations.
+
+An all-or-nothing package transformation is one in which some text is
+transformed into message blocks, such that all blocks must be obtained before
+the reverse transformation can be applied. Thus, if any blocks are corrupted
+or lost, the original message cannot be reproduced.
+
+An all-or-nothing package transformation is not encryption, although a block
+cipher algorithm is used. The encryption key is randomly generated and is
+extractable from the message blocks.
+
+This class implements the All-Or-Nothing package transformation algorithm
+described in:
+
+Ronald L. Rivest. "All-Or-Nothing Encryption and The Package Transform"
+http://theory.lcs.mit.edu/~rivest/fusion.pdf
+
+"""
+
+__revision__ = "$Id$"
+
+import operator
+import sys
+from Crypto.Util.number import bytes_to_long, long_to_bytes
+from Crypto.Util.py3compat import *
+from functools import reduce
+
+def isInt(x):
+ test = 0
+ try:
+ test += x
+ except TypeError:
+ return 0
+ return 1
+
+class AllOrNothing:
+ """Class implementing the All-or-Nothing package transform.
+
+ Methods for subclassing:
+
+ _inventkey(key_size):
+ Returns a randomly generated key. Subclasses can use this to
+ implement better random key generating algorithms. The default
+ algorithm is probably not very cryptographically secure.
+
+ """
+
+ def __init__(self, ciphermodule, mode=None, IV=None):
+ """AllOrNothing(ciphermodule, mode=None, IV=None)
+
+ ciphermodule is a module implementing the cipher algorithm to
+ use. It must provide the PEP272 interface.
+
+ Note that the encryption key is randomly generated
+ automatically when needed. Optional arguments mode and IV are
+ passed directly through to the ciphermodule.new() method; they
+ are the feedback mode and initialization vector to use. All
+ three arguments must be the same for the object used to create
+ the digest, and to undigest'ify the message blocks.
+ """
+
+ self.__ciphermodule = ciphermodule
+ self.__mode = mode
+ self.__IV = IV
+ self.__key_size = ciphermodule.key_size
+ if not isInt(self.__key_size) or self.__key_size==0:
+ self.__key_size = 16
+
+ __K0digit = bchr(0x69)
+
+ def digest(self, text):
+ """digest(text:string) : [string]
+
+ Perform the All-or-Nothing package transform on the given
+ string. Output is a list of message blocks describing the
+ transformed text, where each block is a string of bit length equal
+ to the ciphermodule's block_size.
+ """
+
+ # generate a random session key and K0, the key used to encrypt the
+ # hash blocks. Rivest calls this a fixed, publically-known encryption
+ # key, but says nothing about the security implications of this key or
+ # how to choose it.
+ key = self._inventkey(self.__key_size)
+ K0 = self.__K0digit * self.__key_size
+
+ # we need two cipher objects here, one that is used to encrypt the
+ # message blocks and one that is used to encrypt the hashes. The
+ # former uses the randomly generated key, while the latter uses the
+ # well-known key.
+ mcipher = self.__newcipher(key)
+ hcipher = self.__newcipher(K0)
+
+ # Pad the text so that its length is a multiple of the cipher's
+ # block_size. Pad with trailing spaces, which will be eliminated in
+ # the undigest() step.
+ block_size = self.__ciphermodule.block_size
+ padbytes = block_size - (len(text) % block_size)
+ text = text + b(' ') * padbytes
+
+ # Run through the algorithm:
+ # s: number of message blocks (size of text / block_size)
+ # input sequence: m1, m2, ... ms
+ # random key K' (`key' in the code)
+ # Compute output sequence: m'1, m'2, ... m's' for s' = s + 1
+ # Let m'i = mi ^ E(K', i) for i = 1, 2, 3, ..., s
+ # Let m's' = K' ^ h1 ^ h2 ^ ... hs
+ # where hi = E(K0, m'i ^ i) for i = 1, 2, ... s
+ #
+ # The one complication I add is that the last message block is hard
+ # coded to the number of padbytes added, so that these can be stripped
+ # during the undigest() step
+ s = divmod(len(text), block_size)[0]
+ blocks = []
+ hashes = []
+ for i in range(1, s+1):
+ start = (i-1) * block_size
+ end = start + block_size
+ mi = text[start:end]
+ assert len(mi) == block_size
+ cipherblock = mcipher.encrypt(long_to_bytes(i, block_size))
+ mticki = bytes_to_long(mi) ^ bytes_to_long(cipherblock)
+ blocks.append(mticki)
+ # calculate the hash block for this block
+ hi = hcipher.encrypt(long_to_bytes(mticki ^ i, block_size))
+ hashes.append(bytes_to_long(hi))
+
+ # Add the padbytes length as a message block
+ i = i + 1
+ cipherblock = mcipher.encrypt(long_to_bytes(i, block_size))
+ mticki = padbytes ^ bytes_to_long(cipherblock)
+ blocks.append(mticki)
+
+ # calculate this block's hash
+ hi = hcipher.encrypt(long_to_bytes(mticki ^ i, block_size))
+ hashes.append(bytes_to_long(hi))
+
+ # Now calculate the last message block of the sequence 1..s'. This
+ # will contain the random session key XOR'd with all the hash blocks,
+ # so that for undigest(), once all the hash blocks are calculated, the
+ # session key can be trivially extracted. Calculating all the hash
+ # blocks requires that all the message blocks be received, thus the
+ # All-or-Nothing algorithm succeeds.
+ mtick_stick = bytes_to_long(key) ^ reduce(operator.xor, hashes)
+ blocks.append(mtick_stick)
+
+ # we convert the blocks to strings since in Python, byte sequences are
+ # always represented as strings. This is more consistent with the
+ # model that encryption and hash algorithms always operate on strings.
+ return [long_to_bytes(i,self.__ciphermodule.block_size) for i in blocks]
+
+
+ def undigest(self, blocks):
+ """undigest(blocks : [string]) : string
+
+ Perform the reverse package transformation on a list of message
+ blocks. Note that the ciphermodule used for both transformations
+ must be the same. blocks is a list of strings of bit length
+ equal to the ciphermodule's block_size.
+ """
+
+ # better have at least 2 blocks, for the padbytes package and the hash
+ # block accumulator
+ if len(blocks) < 2:
+ raise ValueError("List must be at least length 2.")
+
+ # blocks is a list of strings. We need to deal with them as long
+ # integers
+ blocks = list(map(bytes_to_long, blocks))
+
+ # Calculate the well-known key, to which the hash blocks are
+ # encrypted, and create the hash cipher.
+ K0 = self.__K0digit * self.__key_size
+ hcipher = self.__newcipher(K0)
+ block_size = self.__ciphermodule.block_size
+
+ # Since we have all the blocks (or this method would have been called
+ # prematurely), we can calculate all the hash blocks.
+ hashes = []
+ for i in range(1, len(blocks)):
+ mticki = blocks[i-1] ^ i
+ hi = hcipher.encrypt(long_to_bytes(mticki, block_size))
+ hashes.append(bytes_to_long(hi))
+
+ # now we can calculate K' (key). remember the last block contains
+ # m's' which we don't include here
+ key = blocks[-1] ^ reduce(operator.xor, hashes)
+
+ # and now we can create the cipher object
+ mcipher = self.__newcipher(long_to_bytes(key, self.__key_size))
+
+ # And we can now decode the original message blocks
+ parts = []
+ for i in range(1, len(blocks)):
+ cipherblock = mcipher.encrypt(long_to_bytes(i, block_size))
+ mi = blocks[i-1] ^ bytes_to_long(cipherblock)
+ parts.append(mi)
+
+ # The last message block contains the number of pad bytes appended to
+ # the original text string, such that its length was an even multiple
+ # of the cipher's block_size. This number should be small enough that
+ # the conversion from long integer to integer should never overflow
+ padbytes = int(parts[-1])
+ text = b('').join(map(long_to_bytes, parts[:-1]))
+ return text[:-padbytes]
+
+ def _inventkey(self, key_size):
+ # Return key_size random bytes
+ from Crypto import Random
+ return Random.new().read(key_size)
+
+ def __newcipher(self, key):
+ if self.__mode is None and self.__IV is None:
+ return self.__ciphermodule.new(key)
+ elif self.__IV is None:
+ return self.__ciphermodule.new(key, self.__mode)
+ else:
+ return self.__ciphermodule.new(key, self.__mode, self.__IV)
+
+
+
+if __name__ == '__main__':
+ import sys
+ import getopt
+ import base64
+
+ usagemsg = '''\
+Test module usage: %(program)s [-c cipher] [-l] [-h]
+
+Where:
+ --cipher module
+ -c module
+ Cipher module to use. Default: %(ciphermodule)s
+
+ --aslong
+ -l
+ Print the encoded message blocks as long integers instead of base64
+ encoded strings
+
+ --help
+ -h
+ Print this help message
+'''
+
+ ciphermodule = 'AES'
+ aslong = 0
+
+ def usage(code, msg=None):
+ if msg:
+ print(msg)
+ print(usagemsg % {'program': sys.argv[0],
+ 'ciphermodule': ciphermodule})
+ sys.exit(code)
+
+ try:
+ opts, args = getopt.getopt(sys.argv[1:],
+ 'c:l', ['cipher=', 'aslong'])
+ except getopt.error as msg:
+ usage(1, msg)
+
+ if args:
+ usage(1, 'Too many arguments')
+
+ for opt, arg in opts:
+ if opt in ('-h', '--help'):
+ usage(0)
+ elif opt in ('-c', '--cipher'):
+ ciphermodule = arg
+ elif opt in ('-l', '--aslong'):
+ aslong = 1
+
+ # ugly hack to force __import__ to give us the end-path module
+ module = __import__('Crypto.Cipher.'+ciphermodule, None, None, ['new'])
+
+ x = AllOrNothing(module)
+ print('Original text:\n==========')
+ print(__doc__)
+ print('==========')
+ msgblocks = x.digest(b(__doc__))
+ print('message blocks:')
+ for i, blk in zip(list(range(len(msgblocks))), msgblocks):
+ # base64 adds a trailing newline
+ print(' %3d' % i, end=' ')
+ if aslong:
+ print(bytes_to_long(blk))
+ else:
+ print(base64.encodestring(blk)[:-1])
+ #
+ # get a new undigest-only object so there's no leakage
+ y = AllOrNothing(module)
+ text = y.undigest(msgblocks)
+ if text == b(__doc__):
+ print('They match!')
+ else:
+ print('They differ!')
diff --git a/frozen_deps/Crypto/Protocol/Chaffing.py b/frozen_deps/Crypto/Protocol/Chaffing.py
new file mode 100644
index 0000000..bbfcbda
--- /dev/null
+++ b/frozen_deps/Crypto/Protocol/Chaffing.py
@@ -0,0 +1,245 @@
+#
+# Chaffing.py : chaffing & winnowing support
+#
+# Part of the Python Cryptography Toolkit
+#
+# Written by Andrew M. Kuchling, Barry A. Warsaw, and others
+#
+# ===================================================================
+# The contents of this file are dedicated to the public domain. To
+# the extent that dedication to the public domain is not available,
+# everyone is granted a worldwide, perpetual, royalty-free,
+# non-exclusive license to exercise all rights associated with the
+# contents of this file for any purpose whatsoever.
+# No rights are reserved.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+# SOFTWARE.
+# ===================================================================
+#
+"""This file implements the chaffing algorithm.
+
+Winnowing and chaffing is a technique for enhancing privacy without requiring
+strong encryption. In short, the technique takes a set of authenticated
+message blocks (the wheat) and adds a number of chaff blocks which have
+randomly chosen data and MAC fields. This means that to an adversary, the
+chaff blocks look as valid as the wheat blocks, and so the authentication
+would have to be performed on every block. By tailoring the number of chaff
+blocks added to the message, the sender can make breaking the message
+computationally infeasible. There are many other interesting properties of
+the winnow/chaff technique.
+
+For example, say Alice is sending a message to Bob. She packetizes the
+message and performs an all-or-nothing transformation on the packets. Then
+she authenticates each packet with a message authentication code (MAC). The
+MAC is a hash of the data packet, and there is a secret key which she must
+share with Bob (key distribution is an exercise left to the reader). She then
+adds a serial number to each packet, and sends the packets to Bob.
+
+Bob receives the packets, and using the shared secret authentication key,
+authenticates the MACs for each packet. Those packets that have bad MACs are
+simply discarded. The remainder are sorted by serial number, and passed
+through the reverse all-or-nothing transform. The transform means that an
+eavesdropper (say Eve) must acquire all the packets before any of the data can
+be read. If even one packet is missing, the data is useless.
+
+There's one twist: by adding chaff packets, Alice and Bob can make Eve's job
+much harder, since Eve now has to break the shared secret key, or try every
+combination of wheat and chaff packet to read any of the message. The cool
+thing is that Bob doesn't need to add any additional code; the chaff packets
+are already filtered out because their MACs don't match (in all likelihood --
+since the data and MACs for the chaff packets are randomly chosen it is
+possible, but very unlikely that a chaff MAC will match the chaff data). And
+Alice need not even be the party adding the chaff! She could be completely
+unaware that a third party, say Charles, is adding chaff packets to her
+messages as they are transmitted.
+
+For more information on winnowing and chaffing see this paper:
+
+Ronald L. Rivest, "Chaffing and Winnowing: Confidentiality without Encryption"
+http://theory.lcs.mit.edu/~rivest/chaffing.txt
+
+"""
+
+__revision__ = "$Id$"
+
+from Crypto.Util.number import bytes_to_long
+
+class Chaff:
+ """Class implementing the chaff adding algorithm.
+
+ Methods for subclasses:
+
+ _randnum(size):
+ Returns a randomly generated number with a byte-length equal
+ to size. Subclasses can use this to implement better random
+ data and MAC generating algorithms. The default algorithm is
+ probably not very cryptographically secure. It is most
+ important that the chaff data does not contain any patterns
+ that can be used to discern it from wheat data without running
+ the MAC.
+
+ """
+
+ def __init__(self, factor=1.0, blocksper=1):
+ """Chaff(factor:float, blocksper:int)
+
+ factor is the number of message blocks to add chaff to,
+ expressed as a percentage between 0.0 and 1.0. blocksper is
+ the number of chaff blocks to include for each block being
+ chaffed. Thus the defaults add one chaff block to every
+ message block. By changing the defaults, you can adjust how
+ computationally difficult it could be for an adversary to
+ brute-force crack the message. The difficulty is expressed
+ as:
+
+ pow(blocksper, int(factor * number-of-blocks))
+
+ For ease of implementation, when factor < 1.0, only the first
+ int(factor*number-of-blocks) message blocks are chaffed.
+ """
+
+ if not (0.0<=factor<=1.0):
+ raise ValueError("'factor' must be between 0.0 and 1.0")
+ if blocksper < 0:
+ raise ValueError("'blocksper' must be zero or more")
+
+ self.__factor = factor
+ self.__blocksper = blocksper
+
+
+ def chaff(self, blocks):
+ """chaff( [(serial-number:int, data:string, MAC:string)] )
+ : [(int, string, string)]
+
+ Add chaff to message blocks. blocks is a list of 3-tuples of the
+ form (serial-number, data, MAC).
+
+ Chaff is created by choosing a random number of the same
+ byte-length as data, and another random number of the same
+ byte-length as MAC. The message block's serial number is
+ placed on the chaff block and all the packet's chaff blocks
+ are randomly interspersed with the single wheat block. This
+ method then returns a list of 3-tuples of the same form.
+ Chaffed blocks will contain multiple instances of 3-tuples
+ with the same serial number, but the only way to figure out
+ which blocks are wheat and which are chaff is to perform the
+ MAC hash and compare values.
+ """
+
+ chaffedblocks = []
+
+ # count is the number of blocks to add chaff to. blocksper is the
+ # number of chaff blocks to add per message block that is being
+ # chaffed.
+ count = len(blocks) * self.__factor
+ blocksper = list(range(self.__blocksper))
+ for i, wheat in zip(list(range(len(blocks))), blocks):
+ # it shouldn't matter which of the n blocks we add chaff to, so for
+ # ease of implementation, we'll just add them to the first count
+ # blocks
+ if i < count:
+ serial, data, mac = wheat
+ datasize = len(data)
+ macsize = len(mac)
+ addwheat = 1
+ # add chaff to this block
+ for j in blocksper:
+ import sys
+ chaffdata = self._randnum(datasize)
+ chaffmac = self._randnum(macsize)
+ chaff = (serial, chaffdata, chaffmac)
+ # mix up the order, if the 5th bit is on then put the
+ # wheat on the list
+ if addwheat and bytes_to_long(self._randnum(16)) & 0x40:
+ chaffedblocks.append(wheat)
+ addwheat = 0
+ chaffedblocks.append(chaff)
+ if addwheat:
+ chaffedblocks.append(wheat)
+ else:
+ # just add the wheat
+ chaffedblocks.append(wheat)
+ return chaffedblocks
+
+ def _randnum(self, size):
+ from Crypto import Random
+ return Random.new().read(size)
+
+
+if __name__ == '__main__':
+ text = """\
+We hold these truths to be self-evident, that all men are created equal, that
+they are endowed by their Creator with certain unalienable Rights, that among
+these are Life, Liberty, and the pursuit of Happiness. That to secure these
+rights, Governments are instituted among Men, deriving their just powers from
+the consent of the governed. That whenever any Form of Government becomes
+destructive of these ends, it is the Right of the People to alter or to
+abolish it, and to institute new Government, laying its foundation on such
+principles and organizing its powers in such form, as to them shall seem most
+likely to effect their Safety and Happiness.
+"""
+ print('Original text:\n==========')
+ print(text)
+ print('==========')
+
+ # first transform the text into packets
+ blocks = [] ; size = 40
+ for i in range(0, len(text), size):
+ blocks.append( text[i:i+size] )
+
+ # now get MACs for all the text blocks. The key is obvious...
+ print('Calculating MACs...')
+ from Crypto.Hash import HMAC, SHA
+ key = 'Jefferson'
+ macs = [HMAC.new(key, block, digestmod=SHA).digest()
+ for block in blocks]
+
+ assert len(blocks) == len(macs)
+
+ # put these into a form acceptable as input to the chaffing procedure
+ source = []
+ m = list(zip(list(range(len(blocks))), blocks, macs))
+ print(m)
+ for i, data, mac in m:
+ source.append((i, data, mac))
+
+ # now chaff these
+ print('Adding chaff...')
+ c = Chaff(factor=0.5, blocksper=2)
+ chaffed = c.chaff(source)
+
+ from base64 import encodestring
+
+ # print the chaffed message blocks. meanwhile, separate the wheat from
+ # the chaff
+
+ wheat = []
+ print('chaffed message blocks:')
+ for i, data, mac in chaffed:
+ # do the authentication
+ h = HMAC.new(key, data, digestmod=SHA)
+ pmac = h.digest()
+ if pmac == mac:
+ tag = '-->'
+ wheat.append(data)
+ else:
+ tag = ' '
+ # base64 adds a trailing newline
+ print(tag, '%3d' % i, \
+ repr(data), encodestring(mac)[:-1])
+
+ # now decode the message packets and check it against the original text
+ print('Undigesting wheat...')
+ # PY3K: This is meant to be text, do not change to bytes (data)
+ newtext = "".join(wheat)
+ if newtext == text:
+ print('They match!')
+ else:
+ print('They differ!')
diff --git a/frozen_deps/Crypto/Protocol/KDF.py b/frozen_deps/Crypto/Protocol/KDF.py
new file mode 100644
index 0000000..af4e2a6
--- /dev/null
+++ b/frozen_deps/Crypto/Protocol/KDF.py
@@ -0,0 +1,123 @@
+#
+# KDF.py : a collection of Key Derivation Functions
+#
+# Part of the Python Cryptography Toolkit
+#
+# ===================================================================
+# The contents of this file are dedicated to the public domain. To
+# the extent that dedication to the public domain is not available,
+# everyone is granted a worldwide, perpetual, royalty-free,
+# non-exclusive license to exercise all rights associated with the
+# contents of this file for any purpose whatsoever.
+# No rights are reserved.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+# SOFTWARE.
+# ===================================================================
+
+"""This file contains a collection of standard key derivation functions.
+
+A key derivation function derives one or more secondary secret keys from
+one primary secret (a master key or a pass phrase).
+
+This is typically done to insulate the secondary keys from each other,
+to avoid that leakage of a secondary key compromises the security of the
+master key, or to thwart attacks on pass phrases (e.g. via rainbow tables).
+
+:undocumented: __revision__
+"""
+
+__revision__ = "$Id$"
+
+import math
+import struct
+
+from Crypto.Util.py3compat import *
+from Crypto.Hash import SHA as SHA1, HMAC
+from Crypto.Util.strxor import strxor
+
+def PBKDF1(password, salt, dkLen, count=1000, hashAlgo=None):
+ """Derive one key from a password (or passphrase).
+
+ This function performs key derivation according an old version of
+ the PKCS#5 standard (v1.5).
+
+ This algorithm is called ``PBKDF1``. Even though it is still described
+ in the latest version of the PKCS#5 standard (version 2, or RFC2898),
+ newer applications should use the more secure and versatile `PBKDF2` instead.
+
+ :Parameters:
+ password : string
+ The secret password or pass phrase to generate the key from.
+ salt : byte string
+ An 8 byte string to use for better protection from dictionary attacks.
+ This value does not need to be kept secret, but it should be randomly
+ chosen for each derivation.
+ dkLen : integer
+ The length of the desired key. Default is 16 bytes, suitable for instance for `Crypto.Cipher.AES`.
+ count : integer
+ The number of iterations to carry out. It's recommended to use at least 1000.
+ hashAlgo : module
+ The hash algorithm to use, as a module or an object from the `Crypto.Hash` package.
+ The digest length must be no shorter than ``dkLen``.
+ The default algorithm is `SHA1`.
+
+ :Return: A byte string of length `dkLen` that can be used as key.
+ """
+ if not hashAlgo:
+ hashAlgo = SHA1
+ password = tobytes(password)
+ pHash = hashAlgo.new(password+salt)
+ digest = pHash.digest_size
+ if dkLen>digest:
+ raise ValueError("Selected hash algorithm has a too short digest (%d bytes)." % digest)
+ if len(salt)!=8:
+ raise ValueError("Salt is not 8 bytes long.")
+ for i in range(count-1):
+ pHash = pHash.new(pHash.digest())
+ return pHash.digest()[:dkLen]
+
+def PBKDF2(password, salt, dkLen=16, count=1000, prf=None):
+ """Derive one or more keys from a password (or passphrase).
+
+ This performs key derivation according to the PKCS#5 standard (v2.0),
+ by means of the ``PBKDF2`` algorithm.
+
+ :Parameters:
+ password : string
+ The secret password or pass phrase to generate the key from.
+ salt : string
+ A string to use for better protection from dictionary attacks.
+ This value does not need to be kept secret, but it should be randomly
+ chosen for each derivation. It is recommended to be at least 8 bytes long.
+ dkLen : integer
+ The cumulative length of the desired keys. Default is 16 bytes, suitable for instance for `Crypto.Cipher.AES`.
+ count : integer
+ The number of iterations to carry out. It's recommended to use at least 1000.
+ prf : callable
+ A pseudorandom function. It must be a function that returns a pseudorandom string
+ from two parameters: a secret and a salt. If not specified, HMAC-SHA1 is used.
+
+ :Return: A byte string of length `dkLen` that can be used as key material.
+ If you wanted multiple keys, just break up this string into segments of the desired length.
+"""
+ password = tobytes(password)
+ if prf is None:
+ prf = lambda p,s: HMAC.new(p,s,SHA1).digest()
+ key = b('')
+ i = 1
+ while len(key)<dkLen:
+ U = previousU = prf(password,salt+struct.pack(">I", i))
+ for j in range(count-1):
+ previousU = t = prf(password,previousU)
+ U = strxor(U,t)
+ key += U
+ i = i + 1
+ return key[:dkLen]
+
diff --git a/frozen_deps/Crypto/Protocol/__init__.py b/frozen_deps/Crypto/Protocol/__init__.py
new file mode 100644
index 0000000..cacc685
--- /dev/null
+++ b/frozen_deps/Crypto/Protocol/__init__.py
@@ -0,0 +1,41 @@
+# -*- coding: utf-8 -*-
+#
+# ===================================================================
+# The contents of this file are dedicated to the public domain. To
+# the extent that dedication to the public domain is not available,
+# everyone is granted a worldwide, perpetual, royalty-free,
+# non-exclusive license to exercise all rights associated with the
+# contents of this file for any purpose whatsoever.
+# No rights are reserved.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+# SOFTWARE.
+# ===================================================================
+
+"""Cryptographic protocols
+
+Implements various cryptographic protocols. (Don't expect to find
+network protocols here.)
+
+Crypto.Protocol.AllOrNothing
+ Transforms a message into a set of message blocks, such that the blocks
+ can be recombined to get the message back.
+
+Crypto.Protocol.Chaffing
+ Takes a set of authenticated message blocks (the wheat) and adds a number
+ of randomly generated blocks (the chaff).
+
+Crypto.Protocol.KDF
+ A collection of standard key derivation functions.
+
+:undocumented: __revision__
+"""
+
+__all__ = ['AllOrNothing', 'Chaffing', 'KDF']
+__revision__ = "$Id$"
diff --git a/frozen_deps/Crypto/PublicKey/DSA.py b/frozen_deps/Crypto/PublicKey/DSA.py
new file mode 100644
index 0000000..648f4b2
--- /dev/null
+++ b/frozen_deps/Crypto/PublicKey/DSA.py
@@ -0,0 +1,379 @@
+# -*- coding: utf-8 -*-
+#
+# PublicKey/DSA.py : DSA signature primitive
+#
+# Written in 2008 by Dwayne C. Litzenberger <[email protected]>
+#
+# ===================================================================
+# The contents of this file are dedicated to the public domain. To
+# the extent that dedication to the public domain is not available,
+# everyone is granted a worldwide, perpetual, royalty-free,
+# non-exclusive license to exercise all rights associated with the
+# contents of this file for any purpose whatsoever.
+# No rights are reserved.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+# SOFTWARE.
+# ===================================================================
+
+"""DSA public-key signature algorithm.
+
+DSA_ is a widespread public-key signature algorithm. Its security is
+based on the discrete logarithm problem (DLP_). Given a cyclic
+group, a generator *g*, and an element *h*, it is hard
+to find an integer *x* such that *g^x = h*. The problem is believed
+to be difficult, and it has been proved such (and therefore secure) for
+more than 30 years.
+
+The group is actually a sub-group over the integers modulo *p*, with *p* prime.
+The sub-group order is *q*, which is prime too; it always holds that *(p-1)* is a multiple of *q*.
+The cryptographic strength is linked to the magnitude of *p* and *q*.
+The signer holds a value *x* (*0<x<q-1*) as private key, and its public
+key (*y* where *y=g^x mod p*) is distributed.
+
+In 2012, a sufficient size is deemed to be 2048 bits for *p* and 256 bits for *q*.
+For more information, see the most recent ECRYPT_ report.
+
+DSA is reasonably secure for new designs.
+
+The algorithm can only be used for authentication (digital signature).
+DSA cannot be used for confidentiality (encryption).
+
+The values *(p,q,g)* are called *domain parameters*;
+they are not sensitive but must be shared by both parties (the signer and the verifier).
+Different signers can share the same domain parameters with no security
+concerns.
+
+The DSA signature is twice as big as the size of *q* (64 bytes if *q* is 256 bit
+long).
+
+This module provides facilities for generating new DSA keys and for constructing
+them from known components. DSA keys allows you to perform basic signing and
+verification.
+
+ >>> from Crypto.Random import random
+ >>> from Crypto.PublicKey import DSA
+ >>> from Crypto.Hash import SHA
+ >>>
+ >>> message = "Hello"
+ >>> key = DSA.generate(1024)
+ >>> h = SHA.new(message).digest()
+ >>> k = random.StrongRandom().randint(1,key.q-1)
+ >>> sig = key.sign(h,k)
+ >>> ...
+ >>> if key.verify(h,sig):
+ >>> print "OK"
+ >>> else:
+ >>> print "Incorrect signature"
+
+.. _DSA: http://en.wikipedia.org/wiki/Digital_Signature_Algorithm
+.. _DLP: http://www.cosic.esat.kuleuven.be/publications/talk-78.pdf
+.. _ECRYPT: http://www.ecrypt.eu.org/documents/D.SPA.17.pdf
+"""
+
+__revision__ = "$Id$"
+
+__all__ = ['generate', 'construct', 'error', 'DSAImplementation', '_DSAobj']
+
+import sys
+if sys.version_info[0] == 2 and sys.version_info[1] == 1:
+ from Crypto.Util.py21compat import *
+
+from Crypto.PublicKey import _DSA, _slowmath, pubkey
+from Crypto import Random
+
+try:
+ from Crypto.PublicKey import _fastmath
+except ImportError:
+ _fastmath = None
+
+class _DSAobj(pubkey.pubkey):
+ """Class defining an actual DSA key.
+
+ :undocumented: __getstate__, __setstate__, __repr__, __getattr__
+ """
+ #: Dictionary of DSA parameters.
+ #:
+ #: A public key will only have the following entries:
+ #:
+ #: - **y**, the public key.
+ #: - **g**, the generator.
+ #: - **p**, the modulus.
+ #: - **q**, the order of the sub-group.
+ #:
+ #: A private key will also have:
+ #:
+ #: - **x**, the private key.
+ keydata = ['y', 'g', 'p', 'q', 'x']
+
+ def __init__(self, implementation, key):
+ self.implementation = implementation
+ self.key = key
+
+ def __getattr__(self, attrname):
+ if attrname in self.keydata:
+ # For backward compatibility, allow the user to get (not set) the
+ # DSA key parameters directly from this object.
+ return getattr(self.key, attrname)
+ else:
+ raise AttributeError("%s object has no %r attribute" % (self.__class__.__name__, attrname,))
+
+ def sign(self, M, K):
+ """Sign a piece of data with DSA.
+
+ :Parameter M: The piece of data to sign with DSA. It may
+ not be longer in bit size than the sub-group order (*q*).
+ :Type M: byte string or long
+
+ :Parameter K: A secret number, chosen randomly in the closed
+ range *[1,q-1]*.
+ :Type K: long (recommended) or byte string (not recommended)
+
+ :attention: selection of *K* is crucial for security. Generating a
+ random number larger than *q* and taking the modulus by *q* is
+ **not** secure, since smaller values will occur more frequently.
+ Generating a random number systematically smaller than *q-1*
+ (e.g. *floor((q-1)/8)* random bytes) is also **not** secure. In general,
+ it shall not be possible for an attacker to know the value of `any
+ bit of K`__.
+
+ :attention: The number *K* shall not be reused for any other
+ operation and shall be discarded immediately.
+
+ :attention: M must be a digest cryptographic hash, otherwise
+ an attacker may mount an existential forgery attack.
+
+ :Return: A tuple with 2 longs.
+
+ .. __: http://www.di.ens.fr/~pnguyen/pub_NgSh00.htm
+ """
+ return pubkey.pubkey.sign(self, M, K)
+
+ def verify(self, M, signature):
+ """Verify the validity of a DSA signature.
+
+ :Parameter M: The expected message.
+ :Type M: byte string or long
+
+ :Parameter signature: The DSA signature to verify.
+ :Type signature: A tuple with 2 longs as return by `sign`
+
+ :Return: True if the signature is correct, False otherwise.
+ """
+ return pubkey.pubkey.verify(self, M, signature)
+
+ def _encrypt(self, c, K):
+ raise TypeError("DSA cannot encrypt")
+
+ def _decrypt(self, c):
+ raise TypeError("DSA cannot decrypt")
+
+ def _blind(self, m, r):
+ raise TypeError("DSA cannot blind")
+
+ def _unblind(self, m, r):
+ raise TypeError("DSA cannot unblind")
+
+ def _sign(self, m, k):
+ return self.key._sign(m, k)
+
+ def _verify(self, m, sig):
+ (r, s) = sig
+ return self.key._verify(m, r, s)
+
+ def has_private(self):
+ return self.key.has_private()
+
+ def size(self):
+ return self.key.size()
+
+ def can_blind(self):
+ return False
+
+ def can_encrypt(self):
+ return False
+
+ def can_sign(self):
+ return True
+
+ def publickey(self):
+ return self.implementation.construct((self.key.y, self.key.g, self.key.p, self.key.q))
+
+ def __getstate__(self):
+ d = {}
+ for k in self.keydata:
+ try:
+ d[k] = getattr(self.key, k)
+ except AttributeError:
+ pass
+ return d
+
+ def __setstate__(self, d):
+ if not hasattr(self, 'implementation'):
+ self.implementation = DSAImplementation()
+ t = []
+ for k in self.keydata:
+ if k not in d:
+ break
+ t.append(d[k])
+ self.key = self.implementation._math.dsa_construct(*tuple(t))
+
+ def __repr__(self):
+ attrs = []
+ for k in self.keydata:
+ if k == 'p':
+ attrs.append("p(%d)" % (self.size()+1,))
+ elif hasattr(self.key, k):
+ attrs.append(k)
+ if self.has_private():
+ attrs.append("private")
+ # PY3K: This is meant to be text, do not change to bytes (data)
+ return "<%s @0x%x %s>" % (self.__class__.__name__, id(self), ",".join(attrs))
+
+class DSAImplementation(object):
+ """
+ A DSA key factory.
+
+ This class is only internally used to implement the methods of the
+ `Crypto.PublicKey.DSA` module.
+ """
+
+ def __init__(self, **kwargs):
+ """Create a new DSA key factory.
+
+ :Keywords:
+ use_fast_math : bool
+ Specify which mathematic library to use:
+
+ - *None* (default). Use fastest math available.
+ - *True* . Use fast math.
+ - *False* . Use slow math.
+ default_randfunc : callable
+ Specify how to collect random data:
+
+ - *None* (default). Use Random.new().read().
+ - not *None* . Use the specified function directly.
+ :Raise RuntimeError:
+ When **use_fast_math** =True but fast math is not available.
+ """
+ use_fast_math = kwargs.get('use_fast_math', None)
+ if use_fast_math is None: # Automatic
+ if _fastmath is not None:
+ self._math = _fastmath
+ else:
+ self._math = _slowmath
+
+ elif use_fast_math: # Explicitly select fast math
+ if _fastmath is not None:
+ self._math = _fastmath
+ else:
+ raise RuntimeError("fast math module not available")
+
+ else: # Explicitly select slow math
+ self._math = _slowmath
+
+ self.error = self._math.error
+
+ # 'default_randfunc' parameter:
+ # None (default) - use Random.new().read
+ # not None - use the specified function
+ self._default_randfunc = kwargs.get('default_randfunc', None)
+ self._current_randfunc = None
+
+ def _get_randfunc(self, randfunc):
+ if randfunc is not None:
+ return randfunc
+ elif self._current_randfunc is None:
+ self._current_randfunc = Random.new().read
+ return self._current_randfunc
+
+ def generate(self, bits, randfunc=None, progress_func=None):
+ """Randomly generate a fresh, new DSA key.
+
+ :Parameters:
+ bits : int
+ Key length, or size (in bits) of the DSA modulus
+ *p*.
+ It must be a multiple of 64, in the closed
+ interval [512,1024].
+ randfunc : callable
+ Random number generation function; it should accept
+ a single integer N and return a string of random data
+ N bytes long.
+ If not specified, a new one will be instantiated
+ from ``Crypto.Random``.
+ progress_func : callable
+ Optional function that will be called with a short string
+ containing the key parameter currently being generated;
+ it's useful for interactive applications where a user is
+ waiting for a key to be generated.
+
+ :attention: You should always use a cryptographically secure random number generator,
+ such as the one defined in the ``Crypto.Random`` module; **don't** just use the
+ current time and the ``random`` module.
+
+ :Return: A DSA key object (`_DSAobj`).
+
+ :Raise ValueError:
+ When **bits** is too little, too big, or not a multiple of 64.
+ """
+
+ # Check against FIPS 186-2, which says that the size of the prime p
+ # must be a multiple of 64 bits between 512 and 1024
+ for i in (0, 1, 2, 3, 4, 5, 6, 7, 8):
+ if bits == 512 + 64*i:
+ return self._generate(bits, randfunc, progress_func)
+
+ # The March 2006 draft of FIPS 186-3 also allows 2048 and 3072-bit
+ # primes, but only with longer q values. Since the current DSA
+ # implementation only supports a 160-bit q, we don't support larger
+ # values.
+ raise ValueError("Number of bits in p must be a multiple of 64 between 512 and 1024, not %d bits" % (bits,))
+
+ def _generate(self, bits, randfunc=None, progress_func=None):
+ rf = self._get_randfunc(randfunc)
+ obj = _DSA.generate_py(bits, rf, progress_func) # TODO: Don't use legacy _DSA module
+ key = self._math.dsa_construct(obj.y, obj.g, obj.p, obj.q, obj.x)
+ return _DSAobj(self, key)
+
+ def construct(self, tup):
+ """Construct a DSA key from a tuple of valid DSA components.
+
+ The modulus *p* must be a prime.
+
+ The following equations must apply:
+
+ - p-1 = 0 mod q
+ - g^x = y mod p
+ - 0 < x < q
+ - 1 < g < p
+
+ :Parameters:
+ tup : tuple
+ A tuple of long integers, with 4 or 5 items
+ in the following order:
+
+ 1. Public key (*y*).
+ 2. Sub-group generator (*g*).
+ 3. Modulus, finite field order (*p*).
+ 4. Sub-group order (*q*).
+ 5. Private key (*x*). Optional.
+
+ :Return: A DSA key object (`_DSAobj`).
+ """
+ key = self._math.dsa_construct(*tup)
+ return _DSAobj(self, key)
+
+_impl = DSAImplementation()
+generate = _impl.generate
+construct = _impl.construct
+error = _impl.error
+
+# vim:set ts=4 sw=4 sts=4 expandtab:
+
diff --git a/frozen_deps/Crypto/PublicKey/ElGamal.py b/frozen_deps/Crypto/PublicKey/ElGamal.py
new file mode 100644
index 0000000..99af71c
--- /dev/null
+++ b/frozen_deps/Crypto/PublicKey/ElGamal.py
@@ -0,0 +1,373 @@
+#
+# ElGamal.py : ElGamal encryption/decryption and signatures
+#
+# Part of the Python Cryptography Toolkit
+#
+# Originally written by: A.M. Kuchling
+#
+# ===================================================================
+# The contents of this file are dedicated to the public domain. To
+# the extent that dedication to the public domain is not available,
+# everyone is granted a worldwide, perpetual, royalty-free,
+# non-exclusive license to exercise all rights associated with the
+# contents of this file for any purpose whatsoever.
+# No rights are reserved.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+# SOFTWARE.
+# ===================================================================
+
+"""ElGamal public-key algorithm (randomized encryption and signature).
+
+Signature algorithm
+-------------------
+The security of the ElGamal signature scheme is based (like DSA) on the discrete
+logarithm problem (DLP_). Given a cyclic group, a generator *g*,
+and an element *h*, it is hard to find an integer *x* such that *g^x = h*.
+
+The group is the largest multiplicative sub-group of the integers modulo *p*,
+with *p* prime.
+The signer holds a value *x* (*0<x<p-1*) as private key, and its public
+key (*y* where *y=g^x mod p*) is distributed.
+
+The ElGamal signature is twice as big as *p*.
+
+Encryption algorithm
+--------------------
+The security of the ElGamal encryption scheme is based on the computational
+Diffie-Hellman problem (CDH_). Given a cyclic group, a generator *g*,
+and two integers *a* and *b*, it is difficult to find
+the element *g^{ab}* when only *g^a* and *g^b* are known, and not *a* and *b*.
+
+As before, the group is the largest multiplicative sub-group of the integers
+modulo *p*, with *p* prime.
+The receiver holds a value *a* (*0<a<p-1*) as private key, and its public key
+(*b* where *b*=g^a*) is given to the sender.
+
+The ElGamal ciphertext is twice as big as *p*.
+
+Domain parameters
+-----------------
+For both signature and encryption schemes, the values *(p,g)* are called
+*domain parameters*.
+They are not sensitive but must be distributed to all parties (senders and
+receivers).
+Different signers can share the same domain parameters, as can
+different recipients of encrypted messages.
+
+Security
+--------
+Both DLP and CDH problem are believed to be difficult, and they have been proved
+such (and therefore secure) for more than 30 years.
+
+The cryptographic strength is linked to the magnitude of *p*.
+In 2012, a sufficient size for *p* is deemed to be 2048 bits.
+For more information, see the most recent ECRYPT_ report.
+
+Even though ElGamal algorithms are in theory reasonably secure for new designs,
+in practice there are no real good reasons for using them.
+The signature is four times larger than the equivalent DSA, and the ciphertext
+is two times larger than the equivalent RSA.
+
+Functionality
+-------------
+This module provides facilities for generating new ElGamal keys and for constructing
+them from known components. ElGamal keys allows you to perform basic signing,
+verification, encryption, and decryption.
+
+ >>> from Crypto import Random
+ >>> from Crypto.Random import random
+ >>> from Crypto.PublicKey import ElGamal
+ >>> from Crypto.Util.number import GCD
+ >>> from Crypto.Hash import SHA
+ >>>
+ >>> message = "Hello"
+ >>> key = ElGamal.generate(1024, Random.new().read)
+ >>> h = SHA.new(message).digest()
+ >>> while 1:
+ >>> k = random.StrongRandom().randint(1,key.p-1)
+ >>> if GCD(k,key.p-1)==1: break
+ >>> sig = key.sign(h,k)
+ >>> ...
+ >>> if key.verify(h,sig):
+ >>> print "OK"
+ >>> else:
+ >>> print "Incorrect signature"
+
+.. _DLP: http://www.cosic.esat.kuleuven.be/publications/talk-78.pdf
+.. _CDH: http://en.wikipedia.org/wiki/Computational_Diffie%E2%80%93Hellman_assumption
+.. _ECRYPT: http://www.ecrypt.eu.org/documents/D.SPA.17.pdf
+"""
+
+__revision__ = "$Id$"
+
+__all__ = ['generate', 'construct', 'error', 'ElGamalobj']
+
+from Crypto.PublicKey.pubkey import *
+from Crypto.Util import number
+
+class error (Exception):
+ pass
+
+# Generate an ElGamal key with N bits
+def generate(bits, randfunc, progress_func=None):
+ """Randomly generate a fresh, new ElGamal key.
+
+ The key will be safe for use for both encryption and signature
+ (although it should be used for **only one** purpose).
+
+ :Parameters:
+ bits : int
+ Key length, or size (in bits) of the modulus *p*.
+ Recommended value is 2048.
+ randfunc : callable
+ Random number generation function; it should accept
+ a single integer N and return a string of random data
+ N bytes long.
+ progress_func : callable
+ Optional function that will be called with a short string
+ containing the key parameter currently being generated;
+ it's useful for interactive applications where a user is
+ waiting for a key to be generated.
+
+ :attention: You should always use a cryptographically secure random number generator,
+ such as the one defined in the ``Crypto.Random`` module; **don't** just use the
+ current time and the ``random`` module.
+
+ :Return: An ElGamal key object (`ElGamalobj`).
+ """
+ obj=ElGamalobj()
+ # Generate a safe prime p
+ # See Algorithm 4.86 in Handbook of Applied Cryptography
+ if progress_func:
+ progress_func('p\n')
+ while 1:
+ q = bignum(getPrime(bits-1, randfunc))
+ obj.p = 2*q+1
+ if number.isPrime(obj.p, randfunc=randfunc):
+ break
+ # Generate generator g
+ # See Algorithm 4.80 in Handbook of Applied Cryptography
+ # Note that the order of the group is n=p-1=2q, where q is prime
+ if progress_func:
+ progress_func('g\n')
+ while 1:
+ # We must avoid g=2 because of Bleichenbacher's attack described
+ # in "Generating ElGamal signatures without knowning the secret key",
+ # 1996
+ #
+ obj.g = number.getRandomRange(3, obj.p, randfunc)
+ safe = 1
+ if pow(obj.g, 2, obj.p)==1:
+ safe=0
+ if safe and pow(obj.g, q, obj.p)==1:
+ safe=0
+ # Discard g if it divides p-1 because of the attack described
+ # in Note 11.67 (iii) in HAC
+ if safe and divmod(obj.p-1, obj.g)[1]==0:
+ safe=0
+ # g^{-1} must not divide p-1 because of Khadir's attack
+ # described in "Conditions of the generator for forging ElGamal
+ # signature", 2011
+ ginv = number.inverse(obj.g, obj.p)
+ if safe and divmod(obj.p-1, ginv)[1]==0:
+ safe=0
+ if safe:
+ break
+ # Generate private key x
+ if progress_func:
+ progress_func('x\n')
+ obj.x=number.getRandomRange(2, obj.p-1, randfunc)
+ # Generate public key y
+ if progress_func:
+ progress_func('y\n')
+ obj.y = pow(obj.g, obj.x, obj.p)
+ return obj
+
+def construct(tup):
+ """Construct an ElGamal key from a tuple of valid ElGamal components.
+
+ The modulus *p* must be a prime.
+
+ The following conditions must apply:
+
+ - 1 < g < p-1
+ - g^{p-1} = 1 mod p
+ - 1 < x < p-1
+ - g^x = y mod p
+
+ :Parameters:
+ tup : tuple
+ A tuple of long integers, with 3 or 4 items
+ in the following order:
+
+ 1. Modulus (*p*).
+ 2. Generator (*g*).
+ 3. Public key (*y*).
+ 4. Private key (*x*). Optional.
+
+ :Return: An ElGamal key object (`ElGamalobj`).
+ """
+
+ obj=ElGamalobj()
+ if len(tup) not in [3,4]:
+ raise ValueError('argument for construct() wrong length')
+ for i in range(len(tup)):
+ field = obj.keydata[i]
+ setattr(obj, field, tup[i])
+ return obj
+
+class ElGamalobj(pubkey):
+ """Class defining an ElGamal key.
+
+ :undocumented: __getstate__, __setstate__, __repr__, __getattr__
+ """
+
+ #: Dictionary of ElGamal parameters.
+ #:
+ #: A public key will only have the following entries:
+ #:
+ #: - **y**, the public key.
+ #: - **g**, the generator.
+ #: - **p**, the modulus.
+ #:
+ #: A private key will also have:
+ #:
+ #: - **x**, the private key.
+ keydata=['p', 'g', 'y', 'x']
+
+ def encrypt(self, plaintext, K):
+ """Encrypt a piece of data with ElGamal.
+
+ :Parameter plaintext: The piece of data to encrypt with ElGamal.
+ It must be numerically smaller than the module (*p*).
+ :Type plaintext: byte string or long
+
+ :Parameter K: A secret number, chosen randomly in the closed
+ range *[1,p-2]*.
+ :Type K: long (recommended) or byte string (not recommended)
+
+ :Return: A tuple with two items. Each item is of the same type as the
+ plaintext (string or long).
+
+ :attention: selection of *K* is crucial for security. Generating a
+ random number larger than *p-1* and taking the modulus by *p-1* is
+ **not** secure, since smaller values will occur more frequently.
+ Generating a random number systematically smaller than *p-1*
+ (e.g. *floor((p-1)/8)* random bytes) is also **not** secure.
+ In general, it shall not be possible for an attacker to know
+ the value of any bit of K.
+
+ :attention: The number *K* shall not be reused for any other
+ operation and shall be discarded immediately.
+ """
+ return pubkey.encrypt(self, plaintext, K)
+
+ def decrypt(self, ciphertext):
+ """Decrypt a piece of data with ElGamal.
+
+ :Parameter ciphertext: The piece of data to decrypt with ElGamal.
+ :Type ciphertext: byte string, long or a 2-item tuple as returned
+ by `encrypt`
+
+ :Return: A byte string if ciphertext was a byte string or a tuple
+ of byte strings. A long otherwise.
+ """
+ return pubkey.decrypt(self, ciphertext)
+
+ def sign(self, M, K):
+ """Sign a piece of data with ElGamal.
+
+ :Parameter M: The piece of data to sign with ElGamal. It may
+ not be longer in bit size than *p-1*.
+ :Type M: byte string or long
+
+ :Parameter K: A secret number, chosen randomly in the closed
+ range *[1,p-2]* and such that *gcd(k,p-1)=1*.
+ :Type K: long (recommended) or byte string (not recommended)
+
+ :attention: selection of *K* is crucial for security. Generating a
+ random number larger than *p-1* and taking the modulus by *p-1* is
+ **not** secure, since smaller values will occur more frequently.
+ Generating a random number systematically smaller than *p-1*
+ (e.g. *floor((p-1)/8)* random bytes) is also **not** secure.
+ In general, it shall not be possible for an attacker to know
+ the value of any bit of K.
+
+ :attention: The number *K* shall not be reused for any other
+ operation and shall be discarded immediately.
+
+ :attention: M must be be a cryptographic hash, otherwise an
+ attacker may mount an existential forgery attack.
+
+ :Return: A tuple with 2 longs.
+ """
+ return pubkey.sign(self, M, K)
+
+ def verify(self, M, signature):
+ """Verify the validity of an ElGamal signature.
+
+ :Parameter M: The expected message.
+ :Type M: byte string or long
+
+ :Parameter signature: The ElGamal signature to verify.
+ :Type signature: A tuple with 2 longs as return by `sign`
+
+ :Return: True if the signature is correct, False otherwise.
+ """
+ return pubkey.verify(self, M, signature)
+
+ def _encrypt(self, M, K):
+ a=pow(self.g, K, self.p)
+ b=( M*pow(self.y, K, self.p) ) % self.p
+ return ( a,b )
+
+ def _decrypt(self, M):
+ if (not hasattr(self, 'x')):
+ raise TypeError('Private key not available in this object')
+ ax=pow(M[0], self.x, self.p)
+ plaintext=(M[1] * inverse(ax, self.p ) ) % self.p
+ return plaintext
+
+ def _sign(self, M, K):
+ if (not hasattr(self, 'x')):
+ raise TypeError('Private key not available in this object')
+ p1=self.p-1
+ if (GCD(K, p1)!=1):
+ raise ValueError('Bad K value: GCD(K,p-1)!=1')
+ a=pow(self.g, K, self.p)
+ t=(M-self.x*a) % p1
+ while t<0: t=t+p1
+ b=(t*inverse(K, p1)) % p1
+ return (a, b)
+
+ def _verify(self, M, sig):
+ if sig[0]<1 or sig[0]>self.p-1:
+ return 0
+ v1=pow(self.y, sig[0], self.p)
+ v1=(v1*pow(sig[0], sig[1], self.p)) % self.p
+ v2=pow(self.g, M, self.p)
+ if v1==v2:
+ return 1
+ return 0
+
+ def size(self):
+ return number.size(self.p) - 1
+
+ def has_private(self):
+ if hasattr(self, 'x'):
+ return 1
+ else:
+ return 0
+
+ def publickey(self):
+ return construct((self.p, self.g, self.y))
+
+
+object=ElGamalobj
diff --git a/frozen_deps/Crypto/PublicKey/RSA.py b/frozen_deps/Crypto/PublicKey/RSA.py
new file mode 100644
index 0000000..debe39e
--- /dev/null
+++ b/frozen_deps/Crypto/PublicKey/RSA.py
@@ -0,0 +1,719 @@
+# -*- coding: utf-8 -*-
+#
+# PublicKey/RSA.py : RSA public key primitive
+#
+# Written in 2008 by Dwayne C. Litzenberger <[email protected]>
+#
+# ===================================================================
+# The contents of this file are dedicated to the public domain. To
+# the extent that dedication to the public domain is not available,
+# everyone is granted a worldwide, perpetual, royalty-free,
+# non-exclusive license to exercise all rights associated with the
+# contents of this file for any purpose whatsoever.
+# No rights are reserved.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+# SOFTWARE.
+# ===================================================================
+
+"""RSA public-key cryptography algorithm (signature and encryption).
+
+RSA_ is the most widespread and used public key algorithm. Its security is
+based on the difficulty of factoring large integers. The algorithm has
+withstood attacks for 30 years, and it is therefore considered reasonably
+secure for new designs.
+
+The algorithm can be used for both confidentiality (encryption) and
+authentication (digital signature). It is worth noting that signing and
+decryption are significantly slower than verification and encryption.
+The cryptograhic strength is primarily linked to the length of the modulus *n*.
+In 2012, a sufficient length is deemed to be 2048 bits. For more information,
+see the most recent ECRYPT_ report.
+
+Both RSA ciphertext and RSA signature are as big as the modulus *n* (256
+bytes if *n* is 2048 bit long).
+
+This module provides facilities for generating fresh, new RSA keys, constructing
+them from known components, exporting them, and importing them.
+
+ >>> from Crypto.PublicKey import RSA
+ >>>
+ >>> key = RSA.generate(2048)
+ >>> f = open('mykey.pem','w')
+ >>> f.write(RSA.exportKey('PEM'))
+ >>> f.close()
+ ...
+ >>> f = open('mykey.pem','r')
+ >>> key = RSA.importKey(f.read())
+
+Even though you may choose to directly use the methods of an RSA key object
+to perform the primitive cryptographic operations (e.g. `_RSAobj.encrypt`),
+it is recommended to use one of the standardized schemes instead (like
+`Crypto.Cipher.PKCS1_v1_5` or `Crypto.Signature.PKCS1_v1_5`).
+
+.. _RSA: http://en.wikipedia.org/wiki/RSA_%28algorithm%29
+.. _ECRYPT: http://www.ecrypt.eu.org/documents/D.SPA.17.pdf
+
+:sort: generate,construct,importKey,error
+"""
+
+__revision__ = "$Id$"
+
+__all__ = ['generate', 'construct', 'error', 'importKey', 'RSAImplementation', '_RSAobj']
+
+import sys
+if sys.version_info[0] == 2 and sys.version_info[1] == 1:
+ from Crypto.Util.py21compat import *
+from Crypto.Util.py3compat import *
+#from Crypto.Util.python_compat import *
+from Crypto.Util.number import getRandomRange, bytes_to_long, long_to_bytes
+
+from Crypto.PublicKey import _RSA, _slowmath, pubkey
+from Crypto import Random
+
+from Crypto.Util.asn1 import DerObject, DerSequence, DerNull
+import binascii
+import struct
+
+from Crypto.Util.number import inverse
+
+from Crypto.Util.number import inverse
+
+try:
+ from Crypto.PublicKey import _fastmath
+except ImportError:
+ _fastmath = None
+
+class _RSAobj(pubkey.pubkey):
+ """Class defining an actual RSA key.
+
+ :undocumented: __getstate__, __setstate__, __repr__, __getattr__
+ """
+ #: Dictionary of RSA parameters.
+ #:
+ #: A public key will only have the following entries:
+ #:
+ #: - **n**, the modulus.
+ #: - **e**, the public exponent.
+ #:
+ #: A private key will also have:
+ #:
+ #: - **d**, the private exponent.
+ #: - **p**, the first factor of n.
+ #: - **q**, the second factor of n.
+ #: - **u**, the CRT coefficient (1/p) mod q.
+ keydata = ['n', 'e', 'd', 'p', 'q', 'u']
+
+ def __init__(self, implementation, key, randfunc=None):
+ self.implementation = implementation
+ self.key = key
+ if randfunc is None:
+ randfunc = Random.new().read
+ self._randfunc = randfunc
+
+ def __getattr__(self, attrname):
+ if attrname in self.keydata:
+ # For backward compatibility, allow the user to get (not set) the
+ # RSA key parameters directly from this object.
+ return getattr(self.key, attrname)
+ else:
+ raise AttributeError("%s object has no %r attribute" % (self.__class__.__name__, attrname,))
+
+ def encrypt(self, plaintext, K):
+ """Encrypt a piece of data with RSA.
+
+ :Parameter plaintext: The piece of data to encrypt with RSA. It may not
+ be numerically larger than the RSA module (**n**).
+ :Type plaintext: byte string or long
+
+ :Parameter K: A random parameter (*for compatibility only. This
+ value will be ignored*)
+ :Type K: byte string or long
+
+ :attention: this function performs the plain, primitive RSA encryption
+ (*textbook*). In real applications, you always need to use proper
+ cryptographic padding, and you should not directly encrypt data with
+ this method. Failure to do so may lead to security vulnerabilities.
+ It is recommended to use modules
+ `Crypto.Cipher.PKCS1_OAEP` or `Crypto.Cipher.PKCS1_v1_5` instead.
+
+ :Return: A tuple with two items. The first item is the ciphertext
+ of the same type as the plaintext (string or long). The second item
+ is always None.
+ """
+ return pubkey.pubkey.encrypt(self, plaintext, K)
+
+ def decrypt(self, ciphertext):
+ """Decrypt a piece of data with RSA.
+
+ Decryption always takes place with blinding.
+
+ :attention: this function performs the plain, primitive RSA decryption
+ (*textbook*). In real applications, you always need to use proper
+ cryptographic padding, and you should not directly decrypt data with
+ this method. Failure to do so may lead to security vulnerabilities.
+ It is recommended to use modules
+ `Crypto.Cipher.PKCS1_OAEP` or `Crypto.Cipher.PKCS1_v1_5` instead.
+
+ :Parameter ciphertext: The piece of data to decrypt with RSA. It may
+ not be numerically larger than the RSA module (**n**). If a tuple,
+ the first item is the actual ciphertext; the second item is ignored.
+
+ :Type ciphertext: byte string, long or a 2-item tuple as returned by
+ `encrypt`
+
+ :Return: A byte string if ciphertext was a byte string or a tuple
+ of byte strings. A long otherwise.
+ """
+ return pubkey.pubkey.decrypt(self, ciphertext)
+
+ def sign(self, M, K):
+ """Sign a piece of data with RSA.
+
+ Signing always takes place with blinding.
+
+ :attention: this function performs the plain, primitive RSA decryption
+ (*textbook*). In real applications, you always need to use proper
+ cryptographic padding, and you should not directly sign data with
+ this method. Failure to do so may lead to security vulnerabilities.
+ It is recommended to use modules
+ `Crypto.Signature.PKCS1_PSS` or `Crypto.Signature.PKCS1_v1_5` instead.
+
+ :Parameter M: The piece of data to sign with RSA. It may
+ not be numerically larger than the RSA module (**n**).
+ :Type M: byte string or long
+
+ :Parameter K: A random parameter (*for compatibility only. This
+ value will be ignored*)
+ :Type K: byte string or long
+
+ :Return: A 2-item tuple. The first item is the actual signature (a
+ long). The second item is always None.
+ """
+ return pubkey.pubkey.sign(self, M, K)
+
+ def verify(self, M, signature):
+ """Verify the validity of an RSA signature.
+
+ :attention: this function performs the plain, primitive RSA encryption
+ (*textbook*). In real applications, you always need to use proper
+ cryptographic padding, and you should not directly verify data with
+ this method. Failure to do so may lead to security vulnerabilities.
+ It is recommended to use modules
+ `Crypto.Signature.PKCS1_PSS` or `Crypto.Signature.PKCS1_v1_5` instead.
+
+ :Parameter M: The expected message.
+ :Type M: byte string or long
+
+ :Parameter signature: The RSA signature to verify. The first item of
+ the tuple is the actual signature (a long not larger than the modulus
+ **n**), whereas the second item is always ignored.
+ :Type signature: A 2-item tuple as return by `sign`
+
+ :Return: True if the signature is correct, False otherwise.
+ """
+ return pubkey.pubkey.verify(self, M, signature)
+
+ def _encrypt(self, c, K):
+ return (self.key._encrypt(c),)
+
+ def _decrypt(self, c):
+ #(ciphertext,) = c
+ (ciphertext,) = c[:1] # HACK - We should use the previous line
+ # instead, but this is more compatible and we're
+ # going to replace the Crypto.PublicKey API soon
+ # anyway.
+
+ # Blinded RSA decryption (to prevent timing attacks):
+ # Step 1: Generate random secret blinding factor r, such that 0 < r < n-1
+ r = getRandomRange(1, self.key.n-1, randfunc=self._randfunc)
+ # Step 2: Compute c' = c * r**e mod n
+ cp = self.key._blind(ciphertext, r)
+ # Step 3: Compute m' = c'**d mod n (ordinary RSA decryption)
+ mp = self.key._decrypt(cp)
+ # Step 4: Compute m = m**(r-1) mod n
+ return self.key._unblind(mp, r)
+
+ def _blind(self, m, r):
+ return self.key._blind(m, r)
+
+ def _unblind(self, m, r):
+ return self.key._unblind(m, r)
+
+ def _sign(self, m, K=None):
+ return (self.key._sign(m),)
+
+ def _verify(self, m, sig):
+ #(s,) = sig
+ (s,) = sig[:1] # HACK - We should use the previous line instead, but
+ # this is more compatible and we're going to replace
+ # the Crypto.PublicKey API soon anyway.
+ return self.key._verify(m, s)
+
+ def has_private(self):
+ return self.key.has_private()
+
+ def size(self):
+ return self.key.size()
+
+ def can_blind(self):
+ return True
+
+ def can_encrypt(self):
+ return True
+
+ def can_sign(self):
+ return True
+
+ def publickey(self):
+ return self.implementation.construct((self.key.n, self.key.e))
+
+ def __getstate__(self):
+ d = {}
+ for k in self.keydata:
+ try:
+ d[k] = getattr(self.key, k)
+ except AttributeError:
+ pass
+ return d
+
+ def __setstate__(self, d):
+ if not hasattr(self, 'implementation'):
+ self.implementation = RSAImplementation()
+ t = []
+ for k in self.keydata:
+ if k not in d:
+ break
+ t.append(d[k])
+ self.key = self.implementation._math.rsa_construct(*tuple(t))
+
+ def __repr__(self):
+ attrs = []
+ for k in self.keydata:
+ if k == 'n':
+ attrs.append("n(%d)" % (self.size()+1,))
+ elif hasattr(self.key, k):
+ attrs.append(k)
+ if self.has_private():
+ attrs.append("private")
+ # PY3K: This is meant to be text, do not change to bytes (data)
+ return "<%s @0x%x %s>" % (self.__class__.__name__, id(self), ",".join(attrs))
+
+ def exportKey(self, format='PEM', passphrase=None, pkcs=1):
+ """Export this RSA key.
+
+ :Parameter format: The format to use for wrapping the key.
+
+ - *'DER'*. Binary encoding, always unencrypted.
+ - *'PEM'*. Textual encoding, done according to `RFC1421`_/`RFC1423`_.
+ Unencrypted (default) or encrypted.
+ - *'OpenSSH'*. Textual encoding, done according to OpenSSH specification.
+ Only suitable for public keys (not private keys).
+ :Type format: string
+
+ :Parameter passphrase: In case of PEM, the pass phrase to derive the encryption key from.
+ :Type passphrase: string
+
+ :Parameter pkcs: The PKCS standard to follow for assembling the key.
+ You have two choices:
+
+ - with **1**, the public key is embedded into an X.509 `SubjectPublicKeyInfo` DER SEQUENCE.
+ The private key is embedded into a `PKCS#1`_ `RSAPrivateKey` DER SEQUENCE.
+ This mode is the default.
+ - with **8**, the private key is embedded into a `PKCS#8`_ `PrivateKeyInfo` DER SEQUENCE.
+ This mode is not available for public keys.
+
+ PKCS standards are not relevant for the *OpenSSH* format.
+ :Type pkcs: integer
+
+ :Return: A byte string with the encoded public or private half.
+ :Raise ValueError:
+ When the format is unknown.
+
+ .. _RFC1421: http://www.ietf.org/rfc/rfc1421.txt
+ .. _RFC1423: http://www.ietf.org/rfc/rfc1423.txt
+ .. _`PKCS#1`: http://www.ietf.org/rfc/rfc3447.txt
+ .. _`PKCS#8`: http://www.ietf.org/rfc/rfc5208.txt
+ """
+ if passphrase is not None:
+ passphrase = tobytes(passphrase)
+ if format=='OpenSSH':
+ eb = long_to_bytes(self.e)
+ nb = long_to_bytes(self.n)
+ if bord(eb[0]) & 0x80: eb=bchr(0x00)+eb
+ if bord(nb[0]) & 0x80: nb=bchr(0x00)+nb
+ keyparts = [ 'ssh-rsa', eb, nb ]
+ keystring = ''.join([ struct.pack(">I",len(kp))+kp for kp in keyparts])
+ return 'ssh-rsa '+binascii.b2a_base64(keystring)[:-1]
+
+ # DER format is always used, even in case of PEM, which simply
+ # encodes it into BASE64.
+ der = DerSequence()
+ if self.has_private():
+ keyType= { 1: 'RSA PRIVATE', 8: 'PRIVATE' }[pkcs]
+ der[:] = [ 0, self.n, self.e, self.d, self.p, self.q,
+ self.d % (self.p-1), self.d % (self.q-1),
+ inverse(self.q, self.p) ]
+ if pkcs==8:
+ derkey = der.encode()
+ der = DerSequence([0])
+ der.append(algorithmIdentifier)
+ der.append(DerObject('OCTET STRING', derkey).encode())
+ else:
+ keyType = "PUBLIC"
+ der.append(algorithmIdentifier)
+ bitmap = DerObject('BIT STRING')
+ derPK = DerSequence( [ self.n, self.e ] )
+ bitmap.payload = bchr(0x00) + derPK.encode()
+ der.append(bitmap.encode())
+ if format=='DER':
+ return der.encode()
+ if format=='PEM':
+ pem = b("-----BEGIN " + keyType + " KEY-----\n")
+ objenc = None
+ if passphrase and keyType.endswith('PRIVATE'):
+ # We only support 3DES for encryption
+ import Crypto.Hash.MD5
+ from Crypto.Cipher import DES3
+ from Crypto.Protocol.KDF import PBKDF1
+ salt = self._randfunc(8)
+ key = PBKDF1(passphrase, salt, 16, 1, Crypto.Hash.MD5)
+ key += PBKDF1(key+passphrase, salt, 8, 1, Crypto.Hash.MD5)
+ objenc = DES3.new(key, Crypto.Cipher.DES3.MODE_CBC, salt)
+ pem += b('Proc-Type: 4,ENCRYPTED\n')
+ pem += b('DEK-Info: DES-EDE3-CBC,') + binascii.b2a_hex(salt).upper() + b('\n\n')
+
+ binaryKey = der.encode()
+ if objenc:
+ # Add PKCS#7-like padding
+ padding = objenc.block_size-len(binaryKey)%objenc.block_size
+ binaryKey = objenc.encrypt(binaryKey+bchr(padding)*padding)
+
+ # Each BASE64 line can take up to 64 characters (=48 bytes of data)
+ chunks = [ binascii.b2a_base64(binaryKey[i:i+48]) for i in range(0, len(binaryKey), 48) ]
+ pem += b('').join(chunks)
+ pem += b("-----END " + keyType + " KEY-----")
+ return pem
+ return ValueError("Unknown key format '%s'. Cannot export the RSA key." % format)
+
+class RSAImplementation(object):
+ """
+ An RSA key factory.
+
+ This class is only internally used to implement the methods of the `Crypto.PublicKey.RSA` module.
+
+ :sort: __init__,generate,construct,importKey
+ :undocumented: _g*, _i*
+ """
+
+ def __init__(self, **kwargs):
+ """Create a new RSA key factory.
+
+ :Keywords:
+ use_fast_math : bool
+ Specify which mathematic library to use:
+
+ - *None* (default). Use fastest math available.
+ - *True* . Use fast math.
+ - *False* . Use slow math.
+ default_randfunc : callable
+ Specify how to collect random data:
+
+ - *None* (default). Use Random.new().read().
+ - not *None* . Use the specified function directly.
+ :Raise RuntimeError:
+ When **use_fast_math** =True but fast math is not available.
+ """
+ use_fast_math = kwargs.get('use_fast_math', None)
+ if use_fast_math is None: # Automatic
+ if _fastmath is not None:
+ self._math = _fastmath
+ else:
+ self._math = _slowmath
+
+ elif use_fast_math: # Explicitly select fast math
+ if _fastmath is not None:
+ self._math = _fastmath
+ else:
+ raise RuntimeError("fast math module not available")
+
+ else: # Explicitly select slow math
+ self._math = _slowmath
+
+ self.error = self._math.error
+
+ self._default_randfunc = kwargs.get('default_randfunc', None)
+ self._current_randfunc = None
+
+ def _get_randfunc(self, randfunc):
+ if randfunc is not None:
+ return randfunc
+ elif self._current_randfunc is None:
+ self._current_randfunc = Random.new().read
+ return self._current_randfunc
+
+ def generate(self, bits, randfunc=None, progress_func=None, e=65537):
+ """Randomly generate a fresh, new RSA key.
+
+ :Parameters:
+ bits : int
+ Key length, or size (in bits) of the RSA modulus.
+ It must be a multiple of 256, and no smaller than 1024.
+
+ randfunc : callable
+ Random number generation function; it should accept
+ a single integer N and return a string of random data
+ N bytes long.
+ If not specified, a new one will be instantiated
+ from ``Crypto.Random``.
+
+ progress_func : callable
+ Optional function that will be called with a short string
+ containing the key parameter currently being generated;
+ it's useful for interactive applications where a user is
+ waiting for a key to be generated.
+
+ e : int
+ Public RSA exponent. It must be an odd positive integer.
+ It is typically a small number with very few ones in its
+ binary representation.
+ The default value 65537 (= ``0b10000000000000001`` ) is a safe
+ choice: other common values are 5, 7, 17, and 257.
+
+ :attention: You should always use a cryptographically secure random number generator,
+ such as the one defined in the ``Crypto.Random`` module; **don't** just use the
+ current time and the ``random`` module.
+
+ :attention: Exponent 3 is also widely used, but it requires very special care when padding
+ the message.
+
+ :Return: An RSA key object (`_RSAobj`).
+
+ :Raise ValueError:
+ When **bits** is too little or not a multiple of 256, or when
+ **e** is not odd or smaller than 2.
+ """
+ if bits < 1024 or (bits & 0xff) != 0:
+ # pubkey.getStrongPrime doesn't like anything that's not a multiple of 256 and >= 1024
+ raise ValueError("RSA modulus length must be a multiple of 256 and >= 1024")
+ if e%2==0 or e<3:
+ raise ValueError("RSA public exponent must be a positive, odd integer larger than 2.")
+ rf = self._get_randfunc(randfunc)
+ obj = _RSA.generate_py(bits, rf, progress_func, e) # TODO: Don't use legacy _RSA module
+ key = self._math.rsa_construct(obj.n, obj.e, obj.d, obj.p, obj.q, obj.u)
+ return _RSAobj(self, key)
+
+ def construct(self, tup):
+ """Construct an RSA key from a tuple of valid RSA components.
+
+ The modulus **n** must be the product of two primes.
+ The public exponent **e** must be odd and larger than 1.
+
+ In case of a private key, the following equations must apply:
+
+ - e != 1
+ - p*q = n
+ - e*d = 1 mod (p-1)(q-1)
+ - p*u = 1 mod q
+
+ :Parameters:
+ tup : tuple
+ A tuple of long integers, with at least 2 and no
+ more than 6 items. The items come in the following order:
+
+ 1. RSA modulus (n).
+ 2. Public exponent (e).
+ 3. Private exponent (d). Only required if the key is private.
+ 4. First factor of n (p). Optional.
+ 5. Second factor of n (q). Optional.
+ 6. CRT coefficient, (1/p) mod q (u). Optional.
+
+ :Return: An RSA key object (`_RSAobj`).
+ """
+ key = self._math.rsa_construct(*tup)
+ return _RSAobj(self, key)
+
+ def _importKeyDER(self, externKey):
+ """Import an RSA key (public or private half), encoded in DER form."""
+
+ try:
+
+ der = DerSequence()
+ der.decode(externKey, True)
+
+ # Try PKCS#1 first, for a private key
+ if len(der)==9 and der.hasOnlyInts() and der[0]==0:
+ # ASN.1 RSAPrivateKey element
+ del der[6:] # Remove d mod (p-1), d mod (q-1), and q^{-1} mod p
+ der.append(inverse(der[4],der[5])) # Add p^{-1} mod q
+ del der[0] # Remove version
+ return self.construct(der[:])
+
+ # Keep on trying PKCS#1, but now for a public key
+ if len(der)==2:
+ # The DER object is an RSAPublicKey SEQUENCE with two elements
+ if der.hasOnlyInts():
+ return self.construct(der[:])
+ # The DER object is a SubjectPublicKeyInfo SEQUENCE with two elements:
+ # an 'algorithm' (or 'algorithmIdentifier') SEQUENCE and a 'subjectPublicKey' BIT STRING.
+ # 'algorithm' takes the value given a few lines above.
+ # 'subjectPublicKey' encapsulates the actual ASN.1 RSAPublicKey element.
+ if der[0]==algorithmIdentifier:
+ bitmap = DerObject()
+ bitmap.decode(der[1], True)
+ if bitmap.isType('BIT STRING') and bord(bitmap.payload[0])==0x00:
+ der.decode(bitmap.payload[1:], True)
+ if len(der)==2 and der.hasOnlyInts():
+ return self.construct(der[:])
+
+ # Try unencrypted PKCS#8
+ if der[0]==0:
+ # The second element in the SEQUENCE is algorithmIdentifier.
+ # It must say RSA (see above for description).
+ if der[1]==algorithmIdentifier:
+ privateKey = DerObject()
+ privateKey.decode(der[2], True)
+ if privateKey.isType('OCTET STRING'):
+ return self._importKeyDER(privateKey.payload)
+
+ except ValueError as IndexError:
+ pass
+
+ raise ValueError("RSA key format is not supported")
+
+ def importKey(self, externKey, passphrase=None):
+ """Import an RSA key (public or private half), encoded in standard form.
+
+ :Parameter externKey:
+ The RSA key to import, encoded as a string.
+
+ An RSA public key can be in any of the following formats:
+
+ - X.509 `subjectPublicKeyInfo` DER SEQUENCE (binary or PEM encoding)
+ - `PKCS#1`_ `RSAPublicKey` DER SEQUENCE (binary or PEM encoding)
+ - OpenSSH (textual public key only)
+
+ An RSA private key can be in any of the following formats:
+
+ - PKCS#1 `RSAPrivateKey` DER SEQUENCE (binary or PEM encoding)
+ - `PKCS#8`_ `PrivateKeyInfo` DER SEQUENCE (binary or PEM encoding)
+ - OpenSSH (textual public key only)
+
+ For details about the PEM encoding, see `RFC1421`_/`RFC1423`_.
+
+ In case of PEM encoding, the private key can be encrypted with DES or 3TDES according to a certain ``pass phrase``.
+ Only OpenSSL-compatible pass phrases are supported.
+ :Type externKey: string
+
+ :Parameter passphrase:
+ In case of an encrypted PEM key, this is the pass phrase from which the encryption key is derived.
+ :Type passphrase: string
+
+ :Return: An RSA key object (`_RSAobj`).
+
+ :Raise ValueError/IndexError/TypeError:
+ When the given key cannot be parsed (possibly because the pass phrase is wrong).
+
+ .. _RFC1421: http://www.ietf.org/rfc/rfc1421.txt
+ .. _RFC1423: http://www.ietf.org/rfc/rfc1423.txt
+ .. _`PKCS#1`: http://www.ietf.org/rfc/rfc3447.txt
+ .. _`PKCS#8`: http://www.ietf.org/rfc/rfc5208.txt
+ """
+ externKey = tobytes(externKey)
+ if passphrase is not None:
+ passphrase = tobytes(passphrase)
+
+ if externKey.startswith(b('-----')):
+ # This is probably a PEM encoded key
+ lines = externKey.replace(b(" "),b('')).split()
+ keyobj = None
+
+ # The encrypted PEM format
+ if lines[1].startswith(b('Proc-Type:4,ENCRYPTED')):
+ DEK = lines[2].split(b(':'))
+ if len(DEK)!=2 or DEK[0]!=b('DEK-Info') or not passphrase:
+ raise ValueError("PEM encryption format not supported.")
+ algo, salt = DEK[1].split(b(','))
+ salt = binascii.a2b_hex(salt)
+ import Crypto.Hash.MD5
+ from Crypto.Cipher import DES, DES3
+ from Crypto.Protocol.KDF import PBKDF1
+ if algo==b("DES-CBC"):
+ # This is EVP_BytesToKey in OpenSSL
+ key = PBKDF1(passphrase, salt, 8, 1, Crypto.Hash.MD5)
+ keyobj = DES.new(key, Crypto.Cipher.DES.MODE_CBC, salt)
+ elif algo==b("DES-EDE3-CBC"):
+ # Note that EVP_BytesToKey is note exactly the same as PBKDF1
+ key = PBKDF1(passphrase, salt, 16, 1, Crypto.Hash.MD5)
+ key += PBKDF1(key+passphrase, salt, 8, 1, Crypto.Hash.MD5)
+ keyobj = DES3.new(key, Crypto.Cipher.DES3.MODE_CBC, salt)
+ else:
+ raise ValueError("Unsupport PEM encryption algorithm.")
+ lines = lines[2:]
+
+ der = binascii.a2b_base64(b('').join(lines[1:-1]))
+ if keyobj:
+ der = keyobj.decrypt(der)
+ padding = bord(der[-1])
+ der = der[:-padding]
+ return self._importKeyDER(der)
+
+ if externKey.startswith(b('ssh-rsa ')):
+ # This is probably an OpenSSH key
+ keystring = binascii.a2b_base64(externKey.split(b(' '))[1])
+ keyparts = []
+ while len(keystring)>4:
+ l = struct.unpack(">I",keystring[:4])[0]
+ keyparts.append(keystring[4:4+l])
+ keystring = keystring[4+l:]
+ e = bytes_to_long(keyparts[1])
+ n = bytes_to_long(keyparts[2])
+ return self.construct([n, e])
+ if bord(externKey[0])==0x30:
+ # This is probably a DER encoded key
+ return self._importKeyDER(externKey)
+
+ raise ValueError("RSA key format is not supported")
+
+#: This is the ASN.1 DER object that qualifies an algorithm as
+#: compliant to PKCS#1 (that is, the standard RSA).
+# It is found in all 'algorithm' fields (also called 'algorithmIdentifier').
+# It is a SEQUENCE with the oid assigned to RSA and with its parameters (none).
+# 0x06 0x09 OBJECT IDENTIFIER, 9 bytes of payload
+# 0x2A 0x86 0x48 0x86 0xF7 0x0D 0x01 0x01 0x01
+# rsaEncryption (1 2 840 113549 1 1 1) (PKCS #1)
+# 0x05 0x00 NULL
+algorithmIdentifier = DerSequence(
+ [ b('\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x01'),
+ DerNull().encode() ]
+ ).encode()
+
+_impl = RSAImplementation()
+#:
+#: Randomly generate a fresh, new RSA key object.
+#:
+#: See `RSAImplementation.generate`.
+#:
+generate = _impl.generate
+#:
+#: Construct an RSA key object from a tuple of valid RSA components.
+#:
+#: See `RSAImplementation.construct`.
+#:
+construct = _impl.construct
+#:
+#: Import an RSA key (public or private half), encoded in standard form.
+#:
+#: See `RSAImplementation.importKey`.
+#:
+importKey = _impl.importKey
+error = _impl.error
+
+# vim:set ts=4 sw=4 sts=4 expandtab:
+
diff --git a/frozen_deps/Crypto/PublicKey/_DSA.py b/frozen_deps/Crypto/PublicKey/_DSA.py
new file mode 100644
index 0000000..1787ced
--- /dev/null
+++ b/frozen_deps/Crypto/PublicKey/_DSA.py
@@ -0,0 +1,115 @@
+
+#
+# DSA.py : Digital Signature Algorithm
+#
+# Part of the Python Cryptography Toolkit
+#
+# Written by Andrew Kuchling, Paul Swartz, and others
+#
+# ===================================================================
+# The contents of this file are dedicated to the public domain. To
+# the extent that dedication to the public domain is not available,
+# everyone is granted a worldwide, perpetual, royalty-free,
+# non-exclusive license to exercise all rights associated with the
+# contents of this file for any purpose whatsoever.
+# No rights are reserved.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+# SOFTWARE.
+# ===================================================================
+#
+
+__revision__ = "$Id$"
+
+from Crypto.PublicKey.pubkey import *
+from Crypto.Util import number
+from Crypto.Util.number import bytes_to_long, long_to_bytes
+from Crypto.Hash import SHA
+from Crypto.Util.py3compat import *
+
+class error (Exception):
+ pass
+
+def generateQ(randfunc):
+ S=randfunc(20)
+ hash1=SHA.new(S).digest()
+ hash2=SHA.new(long_to_bytes(bytes_to_long(S)+1)).digest()
+ q = bignum(0)
+ for i in range(0,20):
+ c=bord(hash1[i])^bord(hash2[i])
+ if i==0:
+ c=c | 128
+ if i==19:
+ c= c | 1
+ q=q*256+c
+ while (not isPrime(q)):
+ q=q+2
+ if pow(2,159) < q < pow(2,160):
+ return S, q
+ raise RuntimeError('Bad q value generated')
+
+def generate_py(bits, randfunc, progress_func=None):
+ """generate(bits:int, randfunc:callable, progress_func:callable)
+
+ Generate a DSA key of length 'bits', using 'randfunc' to get
+ random data and 'progress_func', if present, to display
+ the progress of the key generation.
+ """
+
+ if bits<160:
+ raise ValueError('Key length < 160 bits')
+ obj=DSAobj()
+ # Generate string S and prime q
+ if progress_func:
+ progress_func('p,q\n')
+ while (1):
+ S, obj.q = generateQ(randfunc)
+ n=divmod(bits-1, 160)[0]
+ C, N, V = 0, 2, {}
+ b=(obj.q >> 5) & 15
+ powb=pow(bignum(2), b)
+ powL1=pow(bignum(2), bits-1)
+ while C<4096:
+ for k in range(0, n+1):
+ V[k]=bytes_to_long(SHA.new(S+bstr(N)+bstr(k)).digest())
+ W=V[n] % powb
+ for k in range(n-1, -1, -1):
+ W=(W<<160)+V[k]
+ X=W+powL1
+ p=X-(X%(2*obj.q)-1)
+ if powL1<=p and isPrime(p):
+ break
+ C, N = C+1, N+n+1
+ if C<4096:
+ break
+ if progress_func:
+ progress_func('4096 multiples failed\n')
+
+ obj.p = p
+ power=divmod(p-1, obj.q)[0]
+ if progress_func:
+ progress_func('h,g\n')
+ while (1):
+ h=bytes_to_long(randfunc(bits)) % (p-1)
+ g=pow(h, power, p)
+ if 1<h<p-1 and g>1:
+ break
+ obj.g=g
+ if progress_func:
+ progress_func('x,y\n')
+ while (1):
+ x=bytes_to_long(randfunc(20))
+ if 0 < x < obj.q:
+ break
+ obj.x, obj.y = x, pow(g, x, p)
+ return obj
+
+class DSAobj:
+ pass
+
diff --git a/frozen_deps/Crypto/PublicKey/_RSA.py b/frozen_deps/Crypto/PublicKey/_RSA.py
new file mode 100644
index 0000000..601ab7c
--- /dev/null
+++ b/frozen_deps/Crypto/PublicKey/_RSA.py
@@ -0,0 +1,81 @@
+#
+# RSA.py : RSA encryption/decryption
+#
+# Part of the Python Cryptography Toolkit
+#
+# Written by Andrew Kuchling, Paul Swartz, and others
+#
+# ===================================================================
+# The contents of this file are dedicated to the public domain. To
+# the extent that dedication to the public domain is not available,
+# everyone is granted a worldwide, perpetual, royalty-free,
+# non-exclusive license to exercise all rights associated with the
+# contents of this file for any purpose whatsoever.
+# No rights are reserved.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+# SOFTWARE.
+# ===================================================================
+#
+
+__revision__ = "$Id$"
+
+from Crypto.PublicKey import pubkey
+from Crypto.Util import number
+
+def generate_py(bits, randfunc, progress_func=None, e=65537):
+ """generate(bits:int, randfunc:callable, progress_func:callable, e:int)
+
+ Generate an RSA key of length 'bits', public exponent 'e'(which must be
+ odd), using 'randfunc' to get random data and 'progress_func',
+ if present, to display the progress of the key generation.
+ """
+ obj=RSAobj()
+ obj.e = int(e)
+
+ # Generate the prime factors of n
+ if progress_func:
+ progress_func('p,q\n')
+ p = q = 1
+ while number.size(p*q) < bits:
+ # Note that q might be one bit longer than p if somebody specifies an odd
+ # number of bits for the key. (Why would anyone do that? You don't get
+ # more security.)
+ p = pubkey.getStrongPrime(bits>>1, obj.e, 1e-12, randfunc)
+ q = pubkey.getStrongPrime(bits - (bits>>1), obj.e, 1e-12, randfunc)
+
+ # It's OK for p to be larger than q, but let's be
+ # kind to the function that will invert it for
+ # th calculation of u.
+ if p > q:
+ (p, q)=(q, p)
+ obj.p = p
+ obj.q = q
+
+ if progress_func:
+ progress_func('u\n')
+ obj.u = pubkey.inverse(obj.p, obj.q)
+ obj.n = obj.p*obj.q
+
+ if progress_func:
+ progress_func('d\n')
+ obj.d=pubkey.inverse(obj.e, (obj.p-1)*(obj.q-1))
+
+ assert bits <= 1+obj.size(), "Generated key is too small"
+
+ return obj
+
+class RSAobj(pubkey.pubkey):
+
+ def size(self):
+ """size() : int
+ Return the maximum number of bits that can be handled by this key.
+ """
+ return number.size(self.n) - 1
+
diff --git a/frozen_deps/Crypto/PublicKey/__init__.py b/frozen_deps/Crypto/PublicKey/__init__.py
new file mode 100644
index 0000000..503809f
--- /dev/null
+++ b/frozen_deps/Crypto/PublicKey/__init__.py
@@ -0,0 +1,41 @@
+# -*- coding: utf-8 -*-
+#
+# ===================================================================
+# The contents of this file are dedicated to the public domain. To
+# the extent that dedication to the public domain is not available,
+# everyone is granted a worldwide, perpetual, royalty-free,
+# non-exclusive license to exercise all rights associated with the
+# contents of this file for any purpose whatsoever.
+# No rights are reserved.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+# SOFTWARE.
+# ===================================================================
+
+"""Public-key encryption and signature algorithms.
+
+Public-key encryption uses two different keys, one for encryption and
+one for decryption. The encryption key can be made public, and the
+decryption key is kept private. Many public-key algorithms can also
+be used to sign messages, and some can *only* be used for signatures.
+
+======================== =============================================
+Module Description
+======================== =============================================
+Crypto.PublicKey.DSA Digital Signature Algorithm (Signature only)
+Crypto.PublicKey.ElGamal (Signing and encryption)
+Crypto.PublicKey.RSA (Signing, encryption, and blinding)
+======================== =============================================
+
+:undocumented: _DSA, _RSA, _fastmath, _slowmath, pubkey
+"""
+
+__all__ = ['RSA', 'DSA', 'ElGamal']
+__revision__ = "$Id$"
+
diff --git a/frozen_deps/Crypto/PublicKey/_fastmath.cpython-38-x86_64-linux-gnu.so b/frozen_deps/Crypto/PublicKey/_fastmath.cpython-38-x86_64-linux-gnu.so
new file mode 100755
index 0000000..f0fe708
--- /dev/null
+++ b/frozen_deps/Crypto/PublicKey/_fastmath.cpython-38-x86_64-linux-gnu.so
Binary files differ
diff --git a/frozen_deps/Crypto/PublicKey/_slowmath.py b/frozen_deps/Crypto/PublicKey/_slowmath.py
new file mode 100644
index 0000000..c87bdd2
--- /dev/null
+++ b/frozen_deps/Crypto/PublicKey/_slowmath.py
@@ -0,0 +1,187 @@
+# -*- coding: utf-8 -*-
+#
+# PubKey/RSA/_slowmath.py : Pure Python implementation of the RSA portions of _fastmath
+#
+# Written in 2008 by Dwayne C. Litzenberger <[email protected]>
+#
+# ===================================================================
+# The contents of this file are dedicated to the public domain. To
+# the extent that dedication to the public domain is not available,
+# everyone is granted a worldwide, perpetual, royalty-free,
+# non-exclusive license to exercise all rights associated with the
+# contents of this file for any purpose whatsoever.
+# No rights are reserved.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+# SOFTWARE.
+# ===================================================================
+
+"""Pure Python implementation of the RSA-related portions of Crypto.PublicKey._fastmath."""
+
+__revision__ = "$Id$"
+
+__all__ = ['rsa_construct']
+
+import sys
+
+if sys.version_info[0] == 2 and sys.version_info[1] == 1:
+ from Crypto.Util.py21compat import *
+from Crypto.Util.number import size, inverse, GCD
+
+class error(Exception):
+ pass
+
+class _RSAKey(object):
+ def _blind(self, m, r):
+ # compute r**e * m (mod n)
+ return m * pow(r, self.e, self.n)
+
+ def _unblind(self, m, r):
+ # compute m / r (mod n)
+ return inverse(r, self.n) * m % self.n
+
+ def _decrypt(self, c):
+ # compute c**d (mod n)
+ if not self.has_private():
+ raise TypeError("No private key")
+ if (hasattr(self,'p') and hasattr(self,'q') and hasattr(self,'u')):
+ m1 = pow(c, self.d % (self.p-1), self.p)
+ m2 = pow(c, self.d % (self.q-1), self.q)
+ h = m2 - m1
+ if (h<0):
+ h = h + self.q
+ h = h*self.u % self.q
+ return h*self.p+m1
+ return pow(c, self.d, self.n)
+
+ def _encrypt(self, m):
+ # compute m**d (mod n)
+ return pow(m, self.e, self.n)
+
+ def _sign(self, m): # alias for _decrypt
+ if not self.has_private():
+ raise TypeError("No private key")
+ return self._decrypt(m)
+
+ def _verify(self, m, sig):
+ return self._encrypt(sig) == m
+
+ def has_private(self):
+ return hasattr(self, 'd')
+
+ def size(self):
+ """Return the maximum number of bits that can be encrypted"""
+ return size(self.n) - 1
+
+def rsa_construct(n, e, d=None, p=None, q=None, u=None):
+ """Construct an RSAKey object"""
+ assert isinstance(n, int)
+ assert isinstance(e, int)
+ assert isinstance(d, (int, type(None)))
+ assert isinstance(p, (int, type(None)))
+ assert isinstance(q, (int, type(None)))
+ assert isinstance(u, (int, type(None)))
+ obj = _RSAKey()
+ obj.n = n
+ obj.e = e
+ if d is None:
+ return obj
+ obj.d = d
+ if p is not None and q is not None:
+ obj.p = p
+ obj.q = q
+ else:
+ # Compute factors p and q from the private exponent d.
+ # We assume that n has no more than two factors.
+ # See 8.2.2(i) in Handbook of Applied Cryptography.
+ ktot = d*e-1
+ # The quantity d*e-1 is a multiple of phi(n), even,
+ # and can be represented as t*2^s.
+ t = ktot
+ while t%2==0:
+ t=divmod(t,2)[0]
+ # Cycle through all multiplicative inverses in Zn.
+ # The algorithm is non-deterministic, but there is a 50% chance
+ # any candidate a leads to successful factoring.
+ # See "Digitalized Signatures and Public Key Functions as Intractable
+ # as Factorization", M. Rabin, 1979
+ spotted = 0
+ a = 2
+ while not spotted and a<100:
+ k = t
+ # Cycle through all values a^{t*2^i}=a^k
+ while k<ktot:
+ cand = pow(a,k,n)
+ # Check if a^k is a non-trivial root of unity (mod n)
+ if cand!=1 and cand!=(n-1) and pow(cand,2,n)==1:
+ # We have found a number such that (cand-1)(cand+1)=0 (mod n).
+ # Either of the terms divides n.
+ obj.p = GCD(cand+1,n)
+ spotted = 1
+ break
+ k = k*2
+ # This value was not any good... let's try another!
+ a = a+2
+ if not spotted:
+ raise ValueError("Unable to compute factors p and q from exponent d.")
+ # Found !
+ assert ((n % obj.p)==0)
+ obj.q = divmod(n,obj.p)[0]
+ if u is not None:
+ obj.u = u
+ else:
+ obj.u = inverse(obj.p, obj.q)
+ return obj
+
+class _DSAKey(object):
+ def size(self):
+ """Return the maximum number of bits that can be encrypted"""
+ return size(self.p) - 1
+
+ def has_private(self):
+ return hasattr(self, 'x')
+
+ def _sign(self, m, k): # alias for _decrypt
+ # SECURITY TODO - We _should_ be computing SHA1(m), but we don't because that's the API.
+ if not self.has_private():
+ raise TypeError("No private key")
+ if not (1 < k < self.q):
+ raise ValueError("k is not between 2 and q-1")
+ inv_k = inverse(k, self.q) # Compute k**-1 mod q
+ r = pow(self.g, k, self.p) % self.q # r = (g**k mod p) mod q
+ s = (inv_k * (m + self.x * r)) % self.q
+ return (r, s)
+
+ def _verify(self, m, r, s):
+ # SECURITY TODO - We _should_ be computing SHA1(m), but we don't because that's the API.
+ if not (0 < r < self.q) or not (0 < s < self.q):
+ return False
+ w = inverse(s, self.q)
+ u1 = (m*w) % self.q
+ u2 = (r*w) % self.q
+ v = (pow(self.g, u1, self.p) * pow(self.y, u2, self.p) % self.p) % self.q
+ return v == r
+
+def dsa_construct(y, g, p, q, x=None):
+ assert isinstance(y, int)
+ assert isinstance(g, int)
+ assert isinstance(p, int)
+ assert isinstance(q, int)
+ assert isinstance(x, (int, type(None)))
+ obj = _DSAKey()
+ obj.y = y
+ obj.g = g
+ obj.p = p
+ obj.q = q
+ if x is not None: obj.x = x
+ return obj
+
+
+# vim:set ts=4 sw=4 sts=4 expandtab:
+
diff --git a/frozen_deps/Crypto/PublicKey/pubkey.py b/frozen_deps/Crypto/PublicKey/pubkey.py
new file mode 100644
index 0000000..e46b076
--- /dev/null
+++ b/frozen_deps/Crypto/PublicKey/pubkey.py
@@ -0,0 +1,240 @@
+#
+# pubkey.py : Internal functions for public key operations
+#
+# Part of the Python Cryptography Toolkit
+#
+# Written by Andrew Kuchling, Paul Swartz, and others
+#
+# ===================================================================
+# The contents of this file are dedicated to the public domain. To
+# the extent that dedication to the public domain is not available,
+# everyone is granted a worldwide, perpetual, royalty-free,
+# non-exclusive license to exercise all rights associated with the
+# contents of this file for any purpose whatsoever.
+# No rights are reserved.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+# SOFTWARE.
+# ===================================================================
+#
+
+__revision__ = "$Id$"
+
+import types, warnings
+from Crypto.Util.number import *
+
+# Basic public key class
+class pubkey:
+ """An abstract class for a public key object.
+
+ :undocumented: __getstate__, __setstate__, __eq__, __ne__, validate
+ """
+ def __init__(self):
+ pass
+
+ def __getstate__(self):
+ """To keep key objects platform-independent, the key data is
+ converted to standard Python long integers before being
+ written out. It will then be reconverted as necessary on
+ restoration."""
+ d=self.__dict__
+ for key in self.keydata:
+ if key in d: d[key]=int(d[key])
+ return d
+
+ def __setstate__(self, d):
+ """On unpickling a key object, the key data is converted to the big
+number representation being used, whether that is Python long
+integers, MPZ objects, or whatever."""
+ for key in self.keydata:
+ if key in d: self.__dict__[key]=bignum(d[key])
+
+ def encrypt(self, plaintext, K):
+ """Encrypt a piece of data.
+
+ :Parameter plaintext: The piece of data to encrypt.
+ :Type plaintext: byte string or long
+
+ :Parameter K: A random parameter required by some algorithms
+ :Type K: byte string or long
+
+ :Return: A tuple with two items. Each item is of the same type as the
+ plaintext (string or long).
+ """
+ wasString=0
+ if isinstance(plaintext, bytes):
+ plaintext=bytes_to_long(plaintext) ; wasString=1
+ if isinstance(K, bytes):
+ K=bytes_to_long(K)
+ ciphertext=self._encrypt(plaintext, K)
+ if wasString: return tuple(map(long_to_bytes, ciphertext))
+ else: return ciphertext
+
+ def decrypt(self, ciphertext):
+ """Decrypt a piece of data.
+
+ :Parameter ciphertext: The piece of data to decrypt.
+ :Type ciphertext: byte string, long or a 2-item tuple as returned by `encrypt`
+
+ :Return: A byte string if ciphertext was a byte string or a tuple
+ of byte strings. A long otherwise.
+ """
+ wasString=0
+ if not isinstance(ciphertext, tuple):
+ ciphertext=(ciphertext,)
+ if isinstance(ciphertext[0], bytes):
+ ciphertext=tuple(map(bytes_to_long, ciphertext)) ; wasString=1
+ plaintext=self._decrypt(ciphertext)
+ if wasString: return long_to_bytes(plaintext)
+ else: return plaintext
+
+ def sign(self, M, K):
+ """Sign a piece of data.
+
+ :Parameter M: The piece of data to encrypt.
+ :Type M: byte string or long
+
+ :Parameter K: A random parameter required by some algorithms
+ :Type K: byte string or long
+
+ :Return: A tuple with two items.
+ """
+ if (not self.has_private()):
+ raise TypeError('Private key not available in this object')
+ if isinstance(M, bytes): M=bytes_to_long(M)
+ if isinstance(K, bytes): K=bytes_to_long(K)
+ return self._sign(M, K)
+
+ def verify (self, M, signature):
+ """Verify the validity of a signature.
+
+ :Parameter M: The expected message.
+ :Type M: byte string or long
+
+ :Parameter signature: The signature to verify.
+ :Type signature: tuple with two items, as return by `sign`
+
+ :Return: True if the signature is correct, False otherwise.
+ """
+ if isinstance(M, bytes): M=bytes_to_long(M)
+ return self._verify(M, signature)
+
+ # alias to compensate for the old validate() name
+ def validate (self, M, signature):
+ warnings.warn("validate() method name is obsolete; use verify()",
+ DeprecationWarning)
+
+ def blind(self, M, B):
+ """Blind a message to prevent certain side-channel attacks.
+
+ :Parameter M: The message to blind.
+ :Type M: byte string or long
+
+ :Parameter B: Blinding factor.
+ :Type B: byte string or long
+
+ :Return: A byte string if M was so. A long otherwise.
+ """
+ wasString=0
+ if isinstance(M, bytes):
+ M=bytes_to_long(M) ; wasString=1
+ if isinstance(B, bytes): B=bytes_to_long(B)
+ blindedmessage=self._blind(M, B)
+ if wasString: return long_to_bytes(blindedmessage)
+ else: return blindedmessage
+
+ def unblind(self, M, B):
+ """Unblind a message after cryptographic processing.
+
+ :Parameter M: The encoded message to unblind.
+ :Type M: byte string or long
+
+ :Parameter B: Blinding factor.
+ :Type B: byte string or long
+ """
+ wasString=0
+ if isinstance(M, bytes):
+ M=bytes_to_long(M) ; wasString=1
+ if isinstance(B, bytes): B=bytes_to_long(B)
+ unblindedmessage=self._unblind(M, B)
+ if wasString: return long_to_bytes(unblindedmessage)
+ else: return unblindedmessage
+
+
+ # The following methods will usually be left alone, except for
+ # signature-only algorithms. They both return Boolean values
+ # recording whether this key's algorithm can sign and encrypt.
+ def can_sign (self):
+ """Tell if the algorithm can deal with cryptographic signatures.
+
+ This property concerns the *algorithm*, not the key itself.
+ It may happen that this particular key object hasn't got
+ the private information required to generate a signature.
+
+ :Return: boolean
+ """
+ return 1
+
+ def can_encrypt (self):
+ """Tell if the algorithm can deal with data encryption.
+
+ This property concerns the *algorithm*, not the key itself.
+ It may happen that this particular key object hasn't got
+ the private information required to decrypt data.
+
+ :Return: boolean
+ """
+ return 1
+
+ def can_blind (self):
+ """Tell if the algorithm can deal with data blinding.
+
+ This property concerns the *algorithm*, not the key itself.
+ It may happen that this particular key object hasn't got
+ the private information required carry out blinding.
+
+ :Return: boolean
+ """
+ return 0
+
+ # The following methods will certainly be overridden by
+ # subclasses.
+
+ def size (self):
+ """Tell the maximum number of bits that can be handled by this key.
+
+ :Return: int
+ """
+ return 0
+
+ def has_private (self):
+ """Tell if the key object contains private components.
+
+ :Return: bool
+ """
+ return 0
+
+ def publickey (self):
+ """Construct a new key carrying only the public information.
+
+ :Return: A new `pubkey` object.
+ """
+ return self
+
+ def __eq__ (self, other):
+ """__eq__(other): 0, 1
+ Compare us to other for equality.
+ """
+ return self.__getstate__() == other.__getstate__()
+
+ def __ne__ (self, other):
+ """__ne__(other): 0, 1
+ Compare us to other for inequality.
+ """
+ return not self.__eq__(other)
diff --git a/frozen_deps/Crypto/Random/Fortuna/FortunaAccumulator.py b/frozen_deps/Crypto/Random/Fortuna/FortunaAccumulator.py
new file mode 100644
index 0000000..5c6beb0
--- /dev/null
+++ b/frozen_deps/Crypto/Random/Fortuna/FortunaAccumulator.py
@@ -0,0 +1,171 @@
+# -*- coding: ascii -*-
+#
+# FortunaAccumulator.py : Fortuna's internal accumulator
+#
+# Written in 2008 by Dwayne C. Litzenberger <[email protected]>
+#
+# ===================================================================
+# The contents of this file are dedicated to the public domain. To
+# the extent that dedication to the public domain is not available,
+# everyone is granted a worldwide, perpetual, royalty-free,
+# non-exclusive license to exercise all rights associated with the
+# contents of this file for any purpose whatsoever.
+# No rights are reserved.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+# SOFTWARE.
+# ===================================================================
+
+__revision__ = "$Id$"
+
+import sys
+if sys.version_info[0] == 2 and sys.version_info[1] == 1:
+ from Crypto.Util.py21compat import *
+from Crypto.Util.py3compat import *
+
+from binascii import b2a_hex
+import time
+import warnings
+
+from Crypto.pct_warnings import ClockRewindWarning
+from . import SHAd256
+
+from . import FortunaGenerator
+
+class FortunaPool(object):
+ """Fortuna pool type
+
+ This object acts like a hash object, with the following differences:
+
+ - It keeps a count (the .length attribute) of the number of bytes that
+ have been added to the pool
+ - It supports a .reset() method for in-place reinitialization
+ - The method to add bytes to the pool is .append(), not .update().
+ """
+
+ digest_size = SHAd256.digest_size
+
+ def __init__(self):
+ self.reset()
+
+ def append(self, data):
+ self._h.update(data)
+ self.length += len(data)
+
+ def digest(self):
+ return self._h.digest()
+
+ def hexdigest(self):
+ if sys.version_info[0] == 2:
+ return b2a_hex(self.digest())
+ else:
+ return b2a_hex(self.digest()).decode()
+
+ def reset(self):
+ self._h = SHAd256.new()
+ self.length = 0
+
+def which_pools(r):
+ """Return a list of pools indexes (in range(32)) that are to be included during reseed number r.
+
+ According to _Practical Cryptography_, chapter 10.5.2 "Pools":
+
+ "Pool P_i is included if 2**i is a divisor of r. Thus P_0 is used
+ every reseed, P_1 every other reseed, P_2 every fourth reseed, etc."
+ """
+ # This is a separate function so that it can be unit-tested.
+ assert r >= 1
+ retval = []
+ mask = 0
+ for i in range(32):
+ # "Pool P_i is included if 2**i is a divisor of [reseed_count]"
+ if (r & mask) == 0:
+ retval.append(i)
+ else:
+ break # optimization. once this fails, it always fails
+ mask = (mask << 1) | 1
+ return retval
+
+class FortunaAccumulator(object):
+
+ # An estimate of how many bytes we must append to pool 0 before it will
+ # contain 128 bits of entropy (with respect to an attack). We reseed the
+ # generator only after pool 0 contains `min_pool_size` bytes. Note that
+ # unlike with some other PRNGs, Fortuna's security does not rely on the
+ # accuracy of this estimate---we can accord to be optimistic here.
+ min_pool_size = 64 # size in bytes
+
+ # If an attacker can predict some (but not all) of our entropy sources, the
+ # `min_pool_size` check may not be sufficient to prevent a successful state
+ # compromise extension attack. To resist this attack, Fortuna spreads the
+ # input across 32 pools, which are then consumed (to reseed the output
+ # generator) with exponentially decreasing frequency.
+ #
+ # In order to prevent an attacker from gaining knowledge of all 32 pools
+ # before we have a chance to fill them with enough information that the
+ # attacker cannot predict, we impose a rate limit of 10 reseeds/second (one
+ # per 100 ms). This ensures that a hypothetical 33rd pool would only be
+ # needed after a minimum of 13 years of sustained attack.
+ reseed_interval = 0.100 # time in seconds
+
+ def __init__(self):
+ self.reseed_count = 0
+ self.generator = FortunaGenerator.AESGenerator()
+ self.last_reseed = None
+
+ # Initialize 32 FortunaPool instances.
+ # NB: This is _not_ equivalent to [FortunaPool()]*32, which would give
+ # us 32 references to the _same_ FortunaPool instance (and cause the
+ # assertion below to fail).
+ self.pools = [FortunaPool() for i in range(32)] # 32 pools
+ assert(self.pools[0] is not self.pools[1])
+
+ def _forget_last_reseed(self):
+ # This is not part of the standard Fortuna definition, and using this
+ # function frequently can weaken Fortuna's ability to resist a state
+ # compromise extension attack, but we need this in order to properly
+ # implement Crypto.Random.atfork(). Otherwise, forked child processes
+ # might continue to use their parent's PRNG state for up to 100ms in
+ # some cases. (e.g. CVE-2013-1445)
+ self.last_reseed = None
+
+ def random_data(self, bytes):
+ current_time = time.time()
+ if (self.last_reseed is not None and self.last_reseed > current_time): # Avoid float comparison to None to make Py3k happy
+ warnings.warn("Clock rewind detected. Resetting last_reseed.", ClockRewindWarning)
+ self.last_reseed = None
+ if (self.pools[0].length >= self.min_pool_size and
+ (self.last_reseed is None or
+ current_time > self.last_reseed + self.reseed_interval)):
+ self._reseed(current_time)
+ # The following should fail if we haven't seeded the pool yet.
+ return self.generator.pseudo_random_data(bytes)
+
+ def _reseed(self, current_time=None):
+ if current_time is None:
+ current_time = time.time()
+ seed = []
+ self.reseed_count += 1
+ self.last_reseed = current_time
+ for i in which_pools(self.reseed_count):
+ seed.append(self.pools[i].digest())
+ self.pools[i].reset()
+
+ seed = b("").join(seed)
+ self.generator.reseed(seed)
+
+ def add_random_event(self, source_number, pool_number, data):
+ assert 1 <= len(data) <= 32
+ assert 0 <= source_number <= 255
+ assert 0 <= pool_number <= 31
+ self.pools[pool_number].append(bchr(source_number))
+ self.pools[pool_number].append(bchr(len(data)))
+ self.pools[pool_number].append(data)
+
+# vim:set ts=4 sw=4 sts=4 expandtab:
diff --git a/frozen_deps/Crypto/Random/Fortuna/FortunaGenerator.py b/frozen_deps/Crypto/Random/Fortuna/FortunaGenerator.py
new file mode 100644
index 0000000..489c81e
--- /dev/null
+++ b/frozen_deps/Crypto/Random/Fortuna/FortunaGenerator.py
@@ -0,0 +1,132 @@
+# -*- coding: ascii -*-
+#
+# FortunaGenerator.py : Fortuna's internal PRNG
+#
+# Written in 2008 by Dwayne C. Litzenberger <[email protected]>
+#
+# ===================================================================
+# The contents of this file are dedicated to the public domain. To
+# the extent that dedication to the public domain is not available,
+# everyone is granted a worldwide, perpetual, royalty-free,
+# non-exclusive license to exercise all rights associated with the
+# contents of this file for any purpose whatsoever.
+# No rights are reserved.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+# SOFTWARE.
+# ===================================================================
+
+__revision__ = "$Id$"
+
+import sys
+if sys.version_info[0] is 2 and sys.version_info[1] is 1:
+ from Crypto.Util.py21compat import *
+from Crypto.Util.py3compat import *
+
+import struct
+
+from Crypto.Util.number import ceil_shift, exact_log2, exact_div
+from Crypto.Util import Counter
+from Crypto.Cipher import AES
+
+from . import SHAd256
+
+class AESGenerator(object):
+ """The Fortuna "generator"
+
+ This is used internally by the Fortuna PRNG to generate arbitrary amounts
+ of pseudorandom data from a smaller amount of seed data.
+
+ The output is generated by running AES-256 in counter mode and re-keying
+ after every mebibyte (2**16 blocks) of output.
+ """
+
+ block_size = AES.block_size # output block size in octets (128 bits)
+ key_size = 32 # key size in octets (256 bits)
+
+ # Because of the birthday paradox, we expect to find approximately one
+ # collision for every 2**64 blocks of output from a real random source.
+ # However, this code generates pseudorandom data by running AES in
+ # counter mode, so there will be no collisions until the counter
+ # (theoretically) wraps around at 2**128 blocks. Thus, in order to prevent
+ # Fortuna's pseudorandom output from deviating perceptibly from a true
+ # random source, Ferguson and Schneier specify a limit of 2**16 blocks
+ # without rekeying.
+ max_blocks_per_request = 2**16 # Allow no more than this number of blocks per _pseudo_random_data request
+
+ _four_kiblocks_of_zeros = b("\0") * block_size * 4096
+
+ def __init__(self):
+ self.counter = Counter.new(nbits=self.block_size*8, initial_value=0, little_endian=True)
+ self.key = None
+
+ # Set some helper constants
+ self.block_size_shift = exact_log2(self.block_size)
+ assert (1 << self.block_size_shift) == self.block_size
+
+ self.blocks_per_key = exact_div(self.key_size, self.block_size)
+ assert self.key_size == self.blocks_per_key * self.block_size
+
+ self.max_bytes_per_request = self.max_blocks_per_request * self.block_size
+
+ def reseed(self, seed):
+ if self.key is None:
+ self.key = b("\0") * self.key_size
+
+ self._set_key(SHAd256.new(self.key + seed).digest())
+ self.counter() # increment counter
+ assert len(self.key) == self.key_size
+
+ def pseudo_random_data(self, bytes):
+ assert bytes >= 0
+
+ num_full_blocks = bytes >> 20
+ remainder = bytes & ((1<<20)-1)
+
+ retval = []
+ for i in range(num_full_blocks):
+ retval.append(self._pseudo_random_data(1<<20))
+ retval.append(self._pseudo_random_data(remainder))
+
+ return b("").join(retval)
+
+ def _set_key(self, key):
+ self.key = key
+ self._cipher = AES.new(key, AES.MODE_CTR, counter=self.counter)
+
+ def _pseudo_random_data(self, bytes):
+ if not (0 <= bytes <= self.max_bytes_per_request):
+ raise AssertionError("You cannot ask for more than 1 MiB of data per request")
+
+ num_blocks = ceil_shift(bytes, self.block_size_shift) # num_blocks = ceil(bytes / self.block_size)
+
+ # Compute the output
+ retval = self._generate_blocks(num_blocks)[:bytes]
+
+ # Switch to a new key to avoid later compromises of this output (i.e.
+ # state compromise extension attacks)
+ self._set_key(self._generate_blocks(self.blocks_per_key))
+
+ assert len(retval) == bytes
+ assert len(self.key) == self.key_size
+
+ return retval
+
+ def _generate_blocks(self, num_blocks):
+ if self.key is None:
+ raise AssertionError("generator must be seeded before use")
+ assert 0 <= num_blocks <= self.max_blocks_per_request
+ retval = []
+ for i in range(num_blocks >> 12): # xrange(num_blocks / 4096)
+ retval.append(self._cipher.encrypt(self._four_kiblocks_of_zeros))
+ remaining_bytes = (num_blocks & 4095) << self.block_size_shift # (num_blocks % 4095) * self.block_size
+ retval.append(self._cipher.encrypt(self._four_kiblocks_of_zeros[:remaining_bytes]))
+ return b("").join(retval)
+
+# vim:set ts=4 sw=4 sts=4 expandtab:
diff --git a/frozen_deps/Crypto/Random/Fortuna/SHAd256.py b/frozen_deps/Crypto/Random/Fortuna/SHAd256.py
new file mode 100644
index 0000000..2e135c9
--- /dev/null
+++ b/frozen_deps/Crypto/Random/Fortuna/SHAd256.py
@@ -0,0 +1,98 @@
+# -*- coding: ascii -*-
+#
+# Random/Fortuna/SHAd256.py : SHA_d-256 hash function implementation
+#
+# Written in 2008 by Dwayne C. Litzenberger <[email protected]>
+#
+# ===================================================================
+# The contents of this file are dedicated to the public domain. To
+# the extent that dedication to the public domain is not available,
+# everyone is granted a worldwide, perpetual, royalty-free,
+# non-exclusive license to exercise all rights associated with the
+# contents of this file for any purpose whatsoever.
+# No rights are reserved.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+# SOFTWARE.
+# ===================================================================
+
+"""\
+SHA_d-256 hash function implementation.
+
+This module should comply with PEP 247.
+"""
+
+__revision__ = "$Id$"
+__all__ = ['new', 'digest_size']
+
+import sys
+if sys.version_info[0] == 2 and sys.version_info[1] == 1:
+ from Crypto.Util.py21compat import *
+from Crypto.Util.py3compat import *
+
+from binascii import b2a_hex
+
+from Crypto.Hash import SHA256
+
+assert SHA256.digest_size == 32
+
+class _SHAd256(object):
+ """SHA-256, doubled.
+
+ Returns SHA-256(SHA-256(data)).
+ """
+
+ digest_size = SHA256.digest_size
+
+ _internal = object()
+
+ def __init__(self, internal_api_check, sha256_hash_obj):
+ if internal_api_check is not self._internal:
+ raise AssertionError("Do not instantiate this class directly. Use %s.new()" % (__name__,))
+ self._h = sha256_hash_obj
+
+ # PEP 247 "copy" method
+ def copy(self):
+ """Return a copy of this hashing object"""
+ return _SHAd256(SHAd256._internal, self._h.copy())
+
+ # PEP 247 "digest" method
+ def digest(self):
+ """Return the hash value of this object as a binary string"""
+ retval = SHA256.new(self._h.digest()).digest()
+ assert len(retval) == 32
+ return retval
+
+ # PEP 247 "hexdigest" method
+ def hexdigest(self):
+ """Return the hash value of this object as a (lowercase) hexadecimal string"""
+ retval = b2a_hex(self.digest())
+ assert len(retval) == 64
+ if sys.version_info[0] == 2:
+ return retval
+ else:
+ return retval.decode()
+
+ # PEP 247 "update" method
+ def update(self, data):
+ self._h.update(data)
+
+# PEP 247 module-level "digest_size" variable
+digest_size = _SHAd256.digest_size
+
+# PEP 247 module-level "new" function
+def new(data=None):
+ """Return a new SHAd256 hashing object"""
+ if not data:
+ data=b("")
+ sha = _SHAd256(_SHAd256._internal, SHA256.new(data))
+ sha.new = globals()['new']
+ return sha
+
+# vim:set ts=4 sw=4 sts=4 expandtab:
diff --git a/frozen_deps/Crypto/Random/Fortuna/__init__.py b/frozen_deps/Crypto/Random/Fortuna/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/frozen_deps/Crypto/Random/Fortuna/__init__.py
diff --git a/frozen_deps/Crypto/Random/OSRNG/__init__.py b/frozen_deps/Crypto/Random/OSRNG/__init__.py
new file mode 100644
index 0000000..2fbbecb
--- /dev/null
+++ b/frozen_deps/Crypto/Random/OSRNG/__init__.py
@@ -0,0 +1,40 @@
+#
+# Random/OSRNG/__init__.py : Platform-independent OS RNG API
+#
+# Written in 2008 by Dwayne C. Litzenberger <[email protected]>
+#
+# ===================================================================
+# The contents of this file are dedicated to the public domain. To
+# the extent that dedication to the public domain is not available,
+# everyone is granted a worldwide, perpetual, royalty-free,
+# non-exclusive license to exercise all rights associated with the
+# contents of this file for any purpose whatsoever.
+# No rights are reserved.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+# SOFTWARE.
+# ===================================================================
+
+"""Provides a platform-independent interface to the random number generators
+supplied by various operating systems."""
+
+__revision__ = "$Id$"
+
+import os
+
+if os.name == 'posix':
+ from Crypto.Random.OSRNG.posix import new
+elif os.name == 'nt':
+ from Crypto.Random.OSRNG.nt import new
+elif hasattr(os, 'urandom'):
+ from Crypto.Random.OSRNG.fallback import new
+else:
+ raise ImportError("Not implemented")
+
+# vim:set ts=4 sw=4 sts=4 expandtab:
diff --git a/frozen_deps/Crypto/Random/OSRNG/fallback.py b/frozen_deps/Crypto/Random/OSRNG/fallback.py
new file mode 100644
index 0000000..6d4130d
--- /dev/null
+++ b/frozen_deps/Crypto/Random/OSRNG/fallback.py
@@ -0,0 +1,46 @@
+#
+# Random/OSRNG/fallback.py : Fallback entropy source for systems with os.urandom
+#
+# Written in 2008 by Dwayne C. Litzenberger <[email protected]>
+#
+# ===================================================================
+# The contents of this file are dedicated to the public domain. To
+# the extent that dedication to the public domain is not available,
+# everyone is granted a worldwide, perpetual, royalty-free,
+# non-exclusive license to exercise all rights associated with the
+# contents of this file for any purpose whatsoever.
+# No rights are reserved.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+# SOFTWARE.
+# ===================================================================
+
+
+__revision__ = "$Id$"
+__all__ = ['PythonOSURandomRNG']
+
+import os
+
+from .rng_base import BaseRNG
+
+class PythonOSURandomRNG(BaseRNG):
+
+ name = "<os.urandom>"
+
+ def __init__(self):
+ self._read = os.urandom
+ BaseRNG.__init__(self)
+
+ def _close(self):
+ self._read = None
+
+def new(*args, **kwargs):
+ return PythonOSURandomRNG(*args, **kwargs)
+
+# vim:set ts=4 sw=4 sts=4 expandtab:
diff --git a/frozen_deps/Crypto/Random/OSRNG/posix.py b/frozen_deps/Crypto/Random/OSRNG/posix.py
new file mode 100644
index 0000000..ceea7b7
--- /dev/null
+++ b/frozen_deps/Crypto/Random/OSRNG/posix.py
@@ -0,0 +1,86 @@
+#
+# Random/OSRNG/posix.py : OS entropy source for POSIX systems
+#
+# Written in 2008 by Dwayne C. Litzenberger <[email protected]>
+#
+# ===================================================================
+# The contents of this file are dedicated to the public domain. To
+# the extent that dedication to the public domain is not available,
+# everyone is granted a worldwide, perpetual, royalty-free,
+# non-exclusive license to exercise all rights associated with the
+# contents of this file for any purpose whatsoever.
+# No rights are reserved.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+# SOFTWARE.
+# ===================================================================
+
+
+__revision__ = "$Id$"
+__all__ = ['DevURandomRNG']
+
+import errno
+import os
+import stat
+
+from .rng_base import BaseRNG
+from Crypto.Util.py3compat import b
+
+class DevURandomRNG(BaseRNG):
+
+ def __init__(self, devname=None):
+ if devname is None:
+ self.name = "/dev/urandom"
+ else:
+ self.name = devname
+
+ # Test that /dev/urandom is a character special device
+ f = open(self.name, "rb", 0)
+ fmode = os.fstat(f.fileno())[stat.ST_MODE]
+ if not stat.S_ISCHR(fmode):
+ f.close()
+ raise TypeError("%r is not a character special device" % (self.name,))
+
+ self.__file = f
+
+ BaseRNG.__init__(self)
+
+ def _close(self):
+ self.__file.close()
+
+ def _read(self, N):
+ # Starting with Python 3 open with buffering=0 returns a FileIO object.
+ # FileIO.read behaves like read(2) and not like fread(3) and thus we
+ # have to handle the case that read returns less data as requested here
+ # more carefully.
+ data = b("")
+ while len(data) < N:
+ try:
+ d = self.__file.read(N - len(data))
+ except IOError as e:
+ # read(2) has been interrupted by a signal; redo the read
+ if e.errno == errno.EINTR:
+ continue
+ raise
+
+ if d is None:
+ # __file is in non-blocking mode and no data is available
+ return data
+ if len(d) == 0:
+ # __file is in blocking mode and arrived at EOF
+ return data
+
+ data += d
+ return data
+
+def new(*args, **kwargs):
+ return DevURandomRNG(*args, **kwargs)
+
+
+# vim:set ts=4 sw=4 sts=4 expandtab:
diff --git a/frozen_deps/Crypto/Random/OSRNG/rng_base.py b/frozen_deps/Crypto/Random/OSRNG/rng_base.py
new file mode 100644
index 0000000..546f2e9
--- /dev/null
+++ b/frozen_deps/Crypto/Random/OSRNG/rng_base.py
@@ -0,0 +1,88 @@
+#
+# Random/OSRNG/rng_base.py : Base class for OSRNG
+#
+# Written in 2008 by Dwayne C. Litzenberger <[email protected]>
+#
+# ===================================================================
+# The contents of this file are dedicated to the public domain. To
+# the extent that dedication to the public domain is not available,
+# everyone is granted a worldwide, perpetual, royalty-free,
+# non-exclusive license to exercise all rights associated with the
+# contents of this file for any purpose whatsoever.
+# No rights are reserved.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+# SOFTWARE.
+# ===================================================================
+
+__revision__ = "$Id$"
+
+import sys
+if sys.version_info[0] == 2 and sys.version_info[1] == 1:
+ from Crypto.Util.py21compat import *
+
+class BaseRNG(object):
+
+ def __init__(self):
+ self.closed = False
+ self._selftest()
+
+ def __del__(self):
+ self.close()
+
+ def _selftest(self):
+ # Test that urandom can return data
+ data = self.read(16)
+ if len(data) != 16:
+ raise AssertionError("read truncated")
+
+ # Test that we get different data every time (if we don't, the RNG is
+ # probably malfunctioning)
+ data2 = self.read(16)
+ if data == data2:
+ raise AssertionError("OS RNG returned duplicate data")
+
+ # PEP 343: Support for the "with" statement
+ def __enter__(self):
+ pass
+ def __exit__(self):
+ """PEP 343 support"""
+ self.close()
+
+ def close(self):
+ if not self.closed:
+ self._close()
+ self.closed = True
+
+ def flush(self):
+ pass
+
+ def read(self, N=-1):
+ """Return N bytes from the RNG."""
+ if self.closed:
+ raise ValueError("I/O operation on closed file")
+ if not isinstance(N, int):
+ raise TypeError("an integer is required")
+ if N < 0:
+ raise ValueError("cannot read to end of infinite stream")
+ elif N == 0:
+ return ""
+ data = self._read(N)
+ if len(data) != N:
+ raise AssertionError("%s produced truncated output (requested %d, got %d)" % (self.name, N, len(data)))
+ return data
+
+ def _close(self):
+ raise NotImplementedError("child class must implement this")
+
+ def _read(self, N):
+ raise NotImplementedError("child class must implement this")
+
+
+# vim:set ts=4 sw=4 sts=4 expandtab:
diff --git a/frozen_deps/Crypto/Random/_UserFriendlyRNG.py b/frozen_deps/Crypto/Random/_UserFriendlyRNG.py
new file mode 100644
index 0000000..937c17d
--- /dev/null
+++ b/frozen_deps/Crypto/Random/_UserFriendlyRNG.py
@@ -0,0 +1,230 @@
+# -*- coding: utf-8 -*-
+#
+# Random/_UserFriendlyRNG.py : A user-friendly random number generator
+#
+# Written in 2008 by Dwayne C. Litzenberger <[email protected]>
+#
+# ===================================================================
+# The contents of this file are dedicated to the public domain. To
+# the extent that dedication to the public domain is not available,
+# everyone is granted a worldwide, perpetual, royalty-free,
+# non-exclusive license to exercise all rights associated with the
+# contents of this file for any purpose whatsoever.
+# No rights are reserved.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+# SOFTWARE.
+# ===================================================================
+
+__revision__ = "$Id$"
+
+import sys
+if sys.version_info[0] == 2 and sys.version_info[1] == 1:
+ from Crypto.Util.py21compat import *
+
+import os
+import threading
+import struct
+import time
+from math import floor
+
+from Crypto.Random import OSRNG
+from Crypto.Random.Fortuna import FortunaAccumulator
+
+class _EntropySource(object):
+ def __init__(self, accumulator, src_num):
+ self._fortuna = accumulator
+ self._src_num = src_num
+ self._pool_num = 0
+
+ def feed(self, data):
+ self._fortuna.add_random_event(self._src_num, self._pool_num, data)
+ self._pool_num = (self._pool_num + 1) & 31
+
+class _EntropyCollector(object):
+
+ def __init__(self, accumulator):
+ self._osrng = OSRNG.new()
+ self._osrng_es = _EntropySource(accumulator, 255)
+ self._time_es = _EntropySource(accumulator, 254)
+ self._clock_es = _EntropySource(accumulator, 253)
+
+ def reinit(self):
+ # Add 256 bits to each of the 32 pools, twice. (For a total of 16384
+ # bits collected from the operating system.)
+ for i in range(2):
+ block = self._osrng.read(32*32)
+ for p in range(32):
+ self._osrng_es.feed(block[p*32:(p+1)*32])
+ block = None
+ self._osrng.flush()
+
+ def collect(self):
+ # Collect 64 bits of entropy from the operating system and feed it to Fortuna.
+ self._osrng_es.feed(self._osrng.read(8))
+
+ # Add the fractional part of time.time()
+ t = time.time()
+ self._time_es.feed(struct.pack("@I", int(2**30 * (t - floor(t)))))
+
+ # Add the fractional part of time.clock()
+ t = time.clock()
+ self._clock_es.feed(struct.pack("@I", int(2**30 * (t - floor(t)))))
+
+
+class _UserFriendlyRNG(object):
+
+ def __init__(self):
+ self.closed = False
+ self._fa = FortunaAccumulator.FortunaAccumulator()
+ self._ec = _EntropyCollector(self._fa)
+ self.reinit()
+
+ def reinit(self):
+ """Initialize the random number generator and seed it with entropy from
+ the operating system.
+ """
+
+ # Save the pid (helps ensure that Crypto.Random.atfork() gets called)
+ self._pid = os.getpid()
+
+ # Collect entropy from the operating system and feed it to
+ # FortunaAccumulator
+ self._ec.reinit()
+
+ # Override FortunaAccumulator's 100ms minimum re-seed interval. This
+ # is necessary to avoid a race condition between this function and
+ # self.read(), which that can otherwise cause forked child processes to
+ # produce identical output. (e.g. CVE-2013-1445)
+ #
+ # Note that if this function can be called frequently by an attacker,
+ # (and if the bits from OSRNG are insufficiently random) it will weaken
+ # Fortuna's ability to resist a state compromise extension attack.
+ self._fa._forget_last_reseed()
+
+ def close(self):
+ self.closed = True
+ self._osrng = None
+ self._fa = None
+
+ def flush(self):
+ pass
+
+ def read(self, N):
+ """Return N bytes from the RNG."""
+ if self.closed:
+ raise ValueError("I/O operation on closed file")
+ if not isinstance(N, int):
+ raise TypeError("an integer is required")
+ if N < 0:
+ raise ValueError("cannot read to end of infinite stream")
+
+ # Collect some entropy and feed it to Fortuna
+ self._ec.collect()
+
+ # Ask Fortuna to generate some bytes
+ retval = self._fa.random_data(N)
+
+ # Check that we haven't forked in the meantime. (If we have, we don't
+ # want to use the data, because it might have been duplicated in the
+ # parent process.
+ self._check_pid()
+
+ # Return the random data.
+ return retval
+
+ def _check_pid(self):
+ # Lame fork detection to remind developers to invoke Random.atfork()
+ # after every call to os.fork(). Note that this check is not reliable,
+ # since process IDs can be reused on most operating systems.
+ #
+ # You need to do Random.atfork() in the child process after every call
+ # to os.fork() to avoid reusing PRNG state. If you want to avoid
+ # leaking PRNG state to child processes (for example, if you are using
+ # os.setuid()) then you should also invoke Random.atfork() in the
+ # *parent* process.
+ if os.getpid() != self._pid:
+ raise AssertionError("PID check failed. RNG must be re-initialized after fork(). Hint: Try Random.atfork()")
+
+
+class _LockingUserFriendlyRNG(_UserFriendlyRNG):
+ def __init__(self):
+ self._lock = threading.Lock()
+ _UserFriendlyRNG.__init__(self)
+
+ def close(self):
+ self._lock.acquire()
+ try:
+ return _UserFriendlyRNG.close(self)
+ finally:
+ self._lock.release()
+
+ def reinit(self):
+ self._lock.acquire()
+ try:
+ return _UserFriendlyRNG.reinit(self)
+ finally:
+ self._lock.release()
+
+ def read(self, bytes):
+ self._lock.acquire()
+ try:
+ return _UserFriendlyRNG.read(self, bytes)
+ finally:
+ self._lock.release()
+
+class RNGFile(object):
+ def __init__(self, singleton):
+ self.closed = False
+ self._singleton = singleton
+
+ # PEP 343: Support for the "with" statement
+ def __enter__(self):
+ """PEP 343 support"""
+ def __exit__(self):
+ """PEP 343 support"""
+ self.close()
+
+ def close(self):
+ # Don't actually close the singleton, just close this RNGFile instance.
+ self.closed = True
+ self._singleton = None
+
+ def read(self, bytes):
+ if self.closed:
+ raise ValueError("I/O operation on closed file")
+ return self._singleton.read(bytes)
+
+ def flush(self):
+ if self.closed:
+ raise ValueError("I/O operation on closed file")
+
+_singleton_lock = threading.Lock()
+_singleton = None
+def _get_singleton():
+ global _singleton
+ _singleton_lock.acquire()
+ try:
+ if _singleton is None:
+ _singleton = _LockingUserFriendlyRNG()
+ return _singleton
+ finally:
+ _singleton_lock.release()
+
+def new():
+ return RNGFile(_get_singleton())
+
+def reinit():
+ _get_singleton().reinit()
+
+def get_random_bytes(n):
+ """Return the specified number of cryptographically-strong random bytes."""
+ return _get_singleton().read(n)
+
+# vim:set ts=4 sw=4 sts=4 expandtab:
diff --git a/frozen_deps/Crypto/Random/__init__.py b/frozen_deps/Crypto/Random/__init__.py
new file mode 100644
index 0000000..659ffee
--- /dev/null
+++ b/frozen_deps/Crypto/Random/__init__.py
@@ -0,0 +1,43 @@
+# -*- coding: utf-8 -*-
+#
+# Random/__init__.py : PyCrypto random number generation
+#
+# Written in 2008 by Dwayne C. Litzenberger <[email protected]>
+#
+# ===================================================================
+# The contents of this file are dedicated to the public domain. To
+# the extent that dedication to the public domain is not available,
+# everyone is granted a worldwide, perpetual, royalty-free,
+# non-exclusive license to exercise all rights associated with the
+# contents of this file for any purpose whatsoever.
+# No rights are reserved.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+# SOFTWARE.
+# ===================================================================
+
+__revision__ = "$Id$"
+__all__ = ['new']
+
+from Crypto.Random import OSRNG
+from Crypto.Random import _UserFriendlyRNG
+
+def new(*args, **kwargs):
+ """Return a file-like object that outputs cryptographically random bytes."""
+ return _UserFriendlyRNG.new(*args, **kwargs)
+
+def atfork():
+ """Call this whenever you call os.fork()"""
+ _UserFriendlyRNG.reinit()
+
+def get_random_bytes(n):
+ """Return the specified number of cryptographically-strong random bytes."""
+ return _UserFriendlyRNG.get_random_bytes(n)
+
+# vim:set ts=4 sw=4 sts=4 expandtab:
diff --git a/frozen_deps/Crypto/Random/random.py b/frozen_deps/Crypto/Random/random.py
new file mode 100644
index 0000000..cd9a221
--- /dev/null
+++ b/frozen_deps/Crypto/Random/random.py
@@ -0,0 +1,142 @@
+# -*- coding: utf-8 -*-
+#
+# Random/random.py : Strong alternative for the standard 'random' module
+#
+# Written in 2008 by Dwayne C. Litzenberger <[email protected]>
+#
+# ===================================================================
+# The contents of this file are dedicated to the public domain. To
+# the extent that dedication to the public domain is not available,
+# everyone is granted a worldwide, perpetual, royalty-free,
+# non-exclusive license to exercise all rights associated with the
+# contents of this file for any purpose whatsoever.
+# No rights are reserved.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+# SOFTWARE.
+# ===================================================================
+
+"""A cryptographically strong version of Python's standard "random" module."""
+
+__revision__ = "$Id$"
+__all__ = ['StrongRandom', 'getrandbits', 'randrange', 'randint', 'choice', 'shuffle', 'sample']
+
+from Crypto import Random
+import sys
+if sys.version_info[0] == 2 and sys.version_info[1] == 1:
+ from Crypto.Util.py21compat import *
+
+class StrongRandom(object):
+ def __init__(self, rng=None, randfunc=None):
+ if randfunc is None and rng is None:
+ self._randfunc = None
+ elif randfunc is not None and rng is None:
+ self._randfunc = randfunc
+ elif randfunc is None and rng is not None:
+ self._randfunc = rng.read
+ else:
+ raise ValueError("Cannot specify both 'rng' and 'randfunc'")
+
+ def getrandbits(self, k):
+ """Return a python long integer with k random bits."""
+ if self._randfunc is None:
+ self._randfunc = Random.new().read
+ mask = (1 << k) - 1
+ return mask & bytes_to_long(self._randfunc(ceil_div(k, 8)))
+
+ def randrange(self, *args):
+ """randrange([start,] stop[, step]):
+ Return a randomly-selected element from range(start, stop, step)."""
+ if len(args) == 3:
+ (start, stop, step) = args
+ elif len(args) == 2:
+ (start, stop) = args
+ step = 1
+ elif len(args) == 1:
+ (stop,) = args
+ start = 0
+ step = 1
+ else:
+ raise TypeError("randrange expected at most 3 arguments, got %d" % (len(args),))
+ if (not isinstance(start, int)
+ or not isinstance(stop, int)
+ or not isinstance(step, int)):
+ raise TypeError("randrange requires integer arguments")
+ if step == 0:
+ raise ValueError("randrange step argument must not be zero")
+
+ num_choices = ceil_div(stop - start, step)
+ if num_choices < 0:
+ num_choices = 0
+ if num_choices < 1:
+ raise ValueError("empty range for randrange(%r, %r, %r)" % (start, stop, step))
+
+ # Pick a random number in the range of possible numbers
+ r = num_choices
+ while r >= num_choices:
+ r = self.getrandbits(size(num_choices))
+
+ return start + (step * r)
+
+ def randint(self, a, b):
+ """Return a random integer N such that a <= N <= b."""
+ if not isinstance(a, int) or not isinstance(b, int):
+ raise TypeError("randint requires integer arguments")
+ N = self.randrange(a, b+1)
+ assert a <= N <= b
+ return N
+
+ def choice(self, seq):
+ """Return a random element from a (non-empty) sequence.
+
+ If the seqence is empty, raises IndexError.
+ """
+ if len(seq) == 0:
+ raise IndexError("empty sequence")
+ return seq[self.randrange(len(seq))]
+
+ def shuffle(self, x):
+ """Shuffle the sequence in place."""
+ # Make a (copy) of the list of objects we want to shuffle
+ items = list(x)
+
+ # Choose a random item (without replacement) until all the items have been
+ # chosen.
+ for i in range(len(x)):
+ x[i] = items.pop(self.randrange(len(items)))
+
+ def sample(self, population, k):
+ """Return a k-length list of unique elements chosen from the population sequence."""
+
+ num_choices = len(population)
+ if k > num_choices:
+ raise ValueError("sample larger than population")
+
+ retval = []
+ selected = {} # we emulate a set using a dict here
+ for i in range(k):
+ r = None
+ while r is None or r in selected:
+ r = self.randrange(num_choices)
+ retval.append(population[r])
+ selected[r] = 1
+ return retval
+
+_r = StrongRandom()
+getrandbits = _r.getrandbits
+randrange = _r.randrange
+randint = _r.randint
+choice = _r.choice
+shuffle = _r.shuffle
+sample = _r.sample
+
+# These are at the bottom to avoid problems with recursive imports
+from Crypto.Util.number import ceil_div, bytes_to_long, long_to_bytes, size
+
+# vim:set ts=4 sw=4 sts=4 expandtab:
diff --git a/frozen_deps/Crypto/Signature/PKCS1_PSS.py b/frozen_deps/Crypto/Signature/PKCS1_PSS.py
new file mode 100644
index 0000000..319851e
--- /dev/null
+++ b/frozen_deps/Crypto/Signature/PKCS1_PSS.py
@@ -0,0 +1,355 @@
+# -*- coding: utf-8 -*-
+#
+# Signature/PKCS1_PSS.py : PKCS#1 PPS
+#
+# ===================================================================
+# The contents of this file are dedicated to the public domain. To
+# the extent that dedication to the public domain is not available,
+# everyone is granted a worldwide, perpetual, royalty-free,
+# non-exclusive license to exercise all rights associated with the
+# contents of this file for any purpose whatsoever.
+# No rights are reserved.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+# SOFTWARE.
+# ===================================================================
+
+"""RSA digital signature protocol with appendix according to PKCS#1 PSS.
+
+See RFC3447__ or the `original RSA Labs specification`__.
+
+This scheme is more properly called ``RSASSA-PSS``.
+
+For example, a sender may authenticate a message using SHA-1 and PSS like
+this:
+
+ >>> from Crypto.Signature import PKCS1_PSS
+ >>> from Crypto.Hash import SHA
+ >>> from Crypto.PublicKey import RSA
+ >>> from Crypto import Random
+ >>>
+ >>> message = 'To be signed'
+ >>> key = RSA.importKey(open('privkey.der').read())
+ >>> h = SHA.new()
+ >>> h.update(message)
+ >>> signer = PKCS1_PSS.new(key)
+ >>> signature = PKCS1_PSS.sign(key)
+
+At the receiver side, verification can be done like using the public part of
+the RSA key:
+
+ >>> key = RSA.importKey(open('pubkey.der').read())
+ >>> h = SHA.new()
+ >>> h.update(message)
+ >>> verifier = PKCS1_PSS.new(key)
+ >>> if verifier.verify(h, signature):
+ >>> print "The signature is authentic."
+ >>> else:
+ >>> print "The signature is not authentic."
+
+:undocumented: __revision__, __package__
+
+.. __: http://www.ietf.org/rfc/rfc3447.txt
+.. __: http://www.rsa.com/rsalabs/node.asp?id=2125
+"""
+
+# Allow nested scopes in Python 2.1
+# See http://oreilly.com/pub/a/python/2001/04/19/pythonnews.html
+
+
+__revision__ = "$Id$"
+__all__ = [ 'new', 'PSS_SigScheme' ]
+
+from Crypto.Util.py3compat import *
+if sys.version_info[0] == 2 and sys.version_info[1] == 1:
+ from Crypto.Util.py21compat import *
+import Crypto.Util.number
+from Crypto.Util.number import ceil_shift, ceil_div, long_to_bytes
+from Crypto.Util.strxor import strxor
+
+class PSS_SigScheme:
+ """This signature scheme can perform PKCS#1 PSS RSA signature or verification."""
+
+ def __init__(self, key, mgfunc, saltLen):
+ """Initialize this PKCS#1 PSS signature scheme object.
+
+ :Parameters:
+ key : an RSA key object
+ If a private half is given, both signature and verification are possible.
+ If a public half is given, only verification is possible.
+ mgfunc : callable
+ A mask generation function that accepts two parameters: a string to
+ use as seed, and the lenth of the mask to generate, in bytes.
+ saltLen : int
+ Length of the salt, in bytes.
+ """
+ self._key = key
+ self._saltLen = saltLen
+ self._mgfunc = mgfunc
+
+ def can_sign(self):
+ """Return True if this cipher object can be used for signing messages."""
+ return self._key.has_private()
+
+ def sign(self, mhash):
+ """Produce the PKCS#1 PSS signature of a message.
+
+ This function is named ``RSASSA-PSS-SIGN``, and is specified in
+ section 8.1.1 of RFC3447.
+
+ :Parameters:
+ mhash : hash object
+ The hash that was carried out over the message. This is an object
+ belonging to the `Crypto.Hash` module.
+
+ :Return: The PSS signature encoded as a string.
+ :Raise ValueError:
+ If the RSA key length is not sufficiently long to deal with the given
+ hash algorithm.
+ :Raise TypeError:
+ If the RSA key has no private half.
+
+ :attention: Modify the salt length and the mask generation function only
+ if you know what you are doing.
+ The receiver must use the same parameters too.
+ """
+ # TODO: Verify the key is RSA
+
+ randfunc = self._key._randfunc
+
+ # Set defaults for salt length and mask generation function
+ if self._saltLen == None:
+ sLen = mhash.digest_size
+ else:
+ sLen = self._saltLen
+ if self._mgfunc:
+ mgf = self._mgfunc
+ else:
+ mgf = lambda x,y: MGF1(x,y,mhash)
+
+ modBits = Crypto.Util.number.size(self._key.n)
+
+ # See 8.1.1 in RFC3447
+ k = ceil_div(modBits,8) # Convert from bits to bytes
+ # Step 1
+ em = EMSA_PSS_ENCODE(mhash, modBits-1, randfunc, mgf, sLen)
+ # Step 2a (OS2IP) and 2b (RSASP1)
+ m = self._key.decrypt(em)
+ # Step 2c (I2OSP)
+ S = bchr(0x00)*(k-len(m)) + m
+ return S
+
+ def verify(self, mhash, S):
+ """Verify that a certain PKCS#1 PSS signature is authentic.
+
+ This function checks if the party holding the private half of the given
+ RSA key has really signed the message.
+
+ This function is called ``RSASSA-PSS-VERIFY``, and is specified in section
+ 8.1.2 of RFC3447.
+
+ :Parameters:
+ mhash : hash object
+ The hash that was carried out over the message. This is an object
+ belonging to the `Crypto.Hash` module.
+ S : string
+ The signature that needs to be validated.
+
+ :Return: True if verification is correct. False otherwise.
+ """
+ # TODO: Verify the key is RSA
+
+ # Set defaults for salt length and mask generation function
+ if self._saltLen == None:
+ sLen = mhash.digest_size
+ else:
+ sLen = self._saltLen
+ if self._mgfunc:
+ mgf = self._mgfunc
+ else:
+ mgf = lambda x,y: MGF1(x,y,mhash)
+
+ modBits = Crypto.Util.number.size(self._key.n)
+
+ # See 8.1.2 in RFC3447
+ k = ceil_div(modBits,8) # Convert from bits to bytes
+ # Step 1
+ if len(S) != k:
+ return False
+ # Step 2a (O2SIP), 2b (RSAVP1), and partially 2c (I2OSP)
+ # Note that signature must be smaller than the module
+ # but RSA.py won't complain about it.
+ # TODO: Fix RSA object; don't do it here.
+ em = self._key.encrypt(S, 0)[0]
+ # Step 2c
+ emLen = ceil_div(modBits-1,8)
+ em = bchr(0x00)*(emLen-len(em)) + em
+ # Step 3
+ try:
+ result = EMSA_PSS_VERIFY(mhash, em, modBits-1, mgf, sLen)
+ except ValueError:
+ return False
+ # Step 4
+ return result
+
+def MGF1(mgfSeed, maskLen, hash):
+ """Mask Generation Function, described in B.2.1"""
+ T = b("")
+ for counter in range(ceil_div(maskLen, hash.digest_size)):
+ c = long_to_bytes(counter, 4)
+ T = T + hash.new(mgfSeed + c).digest()
+ assert(len(T)>=maskLen)
+ return T[:maskLen]
+
+def EMSA_PSS_ENCODE(mhash, emBits, randFunc, mgf, sLen):
+ """
+ Implement the ``EMSA-PSS-ENCODE`` function, as defined
+ in PKCS#1 v2.1 (RFC3447, 9.1.1).
+
+ The original ``EMSA-PSS-ENCODE`` actually accepts the message ``M`` as input,
+ and hash it internally. Here, we expect that the message has already
+ been hashed instead.
+
+ :Parameters:
+ mhash : hash object
+ The hash object that holds the digest of the message being signed.
+ emBits : int
+ Maximum length of the final encoding, in bits.
+ randFunc : callable
+ An RNG function that accepts as only parameter an int, and returns
+ a string of random bytes, to be used as salt.
+ mgf : callable
+ A mask generation function that accepts two parameters: a string to
+ use as seed, and the lenth of the mask to generate, in bytes.
+ sLen : int
+ Length of the salt, in bytes.
+
+ :Return: An ``emLen`` byte long string that encodes the hash
+ (with ``emLen = \ceil(emBits/8)``).
+
+ :Raise ValueError:
+ When digest or salt length are too big.
+ """
+
+ emLen = ceil_div(emBits,8)
+
+ # Bitmask of digits that fill up
+ lmask = 0
+ for i in range(8*emLen-emBits):
+ lmask = lmask>>1 | 0x80
+
+ # Step 1 and 2 have been already done
+ # Step 3
+ if emLen < mhash.digest_size+sLen+2:
+ raise ValueError("Digest or salt length are too long for given key size.")
+ # Step 4
+ salt = b("")
+ if randFunc and sLen>0:
+ salt = randFunc(sLen)
+ # Step 5 and 6
+ h = mhash.new(bchr(0x00)*8 + mhash.digest() + salt)
+ # Step 7 and 8
+ db = bchr(0x00)*(emLen-sLen-mhash.digest_size-2) + bchr(0x01) + salt
+ # Step 9
+ dbMask = mgf(h.digest(), emLen-mhash.digest_size-1)
+ # Step 10
+ maskedDB = strxor(db,dbMask)
+ # Step 11
+ maskedDB = bchr(bord(maskedDB[0]) & ~lmask) + maskedDB[1:]
+ # Step 12
+ em = maskedDB + h.digest() + bchr(0xBC)
+ return em
+
+def EMSA_PSS_VERIFY(mhash, em, emBits, mgf, sLen):
+ """
+ Implement the ``EMSA-PSS-VERIFY`` function, as defined
+ in PKCS#1 v2.1 (RFC3447, 9.1.2).
+
+ ``EMSA-PSS-VERIFY`` actually accepts the message ``M`` as input,
+ and hash it internally. Here, we expect that the message has already
+ been hashed instead.
+
+ :Parameters:
+ mhash : hash object
+ The hash object that holds the digest of the message to be verified.
+ em : string
+ The signature to verify, therefore proving that the sender really signed
+ the message that was received.
+ emBits : int
+ Length of the final encoding (em), in bits.
+ mgf : callable
+ A mask generation function that accepts two parameters: a string to
+ use as seed, and the lenth of the mask to generate, in bytes.
+ sLen : int
+ Length of the salt, in bytes.
+
+ :Return: 0 if the encoding is consistent, 1 if it is inconsistent.
+
+ :Raise ValueError:
+ When digest or salt length are too big.
+ """
+
+ emLen = ceil_div(emBits,8)
+
+ # Bitmask of digits that fill up
+ lmask = 0
+ for i in range(8*emLen-emBits):
+ lmask = lmask>>1 | 0x80
+
+ # Step 1 and 2 have been already done
+ # Step 3
+ if emLen < mhash.digest_size+sLen+2:
+ return False
+ # Step 4
+ if ord(em[-1:])!=0xBC:
+ return False
+ # Step 5
+ maskedDB = em[:emLen-mhash.digest_size-1]
+ h = em[emLen-mhash.digest_size-1:-1]
+ # Step 6
+ if lmask & bord(em[0]):
+ return False
+ # Step 7
+ dbMask = mgf(h, emLen-mhash.digest_size-1)
+ # Step 8
+ db = strxor(maskedDB, dbMask)
+ # Step 9
+ db = bchr(bord(db[0]) & ~lmask) + db[1:]
+ # Step 10
+ if not db.startswith(bchr(0x00)*(emLen-mhash.digest_size-sLen-2) + bchr(0x01)):
+ return False
+ # Step 11
+ salt = b("")
+ if sLen: salt = db[-sLen:]
+ # Step 12 and 13
+ hp = mhash.new(bchr(0x00)*8 + mhash.digest() + salt).digest()
+ # Step 14
+ if h!=hp:
+ return False
+ return True
+
+def new(key, mgfunc=None, saltLen=None):
+ """Return a signature scheme object `PSS_SigScheme` that
+ can be used to perform PKCS#1 PSS signature or verification.
+
+ :Parameters:
+ key : RSA key object
+ The key to use to sign or verify the message. This is a `Crypto.PublicKey.RSA` object.
+ Signing is only possible if *key* is a private RSA key.
+ mgfunc : callable
+ A mask generation function that accepts two parameters: a string to
+ use as seed, and the lenth of the mask to generate, in bytes.
+ If not specified, the standard MGF1 is used.
+ saltLen : int
+ Length of the salt, in bytes. If not specified, it matches the output
+ size of the hash function.
+
+ """
+ return PSS_SigScheme(key, mgfunc, saltLen)
+
diff --git a/frozen_deps/Crypto/Signature/PKCS1_v1_5.py b/frozen_deps/Crypto/Signature/PKCS1_v1_5.py
new file mode 100644
index 0000000..73ac251
--- /dev/null
+++ b/frozen_deps/Crypto/Signature/PKCS1_v1_5.py
@@ -0,0 +1,236 @@
+# -*- coding: utf-8 -*-
+#
+# Signature/PKCS1-v1_5.py : PKCS#1 v1.5
+#
+# ===================================================================
+# The contents of this file are dedicated to the public domain. To
+# the extent that dedication to the public domain is not available,
+# everyone is granted a worldwide, perpetual, royalty-free,
+# non-exclusive license to exercise all rights associated with the
+# contents of this file for any purpose whatsoever.
+# No rights are reserved.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+# SOFTWARE.
+# ===================================================================
+
+"""
+RSA digital signature protocol according to PKCS#1 v1.5
+
+See RFC3447__ or the `original RSA Labs specification`__.
+
+This scheme is more properly called ``RSASSA-PKCS1-v1_5``.
+
+For example, a sender may authenticate a message using SHA-1 like
+this:
+
+ >>> from Crypto.Signature import PKCS1_v1_5
+ >>> from Crypto.Hash import SHA
+ >>> from Crypto.PublicKey import RSA
+ >>>
+ >>> message = 'To be signed'
+ >>> key = RSA.importKey(open('privkey.der').read())
+ >>> h = SHA.new(message)
+ >>> signer = PKCS1_v1_5.new(key)
+ >>> signature = signer.sign(h)
+
+At the receiver side, verification can be done using the public part of
+the RSA key:
+
+ >>> key = RSA.importKey(open('pubkey.der').read())
+ >>> h = SHA.new(message)
+ >>> verifier = PKCS1_v1_5.new(key)
+ >>> if verifier.verify(h, signature):
+ >>> print "The signature is authentic."
+ >>> else:
+ >>> print "The signature is not authentic."
+
+:undocumented: __revision__, __package__
+
+.. __: http://www.ietf.org/rfc/rfc3447.txt
+.. __: http://www.rsa.com/rsalabs/node.asp?id=2125
+"""
+
+__revision__ = "$Id$"
+__all__ = [ 'new', 'PKCS115_SigScheme' ]
+
+import Crypto.Util.number
+from Crypto.Util.number import ceil_div
+from Crypto.Util.asn1 import DerSequence, DerNull, DerOctetString
+from Crypto.Util.py3compat import *
+
+class PKCS115_SigScheme:
+ """This signature scheme can perform PKCS#1 v1.5 RSA signature or verification."""
+
+ def __init__(self, key):
+ """Initialize this PKCS#1 v1.5 signature scheme object.
+
+ :Parameters:
+ key : an RSA key object
+ If a private half is given, both signature and verification are possible.
+ If a public half is given, only verification is possible.
+ """
+ self._key = key
+
+ def can_sign(self):
+ """Return True if this cipher object can be used for signing messages."""
+ return self._key.has_private()
+
+ def sign(self, mhash):
+ """Produce the PKCS#1 v1.5 signature of a message.
+
+ This function is named ``RSASSA-PKCS1-V1_5-SIGN``, and is specified in
+ section 8.2.1 of RFC3447.
+
+ :Parameters:
+ mhash : hash object
+ The hash that was carried out over the message. This is an object
+ belonging to the `Crypto.Hash` module.
+
+ :Return: The signature encoded as a string.
+ :Raise ValueError:
+ If the RSA key length is not sufficiently long to deal with the given
+ hash algorithm.
+ :Raise TypeError:
+ If the RSA key has no private half.
+ """
+ # TODO: Verify the key is RSA
+
+ # See 8.2.1 in RFC3447
+ modBits = Crypto.Util.number.size(self._key.n)
+ k = ceil_div(modBits,8) # Convert from bits to bytes
+
+ # Step 1
+ em = EMSA_PKCS1_V1_5_ENCODE(mhash, k)
+ # Step 2a (OS2IP) and 2b (RSASP1)
+ m = self._key.decrypt(em)
+ # Step 2c (I2OSP)
+ S = bchr(0x00)*(k-len(m)) + m
+ return S
+
+ def verify(self, mhash, S):
+ """Verify that a certain PKCS#1 v1.5 signature is authentic.
+
+ This function checks if the party holding the private half of the key
+ really signed the message.
+
+ This function is named ``RSASSA-PKCS1-V1_5-VERIFY``, and is specified in
+ section 8.2.2 of RFC3447.
+
+ :Parameters:
+ mhash : hash object
+ The hash that was carried out over the message. This is an object
+ belonging to the `Crypto.Hash` module.
+ S : string
+ The signature that needs to be validated.
+
+ :Return: True if verification is correct. False otherwise.
+ """
+ # TODO: Verify the key is RSA
+
+ # See 8.2.2 in RFC3447
+ modBits = Crypto.Util.number.size(self._key.n)
+ k = ceil_div(modBits,8) # Convert from bits to bytes
+
+ # Step 1
+ if len(S) != k:
+ return 0
+ # Step 2a (O2SIP) and 2b (RSAVP1)
+ # Note that signature must be smaller than the module
+ # but RSA.py won't complain about it.
+ # TODO: Fix RSA object; don't do it here.
+ m = self._key.encrypt(S, 0)[0]
+ # Step 2c (I2OSP)
+ em1 = bchr(0x00)*(k-len(m)) + m
+ # Step 3
+ try:
+ em2 = EMSA_PKCS1_V1_5_ENCODE(mhash, k)
+ except ValueError:
+ return 0
+ # Step 4
+ # By comparing the full encodings (as opposed to checking each
+ # of its components one at a time) we avoid attacks to the padding
+ # scheme like Bleichenbacher's (see http://www.mail-archive.com/[email protected]/msg06537).
+ #
+ return em1==em2
+
+def EMSA_PKCS1_V1_5_ENCODE(hash, emLen):
+ """
+ Implement the ``EMSA-PKCS1-V1_5-ENCODE`` function, as defined
+ in PKCS#1 v2.1 (RFC3447, 9.2).
+
+ ``EMSA-PKCS1-V1_5-ENCODE`` actually accepts the message ``M`` as input,
+ and hash it internally. Here, we expect that the message has already
+ been hashed instead.
+
+ :Parameters:
+ hash : hash object
+ The hash object that holds the digest of the message being signed.
+ emLen : int
+ The length the final encoding must have, in bytes.
+
+ :attention: the early standard (RFC2313) stated that ``DigestInfo``
+ had to be BER-encoded. This means that old signatures
+ might have length tags in indefinite form, which
+ is not supported in DER. Such encoding cannot be
+ reproduced by this function.
+
+ :attention: the same standard defined ``DigestAlgorithm`` to be
+ of ``AlgorithmIdentifier`` type, where the PARAMETERS
+ item is optional. Encodings for ``MD2/4/5`` without
+ ``PARAMETERS`` cannot be reproduced by this function.
+
+ :Return: An ``emLen`` byte long string that encodes the hash.
+ """
+
+ # First, build the ASN.1 DER object DigestInfo:
+ #
+ # DigestInfo ::= SEQUENCE {
+ # digestAlgorithm AlgorithmIdentifier,
+ # digest OCTET STRING
+ # }
+ #
+ # where digestAlgorithm identifies the hash function and shall be an
+ # algorithm ID with an OID in the set PKCS1-v1-5DigestAlgorithms.
+ #
+ # PKCS1-v1-5DigestAlgorithms ALGORITHM-IDENTIFIER ::= {
+ # { OID id-md2 PARAMETERS NULL }|
+ # { OID id-md5 PARAMETERS NULL }|
+ # { OID id-sha1 PARAMETERS NULL }|
+ # { OID id-sha256 PARAMETERS NULL }|
+ # { OID id-sha384 PARAMETERS NULL }|
+ # { OID id-sha512 PARAMETERS NULL }
+ # }
+ #
+ digestAlgo = DerSequence([hash.oid, DerNull().encode()])
+ digest = DerOctetString(hash.digest())
+ digestInfo = DerSequence([
+ digestAlgo.encode(),
+ digest.encode()
+ ]).encode()
+
+ # We need at least 11 bytes for the remaining data: 3 fixed bytes and
+ # at least 8 bytes of padding).
+ if emLen<len(digestInfo)+11:
+ raise ValueError("Selected hash algorith has a too long digest (%d bytes)." % len(digest))
+ PS = bchr(0xFF) * (emLen - len(digestInfo) - 3)
+ return b("\x00\x01") + PS + bchr(0x00) + digestInfo
+
+def new(key):
+ """Return a signature scheme object `PKCS115_SigScheme` that
+ can be used to perform PKCS#1 v1.5 signature or verification.
+
+ :Parameters:
+ key : RSA key object
+ The key to use to sign or verify the message. This is a `Crypto.PublicKey.RSA` object.
+ Signing is only possible if *key* is a private RSA key.
+
+ """
+ return PKCS115_SigScheme(key)
+
diff --git a/frozen_deps/Crypto/Signature/__init__.py b/frozen_deps/Crypto/Signature/__init__.py
new file mode 100644
index 0000000..ed523b4
--- /dev/null
+++ b/frozen_deps/Crypto/Signature/__init__.py
@@ -0,0 +1,31 @@
+# -*- coding: utf-8 -*-
+#
+# ===================================================================
+# The contents of this file are dedicated to the public domain. To
+# the extent that dedication to the public domain is not available,
+# everyone is granted a worldwide, perpetual, royalty-free,
+# non-exclusive license to exercise all rights associated with the
+# contents of this file for any purpose whatsoever.
+# No rights are reserved.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+# SOFTWARE.
+# ===================================================================
+
+"""Digital signature protocols
+
+A collection of standardized protocols to carry out digital signatures.
+
+:undocumented: __revision__, __package__
+"""
+
+__all__ = [ 'PKCS1_v1_5', 'PKCS1_PSS' ]
+__revision__ = "$Id$"
+
+
diff --git a/frozen_deps/Crypto/Util/Counter.py b/frozen_deps/Crypto/Util/Counter.py
new file mode 100644
index 0000000..f0460e5
--- /dev/null
+++ b/frozen_deps/Crypto/Util/Counter.py
@@ -0,0 +1,127 @@
+# -*- coding: ascii -*-
+#
+# Util/Counter.py : Fast counter for use with CTR-mode ciphers
+#
+# Written in 2008 by Dwayne C. Litzenberger <[email protected]>
+#
+# ===================================================================
+# The contents of this file are dedicated to the public domain. To
+# the extent that dedication to the public domain is not available,
+# everyone is granted a worldwide, perpetual, royalty-free,
+# non-exclusive license to exercise all rights associated with the
+# contents of this file for any purpose whatsoever.
+# No rights are reserved.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+# SOFTWARE.
+# ===================================================================
+"""Fast counter functions for CTR cipher modes.
+
+CTR is a chaining mode for symmetric block encryption or decryption.
+Messages are divideded into blocks, and the cipher operation takes
+place on each block using the secret key and a unique *counter block*.
+
+The most straightforward way to fulfil the uniqueness property is
+to start with an initial, random *counter block* value, and increment it as
+the next block is processed.
+
+The block ciphers from `Crypto.Cipher` (when configured in *MODE_CTR* mode)
+invoke a callable object (the *counter* parameter) to get the next *counter block*.
+Unfortunately, the Python calling protocol leads to major performance degradations.
+
+The counter functions instantiated by this module will be invoked directly
+by the ciphers in `Crypto.Cipher`. The fact that the Python layer is bypassed
+lead to more efficient (and faster) execution of CTR cipher modes.
+
+An example of usage is the following:
+
+ >>> from Crypto.Cipher import AES
+ >>> from Crypto.Util import Counter
+ >>>
+ >>> pt = b'\x00'*1000000
+ >>> ctr = Counter.new(128)
+ >>> cipher = AES.new(b'\x00'*16, AES.MODE_CTR, counter=ctr)
+ >>> ct = cipher.encrypt(pt)
+
+:undocumented: __package__
+"""
+import sys
+if sys.version_info[0] == 2 and sys.version_info[1] == 1:
+ from Crypto.Util.py21compat import *
+from Crypto.Util.py3compat import *
+
+from Crypto.Util import _counter
+import struct
+
+# Factory function
+def new(nbits, prefix=b(""), suffix=b(""), initial_value=1, overflow=0, little_endian=False, allow_wraparound=False, disable_shortcut=False):
+ """Create a stateful counter block function suitable for CTR encryption modes.
+
+ Each call to the function returns the next counter block.
+ Each counter block is made up by three parts::
+
+ prefix || counter value || postfix
+
+ The counter value is incremented by one at each call.
+
+ :Parameters:
+ nbits : integer
+ Length of the desired counter, in bits. It must be a multiple of 8.
+ prefix : byte string
+ The constant prefix of the counter block. By default, no prefix is
+ used.
+ suffix : byte string
+ The constant postfix of the counter block. By default, no suffix is
+ used.
+ initial_value : integer
+ The initial value of the counter. Default value is 1.
+ little_endian : boolean
+ If True, the counter number will be encoded in little endian format.
+ If False (default), in big endian format.
+ allow_wraparound : boolean
+ If True, the function will raise an *OverflowError* exception as soon
+ as the counter wraps around. If False (default), the counter will
+ simply restart from zero.
+ disable_shortcut : boolean
+ If True, do not make ciphers from `Crypto.Cipher` bypass the Python
+ layer when invoking the counter block function.
+ If False (default), bypass the Python layer.
+ :Returns:
+ The counter block function.
+ """
+
+ # Sanity-check the message size
+ (nbytes, remainder) = divmod(nbits, 8)
+ if remainder != 0:
+ # In the future, we might support arbitrary bit lengths, but for now we don't.
+ raise ValueError("nbits must be a multiple of 8; got %d" % (nbits,))
+ if nbytes < 1:
+ raise ValueError("nbits too small")
+ elif nbytes > 0xffff:
+ raise ValueError("nbits too large")
+
+ initval = _encode(initial_value, nbytes, little_endian)
+
+ if little_endian:
+ return _counter._newLE(bstr(prefix), bstr(suffix), initval, allow_wraparound=allow_wraparound, disable_shortcut=disable_shortcut)
+ else:
+ return _counter._newBE(bstr(prefix), bstr(suffix), initval, allow_wraparound=allow_wraparound, disable_shortcut=disable_shortcut)
+
+def _encode(n, nbytes, little_endian=False):
+ retval = []
+ n = int(n)
+ for i in range(nbytes):
+ if little_endian:
+ retval.append(bchr(n & 0xff))
+ else:
+ retval.insert(0, bchr(n & 0xff))
+ n >>= 8
+ return b("").join(retval)
+
+# vim:set ts=4 sw=4 sts=4 expandtab:
diff --git a/frozen_deps/Crypto/Util/RFC1751.py b/frozen_deps/Crypto/Util/RFC1751.py
new file mode 100644
index 0000000..1c10c4a
--- /dev/null
+++ b/frozen_deps/Crypto/Util/RFC1751.py
@@ -0,0 +1,365 @@
+# rfc1751.py : Converts between 128-bit strings and a human-readable
+# sequence of words, as defined in RFC1751: "A Convention for
+# Human-Readable 128-bit Keys", by Daniel L. McDonald.
+#
+# Part of the Python Cryptography Toolkit
+#
+# Written by Andrew M. Kuchling and others
+#
+# ===================================================================
+# The contents of this file are dedicated to the public domain. To
+# the extent that dedication to the public domain is not available,
+# everyone is granted a worldwide, perpetual, royalty-free,
+# non-exclusive license to exercise all rights associated with the
+# contents of this file for any purpose whatsoever.
+# No rights are reserved.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+# SOFTWARE.
+# ===================================================================
+
+__revision__ = "$Id$"
+
+
+import binascii
+from Crypto.Util.py3compat import *
+from functools import reduce
+
+binary={0:'0000', 1:'0001', 2:'0010', 3:'0011', 4:'0100', 5:'0101',
+ 6:'0110', 7:'0111', 8:'1000', 9:'1001', 10:'1010', 11:'1011',
+ 12:'1100', 13:'1101', 14:'1110', 15:'1111'}
+
+def _key2bin(s):
+ "Convert a key into a string of binary digits"
+ kl=[bord(x) for x in s]
+ kl=[binary[x>>4]+binary[x&15] for x in kl]
+ return ''.join(kl)
+
+def _extract(key, start, length):
+ """Extract a bitstring(2.x)/bytestring(2.x) from a string of binary digits, and return its
+ numeric value."""
+ k=key[start:start+length]
+ return reduce(lambda x,y: x*2+ord(y)-48, k, 0)
+
+def key_to_english (key):
+ """key_to_english(key:string(2.x)/bytes(3.x)) : string
+ Transform an arbitrary key into a string containing English words.
+ The key length must be a multiple of 8.
+ """
+ english=''
+ for index in range(0, len(key), 8): # Loop over 8-byte subkeys
+ subkey=key[index:index+8]
+ # Compute the parity of the key
+ skbin=_key2bin(subkey) ; p=0
+ for i in range(0, 64, 2): p=p+_extract(skbin, i, 2)
+ # Append parity bits to the subkey
+ skbin=_key2bin(subkey+bchr((p<<6) & 255))
+ for i in range(0, 64, 11):
+ english=english+wordlist[_extract(skbin, i, 11)]+' '
+
+ return english[:-1] # Remove the trailing space
+
+def english_to_key (s):
+ """english_to_key(string):string(2.x)/bytes(2.x)
+ Transform a string into a corresponding key.
+ The string must contain words separated by whitespace; the number
+ of words must be a multiple of 6.
+ """
+
+ L=s.upper().split() ; key=b('')
+ for index in range(0, len(L), 6):
+ sublist=L[index:index+6] ; char=9*[0] ; bits=0
+ for i in sublist:
+ index = wordlist.index(i)
+ shift = (8-(bits+11)%8) %8
+ y = index << shift
+ cl, cc, cr = (y>>16), (y>>8)&0xff, y & 0xff
+ if (shift>5):
+ char[bits>>3] = char[bits>>3] | cl
+ char[(bits>>3)+1] = char[(bits>>3)+1] | cc
+ char[(bits>>3)+2] = char[(bits>>3)+2] | cr
+ elif shift>-3:
+ char[bits>>3] = char[bits>>3] | cc
+ char[(bits>>3)+1] = char[(bits>>3)+1] | cr
+ else: char[bits>>3] = char[bits>>3] | cr
+ bits=bits+11
+ subkey=reduce(lambda x,y:x+bchr(y), char, b(''))
+
+ # Check the parity of the resulting key
+ skbin=_key2bin(subkey)
+ p=0
+ for i in range(0, 64, 2): p=p+_extract(skbin, i, 2)
+ if (p&3) != _extract(skbin, 64, 2):
+ raise ValueError("Parity error in resulting key")
+ key=key+subkey[0:8]
+ return key
+
+wordlist=[ "A", "ABE", "ACE", "ACT", "AD", "ADA", "ADD",
+ "AGO", "AID", "AIM", "AIR", "ALL", "ALP", "AM", "AMY", "AN", "ANA",
+ "AND", "ANN", "ANT", "ANY", "APE", "APS", "APT", "ARC", "ARE", "ARK",
+ "ARM", "ART", "AS", "ASH", "ASK", "AT", "ATE", "AUG", "AUK", "AVE",
+ "AWE", "AWK", "AWL", "AWN", "AX", "AYE", "BAD", "BAG", "BAH", "BAM",
+ "BAN", "BAR", "BAT", "BAY", "BE", "BED", "BEE", "BEG", "BEN", "BET",
+ "BEY", "BIB", "BID", "BIG", "BIN", "BIT", "BOB", "BOG", "BON", "BOO",
+ "BOP", "BOW", "BOY", "BUB", "BUD", "BUG", "BUM", "BUN", "BUS", "BUT",
+ "BUY", "BY", "BYE", "CAB", "CAL", "CAM", "CAN", "CAP", "CAR", "CAT",
+ "CAW", "COD", "COG", "COL", "CON", "COO", "COP", "COT", "COW", "COY",
+ "CRY", "CUB", "CUE", "CUP", "CUR", "CUT", "DAB", "DAD", "DAM", "DAN",
+ "DAR", "DAY", "DEE", "DEL", "DEN", "DES", "DEW", "DID", "DIE", "DIG",
+ "DIN", "DIP", "DO", "DOE", "DOG", "DON", "DOT", "DOW", "DRY", "DUB",
+ "DUD", "DUE", "DUG", "DUN", "EAR", "EAT", "ED", "EEL", "EGG", "EGO",
+ "ELI", "ELK", "ELM", "ELY", "EM", "END", "EST", "ETC", "EVA", "EVE",
+ "EWE", "EYE", "FAD", "FAN", "FAR", "FAT", "FAY", "FED", "FEE", "FEW",
+ "FIB", "FIG", "FIN", "FIR", "FIT", "FLO", "FLY", "FOE", "FOG", "FOR",
+ "FRY", "FUM", "FUN", "FUR", "GAB", "GAD", "GAG", "GAL", "GAM", "GAP",
+ "GAS", "GAY", "GEE", "GEL", "GEM", "GET", "GIG", "GIL", "GIN", "GO",
+ "GOT", "GUM", "GUN", "GUS", "GUT", "GUY", "GYM", "GYP", "HA", "HAD",
+ "HAL", "HAM", "HAN", "HAP", "HAS", "HAT", "HAW", "HAY", "HE", "HEM",
+ "HEN", "HER", "HEW", "HEY", "HI", "HID", "HIM", "HIP", "HIS", "HIT",
+ "HO", "HOB", "HOC", "HOE", "HOG", "HOP", "HOT", "HOW", "HUB", "HUE",
+ "HUG", "HUH", "HUM", "HUT", "I", "ICY", "IDA", "IF", "IKE", "ILL",
+ "INK", "INN", "IO", "ION", "IQ", "IRA", "IRE", "IRK", "IS", "IT",
+ "ITS", "IVY", "JAB", "JAG", "JAM", "JAN", "JAR", "JAW", "JAY", "JET",
+ "JIG", "JIM", "JO", "JOB", "JOE", "JOG", "JOT", "JOY", "JUG", "JUT",
+ "KAY", "KEG", "KEN", "KEY", "KID", "KIM", "KIN", "KIT", "LA", "LAB",
+ "LAC", "LAD", "LAG", "LAM", "LAP", "LAW", "LAY", "LEA", "LED", "LEE",
+ "LEG", "LEN", "LEO", "LET", "LEW", "LID", "LIE", "LIN", "LIP", "LIT",
+ "LO", "LOB", "LOG", "LOP", "LOS", "LOT", "LOU", "LOW", "LOY", "LUG",
+ "LYE", "MA", "MAC", "MAD", "MAE", "MAN", "MAO", "MAP", "MAT", "MAW",
+ "MAY", "ME", "MEG", "MEL", "MEN", "MET", "MEW", "MID", "MIN", "MIT",
+ "MOB", "MOD", "MOE", "MOO", "MOP", "MOS", "MOT", "MOW", "MUD", "MUG",
+ "MUM", "MY", "NAB", "NAG", "NAN", "NAP", "NAT", "NAY", "NE", "NED",
+ "NEE", "NET", "NEW", "NIB", "NIL", "NIP", "NIT", "NO", "NOB", "NOD",
+ "NON", "NOR", "NOT", "NOV", "NOW", "NU", "NUN", "NUT", "O", "OAF",
+ "OAK", "OAR", "OAT", "ODD", "ODE", "OF", "OFF", "OFT", "OH", "OIL",
+ "OK", "OLD", "ON", "ONE", "OR", "ORB", "ORE", "ORR", "OS", "OTT",
+ "OUR", "OUT", "OVA", "OW", "OWE", "OWL", "OWN", "OX", "PA", "PAD",
+ "PAL", "PAM", "PAN", "PAP", "PAR", "PAT", "PAW", "PAY", "PEA", "PEG",
+ "PEN", "PEP", "PER", "PET", "PEW", "PHI", "PI", "PIE", "PIN", "PIT",
+ "PLY", "PO", "POD", "POE", "POP", "POT", "POW", "PRO", "PRY", "PUB",
+ "PUG", "PUN", "PUP", "PUT", "QUO", "RAG", "RAM", "RAN", "RAP", "RAT",
+ "RAW", "RAY", "REB", "RED", "REP", "RET", "RIB", "RID", "RIG", "RIM",
+ "RIO", "RIP", "ROB", "ROD", "ROE", "RON", "ROT", "ROW", "ROY", "RUB",
+ "RUE", "RUG", "RUM", "RUN", "RYE", "SAC", "SAD", "SAG", "SAL", "SAM",
+ "SAN", "SAP", "SAT", "SAW", "SAY", "SEA", "SEC", "SEE", "SEN", "SET",
+ "SEW", "SHE", "SHY", "SIN", "SIP", "SIR", "SIS", "SIT", "SKI", "SKY",
+ "SLY", "SO", "SOB", "SOD", "SON", "SOP", "SOW", "SOY", "SPA", "SPY",
+ "SUB", "SUD", "SUE", "SUM", "SUN", "SUP", "TAB", "TAD", "TAG", "TAN",
+ "TAP", "TAR", "TEA", "TED", "TEE", "TEN", "THE", "THY", "TIC", "TIE",
+ "TIM", "TIN", "TIP", "TO", "TOE", "TOG", "TOM", "TON", "TOO", "TOP",
+ "TOW", "TOY", "TRY", "TUB", "TUG", "TUM", "TUN", "TWO", "UN", "UP",
+ "US", "USE", "VAN", "VAT", "VET", "VIE", "WAD", "WAG", "WAR", "WAS",
+ "WAY", "WE", "WEB", "WED", "WEE", "WET", "WHO", "WHY", "WIN", "WIT",
+ "WOK", "WON", "WOO", "WOW", "WRY", "WU", "YAM", "YAP", "YAW", "YE",
+ "YEA", "YES", "YET", "YOU", "ABED", "ABEL", "ABET", "ABLE", "ABUT",
+ "ACHE", "ACID", "ACME", "ACRE", "ACTA", "ACTS", "ADAM", "ADDS",
+ "ADEN", "AFAR", "AFRO", "AGEE", "AHEM", "AHOY", "AIDA", "AIDE",
+ "AIDS", "AIRY", "AJAR", "AKIN", "ALAN", "ALEC", "ALGA", "ALIA",
+ "ALLY", "ALMA", "ALOE", "ALSO", "ALTO", "ALUM", "ALVA", "AMEN",
+ "AMES", "AMID", "AMMO", "AMOK", "AMOS", "AMRA", "ANDY", "ANEW",
+ "ANNA", "ANNE", "ANTE", "ANTI", "AQUA", "ARAB", "ARCH", "AREA",
+ "ARGO", "ARID", "ARMY", "ARTS", "ARTY", "ASIA", "ASKS", "ATOM",
+ "AUNT", "AURA", "AUTO", "AVER", "AVID", "AVIS", "AVON", "AVOW",
+ "AWAY", "AWRY", "BABE", "BABY", "BACH", "BACK", "BADE", "BAIL",
+ "BAIT", "BAKE", "BALD", "BALE", "BALI", "BALK", "BALL", "BALM",
+ "BAND", "BANE", "BANG", "BANK", "BARB", "BARD", "BARE", "BARK",
+ "BARN", "BARR", "BASE", "BASH", "BASK", "BASS", "BATE", "BATH",
+ "BAWD", "BAWL", "BEAD", "BEAK", "BEAM", "BEAN", "BEAR", "BEAT",
+ "BEAU", "BECK", "BEEF", "BEEN", "BEER",
+ "BEET", "BELA", "BELL", "BELT", "BEND", "BENT", "BERG", "BERN",
+ "BERT", "BESS", "BEST", "BETA", "BETH", "BHOY", "BIAS", "BIDE",
+ "BIEN", "BILE", "BILK", "BILL", "BIND", "BING", "BIRD", "BITE",
+ "BITS", "BLAB", "BLAT", "BLED", "BLEW", "BLOB", "BLOC", "BLOT",
+ "BLOW", "BLUE", "BLUM", "BLUR", "BOAR", "BOAT", "BOCA", "BOCK",
+ "BODE", "BODY", "BOGY", "BOHR", "BOIL", "BOLD", "BOLO", "BOLT",
+ "BOMB", "BONA", "BOND", "BONE", "BONG", "BONN", "BONY", "BOOK",
+ "BOOM", "BOON", "BOOT", "BORE", "BORG", "BORN", "BOSE", "BOSS",
+ "BOTH", "BOUT", "BOWL", "BOYD", "BRAD", "BRAE", "BRAG", "BRAN",
+ "BRAY", "BRED", "BREW", "BRIG", "BRIM", "BROW", "BUCK", "BUDD",
+ "BUFF", "BULB", "BULK", "BULL", "BUNK", "BUNT", "BUOY", "BURG",
+ "BURL", "BURN", "BURR", "BURT", "BURY", "BUSH", "BUSS", "BUST",
+ "BUSY", "BYTE", "CADY", "CAFE", "CAGE", "CAIN", "CAKE", "CALF",
+ "CALL", "CALM", "CAME", "CANE", "CANT", "CARD", "CARE", "CARL",
+ "CARR", "CART", "CASE", "CASH", "CASK", "CAST", "CAVE", "CEIL",
+ "CELL", "CENT", "CERN", "CHAD", "CHAR", "CHAT", "CHAW", "CHEF",
+ "CHEN", "CHEW", "CHIC", "CHIN", "CHOU", "CHOW", "CHUB", "CHUG",
+ "CHUM", "CITE", "CITY", "CLAD", "CLAM", "CLAN", "CLAW", "CLAY",
+ "CLOD", "CLOG", "CLOT", "CLUB", "CLUE", "COAL", "COAT", "COCA",
+ "COCK", "COCO", "CODA", "CODE", "CODY", "COED", "COIL", "COIN",
+ "COKE", "COLA", "COLD", "COLT", "COMA", "COMB", "COME", "COOK",
+ "COOL", "COON", "COOT", "CORD", "CORE", "CORK", "CORN", "COST",
+ "COVE", "COWL", "CRAB", "CRAG", "CRAM", "CRAY", "CREW", "CRIB",
+ "CROW", "CRUD", "CUBA", "CUBE", "CUFF", "CULL", "CULT", "CUNY",
+ "CURB", "CURD", "CURE", "CURL", "CURT", "CUTS", "DADE", "DALE",
+ "DAME", "DANA", "DANE", "DANG", "DANK", "DARE", "DARK", "DARN",
+ "DART", "DASH", "DATA", "DATE", "DAVE", "DAVY", "DAWN", "DAYS",
+ "DEAD", "DEAF", "DEAL", "DEAN", "DEAR", "DEBT", "DECK", "DEED",
+ "DEEM", "DEER", "DEFT", "DEFY", "DELL", "DENT", "DENY", "DESK",
+ "DIAL", "DICE", "DIED", "DIET", "DIME", "DINE", "DING", "DINT",
+ "DIRE", "DIRT", "DISC", "DISH", "DISK", "DIVE", "DOCK", "DOES",
+ "DOLE", "DOLL", "DOLT", "DOME", "DONE", "DOOM", "DOOR", "DORA",
+ "DOSE", "DOTE", "DOUG", "DOUR", "DOVE", "DOWN", "DRAB", "DRAG",
+ "DRAM", "DRAW", "DREW", "DRUB", "DRUG", "DRUM", "DUAL", "DUCK",
+ "DUCT", "DUEL", "DUET", "DUKE", "DULL", "DUMB", "DUNE", "DUNK",
+ "DUSK", "DUST", "DUTY", "EACH", "EARL", "EARN", "EASE", "EAST",
+ "EASY", "EBEN", "ECHO", "EDDY", "EDEN", "EDGE", "EDGY", "EDIT",
+ "EDNA", "EGAN", "ELAN", "ELBA", "ELLA", "ELSE", "EMIL", "EMIT",
+ "EMMA", "ENDS", "ERIC", "EROS", "EVEN", "EVER", "EVIL", "EYED",
+ "FACE", "FACT", "FADE", "FAIL", "FAIN", "FAIR", "FAKE", "FALL",
+ "FAME", "FANG", "FARM", "FAST", "FATE", "FAWN", "FEAR", "FEAT",
+ "FEED", "FEEL", "FEET", "FELL", "FELT", "FEND", "FERN", "FEST",
+ "FEUD", "FIEF", "FIGS", "FILE", "FILL", "FILM", "FIND", "FINE",
+ "FINK", "FIRE", "FIRM", "FISH", "FISK", "FIST", "FITS", "FIVE",
+ "FLAG", "FLAK", "FLAM", "FLAT", "FLAW", "FLEA", "FLED", "FLEW",
+ "FLIT", "FLOC", "FLOG", "FLOW", "FLUB", "FLUE", "FOAL", "FOAM",
+ "FOGY", "FOIL", "FOLD", "FOLK", "FOND", "FONT", "FOOD", "FOOL",
+ "FOOT", "FORD", "FORE", "FORK", "FORM", "FORT", "FOSS", "FOUL",
+ "FOUR", "FOWL", "FRAU", "FRAY", "FRED", "FREE", "FRET", "FREY",
+ "FROG", "FROM", "FUEL", "FULL", "FUME", "FUND", "FUNK", "FURY",
+ "FUSE", "FUSS", "GAFF", "GAGE", "GAIL", "GAIN", "GAIT", "GALA",
+ "GALE", "GALL", "GALT", "GAME", "GANG", "GARB", "GARY", "GASH",
+ "GATE", "GAUL", "GAUR", "GAVE", "GAWK", "GEAR", "GELD", "GENE",
+ "GENT", "GERM", "GETS", "GIBE", "GIFT", "GILD", "GILL", "GILT",
+ "GINA", "GIRD", "GIRL", "GIST", "GIVE", "GLAD", "GLEE", "GLEN",
+ "GLIB", "GLOB", "GLOM", "GLOW", "GLUE", "GLUM", "GLUT", "GOAD",
+ "GOAL", "GOAT", "GOER", "GOES", "GOLD", "GOLF", "GONE", "GONG",
+ "GOOD", "GOOF", "GORE", "GORY", "GOSH", "GOUT", "GOWN", "GRAB",
+ "GRAD", "GRAY", "GREG", "GREW", "GREY", "GRID", "GRIM", "GRIN",
+ "GRIT", "GROW", "GRUB", "GULF", "GULL", "GUNK", "GURU", "GUSH",
+ "GUST", "GWEN", "GWYN", "HAAG", "HAAS", "HACK", "HAIL", "HAIR",
+ "HALE", "HALF", "HALL", "HALO", "HALT", "HAND", "HANG", "HANK",
+ "HANS", "HARD", "HARK", "HARM", "HART", "HASH", "HAST", "HATE",
+ "HATH", "HAUL", "HAVE", "HAWK", "HAYS", "HEAD", "HEAL", "HEAR",
+ "HEAT", "HEBE", "HECK", "HEED", "HEEL", "HEFT", "HELD", "HELL",
+ "HELM", "HERB", "HERD", "HERE", "HERO", "HERS", "HESS", "HEWN",
+ "HICK", "HIDE", "HIGH", "HIKE", "HILL", "HILT", "HIND", "HINT",
+ "HIRE", "HISS", "HIVE", "HOBO", "HOCK", "HOFF", "HOLD", "HOLE",
+ "HOLM", "HOLT", "HOME", "HONE", "HONK", "HOOD", "HOOF", "HOOK",
+ "HOOT", "HORN", "HOSE", "HOST", "HOUR", "HOVE", "HOWE", "HOWL",
+ "HOYT", "HUCK", "HUED", "HUFF", "HUGE", "HUGH", "HUGO", "HULK",
+ "HULL", "HUNK", "HUNT", "HURD", "HURL", "HURT", "HUSH", "HYDE",
+ "HYMN", "IBIS", "ICON", "IDEA", "IDLE", "IFFY", "INCA", "INCH",
+ "INTO", "IONS", "IOTA", "IOWA", "IRIS", "IRMA", "IRON", "ISLE",
+ "ITCH", "ITEM", "IVAN", "JACK", "JADE", "JAIL", "JAKE", "JANE",
+ "JAVA", "JEAN", "JEFF", "JERK", "JESS", "JEST", "JIBE", "JILL",
+ "JILT", "JIVE", "JOAN", "JOBS", "JOCK", "JOEL", "JOEY", "JOHN",
+ "JOIN", "JOKE", "JOLT", "JOVE", "JUDD", "JUDE", "JUDO", "JUDY",
+ "JUJU", "JUKE", "JULY", "JUNE", "JUNK", "JUNO", "JURY", "JUST",
+ "JUTE", "KAHN", "KALE", "KANE", "KANT", "KARL", "KATE", "KEEL",
+ "KEEN", "KENO", "KENT", "KERN", "KERR", "KEYS", "KICK", "KILL",
+ "KIND", "KING", "KIRK", "KISS", "KITE", "KLAN", "KNEE", "KNEW",
+ "KNIT", "KNOB", "KNOT", "KNOW", "KOCH", "KONG", "KUDO", "KURD",
+ "KURT", "KYLE", "LACE", "LACK", "LACY", "LADY", "LAID", "LAIN",
+ "LAIR", "LAKE", "LAMB", "LAME", "LAND", "LANE", "LANG", "LARD",
+ "LARK", "LASS", "LAST", "LATE", "LAUD", "LAVA", "LAWN", "LAWS",
+ "LAYS", "LEAD", "LEAF", "LEAK", "LEAN", "LEAR", "LEEK", "LEER",
+ "LEFT", "LEND", "LENS", "LENT", "LEON", "LESK", "LESS", "LEST",
+ "LETS", "LIAR", "LICE", "LICK", "LIED", "LIEN", "LIES", "LIEU",
+ "LIFE", "LIFT", "LIKE", "LILA", "LILT", "LILY", "LIMA", "LIMB",
+ "LIME", "LIND", "LINE", "LINK", "LINT", "LION", "LISA", "LIST",
+ "LIVE", "LOAD", "LOAF", "LOAM", "LOAN", "LOCK", "LOFT", "LOGE",
+ "LOIS", "LOLA", "LONE", "LONG", "LOOK", "LOON", "LOOT", "LORD",
+ "LORE", "LOSE", "LOSS", "LOST", "LOUD", "LOVE", "LOWE", "LUCK",
+ "LUCY", "LUGE", "LUKE", "LULU", "LUND", "LUNG", "LURA", "LURE",
+ "LURK", "LUSH", "LUST", "LYLE", "LYNN", "LYON", "LYRA", "MACE",
+ "MADE", "MAGI", "MAID", "MAIL", "MAIN", "MAKE", "MALE", "MALI",
+ "MALL", "MALT", "MANA", "MANN", "MANY", "MARC", "MARE", "MARK",
+ "MARS", "MART", "MARY", "MASH", "MASK", "MASS", "MAST", "MATE",
+ "MATH", "MAUL", "MAYO", "MEAD", "MEAL", "MEAN", "MEAT", "MEEK",
+ "MEET", "MELD", "MELT", "MEMO", "MEND", "MENU", "MERT", "MESH",
+ "MESS", "MICE", "MIKE", "MILD", "MILE", "MILK", "MILL", "MILT",
+ "MIMI", "MIND", "MINE", "MINI", "MINK", "MINT", "MIRE", "MISS",
+ "MIST", "MITE", "MITT", "MOAN", "MOAT", "MOCK", "MODE", "MOLD",
+ "MOLE", "MOLL", "MOLT", "MONA", "MONK", "MONT", "MOOD", "MOON",
+ "MOOR", "MOOT", "MORE", "MORN", "MORT", "MOSS", "MOST", "MOTH",
+ "MOVE", "MUCH", "MUCK", "MUDD", "MUFF", "MULE", "MULL", "MURK",
+ "MUSH", "MUST", "MUTE", "MUTT", "MYRA", "MYTH", "NAGY", "NAIL",
+ "NAIR", "NAME", "NARY", "NASH", "NAVE", "NAVY", "NEAL", "NEAR",
+ "NEAT", "NECK", "NEED", "NEIL", "NELL", "NEON", "NERO", "NESS",
+ "NEST", "NEWS", "NEWT", "NIBS", "NICE", "NICK", "NILE", "NINA",
+ "NINE", "NOAH", "NODE", "NOEL", "NOLL", "NONE", "NOOK", "NOON",
+ "NORM", "NOSE", "NOTE", "NOUN", "NOVA", "NUDE", "NULL", "NUMB",
+ "OATH", "OBEY", "OBOE", "ODIN", "OHIO", "OILY", "OINT", "OKAY",
+ "OLAF", "OLDY", "OLGA", "OLIN", "OMAN", "OMEN", "OMIT", "ONCE",
+ "ONES", "ONLY", "ONTO", "ONUS", "ORAL", "ORGY", "OSLO", "OTIS",
+ "OTTO", "OUCH", "OUST", "OUTS", "OVAL", "OVEN", "OVER", "OWLY",
+ "OWNS", "QUAD", "QUIT", "QUOD", "RACE", "RACK", "RACY", "RAFT",
+ "RAGE", "RAID", "RAIL", "RAIN", "RAKE", "RANK", "RANT", "RARE",
+ "RASH", "RATE", "RAVE", "RAYS", "READ", "REAL", "REAM", "REAR",
+ "RECK", "REED", "REEF", "REEK", "REEL", "REID", "REIN", "RENA",
+ "REND", "RENT", "REST", "RICE", "RICH", "RICK", "RIDE", "RIFT",
+ "RILL", "RIME", "RING", "RINK", "RISE", "RISK", "RITE", "ROAD",
+ "ROAM", "ROAR", "ROBE", "ROCK", "RODE", "ROIL", "ROLL", "ROME",
+ "ROOD", "ROOF", "ROOK", "ROOM", "ROOT", "ROSA", "ROSE", "ROSS",
+ "ROSY", "ROTH", "ROUT", "ROVE", "ROWE", "ROWS", "RUBE", "RUBY",
+ "RUDE", "RUDY", "RUIN", "RULE", "RUNG", "RUNS", "RUNT", "RUSE",
+ "RUSH", "RUSK", "RUSS", "RUST", "RUTH", "SACK", "SAFE", "SAGE",
+ "SAID", "SAIL", "SALE", "SALK", "SALT", "SAME", "SAND", "SANE",
+ "SANG", "SANK", "SARA", "SAUL", "SAVE", "SAYS", "SCAN", "SCAR",
+ "SCAT", "SCOT", "SEAL", "SEAM", "SEAR", "SEAT", "SEED", "SEEK",
+ "SEEM", "SEEN", "SEES", "SELF", "SELL", "SEND", "SENT", "SETS",
+ "SEWN", "SHAG", "SHAM", "SHAW", "SHAY", "SHED", "SHIM", "SHIN",
+ "SHOD", "SHOE", "SHOT", "SHOW", "SHUN", "SHUT", "SICK", "SIDE",
+ "SIFT", "SIGH", "SIGN", "SILK", "SILL", "SILO", "SILT", "SINE",
+ "SING", "SINK", "SIRE", "SITE", "SITS", "SITU", "SKAT", "SKEW",
+ "SKID", "SKIM", "SKIN", "SKIT", "SLAB", "SLAM", "SLAT", "SLAY",
+ "SLED", "SLEW", "SLID", "SLIM", "SLIT", "SLOB", "SLOG", "SLOT",
+ "SLOW", "SLUG", "SLUM", "SLUR", "SMOG", "SMUG", "SNAG", "SNOB",
+ "SNOW", "SNUB", "SNUG", "SOAK", "SOAR", "SOCK", "SODA", "SOFA",
+ "SOFT", "SOIL", "SOLD", "SOME", "SONG", "SOON", "SOOT", "SORE",
+ "SORT", "SOUL", "SOUR", "SOWN", "STAB", "STAG", "STAN", "STAR",
+ "STAY", "STEM", "STEW", "STIR", "STOW", "STUB", "STUN", "SUCH",
+ "SUDS", "SUIT", "SULK", "SUMS", "SUNG", "SUNK", "SURE", "SURF",
+ "SWAB", "SWAG", "SWAM", "SWAN", "SWAT", "SWAY", "SWIM", "SWUM",
+ "TACK", "TACT", "TAIL", "TAKE", "TALE", "TALK", "TALL", "TANK",
+ "TASK", "TATE", "TAUT", "TEAL", "TEAM", "TEAR", "TECH", "TEEM",
+ "TEEN", "TEET", "TELL", "TEND", "TENT", "TERM", "TERN", "TESS",
+ "TEST", "THAN", "THAT", "THEE", "THEM", "THEN", "THEY", "THIN",
+ "THIS", "THUD", "THUG", "TICK", "TIDE", "TIDY", "TIED", "TIER",
+ "TILE", "TILL", "TILT", "TIME", "TINA", "TINE", "TINT", "TINY",
+ "TIRE", "TOAD", "TOGO", "TOIL", "TOLD", "TOLL", "TONE", "TONG",
+ "TONY", "TOOK", "TOOL", "TOOT", "TORE", "TORN", "TOTE", "TOUR",
+ "TOUT", "TOWN", "TRAG", "TRAM", "TRAY", "TREE", "TREK", "TRIG",
+ "TRIM", "TRIO", "TROD", "TROT", "TROY", "TRUE", "TUBA", "TUBE",
+ "TUCK", "TUFT", "TUNA", "TUNE", "TUNG", "TURF", "TURN", "TUSK",
+ "TWIG", "TWIN", "TWIT", "ULAN", "UNIT", "URGE", "USED", "USER",
+ "USES", "UTAH", "VAIL", "VAIN", "VALE", "VARY", "VASE", "VAST",
+ "VEAL", "VEDA", "VEIL", "VEIN", "VEND", "VENT", "VERB", "VERY",
+ "VETO", "VICE", "VIEW", "VINE", "VISE", "VOID", "VOLT", "VOTE",
+ "WACK", "WADE", "WAGE", "WAIL", "WAIT", "WAKE", "WALE", "WALK",
+ "WALL", "WALT", "WAND", "WANE", "WANG", "WANT", "WARD", "WARM",
+ "WARN", "WART", "WASH", "WAST", "WATS", "WATT", "WAVE", "WAVY",
+ "WAYS", "WEAK", "WEAL", "WEAN", "WEAR", "WEED", "WEEK", "WEIR",
+ "WELD", "WELL", "WELT", "WENT", "WERE", "WERT", "WEST", "WHAM",
+ "WHAT", "WHEE", "WHEN", "WHET", "WHOA", "WHOM", "WICK", "WIFE",
+ "WILD", "WILL", "WIND", "WINE", "WING", "WINK", "WINO", "WIRE",
+ "WISE", "WISH", "WITH", "WOLF", "WONT", "WOOD", "WOOL", "WORD",
+ "WORE", "WORK", "WORM", "WORN", "WOVE", "WRIT", "WYNN", "YALE",
+ "YANG", "YANK", "YARD", "YARN", "YAWL", "YAWN", "YEAH", "YEAR",
+ "YELL", "YOGA", "YOKE" ]
+
+if __name__=='__main__':
+ data = [('EB33F77EE73D4053', 'TIDE ITCH SLOW REIN RULE MOT'),
+ ('CCAC2AED591056BE4F90FD441C534766',
+ 'RASH BUSH MILK LOOK BAD BRIM AVID GAFF BAIT ROT POD LOVE'),
+ ('EFF81F9BFBC65350920CDD7416DE8009',
+ 'TROD MUTE TAIL WARM CHAR KONG HAAG CITY BORE O TEAL AWL')
+ ]
+
+ for key, words in data:
+ print('Trying key', key)
+ key=binascii.a2b_hex(key)
+ w2=key_to_english(key)
+ if w2!=words:
+ print('key_to_english fails on key', repr(key), ', producing', str(w2))
+ k2=english_to_key(words)
+ if k2!=key:
+ print('english_to_key fails on key', repr(key), ', producing', repr(k2))
+
+
diff --git a/frozen_deps/Crypto/Util/__init__.py b/frozen_deps/Crypto/Util/__init__.py
new file mode 100644
index 0000000..a3bef8a
--- /dev/null
+++ b/frozen_deps/Crypto/Util/__init__.py
@@ -0,0 +1,37 @@
+# -*- coding: utf-8 -*-
+#
+# ===================================================================
+# The contents of this file are dedicated to the public domain. To
+# the extent that dedication to the public domain is not available,
+# everyone is granted a worldwide, perpetual, royalty-free,
+# non-exclusive license to exercise all rights associated with the
+# contents of this file for any purpose whatsoever.
+# No rights are reserved.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+# SOFTWARE.
+# ===================================================================
+
+"""Miscellaneous modules
+
+Contains useful modules that don't belong into any of the
+other Crypto.* subpackages.
+
+Crypto.Util.number Number-theoretic functions (primality testing, etc.)
+Crypto.Util.randpool Random number generation
+Crypto.Util.RFC1751 Converts between 128-bit keys and human-readable
+ strings of words.
+Crypto.Util.asn1 Minimal support for ASN.1 DER encoding
+
+"""
+
+__all__ = ['randpool', 'RFC1751', 'number', 'strxor', 'asn1' ]
+
+__revision__ = "$Id$"
+
diff --git a/frozen_deps/Crypto/Util/_counter.cpython-38-x86_64-linux-gnu.so b/frozen_deps/Crypto/Util/_counter.cpython-38-x86_64-linux-gnu.so
new file mode 100755
index 0000000..77cd132
--- /dev/null
+++ b/frozen_deps/Crypto/Util/_counter.cpython-38-x86_64-linux-gnu.so
Binary files differ
diff --git a/frozen_deps/Crypto/Util/_number_new.py b/frozen_deps/Crypto/Util/_number_new.py
new file mode 100644
index 0000000..5f29176
--- /dev/null
+++ b/frozen_deps/Crypto/Util/_number_new.py
@@ -0,0 +1,119 @@
+# -*- coding: ascii -*-
+#
+# Util/_number_new.py : utility functions
+#
+# Written in 2008 by Dwayne C. Litzenberger <[email protected]>
+#
+# ===================================================================
+# The contents of this file are dedicated to the public domain. To
+# the extent that dedication to the public domain is not available,
+# everyone is granted a worldwide, perpetual, royalty-free,
+# non-exclusive license to exercise all rights associated with the
+# contents of this file for any purpose whatsoever.
+# No rights are reserved.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+# SOFTWARE.
+# ===================================================================
+
+## NOTE: Do not import this module directly. Import these functions from Crypto.Util.number.
+
+__revision__ = "$Id$"
+__all__ = ['ceil_shift', 'ceil_div', 'floor_div', 'exact_log2', 'exact_div']
+
+import sys
+if sys.version_info[0] == 2 and sys.version_info[1] == 1:
+ from Crypto.Util.py21compat import *
+
+def ceil_shift(n, b):
+ """Return ceil(n / 2**b) without performing any floating-point or division operations.
+
+ This is done by right-shifting n by b bits and incrementing the result by 1
+ if any '1' bits were shifted out.
+ """
+ if not isinstance(n, int) or not isinstance(b, int):
+ raise TypeError("unsupported operand type(s): %r and %r" % (type(n).__name__, type(b).__name__))
+
+ assert n >= 0 and b >= 0 # I haven't tested or even thought about negative values
+ mask = (1 << b) - 1
+ if n & mask:
+ return (n >> b) + 1
+ else:
+ return n >> b
+
+def ceil_div(a, b):
+ """Return ceil(a / b) without performing any floating-point operations."""
+
+ if not isinstance(a, int) or not isinstance(b, int):
+ raise TypeError("unsupported operand type(s): %r and %r" % (type(a).__name__, type(b).__name__))
+
+ (q, r) = divmod(a, b)
+ if r:
+ return q + 1
+ else:
+ return q
+
+def floor_div(a, b):
+ if not isinstance(a, int) or not isinstance(b, int):
+ raise TypeError("unsupported operand type(s): %r and %r" % (type(a).__name__, type(b).__name__))
+
+ (q, r) = divmod(a, b)
+ return q
+
+def exact_log2(num):
+ """Find and return an integer i >= 0 such that num == 2**i.
+
+ If no such integer exists, this function raises ValueError.
+ """
+
+ if not isinstance(num, int):
+ raise TypeError("unsupported operand type: %r" % (type(num).__name__,))
+
+ n = int(num)
+ if n <= 0:
+ raise ValueError("cannot compute logarithm of non-positive number")
+
+ i = 0
+ while n != 0:
+ if (n & 1) and n != 1:
+ raise ValueError("No solution could be found")
+ i += 1
+ n >>= 1
+ i -= 1
+
+ assert num == (1 << i)
+ return i
+
+def exact_div(p, d, allow_divzero=False):
+ """Find and return an integer n such that p == n * d
+
+ If no such integer exists, this function raises ValueError.
+
+ Both operands must be integers.
+
+ If the second operand is zero, this function will raise ZeroDivisionError
+ unless allow_divzero is true (default: False).
+ """
+
+ if not isinstance(p, int) or not isinstance(d, int):
+ raise TypeError("unsupported operand type(s): %r and %r" % (type(p).__name__, type(d).__name__))
+
+ if d == 0 and allow_divzero:
+ n = 0
+ if p != n * d:
+ raise ValueError("No solution could be found")
+ else:
+ (n, r) = divmod(p, d)
+ if r != 0:
+ raise ValueError("No solution could be found")
+
+ assert p == n * d
+ return n
+
+# vim:set ts=4 sw=4 sts=4 expandtab:
diff --git a/frozen_deps/Crypto/Util/asn1.py b/frozen_deps/Crypto/Util/asn1.py
new file mode 100644
index 0000000..9a97d97
--- /dev/null
+++ b/frozen_deps/Crypto/Util/asn1.py
@@ -0,0 +1,286 @@
+# -*- coding: ascii -*-
+#
+# Util/asn1.py : Minimal support for ASN.1 DER binary encoding.
+#
+# ===================================================================
+# The contents of this file are dedicated to the public domain. To
+# the extent that dedication to the public domain is not available,
+# everyone is granted a worldwide, perpetual, royalty-free,
+# non-exclusive license to exercise all rights associated with the
+# contents of this file for any purpose whatsoever.
+# No rights are reserved.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+# SOFTWARE.
+# ===================================================================
+
+from Crypto.Util.number import long_to_bytes, bytes_to_long
+import sys
+from Crypto.Util.py3compat import *
+
+__all__ = [ 'DerObject', 'DerInteger', 'DerOctetString', 'DerNull', 'DerSequence', 'DerObjectId' ]
+
+class DerObject:
+ """Base class for defining a single DER object.
+
+ Instantiate this class ONLY when you have to decode a DER element.
+ """
+
+ # Known TAG types
+ typeTags = { 'SEQUENCE': 0x30, 'BIT STRING': 0x03, 'INTEGER': 0x02,
+ 'OCTET STRING': 0x04, 'NULL': 0x05, 'OBJECT IDENTIFIER': 0x06 }
+
+ def __init__(self, ASN1Type=None, payload=b('')):
+ """Initialize the DER object according to a specific type.
+
+ The ASN.1 type is either specified as the ASN.1 string (e.g.
+ 'SEQUENCE'), directly with its numerical tag or with no tag
+ at all (None)."""
+ if isInt(ASN1Type) or ASN1Type is None:
+ self.typeTag = ASN1Type
+ else:
+ if len(ASN1Type)==1:
+ self.typeTag = ord(ASN1Type)
+ else:
+ self.typeTag = self.typeTags.get(ASN1Type)
+ self.payload = payload
+
+ def isType(self, ASN1Type):
+ return self.typeTags[ASN1Type]==self.typeTag
+
+ def _lengthOctets(self, payloadLen):
+ """Return a byte string that encodes the given payload length (in
+ bytes) in a format suitable for a DER length tag (L).
+ """
+ if payloadLen>127:
+ encoding = long_to_bytes(payloadLen)
+ return bchr(len(encoding)+128) + encoding
+ return bchr(payloadLen)
+
+ def encode(self):
+ """Return a complete DER element, fully encoded as a TLV."""
+ return bchr(self.typeTag) + self._lengthOctets(len(self.payload)) + self.payload
+
+ def _decodeLen(self, idx, der):
+ """Given a (part of a) DER element, and an index to the first byte of
+ a DER length tag (L), return a tuple with the payload size,
+ and the index of the first byte of the such payload (V).
+
+ Raises a ValueError exception if the DER length is invalid.
+ Raises an IndexError exception if the DER element is too short.
+ """
+ length = bord(der[idx])
+ if length<=127:
+ return (length,idx+1)
+ payloadLength = bytes_to_long(der[idx+1:idx+1+(length & 0x7F)])
+ if payloadLength<=127:
+ raise ValueError("Not a DER length tag.")
+ return (payloadLength, idx+1+(length & 0x7F))
+
+ def decode(self, derEle, noLeftOvers=0):
+ """Decode a complete DER element, and re-initializes this
+ object with it.
+
+ @param derEle A complete DER element. It must start with a DER T
+ tag.
+ @param noLeftOvers Indicate whether it is acceptable to complete the
+ parsing of the DER element and find that not all
+ bytes in derEle have been used.
+ @return Index of the first unused byte in the given DER element.
+
+ Raises a ValueError exception in case of parsing errors.
+ Raises an IndexError exception if the DER element is too short.
+ """
+ try:
+ self.typeTag = bord(derEle[0])
+ if (self.typeTag & 0x1F)==0x1F:
+ raise ValueError("Unsupported DER tag")
+ (length,idx) = self._decodeLen(1, derEle)
+ if noLeftOvers and len(derEle) != (idx+length):
+ raise ValueError("Not a DER structure")
+ self.payload = derEle[idx:idx+length]
+ except IndexError:
+ raise ValueError("Not a valid DER SEQUENCE.")
+ return idx+length
+
+class DerInteger(DerObject):
+ def __init__(self, value = 0):
+ """Class to model an INTEGER DER element.
+
+ Limitation: only non-negative values are supported.
+ """
+ DerObject.__init__(self, 'INTEGER')
+ self.value = value
+
+ def encode(self):
+ """Return a complete INTEGER DER element, fully encoded as a TLV."""
+ self.payload = long_to_bytes(self.value)
+ if bord(self.payload[0])>127:
+ self.payload = bchr(0x00) + self.payload
+ return DerObject.encode(self)
+
+ def decode(self, derEle, noLeftOvers=0):
+ """Decode a complete INTEGER DER element, and re-initializes this
+ object with it.
+
+ @param derEle A complete INTEGER DER element. It must start with a DER
+ INTEGER tag.
+ @param noLeftOvers Indicate whether it is acceptable to complete the
+ parsing of the DER element and find that not all
+ bytes in derEle have been used.
+ @return Index of the first unused byte in the given DER element.
+
+ Raises a ValueError exception if the DER element is not a
+ valid non-negative INTEGER.
+ Raises an IndexError exception if the DER element is too short.
+ """
+ tlvLength = DerObject.decode(self, derEle, noLeftOvers)
+ if self.typeTag!=self.typeTags['INTEGER']:
+ raise ValueError ("Not a DER INTEGER.")
+ if bord(self.payload[0])>127:
+ raise ValueError ("Negative INTEGER.")
+ self.value = bytes_to_long(self.payload)
+ return tlvLength
+
+class DerSequence(DerObject):
+ """Class to model a SEQUENCE DER element.
+
+ This object behave like a dynamic Python sequence.
+ Sub-elements that are INTEGERs, look like Python integers.
+ Any other sub-element is a binary string encoded as the complete DER
+ sub-element (TLV).
+ """
+
+ def __init__(self, startSeq=None):
+ """Initialize the SEQUENCE DER object. Always empty
+ initially."""
+ DerObject.__init__(self, 'SEQUENCE')
+ if startSeq==None:
+ self._seq = []
+ else:
+ self._seq = startSeq
+
+ ## A few methods to make it behave like a python sequence
+
+ def __delitem__(self, n):
+ del self._seq[n]
+ def __getitem__(self, n):
+ return self._seq[n]
+ def __setitem__(self, key, value):
+ self._seq[key] = value
+ def __setslice__(self,i,j,sequence):
+ self._seq[i:j] = sequence
+ def __delslice__(self,i,j):
+ del self._seq[i:j]
+ def __getslice__(self, i, j):
+ return self._seq[max(0, i):max(0, j)]
+ def __len__(self):
+ return len(self._seq)
+ def append(self, item):
+ return self._seq.append(item)
+
+ def hasInts(self):
+ """Return the number of items in this sequence that are numbers."""
+ return len(list(filter(isInt, self._seq)))
+
+ def hasOnlyInts(self):
+ """Return True if all items in this sequence are numbers."""
+ return self._seq and self.hasInts()==len(self._seq)
+
+ def encode(self):
+ """Return the DER encoding for the ASN.1 SEQUENCE, containing
+ the non-negative integers and longs added to this object.
+
+ Limitation: Raises a ValueError exception if it some elements
+ in the sequence are neither Python integers nor complete DER INTEGERs.
+ """
+ self.payload = b('')
+ for item in self._seq:
+ try:
+ self.payload += item
+ except:
+ try:
+ self.payload += DerInteger(item).encode()
+ except:
+ raise ValueError("Trying to DER encode an unknown object")
+ return DerObject.encode(self)
+
+ def decode(self, derEle, noLeftOvers=0):
+ """Decode a complete SEQUENCE DER element, and re-initializes this
+ object with it.
+
+ @param derEle A complete SEQUENCE DER element. It must start with a DER
+ SEQUENCE tag.
+ @param noLeftOvers Indicate whether it is acceptable to complete the
+ parsing of the DER element and find that not all
+ bytes in derEle have been used.
+ @return Index of the first unused byte in the given DER element.
+
+ DER INTEGERs are decoded into Python integers. Any other DER
+ element is not decoded. Its validity is not checked.
+
+ Raises a ValueError exception if the DER element is not a
+ valid DER SEQUENCE.
+ Raises an IndexError exception if the DER element is too short.
+ """
+
+ self._seq = []
+ try:
+ tlvLength = DerObject.decode(self, derEle, noLeftOvers)
+ if self.typeTag!=self.typeTags['SEQUENCE']:
+ raise ValueError("Not a DER SEQUENCE.")
+ # Scan one TLV at once
+ idx = 0
+ while idx<len(self.payload):
+ typeTag = bord(self.payload[idx])
+ if typeTag==self.typeTags['INTEGER']:
+ newInteger = DerInteger()
+ idx += newInteger.decode(self.payload[idx:])
+ self._seq.append(newInteger.value)
+ else:
+ itemLen,itemIdx = self._decodeLen(idx+1,self.payload)
+ self._seq.append(self.payload[idx:itemIdx+itemLen])
+ idx = itemIdx + itemLen
+ except IndexError:
+ raise ValueError("Not a valid DER SEQUENCE.")
+ return tlvLength
+
+class DerOctetString(DerObject):
+ def __init__(self, value = b('')):
+ DerObject.__init__(self, 'OCTET STRING')
+ self.payload = value
+
+ def decode(self, derEle, noLeftOvers=0):
+ p = DerObject.decode(derEle, noLeftOvers)
+ if not self.isType("OCTET STRING"):
+ raise ValueError("Not a valid OCTET STRING.")
+ return p
+
+class DerNull(DerObject):
+ def __init__(self):
+ DerObject.__init__(self, 'NULL')
+
+class DerObjectId(DerObject):
+ def __init__(self):
+ DerObject.__init__(self, 'OBJECT IDENTIFIER')
+
+ def decode(self, derEle, noLeftOvers=0):
+ p = DerObject.decode(derEle, noLeftOvers)
+ if not self.isType("OBJECT IDENTIFIER"):
+ raise ValueError("Not a valid OBJECT IDENTIFIER.")
+ return p
+
+def isInt(x):
+ test = 0
+ try:
+ test += x
+ except TypeError:
+ return 0
+ return 1
+
diff --git a/frozen_deps/Crypto/Util/number.py b/frozen_deps/Crypto/Util/number.py
new file mode 100644
index 0000000..0e1baa0
--- /dev/null
+++ b/frozen_deps/Crypto/Util/number.py
@@ -0,0 +1,1456 @@
+#
+# number.py : Number-theoretic functions
+#
+# Part of the Python Cryptography Toolkit
+#
+# Written by Andrew M. Kuchling, Barry A. Warsaw, and others
+#
+# ===================================================================
+# The contents of this file are dedicated to the public domain. To
+# the extent that dedication to the public domain is not available,
+# everyone is granted a worldwide, perpetual, royalty-free,
+# non-exclusive license to exercise all rights associated with the
+# contents of this file for any purpose whatsoever.
+# No rights are reserved.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+# SOFTWARE.
+# ===================================================================
+#
+
+__revision__ = "$Id$"
+
+from Crypto.pct_warnings import GetRandomNumber_DeprecationWarning, PowmInsecureWarning
+from warnings import warn as _warn
+import math
+import sys
+from Crypto.Util.py3compat import *
+
+bignum = int
+try:
+ from Crypto.PublicKey import _fastmath
+except ImportError:
+ # For production, we are going to let import issues due to gmp/mpir shared
+ # libraries not loading slide silently and use slowmath. If you'd rather
+ # see an exception raised if _fastmath exists but cannot be imported,
+ # uncomment the below
+ #
+ # from distutils.sysconfig import get_config_var
+ # import inspect, os
+ # _fm_path = os.path.normpath(os.path.dirname(os.path.abspath(
+ # inspect.getfile(inspect.currentframe())))
+ # +"/../../PublicKey/_fastmath"+get_config_var("SO"))
+ # if os.path.exists(_fm_path):
+ # raise ImportError("While the _fastmath module exists, importing "+
+ # "it failed. This may point to the gmp or mpir shared library "+
+ # "not being in the path. _fastmath was found at "+_fm_path)
+ _fastmath = None
+
+# You need libgmp v5 or later to get mpz_powm_sec. Warn if it's not available.
+if _fastmath is not None and not _fastmath.HAVE_DECL_MPZ_POWM_SEC:
+ _warn("Not using mpz_powm_sec. You should rebuild using libgmp >= 5 to avoid timing attack vulnerability.", PowmInsecureWarning)
+
+# New functions
+from ._number_new import *
+
+# Commented out and replaced with faster versions below
+## def long2str(n):
+## s=''
+## while n>0:
+## s=chr(n & 255)+s
+## n=n>>8
+## return s
+
+## import types
+## def str2long(s):
+## if type(s)!=types.StringType: return s # Integers will be left alone
+## return reduce(lambda x,y : x*256+ord(y), s, 0L)
+
+def size (N):
+ """size(N:long) : int
+ Returns the size of the number N in bits.
+ """
+ bits = 0
+ while N >> bits:
+ bits += 1
+ return bits
+
+def getRandomNumber(N, randfunc=None):
+ """Deprecated. Use getRandomInteger or getRandomNBitInteger instead."""
+ warnings.warn("Crypto.Util.number.getRandomNumber has confusing semantics"+
+ "and has been deprecated. Use getRandomInteger or getRandomNBitInteger instead.",
+ GetRandomNumber_DeprecationWarning)
+ return getRandomNBitInteger(N, randfunc)
+
+def getRandomInteger(N, randfunc=None):
+ """getRandomInteger(N:int, randfunc:callable):long
+ Return a random number with at most N bits.
+
+ If randfunc is omitted, then Random.new().read is used.
+
+ This function is for internal use only and may be renamed or removed in
+ the future.
+ """
+ if randfunc is None:
+ _import_Random()
+ randfunc = Random.new().read
+
+ S = randfunc(N>>3)
+ odd_bits = N % 8
+ if odd_bits != 0:
+ char = ord(randfunc(1)) >> (8-odd_bits)
+ S = bchr(char) + S
+ value = bytes_to_long(S)
+ return value
+
+def getRandomRange(a, b, randfunc=None):
+ """getRandomRange(a:int, b:int, randfunc:callable):long
+ Return a random number n so that a <= n < b.
+
+ If randfunc is omitted, then Random.new().read is used.
+
+ This function is for internal use only and may be renamed or removed in
+ the future.
+ """
+ range_ = b - a - 1
+ bits = size(range_)
+ value = getRandomInteger(bits, randfunc)
+ while value > range_:
+ value = getRandomInteger(bits, randfunc)
+ return a + value
+
+def getRandomNBitInteger(N, randfunc=None):
+ """getRandomInteger(N:int, randfunc:callable):long
+ Return a random number with exactly N-bits, i.e. a random number
+ between 2**(N-1) and (2**N)-1.
+
+ If randfunc is omitted, then Random.new().read is used.
+
+ This function is for internal use only and may be renamed or removed in
+ the future.
+ """
+ value = getRandomInteger (N-1, randfunc)
+ value |= 2 ** (N-1) # Ensure high bit is set
+ assert size(value) >= N
+ return value
+
+def GCD(x,y):
+ """GCD(x:long, y:long): long
+ Return the GCD of x and y.
+ """
+ x = abs(x) ; y = abs(y)
+ while x > 0:
+ x, y = y % x, x
+ return y
+
+def inverse(u, v):
+ """inverse(u:long, v:long):long
+ Return the inverse of u mod v.
+ """
+ u3, v3 = int(u), int(v)
+ u1, v1 = 1, 0
+ while v3 > 0:
+ q=divmod(u3, v3)[0]
+ u1, v1 = v1, u1 - v1*q
+ u3, v3 = v3, u3 - v3*q
+ while u1<0:
+ u1 = u1 + v
+ return u1
+
+# Given a number of bits to generate and a random generation function,
+# find a prime number of the appropriate size.
+
+def getPrime(N, randfunc=None):
+ """getPrime(N:int, randfunc:callable):long
+ Return a random N-bit prime number.
+
+ If randfunc is omitted, then Random.new().read is used.
+ """
+ if randfunc is None:
+ _import_Random()
+ randfunc = Random.new().read
+
+ number=getRandomNBitInteger(N, randfunc) | 1
+ while (not isPrime(number, randfunc=randfunc)):
+ number=number+2
+ return number
+
+
+def _rabinMillerTest(n, rounds, randfunc=None):
+ """_rabinMillerTest(n:long, rounds:int, randfunc:callable):int
+ Tests if n is prime.
+ Returns 0 when n is definitly composite.
+ Returns 1 when n is probably prime.
+ Returns 2 when n is definitly prime.
+
+ If randfunc is omitted, then Random.new().read is used.
+
+ This function is for internal use only and may be renamed or removed in
+ the future.
+ """
+ # check special cases (n==2, n even, n < 2)
+ if n < 3 or (n & 1) == 0:
+ return n == 2
+ # n might be very large so it might be beneficial to precalculate n-1
+ n_1 = n - 1
+ # determine m and b so that 2**b * m = n - 1 and b maximal
+ b = 0
+ m = n_1
+ while (m & 1) == 0:
+ b += 1
+ m >>= 1
+
+ tested = []
+ # we need to do at most n-2 rounds.
+ for i in range (min (rounds, n-2)):
+ # randomly choose a < n and make sure it hasn't been tested yet
+ a = getRandomRange (2, n, randfunc)
+ while a in tested:
+ a = getRandomRange (2, n, randfunc)
+ tested.append (a)
+ # do the rabin-miller test
+ z = pow (a, m, n) # (a**m) % n
+ if z == 1 or z == n_1:
+ continue
+ composite = 1
+ for r in range (b):
+ z = (z * z) % n
+ if z == 1:
+ return 0
+ elif z == n_1:
+ composite = 0
+ break
+ if composite:
+ return 0
+ return 1
+
+def getStrongPrime(N, e=0, false_positive_prob=1e-6, randfunc=None):
+ """getStrongPrime(N:int, e:int, false_positive_prob:float, randfunc:callable):long
+ Return a random strong N-bit prime number.
+ In this context p is a strong prime if p-1 and p+1 have at
+ least one large prime factor.
+ N should be a multiple of 128 and > 512.
+
+ If e is provided the returned prime p-1 will be coprime to e
+ and thus suitable for RSA where e is the public exponent.
+
+ The optional false_positive_prob is the statistical probability
+ that true is returned even though it is not (pseudo-prime).
+ It defaults to 1e-6 (less than 1:1000000).
+ Note that the real probability of a false-positive is far less. This is
+ just the mathematically provable limit.
+
+ randfunc should take a single int parameter and return that
+ many random bytes as a string.
+ If randfunc is omitted, then Random.new().read is used.
+ """
+ # This function was implemented following the
+ # instructions found in the paper:
+ # "FAST GENERATION OF RANDOM, STRONG RSA PRIMES"
+ # by Robert D. Silverman
+ # RSA Laboratories
+ # May 17, 1997
+ # which by the time of writing could be freely downloaded here:
+ # http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.17.2713&rep=rep1&type=pdf
+
+ # Use the accelerator if available
+ if _fastmath is not None:
+ return _fastmath.getStrongPrime(int(N), int(e), false_positive_prob,
+ randfunc)
+
+ if (N < 512) or ((N % 128) != 0):
+ raise ValueError ("bits must be multiple of 128 and > 512")
+
+ rabin_miller_rounds = int(math.ceil(-math.log(false_positive_prob)/math.log(4)))
+
+ # calculate range for X
+ # lower_bound = sqrt(2) * 2^{511 + 128*x}
+ # upper_bound = 2^{512 + 128*x} - 1
+ x = (N - 512) >> 7;
+ # We need to approximate the sqrt(2) in the lower_bound by an integer
+ # expression because floating point math overflows with these numbers
+ lower_bound = divmod(14142135623730950489 * (2 ** (511 + 128*x)),
+ 10000000000000000000)[0]
+ upper_bound = (1 << (512 + 128*x)) - 1
+ # Randomly choose X in calculated range
+ X = getRandomRange (lower_bound, upper_bound, randfunc)
+
+ # generate p1 and p2
+ p = [0, 0]
+ for i in (0, 1):
+ # randomly choose 101-bit y
+ y = getRandomNBitInteger (101, randfunc)
+ # initialize the field for sieving
+ field = [0] * 5 * len (sieve_base)
+ # sieve the field
+ for prime in sieve_base:
+ offset = y % prime
+ for j in range ((prime - offset) % prime, len (field), prime):
+ field[j] = 1
+
+ # look for suitable p[i] starting at y
+ result = 0
+ for j in range(len(field)):
+ composite = field[j]
+ # look for next canidate
+ if composite:
+ continue
+ tmp = y + j
+ result = _rabinMillerTest (tmp, rabin_miller_rounds)
+ if result > 0:
+ p[i] = tmp
+ break
+ if result == 0:
+ raise RuntimeError ("Couln't find prime in field. "
+ "Developer: Increase field_size")
+
+ # Calculate R
+ # R = (p2^{-1} mod p1) * p2 - (p1^{-1} mod p2) * p1
+ tmp1 = inverse (p[1], p[0]) * p[1] # (p2^-1 mod p1)*p2
+ tmp2 = inverse (p[0], p[1]) * p[0] # (p1^-1 mod p2)*p1
+ R = tmp1 - tmp2 # (p2^-1 mod p1)*p2 - (p1^-1 mod p2)*p1
+
+ # search for final prime number starting by Y0
+ # Y0 = X + (R - X mod p1p2)
+ increment = p[0] * p[1]
+ X = X + (R - (X % increment))
+ while 1:
+ is_possible_prime = 1
+ # first check candidate against sieve_base
+ for prime in sieve_base:
+ if (X % prime) == 0:
+ is_possible_prime = 0
+ break
+ # if e is given make sure that e and X-1 are coprime
+ # this is not necessarily a strong prime criterion but useful when
+ # creating them for RSA where the p-1 and q-1 should be coprime to
+ # the public exponent e
+ if e and is_possible_prime:
+ if e & 1:
+ if GCD (e, X-1) != 1:
+ is_possible_prime = 0
+ else:
+ if GCD (e, divmod((X-1),2)[0]) != 1:
+ is_possible_prime = 0
+
+ # do some Rabin-Miller-Tests
+ if is_possible_prime:
+ result = _rabinMillerTest (X, rabin_miller_rounds)
+ if result > 0:
+ break
+ X += increment
+ # abort when X has more bits than requested
+ # TODO: maybe we shouldn't abort but rather start over.
+ if X >= 1 << N:
+ raise RuntimeError ("Couln't find prime in field. "
+ "Developer: Increase field_size")
+ return X
+
+def isPrime(N, false_positive_prob=1e-6, randfunc=None):
+ """isPrime(N:long, false_positive_prob:float, randfunc:callable):bool
+ Return true if N is prime.
+
+ The optional false_positive_prob is the statistical probability
+ that true is returned even though it is not (pseudo-prime).
+ It defaults to 1e-6 (less than 1:1000000).
+ Note that the real probability of a false-positive is far less. This is
+ just the mathematically provable limit.
+
+ If randfunc is omitted, then Random.new().read is used.
+ """
+ if _fastmath is not None:
+ return _fastmath.isPrime(int(N), false_positive_prob, randfunc)
+
+ if N < 3 or N & 1 == 0:
+ return N == 2
+ for p in sieve_base:
+ if N == p:
+ return 1
+ if N % p == 0:
+ return 0
+
+ rounds = int(math.ceil(-math.log(false_positive_prob)/math.log(4)))
+ return _rabinMillerTest(N, rounds, randfunc)
+
+
+# Improved conversion functions contributed by Barry Warsaw, after
+# careful benchmarking
+
+import struct
+
+def long_to_bytes(n, blocksize=0):
+ """long_to_bytes(n:long, blocksize:int) : string
+ Convert a long integer to a byte string.
+
+ If optional blocksize is given and greater than zero, pad the front of the
+ byte string with binary zeros so that the length is a multiple of
+ blocksize.
+ """
+ # after much testing, this algorithm was deemed to be the fastest
+ s = b('')
+ n = int(n)
+ pack = struct.pack
+ while n > 0:
+ s = pack('>I', n & 0xffffffff) + s
+ n = n >> 32
+ # strip off leading zeros
+ for i in range(len(s)):
+ if s[i] != b('\000')[0]:
+ break
+ else:
+ # only happens when n == 0
+ s = b('\000')
+ i = 0
+ s = s[i:]
+ # add back some pad bytes. this could be done more efficiently w.r.t. the
+ # de-padding being done above, but sigh...
+ if blocksize > 0 and len(s) % blocksize:
+ s = (blocksize - len(s) % blocksize) * b('\000') + s
+ return s
+
+def bytes_to_long(s):
+ """bytes_to_long(string) : long
+ Convert a byte string to a long integer.
+
+ This is (essentially) the inverse of long_to_bytes().
+ """
+ acc = 0
+ unpack = struct.unpack
+ length = len(s)
+ if length % 4:
+ extra = (4 - length % 4)
+ s = b('\000') * extra + s
+ length = length + extra
+ for i in range(0, length, 4):
+ acc = (acc << 32) + unpack('>I', s[i:i+4])[0]
+ return acc
+
+# For backwards compatibility...
+import warnings
+def long2str(n, blocksize=0):
+ warnings.warn("long2str() has been replaced by long_to_bytes()")
+ return long_to_bytes(n, blocksize)
+def str2long(s):
+ warnings.warn("str2long() has been replaced by bytes_to_long()")
+ return bytes_to_long(s)
+
+def _import_Random():
+ # This is called in a function instead of at the module level in order to
+ # avoid problems with recursive imports
+ global Random, StrongRandom
+ from Crypto import Random
+ from Crypto.Random.random import StrongRandom
+
+
+
+# The first 10000 primes used for checking primality.
+# This should be enough to eliminate most of the odd
+# numbers before needing to do a Rabin-Miller test at all.
+sieve_base = (
+ 2, 3, 5, 7, 11, 13, 17, 19, 23, 29,
+ 31, 37, 41, 43, 47, 53, 59, 61, 67, 71,
+ 73, 79, 83, 89, 97, 101, 103, 107, 109, 113,
+ 127, 131, 137, 139, 149, 151, 157, 163, 167, 173,
+ 179, 181, 191, 193, 197, 199, 211, 223, 227, 229,
+ 233, 239, 241, 251, 257, 263, 269, 271, 277, 281,
+ 283, 293, 307, 311, 313, 317, 331, 337, 347, 349,
+ 353, 359, 367, 373, 379, 383, 389, 397, 401, 409,
+ 419, 421, 431, 433, 439, 443, 449, 457, 461, 463,
+ 467, 479, 487, 491, 499, 503, 509, 521, 523, 541,
+ 547, 557, 563, 569, 571, 577, 587, 593, 599, 601,
+ 607, 613, 617, 619, 631, 641, 643, 647, 653, 659,
+ 661, 673, 677, 683, 691, 701, 709, 719, 727, 733,
+ 739, 743, 751, 757, 761, 769, 773, 787, 797, 809,
+ 811, 821, 823, 827, 829, 839, 853, 857, 859, 863,
+ 877, 881, 883, 887, 907, 911, 919, 929, 937, 941,
+ 947, 953, 967, 971, 977, 983, 991, 997, 1009, 1013,
+ 1019, 1021, 1031, 1033, 1039, 1049, 1051, 1061, 1063, 1069,
+ 1087, 1091, 1093, 1097, 1103, 1109, 1117, 1123, 1129, 1151,
+ 1153, 1163, 1171, 1181, 1187, 1193, 1201, 1213, 1217, 1223,
+ 1229, 1231, 1237, 1249, 1259, 1277, 1279, 1283, 1289, 1291,
+ 1297, 1301, 1303, 1307, 1319, 1321, 1327, 1361, 1367, 1373,
+ 1381, 1399, 1409, 1423, 1427, 1429, 1433, 1439, 1447, 1451,
+ 1453, 1459, 1471, 1481, 1483, 1487, 1489, 1493, 1499, 1511,
+ 1523, 1531, 1543, 1549, 1553, 1559, 1567, 1571, 1579, 1583,
+ 1597, 1601, 1607, 1609, 1613, 1619, 1621, 1627, 1637, 1657,
+ 1663, 1667, 1669, 1693, 1697, 1699, 1709, 1721, 1723, 1733,
+ 1741, 1747, 1753, 1759, 1777, 1783, 1787, 1789, 1801, 1811,
+ 1823, 1831, 1847, 1861, 1867, 1871, 1873, 1877, 1879, 1889,
+ 1901, 1907, 1913, 1931, 1933, 1949, 1951, 1973, 1979, 1987,
+ 1993, 1997, 1999, 2003, 2011, 2017, 2027, 2029, 2039, 2053,
+ 2063, 2069, 2081, 2083, 2087, 2089, 2099, 2111, 2113, 2129,
+ 2131, 2137, 2141, 2143, 2153, 2161, 2179, 2203, 2207, 2213,
+ 2221, 2237, 2239, 2243, 2251, 2267, 2269, 2273, 2281, 2287,
+ 2293, 2297, 2309, 2311, 2333, 2339, 2341, 2347, 2351, 2357,
+ 2371, 2377, 2381, 2383, 2389, 2393, 2399, 2411, 2417, 2423,
+ 2437, 2441, 2447, 2459, 2467, 2473, 2477, 2503, 2521, 2531,
+ 2539, 2543, 2549, 2551, 2557, 2579, 2591, 2593, 2609, 2617,
+ 2621, 2633, 2647, 2657, 2659, 2663, 2671, 2677, 2683, 2687,
+ 2689, 2693, 2699, 2707, 2711, 2713, 2719, 2729, 2731, 2741,
+ 2749, 2753, 2767, 2777, 2789, 2791, 2797, 2801, 2803, 2819,
+ 2833, 2837, 2843, 2851, 2857, 2861, 2879, 2887, 2897, 2903,
+ 2909, 2917, 2927, 2939, 2953, 2957, 2963, 2969, 2971, 2999,
+ 3001, 3011, 3019, 3023, 3037, 3041, 3049, 3061, 3067, 3079,
+ 3083, 3089, 3109, 3119, 3121, 3137, 3163, 3167, 3169, 3181,
+ 3187, 3191, 3203, 3209, 3217, 3221, 3229, 3251, 3253, 3257,
+ 3259, 3271, 3299, 3301, 3307, 3313, 3319, 3323, 3329, 3331,
+ 3343, 3347, 3359, 3361, 3371, 3373, 3389, 3391, 3407, 3413,
+ 3433, 3449, 3457, 3461, 3463, 3467, 3469, 3491, 3499, 3511,
+ 3517, 3527, 3529, 3533, 3539, 3541, 3547, 3557, 3559, 3571,
+ 3581, 3583, 3593, 3607, 3613, 3617, 3623, 3631, 3637, 3643,
+ 3659, 3671, 3673, 3677, 3691, 3697, 3701, 3709, 3719, 3727,
+ 3733, 3739, 3761, 3767, 3769, 3779, 3793, 3797, 3803, 3821,
+ 3823, 3833, 3847, 3851, 3853, 3863, 3877, 3881, 3889, 3907,
+ 3911, 3917, 3919, 3923, 3929, 3931, 3943, 3947, 3967, 3989,
+ 4001, 4003, 4007, 4013, 4019, 4021, 4027, 4049, 4051, 4057,
+ 4073, 4079, 4091, 4093, 4099, 4111, 4127, 4129, 4133, 4139,
+ 4153, 4157, 4159, 4177, 4201, 4211, 4217, 4219, 4229, 4231,
+ 4241, 4243, 4253, 4259, 4261, 4271, 4273, 4283, 4289, 4297,
+ 4327, 4337, 4339, 4349, 4357, 4363, 4373, 4391, 4397, 4409,
+ 4421, 4423, 4441, 4447, 4451, 4457, 4463, 4481, 4483, 4493,
+ 4507, 4513, 4517, 4519, 4523, 4547, 4549, 4561, 4567, 4583,
+ 4591, 4597, 4603, 4621, 4637, 4639, 4643, 4649, 4651, 4657,
+ 4663, 4673, 4679, 4691, 4703, 4721, 4723, 4729, 4733, 4751,
+ 4759, 4783, 4787, 4789, 4793, 4799, 4801, 4813, 4817, 4831,
+ 4861, 4871, 4877, 4889, 4903, 4909, 4919, 4931, 4933, 4937,
+ 4943, 4951, 4957, 4967, 4969, 4973, 4987, 4993, 4999, 5003,
+ 5009, 5011, 5021, 5023, 5039, 5051, 5059, 5077, 5081, 5087,
+ 5099, 5101, 5107, 5113, 5119, 5147, 5153, 5167, 5171, 5179,
+ 5189, 5197, 5209, 5227, 5231, 5233, 5237, 5261, 5273, 5279,
+ 5281, 5297, 5303, 5309, 5323, 5333, 5347, 5351, 5381, 5387,
+ 5393, 5399, 5407, 5413, 5417, 5419, 5431, 5437, 5441, 5443,
+ 5449, 5471, 5477, 5479, 5483, 5501, 5503, 5507, 5519, 5521,
+ 5527, 5531, 5557, 5563, 5569, 5573, 5581, 5591, 5623, 5639,
+ 5641, 5647, 5651, 5653, 5657, 5659, 5669, 5683, 5689, 5693,
+ 5701, 5711, 5717, 5737, 5741, 5743, 5749, 5779, 5783, 5791,
+ 5801, 5807, 5813, 5821, 5827, 5839, 5843, 5849, 5851, 5857,
+ 5861, 5867, 5869, 5879, 5881, 5897, 5903, 5923, 5927, 5939,
+ 5953, 5981, 5987, 6007, 6011, 6029, 6037, 6043, 6047, 6053,
+ 6067, 6073, 6079, 6089, 6091, 6101, 6113, 6121, 6131, 6133,
+ 6143, 6151, 6163, 6173, 6197, 6199, 6203, 6211, 6217, 6221,
+ 6229, 6247, 6257, 6263, 6269, 6271, 6277, 6287, 6299, 6301,
+ 6311, 6317, 6323, 6329, 6337, 6343, 6353, 6359, 6361, 6367,
+ 6373, 6379, 6389, 6397, 6421, 6427, 6449, 6451, 6469, 6473,
+ 6481, 6491, 6521, 6529, 6547, 6551, 6553, 6563, 6569, 6571,
+ 6577, 6581, 6599, 6607, 6619, 6637, 6653, 6659, 6661, 6673,
+ 6679, 6689, 6691, 6701, 6703, 6709, 6719, 6733, 6737, 6761,
+ 6763, 6779, 6781, 6791, 6793, 6803, 6823, 6827, 6829, 6833,
+ 6841, 6857, 6863, 6869, 6871, 6883, 6899, 6907, 6911, 6917,
+ 6947, 6949, 6959, 6961, 6967, 6971, 6977, 6983, 6991, 6997,
+ 7001, 7013, 7019, 7027, 7039, 7043, 7057, 7069, 7079, 7103,
+ 7109, 7121, 7127, 7129, 7151, 7159, 7177, 7187, 7193, 7207,
+ 7211, 7213, 7219, 7229, 7237, 7243, 7247, 7253, 7283, 7297,
+ 7307, 7309, 7321, 7331, 7333, 7349, 7351, 7369, 7393, 7411,
+ 7417, 7433, 7451, 7457, 7459, 7477, 7481, 7487, 7489, 7499,
+ 7507, 7517, 7523, 7529, 7537, 7541, 7547, 7549, 7559, 7561,
+ 7573, 7577, 7583, 7589, 7591, 7603, 7607, 7621, 7639, 7643,
+ 7649, 7669, 7673, 7681, 7687, 7691, 7699, 7703, 7717, 7723,
+ 7727, 7741, 7753, 7757, 7759, 7789, 7793, 7817, 7823, 7829,
+ 7841, 7853, 7867, 7873, 7877, 7879, 7883, 7901, 7907, 7919,
+ 7927, 7933, 7937, 7949, 7951, 7963, 7993, 8009, 8011, 8017,
+ 8039, 8053, 8059, 8069, 8081, 8087, 8089, 8093, 8101, 8111,
+ 8117, 8123, 8147, 8161, 8167, 8171, 8179, 8191, 8209, 8219,
+ 8221, 8231, 8233, 8237, 8243, 8263, 8269, 8273, 8287, 8291,
+ 8293, 8297, 8311, 8317, 8329, 8353, 8363, 8369, 8377, 8387,
+ 8389, 8419, 8423, 8429, 8431, 8443, 8447, 8461, 8467, 8501,
+ 8513, 8521, 8527, 8537, 8539, 8543, 8563, 8573, 8581, 8597,
+ 8599, 8609, 8623, 8627, 8629, 8641, 8647, 8663, 8669, 8677,
+ 8681, 8689, 8693, 8699, 8707, 8713, 8719, 8731, 8737, 8741,
+ 8747, 8753, 8761, 8779, 8783, 8803, 8807, 8819, 8821, 8831,
+ 8837, 8839, 8849, 8861, 8863, 8867, 8887, 8893, 8923, 8929,
+ 8933, 8941, 8951, 8963, 8969, 8971, 8999, 9001, 9007, 9011,
+ 9013, 9029, 9041, 9043, 9049, 9059, 9067, 9091, 9103, 9109,
+ 9127, 9133, 9137, 9151, 9157, 9161, 9173, 9181, 9187, 9199,
+ 9203, 9209, 9221, 9227, 9239, 9241, 9257, 9277, 9281, 9283,
+ 9293, 9311, 9319, 9323, 9337, 9341, 9343, 9349, 9371, 9377,
+ 9391, 9397, 9403, 9413, 9419, 9421, 9431, 9433, 9437, 9439,
+ 9461, 9463, 9467, 9473, 9479, 9491, 9497, 9511, 9521, 9533,
+ 9539, 9547, 9551, 9587, 9601, 9613, 9619, 9623, 9629, 9631,
+ 9643, 9649, 9661, 9677, 9679, 9689, 9697, 9719, 9721, 9733,
+ 9739, 9743, 9749, 9767, 9769, 9781, 9787, 9791, 9803, 9811,
+ 9817, 9829, 9833, 9839, 9851, 9857, 9859, 9871, 9883, 9887,
+ 9901, 9907, 9923, 9929, 9931, 9941, 9949, 9967, 9973, 10007,
+ 10009, 10037, 10039, 10061, 10067, 10069, 10079, 10091, 10093, 10099,
+ 10103, 10111, 10133, 10139, 10141, 10151, 10159, 10163, 10169, 10177,
+ 10181, 10193, 10211, 10223, 10243, 10247, 10253, 10259, 10267, 10271,
+ 10273, 10289, 10301, 10303, 10313, 10321, 10331, 10333, 10337, 10343,
+ 10357, 10369, 10391, 10399, 10427, 10429, 10433, 10453, 10457, 10459,
+ 10463, 10477, 10487, 10499, 10501, 10513, 10529, 10531, 10559, 10567,
+ 10589, 10597, 10601, 10607, 10613, 10627, 10631, 10639, 10651, 10657,
+ 10663, 10667, 10687, 10691, 10709, 10711, 10723, 10729, 10733, 10739,
+ 10753, 10771, 10781, 10789, 10799, 10831, 10837, 10847, 10853, 10859,
+ 10861, 10867, 10883, 10889, 10891, 10903, 10909, 10937, 10939, 10949,
+ 10957, 10973, 10979, 10987, 10993, 11003, 11027, 11047, 11057, 11059,
+ 11069, 11071, 11083, 11087, 11093, 11113, 11117, 11119, 11131, 11149,
+ 11159, 11161, 11171, 11173, 11177, 11197, 11213, 11239, 11243, 11251,
+ 11257, 11261, 11273, 11279, 11287, 11299, 11311, 11317, 11321, 11329,
+ 11351, 11353, 11369, 11383, 11393, 11399, 11411, 11423, 11437, 11443,
+ 11447, 11467, 11471, 11483, 11489, 11491, 11497, 11503, 11519, 11527,
+ 11549, 11551, 11579, 11587, 11593, 11597, 11617, 11621, 11633, 11657,
+ 11677, 11681, 11689, 11699, 11701, 11717, 11719, 11731, 11743, 11777,
+ 11779, 11783, 11789, 11801, 11807, 11813, 11821, 11827, 11831, 11833,
+ 11839, 11863, 11867, 11887, 11897, 11903, 11909, 11923, 11927, 11933,
+ 11939, 11941, 11953, 11959, 11969, 11971, 11981, 11987, 12007, 12011,
+ 12037, 12041, 12043, 12049, 12071, 12073, 12097, 12101, 12107, 12109,
+ 12113, 12119, 12143, 12149, 12157, 12161, 12163, 12197, 12203, 12211,
+ 12227, 12239, 12241, 12251, 12253, 12263, 12269, 12277, 12281, 12289,
+ 12301, 12323, 12329, 12343, 12347, 12373, 12377, 12379, 12391, 12401,
+ 12409, 12413, 12421, 12433, 12437, 12451, 12457, 12473, 12479, 12487,
+ 12491, 12497, 12503, 12511, 12517, 12527, 12539, 12541, 12547, 12553,
+ 12569, 12577, 12583, 12589, 12601, 12611, 12613, 12619, 12637, 12641,
+ 12647, 12653, 12659, 12671, 12689, 12697, 12703, 12713, 12721, 12739,
+ 12743, 12757, 12763, 12781, 12791, 12799, 12809, 12821, 12823, 12829,
+ 12841, 12853, 12889, 12893, 12899, 12907, 12911, 12917, 12919, 12923,
+ 12941, 12953, 12959, 12967, 12973, 12979, 12983, 13001, 13003, 13007,
+ 13009, 13033, 13037, 13043, 13049, 13063, 13093, 13099, 13103, 13109,
+ 13121, 13127, 13147, 13151, 13159, 13163, 13171, 13177, 13183, 13187,
+ 13217, 13219, 13229, 13241, 13249, 13259, 13267, 13291, 13297, 13309,
+ 13313, 13327, 13331, 13337, 13339, 13367, 13381, 13397, 13399, 13411,
+ 13417, 13421, 13441, 13451, 13457, 13463, 13469, 13477, 13487, 13499,
+ 13513, 13523, 13537, 13553, 13567, 13577, 13591, 13597, 13613, 13619,
+ 13627, 13633, 13649, 13669, 13679, 13681, 13687, 13691, 13693, 13697,
+ 13709, 13711, 13721, 13723, 13729, 13751, 13757, 13759, 13763, 13781,
+ 13789, 13799, 13807, 13829, 13831, 13841, 13859, 13873, 13877, 13879,
+ 13883, 13901, 13903, 13907, 13913, 13921, 13931, 13933, 13963, 13967,
+ 13997, 13999, 14009, 14011, 14029, 14033, 14051, 14057, 14071, 14081,
+ 14083, 14087, 14107, 14143, 14149, 14153, 14159, 14173, 14177, 14197,
+ 14207, 14221, 14243, 14249, 14251, 14281, 14293, 14303, 14321, 14323,
+ 14327, 14341, 14347, 14369, 14387, 14389, 14401, 14407, 14411, 14419,
+ 14423, 14431, 14437, 14447, 14449, 14461, 14479, 14489, 14503, 14519,
+ 14533, 14537, 14543, 14549, 14551, 14557, 14561, 14563, 14591, 14593,
+ 14621, 14627, 14629, 14633, 14639, 14653, 14657, 14669, 14683, 14699,
+ 14713, 14717, 14723, 14731, 14737, 14741, 14747, 14753, 14759, 14767,
+ 14771, 14779, 14783, 14797, 14813, 14821, 14827, 14831, 14843, 14851,
+ 14867, 14869, 14879, 14887, 14891, 14897, 14923, 14929, 14939, 14947,
+ 14951, 14957, 14969, 14983, 15013, 15017, 15031, 15053, 15061, 15073,
+ 15077, 15083, 15091, 15101, 15107, 15121, 15131, 15137, 15139, 15149,
+ 15161, 15173, 15187, 15193, 15199, 15217, 15227, 15233, 15241, 15259,
+ 15263, 15269, 15271, 15277, 15287, 15289, 15299, 15307, 15313, 15319,
+ 15329, 15331, 15349, 15359, 15361, 15373, 15377, 15383, 15391, 15401,
+ 15413, 15427, 15439, 15443, 15451, 15461, 15467, 15473, 15493, 15497,
+ 15511, 15527, 15541, 15551, 15559, 15569, 15581, 15583, 15601, 15607,
+ 15619, 15629, 15641, 15643, 15647, 15649, 15661, 15667, 15671, 15679,
+ 15683, 15727, 15731, 15733, 15737, 15739, 15749, 15761, 15767, 15773,
+ 15787, 15791, 15797, 15803, 15809, 15817, 15823, 15859, 15877, 15881,
+ 15887, 15889, 15901, 15907, 15913, 15919, 15923, 15937, 15959, 15971,
+ 15973, 15991, 16001, 16007, 16033, 16057, 16061, 16063, 16067, 16069,
+ 16073, 16087, 16091, 16097, 16103, 16111, 16127, 16139, 16141, 16183,
+ 16187, 16189, 16193, 16217, 16223, 16229, 16231, 16249, 16253, 16267,
+ 16273, 16301, 16319, 16333, 16339, 16349, 16361, 16363, 16369, 16381,
+ 16411, 16417, 16421, 16427, 16433, 16447, 16451, 16453, 16477, 16481,
+ 16487, 16493, 16519, 16529, 16547, 16553, 16561, 16567, 16573, 16603,
+ 16607, 16619, 16631, 16633, 16649, 16651, 16657, 16661, 16673, 16691,
+ 16693, 16699, 16703, 16729, 16741, 16747, 16759, 16763, 16787, 16811,
+ 16823, 16829, 16831, 16843, 16871, 16879, 16883, 16889, 16901, 16903,
+ 16921, 16927, 16931, 16937, 16943, 16963, 16979, 16981, 16987, 16993,
+ 17011, 17021, 17027, 17029, 17033, 17041, 17047, 17053, 17077, 17093,
+ 17099, 17107, 17117, 17123, 17137, 17159, 17167, 17183, 17189, 17191,
+ 17203, 17207, 17209, 17231, 17239, 17257, 17291, 17293, 17299, 17317,
+ 17321, 17327, 17333, 17341, 17351, 17359, 17377, 17383, 17387, 17389,
+ 17393, 17401, 17417, 17419, 17431, 17443, 17449, 17467, 17471, 17477,
+ 17483, 17489, 17491, 17497, 17509, 17519, 17539, 17551, 17569, 17573,
+ 17579, 17581, 17597, 17599, 17609, 17623, 17627, 17657, 17659, 17669,
+ 17681, 17683, 17707, 17713, 17729, 17737, 17747, 17749, 17761, 17783,
+ 17789, 17791, 17807, 17827, 17837, 17839, 17851, 17863, 17881, 17891,
+ 17903, 17909, 17911, 17921, 17923, 17929, 17939, 17957, 17959, 17971,
+ 17977, 17981, 17987, 17989, 18013, 18041, 18043, 18047, 18049, 18059,
+ 18061, 18077, 18089, 18097, 18119, 18121, 18127, 18131, 18133, 18143,
+ 18149, 18169, 18181, 18191, 18199, 18211, 18217, 18223, 18229, 18233,
+ 18251, 18253, 18257, 18269, 18287, 18289, 18301, 18307, 18311, 18313,
+ 18329, 18341, 18353, 18367, 18371, 18379, 18397, 18401, 18413, 18427,
+ 18433, 18439, 18443, 18451, 18457, 18461, 18481, 18493, 18503, 18517,
+ 18521, 18523, 18539, 18541, 18553, 18583, 18587, 18593, 18617, 18637,
+ 18661, 18671, 18679, 18691, 18701, 18713, 18719, 18731, 18743, 18749,
+ 18757, 18773, 18787, 18793, 18797, 18803, 18839, 18859, 18869, 18899,
+ 18911, 18913, 18917, 18919, 18947, 18959, 18973, 18979, 19001, 19009,
+ 19013, 19031, 19037, 19051, 19069, 19073, 19079, 19081, 19087, 19121,
+ 19139, 19141, 19157, 19163, 19181, 19183, 19207, 19211, 19213, 19219,
+ 19231, 19237, 19249, 19259, 19267, 19273, 19289, 19301, 19309, 19319,
+ 19333, 19373, 19379, 19381, 19387, 19391, 19403, 19417, 19421, 19423,
+ 19427, 19429, 19433, 19441, 19447, 19457, 19463, 19469, 19471, 19477,
+ 19483, 19489, 19501, 19507, 19531, 19541, 19543, 19553, 19559, 19571,
+ 19577, 19583, 19597, 19603, 19609, 19661, 19681, 19687, 19697, 19699,
+ 19709, 19717, 19727, 19739, 19751, 19753, 19759, 19763, 19777, 19793,
+ 19801, 19813, 19819, 19841, 19843, 19853, 19861, 19867, 19889, 19891,
+ 19913, 19919, 19927, 19937, 19949, 19961, 19963, 19973, 19979, 19991,
+ 19993, 19997, 20011, 20021, 20023, 20029, 20047, 20051, 20063, 20071,
+ 20089, 20101, 20107, 20113, 20117, 20123, 20129, 20143, 20147, 20149,
+ 20161, 20173, 20177, 20183, 20201, 20219, 20231, 20233, 20249, 20261,
+ 20269, 20287, 20297, 20323, 20327, 20333, 20341, 20347, 20353, 20357,
+ 20359, 20369, 20389, 20393, 20399, 20407, 20411, 20431, 20441, 20443,
+ 20477, 20479, 20483, 20507, 20509, 20521, 20533, 20543, 20549, 20551,
+ 20563, 20593, 20599, 20611, 20627, 20639, 20641, 20663, 20681, 20693,
+ 20707, 20717, 20719, 20731, 20743, 20747, 20749, 20753, 20759, 20771,
+ 20773, 20789, 20807, 20809, 20849, 20857, 20873, 20879, 20887, 20897,
+ 20899, 20903, 20921, 20929, 20939, 20947, 20959, 20963, 20981, 20983,
+ 21001, 21011, 21013, 21017, 21019, 21023, 21031, 21059, 21061, 21067,
+ 21089, 21101, 21107, 21121, 21139, 21143, 21149, 21157, 21163, 21169,
+ 21179, 21187, 21191, 21193, 21211, 21221, 21227, 21247, 21269, 21277,
+ 21283, 21313, 21317, 21319, 21323, 21341, 21347, 21377, 21379, 21383,
+ 21391, 21397, 21401, 21407, 21419, 21433, 21467, 21481, 21487, 21491,
+ 21493, 21499, 21503, 21517, 21521, 21523, 21529, 21557, 21559, 21563,
+ 21569, 21577, 21587, 21589, 21599, 21601, 21611, 21613, 21617, 21647,
+ 21649, 21661, 21673, 21683, 21701, 21713, 21727, 21737, 21739, 21751,
+ 21757, 21767, 21773, 21787, 21799, 21803, 21817, 21821, 21839, 21841,
+ 21851, 21859, 21863, 21871, 21881, 21893, 21911, 21929, 21937, 21943,
+ 21961, 21977, 21991, 21997, 22003, 22013, 22027, 22031, 22037, 22039,
+ 22051, 22063, 22067, 22073, 22079, 22091, 22093, 22109, 22111, 22123,
+ 22129, 22133, 22147, 22153, 22157, 22159, 22171, 22189, 22193, 22229,
+ 22247, 22259, 22271, 22273, 22277, 22279, 22283, 22291, 22303, 22307,
+ 22343, 22349, 22367, 22369, 22381, 22391, 22397, 22409, 22433, 22441,
+ 22447, 22453, 22469, 22481, 22483, 22501, 22511, 22531, 22541, 22543,
+ 22549, 22567, 22571, 22573, 22613, 22619, 22621, 22637, 22639, 22643,
+ 22651, 22669, 22679, 22691, 22697, 22699, 22709, 22717, 22721, 22727,
+ 22739, 22741, 22751, 22769, 22777, 22783, 22787, 22807, 22811, 22817,
+ 22853, 22859, 22861, 22871, 22877, 22901, 22907, 22921, 22937, 22943,
+ 22961, 22963, 22973, 22993, 23003, 23011, 23017, 23021, 23027, 23029,
+ 23039, 23041, 23053, 23057, 23059, 23063, 23071, 23081, 23087, 23099,
+ 23117, 23131, 23143, 23159, 23167, 23173, 23189, 23197, 23201, 23203,
+ 23209, 23227, 23251, 23269, 23279, 23291, 23293, 23297, 23311, 23321,
+ 23327, 23333, 23339, 23357, 23369, 23371, 23399, 23417, 23431, 23447,
+ 23459, 23473, 23497, 23509, 23531, 23537, 23539, 23549, 23557, 23561,
+ 23563, 23567, 23581, 23593, 23599, 23603, 23609, 23623, 23627, 23629,
+ 23633, 23663, 23669, 23671, 23677, 23687, 23689, 23719, 23741, 23743,
+ 23747, 23753, 23761, 23767, 23773, 23789, 23801, 23813, 23819, 23827,
+ 23831, 23833, 23857, 23869, 23873, 23879, 23887, 23893, 23899, 23909,
+ 23911, 23917, 23929, 23957, 23971, 23977, 23981, 23993, 24001, 24007,
+ 24019, 24023, 24029, 24043, 24049, 24061, 24071, 24077, 24083, 24091,
+ 24097, 24103, 24107, 24109, 24113, 24121, 24133, 24137, 24151, 24169,
+ 24179, 24181, 24197, 24203, 24223, 24229, 24239, 24247, 24251, 24281,
+ 24317, 24329, 24337, 24359, 24371, 24373, 24379, 24391, 24407, 24413,
+ 24419, 24421, 24439, 24443, 24469, 24473, 24481, 24499, 24509, 24517,
+ 24527, 24533, 24547, 24551, 24571, 24593, 24611, 24623, 24631, 24659,
+ 24671, 24677, 24683, 24691, 24697, 24709, 24733, 24749, 24763, 24767,
+ 24781, 24793, 24799, 24809, 24821, 24841, 24847, 24851, 24859, 24877,
+ 24889, 24907, 24917, 24919, 24923, 24943, 24953, 24967, 24971, 24977,
+ 24979, 24989, 25013, 25031, 25033, 25037, 25057, 25073, 25087, 25097,
+ 25111, 25117, 25121, 25127, 25147, 25153, 25163, 25169, 25171, 25183,
+ 25189, 25219, 25229, 25237, 25243, 25247, 25253, 25261, 25301, 25303,
+ 25307, 25309, 25321, 25339, 25343, 25349, 25357, 25367, 25373, 25391,
+ 25409, 25411, 25423, 25439, 25447, 25453, 25457, 25463, 25469, 25471,
+ 25523, 25537, 25541, 25561, 25577, 25579, 25583, 25589, 25601, 25603,
+ 25609, 25621, 25633, 25639, 25643, 25657, 25667, 25673, 25679, 25693,
+ 25703, 25717, 25733, 25741, 25747, 25759, 25763, 25771, 25793, 25799,
+ 25801, 25819, 25841, 25847, 25849, 25867, 25873, 25889, 25903, 25913,
+ 25919, 25931, 25933, 25939, 25943, 25951, 25969, 25981, 25997, 25999,
+ 26003, 26017, 26021, 26029, 26041, 26053, 26083, 26099, 26107, 26111,
+ 26113, 26119, 26141, 26153, 26161, 26171, 26177, 26183, 26189, 26203,
+ 26209, 26227, 26237, 26249, 26251, 26261, 26263, 26267, 26293, 26297,
+ 26309, 26317, 26321, 26339, 26347, 26357, 26371, 26387, 26393, 26399,
+ 26407, 26417, 26423, 26431, 26437, 26449, 26459, 26479, 26489, 26497,
+ 26501, 26513, 26539, 26557, 26561, 26573, 26591, 26597, 26627, 26633,
+ 26641, 26647, 26669, 26681, 26683, 26687, 26693, 26699, 26701, 26711,
+ 26713, 26717, 26723, 26729, 26731, 26737, 26759, 26777, 26783, 26801,
+ 26813, 26821, 26833, 26839, 26849, 26861, 26863, 26879, 26881, 26891,
+ 26893, 26903, 26921, 26927, 26947, 26951, 26953, 26959, 26981, 26987,
+ 26993, 27011, 27017, 27031, 27043, 27059, 27061, 27067, 27073, 27077,
+ 27091, 27103, 27107, 27109, 27127, 27143, 27179, 27191, 27197, 27211,
+ 27239, 27241, 27253, 27259, 27271, 27277, 27281, 27283, 27299, 27329,
+ 27337, 27361, 27367, 27397, 27407, 27409, 27427, 27431, 27437, 27449,
+ 27457, 27479, 27481, 27487, 27509, 27527, 27529, 27539, 27541, 27551,
+ 27581, 27583, 27611, 27617, 27631, 27647, 27653, 27673, 27689, 27691,
+ 27697, 27701, 27733, 27737, 27739, 27743, 27749, 27751, 27763, 27767,
+ 27773, 27779, 27791, 27793, 27799, 27803, 27809, 27817, 27823, 27827,
+ 27847, 27851, 27883, 27893, 27901, 27917, 27919, 27941, 27943, 27947,
+ 27953, 27961, 27967, 27983, 27997, 28001, 28019, 28027, 28031, 28051,
+ 28057, 28069, 28081, 28087, 28097, 28099, 28109, 28111, 28123, 28151,
+ 28163, 28181, 28183, 28201, 28211, 28219, 28229, 28277, 28279, 28283,
+ 28289, 28297, 28307, 28309, 28319, 28349, 28351, 28387, 28393, 28403,
+ 28409, 28411, 28429, 28433, 28439, 28447, 28463, 28477, 28493, 28499,
+ 28513, 28517, 28537, 28541, 28547, 28549, 28559, 28571, 28573, 28579,
+ 28591, 28597, 28603, 28607, 28619, 28621, 28627, 28631, 28643, 28649,
+ 28657, 28661, 28663, 28669, 28687, 28697, 28703, 28711, 28723, 28729,
+ 28751, 28753, 28759, 28771, 28789, 28793, 28807, 28813, 28817, 28837,
+ 28843, 28859, 28867, 28871, 28879, 28901, 28909, 28921, 28927, 28933,
+ 28949, 28961, 28979, 29009, 29017, 29021, 29023, 29027, 29033, 29059,
+ 29063, 29077, 29101, 29123, 29129, 29131, 29137, 29147, 29153, 29167,
+ 29173, 29179, 29191, 29201, 29207, 29209, 29221, 29231, 29243, 29251,
+ 29269, 29287, 29297, 29303, 29311, 29327, 29333, 29339, 29347, 29363,
+ 29383, 29387, 29389, 29399, 29401, 29411, 29423, 29429, 29437, 29443,
+ 29453, 29473, 29483, 29501, 29527, 29531, 29537, 29567, 29569, 29573,
+ 29581, 29587, 29599, 29611, 29629, 29633, 29641, 29663, 29669, 29671,
+ 29683, 29717, 29723, 29741, 29753, 29759, 29761, 29789, 29803, 29819,
+ 29833, 29837, 29851, 29863, 29867, 29873, 29879, 29881, 29917, 29921,
+ 29927, 29947, 29959, 29983, 29989, 30011, 30013, 30029, 30047, 30059,
+ 30071, 30089, 30091, 30097, 30103, 30109, 30113, 30119, 30133, 30137,
+ 30139, 30161, 30169, 30181, 30187, 30197, 30203, 30211, 30223, 30241,
+ 30253, 30259, 30269, 30271, 30293, 30307, 30313, 30319, 30323, 30341,
+ 30347, 30367, 30389, 30391, 30403, 30427, 30431, 30449, 30467, 30469,
+ 30491, 30493, 30497, 30509, 30517, 30529, 30539, 30553, 30557, 30559,
+ 30577, 30593, 30631, 30637, 30643, 30649, 30661, 30671, 30677, 30689,
+ 30697, 30703, 30707, 30713, 30727, 30757, 30763, 30773, 30781, 30803,
+ 30809, 30817, 30829, 30839, 30841, 30851, 30853, 30859, 30869, 30871,
+ 30881, 30893, 30911, 30931, 30937, 30941, 30949, 30971, 30977, 30983,
+ 31013, 31019, 31033, 31039, 31051, 31063, 31069, 31079, 31081, 31091,
+ 31121, 31123, 31139, 31147, 31151, 31153, 31159, 31177, 31181, 31183,
+ 31189, 31193, 31219, 31223, 31231, 31237, 31247, 31249, 31253, 31259,
+ 31267, 31271, 31277, 31307, 31319, 31321, 31327, 31333, 31337, 31357,
+ 31379, 31387, 31391, 31393, 31397, 31469, 31477, 31481, 31489, 31511,
+ 31513, 31517, 31531, 31541, 31543, 31547, 31567, 31573, 31583, 31601,
+ 31607, 31627, 31643, 31649, 31657, 31663, 31667, 31687, 31699, 31721,
+ 31723, 31727, 31729, 31741, 31751, 31769, 31771, 31793, 31799, 31817,
+ 31847, 31849, 31859, 31873, 31883, 31891, 31907, 31957, 31963, 31973,
+ 31981, 31991, 32003, 32009, 32027, 32029, 32051, 32057, 32059, 32063,
+ 32069, 32077, 32083, 32089, 32099, 32117, 32119, 32141, 32143, 32159,
+ 32173, 32183, 32189, 32191, 32203, 32213, 32233, 32237, 32251, 32257,
+ 32261, 32297, 32299, 32303, 32309, 32321, 32323, 32327, 32341, 32353,
+ 32359, 32363, 32369, 32371, 32377, 32381, 32401, 32411, 32413, 32423,
+ 32429, 32441, 32443, 32467, 32479, 32491, 32497, 32503, 32507, 32531,
+ 32533, 32537, 32561, 32563, 32569, 32573, 32579, 32587, 32603, 32609,
+ 32611, 32621, 32633, 32647, 32653, 32687, 32693, 32707, 32713, 32717,
+ 32719, 32749, 32771, 32779, 32783, 32789, 32797, 32801, 32803, 32831,
+ 32833, 32839, 32843, 32869, 32887, 32909, 32911, 32917, 32933, 32939,
+ 32941, 32957, 32969, 32971, 32983, 32987, 32993, 32999, 33013, 33023,
+ 33029, 33037, 33049, 33053, 33071, 33073, 33083, 33091, 33107, 33113,
+ 33119, 33149, 33151, 33161, 33179, 33181, 33191, 33199, 33203, 33211,
+ 33223, 33247, 33287, 33289, 33301, 33311, 33317, 33329, 33331, 33343,
+ 33347, 33349, 33353, 33359, 33377, 33391, 33403, 33409, 33413, 33427,
+ 33457, 33461, 33469, 33479, 33487, 33493, 33503, 33521, 33529, 33533,
+ 33547, 33563, 33569, 33577, 33581, 33587, 33589, 33599, 33601, 33613,
+ 33617, 33619, 33623, 33629, 33637, 33641, 33647, 33679, 33703, 33713,
+ 33721, 33739, 33749, 33751, 33757, 33767, 33769, 33773, 33791, 33797,
+ 33809, 33811, 33827, 33829, 33851, 33857, 33863, 33871, 33889, 33893,
+ 33911, 33923, 33931, 33937, 33941, 33961, 33967, 33997, 34019, 34031,
+ 34033, 34039, 34057, 34061, 34123, 34127, 34129, 34141, 34147, 34157,
+ 34159, 34171, 34183, 34211, 34213, 34217, 34231, 34253, 34259, 34261,
+ 34267, 34273, 34283, 34297, 34301, 34303, 34313, 34319, 34327, 34337,
+ 34351, 34361, 34367, 34369, 34381, 34403, 34421, 34429, 34439, 34457,
+ 34469, 34471, 34483, 34487, 34499, 34501, 34511, 34513, 34519, 34537,
+ 34543, 34549, 34583, 34589, 34591, 34603, 34607, 34613, 34631, 34649,
+ 34651, 34667, 34673, 34679, 34687, 34693, 34703, 34721, 34729, 34739,
+ 34747, 34757, 34759, 34763, 34781, 34807, 34819, 34841, 34843, 34847,
+ 34849, 34871, 34877, 34883, 34897, 34913, 34919, 34939, 34949, 34961,
+ 34963, 34981, 35023, 35027, 35051, 35053, 35059, 35069, 35081, 35083,
+ 35089, 35099, 35107, 35111, 35117, 35129, 35141, 35149, 35153, 35159,
+ 35171, 35201, 35221, 35227, 35251, 35257, 35267, 35279, 35281, 35291,
+ 35311, 35317, 35323, 35327, 35339, 35353, 35363, 35381, 35393, 35401,
+ 35407, 35419, 35423, 35437, 35447, 35449, 35461, 35491, 35507, 35509,
+ 35521, 35527, 35531, 35533, 35537, 35543, 35569, 35573, 35591, 35593,
+ 35597, 35603, 35617, 35671, 35677, 35729, 35731, 35747, 35753, 35759,
+ 35771, 35797, 35801, 35803, 35809, 35831, 35837, 35839, 35851, 35863,
+ 35869, 35879, 35897, 35899, 35911, 35923, 35933, 35951, 35963, 35969,
+ 35977, 35983, 35993, 35999, 36007, 36011, 36013, 36017, 36037, 36061,
+ 36067, 36073, 36083, 36097, 36107, 36109, 36131, 36137, 36151, 36161,
+ 36187, 36191, 36209, 36217, 36229, 36241, 36251, 36263, 36269, 36277,
+ 36293, 36299, 36307, 36313, 36319, 36341, 36343, 36353, 36373, 36383,
+ 36389, 36433, 36451, 36457, 36467, 36469, 36473, 36479, 36493, 36497,
+ 36523, 36527, 36529, 36541, 36551, 36559, 36563, 36571, 36583, 36587,
+ 36599, 36607, 36629, 36637, 36643, 36653, 36671, 36677, 36683, 36691,
+ 36697, 36709, 36713, 36721, 36739, 36749, 36761, 36767, 36779, 36781,
+ 36787, 36791, 36793, 36809, 36821, 36833, 36847, 36857, 36871, 36877,
+ 36887, 36899, 36901, 36913, 36919, 36923, 36929, 36931, 36943, 36947,
+ 36973, 36979, 36997, 37003, 37013, 37019, 37021, 37039, 37049, 37057,
+ 37061, 37087, 37097, 37117, 37123, 37139, 37159, 37171, 37181, 37189,
+ 37199, 37201, 37217, 37223, 37243, 37253, 37273, 37277, 37307, 37309,
+ 37313, 37321, 37337, 37339, 37357, 37361, 37363, 37369, 37379, 37397,
+ 37409, 37423, 37441, 37447, 37463, 37483, 37489, 37493, 37501, 37507,
+ 37511, 37517, 37529, 37537, 37547, 37549, 37561, 37567, 37571, 37573,
+ 37579, 37589, 37591, 37607, 37619, 37633, 37643, 37649, 37657, 37663,
+ 37691, 37693, 37699, 37717, 37747, 37781, 37783, 37799, 37811, 37813,
+ 37831, 37847, 37853, 37861, 37871, 37879, 37889, 37897, 37907, 37951,
+ 37957, 37963, 37967, 37987, 37991, 37993, 37997, 38011, 38039, 38047,
+ 38053, 38069, 38083, 38113, 38119, 38149, 38153, 38167, 38177, 38183,
+ 38189, 38197, 38201, 38219, 38231, 38237, 38239, 38261, 38273, 38281,
+ 38287, 38299, 38303, 38317, 38321, 38327, 38329, 38333, 38351, 38371,
+ 38377, 38393, 38431, 38447, 38449, 38453, 38459, 38461, 38501, 38543,
+ 38557, 38561, 38567, 38569, 38593, 38603, 38609, 38611, 38629, 38639,
+ 38651, 38653, 38669, 38671, 38677, 38693, 38699, 38707, 38711, 38713,
+ 38723, 38729, 38737, 38747, 38749, 38767, 38783, 38791, 38803, 38821,
+ 38833, 38839, 38851, 38861, 38867, 38873, 38891, 38903, 38917, 38921,
+ 38923, 38933, 38953, 38959, 38971, 38977, 38993, 39019, 39023, 39041,
+ 39043, 39047, 39079, 39089, 39097, 39103, 39107, 39113, 39119, 39133,
+ 39139, 39157, 39161, 39163, 39181, 39191, 39199, 39209, 39217, 39227,
+ 39229, 39233, 39239, 39241, 39251, 39293, 39301, 39313, 39317, 39323,
+ 39341, 39343, 39359, 39367, 39371, 39373, 39383, 39397, 39409, 39419,
+ 39439, 39443, 39451, 39461, 39499, 39503, 39509, 39511, 39521, 39541,
+ 39551, 39563, 39569, 39581, 39607, 39619, 39623, 39631, 39659, 39667,
+ 39671, 39679, 39703, 39709, 39719, 39727, 39733, 39749, 39761, 39769,
+ 39779, 39791, 39799, 39821, 39827, 39829, 39839, 39841, 39847, 39857,
+ 39863, 39869, 39877, 39883, 39887, 39901, 39929, 39937, 39953, 39971,
+ 39979, 39983, 39989, 40009, 40013, 40031, 40037, 40039, 40063, 40087,
+ 40093, 40099, 40111, 40123, 40127, 40129, 40151, 40153, 40163, 40169,
+ 40177, 40189, 40193, 40213, 40231, 40237, 40241, 40253, 40277, 40283,
+ 40289, 40343, 40351, 40357, 40361, 40387, 40423, 40427, 40429, 40433,
+ 40459, 40471, 40483, 40487, 40493, 40499, 40507, 40519, 40529, 40531,
+ 40543, 40559, 40577, 40583, 40591, 40597, 40609, 40627, 40637, 40639,
+ 40693, 40697, 40699, 40709, 40739, 40751, 40759, 40763, 40771, 40787,
+ 40801, 40813, 40819, 40823, 40829, 40841, 40847, 40849, 40853, 40867,
+ 40879, 40883, 40897, 40903, 40927, 40933, 40939, 40949, 40961, 40973,
+ 40993, 41011, 41017, 41023, 41039, 41047, 41051, 41057, 41077, 41081,
+ 41113, 41117, 41131, 41141, 41143, 41149, 41161, 41177, 41179, 41183,
+ 41189, 41201, 41203, 41213, 41221, 41227, 41231, 41233, 41243, 41257,
+ 41263, 41269, 41281, 41299, 41333, 41341, 41351, 41357, 41381, 41387,
+ 41389, 41399, 41411, 41413, 41443, 41453, 41467, 41479, 41491, 41507,
+ 41513, 41519, 41521, 41539, 41543, 41549, 41579, 41593, 41597, 41603,
+ 41609, 41611, 41617, 41621, 41627, 41641, 41647, 41651, 41659, 41669,
+ 41681, 41687, 41719, 41729, 41737, 41759, 41761, 41771, 41777, 41801,
+ 41809, 41813, 41843, 41849, 41851, 41863, 41879, 41887, 41893, 41897,
+ 41903, 41911, 41927, 41941, 41947, 41953, 41957, 41959, 41969, 41981,
+ 41983, 41999, 42013, 42017, 42019, 42023, 42043, 42061, 42071, 42073,
+ 42083, 42089, 42101, 42131, 42139, 42157, 42169, 42179, 42181, 42187,
+ 42193, 42197, 42209, 42221, 42223, 42227, 42239, 42257, 42281, 42283,
+ 42293, 42299, 42307, 42323, 42331, 42337, 42349, 42359, 42373, 42379,
+ 42391, 42397, 42403, 42407, 42409, 42433, 42437, 42443, 42451, 42457,
+ 42461, 42463, 42467, 42473, 42487, 42491, 42499, 42509, 42533, 42557,
+ 42569, 42571, 42577, 42589, 42611, 42641, 42643, 42649, 42667, 42677,
+ 42683, 42689, 42697, 42701, 42703, 42709, 42719, 42727, 42737, 42743,
+ 42751, 42767, 42773, 42787, 42793, 42797, 42821, 42829, 42839, 42841,
+ 42853, 42859, 42863, 42899, 42901, 42923, 42929, 42937, 42943, 42953,
+ 42961, 42967, 42979, 42989, 43003, 43013, 43019, 43037, 43049, 43051,
+ 43063, 43067, 43093, 43103, 43117, 43133, 43151, 43159, 43177, 43189,
+ 43201, 43207, 43223, 43237, 43261, 43271, 43283, 43291, 43313, 43319,
+ 43321, 43331, 43391, 43397, 43399, 43403, 43411, 43427, 43441, 43451,
+ 43457, 43481, 43487, 43499, 43517, 43541, 43543, 43573, 43577, 43579,
+ 43591, 43597, 43607, 43609, 43613, 43627, 43633, 43649, 43651, 43661,
+ 43669, 43691, 43711, 43717, 43721, 43753, 43759, 43777, 43781, 43783,
+ 43787, 43789, 43793, 43801, 43853, 43867, 43889, 43891, 43913, 43933,
+ 43943, 43951, 43961, 43963, 43969, 43973, 43987, 43991, 43997, 44017,
+ 44021, 44027, 44029, 44041, 44053, 44059, 44071, 44087, 44089, 44101,
+ 44111, 44119, 44123, 44129, 44131, 44159, 44171, 44179, 44189, 44201,
+ 44203, 44207, 44221, 44249, 44257, 44263, 44267, 44269, 44273, 44279,
+ 44281, 44293, 44351, 44357, 44371, 44381, 44383, 44389, 44417, 44449,
+ 44453, 44483, 44491, 44497, 44501, 44507, 44519, 44531, 44533, 44537,
+ 44543, 44549, 44563, 44579, 44587, 44617, 44621, 44623, 44633, 44641,
+ 44647, 44651, 44657, 44683, 44687, 44699, 44701, 44711, 44729, 44741,
+ 44753, 44771, 44773, 44777, 44789, 44797, 44809, 44819, 44839, 44843,
+ 44851, 44867, 44879, 44887, 44893, 44909, 44917, 44927, 44939, 44953,
+ 44959, 44963, 44971, 44983, 44987, 45007, 45013, 45053, 45061, 45077,
+ 45083, 45119, 45121, 45127, 45131, 45137, 45139, 45161, 45179, 45181,
+ 45191, 45197, 45233, 45247, 45259, 45263, 45281, 45289, 45293, 45307,
+ 45317, 45319, 45329, 45337, 45341, 45343, 45361, 45377, 45389, 45403,
+ 45413, 45427, 45433, 45439, 45481, 45491, 45497, 45503, 45523, 45533,
+ 45541, 45553, 45557, 45569, 45587, 45589, 45599, 45613, 45631, 45641,
+ 45659, 45667, 45673, 45677, 45691, 45697, 45707, 45737, 45751, 45757,
+ 45763, 45767, 45779, 45817, 45821, 45823, 45827, 45833, 45841, 45853,
+ 45863, 45869, 45887, 45893, 45943, 45949, 45953, 45959, 45971, 45979,
+ 45989, 46021, 46027, 46049, 46051, 46061, 46073, 46091, 46093, 46099,
+ 46103, 46133, 46141, 46147, 46153, 46171, 46181, 46183, 46187, 46199,
+ 46219, 46229, 46237, 46261, 46271, 46273, 46279, 46301, 46307, 46309,
+ 46327, 46337, 46349, 46351, 46381, 46399, 46411, 46439, 46441, 46447,
+ 46451, 46457, 46471, 46477, 46489, 46499, 46507, 46511, 46523, 46549,
+ 46559, 46567, 46573, 46589, 46591, 46601, 46619, 46633, 46639, 46643,
+ 46649, 46663, 46679, 46681, 46687, 46691, 46703, 46723, 46727, 46747,
+ 46751, 46757, 46769, 46771, 46807, 46811, 46817, 46819, 46829, 46831,
+ 46853, 46861, 46867, 46877, 46889, 46901, 46919, 46933, 46957, 46993,
+ 46997, 47017, 47041, 47051, 47057, 47059, 47087, 47093, 47111, 47119,
+ 47123, 47129, 47137, 47143, 47147, 47149, 47161, 47189, 47207, 47221,
+ 47237, 47251, 47269, 47279, 47287, 47293, 47297, 47303, 47309, 47317,
+ 47339, 47351, 47353, 47363, 47381, 47387, 47389, 47407, 47417, 47419,
+ 47431, 47441, 47459, 47491, 47497, 47501, 47507, 47513, 47521, 47527,
+ 47533, 47543, 47563, 47569, 47581, 47591, 47599, 47609, 47623, 47629,
+ 47639, 47653, 47657, 47659, 47681, 47699, 47701, 47711, 47713, 47717,
+ 47737, 47741, 47743, 47777, 47779, 47791, 47797, 47807, 47809, 47819,
+ 47837, 47843, 47857, 47869, 47881, 47903, 47911, 47917, 47933, 47939,
+ 47947, 47951, 47963, 47969, 47977, 47981, 48017, 48023, 48029, 48049,
+ 48073, 48079, 48091, 48109, 48119, 48121, 48131, 48157, 48163, 48179,
+ 48187, 48193, 48197, 48221, 48239, 48247, 48259, 48271, 48281, 48299,
+ 48311, 48313, 48337, 48341, 48353, 48371, 48383, 48397, 48407, 48409,
+ 48413, 48437, 48449, 48463, 48473, 48479, 48481, 48487, 48491, 48497,
+ 48523, 48527, 48533, 48539, 48541, 48563, 48571, 48589, 48593, 48611,
+ 48619, 48623, 48647, 48649, 48661, 48673, 48677, 48679, 48731, 48733,
+ 48751, 48757, 48761, 48767, 48779, 48781, 48787, 48799, 48809, 48817,
+ 48821, 48823, 48847, 48857, 48859, 48869, 48871, 48883, 48889, 48907,
+ 48947, 48953, 48973, 48989, 48991, 49003, 49009, 49019, 49031, 49033,
+ 49037, 49043, 49057, 49069, 49081, 49103, 49109, 49117, 49121, 49123,
+ 49139, 49157, 49169, 49171, 49177, 49193, 49199, 49201, 49207, 49211,
+ 49223, 49253, 49261, 49277, 49279, 49297, 49307, 49331, 49333, 49339,
+ 49363, 49367, 49369, 49391, 49393, 49409, 49411, 49417, 49429, 49433,
+ 49451, 49459, 49463, 49477, 49481, 49499, 49523, 49529, 49531, 49537,
+ 49547, 49549, 49559, 49597, 49603, 49613, 49627, 49633, 49639, 49663,
+ 49667, 49669, 49681, 49697, 49711, 49727, 49739, 49741, 49747, 49757,
+ 49783, 49787, 49789, 49801, 49807, 49811, 49823, 49831, 49843, 49853,
+ 49871, 49877, 49891, 49919, 49921, 49927, 49937, 49939, 49943, 49957,
+ 49991, 49993, 49999, 50021, 50023, 50033, 50047, 50051, 50053, 50069,
+ 50077, 50087, 50093, 50101, 50111, 50119, 50123, 50129, 50131, 50147,
+ 50153, 50159, 50177, 50207, 50221, 50227, 50231, 50261, 50263, 50273,
+ 50287, 50291, 50311, 50321, 50329, 50333, 50341, 50359, 50363, 50377,
+ 50383, 50387, 50411, 50417, 50423, 50441, 50459, 50461, 50497, 50503,
+ 50513, 50527, 50539, 50543, 50549, 50551, 50581, 50587, 50591, 50593,
+ 50599, 50627, 50647, 50651, 50671, 50683, 50707, 50723, 50741, 50753,
+ 50767, 50773, 50777, 50789, 50821, 50833, 50839, 50849, 50857, 50867,
+ 50873, 50891, 50893, 50909, 50923, 50929, 50951, 50957, 50969, 50971,
+ 50989, 50993, 51001, 51031, 51043, 51047, 51059, 51061, 51071, 51109,
+ 51131, 51133, 51137, 51151, 51157, 51169, 51193, 51197, 51199, 51203,
+ 51217, 51229, 51239, 51241, 51257, 51263, 51283, 51287, 51307, 51329,
+ 51341, 51343, 51347, 51349, 51361, 51383, 51407, 51413, 51419, 51421,
+ 51427, 51431, 51437, 51439, 51449, 51461, 51473, 51479, 51481, 51487,
+ 51503, 51511, 51517, 51521, 51539, 51551, 51563, 51577, 51581, 51593,
+ 51599, 51607, 51613, 51631, 51637, 51647, 51659, 51673, 51679, 51683,
+ 51691, 51713, 51719, 51721, 51749, 51767, 51769, 51787, 51797, 51803,
+ 51817, 51827, 51829, 51839, 51853, 51859, 51869, 51871, 51893, 51899,
+ 51907, 51913, 51929, 51941, 51949, 51971, 51973, 51977, 51991, 52009,
+ 52021, 52027, 52051, 52057, 52067, 52069, 52081, 52103, 52121, 52127,
+ 52147, 52153, 52163, 52177, 52181, 52183, 52189, 52201, 52223, 52237,
+ 52249, 52253, 52259, 52267, 52289, 52291, 52301, 52313, 52321, 52361,
+ 52363, 52369, 52379, 52387, 52391, 52433, 52453, 52457, 52489, 52501,
+ 52511, 52517, 52529, 52541, 52543, 52553, 52561, 52567, 52571, 52579,
+ 52583, 52609, 52627, 52631, 52639, 52667, 52673, 52691, 52697, 52709,
+ 52711, 52721, 52727, 52733, 52747, 52757, 52769, 52783, 52807, 52813,
+ 52817, 52837, 52859, 52861, 52879, 52883, 52889, 52901, 52903, 52919,
+ 52937, 52951, 52957, 52963, 52967, 52973, 52981, 52999, 53003, 53017,
+ 53047, 53051, 53069, 53077, 53087, 53089, 53093, 53101, 53113, 53117,
+ 53129, 53147, 53149, 53161, 53171, 53173, 53189, 53197, 53201, 53231,
+ 53233, 53239, 53267, 53269, 53279, 53281, 53299, 53309, 53323, 53327,
+ 53353, 53359, 53377, 53381, 53401, 53407, 53411, 53419, 53437, 53441,
+ 53453, 53479, 53503, 53507, 53527, 53549, 53551, 53569, 53591, 53593,
+ 53597, 53609, 53611, 53617, 53623, 53629, 53633, 53639, 53653, 53657,
+ 53681, 53693, 53699, 53717, 53719, 53731, 53759, 53773, 53777, 53783,
+ 53791, 53813, 53819, 53831, 53849, 53857, 53861, 53881, 53887, 53891,
+ 53897, 53899, 53917, 53923, 53927, 53939, 53951, 53959, 53987, 53993,
+ 54001, 54011, 54013, 54037, 54049, 54059, 54083, 54091, 54101, 54121,
+ 54133, 54139, 54151, 54163, 54167, 54181, 54193, 54217, 54251, 54269,
+ 54277, 54287, 54293, 54311, 54319, 54323, 54331, 54347, 54361, 54367,
+ 54371, 54377, 54401, 54403, 54409, 54413, 54419, 54421, 54437, 54443,
+ 54449, 54469, 54493, 54497, 54499, 54503, 54517, 54521, 54539, 54541,
+ 54547, 54559, 54563, 54577, 54581, 54583, 54601, 54617, 54623, 54629,
+ 54631, 54647, 54667, 54673, 54679, 54709, 54713, 54721, 54727, 54751,
+ 54767, 54773, 54779, 54787, 54799, 54829, 54833, 54851, 54869, 54877,
+ 54881, 54907, 54917, 54919, 54941, 54949, 54959, 54973, 54979, 54983,
+ 55001, 55009, 55021, 55049, 55051, 55057, 55061, 55073, 55079, 55103,
+ 55109, 55117, 55127, 55147, 55163, 55171, 55201, 55207, 55213, 55217,
+ 55219, 55229, 55243, 55249, 55259, 55291, 55313, 55331, 55333, 55337,
+ 55339, 55343, 55351, 55373, 55381, 55399, 55411, 55439, 55441, 55457,
+ 55469, 55487, 55501, 55511, 55529, 55541, 55547, 55579, 55589, 55603,
+ 55609, 55619, 55621, 55631, 55633, 55639, 55661, 55663, 55667, 55673,
+ 55681, 55691, 55697, 55711, 55717, 55721, 55733, 55763, 55787, 55793,
+ 55799, 55807, 55813, 55817, 55819, 55823, 55829, 55837, 55843, 55849,
+ 55871, 55889, 55897, 55901, 55903, 55921, 55927, 55931, 55933, 55949,
+ 55967, 55987, 55997, 56003, 56009, 56039, 56041, 56053, 56081, 56087,
+ 56093, 56099, 56101, 56113, 56123, 56131, 56149, 56167, 56171, 56179,
+ 56197, 56207, 56209, 56237, 56239, 56249, 56263, 56267, 56269, 56299,
+ 56311, 56333, 56359, 56369, 56377, 56383, 56393, 56401, 56417, 56431,
+ 56437, 56443, 56453, 56467, 56473, 56477, 56479, 56489, 56501, 56503,
+ 56509, 56519, 56527, 56531, 56533, 56543, 56569, 56591, 56597, 56599,
+ 56611, 56629, 56633, 56659, 56663, 56671, 56681, 56687, 56701, 56711,
+ 56713, 56731, 56737, 56747, 56767, 56773, 56779, 56783, 56807, 56809,
+ 56813, 56821, 56827, 56843, 56857, 56873, 56891, 56893, 56897, 56909,
+ 56911, 56921, 56923, 56929, 56941, 56951, 56957, 56963, 56983, 56989,
+ 56993, 56999, 57037, 57041, 57047, 57059, 57073, 57077, 57089, 57097,
+ 57107, 57119, 57131, 57139, 57143, 57149, 57163, 57173, 57179, 57191,
+ 57193, 57203, 57221, 57223, 57241, 57251, 57259, 57269, 57271, 57283,
+ 57287, 57301, 57329, 57331, 57347, 57349, 57367, 57373, 57383, 57389,
+ 57397, 57413, 57427, 57457, 57467, 57487, 57493, 57503, 57527, 57529,
+ 57557, 57559, 57571, 57587, 57593, 57601, 57637, 57641, 57649, 57653,
+ 57667, 57679, 57689, 57697, 57709, 57713, 57719, 57727, 57731, 57737,
+ 57751, 57773, 57781, 57787, 57791, 57793, 57803, 57809, 57829, 57839,
+ 57847, 57853, 57859, 57881, 57899, 57901, 57917, 57923, 57943, 57947,
+ 57973, 57977, 57991, 58013, 58027, 58031, 58043, 58049, 58057, 58061,
+ 58067, 58073, 58099, 58109, 58111, 58129, 58147, 58151, 58153, 58169,
+ 58171, 58189, 58193, 58199, 58207, 58211, 58217, 58229, 58231, 58237,
+ 58243, 58271, 58309, 58313, 58321, 58337, 58363, 58367, 58369, 58379,
+ 58391, 58393, 58403, 58411, 58417, 58427, 58439, 58441, 58451, 58453,
+ 58477, 58481, 58511, 58537, 58543, 58549, 58567, 58573, 58579, 58601,
+ 58603, 58613, 58631, 58657, 58661, 58679, 58687, 58693, 58699, 58711,
+ 58727, 58733, 58741, 58757, 58763, 58771, 58787, 58789, 58831, 58889,
+ 58897, 58901, 58907, 58909, 58913, 58921, 58937, 58943, 58963, 58967,
+ 58979, 58991, 58997, 59009, 59011, 59021, 59023, 59029, 59051, 59053,
+ 59063, 59069, 59077, 59083, 59093, 59107, 59113, 59119, 59123, 59141,
+ 59149, 59159, 59167, 59183, 59197, 59207, 59209, 59219, 59221, 59233,
+ 59239, 59243, 59263, 59273, 59281, 59333, 59341, 59351, 59357, 59359,
+ 59369, 59377, 59387, 59393, 59399, 59407, 59417, 59419, 59441, 59443,
+ 59447, 59453, 59467, 59471, 59473, 59497, 59509, 59513, 59539, 59557,
+ 59561, 59567, 59581, 59611, 59617, 59621, 59627, 59629, 59651, 59659,
+ 59663, 59669, 59671, 59693, 59699, 59707, 59723, 59729, 59743, 59747,
+ 59753, 59771, 59779, 59791, 59797, 59809, 59833, 59863, 59879, 59887,
+ 59921, 59929, 59951, 59957, 59971, 59981, 59999, 60013, 60017, 60029,
+ 60037, 60041, 60077, 60083, 60089, 60091, 60101, 60103, 60107, 60127,
+ 60133, 60139, 60149, 60161, 60167, 60169, 60209, 60217, 60223, 60251,
+ 60257, 60259, 60271, 60289, 60293, 60317, 60331, 60337, 60343, 60353,
+ 60373, 60383, 60397, 60413, 60427, 60443, 60449, 60457, 60493, 60497,
+ 60509, 60521, 60527, 60539, 60589, 60601, 60607, 60611, 60617, 60623,
+ 60631, 60637, 60647, 60649, 60659, 60661, 60679, 60689, 60703, 60719,
+ 60727, 60733, 60737, 60757, 60761, 60763, 60773, 60779, 60793, 60811,
+ 60821, 60859, 60869, 60887, 60889, 60899, 60901, 60913, 60917, 60919,
+ 60923, 60937, 60943, 60953, 60961, 61001, 61007, 61027, 61031, 61043,
+ 61051, 61057, 61091, 61099, 61121, 61129, 61141, 61151, 61153, 61169,
+ 61211, 61223, 61231, 61253, 61261, 61283, 61291, 61297, 61331, 61333,
+ 61339, 61343, 61357, 61363, 61379, 61381, 61403, 61409, 61417, 61441,
+ 61463, 61469, 61471, 61483, 61487, 61493, 61507, 61511, 61519, 61543,
+ 61547, 61553, 61559, 61561, 61583, 61603, 61609, 61613, 61627, 61631,
+ 61637, 61643, 61651, 61657, 61667, 61673, 61681, 61687, 61703, 61717,
+ 61723, 61729, 61751, 61757, 61781, 61813, 61819, 61837, 61843, 61861,
+ 61871, 61879, 61909, 61927, 61933, 61949, 61961, 61967, 61979, 61981,
+ 61987, 61991, 62003, 62011, 62017, 62039, 62047, 62053, 62057, 62071,
+ 62081, 62099, 62119, 62129, 62131, 62137, 62141, 62143, 62171, 62189,
+ 62191, 62201, 62207, 62213, 62219, 62233, 62273, 62297, 62299, 62303,
+ 62311, 62323, 62327, 62347, 62351, 62383, 62401, 62417, 62423, 62459,
+ 62467, 62473, 62477, 62483, 62497, 62501, 62507, 62533, 62539, 62549,
+ 62563, 62581, 62591, 62597, 62603, 62617, 62627, 62633, 62639, 62653,
+ 62659, 62683, 62687, 62701, 62723, 62731, 62743, 62753, 62761, 62773,
+ 62791, 62801, 62819, 62827, 62851, 62861, 62869, 62873, 62897, 62903,
+ 62921, 62927, 62929, 62939, 62969, 62971, 62981, 62983, 62987, 62989,
+ 63029, 63031, 63059, 63067, 63073, 63079, 63097, 63103, 63113, 63127,
+ 63131, 63149, 63179, 63197, 63199, 63211, 63241, 63247, 63277, 63281,
+ 63299, 63311, 63313, 63317, 63331, 63337, 63347, 63353, 63361, 63367,
+ 63377, 63389, 63391, 63397, 63409, 63419, 63421, 63439, 63443, 63463,
+ 63467, 63473, 63487, 63493, 63499, 63521, 63527, 63533, 63541, 63559,
+ 63577, 63587, 63589, 63599, 63601, 63607, 63611, 63617, 63629, 63647,
+ 63649, 63659, 63667, 63671, 63689, 63691, 63697, 63703, 63709, 63719,
+ 63727, 63737, 63743, 63761, 63773, 63781, 63793, 63799, 63803, 63809,
+ 63823, 63839, 63841, 63853, 63857, 63863, 63901, 63907, 63913, 63929,
+ 63949, 63977, 63997, 64007, 64013, 64019, 64033, 64037, 64063, 64067,
+ 64081, 64091, 64109, 64123, 64151, 64153, 64157, 64171, 64187, 64189,
+ 64217, 64223, 64231, 64237, 64271, 64279, 64283, 64301, 64303, 64319,
+ 64327, 64333, 64373, 64381, 64399, 64403, 64433, 64439, 64451, 64453,
+ 64483, 64489, 64499, 64513, 64553, 64567, 64577, 64579, 64591, 64601,
+ 64609, 64613, 64621, 64627, 64633, 64661, 64663, 64667, 64679, 64693,
+ 64709, 64717, 64747, 64763, 64781, 64783, 64793, 64811, 64817, 64849,
+ 64853, 64871, 64877, 64879, 64891, 64901, 64919, 64921, 64927, 64937,
+ 64951, 64969, 64997, 65003, 65011, 65027, 65029, 65033, 65053, 65063,
+ 65071, 65089, 65099, 65101, 65111, 65119, 65123, 65129, 65141, 65147,
+ 65167, 65171, 65173, 65179, 65183, 65203, 65213, 65239, 65257, 65267,
+ 65269, 65287, 65293, 65309, 65323, 65327, 65353, 65357, 65371, 65381,
+ 65393, 65407, 65413, 65419, 65423, 65437, 65447, 65449, 65479, 65497,
+ 65519, 65521, 65537, 65539, 65543, 65551, 65557, 65563, 65579, 65581,
+ 65587, 65599, 65609, 65617, 65629, 65633, 65647, 65651, 65657, 65677,
+ 65687, 65699, 65701, 65707, 65713, 65717, 65719, 65729, 65731, 65761,
+ 65777, 65789, 65809, 65827, 65831, 65837, 65839, 65843, 65851, 65867,
+ 65881, 65899, 65921, 65927, 65929, 65951, 65957, 65963, 65981, 65983,
+ 65993, 66029, 66037, 66041, 66047, 66067, 66071, 66083, 66089, 66103,
+ 66107, 66109, 66137, 66161, 66169, 66173, 66179, 66191, 66221, 66239,
+ 66271, 66293, 66301, 66337, 66343, 66347, 66359, 66361, 66373, 66377,
+ 66383, 66403, 66413, 66431, 66449, 66457, 66463, 66467, 66491, 66499,
+ 66509, 66523, 66529, 66533, 66541, 66553, 66569, 66571, 66587, 66593,
+ 66601, 66617, 66629, 66643, 66653, 66683, 66697, 66701, 66713, 66721,
+ 66733, 66739, 66749, 66751, 66763, 66791, 66797, 66809, 66821, 66841,
+ 66851, 66853, 66863, 66877, 66883, 66889, 66919, 66923, 66931, 66943,
+ 66947, 66949, 66959, 66973, 66977, 67003, 67021, 67033, 67043, 67049,
+ 67057, 67061, 67073, 67079, 67103, 67121, 67129, 67139, 67141, 67153,
+ 67157, 67169, 67181, 67187, 67189, 67211, 67213, 67217, 67219, 67231,
+ 67247, 67261, 67271, 67273, 67289, 67307, 67339, 67343, 67349, 67369,
+ 67391, 67399, 67409, 67411, 67421, 67427, 67429, 67433, 67447, 67453,
+ 67477, 67481, 67489, 67493, 67499, 67511, 67523, 67531, 67537, 67547,
+ 67559, 67567, 67577, 67579, 67589, 67601, 67607, 67619, 67631, 67651,
+ 67679, 67699, 67709, 67723, 67733, 67741, 67751, 67757, 67759, 67763,
+ 67777, 67783, 67789, 67801, 67807, 67819, 67829, 67843, 67853, 67867,
+ 67883, 67891, 67901, 67927, 67931, 67933, 67939, 67943, 67957, 67961,
+ 67967, 67979, 67987, 67993, 68023, 68041, 68053, 68059, 68071, 68087,
+ 68099, 68111, 68113, 68141, 68147, 68161, 68171, 68207, 68209, 68213,
+ 68219, 68227, 68239, 68261, 68279, 68281, 68311, 68329, 68351, 68371,
+ 68389, 68399, 68437, 68443, 68447, 68449, 68473, 68477, 68483, 68489,
+ 68491, 68501, 68507, 68521, 68531, 68539, 68543, 68567, 68581, 68597,
+ 68611, 68633, 68639, 68659, 68669, 68683, 68687, 68699, 68711, 68713,
+ 68729, 68737, 68743, 68749, 68767, 68771, 68777, 68791, 68813, 68819,
+ 68821, 68863, 68879, 68881, 68891, 68897, 68899, 68903, 68909, 68917,
+ 68927, 68947, 68963, 68993, 69001, 69011, 69019, 69029, 69031, 69061,
+ 69067, 69073, 69109, 69119, 69127, 69143, 69149, 69151, 69163, 69191,
+ 69193, 69197, 69203, 69221, 69233, 69239, 69247, 69257, 69259, 69263,
+ 69313, 69317, 69337, 69341, 69371, 69379, 69383, 69389, 69401, 69403,
+ 69427, 69431, 69439, 69457, 69463, 69467, 69473, 69481, 69491, 69493,
+ 69497, 69499, 69539, 69557, 69593, 69623, 69653, 69661, 69677, 69691,
+ 69697, 69709, 69737, 69739, 69761, 69763, 69767, 69779, 69809, 69821,
+ 69827, 69829, 69833, 69847, 69857, 69859, 69877, 69899, 69911, 69929,
+ 69931, 69941, 69959, 69991, 69997, 70001, 70003, 70009, 70019, 70039,
+ 70051, 70061, 70067, 70079, 70099, 70111, 70117, 70121, 70123, 70139,
+ 70141, 70157, 70163, 70177, 70181, 70183, 70199, 70201, 70207, 70223,
+ 70229, 70237, 70241, 70249, 70271, 70289, 70297, 70309, 70313, 70321,
+ 70327, 70351, 70373, 70379, 70381, 70393, 70423, 70429, 70439, 70451,
+ 70457, 70459, 70481, 70487, 70489, 70501, 70507, 70529, 70537, 70549,
+ 70571, 70573, 70583, 70589, 70607, 70619, 70621, 70627, 70639, 70657,
+ 70663, 70667, 70687, 70709, 70717, 70729, 70753, 70769, 70783, 70793,
+ 70823, 70841, 70843, 70849, 70853, 70867, 70877, 70879, 70891, 70901,
+ 70913, 70919, 70921, 70937, 70949, 70951, 70957, 70969, 70979, 70981,
+ 70991, 70997, 70999, 71011, 71023, 71039, 71059, 71069, 71081, 71089,
+ 71119, 71129, 71143, 71147, 71153, 71161, 71167, 71171, 71191, 71209,
+ 71233, 71237, 71249, 71257, 71261, 71263, 71287, 71293, 71317, 71327,
+ 71329, 71333, 71339, 71341, 71347, 71353, 71359, 71363, 71387, 71389,
+ 71399, 71411, 71413, 71419, 71429, 71437, 71443, 71453, 71471, 71473,
+ 71479, 71483, 71503, 71527, 71537, 71549, 71551, 71563, 71569, 71593,
+ 71597, 71633, 71647, 71663, 71671, 71693, 71699, 71707, 71711, 71713,
+ 71719, 71741, 71761, 71777, 71789, 71807, 71809, 71821, 71837, 71843,
+ 71849, 71861, 71867, 71879, 71881, 71887, 71899, 71909, 71917, 71933,
+ 71941, 71947, 71963, 71971, 71983, 71987, 71993, 71999, 72019, 72031,
+ 72043, 72047, 72053, 72073, 72077, 72089, 72091, 72101, 72103, 72109,
+ 72139, 72161, 72167, 72169, 72173, 72211, 72221, 72223, 72227, 72229,
+ 72251, 72253, 72269, 72271, 72277, 72287, 72307, 72313, 72337, 72341,
+ 72353, 72367, 72379, 72383, 72421, 72431, 72461, 72467, 72469, 72481,
+ 72493, 72497, 72503, 72533, 72547, 72551, 72559, 72577, 72613, 72617,
+ 72623, 72643, 72647, 72649, 72661, 72671, 72673, 72679, 72689, 72701,
+ 72707, 72719, 72727, 72733, 72739, 72763, 72767, 72797, 72817, 72823,
+ 72859, 72869, 72871, 72883, 72889, 72893, 72901, 72907, 72911, 72923,
+ 72931, 72937, 72949, 72953, 72959, 72973, 72977, 72997, 73009, 73013,
+ 73019, 73037, 73039, 73043, 73061, 73063, 73079, 73091, 73121, 73127,
+ 73133, 73141, 73181, 73189, 73237, 73243, 73259, 73277, 73291, 73303,
+ 73309, 73327, 73331, 73351, 73361, 73363, 73369, 73379, 73387, 73417,
+ 73421, 73433, 73453, 73459, 73471, 73477, 73483, 73517, 73523, 73529,
+ 73547, 73553, 73561, 73571, 73583, 73589, 73597, 73607, 73609, 73613,
+ 73637, 73643, 73651, 73673, 73679, 73681, 73693, 73699, 73709, 73721,
+ 73727, 73751, 73757, 73771, 73783, 73819, 73823, 73847, 73849, 73859,
+ 73867, 73877, 73883, 73897, 73907, 73939, 73943, 73951, 73961, 73973,
+ 73999, 74017, 74021, 74027, 74047, 74051, 74071, 74077, 74093, 74099,
+ 74101, 74131, 74143, 74149, 74159, 74161, 74167, 74177, 74189, 74197,
+ 74201, 74203, 74209, 74219, 74231, 74257, 74279, 74287, 74293, 74297,
+ 74311, 74317, 74323, 74353, 74357, 74363, 74377, 74381, 74383, 74411,
+ 74413, 74419, 74441, 74449, 74453, 74471, 74489, 74507, 74509, 74521,
+ 74527, 74531, 74551, 74561, 74567, 74573, 74587, 74597, 74609, 74611,
+ 74623, 74653, 74687, 74699, 74707, 74713, 74717, 74719, 74729, 74731,
+ 74747, 74759, 74761, 74771, 74779, 74797, 74821, 74827, 74831, 74843,
+ 74857, 74861, 74869, 74873, 74887, 74891, 74897, 74903, 74923, 74929,
+ 74933, 74941, 74959, 75011, 75013, 75017, 75029, 75037, 75041, 75079,
+ 75083, 75109, 75133, 75149, 75161, 75167, 75169, 75181, 75193, 75209,
+ 75211, 75217, 75223, 75227, 75239, 75253, 75269, 75277, 75289, 75307,
+ 75323, 75329, 75337, 75347, 75353, 75367, 75377, 75389, 75391, 75401,
+ 75403, 75407, 75431, 75437, 75479, 75503, 75511, 75521, 75527, 75533,
+ 75539, 75541, 75553, 75557, 75571, 75577, 75583, 75611, 75617, 75619,
+ 75629, 75641, 75653, 75659, 75679, 75683, 75689, 75703, 75707, 75709,
+ 75721, 75731, 75743, 75767, 75773, 75781, 75787, 75793, 75797, 75821,
+ 75833, 75853, 75869, 75883, 75913, 75931, 75937, 75941, 75967, 75979,
+ 75983, 75989, 75991, 75997, 76001, 76003, 76031, 76039, 76079, 76081,
+ 76091, 76099, 76103, 76123, 76129, 76147, 76157, 76159, 76163, 76207,
+ 76213, 76231, 76243, 76249, 76253, 76259, 76261, 76283, 76289, 76303,
+ 76333, 76343, 76367, 76369, 76379, 76387, 76403, 76421, 76423, 76441,
+ 76463, 76471, 76481, 76487, 76493, 76507, 76511, 76519, 76537, 76541,
+ 76543, 76561, 76579, 76597, 76603, 76607, 76631, 76649, 76651, 76667,
+ 76673, 76679, 76697, 76717, 76733, 76753, 76757, 76771, 76777, 76781,
+ 76801, 76819, 76829, 76831, 76837, 76847, 76871, 76873, 76883, 76907,
+ 76913, 76919, 76943, 76949, 76961, 76963, 76991, 77003, 77017, 77023,
+ 77029, 77041, 77047, 77069, 77081, 77093, 77101, 77137, 77141, 77153,
+ 77167, 77171, 77191, 77201, 77213, 77237, 77239, 77243, 77249, 77261,
+ 77263, 77267, 77269, 77279, 77291, 77317, 77323, 77339, 77347, 77351,
+ 77359, 77369, 77377, 77383, 77417, 77419, 77431, 77447, 77471, 77477,
+ 77479, 77489, 77491, 77509, 77513, 77521, 77527, 77543, 77549, 77551,
+ 77557, 77563, 77569, 77573, 77587, 77591, 77611, 77617, 77621, 77641,
+ 77647, 77659, 77681, 77687, 77689, 77699, 77711, 77713, 77719, 77723,
+ 77731, 77743, 77747, 77761, 77773, 77783, 77797, 77801, 77813, 77839,
+ 77849, 77863, 77867, 77893, 77899, 77929, 77933, 77951, 77969, 77977,
+ 77983, 77999, 78007, 78017, 78031, 78041, 78049, 78059, 78079, 78101,
+ 78121, 78137, 78139, 78157, 78163, 78167, 78173, 78179, 78191, 78193,
+ 78203, 78229, 78233, 78241, 78259, 78277, 78283, 78301, 78307, 78311,
+ 78317, 78341, 78347, 78367, 78401, 78427, 78437, 78439, 78467, 78479,
+ 78487, 78497, 78509, 78511, 78517, 78539, 78541, 78553, 78569, 78571,
+ 78577, 78583, 78593, 78607, 78623, 78643, 78649, 78653, 78691, 78697,
+ 78707, 78713, 78721, 78737, 78779, 78781, 78787, 78791, 78797, 78803,
+ 78809, 78823, 78839, 78853, 78857, 78877, 78887, 78889, 78893, 78901,
+ 78919, 78929, 78941, 78977, 78979, 78989, 79031, 79039, 79043, 79063,
+ 79087, 79103, 79111, 79133, 79139, 79147, 79151, 79153, 79159, 79181,
+ 79187, 79193, 79201, 79229, 79231, 79241, 79259, 79273, 79279, 79283,
+ 79301, 79309, 79319, 79333, 79337, 79349, 79357, 79367, 79379, 79393,
+ 79397, 79399, 79411, 79423, 79427, 79433, 79451, 79481, 79493, 79531,
+ 79537, 79549, 79559, 79561, 79579, 79589, 79601, 79609, 79613, 79621,
+ 79627, 79631, 79633, 79657, 79669, 79687, 79691, 79693, 79697, 79699,
+ 79757, 79769, 79777, 79801, 79811, 79813, 79817, 79823, 79829, 79841,
+ 79843, 79847, 79861, 79867, 79873, 79889, 79901, 79903, 79907, 79939,
+ 79943, 79967, 79973, 79979, 79987, 79997, 79999, 80021, 80039, 80051,
+ 80071, 80077, 80107, 80111, 80141, 80147, 80149, 80153, 80167, 80173,
+ 80177, 80191, 80207, 80209, 80221, 80231, 80233, 80239, 80251, 80263,
+ 80273, 80279, 80287, 80309, 80317, 80329, 80341, 80347, 80363, 80369,
+ 80387, 80407, 80429, 80447, 80449, 80471, 80473, 80489, 80491, 80513,
+ 80527, 80537, 80557, 80567, 80599, 80603, 80611, 80621, 80627, 80629,
+ 80651, 80657, 80669, 80671, 80677, 80681, 80683, 80687, 80701, 80713,
+ 80737, 80747, 80749, 80761, 80777, 80779, 80783, 80789, 80803, 80809,
+ 80819, 80831, 80833, 80849, 80863, 80897, 80909, 80911, 80917, 80923,
+ 80929, 80933, 80953, 80963, 80989, 81001, 81013, 81017, 81019, 81023,
+ 81031, 81041, 81043, 81047, 81049, 81071, 81077, 81083, 81097, 81101,
+ 81119, 81131, 81157, 81163, 81173, 81181, 81197, 81199, 81203, 81223,
+ 81233, 81239, 81281, 81283, 81293, 81299, 81307, 81331, 81343, 81349,
+ 81353, 81359, 81371, 81373, 81401, 81409, 81421, 81439, 81457, 81463,
+ 81509, 81517, 81527, 81533, 81547, 81551, 81553, 81559, 81563, 81569,
+ 81611, 81619, 81629, 81637, 81647, 81649, 81667, 81671, 81677, 81689,
+ 81701, 81703, 81707, 81727, 81737, 81749, 81761, 81769, 81773, 81799,
+ 81817, 81839, 81847, 81853, 81869, 81883, 81899, 81901, 81919, 81929,
+ 81931, 81937, 81943, 81953, 81967, 81971, 81973, 82003, 82007, 82009,
+ 82013, 82021, 82031, 82037, 82039, 82051, 82067, 82073, 82129, 82139,
+ 82141, 82153, 82163, 82171, 82183, 82189, 82193, 82207, 82217, 82219,
+ 82223, 82231, 82237, 82241, 82261, 82267, 82279, 82301, 82307, 82339,
+ 82349, 82351, 82361, 82373, 82387, 82393, 82421, 82457, 82463, 82469,
+ 82471, 82483, 82487, 82493, 82499, 82507, 82529, 82531, 82549, 82559,
+ 82561, 82567, 82571, 82591, 82601, 82609, 82613, 82619, 82633, 82651,
+ 82657, 82699, 82721, 82723, 82727, 82729, 82757, 82759, 82763, 82781,
+ 82787, 82793, 82799, 82811, 82813, 82837, 82847, 82883, 82889, 82891,
+ 82903, 82913, 82939, 82963, 82981, 82997, 83003, 83009, 83023, 83047,
+ 83059, 83063, 83071, 83077, 83089, 83093, 83101, 83117, 83137, 83177,
+ 83203, 83207, 83219, 83221, 83227, 83231, 83233, 83243, 83257, 83267,
+ 83269, 83273, 83299, 83311, 83339, 83341, 83357, 83383, 83389, 83399,
+ 83401, 83407, 83417, 83423, 83431, 83437, 83443, 83449, 83459, 83471,
+ 83477, 83497, 83537, 83557, 83561, 83563, 83579, 83591, 83597, 83609,
+ 83617, 83621, 83639, 83641, 83653, 83663, 83689, 83701, 83717, 83719,
+ 83737, 83761, 83773, 83777, 83791, 83813, 83833, 83843, 83857, 83869,
+ 83873, 83891, 83903, 83911, 83921, 83933, 83939, 83969, 83983, 83987,
+ 84011, 84017, 84047, 84053, 84059, 84061, 84067, 84089, 84121, 84127,
+ 84131, 84137, 84143, 84163, 84179, 84181, 84191, 84199, 84211, 84221,
+ 84223, 84229, 84239, 84247, 84263, 84299, 84307, 84313, 84317, 84319,
+ 84347, 84349, 84377, 84389, 84391, 84401, 84407, 84421, 84431, 84437,
+ 84443, 84449, 84457, 84463, 84467, 84481, 84499, 84503, 84509, 84521,
+ 84523, 84533, 84551, 84559, 84589, 84629, 84631, 84649, 84653, 84659,
+ 84673, 84691, 84697, 84701, 84713, 84719, 84731, 84737, 84751, 84761,
+ 84787, 84793, 84809, 84811, 84827, 84857, 84859, 84869, 84871, 84913,
+ 84919, 84947, 84961, 84967, 84977, 84979, 84991, 85009, 85021, 85027,
+ 85037, 85049, 85061, 85081, 85087, 85091, 85093, 85103, 85109, 85121,
+ 85133, 85147, 85159, 85193, 85199, 85201, 85213, 85223, 85229, 85237,
+ 85243, 85247, 85259, 85297, 85303, 85313, 85331, 85333, 85361, 85363,
+ 85369, 85381, 85411, 85427, 85429, 85439, 85447, 85451, 85453, 85469,
+ 85487, 85513, 85517, 85523, 85531, 85549, 85571, 85577, 85597, 85601,
+ 85607, 85619, 85621, 85627, 85639, 85643, 85661, 85667, 85669, 85691,
+ 85703, 85711, 85717, 85733, 85751, 85781, 85793, 85817, 85819, 85829,
+ 85831, 85837, 85843, 85847, 85853, 85889, 85903, 85909, 85931, 85933,
+ 85991, 85999, 86011, 86017, 86027, 86029, 86069, 86077, 86083, 86111,
+ 86113, 86117, 86131, 86137, 86143, 86161, 86171, 86179, 86183, 86197,
+ 86201, 86209, 86239, 86243, 86249, 86257, 86263, 86269, 86287, 86291,
+ 86293, 86297, 86311, 86323, 86341, 86351, 86353, 86357, 86369, 86371,
+ 86381, 86389, 86399, 86413, 86423, 86441, 86453, 86461, 86467, 86477,
+ 86491, 86501, 86509, 86531, 86533, 86539, 86561, 86573, 86579, 86587,
+ 86599, 86627, 86629, 86677, 86689, 86693, 86711, 86719, 86729, 86743,
+ 86753, 86767, 86771, 86783, 86813, 86837, 86843, 86851, 86857, 86861,
+ 86869, 86923, 86927, 86929, 86939, 86951, 86959, 86969, 86981, 86993,
+ 87011, 87013, 87037, 87041, 87049, 87071, 87083, 87103, 87107, 87119,
+ 87121, 87133, 87149, 87151, 87179, 87181, 87187, 87211, 87221, 87223,
+ 87251, 87253, 87257, 87277, 87281, 87293, 87299, 87313, 87317, 87323,
+ 87337, 87359, 87383, 87403, 87407, 87421, 87427, 87433, 87443, 87473,
+ 87481, 87491, 87509, 87511, 87517, 87523, 87539, 87541, 87547, 87553,
+ 87557, 87559, 87583, 87587, 87589, 87613, 87623, 87629, 87631, 87641,
+ 87643, 87649, 87671, 87679, 87683, 87691, 87697, 87701, 87719, 87721,
+ 87739, 87743, 87751, 87767, 87793, 87797, 87803, 87811, 87833, 87853,
+ 87869, 87877, 87881, 87887, 87911, 87917, 87931, 87943, 87959, 87961,
+ 87973, 87977, 87991, 88001, 88003, 88007, 88019, 88037, 88069, 88079,
+ 88093, 88117, 88129, 88169, 88177, 88211, 88223, 88237, 88241, 88259,
+ 88261, 88289, 88301, 88321, 88327, 88337, 88339, 88379, 88397, 88411,
+ 88423, 88427, 88463, 88469, 88471, 88493, 88499, 88513, 88523, 88547,
+ 88589, 88591, 88607, 88609, 88643, 88651, 88657, 88661, 88663, 88667,
+ 88681, 88721, 88729, 88741, 88747, 88771, 88789, 88793, 88799, 88801,
+ 88807, 88811, 88813, 88817, 88819, 88843, 88853, 88861, 88867, 88873,
+ 88883, 88897, 88903, 88919, 88937, 88951, 88969, 88993, 88997, 89003,
+ 89009, 89017, 89021, 89041, 89051, 89057, 89069, 89071, 89083, 89087,
+ 89101, 89107, 89113, 89119, 89123, 89137, 89153, 89189, 89203, 89209,
+ 89213, 89227, 89231, 89237, 89261, 89269, 89273, 89293, 89303, 89317,
+ 89329, 89363, 89371, 89381, 89387, 89393, 89399, 89413, 89417, 89431,
+ 89443, 89449, 89459, 89477, 89491, 89501, 89513, 89519, 89521, 89527,
+ 89533, 89561, 89563, 89567, 89591, 89597, 89599, 89603, 89611, 89627,
+ 89633, 89653, 89657, 89659, 89669, 89671, 89681, 89689, 89753, 89759,
+ 89767, 89779, 89783, 89797, 89809, 89819, 89821, 89833, 89839, 89849,
+ 89867, 89891, 89897, 89899, 89909, 89917, 89923, 89939, 89959, 89963,
+ 89977, 89983, 89989, 90001, 90007, 90011, 90017, 90019, 90023, 90031,
+ 90053, 90059, 90067, 90071, 90073, 90089, 90107, 90121, 90127, 90149,
+ 90163, 90173, 90187, 90191, 90197, 90199, 90203, 90217, 90227, 90239,
+ 90247, 90263, 90271, 90281, 90289, 90313, 90353, 90359, 90371, 90373,
+ 90379, 90397, 90401, 90403, 90407, 90437, 90439, 90469, 90473, 90481,
+ 90499, 90511, 90523, 90527, 90529, 90533, 90547, 90583, 90599, 90617,
+ 90619, 90631, 90641, 90647, 90659, 90677, 90679, 90697, 90703, 90709,
+ 90731, 90749, 90787, 90793, 90803, 90821, 90823, 90833, 90841, 90847,
+ 90863, 90887, 90901, 90907, 90911, 90917, 90931, 90947, 90971, 90977,
+ 90989, 90997, 91009, 91019, 91033, 91079, 91081, 91097, 91099, 91121,
+ 91127, 91129, 91139, 91141, 91151, 91153, 91159, 91163, 91183, 91193,
+ 91199, 91229, 91237, 91243, 91249, 91253, 91283, 91291, 91297, 91303,
+ 91309, 91331, 91367, 91369, 91373, 91381, 91387, 91393, 91397, 91411,
+ 91423, 91433, 91453, 91457, 91459, 91463, 91493, 91499, 91513, 91529,
+ 91541, 91571, 91573, 91577, 91583, 91591, 91621, 91631, 91639, 91673,
+ 91691, 91703, 91711, 91733, 91753, 91757, 91771, 91781, 91801, 91807,
+ 91811, 91813, 91823, 91837, 91841, 91867, 91873, 91909, 91921, 91939,
+ 91943, 91951, 91957, 91961, 91967, 91969, 91997, 92003, 92009, 92033,
+ 92041, 92051, 92077, 92083, 92107, 92111, 92119, 92143, 92153, 92173,
+ 92177, 92179, 92189, 92203, 92219, 92221, 92227, 92233, 92237, 92243,
+ 92251, 92269, 92297, 92311, 92317, 92333, 92347, 92353, 92357, 92363,
+ 92369, 92377, 92381, 92383, 92387, 92399, 92401, 92413, 92419, 92431,
+ 92459, 92461, 92467, 92479, 92489, 92503, 92507, 92551, 92557, 92567,
+ 92569, 92581, 92593, 92623, 92627, 92639, 92641, 92647, 92657, 92669,
+ 92671, 92681, 92683, 92693, 92699, 92707, 92717, 92723, 92737, 92753,
+ 92761, 92767, 92779, 92789, 92791, 92801, 92809, 92821, 92831, 92849,
+ 92857, 92861, 92863, 92867, 92893, 92899, 92921, 92927, 92941, 92951,
+ 92957, 92959, 92987, 92993, 93001, 93047, 93053, 93059, 93077, 93083,
+ 93089, 93097, 93103, 93113, 93131, 93133, 93139, 93151, 93169, 93179,
+ 93187, 93199, 93229, 93239, 93241, 93251, 93253, 93257, 93263, 93281,
+ 93283, 93287, 93307, 93319, 93323, 93329, 93337, 93371, 93377, 93383,
+ 93407, 93419, 93427, 93463, 93479, 93481, 93487, 93491, 93493, 93497,
+ 93503, 93523, 93529, 93553, 93557, 93559, 93563, 93581, 93601, 93607,
+ 93629, 93637, 93683, 93701, 93703, 93719, 93739, 93761, 93763, 93787,
+ 93809, 93811, 93827, 93851, 93871, 93887, 93889, 93893, 93901, 93911,
+ 93913, 93923, 93937, 93941, 93949, 93967, 93971, 93979, 93983, 93997,
+ 94007, 94009, 94033, 94049, 94057, 94063, 94079, 94099, 94109, 94111,
+ 94117, 94121, 94151, 94153, 94169, 94201, 94207, 94219, 94229, 94253,
+ 94261, 94273, 94291, 94307, 94309, 94321, 94327, 94331, 94343, 94349,
+ 94351, 94379, 94397, 94399, 94421, 94427, 94433, 94439, 94441, 94447,
+ 94463, 94477, 94483, 94513, 94529, 94531, 94541, 94543, 94547, 94559,
+ 94561, 94573, 94583, 94597, 94603, 94613, 94621, 94649, 94651, 94687,
+ 94693, 94709, 94723, 94727, 94747, 94771, 94777, 94781, 94789, 94793,
+ 94811, 94819, 94823, 94837, 94841, 94847, 94849, 94873, 94889, 94903,
+ 94907, 94933, 94949, 94951, 94961, 94993, 94999, 95003, 95009, 95021,
+ 95027, 95063, 95071, 95083, 95087, 95089, 95093, 95101, 95107, 95111,
+ 95131, 95143, 95153, 95177, 95189, 95191, 95203, 95213, 95219, 95231,
+ 95233, 95239, 95257, 95261, 95267, 95273, 95279, 95287, 95311, 95317,
+ 95327, 95339, 95369, 95383, 95393, 95401, 95413, 95419, 95429, 95441,
+ 95443, 95461, 95467, 95471, 95479, 95483, 95507, 95527, 95531, 95539,
+ 95549, 95561, 95569, 95581, 95597, 95603, 95617, 95621, 95629, 95633,
+ 95651, 95701, 95707, 95713, 95717, 95723, 95731, 95737, 95747, 95773,
+ 95783, 95789, 95791, 95801, 95803, 95813, 95819, 95857, 95869, 95873,
+ 95881, 95891, 95911, 95917, 95923, 95929, 95947, 95957, 95959, 95971,
+ 95987, 95989, 96001, 96013, 96017, 96043, 96053, 96059, 96079, 96097,
+ 96137, 96149, 96157, 96167, 96179, 96181, 96199, 96211, 96221, 96223,
+ 96233, 96259, 96263, 96269, 96281, 96289, 96293, 96323, 96329, 96331,
+ 96337, 96353, 96377, 96401, 96419, 96431, 96443, 96451, 96457, 96461,
+ 96469, 96479, 96487, 96493, 96497, 96517, 96527, 96553, 96557, 96581,
+ 96587, 96589, 96601, 96643, 96661, 96667, 96671, 96697, 96703, 96731,
+ 96737, 96739, 96749, 96757, 96763, 96769, 96779, 96787, 96797, 96799,
+ 96821, 96823, 96827, 96847, 96851, 96857, 96893, 96907, 96911, 96931,
+ 96953, 96959, 96973, 96979, 96989, 96997, 97001, 97003, 97007, 97021,
+ 97039, 97073, 97081, 97103, 97117, 97127, 97151, 97157, 97159, 97169,
+ 97171, 97177, 97187, 97213, 97231, 97241, 97259, 97283, 97301, 97303,
+ 97327, 97367, 97369, 97373, 97379, 97381, 97387, 97397, 97423, 97429,
+ 97441, 97453, 97459, 97463, 97499, 97501, 97511, 97523, 97547, 97549,
+ 97553, 97561, 97571, 97577, 97579, 97583, 97607, 97609, 97613, 97649,
+ 97651, 97673, 97687, 97711, 97729, 97771, 97777, 97787, 97789, 97813,
+ 97829, 97841, 97843, 97847, 97849, 97859, 97861, 97871, 97879, 97883,
+ 97919, 97927, 97931, 97943, 97961, 97967, 97973, 97987, 98009, 98011,
+ 98017, 98041, 98047, 98057, 98081, 98101, 98123, 98129, 98143, 98179,
+ 98207, 98213, 98221, 98227, 98251, 98257, 98269, 98297, 98299, 98317,
+ 98321, 98323, 98327, 98347, 98369, 98377, 98387, 98389, 98407, 98411,
+ 98419, 98429, 98443, 98453, 98459, 98467, 98473, 98479, 98491, 98507,
+ 98519, 98533, 98543, 98561, 98563, 98573, 98597, 98621, 98627, 98639,
+ 98641, 98663, 98669, 98689, 98711, 98713, 98717, 98729, 98731, 98737,
+ 98773, 98779, 98801, 98807, 98809, 98837, 98849, 98867, 98869, 98873,
+ 98887, 98893, 98897, 98899, 98909, 98911, 98927, 98929, 98939, 98947,
+ 98953, 98963, 98981, 98993, 98999, 99013, 99017, 99023, 99041, 99053,
+ 99079, 99083, 99089, 99103, 99109, 99119, 99131, 99133, 99137, 99139,
+ 99149, 99173, 99181, 99191, 99223, 99233, 99241, 99251, 99257, 99259,
+ 99277, 99289, 99317, 99347, 99349, 99367, 99371, 99377, 99391, 99397,
+ 99401, 99409, 99431, 99439, 99469, 99487, 99497, 99523, 99527, 99529,
+ 99551, 99559, 99563, 99571, 99577, 99581, 99607, 99611, 99623, 99643,
+ 99661, 99667, 99679, 99689, 99707, 99709, 99713, 99719, 99721, 99733,
+ 99761, 99767, 99787, 99793, 99809, 99817, 99823, 99829, 99833, 99839,
+ 99859, 99871, 99877, 99881, 99901, 99907, 99923, 99929, 99961, 99971,
+ 99989, 99991, 100003, 100019, 100043, 100049, 100057, 100069, 100103, 100109,
+100129, 100151, 100153, 100169, 100183, 100189, 100193, 100207, 100213, 100237,
+100267, 100271, 100279, 100291, 100297, 100313, 100333, 100343, 100357, 100361,
+100363, 100379, 100391, 100393, 100403, 100411, 100417, 100447, 100459, 100469,
+100483, 100493, 100501, 100511, 100517, 100519, 100523, 100537, 100547, 100549,
+100559, 100591, 100609, 100613, 100621, 100649, 100669, 100673, 100693, 100699,
+100703, 100733, 100741, 100747, 100769, 100787, 100799, 100801, 100811, 100823,
+100829, 100847, 100853, 100907, 100913, 100927, 100931, 100937, 100943, 100957,
+100981, 100987, 100999, 101009, 101021, 101027, 101051, 101063, 101081, 101089,
+101107, 101111, 101113, 101117, 101119, 101141, 101149, 101159, 101161, 101173,
+101183, 101197, 101203, 101207, 101209, 101221, 101267, 101273, 101279, 101281,
+101287, 101293, 101323, 101333, 101341, 101347, 101359, 101363, 101377, 101383,
+101399, 101411, 101419, 101429, 101449, 101467, 101477, 101483, 101489, 101501,
+101503, 101513, 101527, 101531, 101533, 101537, 101561, 101573, 101581, 101599,
+101603, 101611, 101627, 101641, 101653, 101663, 101681, 101693, 101701, 101719,
+101723, 101737, 101741, 101747, 101749, 101771, 101789, 101797, 101807, 101833,
+101837, 101839, 101863, 101869, 101873, 101879, 101891, 101917, 101921, 101929,
+101939, 101957, 101963, 101977, 101987, 101999, 102001, 102013, 102019, 102023,
+102031, 102043, 102059, 102061, 102071, 102077, 102079, 102101, 102103, 102107,
+102121, 102139, 102149, 102161, 102181, 102191, 102197, 102199, 102203, 102217,
+102229, 102233, 102241, 102251, 102253, 102259, 102293, 102299, 102301, 102317,
+102329, 102337, 102359, 102367, 102397, 102407, 102409, 102433, 102437, 102451,
+102461, 102481, 102497, 102499, 102503, 102523, 102533, 102539, 102547, 102551,
+102559, 102563, 102587, 102593, 102607, 102611, 102643, 102647, 102653, 102667,
+102673, 102677, 102679, 102701, 102761, 102763, 102769, 102793, 102797, 102811,
+102829, 102841, 102859, 102871, 102877, 102881, 102911, 102913, 102929, 102931,
+102953, 102967, 102983, 103001, 103007, 103043, 103049, 103067, 103069, 103079,
+103087, 103091, 103093, 103099, 103123, 103141, 103171, 103177, 103183, 103217,
+103231, 103237, 103289, 103291, 103307, 103319, 103333, 103349, 103357, 103387,
+103391, 103393, 103399, 103409, 103421, 103423, 103451, 103457, 103471, 103483,
+103511, 103529, 103549, 103553, 103561, 103567, 103573, 103577, 103583, 103591,
+103613, 103619, 103643, 103651, 103657, 103669, 103681, 103687, 103699, 103703,
+103723, 103769, 103787, 103801, 103811, 103813, 103837, 103841, 103843, 103867,
+103889, 103903, 103913, 103919, 103951, 103963, 103967, 103969, 103979, 103981,
+103991, 103993, 103997, 104003, 104009, 104021, 104033, 104047, 104053, 104059,
+104087, 104089, 104107, 104113, 104119, 104123, 104147, 104149, 104161, 104173,
+104179, 104183, 104207, 104231, 104233, 104239, 104243, 104281, 104287, 104297,
+104309, 104311, 104323, 104327, 104347, 104369, 104381, 104383, 104393, 104399,
+104417, 104459, 104471, 104473, 104479, 104491, 104513, 104527, 104537, 104543,
+104549, 104551, 104561, 104579, 104593, 104597, 104623, 104639, 104651, 104659,
+104677, 104681, 104683, 104693, 104701, 104707, 104711, 104717, 104723, 104729,
+)
diff --git a/frozen_deps/Crypto/Util/py3compat.py b/frozen_deps/Crypto/Util/py3compat.py
new file mode 100644
index 0000000..f8367c9
--- /dev/null
+++ b/frozen_deps/Crypto/Util/py3compat.py
@@ -0,0 +1,107 @@
+# -*- coding: utf-8 -*-
+#
+# Util/py3compat.py : Compatibility code for handling Py3k / Python 2.x
+#
+# Written in 2010 by Thorsten Behrens
+#
+# ===================================================================
+# The contents of this file are dedicated to the public domain. To
+# the extent that dedication to the public domain is not available,
+# everyone is granted a worldwide, perpetual, royalty-free,
+# non-exclusive license to exercise all rights associated with the
+# contents of this file for any purpose whatsoever.
+# No rights are reserved.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+# SOFTWARE.
+# ===================================================================
+
+"""Compatibility code for handling string/bytes changes from Python 2.x to Py3k
+
+In Python 2.x, strings (of type ''str'') contain binary data, including encoded
+Unicode text (e.g. UTF-8). The separate type ''unicode'' holds Unicode text.
+Unicode literals are specified via the u'...' prefix. Indexing or slicing
+either type always produces a string of the same type as the original.
+Data read from a file is always of '''str'' type.
+
+In Python 3.x, strings (type ''str'') may only contain Unicode text. The u'...'
+prefix and the ''unicode'' type are now redundant. A new type (called
+''bytes'') has to be used for binary data (including any particular
+''encoding'' of a string). The b'...' prefix allows one to specify a binary
+literal. Indexing or slicing a string produces another string. Slicing a byte
+string produces another byte string, but the indexing operation produces an
+integer. Data read from a file is of '''str'' type if the file was opened in
+text mode, or of ''bytes'' type otherwise.
+
+Since PyCrypto aims at supporting both Python 2.x and 3.x, the following helper
+functions are used to keep the rest of the library as independent as possible
+from the actual Python version.
+
+In general, the code should always deal with binary strings, and use integers
+instead of 1-byte character strings.
+
+b(s)
+ Take a text string literal (with no prefix or with u'...' prefix) and
+ make a byte string.
+bchr(c)
+ Take an integer and make a 1-character byte string.
+bord(c)
+ Take the result of indexing on a byte string and make an integer.
+tobytes(s)
+ Take a text string, a byte string, or a sequence of character taken from
+ a byte string and make a byte string.
+"""
+
+__revision__ = "$Id$"
+
+import sys
+
+if sys.version_info[0] == 2:
+ def b(s):
+ return s
+ def bchr(s):
+ return chr(s)
+ def bstr(s):
+ return str(s)
+ def bord(s):
+ return ord(s)
+ if sys.version_info[1] == 1:
+ def tobytes(s):
+ try:
+ return s.encode('latin-1')
+ except:
+ return ''.join(s)
+ else:
+ def tobytes(s):
+ if isinstance(s, str):
+ return s.encode("latin-1")
+ else:
+ return ''.join(s)
+else:
+ def b(s):
+ return s.encode("latin-1") # utf-8 would cause some side-effects we don't want
+ def bchr(s):
+ return bytes([s])
+ def bstr(s):
+ if isinstance(s,str):
+ return bytes(s,"latin-1")
+ else:
+ return bytes(s)
+ def bord(s):
+ return s
+ def tobytes(s):
+ if isinstance(s,bytes):
+ return s
+ else:
+ if isinstance(s,str):
+ return s.encode("latin-1")
+ else:
+ return bytes(s)
+
+# vim:set ts=4 sw=4 sts=4 expandtab:
diff --git a/frozen_deps/Crypto/Util/randpool.py b/frozen_deps/Crypto/Util/randpool.py
new file mode 100644
index 0000000..8b5a0b7
--- /dev/null
+++ b/frozen_deps/Crypto/Util/randpool.py
@@ -0,0 +1,82 @@
+#
+# randpool.py : Cryptographically strong random number generation
+#
+# Part of the Python Cryptography Toolkit
+#
+# Written by Andrew M. Kuchling, Mark Moraes, and others
+#
+# ===================================================================
+# The contents of this file are dedicated to the public domain. To
+# the extent that dedication to the public domain is not available,
+# everyone is granted a worldwide, perpetual, royalty-free,
+# non-exclusive license to exercise all rights associated with the
+# contents of this file for any purpose whatsoever.
+# No rights are reserved.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+# SOFTWARE.
+# ===================================================================
+#
+
+__revision__ = "$Id$"
+
+from Crypto.pct_warnings import RandomPool_DeprecationWarning
+import Crypto.Random
+import warnings
+
+class RandomPool:
+ """Deprecated. Use Random.new() instead.
+
+ See http://www.pycrypto.org/randpool-broken
+ """
+ def __init__(self, numbytes = 160, cipher=None, hash=None, file=None):
+ warnings.warn("This application uses RandomPool, which is BROKEN in older releases. See http://www.pycrypto.org/randpool-broken",
+ RandomPool_DeprecationWarning)
+ self.__rng = Crypto.Random.new()
+ self.bytes = numbytes
+ self.bits = self.bytes * 8
+ self.entropy = self.bits
+
+ def get_bytes(self, N):
+ return self.__rng.read(N)
+
+ def _updateEntropyEstimate(self, nbits):
+ self.entropy += nbits
+ if self.entropy < 0:
+ self.entropy = 0
+ elif self.entropy > self.bits:
+ self.entropy = self.bits
+
+ def _randomize(self, N=0, devname="/dev/urandom"):
+ """Dummy _randomize() function"""
+ self.__rng.flush()
+
+ def randomize(self, N=0):
+ """Dummy randomize() function"""
+ self.__rng.flush()
+
+ def stir(self, s=''):
+ """Dummy stir() function"""
+ self.__rng.flush()
+
+ def stir_n(self, N=3):
+ """Dummy stir_n() function"""
+ self.__rng.flush()
+
+ def add_event(self, s=''):
+ """Dummy add_event() function"""
+ self.__rng.flush()
+
+ def getBytes(self, N):
+ """Dummy getBytes() function"""
+ return self.get_bytes(N)
+
+ def addEvent(self, event, s=""):
+ """Dummy addEvent() function"""
+ return self.add_event()
diff --git a/frozen_deps/Crypto/Util/strxor.cpython-38-x86_64-linux-gnu.so b/frozen_deps/Crypto/Util/strxor.cpython-38-x86_64-linux-gnu.so
new file mode 100755
index 0000000..8358023
--- /dev/null
+++ b/frozen_deps/Crypto/Util/strxor.cpython-38-x86_64-linux-gnu.so
Binary files differ
diff --git a/frozen_deps/Crypto/Util/winrandom.py b/frozen_deps/Crypto/Util/winrandom.py
new file mode 100644
index 0000000..0242815
--- /dev/null
+++ b/frozen_deps/Crypto/Util/winrandom.py
@@ -0,0 +1,28 @@
+#
+# Util/winrandom.py : Stub for Crypto.Random.OSRNG.winrandom
+#
+# Written in 2008 by Dwayne C. Litzenberger <[email protected]>
+#
+# ===================================================================
+# The contents of this file are dedicated to the public domain. To
+# the extent that dedication to the public domain is not available,
+# everyone is granted a worldwide, perpetual, royalty-free,
+# non-exclusive license to exercise all rights associated with the
+# contents of this file for any purpose whatsoever.
+# No rights are reserved.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+# SOFTWARE.
+# ===================================================================
+
+__revision__ = "$Id$"
+
+from Crypto.Random.OSRNG.winrandom import *
+
+# vim:set ts=4 sw=4 sts=4 expandtab:
diff --git a/frozen_deps/Crypto/__init__.py b/frozen_deps/Crypto/__init__.py
new file mode 100644
index 0000000..c27402e
--- /dev/null
+++ b/frozen_deps/Crypto/__init__.py
@@ -0,0 +1,51 @@
+# -*- coding: utf-8 -*-
+#
+# ===================================================================
+# The contents of this file are dedicated to the public domain. To
+# the extent that dedication to the public domain is not available,
+# everyone is granted a worldwide, perpetual, royalty-free,
+# non-exclusive license to exercise all rights associated with the
+# contents of this file for any purpose whatsoever.
+# No rights are reserved.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+# SOFTWARE.
+# ===================================================================
+
+"""Python Cryptography Toolkit
+
+A collection of cryptographic modules implementing various algorithms
+and protocols.
+
+Subpackages:
+
+Crypto.Cipher
+ Secret-key (AES, DES, ARC4) and public-key encryption (RSA PKCS#1) algorithms
+Crypto.Hash
+ Hashing algorithms (MD5, SHA, HMAC)
+Crypto.Protocol
+ Cryptographic protocols (Chaffing, all-or-nothing transform, key derivation
+ functions). This package does not contain any network protocols.
+Crypto.PublicKey
+ Public-key encryption and signature algorithms (RSA, DSA)
+Crypto.Signature
+ Public-key signature algorithms (RSA PKCS#1)
+Crypto.Util
+ Various useful modules and functions (long-to-string conversion, random number
+ generation, number theoretic functions)
+"""
+
+__all__ = ['Cipher', 'Hash', 'Protocol', 'PublicKey', 'Util', 'Signature']
+
+__version__ = '2.6.1' # See also below and setup.py
+__revision__ = "$Id$"
+
+# New software should look at this instead of at __version__ above.
+version_info = (2, 6, 1, 'final', 0) # See also above and setup.py
+
diff --git a/frozen_deps/Crypto/pct_warnings.py b/frozen_deps/Crypto/pct_warnings.py
new file mode 100644
index 0000000..9b4361e
--- /dev/null
+++ b/frozen_deps/Crypto/pct_warnings.py
@@ -0,0 +1,60 @@
+# -*- coding: ascii -*-
+#
+# pct_warnings.py : PyCrypto warnings file
+#
+# Written in 2008 by Dwayne C. Litzenberger <[email protected]>
+#
+# ===================================================================
+# The contents of this file are dedicated to the public domain. To
+# the extent that dedication to the public domain is not available,
+# everyone is granted a worldwide, perpetual, royalty-free,
+# non-exclusive license to exercise all rights associated with the
+# contents of this file for any purpose whatsoever.
+# No rights are reserved.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+# SOFTWARE.
+# ===================================================================
+
+#
+# Base classes. All our warnings inherit from one of these in order to allow
+# the user to specifically filter them.
+#
+
+class CryptoWarning(Warning):
+ """Base class for PyCrypto warnings"""
+
+class CryptoDeprecationWarning(DeprecationWarning, CryptoWarning):
+ """Base PyCrypto DeprecationWarning class"""
+
+class CryptoRuntimeWarning(RuntimeWarning, CryptoWarning):
+ """Base PyCrypto RuntimeWarning class"""
+
+#
+# Warnings that we might actually use
+#
+
+class RandomPool_DeprecationWarning(CryptoDeprecationWarning):
+ """Issued when Crypto.Util.randpool.RandomPool is instantiated."""
+
+class ClockRewindWarning(CryptoRuntimeWarning):
+ """Warning for when the system clock moves backwards."""
+
+class GetRandomNumber_DeprecationWarning(CryptoDeprecationWarning):
+ """Issued when Crypto.Util.number.getRandomNumber is invoked."""
+
+class PowmInsecureWarning(CryptoRuntimeWarning):
+ """Warning for when _fastmath is built without mpz_powm_sec"""
+
+# By default, we want this warning to be shown every time we compensate for
+# clock rewinding.
+import warnings as _warnings
+_warnings.filterwarnings('always', category=ClockRewindWarning, append=1)
+
+# vim:set ts=4 sw=4 sts=4 expandtab:
diff --git a/frozen_deps/_pysha3.cpython-38-x86_64-linux-gnu.so b/frozen_deps/_pysha3.cpython-38-x86_64-linux-gnu.so
new file mode 100755
index 0000000..0d09638
--- /dev/null
+++ b/frozen_deps/_pysha3.cpython-38-x86_64-linux-gnu.so
Binary files differ
diff --git a/frozen_deps/base58-2.0.1.dist-info/COPYING b/frozen_deps/base58-2.0.1.dist-info/COPYING
new file mode 100644
index 0000000..342bd62
--- /dev/null
+++ b/frozen_deps/base58-2.0.1.dist-info/COPYING
@@ -0,0 +1,19 @@
+Copyright (c) 2015 David Keijser
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
diff --git a/frozen_deps/base58-2.0.1.dist-info/INSTALLER b/frozen_deps/base58-2.0.1.dist-info/INSTALLER
new file mode 100644
index 0000000..a1b589e
--- /dev/null
+++ b/frozen_deps/base58-2.0.1.dist-info/INSTALLER
@@ -0,0 +1 @@
+pip
diff --git a/frozen_deps/base58-2.0.1.dist-info/METADATA b/frozen_deps/base58-2.0.1.dist-info/METADATA
new file mode 100644
index 0000000..22a37ad
--- /dev/null
+++ b/frozen_deps/base58-2.0.1.dist-info/METADATA
@@ -0,0 +1,20 @@
+Metadata-Version: 2.1
+Name: base58
+Version: 2.0.1
+Summary: Base58 and Base58Check implementation
+Home-page: https://github.com/keis/base58
+Author: David Keijser
+Author-email: [email protected]
+License: MIT
+Platform: UNKNOWN
+Classifier: Development Status :: 5 - Production/Stable
+Classifier: Intended Audience :: Developers
+Classifier: Natural Language :: English
+Classifier: License :: OSI Approved :: MIT License
+Classifier: Programming Language :: Python
+Classifier: Programming Language :: Python :: 3
+Requires-Python: >=3.5
+
+UNKNOWN
+
+
diff --git a/frozen_deps/base58-2.0.1.dist-info/RECORD b/frozen_deps/base58-2.0.1.dist-info/RECORD
new file mode 100644
index 0000000..d20c1c2
--- /dev/null
+++ b/frozen_deps/base58-2.0.1.dist-info/RECORD
@@ -0,0 +1,13 @@
+../../bin/base58,sha256=WWCKVkDRfe64OQtfsxf-b0PQGIclDIn84xO8gkjjWcY,213
+base58-2.0.1.dist-info/COPYING,sha256=z0aU8EC3oxzY7D280LWDpgHA1MN94Ba-eqCgbjpqOlQ,1057
+base58-2.0.1.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4
+base58-2.0.1.dist-info/METADATA,sha256=r4yScmUS3A8Yx7mmsSyaqfMSINg6FAIQK2ocWJO1tJw,540
+base58-2.0.1.dist-info/RECORD,,
+base58-2.0.1.dist-info/WHEEL,sha256=p46_5Uhzqz6AzeSosiOnxK-zmFja1i22CrQCjmYe8ec,92
+base58-2.0.1.dist-info/entry_points.txt,sha256=7WwcggBSeBwcC22-LkpqMOCaPdey0nOG3QEaKok403Y,49
+base58-2.0.1.dist-info/top_level.txt,sha256=BVSonMPECDcX_2XqQ7iILRqitlshZNNEmLCEWlpvUvI,7
+base58/__init__.py,sha256=ccX9CZMek4UC0edA_cHs71MgC4YqJCPBhvycuzhbucc,3085
+base58/__main__.py,sha256=OiE3DXq4vwYyAVYC3SM9Y0AQbMuS2IA0v2mvzwv96pk,1080
+base58/__pycache__/__init__.cpython-38.pyc,,
+base58/__pycache__/__main__.cpython-38.pyc,,
+base58/py.typed,sha256=dcrsqJrcYfTX-ckLFJMTaj6mD8aDe2u0tkQG-ZYxnEg,26
diff --git a/frozen_deps/base58-2.0.1.dist-info/WHEEL b/frozen_deps/base58-2.0.1.dist-info/WHEEL
new file mode 100644
index 0000000..3b5c403
--- /dev/null
+++ b/frozen_deps/base58-2.0.1.dist-info/WHEEL
@@ -0,0 +1,5 @@
+Wheel-Version: 1.0
+Generator: bdist_wheel (0.33.6)
+Root-Is-Purelib: true
+Tag: py3-none-any
+
diff --git a/frozen_deps/base58-2.0.1.dist-info/entry_points.txt b/frozen_deps/base58-2.0.1.dist-info/entry_points.txt
new file mode 100644
index 0000000..dc6d6a2
--- /dev/null
+++ b/frozen_deps/base58-2.0.1.dist-info/entry_points.txt
@@ -0,0 +1,3 @@
+[console_scripts]
+base58 = base58.__main__:main
+
diff --git a/frozen_deps/base58-2.0.1.dist-info/top_level.txt b/frozen_deps/base58-2.0.1.dist-info/top_level.txt
new file mode 100644
index 0000000..b4c9d71
--- /dev/null
+++ b/frozen_deps/base58-2.0.1.dist-info/top_level.txt
@@ -0,0 +1 @@
+base58
diff --git a/frozen_deps/base58/__init__.py b/frozen_deps/base58/__init__.py
new file mode 100644
index 0000000..ff2fa18
--- /dev/null
+++ b/frozen_deps/base58/__init__.py
@@ -0,0 +1,130 @@
+'''Base58 encoding
+
+Implementations of Base58 and Base58Check encodings that are compatible
+with the bitcoin network.
+'''
+
+# This module is based upon base58 snippets found scattered over many bitcoin
+# tools written in python. From what I gather the original source is from a
+# forum post by Gavin Andresen, so direct your praise to him.
+# This module adds shiny packaging and support for python3.
+
+from hashlib import sha256
+from typing import Union
+
+__version__ = '2.0.1'
+
+# 58 character alphabet used
+BITCOIN_ALPHABET = \
+ b'123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz'
+RIPPLE_ALPHABET = b'rpshnaf39wBUDNEGHJKLM4PQRST7VWXYZ2bcdeCg65jkm8oFqi1tuvAxyz'
+
+# Retro compatibility
+alphabet = BITCOIN_ALPHABET
+
+
+def scrub_input(v: Union[str, bytes]) -> bytes:
+ if isinstance(v, str):
+ v = v.encode('ascii')
+
+ return v
+
+
+def b58encode_int(
+ i: int, default_one: bool = True, alphabet: bytes = BITCOIN_ALPHABET
+) -> bytes:
+ """
+ Encode an integer using Base58
+ """
+ if not i and default_one:
+ return alphabet[0:1]
+ string = b""
+ while i:
+ i, idx = divmod(i, 58)
+ string = alphabet[idx:idx+1] + string
+ return string
+
+
+def b58encode(
+ v: Union[str, bytes], alphabet: bytes = BITCOIN_ALPHABET
+) -> bytes:
+ """
+ Encode a string using Base58
+ """
+ v = scrub_input(v)
+
+ nPad = len(v)
+ v = v.lstrip(b'\0')
+ nPad -= len(v)
+
+ p, acc = 1, 0
+ for c in reversed(v):
+ acc += p * c
+ p = p << 8
+ result = b58encode_int(acc, default_one=False, alphabet=alphabet)
+ return alphabet[0:1] * nPad + result
+
+
+def b58decode_int(
+ v: Union[str, bytes], alphabet: bytes = BITCOIN_ALPHABET
+) -> int:
+ """
+ Decode a Base58 encoded string as an integer
+ """
+ v = v.rstrip()
+ v = scrub_input(v)
+
+ decimal = 0
+ for char in v:
+ decimal = decimal * 58 + alphabet.index(char)
+ return decimal
+
+
+def b58decode(
+ v: Union[str, bytes], alphabet: bytes = BITCOIN_ALPHABET
+) -> bytes:
+ """
+ Decode a Base58 encoded string
+ """
+ v = v.rstrip()
+ v = scrub_input(v)
+
+ origlen = len(v)
+ v = v.lstrip(alphabet[0:1])
+ newlen = len(v)
+
+ acc = b58decode_int(v, alphabet=alphabet)
+
+ result = []
+ while acc > 0:
+ acc, mod = divmod(acc, 256)
+ result.append(mod)
+
+ return b'\0' * (origlen - newlen) + bytes(reversed(result))
+
+
+def b58encode_check(
+ v: Union[str, bytes], alphabet: bytes = BITCOIN_ALPHABET
+) -> bytes:
+ """
+ Encode a string using Base58 with a 4 character checksum
+ """
+ v = scrub_input(v)
+
+ digest = sha256(sha256(v).digest()).digest()
+ return b58encode(v + digest[:4], alphabet=alphabet)
+
+
+def b58decode_check(
+ v: Union[str, bytes], alphabet: bytes = BITCOIN_ALPHABET
+) -> bytes:
+ '''Decode and verify the checksum of a Base58 encoded string'''
+
+ result = b58decode(v, alphabet=alphabet)
+ result, check = result[:-4], result[-4:]
+ digest = sha256(sha256(result).digest()).digest()
+
+ if check != digest[:4]:
+ raise ValueError("Invalid checksum")
+
+ return result
diff --git a/frozen_deps/base58/__main__.py b/frozen_deps/base58/__main__.py
new file mode 100644
index 0000000..b76fdad
--- /dev/null
+++ b/frozen_deps/base58/__main__.py
@@ -0,0 +1,47 @@
+import argparse
+import sys
+
+from base58 import b58decode, b58decode_check, b58encode, b58encode_check
+
+
+def main():
+ '''Base58 encode or decode FILE, or standard input, to standard output.'''
+
+ stdout = sys.stdout.buffer
+
+ parser = argparse.ArgumentParser(description=main.__doc__)
+ parser.add_argument(
+ 'file',
+ metavar='FILE',
+ nargs='?',
+ type=argparse.FileType('r'),
+ default='-')
+ parser.add_argument(
+ '-d', '--decode',
+ action='store_true',
+ help='decode data')
+ parser.add_argument(
+ '-c', '--check',
+ action='store_true',
+ help='append a checksum before encoding')
+
+ args = parser.parse_args()
+ fun = {
+ (False, False): b58encode,
+ (False, True): b58encode_check,
+ (True, False): b58decode,
+ (True, True): b58decode_check
+ }[(args.decode, args.check)]
+
+ data = args.file.buffer.read()
+
+ try:
+ result = fun(data)
+ except Exception as e:
+ sys.exit(e)
+
+ stdout.write(result)
+
+
+if __name__ == '__main__':
+ main()
diff --git a/frozen_deps/base58/py.typed b/frozen_deps/base58/py.typed
new file mode 100644
index 0000000..e5aff4f
--- /dev/null
+++ b/frozen_deps/base58/py.typed
@@ -0,0 +1 @@
+# Marker file for PEP 561. \ No newline at end of file
diff --git a/frozen_deps/bech32.py b/frozen_deps/bech32.py
new file mode 100644
index 0000000..d450080
--- /dev/null
+++ b/frozen_deps/bech32.py
@@ -0,0 +1,123 @@
+# Copyright (c) 2017 Pieter Wuille
+#
+# Permission is hereby granted, free of charge, to any person obtaining a copy
+# of this software and associated documentation files (the "Software"), to deal
+# in the Software without restriction, including without limitation the rights
+# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+# copies of the Software, and to permit persons to whom the Software is
+# furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be included in
+# all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+# THE SOFTWARE.
+
+"""Reference implementation for Bech32 and segwit addresses."""
+
+
+CHARSET = "qpzry9x8gf2tvdw0s3jn54khce6mua7l"
+
+
+def bech32_polymod(values):
+ """Internal function that computes the Bech32 checksum."""
+ generator = [0x3b6a57b2, 0x26508e6d, 0x1ea119fa, 0x3d4233dd, 0x2a1462b3]
+ chk = 1
+ for value in values:
+ top = chk >> 25
+ chk = (chk & 0x1ffffff) << 5 ^ value
+ for i in range(5):
+ chk ^= generator[i] if ((top >> i) & 1) else 0
+ return chk
+
+
+def bech32_hrp_expand(hrp):
+ """Expand the HRP into values for checksum computation."""
+ return [ord(x) >> 5 for x in hrp] + [0] + [ord(x) & 31 for x in hrp]
+
+
+def bech32_verify_checksum(hrp, data):
+ """Verify a checksum given HRP and converted data characters."""
+ return bech32_polymod(bech32_hrp_expand(hrp) + data) == 1
+
+
+def bech32_create_checksum(hrp, data):
+ """Compute the checksum values given HRP and data."""
+ values = bech32_hrp_expand(hrp) + data
+ polymod = bech32_polymod(values + [0, 0, 0, 0, 0, 0]) ^ 1
+ return [(polymod >> 5 * (5 - i)) & 31 for i in range(6)]
+
+
+def bech32_encode(hrp, data):
+ """Compute a Bech32 string given HRP and data values."""
+ combined = data + bech32_create_checksum(hrp, data)
+ return hrp + '1' + ''.join([CHARSET[d] for d in combined])
+
+
+def bech32_decode(bech):
+ """Validate a Bech32 string, and determine HRP and data."""
+ if ((any(ord(x) < 33 or ord(x) > 126 for x in bech)) or
+ (bech.lower() != bech and bech.upper() != bech)):
+ return (None, None)
+ bech = bech.lower()
+ pos = bech.rfind('1')
+ if pos < 1 or pos + 7 > len(bech) or len(bech) > 90:
+ return (None, None)
+ if not all(x in CHARSET for x in bech[pos+1:]):
+ return (None, None)
+ hrp = bech[:pos]
+ data = [CHARSET.find(x) for x in bech[pos+1:]]
+ if not bech32_verify_checksum(hrp, data):
+ return (None, None)
+ return (hrp, data[:-6])
+
+
+def convertbits(data, frombits, tobits, pad=True):
+ """General power-of-2 base conversion."""
+ acc = 0
+ bits = 0
+ ret = []
+ maxv = (1 << tobits) - 1
+ max_acc = (1 << (frombits + tobits - 1)) - 1
+ for value in data:
+ if value < 0 or (value >> frombits):
+ return None
+ acc = ((acc << frombits) | value) & max_acc
+ bits += frombits
+ while bits >= tobits:
+ bits -= tobits
+ ret.append((acc >> bits) & maxv)
+ if pad:
+ if bits:
+ ret.append((acc << (tobits - bits)) & maxv)
+ elif bits >= frombits or ((acc << (tobits - bits)) & maxv):
+ return None
+ return ret
+
+
+def decode(hrp, addr):
+ """Decode a segwit address."""
+ hrpgot, data = bech32_decode(addr)
+ if hrpgot != hrp:
+ return (None, None)
+ decoded = convertbits(data[1:], 5, 8, False)
+ if decoded is None or len(decoded) < 2 or len(decoded) > 40:
+ return (None, None)
+ if data[0] > 16:
+ return (None, None)
+ if data[0] == 0 and len(decoded) != 20 and len(decoded) != 32:
+ return (None, None)
+ return (data[0], decoded)
+
+
+def encode(hrp, witver, witprog):
+ """Encode a segwit address."""
+ ret = bech32_encode(hrp, [witver] + convertbits(witprog, 8, 5))
+ if decode(hrp, ret) == (None, None):
+ return None
+ return ret
diff --git a/frozen_deps/bin/base58 b/frozen_deps/bin/base58
new file mode 100755
index 0000000..1e291f0
--- /dev/null
+++ b/frozen_deps/bin/base58
@@ -0,0 +1,8 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+import re
+import sys
+from base58.__main__ import main
+if __name__ == '__main__':
+ sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0])
+ sys.exit(main())
diff --git a/frozen_deps/bin/keytree.py b/frozen_deps/bin/keytree.py
new file mode 100755
index 0000000..1f4bedb
--- /dev/null
+++ b/frozen_deps/bin/keytree.py
@@ -0,0 +1,290 @@
+#!/usr/bin/python
+# MIT License
+#
+# Copyright (c) 2020 Ted Yin <[email protected]>
+#
+# Permission is hereby granted, free of charge, to any person obtaining a copy
+# of this software and associated documentation files (the "Software"), to deal
+# in the Software without restriction, including without limitation the rights
+# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+# copies of the Software, and to permit persons to whom the Software is
+# furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be included in all
+# copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+# SOFTWARE.
+#
+#
+# This little script offers decryption and verification of the existing
+# Ethereum wallets, as well as generation of a new wallet. You can use any
+# utf-8 string as the password, which could provide with better security
+# against the brute-force attack.
+
+# Use at your own risk.
+#
+# Example:
+# python3 ./keytree.py
+
+import os
+import sys
+if sys.version_info[1] < 7:
+ sys.write("Python should be >= 3.7")
+ sys.exit(1)
+basedir = os.path.dirname(os.path.abspath(__file__))
+sys.path.insert(0, basedir + "/frozen_deps")
+
+import re
+import argparse
+import hashlib
+import hmac
+import unicodedata
+import json
+from getpass import getpass
+
+import bech32
+import mnemonic
+from ecdsa import SigningKey, VerifyingKey, SECP256k1
+from ecdsa.ecdsa import generator_secp256k1
+from ecdsa.ellipticcurve import INFINITY
+from base58 import b58encode, b58decode
+from sha3 import keccak_256
+from Crypto.Cipher import AES
+
+
+def sha256(data):
+ h = hashlib.sha256()
+ h.update(data)
+ return h.digest()
+
+
+def ripemd160(data):
+ h = hashlib.new('ripemd160')
+ h.update(data)
+ return h.digest()
+
+
+class KeytreeError(Exception):
+ pass
+
+
+class BIP32Error(KeytreeError):
+ pass
+
+
+# point(p): returns the coordinate pair resulting from EC point multiplication
+# (repeated application of the EC group operation) of the secp256k1 base point
+# with the integer p.
+def point(p):
+ return generator_secp256k1 * p
+
+
+# ser32(i): serialize a 32-bit unsigned integer i as a 4-byte sequence, most
+# significant byte first.
+def ser32(i):
+ return i.to_bytes(4, byteorder='big')
+
+
+# ser256(p): serializes the integer p as a 32-byte sequence, most significant
+# byte first.
+def ser256(p):
+ return p.to_bytes(32, byteorder='big')
+
+
+# serP(P): serializes the coordinate pair P = (x,y) as a byte sequence using
+# SEC1's compressed form: (0x02 or 0x03) || ser256(x), where the header byte
+# depends on the parity of the omitted y coordinate.
+def serP(P):
+ if P.y() & 1 == 0:
+ parity = b'\x02'
+ else:
+ parity = b'\x03'
+ return parity + ser256(P.x())
+
+
+def is_infinity(P):
+ return P == INFINITY
+
+
+# parse256(p): interprets a 32-byte sequence as a 256-bit number, most
+# significant byte first.
+def parse256(p):
+ assert(len(p) == 32)
+ return int.from_bytes(p, byteorder='big')
+
+
+def iH(x):
+ return x + (1 << 31)
+
+
+n = generator_secp256k1.order()
+rformat = re.compile(r"^[0-9]+'?$")
+
+
+def ckd_pub(K_par, c_par, i):
+ if i >= 1 << 31:
+ raise BIP32Error("the child is a hardended key")
+ I = hmac.digest(
+ c_par, serP(K_par) + ser32(i), 'sha512')
+ I_L, I_R = I[:32], I[32:]
+ K_i = point(parse256(I_L)) + K_par
+ c_i = I_R
+ if parse256(I_L) >= n or is_infinity(K_i):
+ raise BIP32Error("invalid i")
+ return K_i, c_i
+
+def ckd_prv(k_par, c_par, i):
+ if i >= 1 << 31:
+ I = hmac.digest(
+ c_par, b'\x00' + ser256(k_par) + ser32(i), 'sha512')
+ else:
+ I = hmac.digest(
+ c_par, serP(point(k_par)) + ser32(i), 'sha512')
+ I_L, I_R = I[:32], I[32:]
+ k_i = (parse256(I_L) + k_par) % n
+ c_i = I_R
+ if parse256(I_L) >= n or k_i == 0:
+ raise BIP32Error("invalid i")
+ return k_i, c_i
+
+class BIP32:
+ path_error = BIP32Error("unsupported BIP32 path format")
+
+ def __init__(self, seed, key="Bitcoin seed"):
+ I = hmac.digest(b"Bitcoin seed", seed, 'sha512')
+ I_L, I_R = I[:32], I[32:]
+ self.m = parse256(I_L)
+ self.M = SigningKey.from_string(I_L, curve=SECP256k1) \
+ .get_verifying_key().pubkey.point
+ self.c = I_R
+
+ def derive(self, path="m"):
+ tokens = path.split('/')
+ if tokens[0] == "m":
+ k = self.m
+ c = self.c
+ for r in tokens[1:]:
+ if not rformat.match(r):
+ raise self.path_error
+ if r[-1] == "'":
+ i = iH(int(r[:-1]))
+ else:
+ i = int(r)
+ k, c = ckd_prv(k, c, i)
+ return SigningKey.from_string(k.to_bytes(32, byteorder='big'), curve=SECP256k1)
+ elif tokens[0] == "M":
+ K = self.M
+ c = self.c
+ for r in tokens[1:]:
+ if not rformat.match(r):
+ raise self.path_error
+ if r[-1] == "'":
+ i = iH(int(r[:-1]))
+ else:
+ i = int(r)
+ K, c = ckd_pub(K, c, i)
+ return VerifyingKey.from_public_point(K, curve=SECP256k1)
+ else:
+ raise self.path_error
+
+def get_eth_addr(pk):
+ pub_key = pk.to_string()
+ m = keccak_256()
+ m.update(pub_key)
+ return m.hexdigest()[24:]
+
+def get_privkey_btc(sk):
+ priv_key = b'\x80' + sk.to_string()
+ checksum = sha256(sha256(priv_key))[:4]
+ return b58encode(priv_key + checksum).decode("utf-8")
+
+def get_btc_addr(pk):
+ h = b'\x00' + ripemd160(sha256(b'\x04' + pk.to_string()))
+ checksum = sha256(sha256(h))[:4]
+ h += checksum
+ return b58encode(h).decode("utf-8")
+
+def load_from_keystore(filename):
+ try:
+ with open(filename, "r") as f:
+ try:
+ parsed = json.load(f)
+ ciphertext = b58decode(parsed['keys'][0]['key'])[:-4]
+ iv = b58decode(parsed['keys'][0]['iv'])[:-4]
+ salt = b58decode(parsed['salt'])[:-4]
+ tag = b58decode(parsed['pass_hash'])[:-4]
+ passwd = getpass('Enter the password to unlock keystore: ').encode('utf-8')
+ key = hashlib.pbkdf2_hmac(
+ 'sha256',
+ sha256(passwd + salt), salt, 200000)
+ obj = AES.new(key,
+ mode=AES.MODE_GCM,
+ nonce=iv)
+ if tag != sha256(passwd + sha256(passwd + salt)):
+ raise KeytreeError("incorrect keystore password")
+ return obj.decrypt(ciphertext[:-16]).decode('utf-8')
+ except KeytreeError as e:
+ raise e
+ except:
+ raise KeytreeError("invalid or corrupted keystore file")
+ except FileNotFoundError:
+ raise KeytreeError("failed to open file")
+
+
+if __name__ == '__main__':
+ parser = argparse.ArgumentParser(description='Derive BIP32 key pairs from BIP39 mnemonic')
+ parser.add_argument('--from-avax-keystore', type=str, default=None, help='load mnemonic from an AVAX keystore file')
+ parser.add_argument('--show-private', action='store_true', default=False, help='also show private keys and the mnemonic')
+ parser.add_argument('--custom-words', action='store_true', default=False, help='use an arbitrary word combination as mnemonic')
+ parser.add_argument('--account-path', default="44'/9000'/0'/0", help="path prefix for key deriving (e.g. \"0/1'/2\")")
+ parser.add_argument('--gen-mnemonic', action='store_true', default=False, help='generate a mnemonic (instead of taking an input)')
+ parser.add_argument('--lang', type=str, default="english", help='language for mnemonic words')
+ parser.add_argument('--start-idx', type=int, default=0, help='the start index for keys')
+ parser.add_argument('--end-idx', type=int, default=1, help='the end index for keys (exclusive)')
+ parser.add_argument('--hrp', type=str, default="avax", help='HRP (Human Readable Prefix, defined by Bech32)')
+
+ args = parser.parse_args()
+
+
+ try:
+ try:
+ if args.gen_mnemonic:
+ mgen = mnemonic.Mnemonic(args.lang)
+ words = mgen.generate(256)
+ else:
+ if args.from_avax_keystore:
+ words = load_from_keystore(args.from_avax_keystore)
+ else:
+ words = getpass('Enter the mnemonic: ').strip()
+ if not args.custom_words:
+ mchecker = mnemonic.Mnemonic(args.lang)
+ if not mchecker.check(words):
+ raise KeytreeError("invalid mnemonic")
+ except FileNotFoundError:
+ raise KeytreeError("invalid language")
+ if args.show_private or args.gen_mnemonic:
+ print("KEEP THIS PRIVATE: {}".format(words))
+ seed = hashlib.pbkdf2_hmac('sha512', unicodedata.normalize('NFKD', words).encode("utf-8"), b"mnemonic", 2048)
+ gen = BIP32(seed)
+ if args.start_idx < 0 or args.end_idx < 0:
+ raise KeytreeError("invalid start/end index")
+ for i in range(args.start_idx, args.end_idx):
+ path = "m/{}/{}".format(args.account_path, i)
+ priv = gen.derive(path)
+ pub = priv.get_verifying_key()
+ cpub = pub.to_string(encoding="compressed")
+ if args.show_private:
+ print("{}.priv(raw) {}".format(i, priv.to_string().hex()))
+ print("{}.priv(BTC) {}".format(i, get_privkey_btc(priv)))
+ print("{}.addr(AVAX) X-{}".format(i, bech32.bech32_encode(args.hrp, bech32.convertbits(ripemd160(sha256(cpub)), 8, 5))))
+ print("{}.addr(BTC) {}".format(i, get_btc_addr(pub)))
+ print("{}.addr(ETH) {}".format(i, get_eth_addr(pub)))
+ except KeytreeError as e:
+ sys.stderr.write("error: {}\n".format(str(e)))
+ sys.exit(1)
diff --git a/frozen_deps/ecdsa-0.16.1.dist-info/INSTALLER b/frozen_deps/ecdsa-0.16.1.dist-info/INSTALLER
new file mode 100644
index 0000000..a1b589e
--- /dev/null
+++ b/frozen_deps/ecdsa-0.16.1.dist-info/INSTALLER
@@ -0,0 +1 @@
+pip
diff --git a/frozen_deps/ecdsa-0.16.1.dist-info/LICENSE b/frozen_deps/ecdsa-0.16.1.dist-info/LICENSE
new file mode 100644
index 0000000..474479a
--- /dev/null
+++ b/frozen_deps/ecdsa-0.16.1.dist-info/LICENSE
@@ -0,0 +1,24 @@
+"python-ecdsa" Copyright (c) 2010 Brian Warner
+
+Portions written in 2005 by Peter Pearson and placed in the public domain.
+
+Permission is hereby granted, free of charge, to any person
+obtaining a copy of this software and associated documentation
+files (the "Software"), to deal in the Software without
+restriction, including without limitation the rights to use,
+copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the
+Software is furnished to do so, subject to the following
+conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+OTHER DEALINGS IN THE SOFTWARE.
diff --git a/frozen_deps/ecdsa-0.16.1.dist-info/METADATA b/frozen_deps/ecdsa-0.16.1.dist-info/METADATA
new file mode 100644
index 0000000..983a64a
--- /dev/null
+++ b/frozen_deps/ecdsa-0.16.1.dist-info/METADATA
@@ -0,0 +1,626 @@
+Metadata-Version: 2.1
+Name: ecdsa
+Version: 0.16.1
+Summary: ECDSA cryptographic signature library (pure python)
+Home-page: http://github.com/warner/python-ecdsa
+Author: Brian Warner
+Author-email: [email protected]
+License: MIT
+Platform: UNKNOWN
+Classifier: Programming Language :: Python
+Classifier: Programming Language :: Python :: 2
+Classifier: Programming Language :: Python :: 2.6
+Classifier: Programming Language :: Python :: 2.7
+Classifier: Programming Language :: Python :: 3
+Classifier: Programming Language :: Python :: 3.3
+Classifier: Programming Language :: Python :: 3.4
+Classifier: Programming Language :: Python :: 3.5
+Classifier: Programming Language :: Python :: 3.6
+Classifier: Programming Language :: Python :: 3.7
+Classifier: Programming Language :: Python :: 3.8
+Requires-Python: >=2.6, !=3.0.*, !=3.1.*, !=3.2.*
+Description-Content-Type: text/markdown
+Requires-Dist: six (>=1.9.0)
+Provides-Extra: gmpy
+Requires-Dist: gmpy ; extra == 'gmpy'
+Provides-Extra: gmpy2
+Requires-Dist: gmpy2 ; extra == 'gmpy2'
+
+# Pure-Python ECDSA
+
+[![build status](https://travis-ci.org/warner/python-ecdsa.png)](http://travis-ci.org/warner/python-ecdsa)
+[![Coverage Status](https://coveralls.io/repos/warner/python-ecdsa/badge.svg)](https://coveralls.io/r/warner/python-ecdsa)
+[![condition coverage](https://img.shields.io/badge/condition%20coverage-81%25-yellow)](https://travis-ci.org/warner/python-ecdsa/jobs/626479178#L776)
+[![Latest Version](https://img.shields.io/pypi/v/ecdsa.svg?style=flat)](https://pypi.python.org/pypi/ecdsa/)
+![Code style: black](https://img.shields.io/badge/code%20style-black-000000.svg?style=flat)
+
+
+This is an easy-to-use implementation of ECDSA cryptography (Elliptic Curve
+Digital Signature Algorithm), implemented purely in Python, released under
+the MIT license. With this library, you can quickly create keypairs (signing
+key and verifying key), sign messages, and verify the signatures. The keys
+and signatures are very short, making them easy to handle and incorporate
+into other protocols.
+
+## Features
+
+This library provides key generation, signing, and verifying, for five
+popular NIST "Suite B" GF(p) (_prime field_) curves, with key lengths of 192,
+224, 256, 384, and 521 bits. The "short names" for these curves, as known by
+the OpenSSL tool (`openssl ecparam -list_curves`), are: `prime192v1`,
+`secp224r1`, `prime256v1`, `secp384r1`, and `secp521r1`. It includes the
+256-bit curve `secp256k1` used by Bitcoin. There is also support for the
+regular (non-twisted) variants of Brainpool curves from 160 to 512 bits. The
+"short names" of those curves are: `brainpoolP160r1`, `brainpoolP192r1`,
+`brainpoolP224r1`, `brainpoolP256r1`, `brainpoolP320r1`, `brainpoolP384r1`,
+`brainpoolP512r1`.
+No other curves are included, but it is not too hard to add support for more
+curves over prime fields.
+
+## Dependencies
+
+This library uses only Python and the 'six' package. It is compatible with
+Python 2.6, 2.7 and 3.3+. It also supports execution on the alternative
+implementations like pypy and pypy3.
+
+If `gmpy2` or `gmpy` is installed, they will be used for faster arithmetic.
+Either of them can be installed after this library is installed,
+`python-ecdsa` will detect their presence on start-up and use them
+automatically.
+
+To run the OpenSSL compatibility tests, the 'openssl' tool must be in your
+`PATH`. This release has been tested successfully against OpenSSL 0.9.8o,
+1.0.0a, 1.0.2f and 1.1.1d (among others).
+
+
+## Installation
+
+This library is available on PyPI, it's recommended to install it using `pip`:
+
+```
+pip install ecdsa
+```
+
+In case higher performance is wanted and using native code is not a problem,
+it's possible to specify installation together with `gmpy2`:
+
+```
+pip install ecdsa[gmpy2]
+```
+
+or (slower, legacy option):
+```
+pip install ecdsa[gmpy]
+```
+
+## Speed
+
+The following table shows how long this library takes to generate keypairs
+(`keygen`), to sign data (`sign`), and to verify those signatures (`verify`).
+All those values are in seconds.
+For convenience, the inverses of those values are also provided:
+how many keys per second can be generated (`keygen/s`), how many signatures
+can be made per second (`sign/s`) and how many signatures can be verified
+per second (`verify/s`). The size of raw signature (generally the smallest
+way a signature can be encoded) is also provided in the `siglen` column.
+Use `tox -e speed` to generate this table on your own computer.
+On an Intel Core i7 4790K @ 4.0GHz I'm getting the following performance:
+
+```
+ siglen keygen keygen/s sign sign/s verify verify/s
+ NIST192p: 48 0.00035s 2893.02 0.00038s 2620.53 0.00069s 1458.92
+ NIST224p: 56 0.00043s 2307.11 0.00048s 2092.00 0.00088s 1131.33
+ NIST256p: 64 0.00056s 1793.70 0.00061s 1639.87 0.00113s 883.79
+ NIST384p: 96 0.00116s 864.33 0.00124s 806.29 0.00233s 429.87
+ NIST521p: 132 0.00221s 452.16 0.00234s 427.31 0.00460s 217.19
+ SECP256k1: 64 0.00056s 1772.65 0.00061s 1628.73 0.00110s 912.13
+ BRAINPOOLP160r1: 40 0.00026s 3801.86 0.00029s 3401.11 0.00052s 1930.47
+ BRAINPOOLP192r1: 48 0.00034s 2925.73 0.00038s 2634.34 0.00070s 1438.06
+ BRAINPOOLP224r1: 56 0.00044s 2287.98 0.00048s 2083.87 0.00088s 1137.52
+ BRAINPOOLP256r1: 64 0.00056s 1774.11 0.00061s 1628.25 0.00112s 890.71
+ BRAINPOOLP320r1: 80 0.00081s 1238.18 0.00087s 1146.71 0.00151s 661.95
+ BRAINPOOLP384r1: 96 0.00117s 855.47 0.00124s 804.56 0.00241s 414.83
+ BRAINPOOLP512r1: 128 0.00223s 447.99 0.00234s 427.49 0.00437s 229.09
+
+ ecdh ecdh/s
+ NIST192p: 0.00110s 910.70
+ NIST224p: 0.00143s 701.17
+ NIST256p: 0.00178s 560.44
+ NIST384p: 0.00383s 261.03
+ NIST521p: 0.00745s 134.23
+ SECP256k1: 0.00168s 596.23
+ BRAINPOOLP160r1: 0.00085s 1174.02
+ BRAINPOOLP192r1: 0.00113s 883.47
+ BRAINPOOLP224r1: 0.00145s 687.82
+ BRAINPOOLP256r1: 0.00195s 514.03
+ BRAINPOOLP320r1: 0.00277s 360.80
+ BRAINPOOLP384r1: 0.00412s 242.58
+ BRAINPOOLP512r1: 0.00787s 127.12
+```
+
+To test performance with `gmpy2` loaded, use `tox -e speedgmpy2`.
+On the same machine I'm getting the following performance with `gmpy2`:
+```
+ siglen keygen keygen/s sign sign/s verify verify/s
+ NIST192p: 48 0.00017s 5945.50 0.00018s 5544.66 0.00033s 3002.54
+ NIST224p: 56 0.00021s 4742.14 0.00022s 4463.52 0.00044s 2248.59
+ NIST256p: 64 0.00024s 4155.73 0.00025s 3994.28 0.00047s 2105.34
+ NIST384p: 96 0.00041s 2415.06 0.00043s 2316.41 0.00085s 1177.18
+ NIST521p: 132 0.00072s 1391.14 0.00074s 1359.63 0.00140s 716.31
+ SECP256k1: 64 0.00024s 4216.50 0.00025s 3994.52 0.00047s 2120.57
+ BRAINPOOLP160r1: 40 0.00014s 7038.99 0.00015s 6501.55 0.00029s 3397.79
+ BRAINPOOLP192r1: 48 0.00017s 5983.18 0.00018s 5626.08 0.00035s 2843.62
+ BRAINPOOLP224r1: 56 0.00021s 4727.54 0.00022s 4464.86 0.00043s 2326.84
+ BRAINPOOLP256r1: 64 0.00024s 4221.00 0.00025s 4010.26 0.00049s 2046.40
+ BRAINPOOLP320r1: 80 0.00032s 3142.14 0.00033s 3009.15 0.00061s 1652.88
+ BRAINPOOLP384r1: 96 0.00041s 2415.98 0.00043s 2340.35 0.00083s 1198.77
+ BRAINPOOLP512r1: 128 0.00064s 1567.27 0.00066s 1526.33 0.00127s 788.51
+
+ ecdh ecdh/s
+ NIST192p: 0.00051s 1960.26
+ NIST224p: 0.00067s 1502.97
+ NIST256p: 0.00073s 1376.12
+ NIST384p: 0.00132s 758.68
+ NIST521p: 0.00231s 433.23
+ SECP256k1: 0.00072s 1387.18
+ BRAINPOOLP160r1: 0.00042s 2366.60
+ BRAINPOOLP192r1: 0.00049s 2026.80
+ BRAINPOOLP224r1: 0.00067s 1486.52
+ BRAINPOOLP256r1: 0.00076s 1310.31
+ BRAINPOOLP320r1: 0.00101s 986.16
+ BRAINPOOLP384r1: 0.00131s 761.35
+ BRAINPOOLP512r1: 0.00211s 473.30
+```
+
+(there's also `gmpy` version, execute it using `tox -e speedgmpy`)
+
+For comparison, a highly optimised implementation (including curve-specific
+assembly for some curves), like the one in OpenSSL 1.1.1d, provides following
+performance numbers on the same machine.
+Run `openssl speed ecdsa` and `openssl speed ecdh` to reproduce it:
+```
+ sign verify sign/s verify/s
+ 192 bits ecdsa (nistp192) 0.0002s 0.0002s 4785.6 5380.7
+ 224 bits ecdsa (nistp224) 0.0000s 0.0001s 22475.6 9822.0
+ 256 bits ecdsa (nistp256) 0.0000s 0.0001s 45069.6 14166.6
+ 384 bits ecdsa (nistp384) 0.0008s 0.0006s 1265.6 1648.1
+ 521 bits ecdsa (nistp521) 0.0003s 0.0005s 3753.1 1819.5
+ 256 bits ecdsa (brainpoolP256r1) 0.0003s 0.0003s 2983.5 3333.2
+ 384 bits ecdsa (brainpoolP384r1) 0.0008s 0.0007s 1258.8 1528.1
+ 512 bits ecdsa (brainpoolP512r1) 0.0015s 0.0012s 675.1 860.1
+
+ op op/s
+ 192 bits ecdh (nistp192) 0.0002s 4853.4
+ 224 bits ecdh (nistp224) 0.0001s 15252.1
+ 256 bits ecdh (nistp256) 0.0001s 18436.3
+ 384 bits ecdh (nistp384) 0.0008s 1292.7
+ 521 bits ecdh (nistp521) 0.0003s 2884.7
+ 256 bits ecdh (brainpoolP256r1) 0.0003s 3066.5
+ 384 bits ecdh (brainpoolP384r1) 0.0008s 1298.0
+ 512 bits ecdh (brainpoolP512r1) 0.0014s 694.8
+```
+
+Keys and signature can be serialized in different ways (see Usage, below).
+For a NIST192p key, the three basic representations require strings of the
+following lengths (in bytes):
+
+ to_string: signkey= 24, verifykey= 48, signature=48
+ compressed: signkey=n/a, verifykey= 25, signature=n/a
+ DER: signkey=106, verifykey= 80, signature=55
+ PEM: signkey=278, verifykey=162, (no support for PEM signatures)
+
+## History
+
+In 2006, Peter Pearson announced his pure-python implementation of ECDSA in a
+[message to sci.crypt][1], available from his [download site][2]. In 2010,
+Brian Warner wrote a wrapper around this code, to make it a bit easier and
+safer to use. Hubert Kario then included an implementation of elliptic curve
+cryptography that uses Jacobian coordinates internally, improving performance
+about 20-fold. You are looking at the README for this wrapper.
+
+[1]: http://www.derkeiler.com/Newsgroups/sci.crypt/2006-01/msg00651.html
+[2]: http://webpages.charter.net/curryfans/peter/downloads.html
+
+## Testing
+
+To run the full test suite, do this:
+
+ tox -e coverage
+
+On an Intel Core i7 4790K @ 4.0GHz, the tests take about 16 seconds to execute.
+The test suite uses
+[`hypothesis`](https://github.com/HypothesisWorks/hypothesis) so there is some
+inherent variability in the test suite execution time.
+
+One part of `test_pyecdsa.py` checks compatibility with OpenSSL, by
+running the "openssl" CLI tool, make sure it's in your `PATH` if you want
+to test compatibility with it.
+
+## Security
+
+This library was not designed with security in mind. If you are processing
+data that needs to be protected we suggest you use a quality wrapper around
+OpenSSL. [pyca/cryptography](https://cryptography.io) is one example of such
+a wrapper. The primary use-case of this library is as a portable library for
+interoperability testing and as a teaching tool.
+
+**This library does not protect against side channel attacks.**
+
+Do not allow attackers to measure how long it takes you to generate a keypair
+or sign a message. Do not allow attackers to run code on the same physical
+machine when keypair generation or signing is taking place (this includes
+virtual machines). Do not allow attackers to measure how much power your
+computer uses while generating the keypair or signing a message. Do not allow
+attackers to measure RF interference coming from your computer while generating
+a keypair or signing a message. Note: just loading the private key will cause
+keypair generation. Other operations or attack vectors may also be
+vulnerable to attacks. **For a sophisticated attacker observing just one
+operation with a private key will be sufficient to completely
+reconstruct the private key**.
+
+Please also note that any Pure-python cryptographic library will be vulnerable
+to the same side channel attacks. This is because Python does not provide
+side-channel secure primitives (with the exception of
+[`hmac.compare_digest()`][3]), making side-channel secure programming
+impossible.
+
+This library depends upon a strong source of random numbers. Do not use it on
+a system where `os.urandom()` does not provide cryptographically secure
+random numbers.
+
+[3]: https://docs.python.org/3/library/hmac.html#hmac.compare_digest
+
+## Usage
+
+You start by creating a `SigningKey`. You can use this to sign data, by passing
+in data as a byte string and getting back the signature (also a byte string).
+You can also ask a `SigningKey` to give you the corresponding `VerifyingKey`.
+The `VerifyingKey` can be used to verify a signature, by passing it both the
+data string and the signature byte string: it either returns True or raises
+`BadSignatureError`.
+
+```python
+from ecdsa import SigningKey
+sk = SigningKey.generate() # uses NIST192p
+vk = sk.verifying_key
+signature = sk.sign(b"message")
+assert vk.verify(signature, b"message")
+```
+
+Each `SigningKey`/`VerifyingKey` is associated with a specific curve, like
+NIST192p (the default one). Longer curves are more secure, but take longer to
+use, and result in longer keys and signatures.
+
+```python
+from ecdsa import SigningKey, NIST384p
+sk = SigningKey.generate(curve=NIST384p)
+vk = sk.verifying_key
+signature = sk.sign(b"message")
+assert vk.verify(signature, b"message")
+```
+
+The `SigningKey` can be serialized into several different formats: the shortest
+is to call `s=sk.to_string()`, and then re-create it with
+`SigningKey.from_string(s, curve)` . This short form does not record the
+curve, so you must be sure to pass to `from_string()` the same curve you used
+for the original key. The short form of a NIST192p-based signing key is just 24
+bytes long. If a point encoding is invalid or it does not lie on the specified
+curve, `from_string()` will raise `MalformedPointError`.
+
+```python
+from ecdsa import SigningKey, NIST384p
+sk = SigningKey.generate(curve=NIST384p)
+sk_string = sk.to_string()
+sk2 = SigningKey.from_string(sk_string, curve=NIST384p)
+print(sk_string.hex())
+print(sk2.to_string().hex())
+```
+
+Note: while the methods are called `to_string()` the type they return is
+actually `bytes`, the "string" part is leftover from Python 2.
+
+`sk.to_pem()` and `sk.to_der()` will serialize the signing key into the same
+formats that OpenSSL uses. The PEM file looks like the familiar ASCII-armored
+`"-----BEGIN EC PRIVATE KEY-----"` base64-encoded format, and the DER format
+is a shorter binary form of the same data.
+`SigningKey.from_pem()/.from_der()` will undo this serialization. These
+formats include the curve name, so you do not need to pass in a curve
+identifier to the deserializer. In case the file is malformed `from_der()`
+and `from_pem()` will raise `UnexpectedDER` or` MalformedPointError`.
+
+```python
+from ecdsa import SigningKey, NIST384p
+sk = SigningKey.generate(curve=NIST384p)
+sk_pem = sk.to_pem()
+sk2 = SigningKey.from_pem(sk_pem)
+# sk and sk2 are the same key
+```
+
+Likewise, the `VerifyingKey` can be serialized in the same way:
+`vk.to_string()/VerifyingKey.from_string()`, `to_pem()/from_pem()`, and
+`to_der()/from_der()`. The same `curve=` argument is needed for
+`VerifyingKey.from_string()`.
+
+```python
+from ecdsa import SigningKey, VerifyingKey, NIST384p
+sk = SigningKey.generate(curve=NIST384p)
+vk = sk.verifying_key
+vk_string = vk.to_string()
+vk2 = VerifyingKey.from_string(vk_string, curve=NIST384p)
+# vk and vk2 are the same key
+
+from ecdsa import SigningKey, VerifyingKey, NIST384p
+sk = SigningKey.generate(curve=NIST384p)
+vk = sk.verifying_key
+vk_pem = vk.to_pem()
+vk2 = VerifyingKey.from_pem(vk_pem)
+# vk and vk2 are the same key
+```
+
+There are a couple of different ways to compute a signature. Fundamentally,
+ECDSA takes a number that represents the data being signed, and returns a
+pair of numbers that represent the signature. The `hashfunc=` argument to
+`sk.sign()` and `vk.verify()` is used to turn an arbitrary string into
+fixed-length digest, which is then turned into a number that ECDSA can sign,
+and both sign and verify must use the same approach. The default value is
+`hashlib.sha1`, but if you use NIST256p or a longer curve, you can use
+`hashlib.sha256` instead.
+
+There are also multiple ways to represent a signature. The default
+`sk.sign()` and `vk.verify()` methods present it as a short string, for
+simplicity and minimal overhead. To use a different scheme, use the
+`sk.sign(sigencode=)` and `vk.verify(sigdecode=)` arguments. There are helper
+functions in the `ecdsa.util` module that can be useful here.
+
+It is also possible to create a `SigningKey` from a "seed", which is
+deterministic. This can be used in protocols where you want to derive
+consistent signing keys from some other secret, for example when you want
+three separate keys and only want to store a single master secret. You should
+start with a uniformly-distributed unguessable seed with about `curve.baselen`
+bytes of entropy, and then use one of the helper functions in `ecdsa.util` to
+convert it into an integer in the correct range, and then finally pass it
+into `SigningKey.from_secret_exponent()`, like this:
+
+```python
+import os
+from ecdsa import NIST384p, SigningKey
+from ecdsa.util import randrange_from_seed__trytryagain
+
+def make_key(seed):
+ secexp = randrange_from_seed__trytryagain(seed, NIST384p.order)
+ return SigningKey.from_secret_exponent(secexp, curve=NIST384p)
+
+seed = os.urandom(NIST384p.baselen) # or other starting point
+sk1a = make_key(seed)
+sk1b = make_key(seed)
+# note: sk1a and sk1b are the same key
+assert sk1a.to_string() == sk1b.to_string()
+sk2 = make_key(b"2-"+seed) # different key
+assert sk1a.to_string() != sk2.to_string()
+```
+
+In case the application will verify a lot of signatures made with a single
+key, it's possible to precompute some of the internal values to make
+signature verification significantly faster. The break-even point occurs at
+about 100 signatures verified.
+
+To perform precomputation, you can call the `precompute()` method
+on `VerifyingKey` instance:
+```python
+from ecdsa import SigningKey, NIST384p
+sk = SigningKey.generate(curve=NIST384p)
+vk = sk.verifying_key
+vk.precompute()
+signature = sk.sign(b"message")
+assert vk.verify(signature, b"message")
+```
+
+Once `precompute()` was called, all signature verifications with this key will
+be faster to execute.
+
+## OpenSSL Compatibility
+
+To produce signatures that can be verified by OpenSSL tools, or to verify
+signatures that were produced by those tools, use:
+
+```python
+# openssl ecparam -name prime256v1 -genkey -out sk.pem
+# openssl ec -in sk.pem -pubout -out vk.pem
+# echo "data for signing" > data
+# openssl dgst -sha256 -sign sk.pem -out data.sig data
+# openssl dgst -sha256 -verify vk.pem -signature data.sig data
+# openssl dgst -sha256 -prverify sk.pem -signature data.sig data
+
+import hashlib
+from ecdsa import SigningKey, VerifyingKey
+from ecdsa.util import sigencode_der, sigdecode_der
+
+with open("vk.pem") as f:
+ vk = VerifyingKey.from_pem(f.read())
+
+with open("data", "rb") as f:
+ data = f.read()
+
+with open("data.sig", "rb") as f:
+ signature = f.read()
+
+assert vk.verify(signature, data, hashlib.sha256, sigdecode=sigdecode_der)
+
+with open("sk.pem") as f:
+ sk = SigningKey.from_pem(f.read(), hashlib.sha256)
+
+new_signature = sk.sign_deterministic(data, sigencode=sigencode_der)
+
+with open("data.sig2", "wb") as f:
+ f.write(new_signature)
+
+# openssl dgst -sha256 -verify vk.pem -signature data.sig2 data
+```
+
+Note: if compatibility with OpenSSL 1.0.0 or earlier is necessary, the
+`sigencode_string` and `sigdecode_string` from `ecdsa.util` can be used for
+respectively writing and reading the signatures.
+
+The keys also can be written in format that openssl can handle:
+
+```python
+from ecdsa import SigningKey, VerifyingKey
+
+with open("sk.pem") as f:
+ sk = SigningKey.from_pem(f.read())
+with open("sk.pem", "wb") as f:
+ f.write(sk.to_pem())
+
+with open("vk.pem") as f:
+ vk = VerifyingKey.from_pem(f.read())
+with open("vk.pem", "wb") as f:
+ f.write(vk.to_pem())
+```
+
+## Entropy
+
+Creating a signing key with `SigningKey.generate()` requires some form of
+entropy (as opposed to
+`from_secret_exponent`/`from_string`/`from_der`/`from_pem`,
+which are deterministic and do not require an entropy source). The default
+source is `os.urandom()`, but you can pass any other function that behaves
+like `os.urandom` as the `entropy=` argument to do something different. This
+may be useful in unit tests, where you want to achieve repeatable results. The
+`ecdsa.util.PRNG` utility is handy here: it takes a seed and produces a strong
+pseudo-random stream from it:
+
+```python
+from ecdsa.util import PRNG
+from ecdsa import SigningKey
+rng1 = PRNG(b"seed")
+sk1 = SigningKey.generate(entropy=rng1)
+rng2 = PRNG(b"seed")
+sk2 = SigningKey.generate(entropy=rng2)
+# sk1 and sk2 are the same key
+```
+
+Likewise, ECDSA signature generation requires a random number, and each
+signature must use a different one (using the same number twice will
+immediately reveal the private signing key). The `sk.sign()` method takes an
+`entropy=` argument which behaves the same as `SigningKey.generate(entropy=)`.
+
+## Deterministic Signatures
+
+If you call `SigningKey.sign_deterministic(data)` instead of `.sign(data)`,
+the code will generate a deterministic signature instead of a random one.
+This uses the algorithm from RFC6979 to safely generate a unique `k` value,
+derived from the private key and the message being signed. Each time you sign
+the same message with the same key, you will get the same signature (using
+the same `k`).
+
+This may become the default in a future version, as it is not vulnerable to
+failures of the entropy source.
+
+## Examples
+
+Create a NIST192p keypair and immediately save both to disk:
+
+```python
+from ecdsa import SigningKey
+sk = SigningKey.generate()
+vk = sk.verifying_key
+with open("private.pem", "wb") as f:
+ f.write(sk.to_pem())
+with open("public.pem", "wb") as f:
+ f.write(vk.to_pem())
+```
+
+Load a signing key from disk, use it to sign a message (using SHA-1), and write
+the signature to disk:
+
+```python
+from ecdsa import SigningKey
+with open("private.pem") as f:
+ sk = SigningKey.from_pem(f.read())
+with open("message", "rb") as f:
+ message = f.read()
+sig = sk.sign(message)
+with open("signature", "wb") as f:
+ f.write(sig)
+```
+
+Load the verifying key, message, and signature from disk, and verify the
+signature (assume SHA-1 hash):
+
+```python
+from ecdsa import VerifyingKey, BadSignatureError
+vk = VerifyingKey.from_pem(open("public.pem").read())
+with open("message", "rb") as f:
+ message = f.read()
+with open("signature", "rb") as f:
+ sig = f.read()
+try:
+ vk.verify(sig, message)
+ print "good signature"
+except BadSignatureError:
+ print "BAD SIGNATURE"
+```
+
+Create a NIST521p keypair:
+
+```python
+from ecdsa import SigningKey, NIST521p
+sk = SigningKey.generate(curve=NIST521p)
+vk = sk.verifying_key
+```
+
+Create three independent signing keys from a master seed:
+
+```python
+from ecdsa import NIST192p, SigningKey
+from ecdsa.util import randrange_from_seed__trytryagain
+
+def make_key_from_seed(seed, curve=NIST192p):
+ secexp = randrange_from_seed__trytryagain(seed, curve.order)
+ return SigningKey.from_secret_exponent(secexp, curve)
+
+sk1 = make_key_from_seed("1:%s" % seed)
+sk2 = make_key_from_seed("2:%s" % seed)
+sk3 = make_key_from_seed("3:%s" % seed)
+```
+
+Load a verifying key from disk and print it using hex encoding in
+uncompressed and compressed format (defined in X9.62 and SEC1 standards):
+
+```python
+from ecdsa import VerifyingKey
+
+with open("public.pem") as f:
+ vk = VerifyingKey.from_pem(f.read())
+
+print("uncompressed: {0}".format(vk.to_string("uncompressed").hex()))
+print("compressed: {0}".format(vk.to_string("compressed").hex()))
+```
+
+Load a verifying key from a hex string from compressed format, output
+uncompressed:
+
+```python
+from ecdsa import VerifyingKey, NIST256p
+
+comp_str = '022799c0d0ee09772fdd337d4f28dc155581951d07082fb19a38aa396b67e77759'
+vk = VerifyingKey.from_string(bytearray.fromhex(comp_str), curve=NIST256p)
+print(vk.to_string("uncompressed").hex())
+```
+
+ECDH key exchange with remote party
+
+```python
+from ecdsa import ECDH, NIST256p
+
+ecdh = ECDH(curve=NIST256p)
+ecdh.generate_private_key()
+local_public_key = ecdh.get_public_key()
+#send `local_public_key` to remote party and receive `remote_public_key` from remote party
+with open("remote_public_key.pem") as e:
+ remote_public_key = e.read()
+ecdh.load_received_public_key_pem(remote_public_key)
+secret = ecdh.generate_sharedsecret_bytes()
+```
+
+
diff --git a/frozen_deps/ecdsa-0.16.1.dist-info/RECORD b/frozen_deps/ecdsa-0.16.1.dist-info/RECORD
new file mode 100644
index 0000000..4382e84
--- /dev/null
+++ b/frozen_deps/ecdsa-0.16.1.dist-info/RECORD
@@ -0,0 +1,52 @@
+ecdsa-0.16.1.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4
+ecdsa-0.16.1.dist-info/LICENSE,sha256=PsqYRXc9LluMydjBGdNF8ApIBuS9Zg1KPWzfnA6di7I,1147
+ecdsa-0.16.1.dist-info/METADATA,sha256=cwaWRd_w5Q-Y4wENZxW14D0cpK13fE3AP56XLw-tF50,24993
+ecdsa-0.16.1.dist-info/RECORD,,
+ecdsa-0.16.1.dist-info/WHEEL,sha256=8zNYZbwQSXoB9IfXOjPfeNwvAsALAjffgk27FqvCWbo,110
+ecdsa-0.16.1.dist-info/top_level.txt,sha256=7ovPHfAPyTou19f8gOSbHm6B9dGjTibWolcCB7Zjovs,6
+ecdsa/__init__.py,sha256=u-_1cu1I_GIwJ0DRYY7LNvkB4pvodv1kHztsAsCX3eA,1325
+ecdsa/__pycache__/__init__.cpython-38.pyc,,
+ecdsa/__pycache__/_compat.cpython-38.pyc,,
+ecdsa/__pycache__/_rwlock.cpython-38.pyc,,
+ecdsa/__pycache__/_version.cpython-38.pyc,,
+ecdsa/__pycache__/curves.cpython-38.pyc,,
+ecdsa/__pycache__/der.cpython-38.pyc,,
+ecdsa/__pycache__/ecdh.cpython-38.pyc,,
+ecdsa/__pycache__/ecdsa.cpython-38.pyc,,
+ecdsa/__pycache__/ellipticcurve.cpython-38.pyc,,
+ecdsa/__pycache__/keys.cpython-38.pyc,,
+ecdsa/__pycache__/numbertheory.cpython-38.pyc,,
+ecdsa/__pycache__/rfc6979.cpython-38.pyc,,
+ecdsa/__pycache__/test_der.cpython-38.pyc,,
+ecdsa/__pycache__/test_ecdh.cpython-38.pyc,,
+ecdsa/__pycache__/test_ecdsa.cpython-38.pyc,,
+ecdsa/__pycache__/test_ellipticcurve.cpython-38.pyc,,
+ecdsa/__pycache__/test_jacobi.cpython-38.pyc,,
+ecdsa/__pycache__/test_keys.cpython-38.pyc,,
+ecdsa/__pycache__/test_malformed_sigs.cpython-38.pyc,,
+ecdsa/__pycache__/test_numbertheory.cpython-38.pyc,,
+ecdsa/__pycache__/test_pyecdsa.cpython-38.pyc,,
+ecdsa/__pycache__/test_rw_lock.cpython-38.pyc,,
+ecdsa/__pycache__/util.cpython-38.pyc,,
+ecdsa/_compat.py,sha256=j_BnKmVOkjucCQbCuLaFsxHSiEUqj_co5sSAPLLWSsk,1659
+ecdsa/_rwlock.py,sha256=CAwHp2V65ksI8B1UqY7EccK9LaUToiv6pDLVzm44eag,2849
+ecdsa/_version.py,sha256=Qncu2Mr06Q_KO_8jvc8zi5RZ4XgaxiWI17VDRqKMrfw,498
+ecdsa/curves.py,sha256=rlAVrS6hwZ6sNnTswdRMJBlC-mryxXYo7zZIEQjYOPE,3735
+ecdsa/der.py,sha256=l528iLGUwqcNokzDkk-2qO3-6_nzL908OfB0GhUhbZ8,14092
+ecdsa/ecdh.py,sha256=K7T-XoiP-Y_bsGcnulcXFsr_7P5LCK2O4wbM-WkopDQ,10631
+ecdsa/ecdsa.py,sha256=5xD8X3qD9By3aZdxVoPOyx_FFDRNVrRUhxtw5j70g0g,21232
+ecdsa/ellipticcurve.py,sha256=l11lgxjqTe2ocyOed9M19FKZR7kNAB3dUfUvjJLAcsk,27437
+ecdsa/keys.py,sha256=1-YQm967hqvOsnF9o7Tw0eHyo21YHkZYzcKOckebfGI,59502
+ecdsa/numbertheory.py,sha256=yLx-P5-esRFT63gDSvKBfoiwOfSyVfjXyFcGF9_SFbM,16764
+ecdsa/rfc6979.py,sha256=x6dCO2l3QlPLHE-w3c456rqthhSBP03dCnTfSweBgBU,2725
+ecdsa/test_der.py,sha256=jifDHof2nEDs2phCEYMOJ-h6oCEuqS-pz8x65rrmm8U,12653
+ecdsa/test_ecdh.py,sha256=PxwESmg9_ckt1N9yXA88yN_0bERwkXDojSP9Oppfub8,13510
+ecdsa/test_ecdsa.py,sha256=csODW8xYt_LhjEvHiWteehEU2UxBLodvkQk21aMNCzs,19696
+ecdsa/test_ellipticcurve.py,sha256=todhFIkd2pyRCqfa7S92o69uOM7DfFp1tkD7LFa2Edw,6112
+ecdsa/test_jacobi.py,sha256=Ie3NocTE1i69oHxfnmnmvwqXJIlQpzVAFAG1rJq3YFU,12178
+ecdsa/test_keys.py,sha256=lT05J0Cu7C0HLu8cicBKBGRzmkuQBIECHQEzBmXYDzQ,14157
+ecdsa/test_malformed_sigs.py,sha256=Sr4RdBG4WWpOdJBME8f4v82uvbqJ_2cKyccL9crsi58,10300
+ecdsa/test_numbertheory.py,sha256=VqEme1ND9gbh2aMKsXXnZXcI4fpSvfkglM1O8DQpxR8,8815
+ecdsa/test_pyecdsa.py,sha256=61c5ASQ9pHKIYg73JWiIZdlCz4wqmkvCqmPJKVBNzn4,73402
+ecdsa/test_rw_lock.py,sha256=pkSoLder1YdsyRPSam8topCvdMytQjV3q-sCqrjx4nE,6959
+ecdsa/util.py,sha256=lHkBmYk4wuUETSUj4V23ssCjL385zCDxFr24jptXxI8,14557
diff --git a/frozen_deps/ecdsa-0.16.1.dist-info/WHEEL b/frozen_deps/ecdsa-0.16.1.dist-info/WHEEL
new file mode 100644
index 0000000..8b701e9
--- /dev/null
+++ b/frozen_deps/ecdsa-0.16.1.dist-info/WHEEL
@@ -0,0 +1,6 @@
+Wheel-Version: 1.0
+Generator: bdist_wheel (0.33.6)
+Root-Is-Purelib: true
+Tag: py2-none-any
+Tag: py3-none-any
+
diff --git a/frozen_deps/ecdsa-0.16.1.dist-info/top_level.txt b/frozen_deps/ecdsa-0.16.1.dist-info/top_level.txt
new file mode 100644
index 0000000..aa5efdb
--- /dev/null
+++ b/frozen_deps/ecdsa-0.16.1.dist-info/top_level.txt
@@ -0,0 +1 @@
+ecdsa
diff --git a/frozen_deps/ecdsa/__init__.py b/frozen_deps/ecdsa/__init__.py
new file mode 100644
index 0000000..4ae0a11
--- /dev/null
+++ b/frozen_deps/ecdsa/__init__.py
@@ -0,0 +1,76 @@
+from .keys import (
+ SigningKey,
+ VerifyingKey,
+ BadSignatureError,
+ BadDigestError,
+ MalformedPointError,
+)
+from .curves import (
+ NIST192p,
+ NIST224p,
+ NIST256p,
+ NIST384p,
+ NIST521p,
+ SECP256k1,
+ BRAINPOOLP160r1,
+ BRAINPOOLP192r1,
+ BRAINPOOLP224r1,
+ BRAINPOOLP256r1,
+ BRAINPOOLP320r1,
+ BRAINPOOLP384r1,
+ BRAINPOOLP512r1,
+)
+from .ecdh import (
+ ECDH,
+ NoKeyError,
+ NoCurveError,
+ InvalidCurveError,
+ InvalidSharedSecretError,
+)
+from .der import UnexpectedDER
+
+# This code comes from http://github.com/warner/python-ecdsa
+from ._version import get_versions
+
+__version__ = get_versions()["version"]
+del get_versions
+
+__all__ = [
+ "curves",
+ "der",
+ "ecdsa",
+ "ellipticcurve",
+ "keys",
+ "numbertheory",
+ "test_pyecdsa",
+ "util",
+ "six",
+]
+
+_hush_pyflakes = [
+ SigningKey,
+ VerifyingKey,
+ BadSignatureError,
+ BadDigestError,
+ MalformedPointError,
+ UnexpectedDER,
+ InvalidCurveError,
+ NoKeyError,
+ InvalidSharedSecretError,
+ ECDH,
+ NoCurveError,
+ NIST192p,
+ NIST224p,
+ NIST256p,
+ NIST384p,
+ NIST521p,
+ SECP256k1,
+ BRAINPOOLP160r1,
+ BRAINPOOLP192r1,
+ BRAINPOOLP224r1,
+ BRAINPOOLP256r1,
+ BRAINPOOLP320r1,
+ BRAINPOOLP384r1,
+ BRAINPOOLP512r1,
+]
+del _hush_pyflakes
diff --git a/frozen_deps/ecdsa/_compat.py b/frozen_deps/ecdsa/_compat.py
new file mode 100644
index 0000000..720360b
--- /dev/null
+++ b/frozen_deps/ecdsa/_compat.py
@@ -0,0 +1,60 @@
+"""
+Common functions for providing cross-python version compatibility.
+"""
+import sys
+import re
+from six import integer_types
+
+
+def str_idx_as_int(string, index):
+ """Take index'th byte from string, return as integer"""
+ val = string[index]
+ if isinstance(val, integer_types):
+ return val
+ return ord(val)
+
+
+if sys.version_info < (3, 0):
+
+ def normalise_bytes(buffer_object):
+ """Cast the input into array of bytes."""
+ # flake8 runs on py3 where `buffer` indeed doesn't exist...
+ return buffer(buffer_object) # noqa: F821
+
+ def hmac_compat(ret):
+ return ret
+
+ if sys.version_info < (2, 7) or sys.version_info < (2, 7, 4):
+
+ def remove_whitespace(text):
+ """Removes all whitespace from passed in string"""
+ return re.sub(r"\s+", "", text)
+
+ else:
+
+ def remove_whitespace(text):
+ """Removes all whitespace from passed in string"""
+ return re.sub(r"\s+", "", text, flags=re.UNICODE)
+
+
+else:
+ if sys.version_info < (3, 4):
+ # on python 3.3 hmac.hmac.update() accepts only bytes, on newer
+ # versions it does accept memoryview() also
+ def hmac_compat(data):
+ if not isinstance(data, bytes):
+ return bytes(data)
+ return data
+
+ else:
+
+ def hmac_compat(data):
+ return data
+
+ def normalise_bytes(buffer_object):
+ """Cast the input into array of bytes."""
+ return memoryview(buffer_object).cast("B")
+
+ def remove_whitespace(text):
+ """Removes all whitespace from passed in string"""
+ return re.sub(r"\s+", "", text, flags=re.UNICODE)
diff --git a/frozen_deps/ecdsa/_rwlock.py b/frozen_deps/ecdsa/_rwlock.py
new file mode 100644
index 0000000..010e498
--- /dev/null
+++ b/frozen_deps/ecdsa/_rwlock.py
@@ -0,0 +1,86 @@
+# Copyright Mateusz Kobos, (c) 2011
+# https://code.activestate.com/recipes/577803-reader-writer-lock-with-priority-for-writers/
+# released under the MIT licence
+
+import threading
+
+
+__author__ = "Mateusz Kobos"
+
+
+class RWLock:
+ """
+ Read-Write locking primitive
+
+ Synchronization object used in a solution of so-called second
+ readers-writers problem. In this problem, many readers can simultaneously
+ access a share, and a writer has an exclusive access to this share.
+ Additionally, the following constraints should be met:
+ 1) no reader should be kept waiting if the share is currently opened for
+ reading unless a writer is also waiting for the share,
+ 2) no writer should be kept waiting for the share longer than absolutely
+ necessary.
+
+ The implementation is based on [1, secs. 4.2.2, 4.2.6, 4.2.7]
+ with a modification -- adding an additional lock (C{self.__readers_queue})
+ -- in accordance with [2].
+
+ Sources:
+ [1] A.B. Downey: "The little book of semaphores", Version 2.1.5, 2008
+ [2] P.J. Courtois, F. Heymans, D.L. Parnas:
+ "Concurrent Control with 'Readers' and 'Writers'",
+ Communications of the ACM, 1971 (via [3])
+ [3] http://en.wikipedia.org/wiki/Readers-writers_problem
+ """
+
+ def __init__(self):
+ """
+ A lock giving an even higher priority to the writer in certain
+ cases (see [2] for a discussion).
+ """
+ self.__read_switch = _LightSwitch()
+ self.__write_switch = _LightSwitch()
+ self.__no_readers = threading.Lock()
+ self.__no_writers = threading.Lock()
+ self.__readers_queue = threading.Lock()
+
+ def reader_acquire(self):
+ self.__readers_queue.acquire()
+ self.__no_readers.acquire()
+ self.__read_switch.acquire(self.__no_writers)
+ self.__no_readers.release()
+ self.__readers_queue.release()
+
+ def reader_release(self):
+ self.__read_switch.release(self.__no_writers)
+
+ def writer_acquire(self):
+ self.__write_switch.acquire(self.__no_readers)
+ self.__no_writers.acquire()
+
+ def writer_release(self):
+ self.__no_writers.release()
+ self.__write_switch.release(self.__no_readers)
+
+
+class _LightSwitch:
+ """An auxiliary "light switch"-like object. The first thread turns on the
+ "switch", the last one turns it off (see [1, sec. 4.2.2] for details)."""
+
+ def __init__(self):
+ self.__counter = 0
+ self.__mutex = threading.Lock()
+
+ def acquire(self, lock):
+ self.__mutex.acquire()
+ self.__counter += 1
+ if self.__counter == 1:
+ lock.acquire()
+ self.__mutex.release()
+
+ def release(self, lock):
+ self.__mutex.acquire()
+ self.__counter -= 1
+ if self.__counter == 0:
+ lock.release()
+ self.__mutex.release()
diff --git a/frozen_deps/ecdsa/_version.py b/frozen_deps/ecdsa/_version.py
new file mode 100644
index 0000000..9a3e5fa
--- /dev/null
+++ b/frozen_deps/ecdsa/_version.py
@@ -0,0 +1,21 @@
+
+# This file was generated by 'versioneer.py' (0.17) from
+# revision-control system data, or from the parent directory name of an
+# unpacked source archive. Distribution tarballs contain a pre-generated copy
+# of this file.
+
+import json
+
+version_json = '''
+{
+ "date": "2020-11-12T20:12:49+0100",
+ "dirty": false,
+ "error": null,
+ "full-revisionid": "9d5a727c766773b8367f6dd0a49bbda21c18dbe7",
+ "version": "0.16.1"
+}
+''' # END VERSION_JSON
+
+
+def get_versions():
+ return json.loads(version_json)
diff --git a/frozen_deps/ecdsa/curves.py b/frozen_deps/ecdsa/curves.py
new file mode 100644
index 0000000..9a10380
--- /dev/null
+++ b/frozen_deps/ecdsa/curves.py
@@ -0,0 +1,194 @@
+from __future__ import division
+
+from . import der, ecdsa
+from .util import orderlen
+
+
+# orderlen was defined in this module previously, so keep it in __all__,
+# will need to mark it as deprecated later
+__all__ = [
+ "UnknownCurveError",
+ "orderlen",
+ "Curve",
+ "NIST192p",
+ "NIST224p",
+ "NIST256p",
+ "NIST384p",
+ "NIST521p",
+ "curves",
+ "find_curve",
+ "SECP256k1",
+ "BRAINPOOLP160r1",
+ "BRAINPOOLP192r1",
+ "BRAINPOOLP224r1",
+ "BRAINPOOLP256r1",
+ "BRAINPOOLP320r1",
+ "BRAINPOOLP384r1",
+ "BRAINPOOLP512r1",
+]
+
+
+class UnknownCurveError(Exception):
+ pass
+
+
+class Curve:
+ def __init__(self, name, curve, generator, oid, openssl_name=None):
+ self.name = name
+ self.openssl_name = openssl_name # maybe None
+ self.curve = curve
+ self.generator = generator
+ self.order = generator.order()
+ self.baselen = orderlen(self.order)
+ self.verifying_key_length = 2 * self.baselen
+ self.signature_length = 2 * self.baselen
+ self.oid = oid
+ self.encoded_oid = der.encode_oid(*oid)
+
+ def __repr__(self):
+ return self.name
+
+
+# the NIST curves
+NIST192p = Curve(
+ "NIST192p",
+ ecdsa.curve_192,
+ ecdsa.generator_192,
+ (1, 2, 840, 10045, 3, 1, 1),
+ "prime192v1",
+)
+
+
+NIST224p = Curve(
+ "NIST224p",
+ ecdsa.curve_224,
+ ecdsa.generator_224,
+ (1, 3, 132, 0, 33),
+ "secp224r1",
+)
+
+
+NIST256p = Curve(
+ "NIST256p",
+ ecdsa.curve_256,
+ ecdsa.generator_256,
+ (1, 2, 840, 10045, 3, 1, 7),
+ "prime256v1",
+)
+
+
+NIST384p = Curve(
+ "NIST384p",
+ ecdsa.curve_384,
+ ecdsa.generator_384,
+ (1, 3, 132, 0, 34),
+ "secp384r1",
+)
+
+
+NIST521p = Curve(
+ "NIST521p",
+ ecdsa.curve_521,
+ ecdsa.generator_521,
+ (1, 3, 132, 0, 35),
+ "secp521r1",
+)
+
+
+SECP256k1 = Curve(
+ "SECP256k1",
+ ecdsa.curve_secp256k1,
+ ecdsa.generator_secp256k1,
+ (1, 3, 132, 0, 10),
+ "secp256k1",
+)
+
+
+BRAINPOOLP160r1 = Curve(
+ "BRAINPOOLP160r1",
+ ecdsa.curve_brainpoolp160r1,
+ ecdsa.generator_brainpoolp160r1,
+ (1, 3, 36, 3, 3, 2, 8, 1, 1, 1),
+ "brainpoolP160r1",
+)
+
+
+BRAINPOOLP192r1 = Curve(
+ "BRAINPOOLP192r1",
+ ecdsa.curve_brainpoolp192r1,
+ ecdsa.generator_brainpoolp192r1,
+ (1, 3, 36, 3, 3, 2, 8, 1, 1, 3),
+ "brainpoolP192r1",
+)
+
+
+BRAINPOOLP224r1 = Curve(
+ "BRAINPOOLP224r1",
+ ecdsa.curve_brainpoolp224r1,
+ ecdsa.generator_brainpoolp224r1,
+ (1, 3, 36, 3, 3, 2, 8, 1, 1, 5),
+ "brainpoolP224r1",
+)
+
+
+BRAINPOOLP256r1 = Curve(
+ "BRAINPOOLP256r1",
+ ecdsa.curve_brainpoolp256r1,
+ ecdsa.generator_brainpoolp256r1,
+ (1, 3, 36, 3, 3, 2, 8, 1, 1, 7),
+ "brainpoolP256r1",
+)
+
+
+BRAINPOOLP320r1 = Curve(
+ "BRAINPOOLP320r1",
+ ecdsa.curve_brainpoolp320r1,
+ ecdsa.generator_brainpoolp320r1,
+ (1, 3, 36, 3, 3, 2, 8, 1, 1, 9),
+ "brainpoolP320r1",
+)
+
+
+BRAINPOOLP384r1 = Curve(
+ "BRAINPOOLP384r1",
+ ecdsa.curve_brainpoolp384r1,
+ ecdsa.generator_brainpoolp384r1,
+ (1, 3, 36, 3, 3, 2, 8, 1, 1, 11),
+ "brainpoolP384r1",
+)
+
+
+BRAINPOOLP512r1 = Curve(
+ "BRAINPOOLP512r1",
+ ecdsa.curve_brainpoolp512r1,
+ ecdsa.generator_brainpoolp512r1,
+ (1, 3, 36, 3, 3, 2, 8, 1, 1, 13),
+ "brainpoolP512r1",
+)
+
+
+curves = [
+ NIST192p,
+ NIST224p,
+ NIST256p,
+ NIST384p,
+ NIST521p,
+ SECP256k1,
+ BRAINPOOLP160r1,
+ BRAINPOOLP192r1,
+ BRAINPOOLP224r1,
+ BRAINPOOLP256r1,
+ BRAINPOOLP320r1,
+ BRAINPOOLP384r1,
+ BRAINPOOLP512r1,
+]
+
+
+def find_curve(oid_curve):
+ for c in curves:
+ if c.oid == oid_curve:
+ return c
+ raise UnknownCurveError(
+ "I don't know about the curve with oid %s."
+ "I only know about these: %s" % (oid_curve, [c.name for c in curves])
+ )
diff --git a/frozen_deps/ecdsa/der.py b/frozen_deps/ecdsa/der.py
new file mode 100644
index 0000000..8c1de9b
--- /dev/null
+++ b/frozen_deps/ecdsa/der.py
@@ -0,0 +1,409 @@
+from __future__ import division
+
+import binascii
+import base64
+import warnings
+from itertools import chain
+from six import int2byte, b, text_type
+from ._compat import str_idx_as_int
+
+
+class UnexpectedDER(Exception):
+ pass
+
+
+def encode_constructed(tag, value):
+ return int2byte(0xA0 + tag) + encode_length(len(value)) + value
+
+
+def encode_integer(r):
+ assert r >= 0 # can't support negative numbers yet
+ h = ("%x" % r).encode()
+ if len(h) % 2:
+ h = b("0") + h
+ s = binascii.unhexlify(h)
+ num = str_idx_as_int(s, 0)
+ if num <= 0x7F:
+ return b("\x02") + encode_length(len(s)) + s
+ else:
+ # DER integers are two's complement, so if the first byte is
+ # 0x80-0xff then we need an extra 0x00 byte to prevent it from
+ # looking negative.
+ return b("\x02") + encode_length(len(s) + 1) + b("\x00") + s
+
+
+# sentry object to check if an argument was specified (used to detect
+# deprecated calling convention)
+_sentry = object()
+
+
+def encode_bitstring(s, unused=_sentry):
+ """
+ Encode a binary string as a BIT STRING using :term:`DER` encoding.
+
+ Note, because there is no native Python object that can encode an actual
+ bit string, this function only accepts byte strings as the `s` argument.
+ The byte string is the actual bit string that will be encoded, padded
+ on the right (least significant bits, looking from big endian perspective)
+ to the first full byte. If the bit string has a bit length that is multiple
+ of 8, then the padding should not be included. For correct DER encoding
+ the padding bits MUST be set to 0.
+
+ Number of bits of padding need to be provided as the `unused` parameter.
+ In case they are specified as None, it means the number of unused bits
+ is already encoded in the string as the first byte.
+
+ The deprecated call convention specifies just the `s` parameters and
+ encodes the number of unused bits as first parameter (same convention
+ as with None).
+
+ Empty string must be encoded with `unused` specified as 0.
+
+ Future version of python-ecdsa will make specifying the `unused` argument
+ mandatory.
+
+ :param s: bytes to encode
+ :type s: bytes like object
+ :param unused: number of bits at the end of `s` that are unused, must be
+ between 0 and 7 (inclusive)
+ :type unused: int or None
+
+ :raises ValueError: when `unused` is too large or too small
+
+ :return: `s` encoded using DER
+ :rtype: bytes
+ """
+ encoded_unused = b""
+ len_extra = 0
+ if unused is _sentry:
+ warnings.warn(
+ "Legacy call convention used, unused= needs to be specified",
+ DeprecationWarning,
+ )
+ elif unused is not None:
+ if not 0 <= unused <= 7:
+ raise ValueError("unused must be integer between 0 and 7")
+ if unused:
+ if not s:
+ raise ValueError("unused is non-zero but s is empty")
+ last = str_idx_as_int(s, -1)
+ if last & (2 ** unused - 1):
+ raise ValueError("unused bits must be zeros in DER")
+ encoded_unused = int2byte(unused)
+ len_extra = 1
+ return b("\x03") + encode_length(len(s) + len_extra) + encoded_unused + s
+
+
+def encode_octet_string(s):
+ return b("\x04") + encode_length(len(s)) + s
+
+
+def encode_oid(first, second, *pieces):
+ assert 0 <= first < 2 and 0 <= second <= 39 or first == 2 and 0 <= second
+ body = b"".join(
+ chain(
+ [encode_number(40 * first + second)],
+ (encode_number(p) for p in pieces),
+ )
+ )
+ return b"\x06" + encode_length(len(body)) + body
+
+
+def encode_sequence(*encoded_pieces):
+ total_len = sum([len(p) for p in encoded_pieces])
+ return b("\x30") + encode_length(total_len) + b("").join(encoded_pieces)
+
+
+def encode_number(n):
+ b128_digits = []
+ while n:
+ b128_digits.insert(0, (n & 0x7F) | 0x80)
+ n = n >> 7
+ if not b128_digits:
+ b128_digits.append(0)
+ b128_digits[-1] &= 0x7F
+ return b("").join([int2byte(d) for d in b128_digits])
+
+
+def is_sequence(string):
+ return string and string[:1] == b"\x30"
+
+
+def remove_constructed(string):
+ s0 = str_idx_as_int(string, 0)
+ if (s0 & 0xE0) != 0xA0:
+ raise UnexpectedDER(
+ "wanted type 'constructed tag' (0xa0-0xbf), got 0x%02x" % s0
+ )
+ tag = s0 & 0x1F
+ length, llen = read_length(string[1:])
+ body = string[1 + llen : 1 + llen + length]
+ rest = string[1 + llen + length :]
+ return tag, body, rest
+
+
+def remove_sequence(string):
+ if not string:
+ raise UnexpectedDER("Empty string does not encode a sequence")
+ if string[:1] != b"\x30":
+ n = str_idx_as_int(string, 0)
+ raise UnexpectedDER("wanted type 'sequence' (0x30), got 0x%02x" % n)
+ length, lengthlength = read_length(string[1:])
+ if length > len(string) - 1 - lengthlength:
+ raise UnexpectedDER("Length longer than the provided buffer")
+ endseq = 1 + lengthlength + length
+ return string[1 + lengthlength : endseq], string[endseq:]
+
+
+def remove_octet_string(string):
+ if string[:1] != b"\x04":
+ n = str_idx_as_int(string, 0)
+ raise UnexpectedDER("wanted type 'octetstring' (0x04), got 0x%02x" % n)
+ length, llen = read_length(string[1:])
+ body = string[1 + llen : 1 + llen + length]
+ rest = string[1 + llen + length :]
+ return body, rest
+
+
+def remove_object(string):
+ if not string:
+ raise UnexpectedDER(
+ "Empty string does not encode an object identifier"
+ )
+ if string[:1] != b"\x06":
+ n = str_idx_as_int(string, 0)
+ raise UnexpectedDER("wanted type 'object' (0x06), got 0x%02x" % n)
+ length, lengthlength = read_length(string[1:])
+ body = string[1 + lengthlength : 1 + lengthlength + length]
+ rest = string[1 + lengthlength + length :]
+ if not body:
+ raise UnexpectedDER("Empty object identifier")
+ if len(body) != length:
+ raise UnexpectedDER(
+ "Length of object identifier longer than the provided buffer"
+ )
+ numbers = []
+ while body:
+ n, ll = read_number(body)
+ numbers.append(n)
+ body = body[ll:]
+ n0 = numbers.pop(0)
+ if n0 < 80:
+ first = n0 // 40
+ else:
+ first = 2
+ second = n0 - (40 * first)
+ numbers.insert(0, first)
+ numbers.insert(1, second)
+ return tuple(numbers), rest
+
+
+def remove_integer(string):
+ if not string:
+ raise UnexpectedDER(
+ "Empty string is an invalid encoding of an integer"
+ )
+ if string[:1] != b"\x02":
+ n = str_idx_as_int(string, 0)
+ raise UnexpectedDER("wanted type 'integer' (0x02), got 0x%02x" % n)
+ length, llen = read_length(string[1:])
+ if length > len(string) - 1 - llen:
+ raise UnexpectedDER("Length longer than provided buffer")
+ if length == 0:
+ raise UnexpectedDER("0-byte long encoding of integer")
+ numberbytes = string[1 + llen : 1 + llen + length]
+ rest = string[1 + llen + length :]
+ msb = str_idx_as_int(numberbytes, 0)
+ if not msb < 0x80:
+ raise UnexpectedDER("Negative integers are not supported")
+ # check if the encoding is the minimal one (DER requirement)
+ if length > 1 and not msb:
+ # leading zero byte is allowed if the integer would have been
+ # considered a negative number otherwise
+ smsb = str_idx_as_int(numberbytes, 1)
+ if smsb < 0x80:
+ raise UnexpectedDER(
+ "Invalid encoding of integer, unnecessary "
+ "zero padding bytes"
+ )
+ return int(binascii.hexlify(numberbytes), 16), rest
+
+
+def read_number(string):
+ number = 0
+ llen = 0
+ if str_idx_as_int(string, 0) == 0x80:
+ raise UnexpectedDER("Non minimal encoding of OID subidentifier")
+ # base-128 big endian, with most significant bit set in all but the last
+ # byte
+ while True:
+ if llen >= len(string):
+ raise UnexpectedDER("ran out of length bytes")
+ number = number << 7
+ d = str_idx_as_int(string, llen)
+ number += d & 0x7F
+ llen += 1
+ if not d & 0x80:
+ break
+ return number, llen
+
+
+def encode_length(l):
+ assert l >= 0
+ if l < 0x80:
+ return int2byte(l)
+ s = ("%x" % l).encode()
+ if len(s) % 2:
+ s = b("0") + s
+ s = binascii.unhexlify(s)
+ llen = len(s)
+ return int2byte(0x80 | llen) + s
+
+
+def read_length(string):
+ if not string:
+ raise UnexpectedDER("Empty string can't encode valid length value")
+ num = str_idx_as_int(string, 0)
+ if not (num & 0x80):
+ # short form
+ return (num & 0x7F), 1
+ # else long-form: b0&0x7f is number of additional base256 length bytes,
+ # big-endian
+ llen = num & 0x7F
+ if not llen:
+ raise UnexpectedDER("Invalid length encoding, length of length is 0")
+ if llen > len(string) - 1:
+ raise UnexpectedDER("Length of length longer than provided buffer")
+ # verify that the encoding is minimal possible (DER requirement)
+ msb = str_idx_as_int(string, 1)
+ if not msb or llen == 1 and msb < 0x80:
+ raise UnexpectedDER("Not minimal encoding of length")
+ return int(binascii.hexlify(string[1 : 1 + llen]), 16), 1 + llen
+
+
+def remove_bitstring(string, expect_unused=_sentry):
+ """
+ Remove a BIT STRING object from `string` following :term:`DER`.
+
+ The `expect_unused` can be used to specify if the bit string should
+ have the amount of unused bits decoded or not. If it's an integer, any
+ read BIT STRING that has number of unused bits different from specified
+ value will cause UnexpectedDER exception to be raised (this is especially
+ useful when decoding BIT STRINGS that have DER encoded object in them;
+ DER encoding is byte oriented, so the unused bits will always equal 0).
+
+ If the `expect_unused` is specified as None, the first element returned
+ will be a tuple, with the first value being the extracted bit string
+ while the second value will be the decoded number of unused bits.
+
+ If the `expect_unused` is unspecified, the decoding of byte with
+ number of unused bits will not be attempted and the bit string will be
+ returned as-is, the callee will be required to decode it and verify its
+ correctness.
+
+ Future version of python will require the `expected_unused` parameter
+ to be specified.
+
+ :param string: string of bytes to extract the BIT STRING from
+ :type string: bytes like object
+ :param expect_unused: number of bits that should be unused in the BIT
+ STRING, or None, to return it to caller
+ :type expect_unused: int or None
+
+ :raises UnexpectedDER: when the encoding does not follow DER.
+
+ :return: a tuple with first element being the extracted bit string and
+ the second being the remaining bytes in the string (if any); if the
+ `expect_unused` is specified as None, the first element of the returned
+ tuple will be a tuple itself, with first element being the bit string
+ as bytes and the second element being the number of unused bits at the
+ end of the byte array as an integer
+ :rtype: tuple
+ """
+ if not string:
+ raise UnexpectedDER("Empty string does not encode a bitstring")
+ if expect_unused is _sentry:
+ warnings.warn(
+ "Legacy call convention used, expect_unused= needs to be"
+ " specified",
+ DeprecationWarning,
+ )
+ num = str_idx_as_int(string, 0)
+ if string[:1] != b"\x03":
+ raise UnexpectedDER("wanted bitstring (0x03), got 0x%02x" % num)
+ length, llen = read_length(string[1:])
+ if not length:
+ raise UnexpectedDER("Invalid length of bit string, can't be 0")
+ body = string[1 + llen : 1 + llen + length]
+ rest = string[1 + llen + length :]
+ if expect_unused is not _sentry:
+ unused = str_idx_as_int(body, 0)
+ if not 0 <= unused <= 7:
+ raise UnexpectedDER("Invalid encoding of unused bits")
+ if expect_unused is not None and expect_unused != unused:
+ raise UnexpectedDER("Unexpected number of unused bits")
+ body = body[1:]
+ if unused:
+ if not body:
+ raise UnexpectedDER("Invalid encoding of empty bit string")
+ last = str_idx_as_int(body, -1)
+ # verify that all the unused bits are set to zero (DER requirement)
+ if last & (2 ** unused - 1):
+ raise UnexpectedDER("Non zero padding bits in bit string")
+ if expect_unused is None:
+ body = (body, unused)
+ return body, rest
+
+
+# SEQUENCE([1, STRING(secexp), cont[0], OBJECT(curvename), cont[1], BINTSTRING)
+
+
+# signatures: (from RFC3279)
+# ansi-X9-62 OBJECT IDENTIFIER ::= {
+# iso(1) member-body(2) us(840) 10045 }
+#
+# id-ecSigType OBJECT IDENTIFIER ::= {
+# ansi-X9-62 signatures(4) }
+# ecdsa-with-SHA1 OBJECT IDENTIFIER ::= {
+# id-ecSigType 1 }
+# so 1,2,840,10045,4,1
+# so 0x42, .. ..
+
+# Ecdsa-Sig-Value ::= SEQUENCE {
+# r INTEGER,
+# s INTEGER }
+
+# id-public-key-type OBJECT IDENTIFIER ::= { ansi-X9.62 2 }
+#
+# id-ecPublicKey OBJECT IDENTIFIER ::= { id-publicKeyType 1 }
+
+# I think the secp224r1 identifier is (t=06,l=05,v=2b81040021)
+# secp224r1 OBJECT IDENTIFIER ::= {
+# iso(1) identified-organization(3) certicom(132) curve(0) 33 }
+# and the secp384r1 is (t=06,l=05,v=2b81040022)
+# secp384r1 OBJECT IDENTIFIER ::= {
+# iso(1) identified-organization(3) certicom(132) curve(0) 34 }
+
+
+def unpem(pem):
+ if isinstance(pem, text_type):
+ pem = pem.encode()
+
+ d = b("").join(
+ [
+ l.strip()
+ for l in pem.split(b("\n"))
+ if l and not l.startswith(b("-----"))
+ ]
+ )
+ return base64.b64decode(d)
+
+
+def topem(der, name):
+ b64 = base64.b64encode(der)
+ lines = [("-----BEGIN %s-----\n" % name).encode()]
+ lines.extend(
+ [b64[start : start + 64] + b("\n") for start in range(0, len(b64), 64)]
+ )
+ lines.append(("-----END %s-----\n" % name).encode())
+ return b("").join(lines)
diff --git a/frozen_deps/ecdsa/ecdh.py b/frozen_deps/ecdsa/ecdh.py
new file mode 100644
index 0000000..9173279
--- /dev/null
+++ b/frozen_deps/ecdsa/ecdh.py
@@ -0,0 +1,327 @@
+"""
+Class for performing Elliptic-curve Diffie-Hellman (ECDH) operations.
+"""
+
+from .util import number_to_string
+from .ellipticcurve import INFINITY
+from .keys import SigningKey, VerifyingKey
+
+
+__all__ = [
+ "ECDH",
+ "NoKeyError",
+ "NoCurveError",
+ "InvalidCurveError",
+ "InvalidSharedSecretError",
+]
+
+
+class NoKeyError(Exception):
+ """ECDH. Key not found but it is needed for operation."""
+
+ pass
+
+
+class NoCurveError(Exception):
+ """ECDH. Curve not set but it is needed for operation."""
+
+ pass
+
+
+class InvalidCurveError(Exception):
+ """
+ ECDH. Raised in case the public and private keys use different curves.
+ """
+
+ pass
+
+
+class InvalidSharedSecretError(Exception):
+ """ECDH. Raised in case the shared secret we obtained is an INFINITY."""
+
+ pass
+
+
+class ECDH(object):
+ """
+ Elliptic-curve Diffie-Hellman (ECDH). A key agreement protocol.
+
+ Allows two parties, each having an elliptic-curve public-private key
+ pair, to establish a shared secret over an insecure channel
+ """
+
+ def __init__(self, curve=None, private_key=None, public_key=None):
+ """
+ ECDH init.
+
+ Call can be initialised without parameters, then the first operation
+ (loading either key) will set the used curve.
+ All parameters must be ultimately set before shared secret
+ calculation will be allowed.
+
+ :param curve: curve for operations
+ :type curve: Curve
+ :param private_key: `my` private key for ECDH
+ :type private_key: SigningKey
+ :param public_key: `their` public key for ECDH
+ :type public_key: VerifyingKey
+ """
+ self.curve = curve
+ self.private_key = None
+ self.public_key = None
+ if private_key:
+ self.load_private_key(private_key)
+ if public_key:
+ self.load_received_public_key(public_key)
+
+ def _get_shared_secret(self, remote_public_key):
+ if not self.private_key:
+ raise NoKeyError(
+ "Private key needs to be set to create shared secret"
+ )
+ if not self.public_key:
+ raise NoKeyError(
+ "Public key needs to be set to create shared secret"
+ )
+ if not (
+ self.private_key.curve == self.curve == remote_public_key.curve
+ ):
+ raise InvalidCurveError(
+ "Curves for public key and private key is not equal."
+ )
+
+ # shared secret = PUBKEYtheirs * PRIVATEKEYours
+ result = (
+ remote_public_key.pubkey.point
+ * self.private_key.privkey.secret_multiplier
+ )
+ if result == INFINITY:
+ raise InvalidSharedSecretError("Invalid shared secret (INFINITY).")
+
+ return result.x()
+
+ def set_curve(self, key_curve):
+ """
+ Set the working curve for ecdh operations.
+
+ :param key_curve: curve from `curves` module
+ :type key_curve: Curve
+ """
+ self.curve = key_curve
+
+ def generate_private_key(self):
+ """
+ Generate local private key for ecdh operation with curve that was set.
+
+ :raises NoCurveError: Curve must be set before key generation.
+
+ :return: public (verifying) key from this private key.
+ :rtype: VerifyingKey object
+ """
+ if not self.curve:
+ raise NoCurveError("Curve must be set prior to key generation.")
+ return self.load_private_key(SigningKey.generate(curve=self.curve))
+
+ def load_private_key(self, private_key):
+ """
+ Load private key from SigningKey (keys.py) object.
+
+ Needs to have the same curve as was set with set_curve method.
+ If curve is not set - it sets from this SigningKey
+
+ :param private_key: Initialised SigningKey class
+ :type private_key: SigningKey
+
+ :raises InvalidCurveError: private_key curve not the same as self.curve
+
+ :return: public (verifying) key from this private key.
+ :rtype: VerifyingKey object
+ """
+ if not self.curve:
+ self.curve = private_key.curve
+ if self.curve != private_key.curve:
+ raise InvalidCurveError("Curve mismatch.")
+ self.private_key = private_key
+ return self.private_key.get_verifying_key()
+
+ def load_private_key_bytes(self, private_key):
+ """
+ Load private key from byte string.
+
+ Uses current curve and checks if the provided key matches
+ the curve of ECDH key agreement.
+ Key loads via from_string method of SigningKey class
+
+ :param private_key: private key in bytes string format
+ :type private_key: :term:`bytes-like object`
+
+ :raises NoCurveError: Curve must be set before loading.
+
+ :return: public (verifying) key from this private key.
+ :rtype: VerifyingKey object
+ """
+ if not self.curve:
+ raise NoCurveError("Curve must be set prior to key load.")
+ return self.load_private_key(
+ SigningKey.from_string(private_key, curve=self.curve)
+ )
+
+ def load_private_key_der(self, private_key_der):
+ """
+ Load private key from DER byte string.
+
+ Compares the curve of the DER-encoded key with the ECDH set curve,
+ uses the former if unset.
+
+ Note, the only DER format supported is the RFC5915
+ Look at keys.py:SigningKey.from_der()
+
+ :param private_key_der: string with the DER encoding of private ECDSA
+ key
+ :type private_key_der: string
+
+ :raises InvalidCurveError: private_key curve not the same as self.curve
+
+ :return: public (verifying) key from this private key.
+ :rtype: VerifyingKey object
+ """
+ return self.load_private_key(SigningKey.from_der(private_key_der))
+
+ def load_private_key_pem(self, private_key_pem):
+ """
+ Load private key from PEM string.
+
+ Compares the curve of the DER-encoded key with the ECDH set curve,
+ uses the former if unset.
+
+ Note, the only PEM format supported is the RFC5915
+ Look at keys.py:SigningKey.from_pem()
+ it needs to have `EC PRIVATE KEY` section
+
+ :param private_key_pem: string with PEM-encoded private ECDSA key
+ :type private_key_pem: string
+
+ :raises InvalidCurveError: private_key curve not the same as self.curve
+
+ :return: public (verifying) key from this private key.
+ :rtype: VerifyingKey object
+ """
+ return self.load_private_key(SigningKey.from_pem(private_key_pem))
+
+ def get_public_key(self):
+ """
+ Provides a public key that matches the local private key.
+
+ Needs to be sent to the remote party.
+
+ :return: public (verifying) key from local private key.
+ :rtype: VerifyingKey object
+ """
+ return self.private_key.get_verifying_key()
+
+ def load_received_public_key(self, public_key):
+ """
+ Load public key from VerifyingKey (keys.py) object.
+
+ Needs to have the same curve as set as current for ecdh operation.
+ If curve is not set - it sets it from VerifyingKey.
+
+ :param public_key: Initialised VerifyingKey class
+ :type public_key: VerifyingKey
+
+ :raises InvalidCurveError: public_key curve not the same as self.curve
+ """
+ if not self.curve:
+ self.curve = public_key.curve
+ if self.curve != public_key.curve:
+ raise InvalidCurveError("Curve mismatch.")
+ self.public_key = public_key
+
+ def load_received_public_key_bytes(self, public_key_str):
+ """
+ Load public key from byte string.
+
+ Uses current curve and checks if key length corresponds to
+ the current curve.
+ Key loads via from_string method of VerifyingKey class
+
+ :param public_key_str: public key in bytes string format
+ :type public_key_str: :term:`bytes-like object`
+ """
+ return self.load_received_public_key(
+ VerifyingKey.from_string(public_key_str, self.curve)
+ )
+
+ def load_received_public_key_der(self, public_key_der):
+ """
+ Load public key from DER byte string.
+
+ Compares the curve of the DER-encoded key with the ECDH set curve,
+ uses the former if unset.
+
+ Note, the only DER format supported is the RFC5912
+ Look at keys.py:VerifyingKey.from_der()
+
+ :param public_key_der: string with the DER encoding of public ECDSA key
+ :type public_key_der: string
+
+ :raises InvalidCurveError: public_key curve not the same as self.curve
+ """
+ return self.load_received_public_key(
+ VerifyingKey.from_der(public_key_der)
+ )
+
+ def load_received_public_key_pem(self, public_key_pem):
+ """
+ Load public key from PEM string.
+
+ Compares the curve of the PEM-encoded key with the ECDH set curve,
+ uses the former if unset.
+
+ Note, the only PEM format supported is the RFC5912
+ Look at keys.py:VerifyingKey.from_pem()
+
+ :param public_key_pem: string with PEM-encoded public ECDSA key
+ :type public_key_pem: string
+
+ :raises InvalidCurveError: public_key curve not the same as self.curve
+ """
+ return self.load_received_public_key(
+ VerifyingKey.from_pem(public_key_pem)
+ )
+
+ def generate_sharedsecret_bytes(self):
+ """
+ Generate shared secret from local private key and remote public key.
+
+ The objects needs to have both private key and received public key
+ before generation is allowed.
+
+ :raises InvalidCurveError: public_key curve not the same as self.curve
+ :raises NoKeyError: public_key or private_key is not set
+
+ :return: shared secret
+ :rtype: byte string
+ """
+ return number_to_string(
+ self.generate_sharedsecret(), self.private_key.curve.order
+ )
+
+ def generate_sharedsecret(self):
+ """
+ Generate shared secret from local private key and remote public key.
+
+ The objects needs to have both private key and received public key
+ before generation is allowed.
+
+ It's the same for local and remote party.
+ shared secret(local private key, remote public key ) ==
+ shared secret (local public key, remote private key)
+
+ :raises InvalidCurveError: public_key curve not the same as self.curve
+ :raises NoKeyError: public_key or private_key is not set
+
+ :return: shared secret
+ :rtype: int
+ """
+ return self._get_shared_secret(self.public_key)
diff --git a/frozen_deps/ecdsa/ecdsa.py b/frozen_deps/ecdsa/ecdsa.py
new file mode 100644
index 0000000..d785a45
--- /dev/null
+++ b/frozen_deps/ecdsa/ecdsa.py
@@ -0,0 +1,754 @@
+#! /usr/bin/env python
+
+"""
+Implementation of Elliptic-Curve Digital Signatures.
+
+Classes and methods for elliptic-curve signatures:
+private keys, public keys, signatures,
+NIST prime-modulus curves with modulus lengths of
+192, 224, 256, 384, and 521 bits.
+
+Example:
+
+ # (In real-life applications, you would probably want to
+ # protect against defects in SystemRandom.)
+ from random import SystemRandom
+ randrange = SystemRandom().randrange
+
+ # Generate a public/private key pair using the NIST Curve P-192:
+
+ g = generator_192
+ n = g.order()
+ secret = randrange( 1, n )
+ pubkey = Public_key( g, g * secret )
+ privkey = Private_key( pubkey, secret )
+
+ # Signing a hash value:
+
+ hash = randrange( 1, n )
+ signature = privkey.sign( hash, randrange( 1, n ) )
+
+ # Verifying a signature for a hash value:
+
+ if pubkey.verifies( hash, signature ):
+ print_("Demo verification succeeded.")
+ else:
+ print_("*** Demo verification failed.")
+
+ # Verification fails if the hash value is modified:
+
+ if pubkey.verifies( hash-1, signature ):
+ print_("**** Demo verification failed to reject tampered hash.")
+ else:
+ print_("Demo verification correctly rejected tampered hash.")
+
+Version of 2009.05.16.
+
+Revision history:
+ 2005.12.31 - Initial version.
+ 2008.11.25 - Substantial revisions introducing new classes.
+ 2009.05.16 - Warn against using random.randrange in real applications.
+ 2009.05.17 - Use random.SystemRandom by default.
+
+Written in 2005 by Peter Pearson and placed in the public domain.
+"""
+
+from six import int2byte, b
+from . import ellipticcurve
+from . import numbertheory
+from .util import bit_length
+from ._compat import remove_whitespace
+
+
+class RSZeroError(RuntimeError):
+ pass
+
+
+class InvalidPointError(RuntimeError):
+ pass
+
+
+class Signature(object):
+ """ECDSA signature."""
+
+ def __init__(self, r, s):
+ self.r = r
+ self.s = s
+
+ def recover_public_keys(self, hash, generator):
+ """Returns two public keys for which the signature is valid
+ hash is signed hash
+ generator is the used generator of the signature
+ """
+ curve = generator.curve()
+ n = generator.order()
+ r = self.r
+ s = self.s
+ e = hash
+ x = r
+
+ # Compute the curve point with x as x-coordinate
+ alpha = (
+ pow(x, 3, curve.p()) + (curve.a() * x) + curve.b()
+ ) % curve.p()
+ beta = numbertheory.square_root_mod_prime(alpha, curve.p())
+ y = beta if beta % 2 == 0 else curve.p() - beta
+
+ # Compute the public key
+ R1 = ellipticcurve.PointJacobi(curve, x, y, 1, n)
+ Q1 = numbertheory.inverse_mod(r, n) * (s * R1 + (-e % n) * generator)
+ Pk1 = Public_key(generator, Q1)
+
+ # And the second solution
+ R2 = ellipticcurve.PointJacobi(curve, x, -y, 1, n)
+ Q2 = numbertheory.inverse_mod(r, n) * (s * R2 + (-e % n) * generator)
+ Pk2 = Public_key(generator, Q2)
+
+ return [Pk1, Pk2]
+
+
+class Public_key(object):
+ """Public key for ECDSA."""
+
+ def __init__(self, generator, point, verify=True):
+ """Low level ECDSA public key object.
+
+ :param generator: the Point that generates the group (the base point)
+ :param point: the Point that defines the public key
+ :param bool verify: if True check if point is valid point on curve
+
+ :raises InvalidPointError: if the point parameters are invalid or
+ point does not lie on the curve
+ """
+
+ self.curve = generator.curve()
+ self.generator = generator
+ self.point = point
+ n = generator.order()
+ p = self.curve.p()
+ if not (0 <= point.x() < p) or not (0 <= point.y() < p):
+ raise InvalidPointError(
+ "The public point has x or y out of range."
+ )
+ if verify and not self.curve.contains_point(point.x(), point.y()):
+ raise InvalidPointError("Point does not lie on the curve")
+ if not n:
+ raise InvalidPointError("Generator point must have order.")
+ # for curve parameters with base point with cofactor 1, all points
+ # that are on the curve are scalar multiples of the base point, so
+ # verifying that is not necessary. See Section 3.2.2.1 of SEC 1 v2
+ if (
+ verify
+ and self.curve.cofactor() != 1
+ and not n * point == ellipticcurve.INFINITY
+ ):
+ raise InvalidPointError("Generator point order is bad.")
+
+ def __eq__(self, other):
+ if isinstance(other, Public_key):
+ """Return True if the points are identical, False otherwise."""
+ return self.curve == other.curve and self.point == other.point
+ return NotImplemented
+
+ def verifies(self, hash, signature):
+ """Verify that signature is a valid signature of hash.
+ Return True if the signature is valid.
+ """
+
+ # From X9.62 J.3.1.
+
+ G = self.generator
+ n = G.order()
+ r = signature.r
+ s = signature.s
+ if r < 1 or r > n - 1:
+ return False
+ if s < 1 or s > n - 1:
+ return False
+ c = numbertheory.inverse_mod(s, n)
+ u1 = (hash * c) % n
+ u2 = (r * c) % n
+ if hasattr(G, "mul_add"):
+ xy = G.mul_add(u1, self.point, u2)
+ else:
+ xy = u1 * G + u2 * self.point
+ v = xy.x() % n
+ return v == r
+
+
+class Private_key(object):
+ """Private key for ECDSA."""
+
+ def __init__(self, public_key, secret_multiplier):
+ """public_key is of class Public_key;
+ secret_multiplier is a large integer.
+ """
+
+ self.public_key = public_key
+ self.secret_multiplier = secret_multiplier
+
+ def __eq__(self, other):
+ if isinstance(other, Private_key):
+ """Return True if the points are identical, False otherwise."""
+ return (
+ self.public_key == other.public_key
+ and self.secret_multiplier == other.secret_multiplier
+ )
+ return NotImplemented
+
+ def sign(self, hash, random_k):
+ """Return a signature for the provided hash, using the provided
+ random nonce. It is absolutely vital that random_k be an unpredictable
+ number in the range [1, self.public_key.point.order()-1]. If
+ an attacker can guess random_k, he can compute our private key from a
+ single signature. Also, if an attacker knows a few high-order
+ bits (or a few low-order bits) of random_k, he can compute our private
+ key from many signatures. The generation of nonces with adequate
+ cryptographic strength is very difficult and far beyond the scope
+ of this comment.
+
+ May raise RuntimeError, in which case retrying with a new
+ random value k is in order.
+ """
+
+ G = self.public_key.generator
+ n = G.order()
+ k = random_k % n
+ # Fix the bit-length of the random nonce,
+ # so that it doesn't leak via timing.
+ # This does not change that ks = k mod n
+ ks = k + n
+ kt = ks + n
+ if bit_length(ks) == bit_length(n):
+ p1 = kt * G
+ else:
+ p1 = ks * G
+ r = p1.x() % n
+ if r == 0:
+ raise RSZeroError("amazingly unlucky random number r")
+ s = (
+ numbertheory.inverse_mod(k, n)
+ * (hash + (self.secret_multiplier * r) % n)
+ ) % n
+ if s == 0:
+ raise RSZeroError("amazingly unlucky random number s")
+ return Signature(r, s)
+
+
+def int_to_string(x):
+ """Convert integer x into a string of bytes, as per X9.62."""
+ assert x >= 0
+ if x == 0:
+ return b("\0")
+ result = []
+ while x:
+ ordinal = x & 0xFF
+ result.append(int2byte(ordinal))
+ x >>= 8
+
+ result.reverse()
+ return b("").join(result)
+
+
+def string_to_int(s):
+ """Convert a string of bytes into an integer, as per X9.62."""
+ result = 0
+ for c in s:
+ if not isinstance(c, int):
+ c = ord(c)
+ result = 256 * result + c
+ return result
+
+
+def digest_integer(m):
+ """Convert an integer into a string of bytes, compute
+ its SHA-1 hash, and convert the result to an integer."""
+ #
+ # I don't expect this function to be used much. I wrote
+ # it in order to be able to duplicate the examples
+ # in ECDSAVS.
+ #
+ from hashlib import sha1
+
+ return string_to_int(sha1(int_to_string(m)).digest())
+
+
+def point_is_valid(generator, x, y):
+ """Is (x,y) a valid public key based on the specified generator?"""
+
+ # These are the tests specified in X9.62.
+
+ n = generator.order()
+ curve = generator.curve()
+ p = curve.p()
+ if not (0 <= x < p) or not (0 <= y < p):
+ return False
+ if not curve.contains_point(x, y):
+ return False
+ if (
+ curve.cofactor() != 1
+ and not n * ellipticcurve.PointJacobi(curve, x, y, 1)
+ == ellipticcurve.INFINITY
+ ):
+ return False
+ return True
+
+
+# NIST Curve P-192:
+_p = 6277101735386680763835789423207666416083908700390324961279
+_r = 6277101735386680763835789423176059013767194773182842284081
+# s = 0x3045ae6fc8422f64ed579528d38120eae12196d5L
+# c = 0x3099d2bbbfcb2538542dcd5fb078b6ef5f3d6fe2c745de65L
+_b = int(
+ remove_whitespace(
+ """
+ 64210519 E59C80E7 0FA7E9AB 72243049 FEB8DEEC C146B9B1"""
+ ),
+ 16,
+)
+_Gx = int(
+ remove_whitespace(
+ """
+ 188DA80E B03090F6 7CBF20EB 43A18800 F4FF0AFD 82FF1012"""
+ ),
+ 16,
+)
+_Gy = int(
+ remove_whitespace(
+ """
+ 07192B95 FFC8DA78 631011ED 6B24CDD5 73F977A1 1E794811"""
+ ),
+ 16,
+)
+
+curve_192 = ellipticcurve.CurveFp(_p, -3, _b, 1)
+generator_192 = ellipticcurve.PointJacobi(
+ curve_192, _Gx, _Gy, 1, _r, generator=True
+)
+
+
+# NIST Curve P-224:
+_p = int(
+ remove_whitespace(
+ """
+ 2695994666715063979466701508701963067355791626002630814351
+ 0066298881"""
+ )
+)
+_r = int(
+ remove_whitespace(
+ """
+ 2695994666715063979466701508701962594045780771442439172168
+ 2722368061"""
+ )
+)
+# s = 0xbd71344799d5c7fcdc45b59fa3b9ab8f6a948bc5L
+# c = 0x5b056c7e11dd68f40469ee7f3c7a7d74f7d121116506d031218291fbL
+_b = int(
+ remove_whitespace(
+ """
+ B4050A85 0C04B3AB F5413256 5044B0B7 D7BFD8BA 270B3943
+ 2355FFB4"""
+ ),
+ 16,
+)
+_Gx = int(
+ remove_whitespace(
+ """
+ B70E0CBD 6BB4BF7F 321390B9 4A03C1D3 56C21122 343280D6
+ 115C1D21"""
+ ),
+ 16,
+)
+_Gy = int(
+ remove_whitespace(
+ """
+ BD376388 B5F723FB 4C22DFE6 CD4375A0 5A074764 44D58199
+ 85007E34"""
+ ),
+ 16,
+)
+
+curve_224 = ellipticcurve.CurveFp(_p, -3, _b, 1)
+generator_224 = ellipticcurve.PointJacobi(
+ curve_224, _Gx, _Gy, 1, _r, generator=True
+)
+
+# NIST Curve P-256:
+_p = int(
+ remove_whitespace(
+ """
+ 1157920892103562487626974469494075735300861434152903141955
+ 33631308867097853951"""
+ )
+)
+_r = int(
+ remove_whitespace(
+ """
+ 115792089210356248762697446949407573529996955224135760342
+ 422259061068512044369"""
+ )
+)
+# s = 0xc49d360886e704936a6678e1139d26b7819f7e90L
+# c = 0x7efba1662985be9403cb055c75d4f7e0ce8d84a9c5114abcaf3177680104fa0dL
+_b = int(
+ remove_whitespace(
+ """
+ 5AC635D8 AA3A93E7 B3EBBD55 769886BC 651D06B0 CC53B0F6
+ 3BCE3C3E 27D2604B"""
+ ),
+ 16,
+)
+_Gx = int(
+ remove_whitespace(
+ """
+ 6B17D1F2 E12C4247 F8BCE6E5 63A440F2 77037D81 2DEB33A0
+ F4A13945 D898C296"""
+ ),
+ 16,
+)
+_Gy = int(
+ remove_whitespace(
+ """
+ 4FE342E2 FE1A7F9B 8EE7EB4A 7C0F9E16 2BCE3357 6B315ECE
+ CBB64068 37BF51F5"""
+ ),
+ 16,
+)
+
+curve_256 = ellipticcurve.CurveFp(_p, -3, _b, 1)
+generator_256 = ellipticcurve.PointJacobi(
+ curve_256, _Gx, _Gy, 1, _r, generator=True
+)
+
+# NIST Curve P-384:
+_p = int(
+ remove_whitespace(
+ """
+ 3940200619639447921227904010014361380507973927046544666794
+ 8293404245721771496870329047266088258938001861606973112319"""
+ )
+)
+_r = int(
+ remove_whitespace(
+ """
+ 3940200619639447921227904010014361380507973927046544666794
+ 6905279627659399113263569398956308152294913554433653942643"""
+ )
+)
+# s = 0xa335926aa319a27a1d00896a6773a4827acdac73L
+# c = int(remove_whitespace(
+# """
+# 79d1e655 f868f02f ff48dcde e14151dd b80643c1 406d0ca1
+# 0dfe6fc5 2009540a 495e8042 ea5f744f 6e184667 cc722483"""
+# ), 16)
+_b = int(
+ remove_whitespace(
+ """
+ B3312FA7 E23EE7E4 988E056B E3F82D19 181D9C6E FE814112
+ 0314088F 5013875A C656398D 8A2ED19D 2A85C8ED D3EC2AEF"""
+ ),
+ 16,
+)
+_Gx = int(
+ remove_whitespace(
+ """
+ AA87CA22 BE8B0537 8EB1C71E F320AD74 6E1D3B62 8BA79B98
+ 59F741E0 82542A38 5502F25D BF55296C 3A545E38 72760AB7"""
+ ),
+ 16,
+)
+_Gy = int(
+ remove_whitespace(
+ """
+ 3617DE4A 96262C6F 5D9E98BF 9292DC29 F8F41DBD 289A147C
+ E9DA3113 B5F0B8C0 0A60B1CE 1D7E819D 7A431D7C 90EA0E5F"""
+ ),
+ 16,
+)
+
+curve_384 = ellipticcurve.CurveFp(_p, -3, _b, 1)
+generator_384 = ellipticcurve.PointJacobi(
+ curve_384, _Gx, _Gy, 1, _r, generator=True
+)
+
+# NIST Curve P-521:
+_p = int(
+ "686479766013060971498190079908139321726943530014330540939"
+ "446345918554318339765605212255964066145455497729631139148"
+ "0858037121987999716643812574028291115057151"
+)
+_r = int(
+ "686479766013060971498190079908139321726943530014330540939"
+ "446345918554318339765539424505774633321719753296399637136"
+ "3321113864768612440380340372808892707005449"
+)
+# s = 0xd09e8800291cb85396cc6717393284aaa0da64baL
+# c = int(remove_whitespace(
+# """
+# 0b4 8bfa5f42 0a349495 39d2bdfc 264eeeeb 077688e4
+# 4fbf0ad8 f6d0edb3 7bd6b533 28100051 8e19f1b9 ffbe0fe9
+# ed8a3c22 00b8f875 e523868c 70c1e5bf 55bad637"""
+# ), 16)
+_b = int(
+ remove_whitespace(
+ """
+ 051 953EB961 8E1C9A1F 929A21A0 B68540EE A2DA725B
+ 99B315F3 B8B48991 8EF109E1 56193951 EC7E937B 1652C0BD
+ 3BB1BF07 3573DF88 3D2C34F1 EF451FD4 6B503F00"""
+ ),
+ 16,
+)
+_Gx = int(
+ remove_whitespace(
+ """
+ C6 858E06B7 0404E9CD 9E3ECB66 2395B442 9C648139
+ 053FB521 F828AF60 6B4D3DBA A14B5E77 EFE75928 FE1DC127
+ A2FFA8DE 3348B3C1 856A429B F97E7E31 C2E5BD66"""
+ ),
+ 16,
+)
+_Gy = int(
+ remove_whitespace(
+ """
+ 118 39296A78 9A3BC004 5C8A5FB4 2C7D1BD9 98F54449
+ 579B4468 17AFBD17 273E662C 97EE7299 5EF42640 C550B901
+ 3FAD0761 353C7086 A272C240 88BE9476 9FD16650"""
+ ),
+ 16,
+)
+
+curve_521 = ellipticcurve.CurveFp(_p, -3, _b, 1)
+generator_521 = ellipticcurve.PointJacobi(
+ curve_521, _Gx, _Gy, 1, _r, generator=True
+)
+
+# Certicom secp256-k1
+_a = 0x0000000000000000000000000000000000000000000000000000000000000000
+_b = 0x0000000000000000000000000000000000000000000000000000000000000007
+_p = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F
+_Gx = 0x79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798
+_Gy = 0x483ADA7726A3C4655DA4FBFC0E1108A8FD17B448A68554199C47D08FFB10D4B8
+_r = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141
+
+curve_secp256k1 = ellipticcurve.CurveFp(_p, _a, _b, 1)
+generator_secp256k1 = ellipticcurve.PointJacobi(
+ curve_secp256k1, _Gx, _Gy, 1, _r, generator=True
+)
+
+# Brainpool P-160-r1
+_a = 0x340E7BE2A280EB74E2BE61BADA745D97E8F7C300
+_b = 0x1E589A8595423412134FAA2DBDEC95C8D8675E58
+_p = 0xE95E4A5F737059DC60DFC7AD95B3D8139515620F
+_Gx = 0xBED5AF16EA3F6A4F62938C4631EB5AF7BDBCDBC3
+_Gy = 0x1667CB477A1A8EC338F94741669C976316DA6321
+_q = 0xE95E4A5F737059DC60DF5991D45029409E60FC09
+
+curve_brainpoolp160r1 = ellipticcurve.CurveFp(_p, _a, _b, 1)
+generator_brainpoolp160r1 = ellipticcurve.PointJacobi(
+ curve_brainpoolp160r1, _Gx, _Gy, 1, _q, generator=True
+)
+
+# Brainpool P-192-r1
+_a = 0x6A91174076B1E0E19C39C031FE8685C1CAE040E5C69A28EF
+_b = 0x469A28EF7C28CCA3DC721D044F4496BCCA7EF4146FBF25C9
+_p = 0xC302F41D932A36CDA7A3463093D18DB78FCE476DE1A86297
+_Gx = 0xC0A0647EAAB6A48753B033C56CB0F0900A2F5C4853375FD6
+_Gy = 0x14B690866ABD5BB88B5F4828C1490002E6773FA2FA299B8F
+_q = 0xC302F41D932A36CDA7A3462F9E9E916B5BE8F1029AC4ACC1
+
+curve_brainpoolp192r1 = ellipticcurve.CurveFp(_p, _a, _b, 1)
+generator_brainpoolp192r1 = ellipticcurve.PointJacobi(
+ curve_brainpoolp192r1, _Gx, _Gy, 1, _q, generator=True
+)
+
+# Brainpool P-224-r1
+_a = 0x68A5E62CA9CE6C1C299803A6C1530B514E182AD8B0042A59CAD29F43
+_b = 0x2580F63CCFE44138870713B1A92369E33E2135D266DBB372386C400B
+_p = 0xD7C134AA264366862A18302575D1D787B09F075797DA89F57EC8C0FF
+_Gx = 0x0D9029AD2C7E5CF4340823B2A87DC68C9E4CE3174C1E6EFDEE12C07D
+_Gy = 0x58AA56F772C0726F24C6B89E4ECDAC24354B9E99CAA3F6D3761402CD
+_q = 0xD7C134AA264366862A18302575D0FB98D116BC4B6DDEBCA3A5A7939F
+
+curve_brainpoolp224r1 = ellipticcurve.CurveFp(_p, _a, _b, 1)
+generator_brainpoolp224r1 = ellipticcurve.PointJacobi(
+ curve_brainpoolp224r1, _Gx, _Gy, 1, _q, generator=True
+)
+
+# Brainpool P-256-r1
+_a = 0x7D5A0975FC2C3057EEF67530417AFFE7FB8055C126DC5C6CE94A4B44F330B5D9
+_b = 0x26DC5C6CE94A4B44F330B5D9BBD77CBF958416295CF7E1CE6BCCDC18FF8C07B6
+_p = 0xA9FB57DBA1EEA9BC3E660A909D838D726E3BF623D52620282013481D1F6E5377
+_Gx = 0x8BD2AEB9CB7E57CB2C4B482FFC81B7AFB9DE27E1E3BD23C23A4453BD9ACE3262
+_Gy = 0x547EF835C3DAC4FD97F8461A14611DC9C27745132DED8E545C1D54C72F046997
+_q = 0xA9FB57DBA1EEA9BC3E660A909D838D718C397AA3B561A6F7901E0E82974856A7
+
+curve_brainpoolp256r1 = ellipticcurve.CurveFp(_p, _a, _b, 1)
+generator_brainpoolp256r1 = ellipticcurve.PointJacobi(
+ curve_brainpoolp256r1, _Gx, _Gy, 1, _q, generator=True
+)
+
+# Brainpool P-320-r1
+_a = int(
+ remove_whitespace(
+ """
+ 3EE30B568FBAB0F883CCEBD46D3F3BB8A2A73513F5EB79DA66190EB085FFA9
+ F492F375A97D860EB4"""
+ ),
+ 16,
+)
+_b = int(
+ remove_whitespace(
+ """
+ 520883949DFDBC42D3AD198640688A6FE13F41349554B49ACC31DCCD884539
+ 816F5EB4AC8FB1F1A6"""
+ ),
+ 16,
+)
+_p = int(
+ remove_whitespace(
+ """
+ D35E472036BC4FB7E13C785ED201E065F98FCFA6F6F40DEF4F92B9EC7893EC
+ 28FCD412B1F1B32E27"""
+ ),
+ 16,
+)
+_Gx = int(
+ remove_whitespace(
+ """
+ 43BD7E9AFB53D8B85289BCC48EE5BFE6F20137D10A087EB6E7871E2A10A599
+ C710AF8D0D39E20611"""
+ ),
+ 16,
+)
+_Gy = int(
+ remove_whitespace(
+ """
+ 14FDD05545EC1CC8AB4093247F77275E0743FFED117182EAA9C77877AAAC6A
+ C7D35245D1692E8EE1"""
+ ),
+ 16,
+)
+_q = int(
+ remove_whitespace(
+ """
+ D35E472036BC4FB7E13C785ED201E065F98FCFA5B68F12A32D482EC7EE8658
+ E98691555B44C59311"""
+ ),
+ 16,
+)
+
+curve_brainpoolp320r1 = ellipticcurve.CurveFp(_p, _a, _b, 1)
+generator_brainpoolp320r1 = ellipticcurve.PointJacobi(
+ curve_brainpoolp320r1, _Gx, _Gy, 1, _q, generator=True
+)
+
+# Brainpool P-384-r1
+_a = int(
+ remove_whitespace(
+ """
+ 7BC382C63D8C150C3C72080ACE05AFA0C2BEA28E4FB22787139165EFBA91F9
+ 0F8AA5814A503AD4EB04A8C7DD22CE2826"""
+ ),
+ 16,
+)
+_b = int(
+ remove_whitespace(
+ """
+ 04A8C7DD22CE28268B39B55416F0447C2FB77DE107DCD2A62E880EA53EEB62
+ D57CB4390295DBC9943AB78696FA504C11"""
+ ),
+ 16,
+)
+_p = int(
+ remove_whitespace(
+ """
+ 8CB91E82A3386D280F5D6F7E50E641DF152F7109ED5456B412B1DA197FB711
+ 23ACD3A729901D1A71874700133107EC53"""
+ ),
+ 16,
+)
+_Gx = int(
+ remove_whitespace(
+ """
+ 1D1C64F068CF45FFA2A63A81B7C13F6B8847A3E77EF14FE3DB7FCAFE0CBD10
+ E8E826E03436D646AAEF87B2E247D4AF1E"""
+ ),
+ 16,
+)
+_Gy = int(
+ remove_whitespace(
+ """
+ 8ABE1D7520F9C2A45CB1EB8E95CFD55262B70B29FEEC5864E19C054FF991292
+ 80E4646217791811142820341263C5315"""
+ ),
+ 16,
+)
+_q = int(
+ remove_whitespace(
+ """
+ 8CB91E82A3386D280F5D6F7E50E641DF152F7109ED5456B31F166E6CAC0425
+ A7CF3AB6AF6B7FC3103B883202E9046565"""
+ ),
+ 16,
+)
+
+curve_brainpoolp384r1 = ellipticcurve.CurveFp(_p, _a, _b, 1)
+generator_brainpoolp384r1 = ellipticcurve.PointJacobi(
+ curve_brainpoolp384r1, _Gx, _Gy, 1, _q, generator=True
+)
+
+# Brainpool P-512-r1
+_a = int(
+ remove_whitespace(
+ """
+ 7830A3318B603B89E2327145AC234CC594CBDD8D3DF91610A83441CAEA9863
+ BC2DED5D5AA8253AA10A2EF1C98B9AC8B57F1117A72BF2C7B9E7C1AC4D77FC94CA"""
+ ),
+ 16,
+)
+_b = int(
+ remove_whitespace(
+ """
+ 3DF91610A83441CAEA9863BC2DED5D5AA8253AA10A2EF1C98B9AC8B57F1117
+ A72BF2C7B9E7C1AC4D77FC94CADC083E67984050B75EBAE5DD2809BD638016F723"""
+ ),
+ 16,
+)
+_p = int(
+ remove_whitespace(
+ """
+ AADD9DB8DBE9C48B3FD4E6AE33C9FC07CB308DB3B3C9D20ED6639CCA703308
+ 717D4D9B009BC66842AECDA12AE6A380E62881FF2F2D82C68528AA6056583A48F3"""
+ ),
+ 16,
+)
+_Gx = int(
+ remove_whitespace(
+ """
+ 81AEE4BDD82ED9645A21322E9C4C6A9385ED9F70B5D916C1B43B62EEF4D009
+ 8EFF3B1F78E2D0D48D50D1687B93B97D5F7C6D5047406A5E688B352209BCB9F822"""
+ ),
+ 16,
+)
+_Gy = int(
+ remove_whitespace(
+ """
+ 7DDE385D566332ECC0EABFA9CF7822FDF209F70024A57B1AA000C55B881F81
+ 11B2DCDE494A5F485E5BCA4BD88A2763AED1CA2B2FA8F0540678CD1E0F3AD80892"""
+ ),
+ 16,
+)
+_q = int(
+ remove_whitespace(
+ """
+ AADD9DB8DBE9C48B3FD4E6AE33C9FC07CB308DB3B3C9D20ED6639CCA703308
+ 70553E5C414CA92619418661197FAC10471DB1D381085DDADDB58796829CA90069"""
+ ),
+ 16,
+)
+
+curve_brainpoolp512r1 = ellipticcurve.CurveFp(_p, _a, _b, 1)
+generator_brainpoolp512r1 = ellipticcurve.PointJacobi(
+ curve_brainpoolp512r1, _Gx, _Gy, 1, _q, generator=True
+)
diff --git a/frozen_deps/ecdsa/ellipticcurve.py b/frozen_deps/ecdsa/ellipticcurve.py
new file mode 100644
index 0000000..25565df
--- /dev/null
+++ b/frozen_deps/ecdsa/ellipticcurve.py
@@ -0,0 +1,847 @@
+#! /usr/bin/env python
+# -*- coding: utf-8 -*-
+#
+# Implementation of elliptic curves, for cryptographic applications.
+#
+# This module doesn't provide any way to choose a random elliptic
+# curve, nor to verify that an elliptic curve was chosen randomly,
+# because one can simply use NIST's standard curves.
+#
+# Notes from X9.62-1998 (draft):
+# Nomenclature:
+# - Q is a public key.
+# The "Elliptic Curve Domain Parameters" include:
+# - q is the "field size", which in our case equals p.
+# - p is a big prime.
+# - G is a point of prime order (5.1.1.1).
+# - n is the order of G (5.1.1.1).
+# Public-key validation (5.2.2):
+# - Verify that Q is not the point at infinity.
+# - Verify that X_Q and Y_Q are in [0,p-1].
+# - Verify that Q is on the curve.
+# - Verify that nQ is the point at infinity.
+# Signature generation (5.3):
+# - Pick random k from [1,n-1].
+# Signature checking (5.4.2):
+# - Verify that r and s are in [1,n-1].
+#
+# Version of 2008.11.25.
+#
+# Revision history:
+# 2005.12.31 - Initial version.
+# 2008.11.25 - Change CurveFp.is_on to contains_point.
+#
+# Written in 2005 by Peter Pearson and placed in the public domain.
+
+from __future__ import division
+
+try:
+ from gmpy2 import mpz
+
+ GMPY = True
+except ImportError:
+ try:
+ from gmpy import mpz
+
+ GMPY = True
+ except ImportError:
+ GMPY = False
+
+
+from six import python_2_unicode_compatible
+from . import numbertheory
+from ._rwlock import RWLock
+
+
+@python_2_unicode_compatible
+class CurveFp(object):
+ """Elliptic Curve over the field of integers modulo a prime."""
+
+ if GMPY:
+
+ def __init__(self, p, a, b, h=None):
+ """
+ The curve of points satisfying y^2 = x^3 + a*x + b (mod p).
+
+ h is an integer that is the cofactor of the elliptic curve domain
+ parameters; it is the number of points satisfying the elliptic
+ curve equation divided by the order of the base point. It is used
+ for selection of efficient algorithm for public point verification.
+ """
+ self.__p = mpz(p)
+ self.__a = mpz(a)
+ self.__b = mpz(b)
+ # h is not used in calculations and it can be None, so don't use
+ # gmpy with it
+ self.__h = h
+
+ else:
+
+ def __init__(self, p, a, b, h=None):
+ """
+ The curve of points satisfying y^2 = x^3 + a*x + b (mod p).
+
+ h is an integer that is the cofactor of the elliptic curve domain
+ parameters; it is the number of points satisfying the elliptic
+ curve equation divided by the order of the base point. It is used
+ for selection of efficient algorithm for public point verification.
+ """
+ self.__p = p
+ self.__a = a
+ self.__b = b
+ self.__h = h
+
+ def __eq__(self, other):
+ if isinstance(other, CurveFp):
+ """Return True if the curves are identical, False otherwise."""
+ return (
+ self.__p == other.__p
+ and self.__a == other.__a
+ and self.__b == other.__b
+ )
+ return NotImplemented
+
+ def __ne__(self, other):
+ return not (self == other)
+
+ def __hash__(self):
+ return hash((self.__p, self.__a, self.__b))
+
+ def p(self):
+ return self.__p
+
+ def a(self):
+ return self.__a
+
+ def b(self):
+ return self.__b
+
+ def cofactor(self):
+ return self.__h
+
+ def contains_point(self, x, y):
+ """Is the point (x,y) on this curve?"""
+ return (y * y - ((x * x + self.__a) * x + self.__b)) % self.__p == 0
+
+ def __str__(self):
+ return "CurveFp(p=%d, a=%d, b=%d, h=%d)" % (
+ self.__p,
+ self.__a,
+ self.__b,
+ self.__h,
+ )
+
+
+class PointJacobi(object):
+ """
+ Point on an elliptic curve. Uses Jacobi coordinates.
+
+ In Jacobian coordinates, there are three parameters, X, Y and Z.
+ They correspond to affine parameters 'x' and 'y' like so:
+
+ x = X / Z²
+ y = Y / Z³
+ """
+
+ def __init__(self, curve, x, y, z, order=None, generator=False):
+ """
+ Initialise a point that uses Jacobi representation internally.
+
+ :param CurveFp curve: curve on which the point resides
+ :param int x: the X parameter of Jacobi representation (equal to x when
+ converting from affine coordinates
+ :param int y: the Y parameter of Jacobi representation (equal to y when
+ converting from affine coordinates
+ :param int z: the Z parameter of Jacobi representation (equal to 1 when
+ converting from affine coordinates
+ :param int order: the point order, must be non zero when using
+ generator=True
+ :param bool generator: the point provided is a curve generator, as
+ such, it will be commonly used with scalar multiplication. This will
+ cause to precompute multiplication table for it
+ """
+ self.__curve = curve
+ # since it's generally better (faster) to use scaled points vs unscaled
+ # ones, use writer-biased RWLock for locking:
+ self._update_lock = RWLock()
+ if GMPY:
+ self.__x = mpz(x)
+ self.__y = mpz(y)
+ self.__z = mpz(z)
+ self.__order = order and mpz(order)
+ else:
+ self.__x = x
+ self.__y = y
+ self.__z = z
+ self.__order = order
+ self.__generator = generator
+ self.__precompute = []
+
+ def _maybe_precompute(self):
+ if self.__generator:
+ # since we lack promotion of read-locks to write-locks, we do a
+ # "acquire-read-lock, check, acquire-write-lock plus recheck" cycle
+ try:
+ self._update_lock.reader_acquire()
+ if self.__precompute:
+ return
+ finally:
+ self._update_lock.reader_release()
+
+ try:
+ self._update_lock.writer_acquire()
+ if self.__precompute:
+ return
+ order = self.__order
+ assert order
+ i = 1
+ order *= 2
+ doubler = PointJacobi(
+ self.__curve, self.__x, self.__y, self.__z, order
+ )
+ order *= 2
+ self.__precompute.append((doubler.x(), doubler.y()))
+
+ while i < order:
+ i *= 2
+ doubler = doubler.double().scale()
+ self.__precompute.append((doubler.x(), doubler.y()))
+
+ finally:
+ self._update_lock.writer_release()
+
+ def __getstate__(self):
+ try:
+ self._update_lock.reader_acquire()
+ state = self.__dict__.copy()
+ finally:
+ self._update_lock.reader_release()
+ del state["_update_lock"]
+ return state
+
+ def __setstate__(self, state):
+ self.__dict__.update(state)
+ self._update_lock = RWLock()
+
+ def __eq__(self, other):
+ """Compare two points with each-other."""
+ try:
+ self._update_lock.reader_acquire()
+ if other is INFINITY:
+ return not self.__y or not self.__z
+ x1, y1, z1 = self.__x, self.__y, self.__z
+ finally:
+ self._update_lock.reader_release()
+ if isinstance(other, Point):
+ x2, y2, z2 = other.x(), other.y(), 1
+ elif isinstance(other, PointJacobi):
+ try:
+ other._update_lock.reader_acquire()
+ x2, y2, z2 = other.__x, other.__y, other.__z
+ finally:
+ other._update_lock.reader_release()
+ else:
+ return NotImplemented
+ if self.__curve != other.curve():
+ return False
+ p = self.__curve.p()
+
+ zz1 = z1 * z1 % p
+ zz2 = z2 * z2 % p
+
+ # compare the fractions by bringing them to the same denominator
+ # depend on short-circuit to save 4 multiplications in case of
+ # inequality
+ return (x1 * zz2 - x2 * zz1) % p == 0 and (
+ y1 * zz2 * z2 - y2 * zz1 * z1
+ ) % p == 0
+
+ def order(self):
+ """Return the order of the point.
+
+ None if it is undefined.
+ """
+ return self.__order
+
+ def curve(self):
+ """Return curve over which the point is defined."""
+ return self.__curve
+
+ def x(self):
+ """
+ Return affine x coordinate.
+
+ This method should be used only when the 'y' coordinate is not needed.
+ It's computationally more efficient to use `to_affine()` and then
+ call x() and y() on the returned instance. Or call `scale()`
+ and then x() and y() on the returned instance.
+ """
+ try:
+ self._update_lock.reader_acquire()
+ if self.__z == 1:
+ return self.__x
+ x = self.__x
+ z = self.__z
+ finally:
+ self._update_lock.reader_release()
+ p = self.__curve.p()
+ z = numbertheory.inverse_mod(z, p)
+ return x * z ** 2 % p
+
+ def y(self):
+ """
+ Return affine y coordinate.
+
+ This method should be used only when the 'x' coordinate is not needed.
+ It's computationally more efficient to use `to_affine()` and then
+ call x() and y() on the returned instance. Or call `scale()`
+ and then x() and y() on the returned instance.
+ """
+ try:
+ self._update_lock.reader_acquire()
+ if self.__z == 1:
+ return self.__y
+ y = self.__y
+ z = self.__z
+ finally:
+ self._update_lock.reader_release()
+ p = self.__curve.p()
+ z = numbertheory.inverse_mod(z, p)
+ return y * z ** 3 % p
+
+ def scale(self):
+ """
+ Return point scaled so that z == 1.
+
+ Modifies point in place, returns self.
+ """
+ try:
+ self._update_lock.reader_acquire()
+ if self.__z == 1:
+ return self
+ finally:
+ self._update_lock.reader_release()
+
+ try:
+ self._update_lock.writer_acquire()
+ # scaling already scaled point is safe (as inverse of 1 is 1) and
+ # quick so we don't need to optimise for the unlikely event when
+ # two threads hit the lock at the same time
+ p = self.__curve.p()
+ z_inv = numbertheory.inverse_mod(self.__z, p)
+ zz_inv = z_inv * z_inv % p
+ self.__x = self.__x * zz_inv % p
+ self.__y = self.__y * zz_inv * z_inv % p
+ # we are setting the z last so that the check above will return
+ # true only after all values were already updated
+ self.__z = 1
+ finally:
+ self._update_lock.writer_release()
+ return self
+
+ def to_affine(self):
+ """Return point in affine form."""
+ if not self.__y or not self.__z:
+ return INFINITY
+ self.scale()
+ # after point is scaled, it's immutable, so no need to perform locking
+ return Point(self.__curve, self.__x, self.__y, self.__order)
+
+ @staticmethod
+ def from_affine(point, generator=False):
+ """Create from an affine point.
+
+ :param bool generator: set to True to make the point to precalculate
+ multiplication table - useful for public point when verifying many
+ signatures (around 100 or so) or for generator points of a curve.
+ """
+ return PointJacobi(
+ point.curve(), point.x(), point.y(), 1, point.order(), generator
+ )
+
+ # plese note that all the methods that use the equations from hyperelliptic
+ # are formatted in a way to maximise performance.
+ # Things that make code faster: multiplying instead of taking to the power
+ # (`xx = x * x; xxxx = xx * xx % p` is faster than `xxxx = x**4 % p` and
+ # `pow(x, 4, p)`),
+ # multiple assignments at the same time (`x1, x2 = self.x1, self.x2` is
+ # faster than `x1 = self.x1; x2 = self.x2`),
+ # similarly, sometimes the `% p` is skipped if it makes the calculation
+ # faster and the result of calculation is later reduced modulo `p`
+
+ def _double_with_z_1(self, X1, Y1, p, a):
+ """Add a point to itself with z == 1."""
+ # after:
+ # http://hyperelliptic.org/EFD/g1p/auto-shortw-jacobian.html#doubling-mdbl-2007-bl
+ XX, YY = X1 * X1 % p, Y1 * Y1 % p
+ if not YY:
+ return 0, 0, 1
+ YYYY = YY * YY % p
+ S = 2 * ((X1 + YY) ** 2 - XX - YYYY) % p
+ M = 3 * XX + a
+ T = (M * M - 2 * S) % p
+ # X3 = T
+ Y3 = (M * (S - T) - 8 * YYYY) % p
+ Z3 = 2 * Y1 % p
+ return T, Y3, Z3
+
+ def _double(self, X1, Y1, Z1, p, a):
+ """Add a point to itself, arbitrary z."""
+ if Z1 == 1:
+ return self._double_with_z_1(X1, Y1, p, a)
+ if not Z1:
+ return 0, 0, 1
+ # after:
+ # http://hyperelliptic.org/EFD/g1p/auto-shortw-jacobian.html#doubling-dbl-2007-bl
+ XX, YY = X1 * X1 % p, Y1 * Y1 % p
+ if not YY:
+ return 0, 0, 1
+ YYYY = YY * YY % p
+ ZZ = Z1 * Z1 % p
+ S = 2 * ((X1 + YY) ** 2 - XX - YYYY) % p
+ M = (3 * XX + a * ZZ * ZZ) % p
+ T = (M * M - 2 * S) % p
+ # X3 = T
+ Y3 = (M * (S - T) - 8 * YYYY) % p
+ Z3 = ((Y1 + Z1) ** 2 - YY - ZZ) % p
+
+ return T, Y3, Z3
+
+ def double(self):
+ """Add a point to itself."""
+ if not self.__y:
+ return INFINITY
+
+ p, a = self.__curve.p(), self.__curve.a()
+
+ try:
+ self._update_lock.reader_acquire()
+ X1, Y1, Z1 = self.__x, self.__y, self.__z
+ finally:
+ self._update_lock.reader_release()
+
+ X3, Y3, Z3 = self._double(X1, Y1, Z1, p, a)
+
+ if not Y3 or not Z3:
+ return INFINITY
+ return PointJacobi(self.__curve, X3, Y3, Z3, self.__order)
+
+ def _add_with_z_1(self, X1, Y1, X2, Y2, p):
+ """add points when both Z1 and Z2 equal 1"""
+ # after:
+ # http://hyperelliptic.org/EFD/g1p/auto-shortw-jacobian.html#addition-mmadd-2007-bl
+ H = X2 - X1
+ HH = H * H
+ I = 4 * HH % p
+ J = H * I
+ r = 2 * (Y2 - Y1)
+ if not H and not r:
+ return self._double_with_z_1(X1, Y1, p, self.__curve.a())
+ V = X1 * I
+ X3 = (r ** 2 - J - 2 * V) % p
+ Y3 = (r * (V - X3) - 2 * Y1 * J) % p
+ Z3 = 2 * H % p
+ return X3, Y3, Z3
+
+ def _add_with_z_eq(self, X1, Y1, Z1, X2, Y2, p):
+ """add points when Z1 == Z2"""
+ # after:
+ # http://hyperelliptic.org/EFD/g1p/auto-shortw-jacobian.html#addition-zadd-2007-m
+ A = (X2 - X1) ** 2 % p
+ B = X1 * A % p
+ C = X2 * A
+ D = (Y2 - Y1) ** 2 % p
+ if not A and not D:
+ return self._double(X1, Y1, Z1, p, self.__curve.a())
+ X3 = (D - B - C) % p
+ Y3 = ((Y2 - Y1) * (B - X3) - Y1 * (C - B)) % p
+ Z3 = Z1 * (X2 - X1) % p
+ return X3, Y3, Z3
+
+ def _add_with_z2_1(self, X1, Y1, Z1, X2, Y2, p):
+ """add points when Z2 == 1"""
+ # after:
+ # http://hyperelliptic.org/EFD/g1p/auto-shortw-jacobian.html#addition-madd-2007-bl
+ Z1Z1 = Z1 * Z1 % p
+ U2, S2 = X2 * Z1Z1 % p, Y2 * Z1 * Z1Z1 % p
+ H = (U2 - X1) % p
+ HH = H * H % p
+ I = 4 * HH % p
+ J = H * I
+ r = 2 * (S2 - Y1) % p
+ if not r and not H:
+ return self._double_with_z_1(X2, Y2, p, self.__curve.a())
+ V = X1 * I
+ X3 = (r * r - J - 2 * V) % p
+ Y3 = (r * (V - X3) - 2 * Y1 * J) % p
+ Z3 = ((Z1 + H) ** 2 - Z1Z1 - HH) % p
+ return X3, Y3, Z3
+
+ def _add_with_z_ne(self, X1, Y1, Z1, X2, Y2, Z2, p):
+ """add points with arbitrary z"""
+ # after:
+ # http://hyperelliptic.org/EFD/g1p/auto-shortw-jacobian.html#addition-add-2007-bl
+ Z1Z1 = Z1 * Z1 % p
+ Z2Z2 = Z2 * Z2 % p
+ U1 = X1 * Z2Z2 % p
+ U2 = X2 * Z1Z1 % p
+ S1 = Y1 * Z2 * Z2Z2 % p
+ S2 = Y2 * Z1 * Z1Z1 % p
+ H = U2 - U1
+ I = 4 * H * H % p
+ J = H * I % p
+ r = 2 * (S2 - S1) % p
+ if not H and not r:
+ return self._double(X1, Y1, Z1, p, self.__curve.a())
+ V = U1 * I
+ X3 = (r * r - J - 2 * V) % p
+ Y3 = (r * (V - X3) - 2 * S1 * J) % p
+ Z3 = ((Z1 + Z2) ** 2 - Z1Z1 - Z2Z2) * H % p
+
+ return X3, Y3, Z3
+
+ def __radd__(self, other):
+ """Add other to self."""
+ return self + other
+
+ def _add(self, X1, Y1, Z1, X2, Y2, Z2, p):
+ """add two points, select fastest method."""
+ if not Y1 or not Z1:
+ return X2, Y2, Z2
+ if not Y2 or not Z2:
+ return X1, Y1, Z1
+ if Z1 == Z2:
+ if Z1 == 1:
+ return self._add_with_z_1(X1, Y1, X2, Y2, p)
+ return self._add_with_z_eq(X1, Y1, Z1, X2, Y2, p)
+ if Z1 == 1:
+ return self._add_with_z2_1(X2, Y2, Z2, X1, Y1, p)
+ if Z2 == 1:
+ return self._add_with_z2_1(X1, Y1, Z1, X2, Y2, p)
+ return self._add_with_z_ne(X1, Y1, Z1, X2, Y2, Z2, p)
+
+ def __add__(self, other):
+ """Add two points on elliptic curve."""
+ if self == INFINITY:
+ return other
+ if other == INFINITY:
+ return self
+ if isinstance(other, Point):
+ other = PointJacobi.from_affine(other)
+ if self.__curve != other.__curve:
+ raise ValueError("The other point is on different curve")
+
+ p = self.__curve.p()
+ try:
+ self._update_lock.reader_acquire()
+ X1, Y1, Z1 = self.__x, self.__y, self.__z
+ finally:
+ self._update_lock.reader_release()
+ try:
+ other._update_lock.reader_acquire()
+ X2, Y2, Z2 = other.__x, other.__y, other.__z
+ finally:
+ other._update_lock.reader_release()
+ X3, Y3, Z3 = self._add(X1, Y1, Z1, X2, Y2, Z2, p)
+
+ if not Y3 or not Z3:
+ return INFINITY
+ return PointJacobi(self.__curve, X3, Y3, Z3, self.__order)
+
+ def __rmul__(self, other):
+ """Multiply point by an integer."""
+ return self * other
+
+ def _mul_precompute(self, other):
+ """Multiply point by integer with precomputation table."""
+ X3, Y3, Z3, p = 0, 0, 1, self.__curve.p()
+ _add = self._add
+ for X2, Y2 in self.__precompute:
+ if other % 2:
+ if other % 4 >= 2:
+ other = (other + 1) // 2
+ X3, Y3, Z3 = _add(X3, Y3, Z3, X2, -Y2, 1, p)
+ else:
+ other = (other - 1) // 2
+ X3, Y3, Z3 = _add(X3, Y3, Z3, X2, Y2, 1, p)
+ else:
+ other //= 2
+
+ if not Y3 or not Z3:
+ return INFINITY
+ return PointJacobi(self.__curve, X3, Y3, Z3, self.__order)
+
+ @staticmethod
+ def _naf(mult):
+ """Calculate non-adjacent form of number."""
+ ret = []
+ while mult:
+ if mult % 2:
+ nd = mult % 4
+ if nd >= 2:
+ nd = nd - 4
+ ret += [nd]
+ mult -= nd
+ else:
+ ret += [0]
+ mult //= 2
+ return ret
+
+ def __mul__(self, other):
+ """Multiply point by an integer."""
+ if not self.__y or not other:
+ return INFINITY
+ if other == 1:
+ return self
+ if self.__order:
+ # order*2 as a protection for Minerva
+ other = other % (self.__order * 2)
+ self._maybe_precompute()
+ if self.__precompute:
+ return self._mul_precompute(other)
+
+ self = self.scale()
+ # once scaled, point is immutable, not need to lock
+ X2, Y2 = self.__x, self.__y
+ X3, Y3, Z3 = 0, 0, 1
+ p, a = self.__curve.p(), self.__curve.a()
+ _double = self._double
+ _add = self._add
+ # since adding points when at least one of them is scaled
+ # is quicker, reverse the NAF order
+ for i in reversed(self._naf(other)):
+ X3, Y3, Z3 = _double(X3, Y3, Z3, p, a)
+ if i < 0:
+ X3, Y3, Z3 = _add(X3, Y3, Z3, X2, -Y2, 1, p)
+ elif i > 0:
+ X3, Y3, Z3 = _add(X3, Y3, Z3, X2, Y2, 1, p)
+
+ if not Y3 or not Z3:
+ return INFINITY
+
+ return PointJacobi(self.__curve, X3, Y3, Z3, self.__order)
+
+ @staticmethod
+ def _leftmost_bit(x):
+ """Return integer with the same magnitude as x but only one bit set"""
+ assert x > 0
+ result = 1
+ while result <= x:
+ result = 2 * result
+ return result // 2
+
+ def mul_add(self, self_mul, other, other_mul):
+ """
+ Do two multiplications at the same time, add results.
+
+ calculates self*self_mul + other*other_mul
+ """
+ if other is INFINITY or other_mul == 0:
+ return self * self_mul
+ if self_mul == 0:
+ return other * other_mul
+ if not isinstance(other, PointJacobi):
+ other = PointJacobi.from_affine(other)
+ # when the points have precomputed answers, then multiplying them alone
+ # is faster (as it uses NAF)
+ self._maybe_precompute()
+ other._maybe_precompute()
+ if self.__precompute and other.__precompute:
+ return self * self_mul + other * other_mul
+
+ if self.__order:
+ self_mul = self_mul % self.__order
+ other_mul = other_mul % self.__order
+
+ i = self._leftmost_bit(max(self_mul, other_mul)) * 2
+ X3, Y3, Z3 = 0, 0, 1
+ p, a = self.__curve.p(), self.__curve.a()
+ self = self.scale()
+ # after scaling, point is immutable, no need for locking
+ X1, Y1 = self.__x, self.__y
+ other = other.scale()
+ X2, Y2 = other.__x, other.__y
+ both = self + other
+ if both is INFINITY:
+ X4, Y4 = 0, 0
+ else:
+ both.scale()
+ X4, Y4 = both.__x, both.__y
+ _double = self._double
+ _add = self._add
+ while i > 1:
+ X3, Y3, Z3 = _double(X3, Y3, Z3, p, a)
+ i = i // 2
+
+ if self_mul & i and other_mul & i:
+ X3, Y3, Z3 = _add(X3, Y3, Z3, X4, Y4, 1, p)
+ elif self_mul & i:
+ X3, Y3, Z3 = _add(X3, Y3, Z3, X1, Y1, 1, p)
+ elif other_mul & i:
+ X3, Y3, Z3 = _add(X3, Y3, Z3, X2, Y2, 1, p)
+
+ if not Y3 or not Z3:
+ return INFINITY
+
+ return PointJacobi(self.__curve, X3, Y3, Z3, self.__order)
+
+ def __neg__(self):
+ """Return negated point."""
+ try:
+ self._update_lock.reader_acquire()
+ return PointJacobi(
+ self.__curve, self.__x, -self.__y, self.__z, self.__order
+ )
+ finally:
+ self._update_lock.reader_release()
+
+
+class Point(object):
+ """A point on an elliptic curve. Altering x and y is forbidding,
+ but they can be read by the x() and y() methods."""
+
+ def __init__(self, curve, x, y, order=None):
+ """curve, x, y, order; order (optional) is the order of this point."""
+ self.__curve = curve
+ if GMPY:
+ self.__x = x and mpz(x)
+ self.__y = y and mpz(y)
+ self.__order = order and mpz(order)
+ else:
+ self.__x = x
+ self.__y = y
+ self.__order = order
+ # self.curve is allowed to be None only for INFINITY:
+ if self.__curve:
+ assert self.__curve.contains_point(x, y)
+ # for curves with cofactor 1, all points that are on the curve are
+ # scalar multiples of the base point, so performing multiplication is
+ # not necessary to verify that. See Section 3.2.2.1 of SEC 1 v2
+ if curve and curve.cofactor() != 1 and order:
+ assert self * order == INFINITY
+
+ def __eq__(self, other):
+ """Return True if the points are identical, False otherwise."""
+ if isinstance(other, Point):
+ return (
+ self.__curve == other.__curve
+ and self.__x == other.__x
+ and self.__y == other.__y
+ )
+ return NotImplemented
+
+ def __neg__(self):
+ return Point(self.__curve, self.__x, self.__curve.p() - self.__y)
+
+ def __add__(self, other):
+ """Add one point to another point."""
+
+ # X9.62 B.3:
+
+ if not isinstance(other, Point):
+ return NotImplemented
+ if other == INFINITY:
+ return self
+ if self == INFINITY:
+ return other
+ assert self.__curve == other.__curve
+ if self.__x == other.__x:
+ if (self.__y + other.__y) % self.__curve.p() == 0:
+ return INFINITY
+ else:
+ return self.double()
+
+ p = self.__curve.p()
+
+ l = (
+ (other.__y - self.__y)
+ * numbertheory.inverse_mod(other.__x - self.__x, p)
+ ) % p
+
+ x3 = (l * l - self.__x - other.__x) % p
+ y3 = (l * (self.__x - x3) - self.__y) % p
+
+ return Point(self.__curve, x3, y3)
+
+ def __mul__(self, other):
+ """Multiply a point by an integer."""
+
+ def leftmost_bit(x):
+ assert x > 0
+ result = 1
+ while result <= x:
+ result = 2 * result
+ return result // 2
+
+ e = other
+ if e == 0 or (self.__order and e % self.__order == 0):
+ return INFINITY
+ if self == INFINITY:
+ return INFINITY
+ if e < 0:
+ return (-self) * (-e)
+
+ # From X9.62 D.3.2:
+
+ e3 = 3 * e
+ negative_self = Point(self.__curve, self.__x, -self.__y, self.__order)
+ i = leftmost_bit(e3) // 2
+ result = self
+ # print_("Multiplying %s by %d (e3 = %d):" % (self, other, e3))
+ while i > 1:
+ result = result.double()
+ if (e3 & i) != 0 and (e & i) == 0:
+ result = result + self
+ if (e3 & i) == 0 and (e & i) != 0:
+ result = result + negative_self
+ # print_(". . . i = %d, result = %s" % ( i, result ))
+ i = i // 2
+
+ return result
+
+ def __rmul__(self, other):
+ """Multiply a point by an integer."""
+
+ return self * other
+
+ def __str__(self):
+ if self == INFINITY:
+ return "infinity"
+ return "(%d,%d)" % (self.__x, self.__y)
+
+ def double(self):
+ """Return a new point that is twice the old."""
+
+ if self == INFINITY:
+ return INFINITY
+
+ # X9.62 B.3:
+
+ p = self.__curve.p()
+ a = self.__curve.a()
+
+ l = (
+ (3 * self.__x * self.__x + a)
+ * numbertheory.inverse_mod(2 * self.__y, p)
+ ) % p
+
+ x3 = (l * l - 2 * self.__x) % p
+ y3 = (l * (self.__x - x3) - self.__y) % p
+
+ return Point(self.__curve, x3, y3)
+
+ def x(self):
+ return self.__x
+
+ def y(self):
+ return self.__y
+
+ def curve(self):
+ return self.__curve
+
+ def order(self):
+ return self.__order
+
+
+# This one point is the Point At Infinity for all purposes:
+INFINITY = Point(None, None, None)
diff --git a/frozen_deps/ecdsa/keys.py b/frozen_deps/ecdsa/keys.py
new file mode 100644
index 0000000..a6fc13f
--- /dev/null
+++ b/frozen_deps/ecdsa/keys.py
@@ -0,0 +1,1453 @@
+"""
+Primary classes for performing signing and verification operations.
+
+.. glossary::
+
+ raw encoding
+ Conversion of public, private keys and signatures (which in
+ mathematical sense are integers or pairs of integers) to strings of
+ bytes that does not use any special tags or encoding rules.
+ For any given curve, all keys of the same type or signatures will be
+ encoded to byte strings of the same length. In more formal sense,
+ the integers are encoded as big-endian, constant length byte strings,
+ where the string length is determined by the curve order (e.g.
+ for NIST256p the order is 256 bits long, so the private key will be 32
+ bytes long while public key will be 64 bytes long). The encoding of a
+ single integer is zero-padded on the left if the numerical value is
+ low. In case of public keys and signatures, which are comprised of two
+ integers, the integers are simply concatenated.
+
+ uncompressed
+ The most common formatting specified in PKIX standards. Specified in
+ X9.62 and SEC1 standards. The only difference between it and
+ :term:`raw encoding` is the prepending of a 0x04 byte. Thus an
+ uncompressed NIST256p public key encoding will be 65 bytes long.
+
+ compressed
+ The public point representation that uses half of bytes of the
+ :term:`uncompressed` encoding (rounded up). It uses the first byte of
+ the encoding to specify the sign of the y coordinate and encodes the
+ x coordinate as-is. The first byte of the encoding is equal to
+ 0x02 or 0x03. Compressed encoding of NIST256p public key will be 33
+ bytes long.
+
+ hybrid
+ A combination of :term:`uncompressed` and :term:`compressed` encodings.
+ Both x and y coordinates are stored just as in :term:`compressed`
+ encoding, but the first byte reflects the sign of the y coordinate. The
+ first byte of the encoding will be equal to 0x06 or 0x7. Hybrid
+ encoding of NIST256p public key will be 65 bytes long.
+
+ PEM
+ The acronym stands for Privacy Enhanced Email, but currently it is used
+ primarily as the way to encode :term:`DER` objects into text that can
+ be either easily copy-pasted or transferred over email.
+ It uses headers like ``-----BEGIN <type of contents>-----`` and footers
+ like ``-----END <type of contents>-----`` to separate multiple
+ types of objects in the same file or the object from the surrounding
+ comments. The actual object stored is base64 encoded.
+
+ DER
+ Distinguished Encoding Rules, the way to encode :term:`ASN.1` objects
+ deterministically and uniquely into byte strings.
+
+ ASN.1
+ Abstract Syntax Notation 1 is a standard description language for
+ specifying serialisation and deserialisation of data structures in a
+ portable and cross-platform way.
+
+ bytes-like object
+ All the types that implement the buffer protocol. That includes
+ ``str`` (only on python2), ``bytes``, ``bytesarray``, ``array.array`
+ and ``memoryview`` of those objects.
+ Please note that ``array.array` serialisation (converting it to byte
+ string) is endianess dependant! Signature computed over ``array.array``
+ of integers on a big-endian system will not be verified on a
+ little-endian system and vice-versa.
+"""
+
+import binascii
+from hashlib import sha1
+from six import PY2, b
+from . import ecdsa
+from . import der
+from . import rfc6979
+from . import ellipticcurve
+from .curves import NIST192p, find_curve
+from .numbertheory import square_root_mod_prime, SquareRootError
+from .ecdsa import RSZeroError
+from .util import string_to_number, number_to_string, randrange
+from .util import sigencode_string, sigdecode_string, bit_length
+from .util import (
+ oid_ecPublicKey,
+ encoded_oid_ecPublicKey,
+ oid_ecDH,
+ oid_ecMQV,
+ MalformedSignature,
+)
+from ._compat import normalise_bytes
+
+
+__all__ = [
+ "BadSignatureError",
+ "BadDigestError",
+ "VerifyingKey",
+ "SigningKey",
+ "MalformedPointError",
+]
+
+
+class BadSignatureError(Exception):
+ """
+ Raised when verification of signature failed.
+
+ Will be raised irrespective of reason of the failure:
+
+ * the calculated or provided hash does not match the signature
+ * the signature does not match the curve/public key
+ * the encoding of the signature is malformed
+ * the size of the signature does not match the curve of the VerifyingKey
+ """
+
+ pass
+
+
+class BadDigestError(Exception):
+ """Raised in case the selected hash is too large for the curve."""
+
+ pass
+
+
+class MalformedPointError(AssertionError):
+ """Raised in case the encoding of private or public key is malformed."""
+
+ pass
+
+
+class VerifyingKey(object):
+ """
+ Class for handling keys that can verify signatures (public keys).
+
+ :ivar ecdsa.curves.Curve curve: The Curve over which all the cryptographic
+ operations will take place
+ :ivar default_hashfunc: the function that will be used for hashing the
+ data. Should implement the same API as hashlib.sha1
+ :vartype default_hashfunc: callable
+ :ivar pubkey: the actual public key
+ :vartype pubkey: ecdsa.ecdsa.Public_key
+ """
+
+ def __init__(self, _error__please_use_generate=None):
+ """Unsupported, please use one of the classmethods to initialise."""
+ if not _error__please_use_generate:
+ raise TypeError(
+ "Please use VerifyingKey.generate() to construct me"
+ )
+ self.curve = None
+ self.default_hashfunc = None
+ self.pubkey = None
+
+ def __repr__(self):
+ pub_key = self.to_string("compressed")
+ return "VerifyingKey.from_string({0!r}, {1!r}, {2})".format(
+ pub_key, self.curve, self.default_hashfunc().name
+ )
+
+ def __eq__(self, other):
+ """Return True if the points are identical, False otherwise."""
+ if isinstance(other, VerifyingKey):
+ return self.curve == other.curve and self.pubkey == other.pubkey
+ return NotImplemented
+
+ @classmethod
+ def from_public_point(
+ cls, point, curve=NIST192p, hashfunc=sha1, validate_point=True
+ ):
+ """
+ Initialise the object from a Point object.
+
+ This is a low-level method, generally you will not want to use it.
+
+ :param point: The point to wrap around, the actual public key
+ :type point: ecdsa.ellipticcurve.Point
+ :param curve: The curve on which the point needs to reside, defaults
+ to NIST192p
+ :type curve: ecdsa.curves.Curve
+ :param hashfunc: The default hash function that will be used for
+ verification, needs to implement the same interface
+ as hashlib.sha1
+ :type hashfunc: callable
+ :type bool validate_point: whether to check if the point lies on curve
+ should always be used if the public point is not a result
+ of our own calculation
+
+ :raises MalformedPointError: if the public point does not lie on the
+ curve
+
+ :return: Initialised VerifyingKey object
+ :rtype: VerifyingKey
+ """
+ self = cls(_error__please_use_generate=True)
+ if not isinstance(point, ellipticcurve.PointJacobi):
+ point = ellipticcurve.PointJacobi.from_affine(point)
+ self.curve = curve
+ self.default_hashfunc = hashfunc
+ try:
+ self.pubkey = ecdsa.Public_key(
+ curve.generator, point, validate_point
+ )
+ except ecdsa.InvalidPointError:
+ raise MalformedPointError("Point does not lie on the curve")
+ self.pubkey.order = curve.order
+ return self
+
+ def precompute(self, lazy=False):
+ """
+ Precompute multiplication tables for faster signature verification.
+
+ Calling this method will cause the library to precompute the
+ scalar multiplication tables, used in signature verification.
+ While it's an expensive operation (comparable to performing
+ as many signatures as the bit size of the curve, i.e. 256 for NIST256p)
+ it speeds up verification 2 times. You should call this method
+ if you expect to verify hundreds of signatures (or more) using the same
+ VerifyingKey object.
+
+ Note: You should call this method only once, this method generates a
+ new precomputation table every time it's called.
+
+ :param bool lazy: whether to calculate the precomputation table now
+ (if set to False) or if it should be delayed to the time of first
+ use (when set to True)
+ """
+ self.pubkey.point = ellipticcurve.PointJacobi.from_affine(
+ self.pubkey.point, True
+ )
+ # as precomputation in now delayed to the time of first use of the
+ # point and we were asked specifically to precompute now, make
+ # sure the precomputation is performed now to preserve the behaviour
+ if not lazy:
+ self.pubkey.point * 2
+
+ @staticmethod
+ def _from_raw_encoding(string, curve):
+ """
+ Decode public point from :term:`raw encoding`.
+
+ :term:`raw encoding` is the same as the :term:`uncompressed` encoding,
+ but without the 0x04 byte at the beginning.
+ """
+ order = curve.order
+ # real assert, from_string() should not call us with different length
+ assert len(string) == curve.verifying_key_length
+ xs = string[: curve.baselen]
+ ys = string[curve.baselen :]
+ if len(xs) != curve.baselen:
+ raise MalformedPointError("Unexpected length of encoded x")
+ if len(ys) != curve.baselen:
+ raise MalformedPointError("Unexpected length of encoded y")
+ x = string_to_number(xs)
+ y = string_to_number(ys)
+
+ return ellipticcurve.PointJacobi(curve.curve, x, y, 1, order)
+
+ @staticmethod
+ def _from_compressed(string, curve):
+ """Decode public point from compressed encoding."""
+ if string[:1] not in (b("\x02"), b("\x03")):
+ raise MalformedPointError("Malformed compressed point encoding")
+
+ is_even = string[:1] == b("\x02")
+ x = string_to_number(string[1:])
+ order = curve.order
+ p = curve.curve.p()
+ alpha = (pow(x, 3, p) + (curve.curve.a() * x) + curve.curve.b()) % p
+ try:
+ beta = square_root_mod_prime(alpha, p)
+ except SquareRootError as e:
+ raise MalformedPointError(
+ "Encoding does not correspond to a point on curve", e
+ )
+ if is_even == bool(beta & 1):
+ y = p - beta
+ else:
+ y = beta
+ return ellipticcurve.PointJacobi(curve.curve, x, y, 1, order)
+
+ @classmethod
+ def _from_hybrid(cls, string, curve, validate_point):
+ """Decode public point from hybrid encoding."""
+ # real assert, from_string() should not call us with different types
+ assert string[:1] in (b("\x06"), b("\x07"))
+
+ # primarily use the uncompressed as it's easiest to handle
+ point = cls._from_raw_encoding(string[1:], curve)
+
+ # but validate if it's self-consistent if we're asked to do that
+ if validate_point and (
+ point.y() & 1
+ and string[:1] != b("\x07")
+ or (not point.y() & 1)
+ and string[:1] != b("\x06")
+ ):
+ raise MalformedPointError("Inconsistent hybrid point encoding")
+
+ return point
+
+ @classmethod
+ def from_string(
+ cls, string, curve=NIST192p, hashfunc=sha1, validate_point=True
+ ):
+ """
+ Initialise the object from byte encoding of public key.
+
+ The method does accept and automatically detect the type of point
+ encoding used. It supports the :term:`raw encoding`,
+ :term:`uncompressed`, :term:`compressed` and :term:`hybrid` encodings.
+
+ Note, while the method is named "from_string" it's a misnomer from
+ Python 2 days when there were no binary strings. In Python 3 the
+ input needs to be a bytes-like object.
+
+ :param string: single point encoding of the public key
+ :type string: :term:`bytes-like object`
+ :param curve: the curve on which the public key is expected to lie
+ :type curve: ecdsa.curves.Curve
+ :param hashfunc: The default hash function that will be used for
+ verification, needs to implement the same interface as hashlib.sha1
+ :type hashfunc: callable
+ :param validate_point: whether to verify that the point lies on the
+ provided curve or not, defaults to True
+ :type validate_point: bool
+
+ :raises MalformedPointError: if the public point does not lie on the
+ curve or the encoding is invalid
+
+ :return: Initialised VerifyingKey object
+ :rtype: VerifyingKey
+ """
+ string = normalise_bytes(string)
+ sig_len = len(string)
+ if sig_len == curve.verifying_key_length:
+ point = cls._from_raw_encoding(string, curve)
+ elif sig_len == curve.verifying_key_length + 1:
+ if string[:1] in (b("\x06"), b("\x07")):
+ point = cls._from_hybrid(string, curve, validate_point)
+ elif string[:1] == b("\x04"):
+ point = cls._from_raw_encoding(string[1:], curve)
+ else:
+ raise MalformedPointError(
+ "Invalid X9.62 encoding of the public point"
+ )
+ elif sig_len == curve.baselen + 1:
+ point = cls._from_compressed(string, curve)
+ else:
+ raise MalformedPointError(
+ "Length of string does not match lengths of "
+ "any of the supported encodings of {0} "
+ "curve.".format(curve.name)
+ )
+ return cls.from_public_point(point, curve, hashfunc, validate_point)
+
+ @classmethod
+ def from_pem(cls, string, hashfunc=sha1):
+ """
+ Initialise from public key stored in :term:`PEM` format.
+
+ The PEM header of the key should be ``BEGIN PUBLIC KEY``.
+
+ See the :func:`~VerifyingKey.from_der()` method for details of the
+ format supported.
+
+ Note: only a single PEM object encoding is supported in provided
+ string.
+
+ :param string: text with PEM-encoded public ECDSA key
+ :type string: str
+
+ :return: Initialised VerifyingKey object
+ :rtype: VerifyingKey
+ """
+ return cls.from_der(der.unpem(string), hashfunc=hashfunc)
+
+ @classmethod
+ def from_der(cls, string, hashfunc=sha1):
+ """
+ Initialise the key stored in :term:`DER` format.
+
+ The expected format of the key is the SubjectPublicKeyInfo structure
+ from RFC5912 (for RSA keys, it's known as the PKCS#1 format)::
+
+ SubjectPublicKeyInfo {PUBLIC-KEY: IOSet} ::= SEQUENCE {
+ algorithm AlgorithmIdentifier {PUBLIC-KEY, {IOSet}},
+ subjectPublicKey BIT STRING
+ }
+
+ Note: only public EC keys are supported by this method. The
+ SubjectPublicKeyInfo.algorithm.algorithm field must specify
+ id-ecPublicKey (see RFC3279).
+
+ Only the named curve encoding is supported, thus the
+ SubjectPublicKeyInfo.algorithm.parameters field needs to be an
+ object identifier. A sequence in that field indicates an explicit
+ parameter curve encoding, this format is not supported. A NULL object
+ in that field indicates an "implicitlyCA" encoding, where the curve
+ parameters come from CA certificate, those, again, are not supported.
+
+ :param string: binary string with the DER encoding of public ECDSA key
+ :type string: bytes-like object
+
+ :return: Initialised VerifyingKey object
+ :rtype: VerifyingKey
+ """
+ string = normalise_bytes(string)
+ # [[oid_ecPublicKey,oid_curve], point_str_bitstring]
+ s1, empty = der.remove_sequence(string)
+ if empty != b"":
+ raise der.UnexpectedDER(
+ "trailing junk after DER pubkey: %s" % binascii.hexlify(empty)
+ )
+ s2, point_str_bitstring = der.remove_sequence(s1)
+ # s2 = oid_ecPublicKey,oid_curve
+ oid_pk, rest = der.remove_object(s2)
+ oid_curve, empty = der.remove_object(rest)
+ if empty != b"":
+ raise der.UnexpectedDER(
+ "trailing junk after DER pubkey objects: %s"
+ % binascii.hexlify(empty)
+ )
+ if not oid_pk == oid_ecPublicKey:
+ raise der.UnexpectedDER(
+ "Unexpected object identifier in DER "
+ "encoding: {0!r}".format(oid_pk)
+ )
+ curve = find_curve(oid_curve)
+ point_str, empty = der.remove_bitstring(point_str_bitstring, 0)
+ if empty != b"":
+ raise der.UnexpectedDER(
+ "trailing junk after pubkey pointstring: %s"
+ % binascii.hexlify(empty)
+ )
+ # raw encoding of point is invalid in DER files
+ if len(point_str) == curve.verifying_key_length:
+ raise der.UnexpectedDER("Malformed encoding of public point")
+ return cls.from_string(point_str, curve, hashfunc=hashfunc)
+
+ @classmethod
+ def from_public_key_recovery(
+ cls, signature, data, curve, hashfunc=sha1, sigdecode=sigdecode_string
+ ):
+ """
+ Return keys that can be used as verifiers of the provided signature.
+
+ Tries to recover the public key that can be used to verify the
+ signature, usually returns two keys like that.
+
+ :param signature: the byte string with the encoded signature
+ :type signature: bytes-like object
+ :param data: the data to be hashed for signature verification
+ :type data: bytes-like object
+ :param curve: the curve over which the signature was performed
+ :type curve: ecdsa.curves.Curve
+ :param hashfunc: The default hash function that will be used for
+ verification, needs to implement the same interface as hashlib.sha1
+ :type hashfunc: callable
+ :param sigdecode: Callable to define the way the signature needs to
+ be decoded to an object, needs to handle `signature` as the
+ first parameter, the curve order (an int) as the second and return
+ a tuple with two integers, "r" as the first one and "s" as the
+ second one. See :func:`ecdsa.util.sigdecode_string` and
+ :func:`ecdsa.util.sigdecode_der` for examples.
+ :type sigdecode: callable
+
+ :return: Initialised VerifyingKey objects
+ :rtype: list of VerifyingKey
+ """
+ data = normalise_bytes(data)
+ digest = hashfunc(data).digest()
+ return cls.from_public_key_recovery_with_digest(
+ signature, digest, curve, hashfunc=hashfunc, sigdecode=sigdecode
+ )
+
+ @classmethod
+ def from_public_key_recovery_with_digest(
+ cls,
+ signature,
+ digest,
+ curve,
+ hashfunc=sha1,
+ sigdecode=sigdecode_string,
+ ):
+ """
+ Return keys that can be used as verifiers of the provided signature.
+
+ Tries to recover the public key that can be used to verify the
+ signature, usually returns two keys like that.
+
+ :param signature: the byte string with the encoded signature
+ :type signature: bytes-like object
+ :param digest: the hash value of the message signed by the signature
+ :type digest: bytes-like object
+ :param curve: the curve over which the signature was performed
+ :type curve: ecdsa.curves.Curve
+ :param hashfunc: The default hash function that will be used for
+ verification, needs to implement the same interface as hashlib.sha1
+ :type hashfunc: callable
+ :param sigdecode: Callable to define the way the signature needs to
+ be decoded to an object, needs to handle `signature` as the
+ first parameter, the curve order (an int) as the second and return
+ a tuple with two integers, "r" as the first one and "s" as the
+ second one. See :func:`ecdsa.util.sigdecode_string` and
+ :func:`ecdsa.util.sigdecode_der` for examples.
+ :type sigdecode: callable
+
+
+ :return: Initialised VerifyingKey object
+ :rtype: VerifyingKey
+ """
+ generator = curve.generator
+ r, s = sigdecode(signature, generator.order())
+ sig = ecdsa.Signature(r, s)
+
+ digest = normalise_bytes(digest)
+ digest_as_number = string_to_number(digest)
+ pks = sig.recover_public_keys(digest_as_number, generator)
+
+ # Transforms the ecdsa.Public_key object into a VerifyingKey
+ verifying_keys = [
+ cls.from_public_point(pk.point, curve, hashfunc) for pk in pks
+ ]
+ return verifying_keys
+
+ def _raw_encode(self):
+ """Convert the public key to the :term:`raw encoding`."""
+ order = self.pubkey.order
+ x_str = number_to_string(self.pubkey.point.x(), order)
+ y_str = number_to_string(self.pubkey.point.y(), order)
+ return x_str + y_str
+
+ def _compressed_encode(self):
+ """Encode the public point into the compressed form."""
+ order = self.pubkey.order
+ x_str = number_to_string(self.pubkey.point.x(), order)
+ if self.pubkey.point.y() & 1:
+ return b("\x03") + x_str
+ else:
+ return b("\x02") + x_str
+
+ def _hybrid_encode(self):
+ """Encode the public point into the hybrid form."""
+ raw_enc = self._raw_encode()
+ if self.pubkey.point.y() & 1:
+ return b("\x07") + raw_enc
+ else:
+ return b("\x06") + raw_enc
+
+ def to_string(self, encoding="raw"):
+ """
+ Convert the public key to a byte string.
+
+ The method by default uses the :term:`raw encoding` (specified
+ by `encoding="raw"`. It can also output keys in :term:`uncompressed`,
+ :term:`compressed` and :term:`hybrid` formats.
+
+ Remember that the curve identification is not part of the encoding
+ so to decode the point using :func:`~VerifyingKey.from_string`, curve
+ needs to be specified.
+
+ Note: while the method is called "to_string", it's a misnomer from
+ Python 2 days when character strings and byte strings shared type.
+ On Python 3 the returned type will be `bytes`.
+
+ :return: :term:`raw encoding` of the public key (public point) on the
+ curve
+ :rtype: bytes
+ """
+ assert encoding in ("raw", "uncompressed", "compressed", "hybrid")
+ if encoding == "raw":
+ return self._raw_encode()
+ elif encoding == "uncompressed":
+ return b("\x04") + self._raw_encode()
+ elif encoding == "hybrid":
+ return self._hybrid_encode()
+ else:
+ return self._compressed_encode()
+
+ def to_pem(self, point_encoding="uncompressed"):
+ """
+ Convert the public key to the :term:`PEM` format.
+
+ The PEM header of the key will be ``BEGIN PUBLIC KEY``.
+
+ The format of the key is described in the
+ :func:`~VerifyingKey.from_der()` method.
+ This method supports only "named curve" encoding of keys.
+
+ :param str point_encoding: specification of the encoding format
+ of public keys. "uncompressed" is most portable, "compressed" is
+ smallest. "hybrid" is uncommon and unsupported by most
+ implementations, it is as big as "uncompressed".
+
+ :return: portable encoding of the public key
+ :rtype: bytes
+
+ .. warning:: The PEM is encoded to US-ASCII, it needs to be
+ re-encoded if the system is incompatible (e.g. uses UTF-16)
+ """
+ return der.topem(self.to_der(point_encoding), "PUBLIC KEY")
+
+ def to_der(self, point_encoding="uncompressed"):
+ """
+ Convert the public key to the :term:`DER` format.
+
+ The format of the key is described in the
+ :func:`~VerifyingKey.from_der()` method.
+ This method supports only "named curve" encoding of keys.
+
+ :param str point_encoding: specification of the encoding format
+ of public keys. "uncompressed" is most portable, "compressed" is
+ smallest. "hybrid" is uncommon and unsupported by most
+ implementations, it is as big as "uncompressed".
+
+ :return: DER encoding of the public key
+ :rtype: bytes
+ """
+ if point_encoding == "raw":
+ raise ValueError("raw point_encoding not allowed in DER")
+ point_str = self.to_string(point_encoding)
+ return der.encode_sequence(
+ der.encode_sequence(
+ encoded_oid_ecPublicKey, self.curve.encoded_oid
+ ),
+ # 0 is the number of unused bits in the
+ # bit string
+ der.encode_bitstring(point_str, 0),
+ )
+
+ def verify(
+ self,
+ signature,
+ data,
+ hashfunc=None,
+ sigdecode=sigdecode_string,
+ allow_truncate=True,
+ ):
+ """
+ Verify a signature made over provided data.
+
+ Will hash `data` to verify the signature.
+
+ By default expects signature in :term:`raw encoding`. Can also be used
+ to verify signatures in ASN.1 DER encoding by using
+ :func:`ecdsa.util.sigdecode_der`
+ as the `sigdecode` parameter.
+
+ :param signature: encoding of the signature
+ :type signature: sigdecode method dependant
+ :param data: data signed by the `signature`, will be hashed using
+ `hashfunc`, if specified, or default hash function
+ :type data: bytes like object
+ :param hashfunc: The default hash function that will be used for
+ verification, needs to implement the same interface as hashlib.sha1
+ :type hashfunc: callable
+ :param sigdecode: Callable to define the way the signature needs to
+ be decoded to an object, needs to handle `signature` as the
+ first parameter, the curve order (an int) as the second and return
+ a tuple with two integers, "r" as the first one and "s" as the
+ second one. See :func:`ecdsa.util.sigdecode_string` and
+ :func:`ecdsa.util.sigdecode_der` for examples.
+ :type sigdecode: callable
+ :param bool allow_truncate: if True, the provided digest can have
+ bigger bit-size than the order of the curve, the extra bits (at
+ the end of the digest) will be truncated. Use it when verifying
+ SHA-384 output using NIST256p or in similar situations. Defaults to
+ True.
+
+ :raises BadSignatureError: if the signature is invalid or malformed
+
+ :return: True if the verification was successful
+ :rtype: bool
+ """
+ # signature doesn't have to be a bytes-like-object so don't normalise
+ # it, the decoders will do that
+ data = normalise_bytes(data)
+
+ hashfunc = hashfunc or self.default_hashfunc
+ digest = hashfunc(data).digest()
+ return self.verify_digest(signature, digest, sigdecode, allow_truncate)
+
+ def verify_digest(
+ self,
+ signature,
+ digest,
+ sigdecode=sigdecode_string,
+ allow_truncate=False,
+ ):
+ """
+ Verify a signature made over provided hash value.
+
+ By default expects signature in :term:`raw encoding`. Can also be used
+ to verify signatures in ASN.1 DER encoding by using
+ :func:`ecdsa.util.sigdecode_der`
+ as the `sigdecode` parameter.
+
+ :param signature: encoding of the signature
+ :type signature: sigdecode method dependant
+ :param digest: raw hash value that the signature authenticates.
+ :type digest: bytes like object
+ :param sigdecode: Callable to define the way the signature needs to
+ be decoded to an object, needs to handle `signature` as the
+ first parameter, the curve order (an int) as the second and return
+ a tuple with two integers, "r" as the first one and "s" as the
+ second one. See :func:`ecdsa.util.sigdecode_string` and
+ :func:`ecdsa.util.sigdecode_der` for examples.
+ :type sigdecode: callable
+ :param bool allow_truncate: if True, the provided digest can have
+ bigger bit-size than the order of the curve, the extra bits (at
+ the end of the digest) will be truncated. Use it when verifying
+ SHA-384 output using NIST256p or in similar situations.
+
+ :raises BadSignatureError: if the signature is invalid or malformed
+ :raises BadDigestError: if the provided digest is too big for the curve
+ associated with this VerifyingKey and allow_truncate was not set
+
+ :return: True if the verification was successful
+ :rtype: bool
+ """
+ # signature doesn't have to be a bytes-like-object so don't normalise
+ # it, the decoders will do that
+ digest = normalise_bytes(digest)
+ if not allow_truncate and len(digest) > self.curve.baselen:
+ raise BadDigestError(
+ "this curve (%s) is too short "
+ "for your digest (%d)" % (self.curve.name, 8 * len(digest))
+ )
+ number = string_to_number(digest)
+ if allow_truncate:
+ max_length = bit_length(self.curve.order)
+ # we don't use bit_length(number) as that truncates leading zeros
+ length = len(digest) * 8
+
+ # See NIST FIPS 186-4:
+ #
+ # When the length of the output of the hash function is greater
+ # than N (i.e., the bit length of q), then the leftmost N bits of
+ # the hash function output block shall be used in any calculation
+ # using the hash function output during the generation or
+ # verification of a digital signature.
+ #
+ # as such, we need to shift-out the low-order bits:
+ number >>= max(0, length - max_length)
+
+ try:
+ r, s = sigdecode(signature, self.pubkey.order)
+ except (der.UnexpectedDER, MalformedSignature) as e:
+ raise BadSignatureError("Malformed formatting of signature", e)
+ sig = ecdsa.Signature(r, s)
+ if self.pubkey.verifies(number, sig):
+ return True
+ raise BadSignatureError("Signature verification failed")
+
+
+class SigningKey(object):
+ """
+ Class for handling keys that can create signatures (private keys).
+
+ :ivar ecdsa.curves.Curve curve: The Curve over which all the cryptographic
+ operations will take place
+ :ivar default_hashfunc: the function that will be used for hashing the
+ data. Should implement the same API as hashlib.sha1
+ :ivar int baselen: the length of a :term:`raw encoding` of private key
+ :ivar ecdsa.keys.VerifyingKey verifying_key: the public key
+ associated with this private key
+ :ivar ecdsa.ecdsa.Private_key privkey: the actual private key
+ """
+
+ def __init__(self, _error__please_use_generate=None):
+ """Unsupported, please use one of the classmethods to initialise."""
+ if not _error__please_use_generate:
+ raise TypeError("Please use SigningKey.generate() to construct me")
+ self.curve = None
+ self.default_hashfunc = None
+ self.baselen = None
+ self.verifying_key = None
+ self.privkey = None
+
+ def __eq__(self, other):
+ """Return True if the points are identical, False otherwise."""
+ if isinstance(other, SigningKey):
+ return (
+ self.curve == other.curve
+ and self.verifying_key == other.verifying_key
+ and self.privkey == other.privkey
+ )
+ return NotImplemented
+
+ @classmethod
+ def generate(cls, curve=NIST192p, entropy=None, hashfunc=sha1):
+ """
+ Generate a random private key.
+
+ :param curve: The curve on which the point needs to reside, defaults
+ to NIST192p
+ :type curve: ecdsa.curves.Curve
+ :param entropy: Source of randomness for generating the private keys,
+ should provide cryptographically secure random numbers if the keys
+ need to be secure. Uses os.urandom() by default.
+ :type entropy: callable
+ :param hashfunc: The default hash function that will be used for
+ signing, needs to implement the same interface
+ as hashlib.sha1
+ :type hashfunc: callable
+
+ :return: Initialised SigningKey object
+ :rtype: SigningKey
+ """
+ secexp = randrange(curve.order, entropy)
+ return cls.from_secret_exponent(secexp, curve, hashfunc)
+
+ @classmethod
+ def from_secret_exponent(cls, secexp, curve=NIST192p, hashfunc=sha1):
+ """
+ Create a private key from a random integer.
+
+ Note: it's a low level method, it's recommended to use the
+ :func:`~SigningKey.generate` method to create private keys.
+
+ :param int secexp: secret multiplier (the actual private key in ECDSA).
+ Needs to be an integer between 1 and the curve order.
+ :param curve: The curve on which the point needs to reside
+ :type curve: ecdsa.curves.Curve
+ :param hashfunc: The default hash function that will be used for
+ signing, needs to implement the same interface
+ as hashlib.sha1
+ :type hashfunc: callable
+
+ :raises MalformedPointError: when the provided secexp is too large
+ or too small for the curve selected
+ :raises RuntimeError: if the generation of public key from private
+ key failed
+
+ :return: Initialised SigningKey object
+ :rtype: SigningKey
+ """
+ self = cls(_error__please_use_generate=True)
+ self.curve = curve
+ self.default_hashfunc = hashfunc
+ self.baselen = curve.baselen
+ n = curve.order
+ if not 1 <= secexp < n:
+ raise MalformedPointError(
+ "Invalid value for secexp, expected integer "
+ "between 1 and {0}".format(n)
+ )
+ pubkey_point = curve.generator * secexp
+ if hasattr(pubkey_point, "scale"):
+ pubkey_point = pubkey_point.scale()
+ self.verifying_key = VerifyingKey.from_public_point(
+ pubkey_point, curve, hashfunc, False
+ )
+ pubkey = self.verifying_key.pubkey
+ self.privkey = ecdsa.Private_key(pubkey, secexp)
+ self.privkey.order = n
+ return self
+
+ @classmethod
+ def from_string(cls, string, curve=NIST192p, hashfunc=sha1):
+ """
+ Decode the private key from :term:`raw encoding`.
+
+ Note: the name of this method is a misnomer coming from days of
+ Python 2, when binary strings and character strings shared a type.
+ In Python 3, the expected type is `bytes`.
+
+ :param string: the raw encoding of the private key
+ :type string: bytes like object
+ :param curve: The curve on which the point needs to reside
+ :type curve: ecdsa.curves.Curve
+ :param hashfunc: The default hash function that will be used for
+ signing, needs to implement the same interface
+ as hashlib.sha1
+ :type hashfunc: callable
+
+ :raises MalformedPointError: if the length of encoding doesn't match
+ the provided curve or the encoded values is too large
+ :raises RuntimeError: if the generation of public key from private
+ key failed
+
+ :return: Initialised SigningKey object
+ :rtype: SigningKey
+ """
+ string = normalise_bytes(string)
+ if len(string) != curve.baselen:
+ raise MalformedPointError(
+ "Invalid length of private key, received {0}, "
+ "expected {1}".format(len(string), curve.baselen)
+ )
+ secexp = string_to_number(string)
+ return cls.from_secret_exponent(secexp, curve, hashfunc)
+
+ @classmethod
+ def from_pem(cls, string, hashfunc=sha1):
+ """
+ Initialise from key stored in :term:`PEM` format.
+
+ The PEM formats supported are the un-encrypted RFC5915
+ (the ssleay format) supported by OpenSSL, and the more common
+ un-encrypted RFC5958 (the PKCS #8 format).
+
+ The legacy format files have the header with the string
+ ``BEGIN EC PRIVATE KEY``.
+ PKCS#8 files have the header ``BEGIN PRIVATE KEY``.
+ Encrypted files (ones that include the string
+ ``Proc-Type: 4,ENCRYPTED``
+ right after the PEM header) are not supported.
+
+ See :func:`~SigningKey.from_der` for ASN.1 syntax of the objects in
+ this files.
+
+ :param string: text with PEM-encoded private ECDSA key
+ :type string: str
+
+ :raises MalformedPointError: if the length of encoding doesn't match
+ the provided curve or the encoded values is too large
+ :raises RuntimeError: if the generation of public key from private
+ key failed
+ :raises UnexpectedDER: if the encoding of the PEM file is incorrect
+
+ :return: Initialised SigningKey object
+ :rtype: SigningKey
+ """
+ if not PY2 and isinstance(string, str):
+ string = string.encode()
+
+ # The privkey pem may have multiple sections, commonly it also has
+ # "EC PARAMETERS", we need just "EC PRIVATE KEY". PKCS#8 should not
+ # have the "EC PARAMETERS" section; it's just "PRIVATE KEY".
+ private_key_index = string.find(b"-----BEGIN EC PRIVATE KEY-----")
+ if private_key_index == -1:
+ private_key_index = string.index(b"-----BEGIN PRIVATE KEY-----")
+
+ return cls.from_der(der.unpem(string[private_key_index:]), hashfunc)
+
+ @classmethod
+ def from_der(cls, string, hashfunc=sha1):
+ """
+ Initialise from key stored in :term:`DER` format.
+
+ The DER formats supported are the un-encrypted RFC5915
+ (the ssleay format) supported by OpenSSL, and the more common
+ un-encrypted RFC5958 (the PKCS #8 format).
+
+ Both formats contain an ASN.1 object following the syntax specified
+ in RFC5915::
+
+ ECPrivateKey ::= SEQUENCE {
+ version INTEGER { ecPrivkeyVer1(1) }} (ecPrivkeyVer1),
+ privateKey OCTET STRING,
+ parameters [0] ECParameters {{ NamedCurve }} OPTIONAL,
+ publicKey [1] BIT STRING OPTIONAL
+ }
+
+ `publicKey` field is ignored completely (errors, if any, in it will
+ be undetected).
+
+ The only format supported for the `parameters` field is the named
+ curve method. Explicit encoding of curve parameters is not supported.
+ In the legacy ssleay format, this implementation requires the optional
+ `parameters` field to get the curve name. In PKCS #8 format, the curve
+ is part of the PrivateKeyAlgorithmIdentifier.
+
+ The PKCS #8 format includes an ECPrivateKey object as the `privateKey`
+ field within a larger structure:
+
+ OneAsymmetricKey ::= SEQUENCE {
+ version Version,
+ privateKeyAlgorithm PrivateKeyAlgorithmIdentifier,
+ privateKey PrivateKey,
+ attributes [0] Attributes OPTIONAL,
+ ...,
+ [[2: publicKey [1] PublicKey OPTIONAL ]],
+ ...
+ }
+
+ The `attributes` and `publicKey` fields are completely ignored; errors
+ in them will not be detected.
+
+ :param string: binary string with DER-encoded private ECDSA key
+ :type string: bytes like object
+
+ :raises MalformedPointError: if the length of encoding doesn't match
+ the provided curve or the encoded values is too large
+ :raises RuntimeError: if the generation of public key from private
+ key failed
+ :raises UnexpectedDER: if the encoding of the DER file is incorrect
+
+ :return: Initialised SigningKey object
+ :rtype: SigningKey
+ """
+ s = normalise_bytes(string)
+ curve = None
+
+ s, empty = der.remove_sequence(s)
+ if empty != b(""):
+ raise der.UnexpectedDER(
+ "trailing junk after DER privkey: %s" % binascii.hexlify(empty)
+ )
+
+ version, s = der.remove_integer(s)
+
+ # At this point, PKCS #8 has a sequence containing the algorithm
+ # identifier and the curve identifier. The ssleay format instead has
+ # an octet string containing the key data, so this is how we can
+ # distinguish the two formats.
+ if der.is_sequence(s):
+ if version not in (0, 1):
+ raise der.UnexpectedDER(
+ "expected version '0' or '1' at start of privkey, got %d"
+ % version
+ )
+
+ sequence, s = der.remove_sequence(s)
+ algorithm_oid, algorithm_identifier = der.remove_object(sequence)
+ curve_oid, empty = der.remove_object(algorithm_identifier)
+ curve = find_curve(curve_oid)
+
+ if algorithm_oid not in (oid_ecPublicKey, oid_ecDH, oid_ecMQV):
+ raise der.UnexpectedDER(
+ "unexpected algorithm identifier '%s'" % (algorithm_oid,)
+ )
+ if empty != b"":
+ raise der.UnexpectedDER(
+ "unexpected data after algorithm identifier: %s"
+ % binascii.hexlify(empty)
+ )
+
+ # Up next is an octet string containing an ECPrivateKey. Ignore
+ # the optional "attributes" and "publicKey" fields that come after.
+ s, _ = der.remove_octet_string(s)
+
+ # Unpack the ECPrivateKey to get to the key data octet string,
+ # and rejoin the ssleay parsing path.
+ s, empty = der.remove_sequence(s)
+ if empty != b(""):
+ raise der.UnexpectedDER(
+ "trailing junk after DER privkey: %s"
+ % binascii.hexlify(empty)
+ )
+
+ version, s = der.remove_integer(s)
+
+ # The version of the ECPrivateKey must be 1.
+ if version != 1:
+ raise der.UnexpectedDER(
+ "expected version '1' at start of DER privkey, got %d"
+ % version
+ )
+
+ privkey_str, s = der.remove_octet_string(s)
+
+ if not curve:
+ tag, curve_oid_str, s = der.remove_constructed(s)
+ if tag != 0:
+ raise der.UnexpectedDER(
+ "expected tag 0 in DER privkey, got %d" % tag
+ )
+ curve_oid, empty = der.remove_object(curve_oid_str)
+ if empty != b(""):
+ raise der.UnexpectedDER(
+ "trailing junk after DER privkey "
+ "curve_oid: %s" % binascii.hexlify(empty)
+ )
+ curve = find_curve(curve_oid)
+
+ # we don't actually care about the following fields
+ #
+ # tag, pubkey_bitstring, s = der.remove_constructed(s)
+ # if tag != 1:
+ # raise der.UnexpectedDER("expected tag 1 in DER privkey, got %d"
+ # % tag)
+ # pubkey_str = der.remove_bitstring(pubkey_bitstring, 0)
+ # if empty != "":
+ # raise der.UnexpectedDER("trailing junk after DER privkey "
+ # "pubkeystr: %s"
+ # % binascii.hexlify(empty))
+
+ # our from_string method likes fixed-length privkey strings
+ if len(privkey_str) < curve.baselen:
+ privkey_str = (
+ b("\x00") * (curve.baselen - len(privkey_str)) + privkey_str
+ )
+ return cls.from_string(privkey_str, curve, hashfunc)
+
+ def to_string(self):
+ """
+ Convert the private key to :term:`raw encoding`.
+
+ Note: while the method is named "to_string", its name comes from
+ Python 2 days, when binary and character strings used the same type.
+ The type used in Python 3 is `bytes`.
+
+ :return: raw encoding of private key
+ :rtype: bytes
+ """
+ secexp = self.privkey.secret_multiplier
+ s = number_to_string(secexp, self.privkey.order)
+ return s
+
+ def to_pem(self, point_encoding="uncompressed", format="ssleay"):
+ """
+ Convert the private key to the :term:`PEM` format.
+
+ See :func:`~SigningKey.from_pem` method for format description.
+
+ Only the named curve format is supported.
+ The public key will be included in generated string.
+
+ The PEM header will specify ``BEGIN EC PRIVATE KEY`` or
+ ``BEGIN PRIVATE KEY``, depending on the desired format.
+
+ :param str point_encoding: format to use for encoding public point
+ :param str format: either ``ssleay`` (default) or ``pkcs8``
+
+ :return: PEM encoded private key
+ :rtype: bytes
+
+ .. warning:: The PEM is encoded to US-ASCII, it needs to be
+ re-encoded if the system is incompatible (e.g. uses UTF-16)
+ """
+ # TODO: "BEGIN ECPARAMETERS"
+ assert format in ("ssleay", "pkcs8")
+ header = "EC PRIVATE KEY" if format == "ssleay" else "PRIVATE KEY"
+ return der.topem(self.to_der(point_encoding, format), header)
+
+ def to_der(self, point_encoding="uncompressed", format="ssleay"):
+ """
+ Convert the private key to the :term:`DER` format.
+
+ See :func:`~SigningKey.from_der` method for format specification.
+
+ Only the named curve format is supported.
+ The public key will be included in the generated string.
+
+ :param str point_encoding: format to use for encoding public point
+ :param str format: either ``ssleay`` (default) or ``pkcs8``
+
+ :return: DER encoded private key
+ :rtype: bytes
+ """
+ # SEQ([int(1), octetstring(privkey),cont[0], oid(secp224r1),
+ # cont[1],bitstring])
+ if point_encoding == "raw":
+ raise ValueError("raw encoding not allowed in DER")
+ assert format in ("ssleay", "pkcs8")
+ encoded_vk = self.get_verifying_key().to_string(point_encoding)
+ # the 0 in encode_bitstring specifies the number of unused bits
+ # in the `encoded_vk` string
+ ec_private_key = der.encode_sequence(
+ der.encode_integer(1),
+ der.encode_octet_string(self.to_string()),
+ der.encode_constructed(0, self.curve.encoded_oid),
+ der.encode_constructed(1, der.encode_bitstring(encoded_vk, 0)),
+ )
+
+ if format == "ssleay":
+ return ec_private_key
+ else:
+ return der.encode_sequence(
+ # version = 1 means the public key is not present in the
+ # top-level structure.
+ der.encode_integer(1),
+ der.encode_sequence(
+ der.encode_oid(*oid_ecPublicKey), self.curve.encoded_oid
+ ),
+ der.encode_octet_string(ec_private_key),
+ )
+
+ def get_verifying_key(self):
+ """
+ Return the VerifyingKey associated with this private key.
+
+ Equivalent to reading the `verifying_key` field of an instance.
+
+ :return: a public key that can be used to verify the signatures made
+ with this SigningKey
+ :rtype: VerifyingKey
+ """
+ return self.verifying_key
+
+ def sign_deterministic(
+ self,
+ data,
+ hashfunc=None,
+ sigencode=sigencode_string,
+ extra_entropy=b"",
+ ):
+ """
+ Create signature over data using the deterministic RFC6679 algorithm.
+
+ The data will be hashed using the `hashfunc` function before signing.
+
+ This is the recommended method for performing signatures when hashing
+ of data is necessary.
+
+ :param data: data to be hashed and computed signature over
+ :type data: bytes like object
+ :param hashfunc: hash function to use for computing the signature,
+ if unspecified, the default hash function selected during
+ object initialisation will be used (see
+ `VerifyingKey.default_hashfunc`). The object needs to implement
+ the same interface as hashlib.sha1.
+ :type hashfunc: callable
+ :param sigencode: function used to encode the signature.
+ The function needs to accept three parameters: the two integers
+ that are the signature and the order of the curve over which the
+ signature was computed. It needs to return an encoded signature.
+ See `ecdsa.util.sigencode_string` and `ecdsa.util.sigencode_der`
+ as examples of such functions.
+ :type sigencode: callable
+ :param extra_entropy: additional data that will be fed into the random
+ number generator used in the RFC6979 process. Entirely optional.
+ :type extra_entropy: bytes like object
+
+ :return: encoded signature over `data`
+ :rtype: bytes or sigencode function dependant type
+ """
+ hashfunc = hashfunc or self.default_hashfunc
+ data = normalise_bytes(data)
+ extra_entropy = normalise_bytes(extra_entropy)
+ digest = hashfunc(data).digest()
+
+ return self.sign_digest_deterministic(
+ digest,
+ hashfunc=hashfunc,
+ sigencode=sigencode,
+ extra_entropy=extra_entropy,
+ allow_truncate=True,
+ )
+
+ def sign_digest_deterministic(
+ self,
+ digest,
+ hashfunc=None,
+ sigencode=sigencode_string,
+ extra_entropy=b"",
+ allow_truncate=False,
+ ):
+ """
+ Create signature for digest using the deterministic RFC6679 algorithm.
+
+ `digest` should be the output of cryptographically secure hash function
+ like SHA256 or SHA-3-256.
+
+ This is the recommended method for performing signatures when no
+ hashing of data is necessary.
+
+ :param digest: hash of data that will be signed
+ :type digest: bytes like object
+ :param hashfunc: hash function to use for computing the random "k"
+ value from RFC6979 process,
+ if unspecified, the default hash function selected during
+ object initialisation will be used (see
+ `VerifyingKey.default_hashfunc`). The object needs to implement
+ the same interface as hashlib.sha1.
+ :type hashfunc: callable
+ :param sigencode: function used to encode the signature.
+ The function needs to accept three parameters: the two integers
+ that are the signature and the order of the curve over which the
+ signature was computed. It needs to return an encoded signature.
+ See `ecdsa.util.sigencode_string` and `ecdsa.util.sigencode_der`
+ as examples of such functions.
+ :type sigencode: callable
+ :param extra_entropy: additional data that will be fed into the random
+ number generator used in the RFC6979 process. Entirely optional.
+ :type extra_entropy: bytes like object
+ :param bool allow_truncate: if True, the provided digest can have
+ bigger bit-size than the order of the curve, the extra bits (at
+ the end of the digest) will be truncated. Use it when signing
+ SHA-384 output using NIST256p or in similar situations.
+
+ :return: encoded signature for the `digest` hash
+ :rtype: bytes or sigencode function dependant type
+ """
+ secexp = self.privkey.secret_multiplier
+ hashfunc = hashfunc or self.default_hashfunc
+ digest = normalise_bytes(digest)
+ extra_entropy = normalise_bytes(extra_entropy)
+
+ def simple_r_s(r, s, order):
+ return r, s, order
+
+ retry_gen = 0
+ while True:
+ k = rfc6979.generate_k(
+ self.curve.generator.order(),
+ secexp,
+ hashfunc,
+ digest,
+ retry_gen=retry_gen,
+ extra_entropy=extra_entropy,
+ )
+ try:
+ r, s, order = self.sign_digest(
+ digest,
+ sigencode=simple_r_s,
+ k=k,
+ allow_truncate=allow_truncate,
+ )
+ break
+ except RSZeroError:
+ retry_gen += 1
+
+ return sigencode(r, s, order)
+
+ def sign(
+ self,
+ data,
+ entropy=None,
+ hashfunc=None,
+ sigencode=sigencode_string,
+ k=None,
+ allow_truncate=True,
+ ):
+ """
+ Create signature over data using the probabilistic ECDSA algorithm.
+
+ This method uses the standard ECDSA algorithm that requires a
+ cryptographically secure random number generator.
+
+ It's recommended to use the :func:`~SigningKey.sign_deterministic`
+ method instead of this one.
+
+ :param data: data that will be hashed for signing
+ :type data: bytes like object
+ :param callable entropy: randomness source, os.urandom by default
+ :param hashfunc: hash function to use for hashing the provided `data`.
+ If unspecified the default hash function selected during
+ object initialisation will be used (see
+ `VerifyingKey.default_hashfunc`).
+ Should behave like hashlib.sha1. The output length of the
+ hash (in bytes) must not be longer than the length of the curve
+ order (rounded up to the nearest byte), so using SHA256 with
+ NIST256p is ok, but SHA256 with NIST192p is not. (In the 2**-96ish
+ unlikely event of a hash output larger than the curve order, the
+ hash will effectively be wrapped mod n).
+ Use hashfunc=hashlib.sha1 to match openssl's -ecdsa-with-SHA1 mode,
+ or hashfunc=hashlib.sha256 for openssl-1.0.0's -ecdsa-with-SHA256.
+ :type hashfunc: callable
+ :param sigencode: function used to encode the signature.
+ The function needs to accept three parameters: the two integers
+ that are the signature and the order of the curve over which the
+ signature was computed. It needs to return an encoded signature.
+ See `ecdsa.util.sigencode_string` and `ecdsa.util.sigencode_der`
+ as examples of such functions.
+ :type sigencode: callable
+ :param int k: a pre-selected nonce for calculating the signature.
+ In typical use cases, it should be set to None (the default) to
+ allow its generation from an entropy source.
+ :param bool allow_truncate: if True, the provided digest can have
+ bigger bit-size than the order of the curve, the extra bits (at
+ the end of the digest) will be truncated. Use it when signing
+ SHA-384 output using NIST256p or in similar situations. True by
+ default.
+
+ :raises RSZeroError: in the unlikely event when "r" parameter or
+ "s" parameter is equal 0 as that would leak the key. Calee should
+ try a better entropy source or different 'k' in such case.
+
+ :return: encoded signature of the hash of `data`
+ :rtype: bytes or sigencode function dependant type
+ """
+ hashfunc = hashfunc or self.default_hashfunc
+ data = normalise_bytes(data)
+ h = hashfunc(data).digest()
+ return self.sign_digest(h, entropy, sigencode, k, allow_truncate)
+
+ def sign_digest(
+ self,
+ digest,
+ entropy=None,
+ sigencode=sigencode_string,
+ k=None,
+ allow_truncate=False,
+ ):
+ """
+ Create signature over digest using the probabilistic ECDSA algorithm.
+
+ This method uses the standard ECDSA algorithm that requires a
+ cryptographically secure random number generator.
+
+ This method does not hash the input.
+
+ It's recommended to use the
+ :func:`~SigningKey.sign_digest_deterministic` method
+ instead of this one.
+
+ :param digest: hash value that will be signed
+ :type digest: bytes like object
+ :param callable entropy: randomness source, os.urandom by default
+ :param sigencode: function used to encode the signature.
+ The function needs to accept three parameters: the two integers
+ that are the signature and the order of the curve over which the
+ signature was computed. It needs to return an encoded signature.
+ See `ecdsa.util.sigencode_string` and `ecdsa.util.sigencode_der`
+ as examples of such functions.
+ :type sigencode: callable
+ :param int k: a pre-selected nonce for calculating the signature.
+ In typical use cases, it should be set to None (the default) to
+ allow its generation from an entropy source.
+ :param bool allow_truncate: if True, the provided digest can have
+ bigger bit-size than the order of the curve, the extra bits (at
+ the end of the digest) will be truncated. Use it when signing
+ SHA-384 output using NIST256p or in similar situations.
+
+ :raises RSZeroError: in the unlikely event when "r" parameter or
+ "s" parameter is equal 0 as that would leak the key. Calee should
+ try a better entropy source in such case.
+
+ :return: encoded signature for the `digest` hash
+ :rtype: bytes or sigencode function dependant type
+ """
+ digest = normalise_bytes(digest)
+ if allow_truncate:
+ digest = digest[: self.curve.baselen]
+ if len(digest) > self.curve.baselen:
+ raise BadDigestError(
+ "this curve (%s) is too short "
+ "for your digest (%d)" % (self.curve.name, 8 * len(digest))
+ )
+ number = string_to_number(digest)
+ r, s = self.sign_number(number, entropy, k)
+ return sigencode(r, s, self.privkey.order)
+
+ def sign_number(self, number, entropy=None, k=None):
+ """
+ Sign an integer directly.
+
+ Note, this is a low level method, usually you will want to use
+ :func:`~SigningKey.sign_deterministic` or
+ :func:`~SigningKey.sign_digest_deterministic`.
+
+ :param int number: number to sign using the probabilistic ECDSA
+ algorithm.
+ :param callable entropy: entropy source, os.urandom by default
+ :param int k: pre-selected nonce for signature operation. If unset
+ it will be selected at random using the entropy source.
+
+ :raises RSZeroError: in the unlikely event when "r" parameter or
+ "s" parameter is equal 0 as that would leak the key. Calee should
+ try a different 'k' in such case.
+
+ :return: the "r" and "s" parameters of the signature
+ :rtype: tuple of ints
+ """
+ order = self.privkey.order
+
+ if k is not None:
+ _k = k
+ else:
+ _k = randrange(order, entropy)
+
+ assert 1 <= _k < order
+ sig = self.privkey.sign(number, _k)
+ return sig.r, sig.s
diff --git a/frozen_deps/ecdsa/numbertheory.py b/frozen_deps/ecdsa/numbertheory.py
new file mode 100644
index 0000000..e5cc888
--- /dev/null
+++ b/frozen_deps/ecdsa/numbertheory.py
@@ -0,0 +1,810 @@
+#! /usr/bin/env python
+#
+# Provide some simple capabilities from number theory.
+#
+# Version of 2008.11.14.
+#
+# Written in 2005 and 2006 by Peter Pearson and placed in the public domain.
+# Revision history:
+# 2008.11.14: Use pow(base, exponent, modulus) for modular_exp.
+# Make gcd and lcm accept arbitrarly many arguments.
+
+from __future__ import division
+
+from six import integer_types, PY2
+from six.moves import reduce
+
+try:
+ xrange
+except NameError:
+ xrange = range
+try:
+ from gmpy2 import powmod
+
+ GMPY2 = True
+ GMPY = False
+except ImportError:
+ GMPY2 = False
+ try:
+ from gmpy import mpz
+
+ GMPY = True
+ except ImportError:
+ GMPY = False
+
+import math
+import warnings
+
+
+class Error(Exception):
+ """Base class for exceptions in this module."""
+
+ pass
+
+
+class SquareRootError(Error):
+ pass
+
+
+class NegativeExponentError(Error):
+ pass
+
+
+def modular_exp(base, exponent, modulus): # pragma: no cover
+ """Raise base to exponent, reducing by modulus"""
+ # deprecated in 0.14
+ warnings.warn(
+ "Function is unused in library code. If you use this code, "
+ "change to pow() builtin.",
+ DeprecationWarning,
+ )
+ if exponent < 0:
+ raise NegativeExponentError(
+ "Negative exponents (%d) not allowed" % exponent
+ )
+ return pow(base, exponent, modulus)
+
+
+def polynomial_reduce_mod(poly, polymod, p):
+ """Reduce poly by polymod, integer arithmetic modulo p.
+
+ Polynomials are represented as lists of coefficients
+ of increasing powers of x."""
+
+ # This module has been tested only by extensive use
+ # in calculating modular square roots.
+
+ # Just to make this easy, require a monic polynomial:
+ assert polymod[-1] == 1
+
+ assert len(polymod) > 1
+
+ while len(poly) >= len(polymod):
+ if poly[-1] != 0:
+ for i in xrange(2, len(polymod) + 1):
+ poly[-i] = (poly[-i] - poly[-1] * polymod[-i]) % p
+ poly = poly[0:-1]
+
+ return poly
+
+
+def polynomial_multiply_mod(m1, m2, polymod, p):
+ """Polynomial multiplication modulo a polynomial over ints mod p.
+
+ Polynomials are represented as lists of coefficients
+ of increasing powers of x."""
+
+ # This is just a seat-of-the-pants implementation.
+
+ # This module has been tested only by extensive use
+ # in calculating modular square roots.
+
+ # Initialize the product to zero:
+
+ prod = (len(m1) + len(m2) - 1) * [0]
+
+ # Add together all the cross-terms:
+
+ for i in xrange(len(m1)):
+ for j in xrange(len(m2)):
+ prod[i + j] = (prod[i + j] + m1[i] * m2[j]) % p
+
+ return polynomial_reduce_mod(prod, polymod, p)
+
+
+def polynomial_exp_mod(base, exponent, polymod, p):
+ """Polynomial exponentiation modulo a polynomial over ints mod p.
+
+ Polynomials are represented as lists of coefficients
+ of increasing powers of x."""
+
+ # Based on the Handbook of Applied Cryptography, algorithm 2.227.
+
+ # This module has been tested only by extensive use
+ # in calculating modular square roots.
+
+ assert exponent < p
+
+ if exponent == 0:
+ return [1]
+
+ G = base
+ k = exponent
+ if k % 2 == 1:
+ s = G
+ else:
+ s = [1]
+
+ while k > 1:
+ k = k // 2
+ G = polynomial_multiply_mod(G, G, polymod, p)
+ if k % 2 == 1:
+ s = polynomial_multiply_mod(G, s, polymod, p)
+
+ return s
+
+
+def jacobi(a, n):
+ """Jacobi symbol"""
+
+ # Based on the Handbook of Applied Cryptography (HAC), algorithm 2.149.
+
+ # This function has been tested by comparison with a small
+ # table printed in HAC, and by extensive use in calculating
+ # modular square roots.
+
+ assert n >= 3
+ assert n % 2 == 1
+ a = a % n
+ if a == 0:
+ return 0
+ if a == 1:
+ return 1
+ a1, e = a, 0
+ while a1 % 2 == 0:
+ a1, e = a1 // 2, e + 1
+ if e % 2 == 0 or n % 8 == 1 or n % 8 == 7:
+ s = 1
+ else:
+ s = -1
+ if a1 == 1:
+ return s
+ if n % 4 == 3 and a1 % 4 == 3:
+ s = -s
+ return s * jacobi(n % a1, a1)
+
+
+def square_root_mod_prime(a, p):
+ """Modular square root of a, mod p, p prime."""
+
+ # Based on the Handbook of Applied Cryptography, algorithms 3.34 to 3.39.
+
+ # This module has been tested for all values in [0,p-1] for
+ # every prime p from 3 to 1229.
+
+ assert 0 <= a < p
+ assert 1 < p
+
+ if a == 0:
+ return 0
+ if p == 2:
+ return a
+
+ jac = jacobi(a, p)
+ if jac == -1:
+ raise SquareRootError("%d has no square root modulo %d" % (a, p))
+
+ if p % 4 == 3:
+ return pow(a, (p + 1) // 4, p)
+
+ if p % 8 == 5:
+ d = pow(a, (p - 1) // 4, p)
+ if d == 1:
+ return pow(a, (p + 3) // 8, p)
+ if d == p - 1:
+ return (2 * a * pow(4 * a, (p - 5) // 8, p)) % p
+ raise RuntimeError("Shouldn't get here.")
+
+ if PY2:
+ # xrange on python2 can take integers representable as C long only
+ range_top = min(0x7FFFFFFF, p)
+ else:
+ range_top = p
+ for b in xrange(2, range_top):
+ if jacobi(b * b - 4 * a, p) == -1:
+ f = (a, -b, 1)
+ ff = polynomial_exp_mod((0, 1), (p + 1) // 2, f, p)
+ assert ff[1] == 0
+ return ff[0]
+ raise RuntimeError("No b found.")
+
+
+if GMPY2:
+
+ def inverse_mod(a, m):
+ """Inverse of a mod m."""
+ if a == 0:
+ return 0
+ return powmod(a, -1, m)
+
+
+elif GMPY:
+
+ def inverse_mod(a, m):
+ """Inverse of a mod m."""
+ # while libgmp likely does support inverses modulo, it is accessible
+ # only using the native `pow()` function, and `pow()` sanity checks
+ # the parameters before passing them on to underlying implementation
+ # on Python2
+ if a == 0:
+ return 0
+ a = mpz(a)
+ m = mpz(m)
+
+ lm, hm = mpz(1), mpz(0)
+ low, high = a % m, m
+ while low > 1:
+ r = high // low
+ lm, low, hm, high = hm - lm * r, high - low * r, lm, low
+
+ return lm % m
+
+
+else:
+
+ def inverse_mod(a, m):
+ """Inverse of a mod m."""
+
+ if a == 0:
+ return 0
+
+ lm, hm = 1, 0
+ low, high = a % m, m
+ while low > 1:
+ r = high // low
+ lm, low, hm, high = hm - lm * r, high - low * r, lm, low
+
+ return lm % m
+
+
+try:
+ gcd2 = math.gcd
+except AttributeError:
+
+ def gcd2(a, b):
+ """Greatest common divisor using Euclid's algorithm."""
+ while a:
+ a, b = b % a, a
+ return b
+
+
+def gcd(*a):
+ """Greatest common divisor.
+
+ Usage: gcd([ 2, 4, 6 ])
+ or: gcd(2, 4, 6)
+ """
+
+ if len(a) > 1:
+ return reduce(gcd2, a)
+ if hasattr(a[0], "__iter__"):
+ return reduce(gcd2, a[0])
+ return a[0]
+
+
+def lcm2(a, b):
+ """Least common multiple of two integers."""
+
+ return (a * b) // gcd(a, b)
+
+
+def lcm(*a):
+ """Least common multiple.
+
+ Usage: lcm([ 3, 4, 5 ])
+ or: lcm(3, 4, 5)
+ """
+
+ if len(a) > 1:
+ return reduce(lcm2, a)
+ if hasattr(a[0], "__iter__"):
+ return reduce(lcm2, a[0])
+ return a[0]
+
+
+def factorization(n):
+ """Decompose n into a list of (prime,exponent) pairs."""
+
+ assert isinstance(n, integer_types)
+
+ if n < 2:
+ return []
+
+ result = []
+ d = 2
+
+ # Test the small primes:
+
+ for d in smallprimes:
+ if d > n:
+ break
+ q, r = divmod(n, d)
+ if r == 0:
+ count = 1
+ while d <= n:
+ n = q
+ q, r = divmod(n, d)
+ if r != 0:
+ break
+ count = count + 1
+ result.append((d, count))
+
+ # If n is still greater than the last of our small primes,
+ # it may require further work:
+
+ if n > smallprimes[-1]:
+ if is_prime(n): # If what's left is prime, it's easy:
+ result.append((n, 1))
+ else: # Ugh. Search stupidly for a divisor:
+ d = smallprimes[-1]
+ while 1:
+ d = d + 2 # Try the next divisor.
+ q, r = divmod(n, d)
+ if q < d: # n < d*d means we're done, n = 1 or prime.
+ break
+ if r == 0: # d divides n. How many times?
+ count = 1
+ n = q
+ while d <= n: # As long as d might still divide n,
+ q, r = divmod(n, d) # see if it does.
+ if r != 0:
+ break
+ n = q # It does. Reduce n, increase count.
+ count = count + 1
+ result.append((d, count))
+ if n > 1:
+ result.append((n, 1))
+
+ return result
+
+
+def phi(n): # pragma: no cover
+ """Return the Euler totient function of n."""
+ # deprecated in 0.14
+ warnings.warn(
+ "Function is unused by library code. If you use this code, "
+ "please open an issue in "
+ "https://github.com/warner/python-ecdsa",
+ DeprecationWarning,
+ )
+
+ assert isinstance(n, integer_types)
+
+ if n < 3:
+ return 1
+
+ result = 1
+ ff = factorization(n)
+ for f in ff:
+ e = f[1]
+ if e > 1:
+ result = result * f[0] ** (e - 1) * (f[0] - 1)
+ else:
+ result = result * (f[0] - 1)
+ return result
+
+
+def carmichael(n): # pragma: no cover
+ """Return Carmichael function of n.
+
+ Carmichael(n) is the smallest integer x such that
+ m**x = 1 mod n for all m relatively prime to n.
+ """
+ # deprecated in 0.14
+ warnings.warn(
+ "Function is unused by library code. If you use this code, "
+ "please open an issue in "
+ "https://github.com/warner/python-ecdsa",
+ DeprecationWarning,
+ )
+
+ return carmichael_of_factorized(factorization(n))
+
+
+def carmichael_of_factorized(f_list): # pragma: no cover
+ """Return the Carmichael function of a number that is
+ represented as a list of (prime,exponent) pairs.
+ """
+ # deprecated in 0.14
+ warnings.warn(
+ "Function is unused by library code. If you use this code, "
+ "please open an issue in "
+ "https://github.com/warner/python-ecdsa",
+ DeprecationWarning,
+ )
+
+ if len(f_list) < 1:
+ return 1
+
+ result = carmichael_of_ppower(f_list[0])
+ for i in xrange(1, len(f_list)):
+ result = lcm(result, carmichael_of_ppower(f_list[i]))
+
+ return result
+
+
+def carmichael_of_ppower(pp): # pragma: no cover
+ """Carmichael function of the given power of the given prime."""
+ # deprecated in 0.14
+ warnings.warn(
+ "Function is unused by library code. If you use this code, "
+ "please open an issue in "
+ "https://github.com/warner/python-ecdsa",
+ DeprecationWarning,
+ )
+
+ p, a = pp
+ if p == 2 and a > 2:
+ return 2 ** (a - 2)
+ else:
+ return (p - 1) * p ** (a - 1)
+
+
+def order_mod(x, m): # pragma: no cover
+ """Return the order of x in the multiplicative group mod m."""
+ # deprecated in 0.14
+ warnings.warn(
+ "Function is unused by library code. If you use this code, "
+ "please open an issue in "
+ "https://github.com/warner/python-ecdsa",
+ DeprecationWarning,
+ )
+
+ # Warning: this implementation is not very clever, and will
+ # take a long time if m is very large.
+
+ if m <= 1:
+ return 0
+
+ assert gcd(x, m) == 1
+
+ z = x
+ result = 1
+ while z != 1:
+ z = (z * x) % m
+ result = result + 1
+ return result
+
+
+def largest_factor_relatively_prime(a, b): # pragma: no cover
+ """Return the largest factor of a relatively prime to b."""
+ # deprecated in 0.14
+ warnings.warn(
+ "Function is unused by library code. If you use this code, "
+ "please open an issue in "
+ "https://github.com/warner/python-ecdsa",
+ DeprecationWarning,
+ )
+
+ while 1:
+ d = gcd(a, b)
+ if d <= 1:
+ break
+ b = d
+ while 1:
+ q, r = divmod(a, d)
+ if r > 0:
+ break
+ a = q
+ return a
+
+
+def kinda_order_mod(x, m): # pragma: no cover
+ """Return the order of x in the multiplicative group mod m',
+ where m' is the largest factor of m relatively prime to x.
+ """
+ # deprecated in 0.14
+ warnings.warn(
+ "Function is unused by library code. If you use this code, "
+ "please open an issue in "
+ "https://github.com/warner/python-ecdsa",
+ DeprecationWarning,
+ )
+
+ return order_mod(x, largest_factor_relatively_prime(m, x))
+
+
+def is_prime(n):
+ """Return True if x is prime, False otherwise.
+
+ We use the Miller-Rabin test, as given in Menezes et al. p. 138.
+ This test is not exact: there are composite values n for which
+ it returns True.
+
+ In testing the odd numbers from 10000001 to 19999999,
+ about 66 composites got past the first test,
+ 5 got past the second test, and none got past the third.
+ Since factors of 2, 3, 5, 7, and 11 were detected during
+ preliminary screening, the number of numbers tested by
+ Miller-Rabin was (19999999 - 10000001)*(2/3)*(4/5)*(6/7)
+ = 4.57 million.
+ """
+
+ # (This is used to study the risk of false positives:)
+ global miller_rabin_test_count
+
+ miller_rabin_test_count = 0
+
+ if n <= smallprimes[-1]:
+ if n in smallprimes:
+ return True
+ else:
+ return False
+
+ if gcd(n, 2 * 3 * 5 * 7 * 11) != 1:
+ return False
+
+ # Choose a number of iterations sufficient to reduce the
+ # probability of accepting a composite below 2**-80
+ # (from Menezes et al. Table 4.4):
+
+ t = 40
+ n_bits = 1 + int(math.log(n, 2))
+ for k, tt in (
+ (100, 27),
+ (150, 18),
+ (200, 15),
+ (250, 12),
+ (300, 9),
+ (350, 8),
+ (400, 7),
+ (450, 6),
+ (550, 5),
+ (650, 4),
+ (850, 3),
+ (1300, 2),
+ ):
+ if n_bits < k:
+ break
+ t = tt
+
+ # Run the test t times:
+
+ s = 0
+ r = n - 1
+ while (r % 2) == 0:
+ s = s + 1
+ r = r // 2
+ for i in xrange(t):
+ a = smallprimes[i]
+ y = pow(a, r, n)
+ if y != 1 and y != n - 1:
+ j = 1
+ while j <= s - 1 and y != n - 1:
+ y = pow(y, 2, n)
+ if y == 1:
+ miller_rabin_test_count = i + 1
+ return False
+ j = j + 1
+ if y != n - 1:
+ miller_rabin_test_count = i + 1
+ return False
+ return True
+
+
+def next_prime(starting_value):
+ """Return the smallest prime larger than the starting value."""
+
+ if starting_value < 2:
+ return 2
+ result = (starting_value + 1) | 1
+ while not is_prime(result):
+ result = result + 2
+ return result
+
+
+smallprimes = [
+ 2,
+ 3,
+ 5,
+ 7,
+ 11,
+ 13,
+ 17,
+ 19,
+ 23,
+ 29,
+ 31,
+ 37,
+ 41,
+ 43,
+ 47,
+ 53,
+ 59,
+ 61,
+ 67,
+ 71,
+ 73,
+ 79,
+ 83,
+ 89,
+ 97,
+ 101,
+ 103,
+ 107,
+ 109,
+ 113,
+ 127,
+ 131,
+ 137,
+ 139,
+ 149,
+ 151,
+ 157,
+ 163,
+ 167,
+ 173,
+ 179,
+ 181,
+ 191,
+ 193,
+ 197,
+ 199,
+ 211,
+ 223,
+ 227,
+ 229,
+ 233,
+ 239,
+ 241,
+ 251,
+ 257,
+ 263,
+ 269,
+ 271,
+ 277,
+ 281,
+ 283,
+ 293,
+ 307,
+ 311,
+ 313,
+ 317,
+ 331,
+ 337,
+ 347,
+ 349,
+ 353,
+ 359,
+ 367,
+ 373,
+ 379,
+ 383,
+ 389,
+ 397,
+ 401,
+ 409,
+ 419,
+ 421,
+ 431,
+ 433,
+ 439,
+ 443,
+ 449,
+ 457,
+ 461,
+ 463,
+ 467,
+ 479,
+ 487,
+ 491,
+ 499,
+ 503,
+ 509,
+ 521,
+ 523,
+ 541,
+ 547,
+ 557,
+ 563,
+ 569,
+ 571,
+ 577,
+ 587,
+ 593,
+ 599,
+ 601,
+ 607,
+ 613,
+ 617,
+ 619,
+ 631,
+ 641,
+ 643,
+ 647,
+ 653,
+ 659,
+ 661,
+ 673,
+ 677,
+ 683,
+ 691,
+ 701,
+ 709,
+ 719,
+ 727,
+ 733,
+ 739,
+ 743,
+ 751,
+ 757,
+ 761,
+ 769,
+ 773,
+ 787,
+ 797,
+ 809,
+ 811,
+ 821,
+ 823,
+ 827,
+ 829,
+ 839,
+ 853,
+ 857,
+ 859,
+ 863,
+ 877,
+ 881,
+ 883,
+ 887,
+ 907,
+ 911,
+ 919,
+ 929,
+ 937,
+ 941,
+ 947,
+ 953,
+ 967,
+ 971,
+ 977,
+ 983,
+ 991,
+ 997,
+ 1009,
+ 1013,
+ 1019,
+ 1021,
+ 1031,
+ 1033,
+ 1039,
+ 1049,
+ 1051,
+ 1061,
+ 1063,
+ 1069,
+ 1087,
+ 1091,
+ 1093,
+ 1097,
+ 1103,
+ 1109,
+ 1117,
+ 1123,
+ 1129,
+ 1151,
+ 1153,
+ 1163,
+ 1171,
+ 1181,
+ 1187,
+ 1193,
+ 1201,
+ 1213,
+ 1217,
+ 1223,
+ 1229,
+]
+
+miller_rabin_test_count = 0
diff --git a/frozen_deps/ecdsa/rfc6979.py b/frozen_deps/ecdsa/rfc6979.py
new file mode 100644
index 0000000..1e577c0
--- /dev/null
+++ b/frozen_deps/ecdsa/rfc6979.py
@@ -0,0 +1,110 @@
+"""
+RFC 6979:
+ Deterministic Usage of the Digital Signature Algorithm (DSA) and
+ Elliptic Curve Digital Signature Algorithm (ECDSA)
+
+ http://tools.ietf.org/html/rfc6979
+
+Many thanks to Coda Hale for his implementation in Go language:
+ https://github.com/codahale/rfc6979
+"""
+
+import hmac
+from binascii import hexlify
+from .util import number_to_string, number_to_string_crop, bit_length
+from ._compat import hmac_compat
+
+
+# bit_length was defined in this module previously so keep it for backwards
+# compatibility, will need to deprecate and remove it later
+__all__ = ["bit_length", "bits2int", "bits2octets", "generate_k"]
+
+
+def bits2int(data, qlen):
+ x = int(hexlify(data), 16)
+ l = len(data) * 8
+
+ if l > qlen:
+ return x >> (l - qlen)
+ return x
+
+
+def bits2octets(data, order):
+ z1 = bits2int(data, bit_length(order))
+ z2 = z1 - order
+
+ if z2 < 0:
+ z2 = z1
+
+ return number_to_string_crop(z2, order)
+
+
+# https://tools.ietf.org/html/rfc6979#section-3.2
+def generate_k(order, secexp, hash_func, data, retry_gen=0, extra_entropy=b""):
+ """
+ order - order of the DSA generator used in the signature
+ secexp - secure exponent (private key) in numeric form
+ hash_func - reference to the same hash function used for generating
+ hash
+ data - hash in binary form of the signing data
+ retry_gen - int - how many good 'k' values to skip before returning
+ extra_entropy - extra added data in binary form as per section-3.6 of
+ rfc6979
+ """
+
+ qlen = bit_length(order)
+ holen = hash_func().digest_size
+ rolen = (qlen + 7) // 8
+ bx = (
+ hmac_compat(number_to_string(secexp, order)),
+ hmac_compat(bits2octets(data, order)),
+ hmac_compat(extra_entropy),
+ )
+
+ # Step B
+ v = b"\x01" * holen
+
+ # Step C
+ k = b"\x00" * holen
+
+ # Step D
+
+ k = hmac.new(k, digestmod=hash_func)
+ k.update(v + b"\x00")
+ for i in bx:
+ k.update(i)
+ k = k.digest()
+
+ # Step E
+ v = hmac.new(k, v, hash_func).digest()
+
+ # Step F
+ k = hmac.new(k, digestmod=hash_func)
+ k.update(v + b"\x01")
+ for i in bx:
+ k.update(i)
+ k = k.digest()
+
+ # Step G
+ v = hmac.new(k, v, hash_func).digest()
+
+ # Step H
+ while True:
+ # Step H1
+ t = b""
+
+ # Step H2
+ while len(t) < rolen:
+ v = hmac.new(k, v, hash_func).digest()
+ t += v
+
+ # Step H3
+ secret = bits2int(t, qlen)
+
+ if 1 <= secret < order:
+ if retry_gen <= 0:
+ return secret
+ retry_gen -= 1
+
+ k = hmac.new(k, v + b"\x00", hash_func).digest()
+ v = hmac.new(k, v, hash_func).digest()
diff --git a/frozen_deps/ecdsa/test_der.py b/frozen_deps/ecdsa/test_der.py
new file mode 100644
index 0000000..746d927
--- /dev/null
+++ b/frozen_deps/ecdsa/test_der.py
@@ -0,0 +1,397 @@
+# compatibility with Python 2.6, for that we need unittest2 package,
+# which is not available on 3.3 or 3.4
+import warnings
+from binascii import hexlify
+
+try:
+ import unittest2 as unittest
+except ImportError:
+ import unittest
+from six import b
+import hypothesis.strategies as st
+from hypothesis import given, example
+import pytest
+from ._compat import str_idx_as_int
+from .curves import NIST256p, NIST224p
+from .der import (
+ remove_integer,
+ UnexpectedDER,
+ read_length,
+ encode_bitstring,
+ remove_bitstring,
+ remove_object,
+ encode_oid,
+)
+
+
+class TestRemoveInteger(unittest.TestCase):
+ # DER requires the integers to be 0-padded only if they would be
+ # interpreted as negative, check if those errors are detected
+ def test_non_minimal_encoding(self):
+ with self.assertRaises(UnexpectedDER):
+ remove_integer(b("\x02\x02\x00\x01"))
+
+ def test_negative_with_high_bit_set(self):
+ with self.assertRaises(UnexpectedDER):
+ remove_integer(b("\x02\x01\x80"))
+
+ def test_minimal_with_high_bit_set(self):
+ val, rem = remove_integer(b("\x02\x02\x00\x80"))
+
+ self.assertEqual(val, 0x80)
+ self.assertFalse(rem)
+
+ def test_two_zero_bytes_with_high_bit_set(self):
+ with self.assertRaises(UnexpectedDER):
+ remove_integer(b("\x02\x03\x00\x00\xff"))
+
+ def test_zero_length_integer(self):
+ with self.assertRaises(UnexpectedDER):
+ remove_integer(b("\x02\x00"))
+
+ def test_empty_string(self):
+ with self.assertRaises(UnexpectedDER):
+ remove_integer(b(""))
+
+ def test_encoding_of_zero(self):
+ val, rem = remove_integer(b("\x02\x01\x00"))
+
+ self.assertEqual(val, 0)
+ self.assertFalse(rem)
+
+ def test_encoding_of_127(self):
+ val, rem = remove_integer(b("\x02\x01\x7f"))
+
+ self.assertEqual(val, 127)
+ self.assertFalse(rem)
+
+ def test_encoding_of_128(self):
+ val, rem = remove_integer(b("\x02\x02\x00\x80"))
+
+ self.assertEqual(val, 128)
+ self.assertFalse(rem)
+
+
+class TestReadLength(unittest.TestCase):
+ # DER requires the lengths between 0 and 127 to be encoded using the short
+ # form and lengths above that encoded with minimal number of bytes
+ # necessary
+ def test_zero_length(self):
+ self.assertEqual((0, 1), read_length(b("\x00")))
+
+ def test_two_byte_zero_length(self):
+ with self.assertRaises(UnexpectedDER):
+ read_length(b("\x81\x00"))
+
+ def test_two_byte_small_length(self):
+ with self.assertRaises(UnexpectedDER):
+ read_length(b("\x81\x7f"))
+
+ def test_long_form_with_zero_length(self):
+ with self.assertRaises(UnexpectedDER):
+ read_length(b("\x80"))
+
+ def test_smallest_two_byte_length(self):
+ self.assertEqual((128, 2), read_length(b("\x81\x80")))
+
+ def test_zero_padded_length(self):
+ with self.assertRaises(UnexpectedDER):
+ read_length(b("\x82\x00\x80"))
+
+ def test_two_three_byte_length(self):
+ self.assertEqual((256, 3), read_length(b"\x82\x01\x00"))
+
+ def test_empty_string(self):
+ with self.assertRaises(UnexpectedDER):
+ read_length(b(""))
+
+ def test_length_overflow(self):
+ with self.assertRaises(UnexpectedDER):
+ read_length(b("\x83\x01\x00"))
+
+
+class TestEncodeBitstring(unittest.TestCase):
+ # DER requires BIT STRINGS to include a number of padding bits in the
+ # encoded byte string, that padding must be between 0 and 7
+
+ def test_old_call_convention(self):
+ """This is the old way to use the function."""
+ warnings.simplefilter("always")
+ with pytest.warns(DeprecationWarning) as warns:
+ der = encode_bitstring(b"\x00\xff")
+
+ self.assertEqual(len(warns), 1)
+ self.assertIn(
+ "unused= needs to be specified", warns[0].message.args[0]
+ )
+
+ self.assertEqual(der, b"\x03\x02\x00\xff")
+
+ def test_new_call_convention(self):
+ """This is how it should be called now."""
+ warnings.simplefilter("always")
+ with pytest.warns(None) as warns:
+ der = encode_bitstring(b"\xff", 0)
+
+ # verify that new call convention doesn't raise Warnings
+ self.assertEqual(len(warns), 0)
+
+ self.assertEqual(der, b"\x03\x02\x00\xff")
+
+ def test_implicit_unused_bits(self):
+ """
+ Writing bit string with already included the number of unused bits.
+ """
+ warnings.simplefilter("always")
+ with pytest.warns(None) as warns:
+ der = encode_bitstring(b"\x00\xff", None)
+
+ # verify that new call convention doesn't raise Warnings
+ self.assertEqual(len(warns), 0)
+
+ self.assertEqual(der, b"\x03\x02\x00\xff")
+
+ def test_explicit_unused_bits(self):
+ der = encode_bitstring(b"\xff\xf0", 4)
+
+ self.assertEqual(der, b"\x03\x03\x04\xff\xf0")
+
+ def test_empty_string(self):
+ self.assertEqual(encode_bitstring(b"", 0), b"\x03\x01\x00")
+
+ def test_invalid_unused_count(self):
+ with self.assertRaises(ValueError):
+ encode_bitstring(b"\xff\x00", 8)
+
+ def test_invalid_unused_with_empty_string(self):
+ with self.assertRaises(ValueError):
+ encode_bitstring(b"", 1)
+
+ def test_non_zero_padding_bits(self):
+ with self.assertRaises(ValueError):
+ encode_bitstring(b"\xff", 2)
+
+
+class TestRemoveBitstring(unittest.TestCase):
+ def test_old_call_convention(self):
+ """This is the old way to call the function."""
+ warnings.simplefilter("always")
+ with pytest.warns(DeprecationWarning) as warns:
+ bits, rest = remove_bitstring(b"\x03\x02\x00\xff")
+
+ self.assertEqual(len(warns), 1)
+ self.assertIn(
+ "expect_unused= needs to be specified", warns[0].message.args[0]
+ )
+
+ self.assertEqual(bits, b"\x00\xff")
+ self.assertEqual(rest, b"")
+
+ def test_new_call_convention(self):
+ warnings.simplefilter("always")
+ with pytest.warns(None) as warns:
+ bits, rest = remove_bitstring(b"\x03\x02\x00\xff", 0)
+
+ self.assertEqual(len(warns), 0)
+
+ self.assertEqual(bits, b"\xff")
+ self.assertEqual(rest, b"")
+
+ def test_implicit_unexpected_unused(self):
+ warnings.simplefilter("always")
+ with pytest.warns(None) as warns:
+ bits, rest = remove_bitstring(b"\x03\x02\x00\xff", None)
+
+ self.assertEqual(len(warns), 0)
+
+ self.assertEqual(bits, (b"\xff", 0))
+ self.assertEqual(rest, b"")
+
+ def test_with_padding(self):
+ ret, rest = remove_bitstring(b"\x03\x02\x04\xf0", None)
+
+ self.assertEqual(ret, (b"\xf0", 4))
+ self.assertEqual(rest, b"")
+
+ def test_not_a_bitstring(self):
+ with self.assertRaises(UnexpectedDER):
+ remove_bitstring(b"\x02\x02\x00\xff", None)
+
+ def test_empty_encoding(self):
+ with self.assertRaises(UnexpectedDER):
+ remove_bitstring(b"\x03\x00", None)
+
+ def test_empty_string(self):
+ with self.assertRaises(UnexpectedDER):
+ remove_bitstring(b"", None)
+
+ def test_no_length(self):
+ with self.assertRaises(UnexpectedDER):
+ remove_bitstring(b"\x03", None)
+
+ def test_unexpected_number_of_unused_bits(self):
+ with self.assertRaises(UnexpectedDER):
+ remove_bitstring(b"\x03\x02\x00\xff", 1)
+
+ def test_invalid_encoding_of_unused_bits(self):
+ with self.assertRaises(UnexpectedDER):
+ remove_bitstring(b"\x03\x03\x08\xff\x00", None)
+
+ def test_invalid_encoding_of_empty_string(self):
+ with self.assertRaises(UnexpectedDER):
+ remove_bitstring(b"\x03\x01\x01", None)
+
+ def test_invalid_padding_bits(self):
+ with self.assertRaises(UnexpectedDER):
+ remove_bitstring(b"\x03\x02\x01\xff", None)
+
+
+class TestStrIdxAsInt(unittest.TestCase):
+ def test_str(self):
+ self.assertEqual(115, str_idx_as_int("str", 0))
+
+ def test_bytes(self):
+ self.assertEqual(115, str_idx_as_int(b"str", 0))
+
+ def test_bytearray(self):
+ self.assertEqual(115, str_idx_as_int(bytearray(b"str"), 0))
+
+
+class TestEncodeOid(unittest.TestCase):
+ def test_pub_key_oid(self):
+ oid_ecPublicKey = encode_oid(1, 2, 840, 10045, 2, 1)
+ self.assertEqual(hexlify(oid_ecPublicKey), b("06072a8648ce3d0201"))
+
+ def test_nist224p_oid(self):
+ self.assertEqual(hexlify(NIST224p.encoded_oid), b("06052b81040021"))
+
+ def test_nist256p_oid(self):
+ self.assertEqual(
+ hexlify(NIST256p.encoded_oid), b"06082a8648ce3d030107"
+ )
+
+ def test_large_second_subid(self):
+ # from X.690, section 8.19.5
+ oid = encode_oid(2, 999, 3)
+ self.assertEqual(oid, b"\x06\x03\x88\x37\x03")
+
+ def test_with_two_subids(self):
+ oid = encode_oid(2, 999)
+ self.assertEqual(oid, b"\x06\x02\x88\x37")
+
+ def test_zero_zero(self):
+ oid = encode_oid(0, 0)
+ self.assertEqual(oid, b"\x06\x01\x00")
+
+ def test_with_wrong_types(self):
+ with self.assertRaises((TypeError, AssertionError)):
+ encode_oid(0, None)
+
+ def test_with_small_first_large_second(self):
+ with self.assertRaises(AssertionError):
+ encode_oid(1, 40)
+
+ def test_small_first_max_second(self):
+ oid = encode_oid(1, 39)
+ self.assertEqual(oid, b"\x06\x01\x4f")
+
+ def test_with_invalid_first(self):
+ with self.assertRaises(AssertionError):
+ encode_oid(3, 39)
+
+
+class TestRemoveObject(unittest.TestCase):
+ @classmethod
+ def setUpClass(cls):
+ cls.oid_ecPublicKey = encode_oid(1, 2, 840, 10045, 2, 1)
+
+ def test_pub_key_oid(self):
+ oid, rest = remove_object(self.oid_ecPublicKey)
+ self.assertEqual(rest, b"")
+ self.assertEqual(oid, (1, 2, 840, 10045, 2, 1))
+
+ def test_with_extra_bytes(self):
+ oid, rest = remove_object(self.oid_ecPublicKey + b"more")
+ self.assertEqual(rest, b"more")
+ self.assertEqual(oid, (1, 2, 840, 10045, 2, 1))
+
+ def test_with_large_second_subid(self):
+ # from X.690, section 8.19.5
+ oid, rest = remove_object(b"\x06\x03\x88\x37\x03")
+ self.assertEqual(rest, b"")
+ self.assertEqual(oid, (2, 999, 3))
+
+ def test_with_padded_first_subid(self):
+ with self.assertRaises(UnexpectedDER):
+ remove_object(b"\x06\x02\x80\x00")
+
+ def test_with_padded_second_subid(self):
+ with self.assertRaises(UnexpectedDER):
+ remove_object(b"\x06\x04\x88\x37\x80\x01")
+
+ def test_with_missing_last_byte_of_multi_byte(self):
+ with self.assertRaises(UnexpectedDER):
+ remove_object(b"\x06\x03\x88\x37\x83")
+
+ def test_with_two_subids(self):
+ oid, rest = remove_object(b"\x06\x02\x88\x37")
+ self.assertEqual(rest, b"")
+ self.assertEqual(oid, (2, 999))
+
+ def test_zero_zero(self):
+ oid, rest = remove_object(b"\x06\x01\x00")
+ self.assertEqual(rest, b"")
+ self.assertEqual(oid, (0, 0))
+
+ def test_empty_string(self):
+ with self.assertRaises(UnexpectedDER):
+ remove_object(b"")
+
+ def test_missing_length(self):
+ with self.assertRaises(UnexpectedDER):
+ remove_object(b"\x06")
+
+ def test_empty_oid(self):
+ with self.assertRaises(UnexpectedDER):
+ remove_object(b"\x06\x00")
+
+ def test_empty_oid_overflow(self):
+ with self.assertRaises(UnexpectedDER):
+ remove_object(b"\x06\x01")
+
+ def test_with_wrong_type(self):
+ with self.assertRaises(UnexpectedDER):
+ remove_object(b"\x04\x02\x88\x37")
+
+ def test_with_too_long_length(self):
+ with self.assertRaises(UnexpectedDER):
+ remove_object(b"\x06\x03\x88\x37")
+
+
+def st_oid(draw, max_value=2 ** 512, max_size=50):
+ """
+ Hypothesis strategy that returns valid OBJECT IDENTIFIERs as tuples
+
+ :param max_value: maximum value of any single sub-identifier
+ :param max_size: maximum length of the generated OID
+ """
+ first = draw(st.integers(min_value=0, max_value=2))
+ if first < 2:
+ second = draw(st.integers(min_value=0, max_value=39))
+ else:
+ second = draw(st.integers(min_value=0, max_value=max_value))
+ rest = draw(
+ st.lists(
+ st.integers(min_value=0, max_value=max_value), max_size=max_size
+ )
+ )
+ return (first, second) + tuple(rest)
+
+
+@given(st_oid())
+def test_oids(ids):
+ encoded_oid = encode_oid(*ids)
+ decoded_oid, rest = remove_object(encoded_oid)
+ assert rest == b""
+ assert decoded_oid == ids
diff --git a/frozen_deps/ecdsa/test_ecdh.py b/frozen_deps/ecdsa/test_ecdh.py
new file mode 100644
index 0000000..caf6835
--- /dev/null
+++ b/frozen_deps/ecdsa/test_ecdh.py
@@ -0,0 +1,370 @@
+import os
+import shutil
+import subprocess
+import pytest
+from binascii import hexlify, unhexlify
+
+from .curves import NIST192p, NIST224p, NIST256p, NIST384p, NIST521p
+from .curves import curves
+from .ecdh import ECDH, InvalidCurveError, InvalidSharedSecretError, NoKeyError
+from .keys import SigningKey, VerifyingKey
+
+
+ "vcurve", curves, ids=[curve.name for curve in curves]
+)
+def test_ecdh_each(vcurve):
+ ecdh1 = ECDH(curve=vcurve)
+ ecdh2 = ECDH(curve=vcurve)
+
+ ecdh2.generate_private_key()
+ ecdh1.load_received_public_key(ecdh2.get_public_key())
+ ecdh2.load_received_public_key(ecdh1.generate_private_key())
+
+ secret1 = ecdh1.generate_sharedsecret_bytes()
+ secret2 = ecdh2.generate_sharedsecret_bytes()
+ assert secret1 == secret2
+
+
+def test_ecdh_no_public_key():
+ ecdh1 = ECDH(curve=NIST192p)
+
+ with pytest.raises(NoKeyError):
+ ecdh1.generate_sharedsecret_bytes()
+
+ ecdh1.generate_private_key()
+
+ with pytest.raises(NoKeyError):
+ ecdh1.generate_sharedsecret_bytes()
+
+
+def test_ecdh_wrong_public_key_curve():
+ ecdh1 = ECDH(curve=NIST192p)
+ ecdh1.generate_private_key()
+ ecdh2 = ECDH(curve=NIST256p)
+ ecdh2.generate_private_key()
+
+ with pytest.raises(InvalidCurveError):
+ ecdh1.load_received_public_key(ecdh2.get_public_key())
+
+ with pytest.raises(InvalidCurveError):
+ ecdh2.load_received_public_key(ecdh1.get_public_key())
+
+ ecdh1.public_key = ecdh2.get_public_key()
+ ecdh2.public_key = ecdh1.get_public_key()
+
+ with pytest.raises(InvalidCurveError):
+ ecdh1.generate_sharedsecret_bytes()
+
+ with pytest.raises(InvalidCurveError):
+ ecdh2.generate_sharedsecret_bytes()
+
+
+def test_ecdh_invalid_shared_secret_curve():
+ ecdh1 = ECDH(curve=NIST256p)
+ ecdh1.generate_private_key()
+
+ ecdh1.load_received_public_key(
+ SigningKey.generate(NIST256p).get_verifying_key()
+ )
+
+ ecdh1.private_key.privkey.secret_multiplier = ecdh1.private_key.curve.order
+
+ with pytest.raises(InvalidSharedSecretError):
+ ecdh1.generate_sharedsecret_bytes()
+
+
+# https://github.com/scogliani/ecc-test-vectors/blob/master/ecdh_kat/secp192r1.txt
+# https://github.com/scogliani/ecc-test-vectors/blob/master/ecdh_kat/secp256r1.txt
+# https://github.com/coruus/nist-testvectors/blob/master/csrc.nist.gov/groups/STM/cavp/documents/components/ecccdhtestvectors/KAS_ECC_CDH_PrimitiveTest.txt
+ "curve,privatekey,pubkey,secret",
+ [
+ pytest.param(
+ NIST192p,
+ "f17d3fea367b74d340851ca4270dcb24c271f445bed9d527",
+ "42ea6dd9969dd2a61fea1aac7f8e98edcc896c6e55857cc0"
+ "dfbe5d7c61fac88b11811bde328e8a0d12bf01a9d204b523",
+ "803d8ab2e5b6e6fca715737c3a82f7ce3c783124f6d51cd0",
+ id="NIST192p-1",
+ ),
+ pytest.param(
+ NIST192p,
+ "56e853349d96fe4c442448dacb7cf92bb7a95dcf574a9bd5",
+ "deb5712fa027ac8d2f22c455ccb73a91e17b6512b5e030e7"
+ "7e2690a02cc9b28708431a29fb54b87b1f0c14e011ac2125",
+ "c208847568b98835d7312cef1f97f7aa298283152313c29d",
+ id="NIST192p-2",
+ ),
+ pytest.param(
+ NIST192p,
+ "c6ef61fe12e80bf56f2d3f7d0bb757394519906d55500949",
+ "4edaa8efc5a0f40f843663ec5815e7762dddc008e663c20f"
+ "0a9f8dc67a3e60ef6d64b522185d03df1fc0adfd42478279",
+ "87229107047a3b611920d6e3b2c0c89bea4f49412260b8dd",
+ id="NIST192p-3",
+ ),
+ pytest.param(
+ NIST192p,
+ "e6747b9c23ba7044f38ff7e62c35e4038920f5a0163d3cda",
+ "8887c276edeed3e9e866b46d58d895c73fbd80b63e382e88"
+ "04c5097ba6645e16206cfb70f7052655947dd44a17f1f9d5",
+ "eec0bed8fc55e1feddc82158fd6dc0d48a4d796aaf47d46c",
+ id="NIST192p-4",
+ ),
+ pytest.param(
+ NIST192p,
+ "beabedd0154a1afcfc85d52181c10f5eb47adc51f655047d",
+ "0d045f30254adc1fcefa8a5b1f31bf4e739dd327cd18d594"
+ "542c314e41427c08278a08ce8d7305f3b5b849c72d8aff73",
+ "716e743b1b37a2cd8479f0a3d5a74c10ba2599be18d7e2f4",
+ id="NIST192p-5",
+ ),
+ pytest.param(
+ NIST192p,
+ "cf70354226667321d6e2baf40999e2fd74c7a0f793fa8699",
+ "fb35ca20d2e96665c51b98e8f6eb3d79113508d8bccd4516"
+ "368eec0d5bfb847721df6aaff0e5d48c444f74bf9cd8a5a7",
+ "f67053b934459985a315cb017bf0302891798d45d0e19508",
+ id="NIST192p-6",
+ ),
+ pytest.param(
+ NIST224p,
+ "8346a60fc6f293ca5a0d2af68ba71d1dd389e5e40837942df3e43cbd",
+ "af33cd0629bc7e996320a3f40368f74de8704fa37b8fab69abaae280"
+ "882092ccbba7930f419a8a4f9bb16978bbc3838729992559a6f2e2d7",
+ "7d96f9a3bd3c05cf5cc37feb8b9d5209d5c2597464dec3e9983743e8",
+ id="NIST224p",
+ ),
+ pytest.param(
+ NIST256p,
+ "7d7dc5f71eb29ddaf80d6214632eeae03d9058af1fb6d22ed80badb62bc1a534",
+ "700c48f77f56584c5cc632ca65640db91b6bacce3a4df6b42ce7cc838833d287"
+ "db71e509e3fd9b060ddb20ba5c51dcc5948d46fbf640dfe0441782cab85fa4ac",
+ "46fc62106420ff012e54a434fbdd2d25ccc5852060561e68040dd7778997bd7b",
+ id="NIST256p-1",
+ ),
+ pytest.param(
+ NIST256p,
+ "38f65d6dce47676044d58ce5139582d568f64bb16098d179dbab07741dd5caf5",
+ "809f04289c64348c01515eb03d5ce7ac1a8cb9498f5caa50197e58d43a86a7ae"
+ "b29d84e811197f25eba8f5194092cb6ff440e26d4421011372461f579271cda3",
+ "057d636096cb80b67a8c038c890e887d1adfa4195e9b3ce241c8a778c59cda67",
+ id="NIST256p-2",
+ ),
+ pytest.param(
+ NIST256p,
+ "1accfaf1b97712b85a6f54b148985a1bdc4c9bec0bd258cad4b3d603f49f32c8",
+ "a2339c12d4a03c33546de533268b4ad667debf458b464d77443636440ee7fec3"
+ "ef48a3ab26e20220bcda2c1851076839dae88eae962869a497bf73cb66faf536",
+ "2d457b78b4614132477618a5b077965ec90730a8c81a1c75d6d4ec68005d67ec",
+ id="NIST256p-3",
+ ),
+ pytest.param(
+ NIST256p,
+ "207c43a79bfee03db6f4b944f53d2fb76cc49ef1c9c4d34d51b6c65c4db6932d",
+ "df3989b9fa55495719b3cf46dccd28b5153f7808191dd518eff0c3cff2b705ed"
+ "422294ff46003429d739a33206c8752552c8ba54a270defc06e221e0feaf6ac4",
+ "96441259534b80f6aee3d287a6bb17b5094dd4277d9e294f8fe73e48bf2a0024",
+ id="NIST256p-4",
+ ),
+ pytest.param(
+ NIST256p,
+ "59137e38152350b195c9718d39673d519838055ad908dd4757152fd8255c09bf",
+ "41192d2813e79561e6a1d6f53c8bc1a433a199c835e141b05a74a97b0faeb922"
+ "1af98cc45e98a7e041b01cf35f462b7562281351c8ebf3ffa02e33a0722a1328",
+ "19d44c8d63e8e8dd12c22a87b8cd4ece27acdde04dbf47f7f27537a6999a8e62",
+ id="NIST256p-5",
+ ),
+ pytest.param(
+ NIST256p,
+ "f5f8e0174610a661277979b58ce5c90fee6c9b3bb346a90a7196255e40b132ef",
+ "33e82092a0f1fb38f5649d5867fba28b503172b7035574bf8e5b7100a3052792"
+ "f2cf6b601e0a05945e335550bf648d782f46186c772c0f20d3cd0d6b8ca14b2f",
+ "664e45d5bba4ac931cd65d52017e4be9b19a515f669bea4703542a2c525cd3d3",
+ id="NIST256p-6",
+ ),
+ pytest.param(
+ NIST384p,
+ "3cc3122a68f0d95027ad38c067916ba0eb8c38894d22e1b1"
+ "5618b6818a661774ad463b205da88cf699ab4d43c9cf98a1",
+ "a7c76b970c3b5fe8b05d2838ae04ab47697b9eaf52e76459"
+ "2efda27fe7513272734466b400091adbf2d68c58e0c50066"
+ "ac68f19f2e1cb879aed43a9969b91a0839c4c38a49749b66"
+ "1efedf243451915ed0905a32b060992b468c64766fc8437a",
+ "5f9d29dc5e31a163060356213669c8ce132e22f57c9a04f4"
+ "0ba7fcead493b457e5621e766c40a2e3d4d6a04b25e533f1",
+ id="NIST384p",
+ ),
+ pytest.param(
+ NIST521p,
+ "017eecc07ab4b329068fba65e56a1f8890aa935e57134ae0ffcce802735151f4ea"
+ "c6564f6ee9974c5e6887a1fefee5743ae2241bfeb95d5ce31ddcb6f9edb4d6fc47",
+ "00685a48e86c79f0f0875f7bc18d25eb5fc8c0b07e5da4f4370f3a949034085433"
+ "4b1e1b87fa395464c60626124a4e70d0f785601d37c09870ebf176666877a2046d"
+ "01ba52c56fc8776d9e8f5db4f0cc27636d0b741bbe05400697942e80b739884a83"
+ "bde99e0f6716939e632bc8986fa18dccd443a348b6c3e522497955a4f3c302f676",
+ "005fc70477c3e63bc3954bd0df3ea0d1f41ee21746ed95fc5e1fdf90930d5e1366"
+ "72d72cc770742d1711c3c3a4c334a0ad9759436a4d3c5bf6e74b9578fac148c831",
+ id="NIST521p",
+ ),
+ ],
+)
+def test_ecdh_NIST(curve, privatekey, pubkey, secret):
+ ecdh = ECDH(curve=curve)
+ ecdh.load_private_key_bytes(unhexlify(privatekey))
+ ecdh.load_received_public_key_bytes(unhexlify(pubkey))
+
+ sharedsecret = ecdh.generate_sharedsecret_bytes()
+
+ assert sharedsecret == unhexlify(secret)
+
+
+pem_local_private_key = (
+ "-----BEGIN EC PRIVATE KEY-----\n"
+ "MF8CAQEEGF7IQgvW75JSqULpiQQ8op9WH6Uldw6xxaAKBggqhkjOPQMBAaE0AzIA\n"
+ "BLiBd9CE7xf15FY5QIAoNg+fWbSk1yZOYtoGUdzkejWkxbRc9RWTQjqLVXucIJnz\n"
+ "bA==\n"
+ "-----END EC PRIVATE KEY-----\n"
+)
+der_local_private_key = (
+ "305f02010104185ec8420bd6ef9252a942e989043ca29f561fa525770eb1c5a00a06082a864"
+ "8ce3d030101a13403320004b88177d084ef17f5e45639408028360f9f59b4a4d7264e62da06"
+ "51dce47a35a4c5b45cf51593423a8b557b9c2099f36c"
+)
+pem_remote_public_key = (
+ "-----BEGIN PUBLIC KEY-----\n"
+ "MEkwEwYHKoZIzj0CAQYIKoZIzj0DAQEDMgAEuIF30ITvF/XkVjlAgCg2D59ZtKTX\n"
+ "Jk5i2gZR3OR6NaTFtFz1FZNCOotVe5wgmfNs\n"
+ "-----END PUBLIC KEY-----\n"
+)
+der_remote_public_key = (
+ "3049301306072a8648ce3d020106082a8648ce3d03010103320004b88177d084ef17f5e4563"
+ "9408028360f9f59b4a4d7264e62da0651dce47a35a4c5b45cf51593423a8b557b9c2099f36c"
+)
+gshared_secret = "8f457e34982478d1c34b9cd2d0c15911b72dd60d869e2cea"
+
+
+def test_ecdh_pem():
+ ecdh = ECDH()
+ ecdh.load_private_key_pem(pem_local_private_key)
+ ecdh.load_received_public_key_pem(pem_remote_public_key)
+
+ sharedsecret = ecdh.generate_sharedsecret_bytes()
+
+ assert sharedsecret == unhexlify(gshared_secret)
+
+
+def test_ecdh_der():
+ ecdh = ECDH()
+ ecdh.load_private_key_der(unhexlify(der_local_private_key))
+ ecdh.load_received_public_key_der(unhexlify(der_remote_public_key))
+
+ sharedsecret = ecdh.generate_sharedsecret_bytes()
+
+ assert sharedsecret == unhexlify(gshared_secret)
+
+
+# Exception classes used by run_openssl.
+class RunOpenSslError(Exception):
+ pass
+
+
+def run_openssl(cmd):
+ OPENSSL = "openssl"
+ p = subprocess.Popen(
+ [OPENSSL] + cmd.split(),
+ stdout=subprocess.PIPE,
+ stderr=subprocess.STDOUT,
+ )
+ stdout, ignored = p.communicate()
+ if p.returncode != 0:
+ raise RunOpenSslError(
+ "cmd '%s %s' failed: rc=%s, stdout/err was %s"
+ % (OPENSSL, cmd, p.returncode, stdout)
+ )
+ return stdout.decode()
+
+
+OPENSSL_SUPPORTED_CURVES = set(
+ c.split(":")[0].strip()
+ for c in run_openssl("ecparam -list_curves").split("\n")
+)
+
+
+ "vcurve", curves, ids=[curve.name for curve in curves]
+)
+def test_ecdh_with_openssl(vcurve):
+ assert vcurve.openssl_name
+
+ if vcurve.openssl_name not in OPENSSL_SUPPORTED_CURVES:
+ pytest.skip("system openssl does not support " + vcurve.openssl_name)
+ return
+
+ try:
+ hlp = run_openssl("pkeyutl -help")
+ if hlp.find("-derive") == 0:
+ pytest.skip("system openssl does not support `pkeyutl -derive`")
+ return
+ except RunOpenSslError:
+ pytest.skip("system openssl does not support `pkeyutl -derive`")
+ return
+
+ if os.path.isdir("t"):
+ shutil.rmtree("t")
+ os.mkdir("t")
+ run_openssl(
+ "ecparam -name %s -genkey -out t/privkey1.pem" % vcurve.openssl_name
+ )
+ run_openssl(
+ "ecparam -name %s -genkey -out t/privkey2.pem" % vcurve.openssl_name
+ )
+ run_openssl("ec -in t/privkey1.pem -pubout -out t/pubkey1.pem")
+
+ ecdh1 = ECDH(curve=vcurve)
+ ecdh2 = ECDH(curve=vcurve)
+ with open("t/privkey1.pem") as e:
+ key = e.read()
+ ecdh1.load_private_key_pem(key)
+ with open("t/privkey2.pem") as e:
+ key = e.read()
+ ecdh2.load_private_key_pem(key)
+
+ with open("t/pubkey1.pem") as e:
+ key = e.read()
+ vk1 = VerifyingKey.from_pem(key)
+ assert vk1.to_string() == ecdh1.get_public_key().to_string()
+ vk2 = ecdh2.get_public_key()
+ with open("t/pubkey2.pem", "wb") as e:
+ e.write(vk2.to_pem())
+
+ ecdh1.load_received_public_key(vk2)
+ ecdh2.load_received_public_key(vk1)
+ secret1 = ecdh1.generate_sharedsecret_bytes()
+ secret2 = ecdh2.generate_sharedsecret_bytes()
+
+ assert secret1 == secret2
+
+ try:
+ run_openssl(
+ "pkeyutl -derive -inkey t/privkey1.pem -peerkey t/pubkey2.pem -out t/secret1"
+ )
+ run_openssl(
+ "pkeyutl -derive -inkey t/privkey2.pem -peerkey t/pubkey1.pem -out t/secret2"
+ )
+ except RunOpenSslError:
+ pytest.skip("system openssl does not support `pkeyutl -derive`")
+ return
+
+ with open("t/secret1", "rb") as e:
+ ssl_secret1 = e.read()
+ with open("t/secret1", "rb") as e:
+ ssl_secret2 = e.read()
+
+ if len(ssl_secret1) != vk1.curve.baselen:
+ pytest.skip("system openssl does not support `pkeyutl -derive`")
+ return
+
+ assert ssl_secret1 == ssl_secret2
+ assert secret1 == ssl_secret1
diff --git a/frozen_deps/ecdsa/test_ecdsa.py b/frozen_deps/ecdsa/test_ecdsa.py
new file mode 100644
index 0000000..e656b88
--- /dev/null
+++ b/frozen_deps/ecdsa/test_ecdsa.py
@@ -0,0 +1,538 @@
+from __future__ import print_function
+import sys
+import hypothesis.strategies as st
+from hypothesis import given, settings, note, example
+
+try:
+ import unittest2 as unittest
+except ImportError:
+ import unittest
+import pytest
+from .ecdsa import (
+ Private_key,
+ Public_key,
+ Signature,
+ generator_192,
+ digest_integer,
+ ellipticcurve,
+ point_is_valid,
+ generator_224,
+ generator_256,
+ generator_384,
+ generator_521,
+ generator_secp256k1,
+)
+
+
+HYP_SETTINGS = {}
+# old hypothesis doesn't have the "deadline" setting
+if sys.version_info > (2, 7): # pragma: no branch
+ # SEC521p is slow, allow long execution for it
+ HYP_SETTINGS["deadline"] = 5000
+
+
+class TestP192FromX9_62(unittest.TestCase):
+ """Check test vectors from X9.62"""
+
+ @classmethod
+ def setUpClass(cls):
+ cls.d = 651056770906015076056810763456358567190100156695615665659
+ cls.Q = cls.d * generator_192
+ cls.k = 6140507067065001063065065565667405560006161556565665656654
+ cls.R = cls.k * generator_192
+
+ cls.msg = 968236873715988614170569073515315707566766479517
+ cls.pubk = Public_key(generator_192, generator_192 * cls.d)
+ cls.privk = Private_key(cls.pubk, cls.d)
+ cls.sig = cls.privk.sign(cls.msg, cls.k)
+
+ def test_point_multiplication(self):
+ assert self.Q.x() == 0x62B12D60690CDCF330BABAB6E69763B471F994DD702D16A5
+
+ def test_point_multiplication_2(self):
+ assert self.R.x() == 0x885052380FF147B734C330C43D39B2C4A89F29B0F749FEAD
+ assert self.R.y() == 0x9CF9FA1CBEFEFB917747A3BB29C072B9289C2547884FD835
+
+ def test_mult_and_addition(self):
+ u1 = 2563697409189434185194736134579731015366492496392189760599
+ u2 = 6266643813348617967186477710235785849136406323338782220568
+ temp = u1 * generator_192 + u2 * self.Q
+ assert temp.x() == 0x885052380FF147B734C330C43D39B2C4A89F29B0F749FEAD
+ assert temp.y() == 0x9CF9FA1CBEFEFB917747A3BB29C072B9289C2547884FD835
+
+ def test_signature(self):
+ r, s = self.sig.r, self.sig.s
+ assert r == 3342403536405981729393488334694600415596881826869351677613
+ assert s == 5735822328888155254683894997897571951568553642892029982342
+
+ def test_verification(self):
+ assert self.pubk.verifies(self.msg, self.sig)
+
+ def test_rejection(self):
+ assert not self.pubk.verifies(self.msg - 1, self.sig)
+
+
+class TestPublicKey(unittest.TestCase):
+ def test_equality_public_keys(self):
+ gen = generator_192
+ x = 0xC58D61F88D905293BCD4CD0080BCB1B7F811F2FFA41979F6
+ y = 0x8804DC7A7C4C7F8B5D437F5156F3312CA7D6DE8A0E11867F
+ point = ellipticcurve.Point(gen.curve(), x, y)
+ pub_key1 = Public_key(gen, point)
+ pub_key2 = Public_key(gen, point)
+ self.assertEqual(pub_key1, pub_key2)
+
+ def test_inequality_public_key(self):
+ gen = generator_192
+ x1 = 0xC58D61F88D905293BCD4CD0080BCB1B7F811F2FFA41979F6
+ y1 = 0x8804DC7A7C4C7F8B5D437F5156F3312CA7D6DE8A0E11867F
+ point1 = ellipticcurve.Point(gen.curve(), x1, y1)
+
+ x2 = 0x6A223D00BD22C52833409A163E057E5B5DA1DEF2A197DD15
+ y2 = 0x7B482604199367F1F303F9EF627F922F97023E90EAE08ABF
+ point2 = ellipticcurve.Point(gen.curve(), x2, y2)
+
+ pub_key1 = Public_key(gen, point1)
+ pub_key2 = Public_key(gen, point2)
+ self.assertNotEqual(pub_key1, pub_key2)
+
+ def test_inequality_public_key_not_implemented(self):
+ gen = generator_192
+ x = 0xC58D61F88D905293BCD4CD0080BCB1B7F811F2FFA41979F6
+ y = 0x8804DC7A7C4C7F8B5D437F5156F3312CA7D6DE8A0E11867F
+ point = ellipticcurve.Point(gen.curve(), x, y)
+ pub_key = Public_key(gen, point)
+ self.assertNotEqual(pub_key, None)
+
+
+class TestPrivateKey(unittest.TestCase):
+ @classmethod
+ def setUpClass(cls):
+ gen = generator_192
+ x = 0xC58D61F88D905293BCD4CD0080BCB1B7F811F2FFA41979F6
+ y = 0x8804DC7A7C4C7F8B5D437F5156F3312CA7D6DE8A0E11867F
+ point = ellipticcurve.Point(gen.curve(), x, y)
+ cls.pub_key = Public_key(gen, point)
+
+ def test_equality_private_keys(self):
+ pr_key1 = Private_key(self.pub_key, 100)
+ pr_key2 = Private_key(self.pub_key, 100)
+ self.assertEqual(pr_key1, pr_key2)
+
+ def test_inequality_private_keys(self):
+ pr_key1 = Private_key(self.pub_key, 100)
+ pr_key2 = Private_key(self.pub_key, 200)
+ self.assertNotEqual(pr_key1, pr_key2)
+
+ def test_inequality_private_keys_not_implemented(self):
+ pr_key = Private_key(self.pub_key, 100)
+ self.assertNotEqual(pr_key, None)
+
+
+# Testing point validity, as per ECDSAVS.pdf B.2.2:
+P192_POINTS = [
+ (
+ generator_192,
+ 0xCD6D0F029A023E9AACA429615B8F577ABEE685D8257CC83A,
+ 0x00019C410987680E9FB6C0B6ECC01D9A2647C8BAE27721BACDFC,
+ False,
+ ),
+ (
+ generator_192,
+ 0x00017F2FCE203639E9EAF9FB50B81FC32776B30E3B02AF16C73B,
+ 0x95DA95C5E72DD48E229D4748D4EEE658A9A54111B23B2ADB,
+ False,
+ ),
+ (
+ generator_192,
+ 0x4F77F8BC7FCCBADD5760F4938746D5F253EE2168C1CF2792,
+ 0x000147156FF824D131629739817EDB197717C41AAB5C2A70F0F6,
+ False,
+ ),
+ (
+ generator_192,
+ 0xC58D61F88D905293BCD4CD0080BCB1B7F811F2FFA41979F6,
+ 0x8804DC7A7C4C7F8B5D437F5156F3312CA7D6DE8A0E11867F,
+ True,
+ ),
+ (
+ generator_192,
+ 0xCDF56C1AA3D8AFC53C521ADF3FFB96734A6A630A4A5B5A70,
+ 0x97C1C44A5FB229007B5EC5D25F7413D170068FFD023CAA4E,
+ True,
+ ),
+ (
+ generator_192,
+ 0x89009C0DC361C81E99280C8E91DF578DF88CDF4B0CDEDCED,
+ 0x27BE44A529B7513E727251F128B34262A0FD4D8EC82377B9,
+ True,
+ ),
+ (
+ generator_192,
+ 0x6A223D00BD22C52833409A163E057E5B5DA1DEF2A197DD15,
+ 0x7B482604199367F1F303F9EF627F922F97023E90EAE08ABF,
+ True,
+ ),
+ (
+ generator_192,
+ 0x6DCCBDE75C0948C98DAB32EA0BC59FE125CF0FB1A3798EDA,
+ 0x0001171A3E0FA60CF3096F4E116B556198DE430E1FBD330C8835,
+ False,
+ ),
+ (
+ generator_192,
+ 0xD266B39E1F491FC4ACBBBC7D098430931CFA66D55015AF12,
+ 0x193782EB909E391A3148B7764E6B234AA94E48D30A16DBB2,
+ False,
+ ),
+ (
+ generator_192,
+ 0x9D6DDBCD439BAA0C6B80A654091680E462A7D1D3F1FFEB43,
+ 0x6AD8EFC4D133CCF167C44EB4691C80ABFFB9F82B932B8CAA,
+ False,
+ ),
+ (
+ generator_192,
+ 0x146479D944E6BDA87E5B35818AA666A4C998A71F4E95EDBC,
+ 0xA86D6FE62BC8FBD88139693F842635F687F132255858E7F6,
+ False,
+ ),
+ (
+ generator_192,
+ 0xE594D4A598046F3598243F50FD2C7BD7D380EDB055802253,
+ 0x509014C0C4D6B536E3CA750EC09066AF39B4C8616A53A923,
+ False,
+ ),
+]
+
+
[email protected]("generator,x,y,expected", P192_POINTS)
+def test_point_validity(generator, x, y, expected):
+ """
+ `generator` defines the curve; is `(x, y)` a point on
+ this curve? `expected` is True if the right answer is Yes.
+ """
+ assert point_is_valid(generator, x, y) == expected
+
+
+# Trying signature-verification tests from ECDSAVS.pdf B.2.4:
+CURVE_192_KATS = [
+ (
+ generator_192,
+ int(
+ "0x84ce72aa8699df436059f052ac51b6398d2511e49631bcb7e71f89c499b9ee"
+ "425dfbc13a5f6d408471b054f2655617cbbaf7937b7c80cd8865cf02c8487d30"
+ "d2b0fbd8b2c4e102e16d828374bbc47b93852f212d5043c3ea720f086178ff79"
+ "8cc4f63f787b9c2e419efa033e7644ea7936f54462dc21a6c4580725f7f0e7d1"
+ "58",
+ 16,
+ ),
+ 0xD9DBFB332AA8E5FF091E8CE535857C37C73F6250FFB2E7AC,
+ 0x282102E364FEDED3AD15DDF968F88D8321AA268DD483EBC4,
+ 0x64DCA58A20787C488D11D6DD96313F1B766F2D8EFE122916,
+ 0x1ECBA28141E84AB4ECAD92F56720E2CC83EB3D22DEC72479,
+ True,
+ ),
+ (
+ generator_192,
+ int(
+ "0x94bb5bacd5f8ea765810024db87f4224ad71362a3c28284b2b9f39fab86db1"
+ "2e8beb94aae899768229be8fdb6c4f12f28912bb604703a79ccff769c1607f5a"
+ "91450f30ba0460d359d9126cbd6296be6d9c4bb96c0ee74cbb44197c207f6db3"
+ "26ab6f5a659113a9034e54be7b041ced9dcf6458d7fb9cbfb2744d999f7dfd63"
+ "f4",
+ 16,
+ ),
+ 0x3E53EF8D3112AF3285C0E74842090712CD324832D4277AE7,
+ 0xCC75F8952D30AEC2CBB719FC6AA9934590B5D0FF5A83ADB7,
+ 0x8285261607283BA18F335026130BAB31840DCFD9C3E555AF,
+ 0x356D89E1B04541AFC9704A45E9C535CE4A50929E33D7E06C,
+ True,
+ ),
+ (
+ generator_192,
+ int(
+ "0xf6227a8eeb34afed1621dcc89a91d72ea212cb2f476839d9b4243c66877911"
+ "b37b4ad6f4448792a7bbba76c63bdd63414b6facab7dc71c3396a73bd7ee14cd"
+ "d41a659c61c99b779cecf07bc51ab391aa3252386242b9853ea7da67fd768d30"
+ "3f1b9b513d401565b6f1eb722dfdb96b519fe4f9bd5de67ae131e64b40e78c42"
+ "dd",
+ 16,
+ ),
+ 0x16335DBE95F8E8254A4E04575D736BEFB258B8657F773CB7,
+ 0x421B13379C59BC9DCE38A1099CA79BBD06D647C7F6242336,
+ 0x4141BD5D64EA36C5B0BD21EF28C02DA216ED9D04522B1E91,
+ 0x159A6AA852BCC579E821B7BB0994C0861FB08280C38DAA09,
+ False,
+ ),
+ (
+ generator_192,
+ int(
+ "0x16b5f93afd0d02246f662761ed8e0dd9504681ed02a253006eb36736b56309"
+ "7ba39f81c8e1bce7a16c1339e345efabbc6baa3efb0612948ae51103382a8ee8"
+ "bc448e3ef71e9f6f7a9676694831d7f5dd0db5446f179bcb737d4a526367a447"
+ "bfe2c857521c7f40b6d7d7e01a180d92431fb0bbd29c04a0c420a57b3ed26ccd"
+ "8a",
+ 16,
+ ),
+ 0xFD14CDF1607F5EFB7B1793037B15BDF4BAA6F7C16341AB0B,
+ 0x83FA0795CC6C4795B9016DAC928FD6BAC32F3229A96312C4,
+ 0x8DFDB832951E0167C5D762A473C0416C5C15BC1195667DC1,
+ 0x1720288A2DC13FA1EC78F763F8FE2FF7354A7E6FDDE44520,
+ False,
+ ),
+ (
+ generator_192,
+ int(
+ "0x08a2024b61b79d260e3bb43ef15659aec89e5b560199bc82cf7c65c77d3919"
+ "2e03b9a895d766655105edd9188242b91fbde4167f7862d4ddd61e5d4ab55196"
+ "683d4f13ceb90d87aea6e07eb50a874e33086c4a7cb0273a8e1c4408f4b846bc"
+ "eae1ebaac1b2b2ea851a9b09de322efe34cebe601653efd6ddc876ce8c2f2072"
+ "fb",
+ 16,
+ ),
+ 0x674F941DC1A1F8B763C9334D726172D527B90CA324DB8828,
+ 0x65ADFA32E8B236CB33A3E84CF59BFB9417AE7E8EDE57A7FF,
+ 0x9508B9FDD7DAF0D8126F9E2BC5A35E4C6D800B5B804D7796,
+ 0x36F2BF6B21B987C77B53BB801B3435A577E3D493744BFAB0,
+ False,
+ ),
+ (
+ generator_192,
+ int(
+ "0x1843aba74b0789d4ac6b0b8923848023a644a7b70afa23b1191829bbe4397c"
+ "e15b629bf21a8838298653ed0c19222b95fa4f7390d1b4c844d96e645537e0aa"
+ "e98afb5c0ac3bd0e4c37f8daaff25556c64e98c319c52687c904c4de7240a1cc"
+ "55cd9756b7edaef184e6e23b385726e9ffcba8001b8f574987c1a3fedaaa83ca"
+ "6d",
+ 16,
+ ),
+ 0x10ECCA1AAD7220B56A62008B35170BFD5E35885C4014A19F,
+ 0x04EB61984C6C12ADE3BC47F3C629ECE7AA0A033B9948D686,
+ 0x82BFA4E82C0DFE9274169B86694E76CE993FD83B5C60F325,
+ 0xA97685676C59A65DBDE002FE9D613431FB183E8006D05633,
+ False,
+ ),
+ (
+ generator_192,
+ int(
+ "0x5a478f4084ddd1a7fea038aa9732a822106385797d02311aeef4d0264f824f"
+ "698df7a48cfb6b578cf3da416bc0799425bb491be5b5ecc37995b85b03420a98"
+ "f2c4dc5c31a69a379e9e322fbe706bbcaf0f77175e05cbb4fa162e0da82010a2"
+ "78461e3e974d137bc746d1880d6eb02aa95216014b37480d84b87f717bb13f76"
+ "e1",
+ 16,
+ ),
+ 0x6636653CB5B894CA65C448277B29DA3AD101C4C2300F7C04,
+ 0xFDF1CBB3FC3FD6A4F890B59E554544175FA77DBDBEB656C1,
+ 0xEAC2DDECDDFB79931A9C3D49C08DE0645C783A24CB365E1C,
+ 0x3549FEE3CFA7E5F93BC47D92D8BA100E881A2A93C22F8D50,
+ False,
+ ),
+ (
+ generator_192,
+ int(
+ "0xc598774259a058fa65212ac57eaa4f52240e629ef4c310722088292d1d4af6"
+ "c39b49ce06ba77e4247b20637174d0bd67c9723feb57b5ead232b47ea452d5d7"
+ "a089f17c00b8b6767e434a5e16c231ba0efa718a340bf41d67ea2d295812ff1b"
+ "9277daacb8bc27b50ea5e6443bcf95ef4e9f5468fe78485236313d53d1c68f6b"
+ "a2",
+ 16,
+ ),
+ 0xA82BD718D01D354001148CD5F69B9EBF38FF6F21898F8AAA,
+ 0xE67CEEDE07FC2EBFAFD62462A51E4B6C6B3D5B537B7CAF3E,
+ 0x4D292486C620C3DE20856E57D3BB72FCDE4A73AD26376955,
+ 0xA85289591A6081D5728825520E62FF1C64F94235C04C7F95,
+ False,
+ ),
+ (
+ generator_192,
+ int(
+ "0xca98ed9db081a07b7557f24ced6c7b9891269a95d2026747add9e9eb80638a"
+ "961cf9c71a1b9f2c29744180bd4c3d3db60f2243c5c0b7cc8a8d40a3f9a7fc91"
+ "0250f2187136ee6413ffc67f1a25e1c4c204fa9635312252ac0e0481d89b6d53"
+ "808f0c496ba87631803f6c572c1f61fa049737fdacce4adff757afed4f05beb6"
+ "58",
+ 16,
+ ),
+ 0x7D3B016B57758B160C4FCA73D48DF07AE3B6B30225126C2F,
+ 0x4AF3790D9775742BDE46F8DA876711BE1B65244B2B39E7EC,
+ 0x95F778F5F656511A5AB49A5D69DDD0929563C29CBC3A9E62,
+ 0x75C87FC358C251B4C83D2DD979FAAD496B539F9F2EE7A289,
+ False,
+ ),
+ (
+ generator_192,
+ int(
+ "0x31dd9a54c8338bea06b87eca813d555ad1850fac9742ef0bbe40dad400e102"
+ "88acc9c11ea7dac79eb16378ebea9490e09536099f1b993e2653cd50240014c9"
+ "0a9c987f64545abc6a536b9bd2435eb5e911fdfde2f13be96ea36ad38df4ae9e"
+ "a387b29cced599af777338af2794820c9cce43b51d2112380a35802ab7e396c9"
+ "7a",
+ 16,
+ ),
+ 0x9362F28C4EF96453D8A2F849F21E881CD7566887DA8BEB4A,
+ 0xE64D26D8D74C48A024AE85D982EE74CD16046F4EE5333905,
+ 0xF3923476A296C88287E8DE914B0B324AD5A963319A4FE73B,
+ 0xF0BAEED7624ED00D15244D8BA2AEDE085517DBDEC8AC65F5,
+ True,
+ ),
+ (
+ generator_192,
+ int(
+ "0xb2b94e4432267c92f9fdb9dc6040c95ffa477652761290d3c7de312283f645"
+ "0d89cc4aabe748554dfb6056b2d8e99c7aeaad9cdddebdee9dbc099839562d90"
+ "64e68e7bb5f3a6bba0749ca9a538181fc785553a4000785d73cc207922f63e8c"
+ "e1112768cb1de7b673aed83a1e4a74592f1268d8e2a4e9e63d414b5d442bd045"
+ "6d",
+ 16,
+ ),
+ 0xCC6FC032A846AAAC25533EB033522824F94E670FA997ECEF,
+ 0xE25463EF77A029ECCDA8B294FD63DD694E38D223D30862F1,
+ 0x066B1D07F3A40E679B620EDA7F550842A35C18B80C5EBE06,
+ 0xA0B0FB201E8F2DF65E2C4508EF303BDC90D934016F16B2DC,
+ False,
+ ),
+ (
+ generator_192,
+ int(
+ "0x4366fcadf10d30d086911de30143da6f579527036937007b337f7282460eae"
+ "5678b15cccda853193ea5fc4bc0a6b9d7a31128f27e1214988592827520b214e"
+ "ed5052f7775b750b0c6b15f145453ba3fee24a085d65287e10509eb5d5f602c4"
+ "40341376b95c24e5c4727d4b859bfe1483d20538acdd92c7997fa9c614f0f839"
+ "d7",
+ 16,
+ ),
+ 0x955C908FE900A996F7E2089BEE2F6376830F76A19135E753,
+ 0xBA0C42A91D3847DE4A592A46DC3FDAF45A7CC709B90DE520,
+ 0x1F58AD77FC04C782815A1405B0925E72095D906CBF52A668,
+ 0xF2E93758B3AF75EDF784F05A6761C9B9A6043C66B845B599,
+ False,
+ ),
+ (
+ generator_192,
+ int(
+ "0x543f8af57d750e33aa8565e0cae92bfa7a1ff78833093421c2942cadf99866"
+ "70a5ff3244c02a8225e790fbf30ea84c74720abf99cfd10d02d34377c3d3b412"
+ "69bea763384f372bb786b5846f58932defa68023136cd571863b304886e95e52"
+ "e7877f445b9364b3f06f3c28da12707673fecb4b8071de06b6e0a3c87da160ce"
+ "f3",
+ 16,
+ ),
+ 0x31F7FA05576D78A949B24812D4383107A9A45BB5FCCDD835,
+ 0x8DC0EB65994A90F02B5E19BD18B32D61150746C09107E76B,
+ 0xBE26D59E4E883DDE7C286614A767B31E49AD88789D3A78FF,
+ 0x8762CA831C1CE42DF77893C9B03119428E7A9B819B619068,
+ False,
+ ),
+ (
+ generator_192,
+ int(
+ "0xd2e8454143ce281e609a9d748014dcebb9d0bc53adb02443a6aac2ffe6cb009f"
+ "387c346ecb051791404f79e902ee333ad65e5c8cb38dc0d1d39a8dc90add502357"
+ "2720e5b94b190d43dd0d7873397504c0c7aef2727e628eb6a74411f2e400c65670"
+ "716cb4a815dc91cbbfeb7cfe8c929e93184c938af2c078584da045e8f8d1",
+ 16,
+ ),
+ 0x66AA8EDBBDB5CF8E28CEB51B5BDA891CAE2DF84819FE25C0,
+ 0x0C6BC2F69030A7CE58D4A00E3B3349844784A13B8936F8DA,
+ 0xA4661E69B1734F4A71B788410A464B71E7FFE42334484F23,
+ 0x738421CF5E049159D69C57A915143E226CAC8355E149AFE9,
+ False,
+ ),
+ (
+ generator_192,
+ int(
+ "0x6660717144040f3e2f95a4e25b08a7079c702a8b29babad5a19a87654bc5c5af"
+ "a261512a11b998a4fb36b5d8fe8bd942792ff0324b108120de86d63f65855e5461"
+ "184fc96a0a8ffd2ce6d5dfb0230cbbdd98f8543e361b3205f5da3d500fdc8bac6d"
+ "b377d75ebef3cb8f4d1ff738071ad0938917889250b41dd1d98896ca06fb",
+ 16,
+ ),
+ 0xBCFACF45139B6F5F690A4C35A5FFFA498794136A2353FC77,
+ 0x6F4A6C906316A6AFC6D98FE1F0399D056F128FE0270B0F22,
+ 0x9DB679A3DAFE48F7CCAD122933ACFE9DA0970B71C94C21C1,
+ 0x984C2DB99827576C0A41A5DA41E07D8CC768BC82F18C9DA9,
+ False,
+ ),
+]
+
+
[email protected]("gen,msg,qx,qy,r,s,expected", CURVE_192_KATS)
+def test_signature_validity(gen, msg, qx, qy, r, s, expected):
+ """
+ `msg` = message, `qx` and `qy` represent the base point on
+ elliptic curve of `gen`, `r` and `s` are the signature, and
+ `expected` is True iff the signature is expected to be valid."""
+ pubk = Public_key(gen, ellipticcurve.Point(gen.curve(), qx, qy))
+ assert expected == pubk.verifies(digest_integer(msg), Signature(r, s))
+
+
+ "gen,msg,qx,qy,r,s,expected", [x for x in CURVE_192_KATS if x[6]]
+)
+def test_pk_recovery(gen, msg, r, s, qx, qy, expected):
+ del expected
+ sign = Signature(r, s)
+ pks = sign.recover_public_keys(digest_integer(msg), gen)
+
+ assert pks
+
+ # Test if the signature is valid for all found public keys
+ for pk in pks:
+ q = pk.point
+ test_signature_validity(gen, msg, q.x(), q.y(), r, s, True)
+
+ # Test if the original public key is in the set of found keys
+ original_q = ellipticcurve.Point(gen.curve(), qx, qy)
+ points = [pk.point for pk in pks]
+ assert original_q in points
+
+
+def st_random_gen_key_msg_nonce(draw):
+ """Hypothesis strategy for test_sig_verify()."""
+ name_gen = {
+ "generator_192": generator_192,
+ "generator_224": generator_224,
+ "generator_256": generator_256,
+ "generator_secp256k1": generator_secp256k1,
+ "generator_384": generator_384,
+ "generator_521": generator_521,
+ }
+ name = draw(st.sampled_from(sorted(name_gen.keys())))
+ note("Generator used: {0}".format(name))
+ generator = name_gen[name]
+ order = int(generator.order())
+
+ key = draw(st.integers(min_value=1, max_value=order))
+ msg = draw(st.integers(min_value=1, max_value=order))
+ nonce = draw(
+ st.integers(min_value=1, max_value=order + 1)
+ | st.integers(min_value=order >> 1, max_value=order)
+ )
+ return generator, key, msg, nonce
+
+
+SIG_VER_SETTINGS = dict(HYP_SETTINGS)
+SIG_VER_SETTINGS["max_examples"] = 10
+
+
+@settings(**SIG_VER_SETTINGS)
+@example((generator_224, 4, 1, 1))
+@given(st_random_gen_key_msg_nonce())
+def test_sig_verify(args):
+ """
+ Check if signing and verification works for arbitrary messages and
+ that signatures for other messages are rejected.
+ """
+ generator, sec_mult, msg, nonce = args
+
+ pubkey = Public_key(generator, generator * sec_mult)
+ privkey = Private_key(pubkey, sec_mult)
+
+ signature = privkey.sign(msg, nonce)
+
+ assert pubkey.verifies(msg, signature)
+
+ assert not pubkey.verifies(msg - 1, signature)
diff --git a/frozen_deps/ecdsa/test_ellipticcurve.py b/frozen_deps/ecdsa/test_ellipticcurve.py
new file mode 100644
index 0000000..def53b2
--- /dev/null
+++ b/frozen_deps/ecdsa/test_ellipticcurve.py
@@ -0,0 +1,200 @@
+import pytest
+from six import print_
+
+try:
+ import unittest2 as unittest
+except ImportError:
+ import unittest
+from hypothesis import given, settings
+import hypothesis.strategies as st
+
+try:
+ from hypothesis import HealthCheck
+
+ HC_PRESENT = True
+except ImportError: # pragma: no cover
+ HC_PRESENT = False
+from .numbertheory import inverse_mod
+from .ellipticcurve import CurveFp, INFINITY, Point
+
+
+HYP_SETTINGS = {}
+if HC_PRESENT: # pragma: no branch
+ HYP_SETTINGS["suppress_health_check"] = [HealthCheck.too_slow]
+ HYP_SETTINGS["deadline"] = 5000
+
+
+# NIST Curve P-192:
+p = 6277101735386680763835789423207666416083908700390324961279
+r = 6277101735386680763835789423176059013767194773182842284081
+# s = 0x3045ae6fc8422f64ed579528d38120eae12196d5
+# c = 0x3099d2bbbfcb2538542dcd5fb078b6ef5f3d6fe2c745de65
+b = 0x64210519E59C80E70FA7E9AB72243049FEB8DEECC146B9B1
+Gx = 0x188DA80EB03090F67CBF20EB43A18800F4FF0AFD82FF1012
+Gy = 0x07192B95FFC8DA78631011ED6B24CDD573F977A11E794811
+
+c192 = CurveFp(p, -3, b)
+p192 = Point(c192, Gx, Gy, r)
+
+c_23 = CurveFp(23, 1, 1)
+g_23 = Point(c_23, 13, 7, 7)
+
+
+HYP_SLOW_SETTINGS = dict(HYP_SETTINGS)
+HYP_SLOW_SETTINGS["max_examples"] = 10
+
+
+@settings(**HYP_SLOW_SETTINGS)
+@given(st.integers(min_value=1, max_value=r + 1))
+def test_p192_mult_tests(multiple):
+ inv_m = inverse_mod(multiple, r)
+
+ p1 = p192 * multiple
+ assert p1 * inv_m == p192
+
+
+def add_n_times(point, n):
+ ret = INFINITY
+ i = 0
+ while i <= n:
+ yield ret
+ ret = ret + point
+ i += 1
+
+
+# From X9.62 I.1 (p. 96):
+ "p, m, check",
+ [(g_23, n, exp) for n, exp in enumerate(add_n_times(g_23, 8))],
+ ids=["g_23 test with mult {0}".format(i) for i in range(9)],
+)
+def test_add_and_mult_equivalence(p, m, check):
+ assert p * m == check
+
+
+class TestCurve(unittest.TestCase):
+ @classmethod
+ def setUpClass(cls):
+ cls.c_23 = CurveFp(23, 1, 1)
+
+ def test_equality_curves(self):
+ self.assertEqual(self.c_23, CurveFp(23, 1, 1))
+
+ def test_inequality_curves(self):
+ c192 = CurveFp(p, -3, b)
+ self.assertNotEqual(self.c_23, c192)
+
+ def test_usability_in_a_hashed_collection_curves(self):
+ {self.c_23: None}
+
+ def test_hashability_curves(self):
+ hash(self.c_23)
+
+ def test_conflation_curves(self):
+ ne1, ne2, ne3 = CurveFp(24, 1, 1), CurveFp(23, 2, 1), CurveFp(23, 1, 2)
+ eq1, eq2, eq3 = CurveFp(23, 1, 1), CurveFp(23, 1, 1), self.c_23
+ self.assertEqual(len(set((c_23, eq1, eq2, eq3))), 1)
+ self.assertEqual(len(set((c_23, ne1, ne2, ne3))), 4)
+ self.assertDictEqual({c_23: None}, {eq1: None})
+ self.assertTrue(eq2 in {eq3: None})
+
+
+class TestPoint(unittest.TestCase):
+ @classmethod
+ def setUpClass(cls):
+ cls.c_23 = CurveFp(23, 1, 1)
+ cls.g_23 = Point(cls.c_23, 13, 7, 7)
+
+ p = 6277101735386680763835789423207666416083908700390324961279
+ r = 6277101735386680763835789423176059013767194773182842284081
+ # s = 0x3045ae6fc8422f64ed579528d38120eae12196d5
+ # c = 0x3099d2bbbfcb2538542dcd5fb078b6ef5f3d6fe2c745de65
+ b = 0x64210519E59C80E70FA7E9AB72243049FEB8DEECC146B9B1
+ Gx = 0x188DA80EB03090F67CBF20EB43A18800F4FF0AFD82FF1012
+ Gy = 0x07192B95FFC8DA78631011ED6B24CDD573F977A11E794811
+
+ cls.c192 = CurveFp(p, -3, b)
+ cls.p192 = Point(cls.c192, Gx, Gy, r)
+
+ def test_p192(self):
+ # Checking against some sample computations presented
+ # in X9.62:
+ d = 651056770906015076056810763456358567190100156695615665659
+ Q = d * self.p192
+ self.assertEqual(
+ Q.x(), 0x62B12D60690CDCF330BABAB6E69763B471F994DD702D16A5
+ )
+
+ k = 6140507067065001063065065565667405560006161556565665656654
+ R = k * self.p192
+ self.assertEqual(
+ R.x(), 0x885052380FF147B734C330C43D39B2C4A89F29B0F749FEAD
+ )
+ self.assertEqual(
+ R.y(), 0x9CF9FA1CBEFEFB917747A3BB29C072B9289C2547884FD835
+ )
+
+ u1 = 2563697409189434185194736134579731015366492496392189760599
+ u2 = 6266643813348617967186477710235785849136406323338782220568
+ temp = u1 * self.p192 + u2 * Q
+ self.assertEqual(
+ temp.x(), 0x885052380FF147B734C330C43D39B2C4A89F29B0F749FEAD
+ )
+ self.assertEqual(
+ temp.y(), 0x9CF9FA1CBEFEFB917747A3BB29C072B9289C2547884FD835
+ )
+
+ def test_double_infinity(self):
+ p1 = INFINITY
+ p3 = p1.double()
+ self.assertEqual(p1, p3)
+ self.assertEqual(p3.x(), p1.x())
+ self.assertEqual(p3.y(), p3.y())
+
+ def test_double(self):
+ x1, y1, x3, y3 = (3, 10, 7, 12)
+
+ p1 = Point(self.c_23, x1, y1)
+ p3 = p1.double()
+ self.assertEqual(p3.x(), x3)
+ self.assertEqual(p3.y(), y3)
+
+ def test_multiply(self):
+ x1, y1, m, x3, y3 = (3, 10, 2, 7, 12)
+ p1 = Point(self.c_23, x1, y1)
+ p3 = p1 * m
+ self.assertEqual(p3.x(), x3)
+ self.assertEqual(p3.y(), y3)
+
+ # Trivial tests from X9.62 B.3:
+ def test_add(self):
+ """We expect that on curve c, (x1,y1) + (x2, y2 ) = (x3, y3)."""
+
+ x1, y1, x2, y2, x3, y3 = (3, 10, 9, 7, 17, 20)
+ p1 = Point(self.c_23, x1, y1)
+ p2 = Point(self.c_23, x2, y2)
+ p3 = p1 + p2
+ self.assertEqual(p3.x(), x3)
+ self.assertEqual(p3.y(), y3)
+
+ def test_add_as_double(self):
+ """We expect that on curve c, (x1,y1) + (x2, y2 ) = (x3, y3)."""
+
+ x1, y1, x2, y2, x3, y3 = (3, 10, 3, 10, 7, 12)
+ p1 = Point(self.c_23, x1, y1)
+ p2 = Point(self.c_23, x2, y2)
+ p3 = p1 + p2
+ self.assertEqual(p3.x(), x3)
+ self.assertEqual(p3.y(), y3)
+
+ def test_equality_points(self):
+ self.assertEqual(self.g_23, Point(self.c_23, 13, 7, 7))
+
+ def test_inequality_points(self):
+ c = CurveFp(100, -3, 100)
+ p = Point(c, 100, 100, 100)
+ self.assertNotEqual(self.g_23, p)
+
+ def test_inequality_points_diff_types(self):
+ c = CurveFp(100, -3, 100)
+ self.assertNotEqual(self.g_23, c)
diff --git a/frozen_deps/ecdsa/test_jacobi.py b/frozen_deps/ecdsa/test_jacobi.py
new file mode 100644
index 0000000..43ed6c1
--- /dev/null
+++ b/frozen_deps/ecdsa/test_jacobi.py
@@ -0,0 +1,438 @@
+import pickle
+
+try:
+ import unittest2 as unittest
+except ImportError:
+ import unittest
+
+import hypothesis.strategies as st
+from hypothesis import given, assume, settings, example
+
+from .ellipticcurve import CurveFp, Point, PointJacobi, INFINITY
+from .ecdsa import (
+ generator_256,
+ curve_256,
+ generator_224,
+ generator_brainpoolp160r1,
+ curve_brainpoolp160r1,
+)
+from .numbertheory import inverse_mod
+
+
+class TestJacobi(unittest.TestCase):
+ def test___init__(self):
+ curve = object()
+ x = 2
+ y = 3
+ z = 1
+ order = 4
+ pj = PointJacobi(curve, x, y, z, order)
+
+ self.assertEqual(pj.order(), order)
+ self.assertIs(pj.curve(), curve)
+ self.assertEqual(pj.x(), x)
+ self.assertEqual(pj.y(), y)
+
+ def test_add_with_different_curves(self):
+ p_a = PointJacobi.from_affine(generator_256)
+ p_b = PointJacobi.from_affine(generator_224)
+
+ with self.assertRaises(ValueError):
+ p_a + p_b
+
+ def test_compare_different_curves(self):
+ self.assertNotEqual(generator_256, generator_224)
+
+ def test_equality_with_non_point(self):
+ pj = PointJacobi.from_affine(generator_256)
+
+ self.assertNotEqual(pj, "value")
+
+ def test_conversion(self):
+ pj = PointJacobi.from_affine(generator_256)
+ pw = pj.to_affine()
+
+ self.assertEqual(generator_256, pw)
+
+ def test_single_double(self):
+ pj = PointJacobi.from_affine(generator_256)
+ pw = generator_256.double()
+
+ pj = pj.double()
+
+ self.assertEqual(pj.x(), pw.x())
+ self.assertEqual(pj.y(), pw.y())
+
+ def test_double_with_zero_point(self):
+ pj = PointJacobi(curve_256, 0, 0, 1)
+
+ pj = pj.double()
+
+ self.assertIs(pj, INFINITY)
+
+ def test_double_with_zero_equivalent_point(self):
+ pj = PointJacobi(curve_256, 0, curve_256.p(), 1)
+
+ pj = pj.double()
+
+ self.assertIs(pj, INFINITY)
+
+ def test_double_with_zero_equivalent_point_non_1_z(self):
+ pj = PointJacobi(curve_256, 0, curve_256.p(), 2)
+
+ pj = pj.double()
+
+ self.assertIs(pj, INFINITY)
+
+ def test_compare_with_affine_point(self):
+ pj = PointJacobi.from_affine(generator_256)
+ pa = pj.to_affine()
+
+ self.assertEqual(pj, pa)
+ self.assertEqual(pa, pj)
+
+ def test_to_affine_with_zero_point(self):
+ pj = PointJacobi(curve_256, 0, 0, 1)
+
+ pa = pj.to_affine()
+
+ self.assertIs(pa, INFINITY)
+
+ def test_add_with_affine_point(self):
+ pj = PointJacobi.from_affine(generator_256)
+ pa = pj.to_affine()
+
+ s = pj + pa
+
+ self.assertEqual(s, pj.double())
+
+ def test_radd_with_affine_point(self):
+ pj = PointJacobi.from_affine(generator_256)
+ pa = pj.to_affine()
+
+ s = pa + pj
+
+ self.assertEqual(s, pj.double())
+
+ def test_add_with_infinity(self):
+ pj = PointJacobi.from_affine(generator_256)
+
+ s = pj + INFINITY
+
+ self.assertEqual(s, pj)
+
+ def test_add_zero_point_to_affine(self):
+ pa = PointJacobi.from_affine(generator_256).to_affine()
+ pj = PointJacobi(curve_256, 0, 0, 1)
+
+ s = pj + pa
+
+ self.assertIs(s, pa)
+
+ def test_multiply_by_zero(self):
+ pj = PointJacobi.from_affine(generator_256)
+
+ pj = pj * 0
+
+ self.assertIs(pj, INFINITY)
+
+ def test_zero_point_multiply_by_one(self):
+ pj = PointJacobi(curve_256, 0, 0, 1)
+
+ pj = pj * 1
+
+ self.assertIs(pj, INFINITY)
+
+ def test_multiply_by_one(self):
+ pj = PointJacobi.from_affine(generator_256)
+ pw = generator_256 * 1
+
+ pj = pj * 1
+
+ self.assertEqual(pj.x(), pw.x())
+ self.assertEqual(pj.y(), pw.y())
+
+ def test_multiply_by_two(self):
+ pj = PointJacobi.from_affine(generator_256)
+ pw = generator_256 * 2
+
+ pj = pj * 2
+
+ self.assertEqual(pj.x(), pw.x())
+ self.assertEqual(pj.y(), pw.y())
+
+ def test_rmul_by_two(self):
+ pj = PointJacobi.from_affine(generator_256)
+ pw = generator_256 * 2
+
+ pj = 2 * pj
+
+ self.assertEqual(pj, pw)
+
+ def test_compare_non_zero_with_infinity(self):
+ pj = PointJacobi.from_affine(generator_256)
+
+ self.assertNotEqual(pj, INFINITY)
+
+ def test_compare_zero_point_with_infinity(self):
+ pj = PointJacobi(curve_256, 0, 0, 1)
+
+ self.assertEqual(pj, INFINITY)
+
+ def test_compare_double_with_multiply(self):
+ pj = PointJacobi.from_affine(generator_256)
+ dbl = pj.double()
+ mlpl = pj * 2
+
+ self.assertEqual(dbl, mlpl)
+
+ @settings(max_examples=10)
+ @given(
+ st.integers(
+ min_value=0, max_value=int(generator_brainpoolp160r1.order())
+ )
+ )
+ def test_multiplications(self, mul):
+ pj = PointJacobi.from_affine(generator_brainpoolp160r1)
+ pw = pj.to_affine() * mul
+
+ pj = pj * mul
+
+ self.assertEqual((pj.x(), pj.y()), (pw.x(), pw.y()))
+ self.assertEqual(pj, pw)
+
+ @settings(max_examples=10)
+ @given(
+ st.integers(
+ min_value=0, max_value=int(generator_brainpoolp160r1.order())
+ )
+ )
+ @example(0)
+ @example(int(generator_brainpoolp160r1.order()))
+ def test_precompute(self, mul):
+ precomp = PointJacobi.from_affine(generator_brainpoolp160r1, True)
+ pj = PointJacobi.from_affine(generator_brainpoolp160r1)
+
+ a = precomp * mul
+ b = pj * mul
+
+ self.assertEqual(a, b)
+
+ @settings(max_examples=10)
+ @given(
+ st.integers(
+ min_value=1, max_value=int(generator_brainpoolp160r1.order())
+ ),
+ st.integers(
+ min_value=1, max_value=int(generator_brainpoolp160r1.order())
+ ),
+ )
+ @example(3, 3)
+ def test_add_scaled_points(self, a_mul, b_mul):
+ j_g = PointJacobi.from_affine(generator_brainpoolp160r1)
+ a = PointJacobi.from_affine(j_g * a_mul)
+ b = PointJacobi.from_affine(j_g * b_mul)
+
+ c = a + b
+
+ self.assertEqual(c, j_g * (a_mul + b_mul))
+
+ @settings(max_examples=10)
+ @given(
+ st.integers(
+ min_value=1, max_value=int(generator_brainpoolp160r1.order())
+ ),
+ st.integers(
+ min_value=1, max_value=int(generator_brainpoolp160r1.order())
+ ),
+ st.integers(min_value=1, max_value=int(curve_brainpoolp160r1.p() - 1)),
+ )
+ def test_add_one_scaled_point(self, a_mul, b_mul, new_z):
+ j_g = PointJacobi.from_affine(generator_brainpoolp160r1)
+ a = PointJacobi.from_affine(j_g * a_mul)
+ b = PointJacobi.from_affine(j_g * b_mul)
+
+ p = curve_brainpoolp160r1.p()
+
+ assume(inverse_mod(new_z, p))
+
+ new_zz = new_z * new_z % p
+
+ b = PointJacobi(
+ curve_brainpoolp160r1,
+ b.x() * new_zz % p,
+ b.y() * new_zz * new_z % p,
+ new_z,
+ )
+
+ c = a + b
+
+ self.assertEqual(c, j_g * (a_mul + b_mul))
+
+ @settings(max_examples=10)
+ @given(
+ st.integers(
+ min_value=1, max_value=int(generator_brainpoolp160r1.order())
+ ),
+ st.integers(
+ min_value=1, max_value=int(generator_brainpoolp160r1.order())
+ ),
+ st.integers(min_value=1, max_value=int(curve_brainpoolp160r1.p() - 1)),
+ )
+ @example(1, 1, 1)
+ @example(3, 3, 3)
+ @example(2, int(generator_brainpoolp160r1.order() - 2), 1)
+ @example(2, int(generator_brainpoolp160r1.order() - 2), 3)
+ def test_add_same_scale_points(self, a_mul, b_mul, new_z):
+ j_g = PointJacobi.from_affine(generator_brainpoolp160r1)
+ a = PointJacobi.from_affine(j_g * a_mul)
+ b = PointJacobi.from_affine(j_g * b_mul)
+
+ p = curve_brainpoolp160r1.p()
+
+ assume(inverse_mod(new_z, p))
+
+ new_zz = new_z * new_z % p
+
+ a = PointJacobi(
+ curve_brainpoolp160r1,
+ a.x() * new_zz % p,
+ a.y() * new_zz * new_z % p,
+ new_z,
+ )
+ b = PointJacobi(
+ curve_brainpoolp160r1,
+ b.x() * new_zz % p,
+ b.y() * new_zz * new_z % p,
+ new_z,
+ )
+
+ c = a + b
+
+ self.assertEqual(c, j_g * (a_mul + b_mul))
+
+ @settings(max_examples=14)
+ @given(
+ st.integers(
+ min_value=1, max_value=int(generator_brainpoolp160r1.order())
+ ),
+ st.integers(
+ min_value=1, max_value=int(generator_brainpoolp160r1.order())
+ ),
+ st.lists(
+ st.integers(
+ min_value=1, max_value=int(curve_brainpoolp160r1.p() - 1)
+ ),
+ min_size=2,
+ max_size=2,
+ unique=True,
+ ),
+ )
+ @example(2, 2, [2, 1])
+ @example(2, 2, [2, 3])
+ @example(2, int(generator_brainpoolp160r1.order() - 2), [2, 3])
+ @example(2, int(generator_brainpoolp160r1.order() - 2), [2, 1])
+ def test_add_different_scale_points(self, a_mul, b_mul, new_z):
+ j_g = PointJacobi.from_affine(generator_brainpoolp160r1)
+ a = PointJacobi.from_affine(j_g * a_mul)
+ b = PointJacobi.from_affine(j_g * b_mul)
+
+ p = curve_brainpoolp160r1.p()
+
+ assume(inverse_mod(new_z[0], p))
+ assume(inverse_mod(new_z[1], p))
+
+ new_zz0 = new_z[0] * new_z[0] % p
+ new_zz1 = new_z[1] * new_z[1] % p
+
+ a = PointJacobi(
+ curve_brainpoolp160r1,
+ a.x() * new_zz0 % p,
+ a.y() * new_zz0 * new_z[0] % p,
+ new_z[0],
+ )
+ b = PointJacobi(
+ curve_brainpoolp160r1,
+ b.x() * new_zz1 % p,
+ b.y() * new_zz1 * new_z[1] % p,
+ new_z[1],
+ )
+
+ c = a + b
+
+ self.assertEqual(c, j_g * (a_mul + b_mul))
+
+ def test_add_point_3_times(self):
+ j_g = PointJacobi.from_affine(generator_256)
+
+ self.assertEqual(j_g * 3, j_g + j_g + j_g)
+
+ def test_mul_add_inf(self):
+ j_g = PointJacobi.from_affine(generator_256)
+
+ self.assertEqual(j_g, j_g.mul_add(1, INFINITY, 1))
+
+ def test_mul_add_same(self):
+ j_g = PointJacobi.from_affine(generator_256)
+
+ self.assertEqual(j_g * 2, j_g.mul_add(1, j_g, 1))
+
+ def test_mul_add_precompute(self):
+ j_g = PointJacobi.from_affine(generator_256, True)
+ b = PointJacobi.from_affine(j_g * 255, True)
+
+ self.assertEqual(j_g * 256, j_g + b)
+ self.assertEqual(j_g * (5 + 255 * 7), j_g * 5 + b * 7)
+ self.assertEqual(j_g * (5 + 255 * 7), j_g.mul_add(5, b, 7))
+
+ def test_mul_add_precompute_large(self):
+ j_g = PointJacobi.from_affine(generator_256, True)
+ b = PointJacobi.from_affine(j_g * 255, True)
+
+ self.assertEqual(j_g * 256, j_g + b)
+ self.assertEqual(
+ j_g * (0xFF00 + 255 * 0xF0F0), j_g * 0xFF00 + b * 0xF0F0
+ )
+ self.assertEqual(
+ j_g * (0xFF00 + 255 * 0xF0F0), j_g.mul_add(0xFF00, b, 0xF0F0)
+ )
+
+ def test_mul_add_to_mul(self):
+ j_g = PointJacobi.from_affine(generator_256)
+
+ a = j_g * 3
+ b = j_g.mul_add(2, j_g, 1)
+
+ self.assertEqual(a, b)
+
+ def test_mul_add(self):
+ j_g = PointJacobi.from_affine(generator_256)
+
+ w_a = generator_256 * 255
+ w_b = generator_256 * (0xA8 * 0xF0)
+ j_b = j_g * 0xA8
+
+ ret = j_g.mul_add(255, j_b, 0xF0)
+
+ self.assertEqual(ret.to_affine(), w_a + w_b)
+
+ def test_mul_add_large(self):
+ j_g = PointJacobi.from_affine(generator_256)
+ b = PointJacobi.from_affine(j_g * 255)
+
+ self.assertEqual(j_g * 256, j_g + b)
+ self.assertEqual(
+ j_g * (0xFF00 + 255 * 0xF0F0), j_g * 0xFF00 + b * 0xF0F0
+ )
+ self.assertEqual(
+ j_g * (0xFF00 + 255 * 0xF0F0), j_g.mul_add(0xFF00, b, 0xF0F0)
+ )
+
+ def test_equality(self):
+ pj1 = PointJacobi(curve=CurveFp(23, 1, 1, 1), x=2, y=3, z=1, order=1)
+ pj2 = PointJacobi(curve=CurveFp(23, 1, 1, 1), x=2, y=3, z=1, order=1)
+ self.assertEqual(pj1, pj2)
+
+ def test_pickle(self):
+ pj = PointJacobi(curve=CurveFp(23, 1, 1, 1), x=2, y=3, z=1, order=1)
+ self.assertEqual(pickle.loads(pickle.dumps(pj)), pj)
diff --git a/frozen_deps/ecdsa/test_keys.py b/frozen_deps/ecdsa/test_keys.py
new file mode 100644
index 0000000..406a5bf
--- /dev/null
+++ b/frozen_deps/ecdsa/test_keys.py
@@ -0,0 +1,454 @@
+try:
+ import unittest2 as unittest
+except ImportError:
+ import unittest
+
+try:
+ buffer
+except NameError:
+ buffer = memoryview
+
+import array
+import six
+import sys
+import pytest
+import hashlib
+
+from .keys import VerifyingKey, SigningKey
+from .der import unpem
+from .util import (
+ sigencode_string,
+ sigencode_der,
+ sigencode_strings,
+ sigdecode_string,
+ sigdecode_der,
+ sigdecode_strings,
+)
+from .curves import NIST256p
+
+
+class TestVerifyingKeyFromString(unittest.TestCase):
+ """
+ Verify that ecdsa.keys.VerifyingKey.from_string() can be used with
+ bytes-like objects
+ """
+
+ @classmethod
+ def setUpClass(cls):
+ cls.key_bytes = (
+ b"\x04L\xa2\x95\xdb\xc7Z\xd7\x1f\x93\nz\xcf\x97\xcf"
+ b"\xd7\xc2\xd9o\xfe8}X!\xae\xd4\xfah\xfa^\rpI\xba\xd1"
+ b"Y\xfb\x92xa\xebo+\x9cG\xfav\xca"
+ )
+ cls.vk = VerifyingKey.from_string(cls.key_bytes)
+
+ def test_bytes(self):
+ self.assertIsNotNone(self.vk)
+ self.assertIsInstance(self.vk, VerifyingKey)
+ self.assertEqual(
+ self.vk.pubkey.point.x(),
+ 105419898848891948935835657980914000059957975659675736097,
+ )
+ self.assertEqual(
+ self.vk.pubkey.point.y(),
+ 4286866841217412202667522375431381222214611213481632495306,
+ )
+
+ def test_bytes_memoryview(self):
+ vk = VerifyingKey.from_string(buffer(self.key_bytes))
+
+ self.assertEqual(self.vk.to_string(), vk.to_string())
+
+ def test_bytearray(self):
+ vk = VerifyingKey.from_string(bytearray(self.key_bytes))
+
+ self.assertEqual(self.vk.to_string(), vk.to_string())
+
+ def test_bytesarray_memoryview(self):
+ vk = VerifyingKey.from_string(buffer(bytearray(self.key_bytes)))
+
+ self.assertEqual(self.vk.to_string(), vk.to_string())
+
+ def test_array_array_of_bytes(self):
+ arr = array.array("B", self.key_bytes)
+ vk = VerifyingKey.from_string(arr)
+
+ self.assertEqual(self.vk.to_string(), vk.to_string())
+
+ def test_array_array_of_bytes_memoryview(self):
+ arr = array.array("B", self.key_bytes)
+ vk = VerifyingKey.from_string(buffer(arr))
+
+ self.assertEqual(self.vk.to_string(), vk.to_string())
+
+ def test_array_array_of_ints(self):
+ arr = array.array("I", self.key_bytes)
+ vk = VerifyingKey.from_string(arr)
+
+ self.assertEqual(self.vk.to_string(), vk.to_string())
+
+ def test_array_array_of_ints_memoryview(self):
+ arr = array.array("I", self.key_bytes)
+ vk = VerifyingKey.from_string(buffer(arr))
+
+ self.assertEqual(self.vk.to_string(), vk.to_string())
+
+ def test_bytes_uncompressed(self):
+ vk = VerifyingKey.from_string(b"\x04" + self.key_bytes)
+
+ self.assertEqual(self.vk.to_string(), vk.to_string())
+
+ def test_bytearray_uncompressed(self):
+ vk = VerifyingKey.from_string(bytearray(b"\x04" + self.key_bytes))
+
+ self.assertEqual(self.vk.to_string(), vk.to_string())
+
+ def test_bytes_compressed(self):
+ vk = VerifyingKey.from_string(b"\x02" + self.key_bytes[:24])
+
+ self.assertEqual(self.vk.to_string(), vk.to_string())
+
+ def test_bytearray_compressed(self):
+ vk = VerifyingKey.from_string(bytearray(b"\x02" + self.key_bytes[:24]))
+
+ self.assertEqual(self.vk.to_string(), vk.to_string())
+
+
+class TestVerifyingKeyFromDer(unittest.TestCase):
+ """
+ Verify that ecdsa.keys.VerifyingKey.from_der() can be used with
+ bytes-like objects.
+ """
+
+ @classmethod
+ def setUpClass(cls):
+ prv_key_str = (
+ "-----BEGIN EC PRIVATE KEY-----\n"
+ "MF8CAQEEGF7IQgvW75JSqULpiQQ8op9WH6Uldw6xxaAKBggqhkjOPQMBAaE0AzIA\n"
+ "BLiBd9CE7xf15FY5QIAoNg+fWbSk1yZOYtoGUdzkejWkxbRc9RWTQjqLVXucIJnz\n"
+ "bA==\n"
+ "-----END EC PRIVATE KEY-----\n"
+ )
+ key_str = (
+ "-----BEGIN PUBLIC KEY-----\n"
+ "MEkwEwYHKoZIzj0CAQYIKoZIzj0DAQEDMgAEuIF30ITvF/XkVjlAgCg2D59ZtKTX\n"
+ "Jk5i2gZR3OR6NaTFtFz1FZNCOotVe5wgmfNs\n"
+ "-----END PUBLIC KEY-----\n"
+ )
+ cls.key_pem = key_str
+
+ cls.key_bytes = unpem(key_str)
+ assert isinstance(cls.key_bytes, bytes)
+ cls.vk = VerifyingKey.from_pem(key_str)
+ cls.sk = SigningKey.from_pem(prv_key_str)
+
+ key_str = (
+ "-----BEGIN PUBLIC KEY-----\n"
+ "MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE4H3iRbG4TSrsSRb/gusPQB/4YcN8\n"
+ "Poqzgjau4kfxBPyZimeRfuY/9g/wMmPuhGl4BUve51DsnKJFRr8psk0ieA==\n"
+ "-----END PUBLIC KEY-----\n"
+ )
+ cls.vk2 = VerifyingKey.from_pem(key_str)
+
+ def test_custom_hashfunc(self):
+ vk = VerifyingKey.from_der(self.key_bytes, hashlib.sha256)
+
+ self.assertIs(vk.default_hashfunc, hashlib.sha256)
+
+ def test_from_pem_with_custom_hashfunc(self):
+ vk = VerifyingKey.from_pem(self.key_pem, hashlib.sha256)
+
+ self.assertIs(vk.default_hashfunc, hashlib.sha256)
+
+ def test_bytes(self):
+ vk = VerifyingKey.from_der(self.key_bytes)
+
+ self.assertEqual(self.vk.to_string(), vk.to_string())
+
+ def test_bytes_memoryview(self):
+ vk = VerifyingKey.from_der(buffer(self.key_bytes))
+
+ self.assertEqual(self.vk.to_string(), vk.to_string())
+
+ def test_bytearray(self):
+ vk = VerifyingKey.from_der(bytearray(self.key_bytes))
+
+ self.assertEqual(self.vk.to_string(), vk.to_string())
+
+ def test_bytesarray_memoryview(self):
+ vk = VerifyingKey.from_der(buffer(bytearray(self.key_bytes)))
+
+ self.assertEqual(self.vk.to_string(), vk.to_string())
+
+ def test_array_array_of_bytes(self):
+ arr = array.array("B", self.key_bytes)
+ vk = VerifyingKey.from_der(arr)
+
+ self.assertEqual(self.vk.to_string(), vk.to_string())
+
+ def test_array_array_of_bytes_memoryview(self):
+ arr = array.array("B", self.key_bytes)
+ vk = VerifyingKey.from_der(buffer(arr))
+
+ self.assertEqual(self.vk.to_string(), vk.to_string())
+
+ def test_equality_on_verifying_keys(self):
+ self.assertEqual(self.vk, self.sk.get_verifying_key())
+
+ def test_inequality_on_verifying_keys(self):
+ self.assertNotEqual(self.vk, self.vk2)
+
+ def test_inequality_on_verifying_keys_not_implemented(self):
+ self.assertNotEqual(self.vk, None)
+
+
+class TestSigningKey(unittest.TestCase):
+ """
+ Verify that ecdsa.keys.SigningKey.from_der() can be used with
+ bytes-like objects.
+ """
+
+ @classmethod
+ def setUpClass(cls):
+ prv_key_str = (
+ "-----BEGIN EC PRIVATE KEY-----\n"
+ "MF8CAQEEGF7IQgvW75JSqULpiQQ8op9WH6Uldw6xxaAKBggqhkjOPQMBAaE0AzIA\n"
+ "BLiBd9CE7xf15FY5QIAoNg+fWbSk1yZOYtoGUdzkejWkxbRc9RWTQjqLVXucIJnz\n"
+ "bA==\n"
+ "-----END EC PRIVATE KEY-----\n"
+ )
+ cls.sk1 = SigningKey.from_pem(prv_key_str)
+
+ prv_key_str = (
+ "-----BEGIN PRIVATE KEY-----\n"
+ "MG8CAQAwEwYHKoZIzj0CAQYIKoZIzj0DAQEEVTBTAgEBBBheyEIL1u+SUqlC6YkE\n"
+ "PKKfVh+lJXcOscWhNAMyAAS4gXfQhO8X9eRWOUCAKDYPn1m0pNcmTmLaBlHc5Ho1\n"
+ "pMW0XPUVk0I6i1V7nCCZ82w=\n"
+ "-----END PRIVATE KEY-----\n"
+ )
+ cls.sk1_pkcs8 = SigningKey.from_pem(prv_key_str)
+
+ prv_key_str = (
+ "-----BEGIN EC PRIVATE KEY-----\n"
+ "MHcCAQEEIKlL2EAm5NPPZuXwxRf4nXMk0A80y6UUbiQ17be/qFhRoAoGCCqGSM49\n"
+ "AwEHoUQDQgAE4H3iRbG4TSrsSRb/gusPQB/4YcN8Poqzgjau4kfxBPyZimeRfuY/\n"
+ "9g/wMmPuhGl4BUve51DsnKJFRr8psk0ieA==\n"
+ "-----END EC PRIVATE KEY-----\n"
+ )
+ cls.sk2 = SigningKey.from_pem(prv_key_str)
+
+ def test_equality_on_signing_keys(self):
+ sk = SigningKey.from_secret_exponent(
+ self.sk1.privkey.secret_multiplier, self.sk1.curve
+ )
+ self.assertEqual(self.sk1, sk)
+ self.assertEqual(self.sk1_pkcs8, sk)
+
+ def test_verify_with_precompute(self):
+ sig = self.sk1.sign(b"message")
+
+ vk = self.sk1.verifying_key
+
+ vk.precompute()
+
+ self.assertTrue(vk.verify(sig, b"message"))
+
+ def test_compare_verifying_key_with_precompute(self):
+ vk1 = self.sk1.verifying_key
+ vk1.precompute()
+
+ vk2 = self.sk1_pkcs8.verifying_key
+
+ self.assertEqual(vk1, vk2)
+
+ def test_verify_with_lazy_precompute(self):
+ sig = self.sk2.sign(b"other message")
+
+ vk = self.sk2.verifying_key
+
+ vk.precompute(lazy=True)
+
+ self.assertTrue(vk.verify(sig, b"other message"))
+
+ def test_inequality_on_signing_keys(self):
+ self.assertNotEqual(self.sk1, self.sk2)
+
+ def test_inequality_on_signing_keys_not_implemented(self):
+ self.assertNotEqual(self.sk1, None)
+
+
+# test VerifyingKey.verify()
+prv_key_str = (
+ "-----BEGIN EC PRIVATE KEY-----\n"
+ "MF8CAQEEGF7IQgvW75JSqULpiQQ8op9WH6Uldw6xxaAKBggqhkjOPQMBAaE0AzIA\n"
+ "BLiBd9CE7xf15FY5QIAoNg+fWbSk1yZOYtoGUdzkejWkxbRc9RWTQjqLVXucIJnz\n"
+ "bA==\n"
+ "-----END EC PRIVATE KEY-----\n"
+)
+key_bytes = unpem(prv_key_str)
+assert isinstance(key_bytes, bytes)
+sk = SigningKey.from_der(key_bytes)
+vk = sk.verifying_key
+
+data = (
+ b"some string for signing"
+ b"contents don't really matter"
+ b"but do include also some crazy values: "
+ b"\x00\x01\t\r\n\x00\x00\x00\xff\xf0"
+)
+assert len(data) % 4 == 0
+sha1 = hashlib.sha1()
+sha1.update(data)
+data_hash = sha1.digest()
+assert isinstance(data_hash, bytes)
+sig_raw = sk.sign(data, sigencode=sigencode_string)
+assert isinstance(sig_raw, bytes)
+sig_der = sk.sign(data, sigencode=sigencode_der)
+assert isinstance(sig_der, bytes)
+sig_strings = sk.sign(data, sigencode=sigencode_strings)
+assert isinstance(sig_strings[0], bytes)
+
+verifiers = []
+for modifier, fun in [
+ ("bytes", lambda x: x),
+ ("bytes memoryview", lambda x: buffer(x)),
+ ("bytearray", lambda x: bytearray(x)),
+ ("bytearray memoryview", lambda x: buffer(bytearray(x))),
+ ("array.array of bytes", lambda x: array.array("B", x)),
+ ("array.array of bytes memoryview", lambda x: buffer(array.array("B", x))),
+ ("array.array of ints", lambda x: array.array("I", x)),
+ ("array.array of ints memoryview", lambda x: buffer(array.array("I", x))),
+]:
+ if "ints" in modifier:
+ conv = lambda x: x
+ else:
+ conv = fun
+ for sig_format, signature, decoder, mod_apply in [
+ ("raw", sig_raw, sigdecode_string, lambda x: conv(x)),
+ ("der", sig_der, sigdecode_der, lambda x: conv(x)),
+ (
+ "strings",
+ sig_strings,
+ sigdecode_strings,
+ lambda x: tuple(conv(i) for i in x),
+ ),
+ ]:
+ for method_name, vrf_mthd, vrf_data in [
+ ("verify", vk.verify, data),
+ ("verify_digest", vk.verify_digest, data_hash),
+ ]:
+ verifiers.append(
+ pytest.param(
+ signature,
+ decoder,
+ mod_apply,
+ fun,
+ vrf_mthd,
+ vrf_data,
+ id="{2}-{0}-{1}".format(modifier, sig_format, method_name),
+ )
+ )
+
+
+ "signature,decoder,mod_apply,fun,vrf_mthd,vrf_data", verifiers
+)
+def test_VerifyingKey_verify(
+ signature, decoder, mod_apply, fun, vrf_mthd, vrf_data
+):
+ sig = mod_apply(signature)
+
+ assert vrf_mthd(sig, fun(vrf_data), sigdecode=decoder)
+
+
+# test SigningKey.from_string()
+prv_key_bytes = (
+ b"^\xc8B\x0b\xd6\xef\x92R\xa9B\xe9\x89\x04<\xa2"
+ b"\x9fV\x1f\xa5%w\x0e\xb1\xc5"
+)
+assert len(prv_key_bytes) == 24
+converters = []
+for modifier, convert in [
+ ("bytes", lambda x: x),
+ ("bytes memoryview", buffer),
+ ("bytearray", bytearray),
+ ("bytearray memoryview", lambda x: buffer(bytearray(x))),
+ ("array.array of bytes", lambda x: array.array("B", x)),
+ ("array.array of bytes memoryview", lambda x: buffer(array.array("B", x))),
+ ("array.array of ints", lambda x: array.array("I", x)),
+ ("array.array of ints memoryview", lambda x: buffer(array.array("I", x))),
+]:
+ converters.append(pytest.param(convert, id=modifier))
+
+
[email protected]("convert", converters)
+def test_SigningKey_from_string(convert):
+ key = convert(prv_key_bytes)
+ sk = SigningKey.from_string(key)
+
+ assert sk.to_string() == prv_key_bytes
+
+
+# test SigningKey.from_der()
+prv_key_str = (
+ "-----BEGIN EC PRIVATE KEY-----\n"
+ "MF8CAQEEGF7IQgvW75JSqULpiQQ8op9WH6Uldw6xxaAKBggqhkjOPQMBAaE0AzIA\n"
+ "BLiBd9CE7xf15FY5QIAoNg+fWbSk1yZOYtoGUdzkejWkxbRc9RWTQjqLVXucIJnz\n"
+ "bA==\n"
+ "-----END EC PRIVATE KEY-----\n"
+)
+key_bytes = unpem(prv_key_str)
+assert isinstance(key_bytes, bytes)
+
+# last two converters are for array.array of ints, those require input
+# that's multiple of 4, which no curve we support produces
[email protected]("convert", converters[:-2])
+def test_SigningKey_from_der(convert):
+ key = convert(key_bytes)
+ sk = SigningKey.from_der(key)
+
+ assert sk.to_string() == prv_key_bytes
+
+
+# test SigningKey.sign_deterministic()
+extra_entropy = b"\x0a\x0b\x0c\x0d\x0e\x0f\x10\x11"
+
+
[email protected]("convert", converters)
+def test_SigningKey_sign_deterministic(convert):
+ sig = sk.sign_deterministic(
+ convert(data), extra_entropy=convert(extra_entropy)
+ )
+
+ vk.verify(sig, data)
+
+
+# test SigningKey.sign_digest_deterministic()
[email protected]("convert", converters)
+def test_SigningKey_sign_digest_deterministic(convert):
+ sig = sk.sign_digest_deterministic(
+ convert(data_hash), extra_entropy=convert(extra_entropy)
+ )
+
+ vk.verify(sig, data)
+
+
[email protected]("convert", converters)
+def test_SigningKey_sign(convert):
+ sig = sk.sign(convert(data))
+
+ vk.verify(sig, data)
+
+
[email protected]("convert", converters)
+def test_SigningKey_sign_digest(convert):
+ sig = sk.sign_digest(convert(data_hash))
+
+ vk.verify(sig, data)
+
+
+def test_SigningKey_with_unlikely_value():
+ sk = SigningKey.from_secret_exponent(NIST256p.order - 1, curve=NIST256p)
+ vk = sk.verifying_key
+ sig = sk.sign(b"hello")
+ assert vk.verify(sig, b"hello")
diff --git a/frozen_deps/ecdsa/test_malformed_sigs.py b/frozen_deps/ecdsa/test_malformed_sigs.py
new file mode 100644
index 0000000..4895cea
--- /dev/null
+++ b/frozen_deps/ecdsa/test_malformed_sigs.py
@@ -0,0 +1,350 @@
+from __future__ import with_statement, division
+
+import hashlib
+
+try:
+ from hashlib import algorithms_available
+except ImportError: # pragma: no cover
+ algorithms_available = [
+ "md5",
+ "sha1",
+ "sha224",
+ "sha256",
+ "sha384",
+ "sha512",
+ ]
+from functools import partial
+import pytest
+import sys
+from six import binary_type
+import hypothesis.strategies as st
+from hypothesis import note, assume, given, settings, example
+
+from .keys import SigningKey
+from .keys import BadSignatureError
+from .util import sigencode_der, sigencode_string
+from .util import sigdecode_der, sigdecode_string
+from .curves import curves, NIST256p
+from .der import (
+ encode_integer,
+ encode_bitstring,
+ encode_octet_string,
+ encode_oid,
+ encode_sequence,
+ encode_constructed,
+)
+
+
+example_data = b"some data to sign"
+"""Since the data is hashed for processing, really any string will do."""
+
+
+hash_and_size = [
+ (name, hashlib.new(name).digest_size) for name in algorithms_available
+]
+"""Pairs of hash names and their output sizes.
+Needed for pairing with curves as we don't support hashes
+bigger than order sizes of curves."""
+
+
+keys_and_sigs = []
+"""Name of the curve+hash combination, VerifyingKey and DER signature."""
+
+
+# for hypothesis strategy shrinking we want smallest curves and hashes first
+for curve in sorted(curves, key=lambda x: x.baselen):
+ for hash_alg in [
+ name
+ for name, size in sorted(hash_and_size, key=lambda x: x[1])
+ if 0 < size <= curve.baselen
+ ]:
+ sk = SigningKey.generate(
+ curve, hashfunc=partial(hashlib.new, hash_alg)
+ )
+
+ keys_and_sigs.append(
+ (
+ "{0} {1}".format(curve, hash_alg),
+ sk.verifying_key,
+ sk.sign(example_data, sigencode=sigencode_der),
+ )
+ )
+
+
+# first make sure that the signatures can be verified
+ "verifying_key,signature",
+ [pytest.param(vk, sig, id=name) for name, vk, sig in keys_and_sigs],
+)
+def test_signatures(verifying_key, signature):
+ assert verifying_key.verify(
+ signature, example_data, sigdecode=sigdecode_der
+ )
+
+
+def st_fuzzed_sig(draw, keys_and_sigs):
+ """
+ Hypothesis strategy that generates pairs of VerifyingKey and malformed
+ signatures created by fuzzing of a valid signature.
+ """
+ name, verifying_key, old_sig = draw(st.sampled_from(keys_and_sigs))
+ note("Configuration: {0}".format(name))
+
+ sig = bytearray(old_sig)
+
+ # decide which bytes should be removed
+ to_remove = draw(
+ st.lists(st.integers(min_value=0, max_value=len(sig) - 1), unique=True)
+ )
+ to_remove.sort()
+ for i in reversed(to_remove):
+ del sig[i]
+ note("Remove bytes: {0}".format(to_remove))
+
+ # decide which bytes of the original signature should be changed
+ if sig: # pragma: no branch
+ xors = draw(
+ st.dictionaries(
+ st.integers(min_value=0, max_value=len(sig) - 1),
+ st.integers(min_value=1, max_value=255),
+ )
+ )
+ for i, val in xors.items():
+ sig[i] ^= val
+ note("xors: {0}".format(xors))
+
+ # decide where new data should be inserted
+ insert_pos = draw(st.integers(min_value=0, max_value=len(sig)))
+ # NIST521p signature is about 140 bytes long, test slightly longer
+ insert_data = draw(st.binary(max_size=256))
+
+ sig = sig[:insert_pos] + insert_data + sig[insert_pos:]
+ note(
+ "Inserted at position {0} bytes: {1!r}".format(insert_pos, insert_data)
+ )
+
+ sig = bytes(sig)
+ # make sure that there was performed at least one mutation on the data
+ assume(to_remove or xors or insert_data)
+ # and that the mutations didn't cancel each-other out
+ assume(sig != old_sig)
+
+ return verifying_key, sig
+
+
+params = {}
+# not supported in hypothesis 2.0.0
+if sys.version_info >= (2, 7): # pragma: no branch
+ from hypothesis import HealthCheck
+
+ # deadline=5s because NIST521p are slow to verify
+ params["deadline"] = 5000
+ params["suppress_health_check"] = [
+ HealthCheck.data_too_large,
+ HealthCheck.filter_too_much,
+ HealthCheck.too_slow,
+ ]
+
+slow_params = dict(params)
+slow_params["max_examples"] = 10
+
+
+@settings(**params)
+@given(st_fuzzed_sig(keys_and_sigs))
+def test_fuzzed_der_signatures(args):
+ verifying_key, sig = args
+
+ with pytest.raises(BadSignatureError):
+ verifying_key.verify(sig, example_data, sigdecode=sigdecode_der)
+
+
+def st_random_der_ecdsa_sig_value(draw):
+ """
+ Hypothesis strategy for selecting random values and encoding them
+ to ECDSA-Sig-Value object::
+
+ ECDSA-Sig-Value ::= SEQUENCE {
+ r INTEGER,
+ s INTEGER
+ }
+ """
+ name, verifying_key, _ = draw(st.sampled_from(keys_and_sigs))
+ note("Configuration: {0}".format(name))
+ order = int(verifying_key.curve.order)
+
+ # the encode_integer doesn't suport negative numbers, would be nice
+ # to generate them too, but we have coverage for remove_integer()
+ # verifying that it doesn't accept them, so meh.
+ # Test all numbers around the ones that can show up (around order)
+ # way smaller and slightly bigger
+ r = draw(
+ st.integers(min_value=0, max_value=order << 4)
+ | st.integers(min_value=order >> 2, max_value=order + 1)
+ )
+ s = draw(
+ st.integers(min_value=0, max_value=order << 4)
+ | st.integers(min_value=order >> 2, max_value=order + 1)
+ )
+
+ sig = encode_sequence(encode_integer(r), encode_integer(s))
+
+ return verifying_key, sig
+
+
+@settings(**slow_params)
+@given(st_random_der_ecdsa_sig_value())
+def test_random_der_ecdsa_sig_value(params):
+ """
+ Check if random values encoded in ECDSA-Sig-Value structure are rejected
+ as signature.
+ """
+ verifying_key, sig = params
+
+ with pytest.raises(BadSignatureError):
+ verifying_key.verify(sig, example_data, sigdecode=sigdecode_der)
+
+
+def st_der_integer(*args, **kwargs):
+ """
+ Hypothesis strategy that returns a random positive integer as DER
+ INTEGER.
+ Parameters are passed to hypothesis.strategy.integer.
+ """
+ if "min_value" not in kwargs: # pragma: no branch
+ kwargs["min_value"] = 0
+ return st.builds(encode_integer, st.integers(*args, **kwargs))
+
+
+def st_der_bit_string(draw, *args, **kwargs):
+ """
+ Hypothesis strategy that returns a random DER BIT STRING.
+ Parameters are passed to hypothesis.strategy.binary.
+ """
+ data = draw(st.binary(*args, **kwargs))
+ if data:
+ unused = draw(st.integers(min_value=0, max_value=7))
+ data = bytearray(data)
+ data[-1] &= -(2 ** unused)
+ data = bytes(data)
+ else:
+ unused = 0
+ return encode_bitstring(data, unused)
+
+
+def st_der_octet_string(*args, **kwargs):
+ """
+ Hypothesis strategy that returns a random DER OCTET STRING object.
+ Parameters are passed to hypothesis.strategy.binary
+ """
+ return st.builds(encode_octet_string, st.binary(*args, **kwargs))
+
+
+def st_der_null():
+ """
+ Hypothesis strategy that returns DER NULL object.
+ """
+ return st.just(b"\x05\x00")
+
+
+def st_der_oid(draw):
+ """
+ Hypothesis strategy that returns DER OBJECT IDENTIFIER objects.
+ """
+ first = draw(st.integers(min_value=0, max_value=2))
+ if first < 2:
+ second = draw(st.integers(min_value=0, max_value=39))
+ else:
+ second = draw(st.integers(min_value=0, max_value=2 ** 512))
+ rest = draw(
+ st.lists(st.integers(min_value=0, max_value=2 ** 512), max_size=50)
+ )
+ return encode_oid(first, second, *rest)
+
+
+def st_der():
+ """
+ Hypothesis strategy that returns random DER structures.
+
+ A valid DER structure is any primitive object, an octet encoding
+ of a valid DER structure, sequence of valid DER objects or a constructed
+ encoding of any of the above.
+ """
+ return st.recursive(
+ st.just(b"")
+ | st_der_integer(max_value=2 ** 4096)
+ | st_der_bit_string(max_size=1024 ** 2)
+ | st_der_octet_string(max_size=1024 ** 2)
+ | st_der_null()
+ | st_der_oid(),
+ lambda children: st.builds(
+ lambda x: encode_octet_string(x), st.one_of(children)
+ )
+ | st.builds(lambda x: encode_bitstring(x, 0), st.one_of(children))
+ | st.builds(
+ lambda x: encode_sequence(*x), st.lists(children, max_size=200)
+ )
+ | st.builds(
+ lambda tag, x: encode_constructed(tag, x),
+ st.integers(min_value=0, max_value=0x3F),
+ st.one_of(children),
+ ),
+ max_leaves=40,
+ )
+
+
+@settings(**params)
+@given(st.sampled_from(keys_and_sigs), st_der())
+def test_random_der_as_signature(params, der):
+ """Check if random DER structures are rejected as signature"""
+ name, verifying_key, _ = params
+
+ with pytest.raises(BadSignatureError):
+ verifying_key.verify(der, example_data, sigdecode=sigdecode_der)
+
+
+@settings(**params)
+@given(st.sampled_from(keys_and_sigs), st.binary(max_size=1024 ** 2))
+@example(
+ keys_and_sigs[0], encode_sequence(encode_integer(0), encode_integer(0))
+)
+@example(
+ keys_and_sigs[0],
+ encode_sequence(encode_integer(1), encode_integer(1)) + b"\x00",
+)
+@example(keys_and_sigs[0], encode_sequence(*[encode_integer(1)] * 3))
+def test_random_bytes_as_signature(params, der):
+ """Check if random bytes are rejected as signature"""
+ name, verifying_key, _ = params
+
+ with pytest.raises(BadSignatureError):
+ verifying_key.verify(der, example_data, sigdecode=sigdecode_der)
+
+
+keys_and_string_sigs = [
+ (
+ name,
+ verifying_key,
+ sigencode_string(
+ *sigdecode_der(sig, verifying_key.curve.order),
+ order=verifying_key.curve.order
+ ),
+ )
+ for name, verifying_key, sig in keys_and_sigs
+]
+"""
+Name of the curve+hash combination, VerifyingKey and signature as a
+byte string.
+"""
+
+
+@settings(**params)
+@given(st_fuzzed_sig(keys_and_string_sigs))
+def test_fuzzed_string_signatures(params):
+ verifying_key, sig = params
+
+ with pytest.raises(BadSignatureError):
+ verifying_key.verify(sig, example_data, sigdecode=sigdecode_string)
diff --git a/frozen_deps/ecdsa/test_numbertheory.py b/frozen_deps/ecdsa/test_numbertheory.py
new file mode 100644
index 0000000..4912c57
--- /dev/null
+++ b/frozen_deps/ecdsa/test_numbertheory.py
@@ -0,0 +1,326 @@
+import operator
+from six import print_
+from functools import reduce
+import operator
+
+try:
+ import unittest2 as unittest
+except ImportError:
+ import unittest
+import hypothesis.strategies as st
+import pytest
+from hypothesis import given, settings, example
+
+try:
+ from hypothesis import HealthCheck
+
+ HC_PRESENT = True
+except ImportError: # pragma: no cover
+ HC_PRESENT = False
+from .numbertheory import (
+ SquareRootError,
+ factorization,
+ gcd,
+ lcm,
+ jacobi,
+ inverse_mod,
+ is_prime,
+ next_prime,
+ smallprimes,
+ square_root_mod_prime,
+)
+
+
+BIGPRIMES = (
+ 999671,
+ 999683,
+ 999721,
+ 999727,
+ 999749,
+ 999763,
+ 999769,
+ 999773,
+ 999809,
+ 999853,
+ 999863,
+ 999883,
+ 999907,
+ 999917,
+ 999931,
+ 999953,
+ 999959,
+ 999961,
+ 999979,
+ 999983,
+)
+
+
+ "prime, next_p", [(p, q) for p, q in zip(BIGPRIMES[:-1], BIGPRIMES[1:])]
+)
+def test_next_prime(prime, next_p):
+ assert next_prime(prime) == next_p
+
+
[email protected]("val", [-1, 0, 1])
+def test_next_prime_with_nums_less_2(val):
+ assert next_prime(val) == 2
+
+
[email protected]("prime", smallprimes)
+def test_square_root_mod_prime_for_small_primes(prime):
+ squares = set()
+ for num in range(0, 1 + prime // 2):
+ sq = num * num % prime
+ squares.add(sq)
+ root = square_root_mod_prime(sq, prime)
+ # tested for real with TestNumbertheory.test_square_root_mod_prime
+ assert root * root % prime == sq
+
+ for nonsquare in range(0, prime):
+ if nonsquare in squares:
+ continue
+ with pytest.raises(SquareRootError):
+ square_root_mod_prime(nonsquare, prime)
+
+
+def st_two_nums_rel_prime(draw):
+ # 521-bit is the biggest curve we operate on, use 1024 for a bit
+ # of breathing space
+ mod = draw(st.integers(min_value=2, max_value=2 ** 1024))
+ num = draw(
+ st.integers(min_value=1, max_value=mod - 1).filter(
+ lambda x: gcd(x, mod) == 1
+ )
+ )
+ return num, mod
+
+
+def st_primes(draw, *args, **kwargs):
+ if "min_value" not in kwargs: # pragma: no branch
+ kwargs["min_value"] = 1
+ prime = draw(
+ st.sampled_from(smallprimes)
+ | st.integers(*args, **kwargs).filter(is_prime)
+ )
+ return prime
+
+
+def st_num_square_prime(draw):
+ prime = draw(st_primes(max_value=2 ** 1024))
+ num = draw(st.integers(min_value=0, max_value=1 + prime // 2))
+ sq = num * num % prime
+ return sq, prime
+
+
+def st_comp_with_com_fac(draw):
+ """
+ Strategy that returns lists of numbers, all having a common factor.
+ """
+ primes = draw(
+ st.lists(st_primes(max_value=2 ** 512), min_size=1, max_size=10)
+ )
+ # select random prime(s) that will make the common factor of composites
+ com_fac_primes = draw(
+ st.lists(st.sampled_from(primes), min_size=1, max_size=20)
+ )
+ com_fac = reduce(operator.mul, com_fac_primes, 1)
+
+ # select at most 20 lists (returned numbers),
+ # each having at most 30 primes (factors) including none (then the number
+ # will be 1)
+ comp_primes = draw(
+ st.integers(min_value=1, max_value=20).flatmap(
+ lambda n: st.lists(
+ st.lists(st.sampled_from(primes), max_size=30),
+ min_size=1,
+ max_size=n,
+ )
+ )
+ )
+
+ return [reduce(operator.mul, nums, 1) * com_fac for nums in comp_primes]
+
+
+def st_comp_no_com_fac(draw):
+ """
+ Strategy that returns lists of numbers that don't have a common factor.
+ """
+ primes = draw(
+ st.lists(
+ st_primes(max_value=2 ** 512), min_size=2, max_size=10, unique=True
+ )
+ )
+ # first select the primes that will create the uncommon factor
+ # between returned numbers
+ uncom_fac_primes = draw(
+ st.lists(
+ st.sampled_from(primes),
+ min_size=1,
+ max_size=len(primes) - 1,
+ unique=True,
+ )
+ )
+ uncom_fac = reduce(operator.mul, uncom_fac_primes, 1)
+
+ # then build composites from leftover primes
+ leftover_primes = [i for i in primes if i not in uncom_fac_primes]
+
+ assert leftover_primes
+ assert uncom_fac_primes
+
+ # select at most 20 lists, each having at most 30 primes
+ # selected from the leftover_primes list
+ number_primes = draw(
+ st.integers(min_value=1, max_value=20).flatmap(
+ lambda n: st.lists(
+ st.lists(st.sampled_from(leftover_primes), max_size=30),
+ min_size=1,
+ max_size=n,
+ )
+ )
+ )
+
+ numbers = [reduce(operator.mul, nums, 1) for nums in number_primes]
+
+ insert_at = draw(st.integers(min_value=0, max_value=len(numbers)))
+ numbers.insert(insert_at, uncom_fac)
+ return numbers
+
+
+HYP_SETTINGS = {}
+if HC_PRESENT: # pragma: no branch
+ HYP_SETTINGS["suppress_health_check"] = [
+ HealthCheck.filter_too_much,
+ HealthCheck.too_slow,
+ ]
+ # the factorization() sometimes takes a long time to finish
+ HYP_SETTINGS["deadline"] = 5000
+
+
+HYP_SLOW_SETTINGS = dict(HYP_SETTINGS)
+HYP_SLOW_SETTINGS["max_examples"] = 10
+
+
+class TestNumbertheory(unittest.TestCase):
+ def test_gcd(self):
+ assert gcd(3 * 5 * 7, 3 * 5 * 11, 3 * 5 * 13) == 3 * 5
+ assert gcd([3 * 5 * 7, 3 * 5 * 11, 3 * 5 * 13]) == 3 * 5
+ assert gcd(3) == 3
+
+ @unittest.skipUnless(
+ HC_PRESENT,
+ "Hypothesis 2.0.0 can't be made tolerant of hard to "
+ "meet requirements (like `is_prime()`), the test "
+ "case times-out on it",
+ )
+ @settings(**HYP_SLOW_SETTINGS)
+ @given(st_comp_with_com_fac())
+ def test_gcd_with_com_factor(self, numbers):
+ n = gcd(numbers)
+ assert 1 in numbers or n != 1
+ for i in numbers:
+ assert i % n == 0
+
+ @unittest.skipUnless(
+ HC_PRESENT,
+ "Hypothesis 2.0.0 can't be made tolerant of hard to "
+ "meet requirements (like `is_prime()`), the test "
+ "case times-out on it",
+ )
+ @settings(**HYP_SLOW_SETTINGS)
+ @given(st_comp_no_com_fac())
+ def test_gcd_with_uncom_factor(self, numbers):
+ n = gcd(numbers)
+ assert n == 1
+
+ @given(
+ st.lists(
+ st.integers(min_value=1, max_value=2 ** 8192),
+ min_size=1,
+ max_size=20,
+ )
+ )
+ def test_gcd_with_random_numbers(self, numbers):
+ n = gcd(numbers)
+ for i in numbers:
+ # check that at least it's a divider
+ assert i % n == 0
+
+ def test_lcm(self):
+ assert lcm(3, 5 * 3, 7 * 3) == 3 * 5 * 7
+ assert lcm([3, 5 * 3, 7 * 3]) == 3 * 5 * 7
+ assert lcm(3) == 3
+
+ @given(
+ st.lists(
+ st.integers(min_value=1, max_value=2 ** 8192),
+ min_size=1,
+ max_size=20,
+ )
+ )
+ def test_lcm_with_random_numbers(self, numbers):
+ n = lcm(numbers)
+ for i in numbers:
+ assert n % i == 0
+
+ @unittest.skipUnless(
+ HC_PRESENT,
+ "Hypothesis 2.0.0 can't be made tolerant of hard to "
+ "meet requirements (like `is_prime()`), the test "
+ "case times-out on it",
+ )
+ @settings(**HYP_SETTINGS)
+ @given(st_num_square_prime())
+ def test_square_root_mod_prime(self, vals):
+ square, prime = vals
+
+ calc = square_root_mod_prime(square, prime)
+ assert calc * calc % prime == square
+
+ @settings(**HYP_SETTINGS)
+ @given(st.integers(min_value=1, max_value=10 ** 12))
+ @example(265399 * 1526929)
+ @example(373297 ** 2 * 553991)
+ def test_factorization(self, num):
+ factors = factorization(num)
+ mult = 1
+ for i in factors:
+ mult *= i[0] ** i[1]
+ assert mult == num
+
+ @settings(**HYP_SETTINGS)
+ @given(st.integers(min_value=3, max_value=1000).filter(lambda x: x % 2))
+ def test_jacobi(self, mod):
+ if is_prime(mod):
+ squares = set()
+ for root in range(1, mod):
+ assert jacobi(root * root, mod) == 1
+ squares.add(root * root % mod)
+ for i in range(1, mod):
+ if i not in squares:
+ assert jacobi(i, mod) == -1
+ else:
+ factors = factorization(mod)
+ for a in range(1, mod):
+ c = 1
+ for i in factors:
+ c *= jacobi(a, i[0]) ** i[1]
+ assert c == jacobi(a, mod)
+
+ @given(st_two_nums_rel_prime())
+ def test_inverse_mod(self, nums):
+ num, mod = nums
+
+ inv = inverse_mod(num, mod)
+
+ assert 0 < inv < mod
+ assert num * inv % mod == 1
+
+ def test_inverse_mod_with_zero(self):
+ assert 0 == inverse_mod(0, 11)
diff --git a/frozen_deps/ecdsa/test_pyecdsa.py b/frozen_deps/ecdsa/test_pyecdsa.py
new file mode 100644
index 0000000..65b6716
--- /dev/null
+++ b/frozen_deps/ecdsa/test_pyecdsa.py
@@ -0,0 +1,1989 @@
+from __future__ import with_statement, division
+
+try:
+ import unittest2 as unittest
+except ImportError:
+ import unittest
+import os
+import time
+import shutil
+import subprocess
+import pytest
+from binascii import hexlify, unhexlify
+from hashlib import sha1, sha256, sha384, sha512
+import hashlib
+from functools import partial
+
+from hypothesis import given
+import hypothesis.strategies as st
+
+from six import b, print_, binary_type
+from .keys import SigningKey, VerifyingKey
+from .keys import BadSignatureError, MalformedPointError, BadDigestError
+from . import util
+from .util import sigencode_der, sigencode_strings
+from .util import sigdecode_der, sigdecode_strings
+from .util import number_to_string, encoded_oid_ecPublicKey, MalformedSignature
+from .curves import Curve, UnknownCurveError
+from .curves import (
+ NIST192p,
+ NIST224p,
+ NIST256p,
+ NIST384p,
+ NIST521p,
+ SECP256k1,
+ BRAINPOOLP160r1,
+ BRAINPOOLP192r1,
+ BRAINPOOLP224r1,
+ BRAINPOOLP256r1,
+ BRAINPOOLP320r1,
+ BRAINPOOLP384r1,
+ BRAINPOOLP512r1,
+ curves,
+)
+from .ecdsa import (
+ curve_brainpoolp224r1,
+ curve_brainpoolp256r1,
+ curve_brainpoolp384r1,
+ curve_brainpoolp512r1,
+)
+from .ellipticcurve import Point
+from . import der
+from . import rfc6979
+from . import ecdsa
+
+
+class SubprocessError(Exception):
+ pass
+
+
+def run_openssl(cmd):
+ OPENSSL = "openssl"
+ p = subprocess.Popen(
+ [OPENSSL] + cmd.split(),
+ stdout=subprocess.PIPE,
+ stderr=subprocess.STDOUT,
+ )
+ stdout, ignored = p.communicate()
+ if p.returncode != 0:
+ raise SubprocessError(
+ "cmd '%s %s' failed: rc=%s, stdout/err was %s"
+ % (OPENSSL, cmd, p.returncode, stdout)
+ )
+ return stdout.decode()
+
+
+class ECDSA(unittest.TestCase):
+ def test_basic(self):
+ priv = SigningKey.generate()
+ pub = priv.get_verifying_key()
+
+ data = b("blahblah")
+ sig = priv.sign(data)
+
+ self.assertTrue(pub.verify(sig, data))
+ self.assertRaises(BadSignatureError, pub.verify, sig, data + b("bad"))
+
+ pub2 = VerifyingKey.from_string(pub.to_string())
+ self.assertTrue(pub2.verify(sig, data))
+
+ def test_deterministic(self):
+ data = b("blahblah")
+ secexp = int("9d0219792467d7d37b4d43298a7d0c05", 16)
+
+ priv = SigningKey.from_secret_exponent(secexp, SECP256k1, sha256)
+ pub = priv.get_verifying_key()
+
+ k = rfc6979.generate_k(
+ SECP256k1.generator.order(), secexp, sha256, sha256(data).digest()
+ )
+
+ sig1 = priv.sign(data, k=k)
+ self.assertTrue(pub.verify(sig1, data))
+
+ sig2 = priv.sign(data, k=k)
+ self.assertTrue(pub.verify(sig2, data))
+
+ sig3 = priv.sign_deterministic(data, sha256)
+ self.assertTrue(pub.verify(sig3, data))
+
+ self.assertEqual(sig1, sig2)
+ self.assertEqual(sig1, sig3)
+
+ def test_bad_usage(self):
+ # sk=SigningKey() is wrong
+ self.assertRaises(TypeError, SigningKey)
+ self.assertRaises(TypeError, VerifyingKey)
+
+ def test_lengths(self):
+ default = NIST192p
+ priv = SigningKey.generate()
+ pub = priv.get_verifying_key()
+ self.assertEqual(len(pub.to_string()), default.verifying_key_length)
+ sig = priv.sign(b("data"))
+ self.assertEqual(len(sig), default.signature_length)
+ for curve in (
+ NIST192p,
+ NIST224p,
+ NIST256p,
+ NIST384p,
+ NIST521p,
+ BRAINPOOLP160r1,
+ BRAINPOOLP192r1,
+ BRAINPOOLP224r1,
+ BRAINPOOLP256r1,
+ BRAINPOOLP320r1,
+ BRAINPOOLP384r1,
+ BRAINPOOLP512r1,
+ ):
+ start = time.time()
+ priv = SigningKey.generate(curve=curve)
+ pub1 = priv.get_verifying_key()
+ keygen_time = time.time() - start
+ pub2 = VerifyingKey.from_string(pub1.to_string(), curve)
+ self.assertEqual(pub1.to_string(), pub2.to_string())
+ self.assertEqual(len(pub1.to_string()), curve.verifying_key_length)
+ start = time.time()
+ sig = priv.sign(b("data"))
+ sign_time = time.time() - start
+ self.assertEqual(len(sig), curve.signature_length)
+
+ def test_serialize(self):
+ seed = b("secret")
+ curve = NIST192p
+ secexp1 = util.randrange_from_seed__trytryagain(seed, curve.order)
+ secexp2 = util.randrange_from_seed__trytryagain(seed, curve.order)
+ self.assertEqual(secexp1, secexp2)
+ priv1 = SigningKey.from_secret_exponent(secexp1, curve)
+ priv2 = SigningKey.from_secret_exponent(secexp2, curve)
+ self.assertEqual(
+ hexlify(priv1.to_string()), hexlify(priv2.to_string())
+ )
+ self.assertEqual(priv1.to_pem(), priv2.to_pem())
+ pub1 = priv1.get_verifying_key()
+ pub2 = priv2.get_verifying_key()
+ data = b("data")
+ sig1 = priv1.sign(data)
+ sig2 = priv2.sign(data)
+ self.assertTrue(pub1.verify(sig1, data))
+ self.assertTrue(pub2.verify(sig1, data))
+ self.assertTrue(pub1.verify(sig2, data))
+ self.assertTrue(pub2.verify(sig2, data))
+ self.assertEqual(hexlify(pub1.to_string()), hexlify(pub2.to_string()))
+
+ def test_nonrandom(self):
+ s = b("all the entropy in the entire world, compressed into one line")
+
+ def not_much_entropy(numbytes):
+ return s[:numbytes]
+
+ # we control the entropy source, these two keys should be identical:
+ priv1 = SigningKey.generate(entropy=not_much_entropy)
+ priv2 = SigningKey.generate(entropy=not_much_entropy)
+ self.assertEqual(
+ hexlify(priv1.get_verifying_key().to_string()),
+ hexlify(priv2.get_verifying_key().to_string()),
+ )
+ # likewise, signatures should be identical. Obviously you'd never
+ # want to do this with keys you care about, because the secrecy of
+ # the private key depends upon using different random numbers for
+ # each signature
+ sig1 = priv1.sign(b("data"), entropy=not_much_entropy)
+ sig2 = priv2.sign(b("data"), entropy=not_much_entropy)
+ self.assertEqual(hexlify(sig1), hexlify(sig2))
+
+ def assertTruePrivkeysEqual(self, priv1, priv2):
+ self.assertEqual(
+ priv1.privkey.secret_multiplier, priv2.privkey.secret_multiplier
+ )
+ self.assertEqual(
+ priv1.privkey.public_key.generator,
+ priv2.privkey.public_key.generator,
+ )
+
+ def test_privkey_creation(self):
+ s = b("all the entropy in the entire world, compressed into one line")
+
+ def not_much_entropy(numbytes):
+ return s[:numbytes]
+
+ priv1 = SigningKey.generate()
+ self.assertEqual(priv1.baselen, NIST192p.baselen)
+
+ priv1 = SigningKey.generate(curve=NIST224p)
+ self.assertEqual(priv1.baselen, NIST224p.baselen)
+
+ priv1 = SigningKey.generate(entropy=not_much_entropy)
+ self.assertEqual(priv1.baselen, NIST192p.baselen)
+ priv2 = SigningKey.generate(entropy=not_much_entropy)
+ self.assertEqual(priv2.baselen, NIST192p.baselen)
+ self.assertTruePrivkeysEqual(priv1, priv2)
+
+ priv1 = SigningKey.from_secret_exponent(secexp=3)
+ self.assertEqual(priv1.baselen, NIST192p.baselen)
+ priv2 = SigningKey.from_secret_exponent(secexp=3)
+ self.assertTruePrivkeysEqual(priv1, priv2)
+
+ priv1 = SigningKey.from_secret_exponent(secexp=4, curve=NIST224p)
+ self.assertEqual(priv1.baselen, NIST224p.baselen)
+
+ def test_privkey_strings(self):
+ priv1 = SigningKey.generate()
+ s1 = priv1.to_string()
+ self.assertEqual(type(s1), binary_type)
+ self.assertEqual(len(s1), NIST192p.baselen)
+ priv2 = SigningKey.from_string(s1)
+ self.assertTruePrivkeysEqual(priv1, priv2)
+
+ s1 = priv1.to_pem()
+ self.assertEqual(type(s1), binary_type)
+ self.assertTrue(s1.startswith(b("-----BEGIN EC PRIVATE KEY-----")))
+ self.assertTrue(s1.strip().endswith(b("-----END EC PRIVATE KEY-----")))
+ priv2 = SigningKey.from_pem(s1)
+ self.assertTruePrivkeysEqual(priv1, priv2)
+
+ s1 = priv1.to_der()
+ self.assertEqual(type(s1), binary_type)
+ priv2 = SigningKey.from_der(s1)
+ self.assertTruePrivkeysEqual(priv1, priv2)
+
+ priv1 = SigningKey.generate(curve=NIST256p)
+ s1 = priv1.to_pem()
+ self.assertEqual(type(s1), binary_type)
+ self.assertTrue(s1.startswith(b("-----BEGIN EC PRIVATE KEY-----")))
+ self.assertTrue(s1.strip().endswith(b("-----END EC PRIVATE KEY-----")))
+ priv2 = SigningKey.from_pem(s1)
+ self.assertTruePrivkeysEqual(priv1, priv2)
+
+ s1 = priv1.to_der()
+ self.assertEqual(type(s1), binary_type)
+ priv2 = SigningKey.from_der(s1)
+ self.assertTruePrivkeysEqual(priv1, priv2)
+
+ def test_privkey_strings_brainpool(self):
+ priv1 = SigningKey.generate(curve=BRAINPOOLP512r1)
+ s1 = priv1.to_pem()
+ self.assertEqual(type(s1), binary_type)
+ self.assertTrue(s1.startswith(b("-----BEGIN EC PRIVATE KEY-----")))
+ self.assertTrue(s1.strip().endswith(b("-----END EC PRIVATE KEY-----")))
+ priv2 = SigningKey.from_pem(s1)
+ self.assertTruePrivkeysEqual(priv1, priv2)
+
+ s1 = priv1.to_der()
+ self.assertEqual(type(s1), binary_type)
+ priv2 = SigningKey.from_der(s1)
+ self.assertTruePrivkeysEqual(priv1, priv2)
+
+ def assertTruePubkeysEqual(self, pub1, pub2):
+ self.assertEqual(pub1.pubkey.point, pub2.pubkey.point)
+ self.assertEqual(pub1.pubkey.generator, pub2.pubkey.generator)
+ self.assertEqual(pub1.curve, pub2.curve)
+
+ def test_pubkey_strings(self):
+ priv1 = SigningKey.generate()
+ pub1 = priv1.get_verifying_key()
+ s1 = pub1.to_string()
+ self.assertEqual(type(s1), binary_type)
+ self.assertEqual(len(s1), NIST192p.verifying_key_length)
+ pub2 = VerifyingKey.from_string(s1)
+ self.assertTruePubkeysEqual(pub1, pub2)
+
+ priv1 = SigningKey.generate(curve=NIST256p)
+ pub1 = priv1.get_verifying_key()
+ s1 = pub1.to_string()
+ self.assertEqual(type(s1), binary_type)
+ self.assertEqual(len(s1), NIST256p.verifying_key_length)
+ pub2 = VerifyingKey.from_string(s1, curve=NIST256p)
+ self.assertTruePubkeysEqual(pub1, pub2)
+
+ pub1_der = pub1.to_der()
+ self.assertEqual(type(pub1_der), binary_type)
+ pub2 = VerifyingKey.from_der(pub1_der)
+ self.assertTruePubkeysEqual(pub1, pub2)
+
+ self.assertRaises(
+ der.UnexpectedDER, VerifyingKey.from_der, pub1_der + b("junk")
+ )
+ badpub = VerifyingKey.from_der(pub1_der)
+
+ class FakeGenerator:
+ def order(self):
+ return 123456789
+
+ badcurve = Curve(
+ "unknown", None, FakeGenerator(), (1, 2, 3, 4, 5, 6), None
+ )
+ badpub.curve = badcurve
+ badder = badpub.to_der()
+ self.assertRaises(UnknownCurveError, VerifyingKey.from_der, badder)
+
+ pem = pub1.to_pem()
+ self.assertEqual(type(pem), binary_type)
+ self.assertTrue(pem.startswith(b("-----BEGIN PUBLIC KEY-----")), pem)
+ self.assertTrue(
+ pem.strip().endswith(b("-----END PUBLIC KEY-----")), pem
+ )
+ pub2 = VerifyingKey.from_pem(pem)
+ self.assertTruePubkeysEqual(pub1, pub2)
+
+ def test_pubkey_strings_brainpool(self):
+ priv1 = SigningKey.generate(curve=BRAINPOOLP512r1)
+ pub1 = priv1.get_verifying_key()
+ s1 = pub1.to_string()
+ self.assertEqual(type(s1), binary_type)
+ self.assertEqual(len(s1), BRAINPOOLP512r1.verifying_key_length)
+ pub2 = VerifyingKey.from_string(s1, curve=BRAINPOOLP512r1)
+ self.assertTruePubkeysEqual(pub1, pub2)
+
+ pub1_der = pub1.to_der()
+ self.assertEqual(type(pub1_der), binary_type)
+ pub2 = VerifyingKey.from_der(pub1_der)
+ self.assertTruePubkeysEqual(pub1, pub2)
+
+ def test_vk_to_der_with_invalid_point_encoding(self):
+ sk = SigningKey.generate()
+ vk = sk.verifying_key
+
+ with self.assertRaises(ValueError):
+ vk.to_der("raw")
+
+ def test_sk_to_der_with_invalid_point_encoding(self):
+ sk = SigningKey.generate()
+
+ with self.assertRaises(ValueError):
+ sk.to_der("raw")
+
+ def test_vk_from_der_garbage_after_curve_oid(self):
+ type_oid_der = encoded_oid_ecPublicKey
+ curve_oid_der = der.encode_oid(*(1, 2, 840, 10045, 3, 1, 1)) + b(
+ "garbage"
+ )
+ enc_type_der = der.encode_sequence(type_oid_der, curve_oid_der)
+ point_der = der.encode_bitstring(b"\x00\xff", None)
+ to_decode = der.encode_sequence(enc_type_der, point_der)
+
+ with self.assertRaises(der.UnexpectedDER):
+ VerifyingKey.from_der(to_decode)
+
+ def test_vk_from_der_invalid_key_type(self):
+ type_oid_der = der.encode_oid(*(1, 2, 3))
+ curve_oid_der = der.encode_oid(*(1, 2, 840, 10045, 3, 1, 1))
+ enc_type_der = der.encode_sequence(type_oid_der, curve_oid_der)
+ point_der = der.encode_bitstring(b"\x00\xff", None)
+ to_decode = der.encode_sequence(enc_type_der, point_der)
+
+ with self.assertRaises(der.UnexpectedDER):
+ VerifyingKey.from_der(to_decode)
+
+ def test_vk_from_der_garbage_after_point_string(self):
+ type_oid_der = encoded_oid_ecPublicKey
+ curve_oid_der = der.encode_oid(*(1, 2, 840, 10045, 3, 1, 1))
+ enc_type_der = der.encode_sequence(type_oid_der, curve_oid_der)
+ point_der = der.encode_bitstring(b"\x00\xff", None) + b("garbage")
+ to_decode = der.encode_sequence(enc_type_der, point_der)
+
+ with self.assertRaises(der.UnexpectedDER):
+ VerifyingKey.from_der(to_decode)
+
+ def test_vk_from_der_invalid_bitstring(self):
+ type_oid_der = encoded_oid_ecPublicKey
+ curve_oid_der = der.encode_oid(*(1, 2, 840, 10045, 3, 1, 1))
+ enc_type_der = der.encode_sequence(type_oid_der, curve_oid_der)
+ point_der = der.encode_bitstring(b"\x08\xff", None)
+ to_decode = der.encode_sequence(enc_type_der, point_der)
+
+ with self.assertRaises(der.UnexpectedDER):
+ VerifyingKey.from_der(to_decode)
+
+ def test_vk_from_der_with_invalid_length_of_encoding(self):
+ type_oid_der = encoded_oid_ecPublicKey
+ curve_oid_der = der.encode_oid(*(1, 2, 840, 10045, 3, 1, 1))
+ enc_type_der = der.encode_sequence(type_oid_der, curve_oid_der)
+ point_der = der.encode_bitstring(b"\xff" * 64, 0)
+ to_decode = der.encode_sequence(enc_type_der, point_der)
+
+ with self.assertRaises(MalformedPointError):
+ VerifyingKey.from_der(to_decode)
+
+ def test_vk_from_der_with_raw_encoding(self):
+ type_oid_der = encoded_oid_ecPublicKey
+ curve_oid_der = der.encode_oid(*(1, 2, 840, 10045, 3, 1, 1))
+ enc_type_der = der.encode_sequence(type_oid_der, curve_oid_der)
+ point_der = der.encode_bitstring(b"\xff" * 48, 0)
+ to_decode = der.encode_sequence(enc_type_der, point_der)
+
+ with self.assertRaises(der.UnexpectedDER):
+ VerifyingKey.from_der(to_decode)
+
+ def test_signature_strings(self):
+ priv1 = SigningKey.generate()
+ pub1 = priv1.get_verifying_key()
+ data = b("data")
+
+ sig = priv1.sign(data)
+ self.assertEqual(type(sig), binary_type)
+ self.assertEqual(len(sig), NIST192p.signature_length)
+ self.assertTrue(pub1.verify(sig, data))
+
+ sig = priv1.sign(data, sigencode=sigencode_strings)
+ self.assertEqual(type(sig), tuple)
+ self.assertEqual(len(sig), 2)
+ self.assertEqual(type(sig[0]), binary_type)
+ self.assertEqual(type(sig[1]), binary_type)
+ self.assertEqual(len(sig[0]), NIST192p.baselen)
+ self.assertEqual(len(sig[1]), NIST192p.baselen)
+ self.assertTrue(pub1.verify(sig, data, sigdecode=sigdecode_strings))
+
+ sig_der = priv1.sign(data, sigencode=sigencode_der)
+ self.assertEqual(type(sig_der), binary_type)
+ self.assertTrue(pub1.verify(sig_der, data, sigdecode=sigdecode_der))
+
+ def test_sig_decode_strings_with_invalid_count(self):
+ with self.assertRaises(MalformedSignature):
+ sigdecode_strings([b("one"), b("two"), b("three")], 0xFF)
+
+ def test_sig_decode_strings_with_wrong_r_len(self):
+ with self.assertRaises(MalformedSignature):
+ sigdecode_strings([b("one"), b("two")], 0xFF)
+
+ def test_sig_decode_strings_with_wrong_s_len(self):
+ with self.assertRaises(MalformedSignature):
+ sigdecode_strings([b("\xa0"), b("\xb0\xff")], 0xFF)
+
+ def test_verify_with_too_long_input(self):
+ sk = SigningKey.generate()
+ vk = sk.verifying_key
+
+ with self.assertRaises(BadDigestError):
+ vk.verify_digest(None, b("\x00") * 128)
+
+ def test_sk_from_secret_exponent_with_wrong_sec_exponent(self):
+ with self.assertRaises(MalformedPointError):
+ SigningKey.from_secret_exponent(0)
+
+ def test_sk_from_string_with_wrong_len_string(self):
+ with self.assertRaises(MalformedPointError):
+ SigningKey.from_string(b("\x01"))
+
+ def test_sk_from_der_with_junk_after_sequence(self):
+ ver_der = der.encode_integer(1)
+ to_decode = der.encode_sequence(ver_der) + b("garbage")
+
+ with self.assertRaises(der.UnexpectedDER):
+ SigningKey.from_der(to_decode)
+
+ def test_sk_from_der_with_wrong_version(self):
+ ver_der = der.encode_integer(0)
+ to_decode = der.encode_sequence(ver_der)
+
+ with self.assertRaises(der.UnexpectedDER):
+ SigningKey.from_der(to_decode)
+
+ def test_sk_from_der_invalid_const_tag(self):
+ ver_der = der.encode_integer(1)
+ privkey_der = der.encode_octet_string(b("\x00\xff"))
+ curve_oid_der = der.encode_oid(*(1, 2, 3))
+ const_der = der.encode_constructed(1, curve_oid_der)
+ to_decode = der.encode_sequence(
+ ver_der, privkey_der, const_der, curve_oid_der
+ )
+
+ with self.assertRaises(der.UnexpectedDER):
+ SigningKey.from_der(to_decode)
+
+ def test_sk_from_der_garbage_after_privkey_oid(self):
+ ver_der = der.encode_integer(1)
+ privkey_der = der.encode_octet_string(b("\x00\xff"))
+ curve_oid_der = der.encode_oid(*(1, 2, 3)) + b("garbage")
+ const_der = der.encode_constructed(0, curve_oid_der)
+ to_decode = der.encode_sequence(
+ ver_der, privkey_der, const_der, curve_oid_der
+ )
+
+ with self.assertRaises(der.UnexpectedDER):
+ SigningKey.from_der(to_decode)
+
+ def test_sk_from_der_with_short_privkey(self):
+ ver_der = der.encode_integer(1)
+ privkey_der = der.encode_octet_string(b("\x00\xff"))
+ curve_oid_der = der.encode_oid(*(1, 2, 840, 10045, 3, 1, 1))
+ const_der = der.encode_constructed(0, curve_oid_der)
+ to_decode = der.encode_sequence(
+ ver_der, privkey_der, const_der, curve_oid_der
+ )
+
+ sk = SigningKey.from_der(to_decode)
+ self.assertEqual(sk.privkey.secret_multiplier, 255)
+
+ def test_sk_from_p8_der_with_wrong_version(self):
+ ver_der = der.encode_integer(2)
+ algorithm_der = der.encode_sequence(
+ der.encode_oid(1, 2, 840, 10045, 2, 1),
+ der.encode_oid(1, 2, 840, 10045, 3, 1, 1),
+ )
+ privkey_der = der.encode_octet_string(
+ der.encode_sequence(
+ der.encode_integer(1), der.encode_octet_string(b"\x00\xff")
+ )
+ )
+ to_decode = der.encode_sequence(ver_der, algorithm_der, privkey_der)
+
+ with self.assertRaises(der.UnexpectedDER):
+ SigningKey.from_der(to_decode)
+
+ def test_sk_from_p8_der_with_wrong_algorithm(self):
+ ver_der = der.encode_integer(1)
+ algorithm_der = der.encode_sequence(
+ der.encode_oid(1, 2, 3), der.encode_oid(1, 2, 840, 10045, 3, 1, 1)
+ )
+ privkey_der = der.encode_octet_string(
+ der.encode_sequence(
+ der.encode_integer(1), der.encode_octet_string(b"\x00\xff")
+ )
+ )
+ to_decode = der.encode_sequence(ver_der, algorithm_der, privkey_der)
+
+ with self.assertRaises(der.UnexpectedDER):
+ SigningKey.from_der(to_decode)
+
+ def test_sk_from_p8_der_with_trailing_junk_after_algorithm(self):
+ ver_der = der.encode_integer(1)
+ algorithm_der = der.encode_sequence(
+ der.encode_oid(1, 2, 840, 10045, 2, 1),
+ der.encode_oid(1, 2, 840, 10045, 3, 1, 1),
+ der.encode_octet_string(b"junk"),
+ )
+ privkey_der = der.encode_octet_string(
+ der.encode_sequence(
+ der.encode_integer(1), der.encode_octet_string(b"\x00\xff")
+ )
+ )
+ to_decode = der.encode_sequence(ver_der, algorithm_der, privkey_der)
+
+ with self.assertRaises(der.UnexpectedDER):
+ SigningKey.from_der(to_decode)
+
+ def test_sk_from_p8_der_with_trailing_junk_after_key(self):
+ ver_der = der.encode_integer(1)
+ algorithm_der = der.encode_sequence(
+ der.encode_oid(1, 2, 840, 10045, 2, 1),
+ der.encode_oid(1, 2, 840, 10045, 3, 1, 1),
+ )
+ privkey_der = der.encode_octet_string(
+ der.encode_sequence(
+ der.encode_integer(1), der.encode_octet_string(b"\x00\xff")
+ )
+ + der.encode_integer(999)
+ )
+ to_decode = der.encode_sequence(
+ ver_der,
+ algorithm_der,
+ privkey_der,
+ der.encode_octet_string(b"junk"),
+ )
+
+ with self.assertRaises(der.UnexpectedDER):
+ SigningKey.from_der(to_decode)
+
+ def test_sign_with_too_long_hash(self):
+ sk = SigningKey.from_secret_exponent(12)
+
+ with self.assertRaises(BadDigestError):
+ sk.sign_digest(b("\xff") * 64)
+
+ def test_hashfunc(self):
+ sk = SigningKey.generate(curve=NIST256p, hashfunc=sha256)
+ data = b("security level is 128 bits")
+ sig = sk.sign(data)
+ vk = VerifyingKey.from_string(
+ sk.get_verifying_key().to_string(), curve=NIST256p, hashfunc=sha256
+ )
+ self.assertTrue(vk.verify(sig, data))
+
+ sk2 = SigningKey.generate(curve=NIST256p)
+ sig2 = sk2.sign(data, hashfunc=sha256)
+ vk2 = VerifyingKey.from_string(
+ sk2.get_verifying_key().to_string(),
+ curve=NIST256p,
+ hashfunc=sha256,
+ )
+ self.assertTrue(vk2.verify(sig2, data))
+
+ vk3 = VerifyingKey.from_string(
+ sk.get_verifying_key().to_string(), curve=NIST256p
+ )
+ self.assertTrue(vk3.verify(sig, data, hashfunc=sha256))
+
+ def test_public_key_recovery(self):
+ # Create keys
+ curve = NIST256p
+
+ sk = SigningKey.generate(curve=curve)
+ vk = sk.get_verifying_key()
+
+ # Sign a message
+ data = b("blahblah")
+ signature = sk.sign(data)
+
+ # Recover verifying keys
+ recovered_vks = VerifyingKey.from_public_key_recovery(
+ signature, data, curve
+ )
+
+ # Test if each pk is valid
+ for recovered_vk in recovered_vks:
+ # Test if recovered vk is valid for the data
+ self.assertTrue(recovered_vk.verify(signature, data))
+
+ # Test if properties are equal
+ self.assertEqual(vk.curve, recovered_vk.curve)
+ self.assertEqual(
+ vk.default_hashfunc, recovered_vk.default_hashfunc
+ )
+
+ # Test if original vk is the list of recovered keys
+ self.assertTrue(
+ vk.pubkey.point
+ in [recovered_vk.pubkey.point for recovered_vk in recovered_vks]
+ )
+
+ def test_public_key_recovery_with_custom_hash(self):
+ # Create keys
+ curve = NIST256p
+
+ sk = SigningKey.generate(curve=curve, hashfunc=sha256)
+ vk = sk.get_verifying_key()
+
+ # Sign a message
+ data = b("blahblah")
+ signature = sk.sign(data)
+
+ # Recover verifying keys
+ recovered_vks = VerifyingKey.from_public_key_recovery(
+ signature, data, curve, hashfunc=sha256
+ )
+
+ # Test if each pk is valid
+ for recovered_vk in recovered_vks:
+ # Test if recovered vk is valid for the data
+ self.assertTrue(recovered_vk.verify(signature, data))
+
+ # Test if properties are equal
+ self.assertEqual(vk.curve, recovered_vk.curve)
+ self.assertEqual(sha256, recovered_vk.default_hashfunc)
+
+ # Test if original vk is the list of recovered keys
+ self.assertTrue(
+ vk.pubkey.point
+ in [recovered_vk.pubkey.point for recovered_vk in recovered_vks]
+ )
+
+ def test_encoding(self):
+ sk = SigningKey.from_secret_exponent(123456789)
+ vk = sk.verifying_key
+
+ exp = b(
+ "\x0c\xe0\x1d\xe0d\x1c\x8eS\x8a\xc0\x9eK\xa8x !\xd5\xc2\xc3"
+ "\xfd\xc8\xa0c\xff\xfb\x02\xb9\xc4\x84)\x1a\x0f\x8b\x87\xa4"
+ "z\x8a#\xb5\x97\xecO\xb6\xa0HQ\x89*"
+ )
+ self.assertEqual(vk.to_string(), exp)
+ self.assertEqual(vk.to_string("raw"), exp)
+ self.assertEqual(vk.to_string("uncompressed"), b("\x04") + exp)
+ self.assertEqual(vk.to_string("compressed"), b("\x02") + exp[:24])
+ self.assertEqual(vk.to_string("hybrid"), b("\x06") + exp)
+
+ def test_decoding(self):
+ sk = SigningKey.from_secret_exponent(123456789)
+ vk = sk.verifying_key
+
+ enc = b(
+ "\x0c\xe0\x1d\xe0d\x1c\x8eS\x8a\xc0\x9eK\xa8x !\xd5\xc2\xc3"
+ "\xfd\xc8\xa0c\xff\xfb\x02\xb9\xc4\x84)\x1a\x0f\x8b\x87\xa4"
+ "z\x8a#\xb5\x97\xecO\xb6\xa0HQ\x89*"
+ )
+
+ from_raw = VerifyingKey.from_string(enc)
+ self.assertEqual(from_raw.pubkey.point, vk.pubkey.point)
+
+ from_uncompressed = VerifyingKey.from_string(b("\x04") + enc)
+ self.assertEqual(from_uncompressed.pubkey.point, vk.pubkey.point)
+
+ from_compressed = VerifyingKey.from_string(b("\x02") + enc[:24])
+ self.assertEqual(from_compressed.pubkey.point, vk.pubkey.point)
+
+ from_uncompressed = VerifyingKey.from_string(b("\x06") + enc)
+ self.assertEqual(from_uncompressed.pubkey.point, vk.pubkey.point)
+
+ def test_decoding_with_malformed_uncompressed(self):
+ enc = b(
+ "\x0c\xe0\x1d\xe0d\x1c\x8eS\x8a\xc0\x9eK\xa8x !\xd5\xc2\xc3"
+ "\xfd\xc8\xa0c\xff\xfb\x02\xb9\xc4\x84)\x1a\x0f\x8b\x87\xa4"
+ "z\x8a#\xb5\x97\xecO\xb6\xa0HQ\x89*"
+ )
+
+ with self.assertRaises(MalformedPointError):
+ VerifyingKey.from_string(b("\x02") + enc)
+
+ def test_decoding_with_malformed_compressed(self):
+ enc = b(
+ "\x0c\xe0\x1d\xe0d\x1c\x8eS\x8a\xc0\x9eK\xa8x !\xd5\xc2\xc3"
+ "\xfd\xc8\xa0c\xff\xfb\x02\xb9\xc4\x84)\x1a\x0f\x8b\x87\xa4"
+ "z\x8a#\xb5\x97\xecO\xb6\xa0HQ\x89*"
+ )
+
+ with self.assertRaises(MalformedPointError):
+ VerifyingKey.from_string(b("\x01") + enc[:24])
+
+ def test_decoding_with_inconsistent_hybrid(self):
+ enc = b(
+ "\x0c\xe0\x1d\xe0d\x1c\x8eS\x8a\xc0\x9eK\xa8x !\xd5\xc2\xc3"
+ "\xfd\xc8\xa0c\xff\xfb\x02\xb9\xc4\x84)\x1a\x0f\x8b\x87\xa4"
+ "z\x8a#\xb5\x97\xecO\xb6\xa0HQ\x89*"
+ )
+
+ with self.assertRaises(MalformedPointError):
+ VerifyingKey.from_string(b("\x07") + enc)
+
+ def test_decoding_with_point_not_on_curve(self):
+ enc = b(
+ "\x0c\xe0\x1d\xe0d\x1c\x8eS\x8a\xc0\x9eK\xa8x !\xd5\xc2\xc3"
+ "\xfd\xc8\xa0c\xff\xfb\x02\xb9\xc4\x84)\x1a\x0f\x8b\x87\xa4"
+ "z\x8a#\xb5\x97\xecO\xb6\xa0HQ\x89*"
+ )
+
+ with self.assertRaises(MalformedPointError):
+ VerifyingKey.from_string(enc[:47] + b("\x00"))
+
+ def test_decoding_with_point_at_infinity(self):
+ # decoding it is unsupported, as it's not necessary to encode it
+ with self.assertRaises(MalformedPointError):
+ VerifyingKey.from_string(b("\x00"))
+
+ def test_not_lying_on_curve(self):
+ enc = number_to_string(NIST192p.curve.p(), NIST192p.curve.p() + 1)
+
+ with self.assertRaises(MalformedPointError):
+ VerifyingKey.from_string(b("\x02") + enc)
+
+ def test_from_string_with_invalid_curve_too_short_ver_key_len(self):
+ # both verifying_key_length and baselen are calculated internally
+ # by the Curve constructor, but since we depend on them verify
+ # that inconsistent values are detected
+ curve = Curve("test", ecdsa.curve_192, ecdsa.generator_192, (1, 2))
+ curve.verifying_key_length = 16
+ curve.baselen = 32
+
+ with self.assertRaises(MalformedPointError):
+ VerifyingKey.from_string(b("\x00") * 16, curve)
+
+ def test_from_string_with_invalid_curve_too_long_ver_key_len(self):
+ # both verifying_key_length and baselen are calculated internally
+ # by the Curve constructor, but since we depend on them verify
+ # that inconsistent values are detected
+ curve = Curve("test", ecdsa.curve_192, ecdsa.generator_192, (1, 2))
+ curve.verifying_key_length = 16
+ curve.baselen = 16
+
+ with self.assertRaises(MalformedPointError):
+ VerifyingKey.from_string(b("\x00") * 16, curve)
+
+
+ "val,even", [(i, j) for i in range(256) for j in [True, False]]
+)
+def test_VerifyingKey_decode_with_small_values(val, even):
+ enc = number_to_string(val, NIST192p.order)
+
+ if even:
+ enc = b("\x02") + enc
+ else:
+ enc = b("\x03") + enc
+
+ # small values can both be actual valid public keys and not, verify that
+ # only expected exceptions are raised if they are not
+ try:
+ vk = VerifyingKey.from_string(enc)
+ assert isinstance(vk, VerifyingKey)
+ except MalformedPointError:
+ assert True
+
+
+params = []
+for curve in curves:
+ for enc in ["raw", "uncompressed", "compressed", "hybrid"]:
+ params.append(
+ pytest.param(curve, enc, id="{0}-{1}".format(curve.name, enc))
+ )
+
+
[email protected]("curve,encoding", params)
+def test_VerifyingKey_encode_decode(curve, encoding):
+ sk = SigningKey.generate(curve=curve)
+ vk = sk.verifying_key
+
+ encoded = vk.to_string(encoding)
+
+ from_enc = VerifyingKey.from_string(encoded, curve=curve)
+
+ assert vk.pubkey.point == from_enc.pubkey.point
+
+
+class OpenSSL(unittest.TestCase):
+ # test interoperability with OpenSSL tools. Note that openssl's ECDSA
+ # sign/verify arguments changed between 0.9.8 and 1.0.0: the early
+ # versions require "-ecdsa-with-SHA1", the later versions want just
+ # "-SHA1" (or to leave out that argument entirely, which means the
+ # signature will use some default digest algorithm, probably determined
+ # by the key, probably always SHA1).
+ #
+ # openssl ecparam -name secp224r1 -genkey -out privkey.pem
+ # openssl ec -in privkey.pem -text -noout # get the priv/pub keys
+ # openssl dgst -ecdsa-with-SHA1 -sign privkey.pem -out data.sig data.txt
+ # openssl asn1parse -in data.sig -inform DER
+ # data.sig is 64 bytes, probably 56b plus ASN1 overhead
+ # openssl dgst -ecdsa-with-SHA1 -prverify privkey.pem -signature data.sig data.txt ; echo $?
+ # openssl ec -in privkey.pem -pubout -out pubkey.pem
+ # openssl ec -in privkey.pem -pubout -outform DER -out pubkey.der
+
+ OPENSSL_SUPPORTED_CURVES = set(
+ c.split(":")[0].strip()
+ for c in run_openssl("ecparam -list_curves").split("\n")
+ )
+
+ def get_openssl_messagedigest_arg(self, hash_name):
+ v = run_openssl("version")
+ # e.g. "OpenSSL 1.0.0 29 Mar 2010", or "OpenSSL 1.0.0a 1 Jun 2010",
+ # or "OpenSSL 0.9.8o 01 Jun 2010"
+ vs = v.split()[1].split(".")
+ if vs >= ["1", "0", "0"]: # pragma: no cover
+ return "-{0}".format(hash_name)
+ else: # pragma: no cover
+ return "-ecdsa-with-{0}".format(hash_name)
+
+ # sk: 1:OpenSSL->python 2:python->OpenSSL
+ # vk: 3:OpenSSL->python 4:python->OpenSSL
+ # sig: 5:OpenSSL->python 6:python->OpenSSL
+
+ @pytest.mark.skipif(
+ "prime192v1" not in OPENSSL_SUPPORTED_CURVES,
+ reason="system openssl does not support prime192v1",
+ )
+ def test_from_openssl_nist192p(self):
+ return self.do_test_from_openssl(NIST192p)
+
+ @pytest.mark.skipif(
+ "prime192v1" not in OPENSSL_SUPPORTED_CURVES,
+ reason="system openssl does not support prime192v1",
+ )
+ def test_from_openssl_nist192p_sha256(self):
+ return self.do_test_from_openssl(NIST192p, "SHA256")
+
+ @pytest.mark.skipif(
+ "secp224r1" not in OPENSSL_SUPPORTED_CURVES,
+ reason="system openssl does not support secp224r1",
+ )
+ def test_from_openssl_nist224p(self):
+ return self.do_test_from_openssl(NIST224p)
+
+ @pytest.mark.skipif(
+ "prime256v1" not in OPENSSL_SUPPORTED_CURVES,
+ reason="system openssl does not support prime256v1",
+ )
+ def test_from_openssl_nist256p(self):
+ return self.do_test_from_openssl(NIST256p)
+
+ @pytest.mark.skipif(
+ "prime256v1" not in OPENSSL_SUPPORTED_CURVES,
+ reason="system openssl does not support prime256v1",
+ )
+ def test_from_openssl_nist256p_sha384(self):
+ return self.do_test_from_openssl(NIST256p, "SHA384")
+
+ @pytest.mark.skipif(
+ "prime256v1" not in OPENSSL_SUPPORTED_CURVES,
+ reason="system openssl does not support prime256v1",
+ )
+ def test_from_openssl_nist256p_sha512(self):
+ return self.do_test_from_openssl(NIST256p, "SHA512")
+
+ @pytest.mark.skipif(
+ "secp384r1" not in OPENSSL_SUPPORTED_CURVES,
+ reason="system openssl does not support secp384r1",
+ )
+ def test_from_openssl_nist384p(self):
+ return self.do_test_from_openssl(NIST384p)
+
+ @pytest.mark.skipif(
+ "secp521r1" not in OPENSSL_SUPPORTED_CURVES,
+ reason="system openssl does not support secp521r1",
+ )
+ def test_from_openssl_nist521p(self):
+ return self.do_test_from_openssl(NIST521p)
+
+ @pytest.mark.skipif(
+ "secp256k1" not in OPENSSL_SUPPORTED_CURVES,
+ reason="system openssl does not support secp256k1",
+ )
+ def test_from_openssl_secp256k1(self):
+ return self.do_test_from_openssl(SECP256k1)
+
+ @pytest.mark.skipif(
+ "brainpoolP160r1" not in OPENSSL_SUPPORTED_CURVES,
+ reason="system openssl does not support brainpoolP160r1",
+ )
+ def test_from_openssl_brainpoolp160r1(self):
+ return self.do_test_from_openssl(BRAINPOOLP160r1)
+
+ @pytest.mark.skipif(
+ "brainpoolP192r1" not in OPENSSL_SUPPORTED_CURVES,
+ reason="system openssl does not support brainpoolP192r1",
+ )
+ def test_from_openssl_brainpoolp192r1(self):
+ return self.do_test_from_openssl(BRAINPOOLP192r1)
+
+ @pytest.mark.skipif(
+ "brainpoolP224r1" not in OPENSSL_SUPPORTED_CURVES,
+ reason="system openssl does not support brainpoolP224r1",
+ )
+ def test_from_openssl_brainpoolp224r1(self):
+ return self.do_test_from_openssl(BRAINPOOLP224r1)
+
+ @pytest.mark.skipif(
+ "brainpoolP256r1" not in OPENSSL_SUPPORTED_CURVES,
+ reason="system openssl does not support brainpoolP256r1",
+ )
+ def test_from_openssl_brainpoolp256r1(self):
+ return self.do_test_from_openssl(BRAINPOOLP256r1)
+
+ @pytest.mark.skipif(
+ "brainpoolP320r1" not in OPENSSL_SUPPORTED_CURVES,
+ reason="system openssl does not support brainpoolP320r1",
+ )
+ def test_from_openssl_brainpoolp320r1(self):
+ return self.do_test_from_openssl(BRAINPOOLP320r1)
+
+ @pytest.mark.skipif(
+ "brainpoolP384r1" not in OPENSSL_SUPPORTED_CURVES,
+ reason="system openssl does not support brainpoolP384r1",
+ )
+ def test_from_openssl_brainpoolp384r1(self):
+ return self.do_test_from_openssl(BRAINPOOLP384r1)
+
+ @pytest.mark.skipif(
+ "brainpoolP512r1" not in OPENSSL_SUPPORTED_CURVES,
+ reason="system openssl does not support brainpoolP512r1",
+ )
+ def test_from_openssl_brainpoolp512r1(self):
+ return self.do_test_from_openssl(BRAINPOOLP512r1)
+
+ def do_test_from_openssl(self, curve, hash_name="SHA1"):
+ curvename = curve.openssl_name
+ assert curvename
+ # OpenSSL: create sk, vk, sign.
+ # Python: read vk(3), checksig(5), read sk(1), sign, check
+ mdarg = self.get_openssl_messagedigest_arg(hash_name)
+ if os.path.isdir("t"): # pragma: no cover
+ shutil.rmtree("t")
+ os.mkdir("t")
+ run_openssl("ecparam -name %s -genkey -out t/privkey.pem" % curvename)
+ run_openssl("ec -in t/privkey.pem -pubout -out t/pubkey.pem")
+ data = b("data")
+ with open("t/data.txt", "wb") as e:
+ e.write(data)
+ run_openssl(
+ "dgst %s -sign t/privkey.pem -out t/data.sig t/data.txt" % mdarg
+ )
+ run_openssl(
+ "dgst %s -verify t/pubkey.pem -signature t/data.sig t/data.txt"
+ % mdarg
+ )
+ with open("t/pubkey.pem", "rb") as e:
+ pubkey_pem = e.read()
+ vk = VerifyingKey.from_pem(pubkey_pem) # 3
+ with open("t/data.sig", "rb") as e:
+ sig_der = e.read()
+ self.assertTrue(
+ vk.verify(
+ sig_der,
+ data, # 5
+ hashfunc=partial(hashlib.new, hash_name),
+ sigdecode=sigdecode_der,
+ )
+ )
+
+ with open("t/privkey.pem") as e:
+ fp = e.read()
+ sk = SigningKey.from_pem(fp) # 1
+ sig = sk.sign(data, hashfunc=partial(hashlib.new, hash_name))
+ self.assertTrue(
+ vk.verify(sig, data, hashfunc=partial(hashlib.new, hash_name))
+ )
+
+ run_openssl(
+ "pkcs8 -topk8 -nocrypt "
+ "-in t/privkey.pem -outform pem -out t/privkey-p8.pem"
+ )
+ with open("t/privkey-p8.pem", "rb") as e:
+ privkey_p8_pem = e.read()
+ sk_from_p8 = SigningKey.from_pem(privkey_p8_pem)
+ self.assertEqual(sk, sk_from_p8)
+
+ @pytest.mark.skipif(
+ "prime192v1" not in OPENSSL_SUPPORTED_CURVES,
+ reason="system openssl does not support prime192v1",
+ )
+ def test_to_openssl_nist192p(self):
+ self.do_test_to_openssl(NIST192p)
+
+ @pytest.mark.skipif(
+ "prime192v1" not in OPENSSL_SUPPORTED_CURVES,
+ reason="system openssl does not support prime192v1",
+ )
+ def test_to_openssl_nist192p_sha256(self):
+ self.do_test_to_openssl(NIST192p, "SHA256")
+
+ @pytest.mark.skipif(
+ "secp224r1" not in OPENSSL_SUPPORTED_CURVES,
+ reason="system openssl does not support secp224r1",
+ )
+ def test_to_openssl_nist224p(self):
+ self.do_test_to_openssl(NIST224p)
+
+ @pytest.mark.skipif(
+ "prime256v1" not in OPENSSL_SUPPORTED_CURVES,
+ reason="system openssl does not support prime256v1",
+ )
+ def test_to_openssl_nist256p(self):
+ self.do_test_to_openssl(NIST256p)
+
+ @pytest.mark.skipif(
+ "prime256v1" not in OPENSSL_SUPPORTED_CURVES,
+ reason="system openssl does not support prime256v1",
+ )
+ def test_to_openssl_nist256p_sha384(self):
+ self.do_test_to_openssl(NIST256p, "SHA384")
+
+ @pytest.mark.skipif(
+ "prime256v1" not in OPENSSL_SUPPORTED_CURVES,
+ reason="system openssl does not support prime256v1",
+ )
+ def test_to_openssl_nist256p_sha512(self):
+ self.do_test_to_openssl(NIST256p, "SHA512")
+
+ @pytest.mark.skipif(
+ "secp384r1" not in OPENSSL_SUPPORTED_CURVES,
+ reason="system openssl does not support secp384r1",
+ )
+ def test_to_openssl_nist384p(self):
+ self.do_test_to_openssl(NIST384p)
+
+ @pytest.mark.skipif(
+ "secp521r1" not in OPENSSL_SUPPORTED_CURVES,
+ reason="system openssl does not support secp521r1",
+ )
+ def test_to_openssl_nist521p(self):
+ self.do_test_to_openssl(NIST521p)
+
+ @pytest.mark.skipif(
+ "secp256k1" not in OPENSSL_SUPPORTED_CURVES,
+ reason="system openssl does not support secp256k1",
+ )
+ def test_to_openssl_secp256k1(self):
+ self.do_test_to_openssl(SECP256k1)
+
+ @pytest.mark.skipif(
+ "brainpoolP160r1" not in OPENSSL_SUPPORTED_CURVES,
+ reason="system openssl does not support brainpoolP160r1",
+ )
+ def test_to_openssl_brainpoolp160r1(self):
+ self.do_test_to_openssl(BRAINPOOLP160r1)
+
+ @pytest.mark.skipif(
+ "brainpoolP192r1" not in OPENSSL_SUPPORTED_CURVES,
+ reason="system openssl does not support brainpoolP192r1",
+ )
+ def test_to_openssl_brainpoolp192r1(self):
+ self.do_test_to_openssl(BRAINPOOLP192r1)
+
+ @pytest.mark.skipif(
+ "brainpoolP224r1" not in OPENSSL_SUPPORTED_CURVES,
+ reason="system openssl does not support brainpoolP224r1",
+ )
+ def test_to_openssl_brainpoolp224r1(self):
+ self.do_test_to_openssl(BRAINPOOLP224r1)
+
+ @pytest.mark.skipif(
+ "brainpoolP256r1" not in OPENSSL_SUPPORTED_CURVES,
+ reason="system openssl does not support brainpoolP256r1",
+ )
+ def test_to_openssl_brainpoolp256r1(self):
+ self.do_test_to_openssl(BRAINPOOLP256r1)
+
+ @pytest.mark.skipif(
+ "brainpoolP320r1" not in OPENSSL_SUPPORTED_CURVES,
+ reason="system openssl does not support brainpoolP320r1",
+ )
+ def test_to_openssl_brainpoolp320r1(self):
+ self.do_test_to_openssl(BRAINPOOLP320r1)
+
+ @pytest.mark.skipif(
+ "brainpoolP384r1" not in OPENSSL_SUPPORTED_CURVES,
+ reason="system openssl does not support brainpoolP384r1",
+ )
+ def test_to_openssl_brainpoolp384r1(self):
+ self.do_test_to_openssl(BRAINPOOLP384r1)
+
+ @pytest.mark.skipif(
+ "brainpoolP512r1" not in OPENSSL_SUPPORTED_CURVES,
+ reason="system openssl does not support brainpoolP512r1",
+ )
+ def test_to_openssl_brainpoolp512r1(self):
+ self.do_test_to_openssl(BRAINPOOLP512r1)
+
+ def do_test_to_openssl(self, curve, hash_name="SHA1"):
+ curvename = curve.openssl_name
+ assert curvename
+ # Python: create sk, vk, sign.
+ # OpenSSL: read vk(4), checksig(6), read sk(2), sign, check
+ mdarg = self.get_openssl_messagedigest_arg(hash_name)
+ if os.path.isdir("t"): # pragma: no cover
+ shutil.rmtree("t")
+ os.mkdir("t")
+ sk = SigningKey.generate(curve=curve)
+ vk = sk.get_verifying_key()
+ data = b("data")
+ with open("t/pubkey.der", "wb") as e:
+ e.write(vk.to_der()) # 4
+ with open("t/pubkey.pem", "wb") as e:
+ e.write(vk.to_pem()) # 4
+ sig_der = sk.sign(
+ data,
+ hashfunc=partial(hashlib.new, hash_name),
+ sigencode=sigencode_der,
+ )
+
+ with open("t/data.sig", "wb") as e:
+ e.write(sig_der) # 6
+ with open("t/data.txt", "wb") as e:
+ e.write(data)
+ with open("t/baddata.txt", "wb") as e:
+ e.write(data + b("corrupt"))
+
+ self.assertRaises(
+ SubprocessError,
+ run_openssl,
+ "dgst %s -verify t/pubkey.der -keyform DER -signature t/data.sig t/baddata.txt"
+ % mdarg,
+ )
+ run_openssl(
+ "dgst %s -verify t/pubkey.der -keyform DER -signature t/data.sig t/data.txt"
+ % mdarg
+ )
+
+ with open("t/privkey.pem", "wb") as e:
+ e.write(sk.to_pem()) # 2
+ run_openssl(
+ "dgst %s -sign t/privkey.pem -out t/data.sig2 t/data.txt" % mdarg
+ )
+ run_openssl(
+ "dgst %s -verify t/pubkey.pem -signature t/data.sig2 t/data.txt"
+ % mdarg
+ )
+
+ with open("t/privkey-p8.pem", "wb") as e:
+ e.write(sk.to_pem(format="pkcs8"))
+ run_openssl(
+ "dgst %s -sign t/privkey-p8.pem -out t/data.sig3 t/data.txt"
+ % mdarg
+ )
+ run_openssl(
+ "dgst %s -verify t/pubkey.pem -signature t/data.sig3 t/data.txt"
+ % mdarg
+ )
+
+
+class TooSmallCurve(unittest.TestCase):
+ OPENSSL_SUPPORTED_CURVES = set(
+ c.split(":")[0].strip()
+ for c in run_openssl("ecparam -list_curves").split("\n")
+ )
+
+ @pytest.mark.skipif(
+ "prime192v1" not in OPENSSL_SUPPORTED_CURVES,
+ reason="system openssl does not support prime192v1",
+ )
+ def test_sign_too_small_curve_dont_allow_truncate_raises(self):
+ sk = SigningKey.generate(curve=NIST192p)
+ vk = sk.get_verifying_key()
+ data = b("data")
+ with self.assertRaises(BadDigestError):
+ sk.sign(
+ data,
+ hashfunc=partial(hashlib.new, "SHA256"),
+ sigencode=sigencode_der,
+ allow_truncate=False,
+ )
+
+ @pytest.mark.skipif(
+ "prime192v1" not in OPENSSL_SUPPORTED_CURVES,
+ reason="system openssl does not support prime192v1",
+ )
+ def test_verify_too_small_curve_dont_allow_truncate_raises(self):
+ sk = SigningKey.generate(curve=NIST192p)
+ vk = sk.get_verifying_key()
+ data = b("data")
+ sig_der = sk.sign(
+ data,
+ hashfunc=partial(hashlib.new, "SHA256"),
+ sigencode=sigencode_der,
+ allow_truncate=True,
+ )
+ with self.assertRaises(BadDigestError):
+ vk.verify(
+ sig_der,
+ data,
+ hashfunc=partial(hashlib.new, "SHA256"),
+ sigdecode=sigdecode_der,
+ allow_truncate=False,
+ )
+
+
+class DER(unittest.TestCase):
+ def test_integer(self):
+ self.assertEqual(der.encode_integer(0), b("\x02\x01\x00"))
+ self.assertEqual(der.encode_integer(1), b("\x02\x01\x01"))
+ self.assertEqual(der.encode_integer(127), b("\x02\x01\x7f"))
+ self.assertEqual(der.encode_integer(128), b("\x02\x02\x00\x80"))
+ self.assertEqual(der.encode_integer(256), b("\x02\x02\x01\x00"))
+ # self.assertEqual(der.encode_integer(-1), b("\x02\x01\xff"))
+
+ def s(n):
+ return der.remove_integer(der.encode_integer(n) + b("junk"))
+
+ self.assertEqual(s(0), (0, b("junk")))
+ self.assertEqual(s(1), (1, b("junk")))
+ self.assertEqual(s(127), (127, b("junk")))
+ self.assertEqual(s(128), (128, b("junk")))
+ self.assertEqual(s(256), (256, b("junk")))
+ self.assertEqual(
+ s(1234567890123456789012345678901234567890),
+ (1234567890123456789012345678901234567890, b("junk")),
+ )
+
+ def test_number(self):
+ self.assertEqual(der.encode_number(0), b("\x00"))
+ self.assertEqual(der.encode_number(127), b("\x7f"))
+ self.assertEqual(der.encode_number(128), b("\x81\x00"))
+ self.assertEqual(der.encode_number(3 * 128 + 7), b("\x83\x07"))
+ # self.assertEqual(der.read_number("\x81\x9b" + "more"), (155, 2))
+ # self.assertEqual(der.encode_number(155), b("\x81\x9b"))
+ for n in (0, 1, 2, 127, 128, 3 * 128 + 7, 840, 10045): # , 155):
+ x = der.encode_number(n) + b("more")
+ n1, llen = der.read_number(x)
+ self.assertEqual(n1, n)
+ self.assertEqual(x[llen:], b("more"))
+
+ def test_length(self):
+ self.assertEqual(der.encode_length(0), b("\x00"))
+ self.assertEqual(der.encode_length(127), b("\x7f"))
+ self.assertEqual(der.encode_length(128), b("\x81\x80"))
+ self.assertEqual(der.encode_length(255), b("\x81\xff"))
+ self.assertEqual(der.encode_length(256), b("\x82\x01\x00"))
+ self.assertEqual(der.encode_length(3 * 256 + 7), b("\x82\x03\x07"))
+ self.assertEqual(der.read_length(b("\x81\x9b") + b("more")), (155, 2))
+ self.assertEqual(der.encode_length(155), b("\x81\x9b"))
+ for n in (0, 1, 2, 127, 128, 255, 256, 3 * 256 + 7, 155):
+ x = der.encode_length(n) + b("more")
+ n1, llen = der.read_length(x)
+ self.assertEqual(n1, n)
+ self.assertEqual(x[llen:], b("more"))
+
+ def test_sequence(self):
+ x = der.encode_sequence(b("ABC"), b("DEF")) + b("GHI")
+ self.assertEqual(x, b("\x30\x06ABCDEFGHI"))
+ x1, rest = der.remove_sequence(x)
+ self.assertEqual(x1, b("ABCDEF"))
+ self.assertEqual(rest, b("GHI"))
+
+ def test_constructed(self):
+ x = der.encode_constructed(0, NIST224p.encoded_oid)
+ self.assertEqual(hexlify(x), b("a007") + b("06052b81040021"))
+ x = der.encode_constructed(1, unhexlify(b("0102030a0b0c")))
+ self.assertEqual(hexlify(x), b("a106") + b("0102030a0b0c"))
+
+
+class Util(unittest.TestCase):
+ def test_trytryagain(self):
+ tta = util.randrange_from_seed__trytryagain
+ for i in range(1000):
+ seed = "seed-%d" % i
+ for order in (
+ 2 ** 8 - 2,
+ 2 ** 8 - 1,
+ 2 ** 8,
+ 2 ** 8 + 1,
+ 2 ** 8 + 2,
+ 2 ** 16 - 1,
+ 2 ** 16 + 1,
+ ):
+ n = tta(seed, order)
+ self.assertTrue(1 <= n < order, (1, n, order))
+ # this trytryagain *does* provide long-term stability
+ self.assertEqual(
+ ("%x" % (tta("seed", NIST224p.order))).encode(),
+ b("6fa59d73bf0446ae8743cf748fc5ac11d5585a90356417e97155c3bc"),
+ )
+
+ @given(st.integers(min_value=0, max_value=10 ** 200))
+ def test_randrange(self, i):
+ # util.randrange does not provide long-term stability: we might
+ # change the algorithm in the future.
+ entropy = util.PRNG("seed-%d" % i)
+ for order in (
+ 2 ** 8 - 2,
+ 2 ** 8 - 1,
+ 2 ** 8,
+ 2 ** 16 - 1,
+ 2 ** 16 + 1,
+ ):
+ # that oddball 2**16+1 takes half our runtime
+ n = util.randrange(order, entropy=entropy)
+ self.assertTrue(1 <= n < order, (1, n, order))
+
+ def OFF_test_prove_uniformity(self): # pragma: no cover
+ order = 2 ** 8 - 2
+ counts = dict([(i, 0) for i in range(1, order)])
+ assert 0 not in counts
+ assert order not in counts
+ for i in range(1000000):
+ seed = "seed-%d" % i
+ n = util.randrange_from_seed__trytryagain(seed, order)
+ counts[n] += 1
+ # this technique should use the full range
+ self.assertTrue(counts[order - 1])
+ for i in range(1, order):
+ print_("%3d: %s" % (i, "*" * (counts[i] // 100)))
+
+
+class RFC6979(unittest.TestCase):
+ # https://tools.ietf.org/html/rfc6979#appendix-A.1
+ def _do(self, generator, secexp, hsh, hash_func, expected):
+ actual = rfc6979.generate_k(generator.order(), secexp, hash_func, hsh)
+ self.assertEqual(expected, actual)
+
+ def test_SECP256k1(self):
+ """RFC doesn't contain test vectors for SECP256k1 used in bitcoin.
+ This vector has been computed by Golang reference implementation instead."""
+ self._do(
+ generator=SECP256k1.generator,
+ secexp=int("9d0219792467d7d37b4d43298a7d0c05", 16),
+ hsh=sha256(b("sample")).digest(),
+ hash_func=sha256,
+ expected=int(
+ "8fa1f95d514760e498f28957b824ee6ec39ed64826ff4fecc2b5739ec45b91cd",
+ 16,
+ ),
+ )
+
+ def test_SECP256k1_2(self):
+ self._do(
+ generator=SECP256k1.generator,
+ secexp=int(
+ "cca9fbcc1b41e5a95d369eaa6ddcff73b61a4efaa279cfc6567e8daa39cbaf50",
+ 16,
+ ),
+ hsh=sha256(b("sample")).digest(),
+ hash_func=sha256,
+ expected=int(
+ "2df40ca70e639d89528a6b670d9d48d9165fdc0febc0974056bdce192b8e16a3",
+ 16,
+ ),
+ )
+
+ def test_SECP256k1_3(self):
+ self._do(
+ generator=SECP256k1.generator,
+ secexp=0x1,
+ hsh=sha256(b("Satoshi Nakamoto")).digest(),
+ hash_func=sha256,
+ expected=0x8F8A276C19F4149656B280621E358CCE24F5F52542772691EE69063B74F15D15,
+ )
+
+ def test_SECP256k1_4(self):
+ self._do(
+ generator=SECP256k1.generator,
+ secexp=0x1,
+ hsh=sha256(
+ b(
+ "All those moments will be lost in time, like tears in rain. Time to die..."
+ )
+ ).digest(),
+ hash_func=sha256,
+ expected=0x38AA22D72376B4DBC472E06C3BA403EE0A394DA63FC58D88686C611ABA98D6B3,
+ )
+
+ def test_SECP256k1_5(self):
+ self._do(
+ generator=SECP256k1.generator,
+ secexp=0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364140,
+ hsh=sha256(b("Satoshi Nakamoto")).digest(),
+ hash_func=sha256,
+ expected=0x33A19B60E25FB6F4435AF53A3D42D493644827367E6453928554F43E49AA6F90,
+ )
+
+ def test_SECP256k1_6(self):
+ self._do(
+ generator=SECP256k1.generator,
+ secexp=0xF8B8AF8CE3C7CCA5E300D33939540C10D45CE001B8F252BFBC57BA0342904181,
+ hsh=sha256(b("Alan Turing")).digest(),
+ hash_func=sha256,
+ expected=0x525A82B70E67874398067543FD84C83D30C175FDC45FDEEE082FE13B1D7CFDF1,
+ )
+
+ def test_1(self):
+ # Basic example of the RFC, it also tests 'try-try-again' from Step H of rfc6979
+ self._do(
+ generator=Point(
+ None,
+ 0,
+ 0,
+ int("4000000000000000000020108A2E0CC0D99F8A5EF", 16),
+ ),
+ secexp=int("09A4D6792295A7F730FC3F2B49CBC0F62E862272F", 16),
+ hsh=unhexlify(
+ b(
+ "AF2BDBE1AA9B6EC1E2ADE1D694F41FC71A831D0268E9891562113D8A62ADD1BF"
+ )
+ ),
+ hash_func=sha256,
+ expected=int("23AF4074C90A02B3FE61D286D5C87F425E6BDD81B", 16),
+ )
+
+ def test_2(self):
+ self._do(
+ generator=NIST192p.generator,
+ secexp=int("6FAB034934E4C0FC9AE67F5B5659A9D7D1FEFD187EE09FD4", 16),
+ hsh=sha1(b("sample")).digest(),
+ hash_func=sha1,
+ expected=int(
+ "37D7CA00D2C7B0E5E412AC03BD44BA837FDD5B28CD3B0021", 16
+ ),
+ )
+
+ def test_3(self):
+ self._do(
+ generator=NIST192p.generator,
+ secexp=int("6FAB034934E4C0FC9AE67F5B5659A9D7D1FEFD187EE09FD4", 16),
+ hsh=sha256(b("sample")).digest(),
+ hash_func=sha256,
+ expected=int(
+ "32B1B6D7D42A05CB449065727A84804FB1A3E34D8F261496", 16
+ ),
+ )
+
+ def test_4(self):
+ self._do(
+ generator=NIST192p.generator,
+ secexp=int("6FAB034934E4C0FC9AE67F5B5659A9D7D1FEFD187EE09FD4", 16),
+ hsh=sha512(b("sample")).digest(),
+ hash_func=sha512,
+ expected=int(
+ "A2AC7AB055E4F20692D49209544C203A7D1F2C0BFBC75DB1", 16
+ ),
+ )
+
+ def test_5(self):
+ self._do(
+ generator=NIST192p.generator,
+ secexp=int("6FAB034934E4C0FC9AE67F5B5659A9D7D1FEFD187EE09FD4", 16),
+ hsh=sha1(b("test")).digest(),
+ hash_func=sha1,
+ expected=int(
+ "D9CF9C3D3297D3260773A1DA7418DB5537AB8DD93DE7FA25", 16
+ ),
+ )
+
+ def test_6(self):
+ self._do(
+ generator=NIST192p.generator,
+ secexp=int("6FAB034934E4C0FC9AE67F5B5659A9D7D1FEFD187EE09FD4", 16),
+ hsh=sha256(b("test")).digest(),
+ hash_func=sha256,
+ expected=int(
+ "5C4CE89CF56D9E7C77C8585339B006B97B5F0680B4306C6C", 16
+ ),
+ )
+
+ def test_7(self):
+ self._do(
+ generator=NIST192p.generator,
+ secexp=int("6FAB034934E4C0FC9AE67F5B5659A9D7D1FEFD187EE09FD4", 16),
+ hsh=sha512(b("test")).digest(),
+ hash_func=sha512,
+ expected=int(
+ "0758753A5254759C7CFBAD2E2D9B0792EEE44136C9480527", 16
+ ),
+ )
+
+ def test_8(self):
+ self._do(
+ generator=NIST521p.generator,
+ secexp=int(
+ "0FAD06DAA62BA3B25D2FB40133DA757205DE67F5BB0018FEE8C86E1B68C7E75CAA896EB32F1F47C70855836A6D16FCC1466F6D8FBEC67DB89EC0C08B0E996B83538",
+ 16,
+ ),
+ hsh=sha1(b("sample")).digest(),
+ hash_func=sha1,
+ expected=int(
+ "089C071B419E1C2820962321787258469511958E80582E95D8378E0C2CCDB3CB42BEDE42F50E3FA3C71F5A76724281D31D9C89F0F91FC1BE4918DB1C03A5838D0F9",
+ 16,
+ ),
+ )
+
+ def test_9(self):
+ self._do(
+ generator=NIST521p.generator,
+ secexp=int(
+ "0FAD06DAA62BA3B25D2FB40133DA757205DE67F5BB0018FEE8C86E1B68C7E75CAA896EB32F1F47C70855836A6D16FCC1466F6D8FBEC67DB89EC0C08B0E996B83538",
+ 16,
+ ),
+ hsh=sha256(b("sample")).digest(),
+ hash_func=sha256,
+ expected=int(
+ "0EDF38AFCAAECAB4383358B34D67C9F2216C8382AAEA44A3DAD5FDC9C32575761793FEF24EB0FC276DFC4F6E3EC476752F043CF01415387470BCBD8678ED2C7E1A0",
+ 16,
+ ),
+ )
+
+ def test_10(self):
+ self._do(
+ generator=NIST521p.generator,
+ secexp=int(
+ "0FAD06DAA62BA3B25D2FB40133DA757205DE67F5BB0018FEE8C86E1B68C7E75CAA896EB32F1F47C70855836A6D16FCC1466F6D8FBEC67DB89EC0C08B0E996B83538",
+ 16,
+ ),
+ hsh=sha512(b("test")).digest(),
+ hash_func=sha512,
+ expected=int(
+ "16200813020EC986863BEDFC1B121F605C1215645018AEA1A7B215A564DE9EB1B38A67AA1128B80CE391C4FB71187654AAA3431027BFC7F395766CA988C964DC56D",
+ 16,
+ ),
+ )
+
+
+class ECDH(unittest.TestCase):
+ def _do(self, curve, generator, dA, x_qA, y_qA, dB, x_qB, y_qB, x_Z, y_Z):
+ qA = dA * generator
+ qB = dB * generator
+ Z = dA * qB
+ self.assertEqual(Point(curve, x_qA, y_qA), qA)
+ self.assertEqual(Point(curve, x_qB, y_qB), qB)
+ self.assertTrue(
+ (dA * qB)
+ == (dA * dB * generator)
+ == (dB * dA * generator)
+ == (dB * qA)
+ )
+ self.assertEqual(Point(curve, x_Z, y_Z), Z)
+
+
+class RFC6932(ECDH):
+ # https://tools.ietf.org/html/rfc6932#appendix-A.1
+
+ def test_brainpoolP224r1(self):
+ self._do(
+ curve=curve_brainpoolp224r1,
+ generator=BRAINPOOLP224r1.generator,
+ dA=int(
+ "7C4B7A2C8A4BAD1FBB7D79CC0955DB7C6A4660CA64CC4778159B495E", 16
+ ),
+ x_qA=int(
+ "B104A67A6F6E85E14EC1825E1539E8ECDBBF584922367DD88C6BDCF2", 16
+ ),
+ y_qA=int(
+ "46D782E7FDB5F60CD8404301AC5949C58EDB26BC68BA07695B750A94", 16
+ ),
+ dB=int(
+ "63976D4AAE6CD0F6DD18DEFEF55D96569D0507C03E74D6486FFA28FB", 16
+ ),
+ x_qB=int(
+ "2A97089A9296147B71B21A4B574E1278245B536F14D8C2B9D07A874E", 16
+ ),
+ y_qB=int(
+ "9B900D7C77A709A797276B8CA1BA61BB95B546FC29F862E44D59D25B", 16
+ ),
+ x_Z=int(
+ "312DFD98783F9FB77B9704945A73BEB6DCCBE3B65D0F967DCAB574EB", 16
+ ),
+ y_Z=int(
+ "6F800811D64114B1C48C621AB3357CF93F496E4238696A2A012B3C98", 16
+ ),
+ )
+
+ def test_brainpoolP256r1(self):
+ self._do(
+ curve=curve_brainpoolp256r1,
+ generator=BRAINPOOLP256r1.generator,
+ dA=int(
+ "041EB8B1E2BC681BCE8E39963B2E9FC415B05283313DD1A8BCC055F11AE"
+ "49699",
+ 16,
+ ),
+ x_qA=int(
+ "78028496B5ECAAB3C8B6C12E45DB1E02C9E4D26B4113BC4F015F60C5C"
+ "CC0D206",
+ 16,
+ ),
+ y_qA=int(
+ "A2AE1762A3831C1D20F03F8D1E3C0C39AFE6F09B4D44BBE80CD100987"
+ "B05F92B",
+ 16,
+ ),
+ dB=int(
+ "06F5240EACDB9837BC96D48274C8AA834B6C87BA9CC3EEDD81F99A16B8D"
+ "804D3",
+ 16,
+ ),
+ x_qB=int(
+ "8E07E219BA588916C5B06AA30A2F464C2F2ACFC1610A3BE2FB240B635"
+ "341F0DB",
+ 16,
+ ),
+ y_qB=int(
+ "148EA1D7D1E7E54B9555B6C9AC90629C18B63BEE5D7AA6949EBBF47B2"
+ "4FDE40D",
+ 16,
+ ),
+ x_Z=int(
+ "05E940915549E9F6A4A75693716E37466ABA79B4BF2919877A16DD2CC2"
+ "E23708",
+ 16,
+ ),
+ y_Z=int(
+ "6BC23B6702BC5A019438CEEA107DAAD8B94232FFBBC350F3B137628FE6"
+ "FD134C",
+ 16,
+ ),
+ )
+
+ def test_brainpoolP384r1(self):
+ self._do(
+ curve=curve_brainpoolp384r1,
+ generator=BRAINPOOLP384r1.generator,
+ dA=int(
+ "014EC0755B78594BA47FB0A56F6173045B4331E74BA1A6F47322E70D79D"
+ "828D97E095884CA72B73FDABD5910DF0FA76A",
+ 16,
+ ),
+ x_qA=int(
+ "45CB26E4384DAF6FB776885307B9A38B7AD1B5C692E0C32F012533277"
+ "8F3B8D3F50CA358099B30DEB5EE69A95C058B4E",
+ 16,
+ ),
+ y_qA=int(
+ "8173A1C54AFFA7E781D0E1E1D12C0DC2B74F4DF58E4A4E3AF7026C5D3"
+ "2DC530A2CD89C859BB4B4B768497F49AB8CC859",
+ 16,
+ ),
+ dB=int(
+ "6B461CB79BD0EA519A87D6828815D8CE7CD9B3CAA0B5A8262CBCD550A01"
+ "5C90095B976F3529957506E1224A861711D54",
+ 16,
+ ),
+ x_qB=int(
+ "01BF92A92EE4BE8DED1A911125C209B03F99E3161CFCC986DC7711383"
+ "FC30AF9CE28CA3386D59E2C8D72CE1E7B4666E8",
+ 16,
+ ),
+ y_qB=int(
+ "3289C4A3A4FEE035E39BDB885D509D224A142FF9FBCC5CFE5CCBB3026"
+ "8EE47487ED8044858D31D848F7A95C635A347AC",
+ 16,
+ ),
+ x_Z=int(
+ "04CC4FF3DCCCB07AF24E0ACC529955B36D7C807772B92FCBE48F3AFE9A"
+ "2F370A1F98D3FA73FD0C0747C632E12F1423EC",
+ 16,
+ ),
+ y_Z=int(
+ "7F465F90BD69AFB8F828A214EB9716D66ABC59F17AF7C75EE7F1DE22AB"
+ "5D05085F5A01A9382D05BF72D96698FE3FF64E",
+ 16,
+ ),
+ )
+
+ def test_brainpoolP512r1(self):
+ self._do(
+ curve=curve_brainpoolp512r1,
+ generator=BRAINPOOLP512r1.generator,
+ dA=int(
+ "636B6BE0482A6C1C41AA7AE7B245E983392DB94CECEA2660A379CFE1595"
+ "59E357581825391175FC195D28BAC0CF03A7841A383B95C262B98378287"
+ "4CCE6FE333",
+ 16,
+ ),
+ x_qA=int(
+ "0562E68B9AF7CBFD5565C6B16883B777FF11C199161ECC427A39D17EC"
+ "2166499389571D6A994977C56AD8252658BA8A1B72AE42F4FB7532151"
+ "AFC3EF0971CCDA",
+ 16,
+ ),
+ y_qA=int(
+ "A7CA2D8191E21776A89860AFBC1F582FAA308D551C1DC6133AF9F9C3C"
+ "AD59998D70079548140B90B1F311AFB378AA81F51B275B2BE6B7DEE97"
+ "8EFC7343EA642E",
+ 16,
+ ),
+ dB=int(
+ "0AF4E7F6D52EDD52907BB8DBAB3992A0BB696EC10DF11892FF205B66D38"
+ "1ECE72314E6A6EA079CEA06961DBA5AE6422EF2E9EE803A1F236FB96A17"
+ "99B86E5C8B",
+ 16,
+ ),
+ x_qB=int(
+ "5A7954E32663DFF11AE24712D87419F26B708AC2B92877D6BFEE2BFC4"
+ "3714D89BBDB6D24D807BBD3AEB7F0C325F862E8BADE4F74636B97EAAC"
+ "E739E11720D323",
+ 16,
+ ),
+ y_qB=int(
+ "96D14621A9283A1BED84DE8DD64836B2C0758B11441179DC0C54C0D49"
+ "A47C03807D171DD544B72CAAEF7B7CE01C7753E2CAD1A861ECA55A719"
+ "54EE1BA35E04BE",
+ 16,
+ ),
+ x_Z=int(
+ "1EE8321A4BBF93B9CF8921AB209850EC9B7066D1984EF08C2BB7232362"
+ "08AC8F1A483E79461A00E0D5F6921CE9D360502F85C812BEDEE23AC5B2"
+ "10E5811B191E",
+ 16,
+ ),
+ y_Z=int(
+ "2632095B7B936174B41FD2FAF369B1D18DCADEED7E410A7E251F083109"
+ "7C50D02CFED02607B6A2D5ADB4C0006008562208631875B58B54ECDA5A"
+ "4F9FE9EAABA6",
+ 16,
+ ),
+ )
+
+
+class RFC7027(ECDH):
+ # https://tools.ietf.org/html/rfc7027#appendix-A
+
+ def test_brainpoolP256r1(self):
+ self._do(
+ curve=curve_brainpoolp256r1,
+ generator=BRAINPOOLP256r1.generator,
+ dA=int(
+ "81DB1EE100150FF2EA338D708271BE38300CB54241D79950F77B0630398"
+ "04F1D",
+ 16,
+ ),
+ x_qA=int(
+ "44106E913F92BC02A1705D9953A8414DB95E1AAA49E81D9E85F929A8E"
+ "3100BE5",
+ 16,
+ ),
+ y_qA=int(
+ "8AB4846F11CACCB73CE49CBDD120F5A900A69FD32C272223F789EF10E"
+ "B089BDC",
+ 16,
+ ),
+ dB=int(
+ "55E40BC41E37E3E2AD25C3C6654511FFA8474A91A0032087593852D3E7D"
+ "76BD3",
+ 16,
+ ),
+ x_qB=int(
+ "8D2D688C6CF93E1160AD04CC4429117DC2C41825E1E9FCA0ADDD34E6F"
+ "1B39F7B",
+ 16,
+ ),
+ y_qB=int(
+ "990C57520812BE512641E47034832106BC7D3E8DD0E4C7F1136D70065"
+ "47CEC6A",
+ 16,
+ ),
+ x_Z=int(
+ "89AFC39D41D3B327814B80940B042590F96556EC91E6AE7939BCE31F3A"
+ "18BF2B",
+ 16,
+ ),
+ y_Z=int(
+ "49C27868F4ECA2179BFD7D59B1E3BF34C1DBDE61AE12931648F43E5963"
+ "2504DE",
+ 16,
+ ),
+ )
+
+ def test_brainpoolP384r1(self):
+ self._do(
+ curve=curve_brainpoolp384r1,
+ generator=BRAINPOOLP384r1.generator,
+ dA=int(
+ "1E20F5E048A5886F1F157C74E91BDE2B98C8B52D58E5003D57053FC4B0B"
+ "D65D6F15EB5D1EE1610DF870795143627D042",
+ 16,
+ ),
+ x_qA=int(
+ "68B665DD91C195800650CDD363C625F4E742E8134667B767B1B476793"
+ "588F885AB698C852D4A6E77A252D6380FCAF068",
+ 16,
+ ),
+ y_qA=int(
+ "55BC91A39C9EC01DEE36017B7D673A931236D2F1F5C83942D049E3FA2"
+ "0607493E0D038FF2FD30C2AB67D15C85F7FAA59",
+ 16,
+ ),
+ dB=int(
+ "032640BC6003C59260F7250C3DB58CE647F98E1260ACCE4ACDA3DD869F7"
+ "4E01F8BA5E0324309DB6A9831497ABAC96670",
+ 16,
+ ),
+ x_qB=int(
+ "4D44326F269A597A5B58BBA565DA5556ED7FD9A8A9EB76C25F46DB69D"
+ "19DC8CE6AD18E404B15738B2086DF37E71D1EB4",
+ 16,
+ ),
+ y_qB=int(
+ "62D692136DE56CBE93BF5FA3188EF58BC8A3A0EC6C1E151A21038A42E"
+ "9185329B5B275903D192F8D4E1F32FE9CC78C48",
+ 16,
+ ),
+ x_Z=int(
+ "0BD9D3A7EA0B3D519D09D8E48D0785FB744A6B355E6304BC51C229FBBC"
+ "E239BBADF6403715C35D4FB2A5444F575D4F42",
+ 16,
+ ),
+ y_Z=int(
+ "0DF213417EBE4D8E40A5F76F66C56470C489A3478D146DECF6DF0D94BA"
+ "E9E598157290F8756066975F1DB34B2324B7BD",
+ 16,
+ ),
+ )
+
+ def test_brainpoolP512r1(self):
+ self._do(
+ curve=curve_brainpoolp512r1,
+ generator=BRAINPOOLP512r1.generator,
+ dA=int(
+ "16302FF0DBBB5A8D733DAB7141C1B45ACBC8715939677F6A56850A38BD8"
+ "7BD59B09E80279609FF333EB9D4C061231FB26F92EEB04982A5F1D1764C"
+ "AD57665422",
+ 16,
+ ),
+ x_qA=int(
+ "0A420517E406AAC0ACDCE90FCD71487718D3B953EFD7FBEC5F7F27E28"
+ "C6149999397E91E029E06457DB2D3E640668B392C2A7E737A7F0BF044"
+ "36D11640FD09FD",
+ 16,
+ ),
+ y_qA=int(
+ "72E6882E8DB28AAD36237CD25D580DB23783961C8DC52DFA2EC138AD4"
+ "72A0FCEF3887CF62B623B2A87DE5C588301EA3E5FC269B373B60724F5"
+ "E82A6AD147FDE7",
+ 16,
+ ),
+ dB=int(
+ "230E18E1BCC88A362FA54E4EA3902009292F7F8033624FD471B5D8ACE49"
+ "D12CFABBC19963DAB8E2F1EBA00BFFB29E4D72D13F2224562F405CB8050"
+ "3666B25429",
+ 16,
+ ),
+ x_qB=int(
+ "9D45F66DE5D67E2E6DB6E93A59CE0BB48106097FF78A081DE781CDB31"
+ "FCE8CCBAAEA8DD4320C4119F1E9CD437A2EAB3731FA9668AB268D871D"
+ "EDA55A5473199F",
+ 16,
+ ),
+ y_qB=int(
+ "2FDC313095BCDD5FB3A91636F07A959C8E86B5636A1E930E8396049CB"
+ "481961D365CC11453A06C719835475B12CB52FC3C383BCE35E27EF194"
+ "512B71876285FA",
+ 16,
+ ),
+ x_Z=int(
+ "A7927098655F1F9976FA50A9D566865DC530331846381C87256BAF3226"
+ "244B76D36403C024D7BBF0AA0803EAFF405D3D24F11A9B5C0BEF679FE1"
+ "454B21C4CD1F",
+ 16,
+ ),
+ y_Z=int(
+ "7DB71C3DEF63212841C463E881BDCF055523BD368240E6C3143BD8DEF8"
+ "B3B3223B95E0F53082FF5E412F4222537A43DF1C6D25729DDB51620A83"
+ "2BE6A26680A2",
+ 16,
+ ),
+ )
+
+
+# https://tools.ietf.org/html/rfc4754#page-5
+ "w, gwx, gwy, k, msg, md, r, s, curve",
+ [
+ pytest.param(
+ "DC51D3866A15BACDE33D96F992FCA99DA7E6EF0934E7097559C27F1614C88A7F",
+ "2442A5CC0ECD015FA3CA31DC8E2BBC70BF42D60CBCA20085E0822CB04235E970",
+ "6FC98BD7E50211A4A27102FA3549DF79EBCB4BF246B80945CDDFE7D509BBFD7D",
+ "9E56F509196784D963D1C0A401510EE7ADA3DCC5DEE04B154BF61AF1D5A6DECE",
+ b"abc",
+ sha256,
+ "CB28E0999B9C7715FD0A80D8E47A77079716CBBF917DD72E97566EA1C066957C",
+ "86FA3BB4E26CAD5BF90B7F81899256CE7594BB1EA0C89212748BFF3B3D5B0315",
+ NIST256p,
+ id="ECDSA-256",
+ ),
+ pytest.param(
+ "0BEB646634BA87735D77AE4809A0EBEA865535DE4C1E1DCB692E84708E81A5AF"
+ "62E528C38B2A81B35309668D73524D9F",
+ "96281BF8DD5E0525CA049C048D345D3082968D10FEDF5C5ACA0C64E6465A97EA"
+ "5CE10C9DFEC21797415710721F437922",
+ "447688BA94708EB6E2E4D59F6AB6D7EDFF9301D249FE49C33096655F5D502FAD"
+ "3D383B91C5E7EDAA2B714CC99D5743CA",
+ "B4B74E44D71A13D568003D7489908D564C7761E229C58CBFA18950096EB7463B"
+ "854D7FA992F934D927376285E63414FA",
+ b"abc",
+ sha384,
+ "FB017B914E29149432D8BAC29A514640B46F53DDAB2C69948084E2930F1C8F7E"
+ "08E07C9C63F2D21A07DCB56A6AF56EB3",
+ "B263A1305E057F984D38726A1B46874109F417BCA112674C528262A40A629AF1"
+ "CBB9F516CE0FA7D2FF630863A00E8B9F",
+ NIST384p,
+ id="ECDSA-384",
+ ),
+ pytest.param(
+ "0065FDA3409451DCAB0A0EAD45495112A3D813C17BFD34BDF8C1209D7DF58491"
+ "20597779060A7FF9D704ADF78B570FFAD6F062E95C7E0C5D5481C5B153B48B37"
+ "5FA1",
+ "0151518F1AF0F563517EDD5485190DF95A4BF57B5CBA4CF2A9A3F6474725A35F"
+ "7AFE0A6DDEB8BEDBCD6A197E592D40188901CECD650699C9B5E456AEA5ADD190"
+ "52A8",
+ "006F3B142EA1BFFF7E2837AD44C9E4FF6D2D34C73184BBAD90026DD5E6E85317"
+ "D9DF45CAD7803C6C20035B2F3FF63AFF4E1BA64D1C077577DA3F4286C58F0AEA"
+ "E643",
+ "00C1C2B305419F5A41344D7E4359933D734096F556197A9B244342B8B62F46F9"
+ "373778F9DE6B6497B1EF825FF24F42F9B4A4BD7382CFC3378A540B1B7F0C1B95"
+ "6C2F",
+ b"abc",
+ sha512,
+ "0154FD3836AF92D0DCA57DD5341D3053988534FDE8318FC6AAAAB68E2E6F4339"
+ "B19F2F281A7E0B22C269D93CF8794A9278880ED7DBB8D9362CAEACEE54432055"
+ "2251",
+ "017705A7030290D1CEB605A9A1BB03FF9CDD521E87A696EC926C8C10C8362DF4"
+ "975367101F67D1CF9BCCBF2F3D239534FA509E70AAC851AE01AAC68D62F86647"
+ "2660",
+ NIST521p,
+ id="ECDSA-521",
+ ),
+ ],
+)
+def test_RFC4754_vectors(w, gwx, gwy, k, msg, md, r, s, curve):
+ sk = SigningKey.from_string(unhexlify(w), curve)
+ vk = VerifyingKey.from_string(unhexlify(gwx + gwy), curve)
+ assert sk.verifying_key == vk
+ sig = sk.sign(msg, hashfunc=md, sigencode=sigencode_strings, k=int(k, 16))
+
+ assert sig == (unhexlify(r), unhexlify(s))
+
+ assert vk.verify(sig, msg, md, sigdecode_strings)
diff --git a/frozen_deps/ecdsa/test_rw_lock.py b/frozen_deps/ecdsa/test_rw_lock.py
new file mode 100644
index 0000000..d360482
--- /dev/null
+++ b/frozen_deps/ecdsa/test_rw_lock.py
@@ -0,0 +1,177 @@
+# Copyright Mateusz Kobos, (c) 2011
+# https://code.activestate.com/recipes/577803-reader-writer-lock-with-priority-for-writers/
+# released under the MIT licence
+
+import unittest
+import threading
+import time
+import copy
+from ._rwlock import RWLock
+
+
+class Writer(threading.Thread):
+ def __init__(
+ self, buffer_, rw_lock, init_sleep_time, sleep_time, to_write
+ ):
+ """
+ @param buffer_: common buffer_ shared by the readers and writers
+ @type buffer_: list
+ @type rw_lock: L{RWLock}
+ @param init_sleep_time: sleep time before doing any action
+ @type init_sleep_time: C{float}
+ @param sleep_time: sleep time while in critical section
+ @type sleep_time: C{float}
+ @param to_write: data that will be appended to the buffer
+ """
+ threading.Thread.__init__(self)
+ self.__buffer = buffer_
+ self.__rw_lock = rw_lock
+ self.__init_sleep_time = init_sleep_time
+ self.__sleep_time = sleep_time
+ self.__to_write = to_write
+ self.entry_time = None
+ """Time of entry to the critical section"""
+ self.exit_time = None
+ """Time of exit from the critical section"""
+
+ def run(self):
+ time.sleep(self.__init_sleep_time)
+ self.__rw_lock.writer_acquire()
+ self.entry_time = time.time()
+ time.sleep(self.__sleep_time)
+ self.__buffer.append(self.__to_write)
+ self.exit_time = time.time()
+ self.__rw_lock.writer_release()
+
+
+class Reader(threading.Thread):
+ def __init__(self, buffer_, rw_lock, init_sleep_time, sleep_time):
+ """
+ @param buffer_: common buffer shared by the readers and writers
+ @type buffer_: list
+ @type rw_lock: L{RWLock}
+ @param init_sleep_time: sleep time before doing any action
+ @type init_sleep_time: C{float}
+ @param sleep_time: sleep time while in critical section
+ @type sleep_time: C{float}
+ """
+ threading.Thread.__init__(self)
+ self.__buffer = buffer_
+ self.__rw_lock = rw_lock
+ self.__init_sleep_time = init_sleep_time
+ self.__sleep_time = sleep_time
+ self.buffer_read = None
+ """a copy of a the buffer read while in critical section"""
+ self.entry_time = None
+ """Time of entry to the critical section"""
+ self.exit_time = None
+ """Time of exit from the critical section"""
+
+ def run(self):
+ time.sleep(self.__init_sleep_time)
+ self.__rw_lock.reader_acquire()
+ self.entry_time = time.time()
+ time.sleep(self.__sleep_time)
+ self.buffer_read = copy.deepcopy(self.__buffer)
+ self.exit_time = time.time()
+ self.__rw_lock.reader_release()
+
+
+class RWLockTestCase(unittest.TestCase):
+ def test_readers_nonexclusive_access(self):
+ (buffer_, rw_lock, threads) = self.__init_variables()
+
+ threads.append(Reader(buffer_, rw_lock, 0, 0))
+ threads.append(Writer(buffer_, rw_lock, 0.2, 0.4, 1))
+ threads.append(Reader(buffer_, rw_lock, 0.3, 0.3))
+ threads.append(Reader(buffer_, rw_lock, 0.5, 0))
+
+ self.__start_and_join_threads(threads)
+
+ ## The third reader should enter after the second one but it should
+ ## exit before the second one exits
+ ## (i.e. the readers should be in the critical section
+ ## at the same time)
+
+ self.assertEqual([], threads[0].buffer_read)
+ self.assertEqual([1], threads[2].buffer_read)
+ self.assertEqual([1], threads[3].buffer_read)
+ self.assertTrue(threads[1].exit_time <= threads[2].entry_time)
+ self.assertTrue(threads[2].entry_time <= threads[3].entry_time)
+ self.assertTrue(threads[3].exit_time < threads[2].exit_time)
+
+ def test_writers_exclusive_access(self):
+ (buffer_, rw_lock, threads) = self.__init_variables()
+
+ threads.append(Writer(buffer_, rw_lock, 0, 0.4, 1))
+ threads.append(Writer(buffer_, rw_lock, 0.1, 0, 2))
+ threads.append(Reader(buffer_, rw_lock, 0.2, 0))
+
+ self.__start_and_join_threads(threads)
+
+ ## The second writer should wait for the first one to exit
+
+ self.assertEqual([1, 2], threads[2].buffer_read)
+ self.assertTrue(threads[0].exit_time <= threads[1].entry_time)
+ self.assertTrue(threads[1].exit_time <= threads[2].exit_time)
+
+ def test_writer_priority(self):
+ (buffer_, rw_lock, threads) = self.__init_variables()
+
+ threads.append(Writer(buffer_, rw_lock, 0, 0, 1))
+ threads.append(Reader(buffer_, rw_lock, 0.1, 0.4))
+ threads.append(Writer(buffer_, rw_lock, 0.2, 0, 2))
+ threads.append(Reader(buffer_, rw_lock, 0.3, 0))
+ threads.append(Reader(buffer_, rw_lock, 0.3, 0))
+
+ self.__start_and_join_threads(threads)
+
+ ## The second writer should go before the second and the third reader
+
+ self.assertEqual([1], threads[1].buffer_read)
+ self.assertEqual([1, 2], threads[3].buffer_read)
+ self.assertEqual([1, 2], threads[4].buffer_read)
+ self.assertTrue(threads[0].exit_time < threads[1].entry_time)
+ self.assertTrue(threads[1].exit_time <= threads[2].entry_time)
+ self.assertTrue(threads[2].exit_time <= threads[3].entry_time)
+ self.assertTrue(threads[2].exit_time <= threads[4].entry_time)
+
+ def test_many_writers_priority(self):
+ (buffer_, rw_lock, threads) = self.__init_variables()
+
+ threads.append(Writer(buffer_, rw_lock, 0, 0, 1))
+ threads.append(Reader(buffer_, rw_lock, 0.1, 0.6))
+ threads.append(Writer(buffer_, rw_lock, 0.2, 0.1, 2))
+ threads.append(Reader(buffer_, rw_lock, 0.3, 0))
+ threads.append(Reader(buffer_, rw_lock, 0.4, 0))
+ threads.append(Writer(buffer_, rw_lock, 0.5, 0.1, 3))
+
+ self.__start_and_join_threads(threads)
+
+ ## The two last writers should go first -- after the first reader and
+ ## before the second and the third reader
+
+ self.assertEqual([1], threads[1].buffer_read)
+ self.assertEqual([1, 2, 3], threads[3].buffer_read)
+ self.assertEqual([1, 2, 3], threads[4].buffer_read)
+ self.assertTrue(threads[0].exit_time < threads[1].entry_time)
+ self.assertTrue(threads[1].exit_time <= threads[2].entry_time)
+ self.assertTrue(threads[1].exit_time <= threads[5].entry_time)
+ self.assertTrue(threads[2].exit_time <= threads[3].entry_time)
+ self.assertTrue(threads[2].exit_time <= threads[4].entry_time)
+ self.assertTrue(threads[5].exit_time <= threads[3].entry_time)
+ self.assertTrue(threads[5].exit_time <= threads[4].entry_time)
+
+ @staticmethod
+ def __init_variables():
+ buffer_ = []
+ rw_lock = RWLock()
+ threads = []
+ return (buffer_, rw_lock, threads)
+
+ @staticmethod
+ def __start_and_join_threads(threads):
+ for t in threads:
+ t.start()
+ for t in threads:
+ t.join()
diff --git a/frozen_deps/ecdsa/util.py b/frozen_deps/ecdsa/util.py
new file mode 100644
index 0000000..e77d61c
--- /dev/null
+++ b/frozen_deps/ecdsa/util.py
@@ -0,0 +1,435 @@
+from __future__ import division
+
+import os
+import math
+import binascii
+import sys
+from hashlib import sha256
+from six import PY2, int2byte, b, next
+from . import der
+from ._compat import normalise_bytes
+
+# RFC5480:
+# The "unrestricted" algorithm identifier is:
+# id-ecPublicKey OBJECT IDENTIFIER ::= {
+# iso(1) member-body(2) us(840) ansi-X9-62(10045) keyType(2) 1 }
+
+oid_ecPublicKey = (1, 2, 840, 10045, 2, 1)
+encoded_oid_ecPublicKey = der.encode_oid(*oid_ecPublicKey)
+
+# RFC5480:
+# The ECDH algorithm uses the following object identifier:
+# id-ecDH OBJECT IDENTIFIER ::= {
+# iso(1) identified-organization(3) certicom(132) schemes(1)
+# ecdh(12) }
+
+oid_ecDH = (1, 3, 132, 1, 12)
+
+# RFC5480:
+# The ECMQV algorithm uses the following object identifier:
+# id-ecMQV OBJECT IDENTIFIER ::= {
+# iso(1) identified-organization(3) certicom(132) schemes(1)
+# ecmqv(13) }
+
+oid_ecMQV = (1, 3, 132, 1, 13)
+
+if sys.version_info >= (3,):
+
+ def entropy_to_bits(ent_256):
+ """Convert a bytestring to string of 0's and 1's"""
+ return bin(int.from_bytes(ent_256, "big"))[2:].zfill(len(ent_256) * 8)
+
+
+else:
+
+ def entropy_to_bits(ent_256):
+ """Convert a bytestring to string of 0's and 1's"""
+ return "".join(bin(ord(x))[2:].zfill(8) for x in ent_256)
+
+
+if sys.version_info < (2, 7):
+ # Can't add a method to a built-in type so we are stuck with this
+ def bit_length(x):
+ return len(bin(x)) - 2
+
+
+else:
+
+ def bit_length(x):
+ return x.bit_length() or 1
+
+
+def orderlen(order):
+ return (1 + len("%x" % order)) // 2 # bytes
+
+
+def randrange(order, entropy=None):
+ """Return a random integer k such that 1 <= k < order, uniformly
+ distributed across that range. Worst case should be a mean of 2 loops at
+ (2**k)+2.
+
+ Note that this function is not declared to be forwards-compatible: we may
+ change the behavior in future releases. The entropy= argument (which
+ should get a callable that behaves like os.urandom) can be used to
+ achieve stability within a given release (for repeatable unit tests), but
+ should not be used as a long-term-compatible key generation algorithm.
+ """
+ assert order > 1
+ if entropy is None:
+ entropy = os.urandom
+ upper_2 = bit_length(order - 2)
+ upper_256 = upper_2 // 8 + 1
+ while True: # I don't think this needs a counter with bit-wise randrange
+ ent_256 = entropy(upper_256)
+ ent_2 = entropy_to_bits(ent_256)
+ rand_num = int(ent_2[:upper_2], base=2) + 1
+ if 0 < rand_num < order:
+ return rand_num
+
+
+class PRNG:
+ # this returns a callable which, when invoked with an integer N, will
+ # return N pseudorandom bytes. Note: this is a short-term PRNG, meant
+ # primarily for the needs of randrange_from_seed__trytryagain(), which
+ # only needs to run it a few times per seed. It does not provide
+ # protection against state compromise (forward security).
+ def __init__(self, seed):
+ self.generator = self.block_generator(seed)
+
+ def __call__(self, numbytes):
+ a = [next(self.generator) for i in range(numbytes)]
+
+ if PY2:
+ return "".join(a)
+ else:
+ return bytes(a)
+
+ def block_generator(self, seed):
+ counter = 0
+ while True:
+ for byte in sha256(
+ ("prng-%d-%s" % (counter, seed)).encode()
+ ).digest():
+ yield byte
+ counter += 1
+
+
+def randrange_from_seed__overshoot_modulo(seed, order):
+ # hash the data, then turn the digest into a number in [1,order).
+ #
+ # We use David-Sarah Hopwood's suggestion: turn it into a number that's
+ # sufficiently larger than the group order, then modulo it down to fit.
+ # This should give adequate (but not perfect) uniformity, and simple
+ # code. There are other choices: try-try-again is the main one.
+ base = PRNG(seed)(2 * orderlen(order))
+ number = (int(binascii.hexlify(base), 16) % (order - 1)) + 1
+ assert 1 <= number < order, (1, number, order)
+ return number
+
+
+def lsb_of_ones(numbits):
+ return (1 << numbits) - 1
+
+
+def bits_and_bytes(order):
+ bits = int(math.log(order - 1, 2) + 1)
+ bytes = bits // 8
+ extrabits = bits % 8
+ return bits, bytes, extrabits
+
+
+# the following randrange_from_seed__METHOD() functions take an
+# arbitrarily-sized secret seed and turn it into a number that obeys the same
+# range limits as randrange() above. They are meant for deriving consistent
+# signing keys from a secret rather than generating them randomly, for
+# example a protocol in which three signing keys are derived from a master
+# secret. You should use a uniformly-distributed unguessable seed with about
+# curve.baselen bytes of entropy. To use one, do this:
+# seed = os.urandom(curve.baselen) # or other starting point
+# secexp = ecdsa.util.randrange_from_seed__trytryagain(sed, curve.order)
+# sk = SigningKey.from_secret_exponent(secexp, curve)
+
+
+def randrange_from_seed__truncate_bytes(seed, order, hashmod=sha256):
+ # hash the seed, then turn the digest into a number in [1,order), but
+ # don't worry about trying to uniformly fill the range. This will lose,
+ # on average, four bits of entropy.
+ bits, _bytes, extrabits = bits_and_bytes(order)
+ if extrabits:
+ _bytes += 1
+ base = hashmod(seed).digest()[:_bytes]
+ base = "\x00" * (_bytes - len(base)) + base
+ number = 1 + int(binascii.hexlify(base), 16)
+ assert 1 <= number < order
+ return number
+
+
+def randrange_from_seed__truncate_bits(seed, order, hashmod=sha256):
+ # like string_to_randrange_truncate_bytes, but only lose an average of
+ # half a bit
+ bits = int(math.log(order - 1, 2) + 1)
+ maxbytes = (bits + 7) // 8
+ base = hashmod(seed).digest()[:maxbytes]
+ base = "\x00" * (maxbytes - len(base)) + base
+ topbits = 8 * maxbytes - bits
+ if topbits:
+ base = int2byte(ord(base[0]) & lsb_of_ones(topbits)) + base[1:]
+ number = 1 + int(binascii.hexlify(base), 16)
+ assert 1 <= number < order
+ return number
+
+
+def randrange_from_seed__trytryagain(seed, order):
+ # figure out exactly how many bits we need (rounded up to the nearest
+ # bit), so we can reduce the chance of looping to less than 0.5 . This is
+ # specified to feed from a byte-oriented PRNG, and discards the
+ # high-order bits of the first byte as necessary to get the right number
+ # of bits. The average number of loops will range from 1.0 (when
+ # order=2**k-1) to 2.0 (when order=2**k+1).
+ assert order > 1
+ bits, bytes, extrabits = bits_and_bytes(order)
+ generate = PRNG(seed)
+ while True:
+ extrabyte = b("")
+ if extrabits:
+ extrabyte = int2byte(ord(generate(1)) & lsb_of_ones(extrabits))
+ guess = string_to_number(extrabyte + generate(bytes)) + 1
+ if 1 <= guess < order:
+ return guess
+
+
+def number_to_string(num, order):
+ l = orderlen(order)
+ fmt_str = "%0" + str(2 * l) + "x"
+ string = binascii.unhexlify((fmt_str % num).encode())
+ assert len(string) == l, (len(string), l)
+ return string
+
+
+def number_to_string_crop(num, order):
+ l = orderlen(order)
+ fmt_str = "%0" + str(2 * l) + "x"
+ string = binascii.unhexlify((fmt_str % num).encode())
+ return string[:l]
+
+
+def string_to_number(string):
+ return int(binascii.hexlify(string), 16)
+
+
+def string_to_number_fixedlen(string, order):
+ l = orderlen(order)
+ assert len(string) == l, (len(string), l)
+ return int(binascii.hexlify(string), 16)
+
+
+# these methods are useful for the sigencode= argument to SK.sign() and the
+# sigdecode= argument to VK.verify(), and control how the signature is packed
+# or unpacked.
+
+
+def sigencode_strings(r, s, order):
+ r_str = number_to_string(r, order)
+ s_str = number_to_string(s, order)
+ return (r_str, s_str)
+
+
+def sigencode_string(r, s, order):
+ """
+ Encode the signature to raw format (:term:`raw encoding`)
+
+ It's expected that this function will be used as a `sigencode=` parameter
+ in :func:`ecdsa.keys.SigningKey.sign` method.
+
+ :param int r: first parameter of the signature
+ :param int s: second parameter of the signature
+ :param int order: the order of the curve over which the signature was
+ computed
+
+ :return: raw encoding of ECDSA signature
+ :rtype: bytes
+ """
+ # for any given curve, the size of the signature numbers is
+ # fixed, so just use simple concatenation
+ r_str, s_str = sigencode_strings(r, s, order)
+ return r_str + s_str
+
+
+def sigencode_der(r, s, order):
+ """
+ Encode the signature into the ECDSA-Sig-Value structure using :term:`DER`.
+
+ Encodes the signature to the following :term:`ASN.1` structure::
+
+ Ecdsa-Sig-Value ::= SEQUENCE {
+ r INTEGER,
+ s INTEGER
+ }
+
+ It's expected that this function will be used as a `sigencode=` parameter
+ in :func:`ecdsa.keys.SigningKey.sign` method.
+
+ :param int r: first parameter of the signature
+ :param int s: second parameter of the signature
+ :param int order: the order of the curve over which the signature was
+ computed
+
+ :return: DER encoding of ECDSA signature
+ :rtype: bytes
+ """
+ return der.encode_sequence(der.encode_integer(r), der.encode_integer(s))
+
+
+# canonical versions of sigencode methods
+# these enforce low S values, by negating the value (modulo the order) if
+# above order/2 see CECKey::Sign()
+# https://github.com/bitcoin/bitcoin/blob/master/src/key.cpp#L214
+def sigencode_strings_canonize(r, s, order):
+ if s > order / 2:
+ s = order - s
+ return sigencode_strings(r, s, order)
+
+
+def sigencode_string_canonize(r, s, order):
+ if s > order / 2:
+ s = order - s
+ return sigencode_string(r, s, order)
+
+
+def sigencode_der_canonize(r, s, order):
+ if s > order / 2:
+ s = order - s
+ return sigencode_der(r, s, order)
+
+
+class MalformedSignature(Exception):
+ """
+ Raised by decoding functions when the signature is malformed.
+
+ Malformed in this context means that the relevant strings or integers
+ do not match what a signature over provided curve would create. Either
+ because the byte strings have incorrect lengths or because the encoded
+ values are too large.
+ """
+
+ pass
+
+
+def sigdecode_string(signature, order):
+ """
+ Decoder for :term:`raw encoding` of ECDSA signatures.
+
+ raw encoding is a simple concatenation of the two integers that comprise
+ the signature, with each encoded using the same amount of bytes depending
+ on curve size/order.
+
+ It's expected that this function will be used as the `sigdecode=`
+ parameter to the :func:`ecdsa.keys.VerifyingKey.verify` method.
+
+ :param signature: encoded signature
+ :type signature: bytes like object
+ :param order: order of the curve over which the signature was computed
+ :type order: int
+
+ :raises MalformedSignature: when the encoding of the signature is invalid
+
+ :return: tuple with decoded 'r' and 's' values of signature
+ :rtype: tuple of ints
+ """
+ signature = normalise_bytes(signature)
+ l = orderlen(order)
+ if not len(signature) == 2 * l:
+ raise MalformedSignature(
+ "Invalid length of signature, expected {0} bytes long, "
+ "provided string is {1} bytes long".format(2 * l, len(signature))
+ )
+ r = string_to_number_fixedlen(signature[:l], order)
+ s = string_to_number_fixedlen(signature[l:], order)
+ return r, s
+
+
+def sigdecode_strings(rs_strings, order):
+ """
+ Decode the signature from two strings.
+
+ First string needs to be a big endian encoding of 'r', second needs to
+ be a big endian encoding of the 's' parameter of an ECDSA signature.
+
+ It's expected that this function will be used as the `sigdecode=`
+ parameter to the :func:`ecdsa.keys.VerifyingKey.verify` method.
+
+ :param list rs_strings: list of two bytes-like objects, each encoding one
+ parameter of signature
+ :param int order: order of the curve over which the signature was computed
+
+ :raises MalformedSignature: when the encoding of the signature is invalid
+
+ :return: tuple with decoded 'r' and 's' values of signature
+ :rtype: tuple of ints
+ """
+ if not len(rs_strings) == 2:
+ raise MalformedSignature(
+ "Invalid number of strings provided: {0}, expected 2".format(
+ len(rs_strings)
+ )
+ )
+ (r_str, s_str) = rs_strings
+ r_str = normalise_bytes(r_str)
+ s_str = normalise_bytes(s_str)
+ l = orderlen(order)
+ if not len(r_str) == l:
+ raise MalformedSignature(
+ "Invalid length of first string ('r' parameter), "
+ "expected {0} bytes long, provided string is {1} "
+ "bytes long".format(l, len(r_str))
+ )
+ if not len(s_str) == l:
+ raise MalformedSignature(
+ "Invalid length of second string ('s' parameter), "
+ "expected {0} bytes long, provided string is {1} "
+ "bytes long".format(l, len(s_str))
+ )
+ r = string_to_number_fixedlen(r_str, order)
+ s = string_to_number_fixedlen(s_str, order)
+ return r, s
+
+
+def sigdecode_der(sig_der, order):
+ """
+ Decoder for DER format of ECDSA signatures.
+
+ DER format of signature is one that uses the :term:`ASN.1` :term:`DER`
+ rules to encode it as a sequence of two integers::
+
+ Ecdsa-Sig-Value ::= SEQUENCE {
+ r INTEGER,
+ s INTEGER
+ }
+
+ It's expected that this function will be used as as the `sigdecode=`
+ parameter to the :func:`ecdsa.keys.VerifyingKey.verify` method.
+
+ :param sig_der: encoded signature
+ :type sig_der: bytes like object
+ :param order: order of the curve over which the signature was computed
+ :type order: int
+
+ :raises UnexpectedDER: when the encoding of signature is invalid
+
+ :return: tuple with decoded 'r' and 's' values of signature
+ :rtype: tuple of ints
+ """
+ sig_der = normalise_bytes(sig_der)
+ # return der.encode_sequence(der.encode_integer(r), der.encode_integer(s))
+ rs_strings, empty = der.remove_sequence(sig_der)
+ if empty != b"":
+ raise der.UnexpectedDER(
+ "trailing junk after DER sig: %s" % binascii.hexlify(empty)
+ )
+ r, rest = der.remove_integer(rs_strings)
+ s, empty = der.remove_integer(rest)
+ if empty != b"":
+ raise der.UnexpectedDER(
+ "trailing junk after DER numbers: %s" % binascii.hexlify(empty)
+ )
+ return r, s
diff --git a/frozen_deps/keytree.py-0.2.dist-info/INSTALLER b/frozen_deps/keytree.py-0.2.dist-info/INSTALLER
new file mode 100644
index 0000000..a1b589e
--- /dev/null
+++ b/frozen_deps/keytree.py-0.2.dist-info/INSTALLER
@@ -0,0 +1 @@
+pip
diff --git a/frozen_deps/keytree.py-0.2.dist-info/METADATA b/frozen_deps/keytree.py-0.2.dist-info/METADATA
new file mode 100644
index 0000000..ced8872
--- /dev/null
+++ b/frozen_deps/keytree.py-0.2.dist-info/METADATA
@@ -0,0 +1,18 @@
+Metadata-Version: 2.1
+Name: keytree.py
+Version: 0.2
+Summary: Derive BIP32 key pairs from BIP39 mnemonic
+Home-page: http://github.com/Determinant/keytree.py
+Author: Ted Yin
+Author-email: [email protected]
+License: MIT
+Platform: UNKNOWN
+Requires-Dist: ecdsa
+Requires-Dist: base58
+Requires-Dist: pysha3
+Requires-Dist: pycrypto
+Requires-Dist: mnemonic
+
+UNKNOWN
+
+
diff --git a/frozen_deps/keytree.py-0.2.dist-info/RECORD b/frozen_deps/keytree.py-0.2.dist-info/RECORD
new file mode 100644
index 0000000..6d5e4e7
--- /dev/null
+++ b/frozen_deps/keytree.py-0.2.dist-info/RECORD
@@ -0,0 +1,10 @@
+../../bin/__pycache__/keytree.cpython-38.pyc,,
+../../bin/keytree.py,sha256=3ZAMRh7CeqEydctLUTqBLfcgiVZlDfmcsDfUWcxLYjw,10394
+__pycache__/bech32.cpython-38.pyc,,
+bech32.py,sha256=QZdU7nY1UUzeYfV-5ASwhe3PA3YVVnClyGGrtgJIjsE,4376
+keytree.py-0.2.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4
+keytree.py-0.2.dist-info/METADATA,sha256=mbeKpm8oSaMl3-pBpqeonURUlfmadsd0gw7rt8ZVm1w,363
+keytree.py-0.2.dist-info/RECORD,,
+keytree.py-0.2.dist-info/WHEEL,sha256=g4nMs7d-Xl9-xC9XovUrsDHGXt-FT0E17Yqo92DEfvY,92
+keytree.py-0.2.dist-info/direct_url.json,sha256=6seyiOxGCRXsnt6lrEcpcJtZGEXuBr-KHa0idXAuZDA,71
+keytree.py-0.2.dist-info/top_level.txt,sha256=oESACl4kH99axdjvTQuJATlgqujLpRc8iCwiqjvbI8M,7
diff --git a/frozen_deps/keytree.py-0.2.dist-info/WHEEL b/frozen_deps/keytree.py-0.2.dist-info/WHEEL
new file mode 100644
index 0000000..b552003
--- /dev/null
+++ b/frozen_deps/keytree.py-0.2.dist-info/WHEEL
@@ -0,0 +1,5 @@
+Wheel-Version: 1.0
+Generator: bdist_wheel (0.34.2)
+Root-Is-Purelib: true
+Tag: py3-none-any
+
diff --git a/frozen_deps/keytree.py-0.2.dist-info/direct_url.json b/frozen_deps/keytree.py-0.2.dist-info/direct_url.json
new file mode 100644
index 0000000..650a846
--- /dev/null
+++ b/frozen_deps/keytree.py-0.2.dist-info/direct_url.json
@@ -0,0 +1 @@
+{"dir_info": {}, "url": "file:///home/ymf/work/2020_summer/keytree.py"} \ No newline at end of file
diff --git a/frozen_deps/keytree.py-0.2.dist-info/top_level.txt b/frozen_deps/keytree.py-0.2.dist-info/top_level.txt
new file mode 100644
index 0000000..e5e2a6a
--- /dev/null
+++ b/frozen_deps/keytree.py-0.2.dist-info/top_level.txt
@@ -0,0 +1 @@
+bech32
diff --git a/frozen_deps/mnemonic-0.19.dist-info/AUTHORS b/frozen_deps/mnemonic-0.19.dist-info/AUTHORS
new file mode 100644
index 0000000..34ed344
--- /dev/null
+++ b/frozen_deps/mnemonic-0.19.dist-info/AUTHORS
@@ -0,0 +1,2 @@
+Marek Palatinus <[email protected]>
+Pavol Rusnak <[email protected]>
diff --git a/frozen_deps/mnemonic-0.19.dist-info/INSTALLER b/frozen_deps/mnemonic-0.19.dist-info/INSTALLER
new file mode 100644
index 0000000..a1b589e
--- /dev/null
+++ b/frozen_deps/mnemonic-0.19.dist-info/INSTALLER
@@ -0,0 +1 @@
+pip
diff --git a/frozen_deps/mnemonic-0.19.dist-info/LICENSE b/frozen_deps/mnemonic-0.19.dist-info/LICENSE
new file mode 100644
index 0000000..b135744
--- /dev/null
+++ b/frozen_deps/mnemonic-0.19.dist-info/LICENSE
@@ -0,0 +1,21 @@
+The MIT License (MIT)
+
+Copyright (c) 2013-2016 Pavol Rusnak
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/frozen_deps/mnemonic-0.19.dist-info/METADATA b/frozen_deps/mnemonic-0.19.dist-info/METADATA
new file mode 100644
index 0000000..ccd2d7e
--- /dev/null
+++ b/frozen_deps/mnemonic-0.19.dist-info/METADATA
@@ -0,0 +1,42 @@
+Metadata-Version: 2.1
+Name: mnemonic
+Version: 0.19
+Summary: Implementation of Bitcoin BIP-0039
+Home-page: https://github.com/trezor/python-mnemonic
+Author: Trezor
+Author-email: [email protected]
+License: UNKNOWN
+Platform: UNKNOWN
+Classifier: License :: OSI Approved :: MIT License
+Classifier: Operating System :: POSIX :: Linux
+Classifier: Operating System :: Microsoft :: Windows
+Classifier: Operating System :: MacOS :: MacOS X
+Classifier: Programming Language :: Python :: 2
+Classifier: Programming Language :: Python :: 3
+
+python-mnemonic
+===============
+
+.. image:: https://travis-ci.org/trezor/python-mnemonic.svg?branch=master
+ :target: https://travis-ci.org/trezor/python-mnemonic
+
+Reference implementation of BIP-0039: Mnemonic code for generating
+deterministic keys
+
+Abstract
+--------
+
+This BIP describes the implementation of a mnemonic code or mnemonic sentence --
+a group of easy to remember words -- for the generation of deterministic wallets.
+
+It consists of two parts: generating the mnenomic, and converting it into a
+binary seed. This seed can be later used to generate deterministic wallets using
+BIP-0032 or similar methods.
+
+BIP Paper
+---------
+
+See https://github.com/bitcoin/bips/blob/master/bip-0039.mediawiki
+for full specification
+
+
diff --git a/frozen_deps/mnemonic-0.19.dist-info/RECORD b/frozen_deps/mnemonic-0.19.dist-info/RECORD
new file mode 100644
index 0000000..dea0329
--- /dev/null
+++ b/frozen_deps/mnemonic-0.19.dist-info/RECORD
@@ -0,0 +1,19 @@
+mnemonic-0.19.dist-info/AUTHORS,sha256=5ugihxzh5OoFf-6gBQOnJfgaznUQHX5Vv4L9Th9iGFo,77
+mnemonic-0.19.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4
+mnemonic-0.19.dist-info/LICENSE,sha256=1ePHxiqE6ABzIB4vblEw6eaAT6BfisT4smoTx9OWlpc,1084
+mnemonic-0.19.dist-info/METADATA,sha256=qwLACoQeTvWdaoDuBFWJUNBq0YxKAZ0l1fm06N0OY_w,1260
+mnemonic-0.19.dist-info/RECORD,,
+mnemonic-0.19.dist-info/WHEEL,sha256=HX-v9-noUkyUoxyZ1PMSuS7auUxDAR4VBdoYLqD0xws,110
+mnemonic-0.19.dist-info/top_level.txt,sha256=XlFgB9xaifTc2HXO7w9EXCvIUHFN_x51trUyPQKBSHI,9
+mnemonic/__init__.py,sha256=oASNYH5yS0zFSw4wYRvtw_O42j5Xojt7gZ2ur519DWc,45
+mnemonic/__pycache__/__init__.cpython-38.pyc,,
+mnemonic/__pycache__/mnemonic.cpython-38.pyc,,
+mnemonic/mnemonic.py,sha256=WjWwsSKvpv6cP44mXJXrsWqpJuSR-EN8dSb9GFnPfqs,10532
+mnemonic/wordlist/chinese_simplified.txt,sha256=XFlCeSvYNAy4snzVkvEBXt9WqMWyYnbuGKSCQo58VyY,8192
+mnemonic/wordlist/chinese_traditional.txt,sha256=QXsms9hQCkrj1ZcX1wEZUttvwvuEuAfz-UrHNOicG18,8192
+mnemonic/wordlist/english.txt,sha256=L17tU6Rye0v4iA2PPxme_JDlhQNkbZ_47_Oi7Tsk29o,13116
+mnemonic/wordlist/french.txt,sha256=AQHYifYipgZMqXzbc2iDjdWhPxO7sLOt-nRRFAN1WJg,16779
+mnemonic/wordlist/italian.txt,sha256=05LEn9twCiTNH86yN8H2XcwSj2s0qKrLWLWThLXGSMI,16033
+mnemonic/wordlist/japanese.txt,sha256=Lu0K70kikeBhYz162BF_GisD64CinQ5OMResJSjQX_0,26423
+mnemonic/wordlist/korean.txt,sha256=npX4bBZ96I9FDwqvieh_ZiSlf5c8Z7UW4zjo6LiJf2A,37832
+mnemonic/wordlist/spanish.txt,sha256=RoRqWgE50ePLdyk-UhwoZfe824LETo0KBqLNDsukjAs,13996
diff --git a/frozen_deps/mnemonic-0.19.dist-info/WHEEL b/frozen_deps/mnemonic-0.19.dist-info/WHEEL
new file mode 100644
index 0000000..c8240f0
--- /dev/null
+++ b/frozen_deps/mnemonic-0.19.dist-info/WHEEL
@@ -0,0 +1,6 @@
+Wheel-Version: 1.0
+Generator: bdist_wheel (0.33.1)
+Root-Is-Purelib: true
+Tag: py2-none-any
+Tag: py3-none-any
+
diff --git a/frozen_deps/mnemonic-0.19.dist-info/top_level.txt b/frozen_deps/mnemonic-0.19.dist-info/top_level.txt
new file mode 100644
index 0000000..9015942
--- /dev/null
+++ b/frozen_deps/mnemonic-0.19.dist-info/top_level.txt
@@ -0,0 +1 @@
+mnemonic
diff --git a/frozen_deps/mnemonic/__init__.py b/frozen_deps/mnemonic/__init__.py
new file mode 100644
index 0000000..47e293d
--- /dev/null
+++ b/frozen_deps/mnemonic/__init__.py
@@ -0,0 +1 @@
+from .mnemonic import Mnemonic # noqa: F401
diff --git a/frozen_deps/mnemonic/mnemonic.py b/frozen_deps/mnemonic/mnemonic.py
new file mode 100644
index 0000000..935620a
--- /dev/null
+++ b/frozen_deps/mnemonic/mnemonic.py
@@ -0,0 +1,291 @@
+#
+# Copyright (c) 2013 Pavol Rusnak
+# Copyright (c) 2017 mruddy
+#
+# Permission is hereby granted, free of charge, to any person obtaining a copy of
+# this software and associated documentation files (the "Software"), to deal in
+# the Software without restriction, including without limitation the rights to
+# use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
+# of the Software, and to permit persons to whom the Software is furnished to do
+# so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be included in all
+# copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+
+import binascii
+import bisect
+import hashlib
+import hmac
+import itertools
+import os
+import sys
+import unicodedata
+
+PBKDF2_ROUNDS = 2048
+
+
+class ConfigurationError(Exception):
+ pass
+
+
+# From <https://stackoverflow.com/questions/212358/binary-search-bisection-in-python/2233940#2233940>
+def binary_search(a, x, lo=0, hi=None): # can't use a to specify default for hi
+ hi = hi if hi is not None else len(a) # hi defaults to len(a)
+ pos = bisect.bisect_left(a, x, lo, hi) # find insertion position
+ return pos if pos != hi and a[pos] == x else -1 # don't walk off the end
+
+
+# Refactored code segments from <https://github.com/keis/base58>
+def b58encode(v):
+ alphabet = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz"
+
+ p, acc = 1, 0
+ for c in reversed(v):
+ if sys.version < "3":
+ c = ord(c)
+ acc += p * c
+ p = p << 8
+
+ string = ""
+ while acc:
+ acc, idx = divmod(acc, 58)
+ string = alphabet[idx : idx + 1] + string
+ return string
+
+
+class Mnemonic(object):
+ def __init__(self, language):
+ self.radix = 2048
+ if sys.version < "3":
+ with open("%s/%s.txt" % (self._get_directory(), language), "r") as f:
+ self.wordlist = [w.strip().decode("utf8") for w in f.readlines()]
+ else:
+ with open(
+ "%s/%s.txt" % (self._get_directory(), language), "r", encoding="utf-8"
+ ) as f:
+ self.wordlist = [w.strip() for w in f.readlines()]
+ if len(self.wordlist) != self.radix:
+ raise ConfigurationError(
+ "Wordlist should contain %d words, but it contains %d words."
+ % (self.radix, len(self.wordlist))
+ )
+
+ @classmethod
+ def _get_directory(cls):
+ return os.path.join(os.path.dirname(__file__), "wordlist")
+
+ @classmethod
+ def list_languages(cls):
+ return [
+ f.split(".")[0]
+ for f in os.listdir(cls._get_directory())
+ if f.endswith(".txt")
+ ]
+
+ @classmethod
+ def normalize_string(cls, txt):
+ if isinstance(txt, str if sys.version < "3" else bytes):
+ utxt = txt.decode("utf8")
+ elif isinstance(txt, unicode if sys.version < "3" else str): # noqa: F821
+ utxt = txt
+ else:
+ raise TypeError("String value expected")
+
+ return unicodedata.normalize("NFKD", utxt)
+
+ @classmethod
+ def detect_language(cls, code):
+ code = cls.normalize_string(code)
+ first = code.split(" ")[0]
+ languages = cls.list_languages()
+
+ for lang in languages:
+ mnemo = cls(lang)
+ if first in mnemo.wordlist:
+ return lang
+
+ raise ConfigurationError("Language not detected")
+
+ def generate(self, strength=128):
+ if strength not in [128, 160, 192, 224, 256]:
+ raise ValueError(
+ "Strength should be one of the following [128, 160, 192, 224, 256], but it is not (%d)."
+ % strength
+ )
+ return self.to_mnemonic(os.urandom(strength // 8))
+
+ # Adapted from <http://tinyurl.com/oxmn476>
+ def to_entropy(self, words):
+ if not isinstance(words, list):
+ words = words.split(" ")
+ if len(words) not in [12, 15, 18, 21, 24]:
+ raise ValueError(
+ "Number of words must be one of the following: [12, 15, 18, 21, 24], but it is not (%d)."
+ % len(words)
+ )
+ # Look up all the words in the list and construct the
+ # concatenation of the original entropy and the checksum.
+ concatLenBits = len(words) * 11
+ concatBits = [False] * concatLenBits
+ wordindex = 0
+ if self.detect_language(" ".join(words)) == "english":
+ use_binary_search = True
+ else:
+ use_binary_search = False
+ for word in words:
+ # Find the words index in the wordlist
+ ndx = (
+ binary_search(self.wordlist, word)
+ if use_binary_search
+ else self.wordlist.index(word)
+ )
+ if ndx < 0:
+ raise LookupError('Unable to find "%s" in word list.' % word)
+ # Set the next 11 bits to the value of the index.
+ for ii in range(11):
+ concatBits[(wordindex * 11) + ii] = (ndx & (1 << (10 - ii))) != 0
+ wordindex += 1
+ checksumLengthBits = concatLenBits // 33
+ entropyLengthBits = concatLenBits - checksumLengthBits
+ # Extract original entropy as bytes.
+ entropy = bytearray(entropyLengthBits // 8)
+ for ii in range(len(entropy)):
+ for jj in range(8):
+ if concatBits[(ii * 8) + jj]:
+ entropy[ii] |= 1 << (7 - jj)
+ # Take the digest of the entropy.
+ hashBytes = hashlib.sha256(entropy).digest()
+ if sys.version < "3":
+ hashBits = list(
+ itertools.chain.from_iterable(
+ (
+ [ord(c) & (1 << (7 - i)) != 0 for i in range(8)]
+ for c in hashBytes
+ )
+ )
+ )
+ else:
+ hashBits = list(
+ itertools.chain.from_iterable(
+ ([c & (1 << (7 - i)) != 0 for i in range(8)] for c in hashBytes)
+ )
+ )
+ # Check all the checksum bits.
+ for i in range(checksumLengthBits):
+ if concatBits[entropyLengthBits + i] != hashBits[i]:
+ raise ValueError("Failed checksum.")
+ return entropy
+
+ def to_mnemonic(self, data):
+ if len(data) not in [16, 20, 24, 28, 32]:
+ raise ValueError(
+ "Data length should be one of the following: [16, 20, 24, 28, 32], but it is not (%d)."
+ % len(data)
+ )
+ h = hashlib.sha256(data).hexdigest()
+ b = (
+ bin(int(binascii.hexlify(data), 16))[2:].zfill(len(data) * 8)
+ + bin(int(h, 16))[2:].zfill(256)[: len(data) * 8 // 32]
+ )
+ result = []
+ for i in range(len(b) // 11):
+ idx = int(b[i * 11 : (i + 1) * 11], 2)
+ result.append(self.wordlist[idx])
+ if (
+ self.detect_language(" ".join(result)) == "japanese"
+ ): # Japanese must be joined by ideographic space.
+ result_phrase = u"\u3000".join(result)
+ else:
+ result_phrase = " ".join(result)
+ return result_phrase
+
+ def check(self, mnemonic):
+ mnemonic = self.normalize_string(mnemonic).split(" ")
+ # list of valid mnemonic lengths
+ if len(mnemonic) not in [12, 15, 18, 21, 24]:
+ return False
+ try:
+ idx = map(lambda x: bin(self.wordlist.index(x))[2:].zfill(11), mnemonic)
+ b = "".join(idx)
+ except ValueError:
+ return False
+ l = len(b) # noqa: E741
+ d = b[: l // 33 * 32]
+ h = b[-l // 33 :]
+ nd = binascii.unhexlify(hex(int(d, 2))[2:].rstrip("L").zfill(l // 33 * 8))
+ nh = bin(int(hashlib.sha256(nd).hexdigest(), 16))[2:].zfill(256)[: l // 33]
+ return h == nh
+
+ def expand_word(self, prefix):
+ if prefix in self.wordlist:
+ return prefix
+ else:
+ matches = [word for word in self.wordlist if word.startswith(prefix)]
+ if len(matches) == 1: # matched exactly one word in the wordlist
+ return matches[0]
+ else:
+ # exact match not found.
+ # this is not a validation routine, just return the input
+ return prefix
+
+ def expand(self, mnemonic):
+ return " ".join(map(self.expand_word, mnemonic.split(" ")))
+
+ @classmethod
+ def to_seed(cls, mnemonic, passphrase=""):
+ mnemonic = cls.normalize_string(mnemonic)
+ passphrase = cls.normalize_string(passphrase)
+ passphrase = "mnemonic" + passphrase
+ mnemonic = mnemonic.encode("utf-8")
+ passphrase = passphrase.encode("utf-8")
+ stretched = hashlib.pbkdf2_hmac("sha512", mnemonic, passphrase, PBKDF2_ROUNDS)
+ return stretched[:64]
+
+ @classmethod
+ def to_hd_master_key(cls, seed):
+ if len(seed) != 64:
+ raise ValueError("Provided seed should have length of 64")
+
+ # Compute HMAC-SHA512 of seed
+ seed = hmac.new(b"Bitcoin seed", seed, digestmod=hashlib.sha512).digest()
+
+ # Serialization format can be found at: https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki#Serialization_format
+ xprv = b"\x04\x88\xad\xe4" # Version for private mainnet
+ xprv += b"\x00" * 9 # Depth, parent fingerprint, and child number
+ xprv += seed[32:] # Chain code
+ xprv += b"\x00" + seed[:32] # Master key
+
+ # Double hash using SHA256
+ hashed_xprv = hashlib.sha256(xprv).digest()
+ hashed_xprv = hashlib.sha256(hashed_xprv).digest()
+
+ # Append 4 bytes of checksum
+ xprv += hashed_xprv[:4]
+
+ # Return base58
+ return b58encode(xprv)
+
+
+def main():
+ import binascii
+ import sys
+
+ if len(sys.argv) > 1:
+ data = sys.argv[1]
+ else:
+ data = sys.stdin.readline().strip()
+ data = binascii.unhexlify(data)
+ m = Mnemonic("english")
+ print(m.to_mnemonic(data))
+
+
+if __name__ == "__main__":
+ main()
diff --git a/frozen_deps/mnemonic/wordlist/chinese_simplified.txt b/frozen_deps/mnemonic/wordlist/chinese_simplified.txt
new file mode 100644
index 0000000..b90f1ed
--- /dev/null
+++ b/frozen_deps/mnemonic/wordlist/chinese_simplified.txt
@@ -0,0 +1,2048 @@
+的
+一
+是
+在
+不
+了
+有
+和
+人
+这
+中
+大
+为
+上
+个
+国
+我
+以
+要
+他
+时
+来
+用
+们
+生
+到
+作
+地
+于
+出
+就
+分
+对
+成
+会
+可
+主
+发
+年
+动
+同
+工
+也
+能
+下
+过
+子
+说
+产
+种
+面
+而
+方
+后
+多
+定
+行
+学
+法
+所
+民
+得
+经
+十
+三
+之
+进
+着
+等
+部
+度
+家
+电
+力
+里
+如
+水
+化
+高
+自
+二
+理
+起
+小
+物
+现
+实
+加
+量
+都
+两
+体
+制
+机
+当
+使
+点
+从
+业
+本
+去
+把
+性
+好
+应
+开
+它
+合
+还
+因
+由
+其
+些
+然
+前
+外
+天
+政
+四
+日
+那
+社
+义
+事
+平
+形
+相
+全
+表
+间
+样
+与
+关
+各
+重
+新
+线
+内
+数
+正
+心
+反
+你
+明
+看
+原
+又
+么
+利
+比
+或
+但
+质
+气
+第
+向
+道
+命
+此
+变
+条
+只
+没
+结
+解
+问
+意
+建
+月
+公
+无
+系
+军
+很
+情
+者
+最
+立
+代
+想
+已
+通
+并
+提
+直
+题
+党
+程
+展
+五
+果
+料
+象
+员
+革
+位
+入
+常
+文
+总
+次
+品
+式
+活
+设
+及
+管
+特
+件
+长
+求
+老
+头
+基
+资
+边
+流
+路
+级
+少
+图
+山
+统
+接
+知
+较
+将
+组
+见
+计
+别
+她
+手
+角
+期
+根
+论
+运
+农
+指
+几
+九
+区
+强
+放
+决
+西
+被
+干
+做
+必
+战
+先
+回
+则
+任
+取
+据
+处
+队
+南
+给
+色
+光
+门
+即
+保
+治
+北
+造
+百
+规
+热
+领
+七
+海
+口
+东
+导
+器
+压
+志
+世
+金
+增
+争
+济
+阶
+油
+思
+术
+极
+交
+受
+联
+什
+认
+六
+共
+权
+收
+证
+改
+清
+美
+再
+采
+转
+更
+单
+风
+切
+打
+白
+教
+速
+花
+带
+安
+场
+身
+车
+例
+真
+务
+具
+万
+每
+目
+至
+达
+走
+积
+示
+议
+声
+报
+斗
+完
+类
+八
+离
+华
+名
+确
+才
+科
+张
+信
+马
+节
+话
+米
+整
+空
+元
+况
+今
+集
+温
+传
+土
+许
+步
+群
+广
+石
+记
+需
+段
+研
+界
+拉
+林
+律
+叫
+且
+究
+观
+越
+织
+装
+影
+算
+低
+持
+音
+众
+书
+布
+复
+容
+儿
+须
+际
+商
+非
+验
+连
+断
+深
+难
+近
+矿
+千
+周
+委
+素
+技
+备
+半
+办
+青
+省
+列
+习
+响
+约
+支
+般
+史
+感
+劳
+便
+团
+往
+酸
+历
+市
+克
+何
+除
+消
+构
+府
+称
+太
+准
+精
+值
+号
+率
+族
+维
+划
+选
+标
+写
+存
+候
+毛
+亲
+快
+效
+斯
+院
+查
+江
+型
+眼
+王
+按
+格
+养
+易
+置
+派
+层
+片
+始
+却
+专
+状
+育
+厂
+京
+识
+适
+属
+圆
+包
+火
+住
+调
+满
+县
+局
+照
+参
+红
+细
+引
+听
+该
+铁
+价
+严
+首
+底
+液
+官
+德
+随
+病
+苏
+失
+尔
+死
+讲
+配
+女
+黄
+推
+显
+谈
+罪
+神
+艺
+呢
+席
+含
+企
+望
+密
+批
+营
+项
+防
+举
+球
+英
+氧
+势
+告
+李
+台
+落
+木
+帮
+轮
+破
+亚
+师
+围
+注
+远
+字
+材
+排
+供
+河
+态
+封
+另
+施
+减
+树
+溶
+怎
+止
+案
+言
+士
+均
+武
+固
+叶
+鱼
+波
+视
+仅
+费
+紧
+爱
+左
+章
+早
+朝
+害
+续
+轻
+服
+试
+食
+充
+兵
+源
+判
+护
+司
+足
+某
+练
+差
+致
+板
+田
+降
+黑
+犯
+负
+击
+范
+继
+兴
+似
+余
+坚
+曲
+输
+修
+故
+城
+夫
+够
+送
+笔
+船
+占
+右
+财
+吃
+富
+春
+职
+觉
+汉
+画
+功
+巴
+跟
+虽
+杂
+飞
+检
+吸
+助
+升
+阳
+互
+初
+创
+抗
+考
+投
+坏
+策
+古
+径
+换
+未
+跑
+留
+钢
+曾
+端
+责
+站
+简
+述
+钱
+副
+尽
+帝
+射
+草
+冲
+承
+独
+令
+限
+阿
+宣
+环
+双
+请
+超
+微
+让
+控
+州
+良
+轴
+找
+否
+纪
+益
+依
+优
+顶
+础
+载
+倒
+房
+突
+坐
+粉
+敌
+略
+客
+袁
+冷
+胜
+绝
+析
+块
+剂
+测
+丝
+协
+诉
+念
+陈
+仍
+罗
+盐
+友
+洋
+错
+苦
+夜
+刑
+移
+频
+逐
+靠
+混
+母
+短
+皮
+终
+聚
+汽
+村
+云
+哪
+既
+距
+卫
+停
+烈
+央
+察
+烧
+迅
+境
+若
+印
+洲
+刻
+括
+激
+孔
+搞
+甚
+室
+待
+核
+校
+散
+侵
+吧
+甲
+游
+久
+菜
+味
+旧
+模
+湖
+货
+损
+预
+阻
+毫
+普
+稳
+乙
+妈
+植
+息
+扩
+银
+语
+挥
+酒
+守
+拿
+序
+纸
+医
+缺
+雨
+吗
+针
+刘
+啊
+急
+唱
+误
+训
+愿
+审
+附
+获
+茶
+鲜
+粮
+斤
+孩
+脱
+硫
+肥
+善
+龙
+演
+父
+渐
+血
+欢
+械
+掌
+歌
+沙
+刚
+攻
+谓
+盾
+讨
+晚
+粒
+乱
+燃
+矛
+乎
+杀
+药
+宁
+鲁
+贵
+钟
+煤
+读
+班
+伯
+香
+介
+迫
+句
+丰
+培
+握
+兰
+担
+弦
+蛋
+沉
+假
+穿
+执
+答
+乐
+谁
+顺
+烟
+缩
+征
+脸
+喜
+松
+脚
+困
+异
+免
+背
+星
+福
+买
+染
+井
+概
+慢
+怕
+磁
+倍
+祖
+皇
+促
+静
+补
+评
+翻
+肉
+践
+尼
+衣
+宽
+扬
+棉
+希
+伤
+操
+垂
+秋
+宜
+氢
+套
+督
+振
+架
+亮
+末
+宪
+庆
+编
+牛
+触
+映
+雷
+销
+诗
+座
+居
+抓
+裂
+胞
+呼
+娘
+景
+威
+绿
+晶
+厚
+盟
+衡
+鸡
+孙
+延
+危
+胶
+屋
+乡
+临
+陆
+顾
+掉
+呀
+灯
+岁
+措
+束
+耐
+剧
+玉
+赵
+跳
+哥
+季
+课
+凯
+胡
+额
+款
+绍
+卷
+齐
+伟
+蒸
+殖
+永
+宗
+苗
+川
+炉
+岩
+弱
+零
+杨
+奏
+沿
+露
+杆
+探
+滑
+镇
+饭
+浓
+航
+怀
+赶
+库
+夺
+伊
+灵
+税
+途
+灭
+赛
+归
+召
+鼓
+播
+盘
+裁
+险
+康
+唯
+录
+菌
+纯
+借
+糖
+盖
+横
+符
+私
+努
+堂
+域
+枪
+润
+幅
+哈
+竟
+熟
+虫
+泽
+脑
+壤
+碳
+欧
+遍
+侧
+寨
+敢
+彻
+虑
+斜
+薄
+庭
+纳
+弹
+饲
+伸
+折
+麦
+湿
+暗
+荷
+瓦
+塞
+床
+筑
+恶
+户
+访
+塔
+奇
+透
+梁
+刀
+旋
+迹
+卡
+氯
+遇
+份
+毒
+泥
+退
+洗
+摆
+灰
+彩
+卖
+耗
+夏
+择
+忙
+铜
+献
+硬
+予
+繁
+圈
+雪
+函
+亦
+抽
+篇
+阵
+阴
+丁
+尺
+追
+堆
+雄
+迎
+泛
+爸
+楼
+避
+谋
+吨
+野
+猪
+旗
+累
+偏
+典
+馆
+索
+秦
+脂
+潮
+爷
+豆
+忽
+托
+惊
+塑
+遗
+愈
+朱
+替
+纤
+粗
+倾
+尚
+痛
+楚
+谢
+奋
+购
+磨
+君
+池
+旁
+碎
+骨
+监
+捕
+弟
+暴
+割
+贯
+殊
+释
+词
+亡
+壁
+顿
+宝
+午
+尘
+闻
+揭
+炮
+残
+冬
+桥
+妇
+警
+综
+招
+吴
+付
+浮
+遭
+徐
+您
+摇
+谷
+赞
+箱
+隔
+订
+男
+吹
+园
+纷
+唐
+败
+宋
+玻
+巨
+耕
+坦
+荣
+闭
+湾
+键
+凡
+驻
+锅
+救
+恩
+剥
+凝
+碱
+齿
+截
+炼
+麻
+纺
+禁
+废
+盛
+版
+缓
+净
+睛
+昌
+婚
+涉
+筒
+嘴
+插
+岸
+朗
+庄
+街
+藏
+姑
+贸
+腐
+奴
+啦
+惯
+乘
+伙
+恢
+匀
+纱
+扎
+辩
+耳
+彪
+臣
+亿
+璃
+抵
+脉
+秀
+萨
+俄
+网
+舞
+店
+喷
+纵
+寸
+汗
+挂
+洪
+贺
+闪
+柬
+爆
+烯
+津
+稻
+墙
+软
+勇
+像
+滚
+厘
+蒙
+芳
+肯
+坡
+柱
+荡
+腿
+仪
+旅
+尾
+轧
+冰
+贡
+登
+黎
+削
+钻
+勒
+逃
+障
+氨
+郭
+峰
+币
+港
+伏
+轨
+亩
+毕
+擦
+莫
+刺
+浪
+秘
+援
+株
+健
+售
+股
+岛
+甘
+泡
+睡
+童
+铸
+汤
+阀
+休
+汇
+舍
+牧
+绕
+炸
+哲
+磷
+绩
+朋
+淡
+尖
+启
+陷
+柴
+呈
+徒
+颜
+泪
+稍
+忘
+泵
+蓝
+拖
+洞
+授
+镜
+辛
+壮
+锋
+贫
+虚
+弯
+摩
+泰
+幼
+廷
+尊
+窗
+纲
+弄
+隶
+疑
+氏
+宫
+姐
+震
+瑞
+怪
+尤
+琴
+循
+描
+膜
+违
+夹
+腰
+缘
+珠
+穷
+森
+枝
+竹
+沟
+催
+绳
+忆
+邦
+剩
+幸
+浆
+栏
+拥
+牙
+贮
+礼
+滤
+钠
+纹
+罢
+拍
+咱
+喊
+袖
+埃
+勤
+罚
+焦
+潜
+伍
+墨
+欲
+缝
+姓
+刊
+饱
+仿
+奖
+铝
+鬼
+丽
+跨
+默
+挖
+链
+扫
+喝
+袋
+炭
+污
+幕
+诸
+弧
+励
+梅
+奶
+洁
+灾
+舟
+鉴
+苯
+讼
+抱
+毁
+懂
+寒
+智
+埔
+寄
+届
+跃
+渡
+挑
+丹
+艰
+贝
+碰
+拔
+爹
+戴
+码
+梦
+芽
+熔
+赤
+渔
+哭
+敬
+颗
+奔
+铅
+仲
+虎
+稀
+妹
+乏
+珍
+申
+桌
+遵
+允
+隆
+螺
+仓
+魏
+锐
+晓
+氮
+兼
+隐
+碍
+赫
+拨
+忠
+肃
+缸
+牵
+抢
+博
+巧
+壳
+兄
+杜
+讯
+诚
+碧
+祥
+柯
+页
+巡
+矩
+悲
+灌
+龄
+伦
+票
+寻
+桂
+铺
+圣
+恐
+恰
+郑
+趣
+抬
+荒
+腾
+贴
+柔
+滴
+猛
+阔
+辆
+妻
+填
+撤
+储
+签
+闹
+扰
+紫
+砂
+递
+戏
+吊
+陶
+伐
+喂
+疗
+瓶
+婆
+抚
+臂
+摸
+忍
+虾
+蜡
+邻
+胸
+巩
+挤
+偶
+弃
+槽
+劲
+乳
+邓
+吉
+仁
+烂
+砖
+租
+乌
+舰
+伴
+瓜
+浅
+丙
+暂
+燥
+橡
+柳
+迷
+暖
+牌
+秧
+胆
+详
+簧
+踏
+瓷
+谱
+呆
+宾
+糊
+洛
+辉
+愤
+竞
+隙
+怒
+粘
+乃
+绪
+肩
+籍
+敏
+涂
+熙
+皆
+侦
+悬
+掘
+享
+纠
+醒
+狂
+锁
+淀
+恨
+牲
+霸
+爬
+赏
+逆
+玩
+陵
+祝
+秒
+浙
+貌
+役
+彼
+悉
+鸭
+趋
+凤
+晨
+畜
+辈
+秩
+卵
+署
+梯
+炎
+滩
+棋
+驱
+筛
+峡
+冒
+啥
+寿
+译
+浸
+泉
+帽
+迟
+硅
+疆
+贷
+漏
+稿
+冠
+嫩
+胁
+芯
+牢
+叛
+蚀
+奥
+鸣
+岭
+羊
+凭
+串
+塘
+绘
+酵
+融
+盆
+锡
+庙
+筹
+冻
+辅
+摄
+袭
+筋
+拒
+僚
+旱
+钾
+鸟
+漆
+沈
+眉
+疏
+添
+棒
+穗
+硝
+韩
+逼
+扭
+侨
+凉
+挺
+碗
+栽
+炒
+杯
+患
+馏
+劝
+豪
+辽
+勃
+鸿
+旦
+吏
+拜
+狗
+埋
+辊
+掩
+饮
+搬
+骂
+辞
+勾
+扣
+估
+蒋
+绒
+雾
+丈
+朵
+姆
+拟
+宇
+辑
+陕
+雕
+偿
+蓄
+崇
+剪
+倡
+厅
+咬
+驶
+薯
+刷
+斥
+番
+赋
+奉
+佛
+浇
+漫
+曼
+扇
+钙
+桃
+扶
+仔
+返
+俗
+亏
+腔
+鞋
+棱
+覆
+框
+悄
+叔
+撞
+骗
+勘
+旺
+沸
+孤
+吐
+孟
+渠
+屈
+疾
+妙
+惜
+仰
+狠
+胀
+谐
+抛
+霉
+桑
+岗
+嘛
+衰
+盗
+渗
+脏
+赖
+涌
+甜
+曹
+阅
+肌
+哩
+厉
+烃
+纬
+毅
+昨
+伪
+症
+煮
+叹
+钉
+搭
+茎
+笼
+酷
+偷
+弓
+锥
+恒
+杰
+坑
+鼻
+翼
+纶
+叙
+狱
+逮
+罐
+络
+棚
+抑
+膨
+蔬
+寺
+骤
+穆
+冶
+枯
+册
+尸
+凸
+绅
+坯
+牺
+焰
+轰
+欣
+晋
+瘦
+御
+锭
+锦
+丧
+旬
+锻
+垄
+搜
+扑
+邀
+亭
+酯
+迈
+舒
+脆
+酶
+闲
+忧
+酚
+顽
+羽
+涨
+卸
+仗
+陪
+辟
+惩
+杭
+姚
+肚
+捉
+飘
+漂
+昆
+欺
+吾
+郎
+烷
+汁
+呵
+饰
+萧
+雅
+邮
+迁
+燕
+撒
+姻
+赴
+宴
+烦
+债
+帐
+斑
+铃
+旨
+醇
+董
+饼
+雏
+姿
+拌
+傅
+腹
+妥
+揉
+贤
+拆
+歪
+葡
+胺
+丢
+浩
+徽
+昂
+垫
+挡
+览
+贪
+慰
+缴
+汪
+慌
+冯
+诺
+姜
+谊
+凶
+劣
+诬
+耀
+昏
+躺
+盈
+骑
+乔
+溪
+丛
+卢
+抹
+闷
+咨
+刮
+驾
+缆
+悟
+摘
+铒
+掷
+颇
+幻
+柄
+惠
+惨
+佳
+仇
+腊
+窝
+涤
+剑
+瞧
+堡
+泼
+葱
+罩
+霍
+捞
+胎
+苍
+滨
+俩
+捅
+湘
+砍
+霞
+邵
+萄
+疯
+淮
+遂
+熊
+粪
+烘
+宿
+档
+戈
+驳
+嫂
+裕
+徙
+箭
+捐
+肠
+撑
+晒
+辨
+殿
+莲
+摊
+搅
+酱
+屏
+疫
+哀
+蔡
+堵
+沫
+皱
+畅
+叠
+阁
+莱
+敲
+辖
+钩
+痕
+坝
+巷
+饿
+祸
+丘
+玄
+溜
+曰
+逻
+彭
+尝
+卿
+妨
+艇
+吞
+韦
+怨
+矮
+歇
diff --git a/frozen_deps/mnemonic/wordlist/chinese_traditional.txt b/frozen_deps/mnemonic/wordlist/chinese_traditional.txt
new file mode 100644
index 0000000..9b02047
--- /dev/null
+++ b/frozen_deps/mnemonic/wordlist/chinese_traditional.txt
@@ -0,0 +1,2048 @@
+的
+一
+是
+在
+不
+了
+有
+和
+人
+這
+中
+大
+為
+上
+個
+國
+我
+以
+要
+他
+時
+來
+用
+們
+生
+到
+作
+地
+於
+出
+就
+分
+對
+成
+會
+可
+主
+發
+年
+動
+同
+工
+也
+能
+下
+過
+子
+說
+產
+種
+面
+而
+方
+後
+多
+定
+行
+學
+法
+所
+民
+得
+經
+十
+三
+之
+進
+著
+等
+部
+度
+家
+電
+力
+裡
+如
+水
+化
+高
+自
+二
+理
+起
+小
+物
+現
+實
+加
+量
+都
+兩
+體
+制
+機
+當
+使
+點
+從
+業
+本
+去
+把
+性
+好
+應
+開
+它
+合
+還
+因
+由
+其
+些
+然
+前
+外
+天
+政
+四
+日
+那
+社
+義
+事
+平
+形
+相
+全
+表
+間
+樣
+與
+關
+各
+重
+新
+線
+內
+數
+正
+心
+反
+你
+明
+看
+原
+又
+麼
+利
+比
+或
+但
+質
+氣
+第
+向
+道
+命
+此
+變
+條
+只
+沒
+結
+解
+問
+意
+建
+月
+公
+無
+系
+軍
+很
+情
+者
+最
+立
+代
+想
+已
+通
+並
+提
+直
+題
+黨
+程
+展
+五
+果
+料
+象
+員
+革
+位
+入
+常
+文
+總
+次
+品
+式
+活
+設
+及
+管
+特
+件
+長
+求
+老
+頭
+基
+資
+邊
+流
+路
+級
+少
+圖
+山
+統
+接
+知
+較
+將
+組
+見
+計
+別
+她
+手
+角
+期
+根
+論
+運
+農
+指
+幾
+九
+區
+強
+放
+決
+西
+被
+幹
+做
+必
+戰
+先
+回
+則
+任
+取
+據
+處
+隊
+南
+給
+色
+光
+門
+即
+保
+治
+北
+造
+百
+規
+熱
+領
+七
+海
+口
+東
+導
+器
+壓
+志
+世
+金
+增
+爭
+濟
+階
+油
+思
+術
+極
+交
+受
+聯
+什
+認
+六
+共
+權
+收
+證
+改
+清
+美
+再
+採
+轉
+更
+單
+風
+切
+打
+白
+教
+速
+花
+帶
+安
+場
+身
+車
+例
+真
+務
+具
+萬
+每
+目
+至
+達
+走
+積
+示
+議
+聲
+報
+鬥
+完
+類
+八
+離
+華
+名
+確
+才
+科
+張
+信
+馬
+節
+話
+米
+整
+空
+元
+況
+今
+集
+溫
+傳
+土
+許
+步
+群
+廣
+石
+記
+需
+段
+研
+界
+拉
+林
+律
+叫
+且
+究
+觀
+越
+織
+裝
+影
+算
+低
+持
+音
+眾
+書
+布
+复
+容
+兒
+須
+際
+商
+非
+驗
+連
+斷
+深
+難
+近
+礦
+千
+週
+委
+素
+技
+備
+半
+辦
+青
+省
+列
+習
+響
+約
+支
+般
+史
+感
+勞
+便
+團
+往
+酸
+歷
+市
+克
+何
+除
+消
+構
+府
+稱
+太
+準
+精
+值
+號
+率
+族
+維
+劃
+選
+標
+寫
+存
+候
+毛
+親
+快
+效
+斯
+院
+查
+江
+型
+眼
+王
+按
+格
+養
+易
+置
+派
+層
+片
+始
+卻
+專
+狀
+育
+廠
+京
+識
+適
+屬
+圓
+包
+火
+住
+調
+滿
+縣
+局
+照
+參
+紅
+細
+引
+聽
+該
+鐵
+價
+嚴
+首
+底
+液
+官
+德
+隨
+病
+蘇
+失
+爾
+死
+講
+配
+女
+黃
+推
+顯
+談
+罪
+神
+藝
+呢
+席
+含
+企
+望
+密
+批
+營
+項
+防
+舉
+球
+英
+氧
+勢
+告
+李
+台
+落
+木
+幫
+輪
+破
+亞
+師
+圍
+注
+遠
+字
+材
+排
+供
+河
+態
+封
+另
+施
+減
+樹
+溶
+怎
+止
+案
+言
+士
+均
+武
+固
+葉
+魚
+波
+視
+僅
+費
+緊
+愛
+左
+章
+早
+朝
+害
+續
+輕
+服
+試
+食
+充
+兵
+源
+判
+護
+司
+足
+某
+練
+差
+致
+板
+田
+降
+黑
+犯
+負
+擊
+范
+繼
+興
+似
+餘
+堅
+曲
+輸
+修
+故
+城
+夫
+夠
+送
+筆
+船
+佔
+右
+財
+吃
+富
+春
+職
+覺
+漢
+畫
+功
+巴
+跟
+雖
+雜
+飛
+檢
+吸
+助
+昇
+陽
+互
+初
+創
+抗
+考
+投
+壞
+策
+古
+徑
+換
+未
+跑
+留
+鋼
+曾
+端
+責
+站
+簡
+述
+錢
+副
+盡
+帝
+射
+草
+衝
+承
+獨
+令
+限
+阿
+宣
+環
+雙
+請
+超
+微
+讓
+控
+州
+良
+軸
+找
+否
+紀
+益
+依
+優
+頂
+礎
+載
+倒
+房
+突
+坐
+粉
+敵
+略
+客
+袁
+冷
+勝
+絕
+析
+塊
+劑
+測
+絲
+協
+訴
+念
+陳
+仍
+羅
+鹽
+友
+洋
+錯
+苦
+夜
+刑
+移
+頻
+逐
+靠
+混
+母
+短
+皮
+終
+聚
+汽
+村
+雲
+哪
+既
+距
+衛
+停
+烈
+央
+察
+燒
+迅
+境
+若
+印
+洲
+刻
+括
+激
+孔
+搞
+甚
+室
+待
+核
+校
+散
+侵
+吧
+甲
+遊
+久
+菜
+味
+舊
+模
+湖
+貨
+損
+預
+阻
+毫
+普
+穩
+乙
+媽
+植
+息
+擴
+銀
+語
+揮
+酒
+守
+拿
+序
+紙
+醫
+缺
+雨
+嗎
+針
+劉
+啊
+急
+唱
+誤
+訓
+願
+審
+附
+獲
+茶
+鮮
+糧
+斤
+孩
+脫
+硫
+肥
+善
+龍
+演
+父
+漸
+血
+歡
+械
+掌
+歌
+沙
+剛
+攻
+謂
+盾
+討
+晚
+粒
+亂
+燃
+矛
+乎
+殺
+藥
+寧
+魯
+貴
+鐘
+煤
+讀
+班
+伯
+香
+介
+迫
+句
+豐
+培
+握
+蘭
+擔
+弦
+蛋
+沉
+假
+穿
+執
+答
+樂
+誰
+順
+煙
+縮
+徵
+臉
+喜
+松
+腳
+困
+異
+免
+背
+星
+福
+買
+染
+井
+概
+慢
+怕
+磁
+倍
+祖
+皇
+促
+靜
+補
+評
+翻
+肉
+踐
+尼
+衣
+寬
+揚
+棉
+希
+傷
+操
+垂
+秋
+宜
+氫
+套
+督
+振
+架
+亮
+末
+憲
+慶
+編
+牛
+觸
+映
+雷
+銷
+詩
+座
+居
+抓
+裂
+胞
+呼
+娘
+景
+威
+綠
+晶
+厚
+盟
+衡
+雞
+孫
+延
+危
+膠
+屋
+鄉
+臨
+陸
+顧
+掉
+呀
+燈
+歲
+措
+束
+耐
+劇
+玉
+趙
+跳
+哥
+季
+課
+凱
+胡
+額
+款
+紹
+卷
+齊
+偉
+蒸
+殖
+永
+宗
+苗
+川
+爐
+岩
+弱
+零
+楊
+奏
+沿
+露
+桿
+探
+滑
+鎮
+飯
+濃
+航
+懷
+趕
+庫
+奪
+伊
+靈
+稅
+途
+滅
+賽
+歸
+召
+鼓
+播
+盤
+裁
+險
+康
+唯
+錄
+菌
+純
+借
+糖
+蓋
+橫
+符
+私
+努
+堂
+域
+槍
+潤
+幅
+哈
+竟
+熟
+蟲
+澤
+腦
+壤
+碳
+歐
+遍
+側
+寨
+敢
+徹
+慮
+斜
+薄
+庭
+納
+彈
+飼
+伸
+折
+麥
+濕
+暗
+荷
+瓦
+塞
+床
+築
+惡
+戶
+訪
+塔
+奇
+透
+梁
+刀
+旋
+跡
+卡
+氯
+遇
+份
+毒
+泥
+退
+洗
+擺
+灰
+彩
+賣
+耗
+夏
+擇
+忙
+銅
+獻
+硬
+予
+繁
+圈
+雪
+函
+亦
+抽
+篇
+陣
+陰
+丁
+尺
+追
+堆
+雄
+迎
+泛
+爸
+樓
+避
+謀
+噸
+野
+豬
+旗
+累
+偏
+典
+館
+索
+秦
+脂
+潮
+爺
+豆
+忽
+托
+驚
+塑
+遺
+愈
+朱
+替
+纖
+粗
+傾
+尚
+痛
+楚
+謝
+奮
+購
+磨
+君
+池
+旁
+碎
+骨
+監
+捕
+弟
+暴
+割
+貫
+殊
+釋
+詞
+亡
+壁
+頓
+寶
+午
+塵
+聞
+揭
+炮
+殘
+冬
+橋
+婦
+警
+綜
+招
+吳
+付
+浮
+遭
+徐
+您
+搖
+谷
+贊
+箱
+隔
+訂
+男
+吹
+園
+紛
+唐
+敗
+宋
+玻
+巨
+耕
+坦
+榮
+閉
+灣
+鍵
+凡
+駐
+鍋
+救
+恩
+剝
+凝
+鹼
+齒
+截
+煉
+麻
+紡
+禁
+廢
+盛
+版
+緩
+淨
+睛
+昌
+婚
+涉
+筒
+嘴
+插
+岸
+朗
+莊
+街
+藏
+姑
+貿
+腐
+奴
+啦
+慣
+乘
+夥
+恢
+勻
+紗
+扎
+辯
+耳
+彪
+臣
+億
+璃
+抵
+脈
+秀
+薩
+俄
+網
+舞
+店
+噴
+縱
+寸
+汗
+掛
+洪
+賀
+閃
+柬
+爆
+烯
+津
+稻
+牆
+軟
+勇
+像
+滾
+厘
+蒙
+芳
+肯
+坡
+柱
+盪
+腿
+儀
+旅
+尾
+軋
+冰
+貢
+登
+黎
+削
+鑽
+勒
+逃
+障
+氨
+郭
+峰
+幣
+港
+伏
+軌
+畝
+畢
+擦
+莫
+刺
+浪
+秘
+援
+株
+健
+售
+股
+島
+甘
+泡
+睡
+童
+鑄
+湯
+閥
+休
+匯
+舍
+牧
+繞
+炸
+哲
+磷
+績
+朋
+淡
+尖
+啟
+陷
+柴
+呈
+徒
+顏
+淚
+稍
+忘
+泵
+藍
+拖
+洞
+授
+鏡
+辛
+壯
+鋒
+貧
+虛
+彎
+摩
+泰
+幼
+廷
+尊
+窗
+綱
+弄
+隸
+疑
+氏
+宮
+姐
+震
+瑞
+怪
+尤
+琴
+循
+描
+膜
+違
+夾
+腰
+緣
+珠
+窮
+森
+枝
+竹
+溝
+催
+繩
+憶
+邦
+剩
+幸
+漿
+欄
+擁
+牙
+貯
+禮
+濾
+鈉
+紋
+罷
+拍
+咱
+喊
+袖
+埃
+勤
+罰
+焦
+潛
+伍
+墨
+欲
+縫
+姓
+刊
+飽
+仿
+獎
+鋁
+鬼
+麗
+跨
+默
+挖
+鏈
+掃
+喝
+袋
+炭
+污
+幕
+諸
+弧
+勵
+梅
+奶
+潔
+災
+舟
+鑑
+苯
+訟
+抱
+毀
+懂
+寒
+智
+埔
+寄
+屆
+躍
+渡
+挑
+丹
+艱
+貝
+碰
+拔
+爹
+戴
+碼
+夢
+芽
+熔
+赤
+漁
+哭
+敬
+顆
+奔
+鉛
+仲
+虎
+稀
+妹
+乏
+珍
+申
+桌
+遵
+允
+隆
+螺
+倉
+魏
+銳
+曉
+氮
+兼
+隱
+礙
+赫
+撥
+忠
+肅
+缸
+牽
+搶
+博
+巧
+殼
+兄
+杜
+訊
+誠
+碧
+祥
+柯
+頁
+巡
+矩
+悲
+灌
+齡
+倫
+票
+尋
+桂
+鋪
+聖
+恐
+恰
+鄭
+趣
+抬
+荒
+騰
+貼
+柔
+滴
+猛
+闊
+輛
+妻
+填
+撤
+儲
+簽
+鬧
+擾
+紫
+砂
+遞
+戲
+吊
+陶
+伐
+餵
+療
+瓶
+婆
+撫
+臂
+摸
+忍
+蝦
+蠟
+鄰
+胸
+鞏
+擠
+偶
+棄
+槽
+勁
+乳
+鄧
+吉
+仁
+爛
+磚
+租
+烏
+艦
+伴
+瓜
+淺
+丙
+暫
+燥
+橡
+柳
+迷
+暖
+牌
+秧
+膽
+詳
+簧
+踏
+瓷
+譜
+呆
+賓
+糊
+洛
+輝
+憤
+競
+隙
+怒
+粘
+乃
+緒
+肩
+籍
+敏
+塗
+熙
+皆
+偵
+懸
+掘
+享
+糾
+醒
+狂
+鎖
+淀
+恨
+牲
+霸
+爬
+賞
+逆
+玩
+陵
+祝
+秒
+浙
+貌
+役
+彼
+悉
+鴨
+趨
+鳳
+晨
+畜
+輩
+秩
+卵
+署
+梯
+炎
+灘
+棋
+驅
+篩
+峽
+冒
+啥
+壽
+譯
+浸
+泉
+帽
+遲
+矽
+疆
+貸
+漏
+稿
+冠
+嫩
+脅
+芯
+牢
+叛
+蝕
+奧
+鳴
+嶺
+羊
+憑
+串
+塘
+繪
+酵
+融
+盆
+錫
+廟
+籌
+凍
+輔
+攝
+襲
+筋
+拒
+僚
+旱
+鉀
+鳥
+漆
+沈
+眉
+疏
+添
+棒
+穗
+硝
+韓
+逼
+扭
+僑
+涼
+挺
+碗
+栽
+炒
+杯
+患
+餾
+勸
+豪
+遼
+勃
+鴻
+旦
+吏
+拜
+狗
+埋
+輥
+掩
+飲
+搬
+罵
+辭
+勾
+扣
+估
+蔣
+絨
+霧
+丈
+朵
+姆
+擬
+宇
+輯
+陝
+雕
+償
+蓄
+崇
+剪
+倡
+廳
+咬
+駛
+薯
+刷
+斥
+番
+賦
+奉
+佛
+澆
+漫
+曼
+扇
+鈣
+桃
+扶
+仔
+返
+俗
+虧
+腔
+鞋
+棱
+覆
+框
+悄
+叔
+撞
+騙
+勘
+旺
+沸
+孤
+吐
+孟
+渠
+屈
+疾
+妙
+惜
+仰
+狠
+脹
+諧
+拋
+黴
+桑
+崗
+嘛
+衰
+盜
+滲
+臟
+賴
+湧
+甜
+曹
+閱
+肌
+哩
+厲
+烴
+緯
+毅
+昨
+偽
+症
+煮
+嘆
+釘
+搭
+莖
+籠
+酷
+偷
+弓
+錐
+恆
+傑
+坑
+鼻
+翼
+綸
+敘
+獄
+逮
+罐
+絡
+棚
+抑
+膨
+蔬
+寺
+驟
+穆
+冶
+枯
+冊
+屍
+凸
+紳
+坯
+犧
+焰
+轟
+欣
+晉
+瘦
+禦
+錠
+錦
+喪
+旬
+鍛
+壟
+搜
+撲
+邀
+亭
+酯
+邁
+舒
+脆
+酶
+閒
+憂
+酚
+頑
+羽
+漲
+卸
+仗
+陪
+闢
+懲
+杭
+姚
+肚
+捉
+飄
+漂
+昆
+欺
+吾
+郎
+烷
+汁
+呵
+飾
+蕭
+雅
+郵
+遷
+燕
+撒
+姻
+赴
+宴
+煩
+債
+帳
+斑
+鈴
+旨
+醇
+董
+餅
+雛
+姿
+拌
+傅
+腹
+妥
+揉
+賢
+拆
+歪
+葡
+胺
+丟
+浩
+徽
+昂
+墊
+擋
+覽
+貪
+慰
+繳
+汪
+慌
+馮
+諾
+姜
+誼
+兇
+劣
+誣
+耀
+昏
+躺
+盈
+騎
+喬
+溪
+叢
+盧
+抹
+悶
+諮
+刮
+駕
+纜
+悟
+摘
+鉺
+擲
+頗
+幻
+柄
+惠
+慘
+佳
+仇
+臘
+窩
+滌
+劍
+瞧
+堡
+潑
+蔥
+罩
+霍
+撈
+胎
+蒼
+濱
+倆
+捅
+湘
+砍
+霞
+邵
+萄
+瘋
+淮
+遂
+熊
+糞
+烘
+宿
+檔
+戈
+駁
+嫂
+裕
+徙
+箭
+捐
+腸
+撐
+曬
+辨
+殿
+蓮
+攤
+攪
+醬
+屏
+疫
+哀
+蔡
+堵
+沫
+皺
+暢
+疊
+閣
+萊
+敲
+轄
+鉤
+痕
+壩
+巷
+餓
+禍
+丘
+玄
+溜
+曰
+邏
+彭
+嘗
+卿
+妨
+艇
+吞
+韋
+怨
+矮
+歇
diff --git a/frozen_deps/mnemonic/wordlist/english.txt b/frozen_deps/mnemonic/wordlist/english.txt
new file mode 100644
index 0000000..942040e
--- /dev/null
+++ b/frozen_deps/mnemonic/wordlist/english.txt
@@ -0,0 +1,2048 @@
+abandon
+ability
+able
+about
+above
+absent
+absorb
+abstract
+absurd
+abuse
+access
+accident
+account
+accuse
+achieve
+acid
+acoustic
+acquire
+across
+act
+action
+actor
+actress
+actual
+adapt
+add
+addict
+address
+adjust
+admit
+adult
+advance
+advice
+aerobic
+affair
+afford
+afraid
+again
+age
+agent
+agree
+ahead
+aim
+air
+airport
+aisle
+alarm
+album
+alcohol
+alert
+alien
+all
+alley
+allow
+almost
+alone
+alpha
+already
+also
+alter
+always
+amateur
+amazing
+among
+amount
+amused
+analyst
+anchor
+ancient
+anger
+angle
+angry
+animal
+ankle
+announce
+annual
+another
+answer
+antenna
+antique
+anxiety
+any
+apart
+apology
+appear
+apple
+approve
+april
+arch
+arctic
+area
+arena
+argue
+arm
+armed
+armor
+army
+around
+arrange
+arrest
+arrive
+arrow
+art
+artefact
+artist
+artwork
+ask
+aspect
+assault
+asset
+assist
+assume
+asthma
+athlete
+atom
+attack
+attend
+attitude
+attract
+auction
+audit
+august
+aunt
+author
+auto
+autumn
+average
+avocado
+avoid
+awake
+aware
+away
+awesome
+awful
+awkward
+axis
+baby
+bachelor
+bacon
+badge
+bag
+balance
+balcony
+ball
+bamboo
+banana
+banner
+bar
+barely
+bargain
+barrel
+base
+basic
+basket
+battle
+beach
+bean
+beauty
+because
+become
+beef
+before
+begin
+behave
+behind
+believe
+below
+belt
+bench
+benefit
+best
+betray
+better
+between
+beyond
+bicycle
+bid
+bike
+bind
+biology
+bird
+birth
+bitter
+black
+blade
+blame
+blanket
+blast
+bleak
+bless
+blind
+blood
+blossom
+blouse
+blue
+blur
+blush
+board
+boat
+body
+boil
+bomb
+bone
+bonus
+book
+boost
+border
+boring
+borrow
+boss
+bottom
+bounce
+box
+boy
+bracket
+brain
+brand
+brass
+brave
+bread
+breeze
+brick
+bridge
+brief
+bright
+bring
+brisk
+broccoli
+broken
+bronze
+broom
+brother
+brown
+brush
+bubble
+buddy
+budget
+buffalo
+build
+bulb
+bulk
+bullet
+bundle
+bunker
+burden
+burger
+burst
+bus
+business
+busy
+butter
+buyer
+buzz
+cabbage
+cabin
+cable
+cactus
+cage
+cake
+call
+calm
+camera
+camp
+can
+canal
+cancel
+candy
+cannon
+canoe
+canvas
+canyon
+capable
+capital
+captain
+car
+carbon
+card
+cargo
+carpet
+carry
+cart
+case
+cash
+casino
+castle
+casual
+cat
+catalog
+catch
+category
+cattle
+caught
+cause
+caution
+cave
+ceiling
+celery
+cement
+census
+century
+cereal
+certain
+chair
+chalk
+champion
+change
+chaos
+chapter
+charge
+chase
+chat
+cheap
+check
+cheese
+chef
+cherry
+chest
+chicken
+chief
+child
+chimney
+choice
+choose
+chronic
+chuckle
+chunk
+churn
+cigar
+cinnamon
+circle
+citizen
+city
+civil
+claim
+clap
+clarify
+claw
+clay
+clean
+clerk
+clever
+click
+client
+cliff
+climb
+clinic
+clip
+clock
+clog
+close
+cloth
+cloud
+clown
+club
+clump
+cluster
+clutch
+coach
+coast
+coconut
+code
+coffee
+coil
+coin
+collect
+color
+column
+combine
+come
+comfort
+comic
+common
+company
+concert
+conduct
+confirm
+congress
+connect
+consider
+control
+convince
+cook
+cool
+copper
+copy
+coral
+core
+corn
+correct
+cost
+cotton
+couch
+country
+couple
+course
+cousin
+cover
+coyote
+crack
+cradle
+craft
+cram
+crane
+crash
+crater
+crawl
+crazy
+cream
+credit
+creek
+crew
+cricket
+crime
+crisp
+critic
+crop
+cross
+crouch
+crowd
+crucial
+cruel
+cruise
+crumble
+crunch
+crush
+cry
+crystal
+cube
+culture
+cup
+cupboard
+curious
+current
+curtain
+curve
+cushion
+custom
+cute
+cycle
+dad
+damage
+damp
+dance
+danger
+daring
+dash
+daughter
+dawn
+day
+deal
+debate
+debris
+decade
+december
+decide
+decline
+decorate
+decrease
+deer
+defense
+define
+defy
+degree
+delay
+deliver
+demand
+demise
+denial
+dentist
+deny
+depart
+depend
+deposit
+depth
+deputy
+derive
+describe
+desert
+design
+desk
+despair
+destroy
+detail
+detect
+develop
+device
+devote
+diagram
+dial
+diamond
+diary
+dice
+diesel
+diet
+differ
+digital
+dignity
+dilemma
+dinner
+dinosaur
+direct
+dirt
+disagree
+discover
+disease
+dish
+dismiss
+disorder
+display
+distance
+divert
+divide
+divorce
+dizzy
+doctor
+document
+dog
+doll
+dolphin
+domain
+donate
+donkey
+donor
+door
+dose
+double
+dove
+draft
+dragon
+drama
+drastic
+draw
+dream
+dress
+drift
+drill
+drink
+drip
+drive
+drop
+drum
+dry
+duck
+dumb
+dune
+during
+dust
+dutch
+duty
+dwarf
+dynamic
+eager
+eagle
+early
+earn
+earth
+easily
+east
+easy
+echo
+ecology
+economy
+edge
+edit
+educate
+effort
+egg
+eight
+either
+elbow
+elder
+electric
+elegant
+element
+elephant
+elevator
+elite
+else
+embark
+embody
+embrace
+emerge
+emotion
+employ
+empower
+empty
+enable
+enact
+end
+endless
+endorse
+enemy
+energy
+enforce
+engage
+engine
+enhance
+enjoy
+enlist
+enough
+enrich
+enroll
+ensure
+enter
+entire
+entry
+envelope
+episode
+equal
+equip
+era
+erase
+erode
+erosion
+error
+erupt
+escape
+essay
+essence
+estate
+eternal
+ethics
+evidence
+evil
+evoke
+evolve
+exact
+example
+excess
+exchange
+excite
+exclude
+excuse
+execute
+exercise
+exhaust
+exhibit
+exile
+exist
+exit
+exotic
+expand
+expect
+expire
+explain
+expose
+express
+extend
+extra
+eye
+eyebrow
+fabric
+face
+faculty
+fade
+faint
+faith
+fall
+false
+fame
+family
+famous
+fan
+fancy
+fantasy
+farm
+fashion
+fat
+fatal
+father
+fatigue
+fault
+favorite
+feature
+february
+federal
+fee
+feed
+feel
+female
+fence
+festival
+fetch
+fever
+few
+fiber
+fiction
+field
+figure
+file
+film
+filter
+final
+find
+fine
+finger
+finish
+fire
+firm
+first
+fiscal
+fish
+fit
+fitness
+fix
+flag
+flame
+flash
+flat
+flavor
+flee
+flight
+flip
+float
+flock
+floor
+flower
+fluid
+flush
+fly
+foam
+focus
+fog
+foil
+fold
+follow
+food
+foot
+force
+forest
+forget
+fork
+fortune
+forum
+forward
+fossil
+foster
+found
+fox
+fragile
+frame
+frequent
+fresh
+friend
+fringe
+frog
+front
+frost
+frown
+frozen
+fruit
+fuel
+fun
+funny
+furnace
+fury
+future
+gadget
+gain
+galaxy
+gallery
+game
+gap
+garage
+garbage
+garden
+garlic
+garment
+gas
+gasp
+gate
+gather
+gauge
+gaze
+general
+genius
+genre
+gentle
+genuine
+gesture
+ghost
+giant
+gift
+giggle
+ginger
+giraffe
+girl
+give
+glad
+glance
+glare
+glass
+glide
+glimpse
+globe
+gloom
+glory
+glove
+glow
+glue
+goat
+goddess
+gold
+good
+goose
+gorilla
+gospel
+gossip
+govern
+gown
+grab
+grace
+grain
+grant
+grape
+grass
+gravity
+great
+green
+grid
+grief
+grit
+grocery
+group
+grow
+grunt
+guard
+guess
+guide
+guilt
+guitar
+gun
+gym
+habit
+hair
+half
+hammer
+hamster
+hand
+happy
+harbor
+hard
+harsh
+harvest
+hat
+have
+hawk
+hazard
+head
+health
+heart
+heavy
+hedgehog
+height
+hello
+helmet
+help
+hen
+hero
+hidden
+high
+hill
+hint
+hip
+hire
+history
+hobby
+hockey
+hold
+hole
+holiday
+hollow
+home
+honey
+hood
+hope
+horn
+horror
+horse
+hospital
+host
+hotel
+hour
+hover
+hub
+huge
+human
+humble
+humor
+hundred
+hungry
+hunt
+hurdle
+hurry
+hurt
+husband
+hybrid
+ice
+icon
+idea
+identify
+idle
+ignore
+ill
+illegal
+illness
+image
+imitate
+immense
+immune
+impact
+impose
+improve
+impulse
+inch
+include
+income
+increase
+index
+indicate
+indoor
+industry
+infant
+inflict
+inform
+inhale
+inherit
+initial
+inject
+injury
+inmate
+inner
+innocent
+input
+inquiry
+insane
+insect
+inside
+inspire
+install
+intact
+interest
+into
+invest
+invite
+involve
+iron
+island
+isolate
+issue
+item
+ivory
+jacket
+jaguar
+jar
+jazz
+jealous
+jeans
+jelly
+jewel
+job
+join
+joke
+journey
+joy
+judge
+juice
+jump
+jungle
+junior
+junk
+just
+kangaroo
+keen
+keep
+ketchup
+key
+kick
+kid
+kidney
+kind
+kingdom
+kiss
+kit
+kitchen
+kite
+kitten
+kiwi
+knee
+knife
+knock
+know
+lab
+label
+labor
+ladder
+lady
+lake
+lamp
+language
+laptop
+large
+later
+latin
+laugh
+laundry
+lava
+law
+lawn
+lawsuit
+layer
+lazy
+leader
+leaf
+learn
+leave
+lecture
+left
+leg
+legal
+legend
+leisure
+lemon
+lend
+length
+lens
+leopard
+lesson
+letter
+level
+liar
+liberty
+library
+license
+life
+lift
+light
+like
+limb
+limit
+link
+lion
+liquid
+list
+little
+live
+lizard
+load
+loan
+lobster
+local
+lock
+logic
+lonely
+long
+loop
+lottery
+loud
+lounge
+love
+loyal
+lucky
+luggage
+lumber
+lunar
+lunch
+luxury
+lyrics
+machine
+mad
+magic
+magnet
+maid
+mail
+main
+major
+make
+mammal
+man
+manage
+mandate
+mango
+mansion
+manual
+maple
+marble
+march
+margin
+marine
+market
+marriage
+mask
+mass
+master
+match
+material
+math
+matrix
+matter
+maximum
+maze
+meadow
+mean
+measure
+meat
+mechanic
+medal
+media
+melody
+melt
+member
+memory
+mention
+menu
+mercy
+merge
+merit
+merry
+mesh
+message
+metal
+method
+middle
+midnight
+milk
+million
+mimic
+mind
+minimum
+minor
+minute
+miracle
+mirror
+misery
+miss
+mistake
+mix
+mixed
+mixture
+mobile
+model
+modify
+mom
+moment
+monitor
+monkey
+monster
+month
+moon
+moral
+more
+morning
+mosquito
+mother
+motion
+motor
+mountain
+mouse
+move
+movie
+much
+muffin
+mule
+multiply
+muscle
+museum
+mushroom
+music
+must
+mutual
+myself
+mystery
+myth
+naive
+name
+napkin
+narrow
+nasty
+nation
+nature
+near
+neck
+need
+negative
+neglect
+neither
+nephew
+nerve
+nest
+net
+network
+neutral
+never
+news
+next
+nice
+night
+noble
+noise
+nominee
+noodle
+normal
+north
+nose
+notable
+note
+nothing
+notice
+novel
+now
+nuclear
+number
+nurse
+nut
+oak
+obey
+object
+oblige
+obscure
+observe
+obtain
+obvious
+occur
+ocean
+october
+odor
+off
+offer
+office
+often
+oil
+okay
+old
+olive
+olympic
+omit
+once
+one
+onion
+online
+only
+open
+opera
+opinion
+oppose
+option
+orange
+orbit
+orchard
+order
+ordinary
+organ
+orient
+original
+orphan
+ostrich
+other
+outdoor
+outer
+output
+outside
+oval
+oven
+over
+own
+owner
+oxygen
+oyster
+ozone
+pact
+paddle
+page
+pair
+palace
+palm
+panda
+panel
+panic
+panther
+paper
+parade
+parent
+park
+parrot
+party
+pass
+patch
+path
+patient
+patrol
+pattern
+pause
+pave
+payment
+peace
+peanut
+pear
+peasant
+pelican
+pen
+penalty
+pencil
+people
+pepper
+perfect
+permit
+person
+pet
+phone
+photo
+phrase
+physical
+piano
+picnic
+picture
+piece
+pig
+pigeon
+pill
+pilot
+pink
+pioneer
+pipe
+pistol
+pitch
+pizza
+place
+planet
+plastic
+plate
+play
+please
+pledge
+pluck
+plug
+plunge
+poem
+poet
+point
+polar
+pole
+police
+pond
+pony
+pool
+popular
+portion
+position
+possible
+post
+potato
+pottery
+poverty
+powder
+power
+practice
+praise
+predict
+prefer
+prepare
+present
+pretty
+prevent
+price
+pride
+primary
+print
+priority
+prison
+private
+prize
+problem
+process
+produce
+profit
+program
+project
+promote
+proof
+property
+prosper
+protect
+proud
+provide
+public
+pudding
+pull
+pulp
+pulse
+pumpkin
+punch
+pupil
+puppy
+purchase
+purity
+purpose
+purse
+push
+put
+puzzle
+pyramid
+quality
+quantum
+quarter
+question
+quick
+quit
+quiz
+quote
+rabbit
+raccoon
+race
+rack
+radar
+radio
+rail
+rain
+raise
+rally
+ramp
+ranch
+random
+range
+rapid
+rare
+rate
+rather
+raven
+raw
+razor
+ready
+real
+reason
+rebel
+rebuild
+recall
+receive
+recipe
+record
+recycle
+reduce
+reflect
+reform
+refuse
+region
+regret
+regular
+reject
+relax
+release
+relief
+rely
+remain
+remember
+remind
+remove
+render
+renew
+rent
+reopen
+repair
+repeat
+replace
+report
+require
+rescue
+resemble
+resist
+resource
+response
+result
+retire
+retreat
+return
+reunion
+reveal
+review
+reward
+rhythm
+rib
+ribbon
+rice
+rich
+ride
+ridge
+rifle
+right
+rigid
+ring
+riot
+ripple
+risk
+ritual
+rival
+river
+road
+roast
+robot
+robust
+rocket
+romance
+roof
+rookie
+room
+rose
+rotate
+rough
+round
+route
+royal
+rubber
+rude
+rug
+rule
+run
+runway
+rural
+sad
+saddle
+sadness
+safe
+sail
+salad
+salmon
+salon
+salt
+salute
+same
+sample
+sand
+satisfy
+satoshi
+sauce
+sausage
+save
+say
+scale
+scan
+scare
+scatter
+scene
+scheme
+school
+science
+scissors
+scorpion
+scout
+scrap
+screen
+script
+scrub
+sea
+search
+season
+seat
+second
+secret
+section
+security
+seed
+seek
+segment
+select
+sell
+seminar
+senior
+sense
+sentence
+series
+service
+session
+settle
+setup
+seven
+shadow
+shaft
+shallow
+share
+shed
+shell
+sheriff
+shield
+shift
+shine
+ship
+shiver
+shock
+shoe
+shoot
+shop
+short
+shoulder
+shove
+shrimp
+shrug
+shuffle
+shy
+sibling
+sick
+side
+siege
+sight
+sign
+silent
+silk
+silly
+silver
+similar
+simple
+since
+sing
+siren
+sister
+situate
+six
+size
+skate
+sketch
+ski
+skill
+skin
+skirt
+skull
+slab
+slam
+sleep
+slender
+slice
+slide
+slight
+slim
+slogan
+slot
+slow
+slush
+small
+smart
+smile
+smoke
+smooth
+snack
+snake
+snap
+sniff
+snow
+soap
+soccer
+social
+sock
+soda
+soft
+solar
+soldier
+solid
+solution
+solve
+someone
+song
+soon
+sorry
+sort
+soul
+sound
+soup
+source
+south
+space
+spare
+spatial
+spawn
+speak
+special
+speed
+spell
+spend
+sphere
+spice
+spider
+spike
+spin
+spirit
+split
+spoil
+sponsor
+spoon
+sport
+spot
+spray
+spread
+spring
+spy
+square
+squeeze
+squirrel
+stable
+stadium
+staff
+stage
+stairs
+stamp
+stand
+start
+state
+stay
+steak
+steel
+stem
+step
+stereo
+stick
+still
+sting
+stock
+stomach
+stone
+stool
+story
+stove
+strategy
+street
+strike
+strong
+struggle
+student
+stuff
+stumble
+style
+subject
+submit
+subway
+success
+such
+sudden
+suffer
+sugar
+suggest
+suit
+summer
+sun
+sunny
+sunset
+super
+supply
+supreme
+sure
+surface
+surge
+surprise
+surround
+survey
+suspect
+sustain
+swallow
+swamp
+swap
+swarm
+swear
+sweet
+swift
+swim
+swing
+switch
+sword
+symbol
+symptom
+syrup
+system
+table
+tackle
+tag
+tail
+talent
+talk
+tank
+tape
+target
+task
+taste
+tattoo
+taxi
+teach
+team
+tell
+ten
+tenant
+tennis
+tent
+term
+test
+text
+thank
+that
+theme
+then
+theory
+there
+they
+thing
+this
+thought
+three
+thrive
+throw
+thumb
+thunder
+ticket
+tide
+tiger
+tilt
+timber
+time
+tiny
+tip
+tired
+tissue
+title
+toast
+tobacco
+today
+toddler
+toe
+together
+toilet
+token
+tomato
+tomorrow
+tone
+tongue
+tonight
+tool
+tooth
+top
+topic
+topple
+torch
+tornado
+tortoise
+toss
+total
+tourist
+toward
+tower
+town
+toy
+track
+trade
+traffic
+tragic
+train
+transfer
+trap
+trash
+travel
+tray
+treat
+tree
+trend
+trial
+tribe
+trick
+trigger
+trim
+trip
+trophy
+trouble
+truck
+true
+truly
+trumpet
+trust
+truth
+try
+tube
+tuition
+tumble
+tuna
+tunnel
+turkey
+turn
+turtle
+twelve
+twenty
+twice
+twin
+twist
+two
+type
+typical
+ugly
+umbrella
+unable
+unaware
+uncle
+uncover
+under
+undo
+unfair
+unfold
+unhappy
+uniform
+unique
+unit
+universe
+unknown
+unlock
+until
+unusual
+unveil
+update
+upgrade
+uphold
+upon
+upper
+upset
+urban
+urge
+usage
+use
+used
+useful
+useless
+usual
+utility
+vacant
+vacuum
+vague
+valid
+valley
+valve
+van
+vanish
+vapor
+various
+vast
+vault
+vehicle
+velvet
+vendor
+venture
+venue
+verb
+verify
+version
+very
+vessel
+veteran
+viable
+vibrant
+vicious
+victory
+video
+view
+village
+vintage
+violin
+virtual
+virus
+visa
+visit
+visual
+vital
+vivid
+vocal
+voice
+void
+volcano
+volume
+vote
+voyage
+wage
+wagon
+wait
+walk
+wall
+walnut
+want
+warfare
+warm
+warrior
+wash
+wasp
+waste
+water
+wave
+way
+wealth
+weapon
+wear
+weasel
+weather
+web
+wedding
+weekend
+weird
+welcome
+west
+wet
+whale
+what
+wheat
+wheel
+when
+where
+whip
+whisper
+wide
+width
+wife
+wild
+will
+win
+window
+wine
+wing
+wink
+winner
+winter
+wire
+wisdom
+wise
+wish
+witness
+wolf
+woman
+wonder
+wood
+wool
+word
+work
+world
+worry
+worth
+wrap
+wreck
+wrestle
+wrist
+write
+wrong
+yard
+year
+yellow
+you
+young
+youth
+zebra
+zero
+zone
+zoo
diff --git a/frozen_deps/mnemonic/wordlist/french.txt b/frozen_deps/mnemonic/wordlist/french.txt
new file mode 100644
index 0000000..8600949
--- /dev/null
+++ b/frozen_deps/mnemonic/wordlist/french.txt
@@ -0,0 +1,2048 @@
+abaisser
+abandon
+abdiquer
+abeille
+abolir
+aborder
+aboutir
+aboyer
+abrasif
+abreuver
+abriter
+abroger
+abrupt
+absence
+absolu
+absurde
+abusif
+abyssal
+académie
+acajou
+acarien
+accabler
+accepter
+acclamer
+accolade
+accroche
+accuser
+acerbe
+achat
+acheter
+aciduler
+acier
+acompte
+acquérir
+acronyme
+acteur
+actif
+actuel
+adepte
+adéquat
+adhésif
+adjectif
+adjuger
+admettre
+admirer
+adopter
+adorer
+adoucir
+adresse
+adroit
+adulte
+adverbe
+aérer
+aéronef
+affaire
+affecter
+affiche
+affreux
+affubler
+agacer
+agencer
+agile
+agiter
+agrafer
+agréable
+agrume
+aider
+aiguille
+ailier
+aimable
+aisance
+ajouter
+ajuster
+alarmer
+alchimie
+alerte
+algèbre
+algue
+aliéner
+aliment
+alléger
+alliage
+allouer
+allumer
+alourdir
+alpaga
+altesse
+alvéole
+amateur
+ambigu
+ambre
+aménager
+amertume
+amidon
+amiral
+amorcer
+amour
+amovible
+amphibie
+ampleur
+amusant
+analyse
+anaphore
+anarchie
+anatomie
+ancien
+anéantir
+angle
+angoisse
+anguleux
+animal
+annexer
+annonce
+annuel
+anodin
+anomalie
+anonyme
+anormal
+antenne
+antidote
+anxieux
+apaiser
+apéritif
+aplanir
+apologie
+appareil
+appeler
+apporter
+appuyer
+aquarium
+aqueduc
+arbitre
+arbuste
+ardeur
+ardoise
+argent
+arlequin
+armature
+armement
+armoire
+armure
+arpenter
+arracher
+arriver
+arroser
+arsenic
+artériel
+article
+aspect
+asphalte
+aspirer
+assaut
+asservir
+assiette
+associer
+assurer
+asticot
+astre
+astuce
+atelier
+atome
+atrium
+atroce
+attaque
+attentif
+attirer
+attraper
+aubaine
+auberge
+audace
+audible
+augurer
+aurore
+automne
+autruche
+avaler
+avancer
+avarice
+avenir
+averse
+aveugle
+aviateur
+avide
+avion
+aviser
+avoine
+avouer
+avril
+axial
+axiome
+badge
+bafouer
+bagage
+baguette
+baignade
+balancer
+balcon
+baleine
+balisage
+bambin
+bancaire
+bandage
+banlieue
+bannière
+banquier
+barbier
+baril
+baron
+barque
+barrage
+bassin
+bastion
+bataille
+bateau
+batterie
+baudrier
+bavarder
+belette
+bélier
+belote
+bénéfice
+berceau
+berger
+berline
+bermuda
+besace
+besogne
+bétail
+beurre
+biberon
+bicycle
+bidule
+bijou
+bilan
+bilingue
+billard
+binaire
+biologie
+biopsie
+biotype
+biscuit
+bison
+bistouri
+bitume
+bizarre
+blafard
+blague
+blanchir
+blessant
+blinder
+blond
+bloquer
+blouson
+bobard
+bobine
+boire
+boiser
+bolide
+bonbon
+bondir
+bonheur
+bonifier
+bonus
+bordure
+borne
+botte
+boucle
+boueux
+bougie
+boulon
+bouquin
+bourse
+boussole
+boutique
+boxeur
+branche
+brasier
+brave
+brebis
+brèche
+breuvage
+bricoler
+brigade
+brillant
+brioche
+brique
+brochure
+broder
+bronzer
+brousse
+broyeur
+brume
+brusque
+brutal
+bruyant
+buffle
+buisson
+bulletin
+bureau
+burin
+bustier
+butiner
+butoir
+buvable
+buvette
+cabanon
+cabine
+cachette
+cadeau
+cadre
+caféine
+caillou
+caisson
+calculer
+calepin
+calibre
+calmer
+calomnie
+calvaire
+camarade
+caméra
+camion
+campagne
+canal
+caneton
+canon
+cantine
+canular
+capable
+caporal
+caprice
+capsule
+capter
+capuche
+carabine
+carbone
+caresser
+caribou
+carnage
+carotte
+carreau
+carton
+cascade
+casier
+casque
+cassure
+causer
+caution
+cavalier
+caverne
+caviar
+cédille
+ceinture
+céleste
+cellule
+cendrier
+censurer
+central
+cercle
+cérébral
+cerise
+cerner
+cerveau
+cesser
+chagrin
+chaise
+chaleur
+chambre
+chance
+chapitre
+charbon
+chasseur
+chaton
+chausson
+chavirer
+chemise
+chenille
+chéquier
+chercher
+cheval
+chien
+chiffre
+chignon
+chimère
+chiot
+chlorure
+chocolat
+choisir
+chose
+chouette
+chrome
+chute
+cigare
+cigogne
+cimenter
+cinéma
+cintrer
+circuler
+cirer
+cirque
+citerne
+citoyen
+citron
+civil
+clairon
+clameur
+claquer
+classe
+clavier
+client
+cligner
+climat
+clivage
+cloche
+clonage
+cloporte
+cobalt
+cobra
+cocasse
+cocotier
+coder
+codifier
+coffre
+cogner
+cohésion
+coiffer
+coincer
+colère
+colibri
+colline
+colmater
+colonel
+combat
+comédie
+commande
+compact
+concert
+conduire
+confier
+congeler
+connoter
+consonne
+contact
+convexe
+copain
+copie
+corail
+corbeau
+cordage
+corniche
+corpus
+correct
+cortège
+cosmique
+costume
+coton
+coude
+coupure
+courage
+couteau
+couvrir
+coyote
+crabe
+crainte
+cravate
+crayon
+créature
+créditer
+crémeux
+creuser
+crevette
+cribler
+crier
+cristal
+critère
+croire
+croquer
+crotale
+crucial
+cruel
+crypter
+cubique
+cueillir
+cuillère
+cuisine
+cuivre
+culminer
+cultiver
+cumuler
+cupide
+curatif
+curseur
+cyanure
+cycle
+cylindre
+cynique
+daigner
+damier
+danger
+danseur
+dauphin
+débattre
+débiter
+déborder
+débrider
+débutant
+décaler
+décembre
+déchirer
+décider
+déclarer
+décorer
+décrire
+décupler
+dédale
+déductif
+déesse
+défensif
+défiler
+défrayer
+dégager
+dégivrer
+déglutir
+dégrafer
+déjeuner
+délice
+déloger
+demander
+demeurer
+démolir
+dénicher
+dénouer
+dentelle
+dénuder
+départ
+dépenser
+déphaser
+déplacer
+déposer
+déranger
+dérober
+désastre
+descente
+désert
+désigner
+désobéir
+dessiner
+destrier
+détacher
+détester
+détourer
+détresse
+devancer
+devenir
+deviner
+devoir
+diable
+dialogue
+diamant
+dicter
+différer
+digérer
+digital
+digne
+diluer
+dimanche
+diminuer
+dioxyde
+directif
+diriger
+discuter
+disposer
+dissiper
+distance
+divertir
+diviser
+docile
+docteur
+dogme
+doigt
+domaine
+domicile
+dompter
+donateur
+donjon
+donner
+dopamine
+dortoir
+dorure
+dosage
+doseur
+dossier
+dotation
+douanier
+double
+douceur
+douter
+doyen
+dragon
+draper
+dresser
+dribbler
+droiture
+duperie
+duplexe
+durable
+durcir
+dynastie
+éblouir
+écarter
+écharpe
+échelle
+éclairer
+éclipse
+éclore
+écluse
+école
+économie
+écorce
+écouter
+écraser
+écrémer
+écrivain
+écrou
+écume
+écureuil
+édifier
+éduquer
+effacer
+effectif
+effigie
+effort
+effrayer
+effusion
+égaliser
+égarer
+éjecter
+élaborer
+élargir
+électron
+élégant
+éléphant
+élève
+éligible
+élitisme
+éloge
+élucider
+éluder
+emballer
+embellir
+embryon
+émeraude
+émission
+emmener
+émotion
+émouvoir
+empereur
+employer
+emporter
+emprise
+émulsion
+encadrer
+enchère
+enclave
+encoche
+endiguer
+endosser
+endroit
+enduire
+énergie
+enfance
+enfermer
+enfouir
+engager
+engin
+englober
+énigme
+enjamber
+enjeu
+enlever
+ennemi
+ennuyeux
+enrichir
+enrobage
+enseigne
+entasser
+entendre
+entier
+entourer
+entraver
+énumérer
+envahir
+enviable
+envoyer
+enzyme
+éolien
+épaissir
+épargne
+épatant
+épaule
+épicerie
+épidémie
+épier
+épilogue
+épine
+épisode
+épitaphe
+époque
+épreuve
+éprouver
+épuisant
+équerre
+équipe
+ériger
+érosion
+erreur
+éruption
+escalier
+espadon
+espèce
+espiègle
+espoir
+esprit
+esquiver
+essayer
+essence
+essieu
+essorer
+estime
+estomac
+estrade
+étagère
+étaler
+étanche
+étatique
+éteindre
+étendoir
+éternel
+éthanol
+éthique
+ethnie
+étirer
+étoffer
+étoile
+étonnant
+étourdir
+étrange
+étroit
+étude
+euphorie
+évaluer
+évasion
+éventail
+évidence
+éviter
+évolutif
+évoquer
+exact
+exagérer
+exaucer
+exceller
+excitant
+exclusif
+excuse
+exécuter
+exemple
+exercer
+exhaler
+exhorter
+exigence
+exiler
+exister
+exotique
+expédier
+explorer
+exposer
+exprimer
+exquis
+extensif
+extraire
+exulter
+fable
+fabuleux
+facette
+facile
+facture
+faiblir
+falaise
+fameux
+famille
+farceur
+farfelu
+farine
+farouche
+fasciner
+fatal
+fatigue
+faucon
+fautif
+faveur
+favori
+fébrile
+féconder
+fédérer
+félin
+femme
+fémur
+fendoir
+féodal
+fermer
+féroce
+ferveur
+festival
+feuille
+feutre
+février
+fiasco
+ficeler
+fictif
+fidèle
+figure
+filature
+filetage
+filière
+filleul
+filmer
+filou
+filtrer
+financer
+finir
+fiole
+firme
+fissure
+fixer
+flairer
+flamme
+flasque
+flatteur
+fléau
+flèche
+fleur
+flexion
+flocon
+flore
+fluctuer
+fluide
+fluvial
+folie
+fonderie
+fongible
+fontaine
+forcer
+forgeron
+formuler
+fortune
+fossile
+foudre
+fougère
+fouiller
+foulure
+fourmi
+fragile
+fraise
+franchir
+frapper
+frayeur
+frégate
+freiner
+frelon
+frémir
+frénésie
+frère
+friable
+friction
+frisson
+frivole
+froid
+fromage
+frontal
+frotter
+fruit
+fugitif
+fuite
+fureur
+furieux
+furtif
+fusion
+futur
+gagner
+galaxie
+galerie
+gambader
+garantir
+gardien
+garnir
+garrigue
+gazelle
+gazon
+géant
+gélatine
+gélule
+gendarme
+général
+génie
+genou
+gentil
+géologie
+géomètre
+géranium
+germe
+gestuel
+geyser
+gibier
+gicler
+girafe
+givre
+glace
+glaive
+glisser
+globe
+gloire
+glorieux
+golfeur
+gomme
+gonfler
+gorge
+gorille
+goudron
+gouffre
+goulot
+goupille
+gourmand
+goutte
+graduel
+graffiti
+graine
+grand
+grappin
+gratuit
+gravir
+grenat
+griffure
+griller
+grimper
+grogner
+gronder
+grotte
+groupe
+gruger
+grutier
+gruyère
+guépard
+guerrier
+guide
+guimauve
+guitare
+gustatif
+gymnaste
+gyrostat
+habitude
+hachoir
+halte
+hameau
+hangar
+hanneton
+haricot
+harmonie
+harpon
+hasard
+hélium
+hématome
+herbe
+hérisson
+hermine
+héron
+hésiter
+heureux
+hiberner
+hibou
+hilarant
+histoire
+hiver
+homard
+hommage
+homogène
+honneur
+honorer
+honteux
+horde
+horizon
+horloge
+hormone
+horrible
+houleux
+housse
+hublot
+huileux
+humain
+humble
+humide
+humour
+hurler
+hydromel
+hygiène
+hymne
+hypnose
+idylle
+ignorer
+iguane
+illicite
+illusion
+image
+imbiber
+imiter
+immense
+immobile
+immuable
+impact
+impérial
+implorer
+imposer
+imprimer
+imputer
+incarner
+incendie
+incident
+incliner
+incolore
+indexer
+indice
+inductif
+inédit
+ineptie
+inexact
+infini
+infliger
+informer
+infusion
+ingérer
+inhaler
+inhiber
+injecter
+injure
+innocent
+inoculer
+inonder
+inscrire
+insecte
+insigne
+insolite
+inspirer
+instinct
+insulter
+intact
+intense
+intime
+intrigue
+intuitif
+inutile
+invasion
+inventer
+inviter
+invoquer
+ironique
+irradier
+irréel
+irriter
+isoler
+ivoire
+ivresse
+jaguar
+jaillir
+jambe
+janvier
+jardin
+jauger
+jaune
+javelot
+jetable
+jeton
+jeudi
+jeunesse
+joindre
+joncher
+jongler
+joueur
+jouissif
+journal
+jovial
+joyau
+joyeux
+jubiler
+jugement
+junior
+jupon
+juriste
+justice
+juteux
+juvénile
+kayak
+kimono
+kiosque
+label
+labial
+labourer
+lacérer
+lactose
+lagune
+laine
+laisser
+laitier
+lambeau
+lamelle
+lampe
+lanceur
+langage
+lanterne
+lapin
+largeur
+larme
+laurier
+lavabo
+lavoir
+lecture
+légal
+léger
+légume
+lessive
+lettre
+levier
+lexique
+lézard
+liasse
+libérer
+libre
+licence
+licorne
+liège
+lièvre
+ligature
+ligoter
+ligue
+limer
+limite
+limonade
+limpide
+linéaire
+lingot
+lionceau
+liquide
+lisière
+lister
+lithium
+litige
+littoral
+livreur
+logique
+lointain
+loisir
+lombric
+loterie
+louer
+lourd
+loutre
+louve
+loyal
+lubie
+lucide
+lucratif
+lueur
+lugubre
+luisant
+lumière
+lunaire
+lundi
+luron
+lutter
+luxueux
+machine
+magasin
+magenta
+magique
+maigre
+maillon
+maintien
+mairie
+maison
+majorer
+malaxer
+maléfice
+malheur
+malice
+mallette
+mammouth
+mandater
+maniable
+manquant
+manteau
+manuel
+marathon
+marbre
+marchand
+mardi
+maritime
+marqueur
+marron
+marteler
+mascotte
+massif
+matériel
+matière
+matraque
+maudire
+maussade
+mauve
+maximal
+méchant
+méconnu
+médaille
+médecin
+méditer
+méduse
+meilleur
+mélange
+mélodie
+membre
+mémoire
+menacer
+mener
+menhir
+mensonge
+mentor
+mercredi
+mérite
+merle
+messager
+mesure
+métal
+météore
+méthode
+métier
+meuble
+miauler
+microbe
+miette
+mignon
+migrer
+milieu
+million
+mimique
+mince
+minéral
+minimal
+minorer
+minute
+miracle
+miroiter
+missile
+mixte
+mobile
+moderne
+moelleux
+mondial
+moniteur
+monnaie
+monotone
+monstre
+montagne
+monument
+moqueur
+morceau
+morsure
+mortier
+moteur
+motif
+mouche
+moufle
+moulin
+mousson
+mouton
+mouvant
+multiple
+munition
+muraille
+murène
+murmure
+muscle
+muséum
+musicien
+mutation
+muter
+mutuel
+myriade
+myrtille
+mystère
+mythique
+nageur
+nappe
+narquois
+narrer
+natation
+nation
+nature
+naufrage
+nautique
+navire
+nébuleux
+nectar
+néfaste
+négation
+négliger
+négocier
+neige
+nerveux
+nettoyer
+neurone
+neutron
+neveu
+niche
+nickel
+nitrate
+niveau
+noble
+nocif
+nocturne
+noirceur
+noisette
+nomade
+nombreux
+nommer
+normatif
+notable
+notifier
+notoire
+nourrir
+nouveau
+novateur
+novembre
+novice
+nuage
+nuancer
+nuire
+nuisible
+numéro
+nuptial
+nuque
+nutritif
+obéir
+objectif
+obliger
+obscur
+observer
+obstacle
+obtenir
+obturer
+occasion
+occuper
+océan
+octobre
+octroyer
+octupler
+oculaire
+odeur
+odorant
+offenser
+officier
+offrir
+ogive
+oiseau
+oisillon
+olfactif
+olivier
+ombrage
+omettre
+onctueux
+onduler
+onéreux
+onirique
+opale
+opaque
+opérer
+opinion
+opportun
+opprimer
+opter
+optique
+orageux
+orange
+orbite
+ordonner
+oreille
+organe
+orgueil
+orifice
+ornement
+orque
+ortie
+osciller
+osmose
+ossature
+otarie
+ouragan
+ourson
+outil
+outrager
+ouvrage
+ovation
+oxyde
+oxygène
+ozone
+paisible
+palace
+palmarès
+palourde
+palper
+panache
+panda
+pangolin
+paniquer
+panneau
+panorama
+pantalon
+papaye
+papier
+papoter
+papyrus
+paradoxe
+parcelle
+paresse
+parfumer
+parler
+parole
+parrain
+parsemer
+partager
+parure
+parvenir
+passion
+pastèque
+paternel
+patience
+patron
+pavillon
+pavoiser
+payer
+paysage
+peigne
+peintre
+pelage
+pélican
+pelle
+pelouse
+peluche
+pendule
+pénétrer
+pénible
+pensif
+pénurie
+pépite
+péplum
+perdrix
+perforer
+période
+permuter
+perplexe
+persil
+perte
+peser
+pétale
+petit
+pétrir
+peuple
+pharaon
+phobie
+phoque
+photon
+phrase
+physique
+piano
+pictural
+pièce
+pierre
+pieuvre
+pilote
+pinceau
+pipette
+piquer
+pirogue
+piscine
+piston
+pivoter
+pixel
+pizza
+placard
+plafond
+plaisir
+planer
+plaque
+plastron
+plateau
+pleurer
+plexus
+pliage
+plomb
+plonger
+pluie
+plumage
+pochette
+poésie
+poète
+pointe
+poirier
+poisson
+poivre
+polaire
+policier
+pollen
+polygone
+pommade
+pompier
+ponctuel
+pondérer
+poney
+portique
+position
+posséder
+posture
+potager
+poteau
+potion
+pouce
+poulain
+poumon
+pourpre
+poussin
+pouvoir
+prairie
+pratique
+précieux
+prédire
+préfixe
+prélude
+prénom
+présence
+prétexte
+prévoir
+primitif
+prince
+prison
+priver
+problème
+procéder
+prodige
+profond
+progrès
+proie
+projeter
+prologue
+promener
+propre
+prospère
+protéger
+prouesse
+proverbe
+prudence
+pruneau
+psychose
+public
+puceron
+puiser
+pulpe
+pulsar
+punaise
+punitif
+pupitre
+purifier
+puzzle
+pyramide
+quasar
+querelle
+question
+quiétude
+quitter
+quotient
+racine
+raconter
+radieux
+ragondin
+raideur
+raisin
+ralentir
+rallonge
+ramasser
+rapide
+rasage
+ratisser
+ravager
+ravin
+rayonner
+réactif
+réagir
+réaliser
+réanimer
+recevoir
+réciter
+réclamer
+récolter
+recruter
+reculer
+recycler
+rédiger
+redouter
+refaire
+réflexe
+réformer
+refrain
+refuge
+régalien
+région
+réglage
+régulier
+réitérer
+rejeter
+rejouer
+relatif
+relever
+relief
+remarque
+remède
+remise
+remonter
+remplir
+remuer
+renard
+renfort
+renifler
+renoncer
+rentrer
+renvoi
+replier
+reporter
+reprise
+reptile
+requin
+réserve
+résineux
+résoudre
+respect
+rester
+résultat
+rétablir
+retenir
+réticule
+retomber
+retracer
+réunion
+réussir
+revanche
+revivre
+révolte
+révulsif
+richesse
+rideau
+rieur
+rigide
+rigoler
+rincer
+riposter
+risible
+risque
+rituel
+rival
+rivière
+rocheux
+romance
+rompre
+ronce
+rondin
+roseau
+rosier
+rotatif
+rotor
+rotule
+rouge
+rouille
+rouleau
+routine
+royaume
+ruban
+rubis
+ruche
+ruelle
+rugueux
+ruiner
+ruisseau
+ruser
+rustique
+rythme
+sabler
+saboter
+sabre
+sacoche
+safari
+sagesse
+saisir
+salade
+salive
+salon
+saluer
+samedi
+sanction
+sanglier
+sarcasme
+sardine
+saturer
+saugrenu
+saumon
+sauter
+sauvage
+savant
+savonner
+scalpel
+scandale
+scélérat
+scénario
+sceptre
+schéma
+science
+scinder
+score
+scrutin
+sculpter
+séance
+sécable
+sécher
+secouer
+sécréter
+sédatif
+séduire
+seigneur
+séjour
+sélectif
+semaine
+sembler
+semence
+séminal
+sénateur
+sensible
+sentence
+séparer
+séquence
+serein
+sergent
+sérieux
+serrure
+sérum
+service
+sésame
+sévir
+sevrage
+sextuple
+sidéral
+siècle
+siéger
+siffler
+sigle
+signal
+silence
+silicium
+simple
+sincère
+sinistre
+siphon
+sirop
+sismique
+situer
+skier
+social
+socle
+sodium
+soigneux
+soldat
+soleil
+solitude
+soluble
+sombre
+sommeil
+somnoler
+sonde
+songeur
+sonnette
+sonore
+sorcier
+sortir
+sosie
+sottise
+soucieux
+soudure
+souffle
+soulever
+soupape
+source
+soutirer
+souvenir
+spacieux
+spatial
+spécial
+sphère
+spiral
+stable
+station
+sternum
+stimulus
+stipuler
+strict
+studieux
+stupeur
+styliste
+sublime
+substrat
+subtil
+subvenir
+succès
+sucre
+suffixe
+suggérer
+suiveur
+sulfate
+superbe
+supplier
+surface
+suricate
+surmener
+surprise
+sursaut
+survie
+suspect
+syllabe
+symbole
+symétrie
+synapse
+syntaxe
+système
+tabac
+tablier
+tactile
+tailler
+talent
+talisman
+talonner
+tambour
+tamiser
+tangible
+tapis
+taquiner
+tarder
+tarif
+tartine
+tasse
+tatami
+tatouage
+taupe
+taureau
+taxer
+témoin
+temporel
+tenaille
+tendre
+teneur
+tenir
+tension
+terminer
+terne
+terrible
+tétine
+texte
+thème
+théorie
+thérapie
+thorax
+tibia
+tiède
+timide
+tirelire
+tiroir
+tissu
+titane
+titre
+tituber
+toboggan
+tolérant
+tomate
+tonique
+tonneau
+toponyme
+torche
+tordre
+tornade
+torpille
+torrent
+torse
+tortue
+totem
+toucher
+tournage
+tousser
+toxine
+traction
+trafic
+tragique
+trahir
+train
+trancher
+travail
+trèfle
+tremper
+trésor
+treuil
+triage
+tribunal
+tricoter
+trilogie
+triomphe
+tripler
+triturer
+trivial
+trombone
+tronc
+tropical
+troupeau
+tuile
+tulipe
+tumulte
+tunnel
+turbine
+tuteur
+tutoyer
+tuyau
+tympan
+typhon
+typique
+tyran
+ubuesque
+ultime
+ultrason
+unanime
+unifier
+union
+unique
+unitaire
+univers
+uranium
+urbain
+urticant
+usage
+usine
+usuel
+usure
+utile
+utopie
+vacarme
+vaccin
+vagabond
+vague
+vaillant
+vaincre
+vaisseau
+valable
+valise
+vallon
+valve
+vampire
+vanille
+vapeur
+varier
+vaseux
+vassal
+vaste
+vecteur
+vedette
+végétal
+véhicule
+veinard
+véloce
+vendredi
+vénérer
+venger
+venimeux
+ventouse
+verdure
+vérin
+vernir
+verrou
+verser
+vertu
+veston
+vétéran
+vétuste
+vexant
+vexer
+viaduc
+viande
+victoire
+vidange
+vidéo
+vignette
+vigueur
+vilain
+village
+vinaigre
+violon
+vipère
+virement
+virtuose
+virus
+visage
+viseur
+vision
+visqueux
+visuel
+vital
+vitesse
+viticole
+vitrine
+vivace
+vivipare
+vocation
+voguer
+voile
+voisin
+voiture
+volaille
+volcan
+voltiger
+volume
+vorace
+vortex
+voter
+vouloir
+voyage
+voyelle
+wagon
+xénon
+yacht
+zèbre
+zénith
+zeste
+zoologie \ No newline at end of file
diff --git a/frozen_deps/mnemonic/wordlist/italian.txt b/frozen_deps/mnemonic/wordlist/italian.txt
new file mode 100644
index 0000000..c47370f
--- /dev/null
+++ b/frozen_deps/mnemonic/wordlist/italian.txt
@@ -0,0 +1,2048 @@
+abaco
+abbaglio
+abbinato
+abete
+abisso
+abolire
+abrasivo
+abrogato
+accadere
+accenno
+accusato
+acetone
+achille
+acido
+acqua
+acre
+acrilico
+acrobata
+acuto
+adagio
+addebito
+addome
+adeguato
+aderire
+adipe
+adottare
+adulare
+affabile
+affetto
+affisso
+affranto
+aforisma
+afoso
+africano
+agave
+agente
+agevole
+aggancio
+agire
+agitare
+agonismo
+agricolo
+agrumeto
+aguzzo
+alabarda
+alato
+albatro
+alberato
+albo
+albume
+alce
+alcolico
+alettone
+alfa
+algebra
+aliante
+alibi
+alimento
+allagato
+allegro
+allievo
+allodola
+allusivo
+almeno
+alogeno
+alpaca
+alpestre
+altalena
+alterno
+alticcio
+altrove
+alunno
+alveolo
+alzare
+amalgama
+amanita
+amarena
+ambito
+ambrato
+ameba
+america
+ametista
+amico
+ammasso
+ammenda
+ammirare
+ammonito
+amore
+ampio
+ampliare
+amuleto
+anacardo
+anagrafe
+analista
+anarchia
+anatra
+anca
+ancella
+ancora
+andare
+andrea
+anello
+angelo
+angolare
+angusto
+anima
+annegare
+annidato
+anno
+annuncio
+anonimo
+anticipo
+anzi
+apatico
+apertura
+apode
+apparire
+appetito
+appoggio
+approdo
+appunto
+aprile
+arabica
+arachide
+aragosta
+araldica
+arancio
+aratura
+arazzo
+arbitro
+archivio
+ardito
+arenile
+argento
+argine
+arguto
+aria
+armonia
+arnese
+arredato
+arringa
+arrosto
+arsenico
+arso
+artefice
+arzillo
+asciutto
+ascolto
+asepsi
+asettico
+asfalto
+asino
+asola
+aspirato
+aspro
+assaggio
+asse
+assoluto
+assurdo
+asta
+astenuto
+astice
+astratto
+atavico
+ateismo
+atomico
+atono
+attesa
+attivare
+attorno
+attrito
+attuale
+ausilio
+austria
+autista
+autonomo
+autunno
+avanzato
+avere
+avvenire
+avviso
+avvolgere
+azione
+azoto
+azzimo
+azzurro
+babele
+baccano
+bacino
+baco
+badessa
+badilata
+bagnato
+baita
+balcone
+baldo
+balena
+ballata
+balzano
+bambino
+bandire
+baraonda
+barbaro
+barca
+baritono
+barlume
+barocco
+basilico
+basso
+batosta
+battuto
+baule
+bava
+bavosa
+becco
+beffa
+belgio
+belva
+benda
+benevole
+benigno
+benzina
+bere
+berlina
+beta
+bibita
+bici
+bidone
+bifido
+biga
+bilancia
+bimbo
+binocolo
+biologo
+bipede
+bipolare
+birbante
+birra
+biscotto
+bisesto
+bisnonno
+bisonte
+bisturi
+bizzarro
+blando
+blatta
+bollito
+bonifico
+bordo
+bosco
+botanico
+bottino
+bozzolo
+braccio
+bradipo
+brama
+branca
+bravura
+bretella
+brevetto
+brezza
+briglia
+brillante
+brindare
+broccolo
+brodo
+bronzina
+brullo
+bruno
+bubbone
+buca
+budino
+buffone
+buio
+bulbo
+buono
+burlone
+burrasca
+bussola
+busta
+cadetto
+caduco
+calamaro
+calcolo
+calesse
+calibro
+calmo
+caloria
+cambusa
+camerata
+camicia
+cammino
+camola
+campale
+canapa
+candela
+cane
+canino
+canotto
+cantina
+capace
+capello
+capitolo
+capogiro
+cappero
+capra
+capsula
+carapace
+carcassa
+cardo
+carisma
+carovana
+carretto
+cartolina
+casaccio
+cascata
+caserma
+caso
+cassone
+castello
+casuale
+catasta
+catena
+catrame
+cauto
+cavillo
+cedibile
+cedrata
+cefalo
+celebre
+cellulare
+cena
+cenone
+centesimo
+ceramica
+cercare
+certo
+cerume
+cervello
+cesoia
+cespo
+ceto
+chela
+chiaro
+chicca
+chiedere
+chimera
+china
+chirurgo
+chitarra
+ciao
+ciclismo
+cifrare
+cigno
+cilindro
+ciottolo
+circa
+cirrosi
+citrico
+cittadino
+ciuffo
+civetta
+civile
+classico
+clinica
+cloro
+cocco
+codardo
+codice
+coerente
+cognome
+collare
+colmato
+colore
+colposo
+coltivato
+colza
+coma
+cometa
+commando
+comodo
+computer
+comune
+conciso
+condurre
+conferma
+congelare
+coniuge
+connesso
+conoscere
+consumo
+continuo
+convegno
+coperto
+copione
+coppia
+copricapo
+corazza
+cordata
+coricato
+cornice
+corolla
+corpo
+corredo
+corsia
+cortese
+cosmico
+costante
+cottura
+covato
+cratere
+cravatta
+creato
+credere
+cremoso
+crescita
+creta
+criceto
+crinale
+crisi
+critico
+croce
+cronaca
+crostata
+cruciale
+crusca
+cucire
+cuculo
+cugino
+cullato
+cupola
+curatore
+cursore
+curvo
+cuscino
+custode
+dado
+daino
+dalmata
+damerino
+daniela
+dannoso
+danzare
+datato
+davanti
+davvero
+debutto
+decennio
+deciso
+declino
+decollo
+decreto
+dedicato
+definito
+deforme
+degno
+delegare
+delfino
+delirio
+delta
+demenza
+denotato
+dentro
+deposito
+derapata
+derivare
+deroga
+descritto
+deserto
+desiderio
+desumere
+detersivo
+devoto
+diametro
+dicembre
+diedro
+difeso
+diffuso
+digerire
+digitale
+diluvio
+dinamico
+dinnanzi
+dipinto
+diploma
+dipolo
+diradare
+dire
+dirotto
+dirupo
+disagio
+discreto
+disfare
+disgelo
+disposto
+distanza
+disumano
+dito
+divano
+divelto
+dividere
+divorato
+doblone
+docente
+doganale
+dogma
+dolce
+domato
+domenica
+dominare
+dondolo
+dono
+dormire
+dote
+dottore
+dovuto
+dozzina
+drago
+druido
+dubbio
+dubitare
+ducale
+duna
+duomo
+duplice
+duraturo
+ebano
+eccesso
+ecco
+eclissi
+economia
+edera
+edicola
+edile
+editoria
+educare
+egemonia
+egli
+egoismo
+egregio
+elaborato
+elargire
+elegante
+elencato
+eletto
+elevare
+elfico
+elica
+elmo
+elsa
+eluso
+emanato
+emblema
+emesso
+emiro
+emotivo
+emozione
+empirico
+emulo
+endemico
+enduro
+energia
+enfasi
+enoteca
+entrare
+enzima
+epatite
+epilogo
+episodio
+epocale
+eppure
+equatore
+erario
+erba
+erboso
+erede
+eremita
+erigere
+ermetico
+eroe
+erosivo
+errante
+esagono
+esame
+esanime
+esaudire
+esca
+esempio
+esercito
+esibito
+esigente
+esistere
+esito
+esofago
+esortato
+esoso
+espanso
+espresso
+essenza
+esso
+esteso
+estimare
+estonia
+estroso
+esultare
+etilico
+etnico
+etrusco
+etto
+euclideo
+europa
+evaso
+evidenza
+evitato
+evoluto
+evviva
+fabbrica
+faccenda
+fachiro
+falco
+famiglia
+fanale
+fanfara
+fango
+fantasma
+fare
+farfalla
+farinoso
+farmaco
+fascia
+fastoso
+fasullo
+faticare
+fato
+favoloso
+febbre
+fecola
+fede
+fegato
+felpa
+feltro
+femmina
+fendere
+fenomeno
+fermento
+ferro
+fertile
+fessura
+festivo
+fetta
+feudo
+fiaba
+fiducia
+fifa
+figurato
+filo
+finanza
+finestra
+finire
+fiore
+fiscale
+fisico
+fiume
+flacone
+flamenco
+flebo
+flemma
+florido
+fluente
+fluoro
+fobico
+focaccia
+focoso
+foderato
+foglio
+folata
+folclore
+folgore
+fondente
+fonetico
+fonia
+fontana
+forbito
+forchetta
+foresta
+formica
+fornaio
+foro
+fortezza
+forzare
+fosfato
+fosso
+fracasso
+frana
+frassino
+fratello
+freccetta
+frenata
+fresco
+frigo
+frollino
+fronde
+frugale
+frutta
+fucilata
+fucsia
+fuggente
+fulmine
+fulvo
+fumante
+fumetto
+fumoso
+fune
+funzione
+fuoco
+furbo
+furgone
+furore
+fuso
+futile
+gabbiano
+gaffe
+galateo
+gallina
+galoppo
+gambero
+gamma
+garanzia
+garbo
+garofano
+garzone
+gasdotto
+gasolio
+gastrico
+gatto
+gaudio
+gazebo
+gazzella
+geco
+gelatina
+gelso
+gemello
+gemmato
+gene
+genitore
+gennaio
+genotipo
+gergo
+ghepardo
+ghiaccio
+ghisa
+giallo
+gilda
+ginepro
+giocare
+gioiello
+giorno
+giove
+girato
+girone
+gittata
+giudizio
+giurato
+giusto
+globulo
+glutine
+gnomo
+gobba
+golf
+gomito
+gommone
+gonfio
+gonna
+governo
+gracile
+grado
+grafico
+grammo
+grande
+grattare
+gravoso
+grazia
+greca
+gregge
+grifone
+grigio
+grinza
+grotta
+gruppo
+guadagno
+guaio
+guanto
+guardare
+gufo
+guidare
+ibernato
+icona
+identico
+idillio
+idolo
+idra
+idrico
+idrogeno
+igiene
+ignaro
+ignorato
+ilare
+illeso
+illogico
+illudere
+imballo
+imbevuto
+imbocco
+imbuto
+immane
+immerso
+immolato
+impacco
+impeto
+impiego
+importo
+impronta
+inalare
+inarcare
+inattivo
+incanto
+incendio
+inchino
+incisivo
+incluso
+incontro
+incrocio
+incubo
+indagine
+india
+indole
+inedito
+infatti
+infilare
+inflitto
+ingaggio
+ingegno
+inglese
+ingordo
+ingrosso
+innesco
+inodore
+inoltrare
+inondato
+insano
+insetto
+insieme
+insonnia
+insulina
+intasato
+intero
+intonaco
+intuito
+inumidire
+invalido
+invece
+invito
+iperbole
+ipnotico
+ipotesi
+ippica
+iride
+irlanda
+ironico
+irrigato
+irrorare
+isolato
+isotopo
+isterico
+istituto
+istrice
+italia
+iterare
+labbro
+labirinto
+lacca
+lacerato
+lacrima
+lacuna
+laddove
+lago
+lampo
+lancetta
+lanterna
+lardoso
+larga
+laringe
+lastra
+latenza
+latino
+lattuga
+lavagna
+lavoro
+legale
+leggero
+lembo
+lentezza
+lenza
+leone
+lepre
+lesivo
+lessato
+lesto
+letterale
+leva
+levigato
+libero
+lido
+lievito
+lilla
+limatura
+limitare
+limpido
+lineare
+lingua
+liquido
+lira
+lirica
+lisca
+lite
+litigio
+livrea
+locanda
+lode
+logica
+lombare
+londra
+longevo
+loquace
+lorenzo
+loto
+lotteria
+luce
+lucidato
+lumaca
+luminoso
+lungo
+lupo
+luppolo
+lusinga
+lusso
+lutto
+macabro
+macchina
+macero
+macinato
+madama
+magico
+maglia
+magnete
+magro
+maiolica
+malafede
+malgrado
+malinteso
+malsano
+malto
+malumore
+mana
+mancia
+mandorla
+mangiare
+manifesto
+mannaro
+manovra
+mansarda
+mantide
+manubrio
+mappa
+maratona
+marcire
+maretta
+marmo
+marsupio
+maschera
+massaia
+mastino
+materasso
+matricola
+mattone
+maturo
+mazurca
+meandro
+meccanico
+mecenate
+medesimo
+meditare
+mega
+melassa
+melis
+melodia
+meninge
+meno
+mensola
+mercurio
+merenda
+merlo
+meschino
+mese
+messere
+mestolo
+metallo
+metodo
+mettere
+miagolare
+mica
+micelio
+michele
+microbo
+midollo
+miele
+migliore
+milano
+milite
+mimosa
+minerale
+mini
+minore
+mirino
+mirtillo
+miscela
+missiva
+misto
+misurare
+mitezza
+mitigare
+mitra
+mittente
+mnemonico
+modello
+modifica
+modulo
+mogano
+mogio
+mole
+molosso
+monastero
+monco
+mondina
+monetario
+monile
+monotono
+monsone
+montato
+monviso
+mora
+mordere
+morsicato
+mostro
+motivato
+motosega
+motto
+movenza
+movimento
+mozzo
+mucca
+mucosa
+muffa
+mughetto
+mugnaio
+mulatto
+mulinello
+multiplo
+mummia
+munto
+muovere
+murale
+musa
+muscolo
+musica
+mutevole
+muto
+nababbo
+nafta
+nanometro
+narciso
+narice
+narrato
+nascere
+nastrare
+naturale
+nautica
+naviglio
+nebulosa
+necrosi
+negativo
+negozio
+nemmeno
+neofita
+neretto
+nervo
+nessuno
+nettuno
+neutrale
+neve
+nevrotico
+nicchia
+ninfa
+nitido
+nobile
+nocivo
+nodo
+nome
+nomina
+nordico
+normale
+norvegese
+nostrano
+notare
+notizia
+notturno
+novella
+nucleo
+nulla
+numero
+nuovo
+nutrire
+nuvola
+nuziale
+oasi
+obbedire
+obbligo
+obelisco
+oblio
+obolo
+obsoleto
+occasione
+occhio
+occidente
+occorrere
+occultare
+ocra
+oculato
+odierno
+odorare
+offerta
+offrire
+offuscato
+oggetto
+oggi
+ognuno
+olandese
+olfatto
+oliato
+oliva
+ologramma
+oltre
+omaggio
+ombelico
+ombra
+omega
+omissione
+ondoso
+onere
+onice
+onnivoro
+onorevole
+onta
+operato
+opinione
+opposto
+oracolo
+orafo
+ordine
+orecchino
+orefice
+orfano
+organico
+origine
+orizzonte
+orma
+ormeggio
+ornativo
+orologio
+orrendo
+orribile
+ortensia
+ortica
+orzata
+orzo
+osare
+oscurare
+osmosi
+ospedale
+ospite
+ossa
+ossidare
+ostacolo
+oste
+otite
+otre
+ottagono
+ottimo
+ottobre
+ovale
+ovest
+ovino
+oviparo
+ovocito
+ovunque
+ovviare
+ozio
+pacchetto
+pace
+pacifico
+padella
+padrone
+paese
+paga
+pagina
+palazzina
+palesare
+pallido
+palo
+palude
+pandoro
+pannello
+paolo
+paonazzo
+paprica
+parabola
+parcella
+parere
+pargolo
+pari
+parlato
+parola
+partire
+parvenza
+parziale
+passivo
+pasticca
+patacca
+patologia
+pattume
+pavone
+peccato
+pedalare
+pedonale
+peggio
+peloso
+penare
+pendice
+penisola
+pennuto
+penombra
+pensare
+pentola
+pepe
+pepita
+perbene
+percorso
+perdonato
+perforare
+pergamena
+periodo
+permesso
+perno
+perplesso
+persuaso
+pertugio
+pervaso
+pesatore
+pesista
+peso
+pestifero
+petalo
+pettine
+petulante
+pezzo
+piacere
+pianta
+piattino
+piccino
+picozza
+piega
+pietra
+piffero
+pigiama
+pigolio
+pigro
+pila
+pilifero
+pillola
+pilota
+pimpante
+pineta
+pinna
+pinolo
+pioggia
+piombo
+piramide
+piretico
+pirite
+pirolisi
+pitone
+pizzico
+placebo
+planare
+plasma
+platano
+plenario
+pochezza
+poderoso
+podismo
+poesia
+poggiare
+polenta
+poligono
+pollice
+polmonite
+polpetta
+polso
+poltrona
+polvere
+pomice
+pomodoro
+ponte
+popoloso
+porfido
+poroso
+porpora
+porre
+portata
+posa
+positivo
+possesso
+postulato
+potassio
+potere
+pranzo
+prassi
+pratica
+precluso
+predica
+prefisso
+pregiato
+prelievo
+premere
+prenotare
+preparato
+presenza
+pretesto
+prevalso
+prima
+principe
+privato
+problema
+procura
+produrre
+profumo
+progetto
+prolunga
+promessa
+pronome
+proposta
+proroga
+proteso
+prova
+prudente
+prugna
+prurito
+psiche
+pubblico
+pudica
+pugilato
+pugno
+pulce
+pulito
+pulsante
+puntare
+pupazzo
+pupilla
+puro
+quadro
+qualcosa
+quasi
+querela
+quota
+raccolto
+raddoppio
+radicale
+radunato
+raffica
+ragazzo
+ragione
+ragno
+ramarro
+ramingo
+ramo
+randagio
+rantolare
+rapato
+rapina
+rappreso
+rasatura
+raschiato
+rasente
+rassegna
+rastrello
+rata
+ravveduto
+reale
+recepire
+recinto
+recluta
+recondito
+recupero
+reddito
+redimere
+regalato
+registro
+regola
+regresso
+relazione
+remare
+remoto
+renna
+replica
+reprimere
+reputare
+resa
+residente
+responso
+restauro
+rete
+retina
+retorica
+rettifica
+revocato
+riassunto
+ribadire
+ribelle
+ribrezzo
+ricarica
+ricco
+ricevere
+riciclato
+ricordo
+ricreduto
+ridicolo
+ridurre
+rifasare
+riflesso
+riforma
+rifugio
+rigare
+rigettato
+righello
+rilassato
+rilevato
+rimanere
+rimbalzo
+rimedio
+rimorchio
+rinascita
+rincaro
+rinforzo
+rinnovo
+rinomato
+rinsavito
+rintocco
+rinuncia
+rinvenire
+riparato
+ripetuto
+ripieno
+riportare
+ripresa
+ripulire
+risata
+rischio
+riserva
+risibile
+riso
+rispetto
+ristoro
+risultato
+risvolto
+ritardo
+ritegno
+ritmico
+ritrovo
+riunione
+riva
+riverso
+rivincita
+rivolto
+rizoma
+roba
+robotico
+robusto
+roccia
+roco
+rodaggio
+rodere
+roditore
+rogito
+rollio
+romantico
+rompere
+ronzio
+rosolare
+rospo
+rotante
+rotondo
+rotula
+rovescio
+rubizzo
+rubrica
+ruga
+rullino
+rumine
+rumoroso
+ruolo
+rupe
+russare
+rustico
+sabato
+sabbiare
+sabotato
+sagoma
+salasso
+saldatura
+salgemma
+salivare
+salmone
+salone
+saltare
+saluto
+salvo
+sapere
+sapido
+saporito
+saraceno
+sarcasmo
+sarto
+sassoso
+satellite
+satira
+satollo
+saturno
+savana
+savio
+saziato
+sbadiglio
+sbalzo
+sbancato
+sbarra
+sbattere
+sbavare
+sbendare
+sbirciare
+sbloccato
+sbocciato
+sbrinare
+sbruffone
+sbuffare
+scabroso
+scadenza
+scala
+scambiare
+scandalo
+scapola
+scarso
+scatenare
+scavato
+scelto
+scenico
+scettro
+scheda
+schiena
+sciarpa
+scienza
+scindere
+scippo
+sciroppo
+scivolo
+sclerare
+scodella
+scolpito
+scomparto
+sconforto
+scoprire
+scorta
+scossone
+scozzese
+scriba
+scrollare
+scrutinio
+scuderia
+scultore
+scuola
+scuro
+scusare
+sdebitare
+sdoganare
+seccatura
+secondo
+sedano
+seggiola
+segnalato
+segregato
+seguito
+selciato
+selettivo
+sella
+selvaggio
+semaforo
+sembrare
+seme
+seminato
+sempre
+senso
+sentire
+sepolto
+sequenza
+serata
+serbato
+sereno
+serio
+serpente
+serraglio
+servire
+sestina
+setola
+settimana
+sfacelo
+sfaldare
+sfamato
+sfarzoso
+sfaticato
+sfera
+sfida
+sfilato
+sfinge
+sfocato
+sfoderare
+sfogo
+sfoltire
+sforzato
+sfratto
+sfruttato
+sfuggito
+sfumare
+sfuso
+sgabello
+sgarbato
+sgonfiare
+sgorbio
+sgrassato
+sguardo
+sibilo
+siccome
+sierra
+sigla
+signore
+silenzio
+sillaba
+simbolo
+simpatico
+simulato
+sinfonia
+singolo
+sinistro
+sino
+sintesi
+sinusoide
+sipario
+sisma
+sistole
+situato
+slitta
+slogatura
+sloveno
+smarrito
+smemorato
+smentito
+smeraldo
+smilzo
+smontare
+smottato
+smussato
+snellire
+snervato
+snodo
+sobbalzo
+sobrio
+soccorso
+sociale
+sodale
+soffitto
+sogno
+soldato
+solenne
+solido
+sollazzo
+solo
+solubile
+solvente
+somatico
+somma
+sonda
+sonetto
+sonnifero
+sopire
+soppeso
+sopra
+sorgere
+sorpasso
+sorriso
+sorso
+sorteggio
+sorvolato
+sospiro
+sosta
+sottile
+spada
+spalla
+spargere
+spatola
+spavento
+spazzola
+specie
+spedire
+spegnere
+spelatura
+speranza
+spessore
+spettrale
+spezzato
+spia
+spigoloso
+spillato
+spinoso
+spirale
+splendido
+sportivo
+sposo
+spranga
+sprecare
+spronato
+spruzzo
+spuntino
+squillo
+sradicare
+srotolato
+stabile
+stacco
+staffa
+stagnare
+stampato
+stantio
+starnuto
+stasera
+statuto
+stelo
+steppa
+sterzo
+stiletto
+stima
+stirpe
+stivale
+stizzoso
+stonato
+storico
+strappo
+stregato
+stridulo
+strozzare
+strutto
+stuccare
+stufo
+stupendo
+subentro
+succoso
+sudore
+suggerito
+sugo
+sultano
+suonare
+superbo
+supporto
+surgelato
+surrogato
+sussurro
+sutura
+svagare
+svedese
+sveglio
+svelare
+svenuto
+svezia
+sviluppo
+svista
+svizzera
+svolta
+svuotare
+tabacco
+tabulato
+tacciare
+taciturno
+tale
+talismano
+tampone
+tannino
+tara
+tardivo
+targato
+tariffa
+tarpare
+tartaruga
+tasto
+tattico
+taverna
+tavolata
+tazza
+teca
+tecnico
+telefono
+temerario
+tempo
+temuto
+tendone
+tenero
+tensione
+tentacolo
+teorema
+terme
+terrazzo
+terzetto
+tesi
+tesserato
+testato
+tetro
+tettoia
+tifare
+tigella
+timbro
+tinto
+tipico
+tipografo
+tiraggio
+tiro
+titanio
+titolo
+titubante
+tizio
+tizzone
+toccare
+tollerare
+tolto
+tombola
+tomo
+tonfo
+tonsilla
+topazio
+topologia
+toppa
+torba
+tornare
+torrone
+tortora
+toscano
+tossire
+tostatura
+totano
+trabocco
+trachea
+trafila
+tragedia
+tralcio
+tramonto
+transito
+trapano
+trarre
+trasloco
+trattato
+trave
+treccia
+tremolio
+trespolo
+tributo
+tricheco
+trifoglio
+trillo
+trincea
+trio
+tristezza
+triturato
+trivella
+tromba
+trono
+troppo
+trottola
+trovare
+truccato
+tubatura
+tuffato
+tulipano
+tumulto
+tunisia
+turbare
+turchino
+tuta
+tutela
+ubicato
+uccello
+uccisore
+udire
+uditivo
+uffa
+ufficio
+uguale
+ulisse
+ultimato
+umano
+umile
+umorismo
+uncinetto
+ungere
+ungherese
+unicorno
+unificato
+unisono
+unitario
+unte
+uovo
+upupa
+uragano
+urgenza
+urlo
+usanza
+usato
+uscito
+usignolo
+usuraio
+utensile
+utilizzo
+utopia
+vacante
+vaccinato
+vagabondo
+vagliato
+valanga
+valgo
+valico
+valletta
+valoroso
+valutare
+valvola
+vampata
+vangare
+vanitoso
+vano
+vantaggio
+vanvera
+vapore
+varano
+varcato
+variante
+vasca
+vedetta
+vedova
+veduto
+vegetale
+veicolo
+velcro
+velina
+velluto
+veloce
+venato
+vendemmia
+vento
+verace
+verbale
+vergogna
+verifica
+vero
+verruca
+verticale
+vescica
+vessillo
+vestale
+veterano
+vetrina
+vetusto
+viandante
+vibrante
+vicenda
+vichingo
+vicinanza
+vidimare
+vigilia
+vigneto
+vigore
+vile
+villano
+vimini
+vincitore
+viola
+vipera
+virgola
+virologo
+virulento
+viscoso
+visione
+vispo
+vissuto
+visura
+vita
+vitello
+vittima
+vivanda
+vivido
+viziare
+voce
+voga
+volatile
+volere
+volpe
+voragine
+vulcano
+zampogna
+zanna
+zappato
+zattera
+zavorra
+zefiro
+zelante
+zelo
+zenzero
+zerbino
+zibetto
+zinco
+zircone
+zitto
+zolla
+zotico
+zucchero
+zufolo
+zulu
+zuppa
diff --git a/frozen_deps/mnemonic/wordlist/japanese.txt b/frozen_deps/mnemonic/wordlist/japanese.txt
new file mode 100644
index 0000000..fb8501a
--- /dev/null
+++ b/frozen_deps/mnemonic/wordlist/japanese.txt
@@ -0,0 +1,2048 @@
+あいこくしん
+あいさつ
+あいだ
+あおぞら
+あかちゃん
+あきる
+あけがた
+あける
+あこがれる
+あさい
+あさひ
+あしあと
+あじわう
+あずかる
+あずき
+あそぶ
+あたえる
+あたためる
+あたりまえ
+あたる
+あつい
+あつかう
+あっしゅく
+あつまり
+あつめる
+あてな
+あてはまる
+あひる
+あぶら
+あぶる
+あふれる
+あまい
+あまど
+あまやかす
+あまり
+あみもの
+あめりか
+あやまる
+あゆむ
+あらいぐま
+あらし
+あらすじ
+あらためる
+あらゆる
+あらわす
+ありがとう
+あわせる
+あわてる
+あんい
+あんがい
+あんこ
+あんぜん
+あんてい
+あんない
+あんまり
+いいだす
+いおん
+いがい
+いがく
+いきおい
+いきなり
+いきもの
+いきる
+いくじ
+いくぶん
+いけばな
+いけん
+いこう
+いこく
+いこつ
+いさましい
+いさん
+いしき
+いじゅう
+いじょう
+いじわる
+いずみ
+いずれ
+いせい
+いせえび
+いせかい
+いせき
+いぜん
+いそうろう
+いそがしい
+いだい
+いだく
+いたずら
+いたみ
+いたりあ
+いちおう
+いちじ
+いちど
+いちば
+いちぶ
+いちりゅう
+いつか
+いっしゅん
+いっせい
+いっそう
+いったん
+いっち
+いってい
+いっぽう
+いてざ
+いてん
+いどう
+いとこ
+いない
+いなか
+いねむり
+いのち
+いのる
+いはつ
+いばる
+いはん
+いびき
+いひん
+いふく
+いへん
+いほう
+いみん
+いもうと
+いもたれ
+いもり
+いやがる
+いやす
+いよかん
+いよく
+いらい
+いらすと
+いりぐち
+いりょう
+いれい
+いれもの
+いれる
+いろえんぴつ
+いわい
+いわう
+いわかん
+いわば
+いわゆる
+いんげんまめ
+いんさつ
+いんしょう
+いんよう
+うえき
+うえる
+うおざ
+うがい
+うかぶ
+うかべる
+うきわ
+うくらいな
+うくれれ
+うけたまわる
+うけつけ
+うけとる
+うけもつ
+うける
+うごかす
+うごく
+うこん
+うさぎ
+うしなう
+うしろがみ
+うすい
+うすぎ
+うすぐらい
+うすめる
+うせつ
+うちあわせ
+うちがわ
+うちき
+うちゅう
+うっかり
+うつくしい
+うったえる
+うつる
+うどん
+うなぎ
+うなじ
+うなずく
+うなる
+うねる
+うのう
+うぶげ
+うぶごえ
+うまれる
+うめる
+うもう
+うやまう
+うよく
+うらがえす
+うらぐち
+うらない
+うりあげ
+うりきれ
+うるさい
+うれしい
+うれゆき
+うれる
+うろこ
+うわき
+うわさ
+うんこう
+うんちん
+うんてん
+うんどう
+えいえん
+えいが
+えいきょう
+えいご
+えいせい
+えいぶん
+えいよう
+えいわ
+えおり
+えがお
+えがく
+えきたい
+えくせる
+えしゃく
+えすて
+えつらん
+えのぐ
+えほうまき
+えほん
+えまき
+えもじ
+えもの
+えらい
+えらぶ
+えりあ
+えんえん
+えんかい
+えんぎ
+えんげき
+えんしゅう
+えんぜつ
+えんそく
+えんちょう
+えんとつ
+おいかける
+おいこす
+おいしい
+おいつく
+おうえん
+おうさま
+おうじ
+おうせつ
+おうたい
+おうふく
+おうべい
+おうよう
+おえる
+おおい
+おおう
+おおどおり
+おおや
+おおよそ
+おかえり
+おかず
+おがむ
+おかわり
+おぎなう
+おきる
+おくさま
+おくじょう
+おくりがな
+おくる
+おくれる
+おこす
+おこなう
+おこる
+おさえる
+おさない
+おさめる
+おしいれ
+おしえる
+おじぎ
+おじさん
+おしゃれ
+おそらく
+おそわる
+おたがい
+おたく
+おだやか
+おちつく
+おっと
+おつり
+おでかけ
+おとしもの
+おとなしい
+おどり
+おどろかす
+おばさん
+おまいり
+おめでとう
+おもいで
+おもう
+おもたい
+おもちゃ
+おやつ
+おやゆび
+およぼす
+おらんだ
+おろす
+おんがく
+おんけい
+おんしゃ
+おんせん
+おんだん
+おんちゅう
+おんどけい
+かあつ
+かいが
+がいき
+がいけん
+がいこう
+かいさつ
+かいしゃ
+かいすいよく
+かいぜん
+かいぞうど
+かいつう
+かいてん
+かいとう
+かいふく
+がいへき
+かいほう
+かいよう
+がいらい
+かいわ
+かえる
+かおり
+かかえる
+かがく
+かがし
+かがみ
+かくご
+かくとく
+かざる
+がぞう
+かたい
+かたち
+がちょう
+がっきゅう
+がっこう
+がっさん
+がっしょう
+かなざわし
+かのう
+がはく
+かぶか
+かほう
+かほご
+かまう
+かまぼこ
+かめれおん
+かゆい
+かようび
+からい
+かるい
+かろう
+かわく
+かわら
+がんか
+かんけい
+かんこう
+かんしゃ
+かんそう
+かんたん
+かんち
+がんばる
+きあい
+きあつ
+きいろ
+ぎいん
+きうい
+きうん
+きえる
+きおう
+きおく
+きおち
+きおん
+きかい
+きかく
+きかんしゃ
+ききて
+きくばり
+きくらげ
+きけんせい
+きこう
+きこえる
+きこく
+きさい
+きさく
+きさま
+きさらぎ
+ぎじかがく
+ぎしき
+ぎじたいけん
+ぎじにってい
+ぎじゅつしゃ
+きすう
+きせい
+きせき
+きせつ
+きそう
+きぞく
+きぞん
+きたえる
+きちょう
+きつえん
+ぎっちり
+きつつき
+きつね
+きてい
+きどう
+きどく
+きない
+きなが
+きなこ
+きぬごし
+きねん
+きのう
+きのした
+きはく
+きびしい
+きひん
+きふく
+きぶん
+きぼう
+きほん
+きまる
+きみつ
+きむずかしい
+きめる
+きもだめし
+きもち
+きもの
+きゃく
+きやく
+ぎゅうにく
+きよう
+きょうりゅう
+きらい
+きらく
+きりん
+きれい
+きれつ
+きろく
+ぎろん
+きわめる
+ぎんいろ
+きんかくじ
+きんじょ
+きんようび
+ぐあい
+くいず
+くうかん
+くうき
+くうぐん
+くうこう
+ぐうせい
+くうそう
+ぐうたら
+くうふく
+くうぼ
+くかん
+くきょう
+くげん
+ぐこう
+くさい
+くさき
+くさばな
+くさる
+くしゃみ
+くしょう
+くすのき
+くすりゆび
+くせげ
+くせん
+ぐたいてき
+くださる
+くたびれる
+くちこみ
+くちさき
+くつした
+ぐっすり
+くつろぐ
+くとうてん
+くどく
+くなん
+くねくね
+くのう
+くふう
+くみあわせ
+くみたてる
+くめる
+くやくしょ
+くらす
+くらべる
+くるま
+くれる
+くろう
+くわしい
+ぐんかん
+ぐんしょく
+ぐんたい
+ぐんて
+けあな
+けいかく
+けいけん
+けいこ
+けいさつ
+げいじゅつ
+けいたい
+げいのうじん
+けいれき
+けいろ
+けおとす
+けおりもの
+げきか
+げきげん
+げきだん
+げきちん
+げきとつ
+げきは
+げきやく
+げこう
+げこくじょう
+げざい
+けさき
+げざん
+けしき
+けしごむ
+けしょう
+げすと
+けたば
+けちゃっぷ
+けちらす
+けつあつ
+けつい
+けつえき
+けっこん
+けつじょ
+けっせき
+けってい
+けつまつ
+げつようび
+げつれい
+けつろん
+げどく
+けとばす
+けとる
+けなげ
+けなす
+けなみ
+けぬき
+げねつ
+けねん
+けはい
+げひん
+けぶかい
+げぼく
+けまり
+けみかる
+けむし
+けむり
+けもの
+けらい
+けろけろ
+けわしい
+けんい
+けんえつ
+けんお
+けんか
+げんき
+けんげん
+けんこう
+けんさく
+けんしゅう
+けんすう
+げんそう
+けんちく
+けんてい
+けんとう
+けんない
+けんにん
+げんぶつ
+けんま
+けんみん
+けんめい
+けんらん
+けんり
+こあくま
+こいぬ
+こいびと
+ごうい
+こうえん
+こうおん
+こうかん
+ごうきゅう
+ごうけい
+こうこう
+こうさい
+こうじ
+こうすい
+ごうせい
+こうそく
+こうたい
+こうちゃ
+こうつう
+こうてい
+こうどう
+こうない
+こうはい
+ごうほう
+ごうまん
+こうもく
+こうりつ
+こえる
+こおり
+ごかい
+ごがつ
+ごかん
+こくご
+こくさい
+こくとう
+こくない
+こくはく
+こぐま
+こけい
+こける
+ここのか
+こころ
+こさめ
+こしつ
+こすう
+こせい
+こせき
+こぜん
+こそだて
+こたい
+こたえる
+こたつ
+こちょう
+こっか
+こつこつ
+こつばん
+こつぶ
+こてい
+こてん
+ことがら
+ことし
+ことば
+ことり
+こなごな
+こねこね
+このまま
+このみ
+このよ
+ごはん
+こひつじ
+こふう
+こふん
+こぼれる
+ごまあぶら
+こまかい
+ごますり
+こまつな
+こまる
+こむぎこ
+こもじ
+こもち
+こもの
+こもん
+こやく
+こやま
+こゆう
+こゆび
+こよい
+こよう
+こりる
+これくしょん
+ころっけ
+こわもて
+こわれる
+こんいん
+こんかい
+こんき
+こんしゅう
+こんすい
+こんだて
+こんとん
+こんなん
+こんびに
+こんぽん
+こんまけ
+こんや
+こんれい
+こんわく
+ざいえき
+さいかい
+さいきん
+ざいげん
+ざいこ
+さいしょ
+さいせい
+ざいたく
+ざいちゅう
+さいてき
+ざいりょう
+さうな
+さかいし
+さがす
+さかな
+さかみち
+さがる
+さぎょう
+さくし
+さくひん
+さくら
+さこく
+さこつ
+さずかる
+ざせき
+さたん
+さつえい
+ざつおん
+ざっか
+ざつがく
+さっきょく
+ざっし
+さつじん
+ざっそう
+さつたば
+さつまいも
+さてい
+さといも
+さとう
+さとおや
+さとし
+さとる
+さのう
+さばく
+さびしい
+さべつ
+さほう
+さほど
+さます
+さみしい
+さみだれ
+さむけ
+さめる
+さやえんどう
+さゆう
+さよう
+さよく
+さらだ
+ざるそば
+さわやか
+さわる
+さんいん
+さんか
+さんきゃく
+さんこう
+さんさい
+ざんしょ
+さんすう
+さんせい
+さんそ
+さんち
+さんま
+さんみ
+さんらん
+しあい
+しあげ
+しあさって
+しあわせ
+しいく
+しいん
+しうち
+しえい
+しおけ
+しかい
+しかく
+じかん
+しごと
+しすう
+じだい
+したうけ
+したぎ
+したて
+したみ
+しちょう
+しちりん
+しっかり
+しつじ
+しつもん
+してい
+してき
+してつ
+じてん
+じどう
+しなぎれ
+しなもの
+しなん
+しねま
+しねん
+しのぐ
+しのぶ
+しはい
+しばかり
+しはつ
+しはらい
+しはん
+しひょう
+しふく
+じぶん
+しへい
+しほう
+しほん
+しまう
+しまる
+しみん
+しむける
+じむしょ
+しめい
+しめる
+しもん
+しゃいん
+しゃうん
+しゃおん
+じゃがいも
+しやくしょ
+しゃくほう
+しゃけん
+しゃこ
+しゃざい
+しゃしん
+しゃせん
+しゃそう
+しゃたい
+しゃちょう
+しゃっきん
+じゃま
+しゃりん
+しゃれい
+じゆう
+じゅうしょ
+しゅくはく
+じゅしん
+しゅっせき
+しゅみ
+しゅらば
+じゅんばん
+しょうかい
+しょくたく
+しょっけん
+しょどう
+しょもつ
+しらせる
+しらべる
+しんか
+しんこう
+じんじゃ
+しんせいじ
+しんちく
+しんりん
+すあげ
+すあし
+すあな
+ずあん
+すいえい
+すいか
+すいとう
+ずいぶん
+すいようび
+すうがく
+すうじつ
+すうせん
+すおどり
+すきま
+すくう
+すくない
+すける
+すごい
+すこし
+ずさん
+すずしい
+すすむ
+すすめる
+すっかり
+ずっしり
+ずっと
+すてき
+すてる
+すねる
+すのこ
+すはだ
+すばらしい
+ずひょう
+ずぶぬれ
+すぶり
+すふれ
+すべて
+すべる
+ずほう
+すぼん
+すまい
+すめし
+すもう
+すやき
+すらすら
+するめ
+すれちがう
+すろっと
+すわる
+すんぜん
+すんぽう
+せあぶら
+せいかつ
+せいげん
+せいじ
+せいよう
+せおう
+せかいかん
+せきにん
+せきむ
+せきゆ
+せきらんうん
+せけん
+せこう
+せすじ
+せたい
+せたけ
+せっかく
+せっきゃく
+ぜっく
+せっけん
+せっこつ
+せっさたくま
+せつぞく
+せつだん
+せつでん
+せっぱん
+せつび
+せつぶん
+せつめい
+せつりつ
+せなか
+せのび
+せはば
+せびろ
+せぼね
+せまい
+せまる
+せめる
+せもたれ
+せりふ
+ぜんあく
+せんい
+せんえい
+せんか
+せんきょ
+せんく
+せんげん
+ぜんご
+せんさい
+せんしゅ
+せんすい
+せんせい
+せんぞ
+せんたく
+せんちょう
+せんてい
+せんとう
+せんぬき
+せんねん
+せんぱい
+ぜんぶ
+ぜんぽう
+せんむ
+せんめんじょ
+せんもん
+せんやく
+せんゆう
+せんよう
+ぜんら
+ぜんりゃく
+せんれい
+せんろ
+そあく
+そいとげる
+そいね
+そうがんきょう
+そうき
+そうご
+そうしん
+そうだん
+そうなん
+そうび
+そうめん
+そうり
+そえもの
+そえん
+そがい
+そげき
+そこう
+そこそこ
+そざい
+そしな
+そせい
+そせん
+そそぐ
+そだてる
+そつう
+そつえん
+そっかん
+そつぎょう
+そっけつ
+そっこう
+そっせん
+そっと
+そとがわ
+そとづら
+そなえる
+そなた
+そふぼ
+そぼく
+そぼろ
+そまつ
+そまる
+そむく
+そむりえ
+そめる
+そもそも
+そよかぜ
+そらまめ
+そろう
+そんかい
+そんけい
+そんざい
+そんしつ
+そんぞく
+そんちょう
+ぞんび
+ぞんぶん
+そんみん
+たあい
+たいいん
+たいうん
+たいえき
+たいおう
+だいがく
+たいき
+たいぐう
+たいけん
+たいこ
+たいざい
+だいじょうぶ
+だいすき
+たいせつ
+たいそう
+だいたい
+たいちょう
+たいてい
+だいどころ
+たいない
+たいねつ
+たいのう
+たいはん
+だいひょう
+たいふう
+たいへん
+たいほ
+たいまつばな
+たいみんぐ
+たいむ
+たいめん
+たいやき
+たいよう
+たいら
+たいりょく
+たいる
+たいわん
+たうえ
+たえる
+たおす
+たおる
+たおれる
+たかい
+たかね
+たきび
+たくさん
+たこく
+たこやき
+たさい
+たしざん
+だじゃれ
+たすける
+たずさわる
+たそがれ
+たたかう
+たたく
+ただしい
+たたみ
+たちばな
+だっかい
+だっきゃく
+だっこ
+だっしゅつ
+だったい
+たてる
+たとえる
+たなばた
+たにん
+たぬき
+たのしみ
+たはつ
+たぶん
+たべる
+たぼう
+たまご
+たまる
+だむる
+ためいき
+ためす
+ためる
+たもつ
+たやすい
+たよる
+たらす
+たりきほんがん
+たりょう
+たりる
+たると
+たれる
+たれんと
+たろっと
+たわむれる
+だんあつ
+たんい
+たんおん
+たんか
+たんき
+たんけん
+たんご
+たんさん
+たんじょうび
+だんせい
+たんそく
+たんたい
+だんち
+たんてい
+たんとう
+だんな
+たんにん
+だんねつ
+たんのう
+たんぴん
+だんぼう
+たんまつ
+たんめい
+だんれつ
+だんろ
+だんわ
+ちあい
+ちあん
+ちいき
+ちいさい
+ちえん
+ちかい
+ちから
+ちきゅう
+ちきん
+ちけいず
+ちけん
+ちこく
+ちさい
+ちしき
+ちしりょう
+ちせい
+ちそう
+ちたい
+ちたん
+ちちおや
+ちつじょ
+ちてき
+ちてん
+ちぬき
+ちぬり
+ちのう
+ちひょう
+ちへいせん
+ちほう
+ちまた
+ちみつ
+ちみどろ
+ちめいど
+ちゃんこなべ
+ちゅうい
+ちゆりょく
+ちょうし
+ちょさくけん
+ちらし
+ちらみ
+ちりがみ
+ちりょう
+ちるど
+ちわわ
+ちんたい
+ちんもく
+ついか
+ついたち
+つうか
+つうじょう
+つうはん
+つうわ
+つかう
+つかれる
+つくね
+つくる
+つけね
+つける
+つごう
+つたえる
+つづく
+つつじ
+つつむ
+つとめる
+つながる
+つなみ
+つねづね
+つのる
+つぶす
+つまらない
+つまる
+つみき
+つめたい
+つもり
+つもる
+つよい
+つるぼ
+つるみく
+つわもの
+つわり
+てあし
+てあて
+てあみ
+ていおん
+ていか
+ていき
+ていけい
+ていこく
+ていさつ
+ていし
+ていせい
+ていたい
+ていど
+ていねい
+ていひょう
+ていへん
+ていぼう
+てうち
+ておくれ
+てきとう
+てくび
+でこぼこ
+てさぎょう
+てさげ
+てすり
+てそう
+てちがい
+てちょう
+てつがく
+てつづき
+でっぱ
+てつぼう
+てつや
+でぬかえ
+てぬき
+てぬぐい
+てのひら
+てはい
+てぶくろ
+てふだ
+てほどき
+てほん
+てまえ
+てまきずし
+てみじか
+てみやげ
+てらす
+てれび
+てわけ
+てわたし
+でんあつ
+てんいん
+てんかい
+てんき
+てんぐ
+てんけん
+てんごく
+てんさい
+てんし
+てんすう
+でんち
+てんてき
+てんとう
+てんない
+てんぷら
+てんぼうだい
+てんめつ
+てんらんかい
+でんりょく
+でんわ
+どあい
+といれ
+どうかん
+とうきゅう
+どうぐ
+とうし
+とうむぎ
+とおい
+とおか
+とおく
+とおす
+とおる
+とかい
+とかす
+ときおり
+ときどき
+とくい
+とくしゅう
+とくてん
+とくに
+とくべつ
+とけい
+とける
+とこや
+とさか
+としょかん
+とそう
+とたん
+とちゅう
+とっきゅう
+とっくん
+とつぜん
+とつにゅう
+とどける
+ととのえる
+とない
+となえる
+となり
+とのさま
+とばす
+どぶがわ
+とほう
+とまる
+とめる
+ともだち
+ともる
+どようび
+とらえる
+とんかつ
+どんぶり
+ないかく
+ないこう
+ないしょ
+ないす
+ないせん
+ないそう
+なおす
+ながい
+なくす
+なげる
+なこうど
+なさけ
+なたでここ
+なっとう
+なつやすみ
+ななおし
+なにごと
+なにもの
+なにわ
+なのか
+なふだ
+なまいき
+なまえ
+なまみ
+なみだ
+なめらか
+なめる
+なやむ
+ならう
+ならび
+ならぶ
+なれる
+なわとび
+なわばり
+にあう
+にいがた
+にうけ
+におい
+にかい
+にがて
+にきび
+にくしみ
+にくまん
+にげる
+にさんかたんそ
+にしき
+にせもの
+にちじょう
+にちようび
+にっか
+にっき
+にっけい
+にっこう
+にっさん
+にっしょく
+にっすう
+にっせき
+にってい
+になう
+にほん
+にまめ
+にもつ
+にやり
+にゅういん
+にりんしゃ
+にわとり
+にんい
+にんか
+にんき
+にんげん
+にんしき
+にんずう
+にんそう
+にんたい
+にんち
+にんてい
+にんにく
+にんぷ
+にんまり
+にんむ
+にんめい
+にんよう
+ぬいくぎ
+ぬかす
+ぬぐいとる
+ぬぐう
+ぬくもり
+ぬすむ
+ぬまえび
+ぬめり
+ぬらす
+ぬんちゃく
+ねあげ
+ねいき
+ねいる
+ねいろ
+ねぐせ
+ねくたい
+ねくら
+ねこぜ
+ねこむ
+ねさげ
+ねすごす
+ねそべる
+ねだん
+ねつい
+ねっしん
+ねつぞう
+ねったいぎょ
+ねぶそく
+ねふだ
+ねぼう
+ねほりはほり
+ねまき
+ねまわし
+ねみみ
+ねむい
+ねむたい
+ねもと
+ねらう
+ねわざ
+ねんいり
+ねんおし
+ねんかん
+ねんきん
+ねんぐ
+ねんざ
+ねんし
+ねんちゃく
+ねんど
+ねんぴ
+ねんぶつ
+ねんまつ
+ねんりょう
+ねんれい
+のいず
+のおづま
+のがす
+のきなみ
+のこぎり
+のこす
+のこる
+のせる
+のぞく
+のぞむ
+のたまう
+のちほど
+のっく
+のばす
+のはら
+のべる
+のぼる
+のみもの
+のやま
+のらいぬ
+のらねこ
+のりもの
+のりゆき
+のれん
+のんき
+ばあい
+はあく
+ばあさん
+ばいか
+ばいく
+はいけん
+はいご
+はいしん
+はいすい
+はいせん
+はいそう
+はいち
+ばいばい
+はいれつ
+はえる
+はおる
+はかい
+ばかり
+はかる
+はくしゅ
+はけん
+はこぶ
+はさみ
+はさん
+はしご
+ばしょ
+はしる
+はせる
+ぱそこん
+はそん
+はたん
+はちみつ
+はつおん
+はっかく
+はづき
+はっきり
+はっくつ
+はっけん
+はっこう
+はっさん
+はっしん
+はったつ
+はっちゅう
+はってん
+はっぴょう
+はっぽう
+はなす
+はなび
+はにかむ
+はぶらし
+はみがき
+はむかう
+はめつ
+はやい
+はやし
+はらう
+はろうぃん
+はわい
+はんい
+はんえい
+はんおん
+はんかく
+はんきょう
+ばんぐみ
+はんこ
+はんしゃ
+はんすう
+はんだん
+ぱんち
+ぱんつ
+はんてい
+はんとし
+はんのう
+はんぱ
+はんぶん
+はんぺん
+はんぼうき
+はんめい
+はんらん
+はんろん
+ひいき
+ひうん
+ひえる
+ひかく
+ひかり
+ひかる
+ひかん
+ひくい
+ひけつ
+ひこうき
+ひこく
+ひさい
+ひさしぶり
+ひさん
+びじゅつかん
+ひしょ
+ひそか
+ひそむ
+ひたむき
+ひだり
+ひたる
+ひつぎ
+ひっこし
+ひっし
+ひつじゅひん
+ひっす
+ひつぜん
+ぴったり
+ぴっちり
+ひつよう
+ひてい
+ひとごみ
+ひなまつり
+ひなん
+ひねる
+ひはん
+ひびく
+ひひょう
+ひほう
+ひまわり
+ひまん
+ひみつ
+ひめい
+ひめじし
+ひやけ
+ひやす
+ひよう
+びょうき
+ひらがな
+ひらく
+ひりつ
+ひりょう
+ひるま
+ひるやすみ
+ひれい
+ひろい
+ひろう
+ひろき
+ひろゆき
+ひんかく
+ひんけつ
+ひんこん
+ひんしゅ
+ひんそう
+ぴんち
+ひんぱん
+びんぼう
+ふあん
+ふいうち
+ふうけい
+ふうせん
+ぷうたろう
+ふうとう
+ふうふ
+ふえる
+ふおん
+ふかい
+ふきん
+ふくざつ
+ふくぶくろ
+ふこう
+ふさい
+ふしぎ
+ふじみ
+ふすま
+ふせい
+ふせぐ
+ふそく
+ぶたにく
+ふたん
+ふちょう
+ふつう
+ふつか
+ふっかつ
+ふっき
+ふっこく
+ぶどう
+ふとる
+ふとん
+ふのう
+ふはい
+ふひょう
+ふへん
+ふまん
+ふみん
+ふめつ
+ふめん
+ふよう
+ふりこ
+ふりる
+ふるい
+ふんいき
+ぶんがく
+ぶんぐ
+ふんしつ
+ぶんせき
+ふんそう
+ぶんぽう
+へいあん
+へいおん
+へいがい
+へいき
+へいげん
+へいこう
+へいさ
+へいしゃ
+へいせつ
+へいそ
+へいたく
+へいてん
+へいねつ
+へいわ
+へきが
+へこむ
+べにいろ
+べにしょうが
+へらす
+へんかん
+べんきょう
+べんごし
+へんさい
+へんたい
+べんり
+ほあん
+ほいく
+ぼうぎょ
+ほうこく
+ほうそう
+ほうほう
+ほうもん
+ほうりつ
+ほえる
+ほおん
+ほかん
+ほきょう
+ぼきん
+ほくろ
+ほけつ
+ほけん
+ほこう
+ほこる
+ほしい
+ほしつ
+ほしゅ
+ほしょう
+ほせい
+ほそい
+ほそく
+ほたて
+ほたる
+ぽちぶくろ
+ほっきょく
+ほっさ
+ほったん
+ほとんど
+ほめる
+ほんい
+ほんき
+ほんけ
+ほんしつ
+ほんやく
+まいにち
+まかい
+まかせる
+まがる
+まける
+まこと
+まさつ
+まじめ
+ますく
+まぜる
+まつり
+まとめ
+まなぶ
+まぬけ
+まねく
+まほう
+まもる
+まゆげ
+まよう
+まろやか
+まわす
+まわり
+まわる
+まんが
+まんきつ
+まんぞく
+まんなか
+みいら
+みうち
+みえる
+みがく
+みかた
+みかん
+みけん
+みこん
+みじかい
+みすい
+みすえる
+みせる
+みっか
+みつかる
+みつける
+みてい
+みとめる
+みなと
+みなみかさい
+みねらる
+みのう
+みのがす
+みほん
+みもと
+みやげ
+みらい
+みりょく
+みわく
+みんか
+みんぞく
+むいか
+むえき
+むえん
+むかい
+むかう
+むかえ
+むかし
+むぎちゃ
+むける
+むげん
+むさぼる
+むしあつい
+むしば
+むじゅん
+むしろ
+むすう
+むすこ
+むすぶ
+むすめ
+むせる
+むせん
+むちゅう
+むなしい
+むのう
+むやみ
+むよう
+むらさき
+むりょう
+むろん
+めいあん
+めいうん
+めいえん
+めいかく
+めいきょく
+めいさい
+めいし
+めいそう
+めいぶつ
+めいれい
+めいわく
+めぐまれる
+めざす
+めした
+めずらしい
+めだつ
+めまい
+めやす
+めんきょ
+めんせき
+めんどう
+もうしあげる
+もうどうけん
+もえる
+もくし
+もくてき
+もくようび
+もちろん
+もどる
+もらう
+もんく
+もんだい
+やおや
+やける
+やさい
+やさしい
+やすい
+やすたろう
+やすみ
+やせる
+やそう
+やたい
+やちん
+やっと
+やっぱり
+やぶる
+やめる
+ややこしい
+やよい
+やわらかい
+ゆうき
+ゆうびんきょく
+ゆうべ
+ゆうめい
+ゆけつ
+ゆしゅつ
+ゆせん
+ゆそう
+ゆたか
+ゆちゃく
+ゆでる
+ゆにゅう
+ゆびわ
+ゆらい
+ゆれる
+ようい
+ようか
+ようきゅう
+ようじ
+ようす
+ようちえん
+よかぜ
+よかん
+よきん
+よくせい
+よくぼう
+よけい
+よごれる
+よさん
+よしゅう
+よそう
+よそく
+よっか
+よてい
+よどがわく
+よねつ
+よやく
+よゆう
+よろこぶ
+よろしい
+らいう
+らくがき
+らくご
+らくさつ
+らくだ
+らしんばん
+らせん
+らぞく
+らたい
+らっか
+られつ
+りえき
+りかい
+りきさく
+りきせつ
+りくぐん
+りくつ
+りけん
+りこう
+りせい
+りそう
+りそく
+りてん
+りねん
+りゆう
+りゅうがく
+りよう
+りょうり
+りょかん
+りょくちゃ
+りょこう
+りりく
+りれき
+りろん
+りんご
+るいけい
+るいさい
+るいじ
+るいせき
+るすばん
+るりがわら
+れいかん
+れいぎ
+れいせい
+れいぞうこ
+れいとう
+れいぼう
+れきし
+れきだい
+れんあい
+れんけい
+れんこん
+れんさい
+れんしゅう
+れんぞく
+れんらく
+ろうか
+ろうご
+ろうじん
+ろうそく
+ろくが
+ろこつ
+ろじうら
+ろしゅつ
+ろせん
+ろてん
+ろめん
+ろれつ
+ろんぎ
+ろんぱ
+ろんぶん
+ろんり
+わかす
+わかめ
+わかやま
+わかれる
+わしつ
+わじまし
+わすれもの
+わらう
+われる
diff --git a/frozen_deps/mnemonic/wordlist/korean.txt b/frozen_deps/mnemonic/wordlist/korean.txt
new file mode 100644
index 0000000..1acebf7
--- /dev/null
+++ b/frozen_deps/mnemonic/wordlist/korean.txt
@@ -0,0 +1,2048 @@
+가격
+가끔
+가난
+가능
+가득
+가르침
+가뭄
+가방
+가상
+가슴
+가운데
+가을
+가이드
+가입
+가장
+가정
+가족
+가죽
+각오
+각자
+간격
+간부
+간섭
+간장
+간접
+간판
+갈등
+갈비
+갈색
+갈증
+감각
+감기
+감소
+감수성
+감자
+감정
+갑자기
+강남
+강당
+강도
+강력히
+강변
+강북
+강사
+강수량
+강아지
+강원도
+강의
+강제
+강조
+같이
+개구리
+개나리
+개방
+개별
+개선
+개성
+개인
+객관적
+거실
+거액
+거울
+거짓
+거품
+걱정
+건강
+건물
+건설
+건조
+건축
+걸음
+검사
+검토
+게시판
+게임
+겨울
+견해
+결과
+결국
+결론
+결석
+결승
+결심
+결정
+결혼
+경계
+경고
+경기
+경력
+경복궁
+경비
+경상도
+경영
+경우
+경쟁
+경제
+경주
+경찰
+경치
+경향
+경험
+계곡
+계단
+계란
+계산
+계속
+계약
+계절
+계층
+계획
+고객
+고구려
+고궁
+고급
+고등학생
+고무신
+고민
+고양이
+고장
+고전
+고집
+고춧가루
+고통
+고향
+곡식
+골목
+골짜기
+골프
+공간
+공개
+공격
+공군
+공급
+공기
+공동
+공무원
+공부
+공사
+공식
+공업
+공연
+공원
+공장
+공짜
+공책
+공통
+공포
+공항
+공휴일
+과목
+과일
+과장
+과정
+과학
+관객
+관계
+관광
+관념
+관람
+관련
+관리
+관습
+관심
+관점
+관찰
+광경
+광고
+광장
+광주
+괴로움
+굉장히
+교과서
+교문
+교복
+교실
+교양
+교육
+교장
+교직
+교통
+교환
+교훈
+구경
+구름
+구멍
+구별
+구분
+구석
+구성
+구속
+구역
+구입
+구청
+구체적
+국가
+국기
+국내
+국립
+국물
+국민
+국수
+국어
+국왕
+국적
+국제
+국회
+군대
+군사
+군인
+궁극적
+권리
+권위
+권투
+귀국
+귀신
+규정
+규칙
+균형
+그날
+그냥
+그늘
+그러나
+그룹
+그릇
+그림
+그제서야
+그토록
+극복
+극히
+근거
+근교
+근래
+근로
+근무
+근본
+근원
+근육
+근처
+글씨
+글자
+금강산
+금고
+금년
+금메달
+금액
+금연
+금요일
+금지
+긍정적
+기간
+기관
+기념
+기능
+기독교
+기둥
+기록
+기름
+기법
+기본
+기분
+기쁨
+기숙사
+기술
+기억
+기업
+기온
+기운
+기원
+기적
+기준
+기침
+기혼
+기획
+긴급
+긴장
+길이
+김밥
+김치
+김포공항
+깍두기
+깜빡
+깨달음
+깨소금
+껍질
+꼭대기
+꽃잎
+나들이
+나란히
+나머지
+나물
+나침반
+나흘
+낙엽
+난방
+날개
+날씨
+날짜
+남녀
+남대문
+남매
+남산
+남자
+남편
+남학생
+낭비
+낱말
+내년
+내용
+내일
+냄비
+냄새
+냇물
+냉동
+냉면
+냉방
+냉장고
+넥타이
+넷째
+노동
+노란색
+노력
+노인
+녹음
+녹차
+녹화
+논리
+논문
+논쟁
+놀이
+농구
+농담
+농민
+농부
+농업
+농장
+농촌
+높이
+눈동자
+눈물
+눈썹
+뉴욕
+느낌
+늑대
+능동적
+능력
+다방
+다양성
+다음
+다이어트
+다행
+단계
+단골
+단독
+단맛
+단순
+단어
+단위
+단점
+단체
+단추
+단편
+단풍
+달걀
+달러
+달력
+달리
+닭고기
+담당
+담배
+담요
+담임
+답변
+답장
+당근
+당분간
+당연히
+당장
+대규모
+대낮
+대단히
+대답
+대도시
+대략
+대량
+대륙
+대문
+대부분
+대신
+대응
+대장
+대전
+대접
+대중
+대책
+대출
+대충
+대통령
+대학
+대한민국
+대합실
+대형
+덩어리
+데이트
+도대체
+도덕
+도둑
+도망
+도서관
+도심
+도움
+도입
+도자기
+도저히
+도전
+도중
+도착
+독감
+독립
+독서
+독일
+독창적
+동화책
+뒷모습
+뒷산
+딸아이
+마누라
+마늘
+마당
+마라톤
+마련
+마무리
+마사지
+마약
+마요네즈
+마을
+마음
+마이크
+마중
+마지막
+마찬가지
+마찰
+마흔
+막걸리
+막내
+막상
+만남
+만두
+만세
+만약
+만일
+만점
+만족
+만화
+많이
+말기
+말씀
+말투
+맘대로
+망원경
+매년
+매달
+매력
+매번
+매스컴
+매일
+매장
+맥주
+먹이
+먼저
+먼지
+멀리
+메일
+며느리
+며칠
+면담
+멸치
+명단
+명령
+명예
+명의
+명절
+명칭
+명함
+모금
+모니터
+모델
+모든
+모범
+모습
+모양
+모임
+모조리
+모집
+모퉁이
+목걸이
+목록
+목사
+목소리
+목숨
+목적
+목표
+몰래
+몸매
+몸무게
+몸살
+몸속
+몸짓
+몸통
+몹시
+무관심
+무궁화
+무더위
+무덤
+무릎
+무슨
+무엇
+무역
+무용
+무조건
+무지개
+무척
+문구
+문득
+문법
+문서
+문제
+문학
+문화
+물가
+물건
+물결
+물고기
+물론
+물리학
+물음
+물질
+물체
+미국
+미디어
+미사일
+미술
+미역
+미용실
+미움
+미인
+미팅
+미혼
+민간
+민족
+민주
+믿음
+밀가루
+밀리미터
+밑바닥
+바가지
+바구니
+바나나
+바늘
+바닥
+바닷가
+바람
+바이러스
+바탕
+박물관
+박사
+박수
+반대
+반드시
+반말
+반발
+반성
+반응
+반장
+반죽
+반지
+반찬
+받침
+발가락
+발걸음
+발견
+발달
+발레
+발목
+발바닥
+발생
+발음
+발자국
+발전
+발톱
+발표
+밤하늘
+밥그릇
+밥맛
+밥상
+밥솥
+방금
+방면
+방문
+방바닥
+방법
+방송
+방식
+방안
+방울
+방지
+방학
+방해
+방향
+배경
+배꼽
+배달
+배드민턴
+백두산
+백색
+백성
+백인
+백제
+백화점
+버릇
+버섯
+버튼
+번개
+번역
+번지
+번호
+벌금
+벌레
+벌써
+범위
+범인
+범죄
+법률
+법원
+법적
+법칙
+베이징
+벨트
+변경
+변동
+변명
+변신
+변호사
+변화
+별도
+별명
+별일
+병실
+병아리
+병원
+보관
+보너스
+보라색
+보람
+보름
+보상
+보안
+보자기
+보장
+보전
+보존
+보통
+보편적
+보험
+복도
+복사
+복숭아
+복습
+볶음
+본격적
+본래
+본부
+본사
+본성
+본인
+본질
+볼펜
+봉사
+봉지
+봉투
+부근
+부끄러움
+부담
+부동산
+부문
+부분
+부산
+부상
+부엌
+부인
+부작용
+부장
+부정
+부족
+부지런히
+부친
+부탁
+부품
+부회장
+북부
+북한
+분노
+분량
+분리
+분명
+분석
+분야
+분위기
+분필
+분홍색
+불고기
+불과
+불교
+불꽃
+불만
+불법
+불빛
+불안
+불이익
+불행
+브랜드
+비극
+비난
+비닐
+비둘기
+비디오
+비로소
+비만
+비명
+비밀
+비바람
+비빔밥
+비상
+비용
+비율
+비중
+비타민
+비판
+빌딩
+빗물
+빗방울
+빗줄기
+빛깔
+빨간색
+빨래
+빨리
+사건
+사계절
+사나이
+사냥
+사람
+사랑
+사립
+사모님
+사물
+사방
+사상
+사생활
+사설
+사슴
+사실
+사업
+사용
+사월
+사장
+사전
+사진
+사촌
+사춘기
+사탕
+사투리
+사흘
+산길
+산부인과
+산업
+산책
+살림
+살인
+살짝
+삼계탕
+삼국
+삼십
+삼월
+삼촌
+상관
+상금
+상대
+상류
+상반기
+상상
+상식
+상업
+상인
+상자
+상점
+상처
+상추
+상태
+상표
+상품
+상황
+새벽
+색깔
+색연필
+생각
+생명
+생물
+생방송
+생산
+생선
+생신
+생일
+생활
+서랍
+서른
+서명
+서민
+서비스
+서양
+서울
+서적
+서점
+서쪽
+서클
+석사
+석유
+선거
+선물
+선배
+선생
+선수
+선원
+선장
+선전
+선택
+선풍기
+설거지
+설날
+설렁탕
+설명
+설문
+설사
+설악산
+설치
+설탕
+섭씨
+성공
+성당
+성명
+성별
+성인
+성장
+성적
+성질
+성함
+세금
+세미나
+세상
+세월
+세종대왕
+세탁
+센터
+센티미터
+셋째
+소규모
+소극적
+소금
+소나기
+소년
+소득
+소망
+소문
+소설
+소속
+소아과
+소용
+소원
+소음
+소중히
+소지품
+소질
+소풍
+소형
+속담
+속도
+속옷
+손가락
+손길
+손녀
+손님
+손등
+손목
+손뼉
+손실
+손질
+손톱
+손해
+솔직히
+솜씨
+송아지
+송이
+송편
+쇠고기
+쇼핑
+수건
+수년
+수단
+수돗물
+수동적
+수면
+수명
+수박
+수상
+수석
+수술
+수시로
+수업
+수염
+수영
+수입
+수준
+수집
+수출
+수컷
+수필
+수학
+수험생
+수화기
+숙녀
+숙소
+숙제
+순간
+순서
+순수
+순식간
+순위
+숟가락
+술병
+술집
+숫자
+스님
+스물
+스스로
+스승
+스웨터
+스위치
+스케이트
+스튜디오
+스트레스
+스포츠
+슬쩍
+슬픔
+습관
+습기
+승객
+승리
+승부
+승용차
+승진
+시각
+시간
+시골
+시금치
+시나리오
+시댁
+시리즈
+시멘트
+시민
+시부모
+시선
+시설
+시스템
+시아버지
+시어머니
+시월
+시인
+시일
+시작
+시장
+시절
+시점
+시중
+시즌
+시집
+시청
+시합
+시험
+식구
+식기
+식당
+식량
+식료품
+식물
+식빵
+식사
+식생활
+식초
+식탁
+식품
+신고
+신규
+신념
+신문
+신발
+신비
+신사
+신세
+신용
+신제품
+신청
+신체
+신화
+실감
+실내
+실력
+실례
+실망
+실수
+실습
+실시
+실장
+실정
+실질적
+실천
+실체
+실컷
+실태
+실패
+실험
+실현
+심리
+심부름
+심사
+심장
+심정
+심판
+쌍둥이
+씨름
+씨앗
+아가씨
+아나운서
+아드님
+아들
+아쉬움
+아스팔트
+아시아
+아울러
+아저씨
+아줌마
+아직
+아침
+아파트
+아프리카
+아픔
+아홉
+아흔
+악기
+악몽
+악수
+안개
+안경
+안과
+안내
+안녕
+안동
+안방
+안부
+안주
+알루미늄
+알코올
+암시
+암컷
+압력
+앞날
+앞문
+애인
+애정
+액수
+앨범
+야간
+야단
+야옹
+약간
+약국
+약속
+약수
+약점
+약품
+약혼녀
+양념
+양력
+양말
+양배추
+양주
+양파
+어둠
+어려움
+어른
+어젯밤
+어쨌든
+어쩌다가
+어쩐지
+언니
+언덕
+언론
+언어
+얼굴
+얼른
+얼음
+얼핏
+엄마
+업무
+업종
+업체
+엉덩이
+엉망
+엉터리
+엊그제
+에너지
+에어컨
+엔진
+여건
+여고생
+여관
+여군
+여권
+여대생
+여덟
+여동생
+여든
+여론
+여름
+여섯
+여성
+여왕
+여인
+여전히
+여직원
+여학생
+여행
+역사
+역시
+역할
+연결
+연구
+연극
+연기
+연락
+연설
+연세
+연속
+연습
+연애
+연예인
+연인
+연장
+연주
+연출
+연필
+연합
+연휴
+열기
+열매
+열쇠
+열심히
+열정
+열차
+열흘
+염려
+엽서
+영국
+영남
+영상
+영양
+영역
+영웅
+영원히
+영하
+영향
+영혼
+영화
+옆구리
+옆방
+옆집
+예감
+예금
+예방
+예산
+예상
+예선
+예술
+예습
+예식장
+예약
+예전
+예절
+예정
+예컨대
+옛날
+오늘
+오락
+오랫동안
+오렌지
+오로지
+오른발
+오븐
+오십
+오염
+오월
+오전
+오직
+오징어
+오페라
+오피스텔
+오히려
+옥상
+옥수수
+온갖
+온라인
+온몸
+온종일
+온통
+올가을
+올림픽
+올해
+옷차림
+와이셔츠
+와인
+완성
+완전
+왕비
+왕자
+왜냐하면
+왠지
+외갓집
+외국
+외로움
+외삼촌
+외출
+외침
+외할머니
+왼발
+왼손
+왼쪽
+요금
+요일
+요즘
+요청
+용기
+용서
+용어
+우산
+우선
+우승
+우연히
+우정
+우체국
+우편
+운동
+운명
+운반
+운전
+운행
+울산
+울음
+움직임
+웃어른
+웃음
+워낙
+원고
+원래
+원서
+원숭이
+원인
+원장
+원피스
+월급
+월드컵
+월세
+월요일
+웨이터
+위반
+위법
+위성
+위원
+위험
+위협
+윗사람
+유난히
+유럽
+유명
+유물
+유산
+유적
+유치원
+유학
+유행
+유형
+육군
+육상
+육십
+육체
+은행
+음력
+음료
+음반
+음성
+음식
+음악
+음주
+의견
+의논
+의문
+의복
+의식
+의심
+의외로
+의욕
+의원
+의학
+이것
+이곳
+이념
+이놈
+이달
+이대로
+이동
+이렇게
+이력서
+이론적
+이름
+이민
+이발소
+이별
+이불
+이빨
+이상
+이성
+이슬
+이야기
+이용
+이웃
+이월
+이윽고
+이익
+이전
+이중
+이튿날
+이틀
+이혼
+인간
+인격
+인공
+인구
+인근
+인기
+인도
+인류
+인물
+인생
+인쇄
+인연
+인원
+인재
+인종
+인천
+인체
+인터넷
+인하
+인형
+일곱
+일기
+일단
+일대
+일등
+일반
+일본
+일부
+일상
+일생
+일손
+일요일
+일월
+일정
+일종
+일주일
+일찍
+일체
+일치
+일행
+일회용
+임금
+임무
+입대
+입력
+입맛
+입사
+입술
+입시
+입원
+입장
+입학
+자가용
+자격
+자극
+자동
+자랑
+자부심
+자식
+자신
+자연
+자원
+자율
+자전거
+자정
+자존심
+자판
+작가
+작년
+작성
+작업
+작용
+작은딸
+작품
+잔디
+잔뜩
+잔치
+잘못
+잠깐
+잠수함
+잠시
+잠옷
+잠자리
+잡지
+장관
+장군
+장기간
+장래
+장례
+장르
+장마
+장면
+장모
+장미
+장비
+장사
+장소
+장식
+장애인
+장인
+장점
+장차
+장학금
+재능
+재빨리
+재산
+재생
+재작년
+재정
+재채기
+재판
+재학
+재활용
+저것
+저고리
+저곳
+저녁
+저런
+저렇게
+저번
+저울
+저절로
+저축
+적극
+적당히
+적성
+적용
+적응
+전개
+전공
+전기
+전달
+전라도
+전망
+전문
+전반
+전부
+전세
+전시
+전용
+전자
+전쟁
+전주
+전철
+전체
+전통
+전혀
+전후
+절대
+절망
+절반
+절약
+절차
+점검
+점수
+점심
+점원
+점점
+점차
+접근
+접시
+접촉
+젓가락
+정거장
+정도
+정류장
+정리
+정말
+정면
+정문
+정반대
+정보
+정부
+정비
+정상
+정성
+정오
+정원
+정장
+정지
+정치
+정확히
+제공
+제과점
+제대로
+제목
+제발
+제법
+제삿날
+제안
+제일
+제작
+제주도
+제출
+제품
+제한
+조각
+조건
+조금
+조깅
+조명
+조미료
+조상
+조선
+조용히
+조절
+조정
+조직
+존댓말
+존재
+졸업
+졸음
+종교
+종로
+종류
+종소리
+종업원
+종종
+종합
+좌석
+죄인
+주관적
+주름
+주말
+주머니
+주먹
+주문
+주민
+주방
+주변
+주식
+주인
+주일
+주장
+주전자
+주택
+준비
+줄거리
+줄기
+줄무늬
+중간
+중계방송
+중국
+중년
+중단
+중독
+중반
+중부
+중세
+중소기업
+중순
+중앙
+중요
+중학교
+즉석
+즉시
+즐거움
+증가
+증거
+증권
+증상
+증세
+지각
+지갑
+지경
+지극히
+지금
+지급
+지능
+지름길
+지리산
+지방
+지붕
+지식
+지역
+지우개
+지원
+지적
+지점
+지진
+지출
+직선
+직업
+직원
+직장
+진급
+진동
+진로
+진료
+진리
+진짜
+진찰
+진출
+진통
+진행
+질문
+질병
+질서
+짐작
+집단
+집안
+집중
+짜증
+찌꺼기
+차남
+차라리
+차량
+차림
+차별
+차선
+차츰
+착각
+찬물
+찬성
+참가
+참기름
+참새
+참석
+참여
+참외
+참조
+찻잔
+창가
+창고
+창구
+창문
+창밖
+창작
+창조
+채널
+채점
+책가방
+책방
+책상
+책임
+챔피언
+처벌
+처음
+천국
+천둥
+천장
+천재
+천천히
+철도
+철저히
+철학
+첫날
+첫째
+청년
+청바지
+청소
+청춘
+체계
+체력
+체온
+체육
+체중
+체험
+초등학생
+초반
+초밥
+초상화
+초순
+초여름
+초원
+초저녁
+초점
+초청
+초콜릿
+촛불
+총각
+총리
+총장
+촬영
+최근
+최상
+최선
+최신
+최악
+최종
+추석
+추억
+추진
+추천
+추측
+축구
+축소
+축제
+축하
+출근
+출발
+출산
+출신
+출연
+출입
+출장
+출판
+충격
+충고
+충돌
+충분히
+충청도
+취업
+취직
+취향
+치약
+친구
+친척
+칠십
+칠월
+칠판
+침대
+침묵
+침실
+칫솔
+칭찬
+카메라
+카운터
+칼국수
+캐릭터
+캠퍼스
+캠페인
+커튼
+컨디션
+컬러
+컴퓨터
+코끼리
+코미디
+콘서트
+콜라
+콤플렉스
+콩나물
+쾌감
+쿠데타
+크림
+큰길
+큰딸
+큰소리
+큰아들
+큰어머니
+큰일
+큰절
+클래식
+클럽
+킬로
+타입
+타자기
+탁구
+탁자
+탄생
+태권도
+태양
+태풍
+택시
+탤런트
+터널
+터미널
+테니스
+테스트
+테이블
+텔레비전
+토론
+토마토
+토요일
+통계
+통과
+통로
+통신
+통역
+통일
+통장
+통제
+통증
+통합
+통화
+퇴근
+퇴원
+퇴직금
+튀김
+트럭
+특급
+특별
+특성
+특수
+특징
+특히
+튼튼히
+티셔츠
+파란색
+파일
+파출소
+판결
+판단
+판매
+판사
+팔십
+팔월
+팝송
+패션
+팩스
+팩시밀리
+팬티
+퍼센트
+페인트
+편견
+편의
+편지
+편히
+평가
+평균
+평생
+평소
+평양
+평일
+평화
+포스터
+포인트
+포장
+포함
+표면
+표정
+표준
+표현
+품목
+품질
+풍경
+풍속
+풍습
+프랑스
+프린터
+플라스틱
+피곤
+피망
+피아노
+필름
+필수
+필요
+필자
+필통
+핑계
+하느님
+하늘
+하드웨어
+하룻밤
+하반기
+하숙집
+하순
+하여튼
+하지만
+하천
+하품
+하필
+학과
+학교
+학급
+학기
+학년
+학력
+학번
+학부모
+학비
+학생
+학술
+학습
+학용품
+학원
+학위
+학자
+학점
+한계
+한글
+한꺼번에
+한낮
+한눈
+한동안
+한때
+한라산
+한마디
+한문
+한번
+한복
+한식
+한여름
+한쪽
+할머니
+할아버지
+할인
+함께
+함부로
+합격
+합리적
+항공
+항구
+항상
+항의
+해결
+해군
+해답
+해당
+해물
+해석
+해설
+해수욕장
+해안
+핵심
+핸드백
+햄버거
+햇볕
+햇살
+행동
+행복
+행사
+행운
+행위
+향기
+향상
+향수
+허락
+허용
+헬기
+현관
+현금
+현대
+현상
+현실
+현장
+현재
+현지
+혈액
+협력
+형부
+형사
+형수
+형식
+형제
+형태
+형편
+혜택
+호기심
+호남
+호랑이
+호박
+호텔
+호흡
+혹시
+홀로
+홈페이지
+홍보
+홍수
+홍차
+화면
+화분
+화살
+화요일
+화장
+화학
+확보
+확인
+확장
+확정
+환갑
+환경
+환영
+환율
+환자
+활기
+활동
+활발히
+활용
+활짝
+회견
+회관
+회복
+회색
+회원
+회장
+회전
+횟수
+횡단보도
+효율적
+후반
+후춧가루
+훈련
+훨씬
+휴식
+휴일
+흉내
+흐름
+흑백
+흑인
+흔적
+흔히
+흥미
+흥분
+희곡
+희망
+희생
+흰색
+힘껏
diff --git a/frozen_deps/mnemonic/wordlist/spanish.txt b/frozen_deps/mnemonic/wordlist/spanish.txt
new file mode 100644
index 0000000..fdbc23c
--- /dev/null
+++ b/frozen_deps/mnemonic/wordlist/spanish.txt
@@ -0,0 +1,2048 @@
+ábaco
+abdomen
+abeja
+abierto
+abogado
+abono
+aborto
+abrazo
+abrir
+abuelo
+abuso
+acabar
+academia
+acceso
+acción
+aceite
+acelga
+acento
+aceptar
+ácido
+aclarar
+acné
+acoger
+acoso
+activo
+acto
+actriz
+actuar
+acudir
+acuerdo
+acusar
+adicto
+admitir
+adoptar
+adorno
+aduana
+adulto
+aéreo
+afectar
+afición
+afinar
+afirmar
+ágil
+agitar
+agonía
+agosto
+agotar
+agregar
+agrio
+agua
+agudo
+águila
+aguja
+ahogo
+ahorro
+aire
+aislar
+ajedrez
+ajeno
+ajuste
+alacrán
+alambre
+alarma
+alba
+álbum
+alcalde
+aldea
+alegre
+alejar
+alerta
+aleta
+alfiler
+alga
+algodón
+aliado
+aliento
+alivio
+alma
+almeja
+almíbar
+altar
+alteza
+altivo
+alto
+altura
+alumno
+alzar
+amable
+amante
+amapola
+amargo
+amasar
+ámbar
+ámbito
+ameno
+amigo
+amistad
+amor
+amparo
+amplio
+ancho
+anciano
+ancla
+andar
+andén
+anemia
+ángulo
+anillo
+ánimo
+anís
+anotar
+antena
+antiguo
+antojo
+anual
+anular
+anuncio
+añadir
+añejo
+año
+apagar
+aparato
+apetito
+apio
+aplicar
+apodo
+aporte
+apoyo
+aprender
+aprobar
+apuesta
+apuro
+arado
+araña
+arar
+árbitro
+árbol
+arbusto
+archivo
+arco
+arder
+ardilla
+arduo
+área
+árido
+aries
+armonía
+arnés
+aroma
+arpa
+arpón
+arreglo
+arroz
+arruga
+arte
+artista
+asa
+asado
+asalto
+ascenso
+asegurar
+aseo
+asesor
+asiento
+asilo
+asistir
+asno
+asombro
+áspero
+astilla
+astro
+astuto
+asumir
+asunto
+atajo
+ataque
+atar
+atento
+ateo
+ático
+atleta
+átomo
+atraer
+atroz
+atún
+audaz
+audio
+auge
+aula
+aumento
+ausente
+autor
+aval
+avance
+avaro
+ave
+avellana
+avena
+avestruz
+avión
+aviso
+ayer
+ayuda
+ayuno
+azafrán
+azar
+azote
+azúcar
+azufre
+azul
+baba
+babor
+bache
+bahía
+baile
+bajar
+balanza
+balcón
+balde
+bambú
+banco
+banda
+baño
+barba
+barco
+barniz
+barro
+báscula
+bastón
+basura
+batalla
+batería
+batir
+batuta
+baúl
+bazar
+bebé
+bebida
+bello
+besar
+beso
+bestia
+bicho
+bien
+bingo
+blanco
+bloque
+blusa
+boa
+bobina
+bobo
+boca
+bocina
+boda
+bodega
+boina
+bola
+bolero
+bolsa
+bomba
+bondad
+bonito
+bono
+bonsái
+borde
+borrar
+bosque
+bote
+botín
+bóveda
+bozal
+bravo
+brazo
+brecha
+breve
+brillo
+brinco
+brisa
+broca
+broma
+bronce
+brote
+bruja
+brusco
+bruto
+buceo
+bucle
+bueno
+buey
+bufanda
+bufón
+búho
+buitre
+bulto
+burbuja
+burla
+burro
+buscar
+butaca
+buzón
+caballo
+cabeza
+cabina
+cabra
+cacao
+cadáver
+cadena
+caer
+café
+caída
+caimán
+caja
+cajón
+cal
+calamar
+calcio
+caldo
+calidad
+calle
+calma
+calor
+calvo
+cama
+cambio
+camello
+camino
+campo
+cáncer
+candil
+canela
+canguro
+canica
+canto
+caña
+cañón
+caoba
+caos
+capaz
+capitán
+capote
+captar
+capucha
+cara
+carbón
+cárcel
+careta
+carga
+cariño
+carne
+carpeta
+carro
+carta
+casa
+casco
+casero
+caspa
+castor
+catorce
+catre
+caudal
+causa
+cazo
+cebolla
+ceder
+cedro
+celda
+célebre
+celoso
+célula
+cemento
+ceniza
+centro
+cerca
+cerdo
+cereza
+cero
+cerrar
+certeza
+césped
+cetro
+chacal
+chaleco
+champú
+chancla
+chapa
+charla
+chico
+chiste
+chivo
+choque
+choza
+chuleta
+chupar
+ciclón
+ciego
+cielo
+cien
+cierto
+cifra
+cigarro
+cima
+cinco
+cine
+cinta
+ciprés
+circo
+ciruela
+cisne
+cita
+ciudad
+clamor
+clan
+claro
+clase
+clave
+cliente
+clima
+clínica
+cobre
+cocción
+cochino
+cocina
+coco
+código
+codo
+cofre
+coger
+cohete
+cojín
+cojo
+cola
+colcha
+colegio
+colgar
+colina
+collar
+colmo
+columna
+combate
+comer
+comida
+cómodo
+compra
+conde
+conejo
+conga
+conocer
+consejo
+contar
+copa
+copia
+corazón
+corbata
+corcho
+cordón
+corona
+correr
+coser
+cosmos
+costa
+cráneo
+cráter
+crear
+crecer
+creído
+crema
+cría
+crimen
+cripta
+crisis
+cromo
+crónica
+croqueta
+crudo
+cruz
+cuadro
+cuarto
+cuatro
+cubo
+cubrir
+cuchara
+cuello
+cuento
+cuerda
+cuesta
+cueva
+cuidar
+culebra
+culpa
+culto
+cumbre
+cumplir
+cuna
+cuneta
+cuota
+cupón
+cúpula
+curar
+curioso
+curso
+curva
+cutis
+dama
+danza
+dar
+dardo
+dátil
+deber
+débil
+década
+decir
+dedo
+defensa
+definir
+dejar
+delfín
+delgado
+delito
+demora
+denso
+dental
+deporte
+derecho
+derrota
+desayuno
+deseo
+desfile
+desnudo
+destino
+desvío
+detalle
+detener
+deuda
+día
+diablo
+diadema
+diamante
+diana
+diario
+dibujo
+dictar
+diente
+dieta
+diez
+difícil
+digno
+dilema
+diluir
+dinero
+directo
+dirigir
+disco
+diseño
+disfraz
+diva
+divino
+doble
+doce
+dolor
+domingo
+don
+donar
+dorado
+dormir
+dorso
+dos
+dosis
+dragón
+droga
+ducha
+duda
+duelo
+dueño
+dulce
+dúo
+duque
+durar
+dureza
+duro
+ébano
+ebrio
+echar
+eco
+ecuador
+edad
+edición
+edificio
+editor
+educar
+efecto
+eficaz
+eje
+ejemplo
+elefante
+elegir
+elemento
+elevar
+elipse
+élite
+elixir
+elogio
+eludir
+embudo
+emitir
+emoción
+empate
+empeño
+empleo
+empresa
+enano
+encargo
+enchufe
+encía
+enemigo
+enero
+enfado
+enfermo
+engaño
+enigma
+enlace
+enorme
+enredo
+ensayo
+enseñar
+entero
+entrar
+envase
+envío
+época
+equipo
+erizo
+escala
+escena
+escolar
+escribir
+escudo
+esencia
+esfera
+esfuerzo
+espada
+espejo
+espía
+esposa
+espuma
+esquí
+estar
+este
+estilo
+estufa
+etapa
+eterno
+ética
+etnia
+evadir
+evaluar
+evento
+evitar
+exacto
+examen
+exceso
+excusa
+exento
+exigir
+exilio
+existir
+éxito
+experto
+explicar
+exponer
+extremo
+fábrica
+fábula
+fachada
+fácil
+factor
+faena
+faja
+falda
+fallo
+falso
+faltar
+fama
+familia
+famoso
+faraón
+farmacia
+farol
+farsa
+fase
+fatiga
+fauna
+favor
+fax
+febrero
+fecha
+feliz
+feo
+feria
+feroz
+fértil
+fervor
+festín
+fiable
+fianza
+fiar
+fibra
+ficción
+ficha
+fideo
+fiebre
+fiel
+fiera
+fiesta
+figura
+fijar
+fijo
+fila
+filete
+filial
+filtro
+fin
+finca
+fingir
+finito
+firma
+flaco
+flauta
+flecha
+flor
+flota
+fluir
+flujo
+flúor
+fobia
+foca
+fogata
+fogón
+folio
+folleto
+fondo
+forma
+forro
+fortuna
+forzar
+fosa
+foto
+fracaso
+frágil
+franja
+frase
+fraude
+freír
+freno
+fresa
+frío
+frito
+fruta
+fuego
+fuente
+fuerza
+fuga
+fumar
+función
+funda
+furgón
+furia
+fusil
+fútbol
+futuro
+gacela
+gafas
+gaita
+gajo
+gala
+galería
+gallo
+gamba
+ganar
+gancho
+ganga
+ganso
+garaje
+garza
+gasolina
+gastar
+gato
+gavilán
+gemelo
+gemir
+gen
+género
+genio
+gente
+geranio
+gerente
+germen
+gesto
+gigante
+gimnasio
+girar
+giro
+glaciar
+globo
+gloria
+gol
+golfo
+goloso
+golpe
+goma
+gordo
+gorila
+gorra
+gota
+goteo
+gozar
+grada
+gráfico
+grano
+grasa
+gratis
+grave
+grieta
+grillo
+gripe
+gris
+grito
+grosor
+grúa
+grueso
+grumo
+grupo
+guante
+guapo
+guardia
+guerra
+guía
+guiño
+guion
+guiso
+guitarra
+gusano
+gustar
+haber
+hábil
+hablar
+hacer
+hacha
+hada
+hallar
+hamaca
+harina
+haz
+hazaña
+hebilla
+hebra
+hecho
+helado
+helio
+hembra
+herir
+hermano
+héroe
+hervir
+hielo
+hierro
+hígado
+higiene
+hijo
+himno
+historia
+hocico
+hogar
+hoguera
+hoja
+hombre
+hongo
+honor
+honra
+hora
+hormiga
+horno
+hostil
+hoyo
+hueco
+huelga
+huerta
+hueso
+huevo
+huida
+huir
+humano
+húmedo
+humilde
+humo
+hundir
+huracán
+hurto
+icono
+ideal
+idioma
+ídolo
+iglesia
+iglú
+igual
+ilegal
+ilusión
+imagen
+imán
+imitar
+impar
+imperio
+imponer
+impulso
+incapaz
+índice
+inerte
+infiel
+informe
+ingenio
+inicio
+inmenso
+inmune
+innato
+insecto
+instante
+interés
+íntimo
+intuir
+inútil
+invierno
+ira
+iris
+ironía
+isla
+islote
+jabalí
+jabón
+jamón
+jarabe
+jardín
+jarra
+jaula
+jazmín
+jefe
+jeringa
+jinete
+jornada
+joroba
+joven
+joya
+juerga
+jueves
+juez
+jugador
+jugo
+juguete
+juicio
+junco
+jungla
+junio
+juntar
+júpiter
+jurar
+justo
+juvenil
+juzgar
+kilo
+koala
+labio
+lacio
+lacra
+lado
+ladrón
+lagarto
+lágrima
+laguna
+laico
+lamer
+lámina
+lámpara
+lana
+lancha
+langosta
+lanza
+lápiz
+largo
+larva
+lástima
+lata
+látex
+latir
+laurel
+lavar
+lazo
+leal
+lección
+leche
+lector
+leer
+legión
+legumbre
+lejano
+lengua
+lento
+leña
+león
+leopardo
+lesión
+letal
+letra
+leve
+leyenda
+libertad
+libro
+licor
+líder
+lidiar
+lienzo
+liga
+ligero
+lima
+límite
+limón
+limpio
+lince
+lindo
+línea
+lingote
+lino
+linterna
+líquido
+liso
+lista
+litera
+litio
+litro
+llaga
+llama
+llanto
+llave
+llegar
+llenar
+llevar
+llorar
+llover
+lluvia
+lobo
+loción
+loco
+locura
+lógica
+logro
+lombriz
+lomo
+lonja
+lote
+lucha
+lucir
+lugar
+lujo
+luna
+lunes
+lupa
+lustro
+luto
+luz
+maceta
+macho
+madera
+madre
+maduro
+maestro
+mafia
+magia
+mago
+maíz
+maldad
+maleta
+malla
+malo
+mamá
+mambo
+mamut
+manco
+mando
+manejar
+manga
+maniquí
+manjar
+mano
+manso
+manta
+mañana
+mapa
+máquina
+mar
+marco
+marea
+marfil
+margen
+marido
+mármol
+marrón
+martes
+marzo
+masa
+máscara
+masivo
+matar
+materia
+matiz
+matriz
+máximo
+mayor
+mazorca
+mecha
+medalla
+medio
+médula
+mejilla
+mejor
+melena
+melón
+memoria
+menor
+mensaje
+mente
+menú
+mercado
+merengue
+mérito
+mes
+mesón
+meta
+meter
+método
+metro
+mezcla
+miedo
+miel
+miembro
+miga
+mil
+milagro
+militar
+millón
+mimo
+mina
+minero
+mínimo
+minuto
+miope
+mirar
+misa
+miseria
+misil
+mismo
+mitad
+mito
+mochila
+moción
+moda
+modelo
+moho
+mojar
+molde
+moler
+molino
+momento
+momia
+monarca
+moneda
+monja
+monto
+moño
+morada
+morder
+moreno
+morir
+morro
+morsa
+mortal
+mosca
+mostrar
+motivo
+mover
+móvil
+mozo
+mucho
+mudar
+mueble
+muela
+muerte
+muestra
+mugre
+mujer
+mula
+muleta
+multa
+mundo
+muñeca
+mural
+muro
+músculo
+museo
+musgo
+música
+muslo
+nácar
+nación
+nadar
+naipe
+naranja
+nariz
+narrar
+nasal
+natal
+nativo
+natural
+náusea
+naval
+nave
+navidad
+necio
+néctar
+negar
+negocio
+negro
+neón
+nervio
+neto
+neutro
+nevar
+nevera
+nicho
+nido
+niebla
+nieto
+niñez
+niño
+nítido
+nivel
+nobleza
+noche
+nómina
+noria
+norma
+norte
+nota
+noticia
+novato
+novela
+novio
+nube
+nuca
+núcleo
+nudillo
+nudo
+nuera
+nueve
+nuez
+nulo
+número
+nutria
+oasis
+obeso
+obispo
+objeto
+obra
+obrero
+observar
+obtener
+obvio
+oca
+ocaso
+océano
+ochenta
+ocho
+ocio
+ocre
+octavo
+octubre
+oculto
+ocupar
+ocurrir
+odiar
+odio
+odisea
+oeste
+ofensa
+oferta
+oficio
+ofrecer
+ogro
+oído
+oír
+ojo
+ola
+oleada
+olfato
+olivo
+olla
+olmo
+olor
+olvido
+ombligo
+onda
+onza
+opaco
+opción
+ópera
+opinar
+oponer
+optar
+óptica
+opuesto
+oración
+orador
+oral
+órbita
+orca
+orden
+oreja
+órgano
+orgía
+orgullo
+oriente
+origen
+orilla
+oro
+orquesta
+oruga
+osadía
+oscuro
+osezno
+oso
+ostra
+otoño
+otro
+oveja
+óvulo
+óxido
+oxígeno
+oyente
+ozono
+pacto
+padre
+paella
+página
+pago
+país
+pájaro
+palabra
+palco
+paleta
+pálido
+palma
+paloma
+palpar
+pan
+panal
+pánico
+pantera
+pañuelo
+papá
+papel
+papilla
+paquete
+parar
+parcela
+pared
+parir
+paro
+párpado
+parque
+párrafo
+parte
+pasar
+paseo
+pasión
+paso
+pasta
+pata
+patio
+patria
+pausa
+pauta
+pavo
+payaso
+peatón
+pecado
+pecera
+pecho
+pedal
+pedir
+pegar
+peine
+pelar
+peldaño
+pelea
+peligro
+pellejo
+pelo
+peluca
+pena
+pensar
+peñón
+peón
+peor
+pepino
+pequeño
+pera
+percha
+perder
+pereza
+perfil
+perico
+perla
+permiso
+perro
+persona
+pesa
+pesca
+pésimo
+pestaña
+pétalo
+petróleo
+pez
+pezuña
+picar
+pichón
+pie
+piedra
+pierna
+pieza
+pijama
+pilar
+piloto
+pimienta
+pino
+pintor
+pinza
+piña
+piojo
+pipa
+pirata
+pisar
+piscina
+piso
+pista
+pitón
+pizca
+placa
+plan
+plata
+playa
+plaza
+pleito
+pleno
+plomo
+pluma
+plural
+pobre
+poco
+poder
+podio
+poema
+poesía
+poeta
+polen
+policía
+pollo
+polvo
+pomada
+pomelo
+pomo
+pompa
+poner
+porción
+portal
+posada
+poseer
+posible
+poste
+potencia
+potro
+pozo
+prado
+precoz
+pregunta
+premio
+prensa
+preso
+previo
+primo
+príncipe
+prisión
+privar
+proa
+probar
+proceso
+producto
+proeza
+profesor
+programa
+prole
+promesa
+pronto
+propio
+próximo
+prueba
+público
+puchero
+pudor
+pueblo
+puerta
+puesto
+pulga
+pulir
+pulmón
+pulpo
+pulso
+puma
+punto
+puñal
+puño
+pupa
+pupila
+puré
+quedar
+queja
+quemar
+querer
+queso
+quieto
+química
+quince
+quitar
+rábano
+rabia
+rabo
+ración
+radical
+raíz
+rama
+rampa
+rancho
+rango
+rapaz
+rápido
+rapto
+rasgo
+raspa
+rato
+rayo
+raza
+razón
+reacción
+realidad
+rebaño
+rebote
+recaer
+receta
+rechazo
+recoger
+recreo
+recto
+recurso
+red
+redondo
+reducir
+reflejo
+reforma
+refrán
+refugio
+regalo
+regir
+regla
+regreso
+rehén
+reino
+reír
+reja
+relato
+relevo
+relieve
+relleno
+reloj
+remar
+remedio
+remo
+rencor
+rendir
+renta
+reparto
+repetir
+reposo
+reptil
+res
+rescate
+resina
+respeto
+resto
+resumen
+retiro
+retorno
+retrato
+reunir
+revés
+revista
+rey
+rezar
+rico
+riego
+rienda
+riesgo
+rifa
+rígido
+rigor
+rincón
+riñón
+río
+riqueza
+risa
+ritmo
+rito
+rizo
+roble
+roce
+rociar
+rodar
+rodeo
+rodilla
+roer
+rojizo
+rojo
+romero
+romper
+ron
+ronco
+ronda
+ropa
+ropero
+rosa
+rosca
+rostro
+rotar
+rubí
+rubor
+rudo
+rueda
+rugir
+ruido
+ruina
+ruleta
+rulo
+rumbo
+rumor
+ruptura
+ruta
+rutina
+sábado
+saber
+sabio
+sable
+sacar
+sagaz
+sagrado
+sala
+saldo
+salero
+salir
+salmón
+salón
+salsa
+salto
+salud
+salvar
+samba
+sanción
+sandía
+sanear
+sangre
+sanidad
+sano
+santo
+sapo
+saque
+sardina
+sartén
+sastre
+satán
+sauna
+saxofón
+sección
+seco
+secreto
+secta
+sed
+seguir
+seis
+sello
+selva
+semana
+semilla
+senda
+sensor
+señal
+señor
+separar
+sepia
+sequía
+ser
+serie
+sermón
+servir
+sesenta
+sesión
+seta
+setenta
+severo
+sexo
+sexto
+sidra
+siesta
+siete
+siglo
+signo
+sílaba
+silbar
+silencio
+silla
+símbolo
+simio
+sirena
+sistema
+sitio
+situar
+sobre
+socio
+sodio
+sol
+solapa
+soldado
+soledad
+sólido
+soltar
+solución
+sombra
+sondeo
+sonido
+sonoro
+sonrisa
+sopa
+soplar
+soporte
+sordo
+sorpresa
+sorteo
+sostén
+sótano
+suave
+subir
+suceso
+sudor
+suegra
+suelo
+sueño
+suerte
+sufrir
+sujeto
+sultán
+sumar
+superar
+suplir
+suponer
+supremo
+sur
+surco
+sureño
+surgir
+susto
+sutil
+tabaco
+tabique
+tabla
+tabú
+taco
+tacto
+tajo
+talar
+talco
+talento
+talla
+talón
+tamaño
+tambor
+tango
+tanque
+tapa
+tapete
+tapia
+tapón
+taquilla
+tarde
+tarea
+tarifa
+tarjeta
+tarot
+tarro
+tarta
+tatuaje
+tauro
+taza
+tazón
+teatro
+techo
+tecla
+técnica
+tejado
+tejer
+tejido
+tela
+teléfono
+tema
+temor
+templo
+tenaz
+tender
+tener
+tenis
+tenso
+teoría
+terapia
+terco
+término
+ternura
+terror
+tesis
+tesoro
+testigo
+tetera
+texto
+tez
+tibio
+tiburón
+tiempo
+tienda
+tierra
+tieso
+tigre
+tijera
+tilde
+timbre
+tímido
+timo
+tinta
+tío
+típico
+tipo
+tira
+tirón
+titán
+títere
+título
+tiza
+toalla
+tobillo
+tocar
+tocino
+todo
+toga
+toldo
+tomar
+tono
+tonto
+topar
+tope
+toque
+tórax
+torero
+tormenta
+torneo
+toro
+torpedo
+torre
+torso
+tortuga
+tos
+tosco
+toser
+tóxico
+trabajo
+tractor
+traer
+tráfico
+trago
+traje
+tramo
+trance
+trato
+trauma
+trazar
+trébol
+tregua
+treinta
+tren
+trepar
+tres
+tribu
+trigo
+tripa
+triste
+triunfo
+trofeo
+trompa
+tronco
+tropa
+trote
+trozo
+truco
+trueno
+trufa
+tubería
+tubo
+tuerto
+tumba
+tumor
+túnel
+túnica
+turbina
+turismo
+turno
+tutor
+ubicar
+úlcera
+umbral
+unidad
+unir
+universo
+uno
+untar
+uña
+urbano
+urbe
+urgente
+urna
+usar
+usuario
+útil
+utopía
+uva
+vaca
+vacío
+vacuna
+vagar
+vago
+vaina
+vajilla
+vale
+válido
+valle
+valor
+válvula
+vampiro
+vara
+variar
+varón
+vaso
+vecino
+vector
+vehículo
+veinte
+vejez
+vela
+velero
+veloz
+vena
+vencer
+venda
+veneno
+vengar
+venir
+venta
+venus
+ver
+verano
+verbo
+verde
+vereda
+verja
+verso
+verter
+vía
+viaje
+vibrar
+vicio
+víctima
+vida
+vídeo
+vidrio
+viejo
+viernes
+vigor
+vil
+villa
+vinagre
+vino
+viñedo
+violín
+viral
+virgo
+virtud
+visor
+víspera
+vista
+vitamina
+viudo
+vivaz
+vivero
+vivir
+vivo
+volcán
+volumen
+volver
+voraz
+votar
+voto
+voz
+vuelo
+vulgar
+yacer
+yate
+yegua
+yema
+yerno
+yeso
+yodo
+yoga
+yogur
+zafiro
+zanja
+zapato
+zarza
+zona
+zorro
+zumo
+zurdo
diff --git a/frozen_deps/pycrypto-2.6.1.dist-info/INSTALLER b/frozen_deps/pycrypto-2.6.1.dist-info/INSTALLER
new file mode 100644
index 0000000..a1b589e
--- /dev/null
+++ b/frozen_deps/pycrypto-2.6.1.dist-info/INSTALLER
@@ -0,0 +1 @@
+pip
diff --git a/frozen_deps/pycrypto-2.6.1.dist-info/METADATA b/frozen_deps/pycrypto-2.6.1.dist-info/METADATA
new file mode 100644
index 0000000..3f5b6a7
--- /dev/null
+++ b/frozen_deps/pycrypto-2.6.1.dist-info/METADATA
@@ -0,0 +1,22 @@
+Metadata-Version: 2.1
+Name: pycrypto
+Version: 2.6.1
+Summary: Cryptographic modules for Python.
+Home-page: http://www.pycrypto.org/
+Author: Dwayne C. Litzenberger
+Author-email: [email protected]
+License: UNKNOWN
+Platform: UNKNOWN
+Classifier: Development Status :: 5 - Production/Stable
+Classifier: License :: Public Domain
+Classifier: Intended Audience :: Developers
+Classifier: Operating System :: Unix
+Classifier: Operating System :: Microsoft :: Windows
+Classifier: Operating System :: MacOS :: MacOS X
+Classifier: Topic :: Security :: Cryptography
+Classifier: Programming Language :: Python :: 2
+Classifier: Programming Language :: Python :: 3
+
+UNKNOWN
+
+
diff --git a/frozen_deps/pycrypto-2.6.1.dist-info/RECORD b/frozen_deps/pycrypto-2.6.1.dist-info/RECORD
new file mode 100644
index 0000000..bcad46d
--- /dev/null
+++ b/frozen_deps/pycrypto-2.6.1.dist-info/RECORD
@@ -0,0 +1,261 @@
+Crypto/Cipher/AES.py,sha256=zdQXQvWD37SMh6Pz71Ir_nmzv7cZ7RQjCd6Tp2gE0fY,4218
+Crypto/Cipher/ARC2.py,sha256=3lRMA8tW0jBEbyXC-f_4x88MkzudgmRPZlzGpZ8032M,4916
+Crypto/Cipher/ARC4.py,sha256=HLlyx41Ao7nLwHZ5Z-vqiBPqB0udK9EcmyBnBABYWP4,4265
+Crypto/Cipher/Blowfish.py,sha256=xGVzqqoeDegd6KFyUalrTZ81jZDUbJtE2-zf8nidO2k,4459
+Crypto/Cipher/CAST.py,sha256=G9B9pHPD5A_2f_8laeMU9HtYEWu6iPrzP8kU2pNDr8E,4497
+Crypto/Cipher/DES.py,sha256=BtD_kaaAtHd4eqYUD1R12TJ5tLSlgww6kgJpkiMOcDQ,4403
+Crypto/Cipher/DES3.py,sha256=RxWw3mcYZ6YkVYGGjffQHZWqqOQTv_43s-73SyYko_w,5130
+Crypto/Cipher/PKCS1_OAEP.py,sha256=CEDbzB7NG9LJ5cUPSWkVlUIaIHtHiitGip1z2VDIXIM,9337
+Crypto/Cipher/PKCS1_v1_5.py,sha256=QefUewQFdMeqyzyNtPJWsbm12kidQuoiwMJt2JIGYZc,9109
+Crypto/Cipher/XOR.py,sha256=_tqnB-fVPSeL4UTbD58QNFCikvXACAI_yNYyUZ0veDs,2736
+Crypto/Cipher/_AES.cpython-38-x86_64-linux-gnu.so,sha256=qajgcGRe6FxLNsqyjmC0kvAM-AP5Leg5x-pJ7Ff3YDg,43640
+Crypto/Cipher/_ARC2.cpython-38-x86_64-linux-gnu.so,sha256=Ms1i0EgMSg1u0l0PqooApjfXBXrPdBa4BNvC5JtpXrQ,26904
+Crypto/Cipher/_ARC4.cpython-38-x86_64-linux-gnu.so,sha256=Z8XpYrkIBzeb3bC8G2rVetIbXT-YBEPH0bYACLrL6Nc,18064
+Crypto/Cipher/_Blowfish.cpython-38-x86_64-linux-gnu.so,sha256=_Kj6oU_kwvtnXoZPvtQ6bbvgqan7jtWWDpChUQSu8-A,35368
+Crypto/Cipher/_CAST.cpython-38-x86_64-linux-gnu.so,sha256=74aSGGReYsFWAYaxdzvQvFGArb3ByJUp9fYFOsutwi0,35320
+Crypto/Cipher/_DES.cpython-38-x86_64-linux-gnu.so,sha256=nAbiA_48cuQD5rPQkyIflgckbONIUPlOF5BqLL55CnU,68560
+Crypto/Cipher/_DES3.cpython-38-x86_64-linux-gnu.so,sha256=B5Z5TAcZldhS_Rx0_NvlXpyC697IGYIOgyybb9GjFco,68560
+Crypto/Cipher/_XOR.cpython-38-x86_64-linux-gnu.so,sha256=6yZ52WaICl8oqjJoED3V34JxwnX44C_INVBLjluPqpA,18096
+Crypto/Cipher/__init__.py,sha256=XljqRT7D0kyJEpntdMQbA8n68gWwLQedxzc1T8VygYU,3440
+Crypto/Cipher/__pycache__/AES.cpython-38.pyc,,
+Crypto/Cipher/__pycache__/ARC2.cpython-38.pyc,,
+Crypto/Cipher/__pycache__/ARC4.cpython-38.pyc,,
+Crypto/Cipher/__pycache__/Blowfish.cpython-38.pyc,,
+Crypto/Cipher/__pycache__/CAST.cpython-38.pyc,,
+Crypto/Cipher/__pycache__/DES.cpython-38.pyc,,
+Crypto/Cipher/__pycache__/DES3.cpython-38.pyc,,
+Crypto/Cipher/__pycache__/PKCS1_OAEP.cpython-38.pyc,,
+Crypto/Cipher/__pycache__/PKCS1_v1_5.cpython-38.pyc,,
+Crypto/Cipher/__pycache__/XOR.cpython-38.pyc,,
+Crypto/Cipher/__pycache__/__init__.cpython-38.pyc,,
+Crypto/Cipher/__pycache__/blockalgo.cpython-38.pyc,,
+Crypto/Cipher/blockalgo.py,sha256=iTMWpnhMhwMD1SqyDduyB9B-ueLAKGLiW-oD2Vt-xms,12596
+Crypto/Hash/HMAC.py,sha256=2lpshwFp5OGeymb3D-zirgjDOg6QIdTvWnJAmnJ8xk0,7309
+Crypto/Hash/MD2.py,sha256=AVkf-DC5TPJysc6qXBNfSTWgz-RVIKP8adbOUZBS914,2734
+Crypto/Hash/MD4.py,sha256=4LNMbJUmXeB7Dg24FrtzyZaYpBhHKD3qBsFzsENFAQE,2716
+Crypto/Hash/MD5.py,sha256=tpnoyAq7YDeCfJVMXc2U6rm4R0pCMjLzAF2lMEmDG24,2863
+Crypto/Hash/RIPEMD.py,sha256=VGl2ej_XG3PPByfduL8KNy2g_W45SYukmE4Ww5jUhyg,3005
+Crypto/Hash/SHA.py,sha256=IgvTUNC1j1Y-ITKyKhbZBLSaZGHSFTY_nVEUThXVvbg,2841
+Crypto/Hash/SHA224.py,sha256=HNBj-5K5W9o6hwROHKtan6TzRPM72jGNIxEEKEF0r8o,2851
+Crypto/Hash/SHA256.py,sha256=zUuyPbvEM519lyc9yG1yF9J_WD9QaQCa1wzfDWPwcNw,2852
+Crypto/Hash/SHA384.py,sha256=W7QZ-jYyCA1_vL2IeMQyhtXdCnuuk9KNEwEmwjzHoW8,2853
+Crypto/Hash/SHA512.py,sha256=_5Bk0r-48hJuNMezQYuWemlbGGPW2v4OqHVTYUmMvCg,2850
+Crypto/Hash/_MD2.cpython-38-x86_64-linux-gnu.so,sha256=-YIEL7BIqS1buS_x2LYTYZup3ANqy5PX5Yz37frUyLM,18464
+Crypto/Hash/_MD4.cpython-38-x86_64-linux-gnu.so,sha256=zbK4osbY37dLzSNUPKN6AgxQSZ6YtuVgyGIGuWVj334,18552
+Crypto/Hash/_RIPEMD160.cpython-38-x86_64-linux-gnu.so,sha256=wtjyzmtTp_rYQBvJFviVfZpsAvlk6D-4t_zkKIXUWvI,22888
+Crypto/Hash/_SHA224.cpython-38-x86_64-linux-gnu.so,sha256=4LvpSq7MmkNpZsMf7speKCxgUh_b10plytYXflrBt7Y,18496
+Crypto/Hash/_SHA256.cpython-38-x86_64-linux-gnu.so,sha256=Xa5v4RySkT_tHytuUBm9A5NK90108oebNDxnzePepuk,18496
+Crypto/Hash/_SHA384.cpython-38-x86_64-linux-gnu.so,sha256=URhwdl1hoK0euL23vtoj3N9Jw2Gem3kVqN20nXAbCdU,22592
+Crypto/Hash/_SHA512.cpython-38-x86_64-linux-gnu.so,sha256=uA5QGreT8Ufq54CkniZdr5ayeBhBzTe5BHlyxI0BPY4,22592
+Crypto/Hash/__init__.py,sha256=QtJ_3oI1ELyZ1gm8Gqhli_1xT4CQCECWLaq094HonN4,2432
+Crypto/Hash/__pycache__/HMAC.cpython-38.pyc,,
+Crypto/Hash/__pycache__/MD2.cpython-38.pyc,,
+Crypto/Hash/__pycache__/MD4.cpython-38.pyc,,
+Crypto/Hash/__pycache__/MD5.cpython-38.pyc,,
+Crypto/Hash/__pycache__/RIPEMD.cpython-38.pyc,,
+Crypto/Hash/__pycache__/SHA.cpython-38.pyc,,
+Crypto/Hash/__pycache__/SHA224.cpython-38.pyc,,
+Crypto/Hash/__pycache__/SHA256.cpython-38.pyc,,
+Crypto/Hash/__pycache__/SHA384.cpython-38.pyc,,
+Crypto/Hash/__pycache__/SHA512.cpython-38.pyc,,
+Crypto/Hash/__pycache__/__init__.cpython-38.pyc,,
+Crypto/Hash/__pycache__/hashalgo.cpython-38.pyc,,
+Crypto/Hash/hashalgo.py,sha256=uNOiQseIAw-NXKIwjAomwA3ZdjLHBnzES0GD3Xh6hu8,3984
+Crypto/Protocol/AllOrNothing.py,sha256=szBTydYgyxmPbGbHXv-uthp5rO4XA0N0rgKRGF3FmvM,11959
+Crypto/Protocol/Chaffing.py,sha256=hkUbn2R4nKjQlMEy9CgJ4a4qvuqxjMCz9quqHrYBuJU,10280
+Crypto/Protocol/KDF.py,sha256=98bWbmx1ctD65OHxTNhxqX2dE58TIAXl5p2PCkEPaFo,5069
+Crypto/Protocol/__init__.py,sha256=nIuNk6tS9Xm4HsOhkQPIyG_VMCgT2MwGsZja2sjXrtg,1573
+Crypto/Protocol/__pycache__/AllOrNothing.cpython-38.pyc,,
+Crypto/Protocol/__pycache__/Chaffing.cpython-38.pyc,,
+Crypto/Protocol/__pycache__/KDF.cpython-38.pyc,,
+Crypto/Protocol/__pycache__/__init__.cpython-38.pyc,,
+Crypto/PublicKey/DSA.py,sha256=jXpxkko8IrvH_YfGGEl3idVVpfTbllAjkpliz635Iok,13689
+Crypto/PublicKey/ElGamal.py,sha256=HVZfYJylzakvAJ83W0VxVyyVoUP-eGl5Z6_WM5kYaog,13212
+Crypto/PublicKey/RSA.py,sha256=6DeyV2z4H5wChNI622FyT0M3czDgPX0tUlQrIFzimII,29893
+Crypto/PublicKey/_DSA.py,sha256=m-dMnmKqkw4uOXSNTwf7braa_-eoWuRDcmjPWKQcOVI,3470
+Crypto/PublicKey/_RSA.py,sha256=dFMnO1k9N1rijktx2OFCJv5xzd_oYVepVSWNRv0fkmQ,2760
+Crypto/PublicKey/__init__.py,sha256=dTFZbenEp98vElmrk9vuT2X9IqL3jHHKtq4pITpJZTU,1876
+Crypto/PublicKey/__pycache__/DSA.cpython-38.pyc,,
+Crypto/PublicKey/__pycache__/ElGamal.cpython-38.pyc,,
+Crypto/PublicKey/__pycache__/RSA.cpython-38.pyc,,
+Crypto/PublicKey/__pycache__/_DSA.cpython-38.pyc,,
+Crypto/PublicKey/__pycache__/_RSA.cpython-38.pyc,,
+Crypto/PublicKey/__pycache__/__init__.cpython-38.pyc,,
+Crypto/PublicKey/__pycache__/_slowmath.cpython-38.pyc,,
+Crypto/PublicKey/__pycache__/pubkey.cpython-38.pyc,,
+Crypto/PublicKey/_fastmath.cpython-38-x86_64-linux-gnu.so,sha256=wVmNfdPPprXNgY8Db86ZywNBsLIGDjaKCuWmE56Sy-s,78864
+Crypto/PublicKey/_slowmath.py,sha256=bZTi0MEViDieJfhsEnKRatt86yZ7V-MToW3viDDT3c4,6409
+Crypto/PublicKey/pubkey.py,sha256=swCmQTk5oHjODolNoO78znO1vlb044LgT2EcvKWEXW4,8088
+Crypto/Random/Fortuna/FortunaAccumulator.py,sha256=LJ9Npmoq9uPyCLjEAw0cceitozqKLPHsIHfHsjGc4LA,6788
+Crypto/Random/Fortuna/FortunaGenerator.py,sha256=GfaMASoqHTeCPW9lPJ2cuIe4z245H9XrykNMS-BvFJU,5270
+Crypto/Random/Fortuna/SHAd256.py,sha256=BNLUDG0QSNqlBpmorD8Qv583LTinuAgpAi2HgThsaag,3098
+Crypto/Random/Fortuna/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
+Crypto/Random/Fortuna/__pycache__/FortunaAccumulator.cpython-38.pyc,,
+Crypto/Random/Fortuna/__pycache__/FortunaGenerator.cpython-38.pyc,,
+Crypto/Random/Fortuna/__pycache__/SHAd256.cpython-38.pyc,,
+Crypto/Random/Fortuna/__pycache__/__init__.cpython-38.pyc,,
+Crypto/Random/OSRNG/__init__.py,sha256=6Q_9uzT3pk7G_Wk97D8Ze_JlFvSG2owPxJkyd24xP5E,1542
+Crypto/Random/OSRNG/__pycache__/__init__.cpython-38.pyc,,
+Crypto/Random/OSRNG/__pycache__/fallback.cpython-38.pyc,,
+Crypto/Random/OSRNG/__pycache__/posix.cpython-38.pyc,,
+Crypto/Random/OSRNG/__pycache__/rng_base.cpython-38.pyc,,
+Crypto/Random/OSRNG/fallback.py,sha256=MH99pYPRTmw7m8KorK2xeSwO7xrkLFor76RMNhY5KQg,1521
+Crypto/Random/OSRNG/posix.py,sha256=eTOTZJX9ZrCVc9Wz5Zw_Q7yaCe4iIeaq7O2P7jLv5pM,2838
+Crypto/Random/OSRNG/rng_base.py,sha256=GVjP55P4VRBk7oO_FKTjAGrc83O2NuYuOWVlG9C0EmQ,2867
+Crypto/Random/_UserFriendlyRNG.py,sha256=-K-jbkaPjn7reXc6gplEnYGq5A9lDmf1NiCXipdgK2w,7621
+Crypto/Random/__init__.py,sha256=L6NbHyEB2epH7WRsz3M6_LF9z7_eOnJjDOFH4opFzkg,1669
+Crypto/Random/__pycache__/_UserFriendlyRNG.cpython-38.pyc,,
+Crypto/Random/__pycache__/__init__.cpython-38.pyc,,
+Crypto/Random/__pycache__/random.cpython-38.pyc,,
+Crypto/Random/random.py,sha256=eurKE-iEuqRp3vu39Gpiux67zfl5CJ8OGvnrTd8nWb4,5235
+Crypto/SelfTest/Cipher/__init__.py,sha256=QCrjmEJc9HvASt_x1TFxGvuWXJ0YTLKsVsLTG-V3E4E,2401
+Crypto/SelfTest/Cipher/__pycache__/__init__.cpython-38.pyc,,
+Crypto/SelfTest/Cipher/__pycache__/common.cpython-38.pyc,,
+Crypto/SelfTest/Cipher/__pycache__/test_AES.cpython-38.pyc,,
+Crypto/SelfTest/Cipher/__pycache__/test_ARC2.cpython-38.pyc,,
+Crypto/SelfTest/Cipher/__pycache__/test_ARC4.cpython-38.pyc,,
+Crypto/SelfTest/Cipher/__pycache__/test_Blowfish.cpython-38.pyc,,
+Crypto/SelfTest/Cipher/__pycache__/test_CAST.cpython-38.pyc,,
+Crypto/SelfTest/Cipher/__pycache__/test_DES.cpython-38.pyc,,
+Crypto/SelfTest/Cipher/__pycache__/test_DES3.cpython-38.pyc,,
+Crypto/SelfTest/Cipher/__pycache__/test_XOR.cpython-38.pyc,,
+Crypto/SelfTest/Cipher/__pycache__/test_pkcs1_15.cpython-38.pyc,,
+Crypto/SelfTest/Cipher/__pycache__/test_pkcs1_oaep.cpython-38.pyc,,
+Crypto/SelfTest/Cipher/common.py,sha256=YrMmMD1WSore4F24DC_vxJKvAHpBJLHce-g4NXYzIDY,16568
+Crypto/SelfTest/Cipher/test_AES.py,sha256=nvJaazjoV6kOcXHAWfNjb326Ikb5wZitMaRPwWeth1U,79977
+Crypto/SelfTest/Cipher/test_ARC2.py,sha256=UDWMnNHxGfoaSViVbcPGXs3NomsW2zxKAt2xcFxjIw4,4947
+Crypto/SelfTest/Cipher/test_ARC4.py,sha256=-iqIeQ6i9nR2M_YaME3QEuAFxhhUpelNlg3aCsiftgE,3547
+Crypto/SelfTest/Cipher/test_Blowfish.py,sha256=DLT3g75NF_eeaVaueRCQ2n4_XxJYd16rBouRsS7FIzU,5833
+Crypto/SelfTest/Cipher/test_CAST.py,sha256=YY6x3LJdrJbJgazEJxaHoOxlzfMzdCND8mUJZIZoDRs,1978
+Crypto/SelfTest/Cipher/test_DES.py,sha256=cG4o_9ckWsJvhSZiXU9I6jLBqdxaHBS2V73JlDt9bn4,15011
+Crypto/SelfTest/Cipher/test_DES3.py,sha256=dtR_aOZwlvUgppqFLemz0A6bfyUtiY09k0Sr-bQwhW0,15560
+Crypto/SelfTest/Cipher/test_XOR.py,sha256=Eq6eDUqae8ju8olSN5m9arIt4X6vbqCFmC-ev3htjHM,2539
+Crypto/SelfTest/Cipher/test_pkcs1_15.py,sha256=oLEYASebuOK3ruYz91ZThY8t07Sh04zoiuCfJ9K-UY0,7342
+Crypto/SelfTest/Cipher/test_pkcs1_oaep.py,sha256=uDgrJmzoJqIXeizzJDqKW2w0K8RGSp6NtE2aSIB5XSQ,17253
+Crypto/SelfTest/Hash/__init__.py,sha256=PwY0AUVBF3JZL0jyzajD_i5R7K6HatO5fLNuCqnSbHk,2518
+Crypto/SelfTest/Hash/__pycache__/__init__.cpython-38.pyc,,
+Crypto/SelfTest/Hash/__pycache__/common.cpython-38.pyc,,
+Crypto/SelfTest/Hash/__pycache__/test_HMAC.cpython-38.pyc,,
+Crypto/SelfTest/Hash/__pycache__/test_MD2.cpython-38.pyc,,
+Crypto/SelfTest/Hash/__pycache__/test_MD4.cpython-38.pyc,,
+Crypto/SelfTest/Hash/__pycache__/test_MD5.cpython-38.pyc,,
+Crypto/SelfTest/Hash/__pycache__/test_RIPEMD.cpython-38.pyc,,
+Crypto/SelfTest/Hash/__pycache__/test_SHA.cpython-38.pyc,,
+Crypto/SelfTest/Hash/__pycache__/test_SHA224.cpython-38.pyc,,
+Crypto/SelfTest/Hash/__pycache__/test_SHA256.cpython-38.pyc,,
+Crypto/SelfTest/Hash/__pycache__/test_SHA384.cpython-38.pyc,,
+Crypto/SelfTest/Hash/__pycache__/test_SHA512.cpython-38.pyc,,
+Crypto/SelfTest/Hash/common.py,sha256=0z6RQTvJ_hs-2nL-4NvWgW1TKib6urQjrlDb1tipYtU,7076
+Crypto/SelfTest/Hash/test_HMAC.py,sha256=An7fj5tVxCPoAkFWpTkteliVOTxEJ6wbxQCOLoCE-90,8199
+Crypto/SelfTest/Hash/test_MD2.py,sha256=SU0Bh-hD1BUwbZ1wmK6yOFIx2wkqdjIOW5k8HANxDQA,2369
+Crypto/SelfTest/Hash/test_MD4.py,sha256=xsr0oHX-vFlF6s4u0zK7VuyUBytbiFker7HwREZiCEw,2369
+Crypto/SelfTest/Hash/test_MD5.py,sha256=bd8-oLvo4Zbjk5VI-LiO1NWutLHGCQz8c2pdVm0PuEA,2369
+Crypto/SelfTest/Hash/test_RIPEMD.py,sha256=1uTfKvlGFSin5Zwkb5-EpDN9Hqju5RhBJE1mNzY8qGo,2686
+Crypto/SelfTest/Hash/test_SHA.py,sha256=OPYddyrd0jZwj7iDvEeLHwOcY39mLgg4DxEwOBI4LZo,2312
+Crypto/SelfTest/Hash/test_SHA224.py,sha256=pJv-BVv1U6SbVXuq4qurueae9Gv6ExwjlfhgF_nv8pA,2582
+Crypto/SelfTest/Hash/test_SHA256.py,sha256=lvDWuTKYIqVi07XsWiczsuETvw_MOGJmKT9ASatwpAc,3662
+Crypto/SelfTest/Hash/test_SHA384.py,sha256=nRNxUd0ji_iGhZeelFTS1BtC_7yKbO49oVW2GlKvM7I,2763
+Crypto/SelfTest/Hash/test_SHA512.py,sha256=teZzqGj9pJ1fY2XmMtgJiZRvcvngAourOH6Ka_nL2Hc,2850
+Crypto/SelfTest/Protocol/__init__.py,sha256=n0jyxv7F-g4upKbUa-17TvOvDDNNgR9FAsZPT2pRkf8,1751
+Crypto/SelfTest/Protocol/__pycache__/__init__.cpython-38.pyc,,
+Crypto/SelfTest/Protocol/__pycache__/test_AllOrNothing.cpython-38.pyc,,
+Crypto/SelfTest/Protocol/__pycache__/test_KDF.cpython-38.pyc,,
+Crypto/SelfTest/Protocol/__pycache__/test_chaffing.cpython-38.pyc,,
+Crypto/SelfTest/Protocol/__pycache__/test_rfc1751.cpython-38.pyc,,
+Crypto/SelfTest/Protocol/test_AllOrNothing.py,sha256=9ZTaJ2VE1OqF_RxjKZLo_Geoqg_-26Z_N5hrPk_Dpwc,3024
+Crypto/SelfTest/Protocol/test_KDF.py,sha256=SAIrJVGiqZ5WWWi7xm90tqMBzTySWT4nA16ERp7VkgY,3827
+Crypto/SelfTest/Protocol/test_chaffing.py,sha256=CdumC2qHo_DSlv0NlgMX2Rh_n_IKiL1xxBLJYlQiWu8,2972
+Crypto/SelfTest/Protocol/test_rfc1751.py,sha256=LR3M9XLk_sxOyapPq32PEf93SUMwErFwwzlHNKhUazg,2208
+Crypto/SelfTest/PublicKey/__init__.py,sha256=LwAO13YrBCiPBG8n2EMD4pTH3JBvCJU5xEbWrkcFw5o,1842
+Crypto/SelfTest/PublicKey/__pycache__/__init__.cpython-38.pyc,,
+Crypto/SelfTest/PublicKey/__pycache__/test_DSA.cpython-38.pyc,,
+Crypto/SelfTest/PublicKey/__pycache__/test_ElGamal.cpython-38.pyc,,
+Crypto/SelfTest/PublicKey/__pycache__/test_RSA.cpython-38.pyc,,
+Crypto/SelfTest/PublicKey/__pycache__/test_importKey.cpython-38.pyc,,
+Crypto/SelfTest/PublicKey/test_DSA.py,sha256=bD0J8xd60_K0-V4AEpMGS5gxNpE-43KRDJWLhEKZNyg,9861
+Crypto/SelfTest/PublicKey/test_ElGamal.py,sha256=JrUGohyq8mtTfYFo6aBrPpliybGZ1sO3R9aHjr_j3qM,8511
+Crypto/SelfTest/PublicKey/test_RSA.py,sha256=uHLl_bNVYuWtvgG8vZiySj-s5hKb7BgbcfmzyQGVLRo,16563
+Crypto/SelfTest/PublicKey/test_importKey.py,sha256=yG4mHgEVlUBkYnsLkqw8MKPRzXLJ6i-oIy2A57k1NTw,14907
+Crypto/SelfTest/Random/Fortuna/__init__.py,sha256=0jEzcC4VxLRAnSroCV-xkteVlO9sW8c_2-nldKelw5g,1825
+Crypto/SelfTest/Random/Fortuna/__pycache__/__init__.cpython-38.pyc,,
+Crypto/SelfTest/Random/Fortuna/__pycache__/test_FortunaAccumulator.cpython-38.pyc,,
+Crypto/SelfTest/Random/Fortuna/__pycache__/test_FortunaGenerator.cpython-38.pyc,,
+Crypto/SelfTest/Random/Fortuna/__pycache__/test_SHAd256.cpython-38.pyc,,
+Crypto/SelfTest/Random/Fortuna/test_FortunaAccumulator.py,sha256=I0d-g7-rAKwJqMD4jMHo-DNLvv7j0_PPJU3z9Rci0xE,8655
+Crypto/SelfTest/Random/Fortuna/test_FortunaGenerator.py,sha256=aVxRxI7009xM0IjUt2gmF6ZiZJuZpWAXZELeYZWAezM,3506
+Crypto/SelfTest/Random/Fortuna/test_SHAd256.py,sha256=hCo1zmP1VE90tw1Xa5zNDhz42KY6Zf1A6yEMlIQR5R0,2419
+Crypto/SelfTest/Random/OSRNG/__init__.py,sha256=GHy35y5OsEdAve1otasx-d1P6UnAI9AcWM3pslNHIQQ,2082
+Crypto/SelfTest/Random/OSRNG/__pycache__/__init__.cpython-38.pyc,,
+Crypto/SelfTest/Random/OSRNG/__pycache__/test_fallback.cpython-38.pyc,,
+Crypto/SelfTest/Random/OSRNG/__pycache__/test_generic.cpython-38.pyc,,
+Crypto/SelfTest/Random/OSRNG/__pycache__/test_nt.cpython-38.pyc,,
+Crypto/SelfTest/Random/OSRNG/__pycache__/test_posix.cpython-38.pyc,,
+Crypto/SelfTest/Random/OSRNG/__pycache__/test_winrandom.cpython-38.pyc,,
+Crypto/SelfTest/Random/OSRNG/test_fallback.py,sha256=pReymeE8atbWeOiqmLu3M66K07ZyWaUhnTfMT1YI5kQ,1795
+Crypto/SelfTest/Random/OSRNG/test_generic.py,sha256=86QgZM4AcC_HMpXuyuvwOw2olhE4i--8dKDjXRA5_V8,1746
+Crypto/SelfTest/Random/OSRNG/test_nt.py,sha256=qpxL-Er7veLxAFHtgeqVVlpu7aGbKF3Wdt0xayfnYBQ,1764
+Crypto/SelfTest/Random/OSRNG/test_posix.py,sha256=5f52SxQg1dAPjcOPY0Gltlg5HpJkQqHKLJ9zlG3JKlY,1777
+Crypto/SelfTest/Random/OSRNG/test_winrandom.py,sha256=84h5E-vE6UBA55tBqk9m3q30jBXQzXswGE_RPEne5Vo,1777
+Crypto/SelfTest/Random/__init__.py,sha256=2lrY6di7ijeWWM9w4GX-XEepRuSY28aorzVz1X4K2_U,1973
+Crypto/SelfTest/Random/__pycache__/__init__.cpython-38.pyc,,
+Crypto/SelfTest/Random/__pycache__/test__UserFriendlyRNG.cpython-38.pyc,,
+Crypto/SelfTest/Random/__pycache__/test_random.cpython-38.pyc,,
+Crypto/SelfTest/Random/__pycache__/test_rpoolcompat.cpython-38.pyc,,
+Crypto/SelfTest/Random/test__UserFriendlyRNG.py,sha256=AIuP_vWn3skmVA9dxhfgYOLtMeVvdMPADcMFfTn2Lmo,5672
+Crypto/SelfTest/Random/test_random.py,sha256=BTA8EJQ2Q7DGyzoocXDOuPikskSM1xKkoEnAZsp50Ok,7129
+Crypto/SelfTest/Random/test_rpoolcompat.py,sha256=py3o_QmgRvX6tcvEp7Je6XnEBcVO_pOi-GXvgZmN85w,2030
+Crypto/SelfTest/Signature/__init__.py,sha256=FMHyPlOIGj67IkoPFun0UHpnc_1koKhfuQfw-mxhn44,1528
+Crypto/SelfTest/Signature/__pycache__/__init__.cpython-38.pyc,,
+Crypto/SelfTest/Signature/__pycache__/test_pkcs1_15.cpython-38.pyc,,
+Crypto/SelfTest/Signature/__pycache__/test_pkcs1_pss.cpython-38.pyc,,
+Crypto/SelfTest/Signature/test_pkcs1_15.py,sha256=_b-Mab4CdXRIALdB8cWGqFLqgILZAUScEtfiWViuGb8,9471
+Crypto/SelfTest/Signature/test_pkcs1_pss.py,sha256=4CFckbL8OvCNYQgyB8RLueT6yDT6OTqSD53yOQtc4B4,20565
+Crypto/SelfTest/Util/__init__.py,sha256=TdCWQ_hp0YSq6Dna6rsrYz-VJpBKBcEG9LzqKev-v9Y,1743
+Crypto/SelfTest/Util/__pycache__/__init__.cpython-38.pyc,,
+Crypto/SelfTest/Util/__pycache__/test_Counter.cpython-38.pyc,,
+Crypto/SelfTest/Util/__pycache__/test_asn1.cpython-38.pyc,,
+Crypto/SelfTest/Util/__pycache__/test_number.cpython-38.pyc,,
+Crypto/SelfTest/Util/__pycache__/test_winrandom.cpython-38.pyc,,
+Crypto/SelfTest/Util/test_Counter.py,sha256=WWliRgH8RVIIag6BpG0bSYjH4YL_0azSrEiRt-qgmT4,7087
+Crypto/SelfTest/Util/test_asn1.py,sha256=qRyogItInITbzbAftBJ9Mos1ZSbKjOUSRNfJP_4fVSk,10187
+Crypto/SelfTest/Util/test_number.py,sha256=BTet6CfyOh-3zIBAS8W-O1W4dpIzP6XvxdC9IExjhng,12862
+Crypto/SelfTest/Util/test_winrandom.py,sha256=HvBPZAjbk_1rQiq5ySHCPZQ46OFrXFo8EsCSZSWK40I,1772
+Crypto/SelfTest/__init__.py,sha256=M1NKM4hO2MmSQbI8KTagsloskp0OHJVlUEOTTaYPisQ,3412
+Crypto/SelfTest/__pycache__/__init__.cpython-38.pyc,,
+Crypto/SelfTest/__pycache__/st_common.cpython-38.pyc,,
+Crypto/SelfTest/st_common.py,sha256=qi1uOlmw06U32DD9tWGYZF9A3oA7PJfxWVbx4d8MxrE,2142
+Crypto/Signature/PKCS1_PSS.py,sha256=t6DUy5bgUp6guNII6rmRJRgxOFZa6Vd_foIfiRsA88U,12189
+Crypto/Signature/PKCS1_v1_5.py,sha256=4zF1UXx46uN43K7jRajJZFU8IprxYG4ualoGhES0dy8,8637
+Crypto/Signature/__init__.py,sha256=edI2zDF9wZnt2tGUMl-5QYwsHdspZTXsCot2ewsvyl0,1202
+Crypto/Signature/__pycache__/PKCS1_PSS.cpython-38.pyc,,
+Crypto/Signature/__pycache__/PKCS1_v1_5.cpython-38.pyc,,
+Crypto/Signature/__pycache__/__init__.cpython-38.pyc,,
+Crypto/Util/Counter.py,sha256=wjed6nTp3jmEWXfmYPpUCSjsPDoa6WmiUlvSXhSQvMw,5156
+Crypto/Util/RFC1751.py,sha256=pm9iilAnohlNOVFwowxXCbkWKUSFticbzxQlzdBGDvk,21208
+Crypto/Util/__init__.py,sha256=RygfvkDs72Jet2S2jN7zwtkWOSVTHsSVJ6RVBvp4ugs,1507
+Crypto/Util/__pycache__/Counter.cpython-38.pyc,,
+Crypto/Util/__pycache__/RFC1751.cpython-38.pyc,,
+Crypto/Util/__pycache__/__init__.cpython-38.pyc,,
+Crypto/Util/__pycache__/_number_new.cpython-38.pyc,,
+Crypto/Util/__pycache__/asn1.cpython-38.pyc,,
+Crypto/Util/__pycache__/number.cpython-38.pyc,,
+Crypto/Util/__pycache__/py3compat.cpython-38.pyc,,
+Crypto/Util/__pycache__/randpool.cpython-38.pyc,,
+Crypto/Util/__pycache__/winrandom.cpython-38.pyc,,
+Crypto/Util/_counter.cpython-38-x86_64-linux-gnu.so,sha256=-8wyPt4xwYdGeHnfTmzYJqjesu5UHvvZTdlEaa0QNzU,22856
+Crypto/Util/_number_new.py,sha256=DMlYTwTLefBEAMX139gjP9uDdvyamloCC0kc2oaNQYg,3976
+Crypto/Util/asn1.py,sha256=2eg7T1XMaNDo340pAq9BuO9Hp_1mYf5cWgkfFW97bGQ,12733
+Crypto/Util/number.py,sha256=P_MYzcU9oVwwJAjCQ_AAYmqPsTZrWf-G2j5TiHkdCts,95469
+Crypto/Util/py3compat.py,sha256=e-a4R1jOOvsNeb5CHqNPUhEKa-Qa0Ozwhyu4iwcbDFE,3908
+Crypto/Util/randpool.py,sha256=8qSQTg_aPf6RUHlCNZJQXQ5LZClvydNWaFqEDaG-FEE,2768
+Crypto/Util/strxor.cpython-38-x86_64-linux-gnu.so,sha256=xfCPtgkJehM3uVE4aEViOVeRF0jl4K42PgEI1iJ64ts,16784
+Crypto/Util/winrandom.py,sha256=IhpE9uIOdNmWXmjzSICrTKEVoP0XOxasaTi4m2afB5I,1196
+Crypto/__init__.py,sha256=Bi_KjWxdfCyFeRx_abV-wr3o89SsH7c9fEwx0oLgjiA,1992
+Crypto/__pycache__/__init__.cpython-38.pyc,,
+Crypto/__pycache__/pct_warnings.cpython-38.pyc,,
+Crypto/pct_warnings.py,sha256=Uc2DAGSs6rZGMssd2SNkLzpF-h0CwwH288Alv3SzCeM,2295
+pycrypto-2.6.1.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4
+pycrypto-2.6.1.dist-info/METADATA,sha256=1l-9AVgkccANEeeXZ29e95C1BWovYM_VeUb1T4Lat0g,656
+pycrypto-2.6.1.dist-info/RECORD,,
+pycrypto-2.6.1.dist-info/WHEEL,sha256=TpFVeXF_cAlV118WSIPWtjqW7nPvzoOw-49FmS3fDKQ,103
+pycrypto-2.6.1.dist-info/top_level.txt,sha256=-W2wTtkxc1QnPUPRqBZ0bMwrhD8xRD13HIobFX-wDOs,7
diff --git a/frozen_deps/pycrypto-2.6.1.dist-info/WHEEL b/frozen_deps/pycrypto-2.6.1.dist-info/WHEEL
new file mode 100644
index 0000000..d193dea
--- /dev/null
+++ b/frozen_deps/pycrypto-2.6.1.dist-info/WHEEL
@@ -0,0 +1,5 @@
+Wheel-Version: 1.0
+Generator: bdist_wheel (0.34.2)
+Root-Is-Purelib: false
+Tag: cp38-cp38-linux_x86_64
+
diff --git a/frozen_deps/pycrypto-2.6.1.dist-info/top_level.txt b/frozen_deps/pycrypto-2.6.1.dist-info/top_level.txt
new file mode 100644
index 0000000..e6645e7
--- /dev/null
+++ b/frozen_deps/pycrypto-2.6.1.dist-info/top_level.txt
@@ -0,0 +1 @@
+Crypto
diff --git a/frozen_deps/pysha3-1.0.2.dist-info/INSTALLER b/frozen_deps/pysha3-1.0.2.dist-info/INSTALLER
new file mode 100644
index 0000000..a1b589e
--- /dev/null
+++ b/frozen_deps/pysha3-1.0.2.dist-info/INSTALLER
@@ -0,0 +1 @@
+pip
diff --git a/frozen_deps/pysha3-1.0.2.dist-info/LICENSE b/frozen_deps/pysha3-1.0.2.dist-info/LICENSE
new file mode 100644
index 0000000..311690c
--- /dev/null
+++ b/frozen_deps/pysha3-1.0.2.dist-info/LICENSE
@@ -0,0 +1,49 @@
+PYTHON SOFTWARE FOUNDATION LICENSE VERSION 2
+--------------------------------------------
+
+1. This LICENSE AGREEMENT is between the Python Software Foundation
+("PSF"), and the Individual or Organization ("Licensee") accessing and
+otherwise using this software ("Python") in source or binary form and
+its associated documentation.
+
+2. Subject to the terms and conditions of this License Agreement, PSF
+hereby grants Licensee a nonexclusive, royalty-free, world-wide
+license to reproduce, analyze, test, perform and/or display publicly,
+prepare derivative works, distribute, and otherwise use Python
+alone or in any derivative version, provided, however, that PSF's
+License Agreement and PSF's notice of copyright, i.e., "Copyright (c)
+2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 Python Software Foundation;
+All Rights Reserved" are retained in Python alone or in any derivative
+version prepared by Licensee.
+
+3. In the event Licensee prepares a derivative work that is based on
+or incorporates Python or any part thereof, and wants to make
+the derivative work available to others as provided herein, then
+Licensee hereby agrees to include in any such work a brief summary of
+the changes made to Python.
+
+4. PSF is making Python available to Licensee on an "AS IS"
+basis. PSF MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR
+IMPLIED. BY WAY OF EXAMPLE, BUT NOT LIMITATION, PSF MAKES NO AND
+DISCLAIMS ANY REPRESENTATION OR WARRANTY OF MERCHANTABILITY OR FITNESS
+FOR ANY PARTICULAR PURPOSE OR THAT THE USE OF PYTHON WILL NOT
+INFRINGE ANY THIRD PARTY RIGHTS.
+
+5. PSF SHALL NOT BE LIABLE TO LICENSEE OR ANY OTHER USERS OF PYTHON
+FOR ANY INCIDENTAL, SPECIAL, OR CONSEQUENTIAL DAMAGES OR LOSS AS
+A RESULT OF MODIFYING, DISTRIBUTING, OR OTHERWISE USING PYTHON,
+OR ANY DERIVATIVE THEREOF, EVEN IF ADVISED OF THE POSSIBILITY THEREOF.
+
+6. This License Agreement will automatically terminate upon a material
+breach of its terms and conditions.
+
+7. Nothing in this License Agreement shall be deemed to create any
+relationship of agency, partnership, or joint venture between PSF and
+Licensee. This License Agreement does not grant permission to use PSF
+trademarks or trade name in a trademark sense to endorse or promote
+products or services of Licensee, or any third party.
+
+8. By copying, installing or otherwise using Python, Licensee
+agrees to be bound by the terms and conditions of this License
+Agreement.
+
diff --git a/frozen_deps/pysha3-1.0.2.dist-info/METADATA b/frozen_deps/pysha3-1.0.2.dist-info/METADATA
new file mode 100644
index 0000000..5e11ab7
--- /dev/null
+++ b/frozen_deps/pysha3-1.0.2.dist-info/METADATA
@@ -0,0 +1,251 @@
+Metadata-Version: 2.1
+Name: pysha3
+Version: 1.0.2
+Summary: SHA-3 (Keccak) for Python 2.7 - 3.5
+Home-page: https://github.com/tiran/pysha3
+Author: Christian Heimes
+Author-email: [email protected]
+Maintainer: Christian Heimes
+Maintainer-email: [email protected]
+License: PSFL (Keccak: CC0 1.0 Universal)
+Keywords: sha3 sha-3 keccak hash
+Platform: POSIX
+Platform: Windows
+Classifier: Development Status :: 4 - Beta
+Classifier: Intended Audience :: Developers
+Classifier: License :: OSI Approved :: Python Software Foundation License
+Classifier: License :: CC0 1.0 Universal (CC0 1.0) Public Domain Dedication
+Classifier: Natural Language :: English
+Classifier: Operating System :: MacOS :: MacOS X
+Classifier: Operating System :: POSIX
+Classifier: Operating System :: POSIX :: BSD
+Classifier: Operating System :: POSIX :: Linux
+Classifier: Operating System :: Microsoft :: Windows
+Classifier: Programming Language :: C
+Classifier: Programming Language :: Python
+Classifier: Programming Language :: Python :: 2
+Classifier: Programming Language :: Python :: 2.7
+Classifier: Programming Language :: Python :: 3
+Classifier: Programming Language :: Python :: 3.4
+Classifier: Programming Language :: Python :: 3.5
+Classifier: Topic :: Security :: Cryptography
+
+======
+pysha3
+======
+
+SHA-3 wrapper (keccak) for Python. The package is a wrapper around the
+optimized Keccak Code Package, https://github.com/gvanas/KeccakCodePackage .
+
+The module is a standalone version of my SHA-3 module from Python 3.6
+(currently under development). The code in sha3module.c has been modified to
+be compatible with Python 2.7 to 3.5. Python 2.6 and earlier are not
+supported.
+
+
+Updates since pysha 0.3
+=======================
+
+**pysha3 1.0 is not compatible with pysha3 0.3!**
+
+pysha3 < 1.0 used the old Keccak implementation. During the finalization of
+SHA3, NIST changed the delimiter suffix from 0x01 to 0x06. The Keccak sponge
+function stayed the same. pysha3 1.0 provides the previous Keccak hash, too.
+
+
+Platforms
+=========
+
+pysha3 has been successfully tested on several platforms:
+
+ - Linux (GCC, clang) on X86, X86_64 and ARMv6 (little endian)
+ - Windows (VS 2008, VS 2010, VS2015) on X86 and X86_64
+
+
+Usage
+=====
+
+The `sha3` module contains several constructors for hash objects with a
+PEP 247 compatible interface. The module provides SHA3, SHAKE and Keccak:
+
+* `sha3_228()`, `sha3_256()`, `sha3_384()`, and `sha3_512()`
+* `shake_128()`, `shake_256()`
+* `keccak_228()`, `keccak_256()`, `keccak_384()`, and `keccak_512()`
+
+The `sha3` module monkey patches the `hashlib` module . The monkey patch is
+automatically activated with the first import of the `sha3` module. The
+`hashlib` module of Python 3.6 will support the four SHA-3 algorithms and
+the two SHAKE algorithms on all platforms. Therefore you shouldn't use the
+sha3 module directly and rather go through the `hashlib` interface::
+
+ >>> import sys
+ >>> import hashlib
+ >>> if sys.version_info < (3, 6):
+ ... import sha3
+ >>> s = hashlib.sha3_512()
+ >>> s.name
+ 'sha3_512'
+ >>> s.digest_size
+ 64
+ >>> s.update(b"data")
+ >>> s.hexdigest()
+ 'ceca4daf960c2bbfb4a9edaca9b8137a801b65bae377e0f534ef9141c8684c0fedc1768d1afde9766572846c42b935f61177eaf97d355fa8dc2bca3fecfa754d'
+
+ >>> s = hashlib.shake_256()
+ >>> s.update(b"data")
+ >>> s.hexdigest(4)
+ 'c73dbed8'
+ >>> s.hexdigest(8)
+ 'c73dbed8527f5ae0'
+ >>> s.hexdigest(16)
+ 'c73dbed8527f5ae0568679f30ecc5cb6'
+
+ >>> import sha3
+ >>> k = sha3.keccak_512()
+ >>> k.update(b"data")
+ >>> k.hexdigest()
+ '1065aceeded3a5e4412e2187e919bffeadf815f5bd73d37fe00d384fe29f55f08462fdabe1007b993ce5b8119630e7db93101d9425d6e352e22ffe3dcb56b825'
+
+Changelog
+=========
+
+pysha3 1.0.2
+------------
+
+*Release: 05-Feb-2017*
+
+- Rename internal C extension to _pysha3 to avoild conflict with Python 3.6'
+ _sha3 extension.
+
+pysha3 1.0.1
+------------
+
+*Release: 24-Jan-2017*
+
+- Fix github.org -> github.com (Pi Delport)
+
+- Fix endianness checks for Python 2 (William Grant)
+
+- Fix changelog, the Christmas release was 1.0.0, not 1.1.0
+
+pysha3 1.0.0
+------------
+
+*Release date: 24-Dec-2016*
+
+- Synchronize with Python 3.6.0 release
+
+- Move all backport related additions to backport.inc
+
+- Fix flake8 violations
+
+
+pysha3 1.0b1
+------------
+
+*Release date: 01-May-2016*
+
+- Update backend to use the latest Keccak Code Package. pysha3 now implements
+ the official NIST standard. The old Keccak hashes are available with
+ keccak prefix.
+
+- Add SHAKE support.
+
+- All sha3, shake and keccak variants are separate types instead of factory
+ functions that return the same type.
+
+- Drop Python 2.6 and Python 3.0 to 3.3 support.
+
+- Fix typo that disabled threading optimization.
+
+- Add vector files for additional tests.
+
+- Add experimental HMAC support based on examples from
+ http://wolfgang-ehrhardt.de/hmac-sha3-testvectors.html .
+
+- Test hashing of unaligned data.
+
+- Add ISO C11 memset_s() function as _Py_memset_s() in order to securely
+ wipe memory that holds sensitive data. The page
+ https://www.securecoding.cert.org/confluence/display/seccode/MSC06-C.+Be+aware+of+compiler+optimization+when+dealing+with+sensitive+data
+ explains the motivation for memset_s().
+
+- Add tox support.
+
+- Add Travis and appveyor integration.
+
+- Add _capacity_bits, _rate_bits and _suffix attributes for diagnostic
+ purposes.
+
+
+pysha3 0.3
+----------
+
+*Release date: 14-Oct-2012*
+
+- Fix 64bit big endian support
+
+- Add workaround for alignment error on 64bit SPARC machine by using the opt32
+ implementation.
+
+- block_size now returns NotImplemented to prevent users from using pysha3
+ with the hmac module.
+
+
+pysha3 0.2.2
+------------
+
+*Release date: 07-Oct-2012*
+
+- Re-add brg_endian.h to fix issue on Solaris (big endian platform)
+
+
+pysha3 0.2.1
+------------
+
+*Release date: 06-Oct-2012*
+
+- Fix MANIFEST.in to include Makefile and tests.py
+
+- Add setup.py test command with hack for inplace builds
+
+- Enhance README.txt and fixed its markup
+
+
+pysha3 0.2
+----------
+
+*Release date: 06-Oct-2012*
+
+- Change directory struct to use the same directory layout as Python 3.4.
+
+- Remove C++ comments from Keccak sources for ANSI C compatibility.
+
+- Declare all Keccak functions and globals as static to avoid name clashes.
+
+- Remove alias sha3() for sha3_512().
+
+- Add block_size attribute. Keccak has a internal sponge size of 1600 bits.
+
+- Release GIL around SHA3_update() calls.
+
+- Monkey patch the hashlib module to support, e.g. hashlib.sha3_512() and
+ hashlib.new("sha3_512")
+
+- Release GIL around SHA3_update() when the data exceeds a certain size.
+
+- Fix build on platforms with an unsigned 64bit integer type (uint64_t). The
+ module falls back to 32bit implementation of Keccak with interleave tables.
+
+
+pysha3 0.1
+----------
+
+*Release date: 04-Oct-2012*
+
+- first release
+
+- based on KeccakReferenceAndOptimized-3.2.zip
+
+
+
diff --git a/frozen_deps/pysha3-1.0.2.dist-info/RECORD b/frozen_deps/pysha3-1.0.2.dist-info/RECORD
new file mode 100644
index 0000000..17ecd37
--- /dev/null
+++ b/frozen_deps/pysha3-1.0.2.dist-info/RECORD
@@ -0,0 +1,9 @@
+__pycache__/sha3.cpython-38.pyc,,
+_pysha3.cpython-38-x86_64-linux-gnu.so,sha256=JM0m-PvpwkIqoUIHO_5AuJYgbybynAEV8mKc7qw-hjA,517664
+pysha3-1.0.2.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4
+pysha3-1.0.2.dist-info/LICENSE,sha256=uAzp2oxCofkQeWJ_u-K_JyEK4Qig_-Xwd9WwjgdsJMg,2409
+pysha3-1.0.2.dist-info/METADATA,sha256=mp8k9OmbwPabv7k2zKNy45GRr2rUJ8auKH5xtoi9wIM,6810
+pysha3-1.0.2.dist-info/RECORD,,
+pysha3-1.0.2.dist-info/WHEEL,sha256=TpFVeXF_cAlV118WSIPWtjqW7nPvzoOw-49FmS3fDKQ,103
+pysha3-1.0.2.dist-info/top_level.txt,sha256=FdKZVala00U6bdey3Qbc6yW7Z1rzdaDs8Iet_iwYDP8,13
+sha3.py,sha256=QeJrjR0om_CROYj4xnndQXqkkr9Y9R11XsCKKiyYTzs,746
diff --git a/frozen_deps/pysha3-1.0.2.dist-info/WHEEL b/frozen_deps/pysha3-1.0.2.dist-info/WHEEL
new file mode 100644
index 0000000..d193dea
--- /dev/null
+++ b/frozen_deps/pysha3-1.0.2.dist-info/WHEEL
@@ -0,0 +1,5 @@
+Wheel-Version: 1.0
+Generator: bdist_wheel (0.34.2)
+Root-Is-Purelib: false
+Tag: cp38-cp38-linux_x86_64
+
diff --git a/frozen_deps/pysha3-1.0.2.dist-info/top_level.txt b/frozen_deps/pysha3-1.0.2.dist-info/top_level.txt
new file mode 100644
index 0000000..a9e88ad
--- /dev/null
+++ b/frozen_deps/pysha3-1.0.2.dist-info/top_level.txt
@@ -0,0 +1,2 @@
+_pysha3
+sha3
diff --git a/frozen_deps/sha3.py b/frozen_deps/sha3.py
new file mode 100644
index 0000000..5657f66
--- /dev/null
+++ b/frozen_deps/sha3.py
@@ -0,0 +1,24 @@
+# Copyright (C) 2012-2016 Christian Heimes ([email protected])
+# Licensed to PSF under a Contributor Agreement.
+#
+
+# monkey patch _hashlib
+import hashlib as _hashlib
+
+from _pysha3 import keccak_224, keccak_256, keccak_384, keccak_512
+from _pysha3 import sha3_224, sha3_256, sha3_384, sha3_512
+from _pysha3 import shake_128, shake_256
+
+
+__all__ = ("sha3_224", "sha3_256", "sha3_384", "sha3_512",
+ "keccak_224", "keccak_256", "keccak_384", "keccak_512",
+ "shake_128", "shake_256")
+
+
+if not hasattr(_hashlib, "sha3_512"):
+ _hashlib.sha3_224 = sha3_224
+ _hashlib.sha3_256 = sha3_256
+ _hashlib.sha3_384 = sha3_384
+ _hashlib.sha3_512 = sha3_512
+ _hashlib.shake_128 = shake_128
+ _hashlib.shake_256 = shake_256
diff --git a/frozen_deps/six-1.15.0.dist-info/INSTALLER b/frozen_deps/six-1.15.0.dist-info/INSTALLER
new file mode 100644
index 0000000..a1b589e
--- /dev/null
+++ b/frozen_deps/six-1.15.0.dist-info/INSTALLER
@@ -0,0 +1 @@
+pip
diff --git a/frozen_deps/six-1.15.0.dist-info/LICENSE b/frozen_deps/six-1.15.0.dist-info/LICENSE
new file mode 100644
index 0000000..de66331
--- /dev/null
+++ b/frozen_deps/six-1.15.0.dist-info/LICENSE
@@ -0,0 +1,18 @@
+Copyright (c) 2010-2020 Benjamin Peterson
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of
+this software and associated documentation files (the "Software"), to deal in
+the Software without restriction, including without limitation the rights to
+use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+the Software, and to permit persons to whom the Software is furnished to do so,
+subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
diff --git a/frozen_deps/six-1.15.0.dist-info/METADATA b/frozen_deps/six-1.15.0.dist-info/METADATA
new file mode 100644
index 0000000..869bf25
--- /dev/null
+++ b/frozen_deps/six-1.15.0.dist-info/METADATA
@@ -0,0 +1,49 @@
+Metadata-Version: 2.1
+Name: six
+Version: 1.15.0
+Summary: Python 2 and 3 compatibility utilities
+Home-page: https://github.com/benjaminp/six
+Author: Benjamin Peterson
+Author-email: [email protected]
+License: MIT
+Platform: UNKNOWN
+Classifier: Development Status :: 5 - Production/Stable
+Classifier: Programming Language :: Python :: 2
+Classifier: Programming Language :: Python :: 3
+Classifier: Intended Audience :: Developers
+Classifier: License :: OSI Approved :: MIT License
+Classifier: Topic :: Software Development :: Libraries
+Classifier: Topic :: Utilities
+Requires-Python: >=2.7, !=3.0.*, !=3.1.*, !=3.2.*
+
+.. image:: https://img.shields.io/pypi/v/six.svg
+ :target: https://pypi.org/project/six/
+ :alt: six on PyPI
+
+.. image:: https://travis-ci.org/benjaminp/six.svg?branch=master
+ :target: https://travis-ci.org/benjaminp/six
+ :alt: six on TravisCI
+
+.. image:: https://readthedocs.org/projects/six/badge/?version=latest
+ :target: https://six.readthedocs.io/
+ :alt: six's documentation on Read the Docs
+
+.. image:: https://img.shields.io/badge/license-MIT-green.svg
+ :target: https://github.com/benjaminp/six/blob/master/LICENSE
+ :alt: MIT License badge
+
+Six is a Python 2 and 3 compatibility library. It provides utility functions
+for smoothing over the differences between the Python versions with the goal of
+writing Python code that is compatible on both Python versions. See the
+documentation for more information on what is provided.
+
+Six supports Python 2.7 and 3.3+. It is contained in only one Python
+file, so it can be easily copied into your project. (The copyright and license
+notice must be retained.)
+
+Online documentation is at https://six.readthedocs.io/.
+
+Bugs can be reported to https://github.com/benjaminp/six. The code can also
+be found there.
+
+
diff --git a/frozen_deps/six-1.15.0.dist-info/RECORD b/frozen_deps/six-1.15.0.dist-info/RECORD
new file mode 100644
index 0000000..80bf846
--- /dev/null
+++ b/frozen_deps/six-1.15.0.dist-info/RECORD
@@ -0,0 +1,8 @@
+__pycache__/six.cpython-38.pyc,,
+six-1.15.0.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4
+six-1.15.0.dist-info/LICENSE,sha256=i7hQxWWqOJ_cFvOkaWWtI9gq3_YPI5P8J2K2MYXo5sk,1066
+six-1.15.0.dist-info/METADATA,sha256=W6rlyoeMZHXh6srP9NXNsm0rjAf_660re8WdH5TBT8E,1795
+six-1.15.0.dist-info/RECORD,,
+six-1.15.0.dist-info/WHEEL,sha256=kGT74LWyRUZrL4VgLh6_g12IeVl_9u9ZVhadrgXZUEY,110
+six-1.15.0.dist-info/top_level.txt,sha256=_iVH_iYEtEXnD8nYGQYpYFUvkUW9sEO1GYbkeKSAais,4
+six.py,sha256=U4Z_yv534W5CNyjY9i8V1OXY2SjAny8y2L5vDLhhThM,34159
diff --git a/frozen_deps/six-1.15.0.dist-info/WHEEL b/frozen_deps/six-1.15.0.dist-info/WHEEL
new file mode 100644
index 0000000..ef99c6c
--- /dev/null
+++ b/frozen_deps/six-1.15.0.dist-info/WHEEL
@@ -0,0 +1,6 @@
+Wheel-Version: 1.0
+Generator: bdist_wheel (0.34.2)
+Root-Is-Purelib: true
+Tag: py2-none-any
+Tag: py3-none-any
+
diff --git a/frozen_deps/six-1.15.0.dist-info/top_level.txt b/frozen_deps/six-1.15.0.dist-info/top_level.txt
new file mode 100644
index 0000000..ffe2fce
--- /dev/null
+++ b/frozen_deps/six-1.15.0.dist-info/top_level.txt
@@ -0,0 +1 @@
+six
diff --git a/frozen_deps/six.py b/frozen_deps/six.py
new file mode 100644
index 0000000..83f6978
--- /dev/null
+++ b/frozen_deps/six.py
@@ -0,0 +1,982 @@
+# Copyright (c) 2010-2020 Benjamin Peterson
+#
+# Permission is hereby granted, free of charge, to any person obtaining a copy
+# of this software and associated documentation files (the "Software"), to deal
+# in the Software without restriction, including without limitation the rights
+# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+# copies of the Software, and to permit persons to whom the Software is
+# furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be included in all
+# copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+# SOFTWARE.
+
+"""Utilities for writing code that runs on Python 2 and 3"""
+
+from __future__ import absolute_import
+
+import functools
+import itertools
+import operator
+import sys
+import types
+
+__author__ = "Benjamin Peterson <[email protected]>"
+__version__ = "1.15.0"
+
+
+# Useful for very coarse version differentiation.
+PY2 = sys.version_info[0] == 2
+PY3 = sys.version_info[0] == 3
+PY34 = sys.version_info[0:2] >= (3, 4)
+
+if PY3:
+ string_types = str,
+ integer_types = int,
+ class_types = type,
+ text_type = str
+ binary_type = bytes
+
+ MAXSIZE = sys.maxsize
+else:
+ string_types = basestring,
+ integer_types = (int, long)
+ class_types = (type, types.ClassType)
+ text_type = unicode
+ binary_type = str
+
+ if sys.platform.startswith("java"):
+ # Jython always uses 32 bits.
+ MAXSIZE = int((1 << 31) - 1)
+ else:
+ # It's possible to have sizeof(long) != sizeof(Py_ssize_t).
+ class X(object):
+
+ def __len__(self):
+ return 1 << 31
+ try:
+ len(X())
+ except OverflowError:
+ # 32-bit
+ MAXSIZE = int((1 << 31) - 1)
+ else:
+ # 64-bit
+ MAXSIZE = int((1 << 63) - 1)
+ del X
+
+
+def _add_doc(func, doc):
+ """Add documentation to a function."""
+ func.__doc__ = doc
+
+
+def _import_module(name):
+ """Import module, returning the module after the last dot."""
+ __import__(name)
+ return sys.modules[name]
+
+
+class _LazyDescr(object):
+
+ def __init__(self, name):
+ self.name = name
+
+ def __get__(self, obj, tp):
+ result = self._resolve()
+ setattr(obj, self.name, result) # Invokes __set__.
+ try:
+ # This is a bit ugly, but it avoids running this again by
+ # removing this descriptor.
+ delattr(obj.__class__, self.name)
+ except AttributeError:
+ pass
+ return result
+
+
+class MovedModule(_LazyDescr):
+
+ def __init__(self, name, old, new=None):
+ super(MovedModule, self).__init__(name)
+ if PY3:
+ if new is None:
+ new = name
+ self.mod = new
+ else:
+ self.mod = old
+
+ def _resolve(self):
+ return _import_module(self.mod)
+
+ def __getattr__(self, attr):
+ _module = self._resolve()
+ value = getattr(_module, attr)
+ setattr(self, attr, value)
+ return value
+
+
+class _LazyModule(types.ModuleType):
+
+ def __init__(self, name):
+ super(_LazyModule, self).__init__(name)
+ self.__doc__ = self.__class__.__doc__
+
+ def __dir__(self):
+ attrs = ["__doc__", "__name__"]
+ attrs += [attr.name for attr in self._moved_attributes]
+ return attrs
+
+ # Subclasses should override this
+ _moved_attributes = []
+
+
+class MovedAttribute(_LazyDescr):
+
+ def __init__(self, name, old_mod, new_mod, old_attr=None, new_attr=None):
+ super(MovedAttribute, self).__init__(name)
+ if PY3:
+ if new_mod is None:
+ new_mod = name
+ self.mod = new_mod
+ if new_attr is None:
+ if old_attr is None:
+ new_attr = name
+ else:
+ new_attr = old_attr
+ self.attr = new_attr
+ else:
+ self.mod = old_mod
+ if old_attr is None:
+ old_attr = name
+ self.attr = old_attr
+
+ def _resolve(self):
+ module = _import_module(self.mod)
+ return getattr(module, self.attr)
+
+
+class _SixMetaPathImporter(object):
+
+ """
+ A meta path importer to import six.moves and its submodules.
+
+ This class implements a PEP302 finder and loader. It should be compatible
+ with Python 2.5 and all existing versions of Python3
+ """
+
+ def __init__(self, six_module_name):
+ self.name = six_module_name
+ self.known_modules = {}
+
+ def _add_module(self, mod, *fullnames):
+ for fullname in fullnames:
+ self.known_modules[self.name + "." + fullname] = mod
+
+ def _get_module(self, fullname):
+ return self.known_modules[self.name + "." + fullname]
+
+ def find_module(self, fullname, path=None):
+ if fullname in self.known_modules:
+ return self
+ return None
+
+ def __get_module(self, fullname):
+ try:
+ return self.known_modules[fullname]
+ except KeyError:
+ raise ImportError("This loader does not know module " + fullname)
+
+ def load_module(self, fullname):
+ try:
+ # in case of a reload
+ return sys.modules[fullname]
+ except KeyError:
+ pass
+ mod = self.__get_module(fullname)
+ if isinstance(mod, MovedModule):
+ mod = mod._resolve()
+ else:
+ mod.__loader__ = self
+ sys.modules[fullname] = mod
+ return mod
+
+ def is_package(self, fullname):
+ """
+ Return true, if the named module is a package.
+
+ We need this method to get correct spec objects with
+ Python 3.4 (see PEP451)
+ """
+ return hasattr(self.__get_module(fullname), "__path__")
+
+ def get_code(self, fullname):
+ """Return None
+
+ Required, if is_package is implemented"""
+ self.__get_module(fullname) # eventually raises ImportError
+ return None
+ get_source = get_code # same as get_code
+
+_importer = _SixMetaPathImporter(__name__)
+
+
+class _MovedItems(_LazyModule):
+
+ """Lazy loading of moved objects"""
+ __path__ = [] # mark as package
+
+
+_moved_attributes = [
+ MovedAttribute("cStringIO", "cStringIO", "io", "StringIO"),
+ MovedAttribute("filter", "itertools", "builtins", "ifilter", "filter"),
+ MovedAttribute("filterfalse", "itertools", "itertools", "ifilterfalse", "filterfalse"),
+ MovedAttribute("input", "__builtin__", "builtins", "raw_input", "input"),
+ MovedAttribute("intern", "__builtin__", "sys"),
+ MovedAttribute("map", "itertools", "builtins", "imap", "map"),
+ MovedAttribute("getcwd", "os", "os", "getcwdu", "getcwd"),
+ MovedAttribute("getcwdb", "os", "os", "getcwd", "getcwdb"),
+ MovedAttribute("getoutput", "commands", "subprocess"),
+ MovedAttribute("range", "__builtin__", "builtins", "xrange", "range"),
+ MovedAttribute("reload_module", "__builtin__", "importlib" if PY34 else "imp", "reload"),
+ MovedAttribute("reduce", "__builtin__", "functools"),
+ MovedAttribute("shlex_quote", "pipes", "shlex", "quote"),
+ MovedAttribute("StringIO", "StringIO", "io"),
+ MovedAttribute("UserDict", "UserDict", "collections"),
+ MovedAttribute("UserList", "UserList", "collections"),
+ MovedAttribute("UserString", "UserString", "collections"),
+ MovedAttribute("xrange", "__builtin__", "builtins", "xrange", "range"),
+ MovedAttribute("zip", "itertools", "builtins", "izip", "zip"),
+ MovedAttribute("zip_longest", "itertools", "itertools", "izip_longest", "zip_longest"),
+ MovedModule("builtins", "__builtin__"),
+ MovedModule("configparser", "ConfigParser"),
+ MovedModule("collections_abc", "collections", "collections.abc" if sys.version_info >= (3, 3) else "collections"),
+ MovedModule("copyreg", "copy_reg"),
+ MovedModule("dbm_gnu", "gdbm", "dbm.gnu"),
+ MovedModule("dbm_ndbm", "dbm", "dbm.ndbm"),
+ MovedModule("_dummy_thread", "dummy_thread", "_dummy_thread" if sys.version_info < (3, 9) else "_thread"),
+ MovedModule("http_cookiejar", "cookielib", "http.cookiejar"),
+ MovedModule("http_cookies", "Cookie", "http.cookies"),
+ MovedModule("html_entities", "htmlentitydefs", "html.entities"),
+ MovedModule("html_parser", "HTMLParser", "html.parser"),
+ MovedModule("http_client", "httplib", "http.client"),
+ MovedModule("email_mime_base", "email.MIMEBase", "email.mime.base"),
+ MovedModule("email_mime_image", "email.MIMEImage", "email.mime.image"),
+ MovedModule("email_mime_multipart", "email.MIMEMultipart", "email.mime.multipart"),
+ MovedModule("email_mime_nonmultipart", "email.MIMENonMultipart", "email.mime.nonmultipart"),
+ MovedModule("email_mime_text", "email.MIMEText", "email.mime.text"),
+ MovedModule("BaseHTTPServer", "BaseHTTPServer", "http.server"),
+ MovedModule("CGIHTTPServer", "CGIHTTPServer", "http.server"),
+ MovedModule("SimpleHTTPServer", "SimpleHTTPServer", "http.server"),
+ MovedModule("cPickle", "cPickle", "pickle"),
+ MovedModule("queue", "Queue"),
+ MovedModule("reprlib", "repr"),
+ MovedModule("socketserver", "SocketServer"),
+ MovedModule("_thread", "thread", "_thread"),
+ MovedModule("tkinter", "Tkinter"),
+ MovedModule("tkinter_dialog", "Dialog", "tkinter.dialog"),
+ MovedModule("tkinter_filedialog", "FileDialog", "tkinter.filedialog"),
+ MovedModule("tkinter_scrolledtext", "ScrolledText", "tkinter.scrolledtext"),
+ MovedModule("tkinter_simpledialog", "SimpleDialog", "tkinter.simpledialog"),
+ MovedModule("tkinter_tix", "Tix", "tkinter.tix"),
+ MovedModule("tkinter_ttk", "ttk", "tkinter.ttk"),
+ MovedModule("tkinter_constants", "Tkconstants", "tkinter.constants"),
+ MovedModule("tkinter_dnd", "Tkdnd", "tkinter.dnd"),
+ MovedModule("tkinter_colorchooser", "tkColorChooser",
+ "tkinter.colorchooser"),
+ MovedModule("tkinter_commondialog", "tkCommonDialog",
+ "tkinter.commondialog"),
+ MovedModule("tkinter_tkfiledialog", "tkFileDialog", "tkinter.filedialog"),
+ MovedModule("tkinter_font", "tkFont", "tkinter.font"),
+ MovedModule("tkinter_messagebox", "tkMessageBox", "tkinter.messagebox"),
+ MovedModule("tkinter_tksimpledialog", "tkSimpleDialog",
+ "tkinter.simpledialog"),
+ MovedModule("urllib_parse", __name__ + ".moves.urllib_parse", "urllib.parse"),
+ MovedModule("urllib_error", __name__ + ".moves.urllib_error", "urllib.error"),
+ MovedModule("urllib", __name__ + ".moves.urllib", __name__ + ".moves.urllib"),
+ MovedModule("urllib_robotparser", "robotparser", "urllib.robotparser"),
+ MovedModule("xmlrpc_client", "xmlrpclib", "xmlrpc.client"),
+ MovedModule("xmlrpc_server", "SimpleXMLRPCServer", "xmlrpc.server"),
+]
+# Add windows specific modules.
+if sys.platform == "win32":
+ _moved_attributes += [
+ MovedModule("winreg", "_winreg"),
+ ]
+
+for attr in _moved_attributes:
+ setattr(_MovedItems, attr.name, attr)
+ if isinstance(attr, MovedModule):
+ _importer._add_module(attr, "moves." + attr.name)
+del attr
+
+_MovedItems._moved_attributes = _moved_attributes
+
+moves = _MovedItems(__name__ + ".moves")
+_importer._add_module(moves, "moves")
+
+
+class Module_six_moves_urllib_parse(_LazyModule):
+
+ """Lazy loading of moved objects in six.moves.urllib_parse"""
+
+
+_urllib_parse_moved_attributes = [
+ MovedAttribute("ParseResult", "urlparse", "urllib.parse"),
+ MovedAttribute("SplitResult", "urlparse", "urllib.parse"),
+ MovedAttribute("parse_qs", "urlparse", "urllib.parse"),
+ MovedAttribute("parse_qsl", "urlparse", "urllib.parse"),
+ MovedAttribute("urldefrag", "urlparse", "urllib.parse"),
+ MovedAttribute("urljoin", "urlparse", "urllib.parse"),
+ MovedAttribute("urlparse", "urlparse", "urllib.parse"),
+ MovedAttribute("urlsplit", "urlparse", "urllib.parse"),
+ MovedAttribute("urlunparse", "urlparse", "urllib.parse"),
+ MovedAttribute("urlunsplit", "urlparse", "urllib.parse"),
+ MovedAttribute("quote", "urllib", "urllib.parse"),
+ MovedAttribute("quote_plus", "urllib", "urllib.parse"),
+ MovedAttribute("unquote", "urllib", "urllib.parse"),
+ MovedAttribute("unquote_plus", "urllib", "urllib.parse"),
+ MovedAttribute("unquote_to_bytes", "urllib", "urllib.parse", "unquote", "unquote_to_bytes"),
+ MovedAttribute("urlencode", "urllib", "urllib.parse"),
+ MovedAttribute("splitquery", "urllib", "urllib.parse"),
+ MovedAttribute("splittag", "urllib", "urllib.parse"),
+ MovedAttribute("splituser", "urllib", "urllib.parse"),
+ MovedAttribute("splitvalue", "urllib", "urllib.parse"),
+ MovedAttribute("uses_fragment", "urlparse", "urllib.parse"),
+ MovedAttribute("uses_netloc", "urlparse", "urllib.parse"),
+ MovedAttribute("uses_params", "urlparse", "urllib.parse"),
+ MovedAttribute("uses_query", "urlparse", "urllib.parse"),
+ MovedAttribute("uses_relative", "urlparse", "urllib.parse"),
+]
+for attr in _urllib_parse_moved_attributes:
+ setattr(Module_six_moves_urllib_parse, attr.name, attr)
+del attr
+
+Module_six_moves_urllib_parse._moved_attributes = _urllib_parse_moved_attributes
+
+_importer._add_module(Module_six_moves_urllib_parse(__name__ + ".moves.urllib_parse"),
+ "moves.urllib_parse", "moves.urllib.parse")
+
+
+class Module_six_moves_urllib_error(_LazyModule):
+
+ """Lazy loading of moved objects in six.moves.urllib_error"""
+
+
+_urllib_error_moved_attributes = [
+ MovedAttribute("URLError", "urllib2", "urllib.error"),
+ MovedAttribute("HTTPError", "urllib2", "urllib.error"),
+ MovedAttribute("ContentTooShortError", "urllib", "urllib.error"),
+]
+for attr in _urllib_error_moved_attributes:
+ setattr(Module_six_moves_urllib_error, attr.name, attr)
+del attr
+
+Module_six_moves_urllib_error._moved_attributes = _urllib_error_moved_attributes
+
+_importer._add_module(Module_six_moves_urllib_error(__name__ + ".moves.urllib.error"),
+ "moves.urllib_error", "moves.urllib.error")
+
+
+class Module_six_moves_urllib_request(_LazyModule):
+
+ """Lazy loading of moved objects in six.moves.urllib_request"""
+
+
+_urllib_request_moved_attributes = [
+ MovedAttribute("urlopen", "urllib2", "urllib.request"),
+ MovedAttribute("install_opener", "urllib2", "urllib.request"),
+ MovedAttribute("build_opener", "urllib2", "urllib.request"),
+ MovedAttribute("pathname2url", "urllib", "urllib.request"),
+ MovedAttribute("url2pathname", "urllib", "urllib.request"),
+ MovedAttribute("getproxies", "urllib", "urllib.request"),
+ MovedAttribute("Request", "urllib2", "urllib.request"),
+ MovedAttribute("OpenerDirector", "urllib2", "urllib.request"),
+ MovedAttribute("HTTPDefaultErrorHandler", "urllib2", "urllib.request"),
+ MovedAttribute("HTTPRedirectHandler", "urllib2", "urllib.request"),
+ MovedAttribute("HTTPCookieProcessor", "urllib2", "urllib.request"),
+ MovedAttribute("ProxyHandler", "urllib2", "urllib.request"),
+ MovedAttribute("BaseHandler", "urllib2", "urllib.request"),
+ MovedAttribute("HTTPPasswordMgr", "urllib2", "urllib.request"),
+ MovedAttribute("HTTPPasswordMgrWithDefaultRealm", "urllib2", "urllib.request"),
+ MovedAttribute("AbstractBasicAuthHandler", "urllib2", "urllib.request"),
+ MovedAttribute("HTTPBasicAuthHandler", "urllib2", "urllib.request"),
+ MovedAttribute("ProxyBasicAuthHandler", "urllib2", "urllib.request"),
+ MovedAttribute("AbstractDigestAuthHandler", "urllib2", "urllib.request"),
+ MovedAttribute("HTTPDigestAuthHandler", "urllib2", "urllib.request"),
+ MovedAttribute("ProxyDigestAuthHandler", "urllib2", "urllib.request"),
+ MovedAttribute("HTTPHandler", "urllib2", "urllib.request"),
+ MovedAttribute("HTTPSHandler", "urllib2", "urllib.request"),
+ MovedAttribute("FileHandler", "urllib2", "urllib.request"),
+ MovedAttribute("FTPHandler", "urllib2", "urllib.request"),
+ MovedAttribute("CacheFTPHandler", "urllib2", "urllib.request"),
+ MovedAttribute("UnknownHandler", "urllib2", "urllib.request"),
+ MovedAttribute("HTTPErrorProcessor", "urllib2", "urllib.request"),
+ MovedAttribute("urlretrieve", "urllib", "urllib.request"),
+ MovedAttribute("urlcleanup", "urllib", "urllib.request"),
+ MovedAttribute("URLopener", "urllib", "urllib.request"),
+ MovedAttribute("FancyURLopener", "urllib", "urllib.request"),
+ MovedAttribute("proxy_bypass", "urllib", "urllib.request"),
+ MovedAttribute("parse_http_list", "urllib2", "urllib.request"),
+ MovedAttribute("parse_keqv_list", "urllib2", "urllib.request"),
+]
+for attr in _urllib_request_moved_attributes:
+ setattr(Module_six_moves_urllib_request, attr.name, attr)
+del attr
+
+Module_six_moves_urllib_request._moved_attributes = _urllib_request_moved_attributes
+
+_importer._add_module(Module_six_moves_urllib_request(__name__ + ".moves.urllib.request"),
+ "moves.urllib_request", "moves.urllib.request")
+
+
+class Module_six_moves_urllib_response(_LazyModule):
+
+ """Lazy loading of moved objects in six.moves.urllib_response"""
+
+
+_urllib_response_moved_attributes = [
+ MovedAttribute("addbase", "urllib", "urllib.response"),
+ MovedAttribute("addclosehook", "urllib", "urllib.response"),
+ MovedAttribute("addinfo", "urllib", "urllib.response"),
+ MovedAttribute("addinfourl", "urllib", "urllib.response"),
+]
+for attr in _urllib_response_moved_attributes:
+ setattr(Module_six_moves_urllib_response, attr.name, attr)
+del attr
+
+Module_six_moves_urllib_response._moved_attributes = _urllib_response_moved_attributes
+
+_importer._add_module(Module_six_moves_urllib_response(__name__ + ".moves.urllib.response"),
+ "moves.urllib_response", "moves.urllib.response")
+
+
+class Module_six_moves_urllib_robotparser(_LazyModule):
+
+ """Lazy loading of moved objects in six.moves.urllib_robotparser"""
+
+
+_urllib_robotparser_moved_attributes = [
+ MovedAttribute("RobotFileParser", "robotparser", "urllib.robotparser"),
+]
+for attr in _urllib_robotparser_moved_attributes:
+ setattr(Module_six_moves_urllib_robotparser, attr.name, attr)
+del attr
+
+Module_six_moves_urllib_robotparser._moved_attributes = _urllib_robotparser_moved_attributes
+
+_importer._add_module(Module_six_moves_urllib_robotparser(__name__ + ".moves.urllib.robotparser"),
+ "moves.urllib_robotparser", "moves.urllib.robotparser")
+
+
+class Module_six_moves_urllib(types.ModuleType):
+
+ """Create a six.moves.urllib namespace that resembles the Python 3 namespace"""
+ __path__ = [] # mark as package
+ parse = _importer._get_module("moves.urllib_parse")
+ error = _importer._get_module("moves.urllib_error")
+ request = _importer._get_module("moves.urllib_request")
+ response = _importer._get_module("moves.urllib_response")
+ robotparser = _importer._get_module("moves.urllib_robotparser")
+
+ def __dir__(self):
+ return ['parse', 'error', 'request', 'response', 'robotparser']
+
+_importer._add_module(Module_six_moves_urllib(__name__ + ".moves.urllib"),
+ "moves.urllib")
+
+
+def add_move(move):
+ """Add an item to six.moves."""
+ setattr(_MovedItems, move.name, move)
+
+
+def remove_move(name):
+ """Remove item from six.moves."""
+ try:
+ delattr(_MovedItems, name)
+ except AttributeError:
+ try:
+ del moves.__dict__[name]
+ except KeyError:
+ raise AttributeError("no such move, %r" % (name,))
+
+
+if PY3:
+ _meth_func = "__func__"
+ _meth_self = "__self__"
+
+ _func_closure = "__closure__"
+ _func_code = "__code__"
+ _func_defaults = "__defaults__"
+ _func_globals = "__globals__"
+else:
+ _meth_func = "im_func"
+ _meth_self = "im_self"
+
+ _func_closure = "func_closure"
+ _func_code = "func_code"
+ _func_defaults = "func_defaults"
+ _func_globals = "func_globals"
+
+
+try:
+ advance_iterator = next
+except NameError:
+ def advance_iterator(it):
+ return it.next()
+next = advance_iterator
+
+
+try:
+ callable = callable
+except NameError:
+ def callable(obj):
+ return any("__call__" in klass.__dict__ for klass in type(obj).__mro__)
+
+
+if PY3:
+ def get_unbound_function(unbound):
+ return unbound
+
+ create_bound_method = types.MethodType
+
+ def create_unbound_method(func, cls):
+ return func
+
+ Iterator = object
+else:
+ def get_unbound_function(unbound):
+ return unbound.im_func
+
+ def create_bound_method(func, obj):
+ return types.MethodType(func, obj, obj.__class__)
+
+ def create_unbound_method(func, cls):
+ return types.MethodType(func, None, cls)
+
+ class Iterator(object):
+
+ def next(self):
+ return type(self).__next__(self)
+
+ callable = callable
+_add_doc(get_unbound_function,
+ """Get the function out of a possibly unbound function""")
+
+
+get_method_function = operator.attrgetter(_meth_func)
+get_method_self = operator.attrgetter(_meth_self)
+get_function_closure = operator.attrgetter(_func_closure)
+get_function_code = operator.attrgetter(_func_code)
+get_function_defaults = operator.attrgetter(_func_defaults)
+get_function_globals = operator.attrgetter(_func_globals)
+
+
+if PY3:
+ def iterkeys(d, **kw):
+ return iter(d.keys(**kw))
+
+ def itervalues(d, **kw):
+ return iter(d.values(**kw))
+
+ def iteritems(d, **kw):
+ return iter(d.items(**kw))
+
+ def iterlists(d, **kw):
+ return iter(d.lists(**kw))
+
+ viewkeys = operator.methodcaller("keys")
+
+ viewvalues = operator.methodcaller("values")
+
+ viewitems = operator.methodcaller("items")
+else:
+ def iterkeys(d, **kw):
+ return d.iterkeys(**kw)
+
+ def itervalues(d, **kw):
+ return d.itervalues(**kw)
+
+ def iteritems(d, **kw):
+ return d.iteritems(**kw)
+
+ def iterlists(d, **kw):
+ return d.iterlists(**kw)
+
+ viewkeys = operator.methodcaller("viewkeys")
+
+ viewvalues = operator.methodcaller("viewvalues")
+
+ viewitems = operator.methodcaller("viewitems")
+
+_add_doc(iterkeys, "Return an iterator over the keys of a dictionary.")
+_add_doc(itervalues, "Return an iterator over the values of a dictionary.")
+_add_doc(iteritems,
+ "Return an iterator over the (key, value) pairs of a dictionary.")
+_add_doc(iterlists,
+ "Return an iterator over the (key, [values]) pairs of a dictionary.")
+
+
+if PY3:
+ def b(s):
+ return s.encode("latin-1")
+
+ def u(s):
+ return s
+ unichr = chr
+ import struct
+ int2byte = struct.Struct(">B").pack
+ del struct
+ byte2int = operator.itemgetter(0)
+ indexbytes = operator.getitem
+ iterbytes = iter
+ import io
+ StringIO = io.StringIO
+ BytesIO = io.BytesIO
+ del io
+ _assertCountEqual = "assertCountEqual"
+ if sys.version_info[1] <= 1:
+ _assertRaisesRegex = "assertRaisesRegexp"
+ _assertRegex = "assertRegexpMatches"
+ _assertNotRegex = "assertNotRegexpMatches"
+ else:
+ _assertRaisesRegex = "assertRaisesRegex"
+ _assertRegex = "assertRegex"
+ _assertNotRegex = "assertNotRegex"
+else:
+ def b(s):
+ return s
+ # Workaround for standalone backslash
+
+ def u(s):
+ return unicode(s.replace(r'\\', r'\\\\'), "unicode_escape")
+ unichr = unichr
+ int2byte = chr
+
+ def byte2int(bs):
+ return ord(bs[0])
+
+ def indexbytes(buf, i):
+ return ord(buf[i])
+ iterbytes = functools.partial(itertools.imap, ord)
+ import StringIO
+ StringIO = BytesIO = StringIO.StringIO
+ _assertCountEqual = "assertItemsEqual"
+ _assertRaisesRegex = "assertRaisesRegexp"
+ _assertRegex = "assertRegexpMatches"
+ _assertNotRegex = "assertNotRegexpMatches"
+_add_doc(b, """Byte literal""")
+_add_doc(u, """Text literal""")
+
+
+def assertCountEqual(self, *args, **kwargs):
+ return getattr(self, _assertCountEqual)(*args, **kwargs)
+
+
+def assertRaisesRegex(self, *args, **kwargs):
+ return getattr(self, _assertRaisesRegex)(*args, **kwargs)
+
+
+def assertRegex(self, *args, **kwargs):
+ return getattr(self, _assertRegex)(*args, **kwargs)
+
+
+def assertNotRegex(self, *args, **kwargs):
+ return getattr(self, _assertNotRegex)(*args, **kwargs)
+
+
+if PY3:
+ exec_ = getattr(moves.builtins, "exec")
+
+ def reraise(tp, value, tb=None):
+ try:
+ if value is None:
+ value = tp()
+ if value.__traceback__ is not tb:
+ raise value.with_traceback(tb)
+ raise value
+ finally:
+ value = None
+ tb = None
+
+else:
+ def exec_(_code_, _globs_=None, _locs_=None):
+ """Execute code in a namespace."""
+ if _globs_ is None:
+ frame = sys._getframe(1)
+ _globs_ = frame.f_globals
+ if _locs_ is None:
+ _locs_ = frame.f_locals
+ del frame
+ elif _locs_ is None:
+ _locs_ = _globs_
+ exec("""exec _code_ in _globs_, _locs_""")
+
+ exec_("""def reraise(tp, value, tb=None):
+ try:
+ raise tp, value, tb
+ finally:
+ tb = None
+""")
+
+
+if sys.version_info[:2] > (3,):
+ exec_("""def raise_from(value, from_value):
+ try:
+ raise value from from_value
+ finally:
+ value = None
+""")
+else:
+ def raise_from(value, from_value):
+ raise value
+
+
+print_ = getattr(moves.builtins, "print", None)
+if print_ is None:
+ def print_(*args, **kwargs):
+ """The new-style print function for Python 2.4 and 2.5."""
+ fp = kwargs.pop("file", sys.stdout)
+ if fp is None:
+ return
+
+ def write(data):
+ if not isinstance(data, basestring):
+ data = str(data)
+ # If the file has an encoding, encode unicode with it.
+ if (isinstance(fp, file) and
+ isinstance(data, unicode) and
+ fp.encoding is not None):
+ errors = getattr(fp, "errors", None)
+ if errors is None:
+ errors = "strict"
+ data = data.encode(fp.encoding, errors)
+ fp.write(data)
+ want_unicode = False
+ sep = kwargs.pop("sep", None)
+ if sep is not None:
+ if isinstance(sep, unicode):
+ want_unicode = True
+ elif not isinstance(sep, str):
+ raise TypeError("sep must be None or a string")
+ end = kwargs.pop("end", None)
+ if end is not None:
+ if isinstance(end, unicode):
+ want_unicode = True
+ elif not isinstance(end, str):
+ raise TypeError("end must be None or a string")
+ if kwargs:
+ raise TypeError("invalid keyword arguments to print()")
+ if not want_unicode:
+ for arg in args:
+ if isinstance(arg, unicode):
+ want_unicode = True
+ break
+ if want_unicode:
+ newline = unicode("\n")
+ space = unicode(" ")
+ else:
+ newline = "\n"
+ space = " "
+ if sep is None:
+ sep = space
+ if end is None:
+ end = newline
+ for i, arg in enumerate(args):
+ if i:
+ write(sep)
+ write(arg)
+ write(end)
+if sys.version_info[:2] < (3, 3):
+ _print = print_
+
+ def print_(*args, **kwargs):
+ fp = kwargs.get("file", sys.stdout)
+ flush = kwargs.pop("flush", False)
+ _print(*args, **kwargs)
+ if flush and fp is not None:
+ fp.flush()
+
+_add_doc(reraise, """Reraise an exception.""")
+
+if sys.version_info[0:2] < (3, 4):
+ # This does exactly the same what the :func:`py3:functools.update_wrapper`
+ # function does on Python versions after 3.2. It sets the ``__wrapped__``
+ # attribute on ``wrapper`` object and it doesn't raise an error if any of
+ # the attributes mentioned in ``assigned`` and ``updated`` are missing on
+ # ``wrapped`` object.
+ def _update_wrapper(wrapper, wrapped,
+ assigned=functools.WRAPPER_ASSIGNMENTS,
+ updated=functools.WRAPPER_UPDATES):
+ for attr in assigned:
+ try:
+ value = getattr(wrapped, attr)
+ except AttributeError:
+ continue
+ else:
+ setattr(wrapper, attr, value)
+ for attr in updated:
+ getattr(wrapper, attr).update(getattr(wrapped, attr, {}))
+ wrapper.__wrapped__ = wrapped
+ return wrapper
+ _update_wrapper.__doc__ = functools.update_wrapper.__doc__
+
+ def wraps(wrapped, assigned=functools.WRAPPER_ASSIGNMENTS,
+ updated=functools.WRAPPER_UPDATES):
+ return functools.partial(_update_wrapper, wrapped=wrapped,
+ assigned=assigned, updated=updated)
+ wraps.__doc__ = functools.wraps.__doc__
+
+else:
+ wraps = functools.wraps
+
+
+def with_metaclass(meta, *bases):
+ """Create a base class with a metaclass."""
+ # This requires a bit of explanation: the basic idea is to make a dummy
+ # metaclass for one level of class instantiation that replaces itself with
+ # the actual metaclass.
+ class metaclass(type):
+
+ def __new__(cls, name, this_bases, d):
+ if sys.version_info[:2] >= (3, 7):
+ # This version introduced PEP 560 that requires a bit
+ # of extra care (we mimic what is done by __build_class__).
+ resolved_bases = types.resolve_bases(bases)
+ if resolved_bases is not bases:
+ d['__orig_bases__'] = bases
+ else:
+ resolved_bases = bases
+ return meta(name, resolved_bases, d)
+
+ @classmethod
+ def __prepare__(cls, name, this_bases):
+ return meta.__prepare__(name, bases)
+ return type.__new__(metaclass, 'temporary_class', (), {})
+
+
+def add_metaclass(metaclass):
+ """Class decorator for creating a class with a metaclass."""
+ def wrapper(cls):
+ orig_vars = cls.__dict__.copy()
+ slots = orig_vars.get('__slots__')
+ if slots is not None:
+ if isinstance(slots, str):
+ slots = [slots]
+ for slots_var in slots:
+ orig_vars.pop(slots_var)
+ orig_vars.pop('__dict__', None)
+ orig_vars.pop('__weakref__', None)
+ if hasattr(cls, '__qualname__'):
+ orig_vars['__qualname__'] = cls.__qualname__
+ return metaclass(cls.__name__, cls.__bases__, orig_vars)
+ return wrapper
+
+
+def ensure_binary(s, encoding='utf-8', errors='strict'):
+ """Coerce **s** to six.binary_type.
+
+ For Python 2:
+ - `unicode` -> encoded to `str`
+ - `str` -> `str`
+
+ For Python 3:
+ - `str` -> encoded to `bytes`
+ - `bytes` -> `bytes`
+ """
+ if isinstance(s, binary_type):
+ return s
+ if isinstance(s, text_type):
+ return s.encode(encoding, errors)
+ raise TypeError("not expecting type '%s'" % type(s))
+
+
+def ensure_str(s, encoding='utf-8', errors='strict'):
+ """Coerce *s* to `str`.
+
+ For Python 2:
+ - `unicode` -> encoded to `str`
+ - `str` -> `str`
+
+ For Python 3:
+ - `str` -> `str`
+ - `bytes` -> decoded to `str`
+ """
+ # Optimization: Fast return for the common case.
+ if type(s) is str:
+ return s
+ if PY2 and isinstance(s, text_type):
+ return s.encode(encoding, errors)
+ elif PY3 and isinstance(s, binary_type):
+ return s.decode(encoding, errors)
+ elif not isinstance(s, (text_type, binary_type)):
+ raise TypeError("not expecting type '%s'" % type(s))
+ return s
+
+
+def ensure_text(s, encoding='utf-8', errors='strict'):
+ """Coerce *s* to six.text_type.
+
+ For Python 2:
+ - `unicode` -> `unicode`
+ - `str` -> `unicode`
+
+ For Python 3:
+ - `str` -> `str`
+ - `bytes` -> decoded to `str`
+ """
+ if isinstance(s, binary_type):
+ return s.decode(encoding, errors)
+ elif isinstance(s, text_type):
+ return s
+ else:
+ raise TypeError("not expecting type '%s'" % type(s))
+
+
+def python_2_unicode_compatible(klass):
+ """
+ A class decorator that defines __unicode__ and __str__ methods under Python 2.
+ Under Python 3 it does nothing.
+
+ To support Python 2 and 3 with a single code base, define a __str__ method
+ returning text and apply this decorator to the class.
+ """
+ if PY2:
+ if '__str__' not in klass.__dict__:
+ raise ValueError("@python_2_unicode_compatible cannot be applied "
+ "to %s because it doesn't define __str__()." %
+ klass.__name__)
+ klass.__unicode__ = klass.__str__
+ klass.__str__ = lambda self: self.__unicode__().encode('utf-8')
+ return klass
+
+
+# Complete the moves implementation.
+# This code is at the end of this module to speed up module loading.
+# Turn this module into a package.
+__path__ = [] # required for PEP 302 and PEP 451
+__package__ = __name__ # see PEP 366 @ReservedAssignment
+if globals().get("__spec__") is not None:
+ __spec__.submodule_search_locations = [] # PEP 451 @UndefinedVariable
+# Remove other six meta path importers, since they cause problems. This can
+# happen if six is removed from sys.modules and then reloaded. (Setuptools does
+# this for some reason.)
+if sys.meta_path:
+ for i, importer in enumerate(sys.meta_path):
+ # Here's some real nastiness: Another "instance" of the six module might
+ # be floating around. Therefore, we can't use isinstance() to check for
+ # the six meta path importer, since the other six instance will have
+ # inserted an importer with different class.
+ if (type(importer).__name__ == "_SixMetaPathImporter" and
+ importer.name == __name__):
+ del sys.meta_path[i]
+ break
+ del i, importer
+# Finally, add the importer to the meta path import hook.
+sys.meta_path.append(_importer)