mirror of
				https://github.com/Legrandin/pycryptodome.git
				synced 2025-10-31 13:41:27 +00:00 
			
		
		
		
	 cb48387f66
			
		
	
	
		cb48387f66
		
	
	
	
	
		
			
			o _fastmath now builds and runs on PY3K o Changes to setup.py to allow /usr/include for gmp.h o Changes to setup.py to allow linking fastmath w/ static mpir on Windows without warning messages o Changes to test_DSA/test_RSA to throw an exception if _fastmath is present but cannot be imported (due to an issue building _fastmath or the shared gmp/mpir libraries not being reachable) o number.py has the code to flag a failing _fastmath, but that code is commented out for a better runtime experience o Clean up the if for py21compat import - should have been == not is o Clean up some '== None' occurences, now 'is None' instead
		
			
				
	
	
		
			192 lines
		
	
	
	
		
			6.4 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			192 lines
		
	
	
	
		
			6.4 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
| # -*- coding: utf-8 -*-
 | |
| #
 | |
| #  PublicKey/DSA.py : DSA signature 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.
 | |
| # ===================================================================
 | |
| 
 | |
| """DSA public-key signature algorithm."""
 | |
| 
 | |
| __revision__ = "$Id$"
 | |
| 
 | |
| __all__ = ['generate', 'construct', 'error']
 | |
| 
 | |
| import sys
 | |
| if sys.version_info[0] == 2 and sys.version_info[1] == 1:
 | |
|     from Crypto.Util.py21compat import *
 | |
| 
 | |
| from Crypto.PublicKey import _DSA, _slowmath, pubkey
 | |
| from Crypto import Random
 | |
| 
 | |
| try:
 | |
|     from Crypto.PublicKey import _fastmath
 | |
| except ImportError:
 | |
|     _fastmath = None
 | |
| 
 | |
| class _DSAobj(pubkey.pubkey):
 | |
|     keydata = ['y', 'g', 'p', 'q', 'x']
 | |
| 
 | |
|     def __init__(self, implementation, key):
 | |
|         self.implementation = implementation
 | |
|         self.key = key
 | |
| 
 | |
|     def __getattr__(self, attrname):
 | |
|         if attrname in self.keydata:
 | |
|             # For backward compatibility, allow the user to get (not set) the
 | |
|             # DSA key parameters directly from this object.
 | |
|             return getattr(self.key, attrname)
 | |
|         else:
 | |
|             raise AttributeError("%s object has no %r attribute" % (self.__class__.__name__, attrname,))
 | |
| 
 | |
|     def _encrypt(self, c, K):
 | |
|         raise TypeError("DSA cannot encrypt")
 | |
| 
 | |
|     def _decrypt(self, c):
 | |
|         raise TypeError("DSA cannot decrypt")
 | |
| 
 | |
|     def _blind(self, m, r):
 | |
|         raise TypeError("DSA cannot blind")
 | |
| 
 | |
|     def _unblind(self, m, r):
 | |
|         raise TypeError("DSA cannot unblind")
 | |
| 
 | |
|     def _sign(self, m, k):
 | |
|         return self.key._sign(m, k)
 | |
| 
 | |
|     def _verify(self, m, sig):
 | |
|         (r, s) = sig
 | |
|         return self.key._verify(m, r, s)
 | |
| 
 | |
|     def has_private(self):
 | |
|         return self.key.has_private()
 | |
| 
 | |
|     def size(self):
 | |
|         return self.key.size()
 | |
| 
 | |
|     def can_blind(self):
 | |
|         return False
 | |
| 
 | |
|     def can_encrypt(self):
 | |
|         return False
 | |
| 
 | |
|     def can_sign(self):
 | |
|         return True
 | |
| 
 | |
|     def publickey(self):
 | |
|         return self.implementation.construct((self.key.y, self.key.g, self.key.p, self.key.q))
 | |
| 
 | |
|     def __getstate__(self):
 | |
|         d = {}
 | |
|         for k in self.keydata:
 | |
|             try:
 | |
|                 d[k] = getattr(self.key, k)
 | |
|             except AttributeError:
 | |
|                 pass
 | |
|         return d
 | |
| 
 | |
|     def __setstate__(self, d):
 | |
|         if not hasattr(self, 'implementation'):
 | |
|             self.implementation = DSAImplementation()
 | |
|         t = []
 | |
|         for k in self.keydata:
 | |
|             if not d.has_key(k):
 | |
|                 break
 | |
|             t.append(d[k])
 | |
|         self.key = self.implementation._math.dsa_construct(*tuple(t))
 | |
| 
 | |
|     def __repr__(self):
 | |
|         attrs = []
 | |
|         for k in self.keydata:
 | |
|             if k == 'p':
 | |
|                 attrs.append("p(%d)" % (self.size()+1,))
 | |
|             elif hasattr(self.key, k):
 | |
|                 attrs.append(k)
 | |
|         if self.has_private():
 | |
|             attrs.append("private")
 | |
|         # PY3K: This is meant to be text, do not change to bytes (data)
 | |
|         return "<%s @0x%x %s>" % (self.__class__.__name__, id(self), ",".join(attrs))
 | |
| 
 | |
| class DSAImplementation(object):
 | |
|     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):
 | |
|         # Check against FIPS 186-2, which says that the size of the prime p
 | |
|         # must be a multiple of 64 bits between 512 and 1024
 | |
|         for i in (0, 1, 2, 3, 4, 5, 6, 7, 8):
 | |
|             if bits == 512 + 64*i:
 | |
|                 return self._generate(bits, randfunc, progress_func)
 | |
| 
 | |
|         # The March 2006 draft of FIPS 186-3 also allows 2048 and 3072-bit
 | |
|         # primes, but only with longer q values.  Since the current DSA
 | |
|         # implementation only supports a 160-bit q, we don't support larger
 | |
|         # values.
 | |
|         raise ValueError("Number of bits in p must be a multiple of 64 between 512 and 1024, not %d bits" % (bits,))
 | |
| 
 | |
|     def _generate(self, bits, randfunc=None, progress_func=None):
 | |
|         rf = self._get_randfunc(randfunc)
 | |
|         obj = _DSA.generate_py(bits, rf, progress_func)    # TODO: Don't use legacy _DSA module
 | |
|         key = self._math.dsa_construct(obj.y, obj.g, obj.p, obj.q, obj.x)
 | |
|         return _DSAobj(self, key)
 | |
| 
 | |
|     def construct(self, tup):
 | |
|         key = self._math.dsa_construct(*tup)
 | |
|         return _DSAobj(self, key)
 | |
| 
 | |
| _impl = DSAImplementation()
 | |
| generate = _impl.generate
 | |
| construct = _impl.construct
 | |
| error = _impl.error
 | |
| 
 | |
| # vim:set ts=4 sw=4 sts=4 expandtab:
 | |
| 
 |