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