def check_back_signatures(key, subkey_binding_signature, strict=False, current_time=None):
    """Validates the backsignature of a subkey binding signature if one
    exists.
    """

    for sig in subkey_binding_signature.embedded_signatures:
        if sig.signature_type == constants.PRIMARY_KEY_BINDING_SIGNATURE:
            hashed_subpacket_data = get_hashed_subpacket_data(subkey_binding_signature)
            target = subkey_binding_signature.target()
            if not target:
                continue
            hash_ = utils.hash_packet_for_signature(
                key.to_packet(),
                sig.signature_type,
                sig.version,
                sig.hash_algorithm,
                sig.creation_time,
                sig.public_key_algorithm,
                target.to_packet(),
                hashed_subpacket_data,
            )
            try:
                check_signature(key, sig, hash_, strict, current_time)
            except InvalidSignature as e:
                raise_with(InvalidBackSignature(target.key_id), e)

    if subkey_binding_signature.may_sign_data:
        # "For subkeys that can issue signatures, the subkey binding
        #  signature MUST contain an Embedded Signature subpacket with a
        #  primary key binding signature (0x19) issued by the subkey on
        #  the top-level key."
        raise MissingBackSignature()
def check_back_signatures(key,
                          subkey_binding_signature,
                          strict=False,
                          current_time=None):
    """Validates the backsignature of a subkey binding signature if one
    exists.
    """

    for sig in subkey_binding_signature.embedded_signatures:
        if sig.signature_type == constants.PRIMARY_KEY_BINDING_SIGNATURE:
            hashed_subpacket_data = get_hashed_subpacket_data(
                subkey_binding_signature)
            target = subkey_binding_signature.target()
            if not target:
                continue
            hash_ = utils.hash_packet_for_signature(
                key.to_packet(), sig.signature_type, sig.version,
                sig.hash_algorithm, sig.creation_time,
                sig.public_key_algorithm, target.to_packet(),
                hashed_subpacket_data)
            try:
                check_signature(key, sig, hash_, strict, current_time)
            except InvalidSignature as e:
                raise_with(InvalidBackSignature(target.key_id), e)

    if subkey_binding_signature.may_sign_data:
        # "For subkeys that can issue signatures, the subkey binding
        #  signature MUST contain an Embedded Signature subpacket with a
        #  primary key binding signature (0x19) issued by the subkey on
        #  the top-level key."
        raise MissingBackSignature()
Beispiel #3
0
    def target(self):
        parent = self.parent
        # get target subpacket
        subpackets = self._get_subpackets(C.TARGET_SUBPACKET_TYPE)
        for sub in subpackets:
            expected_digest = sub.hash
            hash_algorithm = sub.hash_algorithm
            pub_algorithm = sub.public_key_algorithm
            for sig in parent.signatures:
                digest = utils.hash_packet_for_signature(
                    sig.to_packet(),
                    self.signature_type,
                    self.signature_version,
                    hash_algorithm,
                    self.creation_time,
                    pub_algorithm,
                )
                if digest == expected_digest:
                    return sig

        # Fallback
        revocable = []
        for sig in parent.signatures:
            if sig is self:
                continue
            if set(self.issuer_key_ids) & set(sig.issuer_key_ids):
                revocable.append(sig)
        if len(revocable) == 1:
            return revocable[0]
Beispiel #4
0
    def target(self):
        parent = self.parent
        # get target subpacket
        subpackets = self._get_subpackets(C.TARGET_SUBPACKET_TYPE)
        for sub in subpackets:
            expected_digest = sub.hash
            hash_algorithm = sub.hash_algorithm
            pub_algorithm = sub.public_key_algorithm
            for sig in parent.signatures:
                digest = utils.hash_packet_for_signature(
                    sig.to_packet(), self.signature_type,
                    self.signature_version,
                    hash_algorithm,
                    self.creation_time,
                    pub_algorithm,
                    )
                if digest == expected_digest:
                    return sig

        # Fallback
        revocable = []
        for sig in parent.signatures:
            if sig is self:
                continue
            if set(self.issuer_key_ids) & set(sig.issuer_key_ids):
                revocable.append(sig)
        if len(revocable) == 1:
            return revocable[0]
