Skip to content

Commit 16b5ec4

Browse files
committed
Keystore: bring keystore spec more up to date
This makes the parts that have been implemented from the keystore spec be reflected on the spec the way that they actually work. Focuses on: * How keys are named and stored on disk (REPO_FS) * What the current interface is (KEYSTORE)
1 parent aac1488 commit 16b5ec4

File tree

3 files changed

+114
-119
lines changed

3 files changed

+114
-119
lines changed

KEYSTORE.md

Lines changed: 87 additions & 96 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-
accomodate 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
151140
'ipfs crypt encrypt' is a command used to encypt data so that only holders of a certain
152-
key can read it.
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,13 +201,13 @@ 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
209+
- Dag Nodes should be generated like normal, then encrypted, and their parents should
210+
link to the hash of the encrypted node
220211
- DagBuilderParams should have extra parameters to acommodate creating a DBH that encrypts the blocks
221212

222213
#### New 'Encrypt' package
@@ -235,33 +226,33 @@ Some tenative mockups (in json) of the new DAG structures for signing and encryp
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

REPO_FS.md

Lines changed: 23 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,8 @@
22

33
**Author(s)**:
44
- [Juan Benet](github.com/jbenet)
5-
5+
- [David Dias](github.com/daviddias)
6+
- [Hector Sanjuan](github.com/hsanjuan)
67
* * *
78

89
**Abstract**
@@ -32,9 +33,8 @@ This spec defines `fs-repo` version `1`, its formats, and semantics.
3233
│ └── aa <--- N tiers
3334
├── config <--- config file (json or toml)
3435
├── hooks/ <--- hook scripts
35-
├── keys/ <--- cryptographic keys
36-
│ ├── id.pri <--- identity private key
37-
│ └── id.pub <--- identity public key
36+
├── keystore/ <--- cryptographic keys
37+
│ ├── key_b32name <--- private key with base32-encoded name
3838
├── datastore/ <--- datastore
3939
├── logs/ <--- 1 or more files (log rotate)
4040
│ └── events.log <--- can be tailed
@@ -116,18 +116,28 @@ Currently available hooks:
116116
none
117117
```
118118

119-
### keys/
119+
### keystore/
120120

121121

122-
The `keys` directory holds all the keys the node has access to. The keys
123-
are named with their hash, and an extension describing what type of key
124-
they are. The only specially-named key is `id.{pub, sec}`
122+
The `keystore` directory holds additional private keys that the node has
123+
access to (the public keys can be derived from them).
125124

126-
```
127-
<key>.pub is a public key
128-
<key>.pri is a private key
129-
<key>.sym is a symmetric secret key
130-
```
125+
The keystore repository should have `0700` permissions (readable, writable by
126+
the owner only).
127+
128+
The key files are named as `key_base32encodedNameNoPadding` where `key_` is a
129+
fixed prefix followed by a base32 encoded identifier, **without padding and
130+
downcased**. The identifier usually corresponds to a human-friendly name given
131+
by the user.
132+
133+
The key files should have '0400' permissions (read-only, by the owner only).
134+
135+
The `self` key identifier is reserved for the peer's main key, and therefore key named
136+
`key_onswyzq` is allowed in this folder.
137+
138+
The key files themselves contain a serialized representation of the keys as
139+
defined in the
140+
[libp2p specification](https://github.com/libp2p/specs/blob/master/peer-ids/peer-ids.md#keys).
131141

132142
### datastore/
133143

0 commit comments

Comments
 (0)