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 build_authorization_header(self):
        """Build authorization headers."""
        if len(self.required_authorization_headers) > 0:
            self.authorization_parameters['headers'] = '{}'.format(' '.join([
                header.lower()
                for header in self.required_authorization_headers
            ]))
        self.build_signing_string()
        signing_bytestring = self.signing_string.encode(self.encoding)
        if self.signing_algorithm == 'RSA':
            signer = RSA.import_key(self.private_key_string)
            if self.hashing_algorithm == 'SHA256':
                hash_obj = SHA256.new(signing_bytestring)
            elif self.hashing_algorithm == 'SHA512':
                hash_obj = SHA512.new(signing_bytestring)
            else:
                raise Exception("Invalid key type")
            signature = pkcs1_15.new(signer).sign(hash_obj)
        else:
            private_key, public_key = PEMEncoder.decode_private_key(
                self.private_key_string)
            if self.hashing_algorithm == 'SHA256':
                hash_function = hashlib.sha256
            elif self.hashing_algorithm == 'SHA512':
                hash_function = hashlib.sha512
            else:
                raise Exception("Invalid key type")

            if self.signing_algorithm.lower() == 'p256':
                r, s = ecdsa.sign(signing_bytestring,
                                  private_key,
                                  curve=curve.P256,
                                  hashfunc=hash_function)
            else:
                raise Exception("Invalid key type")
            signature = DEREncoder.encode_signature(r, s)
        base64_signature = base64.b64encode(signature).decode(self.encoding)
        self.authorization_parameters['signature'] = '{}'.format(
            base64_signature)
        authorization_rows = []
        for key, value in self.authorization_parameters.items():
            if isinstance(value, str):
                authorization_rows.append('{}="{}"'.format(key, value))
            elif isinstance(value, int) or isinstance(value, float):
                authorization_rows.append('{}={}'.format(key, value))
            elif isinstance(value, bool):
                if value is True:
                    authorization_rows.append('{}=true')
                else:
                    authorization_rows.append('{}=false')
        authorization_header = 'Signature {}'.format(
            ','.join(authorization_rows))
        self.headers['Authorization'] = authorization_header
Beispiel #4
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 #5
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 #6
0
def import_verifying_key(pem_bytes: bytes) -> VerifyingKey:
    return PEMEncoder.decode_public_key(pem_bytes.decode(), curve.secp256k1)
Beispiel #7
0
def export_verifying_key(verifying_key: VerifyingKey) -> bytes:
    return PEMEncoder.encode_public_key(verifying_key).encode()