Skip to content

Commit 49a7219

Browse files
authored
Merge pull request #246 from ipfs/fix/keystore
Keystore: bring keystore spec more up to date
2 parents c048c6f + e4fb1ed commit 49a7219

File tree

3 files changed

+116
-121
lines changed

3 files changed

+116
-121
lines changed

KEYSTORE.md

Lines changed: 89 additions & 98 deletions
Original file line numberDiff line numberDiff line change
@@ -2,39 +2,33 @@
22

33
**Authors(s):**
44
- [whyrusleeping](github.com/whyrusleeping)
5+
- [Hector Sanjuan](github.com/hsanjuan)
56

67
* * *
78

89
**Abstract**
910

10-
TODO
11+
This spec provides definitions and operations for the keystore feature in IPFS.
1112

1213
# Table of Contents
1314

1415
TODO
1516

1617
## Goals:
1718

18-
To have a secure, simple and user-friendly way of storing and managing keypairs
19+
To have a secure, simple and user-friendly way of storing and managing keys
1920
for use by ipfs. As well as the ability to share these keys, encrypt, decrypt,
2021
sign and verify data.
2122

2223
## Planned Implementation
23-
### Storage
2424

25-
Keys will be stored in a directory named `keys` under the `$IPFS_PATH`
26-
directory. Each named keypair will be stored across two files, the private key
27-
in `$NAME` and the public key in `$NAME.pub`. They will be encoded in PEM (or
28-
similar) format, and optionally password encrypted. Upon starting the ipfs daemon,
29-
keys will be lazily loaded as needed. If a given key is password protected, the user
30-
should be prompted for the password at the time of loading the key. The `$IPFS_PATH/keys`
31-
directory should be readable only be the owner, with unix permissions of `700`. Keys
32-
in the directory should be readonly, by the owner `400`.
25+
### Key storage
26+
27+
Storage layout and format is defined in the [`REPO_FS`](REPO_FS.md) part of the spec.
3328

3429
### Interface
35-
Several additions and modifications will need to be made to the ipfs toolchain to
36-
accommodate the changes. First, the creation of two subcommands `ipfs key` and
37-
`ipfs crypt`:
30+
31+
#### ipfs key
3832

3933
```
4034
@@ -45,11 +39,11 @@ SUBCOMMANDS:
4539
ipfs key gen - Generates a new named ipfs keypair
4640
ipfs key list - Lists out all local keypairs
4741
ipfs key info <key> - Get information about a given key
48-
ipfs key rm <key> - Delete a given key from your keystore
49-
ipfs key rename <key> <name> - Renames a given key
50-
ipfs key show <key> - Print out a given key
42+
ipfs key rm <key> - Delete a given key from your keystore
43+
ipfs key rename <key> <name> - Renames a given key
44+
ipfs key show <key> - Print out a given key
5145
52-
ipfs key send <key> <peer> - Shares a specified private key with the given peer
46+
ipfs key send <key> <peer> - Shares a specified private key with the given peer
5347
5448
Use 'ipfs key <subcmd> --help' for more information about each command.
5549
@@ -59,9 +53,10 @@ DESCRIPTION:
5953
6054
```
6155

62-
```
56+
#### ipfs crypt
6357

64-
ipfs crypt - Perform cryptographic operations using ipfs keypairs
58+
```
59+
ipfs crypt - Perform cryptographic operations using ipfs keypairs
6560
6661
SUBCOMMANDS:
6762
@@ -72,33 +67,27 @@ SUBCOMMANDS:
7267
7368
DESCRIPTION:
7469
75-
`ipfs crypt` is a command used to perform various cryptographic operations
76-
using ipfs keypairs, including: signing, verifying, encrypting and decrypting.
70+
`ipfs crypt` is a command used to perform various cryptographic operations
71+
using ipfs keypairs, including: signing, verifying, encrypting and decrypting.
7772
```
7873

7974
#### Some subcommands:
8075

81-
##### Key Gen
82-
```
76+
##### ipfs key Gen
8377

84-
ipfs key gen - Generate a new ipfs keypair
8578

86-
OPTIONS:
79+
```
80+
ipfs key gen <name> - Generate a new ipfs keypair
8781
88-
-t, -type string - Specify the type and size of key to generate (i.e. rsa-4096)
89-
-p, -passphrase string - Passphrase for encrypting the private key on disk
90-
-n, -name string - Specify a name for the key
82+
OPTIONS:
83+
-t, -type string - Specify the type and size of key to generate (i.e. rsa)
84+
-s. -size int - Size of the key to generate
85+
-p, -passphrase string - Passphrase for encrypting the private key on disk
9186
9287
DESCRIPTION:
9388
9489
'ipfs key gen' is a command used to generate new keypairs.
95-
If any options are not given, the command will go into interactive mode and prompt
96-
the user for the missing fields.
97-
9890
```
99-
##### Comments:
100-
101-
Similar to ssh's `ssh-keygen` with the `-t` option and interactive prompts.
10291

