diff --git a/_jose.pyx b/_jose.pyx index 50eafb8..f7d24db 100644 --- a/_jose.pyx +++ b/_jose.pyx @@ -357,3 +357,96 @@ def to_compact(dict flat not None): finally: jansson.json_decref(cjose) free(ret) + +def get_supported_algorithms(): + cdef jose.jose_jwe_crypter_t *jwe_crypter + cdef jose.jose_jwe_wrapper_t *jwe_wrapper + cdef jose.jose_jwe_zipper_t *jwe_zipper + cdef jose.jose_jwk_generator_t *jwk_generator + cdef jose.jose_jwk_hasher_t *jwk_hasher + cdef jose.jose_jwk_op_t *jwk_op + cdef jose.jose_jwk_type_t *jwk_type + cdef jose.jose_jws_signer_t *jws_signer + cdef char *p + cdef size_t i + + result = { + 'jwk_types': {}, + 'jwk_ops': [], + 'jwk_generators': set(), + 'jwk_hashers': {}, + 'jws_signers': set(), + 'jwe_crypters': set(), + 'jwe_wrappers': set(), + 'jwe_zippers': set(), + } + + jwe_crypter = jose.jose_jwe_crypters() + while jwe_crypter is not NULL: + result['jwe_crypters'].add(ascii2obj(jwe_crypter.enc)) + jwe_crypter = jwe_crypter.next + + jwe_wrapper = jose.jose_jwe_wrappers() + while jwe_wrapper is not NULL: + result['jwe_wrappers'].add(ascii2obj(jwe_wrapper.alg)) + jwe_wrapper = jwe_wrapper.next + + jwe_zipper = jose.jose_jwe_zippers() + while jwe_zipper is not NULL: + result['jwe_zippers'].add(ascii2obj(jwe_zipper.zip)) + jwe_zipper = jwe_zipper.next + + jwk_generator = jose.jose_jwk_generators() + while jwk_generator is not NULL: + result['jwk_generators'].add(ascii2obj(jwk_generator.kty)) + jwk_generator = jwk_generator.next + + jwk_hasher = jose.jose_jwk_hashers() + while jwk_hasher is not NULL: + name = ascii2obj(jwk_hasher.name) + result['jwk_hashers'][name] = jwk_hasher.size + jwk_hasher = jwk_hasher.next + + jwk_op = jose.jose_jwk_ops() + while jwk_op is not NULL: + result['jwk_ops'].append( + (ascii2obj(jwk_op.pub), + ascii2obj(jwk_op.prv), + ascii2obj(jwk_op.use)) + ) + jwk_op = jwk_op.next + + jwk_type = jose.jose_jwk_types() + while jwk_type is not NULL: + name = ascii2obj(jwk_type.kty) + reqs = [] + prvs = [] + + if jwk_type.req is not NULL: + for i in range(255): + p = jwk_type.req[i] + if p is NULL: + break + reqs.append(ascii2obj(p)) + + if jwk_type.prv is not NULL: + for i in range(255): + p = jwk_type.prv[i] + if p is NULL: + break + prvs.append(ascii2obj(p)) + + result['jwk_types'][name] = { + 'req': reqs, + 'prv': prvs, + 'sym': True if jwk_type.sym else False + } + + jwk_type = jwk_type.next + + jws_signer = jose.jose_jws_signers() + while jws_signer is not NULL: + result['jws_signers'].add(ascii2obj(jws_signer.alg)) + jws_signer = jws_signer.next + + return result diff --git a/src/jose/__init__.py b/src/jose/__init__.py index d13302f..ec492b9 100644 --- a/src/jose/__init__.py +++ b/src/jose/__init__.py @@ -17,5 +17,6 @@ from __future__ import absolute_import from ._jose import JoseOperationError +from ._jose import get_supported_algorithms -__all__ = ('JoseOperationError', ) +__all__ = ('JoseOperationError', 'get_supported_algorithms') diff --git a/src/jose/jose.pxd b/src/jose/jose.pxd index c962c98..d0ea1b4 100644 --- a/src/jose/jose.pxd +++ b/src/jose/jose.pxd @@ -40,3 +40,51 @@ cdef extern from "jose/jws.h": cdef extern from "jose/jose.h": jansson.json_t *jose_from_compact(const char *jose) char *jose_to_compact(const jansson.json_t *jose) + +cdef extern from "jose/hooks.h": + ctypedef struct jose_jwk_type_t: + jose_jwk_type_t *next + bool sym + const char *kty + const char **req + const char **prv + + ctypedef struct jose_jwk_op_t: + jose_jwk_op_t *next + const char *pub + const char *prv + const char *use + + ctypedef struct jose_jwk_generator_t: + jose_jwk_generator_t *next + const char *kty + + ctypedef struct jose_jwk_hasher_t: + jose_jwk_hasher_t *next + const char *name + size_t size + + ctypedef struct jose_jws_signer_t: + jose_jws_signer_t *next + const char *alg + + ctypedef struct jose_jwe_crypter_t: + jose_jwe_crypter_t *next + const char *enc + + ctypedef struct jose_jwe_wrapper_t: + jose_jwe_wrapper_t *next + const char *alg + + ctypedef struct jose_jwe_zipper_t: + jose_jwe_zipper_t *next + const char *zip + + jose_jwk_type_t *jose_jwk_types() + jose_jwk_op_t *jose_jwk_ops() + jose_jwk_generator_t *jose_jwk_generators() + jose_jwk_hasher_t *jose_jwk_hashers() + jose_jws_signer_t *jose_jws_signers() + jose_jwe_crypter_t *jose_jwe_crypters() + jose_jwe_wrapper_t *jose_jwe_wrappers() + jose_jwe_zipper_t *jose_jwe_zippers() diff --git a/tests/test_jose.py b/tests/test_jose.py index dd6b552..06ced43 100644 --- a/tests/test_jose.py +++ b/tests/test_jose.py @@ -46,6 +46,59 @@ def test_jws_sign(self): jose.jws.sign(jws, jwk, None) jose.jws.sign(jws, jwk, sig) + def test_get_supported_algorithms(self): + sup = jose.get_supported_algorithms() + self.assertEqual( + set(sup), + {'jwe_crypters', 'jwe_wrappers', 'jwe_zippers', 'jwk_generators', + 'jwk_hashers', 'jwk_ops', 'jwk_types', 'jws_signers'}) + self.assertEqual( + sup['jwe_crypters'], + {'A128CBC-HS256', 'A128GCM', 'A192CBC-HS384', 'A192GCM', + 'A256CBC-HS512', 'A256GCM'} + ) + self.assertEqual( + sup['jwe_wrappers'], + {'A128GCMKW', 'A128KW', 'A192GCMKW', 'A192KW', + 'A256GCMKW', 'A256KW', 'ECDH-ES', 'ECDH-ES+A128KW', + 'ECDH-ES+A192KW', 'ECDH-ES+A256KW', 'PBES2-HS256+A128KW', + 'PBES2-HS384+A192KW', 'PBES2-HS512+A256KW', 'RSA-OAEP', + 'RSA-OAEP-256', 'RSA1_5', 'dir'} + ) + self.assertEqual(sup['jwe_zippers'], {'DEF'}) + self.assertEqual(sup['jwk_generators'], {'EC', 'oct', 'RSA'}) + self.assertEqual( + sup['jws_signers'], + {'ES256', 'ES384', 'ES512', 'HS256', 'HS384', 'HS512', 'PS256', + 'PS384', 'PS512', 'RS256', 'RS384', 'RS512'}) + self.assertEqual( + sup['jwk_hashers'], + {'sha1': 20, + 'sha224': 28, + 'sha256': 32, + 'sha384': 48, + 'sha512': 64}) + self.assertEqual( + sorted(sup['jwk_ops']), + [('encrypt', 'decrypt', 'enc'), + ('verify', 'sign', 'sig'), + ('wrapKey', 'unwrapKey', 'enc')] + ) + self.assertEqual( + sup['jwk_types'], + { + 'EC': {'prv': ['d'], + 'req': ['crv', 'x', 'y'], + 'sym': False}, + 'RSA': {'prv': ['p', 'd', 'q', 'dp', 'dq', 'qi', 'oth'], + 'req': ['e', 'n'], + 'sym': False}, + 'oct': {'prv': ['k'], + 'req': ['k'], + 'sym': True}, + } + ) + def test_compact(self): filename = os.path.join(HERE, 'vectors', 'rfc7515_A.1.jwsc') with open(filename, 'rb') as f: