Home

Awesome

Uport android signer

CircleCI

This library is used to create and manage keys for uport account. It supports creating keyPairs from seed phrases, protecting these keys with authenticated encryption (android lock-screen / fingerprint), signing ETH transactions and signing uPort specific JWTs.

Where available, keys and seeds created by this lib will be protected by encryption backed by ARM Trusted Execution Environment (TEE).

Note: The curve used for ETH signing is not backed by the TEE, therefore private keys exist in memory while in use but are encrypted with TEE keys at rest.

FAQ and helpdesk support

Import

in your main build.gradle:


allprojects {
    repositories {
        //...
        maven { url 'https://jitpack.io' }
    }
}

in your app build.gradle:

uport_signer_version = "0.4.0"
dependencies {
    //...
    implementation "com.github.uport-project:uport-android-signer:$uport_signer_version"
}

Usage

Key protection

When creating or importing keys/seeds, you must specify the protection KeyProtection.Level desired. When using such a key/seed, the protection level is enforced based on the option used during creation.

Keys and seeds are always protected with hardware backed keys, where available. This option is for choosing user authentication requirements.

The options are:

Important notes:

Create a seed:

This creates a seed that is used for future key derivation and signing: The seed is representable by a bip39 mnemonic phrase.

UportHDSigner().createHDSeed(activity, KeyProtection.Level.SIMPLE, { err, seedHandle, publicKey ->
    if (err != null) {
        //handle error
        println(err)
    } else {
        //seed has been created and is accessible using seedHandle 
        // * the handle is `seedHandle` - save this so you can use the seed later
        // * `publicKey` - a publicKey in base64 encoding, 
        // corresponding to the private key derived using the `UPORT_ROOT_DERIVATION_PATH` "m/7696500'/0'/0'/0'"
        println(publcKey)
    } 
})

You can also import bip39 mnemonic phrases:


//bip39 mnemonic phrase:
val phrase = "vessel ladder alter ... glass valve picture"

UportHDSigner().importHDSeed(activity, KeyProtection.Level.SIMPLE, phrase, { err, seedHandle, publicKey ->

    if (err != null) {
        //handle error
    } else {
        assertEquals("0x794a...e96ac8", seedHandle)
        //seed has been imported and 
        // * the handle is `seedHandle`
        // * the corresponding publicKey in base64 is `publicKey`
    }
         
})

Signing

You can use this lib to calculate ETH transaction signatures. Building and encoding transaction objects into ByteArrays is not in the scope of this lib.

You can sign transactions using keys derived from a previously imported seed. To refer to that seed you must use the seedHandle from the seed creation/import callback Based on the KeyProtection.Level used during seed import/creation, a prompt may be shown to the user on the lock-screen / fingerprint dialog.


val seedHandle = "0x123..." //seedHandle received when creating/importing the seed

//bip32 key derivation
val derivationPath = "m/44'/60'/0'/0/0"

//the transaction payload, base64 encoded
val txPayloadB64 = Base64.encodeToString( transaction.rlpEncode(), Base64.DEFAULT )

//gets shown to the user on fingerprint dialog or on lockscreen, based on `KeyProtection.Level` used
val prompt = "Unlock your key to sign this transaction"

UportHDSigner().signTransaction(activity, seedHandle, derivationPath, txPayloadB64, prompt, { err, sigData ->
    if (err != null) {
        //handle error
    } else {
        //use sigData r,s,v components
        println(sigData)
    }
})

Note: The requirement to encode the transaction payload as a base64 string is subject to change in future releases

uPort specific JWTs

This lib can also produce signatures for uPort specific JWTs: The method signature is the same but the signing method differs.

Also, do note that in the current version of this API, data is a Base64 encoded string (not a serialized JSON) - this is subject to change in future releases


val prompt = "Unlock your key to sign this credential"

UportHDSigner().signJwtBundle(activity, seedHandle, derivationPath, data, prompt, { err, sigData ->
    if (err != null) {
        //process the error
    } else {
        //use sigData r,s,v components
        println(sigData)
    }
})

Changelog

0.4.0

0.3.6

0.3.5

0.3.4

0.3.3

0.3.2

0.3.1

0.3.0

v0.2.x

v0.2.2

v0.2.1

v0.2.0

v0.1.1

v0.0.1