Beispiel #1
0
def verify_signature(data, signature, pubkey):
    """
    Verify a signature.

    If the signature is valid, returns True. If the signature is invalid, raise
    an exception explaining why.
    """
    # Data must be encoded as bytes
    if isinstance(data, str):
        data = data.encode()

    # Content signature implicitly adds a prefix to signed data
    data = b"Content-Signature:\x00" + data

    # fastecdsa expects ASCII armored keys, but ours is unarmored. Add the
    # armor before passing the key to the library.
    EC_PUBLIC_HEADER = "-----BEGIN PUBLIC KEY-----"
    EC_PUBLIC_FOOTER = "-----END PUBLIC KEY-----"
    verifying_pubkey = PEMEncoder.decode_public_key(
        "\n".join([EC_PUBLIC_HEADER, pubkey, EC_PUBLIC_FOOTER])
    )

    try:
        signature = base64.urlsafe_b64decode(signature)
        signature = ecdsa.util.sigdecode_string(signature, order=ecdsa.curves.NIST384p.order)
    except binascii.Error as e:
        if BASE64_WRONG_LENGTH_RE.match(e.args[0]):
            raise WrongSignatureSize("Base64 encoded signature was not a multiple of 4")
        else:
            raise
    except AssertionError as e:
        # The signature decoder has a clause like
        #     assert len(signature) == 2*l, (len(signature), 2*l)
        # If the AssertionError is consistent with that signature, translate it
        # to a nicer error. Otherwise re-raise.
        if (
            len(e.args) == 1
            and isinstance(e.args[0], tuple)
            and len(e.args[0]) == 2
            and isinstance(e.args[0][0], int)
            and isinstance(e.args[0][1], int)
        ):
            raise WrongSignatureSize()
        else:
            raise

    verified = fastecdsa.ecdsa.verify(
        signature, data, verifying_pubkey, curve=fastecdsa.curve.P384, hashfunc=hashlib.sha384
    )

    if not verified:
        raise SignatureDoesNotMatch()

    return True
Beispiel #2
0
def verify_signature(data, signature, pubkey):
    """
    Verify a signature.

    If the signature is valid, returns True. If the signature is invalid, raise
    an exception explaining why.
    """
    # Data must be encoded as bytes
    if isinstance(data, str):
        data = data.encode()

    # Content signature implicitly adds a prefix to signed data
    data = b"Content-Signature:\x00" + data

    # fastecdsa expects ASCII armored keys, but ours is unarmored. Add the
    # armor before passing the key to the library.
    EC_PUBLIC_HEADER = "-----BEGIN PUBLIC KEY-----"
    EC_PUBLIC_FOOTER = "-----END PUBLIC KEY-----"
    verifying_pubkey = PEMEncoder.decode_public_key("\n".join(
        [EC_PUBLIC_HEADER, pubkey, EC_PUBLIC_FOOTER]))

    try:
        signature = base64.urlsafe_b64decode(signature)
        signature = ecdsa.util.sigdecode_string(
            signature, order=ecdsa.curves.NIST384p.order)
    except binascii.Error as e:
        if BASE64_WRONG_LENGTH_RE.match(e.args[0]):
            raise WrongSignatureSize(
                "Base64 encoded signature was not a multiple of 4")
        else:
            raise
    except AssertionError as e:
        # The signature decoder has a clause like
        #     assert len(signature) == 2*l, (len(signature), 2*l)
        # If the AssertionError is consistent with that signature, translate it
        # to a nicer error. Otherwise re-raise.
        if (len(e.args) == 1 and isinstance(e.args[0], tuple)
                and len(e.args[0]) == 2 and isinstance(e.args[0][0], int)
                and isinstance(e.args[0][1], int)):
            raise WrongSignatureSize()
        else:
            raise

    verified = fastecdsa.ecdsa.verify(signature,
                                      data,
                                      verifying_pubkey,
                                      curve=fastecdsa.curve.P384,
                                      hashfunc=hashlib.sha384)

    if not verified:
        raise SignatureDoesNotMatch()

    return True
