Check Device Compatibility

Note that Rivetz is currently available only on the Android platform. The minimum OS requirement is Android 7.0, API level 24 ("Nougat").

If your device is a Samsung, you also will need to ensure you have the required security policy. Navigate to the Settings → About screen on your device, and verify that the Security Enhancements for Android ("SE For Android Status") is enforcing a policy from July 17th, 2015 or later.

Rivetz Application Installation Overview

It is strongly suggested that if you haven’t done so already, you familiarize yourself with the Rivetz objectives and technology by reading the Rivetz Technology Overview document on this website.

In order to develop an application using the Rivetz Toolkit, you must first download and install the Rivetz Application. Because the Rivetz App (the Rivet) is currently in beta, all accounts accessing them through the Google Play Store must be whitelisted by Rivetz. Subsequently, those accounts must opt in to the beta testing program for each Rivetz app.

The installation steps below will walk you through how to join the beta programs, download the Rivetz apps, activate the developer tools and load the TA.

  1. Send a list of developers - including name, beta Rivetz product to test, and an email address that is registered with the Google Play store - to support@rivetz.com.

  2. In a web browser that is logged into the Google Play Store account with the email address submitted above, copy and paste the following link and select “Become a Tester” to opt-in to the beta release. Due to the interaction of the beta Play Store, we recommend completing this step on a computer rather than mobile device. https://play.google.com/apps/testing/com.rivetz.adapter

  3. Open the Google Play Store app on a TEE-compatible mobile device and ensure that it is logged in to the email account submitted in step 1.

  4. Search for “Rivetz” in the Play Store.

  5. Download, then open, the “Rivetz” app.

  6. Swipe sideways to “Activate Developer Tools” and tap that option.

  7. Tap “Accept” to install the Rivetz Trusted Application (TA).

Once complete there will be two "Riveted Apps", RivetzNet and Developer Tools. You can tap these to see the keys they contain.

Connect your device to the Android development environment. Please refer to http://developer.android.com/tools/device.html. Once your device is visible from the desktop using adb devices you’re all set. For example.

user@host:~$ adb devices
List of devices attached
LGH345c670f255	device

Add Rivetz to your Project

Assuming you are using Android Studio, point to our code repository and declare a dependency to the RivetzJ Library and Rivetz Android Bridge. For example, in the module build.gradle file, add the following lines

maven {
    url "https://s3-us-west-2.amazonaws.com/maven.rivetz.com/releases"
}
dependencies {
    compile 'com.rivetz:rivetz-bridge:0.10.3@aar'
    compile 'com.rivetz:rivetz-lib:0.10.3'
}

The example above shows how to specify the current release version in the build file; in this case, the current release is 0.10.3.

Create a Rivet

Import the Rivetz bridge library by adding com.rivetz.bridge to your class file.

import com.rivetz.bridge.Rivet;

Next, instantiate the Rivet class. Note that this is an asynchronous task as it establishes a binding to the Rivet. You can provide a callback if you want to be notified when the binding is ready. In this example, we initialize the Rivet using the Service Provider ID DEVELOPER_SPID. This is a predefined service provider ID that can be used for experimentation.

Rivet rivet = new Rivet(getApplicationContext(), Rivet.DEVELOPER_SPID);

You will want to get your own service provider ID when you are ready to begin developing your Rivetz application(s) for deployment. See Next Steps at the end of this document for more information on acquiring a service provider ID.

Pairing

The trust relationship between a device and service provider is established through a process called pairing, in which the Rivetz Network Registrar signs the service provider data and delivers it to the requesting device. Encrypted keys and other state information is stored on the device in a Rivetz maintained Service Provider Record. When a device pairs with a service provider, the service providers' public key is exchanged with the device public key. The SP private key is stored by the service itself, and the device private key is stored within the TEE.

The pairing process involves user consent, and thus a UI element, but it only needs to happen once per device. You can test rivet.isPaired() or call pair() with the silent flag to just test if pairing is already done.

