Updated DB_Helper by adding firebase methods.
This commit is contained in:
parent
485cc3bbba
commit
c82121d036
1810 changed files with 537281 additions and 1 deletions
100
DBHelper.py
Normal file
100
DBHelper.py
Normal file
|
@ -0,0 +1,100 @@
|
||||||
|
import pyrebase
|
||||||
|
|
||||||
|
firebaseConfig = {
|
||||||
|
'apiKey': "AIzaSyAdL0W5HscjEDFPK4BDi6Cnc7FLa30GPYY",
|
||||||
|
'authDomain': "vehicleantitheftrecognition.firebaseapp.com",
|
||||||
|
'databaseURL': "https://vehicleantitheftrecognition.firebaseio.com",
|
||||||
|
'projectId': "vehicleantitheftrecognition",
|
||||||
|
'storageBucket': "vehicleantitheftrecognition.appspot.com",
|
||||||
|
'messagingSenderId': "163692530359",
|
||||||
|
'appId': "1:163692530359:web:b6dc7ccfc56a79afb11b32",
|
||||||
|
'measurementId': "G-EPWP2LK89Q"
|
||||||
|
}
|
||||||
|
|
||||||
|
firebase = pyrebase.initialize_app(firebaseConfig)
|
||||||
|
db = firebase.database()
|
||||||
|
auth = firebase.auth()
|
||||||
|
storage = firebase.storage()
|
||||||
|
|
||||||
|
class DBHelper:
|
||||||
|
|
||||||
|
# Create account fuction which creates a new account.
|
||||||
|
def createaccount(username, password, confirmpassword):
|
||||||
|
email = username + "@hotmail.com"
|
||||||
|
if password == confirmpassword:
|
||||||
|
auth.create_user_with_email_and_password(email,password)
|
||||||
|
print("Account sucessfully created.")
|
||||||
|
else:
|
||||||
|
print("Confirmed password doesn't match to other password.")
|
||||||
|
|
||||||
|
# Login fuction which verifies the information given.
|
||||||
|
def login(username, password):
|
||||||
|
email = username + "@hotmail.com"
|
||||||
|
try:
|
||||||
|
auth.sign_in_with_email_and_password(email, password)
|
||||||
|
print("Successfully Logged in.")
|
||||||
|
except:
|
||||||
|
print("Invalid username or password.")
|
||||||
|
|
||||||
|
# Uploads the data of specified user uploaded into firebase.
|
||||||
|
def uploadData(userID, firstname, lastname, email, phone, address):
|
||||||
|
data = {"First Name": firstname, "Last Name": lastname, "E-Mail": email, "Phone": phone, "Address": address}
|
||||||
|
db.child("Users").child(userID).set(data)
|
||||||
|
|
||||||
|
# Removes the data of specified user uploaded into firebase.
|
||||||
|
def removeData(userID):
|
||||||
|
db.child("Users").child(userID).remove()
|
||||||
|
|
||||||
|
# Returns the first name or else an empty string.
|
||||||
|
def getfirstname(userID):
|
||||||
|
firstname = ""
|
||||||
|
users = db.child("Users").get()
|
||||||
|
for user in users.each():
|
||||||
|
if user.key() == userID:
|
||||||
|
firstname = user.val()["First Name"]
|
||||||
|
return firstname
|
||||||
|
|
||||||
|
# Returns the last name or else an empty string.
|
||||||
|
def getlastname(userID):
|
||||||
|
lastname = ""
|
||||||
|
users = db.child("Users").get()
|
||||||
|
for user in users.each():
|
||||||
|
if user.key() == userID:
|
||||||
|
lastname = user.val()["Last Name"]
|
||||||
|
return lastname
|
||||||
|
|
||||||
|
# Returns the e-mail or else an empty string.
|
||||||
|
def getemail(userID):
|
||||||
|
email = ""
|
||||||
|
users = db.child("Users").get()
|
||||||
|
for user in users.each():
|
||||||
|
if user.key() == userID:
|
||||||
|
email = user.val()["E-Mail"]
|
||||||
|
return email
|
||||||
|
|
||||||
|
# Returns the phone or else an empty string.
|
||||||
|
def getphone(userID):
|
||||||
|
phone = ""
|
||||||
|
users = db.child("Users").get()
|
||||||
|
for user in users.each():
|
||||||
|
if user.key() == userID:
|
||||||
|
phone = user.val()["Phone"]
|
||||||
|
return phone
|
||||||
|
|
||||||
|
# Returns the address or else an empty string.
|
||||||
|
def getaddress(userID):
|
||||||
|
address = ""
|
||||||
|
users = db.child("Users").get()
|
||||||
|
for user in users.each():
|
||||||
|
if user.key() == userID:
|
||||||
|
address = user.val()["Address"]
|
||||||
|
return address
|
||||||
|
|
||||||
|
# Uploads the photo, input should be something like Photos_of_Users/example.png
|
||||||
|
# or something like Photos_of_Thieves/example.png for the thieves.
|
||||||
|
def uploadphoto(userphoto):
|
||||||
|
userphoto_str = str(userphoto)
|
||||||
|
storage.child(userphoto_str).put(userphoto)
|
||||||
|
|
||||||
|
|
||||||
|
|
288
venv/Lib/site-packages/Crypto/Cipher/AES.py
Normal file
288
venv/Lib/site-packages/Crypto/Cipher/AES.py
Normal file
|
@ -0,0 +1,288 @@
|
||||||
|
# -*- 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
|
||||||
|
>>>
|
||||||
|
>>> key = b'Sixteen byte key'
|
||||||
|
>>> cipher = AES.new(key, AES.MODE_CFB)
|
||||||
|
>>> msg = cipher.iv + cipher.encrypt(b'Attack at dawn')
|
||||||
|
|
||||||
|
A more complicated example is based on CCM, (see `MODE_CCM`) an `AEAD`_ mode
|
||||||
|
that provides both confidentiality and authentication for a message.
|
||||||
|
|
||||||
|
The CCM mode optionally allows the header of the message to remain in the clear,
|
||||||
|
whilst still being authenticated. The encryption is done as follows:
|
||||||
|
|
||||||
|
>>> from Crypto.Cipher import AES
|
||||||
|
>>> from Crypto.Random import get_random_bytes
|
||||||
|
>>>
|
||||||
|
>>>
|
||||||
|
>>> hdr = b'To your eyes only'
|
||||||
|
>>> plaintext = b'Attack at dawn'
|
||||||
|
>>> key = b'Sixteen byte key'
|
||||||
|
>>> cipher = AES.new(key, AES.MODE_CCM, nonce)
|
||||||
|
>>> cipher.update(hdr)
|
||||||
|
>>> msg = cipher.nonce, hdr, cipher.encrypt(plaintext), cipher.digest()
|
||||||
|
|
||||||
|
We assume that the tuple ``msg`` is transmitted to the receiver:
|
||||||
|
|
||||||
|
>>> nonce, hdr, ciphertext, mac = msg
|
||||||
|
>>> key = b'Sixteen byte key'
|
||||||
|
>>> cipher = AES.new(key, AES.MODE_CCM, nonce)
|
||||||
|
>>> cipher.update(hdr)
|
||||||
|
>>> plaintext = cipher.decrypt(ciphertext)
|
||||||
|
>>> try:
|
||||||
|
>>> cipher.verify(mac)
|
||||||
|
>>> print "The message is authentic: hdr=%s, pt=%s" % (hdr, plaintext)
|
||||||
|
>>> except ValueError:
|
||||||
|
>>> print "Key incorrect or message corrupted"
|
||||||
|
|
||||||
|
.. __: http://en.wikipedia.org/wiki/Advanced_Encryption_Standard
|
||||||
|
.. _NIST: http://csrc.nist.gov/publications/fips/fips197/fips-197.pdf
|
||||||
|
.. _AEAD: http://blog.cryptographyengineering.com/2012/05/how-to-choose-authenticated-encryption.html
|
||||||
|
|
||||||
|
:undocumented: __package__
|
||||||
|
"""
|
||||||
|
|
||||||
|
import sys
|
||||||
|
|
||||||
|
from Crypto.Cipher import _create_cipher
|
||||||
|
from Crypto.Util._raw_api import (load_pycryptodome_raw_lib,
|
||||||
|
VoidPointer, SmartPointer,
|
||||||
|
c_size_t, expect_byte_string)
|
||||||
|
|
||||||
|
|
||||||
|
_raw_cpuid_lib = load_pycryptodome_raw_lib("Crypto.Util._cpuid",
|
||||||
|
"int have_aes_ni(void);")
|
||||||
|
|
||||||
|
_cproto = """
|
||||||
|
int AES_start_operation(const uint8_t key[],
|
||||||
|
size_t key_len,
|
||||||
|
void **pResult);
|
||||||
|
int AES_encrypt(const void *state,
|
||||||
|
const uint8_t *in,
|
||||||
|
uint8_t *out,
|
||||||
|
size_t data_len);
|
||||||
|
int AES_decrypt(const void *state,
|
||||||
|
const uint8_t *in,
|
||||||
|
uint8_t *out,
|
||||||
|
size_t data_len);
|
||||||
|
int AES_stop_operation(void *state);
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
|
_raw_aes_lib = load_pycryptodome_raw_lib("Crypto.Cipher._raw_aes",
|
||||||
|
_cproto)
|
||||||
|
|
||||||
|
_raw_aesni_lib = None
|
||||||
|
try:
|
||||||
|
if _raw_cpuid_lib.have_aes_ni() == 1:
|
||||||
|
_raw_aesni_lib = load_pycryptodome_raw_lib("Crypto.Cipher._raw_aesni",
|
||||||
|
_cproto.replace("AES",
|
||||||
|
"AESNI"))
|
||||||
|
except OSError:
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
def _create_base_cipher(dict_parameters):
|
||||||
|
"""This method instantiates and returns a handle to a low-level
|
||||||
|
base cipher. It will absorb named parameters in the process."""
|
||||||
|
|
||||||
|
use_aesni = dict_parameters.pop("use_aesni", True)
|
||||||
|
|
||||||
|
try:
|
||||||
|
key = dict_parameters.pop("key")
|
||||||
|
except KeyError:
|
||||||
|
raise TypeError("Missing 'key' parameter")
|
||||||
|
|
||||||
|
expect_byte_string(key)
|
||||||
|
|
||||||
|
if len(key) not in key_size:
|
||||||
|
raise ValueError("Incorrect AES key length (%d bytes)" % len(key))
|
||||||
|
|
||||||
|
if use_aesni and _raw_aesni_lib:
|
||||||
|
start_operation = _raw_aesni_lib.AESNI_start_operation
|
||||||
|
stop_operation = _raw_aesni_lib.AESNI_stop_operation
|
||||||
|
else:
|
||||||
|
start_operation = _raw_aes_lib.AES_start_operation
|
||||||
|
stop_operation = _raw_aes_lib.AES_stop_operation
|
||||||
|
|
||||||
|
cipher = VoidPointer()
|
||||||
|
result = start_operation(key,
|
||||||
|
c_size_t(len(key)),
|
||||||
|
cipher.address_of())
|
||||||
|
if result:
|
||||||
|
raise ValueError("Error %X while instantiating the AES cipher"
|
||||||
|
% result)
|
||||||
|
return SmartPointer(cipher.get(), stop_operation)
|
||||||
|
|
||||||
|
|
||||||
|
def new(key, mode, *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.
|
||||||
|
|
||||||
|
Only in `MODE_SIV`, it needs to be 32, 48, or 64 bytes long.
|
||||||
|
|
||||||
|
mode : a *MODE_** constant
|
||||||
|
The chaining mode to use for encryption or decryption.
|
||||||
|
If in doubt, use `MODE_EAX`.
|
||||||
|
|
||||||
|
:Keywords:
|
||||||
|
iv : byte string
|
||||||
|
(*Only* `MODE_CBC`, `MODE_CFB`, `MODE_OFB`, `MODE_OPENPGP`).
|
||||||
|
|
||||||
|
The initialization vector to use for encryption or decryption.
|
||||||
|
|
||||||
|
For `MODE_OPENPGP`, it must be 16 bytes long for encryption
|
||||||
|
and 18 bytes for decryption (in the latter case, it is
|
||||||
|
actually the *encrypted* IV which was prefixed to the ciphertext).
|
||||||
|
|
||||||
|
For all other modes, it must be 16 bytes long.
|
||||||
|
|
||||||
|
In not provided, a random byte string is used (you must then
|
||||||
|
read its value with the ``iv`` attribute).
|
||||||
|
|
||||||
|
nonce : byte string
|
||||||
|
(*Only* `MODE_CCM`, `MODE_EAX`, `MODE_GCM`, `MODE_SIV`, `MODE_OCB`,
|
||||||
|
`MODE_CTR`).
|
||||||
|
|
||||||
|
A value that must never be reused for any other encryption done
|
||||||
|
with this key.
|
||||||
|
|
||||||
|
For `MODE_CCM`, its length must be in the range ``[7..13]``.
|
||||||
|
Bear in mind that with CCM there is a trade-off between nonce
|
||||||
|
length and maximum message size.
|
||||||
|
|
||||||
|
For `MODE_OCB`, its length must be in the range ``[1..15]``.
|
||||||
|
|
||||||
|
For `MODE_CTR`, its length must be in the range ``[0..15]``.
|
||||||
|
|
||||||
|
For the other modes, there are no restrictions on its length.
|
||||||
|
|
||||||
|
The recommended length depends on the mode: 8 bytes for `MODE_CTR`,
|
||||||
|
11 bytes for `MODE_CCM`, 15 bytes for `MODE_OCB` and 16 bytes
|
||||||
|
for the remaining modes.
|
||||||
|
|
||||||
|
In not provided, a random byte string of the recommended
|
||||||
|
length is used (you must then read its value with the ``nonce`` attribute).
|
||||||
|
|
||||||
|
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 not specified, it will be assumed to be 8.
|
||||||
|
|
||||||
|
mac_len : integer
|
||||||
|
(*Only* `MODE_EAX`, `MODE_GCM`, `MODE_OCB`, `MODE_CCM`)
|
||||||
|
Length of the authentication tag, in bytes.
|
||||||
|
|
||||||
|
It must be even and in the range ``[4..16]``.
|
||||||
|
The recommended value (and the default, if not specified) is 16.
|
||||||
|
|
||||||
|
msg_len : integer
|
||||||
|
(*Only* `MODE_CCM`). Length of the message to (de)cipher.
|
||||||
|
If not specified, ``encrypt`` must be called with the entire message.
|
||||||
|
Similarly, ``decrypt`` can only be called once.
|
||||||
|
|
||||||
|
assoc_len : integer
|
||||||
|
(*Only* `MODE_CCM`). Length of the associated data.
|
||||||
|
If not specified, all associated data is buffered internally,
|
||||||
|
which may represent a problem for very large messages.
|
||||||
|
|
||||||
|
initial_value : integer
|
||||||
|
(*Only* `MODE_CTR`). The initial value for the counter within
|
||||||
|
the counter block. By default it is 0.
|
||||||
|
|
||||||
|
use_aesni : boolean
|
||||||
|
Use Intel AES-NI hardware extensions if available.
|
||||||
|
|
||||||
|
:Return: an AES object, of the applicable mode:
|
||||||
|
|
||||||
|
- CBC_ mode
|
||||||
|
- CCM_ mode
|
||||||
|
- CFB_ mode
|
||||||
|
- CTR_ mode
|
||||||
|
- EAX_ mode
|
||||||
|
- ECB_ mode
|
||||||
|
- GCM_ mode
|
||||||
|
- OCB_ mode
|
||||||
|
- OFB_ mode
|
||||||
|
- OpenPgp_ mode
|
||||||
|
- SIV_ mode
|
||||||
|
|
||||||
|
.. _CBC: Crypto.Cipher._mode_cbc.CbcMode-class.html
|
||||||
|
.. _CCM: Crypto.Cipher._mode_ccm.CcmMode-class.html
|
||||||
|
.. _CFB: Crypto.Cipher._mode_cfb.CfbMode-class.html
|
||||||
|
.. _CTR: Crypto.Cipher._mode_ctr.CtrMode-class.html
|
||||||
|
.. _EAX: Crypto.Cipher._mode_eax.EaxMode-class.html
|
||||||
|
.. _ECB: Crypto.Cipher._mode_ecb.EcbMode-class.html
|
||||||
|
.. _GCM: Crypto.Cipher._mode_gcm.GcmMode-class.html
|
||||||
|
.. _OCB: Crypto.Cipher._mode_ocb.OcbMode-class.html
|
||||||
|
.. _OFB: Crypto.Cipher._mode_ofb.OfbMode-class.html
|
||||||
|
.. _OpenPgp: Crypto.Cipher._mode_openpgp.OpenPgpMode-class.html
|
||||||
|
.. _SIV: Crypto.Cipher._mode_siv.SivMode-class.html
|
||||||
|
"""
|
||||||
|
|
||||||
|
kwargs["add_aes_modes"] = True
|
||||||
|
return _create_cipher(sys.modules[__name__], key, mode, *args, **kwargs)
|
||||||
|
|
||||||
|
#: Electronic Code Book (ECB). See `Crypto.Cipher._mode_ecb.EcbMode`.
|
||||||
|
MODE_ECB = 1
|
||||||
|
#: Cipher-Block Chaining (CBC). See `Crypto.Cipher._mode_cbc.CbcMode`.
|
||||||
|
MODE_CBC = 2
|
||||||
|
#: Cipher FeedBack (CFB). See `Crypto.Cipher._mode_cfb.CfbMode`.
|
||||||
|
MODE_CFB = 3
|
||||||
|
#: Output FeedBack (OFB). See `Crypto.Cipher._mode_ofb.OfbMode`.
|
||||||
|
MODE_OFB = 5
|
||||||
|
#: CounTer Mode (CTR). See `Crypto.Cipher._mode_ctr.CtrMode`.
|
||||||
|
MODE_CTR = 6
|
||||||
|
#: OpenPGP Mode. See `Crypto.Cipher._mode_openpgp.OpenPgpMode`.
|
||||||
|
MODE_OPENPGP = 7
|
||||||
|
#: Counter with CBC-MAC (CCM) Mode. See `Crypto.Cipher._mode_ccm.CcmMode`.
|
||||||
|
MODE_CCM = 8
|
||||||
|
#: EAX Mode. See `Crypto.Cipher._mode_eax.EaxMode`.
|
||||||
|
MODE_EAX = 9
|
||||||
|
#: Syntethic Initialization Vector (SIV). See `Crypto.Cipher._mode_siv.SivMode`.
|
||||||
|
MODE_SIV = 10
|
||||||
|
#: Galois Counter Mode (GCM). See `Crypto.Cipher._mode_gcm.GcmMode`.
|
||||||
|
MODE_GCM = 11
|
||||||
|
#: Offset Code Book (OCB). See `Crypto.Cipher._mode_ocb.OcbMode`.
|
||||||
|
MODE_OCB = 12
|
||||||
|
|
||||||
|
#: Size of a data block (in bytes)
|
||||||
|
block_size = 16
|
||||||
|
#: Size of a key (in bytes)
|
||||||
|
key_size = (16, 24, 32)
|
218
venv/Lib/site-packages/Crypto/Cipher/ARC2.py
Normal file
218
venv/Lib/site-packages/Crypto/Cipher/ARC2.py
Normal file
|
@ -0,0 +1,218 @@
|
||||||
|
# -*- 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.
|
||||||
|
|
||||||
|
**Use AES, not ARC2. This module is only provided for legacy purposes.**
|
||||||
|
|
||||||
|
As an example, encryption can be done as follows:
|
||||||
|
|
||||||
|
>>> from Crypto.Cipher import ARC2
|
||||||
|
>>>
|
||||||
|
>>> key = b'Sixteen byte key'
|
||||||
|
>>> cipher = ARC2.new(key, ARC2.MODE_CFB)
|
||||||
|
>>> msg = cipher.iv + cipher.encrypt(b'Attack at dawn')
|
||||||
|
|
||||||
|
.. _RC2: http://en.wikipedia.org/wiki/RC2
|
||||||
|
.. _RFC2268: http://tools.ietf.org/html/rfc2268
|
||||||
|
|
||||||
|
:undocumented: __package__
|
||||||
|
"""
|
||||||
|
|
||||||
|
import sys
|
||||||
|
|
||||||
|
from Crypto.Cipher import _create_cipher
|
||||||
|
from Crypto.Util.py3compat import byte_string
|
||||||
|
from Crypto.Util._raw_api import (load_pycryptodome_raw_lib,
|
||||||
|
VoidPointer, SmartPointer,
|
||||||
|
c_size_t, expect_byte_string)
|
||||||
|
|
||||||
|
_raw_arc2_lib = load_pycryptodome_raw_lib(
|
||||||
|
"Crypto.Cipher._raw_arc2",
|
||||||
|
"""
|
||||||
|
int ARC2_start_operation(const uint8_t key[],
|
||||||
|
size_t key_len,
|
||||||
|
size_t effective_key_len,
|
||||||
|
void **pResult);
|
||||||
|
int ARC2_encrypt(const void *state,
|
||||||
|
const uint8_t *in,
|
||||||
|
uint8_t *out,
|
||||||
|
size_t data_len);
|
||||||
|
int ARC2_decrypt(const void *state,
|
||||||
|
const uint8_t *in,
|
||||||
|
uint8_t *out,
|
||||||
|
size_t data_len);
|
||||||
|
int ARC2_stop_operation(void *state);
|
||||||
|
"""
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def _create_base_cipher(dict_parameters):
|
||||||
|
"""This method instantiates and returns a handle to a low-level
|
||||||
|
base cipher. It will absorb named parameters in the process."""
|
||||||
|
|
||||||
|
try:
|
||||||
|
key = dict_parameters.pop("key")
|
||||||
|
except KeyError:
|
||||||
|
raise TypeError("Missing 'key' parameter")
|
||||||
|
|
||||||
|
effective_keylen = dict_parameters.pop("effective_keylen", 1024)
|
||||||
|
|
||||||
|
expect_byte_string(key)
|
||||||
|
|
||||||
|
if len(key) not in key_size:
|
||||||
|
raise ValueError("Incorrect ARC2 key length (%d bytes)" % len(key))
|
||||||
|
|
||||||
|
if not (40 < effective_keylen <= 1024):
|
||||||
|
raise ValueError("'effective_key_len' must be no larger than 1024 "
|
||||||
|
"(not %d)" % effective_keylen)
|
||||||
|
|
||||||
|
start_operation = _raw_arc2_lib.ARC2_start_operation
|
||||||
|
stop_operation = _raw_arc2_lib.ARC2_stop_operation
|
||||||
|
|
||||||
|
cipher = VoidPointer()
|
||||||
|
result = start_operation(key,
|
||||||
|
c_size_t(len(key)),
|
||||||
|
c_size_t(effective_keylen),
|
||||||
|
cipher.address_of())
|
||||||
|
if result:
|
||||||
|
raise ValueError("Error %X while instantiating the ARC2 cipher"
|
||||||
|
% result)
|
||||||
|
|
||||||
|
return SmartPointer(cipher.get(), stop_operation)
|
||||||
|
|
||||||
|
|
||||||
|
def new(key, mode, *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 5 to 128 bytes.
|
||||||
|
|
||||||
|
mode : a *MODE_** constant
|
||||||
|
The chaining mode to use for encryption or decryption.
|
||||||
|
|
||||||
|
:Keywords:
|
||||||
|
iv : byte string
|
||||||
|
(*Only* `MODE_CBC`, `MODE_CFB`, `MODE_OFB`, `MODE_OPENPGP`).
|
||||||
|
|
||||||
|
The initialization vector to use for encryption or decryption.
|
||||||
|
|
||||||
|
For `MODE_OPENPGP`, IV must be 8 bytes long for encryption
|
||||||
|
and 10 bytes for decryption (in the latter case, it is
|
||||||
|
actually the *encrypted* IV which was prefixed to the ciphertext).
|
||||||
|
|
||||||
|
For all other modes, it must be 8 bytes long.
|
||||||
|
|
||||||
|
If not provided, a random byte string will be generated (you
|
||||||
|
must read it back via the ``iv`` attribute of the cipher).
|
||||||
|
|
||||||
|
nonce : byte string
|
||||||
|
(*Only* `MODE_EAX` and `MODE_CTR`).
|
||||||
|
A value that must never be reused for any other encryption done with
|
||||||
|
this key.
|
||||||
|
|
||||||
|
For `MODE_CTR`, its length must be in the range ``[0..7]``.
|
||||||
|
|
||||||
|
For `MODE_EAX`, there are no restrictions, but it is recommended to
|
||||||
|
use at least 16 bytes.
|
||||||
|
|
||||||
|
If not provided for `MODE_EAX`, a random byte string will be
|
||||||
|
generated (you must read it back via the ``nonce`` attribute
|
||||||
|
of the cipher).
|
||||||
|
|
||||||
|
mac_len : integer
|
||||||
|
(*Only* `MODE_EAX`). Length of the authentication tag, in bytes.
|
||||||
|
It must be no larger than 8 (which is the default).
|
||||||
|
|
||||||
|
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 not specified,
|
||||||
|
it will be assumed to be 8.
|
||||||
|
|
||||||
|
initial_value : integer
|
||||||
|
(*Only* `MODE_CTR`). The initial value for the counter within
|
||||||
|
the counter block. By default it is 0.
|
||||||
|
|
||||||
|
effective_keylen : integer
|
||||||
|
Maximum cryptographic strength of the key, in **bits**.
|
||||||
|
It can vary from 40 to 1024. The default value is 1024.
|
||||||
|
|
||||||
|
:Return: an RC2 cipher object, of the applicable mode:
|
||||||
|
|
||||||
|
- CBC_ mode
|
||||||
|
- CFB_ mode
|
||||||
|
- CTR_ mode
|
||||||
|
- EAX_ mode
|
||||||
|
- ECB_ mode
|
||||||
|
- OFB_ mode
|
||||||
|
- OpenPgp_ mode
|
||||||
|
|
||||||
|
.. _CBC: Crypto.Cipher._mode_cbc.CbcMode-class.html
|
||||||
|
.. _CFB: Crypto.Cipher._mode_cfb.CfbMode-class.html
|
||||||
|
.. _CTR: Crypto.Cipher._mode_ctr.CtrMode-class.html
|
||||||
|
.. _EAX: Crypto.Cipher._mode_eax.EaxMode-class.html
|
||||||
|
.. _ECB: Crypto.Cipher._mode_ecb.EcbMode-class.html
|
||||||
|
.. _OFB: Crypto.Cipher._mode_ofb.OfbMode-class.html
|
||||||
|
.. _OpenPgp: Crypto.Cipher._mode_openpgp.OpenPgpMode-class.html
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
return _create_cipher(sys.modules[__name__], key, mode, *args, **kwargs)
|
||||||
|
|
||||||
|
#: Electronic Code Book (ECB). See `Crypto.Cipher._mode_ecb.EcbMode`.
|
||||||
|
MODE_ECB = 1
|
||||||
|
#: Cipher-Block Chaining (CBC). See `Crypto.Cipher._mode_cbc.CbcMode`.
|
||||||
|
MODE_CBC = 2
|
||||||
|
#: Cipher FeedBack (CFB). See `Crypto.Cipher._mode_cfb.CfbMode`.
|
||||||
|
MODE_CFB = 3
|
||||||
|
#: Output FeedBack (OFB). See `Crypto.Cipher._mode_ofb.OfbMode`.
|
||||||
|
MODE_OFB = 5
|
||||||
|
#: CounTer Mode (CTR). See `Crypto.Cipher._mode_ctr.CtrMode`.
|
||||||
|
MODE_CTR = 6
|
||||||
|
#: OpenPGP Mode. See `Crypto.Cipher._mode_openpgp.OpenPgpMode`.
|
||||||
|
MODE_OPENPGP = 7
|
||||||
|
#: EAX Mode. See `Crypto.Cipher._mode_eax.EaxMode`.
|
||||||
|
MODE_EAX = 9
|
||||||
|
|
||||||
|
#: Size of a data block (in bytes)
|
||||||
|
block_size = 8
|
||||||
|
#: Size of a key (in bytes)
|
||||||
|
key_size = range(5, 128 + 1)
|
179
venv/Lib/site-packages/Crypto/Cipher/ARC4.py
Normal file
179
venv/Lib/site-packages/Crypto/Cipher/ARC4.py
Normal file
|
@ -0,0 +1,179 @@
|
||||||
|
# -*- 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.
|
||||||
|
|
||||||
|
**Use ChaCha20, not ARC4. This module is only provided for legacy purposes.**
|
||||||
|
|
||||||
|
As an example, encryption can be done as follows:
|
||||||
|
|
||||||
|
>>> from Crypto.Cipher import ARC4
|
||||||
|
>>> from Crypto.Hash import SHA
|
||||||
|
>>> from Crypto.Random import get_random_bytes
|
||||||
|
>>>
|
||||||
|
>>> key = b'Very long and confidential key'
|
||||||
|
>>> nonce = get_random_bytes(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: __package__
|
||||||
|
"""
|
||||||
|
|
||||||
|
from Crypto.Util.py3compat import b
|
||||||
|
|
||||||
|
from Crypto.Util._raw_api import (load_pycryptodome_raw_lib, VoidPointer,
|
||||||
|
create_string_buffer, get_raw_buffer,
|
||||||
|
SmartPointer, c_size_t, expect_byte_string)
|
||||||
|
|
||||||
|
|
||||||
|
_raw_arc4_lib = load_pycryptodome_raw_lib("Crypto.Cipher._ARC4", """
|
||||||
|
int ARC4_stream_encrypt(void *rc4State, const uint8_t in[],
|
||||||
|
uint8_t out[], size_t len);
|
||||||
|
int ARC4_stream_init(uint8_t *key, size_t keylen,
|
||||||
|
void **pRc4State);
|
||||||
|
int ARC4_stream_destroy(void *rc4State);
|
||||||
|
""")
|
||||||
|
|
||||||
|
|
||||||
|
class ARC4Cipher:
|
||||||
|
"""ARC4 cipher object"""
|
||||||
|
|
||||||
|
def __init__(self, key, *args, **kwargs):
|
||||||
|
"""Initialize an ARC4 cipher object
|
||||||
|
|
||||||
|
See also `new()` at the module level."""
|
||||||
|
|
||||||
|
if len(args) > 0:
|
||||||
|
ndrop = args[0]
|
||||||
|
args = args[1:]
|
||||||
|
else:
|
||||||
|
ndrop = kwargs.pop('drop', 0)
|
||||||
|
|
||||||
|
if len(key) not in key_size:
|
||||||
|
raise ValueError("Incorrect ARC4 key length (%d bytes)" %
|
||||||
|
len(key))
|
||||||
|
|
||||||
|
expect_byte_string(key)
|
||||||
|
|
||||||
|
self._state = VoidPointer()
|
||||||
|
result = _raw_arc4_lib.ARC4_stream_init(key,
|
||||||
|
c_size_t(len(key)),
|
||||||
|
self._state.address_of())
|
||||||
|
if result != 0:
|
||||||
|
raise ValueError("Error %d while creating the ARC4 cipher"
|
||||||
|
% result)
|
||||||
|
self._state = SmartPointer(self._state.get(),
|
||||||
|
_raw_arc4_lib.ARC4_stream_destroy)
|
||||||
|
|
||||||
|
if ndrop > 0:
|
||||||
|
# This is OK even if the cipher is used for decryption,
|
||||||
|
# since encrypt and decrypt are actually the same thing
|
||||||
|
# with ARC4.
|
||||||
|
self.encrypt(b('\x00') * ndrop)
|
||||||
|
|
||||||
|
self.block_size = 1
|
||||||
|
self.key_size = len(key)
|
||||||
|
|
||||||
|
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).
|
||||||
|
"""
|
||||||
|
|
||||||
|
expect_byte_string(plaintext)
|
||||||
|
ciphertext = create_string_buffer(len(plaintext))
|
||||||
|
result = _raw_arc4_lib.ARC4_stream_encrypt(self._state.get(),
|
||||||
|
plaintext,
|
||||||
|
ciphertext,
|
||||||
|
c_size_t(len(plaintext)))
|
||||||
|
if result:
|
||||||
|
raise ValueError("Error %d while encrypting with RC4" % result)
|
||||||
|
return get_raw_buffer(ciphertext)
|
||||||
|
|
||||||
|
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).
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
return self.encrypt(ciphertext)
|
||||||
|
except ValueError as e:
|
||||||
|
raise ValueError(str(e).replace("enc", "dec"))
|
||||||
|
|
||||||
|
|
||||||
|
def new(key, *args, **kwargs):
|
||||||
|
"""Create a new ARC4 cipher
|
||||||
|
|
||||||
|
:Parameters:
|
||||||
|
key : byte string
|
||||||
|
The secret key to use in the symmetric cipher.
|
||||||
|
Its length must be in the range ``[5..256]``.
|
||||||
|
The recommended length is 16 bytes.
|
||||||
|
|
||||||
|
:Keywords:
|
||||||
|
drop : integer
|
||||||
|
The amount of bytes to discard from the initial part of the keystream.
|
||||||
|
In fact, such part has been found to be distinguishable from random
|
||||||
|
data (while it shouldn't) and also correlated to key.
|
||||||
|
|
||||||
|
The recommended value is 3072_ bytes. The default value is 0.
|
||||||
|
|
||||||
|
:Return: an `ARC4Cipher` object
|
||||||
|
|
||||||
|
.. _3072: http://eprint.iacr.org/2002/067.pdf
|
||||||
|
"""
|
||||||
|
return ARC4Cipher(key, *args, **kwargs)
|
||||||
|
|
||||||
|
#: Size of a data block (in bytes)
|
||||||
|
block_size = 1
|
||||||
|
#: Size of a key (in bytes)
|
||||||
|
key_size = range(5, 256+1)
|
195
venv/Lib/site-packages/Crypto/Cipher/Blowfish.py
Normal file
195
venv/Lib/site-packages/Crypto/Cipher/Blowfish.py
Normal file
|
@ -0,0 +1,195 @@
|
||||||
|
# -*- 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).
|
||||||
|
|
||||||
|
**Use AES, not Blowfish. This module is provided only for legacy purposes.**
|
||||||
|
|
||||||
|
As an example, encryption can be done as follows:
|
||||||
|
|
||||||
|
>>> from Crypto.Cipher import Blowfish
|
||||||
|
>>> from struct import pack
|
||||||
|
>>>
|
||||||
|
>>> bs = Blowfish.block_size
|
||||||
|
>>> key = b'An arbitrarily long key'
|
||||||
|
>>> cipher = Blowfish.new(key, Blowfish.MODE_CBC)
|
||||||
|
>>> plaintext = b'docendo discimus '
|
||||||
|
>>> plen = bs - len(plaintext) % bs
|
||||||
|
>>> padding = [plen]*plen
|
||||||
|
>>> padding = pack('b'*plen, *padding)
|
||||||
|
>>> msg = cipher.iv + cipher.encrypt(plaintext + padding)
|
||||||
|
|
||||||
|
.. _Blowfish: http://www.schneier.com/blowfish.html
|
||||||
|
|
||||||
|
:undocumented: __package__
|
||||||
|
"""
|
||||||
|
|
||||||
|
import sys
|
||||||
|
|
||||||
|
from Crypto.Cipher import _create_cipher
|
||||||
|
from Crypto.Util._raw_api import (load_pycryptodome_raw_lib,
|
||||||
|
VoidPointer, SmartPointer, c_size_t,
|
||||||
|
expect_byte_string)
|
||||||
|
|
||||||
|
_raw_blowfish_lib = load_pycryptodome_raw_lib(
|
||||||
|
"Crypto.Cipher._raw_blowfish",
|
||||||
|
"""
|
||||||
|
int Blowfish_start_operation(const uint8_t key[],
|
||||||
|
size_t key_len,
|
||||||
|
void **pResult);
|
||||||
|
int Blowfish_encrypt(const void *state,
|
||||||
|
const uint8_t *in,
|
||||||
|
uint8_t *out,
|
||||||
|
size_t data_len);
|
||||||
|
int Blowfish_decrypt(const void *state,
|
||||||
|
const uint8_t *in,
|
||||||
|
uint8_t *out,
|
||||||
|
size_t data_len);
|
||||||
|
int Blowfish_stop_operation(void *state);
|
||||||
|
"""
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def _create_base_cipher(dict_parameters):
|
||||||
|
"""This method instantiates and returns a smart pointer to
|
||||||
|
a low-level base cipher. It will absorb named parameters in
|
||||||
|
the process."""
|
||||||
|
|
||||||
|
try:
|
||||||
|
key = dict_parameters.pop("key")
|
||||||
|
except KeyError:
|
||||||
|
raise TypeError("Missing 'key' parameter")
|
||||||
|
|
||||||
|
expect_byte_string(key)
|
||||||
|
|
||||||
|
if len(key) not in key_size:
|
||||||
|
raise ValueError("Incorrect Blowfish key length (%d bytes)" % len(key))
|
||||||
|
|
||||||
|
start_operation = _raw_blowfish_lib.Blowfish_start_operation
|
||||||
|
stop_operation = _raw_blowfish_lib.Blowfish_stop_operation
|
||||||
|
|
||||||
|
void_p = VoidPointer()
|
||||||
|
result = start_operation(key, c_size_t(len(key)), void_p.address_of())
|
||||||
|
if result:
|
||||||
|
raise ValueError("Error %X while instantiating the Blowfish cipher"
|
||||||
|
% result)
|
||||||
|
return SmartPointer(void_p.get(), stop_operation)
|
||||||
|
|
||||||
|
|
||||||
|
def new(key, mode, *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 5 to 56 bytes.
|
||||||
|
|
||||||
|
mode : a *MODE_** constant
|
||||||
|
The chaining mode to use for encryption or decryption.
|
||||||
|
|
||||||
|
:Keywords:
|
||||||
|
iv : byte string
|
||||||
|
(*Only* `MODE_CBC`, `MODE_CFB`, `MODE_OFB`, `MODE_OPENPGP`).
|
||||||
|
|
||||||
|
The initialization vector to use for encryption or decryption.
|
||||||
|
|
||||||
|
For `MODE_OPENPGP`, IV must be 8 bytes long for encryption
|
||||||
|
and 10 bytes for decryption (in the latter case, it is
|
||||||
|
actually the *encrypted* IV which was prefixed to the ciphertext).
|
||||||
|
|
||||||
|
For all other modes, it must be 8 bytes long.
|
||||||
|
|
||||||
|
If not provided, a random byte string will be generated (you must
|
||||||
|
read it back via the ``iv`` attribute).
|
||||||
|
|
||||||
|
nonce : byte string
|
||||||
|
(*Only* `MODE_EAX` and `MODE_CTR`).
|
||||||
|
A value that must never be reused for any other encryption.
|
||||||
|
|
||||||
|
For `MODE_CTR`, its length must be in the range ``[0..7]``.
|
||||||
|
|
||||||
|
For `MODE_EAX`, there are no restrictions, but it is recommended to
|
||||||
|
use at least 16 bytes.
|
||||||
|
|
||||||
|
If not provided for `MODE_EAX`, a 16 byte random string will be used
|
||||||
|
(you can read it back via the ``nonce`` attribute).
|
||||||
|
|
||||||
|
mac_len : integer
|
||||||
|
(*Only* `MODE_EAX`). Length of the authentication tag, in bytes.
|
||||||
|
It must be no larger than 8 (which is the default).
|
||||||
|
|
||||||
|
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 not specified, it will be assumed to be 8.
|
||||||
|
|
||||||
|
initial_value : integer
|
||||||
|
(*Only* `MODE_CTR`). The initial value for the counter within
|
||||||
|
the counter block. By default it is 0.
|
||||||
|
|
||||||
|
:Return: a Blowfish cipher object, of the applicable mode:
|
||||||
|
|
||||||
|
- CBC_ mode
|
||||||
|
- CFB_ mode
|
||||||
|
- CTR_ mode
|
||||||
|
- EAX_ mode
|
||||||
|
- ECB_ mode
|
||||||
|
- OFB_ mode
|
||||||
|
- OpenPgp_ mode
|
||||||
|
|
||||||
|
.. _CBC: Crypto.Cipher._mode_cbc.CbcMode-class.html
|
||||||
|
.. _CFB: Crypto.Cipher._mode_cfb.CfbMode-class.html
|
||||||
|
.. _CTR: Crypto.Cipher._mode_ctr.CtrMode-class.html
|
||||||
|
.. _EAX: Crypto.Cipher._mode_eax.EaxMode-class.html
|
||||||
|
.. _ECB: Crypto.Cipher._mode_ecb.EcbMode-class.html
|
||||||
|
.. _OFB: Crypto.Cipher._mode_ofb.OfbMode-class.html
|
||||||
|
.. _OpenPgp: Crypto.Cipher._mode_openpgp.OpenPgpMode-class.html
|
||||||
|
"""
|
||||||
|
|
||||||
|
return _create_cipher(sys.modules[__name__], key, mode, *args, **kwargs)
|
||||||
|
|
||||||
|
#: Electronic Code Book (ECB). See `Crypto.Cipher._mode_ecb.EcbMode`.
|
||||||
|
MODE_ECB = 1
|
||||||
|
#: Cipher-Block Chaining (CBC). See `Crypto.Cipher._mode_cbc.CbcMode`.
|
||||||
|
MODE_CBC = 2
|
||||||
|
#: Cipher FeedBack (CFB). See `Crypto.Cipher._mode_cfb.CfbMode`.
|
||||||
|
MODE_CFB = 3
|
||||||
|
#: Output FeedBack (OFB). See `Crypto.Cipher._mode_ofb.OfbMode`.
|
||||||
|
MODE_OFB = 5
|
||||||
|
#: CounTer Mode (CTR). See `Crypto.Cipher._mode_ctr.CtrMode`.
|
||||||
|
MODE_CTR = 6
|
||||||
|
#: OpenPGP Mode. See `Crypto.Cipher._mode_openpgp.OpenPgpMode`.
|
||||||
|
MODE_OPENPGP = 7
|
||||||
|
#: EAX Mode. See `Crypto.Cipher._mode_eax.EaxMode`.
|
||||||
|
MODE_EAX = 9
|
||||||
|
|
||||||
|
#: Size of a data block (in bytes)
|
||||||
|
block_size = 8
|
||||||
|
#: Size of a key (in bytes)
|
||||||
|
key_size = range(5, 56 + 1)
|
202
venv/Lib/site-packages/Crypto/Cipher/CAST.py
Normal file
202
venv/Lib/site-packages/Crypto/Cipher/CAST.py
Normal file
|
@ -0,0 +1,202 @@
|
||||||
|
# -*- 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).
|
||||||
|
|
||||||
|
**Use AES, not CAST. This module is only provided for legacy purposes.**
|
||||||
|
|
||||||
|
As an example, encryption can be done as follows:
|
||||||
|
|
||||||
|
>>> from Crypto.Cipher import CAST
|
||||||
|
>>>
|
||||||
|
>>> key = b'Sixteen byte key'
|
||||||
|
>>> cipher = CAST.new(key, CAST.MODE_OPENPGP)
|
||||||
|
>>> 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: __package__
|
||||||
|
"""
|
||||||
|
|
||||||
|
import sys
|
||||||
|
|
||||||
|
from Crypto.Cipher import _create_cipher
|
||||||
|
from Crypto.Util.py3compat import byte_string
|
||||||
|
from Crypto.Util._raw_api import (load_pycryptodome_raw_lib,
|
||||||
|
VoidPointer, SmartPointer,
|
||||||
|
c_size_t, expect_byte_string)
|
||||||
|
|
||||||
|
_raw_cast_lib = load_pycryptodome_raw_lib(
|
||||||
|
"Crypto.Cipher._raw_cast",
|
||||||
|
"""
|
||||||
|
int CAST_start_operation(const uint8_t key[],
|
||||||
|
size_t key_len,
|
||||||
|
void **pResult);
|
||||||
|
int CAST_encrypt(const void *state,
|
||||||
|
const uint8_t *in,
|
||||||
|
uint8_t *out,
|
||||||
|
size_t data_len);
|
||||||
|
int CAST_decrypt(const void *state,
|
||||||
|
const uint8_t *in,
|
||||||
|
uint8_t *out,
|
||||||
|
size_t data_len);
|
||||||
|
int CAST_stop_operation(void *state);
|
||||||
|
""")
|
||||||
|
|
||||||
|
|
||||||
|
def _create_base_cipher(dict_parameters):
|
||||||
|
"""This method instantiates and returns a handle to a low-level
|
||||||
|
base cipher. It will absorb named parameters in the process."""
|
||||||
|
|
||||||
|
try:
|
||||||
|
key = dict_parameters.pop("key")
|
||||||
|
except KeyError:
|
||||||
|
raise TypeError("Missing 'key' parameter")
|
||||||
|
|
||||||
|
expect_byte_string(key)
|
||||||
|
|
||||||
|
if len(key) not in key_size:
|
||||||
|
raise ValueError("Incorrect CAST key length (%d bytes)" % len(key))
|
||||||
|
|
||||||
|
start_operation = _raw_cast_lib.CAST_start_operation
|
||||||
|
stop_operation = _raw_cast_lib.CAST_stop_operation
|
||||||
|
|
||||||
|
cipher = VoidPointer()
|
||||||
|
result = start_operation(key,
|
||||||
|
c_size_t(len(key)),
|
||||||
|
cipher.address_of())
|
||||||
|
if result:
|
||||||
|
raise ValueError("Error %X while instantiating the CAST cipher"
|
||||||
|
% result)
|
||||||
|
|
||||||
|
return SmartPointer(cipher.get(), stop_operation)
|
||||||
|
|
||||||
|
|
||||||
|
def new(key, mode, *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.
|
||||||
|
The recommended length is 16 bytes.
|
||||||
|
|
||||||
|
mode : a *MODE_** constant
|
||||||
|
The chaining mode to use for encryption or decryption.
|
||||||
|
|
||||||
|
:Keywords:
|
||||||
|
iv : byte string
|
||||||
|
(*Only* `MODE_CBC`, `MODE_CFB`, `MODE_OFB`, `MODE_OPENPGP`).
|
||||||
|
|
||||||
|
The initialization vector to use for encryption or decryption.
|
||||||
|
|
||||||
|
For `MODE_OPENPGP`, IV must be 8 bytes long for encryption
|
||||||
|
and 10 bytes for decryption (in the latter case, it is
|
||||||
|
actually the *encrypted* IV which was prefixed to the ciphertext).
|
||||||
|
|
||||||
|
For all other modes, it must be 8 bytes long.
|
||||||
|
|
||||||
|
If not provided, a random byte string will be generated (you can
|
||||||
|
read it back via the ``iv`` attribute).
|
||||||
|
|
||||||
|
nonce : byte string
|
||||||
|
(*Only* `MODE_EAX` and `MODE_CTR`)
|
||||||
|
A mandatory value that must never be reused for any other encryption.
|
||||||
|
|
||||||
|
For `MODE_CTR`, its length must be in the range ``[0..7]``.
|
||||||
|
|
||||||
|
For `MODE_EAX`, there are no restrictions, but it is recommended to
|
||||||
|
use at least 16 bytes.
|
||||||
|
|
||||||
|
If not provided for `MODE_EAX`, a random 16 byte string will be
|
||||||
|
generated (you can read it back via the ``nonce`` attribute).
|
||||||
|
|
||||||
|
mac_len : integer
|
||||||
|
(*Only* `MODE_EAX`). Length of the authentication tag, in bytes.
|
||||||
|
It must be no larger than 8 (which is the default).
|
||||||
|
|
||||||
|
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 not specified, it will be assumed to be 8.
|
||||||
|
|
||||||
|
initial_value : integer
|
||||||
|
(*Only* `MODE_CTR`). The initial value for the counter within
|
||||||
|
the counter block. By default it is 0.
|
||||||
|
|
||||||
|
:Return: a CAST cipher object, of the applicable mode:
|
||||||
|
|
||||||
|
- CBC_ mode
|
||||||
|
- CFB_ mode
|
||||||
|
- CTR_ mode
|
||||||
|
- EAX_ mode
|
||||||
|
- ECB_ mode
|
||||||
|
- OFB_ mode
|
||||||
|
- OpenPgp_ mode
|
||||||
|
|
||||||
|
.. _CBC: Crypto.Cipher._mode_cbc.CbcMode-class.html
|
||||||
|
.. _CFB: Crypto.Cipher._mode_cfb.CfbMode-class.html
|
||||||
|
.. _CTR: Crypto.Cipher._mode_ctr.CtrMode-class.html
|
||||||
|
.. _EAX: Crypto.Cipher._mode_eax.EaxMode-class.html
|
||||||
|
.. _ECB: Crypto.Cipher._mode_ecb.EcbMode-class.html
|
||||||
|
.. _OFB: Crypto.Cipher._mode_ofb.OfbMode-class.html
|
||||||
|
.. _OpenPgp: Crypto.Cipher._mode_openpgp.OpenPgpMode-class.html
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
return _create_cipher(sys.modules[__name__], key, mode, *args, **kwargs)
|
||||||
|
|
||||||
|
#: Electronic Code Book (ECB). See `Crypto.Cipher._mode_ecb.EcbMode`.
|
||||||
|
MODE_ECB = 1
|
||||||
|
#: Cipher-Block Chaining (CBC). See `Crypto.Cipher._mode_cbc.CbcMode`.
|
||||||
|
MODE_CBC = 2
|
||||||
|
#: Cipher FeedBack (CFB). See `Crypto.Cipher._mode_cfb.CfbMode`.
|
||||||
|
MODE_CFB = 3
|
||||||
|
#: Output FeedBack (OFB). See `Crypto.Cipher._mode_ofb.OfbMode`.
|
||||||
|
MODE_OFB = 5
|
||||||
|
#: CounTer Mode (CTR). See `Crypto.Cipher._mode_ctr.CtrMode`.
|
||||||
|
MODE_CTR = 6
|
||||||
|
#: OpenPGP Mode. See `Crypto.Cipher._mode_openpgp.OpenPgpMode`.
|
||||||
|
MODE_OPENPGP = 7
|
||||||
|
#: EAX Mode. See `Crypto.Cipher._mode_eax.EaxMode`.
|
||||||
|
MODE_EAX = 9
|
||||||
|
|
||||||
|
#: Size of a data block (in bytes)
|
||||||
|
block_size = 8
|
||||||
|
#: Size of a key (in bytes)
|
||||||
|
key_size = range(5, 16 + 1)
|
220
venv/Lib/site-packages/Crypto/Cipher/ChaCha20.py
Normal file
220
venv/Lib/site-packages/Crypto/Cipher/ChaCha20.py
Normal file
|
@ -0,0 +1,220 @@
|
||||||
|
# ===================================================================
|
||||||
|
#
|
||||||
|
# Copyright (c) 2014, Legrandin <helderijs@gmail.com>
|
||||||
|
# All rights reserved.
|
||||||
|
#
|
||||||
|
# Redistribution and use in source and binary forms, with or without
|
||||||
|
# modification, are permitted provided that the following conditions
|
||||||
|
# are met:
|
||||||
|
#
|
||||||
|
# 1. Redistributions of source code must retain the above copyright
|
||||||
|
# notice, this list of conditions and the following disclaimer.
|
||||||
|
# 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
# notice, this list of conditions and the following disclaimer in
|
||||||
|
# the documentation and/or other materials provided with the
|
||||||
|
# distribution.
|
||||||
|
#
|
||||||
|
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||||
|
# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||||
|
# COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||||
|
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||||
|
# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||||
|
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||||
|
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||||
|
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
|
# POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
# ===================================================================
|
||||||
|
|
||||||
|
"""ChaCha20 stream cipher
|
||||||
|
|
||||||
|
`ChaCha20`_ is a stream cipher designed by Daniel J. Bernstein.
|
||||||
|
|
||||||
|
The key is 256 bits long.
|
||||||
|
|
||||||
|
As an example, encryption can be done as follows:
|
||||||
|
|
||||||
|
>>> from Crypto.Cipher import ChaCha20
|
||||||
|
>>>
|
||||||
|
>>> key = b'*Thirty-two byte (256 bits) key*'
|
||||||
|
>>> cipher = ChaCha20.new(key)
|
||||||
|
>>> msg = cipher.nonce + cipher.encrypt(b'Attack at dawn')
|
||||||
|
|
||||||
|
:undocumented: __package__
|
||||||
|
|
||||||
|
.. _ChaCha20: http://http://cr.yp.to/chacha.html
|
||||||
|
"""
|
||||||
|
|
||||||
|
from Crypto.Random import get_random_bytes
|
||||||
|
|
||||||
|
from Crypto.Util._raw_api import (load_pycryptodome_raw_lib,
|
||||||
|
create_string_buffer,
|
||||||
|
get_raw_buffer, VoidPointer,
|
||||||
|
SmartPointer, c_size_t,
|
||||||
|
expect_byte_string, c_ulong)
|
||||||
|
|
||||||
|
_raw_chacha20_lib = load_pycryptodome_raw_lib("Crypto.Cipher._chacha20",
|
||||||
|
"""
|
||||||
|
int chacha20_init(void **pState,
|
||||||
|
const uint8_t *key,
|
||||||
|
size_t keySize,
|
||||||
|
const uint8_t *nonce,
|
||||||
|
size_t nonceSize);
|
||||||
|
|
||||||
|
int chacha20_destroy(void *state);
|
||||||
|
|
||||||
|
int chacha20_encrypt(void *state,
|
||||||
|
const uint8_t in[],
|
||||||
|
uint8_t out[],
|
||||||
|
size_t len);
|
||||||
|
|
||||||
|
int chacha20_seek(void *state,
|
||||||
|
unsigned long block_high,
|
||||||
|
unsigned long block_low,
|
||||||
|
unsigned offset);
|
||||||
|
""")
|
||||||
|
|
||||||
|
|
||||||
|
class ChaCha20Cipher:
|
||||||
|
"""ChaCha20 cipher object"""
|
||||||
|
|
||||||
|
block_size = 1
|
||||||
|
|
||||||
|
def __init__(self, key, nonce):
|
||||||
|
"""Initialize a ChaCha20 cipher object
|
||||||
|
|
||||||
|
See also `new()` at the module level."""
|
||||||
|
|
||||||
|
expect_byte_string(key)
|
||||||
|
expect_byte_string(nonce)
|
||||||
|
|
||||||
|
self.nonce = nonce
|
||||||
|
|
||||||
|
self._next = ( self.encrypt, self.decrypt )
|
||||||
|
self._state = VoidPointer()
|
||||||
|
result = _raw_chacha20_lib.chacha20_init(
|
||||||
|
self._state.address_of(),
|
||||||
|
key,
|
||||||
|
c_size_t(len(key)),
|
||||||
|
nonce,
|
||||||
|
c_size_t(len(nonce)))
|
||||||
|
if result:
|
||||||
|
raise ValueError("Error %d instantiating a ChaCha20 cipher")
|
||||||
|
self._state = SmartPointer(self._state.get(),
|
||||||
|
_raw_chacha20_lib.chacha20_destroy)
|
||||||
|
|
||||||
|
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).
|
||||||
|
"""
|
||||||
|
|
||||||
|
if self.encrypt not in self._next:
|
||||||
|
raise TypeError("Cipher object can only be used for decryption")
|
||||||
|
self._next = ( self.encrypt, )
|
||||||
|
return self._encrypt(plaintext)
|
||||||
|
|
||||||
|
def _encrypt(self, plaintext):
|
||||||
|
"""Encrypt without FSM checks"""
|
||||||
|
|
||||||
|
expect_byte_string(plaintext)
|
||||||
|
ciphertext = create_string_buffer(len(plaintext))
|
||||||
|
result = _raw_chacha20_lib.chacha20_encrypt(
|
||||||
|
self._state.get(),
|
||||||
|
plaintext,
|
||||||
|
ciphertext,
|
||||||
|
c_size_t(len(plaintext)))
|
||||||
|
if result:
|
||||||
|
raise ValueError("Error %d while encrypting with ChaCha20" % result)
|
||||||
|
return get_raw_buffer(ciphertext)
|
||||||
|
|
||||||
|
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).
|
||||||
|
"""
|
||||||
|
|
||||||
|
if self.decrypt not in self._next:
|
||||||
|
raise TypeError("Cipher object can only be used for encryption")
|
||||||
|
self._next = ( self.decrypt, )
|
||||||
|
|
||||||
|
try:
|
||||||
|
return self._encrypt(ciphertext)
|
||||||
|
except ValueError as e:
|
||||||
|
raise ValueError(str(e).replace("enc", "dec"))
|
||||||
|
|
||||||
|
def seek(self, position):
|
||||||
|
"""Seek at a certain position in the key stream.
|
||||||
|
|
||||||
|
:Parameters:
|
||||||
|
position : integer
|
||||||
|
The absolute position within the key stream, in bytes.
|
||||||
|
"""
|
||||||
|
|
||||||
|
offset = position & 0x3f
|
||||||
|
position >>= 6
|
||||||
|
block_low = position & 0xFFFFFFFF
|
||||||
|
block_high = position >> 32
|
||||||
|
|
||||||
|
result = _raw_chacha20_lib.chacha20_seek(
|
||||||
|
self._state.get(),
|
||||||
|
c_ulong(block_high),
|
||||||
|
c_ulong(block_low),
|
||||||
|
offset
|
||||||
|
)
|
||||||
|
if result:
|
||||||
|
raise ValueError("Error %d while seeking with ChaCha20" % result)
|
||||||
|
|
||||||
|
|
||||||
|
def new(**kwargs):
|
||||||
|
"""Create a new ChaCha20 cipher
|
||||||
|
|
||||||
|
:Keywords:
|
||||||
|
key : byte string
|
||||||
|
The secret key to use in the symmetric cipher.
|
||||||
|
It must be 32 bytes long.
|
||||||
|
|
||||||
|
nonce : byte string
|
||||||
|
A mandatory value that must never be reused for any other encryption
|
||||||
|
done with this key. It must be 8 bytes long.
|
||||||
|
|
||||||
|
If not provided, a random byte string will be generated (you can read
|
||||||
|
it back via the ``nonce`` attribute).
|
||||||
|
|
||||||
|
:Return: a `ChaCha20Cipher` object
|
||||||
|
"""
|
||||||
|
|
||||||
|
try:
|
||||||
|
key = kwargs.pop("key")
|
||||||
|
except KeyError as e:
|
||||||
|
raise TypeError("Missing parameter %s" % e)
|
||||||
|
|
||||||
|
nonce = kwargs.pop("nonce", None)
|
||||||
|
if nonce is None:
|
||||||
|
nonce = get_random_bytes(8)
|
||||||
|
|
||||||
|
if len(key) != 32:
|
||||||
|
raise ValueError("ChaCha20 key must be 32 bytes long")
|
||||||
|
if len(nonce) != 8:
|
||||||
|
raise ValueError("ChaCha20 nonce must be 8 bytes long")
|
||||||
|
|
||||||
|
if kwargs:
|
||||||
|
raise TypeError("Unknown parameters: " + str(kwargs))
|
||||||
|
|
||||||
|
return ChaCha20Cipher(key, nonce)
|
||||||
|
|
||||||
|
#: Size of a data block (in bytes)
|
||||||
|
block_size = 1
|
||||||
|
|
||||||
|
#: Size of a key (in bytes)
|
||||||
|
key_size = 32
|
193
venv/Lib/site-packages/Crypto/Cipher/DES.py
Normal file
193
venv/Lib/site-packages/Crypto/Cipher/DES.py
Normal file
|
@ -0,0 +1,193 @@
|
||||||
|
# -*- 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. The effective key length is
|
||||||
|
therefore 56 bits only.
|
||||||
|
|
||||||
|
DES is cryptographically secure, but its key length is too short by nowadays
|
||||||
|
standards and it could be brute forced with some effort.
|
||||||
|
|
||||||
|
**Use DES, not AES. This module is provided only for legacy purposes.**
|
||||||
|
|
||||||
|
As an example, encryption can be done as follows:
|
||||||
|
|
||||||
|
>>> from Crypto.Cipher import DES
|
||||||
|
>>>
|
||||||
|
>>> key = b'-8B key-'
|
||||||
|
>>> cipher = DES.new(key, DES.MODE_OFB)
|
||||||
|
>>> plaintext = b'sona si latine loqueris '
|
||||||
|
>>> msg = cipher.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: __package__
|
||||||
|
"""
|
||||||
|
|
||||||
|
import sys
|
||||||
|
|
||||||
|
from Crypto.Cipher import _create_cipher
|
||||||
|
from Crypto.Util.py3compat import byte_string
|
||||||
|
from Crypto.Util._raw_api import (load_pycryptodome_raw_lib,
|
||||||
|
VoidPointer, SmartPointer,
|
||||||
|
c_size_t, expect_byte_string)
|
||||||
|
|
||||||
|
_raw_des_lib = load_pycryptodome_raw_lib(
|
||||||
|
"Crypto.Cipher._raw_des",
|
||||||
|
"""
|
||||||
|
int DES_start_operation(const uint8_t key[],
|
||||||
|
size_t key_len,
|
||||||
|
void **pResult);
|
||||||
|
int DES_encrypt(const void *state,
|
||||||
|
const uint8_t *in,
|
||||||
|
uint8_t *out,
|
||||||
|
size_t data_len);
|
||||||
|
int DES_decrypt(const void *state,
|
||||||
|
const uint8_t *in,
|
||||||
|
uint8_t *out,
|
||||||
|
size_t data_len);
|
||||||
|
int DES_stop_operation(void *state);
|
||||||
|
""")
|
||||||
|
|
||||||
|
|
||||||
|
def _create_base_cipher(dict_parameters):
|
||||||
|
"""This method instantiates and returns a handle to a low-level
|
||||||
|
base cipher. It will absorb named parameters in the process."""
|
||||||
|
|
||||||
|
try:
|
||||||
|
key = dict_parameters.pop("key")
|
||||||
|
except KeyError:
|
||||||
|
raise TypeError("Missing 'key' parameter")
|
||||||
|
|
||||||
|
expect_byte_string(key)
|
||||||
|
|
||||||
|
if len(key) != key_size:
|
||||||
|
raise ValueError("Incorrect DES key length (%d bytes)" % len(key))
|
||||||
|
|
||||||
|
start_operation = _raw_des_lib.DES_start_operation
|
||||||
|
stop_operation = _raw_des_lib.DES_stop_operation
|
||||||
|
|
||||||
|
cipher = VoidPointer()
|
||||||
|
result = start_operation(key,
|
||||||
|
c_size_t(len(key)),
|
||||||
|
cipher.address_of())
|
||||||
|
if result:
|
||||||
|
raise ValueError("Error %X while instantiating the DES cipher"
|
||||||
|
% result)
|
||||||
|
return SmartPointer(cipher.get(), stop_operation)
|
||||||
|
|
||||||
|
|
||||||
|
def new(key, mode, *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.
|
||||||
|
|
||||||
|
iv : byte string
|
||||||
|
(*Only* `MODE_CBC`, `MODE_CFB`, `MODE_OFB`, `MODE_OPENPGP`).
|
||||||
|
|
||||||
|
The initialization vector to use for encryption or decryption.
|
||||||
|
|
||||||
|
For `MODE_OPENPGP`, IV must be 8 bytes long for encryption
|
||||||
|
and 10 bytes for decryption (in the latter case, it is
|
||||||
|
actually the *encrypted* IV which was prefixed to the ciphertext).
|
||||||
|
|
||||||
|
For all other modes, it must be 8 bytes long.
|
||||||
|
|
||||||
|
If not provided, a random byte string is generated (you can read it
|
||||||
|
back via the ``iv`` attribute).
|
||||||
|
|
||||||
|
nonce : byte string
|
||||||
|
(*Only* `MODE_EAX` and `MODE_CTR`).
|
||||||
|
A mandatory value that must never be reused for any other encryption.
|
||||||
|
|
||||||
|
For `MODE_CTR`, its length must be in the range ``[0..7]``.
|
||||||
|
|
||||||
|
For `MODE_EAX`, there are no restrictions, but it is recommended to
|
||||||
|
use at least 16 bytes.
|
||||||
|
|
||||||
|
If not provided for `MODE_EAX`, a random byte string is generated (you
|
||||||
|
can read it back via the ``nonce`` attribute).
|
||||||
|
|
||||||
|
mac_len : integer
|
||||||
|
(*Only* `MODE_EAX`). Length of the authentication tag, in bytes.
|
||||||
|
It must be no larger than 8 (which is the default).
|
||||||
|
|
||||||
|
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 not specified, it will be assumed to be 8.
|
||||||
|
|
||||||
|
initial_value : integer
|
||||||
|
(*Only* `MODE_CTR`). The initial value for the counter within
|
||||||
|
the counter block. By default it is 0.
|
||||||
|
|
||||||
|
:Return: a DES cipher, of the applicable mode:
|
||||||
|
|
||||||
|
- CBC_ mode
|
||||||
|
- CFB_ mode
|
||||||
|
- CTR_ mode
|
||||||
|
- EAX_ mode
|
||||||
|
- ECB_ mode
|
||||||
|
- OFB_ mode
|
||||||
|
- OpenPgp_ mode
|
||||||
|
|
||||||
|
.. _CBC: Crypto.Cipher._mode_cbc.CbcMode-class.html
|
||||||
|
.. _CFB: Crypto.Cipher._mode_cfb.CfbMode-class.html
|
||||||
|
.. _CTR: Crypto.Cipher._mode_ctr.CtrMode-class.html
|
||||||
|
.. _EAX: Crypto.Cipher._mode_eax.EaxMode-class.html
|
||||||
|
.. _ECB: Crypto.Cipher._mode_ecb.EcbMode-class.html
|
||||||
|
.. _OFB: Crypto.Cipher._mode_ofb.OfbMode-class.html
|
||||||
|
.. _OpenPgp: Crypto.Cipher._mode_openpgp.OpenPgpMode-class.html
|
||||||
|
"""
|
||||||
|
|
||||||
|
return _create_cipher(sys.modules[__name__], key, mode, *args, **kwargs)
|
||||||
|
|
||||||
|
#: Electronic Code Book (ECB). See `Crypto.Cipher._mode_ecb.EcbMode`.
|
||||||
|
MODE_ECB = 1
|
||||||
|
#: Cipher-Block Chaining (CBC). See `Crypto.Cipher._mode_cbc.CbcMode`.
|
||||||
|
MODE_CBC = 2
|
||||||
|
#: Cipher FeedBack (CFB). See `Crypto.Cipher._mode_cfb.CfbMode`.
|
||||||
|
MODE_CFB = 3
|
||||||
|
#: Output FeedBack (OFB). See `Crypto.Cipher._mode_ofb.OfbMode`.
|
||||||
|
MODE_OFB = 5
|
||||||
|
#: CounTer Mode (CTR). See `Crypto.Cipher._mode_ctr.CtrMode`.
|
||||||
|
MODE_CTR = 6
|
||||||
|
#: OpenPGP Mode. See `Crypto.Cipher._mode_openpgp.OpenPgpMode`.
|
||||||
|
MODE_OPENPGP = 7
|
||||||
|
#: EAX Mode. See `Crypto.Cipher._mode_eax.EaxMode`.
|
||||||
|
MODE_EAX = 9
|
||||||
|
|
||||||
|
#: Size of a data block (in bytes)
|
||||||
|
block_size = 8
|
||||||
|
#: Size of a key (in bytes)
|
||||||
|
key_size = 8
|
237
venv/Lib/site-packages/Crypto/Cipher/DES3.py
Normal file
237
venv/Lib/site-packages/Crypto/Cipher/DES3.py
Normal file
|
@ -0,0 +1,237 @@
|
||||||
|
# -*- 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.
|
||||||
|
|
||||||
|
TDES consists of the concatenation of 3 simple Single `DES` ciphers
|
||||||
|
(encryption - decryption - encryption), where each stage uses an
|
||||||
|
indipendent sub-key.
|
||||||
|
|
||||||
|
A TDES key is therefore 24 (8+8+8) bytes long. However, like Single DES,
|
||||||
|
only 7 out of 8 bits are actually used: the remaining ones are parity
|
||||||
|
bits (which practically all TDES implementations ignore).
|
||||||
|
Theoreticaly, Triple DES achieves up to 112 bits of effective security.
|
||||||
|
|
||||||
|
Triple DES can also operate with a 16 bytes key (Option 2, also termed 2TDES),
|
||||||
|
in which case subkey *K1* equals subkey *K2*. The effective security
|
||||||
|
is as low as `90 bits`_.
|
||||||
|
|
||||||
|
Thi implementation checks and enforces the condition *K1 != K2 != K3*
|
||||||
|
(Option 3), as it degrades Triple DES to Single DES.
|
||||||
|
|
||||||
|
*Use AES, not TDES. This module is provided for legacy purposes only.**
|
||||||
|
|
||||||
|
As an example, encryption can be done as follows:
|
||||||
|
|
||||||
|
>>> from Crypto.Cipher import DES3
|
||||||
|
>>> from Crypto.Random import get_random_bytes
|
||||||
|
>>>
|
||||||
|
>>> # When generating a Triple DES key you must check that
|
||||||
|
>>> # subkey1 != subkey2 and subkey2 != subkey3
|
||||||
|
>>> while True:
|
||||||
|
>>> try:
|
||||||
|
>>> key = DES3.adjust_key_parity(get_random_bytes(24))
|
||||||
|
>>> break
|
||||||
|
>>> except ValueError
|
||||||
|
>>> pass
|
||||||
|
>>>
|
||||||
|
>>> cipher = DES3.new(key, DES3.MODE_CFB)
|
||||||
|
>>> plaintext = b'We are no longer the knights who say ni!'
|
||||||
|
>>> msg = cipher.nonce + cipher.encrypt(plaintext)
|
||||||
|
|
||||||
|
.. __: http://en.wikipedia.org/wiki/Triple_DES
|
||||||
|
.. _NIST: http://csrc.nist.gov/publications/nistpubs/800-67-Rev1/SP-800-67-Rev1.pdf
|
||||||
|
.. _90 bits: http://people.scs.carleton.ca/~paulv/papers/Euro90.pdf
|
||||||
|
|
||||||
|
:undocumented: __package__
|
||||||
|
"""
|
||||||
|
|
||||||
|
import sys
|
||||||
|
|
||||||
|
from Crypto.Cipher import _create_cipher
|
||||||
|
from Crypto.Util.py3compat import byte_string, b, bchr, bord
|
||||||
|
from Crypto.Util._raw_api import (load_pycryptodome_raw_lib,
|
||||||
|
VoidPointer, SmartPointer,
|
||||||
|
c_size_t, expect_byte_string)
|
||||||
|
|
||||||
|
_raw_des3_lib = load_pycryptodome_raw_lib(
|
||||||
|
"Crypto.Cipher._raw_des3",
|
||||||
|
"""
|
||||||
|
int DES3_start_operation(const uint8_t key[],
|
||||||
|
size_t key_len,
|
||||||
|
void **pResult);
|
||||||
|
int DES3_encrypt(const void *state,
|
||||||
|
const uint8_t *in,
|
||||||
|
uint8_t *out,
|
||||||
|
size_t data_len);
|
||||||
|
int DES3_decrypt(const void *state,
|
||||||
|
const uint8_t *in,
|
||||||
|
uint8_t *out,
|
||||||
|
size_t data_len);
|
||||||
|
int DES3_stop_operation(void *state);
|
||||||
|
""")
|
||||||
|
|
||||||
|
|
||||||
|
def adjust_key_parity(key_in):
|
||||||
|
"""Return the TDES key with parity bits correctly set"""
|
||||||
|
|
||||||
|
def parity_byte(key_byte):
|
||||||
|
parity = 1
|
||||||
|
for i in range(1, 8):
|
||||||
|
parity ^= (key_byte >> i) & 1
|
||||||
|
return (key_byte & 0xFE) | parity
|
||||||
|
|
||||||
|
if len(key_in) not in key_size:
|
||||||
|
raise ValueError("Not a valid TDES key")
|
||||||
|
|
||||||
|
key_out = b("").join([ bchr(parity_byte(bord(x)) )for x in key_in ])
|
||||||
|
|
||||||
|
if key_out[:8] == key_out[8:16] or key_out[-16:-8] == key_out[-8:]:
|
||||||
|
raise ValueError("Triple DES key degenerates to single DES")
|
||||||
|
|
||||||
|
return key_out
|
||||||
|
|
||||||
|
|
||||||
|
def _create_base_cipher(dict_parameters):
|
||||||
|
"""This method instantiates and returns a handle to a low-level base cipher.
|
||||||
|
It will absorb named parameters in the process."""
|
||||||
|
|
||||||
|
try:
|
||||||
|
key_in = dict_parameters.pop("key")
|
||||||
|
except KeyError:
|
||||||
|
raise TypeError("Missing 'key' parameter")
|
||||||
|
|
||||||
|
key = adjust_key_parity(key_in)
|
||||||
|
|
||||||
|
start_operation = _raw_des3_lib.DES3_start_operation
|
||||||
|
stop_operation = _raw_des3_lib.DES3_stop_operation
|
||||||
|
|
||||||
|
cipher = VoidPointer()
|
||||||
|
result = start_operation(key,
|
||||||
|
c_size_t(len(key)),
|
||||||
|
cipher.address_of())
|
||||||
|
if result:
|
||||||
|
raise ValueError("Error %X while instantiating the TDES cipher"
|
||||||
|
% result)
|
||||||
|
return SmartPointer(cipher.get(), stop_operation)
|
||||||
|
|
||||||
|
|
||||||
|
def new(key, mode, *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.
|
||||||
|
The condition K1 != K2 != K3 must hold.
|
||||||
|
|
||||||
|
mode : a *MODE_** constant
|
||||||
|
The chaining mode to use for encryption or decryption.
|
||||||
|
|
||||||
|
:Keywords:
|
||||||
|
iv : byte string
|
||||||
|
(*Only* `MODE_CBC`, `MODE_CFB`, `MODE_OFB`, `MODE_OPENPGP`).
|
||||||
|
|
||||||
|
The initialization vector to use for encryption or decryption.
|
||||||
|
|
||||||
|
For `MODE_OPENPGP`, IV must be 8 bytes long for encryption
|
||||||
|
and 10 bytes for decryption (in the latter case, it is
|
||||||
|
actually the *encrypted* IV which was prefixed to the ciphertext).
|
||||||
|
|
||||||
|
For all other modes, it must be 8 bytes long.
|
||||||
|
|
||||||
|
If not provided, a random byte string will be generated (you can read
|
||||||
|
it back via the ``iv`` attribute).
|
||||||
|
|
||||||
|
nonce : byte string
|
||||||
|
(*Only* `MODE_EAX` and `MODE_CTR`)
|
||||||
|
A value that must never be reused for any other encryption.
|
||||||
|
|
||||||
|
For `MODE_CTR`, its length must be in the range ``[0..7]``.
|
||||||
|
|
||||||
|
For `MODE_EAX`, there are no restrictions, but it is recommended to
|
||||||
|
use at least 16 bytes.
|
||||||
|
|
||||||
|
If not provided for `MODE_EAX`, a random 16 byte string is generated
|
||||||
|
(you can read it back via the ``nonce`` attribute).
|
||||||
|
|
||||||
|
mac_len : integer
|
||||||
|
(*Only* `MODE_EAX`). Length of the authentication tag, in bytes.
|
||||||
|
It must be no larger than 8 (which is the default).
|
||||||
|
|
||||||
|
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 not specified, it will be assumed to be 8.
|
||||||
|
|
||||||
|
initial_value : integer
|
||||||
|
(*Only* `MODE_CTR`). The initial value for the counter within
|
||||||
|
the counter block. By default it is 0.
|
||||||
|
|
||||||
|
:Attention: it is important that all 8 byte subkeys are different,
|
||||||
|
otherwise TDES would degrade to single `DES`.
|
||||||
|
|
||||||
|
:Raise ValueError:
|
||||||
|
when the key degrades to Single DES.
|
||||||
|
|
||||||
|
:Return: a DES cipher object, of the applicable mode:
|
||||||
|
|
||||||
|
- CBC_ mode
|
||||||
|
- CFB_ mode
|
||||||
|
- CTR_ mode
|
||||||
|
- EAX_ mode
|
||||||
|
- ECB_ mode
|
||||||
|
- OFB_ mode
|
||||||
|
- OpenPgp_ mode
|
||||||
|
|
||||||
|
.. _CBC: Crypto.Cipher._mode_cbc.CbcMode-class.html
|
||||||
|
.. _CFB: Crypto.Cipher._mode_cfb.CfbMode-class.html
|
||||||
|
.. _CTR: Crypto.Cipher._mode_ctr.CtrMode-class.html
|
||||||
|
.. _EAX: Crypto.Cipher._mode_eax.EaxMode-class.html
|
||||||
|
.. _ECB: Crypto.Cipher._mode_ecb.EcbMode-class.html
|
||||||
|
.. _OFB: Crypto.Cipher._mode_ofb.OfbMode-class.html
|
||||||
|
.. _OpenPgp: Crypto.Cipher._mode_openpgp.OpenPgpMode-class.html
|
||||||
|
"""
|
||||||
|
|
||||||
|
return _create_cipher(sys.modules[__name__], key, mode, *args, **kwargs)
|
||||||
|
|
||||||
|
#: Electronic Code Book (ECB). See `Crypto.Cipher._mode_ecb.EcbMode`.
|
||||||
|
MODE_ECB = 1
|
||||||
|
#: Cipher-Block Chaining (CBC). See `Crypto.Cipher._mode_cbc.CbcMode`.
|
||||||
|
MODE_CBC = 2
|
||||||
|
#: Cipher FeedBack (CFB). See `Crypto.Cipher._mode_cfb.CfbMode`.
|
||||||
|
MODE_CFB = 3
|
||||||
|
#: Output FeedBack (OFB). See `Crypto.Cipher._mode_ofb.OfbMode`.
|
||||||
|
MODE_OFB = 5
|
||||||
|
#: CounTer Mode (CTR). See `Crypto.Cipher._mode_ctr.CtrMode`.
|
||||||
|
MODE_CTR = 6
|
||||||
|
#: OpenPGP Mode. See `Crypto.Cipher._mode_openpgp.OpenPgpMode`.
|
||||||
|
MODE_OPENPGP = 7
|
||||||
|
#: EAX Mode. See `Crypto.Cipher._mode_eax.EaxMode`.
|
||||||
|
MODE_EAX = 9
|
||||||
|
|
||||||
|
#: Size of a data block (in bytes)
|
||||||
|
block_size = 8
|
||||||
|
#: Size of a key (in bytes)
|
||||||
|
key_size = (16, 24)
|
261
venv/Lib/site-packages/Crypto/Cipher/PKCS1_OAEP.py
Normal file
261
venv/Lib/site-packages/Crypto/Cipher/PKCS1_OAEP.py
Normal file
|
@ -0,0 +1,261 @@
|
||||||
|
# -*- 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 = b'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)
|
||||||
|
|
||||||
|
.. __: http://www.ietf.org/rfc/rfc3447.txt
|
||||||
|
.. __: http://www.rsa.com/rsalabs/node.asp?id=2125.
|
||||||
|
"""
|
||||||
|
|
||||||
|
__all__ = [ 'new', 'PKCS1OAEP_Cipher' ]
|
||||||
|
|
||||||
|
from Crypto.Signature.pss import MGF1
|
||||||
|
import Crypto.Hash.SHA1
|
||||||
|
|
||||||
|
from Crypto.Util.py3compat import *
|
||||||
|
import Crypto.Util.number
|
||||||
|
from Crypto.Util.number import ceil_div, bytes_to_long, long_to_bytes
|
||||||
|
from Crypto.Util.strxor import strxor
|
||||||
|
from Crypto import Random
|
||||||
|
|
||||||
|
class PKCS1OAEP_Cipher:
|
||||||
|
"""This cipher can perform PKCS#1 v1.5 OAEP encryption or decryption."""
|
||||||
|
|
||||||
|
def __init__(self, key, hashAlgo, mgfunc, label, randfunc):
|
||||||
|
"""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.SHA1` 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 : byte string
|
||||||
|
A label to apply to this particular encryption. If not specified,
|
||||||
|
an empty string is used. Specifying a label does not improve
|
||||||
|
security.
|
||||||
|
randfunc : callable
|
||||||
|
A function that returns random bytes.
|
||||||
|
|
||||||
|
: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.SHA1
|
||||||
|
|
||||||
|
if mgfunc:
|
||||||
|
self._mgf = mgfunc
|
||||||
|
else:
|
||||||
|
self._mgf = lambda x,y: MGF1(x,y,self._hashObj)
|
||||||
|
|
||||||
|
self._label = label
|
||||||
|
self._randfunc = randfunc
|
||||||
|
|
||||||
|
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 : 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 2, minus twice the hash output size.
|
||||||
|
|
||||||
|
: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
|
||||||
|
|
||||||
|
# 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 = self._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)
|
||||||
|
em_int = bytes_to_long(em)
|
||||||
|
# Step 3b (RSAEP)
|
||||||
|
m_int = self._key._encrypt(em_int)
|
||||||
|
# Step 3c (I2OSP)
|
||||||
|
c = long_to_bytes(m_int, k)
|
||||||
|
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 : byte string
|
||||||
|
The ciphertext that contains the message to recover.
|
||||||
|
|
||||||
|
:Return: A byte 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.
|
||||||
|
"""
|
||||||
|
|
||||||
|
# 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)
|
||||||
|
ct_int = bytes_to_long(ct)
|
||||||
|
# Step 2b (RSADP)
|
||||||
|
m_int = self._key._decrypt(ct_int)
|
||||||
|
# Complete step 2c (I2OSP)
|
||||||
|
em = long_to_bytes(m_int, k)
|
||||||
|
# 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(''), randfunc=None):
|
||||||
|
"""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.SHA1` 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 : byte string
|
||||||
|
A label to apply to this particular encryption. If not specified,
|
||||||
|
an empty string is used. Specifying a label does not improve
|
||||||
|
security.
|
||||||
|
randfunc : callable
|
||||||
|
A function that returns random bytes.
|
||||||
|
The default is `Random.get_random_bytes`.
|
||||||
|
|
||||||
|
:attention: Modify the mask generation function only if you know what you are doing.
|
||||||
|
Sender and receiver must use the same one.
|
||||||
|
"""
|
||||||
|
|
||||||
|
if randfunc is None:
|
||||||
|
randfunc = Random.get_random_bytes
|
||||||
|
return PKCS1OAEP_Cipher(key, hashAlgo, mgfunc, label, randfunc)
|
||||||
|
|
236
venv/Lib/site-packages/Crypto/Cipher/PKCS1_v1_5.py
Normal file
236
venv/Lib/site-packages/Crypto/Cipher/PKCS1_v1_5.py
Normal file
|
@ -0,0 +1,236 @@
|
||||||
|
# -*- 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 = b'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.
|
||||||
|
"""
|
||||||
|
|
||||||
|
__all__ = [ 'new', 'PKCS115_Cipher' ]
|
||||||
|
|
||||||
|
from Crypto.Util.number import ceil_div, bytes_to_long, long_to_bytes
|
||||||
|
from Crypto.Util.py3compat import *
|
||||||
|
import Crypto.Util.number
|
||||||
|
from Crypto import Random
|
||||||
|
|
||||||
|
class PKCS115_Cipher:
|
||||||
|
"""This cipher can perform PKCS#1 v1.5 RSA encryption or decryption."""
|
||||||
|
|
||||||
|
def __init__(self, key, randfunc):
|
||||||
|
"""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.
|
||||||
|
randfunc : callable
|
||||||
|
Function that returns random bytes.
|
||||||
|
"""
|
||||||
|
|
||||||
|
self._key = key
|
||||||
|
self._randfunc = randfunc
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
# 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
|
||||||
|
ps = []
|
||||||
|
while len(ps) != k - mLen - 3:
|
||||||
|
new_byte = self._randfunc(1)
|
||||||
|
if bord(new_byte[0]) == 0x00:
|
||||||
|
continue
|
||||||
|
ps.append(new_byte)
|
||||||
|
ps = b("").join(ps)
|
||||||
|
assert(len(ps) == k - mLen - 3)
|
||||||
|
# Step 2b
|
||||||
|
em = b('\x00\x02') + ps + bchr(0x00) + message
|
||||||
|
# Step 3a (OS2IP)
|
||||||
|
em_int = bytes_to_long(em)
|
||||||
|
# Step 3b (RSAEP)
|
||||||
|
m_int = self._key._encrypt(em_int)
|
||||||
|
# Step 3c (I2OSP)
|
||||||
|
c = long_to_bytes(m_int, k)
|
||||||
|
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
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
# 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)
|
||||||
|
ct_int = bytes_to_long(ct)
|
||||||
|
# Step 2b (RSADP)
|
||||||
|
m_int = self._key._decrypt(ct_int)
|
||||||
|
# Complete step 2c (I2OSP)
|
||||||
|
em = long_to_bytes(m_int, k)
|
||||||
|
# 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, randfunc=None):
|
||||||
|
"""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.
|
||||||
|
randfunc : callable
|
||||||
|
Function that return random bytes.
|
||||||
|
The default is `Crypto.Random.get_random_bytes`.
|
||||||
|
"""
|
||||||
|
|
||||||
|
if randfunc is None:
|
||||||
|
randfunc = Random.get_random_bytes
|
||||||
|
return PKCS115_Cipher(key, randfunc)
|
||||||
|
|
164
venv/Lib/site-packages/Crypto/Cipher/Salsa20.py
Normal file
164
venv/Lib/site-packages/Crypto/Cipher/Salsa20.py
Normal file
|
@ -0,0 +1,164 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
#
|
||||||
|
# Cipher/Salsa20.py : Salsa20 stream cipher (http://cr.yp.to/snuffle.html)
|
||||||
|
#
|
||||||
|
# Contributed by Fabrizio Tarizzo <fabrizio@fabriziotarizzo.org>.
|
||||||
|
#
|
||||||
|
# ===================================================================
|
||||||
|
# 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.
|
||||||
|
# ===================================================================
|
||||||
|
"""Salsa20 stream cipher
|
||||||
|
|
||||||
|
`Salsa20`_ is a stream cipher designed by Daniel J. Bernstein.
|
||||||
|
|
||||||
|
Its key is by preference 256 bits long, but it can also work
|
||||||
|
with 128 bit keys.
|
||||||
|
|
||||||
|
As an example, encryption can be done as follows:
|
||||||
|
|
||||||
|
>>> from Crypto.Cipher import Salsa20
|
||||||
|
>>>
|
||||||
|
>>> key = b'*Thirty-two byte (256 bits) key*'
|
||||||
|
>>> cipher = Salsa20.new(key)
|
||||||
|
>>> msg = cipher.nonce + cipher.encrypt(b'Attack at dawn')
|
||||||
|
|
||||||
|
.. _Salsa20: http://cr.yp.to/snuffle/spec.pdf
|
||||||
|
|
||||||
|
:undocumented: __package__
|
||||||
|
"""
|
||||||
|
|
||||||
|
from Crypto.Util._raw_api import (load_pycryptodome_raw_lib,
|
||||||
|
create_string_buffer,
|
||||||
|
get_raw_buffer, VoidPointer,
|
||||||
|
SmartPointer, c_size_t,
|
||||||
|
expect_byte_string)
|
||||||
|
|
||||||
|
from Crypto.Random import get_random_bytes
|
||||||
|
|
||||||
|
_raw_salsa20_lib = load_pycryptodome_raw_lib("Crypto.Cipher._Salsa20",
|
||||||
|
"""
|
||||||
|
int Salsa20_stream_init(uint8_t *key, size_t keylen,
|
||||||
|
uint8_t *nonce, size_t nonce_len,
|
||||||
|
void **pSalsaState);
|
||||||
|
int Salsa20_stream_destroy(void *salsaState);
|
||||||
|
int Salsa20_stream_encrypt(void *salsaState,
|
||||||
|
const uint8_t in[],
|
||||||
|
uint8_t out[], size_t len);
|
||||||
|
""")
|
||||||
|
|
||||||
|
|
||||||
|
class Salsa20Cipher:
|
||||||
|
"""Salsa20 cipher object"""
|
||||||
|
|
||||||
|
def __init__(self, key, nonce):
|
||||||
|
"""Initialize a Salsa20 cipher object
|
||||||
|
|
||||||
|
See also `new()` at the module level."""
|
||||||
|
|
||||||
|
if len(key) not in key_size:
|
||||||
|
raise ValueError("Incorrect key length for Salsa20 (%d bytes)" % len(key))
|
||||||
|
|
||||||
|
if len(nonce) != 8:
|
||||||
|
raise ValueError("Incorrect nonce length for Salsa20 (%d bytes)" %
|
||||||
|
len(nonce))
|
||||||
|
|
||||||
|
#: Nonce
|
||||||
|
self.nonce = nonce
|
||||||
|
|
||||||
|
expect_byte_string(key)
|
||||||
|
expect_byte_string(nonce)
|
||||||
|
|
||||||
|
self._state = VoidPointer()
|
||||||
|
result = _raw_salsa20_lib.Salsa20_stream_init(
|
||||||
|
key,
|
||||||
|
c_size_t(len(key)),
|
||||||
|
nonce,
|
||||||
|
c_size_t(len(nonce)),
|
||||||
|
self._state.address_of())
|
||||||
|
if result:
|
||||||
|
raise ValueError("Error %d instantiating a Salsa20 cipher")
|
||||||
|
self._state = SmartPointer(self._state.get(),
|
||||||
|
_raw_salsa20_lib.Salsa20_stream_destroy)
|
||||||
|
|
||||||
|
self.block_size = 1
|
||||||
|
self.key_size = len(key)
|
||||||
|
|
||||||
|
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).
|
||||||
|
"""
|
||||||
|
|
||||||
|
expect_byte_string(plaintext)
|
||||||
|
ciphertext = create_string_buffer(len(plaintext))
|
||||||
|
result = _raw_salsa20_lib.Salsa20_stream_encrypt(
|
||||||
|
self._state.get(),
|
||||||
|
plaintext,
|
||||||
|
ciphertext,
|
||||||
|
c_size_t(len(plaintext)))
|
||||||
|
if result:
|
||||||
|
raise ValueError("Error %d while encrypting with Salsa20" % result)
|
||||||
|
return get_raw_buffer(ciphertext)
|
||||||
|
|
||||||
|
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).
|
||||||
|
"""
|
||||||
|
|
||||||
|
try:
|
||||||
|
return self.encrypt(ciphertext)
|
||||||
|
except ValueError as e:
|
||||||
|
raise ValueError(str(e).replace("enc", "dec"))
|
||||||
|
|
||||||
|
def new(key, nonce=None):
|
||||||
|
"""Create a new Salsa20 cipher
|
||||||
|
|
||||||
|
:Parameters:
|
||||||
|
key : byte string
|
||||||
|
The secret key to use in the symmetric cipher.
|
||||||
|
It must be 16 or 32 bytes long.
|
||||||
|
|
||||||
|
nonce : byte string
|
||||||
|
A value that must never be reused for any other encryption.
|
||||||
|
It must be 8 bytes long.
|
||||||
|
|
||||||
|
If not provided, a random byte string will be generated (you can
|
||||||
|
read it back via the ``nonce`` attribute).
|
||||||
|
|
||||||
|
:Return: an `Salsa20Cipher` object
|
||||||
|
"""
|
||||||
|
|
||||||
|
if nonce is None:
|
||||||
|
nonce = get_random_bytes(8)
|
||||||
|
|
||||||
|
return Salsa20Cipher(key, nonce)
|
||||||
|
|
||||||
|
#: Size of a data block (in bytes)
|
||||||
|
block_size = 1
|
||||||
|
|
||||||
|
#: Size of a key (in bytes)
|
||||||
|
key_size = (16, 32)
|
||||||
|
|
BIN
venv/Lib/site-packages/Crypto/Cipher/_ARC4.cp36-win32.pyd
Normal file
BIN
venv/Lib/site-packages/Crypto/Cipher/_ARC4.cp36-win32.pyd
Normal file
Binary file not shown.
BIN
venv/Lib/site-packages/Crypto/Cipher/_Salsa20.cp36-win32.pyd
Normal file
BIN
venv/Lib/site-packages/Crypto/Cipher/_Salsa20.cp36-win32.pyd
Normal file
Binary file not shown.
130
venv/Lib/site-packages/Crypto/Cipher/__init__.py
Normal file
130
venv/Lib/site-packages/Crypto/Cipher/__init__.py
Normal file
|
@ -0,0 +1,130 @@
|
||||||
|
# -*- 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.Salsa20` Stream Salsa20
|
||||||
|
`Crypto.Cipher.ChaCha20` Stream ChaCha20
|
||||||
|
======================== ======= ========================
|
||||||
|
|
||||||
|
|
||||||
|
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: __package__, _AES, _ARC2, _ARC4, _Blowfish
|
||||||
|
_CAST, _DES, _DES3, _XOR, _AESNI, _Salsa20
|
||||||
|
"""
|
||||||
|
|
||||||
|
import os
|
||||||
|
|
||||||
|
from Crypto.Cipher._mode_ecb import _create_ecb_cipher
|
||||||
|
from Crypto.Cipher._mode_cbc import _create_cbc_cipher
|
||||||
|
from Crypto.Cipher._mode_cfb import _create_cfb_cipher
|
||||||
|
from Crypto.Cipher._mode_ofb import _create_ofb_cipher
|
||||||
|
from Crypto.Cipher._mode_ctr import _create_ctr_cipher
|
||||||
|
from Crypto.Cipher._mode_openpgp import _create_openpgp_cipher
|
||||||
|
from Crypto.Cipher._mode_ccm import _create_ccm_cipher
|
||||||
|
from Crypto.Cipher._mode_eax import _create_eax_cipher
|
||||||
|
from Crypto.Cipher._mode_siv import _create_siv_cipher
|
||||||
|
from Crypto.Cipher._mode_gcm import _create_gcm_cipher
|
||||||
|
from Crypto.Cipher._mode_ocb import _create_ocb_cipher
|
||||||
|
|
||||||
|
_modes = { 1:_create_ecb_cipher,
|
||||||
|
2:_create_cbc_cipher,
|
||||||
|
3:_create_cfb_cipher,
|
||||||
|
5:_create_ofb_cipher,
|
||||||
|
6:_create_ctr_cipher,
|
||||||
|
7:_create_openpgp_cipher,
|
||||||
|
9:_create_eax_cipher
|
||||||
|
}
|
||||||
|
|
||||||
|
_extra_modes = { 8:_create_ccm_cipher,
|
||||||
|
10:_create_siv_cipher,
|
||||||
|
11:_create_gcm_cipher,
|
||||||
|
12:_create_ocb_cipher
|
||||||
|
}
|
||||||
|
|
||||||
|
def _create_cipher(factory, key, mode, *args, **kwargs):
|
||||||
|
|
||||||
|
kwargs["key"] = key
|
||||||
|
|
||||||
|
modes = dict(_modes)
|
||||||
|
if kwargs.pop("add_aes_modes", False):
|
||||||
|
modes.update(_extra_modes)
|
||||||
|
if mode not in modes:
|
||||||
|
raise ValueError("Mode not supported")
|
||||||
|
|
||||||
|
if args:
|
||||||
|
if mode in (8, 9, 10, 11, 12):
|
||||||
|
if len(args) > 1:
|
||||||
|
raise TypeError("Too many arguments for this mode")
|
||||||
|
kwargs["nonce"] = args[0]
|
||||||
|
elif mode in (2, 3, 5, 7):
|
||||||
|
if len(args) > 1:
|
||||||
|
raise TypeError("Too many arguments for this mode")
|
||||||
|
kwargs["IV"] = args[0]
|
||||||
|
elif mode == 6:
|
||||||
|
if len(args) > 0:
|
||||||
|
raise TypeError("Too many arguments for this mode")
|
||||||
|
elif mode == 1:
|
||||||
|
raise TypeError("IV is not meaningful for the ECB mode")
|
||||||
|
|
||||||
|
return modes[mode](factory, **kwargs)
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
venv/Lib/site-packages/Crypto/Cipher/_chacha20.cp36-win32.pyd
Normal file
BIN
venv/Lib/site-packages/Crypto/Cipher/_chacha20.cp36-win32.pyd
Normal file
Binary file not shown.
247
venv/Lib/site-packages/Crypto/Cipher/_mode_cbc.py
Normal file
247
venv/Lib/site-packages/Crypto/Cipher/_mode_cbc.py
Normal file
|
@ -0,0 +1,247 @@
|
||||||
|
# ===================================================================
|
||||||
|
#
|
||||||
|
# Copyright (c) 2014, Legrandin <helderijs@gmail.com>
|
||||||
|
# All rights reserved.
|
||||||
|
#
|
||||||
|
# Redistribution and use in source and binary forms, with or without
|
||||||
|
# modification, are permitted provided that the following conditions
|
||||||
|
# are met:
|
||||||
|
#
|
||||||
|
# 1. Redistributions of source code must retain the above copyright
|
||||||
|
# notice, this list of conditions and the following disclaimer.
|
||||||
|
# 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
# notice, this list of conditions and the following disclaimer in
|
||||||
|
# the documentation and/or other materials provided with the
|
||||||
|
# distribution.
|
||||||
|
#
|
||||||
|
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||||
|
# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||||
|
# COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||||
|
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||||
|
# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||||
|
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||||
|
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||||
|
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
|
# POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
# ===================================================================
|
||||||
|
|
||||||
|
"""
|
||||||
|
Ciphertext Block Chaining (CBC) mode.
|
||||||
|
"""
|
||||||
|
|
||||||
|
__all__ = ['CbcMode']
|
||||||
|
|
||||||
|
from Crypto.Util._raw_api import (load_pycryptodome_raw_lib, VoidPointer,
|
||||||
|
create_string_buffer, get_raw_buffer,
|
||||||
|
SmartPointer, c_size_t, expect_byte_string)
|
||||||
|
|
||||||
|
from Crypto.Random import get_random_bytes
|
||||||
|
|
||||||
|
raw_cbc_lib = load_pycryptodome_raw_lib("Crypto.Cipher._raw_cbc", """
|
||||||
|
int CBC_start_operation(void *cipher,
|
||||||
|
const uint8_t iv[],
|
||||||
|
size_t iv_len,
|
||||||
|
void **pResult);
|
||||||
|
int CBC_encrypt(void *cbcState,
|
||||||
|
const uint8_t *in,
|
||||||
|
uint8_t *out,
|
||||||
|
size_t data_len);
|
||||||
|
int CBC_decrypt(void *cbcState,
|
||||||
|
const uint8_t *in,
|
||||||
|
uint8_t *out,
|
||||||
|
size_t data_len);
|
||||||
|
int CBC_stop_operation(void *state);
|
||||||
|
"""
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class CbcMode(object):
|
||||||
|
"""*Cipher-Block Chaining (CBC)*.
|
||||||
|
|
||||||
|
Each of the ciphertext blocks depends on the current
|
||||||
|
and all previous plaintext blocks.
|
||||||
|
|
||||||
|
An Initialization Vector (*IV*) is required.
|
||||||
|
|
||||||
|
See `NIST SP800-38A`_ , Section 6.2 .
|
||||||
|
|
||||||
|
.. _`NIST SP800-38A` : http://csrc.nist.gov/publications/nistpubs/800-38a/sp800-38a.pdf
|
||||||
|
|
||||||
|
:undocumented: __init__
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__(self, block_cipher, iv):
|
||||||
|
"""Create a new block cipher, configured in CBC mode.
|
||||||
|
|
||||||
|
:Parameters:
|
||||||
|
block_cipher : C pointer
|
||||||
|
A smart pointer to the low-level block cipher instance.
|
||||||
|
|
||||||
|
iv : byte string
|
||||||
|
The initialization vector to use for encryption or decryption.
|
||||||
|
It is as long as the cipher block.
|
||||||
|
|
||||||
|
**The IV must be unpredictable**. Ideally it is picked randomly.
|
||||||
|
|
||||||
|
Reusing the *IV* for encryptions performed with the same key
|
||||||
|
compromises confidentiality.
|
||||||
|
"""
|
||||||
|
|
||||||
|
expect_byte_string(iv)
|
||||||
|
self._state = VoidPointer()
|
||||||
|
result = raw_cbc_lib.CBC_start_operation(block_cipher.get(),
|
||||||
|
iv,
|
||||||
|
c_size_t(len(iv)),
|
||||||
|
self._state.address_of())
|
||||||
|
if result:
|
||||||
|
raise ValueError("Error %d while instatiating the CBC mode"
|
||||||
|
% result)
|
||||||
|
|
||||||
|
# Ensure that object disposal of this Python object will (eventually)
|
||||||
|
# free the memory allocated by the raw library for the cipher mode
|
||||||
|
self._state = SmartPointer(self._state.get(),
|
||||||
|
raw_cbc_lib.CBC_stop_operation)
|
||||||
|
|
||||||
|
# Memory allocated for the underlying block cipher is now owed
|
||||||
|
# by the cipher mode
|
||||||
|
block_cipher.release()
|
||||||
|
|
||||||
|
self.block_size = len(iv)
|
||||||
|
"""The block size of the underlying cipher, in bytes."""
|
||||||
|
|
||||||
|
self.iv = iv
|
||||||
|
"""The Initialization Vector originally used to create the object.
|
||||||
|
The value does not change."""
|
||||||
|
|
||||||
|
self.IV = iv
|
||||||
|
"""Alias for `iv`"""
|
||||||
|
|
||||||
|
self._next = [ self.encrypt, self.decrypt ]
|
||||||
|
|
||||||
|
def encrypt(self, plaintext):
|
||||||
|
"""Encrypt data with the key and the parameters set at initialization.
|
||||||
|
|
||||||
|
A cipher object is stateful: once you have encrypted a message
|
||||||
|
you cannot encrypt (or decrypt) another message using the same
|
||||||
|
object.
|
||||||
|
|
||||||
|
The data to encrypt can be broken up in two or
|
||||||
|
more pieces and `encrypt` can be called multiple times.
|
||||||
|
|
||||||
|
That is, the statement:
|
||||||
|
|
||||||
|
>>> c.encrypt(a) + c.encrypt(b)
|
||||||
|
|
||||||
|
is 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 add any padding to the plaintext.
|
||||||
|
|
||||||
|
:Parameters:
|
||||||
|
plaintext : byte string
|
||||||
|
The piece of data to encrypt.
|
||||||
|
Its lenght must be multiple of the cipher block size.
|
||||||
|
:Return:
|
||||||
|
the encrypted data, as a byte string.
|
||||||
|
It is as long as *plaintext*.
|
||||||
|
"""
|
||||||
|
|
||||||
|
if self.encrypt not in self._next:
|
||||||
|
raise TypeError("encrypt() cannot be called after decrypt()")
|
||||||
|
self._next = [ self.encrypt ]
|
||||||
|
|
||||||
|
expect_byte_string(plaintext)
|
||||||
|
ciphertext = create_string_buffer(len(plaintext))
|
||||||
|
result = raw_cbc_lib.CBC_encrypt(self._state.get(),
|
||||||
|
plaintext,
|
||||||
|
ciphertext,
|
||||||
|
c_size_t(len(plaintext)))
|
||||||
|
if result:
|
||||||
|
raise ValueError("Error %d while encrypting in CBC mode" % result)
|
||||||
|
return get_raw_buffer(ciphertext)
|
||||||
|
|
||||||
|
def decrypt(self, ciphertext):
|
||||||
|
"""Decrypt data with the key and the parameters set at initialization.
|
||||||
|
|
||||||
|
A cipher object is stateful: once you have decrypted a message
|
||||||
|
you cannot decrypt (or encrypt) another message with the same
|
||||||
|
object.
|
||||||
|
|
||||||
|
The data to decrypt can be broken up in two or
|
||||||
|
more pieces and `decrypt` can be called multiple times.
|
||||||
|
|
||||||
|
That is, the statement:
|
||||||
|
|
||||||
|
>>> c.decrypt(a) + c.decrypt(b)
|
||||||
|
|
||||||
|
is equivalent to:
|
||||||
|
|
||||||
|
>>> c.decrypt(a+b)
|
||||||
|
|
||||||
|
This function does not remove any padding from the plaintext.
|
||||||
|
|
||||||
|
:Parameters:
|
||||||
|
ciphertext : byte string
|
||||||
|
The piece of data to decrypt.
|
||||||
|
Its length must be multiple of the cipher block size.
|
||||||
|
|
||||||
|
:Return: the decrypted data (byte string).
|
||||||
|
"""
|
||||||
|
|
||||||
|
if self.decrypt not in self._next:
|
||||||
|
raise TypeError("decrypt() cannot be called after encrypt()")
|
||||||
|
self._next = [ self.decrypt ]
|
||||||
|
|
||||||
|
expect_byte_string(ciphertext)
|
||||||
|
plaintext = create_string_buffer(len(ciphertext))
|
||||||
|
result = raw_cbc_lib.CBC_decrypt(self._state.get(),
|
||||||
|
ciphertext,
|
||||||
|
plaintext,
|
||||||
|
c_size_t(len(ciphertext)))
|
||||||
|
if result:
|
||||||
|
raise ValueError("Error %d while decrypting in CBC mode" % result)
|
||||||
|
return get_raw_buffer(plaintext)
|
||||||
|
|
||||||
|
|
||||||
|
def _create_cbc_cipher(factory, **kwargs):
|
||||||
|
"""Instantiate a cipher object that performs CBC encryption/decryption.
|
||||||
|
|
||||||
|
:Parameters:
|
||||||
|
factory : module
|
||||||
|
The underlying block cipher, a module from ``Crypto.Cipher``.
|
||||||
|
|
||||||
|
:Keywords:
|
||||||
|
iv : byte string
|
||||||
|
The IV to use for CBC.
|
||||||
|
|
||||||
|
IV : byte string
|
||||||
|
Alias for ``iv``.
|
||||||
|
|
||||||
|
Any other keyword will be passed to the underlying block cipher.
|
||||||
|
See the relevant documentation for details (at least ``key`` will need
|
||||||
|
to be present).
|
||||||
|
"""
|
||||||
|
|
||||||
|
cipher_state = factory._create_base_cipher(kwargs)
|
||||||
|
iv = kwargs.pop("IV", None)
|
||||||
|
IV = kwargs.pop("iv", None)
|
||||||
|
|
||||||
|
if (None, None) == (iv, IV):
|
||||||
|
iv = get_random_bytes(factory.block_size)
|
||||||
|
if iv is not None:
|
||||||
|
if IV is not None:
|
||||||
|
raise TypeError("You must either use 'iv' or 'IV', not both")
|
||||||
|
else:
|
||||||
|
iv = IV
|
||||||
|
|
||||||
|
if kwargs:
|
||||||
|
raise TypeError("Unknown parameters for CBC: %s" % str(kwargs))
|
||||||
|
|
||||||
|
return CbcMode(cipher_state, iv)
|
620
venv/Lib/site-packages/Crypto/Cipher/_mode_ccm.py
Normal file
620
venv/Lib/site-packages/Crypto/Cipher/_mode_ccm.py
Normal file
|
@ -0,0 +1,620 @@
|
||||||
|
# ===================================================================
|
||||||
|
#
|
||||||
|
# Copyright (c) 2014, Legrandin <helderijs@gmail.com>
|
||||||
|
# All rights reserved.
|
||||||
|
#
|
||||||
|
# Redistribution and use in source and binary forms, with or without
|
||||||
|
# modification, are permitted provided that the following conditions
|
||||||
|
# are met:
|
||||||
|
#
|
||||||
|
# 1. Redistributions of source code must retain the above copyright
|
||||||
|
# notice, this list of conditions and the following disclaimer.
|
||||||
|
# 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
# notice, this list of conditions and the following disclaimer in
|
||||||
|
# the documentation and/or other materials provided with the
|
||||||
|
# distribution.
|
||||||
|
#
|
||||||
|
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||||
|
# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||||
|
# COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||||
|
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||||
|
# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||||
|
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||||
|
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||||
|
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
|
# POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
# ===================================================================
|
||||||
|
|
||||||
|
"""
|
||||||
|
Counter with CBC-MAC (CCM) mode.
|
||||||
|
"""
|
||||||
|
|
||||||
|
__all__ = ['CcmMode']
|
||||||
|
|
||||||
|
from Crypto.Util.py3compat import byte_string, b, bchr, bord, unhexlify
|
||||||
|
|
||||||
|
from Crypto.Util.strxor import strxor
|
||||||
|
from Crypto.Util.number import long_to_bytes
|
||||||
|
|
||||||
|
from Crypto.Hash import BLAKE2s
|
||||||
|
from Crypto.Random import get_random_bytes
|
||||||
|
|
||||||
|
|
||||||
|
def enum(**enums):
|
||||||
|
return type('Enum', (), enums)
|
||||||
|
|
||||||
|
MacStatus = enum(NOT_STARTED=0, PROCESSING_AUTH_DATA=1, PROCESSING_PLAINTEXT=2)
|
||||||
|
|
||||||
|
|
||||||
|
class CcmMode(object):
|
||||||
|
"""Counter with CBC-MAC (CCM).
|
||||||
|
|
||||||
|
This is an Authenticated Encryption with Associated Data (`AEAD`_) mode.
|
||||||
|
It provides both confidentiality and authenticity.
|
||||||
|
|
||||||
|
The header of the message may be left in the clear, if needed, and it will
|
||||||
|
still be subject to authentication. The decryption step tells the receiver
|
||||||
|
if the message comes from a source that really knowns the secret key.
|
||||||
|
Additionally, decryption detects if any part of the message - including the
|
||||||
|
header - has been modified or corrupted.
|
||||||
|
|
||||||
|
This mode requires a nonce. The nonce shall never repeat for two
|
||||||
|
different messages encrypted with the same key, but it does not need
|
||||||
|
to be random.
|
||||||
|
Note that there is a trade-off between the size of the nonce and the
|
||||||
|
maximum size of a single message you can encrypt.
|
||||||
|
|
||||||
|
It is important to use a large nonce if the key is reused across several
|
||||||
|
messages and the nonce is chosen randomly.
|
||||||
|
|
||||||
|
It is acceptable to us a short nonce if the key is only used a few times or
|
||||||
|
if the nonce is taken from a counter.
|
||||||
|
|
||||||
|
The following table shows the trade-off when the nonce is chosen at
|
||||||
|
random. The column on the left shows how many messages it takes
|
||||||
|
for the keystream to repeat **on average**. In practice, you will want to
|
||||||
|
stop using the key way before that.
|
||||||
|
|
||||||
|
+--------------------+---------------+-------------------+
|
||||||
|
| Avg. # of messages | nonce | Max. message |
|
||||||
|
| before keystream | size | size |
|
||||||
|
| repeats | (bytes) | (bytes) |
|
||||||
|
+====================+===============+===================+
|
||||||
|
| 2^52 | 13 | 64K |
|
||||||
|
+--------------------+---------------+-------------------+
|
||||||
|
| 2^48 | 12 | 16M |
|
||||||
|
+--------------------+---------------+-------------------+
|
||||||
|
| 2^44 | 11 | 4G |
|
||||||
|
+--------------------+---------------+-------------------+
|
||||||
|
| 2^40 | 10 | 1T |
|
||||||
|
+--------------------+---------------+-------------------+
|
||||||
|
| 2^36 | 9 | 64P |
|
||||||
|
+--------------------+---------------+-------------------+
|
||||||
|
| 2^32 | 8 | 16E |
|
||||||
|
+--------------------+---------------+-------------------+
|
||||||
|
|
||||||
|
This mode is only available for ciphers that operate on 128 bits blocks
|
||||||
|
(e.g. AES but not TDES).
|
||||||
|
|
||||||
|
See `NIST SP800-38C`_ or RFC3610_.
|
||||||
|
|
||||||
|
.. _`NIST SP800-38C`: http://csrc.nist.gov/publications/nistpubs/800-38C/SP800-38C.pdf
|
||||||
|
.. _RFC3610: https://tools.ietf.org/html/rfc3610
|
||||||
|
.. _AEAD: http://blog.cryptographyengineering.com/2012/05/how-to-choose-authenticated-encryption.html
|
||||||
|
|
||||||
|
:undocumented: __init__
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__(self, factory, key, nonce, mac_len, msg_len, assoc_len,
|
||||||
|
cipher_params):
|
||||||
|
|
||||||
|
self.block_size = factory.block_size
|
||||||
|
"""The block size of the underlying cipher, in bytes."""
|
||||||
|
|
||||||
|
self.nonce = nonce
|
||||||
|
"""The nonce used for this cipher instance"""
|
||||||
|
|
||||||
|
self._factory = factory
|
||||||
|
self._key = key
|
||||||
|
self._mac_len = mac_len
|
||||||
|
self._msg_len = msg_len
|
||||||
|
self._assoc_len = assoc_len
|
||||||
|
self._cipher_params = cipher_params
|
||||||
|
|
||||||
|
self._mac_tag = None # Cache for MAC tag
|
||||||
|
|
||||||
|
if self.block_size != 16:
|
||||||
|
raise ValueError("CCM mode is only available for ciphers"
|
||||||
|
" that operate on 128 bits blocks")
|
||||||
|
|
||||||
|
# MAC tag length (Tlen)
|
||||||
|
if mac_len not in (4, 6, 8, 10, 12, 14, 16):
|
||||||
|
raise ValueError("Parameter 'mac_len' must be even"
|
||||||
|
" and in the range 4..16 (not %d)" % mac_len)
|
||||||
|
|
||||||
|
# Nonce value
|
||||||
|
if not (nonce and 7 <= len(nonce) <= 13):
|
||||||
|
raise ValueError("Length of parameter 'nonce' must be"
|
||||||
|
" in the range 7..13 bytes")
|
||||||
|
|
||||||
|
# Create MAC object (the tag will be the last block
|
||||||
|
# bytes worth of ciphertext)
|
||||||
|
self._mac = self._factory.new(key,
|
||||||
|
factory.MODE_CBC,
|
||||||
|
iv=bchr(0) * 16,
|
||||||
|
**cipher_params)
|
||||||
|
self._mac_status = MacStatus.NOT_STARTED
|
||||||
|
self._t = None
|
||||||
|
|
||||||
|
# Allowed transitions after initialization
|
||||||
|
self._next = [self.update, self.encrypt, self.decrypt,
|
||||||
|
self.digest, self.verify]
|
||||||
|
|
||||||
|
# Cumulative lengths
|
||||||
|
self._cumul_assoc_len = 0
|
||||||
|
self._cumul_msg_len = 0
|
||||||
|
|
||||||
|
# Cache for unaligned associated data/plaintext.
|
||||||
|
# This is a list, but when the MAC starts, it will become a binary
|
||||||
|
# string no longer than the block size.
|
||||||
|
self._cache = []
|
||||||
|
|
||||||
|
# Start CTR cipher, by formatting the counter (A.3)
|
||||||
|
q = 15 - len(nonce) # length of Q, the encoded message length
|
||||||
|
self._cipher = self._factory.new(key,
|
||||||
|
self._factory.MODE_CTR,
|
||||||
|
nonce=bchr(q - 1) + nonce,
|
||||||
|
**cipher_params)
|
||||||
|
|
||||||
|
# S_0, step 6 in 6.1 for j=0
|
||||||
|
self._s_0 = self._cipher.encrypt(bchr(0) * 16)
|
||||||
|
|
||||||
|
# Try to start the MAC
|
||||||
|
if None not in (assoc_len, msg_len):
|
||||||
|
self._start_mac()
|
||||||
|
|
||||||
|
def _start_mac(self):
|
||||||
|
|
||||||
|
assert(self._mac_status == MacStatus.NOT_STARTED)
|
||||||
|
assert(None not in (self._assoc_len, self._msg_len))
|
||||||
|
assert(isinstance(self._cache, list))
|
||||||
|
|
||||||
|
# Formatting control information and nonce (A.2.1)
|
||||||
|
q = 15 - len(self.nonce) # length of Q, the encoded message length
|
||||||
|
flags = (64 * (self._assoc_len > 0) + 8 * ((self._mac_len - 2) // 2) +
|
||||||
|
(q - 1))
|
||||||
|
b_0 = bchr(flags) + self.nonce + long_to_bytes(self._msg_len, q)
|
||||||
|
|
||||||
|
# Formatting associated data (A.2.2)
|
||||||
|
# Encoded 'a' is concatenated with the associated data 'A'
|
||||||
|
assoc_len_encoded = b('')
|
||||||
|
if self._assoc_len > 0:
|
||||||
|
if self._assoc_len < (2 ** 16 - 2 ** 8):
|
||||||
|
enc_size = 2
|
||||||
|
elif self._assoc_len < (2 ** 32):
|
||||||
|
assoc_len_encoded = b('\xFF\xFE')
|
||||||
|
enc_size = 4
|
||||||
|
else:
|
||||||
|
assoc_len_encoded = b('\xFF\xFF')
|
||||||
|
enc_size = 8
|
||||||
|
assoc_len_encoded += long_to_bytes(self._assoc_len, enc_size)
|
||||||
|
|
||||||
|
# b_0 and assoc_len_encoded must be processed first
|
||||||
|
self._cache.insert(0, b_0)
|
||||||
|
self._cache.insert(1, assoc_len_encoded)
|
||||||
|
|
||||||
|
# Process all the data cached so far
|
||||||
|
first_data_to_mac = b("").join(self._cache)
|
||||||
|
self._cache = b("")
|
||||||
|
self._mac_status = MacStatus.PROCESSING_AUTH_DATA
|
||||||
|
self._update(first_data_to_mac)
|
||||||
|
|
||||||
|
def _pad_cache_and_update(self):
|
||||||
|
|
||||||
|
assert(self._mac_status != MacStatus.NOT_STARTED)
|
||||||
|
assert(byte_string(self._cache))
|
||||||
|
assert(len(self._cache) < self.block_size)
|
||||||
|
|
||||||
|
# Associated data is concatenated with the least number
|
||||||
|
# of zero bytes (possibly none) to reach alignment to
|
||||||
|
# the 16 byte boundary (A.2.3)
|
||||||
|
len_cache = len(self._cache)
|
||||||
|
if len_cache > 0:
|
||||||
|
self._update(bchr(0) * (self.block_size - len_cache))
|
||||||
|
|
||||||
|
def update(self, assoc_data):
|
||||||
|
"""Protect associated data
|
||||||
|
|
||||||
|
If there is any associated data, the caller has to invoke
|
||||||
|
this function one or more times, before using
|
||||||
|
``decrypt`` or ``encrypt``.
|
||||||
|
|
||||||
|
By *associated data* it is meant any data (e.g. packet headers) that
|
||||||
|
will not be encrypted and will be transmitted in the clear.
|
||||||
|
However, the receiver is still able to detect any modification to it.
|
||||||
|
In CCM, the *associated data* is also called
|
||||||
|
*additional authenticated data* (AAD).
|
||||||
|
|
||||||
|
If there is no associated data, this method must not be called.
|
||||||
|
|
||||||
|
The caller may split associated data in segments of any size, and
|
||||||
|
invoke this method multiple times, each time with the next segment.
|
||||||
|
|
||||||
|
:Parameters:
|
||||||
|
assoc_data : byte string
|
||||||
|
A piece of associated data. There are no restrictions on its size.
|
||||||
|
"""
|
||||||
|
|
||||||
|
if self.update not in self._next:
|
||||||
|
raise TypeError("update() can only be called"
|
||||||
|
" immediately after initialization")
|
||||||
|
|
||||||
|
self._next = [self.update, self.encrypt, self.decrypt,
|
||||||
|
self.digest, self.verify]
|
||||||
|
|
||||||
|
self._cumul_assoc_len += len(assoc_data)
|
||||||
|
if self._assoc_len is not None and \
|
||||||
|
self._cumul_assoc_len > self._assoc_len:
|
||||||
|
raise ValueError("Associated data is too long")
|
||||||
|
|
||||||
|
self._update(assoc_data)
|
||||||
|
return self
|
||||||
|
|
||||||
|
def _update(self, assoc_data_pt=b("")):
|
||||||
|
"""Update the MAC with associated data or plaintext
|
||||||
|
(without FSM checks)"""
|
||||||
|
|
||||||
|
if self._mac_status == MacStatus.NOT_STARTED:
|
||||||
|
self._cache.append(assoc_data_pt)
|
||||||
|
return
|
||||||
|
|
||||||
|
assert(byte_string(self._cache))
|
||||||
|
assert(len(self._cache) < self.block_size)
|
||||||
|
|
||||||
|
if len(self._cache) > 0:
|
||||||
|
filler = min(self.block_size - len(self._cache),
|
||||||
|
len(assoc_data_pt))
|
||||||
|
self._cache += assoc_data_pt[:filler]
|
||||||
|
assoc_data_pt = assoc_data_pt[filler:]
|
||||||
|
|
||||||
|
if len(self._cache) < self.block_size:
|
||||||
|
return
|
||||||
|
|
||||||
|
# The cache is exactly one block
|
||||||
|
self._t = self._mac.encrypt(self._cache)
|
||||||
|
self._cache = b("")
|
||||||
|
|
||||||
|
update_len = len(assoc_data_pt) // self.block_size * self.block_size
|
||||||
|
self._cache = assoc_data_pt[update_len:]
|
||||||
|
if update_len > 0:
|
||||||
|
self._t = self._mac.encrypt(assoc_data_pt[:update_len])[-16:]
|
||||||
|
|
||||||
|
def encrypt(self, plaintext):
|
||||||
|
"""Encrypt data with the key set at initialization.
|
||||||
|
|
||||||
|
A cipher object is stateful: once you have encrypted a message
|
||||||
|
you cannot encrypt (or decrypt) another message using the same
|
||||||
|
object.
|
||||||
|
|
||||||
|
This method can be called only **once** if ``msg_len`` was
|
||||||
|
not passed at initialization.
|
||||||
|
|
||||||
|
If ``msg_len`` was given, the data to encrypt can be broken
|
||||||
|
up in two or more pieces and `encrypt` can be called
|
||||||
|
multiple times.
|
||||||
|
|
||||||
|
That is, the statement:
|
||||||
|
|
||||||
|
>>> c.encrypt(a) + c.encrypt(b)
|
||||||
|
|
||||||
|
is equivalent to:
|
||||||
|
|
||||||
|
>>> c.encrypt(a+b)
|
||||||
|
|
||||||
|
This function does not add any padding to the plaintext.
|
||||||
|
|
||||||
|
:Parameters:
|
||||||
|
plaintext : byte string
|
||||||
|
The piece of data to encrypt.
|
||||||
|
It can be of any length.
|
||||||
|
:Return:
|
||||||
|
the encrypted data, as a byte string.
|
||||||
|
It is as long as *plaintext*.
|
||||||
|
"""
|
||||||
|
|
||||||
|
if self.encrypt not in self._next:
|
||||||
|
raise TypeError("encrypt() can only be called after"
|
||||||
|
" initialization or an update()")
|
||||||
|
self._next = [self.encrypt, self.digest]
|
||||||
|
|
||||||
|
# No more associated data allowed from now
|
||||||
|
if self._assoc_len is None:
|
||||||
|
assert(isinstance(self._cache, list))
|
||||||
|
self._assoc_len = sum([len(x) for x in self._cache])
|
||||||
|
if self._msg_len is not None:
|
||||||
|
self._start_mac()
|
||||||
|
else:
|
||||||
|
if self._cumul_assoc_len < self._assoc_len:
|
||||||
|
raise ValueError("Associated data is too short")
|
||||||
|
|
||||||
|
# Only once piece of plaintext accepted if message length was
|
||||||
|
# not declared in advance
|
||||||
|
if self._msg_len is None:
|
||||||
|
self._msg_len = len(plaintext)
|
||||||
|
self._start_mac()
|
||||||
|
self._next = [self.digest]
|
||||||
|
|
||||||
|
self._cumul_msg_len += len(plaintext)
|
||||||
|
if self._cumul_msg_len > self._msg_len:
|
||||||
|
raise ValueError("Message is too long")
|
||||||
|
|
||||||
|
if self._mac_status == MacStatus.PROCESSING_AUTH_DATA:
|
||||||
|
# Associated data is concatenated with the least number
|
||||||
|
# of zero bytes (possibly none) to reach alignment to
|
||||||
|
# the 16 byte boundary (A.2.3)
|
||||||
|
self._pad_cache_and_update()
|
||||||
|
self._mac_status = MacStatus.PROCESSING_PLAINTEXT
|
||||||
|
|
||||||
|
self._update(plaintext)
|
||||||
|
return self._cipher.encrypt(plaintext)
|
||||||
|
|
||||||
|
def decrypt(self, ciphertext):
|
||||||
|
"""Decrypt data with the key set at initialization.
|
||||||
|
|
||||||
|
A cipher object is stateful: once you have decrypted a message
|
||||||
|
you cannot decrypt (or encrypt) another message with the same
|
||||||
|
object.
|
||||||
|
|
||||||
|
This method can be called only **once** if ``msg_len`` was
|
||||||
|
not passed at initialization.
|
||||||
|
|
||||||
|
If ``msg_len`` was given, the data to decrypt can be
|
||||||
|
broken up in two or more pieces and `decrypt` can be
|
||||||
|
called multiple times.
|
||||||
|
|
||||||
|
That is, the statement:
|
||||||
|
|
||||||
|
>>> c.decrypt(a) + c.decrypt(b)
|
||||||
|
|
||||||
|
is equivalent to:
|
||||||
|
|
||||||
|
>>> c.decrypt(a+b)
|
||||||
|
|
||||||
|
This function does not remove any padding from the plaintext.
|
||||||
|
|
||||||
|
:Parameters:
|
||||||
|
ciphertext : byte string
|
||||||
|
The piece of data to decrypt.
|
||||||
|
It can be of any length.
|
||||||
|
|
||||||
|
:Return: the decrypted data (byte string).
|
||||||
|
"""
|
||||||
|
|
||||||
|
if self.decrypt not in self._next:
|
||||||
|
raise TypeError("decrypt() can only be called"
|
||||||
|
" after initialization or an update()")
|
||||||
|
self._next = [self.decrypt, self.verify]
|
||||||
|
|
||||||
|
# No more associated data allowed from now
|
||||||
|
if self._assoc_len is None:
|
||||||
|
assert(isinstance(self._cache, list))
|
||||||
|
self._assoc_len = sum([len(x) for x in self._cache])
|
||||||
|
if self._msg_len is not None:
|
||||||
|
self._start_mac()
|
||||||
|
else:
|
||||||
|
if self._cumul_assoc_len < self._assoc_len:
|
||||||
|
raise ValueError("Associated data is too short")
|
||||||
|
|
||||||
|
# Only once piece of ciphertext accepted if message length was
|
||||||
|
# not declared in advance
|
||||||
|
if self._msg_len is None:
|
||||||
|
self._msg_len = len(ciphertext)
|
||||||
|
self._start_mac()
|
||||||
|
self._next = [self.verify]
|
||||||
|
|
||||||
|
self._cumul_msg_len += len(ciphertext)
|
||||||
|
if self._cumul_msg_len > self._msg_len:
|
||||||
|
raise ValueError("Message is too long")
|
||||||
|
|
||||||
|
if self._mac_status == MacStatus.PROCESSING_AUTH_DATA:
|
||||||
|
# Associated data is concatenated with the least number
|
||||||
|
# of zero bytes (possibly none) to reach alignment to
|
||||||
|
# the 16 byte boundary (A.2.3)
|
||||||
|
self._pad_cache_and_update()
|
||||||
|
self._mac_status = MacStatus.PROCESSING_PLAINTEXT
|
||||||
|
|
||||||
|
# Encrypt is equivalent to decrypt with the CTR mode
|
||||||
|
plaintext = self._cipher.encrypt(ciphertext)
|
||||||
|
self._update(plaintext)
|
||||||
|
return plaintext
|
||||||
|
|
||||||
|
def digest(self):
|
||||||
|
"""Compute the *binary* MAC tag.
|
||||||
|
|
||||||
|
The caller invokes this function at the very end.
|
||||||
|
|
||||||
|
This method returns the MAC that shall be sent to the receiver,
|
||||||
|
together with the ciphertext.
|
||||||
|
|
||||||
|
:Return: the MAC, as a byte string.
|
||||||
|
"""
|
||||||
|
|
||||||
|
if self.digest not in self._next:
|
||||||
|
raise TypeError("digest() cannot be called when decrypting"
|
||||||
|
" or validating a message")
|
||||||
|
self._next = [self.digest]
|
||||||
|
return self._digest()
|
||||||
|
|
||||||
|
def _digest(self):
|
||||||
|
if self._mac_tag:
|
||||||
|
return self._mac_tag
|
||||||
|
|
||||||
|
if self._assoc_len is None:
|
||||||
|
assert(isinstance(self._cache, list))
|
||||||
|
self._assoc_len = sum([len(x) for x in self._cache])
|
||||||
|
if self._msg_len is not None:
|
||||||
|
self._start_mac()
|
||||||
|
else:
|
||||||
|
if self._cumul_assoc_len < self._assoc_len:
|
||||||
|
raise ValueError("Associated data is too short")
|
||||||
|
|
||||||
|
if self._msg_len is None:
|
||||||
|
self._msg_len = 0
|
||||||
|
self._start_mac()
|
||||||
|
|
||||||
|
if self._cumul_msg_len != self._msg_len:
|
||||||
|
raise ValueError("Message is too short")
|
||||||
|
|
||||||
|
# Both associated data and payload are concatenated with the least
|
||||||
|
# number of zero bytes (possibly none) that align it to the
|
||||||
|
# 16 byte boundary (A.2.2 and A.2.3)
|
||||||
|
self._pad_cache_and_update()
|
||||||
|
|
||||||
|
# Step 8 in 6.1 (T xor MSB_Tlen(S_0))
|
||||||
|
self._mac_tag = strxor(self._t, self._s_0)[:self._mac_len]
|
||||||
|
|
||||||
|
return self._mac_tag
|
||||||
|
|
||||||
|
def hexdigest(self):
|
||||||
|
"""Compute the *printable* MAC tag.
|
||||||
|
|
||||||
|
This method is like `digest`.
|
||||||
|
|
||||||
|
:Return: the MAC, as a hexadecimal string.
|
||||||
|
"""
|
||||||
|
return "".join(["%02x" % bord(x) for x in self.digest()])
|
||||||
|
|
||||||
|
def verify(self, received_mac_tag):
|
||||||
|
"""Validate the *binary* MAC tag.
|
||||||
|
|
||||||
|
The caller invokes this function at the very end.
|
||||||
|
|
||||||
|
This method checks if the decrypted message is indeed valid
|
||||||
|
(that is, if the key is correct) and it has not been
|
||||||
|
tampered with while in transit.
|
||||||
|
|
||||||
|
:Parameters:
|
||||||
|
received_mac_tag : byte string
|
||||||
|
This is the *binary* MAC, as received from the sender.
|
||||||
|
:Raises ValueError:
|
||||||
|
if the MAC does not match. The message has been tampered with
|
||||||
|
or the key is incorrect.
|
||||||
|
"""
|
||||||
|
|
||||||
|
if self.verify not in self._next:
|
||||||
|
raise TypeError("verify() cannot be called"
|
||||||
|
" when encrypting a message")
|
||||||
|
self._next = [self.verify]
|
||||||
|
|
||||||
|
self._digest()
|
||||||
|
secret = get_random_bytes(16)
|
||||||
|
|
||||||
|
mac1 = BLAKE2s.new(digest_bits=160, key=secret, data=self._mac_tag)
|
||||||
|
mac2 = BLAKE2s.new(digest_bits=160, key=secret, data=received_mac_tag)
|
||||||
|
|
||||||
|
if mac1.digest() != mac2.digest():
|
||||||
|
raise ValueError("MAC check failed")
|
||||||
|
|
||||||
|
def hexverify(self, hex_mac_tag):
|
||||||
|
"""Validate the *printable* MAC tag.
|
||||||
|
|
||||||
|
This method is like `verify`.
|
||||||
|
|
||||||
|
:Parameters:
|
||||||
|
hex_mac_tag : string
|
||||||
|
This is the *printable* MAC, as received from the sender.
|
||||||
|
:Raises ValueError:
|
||||||
|
if the MAC does not match. The message has been tampered with
|
||||||
|
or the key is incorrect.
|
||||||
|
"""
|
||||||
|
|
||||||
|
self.verify(unhexlify(hex_mac_tag))
|
||||||
|
|
||||||
|
def encrypt_and_digest(self, plaintext):
|
||||||
|
"""Perform encrypt() and digest() in one step.
|
||||||
|
|
||||||
|
:Parameters:
|
||||||
|
plaintext : byte string
|
||||||
|
The piece of data to encrypt.
|
||||||
|
:Return:
|
||||||
|
a tuple with two byte strings:
|
||||||
|
|
||||||
|
- the encrypted data
|
||||||
|
- the MAC
|
||||||
|
"""
|
||||||
|
|
||||||
|
return self.encrypt(plaintext), self.digest()
|
||||||
|
|
||||||
|
def decrypt_and_verify(self, ciphertext, received_mac_tag):
|
||||||
|
"""Perform decrypt() and verify() in one step.
|
||||||
|
|
||||||
|
:Parameters:
|
||||||
|
ciphertext : byte string
|
||||||
|
The piece of data to decrypt.
|
||||||
|
received_mac_tag : byte string
|
||||||
|
This is the *binary* MAC, as received from the sender.
|
||||||
|
|
||||||
|
:Return: the decrypted data (byte string).
|
||||||
|
:Raises ValueError:
|
||||||
|
if the MAC does not match. The message has been tampered with
|
||||||
|
or the key is incorrect.
|
||||||
|
"""
|
||||||
|
|
||||||
|
plaintext = self.decrypt(ciphertext)
|
||||||
|
self.verify(received_mac_tag)
|
||||||
|
return plaintext
|
||||||
|
|
||||||
|
|
||||||
|
def _create_ccm_cipher(factory, **kwargs):
|
||||||
|
"""Create a new block cipher, configured in CCM mode.
|
||||||
|
|
||||||
|
:Parameters:
|
||||||
|
factory : module
|
||||||
|
A symmetric cipher module from `Crypto.Cipher` (like
|
||||||
|
`Crypto.Cipher.AES`).
|
||||||
|
|
||||||
|
:Keywords:
|
||||||
|
key : byte string
|
||||||
|
The secret key to use in the symmetric cipher.
|
||||||
|
|
||||||
|
nonce : byte string
|
||||||
|
A value that must never be reused for any other encryption.
|
||||||
|
|
||||||
|
Its length must be in the range ``[7..13]``.
|
||||||
|
11 or 12 bytes are reasonable values in general. Bear in
|
||||||
|
mind that with CCM there is a trade-off between nonce length and
|
||||||
|
maximum message size.
|
||||||
|
|
||||||
|
If not specified, a 11 byte long random string is used.
|
||||||
|
|
||||||
|
mac_len : integer
|
||||||
|
Length of the MAC, in bytes. It must be even and in
|
||||||
|
the range ``[4..16]``. The default is 16.
|
||||||
|
|
||||||
|
msg_len : integer
|
||||||
|
Length of the message to (de)cipher.
|
||||||
|
If not specified, ``encrypt`` or ``decrypt`` may only be called once.
|
||||||
|
|
||||||
|
assoc_len : integer
|
||||||
|
Length of the associated data.
|
||||||
|
If not specified, all data is internally buffered.
|
||||||
|
"""
|
||||||
|
|
||||||
|
try:
|
||||||
|
key = key = kwargs.pop("key")
|
||||||
|
except KeyError as e:
|
||||||
|
raise TypeError("Missing parameter: " + str(e))
|
||||||
|
|
||||||
|
nonce = kwargs.pop("nonce", None) # N
|
||||||
|
if nonce is None:
|
||||||
|
nonce = get_random_bytes(11)
|
||||||
|
mac_len = kwargs.pop("mac_len", factory.block_size)
|
||||||
|
msg_len = kwargs.pop("msg_len", None) # p
|
||||||
|
assoc_len = kwargs.pop("assoc_len", None) # a
|
||||||
|
cipher_params = dict(kwargs)
|
||||||
|
|
||||||
|
return CcmMode(factory, key, nonce, mac_len, msg_len,
|
||||||
|
assoc_len, cipher_params)
|
251
venv/Lib/site-packages/Crypto/Cipher/_mode_cfb.py
Normal file
251
venv/Lib/site-packages/Crypto/Cipher/_mode_cfb.py
Normal file
|
@ -0,0 +1,251 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
#
|
||||||
|
# Cipher/mode_cfb.py : CFB mode
|
||||||
|
#
|
||||||
|
# ===================================================================
|
||||||
|
# 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.
|
||||||
|
# ===================================================================
|
||||||
|
|
||||||
|
"""
|
||||||
|
Counter Feedback (CFB) mode.
|
||||||
|
"""
|
||||||
|
|
||||||
|
__all__ = ['CfbMode']
|
||||||
|
|
||||||
|
from Crypto.Util._raw_api import (load_pycryptodome_raw_lib, VoidPointer,
|
||||||
|
create_string_buffer, get_raw_buffer,
|
||||||
|
SmartPointer, c_size_t, expect_byte_string)
|
||||||
|
|
||||||
|
from Crypto.Random import get_random_bytes
|
||||||
|
|
||||||
|
raw_cfb_lib = load_pycryptodome_raw_lib("Crypto.Cipher._raw_cfb","""
|
||||||
|
int CFB_start_operation(void *cipher,
|
||||||
|
const uint8_t iv[],
|
||||||
|
size_t iv_len,
|
||||||
|
size_t segment_len, /* In bytes */
|
||||||
|
void **pResult);
|
||||||
|
int CFB_encrypt(void *cfbState,
|
||||||
|
const uint8_t *in,
|
||||||
|
uint8_t *out,
|
||||||
|
size_t data_len);
|
||||||
|
int CFB_decrypt(void *cfbState,
|
||||||
|
const uint8_t *in,
|
||||||
|
uint8_t *out,
|
||||||
|
size_t data_len);
|
||||||
|
int CFB_stop_operation(void *state);"""
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class CfbMode(object):
|
||||||
|
"""*Cipher FeedBack (CFB)*.
|
||||||
|
|
||||||
|
This mode is similar to CFB, 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.
|
||||||
|
|
||||||
|
See `NIST SP800-38A`_ , Section 6.3.
|
||||||
|
|
||||||
|
.. _`NIST SP800-38A` : http://csrc.nist.gov/publications/nistpubs/800-38a/sp800-38a.pdf
|
||||||
|
|
||||||
|
:undocumented: __init__
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__(self, block_cipher, iv, segment_size):
|
||||||
|
"""Create a new block cipher, configured in CFB mode.
|
||||||
|
|
||||||
|
:Parameters:
|
||||||
|
block_cipher : C pointer
|
||||||
|
A smart pointer to the low-level block cipher instance.
|
||||||
|
|
||||||
|
iv : byte string
|
||||||
|
The initialization vector to use for encryption or decryption.
|
||||||
|
It is as long as the cipher block.
|
||||||
|
|
||||||
|
**The IV must be unpredictable**. Ideally it is picked randomly.
|
||||||
|
|
||||||
|
Reusing the *IV* for encryptions performed with the same key
|
||||||
|
compromises confidentiality.
|
||||||
|
|
||||||
|
segment_size : integer
|
||||||
|
The number of bytes the plaintext and ciphertext are segmented in.
|
||||||
|
"""
|
||||||
|
|
||||||
|
expect_byte_string(iv)
|
||||||
|
self._state = VoidPointer()
|
||||||
|
result = raw_cfb_lib.CFB_start_operation(block_cipher.get(),
|
||||||
|
iv,
|
||||||
|
c_size_t(len(iv)),
|
||||||
|
c_size_t(segment_size),
|
||||||
|
self._state.address_of())
|
||||||
|
if result:
|
||||||
|
raise ValueError("Error %d while instatiating the CFB mode" % result)
|
||||||
|
|
||||||
|
# Ensure that object disposal of this Python object will (eventually)
|
||||||
|
# free the memory allocated by the raw library for the cipher mode
|
||||||
|
self._state = SmartPointer(self._state.get(),
|
||||||
|
raw_cfb_lib.CFB_stop_operation)
|
||||||
|
|
||||||
|
# Memory allocated for the underlying block cipher is now owed
|
||||||
|
# by the cipher mode
|
||||||
|
block_cipher.release()
|
||||||
|
|
||||||
|
self.block_size = len(iv)
|
||||||
|
"""The block size of the underlying cipher, in bytes."""
|
||||||
|
|
||||||
|
self.iv = iv
|
||||||
|
"""The Initialization Vector originally used to create the object.
|
||||||
|
The value does not change."""
|
||||||
|
|
||||||
|
self.IV = iv
|
||||||
|
"""Alias for `iv`"""
|
||||||
|
|
||||||
|
self._next = [ self.encrypt, self.decrypt ]
|
||||||
|
|
||||||
|
def encrypt(self, plaintext):
|
||||||
|
"""Encrypt data with the key and the parameters set at initialization.
|
||||||
|
|
||||||
|
A cipher object is stateful: once you have encrypted a message
|
||||||
|
you cannot encrypt (or decrypt) another message using the same
|
||||||
|
object.
|
||||||
|
|
||||||
|
The data to encrypt can be broken up in two or
|
||||||
|
more pieces and `encrypt` can be called multiple times.
|
||||||
|
|
||||||
|
That is, the statement:
|
||||||
|
|
||||||
|
>>> c.encrypt(a) + c.encrypt(b)
|
||||||
|
|
||||||
|
is equivalent to:
|
||||||
|
|
||||||
|
>>> c.encrypt(a+b)
|
||||||
|
|
||||||
|
This function does not add any padding to the plaintext.
|
||||||
|
|
||||||
|
:Parameters:
|
||||||
|
plaintext : byte string
|
||||||
|
The piece of data to encrypt.
|
||||||
|
It can be of any length.
|
||||||
|
:Return:
|
||||||
|
the encrypted data, as a byte string.
|
||||||
|
It is as long as *plaintext*.
|
||||||
|
"""
|
||||||
|
|
||||||
|
if self.encrypt not in self._next:
|
||||||
|
raise TypeError("encrypt() cannot be called after decrypt()")
|
||||||
|
self._next = [ self.encrypt ]
|
||||||
|
|
||||||
|
expect_byte_string(plaintext)
|
||||||
|
ciphertext = create_string_buffer(len(plaintext))
|
||||||
|
result = raw_cfb_lib.CFB_encrypt(self._state.get(),
|
||||||
|
plaintext,
|
||||||
|
ciphertext,
|
||||||
|
c_size_t(len(plaintext)))
|
||||||
|
if result:
|
||||||
|
raise ValueError("Error %d while encrypting in CFB mode" % result)
|
||||||
|
return get_raw_buffer(ciphertext)
|
||||||
|
|
||||||
|
def decrypt(self, ciphertext):
|
||||||
|
"""Decrypt data with the key and the parameters set at initialization.
|
||||||
|
|
||||||
|
A cipher object is stateful: once you have decrypted a message
|
||||||
|
you cannot decrypt (or encrypt) another message with the same
|
||||||
|
object.
|
||||||
|
|
||||||
|
The data to decrypt can be broken up in two or
|
||||||
|
more pieces and `decrypt` can be called multiple times.
|
||||||
|
|
||||||
|
That is, the statement:
|
||||||
|
|
||||||
|
>>> c.decrypt(a) + c.decrypt(b)
|
||||||
|
|
||||||
|
is equivalent to:
|
||||||
|
|
||||||
|
>>> c.decrypt(a+b)
|
||||||
|
|
||||||
|
This function does not remove any padding from the plaintext.
|
||||||
|
|
||||||
|
:Parameters:
|
||||||
|
ciphertext : byte string
|
||||||
|
The piece of data to decrypt.
|
||||||
|
It can be of any length.
|
||||||
|
|
||||||
|
:Return: the decrypted data (byte string).
|
||||||
|
"""
|
||||||
|
|
||||||
|
if self.decrypt not in self._next:
|
||||||
|
raise TypeError("decrypt() cannot be called after encrypt()")
|
||||||
|
self._next = [ self.decrypt ]
|
||||||
|
|
||||||
|
expect_byte_string(ciphertext)
|
||||||
|
plaintext = create_string_buffer(len(ciphertext))
|
||||||
|
result = raw_cfb_lib.CFB_decrypt(self._state.get(),
|
||||||
|
ciphertext,
|
||||||
|
plaintext,
|
||||||
|
c_size_t(len(ciphertext)))
|
||||||
|
if result:
|
||||||
|
raise ValueError("Error %d while decrypting in CFB mode" % result)
|
||||||
|
return get_raw_buffer(plaintext)
|
||||||
|
|
||||||
|
|
||||||
|
def _create_cfb_cipher(factory, **kwargs):
|
||||||
|
"""Instantiate a cipher object that performs CFB encryption/decryption.
|
||||||
|
|
||||||
|
:Parameters:
|
||||||
|
factory : module
|
||||||
|
The underlying block cipher, a module from ``Crypto.Cipher``.
|
||||||
|
|
||||||
|
:Keywords:
|
||||||
|
iv : byte string
|
||||||
|
The IV to use for CFB.
|
||||||
|
|
||||||
|
IV : byte string
|
||||||
|
Alias for ``iv``.
|
||||||
|
|
||||||
|
segment_size : integer
|
||||||
|
The number of bit the plaintext and ciphertext are segmented in.
|
||||||
|
If not present, the default is 8.
|
||||||
|
|
||||||
|
Any other keyword will be passed to the underlying block cipher.
|
||||||
|
See the relevant documentation for details (at least ``key`` will need
|
||||||
|
to be present).
|
||||||
|
"""
|
||||||
|
|
||||||
|
cipher_state = factory._create_base_cipher(kwargs)
|
||||||
|
|
||||||
|
iv = kwargs.pop("IV", None)
|
||||||
|
IV = kwargs.pop("iv", None)
|
||||||
|
|
||||||
|
if (None, None) == (iv, IV):
|
||||||
|
iv = get_random_bytes(factory.block_size)
|
||||||
|
if iv is not None:
|
||||||
|
if IV is not None:
|
||||||
|
raise TypeError("You must either use 'iv' or 'IV', not both")
|
||||||
|
else:
|
||||||
|
iv = IV
|
||||||
|
|
||||||
|
segment_size_bytes, rem = divmod(kwargs.pop("segment_size", 8), 8)
|
||||||
|
if segment_size_bytes == 0 or rem != 0:
|
||||||
|
raise ValueError("'segment_size' must be positive and multiple of 8 bits")
|
||||||
|
|
||||||
|
if kwargs:
|
||||||
|
raise TypeError("Unknown parameters for CFB: %s" % str(kwargs))
|
||||||
|
return CfbMode(cipher_state, iv, segment_size_bytes)
|
346
venv/Lib/site-packages/Crypto/Cipher/_mode_ctr.py
Normal file
346
venv/Lib/site-packages/Crypto/Cipher/_mode_ctr.py
Normal file
|
@ -0,0 +1,346 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
#
|
||||||
|
# Cipher/mode_ctr.py : CTR mode
|
||||||
|
#
|
||||||
|
# ===================================================================
|
||||||
|
# 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.
|
||||||
|
# ===================================================================
|
||||||
|
|
||||||
|
"""
|
||||||
|
Counter (CTR) mode.
|
||||||
|
"""
|
||||||
|
|
||||||
|
__all__ = ['CtrMode']
|
||||||
|
|
||||||
|
from Crypto.Util._raw_api import (load_pycryptodome_raw_lib, VoidPointer,
|
||||||
|
create_string_buffer, get_raw_buffer,
|
||||||
|
SmartPointer, c_size_t, expect_byte_string)
|
||||||
|
|
||||||
|
from Crypto.Random import get_random_bytes
|
||||||
|
from Crypto.Util.py3compat import b, bchr
|
||||||
|
from Crypto.Util.number import long_to_bytes
|
||||||
|
|
||||||
|
raw_ctr_lib = load_pycryptodome_raw_lib("Crypto.Cipher._raw_ctr", """
|
||||||
|
int CTR_start_operation(void *cipher,
|
||||||
|
uint8_t initialCounterBlock[],
|
||||||
|
size_t initialCounterBlock_len,
|
||||||
|
size_t prefix_len,
|
||||||
|
unsigned counter_len,
|
||||||
|
unsigned littleEndian,
|
||||||
|
void **pResult);
|
||||||
|
int CTR_encrypt(void *ctrState,
|
||||||
|
const uint8_t *in,
|
||||||
|
uint8_t *out,
|
||||||
|
size_t data_len);
|
||||||
|
int CTR_decrypt(void *ctrState,
|
||||||
|
const uint8_t *in,
|
||||||
|
uint8_t *out,
|
||||||
|
size_t data_len);
|
||||||
|
int CTR_stop_operation(void *ctrState);"""
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class CtrMode(object):
|
||||||
|
"""*CounTeR (CTR)* mode.
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
|
:undocumented: __init__
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__(self, block_cipher, initial_counter_block,
|
||||||
|
prefix_len, counter_len, little_endian):
|
||||||
|
"""Create a new block cipher, configured in CTR mode.
|
||||||
|
|
||||||
|
:Parameters:
|
||||||
|
block_cipher : C pointer
|
||||||
|
A smart pointer to the low-level block cipher instance.
|
||||||
|
|
||||||
|
initial_counter_block : byte string
|
||||||
|
The initial plaintext to use to generate the key stream.
|
||||||
|
|
||||||
|
It is as large as the cipher block, and it embeds
|
||||||
|
the initial value of the counter.
|
||||||
|
|
||||||
|
This value must not be reused.
|
||||||
|
It shall contain a nonce or a random component.
|
||||||
|
Reusing the *initial counter block* for encryptions
|
||||||
|
performed with the same key compromises confidentiality.
|
||||||
|
|
||||||
|
prefix_len : integer
|
||||||
|
The amount of bytes at the beginning of the counter block
|
||||||
|
that never change.
|
||||||
|
|
||||||
|
counter_len : integer
|
||||||
|
The length in bytes of the counter embedded in the counter
|
||||||
|
block.
|
||||||
|
|
||||||
|
little_endian : boolean
|
||||||
|
True if the counter in the counter block is an integer encoded
|
||||||
|
in little endian mode. If False, it is big endian.
|
||||||
|
"""
|
||||||
|
|
||||||
|
if len(initial_counter_block) == prefix_len + counter_len:
|
||||||
|
self.nonce = initial_counter_block[:prefix_len]
|
||||||
|
"""Nonce; not available if there is a fixed suffix"""
|
||||||
|
|
||||||
|
expect_byte_string(initial_counter_block)
|
||||||
|
self._state = VoidPointer()
|
||||||
|
result = raw_ctr_lib.CTR_start_operation(block_cipher.get(),
|
||||||
|
initial_counter_block,
|
||||||
|
c_size_t(len(initial_counter_block)),
|
||||||
|
c_size_t(prefix_len),
|
||||||
|
counter_len,
|
||||||
|
little_endian,
|
||||||
|
self._state.address_of())
|
||||||
|
if result:
|
||||||
|
raise ValueError("Error %X while instatiating the CTR mode"
|
||||||
|
% result)
|
||||||
|
|
||||||
|
# Ensure that object disposal of this Python object will (eventually)
|
||||||
|
# free the memory allocated by the raw library for the cipher mode
|
||||||
|
self._state = SmartPointer(self._state.get(),
|
||||||
|
raw_ctr_lib.CTR_stop_operation)
|
||||||
|
|
||||||
|
# Memory allocated for the underlying block cipher is now owed
|
||||||
|
# by the cipher mode
|
||||||
|
block_cipher.release()
|
||||||
|
|
||||||
|
self.block_size = len(initial_counter_block)
|
||||||
|
"""The block size of the underlying cipher, in bytes."""
|
||||||
|
|
||||||
|
self._next = [self.encrypt, self.decrypt]
|
||||||
|
|
||||||
|
def encrypt(self, plaintext):
|
||||||
|
"""Encrypt data with the key and the parameters set at initialization.
|
||||||
|
|
||||||
|
A cipher object is stateful: once you have encrypted a message
|
||||||
|
you cannot encrypt (or decrypt) another message using the same
|
||||||
|
object.
|
||||||
|
|
||||||
|
The data to encrypt can be broken up in two or
|
||||||
|
more pieces and `encrypt` can be called multiple times.
|
||||||
|
|
||||||
|
That is, the statement:
|
||||||
|
|
||||||
|
>>> c.encrypt(a) + c.encrypt(b)
|
||||||
|
|
||||||
|
is equivalent to:
|
||||||
|
|
||||||
|
>>> c.encrypt(a+b)
|
||||||
|
|
||||||
|
This function does not add any padding to the plaintext.
|
||||||
|
|
||||||
|
:Parameters:
|
||||||
|
plaintext : byte string
|
||||||
|
The piece of data to encrypt.
|
||||||
|
It can be of any length.
|
||||||
|
:Return:
|
||||||
|
the encrypted data, as a byte string.
|
||||||
|
It is as long as *plaintext*.
|
||||||
|
"""
|
||||||
|
|
||||||
|
if self.encrypt not in self._next:
|
||||||
|
raise TypeError("encrypt() cannot be called after decrypt()")
|
||||||
|
self._next = [self.encrypt]
|
||||||
|
|
||||||
|
expect_byte_string(plaintext)
|
||||||
|
ciphertext = create_string_buffer(len(plaintext))
|
||||||
|
result = raw_ctr_lib.CTR_encrypt(self._state.get(),
|
||||||
|
plaintext,
|
||||||
|
ciphertext,
|
||||||
|
c_size_t(len(plaintext)))
|
||||||
|
if result:
|
||||||
|
if result == 0x60002:
|
||||||
|
raise OverflowError("The counter has wrapped around in"
|
||||||
|
" CTR mode")
|
||||||
|
raise ValueError("Error %X while encrypting in CTR mode" % result)
|
||||||
|
return get_raw_buffer(ciphertext)
|
||||||
|
|
||||||
|
def decrypt(self, ciphertext):
|
||||||
|
"""Decrypt data with the key and the parameters set at initialization.
|
||||||
|
|
||||||
|
A cipher object is stateful: once you have decrypted a message
|
||||||
|
you cannot decrypt (or encrypt) another message with the same
|
||||||
|
object.
|
||||||
|
|
||||||
|
The data to decrypt can be broken up in two or
|
||||||
|
more pieces and `decrypt` can be called multiple times.
|
||||||
|
|
||||||
|
That is, the statement:
|
||||||
|
|
||||||
|
>>> c.decrypt(a) + c.decrypt(b)
|
||||||
|
|
||||||
|
is equivalent to:
|
||||||
|
|
||||||
|
>>> c.decrypt(a+b)
|
||||||
|
|
||||||
|
This function does not remove any padding from the plaintext.
|
||||||
|
|
||||||
|
:Parameters:
|
||||||
|
ciphertext : byte string
|
||||||
|
The piece of data to decrypt.
|
||||||
|
It can be of any length.
|
||||||
|
|
||||||
|
:Return: the decrypted data (byte string).
|
||||||
|
"""
|
||||||
|
|
||||||
|
if self.decrypt not in self._next:
|
||||||
|
raise TypeError("decrypt() cannot be called after encrypt()")
|
||||||
|
self._next = [self.decrypt]
|
||||||
|
|
||||||
|
expect_byte_string(ciphertext)
|
||||||
|
plaintext = create_string_buffer(len(ciphertext))
|
||||||
|
result = raw_ctr_lib.CTR_decrypt(self._state.get(),
|
||||||
|
ciphertext,
|
||||||
|
plaintext,
|
||||||
|
c_size_t(len(ciphertext)))
|
||||||
|
if result:
|
||||||
|
if result == 0x60002:
|
||||||
|
raise OverflowError("The counter has wrapped around in"
|
||||||
|
" CTR mode")
|
||||||
|
raise ValueError("Error %X while decrypting in CTR mode" % result)
|
||||||
|
return get_raw_buffer(plaintext)
|
||||||
|
|
||||||
|
|
||||||
|
def _create_ctr_cipher(factory, **kwargs):
|
||||||
|
"""Instantiate a cipher object that performs CTR encryption/decryption.
|
||||||
|
|
||||||
|
:Parameters:
|
||||||
|
factory : module
|
||||||
|
The underlying block cipher, a module from ``Crypto.Cipher``.
|
||||||
|
|
||||||
|
:Keywords:
|
||||||
|
nonce : binary string
|
||||||
|
The fixed part at the beginning of the counter block - the rest is
|
||||||
|
the counter number that gets increased when processing the next block.
|
||||||
|
The nonce must be such that no two messages are encrypted under the
|
||||||
|
same key and the same nonce.
|
||||||
|
|
||||||
|
The nonce must be shorter than the block size (it can have
|
||||||
|
zero length).
|
||||||
|
|
||||||
|
If this parameter is not present, a random nonce will be created with
|
||||||
|
length equal to half the block size. No random nonce shorter than
|
||||||
|
64 bits will be created though - you must really think through all
|
||||||
|
security consequences of using such a short block size.
|
||||||
|
|
||||||
|
initial_value : posive integer
|
||||||
|
The initial value for the counter. If not present, the cipher will
|
||||||
|
start counting from 0. The value is incremented by one for each block.
|
||||||
|
The counter number is encoded in big endian mode.
|
||||||
|
|
||||||
|
counter : object
|
||||||
|
Instance of ``Crypto.Util.Counter``, which allows full customization
|
||||||
|
of the counter block. This parameter is incompatible to both ``nonce``
|
||||||
|
and ``initial_value``.
|
||||||
|
|
||||||
|
Any other keyword will be passed to the underlying block cipher.
|
||||||
|
See the relevant documentation for details (at least ``key`` will need
|
||||||
|
to be present).
|
||||||
|
"""
|
||||||
|
|
||||||
|
cipher_state = factory._create_base_cipher(kwargs)
|
||||||
|
|
||||||
|
counter = kwargs.pop("counter", None)
|
||||||
|
nonce = kwargs.pop("nonce", None)
|
||||||
|
initial_value = kwargs.pop("initial_value", None)
|
||||||
|
if kwargs:
|
||||||
|
raise TypeError("Invalid parameters for CTR mode: %s" % str(kwargs))
|
||||||
|
|
||||||
|
if counter is not None and (nonce, initial_value) != (None, None):
|
||||||
|
raise TypeError("'counter' and 'nonce'/'initial_value'"
|
||||||
|
" are mutually exclusive")
|
||||||
|
|
||||||
|
if counter is None:
|
||||||
|
# Crypto.Util.Counter is not used
|
||||||
|
if nonce is None:
|
||||||
|
if factory.block_size < 16:
|
||||||
|
raise TypeError("Impossible to create a safe nonce for short"
|
||||||
|
" block sizes")
|
||||||
|
nonce = get_random_bytes(factory.block_size // 2)
|
||||||
|
|
||||||
|
if initial_value is None:
|
||||||
|
initial_value = 0
|
||||||
|
|
||||||
|
if len(nonce) >= factory.block_size:
|
||||||
|
raise ValueError("Nonce is too long")
|
||||||
|
|
||||||
|
counter_len = factory.block_size - len(nonce)
|
||||||
|
if (1 << (counter_len * 8)) - 1 < initial_value:
|
||||||
|
raise ValueError("Initial counter value is too large")
|
||||||
|
|
||||||
|
return CtrMode(cipher_state,
|
||||||
|
# initial_counter_block
|
||||||
|
nonce + long_to_bytes(initial_value, counter_len),
|
||||||
|
len(nonce), # prefix
|
||||||
|
counter_len,
|
||||||
|
False) # little_endian
|
||||||
|
|
||||||
|
# Crypto.Util.Counter is used
|
||||||
|
|
||||||
|
# 'counter' used to be a callable object, but now it is
|
||||||
|
# just a dictionary for backward compatibility.
|
||||||
|
_counter = dict(counter)
|
||||||
|
try:
|
||||||
|
counter_len = _counter.pop("counter_len")
|
||||||
|
prefix = _counter.pop("prefix")
|
||||||
|
suffix = _counter.pop("suffix")
|
||||||
|
initial_value = _counter.pop("initial_value")
|
||||||
|
little_endian = _counter.pop("little_endian")
|
||||||
|
except KeyError:
|
||||||
|
raise TypeError("Incorrect counter object"
|
||||||
|
" (use Crypto.Util.Counter.new)")
|
||||||
|
|
||||||
|
# Compute initial counter block
|
||||||
|
words = []
|
||||||
|
while initial_value > 0:
|
||||||
|
words.append(bchr(initial_value & 255))
|
||||||
|
initial_value >>= 8
|
||||||
|
words += [bchr(0)] * max(0, counter_len - len(words))
|
||||||
|
if not little_endian:
|
||||||
|
words.reverse()
|
||||||
|
initial_counter_block = prefix + b("").join(words) + suffix
|
||||||
|
|
||||||
|
if len(initial_counter_block) != factory.block_size:
|
||||||
|
raise ValueError("Size of the counter block (% bytes) must match"
|
||||||
|
" block size (%d)" % (len(initial_counter_block),
|
||||||
|
factory.block_size))
|
||||||
|
|
||||||
|
return CtrMode(cipher_state, initial_counter_block,
|
||||||
|
len(prefix), counter_len, little_endian)
|
379
venv/Lib/site-packages/Crypto/Cipher/_mode_eax.py
Normal file
379
venv/Lib/site-packages/Crypto/Cipher/_mode_eax.py
Normal file
|
@ -0,0 +1,379 @@
|
||||||
|
# ===================================================================
|
||||||
|
#
|
||||||
|
# Copyright (c) 2014, Legrandin <helderijs@gmail.com>
|
||||||
|
# All rights reserved.
|
||||||
|
#
|
||||||
|
# Redistribution and use in source and binary forms, with or without
|
||||||
|
# modification, are permitted provided that the following conditions
|
||||||
|
# are met:
|
||||||
|
#
|
||||||
|
# 1. Redistributions of source code must retain the above copyright
|
||||||
|
# notice, this list of conditions and the following disclaimer.
|
||||||
|
# 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
# notice, this list of conditions and the following disclaimer in
|
||||||
|
# the documentation and/or other materials provided with the
|
||||||
|
# distribution.
|
||||||
|
#
|
||||||
|
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||||
|
# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||||
|
# COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||||
|
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||||
|
# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||||
|
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||||
|
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||||
|
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
|
# POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
# ===================================================================
|
||||||
|
|
||||||
|
"""
|
||||||
|
EAX mode.
|
||||||
|
"""
|
||||||
|
|
||||||
|
__all__ = ['EaxMode']
|
||||||
|
|
||||||
|
from Crypto.Util.py3compat import byte_string, bchr, bord, unhexlify, b
|
||||||
|
|
||||||
|
from Crypto.Util.strxor import strxor
|
||||||
|
from Crypto.Util.number import long_to_bytes, bytes_to_long
|
||||||
|
|
||||||
|
from Crypto.Hash import CMAC, BLAKE2s
|
||||||
|
from Crypto.Random import get_random_bytes
|
||||||
|
|
||||||
|
|
||||||
|
class EaxMode(object):
|
||||||
|
"""*EAX* mode.
|
||||||
|
|
||||||
|
This is an Authenticated Encryption with Associated Data
|
||||||
|
(`AEAD`_) mode. It provides both confidentiality and authenticity.
|
||||||
|
|
||||||
|
The header of the message may be left in the clear, if needed,
|
||||||
|
and it will still be subject to authentication.
|
||||||
|
|
||||||
|
The decryption step tells the receiver if the message comes
|
||||||
|
from a source that really knowns the secret key.
|
||||||
|
Additionally, decryption detects if any part of the message -
|
||||||
|
including the header - has been modified or corrupted.
|
||||||
|
|
||||||
|
This mode requires a *nonce*.
|
||||||
|
|
||||||
|
This mode is only available for ciphers that operate on 64 or
|
||||||
|
128 bits blocks.
|
||||||
|
|
||||||
|
There are no official standards defining EAX.
|
||||||
|
The implementation is based on `a proposal`__ that
|
||||||
|
was presented to NIST.
|
||||||
|
|
||||||
|
.. _AEAD: http://blog.cryptographyengineering.com/2012/05/how-to-choose-authenticated-encryption.html
|
||||||
|
.. __: http://csrc.nist.gov/groups/ST/toolkit/BCM/documents/proposedmodes/eax/eax-spec.pdf
|
||||||
|
|
||||||
|
:undocumented: __init__
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__(self, factory, key, nonce, mac_len, cipher_params):
|
||||||
|
"""EAX cipher mode"""
|
||||||
|
|
||||||
|
self.block_size = factory.block_size
|
||||||
|
"""The block size of the underlying cipher, in bytes."""
|
||||||
|
|
||||||
|
self.nonce = nonce
|
||||||
|
"""The nonce originally used to create the object."""
|
||||||
|
|
||||||
|
self._mac_len = mac_len
|
||||||
|
self._mac_tag = None # Cache for MAC tag
|
||||||
|
|
||||||
|
# Allowed transitions after initialization
|
||||||
|
self._next = [self.update, self.encrypt, self.decrypt,
|
||||||
|
self.digest, self.verify]
|
||||||
|
|
||||||
|
# MAC tag length
|
||||||
|
if not (4 <= self._mac_len <= self.block_size):
|
||||||
|
raise ValueError("Parameter 'mac_len' must not be larger than %d"
|
||||||
|
% self.block_size)
|
||||||
|
|
||||||
|
# Nonce cannot be empty and must be a byte string
|
||||||
|
if len(nonce) == 0:
|
||||||
|
raise ValueError("Nonce cannot be empty in EAX mode")
|
||||||
|
if not byte_string(nonce):
|
||||||
|
raise TypeError("Nonce must be a byte string")
|
||||||
|
|
||||||
|
self._omac = [
|
||||||
|
CMAC.new(key,
|
||||||
|
bchr(0) * (self.block_size - 1) + bchr(i),
|
||||||
|
ciphermod=factory,
|
||||||
|
cipher_params=cipher_params)
|
||||||
|
for i in range(0, 3)
|
||||||
|
]
|
||||||
|
|
||||||
|
# Compute MAC of nonce
|
||||||
|
self._omac[0].update(nonce)
|
||||||
|
self._signer = self._omac[1]
|
||||||
|
|
||||||
|
# MAC of the nonce is also the initial counter for CTR encryption
|
||||||
|
counter_int = bytes_to_long(self._omac[0].digest())
|
||||||
|
self._cipher = factory.new(key,
|
||||||
|
factory.MODE_CTR,
|
||||||
|
initial_value=counter_int,
|
||||||
|
nonce=b(""),
|
||||||
|
**cipher_params)
|
||||||
|
|
||||||
|
def update(self, assoc_data):
|
||||||
|
"""Protect associated data
|
||||||
|
|
||||||
|
If there is any associated data, the caller has to invoke
|
||||||
|
this function one or more times, before using
|
||||||
|
``decrypt`` or ``encrypt``.
|
||||||
|
|
||||||
|
By *associated data* it is meant any data (e.g. packet headers) that
|
||||||
|
will not be encrypted and will be transmitted in the clear.
|
||||||
|
However, the receiver is still able to detect any modification to it.
|
||||||
|
|
||||||
|
If there is no associated data, this method must not be called.
|
||||||
|
|
||||||
|
The caller may split associated data in segments of any size, and
|
||||||
|
invoke this method multiple times, each time with the next segment.
|
||||||
|
|
||||||
|
:Parameters:
|
||||||
|
assoc_data : byte string
|
||||||
|
A piece of associated data. There are no restrictions on its size.
|
||||||
|
"""
|
||||||
|
|
||||||
|
if self.update not in self._next:
|
||||||
|
raise TypeError("update() can only be called"
|
||||||
|
" immediately after initialization")
|
||||||
|
|
||||||
|
self._next = [self.update, self.encrypt, self.decrypt,
|
||||||
|
self.digest, self.verify]
|
||||||
|
|
||||||
|
return self._signer.update(assoc_data)
|
||||||
|
|
||||||
|
def encrypt(self, plaintext):
|
||||||
|
"""Encrypt data with the key and the parameters set at initialization.
|
||||||
|
|
||||||
|
A cipher object is stateful: once you have encrypted a message
|
||||||
|
you cannot encrypt (or decrypt) another message using the same
|
||||||
|
object.
|
||||||
|
|
||||||
|
The data to encrypt can be broken up in two or
|
||||||
|
more pieces and `encrypt` can be called multiple times.
|
||||||
|
|
||||||
|
That is, the statement:
|
||||||
|
|
||||||
|
>>> c.encrypt(a) + c.encrypt(b)
|
||||||
|
|
||||||
|
is equivalent to:
|
||||||
|
|
||||||
|
>>> c.encrypt(a+b)
|
||||||
|
|
||||||
|
This function does not add any padding to the plaintext.
|
||||||
|
|
||||||
|
:Parameters:
|
||||||
|
plaintext : byte string
|
||||||
|
The piece of data to encrypt.
|
||||||
|
It can be of any length.
|
||||||
|
:Return:
|
||||||
|
the encrypted data, as a byte string.
|
||||||
|
It is as long as *plaintext*.
|
||||||
|
"""
|
||||||
|
|
||||||
|
if self.encrypt not in self._next:
|
||||||
|
raise TypeError("encrypt() can only be called after"
|
||||||
|
" initialization or an update()")
|
||||||
|
self._next = [self.encrypt, self.digest]
|
||||||
|
ct = self._cipher.encrypt(plaintext)
|
||||||
|
self._omac[2].update(ct)
|
||||||
|
return ct
|
||||||
|
|
||||||
|
def decrypt(self, ciphertext):
|
||||||
|
"""Decrypt data with the key and the parameters set at initialization.
|
||||||
|
|
||||||
|
A cipher object is stateful: once you have decrypted a message
|
||||||
|
you cannot decrypt (or encrypt) another message with the same
|
||||||
|
object.
|
||||||
|
|
||||||
|
The data to decrypt can be broken up in two or
|
||||||
|
more pieces and `decrypt` can be called multiple times.
|
||||||
|
|
||||||
|
That is, the statement:
|
||||||
|
|
||||||
|
>>> c.decrypt(a) + c.decrypt(b)
|
||||||
|
|
||||||
|
is equivalent to:
|
||||||
|
|
||||||
|
>>> c.decrypt(a+b)
|
||||||
|
|
||||||
|
This function does not remove any padding from the plaintext.
|
||||||
|
|
||||||
|
:Parameters:
|
||||||
|
ciphertext : byte string
|
||||||
|
The piece of data to decrypt.
|
||||||
|
It can be of any length.
|
||||||
|
|
||||||
|
:Return: the decrypted data (byte string).
|
||||||
|
"""
|
||||||
|
|
||||||
|
if self.decrypt not in self._next:
|
||||||
|
raise TypeError("decrypt() can only be called"
|
||||||
|
" after initialization or an update()")
|
||||||
|
self._next = [self.decrypt, self.verify]
|
||||||
|
self._omac[2].update(ciphertext)
|
||||||
|
return self._cipher.decrypt(ciphertext)
|
||||||
|
|
||||||
|
def digest(self):
|
||||||
|
"""Compute the *binary* MAC tag.
|
||||||
|
|
||||||
|
The caller invokes this function at the very end.
|
||||||
|
|
||||||
|
This method returns the MAC that shall be sent to the receiver,
|
||||||
|
together with the ciphertext.
|
||||||
|
|
||||||
|
:Return: the MAC, as a byte string.
|
||||||
|
"""
|
||||||
|
|
||||||
|
if self.digest not in self._next:
|
||||||
|
raise TypeError("digest() cannot be called when decrypting"
|
||||||
|
" or validating a message")
|
||||||
|
self._next = [self.digest]
|
||||||
|
|
||||||
|
if not self._mac_tag:
|
||||||
|
tag = bchr(0) * self.block_size
|
||||||
|
for i in range(3):
|
||||||
|
tag = strxor(tag, self._omac[i].digest())
|
||||||
|
self._mac_tag = tag[:self._mac_len]
|
||||||
|
|
||||||
|
return self._mac_tag
|
||||||
|
|
||||||
|
def hexdigest(self):
|
||||||
|
"""Compute the *printable* MAC tag.
|
||||||
|
|
||||||
|
This method is like `digest`.
|
||||||
|
|
||||||
|
:Return: the MAC, as a hexadecimal string.
|
||||||
|
"""
|
||||||
|
return "".join(["%02x" % bord(x) for x in self.digest()])
|
||||||
|
|
||||||
|
def verify(self, received_mac_tag):
|
||||||
|
"""Validate the *binary* MAC tag.
|
||||||
|
|
||||||
|
The caller invokes this function at the very end.
|
||||||
|
|
||||||
|
This method checks if the decrypted message is indeed valid
|
||||||
|
(that is, if the key is correct) and it has not been
|
||||||
|
tampered with while in transit.
|
||||||
|
|
||||||
|
:Parameters:
|
||||||
|
received_mac_tag : byte string
|
||||||
|
This is the *binary* MAC, as received from the sender.
|
||||||
|
:Raises MacMismatchError:
|
||||||
|
if the MAC does not match. The message has been tampered with
|
||||||
|
or the key is incorrect.
|
||||||
|
"""
|
||||||
|
|
||||||
|
if self.verify not in self._next:
|
||||||
|
raise TypeError("verify() cannot be called"
|
||||||
|
" when encrypting a message")
|
||||||
|
self._next = [self.verify]
|
||||||
|
|
||||||
|
if not self._mac_tag:
|
||||||
|
tag = bchr(0) * self.block_size
|
||||||
|
for i in range(3):
|
||||||
|
tag = strxor(tag, self._omac[i].digest())
|
||||||
|
self._mac_tag = tag[:self._mac_len]
|
||||||
|
|
||||||
|
secret = get_random_bytes(16)
|
||||||
|
|
||||||
|
mac1 = BLAKE2s.new(digest_bits=160, key=secret, data=self._mac_tag)
|
||||||
|
mac2 = BLAKE2s.new(digest_bits=160, key=secret, data=received_mac_tag)
|
||||||
|
|
||||||
|
if mac1.digest() != mac2.digest():
|
||||||
|
raise ValueError("MAC check failed")
|
||||||
|
|
||||||
|
def hexverify(self, hex_mac_tag):
|
||||||
|
"""Validate the *printable* MAC tag.
|
||||||
|
|
||||||
|
This method is like `verify`.
|
||||||
|
|
||||||
|
:Parameters:
|
||||||
|
hex_mac_tag : string
|
||||||
|
This is the *printable* MAC, as received from the sender.
|
||||||
|
:Raises MacMismatchError:
|
||||||
|
if the MAC does not match. The message has been tampered with
|
||||||
|
or the key is incorrect.
|
||||||
|
"""
|
||||||
|
|
||||||
|
self.verify(unhexlify(hex_mac_tag))
|
||||||
|
|
||||||
|
def encrypt_and_digest(self, plaintext):
|
||||||
|
"""Perform encrypt() and digest() in one step.
|
||||||
|
|
||||||
|
:Parameters:
|
||||||
|
plaintext : byte string
|
||||||
|
The piece of data to encrypt.
|
||||||
|
:Return:
|
||||||
|
a tuple with two byte strings:
|
||||||
|
|
||||||
|
- the encrypted data
|
||||||
|
- the MAC
|
||||||
|
"""
|
||||||
|
|
||||||
|
return self.encrypt(plaintext), self.digest()
|
||||||
|
|
||||||
|
def decrypt_and_verify(self, ciphertext, received_mac_tag):
|
||||||
|
"""Perform decrypt() and verify() in one step.
|
||||||
|
|
||||||
|
:Parameters:
|
||||||
|
ciphertext : byte string
|
||||||
|
The piece of data to decrypt.
|
||||||
|
received_mac_tag : byte string
|
||||||
|
This is the *binary* MAC, as received from the sender.
|
||||||
|
|
||||||
|
:Return: the decrypted data (byte string).
|
||||||
|
:Raises MacMismatchError:
|
||||||
|
if the MAC does not match. The message has been tampered with
|
||||||
|
or the key is incorrect.
|
||||||
|
"""
|
||||||
|
|
||||||
|
pt = self.decrypt(ciphertext)
|
||||||
|
self.verify(received_mac_tag)
|
||||||
|
return pt
|
||||||
|
|
||||||
|
|
||||||
|
def _create_eax_cipher(factory, **kwargs):
|
||||||
|
"""Create a new block cipher, configured in EAX mode.
|
||||||
|
|
||||||
|
:Parameters:
|
||||||
|
factory : module
|
||||||
|
A symmetric cipher module from `Crypto.Cipher` (like
|
||||||
|
`Crypto.Cipher.AES`).
|
||||||
|
|
||||||
|
:Keywords:
|
||||||
|
key : byte string
|
||||||
|
The secret key to use in the symmetric cipher.
|
||||||
|
|
||||||
|
nonce : byte string
|
||||||
|
A value that must never be reused for any other encryption.
|
||||||
|
There are no restrictions on its length, but it is recommended to use
|
||||||
|
at least 16 bytes.
|
||||||
|
|
||||||
|
The nonce shall never repeat for two different messages encrypted with
|
||||||
|
the same key, but it does not need to be random.
|
||||||
|
|
||||||
|
If not specified, a 16 byte long random string is used.
|
||||||
|
|
||||||
|
mac_len : integer
|
||||||
|
Length of the MAC, in bytes. It must be no larger than the cipher
|
||||||
|
block bytes (which is the default).
|
||||||
|
"""
|
||||||
|
|
||||||
|
try:
|
||||||
|
key = kwargs.pop("key")
|
||||||
|
nonce = kwargs.pop("nonce", None)
|
||||||
|
if nonce is None:
|
||||||
|
nonce = get_random_bytes(16)
|
||||||
|
mac_len = kwargs.pop("mac_len", factory.block_size)
|
||||||
|
except KeyError as e:
|
||||||
|
raise TypeError("Missing parameter: " + str(e))
|
||||||
|
|
||||||
|
return EaxMode(factory, key, nonce, mac_len, kwargs)
|
178
venv/Lib/site-packages/Crypto/Cipher/_mode_ecb.py
Normal file
178
venv/Lib/site-packages/Crypto/Cipher/_mode_ecb.py
Normal file
|
@ -0,0 +1,178 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
#
|
||||||
|
# Cipher/mode_ecb.py : ECB mode
|
||||||
|
#
|
||||||
|
# ===================================================================
|
||||||
|
# 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.
|
||||||
|
# ===================================================================
|
||||||
|
|
||||||
|
"""
|
||||||
|
Electronic Code Book (ECB) mode.
|
||||||
|
"""
|
||||||
|
|
||||||
|
__all__ = [ 'EcbMode' ]
|
||||||
|
|
||||||
|
from Crypto.Util._raw_api import (load_pycryptodome_raw_lib,
|
||||||
|
VoidPointer, create_string_buffer,
|
||||||
|
get_raw_buffer, SmartPointer,
|
||||||
|
c_size_t, expect_byte_string)
|
||||||
|
|
||||||
|
raw_ecb_lib = load_pycryptodome_raw_lib("Crypto.Cipher._raw_ecb", """
|
||||||
|
int ECB_start_operation(void *cipher,
|
||||||
|
void **pResult);
|
||||||
|
int ECB_encrypt(void *ecbState,
|
||||||
|
const uint8_t *in,
|
||||||
|
uint8_t *out,
|
||||||
|
size_t data_len);
|
||||||
|
int ECB_decrypt(void *ecbState,
|
||||||
|
const uint8_t *in,
|
||||||
|
uint8_t *out,
|
||||||
|
size_t data_len);
|
||||||
|
int ECB_stop_operation(void *state);
|
||||||
|
"""
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class EcbMode(object):
|
||||||
|
"""*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 is dangerous because it 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
|
||||||
|
|
||||||
|
:undocumented: __init__
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__(self, block_cipher):
|
||||||
|
"""Create a new block cipher, configured in ECB mode.
|
||||||
|
|
||||||
|
:Parameters:
|
||||||
|
block_cipher : C pointer
|
||||||
|
A smart pointer to the low-level block cipher instance.
|
||||||
|
"""
|
||||||
|
|
||||||
|
self._state = VoidPointer()
|
||||||
|
result = raw_ecb_lib.ECB_start_operation(block_cipher.get(),
|
||||||
|
self._state.address_of())
|
||||||
|
if result:
|
||||||
|
raise ValueError("Error %d while instatiating the ECB mode"
|
||||||
|
% result)
|
||||||
|
|
||||||
|
# Ensure that object disposal of this Python object will (eventually)
|
||||||
|
# free the memory allocated by the raw library for the cipher
|
||||||
|
# mode
|
||||||
|
self._state = SmartPointer(self._state.get(),
|
||||||
|
raw_ecb_lib.ECB_stop_operation)
|
||||||
|
|
||||||
|
# Memory allocated for the underlying block cipher is now owned
|
||||||
|
# by the cipher mode
|
||||||
|
block_cipher.release()
|
||||||
|
|
||||||
|
def encrypt(self, plaintext):
|
||||||
|
"""Encrypt data with the key set at initialization.
|
||||||
|
|
||||||
|
The data to encrypt can be broken up in two or
|
||||||
|
more pieces and `encrypt` can be called multiple times.
|
||||||
|
|
||||||
|
That is, the statement:
|
||||||
|
|
||||||
|
>>> c.encrypt(a) + c.encrypt(b)
|
||||||
|
|
||||||
|
is equivalent to:
|
||||||
|
|
||||||
|
>>> c.encrypt(a+b)
|
||||||
|
|
||||||
|
This function does not add any padding to the plaintext.
|
||||||
|
|
||||||
|
:Parameters:
|
||||||
|
plaintext : byte string
|
||||||
|
The piece of data to encrypt.
|
||||||
|
The length must be multiple of the cipher block length.
|
||||||
|
:Return:
|
||||||
|
the encrypted data, as a byte string.
|
||||||
|
It is as long as *plaintext*.
|
||||||
|
"""
|
||||||
|
|
||||||
|
expect_byte_string(plaintext)
|
||||||
|
ciphertext = create_string_buffer(len(plaintext))
|
||||||
|
result = raw_ecb_lib.ECB_encrypt(self._state.get(),
|
||||||
|
plaintext,
|
||||||
|
ciphertext,
|
||||||
|
c_size_t(len(plaintext)))
|
||||||
|
if result:
|
||||||
|
raise ValueError("Error %d while encrypting in ECB mode" % result)
|
||||||
|
return get_raw_buffer(ciphertext)
|
||||||
|
|
||||||
|
def decrypt(self, ciphertext):
|
||||||
|
"""Decrypt data with the key set at initialization.
|
||||||
|
|
||||||
|
The data to decrypt can be broken up in two or
|
||||||
|
more pieces and `decrypt` can be called multiple times.
|
||||||
|
|
||||||
|
That is, the statement:
|
||||||
|
|
||||||
|
>>> c.decrypt(a) + c.decrypt(b)
|
||||||
|
|
||||||
|
is equivalent to:
|
||||||
|
|
||||||
|
>>> c.decrypt(a+b)
|
||||||
|
|
||||||
|
This function does not remove any padding from the plaintext.
|
||||||
|
|
||||||
|
:Parameters:
|
||||||
|
ciphertext : byte string
|
||||||
|
The piece of data to decrypt.
|
||||||
|
The length must be multiple of the cipher block length.
|
||||||
|
|
||||||
|
:Return:
|
||||||
|
the decrypted data (byte string).
|
||||||
|
It is as long as *ciphertext*.
|
||||||
|
"""
|
||||||
|
|
||||||
|
expect_byte_string(ciphertext)
|
||||||
|
plaintext = create_string_buffer(len(ciphertext))
|
||||||
|
result = raw_ecb_lib.ECB_decrypt(self._state.get(),
|
||||||
|
ciphertext,
|
||||||
|
plaintext,
|
||||||
|
c_size_t(len(ciphertext)))
|
||||||
|
if result:
|
||||||
|
raise ValueError("Error %d while decrypting in ECB mode" % result)
|
||||||
|
return get_raw_buffer(plaintext)
|
||||||
|
|
||||||
|
|
||||||
|
def _create_ecb_cipher(factory, **kwargs):
|
||||||
|
"""Instantiate a cipher object that performs ECB encryption/decryption.
|
||||||
|
|
||||||
|
:Parameters:
|
||||||
|
factory : module
|
||||||
|
The underlying block cipher, a module from ``Crypto.Cipher``.
|
||||||
|
|
||||||
|
All keywords are passed to the underlying block cipher.
|
||||||
|
See the relevant documentation for details (at least ``key`` will need
|
||||||
|
to be present"""
|
||||||
|
|
||||||
|
cipher_state = factory._create_base_cipher(kwargs)
|
||||||
|
if kwargs:
|
||||||
|
raise TypeError("Unknown parameters for ECB: %s" % str(kwargs))
|
||||||
|
return EcbMode(cipher_state)
|
535
venv/Lib/site-packages/Crypto/Cipher/_mode_gcm.py
Normal file
535
venv/Lib/site-packages/Crypto/Cipher/_mode_gcm.py
Normal file
|
@ -0,0 +1,535 @@
|
||||||
|
# ===================================================================
|
||||||
|
#
|
||||||
|
# Copyright (c) 2014, Legrandin <helderijs@gmail.com>
|
||||||
|
# All rights reserved.
|
||||||
|
#
|
||||||
|
# Redistribution and use in source and binary forms, with or without
|
||||||
|
# modification, are permitted provided that the following conditions
|
||||||
|
# are met:
|
||||||
|
#
|
||||||
|
# 1. Redistributions of source code must retain the above copyright
|
||||||
|
# notice, this list of conditions and the following disclaimer.
|
||||||
|
# 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
# notice, this list of conditions and the following disclaimer in
|
||||||
|
# the documentation and/or other materials provided with the
|
||||||
|
# distribution.
|
||||||
|
#
|
||||||
|
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||||
|
# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||||
|
# COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||||
|
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||||
|
# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||||
|
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||||
|
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||||
|
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
|
# POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
# ===================================================================
|
||||||
|
|
||||||
|
"""
|
||||||
|
Galois/Counter Mode (GCM).
|
||||||
|
"""
|
||||||
|
|
||||||
|
__all__ = ['GcmMode']
|
||||||
|
|
||||||
|
from Crypto.Util.py3compat import b, bchr, byte_string, bord, unhexlify
|
||||||
|
|
||||||
|
from Crypto.Util.number import long_to_bytes, bytes_to_long
|
||||||
|
from Crypto.Hash import BLAKE2s
|
||||||
|
from Crypto.Random import get_random_bytes
|
||||||
|
|
||||||
|
from Crypto.Util._raw_api import (load_pycryptodome_raw_lib, VoidPointer,
|
||||||
|
create_string_buffer, get_raw_buffer,
|
||||||
|
SmartPointer, c_size_t, expect_byte_string)
|
||||||
|
|
||||||
|
_raw_galois_lib = load_pycryptodome_raw_lib("Crypto.Util._galois",
|
||||||
|
"""
|
||||||
|
int ghash( uint8_t y_out[16],
|
||||||
|
const uint8_t block_data[],
|
||||||
|
size_t len,
|
||||||
|
const uint8_t y_in[16],
|
||||||
|
const void *exp_key);
|
||||||
|
int ghash_expand(const uint8_t h[16],
|
||||||
|
void **ghash_tables);
|
||||||
|
int ghash_destroy(void *ghash_tables);
|
||||||
|
""")
|
||||||
|
|
||||||
|
|
||||||
|
class _GHASH(object):
|
||||||
|
"""GHASH function defined in NIST SP 800-38D, Algorithm 2.
|
||||||
|
|
||||||
|
If X_1, X_2, .. X_m are the blocks of input data, the function
|
||||||
|
computes:
|
||||||
|
|
||||||
|
X_1*H^{m} + X_2*H^{m-1} + ... + X_m*H
|
||||||
|
|
||||||
|
in the Galois field GF(2^256) using the reducing polynomial
|
||||||
|
(x^128 + x^7 + x^2 + x + 1).
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__(self, subkey):
|
||||||
|
assert len(subkey) == 16
|
||||||
|
|
||||||
|
expect_byte_string(subkey)
|
||||||
|
self._exp_key = VoidPointer()
|
||||||
|
result = _raw_galois_lib.ghash_expand(subkey,
|
||||||
|
self._exp_key.address_of())
|
||||||
|
if result:
|
||||||
|
raise ValueError("Error %d while expanding the GMAC key" % result)
|
||||||
|
|
||||||
|
self._exp_key = SmartPointer(self._exp_key.get(),
|
||||||
|
_raw_galois_lib.ghash_destroy)
|
||||||
|
|
||||||
|
# create_string_buffer always returns a string of zeroes
|
||||||
|
self._last_y = create_string_buffer(16)
|
||||||
|
|
||||||
|
def update(self, block_data):
|
||||||
|
assert len(block_data) % 16 == 0
|
||||||
|
|
||||||
|
expect_byte_string(block_data)
|
||||||
|
result = _raw_galois_lib.ghash(self._last_y,
|
||||||
|
block_data,
|
||||||
|
c_size_t(len(block_data)),
|
||||||
|
self._last_y,
|
||||||
|
self._exp_key.get())
|
||||||
|
if result:
|
||||||
|
raise ValueError("Error %d while updating GMAC" % result)
|
||||||
|
|
||||||
|
return self
|
||||||
|
|
||||||
|
def digest(self):
|
||||||
|
return get_raw_buffer(self._last_y)
|
||||||
|
|
||||||
|
|
||||||
|
def enum(**enums):
|
||||||
|
return type('Enum', (), enums)
|
||||||
|
|
||||||
|
MacStatus = enum(PROCESSING_AUTH_DATA=1, PROCESSING_CIPHERTEXT=2)
|
||||||
|
|
||||||
|
|
||||||
|
class GcmMode(object):
|
||||||
|
"""Galois Counter Mode (GCM).
|
||||||
|
|
||||||
|
This is an Authenticated Encryption with Associated Data (`AEAD`_) mode.
|
||||||
|
It provides both confidentiality and authenticity.
|
||||||
|
|
||||||
|
The header of the message may be left in the clear, if needed, and it will
|
||||||
|
still be subject to authentication. The decryption step tells the receiver
|
||||||
|
if the message comes from a source that really knowns the secret key.
|
||||||
|
Additionally, decryption detects if any part of the message - including the
|
||||||
|
header - has been modified or corrupted.
|
||||||
|
|
||||||
|
This mode requires a *nonce*.
|
||||||
|
|
||||||
|
This mode is only available for ciphers that operate on 128 bits blocks
|
||||||
|
(e.g. AES but not TDES).
|
||||||
|
|
||||||
|
See `NIST SP800-38D`_.
|
||||||
|
|
||||||
|
.. _`NIST SP800-38D`: http://csrc.nist.gov/publications/nistpubs/800-38D/SP-800-38D.pdf
|
||||||
|
.. _AEAD: http://blog.cryptographyengineering.com/2012/05/how-to-choose-authenticated-encryption.html
|
||||||
|
|
||||||
|
:undocumented: __init__
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__(self, factory, key, nonce, mac_len, cipher_params):
|
||||||
|
|
||||||
|
self.block_size = factory.block_size
|
||||||
|
if self.block_size != 16:
|
||||||
|
raise ValueError("GCM mode is only available for ciphers"
|
||||||
|
" that operate on 128 bits blocks")
|
||||||
|
|
||||||
|
if len(nonce) == 0:
|
||||||
|
raise ValueError("Nonce cannot be empty")
|
||||||
|
if not byte_string(nonce):
|
||||||
|
raise TypeError("Nonce must be a byte string")
|
||||||
|
|
||||||
|
self.nonce = nonce
|
||||||
|
"""Nonce"""
|
||||||
|
|
||||||
|
self._factory = factory
|
||||||
|
self._key = key
|
||||||
|
self._tag = None # Cache for MAC tag
|
||||||
|
|
||||||
|
self._mac_len = mac_len
|
||||||
|
if not (4 <= mac_len <= 16):
|
||||||
|
raise ValueError("Parameter 'mac_len' must be in the range 4..16")
|
||||||
|
|
||||||
|
# Allowed transitions after initialization
|
||||||
|
self._next = [self.update, self.encrypt, self.decrypt,
|
||||||
|
self.digest, self.verify]
|
||||||
|
|
||||||
|
self._no_more_assoc_data = False
|
||||||
|
|
||||||
|
# Length of associated data
|
||||||
|
self._auth_len = 0
|
||||||
|
|
||||||
|
# Length of the ciphertext or plaintext
|
||||||
|
self._msg_len = 0
|
||||||
|
|
||||||
|
# Step 1 in SP800-38D, Algorithm 4 (encryption) - Compute H
|
||||||
|
# See also Algorithm 5 (decryption)
|
||||||
|
hash_subkey = factory.new(key,
|
||||||
|
self._factory.MODE_ECB,
|
||||||
|
**cipher_params
|
||||||
|
).encrypt(bchr(0) * 16)
|
||||||
|
|
||||||
|
# Step 2 - Compute J0 (integer, not byte string!)
|
||||||
|
if len(nonce) == 12:
|
||||||
|
self._j0 = bytes_to_long(nonce + b("\x00\x00\x00\x01"))
|
||||||
|
else:
|
||||||
|
fill = (16 - (len(nonce) % 16)) % 16 + 8
|
||||||
|
ghash_in = (nonce +
|
||||||
|
bchr(0) * fill +
|
||||||
|
long_to_bytes(8 * len(nonce), 8))
|
||||||
|
self._j0 = bytes_to_long(_GHASH(hash_subkey)
|
||||||
|
.update(ghash_in)
|
||||||
|
.digest())
|
||||||
|
|
||||||
|
# Step 3 - Prepare GCTR cipher for encryption/decryption
|
||||||
|
self._cipher = factory.new(key,
|
||||||
|
self._factory.MODE_CTR,
|
||||||
|
initial_value=self._j0 + 1,
|
||||||
|
nonce=b(""),
|
||||||
|
**cipher_params)
|
||||||
|
|
||||||
|
# Step 5 - Bootstrat GHASH
|
||||||
|
self._signer = _GHASH(hash_subkey)
|
||||||
|
|
||||||
|
# Step 6 - Prepare GCTR cipher for GMAC
|
||||||
|
self._tag_cipher = factory.new(key,
|
||||||
|
self._factory.MODE_CTR,
|
||||||
|
initial_value=self._j0,
|
||||||
|
nonce=b(""),
|
||||||
|
**cipher_params)
|
||||||
|
|
||||||
|
# Cache for data to authenticate
|
||||||
|
self._cache = b("")
|
||||||
|
|
||||||
|
self._status = MacStatus.PROCESSING_AUTH_DATA
|
||||||
|
|
||||||
|
def update(self, assoc_data):
|
||||||
|
"""Protect associated data
|
||||||
|
|
||||||
|
If there is any associated data, the caller has to invoke
|
||||||
|
this function one or more times, before using
|
||||||
|
``decrypt`` or ``encrypt``.
|
||||||
|
|
||||||
|
By *associated data* it is meant any data (e.g. packet headers) that
|
||||||
|
will not be encrypted and will be transmitted in the clear.
|
||||||
|
However, the receiver is still able to detect any modification to it.
|
||||||
|
In GCM, the *associated data* is also called
|
||||||
|
*additional authenticated data* (AAD).
|
||||||
|
|
||||||
|
If there is no associated data, this method must not be called.
|
||||||
|
|
||||||
|
The caller may split associated data in segments of any size, and
|
||||||
|
invoke this method multiple times, each time with the next segment.
|
||||||
|
|
||||||
|
:Parameters:
|
||||||
|
assoc_data : byte string
|
||||||
|
A piece of associated data. There are no restrictions on its size.
|
||||||
|
"""
|
||||||
|
|
||||||
|
if self.update not in self._next:
|
||||||
|
raise TypeError("update() can only be called"
|
||||||
|
" immediately after initialization")
|
||||||
|
|
||||||
|
self._next = [self.update, self.encrypt, self.decrypt,
|
||||||
|
self.digest, self.verify]
|
||||||
|
|
||||||
|
self._update(assoc_data)
|
||||||
|
self._auth_len += len(assoc_data)
|
||||||
|
return self
|
||||||
|
|
||||||
|
def _update(self, data):
|
||||||
|
assert(len(self._cache) < 16)
|
||||||
|
|
||||||
|
if len(self._cache) > 0:
|
||||||
|
filler = min(16 - len(self._cache), len(data))
|
||||||
|
self._cache += data[:filler]
|
||||||
|
data = data[filler:]
|
||||||
|
|
||||||
|
if len(self._cache) < 16:
|
||||||
|
return
|
||||||
|
|
||||||
|
# The cache is exactly one block
|
||||||
|
self._signer.update(self._cache)
|
||||||
|
self._cache = b("")
|
||||||
|
|
||||||
|
update_len = len(data) // 16 * 16
|
||||||
|
self._cache = data[update_len:]
|
||||||
|
if update_len > 0:
|
||||||
|
self._signer.update(data[:update_len])
|
||||||
|
|
||||||
|
def _pad_cache_and_update(self):
|
||||||
|
assert(len(self._cache) < 16)
|
||||||
|
|
||||||
|
# The authenticated data A is concatenated to the minimum
|
||||||
|
# number of zero bytes (possibly none) such that the
|
||||||
|
# - ciphertext C is aligned to the 16 byte boundary.
|
||||||
|
# See step 5 in section 7.1
|
||||||
|
# - ciphertext C is aligned to the 16 byte boundary.
|
||||||
|
# See step 6 in section 7.2
|
||||||
|
len_cache = len(self._cache)
|
||||||
|
if len_cache > 0:
|
||||||
|
self._update(bchr(0) * (16 - len_cache))
|
||||||
|
|
||||||
|
def encrypt(self, plaintext):
|
||||||
|
"""Encrypt data with the key and the parameters set at initialization.
|
||||||
|
|
||||||
|
A cipher object is stateful: once you have encrypted a message
|
||||||
|
you cannot encrypt (or decrypt) another message using the same
|
||||||
|
object.
|
||||||
|
|
||||||
|
The data to encrypt can be broken up in two or
|
||||||
|
more pieces and `encrypt` can be called multiple times.
|
||||||
|
|
||||||
|
That is, the statement:
|
||||||
|
|
||||||
|
>>> c.encrypt(a) + c.encrypt(b)
|
||||||
|
|
||||||
|
is equivalent to:
|
||||||
|
|
||||||
|
>>> c.encrypt(a+b)
|
||||||
|
|
||||||
|
This function does not add any padding to the plaintext.
|
||||||
|
|
||||||
|
:Parameters:
|
||||||
|
plaintext : byte string
|
||||||
|
The piece of data to encrypt.
|
||||||
|
It can be of any length.
|
||||||
|
:Return:
|
||||||
|
the encrypted data, as a byte string.
|
||||||
|
It is as long as *plaintext*.
|
||||||
|
"""
|
||||||
|
|
||||||
|
if self.encrypt not in self._next:
|
||||||
|
raise TypeError("encrypt() can only be called after"
|
||||||
|
" initialization or an update()")
|
||||||
|
self._next = [self.encrypt, self.digest]
|
||||||
|
|
||||||
|
ciphertext = self._cipher.encrypt(plaintext)
|
||||||
|
|
||||||
|
if self._status == MacStatus.PROCESSING_AUTH_DATA:
|
||||||
|
self._pad_cache_and_update()
|
||||||
|
self._status = MacStatus.PROCESSING_CIPHERTEXT
|
||||||
|
|
||||||
|
self._update(ciphertext)
|
||||||
|
self._msg_len += len(plaintext)
|
||||||
|
|
||||||
|
return ciphertext
|
||||||
|
|
||||||
|
def decrypt(self, ciphertext):
|
||||||
|
"""Decrypt data with the key and the parameters set at initialization.
|
||||||
|
|
||||||
|
A cipher object is stateful: once you have decrypted a message
|
||||||
|
you cannot decrypt (or encrypt) another message with the same
|
||||||
|
object.
|
||||||
|
|
||||||
|
The data to decrypt can be broken up in two or
|
||||||
|
more pieces and `decrypt` can be called multiple times.
|
||||||
|
|
||||||
|
That is, the statement:
|
||||||
|
|
||||||
|
>>> c.decrypt(a) + c.decrypt(b)
|
||||||
|
|
||||||
|
is equivalent to:
|
||||||
|
|
||||||
|
>>> c.decrypt(a+b)
|
||||||
|
|
||||||
|
This function does not remove any padding from the plaintext.
|
||||||
|
|
||||||
|
:Parameters:
|
||||||
|
ciphertext : byte string
|
||||||
|
The piece of data to decrypt.
|
||||||
|
It can be of any length.
|
||||||
|
|
||||||
|
:Return: the decrypted data (byte string).
|
||||||
|
"""
|
||||||
|
|
||||||
|
if self.decrypt not in self._next:
|
||||||
|
raise TypeError("decrypt() can only be called"
|
||||||
|
" after initialization or an update()")
|
||||||
|
self._next = [self.decrypt, self.verify]
|
||||||
|
|
||||||
|
if self._status == MacStatus.PROCESSING_AUTH_DATA:
|
||||||
|
self._pad_cache_and_update()
|
||||||
|
self._status = MacStatus.PROCESSING_CIPHERTEXT
|
||||||
|
|
||||||
|
self._update(ciphertext)
|
||||||
|
self._msg_len += len(ciphertext)
|
||||||
|
|
||||||
|
return self._cipher.decrypt(ciphertext)
|
||||||
|
|
||||||
|
def digest(self):
|
||||||
|
"""Compute the *binary* MAC tag in an AEAD mode.
|
||||||
|
|
||||||
|
The caller invokes this function at the very end.
|
||||||
|
|
||||||
|
This method returns the MAC that shall be sent to the receiver,
|
||||||
|
together with the ciphertext.
|
||||||
|
|
||||||
|
:Return: the MAC, as a byte string.
|
||||||
|
"""
|
||||||
|
|
||||||
|
if self.digest not in self._next:
|
||||||
|
raise TypeError("digest() cannot be called when decrypting"
|
||||||
|
" or validating a message")
|
||||||
|
self._next = [self.digest]
|
||||||
|
|
||||||
|
return self._compute_mac()
|
||||||
|
|
||||||
|
def _compute_mac(self):
|
||||||
|
"""Compute MAC without any FSM checks."""
|
||||||
|
|
||||||
|
if self._tag:
|
||||||
|
return self._tag
|
||||||
|
|
||||||
|
# Step 5 in NIST SP 800-38D, Algorithm 4 - Compute S
|
||||||
|
self._pad_cache_and_update()
|
||||||
|
self._update(long_to_bytes(8 * self._auth_len, 8))
|
||||||
|
self._update(long_to_bytes(8 * self._msg_len, 8))
|
||||||
|
s_tag = self._signer.digest()
|
||||||
|
|
||||||
|
# Step 6 - Compute T
|
||||||
|
self._tag = self._tag_cipher.encrypt(s_tag)[:self._mac_len]
|
||||||
|
|
||||||
|
return self._tag
|
||||||
|
|
||||||
|
def hexdigest(self):
|
||||||
|
"""Compute the *printable* MAC tag.
|
||||||
|
|
||||||
|
This method is like `digest`.
|
||||||
|
|
||||||
|
:Return: the MAC, as a hexadecimal string.
|
||||||
|
"""
|
||||||
|
return "".join(["%02x" % bord(x) for x in self.digest()])
|
||||||
|
|
||||||
|
def verify(self, received_mac_tag):
|
||||||
|
"""Validate the *binary* MAC tag.
|
||||||
|
|
||||||
|
The caller invokes this function at the very end.
|
||||||
|
|
||||||
|
This method checks if the decrypted message is indeed valid
|
||||||
|
(that is, if the key is correct) and it has not been
|
||||||
|
tampered with while in transit.
|
||||||
|
|
||||||
|
:Parameters:
|
||||||
|
received_mac_tag : byte string
|
||||||
|
This is the *binary* MAC, as received from the sender.
|
||||||
|
:Raises ValueError:
|
||||||
|
if the MAC does not match. The message has been tampered with
|
||||||
|
or the key is incorrect.
|
||||||
|
"""
|
||||||
|
|
||||||
|
if self.verify not in self._next:
|
||||||
|
raise TypeError("verify() cannot be called"
|
||||||
|
" when encrypting a message")
|
||||||
|
self._next = [self.verify]
|
||||||
|
|
||||||
|
secret = get_random_bytes(16)
|
||||||
|
|
||||||
|
mac1 = BLAKE2s.new(digest_bits=160, key=secret,
|
||||||
|
data=self._compute_mac())
|
||||||
|
mac2 = BLAKE2s.new(digest_bits=160, key=secret,
|
||||||
|
data=received_mac_tag)
|
||||||
|
|
||||||
|
if mac1.digest() != mac2.digest():
|
||||||
|
raise ValueError("MAC check failed")
|
||||||
|
|
||||||
|
def hexverify(self, hex_mac_tag):
|
||||||
|
"""Validate the *printable* MAC tag.
|
||||||
|
|
||||||
|
This method is like `verify`.
|
||||||
|
|
||||||
|
:Parameters:
|
||||||
|
hex_mac_tag : string
|
||||||
|
This is the *printable* MAC, as received from the sender.
|
||||||
|
:Raises ValueError:
|
||||||
|
if the MAC does not match. The message has been tampered with
|
||||||
|
or the key is incorrect.
|
||||||
|
"""
|
||||||
|
|
||||||
|
self.verify(unhexlify(hex_mac_tag))
|
||||||
|
|
||||||
|
def encrypt_and_digest(self, plaintext):
|
||||||
|
"""Perform encrypt() and digest() in one step.
|
||||||
|
|
||||||
|
:Parameters:
|
||||||
|
plaintext : byte string
|
||||||
|
The piece of data to encrypt.
|
||||||
|
:Return:
|
||||||
|
a tuple with two byte strings:
|
||||||
|
|
||||||
|
- the encrypted data
|
||||||
|
- the MAC
|
||||||
|
"""
|
||||||
|
|
||||||
|
return self.encrypt(plaintext), self.digest()
|
||||||
|
|
||||||
|
def decrypt_and_verify(self, ciphertext, received_mac_tag):
|
||||||
|
"""Perform decrypt() and verify() in one step.
|
||||||
|
|
||||||
|
:Parameters:
|
||||||
|
ciphertext : byte string
|
||||||
|
The piece of data to decrypt.
|
||||||
|
received_mac_tag : byte string
|
||||||
|
This is the *binary* MAC, as received from the sender.
|
||||||
|
|
||||||
|
:Return: the decrypted data (byte string).
|
||||||
|
:Raises ValueError:
|
||||||
|
if the MAC does not match. The message has been tampered with
|
||||||
|
or the key is incorrect.
|
||||||
|
"""
|
||||||
|
|
||||||
|
plaintext = self.decrypt(ciphertext)
|
||||||
|
self.verify(received_mac_tag)
|
||||||
|
return plaintext
|
||||||
|
|
||||||
|
|
||||||
|
def _create_gcm_cipher(factory, **kwargs):
|
||||||
|
"""Create a new block cipher, configured in Galois Counter Mode (GCM).
|
||||||
|
|
||||||
|
:Parameters:
|
||||||
|
factory : module
|
||||||
|
A block cipher module, taken from `Crypto.Cipher`.
|
||||||
|
The cipher must have block length of 16 bytes.
|
||||||
|
GCM has been only defined for `Crypto.Cipher.AES`.
|
||||||
|
|
||||||
|
:Keywords:
|
||||||
|
key : byte string
|
||||||
|
The secret key to use in the symmetric cipher.
|
||||||
|
It must be 16 (e.g. *AES-128*), 24 (e.g. *AES-192*)
|
||||||
|
or 32 (e.g. *AES-256*) bytes long.
|
||||||
|
|
||||||
|
nonce : byte string
|
||||||
|
A value that must never be reused for any other encryption.
|
||||||
|
|
||||||
|
There are no restrictions on its length,
|
||||||
|
but it is recommended to use at least 16 bytes.
|
||||||
|
|
||||||
|
The nonce shall never repeat for two
|
||||||
|
different messages encrypted with the same key,
|
||||||
|
but it does not need to be random.
|
||||||
|
|
||||||
|
If not provided, a 16 byte nonce will be randomly created.
|
||||||
|
|
||||||
|
mac_len : integer
|
||||||
|
Length of the MAC, in bytes.
|
||||||
|
It must be no larger than 16 bytes (which is the default).
|
||||||
|
"""
|
||||||
|
|
||||||
|
try:
|
||||||
|
key = kwargs.pop("key")
|
||||||
|
except KeyError as e:
|
||||||
|
raise TypeError("Missing parameter:" + str(e))
|
||||||
|
|
||||||
|
nonce = kwargs.pop("nonce", None)
|
||||||
|
if nonce is None:
|
||||||
|
nonce = get_random_bytes(16)
|
||||||
|
mac_len = kwargs.pop("mac_len", 16)
|
||||||
|
|
||||||
|
return GcmMode(factory, key, nonce, mac_len, kwargs)
|
515
venv/Lib/site-packages/Crypto/Cipher/_mode_ocb.py
Normal file
515
venv/Lib/site-packages/Crypto/Cipher/_mode_ocb.py
Normal file
|
@ -0,0 +1,515 @@
|
||||||
|
# ===================================================================
|
||||||
|
#
|
||||||
|
# Copyright (c) 2014, Legrandin <helderijs@gmail.com>
|
||||||
|
# All rights reserved.
|
||||||
|
#
|
||||||
|
# Redistribution and use in source and binary forms, with or without
|
||||||
|
# modification, are permitted provided that the following conditions
|
||||||
|
# are met:
|
||||||
|
#
|
||||||
|
# 1. Redistributions of source code must retain the above copyright
|
||||||
|
# notice, this list of conditions and the following disclaimer.
|
||||||
|
# 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
# notice, this list of conditions and the following disclaimer in
|
||||||
|
# the documentation and/or other materials provided with the
|
||||||
|
# distribution.
|
||||||
|
#
|
||||||
|
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||||
|
# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||||
|
# COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||||
|
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||||
|
# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||||
|
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||||
|
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||||
|
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
|
# POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
# ===================================================================
|
||||||
|
|
||||||
|
"""
|
||||||
|
Offset Codebook (OCB) mode.
|
||||||
|
|
||||||
|
OCB is Authenticated Encryption with Associated Data (AEAD) cipher mode
|
||||||
|
designed by Prof. Phillip Rogaway and specified in `RFC7253`_.
|
||||||
|
|
||||||
|
The algorithm provides both authenticity and privacy, it is very efficient,
|
||||||
|
it uses only one key and it can be used in online mode (so that encryption
|
||||||
|
or decryption can start before the end of the message is available).
|
||||||
|
|
||||||
|
This module implements the third and last variant of OCB (OCB3) and it only
|
||||||
|
works in combination with a 128-bit block symmetric cipher, like AES.
|
||||||
|
|
||||||
|
OCB is patented in US but `free licenses`_ exist for software implementations
|
||||||
|
meant for non-military purposes.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
>>> from Crypto.Cipher import AES
|
||||||
|
>>> from Crypto.Random import get_random_bytes
|
||||||
|
>>>
|
||||||
|
>>> key = get_random_bytes(32)
|
||||||
|
>>> cipher = AES.new(key, AES.MODE_OCB)
|
||||||
|
>>> plaintext = b"Attack at dawn"
|
||||||
|
>>> ciphertext, mac = cipher.encrypt_and_digest(plaintext)
|
||||||
|
>>> # Deliver cipher.nonce, ciphertext and mac
|
||||||
|
...
|
||||||
|
>>> cipher = AES.new(key, AES.MODE_OCB, nonce=nonce)
|
||||||
|
>>> try:
|
||||||
|
>>> plaintext = cipher.decrypt_and_verify(ciphertext, mac)
|
||||||
|
>>> except ValueError:
|
||||||
|
>>> print "Invalid message"
|
||||||
|
>>> else:
|
||||||
|
>>> print plaintext
|
||||||
|
|
||||||
|
:undocumented: __package__
|
||||||
|
|
||||||
|
.. _RFC7253: http://www.rfc-editor.org/info/rfc7253
|
||||||
|
.. _free licenses: http://web.cs.ucdavis.edu/~rogaway/ocb/license.htm
|
||||||
|
"""
|
||||||
|
|
||||||
|
from Crypto.Util.py3compat import b, bord, bchr, unhexlify
|
||||||
|
from Crypto.Util.number import long_to_bytes, bytes_to_long
|
||||||
|
from Crypto.Util.strxor import strxor
|
||||||
|
|
||||||
|
from Crypto.Hash import BLAKE2s
|
||||||
|
from Crypto.Random import get_random_bytes
|
||||||
|
|
||||||
|
from Crypto.Util._raw_api import (load_pycryptodome_raw_lib, VoidPointer,
|
||||||
|
create_string_buffer, get_raw_buffer,
|
||||||
|
SmartPointer, c_size_t, expect_byte_string,
|
||||||
|
)
|
||||||
|
|
||||||
|
_raw_ocb_lib = load_pycryptodome_raw_lib("Crypto.Cipher._raw_ocb", """
|
||||||
|
int OCB_start_operation(void *cipher,
|
||||||
|
const uint8_t *offset_0,
|
||||||
|
size_t offset_0_len,
|
||||||
|
void **pState);
|
||||||
|
int OCB_encrypt(void *state,
|
||||||
|
const uint8_t *in,
|
||||||
|
uint8_t *out,
|
||||||
|
size_t data_len);
|
||||||
|
int OCB_decrypt(void *state,
|
||||||
|
const uint8_t *in,
|
||||||
|
uint8_t *out,
|
||||||
|
size_t data_len);
|
||||||
|
int OCB_update(void *state,
|
||||||
|
const uint8_t *in,
|
||||||
|
size_t data_len);
|
||||||
|
int OCB_digest(void *state,
|
||||||
|
uint8_t *tag,
|
||||||
|
size_t tag_len);
|
||||||
|
int OCB_stop_operation(void *state);
|
||||||
|
""")
|
||||||
|
|
||||||
|
|
||||||
|
class OcbMode(object):
|
||||||
|
"""Offset Codebook (OCB) mode.
|
||||||
|
|
||||||
|
:undocumented: __init__
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__(self, factory, nonce, mac_len, cipher_params):
|
||||||
|
|
||||||
|
if factory.block_size != 16:
|
||||||
|
raise ValueError("OCB mode is only available for ciphers"
|
||||||
|
" that operate on 128 bits blocks")
|
||||||
|
|
||||||
|
self.block_size = 16
|
||||||
|
"""The block size of the underlying cipher, in bytes."""
|
||||||
|
|
||||||
|
self.nonce = nonce
|
||||||
|
"""Nonce used for this session."""
|
||||||
|
if len(nonce) not in list(range(1, 16)):
|
||||||
|
raise ValueError("Nonce must be at most 15 bytes long")
|
||||||
|
|
||||||
|
self._mac_len = mac_len
|
||||||
|
if not 8 <= mac_len <= 16:
|
||||||
|
raise ValueError("MAC tag must be between 8 and 16 bytes long")
|
||||||
|
|
||||||
|
# Cache for MAC tag
|
||||||
|
self._mac_tag = None
|
||||||
|
|
||||||
|
# Cache for unaligned associated data
|
||||||
|
self._cache_A = b("")
|
||||||
|
|
||||||
|
# Cache for unaligned ciphertext/plaintext
|
||||||
|
self._cache_P = b("")
|
||||||
|
|
||||||
|
# Allowed transitions after initialization
|
||||||
|
self._next = [self.update, self.encrypt, self.decrypt,
|
||||||
|
self.digest, self.verify]
|
||||||
|
|
||||||
|
# Compute Offset_0
|
||||||
|
params_without_key = dict(cipher_params)
|
||||||
|
key = params_without_key.pop("key")
|
||||||
|
nonce = (bchr(self._mac_len << 4 & 0xFF) +
|
||||||
|
bchr(0) * (14 - len(self.nonce)) +
|
||||||
|
bchr(1) +
|
||||||
|
self.nonce)
|
||||||
|
bottom = bord(nonce[15]) & 0x3F # 6 bits, 0..63
|
||||||
|
ktop = factory.new(key, factory.MODE_ECB, **params_without_key)\
|
||||||
|
.encrypt(nonce[:15] + bchr(bord(nonce[15]) & 0xC0))
|
||||||
|
stretch = ktop + strxor(ktop[:8], ktop[1:9]) # 192 bits
|
||||||
|
offset_0 = long_to_bytes(bytes_to_long(stretch) >>
|
||||||
|
(64 - bottom), 24)[8:]
|
||||||
|
|
||||||
|
# Create low-level cipher instance
|
||||||
|
raw_cipher = factory._create_base_cipher(cipher_params)
|
||||||
|
if cipher_params:
|
||||||
|
raise TypeError("Unknown keywords: " + str(cipher_params))
|
||||||
|
|
||||||
|
self._state = VoidPointer()
|
||||||
|
result = _raw_ocb_lib.OCB_start_operation(raw_cipher.get(),
|
||||||
|
offset_0,
|
||||||
|
c_size_t(len(offset_0)),
|
||||||
|
self._state.address_of())
|
||||||
|
if result:
|
||||||
|
raise ValueError("Error %d while instantiating the OCB mode"
|
||||||
|
% result)
|
||||||
|
|
||||||
|
# Ensure that object disposal of this Python object will (eventually)
|
||||||
|
# free the memory allocated by the raw library for the cipher mode
|
||||||
|
self._state = SmartPointer(self._state.get(),
|
||||||
|
_raw_ocb_lib.OCB_stop_operation)
|
||||||
|
|
||||||
|
# Memory allocated for the underlying block cipher is now owed
|
||||||
|
# by the cipher mode
|
||||||
|
raw_cipher.release()
|
||||||
|
|
||||||
|
def _update(self, assoc_data, assoc_data_len):
|
||||||
|
expect_byte_string(assoc_data)
|
||||||
|
result = _raw_ocb_lib.OCB_update(self._state.get(),
|
||||||
|
assoc_data,
|
||||||
|
c_size_t(assoc_data_len))
|
||||||
|
if result:
|
||||||
|
raise ValueError("Error %d while MAC-ing in OCB mode" % result)
|
||||||
|
|
||||||
|
def update(self, assoc_data):
|
||||||
|
"""Process the associated data.
|
||||||
|
|
||||||
|
If there is any associated data, the caller has to invoke
|
||||||
|
this method one or more times, before using
|
||||||
|
``decrypt`` or ``encrypt``.
|
||||||
|
|
||||||
|
By *associated data* it is meant any data (e.g. packet headers) that
|
||||||
|
will not be encrypted and will be transmitted in the clear.
|
||||||
|
However, the receiver shall still able to detect modifications.
|
||||||
|
|
||||||
|
If there is no associated data, this method must not be called.
|
||||||
|
|
||||||
|
The caller may split associated data in segments of any size, and
|
||||||
|
invoke this method multiple times, each time with the next segment.
|
||||||
|
|
||||||
|
:Parameters:
|
||||||
|
assoc_data : byte string
|
||||||
|
A piece of associated data.
|
||||||
|
"""
|
||||||
|
|
||||||
|
if self.update not in self._next:
|
||||||
|
raise TypeError("update() can only be called"
|
||||||
|
" immediately after initialization")
|
||||||
|
|
||||||
|
self._next = [self.encrypt, self.decrypt, self.digest,
|
||||||
|
self.verify, self.update]
|
||||||
|
|
||||||
|
if len(self._cache_A) > 0:
|
||||||
|
filler = min(16 - len(self._cache_A), len(assoc_data))
|
||||||
|
self._cache_A += assoc_data[:filler]
|
||||||
|
assoc_data = assoc_data[filler:]
|
||||||
|
|
||||||
|
if len(self._cache_A) < 16:
|
||||||
|
return self
|
||||||
|
|
||||||
|
# Clear the cache, and proceeding with any other aligned data
|
||||||
|
self._cache_A, seg = b(""), self._cache_A
|
||||||
|
self.update(seg)
|
||||||
|
|
||||||
|
update_len = len(assoc_data) // 16 * 16
|
||||||
|
self._cache_A = assoc_data[update_len:]
|
||||||
|
self._update(assoc_data, update_len)
|
||||||
|
return self
|
||||||
|
|
||||||
|
def _transcrypt_aligned(self, in_data, in_data_len,
|
||||||
|
trans_func, trans_desc):
|
||||||
|
|
||||||
|
out_data = create_string_buffer(in_data_len)
|
||||||
|
result = trans_func(self._state.get(),
|
||||||
|
in_data,
|
||||||
|
out_data,
|
||||||
|
c_size_t(in_data_len))
|
||||||
|
if result:
|
||||||
|
raise ValueError("Error %d while %sing in OCB mode"
|
||||||
|
% (result, trans_desc))
|
||||||
|
return get_raw_buffer(out_data)
|
||||||
|
|
||||||
|
def _transcrypt(self, in_data, trans_func, trans_desc):
|
||||||
|
# Last piece to encrypt/decrypt
|
||||||
|
if in_data is None:
|
||||||
|
out_data = self._transcrypt_aligned(self._cache_P,
|
||||||
|
len(self._cache_P),
|
||||||
|
trans_func,
|
||||||
|
trans_desc)
|
||||||
|
self._cache_P = b("")
|
||||||
|
return out_data
|
||||||
|
|
||||||
|
# Try to fill up the cache, if it already contains something
|
||||||
|
expect_byte_string(in_data)
|
||||||
|
prefix = b("")
|
||||||
|
if len(self._cache_P) > 0:
|
||||||
|
filler = min(16 - len(self._cache_P), len(in_data))
|
||||||
|
self._cache_P += in_data[:filler]
|
||||||
|
in_data = in_data[filler:]
|
||||||
|
|
||||||
|
if len(self._cache_P) < 16:
|
||||||
|
# We could not manage to fill the cache, so there is certainly
|
||||||
|
# no output yet.
|
||||||
|
return b("")
|
||||||
|
|
||||||
|
# Clear the cache, and proceeding with any other aligned data
|
||||||
|
prefix = self._transcrypt_aligned(self._cache_P,
|
||||||
|
len(self._cache_P),
|
||||||
|
trans_func,
|
||||||
|
trans_desc)
|
||||||
|
self._cache_P = b("")
|
||||||
|
|
||||||
|
# Process data in multiples of the block size
|
||||||
|
trans_len = len(in_data) // 16 * 16
|
||||||
|
result = self._transcrypt_aligned(in_data,
|
||||||
|
trans_len,
|
||||||
|
trans_func,
|
||||||
|
trans_desc)
|
||||||
|
if prefix:
|
||||||
|
result = prefix + result
|
||||||
|
|
||||||
|
# Left-over
|
||||||
|
self._cache_P = in_data[trans_len:]
|
||||||
|
|
||||||
|
return result
|
||||||
|
|
||||||
|
def encrypt(self, plaintext=None):
|
||||||
|
"""Encrypt the next piece of plaintext.
|
||||||
|
|
||||||
|
After the entire plaintext has been passed (but before `digest`),
|
||||||
|
you **must** call this method one last time with no arguments to collect
|
||||||
|
the final piece of ciphertext.
|
||||||
|
|
||||||
|
If possible, use the method `encrypt_and_digest` instead.
|
||||||
|
|
||||||
|
:Parameters:
|
||||||
|
plaintext : byte string
|
||||||
|
The next piece of data to encrypt or ``None`` to signify
|
||||||
|
that encryption has finished and that any remaining ciphertext
|
||||||
|
has to be produced.
|
||||||
|
:Return:
|
||||||
|
the ciphertext, as a byte string.
|
||||||
|
Its length may not match the length of the *plaintext*.
|
||||||
|
"""
|
||||||
|
|
||||||
|
if self.encrypt not in self._next:
|
||||||
|
raise TypeError("encrypt() can only be called after"
|
||||||
|
" initialization or an update()")
|
||||||
|
|
||||||
|
if plaintext is None:
|
||||||
|
self._next = [self.digest]
|
||||||
|
else:
|
||||||
|
self._next = [self.encrypt]
|
||||||
|
return self._transcrypt(plaintext, _raw_ocb_lib.OCB_encrypt, "encrypt")
|
||||||
|
|
||||||
|
def decrypt(self, ciphertext=None):
|
||||||
|
"""Decrypt the next piece of ciphertext.
|
||||||
|
|
||||||
|
After the entire ciphertext has been passed (but before `verify`),
|
||||||
|
you **must** call this method one last time with no arguments to collect
|
||||||
|
the remaining piece of plaintext.
|
||||||
|
|
||||||
|
If possible, use the method `decrypt_and_verify` instead.
|
||||||
|
|
||||||
|
:Parameters:
|
||||||
|
ciphertext : byte string
|
||||||
|
The next piece of data to decrypt or ``None`` to signify
|
||||||
|
that decryption has finished and that any remaining plaintext
|
||||||
|
has to be produced.
|
||||||
|
:Return:
|
||||||
|
the plaintext, as a byte string.
|
||||||
|
Its length may not match the length of the *ciphertext*.
|
||||||
|
"""
|
||||||
|
|
||||||
|
if self.decrypt not in self._next:
|
||||||
|
raise TypeError("decrypt() can only be called after"
|
||||||
|
" initialization or an update()")
|
||||||
|
|
||||||
|
if ciphertext is None:
|
||||||
|
self._next = [self.verify]
|
||||||
|
else:
|
||||||
|
self._next = [self.decrypt]
|
||||||
|
return self._transcrypt(ciphertext,
|
||||||
|
_raw_ocb_lib.OCB_decrypt,
|
||||||
|
"decrypt")
|
||||||
|
|
||||||
|
def _compute_mac_tag(self):
|
||||||
|
|
||||||
|
if self._mac_tag is not None:
|
||||||
|
return
|
||||||
|
|
||||||
|
if self._cache_A:
|
||||||
|
self._update(self._cache_A, len(self._cache_A))
|
||||||
|
self._cache_A = b("")
|
||||||
|
|
||||||
|
mac_tag = create_string_buffer(16)
|
||||||
|
result = _raw_ocb_lib.OCB_digest(self._state.get(),
|
||||||
|
mac_tag,
|
||||||
|
c_size_t(len(mac_tag))
|
||||||
|
)
|
||||||
|
if result:
|
||||||
|
raise ValueError("Error %d while computing digest in OCB mode"
|
||||||
|
% result)
|
||||||
|
self._mac_tag = get_raw_buffer(mac_tag)[:self._mac_len]
|
||||||
|
|
||||||
|
def digest(self):
|
||||||
|
"""Compute the *binary* MAC tag.
|
||||||
|
|
||||||
|
Call this method after the final `encrypt` (the one with no arguments)
|
||||||
|
to obtain the MAC tag.
|
||||||
|
|
||||||
|
The MAC tag is needed by the receiver to determine authenticity
|
||||||
|
of the message.
|
||||||
|
|
||||||
|
:Return: the MAC, as a byte string.
|
||||||
|
"""
|
||||||
|
|
||||||
|
if self.digest not in self._next:
|
||||||
|
raise TypeError("digest() cannot be called now for this cipher")
|
||||||
|
|
||||||
|
assert(len(self._cache_P) == 0)
|
||||||
|
|
||||||
|
self._next = [self.digest]
|
||||||
|
|
||||||
|
if self._mac_tag is None:
|
||||||
|
self._compute_mac_tag()
|
||||||
|
|
||||||
|
return self._mac_tag
|
||||||
|
|
||||||
|
def hexdigest(self):
|
||||||
|
"""Compute the *printable* MAC tag.
|
||||||
|
|
||||||
|
This method is like `digest`.
|
||||||
|
|
||||||
|
:Return: the MAC, as a hexadecimal string.
|
||||||
|
"""
|
||||||
|
return "".join(["%02x" % bord(x) for x in self.digest()])
|
||||||
|
|
||||||
|
def verify(self, received_mac_tag):
|
||||||
|
"""Validate the *binary* MAC tag.
|
||||||
|
|
||||||
|
Call this method after the final `decrypt` (the one with no arguments)
|
||||||
|
to check if the message is authentic and valid.
|
||||||
|
|
||||||
|
:Parameters:
|
||||||
|
received_mac_tag : byte string
|
||||||
|
This is the *binary* MAC, as received from the sender.
|
||||||
|
:Raises ValueError:
|
||||||
|
if the MAC does not match. The message has been tampered with
|
||||||
|
or the key is incorrect.
|
||||||
|
"""
|
||||||
|
|
||||||
|
if self.verify not in self._next:
|
||||||
|
raise TypeError("verify() cannot be called now for this cipher")
|
||||||
|
|
||||||
|
assert(len(self._cache_P) == 0)
|
||||||
|
|
||||||
|
self._next = [self.verify]
|
||||||
|
|
||||||
|
if self._mac_tag is None:
|
||||||
|
self._compute_mac_tag()
|
||||||
|
|
||||||
|
secret = get_random_bytes(16)
|
||||||
|
mac1 = BLAKE2s.new(digest_bits=160, key=secret, data=self._mac_tag)
|
||||||
|
mac2 = BLAKE2s.new(digest_bits=160, key=secret, data=received_mac_tag)
|
||||||
|
|
||||||
|
if mac1.digest() != mac2.digest():
|
||||||
|
raise ValueError("MAC check failed")
|
||||||
|
|
||||||
|
def hexverify(self, hex_mac_tag):
|
||||||
|
"""Validate the *printable* MAC tag.
|
||||||
|
|
||||||
|
This method is like `verify`.
|
||||||
|
|
||||||
|
:Parameters:
|
||||||
|
hex_mac_tag : string
|
||||||
|
This is the *printable* MAC, as received from the sender.
|
||||||
|
:Raises ValueError:
|
||||||
|
if the MAC does not match. The message has been tampered with
|
||||||
|
or the key is incorrect.
|
||||||
|
"""
|
||||||
|
|
||||||
|
self.verify(unhexlify(hex_mac_tag))
|
||||||
|
|
||||||
|
def encrypt_and_digest(self, plaintext):
|
||||||
|
"""Encrypt the message and create the MAC tag in one step.
|
||||||
|
|
||||||
|
:Parameters:
|
||||||
|
plaintext : byte string
|
||||||
|
The entire message to encrypt.
|
||||||
|
:Return:
|
||||||
|
a tuple with two byte strings:
|
||||||
|
|
||||||
|
- the encrypted data
|
||||||
|
- the MAC
|
||||||
|
"""
|
||||||
|
|
||||||
|
return self.encrypt(plaintext) + self.encrypt(), self.digest()
|
||||||
|
|
||||||
|
def decrypt_and_verify(self, ciphertext, received_mac_tag):
|
||||||
|
"""Decrypted the message and verify its authenticity in one step.
|
||||||
|
|
||||||
|
:Parameters:
|
||||||
|
ciphertext : byte string
|
||||||
|
The entire message to decrypt.
|
||||||
|
received_mac_tag : byte string
|
||||||
|
This is the *binary* MAC, as received from the sender.
|
||||||
|
|
||||||
|
:Return: the decrypted data (byte string).
|
||||||
|
:Raises ValueError:
|
||||||
|
if the MAC does not match. The message has been tampered with
|
||||||
|
or the key is incorrect.
|
||||||
|
"""
|
||||||
|
|
||||||
|
plaintext = self.decrypt(ciphertext) + self.decrypt()
|
||||||
|
self.verify(received_mac_tag)
|
||||||
|
return plaintext
|
||||||
|
|
||||||
|
|
||||||
|
def _create_ocb_cipher(factory, **kwargs):
|
||||||
|
"""Create a new block cipher, configured in OCB mode.
|
||||||
|
|
||||||
|
:Parameters:
|
||||||
|
factory : module
|
||||||
|
A symmetric cipher module from `Crypto.Cipher`
|
||||||
|
(like `Crypto.Cipher.AES`).
|
||||||
|
|
||||||
|
:Keywords:
|
||||||
|
nonce : byte string
|
||||||
|
A value that must never be reused for any other encryption.
|
||||||
|
Its length can vary from 1 to 15 bytes.
|
||||||
|
If not specified, a random 15 bytes long nonce is generated.
|
||||||
|
|
||||||
|
mac_len : integer
|
||||||
|
Length of the MAC, in bytes.
|
||||||
|
It must be in the range ``[8..16]``.
|
||||||
|
The default is 16 (128 bits).
|
||||||
|
|
||||||
|
Any other keyword will be passed to the underlying block cipher.
|
||||||
|
See the relevant documentation for details (at least ``key`` will need
|
||||||
|
to be present).
|
||||||
|
"""
|
||||||
|
|
||||||
|
try:
|
||||||
|
nonce = kwargs.pop("nonce", None)
|
||||||
|
if nonce is None:
|
||||||
|
nonce = get_random_bytes(15)
|
||||||
|
mac_len = kwargs.pop("mac_len", 16)
|
||||||
|
except KeyError as e:
|
||||||
|
raise TypeError("Keyword missing: " + str(e))
|
||||||
|
|
||||||
|
return OcbMode(factory, nonce, mac_len, kwargs)
|
240
venv/Lib/site-packages/Crypto/Cipher/_mode_ofb.py
Normal file
240
venv/Lib/site-packages/Crypto/Cipher/_mode_ofb.py
Normal file
|
@ -0,0 +1,240 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
#
|
||||||
|
# Cipher/mode_ofb.py : OFB mode
|
||||||
|
#
|
||||||
|
# ===================================================================
|
||||||
|
# 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.
|
||||||
|
# ===================================================================
|
||||||
|
|
||||||
|
"""
|
||||||
|
Output Feedback (CFB) mode.
|
||||||
|
"""
|
||||||
|
|
||||||
|
__all__ = ['OfbMode']
|
||||||
|
|
||||||
|
from Crypto.Util._raw_api import (load_pycryptodome_raw_lib, VoidPointer,
|
||||||
|
create_string_buffer, get_raw_buffer,
|
||||||
|
SmartPointer, c_size_t, expect_byte_string)
|
||||||
|
|
||||||
|
from Crypto.Random import get_random_bytes
|
||||||
|
|
||||||
|
raw_ofb_lib = load_pycryptodome_raw_lib("Crypto.Cipher._raw_ofb", """
|
||||||
|
int OFB_start_operation(void *cipher,
|
||||||
|
const uint8_t iv[],
|
||||||
|
size_t iv_len,
|
||||||
|
void **pResult);
|
||||||
|
int OFB_encrypt(void *ofbState,
|
||||||
|
const uint8_t *in,
|
||||||
|
uint8_t *out,
|
||||||
|
size_t data_len);
|
||||||
|
int OFB_decrypt(void *ofbState,
|
||||||
|
const uint8_t *in,
|
||||||
|
uint8_t *out,
|
||||||
|
size_t data_len);
|
||||||
|
int OFB_stop_operation(void *state);
|
||||||
|
"""
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class OfbMode(object):
|
||||||
|
"""*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 the
|
||||||
|
previous ciphertext block.
|
||||||
|
|
||||||
|
An Initialization Vector (*IV*) is required.
|
||||||
|
|
||||||
|
See `NIST SP800-38A`_ , Section 6.4.
|
||||||
|
|
||||||
|
.. _`NIST SP800-38A` : http://csrc.nist.gov/publications/nistpubs/800-38a/sp800-38a.pdf
|
||||||
|
|
||||||
|
:undocumented: __init__
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__(self, block_cipher, iv):
|
||||||
|
"""Create a new block cipher, configured in OFB mode.
|
||||||
|
|
||||||
|
:Parameters:
|
||||||
|
block_cipher : C pointer
|
||||||
|
A smart pointer to the low-level block cipher instance.
|
||||||
|
|
||||||
|
iv : byte string
|
||||||
|
The initialization vector to use for encryption or decryption.
|
||||||
|
It is as long as the cipher block.
|
||||||
|
|
||||||
|
**The IV must be a nonce, to to be reused for any other
|
||||||
|
message**. It shall be a nonce or a random value.
|
||||||
|
|
||||||
|
Reusing the *IV* for encryptions performed with the same key
|
||||||
|
compromises confidentiality.
|
||||||
|
"""
|
||||||
|
|
||||||
|
expect_byte_string(iv)
|
||||||
|
self._state = VoidPointer()
|
||||||
|
result = raw_ofb_lib.OFB_start_operation(block_cipher.get(),
|
||||||
|
iv,
|
||||||
|
c_size_t(len(iv)),
|
||||||
|
self._state.address_of())
|
||||||
|
if result:
|
||||||
|
raise ValueError("Error %d while instatiating the OFB mode"
|
||||||
|
% result)
|
||||||
|
|
||||||
|
# Ensure that object disposal of this Python object will (eventually)
|
||||||
|
# free the memory allocated by the raw library for the cipher mode
|
||||||
|
self._state = SmartPointer(self._state.get(),
|
||||||
|
raw_ofb_lib.OFB_stop_operation)
|
||||||
|
|
||||||
|
# Memory allocated for the underlying block cipher is now owed
|
||||||
|
# by the cipher mode
|
||||||
|
block_cipher.release()
|
||||||
|
|
||||||
|
self.block_size = len(iv)
|
||||||
|
"""The block size of the underlying cipher, in bytes."""
|
||||||
|
|
||||||
|
self.iv = iv
|
||||||
|
"""The Initialization Vector originally used to create the object.
|
||||||
|
The value does not change."""
|
||||||
|
|
||||||
|
self.IV = iv
|
||||||
|
"""Alias for `iv`"""
|
||||||
|
|
||||||
|
self._next = [ self.encrypt, self.decrypt ]
|
||||||
|
|
||||||
|
def encrypt(self, plaintext):
|
||||||
|
"""Encrypt data with the key and the parameters set at initialization.
|
||||||
|
|
||||||
|
A cipher object is stateful: once you have encrypted a message
|
||||||
|
you cannot encrypt (or decrypt) another message using the same
|
||||||
|
object.
|
||||||
|
|
||||||
|
The data to encrypt can be broken up in two or
|
||||||
|
more pieces and `encrypt` can be called multiple times.
|
||||||
|
|
||||||
|
That is, the statement:
|
||||||
|
|
||||||
|
>>> c.encrypt(a) + c.encrypt(b)
|
||||||
|
|
||||||
|
is equivalent to:
|
||||||
|
|
||||||
|
>>> c.encrypt(a+b)
|
||||||
|
|
||||||
|
This function does not add any padding to the plaintext.
|
||||||
|
|
||||||
|
:Parameters:
|
||||||
|
plaintext : byte string
|
||||||
|
The piece of data to encrypt.
|
||||||
|
It can be of any length.
|
||||||
|
:Return:
|
||||||
|
the encrypted data, as a byte string.
|
||||||
|
It is as long as *plaintext*.
|
||||||
|
"""
|
||||||
|
|
||||||
|
if self.encrypt not in self._next:
|
||||||
|
raise TypeError("encrypt() cannot be called after decrypt()")
|
||||||
|
self._next = [ self.encrypt ]
|
||||||
|
|
||||||
|
expect_byte_string(plaintext)
|
||||||
|
ciphertext = create_string_buffer(len(plaintext))
|
||||||
|
result = raw_ofb_lib.OFB_encrypt(self._state.get(),
|
||||||
|
plaintext,
|
||||||
|
ciphertext,
|
||||||
|
c_size_t(len(plaintext)))
|
||||||
|
if result:
|
||||||
|
raise ValueError("Error %d while encrypting in OFB mode" % result)
|
||||||
|
return get_raw_buffer(ciphertext)
|
||||||
|
|
||||||
|
def decrypt(self, ciphertext):
|
||||||
|
"""Decrypt data with the key and the parameters set at initialization.
|
||||||
|
|
||||||
|
A cipher object is stateful: once you have decrypted a message
|
||||||
|
you cannot decrypt (or encrypt) another message with the same
|
||||||
|
object.
|
||||||
|
|
||||||
|
The data to decrypt can be broken up in two or
|
||||||
|
more pieces and `decrypt` can be called multiple times.
|
||||||
|
|
||||||
|
That is, the statement:
|
||||||
|
|
||||||
|
>>> c.decrypt(a) + c.decrypt(b)
|
||||||
|
|
||||||
|
is equivalent to:
|
||||||
|
|
||||||
|
>>> c.decrypt(a+b)
|
||||||
|
|
||||||
|
This function does not remove any padding from the plaintext.
|
||||||
|
|
||||||
|
:Parameters:
|
||||||
|
ciphertext : byte string
|
||||||
|
The piece of data to decrypt.
|
||||||
|
It can be of any length.
|
||||||
|
|
||||||
|
:Return: the decrypted data (byte string).
|
||||||
|
"""
|
||||||
|
|
||||||
|
if self.decrypt not in self._next:
|
||||||
|
raise TypeError("decrypt() cannot be called after encrypt()")
|
||||||
|
self._next = [ self.decrypt ]
|
||||||
|
|
||||||
|
expect_byte_string(ciphertext)
|
||||||
|
plaintext = create_string_buffer(len(ciphertext))
|
||||||
|
result = raw_ofb_lib.OFB_decrypt(self._state.get(),
|
||||||
|
ciphertext,
|
||||||
|
plaintext,
|
||||||
|
c_size_t(len(ciphertext)))
|
||||||
|
if result:
|
||||||
|
raise ValueError("Error %d while decrypting in OFB mode" % result)
|
||||||
|
return get_raw_buffer(plaintext)
|
||||||
|
|
||||||
|
|
||||||
|
def _create_ofb_cipher(factory, **kwargs):
|
||||||
|
"""Instantiate a cipher object that performs OFB encryption/decryption.
|
||||||
|
|
||||||
|
:Parameters:
|
||||||
|
factory : module
|
||||||
|
The underlying block cipher, a module from ``Crypto.Cipher``.
|
||||||
|
|
||||||
|
:Keywords:
|
||||||
|
iv : byte string
|
||||||
|
The IV to use for OFB.
|
||||||
|
|
||||||
|
IV : byte string
|
||||||
|
Alias for ``iv``.
|
||||||
|
|
||||||
|
Any other keyword will be passed to the underlying block cipher.
|
||||||
|
See the relevant documentation for details (at least ``key`` will need
|
||||||
|
to be present).
|
||||||
|
"""
|
||||||
|
|
||||||
|
cipher_state = factory._create_base_cipher(kwargs)
|
||||||
|
iv = kwargs.pop("IV", None)
|
||||||
|
IV = kwargs.pop("iv", None)
|
||||||
|
|
||||||
|
if (None, None) == (iv, IV):
|
||||||
|
iv = get_random_bytes(factory.block_size)
|
||||||
|
if iv is not None:
|
||||||
|
if IV is not None:
|
||||||
|
raise TypeError("You must either use 'iv' or 'IV', not both")
|
||||||
|
else:
|
||||||
|
iv = IV
|
||||||
|
|
||||||
|
if kwargs:
|
||||||
|
raise TypeError("Unknown parameters for OFB: %s" % str(kwargs))
|
||||||
|
|
||||||
|
return OfbMode(cipher_state, iv)
|
204
venv/Lib/site-packages/Crypto/Cipher/_mode_openpgp.py
Normal file
204
venv/Lib/site-packages/Crypto/Cipher/_mode_openpgp.py
Normal file
|
@ -0,0 +1,204 @@
|
||||||
|
# ===================================================================
|
||||||
|
#
|
||||||
|
# Copyright (c) 2014, Legrandin <helderijs@gmail.com>
|
||||||
|
# All rights reserved.
|
||||||
|
#
|
||||||
|
# Redistribution and use in source and binary forms, with or without
|
||||||
|
# modification, are permitted provided that the following conditions
|
||||||
|
# are met:
|
||||||
|
#
|
||||||
|
# 1. Redistributions of source code must retain the above copyright
|
||||||
|
# notice, this list of conditions and the following disclaimer.
|
||||||
|
# 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
# notice, this list of conditions and the following disclaimer in
|
||||||
|
# the documentation and/or other materials provided with the
|
||||||
|
# distribution.
|
||||||
|
#
|
||||||
|
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||||
|
# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||||
|
# COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||||
|
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||||
|
# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||||
|
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||||
|
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||||
|
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
|
# POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
# ===================================================================
|
||||||
|
|
||||||
|
"""
|
||||||
|
OpenPGP mode.
|
||||||
|
"""
|
||||||
|
|
||||||
|
__all__ = ['OpenPgpMode']
|
||||||
|
|
||||||
|
from Crypto.Util.py3compat import bchr
|
||||||
|
from Crypto.Random import get_random_bytes
|
||||||
|
|
||||||
|
class OpenPgpMode(object):
|
||||||
|
"""OpenPGP mode.
|
||||||
|
|
||||||
|
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 *encrypted* IV (not the IV itself) is
|
||||||
|
transmitted to the receiver.
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
|
:undocumented: __init__
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__(self, factory, key, iv, cipher_params):
|
||||||
|
|
||||||
|
#: The block size of the underlying cipher, in bytes.
|
||||||
|
self.block_size = factory.block_size
|
||||||
|
|
||||||
|
self._done_first_block = False # True after the first encryption
|
||||||
|
|
||||||
|
# Instantiate a temporary cipher to process the IV
|
||||||
|
IV_cipher = factory.new(
|
||||||
|
key,
|
||||||
|
factory.MODE_CFB,
|
||||||
|
IV=bchr(0) * self.block_size,
|
||||||
|
segment_size=self.block_size * 8,
|
||||||
|
**cipher_params)
|
||||||
|
|
||||||
|
# The cipher will be used for...
|
||||||
|
if len(iv) == self.block_size:
|
||||||
|
# ... encryption
|
||||||
|
self._encrypted_IV = IV_cipher.encrypt(iv + iv[-2:])
|
||||||
|
elif len(iv) == self.block_size + 2:
|
||||||
|
# ... decryption
|
||||||
|
self._encrypted_IV = iv
|
||||||
|
iv = IV_cipher.decrypt(iv)
|
||||||
|
if iv[-2:] != iv[-4:-2]:
|
||||||
|
raise ValueError("Failed integrity check for OPENPGP IV")
|
||||||
|
iv = iv[:-2]
|
||||||
|
else:
|
||||||
|
raise ValueError("Length of IV must be %d or %d bytes"
|
||||||
|
" for MODE_OPENPGP"
|
||||||
|
% (self.block_size, self.block_size + 2))
|
||||||
|
|
||||||
|
self.iv = self.IV = iv
|
||||||
|
|
||||||
|
# Instantiate the cipher for the real PGP data
|
||||||
|
self._cipher = factory.new(
|
||||||
|
key,
|
||||||
|
factory.MODE_CFB,
|
||||||
|
IV=self._encrypted_IV[-self.block_size:],
|
||||||
|
segment_size=self.block_size * 8,
|
||||||
|
**cipher_params)
|
||||||
|
|
||||||
|
def encrypt(self, plaintext):
|
||||||
|
"""Encrypt data with the key and the parameters set at initialization.
|
||||||
|
|
||||||
|
A cipher object is stateful: once you have encrypted a message
|
||||||
|
you cannot encrypt (or decrypt) another message using the same
|
||||||
|
object.
|
||||||
|
|
||||||
|
The data to encrypt can be broken up in two or
|
||||||
|
more pieces and `encrypt` can be called multiple times.
|
||||||
|
|
||||||
|
That is, the statement:
|
||||||
|
|
||||||
|
>>> c.encrypt(a) + c.encrypt(b)
|
||||||
|
|
||||||
|
is equivalent to:
|
||||||
|
|
||||||
|
>>> c.encrypt(a+b)
|
||||||
|
|
||||||
|
This function does not add any padding to the plaintext.
|
||||||
|
|
||||||
|
: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,
|
||||||
|
the encypted IV is prepended to the returned ciphertext.
|
||||||
|
"""
|
||||||
|
|
||||||
|
res = self._cipher.encrypt(plaintext)
|
||||||
|
if not self._done_first_block:
|
||||||
|
res = self._encrypted_IV + res
|
||||||
|
self._done_first_block = True
|
||||||
|
return res
|
||||||
|
|
||||||
|
def decrypt(self, ciphertext):
|
||||||
|
"""Decrypt data with the key and the parameters set at initialization.
|
||||||
|
|
||||||
|
A cipher object is stateful: once you have decrypted a message
|
||||||
|
you cannot decrypt (or encrypt) another message with the same
|
||||||
|
object.
|
||||||
|
|
||||||
|
The data to decrypt can be broken up in two or
|
||||||
|
more pieces and `decrypt` can be called multiple times.
|
||||||
|
|
||||||
|
That is, the statement:
|
||||||
|
|
||||||
|
>>> c.decrypt(a) + c.decrypt(b)
|
||||||
|
|
||||||
|
is equivalent to:
|
||||||
|
|
||||||
|
>>> c.decrypt(a+b)
|
||||||
|
|
||||||
|
This function does not remove any padding from the plaintext.
|
||||||
|
|
||||||
|
:Parameters:
|
||||||
|
ciphertext : byte string
|
||||||
|
The piece of data to decrypt.
|
||||||
|
|
||||||
|
:Return: the decrypted data (byte string).
|
||||||
|
"""
|
||||||
|
|
||||||
|
return self._cipher.decrypt(ciphertext)
|
||||||
|
|
||||||
|
|
||||||
|
def _create_openpgp_cipher(factory, **kwargs):
|
||||||
|
"""Create a new block cipher, configured in OpenPGP mode.
|
||||||
|
|
||||||
|
:Parameters:
|
||||||
|
factory : module
|
||||||
|
The module.
|
||||||
|
|
||||||
|
:Keywords:
|
||||||
|
key : byte string
|
||||||
|
The secret key to use in the symmetric cipher.
|
||||||
|
|
||||||
|
IV : byte string
|
||||||
|
The initialization vector to use for encryption or decryption.
|
||||||
|
|
||||||
|
For encryption, the IV must be as long as the cipher block size.
|
||||||
|
|
||||||
|
For decryption, it must be 2 bytes longer (it is actually the
|
||||||
|
*encrypted* IV which was prefixed to the ciphertext).
|
||||||
|
"""
|
||||||
|
|
||||||
|
iv = kwargs.pop("IV", None)
|
||||||
|
IV = kwargs.pop("iv", None)
|
||||||
|
|
||||||
|
if (None, None) == (iv, IV):
|
||||||
|
iv = get_random_bytes(factory.block_size)
|
||||||
|
if iv is not None:
|
||||||
|
if IV is not None:
|
||||||
|
raise TypeError("You must either use 'iv' or 'IV', not both")
|
||||||
|
else:
|
||||||
|
iv = IV
|
||||||
|
|
||||||
|
try:
|
||||||
|
key = kwargs.pop("key")
|
||||||
|
except KeyError as e:
|
||||||
|
raise TypeError("Missing component: " + str(e))
|
||||||
|
|
||||||
|
return OpenPgpMode(factory, key, iv, kwargs)
|
394
venv/Lib/site-packages/Crypto/Cipher/_mode_siv.py
Normal file
394
venv/Lib/site-packages/Crypto/Cipher/_mode_siv.py
Normal file
|
@ -0,0 +1,394 @@
|
||||||
|
# ===================================================================
|
||||||
|
#
|
||||||
|
# Copyright (c) 2014, Legrandin <helderijs@gmail.com>
|
||||||
|
# All rights reserved.
|
||||||
|
#
|
||||||
|
# Redistribution and use in source and binary forms, with or without
|
||||||
|
# modification, are permitted provided that the following conditions
|
||||||
|
# are met:
|
||||||
|
#
|
||||||
|
# 1. Redistributions of source code must retain the above copyright
|
||||||
|
# notice, this list of conditions and the following disclaimer.
|
||||||
|
# 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
# notice, this list of conditions and the following disclaimer in
|
||||||
|
# the documentation and/or other materials provided with the
|
||||||
|
# distribution.
|
||||||
|
#
|
||||||
|
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||||
|
# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||||
|
# COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||||
|
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||||
|
# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||||
|
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||||
|
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||||
|
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
|
# POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
# ===================================================================
|
||||||
|
|
||||||
|
"""
|
||||||
|
Synthetic Initialization Vector (SIV) mode.
|
||||||
|
"""
|
||||||
|
|
||||||
|
__all__ = ['SivMode']
|
||||||
|
|
||||||
|
from binascii import hexlify
|
||||||
|
|
||||||
|
from Crypto.Util.py3compat import byte_string, bord, unhexlify, b
|
||||||
|
|
||||||
|
from Crypto.Util.number import long_to_bytes, bytes_to_long
|
||||||
|
from Crypto.Protocol.KDF import _S2V
|
||||||
|
from Crypto.Hash import BLAKE2s
|
||||||
|
from Crypto.Random import get_random_bytes
|
||||||
|
|
||||||
|
|
||||||
|
class SivMode(object):
|
||||||
|
"""Synthetic Initialization Vector (SIV).
|
||||||
|
|
||||||
|
This is an Authenticated Encryption with Associated Data (`AEAD`_) mode.
|
||||||
|
It provides both confidentiality and authenticity.
|
||||||
|
|
||||||
|
The header of the message may be left in the clear, if needed, and it will
|
||||||
|
still be subject to authentication. The decryption step tells the receiver
|
||||||
|
if the message comes from a source that really knowns the secret key.
|
||||||
|
Additionally, decryption detects if any part of the message - including the
|
||||||
|
header - has been modified or corrupted.
|
||||||
|
|
||||||
|
Unlike other AEAD modes such as CCM, EAX or GCM, accidental reuse of a
|
||||||
|
nonce is not catastrophic for the confidentiality of the message. The only
|
||||||
|
effect is that an attacker can tell when the same plaintext (and same
|
||||||
|
associated data) is protected with the same key.
|
||||||
|
|
||||||
|
The length of the MAC is fixed to the block size of the underlying cipher.
|
||||||
|
The key size is twice the length of the key of the underlying cipher.
|
||||||
|
|
||||||
|
This mode is only available for AES ciphers.
|
||||||
|
|
||||||
|
+--------------------+---------------+-------------------+
|
||||||
|
| Cipher | SIV MAC size | SIV key length |
|
||||||
|
| | (bytes) | (bytes) |
|
||||||
|
+====================+===============+===================+
|
||||||
|
| AES-128 | 16 | 32 |
|
||||||
|
+--------------------+---------------+-------------------+
|
||||||
|
| AES-192 | 16 | 48 |
|
||||||
|
+--------------------+---------------+-------------------+
|
||||||
|
| AES-256 | 16 | 64 |
|
||||||
|
+--------------------+---------------+-------------------+
|
||||||
|
|
||||||
|
See `RFC5297`_ and the `original paper`__.
|
||||||
|
|
||||||
|
.. _RFC5297: https://tools.ietf.org/html/rfc5297
|
||||||
|
.. _AEAD: http://blog.cryptographyengineering.com/2012/05/how-to-choose-authenticated-encryption.html
|
||||||
|
.. __: http://www.cs.ucdavis.edu/~rogaway/papers/keywrap.pdf
|
||||||
|
|
||||||
|
:undocumented: __init__
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__(self, factory, key, nonce, kwargs):
|
||||||
|
|
||||||
|
self.block_size = factory.block_size
|
||||||
|
"""The block size of the underlying cipher, in bytes."""
|
||||||
|
|
||||||
|
self._factory = factory
|
||||||
|
|
||||||
|
self._nonce = nonce
|
||||||
|
self._cipher_params = kwargs
|
||||||
|
|
||||||
|
if len(key) not in (32, 48, 64):
|
||||||
|
raise ValueError("Incorrect key length (%d bytes)" % len(key))
|
||||||
|
|
||||||
|
if nonce is not None:
|
||||||
|
if not byte_string(nonce):
|
||||||
|
raise TypeError("When provided, the nonce must be a byte string")
|
||||||
|
|
||||||
|
if len(nonce) == 0:
|
||||||
|
raise ValueError("When provided, the nonce must be non-empty")
|
||||||
|
|
||||||
|
self.nonce = nonce
|
||||||
|
"""Public attribute is only available in case of non-deterministic
|
||||||
|
encryption."""
|
||||||
|
|
||||||
|
subkey_size = len(key) // 2
|
||||||
|
|
||||||
|
self._mac_tag = None # Cache for MAC tag
|
||||||
|
self._kdf = _S2V(key[:subkey_size],
|
||||||
|
ciphermod=factory,
|
||||||
|
cipher_params=self._cipher_params)
|
||||||
|
self._subkey_cipher = key[subkey_size:]
|
||||||
|
|
||||||
|
# Purely for the purpose of verifying that cipher_params are OK
|
||||||
|
factory.new(key[:subkey_size], factory.MODE_ECB, **kwargs)
|
||||||
|
|
||||||
|
# Allowed transitions after initialization
|
||||||
|
self._next = [self.update, self.encrypt, self.decrypt,
|
||||||
|
self.digest, self.verify]
|
||||||
|
|
||||||
|
def _create_ctr_cipher(self, mac_tag):
|
||||||
|
"""Create a new CTR cipher from the MAC in SIV mode"""
|
||||||
|
|
||||||
|
tag_int = bytes_to_long(mac_tag)
|
||||||
|
return self._factory.new(
|
||||||
|
self._subkey_cipher,
|
||||||
|
self._factory.MODE_CTR,
|
||||||
|
initial_value=tag_int ^ (tag_int & 0x8000000080000000),
|
||||||
|
nonce=b(""),
|
||||||
|
**self._cipher_params)
|
||||||
|
|
||||||
|
def update(self, component):
|
||||||
|
"""Protect one associated data component
|
||||||
|
|
||||||
|
For SIV, the associated data is a sequence (*vector*) of non-empty
|
||||||
|
byte strings (*components*).
|
||||||
|
|
||||||
|
This method consumes the next component. It must be called
|
||||||
|
once for each of the components that constitue the associated data.
|
||||||
|
|
||||||
|
Note that the components have clear boundaries, so that:
|
||||||
|
|
||||||
|
>>> cipher.update(b"builtin")
|
||||||
|
>>> cipher.update(b"securely")
|
||||||
|
|
||||||
|
is not equivalent to:
|
||||||
|
|
||||||
|
>>> cipher.update(b"built")
|
||||||
|
>>> cipher.update(b"insecurely")
|
||||||
|
|
||||||
|
If there is no associated data, this method must not be called.
|
||||||
|
|
||||||
|
:Parameters:
|
||||||
|
component : byte string
|
||||||
|
The next associated data component. It must not be empty.
|
||||||
|
"""
|
||||||
|
|
||||||
|
if self.update not in self._next:
|
||||||
|
raise TypeError("update() can only be called"
|
||||||
|
" immediately after initialization")
|
||||||
|
|
||||||
|
self._next = [self.update, self.encrypt, self.decrypt,
|
||||||
|
self.digest, self.verify]
|
||||||
|
|
||||||
|
return self._kdf.update(component)
|
||||||
|
|
||||||
|
def encrypt(self, plaintext):
|
||||||
|
"""Encrypt data with the key and the parameters set at initialization.
|
||||||
|
|
||||||
|
A cipher object is stateful: once you have encrypted a message
|
||||||
|
you cannot encrypt (or decrypt) another message using the same
|
||||||
|
object.
|
||||||
|
|
||||||
|
This method can be called only **once**.
|
||||||
|
|
||||||
|
You cannot reuse an object for encrypting
|
||||||
|
or decrypting other data with the same key.
|
||||||
|
|
||||||
|
This function does not add any padding to the plaintext.
|
||||||
|
|
||||||
|
:Parameters:
|
||||||
|
plaintext : byte string
|
||||||
|
The piece of data to encrypt.
|
||||||
|
It can be of any length, but it cannot be empty.
|
||||||
|
:Return:
|
||||||
|
the encrypted data, as a byte string.
|
||||||
|
It is as long as *plaintext*.
|
||||||
|
"""
|
||||||
|
|
||||||
|
if self.encrypt not in self._next:
|
||||||
|
raise TypeError("encrypt() can only be called after"
|
||||||
|
" initialization or an update()")
|
||||||
|
|
||||||
|
self._next = [self.digest]
|
||||||
|
|
||||||
|
if self._nonce:
|
||||||
|
self._kdf.update(self.nonce)
|
||||||
|
self._kdf.update(plaintext)
|
||||||
|
|
||||||
|
self._mac_tag = self._kdf.derive()
|
||||||
|
cipher = self._create_ctr_cipher(self._mac_tag)
|
||||||
|
|
||||||
|
return cipher.encrypt(plaintext)
|
||||||
|
|
||||||
|
def decrypt(self, ciphertext):
|
||||||
|
"""Decrypt data with the key and the parameters set at initialization.
|
||||||
|
|
||||||
|
For SIV, decryption and verification must take place at the same
|
||||||
|
point. This method shall not be used.
|
||||||
|
|
||||||
|
Use `decrypt_and_verify` instead.
|
||||||
|
"""
|
||||||
|
|
||||||
|
raise TypeError("decrypt() not allowed for SIV mode."
|
||||||
|
" Use decrypt_and_verify() instead.")
|
||||||
|
|
||||||
|
def digest(self):
|
||||||
|
"""Compute the *binary* MAC tag.
|
||||||
|
|
||||||
|
The caller invokes this function at the very end.
|
||||||
|
|
||||||
|
This method returns the MAC that shall be sent to the receiver,
|
||||||
|
together with the ciphertext.
|
||||||
|
|
||||||
|
:Return: the MAC, as a byte string.
|
||||||
|
"""
|
||||||
|
|
||||||
|
if self.digest not in self._next:
|
||||||
|
raise TypeError("digest() cannot be called when decrypting"
|
||||||
|
" or validating a message")
|
||||||
|
self._next = [self.digest]
|
||||||
|
if self._mac_tag is None:
|
||||||
|
self._mac_tag = self._kdf.derive()
|
||||||
|
return self._mac_tag
|
||||||
|
|
||||||
|
def hexdigest(self):
|
||||||
|
"""Compute the *printable* MAC tag.
|
||||||
|
|
||||||
|
This method is like `digest`.
|
||||||
|
|
||||||
|
:Return: the MAC, as a hexadecimal string.
|
||||||
|
"""
|
||||||
|
return "".join(["%02x" % bord(x) for x in self.digest()])
|
||||||
|
|
||||||
|
def verify(self, received_mac_tag):
|
||||||
|
"""Validate the *binary* MAC tag.
|
||||||
|
|
||||||
|
The caller invokes this function at the very end.
|
||||||
|
|
||||||
|
This method checks if the decrypted message is indeed valid
|
||||||
|
(that is, if the key is correct) and it has not been
|
||||||
|
tampered with while in transit.
|
||||||
|
|
||||||
|
:Parameters:
|
||||||
|
received_mac_tag : byte string
|
||||||
|
This is the *binary* MAC, as received from the sender.
|
||||||
|
:Raises ValueError:
|
||||||
|
if the MAC does not match. The message has been tampered with
|
||||||
|
or the key is incorrect.
|
||||||
|
"""
|
||||||
|
|
||||||
|
if self.verify not in self._next:
|
||||||
|
raise TypeError("verify() cannot be called"
|
||||||
|
" when encrypting a message")
|
||||||
|
self._next = [self.verify]
|
||||||
|
|
||||||
|
if self._mac_tag is None:
|
||||||
|
self._mac_tag = self._kdf.derive()
|
||||||
|
|
||||||
|
secret = get_random_bytes(16)
|
||||||
|
|
||||||
|
mac1 = BLAKE2s.new(digest_bits=160, key=secret, data=self._mac_tag)
|
||||||
|
mac2 = BLAKE2s.new(digest_bits=160, key=secret, data=received_mac_tag)
|
||||||
|
|
||||||
|
if mac1.digest() != mac2.digest():
|
||||||
|
raise ValueError("MAC check failed")
|
||||||
|
|
||||||
|
def hexverify(self, hex_mac_tag):
|
||||||
|
"""Validate the *printable* MAC tag.
|
||||||
|
|
||||||
|
This method is like `verify`.
|
||||||
|
|
||||||
|
:Parameters:
|
||||||
|
hex_mac_tag : string
|
||||||
|
This is the *printable* MAC, as received from the sender.
|
||||||
|
:Raises ValueError:
|
||||||
|
if the MAC does not match. The message has been tampered with
|
||||||
|
or the key is incorrect.
|
||||||
|
"""
|
||||||
|
|
||||||
|
self.verify(unhexlify(hex_mac_tag))
|
||||||
|
|
||||||
|
def encrypt_and_digest(self, plaintext):
|
||||||
|
"""Perform encrypt() and digest() in one step.
|
||||||
|
|
||||||
|
:Parameters:
|
||||||
|
plaintext : byte string
|
||||||
|
The piece of data to encrypt.
|
||||||
|
:Return:
|
||||||
|
a tuple with two byte strings:
|
||||||
|
|
||||||
|
- the encrypted data
|
||||||
|
- the MAC
|
||||||
|
"""
|
||||||
|
|
||||||
|
return self.encrypt(plaintext), self.digest()
|
||||||
|
|
||||||
|
def decrypt_and_verify(self, ciphertext, mac_tag):
|
||||||
|
"""Perform decryption and verification in one step.
|
||||||
|
|
||||||
|
A cipher object is stateful: once you have decrypted a message
|
||||||
|
you cannot decrypt (or encrypt) another message with the same
|
||||||
|
object.
|
||||||
|
|
||||||
|
You cannot reuse an object for encrypting
|
||||||
|
or decrypting other data with the same key.
|
||||||
|
|
||||||
|
This function does not remove any padding from the plaintext.
|
||||||
|
|
||||||
|
:Parameters:
|
||||||
|
ciphertext : byte string
|
||||||
|
The piece of data to decrypt.
|
||||||
|
It can be of any length.
|
||||||
|
mac_tag : byte string
|
||||||
|
This is the *binary* MAC, as received from the sender.
|
||||||
|
|
||||||
|
:Return: the decrypted data (byte string).
|
||||||
|
:Raises ValueError:
|
||||||
|
if the MAC does not match. The message has been tampered with
|
||||||
|
or the key is incorrect.
|
||||||
|
"""
|
||||||
|
|
||||||
|
if self.decrypt not in self._next:
|
||||||
|
raise TypeError("decrypt() can only be called"
|
||||||
|
" after initialization or an update()")
|
||||||
|
self._next = [self.verify]
|
||||||
|
|
||||||
|
# Take the MAC and start the cipher for decryption
|
||||||
|
self._cipher = self._create_ctr_cipher(mac_tag)
|
||||||
|
|
||||||
|
plaintext = self._cipher.decrypt(ciphertext)
|
||||||
|
|
||||||
|
if self._nonce:
|
||||||
|
self._kdf.update(self.nonce)
|
||||||
|
if plaintext:
|
||||||
|
self._kdf.update(plaintext)
|
||||||
|
|
||||||
|
self.verify(mac_tag)
|
||||||
|
return plaintext
|
||||||
|
|
||||||
|
|
||||||
|
def _create_siv_cipher(factory, **kwargs):
|
||||||
|
"""Create a new block cipher, configured in
|
||||||
|
Synthetic Initializaton Vector (SIV) mode.
|
||||||
|
|
||||||
|
:Parameters:
|
||||||
|
|
||||||
|
factory : object
|
||||||
|
A symmetric cipher module from `Crypto.Cipher`
|
||||||
|
(like `Crypto.Cipher.AES`).
|
||||||
|
|
||||||
|
:Keywords:
|
||||||
|
|
||||||
|
key : byte string
|
||||||
|
The secret key to use in the symmetric cipher.
|
||||||
|
It must be 32, 48 or 64 bytes long.
|
||||||
|
If AES is the chosen cipher, the variants *AES-128*,
|
||||||
|
*AES-192* and or *AES-256* will be used internally.
|
||||||
|
|
||||||
|
nonce : byte string
|
||||||
|
For deterministic encryption, it is not present.
|
||||||
|
|
||||||
|
Otherwise, it is a value that must never be reused
|
||||||
|
for encrypting message under this key.
|
||||||
|
|
||||||
|
There are no restrictions on its length,
|
||||||
|
but it is recommended to use at least 16 bytes.
|
||||||
|
"""
|
||||||
|
|
||||||
|
try:
|
||||||
|
key = kwargs.pop("key")
|
||||||
|
except KeyError as e:
|
||||||
|
raise TypeError("Missing parameter: " + str(e))
|
||||||
|
|
||||||
|
nonce = kwargs.pop("nonce", None)
|
||||||
|
|
||||||
|
return SivMode(factory, key, nonce, kwargs)
|
BIN
venv/Lib/site-packages/Crypto/Cipher/_raw_aes.cp36-win32.pyd
Normal file
BIN
venv/Lib/site-packages/Crypto/Cipher/_raw_aes.cp36-win32.pyd
Normal file
Binary file not shown.
BIN
venv/Lib/site-packages/Crypto/Cipher/_raw_aesni.cp36-win32.pyd
Normal file
BIN
venv/Lib/site-packages/Crypto/Cipher/_raw_aesni.cp36-win32.pyd
Normal file
Binary file not shown.
BIN
venv/Lib/site-packages/Crypto/Cipher/_raw_arc2.cp36-win32.pyd
Normal file
BIN
venv/Lib/site-packages/Crypto/Cipher/_raw_arc2.cp36-win32.pyd
Normal file
Binary file not shown.
Binary file not shown.
BIN
venv/Lib/site-packages/Crypto/Cipher/_raw_cast.cp36-win32.pyd
Normal file
BIN
venv/Lib/site-packages/Crypto/Cipher/_raw_cast.cp36-win32.pyd
Normal file
Binary file not shown.
BIN
venv/Lib/site-packages/Crypto/Cipher/_raw_cbc.cp36-win32.pyd
Normal file
BIN
venv/Lib/site-packages/Crypto/Cipher/_raw_cbc.cp36-win32.pyd
Normal file
Binary file not shown.
BIN
venv/Lib/site-packages/Crypto/Cipher/_raw_cfb.cp36-win32.pyd
Normal file
BIN
venv/Lib/site-packages/Crypto/Cipher/_raw_cfb.cp36-win32.pyd
Normal file
Binary file not shown.
BIN
venv/Lib/site-packages/Crypto/Cipher/_raw_ctr.cp36-win32.pyd
Normal file
BIN
venv/Lib/site-packages/Crypto/Cipher/_raw_ctr.cp36-win32.pyd
Normal file
Binary file not shown.
BIN
venv/Lib/site-packages/Crypto/Cipher/_raw_des.cp36-win32.pyd
Normal file
BIN
venv/Lib/site-packages/Crypto/Cipher/_raw_des.cp36-win32.pyd
Normal file
Binary file not shown.
BIN
venv/Lib/site-packages/Crypto/Cipher/_raw_des3.cp36-win32.pyd
Normal file
BIN
venv/Lib/site-packages/Crypto/Cipher/_raw_des3.cp36-win32.pyd
Normal file
Binary file not shown.
BIN
venv/Lib/site-packages/Crypto/Cipher/_raw_ecb.cp36-win32.pyd
Normal file
BIN
venv/Lib/site-packages/Crypto/Cipher/_raw_ecb.cp36-win32.pyd
Normal file
Binary file not shown.
BIN
venv/Lib/site-packages/Crypto/Cipher/_raw_ocb.cp36-win32.pyd
Normal file
BIN
venv/Lib/site-packages/Crypto/Cipher/_raw_ocb.cp36-win32.pyd
Normal file
Binary file not shown.
BIN
venv/Lib/site-packages/Crypto/Cipher/_raw_ofb.cp36-win32.pyd
Normal file
BIN
venv/Lib/site-packages/Crypto/Cipher/_raw_ofb.cp36-win32.pyd
Normal file
Binary file not shown.
273
venv/Lib/site-packages/Crypto/Hash/BLAKE2b.py
Normal file
273
venv/Lib/site-packages/Crypto/Hash/BLAKE2b.py
Normal file
|
@ -0,0 +1,273 @@
|
||||||
|
# ===================================================================
|
||||||
|
#
|
||||||
|
# Copyright (c) 2014, Legrandin <helderijs@gmail.com>
|
||||||
|
# All rights reserved.
|
||||||
|
#
|
||||||
|
# Redistribution and use in source and binary forms, with or without
|
||||||
|
# modification, are permitted provided that the following conditions
|
||||||
|
# are met:
|
||||||
|
#
|
||||||
|
# 1. Redistributions of source code must retain the above copyright
|
||||||
|
# notice, this list of conditions and the following disclaimer.
|
||||||
|
# 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
# notice, this list of conditions and the following disclaimer in
|
||||||
|
# the documentation and/or other materials provided with the
|
||||||
|
# distribution.
|
||||||
|
#
|
||||||
|
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||||
|
# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||||
|
# COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||||
|
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||||
|
# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||||
|
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||||
|
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||||
|
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
|
# POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
# ===================================================================
|
||||||
|
|
||||||
|
"""BLAKE2b cryptographic hash algorithm.
|
||||||
|
|
||||||
|
`BLAKE2b`_ is an optimized variant of BLAKE, one of the SHA-3 candidates that
|
||||||
|
made it to the final round of the NIST hash competition.
|
||||||
|
|
||||||
|
The algorithm uses 64 bit words, and it therefore works best on
|
||||||
|
64-bit platforms. The digest size ranges from 8 to 512 bits.
|
||||||
|
|
||||||
|
>>> from Crypto.Hash import BLAKE2b
|
||||||
|
>>>
|
||||||
|
>>> h_obj = BLAKE2b.new(digest_bits=512)
|
||||||
|
>>> h_obj.update(b'Some data')
|
||||||
|
>>> print h_obj.hexdigest()
|
||||||
|
|
||||||
|
Optionally, BLAKE2b can work as a cryptographic MAC when initialized
|
||||||
|
with a secret key.
|
||||||
|
|
||||||
|
>>> from Crypto.Hash import BLAKE2b
|
||||||
|
>>>
|
||||||
|
>>> mac = BLAKE2b.new(digest_bits=256, key=b'secret')
|
||||||
|
>>> mac.update(b'Some data')
|
||||||
|
>>> print mac.hexdigest()
|
||||||
|
|
||||||
|
:undocumented: __package__
|
||||||
|
|
||||||
|
.. _BLAKE2b: https://blake2.net/
|
||||||
|
"""
|
||||||
|
|
||||||
|
from binascii import unhexlify
|
||||||
|
|
||||||
|
from Crypto.Util.py3compat import b, bord, tobytes
|
||||||
|
|
||||||
|
from Crypto.Random import get_random_bytes
|
||||||
|
from Crypto.Util._raw_api import (load_pycryptodome_raw_lib,
|
||||||
|
VoidPointer, SmartPointer,
|
||||||
|
create_string_buffer,
|
||||||
|
get_raw_buffer, c_size_t,
|
||||||
|
expect_byte_string)
|
||||||
|
|
||||||
|
_raw_blake2b_lib = load_pycryptodome_raw_lib("Crypto.Hash._BLAKE2b",
|
||||||
|
"""
|
||||||
|
int blake2b_init(void **state,
|
||||||
|
const uint8_t *key,
|
||||||
|
size_t key_size,
|
||||||
|
size_t digest_size);
|
||||||
|
int blake2b_destroy(void *state);
|
||||||
|
int blake2b_update(void *state,
|
||||||
|
const uint8_t *buf,
|
||||||
|
size_t len);
|
||||||
|
int blake2b_digest(const void *state,
|
||||||
|
uint8_t digest[64]);
|
||||||
|
int blake2b_copy(const void *src, void *dst);
|
||||||
|
""")
|
||||||
|
|
||||||
|
|
||||||
|
class BLAKE2b_Hash(object):
|
||||||
|
"""Class that implements a BLAKE2b hash
|
||||||
|
"""
|
||||||
|
|
||||||
|
#: The internal block size of the hash algorithm in bytes.
|
||||||
|
block_size = 64
|
||||||
|
|
||||||
|
def __init__(self, data, key, digest_bytes, update_after_digest):
|
||||||
|
"""
|
||||||
|
Initialize a BLAKE2b hash object.
|
||||||
|
"""
|
||||||
|
|
||||||
|
#: The size of the resulting hash in bytes.
|
||||||
|
self.digest_size = digest_bytes
|
||||||
|
|
||||||
|
self._update_after_digest = update_after_digest
|
||||||
|
self._digest_done = False
|
||||||
|
|
||||||
|
# See https://tools.ietf.org/html/draft-saarinen-blake2-02
|
||||||
|
if digest_bytes in (20, 32, 48, 64) and not key:
|
||||||
|
self.oid = "1.3.6.1.4.1.1722.12.2.1." + str(digest_bytes)
|
||||||
|
|
||||||
|
expect_byte_string(key)
|
||||||
|
|
||||||
|
state = VoidPointer()
|
||||||
|
result = _raw_blake2b_lib.blake2b_init(state.address_of(),
|
||||||
|
key,
|
||||||
|
c_size_t(len(key)),
|
||||||
|
c_size_t(digest_bytes)
|
||||||
|
)
|
||||||
|
if result:
|
||||||
|
raise ValueError("Error %d while instantiating BLAKE2b" % result)
|
||||||
|
self._state = SmartPointer(state.get(),
|
||||||
|
_raw_blake2b_lib.blake2b_destroy)
|
||||||
|
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.
|
||||||
|
"""
|
||||||
|
|
||||||
|
if self._digest_done and not self._update_after_digest:
|
||||||
|
raise TypeError("You can only call 'digest' or 'hexdigest' on this object")
|
||||||
|
|
||||||
|
expect_byte_string(data)
|
||||||
|
result = _raw_blake2b_lib.blake2b_update(self._state.get(),
|
||||||
|
data,
|
||||||
|
c_size_t(len(data)))
|
||||||
|
if result:
|
||||||
|
raise ValueError("Error %d while hashing BLAKE2b data" % result)
|
||||||
|
return self
|
||||||
|
|
||||||
|
def digest(self):
|
||||||
|
"""Return the **binary** (non-printable) digest of the message that
|
||||||
|
has been hashed so far.
|
||||||
|
|
||||||
|
You cannot update the hash anymore after the first call to ``digest``
|
||||||
|
(or ``hexdigest``).
|
||||||
|
|
||||||
|
:Return: A byte string of `digest_size` bytes. It may contain non-ASCII
|
||||||
|
characters, including null bytes.
|
||||||
|
"""
|
||||||
|
|
||||||
|
bfr = create_string_buffer(64)
|
||||||
|
result = _raw_blake2b_lib.blake2b_digest(self._state.get(),
|
||||||
|
bfr)
|
||||||
|
if result:
|
||||||
|
raise ValueError("Error %d while creating BLAKE2b digest" % result)
|
||||||
|
|
||||||
|
self._digest_done = True
|
||||||
|
|
||||||
|
return get_raw_buffer(bfr)[:self.digest_size]
|
||||||
|
|
||||||
|
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 "".join(["%02x" % bord(x) for x in tuple(self.digest())])
|
||||||
|
|
||||||
|
def verify(self, mac_tag):
|
||||||
|
"""Verify that a given **binary** MAC (computed by another party)
|
||||||
|
is valid.
|
||||||
|
|
||||||
|
:Parameters:
|
||||||
|
mac_tag : byte string
|
||||||
|
The expected MAC of the message.
|
||||||
|
:Raises ValueError:
|
||||||
|
if the MAC does not match. It means that the message
|
||||||
|
has been tampered with or that the MAC key is incorrect.
|
||||||
|
"""
|
||||||
|
|
||||||
|
secret = get_random_bytes(16)
|
||||||
|
|
||||||
|
mac1 = new(digest_bits=160, key=secret, data=mac_tag)
|
||||||
|
mac2 = new(digest_bits=160, key=secret, data=self.digest())
|
||||||
|
|
||||||
|
if mac1.digest() != mac2.digest():
|
||||||
|
raise ValueError("MAC check failed")
|
||||||
|
|
||||||
|
def hexverify(self, hex_mac_tag):
|
||||||
|
"""Verify that a given **printable** MAC (computed by another party)
|
||||||
|
is valid.
|
||||||
|
|
||||||
|
:Parameters:
|
||||||
|
hex_mac_tag : string
|
||||||
|
The expected MAC of the message, as a hexadecimal string.
|
||||||
|
:Raises ValueError:
|
||||||
|
if the MAC does not match. It means that the message
|
||||||
|
has been tampered with or that the MAC key is incorrect.
|
||||||
|
"""
|
||||||
|
|
||||||
|
self.verify(unhexlify(tobytes(hex_mac_tag)))
|
||||||
|
|
||||||
|
def new(self, **kwargs):
|
||||||
|
"""Return a new instance of a BLAKE2b hash object."""
|
||||||
|
|
||||||
|
if "digest_bytes" not in kwargs and "digest_bits" not in kwargs:
|
||||||
|
kwargs["digest_bytes"] = self.digest_size
|
||||||
|
|
||||||
|
return new(**kwargs)
|
||||||
|
|
||||||
|
|
||||||
|
def new(**kwargs):
|
||||||
|
"""Return a new instance of a BLAKE2b hash object.
|
||||||
|
|
||||||
|
:Keywords:
|
||||||
|
data : byte string
|
||||||
|
The very first chunk of the message to hash.
|
||||||
|
It is equivalent to an early call to `BLAKE2b_Hash.update()`.
|
||||||
|
digest_bytes : integer
|
||||||
|
The size of the digest, in bytes (1 to 64).
|
||||||
|
digest_bits : integer
|
||||||
|
The size of the digest, in bits (8 to 512, in steps of 8).
|
||||||
|
key : byte string
|
||||||
|
The key to use to compute the MAC (1 to 64 bytes).
|
||||||
|
If not specified, no key will be used.
|
||||||
|
update_after_digest : boolean
|
||||||
|
Optional. By default, a hash object cannot be updated anymore after
|
||||||
|
the digest is computed. When this flag is ``True``, such check
|
||||||
|
is no longer enforced.
|
||||||
|
:Return: A `BLAKE2b_Hash` object
|
||||||
|
"""
|
||||||
|
|
||||||
|
data = kwargs.pop("data", None)
|
||||||
|
update_after_digest = kwargs.pop("update_after_digest", False)
|
||||||
|
|
||||||
|
digest_bytes = kwargs.pop("digest_bytes", None)
|
||||||
|
digest_bits = kwargs.pop("digest_bits", None)
|
||||||
|
if None not in (digest_bytes, digest_bits):
|
||||||
|
raise TypeError("Only one digest parameter must be provided")
|
||||||
|
if (None, None) == (digest_bytes, digest_bits):
|
||||||
|
raise TypeError("Digest size (bits, bytes) not provided")
|
||||||
|
if digest_bytes is not None:
|
||||||
|
if not (1 <= digest_bytes <= 64):
|
||||||
|
raise ValueError("'digest_bytes' not in range 1..64")
|
||||||
|
else:
|
||||||
|
if not (8 <= digest_bits <= 512) or (digest_bits % 8):
|
||||||
|
raise ValueError("'digest_bytes' not in range 8..512, "
|
||||||
|
"with steps of 8")
|
||||||
|
digest_bytes = digest_bits // 8
|
||||||
|
|
||||||
|
key = kwargs.pop("key", b(""))
|
||||||
|
if len(key) > 64:
|
||||||
|
raise ValueError("BLAKE2s key cannot exceed 64 bytes")
|
||||||
|
|
||||||
|
if kwargs:
|
||||||
|
raise TypeError("Unknown parameters: " + str(kwargs))
|
||||||
|
|
||||||
|
return BLAKE2b_Hash(data, key, digest_bytes, update_after_digest)
|
273
venv/Lib/site-packages/Crypto/Hash/BLAKE2s.py
Normal file
273
venv/Lib/site-packages/Crypto/Hash/BLAKE2s.py
Normal file
|
@ -0,0 +1,273 @@
|
||||||
|
# ===================================================================
|
||||||
|
#
|
||||||
|
# Copyright (c) 2014, Legrandin <helderijs@gmail.com>
|
||||||
|
# All rights reserved.
|
||||||
|
#
|
||||||
|
# Redistribution and use in source and binary forms, with or without
|
||||||
|
# modification, are permitted provided that the following conditions
|
||||||
|
# are met:
|
||||||
|
#
|
||||||
|
# 1. Redistributions of source code must retain the above copyright
|
||||||
|
# notice, this list of conditions and the following disclaimer.
|
||||||
|
# 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
# notice, this list of conditions and the following disclaimer in
|
||||||
|
# the documentation and/or other materials provided with the
|
||||||
|
# distribution.
|
||||||
|
#
|
||||||
|
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||||
|
# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||||
|
# COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||||
|
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||||
|
# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||||
|
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||||
|
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||||
|
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
|
# POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
# ===================================================================
|
||||||
|
|
||||||
|
"""BLAKE2s cryptographic hash algorithm.
|
||||||
|
|
||||||
|
`BLAKE2s`_ is an optimized variant of BLAKE, one of the SHA-3 candidates that
|
||||||
|
made it to the final round of the NIST hash competition.
|
||||||
|
|
||||||
|
The algorithm uses 32 bit words, and it therefore works best
|
||||||
|
on 32-bit platforms. The digest size ranges from 8 to 256 bits.
|
||||||
|
|
||||||
|
>>> from Crypto.Hash import BLAKE2s
|
||||||
|
>>>
|
||||||
|
>>> h_obj = BLAKE2s.new(digest_bits=256)
|
||||||
|
>>> h_obj.update(b'Some data')
|
||||||
|
>>> print h_obj.hexdigest()
|
||||||
|
|
||||||
|
Optionally, BLAKE2s can work as a cryptographic MAC when initialized
|
||||||
|
with a secret key.
|
||||||
|
|
||||||
|
>>> from Crypto.Hash import BLAKE2s
|
||||||
|
>>>
|
||||||
|
>>> mac = BLAKE2s.new(digest_bits=128, key=b'secret')
|
||||||
|
>>> mac.update(b'Some data')
|
||||||
|
>>> print mac.hexdigest()
|
||||||
|
|
||||||
|
:undocumented: __package__
|
||||||
|
|
||||||
|
.. _BLAKE2s: https://blake2.net/
|
||||||
|
"""
|
||||||
|
|
||||||
|
from binascii import unhexlify
|
||||||
|
|
||||||
|
from Crypto.Util.py3compat import b, bord, tobytes
|
||||||
|
|
||||||
|
from Crypto.Random import get_random_bytes
|
||||||
|
from Crypto.Util._raw_api import (load_pycryptodome_raw_lib,
|
||||||
|
VoidPointer, SmartPointer,
|
||||||
|
create_string_buffer,
|
||||||
|
get_raw_buffer, c_size_t,
|
||||||
|
expect_byte_string)
|
||||||
|
|
||||||
|
_raw_blake2s_lib = load_pycryptodome_raw_lib("Crypto.Hash._BLAKE2s",
|
||||||
|
"""
|
||||||
|
int blake2s_init(void **state,
|
||||||
|
const uint8_t *key,
|
||||||
|
size_t key_size,
|
||||||
|
size_t digest_size);
|
||||||
|
int blake2s_destroy(void *state);
|
||||||
|
int blake2s_update(void *state,
|
||||||
|
const uint8_t *buf,
|
||||||
|
size_t len);
|
||||||
|
int blake2s_digest(const void *state,
|
||||||
|
uint8_t digest[32]);
|
||||||
|
int blake2s_copy(const void *src, void *dst);
|
||||||
|
""")
|
||||||
|
|
||||||
|
|
||||||
|
class BLAKE2s_Hash(object):
|
||||||
|
"""Class that implements a BLAKE2s hash
|
||||||
|
"""
|
||||||
|
|
||||||
|
#: The internal block size of the hash algorithm in bytes.
|
||||||
|
block_size = 32
|
||||||
|
|
||||||
|
def __init__(self, data, key, digest_bytes, update_after_digest):
|
||||||
|
"""
|
||||||
|
Initialize a BLAKE2s hash object.
|
||||||
|
"""
|
||||||
|
|
||||||
|
#: The size of the resulting hash in bytes.
|
||||||
|
self.digest_size = digest_bytes
|
||||||
|
|
||||||
|
self._update_after_digest = update_after_digest
|
||||||
|
self._digest_done = False
|
||||||
|
|
||||||
|
# See https://tools.ietf.org/html/draft-saarinen-blake2-02
|
||||||
|
if digest_bytes in (16, 20, 28, 32) and not key:
|
||||||
|
self.oid = "1.3.6.1.4.1.1722.12.2.2." + str(digest_bytes)
|
||||||
|
|
||||||
|
expect_byte_string(key)
|
||||||
|
|
||||||
|
state = VoidPointer()
|
||||||
|
result = _raw_blake2s_lib.blake2s_init(state.address_of(),
|
||||||
|
key,
|
||||||
|
c_size_t(len(key)),
|
||||||
|
c_size_t(digest_bytes)
|
||||||
|
)
|
||||||
|
if result:
|
||||||
|
raise ValueError("Error %d while instantiating BLAKE2s" % result)
|
||||||
|
self._state = SmartPointer(state.get(),
|
||||||
|
_raw_blake2s_lib.blake2s_destroy)
|
||||||
|
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.
|
||||||
|
"""
|
||||||
|
|
||||||
|
if self._digest_done and not self._update_after_digest:
|
||||||
|
raise TypeError("You can only call 'digest' or 'hexdigest' on this object")
|
||||||
|
|
||||||
|
expect_byte_string(data)
|
||||||
|
result = _raw_blake2s_lib.blake2s_update(self._state.get(),
|
||||||
|
data,
|
||||||
|
c_size_t(len(data)))
|
||||||
|
if result:
|
||||||
|
raise ValueError("Error %d while hashing BLAKE2s data" % result)
|
||||||
|
return self
|
||||||
|
|
||||||
|
def digest(self):
|
||||||
|
"""Return the **binary** (non-printable) digest of the message that
|
||||||
|
has been hashed so far.
|
||||||
|
|
||||||
|
You cannot update the hash anymore after the first call to ``digest``
|
||||||
|
(or ``hexdigest``).
|
||||||
|
|
||||||
|
:Return: A byte string of `digest_size` bytes. It may contain non-ASCII
|
||||||
|
characters, including null bytes.
|
||||||
|
"""
|
||||||
|
|
||||||
|
bfr = create_string_buffer(32)
|
||||||
|
result = _raw_blake2s_lib.blake2s_digest(self._state.get(),
|
||||||
|
bfr)
|
||||||
|
if result:
|
||||||
|
raise ValueError("Error %d while creating BLAKE2s digest" % result)
|
||||||
|
|
||||||
|
self._digest_done = True
|
||||||
|
|
||||||
|
return get_raw_buffer(bfr)[:self.digest_size]
|
||||||
|
|
||||||
|
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 "".join(["%02x" % bord(x) for x in tuple(self.digest())])
|
||||||
|
|
||||||
|
def verify(self, mac_tag):
|
||||||
|
"""Verify that a given **binary** MAC (computed by another party)
|
||||||
|
is valid.
|
||||||
|
|
||||||
|
:Parameters:
|
||||||
|
mac_tag : byte string
|
||||||
|
The expected MAC of the message.
|
||||||
|
:Raises ValueError:
|
||||||
|
if the MAC does not match. It means that the message
|
||||||
|
has been tampered with or that the MAC key is incorrect.
|
||||||
|
"""
|
||||||
|
|
||||||
|
secret = get_random_bytes(16)
|
||||||
|
|
||||||
|
mac1 = new(digest_bits=160, key=secret, data=mac_tag)
|
||||||
|
mac2 = new(digest_bits=160, key=secret, data=self.digest())
|
||||||
|
|
||||||
|
if mac1.digest() != mac2.digest():
|
||||||
|
raise ValueError("MAC check failed")
|
||||||
|
|
||||||
|
def hexverify(self, hex_mac_tag):
|
||||||
|
"""Verify that a given **printable** MAC (computed by another party)
|
||||||
|
is valid.
|
||||||
|
|
||||||
|
:Parameters:
|
||||||
|
hex_mac_tag : string
|
||||||
|
The expected MAC of the message, as a hexadecimal string.
|
||||||
|
:Raises ValueError:
|
||||||
|
if the MAC does not match. It means that the message
|
||||||
|
has been tampered with or that the MAC key is incorrect.
|
||||||
|
"""
|
||||||
|
|
||||||
|
self.verify(unhexlify(tobytes(hex_mac_tag)))
|
||||||
|
|
||||||
|
def new(self, **kwargs):
|
||||||
|
"""Return a new instance of a BLAKE2s hash object."""
|
||||||
|
|
||||||
|
if "digest_bytes" not in kwargs and "digest_bits" not in kwargs:
|
||||||
|
kwargs["digest_bytes"] = self.digest_size
|
||||||
|
|
||||||
|
return new(**kwargs)
|
||||||
|
|
||||||
|
|
||||||
|
def new(**kwargs):
|
||||||
|
"""Return a new instance of a BLAKE2s hash object.
|
||||||
|
|
||||||
|
:Keywords:
|
||||||
|
data : byte string
|
||||||
|
The very first chunk of the message to hash.
|
||||||
|
It is equivalent to an early call to `BLAKE2s_Hash.update()`.
|
||||||
|
digest_bytes : integer
|
||||||
|
The size of the digest, in bytes (1 to 32).
|
||||||
|
digest_bits : integer
|
||||||
|
The size of the digest, in bits (8 to 256, in steps of 8).
|
||||||
|
key : byte string
|
||||||
|
The key to use to compute the MAC (1 to 32 bytes).
|
||||||
|
If not specified, no key will be used.
|
||||||
|
update_after_digest : boolean
|
||||||
|
Optional. By default, a hash object cannot be updated anymore after
|
||||||
|
the digest is computed. When this flag is ``True``, such check
|
||||||
|
is no longer enforced.
|
||||||
|
:Return: A `BLAKE2s_Hash` object
|
||||||
|
"""
|
||||||
|
|
||||||
|
data = kwargs.pop("data", None)
|
||||||
|
update_after_digest = kwargs.pop("update_after_digest", False)
|
||||||
|
|
||||||
|
digest_bytes = kwargs.pop("digest_bytes", None)
|
||||||
|
digest_bits = kwargs.pop("digest_bits", None)
|
||||||
|
if None not in (digest_bytes, digest_bits):
|
||||||
|
raise TypeError("Only one digest parameter must be provided")
|
||||||
|
if (None, None) == (digest_bytes, digest_bits):
|
||||||
|
raise TypeError("Digest size (bits, bytes) not provided")
|
||||||
|
if digest_bytes is not None:
|
||||||
|
if not (1 <= digest_bytes <= 32):
|
||||||
|
raise ValueError("'digest_bytes' not in range 1..32")
|
||||||
|
else:
|
||||||
|
if not (8 <= digest_bits <= 256) or (digest_bits % 8):
|
||||||
|
raise ValueError("'digest_bytes' not in range 8..256, "
|
||||||
|
"with steps of 8")
|
||||||
|
digest_bytes = digest_bits // 8
|
||||||
|
|
||||||
|
key = kwargs.pop("key", b(""))
|
||||||
|
if len(key) > 32:
|
||||||
|
raise ValueError("BLAKE2s key cannot exceed 32 bytes")
|
||||||
|
|
||||||
|
if kwargs:
|
||||||
|
raise TypeError("Unknown parameters: " + str(kwargs))
|
||||||
|
|
||||||
|
return BLAKE2s_Hash(data, key, digest_bytes, update_after_digest)
|
352
venv/Lib/site-packages/Crypto/Hash/CMAC.py
Normal file
352
venv/Lib/site-packages/Crypto/Hash/CMAC.py
Normal file
|
@ -0,0 +1,352 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
#
|
||||||
|
# Hash/CMAC.py - Implements the CMAC algorithm
|
||||||
|
#
|
||||||
|
# ===================================================================
|
||||||
|
# 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.
|
||||||
|
# ===================================================================
|
||||||
|
|
||||||
|
"""CMAC (Cipher-based Message Authentication Code) algorithm
|
||||||
|
|
||||||
|
CMAC is a MAC defined in `NIST SP 800-38B`_ and in RFC4493_ (for AES only)
|
||||||
|
and constructed using a block cipher. It was originally known as `OMAC1`_.
|
||||||
|
|
||||||
|
The algorithm is sometimes named *X-CMAC* where *X* is the name
|
||||||
|
of the cipher (e.g. AES-CMAC).
|
||||||
|
|
||||||
|
This is an example showing how to *create* an AES-CMAC:
|
||||||
|
|
||||||
|
>>> from Crypto.Hash import CMAC
|
||||||
|
>>> from Crypto.Cipher import AES
|
||||||
|
>>>
|
||||||
|
>>> secret = b'Sixteen byte key'
|
||||||
|
>>> cobj = CMAC.new(secret, ciphermod=AES)
|
||||||
|
>>> cobj.update(b'Hello')
|
||||||
|
>>> print cobj.hexdigest()
|
||||||
|
|
||||||
|
And this is an example showing how to *check* an AES-CMAC:
|
||||||
|
|
||||||
|
>>> from Crypto.Hash import CMAC
|
||||||
|
>>> from Crypto.Cipher import AES
|
||||||
|
>>>
|
||||||
|
>>> # We have received a message 'msg' together
|
||||||
|
>>> # with its MAC 'mac'
|
||||||
|
>>>
|
||||||
|
>>> secret = b'Sixteen byte key'
|
||||||
|
>>> cobj = CMAC.new(secret, ciphermod=AES)
|
||||||
|
>>> cobj.update(msg)
|
||||||
|
>>> try:
|
||||||
|
>>> cobj.verify(mac)
|
||||||
|
>>> print "The message '%s' is authentic" % msg
|
||||||
|
>>> except ValueError:
|
||||||
|
>>> print "The message or the key is wrong"
|
||||||
|
|
||||||
|
A cipher block size of 128 bits (like for AES) guarantees that the risk
|
||||||
|
of MAC collisions remains negligeable even when the same CMAC key is
|
||||||
|
used to authenticate a large amount of data (2^22 Gbytes).
|
||||||
|
|
||||||
|
This implementation allows also usage of ciphers with a 64 bits block size
|
||||||
|
(like TDES) for legacy purposes only.
|
||||||
|
However, the risk is much higher and one CMAC key should be rotated
|
||||||
|
after as little as 16 MBytes (in total) have been authenticated.
|
||||||
|
|
||||||
|
.. _`NIST SP 800-38B`: http://csrc.nist.gov/publications/nistpubs/800-38B/SP_800-38B.pdf
|
||||||
|
.. _RFC4493: http://www.ietf.org/rfc/rfc4493.txt
|
||||||
|
.. _OMAC1: http://www.nuee.nagoya-u.ac.jp/labs/tiwata/omac/omac.html
|
||||||
|
"""
|
||||||
|
|
||||||
|
from Crypto.Util.py3compat import b, bchr, bord, tobytes
|
||||||
|
|
||||||
|
from binascii import unhexlify
|
||||||
|
|
||||||
|
from Crypto.Hash import BLAKE2s
|
||||||
|
from Crypto.Util.strxor import strxor
|
||||||
|
from Crypto.Util.number import long_to_bytes, bytes_to_long
|
||||||
|
from Crypto.Random import get_random_bytes
|
||||||
|
|
||||||
|
#: The size of the authentication tag produced by the MAC.
|
||||||
|
digest_size = None
|
||||||
|
|
||||||
|
def _shift_bytes(bs, xor_lsb=0):
|
||||||
|
num = (bytes_to_long(bs) << 1) ^ xor_lsb
|
||||||
|
return long_to_bytes(num, len(bs))[-len(bs):]
|
||||||
|
|
||||||
|
|
||||||
|
class CMAC(object):
|
||||||
|
"""Class that implements CMAC"""
|
||||||
|
|
||||||
|
#: The size of the authentication tag produced by the MAC.
|
||||||
|
digest_size = None
|
||||||
|
|
||||||
|
def __init__(self, key, msg=None, ciphermod=None, cipher_params=None):
|
||||||
|
"""Create a new CMAC object.
|
||||||
|
|
||||||
|
:Parameters:
|
||||||
|
key : byte string
|
||||||
|
secret key for the CMAC object.
|
||||||
|
The key must be valid for the underlying cipher algorithm.
|
||||||
|
For instance, it must be 16 bytes long for AES-128.
|
||||||
|
msg : byte string
|
||||||
|
The very first chunk of the message to authenticate.
|
||||||
|
It is equivalent to an early call to `update`. Optional.
|
||||||
|
ciphermod : module
|
||||||
|
A cipher module from `Crypto.Cipher`.
|
||||||
|
The cipher's block size has to be 128 bits.
|
||||||
|
It is recommended to use `Crypto.Cipher.AES`.
|
||||||
|
cipher_params : dictionary
|
||||||
|
Extra keywords to use when creating a new cipher.
|
||||||
|
"""
|
||||||
|
|
||||||
|
if ciphermod is None:
|
||||||
|
raise TypeError("ciphermod must be specified (try AES)")
|
||||||
|
|
||||||
|
self._key = key
|
||||||
|
self._factory = ciphermod
|
||||||
|
if cipher_params is None:
|
||||||
|
self._cipher_params = {}
|
||||||
|
else:
|
||||||
|
self._cipher_params = dict(cipher_params)
|
||||||
|
|
||||||
|
# Section 5.3 of NIST SP 800 38B and Appendix B
|
||||||
|
if ciphermod.block_size == 8:
|
||||||
|
const_Rb = 0x1B
|
||||||
|
self._max_size = 8 * (2 ** 21)
|
||||||
|
elif ciphermod.block_size == 16:
|
||||||
|
const_Rb = 0x87
|
||||||
|
self._max_size = 16 * (2 ** 48)
|
||||||
|
else:
|
||||||
|
raise TypeError("CMAC requires a cipher with a block size"
|
||||||
|
"of 8 or 16 bytes, not %d" %
|
||||||
|
(ciphermod.block_size,))
|
||||||
|
|
||||||
|
# Size of the final MAC tag, in bytes
|
||||||
|
self.digest_size = ciphermod.block_size
|
||||||
|
self._mac_tag = None
|
||||||
|
|
||||||
|
# Compute sub-keys
|
||||||
|
zero_block = bchr(0) * ciphermod.block_size
|
||||||
|
cipher = ciphermod.new(key,
|
||||||
|
ciphermod.MODE_ECB,
|
||||||
|
**self._cipher_params)
|
||||||
|
l = cipher.encrypt(zero_block)
|
||||||
|
if bord(l[0]) & 0x80:
|
||||||
|
self._k1 = _shift_bytes(l, const_Rb)
|
||||||
|
else:
|
||||||
|
self._k1 = _shift_bytes(l)
|
||||||
|
if bord(self._k1[0]) & 0x80:
|
||||||
|
self._k2 = _shift_bytes(self._k1, const_Rb)
|
||||||
|
else:
|
||||||
|
self._k2 = _shift_bytes(self._k1)
|
||||||
|
|
||||||
|
# Initialize CBC cipher with zero IV
|
||||||
|
self._cbc = ciphermod.new(key,
|
||||||
|
ciphermod.MODE_CBC,
|
||||||
|
zero_block,
|
||||||
|
**self._cipher_params)
|
||||||
|
|
||||||
|
# Cache for outstanding data to authenticate
|
||||||
|
self._cache = b("")
|
||||||
|
|
||||||
|
# Last two pieces of ciphertext produced
|
||||||
|
self._last_ct = self._last_pt = zero_block
|
||||||
|
self._before_last_ct = None
|
||||||
|
|
||||||
|
# Counter for total message size
|
||||||
|
self._data_size = 0
|
||||||
|
|
||||||
|
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._data_size += len(msg)
|
||||||
|
|
||||||
|
if len(self._cache) > 0:
|
||||||
|
filler = min(self.digest_size - len(self._cache), len(msg))
|
||||||
|
self._cache += msg[:filler]
|
||||||
|
|
||||||
|
if len(self._cache) < self.digest_size:
|
||||||
|
return self
|
||||||
|
|
||||||
|
msg = msg[filler:]
|
||||||
|
self._update(self._cache)
|
||||||
|
self._cache = b("")
|
||||||
|
|
||||||
|
update_len, remain = divmod(len(msg), self.digest_size)
|
||||||
|
update_len *= self.digest_size
|
||||||
|
if remain > 0:
|
||||||
|
self._update(msg[:update_len])
|
||||||
|
self._cache = msg[update_len:]
|
||||||
|
else:
|
||||||
|
self._update(msg)
|
||||||
|
self._cache = b("")
|
||||||
|
return self
|
||||||
|
|
||||||
|
def _update(self, data_block):
|
||||||
|
"""Update a block aligned to the block boundary"""
|
||||||
|
if len(data_block) == 0:
|
||||||
|
return
|
||||||
|
|
||||||
|
assert len(data_block) % self.digest_size == 0
|
||||||
|
|
||||||
|
ct = self._cbc.encrypt(data_block)
|
||||||
|
|
||||||
|
if len(data_block) == self.digest_size:
|
||||||
|
self._before_last_ct = self._last_ct
|
||||||
|
else:
|
||||||
|
self._before_last_ct = ct[-self.digest_size * 2:-self.digest_size]
|
||||||
|
self._last_ct = ct[-self.digest_size:]
|
||||||
|
self._last_pt = data_block[-self.digest_size:]
|
||||||
|
|
||||||
|
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: A `CMAC` object
|
||||||
|
"""
|
||||||
|
obj = CMAC(self._key,
|
||||||
|
ciphermod=self._factory,
|
||||||
|
cipher_params=self._cipher_params)
|
||||||
|
|
||||||
|
obj._cbc = self._factory.new(self._key,
|
||||||
|
self._factory.MODE_CBC,
|
||||||
|
self._last_ct,
|
||||||
|
**self._cipher_params)
|
||||||
|
for m in ['_mac_tag', '_last_ct', '_before_last_ct', '_cache',
|
||||||
|
'_data_size', '_max_size']:
|
||||||
|
setattr(obj, m, getattr(self, m))
|
||||||
|
return obj
|
||||||
|
|
||||||
|
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.
|
||||||
|
"""
|
||||||
|
|
||||||
|
if self._mac_tag is not None:
|
||||||
|
return self._mac_tag
|
||||||
|
|
||||||
|
if self._data_size > self._max_size:
|
||||||
|
raise ValueError("MAC is unsafe for this message")
|
||||||
|
|
||||||
|
if len(self._cache) == 0 and self._before_last_ct is not None:
|
||||||
|
## Last block was full
|
||||||
|
pt = strxor(strxor(self._before_last_ct, self._k1), self._last_pt)
|
||||||
|
else:
|
||||||
|
## Last block is partial (or message length is zero)
|
||||||
|
ext = self._cache + bchr(0x80) +\
|
||||||
|
bchr(0) * (self.digest_size - len(self._cache) - 1)
|
||||||
|
pt = strxor(strxor(self._last_ct, self._k2), ext)
|
||||||
|
|
||||||
|
cipher = self._factory.new(self._key,
|
||||||
|
self._factory.MODE_ECB,
|
||||||
|
**self._cipher_params)
|
||||||
|
self._mac_tag = cipher.encrypt(pt)
|
||||||
|
|
||||||
|
return self._mac_tag
|
||||||
|
|
||||||
|
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 verify(self, mac_tag):
|
||||||
|
"""Verify that a given **binary** MAC (computed by another party)
|
||||||
|
is valid.
|
||||||
|
|
||||||
|
:Parameters:
|
||||||
|
mac_tag : byte string
|
||||||
|
The expected MAC of the message.
|
||||||
|
:Raises ValueError:
|
||||||
|
if the MAC does not match. It means that the message
|
||||||
|
has been tampered with or that the MAC key is incorrect.
|
||||||
|
"""
|
||||||
|
|
||||||
|
secret = get_random_bytes(16)
|
||||||
|
|
||||||
|
mac1 = BLAKE2s.new(digest_bits=160, key=secret, data=mac_tag)
|
||||||
|
mac2 = BLAKE2s.new(digest_bits=160, key=secret, data=self.digest())
|
||||||
|
|
||||||
|
if mac1.digest() != mac2.digest():
|
||||||
|
raise ValueError("MAC check failed")
|
||||||
|
|
||||||
|
def hexverify(self, hex_mac_tag):
|
||||||
|
"""Verify that a given **printable** MAC (computed by another party)
|
||||||
|
is valid.
|
||||||
|
|
||||||
|
:Parameters:
|
||||||
|
hex_mac_tag : string
|
||||||
|
The expected MAC of the message, as a hexadecimal string.
|
||||||
|
:Raises ValueError:
|
||||||
|
if the MAC does not match. It means that the message
|
||||||
|
has been tampered with or that the MAC key is incorrect.
|
||||||
|
"""
|
||||||
|
|
||||||
|
self.verify(unhexlify(tobytes(hex_mac_tag)))
|
||||||
|
|
||||||
|
|
||||||
|
def new(key, msg=None, ciphermod=None, cipher_params=None):
|
||||||
|
"""Create a new CMAC object.
|
||||||
|
|
||||||
|
:Parameters:
|
||||||
|
key : byte string
|
||||||
|
secret key for the CMAC object.
|
||||||
|
The key must be valid for the underlying cipher algorithm.
|
||||||
|
For instance, it must be 16 bytes long for AES-128.
|
||||||
|
msg : byte string
|
||||||
|
The very first chunk of the message to authenticate.
|
||||||
|
It is equivalent to an early call to `CMAC.update`. Optional.
|
||||||
|
ciphermod : module
|
||||||
|
A cipher module from `Crypto.Cipher`.
|
||||||
|
The cipher's block size has to be 128 bits,
|
||||||
|
like `Crypto.Cipher.AES`, to reduce the probability of collisions.
|
||||||
|
|
||||||
|
:Returns: A `CMAC` object
|
||||||
|
"""
|
||||||
|
return CMAC(key, msg, ciphermod, cipher_params)
|
264
venv/Lib/site-packages/Crypto/Hash/HMAC.py
Normal file
264
venv/Lib/site-packages/Crypto/Hash/HMAC.py
Normal file
|
@ -0,0 +1,264 @@
|
||||||
|
#
|
||||||
|
# HMAC.py - Implements the HMAC algorithm as described by RFC 2104.
|
||||||
|
#
|
||||||
|
# ===================================================================
|
||||||
|
#
|
||||||
|
# Copyright (c) 2014, Legrandin <helderijs@gmail.com>
|
||||||
|
# All rights reserved.
|
||||||
|
#
|
||||||
|
# Redistribution and use in source and binary forms, with or without
|
||||||
|
# modification, are permitted provided that the following conditions
|
||||||
|
# are met:
|
||||||
|
#
|
||||||
|
# 1. Redistributions of source code must retain the above copyright
|
||||||
|
# notice, this list of conditions and the following disclaimer.
|
||||||
|
# 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
# notice, this list of conditions and the following disclaimer in
|
||||||
|
# the documentation and/or other materials provided with the
|
||||||
|
# distribution.
|
||||||
|
#
|
||||||
|
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||||
|
# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||||
|
# COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||||
|
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||||
|
# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||||
|
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||||
|
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||||
|
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
|
# POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
# ===================================================================
|
||||||
|
|
||||||
|
"""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
|
||||||
|
|
||||||
|
This is an example showing how to *create* a MAC:
|
||||||
|
|
||||||
|
>>> from Crypto.Hash import HMAC
|
||||||
|
>>>
|
||||||
|
>>> secret = b'Swordfish'
|
||||||
|
>>> h = HMAC.new(secret)
|
||||||
|
>>> h.update(b'Hello')
|
||||||
|
>>> print h.hexdigest()
|
||||||
|
|
||||||
|
This is an example showing how to *check* a MAC:
|
||||||
|
|
||||||
|
>>> from Crypto.Hash import HMAC
|
||||||
|
>>>
|
||||||
|
>>> # We have received a message 'msg' together
|
||||||
|
>>> # with its MAC 'mac'
|
||||||
|
>>>
|
||||||
|
>>> secret = b'Swordfish'
|
||||||
|
>>> h = HMAC.new(secret)
|
||||||
|
>>> h.update(msg)
|
||||||
|
>>> try:
|
||||||
|
>>> h.verify(mac)
|
||||||
|
>>> print "The message '%s' is authentic" % msg
|
||||||
|
>>> except ValueError:
|
||||||
|
>>> print "The message or the key is wrong"
|
||||||
|
|
||||||
|
.. _RFC2104: http://www.ietf.org/rfc/rfc2104.txt
|
||||||
|
.. _FIPS-198: http://csrc.nist.gov/publications/fips/fips198/fips-198-1_final.pdf
|
||||||
|
"""
|
||||||
|
|
||||||
|
__all__ = ['new', 'HMAC']
|
||||||
|
|
||||||
|
from Crypto.Util.py3compat import b, bchr, bord, tobytes
|
||||||
|
|
||||||
|
from binascii import unhexlify
|
||||||
|
|
||||||
|
from . import MD5, BLAKE2s
|
||||||
|
from Crypto.Util.strxor import strxor
|
||||||
|
from Crypto.Random import get_random_bytes
|
||||||
|
|
||||||
|
|
||||||
|
class HMAC:
|
||||||
|
"""Class that implements HMAC"""
|
||||||
|
|
||||||
|
def __init__(self, key, msg=b(""), 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:
|
||||||
|
digestmod = MD5
|
||||||
|
|
||||||
|
if msg is None:
|
||||||
|
msg = b("")
|
||||||
|
|
||||||
|
#: Size of the MAC tag
|
||||||
|
self.digest_size = digestmod.digest_size
|
||||||
|
|
||||||
|
self._digestmod = digestmod
|
||||||
|
|
||||||
|
try:
|
||||||
|
if len(key) <= digestmod.block_size:
|
||||||
|
# Step 1 or 2
|
||||||
|
key_0 = key + bchr(0) * (digestmod.block_size - len(key))
|
||||||
|
else:
|
||||||
|
# Step 3
|
||||||
|
hash_k = digestmod.new(key).digest()
|
||||||
|
key_0 = hash_k + bchr(0) * (digestmod.block_size - len(hash_k))
|
||||||
|
except AttributeError:
|
||||||
|
# Not all hash types have "block_size"
|
||||||
|
raise ValueError("Hash type incompatible to HMAC")
|
||||||
|
|
||||||
|
# Step 4
|
||||||
|
key_0_ipad = strxor(key_0, bchr(0x36) * len(key_0))
|
||||||
|
|
||||||
|
# Start step 5 and 6
|
||||||
|
self._inner = digestmod.new(key_0_ipad)
|
||||||
|
self._inner.update(msg)
|
||||||
|
|
||||||
|
# Step 7
|
||||||
|
key_0_opad = strxor(key_0, bchr(0x5c) * len(key_0))
|
||||||
|
|
||||||
|
# Start step 8 and 9
|
||||||
|
self._outer = digestmod.new(key_0_opad)
|
||||||
|
|
||||||
|
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
|
||||||
|
"""
|
||||||
|
|
||||||
|
new_hmac = HMAC(b("fake key"), digestmod=self._digestmod)
|
||||||
|
|
||||||
|
# Syncronize the state
|
||||||
|
new_hmac._inner = self._inner.copy()
|
||||||
|
new_hmac._outer = self._outer.copy()
|
||||||
|
|
||||||
|
return new_hmac
|
||||||
|
|
||||||
|
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.
|
||||||
|
"""
|
||||||
|
|
||||||
|
frozen_outer_hash = self._outer.copy()
|
||||||
|
frozen_outer_hash.update(self._inner.digest())
|
||||||
|
return frozen_outer_hash.digest()
|
||||||
|
|
||||||
|
def verify(self, mac_tag):
|
||||||
|
"""Verify that a given **binary** MAC (computed by another party)
|
||||||
|
is valid.
|
||||||
|
|
||||||
|
:Parameters:
|
||||||
|
mac_tag : byte string
|
||||||
|
The expected MAC of the message.
|
||||||
|
:Raises ValueError:
|
||||||
|
if the MAC does not match. It means that the message
|
||||||
|
has been tampered with or that the MAC key is incorrect.
|
||||||
|
"""
|
||||||
|
|
||||||
|
secret = get_random_bytes(16)
|
||||||
|
|
||||||
|
mac1 = BLAKE2s.new(digest_bits=160, key=secret, data=mac_tag)
|
||||||
|
mac2 = BLAKE2s.new(digest_bits=160, key=secret, data=self.digest())
|
||||||
|
|
||||||
|
if mac1.digest() != mac2.digest():
|
||||||
|
raise ValueError("MAC check failed")
|
||||||
|
|
||||||
|
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 hexverify(self, hex_mac_tag):
|
||||||
|
"""Verify that a given **printable** MAC (computed by another party)
|
||||||
|
is valid.
|
||||||
|
|
||||||
|
:Parameters:
|
||||||
|
hex_mac_tag : string
|
||||||
|
The expected MAC of the message, as a hexadecimal string.
|
||||||
|
:Raises ValueError:
|
||||||
|
if the MAC does not match. It means that the message
|
||||||
|
has been tampered with or that the MAC key is incorrect.
|
||||||
|
"""
|
||||||
|
|
||||||
|
self.verify(unhexlify(tobytes(hex_mac_tag)))
|
||||||
|
|
||||||
|
|
||||||
|
def new(key, msg=b(""), 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)
|
188
venv/Lib/site-packages/Crypto/Hash/MD2.py
Normal file
188
venv/Lib/site-packages/Crypto/Hash/MD2.py
Normal file
|
@ -0,0 +1,188 @@
|
||||||
|
# ===================================================================
|
||||||
|
#
|
||||||
|
# Copyright (c) 2014, Legrandin <helderijs@gmail.com>
|
||||||
|
# All rights reserved.
|
||||||
|
#
|
||||||
|
# Redistribution and use in source and binary forms, with or without
|
||||||
|
# modification, are permitted provided that the following conditions
|
||||||
|
# are met:
|
||||||
|
#
|
||||||
|
# 1. Redistributions of source code must retain the above copyright
|
||||||
|
# notice, this list of conditions and the following disclaimer.
|
||||||
|
# 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
# notice, this list of conditions and the following disclaimer in
|
||||||
|
# the documentation and/or other materials provided with the
|
||||||
|
# distribution.
|
||||||
|
#
|
||||||
|
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||||
|
# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||||
|
# COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||||
|
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||||
|
# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||||
|
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||||
|
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||||
|
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
|
# POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
# ===================================================================
|
||||||
|
|
||||||
|
"""
|
||||||
|
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
|
||||||
|
"""
|
||||||
|
|
||||||
|
from Crypto.Util.py3compat import bord
|
||||||
|
|
||||||
|
from Crypto.Util._raw_api import (load_pycryptodome_raw_lib,
|
||||||
|
VoidPointer, SmartPointer,
|
||||||
|
create_string_buffer,
|
||||||
|
get_raw_buffer, c_size_t,
|
||||||
|
expect_byte_string)
|
||||||
|
|
||||||
|
_raw_md2_lib = load_pycryptodome_raw_lib(
|
||||||
|
"Crypto.Hash._MD2",
|
||||||
|
"""
|
||||||
|
int md2_init(void **shaState);
|
||||||
|
int md2_destroy(void *shaState);
|
||||||
|
int md2_update(void *hs,
|
||||||
|
const uint8_t *buf,
|
||||||
|
size_t len);
|
||||||
|
int md2_digest(const void *shaState,
|
||||||
|
uint8_t digest[20]);
|
||||||
|
int md2_copy(const void *src, void *dst);
|
||||||
|
""")
|
||||||
|
|
||||||
|
|
||||||
|
class MD2Hash(object):
|
||||||
|
"""Class that implements an MD2 hash
|
||||||
|
"""
|
||||||
|
|
||||||
|
#: The size of the resulting hash in bytes.
|
||||||
|
digest_size = 16
|
||||||
|
#: The internal block size of the hash algorithm in bytes.
|
||||||
|
block_size = 64
|
||||||
|
#: ASN.1 Object ID
|
||||||
|
oid = "1.2.840.113549.2.2"
|
||||||
|
|
||||||
|
def __init__(self, data=None):
|
||||||
|
state = VoidPointer()
|
||||||
|
result = _raw_md2_lib.md2_init(state.address_of())
|
||||||
|
if result:
|
||||||
|
raise ValueError("Error %d while instantiating MD2"
|
||||||
|
% result)
|
||||||
|
self._state = SmartPointer(state.get(),
|
||||||
|
_raw_md2_lib.md2_destroy)
|
||||||
|
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.
|
||||||
|
"""
|
||||||
|
|
||||||
|
expect_byte_string(data)
|
||||||
|
result = _raw_md2_lib.md2_update(self._state.get(),
|
||||||
|
data,
|
||||||
|
c_size_t(len(data)))
|
||||||
|
if result:
|
||||||
|
raise ValueError("Error %d while instantiating MD2"
|
||||||
|
% result)
|
||||||
|
|
||||||
|
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.
|
||||||
|
"""
|
||||||
|
|
||||||
|
bfr = create_string_buffer(self.digest_size)
|
||||||
|
result = _raw_md2_lib.md2_digest(self._state.get(),
|
||||||
|
bfr)
|
||||||
|
if result:
|
||||||
|
raise ValueError("Error %d while instantiating MD2"
|
||||||
|
% result)
|
||||||
|
|
||||||
|
return get_raw_buffer(bfr)
|
||||||
|
|
||||||
|
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 "".join(["%02x" % bord(x) for x in self.digest()])
|
||||||
|
|
||||||
|
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
|
||||||
|
"""
|
||||||
|
|
||||||
|
clone = MD2Hash()
|
||||||
|
result = _raw_md2_lib.md2_copy(self._state.get(),
|
||||||
|
clone._state.get())
|
||||||
|
if result:
|
||||||
|
raise ValueError("Error %d while copying MD2" % result)
|
||||||
|
return clone
|
||||||
|
|
||||||
|
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: A `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
|
186
venv/Lib/site-packages/Crypto/Hash/MD4.py
Normal file
186
venv/Lib/site-packages/Crypto/Hash/MD4.py
Normal file
|
@ -0,0 +1,186 @@
|
||||||
|
# ===================================================================
|
||||||
|
#
|
||||||
|
# Copyright (c) 2014, Legrandin <helderijs@gmail.com>
|
||||||
|
# All rights reserved.
|
||||||
|
#
|
||||||
|
# Redistribution and use in source and binary forms, with or without
|
||||||
|
# modification, are permitted provided that the following conditions
|
||||||
|
# are met:
|
||||||
|
#
|
||||||
|
# 1. Redistributions of source code must retain the above copyright
|
||||||
|
# notice, this list of conditions and the following disclaimer.
|
||||||
|
# 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
# notice, this list of conditions and the following disclaimer in
|
||||||
|
# the documentation and/or other materials provided with the
|
||||||
|
# distribution.
|
||||||
|
#
|
||||||
|
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||||
|
# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||||
|
# COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||||
|
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||||
|
# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||||
|
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||||
|
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||||
|
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
|
# POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
# ===================================================================
|
||||||
|
|
||||||
|
"""
|
||||||
|
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
|
||||||
|
"""
|
||||||
|
|
||||||
|
from Crypto.Util.py3compat import bord
|
||||||
|
|
||||||
|
from Crypto.Util._raw_api import (load_pycryptodome_raw_lib,
|
||||||
|
VoidPointer, SmartPointer,
|
||||||
|
create_string_buffer,
|
||||||
|
get_raw_buffer, c_size_t,
|
||||||
|
expect_byte_string)
|
||||||
|
|
||||||
|
_raw_md4_lib = load_pycryptodome_raw_lib(
|
||||||
|
"Crypto.Hash._MD4",
|
||||||
|
"""
|
||||||
|
int md4_init(void **shaState);
|
||||||
|
int md4_destroy(void *shaState);
|
||||||
|
int md4_update(void *hs,
|
||||||
|
const uint8_t *buf,
|
||||||
|
size_t len);
|
||||||
|
int md4_digest(const void *shaState,
|
||||||
|
uint8_t digest[20]);
|
||||||
|
int md4_copy(const void *src, void *dst);
|
||||||
|
""")
|
||||||
|
|
||||||
|
|
||||||
|
class MD4Hash(object):
|
||||||
|
"""Class that implements an MD4 hash
|
||||||
|
"""
|
||||||
|
|
||||||
|
#: The size of the resulting hash in bytes.
|
||||||
|
digest_size = 16
|
||||||
|
#: The internal block size of the hash algorithm in bytes.
|
||||||
|
block_size = 64
|
||||||
|
#: ASN.1 Object ID
|
||||||
|
oid = "1.2.840.113549.2.4"
|
||||||
|
|
||||||
|
def __init__(self, data=None):
|
||||||
|
state = VoidPointer()
|
||||||
|
result = _raw_md4_lib.md4_init(state.address_of())
|
||||||
|
if result:
|
||||||
|
raise ValueError("Error %d while instantiating MD4"
|
||||||
|
% result)
|
||||||
|
self._state = SmartPointer(state.get(),
|
||||||
|
_raw_md4_lib.md4_destroy)
|
||||||
|
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.
|
||||||
|
"""
|
||||||
|
|
||||||
|
expect_byte_string(data)
|
||||||
|
result = _raw_md4_lib.md4_update(self._state.get(),
|
||||||
|
data,
|
||||||
|
c_size_t(len(data)))
|
||||||
|
if result:
|
||||||
|
raise ValueError("Error %d while instantiating MD4"
|
||||||
|
% result)
|
||||||
|
|
||||||
|
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.
|
||||||
|
"""
|
||||||
|
|
||||||
|
bfr = create_string_buffer(self.digest_size)
|
||||||
|
result = _raw_md4_lib.md4_digest(self._state.get(),
|
||||||
|
bfr)
|
||||||
|
if result:
|
||||||
|
raise ValueError("Error %d while instantiating MD4"
|
||||||
|
% result)
|
||||||
|
|
||||||
|
return get_raw_buffer(bfr)
|
||||||
|
|
||||||
|
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 "".join(["%02x" % bord(x) for x in self.digest()])
|
||||||
|
|
||||||
|
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
|
||||||
|
"""
|
||||||
|
|
||||||
|
clone = MD4Hash()
|
||||||
|
result = _raw_md4_lib.md4_copy(self._state.get(),
|
||||||
|
clone._state.get())
|
||||||
|
if result:
|
||||||
|
raise ValueError("Error %d while copying MD4" % result)
|
||||||
|
return clone
|
||||||
|
|
||||||
|
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
|
86
venv/Lib/site-packages/Crypto/Hash/MD5.py
Normal file
86
venv/Lib/site-packages/Crypto/Hash/MD5.py
Normal file
|
@ -0,0 +1,86 @@
|
||||||
|
# -*- 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
|
||||||
|
"""
|
||||||
|
|
||||||
|
__all__ = ['new', 'block_size', 'digest_size']
|
||||||
|
|
||||||
|
from Crypto.Util.py3compat import *
|
||||||
|
|
||||||
|
def __make_constructor():
|
||||||
|
try:
|
||||||
|
# The md5 module is deprecated in Python 2.6, so use hashlib when possible.
|
||||||
|
from hashlib import md5 as _hash_new
|
||||||
|
except ImportError:
|
||||||
|
from .md5 import new as _hash_new
|
||||||
|
|
||||||
|
h = _hash_new()
|
||||||
|
if hasattr(h, 'new') and hasattr(h, 'name') and hasattr(h, 'digest_size') and hasattr(h, 'block_size'):
|
||||||
|
# The module from stdlib has the API that we need. Just use it.
|
||||||
|
return _hash_new
|
||||||
|
else:
|
||||||
|
# Wrap the hash object in something that gives us the expected API.
|
||||||
|
_copy_sentinel = object()
|
||||||
|
class _MD5(object):
|
||||||
|
digest_size = 16
|
||||||
|
block_size = 64
|
||||||
|
oid = "1.2.840.113549.2.5"
|
||||||
|
def __init__(self, *args):
|
||||||
|
if args and args[0] is _copy_sentinel:
|
||||||
|
self._h = args[1]
|
||||||
|
else:
|
||||||
|
self._h = _hash_new(*args)
|
||||||
|
def copy(self):
|
||||||
|
return _MD5(_copy_sentinel, self._h.copy())
|
||||||
|
def update(self, *args):
|
||||||
|
f = self.update = self._h.update
|
||||||
|
f(*args)
|
||||||
|
def digest(self):
|
||||||
|
f = self.digest = self._h.digest
|
||||||
|
return f()
|
||||||
|
def hexdigest(self):
|
||||||
|
f = self.hexdigest = self._h.hexdigest
|
||||||
|
return f()
|
||||||
|
_MD5.new = _MD5
|
||||||
|
return _MD5
|
||||||
|
|
||||||
|
new = __make_constructor()
|
||||||
|
del __make_constructor
|
||||||
|
|
||||||
|
#: The size of the resulting hash in bytes.
|
||||||
|
digest_size = new().digest_size
|
||||||
|
|
||||||
|
#: The internal block size of the hash algorithm in bytes.
|
||||||
|
block_size = new().block_size
|
26
venv/Lib/site-packages/Crypto/Hash/RIPEMD.py
Normal file
26
venv/Lib/site-packages/Crypto/Hash/RIPEMD.py
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
# -*- 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.
|
||||||
|
# ===================================================================
|
||||||
|
|
||||||
|
# This file exists for backward compatibility with old code that refers to
|
||||||
|
# Crypto.Hash.RIPEMD
|
||||||
|
|
||||||
|
"""Deprecated alias for `Crypto.Hash.RIPEMD160`"""
|
||||||
|
|
||||||
|
from Crypto.Hash.RIPEMD160 import new, block_size, digest_size
|
191
venv/Lib/site-packages/Crypto/Hash/RIPEMD160.py
Normal file
191
venv/Lib/site-packages/Crypto/Hash/RIPEMD160.py
Normal file
|
@ -0,0 +1,191 @@
|
||||||
|
# ===================================================================
|
||||||
|
#
|
||||||
|
# Copyright (c) 2014, Legrandin <helderijs@gmail.com>
|
||||||
|
# All rights reserved.
|
||||||
|
#
|
||||||
|
# Redistribution and use in source and binary forms, with or without
|
||||||
|
# modification, are permitted provided that the following conditions
|
||||||
|
# are met:
|
||||||
|
#
|
||||||
|
# 1. Redistributions of source code must retain the above copyright
|
||||||
|
# notice, this list of conditions and the following disclaimer.
|
||||||
|
# 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
# notice, this list of conditions and the following disclaimer in
|
||||||
|
# the documentation and/or other materials provided with the
|
||||||
|
# distribution.
|
||||||
|
#
|
||||||
|
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||||
|
# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||||
|
# COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||||
|
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||||
|
# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||||
|
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||||
|
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||||
|
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
|
# POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
# ===================================================================
|
||||||
|
|
||||||
|
"""RIPEMD-160 cryptographic hash algorithm.
|
||||||
|
|
||||||
|
RIPEMD-160_ produces the 160 bit digest of a message.
|
||||||
|
|
||||||
|
>>> from Crypto.Hash import RIPEMD160
|
||||||
|
>>>
|
||||||
|
>>> h = RIPEMD160.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
|
||||||
|
"""
|
||||||
|
|
||||||
|
from Crypto.Util.py3compat import bord
|
||||||
|
|
||||||
|
from Crypto.Util._raw_api import (load_pycryptodome_raw_lib,
|
||||||
|
VoidPointer, SmartPointer,
|
||||||
|
create_string_buffer,
|
||||||
|
get_raw_buffer, c_size_t,
|
||||||
|
expect_byte_string)
|
||||||
|
|
||||||
|
_raw_ripemd160_lib = load_pycryptodome_raw_lib(
|
||||||
|
"Crypto.Hash._RIPEMD160",
|
||||||
|
"""
|
||||||
|
int ripemd160_init(void **shaState);
|
||||||
|
int ripemd160_destroy(void *shaState);
|
||||||
|
int ripemd160_update(void *hs,
|
||||||
|
const uint8_t *buf,
|
||||||
|
size_t len);
|
||||||
|
int ripemd160_digest(const void *shaState,
|
||||||
|
uint8_t digest[20]);
|
||||||
|
int ripemd160_copy(const void *src, void *dst);
|
||||||
|
""")
|
||||||
|
|
||||||
|
|
||||||
|
class RIPEMD160Hash(object):
|
||||||
|
"""Class that implements a RIPEMD-160 hash
|
||||||
|
"""
|
||||||
|
|
||||||
|
#: The size of the resulting hash in bytes.
|
||||||
|
digest_size = 20
|
||||||
|
#: The internal block size of the hash algorithm in bytes.
|
||||||
|
block_size = 64
|
||||||
|
#: ASN.1 Object ID
|
||||||
|
oid = "1.3.36.3.2.1"
|
||||||
|
|
||||||
|
def __init__(self, data=None):
|
||||||
|
state = VoidPointer()
|
||||||
|
result = _raw_ripemd160_lib.ripemd160_init(state.address_of())
|
||||||
|
if result:
|
||||||
|
raise ValueError("Error %d while instantiating RIPEMD160"
|
||||||
|
% result)
|
||||||
|
self._state = SmartPointer(state.get(),
|
||||||
|
_raw_ripemd160_lib.ripemd160_destroy)
|
||||||
|
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.
|
||||||
|
"""
|
||||||
|
|
||||||
|
expect_byte_string(data)
|
||||||
|
result = _raw_ripemd160_lib.ripemd160_update(self._state.get(),
|
||||||
|
data,
|
||||||
|
c_size_t(len(data)))
|
||||||
|
if result:
|
||||||
|
raise ValueError("Error %d while instantiating ripemd160"
|
||||||
|
% result)
|
||||||
|
|
||||||
|
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.
|
||||||
|
"""
|
||||||
|
|
||||||
|
bfr = create_string_buffer(self.digest_size)
|
||||||
|
result = _raw_ripemd160_lib.ripemd160_digest(self._state.get(),
|
||||||
|
bfr)
|
||||||
|
if result:
|
||||||
|
raise ValueError("Error %d while instantiating ripemd160"
|
||||||
|
% result)
|
||||||
|
|
||||||
|
return get_raw_buffer(bfr)
|
||||||
|
|
||||||
|
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 "".join(["%02x" % bord(x) for x in self.digest()])
|
||||||
|
|
||||||
|
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
|
||||||
|
"""
|
||||||
|
|
||||||
|
clone = RIPEMD160Hash()
|
||||||
|
result = _raw_ripemd160_lib.ripemd160_copy(self._state.get(),
|
||||||
|
clone._state.get())
|
||||||
|
if result:
|
||||||
|
raise ValueError("Error %d while copying ripemd160" % result)
|
||||||
|
return clone
|
||||||
|
|
||||||
|
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
|
24
venv/Lib/site-packages/Crypto/Hash/SHA.py
Normal file
24
venv/Lib/site-packages/Crypto/Hash/SHA.py
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
# -*- 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.
|
||||||
|
# ===================================================================
|
||||||
|
|
||||||
|
# This file exists for backward compatibility with old code that refers to
|
||||||
|
# Crypto.Hash.SHA
|
||||||
|
|
||||||
|
from Crypto.Hash.SHA1 import __doc__, new, block_size, digest_size
|
86
venv/Lib/site-packages/Crypto/Hash/SHA1.py
Normal file
86
venv/Lib/site-packages/Crypto/Hash/SHA1.py
Normal file
|
@ -0,0 +1,86 @@
|
||||||
|
# -*- 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 SHA1
|
||||||
|
>>>
|
||||||
|
>>> h = SHA1.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
|
||||||
|
"""
|
||||||
|
|
||||||
|
__all__ = ['new', 'block_size', 'digest_size']
|
||||||
|
|
||||||
|
from Crypto.Util.py3compat import *
|
||||||
|
|
||||||
|
def __make_constructor():
|
||||||
|
try:
|
||||||
|
# The sha module is deprecated in Python 2.6, so use hashlib when possible.
|
||||||
|
from hashlib import sha1 as _hash_new
|
||||||
|
except ImportError:
|
||||||
|
from .sha import new as _hash_new
|
||||||
|
|
||||||
|
h = _hash_new()
|
||||||
|
if hasattr(h, 'new') and hasattr(h, 'name') and hasattr(h, 'digest_size') and hasattr(h, 'block_size'):
|
||||||
|
# The module from stdlib has the API that we need. Just use it.
|
||||||
|
return _hash_new
|
||||||
|
else:
|
||||||
|
# Wrap the hash object in something that gives us the expected API.
|
||||||
|
_copy_sentinel = object()
|
||||||
|
class _SHA1(object):
|
||||||
|
digest_size = 20
|
||||||
|
block_size = 64
|
||||||
|
oid = "1.3.14.3.2.26"
|
||||||
|
def __init__(self, *args):
|
||||||
|
if args and args[0] is _copy_sentinel:
|
||||||
|
self._h = args[1]
|
||||||
|
else:
|
||||||
|
self._h = _hash_new(*args)
|
||||||
|
def copy(self):
|
||||||
|
return _SHA1(_copy_sentinel, self._h.copy())
|
||||||
|
def update(self, *args):
|
||||||
|
f = self.update = self._h.update
|
||||||
|
f(*args)
|
||||||
|
def digest(self):
|
||||||
|
f = self.digest = self._h.digest
|
||||||
|
return f()
|
||||||
|
def hexdigest(self):
|
||||||
|
f = self.hexdigest = self._h.hexdigest
|
||||||
|
return f()
|
||||||
|
_SHA1.new = _SHA1
|
||||||
|
return _SHA1
|
||||||
|
|
||||||
|
new = __make_constructor()
|
||||||
|
del __make_constructor
|
||||||
|
|
||||||
|
#: The size of the resulting hash in bytes.
|
||||||
|
digest_size = new().digest_size
|
||||||
|
|
||||||
|
#: The internal block size of the hash algorithm in bytes.
|
||||||
|
block_size = new().block_size
|
173
venv/Lib/site-packages/Crypto/Hash/SHA224.py
Normal file
173
venv/Lib/site-packages/Crypto/Hash/SHA224.py
Normal file
|
@ -0,0 +1,173 @@
|
||||||
|
# -*- 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-4.pdf
|
||||||
|
"""
|
||||||
|
|
||||||
|
from Crypto.Util.py3compat import *
|
||||||
|
|
||||||
|
from Crypto.Util._raw_api import (load_pycryptodome_raw_lib,
|
||||||
|
VoidPointer, SmartPointer,
|
||||||
|
create_string_buffer,
|
||||||
|
get_raw_buffer, c_size_t,
|
||||||
|
expect_byte_string)
|
||||||
|
|
||||||
|
_raw_sha224_lib = load_pycryptodome_raw_lib("Crypto.Hash._SHA224",
|
||||||
|
"""
|
||||||
|
int SHA224_init(void **shaState);
|
||||||
|
int SHA224_destroy(void *shaState);
|
||||||
|
int SHA224_update(void *hs,
|
||||||
|
const uint8_t *buf,
|
||||||
|
size_t len);
|
||||||
|
int SHA224_digest(const void *shaState,
|
||||||
|
uint8_t digest[16]);
|
||||||
|
int SHA224_copy(const void *src, void *dst);
|
||||||
|
""")
|
||||||
|
|
||||||
|
class SHA224Hash(object):
|
||||||
|
"""Class that implements a SHA-224 hash
|
||||||
|
"""
|
||||||
|
|
||||||
|
#: The size of the resulting hash in bytes.
|
||||||
|
digest_size = 28
|
||||||
|
#: The internal block size of the hash algorithm in bytes.
|
||||||
|
block_size = 64
|
||||||
|
#: ASN.1 Object ID
|
||||||
|
oid = '2.16.840.1.101.3.4.2.4'
|
||||||
|
|
||||||
|
def __init__(self, data=None):
|
||||||
|
state = VoidPointer()
|
||||||
|
result = _raw_sha224_lib.SHA224_init(state.address_of())
|
||||||
|
if result:
|
||||||
|
raise ValueError("Error %d while instantiating SHA224"
|
||||||
|
% result)
|
||||||
|
self._state = SmartPointer(state.get(),
|
||||||
|
_raw_sha224_lib.SHA224_destroy)
|
||||||
|
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.
|
||||||
|
"""
|
||||||
|
|
||||||
|
expect_byte_string(data)
|
||||||
|
result = _raw_sha224_lib.SHA224_update(self._state.get(),
|
||||||
|
data,
|
||||||
|
c_size_t(len(data)))
|
||||||
|
if result:
|
||||||
|
raise ValueError("Error %d while instantiating SHA224"
|
||||||
|
% result)
|
||||||
|
|
||||||
|
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.
|
||||||
|
"""
|
||||||
|
|
||||||
|
bfr = create_string_buffer(self.digest_size)
|
||||||
|
result = _raw_sha224_lib.SHA224_digest(self._state.get(),
|
||||||
|
bfr)
|
||||||
|
if result:
|
||||||
|
raise ValueError("Error %d while instantiating SHA224"
|
||||||
|
% result)
|
||||||
|
|
||||||
|
return get_raw_buffer(bfr)
|
||||||
|
|
||||||
|
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 "".join(["%02x" % bord(x) for x in self.digest()])
|
||||||
|
|
||||||
|
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
|
||||||
|
"""
|
||||||
|
|
||||||
|
clone = SHA224Hash()
|
||||||
|
result = _raw_sha224_lib.SHA224_copy(self._state.get(),
|
||||||
|
clone._state.get())
|
||||||
|
if result:
|
||||||
|
raise ValueError("Error %d while copying SHA224" % result)
|
||||||
|
return clone
|
||||||
|
|
||||||
|
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
|
||||||
|
|
173
venv/Lib/site-packages/Crypto/Hash/SHA256.py
Normal file
173
venv/Lib/site-packages/Crypto/Hash/SHA256.py
Normal file
|
@ -0,0 +1,173 @@
|
||||||
|
# -*- 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-4.pdf
|
||||||
|
"""
|
||||||
|
|
||||||
|
from Crypto.Util.py3compat import *
|
||||||
|
|
||||||
|
from Crypto.Util._raw_api import (load_pycryptodome_raw_lib,
|
||||||
|
VoidPointer, SmartPointer,
|
||||||
|
create_string_buffer,
|
||||||
|
get_raw_buffer, c_size_t,
|
||||||
|
expect_byte_string)
|
||||||
|
|
||||||
|
_raw_sha256_lib = load_pycryptodome_raw_lib("Crypto.Hash._SHA256",
|
||||||
|
"""
|
||||||
|
int SHA256_init(void **shaState);
|
||||||
|
int SHA256_destroy(void *shaState);
|
||||||
|
int SHA256_update(void *hs,
|
||||||
|
const uint8_t *buf,
|
||||||
|
size_t len);
|
||||||
|
int SHA256_digest(const void *shaState,
|
||||||
|
uint8_t digest[32]);
|
||||||
|
int SHA256_copy(const void *src, void *dst);
|
||||||
|
""")
|
||||||
|
|
||||||
|
class SHA256Hash(object):
|
||||||
|
"""Class that implements a SHA-256 hash
|
||||||
|
"""
|
||||||
|
|
||||||
|
#: The size of the resulting hash in bytes.
|
||||||
|
digest_size = 32
|
||||||
|
#: The internal block size of the hash algorithm in bytes.
|
||||||
|
block_size = 64
|
||||||
|
#: ASN.1 Object ID
|
||||||
|
oid = "2.16.840.1.101.3.4.2.1"
|
||||||
|
|
||||||
|
def __init__(self, data=None):
|
||||||
|
state = VoidPointer()
|
||||||
|
result = _raw_sha256_lib.SHA256_init(state.address_of())
|
||||||
|
if result:
|
||||||
|
raise ValueError("Error %d while instantiating SHA256"
|
||||||
|
% result)
|
||||||
|
self._state = SmartPointer(state.get(),
|
||||||
|
_raw_sha256_lib.SHA256_destroy)
|
||||||
|
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.
|
||||||
|
"""
|
||||||
|
|
||||||
|
expect_byte_string(data)
|
||||||
|
result = _raw_sha256_lib.SHA256_update(self._state.get(),
|
||||||
|
data,
|
||||||
|
c_size_t(len(data)))
|
||||||
|
if result:
|
||||||
|
raise ValueError("Error %d while instantiating SHA256"
|
||||||
|
% result)
|
||||||
|
|
||||||
|
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.
|
||||||
|
"""
|
||||||
|
|
||||||
|
bfr = create_string_buffer(self.digest_size)
|
||||||
|
result = _raw_sha256_lib.SHA256_digest(self._state.get(),
|
||||||
|
bfr)
|
||||||
|
if result:
|
||||||
|
raise ValueError("Error %d while instantiating SHA256"
|
||||||
|
% result)
|
||||||
|
|
||||||
|
return get_raw_buffer(bfr)
|
||||||
|
|
||||||
|
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 "".join(["%02x" % bord(x) for x in self.digest()])
|
||||||
|
|
||||||
|
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
|
||||||
|
"""
|
||||||
|
|
||||||
|
clone = SHA256Hash()
|
||||||
|
result = _raw_sha256_lib.SHA256_copy(self._state.get(),
|
||||||
|
clone._state.get())
|
||||||
|
if result:
|
||||||
|
raise ValueError("Error %d while copying SHA256" % result)
|
||||||
|
return clone
|
||||||
|
|
||||||
|
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
|
||||||
|
|
173
venv/Lib/site-packages/Crypto/Hash/SHA384.py
Normal file
173
venv/Lib/site-packages/Crypto/Hash/SHA384.py
Normal file
|
@ -0,0 +1,173 @@
|
||||||
|
# -*- 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-4.pdf
|
||||||
|
"""
|
||||||
|
|
||||||
|
from Crypto.Util.py3compat import *
|
||||||
|
|
||||||
|
from Crypto.Util._raw_api import (load_pycryptodome_raw_lib,
|
||||||
|
VoidPointer, SmartPointer,
|
||||||
|
create_string_buffer,
|
||||||
|
get_raw_buffer, c_size_t,
|
||||||
|
expect_byte_string)
|
||||||
|
|
||||||
|
_raw_sha384_lib = load_pycryptodome_raw_lib("Crypto.Hash._SHA384",
|
||||||
|
"""
|
||||||
|
int SHA384_init(void **shaState);
|
||||||
|
int SHA384_destroy(void *shaState);
|
||||||
|
int SHA384_update(void *hs,
|
||||||
|
const uint8_t *buf,
|
||||||
|
size_t len);
|
||||||
|
int SHA384_digest(const void *shaState,
|
||||||
|
uint8_t digest[48]);
|
||||||
|
int SHA384_copy(const void *src, void *dst);
|
||||||
|
""")
|
||||||
|
|
||||||
|
class SHA384Hash(object):
|
||||||
|
"""Class that implements a SHA-384 hash
|
||||||
|
"""
|
||||||
|
|
||||||
|
#: The size of the resulting hash in bytes.
|
||||||
|
digest_size = 48
|
||||||
|
#: The internal block size of the hash algorithm in bytes.
|
||||||
|
block_size = 128
|
||||||
|
#: ASN.1 Object ID
|
||||||
|
oid = '2.16.840.1.101.3.4.2.2'
|
||||||
|
|
||||||
|
def __init__(self, data=None):
|
||||||
|
state = VoidPointer()
|
||||||
|
result = _raw_sha384_lib.SHA384_init(state.address_of())
|
||||||
|
if result:
|
||||||
|
raise ValueError("Error %d while instantiating SHA384"
|
||||||
|
% result)
|
||||||
|
self._state = SmartPointer(state.get(),
|
||||||
|
_raw_sha384_lib.SHA384_destroy)
|
||||||
|
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.
|
||||||
|
"""
|
||||||
|
|
||||||
|
expect_byte_string(data)
|
||||||
|
result = _raw_sha384_lib.SHA384_update(self._state.get(),
|
||||||
|
data,
|
||||||
|
c_size_t(len(data)))
|
||||||
|
if result:
|
||||||
|
raise ValueError("Error %d while instantiating SHA384"
|
||||||
|
% result)
|
||||||
|
|
||||||
|
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.
|
||||||
|
"""
|
||||||
|
|
||||||
|
bfr = create_string_buffer(self.digest_size)
|
||||||
|
result = _raw_sha384_lib.SHA384_digest(self._state.get(),
|
||||||
|
bfr)
|
||||||
|
if result:
|
||||||
|
raise ValueError("Error %d while instantiating SHA384"
|
||||||
|
% result)
|
||||||
|
|
||||||
|
return get_raw_buffer(bfr)
|
||||||
|
|
||||||
|
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 "".join(["%02x" % bord(x) for x in self.digest()])
|
||||||
|
|
||||||
|
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
|
||||||
|
"""
|
||||||
|
|
||||||
|
clone = SHA384Hash()
|
||||||
|
result = _raw_sha384_lib.SHA384_copy(self._state.get(),
|
||||||
|
clone._state.get())
|
||||||
|
if result:
|
||||||
|
raise ValueError("Error %d while copying SHA384" % result)
|
||||||
|
return clone
|
||||||
|
|
||||||
|
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
|
||||||
|
|
168
venv/Lib/site-packages/Crypto/Hash/SHA3_224.py
Normal file
168
venv/Lib/site-packages/Crypto/Hash/SHA3_224.py
Normal file
|
@ -0,0 +1,168 @@
|
||||||
|
# -*- 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-3/224 cryptographic hash algorithm.
|
||||||
|
|
||||||
|
SHA-3/224 belongs to the SHA-3 family of cryptographic hashes, as specified
|
||||||
|
in `FIPS 202`__.
|
||||||
|
|
||||||
|
The hash function produces the 224 bit digest of a message.
|
||||||
|
|
||||||
|
>>> from Crypto.Hash import SHA3_224
|
||||||
|
>>>
|
||||||
|
>>> h_obj = SHA3_224.new()
|
||||||
|
>>> h_obj.update(b'Some data')
|
||||||
|
>>> print h_obj.hexdigest()
|
||||||
|
|
||||||
|
.. __: http://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.202.pdf
|
||||||
|
"""
|
||||||
|
|
||||||
|
from Crypto.Util.py3compat import bord
|
||||||
|
|
||||||
|
from Crypto.Util._raw_api import (load_pycryptodome_raw_lib,
|
||||||
|
VoidPointer, SmartPointer,
|
||||||
|
create_string_buffer,
|
||||||
|
get_raw_buffer, c_size_t,
|
||||||
|
expect_byte_string)
|
||||||
|
|
||||||
|
from Crypto.Hash.keccak import _raw_keccak_lib
|
||||||
|
|
||||||
|
class SHA3_224_Hash(object):
|
||||||
|
"""Class that implements a SHA-3/224 hash
|
||||||
|
"""
|
||||||
|
|
||||||
|
#: The size of the resulting hash in bytes.
|
||||||
|
digest_size = 28
|
||||||
|
|
||||||
|
#: ASN.1 Object ID
|
||||||
|
oid = "2.16.840.1.101.3.4.2.7"
|
||||||
|
|
||||||
|
def __init__(self, data, update_after_digest):
|
||||||
|
self._update_after_digest = update_after_digest
|
||||||
|
self._digest_done = False
|
||||||
|
|
||||||
|
state = VoidPointer()
|
||||||
|
result = _raw_keccak_lib.keccak_init(state.address_of(),
|
||||||
|
c_size_t(self.digest_size * 2),
|
||||||
|
0x06)
|
||||||
|
if result:
|
||||||
|
raise ValueError("Error %d while instantiating SHA-3/224"
|
||||||
|
% result)
|
||||||
|
self._state = SmartPointer(state.get(),
|
||||||
|
_raw_keccak_lib.keccak_destroy)
|
||||||
|
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.
|
||||||
|
"""
|
||||||
|
|
||||||
|
if self._digest_done and not self._update_after_digest:
|
||||||
|
raise TypeError("You can only call 'digest' or 'hexdigest' on this object")
|
||||||
|
|
||||||
|
expect_byte_string(data)
|
||||||
|
result = _raw_keccak_lib.keccak_absorb(self._state.get(),
|
||||||
|
data,
|
||||||
|
c_size_t(len(data)))
|
||||||
|
if result:
|
||||||
|
raise ValueError("Error %d while updating SHA-3/224"
|
||||||
|
% result)
|
||||||
|
return self
|
||||||
|
|
||||||
|
def digest(self):
|
||||||
|
"""Return the **binary** (non-printable) digest of the message that has been hashed so far.
|
||||||
|
|
||||||
|
You cannot update the hash anymore after the first call to ``digest``
|
||||||
|
(or ``hexdigest``).
|
||||||
|
|
||||||
|
:Return: A byte string of `digest_size` bytes. It may contain non-ASCII
|
||||||
|
characters, including null bytes.
|
||||||
|
"""
|
||||||
|
|
||||||
|
self._digest_done = True
|
||||||
|
|
||||||
|
bfr = create_string_buffer(self.digest_size)
|
||||||
|
result = _raw_keccak_lib.keccak_digest(self._state.get(),
|
||||||
|
bfr,
|
||||||
|
c_size_t(self.digest_size))
|
||||||
|
if result:
|
||||||
|
raise ValueError("Error %d while instantiating SHA-3/224"
|
||||||
|
% result)
|
||||||
|
|
||||||
|
self._digest_value = get_raw_buffer(bfr)
|
||||||
|
return self._digest_value
|
||||||
|
|
||||||
|
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 "".join(["%02x" % bord(x) for x in self.digest()])
|
||||||
|
|
||||||
|
def new(self):
|
||||||
|
return type(self)(None, self._update_after_digest)
|
||||||
|
|
||||||
|
|
||||||
|
def new(*args, **kwargs):
|
||||||
|
"""Return a fresh instance of the hash object.
|
||||||
|
|
||||||
|
:Keywords:
|
||||||
|
data : byte string
|
||||||
|
Optional. The very first chunk of the message to hash.
|
||||||
|
It is equivalent to an early call to ``update()``.
|
||||||
|
update_after_digest : boolean
|
||||||
|
Optional. By default, a hash object cannot be updated anymore after
|
||||||
|
the digest is computed. When this flag is ``True``, such check
|
||||||
|
is no longer enforced.
|
||||||
|
|
||||||
|
:Return: A `SHA3_224_Hash` object
|
||||||
|
"""
|
||||||
|
|
||||||
|
data = kwargs.pop("data", None)
|
||||||
|
update_after_digest = kwargs.pop("update_after_digest", False)
|
||||||
|
if len(args) == 1:
|
||||||
|
if data:
|
||||||
|
raise ValueError("Initial data for hash specified twice")
|
||||||
|
data = args[0]
|
||||||
|
|
||||||
|
if kwargs:
|
||||||
|
raise TypeError("Unknown parameters: " + str(kwargs))
|
||||||
|
|
||||||
|
return SHA3_224_Hash(data, update_after_digest)
|
||||||
|
|
||||||
|
#: The size of the resulting hash in bytes.
|
||||||
|
digest_size = SHA3_224_Hash.digest_size
|
168
venv/Lib/site-packages/Crypto/Hash/SHA3_256.py
Normal file
168
venv/Lib/site-packages/Crypto/Hash/SHA3_256.py
Normal file
|
@ -0,0 +1,168 @@
|
||||||
|
# -*- 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-3/256 cryptographic hash algorithm.
|
||||||
|
|
||||||
|
SHA-3/256 belongs to the SHA-3 family of cryptographic hashes, as specified
|
||||||
|
in `FIPS 202`__.
|
||||||
|
|
||||||
|
The hash function produces the 256 bit digest of a message.
|
||||||
|
|
||||||
|
>>> from Crypto.Hash import SHA3_256
|
||||||
|
>>>
|
||||||
|
>>> h_obj = SHA3_256.new()
|
||||||
|
>>> h_obj.update(b'Some data')
|
||||||
|
>>> print h_obj.hexdigest()
|
||||||
|
|
||||||
|
.. __: http://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.202.pdf
|
||||||
|
"""
|
||||||
|
|
||||||
|
from Crypto.Util.py3compat import bord
|
||||||
|
|
||||||
|
from Crypto.Util._raw_api import (load_pycryptodome_raw_lib,
|
||||||
|
VoidPointer, SmartPointer,
|
||||||
|
create_string_buffer,
|
||||||
|
get_raw_buffer, c_size_t,
|
||||||
|
expect_byte_string)
|
||||||
|
|
||||||
|
from Crypto.Hash.keccak import _raw_keccak_lib
|
||||||
|
|
||||||
|
class SHA3_256_Hash(object):
|
||||||
|
"""Class that implements a SHA-3/256 hash
|
||||||
|
"""
|
||||||
|
|
||||||
|
#: The size of the resulting hash in bytes.
|
||||||
|
digest_size = 32
|
||||||
|
|
||||||
|
#: ASN.1 Object ID
|
||||||
|
oid = "2.16.840.1.101.3.4.2.8"
|
||||||
|
|
||||||
|
def __init__(self, data, update_after_digest):
|
||||||
|
self._update_after_digest = update_after_digest
|
||||||
|
self._digest_done = False
|
||||||
|
|
||||||
|
state = VoidPointer()
|
||||||
|
result = _raw_keccak_lib.keccak_init(state.address_of(),
|
||||||
|
c_size_t(self.digest_size * 2),
|
||||||
|
0x06)
|
||||||
|
if result:
|
||||||
|
raise ValueError("Error %d while instantiating SHA-3/256"
|
||||||
|
% result)
|
||||||
|
self._state = SmartPointer(state.get(),
|
||||||
|
_raw_keccak_lib.keccak_destroy)
|
||||||
|
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.
|
||||||
|
"""
|
||||||
|
|
||||||
|
if self._digest_done and not self._update_after_digest:
|
||||||
|
raise TypeError("You can only call 'digest' or 'hexdigest' on this object")
|
||||||
|
|
||||||
|
expect_byte_string(data)
|
||||||
|
result = _raw_keccak_lib.keccak_absorb(self._state.get(),
|
||||||
|
data,
|
||||||
|
c_size_t(len(data)))
|
||||||
|
if result:
|
||||||
|
raise ValueError("Error %d while updating SHA-3/256"
|
||||||
|
% result)
|
||||||
|
return self
|
||||||
|
|
||||||
|
def digest(self):
|
||||||
|
"""Return the **binary** (non-printable) digest of the message that has been hashed so far.
|
||||||
|
|
||||||
|
You cannot update the hash anymore after the first call to ``digest``
|
||||||
|
(or ``hexdigest``).
|
||||||
|
|
||||||
|
:Return: A byte string of `digest_size` bytes. It may contain non-ASCII
|
||||||
|
characters, including null bytes.
|
||||||
|
"""
|
||||||
|
|
||||||
|
self._digest_done = True
|
||||||
|
|
||||||
|
bfr = create_string_buffer(self.digest_size)
|
||||||
|
result = _raw_keccak_lib.keccak_digest(self._state.get(),
|
||||||
|
bfr,
|
||||||
|
c_size_t(self.digest_size))
|
||||||
|
if result:
|
||||||
|
raise ValueError("Error %d while instantiating SHA-3/256"
|
||||||
|
% result)
|
||||||
|
|
||||||
|
self._digest_value = get_raw_buffer(bfr)
|
||||||
|
return self._digest_value
|
||||||
|
|
||||||
|
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 "".join(["%02x" % bord(x) for x in self.digest()])
|
||||||
|
|
||||||
|
def new(self):
|
||||||
|
return type(self)(None, self._update_after_digest)
|
||||||
|
|
||||||
|
|
||||||
|
def new(*args, **kwargs):
|
||||||
|
"""Return a fresh instance of the hash object.
|
||||||
|
|
||||||
|
:Keywords:
|
||||||
|
data : byte string
|
||||||
|
Optional. The very first chunk of the message to hash.
|
||||||
|
It is equivalent to an early call to ``update()``.
|
||||||
|
update_after_digest : boolean
|
||||||
|
Optional. By default, a hash object cannot be updated anymore after
|
||||||
|
the digest is computed. When this flag is ``True``, such check
|
||||||
|
is no longer enforced.
|
||||||
|
|
||||||
|
:Return: A `SHA3_256_Hash` object
|
||||||
|
"""
|
||||||
|
|
||||||
|
data = kwargs.pop("data", None)
|
||||||
|
update_after_digest = kwargs.pop("update_after_digest", False)
|
||||||
|
if len(args) == 1:
|
||||||
|
if data:
|
||||||
|
raise ValueError("Initial data for hash specified twice")
|
||||||
|
data = args[0]
|
||||||
|
|
||||||
|
if kwargs:
|
||||||
|
raise TypeError("Unknown parameters: " + str(kwargs))
|
||||||
|
|
||||||
|
return SHA3_256_Hash(data, update_after_digest)
|
||||||
|
|
||||||
|
#: The size of the resulting hash in bytes.
|
||||||
|
digest_size = SHA3_256_Hash.digest_size
|
168
venv/Lib/site-packages/Crypto/Hash/SHA3_384.py
Normal file
168
venv/Lib/site-packages/Crypto/Hash/SHA3_384.py
Normal file
|
@ -0,0 +1,168 @@
|
||||||
|
# -*- 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-3/384 cryptographic hash algorithm.
|
||||||
|
|
||||||
|
SHA-3/384 belongs to the SHA-3 family of cryptographic hashes, as specified
|
||||||
|
in `FIPS 202`__.
|
||||||
|
|
||||||
|
The hash function produces the 384 bit digest of a message.
|
||||||
|
|
||||||
|
>>> from Crypto.Hash import SHA3_384
|
||||||
|
>>>
|
||||||
|
>>> h_obj = SHA3_384.new()
|
||||||
|
>>> h_obj.update(b'Some data')
|
||||||
|
>>> print h_obj.hexdigest()
|
||||||
|
|
||||||
|
.. __: http://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.202.pdf
|
||||||
|
"""
|
||||||
|
|
||||||
|
from Crypto.Util.py3compat import bord
|
||||||
|
|
||||||
|
from Crypto.Util._raw_api import (load_pycryptodome_raw_lib,
|
||||||
|
VoidPointer, SmartPointer,
|
||||||
|
create_string_buffer,
|
||||||
|
get_raw_buffer, c_size_t,
|
||||||
|
expect_byte_string)
|
||||||
|
|
||||||
|
from Crypto.Hash.keccak import _raw_keccak_lib
|
||||||
|
|
||||||
|
class SHA3_384_Hash(object):
|
||||||
|
"""Class that implements a SHA-3/384 hash
|
||||||
|
"""
|
||||||
|
|
||||||
|
#: The size of the resulting hash in bytes.
|
||||||
|
digest_size = 48
|
||||||
|
|
||||||
|
#: ASN.1 Object ID
|
||||||
|
oid = "2.16.840.1.101.3.4.2.9"
|
||||||
|
|
||||||
|
def __init__(self, data, update_after_digest):
|
||||||
|
self._update_after_digest = update_after_digest
|
||||||
|
self._digest_done = False
|
||||||
|
|
||||||
|
state = VoidPointer()
|
||||||
|
result = _raw_keccak_lib.keccak_init(state.address_of(),
|
||||||
|
c_size_t(self.digest_size * 2),
|
||||||
|
0x06)
|
||||||
|
if result:
|
||||||
|
raise ValueError("Error %d while instantiating SHA-3/384"
|
||||||
|
% result)
|
||||||
|
self._state = SmartPointer(state.get(),
|
||||||
|
_raw_keccak_lib.keccak_destroy)
|
||||||
|
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.
|
||||||
|
"""
|
||||||
|
|
||||||
|
if self._digest_done and not self._update_after_digest:
|
||||||
|
raise TypeError("You can only call 'digest' or 'hexdigest' on this object")
|
||||||
|
|
||||||
|
expect_byte_string(data)
|
||||||
|
result = _raw_keccak_lib.keccak_absorb(self._state.get(),
|
||||||
|
data,
|
||||||
|
c_size_t(len(data)))
|
||||||
|
if result:
|
||||||
|
raise ValueError("Error %d while updating SHA-3/384"
|
||||||
|
% result)
|
||||||
|
return self
|
||||||
|
|
||||||
|
def digest(self):
|
||||||
|
"""Return the **binary** (non-printable) digest of the message that has been hashed so far.
|
||||||
|
|
||||||
|
You cannot update the hash anymore after the first call to ``digest``
|
||||||
|
(or ``hexdigest``).
|
||||||
|
|
||||||
|
:Return: A byte string of `digest_size` bytes. It may contain non-ASCII
|
||||||
|
characters, including null bytes.
|
||||||
|
"""
|
||||||
|
|
||||||
|
self._digest_done = True
|
||||||
|
|
||||||
|
bfr = create_string_buffer(self.digest_size)
|
||||||
|
result = _raw_keccak_lib.keccak_digest(self._state.get(),
|
||||||
|
bfr,
|
||||||
|
c_size_t(self.digest_size))
|
||||||
|
if result:
|
||||||
|
raise ValueError("Error %d while instantiating SHA-3/384"
|
||||||
|
% result)
|
||||||
|
|
||||||
|
self._digest_value = get_raw_buffer(bfr)
|
||||||
|
return self._digest_value
|
||||||
|
|
||||||
|
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 "".join(["%02x" % bord(x) for x in self.digest()])
|
||||||
|
|
||||||
|
def new(self):
|
||||||
|
return type(self)(None, self._update_after_digest)
|
||||||
|
|
||||||
|
|
||||||
|
def new(*args, **kwargs):
|
||||||
|
"""Return a fresh instance of the hash object.
|
||||||
|
|
||||||
|
:Keywords:
|
||||||
|
data : byte string
|
||||||
|
Optional. The very first chunk of the message to hash.
|
||||||
|
It is equivalent to an early call to ``update()``.
|
||||||
|
update_after_digest : boolean
|
||||||
|
Optional. By default, a hash object cannot be updated anymore after
|
||||||
|
the digest is computed. When this flag is ``True``, such check
|
||||||
|
is no longer enforced.
|
||||||
|
|
||||||
|
:Return: A `SHA3_384_Hash` object
|
||||||
|
"""
|
||||||
|
|
||||||
|
data = kwargs.pop("data", None)
|
||||||
|
update_after_digest = kwargs.pop("update_after_digest", False)
|
||||||
|
if len(args) == 1:
|
||||||
|
if data:
|
||||||
|
raise ValueError("Initial data for hash specified twice")
|
||||||
|
data = args[0]
|
||||||
|
|
||||||
|
if kwargs:
|
||||||
|
raise TypeError("Unknown parameters: " + str(kwargs))
|
||||||
|
|
||||||
|
return SHA3_384_Hash(data, update_after_digest)
|
||||||
|
|
||||||
|
#: The size of the resulting hash in bytes.
|
||||||
|
digest_size = SHA3_384_Hash.digest_size
|
168
venv/Lib/site-packages/Crypto/Hash/SHA3_512.py
Normal file
168
venv/Lib/site-packages/Crypto/Hash/SHA3_512.py
Normal file
|
@ -0,0 +1,168 @@
|
||||||
|
# -*- 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-3/512 cryptographic hash algorithm.
|
||||||
|
|
||||||
|
SHA-3/512 belongs to the SHA-3 family of cryptographic hashes, as specified
|
||||||
|
in `FIPS 202`__.
|
||||||
|
|
||||||
|
The hash function produces the 512 bit digest of a message.
|
||||||
|
|
||||||
|
>>> from Crypto.Hash import SHA3_512
|
||||||
|
>>>
|
||||||
|
>>> h_obj = SHA3_512.new()
|
||||||
|
>>> h_obj.update(b'Some data')
|
||||||
|
>>> print h_obj.hexdigest()
|
||||||
|
|
||||||
|
.. __: http://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.202.pdf
|
||||||
|
"""
|
||||||
|
|
||||||
|
from Crypto.Util.py3compat import bord
|
||||||
|
|
||||||
|
from Crypto.Util._raw_api import (load_pycryptodome_raw_lib,
|
||||||
|
VoidPointer, SmartPointer,
|
||||||
|
create_string_buffer,
|
||||||
|
get_raw_buffer, c_size_t,
|
||||||
|
expect_byte_string)
|
||||||
|
|
||||||
|
from Crypto.Hash.keccak import _raw_keccak_lib
|
||||||
|
|
||||||
|
class SHA3_512_Hash(object):
|
||||||
|
"""Class that implements a SHA-3/512 hash
|
||||||
|
"""
|
||||||
|
|
||||||
|
#: The size of the resulting hash in bytes.
|
||||||
|
digest_size = 64
|
||||||
|
|
||||||
|
#: ASN.1 Object ID
|
||||||
|
oid = "2.16.840.1.101.3.4.2.10"
|
||||||
|
|
||||||
|
def __init__(self, data, update_after_digest):
|
||||||
|
self._update_after_digest = update_after_digest
|
||||||
|
self._digest_done = False
|
||||||
|
|
||||||
|
state = VoidPointer()
|
||||||
|
result = _raw_keccak_lib.keccak_init(state.address_of(),
|
||||||
|
c_size_t(self.digest_size * 2),
|
||||||
|
0x06)
|
||||||
|
if result:
|
||||||
|
raise ValueError("Error %d while instantiating SHA-3/512"
|
||||||
|
% result)
|
||||||
|
self._state = SmartPointer(state.get(),
|
||||||
|
_raw_keccak_lib.keccak_destroy)
|
||||||
|
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.
|
||||||
|
"""
|
||||||
|
|
||||||
|
if self._digest_done and not self._update_after_digest:
|
||||||
|
raise TypeError("You can only call 'digest' or 'hexdigest' on this object")
|
||||||
|
|
||||||
|
expect_byte_string(data)
|
||||||
|
result = _raw_keccak_lib.keccak_absorb(self._state.get(),
|
||||||
|
data,
|
||||||
|
c_size_t(len(data)))
|
||||||
|
if result:
|
||||||
|
raise ValueError("Error %d while updating SHA-3/512"
|
||||||
|
% result)
|
||||||
|
return self
|
||||||
|
|
||||||
|
def digest(self):
|
||||||
|
"""Return the **binary** (non-printable) digest of the message that has been hashed so far.
|
||||||
|
|
||||||
|
You cannot update the hash anymore after the first call to ``digest``
|
||||||
|
(or ``hexdigest``).
|
||||||
|
|
||||||
|
:Return: A byte string of `digest_size` bytes. It may contain non-ASCII
|
||||||
|
characters, including null bytes.
|
||||||
|
"""
|
||||||
|
|
||||||
|
self._digest_done = True
|
||||||
|
|
||||||
|
bfr = create_string_buffer(self.digest_size)
|
||||||
|
result = _raw_keccak_lib.keccak_digest(self._state.get(),
|
||||||
|
bfr,
|
||||||
|
c_size_t(self.digest_size))
|
||||||
|
if result:
|
||||||
|
raise ValueError("Error %d while instantiating SHA-3/512"
|
||||||
|
% result)
|
||||||
|
|
||||||
|
self._digest_value = get_raw_buffer(bfr)
|
||||||
|
return self._digest_value
|
||||||
|
|
||||||
|
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 "".join(["%02x" % bord(x) for x in self.digest()])
|
||||||
|
|
||||||
|
def new(self):
|
||||||
|
return type(self)(None, self._update_after_digest)
|
||||||
|
|
||||||
|
|
||||||
|
def new(*args, **kwargs):
|
||||||
|
"""Return a fresh instance of the hash object.
|
||||||
|
|
||||||
|
:Keywords:
|
||||||
|
data : byte string
|
||||||
|
Optional. The very first chunk of the message to hash.
|
||||||
|
It is equivalent to an early call to ``update()``.
|
||||||
|
update_after_digest : boolean
|
||||||
|
Optional. By default, a hash object cannot be updated anymore after
|
||||||
|
the digest is computed. When this flag is ``True``, such check
|
||||||
|
is no longer enforced.
|
||||||
|
|
||||||
|
:Return: A `SHA3_512_Hash` object
|
||||||
|
"""
|
||||||
|
|
||||||
|
data = kwargs.pop("data", None)
|
||||||
|
update_after_digest = kwargs.pop("update_after_digest", False)
|
||||||
|
if len(args) == 1:
|
||||||
|
if data:
|
||||||
|
raise ValueError("Initial data for hash specified twice")
|
||||||
|
data = args[0]
|
||||||
|
|
||||||
|
if kwargs:
|
||||||
|
raise TypeError("Unknown parameters: " + str(kwargs))
|
||||||
|
|
||||||
|
return SHA3_512_Hash(data, update_after_digest)
|
||||||
|
|
||||||
|
#: The size of the resulting hash in bytes.
|
||||||
|
digest_size = SHA3_512_Hash.digest_size
|
173
venv/Lib/site-packages/Crypto/Hash/SHA512.py
Normal file
173
venv/Lib/site-packages/Crypto/Hash/SHA512.py
Normal file
|
@ -0,0 +1,173 @@
|
||||||
|
# -*- 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-4.pdf
|
||||||
|
"""
|
||||||
|
|
||||||
|
from Crypto.Util.py3compat import *
|
||||||
|
|
||||||
|
from Crypto.Util._raw_api import (load_pycryptodome_raw_lib,
|
||||||
|
VoidPointer, SmartPointer,
|
||||||
|
create_string_buffer,
|
||||||
|
get_raw_buffer, c_size_t,
|
||||||
|
expect_byte_string)
|
||||||
|
|
||||||
|
_raw_sha512_lib = load_pycryptodome_raw_lib("Crypto.Hash._SHA512",
|
||||||
|
"""
|
||||||
|
int SHA512_init(void **shaState);
|
||||||
|
int SHA512_destroy(void *shaState);
|
||||||
|
int SHA512_update(void *hs,
|
||||||
|
const uint8_t *buf,
|
||||||
|
size_t len);
|
||||||
|
int SHA512_digest(const void *shaState,
|
||||||
|
uint8_t digest[64]);
|
||||||
|
int SHA512_copy(const void *src, void *dst);
|
||||||
|
""")
|
||||||
|
|
||||||
|
class SHA512Hash(object):
|
||||||
|
"""Class that implements a SHA-512 hash
|
||||||
|
"""
|
||||||
|
|
||||||
|
#: The size of the resulting hash in bytes.
|
||||||
|
digest_size = 64
|
||||||
|
#: The internal block size of the hash algorithm in bytes.
|
||||||
|
block_size = 128
|
||||||
|
#: ASN.1 Object ID
|
||||||
|
oid = "2.16.840.1.101.3.4.2.3"
|
||||||
|
|
||||||
|
def __init__(self, data=None):
|
||||||
|
state = VoidPointer()
|
||||||
|
result = _raw_sha512_lib.SHA512_init(state.address_of())
|
||||||
|
if result:
|
||||||
|
raise ValueError("Error %d while instantiating SHA512"
|
||||||
|
% result)
|
||||||
|
self._state = SmartPointer(state.get(),
|
||||||
|
_raw_sha512_lib.SHA512_destroy)
|
||||||
|
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.
|
||||||
|
"""
|
||||||
|
|
||||||
|
expect_byte_string(data)
|
||||||
|
result = _raw_sha512_lib.SHA512_update(self._state.get(),
|
||||||
|
data,
|
||||||
|
c_size_t(len(data)))
|
||||||
|
if result:
|
||||||
|
raise ValueError("Error %d while instantiating SHA512"
|
||||||
|
% result)
|
||||||
|
|
||||||
|
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.
|
||||||
|
"""
|
||||||
|
|
||||||
|
bfr = create_string_buffer(self.digest_size)
|
||||||
|
result = _raw_sha512_lib.SHA512_digest(self._state.get(),
|
||||||
|
bfr)
|
||||||
|
if result:
|
||||||
|
raise ValueError("Error %d while instantiating SHA512"
|
||||||
|
% result)
|
||||||
|
|
||||||
|
return get_raw_buffer(bfr)
|
||||||
|
|
||||||
|
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 "".join(["%02x" % bord(x) for x in self.digest()])
|
||||||
|
|
||||||
|
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
|
||||||
|
"""
|
||||||
|
|
||||||
|
clone = SHA512Hash()
|
||||||
|
result = _raw_sha512_lib.SHA512_copy(self._state.get(),
|
||||||
|
clone._state.get())
|
||||||
|
if result:
|
||||||
|
raise ValueError("Error %d while copying SHA512" % result)
|
||||||
|
return clone
|
||||||
|
|
||||||
|
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
|
||||||
|
|
151
venv/Lib/site-packages/Crypto/Hash/SHAKE128.py
Normal file
151
venv/Lib/site-packages/Crypto/Hash/SHAKE128.py
Normal file
|
@ -0,0 +1,151 @@
|
||||||
|
# ===================================================================
|
||||||
|
#
|
||||||
|
# Copyright (c) 2015, Legrandin <helderijs@gmail.com>
|
||||||
|
# All rights reserved.
|
||||||
|
#
|
||||||
|
# Redistribution and use in source and binary forms, with or without
|
||||||
|
# modification, are permitted provided that the following conditions
|
||||||
|
# are met:
|
||||||
|
#
|
||||||
|
# 1. Redistributions of source code must retain the above copyright
|
||||||
|
# notice, this list of conditions and the following disclaimer.
|
||||||
|
# 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
# notice, this list of conditions and the following disclaimer in
|
||||||
|
# the documentation and/or other materials provided with the
|
||||||
|
# distribution.
|
||||||
|
#
|
||||||
|
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||||
|
# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||||
|
# COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||||
|
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||||
|
# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||||
|
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||||
|
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||||
|
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
|
# POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
# ===================================================================
|
||||||
|
|
||||||
|
"""SHAKE128 extendable-output function (XOF).
|
||||||
|
|
||||||
|
SHAKE128 belongs to the SHA-3 family, as specified in `FIPS 202`_.
|
||||||
|
|
||||||
|
As a XOF, SHAKE128 is a generalization of a cryptographic hash function.
|
||||||
|
Instead of having a fixed-length output (e.g. 32 bytes like SHA-2/256),
|
||||||
|
the output length for a XOF is unlimited.
|
||||||
|
|
||||||
|
The *128* in its name indicates its maximum security level (in bits),
|
||||||
|
as described in Section A.2 of `FIPS 202`_.
|
||||||
|
|
||||||
|
For instance:
|
||||||
|
|
||||||
|
>>> from Crypto.Hash import SHAKE128
|
||||||
|
>>> from binascii import hexlify
|
||||||
|
>>>
|
||||||
|
>>> shake = SHAKE128.new()
|
||||||
|
>>> shake.update(b'Some data')
|
||||||
|
>>> print hexlify(shake.read(26))
|
||||||
|
|
||||||
|
.. _FIPS 202: http://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.202.pdf
|
||||||
|
"""
|
||||||
|
|
||||||
|
from Crypto.Util.py3compat import bord
|
||||||
|
|
||||||
|
from Crypto.Util._raw_api import (load_pycryptodome_raw_lib,
|
||||||
|
VoidPointer, SmartPointer,
|
||||||
|
create_string_buffer,
|
||||||
|
get_raw_buffer, c_size_t,
|
||||||
|
expect_byte_string)
|
||||||
|
|
||||||
|
from Crypto.Hash.keccak import _raw_keccak_lib
|
||||||
|
|
||||||
|
class SHAKE128_XOF(object):
|
||||||
|
"""Class that implements a SHAKE128 XOF
|
||||||
|
"""
|
||||||
|
|
||||||
|
#: ASN.1 Object ID
|
||||||
|
oid = "2.16.840.1.101.3.4.2.11"
|
||||||
|
|
||||||
|
def __init__(self, data=None):
|
||||||
|
state = VoidPointer()
|
||||||
|
result = _raw_keccak_lib.keccak_init(state.address_of(),
|
||||||
|
c_size_t(32),
|
||||||
|
0x1F)
|
||||||
|
if result:
|
||||||
|
raise ValueError("Error %d while instantiating SHAKE128"
|
||||||
|
% result)
|
||||||
|
self._state = SmartPointer(state.get(),
|
||||||
|
_raw_keccak_lib.keccak_destroy)
|
||||||
|
self._is_squeezing = False
|
||||||
|
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)
|
||||||
|
|
||||||
|
You cannot use ``update`` anymore after the first call to ``read``.
|
||||||
|
|
||||||
|
:Parameters:
|
||||||
|
data : byte string
|
||||||
|
The next chunk of the message being hashed.
|
||||||
|
"""
|
||||||
|
|
||||||
|
if self._is_squeezing:
|
||||||
|
raise TypeError("You cannot call 'update' after the first 'read'")
|
||||||
|
|
||||||
|
expect_byte_string(data)
|
||||||
|
result = _raw_keccak_lib.keccak_absorb(self._state.get(),
|
||||||
|
data,
|
||||||
|
c_size_t(len(data)))
|
||||||
|
if result:
|
||||||
|
raise ValueError("Error %d while updating SHAKE128 state"
|
||||||
|
% result)
|
||||||
|
return self
|
||||||
|
|
||||||
|
def read(self, length):
|
||||||
|
"""Return the next ``length`` bytes of **binary** (non-printable)
|
||||||
|
digest for the message.
|
||||||
|
|
||||||
|
You cannot use ``update`` anymore after the first call to ``read``.
|
||||||
|
|
||||||
|
:Return: A byte string of `length` bytes.
|
||||||
|
"""
|
||||||
|
|
||||||
|
self._is_squeezing = True
|
||||||
|
bfr = create_string_buffer(length)
|
||||||
|
result = _raw_keccak_lib.keccak_squeeze(self._state.get(),
|
||||||
|
bfr,
|
||||||
|
c_size_t(length))
|
||||||
|
if result:
|
||||||
|
raise ValueError("Error %d while extracting from SHAKE128"
|
||||||
|
% result)
|
||||||
|
|
||||||
|
return get_raw_buffer(bfr)
|
||||||
|
|
||||||
|
def new(self, data=None):
|
||||||
|
return type(self)(data=data)
|
||||||
|
|
||||||
|
|
||||||
|
def new(data=None):
|
||||||
|
"""Return a fresh instance of a SHAKE128 object.
|
||||||
|
|
||||||
|
:Parameters:
|
||||||
|
data : byte string
|
||||||
|
The very first chunk of the message to hash.
|
||||||
|
It is equivalent to an early call to ``update()``.
|
||||||
|
Optional.
|
||||||
|
|
||||||
|
:Return: A `SHAKE128_XOF` object
|
||||||
|
"""
|
||||||
|
return SHAKE128_XOF(data=data)
|
151
venv/Lib/site-packages/Crypto/Hash/SHAKE256.py
Normal file
151
venv/Lib/site-packages/Crypto/Hash/SHAKE256.py
Normal file
|
@ -0,0 +1,151 @@
|
||||||
|
# ===================================================================
|
||||||
|
#
|
||||||
|
# Copyright (c) 2015, Legrandin <helderijs@gmail.com>
|
||||||
|
# All rights reserved.
|
||||||
|
#
|
||||||
|
# Redistribution and use in source and binary forms, with or without
|
||||||
|
# modification, are permitted provided that the following conditions
|
||||||
|
# are met:
|
||||||
|
#
|
||||||
|
# 1. Redistributions of source code must retain the above copyright
|
||||||
|
# notice, this list of conditions and the following disclaimer.
|
||||||
|
# 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
# notice, this list of conditions and the following disclaimer in
|
||||||
|
# the documentation and/or other materials provided with the
|
||||||
|
# distribution.
|
||||||
|
#
|
||||||
|
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||||
|
# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||||
|
# COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||||
|
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||||
|
# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||||
|
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||||
|
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||||
|
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
|
# POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
# ===================================================================
|
||||||
|
|
||||||
|
"""SHAKE256 extendable-output function.
|
||||||
|
|
||||||
|
SHAKE256 belongs to the SHA-3 family, as specified in `FIPS 202`_.
|
||||||
|
|
||||||
|
As a XOF, SHAKE256 is a generalization of a cryptographic hash function.
|
||||||
|
Instead of having a fixed-length output (e.g. 32 bytes like SHA-2/256),
|
||||||
|
the output length for a XOF is unlimited.
|
||||||
|
|
||||||
|
The *256* in its name indicates its maximum security level (in bits),
|
||||||
|
as described in Section A.2 of `FIPS 202`_.
|
||||||
|
|
||||||
|
For instance:
|
||||||
|
|
||||||
|
>>> from Crypto.Hash import SHAKE256
|
||||||
|
>>> from binascii import hexlify
|
||||||
|
>>>
|
||||||
|
>>> shake = SHAKE256.new()
|
||||||
|
>>> shake.update(b'Some data')
|
||||||
|
>>> print hexlify(shake.read(26))
|
||||||
|
|
||||||
|
.. _FIPS 202: http://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.202.pdf
|
||||||
|
"""
|
||||||
|
|
||||||
|
from Crypto.Util.py3compat import bord
|
||||||
|
|
||||||
|
from Crypto.Util._raw_api import (load_pycryptodome_raw_lib,
|
||||||
|
VoidPointer, SmartPointer,
|
||||||
|
create_string_buffer,
|
||||||
|
get_raw_buffer, c_size_t,
|
||||||
|
expect_byte_string)
|
||||||
|
|
||||||
|
from Crypto.Hash.keccak import _raw_keccak_lib
|
||||||
|
|
||||||
|
class SHAKE256_XOF(object):
|
||||||
|
"""Class that implements a SHAKE256 XOF
|
||||||
|
"""
|
||||||
|
|
||||||
|
#: ASN.1 Object ID
|
||||||
|
oid = "2.16.840.1.101.3.4.2.12"
|
||||||
|
|
||||||
|
def __init__(self, data=None):
|
||||||
|
state = VoidPointer()
|
||||||
|
result = _raw_keccak_lib.keccak_init(state.address_of(),
|
||||||
|
c_size_t(64),
|
||||||
|
0x1F)
|
||||||
|
if result:
|
||||||
|
raise ValueError("Error %d while instantiating SHAKE256"
|
||||||
|
% result)
|
||||||
|
self._state = SmartPointer(state.get(),
|
||||||
|
_raw_keccak_lib.keccak_destroy)
|
||||||
|
self._is_squeezing = False
|
||||||
|
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)
|
||||||
|
|
||||||
|
You cannot use ``update`` anymore after the first call to ``read``.
|
||||||
|
|
||||||
|
:Parameters:
|
||||||
|
data : byte string
|
||||||
|
The next chunk of the message being hashed.
|
||||||
|
"""
|
||||||
|
|
||||||
|
if self._is_squeezing:
|
||||||
|
raise TypeError("You cannot call 'update' after the first 'read'")
|
||||||
|
|
||||||
|
expect_byte_string(data)
|
||||||
|
result = _raw_keccak_lib.keccak_absorb(self._state.get(),
|
||||||
|
data,
|
||||||
|
c_size_t(len(data)))
|
||||||
|
if result:
|
||||||
|
raise ValueError("Error %d while updating SHAKE256 state"
|
||||||
|
% result)
|
||||||
|
return self
|
||||||
|
|
||||||
|
def read(self, length):
|
||||||
|
"""Return the next ``length`` bytes of **binary** (non-printable)
|
||||||
|
digest for the message.
|
||||||
|
|
||||||
|
You cannot use ``update`` anymore after the first call to ``read``.
|
||||||
|
|
||||||
|
:Return: A byte string of `length` bytes.
|
||||||
|
"""
|
||||||
|
|
||||||
|
self._is_squeezing = True
|
||||||
|
bfr = create_string_buffer(length)
|
||||||
|
result = _raw_keccak_lib.keccak_squeeze(self._state.get(),
|
||||||
|
bfr,
|
||||||
|
c_size_t(length))
|
||||||
|
if result:
|
||||||
|
raise ValueError("Error %d while extracting from SHAKE256"
|
||||||
|
% result)
|
||||||
|
|
||||||
|
return get_raw_buffer(bfr)
|
||||||
|
|
||||||
|
def new(self, data=None):
|
||||||
|
return type(self)(data=data)
|
||||||
|
|
||||||
|
|
||||||
|
def new(data=None):
|
||||||
|
"""Return a fresh instance of a SHAKE256 object.
|
||||||
|
|
||||||
|
:Parameters:
|
||||||
|
data : byte string
|
||||||
|
The very first chunk of the message to hash.
|
||||||
|
It is equivalent to an early call to ``update()``.
|
||||||
|
Optional.
|
||||||
|
|
||||||
|
:Return: A `SHAKE256_XOF` object
|
||||||
|
"""
|
||||||
|
return SHAKE256_XOF(data=data)
|
BIN
venv/Lib/site-packages/Crypto/Hash/_BLAKE2b.cp36-win32.pyd
Normal file
BIN
venv/Lib/site-packages/Crypto/Hash/_BLAKE2b.cp36-win32.pyd
Normal file
Binary file not shown.
BIN
venv/Lib/site-packages/Crypto/Hash/_BLAKE2s.cp36-win32.pyd
Normal file
BIN
venv/Lib/site-packages/Crypto/Hash/_BLAKE2s.cp36-win32.pyd
Normal file
Binary file not shown.
BIN
venv/Lib/site-packages/Crypto/Hash/_MD2.cp36-win32.pyd
Normal file
BIN
venv/Lib/site-packages/Crypto/Hash/_MD2.cp36-win32.pyd
Normal file
Binary file not shown.
BIN
venv/Lib/site-packages/Crypto/Hash/_MD4.cp36-win32.pyd
Normal file
BIN
venv/Lib/site-packages/Crypto/Hash/_MD4.cp36-win32.pyd
Normal file
Binary file not shown.
BIN
venv/Lib/site-packages/Crypto/Hash/_RIPEMD160.cp36-win32.pyd
Normal file
BIN
venv/Lib/site-packages/Crypto/Hash/_RIPEMD160.cp36-win32.pyd
Normal file
Binary file not shown.
BIN
venv/Lib/site-packages/Crypto/Hash/_SHA224.cp36-win32.pyd
Normal file
BIN
venv/Lib/site-packages/Crypto/Hash/_SHA224.cp36-win32.pyd
Normal file
Binary file not shown.
BIN
venv/Lib/site-packages/Crypto/Hash/_SHA256.cp36-win32.pyd
Normal file
BIN
venv/Lib/site-packages/Crypto/Hash/_SHA256.cp36-win32.pyd
Normal file
Binary file not shown.
BIN
venv/Lib/site-packages/Crypto/Hash/_SHA384.cp36-win32.pyd
Normal file
BIN
venv/Lib/site-packages/Crypto/Hash/_SHA384.cp36-win32.pyd
Normal file
Binary file not shown.
BIN
venv/Lib/site-packages/Crypto/Hash/_SHA512.cp36-win32.pyd
Normal file
BIN
venv/Lib/site-packages/Crypto/Hash/_SHA512.cp36-win32.pyd
Normal file
Binary file not shown.
48
venv/Lib/site-packages/Crypto/Hash/__init__.py
Normal file
48
venv/Lib/site-packages/Crypto/Hash/__init__.py
Normal file
|
@ -0,0 +1,48 @@
|
||||||
|
# -*- 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.
|
||||||
|
|
||||||
|
:undocumented: _MD2, _MD4, _RIPEMD160, _SHA224, _SHA256, _SHA384, _SHA512, _RIPEMD
|
||||||
|
"""
|
||||||
|
|
||||||
|
__all__ = ['HMAC', 'MD2', 'MD4', 'MD5', 'RIPEMD160', 'SHA1',
|
||||||
|
'SHA224', 'SHA256', 'SHA384', 'SHA512', 'CMAC']
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue