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 }