-
Notifications
You must be signed in to change notification settings - Fork 88
/
keys.go
155 lines (129 loc) · 4.01 KB
/
keys.go
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
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
package config
import (
"crypto"
"crypto/rsa"
"crypto/x509"
"encoding/base64"
"encoding/pem"
"fmt"
"io"
"os"
libp2p_crypto "github.com/libp2p/go-libp2p/core/crypto"
"github.com/spf13/viper"
"github.com/bacalhau-project/bacalhau/pkg/config/types"
"github.com/bacalhau-project/bacalhau/pkg/util/closer"
)
// GetClientPublicKeyString returns a base64-encoding of the user's public ID key:
// NOTE: must be called after InitConfig() or system will panic.
func GetClientPublicKeyString() (string, error) {
userIDKey, err := loadUserIDKey()
if err != nil {
return "", err
}
return encodePublicKey(&userIDKey.PublicKey), nil
}
func GetClientPublicKey() (*rsa.PublicKey, error) {
privKey, err := loadUserIDKey()
if err != nil {
return nil, err
}
return &privKey.PublicKey, nil
}
func GetClientPrivateKey() (*rsa.PrivateKey, error) {
privKey, err := loadUserIDKey()
if err != nil {
return nil, err
}
return privKey, nil
}
func GetClientID() (string, error) {
return loadClientID()
}
func GetInstallationUserID() (string, error) {
return loadInstallationUserIDKey()
}
// loadClientID loads a hash identifying a user based on their ID key.
func loadClientID() (string, error) {
key, err := loadUserIDKey()
if err != nil {
return "", fmt.Errorf("failed to load user ID key: %w", err)
}
return convertToClientID(&key.PublicKey), nil
}
const (
sigHash = crypto.SHA256 // hash function to use for sign/verify
)
// convertToClientID converts a public key to a client ID:
func convertToClientID(key *rsa.PublicKey) string {
hash := sigHash.New()
hash.Write(key.N.Bytes())
hashBytes := hash.Sum(nil)
return fmt.Sprintf("%x", hashBytes)
}
// encodePublicKey encodes a public key as a string:
func encodePublicKey(key *rsa.PublicKey) string {
return base64.StdEncoding.EncodeToString(x509.MarshalPKCS1PublicKey(key))
}
func loadInstallationUserIDKey() (string, error) {
key := viper.GetString(types.UserInstallationID)
if key == "" {
return "", fmt.Errorf("config error: user-installation-id-key not set")
}
return key, nil
}
// loadUserIDKey loads the user ID key from whatever source is configured.
func loadUserIDKey() (*rsa.PrivateKey, error) {
keyFile := viper.GetString(types.UserKeyPath)
if keyFile == "" {
return nil, fmt.Errorf("config error: user-id-key not set")
}
file, err := os.Open(keyFile)
if err != nil {
return nil, fmt.Errorf("failed to open user ID key file: %w", err)
}
defer closer.CloseWithLogOnError("user ID key file", file)
keyBytes, err := io.ReadAll(file)
if err != nil {
return nil, fmt.Errorf("failed to read user ID key file: %w", err)
}
keyBlock, _ := pem.Decode(keyBytes)
if keyBlock == nil {
return nil, fmt.Errorf("failed to decode user ID key file %q", keyFile)
}
// TODO: #3159 Add support for both rsa _and_ ecdsa private keys, see crypto.PrivateKey.
// Since we have access to the private key we can hack it by signing a
// message twice and comparing them, rather than verifying directly.
// ecdsaKey, err = x509.ParseECPrivateKey(keyBlock.Bytes)
// if err != nil {
// return nil, fmt.Errorf("failed to parse user: %w", err)
// }
key, err := x509.ParsePKCS1PrivateKey(keyBlock.Bytes)
if err != nil {
return nil, fmt.Errorf("failed to parse user ID key file: %w", err)
}
return key, nil
}
func GetLibp2pPrivKey() (libp2p_crypto.PrivKey, error) {
return loadLibp2pPrivKey()
}
func loadLibp2pPrivKey() (libp2p_crypto.PrivKey, error) {
keyFile := viper.GetString(types.UserLibp2pKeyPath)
if keyFile == "" {
return nil, fmt.Errorf("config error: libp2p private key not set")
}
keyBytes, err := os.ReadFile(keyFile)
if err != nil {
return nil, fmt.Errorf("failed to read private key: %v", err)
}
// base64 decode keyBytes
b64, err := base64.StdEncoding.DecodeString(string(keyBytes))
if err != nil {
return nil, fmt.Errorf("failed to decode private key: %v", err)
}
// parse the private key
key, err := libp2p_crypto.UnmarshalPrivateKey(b64)
if err != nil {
return nil, fmt.Errorf("failed to parse private key: %v", err)
}
return key, nil
}