Exemple #1
0
def decode(token, key):
    """Decode a web token into an assertion dictionary

    This attempts to rectify both ecdsa and openssl generated signatures.

    :param token: VAPID auth token
    :type token: str
    :param key: bitarray containing the public key
    :type key: str

    :return dict of the VAPID claims

    :raise InvalidSignature

    """
    try:
        sig_material, signature = extract_signature(token)
        dkey = b64urldecode(key.encode('utf8'))
        pkey = ec.EllipticCurvePublicNumbers.from_encoded_point(
            ec.SECP256R1(),
            dkey,
        ).public_key(default_backend())
        pkey.verify(signature, sig_material, ec.ECDSA(hashes.SHA256()))
        return json.loads(
            b64urldecode(sig_material.split(b'.')[1]).decode('utf8'))
    except InvalidSignature:
        raise
    except (ValueError, TypeError, binascii.Error):
        raise InvalidSignature()
Exemple #2
0
def decode(token, key):
    """Decode a web token into an assertion dictionary

    :param token: VAPID auth token
    :type token: str
    :param key: bitarray containing the public key
    :type key: str

    :return dict of the VAPID claims

    :raise InvalidSignature

    """
    try:
        sig_material, signature = extract_signature(token)
        dkey = b64urldecode(key.encode('utf8'))
        pkey = ec.EllipticCurvePublicKey.from_encoded_point(
            ec.SECP256R1(),
            dkey,
        )
        pkey.verify(
            signature,
            sig_material,
            ec.ECDSA(hashes.SHA256())
        )
        return json.loads(
            b64urldecode(sig_material.split(b'.')[1]).decode('utf8')
        )
    except InvalidSignature:
        raise
    except(ValueError, TypeError, binascii.Error):
        raise InvalidSignature()
Exemple #3
0
 def from_raw_public(cls, public_raw):
     key = ec.EllipticCurvePublicNumbers.from_encoded_point(
         curve=ec.SECP256R1(),
         data=b64urldecode(public_raw)).public_key(default_backend())
     ss = cls()
     ss._public_key = key
     return ss
Exemple #4
0
 def from_raw_public(cls, public_raw):
     key = ec.EllipticCurvePublicKey.from_encoded_point(
         curve=ec.SECP256R1(),
         data=b64urldecode(public_raw)
     )
     ss = cls()
     ss._public_key = key
     return ss
Exemple #5
0
 def from_raw_public(cls, public_raw):
     key = ec.EllipticCurvePublicKey.from_encoded_point(
         curve=ec.SECP256R1(),
         data=b64urldecode(public_raw)
     )
     ss = cls()
     ss._public_key = key
     return ss
Exemple #6
0
    def from_der(cls, private_key):
        """Initialize VAPID using a private key in DER format.

        :param private_key: A private key in DER format and Base64-encoded.
        :type private_key: bytes

        """
        key = serialization.load_der_private_key(b64urldecode(private_key),
                                                 password=None,
                                                 backend=default_backend())
        return cls(key)
Exemple #7
0
    def from_der(cls, private_key):
        """Initialize VAPID using a private key in DER format.

        :param private_key: A private key in DER format and Base64-encoded.
        :type private_key: bytes

        """
        key = serialization.load_der_private_key(b64urldecode(private_key),
                                                 password=None,
                                                 backend=default_backend())
        return cls(key)
Exemple #8
0
    def from_string(cls, private_key):
        """Initialize VAPID using a string containing the private key. This
        will try to determine if the key is in RAW or DER format.

        :param private_key: String containing the key info
        :type private_key: str

        """

        pkey = private_key.encode().replace(b"\n", b"")
        key = b64urldecode(pkey)
        if len(key) == 32:
            return cls.from_raw(pkey)
        return cls.from_der(pkey)
Exemple #9
0
    def from_raw(cls, private_raw):
        """Initialize VAPID using a private key point in "raw" or
        "uncompressed" form. Raw keys consist of a single, 32 octet
        encoded integer.

        :param private_raw: A private key point in uncompressed form.
        :type private_raw: bytes

        """
        key = ec.derive_private_key(
            int(binascii.hexlify(b64urldecode(private_raw)), 16),
            curve=ec.SECP256R1(),
            backend=default_backend())
        return cls(key)
Exemple #10
0
    def from_string(cls, private_key):
        """Initialize VAPID using a string containing the private key. This
        will try to determine if the key is in RAW or DER format.

        :param private_key: String containing the key info
        :type private_key: str

        """

        pkey = private_key.encode().replace(b"\n", b"")
        key = b64urldecode(pkey)
        if len(key) == 32:
            return cls.from_raw(pkey)
        return cls.from_der(pkey)
Exemple #11
0
    def from_raw(cls, private_raw):
        """Initialize VAPID using a private key point in "raw" or
        "uncompressed" form. Raw keys consist of a single, 32 octet
        encoded integer.

        :param private_raw: A private key point in uncompressed form.
        :type private_raw: bytes

        """
        key = ec.derive_private_key(
            int(binascii.hexlify(b64urldecode(private_raw)), 16),
            curve=ec.SECP256R1(),
            backend=default_backend())
        return cls(key)
