Ninki Wallet is delivered as a Chrome App via Google's Chrome Store. This enables a web type interface but without the insecurity of delivering code via a webpage.
Chrome Apps are not extensions, they do not run in the Chrome browser. They are a sandboxed application that runs in it's own instance of Chrome.
Chrome Apps disable certain features of Javascript that are responsbile for most XSS injection attacks and require a Content Security Policy to explicitly authorise access to external domains.
A summary of the disabled functions can be found here
The application itself is delivered via a signed delivery system and will not install unless the signature is correct. Updates can be pushed to users by a person in ownership of the Google account the app is registered under. In this respect it is very similar to the model for delivering iPhone and Android phone apps.
| Asset | Owner | Method |
|---|---|---|
| Online Key | User | Chrome Storage (Encrypted) + Encrypted backup |
| Offline Key | User | Offline Storage eg. written down, kept in safe, safety deposit |
| Countersign Key | Service | Encrypted Stored in database |
| PGP Key | User/Service | Encrypted by the user / stored in databse |
The following describes the process of the server authenticating the user and issuance of a session token.
When the user creates an account a secret is shared between the server and the client. The client encrypts a randomly generated secret using their password as an input to a pbkdf along with a unique salt. The encryption scheme is AES 256 Mode: CBC, Padding: No Padding
The encrypted secret is stored on the server. When the user attempts to login to the server the entered password is derived to a passphrase using a unique salt. The client requests the encrypted secret from the server, the server returns the encrypted secret and the client decrypts using the passphrase. The result is sent back to the server and the server compares the secret with value originally shared.
Once the user has proven that they can decrypt the secret, and therefore know the password, the server challenges them to provide a one time 2 factor authentication code. If this is validated succesfully the user is authenticated and a session token is issued.
The encrypted packet containing the users api key and public key information is sent to the client and decrypted using the passphrase. The client maintains a connection with the server polling every 10 seconds, if there is no communication for over 60 seconds, the session is timed out and the user will have to authenticate to establish a session.
All keys are deterministic as defined in BIP32
The online and offline keys are derived from a random 32 byte array using window.crypto.getRandomValues. The data is then hashed using SHA256 and used as a seed to an HD key space.
Node m/0/0 is used for receiving address generation, node m/0/1 is used for change address generation and m/0/1000 is used for allocating nodes to contacts on your network.
Bitcoin addresses are difficult to exchange and require either copying and pasting or qr code scanning. This promotes address re-use which in turn can make funds vunerable to R value attacks and are detrimental to financial privacy.
The PGP scheme described here removes the need for exchanging bitcoin addresses everytime two users transact, and promotes zero address re-use. After the PGP validation is complete it becomes less effort to generate new addreses on behalf of each other then it does to find the previous address used for that user and copy/paste it into a transaction.
The server can facilitate the initial exchange, but should not be trusted, and so an out of band validation is required. Note: this should also happen over a secure channel, however this is up to the user as we have, by definition no control over the choice of channel.
Finally, the addresses are generated by the client and not handed off from the server, removing the threat of the server handing off bad addresses. The server acts purely as a verification service, a cross check between what the client has generated and what the server expected.
This provides an extra layer of security against malware on the client replacing the address before the transaction is signed and sent to our server.
The wallet supports exchanging HD public key nodes with other users on the service. The purpose of this is to allow users who regularly transact with each other, to generate addresses on each other's behalf. So instead of you sending me an address, I simply derive one from the next node on the public key chain you assinged and sent to me.
This presents a problem of a MIM attack when exchanging nodes. How do we know the server which is facilitating the exchange is not compromised?
To solve this we use PGP with the keys generated on the client at the time of account creation and stored in an encrypted packet, using the user's passphrase.
An out-of-band fingerprint exchange must occur between the two users in order to validate that the service or another actor has not compromised the integrity of the key exchange. We present this fingerprint in the form of a BIP39 encoded mnemonic referred to as a 'Ninki Phrase'.
exhaust lumber tone tribe poem glide alpha vendor select morning maze tongue vote rain clock
Whenever Bob needs to generate an address for Alice, he retrieves the packet from the server, decrypts it with his PGP private key and derives a new address for Alice. The reverse process happens and Alice and Bob now have connected wallets.
Ninki Wallet is a 2 of 3 multi-signature wallet where 2 keys are controlled by the user and one key is controlled by Ninki. The user would typically store one encrypted key online, on a usb drive or a cloud storage service. This is referred to as the Online key and should always be stored using encryption. The other user key would typically be stored offline, perhaps in paper format in a safe deposit box or safe. The Countersigning key is secured by Ninki on the server.
This configuration allows Ninki to act as a counter-signing service, but without the ability to move the funds alone, and provides the user with the ability to recover their funds in any event.
When the user initiates a transaction, it is built locally on the client, signed with the online key and then sent to the server for counter signing. The server validates the transaction and then countersigns and broadcasts it to the Bitcoin network.
Before countersigning the following items are checked on the server:
Sending beyond a transaction limit, requires two factor authentication, and is not possible from the mobile app