tools v3.0
First combined mobi/topaz kindle tool
This commit is contained in:
@@ -45,6 +45,8 @@
|
||||
# - Incorporated SomeUpdates zipfix routine.
|
||||
# 0.1.2 - Removed Carbon dependency for Mac users. Fixes an issue that was a
|
||||
# result of Calibre changing to python 2.7.
|
||||
# 0.1.3 - bug fix for epubs with non-ascii chars in file names
|
||||
|
||||
|
||||
|
||||
"""
|
||||
@@ -308,6 +310,7 @@ class Decryptor(object):
|
||||
enc('CipherReference'))
|
||||
for elem in encryption.findall(expr):
|
||||
path = elem.get('URI', None)
|
||||
path = path.encode('utf-8')
|
||||
if path is not None:
|
||||
encrypted.add(path)
|
||||
|
||||
@@ -365,7 +368,7 @@ class IneptDeDRM(FileTypePlugin):
|
||||
Credit given to I <3 Cabbages for the original stand-alone scripts.'
|
||||
supported_platforms = ['linux', 'osx', 'windows']
|
||||
author = 'DiapDealer'
|
||||
version = (0, 1, 2)
|
||||
version = (0, 1, 3)
|
||||
minimum_calibre_version = (0, 6, 44) # Compiled python libraries cannot be imported in earlier versions.
|
||||
file_types = set(['epub'])
|
||||
on_import = True
|
||||
@@ -379,17 +382,10 @@ class IneptDeDRM(FileTypePlugin):
|
||||
from PyQt4.Qt import QMessageBox
|
||||
from calibre.constants import iswindows, isosx
|
||||
|
||||
# Add the included pycrypto import directory for Windows users.
|
||||
# Add the included Carbon import directory for Mac users.
|
||||
pdir = 'windows' if iswindows else 'osx' if isosx else 'linux'
|
||||
ppath = os.path.join(self.sys_insertion_path, pdir)
|
||||
sys.path.append(ppath)
|
||||
|
||||
AES, RSA = _load_crypto()
|
||||
|
||||
if AES == None or RSA == None:
|
||||
# Failed to load libcrypto or PyCrypto... Adobe Epubs can\'t be decrypted.'
|
||||
sys.path.remove(ppath)
|
||||
raise ADEPTError('IneptEpub: Failed to load crypto libs... Adobe Epubs can\'t be decrypted.')
|
||||
return
|
||||
|
||||
@@ -432,7 +428,6 @@ class IneptDeDRM(FileTypePlugin):
|
||||
|
||||
if not userkeys:
|
||||
# No user keys found... bail out.
|
||||
sys.path.remove(ppath)
|
||||
raise ADEPTError('IneptEpub - No keys found. Check keyfile(s)/ADE install')
|
||||
return
|
||||
|
||||
@@ -458,7 +453,6 @@ class IneptDeDRM(FileTypePlugin):
|
||||
if result == 1:
|
||||
print 'IneptEpub: Not an Adobe Adept Epub... punting.'
|
||||
of.close()
|
||||
sys.path.remove(ppath)
|
||||
return path_to_ebook
|
||||
break
|
||||
|
||||
@@ -467,7 +461,6 @@ class IneptDeDRM(FileTypePlugin):
|
||||
if result == 0:
|
||||
print 'IneptEpub: Encryption successfully removed.'
|
||||
of.close
|
||||
sys.path.remove(ppath)
|
||||
return of.name
|
||||
break
|
||||
|
||||
@@ -477,7 +470,6 @@ class IneptDeDRM(FileTypePlugin):
|
||||
# Something went wrong with decryption.
|
||||
# Import the original unmolested epub.
|
||||
of.close
|
||||
sys.path.remove(ppath)
|
||||
raise ADEPTError('IneptEpub - Ultimately failed to decrypt')
|
||||
return
|
||||
|
||||
|
||||
Binary file not shown.
@@ -1,51 +0,0 @@
|
||||
# -*- 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.
|
||||
# ===================================================================
|
||||
|
||||
"""Secret-key encryption algorithms.
|
||||
|
||||
Secret-key encryption algorithms transform plaintext in some way that
|
||||
is dependent on a key, producing ciphertext. This transformation can
|
||||
easily be reversed, if (and, hopefully, only if) one knows the key.
|
||||
|
||||
The 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.
|
||||
|
||||
Crypto.Cipher.AES Advanced Encryption Standard
|
||||
Crypto.Cipher.ARC2 Alleged RC2
|
||||
Crypto.Cipher.ARC4 Alleged RC4
|
||||
Crypto.Cipher.Blowfish
|
||||
Crypto.Cipher.CAST
|
||||
Crypto.Cipher.DES The Data Encryption Standard. Very commonly used
|
||||
in the past, but today its 56-bit keys are too small.
|
||||
Crypto.Cipher.DES3 Triple DES.
|
||||
Crypto.Cipher.XOR The simple XOR cipher.
|
||||
"""
|
||||
|
||||
__all__ = ['AES', 'ARC2', 'ARC4',
|
||||
'Blowfish', 'CAST', 'DES', 'DES3',
|
||||
'XOR'
|
||||
]
|
||||
|
||||
__revision__ = "$Id$"
|
||||
|
||||
|
||||
Binary file not shown.
@@ -1,44 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# ===================================================================
|
||||
# The contents of this file are dedicated to the public domain. To
|
||||
# the extent that dedication to the public domain is not available,
|
||||
# everyone is granted a worldwide, perpetual, royalty-free,
|
||||
# non-exclusive license to exercise all rights associated with the
|
||||
# contents of this file for any purpose whatsoever.
|
||||
# No rights are reserved.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
# SOFTWARE.
|
||||
# ===================================================================
|
||||
|
||||
"""Hashing algorithms
|
||||
|
||||
Hash functions take arbitrary strings as input, and produce an output
|
||||
of fixed size that is dependent on the input; it should never be
|
||||
possible to derive the input data given only the hash function's
|
||||
output. Hash functions can be used simply as a checksum, or, in
|
||||
association with a public-key algorithm, can be used to implement
|
||||
digital signatures.
|
||||
|
||||
The hashing modules here all support the interface described in PEP
|
||||
247, "API for Cryptographic Hash Functions".
|
||||
|
||||
Submodules:
|
||||
Crypto.Hash.HMAC RFC 2104: Keyed-Hashing for Message Authentication
|
||||
Crypto.Hash.MD2
|
||||
Crypto.Hash.MD4
|
||||
Crypto.Hash.MD5
|
||||
Crypto.Hash.RIPEMD160
|
||||
Crypto.Hash.SHA
|
||||
"""
|
||||
|
||||
__all__ = ['HMAC', 'MD2', 'MD4', 'MD5', 'RIPEMD', 'RIPEMD160', 'SHA', 'SHA256']
|
||||
__revision__ = "$Id$"
|
||||
|
||||
@@ -1,184 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# PublicKey/RSA.py : RSA public key primitive
|
||||
#
|
||||
# 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.
|
||||
# ===================================================================
|
||||
|
||||
"""RSA public-key cryptography algorithm."""
|
||||
|
||||
__revision__ = "$Id$"
|
||||
|
||||
__all__ = ['generate', 'construct', 'error']
|
||||
|
||||
from Crypto.Util.python_compat import *
|
||||
|
||||
from Crypto.PublicKey import _RSA, _slowmath, pubkey
|
||||
from Crypto import Random
|
||||
|
||||
try:
|
||||
from Crypto.PublicKey import _fastmath
|
||||
except ImportError:
|
||||
_fastmath = None
|
||||
|
||||
class _RSAobj(pubkey.pubkey):
|
||||
keydata = ['n', 'e', 'd', 'p', 'q', 'u']
|
||||
|
||||
def __init__(self, implementation, key):
|
||||
self.implementation = implementation
|
||||
self.key = key
|
||||
|
||||
def __getattr__(self, attrname):
|
||||
if attrname in self.keydata:
|
||||
# For backward compatibility, allow the user to get (not set) the
|
||||
# RSA key parameters directly from this object.
|
||||
return getattr(self.key, attrname)
|
||||
else:
|
||||
raise AttributeError("%s object has no %r attribute" % (self.__class__.__name__, attrname,))
|
||||
|
||||
def _encrypt(self, c, K):
|
||||
return (self.key._encrypt(c),)
|
||||
|
||||
def _decrypt(self, c):
|
||||
#(ciphertext,) = c
|
||||
(ciphertext,) = c[:1] # HACK - We should use the previous line
|
||||
# instead, but this is more compatible and we're
|
||||
# going to replace the Crypto.PublicKey API soon
|
||||
# anyway.
|
||||
return self.key._decrypt(ciphertext)
|
||||
|
||||
def _blind(self, m, r):
|
||||
return self.key._blind(m, r)
|
||||
|
||||
def _unblind(self, m, r):
|
||||
return self.key._unblind(m, r)
|
||||
|
||||
def _sign(self, m, K=None):
|
||||
return (self.key._sign(m),)
|
||||
|
||||
def _verify(self, m, sig):
|
||||
#(s,) = sig
|
||||
(s,) = sig[:1] # HACK - We should use the previous line instead, but
|
||||
# this is more compatible and we're going to replace
|
||||
# the Crypto.PublicKey API soon anyway.
|
||||
return self.key._verify(m, s)
|
||||
|
||||
def has_private(self):
|
||||
return self.key.has_private()
|
||||
|
||||
def size(self):
|
||||
return self.key.size()
|
||||
|
||||
def can_blind(self):
|
||||
return True
|
||||
|
||||
def can_encrypt(self):
|
||||
return True
|
||||
|
||||
def can_sign(self):
|
||||
return True
|
||||
|
||||
def publickey(self):
|
||||
return self.implementation.construct((self.key.n, self.key.e))
|
||||
|
||||
def __getstate__(self):
|
||||
d = {}
|
||||
for k in self.keydata:
|
||||
try:
|
||||
d[k] = getattr(self.key, k)
|
||||
except AttributeError:
|
||||
pass
|
||||
return d
|
||||
|
||||
def __setstate__(self, d):
|
||||
if not hasattr(self, 'implementation'):
|
||||
self.implementation = RSAImplementation()
|
||||
t = []
|
||||
for k in self.keydata:
|
||||
if not d.has_key(k):
|
||||
break
|
||||
t.append(d[k])
|
||||
self.key = self.implementation._math.rsa_construct(*tuple(t))
|
||||
|
||||
def __repr__(self):
|
||||
attrs = []
|
||||
for k in self.keydata:
|
||||
if k == 'n':
|
||||
attrs.append("n(%d)" % (self.size()+1,))
|
||||
elif hasattr(self.key, k):
|
||||
attrs.append(k)
|
||||
if self.has_private():
|
||||
attrs.append("private")
|
||||
return "<%s @0x%x %s>" % (self.__class__.__name__, id(self), ",".join(attrs))
|
||||
|
||||
class RSAImplementation(object):
|
||||
def __init__(self, **kwargs):
|
||||
# 'use_fast_math' parameter:
|
||||
# None (default) - Use fast math if available; Use slow math if not.
|
||||
# True - Use fast math, and raise RuntimeError if it's not available.
|
||||
# False - Use slow math.
|
||||
use_fast_math = kwargs.get('use_fast_math', None)
|
||||
if use_fast_math is None: # Automatic
|
||||
if _fastmath is not None:
|
||||
self._math = _fastmath
|
||||
else:
|
||||
self._math = _slowmath
|
||||
|
||||
elif use_fast_math: # Explicitly select fast math
|
||||
if _fastmath is not None:
|
||||
self._math = _fastmath
|
||||
else:
|
||||
raise RuntimeError("fast math module not available")
|
||||
|
||||
else: # Explicitly select slow math
|
||||
self._math = _slowmath
|
||||
|
||||
self.error = self._math.error
|
||||
|
||||
# 'default_randfunc' parameter:
|
||||
# None (default) - use Random.new().read
|
||||
# not None - use the specified function
|
||||
self._default_randfunc = kwargs.get('default_randfunc', None)
|
||||
self._current_randfunc = None
|
||||
|
||||
def _get_randfunc(self, randfunc):
|
||||
if randfunc is not None:
|
||||
return randfunc
|
||||
elif self._current_randfunc is None:
|
||||
self._current_randfunc = Random.new().read
|
||||
return self._current_randfunc
|
||||
|
||||
def generate(self, bits, randfunc=None, progress_func=None):
|
||||
rf = self._get_randfunc(randfunc)
|
||||
obj = _RSA.generate_py(bits, rf, progress_func) # TODO: Don't use legacy _RSA module
|
||||
key = self._math.rsa_construct(obj.n, obj.e, obj.d, obj.p, obj.q, obj.u)
|
||||
return _RSAobj(self, key)
|
||||
|
||||
def construct(self, tup):
|
||||
key = self._math.rsa_construct(*tup)
|
||||
return _RSAobj(self, key)
|
||||
|
||||
_impl = RSAImplementation()
|
||||
generate = _impl.generate
|
||||
construct = _impl.construct
|
||||
error = _impl.error
|
||||
|
||||
# vim:set ts=4 sw=4 sts=4 expandtab:
|
||||
|
||||
@@ -1,95 +0,0 @@
|
||||
#
|
||||
# RSA.py : RSA encryption/decryption
|
||||
#
|
||||
# Part of the Python Cryptography Toolkit
|
||||
#
|
||||
# Written by Andrew Kuchling, Paul Swartz, and others
|
||||
#
|
||||
# ===================================================================
|
||||
# The contents of this file are dedicated to the public domain. To
|
||||
# the extent that dedication to the public domain is not available,
|
||||
# everyone is granted a worldwide, perpetual, royalty-free,
|
||||
# non-exclusive license to exercise all rights associated with the
|
||||
# contents of this file for any purpose whatsoever.
|
||||
# No rights are reserved.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
# SOFTWARE.
|
||||
# ===================================================================
|
||||
#
|
||||
|
||||
__revision__ = "$Id$"
|
||||
|
||||
from Crypto.PublicKey import pubkey
|
||||
from Crypto.Util import number
|
||||
|
||||
def generate_py(bits, randfunc, progress_func=None):
|
||||
"""generate(bits:int, randfunc:callable, progress_func:callable)
|
||||
|
||||
Generate an RSA key of length 'bits', using 'randfunc' to get
|
||||
random data and 'progress_func', if present, to display
|
||||
the progress of the key generation.
|
||||
"""
|
||||
obj=RSAobj()
|
||||
obj.e = 65537L
|
||||
|
||||
# Generate the prime factors of n
|
||||
if progress_func:
|
||||
progress_func('p,q\n')
|
||||
p = q = 1L
|
||||
while number.size(p*q) < bits:
|
||||
# Note that q might be one bit longer than p if somebody specifies an odd
|
||||
# number of bits for the key. (Why would anyone do that? You don't get
|
||||
# more security.)
|
||||
#
|
||||
# Note also that we ensure that e is coprime to (p-1) and (q-1).
|
||||
# This is needed for encryption to work properly, according to the 1997
|
||||
# paper by Robert D. Silverman of RSA Labs, "Fast generation of random,
|
||||
# strong RSA primes", available at
|
||||
# http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.17.2713&rep=rep1&type=pdf
|
||||
# Since e=65537 is prime, it is sufficient to check that e divides
|
||||
# neither (p-1) nor (q-1).
|
||||
p = 1L
|
||||
while (p - 1) % obj.e == 0:
|
||||
if progress_func:
|
||||
progress_func('p\n')
|
||||
p = pubkey.getPrime(bits/2, randfunc)
|
||||
q = 1L
|
||||
while (q - 1) % obj.e == 0:
|
||||
if progress_func:
|
||||
progress_func('q\n')
|
||||
q = pubkey.getPrime(bits - (bits/2), randfunc)
|
||||
|
||||
# p shall be smaller than q (for calc of u)
|
||||
if p > q:
|
||||
(p, q)=(q, p)
|
||||
obj.p = p
|
||||
obj.q = q
|
||||
|
||||
if progress_func:
|
||||
progress_func('u\n')
|
||||
obj.u = pubkey.inverse(obj.p, obj.q)
|
||||
obj.n = obj.p*obj.q
|
||||
|
||||
if progress_func:
|
||||
progress_func('d\n')
|
||||
obj.d=pubkey.inverse(obj.e, (obj.p-1)*(obj.q-1))
|
||||
|
||||
assert bits <= 1+obj.size(), "Generated key is too small"
|
||||
|
||||
return obj
|
||||
|
||||
class RSAobj(pubkey.pubkey):
|
||||
|
||||
def size(self):
|
||||
"""size() : int
|
||||
Return the maximum number of bits that can be handled by this key.
|
||||
"""
|
||||
return number.size(self.n) - 1
|
||||
|
||||
@@ -1,37 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# ===================================================================
|
||||
# The contents of this file are dedicated to the public domain. To
|
||||
# the extent that dedication to the public domain is not available,
|
||||
# everyone is granted a worldwide, perpetual, royalty-free,
|
||||
# non-exclusive license to exercise all rights associated with the
|
||||
# contents of this file for any purpose whatsoever.
|
||||
# No rights are reserved.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
# SOFTWARE.
|
||||
# ===================================================================
|
||||
|
||||
"""Public-key encryption and signature algorithms.
|
||||
|
||||
Public-key encryption uses two different keys, one for encryption and
|
||||
one for decryption. The encryption key can be made public, and the
|
||||
decryption key is kept private. Many public-key algorithms can also
|
||||
be used to sign messages, and some can *only* be used for signatures.
|
||||
|
||||
Crypto.PublicKey.DSA Digital Signature Algorithm. (Signature only)
|
||||
Crypto.PublicKey.ElGamal (Signing and encryption)
|
||||
Crypto.PublicKey.RSA (Signing, encryption, and blinding)
|
||||
Crypto.PublicKey.qNEW (Signature only)
|
||||
|
||||
"""
|
||||
|
||||
__all__ = ['RSA', 'DSA', 'ElGamal', 'qNEW']
|
||||
__revision__ = "$Id$"
|
||||
|
||||
@@ -1,134 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# PubKey/RSA/_slowmath.py : Pure Python implementation of the RSA portions of _fastmath
|
||||
#
|
||||
# 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.
|
||||
# ===================================================================
|
||||
|
||||
"""Pure Python implementation of the RSA-related portions of Crypto.PublicKey._fastmath."""
|
||||
|
||||
__revision__ = "$Id$"
|
||||
|
||||
__all__ = ['rsa_construct']
|
||||
|
||||
from Crypto.Util.python_compat import *
|
||||
|
||||
from Crypto.Util.number import size, inverse
|
||||
|
||||
class error(Exception):
|
||||
pass
|
||||
|
||||
class _RSAKey(object):
|
||||
def _blind(self, m, r):
|
||||
# compute r**e * m (mod n)
|
||||
return m * pow(r, self.e, self.n)
|
||||
|
||||
def _unblind(self, m, r):
|
||||
# compute m / r (mod n)
|
||||
return inverse(r, self.n) * m % self.n
|
||||
|
||||
def _decrypt(self, c):
|
||||
# compute c**d (mod n)
|
||||
if not self.has_private():
|
||||
raise TypeError("No private key")
|
||||
return pow(c, self.d, self.n) # TODO: CRT exponentiation
|
||||
|
||||
def _encrypt(self, m):
|
||||
# compute m**d (mod n)
|
||||
return pow(m, self.e, self.n)
|
||||
|
||||
def _sign(self, m): # alias for _decrypt
|
||||
if not self.has_private():
|
||||
raise TypeError("No private key")
|
||||
return self._decrypt(m)
|
||||
|
||||
def _verify(self, m, sig):
|
||||
return self._encrypt(sig) == m
|
||||
|
||||
def has_private(self):
|
||||
return hasattr(self, 'd')
|
||||
|
||||
def size(self):
|
||||
"""Return the maximum number of bits that can be encrypted"""
|
||||
return size(self.n) - 1
|
||||
|
||||
def rsa_construct(n, e, d=None, p=None, q=None, u=None):
|
||||
"""Construct an RSAKey object"""
|
||||
assert isinstance(n, long)
|
||||
assert isinstance(e, long)
|
||||
assert isinstance(d, (long, type(None)))
|
||||
assert isinstance(p, (long, type(None)))
|
||||
assert isinstance(q, (long, type(None)))
|
||||
assert isinstance(u, (long, type(None)))
|
||||
obj = _RSAKey()
|
||||
obj.n = n
|
||||
obj.e = e
|
||||
if d is not None: obj.d = d
|
||||
if p is not None: obj.p = p
|
||||
if q is not None: obj.q = q
|
||||
if u is not None: obj.u = u
|
||||
return obj
|
||||
|
||||
class _DSAKey(object):
|
||||
def size(self):
|
||||
"""Return the maximum number of bits that can be encrypted"""
|
||||
return size(self.p) - 1
|
||||
|
||||
def has_private(self):
|
||||
return hasattr(self, 'x')
|
||||
|
||||
def _sign(self, m, k): # alias for _decrypt
|
||||
# SECURITY TODO - We _should_ be computing SHA1(m), but we don't because that's the API.
|
||||
if not self.has_private():
|
||||
raise TypeError("No private key")
|
||||
if not (1L < k < self.q):
|
||||
raise ValueError("k is not between 2 and q-1")
|
||||
inv_k = inverse(k, self.q) # Compute k**-1 mod q
|
||||
r = pow(self.g, k, self.p) % self.q # r = (g**k mod p) mod q
|
||||
s = (inv_k * (m + self.x * r)) % self.q
|
||||
return (r, s)
|
||||
|
||||
def _verify(self, m, r, s):
|
||||
# SECURITY TODO - We _should_ be computing SHA1(m), but we don't because that's the API.
|
||||
if not (0 < r < self.q) or not (0 < s < self.q):
|
||||
return False
|
||||
w = inverse(s, self.q)
|
||||
u1 = (m*w) % self.q
|
||||
u2 = (r*w) % self.q
|
||||
v = (pow(self.g, u1, self.p) * pow(self.y, u2, self.p) % self.p) % self.q
|
||||
return v == r
|
||||
|
||||
def dsa_construct(y, g, p, q, x=None):
|
||||
assert isinstance(y, long)
|
||||
assert isinstance(g, long)
|
||||
assert isinstance(p, long)
|
||||
assert isinstance(q, long)
|
||||
assert isinstance(x, (long, type(None)))
|
||||
obj = _DSAKey()
|
||||
obj.y = y
|
||||
obj.g = g
|
||||
obj.p = p
|
||||
obj.q = q
|
||||
if x is not None: obj.x = x
|
||||
return obj
|
||||
|
||||
|
||||
# vim:set ts=4 sw=4 sts=4 expandtab:
|
||||
|
||||
@@ -1,192 +0,0 @@
|
||||
#
|
||||
# pubkey.py : Internal functions for public key operations
|
||||
#
|
||||
# Part of the Python Cryptography Toolkit
|
||||
#
|
||||
# Written by Andrew Kuchling, Paul Swartz, and others
|
||||
#
|
||||
# ===================================================================
|
||||
# The contents of this file are dedicated to the public domain. To
|
||||
# the extent that dedication to the public domain is not available,
|
||||
# everyone is granted a worldwide, perpetual, royalty-free,
|
||||
# non-exclusive license to exercise all rights associated with the
|
||||
# contents of this file for any purpose whatsoever.
|
||||
# No rights are reserved.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
# SOFTWARE.
|
||||
# ===================================================================
|
||||
#
|
||||
|
||||
__revision__ = "$Id$"
|
||||
|
||||
import types, warnings
|
||||
from Crypto.Util.number import *
|
||||
|
||||
# Basic public key class
|
||||
class pubkey:
|
||||
def __init__(self):
|
||||
pass
|
||||
|
||||
def __getstate__(self):
|
||||
"""To keep key objects platform-independent, the key data is
|
||||
converted to standard Python long integers before being
|
||||
written out. It will then be reconverted as necessary on
|
||||
restoration."""
|
||||
d=self.__dict__
|
||||
for key in self.keydata:
|
||||
if d.has_key(key): d[key]=long(d[key])
|
||||
return d
|
||||
|
||||
def __setstate__(self, d):
|
||||
"""On unpickling a key object, the key data is converted to the big
|
||||
number representation being used, whether that is Python long
|
||||
integers, MPZ objects, or whatever."""
|
||||
for key in self.keydata:
|
||||
if d.has_key(key): self.__dict__[key]=bignum(d[key])
|
||||
|
||||
def encrypt(self, plaintext, K):
|
||||
"""encrypt(plaintext:string|long, K:string|long) : tuple
|
||||
Encrypt the string or integer plaintext. K is a random
|
||||
parameter required by some algorithms.
|
||||
"""
|
||||
wasString=0
|
||||
if isinstance(plaintext, types.StringType):
|
||||
plaintext=bytes_to_long(plaintext) ; wasString=1
|
||||
if isinstance(K, types.StringType):
|
||||
K=bytes_to_long(K)
|
||||
ciphertext=self._encrypt(plaintext, K)
|
||||
if wasString: return tuple(map(long_to_bytes, ciphertext))
|
||||
else: return ciphertext
|
||||
|
||||
def decrypt(self, ciphertext):
|
||||
"""decrypt(ciphertext:tuple|string|long): string
|
||||
Decrypt 'ciphertext' using this key.
|
||||
"""
|
||||
wasString=0
|
||||
if not isinstance(ciphertext, types.TupleType):
|
||||
ciphertext=(ciphertext,)
|
||||
if isinstance(ciphertext[0], types.StringType):
|
||||
ciphertext=tuple(map(bytes_to_long, ciphertext)) ; wasString=1
|
||||
plaintext=self._decrypt(ciphertext)
|
||||
if wasString: return long_to_bytes(plaintext)
|
||||
else: return plaintext
|
||||
|
||||
def sign(self, M, K):
|
||||
"""sign(M : string|long, K:string|long) : tuple
|
||||
Return a tuple containing the signature for the message M.
|
||||
K is a random parameter required by some algorithms.
|
||||
"""
|
||||
if (not self.has_private()):
|
||||
raise TypeError('Private key not available in this object')
|
||||
if isinstance(M, types.StringType): M=bytes_to_long(M)
|
||||
if isinstance(K, types.StringType): K=bytes_to_long(K)
|
||||
return self._sign(M, K)
|
||||
|
||||
def verify (self, M, signature):
|
||||
"""verify(M:string|long, signature:tuple) : bool
|
||||
Verify that the signature is valid for the message M;
|
||||
returns true if the signature checks out.
|
||||
"""
|
||||
if isinstance(M, types.StringType): M=bytes_to_long(M)
|
||||
return self._verify(M, signature)
|
||||
|
||||
# alias to compensate for the old validate() name
|
||||
def validate (self, M, signature):
|
||||
warnings.warn("validate() method name is obsolete; use verify()",
|
||||
DeprecationWarning)
|
||||
|
||||
def blind(self, M, B):
|
||||
"""blind(M : string|long, B : string|long) : string|long
|
||||
Blind message M using blinding factor B.
|
||||
"""
|
||||
wasString=0
|
||||
if isinstance(M, types.StringType):
|
||||
M=bytes_to_long(M) ; wasString=1
|
||||
if isinstance(B, types.StringType): B=bytes_to_long(B)
|
||||
blindedmessage=self._blind(M, B)
|
||||
if wasString: return long_to_bytes(blindedmessage)
|
||||
else: return blindedmessage
|
||||
|
||||
def unblind(self, M, B):
|
||||
"""unblind(M : string|long, B : string|long) : string|long
|
||||
Unblind message M using blinding factor B.
|
||||
"""
|
||||
wasString=0
|
||||
if isinstance(M, types.StringType):
|
||||
M=bytes_to_long(M) ; wasString=1
|
||||
if isinstance(B, types.StringType): B=bytes_to_long(B)
|
||||
unblindedmessage=self._unblind(M, B)
|
||||
if wasString: return long_to_bytes(unblindedmessage)
|
||||
else: return unblindedmessage
|
||||
|
||||
|
||||
# The following methods will usually be left alone, except for
|
||||
# signature-only algorithms. They both return Boolean values
|
||||
# recording whether this key's algorithm can sign and encrypt.
|
||||
def can_sign (self):
|
||||
"""can_sign() : bool
|
||||
Return a Boolean value recording whether this algorithm can
|
||||
generate signatures. (This does not imply that this
|
||||
particular key object has the private information required to
|
||||
to generate a signature.)
|
||||
"""
|
||||
return 1
|
||||
|
||||
def can_encrypt (self):
|
||||
"""can_encrypt() : bool
|
||||
Return a Boolean value recording whether this algorithm can
|
||||
encrypt data. (This does not imply that this
|
||||
particular key object has the private information required to
|
||||
to decrypt a message.)
|
||||
"""
|
||||
return 1
|
||||
|
||||
def can_blind (self):
|
||||
"""can_blind() : bool
|
||||
Return a Boolean value recording whether this algorithm can
|
||||
blind data. (This does not imply that this
|
||||
particular key object has the private information required to
|
||||
to blind a message.)
|
||||
"""
|
||||
return 0
|
||||
|
||||
# The following methods will certainly be overridden by
|
||||
# subclasses.
|
||||
|
||||
def size (self):
|
||||
"""size() : int
|
||||
Return the maximum number of bits that can be handled by this key.
|
||||
"""
|
||||
return 0
|
||||
|
||||
def has_private (self):
|
||||
"""has_private() : bool
|
||||
Return a Boolean denoting whether the object contains
|
||||
private components.
|
||||
"""
|
||||
return 0
|
||||
|
||||
def publickey (self):
|
||||
"""publickey(): object
|
||||
Return a new key object containing only the public information.
|
||||
"""
|
||||
return self
|
||||
|
||||
def __eq__ (self, other):
|
||||
"""__eq__(other): 0, 1
|
||||
Compare us to other for equality.
|
||||
"""
|
||||
return self.__getstate__() == other.__getstate__()
|
||||
|
||||
def __ne__ (self, other):
|
||||
"""__ne__(other): 0, 1
|
||||
Compare us to other for inequality.
|
||||
"""
|
||||
return not self.__eq__(other)
|
||||
@@ -1,139 +0,0 @@
|
||||
# -*- coding: ascii -*-
|
||||
#
|
||||
# FortunaAccumulator.py : Fortuna's internal accumulator
|
||||
#
|
||||
# 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.
|
||||
# ===================================================================
|
||||
|
||||
__revision__ = "$Id$"
|
||||
|
||||
from Crypto.Util.python_compat import *
|
||||
|
||||
from binascii import b2a_hex
|
||||
import time
|
||||
import warnings
|
||||
|
||||
from Crypto.pct_warnings import ClockRewindWarning
|
||||
import SHAd256
|
||||
|
||||
import FortunaGenerator
|
||||
|
||||
class FortunaPool(object):
|
||||
"""Fortuna pool type
|
||||
|
||||
This object acts like a hash object, with the following differences:
|
||||
|
||||
- It keeps a count (the .length attribute) of the number of bytes that
|
||||
have been added to the pool
|
||||
- It supports a .reset() method for in-place reinitialization
|
||||
- The method to add bytes to the pool is .append(), not .update().
|
||||
"""
|
||||
|
||||
digest_size = SHAd256.digest_size
|
||||
|
||||
def __init__(self):
|
||||
self.reset()
|
||||
|
||||
def append(self, data):
|
||||
self._h.update(data)
|
||||
self.length += len(data)
|
||||
|
||||
def digest(self):
|
||||
return self._h.digest()
|
||||
|
||||
def hexdigest(self):
|
||||
return b2a_hex(self.digest())
|
||||
|
||||
def reset(self):
|
||||
self._h = SHAd256.new()
|
||||
self.length = 0
|
||||
|
||||
def which_pools(r):
|
||||
"""Return a list of pools indexes (in range(32)) that are to be included during reseed number r.
|
||||
|
||||
According to _Practical Cryptography_, chapter 10.5.2 "Pools":
|
||||
|
||||
"Pool P_i is included if 2**i is a divisor of r. Thus P_0 is used
|
||||
every reseed, P_1 every other reseed, P_2 every fourth reseed, etc."
|
||||
"""
|
||||
# This is a separate function so that it can be unit-tested.
|
||||
assert r >= 1
|
||||
retval = []
|
||||
mask = 0
|
||||
for i in range(32):
|
||||
# "Pool P_i is included if 2**i is a divisor of [reseed_count]"
|
||||
if (r & mask) == 0:
|
||||
retval.append(i)
|
||||
else:
|
||||
break # optimization. once this fails, it always fails
|
||||
mask = (mask << 1) | 1L
|
||||
return retval
|
||||
|
||||
class FortunaAccumulator(object):
|
||||
|
||||
min_pool_size = 64 # TODO: explain why
|
||||
reseed_interval = 0.100 # 100 ms TODO: explain why
|
||||
|
||||
def __init__(self):
|
||||
self.reseed_count = 0
|
||||
self.generator = FortunaGenerator.AESGenerator()
|
||||
self.last_reseed = None
|
||||
|
||||
# Initialize 32 FortunaPool instances.
|
||||
# NB: This is _not_ equivalent to [FortunaPool()]*32, which would give
|
||||
# us 32 references to the _same_ FortunaPool instance (and cause the
|
||||
# assertion below to fail).
|
||||
self.pools = [FortunaPool() for i in range(32)] # 32 pools
|
||||
assert(self.pools[0] is not self.pools[1])
|
||||
|
||||
def random_data(self, bytes):
|
||||
current_time = time.time()
|
||||
if self.last_reseed > current_time:
|
||||
warnings.warn("Clock rewind detected. Resetting last_reseed.", ClockRewindWarning)
|
||||
self.last_reseed = None
|
||||
if (self.pools[0].length >= self.min_pool_size and
|
||||
(self.last_reseed is None or
|
||||
current_time > self.last_reseed + self.reseed_interval)):
|
||||
self._reseed(current_time)
|
||||
# The following should fail if we haven't seeded the pool yet.
|
||||
return self.generator.pseudo_random_data(bytes)
|
||||
|
||||
def _reseed(self, current_time=None):
|
||||
if current_time is None:
|
||||
current_time = time.time()
|
||||
seed = []
|
||||
self.reseed_count += 1
|
||||
self.last_reseed = current_time
|
||||
for i in which_pools(self.reseed_count):
|
||||
seed.append(self.pools[i].digest())
|
||||
self.pools[i].reset()
|
||||
|
||||
seed = "".join(seed)
|
||||
self.generator.reseed(seed)
|
||||
|
||||
def add_random_event(self, source_number, pool_number, data):
|
||||
assert 1 <= len(data) <= 32
|
||||
assert 0 <= source_number <= 255
|
||||
assert 0 <= pool_number <= 31
|
||||
self.pools[pool_number].append(chr(source_number))
|
||||
self.pools[pool_number].append(chr(len(data)))
|
||||
self.pools[pool_number].append(data)
|
||||
|
||||
# vim:set ts=4 sw=4 sts=4 expandtab:
|
||||
@@ -1,128 +0,0 @@
|
||||
# -*- coding: ascii -*-
|
||||
#
|
||||
# FortunaGenerator.py : Fortuna's internal PRNG
|
||||
#
|
||||
# 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.
|
||||
# ===================================================================
|
||||
|
||||
__revision__ = "$Id$"
|
||||
|
||||
from Crypto.Util.python_compat import *
|
||||
|
||||
import struct
|
||||
|
||||
from Crypto.Util.number import ceil_shift, exact_log2, exact_div
|
||||
from Crypto.Util import Counter
|
||||
from Crypto.Cipher import AES
|
||||
|
||||
import SHAd256
|
||||
|
||||
class AESGenerator(object):
|
||||
"""The Fortuna "generator"
|
||||
|
||||
This is used internally by the Fortuna PRNG to generate arbitrary amounts
|
||||
of pseudorandom data from a smaller amount of seed data.
|
||||
|
||||
The output is generated by running AES-256 in counter mode and re-keying
|
||||
after every mebibyte (2**16 blocks) of output.
|
||||
"""
|
||||
|
||||
block_size = AES.block_size # output block size in octets (128 bits)
|
||||
key_size = 32 # key size in octets (256 bits)
|
||||
|
||||
# Because of the birthday paradox, we expect to find approximately one
|
||||
# collision for every 2**64 blocks of output from a real random source.
|
||||
# However, this code generates pseudorandom data by running AES in
|
||||
# counter mode, so there will be no collisions until the counter
|
||||
# (theoretically) wraps around at 2**128 blocks. Thus, in order to prevent
|
||||
# Fortuna's pseudorandom output from deviating perceptibly from a true
|
||||
# random source, Ferguson and Schneier specify a limit of 2**16 blocks
|
||||
# without rekeying.
|
||||
max_blocks_per_request = 2**16 # Allow no more than this number of blocks per _pseudo_random_data request
|
||||
|
||||
_four_kiblocks_of_zeros = "\0" * block_size * 4096
|
||||
|
||||
def __init__(self):
|
||||
self.counter = Counter.new(nbits=self.block_size*8, initial_value=0, little_endian=True)
|
||||
self.key = None
|
||||
|
||||
# Set some helper constants
|
||||
self.block_size_shift = exact_log2(self.block_size)
|
||||
assert (1 << self.block_size_shift) == self.block_size
|
||||
|
||||
self.blocks_per_key = exact_div(self.key_size, self.block_size)
|
||||
assert self.key_size == self.blocks_per_key * self.block_size
|
||||
|
||||
self.max_bytes_per_request = self.max_blocks_per_request * self.block_size
|
||||
|
||||
def reseed(self, seed):
|
||||
if self.key is None:
|
||||
self.key = "\0" * self.key_size
|
||||
self._set_key(SHAd256.new(self.key + seed).digest())
|
||||
self.counter() # increment counter
|
||||
assert len(self.key) == self.key_size
|
||||
|
||||
def pseudo_random_data(self, bytes):
|
||||
assert bytes >= 0
|
||||
|
||||
num_full_blocks = bytes >> 20
|
||||
remainder = bytes & ((1<<20)-1)
|
||||
|
||||
retval = []
|
||||
for i in xrange(num_full_blocks):
|
||||
retval.append(self._pseudo_random_data(1<<20))
|
||||
retval.append(self._pseudo_random_data(remainder))
|
||||
|
||||
return "".join(retval)
|
||||
|
||||
def _set_key(self, key):
|
||||
self.key = key
|
||||
self._cipher = AES.new(key, AES.MODE_CTR, counter=self.counter)
|
||||
|
||||
def _pseudo_random_data(self, bytes):
|
||||
if not (0 <= bytes <= self.max_bytes_per_request):
|
||||
raise AssertionError("You cannot ask for more than 1 MiB of data per request")
|
||||
|
||||
num_blocks = ceil_shift(bytes, self.block_size_shift) # num_blocks = ceil(bytes / self.block_size)
|
||||
|
||||
# Compute the output
|
||||
retval = self._generate_blocks(num_blocks)[:bytes]
|
||||
|
||||
# Switch to a new key to avoid later compromises of this output (i.e.
|
||||
# state compromise extension attacks)
|
||||
self._set_key(self._generate_blocks(self.blocks_per_key))
|
||||
|
||||
assert len(retval) == bytes
|
||||
assert len(self.key) == self.key_size
|
||||
|
||||
return retval
|
||||
|
||||
def _generate_blocks(self, num_blocks):
|
||||
if self.key is None:
|
||||
raise AssertionError("generator must be seeded before use")
|
||||
assert 0 <= num_blocks <= self.max_blocks_per_request
|
||||
retval = []
|
||||
for i in xrange(num_blocks >> 12): # xrange(num_blocks / 4096)
|
||||
retval.append(self._cipher.encrypt(self._four_kiblocks_of_zeros))
|
||||
remaining_bytes = (num_blocks & 4095) << self.block_size_shift # (num_blocks % 4095) * self.block_size
|
||||
retval.append(self._cipher.encrypt(self._four_kiblocks_of_zeros[:remaining_bytes]))
|
||||
return "".join(retval)
|
||||
|
||||
# vim:set ts=4 sw=4 sts=4 expandtab:
|
||||
@@ -1,88 +0,0 @@
|
||||
# -*- coding: ascii -*-
|
||||
#
|
||||
# Random/Fortuna/SHAd256.py : SHA_d-256 hash function implementation
|
||||
#
|
||||
# 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.
|
||||
# ===================================================================
|
||||
|
||||
"""\
|
||||
SHA_d-256 hash function implementation.
|
||||
|
||||
This module should comply with PEP 247.
|
||||
"""
|
||||
|
||||
__revision__ = "$Id$"
|
||||
__all__ = ['new', 'digest_size']
|
||||
|
||||
from Crypto.Util.python_compat import *
|
||||
|
||||
from binascii import b2a_hex
|
||||
|
||||
from Crypto.Hash import SHA256
|
||||
|
||||
assert SHA256.digest_size == 32
|
||||
|
||||
class _SHAd256(object):
|
||||
"""SHA-256, doubled.
|
||||
|
||||
Returns SHA-256(SHA-256(data)).
|
||||
"""
|
||||
|
||||
digest_size = SHA256.digest_size
|
||||
|
||||
_internal = object()
|
||||
|
||||
def __init__(self, internal_api_check, sha256_hash_obj):
|
||||
if internal_api_check is not self._internal:
|
||||
raise AssertionError("Do not instantiate this class directly. Use %s.new()" % (__name__,))
|
||||
self._h = sha256_hash_obj
|
||||
|
||||
# PEP 247 "copy" method
|
||||
def copy(self):
|
||||
"""Return a copy of this hashing object"""
|
||||
return _SHAd256(SHAd256._internal, self._h.copy())
|
||||
|
||||
# PEP 247 "digest" method
|
||||
def digest(self):
|
||||
"""Return the hash value of this object as a binary string"""
|
||||
retval = SHA256.new(self._h.digest()).digest()
|
||||
assert len(retval) == 32
|
||||
return retval
|
||||
|
||||
# PEP 247 "hexdigest" method
|
||||
def hexdigest(self):
|
||||
"""Return the hash value of this object as a (lowercase) hexadecimal string"""
|
||||
retval = b2a_hex(self.digest())
|
||||
assert len(retval) == 64
|
||||
return retval
|
||||
|
||||
# PEP 247 "update" method
|
||||
def update(self, data):
|
||||
self._h.update(data)
|
||||
|
||||
# PEP 247 module-level "digest_size" variable
|
||||
digest_size = _SHAd256.digest_size
|
||||
|
||||
# PEP 247 module-level "new" function
|
||||
def new(data=""):
|
||||
"""Return a new SHAd256 hashing object"""
|
||||
return _SHAd256(_SHAd256._internal, SHA256.new(data))
|
||||
|
||||
# vim:set ts=4 sw=4 sts=4 expandtab:
|
||||
@@ -1,40 +0,0 @@
|
||||
#
|
||||
# Random/OSRNG/__init__.py : Platform-independent OS RNG API
|
||||
#
|
||||
# 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.
|
||||
# ===================================================================
|
||||
|
||||
"""Provides a platform-independent interface to the random number generators
|
||||
supplied by various operating systems."""
|
||||
|
||||
__revision__ = "$Id$"
|
||||
|
||||
import os
|
||||
|
||||
if os.name == 'posix':
|
||||
from Crypto.Random.OSRNG.posix import new
|
||||
elif os.name == 'nt':
|
||||
from Crypto.Random.OSRNG.nt import new
|
||||
elif hasattr(os, 'urandom'):
|
||||
from Crypto.Random.OSRNG.fallback import new
|
||||
else:
|
||||
raise ImportError("Not implemented")
|
||||
|
||||
# vim:set ts=4 sw=4 sts=4 expandtab:
|
||||
@@ -1,46 +0,0 @@
|
||||
#
|
||||
# Random/OSRNG/fallback.py : Fallback entropy source for systems with os.urandom
|
||||
#
|
||||
# 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.
|
||||
# ===================================================================
|
||||
|
||||
|
||||
__revision__ = "$Id$"
|
||||
__all__ = ['PythonOSURandomRNG']
|
||||
|
||||
import os
|
||||
|
||||
from rng_base import BaseRNG
|
||||
|
||||
class PythonOSURandomRNG(BaseRNG):
|
||||
|
||||
name = "<os.urandom>"
|
||||
|
||||
def __init__(self):
|
||||
self._read = os.urandom
|
||||
BaseRNG.__init__(self)
|
||||
|
||||
def _close(self):
|
||||
self._read = None
|
||||
|
||||
def new(*args, **kwargs):
|
||||
return PythonOSURandomRNG(*args, **kwargs)
|
||||
|
||||
# vim:set ts=4 sw=4 sts=4 expandtab:
|
||||
@@ -1,74 +0,0 @@
|
||||
#
|
||||
# Random/OSRNG/nt.py : OS entropy source for MS Windows
|
||||
#
|
||||
# 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.
|
||||
# ===================================================================
|
||||
|
||||
|
||||
__revision__ = "$Id$"
|
||||
__all__ = ['WindowsRNG']
|
||||
|
||||
import winrandom
|
||||
from rng_base import BaseRNG
|
||||
|
||||
class WindowsRNG(BaseRNG):
|
||||
|
||||
name = "<CryptGenRandom>"
|
||||
|
||||
def __init__(self):
|
||||
self.__winrand = winrandom.new()
|
||||
BaseRNG.__init__(self)
|
||||
|
||||
def flush(self):
|
||||
"""Work around weakness in Windows RNG.
|
||||
|
||||
The CryptGenRandom mechanism in some versions of Windows allows an
|
||||
attacker to learn 128 KiB of past and future output. As a workaround,
|
||||
this function reads 128 KiB of 'random' data from Windows and discards
|
||||
it.
|
||||
|
||||
For more information about the weaknesses in CryptGenRandom, see
|
||||
_Cryptanalysis of the Random Number Generator of the Windows Operating
|
||||
System_, by Leo Dorrendorf and Zvi Gutterman and Benny Pinkas
|
||||
http://eprint.iacr.org/2007/419
|
||||
"""
|
||||
if self.closed:
|
||||
raise ValueError("I/O operation on closed file")
|
||||
data = self.__winrand.get_bytes(128*1024)
|
||||
assert (len(data) == 128*1024)
|
||||
BaseRNG.flush(self)
|
||||
|
||||
def _close(self):
|
||||
self.__winrand = None
|
||||
|
||||
def _read(self, N):
|
||||
# Unfortunately, research shows that CryptGenRandom doesn't provide
|
||||
# forward secrecy and fails the next-bit test unless we apply a
|
||||
# workaround, which we do here. See http://eprint.iacr.org/2007/419
|
||||
# for information on the vulnerability.
|
||||
self.flush()
|
||||
data = self.__winrand.get_bytes(N)
|
||||
self.flush()
|
||||
return data
|
||||
|
||||
def new(*args, **kwargs):
|
||||
return WindowsRNG(*args, **kwargs)
|
||||
|
||||
# vim:set ts=4 sw=4 sts=4 expandtab:
|
||||
@@ -1,86 +0,0 @@
|
||||
#
|
||||
# Random/OSRNG/rng_base.py : Base class for OSRNG
|
||||
#
|
||||
# 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.
|
||||
# ===================================================================
|
||||
|
||||
__revision__ = "$Id$"
|
||||
|
||||
from Crypto.Util.python_compat import *
|
||||
|
||||
class BaseRNG(object):
|
||||
|
||||
def __init__(self):
|
||||
self.closed = False
|
||||
self._selftest()
|
||||
|
||||
def __del__(self):
|
||||
self.close()
|
||||
|
||||
def _selftest(self):
|
||||
# Test that urandom can return data
|
||||
data = self.read(16)
|
||||
if len(data) != 16:
|
||||
raise AssertionError("read truncated")
|
||||
|
||||
# Test that we get different data every time (if we don't, the RNG is
|
||||
# probably malfunctioning)
|
||||
data2 = self.read(16)
|
||||
if data == data2:
|
||||
raise AssertionError("OS RNG returned duplicate data")
|
||||
|
||||
# PEP 343: Support for the "with" statement
|
||||
def __enter__(self):
|
||||
pass
|
||||
def __exit__(self):
|
||||
"""PEP 343 support"""
|
||||
self.close()
|
||||
|
||||
def close(self):
|
||||
if not self.closed:
|
||||
self._close()
|
||||
self.closed = True
|
||||
|
||||
def flush(self):
|
||||
pass
|
||||
|
||||
def read(self, N=-1):
|
||||
"""Return N bytes from the RNG."""
|
||||
if self.closed:
|
||||
raise ValueError("I/O operation on closed file")
|
||||
if not isinstance(N, (long, int)):
|
||||
raise TypeError("an integer is required")
|
||||
if N < 0:
|
||||
raise ValueError("cannot read to end of infinite stream")
|
||||
elif N == 0:
|
||||
return ""
|
||||
data = self._read(N)
|
||||
if len(data) != N:
|
||||
raise AssertionError("%s produced truncated output (requested %d, got %d)" % (self.name, N, len(data)))
|
||||
return data
|
||||
|
||||
def _close(self):
|
||||
raise NotImplementedError("child class must implement this")
|
||||
|
||||
def _read(self, N):
|
||||
raise NotImplementedError("child class must implement this")
|
||||
|
||||
|
||||
# vim:set ts=4 sw=4 sts=4 expandtab:
|
||||
Binary file not shown.
@@ -1,213 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# Random/_UserFriendlyRNG.py : A user-friendly random number generator
|
||||
#
|
||||
# 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.
|
||||
# ===================================================================
|
||||
|
||||
__revision__ = "$Id$"
|
||||
|
||||
from Crypto.Util.python_compat import *
|
||||
|
||||
import os
|
||||
import threading
|
||||
import struct
|
||||
import time
|
||||
from math import floor
|
||||
|
||||
from Crypto.Random import OSRNG
|
||||
from Crypto.Random.Fortuna import FortunaAccumulator
|
||||
|
||||
class _EntropySource(object):
|
||||
def __init__(self, accumulator, src_num):
|
||||
self._fortuna = accumulator
|
||||
self._src_num = src_num
|
||||
self._pool_num = 0
|
||||
|
||||
def feed(self, data):
|
||||
self._fortuna.add_random_event(self._src_num, self._pool_num, data)
|
||||
self._pool_num = (self._pool_num + 1) & 31
|
||||
|
||||
class _EntropyCollector(object):
|
||||
|
||||
def __init__(self, accumulator):
|
||||
self._osrng = OSRNG.new()
|
||||
self._osrng_es = _EntropySource(accumulator, 255)
|
||||
self._time_es = _EntropySource(accumulator, 254)
|
||||
self._clock_es = _EntropySource(accumulator, 253)
|
||||
|
||||
def reinit(self):
|
||||
# Add 256 bits to each of the 32 pools, twice. (For a total of 16384
|
||||
# bits collected from the operating system.)
|
||||
for i in range(2):
|
||||
block = self._osrng.read(32*32)
|
||||
for p in range(32):
|
||||
self._osrng_es.feed(block[p*32:(p+1)*32])
|
||||
block = None
|
||||
self._osrng.flush()
|
||||
|
||||
def collect(self):
|
||||
# Collect 64 bits of entropy from the operating system and feed it to Fortuna.
|
||||
self._osrng_es.feed(self._osrng.read(8))
|
||||
|
||||
# Add the fractional part of time.time()
|
||||
t = time.time()
|
||||
self._time_es.feed(struct.pack("@I", int(2**30 * (t - floor(t)))))
|
||||
|
||||
# Add the fractional part of time.clock()
|
||||
t = time.clock()
|
||||
self._clock_es.feed(struct.pack("@I", int(2**30 * (t - floor(t)))))
|
||||
|
||||
|
||||
class _UserFriendlyRNG(object):
|
||||
|
||||
def __init__(self):
|
||||
self.closed = False
|
||||
self._fa = FortunaAccumulator.FortunaAccumulator()
|
||||
self._ec = _EntropyCollector(self._fa)
|
||||
self.reinit()
|
||||
|
||||
def reinit(self):
|
||||
"""Initialize the random number generator and seed it with entropy from
|
||||
the operating system.
|
||||
"""
|
||||
self._pid = os.getpid()
|
||||
self._ec.reinit()
|
||||
|
||||
def close(self):
|
||||
self.closed = True
|
||||
self._osrng = None
|
||||
self._fa = None
|
||||
|
||||
def flush(self):
|
||||
pass
|
||||
|
||||
def read(self, N):
|
||||
"""Return N bytes from the RNG."""
|
||||
if self.closed:
|
||||
raise ValueError("I/O operation on closed file")
|
||||
if not isinstance(N, (long, int)):
|
||||
raise TypeError("an integer is required")
|
||||
if N < 0:
|
||||
raise ValueError("cannot read to end of infinite stream")
|
||||
|
||||
# Collect some entropy and feed it to Fortuna
|
||||
self._ec.collect()
|
||||
|
||||
# Ask Fortuna to generate some bytes
|
||||
retval = self._fa.random_data(N)
|
||||
|
||||
# Check that we haven't forked in the meantime. (If we have, we don't
|
||||
# want to use the data, because it might have been duplicated in the
|
||||
# parent process.
|
||||
self._check_pid()
|
||||
|
||||
# Return the random data.
|
||||
return retval
|
||||
|
||||
def _check_pid(self):
|
||||
# Lame fork detection to remind developers to invoke Random.atfork()
|
||||
# after every call to os.fork(). Note that this check is not reliable,
|
||||
# since process IDs can be reused on most operating systems.
|
||||
#
|
||||
# You need to do Random.atfork() in the child process after every call
|
||||
# to os.fork() to avoid reusing PRNG state. If you want to avoid
|
||||
# leaking PRNG state to child processes (for example, if you are using
|
||||
# os.setuid()) then you should also invoke Random.atfork() in the
|
||||
# *parent* process.
|
||||
if os.getpid() != self._pid:
|
||||
raise AssertionError("PID check failed. RNG must be re-initialized after fork(). Hint: Try Random.atfork()")
|
||||
|
||||
|
||||
class _LockingUserFriendlyRNG(_UserFriendlyRNG):
|
||||
def __init__(self):
|
||||
self._lock = threading.Lock()
|
||||
_UserFriendlyRNG.__init__(self)
|
||||
|
||||
def close(self):
|
||||
self._lock.acquire()
|
||||
try:
|
||||
return _UserFriendlyRNG.close(self)
|
||||
finally:
|
||||
self._lock.release()
|
||||
|
||||
def reinit(self):
|
||||
self._lock.acquire()
|
||||
try:
|
||||
return _UserFriendlyRNG.reinit(self)
|
||||
finally:
|
||||
self._lock.release()
|
||||
|
||||
def read(self, bytes):
|
||||
self._lock.acquire()
|
||||
try:
|
||||
return _UserFriendlyRNG.read(self, bytes)
|
||||
finally:
|
||||
self._lock.release()
|
||||
|
||||
class RNGFile(object):
|
||||
def __init__(self, singleton):
|
||||
self.closed = False
|
||||
self._singleton = singleton
|
||||
|
||||
# PEP 343: Support for the "with" statement
|
||||
def __enter__(self):
|
||||
"""PEP 343 support"""
|
||||
def __exit__(self):
|
||||
"""PEP 343 support"""
|
||||
self.close()
|
||||
|
||||
def close(self):
|
||||
# Don't actually close the singleton, just close this RNGFile instance.
|
||||
self.closed = True
|
||||
self._singleton = None
|
||||
|
||||
def read(self, bytes):
|
||||
if self.closed:
|
||||
raise ValueError("I/O operation on closed file")
|
||||
return self._singleton.read(bytes)
|
||||
|
||||
def flush(self):
|
||||
if self.closed:
|
||||
raise ValueError("I/O operation on closed file")
|
||||
|
||||
_singleton_lock = threading.Lock()
|
||||
_singleton = None
|
||||
def _get_singleton():
|
||||
global _singleton
|
||||
_singleton_lock.acquire()
|
||||
try:
|
||||
if _singleton is None:
|
||||
_singleton = _LockingUserFriendlyRNG()
|
||||
return _singleton
|
||||
finally:
|
||||
_singleton_lock.release()
|
||||
|
||||
def new():
|
||||
return RNGFile(_get_singleton())
|
||||
|
||||
def reinit():
|
||||
_get_singleton().reinit()
|
||||
|
||||
def get_random_bytes(n):
|
||||
"""Return the specified number of cryptographically-strong random bytes."""
|
||||
return _get_singleton().read(n)
|
||||
|
||||
# vim:set ts=4 sw=4 sts=4 expandtab:
|
||||
@@ -1,43 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# Random/__init__.py : PyCrypto random number generation
|
||||
#
|
||||
# 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.
|
||||
# ===================================================================
|
||||
|
||||
__revision__ = "$Id$"
|
||||
__all__ = ['new']
|
||||
|
||||
import OSRNG
|
||||
import _UserFriendlyRNG
|
||||
|
||||
def new(*args, **kwargs):
|
||||
"""Return a file-like object that outputs cryptographically random bytes."""
|
||||
return _UserFriendlyRNG.new(*args, **kwargs)
|
||||
|
||||
def atfork():
|
||||
"""Call this whenever you call os.fork()"""
|
||||
_UserFriendlyRNG.reinit()
|
||||
|
||||
def get_random_bytes(n):
|
||||
"""Return the specified number of cryptographically-strong random bytes."""
|
||||
return _UserFriendlyRNG.get_random_bytes(n)
|
||||
|
||||
# vim:set ts=4 sw=4 sts=4 expandtab:
|
||||
@@ -1,143 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# Random/random.py : Strong alternative for the standard 'random' module
|
||||
#
|
||||
# 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.
|
||||
# ===================================================================
|
||||
|
||||
"""A cryptographically strong version of Python's standard "random" module."""
|
||||
|
||||
__revision__ = "$Id$"
|
||||
__all__ = ['StrongRandom', 'getrandbits', 'randrange', 'randint', 'choice', 'shuffle', 'sample']
|
||||
|
||||
from Crypto import Random
|
||||
|
||||
from Crypto.Util.python_compat import *
|
||||
|
||||
class StrongRandom(object):
|
||||
def __init__(self, rng=None, randfunc=None):
|
||||
if randfunc is None and rng is None:
|
||||
self._randfunc = None
|
||||
elif randfunc is not None and rng is None:
|
||||
self._randfunc = randfunc
|
||||
elif randfunc is None and rng is not None:
|
||||
self._randfunc = rng.read
|
||||
else:
|
||||
raise ValueError("Cannot specify both 'rng' and 'randfunc'")
|
||||
|
||||
def getrandbits(self, k):
|
||||
"""Return a python long integer with k random bits."""
|
||||
if self._randfunc is None:
|
||||
self._randfunc = Random.new().read
|
||||
mask = (1L << k) - 1
|
||||
return mask & bytes_to_long(self._randfunc(ceil_div(k, 8)))
|
||||
|
||||
def randrange(self, *args):
|
||||
"""randrange([start,] stop[, step]):
|
||||
Return a randomly-selected element from range(start, stop, step)."""
|
||||
if len(args) == 3:
|
||||
(start, stop, step) = args
|
||||
elif len(args) == 2:
|
||||
(start, stop) = args
|
||||
step = 1
|
||||
elif len(args) == 1:
|
||||
(stop,) = args
|
||||
start = 0
|
||||
step = 1
|
||||
else:
|
||||
raise TypeError("randrange expected at most 3 arguments, got %d" % (len(args),))
|
||||
if (not isinstance(start, (int, long))
|
||||
or not isinstance(stop, (int, long))
|
||||
or not isinstance(step, (int, long))):
|
||||
raise TypeError("randrange requires integer arguments")
|
||||
if step == 0:
|
||||
raise ValueError("randrange step argument must not be zero")
|
||||
|
||||
num_choices = ceil_div(stop - start, step)
|
||||
if num_choices < 0:
|
||||
num_choices = 0
|
||||
if num_choices < 1:
|
||||
raise ValueError("empty range for randrange(%r, %r, %r)" % (start, stop, step))
|
||||
|
||||
# Pick a random number in the range of possible numbers
|
||||
r = num_choices
|
||||
while r >= num_choices:
|
||||
r = self.getrandbits(size(num_choices))
|
||||
|
||||
return start + (step * r)
|
||||
|
||||
def randint(self, a, b):
|
||||
"""Return a random integer N such that a <= N <= b."""
|
||||
if not isinstance(a, (int, long)) or not isinstance(b, (int, long)):
|
||||
raise TypeError("randint requires integer arguments")
|
||||
N = self.randrange(a, b+1)
|
||||
assert a <= N <= b
|
||||
return N
|
||||
|
||||
def choice(self, seq):
|
||||
"""Return a random element from a (non-empty) sequence.
|
||||
|
||||
If the seqence is empty, raises IndexError.
|
||||
"""
|
||||
if len(seq) == 0:
|
||||
raise IndexError("empty sequence")
|
||||
return seq[self.randrange(len(seq))]
|
||||
|
||||
def shuffle(self, x):
|
||||
"""Shuffle the sequence in place."""
|
||||
# Make a (copy) of the list of objects we want to shuffle
|
||||
items = list(x)
|
||||
|
||||
# Choose a random item (without replacement) until all the items have been
|
||||
# chosen.
|
||||
for i in xrange(len(x)):
|
||||
p = self.randint(len(items))
|
||||
x[i] = items[p]
|
||||
del items[p]
|
||||
|
||||
def sample(self, population, k):
|
||||
"""Return a k-length list of unique elements chosen from the population sequence."""
|
||||
|
||||
num_choices = len(population)
|
||||
if k > num_choices:
|
||||
raise ValueError("sample larger than population")
|
||||
|
||||
retval = []
|
||||
selected = {} # we emulate a set using a dict here
|
||||
for i in xrange(k):
|
||||
r = None
|
||||
while r is None or r in selected:
|
||||
r = self.randrange(num_choices)
|
||||
retval.append(population[r])
|
||||
selected[r] = 1
|
||||
return retval
|
||||
|
||||
_r = StrongRandom()
|
||||
getrandbits = _r.getrandbits
|
||||
randrange = _r.randrange
|
||||
randint = _r.randint
|
||||
choice = _r.choice
|
||||
shuffle = _r.shuffle
|
||||
sample = _r.sample
|
||||
|
||||
# These are at the bottom to avoid problems with recursive imports
|
||||
from Crypto.Util.number import ceil_div, bytes_to_long, long_to_bytes, size
|
||||
|
||||
# vim:set ts=4 sw=4 sts=4 expandtab:
|
||||
@@ -1,61 +0,0 @@
|
||||
# -*- coding: ascii -*-
|
||||
#
|
||||
# Util/Counter.py : Fast counter for use with CTR-mode ciphers
|
||||
#
|
||||
# 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.
|
||||
# ===================================================================
|
||||
|
||||
from Crypto.Util.python_compat import *
|
||||
|
||||
from Crypto.Util import _counter
|
||||
import struct
|
||||
|
||||
# Factory function
|
||||
def new(nbits, prefix="", suffix="", initial_value=1, overflow=0, little_endian=False, allow_wraparound=False, disable_shortcut=False):
|
||||
# TODO: Document this
|
||||
|
||||
# Sanity-check the message size
|
||||
(nbytes, remainder) = divmod(nbits, 8)
|
||||
if remainder != 0:
|
||||
# In the future, we might support arbitrary bit lengths, but for now we don't.
|
||||
raise ValueError("nbits must be a multiple of 8; got %d" % (nbits,))
|
||||
if nbytes < 1:
|
||||
raise ValueError("nbits too small")
|
||||
elif nbytes > 0xffff:
|
||||
raise ValueError("nbits too large")
|
||||
|
||||
initval = _encode(initial_value, nbytes, little_endian)
|
||||
if little_endian:
|
||||
return _counter._newLE(str(prefix), str(suffix), initval, allow_wraparound=allow_wraparound, disable_shortcut=disable_shortcut)
|
||||
else:
|
||||
return _counter._newBE(str(prefix), str(suffix), initval, allow_wraparound=allow_wraparound, disable_shortcut=disable_shortcut)
|
||||
|
||||
def _encode(n, nbytes, little_endian=False):
|
||||
retval = []
|
||||
n = long(n)
|
||||
for i in range(nbytes):
|
||||
if little_endian:
|
||||
retval.append(chr(n & 0xff))
|
||||
else:
|
||||
retval.insert(0, chr(n & 0xff))
|
||||
n >>= 8
|
||||
return "".join(retval)
|
||||
|
||||
# vim:set ts=4 sw=4 sts=4 expandtab:
|
||||
@@ -1,36 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# ===================================================================
|
||||
# The contents of this file are dedicated to the public domain. To
|
||||
# the extent that dedication to the public domain is not available,
|
||||
# everyone is granted a worldwide, perpetual, royalty-free,
|
||||
# non-exclusive license to exercise all rights associated with the
|
||||
# contents of this file for any purpose whatsoever.
|
||||
# No rights are reserved.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
# SOFTWARE.
|
||||
# ===================================================================
|
||||
|
||||
"""Miscellaneous modules
|
||||
|
||||
Contains useful modules that don't belong into any of the
|
||||
other Crypto.* subpackages.
|
||||
|
||||
Crypto.Util.number Number-theoretic functions (primality testing, etc.)
|
||||
Crypto.Util.randpool Random number generation
|
||||
Crypto.Util.RFC1751 Converts between 128-bit keys and human-readable
|
||||
strings of words.
|
||||
|
||||
"""
|
||||
|
||||
__all__ = ['randpool', 'RFC1751', 'number', 'strxor']
|
||||
|
||||
__revision__ = "$Id$"
|
||||
|
||||
Binary file not shown.
@@ -1,117 +0,0 @@
|
||||
# -*- coding: ascii -*-
|
||||
#
|
||||
# Util/_number_new.py : utility functions
|
||||
#
|
||||
# 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.
|
||||
# ===================================================================
|
||||
|
||||
## NOTE: Do not import this module directly. Import these functions from Crypto.Util.number.
|
||||
|
||||
__revision__ = "$Id$"
|
||||
__all__ = ['ceil_shift', 'ceil_div', 'floor_div', 'exact_log2', 'exact_div']
|
||||
|
||||
from Crypto.Util.python_compat import *
|
||||
|
||||
def ceil_shift(n, b):
|
||||
"""Return ceil(n / 2**b) without performing any floating-point or division operations.
|
||||
|
||||
This is done by right-shifting n by b bits and incrementing the result by 1
|
||||
if any '1' bits were shifted out.
|
||||
"""
|
||||
if not isinstance(n, (int, long)) or not isinstance(b, (int, long)):
|
||||
raise TypeError("unsupported operand type(s): %r and %r" % (type(n).__name__, type(b).__name__))
|
||||
|
||||
assert n >= 0 and b >= 0 # I haven't tested or even thought about negative values
|
||||
mask = (1L << b) - 1
|
||||
if n & mask:
|
||||
return (n >> b) + 1
|
||||
else:
|
||||
return n >> b
|
||||
|
||||
def ceil_div(a, b):
|
||||
"""Return ceil(a / b) without performing any floating-point operations."""
|
||||
|
||||
if not isinstance(a, (int, long)) or not isinstance(b, (int, long)):
|
||||
raise TypeError("unsupported operand type(s): %r and %r" % (type(a).__name__, type(b).__name__))
|
||||
|
||||
(q, r) = divmod(a, b)
|
||||
if r:
|
||||
return q + 1
|
||||
else:
|
||||
return q
|
||||
|
||||
def floor_div(a, b):
|
||||
if not isinstance(a, (int, long)) or not isinstance(b, (int, long)):
|
||||
raise TypeError("unsupported operand type(s): %r and %r" % (type(a).__name__, type(b).__name__))
|
||||
|
||||
(q, r) = divmod(a, b)
|
||||
return q
|
||||
|
||||
def exact_log2(num):
|
||||
"""Find and return an integer i >= 0 such that num == 2**i.
|
||||
|
||||
If no such integer exists, this function raises ValueError.
|
||||
"""
|
||||
|
||||
if not isinstance(num, (int, long)):
|
||||
raise TypeError("unsupported operand type: %r" % (type(num).__name__,))
|
||||
|
||||
n = long(num)
|
||||
if n <= 0:
|
||||
raise ValueError("cannot compute logarithm of non-positive number")
|
||||
|
||||
i = 0
|
||||
while n != 0:
|
||||
if (n & 1) and n != 1:
|
||||
raise ValueError("No solution could be found")
|
||||
i += 1
|
||||
n >>= 1
|
||||
i -= 1
|
||||
|
||||
assert num == (1L << i)
|
||||
return i
|
||||
|
||||
def exact_div(p, d, allow_divzero=False):
|
||||
"""Find and return an integer n such that p == n * d
|
||||
|
||||
If no such integer exists, this function raises ValueError.
|
||||
|
||||
Both operands must be integers.
|
||||
|
||||
If the second operand is zero, this function will raise ZeroDivisionError
|
||||
unless allow_divzero is true (default: False).
|
||||
"""
|
||||
|
||||
if not isinstance(p, (int, long)) or not isinstance(d, (int, long)):
|
||||
raise TypeError("unsupported operand type(s): %r and %r" % (type(p).__name__, type(d).__name__))
|
||||
|
||||
if d == 0 and allow_divzero:
|
||||
n = 0
|
||||
if p != n * d:
|
||||
raise ValueError("No solution could be found")
|
||||
else:
|
||||
(n, r) = divmod(p, d)
|
||||
if r != 0:
|
||||
raise ValueError("No solution could be found")
|
||||
|
||||
assert p == n * d
|
||||
return n
|
||||
|
||||
# vim:set ts=4 sw=4 sts=4 expandtab:
|
||||
@@ -1,250 +0,0 @@
|
||||
#
|
||||
# number.py : Number-theoretic functions
|
||||
#
|
||||
# Part of the Python Cryptography Toolkit
|
||||
#
|
||||
# Written by Andrew M. Kuchling, Barry A. Warsaw, and others
|
||||
#
|
||||
# ===================================================================
|
||||
# The contents of this file are dedicated to the public domain. To
|
||||
# the extent that dedication to the public domain is not available,
|
||||
# everyone is granted a worldwide, perpetual, royalty-free,
|
||||
# non-exclusive license to exercise all rights associated with the
|
||||
# contents of this file for any purpose whatsoever.
|
||||
# No rights are reserved.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
# SOFTWARE.
|
||||
# ===================================================================
|
||||
#
|
||||
|
||||
__revision__ = "$Id$"
|
||||
|
||||
bignum = long
|
||||
try:
|
||||
from Crypto.PublicKey import _fastmath
|
||||
except ImportError:
|
||||
_fastmath = None
|
||||
|
||||
# New functions
|
||||
from _number_new import *
|
||||
|
||||
# Commented out and replaced with faster versions below
|
||||
## def long2str(n):
|
||||
## s=''
|
||||
## while n>0:
|
||||
## s=chr(n & 255)+s
|
||||
## n=n>>8
|
||||
## return s
|
||||
|
||||
## import types
|
||||
## def str2long(s):
|
||||
## if type(s)!=types.StringType: return s # Integers will be left alone
|
||||
## return reduce(lambda x,y : x*256+ord(y), s, 0L)
|
||||
|
||||
def size (N):
|
||||
"""size(N:long) : int
|
||||
Returns the size of the number N in bits.
|
||||
"""
|
||||
bits, power = 0,1L
|
||||
while N >= power:
|
||||
bits += 1
|
||||
power = power << 1
|
||||
return bits
|
||||
|
||||
def getRandomNumber(N, randfunc=None):
|
||||
"""getRandomNumber(N:int, randfunc:callable):long
|
||||
Return a random N-bit number.
|
||||
|
||||
If randfunc is omitted, then Random.new().read is used.
|
||||
|
||||
NOTE: Confusingly, this function does NOT return N random bits; It returns
|
||||
a random N-bit number, i.e. a random number between 2**(N-1) and (2**N)-1.
|
||||
|
||||
This function is for internal use only and may be renamed or removed in
|
||||
the future.
|
||||
"""
|
||||
if randfunc is None:
|
||||
_import_Random()
|
||||
randfunc = Random.new().read
|
||||
|
||||
S = randfunc(N/8)
|
||||
odd_bits = N % 8
|
||||
if odd_bits != 0:
|
||||
char = ord(randfunc(1)) >> (8-odd_bits)
|
||||
S = chr(char) + S
|
||||
value = bytes_to_long(S)
|
||||
value |= 2L ** (N-1) # Ensure high bit is set
|
||||
assert size(value) >= N
|
||||
return value
|
||||
|
||||
def GCD(x,y):
|
||||
"""GCD(x:long, y:long): long
|
||||
Return the GCD of x and y.
|
||||
"""
|
||||
x = abs(x) ; y = abs(y)
|
||||
while x > 0:
|
||||
x, y = y % x, x
|
||||
return y
|
||||
|
||||
def inverse(u, v):
|
||||
"""inverse(u:long, u:long):long
|
||||
Return the inverse of u mod v.
|
||||
"""
|
||||
u3, v3 = long(u), long(v)
|
||||
u1, v1 = 1L, 0L
|
||||
while v3 > 0:
|
||||
q=u3 / v3
|
||||
u1, v1 = v1, u1 - v1*q
|
||||
u3, v3 = v3, u3 - v3*q
|
||||
while u1<0:
|
||||
u1 = u1 + v
|
||||
return u1
|
||||
|
||||
# Given a number of bits to generate and a random generation function,
|
||||
# find a prime number of the appropriate size.
|
||||
|
||||
def getPrime(N, randfunc=None):
|
||||
"""getPrime(N:int, randfunc:callable):long
|
||||
Return a random N-bit prime number.
|
||||
|
||||
If randfunc is omitted, then Random.new().read is used.
|
||||
"""
|
||||
if randfunc is None:
|
||||
_import_Random()
|
||||
randfunc = Random.new().read
|
||||
|
||||
number=getRandomNumber(N, randfunc) | 1
|
||||
while (not isPrime(number, randfunc=randfunc)):
|
||||
number=number+2
|
||||
return number
|
||||
|
||||
def isPrime(N, randfunc=None):
|
||||
"""isPrime(N:long, randfunc:callable):bool
|
||||
Return true if N is prime.
|
||||
|
||||
If randfunc is omitted, then Random.new().read is used.
|
||||
"""
|
||||
_import_Random()
|
||||
if randfunc is None:
|
||||
randfunc = Random.new().read
|
||||
|
||||
randint = StrongRandom(randfunc=randfunc).randint
|
||||
|
||||
if N == 1:
|
||||
return 0
|
||||
if N in sieve:
|
||||
return 1
|
||||
for i in sieve:
|
||||
if (N % i)==0:
|
||||
return 0
|
||||
|
||||
# Use the accelerator if available
|
||||
if _fastmath is not None:
|
||||
return _fastmath.isPrime(N)
|
||||
|
||||
# Compute the highest bit that's set in N
|
||||
N1 = N - 1L
|
||||
n = 1L
|
||||
while (n<N):
|
||||
n=n<<1L
|
||||
n = n >> 1L
|
||||
|
||||
# Rabin-Miller test
|
||||
for c in sieve[:7]:
|
||||
a=long(c) ; d=1L ; t=n
|
||||
while (t): # Iterate over the bits in N1
|
||||
x=(d*d) % N
|
||||
if x==1L and d!=1L and d!=N1:
|
||||
return 0 # Square root of 1 found
|
||||
if N1 & t:
|
||||
d=(x*a) % N
|
||||
else:
|
||||
d=x
|
||||
t = t >> 1L
|
||||
if d!=1L:
|
||||
return 0
|
||||
return 1
|
||||
|
||||
# Small primes used for checking primality; these are all the primes
|
||||
# less than 256. This should be enough to eliminate most of the odd
|
||||
# numbers before needing to do a Rabin-Miller test at all.
|
||||
|
||||
sieve=[2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59,
|
||||
61, 67, 71, 73, 79, 83, 89, 97, 101, 103, 107, 109, 113, 127,
|
||||
131, 137, 139, 149, 151, 157, 163, 167, 173, 179, 181, 191, 193,
|
||||
197, 199, 211, 223, 227, 229, 233, 239, 241, 251]
|
||||
|
||||
# Improved conversion functions contributed by Barry Warsaw, after
|
||||
# careful benchmarking
|
||||
|
||||
import struct
|
||||
|
||||
def long_to_bytes(n, blocksize=0):
|
||||
"""long_to_bytes(n:long, blocksize:int) : string
|
||||
Convert a long integer to a byte string.
|
||||
|
||||
If optional blocksize is given and greater than zero, pad the front of the
|
||||
byte string with binary zeros so that the length is a multiple of
|
||||
blocksize.
|
||||
"""
|
||||
# after much testing, this algorithm was deemed to be the fastest
|
||||
s = ''
|
||||
n = long(n)
|
||||
pack = struct.pack
|
||||
while n > 0:
|
||||
s = pack('>I', n & 0xffffffffL) + s
|
||||
n = n >> 32
|
||||
# strip off leading zeros
|
||||
for i in range(len(s)):
|
||||
if s[i] != '\000':
|
||||
break
|
||||
else:
|
||||
# only happens when n == 0
|
||||
s = '\000'
|
||||
i = 0
|
||||
s = s[i:]
|
||||
# add back some pad bytes. this could be done more efficiently w.r.t. the
|
||||
# de-padding being done above, but sigh...
|
||||
if blocksize > 0 and len(s) % blocksize:
|
||||
s = (blocksize - len(s) % blocksize) * '\000' + s
|
||||
return s
|
||||
|
||||
def bytes_to_long(s):
|
||||
"""bytes_to_long(string) : long
|
||||
Convert a byte string to a long integer.
|
||||
|
||||
This is (essentially) the inverse of long_to_bytes().
|
||||
"""
|
||||
acc = 0L
|
||||
unpack = struct.unpack
|
||||
length = len(s)
|
||||
if length % 4:
|
||||
extra = (4 - length % 4)
|
||||
s = '\000' * extra + s
|
||||
length = length + extra
|
||||
for i in range(0, length, 4):
|
||||
acc = (acc << 32) + unpack('>I', s[i:i+4])[0]
|
||||
return acc
|
||||
|
||||
# For backwards compatibility...
|
||||
import warnings
|
||||
def long2str(n, blocksize=0):
|
||||
warnings.warn("long2str() has been replaced by long_to_bytes()")
|
||||
return long_to_bytes(n, blocksize)
|
||||
def str2long(s):
|
||||
warnings.warn("str2long() has been replaced by bytes_to_long()")
|
||||
return bytes_to_long(s)
|
||||
|
||||
def _import_Random():
|
||||
# This is called in a function instead of at the module level in order to avoid problems with recursive imports
|
||||
global Random, StrongRandom
|
||||
from Crypto import Random
|
||||
from Crypto.Random.random import StrongRandom
|
||||
|
||||
@@ -1,84 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# Util/python_compat.py : Compatibility code for old versions of Python
|
||||
#
|
||||
# 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.
|
||||
# ===================================================================
|
||||
|
||||
"""Compatibility code for old versions of Python
|
||||
|
||||
Currently, this just defines:
|
||||
- True and False
|
||||
- object
|
||||
- isinstance
|
||||
"""
|
||||
|
||||
__revision__ = "$Id$"
|
||||
__all__ = []
|
||||
|
||||
import sys
|
||||
import __builtin__
|
||||
|
||||
# 'True' and 'False' aren't defined in Python 2.1. Define them.
|
||||
try:
|
||||
True, False
|
||||
except NameError:
|
||||
(True, False) = (1, 0)
|
||||
__all__ += ['True', 'False']
|
||||
|
||||
# New-style classes were introduced in Python 2.2. Defining "object" in Python
|
||||
# 2.1 lets us use new-style classes in versions of Python that support them,
|
||||
# while still maintaining backward compatibility with old-style classes
|
||||
try:
|
||||
object
|
||||
except NameError:
|
||||
class object: pass
|
||||
__all__ += ['object']
|
||||
|
||||
# Starting with Python 2.2, isinstance allows a tuple for the second argument.
|
||||
# Also, builtins like "tuple", "list", "str", "unicode", "int", and "long"
|
||||
# became first-class types, rather than functions. We want to support
|
||||
# constructs like:
|
||||
# isinstance(x, (int, long))
|
||||
# So we hack it for Python 2.1.
|
||||
try:
|
||||
isinstance(5, (int, long))
|
||||
except TypeError:
|
||||
__all__ += ['isinstance']
|
||||
_builtin_type_map = {
|
||||
tuple: type(()),
|
||||
list: type([]),
|
||||
str: type(""),
|
||||
unicode: type(u""),
|
||||
int: type(0),
|
||||
long: type(0L),
|
||||
}
|
||||
def isinstance(obj, t):
|
||||
if not __builtin__.isinstance(t, type(())):
|
||||
# t is not a tuple
|
||||
return __builtin__.isinstance(obj, _builtin_type_map.get(t, t))
|
||||
else:
|
||||
# t is a tuple
|
||||
for typ in t:
|
||||
if __builtin__.isinstance(obj, _builtin_type_map.get(typ, typ)):
|
||||
return True
|
||||
return False
|
||||
|
||||
# vim:set ts=4 sw=4 sts=4 expandtab:
|
||||
@@ -1,46 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# ===================================================================
|
||||
# The contents of this file are dedicated to the public domain. To
|
||||
# the extent that dedication to the public domain is not available,
|
||||
# everyone is granted a worldwide, perpetual, royalty-free,
|
||||
# non-exclusive license to exercise all rights associated with the
|
||||
# contents of this file for any purpose whatsoever.
|
||||
# No rights are reserved.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
# SOFTWARE.
|
||||
# ===================================================================
|
||||
|
||||
"""Python Cryptography Toolkit
|
||||
|
||||
A collection of cryptographic modules implementing various algorithms
|
||||
and protocols.
|
||||
|
||||
Subpackages:
|
||||
Crypto.Cipher Secret-key encryption algorithms (AES, DES, ARC4)
|
||||
Crypto.Hash Hashing algorithms (MD5, SHA, HMAC)
|
||||
Crypto.Protocol Cryptographic protocols (Chaffing, all-or-nothing
|
||||
transform). This package does not contain any
|
||||
network protocols.
|
||||
Crypto.PublicKey Public-key encryption and signature algorithms
|
||||
(RSA, DSA)
|
||||
Crypto.Util Various useful modules and functions (long-to-string
|
||||
conversion, random number generation, number
|
||||
theoretic functions)
|
||||
"""
|
||||
|
||||
__all__ = ['Cipher', 'Hash', 'Protocol', 'PublicKey', 'Util']
|
||||
|
||||
__version__ = '2.3' # See also below and setup.py
|
||||
__revision__ = "$Id$"
|
||||
|
||||
# New software should look at this instead of at __version__ above.
|
||||
version_info = (2, 1, 0, 'final', 0) # See also above and setup.py
|
||||
|
||||
@@ -1,57 +0,0 @@
|
||||
# -*- coding: ascii -*-
|
||||
#
|
||||
# pct_warnings.py : PyCrypto warnings file
|
||||
#
|
||||
# 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.
|
||||
# ===================================================================
|
||||
|
||||
#
|
||||
# Base classes. All our warnings inherit from one of these in order to allow
|
||||
# the user to specifically filter them.
|
||||
#
|
||||
|
||||
class CryptoWarning(Warning):
|
||||
"""Base class for PyCrypto warnings"""
|
||||
|
||||
class CryptoDeprecationWarning(DeprecationWarning, CryptoWarning):
|
||||
"""Base PyCrypto DeprecationWarning class"""
|
||||
|
||||
class CryptoRuntimeWarning(RuntimeWarning, CryptoWarning):
|
||||
"""Base PyCrypto RuntimeWarning class"""
|
||||
|
||||
#
|
||||
# Warnings that we might actually use
|
||||
#
|
||||
|
||||
class RandomPool_DeprecationWarning(CryptoDeprecationWarning):
|
||||
"""Issued when Crypto.Util.randpool.RandomPool is instantiated."""
|
||||
|
||||
class ClockRewindWarning(CryptoRuntimeWarning):
|
||||
"""Warning for when the system clock moves backwards."""
|
||||
|
||||
class GetRandomNumber_DeprecationWarning(CryptoDeprecationWarning):
|
||||
"""Issued when Crypto.Util.number.getRandomNumber is invoked."""
|
||||
|
||||
# By default, we want this warning to be shown every time we compensate for
|
||||
# clock rewinding.
|
||||
import warnings as _warnings
|
||||
_warnings.filterwarnings('always', category=ClockRewindWarning, append=1)
|
||||
|
||||
# vim:set ts=4 sw=4 sts=4 expandtab:
|
||||
Reference in New Issue
Block a user