summaryrefslogtreecommitdiff
path: root/paramiko/dsskey.py
diff options
context:
space:
mode:
authorAlex Gaynor <alex.gaynor@gmail.com>2014-09-15 14:05:15 -0700
committerAlex Gaynor <alex.gaynor@gmail.com>2014-09-15 14:05:15 -0700
commit56a4739923a356ff5670b4620139ca55a2f30148 (patch)
tree405e2573eaacc37615607a349773d389078c31fc /paramiko/dsskey.py
parentf74c7d76ec2ea9d39a4af6643761b648f81bd266 (diff)
downloadparamiko-56a4739923a356ff5670b4620139ca55a2f30148.tar.gz
Switched everything to use cryptography
Diffstat (limited to 'paramiko/dsskey.py')
-rw-r--r--paramiko/dsskey.py89
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)