Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(400)

Side by Side Diff: third_party/google-endpoints/jwkest/__init__.py

Issue 2666783008: Add google-endpoints to third_party/. (Closed)
Patch Set: Created 3 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 """JSON Web Token"""
2 import base64
3 import logging
4 import re
5 import struct
6 import six
7
8 try:
9 from builtins import zip
10 from builtins import hex
11 from builtins import str
12 except ImportError:
13 pass
14
15 from binascii import unhexlify
16
17 __version__ = "1.0.9"
18
19 logger = logging.getLogger(__name__)
20
21 JWT_TYPES = (u"JWT", u"application/jws", u"JWS", u"JWE")
22
23 JWT_CLAIMS = {"iss": str, "sub": str, "aud": str, "exp": int, "nbf": int,
24 "iat": int, "jti": str, "typ": str}
25
26 JWT_HEADERS = ["typ", "cty"]
27
28
29 class JWKESTException(Exception):
30 pass
31
32
33 # XXX Should this be a subclass of ValueError?
34 class Invalid(JWKESTException):
35 """The JWT is invalid."""
36
37
38 class BadSyntax(Invalid):
39 """The JWT could not be parsed because the syntax is invalid."""
40
41 def __init__(self, value, msg):
42 Invalid.__init__(self)
43 self.value = value
44 self.msg = msg
45
46 def __str__(self):
47 return "%s: %r" % (self.msg, self.value)
48
49
50 class BadSignature(Invalid):
51 """The signature of the JWT is invalid."""
52
53
54 class Expired(Invalid):
55 """The JWT claim has expired or is not yet valid."""
56
57
58 class UnknownAlgorithm(Invalid):
59 """The JWT uses an unknown signing algorithm"""
60
61
62 class BadType(Invalid):
63 """The JWT has an unexpected "typ" value."""
64
65
66 class MissingKey(JWKESTException):
67 """ No usable key """
68
69
70 class UnknownKeytype(Invalid):
71 """An unknown key type"""
72
73
74 # ---------------------------------------------------------------------------
75 # Helper functions
76
77
78 def intarr2bin(arr):
79 return unhexlify(''.join(["%02x" % byte for byte in arr]))
80
81
82 def long2hexseq(l):
83 try:
84 return unhexlify(hex(l)[2:])
85 except TypeError:
86 return unhexlify(hex(l)[2:-1])
87
88
89 def intarr2long(arr):
90 return int(''.join(["%02x" % byte for byte in arr]), 16)
91
92
93 def long2intarr(long_int):
94 _bytes = []
95 while long_int:
96 long_int, r = divmod(long_int, 256)
97 _bytes.insert(0, r)
98 return _bytes
99
100
101 def long_to_base64(n):
102 bys = long2intarr(n)
103 data = struct.pack('%sB' % len(bys), *bys)
104 if not len(data):
105 data = '\x00'
106 s = base64.urlsafe_b64encode(data).rstrip(b'=')
107 return s.decode("ascii")
108
109
110 def base64_to_long(data):
111 if isinstance(data, six.text_type):
112 data = data.encode("ascii")
113
114 # urlsafe_b64decode will happily convert b64encoded data
115 _d = base64.urlsafe_b64decode(bytes(data) + b'==')
116 return intarr2long(struct.unpack('%sB' % len(_d), _d))
117
118
119 def base64url_to_long(data):
120 """
121 Stricter then base64_to_long since it really checks that it's
122 base64url encoded
123
124 :param data: The base64 string
125 :return:
126 """
127 _d = base64.urlsafe_b64decode(bytes(data) + b'==')
128 # verify that it's base64url encoded and not just base64
129 # that is no '+' and '/' characters and not trailing "="s.
130 if [e for e in [b'+', b'/', b'='] if e in data]:
131 raise ValueError("Not base64url encoded")
132 return intarr2long(struct.unpack('%sB' % len(_d), _d))
133
134
135 # =============================================================================
136
137 def b64e(b):
138 """Base64 encode some bytes.
139
140 Uses the url-safe - and _ characters, and doesn't pad with = characters."""
141 return base64.urlsafe_b64encode(b).rstrip(b"=")
142
143
144 _b64_re = re.compile(b"^[A-Za-z0-9_-]*$")
145
146
147 def add_padding(b):
148 # add padding chars
149 m = len(b) % 4
150 if m == 1:
151 # NOTE: for some reason b64decode raises *TypeError* if the
152 # padding is incorrect.
153 raise BadSyntax(b, "incorrect padding")
154 elif m == 2:
155 b += b"=="
156 elif m == 3:
157 b += b"="
158 return b
159
160
161 def b64d(b):
162 """Decode some base64-encoded bytes.
163
164 Raises BadSyntax if the string contains invalid characters or padding.
165
166 :param b: bytes
167 """
168
169 cb = b.rstrip(b"=") # shouldn't but there you are
170
171 # Python's base64 functions ignore invalid characters, so we need to
172 # check for them explicitly.
173 if not _b64_re.match(cb):
174 raise BadSyntax(cb, "base64-encoded data contains illegal characters")
175
176 if cb == b:
177 b = add_padding(b)
178
179 return base64.urlsafe_b64decode(b)
180
181
182 def b64e_enc_dec(str, encode, decode):
183 return base64.urlsafe_b64encode(str.encode(encode)).decode(decode)
184
185
186 def b64d_enc_dec(str, encode, decode):
187 return base64.urlsafe_b64decode(str.encode(encode)).decode(decode)
188
189
190 # 'Stolen' from Werkzeug
191 def safe_str_cmp(a, b):
192 """Compare two strings in constant time."""
193 if len(a) != len(b):
194 return False
195 r = 0
196 for c, d in zip(a, b):
197 r |= ord(c) ^ ord(d)
198 return r == 0
199
200
201 def constant_time_compare(a, b):
202 """Compare two strings in constant time."""
203 if len(a) != len(b):
204 return False
205 r = 0
206 for c, d in zip(a, b):
207 r |= c ^ d
208 return r == 0
209
210
211 def as_bytes(s):
212 """
213 Convert an unicode string to bytes.
214 :param s: Unicode / bytes string
215 :return: bytes string
216 """
217 try:
218 s = s.encode()
219 except (AttributeError, UnicodeDecodeError):
220 pass
221 return s
222
223
224 def as_unicode(b):
225 """
226 Convert a byte string to a unicode string
227 :param b: byte string
228 :return: unicode string
229 """
230 try:
231 b = b.decode()
232 except (AttributeError, UnicodeDecodeError):
233 pass
234 return b
OLDNEW
« no previous file with comments | « third_party/google-endpoints/jwkest/PBKDF2.py ('k') | third_party/google-endpoints/jwkest/aes_gcm.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698