This repository has been archived by the owner on Mar 27, 2024. It is now read-only.
/
ecdh_nistpkw_private_key_manager.go
220 lines (180 loc) · 7.26 KB
/
ecdh_nistpkw_private_key_manager.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
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
/*
Copyright SecureKey Technologies Inc. All Rights Reserved.
SPDX-License-Identifier: Apache-2.0
*/
package ecdh
import (
"crypto/elliptic"
"errors"
"fmt"
"github.com/google/tink/go/core/registry"
hybrid "github.com/google/tink/go/hybrid/subtle"
"github.com/google/tink/go/keyset"
tinkpb "github.com/google/tink/go/proto/tink_go_proto"
"google.golang.org/protobuf/proto"
"github.com/hyperledger/aries-framework-go/component/kmscrypto/crypto/tinkcrypto/primitive/composite"
"github.com/hyperledger/aries-framework-go/component/kmscrypto/crypto/tinkcrypto/primitive/composite/ecdh/subtle"
ecdhpb "github.com/hyperledger/aries-framework-go/component/kmscrypto/crypto/tinkcrypto/primitive/proto/ecdh_aead_go_proto"
)
const (
nistpECDHKWPrivateKeyVersion = 0
nistpECDHKWPrivateKeyTypeURL = "type.hyperledger.org/hyperledger.aries.crypto.tink.NistPEcdhKwPrivateKey"
)
// common errors.
var (
errInvalidNISTPECDHKWPrivateKey = errors.New("nistpkw_ecdh_private_key_manager: invalid key")
errInvalidNISTPECDHKWPrivateKeyFormat = errors.New("nistpkw_ecdh_private_key_manager: invalid key format")
)
// nistPECDHKWPrivateKeyManager is an implementation of PrivateKeyManager interface for NIST P curved key wrapping.
// It generates new ECDHPrivateKey (NIST P KW) keys and produces new instances of ECDHAEADCompositeDecrypt subtle.
type nistPECDHKWPrivateKeyManager struct{}
// Assert that nistPECDHKWPrivateKeyManager implements the PrivateKeyManager interface.
var _ registry.PrivateKeyManager = (*nistPECDHKWPrivateKeyManager)(nil)
// newECDHNISTPAESPrivateKeyManager creates a new nistPECDHKWPrivateKeyManager.
func newECDHNISTPAESPrivateKeyManager() *nistPECDHKWPrivateKeyManager {
return new(nistPECDHKWPrivateKeyManager)
}
// Primitive creates an ECDHESPrivateKey subtle for the given serialized ECDHESPrivateKey proto.
func (km *nistPECDHKWPrivateKeyManager) Primitive(serializedKey []byte) (interface{}, error) {
if len(serializedKey) == 0 {
return nil, errInvalidNISTPECDHKWPrivateKey
}
key := new(ecdhpb.EcdhAeadPrivateKey)
err := proto.Unmarshal(serializedKey, key)
if err != nil {
return nil, errInvalidNISTPECDHKWPrivateKey
}
_, err = km.validateKey(key)
if err != nil {
return nil, errInvalidNISTPECDHKWPrivateKey
}
rEnc, err := composite.NewRegisterCompositeAEADEncHelper(key.PublicKey.Params.EncParams.AeadEnc)
if err != nil {
return nil, fmt.Errorf("nistpkw_ecdh_private_key_manager: NewRegisterCompositeAEADEncHelper "+
"failed: %w", err)
}
return subtle.NewECDHAEADCompositeDecrypt(rEnc, key.PublicKey.Params.EncParams.CEK), nil
}
// NewKey creates a new key according to the specification of ECDHESPrivateKey format.
func (km *nistPECDHKWPrivateKeyManager) NewKey(serializedKeyFormat []byte) (proto.Message, error) {
if len(serializedKeyFormat) == 0 {
return nil, errInvalidNISTPECDHKWPrivateKeyFormat
}
keyFormat := new(ecdhpb.EcdhAeadKeyFormat)
err := proto.Unmarshal(serializedKeyFormat, keyFormat)
if err != nil {
return nil, errInvalidNISTPECDHKWPrivateKeyFormat
}
curve, err := validateKeyFormat(keyFormat.Params)
if err != nil {
return nil, errInvalidNISTPECDHKWPrivateKeyFormat
}
// If CEK is present, this key is used for primitive execution only, ie this is a dummy key, not meant to be stored.
// This avoids creating a real key to improve performance.
if keyFormat.Params.EncParams.CEK != nil {
return &ecdhpb.EcdhAeadPrivateKey{
Version: nistpECDHKWPrivateKeyVersion,
KeyValue: []byte{},
PublicKey: &ecdhpb.EcdhAeadPublicKey{
Version: nistpECDHKWPrivateKeyVersion,
Params: keyFormat.Params,
X: []byte{},
Y: []byte{},
},
}, nil
}
pvt, err := hybrid.GenerateECDHKeyPair(curve)
if err != nil {
return nil, fmt.Errorf("nistpkw_ecdh_private_key_manager: GenerateECDHKeyPair failed: %w", err)
}
return &ecdhpb.EcdhAeadPrivateKey{
Version: nistpECDHKWPrivateKeyVersion,
KeyValue: pvt.D.Bytes(),
PublicKey: &ecdhpb.EcdhAeadPublicKey{
Version: nistpECDHKWPrivateKeyVersion,
Params: keyFormat.Params,
X: pvt.PublicKey.Point.X.Bytes(),
Y: pvt.PublicKey.Point.Y.Bytes(),
},
}, nil
}
// NewKeyData creates a new KeyData according to the specification of ECDHESPrivateKey Format.
// It should be used solely by the key management API.
func (km *nistPECDHKWPrivateKeyManager) NewKeyData(serializedKeyFormat []byte) (*tinkpb.KeyData, error) {
key, err := km.NewKey(serializedKeyFormat)
if err != nil {
return nil, err
}
serializedKey, err := proto.Marshal(key)
if err != nil {
return nil, fmt.Errorf("nistpkw_ecdh_private_key_manager: Proto.Marshal failed: %w", err)
}
return &tinkpb.KeyData{
TypeUrl: nistpECDHKWPrivateKeyTypeURL,
Value: serializedKey,
KeyMaterialType: tinkpb.KeyData_ASYMMETRIC_PRIVATE,
}, nil
}
// PublicKeyData returns the enclosed public key data of serializedPrivKey.
func (km *nistPECDHKWPrivateKeyManager) PublicKeyData(serializedPrivKey []byte) (*tinkpb.KeyData, error) {
privKey := new(ecdhpb.EcdhAeadPrivateKey)
err := proto.Unmarshal(serializedPrivKey, privKey)
if err != nil {
return nil, errInvalidNISTPECDHKWPrivateKey
}
serializedPubKey, err := proto.Marshal(privKey.PublicKey)
if err != nil {
return nil, errInvalidNISTPECDHKWPrivateKey
}
return &tinkpb.KeyData{
TypeUrl: nistpECDHKWPublicKeyTypeURL,
Value: serializedPubKey,
KeyMaterialType: tinkpb.KeyData_ASYMMETRIC_PUBLIC,
}, nil
}
// DoesSupport indicates if this key manager supports the given key type.
func (km *nistPECDHKWPrivateKeyManager) DoesSupport(typeURL string) bool {
return typeURL == nistpECDHKWPrivateKeyTypeURL
}
// TypeURL returns the key type of keys managed by this key manager.
func (km *nistPECDHKWPrivateKeyManager) TypeURL() string {
return nistpECDHKWPrivateKeyTypeURL
}
// validateKey validates the given ECDHPrivateKey and returns the KW curve.
func (km *nistPECDHKWPrivateKeyManager) validateKey(key *ecdhpb.EcdhAeadPrivateKey) (elliptic.Curve, error) {
err := keyset.ValidateKeyVersion(key.Version, nistpECDHKWPrivateKeyVersion)
if err != nil {
return nil, fmt.Errorf("nistpkw_ecdh_private_key_manager: invalid key: %w", err)
}
return validateKeyFormat(key.PublicKey.Params)
}
// validateKeyFormat validates the given ECDHESKeyFormat and returns the KW Curve.
func validateKeyFormat(params *ecdhpb.EcdhAeadParams) (elliptic.Curve, error) {
var (
c elliptic.Curve
err error
)
// if CEK is set, then curve is unknown, ie this is not a recipient key, it's a primitive execution key for
// Encryption/Decryption. Set P-384 curve for key generation
if params.EncParams.CEK == nil {
c, err = hybrid.GetCurve(params.KwParams.CurveType.String())
if err != nil {
return nil, fmt.Errorf("nistpkw_ecdh_private_key_manager: invalid key: %w", err)
}
} else {
c = elliptic.P384()
}
km, err := registry.GetKeyManager(params.EncParams.AeadEnc.TypeUrl)
if err != nil {
return nil, fmt.Errorf("nistpkw_ecdh_private_key_manager: GetKeyManager error: %w", err)
}
_, err = km.NewKeyData(params.EncParams.AeadEnc.Value)
if err != nil {
return nil, fmt.Errorf("nistpkw_ecdh_private_key_manager: NewKeyData error: %w", err)
}
if params.KwParams.KeyType.String() != ecdhpb.KeyType_EC.String() {
return nil, fmt.Errorf("nistpkw_ecdh_private_key_manager: invalid key type %v",
params.KwParams.KeyType)
}
return c, nil
}