Bunkr is a command line tool for secure storage and dynamic access management of sensitive or private data. Bunkr users store their private data across a decentralized network of remote machines using state of the art cryptographic techniques (Shamir Secret Sharing, Secure Multi Party Computation) that make sure the data is maximally resistant to either theft or loss. Data stored in Bunkr is accessible only to the exact devices specified by the user(s), and permissions can be granted and revoked dynamically. Even the remote machines that collectively store and serve data to Bunkr users have no way of individually knowing the underlying data they process. Passwords, API Keys, Cryptographic Keys and more can all be handled with previously inconceivable security and convenience thanks to Bunkr.
This repository is a pre-release beta version of Bunkr. We highly recommend keeping back ups of any important data you store on the beta platform. This is the first open public testing of our cli and the majority of the code is not yet open source. We are providing free and unlimited use of our state of the art distributed secrets management platform, but the binary is offered as is, with no guarantees.
If you think you have found any bugs or security leaks please open an issue here on github or contact us at [email protected].
- Installation and Setup
- Bunkr CLI Cheatsheet
- Basic Secret Storage
- Share Secret Across Devices
- Bunkr Groups
- Bunkr CLI Configuration
- Bunkr CLI Documentation
Set up your free Bunkr Beta account in seconds. Follow the instructions to Install
the CLI and Sign In
your device:
The Bunkr CLI Beta binary file can be downloaded from this repository's releases. To use the binary from the command-line, make sure to place it somewhere on your PATH
(e.g. /usr/local/bin
).
OSX Installation:
$ wget https://github.com/off-the-grid-inc/bunkr/releases/download/1.0.0/bunkr-osx -O /usr/local/bin/bunkr
$ chmod +x /usr/local/bin/bunkr
$ bunkr -version
Version: 1.0.0
Linux Installation:
$ wget https://github.com/off-the-grid-inc/bunkr/releases/download/1.0.0/bunkr-linux -O /usr/local/bin/bunkr
$ chmod +x /usr/local/bin/bunkr
$ bunkr -version
Version: 1.0.0
Before you can store bunkr secrets on a new device you must "sign in" the device and verify your email. It is a two step process:
- Sign in with an email address (
signin
) - Verify the 8 digit confirmation code that was emailed to you (
confirm-signin
)
$ bunkr -I
Choose Bunkr Passphrase:
Re-enter Bunkr Passphrase:
bunkr: >> signin [email protected] myDeviceName;
bunkr: >> confirm-signin [email protected] XXXXXXXX;
bunkr: >> quit;
If you do not see the verification code in your email after a few minutes- it may be in your spam folder
Note that the first time you use bunkr you will be prompted to create a passphrase. Be sure to back it up (to learn more about bunkr password protection see here).
- Running interactive bunkr cli:
$ bunkr -I
- Execute commands in interactive cli:
bunkr: >> access nameOfSecret;
- Execute single shot commands:
$ bunkr access nameOfSecret
- Running bunkr daemon:
$ bunkr -D
$ ./nohup_bunkr.sh
- Stopping daemon:
$ ps aux | grep bunkr
to get the PID and thenkill 25678
$ ./stop_nohup_bunkr.sh
All commands work identically as single shot commands or in the interactive cli. For a comprehensive list of bunkr commands see Bunkr CLI Documentation.
For detailed information on bunkr execution see Bunkr CLI Configuration
$ bunkr -I
Enter Bunkr Passphrase:
bunkr: >>
We recommend running an interactive session when writing secret data to Bunkr when possible. This way no secrets will be unwittingly cached in the command line history.
bunkr: >> new-text-secret API_KEY K9ERzWzhyNB3egjJfBer-PgpvzKDHgYBsdd43;
Secret created
bunkr: >> quit;
$ bunkr access API_KEY
Enter Bunkr Passphrase:
K9ERzWzhyNB3egjJfBer-PgpvzKDHgYBsdd43
You can run the bunkr daemon to keep your bunkr "unlocked" indefinitely. This way you will not be prompted for your password every single time you run a bunkr
command.
$ bunkr -D
Serving RPC handler at /tmp/bunkr_daemon.sock
Now (in another terminal) we see commands execute without the passphrase:
$ bunkr access API_KEY
K9ERzWzhyNB3egjJfBer-PgpvzKDHgYBsdd43
$ bunkr -I
bunkr: >>
To use the bunkr client libraries, or any software built on top of bunkr, the bunkr daemon will need to be running.
Stop the Bunkr Daemon at any time with Ctrl+C
(i.e. kill the daemon process). To run a daemon in the background use the shell scripts nohup_bunkr.sh
and stop_nohup_bunkr.sh
.
Before devices can authorize each other on their secrets, they have to know each other. In this scenario Device A and Device B are both running Bunkr.
Device B:
$ bunkr send-device device-B
This is my device device-B:
raw link (lasts forever): <raw url>
shortened (lasts 24hrs): https://url.bunkr.app/BG6213ghHyDW2iXPTGxUun
It is up to user/s to communicate links via some outside channel (since no private information is being passed, there is nothing insecure about sending this information over normal channels like email or sms). However, only import bunkr information that you are sure is coming from a trusted source (i.e. beware of phishing).
After receiving a link from Device B, Device A imports the device information and begins granting capabilities to Device B.
Device A:
$ bunkr receive-device https://url.bunkr.app/BG6213ghHyDW2iXPTGxUun
New device stored as device-B
$ bunkr grant device-B API_KEY
Capability granted:
raw link (lasts forever): <raw url>
shortened (lasts 24hrs): https://url.bunkr.app/K4StLbTFCQmxxDYDH1tmxf
This link imports the capability information allowing Device B to access the secret.
From Device B:
$ bunkr receive-capability https://url.bunkr.app/K4StLbTFCQmxxDYDH1tmxf
You now have capability on a new secret: API_KEY
$ bunkr access API_KEY
K9ERzWzhyNB3egjJfBer-PgpvzKDHgYBsdd43
Note that while Device A fully controls the secret (can grant or revoke permissions as well as overwrite or delete the secret value), Device B is limited to the access operation.
Device A can revoke Device B's permission to access the secret at any time.
From Device A:
$ bunkr revoke device-B API_KEY
Capability revoked
From Device B:
$ bunkr access API_KEY
SendRequest failed with error: {"Traces":[{"Msg":"Operation failed, [timed out = false] replies expected 7, received 3, failed 3 [errors: [DENIED DENIED DENIED]]" ...}
We introduce a new concept which is the Bunkr Group
. A group is simply a private key stored as a Bunkr Secret, but it will be put to use in a specific way so that we can conveniently define a whole set of capabilities with just one capability. If a device is given permissions on a group it immediately inherits the permissions that the group has on any other secrets.
We will continue using Device A and Device B from the previous tutorial and assume these devices are already aware of each other.
Lets imagine that we are the admin of our company's secrets. First we will write the company secrets to Bunkr.
$ bunkr -I
bunkr: >> new-text-secret companyPassword foobar;
Secret created
bunkr: >> quit;
$ bunkr new-ssh-key companyKey;
Secret created
Notice that when writing a text secret we use interactive mode but since the value of a key is generated internally, this is not necessary with the command new-ssh-key
. Essentially, use the interactive mode if you are passing a secret value as an argument directly. In all other cases, either mode suffices.
In the example below we grant the group "company" permission to sign with "companyKey" and permission to access "companyPassword". Anyone who obtains a "company" signature inherits these capabilities.
$ bunkr new-group company
$ bunkr grant company companyKey
Capability Granted:
...
$ bunkr grant company companyPassword
Capability Granted:
...
Device A:
$ bunkr grant device-B company
Capability Granted:
raw link (lasts forever): <raw url>
shortened (lasts 24hrs): https://url.bunkr.app/K4StLbTFCQmxxDYDH1tmxf
Device B:
$ bunkr receive-capability https://url.bunkr.app/K4StLbTFCQmxxDYDH1tmxf
You now have capability on a new secret: company
$ bunkr list-secrets
Your Secrets:
company (type ECDSA-P256)
company Secrets:
companyPassword (type GENERIC-GF256)
companyKey (type ECDSA-P256)
$ bunkr access companyPassword
foobar
Bunkr CLI has 3 main execution modes
- Daemonized (
-D
) - Interactive session (
-I
) - Single command execution
When running daemonized it will listen to commands from another instance of the tool or any of the available client libraries.
This means that when running single commands or bunkr -I
the cli tool will send the
commands to the already running daemon. In case no daemon is found they will start a session
client that will be killed once the process is finished.
It is easy to start the daemon using the nohup_bunkr.sh
script in the root of this repository.
This script redirects the output to a file (bunkr.out
) that can be used to debug the daemonized process.
Since the process is running in the background we need to manually stop it. Or use the stop_nohup_bunkr.sh
script. The first script dumps the PID of the daemonized process into a bunkr_pid.txt
file which then is read by the stop script. Notice that they only work when the current working directory is the same root as the Bunkr executable.
-bindAddr
=> Address where the client will be listening to incoming messages. By default localhost
-bindPort
=> Port where the client will be listening. By default 8086
-D
=> Run the Bunkr as a daemon
-I
=> Run an interactive Bunkr session
-disablePassword
=> Disable password protection (only for first runs)
-daemonAddr
=> Unix socket address where the daemon will be listening. By default /tmp/bunkr_daemon.sock
-version
=> Show binary version
-debug
=> Activate debug logging
-logFile
=> Path to output log file. By default ./bunkr.log
-identityFilename
=> Set identity file name. By default client_identity
-proposalTimeout
=> Set operations timeout. By default 120000ms
The first time we run the cli it will prompt for a passphrase. You can simply skip through it or use the flag to disable it for no password protection, but it's strongly advised against. The passphrase is used to protect the identity file that will be stored on your device. Each time we run a new instance Bunkr will ask for the passphrase to decrypt the identity file:
$ bunkr -I
Enter Bunkr Passphrase:
Alternately you can generate the identity file for Bunkr yourself (it must be an PEM formatted EC private key on NIST-P256 elliptic curve, either encrypted with the aes-128-cbc algorithm or unencrypted):
$ openssl ecparam -genkey -name prime256v1 | openssl ec -aes-128-cbc -out <path-to-file>
The key you generate must go into your Bunkr Directory: ~/.bunkr
and should be named client_identity
or else the identityFilename execution flag can be used.
If you lose/alter your identity file or forget the passphrase that decrypts it, then that device will not be able to interact with its existing Bunkr secrets. Bunkr cannot help you to recover your identity since that is private information that is only generated and stored locally.
Once we are inside the Bunkr interactive terminal we can use tab
to list the available commands:
bunkr: »
quit help ssh-public-data rename create
write access grant revoke new-text-secret
new-file-secret new-ssh-key import-ssh-key list-secrets send-device
receive-device remove-device list-devices receive-capability secret-info
delete noop-test reset-triples new-group sign-ecdsa
If we start writing a command, then tab
will autocomplete the command.
We can also use the command help;
to show the list of available commands.
We can show the help for any command by invoking it incomplete or malformed:
bunkr: » new-text-secret;
Wrong number of arguments provided.
new-text-secret creates and stores a text secret.
Usage: new-text-secret <secret name> <utf8 text content>
Notice that in the interactive terminal multi-line commands are permitted, so all commands must end with ;
bunkr: >> access <secret name> (optional: <mode>);
The access command recomposes the data securely stored in Bunkr on your local machine. The access command will only succeed if the device requesting access actually has permission to do so.
The optional mode argument specifies how to output the retrieved data. There are three options:
b64
which will return the data as a base64 encoded stringtext
which assumes the data to be text and encodes it as a utf-8 string.file <path to file>
which will write the data as a file (and saved to the path specified).
bunkr: >> confirm-signin <email> <confirmation code>;
Second part of Sign In process for a new device running the CLI (for first part see signin
command).
The 8 digit confirmation code
should have been emailed to you after a proper signin command. email
must be the address where the confirmation code was received.
bunkr: >> create <secret name> <secret type>;
The create command is a low level command (use new-file-secret
/new-text-secret
/etc. instead unless you have a good reason). It creates a new namespace in Bunkr without writing any data to Bunkr yet.
The possible secret types are:
- GENERIC-GF256 (used for text)
- ECDSA-P256 (used for ssh keys)
- ECDSA-SECP256k1 (used for bitcoin keys)
After a create
a coalition expects the next operation to be a write
to fully initialize the secret (see write
command).
bunkr: >> delete <secret name>;
Delete completely removes a secret from Bunkr. This includes all information about permissions, and any secret data. This operation is only permitted for an Admin on the secret.
bunkr: >> grant <device name> <secret name> (optional: <admin flag>);
Grant installs a new capability on a bunkr secret.
When creating a new bunkr secret the device used, and that device alone, has unlimited permissions on the secret. It can access the data, overwrite it, and change or extend the permissions arbitrarily. To grant permission for any other device on a secret you’ll first have to know other devices (see: receive-device).
Here you are granting permission to the specified device on the specified secret. The optional admin
flag specifies whether the permission is admin level or not. Admin level permissions means that this new device will also be able to alter permissions and overwrite the secret. Without the admin flag the permission is access-only (in the case of text secrets) or to signature-only (in the case of ssh keys). Here is an example of granting admin capabilities:
bunkr: >> grant “Home Computer” myBitcoinKey admin;
Now the device “Home Computer” would be able to query, overwrite, and add permissions to the secret myBitcoinKey. If you are not an admin on a secret then a grant operation will fail (you are not authorized to change the permissions, so the operation will not be executed)
Grant operations always output links in case you want to send that capability along to the apropriate devices.
bunkr: >> import-ssh-key <secret name> <path to private key file>;
Import ssh key takes a local PEM ecdsa-p256 private key file and stores the key as a Bunkr secret.
bunkr: >> list-devices;
This command lists all the devices known to your bunkr
bunkr: >> list-groups;
This command lists all the groups known to your bunkr
bunkr: >> list-secrets;
This command lists all the secrets known to your bunkr. The secrets are categorized by which devices or groups have permissions on them e.g.
bunkr: >> list-secrets;
Your Secrets:
myGroup (type ECDSA-P256)
myGroup Secrets:
password (type GENERIC-GF256)
serverKey (type ECDSA-P256)
bunkr: >> new-file-secret <secret name> <path to file>;
This command stores a local file directly into Bunkr (the size limit is currently ~1MB).
bunkr: >> new-group <group name>;
A group is an intermediary Private Key stored in Bunkr which is used to group a number of Bunkr Secrets under a single capability. If you grant a group capability on a secret this means the group key has the capability to query that secret. In this way, if you grant a device capability on the Group Private Key, that device immediately inherits access to all the secrets attached to the group.
Create a group private key:
bunkr: >> new-group myGroup;
Grant a group capability on a secret:
bunkr: >> grant myGroup <secret name>;
Grant a device capability on a group:
bunkr: >> grant <device name> myGroup;
Note that operations to grouped secrets have a computational cost because it means performing Bunkr operations from the device to the group private key (to get signatures on the requests to the actual secret of interest) and then finally executing the Bunkr operation on the secret of interest (which is attached to that group).
bunkr: >> new-ssh-key <secret name>;
Store an ssh key (an ecdsa private key on nist-p256 curve) as a bunkr secret.
bunkr: >> new-text-secret <secret name> <text>;
Store a basic text secret (e.g. a password).
The secret name
is just a reference name for your stored secret data. text
can be any set of utf-8 symbols that you want to store as a secret.
If you want to include spaces in the command arguments then frame them with quotes. For example:
bunkr: >> new-text-secret “Visa Credit Card” “9999 8888 7777 6666 05/23 Jonathan Martin”;
bunkr: >> receive-capability <url> (optional: <custom secret name>);
Import a capability granted to you. If the capability is a group secret all the inherited capabilities will also be automatically imported.
bunkr: >> receive-device <url> (optional: <custom device name>);
Store information about a third party device. This will store the device information locally, under the provided device name (optional parameter). If no name is provided it will default to the name the user gave the device on sending it.
If using an unshortened "raw" link make sure to keep the link with surrounded double quotes or it may have issues being parsed by the cli.
bunkr: >> remove-local <secret name>;
Stop tracking a secret in your bunkr (without removing the secret from bunkr entirely).
Bunkr will not allow you to remove a secret without deleting it if you are the only admin on the secret (to avoid phantom secrets that exist but are irretreivable by any clients)
bunkr: >> rename <old name> <new name>;
Rename a secret or device. All Bunkr secrets and devices have unique file identifiers that never change, but the human readable reference names to secrets are arbitrary and can be changed at any time.
To avoid confusion secrets cannot share the same reference names. When receiving capabilities, if the secrets being received have the same name as existing secrets the operation will fail, and in this case the rename function may becomes necessary (rename the existing secret and then the import will succeed).
bunkr: >> reset-triples <secret name>;
In the (unlikely) case that a bunkr key you use is having trouble executing valid signatures it may be that the Secure Triple Shares which provide randomness to every signature computation are not synched across the nodes (this can happen if a node dies exactly during signature execution).
This operation will flush the existing Triple Shares and resync the nodes so signatures can succeed again. It will only work if all the nodes are back online (since we want to sync them). This command does not alter or reveal anything about the secret values in Bunkr so anyone with capability (admin or not) can execute this.
bunkr: >> revoke <device name> <secret name>;
This command completely removes a device's permissions on a secret. If a device has been compromised, no longer exists, or you simply don’t want it to have capabilities on a secret anymore you can revoke their access. If you are not an admin on the secret then the revoke operation will fail.
bunkr: >> send-device (optional: <custom device name>);
Send your Bunkr Device information.
This will output a link which you can send by any means (sms, email etc.) to any other desired device running Bunkr. The optional argument is to give your device a custom name. For example:
bunkr: >> send-device “John’s Work Computer”;
THe output link comes in two forms a shortened url which is more portable but only lasts 24hrs and a raw url which is long and ugly but lasts forever.
bunkr: >> signin <email> <device name>;
First part of Sign In process for a new device running the CLI (for second part see confirm-signin
command).
A confirmation code will be sent to whatever email
you provide (the code will be verified in confirm-signin
). device name
is just any identifier you choose for your device. ANy device that is signed in under this email address will be considered part of the same Bunkr account.
bunkr: >> write <secret name> <mode> <data>;
The write command is used to write (or overwrite) data to a Bunkr Secret. Execute:
The possible mode and data combinations are:
b64 <base 64 encoded data>
text <utf-8 string>
As an example we can use the create and write commands to store a Bitcoin Private Key in Bunkr:
bunkr: >> create myBitcoinKey ECDSA-SECP256k1;
bunkr: >> write myBitcoinKey b64 3ABFM/7485746283498BFAC/2==;
Note in the above example that when writing ECDSA keys manually (either NIST-P256 or SECP256k1 curves) the content of the secret is expected to be the raw big endian bytes of the secret multiplier of the private key (encoded in base64 or utf-8)