rivet.pair(getApplicationContext());

Basic Operations

The following sections describe some of the most common operations performed using the Rivetz Toolkit. These operations are demonstrated in a simple application described in the next section.

Create a Key

In general, you call the Rivet to create a key:

rivet.createKey(KeyType.ECDSA_DFLT, "mykey");

This method is used to generate a riveted key. In order to understand the example calling sequences described below that use this key, there are a couple of parameter types requiring further explanation;

1. KeyRecord - Rather than a byte array of a single key (or keys), this structure is returned on successful creation of a key. The fields of the KeyRecord structure are

  • java.lang.String name

  • byte[] privateKey

  • byte[] publicKey

  • java.util.ArrayList<KeyUsageRule> rules

  • RivetBase.KeyType type

Note that in the case of a symmetric key, the key value is returned in the privateKey field. The Utilities class provides methods that transform keys to and from the KeyRecord format. For example, the method getPublicKeyBytes() doesn’t return the raw byte array, but calls the utility method to condense the key and return that. Other methods of interest in the Utilities class include rivetSigToComponents() which returns the keys in the r,s format expected by external cryptographic service providers, such as Bouncy Castle.

2. KeyUsageRule - This parameter is used to specify the usage policy for the key being created. Keys can be restrained by key usage rules that enforce the conditions under which they are used. Some examples of key usage rules include:

SP_IDENTITY_KEY

Specifies a key as an SP’s Identity key. An SP record must have an SP identity key and there can only be one SP identity key. The identity key must also contain a LIFETIME_PERMANENT Usage Rule.

REQUIRE_TUI_CONFIRM

Specifies the key will not be applied to an operation unless user authorization is with a Trusted User Interface confirmation.

DEV_IDENTITY_KEY

Indicates that this is a device identity key which, if present, will be used to sign responses. Each Service Provider will only have a single device identity key.

REQUIRE_SIGNED_REQUEST

Specifies a valid signature must be provided to authorize use of this key.

PRIV_KEY_EXPORTABLE

Specifies the private key can be exported. If a key is not exportable it cannot be backed up or cloned to another device.

LIFETIME_PERMANENT

Specifies the key is permanent and can’t be deleted from the service provider record. To remove the key the entire Service Provider Record must be deleted from the Rivet.

REQUIRE_TUI_PIN

Specifies the key will not be applied to an operation unless authorization is confirmed using a PINPAD entry

The parameters used in the various method constructors for the createKey call are:

  • Keytype: indicates the type of the key. Rivetz supports the creation and use of both symmetric and asymmetric keys. The default key types for these are:

    • Symmetric: AES_256_GM

    • Asymmetric: ECDSA_NIST256

  • Name: provides a name for the key which is used for reference in future calls.

  • UsageRules: Zero or more usage rules that will be applied to the riveted key.

KeyRecord createKey(RivetBase.KeyType type);

KeyRecord createKey(RivetBase.KeyType type, String name, RivetBase.UsageRule... rules);

On Return:

  • A new KeyRecord is returned on success.

  • A null return indicates an error

Having created (or retrieved from secure storage) one or more keys, we can now look at some of the typical operations that can be performed on them. Here are some example APIs demonstrating 5 of the most commonly used functions;

1. ENCRYPT Some Data

Encryption is supported for both symmetric and asymmetric keys. The calling sequence of the encrypt method differs, depending on which key type is used.

Parameters:

  • keyName: name of the key to use for encryption

  • iv: AES ENCRYPTION ONLY - Initialization Vector

  • payload: a byte array of the data to be encrypted

byte[] encrypt(String keyName, byte[] payload);

byte[] encrypt(String keyName, byte[] iv, byte[] payload);

On Return:

  • A byte array containing the encrypted data is returned on success

    • ECIES encryption will be in envelope format

    • AES-GCM encryption will be formatted as a 16 byte IV + data + 16 byte HMAC/tag

    • A null return indicates an error

