Skip to content

Commit

Permalink
Merge pull request #1 from blag/add-jwe-aenglander
Browse files Browse the repository at this point in the history
Add JWE support
  • Loading branch information
blag committed Aug 22, 2020
2 parents 1bc6795 + 5276cae commit 581c6d7
Show file tree
Hide file tree
Showing 25 changed files with 2,404 additions and 120 deletions.
2 changes: 2 additions & 0 deletions docs/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ Contents
jws/index
jwt/index
jwk/index
jwe/index


APIs
Expand All @@ -35,6 +36,7 @@ APIs
jws/api
jwt/api
jwk/api
jwe/api


Principles
Expand Down
6 changes: 6 additions & 0 deletions docs/jwe/api.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@

JWE API
^^^^^^^

.. automodule:: jose.jwe
:members:
71 changes: 71 additions & 0 deletions docs/jwe/index.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
JSON Web Encryption
===================

JSON Web Encryption (JWE) are used to encrypt a payload and represent it as a
compact URL-safe string.

Supported Content Encryption Algorithms
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

The following algorithms are currently supported.

+------------------+------------------------------------------------+
| Encryption Value | Encryption Algorithm, Mode, and Auth Tag |
+==================+================================================+
| A128CBC_HS256 | AES w/128 bit key in CBC mode w/SHA256 HMAC |
+------------------+------------------------------------------------+
| A192CBC_HS384 | AES w/128 bit key in CBC mode w/SHA256 HMAC |
+------------------+------------------------------------------------+
| A256CBC_HS512 | AES w/128 bit key in CBC mode w/SHA256 HMAC |
+------------------+------------------------------------------------+
| A128GCM | AES w/128 bit key in GCM mode and GCM auth tag |
+------------------+------------------------------------------------+
| A192GCM | AES w/192 bit key in GCM mode and GCM auth tag |
+------------------+------------------------------------------------+
| A256GCM | AES w/256 bit key in GCM mode and GCM auth tag |
+------------------+------------------------------------------------+

Supported Key Management Algorithms
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

The following algorithms are currently supported.

+-----------------+------------------------------------------------+
| Algorithm Value | Key Wrap Algorithm |
+=================+================================================+
| DIR | Direct (no key wrap) |
+-----------------+------------------------------------------------+
| RSA1_5 | RSAES with PKCS1 v1.5 |
+-----------------+------------------------------------------------+
| RSA_OAEP | RSAES OAEP using default parameters |
+-----------------+------------------------------------------------+
| RSA_OAEP_256 | RSAES OAEP using SHA-256 and MGF1 with SHA-256 |
+-----------------+------------------------------------------------+
| A128KW | AES Key Wrap with default IV using 128-bit key |
+-----------------+------------------------------------------------+
| A192KW m | AES Key Wrap with default IV using 192-bit key |
+-----------------+------------------------------------------------+
| A256KW | AES Key Wrap with default IV using 256-bit key |
+-----------------+------------------------------------------------+

Examples
^^^^^^^^

Encrypting Payloads
-------------------

.. code:: python
>>> from jose import jwe
>>> jwe.encrypt('Hello, World!', 'asecret128bitkey', algorithm='dir', encryption='A128GCM')
'eyJhbGciOiJkaXIiLCJlbmMiOiJBMTI4R0NNIn0..McILMB3dYsNJSuhcDzQshA.OfX9H_mcUpHDeRM4IA.CcnTWqaqxNsjT4eCaUABSg'
Decrypting Payloads
--------------------------

.. code:: python
>>> from jose import jwe
>>> jwe.decrypt('eyJhbGciOiJkaXIiLCJlbmMiOiJBMTI4R0NNIn0..McILMB3dYsNJSuhcDzQshA.OfX9H_mcUpHDeRM4IA.CcnTWqaqxNsjT4eCaUABSg', 'asecret128bitkey')
'Hello, World!'
22 changes: 22 additions & 0 deletions jose/backends/__init__.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,10 @@
try:
from jose.backends.cryptography_backend import get_random_bytes # noqa: F401
except ImportError:
try:
from jose.backends.pycrypto_backend import get_random_bytes # noqa: F401
except ImportError:
from jose.backends.native import get_random_bytes # noqa: F401

try:
from jose.backends.cryptography_backend import CryptographyRSAKey as RSAKey # noqa: F401
Expand All @@ -21,3 +28,18 @@
from jose.backends.cryptography_backend import CryptographyECKey as ECKey # noqa: F401
except ImportError:
from jose.backends.ecdsa_backend import ECDSAECKey as ECKey # noqa: F401

try:
from jose.backends.cryptography_backend import CryptographyAESKey as AESKey # noqa: F401
except ImportError:
try:
from jose.backends.pycrypto_backend import AESKey # noqa: F401
except ImportError:
AESKey = None

try:
from jose.backends.cryptography_backend import CryptographyHMACKey as HMACKey # noqa: F401
except ImportError:
from jose.backends.native import HMACKey # noqa: F401

from .base import DIRKey # noqa: F401
69 changes: 69 additions & 0 deletions jose/backends/base.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
import six

from ..utils import base64url_encode


class Key(object):
"""
A simple interface for implementing JWK keys.
Expand All @@ -19,3 +24,67 @@ def to_pem(self):

def to_dict(self):
raise NotImplementedError()

def encrypt(self, plain_text, aad=None):
"""
Encrypt the plain text and generate an auth tag if appropriate
Args:
plain_text (bytes): Data to encrypt
aad (bytes, optional): Authenticated Additional Data if key's algorithm supports auth mode
Returns:
(bytes, bytes, bytes): IV, cipher text, and auth tag
"""
raise NotImplementedError()

def decrypt(self, cipher_text, iv=None, aad=None, tag=None):
"""
Decrypt the cipher text and validate the auth tag if present
Args:
cipher_text (bytes): Cipher text to decrypt
iv (bytes): IV if block mode
aad (bytes): Additional Authenticated Data to verify if auth mode
tag (bytes): Authentication tag if auth mode
Returns:
bytes: Decrypted value
"""
raise NotImplementedError()

def wrap_key(self, key_data):
"""
Wrap the the plain text key data
Args:
key_data (bytes): Key data to wrap
Returns:
bytes: Wrapped key
"""
raise NotImplementedError()

def unwrap_key(self, wrapped_key):
"""
Unwrap the the wrapped key data
Args:
wrapped_key (bytes): Wrapped key data to unwrap
Returns:
bytes: Unwrapped key
"""
raise NotImplementedError()


class DIRKey(Key):
def __init__(self, key_data, algorithm):
self._key = six.ensure_binary(key_data)
self._alg = algorithm

def to_dict(self):
return {
'alg': self._alg,
'kty': 'oct',
'k': base64url_encode(self._key),
}

0 comments on commit 581c6d7

Please sign in to comment.