Skip to content

Commit b56cb53

Browse files
authored
[PRODCRE-1746] Move keys from core to corekeys. (#1837)
* Minor. * Minor. * Minor. * Minor. * Minor. * chore: trigger pipeline * Minor. * Minor. * Minor. * Minor. * Minor.
1 parent f5d06ba commit b56cb53

126 files changed

Lines changed: 10597 additions & 573 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

go.md

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@ flowchart LR
1616
chainlink-common --> libocr
1717
click chainlink-common href "https://github.com/smartcontractkit/chainlink-common"
1818
chainlink-common/keystore --> chainlink-common
19+
chainlink-common/keystore --> smdkg
20+
chainlink-common/keystore --> wsrpc
1921
click chainlink-common/keystore href "https://github.com/smartcontractkit/chainlink-common"
2022
chainlink-common/pkg/chipingress
2123
click chainlink-common/pkg/chipingress href "https://github.com/smartcontractkit/chainlink-common"
@@ -37,10 +39,19 @@ flowchart LR
3739
click chainlink-protos/workflows/go href "https://github.com/smartcontractkit/chainlink-protos"
3840
freeport
3941
click freeport href "https://github.com/smartcontractkit/freeport"
42+
go-sumtype2
43+
click go-sumtype2 href "https://github.com/smartcontractkit/go-sumtype2"
4044
grpc-proxy
4145
click grpc-proxy href "https://github.com/smartcontractkit/grpc-proxy"
42-
libocr
46+
libocr --> go-sumtype2
4347
click libocr href "https://github.com/smartcontractkit/libocr"
48+
smdkg --> libocr
49+
smdkg --> tdh2/go/tdh2
50+
click smdkg href "https://github.com/smartcontractkit/smdkg"
51+
tdh2/go/tdh2
52+
click tdh2/go/tdh2 href "https://github.com/smartcontractkit/tdh2"
53+
wsrpc
54+
click wsrpc href "https://github.com/smartcontractkit/wsrpc"
4455
4556
subgraph chainlink-common-repo[chainlink-common]
4657
chainlink-common
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
package aptoskey
2+
3+
import (
4+
"encoding/hex"
5+
6+
"github.com/ethereum/go-ethereum/accounts/keystore"
7+
8+
commonkeystore "github.com/smartcontractkit/chainlink-common/keystore"
9+
"github.com/smartcontractkit/chainlink-common/keystore/internal"
10+
)
11+
12+
const keyTypeIdentifier = "Aptos"
13+
14+
// FromEncryptedJSON gets key from json and password
15+
func FromEncryptedJSON(keyJSON []byte, password string) (Key, error) {
16+
return internal.FromEncryptedJSON(
17+
keyTypeIdentifier,
18+
keyJSON,
19+
password,
20+
adulteratedPassword,
21+
func(_ internal.EncryptedKeyExport, rawPrivKey internal.Raw) (Key, error) {
22+
return KeyFor(rawPrivKey), nil
23+
},
24+
)
25+
}
26+
27+
// ToEncryptedJSON returns encrypted JSON representing key
28+
func (key Key) ToEncryptedJSON(password string, scryptParams commonkeystore.ScryptParams) (export []byte, err error) {
29+
return internal.ToEncryptedJSON(
30+
keyTypeIdentifier,
31+
key,
32+
password,
33+
scryptParams.N,
34+
scryptParams.P,
35+
adulteratedPassword,
36+
func(id string, key Key, cryptoJSON keystore.CryptoJSON) internal.EncryptedKeyExport {
37+
return internal.EncryptedKeyExport{
38+
KeyType: id,
39+
PublicKey: hex.EncodeToString(key.pubKey),
40+
Crypto: cryptoJSON,
41+
}
42+
},
43+
)
44+
}
45+
46+
func adulteratedPassword(password string) string {
47+
return "aptoskey" + password
48+
}
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
package aptoskey
2+
3+
import (
4+
"testing"
5+
6+
"github.com/smartcontractkit/chainlink-common/keystore/corekeys"
7+
)
8+
9+
func TestAptosKeys_ExportImport(t *testing.T) {
10+
corekeys.RunKeyExportImportTestcase(t, createKey, decryptKey)
11+
}
12+
13+
func createKey() (corekeys.KeyType, error) {
14+
return New()
15+
}
16+
17+
func decryptKey(keyJSON []byte, password string) (corekeys.KeyType, error) {
18+
return FromEncryptedJSON(keyJSON, password)
19+
}

keystore/corekeys/aptoskey/key.go

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
package aptoskey
2+
3+
import (
4+
"crypto"
5+
"crypto/ed25519"
6+
crypto_rand "crypto/rand"
7+
"fmt"
8+
"io"
9+
10+
"golang.org/x/crypto/sha3"
11+
12+
"github.com/smartcontractkit/chainlink-common/keystore/internal"
13+
)
14+
15+
// Key represents Aptos key
16+
type Key struct {
17+
// TODO: store initial Account() derivation to support key rotation
18+
raw internal.Raw
19+
signFn func(io.Reader, []byte, crypto.SignerOpts) ([]byte, error)
20+
pubKey ed25519.PublicKey
21+
}
22+
23+
func KeyFor(raw internal.Raw) Key {
24+
privKey := ed25519.NewKeyFromSeed(internal.Bytes(raw))
25+
pubKey := privKey.Public().(ed25519.PublicKey)
26+
return Key{
27+
raw: raw,
28+
signFn: privKey.Sign,
29+
pubKey: pubKey,
30+
}
31+
}
32+
33+
// New creates new Key
34+
func New() (Key, error) {
35+
return newFrom(crypto_rand.Reader)
36+
}
37+
38+
// MustNewInsecure return Key if no error
39+
func MustNewInsecure(reader io.Reader) Key {
40+
key, err := newFrom(reader)
41+
if err != nil {
42+
panic(err)
43+
}
44+
return key
45+
}
46+
47+
// newFrom creates new Key from a provided random reader
48+
func newFrom(reader io.Reader) (Key, error) {
49+
pub, priv, err := ed25519.GenerateKey(reader)
50+
if err != nil {
51+
return Key{}, err
52+
}
53+
return Key{
54+
raw: internal.NewRaw(priv.Seed()),
55+
signFn: priv.Sign,
56+
pubKey: pub,
57+
}, nil
58+
}
59+
60+
// ID gets Key ID
61+
func (key Key) ID() string {
62+
return key.PublicKeyStr()
63+
}
64+
65+
// https://github.com/aptos-foundation/AIPs/blob/main/aips/aip-40.md#long
66+
func (key Key) Account() string {
67+
authKey := sha3.Sum256(append([]byte(key.pubKey), 0x00))
68+
return fmt.Sprintf("%064x", authKey)
69+
}
70+
71+
// GetPublic get Key's public key
72+
func (key Key) GetPublic() ed25519.PublicKey {
73+
return key.pubKey
74+
}
75+
76+
// PublicKeyStr returns hex encoded public key
77+
func (key Key) PublicKeyStr() string {
78+
return fmt.Sprintf("%064x", key.pubKey)
79+
}
80+
81+
// Raw returns the seed from private key
82+
func (key Key) Raw() internal.Raw { return key.raw }
83+
84+
// Sign is used to sign a message
85+
func (key Key) Sign(msg []byte) ([]byte, error) {
86+
return key.signFn(crypto_rand.Reader, msg, crypto.Hash(0)) // no specific hash function used
87+
}
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
package aptoskey
2+
3+
import (
4+
"encoding/hex"
5+
"testing"
6+
7+
"github.com/stretchr/testify/assert"
8+
"github.com/stretchr/testify/require"
9+
10+
"github.com/smartcontractkit/chainlink-common/keystore/internal"
11+
)
12+
13+
func TestAptosKey(t *testing.T) {
14+
bytes, err := hex.DecodeString("f0d07ab448018b2754475f9a3b580218b0675a1456aad96ad607c7bbd7d9237b")
15+
require.NoError(t, err)
16+
k := KeyFor(internal.NewRaw(bytes))
17+
assert.Equal(t, "2acd605efc181e2af8a0b8c0686a5e12578efa1253d15a235fa5e5ad970c4b29", k.PublicKeyStr())
18+
assert.Equal(t, "69d8b07f5945185873c622ea66873b0e1fb921de7b94d904d3ef9be80770682e", k.Account())
19+
}
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
package cosmoskey
2+
3+
import (
4+
"encoding/hex"
5+
6+
"github.com/ethereum/go-ethereum/accounts/keystore"
7+
8+
commonkeystore "github.com/smartcontractkit/chainlink-common/keystore"
9+
"github.com/smartcontractkit/chainlink-common/keystore/internal"
10+
)
11+
12+
const keyTypeIdentifier = "Cosmos"
13+
14+
// FromEncryptedJSON gets key from json and password
15+
func FromEncryptedJSON(keyJSON []byte, password string) (Key, error) {
16+
return internal.FromEncryptedJSON(
17+
keyTypeIdentifier,
18+
keyJSON,
19+
password,
20+
adulteratedPassword,
21+
func(_ internal.EncryptedKeyExport, rawPrivKey internal.Raw) (Key, error) {
22+
return KeyFor(rawPrivKey), nil
23+
},
24+
)
25+
}
26+
27+
// ToEncryptedJSON returns encrypted JSON representing key
28+
func (key Key) ToEncryptedJSON(password string, scryptParams commonkeystore.ScryptParams) (export []byte, err error) {
29+
return internal.ToEncryptedJSON(
30+
keyTypeIdentifier,
31+
key,
32+
password,
33+
scryptParams.N,
34+
scryptParams.P,
35+
adulteratedPassword,
36+
func(id string, key Key, cryptoJSON keystore.CryptoJSON) internal.EncryptedKeyExport {
37+
return internal.EncryptedKeyExport{
38+
KeyType: id,
39+
PublicKey: hex.EncodeToString(key.PublicKey().Bytes()),
40+
Crypto: cryptoJSON,
41+
}
42+
},
43+
)
44+
}
45+
46+
func adulteratedPassword(password string) string {
47+
return "cosmoskey" + password
48+
}
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
package cosmoskey
2+
3+
import (
4+
"testing"
5+
6+
"github.com/smartcontractkit/chainlink-common/keystore/corekeys"
7+
)
8+
9+
func TestCosmosKeys_ExportImport(t *testing.T) {
10+
corekeys.RunKeyExportImportTestcase(t, createKey, decryptKey)
11+
}
12+
13+
func createKey() (corekeys.KeyType, error) {
14+
return New(), nil
15+
}
16+
17+
func decryptKey(keyJSON []byte, password string) (corekeys.KeyType, error) {
18+
return FromEncryptedJSON(keyJSON, password)
19+
}

keystore/corekeys/cosmoskey/key.go

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
package cosmoskey
2+
3+
import (
4+
"crypto/ecdsa"
5+
cryptorand "crypto/rand"
6+
"fmt"
7+
"io"
8+
"math/big"
9+
10+
"github.com/cosmos/cosmos-sdk/crypto/hd"
11+
"github.com/cosmos/cosmos-sdk/crypto/keyring"
12+
"github.com/ethereum/go-ethereum/crypto"
13+
14+
cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types"
15+
16+
"github.com/smartcontractkit/chainlink-common/keystore/internal"
17+
)
18+
19+
var secpSigningAlgo, _ = keyring.NewSigningAlgoFromString(string(hd.Secp256k1Type), []keyring.SignatureAlgo{hd.Secp256k1})
20+
21+
func KeyFor(raw internal.Raw) Key {
22+
d := big.NewInt(0).SetBytes(internal.Bytes(raw))
23+
privKey := secpSigningAlgo.Generate()(d.Bytes())
24+
return Key{
25+
raw: raw,
26+
signFn: privKey.Sign,
27+
pubKey: privKey.PubKey(),
28+
}
29+
}
30+
31+
// Key represents Cosmos key
32+
type Key struct {
33+
raw internal.Raw
34+
signFn func([]byte) ([]byte, error)
35+
pubKey cryptotypes.PubKey
36+
}
37+
38+
// New creates new Key
39+
func New() Key {
40+
return newFrom(cryptorand.Reader)
41+
}
42+
43+
// MustNewInsecure return Key
44+
func MustNewInsecure(reader io.Reader) Key {
45+
return newFrom(reader)
46+
}
47+
48+
func newFrom(reader io.Reader) Key {
49+
rawKey, err := ecdsa.GenerateKey(crypto.S256(), reader)
50+
if err != nil {
51+
panic(err)
52+
}
53+
privKey := secpSigningAlgo.Generate()(rawKey.D.Bytes())
54+
55+
return Key{
56+
raw: internal.NewRaw(rawKey.D.Bytes()),
57+
signFn: privKey.Sign,
58+
pubKey: privKey.PubKey(),
59+
}
60+
}
61+
62+
func (key Key) ID() string {
63+
return key.PublicKeyStr()
64+
}
65+
66+
func (key Key) PublicKey() (pubKey cryptotypes.PubKey) {
67+
return key.pubKey
68+
}
69+
70+
func (key Key) PublicKeyStr() string {
71+
return fmt.Sprintf("%X", key.pubKey.Bytes())
72+
}
73+
74+
func (key Key) Raw() internal.Raw { return key.raw }
75+
76+
func (key Key) Sign(data []byte) ([]byte, error) {
77+
return key.signFn(data)
78+
}

0 commit comments

Comments
 (0)