10392
* * *
10493

@@ -109,18 +98,18 @@ Similar to ssh's `ssh-keygen` with the `-t` option and interactive prompts.
10998
11099
OPTIONS:
111100
112-
-y, -yes bool - Yes to the prompt
101+
-y, -yes bool - Yes to the prompt
113102
114103
DESCRIPTION:
115104
116105
'ipfs key send' is a command used to share keypairs with other trusted users.
117106
118-
It will first look up the peer specified and print out their information and
119-
prompt the user "are you sure? [y/n]" before sending the keypair. The target
120-
peer must be online and dialable in order for the key to be sent.
107+
It will first look up the peer specified and print out their information and
108+
prompt the user "are you sure? [y/n]" before sending the keypair. The target
109+
peer must be online and dialable in order for the key to be sent.
121110
122-
Note: while it is still managed through the keystore, ipfs will prevent you from
123-
sharing your nodes private key with anyone else.
111+
Note: while it is still managed through the keystore, ipfs will prevent you from
112+
sharing your nodes private key with anyone else.
124113
125114
```
126115

@@ -137,19 +126,19 @@ Ensure that the user knows the implications of sending a key.
137126
138127
ARGUMENTS:
139128
140-
data - The filename of the data to be encrypted ("-" for stdin)
129+
data - The filename of the data to be encrypted ("-" for stdin)
141130
142131
OPTIONS:
143132
144-
-k, -key string - The name of the key to use for encryption (default: localkey)
145-
-o, -output string - The name of the output file (default: stdout)
146-
-c, -cipher string - The cipher to use for the operation
147-
-m, -mode string - The block cipher mode to use for the operation
133+
-k, -key string - The name of the key to use for encryption (default: localkey)
134+
-o, -output string - The name of the output file (default: stdout)
135+
-c, -cipher string - The cipher to use for the operation
136+
-m, -mode string - The block cipher mode to use for the operation
148137
149138
DESCRIPTION:
150139
151-
'ipfs crypt encrypt' is a command used to encrypt data so that only holders of a certain
152-
key can read it.
140+
'ipfs crypt encrypt' is a command used to encypt data so that only holders of a certain
141+
key can read it.
153142
154143
```
155144

@@ -165,8 +154,8 @@ We will also need to make additions to support keys in other commands, these cha
165154

166155
- `ipfs add`
167156
- Support for a `-encrypt-key` option, for block encrypting the file being added with the key
168-
- also adds an 'encrypted' node above the root unixfs node
169-
- Support for a `-sign-key` option to attach a signature node above the root unixfs node
157+
- also adds an 'encrypted' node above the root unixfs node
158+
- Support for a `-sign-key` option to attach a signature node above the root unixfs node
170159

171160
- `ipfs block put`
172161
- Support for a `-encrypt-key` option, for encrypting the block before hashing and storing
@@ -175,28 +164,30 @@ We will also need to make additions to support keys in other commands, these cha
175164
- Support for a `-encrypt-key` option, for encrypting the object before hashing and storing
176165

