Timestamping Workflow

Overview

The generation of a tamper-proof timestamp takes place in several phases.

First, the SHA-256 hash of the file that is submitted for timestamping is calculated by you, inside the browser or by using the OriginStamp Dashboard.

OriginStamp only submits this cryptographic hash of a file for mainly two reasons: As a file that is submitted to OriginStamp can contain confidential information, it is mandatory that the confidentiality of the submitted file is not compromised.

The SHA-256 hash function is beneficial regarding this requirement, since it is a mathematical one-way function. From a given hash, however, it is due to high computational complexity infeasible to determine a matching input file. As a result, the fingerprint of a file does not grow with the size of that file. This allows to generate efficient timestamps even for very large files.

After the hash of a file, i.e. its fingerprint, has been created, it must be embedded in the blockchain. Each hash that should be embedded in the blockchain would naively require a single transaction. Thus, the total hash submission cost would rise linearly with the number of timestamps as explained below. Furthermore, it would artificially increase the load on the network (e.g. Bitcoin) and potentially block other transactions.

To avoid most of this load and to reduce the total cost to be linear with time, the OriginStamp system combines all hashes that are submitted within a fixed period to form a single submission.

Triggered by a scheduler, all hashes that were submitted in such a period and additionally are not yet timestamped are collected and sorted in lexicographical ascending order.

These hashes are used to build a balanced Merkle Tree. This has the advantage over seed files that only a small section is required for verification. The root of the tree (formerly seed hash) is embedded in a blockchain using a transaction. Importantly, any changes to the proof also alters the root hash of the Merkle Tree.

To perform the actual submission, the root hash is directly and without any further modifications embedded into a blockchain.

Calculate SHA-256

To create a timestamp, you must first calculate the SHA-256 hash of your record. There are standard libraries for all programming languages:

Java

public String getSHA256(byte[] input) {
    MessageDigest digest = MessageDigest.getInstance("SHA-256");
    byte[] encodedhash = digest.digest(input);
    return bytesToHex(encodedhash);
}

private static String bytesToHex(byte[] hash) {
    StringBuffer hexString = new StringBuffer();
    for (int i = 0; i < hash.length; i++) {
    String hex = Integer.toHexString(0xff & hash[i]);
    if(hex.length() == 1) hexString.append('0');
        hexString.append(hex);
    }
    return hexString.toString();
}

C#

static string ComputeSha256Hash(string rawData)  
{  
    // Create a SHA256   
    using (SHA256 sha256Hash = SHA256.Create())  
    {  
        // ComputeHash - returns byte array  
        byte[] bytes = sha256Hash.ComputeHash(Encoding.UTF8.GetBytes(rawData));  

        // Convert byte array to a string   
        StringBuilder builder = new StringBuilder();  
        for (int i = 0; i < bytes.Length; i++)  
        {  
            builder.Append(bytes[i].ToString("x2"));  
        }  
        return builder.ToString();  
    }  
}

Python

import hashlib

hashlib.sha256("test").hexdigest()

Submit your hash

Request

POST /v3/timestamp/create

curl -X POST "http://api.originstamp.com/v3/timestamp/create"\
     -H "Authorization: YOUR_API_KEY"\
     -H "Content-Type: application/json"
     -d YOUR_PAYLOAD

Payload

{
  "comment": "test",
  "hash": "2c5d36be542f8f0e7345d77753a5d7ea61a443ba6a9a86bb060332ad56dba38e",
  "notifications": [
    {
      "currency": 0,
      "notification_type": 0,
      "target": "[email protected]"
    },
    {
      "currency": 0,
      "notification_type": 1,
      "target": "https://webhook-notification.url"
    }
  ],
  "url": "string"
}

comment (optional)

You can add a short comment (max. 256 characters) which can be used for indexing and searching (public).

Example

test

hash (required)

Hash in HEX representation. We suggest to use SHA-256. This hash will be aggregated and included into the blockchain.

Example

2c5d36be542f8f0e7345d77753a5d7ea61a443ba6a9a86bb060332ad56dba38e

notifications (optional)

Add a notification/notification list to your submission. Our system will notify the specified target with the timestamp information.

Example

[{
  "currency": 0,
  "notification_type": 0,
  "target": "[email protected]"
}]
currency
  • 0: Bitcoin
  • 1: Ethereum
  • 2: AION
  • 100: Südkurier
notification_type
  • 0: Mail
  • 1: Webhook
target

Mail address or URL to which the notification should be sent.

url (optional)

Preprint URL. Insert the generated UUID here. You can generate an UUID-4 and include it into your document. When submitting the your file, the URL is part of the hash, which finally means it the link to the timestamp is part of the timestamp.

Response

created

If true, this was the first time the hash was submitted to OriginStamp.

Check the timestamp status

Request

GET /v3/timestamp/{hash_string}

curl -X GET "http://api.originstamp.com/v3/timestamp/2c5d36be542f8f0e7345d77753a5d7ea61a443ba6a9a86bb060332ad56dba38e"\
     -H "Authorization: YOUR_API_KEY"

Response

The default timestamp object is returned that contains all necessary timestamp information. OriginStamp submits the hash to more than one blockchain, which is the reason why there is a timestamp data array for each active currency.

{
  "data": {
    "comment": "string",
    "created": false,
    "date_created": 0,
    "hash_string": "string",
    "timestamps": [
      {
        "currency_id": 0,
        "private_key": "string",
        "submit_status": 0,
        "timestamp": 0,
        "transaction": "string"
      }
    ]
  },
  "error_code": 0,
  "error_message": "string"
}
comment

The timestamp's comment, if any.

created

Field is true if it is a novel hash. If the flag is false, the hash was already submitted before.

date_created

The time when your hash was submitted to OriginStamp. The date is returned in milliseconds since 1.1.1970 (unix epoch), timezone: UTC. This is not considered as a tamper-proof timestamp.

hash_string

The hash string that you check for. Redundant with the {hash_string} route parameter.

timestamps

Timestamps that exist for this hash, no matter whether they are tamper-proof yet. Can contain zero (no timestamp yet) to an arbitrary number of items.

currency_id
  • 0: Bitcoin
  • 1: Ethereum
  • 2: AION
  • 100: Südkurier
private_key

The private key represents the top hash in the Merkle Tree. Synonyms: root hash, private key, top hash, seed hash.

submit_status
  • 0: Hash is only submitted to OriginStamp and added to the timestamping queue. It will be timestamped with the next timestamp submission.
  • 1: Hash is submitted to the blockchain network, but not included.
  • 2: Hash is included into the latest block.
  • 3: Hash has a tamper-proof timestamp.
timestamp

The tamper-proof is returned in the following format: [ms] since 1.1.1970 (unix epoch), timezone: UTC. This is the tamper-proof timestamp.

transaction

If available: the transaction ID of the timestamp, e.g. transaction hash in Bitcoin.

Status Changes

Because of the timestamping interval and blockchain network times, we cannot exactly predict when a timestamp is going to be tamper-proof. Instead of polling the API for status updates, you should rather subscribe to status change notifications when submitting the timestamp.

As soon as a timestamp reaches a tamper-proof state, you are automatically notified via email and/or webhook in case you subscribed.