arrayio / array-io-keychain

A highly secure standalone application for signing transactions and generating key pairs.
https://keychain.array.io/
MIT License
26 stars 3 forks source link

A keychain functionality proposal #2

Open vladiuz1 opened 6 years ago

vladiuz1 commented 6 years ago

 AIP: - Title: Keychain application Status: Draft Type: Client Author: @vladiuz1 (vs@array.io) Created: 2018-03-20

Abstract

A keychain is a multiformart multiplatform secure keystore application. At the moment a developer of multichain functionality is using different formats of storing keys. bitcoind, geth keystore, electrum's keyfiles all use the same public/private key standards but store them in different file formats, and have different interfaces to interract with keys.

Motivation

Most blockchain project's wallets have duplicate functionality, and many differ only in the hash function signing transactions and generating addresses. However functionally it is the same public/private key cryptography with repeating functionality. create/sign/get public key.

Array.io client application can eventually be used for design of multi-blockchain applications. For example direct atomic swaps, lightning network applications, multi-blockchain wallets, etc. A keystorage that can keep and sign a key from any blockchain is extremely helpful. Security of keeping the key in a dapps environment is of utmost importance. Hence keychain environment must be separated from client application.

Summary

An Array.io Keychain is an application that creates and manages private/public key pairs and signs transactions. It is a standalone application that can be run in commandline or gui mode.

screenshot-2018-3-21 array io - array-io-keychain-list moqups 1

The most important functionality of the keychain is ability to sign transactions. Most blockchain projects today are using the same public/private key algorithm - secp256k1. And one key may be used for many different blockchains. The keychain must be modular application that knows how to sign trsansactions of multiple blockchains. It must understand multiple raw transaction formats eventually.

Another important command of the keychain is generation key pairs. As part of generation flow, a user must be prompted to write down a 12 word mnemonic seed.

And since the generation of keys is the main feature, we must also allow adding functionality to recognize multiple wallet formats, so keys could be conveniently imported into keychain from other client formats. E.g. electrum, ethereum, bitcoind's wallet.dat, etc...

screen shot 2018-03-21 at 03 19 43

Even though this is a standalone application it will rarely be launched by a user in either GUI or command line mode. It will most often be used by dapps server or array-io-node to sign transaction in a pipeline mode. Where the output of node or server is piped to the input of array-io-keychain.

Specification

Synopsis

arrayio-keychain command [options] [arguments]

List of commands:

Command Arguments Options Result Description Issue
list key list list all master keys in keychain
sign key_file, raw_tx -hd_path, -in_format, -out_format signature sing a raw transaction
public_key key_file -hd_path, -out_format public_key get public key for the wallet #18
create key_file -cruve, -cipher success create a new keypair
seed key_file -language seed view BIP39 mnemonic seed for the key
restore key_file -curve, -cipher, -language success restore key pair from a BIP39 seed
remove key_file -delete success remove a key from keychain
export key_file, filename -format success export key to an alternative format
import filename, key_file -format, -cipher success import key from another format
list-ciphers <list> list available ciphers you can use to encrypt your wallet
list-curves <list> list availble curves
help command display help

Modes of operation

Example usage:

Commandline:

$ array-io-keychain sign —keyname=test0 --chainid=1 --in-format=hex --out-format=hex 871689d060721b5cec5a010080841e00000000000011130065cd1d0000000000000000
< 1f3314428fe189b2a5424b874dc4ef25c8df65c9d13504ede32a2b2c4c8ada5041161705139e81b981c5c31336d719cf40bd5619a24d890c89b1772944c3fffcc4

Pipeline:

$ array-io-keychain —keyname=test0
> sign --chainid=1 --in-format=hex --out-format=hex 871689d060721b5cec5a010080841e00000000000011130065cd1d0000000000000000
< 1f3314428fe189b2a5424b874dc4ef25c8df65c9d13504ede32a2b2c4c8ada5041161705139e81b981c5c31336d719cf40bd5619a24d890c89b1772944c3fffcc4
vladiuz1 commented 6 years ago

during our brainstorm sessions it was suggested to make a pipeline interface for signing/locking/unlocking wallet. but i am thinking websocket daemon maybe a better choice, since it allows us to integrate into browsers, and it may become a standard for in-browser use for wallets like mew. and be used well beyond array.io

vladiuz1 commented 6 years ago

Useful links:

tsrman commented 6 years ago

Bitshares uses a different (not BIP39 compatible) mechanism for generate private keys from seeds:

Keys in Graphene are derived from a seed brain key which is a string of
16 words out of a predefined dictionary with 49744 words. It is a
simple single-chain key derivation scheme that is not compatible with
BIP44 but easy to use.
Given the brain key, a private key is derived as:
  privkey = SHA256(SHA512(brainkey + " " + sequence))
Incrementing the sequence number yields a new key that can be
regenerated given the brain key.
vladiuz1 commented 6 years ago

@tsrman we don't really care about that, we can create our own scheme.

https://en.bitcoin.it/wiki/Elliptic_Curve_Digital_Signature_Algorithm (used in bitshares and other crypto):

private key: A secret number, known only to the person that generated it. A private key is essentially a randomly generated number. In Bitcoin, someone with the private key that corresponds to funds on the public ledger can spend the funds. In Bitcoin, a private key is a single unsigned 256 bit integer (32 bytes).

The private key is an ECDSA secp256k1, and is a random number. This secp256k1 has to be a number between 1 and >115792089237316195423570985008687907852837564279074904382605163141518161494336 (or in hexadecimal, between 1 and FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFE BAAEDCE6 AF48A03B BFD25E8C D0364140).

Derivation scheme from seed to private key is not that important as long as it is deterministic and produces a valid private key. Every blockchain uses own seed->key derivation scheme, its not important, we can use any of them, bitshares for example. Or we can support few different schemes, so we can restore keys from other client applications. It is not so much protocol dependant feature, it is more implementation dependant. Even in bitcoin, different wallets use different scheme. Electrum seed won't work with bitcoind scheme.

privkey = SHA256(SHA512(brainkey + " " + sequence))

It is a nice feature being able to derive few keys from one seed. We can use same scheme if we want. So that when restoring the private key we also offer to provide a sequence number. But in the end, the private key that we restored is still same old secp256k1 private key that we need to keep.

The problem with this scheme is that you can't determine the seed without brain key. So if you restored your private key 1 from your key and saved it in keychain, you can't get the brain key from this key. So, i don't think its a good scheme. Or we need to keep the brainkey itself in the keychain.

vladiuz1 commented 6 years ago

Ok i think we need 1 more operation, called public_key and also we need an option to both public_key and sign operations. and this option is: derive = "m/44'/60'/0'/0"

obviously the public_key operation will show the public key of the key pair,

but the option derive is something interesting, it will give the public key that corresponds to HD wallet or sign with derived private key