Notarizing a file and verifying its authenticity
In this tutorial, you will take a file, calculate the hash value of its contents by using a cryptographic hash function, send this value to the notary service for writing it to the Ethereum blockchain (notarize the file), and then pass this value to the service again to check if the service has indeed written it to the blockchain (verify the file authenticity).
Step-by-step procedure
Start the Python shell and configure its session.
The following variables should be available now:
>>> base_url # the base URL of the API 'https://eu2-cloud.acronis.com/api/notary/v2' >>> auth # the 'Authorization' header value with the access token {'Authorization': 'Bearer 8770b34b74f9e4d9424eff50c38182bb4ae7f5596582ae61900b1b6a23e3ec58'}
Define a variable named
file_path
, and then assign the path to your file to this variable:>>> file_path = '<path to file>'
Important
If the path contains backslashes, remember to escape them with an additional backslash.
Open the file for reading in binary mode:
>>> file = open(file_path, 'rb')
Calculate the hash value of the file contents by using the SHA-256 algorithm:
>>> sha256 = hashlib.sha256() >>> chunk = file.read(128 * sha256.block_size) >>> while chunk: ... sha256.update(chunk) ... chunk = file.read(128 * sha256.block_size) >>> file_hash = sha256.hexdigest() >>> file_hash '2c7c3d5f244f1a40069a32224215e0cf9b42485c99d80f357d76f006359c7a18'
Close the file:
>>> file.close()
Fetch the file name from the file path:
>>> file_name = os.path.basename(file_path)
Define a variable named
metadata
, and then assign an object with the following JSON parameters to this variable:>>> metadata = { ... 'GUID': file_name, ... 'eTag': file_hash ... }
You may specify other information about the file in additional keys. Refer to the API reference for more information.
Warning
Do not specify sensitive information in this object because the entire object contents will be available in the notarization certificate that will be created for the object when you send it to the notary service.
Key names are case-sensitive. For example, if you do not write
eTag
as shown in the snippet above, the notary service will calculate the SHA-256 hash value of the entire object contents and write this value to the blockchain. Thus, an attempt to later verify the file’s authenticity will fail.
Convert the
metadata
object to a JSON text:>>> metadata = json.dumps(metadata, indent=4)
Send a POST request with the JSON text to the
/meta
endpoint:>>> response = requests.post( ... f'{base_url}/meta', ... headers={'Content-Type': 'application/json', **auth}, ... data=metadata, ... )
Check the status code of the response:
>>> response.status_code 200
The 200 code means the following:
The object has been successfully sent to the notary service.
The service has received the object.
The service has queued the hash value specified in the object’s
eTag
key for writing it to the blockchain.Note
The writing of queued hash values is triggered every hour and the time when the writing is completed depends on the Ethereum network status.
Important
It is not possible to delete a value from the queue and cancel the notarization.
The service has created a notarization certificate for the object.
A different code means that an error has occurred. For more information, refer to “Status and error codes”.
Convert the JSON text that the response body contains to an object, and then fetch the ID of the created notarization certificate:
>>> certificate_id = response.json()['certificate_id'] >>> certificate_id '7605f73deaee7b071a570b3ac20cc9fe7a3abf337be7c86c55c28af9d3d8435c'
Check the notarization status by sending a GET request to the
/certificates/{certificate_id}
endpoint. We recommend waiting about an hour before checking because the notarization process may take a long time:>>> response = requests.get(f'{base_url}/certificates/{certificate_id}', headers=auth)
Check the status code of the response:
>>> response.status_code 200
Status code 200 means that the request was successful.
A different status code means that an error has occurred. For the details, refer to “Status and error codes”.
Also, the response body contains the notarization certificate object formatted as a JSON text. When converted to an object, it will look as follows:
>>> pprint.pprint(response.json()) {'contract': '0xd10e3Be2bc8f959Bc8C41CF65F60dE721cF89ADF', 'eventtime': '2019-11-11T13:07:07.004366Z', 'id': '7605f73deaee7b071a570b3ac20cc9fe7a3abf337be7c86c55c28af9d3d8435c', 'merkle_proof': '[{"left":"88c20ca21dd6fa9e0a64c7e981a012812bbca152010195cd4296d959cfa35f1e"}]', 'merkle_root': '6d05fb9f0c2cff4942987661a44e71f0f554d435ce494dd3e7a21df6c6ba963c', 'notarized_location': 'beta-baas', 'object': {'eTag': '2c7c3d5f244f1a40069a32224215e0cf9b42485c99d80f357d76f006359c7a18', 'key': '<file name>', 'sequencer': 'DEF04BD0C5114542F8', 'size': 446}, 'blockchain': 'eth', 'qr_code': 'data:image/png;base64,iVBORw0KGgoAAAANSUh...', 'sender': '0x201354729f8d0f8b64e9a0c353c672c6a66b3857', 'signee_details': {'tenant_name': 'John Doe'}, 'timestamp': 1573572432, 'txid': '0x6494a098f6487ebbcfa85b7cbe64c1f9f077f03866477b67be64320ea109fa73', 'version': '3'}
Once the notarization is complete, verify the file’s authenticity by sending a POST request with the JSON text to the
/meta/verify
endpoint:>>> response = requests.post( ... f'{base_url}/meta/verify', ... headers={'Content-Type': 'application/json', **auth}, ... data=metadata, ... )
Note
We do not recalculate the hash value because we assume that the file contents have not been changed.
Check the status code of the response:
>>> response.status_code 200
Status code 200 means that the request was successful.
A different status code means that an error has occurred. For the details, refer to “Status and error codes”.
Also, the response body contains the
certificates
key containing an array of notarization certificate objects formatted as a JSON text. When converted to an object, it will look as follows:>>> pprint.pprint(response.json()) {'certificates': [{'id': '7605f73deaee7b071a570b3ac20cc9fe7a3abf337be7c86c55c28af9d3d8435c', ..., 'version': '3'}]}
The array in the certificates key of the response’s JSON object should contain the notarization certificate with the same ID and contents as in the previous step.