Beispiel #3
0
def verify_signature_pubkey(data, signature, pubkey):
    """
    Verify a signature.

    If the signature is valid, returns True. If the signature is invalid, raise
    an exception explaining why.
    """
    # Data must be encoded as bytes
    if isinstance(data, str):
        data = data.encode()

    # Content signature implicitly adds a prefix to signed data
    data = b"Content-Signature:\x00" + data

    # fastecdsa expects ASCII armored keys, but ours is unarmored. Add the
    # armor before passing the key to the library.
    EC_PUBLIC_HEADER = "-----BEGIN PUBLIC KEY-----"
    EC_PUBLIC_FOOTER = "-----END PUBLIC KEY-----"
    verifying_pubkey = PEMEncoder.decode_public_key("\n".join(
        [EC_PUBLIC_HEADER, pubkey, EC_PUBLIC_FOOTER]))

    try:
        signature = base64.urlsafe_b64decode(signature)
        signature = ecdsa.util.sigdecode_string(
            signature, order=ecdsa.curves.NIST384p.order)
    except binascii.Error as e:
        if BASE64_WRONG_LENGTH_RE.match(e.args[0]):
            raise WrongSignatureSize(
                "Base64 encoded signature was not a multiple of 4")
        else:
            raise
    except ecdsa.util.MalformedSignature:
        raise WrongSignatureSize()

    verified = fastecdsa.ecdsa.verify(signature,
                                      data,
                                      verifying_pubkey,
                                      curve=fastecdsa.curve.P384,
                                      hashfunc=hashlib.sha384)

    if not verified:
        raise SignatureDoesNotMatch()

    return True
Beispiel #4
0
    def __validate_fastecdsa_signature(self, verification_string, signature,
                                       charset):
        """Return True if signature is valid, using FastEDSA algorithms."""
        ecdsa_public_key = PEMEncoder.decode_public_key(
            self.inflated_public_key)
        # signature_length = len(signature)
        r, s = DEREncoder.decode_signature(signature)
        # r_bytes, s_bytes = signature[:signature_length // 2], signature[signature_length // 2:signature_length]
        # r, s = int.from_bytes(r_bytes, 'big', signed=False), int.from_bytes(s_bytes, 'big', signed=False)
        signing_algorithm = self.signing_algorithm.upper()
        if ('SHA-' in signing_algorithm):
            signing_algorithm = signing_algorithm.replace('SHA-', 'SHA')
        if ('P-' in signing_algorithm):
            signing_algorithm = signing_algorithm.replace('P-', 'P')
        if signing_algorithm == self.SIGNING_ALGORITHM_ECDSA_P256:
            curve_algorithm = curve.P256
        elif signing_algorithm == self.SIGNING_ALGORITHM_ECDSA_P384:
            curve_algorithm = curve.P384
        elif signing_algorithm == self.SIGNING_ALGORITHM_ECDSA_P521:
            curve_algorithm = curve.P2521
        elif signing_algorithm == self.SIGNING_ALGORITHM_ECDSA_CURVE25519:
            curve_algorithm = curve.W25519
        else:
            raise UnsupportedAlgorithmException(self.signing_algorithm)
        hashing_algorithm = self.hashing_algorithm.upper().replace('-', '')
        if hashing_algorithm == self.HASHING_ALGORITHM_SHA256:
            hash_function = hashlib.sha256
        elif hashing_algorithm == self.HASHING_ALGORITHM_SHA512:
            hash_function = hashlib.sha512
        else:
            raise UnsupportedAlgorithmException(self.hashing_algorithm)

        is_valid = False
        try:
            ecdsa.verify((r, s),
                         signature,
                         ecdsa_public_key,
                         curve=curve_algorithm,
                         hashfunc=hash_function)
            is_valid = True
        except ecdsa.EcdsaError:
            is_valid = False
        return is_valid
Beispiel #5
0
def import_verifying_key(pem_bytes: bytes) -> VerifyingKey:
    return PEMEncoder.decode_public_key(pem_bytes.decode(), curve.secp256k1)