예제 #1
0
파일: core.py 프로젝트: phizaz/gaw
def _verify(b, secret, signature):
    alg = HMACAlgorithm(HMACAlgorithm.SHA256)
    key = alg.prepare_key(secret)
    if not alg.verify(b, key, signature):
        raise PostofficeException(name='DecodeError',
                                  message='signature verification failed')
    return True
예제 #2
0
    def test_hmac_should_reject_nonstring_key(self):
        algo = HMACAlgorithm(HMACAlgorithm.SHA256)

        with pytest.raises(TypeError) as context:
            algo.prepare_key(object())

        exception = context.value
        assert str(exception) == 'Expecting a string- or bytes-formatted key.'
예제 #3
0
    def test_hmac_jwk_should_parse_and_verify(self):
        algo = HMACAlgorithm(HMACAlgorithm.SHA256)

        with open(key_path("jwk_hmac.json")) as keyfile:
            key = algo.from_jwk(keyfile.read())

        signature = algo.sign(b"Hello World!", key)
        assert algo.verify(b"Hello World!", key, signature)
예제 #4
0
    def test_hmac_should_reject_nonstring_key(self):
        algo = HMACAlgorithm(HMACAlgorithm.SHA256)

        with self.assertRaises(TypeError) as context:
            algo.prepare_key(object())

        exception = context.exception
        self.assertEqual(str(exception), 'Expecting a string- or bytes-formatted key.')
class ShortClientTokenTool(object):

    ALGORITHM = 'HS256'
    signer = HMACAlgorithm(HMACAlgorithm.SHA256)

    @classmethod
    def adobe_base64_encode(cls, to_encode):
        """A modified base64 encoding that avoids triggering an Adobe bug.

        The bug seems to happen when the 'password' portion of a
        username/password pair contains a + character. So we replace +
        with :. We also replace / (another "suspicious" character)
        with ;. and strip newlines.
        """
        if isinstance(to_encode, unicode):
            to_encode = to_encode.encode("utf8")
        encoded = base64.encodestring(to_encode)
        return encoded.replace(b"+", b":").replace(b"/",
                                                   b";").replace(b"=",
                                                                 b"@").strip()

    @classmethod
    def adobe_base64_decode(cls, to_decode):
        """Undoes adobe_base64_encode."""
        if isinstance(to_decode, unicode):
            to_decode = to_decode.encode("utf8")
        to_decode = to_decode.replace(b":",
                                      b"+").replace(b";",
                                                    b"/").replace(b"@", b"=")
        return base64.decodestring(to_decode)

    # The JWT spec takes January 1 1970 as the epoch.
    JWT_EPOCH = datetime.datetime(1970, 1, 1)

    # For the sake of shortening tokens, the Short Client Token spec
    # takes January 1 2017 as the epoch, and measures time in minutes
    # rather than seconds.
    SCT_EPOCH = datetime.datetime(2017, 1, 1)

    @classmethod
    def sct_numericdate(cls, d):
        """Turn a datetime object into a number of minutes since the epoch, as
        per the Short Client Token spec.
        """
        return (d - cls.SCT_EPOCH).total_seconds() / 60

    @classmethod
    def jwt_numericdate(cls, d):
        """Turn a datetime object into a NumericDate as per RFC 7519."""
        return (d - cls.JWT_EPOCH).total_seconds()
예제 #6
0
    def test_hmac_verify_should_return_true_for_test_vector(self):
        """
        This test verifies that HMAC verification works with a known good
        signature and key.

        Reference: https://tools.ietf.org/html/rfc7520#section-4.4
        """
        signing_input = ensure_bytes(
            'eyJhbGciOiJIUzI1NiIsImtpZCI6IjAxOGMwYWU1LTRkOWItNDcxYi1iZmQ2LWVlZ'
            'jMxNGJjNzAzNyJ9.SXTigJlzIGEgZGFuZ2Vyb3VzIGJ1c2luZXNzLCBGcm9kbywgZ'
            '29pbmcgb3V0IHlvdXIgZG9vci4gWW91IHN0ZXAgb250byB0aGUgcm9hZCwgYW5kIG'
            'lmIHlvdSBkb24ndCBrZWVwIHlvdXIgZmVldCwgdGhlcmXigJlzIG5vIGtub3dpbmc'
            'gd2hlcmUgeW91IG1pZ2h0IGJlIHN3ZXB0IG9mZiB0by4')

        signature = base64url_decode(
            ensure_bytes('s0h6KThzkfBBBkLspW1h84VsJZFTsPPqMDA7g1Md7p0'))

        algo = HMACAlgorithm(HMACAlgorithm.SHA256)
        key = algo.prepare_key(load_hmac_key())

        result = algo.verify(signing_input, key, signature)
        assert result
예제 #7
0
    def test_hmac_should_throw_exception(self, key):
        algo = HMACAlgorithm(HMACAlgorithm.SHA256)

        with pytest.raises(InvalidKeyError):
            with open(key_path(key)) as keyfile:
                algo.prepare_key(keyfile.read())
