forked from hyperledger-archives/aries-framework-go
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: first change for ECDH-1PU crypto primtive
First change to introduce ECDH-1PU primitive: Includes new key/primitive types, key managers, protobufs, first change of (incomplete) key wrapping logic. Includes introduction of composite_common proto file for sharing the comment key type for ECDH-ES and ECHD-1PU. Follow up changes will include primitive factories, key templates and 1PU implementation. part of hyperledger-archives#1806 Signed-off-by: Baha Shaaban <[email protected]>
- Loading branch information
Baha Shaaban
committed
Jun 8, 2020
1 parent
a10d75a
commit 6275735
Showing
43 changed files
with
3,079 additions
and
211 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
107 changes: 107 additions & 0 deletions
107
pkg/crypto/tinkcrypto/primitive/composite/ecdh1pu/ecdh1pu.go
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,107 @@ | ||
/* | ||
Copyright SecureKey Technologies Inc. All Rights Reserved. | ||
SPDX-License-Identifier: Apache-2.0 | ||
*/ | ||
|
||
// Package ecdh1pu provides implementations of payload encryption using ECDH-1PU KW key wrapping with AEAD primitives. | ||
// | ||
// The functionality of ecdh1pu Encryption is represented as a pair of | ||
// primitives (interfaces): | ||
// | ||
// * ECDH1PUEncrypt for encryption of data and aad for a given list of recipients keys | ||
// | ||
// * ECDH1PUDecrypt for decryption of data for a certain recipient key and returning decrypted plaintext | ||
// | ||
// | ||
// Example: | ||
// | ||
// package main | ||
// | ||
// import ( | ||
// "bytes" | ||
// | ||
// "github.com/google/tink/go/keyset" | ||
// | ||
// "github.com/hyperledger/aries-framework-go/pkg/crypto/tinkcrypto/primitive/composite/ecdh1pu/subtle" | ||
// "github.com/aries-framework-go/pkg/crypto/tinkcrypto/composite/ecdh1pu" | ||
// ) | ||
// | ||
// func main() { | ||
// // create recipient side keyset handle | ||
// recKH, err := keyset.NewHandle(ecdh1pu.ECDH1PU256KWAES256GCMKeyTemplate()) | ||
// if err != nil { | ||
// //handle error | ||
// } | ||
// | ||
// // extract recipient public keyset handle and key | ||
// recPubKH, err := recKH.Public() | ||
// if err != nil { | ||
// //handle error | ||
// } | ||
// | ||
// buf := new(bytes.Buffer) | ||
// pubKeyWriter := ecdh1pu.NewWriter(buf) | ||
// err = recPubKH.WriteWithNoSecrets(pubKeyWriter) | ||
// if err != nil { | ||
// //handle error | ||
// } | ||
// | ||
// ecPubKey := new(subtle.ECPublicKey) | ||
// err := json.Unmarshal(buf.Bytes(), ecPubKey) | ||
// | ||
// // now create sender keyset handle with recipient public key (ecPubKey) | ||
// sKH, err := keyset.NewHandle(ECDH1PU256KWAES256GCMKeyTemplateWithRecipients( | ||
// []subtle.ECPublicKey{*ecPubKey})) | ||
// if err != nil { | ||
// // handle error | ||
// } | ||
// | ||
// // for more recipient keys pass in a list: []subtle.ECPublicKey{*ecPubKey1, *ecPubKey2, *ecPubKey3, etc.}) | ||
// // at least 1 recipient is required. | ||
// | ||
// // extract sender public keyset handle to encrypt | ||
// senderPubKH, err := sKH.Public() | ||
// if err != nil { | ||
// //handle error | ||
// } | ||
// | ||
// e := ecdh1pu.NewECDH1PUEncrypt(senderPubKH) | ||
// | ||
// ct, err = e.Encrypt([]byte("secret message"), []byte("some aad")) | ||
// if err != nil { | ||
// // handle error | ||
// } | ||
// | ||
// // get a handle on the decryption key material for a recipient | ||
// // this is usually reloading the recipient's keyset handle (ie: `recKH` above) from a kms | ||
// refRecKH , err := keyset.NewHandle( .....reference/rebuild `recKH` here...); | ||
// d := ecdh1pu.NewECDH1PUDecrypt(refRecKH) | ||
// | ||
// pt, err := d.Decrypt(ct) | ||
// if err != nil { | ||
// // handle error | ||
// } | ||
// } | ||
package ecdh1pu | ||
|
||
import ( | ||
"fmt" | ||
|
||
"github.com/google/tink/go/core/registry" | ||
) | ||
|
||
// TODO - find a better way to setup tink than init. | ||
// nolint: gochecknoinits | ||
func init() { | ||
// TODO - avoid the tink registry singleton (if possible). | ||
err := registry.RegisterKeyManager(newECDH1PUPrivateKeyManager()) | ||
if err != nil { | ||
panic(fmt.Sprintf("ecdh1pu.init() failed: %v", err)) | ||
} | ||
|
||
err = registry.RegisterKeyManager(newECDH1PUPublicKeyManager()) | ||
if err != nil { | ||
panic(fmt.Sprintf("ecdh1pu.init() failed: %v", err)) | ||
} | ||
} |
191 changes: 191 additions & 0 deletions
191
pkg/crypto/tinkcrypto/primitive/composite/ecdh1pu/ecdh1pu_aes_aead_private_key_manager.go
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,191 @@ | ||
/* | ||
Copyright SecureKey Technologies Inc. All Rights Reserved. | ||
SPDX-License-Identifier: Apache-2.0 | ||
*/ | ||
|
||
package ecdh1pu | ||
|
||
import ( | ||
"crypto/elliptic" | ||
"fmt" | ||
|
||
"github.com/golang/protobuf/proto" | ||
"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" | ||
|
||
"github.com/hyperledger/aries-framework-go/pkg/crypto/tinkcrypto/primitive/composite/ecdh1pu/subtle" | ||
commonpb "github.com/hyperledger/aries-framework-go/pkg/crypto/tinkcrypto/primitive/proto/common_composite_go_proto" | ||
ecdh1pupb "github.com/hyperledger/aries-framework-go/pkg/crypto/tinkcrypto/primitive/proto/ecdh1pu_aead_go_proto" | ||
) | ||
|
||
const ( | ||
ecdh1puAESPrivateKeyVersion = 0 | ||
ecdh1puAESPrivateKeyTypeURL = "type.hyperledger.org/hyperledger.aries.crypto.tink.Ecdh1puAesAeadPrivateKey" | ||
) | ||
|
||
// common errors | ||
var errInvalidECDH1PUAESPrivateKey = fmt.Errorf("ecdh1pu_aes_private_key_manager: invalid key") | ||
var errInvalidECDH1PUAESPrivateKeyFormat = fmt.Errorf("ecdh1pu_aes_private_key_manager: invalid key format") | ||
|
||
// ecdh1puAESPrivateKeyManager is an implementation of PrivateKeyManager interface. | ||
// It generates new ECDHESPrivateKey (AES) keys and produces new instances of ECDH1PUAEADCompositeDecrypt subtle. | ||
type ecdh1puAESPrivateKeyManager struct{} | ||
|
||
// Assert that ecdh1puAESPrivateKeyManager implements the PrivateKeyManager interface. | ||
var _ registry.PrivateKeyManager = (*ecdh1puAESPrivateKeyManager)(nil) | ||
|
||
// newECDH1PUPrivateKeyManager creates a new ecdh1puAESPrivateKeyManager. | ||
func newECDH1PUPrivateKeyManager() *ecdh1puAESPrivateKeyManager { | ||
return new(ecdh1puAESPrivateKeyManager) | ||
} | ||
|
||
// Primitive creates an ECDHESPrivateKey subtle for the given serialized ECDHESPrivateKey proto. | ||
func (km *ecdh1puAESPrivateKeyManager) Primitive(serializedKey []byte) (interface{}, error) { | ||
if len(serializedKey) == 0 { | ||
return nil, errInvalidECDH1PUAESPrivateKey | ||
} | ||
|
||
key := new(ecdh1pupb.Ecdh1PuAeadPrivateKey) | ||
|
||
err := proto.Unmarshal(serializedKey, key) | ||
if err != nil { | ||
return nil, errInvalidECDH1PUAESPrivateKey | ||
} | ||
|
||
curve, err := km.validateKey(key) | ||
if err != nil { | ||
return nil, errInvalidECDH1PUAESPrivateKey | ||
} | ||
|
||
pvt := hybrid.GetECPrivateKey(curve, key.KeyValue) | ||
|
||
rEnc, err := newRegisterECDH1PUAEADEncHelper(key.PublicKey.Params.EncParams.AeadEnc) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
ptFormat := key.PublicKey.Params.EcPointFormat.String() | ||
|
||
return subtle.NewECDH1PUAEADCompositeDecrypt(pvt, ptFormat, rEnc, commonpb.KeyType_EC), nil | ||
} | ||
|
||
// NewKey creates a new key according to the specification of ECDH1PUPrivateKey format. | ||
func (km *ecdh1puAESPrivateKeyManager) NewKey(serializedKeyFormat []byte) (proto.Message, error) { | ||
if len(serializedKeyFormat) == 0 { | ||
return nil, errInvalidECDH1PUAESPrivateKeyFormat | ||
} | ||
|
||
keyFormat := new(ecdh1pupb.Ecdh1PuAeadKeyFormat) | ||
|
||
err := proto.Unmarshal(serializedKeyFormat, keyFormat) | ||
if err != nil { | ||
return nil, errInvalidECDH1PUAESPrivateKeyFormat | ||
} | ||
|
||
curve, err := validateKeyFormat(keyFormat.Params) | ||
if err != nil { | ||
return nil, errInvalidECDH1PUAESPrivateKeyFormat | ||
} | ||
|
||
keyFormat.Params.KwParams.KeyType = commonpb.KeyType_EC | ||
|
||
pvt, err := hybrid.GenerateECDHKeyPair(curve) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
return &ecdh1pupb.Ecdh1PuAeadPrivateKey{ | ||
Version: ecdh1puAESPrivateKeyVersion, | ||
KeyValue: pvt.D.Bytes(), | ||
PublicKey: &ecdh1pupb.Ecdh1PuAeadPublicKey{ | ||
Version: ecdh1puAESPrivateKeyVersion, | ||
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 *ecdh1puAESPrivateKeyManager) 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, err | ||
} | ||
|
||
return &tinkpb.KeyData{ | ||
TypeUrl: ecdh1puAESPrivateKeyTypeURL, | ||
Value: serializedKey, | ||
KeyMaterialType: tinkpb.KeyData_ASYMMETRIC_PRIVATE, | ||
}, nil | ||
} | ||
|
||
// PublicKeyData returns the enclosed public key data of serializedPrivKey | ||
func (km *ecdh1puAESPrivateKeyManager) PublicKeyData(serializedPrivKey []byte) (*tinkpb.KeyData, error) { | ||
privKey := new(ecdh1pupb.Ecdh1PuAeadPrivateKey) | ||
|
||
err := proto.Unmarshal(serializedPrivKey, privKey) | ||
if err != nil { | ||
return nil, errInvalidECDH1PUAESPrivateKey | ||
} | ||
|
||
serializedPubKey, err := proto.Marshal(privKey.PublicKey) | ||
if err != nil { | ||
return nil, errInvalidECDH1PUAESPrivateKey | ||
} | ||
|
||
return &tinkpb.KeyData{ | ||
TypeUrl: ecdh1puAESPublicKeyTypeURL, | ||
Value: serializedPubKey, | ||
KeyMaterialType: tinkpb.KeyData_ASYMMETRIC_PUBLIC, | ||
}, nil | ||
} | ||
|
||
// DoesSupport indicates if this key manager supports the given key type. | ||
func (km *ecdh1puAESPrivateKeyManager) DoesSupport(typeURL string) bool { | ||
return typeURL == ecdh1puAESPrivateKeyTypeURL | ||
} | ||
|
||
// TypeURL returns the key type of keys managed by this key manager. | ||
func (km *ecdh1puAESPrivateKeyManager) TypeURL() string { | ||
return ecdh1puAESPrivateKeyTypeURL | ||
} | ||
|
||
// validateKey validates the given ECDH1PUPrivateKey and returns the KW curve. | ||
func (km *ecdh1puAESPrivateKeyManager) validateKey(key *ecdh1pupb.Ecdh1PuAeadPrivateKey) (elliptic.Curve, error) { | ||
err := keyset.ValidateKeyVersion(key.Version, ecdh1puAESPrivateKeyVersion) | ||
if err != nil { | ||
return nil, fmt.Errorf("ecdh1pu_private_key_manager: invalid key: %s", err) | ||
} | ||
|
||
return validateKeyFormat(key.PublicKey.Params) | ||
} | ||
|
||
// validateKeyFormat validates the given ECDHESKeyFormat and returns the KW Curve. | ||
func validateKeyFormat(params *ecdh1pupb.Ecdh1PuAeadParams) (elliptic.Curve, error) { | ||
c, err := hybrid.GetCurve(params.KwParams.CurveType.String()) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
km, err := registry.GetKeyManager(params.EncParams.AeadEnc.TypeUrl) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
_, err = km.NewKeyData(params.EncParams.AeadEnc.Value) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
return c, nil | ||
} |
Oops, something went wrong.