This repository has been archived by the owner on Mar 27, 2024. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 160
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: Add Default implementation for JWE Anoncrypt
This change introduces a new Tink key template that supports encrypting a plaintext into a JWE protected by the (recipient) public key of the template and also supports decrypting the protected JWE using the (recipient's) private key of the template. closes #1469 closes #1472 closes #1470 Signed-off-by: Baha Shaaban <[email protected]>
- Loading branch information
Baha Shaaban
committed
Mar 31, 2020
1 parent
b14f446
commit 516c2ad
Showing
19 changed files
with
1,626 additions
and
1 deletion.
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
200 changes: 200 additions & 0 deletions
200
pkg/crypto/tinkcrypto/primitive/jwe/ecdhes/ecdh_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,200 @@ | ||
/* | ||
Copyright SecureKey Technologies Inc. All Rights Reserved. | ||
SPDX-License-Identifier: Apache-2.0 | ||
*/ | ||
|
||
package ecdhes | ||
|
||
import ( | ||
"fmt" | ||
|
||
"github.com/golang/protobuf/proto" | ||
"github.com/google/tink/go/core/registry" | ||
"github.com/google/tink/go/keyset" | ||
"github.com/google/tink/go/subtle/hybrid" | ||
tinkpb "github.com/google/tink/proto/tink_go_proto" | ||
|
||
"github.com/hyperledger/aries-framework-go/pkg/crypto/tinkcrypto/primitive/jwe/subtle/ecdhes" | ||
ecdhespb "github.com/hyperledger/aries-framework-go/pkg/crypto/tinkcrypto/primitive/proto/ecdhes_aead_go_proto" | ||
) | ||
|
||
const ( | ||
ecdhesPrivateKeyVersion = 0 | ||
ecdhesPrivateKeyTypeURL = "type.googleapis.com/google.crypto.tink.EcdhesAeadPrivateKey" | ||
) | ||
|
||
// common errors | ||
var errInvalidECDHESPrivateKey = fmt.Errorf("ecdhes_private_key_manager: invalid key") | ||
var errInvalidECDHESPrivateKeyFormat = fmt.Errorf("ecdhes_private_key_manager: invalid key format") | ||
|
||
// ecdhesPrivateKeyManager is an implementation of PrivateKeyManager interface. | ||
// It generates new ECDHESPrivateKey keys and produces new instances of ECDHESPrivateKey subtle. | ||
type ecdhesPrivateKeyManager struct{} | ||
|
||
// Assert that ecdhesPrivateKeyManager implements the PrivateKeyManager interface. | ||
var _ registry.PrivateKeyManager = (*ecdhesPrivateKeyManager)(nil) | ||
|
||
// newECDHESPrivateKeyManager creates a new aesGcmKeyManager. | ||
func newECDHESPrivateKeyManager() *ecdhesPrivateKeyManager { | ||
return new(ecdhesPrivateKeyManager) | ||
} | ||
|
||
// Primitive creates an ECDHESPrivateKey subtle for the given serialized ECDHESPrivateKey proto. | ||
func (km *ecdhesPrivateKeyManager) Primitive(serializedKey []byte) (interface{}, error) { | ||
if len(serializedKey) == 0 { | ||
return nil, errInvalidECDHESPrivateKey | ||
} | ||
|
||
key := new(ecdhespb.EcdhesAeadPrivateKey) | ||
|
||
err := proto.Unmarshal(serializedKey, key) | ||
if err != nil { | ||
return nil, errInvalidECDHESPrivateKey | ||
} | ||
|
||
err = km.validateKey(key) | ||
if err != nil { | ||
return nil, errInvalidECDHESPrivateKey | ||
} | ||
|
||
curve, err := hybrid.GetCurve(key.PublicKey.Params.KemParams.CurveType.String()) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
pvt := hybrid.GetECPrivateKey(curve, key.KeyValue) | ||
|
||
rDem, err := newRegisterECDHESEncHelper(key.PublicKey.Params.DemParams.AeadDem) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
ptFormat := key.PublicKey.Params.EcPointFormat.String() | ||
|
||
return ecdhes.NewECDHESDecrypt(pvt, ptFormat, rDem) | ||
} | ||
|
||
// NewKey creates a new key according to the specification of ECDHESPrivateKey format. | ||
func (km *ecdhesPrivateKeyManager) NewKey(serializedKeyFormat []byte) (proto.Message, error) { | ||
if len(serializedKeyFormat) == 0 { | ||
return nil, errInvalidECDHESPrivateKeyFormat | ||
} | ||
|
||
keyFormat := new(ecdhespb.EcdhesAeadKeyFormat) | ||
|
||
err := proto.Unmarshal(serializedKeyFormat, keyFormat) | ||
if err != nil { | ||
return nil, errInvalidECDHESPrivateKeyFormat | ||
} | ||
|
||
err = km.validateKeyFormat(keyFormat) | ||
if err != nil { | ||
return nil, errInvalidECDHESPrivateKeyFormat | ||
} | ||
|
||
curve, err := hybrid.GetCurve(keyFormat.Params.KemParams.CurveType.String()) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
pvt, err := hybrid.GenerateECDHKeyPair(curve) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
return &ecdhespb.EcdhesAeadPrivateKey{ | ||
Version: ecdhesPrivateKeyVersion, | ||
KeyValue: pvt.D.Bytes(), | ||
PublicKey: &ecdhespb.EcdhesAeadPublicKey{ | ||
Version: ecdhesPrivateKeyVersion, | ||
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 *ecdhesPrivateKeyManager) 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: ecdhesPrivateKeyTypeURL, | ||
Value: serializedKey, | ||
KeyMaterialType: tinkpb.KeyData_ASYMMETRIC_PRIVATE, | ||
}, nil | ||
} | ||
|
||
func (km *ecdhesPrivateKeyManager) PublicKeyData(serializedPrivKey []byte) (*tinkpb.KeyData, error) { | ||
privKey := new(ecdhespb.EcdhesAeadPrivateKey) | ||
|
||
err := proto.Unmarshal(serializedPrivKey, privKey) | ||
if err != nil { | ||
return nil, errInvalidECDHESPrivateKey | ||
} | ||
|
||
serializedPubKey, err := proto.Marshal(privKey.PublicKey) | ||
if err != nil { | ||
return nil, errInvalidECDHESPrivateKey | ||
} | ||
|
||
return &tinkpb.KeyData{ | ||
TypeUrl: ecdhesPublicKeyTypeURL, | ||
Value: serializedPubKey, | ||
KeyMaterialType: tinkpb.KeyData_ASYMMETRIC_PUBLIC, | ||
}, nil | ||
} | ||
|
||
// DoesSupport indicates if this key manager supports the given key type. | ||
func (km *ecdhesPrivateKeyManager) DoesSupport(typeURL string) bool { | ||
return typeURL == ecdhesPrivateKeyTypeURL | ||
} | ||
|
||
// TypeURL returns the key type of keys managed by this key manager. | ||
func (km *ecdhesPrivateKeyManager) TypeURL() string { | ||
return ecdhesPrivateKeyTypeURL | ||
} | ||
|
||
// validateKey validates the given ECDHESPrivateKey. | ||
func (km *ecdhesPrivateKeyManager) validateKey(key *ecdhespb.EcdhesAeadPrivateKey) error { | ||
err := keyset.ValidateKeyVersion(key.Version, ecdhesPrivateKeyVersion) | ||
if err != nil { | ||
return fmt.Errorf("ecdhes_private_key_manager: invalid key: %s", err) | ||
} | ||
|
||
return checkECDHESParams(key.PublicKey.Params) | ||
} | ||
|
||
// validateKeyFormat validates the given ECDSAKeyFormat. | ||
func (km *ecdhesPrivateKeyManager) validateKeyFormat(format *ecdhespb.EcdhesAeadKeyFormat) error { | ||
return checkECDHESParams(format.Params) | ||
} | ||
|
||
func checkECDHESParams(params *ecdhespb.EcdhesAeadParams) error { | ||
_, err := hybrid.GetCurve(params.KemParams.CurveType.String()) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
km, err := registry.GetKeyManager(params.DemParams.AeadDem.TypeUrl) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
_, err = km.NewKeyData(params.DemParams.AeadDem.Value) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
return nil | ||
} |
115 changes: 115 additions & 0 deletions
115
pkg/crypto/tinkcrypto/primitive/jwe/ecdhes/ecdh_aead_public_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,115 @@ | ||
/* | ||
Copyright SecureKey Technologies Inc. All Rights Reserved. | ||
SPDX-License-Identifier: Apache-2.0 | ||
*/ | ||
|
||
package ecdhes | ||
|
||
import ( | ||
"fmt" | ||
"math/big" | ||
|
||
"github.com/golang/protobuf/proto" | ||
"github.com/google/tink/go/core/registry" | ||
"github.com/google/tink/go/keyset" | ||
"github.com/google/tink/go/subtle/hybrid" | ||
tinkpb "github.com/google/tink/proto/tink_go_proto" | ||
|
||
sbutleecdhes "github.com/hyperledger/aries-framework-go/pkg/crypto/tinkcrypto/primitive/jwe/subtle/ecdhes" | ||
ecdhespb "github.com/hyperledger/aries-framework-go/pkg/crypto/tinkcrypto/primitive/proto/ecdhes_aead_go_proto" | ||
) | ||
|
||
const ( | ||
ecdhesPublicKeyVersion = 0 | ||
ecdhesPublicKeyTypeURL = "type.googleapis.com/google.crypto.tink.EcdhesAeadPublicKey" | ||
) | ||
|
||
// common errors | ||
var errInvalidECDHESPublicKey = fmt.Errorf("ecdhes_public_key_manager: invalid key") | ||
|
||
// ecdhesPublicKeyManager is an implementation of KeyManager interface. | ||
// It generates new ECDHESPublicKey keys and produces new instances of ECDHESPublicKey subtle. | ||
type ecdhesPublicKeyManager struct{} | ||
|
||
// Assert that ecdhesPublicKeyManager implements the KeyManager interface. | ||
var _ registry.KeyManager = (*ecdhesPublicKeyManager)(nil) | ||
|
||
// newECDHESPublicKeyManager creates a new aesGcmKeyManager. | ||
func newECDHESPublicKeyManager() *ecdhesPublicKeyManager { | ||
return new(ecdhesPublicKeyManager) | ||
} | ||
|
||
// Primitive creates an ECDHESPublicKey subtle for the given serialized ECDHESPublicKey proto. | ||
func (km *ecdhesPublicKeyManager) Primitive(serializedKey []byte) (interface{}, error) { | ||
if len(serializedKey) == 0 { | ||
return nil, errInvalidECDHESPublicKey | ||
} | ||
|
||
key := new(ecdhespb.EcdhesAeadPublicKey) | ||
|
||
err := proto.Unmarshal(serializedKey, key) | ||
if err != nil { | ||
return nil, errInvalidECDHESPublicKey | ||
} | ||
|
||
err = km.validateKey(key) | ||
if err != nil { | ||
return nil, errInvalidECDHESPublicKey | ||
} | ||
|
||
curve, err := hybrid.GetCurve(key.Params.KemParams.CurveType.String()) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
pub := hybrid.ECPublicKey{ | ||
Curve: curve, | ||
Point: hybrid.ECPoint{ | ||
X: new(big.Int).SetBytes(key.X), | ||
Y: new(big.Int).SetBytes(key.Y), | ||
}, | ||
} | ||
|
||
rDem, err := newRegisterECDHESEncHelper(key.Params.DemParams.AeadDem) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
ptFormat := key.Params.EcPointFormat.String() | ||
|
||
// TODO add support for multiple 'recipient' keys somehow. | ||
// 1 key template is for 1 recipient only. A possible solution would be to update Encrypt() interface to take | ||
// a list of recipients public keys. | ||
return sbutleecdhes.NewECDHESEncrypt(&pub, ptFormat, rDem) | ||
} | ||
|
||
// DoesSupport indicates if this key manager supports the given key type. | ||
func (km *ecdhesPublicKeyManager) DoesSupport(typeURL string) bool { | ||
return typeURL == ecdhesPublicKeyTypeURL | ||
} | ||
|
||
// TypeURL returns the key type of keys managed by this key manager. | ||
func (km *ecdhesPublicKeyManager) TypeURL() string { | ||
return ecdhesPublicKeyTypeURL | ||
} | ||
|
||
// NewKey is not implemented for public key manager. | ||
func (km *ecdhesPublicKeyManager) NewKey(serializedKeyFormat []byte) (proto.Message, error) { | ||
return nil, fmt.Errorf("ecdhes_public_key_manager: NewKey not implemented") | ||
} | ||
|
||
// NewKeyData is not implemented for public key manager. | ||
func (km *ecdhesPublicKeyManager) NewKeyData(serializedKeyFormat []byte) (*tinkpb.KeyData, error) { | ||
return nil, fmt.Errorf("ecdhes_public_key_manager: NewKeyData not implemented") | ||
} | ||
|
||
// validateKey validates the given ECDHESPublicKey. | ||
func (km *ecdhesPublicKeyManager) validateKey(key *ecdhespb.EcdhesAeadPublicKey) error { | ||
err := keyset.ValidateKeyVersion(key.Version, ecdhesPublicKeyVersion) | ||
if err != nil { | ||
return fmt.Errorf("ecdhes_public_key_manager: invalid key: %s", err) | ||
} | ||
|
||
return checkECDHESParams(key.Params) | ||
} |
Oops, something went wrong.