Skip to content

Commit 581c6d7

Browse files
authored
Merge pull request #1 from blag/add-jwe-aenglander
Add JWE support
2 parents 1bc6795 + 5276cae commit 581c6d7

25 files changed

+2404
-120
lines changed

docs/index.rst

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ Contents
2424
jws/index
2525
jwt/index
2626
jwk/index
27+
jwe/index
2728

2829

2930
APIs
@@ -35,6 +36,7 @@ APIs
3536
jws/api
3637
jwt/api
3738
jwk/api
39+
jwe/api
3840

3941

4042
Principles

docs/jwe/api.rst

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
2+
JWE API
3+
^^^^^^^
4+
5+
.. automodule:: jose.jwe
6+
:members:

docs/jwe/index.rst

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
JSON Web Encryption
2+
===================
3+
4+
JSON Web Encryption (JWE) are used to encrypt a payload and represent it as a
5+
compact URL-safe string.
6+
7+
Supported Content Encryption Algorithms
8+
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
9+
10+
The following algorithms are currently supported.
11+
12+
+------------------+------------------------------------------------+
13+
| Encryption Value | Encryption Algorithm, Mode, and Auth Tag |
14+
+==================+================================================+
15+
| A128CBC_HS256 | AES w/128 bit key in CBC mode w/SHA256 HMAC |
16+
+------------------+------------------------------------------------+
17+
| A192CBC_HS384 | AES w/128 bit key in CBC mode w/SHA256 HMAC |
18+
+------------------+------------------------------------------------+
19+
| A256CBC_HS512 | AES w/128 bit key in CBC mode w/SHA256 HMAC |
20+
+------------------+------------------------------------------------+
21+
| A128GCM | AES w/128 bit key in GCM mode and GCM auth tag |
22+
+------------------+------------------------------------------------+
23+
| A192GCM | AES w/192 bit key in GCM mode and GCM auth tag |
24+
+------------------+------------------------------------------------+
25+
| A256GCM | AES w/256 bit key in GCM mode and GCM auth tag |
26+
+------------------+------------------------------------------------+
27+
28+
Supported Key Management Algorithms
29+
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
30+
31+
The following algorithms are currently supported.
32+
33+
+-----------------+------------------------------------------------+
34+
| Algorithm Value | Key Wrap Algorithm |
35+
+=================+================================================+
36+
| DIR | Direct (no key wrap) |
37+
+-----------------+------------------------------------------------+
38+
| RSA1_5 | RSAES with PKCS1 v1.5 |
39+
+-----------------+------------------------------------------------+
40+
| RSA_OAEP | RSAES OAEP using default parameters |
41+
+-----------------+------------------------------------------------+
42+
| RSA_OAEP_256 | RSAES OAEP using SHA-256 and MGF1 with SHA-256 |
43+
+-----------------+------------------------------------------------+
44+
| A128KW | AES Key Wrap with default IV using 128-bit key |
45+
+-----------------+------------------------------------------------+
46+
| A192KW m | AES Key Wrap with default IV using 192-bit key |
47+
+-----------------+------------------------------------------------+
48+
| A256KW | AES Key Wrap with default IV using 256-bit key |
49+
+-----------------+------------------------------------------------+
50+
51+
Examples
52+
^^^^^^^^
53+
54+
Encrypting Payloads
55+
-------------------
56+
57+
.. code:: python
58+
59+
>>> from jose import jwe
60+
>>> jwe.encrypt('Hello, World!', 'asecret128bitkey', algorithm='dir', encryption='A128GCM')
61+
'eyJhbGciOiJkaXIiLCJlbmMiOiJBMTI4R0NNIn0..McILMB3dYsNJSuhcDzQshA.OfX9H_mcUpHDeRM4IA.CcnTWqaqxNsjT4eCaUABSg'
62+
63+
64+
Decrypting Payloads
65+
--------------------------
66+
67+
.. code:: python
68+
69+
>>> from jose import jwe
70+
>>> jwe.decrypt('eyJhbGciOiJkaXIiLCJlbmMiOiJBMTI4R0NNIn0..McILMB3dYsNJSuhcDzQshA.OfX9H_mcUpHDeRM4IA.CcnTWqaqxNsjT4eCaUABSg', 'asecret128bitkey')
71+
'Hello, World!'

