podman

Форк
0
253 строки · 8.1 Кб
1
package libtrust
2

3
import (
4
	"crypto"
5
	"crypto/ecdsa"
6
	"crypto/rsa"
7
	"crypto/x509"
8
	"encoding/json"
9
	"encoding/pem"
10
	"errors"
11
	"fmt"
12
	"io"
13
)
14

15
// PublicKey is a generic interface for a Public Key.
16
type PublicKey interface {
17
	// KeyType returns the key type for this key. For elliptic curve keys,
18
	// this value should be "EC". For RSA keys, this value should be "RSA".
19
	KeyType() string
20
	// KeyID returns a distinct identifier which is unique to this Public Key.
21
	// The format generated by this library is a base32 encoding of a 240 bit
22
	// hash of the public key data divided into 12 groups like so:
23
	//    ABCD:EFGH:IJKL:MNOP:QRST:UVWX:YZ23:4567:ABCD:EFGH:IJKL:MNOP
24
	KeyID() string
25
	// Verify verifyies the signature of the data in the io.Reader using this
26
	// Public Key. The alg parameter should identify the digital signature
27
	// algorithm which was used to produce the signature and should be
28
	// supported by this public key. Returns a nil error if the signature
29
	// is valid.
30
	Verify(data io.Reader, alg string, signature []byte) error
31
	// CryptoPublicKey returns the internal object which can be used as a
32
	// crypto.PublicKey for use with other standard library operations. The type
33
	// is either *rsa.PublicKey or *ecdsa.PublicKey
34
	CryptoPublicKey() crypto.PublicKey
35
	// These public keys can be serialized to the standard JSON encoding for
36
	// JSON Web Keys. See section 6 of the IETF draft RFC for JOSE JSON Web
37
	// Algorithms.
38
	MarshalJSON() ([]byte, error)
39
	// These keys can also be serialized to the standard PEM encoding.
40
	PEMBlock() (*pem.Block, error)
41
	// The string representation of a key is its key type and ID.
42
	String() string
43
	AddExtendedField(string, interface{})
44
	GetExtendedField(string) interface{}
45
}
46

47
// PrivateKey is a generic interface for a Private Key.
48
type PrivateKey interface {
49
	// A PrivateKey contains all fields and methods of a PublicKey of the
50
	// same type. The MarshalJSON method also outputs the private key as a
51
	// JSON Web Key, and the PEMBlock method outputs the private key as a
52
	// PEM block.
53
	PublicKey
54
	// PublicKey returns the PublicKey associated with this PrivateKey.
55
	PublicKey() PublicKey
56
	// Sign signs the data read from the io.Reader using a signature algorithm
57
	// supported by the private key. If the specified hashing algorithm is
58
	// supported by this key, that hash function is used to generate the
59
	// signature otherwise the the default hashing algorithm for this key is
60
	// used. Returns the signature and identifier of the algorithm used.
61
	Sign(data io.Reader, hashID crypto.Hash) (signature []byte, alg string, err error)
62
	// CryptoPrivateKey returns the internal object which can be used as a
63
	// crypto.PublicKey for use with other standard library operations. The
64
	// type is either *rsa.PublicKey or *ecdsa.PublicKey
65
	CryptoPrivateKey() crypto.PrivateKey
66
}
67

68
// FromCryptoPublicKey returns a libtrust PublicKey representation of the given
69
// *ecdsa.PublicKey or *rsa.PublicKey. Returns a non-nil error when the given
70
// key is of an unsupported type.
71
func FromCryptoPublicKey(cryptoPublicKey crypto.PublicKey) (PublicKey, error) {
72
	switch cryptoPublicKey := cryptoPublicKey.(type) {
73
	case *ecdsa.PublicKey:
74
		return fromECPublicKey(cryptoPublicKey)
75
	case *rsa.PublicKey:
76
		return fromRSAPublicKey(cryptoPublicKey), nil
77
	default:
78
		return nil, fmt.Errorf("public key type %T is not supported", cryptoPublicKey)
79
	}
80
}
81

82
// FromCryptoPrivateKey returns a libtrust PrivateKey representation of the given
83
// *ecdsa.PrivateKey or *rsa.PrivateKey. Returns a non-nil error when the given
84
// key is of an unsupported type.
85
func FromCryptoPrivateKey(cryptoPrivateKey crypto.PrivateKey) (PrivateKey, error) {
86
	switch cryptoPrivateKey := cryptoPrivateKey.(type) {
87
	case *ecdsa.PrivateKey:
88
		return fromECPrivateKey(cryptoPrivateKey)
89
	case *rsa.PrivateKey:
90
		return fromRSAPrivateKey(cryptoPrivateKey), nil
91
	default:
92
		return nil, fmt.Errorf("private key type %T is not supported", cryptoPrivateKey)
93
	}
94
}
95

96
// UnmarshalPublicKeyPEM parses the PEM encoded data and returns a libtrust
97
// PublicKey or an error if there is a problem with the encoding.
98
func UnmarshalPublicKeyPEM(data []byte) (PublicKey, error) {
99
	pemBlock, _ := pem.Decode(data)
100
	if pemBlock == nil {
101
		return nil, errors.New("unable to find PEM encoded data")
102
	} else if pemBlock.Type != "PUBLIC KEY" {
103
		return nil, fmt.Errorf("unable to get PublicKey from PEM type: %s", pemBlock.Type)
104
	}
105

106
	return pubKeyFromPEMBlock(pemBlock)
107
}
108

