def _extract(s): try: s = to_bytes(s) signing_input, signature_segment = s.rsplit(b'.', 1) header_segment, payload_segment = signing_input.split(b'.', 1) except ValueError: raise DecodeError('Not enough segments') try: header_data = urlsafe_b64decode(header_segment) except (TypeError, binascii.Error): raise DecodeError('Invalid header padding') try: header = json.loads(header_data.decode('utf-8')) except ValueError as e: raise DecodeError('Invalid header string: {}'.format(e)) if not isinstance(header, Mapping): raise DecodeError('Header must be a json object') if 'alg' not in header: raise DecodeError('Missing "alg" in header') try: payload = urlsafe_b64decode(payload_segment) except (TypeError, binascii.Error): raise DecodeError('Invalid payload padding') try: signature = urlsafe_b64decode(signature_segment) except (TypeError, binascii.Error): raise DecodeError('Invalid crypto padding') return header, payload, signing_input, signature
def _u32be_len_input(s, base64=False): if not s: return b'\x00\x00\x00\x00' if base64: s = urlsafe_b64decode(to_bytes(s)) else: s = to_bytes(s) return struct.pack('>I', len(s)) + s
def unwrap(self, ek, headers, key): self._check_key(key) iv = headers.get('iv') if not iv: raise ValueError('Missing "iv" in headers') tag = headers.get('tag') if not tag: raise ValueError('Missing "tag" in headers') iv = urlsafe_b64decode(to_bytes(iv)) tag = urlsafe_b64decode(to_bytes(tag)) cipher = Cipher(AES(key), GCM(iv, tag), backend=default_backend()) d = cipher.decryptor() cek = d.update(ek) + d.finalize() return cek
def loads(self, obj): for k in ['crv', 'x']: if k not in obj: raise ValueError('Not a elliptic curve key') crv = obj['crv'] if crv not in CURVES_KEYS: raise ValueError('Unsupported crv for OKP') keys = CURVES_KEYS[crv] # The parameter "d" MUST be present for private keys if 'd' in obj: crv_key = keys[1] d_bytes = urlsafe_b64decode(to_bytes(obj['d'])) return crv_key.from_private_bytes(d_bytes) crv_key = keys[0] x_bytes = urlsafe_b64decode(to_bytes(obj['x'])) return crv_key.from_public_bytes(x_bytes)
def unwrap(self, enc_alg, ek, headers, key): op_key = key.get_op_key('unwrapKey') self._check_key(op_key) iv = headers.get('iv') if not iv: raise ValueError('Missing "iv" in headers') tag = headers.get('tag') if not tag: raise ValueError('Missing "tag" in headers') iv = urlsafe_b64decode(to_bytes(iv)) tag = urlsafe_b64decode(to_bytes(tag)) cipher = Cipher(AES(op_key), GCM(iv, tag), backend=default_backend()) d = cipher.decryptor() cek = d.update(ek) + d.finalize() if len(cek) * 8 != enc_alg.CEK_SIZE: raise ValueError('Invalid "cek" length') return cek
def _extract_header(header_segment): try: header_data = urlsafe_b64decode(header_segment) except (TypeError, binascii.Error): raise DecodeError('Invalid header padding') try: header = json.loads(header_data.decode('utf-8')) except ValueError as e: raise DecodeError('Invalid header string: {}'.format(e)) if not isinstance(header, dict): raise DecodeError('Header must be a json object') return header
def import_key(cls, raw, options=None): if isinstance(raw, dict): cls.check_required_fields(raw) payload = raw raw_key = urlsafe_b64decode(to_bytes(payload['k'])) else: raw_key = to_bytes(raw) k = to_unicode(urlsafe_b64encode(raw_key)) payload = {'k': k} if options is not None: payload.update(options) obj = cls(payload) obj.raw_key = raw_key obj.key_type = 'secret' return obj
def loads(self, obj): return urlsafe_b64decode(to_bytes(obj['k']))
def _extract_signature(signature_segment): try: return urlsafe_b64decode(signature_segment) except (TypeError, binascii.Error): raise DecodeError('Invalid signature')
def extract_payload(self, payload_segment): try: return urlsafe_b64decode(payload_segment) except (TypeError, binascii.Error): raise DecodeError('Invalid payload padding')
def load_private_key(self): crv_key = PRIVATE_KEYS_MAP[self._dict_data['crv']] d_bytes = urlsafe_b64decode(to_bytes(self._dict_data['d'])) return crv_key.from_private_bytes(d_bytes)
def test_keys(): """Try to store/get/remove keys""" # JWS jws = JsonWebSignature(algorithms=["RS256"]) code_payload = { "user_id": "user", "scope": "scope", "client_id": "client", "redirect_uri": "redirect_uri", "code_challenge": "code_challenge", } # Token metadata header = {"alg": "RS256"} payload = { "sub": "user", "iss": "issuer", "scope": "scope", "setup": "setup", "group": "my_group" } # Remove all keys result = db.removeKeys() assert result["OK"], result["Message"] # Check active keys result = db.getActiveKeys() assert result["OK"], result["Message"] assert result["Value"] == [] # Create new one result = db.getPrivateKey() assert result["OK"], result["Message"] private_key = result["Value"] assert isinstance(private_key, RSAKey) # Sign token header["kid"] = private_key.thumbprint() # Find key by KID result = db.getPrivateKey(header["kid"]) assert result["OK"], result["Message"] # as_dict has no arguments for authlib < 1.0.0 # for authlib >= 1.0.0: assert result["Value"].as_dict(True) == private_key.as_dict(True) # Sign token token = jwt.encode(header, payload, private_key) # Sign auth code code = jws.serialize_compact(header, json_b64encode(code_payload), private_key) # Get public key set result = db.getKeySet() keyset = result["Value"] assert result["OK"], result["Message"] # as_dict has no arguments for authlib < 1.0.0 # for authlib >= 1.0.0: assert bool([ key for key in keyset.as_dict(True)["keys"] if key["kid"] == header["kid"] ]) # Read token _payload = jwt.decode(token, JsonWebKey.import_key_set(keyset.as_dict())) assert _payload == payload # Read auth code data = jws.deserialize_compact(code, keyset.keys[0]) _code_payload = json_loads(urlsafe_b64decode(data["payload"])) assert _code_payload == code_payload
def loads_public_key(obj): crv_key = PUBLIC_KEYS_MAP[obj['crv']] x_bytes = urlsafe_b64decode(to_bytes(obj['x'])) return crv_key.from_public_bytes(x_bytes)
def loads_private_key(obj): crv_key = PRIVATE_KEYS_MAP[obj['crv']] d_bytes = urlsafe_b64decode(to_bytes(obj['d'])) return crv_key.from_private_bytes(d_bytes)
def jwt_decode(s: str) -> dict: from authlib.common.encoding import urlsafe_b64decode, json_loads return json_loads(urlsafe_b64decode(s.encode('ascii')))
def load_public_key(self): crv_key = PUBLIC_KEYS_MAP[self._dict_data['crv']] x_bytes = urlsafe_b64decode(to_bytes(self._dict_data['x'])) return crv_key.from_public_bytes(x_bytes)
def extract_segment(segment, error_cls, name='payload'): try: return urlsafe_b64decode(segment) except (TypeError, binascii.Error): msg = 'Invalid {} padding'.format(name) raise error_cls(msg)
def load_raw_key(self): self.raw_key = urlsafe_b64decode(to_bytes(self.tokens['k']))