Exemple #12
0
    def verify_token(self, validation_token, verification_token):
        """Internally used to verify the verification token is correct.

        :param validation_token: Provided validation token string
        :type validation_token: str
        :param verification_token: Generated verification token
        :type verification_token: str
        :returns: Boolean indicating if verifictation token is valid.
        :rtype: boolean

        """
        hsig = b64urldecode(verification_token.encode('utf8'))
        return self.public_key.verify(
            hsig,
            validation_token,
            signature_algorithm=ec.ECDSA(hashes.SHA256())
        )
Exemple #13
0
def extract_signature(auth):
    """Extracts the payload and signature from a JWT, converting from RFC7518
    to RFC 3279

    :param auth: A JWT Authorization Token.
    :type auth: str

    :return tuple containing the signature material and signature

    """
    payload, asig = auth.encode('utf8').rsplit(b'.', 1)
    sig = b64urldecode(asig)
    if len(sig) != 64:
        raise InvalidSignature()

    encoded = utils.encode_dss_signature(s=int(binascii.hexlify(sig[32:]), 16),
                                         r=int(binascii.hexlify(sig[:32]), 16))
    return payload, encoded
Exemple #14
0
def extract_signature(auth):
    """Fix the JWT auth token

    convert a ecdsa integer pair into an OpenSSL DER pair.

    :param auth: A JWT Authorization Token.
    :type auth: str

    :return tuple containing the signature material and signature

    """
    payload, asig = auth.encode('utf8').rsplit(b'.', 1)
    sig = b64urldecode(asig)
    if len(sig) != 64:
        return payload, sig

    encoded = utils.encode_dss_signature(s=int(binascii.hexlify(sig[32:]), 16),
                                         r=int(binascii.hexlify(sig[:32]), 16))
    return payload, encoded
Exemple #15
0
def extract_signature(auth):
    """Extracts the payload and signature from a JWT, converting from RFC7518
    to RFC 3279

    :param auth: A JWT Authorization Token.
    :type auth: str

    :return tuple containing the signature material and signature

    """
    payload, asig = auth.encode('utf8').rsplit(b'.', 1)
    sig = b64urldecode(asig)
    if len(sig) != 64:
        raise InvalidSignature()

    encoded = utils.encode_dss_signature(
        s=int(binascii.hexlify(sig[32:]), 16),
        r=int(binascii.hexlify(sig[:32]), 16)
    )
    return payload, encoded
Exemple #16
0
    def test_alt_sign(self):
        """ecdsa uses a raw key pair to sign, openssl uses a DER."""
        v = Vapid01.from_file("/tmp/private")
        claims = {"aud": "https://example.com",
                  "sub": "mailto:[email protected]",
                  "foo": "extra value"}
        # Get a signed token.
        result = v.sign(claims)
        # Convert the dss into raw.
        auth, sig = result.get('Authorization').split(' ')[1].rsplit('.', 1)
        ss = utils.decode_dss_signature(b64urldecode(sig.encode('utf8')))
        new_sig = binascii.b2a_base64(
            binascii.unhexlify("%064x%064x" % ss)
        ).strip().strip(b'=').decode()
        new_auth = auth + '.' + new_sig
        # phew, all that done, now check
        pkey = result.get("Crypto-Key").split('=')[1]
        items = decode(new_auth, pkey)

        eq_(items, claims)
Exemple #17
0
    def verify_token(self, validation_token, verification_token):
        """Internally used to verify the verification token is correct.

        :param validation_token: Provided validation token string
        :type validation_token: str
        :param verification_token: Generated verification token
        :type verification_token: str
        :returns: Boolean indicating if verifictation token is valid.
        :rtype: boolean

        """
        hsig = b64urldecode(verification_token.encode('utf8'))
        r = int(binascii.hexlify(hsig[:32]), 16)
        s = int(binascii.hexlify(hsig[32:]), 16)
        try:
            self.public_key.verify(ecutils.encode_dss_signature(r, s),
                                   validation_token,
                                   signature_algorithm=ec.ECDSA(
                                       hashes.SHA256()))
            return True
        except InvalidSignature:
            return False
Exemple #18
0
    def verify_token(self, validation_token, verification_token):
        """Internally used to verify the verification token is correct.

        :param validation_token: Provided validation token string
        :type validation_token: str
        :param verification_token: Generated verification token
        :type verification_token: str
        :returns: Boolean indicating if verifictation token is valid.
        :rtype: boolean

        """
        hsig = b64urldecode(verification_token.encode('utf8'))
        r = int(binascii.hexlify(hsig[:32]), 16)
        s = int(binascii.hexlify(hsig[32:]), 16)
        try:
            self.public_key.verify(
                ecutils.encode_dss_signature(r, s),
                validation_token,
                signature_algorithm=ec.ECDSA(hashes.SHA256())
            )
            return True
        except InvalidSignature:
            return False