def forgot_password(mode) : """ @app.route('/forgot_password/', methods = ['GET', 'POST']) This function is called from the login view. build JWE to store timestamp, username and email, we use Talao RSA key """ if request.method == 'GET' : return render_template('./login/forgot_password_init.html') if request.method == 'POST' : username = request.form.get('username') if not ns.username_exist(username, mode) : flash("Username not found", "warning") return render_template('./login/login_password.html') email= ns.get_data_from_username(username, mode)['email'] private_rsa_key = privatekey.get_key(mode.owner_talao, 'rsa_key', mode) RSA_KEY = RSA.import_key(private_rsa_key) public_rsa_key = RSA_KEY.publickey().export_key('PEM').decode('utf-8') expired = datetime.timestamp(datetime.now()) + 180 # 3 minutes live # build JWE jwe = JsonWebEncryption() header = {'alg': 'RSA1_5', 'enc': 'A256GCM'} json_string = json.dumps({'username' : username, 'email' : email, 'expired' : expired}) payload = bytes(json_string, 'utf-8') token = jwe.serialize_compact(header, payload, public_rsa_key) link = mode.server + 'forgot_password_token/?'+ urlencode({'token' : token.decode('utf-8')}, doseq=True) subject = "Renew your password" if Talao_message.messageHTML(subject, email, 'forgot_password', {'link': link}, mode): flash("You are going to receive an email to renew your password.", "success") return render_template('./login/login_password.html')
def test_compact_rsa(self): jwe = JsonWebEncryption(algorithms=JWE_ALGORITHMS) s = jwe.serialize_compact({ 'alg': 'RSA-OAEP', 'enc': 'A256GCM' }, 'hello', read_file_path('rsa_public.pem')) data = jwe.deserialize_compact(s, read_file_path('rsa_private.pem')) header, payload = data['header'], data['payload'] self.assertEqual(payload, b'hello') self.assertEqual(header['alg'], 'RSA-OAEP')
def test_ecdh_es_with_okp(self): jwe = JsonWebEncryption(algorithms=JWE_ALGORITHMS) key = OKPKey.generate_key('X25519', is_private=True) for alg in [ "ECDH-ES", "ECDH-ES+A128KW", "ECDH-ES+A192KW", "ECDH-ES+A256KW" ]: protected = {'alg': alg, 'enc': 'A128GCM'} data = jwe.serialize_compact(protected, b'hello', key) rv = jwe.deserialize_compact(data, key) self.assertEqual(rv['payload'], b'hello')
def test_with_zip_header(self): jwe = JsonWebEncryption() s = jwe.serialize_compact( { 'alg': 'RSA-OAEP', 'enc': 'A128CBC-HS256', 'zip': 'DEF' }, 'hello', read_file_path('rsa_public.pem')) data = jwe.deserialize_compact(s, read_file_path('rsa_private.pem')) header, payload = data['header'], data['payload'] self.assertEqual(payload, b'hello') self.assertEqual(header['alg'], 'RSA-OAEP')
def test_dir_alg_c20p(self): jwe = JsonWebEncryption(algorithms=JWE_ALGORITHMS) key = OctKey.generate_key(256, is_private=True) protected = {'alg': 'dir', 'enc': 'C20P'} data = jwe.serialize_compact(protected, b'hello', key) rv = jwe.deserialize_compact(data, key) self.assertEqual(rv['payload'], b'hello') key2 = OctKey.generate_key(128, is_private=True) self.assertRaises(ValueError, jwe.deserialize_compact, data, key2) self.assertRaises(ValueError, jwe.serialize_compact, protected, b'hello', key2)
def test_ecdh_es_raise(self): jwe = JsonWebEncryption(algorithms=JWE_ALGORITHMS) protected = {'alg': 'ECDH-ES', 'enc': 'A128GCM'} key = { "kty": "EC", "crv": "P-256", "x": "gI0GAILBdu7T53akrFmMyGcsF3n5dO7MmwNBHKW5SV0", "y": "SLW_xSffzlPWrHEVI30DHM_4egVwt3NQqeUD7nMFpps", } data = jwe.serialize_compact(protected, b'hello', key) self.assertRaises(ValueError, jwe.deserialize_compact, data, key) key = OKPKey.generate_key('Ed25519', is_private=True) self.assertRaises(ValueError, jwe.serialize_compact, protected, b'hello', key)
def test_aes_gcm_jwe(self): jwe = JsonWebEncryption(algorithms=JWE_ALGORITHMS) sizes = [128, 192, 256] _enc_choices = [ 'A128CBC-HS256', 'A192CBC-HS384', 'A256CBC-HS512', 'A128GCM', 'A192GCM', 'A256GCM' ] for s in sizes: alg = 'A{}GCMKW'.format(s) key = os.urandom(s // 8) for enc in _enc_choices: protected = {'alg': alg, 'enc': enc} data = jwe.serialize_compact(protected, b'hello', key) rv = jwe.deserialize_compact(data, key) self.assertEqual(rv['payload'], b'hello')
def test_ecdh_es_jwe(self): jwe = JsonWebEncryption(algorithms=JWE_ALGORITHMS) key = { "kty": "EC", "crv": "P-256", "x": "gI0GAILBdu7T53akrFmMyGcsF3n5dO7MmwNBHKW5SV0", "y": "SLW_xSffzlPWrHEVI30DHM_4egVwt3NQqeUD7nMFpps", "d": "0_NxaRPUMQoAJt50Gz8YiTr8gRTwyEaCumd-MToTmIo" } for alg in [ "ECDH-ES", "ECDH-ES+A128KW", "ECDH-ES+A192KW", "ECDH-ES+A256KW" ]: protected = {'alg': alg, 'enc': 'A128GCM'} data = jwe.serialize_compact(protected, b'hello', key) rv = jwe.deserialize_compact(data, key) self.assertEqual(rv['payload'], b'hello')
def test_not_supported_alg(self): public_key = read_file_path('rsa_public.pem') private_key = read_file_path('rsa_private.pem') jwe = JsonWebEncryption(algorithms=JWE_ALGORITHMS) s = jwe.serialize_compact({ 'alg': 'RSA-OAEP', 'enc': 'A256GCM' }, 'hello', public_key) jwe = JsonWebEncryption(algorithms=['RSA1_5', 'A256GCM']) self.assertRaises(errors.UnsupportedAlgorithmError, jwe.serialize_compact, { 'alg': 'RSA-OAEP', 'enc': 'A256GCM' }, 'hello', public_key) self.assertRaises(errors.UnsupportedCompressionAlgorithmError, jwe.serialize_compact, { 'alg': 'RSA1_5', 'enc': 'A256GCM', 'zip': 'DEF' }, 'hello', public_key) self.assertRaises( errors.UnsupportedAlgorithmError, jwe.deserialize_compact, s, private_key, ) jwe = JsonWebEncryption(algorithms=['RSA-OAEP', 'A192GCM']) self.assertRaises(errors.UnsupportedEncryptionAlgorithmError, jwe.serialize_compact, { 'alg': 'RSA-OAEP', 'enc': 'A256GCM' }, 'hello', public_key) self.assertRaises(errors.UnsupportedCompressionAlgorithmError, jwe.serialize_compact, { 'alg': 'RSA-OAEP', 'enc': 'A192GCM', 'zip': 'DEF' }, 'hello', public_key) self.assertRaises( errors.UnsupportedEncryptionAlgorithmError, jwe.deserialize_compact, s, private_key, )
def encrypt(self, data, type='AES', Key=None, dump=True): """ Encrypt data using RSA , AES param: type= type of key used in encryption: 'AES' or 'RSA' param: key= use your own key for RSA encryption param: dump= dumps the data if neccessary """ if dump == True: payload = str(json.dumps(data)).encode() else: payload = str(data).encode() if type == 'RSA': key = RSA.generate(2048) key = key.exportKey('PEM') key = jwk.dumps(key, kty='RSA') if Key: key = Key protected = {'alg': 'RSA-OAEP', 'enc': 'A256GCM'} jwe = JsonWebEncryption() token = jwe.serialize_compact(protected, payload, key) token = token.decode() else: key = secrets.token_urlsafe(32) token = SJCL().encrypt(payload, key, "ccm", 1000, 32) token['salt'] = str(token['salt']).replace("b'", "").replace("'", "") token['ct'] = str(token['ct']).replace("b'", "").replace("'", "") token['iv'] = str(token['iv']).replace("b'", "").replace("'", "") dic = {} dic['iv'] = token['iv'] dic['v'] = token['v'] dic['iter'] = token['iter'] dic['ks'] = token['ks'] dic['ts'] = token['ts'] dic['mode'] = token['mode'] dic['adata'] = token['adata'] dic['cipher'] = token['cipher'] dic['salt'] = token['salt'] dic['ct'] = token['ct'] token = dic return {'token': token, 'key': key}
def jweRsaEncryptToBase64UrlToken(rsaPublicKey, jweKeyAlgorithm, jweEncryptionAlgorithm, jwePayloadObject): jwe = JsonWebEncryption() jweHeaderObject = buildHeaderObject(jweKeyAlgorithm, jweEncryptionAlgorithm) return jwe.serialize_compact(jweHeaderObject, json.dumps(jwePayloadObject), rsaPublicKey)
def _create(address_from, workspace_contract_from, address_to, workspace_contract_to, private_key_from, doctype, data, mydays, privacy, mode, synchronous, version, id, sequence): # align doctype with privacy if privacy == 'private' and doctype == 20000: doctype = 20001 if privacy == 'secret' and doctype == 20000: doctype = 20002 # @data = dict if isinstance(data, str): data = json.loads(data) logging.error('data must be a dict') #encrypt data with AES key (public, private or secret) Deprecated if version == 3: data = privatekey.encrypt_data(workspace_contract_to, data, privacy, mode) if not data: logging.error('encryption problem') return None, None, None #encrypt server side data as JWE with identity RSA key elif version == 4: jwe = JsonWebEncryption() protected = {'alg': 'RSA-OAEP', 'enc': 'A256GCM'} payload = json.dumps(data).encode() private_rsa_key = privatekey.get_key(address_to, 'rsa_key', mode) RSA_KEY = RSA.import_key(private_rsa_key) public_rsa_key = RSA_KEY.publickey().export_key('PEM').decode('utf-8') if not id: id = str(uuid.uuid1()) if not sequence: sequence = 0 data = { "id": id, "sequence": sequence, "jwe": jwe.serialize_compact(protected, payload, public_rsa_key).decode() } # encrypt data with AES key of identity" elif version == 5: jwe = JsonWebEncryption() protected = {'alg': 'A128KW', 'enc': 'A128CBC-HS256'} payload = json.dumps(data).encode() if privacy == 'public': secret = mode.aes_public_key.encode() else: secret = privatekey.get_key(address_to, privacy, mode) if not id: id = str(uuid.uuid1()) if not sequence: sequence = 0 data = { "id": id, "sequence": sequence, "jwe": jwe.serialize_compact(protected, payload, secret).decode() } # No data encryption. data have been probably encrypted as JWE client side elif version == 6: data = { "id": str(uuid.uuid1()), "sequence": 0, 'jwe': json.dumps(data) } else: logging.error('pb version') return None, None, None # Build transaction contract = mode.w3.eth.contract(workspace_contract_to, abi=constante.workspace_ABI) nonce = mode.w3.eth.getTransactionCount(address_from) # upkoad on ipfs ipfs_hash = Talao_ipfs.ipfs_add(data, mode) if not ipfs_hash: logging.error('IPFS connexion problem') return None, None, None # checksum (bytes) checksum = hashlib.md5(bytes(json.dumps(data), 'utf-8')).hexdigest() # Transaction expires = 0 txn = contract.functions.createDocument(doctype, version, expires, checksum, 1, bytes(ipfs_hash, 'utf-8'), True).buildTransaction({ 'chainId': mode.CHAIN_ID, 'gas': 1000000, 'gasPrice': mode.w3.toWei( mode.GASPRICE, 'gwei'), 'nonce': nonce, }) signed_txn = mode.w3.eth.account.signTransaction(txn, private_key_from) mode.w3.eth.sendRawTransaction(signed_txn.rawTransaction) transaction_hash = mode.w3.toHex(mode.w3.keccak(signed_txn.rawTransaction)) if synchronous: if not mode.w3.eth.waitForTransactionReceipt( transaction_hash, timeout=2000, poll_latency=1)['status']: logging.error('transaction to create document failed') return None, None, None # Get document id on last event contract = mode.w3.eth.contract(workspace_contract_to, abi=constante.workspace_ABI) from_block = mode.w3.eth.blockNumber - 10 myfilter = contract.events.DocumentAdded.createFilter( fromBlock=from_block, toBlock='latest') eventlist = myfilter.get_all_entries() document_id = eventlist[-1]['args']['id'] return document_id, ipfs_hash, transaction_hash else: return None, None, None