master
md 295 lines 8.12 KB
Rendered Raw
1 # ![](https://img.shields.io/badge/status-wip-orange.svg?style=flat-square) Keystore
2
3 **Authors(s):**
4 - [whyrusleeping](github.com/whyrusleeping)
5 - [Hector Sanjuan](github.com/hsanjuan)
6
7 **Abstract**
8
9 This spec provides definitions and operations for the keystore feature in IPFS.
10
11 # Table of Contents
12
13 - [Goals](#goals)
14 - [Planned Implementation](#planned-implementation)
15 - [Key storage](#key-storage)
16 - [Interface](#interface)
17 - [Code changes and additions](#code-changes-and-additions)
18 - [Structures](#structures)
19
20 ## Goals
21
22 To have a secure, simple and user-friendly way of storing and managing keys
23 for use by ipfs. As well as the ability to share these keys, encrypt, decrypt,
24 sign and verify data.
25
26 ## Planned Implementation
27
28 ### Key storage
29
30 Storage layout and format is defined in the [`repository_fs`](repository_fs.md) part of the spec.
31
32 ### Interface
33
34 #### ipfs key
35
36 ```
37 USAGE
38 ipfs key - Create and list IPNS name keypairs
39
40 ipfs key
41
42 'ipfs key gen' generates a new keypair for usage with IPNS and 'ipfs name
43 publish'.
44
45 > ipfs key gen --type=rsa --size=2048 mykey
46 > ipfs name publish --key=mykey QmSomeHash
47
48 'ipfs key list' lists the available keys.
49
50 > ipfs key list
51 self
52 mykey
53
54
55 SUBCOMMANDS
56 ipfs key export <name> - Export a keypair
57 ipfs key gen <name> - Create a new keypair
58 ipfs key import <name> <key> - Import a key and prints imported key id
59 ipfs key list - List all local keypairs.
60 ipfs key rename <name> <newName> - Rename a keypair.
61 ipfs key rm <name>... - Remove a keypair.
62 ipfs key rotate - Rotates the IPFS identity.
63
64 For more information about each command, use:
65 'ipfs key <subcmd> --help'
66 ```
67
68 #### ipfs crypt
69
70 **NOTE:** as of 2023 Q4, `ipfs crypt` commands are not implemented yet.
71
72 ```
73 ipfs crypt - Perform cryptographic operations using ipfs keypairs
74
75 SUBCOMMANDS:
76
77 ipfs crypt sign <data> - Generates a signature for the given data with a specified key
78 ipfs crypt verify <data> <sig> - Verify that the given data and signature match
79 ipfs crypt encrypt <data> - Encrypt the given data
80 ipfs crypt decrypt <data> - Decrypt the given data
81
82 DESCRIPTION:
83
84 `ipfs crypt` is a command used to perform various cryptographic operations
85 using ipfs keypairs, including: signing, verifying, encrypting and decrypting.
86 ```
87
88 #### Some subcommands:
89
90 ##### ipfs key Gen
91
92
93 ```
94 USAGE
95 ipfs key gen <name> - Create a new keypair
96
97 SYNOPSIS
98 ipfs key gen [--type=<type> | -t] [--size=<size> | -s]
99 [--ipns-base=<ipns-base>] [--] <name>
100
101 ARGUMENTS
102
103 <name> - name of key to create
104
105 OPTIONS
106
107 -t, --type string - type of the key to create: rsa, ed25519. Default:
108 ed25519.
109 -s, --size int - size of the key to generate.
110 --ipns-base string - Encoding used for keys: Can either be a multibase
111 encoded CID or a base58btc encoded multihash. Takes
112 {b58mh|base36|k|base32|b...}. Default: base36.
113 ```
114
115 * * *
116
117 ##### Key Send
118
119 ```
120 USAGE
121 ipfs key - Create and list IPNS name keypairs
122
123 SYNOPSIS
124 ipfs key
125
126 DESCRIPTION
127
128 'ipfs key gen' generates a new keypair for usage with IPNS and 'ipfs name
129 publish'.
130
131 > ipfs key gen --type=rsa --size=2048 mykey
132 > ipfs name publish --key=mykey QmSomeHash
133
134 'ipfs key list' lists the available keys.
135
136 > ipfs key list
137 self
138 mykey
139
140
141 SUBCOMMANDS
142 ipfs key export <name> - Export a keypair
143 ipfs key gen <name> - Create a new keypair
144 ipfs key import <name> <key> - Import a key and prints imported key id
145 ipfs key list - List all local keypairs.
146 ipfs key rename <name> <newName> - Rename a keypair.
147 ipfs key rm <name>... - Remove a keypair.
148 ipfs key rotate - Rotates the IPFS identity.
149
150 For more information about each command, use:
151 'ipfs key <subcmd> --help'
152 ```
153
154 ##### Comments:
155
156 Ensure that the user knows the implications of sending a key.
157
158 * * *
159
160 ##### Crypt Encrypt
161
162 ```
163 ipfs crypt encrypt <data> - Encrypt the given data with a specified key
164
165 ARGUMENTS:
166
167 data - The filename of the data to be encrypted ("-" for stdin)
168
169 OPTIONS:
170
171 -k, -key string - The name of the key to use for encryption (default: localkey)
172 -o, -output string - The name of the output file (default: stdout)
173 -c, -cipher string - The cipher to use for the operation
174 -m, -mode string - The block cipher mode to use for the operation
175
176 DESCRIPTION:
177
178 'ipfs crypt encrypt' is a command used to encrypt data so that only holders of a certain
179 key can read it.
180 ```
181
182 ##### Comments:
183
184 This should probably just operate on raw data and not on DAGs.
185
186 * * *
187
188 ##### Other Interface Changes
189
190 We will also need to make additions to support keys in other commands, these changes are as follows:
191
192 - `ipfs add`
193 - Support for a `-encrypt-key` option, for block encrypting the file being added with the key
194 - also adds an 'encrypted' node above the root unixfs node
195 - Support for a `-sign-key` option to attach a signature node above the root unixfs node
196
197 - `ipfs block put`
198 - Support for a `-encrypt-key` option, for encrypting the block before hashing and storing
199
200 - `ipfs object put`
201 - Support for a `-encrypt-key` option, for encrypting the object before hashing and storing
202
203 - `ipfs name publish`
204 - Support for a `-key` option to select which keyspace to publish to
205
206 ### Code changes and additions
207
208 This sections outlines code organization around this feature.
209
210 #### Keystore package
211
212 The fsrepo carries a `keystore` that can be used to load/store keys. The keystore is implemented following this interface:
213
214 ```go
215 // Keystore provides a key management interface
216 type Keystore interface {
217 // Has returns whether or not a key exist in the Keystore
218 Has(string) (bool, error)
219 // Put stores a key in the Keystore, if a key with the same name already exists, returns ErrKeyExists
220 Put(string, ci.PrivKey) error
221 // Get retrieves a key from the Keystore if it exists, and returns ErrNoSuchKey
222 // otherwise.
223 Get(string) (ci.PrivKey, error)
224 // Delete removes a key from the Keystore
225 Delete(string) error
226 // List returns a list of key identifier
227 List() ([]string, error)
228 }
229 ```
230
231 Note: Never store passwords as strings, strings cannot be zeroed out after they are used.
232 using a byte array allows you to write zeroes over the memory so that the users password
233 does not linger in memory.
234
235 #### Unixfs
236
237 - new node types, 'encrypted' and 'signed', probably shouldn't be in unixfs, just understood by it
238 - if new node types are not unixfs nodes, special consideration must be given to the interop
239
240 - DagReader needs to be able to access keystore to seamlessly stream encrypted data we have keys for
241 - also needs to be able to verify signatures
242
243 #### Importer
244
245 - DagBuilderHelper needs to be able to encrypt blocks
246 - Dag Nodes should be generated like normal, then encrypted, and their parents should
247 link to the hash of the encrypted node
248 - DagBuilderParams should have extra parameters to accommodate creating a DBH that encrypts the blocks
249
250 #### New 'Encrypt' package
251
252 Should contain code for crypto operations on dags.
253
254 Encryption of dags should work by first generating a symmetric key, and using
255 that key to encrypt all the data. That key should then be encrypted with the
256 public key chosen and stored in the Encrypted DAG structure.
257
258 Note: One option is to simply add it to the key interface.
259
260 ### Structures
261 Some tentative mockups (in json) of the new DAG structures for signing and encrypting
262
263 Signed DAG:
264 ```
265 {
266 "Links" : [
267 {
268 "Name":"@content",
269 "Hash":"QmTheContent",
270 }
271 ],
272 "Data": protobuf{
273 "Type":"Signed DAG",
274 "Signature": "thesignature",
275 "PubKeyID": "QmPubKeyHash",
276 }
277 }
278 ```
279
280 Encrypted DAG:
281 ```
282 {
283 "Links" : [
284 {
285 "Name":"@content",
286 "Hash":"QmRawEncryptedDag",
287 }
288 ],
289 "Data": protobuf{
290 "Type":"Encrypted DAG",
291 "PubKeyID": "QmPubKeyHash",
292 "Key": "ephemeral symmetric key, encrypted with public key",
293 }
294 }
295 ```