-
Notifications
You must be signed in to change notification settings - Fork 17
/
Copy pathjwe_hmac.py
102 lines (82 loc) · 2.89 KB
/
jwe_hmac.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
import logging
import zlib
from cryptography.hazmat.primitives.keywrap import aes_key_unwrap
from cryptography.hazmat.primitives.keywrap import aes_key_wrap
from ..exception import MissingKey
from ..exception import WrongNumberOfParts
from ..jwk.hmac import SYMKey
from ..utils import as_bytes
from ..utils import intarr2str
from .jwekey import JWEKey
from .jwenc import JWEnc
logger = logging.getLogger(__name__)
__author__ = "Roland Hedberg"
class JWE_SYM(JWEKey):
args = JWEKey.args[:]
args.append("enc")
def encrypt(self, key, iv="", cek="", **kwargs):
"""
Produces a JWE as defined in RFC7516 using symmetric keys
:param key: Shared symmetric key
:param iv: Initialization vector
:param cek: Content master key
:param kwargs: Extra keyword arguments, just ignore for now.
:return:
"""
_msg = as_bytes(self.msg)
_args = self._dict
try:
_args["kid"] = kwargs["kid"]
except KeyError:
pass
jwe = JWEnc(**_args)
# If no iv and cek are given generate them
iv = self._generate_iv(self["enc"], iv)
cek = self._generate_key(self["enc"], cek)
if isinstance(key, SYMKey):
try:
kek = key.key.encode("utf8")
except AttributeError:
kek = key.key
elif isinstance(key, bytes):
kek = key
else:
kek = intarr2str(key)
# The iv for this function must be 64 bit
# Which is certainly different from the one above
jek = aes_key_wrap(kek, cek)
_enc = self["enc"]
_auth_data = jwe.b64_encode_header()
ctxt, tag, cek = self.enc_setup(_enc, _msg, auth_data=_auth_data, key=cek, iv=iv)
return jwe.pack(parts=[jek, iv, ctxt, tag])
def decrypt(self, token, key=None, cek=None):
logger.debug("SYM decrypt")
if not key and not cek:
raise MissingKey("On of key or cek must be specified")
if isinstance(token, JWEnc):
jwe = token
else:
jwe = JWEnc().unpack(token)
if len(jwe) != 5:
raise WrongNumberOfParts(len(jwe))
if not cek:
jek = jwe.encrypted_key()
if isinstance(key, SYMKey):
try:
key = key.key.encode("utf8")
except AttributeError:
key = key.key
# The iv for this function must be 64 bit
cek = aes_key_unwrap(key, jek)
auth_data = jwe.b64_protected_header()
msg = self._decrypt(
jwe.headers["enc"],
cek,
jwe.ciphertext(),
auth_data=auth_data,
iv=jwe.initialization_vector(),
tag=jwe.authentication_tag(),
)
if "zip" in self and self["zip"] == "DEF":
msg = zlib.decompress(msg)
return msg