109
// UnmarshalPublicKeyPEMBundle parses the PEM encoded data as a bundle of
110
// PEM blocks appended one after the other and returns a slice of PublicKey
111
// objects that it finds.
112
func UnmarshalPublicKeyPEMBundle(data []byte) ([]PublicKey, error) {
113
	pubKeys := []PublicKey{}
114

115
	for {
116
		var pemBlock *pem.Block
117
		pemBlock, data = pem.Decode(data)
118
		if pemBlock == nil {
119
			break
120
		} else if pemBlock.Type != "PUBLIC KEY" {
121
			return nil, fmt.Errorf("unable to get PublicKey from PEM type: %s", pemBlock.Type)
122
		}
123

124
		pubKey, err := pubKeyFromPEMBlock(pemBlock)
125
		if err != nil {
126
			return nil, err
127
		}
128

129
		pubKeys = append(pubKeys, pubKey)
130
	}
131

132
	return pubKeys, nil
133
}
134

135
// UnmarshalPrivateKeyPEM parses the PEM encoded data and returns a libtrust
136
// PrivateKey or an error if there is a problem with the encoding.
137
func UnmarshalPrivateKeyPEM(data []byte) (PrivateKey, error) {
138
	pemBlock, _ := pem.Decode(data)
139
	if pemBlock == nil {
140
		return nil, errors.New("unable to find PEM encoded data")
141
	}
142

143
	var key PrivateKey
144

145
	switch {
146
	case pemBlock.Type == "RSA PRIVATE KEY":
147
		rsaPrivateKey, err := x509.ParsePKCS1PrivateKey(pemBlock.Bytes)
148
		if err != nil {
149
			return nil, fmt.Errorf("unable to decode RSA Private Key PEM data: %s", err)
150
		}
151
		key = fromRSAPrivateKey(rsaPrivateKey)
152
	case pemBlock.Type == "EC PRIVATE KEY":
153
		ecPrivateKey, err := x509.ParseECPrivateKey(pemBlock.Bytes)
154
		if err != nil {
155
			return nil, fmt.Errorf("unable to decode EC Private Key PEM data: %s", err)
156
		}
157
		key, err = fromECPrivateKey(ecPrivateKey)
158
		if err != nil {
159
			return nil, err
160
		}
161
	default:
162
		return nil, fmt.Errorf("unable to get PrivateKey from PEM type: %s", pemBlock.Type)
163
	}
164

165
	addPEMHeadersToKey(pemBlock, key.PublicKey())
166

167
	return key, nil
168
}
169

170
// UnmarshalPublicKeyJWK unmarshals the given JSON Web Key into a generic
171
// Public Key to be used with libtrust.
172
func UnmarshalPublicKeyJWK(data []byte) (PublicKey, error) {
173
	jwk := make(map[string]interface{})
174

175
	err := json.Unmarshal(data, &jwk)
176
	if err != nil {
177
		return nil, fmt.Errorf(
178
			"decoding JWK Public Key JSON data: %s\n", err,
179
		)
180
	}
181

182
	// Get the Key Type value.
183
	kty, err := stringFromMap(jwk, "kty")
184
	if err != nil {
185
		return nil, fmt.Errorf("JWK Public Key type: %s", err)
186
	}
187

188
	switch {
189
	case kty == "EC":
190
		// Call out to unmarshal EC public key.
191
		return ecPublicKeyFromMap(jwk)
192
	case kty == "RSA":
193
		// Call out to unmarshal RSA public key.
194
		return rsaPublicKeyFromMap(jwk)
195
	default:
196
		return nil, fmt.Errorf(
197
			"JWK Public Key type not supported: %q\n", kty,
198
		)
199
	}
200
}
201

202
// UnmarshalPublicKeyJWKSet parses the JSON encoded data as a JSON Web Key Set
203
// and returns a slice of Public Key objects.
204
func UnmarshalPublicKeyJWKSet(data []byte) ([]PublicKey, error) {
205
	rawKeys, err := loadJSONKeySetRaw(data)
206
	if err != nil {
207
		return nil, err
208
	}
209

210
	pubKeys := make([]PublicKey, 0, len(rawKeys))
211

212
	for _, rawKey := range rawKeys {
213
		pubKey, err := UnmarshalPublicKeyJWK(rawKey)
214
		if err != nil {
215
			return nil, err
216
		}
217
		pubKeys = append(pubKeys, pubKey)
218
	}
219

220
	return pubKeys, nil
221
}
222

223
// UnmarshalPrivateKeyJWK unmarshals the given JSON Web Key into a generic
224
// Private Key to be used with libtrust.
225
func UnmarshalPrivateKeyJWK(data []byte) (PrivateKey, error) {
226
	jwk := make(map[string]interface{})
227

228
	err := json.Unmarshal(data, &jwk)
229
	if err != nil {
230
		return nil, fmt.Errorf(
231
			"decoding JWK Private Key JSON data: %s\n", err,
232
		)
233
	}
234

235
	// Get the Key Type value.
236
	kty, err := stringFromMap(jwk, "kty")
237
	if err != nil {
238
		return nil, fmt.Errorf("JWK Private Key type: %s", err)
239
	}
240

241
	switch {
242
	case kty == "EC":
243
		// Call out to unmarshal EC private key.
244
		return ecPrivateKeyFromMap(jwk)
245
	case kty == "RSA":
246
		// Call out to unmarshal RSA private key.
247
		return rsaPrivateKeyFromMap(jwk)
248
	default:
249
		return nil, fmt.Errorf(
250
			"JWK Private Key type not supported: %q\n", kty,
251
		)
252
	}
253
}
254

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.