diff options
author | Alex Gaynor <alex.gaynor@gmail.com> | 2014-09-15 14:05:15 -0700 |
---|---|---|
committer | Alex Gaynor <alex.gaynor@gmail.com> | 2014-09-15 14:05:15 -0700 |
commit | 56a4739923a356ff5670b4620139ca55a2f30148 (patch) | |
tree | 405e2573eaacc37615607a349773d389078c31fc /paramiko/dsskey.py | |
parent | f74c7d76ec2ea9d39a4af6643761b648f81bd266 (diff) | |
download | paramiko-56a4739923a356ff5670b4620139ca55a2f30148.tar.gz |
Switched everything to use cryptography
Diffstat (limited to 'paramiko/dsskey.py')
-rw-r--r-- | paramiko/dsskey.py | 89 |
1 files changed, 65 insertions, 24 deletions
diff --git a/paramiko/dsskey.py b/paramiko/dsskey.py index 1901596d..87293e3c 100644 --- a/paramiko/dsskey.py +++ b/paramiko/dsskey.py @@ -21,20 +21,31 @@ DSS keys. """ import os -from hashlib import sha1 -from Crypto.PublicKey import DSA +from cryptography.exceptions import InvalidSignature +from cryptography.hazmat.backends import default_backend +from cryptography.hazmat.primitives import hashes +from cryptography.hazmat.primitives.asymmetric import dsa + +from pyasn1.codec.der import encoder, decoder +from pyasn1.type import namedtype, univ from paramiko import util from paramiko.common import zero_byte -from paramiko.py3compat import long from paramiko.ssh_exception import SSHException from paramiko.message import Message from paramiko.ber import BER, BERException from paramiko.pkey import PKey -class DSSKey (PKey): +class _DSSSigValue(univ.Sequence): + componentType = namedtype.NamedTypes( + namedtype.NamedType('r', univ.Integer()), + namedtype.NamedType('s', univ.Integer()) + ) + + +class DSSKey(PKey): """ Representation of a DSS key which can be used to sign an verify SSH2 data. @@ -98,20 +109,27 @@ class DSSKey (PKey): return self.x is not None def sign_ssh_data(self, data): - digest = sha1(data).digest() - dss = DSA.construct((long(self.y), long(self.g), long(self.p), long(self.q), long(self.x))) - # generate a suitable k - qsize = len(util.deflate_long(self.q, 0)) - while True: - k = util.inflate_long(os.urandom(qsize), 1) - if (k > 2) and (k < self.q): - break - r, s = dss.sign(util.inflate_long(digest, 1), k) + key = dsa.DSAPrivateNumbers( + x=self.x, + public_numbers=dsa.DSAPublicNumbers( + y=self.y, + parameter_numbers=dsa.DSAParameterNumbers( + p=self.p, + q=self.q, + g=self.g + ) + ) + ).private_key(backend=default_backend()) + signer = key.signer(hashes.SHA1()) + signer.update(data) + signature = signer.finalize() + (r, s), _ = decoder.decode(signature) + m = Message() m.add_string('ssh-dss') # apparently, in rare cases, r or s may be shorter than 20 bytes! - rstr = util.deflate_long(r, 0) - sstr = util.deflate_long(s, 0) + rstr = util.deflate_long(int(r), 0) + sstr = util.deflate_long(int(s), 0) if len(rstr) < 20: rstr = zero_byte * (20 - len(rstr)) + rstr if len(sstr) < 20: @@ -132,10 +150,28 @@ class DSSKey (PKey): # pull out (r, s) which are NOT encoded as mpints sigR = util.inflate_long(sig[:20], 1) sigS = util.inflate_long(sig[20:], 1) - sigM = util.inflate_long(sha1(data).digest(), 1) - dss = DSA.construct((long(self.y), long(self.g), long(self.p), long(self.q))) - return dss.verify(sigM, (sigR, sigS)) + sig_asn1 = _DSSSigValue() + sig_asn1.setComponentByName('r', sigR) + sig_asn1.setComponentByName('s', sigS) + signature = encoder.encode(sig_asn1) + + key = dsa.DSAPublicNumbers( + y=self.y, + parameter_numbers=dsa.DSAParameterNumbers( + p=self.p, + q=self.q, + g=self.g + ) + ).public_key(backend=default_backend()) + verifier = key.verifier(signature, hashes.SHA1()) + verifier.update(data) + try: + verifier.verify() + except InvalidSignature: + return False + else: + return True def _encode_key(self): if self.x is None: @@ -160,14 +196,19 @@ class DSSKey (PKey): generate a new host key or authentication key. :param int bits: number of bits the generated key should be. - :param function progress_func: - an optional function to call at key points in key generation (used - by ``pyCrypto.PublicKey``). + :param function progress_func: Unused :return: new `.DSSKey` private key """ - dsa = DSA.generate(bits, os.urandom, progress_func) - key = DSSKey(vals=(dsa.p, dsa.q, dsa.g, dsa.y)) - key.x = dsa.x + numbers = dsa.generate_private_key( + bits, backend=default_backend() + ).private_numbers() + key = DSSKey(vals=( + numbers.public_numbers.parameter_numbers.p, + numbers.public_numbers.parameter_numbers.q, + numbers.public_numbers.parameter_numbers.g, + numbers.public_numbers.y + )) + key.x = numbers.x return key generate = staticmethod(generate) |