This is a working, throwaway prototype of the core of Vera, an offline authentication protocol incubated by Relaycorp. The purpose of this prototype is to inform the eventual implementation of the protocol by:
- Making sure that there's nothing that would make the implementation impossible or infeasible (e.g., key assumptions that turn out to be wrong, lack of tooling).
- Identifying the libraries, tools and systems that we could leverage in an eventual implementation, as well as the Vera-agnostic components that we'd have to build.
- Getting a sense of the effort required to implement the protocol.
- Understanding the data storage and data processing capacity required by the various components of the system.
Read the wiki to learn more about the outcome of this project, or watch this prototype in action.
- System dependencies: Bash, Java 8+ and OpenSSL.
- A domain with DNSSEC properly configured. Use DNSSEC Analyzer to check that DNSSEC is indeed working properly.
Simply run ./gradlew build
.
We'll use chores.fans
as an example but make sure to use your own domain name.
First, as an Organisation Admin (OA) you have to provision Vera:
-
Generate a private key for your organisation and save it to
org-private-key.der
:./bin/vera-ca key-gen chores.fans org-private-key.der
By default, the Vera TXT time-to-live (TTL) will be set to 90 days. To customise this, use the option
--ttl
; for example,--ttl=60d
for 60 days. -
Go to your DNS hosting provider and create the
TXT
record output above.
The Organisation Member (OM) should first provision their Vera key pair:
- Generate a private key and save it to
member-private-key.der
:openssl genpkey \ -algorithm rsa-pss \ -pkeyopt rsa_keygen_bits:2048 \ -outform DER \ -out member-private-key.der
- Extract the public key and save it to
member-public-key.der
:openssl rsa -inform DER -in member-private-key.der -outform DER -pubout > member-public-key.der
Then the OA can issue a Vera Id to the OM (in the real world this would only be done after authenticating the OM):
-
Retrieve a DNSSEC chain for the
TXT
created above and save it todnssec-chain.der
:./bin/vera-ca get-dnssec-chain chores.fans > dnssec-chain.der
This chain can be cached and reused across Vera Ids, but the more recent the better since chains expire.
-
Generate a certificate for the organisation and save it to
org-certificate.der
:./bin/vera-ca generate-root-ca chores.fans \ <org-private-key.der > org-certificate.der
This too can be cached and reused across Vera Ids, but the more recent the better.
By default, the certificate will be valid for 90 days. To customise this, use the option
--ttl
; for example,--ttl=30d
for 30 days. -
Issue the id to the member (using their public key) and save it to
member-id.der
:./bin/vera-ca issue-member-id \ dnssec-chain.der \ org-private-key.der \ org-certificate.der \ 1.2.3.4.5 \ <member-public-key.der >member-id.der
1.2.3.4.5
denotes the Object Identifier (OID) for the Vera service where this Vera Id is valid. For example,1.3.6.1.4.1.58708.1.0
will probably be the OID for Letro.By default, the OM is assumed to be a bot that will act on behalf of the organisation in the context of the specified service. To issue an id to a user, pass the
--user-name
option; for example--user-name=alice
.By default, the Vera Id will be valid for 30 days. To customise this, use the option
--ttl
; for example,--ttl=7d
for 7 days or--ttl=48h
for 48 hours.
An OM holding a Vera Id can sign a given plaintext as follows:
./bin/vera-app sign \
member-private-key.der \
member-id.der \
<plaintext.txt >signature.der
Where:
plaintext.txt
is the file to be signed. It can be binary.signature.der
will be the resulting Vera signature.
The OM can now share the two files above with anyone that wants to verify the authenticity of plaintext.txt
.
Now anyone can verify the signature as follows:
./bin/vera-app verify signature.der 1.2.3.4.5 <plaintext.txt
Apart from checking that the plaintext was signed with the private key corresponding to the Member Id encapsulated in the signature, the following is also enforced:
- The service id (
1.2.3.4.5
in the example) must match the service id that the OA used to issue the Member Id. - The Member Id must not be older than 30 days. This can be changed with the
--ttl
option; for example,--ttl=24h
for 24 hours.