page.title

Demo ( Source code )

Sample reviews
52fb5c23c2b5a44ca4bd61c05393b5dbb80a7279ab966187d8d6b83870634fa9
N1hwkg7V9PPpqDdHnLFWyS3SrXGHSzwSF3
or Connect with Traity to import your own reviews from different providers

How does it work?

As explained in our Decentralized Identity and Reputation draft, the 'cards' have to be signed to verify their authenticity. By signing the content we can confirm who generated them and we can also assure that the content was not tampered.

Imagine we have this review (please refer to the review specification to see its format):

[{
  "name": "external_api_seller",
  "text": "Wonderful buyer, very fast payment.",
  "provider": "ebay",
  "created_at": 1424858051,
  "version": "1.0",
  "ratings": [
    {
      "score": 87.23,
      "version": "0.2",
      "provider": "traity"
    }
  ]
}]

In order to sign the document, we need at least one private key. Using the example private key e2a4188f9adc09c0582c9740741117e0ada281c56e53164c9d7ef1fe882ccd95 we would generate the following document:

[
  {
    "review": {
      "name": "external_api_seller",
      "text": "Wonderful buyer, very fast payment.",
      "provider": "ebay",
      "created_at": 1424858051,
      "version": "1.0",
      "ratings": [
        {
          "score": 87.5,
          "version": "0.2",
          "provider": "traity"
        }
      ]
    },
    "signatures": [
      {
        "address": "MwesPafEAcvxD2cPjMAFMVfpT26Lwkjfpv",
        "signature": "Hx4pyYBluWIyo5bvXk92cm1Rg1MJAmWtZcPuokOmvsMo7N8gkR8xKX13cdjSS9WcL9VRLsB0spyMDvf/koRBmj0="
      }
    ]
  }
]

The signature is generated with the ECDSA algorithm as used in Bitcoin, using the SHA2 digest of the document as the payload.

Having this signature, we could easily detect if the text was modified or not:

Bitcoin.network = :namecoin
payload = Digest::SHA2.hexdigest(JSON.parse(review).to_json)
puts Bitcoin.verify_message(address, signature, payload)

Now, because this document has sensitive data that we might not want to store in the blockchain, we will generate a hash for the list of reviews and that is what we will store: 9bd4eda087f1dd60448c808bac0e713e2acf322ee97a02a15dfbcc8fc7145b9f

Eventually, we also would like to confirm if the stored value was really generated by an authorized user, so we will add a signature in the stored document in order to be able to verify it using the public address, having this final value:

{
  "hash":"9bd4eda087f1dd60448c808bac0e713e2acf322ee97a02a15dfbcc8fc7145b9f",
  "signature":"IINRlcFmrUcMmeBrKsM2Syz3IyAZznTuujx/HXB978JvzFjn+hHzt4M6+bFpx9ZrqGFrujF9zTGshDX5LME4Sw8="
}

Generating the identifier

As we mentioned before, we are using Namecoin's blockchain which can be a used as a key-value data store. From now, we will refer to the key as the identifier in order to prevent confussions with the private/public key term.

The chosen identifier should accomplish the following points:

In order to accomplish the first point, we will use the user Namecoin address as the first part of the identifier. So, by knowing the address which is a public information and does not reveal any private data, we could find the list of hashes for a specific user: /namecoind name_filter "MwesPafEAcvxD2cPjMAFMVfpT26Lwkjfpv_*"

Because the identifier should be idempotent, we should know in advance how it will be calculated. This leads to the problem that someone could generate this identifier in our behalf. This can be solved if this identifier is generated using certain information that is only known by us like the private key we used to sign the reviews. So, the second part of the identifier is generated in this way: <address> + "_" + hash160("reviews_" + <provider> + "_" + <private_key>) which generates the following identifier for the provider 'airbnb' and: MwesPafEAcvxD2cPjMAFMVfpT26Lwkjfpv_67046ab4b5629a1e33993d5570a31cb3075f3a5