jose/backends/__init__.py

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,10 @@
1+
try:
2+
from jose.backends.cryptography_backend import get_random_bytes # noqa: F401
3+
except ImportError:
4+
try:
5+
from jose.backends.pycrypto_backend import get_random_bytes # noqa: F401
6+
except ImportError:
7+
from jose.backends.native import get_random_bytes # noqa: F401
18

29
try:
310
from jose.backends.cryptography_backend import CryptographyRSAKey as RSAKey # noqa: F401
@@ -21,3 +28,18 @@
2128
from jose.backends.cryptography_backend import CryptographyECKey as ECKey # noqa: F401
2229
except ImportError:
2330
from jose.backends.ecdsa_backend import ECDSAECKey as ECKey # noqa: F401
31+
32+
try:
33+
from jose.backends.cryptography_backend import CryptographyAESKey as AESKey # noqa: F401
34+
except ImportError:
35+
try:
36+
from jose.backends.pycrypto_backend import AESKey # noqa: F401
37+
except ImportError:
38+
AESKey = None
39+
40+
try:
41+
from jose.backends.cryptography_backend import CryptographyHMACKey as HMACKey # noqa: F401
42+
except ImportError:
43+
from jose.backends.native import HMACKey # noqa: F401
44+
45+
from .base import DIRKey # noqa: F401

jose/backends/base.py

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,8 @@
1+
import six
2+
3+
from ..utils import base64url_encode
4+
5+
16
class Key(object):
27
"""
38
A simple interface for implementing JWK keys.
@@ -19,3 +24,67 @@ def to_pem(self):
1924

2025
def to_dict(self):
2126
raise NotImplementedError()
27+
28+
def encrypt(self, plain_text, aad=None):
29+
"""
30+
Encrypt the plain text and generate an auth tag if appropriate
31+
32+
Args:
33+
plain_text (bytes): Data to encrypt
34+
aad (bytes, optional): Authenticated Additional Data if key's algorithm supports auth mode
35+
36+
Returns:
37+
(bytes, bytes, bytes): IV, cipher text, and auth tag
38+
"""
39+
raise NotImplementedError()
40+
41+
def decrypt(self, cipher_text, iv=None, aad=None, tag=None):
42+
"""
43+
Decrypt the cipher text and validate the auth tag if present
44+
Args:
45+
cipher_text (bytes): Cipher text to decrypt
46+
iv (bytes): IV if block mode
47+
aad (bytes): Additional Authenticated Data to verify if auth mode
48+
tag (bytes): Authentication tag if auth mode
49+
50+
Returns:
51+
bytes: Decrypted value
52+
"""
53+
raise NotImplementedError()
54+
55+
def wrap_key(self, key_data):
56+
"""
57+
Wrap the the plain text key data
58+
59+
Args:
60+
key_data (bytes): Key data to wrap
61+
62+
Returns:
63+
bytes: Wrapped key
64+
"""
65+
raise NotImplementedError()
66+
67+
def unwrap_key(self, wrapped_key):
68+
"""
69+
Unwrap the the wrapped key data
70+
71+
Args:
72+
wrapped_key (bytes): Wrapped key data to unwrap
73+
74+
Returns:
75+
bytes: Unwrapped key
76+
"""
77+
raise NotImplementedError()
78+
79+
80+
class DIRKey(Key):
81+
def __init__(self, key_data, algorithm):
82+
self._key = six.ensure_binary(key_data)
83+
self._alg = algorithm
84+
85+
def to_dict(self):
86+
return {
87+
'alg': self._alg,
88+
'kty': 'oct',
89+
'k': base64url_encode(self._key),
90+
}

0 commit comments

Comments
 (0)