Last modified: Mon Nov 04 2019 16:15:12 GMT+0000 (Coordinated Universal Time)

Direct Connect

Let's say we have two companies: 0xSUPPLIER (e.g. hotel) and 0xAGGREGATOR (an OTA or TMS). 0xAGGREGATOR wants to connect to 0xSUPPLIER in order to include their inventory into aggregator's customer offerings.

0xSUPPLIER published their API URL in ORG.JSON, so 0xAGGREGATOR can start making requests to that API. But 0xSUPPLIER wants to talk only to partners he can trust, so 0xAGGREGATOR has to provide authentication information with each request.

1. Adding Associated Keys

An important part of the trust clue system is its undeniability. ORG.IDs must use digital signatures in order to prove that a message is coming from the right person and that it was not tampered with on the way. For this to work, you need an identity that can produce such signatures, and that requires a private key (0xORG is a smart contract and doesn't have a private key). That is why every 0xORG can have many associatedKeys in the form of public key fingerprints. Every associated key can then produce signed messages that are associated with the ORG.ID if the key is present in 0xORG at the time of message reception.

1.1. Generating Key Pairs

Info

Currently Winding Tree works with keys in Ethereum format only. We will be adding other formats eventually.

We are heavily borrowing from an excellent article by Vincent Kobel. You will find links to prebuilt keccak-256sum binary there as well. If this doesn't work for you, you can use any other way of creating a private-public key pair for Ethereum.

An Ethereum private key is a random positive integer in the range [1,secp256k1n−1]. We can easily generate one using OpenSSL.

> openssl ecparam -name secp256k1 -genkey -noout -out key.pem

You should see a key.pem file create with your private key in PEM format in it.

-----BEGIN EC PRIVATE KEY-----
MHQCAQEEIGYrAkjWe6nwB+Z15l4AF024DzFy8Ad+sxVIJgHHI6ZmoAcGBSuBBAAK
oUQDQgAEUTKWQe1j0pcHVNONpFd413ZPywVwdcU8ELR4J7iYZUiqznFvuINdZVGk
+HdzqkmUIY+wFe62Y2IwNcSHYmQK4g==
-----END EC PRIVATE KEY-----

Let's derive its public key and display it in hex format.

> openssl ec -in key.pem -text -noout
read EC key
Private-Key: (256 bit)
priv:
    66:2b:02:48:d6:7b:a9:f0:07:e6:75:e6:5e:00:17:
    4d:b8:0f:31:72:f0:07:7e:b3:15:48:26:01:c7:23:
    a6:66
pub:
    04:51:32:96:41:ed:63:d2:97:07:54:d3:8d:a4:57:
    78:d7:76:4f:cb:05:70:75:c5:3c:10:b4:78:27:b8:
    98:65:48:aa:ce:71:6f:b8:83:5d:65:51:a4:f8:77:
    73:aa:49:94:21:8f:b0:15:ee:b6:63:62:30:35:c4:
    87:62:64:0a:e2
ASN1 OID: secp256k1

The public key must be 65 bytes long with the 0x04 prefix. Let's save it in a file pub.key, stripping off the leading 0x04:

> openssl ec -in key.pem -text -noout | grep pub -A 5 | tail -n +2 | tr -d '\n[:space:]:' | sed 's/^04//' | awk '{print $1""}' > pub.key

An Ethereum address (public key fingerprint) is the last 20 bytes of keccak-256 hash of the public key. Let's calculate it:

> cat pub.key | keccak-256sum -x -l | tr -d ' -' | tail -c 41
fc69560bfad47d0f104deb4656f20777d7745475

Now you can add 0xfc69560bfad47d0f104deb4656f20777d7745475 to the list of associatedKeys.

1.2. Adding Generated Keys to ORG.ID

If you have completed the ORG.ID Onboarding Guide, you can just

> cd orgid-tutorial
> npm run truffle

Info

The truffle console has to be run with an account that created the 0xORG smart contract (we call it the ORG.ID "owner"). It is the only account that can add associated keys.

We will add an address by simply invoking a transaction on our 0xORG instance. An associated key can be the 0xORG owner, but for security reasons the associated keys should be standalone single-purpose accounts.

truffle(ropsten)> orgid = await Organization.at('0xE61d952f077EfF0C022cC0FEC841059DA2289526')
undefined
truffle(ropsten)> orgid.addAssociatedKey('0xfc69560bfad47d0f104deb4656f20777d7745475')
{ tx: '0xae54c8358eb05a8a477832230cb6891239200a58ce99071b04b78d7ef5cab835',
  ...
}
truffle(ropsten)> orgid.getAssociatedKeys()
[ '0x0000000000000000000000000000000000000000',
  '0xfc69560bfad47d0f104deb4656f20777d7745475' ]

Now the 0xfc69560bfad47d0f104deb4656f20777d7745475 key can represent the 0xE61d952f077EfF0C022cC0FEC841059DA2289526 ORG.ID.

2. Message Signing

Info

This is intentionally vague as there are many options how the message signing can work. We offer a few examples, but better schemes might exist.

Now when your organization has private/public keys, it can start to sign any messages including guarantees, e-mails or http requests. It can also be used to get an access to a restricted API. The principle is always something like this:

  1. 0xAGGREGATOR registers an associated key to their ORG.ID as above.
  2. 0xAGGREGATOR signs all the outgoing requests with a private key tied to its public counterpart in the associatedKeys.
  3. 0xSUPPLIER extracts the signer from the incoming request and the signature. The request has to contain 0xAGGREGATOR's ORG.ID.
  4. 0xSUPPLIER checks that the signature was not tampered with.
  5. 0xSUPPLIER checks that the signer is an associatedKey of 0xAGGREGATOR.
  6. 0xSUPPLIER checks that the trust clues of 0xAGGREGATOR are OK for him.
  7. 0xSUPPLIER accepts the request and produces a response signed with an associatedKey of 0xSUPPLIER.
  8. (Optional) 0xAGGREGATOR extracts the signer from the incoming response and the signature.
  9. (Optional) 0xAGGREGATOR checks that the signer is an associatedKey of 0xSUPPLIER.

There are many ways how to transport a signed message over the wire, there's even a few years old draft for HTTP. Nonetheless, the common thing for any message exchange scheme in our case is, that it uses ORG.IDs and associated keys as decentrally stored identities that author the signed messages. This might eliminate centralized points of traditional authentication systems such as Private Certification Authorities, single purpose user-password pairs or centrally managed access tokens.

In combination with the trust clues design, it can open up many new ways of interconnecting the APIs.

Examples

Message Signing and Verification process