updated pycrypto
This commit is contained in:
@@ -31,87 +31,32 @@ encryption.
|
||||
As an example, encryption can be done as follows:
|
||||
|
||||
>>> from Crypto.Cipher import AES
|
||||
>>> from Crypto.Random import get_random_bytes
|
||||
>>> from Crypto import Random
|
||||
>>>
|
||||
>>> key = b'Sixteen byte key'
|
||||
>>> iv = get_random_bytes(16)
|
||||
>>> iv = Random.new().read(AES.block_size)
|
||||
>>> cipher = AES.new(key, AES.MODE_CFB, iv)
|
||||
>>> msg = 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.
|
||||
It also allows message for the header 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'
|
||||
>>> nonce = get_random_bytes(11)
|
||||
>>> cipher = AES.new(key, AES.MODE_CCM, nonce)
|
||||
>>> cipher.update(hdr)
|
||||
>>> msg = 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: __revision__, __package__
|
||||
"""
|
||||
|
||||
__revision__ = "$Id$"
|
||||
|
||||
import sys
|
||||
if sys.version_info[0] == 2 and sys.version_info[1] == 1:
|
||||
from Crypto.Util.py21compat import *
|
||||
from Crypto.Cipher import blockalgo
|
||||
from Crypto.Cipher import _AES
|
||||
from Crypto.Util import cpuid
|
||||
# Import _AESNI. If AES-NI is not available or _AESNI has not been built, set
|
||||
# _AESNI to None.
|
||||
try:
|
||||
if cpuid.have_aes_ni():
|
||||
from Crypto.Cipher import _AESNI
|
||||
else:
|
||||
_AESNI = None
|
||||
except ImportError:
|
||||
_AESNI = None
|
||||
|
||||
class AESCipher (blockalgo.BlockAlgo):
|
||||
"""AES cipher object"""
|
||||
|
||||
def __init__(self, key, *args, **kwargs):
|
||||
"""Initialize an AES cipher object
|
||||
|
||||
|
||||
See also `new()` at the module level."""
|
||||
|
||||
# Check if the use_aesni was specified.
|
||||
use_aesni = True
|
||||
if kwargs.has_key('use_aesni'):
|
||||
use_aesni = kwargs['use_aesni']
|
||||
del kwargs['use_aesni']
|
||||
|
||||
# Use _AESNI if the user requested AES-NI and it's available
|
||||
if _AESNI is not None and use_aesni:
|
||||
blockalgo.BlockAlgo.__init__(self, _AESNI, key, *args, **kwargs)
|
||||
else:
|
||||
blockalgo.BlockAlgo.__init__(self, _AES, key, *args, **kwargs)
|
||||
blockalgo.BlockAlgo.__init__(self, _AES, key, *args, **kwargs)
|
||||
|
||||
def new(key, *args, **kwargs):
|
||||
"""Create a new AES cipher
|
||||
@@ -120,15 +65,11 @@ def new(key, *args, **kwargs):
|
||||
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.
|
||||
:Keywords:
|
||||
mode : a *MODE_** constant
|
||||
The chaining mode to use for encryption or decryption.
|
||||
Default is `MODE_ECB`.
|
||||
IV : byte string
|
||||
(*Only* `MODE_CBC`, `MODE_CFB`, `MODE_OFB`, `MODE_OPENPGP`).
|
||||
|
||||
The initialization vector to use for encryption or decryption.
|
||||
|
||||
It is ignored for `MODE_ECB` and `MODE_CTR`.
|
||||
@@ -137,20 +78,9 @@ def new(key, *args, **kwargs):
|
||||
and `block_size` +2 bytes for decryption (in the latter case, it is
|
||||
actually the *encrypted* IV which was prefixed to the ciphertext).
|
||||
It is mandatory.
|
||||
|
||||
For all other modes, it must be 16 bytes long.
|
||||
nonce : byte string
|
||||
(*Only* `MODE_CCM`, `MODE_EAX`, `MODE_GCM`, `MODE_SIV`).
|
||||
|
||||
A mandatory value that must never be reused for any other encryption.
|
||||
|
||||
For `MODE_CCM`, 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.
|
||||
|
||||
For the other modes, there are no restrictions on its length,
|
||||
but it is recommended to use at least 16 bytes.
|
||||
|
||||
For all other modes, it must be `block_size` bytes longs. It is optional and
|
||||
when not present it will be given a default value of all zeroes.
|
||||
counter : callable
|
||||
(*Only* `MODE_CTR`). A stateful function that returns the next
|
||||
*counter block*, which is a byte string of `block_size` bytes.
|
||||
@@ -159,20 +89,6 @@ def new(key, *args, **kwargs):
|
||||
(*Only* `MODE_CFB`).The number of bits the plaintext and ciphertext
|
||||
are segmented in.
|
||||
It must be a multiple of 8. If 0 or not specified, it will be assumed to be 8.
|
||||
mac_len : integer
|
||||
(*Only* `MODE_CCM`). Length of the MAC, in bytes. It must be even and in
|
||||
the range ``[4..16]``. The default is 16.
|
||||
|
||||
(*Only* `MODE_EAX` and `MODE_GCM`). Length of the MAC, in bytes. It must be no
|
||||
larger than 16 bytes (which is the default).
|
||||
msg_len : integer
|
||||
(*Only* `MODE_CCM`). Length of the message to (de)cipher.
|
||||
If not specified, ``encrypt`` or ``decrypt`` may only be called once.
|
||||
assoc_len : integer
|
||||
(*Only* `MODE_CCM`). Length of the associated data.
|
||||
If not specified, all data is internally buffered.
|
||||
use_aesni : boolean
|
||||
Use AES-NI if available.
|
||||
|
||||
:Return: an `AESCipher` object
|
||||
"""
|
||||
@@ -192,14 +108,6 @@ MODE_OFB = 5
|
||||
MODE_CTR = 6
|
||||
#: OpenPGP Mode. See `blockalgo.MODE_OPENPGP`.
|
||||
MODE_OPENPGP = 7
|
||||
#: Counter with CBC-MAC (CCM) Mode. See `blockalgo.MODE_CCM`.
|
||||
MODE_CCM = 8
|
||||
#: EAX Mode. See `blockalgo.MODE_EAX`.
|
||||
MODE_EAX = 9
|
||||
#: Syntethic Initialization Vector (SIV). See `blockalgo.MODE_SIV`.
|
||||
MODE_SIV = 10
|
||||
#: Galois Counter Mode (GCM). See `blockalgo.MODE_GCM`.
|
||||
MODE_GCM = 11
|
||||
#: Size of a data block (in bytes)
|
||||
block_size = 16
|
||||
#: Size of a key (in bytes)
|
||||
|
||||
@@ -32,7 +32,7 @@ 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
|
||||
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
|
||||
@@ -66,7 +66,7 @@ class RC2Cipher (blockalgo.BlockAlgo):
|
||||
|
||||
def __init__(self, key, *args, **kwargs):
|
||||
"""Initialize an ARC2 cipher object
|
||||
|
||||
|
||||
See also `new()` at the module level."""
|
||||
blockalgo.BlockAlgo.__init__(self, _ARC2, key, *args, **kwargs)
|
||||
|
||||
@@ -82,8 +82,6 @@ def new(key, *args, **kwargs):
|
||||
The chaining mode to use for encryption or decryption.
|
||||
Default is `MODE_ECB`.
|
||||
IV : byte string
|
||||
(*Only* `MODE_CBC`, `MODE_CFB`, `MODE_OFB`, `MODE_OPENPGP`).
|
||||
|
||||
The initialization vector to use for encryption or decryption.
|
||||
|
||||
It is ignored for `MODE_ECB` and `MODE_CTR`.
|
||||
@@ -92,20 +90,13 @@ def new(key, *args, **kwargs):
|
||||
and `block_size` +2 bytes for decryption (in the latter case, it is
|
||||
actually the *encrypted* IV which was prefixed to the ciphertext).
|
||||
It is mandatory.
|
||||
|
||||
For all other modes, it must be 8 bytes long.
|
||||
nonce : byte string
|
||||
(*Only* `MODE_EAX`).
|
||||
A mandatory 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.
|
||||
|
||||
For all other modes, it must be `block_size` bytes longs. It is optional and
|
||||
when not present it will be given a default value of all zeroes.
|
||||
counter : callable
|
||||
(*Only* `MODE_CTR`). A stateful function that returns the next
|
||||
*counter block*, which is a byte string of `block_size` bytes.
|
||||
For better performance, use `Crypto.Util.Counter`.
|
||||
mac_len : integer
|
||||
(*Only* `MODE_EAX`). Length of the MAC, 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.
|
||||
@@ -132,8 +123,6 @@ MODE_OFB = 5
|
||||
MODE_CTR = 6
|
||||
#: OpenPGP Mode. See `blockalgo.MODE_OPENPGP`.
|
||||
MODE_OPENPGP = 7
|
||||
#: EAX Mode. See `blockalgo.MODE_EAX`.
|
||||
MODE_EAX = 9
|
||||
#: Size of a data block (in bytes)
|
||||
block_size = 8
|
||||
#: Size of a key (in bytes)
|
||||
|
||||
@@ -63,7 +63,6 @@ As an example, encryption can be done as follows:
|
||||
|
||||
__revision__ = "$Id$"
|
||||
|
||||
from Crypto.Util.py3compat import *
|
||||
from Crypto.Cipher import _ARC4
|
||||
|
||||
class ARC4Cipher:
|
||||
@@ -75,18 +74,7 @@ class ARC4Cipher:
|
||||
|
||||
See also `new()` at the module level."""
|
||||
|
||||
if len(args)>0:
|
||||
ndrop = args[0]
|
||||
args = args[1:]
|
||||
else:
|
||||
ndrop = kwargs.get('drop', 0)
|
||||
if ndrop: del kwargs['drop']
|
||||
self._cipher = _ARC4.new(key, *args, **kwargs)
|
||||
if ndrop:
|
||||
# This is OK even if the cipher is used for decryption, since encrypt
|
||||
# and decrypt are actually the same thing with ARC4.
|
||||
self._cipher.encrypt(b('\x00')*ndrop)
|
||||
|
||||
self.block_size = self._cipher.block_size
|
||||
self.key_size = self._cipher.key_size
|
||||
|
||||
@@ -120,17 +108,8 @@ def new(key, *args, **kwargs):
|
||||
The secret key to use in the symmetric cipher.
|
||||
It can have any length, with a minimum of 40 bytes.
|
||||
Its cryptograpic strength is always capped to 2048 bits (256 bytes).
|
||||
: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)
|
||||
|
||||
|
||||
@@ -60,7 +60,7 @@ class BlowfishCipher (blockalgo.BlockAlgo):
|
||||
|
||||
def __init__(self, key, *args, **kwargs):
|
||||
"""Initialize a Blowfish cipher object
|
||||
|
||||
|
||||
See also `new()` at the module level."""
|
||||
blockalgo.BlockAlgo.__init__(self, _Blowfish, key, *args, **kwargs)
|
||||
|
||||
@@ -76,8 +76,6 @@ def new(key, *args, **kwargs):
|
||||
The chaining mode to use for encryption or decryption.
|
||||
Default is `MODE_ECB`.
|
||||
IV : byte string
|
||||
(*Only* `MODE_CBC`, `MODE_CFB`, `MODE_OFB`, `MODE_OPENPGP`).
|
||||
|
||||
The initialization vector to use for encryption or decryption.
|
||||
|
||||
It is ignored for `MODE_ECB` and `MODE_CTR`.
|
||||
@@ -86,20 +84,13 @@ def new(key, *args, **kwargs):
|
||||
and `block_size` +2 bytes for decryption (in the latter case, it is
|
||||
actually the *encrypted* IV which was prefixed to the ciphertext).
|
||||
It is mandatory.
|
||||
|
||||
For all other modes, it must be 8 bytes long.
|
||||
nonce : byte string
|
||||
(*Only* `MODE_EAX`).
|
||||
A mandatory 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.
|
||||
|
||||
For all other modes, it must be `block_size` bytes longs. It is optional and
|
||||
when not present it will be given a default value of all zeroes.
|
||||
counter : callable
|
||||
(*Only* `MODE_CTR`). A stateful function that returns the next
|
||||
*counter block*, which is a byte string of `block_size` bytes.
|
||||
For better performance, use `Crypto.Util.Counter`.
|
||||
mac_len : integer
|
||||
(*Only* `MODE_EAX`). Length of the MAC, 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.
|
||||
@@ -123,8 +114,6 @@ MODE_OFB = 5
|
||||
MODE_CTR = 6
|
||||
#: OpenPGP Mode. See `blockalgo.MODE_OPENPGP`.
|
||||
MODE_OPENPGP = 7
|
||||
#: EAX Mode. See `blockalgo.MODE_EAX`.
|
||||
MODE_EAX = 9
|
||||
#: Size of a data block (in bytes)
|
||||
block_size = 8
|
||||
#: Size of a key (in bytes)
|
||||
|
||||
@@ -63,7 +63,7 @@ class CAST128Cipher(blockalgo.BlockAlgo):
|
||||
|
||||
def __init__(self, key, *args, **kwargs):
|
||||
"""Initialize a CAST-128 cipher object
|
||||
|
||||
|
||||
See also `new()` at the module level."""
|
||||
blockalgo.BlockAlgo.__init__(self, _CAST, key, *args, **kwargs)
|
||||
|
||||
@@ -79,8 +79,6 @@ def new(key, *args, **kwargs):
|
||||
The chaining mode to use for encryption or decryption.
|
||||
Default is `MODE_ECB`.
|
||||
IV : byte string
|
||||
(*Only* `MODE_CBC`, `MODE_CFB`, `MODE_OFB`, `MODE_OPENPGP`).
|
||||
|
||||
The initialization vector to use for encryption or decryption.
|
||||
|
||||
It is ignored for `MODE_ECB` and `MODE_CTR`.
|
||||
@@ -89,20 +87,13 @@ def new(key, *args, **kwargs):
|
||||
and `block_size` +2 bytes for decryption (in the latter case, it is
|
||||
actually the *encrypted* IV which was prefixed to the ciphertext).
|
||||
It is mandatory.
|
||||
|
||||
For all other modes, it must be 8 bytes long.
|
||||
nonce : byte string
|
||||
(*Only* `MODE_EAX`).
|
||||
A mandatory 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.
|
||||
|
||||
For all other modes, it must be `block_size` bytes longs. It is optional and
|
||||
when not present it will be given a default value of all zeroes.
|
||||
counter : callable
|
||||
(*Only* `MODE_CTR`). A stateful function that returns the next
|
||||
*counter block*, which is a byte string of `block_size` bytes.
|
||||
For better performance, use `Crypto.Util.Counter`.
|
||||
mac_len : integer
|
||||
(*Only* `MODE_EAX`). Length of the MAC, 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.
|
||||
@@ -126,8 +117,6 @@ MODE_OFB = 5
|
||||
MODE_CTR = 6
|
||||
#: OpenPGP Mode. See `blockalgo.MODE_OPENPGP`.
|
||||
MODE_OPENPGP = 7
|
||||
#: EAX Mode. See `blockalgo.MODE_EAX`.
|
||||
MODE_EAX = 9
|
||||
#: Size of a data block (in bytes)
|
||||
block_size = 8
|
||||
#: Size of a key (in bytes)
|
||||
|
||||
@@ -33,12 +33,12 @@ DES should not be used for new designs. Use `AES`.
|
||||
|
||||
As an example, encryption can be done as follows:
|
||||
|
||||
>>> from Crypto.Cipher import DES
|
||||
>>> from Crypto.Cipher import DES3
|
||||
>>> from Crypto import Random
|
||||
>>>
|
||||
>>> key = b'-8B key-'
|
||||
>>> iv = Random.new().read(DES.block_size)
|
||||
>>> cipher = DES.new(key, DES.MODE_OFB, iv)
|
||||
>>> key = b'Sixteen byte key'
|
||||
>>> iv = Random.new().read(DES3.block_size)
|
||||
>>> cipher = DES3.new(key, DES3.MODE_OFB, iv)
|
||||
>>> plaintext = b'sona si latine loqueris '
|
||||
>>> msg = iv + cipher.encrypt(plaintext)
|
||||
|
||||
@@ -58,7 +58,7 @@ class DESCipher(blockalgo.BlockAlgo):
|
||||
|
||||
def __init__(self, key, *args, **kwargs):
|
||||
"""Initialize a DES cipher object
|
||||
|
||||
|
||||
See also `new()` at the module level."""
|
||||
blockalgo.BlockAlgo.__init__(self, _DES, key, *args, **kwargs)
|
||||
|
||||
@@ -74,8 +74,6 @@ def new(key, *args, **kwargs):
|
||||
The chaining mode to use for encryption or decryption.
|
||||
Default is `MODE_ECB`.
|
||||
IV : byte string
|
||||
(*Only* `MODE_CBC`, `MODE_CFB`, `MODE_OFB`, `MODE_OPENPGP`).
|
||||
|
||||
The initialization vector to use for encryption or decryption.
|
||||
|
||||
It is ignored for `MODE_ECB` and `MODE_CTR`.
|
||||
@@ -84,20 +82,13 @@ def new(key, *args, **kwargs):
|
||||
and `block_size` +2 bytes for decryption (in the latter case, it is
|
||||
actually the *encrypted* IV which was prefixed to the ciphertext).
|
||||
It is mandatory.
|
||||
|
||||
For all other modes, it must be 8 bytes long.
|
||||
nonce : byte string
|
||||
(*Only* `MODE_EAX`).
|
||||
A mandatory 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.
|
||||
|
||||
For all other modes, it must be `block_size` bytes longs. It is optional and
|
||||
when not present it will be given a default value of all zeroes.
|
||||
counter : callable
|
||||
(*Only* `MODE_CTR`). A stateful function that returns the next
|
||||
*counter block*, which is a byte string of `block_size` bytes.
|
||||
For better performance, use `Crypto.Util.Counter`.
|
||||
mac_len : integer
|
||||
(*Only* `MODE_EAX`). Length of the MAC, 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.
|
||||
@@ -121,8 +112,6 @@ MODE_OFB = 5
|
||||
MODE_CTR = 6
|
||||
#: OpenPGP Mode. See `blockalgo.MODE_OPENPGP`.
|
||||
MODE_OPENPGP = 7
|
||||
#: EAX Mode. See `blockalgo.MODE_EAX`.
|
||||
MODE_EAX = 9
|
||||
#: Size of a data block (in bytes)
|
||||
block_size = 8
|
||||
#: Size of a key (in bytes)
|
||||
|
||||
@@ -44,14 +44,14 @@ as `AES`.
|
||||
|
||||
As an example, encryption can be done as follows:
|
||||
|
||||
>>> from Crypto.Cipher import DES3
|
||||
>>> from Crypto.Cipher import DES
|
||||
>>> from Crypto import Random
|
||||
>>> from Crypto.Util import Counter
|
||||
>>>
|
||||
>>> key = b'Sixteen byte key'
|
||||
>>> nonce = Random.new().read(DES3.block_size/2)
|
||||
>>> ctr = Counter.new(DES3.block_size*8/2, prefix=nonce)
|
||||
>>> cipher = DES3.new(key, DES3.MODE_CTR, counter=ctr)
|
||||
>>> key = b'-8B key-'
|
||||
>>> nonce = Random.new().read(DES.block_size/2)
|
||||
>>> ctr = Counter.new(DES.block_size*8/2, prefix=nonce)
|
||||
>>> cipher = DES.new(key, DES.MODE_CTR, counter=ctr)
|
||||
>>> plaintext = b'We are no longer the knights who say ni!'
|
||||
>>> msg = nonce + cipher.encrypt(plaintext)
|
||||
|
||||
@@ -71,7 +71,7 @@ class DES3Cipher(blockalgo.BlockAlgo):
|
||||
|
||||
def __init__(self, key, *args, **kwargs):
|
||||
"""Initialize a TDES cipher object
|
||||
|
||||
|
||||
See also `new()` at the module level."""
|
||||
blockalgo.BlockAlgo.__init__(self, _DES3, key, *args, **kwargs)
|
||||
|
||||
@@ -87,8 +87,6 @@ def new(key, *args, **kwargs):
|
||||
The chaining mode to use for encryption or decryption.
|
||||
Default is `MODE_ECB`.
|
||||
IV : byte string
|
||||
(*Only* `MODE_CBC`, `MODE_CFB`, `MODE_OFB`, `MODE_OPENPGP`).
|
||||
|
||||
The initialization vector to use for encryption or decryption.
|
||||
|
||||
It is ignored for `MODE_ECB` and `MODE_CTR`.
|
||||
@@ -97,20 +95,13 @@ def new(key, *args, **kwargs):
|
||||
and `block_size` +2 bytes for decryption (in the latter case, it is
|
||||
actually the *encrypted* IV which was prefixed to the ciphertext).
|
||||
It is mandatory.
|
||||
|
||||
For all other modes, it must be 8 bytes long.
|
||||
nonce : byte string
|
||||
(*Only* `MODE_EAX`).
|
||||
A mandatory 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.
|
||||
|
||||
For all other modes, it must be `block_size` bytes longs. It is optional and
|
||||
when not present it will be given a default value of all zeroes.
|
||||
counter : callable
|
||||
(*Only* `MODE_CTR`). A stateful function that returns the next
|
||||
*counter block*, which is a byte string of 8 bytes.
|
||||
*counter block*, which is a byte string of `block_size` bytes.
|
||||
For better performance, use `Crypto.Util.Counter`.
|
||||
mac_len : integer
|
||||
(*Only* `MODE_EAX`). Length of the MAC, 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.
|
||||
@@ -136,8 +127,6 @@ MODE_OFB = 5
|
||||
MODE_CTR = 6
|
||||
#: OpenPGP Mode. See `blockalgo.MODE_OPENPGP`.
|
||||
MODE_OPENPGP = 7
|
||||
#: EAX Mode. See `blockalgo.MODE_EAX`.
|
||||
MODE_EAX = 9
|
||||
#: Size of a data block (in bytes)
|
||||
block_size = 8
|
||||
#: Size of a key (in bytes)
|
||||
|
||||
@@ -31,7 +31,7 @@ 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'
|
||||
>>> message = 'To be encrypted'
|
||||
>>> key = RSA.importKey(open('pubkey.der').read())
|
||||
>>> cipher = PKCS1_OAEP.new(key)
|
||||
>>> ciphertext = cipher.encrypt(message)
|
||||
@@ -55,7 +55,7 @@ __revision__ = "$Id$"
|
||||
__all__ = [ 'new', 'PKCS1OAEP_Cipher' ]
|
||||
|
||||
import Crypto.Signature.PKCS1_PSS
|
||||
import Crypto.Hash.SHA1
|
||||
import Crypto.Hash.SHA
|
||||
|
||||
from Crypto.Util.py3compat import *
|
||||
import Crypto.Util.number
|
||||
@@ -70,17 +70,17 @@ class PKCS1OAEP_Cipher:
|
||||
|
||||
: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.
|
||||
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.
|
||||
`Crypto.Hash.SHA` (that is, SHA-1) is used.
|
||||
mgfunc : callable
|
||||
A mask generation function that accepts two parameters: a string to
|
||||
use as seed, and the lenth of the mask to generate, in bytes.
|
||||
If not specified, the standard MGF1 is used (a safe choice).
|
||||
label : byte string
|
||||
label : string
|
||||
A label to apply to this particular encryption. If not specified,
|
||||
an empty string is used. Specifying a label does not improve
|
||||
security.
|
||||
@@ -93,7 +93,7 @@ class PKCS1OAEP_Cipher:
|
||||
if hashAlgo:
|
||||
self._hashObj = hashAlgo
|
||||
else:
|
||||
self._hashObj = Crypto.Hash.SHA1
|
||||
self._hashObj = Crypto.Hash.SHA
|
||||
|
||||
if mgfunc:
|
||||
self._mgf = mgfunc
|
||||
@@ -117,12 +117,12 @@ class PKCS1OAEP_Cipher:
|
||||
section 7.1.1 of RFC3447.
|
||||
|
||||
:Parameters:
|
||||
message : byte string
|
||||
message : string
|
||||
The message to encrypt, also known as plaintext. It can be of
|
||||
variable length, but not longer than the RSA modulus (in bytes)
|
||||
minus 2, minus twice the hash output size.
|
||||
|
||||
:Return: A byte string, the ciphertext in which the message is encrypted.
|
||||
:Return: A string, the ciphertext in which the message is encrypted.
|
||||
It is as long as the RSA modulus (in bytes).
|
||||
:Raise ValueError:
|
||||
If the RSA key length is not sufficiently long to deal with the given
|
||||
@@ -173,10 +173,10 @@ class PKCS1OAEP_Cipher:
|
||||
section 7.1.2 of RFC3447.
|
||||
|
||||
:Parameters:
|
||||
ct : byte string
|
||||
ct : string
|
||||
The ciphertext that contains the message to recover.
|
||||
|
||||
:Return: A byte string, the original message.
|
||||
:Return: A string, the original message.
|
||||
:Raise ValueError:
|
||||
If the ciphertext length is incorrect, or if the decryption does not
|
||||
succeed.
|
||||
@@ -238,12 +238,12 @@ def new(key, hashAlgo=None, mgfunc=None, label=b('')):
|
||||
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.
|
||||
`Crypto.Hash.SHA` (that is, SHA-1) is used.
|
||||
mgfunc : callable
|
||||
A mask generation function that accepts two parameters: a string to
|
||||
use as seed, and the lenth of the mask to generate, in bytes.
|
||||
If not specified, the standard MGF1 is used (a safe choice).
|
||||
label : byte string
|
||||
label : string
|
||||
A label to apply to this particular encryption. If not specified,
|
||||
an empty string is used. Specifying a label does not improve
|
||||
security.
|
||||
|
||||
@@ -34,7 +34,7 @@ As an example, a sender may encrypt a message in this way:
|
||||
>>> from Crypto.PublicKey import RSA
|
||||
>>> from Crypto.Hash import SHA
|
||||
>>>
|
||||
>>> message = b'To be encrypted'
|
||||
>>> message = 'To be encrypted'
|
||||
>>> h = SHA.new(message)
|
||||
>>>
|
||||
>>> key = RSA.importKey(open('pubkey.der').read())
|
||||
|
||||
Executable
BIN
Binary file not shown.
Executable
BIN
Binary file not shown.
Executable
BIN
Binary file not shown.
Executable
BIN
Binary file not shown.
Executable
BIN
Binary file not shown.
Executable
BIN
Binary file not shown.
Executable
BIN
Binary file not shown.
Executable
BIN
Binary file not shown.
File diff suppressed because it is too large
Load Diff
@@ -43,7 +43,7 @@ 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:
|
||||
An example of possible usage is the following:
|
||||
|
||||
>>> from Crypto.Hash import HMAC
|
||||
>>>
|
||||
@@ -52,22 +52,6 @@ This is an example showing how to *create* a MAC:
|
||||
>>> 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-198a.pdf
|
||||
"""
|
||||
@@ -79,8 +63,6 @@ __revision__ = "$Id$"
|
||||
|
||||
__all__ = ['new', 'digest_size', 'HMAC' ]
|
||||
|
||||
from binascii import unhexlify
|
||||
|
||||
from Crypto.Util.strxor import strxor_c
|
||||
from Crypto.Util.py3compat import *
|
||||
|
||||
@@ -189,32 +171,12 @@ class HMAC:
|
||||
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.
|
||||
characters, including null bytes.
|
||||
"""
|
||||
|
||||
h = self.outer.copy()
|
||||
h.update(self.inner.digest())
|
||||
return h.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.
|
||||
"""
|
||||
|
||||
mac = self.digest()
|
||||
res = 0
|
||||
# Constant-time comparison
|
||||
for x,y in zip(mac, mac_tag):
|
||||
res |= bord(x) ^ bord(y)
|
||||
if res or len(mac_tag)!=self.digest_size:
|
||||
raise ValueError("MAC check failed")
|
||||
|
||||
def hexdigest(self):
|
||||
"""Return the **printable** MAC of the message that has been
|
||||
authenticated so far.
|
||||
@@ -227,19 +189,6 @@ class HMAC:
|
||||
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 = None, digestmod = None):
|
||||
"""Create a new HMAC object.
|
||||
|
||||
|
||||
@@ -0,0 +1,91 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# ===================================================================
|
||||
# The contents of this file are dedicated to the public domain. To
|
||||
# the extent that dedication to the public domain is not available,
|
||||
# everyone is granted a worldwide, perpetual, royalty-free,
|
||||
# non-exclusive license to exercise all rights associated with the
|
||||
# contents of this file for any purpose whatsoever.
|
||||
# No rights are reserved.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
# SOFTWARE.
|
||||
# ===================================================================
|
||||
|
||||
"""MD2 cryptographic hash algorithm.
|
||||
|
||||
MD2 is specified in RFC1319_ and it produces the 128 bit digest of a message.
|
||||
|
||||
>>> from Crypto.Hash import MD2
|
||||
>>>
|
||||
>>> h = MD2.new()
|
||||
>>> h.update(b'Hello')
|
||||
>>> print h.hexdigest()
|
||||
|
||||
MD2 stand for Message Digest version 2, and it was invented by Rivest in 1989.
|
||||
|
||||
This algorithm is both slow and insecure. Do not use it for new designs.
|
||||
|
||||
.. _RFC1319: http://tools.ietf.org/html/rfc1319
|
||||
"""
|
||||
|
||||
_revision__ = "$Id$"
|
||||
|
||||
__all__ = ['new', 'digest_size', 'MD2Hash' ]
|
||||
|
||||
from Crypto.Util.py3compat import *
|
||||
from Crypto.Hash.hashalgo import HashAlgo
|
||||
|
||||
import Crypto.Hash._MD2 as _MD2
|
||||
hashFactory = _MD2
|
||||
|
||||
class MD2Hash(HashAlgo):
|
||||
"""Class that implements an MD2 hash
|
||||
|
||||
:undocumented: block_size
|
||||
"""
|
||||
|
||||
#: ASN.1 Object identifier (OID)::
|
||||
#:
|
||||
#: id-md2 OBJECT IDENTIFIER ::= {
|
||||
#: iso(1) member-body(2) us(840) rsadsi(113549)
|
||||
#: digestAlgorithm(2) 2
|
||||
#: }
|
||||
#:
|
||||
#: This value uniquely identifies the MD2 algorithm.
|
||||
oid = b('\x06\x08\x2a\x86\x48\x86\xf7\x0d\x02\x02')
|
||||
|
||||
digest_size = 16
|
||||
block_size = 16
|
||||
|
||||
def __init__(self, data=None):
|
||||
HashAlgo.__init__(self, hashFactory, data)
|
||||
|
||||
def new(self, data=None):
|
||||
return MD2Hash(data)
|
||||
|
||||
def new(data=None):
|
||||
"""Return a fresh instance of the hash object.
|
||||
|
||||
:Parameters:
|
||||
data : byte string
|
||||
The very first chunk of the message to hash.
|
||||
It is equivalent to an early call to `MD2Hash.update()`.
|
||||
Optional.
|
||||
|
||||
:Return: An `MD2Hash` object
|
||||
"""
|
||||
return MD2Hash().new(data)
|
||||
|
||||
#: The size of the resulting hash in bytes.
|
||||
digest_size = MD2Hash.digest_size
|
||||
|
||||
#: The internal block size of the hash algorithm in bytes.
|
||||
block_size = MD2Hash.block_size
|
||||
|
||||
@@ -0,0 +1,91 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# ===================================================================
|
||||
# The contents of this file are dedicated to the public domain. To
|
||||
# the extent that dedication to the public domain is not available,
|
||||
# everyone is granted a worldwide, perpetual, royalty-free,
|
||||
# non-exclusive license to exercise all rights associated with the
|
||||
# contents of this file for any purpose whatsoever.
|
||||
# No rights are reserved.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
# SOFTWARE.
|
||||
# ===================================================================
|
||||
|
||||
"""MD4 cryptographic hash algorithm.
|
||||
|
||||
MD4 is specified in RFC1320_ and produces the 128 bit digest of a message.
|
||||
|
||||
>>> from Crypto.Hash import MD4
|
||||
>>>
|
||||
>>> h = MD4.new()
|
||||
>>> h.update(b'Hello')
|
||||
>>> print h.hexdigest()
|
||||
|
||||
MD4 stand for Message Digest version 4, and it was invented by Rivest in 1990.
|
||||
|
||||
This algorithm is insecure. Do not use it for new designs.
|
||||
|
||||
.. _RFC1320: http://tools.ietf.org/html/rfc1320
|
||||
"""
|
||||
|
||||
_revision__ = "$Id$"
|
||||
|
||||
__all__ = ['new', 'digest_size', 'MD4Hash' ]
|
||||
|
||||
from Crypto.Util.py3compat import *
|
||||
from Crypto.Hash.hashalgo import HashAlgo
|
||||
|
||||
import Crypto.Hash._MD4 as _MD4
|
||||
hashFactory = _MD4
|
||||
|
||||
class MD4Hash(HashAlgo):
|
||||
"""Class that implements an MD4 hash
|
||||
|
||||
:undocumented: block_size
|
||||
"""
|
||||
|
||||
#: ASN.1 Object identifier (OID)::
|
||||
#:
|
||||
#: id-md2 OBJECT IDENTIFIER ::= {
|
||||
#: iso(1) member-body(2) us(840) rsadsi(113549)
|
||||
#: digestAlgorithm(2) 4
|
||||
#: }
|
||||
#:
|
||||
#: This value uniquely identifies the MD4 algorithm.
|
||||
oid = b('\x06\x08\x2a\x86\x48\x86\xf7\x0d\x02\x04')
|
||||
|
||||
digest_size = 16
|
||||
block_size = 64
|
||||
|
||||
def __init__(self, data=None):
|
||||
HashAlgo.__init__(self, hashFactory, data)
|
||||
|
||||
def new(self, data=None):
|
||||
return MD4Hash(data)
|
||||
|
||||
def new(data=None):
|
||||
"""Return a fresh instance of the hash object.
|
||||
|
||||
:Parameters:
|
||||
data : byte string
|
||||
The very first chunk of the message to hash.
|
||||
It is equivalent to an early call to `MD4Hash.update()`.
|
||||
Optional.
|
||||
|
||||
:Return: A `MD4Hash` object
|
||||
"""
|
||||
return MD4Hash().new(data)
|
||||
|
||||
#: The size of the resulting hash in bytes.
|
||||
digest_size = MD4Hash.digest_size
|
||||
|
||||
#: The internal block size of the hash algorithm in bytes.
|
||||
block_size = MD4Hash.block_size
|
||||
|
||||
+49
-44
@@ -35,58 +35,63 @@ This algorithm is insecure. Do not use it for new designs.
|
||||
.. _RFC1321: http://tools.ietf.org/html/rfc1321
|
||||
"""
|
||||
|
||||
from __future__ import nested_scopes
|
||||
|
||||
_revision__ = "$Id$"
|
||||
|
||||
__all__ = ['new', 'block_size', 'digest_size']
|
||||
__all__ = ['new', 'digest_size', 'MD5Hash' ]
|
||||
|
||||
from Crypto.Util.py3compat import *
|
||||
if sys.version_info[0] == 2 and sys.version_info[1] == 1:
|
||||
from Crypto.Util.py21compat import *
|
||||
from Crypto.Hash.hashalgo import HashAlgo
|
||||
|
||||
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
|
||||
try:
|
||||
# The md5 module is deprecated in Python 2.6, so use hashlib when possible.
|
||||
import hashlib
|
||||
hashFactory = hashlib.md5
|
||||
|
||||
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
|
||||
name = "md5"
|
||||
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
|
||||
except ImportError:
|
||||
import md5
|
||||
hashFactory = md5
|
||||
|
||||
new = __make_constructor()
|
||||
del __make_constructor
|
||||
class MD5Hash(HashAlgo):
|
||||
"""Class that implements an MD5 hash
|
||||
|
||||
:undocumented: block_size
|
||||
"""
|
||||
|
||||
#: ASN.1 Object identifier (OID)::
|
||||
#:
|
||||
#: id-md5 OBJECT IDENTIFIER ::= {
|
||||
#: iso(1) member-body(2) us(840) rsadsi(113549)
|
||||
#: digestAlgorithm(2) 5
|
||||
#: }
|
||||
#:
|
||||
#: This value uniquely identifies the MD5 algorithm.
|
||||
oid = b('\x06\x08\x2a\x86\x48\x86\xf7\x0d\x02\x05')
|
||||
|
||||
digest_size = 16
|
||||
block_size = 64
|
||||
|
||||
def __init__(self, data=None):
|
||||
HashAlgo.__init__(self, hashFactory, data)
|
||||
|
||||
def new(self, data=None):
|
||||
return MD5Hash(data)
|
||||
|
||||
def new(data=None):
|
||||
"""Return a fresh instance of the hash object.
|
||||
|
||||
:Parameters:
|
||||
data : byte string
|
||||
The very first chunk of the message to hash.
|
||||
It is equivalent to an early call to `MD5Hash.update()`.
|
||||
Optional.
|
||||
|
||||
:Return: A `MD5Hash` object
|
||||
"""
|
||||
return MD5Hash().new(data)
|
||||
|
||||
#: The size of the resulting hash in bytes.
|
||||
digest_size = new().digest_size
|
||||
digest_size = MD5Hash.digest_size
|
||||
|
||||
#: The internal block size of the hash algorithm in bytes.
|
||||
block_size = new().block_size
|
||||
block_size = MD5Hash.block_size
|
||||
|
||||
|
||||
@@ -18,9 +18,77 @@
|
||||
# SOFTWARE.
|
||||
# ===================================================================
|
||||
|
||||
# This file exists for backward compatibility with old code that refers to
|
||||
# Crypto.Hash.RIPEMD
|
||||
"""RIPEMD-160 cryptographic hash algorithm.
|
||||
|
||||
"""Deprecated alias for `Crypto.Hash.RIPEMD160`"""
|
||||
RIPEMD-160_ produces the 160 bit digest of a message.
|
||||
|
||||
>>> from Crypto.Hash import RIPEMD
|
||||
>>>
|
||||
>>> h = RIPEMD.new()
|
||||
>>> h.update(b'Hello')
|
||||
>>> print h.hexdigest()
|
||||
|
||||
RIPEMD-160 stands for RACE Integrity Primitives Evaluation Message Digest
|
||||
with a 160 bit digest. It was invented by Dobbertin, Bosselaers, and Preneel.
|
||||
|
||||
This algorithm is considered secure, although it has not been scrutinized as
|
||||
extensively as SHA-1. Moreover, it provides an informal security level of just
|
||||
80bits.
|
||||
|
||||
.. _RIPEMD-160: http://homes.esat.kuleuven.be/~bosselae/ripemd160.html
|
||||
"""
|
||||
|
||||
_revision__ = "$Id$"
|
||||
|
||||
__all__ = ['new', 'digest_size', 'RIPEMD160Hash' ]
|
||||
|
||||
from Crypto.Util.py3compat import *
|
||||
from Crypto.Hash.hashalgo import HashAlgo
|
||||
|
||||
import Crypto.Hash._RIPEMD160 as _RIPEMD160
|
||||
hashFactory = _RIPEMD160
|
||||
|
||||
class RIPEMD160Hash(HashAlgo):
|
||||
"""Class that implements a RIPMD-160 hash
|
||||
|
||||
:undocumented: block_size
|
||||
"""
|
||||
|
||||
#: ASN.1 Object identifier (OID)::
|
||||
#:
|
||||
#: id-ripemd160 OBJECT IDENTIFIER ::= {
|
||||
#: iso(1) identified-organization(3) teletrust(36)
|
||||
#: algorithm(3) hashAlgorithm(2) ripemd160(1)
|
||||
#: }
|
||||
#:
|
||||
#: This value uniquely identifies the RIPMD-160 algorithm.
|
||||
oid = b("\x06\x05\x2b\x24\x03\x02\x01")
|
||||
|
||||
digest_size = 20
|
||||
block_size = 64
|
||||
|
||||
def __init__(self, data=None):
|
||||
HashAlgo.__init__(self, hashFactory, data)
|
||||
|
||||
def new(self, data=None):
|
||||
return RIPEMD160Hash(data)
|
||||
|
||||
def new(data=None):
|
||||
"""Return a fresh instance of the hash object.
|
||||
|
||||
:Parameters:
|
||||
data : byte string
|
||||
The very first chunk of the message to hash.
|
||||
It is equivalent to an early call to `RIPEMD160Hash.update()`.
|
||||
Optional.
|
||||
|
||||
:Return: A `RIPEMD160Hash` object
|
||||
"""
|
||||
return RIPEMD160Hash().new(data)
|
||||
|
||||
#: The size of the resulting hash in bytes.
|
||||
digest_size = RIPEMD160Hash.digest_size
|
||||
|
||||
#: The internal block size of the hash algorithm in bytes.
|
||||
block_size = RIPEMD160Hash.block_size
|
||||
|
||||
from Crypto.Hash.RIPEMD160 import new, block_size, digest_size
|
||||
|
||||
@@ -18,7 +18,81 @@
|
||||
# SOFTWARE.
|
||||
# ===================================================================
|
||||
|
||||
# This file exists for backward compatibility with old code that refers to
|
||||
# Crypto.Hash.SHA
|
||||
"""SHA-1 cryptographic hash algorithm.
|
||||
|
||||
SHA-1_ produces the 160 bit digest of a message.
|
||||
|
||||
>>> from Crypto.Hash import SHA
|
||||
>>>
|
||||
>>> h = SHA.new()
|
||||
>>> h.update(b'Hello')
|
||||
>>> print h.hexdigest()
|
||||
|
||||
*SHA* stands for Secure Hash Algorithm.
|
||||
|
||||
This algorithm is not considered secure. Do not use it for new designs.
|
||||
|
||||
.. _SHA-1: http://csrc.nist.gov/publications/fips/fips180-2/fips180-2.pdf
|
||||
"""
|
||||
|
||||
_revision__ = "$Id$"
|
||||
|
||||
__all__ = ['new', 'digest_size', 'SHA1Hash' ]
|
||||
|
||||
from Crypto.Util.py3compat import *
|
||||
from Crypto.Hash.hashalgo import HashAlgo
|
||||
|
||||
try:
|
||||
# The sha module is deprecated in Python 2.6, so use hashlib when possible.
|
||||
import hashlib
|
||||
hashFactory = hashlib.sha1
|
||||
|
||||
except ImportError:
|
||||
import sha
|
||||
hashFactory = sha
|
||||
|
||||
class SHA1Hash(HashAlgo):
|
||||
"""Class that implements a SHA-1 hash
|
||||
|
||||
:undocumented: block_size
|
||||
"""
|
||||
|
||||
#: ASN.1 Object identifier (OID)::
|
||||
#:
|
||||
#: id-sha1 OBJECT IDENTIFIER ::= {
|
||||
#: iso(1) identified-organization(3) oiw(14) secsig(3)
|
||||
#: algorithms(2) 26
|
||||
#: }
|
||||
#:
|
||||
#: This value uniquely identifies the SHA-1 algorithm.
|
||||
oid = b('\x06\x05\x2b\x0e\x03\x02\x1a')
|
||||
|
||||
digest_size = 20
|
||||
block_size = 64
|
||||
|
||||
def __init__(self, data=None):
|
||||
HashAlgo.__init__(self, hashFactory, data)
|
||||
|
||||
def new(self, data=None):
|
||||
return SHA1Hash(data)
|
||||
|
||||
def new(data=None):
|
||||
"""Return a fresh instance of the hash object.
|
||||
|
||||
:Parameters:
|
||||
data : byte string
|
||||
The very first chunk of the message to hash.
|
||||
It is equivalent to an early call to `SHA1Hash.update()`.
|
||||
Optional.
|
||||
|
||||
:Return: A `SHA1Hash` object
|
||||
"""
|
||||
return SHA1Hash().new(data)
|
||||
|
||||
#: The size of the resulting hash in bytes.
|
||||
digest_size = SHA1Hash.digest_size
|
||||
|
||||
#: The internal block size of the hash algorithm in bytes.
|
||||
block_size = SHA1Hash.block_size
|
||||
|
||||
|
||||
from Crypto.Hash.SHA1 import __doc__, new, block_size, digest_size
|
||||
|
||||
@@ -0,0 +1,95 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# ===================================================================
|
||||
# The contents of this file are dedicated to the public domain. To
|
||||
# the extent that dedication to the public domain is not available,
|
||||
# everyone is granted a worldwide, perpetual, royalty-free,
|
||||
# non-exclusive license to exercise all rights associated with the
|
||||
# contents of this file for any purpose whatsoever.
|
||||
# No rights are reserved.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
# SOFTWARE.
|
||||
# ===================================================================
|
||||
|
||||
"""SHA-224 cryptographic hash algorithm.
|
||||
|
||||
SHA-224 belongs to the SHA-2_ family of cryptographic hashes.
|
||||
It produces the 224 bit digest of a message.
|
||||
|
||||
>>> from Crypto.Hash import SHA224
|
||||
>>>
|
||||
>>> h = SHA224.new()
|
||||
>>> h.update(b'Hello')
|
||||
>>> print h.hexdigest()
|
||||
|
||||
*SHA* stands for Secure Hash Algorithm.
|
||||
|
||||
.. _SHA-2: http://csrc.nist.gov/publications/fips/fips180-2/fips180-2.pdf
|
||||
"""
|
||||
|
||||
_revision__ = "$Id$"
|
||||
|
||||
__all__ = ['new', 'digest_size', 'SHA224Hash' ]
|
||||
|
||||
from Crypto.Util.py3compat import *
|
||||
from Crypto.Hash.hashalgo import HashAlgo
|
||||
|
||||
try:
|
||||
import hashlib
|
||||
hashFactory = hashlib.sha224
|
||||
|
||||
except ImportError:
|
||||
from Crypto.Hash import _SHA224
|
||||
hashFactory = _SHA224
|
||||
|
||||
class SHA224Hash(HashAlgo):
|
||||
"""Class that implements a SHA-224 hash
|
||||
|
||||
:undocumented: block_size
|
||||
"""
|
||||
|
||||
#: ASN.1 Object identifier (OID)::
|
||||
#:
|
||||
#: id-sha224 OBJECT IDENTIFIER ::= {
|
||||
#: joint-iso-itu-t(2) country(16) us(840) organization(1) gov(101) csor(3)
|
||||
#: nistalgorithm(4) hashalgs(2) 4
|
||||
#: }
|
||||
#:
|
||||
#: This value uniquely identifies the SHA-224 algorithm.
|
||||
oid = b('\x06\x09\x60\x86\x48\x01\x65\x03\x04\x02\x04')
|
||||
|
||||
digest_size = 28
|
||||
block_size = 64
|
||||
|
||||
def __init__(self, data=None):
|
||||
HashAlgo.__init__(self, hashFactory, data)
|
||||
|
||||
def new(self, data=None):
|
||||
return SHA224Hash(data)
|
||||
|
||||
def new(data=None):
|
||||
"""Return a fresh instance of the hash object.
|
||||
|
||||
:Parameters:
|
||||
data : byte string
|
||||
The very first chunk of the message to hash.
|
||||
It is equivalent to an early call to `SHA224Hash.update()`.
|
||||
Optional.
|
||||
|
||||
:Return: A `SHA224Hash` object
|
||||
"""
|
||||
return SHA224Hash().new(data)
|
||||
|
||||
#: The size of the resulting hash in bytes.
|
||||
digest_size = SHA224Hash.digest_size
|
||||
|
||||
#: The internal block size of the hash algorithm in bytes.
|
||||
block_size = SHA224Hash.block_size
|
||||
|
||||
@@ -0,0 +1,95 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# ===================================================================
|
||||
# The contents of this file are dedicated to the public domain. To
|
||||
# the extent that dedication to the public domain is not available,
|
||||
# everyone is granted a worldwide, perpetual, royalty-free,
|
||||
# non-exclusive license to exercise all rights associated with the
|
||||
# contents of this file for any purpose whatsoever.
|
||||
# No rights are reserved.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
# SOFTWARE.
|
||||
# ===================================================================
|
||||
|
||||
"""SHA-256 cryptographic hash algorithm.
|
||||
|
||||
SHA-256 belongs to the SHA-2_ family of cryptographic hashes.
|
||||
It produces the 256 bit digest of a message.
|
||||
|
||||
>>> from Crypto.Hash import SHA256
|
||||
>>>
|
||||
>>> h = SHA256.new()
|
||||
>>> h.update(b'Hello')
|
||||
>>> print h.hexdigest()
|
||||
|
||||
*SHA* stands for Secure Hash Algorithm.
|
||||
|
||||
.. _SHA-2: http://csrc.nist.gov/publications/fips/fips180-2/fips180-2.pdf
|
||||
"""
|
||||
|
||||
_revision__ = "$Id$"
|
||||
|
||||
__all__ = ['new', 'digest_size', 'SHA256Hash' ]
|
||||
|
||||
from Crypto.Util.py3compat import *
|
||||
from Crypto.Hash.hashalgo import HashAlgo
|
||||
|
||||
try:
|
||||
import hashlib
|
||||
hashFactory = hashlib.sha256
|
||||
|
||||
except ImportError:
|
||||
from Crypto.Hash import _SHA256
|
||||
hashFactory = _SHA256
|
||||
|
||||
class SHA256Hash(HashAlgo):
|
||||
"""Class that implements a SHA-256 hash
|
||||
|
||||
:undocumented: block_size
|
||||
"""
|
||||
|
||||
#: ASN.1 Object identifier (OID)::
|
||||
#:
|
||||
#: id-sha256 OBJECT IDENTIFIER ::= {
|
||||
#: joint-iso-itu-t(2) country(16) us(840) organization(1)
|
||||
#: gov(101) csor(3) nistalgorithm(4) hashalgs(2) 1
|
||||
#: }
|
||||
#:
|
||||
#: This value uniquely identifies the SHA-256 algorithm.
|
||||
oid = b('\x06\x09\x60\x86\x48\x01\x65\x03\x04\x02\x01')
|
||||
|
||||
digest_size = 32
|
||||
block_size = 64
|
||||
|
||||
def __init__(self, data=None):
|
||||
HashAlgo.__init__(self, hashFactory, data)
|
||||
|
||||
def new(self, data=None):
|
||||
return SHA256Hash(data)
|
||||
|
||||
def new(data=None):
|
||||
"""Return a fresh instance of the hash object.
|
||||
|
||||
:Parameters:
|
||||
data : byte string
|
||||
The very first chunk of the message to hash.
|
||||
It is equivalent to an early call to `SHA256Hash.update()`.
|
||||
Optional.
|
||||
|
||||
:Return: A `SHA256Hash` object
|
||||
"""
|
||||
return SHA256Hash().new(data)
|
||||
|
||||
#: The size of the resulting hash in bytes.
|
||||
digest_size = SHA256Hash.digest_size
|
||||
|
||||
#: The internal block size of the hash algorithm in bytes.
|
||||
block_size = SHA256Hash.block_size
|
||||
|
||||
@@ -0,0 +1,96 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# ===================================================================
|
||||
# The contents of this file are dedicated to the public domain. To
|
||||
# the extent that dedication to the public domain is not available,
|
||||
# everyone is granted a worldwide, perpetual, royalty-free,
|
||||
# non-exclusive license to exercise all rights associated with the
|
||||
# contents of this file for any purpose whatsoever.
|
||||
# No rights are reserved.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
# SOFTWARE.
|
||||
# ===================================================================
|
||||
|
||||
"""SHA-384 cryptographic hash algorithm.
|
||||
|
||||
SHA-384 belongs to the SHA-2_ family of cryptographic hashes.
|
||||
It produces the 384 bit digest of a message.
|
||||
|
||||
>>> from Crypto.Hash import SHA384
|
||||
>>>
|
||||
>>> h = SHA384.new()
|
||||
>>> h.update(b'Hello')
|
||||
>>> print h.hexdigest()
|
||||
|
||||
*SHA* stands for Secure Hash Algorithm.
|
||||
|
||||
.. _SHA-2: http://csrc.nist.gov/publications/fips/fips180-2/fips180-2.pdf
|
||||
"""
|
||||
|
||||
_revision__ = "$Id$"
|
||||
|
||||
__all__ = ['new', 'digest_size', 'SHA384Hash' ]
|
||||
|
||||
from Crypto.Util.py3compat import *
|
||||
from Crypto.Hash.hashalgo import HashAlgo
|
||||
|
||||
try:
|
||||
import hashlib
|
||||
hashFactory = hashlib.sha384
|
||||
|
||||
except ImportError:
|
||||
from Crypto.Hash import _SHA384
|
||||
hashFactory = _SHA384
|
||||
|
||||
class SHA384Hash(HashAlgo):
|
||||
"""Class that implements a SHA-384 hash
|
||||
|
||||
:undocumented: block_size
|
||||
"""
|
||||
|
||||
#: ASN.1 Object identifier (OID)::
|
||||
#:
|
||||
#: id-sha384 OBJECT IDENTIFIER ::= {
|
||||
#: joint-iso-itu-t(2) country(16) us(840) organization(1) gov(101) csor(3)
|
||||
#: nistalgorithm(4) hashalgs(2) 2
|
||||
#: }
|
||||
#:
|
||||
#: This value uniquely identifies the SHA-384 algorithm.
|
||||
oid = b('\x06\x09\x60\x86\x48\x01\x65\x03\x04\x02\x02')
|
||||
|
||||
digest_size = 48
|
||||
block_size = 128
|
||||
|
||||
def __init__(self, data=None):
|
||||
HashAlgo.__init__(self, hashFactory, data)
|
||||
|
||||
def new(self, data=None):
|
||||
return SHA384Hash(data)
|
||||
|
||||
def new(data=None):
|
||||
"""Return a fresh instance of the hash object.
|
||||
|
||||
:Parameters:
|
||||
data : byte string
|
||||
The very first chunk of the message to hash.
|
||||
It is equivalent to an early call to `SHA384Hash.update()`.
|
||||
Optional.
|
||||
|
||||
:Return: A `SHA384Hash` object
|
||||
"""
|
||||
return SHA384Hash().new(data)
|
||||
|
||||
#: The size of the resulting hash in bytes.
|
||||
digest_size = SHA384Hash.digest_size
|
||||
|
||||
#: The internal block size of the hash algorithm in bytes.
|
||||
block_size = SHA384Hash.block_size
|
||||
|
||||
|
||||
@@ -0,0 +1,95 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# ===================================================================
|
||||
# The contents of this file are dedicated to the public domain. To
|
||||
# the extent that dedication to the public domain is not available,
|
||||
# everyone is granted a worldwide, perpetual, royalty-free,
|
||||
# non-exclusive license to exercise all rights associated with the
|
||||
# contents of this file for any purpose whatsoever.
|
||||
# No rights are reserved.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
# SOFTWARE.
|
||||
# ===================================================================
|
||||
|
||||
"""SHA-512 cryptographic hash algorithm.
|
||||
|
||||
SHA-512 belongs to the SHA-2_ family of cryptographic hashes.
|
||||
It produces the 512 bit digest of a message.
|
||||
|
||||
>>> from Crypto.Hash import SHA512
|
||||
>>>
|
||||
>>> h = SHA512.new()
|
||||
>>> h.update(b'Hello')
|
||||
>>> print h.hexdigest()
|
||||
|
||||
*SHA* stands for Secure Hash Algorithm.
|
||||
|
||||
.. _SHA-2: http://csrc.nist.gov/publications/fips/fips180-2/fips180-2.pdf
|
||||
"""
|
||||
|
||||
_revision__ = "$Id$"
|
||||
|
||||
__all__ = ['new', 'digest_size', 'SHA512Hash' ]
|
||||
|
||||
from Crypto.Util.py3compat import *
|
||||
from Crypto.Hash.hashalgo import HashAlgo
|
||||
|
||||
try:
|
||||
import hashlib
|
||||
hashFactory = hashlib.sha512
|
||||
|
||||
except ImportError:
|
||||
from Crypto.Hash import _SHA512
|
||||
hashFactory = _SHA512
|
||||
|
||||
class SHA512Hash(HashAlgo):
|
||||
"""Class that implements a SHA-512 hash
|
||||
|
||||
:undocumented: block_size
|
||||
"""
|
||||
|
||||
#: ASN.1 Object identifier (OID)::
|
||||
#:
|
||||
#: id-sha512 OBJECT IDENTIFIER ::= {
|
||||
#: joint-iso-itu-t(2)
|
||||
#: country(16) us(840) organization(1) gov(101) csor(3) nistalgorithm(4) hashalgs(2) 3
|
||||
#: }
|
||||
#:
|
||||
#: This value uniquely identifies the SHA-512 algorithm.
|
||||
oid = b('\x06\x09\x60\x86\x48\x01\x65\x03\x04\x02\x03')
|
||||
|
||||
digest_size = 64
|
||||
block_size = 128
|
||||
|
||||
def __init__(self, data=None):
|
||||
HashAlgo.__init__(self, hashFactory, data)
|
||||
|
||||
def new(self, data=None):
|
||||
return SHA512Hash(data)
|
||||
|
||||
def new(data=None):
|
||||
"""Return a fresh instance of the hash object.
|
||||
|
||||
:Parameters:
|
||||
data : byte string
|
||||
The very first chunk of the message to hash.
|
||||
It is equivalent to an early call to `SHA512Hash.update()`.
|
||||
Optional.
|
||||
|
||||
:Return: A `SHA512Hash` object
|
||||
"""
|
||||
return SHA512Hash().new(data)
|
||||
|
||||
#: The size of the resulting hash in bytes.
|
||||
digest_size = SHA512Hash.digest_size
|
||||
|
||||
#: The internal block size of the hash algorithm in bytes.
|
||||
block_size = SHA512Hash.block_size
|
||||
|
||||
Executable
BIN
Binary file not shown.
Executable
BIN
Binary file not shown.
Executable
BIN
Binary file not shown.
Executable
BIN
Binary file not shown.
Executable
BIN
Binary file not shown.
Executable
BIN
Binary file not shown.
Executable
BIN
Binary file not shown.
@@ -49,128 +49,8 @@ The hashing modules here all support the interface described in `PEP
|
||||
:undocumented: _MD2, _MD4, _RIPEMD160, _SHA224, _SHA256, _SHA384, _SHA512
|
||||
"""
|
||||
|
||||
__all__ = ['HMAC', 'MD2', 'MD4', 'MD5', 'RIPEMD160', 'SHA1',
|
||||
'SHA224', 'SHA256', 'SHA384', 'SHA512', 'CMAC']
|
||||
|
||||
__all__ = ['HMAC', 'MD2', 'MD4', 'MD5', 'RIPEMD', 'SHA',
|
||||
'SHA224', 'SHA256', 'SHA384', 'SHA512']
|
||||
__revision__ = "$Id$"
|
||||
|
||||
import sys
|
||||
if sys.version_info[0] == 2 and sys.version_info[1] == 1:
|
||||
from Crypto.Util.py21compat import *
|
||||
from Crypto.Util.py3compat import *
|
||||
|
||||
def new(algo, *args):
|
||||
"""Initialize a new hash object.
|
||||
|
||||
The first argument to this function may be an algorithm name or another
|
||||
hash object.
|
||||
|
||||
This function has significant overhead. It's recommended that you instead
|
||||
import and use the individual hash modules directly.
|
||||
"""
|
||||
|
||||
# Try just invoking algo.new()
|
||||
# We do this first so that this is the fastest.
|
||||
try:
|
||||
new_func = algo.new
|
||||
except AttributeError:
|
||||
pass
|
||||
else:
|
||||
return new_func(*args)
|
||||
|
||||
# Try getting the algorithm name.
|
||||
if isinstance(algo, str):
|
||||
name = algo
|
||||
else:
|
||||
try:
|
||||
name = algo.name
|
||||
except AttributeError:
|
||||
raise ValueError("unsupported hash type %r" % (algo,))
|
||||
|
||||
# Got the name. Let's see if we have a PyCrypto implementation.
|
||||
try:
|
||||
new_func = _new_funcs[name]
|
||||
except KeyError:
|
||||
# No PyCrypto implementation. Try hashlib.
|
||||
try:
|
||||
import hashlib
|
||||
except ImportError:
|
||||
# There is no hashlib.
|
||||
raise ValueError("unsupported hash type %s" % (name,))
|
||||
return hashlib.new(name, *args)
|
||||
else:
|
||||
# We have a PyCrypto implementation. Instantiate it.
|
||||
return new_func(*args)
|
||||
|
||||
# This dict originally gets the following _*_new methods, but its members get
|
||||
# replaced with the real new() methods of the various hash modules as they are
|
||||
# used. We do it without locks to improve performance, which is safe in
|
||||
# CPython because dict access is atomic in CPython. This might break PyPI.
|
||||
_new_funcs = {}
|
||||
|
||||
def _md2_new(*args):
|
||||
from Crypto.Hash import MD2
|
||||
_new_funcs['MD2'] = _new_funcs['md2'] = MD2.new
|
||||
return MD2.new(*args)
|
||||
_new_funcs['MD2'] = _new_funcs['md2'] = _md2_new
|
||||
del _md2_new
|
||||
|
||||
def _md4_new(*args):
|
||||
from Crypto.Hash import MD4
|
||||
_new_funcs['MD4'] = _new_funcs['md4'] = MD4.new
|
||||
return MD4.new(*args)
|
||||
_new_funcs['MD4'] = _new_funcs['md4'] = _md4_new
|
||||
del _md4_new
|
||||
|
||||
def _md5_new(*args):
|
||||
from Crypto.Hash import MD5
|
||||
_new_funcs['MD5'] = _new_funcs['md5'] = MD5.new
|
||||
return MD5.new(*args)
|
||||
_new_funcs['MD5'] = _new_funcs['md5'] = _md5_new
|
||||
del _md5_new
|
||||
|
||||
def _ripemd160_new(*args):
|
||||
from Crypto.Hash import RIPEMD160
|
||||
_new_funcs['RIPEMD160'] = _new_funcs['ripemd160'] = \
|
||||
_new_funcs['RIPEMD'] = _new_funcs['ripemd'] = RIPEMD160.new
|
||||
return RIPEMD160.new(*args)
|
||||
_new_funcs['RIPEMD160'] = _new_funcs['ripemd160'] = \
|
||||
_new_funcs['RIPEMD'] = _new_funcs['ripemd'] = _ripemd160_new
|
||||
del _ripemd160_new
|
||||
|
||||
def _sha1_new(*args):
|
||||
from Crypto.Hash import SHA1
|
||||
_new_funcs['SHA1'] = _new_funcs['sha1'] = \
|
||||
_new_funcs['SHA'] = _new_funcs['sha'] = SHA1.new
|
||||
return SHA1.new(*args)
|
||||
_new_funcs['SHA1'] = _new_funcs['sha1'] = \
|
||||
_new_funcs['SHA'] = _new_funcs['sha'] = _sha1_new
|
||||
del _sha1_new
|
||||
|
||||
def _sha224_new(*args):
|
||||
from Crypto.Hash import SHA224
|
||||
_new_funcs['SHA224'] = _new_funcs['sha224'] = SHA224.new
|
||||
return SHA224.new(*args)
|
||||
_new_funcs['SHA224'] = _new_funcs['sha224'] = _sha224_new
|
||||
del _sha224_new
|
||||
|
||||
def _sha256_new(*args):
|
||||
from Crypto.Hash import SHA256
|
||||
_new_funcs['SHA256'] = _new_funcs['sha256'] = SHA256.new
|
||||
return SHA256.new(*args)
|
||||
_new_funcs['SHA256'] = _new_funcs['sha256'] = _sha256_new
|
||||
del _sha256_new
|
||||
|
||||
def _sha384_new(*args):
|
||||
from Crypto.Hash import SHA384
|
||||
_new_funcs['SHA384'] = _new_funcs['sha384'] = SHA384.new
|
||||
return SHA384.new(*args)
|
||||
_new_funcs['SHA384'] = _new_funcs['sha384'] = _sha384_new
|
||||
del _sha384_new
|
||||
|
||||
def _sha512_new(*args):
|
||||
from Crypto.Hash import SHA512
|
||||
_new_funcs['SHA512'] = _new_funcs['sha512'] = SHA512.new
|
||||
return SHA512.new(*args)
|
||||
_new_funcs['SHA512'] = _new_funcs['sha512'] = _sha512_new
|
||||
del _sha512_new
|
||||
|
||||
@@ -0,0 +1,116 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# ===================================================================
|
||||
# The contents of this file are dedicated to the public domain. To
|
||||
# the extent that dedication to the public domain is not available,
|
||||
# everyone is granted a worldwide, perpetual, royalty-free,
|
||||
# non-exclusive license to exercise all rights associated with the
|
||||
# contents of this file for any purpose whatsoever.
|
||||
# No rights are reserved.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
# SOFTWARE.
|
||||
# ===================================================================
|
||||
|
||||
from binascii import hexlify
|
||||
|
||||
class HashAlgo:
|
||||
"""A generic class for an abstract cryptographic hash algorithm.
|
||||
|
||||
:undocumented: block_size
|
||||
"""
|
||||
|
||||
#: The size of the resulting hash in bytes.
|
||||
digest_size = None
|
||||
#: The internal block size of the hash algorithm in bytes.
|
||||
block_size = None
|
||||
|
||||
def __init__(self, hashFactory, data=None):
|
||||
"""Initialize the hash object.
|
||||
|
||||
:Parameters:
|
||||
hashFactory : callable
|
||||
An object that will generate the actual hash implementation.
|
||||
*hashFactory* must have a *new()* method, or must be directly
|
||||
callable.
|
||||
data : byte string
|
||||
The very first chunk of the message to hash.
|
||||
It is equivalent to an early call to `update()`.
|
||||
"""
|
||||
if hasattr(hashFactory, 'new'):
|
||||
self._hash = hashFactory.new()
|
||||
else:
|
||||
self._hash = hashFactory()
|
||||
if data:
|
||||
self.update(data)
|
||||
|
||||
def update(self, data):
|
||||
"""Continue hashing of a message by consuming the next chunk of data.
|
||||
|
||||
Repeated calls are equivalent to a single call with the concatenation
|
||||
of all the arguments. In other words:
|
||||
|
||||
>>> m.update(a); m.update(b)
|
||||
|
||||
is equivalent to:
|
||||
|
||||
>>> m.update(a+b)
|
||||
|
||||
:Parameters:
|
||||
data : byte string
|
||||
The next chunk of the message being hashed.
|
||||
"""
|
||||
return self._hash.update(data)
|
||||
|
||||
def digest(self):
|
||||
"""Return the **binary** (non-printable) digest of the message that has been hashed so far.
|
||||
|
||||
This method does not change the state of the hash object.
|
||||
You can continue updating the object after calling this function.
|
||||
|
||||
:Return: A byte string of `digest_size` bytes. It may contain non-ASCII
|
||||
characters, including null bytes.
|
||||
"""
|
||||
return self._hash.digest()
|
||||
|
||||
def hexdigest(self):
|
||||
"""Return the **printable** digest of the message that has been hashed so far.
|
||||
|
||||
This method does not change the state of the hash object.
|
||||
|
||||
:Return: A string of 2* `digest_size` characters. It contains only
|
||||
hexadecimal ASCII digits.
|
||||
"""
|
||||
return self._hash.hexdigest()
|
||||
|
||||
def copy(self):
|
||||
"""Return a copy ("clone") of the hash object.
|
||||
|
||||
The copy will have the same internal state as the original hash
|
||||
object.
|
||||
This can be used to efficiently compute the digests of strings that
|
||||
share a common initial substring.
|
||||
|
||||
:Return: A hash object of the same type
|
||||
"""
|
||||
return self._hash.copy()
|
||||
|
||||
def new(self, data=None):
|
||||
"""Return a fresh instance of the hash object.
|
||||
|
||||
Unlike the `copy` method, the internal state of the object is empty.
|
||||
|
||||
:Parameters:
|
||||
data : byte string
|
||||
The next chunk of the message being hashed.
|
||||
|
||||
:Return: A hash object of the same type
|
||||
"""
|
||||
pass
|
||||
|
||||
@@ -38,21 +38,16 @@ __revision__ = "$Id$"
|
||||
import math
|
||||
import struct
|
||||
|
||||
import sys
|
||||
if sys.version_info[0] == 2 and sys.version_info[1] == 1:
|
||||
from Crypto.Util.py21compat import *
|
||||
from Crypto.Util.py3compat import *
|
||||
|
||||
from Crypto.Hash import SHA1, HMAC, CMAC
|
||||
from Crypto.Hash import SHA as SHA1, HMAC
|
||||
from Crypto.Util.strxor import strxor
|
||||
from Crypto.Util.number import long_to_bytes, bytes_to_long
|
||||
|
||||
def PBKDF1(password, salt, dkLen, count=1000, hashAlgo=None):
|
||||
"""Derive one key from a password (or passphrase).
|
||||
|
||||
This function performs key derivation according an old version of
|
||||
the PKCS#5 standard (v1.5).
|
||||
|
||||
|
||||
This algorithm is called ``PBKDF1``. Even though it is still described
|
||||
in the latest version of the PKCS#5 standard (version 2, or RFC2898),
|
||||
newer applications should use the more secure and versatile `PBKDF2` instead.
|
||||
@@ -81,7 +76,7 @@ def PBKDF1(password, salt, dkLen, count=1000, hashAlgo=None):
|
||||
pHash = hashAlgo.new(password+salt)
|
||||
digest = pHash.digest_size
|
||||
if dkLen>digest:
|
||||
raise TypeError("Selected hash algorithm has a too short digest (%d bytes)." % digest)
|
||||
raise ValueError("Selected hash algorithm has a too short digest (%d bytes)." % digest)
|
||||
if len(salt)!=8:
|
||||
raise ValueError("Salt is not 8 bytes long.")
|
||||
for i in xrange(count-1):
|
||||
@@ -126,84 +121,3 @@ def PBKDF2(password, salt, dkLen=16, count=1000, prf=None):
|
||||
i = i + 1
|
||||
return key[:dkLen]
|
||||
|
||||
class _S2V(object):
|
||||
"""String-to-vector PRF as defined in `RFC5297`_.
|
||||
|
||||
This class implements a pseudorandom function family
|
||||
based on CMAC that takes as input a vector of strings.
|
||||
|
||||
.. _RFC5297: http://tools.ietf.org/html/rfc5297
|
||||
"""
|
||||
|
||||
def __init__(self, key, ciphermod):
|
||||
"""Initialize the S2V PRF.
|
||||
|
||||
:Parameters:
|
||||
key : byte string
|
||||
A secret that can be used as key for CMACs
|
||||
based on ciphers from ``ciphermod``.
|
||||
ciphermod : module
|
||||
A block cipher module from `Crypto.Cipher`.
|
||||
"""
|
||||
|
||||
self._key = key
|
||||
self._ciphermod = ciphermod
|
||||
self._last_string = self._cache = bchr(0)*ciphermod.block_size
|
||||
self._n_updates = ciphermod.block_size*8-1
|
||||
|
||||
def new(key, ciphermod):
|
||||
"""Create a new S2V PRF.
|
||||
|
||||
:Parameters:
|
||||
key : byte string
|
||||
A secret that can be used as key for CMACs
|
||||
based on ciphers from ``ciphermod``.
|
||||
ciphermod : module
|
||||
A block cipher module from `Crypto.Cipher`.
|
||||
"""
|
||||
return _S2V(key, ciphermod)
|
||||
new = staticmethod(new)
|
||||
|
||||
def _double(self, bs):
|
||||
doubled = bytes_to_long(bs)<<1
|
||||
if bord(bs[0]) & 0x80:
|
||||
doubled ^= 0x87
|
||||
return long_to_bytes(doubled, len(bs))[-len(bs):]
|
||||
|
||||
def update(self, item):
|
||||
"""Pass the next component of the vector.
|
||||
|
||||
The maximum number of components you can pass is equal to the block
|
||||
length of the cipher (in bits) minus 1.
|
||||
|
||||
:Parameters:
|
||||
item : byte string
|
||||
The next component of the vector.
|
||||
:Raise TypeError: when the limit on the number of components has been reached.
|
||||
:Raise ValueError: when the component is empty
|
||||
"""
|
||||
|
||||
if not item:
|
||||
raise ValueError("A component cannot be empty")
|
||||
|
||||
if self._n_updates==0:
|
||||
raise TypeError("Too many components passed to S2V")
|
||||
self._n_updates -= 1
|
||||
|
||||
mac = CMAC.new(self._key, msg=self._last_string, ciphermod=self._ciphermod)
|
||||
self._cache = strxor(self._double(self._cache), mac.digest())
|
||||
self._last_string = item
|
||||
|
||||
def derive(self):
|
||||
""""Derive a secret from the vector of components.
|
||||
|
||||
:Return: a byte string, as long as the block length of the cipher.
|
||||
"""
|
||||
|
||||
if len(self._last_string)>=16:
|
||||
final = self._last_string[:-16] + strxor(self._last_string[-16:], self._cache)
|
||||
else:
|
||||
padded = (self._last_string + bchr(0x80)+ bchr(0)*15)[:16]
|
||||
final = strxor(padded, self._double(self._cache))
|
||||
mac = CMAC.new(self._key, msg=final, ciphermod=self._ciphermod)
|
||||
return mac.digest()
|
||||
|
||||
@@ -59,20 +59,14 @@ verification.
|
||||
|
||||
>>> from Crypto.Random import random
|
||||
>>> from Crypto.PublicKey import DSA
|
||||
>>> from Crypto.Hash import SHA256
|
||||
>>> from Crypto.Hash import SHA
|
||||
>>>
|
||||
>>> message = "Hello"
|
||||
>>> key = DSA.generate(2048)
|
||||
>>> f = open("public_key.pem", "w")
|
||||
>>> f.write(key.publickey().exportKey(key))
|
||||
>>> h = SHA256.new(message).digest()
|
||||
>>> key = DSA.generate(1024)
|
||||
>>> h = SHA.new(message).digest()
|
||||
>>> k = random.StrongRandom().randint(1,key.q-1)
|
||||
>>> sig = key.sign(h,k)
|
||||
>>> ...
|
||||
>>> ...
|
||||
>>> f = open("public_key.pem", "r")
|
||||
>>> h = SHA256.new(message).digest()
|
||||
>>> key = DSA.importKey(f.read())
|
||||
>>> if key.verify(h,sig):
|
||||
>>> print "OK"
|
||||
>>> else:
|
||||
@@ -85,64 +79,20 @@ verification.
|
||||
|
||||
__revision__ = "$Id$"
|
||||
|
||||
__all__ = ['generate', 'construct', 'error', 'DSAImplementation',
|
||||
'_DSAobj', 'importKey']
|
||||
|
||||
import binascii
|
||||
import struct
|
||||
__all__ = ['generate', 'construct', 'error', 'DSAImplementation', '_DSAobj']
|
||||
|
||||
import sys
|
||||
if sys.version_info[0] == 2 and sys.version_info[1] == 1:
|
||||
from Crypto.Util.py21compat import *
|
||||
from Crypto.Util.py3compat import *
|
||||
|
||||
from Crypto.PublicKey import _DSA, _slowmath, pubkey
|
||||
from Crypto import Random
|
||||
from Crypto.IO import PKCS8, PEM
|
||||
from Crypto.Util.number import bytes_to_long, long_to_bytes
|
||||
from Crypto.PublicKey import _DSA, _slowmath, pubkey, KeyFormatError
|
||||
from Crypto.Util.asn1 import DerObject, DerSequence,\
|
||||
DerInteger, DerObjectId, DerBitString, newDerSequence, newDerBitString
|
||||
|
||||
try:
|
||||
from Crypto.PublicKey import _fastmath
|
||||
except ImportError:
|
||||
_fastmath = None
|
||||
|
||||
def decode_der(obj_class, binstr):
|
||||
"""Instantiate a DER object class, decode a DER binary string in it,
|
||||
and return the object."""
|
||||
der = obj_class()
|
||||
der.decode(binstr)
|
||||
return der
|
||||
|
||||
# ; The following ASN.1 types are relevant for DSA
|
||||
#
|
||||
# SubjectPublicKeyInfo ::= SEQUENCE {
|
||||
# algorithm AlgorithmIdentifier,
|
||||
# subjectPublicKey BIT STRING
|
||||
# }
|
||||
#
|
||||
# id-dsa ID ::= { iso(1) member-body(2) us(840) x9-57(10040) x9cm(4) 1 }
|
||||
#
|
||||
# ; See RFC3279
|
||||
# Dss-Parms ::= SEQUENCE {
|
||||
# p INTEGER,
|
||||
# q INTEGER,
|
||||
# g INTEGER
|
||||
# }
|
||||
#
|
||||
# DSAPublicKey ::= INTEGER
|
||||
#
|
||||
# DSSPrivatKey_OpenSSL ::= SEQUENCE
|
||||
# version INTEGER,
|
||||
# p INTEGER,
|
||||
# q INTEGER,
|
||||
# g INTEGER,
|
||||
# y INTEGER,
|
||||
# x INTEGER
|
||||
# }
|
||||
#
|
||||
|
||||
class _DSAobj(pubkey.pubkey):
|
||||
"""Class defining an actual DSA key.
|
||||
|
||||
@@ -162,12 +112,9 @@ class _DSAobj(pubkey.pubkey):
|
||||
#: - **x**, the private key.
|
||||
keydata = ['y', 'g', 'p', 'q', 'x']
|
||||
|
||||
def __init__(self, implementation, key, randfunc=None):
|
||||
def __init__(self, implementation, key):
|
||||
self.implementation = implementation
|
||||
self.key = key
|
||||
if randfunc is None:
|
||||
randfunc = Random.new().read
|
||||
self._randfunc = randfunc
|
||||
|
||||
def __getattr__(self, attrname):
|
||||
if attrname in self.keydata:
|
||||
@@ -270,8 +217,6 @@ class _DSAobj(pubkey.pubkey):
|
||||
def __setstate__(self, d):
|
||||
if not hasattr(self, 'implementation'):
|
||||
self.implementation = DSAImplementation()
|
||||
if not hasattr(self, '_randfunc'):
|
||||
self._randfunc = Random.new().read
|
||||
t = []
|
||||
for k in self.keydata:
|
||||
if not d.has_key(k):
|
||||
@@ -291,124 +236,6 @@ class _DSAobj(pubkey.pubkey):
|
||||
# PY3K: This is meant to be text, do not change to bytes (data)
|
||||
return "<%s @0x%x %s>" % (self.__class__.__name__, id(self), ",".join(attrs))
|
||||
|
||||
def exportKey(self, format='PEM', pkcs8=None, passphrase=None,
|
||||
protection=None):
|
||||
"""Export this DSA key.
|
||||
|
||||
:Parameters:
|
||||
format : string
|
||||
The format to use for wrapping the key:
|
||||
|
||||
- *'DER'*. Binary encoding.
|
||||
- *'PEM'*. Textual encoding, done according to `RFC1421`_/
|
||||
`RFC1423`_ (default).
|
||||
- *'OpenSSH'*. Textual encoding, one line of text, see `RFC4253`_.
|
||||
Only suitable for public keys, not private keys.
|
||||
|
||||
passphrase : string
|
||||
For private keys only. The pass phrase to use for deriving
|
||||
the encryption key.
|
||||
|
||||
pkcs8 : boolean
|
||||
For private keys only. If ``True`` (default), the key is arranged
|
||||
according to `PKCS#8`_ and if `False`, according to the custom
|
||||
OpenSSL/OpenSSH encoding.
|
||||
|
||||
protection : string
|
||||
The encryption scheme to use for protecting the private key.
|
||||
It is only meaningful when a pass phrase is present too.
|
||||
|
||||
If ``pkcs8`` takes value ``True``, ``protection`` is the PKCS#8
|
||||
algorithm to use for deriving the secret and encrypting
|
||||
the private DSA key.
|
||||
For a complete list of algorithms, see `Crypto.IO.PKCS8`.
|
||||
The default is *PBKDF2WithHMAC-SHA1AndDES-EDE3-CBC*.
|
||||
|
||||
If ``pkcs8`` is ``False``, the obsolete PEM encryption scheme is
|
||||
used. It is based on MD5 for key derivation, and Triple DES for
|
||||
encryption. Parameter ``protection`` is ignored.
|
||||
|
||||
The combination ``format='DER'`` and ``pkcs8=False`` is not allowed
|
||||
if a passphrase is present.
|
||||
|
||||
:Return: A byte string with the encoded public or private half
|
||||
of the key.
|
||||
:Raise ValueError:
|
||||
When the format is unknown or when you try to encrypt a private
|
||||
key with *DER* format and OpenSSL/OpenSSH.
|
||||
:attention:
|
||||
If you don't provide a pass phrase, the private key will be
|
||||
exported in the clear!
|
||||
|
||||
.. _RFC1421: http://www.ietf.org/rfc/rfc1421.txt
|
||||
.. _RFC1423: http://www.ietf.org/rfc/rfc1423.txt
|
||||
.. _RFC4253: http://www.ietf.org/rfc/rfc4253.txt
|
||||
.. _`PKCS#8`: http://www.ietf.org/rfc/rfc5208.txt
|
||||
"""
|
||||
if passphrase is not None:
|
||||
passphrase = tobytes(passphrase)
|
||||
if format == 'OpenSSH':
|
||||
tup1 = [long_to_bytes(x) for x in (self.p, self.q, self.g, self.y)]
|
||||
|
||||
def func(x):
|
||||
if (bord(x[0]) & 0x80):
|
||||
return bchr(0) + x
|
||||
else:
|
||||
return x
|
||||
|
||||
tup2 = map(func, tup1)
|
||||
keyparts = [b('ssh-dss')] + tup2
|
||||
keystring = b('').join(
|
||||
[struct.pack(">I", len(kp)) + kp for kp in keyparts]
|
||||
)
|
||||
return b('ssh-dss ') + binascii.b2a_base64(keystring)[:-1]
|
||||
|
||||
# DER format is always used, even in case of PEM, which simply
|
||||
# encodes it into BASE64.
|
||||
params = newDerSequence(self.p, self.q, self.g)
|
||||
if self.has_private():
|
||||
if pkcs8 is None:
|
||||
pkcs8 = True
|
||||
if pkcs8:
|
||||
if not protection:
|
||||
protection = 'PBKDF2WithHMAC-SHA1AndDES-EDE3-CBC'
|
||||
private_key = DerInteger(self.x).encode()
|
||||
binary_key = PKCS8.wrap(
|
||||
private_key, oid, passphrase,
|
||||
protection, key_params=params,
|
||||
randfunc=self._randfunc
|
||||
)
|
||||
if passphrase:
|
||||
key_type = 'ENCRYPTED PRIVATE'
|
||||
else:
|
||||
key_type = 'PRIVATE'
|
||||
passphrase = None
|
||||
else:
|
||||
if format != 'PEM' and passphrase:
|
||||
raise ValueError("DSA private key cannot be encrypted")
|
||||
ints = [0, self.p, self.q, self.g, self.y, self.x]
|
||||
binary_key = newDerSequence(*ints).encode()
|
||||
key_type = "DSA PRIVATE"
|
||||
else:
|
||||
if pkcs8:
|
||||
raise ValueError("PKCS#8 is only meaningful for private keys")
|
||||
binary_key = newDerSequence(
|
||||
newDerSequence(DerObjectId(oid), params),
|
||||
newDerBitString(DerInteger(self.y))
|
||||
).encode()
|
||||
key_type = "DSA PUBLIC"
|
||||
|
||||
if format == 'DER':
|
||||
return binary_key
|
||||
if format == 'PEM':
|
||||
pem_str = PEM.encode(
|
||||
binary_key, key_type + " KEY",
|
||||
passphrase, self._randfunc
|
||||
)
|
||||
return tobytes(pem_str)
|
||||
raise ValueError("Unknown key format '%s'. Cannot export the DSA key." % format)
|
||||
|
||||
|
||||
class DSAImplementation(object):
|
||||
"""
|
||||
A DSA key factory.
|
||||
@@ -416,7 +243,7 @@ class DSAImplementation(object):
|
||||
This class is only internally used to implement the methods of the
|
||||
`Crypto.PublicKey.DSA` module.
|
||||
"""
|
||||
|
||||
|
||||
def __init__(self, **kwargs):
|
||||
"""Create a new DSA key factory.
|
||||
|
||||
@@ -543,139 +370,9 @@ class DSAImplementation(object):
|
||||
key = self._math.dsa_construct(*tup)
|
||||
return _DSAobj(self, key)
|
||||
|
||||
def _importKeyDER(self, key_data, passphrase=None, params=None):
|
||||
"""Import a DSA key (public or private half), encoded in DER form."""
|
||||
|
||||
try:
|
||||
#
|
||||
# Dss-Parms ::= SEQUENCE {
|
||||
# p OCTET STRING,
|
||||
# q OCTET STRING,
|
||||
# g OCTET STRING
|
||||
# }
|
||||
#
|
||||
|
||||
# Try a simple private key first
|
||||
if params:
|
||||
x = decode_der(DerInteger, key_data).value
|
||||
params = decode_der(DerSequence, params) # Dss-Parms
|
||||
p, q, g = list(params)
|
||||
y = pow(g, x, p)
|
||||
tup = (y, g, p, q, x)
|
||||
return self.construct(tup)
|
||||
|
||||
der = decode_der(DerSequence, key_data)
|
||||
|
||||
# Try OpenSSL format for private keys
|
||||
if len(der) == 6 and der.hasOnlyInts() and der[0] == 0:
|
||||
tup = [der[comp] for comp in (4, 3, 1, 2, 5)]
|
||||
return self.construct(tup)
|
||||
|
||||
# Try SubjectPublicKeyInfo
|
||||
if len(der) == 2:
|
||||
try:
|
||||
algo = decode_der(DerSequence, der[0])
|
||||
algo_oid = decode_der(DerObjectId, algo[0]).value
|
||||
params = decode_der(DerSequence, algo[1]) # Dss-Parms
|
||||
|
||||
if algo_oid == oid and len(params) == 3 and\
|
||||
params.hasOnlyInts():
|
||||
bitmap = decode_der(DerBitString, der[1])
|
||||
pub_key = decode_der(DerInteger, bitmap.value)
|
||||
tup = [pub_key.value]
|
||||
tup += [params[comp] for comp in (2, 0, 1)]
|
||||
return self.construct(tup)
|
||||
except (ValueError, EOFError):
|
||||
pass
|
||||
|
||||
# Try unencrypted PKCS#8
|
||||
p8_pair = PKCS8.unwrap(key_data, passphrase)
|
||||
if p8_pair[0] == oid:
|
||||
return self._importKeyDER(p8_pair[1], passphrase, p8_pair[2])
|
||||
|
||||
except (ValueError, EOFError):
|
||||
pass
|
||||
|
||||
raise KeyFormatError("DSA key format is not supported")
|
||||
|
||||
def importKey(self, extern_key, passphrase=None):
|
||||
"""Import a DSA key (public or private).
|
||||
|
||||
:Parameters:
|
||||
extern_key : (byte) string
|
||||
The DSA key to import.
|
||||
|
||||
An DSA *public* key can be in any of the following formats:
|
||||
|
||||
- X.509 ``subjectPublicKeyInfo`` (binary or PEM)
|
||||
- OpenSSH (one line of text, see `RFC4253`_)
|
||||
|
||||
A DSA *private* key can be in any of the following formats:
|
||||
|
||||
- `PKCS#8`_ ``PrivateKeyInfo`` or ``EncryptedPrivateKeyInfo``
|
||||
DER SEQUENCE (binary or PEM encoding)
|
||||
- OpenSSL/OpenSSH (binary or PEM)
|
||||
|
||||
For details about the PEM encoding, see `RFC1421`_/`RFC1423`_.
|
||||
|
||||
The private key may be encrypted by means of a certain pass phrase
|
||||
either at the PEM level or at the PKCS#8 level.
|
||||
|
||||
passphrase : string
|
||||
In case of an encrypted private key, this is the pass phrase
|
||||
from which the decryption key is derived.
|
||||
|
||||
:Return: A DSA key object (`_DSAobj`).
|
||||
:Raise KeyFormatError:
|
||||
When the given key cannot be parsed (possibly because
|
||||
the pass phrase is wrong).
|
||||
|
||||
.. _RFC1421: http://www.ietf.org/rfc/rfc1421.txt
|
||||
.. _RFC1423: http://www.ietf.org/rfc/rfc1423.txt
|
||||
.. _RFC4253: http://www.ietf.org/rfc/rfc4253.txt
|
||||
.. _PKCS#8: http://www.ietf.org/rfc/rfc5208.txt
|
||||
"""
|
||||
|
||||
extern_key = tobytes(extern_key)
|
||||
if passphrase is not None:
|
||||
passphrase = tobytes(passphrase)
|
||||
|
||||
if extern_key.startswith(b('-----')):
|
||||
# This is probably a PEM encoded key
|
||||
(der, marker, enc_flag) = PEM.decode(tostr(extern_key), passphrase)
|
||||
if enc_flag:
|
||||
passphrase = None
|
||||
return self._importKeyDER(der, passphrase)
|
||||
|
||||
if extern_key.startswith(b('ssh-dss ')):
|
||||
# This is probably a public OpenSSH key
|
||||
keystring = binascii.a2b_base64(extern_key.split(b(' '))[1])
|
||||
keyparts = []
|
||||
while len(keystring) > 4:
|
||||
length = struct.unpack(">I", keystring[:4])[0]
|
||||
keyparts.append(keystring[4:4 + length])
|
||||
keystring = keystring[4 + length:]
|
||||
if keyparts[0] == b("ssh-dss"):
|
||||
tup = [bytes_to_long(keyparts[x]) for x in (4, 3, 1, 2)]
|
||||
return self.construct(tup)
|
||||
|
||||
if bord(extern_key[0]) == 0x30:
|
||||
# This is probably a DER encoded key
|
||||
return self._importKeyDER(extern_key, passphrase)
|
||||
|
||||
raise KeyFormatError("DSA key format is not supported")
|
||||
|
||||
#: `Object ID`_ for a DSA key.
|
||||
#:
|
||||
#: id-dsa ID ::= { iso(1) member-body(2) us(840) x9-57(10040) x9cm(4) 1 }
|
||||
#:
|
||||
#: .. _`Object ID`: http://www.alvestrand.no/objectid/1.2.840.10040.4.1.html
|
||||
oid = "1.2.840.10040.4.1"
|
||||
|
||||
_impl = DSAImplementation()
|
||||
generate = _impl.generate
|
||||
construct = _impl.construct
|
||||
importKey = _impl.importKey
|
||||
error = _impl.error
|
||||
|
||||
# vim:set ts=4 sw=4 sts=4 expandtab:
|
||||
|
||||
@@ -111,7 +111,6 @@ __all__ = ['generate', 'construct', 'error', 'ElGamalobj']
|
||||
|
||||
from Crypto.PublicKey.pubkey import *
|
||||
from Crypto.Util import number
|
||||
from Crypto import Random
|
||||
|
||||
class error (Exception):
|
||||
pass
|
||||
@@ -243,11 +242,6 @@ class ElGamalobj(pubkey):
|
||||
#: - **x**, the private key.
|
||||
keydata=['p', 'g', 'y', 'x']
|
||||
|
||||
def __init__(self, randfunc=None):
|
||||
if randfunc is None:
|
||||
randfunc = Random.new().read
|
||||
self._randfunc = randfunc
|
||||
|
||||
def encrypt(self, plaintext, K):
|
||||
"""Encrypt a piece of data with ElGamal.
|
||||
|
||||
@@ -337,11 +331,8 @@ class ElGamalobj(pubkey):
|
||||
def _decrypt(self, M):
|
||||
if (not hasattr(self, 'x')):
|
||||
raise TypeError('Private key not available in this object')
|
||||
r = number.getRandomRange(2, self.p-1, self._randfunc)
|
||||
a_blind = (M[0] * pow(self.g, r, self.p)) % self.p
|
||||
ax=pow(a_blind, self.x, self.p)
|
||||
plaintext_blind = (M[1] * inverse(ax, self.p ) ) % self.p
|
||||
plaintext = (plaintext_blind * pow(self.y, r, self.p)) % self.p
|
||||
ax=pow(M[0], self.x, self.p)
|
||||
plaintext=(M[1] * inverse(ax, self.p ) ) % self.p
|
||||
return plaintext
|
||||
|
||||
def _sign(self, M, K):
|
||||
|
||||
+169
-182
@@ -46,7 +46,7 @@ them from known components, exporting them, and importing them.
|
||||
>>>
|
||||
>>> key = RSA.generate(2048)
|
||||
>>> f = open('mykey.pem','w')
|
||||
>>> f.write(key.exportKey('PEM'))
|
||||
>>> f.write(RSA.exportKey('PEM'))
|
||||
>>> f.close()
|
||||
...
|
||||
>>> f = open('mykey.pem','r')
|
||||
@@ -65,39 +65,31 @@ it is recommended to use one of the standardized schemes instead (like
|
||||
|
||||
__revision__ = "$Id$"
|
||||
|
||||
__all__ = ['generate', 'construct', 'error', 'importKey', 'RSAImplementation',
|
||||
'_RSAobj', 'oid' , 'algorithmIdentifier' ]
|
||||
__all__ = ['generate', 'construct', 'error', 'importKey', 'RSAImplementation', '_RSAobj']
|
||||
|
||||
import sys
|
||||
if sys.version_info[0] == 2 and sys.version_info[1] == 1:
|
||||
from Crypto.Util.py21compat import *
|
||||
from Crypto.Util.py3compat import *
|
||||
|
||||
#from Crypto.Util.python_compat import *
|
||||
from Crypto.Util.number import getRandomRange, bytes_to_long, long_to_bytes
|
||||
|
||||
from Crypto.PublicKey import _RSA, _slowmath, pubkey
|
||||
from Crypto.IO import PKCS8, PEM
|
||||
from Crypto import Random
|
||||
|
||||
from Crypto.Util.asn1 import *
|
||||
|
||||
from Crypto.Util.asn1 import DerObject, DerSequence, DerNull
|
||||
import binascii
|
||||
import struct
|
||||
|
||||
from Crypto.Util.number import inverse
|
||||
|
||||
from Crypto.Util.number import inverse
|
||||
|
||||
try:
|
||||
from Crypto.PublicKey import _fastmath
|
||||
except ImportError:
|
||||
_fastmath = None
|
||||
|
||||
def decode_der(obj_class, binstr):
|
||||
"""Instantiate a DER object class, decode a DER binary string in it, and
|
||||
return the object."""
|
||||
der = obj_class()
|
||||
der.decode(binstr)
|
||||
return der
|
||||
|
||||
class _RSAobj(pubkey.pubkey):
|
||||
"""Class defining an actual RSA key.
|
||||
|
||||
@@ -294,8 +286,6 @@ class _RSAobj(pubkey.pubkey):
|
||||
def __setstate__(self, d):
|
||||
if not hasattr(self, 'implementation'):
|
||||
self.implementation = RSAImplementation()
|
||||
if not hasattr(self, '_randfunc'):
|
||||
self._randfunc = Random.new().read
|
||||
t = []
|
||||
for k in self.keydata:
|
||||
if not d.has_key(k):
|
||||
@@ -315,66 +305,36 @@ class _RSAobj(pubkey.pubkey):
|
||||
# PY3K: This is meant to be text, do not change to bytes (data)
|
||||
return "<%s @0x%x %s>" % (self.__class__.__name__, id(self), ",".join(attrs))
|
||||
|
||||
def exportKey(self, format='PEM', passphrase=None, pkcs=1, protection=None):
|
||||
def exportKey(self, format='PEM', passphrase=None, pkcs=1):
|
||||
"""Export this RSA key.
|
||||
|
||||
:Parameters:
|
||||
format : string
|
||||
The format to use for wrapping the key:
|
||||
:Parameter format: The format to use for wrapping the key.
|
||||
|
||||
- *'DER'*. Binary encoding.
|
||||
- *'DER'*. Binary encoding, always unencrypted.
|
||||
- *'PEM'*. Textual encoding, done according to `RFC1421`_/`RFC1423`_.
|
||||
Unencrypted (default) or encrypted.
|
||||
- *'OpenSSH'*. Textual encoding, done according to OpenSSH specification.
|
||||
Only suitable for public keys (not private keys).
|
||||
:Type format: string
|
||||
|
||||
passphrase : string
|
||||
For private keys only. The pass phrase used for deriving the encryption
|
||||
key.
|
||||
:Parameter passphrase: In case of PEM, the pass phrase to derive the encryption key from.
|
||||
:Type passphrase: string
|
||||
|
||||
pkcs : integer
|
||||
For *DER* and *PEM* format only.
|
||||
The PKCS standard to follow for assembling the components of the key.
|
||||
You have two choices:
|
||||
:Parameter pkcs: The PKCS standard to follow for assembling the key.
|
||||
You have two choices:
|
||||
|
||||
- **1** (default): the public key is embedded into
|
||||
an X.509 ``SubjectPublicKeyInfo`` DER SEQUENCE.
|
||||
The private key is embedded into a `PKCS#1`_
|
||||
``RSAPrivateKey`` DER SEQUENCE.
|
||||
- **8**: the private key is embedded into a `PKCS#8`_
|
||||
``PrivateKeyInfo`` DER SEQUENCE. This value cannot be used
|
||||
for public keys.
|
||||
- with **1**, the public key is embedded into an X.509 `SubjectPublicKeyInfo` DER SEQUENCE.
|
||||
The private key is embedded into a `PKCS#1`_ `RSAPrivateKey` DER SEQUENCE.
|
||||
This mode is the default.
|
||||
- with **8**, the private key is embedded into a `PKCS#8`_ `PrivateKeyInfo` DER SEQUENCE.
|
||||
This mode is not available for public keys.
|
||||
|
||||
protection : string
|
||||
The encryption scheme to use for protecting the private key.
|
||||
PKCS standards are not relevant for the *OpenSSH* format.
|
||||
:Type pkcs: integer
|
||||
|
||||
If ``None`` (default), the behavior depends on ``format``:
|
||||
|
||||
- For *DER*, the *PBKDF2WithHMAC-SHA1AndDES-EDE3-CBC*
|
||||
scheme is used. The following operations are performed:
|
||||
|
||||
1. A 16 byte Triple DES key is derived from the passphrase
|
||||
using `Crypto.Protocol.KDF.PBKDF2` with 8 bytes salt,
|
||||
and 1 000 iterations of `Crypto.Hash.HMAC`.
|
||||
2. The private key is encrypted using CBC.
|
||||
3. The encrypted key is encoded according to PKCS#8.
|
||||
|
||||
- For *PEM*, the obsolete PEM encryption scheme is used.
|
||||
It is based on MD5 for key derivation, and Triple DES for encryption.
|
||||
|
||||
Specifying a value for ``protection`` is only meaningful for PKCS#8
|
||||
(that is, ``pkcs=8``) and only if a pass phrase is present too.
|
||||
|
||||
The supported schemes for PKCS#8 are listed in the
|
||||
`Crypto.IO.PKCS8` module (see ``wrap_algo`` parameter).
|
||||
|
||||
:Return: A byte string with the encoded public or private half
|
||||
of the key.
|
||||
:Return: A byte string with the encoded public or private half.
|
||||
:Raise ValueError:
|
||||
When the format is unknown or when you try to encrypt a private
|
||||
key with *DER* format and PKCS#1.
|
||||
:attention:
|
||||
If you don't provide a pass phrase, the private key will be
|
||||
exported in the clear!
|
||||
When the format is unknown.
|
||||
|
||||
.. _RFC1421: http://www.ietf.org/rfc/rfc1421.txt
|
||||
.. _RFC1423: http://www.ietf.org/rfc/rfc1423.txt
|
||||
@@ -388,52 +348,59 @@ class _RSAobj(pubkey.pubkey):
|
||||
nb = long_to_bytes(self.n)
|
||||
if bord(eb[0]) & 0x80: eb=bchr(0x00)+eb
|
||||
if bord(nb[0]) & 0x80: nb=bchr(0x00)+nb
|
||||
keyparts = [ b('ssh-rsa'), eb, nb ]
|
||||
keystring = b('').join([ struct.pack(">I",len(kp))+kp for kp in keyparts])
|
||||
return b('ssh-rsa ')+binascii.b2a_base64(keystring)[:-1]
|
||||
keyparts = [ 'ssh-rsa', eb, nb ]
|
||||
keystring = ''.join([ struct.pack(">I",len(kp))+kp for kp in keyparts])
|
||||
return 'ssh-rsa '+binascii.b2a_base64(keystring)[:-1]
|
||||
|
||||
# DER format is always used, even in case of PEM, which simply
|
||||
# encodes it into BASE64.
|
||||
der = DerSequence()
|
||||
if self.has_private():
|
||||
binary_key = newDerSequence(
|
||||
0,
|
||||
self.n,
|
||||
self.e,
|
||||
self.d,
|
||||
self.p,
|
||||
self.q,
|
||||
self.d % (self.p-1),
|
||||
self.d % (self.q-1),
|
||||
inverse(self.q, self.p)
|
||||
).encode()
|
||||
if pkcs==1:
|
||||
keyType = 'RSA PRIVATE'
|
||||
if format=='DER' and passphrase:
|
||||
raise ValueError("PKCS#1 private key cannot be encrypted")
|
||||
else: # PKCS#8
|
||||
if format=='PEM' and protection is None:
|
||||
keyType = 'PRIVATE'
|
||||
binary_key = PKCS8.wrap(binary_key, oid, None)
|
||||
else:
|
||||
keyType = 'ENCRYPTED PRIVATE'
|
||||
if not protection:
|
||||
protection = 'PBKDF2WithHMAC-SHA1AndDES-EDE3-CBC'
|
||||
binary_key = PKCS8.wrap(binary_key, oid, passphrase, protection)
|
||||
passphrase = None
|
||||
keyType= { 1: 'RSA PRIVATE', 8: 'PRIVATE' }[pkcs]
|
||||
der[:] = [ 0, self.n, self.e, self.d, self.p, self.q,
|
||||
self.d % (self.p-1), self.d % (self.q-1),
|
||||
inverse(self.q, self.p) ]
|
||||
if pkcs==8:
|
||||
derkey = der.encode()
|
||||
der = DerSequence([0])
|
||||
der.append(algorithmIdentifier)
|
||||
der.append(DerObject('OCTET STRING', derkey).encode())
|
||||
else:
|
||||
keyType = "RSA PUBLIC"
|
||||
binary_key = newDerSequence(
|
||||
algorithmIdentifier,
|
||||
newDerBitString(
|
||||
newDerSequence( self.n, self.e )
|
||||
)
|
||||
).encode()
|
||||
keyType = "PUBLIC"
|
||||
der.append(algorithmIdentifier)
|
||||
bitmap = DerObject('BIT STRING')
|
||||
derPK = DerSequence( [ self.n, self.e ] )
|
||||
bitmap.payload = bchr(0x00) + derPK.encode()
|
||||
der.append(bitmap.encode())
|
||||
if format=='DER':
|
||||
return binary_key
|
||||
return der.encode()
|
||||
if format=='PEM':
|
||||
pem_str = PEM.encode(binary_key, keyType+" KEY", passphrase, self._randfunc)
|
||||
return tobytes(pem_str)
|
||||
raise ValueError("Unknown key format '%s'. Cannot export the RSA key." % format)
|
||||
pem = b("-----BEGIN " + keyType + " KEY-----\n")
|
||||
objenc = None
|
||||
if passphrase and keyType.endswith('PRIVATE'):
|
||||
# We only support 3DES for encryption
|
||||
import Crypto.Hash.MD5
|
||||
from Crypto.Cipher import DES3
|
||||
from Crypto.Protocol.KDF import PBKDF1
|
||||
salt = self._randfunc(8)
|
||||
key = PBKDF1(passphrase, salt, 16, 1, Crypto.Hash.MD5)
|
||||
key += PBKDF1(key+passphrase, salt, 8, 1, Crypto.Hash.MD5)
|
||||
objenc = DES3.new(key, Crypto.Cipher.DES3.MODE_CBC, salt)
|
||||
pem += b('Proc-Type: 4,ENCRYPTED\n')
|
||||
pem += b('DEK-Info: DES-EDE3-CBC,') + binascii.b2a_hex(salt).upper() + b('\n\n')
|
||||
|
||||
binaryKey = der.encode()
|
||||
if objenc:
|
||||
# Add PKCS#7-like padding
|
||||
padding = objenc.block_size-len(binaryKey)%objenc.block_size
|
||||
binaryKey = objenc.encrypt(binaryKey+bchr(padding)*padding)
|
||||
|
||||
# Each BASE64 line can take up to 64 characters (=48 bytes of data)
|
||||
chunks = [ binascii.b2a_base64(binaryKey[i:i+48]) for i in range(0, len(binaryKey), 48) ]
|
||||
pem += b('').join(chunks)
|
||||
pem += b("-----END " + keyType + " KEY-----")
|
||||
return pem
|
||||
return ValueError("Unknown key format '%s'. Cannot export the RSA key." % format)
|
||||
|
||||
class RSAImplementation(object):
|
||||
"""
|
||||
@@ -572,139 +539,159 @@ class RSAImplementation(object):
|
||||
key = self._math.rsa_construct(*tup)
|
||||
return _RSAobj(self, key)
|
||||
|
||||
def _importKeyDER(self, extern_key, passphrase=None):
|
||||
def _importKeyDER(self, externKey):
|
||||
"""Import an RSA key (public or private half), encoded in DER form."""
|
||||
|
||||
try:
|
||||
|
||||
der = decode_der(DerSequence, extern_key)
|
||||
der = DerSequence()
|
||||
der.decode(externKey, True)
|
||||
|
||||
# Try PKCS#1 first, for a private key
|
||||
if len(der) == 9 and der.hasOnlyInts() and der[0] == 0:
|
||||
if len(der)==9 and der.hasOnlyInts() and der[0]==0:
|
||||
# ASN.1 RSAPrivateKey element
|
||||
del der[6:] # Remove d mod (p-1),
|
||||
# d mod (q-1), and
|
||||
# q^{-1} mod p
|
||||
der.append(inverse(der[4], der[5])) # Add p^{-1} mod q
|
||||
del der[6:] # Remove d mod (p-1), d mod (q-1), and q^{-1} mod p
|
||||
der.append(inverse(der[4],der[5])) # Add p^{-1} mod q
|
||||
del der[0] # Remove version
|
||||
return self.construct(der[:])
|
||||
|
||||
# Keep on trying PKCS#1, but now for a public key
|
||||
if len(der) == 2:
|
||||
try:
|
||||
# The DER object is an RSAPublicKey SEQUENCE with
|
||||
# two elements
|
||||
if der.hasOnlyInts():
|
||||
return self.construct(der[:])
|
||||
# The DER object is a SubjectPublicKeyInfo SEQUENCE
|
||||
# with two elements: an 'algorithmIdentifier' and a
|
||||
# 'subjectPublicKey'BIT STRING.
|
||||
# 'algorithmIdentifier' takes the value given at the
|
||||
# module level.
|
||||
# 'subjectPublicKey' encapsulates the actual ASN.1
|
||||
# RSAPublicKey element.
|
||||
if der[0] == algorithmIdentifier:
|
||||
bitmap = decode_der(DerBitString, der[1])
|
||||
rsaPub = decode_der(DerSequence, bitmap.value)
|
||||
if len(rsaPub) == 2 and rsaPub.hasOnlyInts():
|
||||
return self.construct(rsaPub[:])
|
||||
except (ValueError, EOFError):
|
||||
pass
|
||||
if len(der)==2:
|
||||
# The DER object is an RSAPublicKey SEQUENCE with two elements
|
||||
if der.hasOnlyInts():
|
||||
return self.construct(der[:])
|
||||
# The DER object is a SubjectPublicKeyInfo SEQUENCE with two elements:
|
||||
# an 'algorithm' (or 'algorithmIdentifier') SEQUENCE and a 'subjectPublicKey' BIT STRING.
|
||||
# 'algorithm' takes the value given a few lines above.
|
||||
# 'subjectPublicKey' encapsulates the actual ASN.1 RSAPublicKey element.
|
||||
if der[0]==algorithmIdentifier:
|
||||
bitmap = DerObject()
|
||||
bitmap.decode(der[1], True)
|
||||
if bitmap.isType('BIT STRING') and bord(bitmap.payload[0])==0x00:
|
||||
der.decode(bitmap.payload[1:], True)
|
||||
if len(der)==2 and der.hasOnlyInts():
|
||||
return self.construct(der[:])
|
||||
|
||||
# Try PKCS#8 (possibly encrypted)
|
||||
k = PKCS8.unwrap(extern_key, passphrase)
|
||||
if k[0] == oid:
|
||||
return self._importKeyDER(k[1], passphrase)
|
||||
# Try unencrypted PKCS#8
|
||||
if der[0]==0:
|
||||
# The second element in the SEQUENCE is algorithmIdentifier.
|
||||
# It must say RSA (see above for description).
|
||||
if der[1]==algorithmIdentifier:
|
||||
privateKey = DerObject()
|
||||
privateKey.decode(der[2], True)
|
||||
if privateKey.isType('OCTET STRING'):
|
||||
return self._importKeyDER(privateKey.payload)
|
||||
|
||||
except (ValueError, EOFError):
|
||||
except ValueError, IndexError:
|
||||
pass
|
||||
|
||||
raise ValueError("RSA key format is not supported")
|
||||
|
||||
def importKey(self, extern_key, passphrase=None):
|
||||
"""Import an RSA key (public or private half), encoded in standard
|
||||
form.
|
||||
def importKey(self, externKey, passphrase=None):
|
||||
"""Import an RSA key (public or private half), encoded in standard form.
|
||||
|
||||
:Parameter extern_key:
|
||||
:Parameter externKey:
|
||||
The RSA key to import, encoded as a string.
|
||||
|
||||
An RSA public key can be in any of the following formats:
|
||||
|
||||
- X.509 ``subjectPublicKeyInfo`` DER SEQUENCE (binary or PEM
|
||||
encoding)
|
||||
- `PKCS#1`_ ``RSAPublicKey`` DER SEQUENCE (binary or PEM encoding)
|
||||
- X.509 `subjectPublicKeyInfo` DER SEQUENCE (binary or PEM encoding)
|
||||
- `PKCS#1`_ `RSAPublicKey` DER SEQUENCE (binary or PEM encoding)
|
||||
- OpenSSH (textual public key only)
|
||||
|
||||
An RSA private key can be in any of the following formats:
|
||||
|
||||
- PKCS#1 ``RSAPrivateKey`` DER SEQUENCE (binary or PEM encoding)
|
||||
- `PKCS#8`_ ``PrivateKeyInfo`` or ``EncryptedPrivateKeyInfo``
|
||||
DER SEQUENCE (binary or PEM encoding)
|
||||
- PKCS#1 `RSAPrivateKey` DER SEQUENCE (binary or PEM encoding)
|
||||
- `PKCS#8`_ `PrivateKeyInfo` DER SEQUENCE (binary or PEM encoding)
|
||||
- OpenSSH (textual public key only)
|
||||
|
||||
For details about the PEM encoding, see `RFC1421`_/`RFC1423`_.
|
||||
|
||||
The private key may be encrypted by means of a certain pass phrase
|
||||
either at the PEM level or at the PKCS#8 level.
|
||||
:Type extern_key: string
|
||||
|
||||
In case of PEM encoding, the private key can be encrypted with DES or 3TDES according to a certain ``pass phrase``.
|
||||
Only OpenSSL-compatible pass phrases are supported.
|
||||
:Type externKey: string
|
||||
|
||||
:Parameter passphrase:
|
||||
In case of an encrypted private key, this is the pass phrase from
|
||||
which the decryption key is derived.
|
||||
In case of an encrypted PEM key, this is the pass phrase from which the encryption key is derived.
|
||||
:Type passphrase: string
|
||||
|
||||
|
||||
:Return: An RSA key object (`_RSAobj`).
|
||||
|
||||
:Raise ValueError/IndexError/TypeError:
|
||||
When the given key cannot be parsed (possibly because the pass
|
||||
phrase is wrong).
|
||||
When the given key cannot be parsed (possibly because the pass phrase is wrong).
|
||||
|
||||
.. _RFC1421: http://www.ietf.org/rfc/rfc1421.txt
|
||||
.. _RFC1423: http://www.ietf.org/rfc/rfc1423.txt
|
||||
.. _`PKCS#1`: http://www.ietf.org/rfc/rfc3447.txt
|
||||
.. _`PKCS#8`: http://www.ietf.org/rfc/rfc5208.txt
|
||||
"""
|
||||
extern_key = tobytes(extern_key)
|
||||
externKey = tobytes(externKey)
|
||||
if passphrase is not None:
|
||||
passphrase = tobytes(passphrase)
|
||||
|
||||
if extern_key.startswith(b('-----')):
|
||||
# This is probably a PEM encoded key.
|
||||
(der, marker, enc_flag) = PEM.decode(tostr(extern_key), passphrase)
|
||||
if enc_flag:
|
||||
passphrase = None
|
||||
return self._importKeyDER(der, passphrase)
|
||||
if externKey.startswith(b('-----')):
|
||||
# This is probably a PEM encoded key
|
||||
lines = externKey.replace(b(" "),b('')).split()
|
||||
keyobj = None
|
||||
|
||||
if extern_key.startswith(b('ssh-rsa ')):
|
||||
# The encrypted PEM format
|
||||
if lines[1].startswith(b('Proc-Type:4,ENCRYPTED')):
|
||||
DEK = lines[2].split(b(':'))
|
||||
if len(DEK)!=2 or DEK[0]!=b('DEK-Info') or not passphrase:
|
||||
raise ValueError("PEM encryption format not supported.")
|
||||
algo, salt = DEK[1].split(b(','))
|
||||
salt = binascii.a2b_hex(salt)
|
||||
import Crypto.Hash.MD5
|
||||
from Crypto.Cipher import DES, DES3
|
||||
from Crypto.Protocol.KDF import PBKDF1
|
||||
if algo==b("DES-CBC"):
|
||||
# This is EVP_BytesToKey in OpenSSL
|
||||
key = PBKDF1(passphrase, salt, 8, 1, Crypto.Hash.MD5)
|
||||
keyobj = DES.new(key, Crypto.Cipher.DES.MODE_CBC, salt)
|
||||
elif algo==b("DES-EDE3-CBC"):
|
||||
# Note that EVP_BytesToKey is note exactly the same as PBKDF1
|
||||
key = PBKDF1(passphrase, salt, 16, 1, Crypto.Hash.MD5)
|
||||
key += PBKDF1(key+passphrase, salt, 8, 1, Crypto.Hash.MD5)
|
||||
keyobj = DES3.new(key, Crypto.Cipher.DES3.MODE_CBC, salt)
|
||||
else:
|
||||
raise ValueError("Unsupport PEM encryption algorithm.")
|
||||
lines = lines[2:]
|
||||
|
||||
der = binascii.a2b_base64(b('').join(lines[1:-1]))
|
||||
if keyobj:
|
||||
der = keyobj.decrypt(der)
|
||||
padding = bord(der[-1])
|
||||
der = der[:-padding]
|
||||
return self._importKeyDER(der)
|
||||
|
||||
if externKey.startswith(b('ssh-rsa ')):
|
||||
# This is probably an OpenSSH key
|
||||
keystring = binascii.a2b_base64(extern_key.split(b(' '))[1])
|
||||
keystring = binascii.a2b_base64(externKey.split(b(' '))[1])
|
||||
keyparts = []
|
||||
while len(keystring) > 4:
|
||||
l = struct.unpack(">I", keystring[:4])[0]
|
||||
keyparts.append(keystring[4:4 + l])
|
||||
keystring = keystring[4 + l:]
|
||||
while len(keystring)>4:
|
||||
l = struct.unpack(">I",keystring[:4])[0]
|
||||
keyparts.append(keystring[4:4+l])
|
||||
keystring = keystring[4+l:]
|
||||
e = bytes_to_long(keyparts[1])
|
||||
n = bytes_to_long(keyparts[2])
|
||||
return self.construct([n, e])
|
||||
|
||||
if bord(extern_key[0]) == 0x30:
|
||||
if bord(externKey[0])==0x30:
|
||||
# This is probably a DER encoded key
|
||||
return self._importKeyDER(extern_key, passphrase)
|
||||
|
||||
return self._importKeyDER(externKey)
|
||||
|
||||
raise ValueError("RSA key format is not supported")
|
||||
|
||||
#: `Object ID`_ for the RSA encryption algorithm. This OID often indicates
|
||||
#: a generic RSA key, even when such key will be actually used for digital
|
||||
#: signatures.
|
||||
#:
|
||||
#: .. _`Object ID`: http://www.alvestrand.no/objectid/1.2.840.113549.1.1.1.html
|
||||
oid = "1.2.840.113549.1.1.1"
|
||||
|
||||
#: This is the standard DER object that qualifies a cryptographic algorithm
|
||||
#: in ASN.1-based data structures (e.g. X.509 certificates).
|
||||
#: This is the ASN.1 DER object that qualifies an algorithm as
|
||||
#: compliant to PKCS#1 (that is, the standard RSA).
|
||||
# It is found in all 'algorithm' fields (also called 'algorithmIdentifier').
|
||||
# It is a SEQUENCE with the oid assigned to RSA and with its parameters (none).
|
||||
# 0x06 0x09 OBJECT IDENTIFIER, 9 bytes of payload
|
||||
# 0x2A 0x86 0x48 0x86 0xF7 0x0D 0x01 0x01 0x01
|
||||
# rsaEncryption (1 2 840 113549 1 1 1) (PKCS #1)
|
||||
# 0x05 0x00 NULL
|
||||
algorithmIdentifier = DerSequence(
|
||||
[DerObjectId(oid).encode(), # algorithm field
|
||||
DerNull().encode()] # parameters field
|
||||
[ b('\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x01'),
|
||||
DerNull().encode() ]
|
||||
).encode()
|
||||
|
||||
_impl = RSAImplementation()
|
||||
|
||||
@@ -30,7 +30,7 @@ __revision__ = "$Id$"
|
||||
from Crypto.PublicKey.pubkey import *
|
||||
from Crypto.Util import number
|
||||
from Crypto.Util.number import bytes_to_long, long_to_bytes
|
||||
from Crypto.Hash import SHA1
|
||||
from Crypto.Hash import SHA
|
||||
from Crypto.Util.py3compat import *
|
||||
|
||||
class error (Exception):
|
||||
@@ -38,8 +38,8 @@ class error (Exception):
|
||||
|
||||
def generateQ(randfunc):
|
||||
S=randfunc(20)
|
||||
hash1=SHA1.new(S).digest()
|
||||
hash2=SHA1.new(long_to_bytes(bytes_to_long(S)+1)).digest()
|
||||
hash1=SHA.new(S).digest()
|
||||
hash2=SHA.new(long_to_bytes(bytes_to_long(S)+1)).digest()
|
||||
q = bignum(0)
|
||||
for i in range(0,20):
|
||||
c=bord(hash1[i])^bord(hash2[i])
|
||||
@@ -77,7 +77,7 @@ def generate_py(bits, randfunc, progress_func=None):
|
||||
powL1=pow(bignum(2), bits-1)
|
||||
while C<4096:
|
||||
for k in range(0, n+1):
|
||||
V[k]=bytes_to_long(SHA1.new(S+bstr(N)+bstr(k)).digest())
|
||||
V[k]=bytes_to_long(SHA.new(S+bstr(N)+bstr(k)).digest())
|
||||
W=V[n] % powb
|
||||
for k in range(n-1, -1, -1):
|
||||
W=(W<<160L)+V[k]
|
||||
|
||||
@@ -36,9 +36,6 @@ Crypto.PublicKey.RSA (Signing, encryption, and blinding)
|
||||
:undocumented: _DSA, _RSA, _fastmath, _slowmath, pubkey
|
||||
"""
|
||||
|
||||
class KeyFormatError(ValueError):
|
||||
pass
|
||||
|
||||
__all__ = ['RSA', 'DSA', 'ElGamal']
|
||||
__revision__ = "$Id$"
|
||||
|
||||
|
||||
@@ -36,9 +36,6 @@ import warnings
|
||||
from Crypto.pct_warnings import ClockRewindWarning
|
||||
import SHAd256
|
||||
|
||||
# If the system has monotonic time, we'll use it.
|
||||
from Crypto.Util._time import maybe_monotonic_time
|
||||
|
||||
import FortunaGenerator
|
||||
|
||||
class FortunaPool(object):
|
||||
@@ -97,25 +94,8 @@ def which_pools(r):
|
||||
|
||||
class FortunaAccumulator(object):
|
||||
|
||||
# An estimate of how many bytes we must append to pool 0 before it will
|
||||
# contain 128 bits of entropy (with respect to an attack). We reseed the
|
||||
# generator only after pool 0 contains `min_pool_size` bytes. Note that
|
||||
# unlike with some other PRNGs, Fortuna's security does not rely on the
|
||||
# accuracy of this estimate---we can accord to be optimistic here.
|
||||
min_pool_size = 64 # size in bytes
|
||||
|
||||
# If an attacker can predict some (but not all) of our entropy sources, the
|
||||
# `min_pool_size` check may not be sufficient to prevent a successful state
|
||||
# compromise extension attack. To resist this attack, Fortuna spreads the
|
||||
# input across 32 pools, which are then consumed (to reseed the output
|
||||
# generator) with exponentially decreasing frequency.
|
||||
#
|
||||
# In order to prevent an attacker from gaining knowledge of all 32 pools
|
||||
# before we have a chance to fill them with enough information that the
|
||||
# attacker cannot predict, we impose a rate limit of 10 reseeds/second (one
|
||||
# per 100 ms). This ensures that a hypothetical 33rd pool would only be
|
||||
# needed after a minimum of 13 years of sustained attack.
|
||||
reseed_interval = 0.100 # time in seconds
|
||||
min_pool_size = 64 # TODO: explain why
|
||||
reseed_interval = 0.100 # 100 ms TODO: explain why
|
||||
|
||||
def __init__(self):
|
||||
self.reseed_count = 0
|
||||
@@ -129,17 +109,8 @@ class FortunaAccumulator(object):
|
||||
self.pools = [FortunaPool() for i in range(32)] # 32 pools
|
||||
assert(self.pools[0] is not self.pools[1])
|
||||
|
||||
def _forget_last_reseed(self):
|
||||
# This is not part of the standard Fortuna definition, and using this
|
||||
# function frequently can weaken Fortuna's ability to resist a state
|
||||
# compromise extension attack, but we need this in order to properly
|
||||
# implement Crypto.Random.atfork(). Otherwise, forked child processes
|
||||
# might continue to use their parent's PRNG state for up to 100ms in
|
||||
# some cases. (e.g. CVE-2013-1445)
|
||||
self.last_reseed = None
|
||||
|
||||
def random_data(self, bytes):
|
||||
current_time = maybe_monotonic_time()
|
||||
current_time = time.time()
|
||||
if (self.last_reseed is not None and self.last_reseed > current_time): # Avoid float comparison to None to make Py3k happy
|
||||
warnings.warn("Clock rewind detected. Resetting last_reseed.", ClockRewindWarning)
|
||||
self.last_reseed = None
|
||||
@@ -152,7 +123,7 @@ class FortunaAccumulator(object):
|
||||
|
||||
def _reseed(self, current_time=None):
|
||||
if current_time is None:
|
||||
current_time = maybe_monotonic_time()
|
||||
current_time = time.time()
|
||||
seed = []
|
||||
self.reseed_count += 1
|
||||
self.last_reseed = current_time
|
||||
|
||||
@@ -25,7 +25,7 @@
|
||||
__revision__ = "$Id$"
|
||||
|
||||
import sys
|
||||
if sys.version_info[0] == 2 and sys.version_info[1] == 1:
|
||||
if sys.version_info[0] is 2 and sys.version_info[1] is 1:
|
||||
from Crypto.Util.py21compat import *
|
||||
from Crypto.Util.py3compat import *
|
||||
|
||||
|
||||
@@ -25,7 +25,7 @@
|
||||
__revision__ = "$Id$"
|
||||
__all__ = ['WindowsRNG']
|
||||
|
||||
from Crypto.Random.OSRNG import winrandom
|
||||
import winrandom
|
||||
from rng_base import BaseRNG
|
||||
|
||||
class WindowsRNG(BaseRNG):
|
||||
|
||||
@@ -90,24 +90,9 @@ class _UserFriendlyRNG(object):
|
||||
"""Initialize the random number generator and seed it with entropy from
|
||||
the operating system.
|
||||
"""
|
||||
|
||||
# Save the pid (helps ensure that Crypto.Random.atfork() gets called)
|
||||
self._pid = os.getpid()
|
||||
|
||||
# Collect entropy from the operating system and feed it to
|
||||
# FortunaAccumulator
|
||||
self._ec.reinit()
|
||||
|
||||
# Override FortunaAccumulator's 100ms minimum re-seed interval. This
|
||||
# is necessary to avoid a race condition between this function and
|
||||
# self.read(), which that can otherwise cause forked child processes to
|
||||
# produce identical output. (e.g. CVE-2013-1445)
|
||||
#
|
||||
# Note that if this function can be called frequently by an attacker,
|
||||
# (and if the bits from OSRNG are insufficiently random) it will weaken
|
||||
# Fortuna's ability to resist a state compromise extension attack.
|
||||
self._fa._forget_last_reseed()
|
||||
|
||||
def close(self):
|
||||
self.closed = True
|
||||
self._osrng = None
|
||||
|
||||
@@ -103,13 +103,13 @@ class StrongRandom(object):
|
||||
|
||||
def shuffle(self, x):
|
||||
"""Shuffle the sequence in place."""
|
||||
# Fisher-Yates shuffle. O(n)
|
||||
# See http://en.wikipedia.org/wiki/Fisher-Yates_shuffle
|
||||
# Working backwards from the end of the array, we choose a random item
|
||||
# from the remaining items until all items have been chosen.
|
||||
for i in xrange(len(x)-1, 0, -1): # iterate from len(x)-1 downto 1
|
||||
j = self.randrange(0, i+1) # choose random j such that 0 <= j <= i
|
||||
x[i], x[j] = x[j], x[i] # exchange x[i] and x[j]
|
||||
# Make a (copy) of the list of objects we want to shuffle
|
||||
items = list(x)
|
||||
|
||||
# Choose a random item (without replacement) until all the items have been
|
||||
# chosen.
|
||||
for i in xrange(len(x)):
|
||||
x[i] = items.pop(self.randrange(len(items)))
|
||||
|
||||
def sample(self, population, k):
|
||||
"""Return a k-length list of unique elements chosen from the population sequence."""
|
||||
|
||||
@@ -24,19 +24,12 @@
|
||||
|
||||
"""Self-testing for PyCrypto hash modules"""
|
||||
|
||||
from __future__ import nested_scopes
|
||||
|
||||
__revision__ = "$Id$"
|
||||
|
||||
import sys
|
||||
if sys.version_info[0] == 2 and sys.version_info[1] == 1:
|
||||
from Crypto.Util.py21compat import *
|
||||
|
||||
import unittest
|
||||
from binascii import a2b_hex, b2a_hex, hexlify
|
||||
|
||||
from binascii import a2b_hex, b2a_hex
|
||||
from Crypto.Util.py3compat import *
|
||||
from Crypto.Util.strxor import strxor_c
|
||||
|
||||
# For compatibility with Python 2.1 and Python 2.2
|
||||
if sys.hexversion < 0x02030000:
|
||||
@@ -73,22 +66,14 @@ class CipherSelfTest(unittest.TestCase):
|
||||
self.plaintext = b(_extract(params, 'plaintext'))
|
||||
self.ciphertext = b(_extract(params, 'ciphertext'))
|
||||
self.module_name = _extract(params, 'module_name', None)
|
||||
self.assoc_data = _extract(params, 'assoc_data', None)
|
||||
self.mac = _extract(params, 'mac', None)
|
||||
if self.assoc_data:
|
||||
self.mac = b(self.mac)
|
||||
|
||||
mode = _extract(params, 'mode', None)
|
||||
self.mode_name = str(mode)
|
||||
if mode is not None:
|
||||
# Block cipher
|
||||
self.mode = getattr(self.module, "MODE_" + mode)
|
||||
|
||||
self.iv = _extract(params, 'iv', None)
|
||||
if self.iv is None:
|
||||
self.iv = _extract(params, 'nonce', None)
|
||||
if self.iv is not None:
|
||||
self.iv = b(self.iv)
|
||||
if self.iv is not None: self.iv = b(self.iv)
|
||||
|
||||
# Only relevant for OPENPGP mode
|
||||
self.encrypted_iv = _extract(params, 'encrypted_iv', None)
|
||||
@@ -132,60 +117,29 @@ class CipherSelfTest(unittest.TestCase):
|
||||
else:
|
||||
return self.module.new(a2b_hex(self.key), self.mode, a2b_hex(self.iv), **params)
|
||||
|
||||
def isMode(self, name):
|
||||
if not hasattr(self.module, "MODE_"+name):
|
||||
return False
|
||||
return self.mode == getattr(self.module, "MODE_"+name)
|
||||
|
||||
def runTest(self):
|
||||
plaintext = a2b_hex(self.plaintext)
|
||||
ciphertext = a2b_hex(self.ciphertext)
|
||||
assoc_data = []
|
||||
if self.assoc_data:
|
||||
assoc_data = [ a2b_hex(b(x)) for x in self.assoc_data]
|
||||
|
||||
ct = None
|
||||
pt = None
|
||||
ct1 = b2a_hex(self._new().encrypt(plaintext))
|
||||
pt1 = b2a_hex(self._new(1).decrypt(ciphertext))
|
||||
ct2 = b2a_hex(self._new().encrypt(plaintext))
|
||||
pt2 = b2a_hex(self._new(1).decrypt(ciphertext))
|
||||
|
||||
#
|
||||
# Repeat the same encryption or decryption twice and verify
|
||||
# that the result is always the same
|
||||
#
|
||||
for i in xrange(2):
|
||||
cipher = self._new()
|
||||
decipher = self._new(1)
|
||||
|
||||
# Only AEAD modes
|
||||
for comp in assoc_data:
|
||||
cipher.update(comp)
|
||||
decipher.update(comp)
|
||||
|
||||
ctX = b2a_hex(cipher.encrypt(plaintext))
|
||||
if self.isMode("SIV"):
|
||||
ptX = b2a_hex(decipher.decrypt_and_verify(ciphertext, a2b_hex(self.mac)))
|
||||
else:
|
||||
ptX = b2a_hex(decipher.decrypt(ciphertext))
|
||||
|
||||
if ct:
|
||||
self.assertEqual(ct, ctX)
|
||||
self.assertEqual(pt, ptX)
|
||||
ct, pt = ctX, ptX
|
||||
|
||||
if self.isMode("OPENPGP"):
|
||||
if hasattr(self.module, "MODE_OPENPGP") and self.mode == self.module.MODE_OPENPGP:
|
||||
# In PGP mode, data returned by the first encrypt()
|
||||
# is prefixed with the encrypted IV.
|
||||
# Here we check it and then remove it from the ciphertexts.
|
||||
eilen = len(self.encrypted_iv)
|
||||
self.assertEqual(self.encrypted_iv, ct[:eilen])
|
||||
ct = ct[eilen:]
|
||||
self.assertEqual(self.encrypted_iv, ct1[:eilen])
|
||||
self.assertEqual(self.encrypted_iv, ct2[:eilen])
|
||||
ct1 = ct1[eilen:]
|
||||
ct2 = ct2[eilen:]
|
||||
|
||||
self.assertEqual(self.ciphertext, ct) # encrypt
|
||||
self.assertEqual(self.plaintext, pt) # decrypt
|
||||
|
||||
if self.mac:
|
||||
mac = b2a_hex(cipher.digest())
|
||||
self.assertEqual(self.mac, mac)
|
||||
decipher.verify(a2b_hex(self.mac))
|
||||
self.assertEqual(self.ciphertext, ct1) # encrypt
|
||||
self.assertEqual(self.ciphertext, ct2) # encrypt (second time)
|
||||
self.assertEqual(self.plaintext, pt1) # decrypt
|
||||
self.assertEqual(self.plaintext, pt2) # decrypt (second time)
|
||||
|
||||
class CipherStreamingSelfTest(CipherSelfTest):
|
||||
|
||||
@@ -241,43 +195,18 @@ class CTRWraparoundTest(unittest.TestCase):
|
||||
self.module_name = params.get('module_name', None)
|
||||
|
||||
def shortDescription(self):
|
||||
return """Regression test: %s with MODE_CTR raising OverflowError on wraparound""" % (self.module_name,)
|
||||
return """Regression test: %s with MODE_CTR should raise OverflowError on wraparound when shortcut used""" % (self.module_name,)
|
||||
|
||||
def runTest(self):
|
||||
from Crypto.Util import Counter
|
||||
|
||||
def pythonCounter():
|
||||
state = [0]
|
||||
def ctr():
|
||||
# First block succeeds; Second and subsequent blocks raise OverflowError
|
||||
if state[0] == 0:
|
||||
state[0] = 1
|
||||
return b("\xff") * self.module.block_size
|
||||
else:
|
||||
raise OverflowError
|
||||
return ctr
|
||||
|
||||
for little_endian in (0, 1): # (False, True) Test both endiannesses
|
||||
block = b("\x00") * self.module.block_size
|
||||
|
||||
# Test PyObject_CallObject code path: if the counter raises OverflowError
|
||||
cipher = self.module.new(a2b_hex(self.key), self.module.MODE_CTR, counter=pythonCounter())
|
||||
cipher.encrypt(block)
|
||||
self.assertRaises(OverflowError, cipher.encrypt, block)
|
||||
self.assertRaises(OverflowError, cipher.encrypt, block)
|
||||
|
||||
# Test PyObject_CallObject code path: counter object should raise OverflowError
|
||||
ctr = Counter.new(8*self.module.block_size, initial_value=2L**(8*self.module.block_size)-1, little_endian=little_endian)
|
||||
ctr()
|
||||
self.assertRaises(OverflowError, ctr)
|
||||
self.assertRaises(OverflowError, ctr)
|
||||
|
||||
# Test the CTR-mode shortcut
|
||||
ctr = Counter.new(8*self.module.block_size, initial_value=2L**(8*self.module.block_size)-1, little_endian=little_endian)
|
||||
cipher = self.module.new(a2b_hex(self.key), self.module.MODE_CTR, counter=ctr)
|
||||
cipher.encrypt(block)
|
||||
self.assertRaises(OverflowError, cipher.encrypt, block)
|
||||
self.assertRaises(OverflowError, cipher.encrypt, block)
|
||||
for disable_shortcut in (0, 1): # (False, True) Test CTR-mode shortcut and PyObject_CallObject code paths
|
||||
for little_endian in (0, 1): # (False, True) Test both endiannesses
|
||||
ctr = Counter.new(8*self.module.block_size, initial_value=2L**(8*self.module.block_size)-1, little_endian=little_endian, disable_shortcut=disable_shortcut)
|
||||
cipher = self.module.new(a2b_hex(self.key), self.module.MODE_CTR, counter=ctr)
|
||||
block = b("\x00") * self.module.block_size
|
||||
cipher.encrypt(block)
|
||||
self.assertRaises(OverflowError, cipher.encrypt, block)
|
||||
|
||||
class CFBSegmentSizeTest(unittest.TestCase):
|
||||
|
||||
@@ -296,301 +225,6 @@ class CFBSegmentSizeTest(unittest.TestCase):
|
||||
self.assertRaises(ValueError, self.module.new, a2b_hex(self.key), self.module.MODE_CFB, segment_size=i)
|
||||
self.module.new(a2b_hex(self.key), self.module.MODE_CFB, "\0"*self.module.block_size, segment_size=8) # should succeed
|
||||
|
||||
class CCMMACLengthTest(unittest.TestCase):
|
||||
"""CCM specific tests about MAC"""
|
||||
|
||||
def __init__(self, module):
|
||||
unittest.TestCase.__init__(self)
|
||||
self.module = module
|
||||
self.key = b('\xFF')*16
|
||||
self.iv = b('\x00')*10
|
||||
|
||||
def shortDescription(self):
|
||||
return self.description
|
||||
|
||||
def runTest(self):
|
||||
"""Verify that MAC can only be 4,6,8,..,16 bytes long."""
|
||||
for i in range(3,16,2):
|
||||
self.description = "CCM MAC length check (%d bytes)" % i
|
||||
self.assertRaises(ValueError, self.module.new, self.key,
|
||||
self.module.MODE_CCM, self.iv, msg_len=10, mac_len=i)
|
||||
|
||||
"""Verify that default MAC length is 16."""
|
||||
self.description = "CCM default MAC length check"
|
||||
cipher = self.module.new(self.key, self.module.MODE_CCM,
|
||||
self.iv, msg_len=4)
|
||||
cipher.encrypt(b('z')*4)
|
||||
self.assertEqual(len(cipher.digest()), 16)
|
||||
|
||||
class CCMSplitEncryptionTest(unittest.TestCase):
|
||||
"""CCM specific tests to validate how encrypt()
|
||||
decrypt() can be called multiple times on the
|
||||
same object."""
|
||||
|
||||
def __init__(self, module):
|
||||
unittest.TestCase.__init__(self)
|
||||
self.module = module
|
||||
self.key = b('\xFF')*16
|
||||
self.iv = b('\x00')*10
|
||||
self.description = "CCM Split Encryption Test"
|
||||
|
||||
def shortDescription(self):
|
||||
return self.description
|
||||
|
||||
def runTest(self):
|
||||
"""Verify that CCM update()/encrypt() can be called multiple times,
|
||||
provided that lengths are declared beforehand"""
|
||||
|
||||
data = b("AUTH DATA")
|
||||
pt1 = b("PLAINTEXT1") # Short
|
||||
pt2 = b("PLAINTEXT2") # Long
|
||||
pt_ref = pt1+pt2
|
||||
|
||||
# REFERENCE: Run with 1 update() and 1 encrypt()
|
||||
cipher = self.module.new(self.key, self.module.MODE_CCM,
|
||||
self.iv)
|
||||
cipher.update(data)
|
||||
ct_ref = cipher.encrypt(pt_ref)
|
||||
mac_ref = cipher.digest()
|
||||
|
||||
# Verify that calling CCM encrypt()/decrypt() twice is not
|
||||
# possible without the 'msg_len' parameter and regardless
|
||||
# of the 'assoc_len' parameter
|
||||
for ad_len in None, len(data):
|
||||
cipher = self.module.new(self.key, self.module.MODE_CCM,
|
||||
self.iv, assoc_len=ad_len)
|
||||
cipher.update(data)
|
||||
cipher.encrypt(pt1)
|
||||
self.assertRaises(TypeError, cipher.encrypt, pt2)
|
||||
|
||||
cipher = self.module.new(self.key, self.module.MODE_CCM,
|
||||
self.iv, assoc_len=ad_len)
|
||||
cipher.update(data)
|
||||
cipher.decrypt(ct_ref[:len(pt1)])
|
||||
self.assertRaises(TypeError, cipher.decrypt, ct_ref[len(pt1):])
|
||||
|
||||
# Run with 2 encrypt()/decrypt(). Results must be the same
|
||||
# regardless of the 'assoc_len' parameter
|
||||
for ad_len in None, len(data):
|
||||
cipher = self.module.new(self.key, self.module.MODE_CCM,
|
||||
self.iv, assoc_len=ad_len, msg_len=len(pt_ref))
|
||||
cipher.update(data)
|
||||
ct = cipher.encrypt(pt1)
|
||||
ct += cipher.encrypt(pt2)
|
||||
mac = cipher.digest()
|
||||
self.assertEqual(ct_ref, ct)
|
||||
self.assertEqual(mac_ref, mac)
|
||||
|
||||
cipher = self.module.new(self.key, self.module.MODE_CCM,
|
||||
self.iv, msg_len=len(pt1+pt2))
|
||||
cipher.update(data)
|
||||
pt = cipher.decrypt(ct[:len(pt1)])
|
||||
pt += cipher.decrypt(ct[len(pt1):])
|
||||
mac = cipher.verify(mac_ref)
|
||||
self.assertEqual(pt_ref, pt)
|
||||
|
||||
class AEADTests(unittest.TestCase):
|
||||
"""Tests generic to all AEAD modes"""
|
||||
|
||||
def __init__(self, module, mode_name, key_size):
|
||||
unittest.TestCase.__init__(self)
|
||||
self.module = module
|
||||
self.mode_name = mode_name
|
||||
self.mode = getattr(module, mode_name)
|
||||
if not self.isMode("SIV"):
|
||||
self.key = b('\xFF')*key_size
|
||||
else:
|
||||
self.key = b('\xFF')*key_size*2
|
||||
self.iv = b('\x00')*10
|
||||
self.description = "AEAD Test"
|
||||
|
||||
def isMode(self, name):
|
||||
if not hasattr(self.module, "MODE_"+name):
|
||||
return False
|
||||
return self.mode == getattr(self.module, "MODE_"+name)
|
||||
|
||||
def right_mac_test(self):
|
||||
"""Positive tests for MAC"""
|
||||
|
||||
self.description = "Test for right MAC in %s of %s" % \
|
||||
(self.mode_name, self.module.__name__)
|
||||
|
||||
ad_ref = b("Reference AD")
|
||||
pt_ref = b("Reference plaintext")
|
||||
|
||||
# Encrypt and create the reference MAC
|
||||
cipher = self.module.new(self.key, self.mode, self.iv)
|
||||
cipher.update(ad_ref)
|
||||
ct_ref = cipher.encrypt(pt_ref)
|
||||
mac_ref = cipher.digest()
|
||||
|
||||
# Decrypt and verify that MAC is accepted
|
||||
decipher = self.module.new(self.key, self.mode, self.iv)
|
||||
decipher.update(ad_ref)
|
||||
pt = decipher.decrypt_and_verify(ct_ref, mac_ref)
|
||||
self.assertEqual(pt, pt_ref)
|
||||
|
||||
# Verify that hexverify work
|
||||
decipher.hexverify(hexlify(mac_ref))
|
||||
|
||||
def wrong_mac_test(self):
|
||||
"""Negative tests for MAC"""
|
||||
|
||||
self.description = "Test for wrong MAC in %s of %s" % \
|
||||
(self.mode_name, self.module.__name__)
|
||||
|
||||
ad_ref = b("Reference AD")
|
||||
pt_ref = b("Reference plaintext")
|
||||
|
||||
# Encrypt and create the reference MAC
|
||||
cipher = self.module.new(self.key, self.mode, self.iv)
|
||||
cipher.update(ad_ref)
|
||||
ct_ref = cipher.encrypt(pt_ref)
|
||||
mac_ref = cipher.digest()
|
||||
|
||||
# Modify the MAC and verify it is NOT ACCEPTED
|
||||
wrong_mac = strxor_c(mac_ref, 255)
|
||||
decipher = self.module.new(self.key, self.mode, self.iv)
|
||||
decipher.update(ad_ref)
|
||||
self.assertRaises(ValueError, decipher.decrypt_and_verify,
|
||||
ct_ref, wrong_mac)
|
||||
|
||||
def zero_data(self):
|
||||
"""Verify transition from INITIALIZED to FINISHED"""
|
||||
|
||||
self.description = "Test for zero data in %s of %s" % \
|
||||
(self.mode_name, self.module.__name__)
|
||||
cipher = self.module.new(self.key, self.mode, self.iv)
|
||||
cipher.digest()
|
||||
|
||||
def multiple_updates(self):
|
||||
"""Verify that update() can be called multiple times"""
|
||||
|
||||
self.description = "Test for multiple updates in %s of %s" % \
|
||||
(self.mode_name, self.module.__name__)
|
||||
|
||||
# In all modes other than SIV, the associated data is a single
|
||||
# component that can be arbitrarilly split and submitted to update().
|
||||
#
|
||||
# In SIV, associated data is instead organized in a vector or multiple
|
||||
# components. Each component is passed to update() as a whole.
|
||||
# This test is therefore not meaningful to SIV.
|
||||
if self.isMode("SIV"):
|
||||
return
|
||||
|
||||
ad = b("").join([bchr(x) for x in xrange(0,128)])
|
||||
|
||||
mac1, mac2, mac3 = (None,)*3
|
||||
for chunk_length in 1,10,40,80,128:
|
||||
chunks = [ad[i:i+chunk_length] for i in range(0, len(ad), chunk_length)]
|
||||
|
||||
# No encryption/decryption
|
||||
cipher = self.module.new(self.key, self.mode, self.iv)
|
||||
for c in chunks:
|
||||
cipher.update(c)
|
||||
if mac1:
|
||||
cipher.verify(mac1)
|
||||
else:
|
||||
mac1 = cipher.digest()
|
||||
|
||||
# Encryption
|
||||
cipher = self.module.new(self.key, self.mode, self.iv)
|
||||
for c in chunks:
|
||||
cipher.update(c)
|
||||
ct = cipher.encrypt(b("PT"))
|
||||
mac2 = cipher.digest()
|
||||
|
||||
# Decryption
|
||||
cipher = self.module.new(self.key, self.mode, self.iv)
|
||||
for c in chunks:
|
||||
cipher.update(c)
|
||||
cipher.decrypt(ct)
|
||||
cipher.verify(mac2)
|
||||
|
||||
def no_mix_encrypt_decrypt(self):
|
||||
"""Verify that encrypt and decrypt cannot be mixed up"""
|
||||
|
||||
self.description = "Test for mix of encrypt and decrypt in %s of %s" % \
|
||||
(self.mode_name, self.module.__name__)
|
||||
|
||||
# Calling decrypt after encrypt raises an exception
|
||||
cipher = self.module.new(self.key, self.mode, self.iv)
|
||||
cipher.encrypt(b("PT")*40)
|
||||
self.assertRaises(TypeError, cipher.decrypt, b("XYZ")*40)
|
||||
|
||||
# Calling encrypt() after decrypt() raises an exception
|
||||
# (excluded for SIV, since decrypt() is not valid)
|
||||
if not self.isMode("SIV"):
|
||||
cipher = self.module.new(self.key, self.mode, self.iv)
|
||||
cipher.decrypt(b("CT")*40)
|
||||
self.assertRaises(TypeError, cipher.encrypt, b("XYZ")*40)
|
||||
|
||||
# Calling verify after encrypt raises an exception
|
||||
cipher = self.module.new(self.key, self.mode, self.iv)
|
||||
cipher.encrypt(b("PT")*40)
|
||||
self.assertRaises(TypeError, cipher.verify, b("XYZ"))
|
||||
self.assertRaises(TypeError, cipher.hexverify, "12")
|
||||
|
||||
# Calling digest() after decrypt() raises an exception
|
||||
# (excluded for SIV, since decrypt() is not valid)
|
||||
if not self.isMode("SIV"):
|
||||
cipher = self.module.new(self.key, self.mode, self.iv)
|
||||
cipher.decrypt(b("CT")*40)
|
||||
self.assertRaises(TypeError, cipher.digest)
|
||||
self.assertRaises(TypeError, cipher.hexdigest)
|
||||
|
||||
def no_late_update(self):
|
||||
"""Verify that update cannot be called after encrypt or decrypt"""
|
||||
|
||||
self.description = "Test for late update in %s of %s" % \
|
||||
(self.mode_name, self.module.__name__)
|
||||
|
||||
# Calling update after encrypt raises an exception
|
||||
cipher = self.module.new(self.key, self.mode, self.iv)
|
||||
cipher.update(b("XX"))
|
||||
cipher.encrypt(b("PT")*40)
|
||||
self.assertRaises(TypeError, cipher.update, b("XYZ"))
|
||||
|
||||
# Calling update() after decrypt() raises an exception
|
||||
# (excluded for SIV, since decrypt() is not valid)
|
||||
if not self.isMode("SIV"):
|
||||
cipher = self.module.new(self.key, self.mode, self.iv)
|
||||
cipher.update(b("XX"))
|
||||
cipher.decrypt(b("CT")*40)
|
||||
self.assertRaises(TypeError, cipher.update, b("XYZ"))
|
||||
|
||||
def loopback(self):
|
||||
"""Verify composition of encrypt_and_digest() and decrypt_and_verify()
|
||||
is the identity function."""
|
||||
|
||||
self.description = "Lookback test decrypt_and_verify(encrypt_and_digest)"\
|
||||
"for %s in %s" % (self.mode_name,
|
||||
self.module.__name__)
|
||||
|
||||
enc_cipher = self.module.new(self.key, self.mode, self.iv)
|
||||
dec_cipher = self.module.new(self.key, self.mode, self.iv)
|
||||
|
||||
enc_cipher.update(b("XXX"))
|
||||
dec_cipher.update(b("XXX"))
|
||||
|
||||
plaintext = b("Reference") * 10
|
||||
ct, mac = enc_cipher.encrypt_and_digest(plaintext)
|
||||
pt = dec_cipher.decrypt_and_verify(ct, mac)
|
||||
|
||||
self.assertEqual(plaintext, pt)
|
||||
|
||||
def runTest(self):
|
||||
self.right_mac_test()
|
||||
self.wrong_mac_test()
|
||||
self.zero_data()
|
||||
self.multiple_updates()
|
||||
self.no_mix_encrypt_decrypt()
|
||||
self.no_late_update()
|
||||
self.loopback()
|
||||
|
||||
def shortDescription(self):
|
||||
return self.description
|
||||
|
||||
class RoundtripTest(unittest.TestCase):
|
||||
def __init__(self, module, params):
|
||||
from Crypto import Random
|
||||
@@ -608,7 +242,7 @@ class RoundtripTest(unittest.TestCase):
|
||||
for mode in (self.module.MODE_ECB, self.module.MODE_CBC, self.module.MODE_CFB, self.module.MODE_OFB, self.module.MODE_OPENPGP):
|
||||
encryption_cipher = self.module.new(a2b_hex(self.key), mode, self.iv)
|
||||
ciphertext = encryption_cipher.encrypt(self.plaintext)
|
||||
|
||||
|
||||
if mode != self.module.MODE_OPENPGP:
|
||||
decryption_cipher = self.module.new(a2b_hex(self.key), mode, self.iv)
|
||||
else:
|
||||
@@ -649,17 +283,13 @@ class IVLengthTest(unittest.TestCase):
|
||||
self.module.MODE_OFB, "")
|
||||
self.assertRaises(ValueError, self.module.new, a2b_hex(self.key),
|
||||
self.module.MODE_OPENPGP, "")
|
||||
if hasattr(self.module, "MODE_CCM"):
|
||||
for ivlen in (0,6,14):
|
||||
self.assertRaises(ValueError, self.module.new, a2b_hex(self.key),
|
||||
self.module.MODE_CCM, bchr(0)*ivlen, msg_len=10)
|
||||
self.module.new(a2b_hex(self.key), self.module.MODE_ECB, "")
|
||||
self.module.new(a2b_hex(self.key), self.module.MODE_CTR, "", counter=self._dummy_counter)
|
||||
|
||||
def _dummy_counter(self):
|
||||
return "\0" * self.module.block_size
|
||||
|
||||
def make_block_tests(module, module_name, test_data, additional_params=dict()):
|
||||
def make_block_tests(module, module_name, test_data):
|
||||
tests = []
|
||||
extra_tests_added = 0
|
||||
for i in range(len(test_data)):
|
||||
@@ -696,7 +326,6 @@ def make_block_tests(module, module_name, test_data, additional_params=dict()):
|
||||
name = "%s #%d: %s" % (module_name, i+1, description)
|
||||
params['description'] = name
|
||||
params['module_name'] = module_name
|
||||
params.update(additional_params)
|
||||
|
||||
# Add extra test(s) to the test suite before the current test
|
||||
if not extra_tests_added:
|
||||
@@ -710,18 +339,11 @@ def make_block_tests(module, module_name, test_data, additional_params=dict()):
|
||||
]
|
||||
extra_tests_added = 1
|
||||
|
||||
# Extract associated data and MAC for AEAD modes
|
||||
if p_mode in ('CCM', 'EAX', 'SIV', 'GCM'):
|
||||
assoc_data, params['plaintext'] = params['plaintext'].split('|')
|
||||
assoc_data2, params['ciphertext'], params['mac'] = params['ciphertext'].split('|')
|
||||
params['assoc_data'] = assoc_data.split("-")
|
||||
params['mac_len'] = len(params['mac'])>>1
|
||||
|
||||
# Add the current test to the test suite
|
||||
tests.append(CipherSelfTest(module, params))
|
||||
|
||||
# When using CTR mode, test that the interface behaves like a stream cipher
|
||||
if p_mode in ('OFB', 'CTR'):
|
||||
if p_mode == 'CTR':
|
||||
tests.append(CipherStreamingSelfTest(module, params))
|
||||
|
||||
# When using CTR mode, test the non-shortcut code path.
|
||||
@@ -733,25 +355,6 @@ def make_block_tests(module, module_name, test_data, additional_params=dict()):
|
||||
if not params2['ctr_params'].has_key('disable_shortcut'):
|
||||
params2['ctr_params']['disable_shortcut'] = 1
|
||||
tests.append(CipherSelfTest(module, params2))
|
||||
|
||||
# Add tests that don't use test vectors
|
||||
if hasattr(module, "MODE_CCM"):
|
||||
tests += [
|
||||
CCMMACLengthTest(module),
|
||||
CCMSplitEncryptionTest(module),
|
||||
]
|
||||
for aead_mode in ("MODE_CCM","MODE_EAX", "MODE_SIV", "MODE_GCM"):
|
||||
if hasattr(module, aead_mode):
|
||||
key_sizes = []
|
||||
try:
|
||||
key_sizes += module.key_size
|
||||
except TypeError:
|
||||
key_sizes = [ module.key_size ]
|
||||
for ks in key_sizes:
|
||||
tests += [
|
||||
AEADTests(module, aead_mode, ks),
|
||||
]
|
||||
|
||||
return tests
|
||||
|
||||
def make_stream_tests(module, module_name, test_data):
|
||||
|
||||
@@ -26,11 +26,8 @@
|
||||
|
||||
__revision__ = "$Id$"
|
||||
|
||||
import sys
|
||||
if sys.version_info[0] == 2 and sys.version_info[1] == 1:
|
||||
from Crypto.Util.py21compat import *
|
||||
from Crypto.Util.py3compat import *
|
||||
from common import dict # For compatibility with Python 2.1 and 2.2
|
||||
from Crypto.Util.py3compat import *
|
||||
from binascii import hexlify
|
||||
|
||||
# This is a list of (plaintext, ciphertext, key[, description[, params]]) tuples.
|
||||
@@ -1323,30 +1320,6 @@ test_data = [
|
||||
'NIST 800-38A, F.4.5, OFB and AES-256',
|
||||
dict(mode='OFB', iv='000102030405060708090a0b0c0d0e0f')),
|
||||
|
||||
('6bc1bee22e409f96e93d7e117393172a'+'ae2d8a571e03ac9c9eb76fac45af8e51'+
|
||||
'30c81c46a35ce411e5fbc1191a0a52ef'+'f69f2445df4f9b17',
|
||||
'3b3fd92eb72dad20333449f8e83cfb4a'+'7789508d16918f03f53c52dac54ed825'+
|
||||
'9740051e9c5fecf64344f7a82260edcc'+'304c6528f659c778',
|
||||
'2b7e151628aed2a6abf7158809cf4f3c',
|
||||
'NIST 800-38A, F.4.1, OFB and AES-128 (partial last block)',
|
||||
dict(mode='OFB', iv='000102030405060708090a0b0c0d0e0f')),
|
||||
|
||||
('6bc1bee22e409f96e93d7e117393172a'+'ae2d8a571e03ac9c9eb76fac45af8e51'+
|
||||
'30c81c46a35ce411e5fbc1191a0a52ef'+'f69f2445df4f9b17',
|
||||
'cdc80d6fddf18cab34c25909c99a4174'+'fcc28b8d4c63837c09e81700c1100401'+
|
||||
'8d9a9aeac0f6596f559c6d4daf59a5f2'+'6d9f200857ca6c3e',
|
||||
'8e73b0f7da0e6452c810f32b809079e562f8ead2522c6b7b',
|
||||
'NIST 800-38A, F.4.3, OFB and AES-192 (partial last block)',
|
||||
dict(mode='OFB', iv='000102030405060708090a0b0c0d0e0f')),
|
||||
|
||||
('6bc1bee22e409f96e93d7e117393172a'+'ae2d8a571e03ac9c9eb76fac45af8e51'+
|
||||
'30c81c46a35ce411e5fbc1191a0a52ef'+'f69f2445df4f9b17',
|
||||
'dc7e84bfda79164b7ecd8486985d3860'+'4febdc6740d20b3ac88f6ad82a4fb08d'+
|
||||
'71ab47a086e86eedf39d1c5bba97c408'+'0126141d67f37be8',
|
||||
'603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4',
|
||||
'NIST 800-38A, F.4.5, OFB and AES-256 (partial last block)',
|
||||
dict(mode='OFB', iv='000102030405060708090a0b0c0d0e0f')),
|
||||
|
||||
('6bc1bee22e409f96e93d7e117393172a'+'ae2d8a571e03ac9c9eb76fac45af8e51'+
|
||||
'30c81c46a35ce411e5fbc1191a0a52ef'+'f69f2445df4f9b17ad2b417be66c3710',
|
||||
'874d6191b620e3261bef6864990db6ce'+'9806f66b7970fdff8617187bb9fffdff'+
|
||||
@@ -1445,565 +1418,12 @@ test_data = [
|
||||
'5baa61e4c9b93f3f0682250b6cf8331b', # Key (hash of 'password')
|
||||
'GPG Test Vector #1',
|
||||
dict(mode='OPENPGP', iv='3d7d3e62282add7eb203eeba5c800733', encrypted_iv='fd934601ef49cb58b6d9aebca6056bdb96ef' ) ),
|
||||
|
||||
# NIST SP 800-38C test vectors for CCM
|
||||
# This is a list of tuples with 5 items:
|
||||
#
|
||||
# 1. Associated data + '|' + plaintext
|
||||
# 2. Associated data + '|' + ciphertext + '|' + MAC
|
||||
# 3. AES-128 key
|
||||
# 4. Description
|
||||
# 5. Dictionary of parameters to be passed to AES.new().
|
||||
# It must include the nonce.
|
||||
#
|
||||
( '0001020304050607|20212223',
|
||||
'0001020304050607|7162015b|4dac255d',
|
||||
'404142434445464748494a4b4c4d4e4f',
|
||||
'NIST SP 800-38C Appex C.1',
|
||||
dict(mode='CCM', nonce='10111213141516')
|
||||
),
|
||||
( '000102030405060708090a0b0c0d0e0f|202122232425262728292a2b2c2d2e2f',
|
||||
'000102030405060708090a0b0c0d0e0f|d2a1f0e051ea5f62081a7792073d593d|1fc64fbfaccd',
|
||||
'404142434445464748494a4b4c4d4e4f',
|
||||
'NIST SP 800-38C Appex C.2',
|
||||
dict(mode='CCM', nonce='1011121314151617')
|
||||
),
|
||||
( '000102030405060708090a0b0c0d0e0f10111213|'+
|
||||
'202122232425262728292a2b2c2d2e2f3031323334353637',
|
||||
'000102030405060708090a0b0c0d0e0f10111213|'+
|
||||
'e3b201a9f5b71a7a9b1ceaeccd97e70b6176aad9a4428aa5|484392fbc1b09951',
|
||||
'404142434445464748494a4b4c4d4e4f',
|
||||
'NIST SP 800-38C Appex C.3',
|
||||
dict(mode='CCM', nonce='101112131415161718191a1b')
|
||||
),
|
||||
(
|
||||
(''.join(["%02X" % (x*16+y) for x in xrange(0,16) for y in xrange(0,16)]))*256+'|'+
|
||||
'202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f',
|
||||
(''.join(["%02X" % (x*16+y) for x in xrange(0,16) for y in xrange(0,16)]))*256+'|'+
|
||||
'69915dad1e84c6376a68c2967e4dab615ae0fd1faec44cc484828529463ccf72|'+
|
||||
'b4ac6bec93e8598e7f0dadbcea5b',
|
||||
'404142434445464748494a4b4c4d4e4f',
|
||||
'NIST SP 800-38C Appex C.4',
|
||||
dict(mode='CCM', nonce='101112131415161718191a1b1c')
|
||||
),
|
||||
# RFC3610 test vectors
|
||||
(
|
||||
'0001020304050607|08090a0b0c0d0e0f101112131415161718191a1b1c1d1e',
|
||||
'0001020304050607|588c979a61c663d2f066d0c2c0f989806d5f6b61dac384|'+
|
||||
'17e8d12cfdf926e0',
|
||||
'c0c1c2c3c4c5c6c7c8c9cacbcccdcecf',
|
||||
'RFC3610 Packet Vector #1',
|
||||
dict(mode='CCM', nonce='00000003020100a0a1a2a3a4a5')
|
||||
),
|
||||
(
|
||||
'0001020304050607|08090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f',
|
||||
'0001020304050607|72c91a36e135f8cf291ca894085c87e3cc15c439c9e43a3b|'+
|
||||
'a091d56e10400916',
|
||||
'c0c1c2c3c4c5c6c7c8c9cacbcccdcecf',
|
||||
'RFC3610 Packet Vector #2',
|
||||
dict(mode='CCM', nonce='00000004030201a0a1a2a3a4a5')
|
||||
),
|
||||
(
|
||||
'0001020304050607|08090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f20',
|
||||
'0001020304050607|51b1e5f44a197d1da46b0f8e2d282ae871e838bb64da859657|'+
|
||||
'4adaa76fbd9fb0c5',
|
||||
'c0c1c2c3c4c5c6c7c8c9cacbcccdcecf',
|
||||
'RFC3610 Packet Vector #3',
|
||||
dict(mode='CCM', nonce='00000005040302A0A1A2A3A4A5')
|
||||
),
|
||||
(
|
||||
'000102030405060708090a0b|0c0d0e0f101112131415161718191a1b1c1d1e',
|
||||
'000102030405060708090a0b|a28c6865939a9a79faaa5c4c2a9d4a91cdac8c|'+
|
||||
'96c861b9c9e61ef1',
|
||||
'c0c1c2c3c4c5c6c7c8c9cacbcccdcecf',
|
||||
'RFC3610 Packet Vector #4',
|
||||
dict(mode='CCM', nonce='00000006050403a0a1a2a3a4a5')
|
||||
),
|
||||
(
|
||||
'000102030405060708090a0b|0c0d0e0f101112131415161718191a1b1c1d1e1f',
|
||||
'000102030405060708090a0b|dcf1fb7b5d9e23fb9d4e131253658ad86ebdca3e|'+
|
||||
'51e83f077d9c2d93',
|
||||
'c0c1c2c3c4c5c6c7c8c9cacbcccdcecf',
|
||||
'RFC3610 Packet Vector #5',
|
||||
dict(mode='CCM', nonce='00000007060504a0a1a2a3a4a5')
|
||||
),
|
||||
(
|
||||
'000102030405060708090a0b|0c0d0e0f101112131415161718191a1b1c1d1e1f20',
|
||||
'000102030405060708090a0b|6fc1b011f006568b5171a42d953d469b2570a4bd87|'+
|
||||
'405a0443ac91cb94',
|
||||
'c0c1c2c3c4c5c6c7c8c9cacbcccdcecf',
|
||||
'RFC3610 Packet Vector #6',
|
||||
dict(mode='CCM', nonce='00000008070605a0a1a2a3a4a5')
|
||||
),
|
||||
(
|
||||
'0001020304050607|08090a0b0c0d0e0f101112131415161718191a1b1c1d1e',
|
||||
'0001020304050607|0135d1b2c95f41d5d1d4fec185d166b8094e999dfed96c|'+
|
||||
'048c56602c97acbb7490',
|
||||
'c0c1c2c3c4c5c6c7c8c9cacbcccdcecf',
|
||||
'RFC3610 Packet Vector #7',
|
||||
dict(mode='CCM', nonce='00000009080706a0a1a2a3a4a5')
|
||||
),
|
||||
(
|
||||
'0001020304050607|08090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f',
|
||||
'0001020304050607|7b75399ac0831dd2f0bbd75879a2fd8f6cae6b6cd9b7db24|'+
|
||||
'c17b4433f434963f34b4',
|
||||
'c0c1c2c3c4c5c6c7c8c9cacbcccdcecf',
|
||||
'RFC3610 Packet Vector #8',
|
||||
dict(mode='CCM', nonce='0000000a090807a0a1a2a3a4a5')
|
||||
),
|
||||
(
|
||||
'0001020304050607|08090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f20',
|
||||
'0001020304050607|82531a60cc24945a4b8279181ab5c84df21ce7f9b73f42e197|'+
|
||||
'ea9c07e56b5eb17e5f4e',
|
||||
'c0c1c2c3c4c5c6c7c8c9cacbcccdcecf',
|
||||
'RFC3610 Packet Vector #9',
|
||||
dict(mode='CCM', nonce='0000000b0a0908a0a1a2a3a4a5')
|
||||
),
|
||||
(
|
||||
'000102030405060708090a0b|0c0d0e0f101112131415161718191a1b1c1d1e',
|
||||
'000102030405060708090a0b|07342594157785152b074098330abb141b947b|'+
|
||||
'566aa9406b4d999988dd',
|
||||
'c0c1c2c3c4c5c6c7c8c9cacbcccdcecf',
|
||||
'RFC3610 Packet Vector #10',
|
||||
dict(mode='CCM', nonce='0000000c0b0a09a0a1a2a3a4a5')
|
||||
),
|
||||
(
|
||||
'000102030405060708090a0b|0c0d0e0f101112131415161718191a1b1c1d1e1f',
|
||||
'000102030405060708090a0b|676bb20380b0e301e8ab79590a396da78b834934|'+
|
||||
'f53aa2e9107a8b6c022c',
|
||||
'c0c1c2c3c4c5c6c7c8c9cacbcccdcecf',
|
||||
'RFC3610 Packet Vector #11',
|
||||
dict(mode='CCM', nonce='0000000d0c0b0aa0a1a2a3a4a5')
|
||||
),
|
||||
(
|
||||
'000102030405060708090a0b|0c0d0e0f101112131415161718191a1b1c1d1e1f20',
|
||||
'000102030405060708090a0b|c0ffa0d6f05bdb67f24d43a4338d2aa4bed7b20e43|'+
|
||||
'cd1aa31662e7ad65d6db',
|
||||
'c0c1c2c3c4c5c6c7c8c9cacbcccdcecf',
|
||||
'RFC3610 Packet Vector #12',
|
||||
dict(mode='CCM', nonce='0000000e0d0c0ba0a1a2a3a4a5')
|
||||
),
|
||||
(
|
||||
'0be1a88bace018b1|08e8cf97d820ea258460e96ad9cf5289054d895ceac47c',
|
||||
'0be1a88bace018b1|4cb97f86a2a4689a877947ab8091ef5386a6ffbdd080f8|'+
|
||||
'e78cf7cb0cddd7b3',
|
||||
'd7828d13b2b0bdc325a76236df93cc6b',
|
||||
'RFC3610 Packet Vector #13',
|
||||
dict(mode='CCM', nonce='00412b4ea9cdbe3c9696766cfa')
|
||||
),
|
||||
(
|
||||
'63018f76dc8a1bcb|9020ea6f91bdd85afa0039ba4baff9bfb79c7028949cd0ec',
|
||||
'63018f76dc8a1bcb|4ccb1e7ca981befaa0726c55d378061298c85c92814abc33|'+
|
||||
'c52ee81d7d77c08a',
|
||||
'd7828d13b2b0bdc325a76236df93cc6b',
|
||||
'RFC3610 Packet Vector #14',
|
||||
dict(mode='CCM', nonce='0033568ef7b2633c9696766cfa')
|
||||
),
|
||||
(
|
||||
'aa6cfa36cae86b40|b916e0eacc1c00d7dcec68ec0b3bbb1a02de8a2d1aa346132e',
|
||||
'aa6cfa36cae86b40|b1d23a2220ddc0ac900d9aa03c61fcf4a559a4417767089708|'+
|
||||
'a776796edb723506',
|
||||
'd7828d13b2b0bdc325a76236df93cc6b',
|
||||
'RFC3610 Packet Vector #15',
|
||||
dict(mode='CCM', nonce='00103fe41336713c9696766cfa')
|
||||
),
|
||||
(
|
||||
'd0d0735c531e1becf049c244|12daac5630efa5396f770ce1a66b21f7b2101c',
|
||||
'd0d0735c531e1becf049c244|14d253c3967b70609b7cbb7c49916028324526|'+
|
||||
'9a6f49975bcadeaf',
|
||||
'd7828d13b2b0bdc325a76236df93cc6b',
|
||||
'RFC3610 Packet Vector #16',
|
||||
dict(mode='CCM', nonce='00764c63b8058e3c9696766cfa')
|
||||
),
|
||||
(
|
||||
'77b60f011c03e1525899bcae|e88b6a46c78d63e52eb8c546efb5de6f75e9cc0d',
|
||||
'77b60f011c03e1525899bcae|5545ff1a085ee2efbf52b2e04bee1e2336c73e3f|'+
|
||||
'762c0c7744fe7e3c',
|
||||
'd7828d13b2b0bdc325a76236df93cc6b',
|
||||
'RFC3610 Packet Vector #17',
|
||||
dict(mode='CCM', nonce='00f8b678094e3b3c9696766cfa')
|
||||
),
|
||||
(
|
||||
'cd9044d2b71fdb8120ea60c0|6435acbafb11a82e2f071d7ca4a5ebd93a803ba87f',
|
||||
'cd9044d2b71fdb8120ea60c0|009769ecabdf48625594c59251e6035722675e04c8|'+
|
||||
'47099e5ae0704551',
|
||||
'd7828d13b2b0bdc325a76236df93cc6b',
|
||||
'RFC3610 Packet Vector #18',
|
||||
dict(mode='CCM', nonce='00d560912d3f703c9696766cfa')
|
||||
),
|
||||
(
|
||||
'd85bc7e69f944fb8|8a19b950bcf71a018e5e6701c91787659809d67dbedd18',
|
||||
'd85bc7e69f944fb8|bc218daa947427b6db386a99ac1aef23ade0b52939cb6a|'+
|
||||
'637cf9bec2408897c6ba',
|
||||
'd7828d13b2b0bdc325a76236df93cc6b',
|
||||
'RFC3610 Packet Vector #19',
|
||||
dict(mode='CCM', nonce='0042fff8f1951c3c9696766cfa')
|
||||
),
|
||||
(
|
||||
'74a0ebc9069f5b37|1761433c37c5a35fc1f39f406302eb907c6163be38c98437',
|
||||
'74a0ebc9069f5b37|5810e6fd25874022e80361a478e3e9cf484ab04f447efff6|'+
|
||||
'f0a477cc2fc9bf548944',
|
||||
'd7828d13b2b0bdc325a76236df93cc6b',
|
||||
'RFC3610 Packet Vector #20',
|
||||
dict(mode='CCM', nonce='00920f40e56cdc3c9696766cfa')
|
||||
),
|
||||
(
|
||||
'44a3aa3aae6475ca|a434a8e58500c6e41530538862d686ea9e81301b5ae4226bfa',
|
||||
'44a3aa3aae6475ca|f2beed7bc5098e83feb5b31608f8e29c38819a89c8e776f154|'+
|
||||
'4d4151a4ed3a8b87b9ce',
|
||||
'd7828d13b2b0bdc325a76236df93cc6b',
|
||||
'RFC3610 Packet Vector #21',
|
||||
dict(mode='CCM', nonce='0027ca0c7120bc3c9696766cfa')
|
||||
),
|
||||
(
|
||||
'ec46bb63b02520c33c49fd70|b96b49e21d621741632875db7f6c9243d2d7c2',
|
||||
'ec46bb63b02520c33c49fd70|31d750a09da3ed7fddd49a2032aabf17ec8ebf|'+
|
||||
'7d22c8088c666be5c197',
|
||||
'd7828d13b2b0bdc325a76236df93cc6b',
|
||||
'RFC3610 Packet Vector #22',
|
||||
dict(mode='CCM', nonce='005b8ccbcd9af83c9696766cfa')
|
||||
),
|
||||
(
|
||||
'47a65ac78b3d594227e85e71|e2fcfbb880442c731bf95167c8ffd7895e337076',
|
||||
'47a65ac78b3d594227e85e71|e882f1dbd38ce3eda7c23f04dd65071eb41342ac|'+
|
||||
'df7e00dccec7ae52987d',
|
||||
'd7828d13b2b0bdc325a76236df93cc6b',
|
||||
'RFC3610 Packet Vector #23',
|
||||
dict(mode='CCM', nonce='003ebe94044b9a3c9696766cfa')
|
||||
),
|
||||
(
|
||||
'6e37a6ef546d955d34ab6059|abf21c0b02feb88f856df4a37381bce3cc128517d4',
|
||||
'6e37a6ef546d955d34ab6059|f32905b88a641b04b9c9ffb58cc390900f3da12ab1|'+
|
||||
'6dce9e82efa16da62059',
|
||||
'd7828d13b2b0bdc325a76236df93cc6b',
|
||||
'RFC3610 Packet Vector #24',
|
||||
dict(mode='CCM', nonce='008d493b30ae8b3c9696766cfa')
|
||||
),
|
||||
|
||||
# Test vectors for EAX taken from http://www.cs.ucdavis.edu/~rogaway/papers/eax.pdf
|
||||
# This is a list of tuples with 5 items:
|
||||
#
|
||||
# 1. Header + '|' + plaintext
|
||||
# 2. Header + '|' + ciphertext + '|' + MAC
|
||||
# 3. AES-128 key
|
||||
# 4. Description
|
||||
# 5. Dictionary of parameters to be passed to AES.new(). It must
|
||||
# include the nonce.
|
||||
#
|
||||
( '6bfb914fd07eae6b|',
|
||||
'6bfb914fd07eae6b||e037830e8389f27b025a2d6527e79d01',
|
||||
'233952dee4d5ed5f9b9c6d6ff80ff478',
|
||||
'EAX spec Appendix G',
|
||||
dict(mode='EAX', nonce='62EC67F9C3A4A407FCB2A8C49031A8B3')
|
||||
),
|
||||
|
||||
( 'fa3bfd4806eb53fa|f7fb',
|
||||
'fa3bfd4806eb53fa|19dd|5c4c9331049d0bdab0277408f67967e5',
|
||||
'91945d3f4dcbee0bf45ef52255f095a4',
|
||||
'EAX spec Appendix G',
|
||||
dict(mode='EAX', nonce='BECAF043B0A23D843194BA972C66DEBD')
|
||||
),
|
||||
|
||||
( '234a3463c1264ac6|1a47cb4933',
|
||||
'234a3463c1264ac6|d851d5bae0|3a59f238a23e39199dc9266626c40f80',
|
||||
'01f74ad64077f2e704c0f60ada3dd523',
|
||||
'EAX spec Appendix G',
|
||||
dict(mode='EAX', nonce='70C3DB4F0D26368400A10ED05D2BFF5E')
|
||||
),
|
||||
|
||||
( '33cce2eabff5a79d|481c9e39b1',
|
||||
'33cce2eabff5a79d|632a9d131a|d4c168a4225d8e1ff755939974a7bede',
|
||||
'd07cf6cbb7f313bdde66b727afd3c5e8',
|
||||
'EAX spec Appendix G',
|
||||
dict(mode='EAX', nonce='8408DFFF3C1A2B1292DC199E46B7D617')
|
||||
),
|
||||
|
||||
( 'aeb96eaebe2970e9|40d0c07da5e4',
|
||||
'aeb96eaebe2970e9|071dfe16c675|cb0677e536f73afe6a14b74ee49844dd',
|
||||
'35b6d0580005bbc12b0587124557d2c2',
|
||||
'EAX spec Appendix G',
|
||||
dict(mode='EAX', nonce='FDB6B06676EEDC5C61D74276E1F8E816')
|
||||
),
|
||||
|
||||
( 'd4482d1ca78dce0f|4de3b35c3fc039245bd1fb7d',
|
||||
'd4482d1ca78dce0f|835bb4f15d743e350e728414|abb8644fd6ccb86947c5e10590210a4f',
|
||||
'bd8e6e11475e60b268784c38c62feb22',
|
||||
'EAX spec Appendix G',
|
||||
dict(mode='EAX', nonce='6EAC5C93072D8E8513F750935E46DA1B')
|
||||
),
|
||||
|
||||
( '65d2017990d62528|8b0a79306c9ce7ed99dae4f87f8dd61636',
|
||||
'65d2017990d62528|02083e3979da014812f59f11d52630da30|137327d10649b0aa6e1c181db617d7f2',
|
||||
'7c77d6e813bed5ac98baa417477a2e7d',
|
||||
'EAX spec Appendix G',
|
||||
dict(mode='EAX', nonce='1A8C98DCD73D38393B2BF1569DEEFC19')
|
||||
),
|
||||
|
||||
( '54b9f04e6a09189a|1bda122bce8a8dbaf1877d962b8592dd2d56',
|
||||
'54b9f04e6a09189a|2ec47b2c4954a489afc7ba4897edcdae8cc3|3b60450599bd02c96382902aef7f832a',
|
||||
'5fff20cafab119ca2fc73549e20f5b0d',
|
||||
'EAX spec Appendix G',
|
||||
dict(mode='EAX', nonce='DDE59B97D722156D4D9AFF2BC7559826')
|
||||
),
|
||||
|
||||
( '899a175897561d7e|6cf36720872b8513f6eab1a8a44438d5ef11',
|
||||
'899a175897561d7e|0de18fd0fdd91e7af19f1d8ee8733938b1e8|e7f6d2231618102fdb7fe55ff1991700',
|
||||
'a4a4782bcffd3ec5e7ef6d8c34a56123',
|
||||
'EAX spec Appendix G',
|
||||
dict(mode='EAX', nonce='B781FCF2F75FA5A8DE97A9CA48E522EC')
|
||||
),
|
||||
|
||||
( '126735fcc320d25a|ca40d7446e545ffaed3bd12a740a659ffbbb3ceab7',
|
||||
'126735fcc320d25a|cb8920f87a6c75cff39627b56e3ed197c552d295a7|cfc46afc253b4652b1af3795b124ab6e',
|
||||
'8395fcf1e95bebd697bd010bc766aac3',
|
||||
'EAX spec Appendix G',
|
||||
dict(mode='EAX', nonce='22E7ADD93CFC6393C57EC0B3C17D6B44')
|
||||
),
|
||||
|
||||
# Test vectors for SIV taken from RFC5297
|
||||
# This is a list of tuples with 5 items:
|
||||
#
|
||||
# 1. Header + '|' + plaintext
|
||||
# 2. Header + '|' + ciphertext + '|' + MAC
|
||||
# 3. AES-128 key
|
||||
# 4. Description
|
||||
# 5. Dictionary of parameters to be passed to AES.new().
|
||||
# It must include the nonce.
|
||||
#
|
||||
# A "Header" is a dash ('-') separated sequece of components.
|
||||
#
|
||||
( '101112131415161718191a1b1c1d1e1f2021222324252627|112233445566778899aabbccddee',
|
||||
'101112131415161718191a1b1c1d1e1f2021222324252627|40c02b9690c4dc04daef7f6afe5c|' +
|
||||
'85632d07c6e8f37f950acd320a2ecc93',
|
||||
'fffefdfcfbfaf9f8f7f6f5f4f3f2f1f0f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff',
|
||||
'RFC5297 A.1',
|
||||
dict(mode='SIV', nonce=None)
|
||||
),
|
||||
|
||||
( '00112233445566778899aabbccddeeffdeaddadadeaddadaffeeddccbbaa9988' +
|
||||
'7766554433221100-102030405060708090a0|' +
|
||||
'7468697320697320736f6d6520706c61696e7465787420746f20656e63727970' +
|
||||
'74207573696e67205349562d414553',
|
||||
|
||||
'00112233445566778899aabbccddeeffdeaddadadeaddadaffeeddccbbaa9988' +
|
||||
'7766554433221100-102030405060708090a0|' +
|
||||
'cb900f2fddbe404326601965c889bf17dba77ceb094fa663b7a3f748ba8af829' +
|
||||
'ea64ad544a272e9c485b62a3fd5c0d|' +
|
||||
'7bdb6e3b432667eb06f4d14bff2fbd0f',
|
||||
|
||||
'7f7e7d7c7b7a79787776757473727170404142434445464748494a4b4c4d4e4f',
|
||||
'RFC5297 A.2',
|
||||
dict(mode='SIV', nonce='09f911029d74e35bd84156c5635688c0')
|
||||
),
|
||||
|
||||
# Test vectors for GCM taken from
|
||||
# http://csrc.nist.gov/groups/ST/toolkit/BCM/documents/proposedmodes/gcm/gcm-revised-spec.pdf
|
||||
# This is a list of tuples with 5 items:
|
||||
#
|
||||
# 1. Header + '|' + plaintext
|
||||
# 2. Header + '|' + ciphertext + '|' + MAC
|
||||
# 3. AES-128 key
|
||||
# 4. Description
|
||||
# 5. Dictionary of parameters to be passed to AES.new().
|
||||
# It must include the nonce.
|
||||
#
|
||||
( '|',
|
||||
'||58e2fccefa7e3061367f1d57a4e7455a',
|
||||
'00000000000000000000000000000000',
|
||||
'GCM Test Case 1',
|
||||
dict(mode='GCM', nonce='000000000000000000000000')
|
||||
),
|
||||
|
||||
( '|00000000000000000000000000000000',
|
||||
'|0388dace60b6a392f328c2b971b2fe78|ab6e47d42cec13bdf53a67b21257bddf',
|
||||
'00000000000000000000000000000000',
|
||||
'GCM Test Case 2',
|
||||
dict(mode='GCM', nonce='000000000000000000000000')
|
||||
),
|
||||
|
||||
( '|d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a72' +
|
||||
'1c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b391aafd255',
|
||||
'|42831ec2217774244b7221b784d0d49ce3aa212f2c02a4e035c17e2329aca12e' +
|
||||
'21d514b25466931c7d8f6a5aac84aa051ba30b396a0aac973d58e091473f5985|' +
|
||||
'4d5c2af327cd64a62cf35abd2ba6fab4',
|
||||
'feffe9928665731c6d6a8f9467308308',
|
||||
'GCM Test Case 3',
|
||||
dict(mode='GCM', nonce='cafebabefacedbaddecaf888')
|
||||
),
|
||||
|
||||
( 'feedfacedeadbeeffeedfacedeadbeefabaddad2|' +
|
||||
'd9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a72' +
|
||||
'1c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39',
|
||||
'feedfacedeadbeeffeedfacedeadbeefabaddad2|' +
|
||||
'42831ec2217774244b7221b784d0d49ce3aa212f2c02a4e035c17e2329aca12e' +
|
||||
'21d514b25466931c7d8f6a5aac84aa051ba30b396a0aac973d58e091|' +
|
||||
'5bc94fbc3221a5db94fae95ae7121a47',
|
||||
'feffe9928665731c6d6a8f9467308308',
|
||||
'GCM Test Case 4',
|
||||
dict(mode='GCM', nonce='cafebabefacedbaddecaf888')
|
||||
),
|
||||
|
||||
( 'feedfacedeadbeeffeedfacedeadbeefabaddad2|' +
|
||||
'd9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a72' +
|
||||
'1c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39',
|
||||
'feedfacedeadbeeffeedfacedeadbeefabaddad2|' +
|
||||
'61353b4c2806934a777ff51fa22a4755699b2a714fcdc6f83766e5f97b6c7423' +
|
||||
'73806900e49f24b22b097544d4896b424989b5e1ebac0f07c23f4598|' +
|
||||
'3612d2e79e3b0785561be14aaca2fccb',
|
||||
'feffe9928665731c6d6a8f9467308308',
|
||||
'GCM Test Case 5',
|
||||
dict(mode='GCM', nonce='cafebabefacedbad')
|
||||
),
|
||||
|
||||
( 'feedfacedeadbeeffeedfacedeadbeefabaddad2|' +
|
||||
'd9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a72' +
|
||||
'1c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39',
|
||||
'feedfacedeadbeeffeedfacedeadbeefabaddad2|' +
|
||||
'8ce24998625615b603a033aca13fb894be9112a5c3a211a8ba262a3cca7e2ca7' +
|
||||
'01e4a9a4fba43c90ccdcb281d48c7c6fd62875d2aca417034c34aee5|' +
|
||||
'619cc5aefffe0bfa462af43c1699d050',
|
||||
'feffe9928665731c6d6a8f9467308308',
|
||||
'GCM Test Case 6',
|
||||
dict(mode='GCM', nonce='9313225df88406e555909c5aff5269aa'+
|
||||
'6a7a9538534f7da1e4c303d2a318a728c3c0c95156809539fcf0e2429a6b5254'+
|
||||
'16aedbf5a0de6a57a637b39b' )
|
||||
),
|
||||
|
||||
( '|',
|
||||
'||cd33b28ac773f74ba00ed1f312572435',
|
||||
'000000000000000000000000000000000000000000000000',
|
||||
'GCM Test Case 7',
|
||||
dict(mode='GCM', nonce='000000000000000000000000')
|
||||
),
|
||||
|
||||
( '|00000000000000000000000000000000',
|
||||
'|98e7247c07f0fe411c267e4384b0f600|2ff58d80033927ab8ef4d4587514f0fb',
|
||||
'000000000000000000000000000000000000000000000000',
|
||||
'GCM Test Case 8',
|
||||
dict(mode='GCM', nonce='000000000000000000000000')
|
||||
),
|
||||
|
||||
( '|d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a72' +
|
||||
'1c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b391aafd255',
|
||||
'|3980ca0b3c00e841eb06fac4872a2757859e1ceaa6efd984628593b40ca1e19c' +
|
||||
'7d773d00c144c525ac619d18c84a3f4718e2448b2fe324d9ccda2710acade256|' +
|
||||
'9924a7c8587336bfb118024db8674a14',
|
||||
'feffe9928665731c6d6a8f9467308308feffe9928665731c',
|
||||
'GCM Test Case 9',
|
||||
dict(mode='GCM', nonce='cafebabefacedbaddecaf888')
|
||||
),
|
||||
|
||||
( 'feedfacedeadbeeffeedfacedeadbeefabaddad2|' +
|
||||
'd9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a72' +
|
||||
'1c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39',
|
||||
'feedfacedeadbeeffeedfacedeadbeefabaddad2|' +
|
||||
'3980ca0b3c00e841eb06fac4872a2757859e1ceaa6efd984628593b40ca1e19c' +
|
||||
'7d773d00c144c525ac619d18c84a3f4718e2448b2fe324d9ccda2710|' +
|
||||
'2519498e80f1478f37ba55bd6d27618c',
|
||||
'feffe9928665731c6d6a8f9467308308feffe9928665731c',
|
||||
'GCM Test Case 10',
|
||||
dict(mode='GCM', nonce='cafebabefacedbaddecaf888')
|
||||
),
|
||||
|
||||
( 'feedfacedeadbeeffeedfacedeadbeefabaddad2|' +
|
||||
'd9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a72' +
|
||||
'1c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39',
|
||||
'feedfacedeadbeeffeedfacedeadbeefabaddad2|' +
|
||||
'0f10f599ae14a154ed24b36e25324db8c566632ef2bbb34f8347280fc4507057' +
|
||||
'fddc29df9a471f75c66541d4d4dad1c9e93a19a58e8b473fa0f062f7|' +
|
||||
'65dcc57fcf623a24094fcca40d3533f8',
|
||||
'feffe9928665731c6d6a8f9467308308feffe9928665731c',
|
||||
'GCM Test Case 11',
|
||||
dict(mode='GCM', nonce='cafebabefacedbad')
|
||||
),
|
||||
|
||||
( 'feedfacedeadbeeffeedfacedeadbeefabaddad2|' +
|
||||
'd9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a72' +
|
||||
'1c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39',
|
||||
'feedfacedeadbeeffeedfacedeadbeefabaddad2|' +
|
||||
'd27e88681ce3243c4830165a8fdcf9ff1de9a1d8e6b447ef6ef7b79828666e45' +
|
||||
'81e79012af34ddd9e2f037589b292db3e67c036745fa22e7e9b7373b|' +
|
||||
'dcf566ff291c25bbb8568fc3d376a6d9',
|
||||
'feffe9928665731c6d6a8f9467308308feffe9928665731c',
|
||||
'GCM Test Case 12',
|
||||
dict(mode='GCM', nonce='9313225df88406e555909c5aff5269aa'+
|
||||
'6a7a9538534f7da1e4c303d2a318a728c3c0c95156809539fcf0e2429a6b5254'+
|
||||
'16aedbf5a0de6a57a637b39b' )
|
||||
),
|
||||
|
||||
( '|',
|
||||
'||530f8afbc74536b9a963b4f1c4cb738b',
|
||||
'0000000000000000000000000000000000000000000000000000000000000000',
|
||||
'GCM Test Case 13',
|
||||
dict(mode='GCM', nonce='000000000000000000000000')
|
||||
),
|
||||
|
||||
( '|00000000000000000000000000000000',
|
||||
'|cea7403d4d606b6e074ec5d3baf39d18|d0d1c8a799996bf0265b98b5d48ab919',
|
||||
'0000000000000000000000000000000000000000000000000000000000000000',
|
||||
'GCM Test Case 14',
|
||||
dict(mode='GCM', nonce='000000000000000000000000')
|
||||
),
|
||||
|
||||
( '|d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a72' +
|
||||
'1c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b391aafd255',
|
||||
'|522dc1f099567d07f47f37a32a84427d643a8cdcbfe5c0c97598a2bd2555d1aa' +
|
||||
'8cb08e48590dbb3da7b08b1056828838c5f61e6393ba7a0abcc9f662898015ad|' +
|
||||
'b094dac5d93471bdec1a502270e3cc6c',
|
||||
'feffe9928665731c6d6a8f9467308308feffe9928665731c6d6a8f9467308308',
|
||||
'GCM Test Case 15',
|
||||
dict(mode='GCM', nonce='cafebabefacedbaddecaf888')
|
||||
),
|
||||
|
||||
( 'feedfacedeadbeeffeedfacedeadbeefabaddad2|' +
|
||||
'd9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a72' +
|
||||
'1c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39',
|
||||
'feedfacedeadbeeffeedfacedeadbeefabaddad2|' +
|
||||
'522dc1f099567d07f47f37a32a84427d643a8cdcbfe5c0c97598a2bd2555d1aa' +
|
||||
'8cb08e48590dbb3da7b08b1056828838c5f61e6393ba7a0abcc9f662|' +
|
||||
'76fc6ece0f4e1768cddf8853bb2d551b',
|
||||
'feffe9928665731c6d6a8f9467308308feffe9928665731c6d6a8f9467308308',
|
||||
'GCM Test Case 16',
|
||||
dict(mode='GCM', nonce='cafebabefacedbaddecaf888')
|
||||
),
|
||||
|
||||
( 'feedfacedeadbeeffeedfacedeadbeefabaddad2|' +
|
||||
'd9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a72' +
|
||||
'1c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39',
|
||||
'feedfacedeadbeeffeedfacedeadbeefabaddad2|' +
|
||||
'c3762df1ca787d32ae47c13bf19844cbaf1ae14d0b976afac52ff7d79bba9de0' +
|
||||
'feb582d33934a4f0954cc2363bc73f7862ac430e64abe499f47c9b1f|' +
|
||||
'3a337dbf46a792c45e454913fe2ea8f2',
|
||||
'feffe9928665731c6d6a8f9467308308feffe9928665731c6d6a8f9467308308',
|
||||
'GCM Test Case 17',
|
||||
dict(mode='GCM', nonce='cafebabefacedbad')
|
||||
),
|
||||
|
||||
( 'feedfacedeadbeeffeedfacedeadbeefabaddad2|' +
|
||||
'd9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a72' +
|
||||
'1c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39',
|
||||
'feedfacedeadbeeffeedfacedeadbeefabaddad2|' +
|
||||
'5a8def2f0c9e53f1f75d7853659e2a20eeb2b22aafde6419a058ab4f6f746bf4' +
|
||||
'0fc0c3b780f244452da3ebf1c5d82cdea2418997200ef82e44ae7e3f|' +
|
||||
'a44a8266ee1c8eb0c8b5d4cf5ae9f19a',
|
||||
'feffe9928665731c6d6a8f9467308308feffe9928665731c6d6a8f9467308308',
|
||||
'GCM Test Case 18',
|
||||
dict(mode='GCM', nonce='9313225df88406e555909c5aff5269aa'+
|
||||
'6a7a9538534f7da1e4c303d2a318a728c3c0c95156809539fcf0e2429a6b5254'+
|
||||
'16aedbf5a0de6a57a637b39b' )
|
||||
),
|
||||
]
|
||||
|
||||
def get_tests(config={}):
|
||||
from Crypto.Cipher import AES
|
||||
from Crypto.Util import cpuid
|
||||
from common import make_block_tests
|
||||
|
||||
tests = make_block_tests(AES, "AES", test_data, {'use_aesni': False})
|
||||
if cpuid.have_aes_ni():
|
||||
# Run tests with AES-NI instructions if they are available.
|
||||
tests += make_block_tests(AES, "AESNI", test_data, {'use_aesni': True})
|
||||
return tests
|
||||
return make_block_tests(AES, "AES", test_data)
|
||||
|
||||
if __name__ == '__main__':
|
||||
import unittest
|
||||
|
||||
@@ -27,10 +27,6 @@
|
||||
__revision__ = "$Id$"
|
||||
|
||||
from Crypto.Util.py3compat import *
|
||||
from Crypto.SelfTest.st_common import *
|
||||
from binascii import unhexlify
|
||||
|
||||
from Crypto.Cipher import ARC4
|
||||
|
||||
# This is a list of (plaintext, ciphertext, key[, description]) tuples.
|
||||
test_data = [
|
||||
@@ -72,382 +68,10 @@ test_data = [
|
||||
"Test vector 4"),
|
||||
]
|
||||
|
||||
class RFC6229_Tests(unittest.TestCase):
|
||||
# Test vectors from RFC 6229. Each test vector is a tuple with two items:
|
||||
# the ARC4 key and a dictionary. The dictionary has keystream offsets as keys
|
||||
# and the 16-byte keystream starting at the relevant offset as value.
|
||||
rfc6229_data = [
|
||||
# Page 3
|
||||
(
|
||||
'0102030405',
|
||||
{
|
||||
0: 'b2 39 63 05 f0 3d c0 27 cc c3 52 4a 0a 11 18 a8',
|
||||
16: '69 82 94 4f 18 fc 82 d5 89 c4 03 a4 7a 0d 09 19',
|
||||
240: '28 cb 11 32 c9 6c e2 86 42 1d ca ad b8 b6 9e ae',
|
||||
256: '1c fc f6 2b 03 ed db 64 1d 77 df cf 7f 8d 8c 93',
|
||||
496: '42 b7 d0 cd d9 18 a8 a3 3d d5 17 81 c8 1f 40 41',
|
||||
512: '64 59 84 44 32 a7 da 92 3c fb 3e b4 98 06 61 f6',
|
||||
752: 'ec 10 32 7b de 2b ee fd 18 f9 27 76 80 45 7e 22',
|
||||
768: 'eb 62 63 8d 4f 0b a1 fe 9f ca 20 e0 5b f8 ff 2b',
|
||||
1008:'45 12 90 48 e6 a0 ed 0b 56 b4 90 33 8f 07 8d a5',
|
||||
1024:'30 ab bc c7 c2 0b 01 60 9f 23 ee 2d 5f 6b b7 df',
|
||||
1520:'32 94 f7 44 d8 f9 79 05 07 e7 0f 62 e5 bb ce ea',
|
||||
1536:'d8 72 9d b4 18 82 25 9b ee 4f 82 53 25 f5 a1 30',
|
||||
2032:'1e b1 4a 0c 13 b3 bf 47 fa 2a 0b a9 3a d4 5b 8b',
|
||||
2048:'cc 58 2f 8b a9 f2 65 e2 b1 be 91 12 e9 75 d2 d7',
|
||||
3056:'f2 e3 0f 9b d1 02 ec bf 75 aa ad e9 bc 35 c4 3c',
|
||||
3072:'ec 0e 11 c4 79 dc 32 9d c8 da 79 68 fe 96 56 81',
|
||||
4080:'06 83 26 a2 11 84 16 d2 1f 9d 04 b2 cd 1c a0 50',
|
||||
4096:'ff 25 b5 89 95 99 67 07 e5 1f bd f0 8b 34 d8 75'
|
||||
}
|
||||
),
|
||||
# Page 4
|
||||
(
|
||||
'01020304050607',
|
||||
{
|
||||
0: '29 3f 02 d4 7f 37 c9 b6 33 f2 af 52 85 fe b4 6b',
|
||||
16: 'e6 20 f1 39 0d 19 bd 84 e2 e0 fd 75 20 31 af c1',
|
||||
240: '91 4f 02 53 1c 92 18 81 0d f6 0f 67 e3 38 15 4c',
|
||||
256: 'd0 fd b5 83 07 3c e8 5a b8 39 17 74 0e c0 11 d5',
|
||||
496: '75 f8 14 11 e8 71 cf fa 70 b9 0c 74 c5 92 e4 54',
|
||||
512: '0b b8 72 02 93 8d ad 60 9e 87 a5 a1 b0 79 e5 e4',
|
||||
752: 'c2 91 12 46 b6 12 e7 e7 b9 03 df ed a1 da d8 66',
|
||||
768: '32 82 8f 91 50 2b 62 91 36 8d e8 08 1d e3 6f c2',
|
||||
1008:'f3 b9 a7 e3 b2 97 bf 9a d8 04 51 2f 90 63 ef f1',
|
||||
1024:'8e cb 67 a9 ba 1f 55 a5 a0 67 e2 b0 26 a3 67 6f',
|
||||
1520:'d2 aa 90 2b d4 2d 0d 7c fd 34 0c d4 58 10 52 9f',
|
||||
1536:'78 b2 72 c9 6e 42 ea b4 c6 0b d9 14 e3 9d 06 e3',
|
||||
2032:'f4 33 2f d3 1a 07 93 96 ee 3c ee 3f 2a 4f f0 49',
|
||||
2048:'05 45 97 81 d4 1f da 7f 30 c1 be 7e 12 46 c6 23',
|
||||
3056:'ad fd 38 68 b8 e5 14 85 d5 e6 10 01 7e 3d d6 09',
|
||||
3072:'ad 26 58 1c 0c 5b e4 5f 4c ea 01 db 2f 38 05 d5',
|
||||
4080:'f3 17 2c ef fc 3b 3d 99 7c 85 cc d5 af 1a 95 0c',
|
||||
4096:'e7 4b 0b 97 31 22 7f d3 7c 0e c0 8a 47 dd d8 b8'
|
||||
}
|
||||
),
|
||||
(
|
||||
'0102030405060708',
|
||||
{
|
||||
0: '97 ab 8a 1b f0 af b9 61 32 f2 f6 72 58 da 15 a8',
|
||||
16: '82 63 ef db 45 c4 a1 86 84 ef 87 e6 b1 9e 5b 09',
|
||||
240: '96 36 eb c9 84 19 26 f4 f7 d1 f3 62 bd df 6e 18',
|
||||
256: 'd0 a9 90 ff 2c 05 fe f5 b9 03 73 c9 ff 4b 87 0a',
|
||||
496: '73 23 9f 1d b7 f4 1d 80 b6 43 c0 c5 25 18 ec 63',
|
||||
512: '16 3b 31 99 23 a6 bd b4 52 7c 62 61 26 70 3c 0f',
|
||||
752: '49 d6 c8 af 0f 97 14 4a 87 df 21 d9 14 72 f9 66',
|
||||
768: '44 17 3a 10 3b 66 16 c5 d5 ad 1c ee 40 c8 63 d0',
|
||||
1008:'27 3c 9c 4b 27 f3 22 e4 e7 16 ef 53 a4 7d e7 a4',
|
||||
1024:'c6 d0 e7 b2 26 25 9f a9 02 34 90 b2 61 67 ad 1d',
|
||||
1520:'1f e8 98 67 13 f0 7c 3d 9a e1 c1 63 ff 8c f9 d3',
|
||||
1536:'83 69 e1 a9 65 61 0b e8 87 fb d0 c7 91 62 aa fb',
|
||||
2032:'0a 01 27 ab b4 44 84 b9 fb ef 5a bc ae 1b 57 9f',
|
||||
2048:'c2 cd ad c6 40 2e 8e e8 66 e1 f3 7b db 47 e4 2c',
|
||||
3056:'26 b5 1e a3 7d f8 e1 d6 f7 6f c3 b6 6a 74 29 b3',
|
||||
3072:'bc 76 83 20 5d 4f 44 3d c1 f2 9d da 33 15 c8 7b',
|
||||
4080:'d5 fa 5a 34 69 d2 9a aa f8 3d 23 58 9d b8 c8 5b',
|
||||
4096:'3f b4 6e 2c 8f 0f 06 8e dc e8 cd cd 7d fc 58 62'
|
||||
}
|
||||
),
|
||||
# Page 5
|
||||
(
|
||||
'0102030405060708090a',
|
||||
{
|
||||
0: 'ed e3 b0 46 43 e5 86 cc 90 7d c2 18 51 70 99 02',
|
||||
16: '03 51 6b a7 8f 41 3b eb 22 3a a5 d4 d2 df 67 11',
|
||||
240: '3c fd 6c b5 8e e0 fd de 64 01 76 ad 00 00 04 4d',
|
||||
256: '48 53 2b 21 fb 60 79 c9 11 4c 0f fd 9c 04 a1 ad',
|
||||
496: '3e 8c ea 98 01 71 09 97 90 84 b1 ef 92 f9 9d 86',
|
||||
512: 'e2 0f b4 9b db 33 7e e4 8b 8d 8d c0 f4 af ef fe',
|
||||
752: '5c 25 21 ea cd 79 66 f1 5e 05 65 44 be a0 d3 15',
|
||||
768: 'e0 67 a7 03 19 31 a2 46 a6 c3 87 5d 2f 67 8a cb',
|
||||
1008:'a6 4f 70 af 88 ae 56 b6 f8 75 81 c0 e2 3e 6b 08',
|
||||
1024:'f4 49 03 1d e3 12 81 4e c6 f3 19 29 1f 4a 05 16',
|
||||
1520:'bd ae 85 92 4b 3c b1 d0 a2 e3 3a 30 c6 d7 95 99',
|
||||
1536:'8a 0f ed db ac 86 5a 09 bc d1 27 fb 56 2e d6 0a',
|
||||
2032:'b5 5a 0a 5b 51 a1 2a 8b e3 48 99 c3 e0 47 51 1a',
|
||||
2048:'d9 a0 9c ea 3c e7 5f e3 96 98 07 03 17 a7 13 39',
|
||||
3056:'55 22 25 ed 11 77 f4 45 84 ac 8c fa 6c 4e b5 fc',
|
||||
3072:'7e 82 cb ab fc 95 38 1b 08 09 98 44 21 29 c2 f8',
|
||||
4080:'1f 13 5e d1 4c e6 0a 91 36 9d 23 22 be f2 5e 3c',
|
||||
4096:'08 b6 be 45 12 4a 43 e2 eb 77 95 3f 84 dc 85 53'
|
||||
}
|
||||
),
|
||||
(
|
||||
'0102030405060708090a0b0c0d0e0f10',
|
||||
{
|
||||
0: '9a c7 cc 9a 60 9d 1e f7 b2 93 28 99 cd e4 1b 97',
|
||||
16: '52 48 c4 95 90 14 12 6a 6e 8a 84 f1 1d 1a 9e 1c',
|
||||
240: '06 59 02 e4 b6 20 f6 cc 36 c8 58 9f 66 43 2f 2b',
|
||||
256: 'd3 9d 56 6b c6 bc e3 01 07 68 15 15 49 f3 87 3f',
|
||||
496: 'b6 d1 e6 c4 a5 e4 77 1c ad 79 53 8d f2 95 fb 11',
|
||||
512: 'c6 8c 1d 5c 55 9a 97 41 23 df 1d bc 52 a4 3b 89',
|
||||
752: 'c5 ec f8 8d e8 97 fd 57 fe d3 01 70 1b 82 a2 59',
|
||||
768: 'ec cb e1 3d e1 fc c9 1c 11 a0 b2 6c 0b c8 fa 4d',
|
||||
1008:'e7 a7 25 74 f8 78 2a e2 6a ab cf 9e bc d6 60 65',
|
||||
1024:'bd f0 32 4e 60 83 dc c6 d3 ce dd 3c a8 c5 3c 16',
|
||||
1520:'b4 01 10 c4 19 0b 56 22 a9 61 16 b0 01 7e d2 97',
|
||||
1536:'ff a0 b5 14 64 7e c0 4f 63 06 b8 92 ae 66 11 81',
|
||||
2032:'d0 3d 1b c0 3c d3 3d 70 df f9 fa 5d 71 96 3e bd',
|
||||
2048:'8a 44 12 64 11 ea a7 8b d5 1e 8d 87 a8 87 9b f5',
|
||||
3056:'fa be b7 60 28 ad e2 d0 e4 87 22 e4 6c 46 15 a3',
|
||||
3072:'c0 5d 88 ab d5 03 57 f9 35 a6 3c 59 ee 53 76 23',
|
||||
4080:'ff 38 26 5c 16 42 c1 ab e8 d3 c2 fe 5e 57 2b f8',
|
||||
4096:'a3 6a 4c 30 1a e8 ac 13 61 0c cb c1 22 56 ca cc'
|
||||
}
|
||||
),
|
||||
# Page 6
|
||||
(
|
||||
'0102030405060708090a0b0c0d0e0f101112131415161718',
|
||||
{
|
||||
0: '05 95 e5 7f e5 f0 bb 3c 70 6e da c8 a4 b2 db 11',
|
||||
16: 'df de 31 34 4a 1a f7 69 c7 4f 07 0a ee 9e 23 26',
|
||||
240: 'b0 6b 9b 1e 19 5d 13 d8 f4 a7 99 5c 45 53 ac 05',
|
||||
256: '6b d2 37 8e c3 41 c9 a4 2f 37 ba 79 f8 8a 32 ff',
|
||||
496: 'e7 0b ce 1d f7 64 5a db 5d 2c 41 30 21 5c 35 22',
|
||||
512: '9a 57 30 c7 fc b4 c9 af 51 ff da 89 c7 f1 ad 22',
|
||||
752: '04 85 05 5f d4 f6 f0 d9 63 ef 5a b9 a5 47 69 82',
|
||||
768: '59 1f c6 6b cd a1 0e 45 2b 03 d4 55 1f 6b 62 ac',
|
||||
1008:'27 53 cc 83 98 8a fa 3e 16 88 a1 d3 b4 2c 9a 02',
|
||||
1024:'93 61 0d 52 3d 1d 3f 00 62 b3 c2 a3 bb c7 c7 f0',
|
||||
1520:'96 c2 48 61 0a ad ed fe af 89 78 c0 3d e8 20 5a',
|
||||
1536:'0e 31 7b 3d 1c 73 b9 e9 a4 68 8f 29 6d 13 3a 19',
|
||||
2032:'bd f0 e6 c3 cc a5 b5 b9 d5 33 b6 9c 56 ad a1 20',
|
||||
2048:'88 a2 18 b6 e2 ec e1 e6 24 6d 44 c7 59 d1 9b 10',
|
||||
3056:'68 66 39 7e 95 c1 40 53 4f 94 26 34 21 00 6e 40',
|
||||
3072:'32 cb 0a 1e 95 42 c6 b3 b8 b3 98 ab c3 b0 f1 d5',
|
||||
4080:'29 a0 b8 ae d5 4a 13 23 24 c6 2e 42 3f 54 b4 c8',
|
||||
4096:'3c b0 f3 b5 02 0a 98 b8 2a f9 fe 15 44 84 a1 68'
|
||||
}
|
||||
),
|
||||
(
|
||||
'0102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f20',
|
||||
{
|
||||
0: 'ea a6 bd 25 88 0b f9 3d 3f 5d 1e 4c a2 61 1d 91',
|
||||
16: 'cf a4 5c 9f 7e 71 4b 54 bd fa 80 02 7c b1 43 80',
|
||||
240: '11 4a e3 44 de d7 1b 35 f2 e6 0f eb ad 72 7f d8',
|
||||
256: '02 e1 e7 05 6b 0f 62 39 00 49 64 22 94 3e 97 b6',
|
||||
496: '91 cb 93 c7 87 96 4e 10 d9 52 7d 99 9c 6f 93 6b',
|
||||
512: '49 b1 8b 42 f8 e8 36 7c be b5 ef 10 4b a1 c7 cd',
|
||||
752: '87 08 4b 3b a7 00 ba de 95 56 10 67 27 45 b3 74',
|
||||
768: 'e7 a7 b9 e9 ec 54 0d 5f f4 3b db 12 79 2d 1b 35',
|
||||
1008:'c7 99 b5 96 73 8f 6b 01 8c 76 c7 4b 17 59 bd 90',
|
||||
1024:'7f ec 5b fd 9f 9b 89 ce 65 48 30 90 92 d7 e9 58',
|
||||
1520:'40 f2 50 b2 6d 1f 09 6a 4a fd 4c 34 0a 58 88 15',
|
||||
1536:'3e 34 13 5c 79 db 01 02 00 76 76 51 cf 26 30 73',
|
||||
2032:'f6 56 ab cc f8 8d d8 27 02 7b 2c e9 17 d4 64 ec',
|
||||
2048:'18 b6 25 03 bf bc 07 7f ba bb 98 f2 0d 98 ab 34',
|
||||
3056:'8a ed 95 ee 5b 0d cb fb ef 4e b2 1d 3a 3f 52 f9',
|
||||
3072:'62 5a 1a b0 0e e3 9a 53 27 34 6b dd b0 1a 9c 18',
|
||||
4080:'a1 3a 7c 79 c7 e1 19 b5 ab 02 96 ab 28 c3 00 b9',
|
||||
4096:'f3 e4 c0 a2 e0 2d 1d 01 f7 f0 a7 46 18 af 2b 48'
|
||||
}
|
||||
),
|
||||
# Page 7
|
||||
(
|
||||
'833222772a',
|
||||
{
|
||||
0: '80 ad 97 bd c9 73 df 8a 2e 87 9e 92 a4 97 ef da',
|
||||
16: '20 f0 60 c2 f2 e5 12 65 01 d3 d4 fe a1 0d 5f c0',
|
||||
240: 'fa a1 48 e9 90 46 18 1f ec 6b 20 85 f3 b2 0e d9',
|
||||
256: 'f0 da f5 ba b3 d5 96 83 98 57 84 6f 73 fb fe 5a',
|
||||
496: '1c 7e 2f c4 63 92 32 fe 29 75 84 b2 96 99 6b c8',
|
||||
512: '3d b9 b2 49 40 6c c8 ed ff ac 55 cc d3 22 ba 12',
|
||||
752: 'e4 f9 f7 e0 06 61 54 bb d1 25 b7 45 56 9b c8 97',
|
||||
768: '75 d5 ef 26 2b 44 c4 1a 9c f6 3a e1 45 68 e1 b9',
|
||||
1008:'6d a4 53 db f8 1e 82 33 4a 3d 88 66 cb 50 a1 e3',
|
||||
1024:'78 28 d0 74 11 9c ab 5c 22 b2 94 d7 a9 bf a0 bb',
|
||||
1520:'ad b8 9c ea 9a 15 fb e6 17 29 5b d0 4b 8c a0 5c',
|
||||
1536:'62 51 d8 7f d4 aa ae 9a 7e 4a d5 c2 17 d3 f3 00',
|
||||
2032:'e7 11 9b d6 dd 9b 22 af e8 f8 95 85 43 28 81 e2',
|
||||
2048:'78 5b 60 fd 7e c4 e9 fc b6 54 5f 35 0d 66 0f ab',
|
||||
3056:'af ec c0 37 fd b7 b0 83 8e b3 d7 0b cd 26 83 82',
|
||||
3072:'db c1 a7 b4 9d 57 35 8c c9 fa 6d 61 d7 3b 7c f0',
|
||||
4080:'63 49 d1 26 a3 7a fc ba 89 79 4f 98 04 91 4f dc',
|
||||
4096:'bf 42 c3 01 8c 2f 7c 66 bf de 52 49 75 76 81 15'
|
||||
}
|
||||
),
|
||||
(
|
||||
'1910833222772a',
|
||||
{
|
||||
0: 'bc 92 22 db d3 27 4d 8f c6 6d 14 cc bd a6 69 0b',
|
||||
16: '7a e6 27 41 0c 9a 2b e6 93 df 5b b7 48 5a 63 e3',
|
||||
240: '3f 09 31 aa 03 de fb 30 0f 06 01 03 82 6f 2a 64',
|
||||
256: 'be aa 9e c8 d5 9b b6 81 29 f3 02 7c 96 36 11 81',
|
||||
496: '74 e0 4d b4 6d 28 64 8d 7d ee 8a 00 64 b0 6c fe',
|
||||
512: '9b 5e 81 c6 2f e0 23 c5 5b e4 2f 87 bb f9 32 b8',
|
||||
752: 'ce 17 8f c1 82 6e fe cb c1 82 f5 79 99 a4 61 40',
|
||||
768: '8b df 55 cd 55 06 1c 06 db a6 be 11 de 4a 57 8a',
|
||||
1008:'62 6f 5f 4d ce 65 25 01 f3 08 7d 39 c9 2c c3 49',
|
||||
1024:'42 da ac 6a 8f 9a b9 a7 fd 13 7c 60 37 82 56 82',
|
||||
1520:'cc 03 fd b7 91 92 a2 07 31 2f 53 f5 d4 dc 33 d9',
|
||||
1536:'f7 0f 14 12 2a 1c 98 a3 15 5d 28 b8 a0 a8 a4 1d',
|
||||
2032:'2a 3a 30 7a b2 70 8a 9c 00 fe 0b 42 f9 c2 d6 a1',
|
||||
2048:'86 26 17 62 7d 22 61 ea b0 b1 24 65 97 ca 0a e9',
|
||||
3056:'55 f8 77 ce 4f 2e 1d db bf 8e 13 e2 cd e0 fd c8',
|
||||
3072:'1b 15 56 cb 93 5f 17 33 37 70 5f bb 5d 50 1f c1',
|
||||
4080:'ec d0 e9 66 02 be 7f 8d 50 92 81 6c cc f2 c2 e9',
|
||||
4096:'02 78 81 fa b4 99 3a 1c 26 20 24 a9 4f ff 3f 61'
|
||||
}
|
||||
),
|
||||
# Page 8
|
||||
(
|
||||
'641910833222772a',
|
||||
{
|
||||
0: 'bb f6 09 de 94 13 17 2d 07 66 0c b6 80 71 69 26',
|
||||
16: '46 10 1a 6d ab 43 11 5d 6c 52 2b 4f e9 36 04 a9',
|
||||
240: 'cb e1 ff f2 1c 96 f3 ee f6 1e 8f e0 54 2c bd f0',
|
||||
256: '34 79 38 bf fa 40 09 c5 12 cf b4 03 4b 0d d1 a7',
|
||||
496: '78 67 a7 86 d0 0a 71 47 90 4d 76 dd f1 e5 20 e3',
|
||||
512: '8d 3e 9e 1c ae fc cc b3 fb f8 d1 8f 64 12 0b 32',
|
||||
752: '94 23 37 f8 fd 76 f0 fa e8 c5 2d 79 54 81 06 72',
|
||||
768: 'b8 54 8c 10 f5 16 67 f6 e6 0e 18 2f a1 9b 30 f7',
|
||||
1008:'02 11 c7 c6 19 0c 9e fd 12 37 c3 4c 8f 2e 06 c4',
|
||||
1024:'bd a6 4f 65 27 6d 2a ac b8 f9 02 12 20 3a 80 8e',
|
||||
1520:'bd 38 20 f7 32 ff b5 3e c1 93 e7 9d 33 e2 7c 73',
|
||||
1536:'d0 16 86 16 86 19 07 d4 82 e3 6c da c8 cf 57 49',
|
||||
2032:'97 b0 f0 f2 24 b2 d2 31 71 14 80 8f b0 3a f7 a0',
|
||||
2048:'e5 96 16 e4 69 78 79 39 a0 63 ce ea 9a f9 56 d1',
|
||||
3056:'c4 7e 0d c1 66 09 19 c1 11 01 20 8f 9e 69 aa 1f',
|
||||
3072:'5a e4 f1 28 96 b8 37 9a 2a ad 89 b5 b5 53 d6 b0',
|
||||
4080:'6b 6b 09 8d 0c 29 3b c2 99 3d 80 bf 05 18 b6 d9',
|
||||
4096:'81 70 cc 3c cd 92 a6 98 62 1b 93 9d d3 8f e7 b9'
|
||||
}
|
||||
),
|
||||
(
|
||||
'8b37641910833222772a',
|
||||
{
|
||||
0: 'ab 65 c2 6e dd b2 87 60 0d b2 fd a1 0d 1e 60 5c',
|
||||
16: 'bb 75 90 10 c2 96 58 f2 c7 2d 93 a2 d1 6d 29 30',
|
||||
240: 'b9 01 e8 03 6e d1 c3 83 cd 3c 4c 4d d0 a6 ab 05',
|
||||
256: '3d 25 ce 49 22 92 4c 55 f0 64 94 33 53 d7 8a 6c',
|
||||
496: '12 c1 aa 44 bb f8 7e 75 e6 11 f6 9b 2c 38 f4 9b',
|
||||
512: '28 f2 b3 43 4b 65 c0 98 77 47 00 44 c6 ea 17 0d',
|
||||
752: 'bd 9e f8 22 de 52 88 19 61 34 cf 8a f7 83 93 04',
|
||||
768: '67 55 9c 23 f0 52 15 84 70 a2 96 f7 25 73 5a 32',
|
||||
1008:'8b ab 26 fb c2 c1 2b 0f 13 e2 ab 18 5e ab f2 41',
|
||||
1024:'31 18 5a 6d 69 6f 0c fa 9b 42 80 8b 38 e1 32 a2',
|
||||
1520:'56 4d 3d ae 18 3c 52 34 c8 af 1e 51 06 1c 44 b5',
|
||||
1536:'3c 07 78 a7 b5 f7 2d 3c 23 a3 13 5c 7d 67 b9 f4',
|
||||
2032:'f3 43 69 89 0f cf 16 fb 51 7d ca ae 44 63 b2 dd',
|
||||
2048:'02 f3 1c 81 e8 20 07 31 b8 99 b0 28 e7 91 bf a7',
|
||||
3056:'72 da 64 62 83 22 8c 14 30 08 53 70 17 95 61 6f',
|
||||
3072:'4e 0a 8c 6f 79 34 a7 88 e2 26 5e 81 d6 d0 c8 f4',
|
||||
4080:'43 8d d5 ea fe a0 11 1b 6f 36 b4 b9 38 da 2a 68',
|
||||
4096:'5f 6b fc 73 81 58 74 d9 71 00 f0 86 97 93 57 d8'
|
||||
}
|
||||
),
|
||||
# Page 9
|
||||
(
|
||||
'ebb46227c6cc8b37641910833222772a',
|
||||
{
|
||||
0: '72 0c 94 b6 3e df 44 e1 31 d9 50 ca 21 1a 5a 30',
|
||||
16: 'c3 66 fd ea cf 9c a8 04 36 be 7c 35 84 24 d2 0b',
|
||||
240: 'b3 39 4a 40 aa bf 75 cb a4 22 82 ef 25 a0 05 9f',
|
||||
256: '48 47 d8 1d a4 94 2d bc 24 9d ef c4 8c 92 2b 9f',
|
||||
496: '08 12 8c 46 9f 27 53 42 ad da 20 2b 2b 58 da 95',
|
||||
512: '97 0d ac ef 40 ad 98 72 3b ac 5d 69 55 b8 17 61',
|
||||
752: '3c b8 99 93 b0 7b 0c ed 93 de 13 d2 a1 10 13 ac',
|
||||
768: 'ef 2d 67 6f 15 45 c2 c1 3d c6 80 a0 2f 4a db fe',
|
||||
1008:'b6 05 95 51 4f 24 bc 9f e5 22 a6 ca d7 39 36 44',
|
||||
1024:'b5 15 a8 c5 01 17 54 f5 90 03 05 8b db 81 51 4e',
|
||||
1520:'3c 70 04 7e 8c bc 03 8e 3b 98 20 db 60 1d a4 95',
|
||||
1536:'11 75 da 6e e7 56 de 46 a5 3e 2b 07 56 60 b7 70',
|
||||
2032:'00 a5 42 bb a0 21 11 cc 2c 65 b3 8e bd ba 58 7e',
|
||||
2048:'58 65 fd bb 5b 48 06 41 04 e8 30 b3 80 f2 ae de',
|
||||
3056:'34 b2 1a d2 ad 44 e9 99 db 2d 7f 08 63 f0 d9 b6',
|
||||
3072:'84 a9 21 8f c3 6e 8a 5f 2c cf be ae 53 a2 7d 25',
|
||||
4080:'a2 22 1a 11 b8 33 cc b4 98 a5 95 40 f0 54 5f 4a',
|
||||
4096:'5b be b4 78 7d 59 e5 37 3f db ea 6c 6f 75 c2 9b'
|
||||
}
|
||||
),
|
||||
(
|
||||
'c109163908ebe51debb46227c6cc8b37641910833222772a',
|
||||
{
|
||||
0: '54 b6 4e 6b 5a 20 b5 e2 ec 84 59 3d c7 98 9d a7',
|
||||
16: 'c1 35 ee e2 37 a8 54 65 ff 97 dc 03 92 4f 45 ce',
|
||||
240: 'cf cc 92 2f b4 a1 4a b4 5d 61 75 aa bb f2 d2 01',
|
||||
256: '83 7b 87 e2 a4 46 ad 0e f7 98 ac d0 2b 94 12 4f',
|
||||
496: '17 a6 db d6 64 92 6a 06 36 b3 f4 c3 7a 4f 46 94',
|
||||
512: '4a 5f 9f 26 ae ee d4 d4 a2 5f 63 2d 30 52 33 d9',
|
||||
752: '80 a3 d0 1e f0 0c 8e 9a 42 09 c1 7f 4e eb 35 8c',
|
||||
768: 'd1 5e 7d 5f fa aa bc 02 07 bf 20 0a 11 77 93 a2',
|
||||
1008:'34 96 82 bf 58 8e aa 52 d0 aa 15 60 34 6a ea fa',
|
||||
1024:'f5 85 4c db 76 c8 89 e3 ad 63 35 4e 5f 72 75 e3',
|
||||
1520:'53 2c 7c ec cb 39 df 32 36 31 84 05 a4 b1 27 9c',
|
||||
1536:'ba ef e6 d9 ce b6 51 84 22 60 e0 d1 e0 5e 3b 90',
|
||||
2032:'e8 2d 8c 6d b5 4e 3c 63 3f 58 1c 95 2b a0 42 07',
|
||||
2048:'4b 16 e5 0a bd 38 1b d7 09 00 a9 cd 9a 62 cb 23',
|
||||
3056:'36 82 ee 33 bd 14 8b d9 f5 86 56 cd 8f 30 d9 fb',
|
||||
3072:'1e 5a 0b 84 75 04 5d 9b 20 b2 62 86 24 ed fd 9e',
|
||||
4080:'63 ed d6 84 fb 82 62 82 fe 52 8f 9c 0e 92 37 bc',
|
||||
4096:'e4 dd 2e 98 d6 96 0f ae 0b 43 54 54 56 74 33 91'
|
||||
}
|
||||
),
|
||||
# Page 10
|
||||
(
|
||||
'1ada31d5cf688221c109163908ebe51debb46227c6cc8b37641910833222772a',
|
||||
{
|
||||
0: 'dd 5b cb 00 18 e9 22 d4 94 75 9d 7c 39 5d 02 d3',
|
||||
16: 'c8 44 6f 8f 77 ab f7 37 68 53 53 eb 89 a1 c9 eb',
|
||||
240: 'af 3e 30 f9 c0 95 04 59 38 15 15 75 c3 fb 90 98',
|
||||
256: 'f8 cb 62 74 db 99 b8 0b 1d 20 12 a9 8e d4 8f 0e',
|
||||
496: '25 c3 00 5a 1c b8 5d e0 76 25 98 39 ab 71 98 ab',
|
||||
512: '9d cb c1 83 e8 cb 99 4b 72 7b 75 be 31 80 76 9c',
|
||||
752: 'a1 d3 07 8d fa 91 69 50 3e d9 d4 49 1d ee 4e b2',
|
||||
768: '85 14 a5 49 58 58 09 6f 59 6e 4b cd 66 b1 06 65',
|
||||
1008:'5f 40 d5 9e c1 b0 3b 33 73 8e fa 60 b2 25 5d 31',
|
||||
1024:'34 77 c7 f7 64 a4 1b ac ef f9 0b f1 4f 92 b7 cc',
|
||||
1520:'ac 4e 95 36 8d 99 b9 eb 78 b8 da 8f 81 ff a7 95',
|
||||
1536:'8c 3c 13 f8 c2 38 8b b7 3f 38 57 6e 65 b7 c4 46',
|
||||
2032:'13 c4 b9 c1 df b6 65 79 ed dd 8a 28 0b 9f 73 16',
|
||||
2048:'dd d2 78 20 55 01 26 69 8e fa ad c6 4b 64 f6 6e',
|
||||
3056:'f0 8f 2e 66 d2 8e d1 43 f3 a2 37 cf 9d e7 35 59',
|
||||
3072:'9e a3 6c 52 55 31 b8 80 ba 12 43 34 f5 7b 0b 70',
|
||||
4080:'d5 a3 9e 3d fc c5 02 80 ba c4 a6 b5 aa 0d ca 7d',
|
||||
4096:'37 0b 1c 1f e6 55 91 6d 97 fd 0d 47 ca 1d 72 b8'
|
||||
}
|
||||
)
|
||||
]
|
||||
|
||||
def test_keystream(self):
|
||||
for tv in self.rfc6229_data:
|
||||
key = unhexlify(b((tv[0])))
|
||||
cipher = ARC4.new(key)
|
||||
count = 0
|
||||
for offset in range(0,4096+1,16):
|
||||
ct = cipher.encrypt(b('\x00')*16)
|
||||
expected = tv[1].get(offset)
|
||||
if expected:
|
||||
expected = unhexlify(b(expected.replace(" ",'')))
|
||||
self.assertEquals(ct, expected)
|
||||
count += 1
|
||||
self.assertEqual(count, len(tv[1]))
|
||||
|
||||
class Drop_Tests(unittest.TestCase):
|
||||
key = b('\xAA')*16
|
||||
data = b('\x00')*5000
|
||||
|
||||
def setUp(self):
|
||||
self.cipher = ARC4.new(self.key)
|
||||
|
||||
def test_drop256_encrypt(self):
|
||||
cipher_drop = ARC4.new(self.key, 256)
|
||||
ct_drop = cipher_drop.encrypt(self.data[:16])
|
||||
ct = self.cipher.encrypt(self.data)[256:256+16]
|
||||
self.assertEquals(ct_drop, ct)
|
||||
|
||||
def test_drop256_decrypt(self):
|
||||
cipher_drop = ARC4.new(self.key, 256)
|
||||
pt_drop = cipher_drop.decrypt(self.data[:16])
|
||||
pt = self.cipher.decrypt(self.data)[256:256+16]
|
||||
self.assertEquals(pt_drop, pt)
|
||||
|
||||
def get_tests(config={}):
|
||||
from Crypto.Cipher import ARC4
|
||||
from common import make_stream_tests
|
||||
tests = make_stream_tests(ARC4, "ARC4", test_data)
|
||||
tests += list_test_cases(RFC6229_Tests)
|
||||
tests += list_test_cases(Drop_Tests)
|
||||
return tests
|
||||
return make_stream_tests(ARC4, "ARC4", test_data)
|
||||
|
||||
if __name__ == '__main__':
|
||||
import unittest
|
||||
|
||||
@@ -31,7 +31,7 @@ from Crypto.SelfTest.st_common import list_test_cases, a2b_hex, b2a_hex
|
||||
from Crypto.Util.py3compat import *
|
||||
from Crypto.PublicKey import RSA
|
||||
from Crypto.Cipher import PKCS1_OAEP as PKCS
|
||||
from Crypto.Hash import MD2,MD5,SHA1,SHA256,RIPEMD160
|
||||
from Crypto.Hash import MD2,MD5,SHA as SHA1,SHA256,RIPEMD
|
||||
from Crypto import Random
|
||||
|
||||
def rws(t):
|
||||
@@ -314,12 +314,11 @@ class PKCS1_OAEP_Tests(unittest.TestCase):
|
||||
# Encrypt/Decrypt messages of length [0..128-2*20-2]
|
||||
for pt_len in xrange(0,128-2*20-2):
|
||||
pt = self.rng(pt_len)
|
||||
cipher = PKCS.new(self.key1024)
|
||||
ct = cipher.encrypt(pt)
|
||||
pt2 = cipher.decrypt(ct)
|
||||
ct = PKCS.encrypt(pt, self.key1024)
|
||||
pt2 = PKCS.decrypt(ct, self.key1024)
|
||||
self.assertEqual(pt,pt2)
|
||||
|
||||
def testEncryptDecrypt2(self):
|
||||
def testEncryptDecrypt1(self):
|
||||
# Helper function to monitor what's requested from RNG
|
||||
global asked
|
||||
def localRng(N):
|
||||
@@ -327,7 +326,7 @@ class PKCS1_OAEP_Tests(unittest.TestCase):
|
||||
asked += N
|
||||
return self.rng(N)
|
||||
# Verify that OAEP is friendly to all hashes
|
||||
for hashmod in (MD2,MD5,SHA1,SHA256,RIPEMD160):
|
||||
for hashmod in (MD2,MD5,SHA1,SHA256,RIPEMD):
|
||||
# Verify that encrypt() asks for as many random bytes
|
||||
# as the hash output size
|
||||
asked = 0
|
||||
@@ -338,7 +337,7 @@ class PKCS1_OAEP_Tests(unittest.TestCase):
|
||||
self.assertEqual(cipher.decrypt(ct), pt)
|
||||
self.failUnless(asked > hashmod.digest_size)
|
||||
|
||||
def testEncryptDecrypt3(self):
|
||||
def testEncryptDecrypt2(self):
|
||||
# Verify that OAEP supports labels
|
||||
pt = self.rng(35)
|
||||
xlabel = self.rng(22)
|
||||
@@ -346,7 +345,7 @@ class PKCS1_OAEP_Tests(unittest.TestCase):
|
||||
ct = cipher.encrypt(pt)
|
||||
self.assertEqual(cipher.decrypt(ct), pt)
|
||||
|
||||
def testEncryptDecrypt4(self):
|
||||
def testEncryptDecrypt3(self):
|
||||
# Verify that encrypt() uses the custom MGF
|
||||
global mgfcalls
|
||||
# Helper function to monitor what's requested from MGF
|
||||
|
||||
@@ -28,14 +28,13 @@ __revision__ = "$Id$"
|
||||
|
||||
def get_tests(config={}):
|
||||
tests = []
|
||||
from Crypto.SelfTest.Hash import test_HMAC; tests += test_HMAC.get_tests(config=config)
|
||||
from Crypto.SelfTest.Hash import test_CMAC; tests += test_CMAC.get_tests(config=config)
|
||||
from Crypto.SelfTest.Hash import test_MD2; tests += test_MD2.get_tests(config=config)
|
||||
from Crypto.SelfTest.Hash import test_MD4; tests += test_MD4.get_tests(config=config)
|
||||
from Crypto.SelfTest.Hash import test_MD5; tests += test_MD5.get_tests(config=config)
|
||||
from Crypto.SelfTest.Hash import test_RIPEMD160; tests += test_RIPEMD160.get_tests(config=config)
|
||||
from Crypto.SelfTest.Hash import test_SHA1; tests += test_SHA1.get_tests(config=config)
|
||||
from Crypto.SelfTest.Hash import test_SHA256; tests += test_SHA256.get_tests(config=config)
|
||||
from Crypto.SelfTest.Hash import test_HMAC; tests += test_HMAC.get_tests(config=config)
|
||||
from Crypto.SelfTest.Hash import test_MD2; tests += test_MD2.get_tests(config=config)
|
||||
from Crypto.SelfTest.Hash import test_MD4; tests += test_MD4.get_tests(config=config)
|
||||
from Crypto.SelfTest.Hash import test_MD5; tests += test_MD5.get_tests(config=config)
|
||||
from Crypto.SelfTest.Hash import test_RIPEMD; tests += test_RIPEMD.get_tests(config=config)
|
||||
from Crypto.SelfTest.Hash import test_SHA; tests += test_SHA.get_tests(config=config)
|
||||
from Crypto.SelfTest.Hash import test_SHA256; tests += test_SHA256.get_tests(config=config)
|
||||
try:
|
||||
from Crypto.SelfTest.Hash import test_SHA224; tests += test_SHA224.get_tests(config=config)
|
||||
from Crypto.SelfTest.Hash import test_SHA384; tests += test_SHA384.get_tests(config=config)
|
||||
|
||||
@@ -29,10 +29,7 @@ __revision__ = "$Id$"
|
||||
import sys
|
||||
import unittest
|
||||
import binascii
|
||||
import Crypto.Hash
|
||||
from Crypto.Util.py3compat import *
|
||||
if sys.version_info[0] == 2 and sys.version_info[1] == 1:
|
||||
from Crypto.Util.py21compat import *
|
||||
|
||||
# For compatibility with Python 2.1 and Python 2.2
|
||||
if sys.hexversion < 0x02030000:
|
||||
@@ -43,7 +40,6 @@ if sys.hexversion < 0x02030000:
|
||||
else:
|
||||
dict = dict
|
||||
|
||||
from Crypto.Util.strxor import strxor_c
|
||||
|
||||
class HashDigestSizeSelfTest(unittest.TestCase):
|
||||
|
||||
@@ -98,27 +94,11 @@ class HashSelfTest(unittest.TestCase):
|
||||
self.assertEqual(self.expected.decode(), out3) # h = .new(data); h.hexdigest()
|
||||
self.assertEqual(self.expected, out4) # h = .new(data); h.digest()
|
||||
|
||||
# Verify that the .new() method produces a fresh hash object, except
|
||||
# for MD5 and SHA1, which are hashlib objects. (But test any .new()
|
||||
# method that does exist.)
|
||||
if self.hashmod.__name__ not in ('Crypto.Hash.MD5', 'Crypto.Hash.SHA1') or hasattr(h, 'new'):
|
||||
h2 = h.new()
|
||||
h2.update(self.input)
|
||||
out5 = binascii.b2a_hex(h2.digest())
|
||||
self.assertEqual(self.expected, out5)
|
||||
|
||||
# Verify that Crypto.Hash.new(h) produces a fresh hash object
|
||||
h3 = Crypto.Hash.new(h)
|
||||
h3.update(self.input)
|
||||
out6 = binascii.b2a_hex(h3.digest())
|
||||
self.assertEqual(self.expected, out6)
|
||||
|
||||
if hasattr(h, 'name'):
|
||||
# Verify that Crypto.Hash.new(h.name) produces a fresh hash object
|
||||
h4 = Crypto.Hash.new(h.name)
|
||||
h4.update(self.input)
|
||||
out7 = binascii.b2a_hex(h4.digest())
|
||||
self.assertEqual(self.expected, out7)
|
||||
# Verify that new() object method produces a fresh hash object
|
||||
h2 = h.new()
|
||||
h2.update(self.input)
|
||||
out5 = binascii.b2a_hex(h2.digest())
|
||||
self.assertEqual(self.expected, out5)
|
||||
|
||||
class HashTestOID(unittest.TestCase):
|
||||
def __init__(self, hashmod, oid):
|
||||
@@ -127,105 +107,65 @@ class HashTestOID(unittest.TestCase):
|
||||
self.oid = oid
|
||||
|
||||
def runTest(self):
|
||||
from Crypto.Signature import PKCS1_v1_5
|
||||
h = self.hashmod.new()
|
||||
self.assertEqual(PKCS1_v1_5._HASH_OIDS[h.name], self.oid)
|
||||
|
||||
class HashDocStringTest(unittest.TestCase):
|
||||
def __init__(self, hashmod):
|
||||
unittest.TestCase.__init__(self)
|
||||
self.hashmod = hashmod
|
||||
|
||||
def runTest(self):
|
||||
docstring = self.hashmod.__doc__
|
||||
self.assert_(hasattr(self.hashmod, '__doc__'))
|
||||
self.assert_(isinstance(self.hashmod.__doc__, str))
|
||||
|
||||
class GenericHashConstructorTest(unittest.TestCase):
|
||||
def __init__(self, hashmod):
|
||||
unittest.TestCase.__init__(self)
|
||||
self.hashmod = hashmod
|
||||
|
||||
def runTest(self):
|
||||
obj1 = self.hashmod.new("foo")
|
||||
obj2 = self.hashmod.new()
|
||||
obj3 = Crypto.Hash.new(obj1.name, "foo")
|
||||
obj4 = Crypto.Hash.new(obj1.name)
|
||||
obj5 = Crypto.Hash.new(obj1, "foo")
|
||||
obj6 = Crypto.Hash.new(obj1)
|
||||
self.assert_(isinstance(self.hashmod, obj1))
|
||||
self.assert_(isinstance(self.hashmod, obj2))
|
||||
self.assert_(isinstance(self.hashmod, obj3))
|
||||
self.assert_(isinstance(self.hashmod, obj4))
|
||||
self.assert_(isinstance(self.hashmod, obj5))
|
||||
self.assert_(isinstance(self.hashmod, obj6))
|
||||
if self.oid==None:
|
||||
try:
|
||||
raised = 0
|
||||
a = h.oid
|
||||
except AttributeError:
|
||||
raised = 1
|
||||
self.assertEqual(raised,1)
|
||||
else:
|
||||
self.assertEqual(h.oid, self.oid)
|
||||
|
||||
class MACSelfTest(unittest.TestCase):
|
||||
|
||||
def __init__(self, module, description, result, input, key, params):
|
||||
def __init__(self, hashmod, description, expected_dict, input, key, hashmods):
|
||||
unittest.TestCase.__init__(self)
|
||||
self.module = module
|
||||
self.result = result
|
||||
self.hashmod = hashmod
|
||||
self.expected_dict = expected_dict
|
||||
self.input = input
|
||||
self.key = key
|
||||
self.params = params
|
||||
self.hashmods = hashmods
|
||||
self.description = description
|
||||
|
||||
def shortDescription(self):
|
||||
return self.description
|
||||
|
||||
def runTest(self):
|
||||
key = binascii.a2b_hex(b(self.key))
|
||||
data = binascii.a2b_hex(b(self.input))
|
||||
for hashname in self.expected_dict.keys():
|
||||
hashmod = self.hashmods[hashname]
|
||||
key = binascii.a2b_hex(b(self.key))
|
||||
data = binascii.a2b_hex(b(self.input))
|
||||
|
||||
# Strip whitespace from the expected string (which should be in lowercase-hex)
|
||||
expected = b("".join(self.result.split()))
|
||||
# Strip whitespace from the expected string (which should be in lowercase-hex)
|
||||
expected = b("".join(self.expected_dict[hashname].split()))
|
||||
|
||||
h = self.module.new(key, **self.params)
|
||||
h.update(data)
|
||||
out1_bin = h.digest()
|
||||
out1 = binascii.b2a_hex(h.digest())
|
||||
out2 = h.hexdigest()
|
||||
h = self.hashmod.new(key, digestmod=hashmod)
|
||||
h.update(data)
|
||||
out1 = binascii.b2a_hex(h.digest())
|
||||
out2 = h.hexdigest()
|
||||
|
||||
# Verify that correct MAC does not raise any exception
|
||||
h.hexverify(out1)
|
||||
h.verify(out1_bin)
|
||||
h = self.hashmod.new(key, data, hashmod)
|
||||
|
||||
# Verify that incorrect MAC does raise ValueError exception
|
||||
wrong_mac = strxor_c(out1_bin, 255)
|
||||
self.assertRaises(ValueError, h.verify, wrong_mac)
|
||||
self.assertRaises(ValueError, h.hexverify, "4556")
|
||||
out3 = h.hexdigest()
|
||||
out4 = binascii.b2a_hex(h.digest())
|
||||
|
||||
h = self.module.new(key, data, **self.params)
|
||||
# Test .copy()
|
||||
h2 = h.copy()
|
||||
h.update(b("blah blah blah")) # Corrupt the original hash object
|
||||
out5 = binascii.b2a_hex(h2.digest()) # The copied hash object should return the correct result
|
||||
|
||||
out3 = h.hexdigest()
|
||||
out4 = binascii.b2a_hex(h.digest())
|
||||
|
||||
# Test .copy()
|
||||
h2 = h.copy()
|
||||
h.update(b("blah blah blah")) # Corrupt the original hash object
|
||||
out5 = binascii.b2a_hex(h2.digest()) # The copied hash object should return the correct result
|
||||
|
||||
# PY3K: Check that hexdigest() returns str and digest() returns bytes
|
||||
if sys.version_info[0] > 2:
|
||||
self.assertTrue(isinstance(h.digest(), type(b(""))))
|
||||
self.assertTrue(isinstance(h.hexdigest(), type("")))
|
||||
|
||||
# PY3K: Check that .hexverify() accepts bytes or str
|
||||
if sys.version_info[0] > 2:
|
||||
h.hexverify(h.hexdigest())
|
||||
h.hexverify(h.hexdigest().encode('ascii'))
|
||||
|
||||
# PY3K: hexdigest() should return str, and digest() should return bytes
|
||||
self.assertEqual(expected, out1)
|
||||
if sys.version_info[0] == 2:
|
||||
self.assertEqual(expected, out2)
|
||||
self.assertEqual(expected, out3)
|
||||
else:
|
||||
self.assertEqual(expected.decode(), out2)
|
||||
self.assertEqual(expected.decode(), out3)
|
||||
self.assertEqual(expected, out4)
|
||||
self.assertEqual(expected, out5)
|
||||
# PY3K: hexdigest() should return str(), and digest() bytes
|
||||
self.assertEqual(expected, out1)
|
||||
if sys.version_info[0] == 2:
|
||||
self.assertEqual(expected, out2)
|
||||
self.assertEqual(expected, out3)
|
||||
else:
|
||||
self.assertEqual(expected.decode(), out2)
|
||||
self.assertEqual(expected.decode(), out3)
|
||||
self.assertEqual(expected, out4)
|
||||
self.assertEqual(expected, out5)
|
||||
|
||||
def make_hash_tests(module, module_name, test_data, digest_size, oid=None):
|
||||
tests = []
|
||||
@@ -238,22 +178,20 @@ def make_hash_tests(module, module_name, test_data, digest_size, oid=None):
|
||||
description = row[2].encode('latin-1')
|
||||
name = "%s #%d: %s" % (module_name, i+1, description)
|
||||
tests.append(HashSelfTest(module, name, expected, input))
|
||||
if oid is not None:
|
||||
oid = b(oid)
|
||||
name = "%s #%d: digest_size" % (module_name, i+1)
|
||||
tests.append(HashDigestSizeSelfTest(module, name, digest_size))
|
||||
if oid is not None:
|
||||
tests.append(HashTestOID(module, oid))
|
||||
tests.append(HashDocStringTest(module))
|
||||
if getattr(module, 'name', None) is not None:
|
||||
tests.append(GenericHashConstructorTest(module))
|
||||
tests.append(HashTestOID(module, oid))
|
||||
return tests
|
||||
|
||||
def make_mac_tests(module, module_name, test_data):
|
||||
def make_mac_tests(module, module_name, test_data, hashmods):
|
||||
tests = []
|
||||
for i in range(len(test_data)):
|
||||
row = test_data[i]
|
||||
(key, data, results, description, params) = row
|
||||
(key, data, results, description) = row
|
||||
name = "%s #%d: %s" % (module_name, i+1, description)
|
||||
tests.append(MACSelfTest(module, name, results, data, key, params))
|
||||
tests.append(MACSelfTest(module, name, results, data, key, hashmods))
|
||||
return tests
|
||||
|
||||
# vim:set ts=4 sw=4 sts=4 expandtab:
|
||||
|
||||
@@ -29,17 +29,13 @@ __revision__ = "$Id$"
|
||||
from common import dict # For compatibility with Python 2.1 and 2.2
|
||||
from Crypto.Util.py3compat import *
|
||||
|
||||
from Crypto.Hash import MD5, SHA1, SHA224, SHA256, SHA384, SHA512, HMAC
|
||||
|
||||
default_hash = None
|
||||
|
||||
# This is a list of (key, data, results, description) tuples.
|
||||
test_data = [
|
||||
## Test vectors from RFC 2202 ##
|
||||
# Test that the default hashmod is MD5
|
||||
('0b' * 16,
|
||||
'4869205468657265',
|
||||
dict(default_hash='9294727a3638bb1c13f48ef8158bfc9d'),
|
||||
dict(default='9294727a3638bb1c13f48ef8158bfc9d'),
|
||||
'default-is-MD5'),
|
||||
|
||||
# Test case 1 (MD5)
|
||||
@@ -179,7 +175,9 @@ test_data = [
|
||||
bfdc63644f0713938a7f51535c3a35e2
|
||||
'''),
|
||||
'RFC 4231 #7 (HMAC-SHA256)'),
|
||||
]
|
||||
|
||||
hashlib_test_data = [
|
||||
# Test case 8 (SHA224)
|
||||
('4a656665',
|
||||
'7768617420646f2079612077616e74'
|
||||
@@ -205,25 +203,17 @@ test_data = [
|
||||
|
||||
def get_tests(config={}):
|
||||
global test_data
|
||||
from Crypto.Hash import HMAC, MD5, SHA as SHA1, SHA256
|
||||
from common import make_mac_tests
|
||||
|
||||
# A test vector contains multiple results, each one for a
|
||||
# different hash algorithm.
|
||||
# Here we expand each test vector into multiple ones,
|
||||
# and add the relevant parameters that will be passed to new()
|
||||
exp_test_data = []
|
||||
for row in test_data:
|
||||
for modname in row[2].keys():
|
||||
t = list(row)
|
||||
t[2] = row[2][modname]
|
||||
try:
|
||||
t.append(dict(digestmod=globals()[modname]))
|
||||
exp_test_data.append(t)
|
||||
except AttributeError:
|
||||
import sys
|
||||
sys.stderr.write("SelfTest: warning: not testing HMAC-%s (not available)\n" % modname)
|
||||
|
||||
return make_mac_tests(HMAC, "HMAC", exp_test_data)
|
||||
hashmods = dict(MD5=MD5, SHA1=SHA1, SHA256=SHA256, default=None)
|
||||
try:
|
||||
from Crypto.Hash import SHA224, SHA384, SHA512
|
||||
hashmods.update(dict(SHA224=SHA224, SHA384=SHA384, SHA512=SHA512))
|
||||
test_data += hashlib_test_data
|
||||
except ImportError:
|
||||
import sys
|
||||
sys.stderr.write("SelfTest: warning: not testing HMAC-SHA224/384/512 (not available)\n")
|
||||
return make_mac_tests(HMAC, "HMAC", test_data, hashmods)
|
||||
|
||||
if __name__ == '__main__':
|
||||
import unittest
|
||||
|
||||
@@ -54,7 +54,7 @@ def get_tests(config={}):
|
||||
from common import make_hash_tests
|
||||
return make_hash_tests(MD2, "MD2", test_data,
|
||||
digest_size=16,
|
||||
oid="1.2.840.113549.2.2")
|
||||
oid="\x06\x08\x2a\x86\x48\x86\xf7\x0d\x02\x02")
|
||||
|
||||
if __name__ == '__main__':
|
||||
import unittest
|
||||
|
||||
@@ -54,7 +54,7 @@ def get_tests(config={}):
|
||||
from common import make_hash_tests
|
||||
return make_hash_tests(MD4, "MD4", test_data,
|
||||
digest_size=16,
|
||||
oid="1.2.840.113549.2.4")
|
||||
oid="\x06\x08\x2a\x86\x48\x86\xf7\x0d\x02\x04")
|
||||
|
||||
if __name__ == '__main__':
|
||||
import unittest
|
||||
|
||||
@@ -54,7 +54,7 @@ def get_tests(config={}):
|
||||
from common import make_hash_tests
|
||||
return make_hash_tests(MD5, "MD5", test_data,
|
||||
digest_size=16,
|
||||
oid="1.2.840.113549.2.5")
|
||||
oid="\x06\x08\x2a\x86\x48\x86\xf7\x0d\x02\x05")
|
||||
|
||||
if __name__ == '__main__':
|
||||
import unittest
|
||||
|
||||
@@ -0,0 +1,73 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# SelfTest/Hash/test_RIPEMD.py: Self-test for the RIPEMD-160 hash function
|
||||
#
|
||||
# Written in 2008 by Dwayne C. Litzenberger <dlitz@dlitz.net>
|
||||
#
|
||||
# ===================================================================
|
||||
# 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.
|
||||
# ===================================================================
|
||||
|
||||
#"""Self-test suite for Crypto.Hash.RIPEMD"""
|
||||
|
||||
__revision__ = "$Id$"
|
||||
|
||||
from Crypto.Util.py3compat import *
|
||||
|
||||
# This is a list of (expected_result, input[, description]) tuples.
|
||||
test_data = [
|
||||
# Test vectors downloaded 2008-09-12 from
|
||||
# http://homes.esat.kuleuven.be/~bosselae/ripemd160.html
|
||||
('9c1185a5c5e9fc54612808977ee8f548b2258d31', '', "'' (empty string)"),
|
||||
('0bdc9d2d256b3ee9daae347be6f4dc835a467ffe', 'a'),
|
||||
('8eb208f7e05d987a9b044a8e98c6b087f15a0bfc', 'abc'),
|
||||
('5d0689ef49d2fae572b881b123a85ffa21595f36', 'message digest'),
|
||||
|
||||
('f71c27109c692c1b56bbdceb5b9d2865b3708dbc',
|
||||
'abcdefghijklmnopqrstuvwxyz',
|
||||
'a-z'),
|
||||
|
||||
('12a053384a9c0c88e405a06c27dcf49ada62eb2b',
|
||||
'abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq',
|
||||
'abcdbcd...pnopq'),
|
||||
|
||||
('b0e20b6e3116640286ed3a87a5713079b21f5189',
|
||||
'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789',
|
||||
'A-Z, a-z, 0-9'),
|
||||
|
||||
('9b752e45573d4b39f4dbd3323cab82bf63326bfb',
|
||||
'1234567890' * 8,
|
||||
"'1234567890' * 8"),
|
||||
|
||||
('52783243c1697bdbe16d37f97f68f08325dc1528',
|
||||
'a' * 10**6,
|
||||
'"a" * 10**6'),
|
||||
]
|
||||
|
||||
def get_tests(config={}):
|
||||
from Crypto.Hash import RIPEMD
|
||||
from common import make_hash_tests
|
||||
return make_hash_tests(RIPEMD, "RIPEMD", test_data,
|
||||
digest_size=20,
|
||||
oid="\x06\x05\x2b\x24\x03\02\x01")
|
||||
|
||||
if __name__ == '__main__':
|
||||
import unittest
|
||||
suite = lambda: unittest.TestSuite(get_tests())
|
||||
unittest.main(defaultTest='suite')
|
||||
|
||||
# vim:set ts=4 sw=4 sts=4 expandtab:
|
||||
@@ -0,0 +1,64 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# SelfTest/Hash/SHA.py: Self-test for the SHA-1 hash function
|
||||
#
|
||||
# Written in 2008 by Dwayne C. Litzenberger <dlitz@dlitz.net>
|
||||
#
|
||||
# ===================================================================
|
||||
# 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.
|
||||
# ===================================================================
|
||||
|
||||
"""Self-test suite for Crypto.Hash.SHA"""
|
||||
|
||||
__revision__ = "$Id$"
|
||||
|
||||
from Crypto.Util.py3compat import *
|
||||
|
||||
# Test vectors from various sources
|
||||
# This is a list of (expected_result, input[, description]) tuples.
|
||||
test_data = [
|
||||
# FIPS PUB 180-2, A.1 - "One-Block Message"
|
||||
('a9993e364706816aba3e25717850c26c9cd0d89d', 'abc'),
|
||||
|
||||
# FIPS PUB 180-2, A.2 - "Multi-Block Message"
|
||||
('84983e441c3bd26ebaae4aa1f95129e5e54670f1',
|
||||
'abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq'),
|
||||
|
||||
# FIPS PUB 180-2, A.3 - "Long Message"
|
||||
# ('34aa973cd4c4daa4f61eeb2bdbad27316534016f',
|
||||
# 'a' * 10**6,
|
||||
# '"a" * 10**6'),
|
||||
|
||||
# RFC 3174: Section 7.3, "TEST4" (multiple of 512 bits)
|
||||
('dea356a2cddd90c7a7ecedc5ebb563934f460452',
|
||||
'01234567' * 80,
|
||||
'"01234567" * 80'),
|
||||
]
|
||||
|
||||
def get_tests(config={}):
|
||||
from Crypto.Hash import SHA
|
||||
from common import make_hash_tests
|
||||
return make_hash_tests(SHA, "SHA", test_data,
|
||||
digest_size=20,
|
||||
oid="\x06\x05\x2B\x0E\x03\x02\x1A")
|
||||
|
||||
if __name__ == '__main__':
|
||||
import unittest
|
||||
suite = lambda: unittest.TestSuite(get_tests())
|
||||
unittest.main(defaultTest='suite')
|
||||
|
||||
# vim:set ts=4 sw=4 sts=4 expandtab:
|
||||
@@ -55,7 +55,7 @@ def get_tests(config={}):
|
||||
from common import make_hash_tests
|
||||
return make_hash_tests(SHA224, "SHA224", test_data,
|
||||
digest_size=28,
|
||||
oid='2.16.840.1.101.3.4.2.4')
|
||||
oid='\x06\x09\x60\x86\x48\x01\x65\x03\x04\x02\x04')
|
||||
|
||||
if __name__ == '__main__':
|
||||
import unittest
|
||||
|
||||
@@ -81,7 +81,7 @@ def get_tests(config={}):
|
||||
from common import make_hash_tests
|
||||
tests = make_hash_tests(SHA256, "SHA256", test_data,
|
||||
digest_size=32,
|
||||
oid="2.16.840.1.101.3.4.2.1")
|
||||
oid="\x06\x09\x60\x86\x48\x01\x65\x03\x04\x02\x01")
|
||||
|
||||
if config.get('slow_tests'):
|
||||
tests += [LargeSHA256Test()]
|
||||
|
||||
@@ -53,7 +53,7 @@ def get_tests(config={}):
|
||||
from common import make_hash_tests
|
||||
return make_hash_tests(SHA384, "SHA384", test_data,
|
||||
digest_size=48,
|
||||
oid='2.16.840.1.101.3.4.2.2')
|
||||
oid='\x06\x09\x60\x86\x48\x01\x65\x03\x04\x02\x02')
|
||||
|
||||
if __name__ == '__main__':
|
||||
import unittest
|
||||
|
||||
@@ -50,7 +50,7 @@ def get_tests(config={}):
|
||||
from common import make_hash_tests
|
||||
return make_hash_tests(SHA512, "SHA512", test_data,
|
||||
digest_size=64,
|
||||
oid="2.16.840.1.101.3.4.2.3")
|
||||
oid="\x06\x09\x60\x86\x48\x01\x65\x03\x04\x02\x03")
|
||||
|
||||
if __name__ == '__main__':
|
||||
import unittest
|
||||
|
||||
@@ -31,7 +31,6 @@ def get_tests(config={}):
|
||||
from Crypto.SelfTest.Protocol import test_chaffing; tests += test_chaffing.get_tests(config=config)
|
||||
from Crypto.SelfTest.Protocol import test_rfc1751; tests += test_rfc1751.get_tests(config=config)
|
||||
from Crypto.SelfTest.Protocol import test_AllOrNothing; tests += test_AllOrNothing.get_tests(config=config)
|
||||
from Crypto.SelfTest.Protocol import test_KDF; tests += test_KDF.get_tests(config=config)
|
||||
return tests
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
||||
@@ -25,13 +25,10 @@ __revision__ = "$Id$"
|
||||
import unittest
|
||||
from binascii import unhexlify
|
||||
|
||||
from Crypto.Util.py3compat import *
|
||||
|
||||
from Crypto.SelfTest.st_common import list_test_cases
|
||||
from Crypto.Hash import SHA1, HMAC
|
||||
from Crypto.Cipher import AES, DES3
|
||||
from Crypto.Hash import SHA as SHA1,HMAC
|
||||
|
||||
from Crypto.Protocol.KDF import PBKDF1, PBKDF2, _S2V
|
||||
from Crypto.Protocol.KDF import *
|
||||
|
||||
def t2b(t): return unhexlify(b(t))
|
||||
|
||||
@@ -48,7 +45,7 @@ class PBKDF1_Tests(unittest.TestCase):
|
||||
# From http://www.di-mgt.com.au/cryptoKDFs.html#examplespbkdf
|
||||
("password","78578E5A5D63CB06",16,1000,"DC19847E05C64D2FAF10EBFB4A3D2A20"),
|
||||
)
|
||||
|
||||
|
||||
def test1(self):
|
||||
v = self._testData[0]
|
||||
res = PBKDF1(v[0], t2b(v[1]), v[2], v[3], SHA1)
|
||||
@@ -74,7 +71,7 @@ class PBKDF2_Tests(unittest.TestCase):
|
||||
25, 4096, "3d2eec4fe41c849b80c8d83662c0e44a8b291a964cf2f07038"),
|
||||
( 'pass\x00word',"7361006c74",16,4096, "56fa6aa75548099dcc37d7f03425e0c3"),
|
||||
)
|
||||
|
||||
|
||||
def test1(self):
|
||||
# Test only for HMAC-SHA1 as PRF
|
||||
|
||||
@@ -88,67 +85,10 @@ class PBKDF2_Tests(unittest.TestCase):
|
||||
self.assertEqual(res, t2b(v[4]))
|
||||
self.assertEqual(res, res2)
|
||||
|
||||
class S2V_Tests(unittest.TestCase):
|
||||
|
||||
# Sequence of test vectors.
|
||||
# Each test vector is made up by:
|
||||
# Item #0: a tuple of strings
|
||||
# Item #1: an AES key
|
||||
# Item #2: the result
|
||||
# Item #3: the cipher module S2V is based on
|
||||
# Everything is hex encoded
|
||||
_testData = [
|
||||
|
||||
# RFC5297, A.1
|
||||
(
|
||||
( '101112131415161718191a1b1c1d1e1f2021222324252627',
|
||||
'112233445566778899aabbccddee' ),
|
||||
'fffefdfcfbfaf9f8f7f6f5f4f3f2f1f0',
|
||||
'85632d07c6e8f37f950acd320a2ecc93',
|
||||
AES
|
||||
),
|
||||
|
||||
# RFC5297, A.2
|
||||
(
|
||||
( '00112233445566778899aabbccddeeffdeaddadadeaddadaffeeddcc'+
|
||||
'bbaa99887766554433221100',
|
||||
'102030405060708090a0',
|
||||
'09f911029d74e35bd84156c5635688c0',
|
||||
'7468697320697320736f6d6520706c61'+
|
||||
'696e7465787420746f20656e63727970'+
|
||||
'74207573696e67205349562d414553'),
|
||||
'7f7e7d7c7b7a79787776757473727170',
|
||||
'7bdb6e3b432667eb06f4d14bff2fbd0f',
|
||||
AES
|
||||
),
|
||||
|
||||
]
|
||||
|
||||
def test1(self):
|
||||
"""Verify correctness of test vector"""
|
||||
for tv in self._testData:
|
||||
s2v = _S2V.new(t2b(tv[1]), tv[3])
|
||||
for s in tv[0]:
|
||||
s2v.update(t2b(s))
|
||||
result = s2v.derive()
|
||||
self.assertEqual(result, t2b(tv[2]))
|
||||
|
||||
def test2(self):
|
||||
"""Verify that no more than 127(AES) and 63(TDES)
|
||||
components are accepted."""
|
||||
key = bchr(0)*16
|
||||
for module in (AES, DES3):
|
||||
s2v = _S2V.new(key, module)
|
||||
max_comps = module.block_size*8-1
|
||||
for i in xrange(max_comps):
|
||||
s2v.update(b("XX"))
|
||||
self.assertRaises(TypeError, s2v.update, b("YY"))
|
||||
|
||||
def get_tests(config={}):
|
||||
tests = []
|
||||
tests += list_test_cases(PBKDF1_Tests)
|
||||
tests += list_test_cases(PBKDF2_Tests)
|
||||
tests += list_test_cases(S2V_Tests)
|
||||
return tests
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
||||
@@ -32,13 +32,7 @@ def get_tests(config={}):
|
||||
tests = []
|
||||
from Crypto.SelfTest.PublicKey import test_DSA; tests += test_DSA.get_tests(config=config)
|
||||
from Crypto.SelfTest.PublicKey import test_RSA; tests += test_RSA.get_tests(config=config)
|
||||
|
||||
from Crypto.SelfTest.PublicKey import test_import_DSA
|
||||
tests +=test_import_DSA.get_tests(config=config)
|
||||
|
||||
from Crypto.SelfTest.PublicKey import test_import_RSA
|
||||
tests += test_import_RSA.get_tests(config=config)
|
||||
|
||||
from Crypto.SelfTest.PublicKey import test_importKey; tests += test_importKey.get_tests(config=config)
|
||||
from Crypto.SelfTest.PublicKey import test_ElGamal; tests += test_ElGamal.get_tests(config=config)
|
||||
return tests
|
||||
|
||||
|
||||
@@ -28,7 +28,7 @@ import unittest
|
||||
from Crypto.SelfTest.st_common import list_test_cases, a2b_hex, b2a_hex
|
||||
from Crypto import Random
|
||||
from Crypto.PublicKey import ElGamal
|
||||
from Crypto.Util.number import bytes_to_long
|
||||
from Crypto.Util.number import *
|
||||
from Crypto.Util.py3compat import *
|
||||
|
||||
class ElGamalTest(unittest.TestCase):
|
||||
@@ -151,7 +151,7 @@ class ElGamalTest(unittest.TestCase):
|
||||
tv2['key'] += [tv2[c]]
|
||||
del tv2[c]
|
||||
return tv2
|
||||
|
||||
|
||||
def _test_random_key(self, bits):
|
||||
elgObj = ElGamal.generate(bits, Random.new().read)
|
||||
self._check_private_key(elgObj)
|
||||
|
||||
@@ -28,7 +28,6 @@ __revision__ = "$Id$"
|
||||
|
||||
import sys
|
||||
import os
|
||||
import pickle
|
||||
if sys.version_info[0] == 2 and sys.version_info[1] == 1:
|
||||
from Crypto.Util.py21compat import *
|
||||
from Crypto.Util.py3compat import *
|
||||
@@ -88,21 +87,6 @@ class RSATest(unittest.TestCase):
|
||||
ce 33 52 52 4d 04 16 a5 a4 41 e7 00 af 46 15 03
|
||||
"""
|
||||
|
||||
# The same key, in pickled format (from pycrypto 2.3)
|
||||
# to ensure backward compatibility
|
||||
pickled_key_2_3 = \
|
||||
"(iCrypto.PublicKey.RSA\n_RSAobj\np0\n(dp2\nS'e'\np3\nL17L\nsS'd'\np4"\
|
||||
"\nL11646763154293086160147889314553506764606353688284149120983587488"\
|
||||
"79382229568306696406525871631480713149376749558222371890533687587223"\
|
||||
"51580531956820574156366843733156436163097164007967904900300775223658"\
|
||||
"03543233292399245064743971969473468304536714979010219881003396235861"\
|
||||
"8370829441895425705728523874962107052993L\nsS'n'\np5\nL1319966490819"\
|
||||
"88309815009412231606409998872008467220356704480658206329986017741425"\
|
||||
"59273959878490114749026269828326520214759381792655199845793621772998"\
|
||||
"40439054838068985140623386496543388290455526885872858516219460533763"\
|
||||
"92312680578795692682905599590422046720587710762927130740460442438533"\
|
||||
"124053848898103790124491L\nsb."
|
||||
|
||||
def setUp(self):
|
||||
global RSA, Random, bytes_to_long
|
||||
from Crypto.PublicKey import RSA
|
||||
@@ -194,31 +178,6 @@ class RSATest(unittest.TestCase):
|
||||
|
||||
self.assertRaises(ValueError, self.rsa.construct, [self.n, self.e, self.n-1])
|
||||
|
||||
def test_serialization(self):
|
||||
"""RSA (default implementation) serialize/unserialize key"""
|
||||
rsaObj_orig = self.rsa.generate(1024)
|
||||
rsaObj = pickle.loads(pickle.dumps(rsaObj_orig))
|
||||
self._check_private_key(rsaObj)
|
||||
self._exercise_primitive(rsaObj)
|
||||
pub = rsaObj.publickey()
|
||||
self._check_public_key(pub)
|
||||
self._exercise_public_primitive(rsaObj)
|
||||
|
||||
plaintext = a2b_hex(self.plaintext)
|
||||
ciphertext1 = rsaObj_orig.encrypt(plaintext, b(""))
|
||||
ciphertext2 = rsaObj.encrypt(plaintext, b(""))
|
||||
self.assertEqual(ciphertext1, ciphertext2)
|
||||
|
||||
if not (3, 0) <= sys.version_info < (3, 1, 2, 'final', 0):
|
||||
# Unpickling is broken in Python 3 before 3.1.2 due to http://bugs.python.org/issue6137
|
||||
def test_serialization_compat(self):
|
||||
"""RSA (default implementation) backward compatibility serialization"""
|
||||
rsaObj = pickle.loads(b(self.pickled_key_2_3))
|
||||
plaintext = a2b_hex(self.plaintext)
|
||||
ciphertext = a2b_hex(self.ciphertext)
|
||||
ciphertext_result = rsaObj.encrypt(plaintext, b(""))[0]
|
||||
self.assertEqual(ciphertext_result, ciphertext)
|
||||
|
||||
def _check_private_key(self, rsaObj):
|
||||
# Check capabilities
|
||||
self.assertEqual(1, rsaObj.has_private())
|
||||
@@ -393,20 +352,6 @@ class RSAFastMathTest(RSATest):
|
||||
def test_factoring(self):
|
||||
RSATest.test_factoring(self)
|
||||
|
||||
|
||||
def test_serialization(self):
|
||||
"""RSA (_fastmath implementation) serialize/unserialize key
|
||||
"""
|
||||
RSATest.test_serialization(self)
|
||||
|
||||
if not (3, 0) <= sys.version_info < (3, 1, 2, 'final', 0):
|
||||
# Unpickling is broken in Python 3 before 3.1.2 due to http://bugs.python.org/issue6137
|
||||
def test_serialization_compat(self):
|
||||
"""RSA (_fastmath implementation) backward compatibility serialization
|
||||
"""
|
||||
RSATest.test_serialization_compat(self)
|
||||
|
||||
|
||||
class RSASlowMathTest(RSATest):
|
||||
def setUp(self):
|
||||
RSATest.setUp(self)
|
||||
@@ -443,17 +388,6 @@ class RSASlowMathTest(RSATest):
|
||||
def test_factoring(self):
|
||||
RSATest.test_factoring(self)
|
||||
|
||||
def test_serialization(self):
|
||||
"""RSA (_slowmath implementation) serialize/unserialize key"""
|
||||
RSATest.test_serialization(self)
|
||||
|
||||
if not (3, 0) <= sys.version_info < (3, 1, 2, 'final', 0):
|
||||
# Unpickling is broken in Python 3 before 3.1.2 due to http://bugs.python.org/issue6137
|
||||
def test_serialization_compat(self):
|
||||
"""RSA (_slowmath implementation) backward compatibility serialization
|
||||
"""
|
||||
RSATest.test_serialization_compat(self)
|
||||
|
||||
def get_tests(config={}):
|
||||
tests = []
|
||||
tests += list_test_cases(RSATest)
|
||||
|
||||
@@ -0,0 +1,345 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# SelfTest/PublicKey/test_importKey.py: Self-test for importing RSA keys
|
||||
#
|
||||
# ===================================================================
|
||||
# The contents of this file are dedicated to the public domain. To
|
||||
# the extent that dedication to the public domain is not available,
|
||||
# everyone is granted a worldwide, perpetual, royalty-free,
|
||||
# non-exclusive license to exercise all rights associated with the
|
||||
# contents of this file for any purpose whatsoever.
|
||||
# No rights are reserved.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
# SOFTWARE.
|
||||
# ===================================================================
|
||||
|
||||
from __future__ import nested_scopes
|
||||
|
||||
__revision__ = "$Id$"
|
||||
|
||||
import unittest
|
||||
|
||||
from Crypto.PublicKey import RSA
|
||||
from Crypto.SelfTest.st_common import *
|
||||
from Crypto.Util.py3compat import *
|
||||
from Crypto.Util.number import inverse
|
||||
from Crypto.Util import asn1
|
||||
|
||||
def der2pem(der, text='PUBLIC'):
|
||||
import binascii
|
||||
chunks = [ binascii.b2a_base64(der[i:i+48]) for i in range(0, len(der), 48) ]
|
||||
pem = b('-----BEGIN %s KEY-----\n' % text)
|
||||
pem += b('').join(chunks)
|
||||
pem += b('-----END %s KEY-----' % text)
|
||||
return pem
|
||||
|
||||
class ImportKeyTests(unittest.TestCase):
|
||||
# 512-bit RSA key generated with openssl
|
||||
rsaKeyPEM = u'''-----BEGIN RSA PRIVATE KEY-----
|
||||
MIIBOwIBAAJBAL8eJ5AKoIsjURpcEoGubZMxLD7+kT+TLr7UkvEtFrRhDDKMtuII
|
||||
q19FrL4pUIMymPMSLBn3hJLe30Dw48GQM4UCAwEAAQJACUSDEp8RTe32ftq8IwG8
|
||||
Wojl5mAd1wFiIOrZ/Uv8b963WJOJiuQcVN29vxU5+My9GPZ7RA3hrDBEAoHUDPrI
|
||||
OQIhAPIPLz4dphiD9imAkivY31Rc5AfHJiQRA7XixTcjEkojAiEAyh/pJHks/Mlr
|
||||
+rdPNEpotBjfV4M4BkgGAA/ipcmaAjcCIQCHvhwwKVBLzzTscT2HeUdEeBMoiXXK
|
||||
JACAr3sJQJGxIQIgarRp+m1WSKV1MciwMaTOnbU7wxFs9DP1pva76lYBzgUCIQC9
|
||||
n0CnZCJ6IZYqSt0H5N7+Q+2Ro64nuwV/OSQfM6sBwQ==
|
||||
-----END RSA PRIVATE KEY-----'''
|
||||
|
||||
# As above, but this is actually an unencrypted PKCS#8 key
|
||||
rsaKeyPEM8 = u'''-----BEGIN PRIVATE KEY-----
|
||||
MIIBVQIBADANBgkqhkiG9w0BAQEFAASCAT8wggE7AgEAAkEAvx4nkAqgiyNRGlwS
|
||||
ga5tkzEsPv6RP5MuvtSS8S0WtGEMMoy24girX0WsvilQgzKY8xIsGfeEkt7fQPDj
|
||||
wZAzhQIDAQABAkAJRIMSnxFN7fZ+2rwjAbxaiOXmYB3XAWIg6tn9S/xv3rdYk4mK
|
||||
5BxU3b2/FTn4zL0Y9ntEDeGsMEQCgdQM+sg5AiEA8g8vPh2mGIP2KYCSK9jfVFzk
|
||||
B8cmJBEDteLFNyMSSiMCIQDKH+kkeSz8yWv6t080Smi0GN9XgzgGSAYAD+KlyZoC
|
||||
NwIhAIe+HDApUEvPNOxxPYd5R0R4EyiJdcokAICvewlAkbEhAiBqtGn6bVZIpXUx
|
||||
yLAxpM6dtTvDEWz0M/Wm9rvqVgHOBQIhAL2fQKdkInohlipK3Qfk3v5D7ZGjrie7
|
||||
BX85JB8zqwHB
|
||||
-----END PRIVATE KEY-----'''
|
||||
|
||||
# The same RSA private key as in rsaKeyPEM, but now encrypted
|
||||
rsaKeyEncryptedPEM=(
|
||||
|
||||
# With DES and passphrase 'test'
|
||||
('test', u'''-----BEGIN RSA PRIVATE KEY-----
|
||||
Proc-Type: 4,ENCRYPTED
|
||||
DEK-Info: DES-CBC,AF8F9A40BD2FA2FC
|
||||
|
||||
Ckl9ex1kaVEWhYC2QBmfaF+YPiR4NFkRXA7nj3dcnuFEzBnY5XULupqQpQI3qbfA
|
||||
u8GYS7+b3toWWiHZivHbAAUBPDIZG9hKDyB9Sq2VMARGsX1yW1zhNvZLIiVJzUHs
|
||||
C6NxQ1IJWOXzTew/xM2I26kPwHIvadq+/VaT8gLQdjdH0jOiVNaevjWnLgrn1mLP
|
||||
BCNRMdcexozWtAFNNqSzfW58MJL2OdMi21ED184EFytIc1BlB+FZiGZduwKGuaKy
|
||||
9bMbdb/1PSvsSzPsqW7KSSrTw6MgJAFJg6lzIYvR5F4poTVBxwBX3+EyEmShiaNY
|
||||
IRX3TgQI0IjrVuLmvlZKbGWP18FXj7I7k9tSsNOOzllTTdq3ny5vgM3A+ynfAaxp
|
||||
dysKznQ6P+IoqML1WxAID4aGRMWka+uArOJ148Rbj9s=
|
||||
-----END RSA PRIVATE KEY-----''',
|
||||
"\xAF\x8F\x9A\x40\xBD\x2F\xA2\xFC"),
|
||||
|
||||
# With Triple-DES and passphrase 'rocking'
|
||||
('rocking', u'''-----BEGIN RSA PRIVATE KEY-----
|
||||
Proc-Type: 4,ENCRYPTED
|
||||
DEK-Info: DES-EDE3-CBC,C05D6C07F7FC02F6
|
||||
|
||||
w4lwQrXaVoTTJ0GgwY566htTA2/t1YlimhxkxYt9AEeCcidS5M0Wq9ClPiPz9O7F
|
||||
m6K5QpM1rxo1RUE/ZyI85gglRNPdNwkeTOqit+kum7nN73AToX17+irVmOA4Z9E+
|
||||
4O07t91GxGMcjUSIFk0ucwEU4jgxRvYscbvOMvNbuZszGdVNzBTVddnShKCsy9i7
|
||||
nJbPlXeEKYi/OkRgO4PtfqqWQu5GIEFVUf9ev1QV7AvC+kyWTR1wWYnHX265jU5c
|
||||
sopxQQtP8XEHIJEdd5/p1oieRcWTCNyY8EkslxDSsrf0OtZp6mZH9N+KU47cgQtt
|
||||
9qGORmlWnsIoFFKcDohbtOaWBTKhkj5h6OkLjFjfU/sBeV1c+7wDT3dAy5tawXjG
|
||||
YSxC7qDQIT/RECvV3+oQKEcmpEujn45wAnkTi12BH30=
|
||||
-----END RSA PRIVATE KEY-----''',
|
||||
"\xC0\x5D\x6C\x07\xF7\xFC\x02\xF6"),
|
||||
)
|
||||
|
||||
rsaPublicKeyPEM = u'''-----BEGIN PUBLIC KEY-----
|
||||
MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAL8eJ5AKoIsjURpcEoGubZMxLD7+kT+T
|
||||
Lr7UkvEtFrRhDDKMtuIIq19FrL4pUIMymPMSLBn3hJLe30Dw48GQM4UCAwEAAQ==
|
||||
-----END PUBLIC KEY-----'''
|
||||
|
||||
# Obtained using 'ssh-keygen -i -m PKCS8 -f rsaPublicKeyPEM'
|
||||
rsaPublicKeyOpenSSH = '''ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAQQC/HieQCqCLI1EaXBKBrm2TMSw+/pE/ky6+1JLxLRa0YQwyjLbiCKtfRay+KVCDMpjzEiwZ94SS3t9A8OPBkDOF comment\n'''
|
||||
|
||||
# The private key, in PKCS#1 format encoded with DER
|
||||
rsaKeyDER = a2b_hex(
|
||||
'''3082013b020100024100bf1e27900aa08b23511a5c1281ae6d93312c3efe
|
||||
913f932ebed492f12d16b4610c328cb6e208ab5f45acbe2950833298f312
|
||||
2c19f78492dedf40f0e3c190338502030100010240094483129f114dedf6
|
||||
7edabc2301bc5a88e5e6601dd7016220ead9fd4bfc6fdeb75893898ae41c
|
||||
54ddbdbf1539f8ccbd18f67b440de1ac30440281d40cfac839022100f20f
|
||||
2f3e1da61883f62980922bd8df545ce407c726241103b5e2c53723124a23
|
||||
022100ca1fe924792cfcc96bfab74f344a68b418df578338064806000fe2
|
||||
a5c99a023702210087be1c3029504bcf34ec713d877947447813288975ca
|
||||
240080af7b094091b12102206ab469fa6d5648a57531c8b031a4ce9db53b
|
||||
c3116cf433f5a6f6bbea5601ce05022100bd9f40a764227a21962a4add07
|
||||
e4defe43ed91a3ae27bb057f39241f33ab01c1
|
||||
'''.replace(" ",""))
|
||||
|
||||
# The private key, in unencrypted PKCS#8 format encoded with DER
|
||||
rsaKeyDER8 = a2b_hex(
|
||||
'''30820155020100300d06092a864886f70d01010105000482013f3082013
|
||||
b020100024100bf1e27900aa08b23511a5c1281ae6d93312c3efe913f932
|
||||
ebed492f12d16b4610c328cb6e208ab5f45acbe2950833298f3122c19f78
|
||||
492dedf40f0e3c190338502030100010240094483129f114dedf67edabc2
|
||||
301bc5a88e5e6601dd7016220ead9fd4bfc6fdeb75893898ae41c54ddbdb
|
||||
f1539f8ccbd18f67b440de1ac30440281d40cfac839022100f20f2f3e1da
|
||||
61883f62980922bd8df545ce407c726241103b5e2c53723124a23022100c
|
||||
a1fe924792cfcc96bfab74f344a68b418df578338064806000fe2a5c99a0
|
||||
23702210087be1c3029504bcf34ec713d877947447813288975ca240080a
|
||||
f7b094091b12102206ab469fa6d5648a57531c8b031a4ce9db53bc3116cf
|
||||
433f5a6f6bbea5601ce05022100bd9f40a764227a21962a4add07e4defe4
|
||||
3ed91a3ae27bb057f39241f33ab01c1
|
||||
'''.replace(" ",""))
|
||||
|
||||
rsaPublicKeyDER = a2b_hex(
|
||||
'''305c300d06092a864886f70d0101010500034b003048024100bf1e27900a
|
||||
a08b23511a5c1281ae6d93312c3efe913f932ebed492f12d16b4610c328c
|
||||
b6e208ab5f45acbe2950833298f3122c19f78492dedf40f0e3c190338502
|
||||
03010001
|
||||
'''.replace(" ",""))
|
||||
|
||||
n = long('BF 1E 27 90 0A A0 8B 23 51 1A 5C 12 81 AE 6D 93 31 2C 3E FE 91 3F 93 2E BE D4 92 F1 2D 16 B4 61 0C 32 8C B6 E2 08 AB 5F 45 AC BE 29 50 83 32 98 F3 12 2C 19 F7 84 92 DE DF 40 F0 E3 C1 90 33 85'.replace(" ",""),16)
|
||||
e = 65537L
|
||||
d = long('09 44 83 12 9F 11 4D ED F6 7E DA BC 23 01 BC 5A 88 E5 E6 60 1D D7 01 62 20 EA D9 FD 4B FC 6F DE B7 58 93 89 8A E4 1C 54 DD BD BF 15 39 F8 CC BD 18 F6 7B 44 0D E1 AC 30 44 02 81 D4 0C FA C8 39'.replace(" ",""),16)
|
||||
p = long('00 F2 0F 2F 3E 1D A6 18 83 F6 29 80 92 2B D8 DF 54 5C E4 07 C7 26 24 11 03 B5 E2 C5 37 23 12 4A 23'.replace(" ",""),16)
|
||||
q = long('00 CA 1F E9 24 79 2C FC C9 6B FA B7 4F 34 4A 68 B4 18 DF 57 83 38 06 48 06 00 0F E2 A5 C9 9A 02 37'.replace(" ",""),16)
|
||||
|
||||
# This is q^{-1} mod p). fastmath and slowmath use pInv (p^{-1}
|
||||
# mod q) instead!
|
||||
qInv = long('00 BD 9F 40 A7 64 22 7A 21 96 2A 4A DD 07 E4 DE FE 43 ED 91 A3 AE 27 BB 05 7F 39 24 1F 33 AB 01 C1'.replace(" ",""),16)
|
||||
pInv = inverse(p,q)
|
||||
|
||||
def testImportKey1(self):
|
||||
"""Verify import of RSAPrivateKey DER SEQUENCE"""
|
||||
key = self.rsa.importKey(self.rsaKeyDER)
|
||||
self.failUnless(key.has_private())
|
||||
self.assertEqual(key.n, self.n)
|
||||
self.assertEqual(key.e, self.e)
|
||||
self.assertEqual(key.d, self.d)
|
||||
self.assertEqual(key.p, self.p)
|
||||
self.assertEqual(key.q, self.q)
|
||||
|
||||
def testImportKey2(self):
|
||||
"""Verify import of SubjectPublicKeyInfo DER SEQUENCE"""
|
||||
key = self.rsa.importKey(self.rsaPublicKeyDER)
|
||||
self.failIf(key.has_private())
|
||||
self.assertEqual(key.n, self.n)
|
||||
self.assertEqual(key.e, self.e)
|
||||
|
||||
def testImportKey3unicode(self):
|
||||
"""Verify import of RSAPrivateKey DER SEQUENCE, encoded with PEM as unicode"""
|
||||
key = RSA.importKey(self.rsaKeyPEM)
|
||||
self.assertEqual(key.has_private(),True) # assert_
|
||||
self.assertEqual(key.n, self.n)
|
||||
self.assertEqual(key.e, self.e)
|
||||
self.assertEqual(key.d, self.d)
|
||||
self.assertEqual(key.p, self.p)
|
||||
self.assertEqual(key.q, self.q)
|
||||
|
||||
def testImportKey3bytes(self):
|
||||
"""Verify import of RSAPrivateKey DER SEQUENCE, encoded with PEM as byte string"""
|
||||
key = RSA.importKey(b(self.rsaKeyPEM))
|
||||
self.assertEqual(key.has_private(),True) # assert_
|
||||
self.assertEqual(key.n, self.n)
|
||||
self.assertEqual(key.e, self.e)
|
||||
self.assertEqual(key.d, self.d)
|
||||
self.assertEqual(key.p, self.p)
|
||||
self.assertEqual(key.q, self.q)
|
||||
|
||||
def testImportKey4unicode(self):
|
||||
"""Verify import of RSAPrivateKey DER SEQUENCE, encoded with PEM as unicode"""
|
||||
key = RSA.importKey(self.rsaPublicKeyPEM)
|
||||
self.assertEqual(key.has_private(),False) # failIf
|
||||
self.assertEqual(key.n, self.n)
|
||||
self.assertEqual(key.e, self.e)
|
||||
|
||||
def testImportKey4bytes(self):
|
||||
"""Verify import of SubjectPublicKeyInfo DER SEQUENCE, encoded with PEM as byte string"""
|
||||
key = RSA.importKey(b(self.rsaPublicKeyPEM))
|
||||
self.assertEqual(key.has_private(),False) # failIf
|
||||
self.assertEqual(key.n, self.n)
|
||||
self.assertEqual(key.e, self.e)
|
||||
|
||||
def testImportKey5(self):
|
||||
"""Verifies that the imported key is still a valid RSA pair"""
|
||||
key = RSA.importKey(self.rsaKeyPEM)
|
||||
idem = key.encrypt(key.decrypt(b("Test")),0)
|
||||
self.assertEqual(idem[0],b("Test"))
|
||||
|
||||
def testImportKey6(self):
|
||||
"""Verifies that the imported key is still a valid RSA pair"""
|
||||
key = RSA.importKey(self.rsaKeyDER)
|
||||
idem = key.encrypt(key.decrypt(b("Test")),0)
|
||||
self.assertEqual(idem[0],b("Test"))
|
||||
|
||||
def testImportKey7(self):
|
||||
"""Verify import of OpenSSH public key"""
|
||||
key = self.rsa.importKey(self.rsaPublicKeyOpenSSH)
|
||||
self.assertEqual(key.n, self.n)
|
||||
self.assertEqual(key.e, self.e)
|
||||
|
||||
def testImportKey8(self):
|
||||
"""Verify import of encrypted PrivateKeyInfo DER SEQUENCE"""
|
||||
for t in self.rsaKeyEncryptedPEM:
|
||||
key = self.rsa.importKey(t[1], t[0])
|
||||
self.failUnless(key.has_private())
|
||||
self.assertEqual(key.n, self.n)
|
||||
self.assertEqual(key.e, self.e)
|
||||
self.assertEqual(key.d, self.d)
|
||||
self.assertEqual(key.p, self.p)
|
||||
self.assertEqual(key.q, self.q)
|
||||
|
||||
def testImportKey9(self):
|
||||
"""Verify import of unencrypted PrivateKeyInfo DER SEQUENCE"""
|
||||
key = self.rsa.importKey(self.rsaKeyDER8)
|
||||
self.failUnless(key.has_private())
|
||||
self.assertEqual(key.n, self.n)
|
||||
self.assertEqual(key.e, self.e)
|
||||
self.assertEqual(key.d, self.d)
|
||||
self.assertEqual(key.p, self.p)
|
||||
self.assertEqual(key.q, self.q)
|
||||
|
||||
def testImportKey10(self):
|
||||
"""Verify import of unencrypted PrivateKeyInfo DER SEQUENCE, encoded with PEM"""
|
||||
key = self.rsa.importKey(self.rsaKeyPEM8)
|
||||
self.failUnless(key.has_private())
|
||||
self.assertEqual(key.n, self.n)
|
||||
self.assertEqual(key.e, self.e)
|
||||
self.assertEqual(key.d, self.d)
|
||||
self.assertEqual(key.p, self.p)
|
||||
self.assertEqual(key.q, self.q)
|
||||
|
||||
def testImportKey11(self):
|
||||
"""Verify import of RSAPublicKey DER SEQUENCE"""
|
||||
der = asn1.DerSequence([17, 3]).encode()
|
||||
key = self.rsa.importKey(der)
|
||||
self.assertEqual(key.n, 17)
|
||||
self.assertEqual(key.e, 3)
|
||||
|
||||
def testImportKey12(self):
|
||||
"""Verify import of RSAPublicKey DER SEQUENCE, encoded with PEM"""
|
||||
der = asn1.DerSequence([17, 3]).encode()
|
||||
pem = der2pem(der)
|
||||
key = self.rsa.importKey(pem)
|
||||
self.assertEqual(key.n, 17)
|
||||
self.assertEqual(key.e, 3)
|
||||
|
||||
###
|
||||
def testExportKey1(self):
|
||||
key = self.rsa.construct([self.n, self.e, self.d, self.p, self.q, self.pInv])
|
||||
derKey = key.exportKey("DER")
|
||||
self.assertEqual(derKey, self.rsaKeyDER)
|
||||
|
||||
def testExportKey2(self):
|
||||
key = self.rsa.construct([self.n, self.e])
|
||||
derKey = key.exportKey("DER")
|
||||
self.assertEqual(derKey, self.rsaPublicKeyDER)
|
||||
|
||||
def testExportKey3(self):
|
||||
key = self.rsa.construct([self.n, self.e, self.d, self.p, self.q, self.pInv])
|
||||
pemKey = key.exportKey("PEM")
|
||||
self.assertEqual(pemKey, b(self.rsaKeyPEM))
|
||||
|
||||
def testExportKey4(self):
|
||||
key = self.rsa.construct([self.n, self.e])
|
||||
pemKey = key.exportKey("PEM")
|
||||
self.assertEqual(pemKey, b(self.rsaPublicKeyPEM))
|
||||
|
||||
def testExportKey5(self):
|
||||
key = self.rsa.construct([self.n, self.e])
|
||||
openssh_1 = key.exportKey("OpenSSH").split()
|
||||
openssh_2 = self.rsaPublicKeyOpenSSH.split()
|
||||
self.assertEqual(openssh_1[0], openssh_2[0])
|
||||
self.assertEqual(openssh_1[1], openssh_2[1])
|
||||
|
||||
def testExportKey4(self):
|
||||
key = self.rsa.construct([self.n, self.e, self.d, self.p, self.q, self.pInv])
|
||||
# Tuple with index #1 is encrypted with 3DES
|
||||
t = map(b,self.rsaKeyEncryptedPEM[1])
|
||||
# Force the salt being used when exporting
|
||||
key._randfunc = lambda N: (t[2]*divmod(N+len(t[2]),len(t[2]))[0])[:N]
|
||||
pemKey = key.exportKey("PEM", t[0])
|
||||
self.assertEqual(pemKey, t[1])
|
||||
|
||||
def testExportKey5(self):
|
||||
key = self.rsa.construct([self.n, self.e, self.d, self.p, self.q, self.pInv])
|
||||
derKey = key.exportKey("DER", pkcs=8)
|
||||
self.assertEqual(derKey, self.rsaKeyDER8)
|
||||
|
||||
def testExportKey6(self):
|
||||
key = self.rsa.construct([self.n, self.e, self.d, self.p, self.q, self.pInv])
|
||||
pemKey = key.exportKey("PEM", pkcs=8)
|
||||
self.assertEqual(pemKey, b(self.rsaKeyPEM8))
|
||||
|
||||
class ImportKeyTestsSlow(ImportKeyTests):
|
||||
def setUp(self):
|
||||
self.rsa = RSA.RSAImplementation(use_fast_math=0)
|
||||
|
||||
class ImportKeyTestsFast(ImportKeyTests):
|
||||
def setUp(self):
|
||||
self.rsa = RSA.RSAImplementation(use_fast_math=1)
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
|
||||
def get_tests(config={}):
|
||||
tests = []
|
||||
try:
|
||||
from Crypto.PublicKey import _fastmath
|
||||
tests += list_test_cases(ImportKeyTestsFast)
|
||||
except ImportError:
|
||||
pass
|
||||
tests += list_test_cases(ImportKeyTestsSlow)
|
||||
return tests
|
||||
|
||||
if __name__ == '__main__':
|
||||
suite = lambda: unittest.TestSuite(get_tests())
|
||||
unittest.main(defaultTest='suite')
|
||||
|
||||
# vim:set ts=4 sw=4 sts=4 expandtab:
|
||||
@@ -32,7 +32,6 @@ def get_tests(config={}):
|
||||
from Crypto.SelfTest.Random import OSRNG; tests += OSRNG.get_tests(config=config)
|
||||
from Crypto.SelfTest.Random import test_random; tests += test_random.get_tests(config=config)
|
||||
from Crypto.SelfTest.Random import test_rpoolcompat; tests += test_rpoolcompat.get_tests(config=config)
|
||||
from Crypto.SelfTest.Random import test__UserFriendlyRNG; tests += test__UserFriendlyRNG.get_tests(config=config)
|
||||
return tests
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
||||
@@ -133,7 +133,7 @@ class SimpleTest(unittest.TestCase):
|
||||
self.assertEqual(b('1') in z, True)
|
||||
self.assertRaises(TypeError, random.shuffle, b('12'))
|
||||
self.assertRaises(TypeError, random.shuffle, 1)
|
||||
self.assertRaises(TypeError, random.shuffle, "11")
|
||||
self.assertRaises(TypeError, random.shuffle, "1")
|
||||
self.assertRaises(TypeError, random.shuffle, (1,2))
|
||||
# 2to3 wraps a list() around it, alas - but I want to shoot
|
||||
# myself in the foot here! :D
|
||||
|
||||
@@ -26,8 +26,7 @@ import unittest
|
||||
|
||||
from Crypto.PublicKey import RSA
|
||||
from Crypto.SelfTest.st_common import list_test_cases, a2b_hex, b2a_hex
|
||||
from Crypto.Hash import MD2, SHA1, MD5, SHA224, SHA256, SHA384, SHA512,\
|
||||
RIPEMD160
|
||||
from Crypto.Hash import *
|
||||
from Crypto import Random
|
||||
from Crypto.Signature import PKCS1_v1_5 as PKCS
|
||||
from Crypto.Util.py3compat import *
|
||||
@@ -124,7 +123,7 @@ class PKCS1_15_Tests(unittest.TestCase):
|
||||
'''4a700a16432a291a3194646952687d5316458b8b86fb0a25aa30e0dcecdb
|
||||
442676759ac63d56ec1499c3ae4c0013c2053cabd5b5804848994541ac16
|
||||
fa243a4d''',
|
||||
SHA1
|
||||
SHA
|
||||
),
|
||||
|
||||
#
|
||||
@@ -147,7 +146,7 @@ class PKCS1_15_Tests(unittest.TestCase):
|
||||
A9D20970C54E6651070B0144D43844C899320DD8FA7819F7EBC6A7715287332E
|
||||
C8675C136183B3F8A1F81EF969418267130A756FDBB2C71D9A667446E34E0EAD
|
||||
9CF31BFB66F816F319D0B7E430A5F2891553986E003720261C7E9022C0D9F11F''',
|
||||
SHA1
|
||||
SHA
|
||||
)
|
||||
|
||||
)
|
||||
@@ -198,7 +197,7 @@ class PKCS1_15_Tests(unittest.TestCase):
|
||||
rng = Random.new().read
|
||||
key = RSA.generate(1024, rng)
|
||||
|
||||
for hashmod in (MD2,MD5,SHA1,SHA224,SHA256,SHA384,SHA512,RIPEMD160):
|
||||
for hashmod in (MD2,MD5,SHA,SHA224,SHA256,SHA384,SHA512,RIPEMD):
|
||||
h = hashmod.new()
|
||||
h.update(b('blah blah blah'))
|
||||
|
||||
@@ -207,37 +206,10 @@ class PKCS1_15_Tests(unittest.TestCase):
|
||||
result = signer.verify(h, s)
|
||||
self.failUnless(result)
|
||||
|
||||
class PKCS1_15_NoParams(unittest.TestCase):
|
||||
"""Verify that PKCS#1 v1.5 signatures pass even without NULL parameters in
|
||||
the algorithm identifier (bug #1119552)."""
|
||||
|
||||
rsakey = """-----BEGIN RSA PRIVATE KEY-----
|
||||
MIIBOwIBAAJBAL8eJ5AKoIsjURpcEoGubZMxLD7+kT+TLr7UkvEtFrRhDDKMtuII
|
||||
q19FrL4pUIMymPMSLBn3hJLe30Dw48GQM4UCAwEAAQJACUSDEp8RTe32ftq8IwG8
|
||||
Wojl5mAd1wFiIOrZ/Uv8b963WJOJiuQcVN29vxU5+My9GPZ7RA3hrDBEAoHUDPrI
|
||||
OQIhAPIPLz4dphiD9imAkivY31Rc5AfHJiQRA7XixTcjEkojAiEAyh/pJHks/Mlr
|
||||
+rdPNEpotBjfV4M4BkgGAA/ipcmaAjcCIQCHvhwwKVBLzzTscT2HeUdEeBMoiXXK
|
||||
JACAr3sJQJGxIQIgarRp+m1WSKV1MciwMaTOnbU7wxFs9DP1pva76lYBzgUCIQC9
|
||||
n0CnZCJ6IZYqSt0H5N7+Q+2Ro64nuwV/OSQfM6sBwQ==
|
||||
-----END RSA PRIVATE KEY-----"""
|
||||
|
||||
msg = b("This is a test\x0a")
|
||||
|
||||
# PKCS1 v1.5 signature of the message computed using SHA-1.
|
||||
# The digestAlgorithm SEQUENCE does NOT contain the NULL parameter.
|
||||
signature = '''a287a13517f716e72fb14eea8e33a8db4a4643314607e7ca3e3e281893db7401
|
||||
3dda8b855fd99f6fecedcb25fcb7a434f35cd0a101f8b19348e0bd7b6f152dfc'''
|
||||
|
||||
def testVerify(self):
|
||||
verifier = PKCS.new(RSA.importKey(self.rsakey))
|
||||
h = SHA1.new(self.msg)
|
||||
result = verifier.verify(h, t2b(self.signature))
|
||||
self.failUnless(result)
|
||||
|
||||
def get_tests(config={}):
|
||||
tests = []
|
||||
tests += list_test_cases(PKCS1_15_Tests)
|
||||
tests += list_test_cases(PKCS1_15_NoParams)
|
||||
return tests
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
||||
@@ -29,8 +29,7 @@ import unittest
|
||||
from Crypto.PublicKey import RSA
|
||||
from Crypto import Random
|
||||
from Crypto.SelfTest.st_common import list_test_cases, a2b_hex, b2a_hex
|
||||
from Crypto.Hash import SHA1, MD2, RIPEMD160, SHA224, SHA384, SHA512,\
|
||||
SHA256, MD5
|
||||
from Crypto.Hash import *
|
||||
from Crypto.Signature import PKCS1_PSS as PKCS
|
||||
from Crypto.Util.py3compat import *
|
||||
|
||||
@@ -137,7 +136,7 @@ class PKCS1_PSS_Tests(unittest.TestCase):
|
||||
'''e3 b5 d5 d0 02 c1 bc e5 0c 2b 65 ef 88 a1 88 d8
|
||||
3b ce 7e 61''',
|
||||
# Hash algorithm
|
||||
SHA1
|
||||
SHA
|
||||
),
|
||||
|
||||
#
|
||||
@@ -193,7 +192,7 @@ class PKCS1_PSS_Tests(unittest.TestCase):
|
||||
'''de e9 59 c7 e0 64 11 36 14 20 ff 80 18 5e d5 7f
|
||||
3e 67 76 af''',
|
||||
# Hash
|
||||
SHA1
|
||||
SHA
|
||||
),
|
||||
|
||||
#
|
||||
@@ -239,7 +238,7 @@ class PKCS1_PSS_Tests(unittest.TestCase):
|
||||
'''ef 28 69 fa 40 c3 46 cb 18 3d ab 3d 7b ff c9 8f
|
||||
d5 6d f4 2d''',
|
||||
# Hash
|
||||
SHA1
|
||||
SHA
|
||||
),
|
||||
|
||||
#
|
||||
@@ -286,7 +285,7 @@ class PKCS1_PSS_Tests(unittest.TestCase):
|
||||
# Salt
|
||||
'''57 bf 16 0b cb 02 bb 1d c7 28 0c f0 45 85 30 b7
|
||||
d2 83 2f f7''',
|
||||
SHA1
|
||||
SHA
|
||||
),
|
||||
|
||||
#
|
||||
@@ -340,7 +339,7 @@ class PKCS1_PSS_Tests(unittest.TestCase):
|
||||
# Salt
|
||||
'''1d 65 49 1d 79 c8 64 b3 73 00 9b e6 f6 f2 46 7b
|
||||
ac 4c 78 fa''',
|
||||
SHA1
|
||||
SHA
|
||||
)
|
||||
)
|
||||
|
||||
@@ -381,12 +380,12 @@ class PKCS1_PSS_Tests(unittest.TestCase):
|
||||
self.failUnless(result)
|
||||
|
||||
def testSignVerify(self):
|
||||
h = SHA1.new()
|
||||
h = SHA.new()
|
||||
h.update(b('blah blah blah'))
|
||||
|
||||
rng = Random.new().read
|
||||
key = MyKey(RSA.generate(1024,rng))
|
||||
|
||||
|
||||
# Helper function to monitor what's request from MGF
|
||||
global mgfcalls
|
||||
def newMGF(seed,maskLen):
|
||||
@@ -395,7 +394,7 @@ class PKCS1_PSS_Tests(unittest.TestCase):
|
||||
return bchr(0x00)*maskLen
|
||||
|
||||
# Verify that PSS is friendly to all ciphers
|
||||
for hashmod in (MD2,MD5,SHA1,SHA224,SHA256,SHA384,RIPEMD160):
|
||||
for hashmod in (MD2,MD5,SHA,SHA224,SHA256,SHA384,RIPEMD):
|
||||
h = hashmod.new()
|
||||
h.update(b('blah blah blah'))
|
||||
|
||||
@@ -407,7 +406,7 @@ class PKCS1_PSS_Tests(unittest.TestCase):
|
||||
self.failUnless(signer.verify(h, s))
|
||||
self.assertEqual(key.asked, h.digest_size)
|
||||
|
||||
h = SHA1.new()
|
||||
h = SHA.new()
|
||||
h.update(b('blah blah blah'))
|
||||
|
||||
# Verify that sign() uses a different salt length
|
||||
|
||||
@@ -34,7 +34,6 @@ def get_tests(config={}):
|
||||
from Crypto.SelfTest.Util import test_winrandom; tests += test_winrandom.get_tests(config=config)
|
||||
from Crypto.SelfTest.Util import test_number; tests += test_number.get_tests(config=config)
|
||||
from Crypto.SelfTest.Util import test_Counter; tests += test_Counter.get_tests(config=config)
|
||||
from Crypto.SelfTest.Util import test_Padding; tests += test_Padding.get_tests(config=config)
|
||||
return tests
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
||||
@@ -39,24 +39,34 @@ class CounterTests(unittest.TestCase):
|
||||
from Crypto.Util import Counter
|
||||
|
||||
def test_BE_shortcut(self):
|
||||
"""Big endian"""
|
||||
"""Big endian, shortcut enabled"""
|
||||
c = Counter.new(128)
|
||||
self.assertEqual(c.__PCT_CTR_SHORTCUT__,True) # assert_
|
||||
c = Counter.new(128, little_endian=False)
|
||||
self.assertEqual(c.__PCT_CTR_SHORTCUT__,True) # assert_
|
||||
c = Counter.new(128, disable_shortcut=False)
|
||||
self.assertEqual(c.__PCT_CTR_SHORTCUT__,True) # assert_
|
||||
c = Counter.new(128, little_endian=False, disable_shortcut=False)
|
||||
self.assertEqual(c.__PCT_CTR_SHORTCUT__,True) # assert_
|
||||
|
||||
def test_LE_shortcut(self):
|
||||
"""Little endian"""
|
||||
"""Little endian, shortcut enabled"""
|
||||
c = Counter.new(128, little_endian=True)
|
||||
self.assertEqual(c.__PCT_CTR_SHORTCUT__,True) # assert_
|
||||
c = Counter.new(128, little_endian=True, disable_shortcut=False)
|
||||
self.assertEqual(c.__PCT_CTR_SHORTCUT__,True) # assert_
|
||||
|
||||
def test_BE_no_shortcut(self):
|
||||
"""Big endian, with disable_shortcut"""
|
||||
# Just testing API backward-compatibility. disable_shortcut is now a no-op.
|
||||
"""Big endian, shortcut disabled"""
|
||||
c = Counter.new(128, disable_shortcut=True)
|
||||
self.assertRaises(AttributeError, getattr, c, '__PCT_CTR_SHORTCUT__')
|
||||
c = Counter.new(128, little_endian=False, disable_shortcut=True)
|
||||
self.assertRaises(AttributeError, getattr, c, '__PCT_CTR_SHORTCUT__')
|
||||
|
||||
def test_LE_no_shortcut(self):
|
||||
"""Little endian, shortcut disabled"""
|
||||
# Just testing API backward-compatibility. disable_shortcut is now a no-op.
|
||||
c = Counter.new(128, little_endian=True, disable_shortcut=True)
|
||||
self.assertRaises(AttributeError, getattr, c, '__PCT_CTR_SHORTCUT__')
|
||||
|
||||
def test_BE_defaults(self):
|
||||
"""128-bit, Big endian, defaults"""
|
||||
|
||||
@@ -28,626 +28,262 @@ import unittest
|
||||
import sys
|
||||
|
||||
from Crypto.Util.py3compat import *
|
||||
from Crypto.Util.asn1 import DerObject, DerSetOf, newDerSetOf, DerInteger,\
|
||||
DerBitString, newDerBitString, newDerObjectId,\
|
||||
DerObjectId, DerNull, DerOctetString,\
|
||||
newDerOctetString, DerSequence, newDerSequence,\
|
||||
newDerInteger
|
||||
if sys.version_info[0] == 2 and sys.version_info[1] == 1:
|
||||
from Crypto.Util.py21compat import *
|
||||
from Crypto.Util.asn1 import DerSequence, DerObject
|
||||
|
||||
class DerObjectTests(unittest.TestCase):
|
||||
|
||||
def testObjInit1(self):
|
||||
# Fail with invalid tag format (must be 1 byte)
|
||||
self.assertRaises(ValueError, DerObject, b('\x00\x99'))
|
||||
# Fail with invalid implicit tag (must be <0x1F)
|
||||
self.assertRaises(ValueError, DerObject, 0x1F)
|
||||
def testObjEncode1(self):
|
||||
# No payload
|
||||
der = DerObject(b('\x33'))
|
||||
self.assertEquals(der.encode(), b('\x33\x00'))
|
||||
# Small payload
|
||||
der.payload = b('\x45')
|
||||
self.assertEquals(der.encode(), b('\x33\x01\x45'))
|
||||
# Invariant
|
||||
self.assertEquals(der.encode(), b('\x33\x01\x45'))
|
||||
# Initialize with numerical tag
|
||||
der = DerObject(b(0x33))
|
||||
der.payload = b('\x45')
|
||||
self.assertEquals(der.encode(), b('\x33\x01\x45'))
|
||||
|
||||
# ------
|
||||
def testObjEncode2(self):
|
||||
# Known types
|
||||
der = DerObject('SEQUENCE')
|
||||
self.assertEquals(der.encode(), b('\x30\x00'))
|
||||
der = DerObject('BIT STRING')
|
||||
self.assertEquals(der.encode(), b('\x03\x00'))
|
||||
|
||||
def testObjEncode3(self):
|
||||
# Long payload
|
||||
der = DerObject(b('\x34'))
|
||||
der.payload = b("0")*128
|
||||
self.assertEquals(der.encode(), b('\x34\x81\x80' + "0"*128))
|
||||
|
||||
def testObjEncode1(self):
|
||||
# No payload
|
||||
der = DerObject(b('\x02'))
|
||||
self.assertEquals(der.encode(), b('\x02\x00'))
|
||||
# Small payload (primitive)
|
||||
der.payload = b('\x45')
|
||||
self.assertEquals(der.encode(), b('\x02\x01\x45'))
|
||||
# Invariant
|
||||
self.assertEquals(der.encode(), b('\x02\x01\x45'))
|
||||
# Initialize with numerical tag
|
||||
der = DerObject(0x04)
|
||||
der.payload = b('\x45')
|
||||
self.assertEquals(der.encode(), b('\x04\x01\x45'))
|
||||
# Initialize with constructed type
|
||||
der = DerObject(b('\x10'), constructed=True)
|
||||
self.assertEquals(der.encode(), b('\x30\x00'))
|
||||
def testObjDecode1(self):
|
||||
# Decode short payload
|
||||
der = DerObject()
|
||||
der.decode(b('\x20\x02\x01\x02'))
|
||||
self.assertEquals(der.payload, b("\x01\x02"))
|
||||
self.assertEquals(der.typeTag, 0x20)
|
||||
|
||||
def testObjEncode2(self):
|
||||
# Initialize with payload
|
||||
der = DerObject(0x03, b('\x12\x12'))
|
||||
self.assertEquals(der.encode(), b('\x03\x02\x12\x12'))
|
||||
|
||||
def testObjEncode3(self):
|
||||
# Long payload
|
||||
der = DerObject(b('\x10'))
|
||||
der.payload = b("0")*128
|
||||
self.assertEquals(der.encode(), b('\x10\x81\x80' + "0"*128))
|
||||
|
||||
def testObjEncode4(self):
|
||||
# Implicit tags (constructed)
|
||||
der = DerObject(0x10, implicit=1, constructed=True)
|
||||
der.payload = b('ppll')
|
||||
self.assertEquals(der.encode(), b('\xa1\x04ppll'))
|
||||
# Implicit tags (primitive)
|
||||
der = DerObject(0x02, implicit=0x1E, constructed=False)
|
||||
der.payload = b('ppll')
|
||||
self.assertEquals(der.encode(), b('\x9E\x04ppll'))
|
||||
|
||||
# -----
|
||||
|
||||
def testObjDecode1(self):
|
||||
# Decode short payload
|
||||
der = DerObject(0x02)
|
||||
der.decode(b('\x02\x02\x01\x02'))
|
||||
self.assertEquals(der.payload, b("\x01\x02"))
|
||||
self.assertEquals(der._idOctet, 0x02)
|
||||
|
||||
def testObjDecode2(self):
|
||||
# Decode long payload
|
||||
der = DerObject(0x02)
|
||||
der.decode(b('\x02\x81\x80' + "1"*128))
|
||||
self.assertEquals(der.payload, b("1")*128)
|
||||
self.assertEquals(der._idOctet, 0x02)
|
||||
|
||||
def testObjDecode3(self):
|
||||
# Decode payload with too much data gives error
|
||||
der = DerObject(0x02)
|
||||
self.assertRaises(ValueError, der.decode, b('\x02\x02\x01\x02\xFF'))
|
||||
# Decode payload with too little data gives error
|
||||
der = DerObject(0x02)
|
||||
self.assertRaises(EOFError, der.decode, b('\x02\x02\x01'))
|
||||
|
||||
def testObjDecode4(self):
|
||||
# Decode implicit tag (primitive)
|
||||
der = DerObject(0x02, constructed=False, implicit=0xF)
|
||||
self.assertRaises(ValueError, der.decode, b('\x02\x02\x01\x02'))
|
||||
der.decode(b('\x8F\x01\x00'))
|
||||
self.assertEquals(der.payload, b('\x00'))
|
||||
# Decode implicit tag (constructed)
|
||||
der = DerObject(0x02, constructed=True, implicit=0xF)
|
||||
self.assertRaises(ValueError, der.decode, b('\x02\x02\x01\x02'))
|
||||
der.decode(b('\xAF\x01\x00'))
|
||||
self.assertEquals(der.payload, b('\x00'))
|
||||
|
||||
def testObjDecode5(self):
|
||||
# Decode payload with unexpected tag gives error
|
||||
der = DerObject(0x02)
|
||||
self.assertRaises(ValueError, der.decode, b('\x03\x02\x01\x02'))
|
||||
|
||||
def testObjDecode6(self):
|
||||
# Arbitrary DER object
|
||||
der = DerObject()
|
||||
der.decode(b('\x65\x01\x88'))
|
||||
self.assertEquals(der._idOctet, 0x65)
|
||||
self.assertEquals(der.payload, b('\x88'))
|
||||
|
||||
class DerIntegerTests(unittest.TestCase):
|
||||
|
||||
def testInit1(self):
|
||||
der = newDerInteger(1)
|
||||
self.assertEquals(der.encode(), b('\x02\x01\x01'))
|
||||
|
||||
def testEncode1(self):
|
||||
# Single-byte integers
|
||||
# Value 0
|
||||
der = DerInteger(0)
|
||||
self.assertEquals(der.encode(), b('\x02\x01\x00'))
|
||||
# Value 1
|
||||
der = DerInteger(1)
|
||||
self.assertEquals(der.encode(), b('\x02\x01\x01'))
|
||||
# Value 127
|
||||
der = DerInteger(127)
|
||||
self.assertEquals(der.encode(), b('\x02\x01\x7F'))
|
||||
|
||||
def testEncode2(self):
|
||||
# Multi-byte integers
|
||||
# Value 128
|
||||
der = DerInteger(128)
|
||||
self.assertEquals(der.encode(), b('\x02\x02\x00\x80'))
|
||||
# Value 0x180
|
||||
der = DerInteger(0x180L)
|
||||
self.assertEquals(der.encode(), b('\x02\x02\x01\x80'))
|
||||
# One very long integer
|
||||
der = DerInteger(2L**2048)
|
||||
self.assertEquals(der.encode(),
|
||||
b('\x02\x82\x01\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00')+
|
||||
b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+
|
||||
b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+
|
||||
b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+
|
||||
b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+
|
||||
b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+
|
||||
b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+
|
||||
b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+
|
||||
b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+
|
||||
b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+
|
||||
b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+
|
||||
b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+
|
||||
b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+
|
||||
b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+
|
||||
b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+
|
||||
b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+
|
||||
b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+
|
||||
b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+
|
||||
b('\x00\x00\x00\x00\x00\x00\x00\x00\x00'))
|
||||
|
||||
def testEncode3(self):
|
||||
# Negative integers
|
||||
# Value -1
|
||||
der = DerInteger(-1)
|
||||
self.assertEquals(der.encode(), b('\x02\x01\xFF'))
|
||||
# Value -128
|
||||
der = DerInteger(-128)
|
||||
self.assertEquals(der.encode(), b('\x02\x01\x80'))
|
||||
# Value
|
||||
der = DerInteger(-87873)
|
||||
self.assertEquals(der.encode(), b('\x02\x03\xFE\xA8\xBF'))
|
||||
|
||||
# -----
|
||||
|
||||
def testDecode1(self):
|
||||
# Single-byte integer
|
||||
der = DerInteger()
|
||||
# Value 0
|
||||
der.decode(b('\x02\x01\x00'))
|
||||
self.assertEquals(der.value, 0)
|
||||
# Value 1
|
||||
der.decode(b('\x02\x01\x01'))
|
||||
self.assertEquals(der.value, 1)
|
||||
# Value 127
|
||||
der.decode(b('\x02\x01\x7F'))
|
||||
self.assertEquals(der.value, 127)
|
||||
|
||||
def testDecode2(self):
|
||||
# Multi-byte integer
|
||||
der = DerInteger()
|
||||
# Value 0x180L
|
||||
der.decode(b('\x02\x02\x01\x80'))
|
||||
self.assertEquals(der.value,0x180L)
|
||||
# One very long integer
|
||||
der.decode(
|
||||
b('\x02\x82\x01\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00')+
|
||||
b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+
|
||||
b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+
|
||||
b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+
|
||||
b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+
|
||||
b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+
|
||||
b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+
|
||||
b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+
|
||||
b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+
|
||||
b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+
|
||||
b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+
|
||||
b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+
|
||||
b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+
|
||||
b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+
|
||||
b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+
|
||||
b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+
|
||||
b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+
|
||||
b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+
|
||||
b('\x00\x00\x00\x00\x00\x00\x00\x00\x00'))
|
||||
self.assertEquals(der.value,2L**2048)
|
||||
|
||||
def testDecode3(self):
|
||||
# Negative integer
|
||||
der = DerInteger()
|
||||
# Value -1
|
||||
der.decode(b('\x02\x01\xFF'))
|
||||
self.assertEquals(der.value, -1)
|
||||
# Value -32768
|
||||
der.decode(b('\x02\x02\x80\x00'))
|
||||
self.assertEquals(der.value, -32768)
|
||||
|
||||
def testDecode5(self):
|
||||
# We still accept BER integer format
|
||||
der = DerInteger()
|
||||
# Redundant leading zeroes
|
||||
der.decode(b('\x02\x02\x00\x01'))
|
||||
self.assertEquals(der.value, 1)
|
||||
# Redundant leading 0xFF
|
||||
der.decode(b('\x02\x02\xFF\xFF'))
|
||||
self.assertEquals(der.value, -1)
|
||||
# Empty payload
|
||||
der.decode(b('\x02\x00'))
|
||||
self.assertEquals(der.value, 0)
|
||||
|
||||
def testErrDecode1(self):
|
||||
# Wide length field
|
||||
der = DerInteger()
|
||||
self.assertRaises(ValueError, der.decode, b('\x02\x81\x01\x01'))
|
||||
def testObjDecode2(self):
|
||||
# Decode short payload
|
||||
der = DerObject()
|
||||
der.decode(b('\x22\x81\x80' + "1"*128))
|
||||
self.assertEquals(der.payload, b("1")*128)
|
||||
self.assertEquals(der.typeTag, 0x22)
|
||||
|
||||
class DerSequenceTests(unittest.TestCase):
|
||||
|
||||
def testInit1(self):
|
||||
der = newDerSequence(1, DerInteger(2), '0\x00')
|
||||
self.assertEquals(der.encode(), b('0\x08\x02\x01\x01\x02\x01\x020\x00'))
|
||||
def testEncode1(self):
|
||||
# Empty sequence
|
||||
der = DerSequence()
|
||||
self.assertEquals(der.encode(), b('0\x00'))
|
||||
self.failIf(der.hasOnlyInts())
|
||||
# One single-byte integer (zero)
|
||||
der.append(0)
|
||||
self.assertEquals(der.encode(), b('0\x03\x02\x01\x00'))
|
||||
self.failUnless(der.hasOnlyInts())
|
||||
# Invariant
|
||||
self.assertEquals(der.encode(), b('0\x03\x02\x01\x00'))
|
||||
|
||||
def testEncode1(self):
|
||||
# Empty sequence
|
||||
der = DerSequence()
|
||||
self.assertEquals(der.encode(), b('0\x00'))
|
||||
self.failIf(der.hasOnlyInts())
|
||||
# One single-byte integer (zero)
|
||||
der.append(0)
|
||||
self.assertEquals(der.encode(), b('0\x03\x02\x01\x00'))
|
||||
self.assertEquals(der.hasInts(),1)
|
||||
self.assertEquals(der.hasInts(False),1)
|
||||
self.failUnless(der.hasOnlyInts())
|
||||
self.failUnless(der.hasOnlyInts(False))
|
||||
# Invariant
|
||||
self.assertEquals(der.encode(), b('0\x03\x02\x01\x00'))
|
||||
|
||||
def testEncode2(self):
|
||||
# Indexing
|
||||
der = DerSequence()
|
||||
der.append(0)
|
||||
der[0] = 1
|
||||
self.assertEquals(len(der),1)
|
||||
self.assertEquals(der[0],1)
|
||||
self.assertEquals(der[-1],1)
|
||||
self.assertEquals(der.encode(), b('0\x03\x02\x01\x01'))
|
||||
#
|
||||
der[:] = [1]
|
||||
self.assertEquals(len(der),1)
|
||||
self.assertEquals(der[0],1)
|
||||
self.assertEquals(der.encode(), b('0\x03\x02\x01\x01'))
|
||||
|
||||
def testEncode3(self):
|
||||
# One multi-byte integer (non-zero)
|
||||
der = DerSequence()
|
||||
der.append(0x180L)
|
||||
self.assertEquals(der.encode(), b('0\x04\x02\x02\x01\x80'))
|
||||
|
||||
def testEncode4(self):
|
||||
# One very long integer
|
||||
der = DerSequence()
|
||||
der.append(2L**2048)
|
||||
self.assertEquals(der.encode(), b('0\x82\x01\x05')+
|
||||
b('\x02\x82\x01\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00')+
|
||||
def testEncode2(self):
|
||||
# One single-byte integer (non-zero)
|
||||
der = DerSequence()
|
||||
der.append(127)
|
||||
self.assertEquals(der.encode(), b('0\x03\x02\x01\x7f'))
|
||||
# Indexing
|
||||
der[0] = 1
|
||||
self.assertEquals(len(der),1)
|
||||
self.assertEquals(der[0],1)
|
||||
self.assertEquals(der[-1],1)
|
||||
self.assertEquals(der.encode(), b('0\x03\x02\x01\x01'))
|
||||
#
|
||||
der[:] = [1]
|
||||
self.assertEquals(len(der),1)
|
||||
self.assertEquals(der[0],1)
|
||||
self.assertEquals(der.encode(), b('0\x03\x02\x01\x01'))
|
||||
|
||||
def testEncode3(self):
|
||||
# One multi-byte integer (non-zero)
|
||||
der = DerSequence()
|
||||
der.append(0x180L)
|
||||
self.assertEquals(der.encode(), b('0\x04\x02\x02\x01\x80'))
|
||||
|
||||
def testEncode4(self):
|
||||
# One very long integer
|
||||
der = DerSequence()
|
||||
der.append(2**2048)
|
||||
self.assertEquals(der.encode(), b('0\x82\x01\x05')+
|
||||
b('\x02\x82\x01\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00')+
|
||||
b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+
|
||||
b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+
|
||||
b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+
|
||||
b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+
|
||||
b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+
|
||||
b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+
|
||||
b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+
|
||||
b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+
|
||||
b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+
|
||||
b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+
|
||||
b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+
|
||||
b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+
|
||||
b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+
|
||||
b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+
|
||||
b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+
|
||||
b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+
|
||||
b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+
|
||||
b('\x00\x00\x00\x00\x00\x00\x00\x00\x00'))
|
||||
|
||||
def testEncode5(self):
|
||||
# One single-byte integer (looks negative)
|
||||
der = DerSequence()
|
||||
der.append(0xFFL)
|
||||
self.assertEquals(der.encode(), b('0\x04\x02\x02\x00\xff'))
|
||||
|
||||
def testEncode6(self):
|
||||
# Two integers
|
||||
der = DerSequence()
|
||||
der.append(0x180L)
|
||||
der.append(0xFFL)
|
||||
self.assertEquals(der.encode(), b('0\x08\x02\x02\x01\x80\x02\x02\x00\xff'))
|
||||
self.failUnless(der.hasOnlyInts())
|
||||
#
|
||||
der.append(0x01)
|
||||
der[1:] = [9,8]
|
||||
self.assertEquals(len(der),3)
|
||||
self.assertEqual(der[1:],[9,8])
|
||||
self.assertEqual(der[1:-1],[9])
|
||||
self.assertEquals(der.encode(), b('0\x0A\x02\x02\x01\x80\x02\x01\x09\x02\x01\x08'))
|
||||
|
||||
def testEncode6(self):
|
||||
# One integer and another type (no matter what it is)
|
||||
der = DerSequence()
|
||||
der.append(0x180L)
|
||||
der.append(b('\x00\x02\x00\x00'))
|
||||
self.assertEquals(der.encode(), b('0\x08\x02\x02\x01\x80\x00\x02\x00\x00'))
|
||||
self.failIf(der.hasOnlyInts())
|
||||
|
||||
####
|
||||
|
||||
def testDecode1(self):
|
||||
# Empty sequence
|
||||
der = DerSequence()
|
||||
der.decode(b('0\x00'))
|
||||
self.assertEquals(len(der),0)
|
||||
# One single-byte integer (zero)
|
||||
der.decode(b('0\x03\x02\x01\x00'))
|
||||
self.assertEquals(len(der),1)
|
||||
self.assertEquals(der[0],0)
|
||||
# Invariant
|
||||
der.decode(b('0\x03\x02\x01\x00'))
|
||||
self.assertEquals(len(der),1)
|
||||
self.assertEquals(der[0],0)
|
||||
|
||||
def testDecode2(self):
|
||||
# One single-byte integer (non-zero)
|
||||
der = DerSequence()
|
||||
der.decode(b('0\x03\x02\x01\x7f'))
|
||||
self.assertEquals(len(der),1)
|
||||
self.assertEquals(der[0],127)
|
||||
|
||||
def testDecode3(self):
|
||||
# One multi-byte integer (non-zero)
|
||||
der = DerSequence()
|
||||
der.decode(b('0\x04\x02\x02\x01\x80'))
|
||||
self.assertEquals(len(der),1)
|
||||
self.assertEquals(der[0],0x180L)
|
||||
|
||||
def testDecode4(self):
|
||||
# One very long integer
|
||||
der = DerSequence()
|
||||
der.decode(b('0\x82\x01\x05')+
|
||||
b('\x02\x82\x01\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00')+
|
||||
b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+
|
||||
b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+
|
||||
b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+
|
||||
b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+
|
||||
b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+
|
||||
b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+
|
||||
b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+
|
||||
b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+
|
||||
b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+
|
||||
b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+
|
||||
b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+
|
||||
b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+
|
||||
b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+
|
||||
b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+
|
||||
b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+
|
||||
b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+
|
||||
b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+
|
||||
b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+
|
||||
b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+
|
||||
b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+
|
||||
b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+
|
||||
b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+
|
||||
b('\x00\x00\x00\x00\x00\x00\x00\x00\x00'))
|
||||
b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+
|
||||
b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+
|
||||
b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+
|
||||
b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+
|
||||
b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+
|
||||
b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+
|
||||
b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+
|
||||
b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+
|
||||
b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+
|
||||
b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+
|
||||
b('\x00\x00\x00\x00\x00\x00\x00\x00\x00'))
|
||||
self.assertEquals(len(der),1)
|
||||
self.assertEquals(der[0],2**2048)
|
||||
|
||||
def testEncode5(self):
|
||||
der = DerSequence()
|
||||
der += 1
|
||||
der += b('\x30\x00')
|
||||
self.assertEquals(der.encode(), b('\x30\x05\x02\x01\x01\x30\x00'))
|
||||
def testDecode5(self):
|
||||
# One single-byte integer (looks negative)
|
||||
der = DerSequence()
|
||||
der.decode(b('0\x04\x02\x02\x00\xff'))
|
||||
self.assertEquals(len(der),1)
|
||||
self.assertEquals(der[0],0xFFL)
|
||||
|
||||
def testEncode6(self):
|
||||
# Two positive integers
|
||||
der = DerSequence()
|
||||
der.append(0x180L)
|
||||
der.append(0xFFL)
|
||||
self.assertEquals(der.encode(), b('0\x08\x02\x02\x01\x80\x02\x02\x00\xff'))
|
||||
self.failUnless(der.hasOnlyInts())
|
||||
self.failUnless(der.hasOnlyInts(False))
|
||||
# Two mixed integers
|
||||
der = DerSequence()
|
||||
der.append(2)
|
||||
der.append(-2)
|
||||
self.assertEquals(der.encode(), b('0\x06\x02\x01\x02\x02\x01\xFE'))
|
||||
self.assertEquals(der.hasInts(), 1)
|
||||
self.assertEquals(der.hasInts(False), 2)
|
||||
self.failIf(der.hasOnlyInts())
|
||||
self.failUnless(der.hasOnlyInts(False))
|
||||
#
|
||||
der.append(0x01)
|
||||
der[1:] = [9,8]
|
||||
self.assertEquals(len(der),3)
|
||||
self.assertEqual(der[1:],[9,8])
|
||||
self.assertEqual(der[1:-1],[9])
|
||||
self.assertEquals(der.encode(), b('0\x09\x02\x01\x02\x02\x01\x09\x02\x01\x08'))
|
||||
def testDecode6(self):
|
||||
# Two integers
|
||||
der = DerSequence()
|
||||
der.decode(b('0\x08\x02\x02\x01\x80\x02\x02\x00\xff'))
|
||||
self.assertEquals(len(der),2)
|
||||
self.assertEquals(der[0],0x180L)
|
||||
self.assertEquals(der[1],0xFFL)
|
||||
|
||||
def testEncode7(self):
|
||||
# One integer and another type (no matter what it is)
|
||||
der = DerSequence()
|
||||
der.append(0x180L)
|
||||
der.append(b('\x00\x02\x00\x00'))
|
||||
self.assertEquals(der.encode(), b('0\x08\x02\x02\x01\x80\x00\x02\x00\x00'))
|
||||
self.failIf(der.hasOnlyInts())
|
||||
def testDecode7(self):
|
||||
# One integer and 2 other types
|
||||
der = DerSequence()
|
||||
der.decode(b('0\x0A\x02\x02\x01\x80\x24\x02\xb6\x63\x12\x00'))
|
||||
self.assertEquals(len(der),3)
|
||||
self.assertEquals(der[0],0x180L)
|
||||
self.assertEquals(der[1],b('\x24\x02\xb6\x63'))
|
||||
self.assertEquals(der[2],b('\x12\x00'))
|
||||
|
||||
####
|
||||
def testDecode8(self):
|
||||
# Only 2 other types
|
||||
der = DerSequence()
|
||||
der.decode(b('0\x06\x24\x02\xb6\x63\x12\x00'))
|
||||
self.assertEquals(len(der),2)
|
||||
self.assertEquals(der[0],b('\x24\x02\xb6\x63'))
|
||||
self.assertEquals(der[1],b('\x12\x00'))
|
||||
|
||||
def testDecode1(self):
|
||||
# Empty sequence
|
||||
der = DerSequence()
|
||||
der.decode(b('0\x00'))
|
||||
self.assertEquals(len(der),0)
|
||||
# One single-byte integer (zero)
|
||||
der.decode(b('0\x03\x02\x01\x00'))
|
||||
self.assertEquals(len(der),1)
|
||||
self.assertEquals(der[0],0)
|
||||
# Invariant
|
||||
der.decode(b('0\x03\x02\x01\x00'))
|
||||
self.assertEquals(len(der),1)
|
||||
self.assertEquals(der[0],0)
|
||||
def testErrDecode1(self):
|
||||
# Not a sequence
|
||||
der = DerSequence()
|
||||
self.assertRaises(ValueError, der.decode, b(''))
|
||||
self.assertRaises(ValueError, der.decode, b('\x00'))
|
||||
self.assertRaises(ValueError, der.decode, b('\x30'))
|
||||
|
||||
def testDecode2(self):
|
||||
# One single-byte integer (non-zero)
|
||||
der = DerSequence()
|
||||
der.decode(b('0\x03\x02\x01\x7f'))
|
||||
self.assertEquals(len(der),1)
|
||||
self.assertEquals(der[0],127)
|
||||
def testErrDecode2(self):
|
||||
# Wrong payload type
|
||||
der = DerSequence()
|
||||
self.assertRaises(ValueError, der.decode, b('\x30\x00\x00'), True)
|
||||
|
||||
def testDecode4(self):
|
||||
# One very long integer
|
||||
der = DerSequence()
|
||||
der.decode(b('0\x82\x01\x05')+
|
||||
b('\x02\x82\x01\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00')+
|
||||
b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+
|
||||
b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+
|
||||
b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+
|
||||
b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+
|
||||
b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+
|
||||
b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+
|
||||
b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+
|
||||
b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+
|
||||
b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+
|
||||
b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+
|
||||
b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+
|
||||
b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+
|
||||
b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+
|
||||
b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+
|
||||
b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+
|
||||
b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+
|
||||
b('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')+
|
||||
b('\x00\x00\x00\x00\x00\x00\x00\x00\x00'))
|
||||
self.assertEquals(len(der),1)
|
||||
self.assertEquals(der[0],2L**2048)
|
||||
def testErrDecode3(self):
|
||||
# Wrong length format
|
||||
der = DerSequence()
|
||||
self.assertRaises(ValueError, der.decode, b('\x30\x04\x02\x01\x01\x00'))
|
||||
self.assertRaises(ValueError, der.decode, b('\x30\x81\x03\x02\x01\x01'))
|
||||
self.assertRaises(ValueError, der.decode, b('\x30\x04\x02\x81\x01\x01'))
|
||||
|
||||
def testDecode6(self):
|
||||
# Two integers
|
||||
der = DerSequence()
|
||||
der.decode(b('0\x08\x02\x02\x01\x80\x02\x02\x00\xff'))
|
||||
self.assertEquals(len(der),2)
|
||||
self.assertEquals(der[0],0x180L)
|
||||
self.assertEquals(der[1],0xFFL)
|
||||
|
||||
def testDecode7(self):
|
||||
# One integer and 2 other types
|
||||
der = DerSequence()
|
||||
der.decode(b('0\x0A\x02\x02\x01\x80\x24\x02\xb6\x63\x12\x00'))
|
||||
self.assertEquals(len(der),3)
|
||||
self.assertEquals(der[0],0x180L)
|
||||
self.assertEquals(der[1],b('\x24\x02\xb6\x63'))
|
||||
self.assertEquals(der[2],b('\x12\x00'))
|
||||
|
||||
def testDecode8(self):
|
||||
# Only 2 other types
|
||||
der = DerSequence()
|
||||
der.decode(b('0\x06\x24\x02\xb6\x63\x12\x00'))
|
||||
self.assertEquals(len(der),2)
|
||||
self.assertEquals(der[0],b('\x24\x02\xb6\x63'))
|
||||
self.assertEquals(der[1],b('\x12\x00'))
|
||||
self.assertEquals(der.hasInts(), 0)
|
||||
self.assertEquals(der.hasInts(False), 0)
|
||||
self.failIf(der.hasOnlyInts())
|
||||
self.failIf(der.hasOnlyInts(False))
|
||||
|
||||
def testErrDecode1(self):
|
||||
# Not a sequence
|
||||
der = DerSequence()
|
||||
self.assertRaises(EOFError, der.decode, b(''))
|
||||
self.assertRaises(ValueError, der.decode, b('\x00'))
|
||||
self.assertRaises(EOFError, der.decode, b('\x30'))
|
||||
|
||||
def testErrDecode2(self):
|
||||
der = DerSequence()
|
||||
# Too much data
|
||||
self.assertRaises(ValueError, der.decode, b('\x30\x00\x00'))
|
||||
|
||||
def testErrDecode3(self):
|
||||
# Wrong length format
|
||||
der = DerSequence()
|
||||
# Missing length in sub-item
|
||||
self.assertRaises(EOFError, der.decode, b('\x30\x04\x02\x01\x01\x00'))
|
||||
# Valid BER, but invalid DER length
|
||||
self.assertRaises(ValueError, der.decode, b('\x30\x81\x03\x02\x01\x01'))
|
||||
self.assertRaises(ValueError, der.decode, b('\x30\x04\x02\x81\x01\x01'))
|
||||
|
||||
class DerOctetStringTests(unittest.TestCase):
|
||||
|
||||
def testInit1(self):
|
||||
der = newDerOctetString(b('\xFF'))
|
||||
self.assertEquals(der.encode(), b('\x04\x01\xFF'))
|
||||
|
||||
def testEncode1(self):
|
||||
# Empty sequence
|
||||
der = DerOctetString()
|
||||
self.assertEquals(der.encode(), b('\x04\x00'))
|
||||
# Small payload
|
||||
der.payload = b('\x01\x02')
|
||||
self.assertEquals(der.encode(), b('\x04\x02\x01\x02'))
|
||||
|
||||
####
|
||||
|
||||
def testDecode1(self):
|
||||
# Empty sequence
|
||||
der = DerOctetString()
|
||||
der.decode(b('\x04\x00'))
|
||||
self.assertEquals(der.payload, b(''))
|
||||
# Small payload
|
||||
der.decode(b('\x04\x02\x01\x02'))
|
||||
self.assertEquals(der.payload, b('\x01\x02'))
|
||||
|
||||
def testErrDecode1(self):
|
||||
# No leftovers allowed
|
||||
der = DerOctetString()
|
||||
self.assertRaises(ValueError, der.decode, b('\x04\x01\x01\xff'))
|
||||
|
||||
class DerNullTests(unittest.TestCase):
|
||||
|
||||
def testEncode1(self):
|
||||
der = DerNull()
|
||||
self.assertEquals(der.encode(), b('\x05\x00'))
|
||||
|
||||
####
|
||||
|
||||
def testDecode1(self):
|
||||
# Empty sequence
|
||||
der = DerNull()
|
||||
der.decode(b('\x05\x00'))
|
||||
|
||||
class DerObjectIdTests(unittest.TestCase):
|
||||
|
||||
def testInit1(self):
|
||||
der = newDerObjectId("1.1")
|
||||
self.assertEquals(der.encode(), b('\x06\x01)'))
|
||||
|
||||
def testEncode1(self):
|
||||
der = DerObjectId('1.2.840.113549.1.1.1')
|
||||
self.assertEquals(der.encode(), b('\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x01'))
|
||||
#
|
||||
der = DerObjectId()
|
||||
der.value = '1.2.840.113549.1.1.1'
|
||||
self.assertEquals(der.encode(), b('\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x01'))
|
||||
|
||||
####
|
||||
|
||||
def testDecode1(self):
|
||||
# Empty sequence
|
||||
der = DerObjectId()
|
||||
der.decode(b('\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x01'))
|
||||
self.assertEquals(der.value, '1.2.840.113549.1.1.1')
|
||||
|
||||
class DerBitStringTests(unittest.TestCase):
|
||||
|
||||
def testInit1(self):
|
||||
der = newDerBitString(b("\xFF"))
|
||||
self.assertEquals(der.encode(), b('\x03\x02\x00\xFF'))
|
||||
|
||||
def testEncode1(self):
|
||||
# Empty sequence
|
||||
der = DerBitString()
|
||||
self.assertEquals(der.encode(), b('\x03\x01\x00'))
|
||||
# Small payload
|
||||
der = DerBitString(b('\x01\x02'))
|
||||
self.assertEquals(der.encode(), b('\x03\x03\x00\x01\x02'))
|
||||
# Small payload
|
||||
der = DerBitString()
|
||||
der.value = b('\x01\x02')
|
||||
self.assertEquals(der.encode(), b('\x03\x03\x00\x01\x02'))
|
||||
|
||||
####
|
||||
|
||||
def testDecode1(self):
|
||||
# Empty sequence
|
||||
der = DerBitString()
|
||||
der.decode(b('\x03\x00'))
|
||||
self.assertEquals(der.value, b(''))
|
||||
# Small payload
|
||||
der.decode(b('\x03\x03\x00\x01\x02'))
|
||||
self.assertEquals(der.value, b('\x01\x02'))
|
||||
|
||||
class DerSetOfTests(unittest.TestCase):
|
||||
|
||||
def testInit1(self):
|
||||
der = newDerSetOf(DerInteger(1), DerInteger(2))
|
||||
self.assertEquals(der.encode(), b('1\x06\x02\x01\x01\x02\x01\x02'))
|
||||
|
||||
def testEncode1(self):
|
||||
# Empty set
|
||||
der = DerSetOf()
|
||||
self.assertEquals(der.encode(), b('1\x00'))
|
||||
# One single-byte integer (zero)
|
||||
der.add(0)
|
||||
self.assertEquals(der.encode(), b('1\x03\x02\x01\x00'))
|
||||
# Invariant
|
||||
self.assertEquals(der.encode(), b('1\x03\x02\x01\x00'))
|
||||
|
||||
def testEncode2(self):
|
||||
# Two integers
|
||||
der = DerSetOf()
|
||||
der.add(0x180L)
|
||||
der.add(0xFFL)
|
||||
self.assertEquals(der.encode(), b('1\x08\x02\x02\x00\xff\x02\x02\x01\x80'))
|
||||
# Initialize with integers
|
||||
der = DerSetOf([0x180L, 0xFFL])
|
||||
self.assertEquals(der.encode(), b('1\x08\x02\x02\x00\xff\x02\x02\x01\x80'))
|
||||
|
||||
def testEncode3(self):
|
||||
# One integer and another type (no matter what it is)
|
||||
der = DerSetOf()
|
||||
der.add(0x180L)
|
||||
self.assertRaises(ValueError, der.add, b('\x00\x02\x00\x00'))
|
||||
|
||||
def testEncode4(self):
|
||||
# Only non integers
|
||||
der = DerSetOf()
|
||||
der.add(b('\x01\x00'))
|
||||
der.add(b('\x01\x01\x01'))
|
||||
self.assertEquals(der.encode(), b('1\x05\x01\x00\x01\x01\x01'))
|
||||
|
||||
####
|
||||
|
||||
def testDecode1(self):
|
||||
# Empty sequence
|
||||
der = DerSetOf()
|
||||
der.decode(b('1\x00'))
|
||||
self.assertEquals(len(der),0)
|
||||
# One single-byte integer (zero)
|
||||
der.decode(b('1\x03\x02\x01\x00'))
|
||||
self.assertEquals(len(der),1)
|
||||
self.assertEquals(list(der),[0])
|
||||
|
||||
def testDecode2(self):
|
||||
# Two integers
|
||||
der = DerSetOf()
|
||||
der.decode(b('1\x08\x02\x02\x01\x80\x02\x02\x00\xff'))
|
||||
self.assertEquals(len(der),2)
|
||||
l = list(der)
|
||||
self.failUnless(0x180 in l)
|
||||
self.failUnless(0xFF in l)
|
||||
|
||||
def testDecode3(self):
|
||||
# One integer and 2 other types
|
||||
der = DerSetOf()
|
||||
#import pdb; pdb.set_trace()
|
||||
self.assertRaises(ValueError, der.decode,
|
||||
b('0\x0A\x02\x02\x01\x80\x24\x02\xb6\x63\x12\x00'))
|
||||
|
||||
def testErrDecode1(self):
|
||||
# No leftovers allowed
|
||||
der = DerSetOf()
|
||||
self.assertRaises(ValueError, der.decode,
|
||||
b('1\x08\x02\x02\x01\x80\x02\x02\x00\xff\xAA'))
|
||||
def testErrDecode4(self):
|
||||
# Wrong integer format
|
||||
der = DerSequence()
|
||||
# Multi-byte encoding for zero
|
||||
#self.assertRaises(ValueError, der.decode, '\x30\x04\x02\x02\x00\x00')
|
||||
# Negative integer
|
||||
self.assertRaises(ValueError, der.decode, b('\x30\x04\x02\x01\xFF'))
|
||||
|
||||
def get_tests(config={}):
|
||||
from Crypto.SelfTest.st_common import list_test_cases
|
||||
listTests = []
|
||||
listTests += list_test_cases(DerObjectTests)
|
||||
listTests += list_test_cases(DerIntegerTests)
|
||||
listTests += list_test_cases(DerSequenceTests)
|
||||
listTests += list_test_cases(DerOctetStringTests)
|
||||
listTests += list_test_cases(DerNullTests)
|
||||
listTests += list_test_cases(DerObjectIdTests)
|
||||
listTests += list_test_cases(DerBitStringTests)
|
||||
listTests += list_test_cases(DerSetOfTests)
|
||||
return listTests
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
||||
@@ -32,9 +32,6 @@ if sys.version_info[0] == 2 and sys.version_info[1] == 1:
|
||||
|
||||
import unittest
|
||||
|
||||
class MyError(Exception):
|
||||
"""Dummy exception used for tests"""
|
||||
|
||||
# NB: In some places, we compare tuples instead of just output values so that
|
||||
# if any inputs cause a test failure, we'll be able to tell which ones.
|
||||
|
||||
@@ -279,11 +276,6 @@ class MiscTests(unittest.TestCase):
|
||||
self.assertEqual(number.size(0xa2ba40),8*3)
|
||||
self.assertEqual(number.size(0xa2ba40ee07e3b2bd2f02ce227f36a195024486e49c19cb41bbbdfbba98b22b0e577c2eeaffa20d883a76e65e394c69d4b3c05a1e8fadda27edb2a42bc000fe888b9b32c22d15add0cd76b3e7936e19955b220dd17d4ea904b1ec102b2e4de7751222aa99151024c7cb41cc5ea21d00eeb41f7c800834d2c6e06bce3bce7ea9a5L), 1024)
|
||||
|
||||
class FastmathTests(unittest.TestCase):
|
||||
def setUp(self):
|
||||
global number
|
||||
from Crypto.Util import number
|
||||
|
||||
def test_negative_number_roundtrip_mpzToLongObj_longObjToMPZ(self):
|
||||
"""Test that mpzToLongObj and longObjToMPZ (internal functions) roundtrip negative numbers correctly."""
|
||||
n = -100000000000000000000000000000000000L
|
||||
@@ -292,49 +284,9 @@ class FastmathTests(unittest.TestCase):
|
||||
self.assertEqual(n, k.n)
|
||||
self.assertEqual(e, k.e)
|
||||
|
||||
def test_isPrime_randfunc_exception(self):
|
||||
"""Test that when isPrime is called, an exception raised in randfunc is propagated."""
|
||||
def randfunc(n):
|
||||
raise MyError
|
||||
prime = 3536384141L # Needs to be large enough so that rabinMillerTest will be invoked
|
||||
self.assertRaises(MyError, number._fastmath.isPrime, prime, randfunc=randfunc)
|
||||
|
||||
def test_getStrongPrime_randfunc_exception(self):
|
||||
"""Test that when getStrongPrime is called, an exception raised in randfunc is propagated."""
|
||||
def randfunc(n):
|
||||
raise MyError
|
||||
self.assertRaises(MyError, number._fastmath.getStrongPrime, 512, randfunc=randfunc)
|
||||
|
||||
def test_isPrime_randfunc_bogus(self):
|
||||
"""Test that when isPrime is called, an exception is raised if randfunc returns something bogus."""
|
||||
def randfunc(n):
|
||||
return None
|
||||
prime = 3536384141L # Needs to be large enough so that rabinMillerTest will be invoked
|
||||
self.assertRaises(TypeError, number._fastmath.isPrime, prime, randfunc=randfunc)
|
||||
|
||||
def test_getStrongPrime_randfunc_bogus(self):
|
||||
"""Test that when getStrongPrime is called, an exception is raised if randfunc returns something bogus."""
|
||||
def randfunc(n):
|
||||
return None
|
||||
self.assertRaises(TypeError, number._fastmath.getStrongPrime, 512, randfunc=randfunc)
|
||||
|
||||
def get_tests(config={}):
|
||||
from Crypto.SelfTest.st_common import list_test_cases
|
||||
tests = list_test_cases(MiscTests)
|
||||
try:
|
||||
from Crypto.PublicKey import _fastmath
|
||||
tests += list_test_cases(FastmathTests)
|
||||
except ImportError:
|
||||
from distutils.sysconfig import get_config_var
|
||||
import inspect, os.path
|
||||
_fm_path = os.path.normpath(os.path.dirname(os.path.abspath(
|
||||
inspect.getfile(inspect.currentframe())))
|
||||
+"/../../PublicKey/_fastmath"+get_config_var("SO"))
|
||||
if os.path.exists(_fm_path):
|
||||
raise ImportError("While the _fastmath module exists, importing "+
|
||||
"it failed. This may point to the gmp or mpir shared library "+
|
||||
"not being in the path. _fastmath was found at "+_fm_path)
|
||||
return tests
|
||||
return list_test_cases(MiscTests)
|
||||
|
||||
if __name__ == '__main__':
|
||||
suite = lambda: unittest.TestSuite(get_tests())
|
||||
|
||||
@@ -66,13 +66,11 @@ def run(module=None, verbosity=0, stream=None, tests=None, config=None, **kwargs
|
||||
raise ValueError("'module' and 'tests' arguments are mutually exclusive")
|
||||
if stream is None:
|
||||
kwargs['stream'] = StringIO()
|
||||
else:
|
||||
kwargs['stream'] = stream
|
||||
runner = unittest.TextTestRunner(verbosity=verbosity, **kwargs)
|
||||
result = runner.run(suite)
|
||||
if not result.wasSuccessful():
|
||||
if stream is None:
|
||||
sys.stderr.write(kwargs['stream'].getvalue())
|
||||
sys.stderr.write(stream.getvalue())
|
||||
raise SelfTestError("Self-test failed", result)
|
||||
return result
|
||||
|
||||
@@ -85,7 +83,6 @@ def get_tests(config={}):
|
||||
from Crypto.SelfTest import Random; tests += Random.get_tests(config=config)
|
||||
from Crypto.SelfTest import Util; tests += Util.get_tests(config=config)
|
||||
from Crypto.SelfTest import Signature; tests += Signature.get_tests(config=config)
|
||||
from Crypto.SelfTest import IO; tests += IO.get_tests(config=config)
|
||||
return tests
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
||||
@@ -30,22 +30,22 @@ For example, a sender may authenticate a message using SHA-1 and PSS like
|
||||
this:
|
||||
|
||||
>>> from Crypto.Signature import PKCS1_PSS
|
||||
>>> from Crypto.Hash import SHA1
|
||||
>>> from Crypto.PublicKey import RSA1
|
||||
>>> from Crypto.Hash import SHA
|
||||
>>> from Crypto.PublicKey import RSA
|
||||
>>> from Crypto import Random
|
||||
>>>
|
||||
>>> message = 'To be signed'
|
||||
>>> key = RSA.importKey(open('privkey.der').read())
|
||||
>>> h = SHA1.new()
|
||||
>>> h = SHA.new()
|
||||
>>> h.update(message)
|
||||
>>> signer = PKCS1_PSS.new(key)
|
||||
>>> signature = signer.sign(key)
|
||||
>>> signature = PKCS1_PSS.sign(key)
|
||||
|
||||
At the receiver side, verification can be done like using the public part of
|
||||
the RSA key:
|
||||
|
||||
>>> key = RSA.importKey(open('pubkey.der').read())
|
||||
>>> h = SHA1.new()
|
||||
>>> h = SHA.new()
|
||||
>>> h.update(message)
|
||||
>>> verifier = PKCS1_PSS.new(key)
|
||||
>>> if verifier.verify(h, signature):
|
||||
@@ -72,7 +72,6 @@ if sys.version_info[0] == 2 and sys.version_info[1] == 1:
|
||||
import Crypto.Util.number
|
||||
from Crypto.Util.number import ceil_shift, ceil_div, long_to_bytes
|
||||
from Crypto.Util.strxor import strxor
|
||||
from Crypto.Hash import new as Hash_new
|
||||
|
||||
class PSS_SigScheme:
|
||||
"""This signature scheme can perform PKCS#1 PSS RSA signature or verification."""
|
||||
@@ -204,11 +203,7 @@ def MGF1(mgfSeed, maskLen, hash):
|
||||
T = b("")
|
||||
for counter in xrange(ceil_div(maskLen, hash.digest_size)):
|
||||
c = long_to_bytes(counter, 4)
|
||||
try:
|
||||
T = T + hash.new(mgfSeed + c).digest()
|
||||
except AttributeError:
|
||||
# hash object doesn't have a "new" method. Use Crypto.Hash.new() to instantiate it
|
||||
T = T + Hash_new(hash, mgfSeed + c).digest()
|
||||
T = T + hash.new(mgfSeed + c).digest()
|
||||
assert(len(T)>=maskLen)
|
||||
return T[:maskLen]
|
||||
|
||||
@@ -258,11 +253,7 @@ def EMSA_PSS_ENCODE(mhash, emBits, randFunc, mgf, sLen):
|
||||
if randFunc and sLen>0:
|
||||
salt = randFunc(sLen)
|
||||
# Step 5 and 6
|
||||
try:
|
||||
h = mhash.new(bchr(0x00)*8 + mhash.digest() + salt)
|
||||
except AttributeError:
|
||||
# hash object doesn't have a "new" method. Use Crypto.Hash.new() to instantiate it
|
||||
h = Hash_new(mhash, bchr(0x00)*8 + mhash.digest() + salt)
|
||||
h = mhash.new(bchr(0x00)*8 + mhash.digest() + salt)
|
||||
# Step 7 and 8
|
||||
db = bchr(0x00)*(emLen-sLen-mhash.digest_size-2) + bchr(0x01) + salt
|
||||
# Step 9
|
||||
@@ -337,11 +328,7 @@ def EMSA_PSS_VERIFY(mhash, em, emBits, mgf, sLen):
|
||||
salt = b("")
|
||||
if sLen: salt = db[-sLen:]
|
||||
# Step 12 and 13
|
||||
try:
|
||||
hp = mhash.new(bchr(0x00)*8 + mhash.digest() + salt).digest()
|
||||
except AttributeError:
|
||||
# hash object doesn't have a "new" method. Use Crypto.Hash.new() to instantiate it
|
||||
hp = Hash_new(mhash, bchr(0x00)*8 + mhash.digest() + salt).digest()
|
||||
hp = mhash.new(bchr(0x00)*8 + mhash.digest() + salt).digest()
|
||||
# Step 14
|
||||
if h!=hp:
|
||||
return False
|
||||
|
||||
@@ -60,13 +60,9 @@ the RSA key:
|
||||
__revision__ = "$Id$"
|
||||
__all__ = [ 'new', 'PKCS115_SigScheme' ]
|
||||
|
||||
import sys
|
||||
|
||||
import Crypto.Util.number
|
||||
from Crypto.Util.number import ceil_div
|
||||
from Crypto.Util.asn1 import DerSequence, DerNull, DerOctetString, DerObjectId
|
||||
if sys.version_info[0] == 2 and sys.version_info[1] == 1:
|
||||
from Crypto.Util.py21compat import *
|
||||
from Crypto.Util.asn1 import DerSequence, DerNull, DerOctetString
|
||||
from Crypto.Util.py3compat import *
|
||||
|
||||
class PKCS115_SigScheme:
|
||||
@@ -154,13 +150,7 @@ class PKCS115_SigScheme:
|
||||
em1 = bchr(0x00)*(k-len(m)) + m
|
||||
# Step 3
|
||||
try:
|
||||
em2_with_params = EMSA_PKCS1_V1_5_ENCODE(mhash, k, True)
|
||||
# MD hashes always require NULL params in AlgorithmIdentifier.
|
||||
# For all others, it is optional.
|
||||
if _HASH_OIDS[mhash.name].startswith('1.2.840.113549.2.'): # MD2/MD4/MD5
|
||||
em2_without_params = em2_with_params
|
||||
else:
|
||||
em2_without_params = EMSA_PKCS1_V1_5_ENCODE(mhash, k, False)
|
||||
em2 = EMSA_PKCS1_V1_5_ENCODE(mhash, k)
|
||||
except ValueError:
|
||||
return 0
|
||||
# Step 4
|
||||
@@ -168,9 +158,9 @@ class PKCS115_SigScheme:
|
||||
# of its components one at a time) we avoid attacks to the padding
|
||||
# scheme like Bleichenbacher's (see http://www.mail-archive.com/cryptography@metzdowd.com/msg06537).
|
||||
#
|
||||
return em1==em2_with_params or em1==em2_without_params
|
||||
return em1==em2
|
||||
|
||||
def EMSA_PKCS1_V1_5_ENCODE(hash, emLen, with_hash_parameters=True):
|
||||
def EMSA_PKCS1_V1_5_ENCODE(hash, emLen):
|
||||
"""
|
||||
Implement the ``EMSA-PKCS1-V1_5-ENCODE`` function, as defined
|
||||
in PKCS#1 v2.1 (RFC3447, 9.2).
|
||||
@@ -184,9 +174,6 @@ def EMSA_PKCS1_V1_5_ENCODE(hash, emLen, with_hash_parameters=True):
|
||||
The hash object that holds the digest of the message being signed.
|
||||
emLen : int
|
||||
The length the final encoding must have, in bytes.
|
||||
with_hash_parameters:
|
||||
If True (default), include NULL parameters for the hash
|
||||
algorithm in the ``digestAlgorithm`` SEQUENCE.
|
||||
|
||||
:attention: the early standard (RFC2313) stated that ``DigestInfo``
|
||||
had to be BER-encoded. This means that old signatures
|
||||
@@ -194,6 +181,11 @@ def EMSA_PKCS1_V1_5_ENCODE(hash, emLen, with_hash_parameters=True):
|
||||
is not supported in DER. Such encoding cannot be
|
||||
reproduced by this function.
|
||||
|
||||
:attention: the same standard defined ``DigestAlgorithm`` to be
|
||||
of ``AlgorithmIdentifier`` type, where the PARAMETERS
|
||||
item is optional. Encodings for ``MD2/4/5`` without
|
||||
``PARAMETERS`` cannot be reproduced by this function.
|
||||
|
||||
:Return: An ``emLen`` byte long string that encodes the hash.
|
||||
"""
|
||||
|
||||
@@ -216,19 +208,7 @@ def EMSA_PKCS1_V1_5_ENCODE(hash, emLen, with_hash_parameters=True):
|
||||
# { OID id-sha512 PARAMETERS NULL }
|
||||
# }
|
||||
#
|
||||
# Appendix B.1 also says that for SHA-1/-2 algorithms, the parameters
|
||||
# should be omitted. They may be present, but when they are, they shall
|
||||
# have NULL value.
|
||||
|
||||
if with_hash_parameters:
|
||||
digestAlgo = DerSequence([
|
||||
DerObjectId(_HASH_OIDS[hash.name]).encode(),
|
||||
DerNull().encode()
|
||||
])
|
||||
else:
|
||||
digestAlgo = DerSequence([
|
||||
DerObjectId(_HASH_OIDS[hash.name]).encode(),
|
||||
])
|
||||
digestAlgo = DerSequence([hash.oid, DerNull().encode()])
|
||||
digest = DerOctetString(hash.digest())
|
||||
digestInfo = DerSequence([
|
||||
digestAlgo.encode(),
|
||||
@@ -238,7 +218,7 @@ def EMSA_PKCS1_V1_5_ENCODE(hash, emLen, with_hash_parameters=True):
|
||||
# We need at least 11 bytes for the remaining data: 3 fixed bytes and
|
||||
# at least 8 bytes of padding).
|
||||
if emLen<len(digestInfo)+11:
|
||||
raise TypeError("Selected hash algorith has a too long digest (%d bytes)." % len(digest))
|
||||
raise ValueError("Selected hash algorith has a too long digest (%d bytes)." % len(digest))
|
||||
PS = bchr(0xFF) * (emLen - len(digestInfo) - 3)
|
||||
return b("\x00\x01") + PS + bchr(0x00) + digestInfo
|
||||
|
||||
@@ -254,75 +234,3 @@ def new(key):
|
||||
"""
|
||||
return PKCS115_SigScheme(key)
|
||||
|
||||
# AlgorithmIdentifier OIDs for use with PKCS#1 v1.5.
|
||||
#
|
||||
# These map names to the associated OIDs. We should try to be compatible
|
||||
# with the standard library's hashlib modules, where possible.
|
||||
#
|
||||
# XXX - These will probably be moved somewhere else soon.
|
||||
_HASH_OIDS = {
|
||||
#: id-md2 OBJECT IDENTIFIER ::= {
|
||||
#: iso(1) member-body(2) us(840) rsadsi(113549)
|
||||
#: digestAlgorithm(2) 2
|
||||
#: }
|
||||
"MD2": "1.2.840.113549.2.2",
|
||||
"md2": "1.2.840.113549.2.2",
|
||||
|
||||
#: id-md4 OBJECT IDENTIFIER ::= {
|
||||
#: iso(1) member-body(2) us(840) rsadsi(113549)
|
||||
#: digestAlgorithm(2) 4
|
||||
#: }
|
||||
"MD4": "1.2.840.113549.2.4",
|
||||
"md4": "1.2.840.113549.2.4",
|
||||
|
||||
#: id-md5 OBJECT IDENTIFIER ::= {
|
||||
#: iso(1) member-body(2) us(840) rsadsi(113549)
|
||||
#: digestAlgorithm(2) 5
|
||||
#: }
|
||||
"MD5": "1.2.840.113549.2.5",
|
||||
"md5": "1.2.840.113549.2.5",
|
||||
|
||||
#: id-ripemd160 OBJECT IDENTIFIER ::= {
|
||||
#: iso(1) identified-organization(3) teletrust(36)
|
||||
#: algorithm(3) hashAlgorithm(2) ripemd160(1)
|
||||
#: }
|
||||
"RIPEMD160": "1.3.36.3.2.1",
|
||||
"ripemd160": "1.3.36.3.2.1",
|
||||
|
||||
#: id-sha1 OBJECT IDENTIFIER ::= {
|
||||
#: iso(1) identified-organization(3) oiw(14) secsig(3)
|
||||
#: algorithms(2) 26
|
||||
#: }
|
||||
"SHA1": "1.3.14.3.2.26",
|
||||
"sha1": "1.3.14.3.2.26",
|
||||
|
||||
#: id-sha224 OBJECT IDENTIFIER ::= {
|
||||
#: joint-iso-itu-t(2) country(16) us(840) organization(1) gov(101) csor(3)
|
||||
#: nistalgorithm(4) hashalgs(2) 4
|
||||
#: }
|
||||
"SHA224": '2.16.840.1.101.3.4.2.4',
|
||||
"sha224": '2.16.840.1.101.3.4.2.4',
|
||||
|
||||
#: id-sha256 OBJECT IDENTIFIER ::= {
|
||||
#: joint-iso-itu-t(2) country(16) us(840) organization(1)
|
||||
#: gov(101) csor(3) nistalgorithm(4) hashalgs(2) 1
|
||||
#: }
|
||||
"SHA256": "2.16.840.1.101.3.4.2.1",
|
||||
"sha256": "2.16.840.1.101.3.4.2.1",
|
||||
|
||||
#: id-sha384 OBJECT IDENTIFIER ::= {
|
||||
#: joint-iso-itu-t(2) country(16) us(840) organization(1) gov(101) csor(3)
|
||||
#: nistalgorithm(4) hashalgs(2) 2
|
||||
#: }
|
||||
"SHA384": '2.16.840.1.101.3.4.2.2',
|
||||
"sha384": '2.16.840.1.101.3.4.2.2',
|
||||
|
||||
#: id-sha512 OBJECT IDENTIFIER ::= {
|
||||
#: joint-iso-itu-t(2)
|
||||
#: country(16) us(840) organization(1) gov(101) csor(3) nistalgorithm(4) hashalgs(2) 3
|
||||
#: }
|
||||
"SHA512": "2.16.840.1.101.3.4.2.3",
|
||||
"sha512": "2.16.840.1.101.3.4.2.3",
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -44,10 +44,9 @@ An example of usage is the following:
|
||||
>>> from Crypto.Cipher import AES
|
||||
>>> from Crypto.Util import Counter
|
||||
>>>
|
||||
>>> pt = b'X'*1000000
|
||||
>>> pt = b'\x00'*1000000
|
||||
>>> ctr = Counter.new(128)
|
||||
>>> key = b'AES-128 symm key'
|
||||
>>> cipher = AES.new(key, AES.MODE_CTR, counter=ctr)
|
||||
>>> cipher = AES.new(b'\x00'*16, AES.MODE_CTR, counter=ctr)
|
||||
>>> ct = cipher.encrypt(pt)
|
||||
|
||||
:undocumented: __package__
|
||||
@@ -57,15 +56,11 @@ if sys.version_info[0] == 2 and sys.version_info[1] == 1:
|
||||
from Crypto.Util.py21compat import *
|
||||
from Crypto.Util.py3compat import *
|
||||
|
||||
from Crypto.pct_warnings import DisableShortcut_DeprecationWarning
|
||||
from Crypto.Util import _counter
|
||||
import struct
|
||||
import warnings
|
||||
|
||||
|
||||
# Factory function
|
||||
_deprecated = "deprecated"
|
||||
def new(nbits, prefix=b(""), suffix=b(""), initial_value=1, overflow=0, little_endian=False, allow_wraparound=False, disable_shortcut=_deprecated):
|
||||
def new(nbits, prefix=b(""), suffix=b(""), initial_value=1, overflow=0, little_endian=False, allow_wraparound=False, disable_shortcut=False):
|
||||
"""Create a stateful counter block function suitable for CTR encryption modes.
|
||||
|
||||
Each call to the function returns the next counter block.
|
||||
@@ -73,7 +68,7 @@ def new(nbits, prefix=b(""), suffix=b(""), initial_value=1, overflow=0, little_e
|
||||
|
||||
prefix || counter value || postfix
|
||||
|
||||
The counter value is incremented by 1 at each call.
|
||||
The counter value is incremented by one at each call.
|
||||
|
||||
:Parameters:
|
||||
nbits : integer
|
||||
@@ -86,18 +81,17 @@ def new(nbits, prefix=b(""), suffix=b(""), initial_value=1, overflow=0, little_e
|
||||
used.
|
||||
initial_value : integer
|
||||
The initial value of the counter. Default value is 1.
|
||||
overflow : integer
|
||||
This value is currently ignored.
|
||||
little_endian : boolean
|
||||
If *True*, the counter number will be encoded in little endian format.
|
||||
If *False* (default), in big endian format.
|
||||
If True, the counter number will be encoded in little endian format.
|
||||
If False (default), in big endian format.
|
||||
allow_wraparound : boolean
|
||||
If *True*, the counter will automatically restart from zero after
|
||||
reaching the maximum value (``2**nbits-1``).
|
||||
If *False* (default), the object will raise an *OverflowError*.
|
||||
disable_shortcut : deprecated
|
||||
This option is a no-op for backward compatibility. It will be removed
|
||||
in a future version. Don't use it.
|
||||
If True, the function will raise an *OverflowError* exception as soon
|
||||
as the counter wraps around. If False (default), the counter will
|
||||
simply restart from zero.
|
||||
disable_shortcut : boolean
|
||||
If True, do not make ciphers from `Crypto.Cipher` bypass the Python
|
||||
layer when invoking the counter block function.
|
||||
If False (default), bypass the Python layer.
|
||||
:Returns:
|
||||
The counter block function.
|
||||
"""
|
||||
@@ -114,13 +108,10 @@ def new(nbits, prefix=b(""), suffix=b(""), initial_value=1, overflow=0, little_e
|
||||
|
||||
initval = _encode(initial_value, nbytes, little_endian)
|
||||
|
||||
if disable_shortcut is not _deprecated: # exact object comparison
|
||||
warnings.warn("disable_shortcut has no effect and is deprecated", DisableShortcut_DeprecationWarning)
|
||||
|
||||
if little_endian:
|
||||
return _counter._newLE(bstr(prefix), bstr(suffix), initval, allow_wraparound=allow_wraparound)
|
||||
return _counter._newLE(bstr(prefix), bstr(suffix), initval, allow_wraparound=allow_wraparound, disable_shortcut=disable_shortcut)
|
||||
else:
|
||||
return _counter._newBE(bstr(prefix), bstr(suffix), initval, allow_wraparound=allow_wraparound)
|
||||
return _counter._newBE(bstr(prefix), bstr(suffix), initval, allow_wraparound=allow_wraparound, disable_shortcut=disable_shortcut)
|
||||
|
||||
def _encode(n, nbytes, little_endian=False):
|
||||
retval = []
|
||||
|
||||
@@ -23,22 +23,15 @@
|
||||
Contains useful modules that don't belong into any of the
|
||||
other Crypto.* subpackages.
|
||||
|
||||
======================== =============================================
|
||||
Module Description
|
||||
======================== =============================================
|
||||
`Crypto.Util.number` Number-theoretic functions (primality testing, etc.)
|
||||
`Crypto.Util.Counter` Fast counter functions for CTR cipher modes.
|
||||
`Crypto.Util.randpool` Random number generation
|
||||
`Crypto.Util.RFC1751` Converts between 128-bit keys and human-readable
|
||||
strings of words.
|
||||
`Crypto.Util.asn1` Minimal support for ASN.1 DER encoding
|
||||
`Crypto.Util.Padding` Set of functions for adding and removing padding.
|
||||
======================== =============================================
|
||||
Crypto.Util.number Number-theoretic functions (primality testing, etc.)
|
||||
Crypto.Util.randpool Random number generation
|
||||
Crypto.Util.RFC1751 Converts between 128-bit keys and human-readable
|
||||
strings of words.
|
||||
Crypto.Util.asn1 Minimal support for ASN.1 DER encoding
|
||||
|
||||
"""
|
||||
|
||||
__all__ = ['randpool', 'RFC1751', 'number', 'strxor', 'asn1', 'Counter',
|
||||
'Padding' ]
|
||||
__all__ = ['randpool', 'RFC1751', 'number', 'strxor', 'asn1' ]
|
||||
|
||||
__revision__ = "$Id$"
|
||||
|
||||
|
||||
Executable
BIN
Binary file not shown.
+165
-778
File diff suppressed because it is too large
Load Diff
@@ -81,21 +81,4 @@ except TypeError:
|
||||
return True
|
||||
return False
|
||||
|
||||
#
|
||||
# Python 2.2 introduces the built-in staticmethod(). Python 2.4 turns
|
||||
# it into a function decorator (@staticmethod).
|
||||
#
|
||||
# The following recipe for achieving the same thing in Python 2.1 comes
|
||||
# from the Python Cookbok ("Implementanting Static Methods").
|
||||
#
|
||||
try:
|
||||
class A:
|
||||
def a(): pass
|
||||
a = staticmethod(a)
|
||||
except NameError:
|
||||
class staticmethod:
|
||||
def __init__(self, anycallable):
|
||||
self.__call__ = anycallable
|
||||
__all__ += ['staticmethod']
|
||||
|
||||
# vim:set ts=4 sw=4 sts=4 expandtab:
|
||||
|
||||
@@ -77,18 +77,12 @@ if sys.version_info[0] == 2:
|
||||
return s.encode('latin-1')
|
||||
except:
|
||||
return ''.join(s)
|
||||
def tostr(bs):
|
||||
return unicode(bs, 'latin-1')
|
||||
else:
|
||||
def tobytes(s):
|
||||
if isinstance(s, unicode):
|
||||
return s.encode("latin-1")
|
||||
else:
|
||||
return ''.join(s)
|
||||
def tostr(bs):
|
||||
return bs.decode('latin-1')
|
||||
# In Pyton 2.x, StringIO is a stand-alone module
|
||||
from StringIO import StringIO as BytesIO
|
||||
else:
|
||||
def b(s):
|
||||
return s.encode("latin-1") # utf-8 would cause some side-effects we don't want
|
||||
@@ -109,9 +103,5 @@ else:
|
||||
return s.encode("latin-1")
|
||||
else:
|
||||
return bytes(s)
|
||||
def tostr(bs):
|
||||
return bs.decode("latin-1")
|
||||
# In Pyton 3.x, StringIO is a sub-module of io
|
||||
from io import BytesIO
|
||||
|
||||
|
||||
# vim:set ts=4 sw=4 sts=4 expandtab:
|
||||
|
||||
Executable
BIN
Binary file not shown.
@@ -35,17 +35,17 @@ Crypto.Protocol
|
||||
Crypto.PublicKey
|
||||
Public-key encryption and signature algorithms (RSA, DSA)
|
||||
Crypto.Signature
|
||||
Public-key signature algorithms (RSA PKCS#1)
|
||||
Public-key signature algorithms (RSA PKCS#1)
|
||||
Crypto.Util
|
||||
Various useful modules and functions (long-to-string conversion, random number
|
||||
generation, number theoretic functions)
|
||||
"""
|
||||
|
||||
__all__ = ['Cipher', 'Hash', 'Protocol', 'PublicKey', 'Util', 'Signature', 'IO']
|
||||
__all__ = ['Cipher', 'Hash', 'Protocol', 'PublicKey', 'Util', 'Signature']
|
||||
|
||||
__version__ = '2.7a1' # See also below and setup.py
|
||||
__version__ = '2.6' # See also below and setup.py
|
||||
__revision__ = "$Id$"
|
||||
|
||||
# New software should look at this instead of at __version__ above.
|
||||
version_info = (2, 7, 0, 'alpha', 1) # See also above and setup.py
|
||||
version_info = (2, 6, 0, 'final', 0) # See also above and setup.py
|
||||
|
||||
|
||||
@@ -49,9 +49,6 @@ class ClockRewindWarning(CryptoRuntimeWarning):
|
||||
class GetRandomNumber_DeprecationWarning(CryptoDeprecationWarning):
|
||||
"""Issued when Crypto.Util.number.getRandomNumber is invoked."""
|
||||
|
||||
class DisableShortcut_DeprecationWarning(CryptoDeprecationWarning):
|
||||
"""Issued when Counter.new(disable_shortcut=...) is invoked."""
|
||||
|
||||
class PowmInsecureWarning(CryptoRuntimeWarning):
|
||||
"""Warning for when _fastmath is built without mpz_powm_sec"""
|
||||
|
||||
|
||||
@@ -0,0 +1,199 @@
|
||||
import bson, scrypt
|
||||
|
||||
from Crypto.Cipher import AES
|
||||
from Crypto.Util import Counter
|
||||
from Crypto.PublicKey import RSA
|
||||
from Crypto.PublicKey import DSA
|
||||
from salsa20 import Salsa20_keystream
|
||||
import os, struct, time, hashlib, hashlib, random
|
||||
|
||||
|
||||
class EncryptedScreenshot:
|
||||
def __init__(self, metadata,id=None,signer=None,password_encryptor=None):
|
||||
def rand(len):
|
||||
return ''.join(
|
||||
random.choice("1234567890ABCDEFGHIJKLMNOPQRSTUWVXYZabcdefghijklmnopqrstuwvxyz") for _ in range(len))
|
||||
|
||||
self.password = rand(16)
|
||||
print "Passphrase %s" % str(bytearray(self.passphrase())).encode("hex")
|
||||
self.id = id
|
||||
if id is None:
|
||||
self.id = rand(8)
|
||||
self.metadata_encryption = True
|
||||
self.metadata = metadata
|
||||
self.signer = signer
|
||||
self.password_encryptor = password_encryptor
|
||||
|
||||
def caesar_encrypted_password(self):
|
||||
caesar_key = reduce(lambda sum,charcode: sum+charcode, map(ord,list(self.id)))
|
||||
caesar_plaintext = map(ord, self.password)
|
||||
caesar_ciphertext = Caesar().encrypt(caesar_plaintext,caesar_key)
|
||||
return ''.join(map(chr,caesar_ciphertext))
|
||||
|
||||
def passphrase(self):
|
||||
# new ScryptParameters(64, 8, 1,32, new Uint8List.fromList(new List<int>()))
|
||||
print "Password units: %s" % (map(ord, self.password.encode("utf-8")),)
|
||||
sha = hashlib.sha256()
|
||||
sha.update(self.password)
|
||||
return sha.digest() # scrypt.hash(self.password.encode("utf-8"), '', 64, 8, 1, 32)
|
||||
|
||||
def assemble(self, file):
|
||||
(image_digest, encrypted_image) = self.encrypt(file)
|
||||
self.metadata["hash"] = image_digest
|
||||
unencrypted_metadata = bson.dumps(self.metadata)
|
||||
if len(unencrypted_metadata) % 16 != 0:
|
||||
unencrypted_metadata += ' ' * (16 - len(unencrypted_metadata) % 16)
|
||||
(encryptor, iv) = self.encryptor(len(unencrypted_metadata))
|
||||
encrypted_metadata = []
|
||||
|
||||
encrypted_metadata += encryptor(unencrypted_metadata)
|
||||
|
||||
encrypted_metadata = iv + str(bytearray(encrypted_metadata))
|
||||
|
||||
print "Metadata: %s" % str(encrypted_metadata).encode("base64").replace("\n", "")
|
||||
print "%s %s" % (str(encrypted_metadata[:16]).encode("hex"), str(encrypted_metadata[16:]).encode("hex"))
|
||||
print "Unencrypted: %s" % (unencrypted_metadata.encode("hex"))
|
||||
print "Password %s" % self.password
|
||||
|
||||
print bson.loads(unencrypted_metadata)
|
||||
|
||||
fields = {
|
||||
"image": encrypted_image,
|
||||
"metadata_encryption": self.metadata_encryption,
|
||||
"metadata": encrypted_metadata if self.metadata_encryption else self.metadata
|
||||
}
|
||||
|
||||
if self.signer is not None:
|
||||
fields["signature"] = self.signer.signature(encrypted_metadata if self.metadata_encryption else bson.dumps(self.metadata))
|
||||
|
||||
if self.password_encryptor is not None:
|
||||
fields["password"] = self.password_encryptor.encrypt_password(self.password)
|
||||
|
||||
return bson.dumps(fields)
|
||||
|
||||
def encryptor(self,length=0):
|
||||
iv = os.urandom(16)
|
||||
ctr = Counter.new(128, initial_value=long(iv.encode("hex"), 16))
|
||||
print "IV: %s" % iv.encode("hex")
|
||||
cipher = AES.new(self.passphrase(), AES.MODE_CTR, counter=ctr)
|
||||
|
||||
#salsa
|
||||
# keysstream = bytearray(Salsa20_keystream(length,iv[:8],self.passphrase()))
|
||||
# offset={"offset": 0}
|
||||
def encrypt(data):
|
||||
#Salsa20
|
||||
# array = bytearray(data)
|
||||
# for i in range(len(array)):
|
||||
# array[i] ^= keysstream[i+offset["offset"]]
|
||||
# offset["offset"] += len(array)
|
||||
# return str(array)
|
||||
return cipher.encrypt(data)
|
||||
|
||||
return (encrypt, iv)
|
||||
|
||||
def encrypt(self, file):
|
||||
filesize = os.path.getsize(file)
|
||||
(encryptor, iv) = self.encryptor(filesize)
|
||||
binary = []
|
||||
digest = hashlib.sha256()
|
||||
with open(file, 'rb') as infile:
|
||||
# binary += struct.pack('<Q', filesize)
|
||||
while True:
|
||||
chunk = infile.read(64 * 1024)
|
||||
if len(chunk) == 0:
|
||||
break
|
||||
elif len(chunk) % 16 != 0:
|
||||
pass # chunk += ' ' * (16 - len(chunk) % 16)
|
||||
digest.update(chunk)
|
||||
binary += encryptor(chunk)
|
||||
return (digest.digest(), iv + str(bytearray(binary)))
|
||||
|
||||
from Crypto.Signature import PKCS1_v1_5
|
||||
from Crypto.Hash import SHA256
|
||||
|
||||
class Signer:
|
||||
|
||||
@staticmethod
|
||||
def default():
|
||||
return Signer(RSA.importKey("-----BEGIN RSA PRIVATE KEY-----\nMIIJKAIBAAKCAgEAuTEHVWjtwFydG/VmHKr15qymIkwZIaNnQeKmBzzn+n87Zjdg\nkEDtCEYSq3W1VxlgUw1Dh8KTTr3K1LQwcDfx8vdArk99OX4mxqpYWRbdfEQk1wUD\n7ctr2E5eKQcCcbAl/OKYFa/PkY3KsBuns06Rlf85sHSZ7CfirqH6FoefrXDZVAJO\nmrQhTh/0qGlBy1f13c2a12sFNOmncLs8Vp4ftJxLr9GoE4vsQvX/6oQvi7PqWYmv\nlwmUUvhCPS/JSF8kCuvmvfgcF8OXOj1Q6itOLZDt8/ZuZeok7nS8JxhR73HzHR4a\nHWnqC8UkIx1CR/VvlZhp/7gbS/y1EORRaVlO3YTkF2UMTtF2BoCsY5glpealDV6F\nh9YZwq68APb5/cleuXu8tebYpo5yuwH9G8m0bp7mIrVUnaBPCE/Wsj6HFULniUi8\n0N8149cM2kLmm7c+JNC4QUupc3iy3qylqh1KFlU0SWPAinDbODSHqnPiWV0IHjC9\nmVeAmMDjg/6R7uaAubLz0rJso/odk0kfWYO98D43Hv7C+TG/If9oE7JdsgSCCfeT\nuaKE5XH3C3GegciDOyr6Sd/08KprQwvy7nZpJJxzpyr2MoJ/n8O6O4IqDt76EAZz\n76nUvJzPXSoUGy7942QOwywpRYB6NbrVpPUemUCsUttUJzhgHU70ElqE2hsCAwEA\nAQKCAgBVyMZS5BYt4zjLuLMiWHcr8ZHLlWCW2nB8bpbmB2qV+NX1FXXfnJOwH3WK\ngy4LOLAMCLrdal5+PSB1wzok4WVsXOhTVnL1bOBdao8eRZ83bwF5sNMPFgnQ2wx3\nCM4zB5uxNu2oLhaCoCHhzg2y25RI3T9F491hLWCt8E4+nXh0CTBC4Aa1VveOjvLw\nCEH4BbjYk+NEIkj5J7ruV20t2nVpXnUY7o9i7o/0vKtdYPn9RswpycPSvRc+D83v\nNfGRWrEBdiEeoo2w3GNzEPAoaQL/zIDNX7vn7bxJ0T1PBs79kdVCCa2jLmrCJQIG\nWglX9/NGYqHHWOscGeVt+7VSjZIf8+q32khXcheBUP++wsDC1YoxiT2aDwV7zX8d\nBhB6MMi7QUqkkwnuvXdyUIUy4J7lJHDsC5l4EYDmbhViTax8Qp42MobJ32tHoS1c\nhfN5w4Usqx7yGRL0vUQmbGrh7JbyayD6CFYiZOinhN0ma7dMqglQ4ch3HPeMct9T\nLskF+gSlol2gTCMYjl9Zwb2rG8uSthjXFd2CDCHbiqzzRhskHG2vWuhxvASP4yeD\nNbm85H8ZKqhejcWL4XlJIZK2ZbWUjdMDPCDDd3ipwQ/GUmSo6IaNxEFMCFLsk/xl\n2BGg99xDuacldKNUtf+aMv4HglW6at+TasVsmWXsF/cWR1JusQKCAQEA88JECQTE\nm8AIOaHY5rOWxkYCsVzVw9zRHOfIXbvMMr9k3OTE/9gNy35QTee5UYVEnjRuWP/r\n2hRJhbTfwP5LmcvsxN3cE3SkrlNCulo0TWD4O78W+PnEkSzN+1h39QOfA/TTN9pV\nnqh7Bf5u9kBioooPeUe6yU/eMlVa+mzwNfDC9ogS7o1/1Zy4ui4beo0XpIv5KNtV\nU5K2uEcx0jnAzhcd+IKzDNm7HuU82KCsYNUCdHIJOpoq0WqPTqa350LPWHqbZA9n\nOa+5Yo1ADMn/rMFohErWq2zjUlO3qFjyGBaVAQCYCeprmk56vk4gP44X2YkW524G\nHg/CWYITF42W7QKCAQEAwn3UDzS1LeCZq82TSlFPWO3dojh4fMwssQWzJkrkJg4N\nNlAGGteh7K2eIFjACk7bLe037F2RhPxk+RZEIy4Adr5oAcNLKXMIcaAx9Xca+JrX\nRjLAGsBuoOJFYBVm+/ZlwoVkhOnX1VOJ4Zt4TNOYcImrhZyeVjVfJI7ijTU61v5M\n2+6Ekc2pq6WI7/2hmM+UOw6xvroNvCx0neWVgAVdCWfWWmCkUqjsS8FJ2z9q/8or\nnFPKeAT/kcDg2N+8LiPeVfAqdl6GZ3SY3lZ+Q+JEJMAZEsFsbh0x5OT4750Y/MBz\nqQF1oU2HkV5xah5tAqECp37/FSIxPG2e/qklGqbMJwKCAQA/qkSUym8DcvNzAgeh\nsdQ2cwCvDF00q87eKteVS8B4nK6eVw3w+KAZvyMARf6MAS+71lvf2O/j5JqTVnt+\nb6yVPcLYZE3fsv50HYD3JSo175bGHBHG841YkYg3FpM2Jjz5Do/ALcFhEAYZuauH\nm6dnZoHGHmr1u2uAX/TEJYHTxM9XDpFLRx/VTfqdff9lUcaUDo8EEc1GZ7JbjRTB\nIJ5v9W+5gYF8YL3TwvHSbpy3KctbWJF6gdufGKLXWwn7V+LJ7DP7vV4rne7gg53v\n+S5TE6zVqKpK2cTBsuXsDVcl3XgLa/lJ1bVG9ypt2//mOZmXEowt4/mrDlingia0\nZyG9AoIBAAvBQSTeIakxLviER0exnGMalU+trBKW4IieeJJy6lEmfkPvGD9dEwtT\n/v+jfY/h7jtbYAroKNhpzMyFPP8HU73Zij25CPzrV/JOJVbZqQanjSVQAe5b/RO6\nOUkyYfQOk13rZATogUQCdY3uMJosG8WJfJVpvuQk+6gg/q5cLj86RXjxdI+/Z2bZ\nbWpb4P10ZlgfbjzBz/y0jyPP8XY4XMQpw3nY53WbghSeDRG0RopJNNOQ+ObCHpQ3\nnR9efmgngNOe3WIkGml8UZT2k1EVBttVxO4uRJhvKUnVUPpie1UjaJopXWuvXOc7\nVw1740jKZHetJEupsmIdmgN4Q6bVt/cCggEBAILm8bfc2OGbZgN4RT4315EkWekb\nMngMFETDDgn6p2jmkVjXDGku1oX502X7BKteZ+gD4Oqy8BtrvshyzvzoBerthrDj\nJ4M3t7uFC14mvRfdelRcKyed13SGzZNJxxxL7vNq2Me81yzBaMPiAZpDIN4awEzV\nPQwWMmogo6sEp2ND2NhvbP4Hxl8WXoI+3hH5hetE31kvBzDlWek4Wj059BeeIhjF\nBNUxIwbqlSwt+2VuY17LBzCe4Tnp3Ns+ptD9Fn2vm+Azl9qBY2VvqOcdp0R8tmeo\nwpjrWKwP9LkwCt9ZxVzCQBiIFYtpZ8a2EahqTbOlFEsvcDbTfQlf/lykhjA=\n-----END RSA PRIVATE KEY-----\n"),"PUBLIC")
|
||||
|
||||
def __init__(self,privateKey,privateKeyId, mode=RSA):
|
||||
self.mode = mode
|
||||
self.privateKeyId = privateKeyId
|
||||
self._signer = PKCS1_v1_5.new(privateKey)
|
||||
|
||||
def sign(self, data):
|
||||
digest = SHA256.new()
|
||||
digest.update(data)
|
||||
return self._signer.sign(digest)
|
||||
|
||||
def signature(self,data):
|
||||
signed = self.sign(data)
|
||||
return {"signed-hash": signed,
|
||||
"signature-algorithm": "SHA-256/%s" % unicode("RSA" if self.mode == RSA else "DSA"),
|
||||
"key-id": unicode(self.privateKeyId)
|
||||
}
|
||||
|
||||
|
||||
class EncryptedPassword:
|
||||
|
||||
def __init__(self,publicKey,publicKeyId,mode=RSA):
|
||||
assert mode == RSA
|
||||
self.mode = mode
|
||||
self.publicKey = publicKey
|
||||
self.publicKeyId = publicKeyId
|
||||
|
||||
def encrypt(self,password):
|
||||
return self.publicKey.encrypt(password.encode("utf-8"), os.urandom(32))[0]
|
||||
|
||||
def encrypt_password(self,password):
|
||||
return {"algorithm": unicode( "RSA" if self.mode == RSA else "DSA"),
|
||||
"key-id": unicode(self.publicKeyId),
|
||||
"password": self.encrypt(password)
|
||||
}
|
||||
|
||||
class Caesar:
|
||||
|
||||
def __init__(self,charset = map(ord,list("1234567890ABCDEFGHIJKLMNOPQRSTUWVXYZabcdefghijklmnopqrstuwvxyz"))):
|
||||
self.charset = charset
|
||||
|
||||
def encrypt(self,plaintext,key):
|
||||
if key >= len(self.charset) or key < 0:
|
||||
key = key % len(self.charset)
|
||||
|
||||
def addKey(charcode):
|
||||
pos = self.charset.index(charcode)
|
||||
if pos + key >= len(self.charset):
|
||||
return self.charset[pos+key - len(self.charset)]
|
||||
else:
|
||||
return self.charset[pos+key]
|
||||
return map(addKey,plaintext)
|
||||
|
||||
def decrypt(self,ciphertext,key):
|
||||
return self.encrypt(ciphertext,key*-1)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
privateKey = "LS0tLS1CRUdJTiBSU0EgUFJJVkFURSBLRVktLS0tLQpNSUlKS0FJQkFBS0NBZ0VBdVRFSFZXanR3RnlkRy9WbUhLcjE1cXltSWt3WklhTm5RZUttQnp6bituODdaamRnCmtFRHRDRVlTcTNXMVZ4bGdVdzFEaDhLVFRyM0sxTFF3Y0RmeDh2ZEFyazk5T1g0bXhxcFlXUmJkZkVRazF3VUQKN2N0cjJFNWVLUWNDY2JBbC9PS1lGYS9Qa1kzS3NCdW5zMDZSbGY4NXNIU1o3Q2ZpcnFINkZvZWZyWERaVkFKTwptclFoVGgvMHFHbEJ5MWYxM2MyYTEyc0ZOT21uY0xzOFZwNGZ0SnhMcjlHb0U0dnNRdlgvNm9Rdmk3UHFXWW12Cmx3bVVVdmhDUFMvSlNGOGtDdXZtdmZnY0Y4T1hPajFRNml0T0xaRHQ4L1p1WmVvazduUzhKeGhSNzNIekhSNGEKSFducUM4VWtJeDFDUi9WdmxaaHAvN2diUy95MUVPUlJhVmxPM1lUa0YyVU1UdEYyQm9Dc1k1Z2xwZWFsRFY2RgpoOVlad3E2OEFQYjUvY2xldVh1OHRlYllwbzV5dXdIOUc4bTBicDdtSXJWVW5hQlBDRS9Xc2o2SEZVTG5pVWk4CjBOODE0OWNNMmtMbW03YytKTkM0UVV1cGMzaXkzcXlscWgxS0ZsVTBTV1BBaW5EYk9EU0hxblBpV1YwSUhqQzkKbVZlQW1NRGpnLzZSN3VhQXViTHowckpzby9vZGswa2ZXWU85OEQ0M0h2N0MrVEcvSWY5b0U3SmRzZ1NDQ2ZlVAp1YUtFNVhIM0MzR2VnY2lET3lyNlNkLzA4S3ByUXd2eTduWnBKSnh6cHlyMk1vSi9uOE82TzRJcUR0NzZFQVp6Cjc2blV2SnpQWFNvVUd5Nzk0MlFPd3l3cFJZQjZOYnJWcFBVZW1VQ3NVdHRVSnpoZ0hVNzBFbHFFMmhzQ0F3RUEKQVFLQ0FnQlZ5TVpTNUJZdDR6akx1TE1pV0hjcjhaSExsV0NXMm5COGJwYm1CMnFWK05YMUZYWGZuSk93SDNXSwpneTRMT0xBTUNMcmRhbDUrUFNCMXd6b2s0V1ZzWE9oVFZuTDFiT0JkYW84ZVJaODNid0Y1c05NUEZnblEyd3gzCkNNNHpCNXV4TnUyb0xoYUNvQ0hoemcyeTI1UkkzVDlGNDkxaExXQ3Q4RTQrblhoMENUQkM0QWExVnZlT2p2THcKQ0VINEJiallrK05FSWtqNUo3cnVWMjB0Mm5WcFhuVVk3bzlpN28vMHZLdGRZUG45UnN3cHljUFN2UmMrRDgzdgpOZkdSV3JFQmRpRWVvbzJ3M0dOekVQQW9hUUwveklETlg3dm43YnhKMFQxUEJzNzlrZFZDQ2EyakxtckNKUUlHCldnbFg5L05HWXFISFdPc2NHZVZ0KzdWU2paSWY4K3EzMmtoWGNoZUJVUCsrd3NEQzFZb3hpVDJhRHdWN3pYOGQKQmhCNk1NaTdRVXFra3dudXZYZHlVSVV5NEo3bEpIRHNDNWw0RVlEbWJoVmlUYXg4UXA0Mk1vYkozMnRIb1MxYwpoZk41dzRVc3F4N3lHUkwwdlVRbWJHcmg3SmJ5YXlENkNGWWlaT2luaE4wbWE3ZE1xZ2xRNGNoM0hQZU1jdDlUCkxza0YrZ1Nsb2wyZ1RDTVlqbDlad2Iyckc4dVN0aGpYRmQyQ0RDSGJpcXp6Umhza0hHMnZXdWh4dkFTUDR5ZUQKTmJtODVIOFpLcWhlamNXTDRYbEpJWksyWmJXVWpkTURQQ0REZDNpcHdRL0dVbVNvNklhTnhFRk1DRkxzay94bAoyQkdnOTl4RHVhY2xkS05VdGYrYU12NEhnbFc2YXQrVGFzVnNtV1hzRi9jV1IxSnVzUUtDQVFFQTg4SkVDUVRFCm04QUlPYUhZNXJPV3hrWUNzVnpWdzl6UkhPZklYYnZNTXI5azNPVEUvOWdOeTM1UVRlZTVVWVZFbmpSdVdQL3IKMmhSSmhiVGZ3UDVMbWN2c3hOM2NFM1NrcmxOQ3VsbzBUV0Q0Tzc4VytQbkVrU3pOKzFoMzlRT2ZBL1RUTjlwVgpucWg3QmY1dTlrQmlvb29QZVVlNnlVL2VNbFZhK216d05mREM5b2dTN28xLzFaeTR1aTRiZW8wWHBJdjVLTnRWClU1SzJ1RWN4MGpuQXpoY2QrSUt6RE5tN0h1VTgyS0NzWU5VQ2RISUpPcG9xMFdxUFRxYTM1MExQV0hxYlpBOW4KT2ErNVlvMUFETW4vck1Gb2hFcldxMnpqVWxPM3FGanlHQmFWQVFDWUNlcHJtazU2dms0Z1A0NFgyWWtXNTI0RwpIZy9DV1lJVEY0Mlc3UUtDQVFFQXduM1VEelMxTGVDWnE4MlRTbEZQV08zZG9qaDRmTXdzc1FXekprcmtKZzROCk5sQUdHdGVoN0syZUlGakFDazdiTGUwMzdGMlJoUHhrK1JaRUl5NEFkcjVvQWNOTEtYTUljYUF4OVhjYStKclgKUmpMQUdzQnVvT0pGWUJWbSsvWmx3b1ZraE9uWDFWT0o0WnQ0VE5PWWNJbXJoWnllVmpWZkpJN2lqVFU2MXY1TQoyKzZFa2MycHE2V0k3LzJobU0rVU93Nnh2cm9OdkN4MG5lV1ZnQVZkQ1dmV1dtQ2tVcWpzUzhGSjJ6OXEvOG9yCm5GUEtlQVQva2NEZzJOKzhMaVBlVmZBcWRsNkdaM1NZM2xaK1ErSkVKTUFaRXNGc2JoMHg1T1Q0NzUwWS9NQnoKcVFGMW9VMkhrVjV4YWg1dEFxRUNwMzcvRlNJeFBHMmUvcWtsR3FiTUp3S0NBUUEvcWtTVXltOERjdk56QWdlaApzZFEyY3dDdkRGMDBxODdlS3RlVlM4QjRuSzZlVnczdytLQVp2eU1BUmY2TUFTKzcxbHZmMk8vajVKcVRWbnQrCmI2eVZQY0xZWkUzZnN2NTBIWUQzSlNvMTc1YkdIQkhHODQxWWtZZzNGcE0ySmp6NURvL0FMY0ZoRUFZWnVhdUgKbTZkblpvSEdIbXIxdTJ1QVgvVEVKWUhUeE05WERwRkxSeC9WVGZxZGZmOWxVY2FVRG84RUVjMUdaN0pialJUQgpJSjV2OVcrNWdZRjhZTDNUd3ZIU2JweTNLY3RiV0pGNmdkdWZHS0xYV3duN1YrTEo3RFA3dlY0cm5lN2dnNTN2CitTNVRFNnpWcUtwSzJjVEJzdVhzRFZjbDNYZ0xhL2xKMWJWRzl5cHQyLy9tT1ptWEVvd3Q0L21yRGxpbmdpYTAKWnlHOUFvSUJBQXZCUVNUZUlha3hMdmlFUjBleG5HTWFsVSt0ckJLVzRJaWVlSkp5NmxFbWZrUHZHRDlkRXd0VAovditqZlkvaDdqdGJZQXJvS05ocHpNeUZQUDhIVTczWmlqMjVDUHpyVi9KT0pWYlpxUWFualNWUUFlNWIvUk82Ck9Va3lZZlFPazEzclpBVG9nVVFDZFkzdU1Kb3NHOFdKZkpWcHZ1UWsrNmdnL3E1Y0xqODZSWGp4ZEkrL1oyYloKYldwYjRQMTBabGdmYmp6QnoveTBqeVBQOFhZNFhNUXB3M25ZNTNXYmdoU2VEUkcwUm9wSk5OT1ErT2JDSHBRMwpuUjllZm1nbmdOT2UzV0lrR21sOFVaVDJrMUVWQnR0VnhPNHVSSmh2S1VuVlVQcGllMVVqYUpvcFhXdXZYT2M3ClZ3MTc0MGpLWkhldEpFdXBzbUlkbWdONFE2YlZ0L2NDZ2dFQkFJTG04YmZjMk9HYlpnTjRSVDQzMTVFa1dla2IKTW5nTUZFVEREZ242cDJqbWtWalhER2t1MW9YNTAyWDdCS3RlWitnRDRPcXk4QnRydnNoeXp2em9CZXJ0aHJEagpKNE0zdDd1RkMxNG12UmZkZWxSY0t5ZWQxM1NHelpOSnh4eEw3dk5xMk1lODF5ekJhTVBpQVpwRElONGF3RXpWClBRd1dNbW9nbzZzRXAyTkQyTmh2YlA0SHhsOFdYb0krM2hINWhldEUzMWt2QnpEbFdlazRXajA1OUJlZUloakYKQk5VeEl3YnFsU3d0KzJWdVkxN0xCekNlNFRucDNOcytwdEQ5Rm4ydm0rQXpsOXFCWTJWdnFPY2RwMFI4dG1lbwp3cGpyV0t3UDlMa3dDdDlaeFZ6Q1FCaUlGWXRwWjhhMkVhaHFUYk9sRkVzdmNEYlRmUWxmL2x5a2hqQT0KLS0tLS1FTkQgUlNBIFBSSVZBVEUgS0VZLS0tLS0K="
|
||||
publicKey = "LS0tLS1CRUdJTiBQVUJMSUMgS0VZLS0tLS0KTUlJQ0lqQU5CZ2txaGtpRzl3MEJBUUVGQUFPQ0FnOEFNSUlDQ2dLQ0FnRUF1VEVIVldqdHdGeWRHL1ZtSEtyMQo1cXltSWt3WklhTm5RZUttQnp6bituODdaamRna0VEdENFWVNxM1cxVnhsZ1V3MURoOEtUVHIzSzFMUXdjRGZ4Cjh2ZEFyazk5T1g0bXhxcFlXUmJkZkVRazF3VUQ3Y3RyMkU1ZUtRY0NjYkFsL09LWUZhL1BrWTNLc0J1bnMwNlIKbGY4NXNIU1o3Q2ZpcnFINkZvZWZyWERaVkFKT21yUWhUaC8wcUdsQnkxZjEzYzJhMTJzRk5PbW5jTHM4VnA0Zgp0SnhMcjlHb0U0dnNRdlgvNm9Rdmk3UHFXWW12bHdtVVV2aENQUy9KU0Y4a0N1dm12ZmdjRjhPWE9qMVE2aXRPCkxaRHQ4L1p1WmVvazduUzhKeGhSNzNIekhSNGFIV25xQzhVa0l4MUNSL1Z2bFpocC83Z2JTL3kxRU9SUmFWbE8KM1lUa0YyVU1UdEYyQm9Dc1k1Z2xwZWFsRFY2Rmg5WVp3cTY4QVBiNS9jbGV1WHU4dGViWXBvNXl1d0g5RzhtMApicDdtSXJWVW5hQlBDRS9Xc2o2SEZVTG5pVWk4ME44MTQ5Y00ya0xtbTdjK0pOQzRRVXVwYzNpeTNxeWxxaDFLCkZsVTBTV1BBaW5EYk9EU0hxblBpV1YwSUhqQzltVmVBbU1EamcvNlI3dWFBdWJMejBySnNvL29kazBrZldZTzkKOEQ0M0h2N0MrVEcvSWY5b0U3SmRzZ1NDQ2ZlVHVhS0U1WEgzQzNHZWdjaURPeXI2U2QvMDhLcHJRd3Z5N25acApKSnh6cHlyMk1vSi9uOE82TzRJcUR0NzZFQVp6NzZuVXZKelBYU29VR3k3OTQyUU93eXdwUllCNk5iclZwUFVlCm1VQ3NVdHRVSnpoZ0hVNzBFbHFFMmhzQ0F3RUFBUT09Ci0tLS0tRU5EIFBVQkxJQyBLRVktLS0tLQo="
|
||||
encrypted = EncryptedScreenshot({"owner": u"test", "format": u"jpg", "title": u"5x5 Red", "timestamp": int(time.time()*1000)},
|
||||
signer=Signer.default(),
|
||||
password_encryptor=EncryptedPassword(RSA.importKey(publicKey.decode("base64")),"PUBLIC"))
|
||||
fixed_id = encrypted.id #"W9u9Zm0u"
|
||||
print len(encrypted.passphrase())
|
||||
out = open("/home/marvin/Dokumente/IdeaProjects/EncryptedScreencloud/Frontend/WebApp/web/data/" + fixed_id, 'wb')
|
||||
assembled = encrypted.assemble("5x5red.png")
|
||||
out.write(assembled)
|
||||
b = bson.loads(assembled)
|
||||
del b["image"]
|
||||
print b
|
||||
#print assembled.encode("base64").replace("\n","")
|
||||
print "http://localhost:8080/#%s%s" % (fixed_id, encrypted.password)
|
||||
caesar_key = reduce(lambda sum,charcode: sum+charcode, map(ord,list(fixed_id)))
|
||||
caesar_plaintext = map(ord,encrypted.password)
|
||||
caesar_ciphertext = Caesar().encrypt(caesar_plaintext,caesar_key)
|
||||
assert caesar_plaintext == Caesar().decrypt(caesar_ciphertext,caesar_key)
|
||||
print "caesar_key=%s %s -> %s" % (caesar_key,encrypted.password,''.join(map(chr,caesar_ciphertext)))
|
||||
print "http://localhost:8080/#%s%sC" % (fixed_id, encrypted.caesar_encrypted_password())
|
||||
print "http://localhost:8080/#%s" % (fixed_id, )
|
||||
out.close()
|
||||
+26
-6
@@ -52,31 +52,43 @@ class SeafileLibrary:
|
||||
self.name = name
|
||||
self.owner = owner
|
||||
|
||||
def upload(self,file,file_name,directory):
|
||||
def api_endpoint(self):
|
||||
return "%s/repos/%s" % (self.client.api_endpoint(),self.id)
|
||||
|
||||
def upload(self,file,file_name,directory,link=None):
|
||||
def obtain_link():
|
||||
#curl -H "Authorization: Token f2210dacd9c6ccb8133606d94ff8e61d99b477fd" https://cloud.seafile.com/api2/repos/99b758e6-91ab-4265-b705-925367374cf0/upload-link/
|
||||
quoted = requests.get("%s/repos/%s/upload-link" % (self.client.api_endpoint(),self.id), headers = {'Authorization': "Token %s" % self.client.token.token,}).text
|
||||
print "%s/upload-link" % self.api_endpoint()
|
||||
quoted = requests.get("%s/upload-link" % self.api_endpoint(), headers = {'Authorization': "Token %s" % self.client.token.token,}).text
|
||||
return quoted[1:-1]
|
||||
|
||||
#curl -H "Authorization: Token f2210dacd9c6ccb8133606d94ff8e61d99b477fd" -F file=@test.txt -F filename=test.txt -F parent_dir=/ http://cloud.seafile.com:8082/upload-api/73c5d117-3bcf-48a0-aa2a-3f48d5274ae3
|
||||
resp = requests.post(obtain_link(),
|
||||
files={'file': (file_name,open(file, 'rb')), 'parent_dir': directory},
|
||||
resp = requests.post(link or obtain_link() ,
|
||||
files={'file': (file_name,open(file, 'rb')), 'parent_dir': directory, 'target_file': "%s/%s" % (directory,file_name)},
|
||||
headers = {'Authorization': "Token %s" % self.client.token.token,}
|
||||
)
|
||||
if resp.status_code == 200:
|
||||
return SeafileFile(self,("%s/%s" % (directory,file_name)).replace('//','/').replace('//','/'),resp.text)
|
||||
return False
|
||||
|
||||
|
||||
#curl -H 'Authorization: Token f2210dacd3606d94ff8e61d99b477fd' -H 'Accept: application/json; charset=utf-8; indent=4' https://cloud.seafile.com/api2/repos/dae8cecc-2359-4d33-aa42-01b7846c4b32/file/detail/?p=/foo.c
|
||||
def file_info(self,path):
|
||||
resp=requests.get("%s/file/detail/?p=%s" % (self.api_endpoint(),path), headers = {'Authorization': "Token %s" % self.token.token, 'Accept': 'application/json; indent=4' })
|
||||
if resp.status_code == 200:
|
||||
json = resp.json()
|
||||
return SeafileFile(self,path,json['id'],json['size'])
|
||||
return False
|
||||
|
||||
def __str__(self):
|
||||
return "%s on %s by %s" % (self.name,self.client.server,self.owner)
|
||||
|
||||
class SeafileFile:
|
||||
|
||||
def __init__(self,library,path,id):
|
||||
def __init__(self,library,path,id,size=0):
|
||||
self.id = id
|
||||
self.path = path
|
||||
self.library = library
|
||||
self.size = size
|
||||
|
||||
#curl -v -X PUT -d "p=/foo.md" -H 'Authorization: Token f2210dacd9c6ccb8133606d94ff8e61d99b477fd' -H 'Accept: application/json; indent=4' https://cloud.seafile.com/api2/repos/afc3b694-7d4c-4b8a-86a4-89c9f3261b12/file/shared-link/
|
||||
def share(self):
|
||||
@@ -86,6 +98,14 @@ class SeafileFile:
|
||||
)
|
||||
return resp.headers.get("location")
|
||||
|
||||
def update(self,file):
|
||||
def obtain_link():
|
||||
#curl -H "Authorization: Token f2210dacd9c6ccb8133606d94ff8e61d99b477fd" https://cloud.seafile.com/api2/repos/99b758e6-91ab-4265-b705-925367374cf0/upload-link/
|
||||
quoted = requests.get("%s/update-link" % self.library.api_endpoint(), headers = {'Authorization': "Token %s" % self.library.client.token.token,}).text
|
||||
return quoted[1:-1]
|
||||
directory, name = os.path.split(self.path)
|
||||
return self.library.upload(file,name,directory,obtain_link())
|
||||
|
||||
class SeafileToken:
|
||||
|
||||
def __init__(self,username,token):
|
||||
|
||||
Reference in New Issue
Block a user