summaryrefslogtreecommitdiffstats
path: root/base/common/python
diff options
context:
space:
mode:
authorAbhishek Koneru <akoneru@redhat.com>2014-07-24 11:20:12 -0400
committerAbhishek Koneru <akoneru@redhat.com>2014-08-27 01:15:35 -0400
commit6444287caa2ad171086d0ce9d93761a897247e06 (patch)
tree86e13cafc3f7b866be86b21cf0d96e401d0b9f01 /base/common/python
parent8e464b6ba5d83d7915978db5841967f20672dfd0 (diff)
downloadpki-6444287caa2ad171086d0ce9d93761a897247e06.tar.gz
pki-6444287caa2ad171086d0ce9d93761a897247e06.tar.xz
pki-6444287caa2ad171086d0ce9d93761a897247e06.zip
Generate asymmetric keys in the DRM.
Adds methods to key client to generate asymmetric keys using algorithms RSA and DSA for a valid key sizes of 512, 1024, 2048,4096. The generated keys are archived in the database. Using the CLI, the public key(base64 encoded) can be retrieved by using the key-show command. The private key(base64 encoded) can be retrieved using the key-retrieve command. Ticket #1023
Diffstat (limited to 'base/common/python')
-rw-r--r--base/common/python/pki/key.py116
1 files changed, 103 insertions, 13 deletions
diff --git a/base/common/python/pki/key.py b/base/common/python/pki/key.py
index af34a7ff4..0be438a28 100644
--- a/base/common/python/pki/key.py
+++ b/base/common/python/pki/key.py
@@ -105,7 +105,7 @@ class KeyInfo(object):
json_attribute_names = {
'clientKeyID': 'client_key_id', 'keyURL': 'key_url',
- 'ownerName': 'owner_name'
+ 'ownerName': 'owner_name', 'publicKey': 'public_key'
}
# pylint: disable-msg=C0103
@@ -117,6 +117,7 @@ class KeyInfo(object):
self.status = None
self.owner_name = None
self.size = None
+ self.public_key = None
@classmethod
def from_json(cls, attr_list):
@@ -127,6 +128,8 @@ class KeyInfo(object):
setattr(key_info, KeyInfo.json_attribute_names[k], v)
else:
setattr(key_info, k, v)
+ if key_info.public_key is not None:
+ key_info.public_key = base64.decodestring(key_info.public_key)
return key_info
def get_key_id(self):
@@ -339,7 +342,7 @@ class KeyRecoveryRequest(pki.ResourceMessage):
class SymKeyGenerationRequest(pki.ResourceMessage):
"""
Class representing the data sent to the DRM when generating and archiving
- a symmetric key on the DRM.
+ a symmetric key in the DRM.
"""
UNWRAP_USAGE = "unwrap"
@@ -363,6 +366,36 @@ class SymKeyGenerationRequest(pki.ResourceMessage):
self.add_attribute("transWrappedSessionKey", trans_wrapped_session_key)
+class AsymKeyGenerationRequest(pki.ResourceMessage):
+
+ """
+ Class representing the data sent to the DRM when generating and archiving
+ asymmetric keys in the DRM.
+ """
+ UNWRAP_USAGE = "unwrap"
+ WRAP_USAGE = "wrap"
+ VERIFY_USAGE = "verify"
+ VERIFY_RECOVER_USAGE = "verify_recover"
+ SIGN_USAGE = "sign"
+ SIGN_RECOVER_USAGE = "sign_recover"
+ DECRYPT_USAGE = "decrypt"
+ ENCRYPT_USAGE = "encrypt"
+ DERIVE_USAGE = "derive"
+
+ def __init__(self, client_key_id=None, key_size=None, key_algorithm=None,
+ key_usages=None, trans_wrapped_session_key=None):
+ """ Constructor """
+ pki.ResourceMessage.__init__(
+ self,
+ "com.netscape.certsrv.key.AsymKeyGenerationRequest")
+ key_usages = key_usages or []
+ self.add_attribute("clientKeyID", client_key_id)
+ self.add_attribute("keySize", key_size)
+ self.add_attribute("keyAlgorithm", key_algorithm)
+ self.add_attribute("keyUsage", ','.join(key_usages))
+ self.add_attribute("transWrappedSessionKey", trans_wrapped_session_key)
+
+
class KeyClient(object):
"""
Class that encapsulates and mirrors the functions in the KeyResource
@@ -383,6 +416,10 @@ class KeyClient(object):
RC4_ALGORITHM = "RC4"
AES_ALGORITHM = "AES"
+ # Asymmetric Key Algorithms
+ RSA_ALGORITHM = "RSA"
+ DSA_ALGORITHM = "DSA"
+
#default session key wrapping algorithm
DES_EDE3_CBC_OID = "{1 2 840 113549 3 7}"
@@ -509,12 +546,13 @@ class KeyClient(object):
self.connection.post(url, None, self.headers)
@pki.handle_exceptions()
- def create_request(self, request):
+ def submit_request(self, request):
""" Submit an archival, recovery or key generation request
to the DRM.
@param request - is either a KeyArchivalRequest,
- KeyRecoverRequest or SymKeyGenerationRequest.
+ KeyRecoverRequest, SymKeyGenerationRequest or
+ AsymKeyGenerationRequest.
returns a KeyRequestResponse object.
"""
@@ -558,7 +596,57 @@ class KeyClient(object):
key_size=size,
key_algorithm=algorithm,
key_usages=usages)
- return self.create_request(request)
+ return self.submit_request(request)
+
+ @pki.handle_exceptions()
+ def generate_asymmetric_key(self, client_key_id, algorithm=None,
+ key_size=None, usages=None,
+ trans_wrapped_session_key=None):
+ """ Generate and archive asymmetric keys in the DRM.
+ Supports algorithms RSA and DSA.
+ Valid key size for RSA = 256 + (16 * n), where n: 0-496
+ Valid key size for DSA = 512, 768, 1024. p,q,g params are not
+ supported.
+
+ Return a KeyRequestResponse which contains a KeyRequestInfo
+ object that describes the URL for the request and generated keys.
+
+ """
+ if client_key_id is None:
+ raise TypeError("Must specify Client Key ID")
+
+ if str(algorithm).upper() not in \
+ [self.RSA_ALGORITHM, self.DSA_ALGORITHM]:
+ raise TypeError("Only RSA and DSA algorithms are supported.")
+
+ # For generating keys using the RSA algorithm, the valid range of key
+ # sizes is:
+ # 256 + 16 * n, where 0 <= n <= 1008
+ # When using DSA, the current supported values are 512, 768, 1024
+
+ if algorithm == self.RSA_ALGORITHM:
+ if key_size < 256:
+ raise ValueError("Invalid key size specified.")
+ if ((key_size-256) % 16) != 0:
+ raise ValueError("Invalid key size specified.")
+ if algorithm == self.DSA_ALGORITHM:
+ if key_size not in [512, 768, 1024]:
+ raise ValueError("Invalid key size specified.")
+
+ if trans_wrapped_session_key is not None:
+ raise NotImplementedError(
+ "Returning the asymmetric keys in the same call is not yet "
+ "implemented.")
+
+ request = AsymKeyGenerationRequest(
+ client_key_id=client_key_id,
+ key_size=key_size,
+ key_algorithm=algorithm,
+ key_usages=usages,
+ trans_wrapped_session_key=trans_wrapped_session_key
+ )
+
+ return self.submit_request(request)
@pki.handle_exceptions()
def archive_key(self, client_key_id, data_type, private_data,
@@ -666,7 +754,7 @@ class KeyClient(object):
key_algorithm=key_algorithm,
key_size=key_size)
- return self.create_request(request)
+ return self.submit_request(request)
@pki.handle_exceptions()
def archive_pki_options(self, client_key_id, data_type, pki_archive_options,
@@ -701,7 +789,7 @@ class KeyClient(object):
pki_archive_options=data,
key_algorithm=key_algorithm,
key_size=key_size)
- return self.create_request(request)
+ return self.submit_request(request)
@pki.handle_exceptions()
def recover_key(self, key_id, request_id=None,
@@ -729,7 +817,7 @@ class KeyClient(object):
session_wrapped_passphrase=session_wrapped_passphrase,
certificate=b64certificate,
nonce_data=nonce_data)
- return self.create_request(request)
+ return self.submit_request(request)
@pki.handle_exceptions()
def retrieve_key_data(self, data):
@@ -770,9 +858,10 @@ class KeyClient(object):
1) trans_wrapped_session_key is not provided by caller.
- In this case, the function will call CryptoProvider methods to generate and
- wrap the session key. The function will return the KeyData object with
- a private_data attribute which stores the unwrapped key information.
+ In this case, the function will call CryptoProvider methods to generate
+ and wrap the session key. The function will return the KeyData object
+ with a private_data attribute which stores the unwrapped key
+ information.
2) The trans_wrapped_session_key is provided by the caller.
@@ -833,8 +922,8 @@ class KeyClient(object):
1) A passphrase is provided by the caller.
- In this case, CryptoProvider methods will be called to create the data to
- securely send the passphrase to the DRM. Basically, three pieces of
+ In this case, CryptoProvider methods will be called to create the data
+ to securely send the passphrase to the DRM. Basically, three pieces of
data will be sent:
- the passphrase wrapped by a 168 bit 3DES symmetric key (the session
@@ -894,6 +983,7 @@ encoder.NOTYPES['KeyArchivalRequest'] = KeyArchivalRequest
encoder.NOTYPES['KeyRecoveryRequest'] = KeyRecoveryRequest
encoder.NOTYPES['ResourceMessage'] = pki.ResourceMessage
encoder.NOTYPES['SymKeyGenerationRequest'] = SymKeyGenerationRequest
+encoder.NOTYPES['AsymKeyGenerationRequest'] = AsymKeyGenerationRequest
def main():