class CursiveException(Exception): """Base Cursive Exception To correctly use this class, inherit from it and define a 'msg_fmt' property. That msg_fmt will get printf'd with the keyword arguments provided to the constructor. """ msg_fmt = _("An unknown exception occurred.") headers = {} safe = False def __init__(self, message=None, **kwargs): self.kwargs = kwargs if not message: try: message = self.msg_fmt % kwargs except Exception: # at least get the core message out if something happened message = self.msg_fmt self.message = message super(CursiveException, self).__init__(message) def format_message(self): # NOTE(dane-fichter): use the first argument to the python Exception # object which should be our full CursiveException message return self.args[0]
def get_verifier(context, img_signature_certificate_uuid, img_signature_hash_method, img_signature, img_signature_key_type): """Instantiate signature properties and use them to create a verifier. :param context: the user context for authentication :param img_signature_certificate_uuid: uuid of signing certificate stored in key manager :param img_signature_hash_method: string denoting hash method used to compute signature :param img_signature: string of base64 encoding of signature :param img_signature_key_type: string denoting type of keypair used to compute signature :returns: instance of cryptography.hazmat.primitives.asymmetric.AsymmetricVerificationContext :raises: SignatureVerificationError if we fail to build the verifier """ image_meta_props = {'img_signature_uuid': img_signature_certificate_uuid, 'img_signature_hash_method': img_signature_hash_method, 'img_signature': img_signature, 'img_signature_key_type': img_signature_key_type} for key in image_meta_props.keys(): if image_meta_props[key] is None: raise exception.SignatureVerificationError( reason=_('Required image properties for signature verification' ' do not exist. Cannot verify signature. Missing' ' property: %s') % key) signature = get_signature(img_signature) hash_method = get_hash_method(img_signature_hash_method) signature_key_type = SignatureKeyType.lookup(img_signature_key_type) public_key = get_public_key(context, img_signature_certificate_uuid, signature_key_type) # create the verifier based on the signature key type verifier = signature_key_type.create_verifier(signature, hash_method, public_key) if verifier: return verifier else: # Error creating the verifier raise exception.SignatureVerificationError( reason=_('Error occurred while creating the verifier'))
def get_certificate(context, signature_certificate_uuid): """Create the certificate object from the retrieved certificate data. :param context: the user context for authentication :param signature_certificate_uuid: the uuid to use to retrieve the certificate :returns: the certificate cryptography object :raises: SignatureVerificationError if the retrieval fails or the format is invalid """ keymgr_api = key_manager.API() try: # The certificate retrieved here is a castellan certificate object cert = keymgr_api.get(context, signature_certificate_uuid) except ManagedObjectNotFoundError as e: raise exception.SignatureVerificationError( reason=_('Certificate not found with ID: %s') % signature_certificate_uuid) except KeyManagerError as e: # The problem encountered may be backend-specific, since castellan # can use different backends. Rather than importing all possible # backends here, the generic "Exception" is used. msg = (_LE("Unable to retrieve certificate with ID %(id)s: %(e)s") % {'id': signature_certificate_uuid, 'e': encodeutils.exception_to_unicode(e)}) LOG.error(msg) raise exception.SignatureVerificationError( reason=_('Unable to retrieve certificate with ID: %s') % signature_certificate_uuid) if cert.format not in CERTIFICATE_FORMATS: raise exception.SignatureVerificationError( reason=_('Invalid certificate format: %s') % cert.format) if cert.format == X_509: # castellan always encodes certificates in DER format cert_data = cert.get_encoded() certificate = x509.load_der_x509_certificate(cert_data, default_backend()) return certificate
def lookup(cls, name): """Look up the signature key type. :param name: the name of the signature key type :returns: the SignatureKeyType object :raises: SignatureVerificationError if signature key type is invalid """ if name not in cls.REGISTERED_TYPES: raise exception.SignatureVerificationError( reason=_('Invalid signature key type: %s') % name) return cls.REGISTERED_TYPES[name]
def get_hash_method(hash_method_name): """Verify the hash method name and create the hash method. :param hash_method_name: the name of the hash method to retrieve :returns: the hash method, a cryptography object :raises: SignatureVerificationError if the hash method name is invalid """ if hash_method_name not in HASH_METHODS: raise exception.SignatureVerificationError( reason=_('Invalid signature hash method: %s') % hash_method_name) return HASH_METHODS[hash_method_name]
def get_signature(signature_data): """Decode the signature data and returns the signature. :param signature_data: the base64-encoded signature data :returns: the decoded signature :raises: SignatureVerificationError if the signature data is malformatted """ try: signature = base64.decode_as_bytes(signature_data) except (TypeError, binascii.Error): raise exception.SignatureVerificationError( reason=_('The signature data was not properly ' 'encoded using base64')) return signature
def get_public_key(context, signature_certificate_uuid, signature_key_type): """Create the public key object from a retrieved certificate. :param context: the user context for authentication :param signature_certificate_uuid: the uuid to use to retrieve the certificate :param signature_key_type: a SignatureKeyType object :returns: the public key cryptography object :raises: SignatureVerificationError if public key format is invalid """ certificate = get_certificate(context, signature_certificate_uuid) # Note that this public key could either be # RSAPublicKey, DSAPublicKey, or EllipticCurvePublicKey public_key = certificate.public_key() # Confirm the type is of the type expected based on the signature key type if not isinstance(public_key, signature_key_type.public_key_type): raise exception.SignatureVerificationError( reason=_('Invalid public key type for signature key type: %s') % signature_key_type.name) return public_key
class SignatureVerificationError(CursiveException): msg_fmt = _("Signature verification for the image " "failed: %(reason)s.")