github.com/hyperledger/burrow@v0.34.5-0.20220512172541-77f09336001d/keys/server.go (about)

     1  package keys
     2  
     3  import (
     4  	"context"
     5  	"crypto/sha256"
     6  	"encoding/json"
     7  	"fmt"
     8  	"hash"
     9  	"strings"
    10  
    11  	"github.com/hyperledger/burrow/crypto"
    12  	hex "github.com/tmthrgd/go-hex"
    13  	"golang.org/x/crypto/ripemd160"
    14  	"google.golang.org/grpc"
    15  )
    16  
    17  //------------------------------------------------------------------------
    18  // all cli commands pass through the http KeyStore
    19  // the KeyStore process also maintains the unlocked accounts
    20  
    21  func StandAloneServer(keysDir string, AllowBadFilePermissions bool) *grpc.Server {
    22  	grpcServer := grpc.NewServer()
    23  	RegisterKeysServer(grpcServer, NewFilesystemKeyStore(keysDir, AllowBadFilePermissions))
    24  	return grpcServer
    25  }
    26  
    27  //------------------------------------------------------------------------
    28  // handlers
    29  
    30  func (k *FilesystemKeyStore) GenerateKey(ctx context.Context, in *GenRequest) (*GenResponse, error) {
    31  	curveT, err := crypto.CurveTypeFromString(in.CurveType)
    32  	if err != nil {
    33  		return nil, err
    34  	}
    35  
    36  	key, err := k.Gen(in.Passphrase, curveT)
    37  	if err != nil {
    38  		return nil, fmt.Errorf("error generating key %s %s", curveT, err)
    39  	}
    40  
    41  	addrH := key.Address.String()
    42  	if in.KeyName != "" {
    43  		err = coreNameAdd(k.keysDirPath, in.KeyName, addrH)
    44  		if err != nil {
    45  			return nil, err
    46  		}
    47  	}
    48  
    49  	return &GenResponse{Address: addrH}, nil
    50  }
    51  
    52  func (k *FilesystemKeyStore) Export(ctx context.Context, in *ExportRequest) (*ExportResponse, error) {
    53  	addr, err := getNameAddr(k.keysDirPath, in.GetName(), in.GetAddress())
    54  
    55  	if err != nil {
    56  		return nil, err
    57  	}
    58  
    59  	addrB, err := crypto.AddressFromHexString(addr)
    60  	if err != nil {
    61  		return nil, err
    62  	}
    63  
    64  	// No phrase needed for public key. I hope.
    65  	key, err := k.GetKey(in.GetPassphrase(), addrB.Bytes())
    66  	if err != nil {
    67  		return nil, err
    68  	}
    69  
    70  	return &ExportResponse{
    71  		Address:    addrB[:],
    72  		CurveType:  key.CurveType.String(),
    73  		Publickey:  key.PublicKey.PublicKey[:],
    74  		Privatekey: key.PrivateKey.PrivateKey[:],
    75  	}, nil
    76  }
    77  
    78  func (k *FilesystemKeyStore) PublicKey(ctx context.Context, in *PubRequest) (*PubResponse, error) {
    79  	addr, err := getNameAddr(k.keysDirPath, in.GetName(), in.GetAddress())
    80  	if err != nil {
    81  		return nil, err
    82  	}
    83  
    84  	addrB, err := crypto.AddressFromHexString(addr)
    85  	if err != nil {
    86  		return nil, err
    87  	}
    88  
    89  	// No phrase needed for public key. I hope.
    90  	key, err := k.GetKey("", addrB.Bytes())
    91  	if key == nil {
    92  		return nil, err
    93  	}
    94  
    95  	return &PubResponse{CurveType: key.CurveType.String(), PublicKey: key.Pubkey()}, nil
    96  }
    97  
    98  func (k *FilesystemKeyStore) Sign(ctx context.Context, in *SignRequest) (*SignResponse, error) {
    99  	addr, err := getNameAddr(k.keysDirPath, in.GetName(), in.GetAddress())
   100  	if err != nil {
   101  		return nil, err
   102  	}
   103  
   104  	addrB, err := crypto.AddressFromHexString(addr)
   105  	if err != nil {
   106  		return nil, err
   107  	}
   108  
   109  	key, err := k.GetKey(in.GetPassphrase(), addrB[:])
   110  	if err != nil {
   111  		return nil, err
   112  	}
   113  
   114  	sig, err := key.PrivateKey.Sign(in.GetMessage())
   115  	if err != nil {
   116  		return nil, err
   117  	}
   118  	return &SignResponse{Signature: sig}, err
   119  }
   120  
   121  func (k *FilesystemKeyStore) Verify(ctx context.Context, in *VerifyRequest) (*VerifyResponse, error) {
   122  	if in.GetPublicKey() == nil {
   123  		return nil, fmt.Errorf("must provide a pubkey")
   124  	}
   125  	if in.GetMessage() == nil {
   126  		return nil, fmt.Errorf("must provide a message")
   127  	}
   128  	if in.GetSignature() == nil {
   129  		return nil, fmt.Errorf("must provide a signature")
   130  	}
   131  
   132  	sig := in.GetSignature()
   133  	pubkey, err := crypto.PublicKeyFromBytes(in.GetPublicKey(), sig.GetCurveType())
   134  	if err != nil {
   135  		return nil, err
   136  	}
   137  	err = pubkey.Verify(in.GetMessage(), sig)
   138  	if err != nil {
   139  		return nil, err
   140  	}
   141  
   142  	return &VerifyResponse{}, nil
   143  }
   144  
   145  func (k *FilesystemKeyStore) Hash(ctx context.Context, in *HashRequest) (*HashResponse, error) {
   146  	var hasher hash.Hash
   147  	switch in.GetHashtype() {
   148  	case "ripemd160":
   149  		hasher = ripemd160.New()
   150  	case "sha256":
   151  		hasher = sha256.New()
   152  	// case "sha3":
   153  	default:
   154  		return nil, fmt.Errorf("unknown hash type %v", in.GetHashtype())
   155  	}
   156  
   157  	hasher.Write(in.GetMessage())
   158  
   159  	return &HashResponse{Hash: hex.EncodeUpperToString(hasher.Sum(nil))}, nil
   160  }
   161  
   162  func (k *FilesystemKeyStore) ImportJSON(ctx context.Context, in *ImportJSONRequest) (*ImportResponse, error) {
   163  	keyJSON := []byte(in.GetJSON())
   164  	addr := isValidKeyJson(keyJSON)
   165  	if addr != nil {
   166  		_, err := writeKey(k.keysDirPath, addr, keyJSON)
   167  		if err != nil {
   168  			return nil, err
   169  		}
   170  	} else {
   171  		j1 := new(struct {
   172  			CurveType   string
   173  			Address     string
   174  			PublicKey   string
   175  			AddressHash string
   176  			PrivateKey  string
   177  		})
   178  
   179  		err := json.Unmarshal([]byte(in.GetJSON()), &j1)
   180  		if err != nil {
   181  			return nil, err
   182  		}
   183  
   184  		addr, err = hex.DecodeString(j1.Address)
   185  		if err != nil {
   186  			return nil, err
   187  		}
   188  
   189  		curveT, err := crypto.CurveTypeFromString(j1.CurveType)
   190  		if err != nil {
   191  			return nil, err
   192  		}
   193  
   194  		privKey, err := hex.DecodeString(j1.PrivateKey)
   195  		if err != nil {
   196  			return nil, err
   197  		}
   198  
   199  		key, err := NewKeyFromPriv(curveT, privKey)
   200  		if err != nil {
   201  			return nil, err
   202  		}
   203  
   204  		// store the new key
   205  		if err = k.StoreKey(in.GetPassphrase(), key); err != nil {
   206  			return nil, err
   207  		}
   208  	}
   209  	return &ImportResponse{Address: hex.EncodeUpperToString(addr)}, nil
   210  }
   211  
   212  func (k *FilesystemKeyStore) Import(ctx context.Context, in *ImportRequest) (*ImportResponse, error) {
   213  	curveT, err := crypto.CurveTypeFromString(in.GetCurveType())
   214  	if err != nil {
   215  		return nil, err
   216  	}
   217  	key, err := NewKeyFromPriv(curveT, in.GetKeyBytes())
   218  	if err != nil {
   219  		return nil, err
   220  	}
   221  
   222  	// store the new key
   223  	if err = k.StoreKey(in.GetPassphrase(), key); err != nil {
   224  		return nil, err
   225  	}
   226  
   227  	if in.GetName() != "" {
   228  		if err := coreNameAdd(k.keysDirPath, in.GetName(), key.Address.String()); err != nil {
   229  			return nil, err
   230  		}
   231  	}
   232  	return &ImportResponse{Address: hex.EncodeUpperToString(key.Address[:])}, nil
   233  }
   234  
   235  func (k *FilesystemKeyStore) List(ctx context.Context, in *ListRequest) (*ListResponse, error) {
   236  	byname, err := coreNameList(k.keysDirPath)
   237  	if err != nil {
   238  		return nil, err
   239  	}
   240  
   241  	var list []*KeyID
   242  
   243  	if in.KeyName != "" {
   244  		if addr, ok := byname[in.KeyName]; ok {
   245  			list = append(list, &KeyID{KeyName: getAddressNames(addr, byname), Address: addr})
   246  		} else {
   247  			if addr, err := crypto.AddressFromHexString(in.KeyName); err == nil {
   248  				_, err := k.GetKey("", addr[:])
   249  				if err == nil {
   250  					address := addr.String()
   251  					list = append(list, &KeyID{Address: address, KeyName: getAddressNames(address, byname)})
   252  				}
   253  			}
   254  		}
   255  	} else {
   256  		// list all address
   257  
   258  		datadir, err := returnDataDir(k.keysDirPath)
   259  		if err != nil {
   260  			return nil, err
   261  		}
   262  		addrs, err := getAllAddresses(datadir)
   263  		if err != nil {
   264  			return nil, err
   265  		}
   266  
   267  		for _, addr := range addrs {
   268  			list = append(list, &KeyID{KeyName: getAddressNames(addr, byname), Address: addr})
   269  		}
   270  	}
   271  
   272  	return &ListResponse{Key: list}, nil
   273  }
   274  
   275  func getAddressNames(address string, byname map[string]string) []string {
   276  	names := make([]string, 0)
   277  
   278  	for name, addr := range byname {
   279  		if address == addr {
   280  			names = append(names, name)
   281  		}
   282  	}
   283  
   284  	return names
   285  }
   286  
   287  func (k *FilesystemKeyStore) RemoveName(ctx context.Context, in *RemoveNameRequest) (*RemoveNameResponse, error) {
   288  	if in.GetKeyName() == "" {
   289  		return nil, fmt.Errorf("please specify a name")
   290  	}
   291  
   292  	return &RemoveNameResponse{}, coreNameRm(k.keysDirPath, in.GetKeyName())
   293  }
   294  
   295  func (k *FilesystemKeyStore) AddName(ctx context.Context, in *AddNameRequest) (*AddNameResponse, error) {
   296  	if in.GetKeyname() == "" {
   297  		return nil, fmt.Errorf("please specify a name")
   298  	}
   299  
   300  	if in.GetAddress() == "" {
   301  		return nil, fmt.Errorf("please specify an address")
   302  	}
   303  
   304  	return &AddNameResponse{}, coreNameAdd(k.keysDirPath, in.GetKeyname(), strings.ToUpper(in.GetAddress()))
   305  }