예제 #8
0
    def __init__(self,
                 vendor_id,
                 library_uri,
                 library_short_name,
                 secret,
                 other_libraries={}):
        """Basic constructor.

        :param vendor_id: The Adobe Vendor ID that should accompany authdata
        generated by this utility.

        If this library has its own Adobe Vendor ID, it should go
        here. If this library is delegating authdata control to some
        other library, that library's Vendor ID should go here.

        :param library_uri: A URI identifying this library. This is
        used when generating JWTs.

        :param short_name: A short string identifying this
        library. This is used when generating short client tokens,
        which must be as short as possible (thus the name).

        :param secret: A secret used to sign this library's authdata.

        :param other_libraries: A dictionary mapping other libraries'
        canonical URIs to their (short name, secret) 2-tuples. An
        instance of this class will be able to decode an authdata from
        any library in this dictionary (plus the library it was
        initialized for).
        """
        self.vendor_id = vendor_id

        # This is used to _encode_ JWTs and send them to the
        # delegation authority.
        self.library_uri = library_uri

        # This is used to _encode_ short client tokens.
        self.short_name = library_short_name.upper()

        # This is used to encode both JWTs and short client tokens.
        self.secret = secret

        # This is used by the delegation authority to _decode_ JWTs.
        self.secrets_by_library_uri = {}
        self.secrets_by_library_uri[self.library_uri] = secret

        # This is used by the delegation authority to _decode_ short
        # client tokens.
        self.library_uris_by_short_name = {}
        self.library_uris_by_short_name[self.short_name] = self.library_uri

        # Fill in secrets_by_library_uri and library_uris_by_short_name
        # for other libraries.
        for uri, v in other_libraries.items():
            short_name, secret = v
            short_name = short_name.upper()
            if short_name in self.library_uris_by_short_name:
                # This can happen if the same library is in the list
                # twice, capitalized differently.
                raise ValueError("Duplicate short name: %s" % short_name)
            self.library_uris_by_short_name[short_name] = uri
            self.secrets_by_library_uri[uri] = secret

        self.log = logging.getLogger("Adobe authdata utility")

        self.short_token_signer = HMACAlgorithm(HMACAlgorithm.SHA256)
        self.short_token_signing_key = self.short_token_signer.prepare_key(
            self.secret)
예제 #9
0
    def test_hmac_should_throw_exception_if_key_is_ssh_public_key(self):
        algo = HMACAlgorithm(HMACAlgorithm.SHA256)

        with self.assertRaises(InvalidKeyError):
            with open(key_path('testkey_rsa.pub'), 'r') as keyfile:
                algo.prepare_key(keyfile.read())
예제 #10
0
    def test_hmac_to_jwk_returns_correct_values(self):
        algo = HMACAlgorithm(HMACAlgorithm.SHA256)
        key = algo.to_jwk("secret")

        assert json.loads(key) == {"kty": "oct", "k": "c2VjcmV0"}
예제 #11
0
    def test_hmac_should_accept_unicode_key(self):
        algo = HMACAlgorithm(HMACAlgorithm.SHA256)

        algo.prepare_key(ensure_unicode('awesome'))
예제 #12
0
    def test_hmac_to_jwk_returns_correct_values(self):
        algo = HMACAlgorithm(HMACAlgorithm.SHA256)
        key = algo.to_jwk('secret')

        assert json.loads(key) == {'kty': 'oct', 'k': 'c2VjcmV0'}
예제 #13
0
    def test_hmac_from_jwk_should_raise_exception_if_not_hmac_key(self):
        algo = HMACAlgorithm(HMACAlgorithm.SHA256)

        with open(key_path("jwk_rsa_pub.json")) as keyfile:
            with pytest.raises(InvalidKeyError):
                algo.from_jwk(keyfile.read())
예제 #14
0
    def test_hmac_should_throw_exception_if_key_is_x509_certificate(self):
        algo = HMACAlgorithm(HMACAlgorithm.SHA256)

        with pytest.raises(InvalidKeyError):
            with open(key_path("testkey_rsa.cer")) as keyfile:
                algo.prepare_key(keyfile.read())
예제 #15
0
    def test_hmac_should_throw_exception_if_key_is_pkcs1_pem_public(self):
        algo = HMACAlgorithm(HMACAlgorithm.SHA256)

        with pytest.raises(InvalidKeyError):
            with open(key_path("testkey_pkcs1.pub.pem")) as keyfile:
                algo.prepare_key(keyfile.read())
예제 #16
0
    def test_hmac_should_throw_exception_if_key_is_ssh_public_key(self):
        algo = HMACAlgorithm(HMACAlgorithm.SHA256)

        with pytest.raises(InvalidKeyError):
            with open(key_path("testkey_rsa.pub"), "r") as keyfile:
                algo.prepare_key(keyfile.read())
예제 #17
0
    def test_hmac_should_accept_unicode_key(self):
        algo = HMACAlgorithm(HMACAlgorithm.SHA256)

        algo.prepare_key(force_unicode("awesome"))
예제 #18
0
    def test_hmac_should_throw_exception_if_key_is_x509_cert(self):
        algo = HMACAlgorithm(HMACAlgorithm.SHA256)

        with pytest.raises(InvalidKeyError):
            with open(key_path('testkey2_rsa.pub.pem'), 'r') as keyfile:
                algo.prepare_key(keyfile.read())
예제 #19
0
파일: core.py 프로젝트: phizaz/gaw
def _sign(b, secret):
    alg = HMACAlgorithm(HMACAlgorithm.SHA256)
    key = alg.prepare_key(secret)
    signature = alg.sign(b, key)
    return signature