diff options
author | Determinant <[email protected]> | 2020-11-17 18:47:40 -0500 |
---|---|---|
committer | Determinant <[email protected]> | 2020-11-17 18:47:40 -0500 |
commit | 3bef51eec2299403467e621ae660cef3f9256ac8 (patch) | |
tree | 9b72aaa95fb6dffacd8b20164699870a32ab6825 /frozen_deps/Crypto/Cipher | |
parent | 92b8b8e9628cac41d37226416107adc76b10e01b (diff) |
update frozen deps
Diffstat (limited to 'frozen_deps/Crypto/Cipher')
20 files changed, 1806 insertions, 0 deletions
diff --git a/frozen_deps/Crypto/Cipher/AES.py b/frozen_deps/Crypto/Cipher/AES.py new file mode 100644 index 0000000..14f68d8 --- /dev/null +++ b/frozen_deps/Crypto/Cipher/AES.py @@ -0,0 +1,115 @@ +# -*- coding: utf-8 -*- +# +# Cipher/AES.py : AES +# +# =================================================================== +# The contents of this file are dedicated to the public domain. To +# the extent that dedication to the public domain is not available, +# everyone is granted a worldwide, perpetual, royalty-free, +# non-exclusive license to exercise all rights associated with the +# contents of this file for any purpose whatsoever. +# No rights are reserved. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS +# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. +# =================================================================== +"""AES symmetric cipher + +AES `(Advanced Encryption Standard)`__ is a symmetric block cipher standardized +by NIST_ . It has a fixed data block size of 16 bytes. +Its keys can be 128, 192, or 256 bits long. + +AES is very fast and secure, and it is the de facto standard for symmetric +encryption. + +As an example, encryption can be done as follows: + + >>> from Crypto.Cipher import AES + >>> from Crypto import Random + >>> + >>> key = b'Sixteen byte key' + >>> iv = Random.new().read(AES.block_size) + >>> cipher = AES.new(key, AES.MODE_CFB, iv) + >>> msg = iv + cipher.encrypt(b'Attack at dawn') + +.. __: http://en.wikipedia.org/wiki/Advanced_Encryption_Standard +.. _NIST: http://csrc.nist.gov/publications/fips/fips197/fips-197.pdf + +:undocumented: __revision__, __package__ +""" + +__revision__ = "$Id$" + +from Crypto.Cipher import blockalgo +from Crypto.Cipher import _AES + +class AESCipher (blockalgo.BlockAlgo): + """AES cipher object""" + + def __init__(self, key, *args, **kwargs): + """Initialize an AES cipher object + + See also `new()` at the module level.""" + blockalgo.BlockAlgo.__init__(self, _AES, key, *args, **kwargs) + +def new(key, *args, **kwargs): + """Create a new AES cipher + + :Parameters: + key : byte string + The secret key to use in the symmetric cipher. + It must be 16 (*AES-128*), 24 (*AES-192*), or 32 (*AES-256*) bytes long. + :Keywords: + mode : a *MODE_** constant + The chaining mode to use for encryption or decryption. + Default is `MODE_ECB`. + IV : byte string + The initialization vector to use for encryption or decryption. + + It is ignored for `MODE_ECB` and `MODE_CTR`. + + For `MODE_OPENPGP`, IV must be `block_size` bytes long for encryption + and `block_size` +2 bytes for decryption (in the latter case, it is + actually the *encrypted* IV which was prefixed to the ciphertext). + It is mandatory. + + For all other modes, it must be `block_size` bytes longs. It is optional and + when not present it will be given a default value of all zeroes. + counter : callable + (*Only* `MODE_CTR`). A stateful function that returns the next + *counter block*, which is a byte string of `block_size` bytes. + For better performance, use `Crypto.Util.Counter`. + segment_size : integer + (*Only* `MODE_CFB`).The number of bits the plaintext and ciphertext + are segmented in. + It must be a multiple of 8. If 0 or not specified, it will be assumed to be 8. + + :Return: an `AESCipher` object + """ + return AESCipher(key, *args, **kwargs) + +#: Electronic Code Book (ECB). See `blockalgo.MODE_ECB`. +MODE_ECB = 1 +#: Cipher-Block Chaining (CBC). See `blockalgo.MODE_CBC`. +MODE_CBC = 2 +#: Cipher FeedBack (CFB). See `blockalgo.MODE_CFB`. +MODE_CFB = 3 +#: This mode should not be used. +MODE_PGP = 4 +#: Output FeedBack (OFB). See `blockalgo.MODE_OFB`. +MODE_OFB = 5 +#: CounTer Mode (CTR). See `blockalgo.MODE_CTR`. +MODE_CTR = 6 +#: OpenPGP Mode. See `blockalgo.MODE_OPENPGP`. +MODE_OPENPGP = 7 +#: Size of a data block (in bytes) +block_size = 16 +#: Size of a key (in bytes) +key_size = ( 16, 24, 32 ) + diff --git a/frozen_deps/Crypto/Cipher/ARC2.py b/frozen_deps/Crypto/Cipher/ARC2.py new file mode 100644 index 0000000..b5234e6 --- /dev/null +++ b/frozen_deps/Crypto/Cipher/ARC2.py @@ -0,0 +1,130 @@ +# -*- coding: utf-8 -*- +# +# Cipher/ARC2.py : ARC2.py +# +# =================================================================== +# The contents of this file are dedicated to the public domain. To +# the extent that dedication to the public domain is not available, +# everyone is granted a worldwide, perpetual, royalty-free, +# non-exclusive license to exercise all rights associated with the +# contents of this file for any purpose whatsoever. +# No rights are reserved. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS +# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. +# =================================================================== +"""RC2 symmetric cipher + +RC2_ (Rivest's Cipher version 2) is a symmetric block cipher designed +by Ron Rivest in 1987. The cipher started as a proprietary design, +that was reverse engineered and anonymously posted on Usenet in 1996. +For this reason, the algorithm was first called *Alleged* RC2 (ARC2), +since the company that owned RC2 (RSA Data Inc.) did not confirm whether +the details leaked into public domain were really correct. + +The company eventually published its full specification in RFC2268_. + +RC2 has a fixed data block size of 8 bytes. Length of its keys can vary from +8 to 128 bits. One particular property of RC2 is that the actual +cryptographic strength of the key (*effective key length*) can be reduced +via a parameter. + +Even though RC2 is not cryptographically broken, it has not been analyzed as +thoroughly as AES, which is also faster than RC2. + +New designs should not use RC2. + +As an example, encryption can be done as follows: + + >>> from Crypto.Cipher import ARC2 + >>> from Crypto import Random + >>> + >>> key = b'Sixteen byte key' + >>> iv = Random.new().read(ARC2.block_size) + >>> cipher = ARC2.new(key, ARC2.MODE_CFB, iv) + >>> msg = iv + cipher.encrypt(b'Attack at dawn') + +.. _RC2: http://en.wikipedia.org/wiki/RC2 +.. _RFC2268: http://tools.ietf.org/html/rfc2268 + +:undocumented: __revision__, __package__ +""" + +__revision__ = "$Id$" + +from Crypto.Cipher import blockalgo +from Crypto.Cipher import _ARC2 + +class RC2Cipher (blockalgo.BlockAlgo): + """RC2 cipher object""" + + def __init__(self, key, *args, **kwargs): + """Initialize an ARC2 cipher object + + See also `new()` at the module level.""" + blockalgo.BlockAlgo.__init__(self, _ARC2, key, *args, **kwargs) + +def new(key, *args, **kwargs): + """Create a new RC2 cipher + + :Parameters: + key : byte string + The secret key to use in the symmetric cipher. + Its length can vary from 1 to 128 bytes. + :Keywords: + mode : a *MODE_** constant + The chaining mode to use for encryption or decryption. + Default is `MODE_ECB`. + IV : byte string + The initialization vector to use for encryption or decryption. + + It is ignored for `MODE_ECB` and `MODE_CTR`. + + For `MODE_OPENPGP`, IV must be `block_size` bytes long for encryption + and `block_size` +2 bytes for decryption (in the latter case, it is + actually the *encrypted* IV which was prefixed to the ciphertext). + It is mandatory. + + For all other modes, it must be `block_size` bytes longs. It is optional and + when not present it will be given a default value of all zeroes. + counter : callable + (*Only* `MODE_CTR`). A stateful function that returns the next + *counter block*, which is a byte string of `block_size` bytes. + For better performance, use `Crypto.Util.Counter`. + segment_size : integer + (*Only* `MODE_CFB`).The number of bits the plaintext and ciphertext + are segmented in. + It must be a multiple of 8. If 0 or not specified, it will be assumed to be 8. + effective_keylen : integer + Maximum cryptographic strength of the key, in bits. + It can vary from 0 to 1024. The default value is 1024. + + :Return: an `RC2Cipher` object + """ + return RC2Cipher(key, *args, **kwargs) + +#: Electronic Code Book (ECB). See `blockalgo.MODE_ECB`. +MODE_ECB = 1 +#: Cipher-Block Chaining (CBC). See `blockalgo.MODE_CBC`. +MODE_CBC = 2 +#: Cipher FeedBack (CFB). See `blockalgo.MODE_CFB`. +MODE_CFB = 3 +#: This mode should not be used. +MODE_PGP = 4 +#: Output FeedBack (OFB). See `blockalgo.MODE_OFB`. +MODE_OFB = 5 +#: CounTer Mode (CTR). See `blockalgo.MODE_CTR`. +MODE_CTR = 6 +#: OpenPGP Mode. See `blockalgo.MODE_OPENPGP`. +MODE_OPENPGP = 7 +#: Size of a data block (in bytes) +block_size = 8 +#: Size of a key (in bytes) +key_size = range(1,16+1) + diff --git a/frozen_deps/Crypto/Cipher/ARC4.py b/frozen_deps/Crypto/Cipher/ARC4.py new file mode 100644 index 0000000..d83f75b --- /dev/null +++ b/frozen_deps/Crypto/Cipher/ARC4.py @@ -0,0 +1,120 @@ +# -*- coding: utf-8 -*- +# +# Cipher/ARC4.py : ARC4 +# +# =================================================================== +# The contents of this file are dedicated to the public domain. To +# the extent that dedication to the public domain is not available, +# everyone is granted a worldwide, perpetual, royalty-free, +# non-exclusive license to exercise all rights associated with the +# contents of this file for any purpose whatsoever. +# No rights are reserved. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS +# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. +# =================================================================== +"""ARC4 symmetric cipher + +ARC4_ (Alleged RC4) is an implementation of RC4 (Rivest's Cipher version 4), +a symmetric stream cipher designed by Ron Rivest in 1987. + +The cipher started as a proprietary design, that was reverse engineered and +anonymously posted on Usenet in 1994. The company that owns RC4 (RSA Data +Inc.) never confirmed the correctness of the leaked algorithm. + +Unlike RC2, the company has never published the full specification of RC4, +of whom it still holds the trademark. + +ARC4 keys can vary in length from 40 to 2048 bits. + +One problem of ARC4 is that it does not take a nonce or an IV. If it is required +to encrypt multiple messages with the same long-term key, a distinct +independent nonce must be created for each message, and a short-term key must +be derived from the combination of the long-term key and the nonce. +Due to the weak key scheduling algorithm of RC2, the combination must be carried +out with a complex function (e.g. a cryptographic hash) and not by simply +concatenating key and nonce. + +New designs should not use ARC4. A good alternative is AES +(`Crypto.Cipher.AES`) in any of the modes that turn it into a stream cipher (OFB, CFB, or CTR). + +As an example, encryption can be done as follows: + + >>> from Crypto.Cipher import ARC4 + >>> from Crypto.Hash import SHA + >>> from Crypto import Random + >>> + >>> key = b'Very long and confidential key' + >>> nonce = Random.new().read(16) + >>> tempkey = SHA.new(key+nonce).digest() + >>> cipher = ARC4.new(tempkey) + >>> msg = nonce + cipher.encrypt(b'Open the pod bay doors, HAL') + +.. _ARC4: http://en.wikipedia.org/wiki/RC4 + +:undocumented: __revision__, __package__ +""" + +__revision__ = "$Id$" + +from Crypto.Cipher import _ARC4 + +class ARC4Cipher: + """ARC4 cipher object""" + + + def __init__(self, key, *args, **kwargs): + """Initialize an ARC4 cipher object + + See also `new()` at the module level.""" + + self._cipher = _ARC4.new(key, *args, **kwargs) + self.block_size = self._cipher.block_size + self.key_size = self._cipher.key_size + + def encrypt(self, plaintext): + """Encrypt a piece of data. + + :Parameters: + plaintext : byte string + The piece of data to encrypt. It can be of any size. + :Return: the encrypted data (byte string, as long as the + plaintext). + """ + return self._cipher.encrypt(plaintext) + + def decrypt(self, ciphertext): + """Decrypt a piece of data. + + :Parameters: + ciphertext : byte string + The piece of data to decrypt. It can be of any size. + :Return: the decrypted data (byte string, as long as the + ciphertext). + """ + return self._cipher.decrypt(ciphertext) + +def new(key, *args, **kwargs): + """Create a new ARC4 cipher + + :Parameters: + key : byte string + The secret key to use in the symmetric cipher. + It can have any length, with a minimum of 40 bytes. + Its cryptograpic strength is always capped to 2048 bits (256 bytes). + + :Return: an `ARC4Cipher` object + """ + return ARC4Cipher(key, *args, **kwargs) + +#: Size of a data block (in bytes) +block_size = 1 +#: Size of a key (in bytes) +key_size = range(1,256+1) + diff --git a/frozen_deps/Crypto/Cipher/Blowfish.py b/frozen_deps/Crypto/Cipher/Blowfish.py new file mode 100644 index 0000000..8c81d96 --- /dev/null +++ b/frozen_deps/Crypto/Cipher/Blowfish.py @@ -0,0 +1,121 @@ +# -*- coding: utf-8 -*- +# +# Cipher/Blowfish.py : Blowfish +# +# =================================================================== +# The contents of this file are dedicated to the public domain. To +# the extent that dedication to the public domain is not available, +# everyone is granted a worldwide, perpetual, royalty-free, +# non-exclusive license to exercise all rights associated with the +# contents of this file for any purpose whatsoever. +# No rights are reserved. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS +# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. +# =================================================================== +"""Blowfish symmetric cipher + +Blowfish_ is a symmetric block cipher designed by Bruce Schneier. + +It has a fixed data block size of 8 bytes and its keys can vary in length +from 32 to 448 bits (4 to 56 bytes). + +Blowfish is deemed secure and it is fast. However, its keys should be chosen +to be big enough to withstand a brute force attack (e.g. at least 16 bytes). + +As an example, encryption can be done as follows: + + >>> from Crypto.Cipher import Blowfish + >>> from Crypto import Random + >>> from struct import pack + >>> + >>> bs = Blowfish.block_size + >>> key = b'An arbitrarily long key' + >>> iv = Random.new().read(bs) + >>> cipher = Blowfish.new(key, Blowfish.MODE_CBC, iv) + >>> plaintext = b'docendo discimus ' + >>> plen = bs - divmod(len(plaintext),bs)[1] + >>> padding = [plen]*plen + >>> padding = pack('b'*plen, *padding) + >>> msg = iv + cipher.encrypt(plaintext + padding) + +.. _Blowfish: http://www.schneier.com/blowfish.html + +:undocumented: __revision__, __package__ +""" + +__revision__ = "$Id$" + +from Crypto.Cipher import blockalgo +from Crypto.Cipher import _Blowfish + +class BlowfishCipher (blockalgo.BlockAlgo): + """Blowfish cipher object""" + + def __init__(self, key, *args, **kwargs): + """Initialize a Blowfish cipher object + + See also `new()` at the module level.""" + blockalgo.BlockAlgo.__init__(self, _Blowfish, key, *args, **kwargs) + +def new(key, *args, **kwargs): + """Create a new Blowfish cipher + + :Parameters: + key : byte string + The secret key to use in the symmetric cipher. + Its length can vary from 4 to 56 bytes. + :Keywords: + mode : a *MODE_** constant + The chaining mode to use for encryption or decryption. + Default is `MODE_ECB`. + IV : byte string + The initialization vector to use for encryption or decryption. + + It is ignored for `MODE_ECB` and `MODE_CTR`. + + For `MODE_OPENPGP`, IV must be `block_size` bytes long for encryption + and `block_size` +2 bytes for decryption (in the latter case, it is + actually the *encrypted* IV which was prefixed to the ciphertext). + It is mandatory. + + For all other modes, it must be `block_size` bytes longs. It is optional and + when not present it will be given a default value of all zeroes. + counter : callable + (*Only* `MODE_CTR`). A stateful function that returns the next + *counter block*, which is a byte string of `block_size` bytes. + For better performance, use `Crypto.Util.Counter`. + segment_size : integer + (*Only* `MODE_CFB`).The number of bits the plaintext and ciphertext + are segmented in. + It must be a multiple of 8. If 0 or not specified, it will be assumed to be 8. + + :Return: a `BlowfishCipher` object + """ + return BlowfishCipher(key, *args, **kwargs) + +#: Electronic Code Book (ECB). See `blockalgo.MODE_ECB`. +MODE_ECB = 1 +#: Cipher-Block Chaining (CBC). See `blockalgo.MODE_CBC`. +MODE_CBC = 2 +#: Cipher FeedBack (CFB). See `blockalgo.MODE_CFB`. +MODE_CFB = 3 +#: This mode should not be used. +MODE_PGP = 4 +#: Output FeedBack (OFB). See `blockalgo.MODE_OFB`. +MODE_OFB = 5 +#: CounTer Mode (CTR). See `blockalgo.MODE_CTR`. +MODE_CTR = 6 +#: OpenPGP Mode. See `blockalgo.MODE_OPENPGP`. +MODE_OPENPGP = 7 +#: Size of a data block (in bytes) +block_size = 8 +#: Size of a key (in bytes) +key_size = range(4,56+1) + diff --git a/frozen_deps/Crypto/Cipher/CAST.py b/frozen_deps/Crypto/Cipher/CAST.py new file mode 100644 index 0000000..89543b2 --- /dev/null +++ b/frozen_deps/Crypto/Cipher/CAST.py @@ -0,0 +1,123 @@ +# -*- coding: utf-8 -*- +# +# Cipher/CAST.py : CAST +# +# =================================================================== +# The contents of this file are dedicated to the public domain. To +# the extent that dedication to the public domain is not available, +# everyone is granted a worldwide, perpetual, royalty-free, +# non-exclusive license to exercise all rights associated with the +# contents of this file for any purpose whatsoever. +# No rights are reserved. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS +# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. +# =================================================================== +"""CAST-128 symmetric cipher + +CAST-128_ (or CAST5) is a symmetric block cipher specified in RFC2144_. + +It has a fixed data block size of 8 bytes. Its key can vary in length +from 40 to 128 bits. + +CAST is deemed to be cryptographically secure, but its usage is not widespread. +Keys of sufficient length should be used to prevent brute force attacks +(128 bits are recommended). + +As an example, encryption can be done as follows: + + >>> from Crypto.Cipher import CAST + >>> from Crypto import Random + >>> + >>> key = b'Sixteen byte key' + >>> iv = Random.new().read(CAST.block_size) + >>> cipher = CAST.new(key, CAST.MODE_OPENPGP, iv) + >>> plaintext = b'sona si latine loqueris ' + >>> msg = cipher.encrypt(plaintext) + >>> + ... + >>> eiv = msg[:CAST.block_size+2] + >>> ciphertext = msg[CAST.block_size+2:] + >>> cipher = CAST.new(key, CAST.MODE_OPENPGP, eiv) + >>> print cipher.decrypt(ciphertext) + +.. _CAST-128: http://en.wikipedia.org/wiki/CAST-128 +.. _RFC2144: http://tools.ietf.org/html/rfc2144 + +:undocumented: __revision__, __package__ +""" + +__revision__ = "$Id$" + +from Crypto.Cipher import blockalgo +from Crypto.Cipher import _CAST + +class CAST128Cipher(blockalgo.BlockAlgo): + """CAST-128 cipher object""" + + def __init__(self, key, *args, **kwargs): + """Initialize a CAST-128 cipher object + + See also `new()` at the module level.""" + blockalgo.BlockAlgo.__init__(self, _CAST, key, *args, **kwargs) + +def new(key, *args, **kwargs): + """Create a new CAST-128 cipher + + :Parameters: + key : byte string + The secret key to use in the symmetric cipher. + Its length may vary from 5 to 16 bytes. + :Keywords: + mode : a *MODE_** constant + The chaining mode to use for encryption or decryption. + Default is `MODE_ECB`. + IV : byte string + The initialization vector to use for encryption or decryption. + + It is ignored for `MODE_ECB` and `MODE_CTR`. + + For `MODE_OPENPGP`, IV must be `block_size` bytes long for encryption + and `block_size` +2 bytes for decryption (in the latter case, it is + actually the *encrypted* IV which was prefixed to the ciphertext). + It is mandatory. + + For all other modes, it must be `block_size` bytes longs. It is optional and + when not present it will be given a default value of all zeroes. + counter : callable + (*Only* `MODE_CTR`). A stateful function that returns the next + *counter block*, which is a byte string of `block_size` bytes. + For better performance, use `Crypto.Util.Counter`. + segment_size : integer + (*Only* `MODE_CFB`).The number of bits the plaintext and ciphertext + are segmented in. + It must be a multiple of 8. If 0 or not specified, it will be assumed to be 8. + + :Return: an `CAST128Cipher` object + """ + return CAST128Cipher(key, *args, **kwargs) + +#: Electronic Code Book (ECB). See `blockalgo.MODE_ECB`. +MODE_ECB = 1 +#: Cipher-Block Chaining (CBC). See `blockalgo.MODE_CBC`. +MODE_CBC = 2 +#: Cipher FeedBack (CFB). See `blockalgo.MODE_CFB`. +MODE_CFB = 3 +#: This mode should not be used. +MODE_PGP = 4 +#: Output FeedBack (OFB). See `blockalgo.MODE_OFB`. +MODE_OFB = 5 +#: CounTer Mode (CTR). See `blockalgo.MODE_CTR`. +MODE_CTR = 6 +#: OpenPGP Mode. See `blockalgo.MODE_OPENPGP`. +MODE_OPENPGP = 7 +#: Size of a data block (in bytes) +block_size = 8 +#: Size of a key (in bytes) +key_size = range(5,16+1) diff --git a/frozen_deps/Crypto/Cipher/DES.py b/frozen_deps/Crypto/Cipher/DES.py new file mode 100644 index 0000000..2fae42f --- /dev/null +++ b/frozen_deps/Crypto/Cipher/DES.py @@ -0,0 +1,118 @@ +# -*- coding: utf-8 -*- +# +# Cipher/DES.py : DES +# +# =================================================================== +# The contents of this file are dedicated to the public domain. To +# the extent that dedication to the public domain is not available, +# everyone is granted a worldwide, perpetual, royalty-free, +# non-exclusive license to exercise all rights associated with the +# contents of this file for any purpose whatsoever. +# No rights are reserved. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS +# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. +# =================================================================== +"""DES symmetric cipher + +DES `(Data Encryption Standard)`__ is a symmetric block cipher standardized +by NIST_ . It has a fixed data block size of 8 bytes. +Its keys are 64 bits long, even though 8 bits were used for integrity (now they +are ignored) and do not contribute to securty. + +DES is cryptographically secure, but its key length is too short by nowadays +standards and it could be brute forced with some effort. + +DES should not be used for new designs. Use `AES`. + +As an example, encryption can be done as follows: + + >>> from Crypto.Cipher import DES3 + >>> from Crypto import Random + >>> + >>> key = b'Sixteen byte key' + >>> iv = Random.new().read(DES3.block_size) + >>> cipher = DES3.new(key, DES3.MODE_OFB, iv) + >>> plaintext = b'sona si latine loqueris ' + >>> msg = iv + cipher.encrypt(plaintext) + +.. __: http://en.wikipedia.org/wiki/Data_Encryption_Standard +.. _NIST: http://csrc.nist.gov/publications/fips/fips46-3/fips46-3.pdf + +:undocumented: __revision__, __package__ +""" + +__revision__ = "$Id$" + +from Crypto.Cipher import blockalgo +from Crypto.Cipher import _DES + +class DESCipher(blockalgo.BlockAlgo): + """DES cipher object""" + + def __init__(self, key, *args, **kwargs): + """Initialize a DES cipher object + + See also `new()` at the module level.""" + blockalgo.BlockAlgo.__init__(self, _DES, key, *args, **kwargs) + +def new(key, *args, **kwargs): + """Create a new DES cipher + + :Parameters: + key : byte string + The secret key to use in the symmetric cipher. + It must be 8 byte long. The parity bits will be ignored. + :Keywords: + mode : a *MODE_** constant + The chaining mode to use for encryption or decryption. + Default is `MODE_ECB`. + IV : byte string + The initialization vector to use for encryption or decryption. + + It is ignored for `MODE_ECB` and `MODE_CTR`. + + For `MODE_OPENPGP`, IV must be `block_size` bytes long for encryption + and `block_size` +2 bytes for decryption (in the latter case, it is + actually the *encrypted* IV which was prefixed to the ciphertext). + It is mandatory. + + For all other modes, it must be `block_size` bytes longs. It is optional and + when not present it will be given a default value of all zeroes. + counter : callable + (*Only* `MODE_CTR`). A stateful function that returns the next + *counter block*, which is a byte string of `block_size` bytes. + For better performance, use `Crypto.Util.Counter`. + segment_size : integer + (*Only* `MODE_CFB`).The number of bits the plaintext and ciphertext + are segmented in. + It must be a multiple of 8. If 0 or not specified, it will be assumed to be 8. + + :Return: an `DESCipher` object + """ + return DESCipher(key, *args, **kwargs) + +#: Electronic Code Book (ECB). See `blockalgo.MODE_ECB`. +MODE_ECB = 1 +#: Cipher-Block Chaining (CBC). See `blockalgo.MODE_CBC`. +MODE_CBC = 2 +#: Cipher FeedBack (CFB). See `blockalgo.MODE_CFB`. +MODE_CFB = 3 +#: This mode should not be used. +MODE_PGP = 4 +#: Output FeedBack (OFB). See `blockalgo.MODE_OFB`. +MODE_OFB = 5 +#: CounTer Mode (CTR). See `blockalgo.MODE_CTR`. +MODE_CTR = 6 +#: OpenPGP Mode. See `blockalgo.MODE_OPENPGP`. +MODE_OPENPGP = 7 +#: Size of a data block (in bytes) +block_size = 8 +#: Size of a key (in bytes) +key_size = 8 diff --git a/frozen_deps/Crypto/Cipher/DES3.py b/frozen_deps/Crypto/Cipher/DES3.py new file mode 100644 index 0000000..7fedac8 --- /dev/null +++ b/frozen_deps/Crypto/Cipher/DES3.py @@ -0,0 +1,133 @@ +# -*- coding: utf-8 -*- +# +# Cipher/DES3.py : DES3 +# +# =================================================================== +# The contents of this file are dedicated to the public domain. To +# the extent that dedication to the public domain is not available, +# everyone is granted a worldwide, perpetual, royalty-free, +# non-exclusive license to exercise all rights associated with the +# contents of this file for any purpose whatsoever. +# No rights are reserved. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS +# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. +# =================================================================== +"""Triple DES symmetric cipher + +`Triple DES`__ (or TDES or TDEA or 3DES) is a symmetric block cipher standardized by NIST_. +It has a fixed data block size of 8 bytes. Its keys are 128 (*Option 1*) or 192 +bits (*Option 2*) long. +However, 1 out of 8 bits is used for redundancy and do not contribute to +security. The effective key length is respectively 112 or 168 bits. + +TDES consists of the concatenation of 3 simple `DES` ciphers. + +The plaintext is first DES encrypted with *K1*, then decrypted with *K2*, +and finally encrypted again with *K3*. The ciphertext is decrypted in the reverse manner. + +The 192 bit key is a bundle of three 64 bit independent subkeys: *K1*, *K2*, and *K3*. + +The 128 bit key is split into *K1* and *K2*, whereas *K1=K3*. + +It is important that all subkeys are different, otherwise TDES would degrade to +single `DES`. + +TDES is cryptographically secure, even though it is neither as secure nor as fast +as `AES`. + +As an example, encryption can be done as follows: + + >>> from Crypto.Cipher import DES + >>> from Crypto import Random + >>> from Crypto.Util import Counter + >>> + >>> key = b'-8B key-' + >>> nonce = Random.new().read(DES.block_size/2) + >>> ctr = Counter.new(DES.block_size*8/2, prefix=nonce) + >>> cipher = DES.new(key, DES.MODE_CTR, counter=ctr) + >>> plaintext = b'We are no longer the knights who say ni!' + >>> msg = nonce + cipher.encrypt(plaintext) + +.. __: http://en.wikipedia.org/wiki/Triple_DES +.. _NIST: http://csrc.nist.gov/publications/nistpubs/800-67/SP800-67.pdf + +:undocumented: __revision__, __package__ +""" + +__revision__ = "$Id$" + +from Crypto.Cipher import blockalgo +from Crypto.Cipher import _DES3 + +class DES3Cipher(blockalgo.BlockAlgo): + """TDES cipher object""" + + def __init__(self, key, *args, **kwargs): + """Initialize a TDES cipher object + + See also `new()` at the module level.""" + blockalgo.BlockAlgo.__init__(self, _DES3, key, *args, **kwargs) + +def new(key, *args, **kwargs): + """Create a new TDES cipher + + :Parameters: + key : byte string + The secret key to use in the symmetric cipher. + It must be 16 or 24 bytes long. The parity bits will be ignored. + :Keywords: + mode : a *MODE_** constant + The chaining mode to use for encryption or decryption. + Default is `MODE_ECB`. + IV : byte string + The initialization vector to use for encryption or decryption. + + It is ignored for `MODE_ECB` and `MODE_CTR`. + + For `MODE_OPENPGP`, IV must be `block_size` bytes long for encryption + and `block_size` +2 bytes for decryption (in the latter case, it is + actually the *encrypted* IV which was prefixed to the ciphertext). + It is mandatory. + + For all other modes, it must be `block_size` bytes longs. It is optional and + when not present it will be given a default value of all zeroes. + counter : callable + (*Only* `MODE_CTR`). A stateful function that returns the next + *counter block*, which is a byte string of `block_size` bytes. + For better performance, use `Crypto.Util.Counter`. + segment_size : integer + (*Only* `MODE_CFB`).The number of bits the plaintext and ciphertext + are segmented in. + It must be a multiple of 8. If 0 or not specified, it will be assumed to be 8. + + :Attention: it is important that all 8 byte subkeys are different, + otherwise TDES would degrade to single `DES`. + :Return: an `DES3Cipher` object + """ + return DES3Cipher(key, *args, **kwargs) + +#: Electronic Code Book (ECB). See `blockalgo.MODE_ECB`. +MODE_ECB = 1 +#: Cipher-Block Chaining (CBC). See `blockalgo.MODE_CBC`. +MODE_CBC = 2 +#: Cipher FeedBack (CFB). See `blockalgo.MODE_CFB`. +MODE_CFB = 3 +#: This mode should not be used. +MODE_PGP = 4 +#: Output FeedBack (OFB). See `blockalgo.MODE_OFB`. +MODE_OFB = 5 +#: CounTer Mode (CTR). See `blockalgo.MODE_CTR`. +MODE_CTR = 6 +#: OpenPGP Mode. See `blockalgo.MODE_OPENPGP`. +MODE_OPENPGP = 7 +#: Size of a data block (in bytes) +block_size = 8 +#: Size of a key (in bytes) +key_size = ( 16, 24 ) diff --git a/frozen_deps/Crypto/Cipher/PKCS1_OAEP.py b/frozen_deps/Crypto/Cipher/PKCS1_OAEP.py new file mode 100644 index 0000000..2738ce3 --- /dev/null +++ b/frozen_deps/Crypto/Cipher/PKCS1_OAEP.py @@ -0,0 +1,255 @@ +# -*- coding: utf-8 -*- +# +# Cipher/PKCS1_OAEP.py : PKCS#1 OAEP +# +# =================================================================== +# The contents of this file are dedicated to the public domain. To +# the extent that dedication to the public domain is not available, +# everyone is granted a worldwide, perpetual, royalty-free, +# non-exclusive license to exercise all rights associated with the +# contents of this file for any purpose whatsoever. +# No rights are reserved. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS +# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. +# =================================================================== + +"""RSA encryption protocol according to PKCS#1 OAEP + +See RFC3447__ or the `original RSA Labs specification`__ . + +This scheme is more properly called ``RSAES-OAEP``. + +As an example, a sender may encrypt a message in this way: + + >>> from Crypto.Cipher import PKCS1_OAEP + >>> from Crypto.PublicKey import RSA + >>> + >>> message = 'To be encrypted' + >>> key = RSA.importKey(open('pubkey.der').read()) + >>> cipher = PKCS1_OAEP.new(key) + >>> ciphertext = cipher.encrypt(message) + +At the receiver side, decryption can be done using the private part of +the RSA key: + + >>> key = RSA.importKey(open('privkey.der').read()) + >>> cipher = PKCS1_OAP.new(key) + >>> message = cipher.decrypt(ciphertext) + +:undocumented: __revision__, __package__ + +.. __: http://www.ietf.org/rfc/rfc3447.txt +.. __: http://www.rsa.com/rsalabs/node.asp?id=2125. +""" + + + +__revision__ = "$Id$" +__all__ = [ 'new', 'PKCS1OAEP_Cipher' ] + +import Crypto.Signature.PKCS1_PSS +import Crypto.Hash.SHA + +from Crypto.Util.py3compat import * +import Crypto.Util.number +from Crypto.Util.number import ceil_div +from Crypto.Util.strxor import strxor + +class PKCS1OAEP_Cipher: + """This cipher can perform PKCS#1 v1.5 OAEP encryption or decryption.""" + + def __init__(self, key, hashAlgo, mgfunc, label): + """Initialize this PKCS#1 OAEP cipher object. + + :Parameters: + key : an RSA key object + If a private half is given, both encryption and decryption are possible. + If a public half is given, only encryption is possible. + hashAlgo : hash object + The hash function to use. This can be a module under `Crypto.Hash` + or an existing hash object created from any of such modules. If not specified, + `Crypto.Hash.SHA` (that is, SHA-1) is used. + mgfunc : callable + A mask generation function that accepts two parameters: a string to + use as seed, and the lenth of the mask to generate, in bytes. + If not specified, the standard MGF1 is used (a safe choice). + label : string + A label to apply to this particular encryption. If not specified, + an empty string is used. Specifying a label does not improve + security. + + :attention: Modify the mask generation function only if you know what you are doing. + Sender and receiver must use the same one. + """ + self._key = key + + if hashAlgo: + self._hashObj = hashAlgo + else: + self._hashObj = Crypto.Hash.SHA + + if mgfunc: + self._mgf = mgfunc + else: + self._mgf = lambda x,y: Crypto.Signature.PKCS1_PSS.MGF1(x,y,self._hashObj) + + self._label = label + + def can_encrypt(self): + """Return True/1 if this cipher object can be used for encryption.""" + return self._key.can_encrypt() + + def can_decrypt(self): + """Return True/1 if this cipher object can be used for decryption.""" + return self._key.can_decrypt() + + def encrypt(self, message): + """Produce the PKCS#1 OAEP encryption of a message. + + This function is named ``RSAES-OAEP-ENCRYPT``, and is specified in + section 7.1.1 of RFC3447. + + :Parameters: + message : string + The message to encrypt, also known as plaintext. It can be of + variable length, but not longer than the RSA modulus (in bytes) + minus 2, minus twice the hash output size. + + :Return: A string, the ciphertext in which the message is encrypted. + It is as long as the RSA modulus (in bytes). + :Raise ValueError: + If the RSA key length is not sufficiently long to deal with the given + message. + """ + # TODO: Verify the key is RSA + + randFunc = self._key._randfunc + + # See 7.1.1 in RFC3447 + modBits = Crypto.Util.number.size(self._key.n) + k = ceil_div(modBits,8) # Convert from bits to bytes + hLen = self._hashObj.digest_size + mLen = len(message) + + # Step 1b + ps_len = k-mLen-2*hLen-2 + if ps_len<0: + raise ValueError("Plaintext is too long.") + # Step 2a + lHash = self._hashObj.new(self._label).digest() + # Step 2b + ps = bchr(0x00)*ps_len + # Step 2c + db = lHash + ps + bchr(0x01) + message + # Step 2d + ros = randFunc(hLen) + # Step 2e + dbMask = self._mgf(ros, k-hLen-1) + # Step 2f + maskedDB = strxor(db, dbMask) + # Step 2g + seedMask = self._mgf(maskedDB, hLen) + # Step 2h + maskedSeed = strxor(ros, seedMask) + # Step 2i + em = bchr(0x00) + maskedSeed + maskedDB + # Step 3a (OS2IP), step 3b (RSAEP), part of step 3c (I2OSP) + m = self._key.encrypt(em, 0)[0] + # Complete step 3c (I2OSP) + c = bchr(0x00)*(k-len(m)) + m + return c + + def decrypt(self, ct): + """Decrypt a PKCS#1 OAEP ciphertext. + + This function is named ``RSAES-OAEP-DECRYPT``, and is specified in + section 7.1.2 of RFC3447. + + :Parameters: + ct : string + The ciphertext that contains the message to recover. + + :Return: A string, the original message. + :Raise ValueError: + If the ciphertext length is incorrect, or if the decryption does not + succeed. + :Raise TypeError: + If the RSA key has no private half. + """ + # TODO: Verify the key is RSA + + # See 7.1.2 in RFC3447 + modBits = Crypto.Util.number.size(self._key.n) + k = ceil_div(modBits,8) # Convert from bits to bytes + hLen = self._hashObj.digest_size + + # Step 1b and 1c + if len(ct) != k or k<hLen+2: + raise ValueError("Ciphertext with incorrect length.") + # Step 2a (O2SIP), 2b (RSADP), and part of 2c (I2OSP) + m = self._key.decrypt(ct) + # Complete step 2c (I2OSP) + em = bchr(0x00)*(k-len(m)) + m + # Step 3a + lHash = self._hashObj.new(self._label).digest() + # Step 3b + y = em[0] + # y must be 0, but we MUST NOT check it here in order not to + # allow attacks like Manger's (http://dl.acm.org/citation.cfm?id=704143) + maskedSeed = em[1:hLen+1] + maskedDB = em[hLen+1:] + # Step 3c + seedMask = self._mgf(maskedDB, hLen) + # Step 3d + seed = strxor(maskedSeed, seedMask) + # Step 3e + dbMask = self._mgf(seed, k-hLen-1) + # Step 3f + db = strxor(maskedDB, dbMask) + # Step 3g + valid = 1 + one = db[hLen:].find(bchr(0x01)) + lHash1 = db[:hLen] + if lHash1!=lHash: + valid = 0 + if one<0: + valid = 0 + if bord(y)!=0: + valid = 0 + if not valid: + raise ValueError("Incorrect decryption.") + # Step 4 + return db[hLen+one+1:] + +def new(key, hashAlgo=None, mgfunc=None, label=b('')): + """Return a cipher object `PKCS1OAEP_Cipher` that can be used to perform PKCS#1 OAEP encryption or decryption. + + :Parameters: + key : RSA key object + The key to use to encrypt or decrypt the message. This is a `Crypto.PublicKey.RSA` object. + Decryption is only possible if *key* is a private RSA key. + hashAlgo : hash object + The hash function to use. This can be a module under `Crypto.Hash` + or an existing hash object created from any of such modules. If not specified, + `Crypto.Hash.SHA` (that is, SHA-1) is used. + mgfunc : callable + A mask generation function that accepts two parameters: a string to + use as seed, and the lenth of the mask to generate, in bytes. + If not specified, the standard MGF1 is used (a safe choice). + label : string + A label to apply to this particular encryption. If not specified, + an empty string is used. Specifying a label does not improve + security. + + :attention: Modify the mask generation function only if you know what you are doing. + Sender and receiver must use the same one. + """ + return PKCS1OAEP_Cipher(key, hashAlgo, mgfunc, label) + diff --git a/frozen_deps/Crypto/Cipher/PKCS1_v1_5.py b/frozen_deps/Crypto/Cipher/PKCS1_v1_5.py new file mode 100644 index 0000000..3602cb0 --- /dev/null +++ b/frozen_deps/Crypto/Cipher/PKCS1_v1_5.py @@ -0,0 +1,226 @@ +# -*- coding: utf-8 -*- +# +# Cipher/PKCS1-v1_5.py : PKCS#1 v1.5 +# +# =================================================================== +# The contents of this file are dedicated to the public domain. To +# the extent that dedication to the public domain is not available, +# everyone is granted a worldwide, perpetual, royalty-free, +# non-exclusive license to exercise all rights associated with the +# contents of this file for any purpose whatsoever. +# No rights are reserved. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS +# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. +# =================================================================== + +"""RSA encryption protocol according to PKCS#1 v1.5 + +See RFC3447__ or the `original RSA Labs specification`__ . + +This scheme is more properly called ``RSAES-PKCS1-v1_5``. + +**If you are designing a new protocol, consider using the more robust PKCS#1 OAEP.** + +As an example, a sender may encrypt a message in this way: + + >>> from Crypto.Cipher import PKCS1_v1_5 + >>> from Crypto.PublicKey import RSA + >>> from Crypto.Hash import SHA + >>> + >>> message = 'To be encrypted' + >>> h = SHA.new(message) + >>> + >>> key = RSA.importKey(open('pubkey.der').read()) + >>> cipher = PKCS1_v1_5.new(key) + >>> ciphertext = cipher.encrypt(message+h.digest()) + +At the receiver side, decryption can be done using the private part of +the RSA key: + + >>> From Crypto.Hash import SHA + >>> from Crypto import Random + >>> + >>> key = RSA.importKey(open('privkey.der').read()) + >>> + >>> dsize = SHA.digest_size + >>> sentinel = Random.new().read(15+dsize) # Let's assume that average data length is 15 + >>> + >>> cipher = PKCS1_v1_5.new(key) + >>> message = cipher.decrypt(ciphertext, sentinel) + >>> + >>> digest = SHA.new(message[:-dsize]).digest() + >>> if digest==message[-dsize:]: # Note how we DO NOT look for the sentinel + >>> print "Encryption was correct." + >>> else: + >>> print "Encryption was not correct." + +:undocumented: __revision__, __package__ + +.. __: http://www.ietf.org/rfc/rfc3447.txt +.. __: http://www.rsa.com/rsalabs/node.asp?id=2125. +""" + +__revision__ = "$Id$" +__all__ = [ 'new', 'PKCS115_Cipher' ] + +from Crypto.Util.number import ceil_div +from Crypto.Util.py3compat import * +import Crypto.Util.number + +class PKCS115_Cipher: + """This cipher can perform PKCS#1 v1.5 RSA encryption or decryption.""" + + def __init__(self, key): + """Initialize this PKCS#1 v1.5 cipher object. + + :Parameters: + key : an RSA key object + If a private half is given, both encryption and decryption are possible. + If a public half is given, only encryption is possible. + """ + self._key = key + + def can_encrypt(self): + """Return True if this cipher object can be used for encryption.""" + return self._key.can_encrypt() + + def can_decrypt(self): + """Return True if this cipher object can be used for decryption.""" + return self._key.can_decrypt() + + def encrypt(self, message): + """Produce the PKCS#1 v1.5 encryption of a message. + + This function is named ``RSAES-PKCS1-V1_5-ENCRYPT``, and is specified in + section 7.2.1 of RFC3447. + For a complete example see `Crypto.Cipher.PKCS1_v1_5`. + + :Parameters: + message : byte string + The message to encrypt, also known as plaintext. It can be of + variable length, but not longer than the RSA modulus (in bytes) minus 11. + + :Return: A byte string, the ciphertext in which the message is encrypted. + It is as long as the RSA modulus (in bytes). + :Raise ValueError: + If the RSA key length is not sufficiently long to deal with the given + message. + + """ + # TODO: Verify the key is RSA + + randFunc = self._key._randfunc + + # See 7.2.1 in RFC3447 + modBits = Crypto.Util.number.size(self._key.n) + k = ceil_div(modBits,8) # Convert from bits to bytes + mLen = len(message) + + # Step 1 + if mLen > k-11: + raise ValueError("Plaintext is too long.") + # Step 2a + class nonZeroRandByte: + def __init__(self, rf): self.rf=rf + def __call__(self, c): + while bord(c)==0x00: c=self.rf(1)[0] + return c + ps = tobytes(list(map(nonZeroRandByte(randFunc), randFunc(k-mLen-3)))) + # Step 2b + em = b('\x00\x02') + ps + bchr(0x00) + message + # Step 3a (OS2IP), step 3b (RSAEP), part of step 3c (I2OSP) + m = self._key.encrypt(em, 0)[0] + # Complete step 3c (I2OSP) + c = bchr(0x00)*(k-len(m)) + m + return c + + def decrypt(self, ct, sentinel): + """Decrypt a PKCS#1 v1.5 ciphertext. + + This function is named ``RSAES-PKCS1-V1_5-DECRYPT``, and is specified in + section 7.2.2 of RFC3447. + For a complete example see `Crypto.Cipher.PKCS1_v1_5`. + + :Parameters: + ct : byte string + The ciphertext that contains the message to recover. + sentinel : any type + The object to return to indicate that an error was detected during decryption. + + :Return: A byte string. It is either the original message or the ``sentinel`` (in case of an error). + :Raise ValueError: + If the ciphertext length is incorrect + :Raise TypeError: + If the RSA key has no private half. + + :attention: + You should **never** let the party who submitted the ciphertext know that + this function returned the ``sentinel`` value. + Armed with such knowledge (for a fair amount of carefully crafted but invalid ciphertexts), + an attacker is able to recontruct the plaintext of any other encryption that were carried out + with the same RSA public key (see `Bleichenbacher's`__ attack). + + In general, it should not be possible for the other party to distinguish + whether processing at the server side failed because the value returned + was a ``sentinel`` as opposed to a random, invalid message. + + In fact, the second option is not that unlikely: encryption done according to PKCS#1 v1.5 + embeds no good integrity check. There is roughly one chance + in 2^16 for a random ciphertext to be returned as a valid message + (although random looking). + + It is therefore advisabled to: + + 1. Select as ``sentinel`` a value that resembles a plausable random, invalid message. + 2. Not report back an error as soon as you detect a ``sentinel`` value. + Put differently, you should not explicitly check if the returned value is the ``sentinel`` or not. + 3. Cover all possible errors with a single, generic error indicator. + 4. Embed into the definition of ``message`` (at the protocol level) a digest (e.g. ``SHA-1``). + It is recommended for it to be the rightmost part ``message``. + 5. Where possible, monitor the number of errors due to ciphertexts originating from the same party, + and slow down the rate of the requests from such party (or even blacklist it altogether). + + **If you are designing a new protocol, consider using the more robust PKCS#1 OAEP.** + + .. __: http://www.bell-labs.com/user/bleichen/papers/pkcs.ps + + """ + + # TODO: Verify the key is RSA + + # See 7.2.1 in RFC3447 + modBits = Crypto.Util.number.size(self._key.n) + k = ceil_div(modBits,8) # Convert from bits to bytes + + # Step 1 + if len(ct) != k: + raise ValueError("Ciphertext with incorrect length.") + # Step 2a (O2SIP), 2b (RSADP), and part of 2c (I2OSP) + m = self._key.decrypt(ct) + # Complete step 2c (I2OSP) + em = bchr(0x00)*(k-len(m)) + m + # Step 3 + sep = em.find(bchr(0x00),2) + if not em.startswith(b('\x00\x02')) or sep<10: + return sentinel + # Step 4 + return em[sep+1:] + +def new(key): + """Return a cipher object `PKCS115_Cipher` that can be used to perform PKCS#1 v1.5 encryption or decryption. + + :Parameters: + key : RSA key object + The key to use to encrypt or decrypt the message. This is a `Crypto.PublicKey.RSA` object. + Decryption is only possible if *key* is a private RSA key. + + """ + return PKCS115_Cipher(key) + diff --git a/frozen_deps/Crypto/Cipher/XOR.py b/frozen_deps/Crypto/Cipher/XOR.py new file mode 100644 index 0000000..46b8464 --- /dev/null +++ b/frozen_deps/Crypto/Cipher/XOR.py @@ -0,0 +1,86 @@ +# -*- coding: utf-8 -*- +# +# Cipher/XOR.py : XOR +# +# =================================================================== +# The contents of this file are dedicated to the public domain. To +# the extent that dedication to the public domain is not available, +# everyone is granted a worldwide, perpetual, royalty-free, +# non-exclusive license to exercise all rights associated with the +# contents of this file for any purpose whatsoever. +# No rights are reserved. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS +# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. +# =================================================================== +"""XOR toy cipher + +XOR is one the simplest stream ciphers. Encryption and decryption are +performed by XOR-ing data with a keystream made by contatenating +the key. + +Do not use it for real applications! + +:undocumented: __revision__, __package__ +""" + +__revision__ = "$Id$" + +from Crypto.Cipher import _XOR + +class XORCipher: + """XOR cipher object""" + + def __init__(self, key, *args, **kwargs): + """Initialize a XOR cipher object + + See also `new()` at the module level.""" + self._cipher = _XOR.new(key, *args, **kwargs) + self.block_size = self._cipher.block_size + self.key_size = self._cipher.key_size + + def encrypt(self, plaintext): + """Encrypt a piece of data. + + :Parameters: + plaintext : byte string + The piece of data to encrypt. It can be of any size. + :Return: the encrypted data (byte string, as long as the + plaintext). + """ + return self._cipher.encrypt(plaintext) + + def decrypt(self, ciphertext): + """Decrypt a piece of data. + + :Parameters: + ciphertext : byte string + The piece of data to decrypt. It can be of any size. + :Return: the decrypted data (byte string, as long as the + ciphertext). + """ + return self._cipher.decrypt(ciphertext) + +def new(key, *args, **kwargs): + """Create a new XOR cipher + + :Parameters: + key : byte string + The secret key to use in the symmetric cipher. + Its length may vary from 1 to 32 bytes. + + :Return: an `XORCipher` object + """ + return XORCipher(key, *args, **kwargs) + +#: Size of a data block (in bytes) +block_size = 1 +#: Size of a key (in bytes) +key_size = range(1,32+1) + diff --git a/frozen_deps/Crypto/Cipher/_AES.cpython-38-x86_64-linux-gnu.so b/frozen_deps/Crypto/Cipher/_AES.cpython-38-x86_64-linux-gnu.so Binary files differnew file mode 100755 index 0000000..e9ffeb9 --- /dev/null +++ b/frozen_deps/Crypto/Cipher/_AES.cpython-38-x86_64-linux-gnu.so diff --git a/frozen_deps/Crypto/Cipher/_ARC2.cpython-38-x86_64-linux-gnu.so b/frozen_deps/Crypto/Cipher/_ARC2.cpython-38-x86_64-linux-gnu.so Binary files differnew file mode 100755 index 0000000..b325488 --- /dev/null +++ b/frozen_deps/Crypto/Cipher/_ARC2.cpython-38-x86_64-linux-gnu.so diff --git a/frozen_deps/Crypto/Cipher/_ARC4.cpython-38-x86_64-linux-gnu.so b/frozen_deps/Crypto/Cipher/_ARC4.cpython-38-x86_64-linux-gnu.so Binary files differnew file mode 100755 index 0000000..982a28d --- /dev/null +++ b/frozen_deps/Crypto/Cipher/_ARC4.cpython-38-x86_64-linux-gnu.so diff --git a/frozen_deps/Crypto/Cipher/_Blowfish.cpython-38-x86_64-linux-gnu.so b/frozen_deps/Crypto/Cipher/_Blowfish.cpython-38-x86_64-linux-gnu.so Binary files differnew file mode 100755 index 0000000..2648636 --- /dev/null +++ b/frozen_deps/Crypto/Cipher/_Blowfish.cpython-38-x86_64-linux-gnu.so diff --git a/frozen_deps/Crypto/Cipher/_CAST.cpython-38-x86_64-linux-gnu.so b/frozen_deps/Crypto/Cipher/_CAST.cpython-38-x86_64-linux-gnu.so Binary files differnew file mode 100755 index 0000000..439731a --- /dev/null +++ b/frozen_deps/Crypto/Cipher/_CAST.cpython-38-x86_64-linux-gnu.so diff --git a/frozen_deps/Crypto/Cipher/_DES.cpython-38-x86_64-linux-gnu.so b/frozen_deps/Crypto/Cipher/_DES.cpython-38-x86_64-linux-gnu.so Binary files differnew file mode 100755 index 0000000..e025c0d --- /dev/null +++ b/frozen_deps/Crypto/Cipher/_DES.cpython-38-x86_64-linux-gnu.so diff --git a/frozen_deps/Crypto/Cipher/_DES3.cpython-38-x86_64-linux-gnu.so b/frozen_deps/Crypto/Cipher/_DES3.cpython-38-x86_64-linux-gnu.so Binary files differnew file mode 100755 index 0000000..faef3f9 --- /dev/null +++ b/frozen_deps/Crypto/Cipher/_DES3.cpython-38-x86_64-linux-gnu.so diff --git a/frozen_deps/Crypto/Cipher/_XOR.cpython-38-x86_64-linux-gnu.so b/frozen_deps/Crypto/Cipher/_XOR.cpython-38-x86_64-linux-gnu.so Binary files differnew file mode 100755 index 0000000..43f0560 --- /dev/null +++ b/frozen_deps/Crypto/Cipher/_XOR.cpython-38-x86_64-linux-gnu.so diff --git a/frozen_deps/Crypto/Cipher/__init__.py b/frozen_deps/Crypto/Cipher/__init__.py new file mode 100644 index 0000000..7afed2d --- /dev/null +++ b/frozen_deps/Crypto/Cipher/__init__.py @@ -0,0 +1,83 @@ +# -*- coding: utf-8 -*- +# +# =================================================================== +# The contents of this file are dedicated to the public domain. To +# the extent that dedication to the public domain is not available, +# everyone is granted a worldwide, perpetual, royalty-free, +# non-exclusive license to exercise all rights associated with the +# contents of this file for any purpose whatsoever. +# No rights are reserved. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS +# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. +# =================================================================== + +"""Symmetric- and asymmetric-key encryption algorithms. + +Encryption algorithms transform plaintext in some way that +is dependent on a key or key pair, producing ciphertext. + +Symmetric algorithms +-------------------- + +Encryption can easily be reversed, if (and, hopefully, only if) +one knows the same key. +In other words, sender and receiver share the same key. + +The symmetric encryption modules here all support the interface described in PEP +272, "API for Block Encryption Algorithms". + +If you don't know which algorithm to choose, use AES because it's +standard and has undergone a fair bit of examination. + +======================== ======= ======================== +Module name Type Description +======================== ======= ======================== +`Crypto.Cipher.AES` Block Advanced Encryption Standard +`Crypto.Cipher.ARC2` Block Alleged RC2 +`Crypto.Cipher.ARC4` Stream Alleged RC4 +`Crypto.Cipher.Blowfish` Block Blowfish +`Crypto.Cipher.CAST` Block CAST +`Crypto.Cipher.DES` Block The Data Encryption Standard. + Very commonly used in the past, + but today its 56-bit keys are too small. +`Crypto.Cipher.DES3` Block Triple DES. +`Crypto.Cipher.XOR` Stream The simple XOR cipher. +======================== ======= ======================== + + +Asymmetric algorithms +--------------------- + +For asymmetric algorithms, the key to be used for decryption is totally +different and cannot be derived in a feasible way from the key used +for encryption. Put differently, sender and receiver each own one half +of a key pair. The encryption key is often called ``public`` whereas +the decryption key is called ``private``. + +========================== ======================= +Module name Description +========================== ======================= +`Crypto.Cipher.PKCS1_v1_5` PKCS#1 v1.5 encryption, based on RSA key pairs +`Crypto.Cipher.PKCS1_OAEP` PKCS#1 OAEP encryption, based on RSA key pairs +========================== ======================= + +:undocumented: __revision__, __package__, _AES, _ARC2, _ARC4, _Blowfish + _CAST, _DES, _DES3, _XOR +""" + +__all__ = ['AES', 'ARC2', 'ARC4', + 'Blowfish', 'CAST', 'DES', 'DES3', + 'XOR', + 'PKCS1_v1_5', 'PKCS1_OAEP' + ] + +__revision__ = "$Id$" + + diff --git a/frozen_deps/Crypto/Cipher/blockalgo.py b/frozen_deps/Crypto/Cipher/blockalgo.py new file mode 100644 index 0000000..dd183dc --- /dev/null +++ b/frozen_deps/Crypto/Cipher/blockalgo.py @@ -0,0 +1,296 @@ +# -*- coding: utf-8 -*- +# +# Cipher/blockalgo.py +# +# =================================================================== +# The contents of this file are dedicated to the public domain. To +# the extent that dedication to the public domain is not available, +# everyone is granted a worldwide, perpetual, royalty-free, +# non-exclusive license to exercise all rights associated with the +# contents of this file for any purpose whatsoever. +# No rights are reserved. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS +# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. +# =================================================================== +"""Module with definitions common to all block ciphers.""" + +import sys +if sys.version_info[0] == 2 and sys.version_info[1] == 1: + from Crypto.Util.py21compat import * +from Crypto.Util.py3compat import * + +#: *Electronic Code Book (ECB)*. +#: This is the simplest encryption mode. Each of the plaintext blocks +#: is directly encrypted into a ciphertext block, independently of +#: any other block. This mode exposes frequency of symbols +#: in your plaintext. Other modes (e.g. *CBC*) should be used instead. +#: +#: See `NIST SP800-38A`_ , Section 6.1 . +#: +#: .. _`NIST SP800-38A` : http://csrc.nist.gov/publications/nistpubs/800-38a/sp800-38a.pdf +MODE_ECB = 1 + +#: *Cipher-Block Chaining (CBC)*. Each of the ciphertext blocks depends +#: on the current and all previous plaintext blocks. An Initialization Vector +#: (*IV*) is required. +#: +#: The *IV* is a data block to be transmitted to the receiver. +#: The *IV* can be made public, but it must be authenticated by the receiver and +#: it should be picked randomly. +#: +#: See `NIST SP800-38A`_ , Section 6.2 . +#: +#: .. _`NIST SP800-38A` : http://csrc.nist.gov/publications/nistpubs/800-38a/sp800-38a.pdf +MODE_CBC = 2 + +#: *Cipher FeedBack (CFB)*. This mode is similar to CBC, but it transforms +#: the underlying block cipher into a stream cipher. Plaintext and ciphertext +#: are processed in *segments* of **s** bits. The mode is therefore sometimes +#: labelled **s**-bit CFB. An Initialization Vector (*IV*) is required. +#: +#: When encrypting, each ciphertext segment contributes to the encryption of +#: the next plaintext segment. +#: +#: This *IV* is a data block to be transmitted to the receiver. +#: The *IV* can be made public, but it should be picked randomly. +#: Reusing the same *IV* for encryptions done with the same key lead to +#: catastrophic cryptographic failures. +#: +#: See `NIST SP800-38A`_ , Section 6.3 . +#: +#: .. _`NIST SP800-38A` : http://csrc.nist.gov/publications/nistpubs/800-38a/sp800-38a.pdf +MODE_CFB = 3 + +#: This mode should not be used. +MODE_PGP = 4 + +#: *Output FeedBack (OFB)*. This mode is very similar to CBC, but it +#: transforms the underlying block cipher into a stream cipher. +#: The keystream is the iterated block encryption of an Initialization Vector (*IV*). +#: +#: The *IV* is a data block to be transmitted to the receiver. +#: The *IV* can be made public, but it should be picked randomly. +#: +#: Reusing the same *IV* for encryptions done with the same key lead to +#: catastrophic cryptograhic failures. +#: +#: See `NIST SP800-38A`_ , Section 6.4 . +#: +#: .. _`NIST SP800-38A` : http://csrc.nist.gov/publications/nistpubs/800-38a/sp800-38a.pdf +MODE_OFB = 5 + +#: *CounTeR (CTR)*. This mode is very similar to ECB, in that +#: encryption of one block is done independently of all other blocks. +#: Unlike ECB, the block *position* contributes to the encryption and no +#: information leaks about symbol frequency. +#: +#: Each message block is associated to a *counter* which must be unique +#: across all messages that get encrypted with the same key (not just within +#: the same message). The counter is as big as the block size. +#: +#: Counters can be generated in several ways. The most straightword one is +#: to choose an *initial counter block* (which can be made public, similarly +#: to the *IV* for the other modes) and increment its lowest **m** bits by +#: one (modulo *2^m*) for each block. In most cases, **m** is chosen to be half +#: the block size. +#: +#: Reusing the same *initial counter block* for encryptions done with the same +#: key lead to catastrophic cryptograhic failures. +#: +#: See `NIST SP800-38A`_ , Section 6.5 (for the mode) and Appendix B (for how +#: to manage the *initial counter block*). +#: +#: .. _`NIST SP800-38A` : http://csrc.nist.gov/publications/nistpubs/800-38a/sp800-38a.pdf +MODE_CTR = 6 + +#: OpenPGP. This mode is a variant of CFB, and it is only used in PGP and OpenPGP_ applications. +#: An Initialization Vector (*IV*) is required. +#: +#: Unlike CFB, the IV is not transmitted to the receiver. Instead, the *encrypted* IV is. +#: The IV is a random data block. Two of its bytes are duplicated to act as a checksum +#: for the correctness of the key. The encrypted IV is therefore 2 bytes longer than +#: the clean IV. +#: +#: .. _OpenPGP: http://tools.ietf.org/html/rfc4880 +MODE_OPENPGP = 7 + +def _getParameter(name, index, args, kwargs, default=None): + """Find a parameter in tuple and dictionary arguments a function receives""" + param = kwargs.get(name) + if len(args)>index: + if param: + raise ValueError("Parameter '%s' is specified twice" % name) + param = args[index] + return param or default + +class BlockAlgo: + """Class modelling an abstract block cipher.""" + + def __init__(self, factory, key, *args, **kwargs): + self.mode = _getParameter('mode', 0, args, kwargs, default=MODE_ECB) + self.block_size = factory.block_size + + if self.mode != MODE_OPENPGP: + self._cipher = factory.new(key, *args, **kwargs) + self.IV = self._cipher.IV + else: + # OPENPGP mode. For details, see 13.9 in RCC4880. + # + # A few members are specifically created for this mode: + # - _encrypted_iv, set in this constructor + # - _done_first_block, set to True after the first encryption + # - _done_last_block, set to True after a partial block is processed + + self._done_first_block = False + self._done_last_block = False + self.IV = _getParameter('iv', 1, args, kwargs) + if not self.IV: + raise ValueError("MODE_OPENPGP requires an IV") + + # Instantiate a temporary cipher to process the IV + IV_cipher = factory.new(key, MODE_CFB, + b('\x00')*self.block_size, # IV for CFB + segment_size=self.block_size*8) + + # The cipher will be used for... + if len(self.IV) == self.block_size: + # ... encryption + self._encrypted_IV = IV_cipher.encrypt( + self.IV + self.IV[-2:] + # Plaintext + b('\x00')*(self.block_size-2) # Padding + )[:self.block_size+2] + elif len(self.IV) == self.block_size+2: + # ... decryption + self._encrypted_IV = self.IV + self.IV = IV_cipher.decrypt(self.IV + # Ciphertext + b('\x00')*(self.block_size-2) # Padding + )[:self.block_size+2] + if self.IV[-2:] != self.IV[-4:-2]: + raise ValueError("Failed integrity check for OPENPGP IV") + self.IV = self.IV[:-2] + else: + raise ValueError("Length of IV must be %d or %d bytes for MODE_OPENPGP" + % (self.block_size, self.block_size+2)) + + # Instantiate the cipher for the real PGP data + self._cipher = factory.new(key, MODE_CFB, + self._encrypted_IV[-self.block_size:], + segment_size=self.block_size*8) + + def encrypt(self, plaintext): + """Encrypt data with the key and the parameters set at initialization. + + The cipher object is stateful; encryption of a long block + of data can be broken up in two or more calls to `encrypt()`. + That is, the statement: + + >>> c.encrypt(a) + c.encrypt(b) + + is always equivalent to: + + >>> c.encrypt(a+b) + + That also means that you cannot reuse an object for encrypting + or decrypting other data with the same key. + + This function does not perform any padding. + + - For `MODE_ECB`, `MODE_CBC`, and `MODE_OFB`, *plaintext* length + (in bytes) must be a multiple of *block_size*. + + - For `MODE_CFB`, *plaintext* length (in bytes) must be a multiple + of *segment_size*/8. + + - For `MODE_CTR`, *plaintext* can be of any length. + + - For `MODE_OPENPGP`, *plaintext* must be a multiple of *block_size*, + unless it is the last chunk of the message. + + :Parameters: + plaintext : byte string + The piece of data to encrypt. + :Return: + the encrypted data, as a byte string. It is as long as + *plaintext* with one exception: when encrypting the first message + chunk with `MODE_OPENPGP`, the encypted IV is prepended to the + returned ciphertext. + """ + + if self.mode == MODE_OPENPGP: + padding_length = (self.block_size - len(plaintext) % self.block_size) % self.block_size + if padding_length>0: + # CFB mode requires ciphertext to have length multiple of block size, + # but PGP mode allows the last block to be shorter + if self._done_last_block: + raise ValueError("Only the last chunk is allowed to have length not multiple of %d bytes", + self.block_size) + self._done_last_block = True + padded = plaintext + b('\x00')*padding_length + res = self._cipher.encrypt(padded)[:len(plaintext)] + else: + res = self._cipher.encrypt(plaintext) + if not self._done_first_block: + res = self._encrypted_IV + res + self._done_first_block = True + return res + + return self._cipher.encrypt(plaintext) + + def decrypt(self, ciphertext): + """Decrypt data with the key and the parameters set at initialization. + + The cipher object is stateful; decryption of a long block + of data can be broken up in two or more calls to `decrypt()`. + That is, the statement: + + >>> c.decrypt(a) + c.decrypt(b) + + is always equivalent to: + + >>> c.decrypt(a+b) + + That also means that you cannot reuse an object for encrypting + or decrypting other data with the same key. + + This function does not perform any padding. + + - For `MODE_ECB`, `MODE_CBC`, and `MODE_OFB`, *ciphertext* length + (in bytes) must be a multiple of *block_size*. + + - For `MODE_CFB`, *ciphertext* length (in bytes) must be a multiple + of *segment_size*/8. + + - For `MODE_CTR`, *ciphertext* can be of any length. + + - For `MODE_OPENPGP`, *plaintext* must be a multiple of *block_size*, + unless it is the last chunk of the message. + + :Parameters: + ciphertext : byte string + The piece of data to decrypt. + :Return: the decrypted data (byte string, as long as *ciphertext*). + """ + if self.mode == MODE_OPENPGP: + padding_length = (self.block_size - len(ciphertext) % self.block_size) % self.block_size + if padding_length>0: + # CFB mode requires ciphertext to have length multiple of block size, + # but PGP mode allows the last block to be shorter + if self._done_last_block: + raise ValueError("Only the last chunk is allowed to have length not multiple of %d bytes", + self.block_size) + self._done_last_block = True + padded = ciphertext + b('\x00')*padding_length + res = self._cipher.decrypt(padded)[:len(ciphertext)] + else: + res = self._cipher.decrypt(ciphertext) + return res + + return self._cipher.decrypt(ciphertext) + |