2. DECRYPT Some Data

Perform a simple decryption on a small amount of data.

Parameters:

  • keyName: name of the key to use for decryption

  • payload: a byte array of the data to be decrypted

    • ECIES encryption will be in envelope format

    • AES-GCM encryption will be formatted as a 16 byte IV + data + 16 byte HMAC/tag

byte[] decrypt(String keyName, byte[] payload);

On Return:

  • A byte array containing the decrypted data is returned on success

    • A null return indicates an error

3. SIGN Some Data

Returns input data signed with the named key.

Parameters:

  • keyName: name of the key to use for signing

  • payload: a byte array or string containing the data to be signed

byte[] sign(String keyName, byte[] payload);

byte[] sign(String keyName, String payload);

On Return:

  • A byte array containing the signed data is returned on success

    • A null return indicates an error

4. VERIFY a Signature

Verify a signature with the named key.

Parameters:

  • keyName: name of the key to use for verification

  • signature: Signature to be verified

  • payload: a byte array or string containing the data to be verified

return true if

Boolean verify(String keyName, byte[] signature, byte[] payload);

Boolean verify(String keyName, byte[] signature, String payload);

On Return:

  • True, if signature has been successfully verified

    • False otherwise.

5. Hash some data

Apply a hashing function to the given payload.

Parameters:

  • hashAlgo: Hashing algorithm to be used.

  • payload: a byte array or string containing the data to be hashed

byte[] hash(String hashAlgo, byte[] payload);

byte[] hash(String hashAlgo, String payload);

On Return:

  • A byte array containing the hash is returned on success

    • A null return indicates an error

Next Steps

Run the Sample Application

We have developed a sample application which includes the source for creating and using a Rivet with a very simple UI. The full project is available on GitHub: https://github.com/rivetz/SampleApp. The application is ready to import into Android Studio 3.

We strongly recommend you download, build and run this application as a way to verify that your development environment and test mobile device are configured properly.

The sample application will not run on an Android Virtual Device. The test device must be physically connected. It must also have the Rivetz application installed and running as described at the beginning of this document, prior to executing the sample application.

Create a Service Provider ID

In the above example we used the simplest interface and a Test Service Provider. For a production deployment, you will want to create your own Service Provider ID and sign instructions sent to the Rivet.

A Service Provider represents legal and cryptographic ownership over keys created and applied using the SPID. In order to protect access to your Riveted keys you can require that all instructions using those keys be signed by your Service Provider Key. The Service Provider Key is established prior to registering with Rivetz and supplied in the registration process.

To create your key on a Linux system you can use ssh-keygen.

$ ssh-keygen -t ecdsa
Generating public/private ecdsa key pair.
Enter file in which to save the key (/home/user/.ssh/id_ecdsa): rivetz-key
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in rivetz-key.
Your public key has been saved in rivetz-key.pub.

Navigate to http://rivetz.com/docs/registration.html and fill out the registration form. You will need to provide company information and upload the key created in the last step.

You will also be asked to provide a logo for your app. This is an important visual identifier that is signed by Rivetz so it can’t be spoofed, particularly when used with Trusted User Interface. The logo should be a 256x256 pixel PNG file. Ideally the logo should be simple so the file size is kept to a minimum. White (#FFFFFF) is the default background color.

As a result of registration you will be emailed a newly minted Service Provider ID. Congratulations!

Sign your instructions

In the above example, the calls to Rivetz are made directly within the client Android App. Generally, you will want to create Rivet instructions on your server so you can sign them first. A key can be configured to only accept signed instructions.

The Rivetz Code Library is used by your server code to construct an instruction. This instruction is a byte array, which is signed and then passed down to the device. The instruction is invoked using rivet.execute(). A result record is returned, signed by the service provider unique device identity key, if present.

See the SDK Reference for full documentation of the Rivetz API classes.