Skip to content

Commit

Permalink
[Fix #20] Sign key with sha1 on Solaris 10 on other systems which don…
Browse files Browse the repository at this point in the history
…'t support sha256.
  • Loading branch information
adiroiban committed Apr 20, 2015
1 parent bc3b544 commit 62fdd01
Show file tree
Hide file tree
Showing 11 changed files with 96 additions and 214 deletions.
11 changes: 9 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -64,12 +64,19 @@ endif
dev_deps:
@$(BASE_PATH)/pip install buildbot

test_remote:
git_push:
@echo 'Sending commited changes before sending patch'
@git push

test_remote: git_push
ifeq "$(TARGET)" ""
$(BUILDBOT_TRY) --get-builder-names | grep keycert
else
$(BUILDBOT_TRY) -b $(TARGET)
endif

test_remote_with_clean:
test_remote_with_clean: git_push
$(BUILDBOT_TRY) -b $(TARGET) --properties=force_clean=yes

test_remote_with_wait: git_push
$(BUILDBOT_TRY) -b $(TARGET) --wait
4 changes: 2 additions & 2 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,8 @@ It depends on these C modules:

It provides the following functionalities:

* Generate SSL key and self signed SSL certificate.
* Generate SSL key and CSR.
* Generate SSL key and self signed SSL certificate signed with SHA1.
* Generate SSL key and CSR. Signed with SHA256 or fall back to SHA1.
* Generate RSA/DSA keys.
* Convert OpenSSH, SSH.com, Putty, LSH.
* Populate an argparser subparser with command line options.
Expand Down
4 changes: 2 additions & 2 deletions chevah/keycert/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,10 @@
import sys


def _path(path, encoding):
def _path(path, encoding='utf-8'):
if os.name != 'posix' or sys.platform.startswith('darwin'):
# On Windows and OSX we always use unicode.
# We don't run yet tests on Windows and OSX.
return path # pragma: no cover

return path.encode('utf-8')
return path.encode(encoding)
9 changes: 3 additions & 6 deletions chevah/keycert/ssh.py
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,7 @@ def generate_ssh_key(options, open_method=None):
key_type = options.key_type.lower()

if not hasattr(options, 'key_file') or options.key_file is None:
options.key_file = 'id_%s' % (key_type)
options.key_file = u'id_%s' % (key_type)

private_file = options.key_file

Expand All @@ -132,10 +132,7 @@ def generate_ssh_key(options, open_method=None):

key = Key.generate(key_type=key_type, key_size=key_size)

private_file_path = local_filesystem.getEncodedPath(private_file)
public_file_path = local_filesystem.getEncodedPath(public_file)

with open_method(private_file_path, 'wb') as file_handler:
with open_method(_path(private_file), 'wb') as file_handler:
_store_OpenSSH(key, private_file=file_handler)

key_comment = None
Expand All @@ -145,7 +142,7 @@ def generate_ssh_key(options, open_method=None):
else:
message_comment = u'without a comment'

with open_method(public_file_path, 'wb') as file_handler:
with open_method(_path(public_file), 'wb') as file_handler:
_store_OpenSSH(key, public_file=file_handler, comment=key_comment)

message = (
Expand Down
10 changes: 9 additions & 1 deletion chevah/keycert/ssl.py
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,9 @@ def _generate_csr(options):
"""
Helper to catch all crypto errors and reduce indentation.
"""
if options.key_size < 512:
raise KeyCertException('Key size must be greater or equal to 512.')

key_type = crypto.TYPE_RSA

csr = crypto.X509Req()
Expand Down Expand Up @@ -188,7 +191,12 @@ def _generate_csr(options):

csr.add_extensions(extensions)
csr.set_pubkey(key)
csr.sign(key, 'sha256')

try:
csr.sign(key, 'sha256')
except ValueError: # pragma: no cover
# If SHA256 is not supported, fallback to sha1.
csr.sign(key, 'sha1')

csr_pem = crypto.dump_certificate_request(crypto.FILETYPE_PEM, csr)
if options.key_password:
Expand Down
25 changes: 18 additions & 7 deletions chevah/keycert/tests/test_ssh.py
Original file line number Diff line number Diff line change
Expand Up @@ -1798,16 +1798,26 @@ def setUp(self):
help='Available sub-commands', dest='sub_command')
generate_ssh_key_parser(subparser, self.sub_command_name)

def assertPathEqual(self, expected, actual):
"""
Check that pats are equal.
"""
if self.os_family == 'posix':
expected = expected.encode('utf-8')
self.assertEqual(expected, actual)

def test_generate_ssh_key_custom_values(self):
"""
When custom values are provided, the key is generated using those
values.
"""
file_name = mk.string()
file_name_pub = file_name + u'.pub'
options = self.parseArguments([
self.sub_command_name,
'--key-size=512',
'--key-type=DSA',
'--key-file=test_file',
u'--key-file=' + file_name,
'--key-comment=this is a comment',
])
open_method = DummyOpenContext()
Expand All @@ -1820,23 +1830,24 @@ def test_generate_ssh_key_custom_values(self):

# First it writes the private key.
first_file = open_method.calls.pop(0)
self.assertEqual('test_file', first_file['path'])
self.assertPathEqual(file_name, first_file['path'])
self.assertEqual('wb', first_file['mode'])
self.assertEqual(
key.toString('openssh'), first_file['stream'].getvalue())

# Second it writes the public key.
second_file = open_method.calls.pop(0)
self.assertEqual('test_file.pub', second_file['path'])
self.assertPathEqual(file_name_pub, second_file['path'])
self.assertEqual('wb', second_file['mode'])
self.assertEqual(
key.public().toString('openssh', 'this is a comment'),
second_file['stream'].getvalue())

self.assertEqual(
u'SSH key of type "dsa" and length "512" generated as public '
u'key file "test_file.pub" and private key file "test_file" '
u'having comment "this is a comment".',
u'key file "%s" and private key file "%s" '
u'having comment "this is a comment".' % (
file_name_pub, file_name),
message,
)
self.assertEqual(0, exit_code)
Expand All @@ -1861,14 +1872,14 @@ def test_generate_ssh_key_default_values(self):

# First it writes the private key.
first_file = open_method.calls.pop(0)
self.assertEqual('id_rsa', first_file['path'])
self.assertPathEqual(u'id_rsa', first_file['path'])
self.assertEqual('wb', first_file['mode'])
self.assertEqual(
key.toString('openssh'), first_file['stream'].getvalue())

# Second it writes the public key.
second_file = open_method.calls.pop(0)
self.assertEqual('id_rsa.pub', second_file['path'])
self.assertPathEqual(u'id_rsa.pub', second_file['path'])
self.assertEqual('wb', second_file['mode'])
self.assertEqual(
key.public().toString('openssh'), second_file['stream'].getvalue())
Expand Down
4 changes: 3 additions & 1 deletion chevah/keycert/tests/test_ssl.py
Original file line number Diff line number Diff line change
Expand Up @@ -190,7 +190,9 @@ def test_bad_size(self):
with self.assertRaises(KeyCertException) as context:
generate_csr(options)

self.assertEqual('key size too small', context.exception.message)
self.assertEqual(
'Key size must be greater or equal to 512.',
context.exception.message)

def test_bad_country_long(self):
"""
Expand Down
2 changes: 1 addition & 1 deletion keycert-demo.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
generate_and_store_csr,
)

parser = argparse.ArgumentParser(prog='PROG', prefix_chars='-+')
parser = argparse.ArgumentParser(prog='PROG')
subparser = parser.add_subparsers(
help='Available sub-commands', dest='sub_command')

Expand Down

0 comments on commit 62fdd01

Please sign in to comment.