Beispiel #5
0
def make_signature_packet(secret_key,
                          public_key_packet,
                          packet,
                          version,
                          type_,
                          pub_algorithm_type,
                          hash_algorithm_type,
                          creation_time=None,
                          expiration_time=None,
                          key_id=None,
                          subpackets=None):
    subpackets = subpackets or []
    signature = {
        'type': 2,
        'version': version,
        'sig_version': version,
        'sig_type': type_,
        'pub_algorithm_type': pub_algorithm_type,
        'hash_algorithm_type': hash_algorithm_type,
        'subpackets': subpackets
    }

    hashed_subpacket_data = bytearray()
    if version in (2, 3):
        if None in (creation_time, key_id):
            raise TypeError(
                'Creation time and key ID must be provided for version 3 '
                'signatures.')
        signature['creation_time'] = creation_time
        signature['key_id'] = key_id
    elif version >= 4:
        if (creation_time, key_id) != (None, None):
            raise TypeError(
                'Version 4 signatures must store creation time and key '
                'ID in subpackets.')
        for subpacket in subpackets:
            if subpacket['hashed']:
                hashed_subpacket_data.extend(subpacket_to_bytes(subpacket))

    hash_ = utils.hash_packet_for_signature(
        packet_to_content_bytes(public_key_packet), packet['type'],
        packet_to_content_bytes(packet), type_, version, hash_algorithm_type,
        creation_time, pub_algorithm_type, hashed_subpacket_data)
    digest = bytearray(hash_.digest())
    signature['hash2'] = digest[:2]
    k = None
    if pub_algorithm_type == 20:
        k = TEST_ELG_K
    values = utils.sign_hash(pub_algorithm_type, secret_key, hash_, k=k)
    signature['values'] = values

    return signature
Beispiel #6
0
def make_signature_packet(secret_key, public_key_packet, packet, version,
                          type_, pub_algorithm_type, hash_algorithm_type,
                          creation_time=None, expiration_time=None,
                          key_id=None, subpackets=None):
    subpackets = subpackets or []
    signature = {
        'type': 2,
        'version': version,
        'sig_version': version,
        'sig_type': type_,
        'pub_algorithm_type': pub_algorithm_type,
        'hash_algorithm_type': hash_algorithm_type,
        'subpackets': subpackets
        }

    hashed_subpacket_data = bytearray()
    if version in (2, 3):
        if None in (creation_time, key_id):
            raise TypeError(
                    'Creation time and key ID must be provided for version 3 '
                    'signatures.')
        signature['creation_time'] = creation_time
        signature['key_id'] = key_id
    elif version >= 4:
        if (creation_time, key_id) != (None, None):
            raise TypeError(
                    'Version 4 signatures must store creation time and key '
                    'ID in subpackets.')
        for subpacket in subpackets:
            if subpacket['hashed']:
                hashed_subpacket_data.extend(subpacket_to_bytes(subpacket))

    hash_ = utils.hash_packet_for_signature(
                    packet_to_content_bytes(public_key_packet),
                    packet['type'],
                    packet_to_content_bytes(packet),
                    type_,
                    version,
                    hash_algorithm_type,
                    creation_time,
                    pub_algorithm_type,
                    hashed_subpacket_data
                )
    digest = bytearray(hash_.digest())
    signature['hash2'] = digest[:2]
    k = None
    if pub_algorithm_type == 20:
        k = TEST_ELG_K
    values = utils.sign_hash(pub_algorithm_type, secret_key, hash_, k=k)
    signature['values'] = values

    return signature
def validate_signature(target, signature, signing_key, public_key=None, strict=False, current_time=None):
    """Returns a tuple of three booleans, the first indicates whether
    the signature has expired, the second indicates if the signing key
    has expired, the third indicates if the signing key has been
    revoked.

    If the signing_key passed in is a subkey, it must have the 'parent'
    item set to its public key data.
    """

    hashed_subpacket_data = get_hashed_subpacket_data(signature)
    sig_type = signature.signature_type
    hash_ = utils.hash_packet_for_signature(
        target.to_packet(),
        signature.signature_type,
        signature.version,
        signature.hash_algorithm,
        signature.creation_time,
        signature.public_key_algorithm,
        public_key.to_packet(),
        hashed_subpacket_data,
    )
    result = False, False
    if sig_type == constants.KEY_REVOCATION_SIGNATURE:
        # public key revocation
        if public_key.key_id not in signature.issuer_key_ids:
            result = check_revocation_keys(public_key, signature, hash_, signing_key, strict, current_time)
        else:
            result = check_signature(public_key, signature, hash_, strict, current_time)
    elif sig_type == constants.SUBKEY_REVOCATION_SIGNATURE:
        # subkey revocation
        result = check_signature(public_key, signature, hash_, strict, current_time)
    elif sig_type == constants.SUBKEY_BINDING_SIGNATURE:
        # key binding
        if public_key.key_id not in signature.issuer_key_ids:
            raise InvalidSubkeyBindingSignature()
        result = check_signature(public_key, signature, hash_, strict, current_time)
    elif sig_type == constants.SIGNATURE_DIRECTLY_ON_A_KEY:
        # direct key signature
        result = check_signature(public_key, signature, hash_, strict, current_time)
    elif sig_type in (
        constants.GENERIC_CERTIFICATION,
        constants.CASUAL_CERTIFICATION,
        constants.POSITIVE_CERTIFICATION,
        constants.PERSONA_CERTIFICATION,
    ):
        result = check_signature(signing_key, signature, hash_, strict, current_time)
    elif sig_type == constants.PRIMARY_KEY_BINDING_SIGNATURE:
        # Backsignature, we shouldn't have this here
        raise UnexpectedSignatureType(constants.PRIMARY_KEY_BINDING_SIGNATURE)
    elif sig_type == constants.CERTIFICATION_REVOCATION_SIGNATURE:
        revocation_keys = [rev_key.fingerprint[-16:] for rev_key in signature.parent.revocation_keys]
        if not signature.target:
            pass
        elif signing_key.key_id not in signature.target.issuer_key_ids and signing_key.key_id not in revocation_keys:
            raise SignatureVerificationFailed("Signature cannot be revoked by this key")
        elif signature.target.revocable is False:
            raise SignatureVerificationFailed("Signature cannot be revoked")
        elif signature.target.creation_time > signature.creation_time:
            raise SignatureCreatedBeforeContent()
        # TODO: FIX THIS
        # result = check_signature(signing_key, signature, hash_,
        #                          strict)
    else:
        # 0x00, 0x01, 0x02, 0x30, 0x40 & 0x50 do not apply to public keys
        raise UnexpectedSignatureType(sig_type)

    return result
