Package list python-castellan / cf2d3b4
Update mock key manager Adds functionality to the mock key manager for create_key_pair. Change-Id: Iff5c3f9f088da422c088aa9dcac3f39deedcd2d6 Kaitlin Farr 6 years ago
3 changed file(s) with 139 addition(s) and 4 deletion(s). Raw diff Collapse all Expand all
2929 import random
3030 import uuid
3131
32 from cryptography.hazmat import backends
33 from cryptography.hazmat.primitives.asymmetric import rsa
34 from cryptography.hazmat.primitives import serialization
35
3236 from castellan.common import exception
37 from castellan.common.objects import private_key as pri_key
38 from castellan.common.objects import public_key as pub_key
3339 from castellan.common.objects import symmetric_key as sym_key
3440 from castellan.key_manager import key_manager
3541
6773 def create_key(self, context, **kwargs):
6874 """Creates a symmetric key.
6975
70 This implementation returns a UUID for the created key. A
71 Forbidden exception is raised if the specified context is None.
76 This implementation returns a UUID for the created key. The algorithm
77 for the key will always be AES. A Forbidden exception is raised if the
78 specified context is None.
7279 """
7380 if context is None:
7481 raise exception.Forbidden()
7683 key = self._generate_key(**kwargs)
7784 return self.store(context, key)
7885
86 def _generate_public_and_private_key(self, length):
87 crypto_private_key = rsa.generate_private_key(
88 public_exponent=65537,
89 key_size=length,
90 backend=backends.default_backend())
91
92 private_der = crypto_private_key.private_bytes(
93 encoding=serialization.Encoding.DER,
94 format=serialization.PrivateFormat.PKCS8,
95 encryption_algorithm=serialization.NoEncryption())
96
97 crypto_public_key = crypto_private_key.public_key()
98
99 public_der = crypto_public_key.public_bytes(
100 encoding=serialization.Encoding.DER,
101 format=serialization.PublicFormat.SubjectPublicKeyInfo)
102
103 private_key = pri_key.PrivateKey(
104 algorithm='RSA',
105 bit_length=length,
106 key=bytearray(private_der))
107
108 public_key = pub_key.PublicKey(
109 algorithm='RSA',
110 bit_length=length,
111 key=bytearray(public_der))
112
113 return private_key, public_key
114
79115 def create_key_pair(self, context, algorithm, length, expiration=None):
80 raise NotImplementedError()
116 """Creates an asymmetric key pair.
117
118 This implementation returns UUIDs for the created keys in the order:
119 (private, public)
120 Forbidden is raised if the context is None.
121 """
122 if context is None:
123 raise exception.Forbidden()
124
125 if algorithm.lower() != 'rsa':
126 msg = 'Invalid algorithm: {}, only RSA supported'.format(algorithm)
127 raise ValueError(msg)
128
129 valid_lengths = [2048, 3072, 4096]
130
131 if length not in valid_lengths:
132 msg = 'Invalid bit length: {}, only {} supported'.format(
133 length, valid_lengths)
134 raise ValueError(msg)
135
136 private_key, public_key = self._generate_public_and_private_key(length)
137
138 private_key_uuid = self.store(context, private_key)
139 public_key_uuid = self.store(context, public_key)
140
141 return private_key_uuid, public_key_uuid
81142
82143 def _generate_key_id(self):
83144 key_id = str(uuid.uuid4())
1616 Test cases for the mock key manager.
1717 """
1818
19 from cryptography.hazmat import backends
20 from cryptography.hazmat.primitives.asymmetric import padding
21 from cryptography.hazmat.primitives import hashes
22 from cryptography.hazmat.primitives import serialization
1923 from oslo_context import context
2024
2125 from castellan.common import exception
2226 from castellan.common.objects import symmetric_key as sym_key
2327 from castellan.tests.unit.key_manager import mock_key_manager as mock_key_mgr
2428 from castellan.tests.unit.key_manager import test_key_manager as test_key_mgr
29
30
31 def get_cryptography_private_key(private_key):
32 crypto_private_key = serialization.load_der_private_key(
33 bytes(private_key.get_encoded()),
34 password=None,
35 backend=backends.default_backend())
36 return crypto_private_key
37
38
39 def get_cryptography_public_key(public_key):
40 crypto_public_key = serialization.load_der_public_key(
41 bytes(public_key.get_encoded()),
42 backend=backends.default_backend())
43 return crypto_public_key
2544
2645
2746 class MockKeyManagerTestCase(test_key_mgr.KeyManagerTestCase):
4665 key = self.key_mgr.get(self.context, key_id)
4766 self.assertEqual(length / 8, len(key.get_encoded()))
4867
49 def test_create_null_context(self):
68 def test_create_key_null_context(self):
5069 self.assertRaises(exception.Forbidden,
5170 self.key_mgr.create_key, None)
71
72 def test_create_key_pair(self):
73 for length in [2048, 3072, 4096]:
74 private_key_uuid, public_key_uuid = self.key_mgr.create_key_pair(
75 self.context, 'RSA', length)
76
77 private_key = self.key_mgr.get(self.context, private_key_uuid)
78 public_key = self.key_mgr.get(self.context, public_key_uuid)
79
80 crypto_private_key = get_cryptography_private_key(private_key)
81 crypto_public_key = get_cryptography_public_key(public_key)
82
83 self.assertEqual(length, crypto_private_key.key_size)
84 self.assertEqual(length, crypto_public_key.key_size)
85
86 def test_create_key_pair_encryption(self):
87 private_key_uuid, public_key_uuid = self.key_mgr.create_key_pair(
88 self.context, 'RSA', 2048)
89
90 private_key = self.key_mgr.get(self.context, private_key_uuid)
91 public_key = self.key_mgr.get(self.context, public_key_uuid)
92
93 crypto_private_key = get_cryptography_private_key(private_key)
94 crypto_public_key = get_cryptography_public_key(public_key)
95
96 message = b'secret plaintext'
97 ciphertext = crypto_public_key.encrypt(
98 message,
99 padding.OAEP(
100 mgf=padding.MGF1(algorithm=hashes.SHA1()),
101 algorithm=hashes.SHA1(),
102 label=None))
103 plaintext = crypto_private_key.decrypt(
104 ciphertext,
105 padding.OAEP(
106 mgf=padding.MGF1(algorithm=hashes.SHA1()),
107 algorithm=hashes.SHA1(),
108 label=None))
109
110 self.assertEqual(message, plaintext)
111
112 def test_create_key_pair_null_context(self):
113 self.assertRaises(exception.Forbidden,
114 self.key_mgr.create_key_pair, None, 'RSA', 2048)
115
116 def test_create_key_pair_invalid_algorithm(self):
117 self.assertRaises(ValueError,
118 self.key_mgr.create_key_pair,
119 self.context, 'DSA', 2048)
120
121 def test_create_key_pair_invalid_length(self):
122 self.assertRaises(ValueError,
123 self.key_mgr.create_key_pair,
124 self.context, 'RSA', 10)
52125
53126 def test_store_and_get_key(self):
54127 secret_key = bytes(b'0' * 64)
33
44 pbr>=0.6,!=0.7,<1.0
55 Babel>=1.3
6 cryptography>=0.9.1 # Apache-2.0
67 oslo.config>=1.9.3,<1.10.0 # Apache-2.0
78 oslo.context>=0.2.0 # Apache-2.0
89 oslo.log>=1.0.0,<1.1.0 # Apache-2.0