Skip to content

Commit

Permalink
PKey._write_private_key_file: pass the password along.
Browse files Browse the repository at this point in the history
  • Loading branch information
harley-gorrell committed Feb 24, 2017
1 parent 5061ee6 commit 739cbc9
Show file tree
Hide file tree
Showing 3 changed files with 47 additions and 3 deletions.
2 changes: 2 additions & 0 deletions demos/demo_keygen.py
Expand Up @@ -96,6 +96,8 @@ def progress(arg=None):

if options.newphrase:
phrase = getattr(options, 'newphrase')
# Turn it into bytes.
phrase=phrase.encode("utf-8")

if options.verbose:
pfunc = progress
Expand Down
10 changes: 8 additions & 2 deletions paramiko/pkey.py
Expand Up @@ -48,6 +48,12 @@ class PKey(object):
'blocksize': 16,
'mode': modes.CBC
},
'AES-256-CBC': {
'cipher': algorithms.AES,
'keysize': 32,
'blocksize': 16,
'mode': modes.CBC
},
'DES-EDE3-CBC': {
'cipher': algorithms.TripleDES,
'keysize': 24,
Expand Down Expand Up @@ -335,13 +341,13 @@ def _write_private_key_file(self, filename, key, format, password=None):
"""
with open(filename, 'w') as f:
os.chmod(filename, o600)
self._write_private_key(f, key, format)
self._write_private_key(f, key, format, password=password)

def _write_private_key(self, f, key, format, password=None):
if password is None:
encryption = serialization.NoEncryption()
else:
encryption = serialization.BestEncryption(password)
encryption = serialization.BestAvailableEncryption(password)

f.write(key.private_bytes(
serialization.Encoding.PEM,
Expand Down
38 changes: 37 additions & 1 deletion tests/test_pkey.py
Expand Up @@ -29,6 +29,7 @@

from paramiko import RSAKey, DSSKey, ECDSAKey, Message, util
from paramiko.py3compat import StringIO, byte_chr, b, bytes, PY2
from cryptography.hazmat.primitives.serialization import BestAvailableEncryption

from tests.util import test_path

Expand Down Expand Up @@ -120,6 +121,13 @@ def setUp(self):
def tearDown(self):
pass

def assert_keyfile_is_encrypted(self,keyfile):
"""A quick check that filename looks like an encrypted key."""
with open(keyfile,"r") as fh:
self.assertEqual(fh.readline()[:-1],"-----BEGIN RSA PRIVATE KEY-----")
self.assertEqual(fh.readline()[:-1],"Proc-Type: 4,ENCRYPTED")
self.assertEqual(fh.readline()[0:10],"DEK-Info: ")

def test_1_generate_key_bytes(self):
key = util.generate_key_bytes(md5, x1234, 'happy birthday', 30)
exp = b'\x61\xE1\xF2\x72\xF4\xC1\xC4\x56\x15\x86\xBD\x32\x24\x98\xC0\xE9\x24\x67\x27\x80\xF4\x7B\xB3\x7D\xDA\x7D\x54\x01\x9E\x64'
Expand Down Expand Up @@ -420,12 +428,13 @@ def test_salt_size(self):
file_ = test_path('test_rsa_password.key')
password = 'television'
newfile = file_ + '.new'
newpassword = 'radio'
newpassword = b'radio'
key = RSAKey(filename=file_, password=password)
# Write out a newly re-encrypted copy with a new password.
# When the bug under test exists, this will ValueError.
try:
key.write_private_key_file(newfile, password=newpassword)
self.assert_keyfile_is_encrypted(newfile)
# Verify the inner key data still matches (when no ValueError)
key2 = RSAKey(filename=newfile, password=newpassword)
self.assertEqual(key, key2)
Expand All @@ -436,3 +445,30 @@ def test_stringification(self):
key = RSAKey.from_private_key_file(test_path('test_rsa.key'))
comparable = TEST_KEY_BYTESTR_2 if PY2 else TEST_KEY_BYTESTR_3
self.assertEqual(str(key), comparable)

def test_BestAvailableEncryption(self):
# the ok case:
self.assertTrue(BestAvailableEncryption(b"password"))

# bad: not a string
with self.assertRaises(ValueError):
BestAvailableEncryption("not bytes")
# bad: too short
with self.assertRaises(ValueError):
BestAvailableEncryption(b"")

def test_keyfile_is_actually_encrypted(self):
# Read an existing encrypted private key
file_ = test_path('test_rsa_password.key')
# @todo: The decryptor takes string or bytes; Whereas encryption only takes bytes.
password = 'television'
newfile = file_ + '.new'
newpassword = b'radio'
key = RSAKey(filename=file_, password=password)
# Write out a newly re-encrypted copy with a new password.
# When the bug under test exists, this will ValueError.
try:
key.write_private_key_file(newfile, password=newpassword)
self.assert_keyfile_is_encrypted(newfile)
finally:
os.remove(newfile)

0 comments on commit 739cbc9

Please sign in to comment.