github.com/linapex/ethereum-go-chinese@v0.0.0-20190316121929-f8b7a73c3fa1/cmd/swarm/access.go (about) 1 2 //<developer> 3 // <name>linapex 曹一峰</name> 4 // <email>linapex@163.com</email> 5 // <wx>superexc</wx> 6 // <qqgroup>128148617</qqgroup> 7 // <url>https://jsq.ink</url> 8 // <role>pku engineer</role> 9 // <date>2019-03-16 19:16:33</date> 10 //</624450070346993664> 11 12 package main 13 14 import ( 15 "crypto/rand" 16 "encoding/json" 17 "fmt" 18 "io" 19 "io/ioutil" 20 "strings" 21 22 "github.com/ethereum/go-ethereum/cmd/utils" 23 "github.com/ethereum/go-ethereum/swarm/api" 24 "github.com/ethereum/go-ethereum/swarm/api/client" 25 "gopkg.in/urfave/cli.v1" 26 ) 27 28 var ( 29 salt = make([]byte, 32) 30 accessCommand = cli.Command{ 31 CustomHelpTemplate: helpTemplate, 32 Name: "access", 33 Usage: "encrypts a reference and embeds it into a root manifest", 34 ArgsUsage: "<ref>", 35 Description: "encrypts a reference and embeds it into a root manifest", 36 Subcommands: []cli.Command{ 37 { 38 CustomHelpTemplate: helpTemplate, 39 Name: "new", 40 Usage: "encrypts a reference and embeds it into a root manifest", 41 ArgsUsage: "<ref>", 42 Description: "encrypts a reference and embeds it into a root access manifest and prints the resulting manifest", 43 Subcommands: []cli.Command{ 44 { 45 Action: accessNewPass, 46 CustomHelpTemplate: helpTemplate, 47 Flags: []cli.Flag{ 48 utils.PasswordFileFlag, 49 SwarmDryRunFlag, 50 }, 51 Name: "pass", 52 Usage: "encrypts a reference with a password and embeds it into a root manifest", 53 ArgsUsage: "<ref>", 54 Description: "encrypts a reference and embeds it into a root access manifest and prints the resulting manifest", 55 }, 56 { 57 Action: accessNewPK, 58 CustomHelpTemplate: helpTemplate, 59 Flags: []cli.Flag{ 60 utils.PasswordFileFlag, 61 SwarmDryRunFlag, 62 SwarmAccessGrantKeyFlag, 63 }, 64 Name: "pk", 65 Usage: "encrypts a reference with the node's private key and a given grantee's public key and embeds it into a root manifest", 66 ArgsUsage: "<ref>", 67 Description: "encrypts a reference and embeds it into a root access manifest and prints the resulting manifest", 68 }, 69 { 70 Action: accessNewACT, 71 CustomHelpTemplate: helpTemplate, 72 Flags: []cli.Flag{ 73 SwarmAccessGrantKeysFlag, 74 SwarmDryRunFlag, 75 utils.PasswordFileFlag, 76 }, 77 Name: "act", 78 Usage: "encrypts a reference with the node's private key and a given grantee's public key and embeds it into a root manifest", 79 ArgsUsage: "<ref>", 80 Description: "encrypts a reference and embeds it into a root access manifest and prints the resulting manifest", 81 }, 82 }, 83 }, 84 }, 85 } 86 ) 87 88 func init() { 89 if _, err := io.ReadFull(rand.Reader, salt); err != nil { 90 panic("reading from crypto/rand failed: " + err.Error()) 91 } 92 } 93 94 func accessNewPass(ctx *cli.Context) { 95 args := ctx.Args() 96 if len(args) != 1 { 97 utils.Fatalf("Expected 1 argument - the ref") 98 } 99 100 var ( 101 ae *api.AccessEntry 102 accessKey []byte 103 err error 104 ref = args[0] 105 password = getPassPhrase("", 0, makePasswordList(ctx)) 106 dryRun = ctx.Bool(SwarmDryRunFlag.Name) 107 ) 108 accessKey, ae, err = api.DoPassword(ctx, password, salt) 109 if err != nil { 110 utils.Fatalf("error getting session key: %v", err) 111 } 112 m, err := api.GenerateAccessControlManifest(ctx, ref, accessKey, ae) 113 if err != nil { 114 utils.Fatalf("had an error generating the manifest: %v", err) 115 } 116 if dryRun { 117 err = printManifests(m, nil) 118 if err != nil { 119 utils.Fatalf("had an error printing the manifests: %v", err) 120 } 121 } else { 122 err = uploadManifests(ctx, m, nil) 123 if err != nil { 124 utils.Fatalf("had an error uploading the manifests: %v", err) 125 } 126 } 127 } 128 129 func accessNewPK(ctx *cli.Context) { 130 args := ctx.Args() 131 if len(args) != 1 { 132 utils.Fatalf("Expected 1 argument - the ref") 133 } 134 135 var ( 136 ae *api.AccessEntry 137 sessionKey []byte 138 err error 139 ref = args[0] 140 privateKey = getPrivKey(ctx) 141 granteePublicKey = ctx.String(SwarmAccessGrantKeyFlag.Name) 142 dryRun = ctx.Bool(SwarmDryRunFlag.Name) 143 ) 144 sessionKey, ae, err = api.DoPK(ctx, privateKey, granteePublicKey, salt) 145 if err != nil { 146 utils.Fatalf("error getting session key: %v", err) 147 } 148 m, err := api.GenerateAccessControlManifest(ctx, ref, sessionKey, ae) 149 if err != nil { 150 utils.Fatalf("had an error generating the manifest: %v", err) 151 } 152 if dryRun { 153 err = printManifests(m, nil) 154 if err != nil { 155 utils.Fatalf("had an error printing the manifests: %v", err) 156 } 157 } else { 158 err = uploadManifests(ctx, m, nil) 159 if err != nil { 160 utils.Fatalf("had an error uploading the manifests: %v", err) 161 } 162 } 163 } 164 165 func accessNewACT(ctx *cli.Context) { 166 args := ctx.Args() 167 if len(args) != 1 { 168 utils.Fatalf("Expected 1 argument - the ref") 169 } 170 171 var ( 172 ae *api.AccessEntry 173 actManifest *api.Manifest 174 accessKey []byte 175 err error 176 ref = args[0] 177 pkGrantees = []string{} 178 passGrantees = []string{} 179 pkGranteesFilename = ctx.String(SwarmAccessGrantKeysFlag.Name) 180 passGranteesFilename = ctx.String(utils.PasswordFileFlag.Name) 181 privateKey = getPrivKey(ctx) 182 dryRun = ctx.Bool(SwarmDryRunFlag.Name) 183 ) 184 if pkGranteesFilename == "" && passGranteesFilename == "" { 185 utils.Fatalf("you have to provide either a grantee public-keys file or an encryption passwords file (or both)") 186 } 187 188 if pkGranteesFilename != "" { 189 bytes, err := ioutil.ReadFile(pkGranteesFilename) 190 if err != nil { 191 utils.Fatalf("had an error reading the grantee public key list") 192 } 193 pkGrantees = strings.Split(strings.Trim(string(bytes), "\n"), "\n") 194 } 195 196 if passGranteesFilename != "" { 197 bytes, err := ioutil.ReadFile(passGranteesFilename) 198 if err != nil { 199 utils.Fatalf("could not read password filename: %v", err) 200 } 201 passGrantees = strings.Split(strings.Trim(string(bytes), "\n"), "\n") 202 } 203 accessKey, ae, actManifest, err = api.DoACT(ctx, privateKey, salt, pkGrantees, passGrantees) 204 if err != nil { 205 utils.Fatalf("error generating ACT manifest: %v", err) 206 } 207 208 if err != nil { 209 utils.Fatalf("error getting session key: %v", err) 210 } 211 m, err := api.GenerateAccessControlManifest(ctx, ref, accessKey, ae) 212 if err != nil { 213 utils.Fatalf("error generating root access manifest: %v", err) 214 } 215 216 if dryRun { 217 err = printManifests(m, actManifest) 218 if err != nil { 219 utils.Fatalf("had an error printing the manifests: %v", err) 220 } 221 } else { 222 err = uploadManifests(ctx, m, actManifest) 223 if err != nil { 224 utils.Fatalf("had an error uploading the manifests: %v", err) 225 } 226 } 227 } 228 229 func printManifests(rootAccessManifest, actManifest *api.Manifest) error { 230 js, err := json.Marshal(rootAccessManifest) 231 if err != nil { 232 return err 233 } 234 fmt.Println(string(js)) 235 236 if actManifest != nil { 237 js, err := json.Marshal(actManifest) 238 if err != nil { 239 return err 240 } 241 fmt.Println(string(js)) 242 } 243 return nil 244 } 245 246 func uploadManifests(ctx *cli.Context, rootAccessManifest, actManifest *api.Manifest) error { 247 bzzapi := strings.TrimRight(ctx.GlobalString(SwarmApiFlag.Name), "/") 248 client := client.NewClient(bzzapi) 249 250 var ( 251 key string 252 err error 253 ) 254 if actManifest != nil { 255 key, err = client.UploadManifest(actManifest, false) 256 if err != nil { 257 return err 258 } 259 260 rootAccessManifest.Entries[0].Access.Act = key 261 } 262 key, err = client.UploadManifest(rootAccessManifest, false) 263 if err != nil { 264 return err 265 } 266 fmt.Println(key) 267 return nil 268 } 269 270 //makepasswordlist从global--password标志指定的文件中读取密码行 271 //以及同一个子命令——密码标志。 272 //此函数是utils.makepasswordlist的分支,用于查找子命令的CLI上下文。 273 //函数ctx.setglobal未设置可访问的全局标志值 274 // 275 func makePasswordList(ctx *cli.Context) []string { 276 path := ctx.GlobalString(utils.PasswordFileFlag.Name) 277 if path == "" { 278 path = ctx.String(utils.PasswordFileFlag.Name) 279 if path == "" { 280 return nil 281 } 282 } 283 text, err := ioutil.ReadFile(path) 284 if err != nil { 285 utils.Fatalf("Failed to read password file: %v", err) 286 } 287 lines := strings.Split(string(text), "\n") 288 //对DOS行结尾进行消毒。 289 for i := range lines { 290 lines[i] = strings.TrimRight(lines[i], "\r") 291 } 292 return lines 293 } 294