177166
- `ipfs name publish`
178-
- Support for a `-key` option to select which keyspace to publish to
179-
180-
### Code Changes/Additions
181-
An outline of which packages or submodules will be affected.
182-
183-
#### Repo
184-
185-
- add `keystore` concept to repo, load/store keys securely
186-
- needs to understand PEM (or $CHOSEN_FORMAT) encoding
187-
188-
Expected Interface: (very wip)
189-
190-
```
191-
type KeyStore interface {
192-
// Get a key from the cache
193-
GetKey(name string) (ci.PrivKey, error)
194-
195-
// Save a new key into the cache, and write to disk
196-
StoreKey(name string, key ci.PrivKey) error
197-
198-
// LoadKey reads the key from its file on disk, and stores it in the cache
199-
LoadKey(name string, password []byte) error
167+
- Support for a `-key` option to select which keyspace to publish to
168+
169+
### Code changes and additions
170+
171+
This sections outlines code organization around this feature.
172+
173+
#### Keystore package
174+
175+
The fsrepo carries a `keystore` that can be used to load/store keys. The keystore is implemented following this interface:
176+
177+
```go
178+
// Keystore provides a key management interface
179+
type Keystore interface {
180+
// Has returns whether or not a key exist in the Keystore
181+
Has(string) (bool, error)
182+
// Put stores a key in the Keystore, if a key with the same name already exists, returns ErrKeyExists
183+
Put(string, ci.PrivKey) error
184+
// Get retrieves a key from the Keystore if it exists, and returns ErrNoSuchKey
185+
// otherwise.
186+
Get(string) (ci.PrivKey, error)
187+
// Delete removes a key from the Keystore
188+
Delete(string) error
189+
// List returns a list of key identifier
190+
List() ([]string, error)
200191
}
201192
```
202193

@@ -210,14 +201,14 @@ does not linger in memory.
210201
- if new node types are not unixfs nodes, special consideration must be given to the interop
211202

212203
- DagReader needs to be able to access keystore to seamlessly stream encrypted data we have keys for
213-
- also needs to be able to verify signatures
204+
- also needs to be able to verify signatures
214205

215206
#### Importer
216207

217208
- DagBuilderHelper needs to be able to encrypt blocks
218-
- Dag Nodes should be generated like normal, then encrypted, and their parents should
219-
link to the hash of the encrypted node
220-
- DagBuilderParams should have extra parameters to accommodate creating a DBH that encrypts the blocks
209+
- Dag Nodes should be generated like normal, then encrypted, and their parents should
210+
link to the hash of the encrypted node
211+
- DagBuilderParams should have extra parameters to acommodate creating a DBH that encrypts the blocks
221212

222213
#### New 'Encrypt' package
223214

@@ -235,33 +226,33 @@ Some tentative mockups (in json) of the new DAG structures for signing and encry
235226
Signed DAG:
236227
```
237228
{
238-
"Links" : [
239-
{
240-
"Name":"@content",
241-
"Hash":"QmTheContent",
242-
}
243-
],
244-
"Data": protobuf{
245-
"Type":"Signed DAG",
246-
"Signature": "thesignature",
247-
"PubKeyID": "QmPubKeyHash",
248-
}
229+
"Links" : [
230+
{
231+
"Name":"@content",
232+
"Hash":"QmTheContent",
233+
}
234+
],
235+
"Data": protobuf{
236+
"Type":"Signed DAG",
237+
"Signature": "thesignature",
238+
"PubKeyID": "QmPubKeyHash",
239+
}
249240
}
250241
```
251242

252243
Encrypted DAG:
253244
```
254245
{
255-
"Links" : [
256-
{
257-
"Name":"@content",
258-
"Hash":"QmRawEncryptedDag",
259-
}
260-
],
261-
"Data": protobuf{
262-
"Type":"Encrypted DAG",
263-
"PubKeyID": "QmPubKeyHash",
264-
"Key": "ephemeral symmetric key, encrypted with public key",
265-
}
246+
"Links" : [
247+
{
248+
"Name":"@content",
249+
"Hash":"QmRawEncryptedDag",
250+
}
251+
],
252+
"Data": protobuf{
253+
"Type":"Encrypted DAG",
254+
"PubKeyID": "QmPubKeyHash",
255+
"Key": "ephemeral symmetric key, encrypted with public key",
256+
}
266257
}
267258
```

REPO.md

Lines changed: 4 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ The Repo stores a collection of [IPLD](https://github.com/ipld/specs#readme) obj
3737

3838
- **config** - node configuration and settings
3939
- **datastore** - content stored locally, and indexing data
40-
- **keys** - cryptographic keys, including node's identity
40+
- **keystore** - cryptographic keys, including node's identity
4141
- **hooks** - scripts to run at predefined times (not yet implemented)
4242

4343
Note that the IPLD objects a repo stores are divided into:
@@ -73,17 +73,11 @@ The name "datastore" comes from [go-datastore](https://github.com/jbenet/go-data
7373

7474
This makes it easy to change properties or performance characteristics of a repo without an entirely new implementation.
7575

76-
### keys (state)
76+
### keystore
7777

78-
A Repo typically holds the keys a node has access to, for signing and for encryption. This includes:
78+
A Repo typically holds the keys a node has access to, for signing and for encryption.
7979

80-
- a special (private, public) key pair that defines the node's identity
81-
- (private, public) key pairs
82-
- symmetric keys
83-
84-
Some repos MAY support key-agent delegation, instead of storing the keys directly.
85-
86-
Keys are structured using the [multikey](https://github.com/jbenet/multikey) format, and are part of the [keychain](../keychain) datastructure. This means all keys are IPLD objects, and that they link to all the data needed to make sense of them, including parent keys, identities, and certificates.
80+
Details on operation and storage of the keystore can be found in [`REPO_FS.md`](REPO_FS.md) and [`KEYSTORE.md`](KEYSTORE.md).
8781

8882
### config (state)
8983

0 commit comments

Comments
 (0)