def validate_signature(target,
                       signature,
                       signing_key,
                       public_key=None,
                       strict=False,
                       current_time=None):
    """Returns a tuple of three booleans, the first indicates whether
    the signature has expired, the second indicates if the signing key
    has expired, the third indicates if the signing key has been
    revoked.

    If the signing_key passed in is a subkey, it must have the 'parent'
    item set to its public key data.
    """

    hashed_subpacket_data = get_hashed_subpacket_data(signature)
    sig_type = signature.signature_type
    hash_ = utils.hash_packet_for_signature(
        target.to_packet(), signature.signature_type, signature.version,
        signature.hash_algorithm,
        signature.creation_time, signature.public_key_algorithm,
        public_key.to_packet(), hashed_subpacket_data)
    result = False, False
    if sig_type == constants.KEY_REVOCATION_SIGNATURE:
        # public key revocation
        if public_key.key_id not in signature.issuer_key_ids:
            result = check_revocation_keys(public_key, signature, hash_,
                                           signing_key, strict, current_time)
        else:
            result = check_signature(public_key, signature, hash_, strict,
                                     current_time)
    elif sig_type == constants.SUBKEY_REVOCATION_SIGNATURE:
        # subkey revocation
        result = check_signature(public_key, signature, hash_, strict,
                                 current_time)
    elif sig_type == constants.SUBKEY_BINDING_SIGNATURE:
        # key binding
        if public_key.key_id not in signature.issuer_key_ids:
            raise InvalidSubkeyBindingSignature()
        result = check_signature(public_key, signature, hash_, strict,
                                 current_time)
    elif sig_type == constants.SIGNATURE_DIRECTLY_ON_A_KEY:
        # direct key signature
        result = check_signature(public_key, signature, hash_, strict,
                                 current_time)
    elif sig_type in (constants.GENERIC_CERTIFICATION,
                      constants.CASUAL_CERTIFICATION,
                      constants.POSITIVE_CERTIFICATION,
                      constants.PERSONA_CERTIFICATION):
        result = check_signature(signing_key, signature, hash_, strict,
                                 current_time)
    elif sig_type == constants.PRIMARY_KEY_BINDING_SIGNATURE:
        # Backsignature, we shouldn't have this here
        raise UnexpectedSignatureType(constants.PRIMARY_KEY_BINDING_SIGNATURE)
    elif sig_type == constants.CERTIFICATION_REVOCATION_SIGNATURE:
        revocation_keys = [
            rev_key.fingerprint[-16:]
            for rev_key in signature.parent.revocation_keys
        ]
        if not signature.target:
            pass
        elif (signing_key.key_id not in signature.target.issuer_key_ids
              and signing_key.key_id not in revocation_keys):
            raise SignatureVerificationFailed(
                'Signature cannot be revoked by this key')
        elif signature.target.revocable is False:
            raise SignatureVerificationFailed('Signature cannot be revoked')
        elif signature.target.creation_time > signature.creation_time:
            raise SignatureCreatedBeforeContent()
        # TODO: FIX THIS
        # result = check_signature(signing_key, signature, hash_,
        #                          strict)
    else:
        # 0x00, 0x01, 0x02, 0x30, 0x40 & 0x50 do not apply to public keys
        raise UnexpectedSignatureType(sig_type)

    return result