singe/thirdparty/openssl/tlslite-ng/tlslite/utils/python_dsakey.py
2023-11-16 22:15:24 -06:00

135 lines
3.7 KiB
Python

# Author: Frantisek Krenzelok
"""Pure-Python RSA implementation."""
from ecdsa.der import encode_sequence, encode_integer, \
remove_sequence, remove_integer
from .cryptomath import getRandomNumber, getRandomPrime, \
powMod, numBits, bytesToNumber, invMod, \
secureHash, GMPY2_LOADED, gmpyLoaded
from .compat import compatHMAC
if GMPY2_LOADED:
from gmpy2 import mpz
elif gmpyLoaded:
from gmpy import mpz
from .dsakey import DSAKey
class Python_DSAKey(DSAKey):
"""
Concrete implementaion of DSA object.
for func docstring see tlslite/dsakey.py
"""
def __init__(self, p=0, q=0, g=0, x=0, y=0):
if gmpyLoaded or GMPY2_LOADED:
p = mpz(p)
q = mpz(q)
g = mpz(g)
x = mpz(x)
y = mpz(y)
self.p = p
self.q = q
self.g = g
self.private_key = x
self.public_key = y
self.key_type = "dsa"
if p and q and p < q:
raise ValueError("q is greater than p")
def __len__(self):
return numBits(self.p)
def hasPrivateKey(self):
return bool(self.private_key)
@staticmethod
def generate(L, N):
assert (L, N) in [(1024, 160), (2048, 224), (2048, 256), (3072, 256)]
key = Python_DSAKey()
(q, p) = Python_DSAKey.generate_qp(L, N)
index = getRandomNumber(1, (p-1))
g = powMod(index, int((p-1)/q), p)
x = getRandomNumber(1, q-1)
y = powMod(g, x, p)
if gmpyLoaded or GMPY2_LOADED:
p = mpz(p)
q = mpz(q)
g = mpz(g)
x = mpz(x)
y = mpz(y)
key.q = q
key.p = p
key.g = g
key.private_key = x
key.public_key = y
return key
@staticmethod
def generate_qp(L, N):
assert (L, N) in [(1024, 160), (2048, 224), (2048, 256), (3072, 256)]
q = int(getRandomPrime(N))
while True:
p = int(getRandomPrime(L))
if (p-1) % q:
break
return (q, p)
def hashAndSign(self, data, hAlg="sha1"):
hashData = (secureHash(bytearray(data), hAlg))
return self.sign(hashData)
def sign(self, data):
N = numBits(self.q)
digest_len = len(data) * 8
digest = bytesToNumber(data)
if N < digest_len:
digest >>= digest_len - N
k = getRandomNumber(1, (self.q-1))
r = powMod(self.g, k, self.p) % self.q
s = invMod(k, self.q) * (digest + self.private_key * r) % self.q
return encode_sequence(encode_integer(r), encode_integer(s))
def verify(self, signature, hashData):
N = numBits(self.q)
digest_len = len(hashData) * 8
digest = bytesToNumber(hashData)
if N < digest_len:
digest >>= digest_len - N
signature = compatHMAC(signature)
# get r, s keys
if not signature:
return False
body, rest = remove_sequence(signature)
if rest:
return False
r, rest = remove_integer(body)
s, rest = remove_integer(rest)
if rest:
return False
if gmpyLoaded or GMPY2_LOADED:
r = mpz(r)
s = mpz(s)
# check the signature
if 0 < r < self.q and 0 < s < self.q:
w = invMod(s, self.q)
u1 = (digest * w) % self.q
u2 = (r * w) % self.q
v = ((powMod(self.g, u1, self.p) * \
powMod(self.public_key, u2, self.p)) % self.p) % self.q
return r == v
return False
def hashAndVerify(self, signature, data, hAlg="sha1"):
digest = secureHash(bytearray(data), hAlg)
return self.verify(signature, digest)