def testGetAllOtpBlobs(): seed = b'\x92[\xcb\xf4\xee5+\xcf\xd4b*%/\xabw8\xd4d\xa2\xf8\xad\xa7U\x19,\xcfS\x12\xa6l\xba"' dbing.setupDbEnv(DB_DIR_PATH) data = { "id": DID, "blob": "aj;skldfjaoisfjweoijfoiajfo;iasjvjncowrnoiarejnfoj;csacivnfgo;afiewvajdfvo;hnafddjio;ahjfgoia;ehroi;hs" } sigs = [help.signResource(json.dumps(data).encode(), SK)] otpBlob1 = dbing.saveOtpBlob(DID, data, sigs) vk, sk, did, body = help.genDidHistory(seed, signer=0, numSigners=2) data = { "id": did, "blob": "aj;skldfjaoisfjweoijfoiajfo;iasjvjncowrnoiarejnfoj;csacivnfgo;afiewvajdfvo;hnafddjio;ahjfgoia;ehroi;hs" } sigs = [help.signResource(json.dumps(data).encode(), sk)] otpBlob2 = dbing.saveOtpBlob(did, data, sigs) exp_data = {'data': [otpBlob1, otpBlob2]} actual_data = dbing.getAllOtpBlobs() assert actual_data == exp_data
def testPutPreRotationIsEmpty(client): seed = libnacl.randombytes(libnacl.crypto_sign_SEEDBYTES) vk, sk, did, body = h.genDidHistory(seed, signer=0, numSigners=2) headers = {"Signature": 'signer="{0}"'.format(h.signResource(body, sk))} client.simulate_post(HISTORY_BASE_PATH, body=body, headers=headers) # Add did to database body = json.loads(body) body['changed'] = "2000-01-01T00:00:02+00:00" body['signer'] = 1 body['signers'].append("") headers = { "Signature": 'signer="{0}"; rotation="{1}"'.format( h.signResource(json.dumps(body, ensure_ascii=False).encode(), sk), h.signResource(json.dumps(body, ensure_ascii=False).encode(), sk)) } exp_result = { "title": "Validation Error", "description": "signers keys cannot be empty." } verifyRequest(client.simulate_put, "{0}/{1}".format(HISTORY_BASE_PATH, did), body, headers, exp_result=exp_result, exp_status=falcon.HTTP_400)
def testGetAllHistories(): seed = b'\x92[\xcb\xf4\xee5+\xcf\xd4b*%/\xabw8\xd4d\xa2\xf8\xad\xa7U\x19,\xcfS\x12\xa6l\xba"' dbing.setupDbEnv(DB_DIR_PATH) data = { "id": DID, "signer": 0, "signers": [ "NOf6ZghvGNbFc_wr3CC0tKZHz1qWAR4lD5aM-i0zSjw=", "NOf6ZghvGNbFc_wr3CC0tKZHz1qWAR4lD5aM-i0zSjw=" ] } sigs = [help.signResource(json.dumps(data).encode(), SK)] history1 = dbing.saveHistory(DID, data, sigs) vk, sk, did, body = help.genDidHistory(seed, signer=0, numSigners=2) data = json.loads(body) sigs = [help.signResource(json.dumps(data).encode(), sk)] history2 = dbing.saveHistory(did, data, sigs) exp_data = {'data': [history1, history2]} actual_data = dbing.getAllHistories() assert actual_data == exp_data
def testValidPut(client): seed = b'\x92[\xcb\xf4\xee5+\xcf\xd4b*%/\xabw8\xd4d\xa2\xf8\xad\xa7U\x19,\xcfS\x12\xa6l\xba"' # Test Valid rotation event vk, sk, did, body = h.genDidHistory(seed, signer=0, numSigners=2) headers = { "Signature": 'signer="{0}"; rotation="{1}"'.format(h.signResource(body, sk), h.signResource(body, sk)) } client.simulate_post(HISTORY_BASE_PATH, body=body, headers=headers) # Add did to database body = json.loads(body) body['changed'] = "2000-01-01T00:00:01+00:00" body['signer'] = 1 body['signers'].append(body['signers'][0]) headers = { "Signature": 'signer="{0}"; rotation="{1}"'.format( h.signResource( json.dumps(body, ensure_ascii=False).encode('utf-8'), sk), h.signResource( json.dumps(body, ensure_ascii=False).encode('utf-8'), sk)) } exp_result = { "history": { "id": "did:dad:iy67FstqFl_a5e-sni6yAWoj60-1E2RtzmMGjrjHaSY=", "changed": "2000-01-01T00:00:01+00:00", "signer": 1, "signers": [ "iy67FstqFl_a5e-sni6yAWoj60-1E2RtzmMGjrjHaSY=", "iy67FstqFl_a5e-sni6yAWoj60-1E2RtzmMGjrjHaSY=", "iy67FstqFl_a5e-sni6yAWoj60-1E2RtzmMGjrjHaSY=" ] }, "signatures": { "signer": "bu-HIoIp2ZtBqsZtURP_q6rm8WPuDQGtN6maXbDHZbVHJ-QfGpwvXkE-fmi7XymvQJnS9tZXFQ5MPos5u09HDw==", "rotation": "bu-HIoIp2ZtBqsZtURP_q6rm8WPuDQGtN6maXbDHZbVHJ-QfGpwvXkE-fmi7XymvQJnS9tZXFQ5MPos5u09HDw==" } } verifyRequest(client.simulate_put, "{0}/{1}".format(HISTORY_BASE_PATH, did), body, headers, exp_result=exp_result, exp_status=falcon.HTTP_200)
def testDeleteHistory(): seed = b'\x92[\xcb\xf4\xee5+\xcf\xd4b*%/\xabw8\xd4d\xa2\xf8\xad\xa7U\x19,\xcfS\x12\xa6l\xba"' vk, sk, did, body = help.genDidHistory(seed, signer=0, numSigners=2) data = json.loads(body) sigs = [help.signResource(json.dumps(data).encode(), sk)] dbing.saveHistory(did, data, sigs) status = dbing.deleteHistory(did) assert status is True assert dbing.getHistory(did) is None
def testValidDelete(client): seed = b'\x92[\xcb\xf4\xee5+\xcf\xd4b*%/\xabw8\xd4d\xa2\xf8\xad\xa7U\x19,\xcfS\x12\xa6l\xba"' vk, sk, did, body = h.genDidHistory(seed, signer=0, numSigners=2) url = "{0}/{1}".format(HISTORY_BASE_PATH, did) signature = h.signResource(body, sk) headers = {"Signature": 'signer="{0}"'.format(signature)} client.simulate_post(HISTORY_BASE_PATH, body=body, headers=headers) # Add did to database data = json.dumps({"id": did}, ensure_ascii=False).encode() headers = {"Signature": 'signer="{0}"'.format(h.signResource(data, sk))} response = client.simulate_delete(url, body=data, headers=headers) resp_content = json.loads(response.content) assert response.status == falcon.HTTP_200 assert resp_content["deleted"]["history"] == json.loads(body) assert resp_content["deleted"]["signatures"]["signer"] == signature
def testPostPreRotationIsEmpty(client): seed = libnacl.randombytes(libnacl.crypto_sign_SEEDBYTES) vk, sk, did, body = h.genDidHistory(seed, signer=0, numSigners=2) body = json.loads(body) body['signers'][1] = "" body = json.dumps(body, ensure_ascii=False, separators=(",", ":")).encode() headers = {"Signature": 'signer="{0}"'.format(h.signResource(body, sk))} response = client.simulate_post(HISTORY_BASE_PATH, body=body, headers=headers) # Add did to database exp_result = { "title": "Validation Error", "description": "signers keys cannot be empty." } assert response.status == falcon.HTTP_400 assert json.loads(response.content) == exp_result
def testPutValidation(client): url = "{0}/{1}".format(HISTORY_BASE_PATH, DID) seed = b'\x03\xa7w\xa6\x8c\xf3-&\xbf)\xdf\tk\xb5l\xc0-ry\x9bq\xecC\xbd\x1e\xe7\xdd\xe8\xad\x80\x95\x89' # Test that did resource already exists vk, sk, did, body = h.genDidHistory(seed, signer=1) exp_result = {"title": "404 Not Found"} headers = { "Signature": 'signer="{0}"; rotation="{1}"'.format(h.signResource(body, sk), h.signResource(body, sk)) } verifyRequest(client.simulate_put, "{0}/{1}".format(HISTORY_BASE_PATH, did), json.loads(body), headers, exp_result=exp_result, exp_status=falcon.HTTP_404) # Run basic validation tests basicValidation(client.simulate_put, url, putData) # Test that signers field has three keys body = deepcopy(putData) del body['signers'][3] del body['signers'][2] exp_result = { "title": "Validation Error", "description": "PUT endpoint is for rotation events. Must contain at least the original key, a current signing" " key, and a pre-rotated key." } verifyRequest(client.simulate_put, url, body, exp_result=exp_result, exp_status=falcon.HTTP_400) # Test that signers field has three keys body = deepcopy(putData) body['signers'] = [] exp_result = { "title": "Validation Error", "description": "PUT endpoint is for rotation events. Must contain at least the original key, a current signing" " key, and a pre-rotated key." } verifyRequest(client.simulate_put, url, body, exp_result=exp_result, exp_status=falcon.HTTP_400) # Test that signers field has three keys body = deepcopy(putData) body['signer'] = 0 body['signers'] = [ "NOf6ZghvGNbFc_wr3CC0tKZHz1qWAR4lD5aM-i0zSjw=", "NOf6ZghvGNbFc_wr3CC0tKZHz1qWAR4lD5aM-i0zSjw=" ] verifyRequest(client.simulate_post, HISTORY_BASE_PATH, body, exp_status=falcon.HTTP_201) body = deepcopy(putData) body['changed'] = "2000-01-01T00:00:01+00:00" body['signers'] = [ "NOf6ZghvGNbFc_wr3CC0tKZHz1qWAR4lD5aM-i0zSjw=", "NOf6ZghvGNbFc_wr3CC0tKZHz1qWAR4lD5aM-i0zSjw=", "NOf6ZghvGNbFc_wr3CC0tKZHz1qWAR4lD5aM-i0zSjw=" ] verifyRequest(client.simulate_put, url, body, exp_status=falcon.HTTP_200) # Test that signer field is a valid index into signers field body = deepcopy(putData) body['signer'] = 4 exp_result = { "title": "Validation Error", "description": "\"signer\" cannot reference the first or last key in the \"signers\" field on PUT requests." } verifyRequest(client.simulate_put, url, body, exp_result=exp_result, exp_status=falcon.HTTP_400) # Test that signer is not 0 body = deepcopy(putData) body['signer'] = 0 exp_result = { "title": "Validation Error", "description": "\"signer\" cannot reference the first or last key in the \"signers\" field on PUT requests." } verifyRequest(client.simulate_put, url, body, exp_result=exp_result, exp_status=falcon.HTTP_400) # Test that signers field has a pre-rotated key body = deepcopy(putData) body['signer'] = 3 exp_result = { "title": "Validation Error", "description": "Missing pre rotated key in the signers field." } verifyRequest(client.simulate_put, url, body, exp_result=exp_result, exp_status=falcon.HTTP_400) # Test that the url has a did in it body = deepcopy(putData) exp_result = { "title": "Validation Error", "description": "DID value missing from url." } verifyRequest(client.simulate_put, HISTORY_BASE_PATH, body, exp_result=exp_result, exp_status=falcon.HTTP_400) # Test that changed field is greater than previous date vk, sk, did, body = h.genDidHistory(seed, signer=0, numSigners=4) headers = { "Signature": 'signer="{0}"; rotation="{1}"'.format(h.signResource(body, sk), h.signResource(body, sk)) } client.simulate_post(HISTORY_BASE_PATH, body=body, headers=headers) # Add did to database body = json.loads(body) body['signer'] = 1 headers = { "Signature": 'signer="{0}"; rotation="{1}"'.format( h.signResource( json.dumps(body, ensure_ascii=False).encode('utf-8'), sk), h.signResource( json.dumps(body, ensure_ascii=False).encode('utf-8'), sk)) } exp_result = { "title": "Validation Error", "description": "\"changed\" field not later than previous update." } verifyRequest(client.simulate_put, "{0}/{1}".format(HISTORY_BASE_PATH, did), body, headers, exp_result=exp_result, exp_status=falcon.HTTP_400) # Test that signers field length hasn't changed body['changed'] = "2000-01-01T00:00:01+00:00" headers = { "Signature": 'signer="{0}"; rotation="{1}"'.format( h.signResource( json.dumps(body, ensure_ascii=False).encode('utf-8'), sk), h.signResource( json.dumps(body, ensure_ascii=False).encode('utf-8'), sk)) } exp_result = { "title": "Validation Error", "description": "signers field is missing keys." } verifyRequest(client.simulate_put, "{0}/{1}".format(HISTORY_BASE_PATH, did), body, headers, exp_result=exp_result, exp_status=falcon.HTTP_400) del body['signers'][3] headers = { "Signature": 'signer="{0}"; rotation="{1}"'.format( h.signResource( json.dumps(body, ensure_ascii=False).encode('utf-8'), sk), h.signResource( json.dumps(body, ensure_ascii=False).encode('utf-8'), sk)) } exp_result = { "title": "Validation Error", "description": "signers field is missing keys." } verifyRequest(client.simulate_put, "{0}/{1}".format(HISTORY_BASE_PATH, did), body, headers, exp_result=exp_result, exp_status=falcon.HTTP_400) # Test that previously verified keys have not been changed body['signers'].append("Xq5YqaL6L48pf0fu7IUhL0JRaU2_RxFP0AL43wYn148=") body['signers'].append("Xq5YqaL6L48pf0fu7IUhL0JRaU2_RxFP0AL43wYn148=") headers = { "Signature": 'signer="{0}"; rotation="{1}"'.format( h.signResource( json.dumps(body, ensure_ascii=False).encode('utf-8'), sk), h.signResource( json.dumps(body, ensure_ascii=False).encode('utf-8'), sk)) } exp_result = { "title": "Validation Error", "description": "signers field missing previously verified keys." } verifyRequest(client.simulate_put, "{0}/{1}".format(HISTORY_BASE_PATH, did), body, headers, exp_result=exp_result, exp_status=falcon.HTTP_400) # test that signer field is updated from previous requests seed = libnacl.randombytes(libnacl.crypto_sign_SEEDBYTES) vk, sk, did, body = h.genDidHistory(seed, signer=0, numSigners=2) vk = h.keyToKey64u(vk) headers = { "Signature": 'signer="{0}"; rotation="{1}"'.format(h.signResource(body, sk), h.signResource(body, sk)) } # send inception event client.simulate_post(HISTORY_BASE_PATH, body=body, headers=headers) # Add did to database # rotate once body = json.loads(body) body['changed'] = "2000-01-01T00:00:01+00:00" body['signer'] = 1 body['signers'].append(vk) headers = { "Signature": 'signer="{0}"; rotation="{1}"'.format( h.signResource(json.dumps(body, ensure_ascii=False).encode(), sk), h.signResource(json.dumps(body, ensure_ascii=False).encode(), sk)) } verifyRequest(client.simulate_put, "{0}/{1}".format(HISTORY_BASE_PATH, did), body, headers, exp_status=falcon.HTTP_200) # send updated history with new public key but unchanged signer field body['changed'] = "2000-01-01T00:00:02+00:00" body['signer'] = 1 body['signers'].append(vk) headers = { "Signature": 'signer="{0}"; rotation="{1}"'.format( h.signResource(json.dumps(body, ensure_ascii=False).encode(), sk), h.signResource(json.dumps(body, ensure_ascii=False).encode(), sk)) } exp_result = { "title": "Validation Error", "description": "signer field must be one greater than previous." } verifyRequest(client.simulate_put, "{0}/{1}".format(HISTORY_BASE_PATH, did), body, headers, exp_result=exp_result, exp_status=falcon.HTTP_400)
def testKeyRevocation(client): seed = b'\x92[\xcb\xf4\xee5+\xcf\xd4b*%/\xabw8\xd4d\xa2\xf8\xad\xa7U\x19,\xcfS\x12\xa6l\xba"' # Test Valid rotation event vk, sk, did, body = h.genDidHistory(seed, signer=0, numSigners=2) vk = h.keyToKey64u(vk) headers = { "Signature": 'signer="{0}"; rotation="{1}"'.format(h.signResource(body, sk), h.signResource(body, sk)) } client.simulate_post(HISTORY_BASE_PATH, body=body, headers=headers) # Add did to database # revoke key body = json.loads(body) body['changed'] = "2000-01-01T00:00:01+00:00" body['signer'] = 2 body['signers'].append(None) signature = h.signResource( json.dumps(body, ensure_ascii=False).encode('utf-8'), sk) headers = { "Signature": 'signer="{0}"; rotation="{1}"'.format(signature, signature) } exp_result = { "history": { "id": "did:dad:iy67FstqFl_a5e-sni6yAWoj60-1E2RtzmMGjrjHaSY=", "changed": "2000-01-01T00:00:01+00:00", "signer": 2, "signers": [ "iy67FstqFl_a5e-sni6yAWoj60-1E2RtzmMGjrjHaSY=", "iy67FstqFl_a5e-sni6yAWoj60-1E2RtzmMGjrjHaSY=", None ] }, "signatures": { "signer": signature, "rotation": signature } } verifyRequest(client.simulate_put, "{0}/{1}".format(HISTORY_BASE_PATH, did), body, headers, exp_result=exp_result, exp_status=falcon.HTTP_200) # try to rotate away from the null key body['changed'] = "2000-01-01T00:00:02+00:00" body['signer'] = 3 body['signers'].append(vk) body['signers'].append(vk) headers = { "Signature": 'signer="{0}"; rotation="{1}"'.format( h.signResource(json.dumps(body, ensure_ascii=False).encode(), sk), h.signResource(json.dumps(body, ensure_ascii=False).encode(), sk)) } exp_result = { "title": "Validation Error", "description": "signers keys cannot be null unless revoking a key." } verifyRequest(client.simulate_put, "{0}/{1}".format(HISTORY_BASE_PATH, did), body, headers, exp_result=exp_result, exp_status=falcon.HTTP_400) # try to rotate away from the null key body['changed'] = "2000-01-01T00:00:02+00:00" body['signer'] = 4 body['signers'].append(vk) body['signers'].append(vk) body['signers'].append(vk) headers = { "Signature": 'signer="{0}"; rotation="{1}"'.format( h.signResource(json.dumps(body, ensure_ascii=False).encode(), sk), h.signResource(json.dumps(body, ensure_ascii=False).encode(), sk)) } exp_result = { "title": "Validation Error", "description": "signers keys cannot be null unless revoking a key." } verifyRequest(client.simulate_put, "{0}/{1}".format(HISTORY_BASE_PATH, did), body, headers, exp_result=exp_result, exp_status=falcon.HTTP_400) # try to rotate into the null key prematurely seed = libnacl.randombytes(libnacl.crypto_sign_SEEDBYTES) vk, sk, did, body = h.genDidHistory(seed, signer=0, numSigners=2) headers = { "Signature": 'signer="{0}"; rotation="{1}"'.format(h.signResource(body, sk), h.signResource(body, sk)) } client.simulate_post(HISTORY_BASE_PATH, body=body, headers=headers) # Add did to database body = json.loads(body) body['changed'] = "2000-01-01T00:00:02+00:00" body['signer'] = 4 body['signers'].append(None) body['signers'].append(None) body['signers'].append(None) headers = { "Signature": 'signer="{0}"; rotation="{1}"'.format( h.signResource(json.dumps(body, ensure_ascii=False).encode(), sk), h.signResource(json.dumps(body, ensure_ascii=False).encode(), sk)) } exp_result = { "title": "Validation Error", "description": "signers keys cannot be null unless revoking a key." } verifyRequest(client.simulate_put, "{0}/{1}".format(HISTORY_BASE_PATH, did), body, headers, exp_result=exp_result, exp_status=falcon.HTTP_400)
def testDeleteValidation(client): seed = b'\x92[\xcb\xf4\xee5+\xcf\xd4b*%/\xabw8\xd4d\xa2\xf8\xad\xa7U\x19,\xcfS\x12\xa6l\xba"' vk, sk, did, body = h.genDidHistory(seed, signer=0, numSigners=2) # Test missing url did headers = {"Signature": 'signer="{0}"'.format(h.signResource(body, sk))} client.simulate_post(HISTORY_BASE_PATH, body=body, headers=headers) # Add did to database data = json.dumps({"id": did}, ensure_ascii=False).encode() headers = {"Signature": 'signer="{0}"'.format(h.signResource(data, sk))} response = client.simulate_delete(HISTORY_BASE_PATH, body=data, headers=headers) resp_content = json.loads(response.content) assert response.status == falcon.HTTP_400 assert resp_content["title"] == "Validation Error" assert resp_content["description"] == "DID value missing from url." # Test no Signature header url = "{0}/{1}".format(HISTORY_BASE_PATH, did) headers = {"Signature": 'signer="{0}"'.format(h.signResource(body, sk))} client.simulate_post(HISTORY_BASE_PATH, body=body, headers=headers) # Add did to database data = json.dumps({"id": did}, ensure_ascii=False).encode() response = client.simulate_delete(url, body=data) resp_content = json.loads(response.content) assert response.status == falcon.HTTP_400 assert resp_content["title"] == "Missing header value" assert resp_content["description"] == "The Signature header is required." # Test empty Signature header headers = {"Signature": 'signer="{0}"'.format(h.signResource(body, sk))} client.simulate_post(HISTORY_BASE_PATH, body=body, headers=headers) # Add did to database data = json.dumps({"id": did}, ensure_ascii=False).encode() headers = {"Signature": ""} response = client.simulate_delete(url, body=data, headers=headers) resp_content = json.loads(response.content) assert response.status == falcon.HTTP_401 assert resp_content["title"] == "Authorization Error" assert resp_content["description"] == "Empty Signature header." # Test bad Signature header tag headers = {"Signature": 'signer="{0}"'.format(h.signResource(body, sk))} client.simulate_post(HISTORY_BASE_PATH, body=body, headers=headers) # Add did to database data = json.dumps({"id": did}, ensure_ascii=False).encode() headers = {"Signature": 'rotation="{0}"'.format(h.signResource(data, sk))} response = client.simulate_delete(url, body=data, headers=headers) resp_content = json.loads(response.content) assert response.status == falcon.HTTP_401 assert resp_content["title"] == "Authorization Error" assert resp_content[ "description"] == 'Signature header missing signature for "signer".' # Test mismatched dids url = "{0}/{1}".format(HISTORY_BASE_PATH, DID) headers = {"Signature": 'signer="{0}"'.format(h.signResource(body, sk))} client.simulate_post(HISTORY_BASE_PATH, body=body, headers=headers) # Add did to database data = json.dumps({"id": did}, ensure_ascii=False).encode() headers = {"Signature": 'signer="{0}"'.format(h.signResource(data, sk))} response = client.simulate_delete(url, body=data, headers=headers) resp_content = json.loads(response.content) assert response.status == falcon.HTTP_400 assert resp_content["title"] == "Validation Error" assert resp_content["description"] == "Url did must match id field did." # Test delete non existent resource url = "{0}/{1}".format(HISTORY_BASE_PATH, did) data = json.dumps({"id": did}, ensure_ascii=False).encode() headers = {"Signature": 'signer="{0}"'.format(h.signResource(data, sk))} client.simulate_delete(url, body=data, headers=headers) response = client.simulate_delete(url, body=data, headers=headers) assert response.status == falcon.HTTP_404 # Test invalid signature url = "{0}/{1}".format(HISTORY_BASE_PATH, did) headers = {"Signature": 'signer="{0}"'.format(h.signResource(body, sk))} client.simulate_post(HISTORY_BASE_PATH, body=body, headers=headers) # Add did to database data = json.dumps({"id": did}, ensure_ascii=False).encode() headers = {"Signature": 'signer="{0}"'.format(h.signResource(data, SK))} response = client.simulate_delete(url, body=data, headers=headers) resp_content = json.loads(response.content) print(resp_content) assert response.status == falcon.HTTP_401 assert resp_content["title"] == "Authorization Error" assert resp_content[ "description"] == "Could not validate the request signature for signer field. Unverifiable signature."