mirror of
https://github.com/noDRM/DeDRM_tools.git
synced 2024-08-25 18:46:10 +06:00
135 lines
4.3 KiB
Python
135 lines
4.3 KiB
Python
|
# -*- 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:
|
||
|
|