Viewing file: DSA.py (6.25 KB) -rw-r--r-- Select action/file-type: (+) | (+) | (+) | Code (+) | Session (+) | (+) | SDB (+) | (+) | (+) | (+) | (+) | (+) |
# -*- 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']
from Crypto.Util.python_compat 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") 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:
|