-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathsign.go
More file actions
128 lines (116 loc) · 3.39 KB
/
Copy pathsign.go
File metadata and controls
128 lines (116 loc) · 3.39 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
package kms
import (
"context"
"encoding/hex"
"fmt"
"github.com/decred/dcrd/dcrec/secp256k1/v4"
"github.com/hashicorp/vault/sdk/framework"
"github.com/hashicorp/vault/sdk/logical"
"github.com/perme-io/vault-plugin-secrets-kms/chains"
"golang.org/x/crypto/sha3"
)
func pathSign(b *kmsBackend) []*framework.Path {
return []*framework.Path{
{
Pattern: "wallet/sign",
Fields: map[string]*framework.FieldSchema{
"username": {
Type: framework.TypeString,
Description: "username of wallet",
Required: true,
},
"address": {
Type: framework.TypeString,
Description: "address of wallet",
Required: true,
},
"chainName": {
Type: framework.TypeString,
Description: "name of blockchain",
Required: true,
},
"txSerialized": {
Type: framework.TypeString,
Description: "serialized transaction data",
Required: false,
},
"msgHash": {
Type: framework.TypeString,
Description: "an arbitrary 32-byte message hash to sign, expressed as a hex string",
Required: false,
},
},
Operations: map[logical.Operation]framework.OperationHandler{
logical.CreateOperation: &framework.PathOperation{
Callback: b.pathSignCreate,
},
logical.UpdateOperation: &framework.PathOperation{
Callback: b.pathSignCreate,
},
},
HelpSynopsis: pathSignHelpSynopsis,
HelpDescription: pathSignHelpDescription,
},
}
}
func (b *kmsBackend) pathSignCreate(ctx context.Context, req *logical.Request, d *framework.FieldData) (*logical.Response, error) {
var username string
if un, ok := d.GetOk("username"); ok {
username = un.(string)
} else {
return nil, fmt.Errorf("missing username in sign")
}
var address string
if addr, ok := d.GetOk("address"); ok {
address = addr.(string)
} else {
return nil, fmt.Errorf("missing address in sign")
}
var chainName chains.ChainName
if wtype, ok := d.GetOk("chainName"); ok {
chainName = chains.ChainName(wtype.(string))
} else {
return nil, fmt.Errorf("missing chainName in sign")
}
var hashBytes []byte
if ts, ok := d.GetOk("txSerialized"); ok {
txSerialized := ts.(string)
digest := sha3.Sum256([]byte(txSerialized))
hashBytes = digest[:]
} else if mh, ok := d.GetOk("msgHash"); ok {
hexString := mh.(string)
hashBytes, _ = hex.DecodeString(hexString)
} else {
return nil, fmt.Errorf("missing txSerialized or msgHash in sign")
}
if len(hashBytes) != 32 {
return nil, fmt.Errorf("invalid hash length")
}
walletPath := getWalletPath(username, address)
wallet, err := getWallet(ctx, req, walletPath)
if err != nil {
return nil, err
}
if privKeyBytes, err := hex.DecodeString(wallet.PrivateKey); err == nil {
privateKey := secp256k1.PrivKeyFromBytes(privKeyBytes)
chain, err := chains.NewChain(chainName, privateKey)
if err != nil {
return nil, err
}
if signature, err := chain.SignCompact(hashBytes); err == nil {
return &logical.Response{
Data: map[string]interface{}{
"signature": signature,
},
}, nil
}
}
return nil, fmt.Errorf("faild to sign: err=%v", err)
}
const (
pathSignHelpSynopsis = `Manages the Vault signature for send transaction.`
pathSignHelpDescription = `
This path lets you create a signature for sending a transaction.
You can get a signature from the user's wallet by providing the username and txSerialized (or msgHash) fields.
`
)