summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorAlex Gaynor <alex.gaynor@gmail.com>2015-03-18 07:54:23 -0400
committerAlex Gaynor <alex.gaynor@gmail.com>2015-03-18 07:54:23 -0400
commitffcbc09d314d710f5db87573b398be1c8c5f177c (patch)
treea33105d9d10079b749d54dbab204baadcb0ae8d8
parent6ed173a4606e404a3908926beabc02b50a5ad8a8 (diff)
More progress towards cleanup
-rw-r--r--paramiko/dsskey.py51
-rw-r--r--paramiko/ecdsakey.py27
-rw-r--r--paramiko/pkey.py51
-rw-r--r--paramiko/rsakey.py51
4 files changed, 99 insertions, 81 deletions
diff --git a/paramiko/dsskey.py b/paramiko/dsskey.py
index 8e0c2ba9..2f1c1ec8 100644
--- a/paramiko/dsskey.py
+++ b/paramiko/dsskey.py
@@ -22,7 +22,7 @@ DSS keys.
from cryptography.exceptions import InvalidSignature
from cryptography.hazmat.backends import default_backend
-from cryptography.hazmat.primitives import hashes
+from cryptography.hazmat.primitives import hashes, serialization
from cryptography.hazmat.primitives.asymmetric import dsa
from cryptography.hazmat.primitives.asymmetric.utils import (
decode_rfc6979_signature, encode_rfc6979_signature
@@ -160,22 +160,45 @@ class DSSKey(PKey):
else:
return True
- def _encode_key(self):
- if self.x is None:
- raise SSHException('Not enough key information')
- keylist = [0, self.p, self.q, self.g, self.y, self.x]
- try:
- b = BER()
- b.encode(keylist)
- except BERException:
- raise SSHException('Unable to create ber encoding of key')
- return b.asbytes()
-
def write_private_key_file(self, filename, password=None):
- self._write_private_key_file('DSA', filename, self._encode_key(), password)
+ 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())
+
+ self._write_private_key_file(
+ filename,
+ key,
+ serialization.Format.TraditionalOpenSSL,
+ password=password
+ )
def write_private_key(self, file_obj, password=None):
- self._write_private_key('DSA', file_obj, self._encode_key(), password)
+ 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())
+
+ self._write_private_key(
+ file_obj,
+ key,
+ serialization.Format.TraditionalOpenSSL,
+ password=password
+ )
@staticmethod
def generate(bits=1024, progress_func=None):
diff --git a/paramiko/ecdsakey.py b/paramiko/ecdsakey.py
index af9200c0..16a2c3db 100644
--- a/paramiko/ecdsakey.py
+++ b/paramiko/ecdsakey.py
@@ -144,12 +144,20 @@ class ECDSAKey(PKey):
return True
def write_private_key_file(self, filename, password=None):
- with open(filename, "w") as f:
- self.write_private_key(f, password=password)
+ self._write_private_key_file(
+ filename,
+ self.signing_key,
+ serialization.Format.TraditionalOpenSSL,
+ password=password
+ )
def write_private_key(self, file_obj, password=None):
- key = self.signing_key or self.verifying_key
- file_obj.write(self._to_pem(key, password=password).decode())
+ self._write_private_key(
+ file_obj,
+ self.signing_key,
+ serialization.Format.TraditionalOpenSSL,
+ password=password
+ )
@staticmethod
def generate(curve=ec.SECP256R1(), progress_func=None):
@@ -182,17 +190,6 @@ class ECDSAKey(PKey):
self.verifying_key = key.public_key()
self.size = key.curve.key_size
- def _to_pem(self, key, password):
- if password is None:
- encryption = serialization.NoEncryption()
- else:
- encryption = serialization.BestEncryption(password)
- return key.private_bytes(
- serialization.Encoding.PEM,
- serialization.PrivateFormat.TraditionalOpenSSL,
- encryption
- )
-
def _sigencode(self, r, s):
msg = Message()
msg.add_mpint(r)
diff --git a/paramiko/pkey.py b/paramiko/pkey.py
index 24fb0d60..b21a867c 100644
--- a/paramiko/pkey.py
+++ b/paramiko/pkey.py
@@ -21,15 +21,16 @@ Common API for all public keys.
"""
import base64
-from binascii import hexlify, unhexlify
+from binascii import unhexlify
import os
from hashlib import md5
from cryptography.hazmat.backends import default_backend
+from cryptography.hazmat.primitives import serialization
from cryptography.hazmat.primitives.ciphers import algorithms, modes, Cipher
from paramiko import util
-from paramiko.common import o600, zero_byte
+from paramiko.common import o600
from paramiko.py3compat import u, encodebytes, decodebytes, b
from paramiko.ssh_exception import SSHException, PasswordRequiredException
@@ -316,7 +317,7 @@ class PKey(object):
).decryptor()
return decryptor.update(data) + decryptor.finalize()
- def _write_private_key_file(self, tag, filename, data, password=None):
+ def _write_private_key_file(self, filename, key, format, password=None):
"""
Write an SSH2-format private key file in a form that can be read by
paramiko or openssh. If no password is given, the key is written in
@@ -333,34 +334,16 @@ class PKey(object):
with open(filename, 'w', o600) as f:
# grrr... the mode doesn't always take hold
os.chmod(filename, o600)
- self._write_private_key(tag, f, data, password)
-
- def _write_private_key(self, tag, f, data, password=None):
- f.write('-----BEGIN %s PRIVATE KEY-----\n' % tag)
- if password is not None:
- cipher_name = list(self._CIPHER_TABLE.keys())[0]
- cipher = self._CIPHER_TABLE[cipher_name]['cipher']
- keysize = self._CIPHER_TABLE[cipher_name]['keysize']
- blocksize = self._CIPHER_TABLE[cipher_name]['blocksize']
- mode = self._CIPHER_TABLE[cipher_name]['mode']
- salt = os.urandom(blocksize)
- key = util.generate_key_bytes(md5, salt, password, keysize)
- if len(data) % blocksize != 0:
- n = blocksize - len(data) % blocksize
- #data += os.urandom(n)
- # that would make more sense ^, but it confuses openssh.
- data += zero_byte * n
- encryptor = Cipher(
- cipher(key), mode(salt), backend=default_backend()
- ).encryptor()
- data = encryptor.update(data) + encryptor.finalize()
- f.write('Proc-Type: 4,ENCRYPTED\n')
- f.write('DEK-Info: %s,%s\n' % (cipher_name, u(hexlify(salt)).upper()))
- f.write('\n')
- s = u(encodebytes(data))
- # re-wrap to 64-char lines
- s = ''.join(s.split('\n'))
- s = '\n'.join([s[i: i + 64] for i in range(0, len(s), 64)])
- f.write(s)
- f.write('\n')
- f.write('-----END %s PRIVATE KEY-----\n' % tag)
+ self._write_private_key(f, key, format)
+
+ def _write_private_key(self, f, key, format, password=None):
+ if password is None:
+ encryption = serialization.NoEncryption()
+ else:
+ encryption = serialization.BestEncryption(password)
+
+ f.write(key.private_bytes(
+ serialization.Encoding.PEM,
+ format,
+ encryption
+ ))
diff --git a/paramiko/rsakey.py b/paramiko/rsakey.py
index aac57f91..17fa6104 100644
--- a/paramiko/rsakey.py
+++ b/paramiko/rsakey.py
@@ -20,11 +20,9 @@
RSA keys.
"""
-import os
-
from cryptography.exceptions import InvalidSignature
from cryptography.hazmat.backends import default_backend
-from cryptography.hazmat.primitives import hashes
+from cryptography.hazmat.primitives import hashes, serialization
from cryptography.hazmat.primitives.asymmetric import rsa, padding
from paramiko import util
@@ -136,24 +134,41 @@ class RSAKey(PKey):
else:
return True
- def _encode_key(self):
- if (self.p is None) or (self.q is None):
- raise SSHException('Not enough key info to write private key file')
- keylist = [0, self.n, self.e, self.d, self.p, self.q,
- self.d % (self.p - 1), self.d % (self.q - 1),
- util.mod_inverse(self.q, self.p)]
- try:
- b = BER()
- b.encode(keylist)
- except BERException:
- raise SSHException('Unable to create ber encoding of key')
- return b.asbytes()
-
def write_private_key_file(self, filename, password=None):
- self._write_private_key_file('RSA', filename, self._encode_key(), password)
+ key = rsa.RSAPrivateNumbers(
+ p=self.p,
+ q=self.q,
+ d=self.d,
+ dmp1=self.dmp1,
+ dmq1=self.dmq1,
+ iqmp=self.iqmp,
+ public_numbers=rsa.RSAPublicNumbers(self.e, self.n)
+ ).private_key(backend=default_backend())
+
+ self._write_private_key_file(
+ filename,
+ key,
+ serialization.Format.TraditionalOpenSSL,
+ password=password
+ )
def write_private_key(self, file_obj, password=None):
- self._write_private_key('RSA', file_obj, self._encode_key(), password)
+ key = rsa.RSAPrivateNumbers(
+ p=self.p,
+ q=self.q,
+ d=self.d,
+ dmp1=self.dmp1,
+ dmq1=self.dmq1,
+ iqmp=self.iqmp,
+ public_numbers=rsa.RSAPublicNumbers(self.e, self.n)
+ ).private_key(backend=default_backend())
+
+ self._write_private_key(
+ file_obj,
+ key,
+ serialization.Format.TraditionalOpenSSL,
+ password=password
+ )
@staticmethod
def generate(bits, progress_func=None):