Skip to content
This repository has been archived by the owner on Mar 27, 2024. It is now read-only.

Commit

Permalink
CL Anoncreds KMS extension (#3329)
Browse files Browse the repository at this point in the history
* extended kms API key create/rotate/export with extra options
* added CL CredDef and MasterSecret keys to localkms
* implemented CredDef pubkey export
* refactored keytemplate resolving
* added unit tests for CL keys
* re-generated kms's mock

Signed-off-by: konstantin.goncharov <konstantin.goncharov@avast.com>

Signed-off-by: konstantin.goncharov <konstantin.goncharov@avast.com>
  • Loading branch information
Konstantin Goncharov committed Aug 16, 2022
1 parent 5fa4db1 commit aab94d2
Show file tree
Hide file tree
Showing 13 changed files with 434 additions and 124 deletions.
52 changes: 36 additions & 16 deletions pkg/internal/gomocks/kms/mocks.gen.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

20 changes: 16 additions & 4 deletions pkg/kms/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,23 +19,25 @@ import (
// KeyManager manages keys and their storage for the aries framework.
type KeyManager interface {
// Create a new key/keyset/key handle for the type kt
// Some key types may require additional attributes described in `opts`
// Returns:
// - keyID of the handle
// - handle instance (to private key)
// - error if failure
Create(kt KeyType) (string, interface{}, error)
Create(kt KeyType, opts ...KeyOpts) (string, interface{}, error)
// Get key handle for the given keyID
// Returns:
// - handle instance (to private key)
// - error if failure
Get(keyID string) (interface{}, error)
// Rotate a key referenced by keyID and return a new handle of a keyset including old key and
// new key with type kt. It also returns the updated keyID as the first return value
// Some key types may require additional attributes described in `opts`
// Returns:
// - new KeyID
// - handle instance (to private key)
// - error if failure
Rotate(kt KeyType, keyID string) (string, interface{}, error)
Rotate(kt KeyType, keyID string, opts ...KeyOpts) (string, interface{}, error)
// ExportPubKeyBytes will fetch a key referenced by id then gets its public key in raw bytes and returns it.
// The key must be an asymmetric key.
// Returns:
Expand All @@ -44,17 +46,19 @@ type KeyManager interface {
ExportPubKeyBytes(keyID string) ([]byte, KeyType, error)
// CreateAndExportPubKeyBytes will create a key of type kt and export its public key in raw bytes and returns it.
// The key must be an asymmetric key.
// Some key types may require additional attributes described in `opts`
// Returns:
// - keyID of the new handle created.
// - marshalled public key []byte
// - error if it fails to export the public key bytes
CreateAndExportPubKeyBytes(kt KeyType) (string, []byte, error)
CreateAndExportPubKeyBytes(kt KeyType, opts ...KeyOpts) (string, []byte, error)
// PubKeyBytesToHandle transforms pubKey raw bytes into a key handle of keyType. This function is only a utility to
// provide a public key handle for Tink/Crypto primitive execution, it does not persist the key handle.
// Some key types may require additional attributes described in `opts`
// Returns:
// - handle instance to the public key of type keyType
// - error if keyType is not supported, the key does not match keyType or unmarshal fails
PubKeyBytesToHandle(pubKey []byte, kt KeyType) (interface{}, error)
PubKeyBytesToHandle(pubKey []byte, kt KeyType, opts ...KeyOpts) (interface{}, error)
// ImportPrivateKey will import privKey into the KMS storage for the given keyType then returns the new key id and
// the newly persisted Handle.
// 'privKey' possible types are: *ecdsa.PrivateKey and ed25519.PrivateKey
Expand Down Expand Up @@ -120,6 +124,10 @@ const (
X25519ECDHKW = "X25519ECDHKW"
// BLS12381G2 BBS+ key type value.
BLS12381G2 = "BLS12381G2"
// CLCredDef key type value.
CLCredDef = "CLCredDef"
// CLMasterSecret key type value.
CLMasterSecret = "CLMasterSecret"
)

// KeyType represents a key type supported by the KMS.
Expand Down Expand Up @@ -168,6 +176,10 @@ const (
X25519ECDHKWType = KeyType(X25519ECDHKW)
// BLS12381G2Type BBS+ key type value.
BLS12381G2Type = KeyType(BLS12381G2)
// CLCredDefType type value.
CLCredDefType = KeyType(CLCredDef)
// CLMasterSecretType key type value.
CLMasterSecretType = KeyType(CLMasterSecret)
)

// CryptoBox is a libsodium crypto service used by legacy authcrypt packer.
Expand Down
36 changes: 36 additions & 0 deletions pkg/kms/key_opts.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
/*
Copyright SecureKey Technologies Inc. All Rights Reserved.
SPDX-License-Identifier: Apache-2.0
*/

package kms

// keyOpts holds options for Create, Rotate and CreateAndExportPubKeyBytes.
type keyOpts struct {
attrs []string
}

// NewKeyOpt creates a new empty key option.
// Not to be used directly. It's intended for implementations of KeyManager interface
// Use WithAttrs() option function below instead.
func NewKeyOpt() *keyOpts { // nolint
return &keyOpts{}
}

// Attrs gets the additional attributes to be used for a key creation.
// Not to be used directly. It's intended for implementations of KeyManager interface
// Use WithAttrs() option function below instead.
func (pk *keyOpts) Attrs() []string {
return pk.attrs
}

// KeyOpts are the create key option.
type KeyOpts func(opts *keyOpts)

// WithAttrs option is for creating a key that requires extra attributes.
func WithAttrs(attrs []string) KeyOpts {
return func(opts *keyOpts) {
opts.attrs = attrs
}
}
94 changes: 94 additions & 0 deletions pkg/kms/localkms/keytemplate.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
/*
Copyright Avast Software. All Rights Reserved.
SPDX-License-Identifier: Apache-2.0
*/

package localkms

import (
"fmt"

"github.com/golang/protobuf/proto"
"github.com/google/tink/go/aead"
"github.com/google/tink/go/mac"
commonpb "github.com/google/tink/go/proto/common_go_proto"
ecdsapb "github.com/google/tink/go/proto/ecdsa_go_proto"
tinkpb "github.com/google/tink/go/proto/tink_go_proto"
"github.com/google/tink/go/signature"

"github.com/hyperledger/aries-framework-go/pkg/crypto/tinkcrypto/primitive/bbs"
"github.com/hyperledger/aries-framework-go/pkg/crypto/tinkcrypto/primitive/composite/ecdh"
"github.com/hyperledger/aries-framework-go/pkg/kms"
)

// nolint:gocyclo
func keyTemplate(keyType kms.KeyType, _ ...kms.KeyOpts) (*tinkpb.KeyTemplate, error) {
switch keyType {
case kms.AES128GCMType:
return aead.AES128GCMKeyTemplate(), nil
case kms.AES256GCMNoPrefixType:
// RAW (to support keys not generated by Tink)
return aead.AES256GCMNoPrefixKeyTemplate(), nil
case kms.AES256GCMType:
return aead.AES256GCMKeyTemplate(), nil
case kms.ChaCha20Poly1305Type:
return aead.ChaCha20Poly1305KeyTemplate(), nil
case kms.XChaCha20Poly1305Type:
return aead.XChaCha20Poly1305KeyTemplate(), nil
case kms.ECDSAP256TypeDER:
return signature.ECDSAP256KeyWithoutPrefixTemplate(), nil
case kms.ECDSAP384TypeDER:
// Since Tink's signature.ECDSAP384KeyWithoutPrefixTemplate() uses SHA_512 as the hashing function during
// signature/verification, the kms type must explicitly use SHA_384 just as IEEEP384 key template below.
// For this reason, the KMS cannot use Tink's `signature.ECDSAP384KeyWithoutPrefixTemplate()` template here.
return createECDSAKeyTemplate(ecdsapb.EcdsaSignatureEncoding_DER, commonpb.HashType_SHA384,
commonpb.EllipticCurveType_NIST_P384), nil
case kms.ECDSAP521TypeDER:
return signature.ECDSAP521KeyWithoutPrefixTemplate(), nil
case kms.ECDSAP256TypeIEEEP1363:
// JWS keys should sign using IEEE_P1363 format only (not DER format)
return createECDSAIEEE1363KeyTemplate(commonpb.HashType_SHA256, commonpb.EllipticCurveType_NIST_P256), nil
case kms.ECDSAP384TypeIEEEP1363:
return createECDSAIEEE1363KeyTemplate(commonpb.HashType_SHA384, commonpb.EllipticCurveType_NIST_P384), nil
case kms.ECDSAP521TypeIEEEP1363:
return createECDSAIEEE1363KeyTemplate(commonpb.HashType_SHA512, commonpb.EllipticCurveType_NIST_P521), nil
case kms.ED25519Type:
return signature.ED25519KeyWithoutPrefixTemplate(), nil
case kms.HMACSHA256Tag256Type:
return mac.HMACSHA256Tag256KeyTemplate(), nil
case kms.NISTP256ECDHKWType:
return ecdh.NISTP256ECDHKWKeyTemplate(), nil
case kms.NISTP384ECDHKWType:
return ecdh.NISTP384ECDHKWKeyTemplate(), nil
case kms.NISTP521ECDHKWType:
return ecdh.NISTP521ECDHKWKeyTemplate(), nil
case kms.X25519ECDHKWType:
return ecdh.X25519ECDHKWKeyTemplate(), nil
case kms.BLS12381G2Type:
return bbs.BLS12381G2KeyTemplate(), nil
default:
return nil, fmt.Errorf("getKeyTemplate: key type '%s' unrecognized", keyType)
}
}

func createECDSAIEEE1363KeyTemplate(hashType commonpb.HashType, curve commonpb.EllipticCurveType) *tinkpb.KeyTemplate {
return createECDSAKeyTemplate(ecdsapb.EcdsaSignatureEncoding_IEEE_P1363, hashType, curve)
}

func createECDSAKeyTemplate(sigEncoding ecdsapb.EcdsaSignatureEncoding, hashType commonpb.HashType,
curve commonpb.EllipticCurveType) *tinkpb.KeyTemplate {
params := &ecdsapb.EcdsaParams{
HashType: hashType,
Curve: curve,
Encoding: sigEncoding,
}
format := &ecdsapb.EcdsaKeyFormat{Params: params}
serializedFormat, _ := proto.Marshal(format) //nolint:errcheck

return &tinkpb.KeyTemplate{
TypeUrl: ecdsaPrivateKeyTypeURL,
Value: serializedFormat,
OutputPrefixType: tinkpb.OutputPrefixType_RAW,
}
}
21 changes: 21 additions & 0 deletions pkg/kms/localkms/keytemplate_factory.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
//go:build !ursa
// +build !ursa

/*
Copyright Avast Software. All Rights Reserved.
SPDX-License-Identifier: Apache-2.0
*/

package localkms

import (
tinkpb "github.com/google/tink/go/proto/tink_go_proto"

"github.com/hyperledger/aries-framework-go/pkg/kms"
)

// getKeyTemplate returns tink KeyTemplate associated with the provided keyType.
func getKeyTemplate(keyType kms.KeyType, opts ...kms.KeyOpts) (*tinkpb.KeyTemplate, error) {
return keyTemplate(keyType, opts...)
}
36 changes: 36 additions & 0 deletions pkg/kms/localkms/keytemplate_factory_ursa.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
//go:build ursa
// +build ursa

/*
Copyright Avast Software. All Rights Reserved.
SPDX-License-Identifier: Apache-2.0
*/

package localkms

import (
tinkpb "github.com/google/tink/go/proto/tink_go_proto"

clbld "github.com/hyperledger/aries-framework-go/pkg/crypto/tinkcrypto/primitive/cl/blinder"
clsgn "github.com/hyperledger/aries-framework-go/pkg/crypto/tinkcrypto/primitive/cl/signer"
"github.com/hyperledger/aries-framework-go/pkg/kms"
)

// getKeyTemplate returns tink KeyTemplate associated with the provided keyType.
func getKeyTemplate(keyType kms.KeyType, opts ...kms.KeyOpts) (*tinkpb.KeyTemplate, error) {
switch keyType {
case kms.CLCredDefType:
keyOpts := kms.NewKeyOpt()

for _, opt := range opts {
opt(keyOpts)
}

return clsgn.CredDefKeyTemplate(keyOpts.Attrs()), nil
case kms.CLMasterSecretType:
return clbld.MasterSecretKeyTemplate(), nil
default:
return keyTemplate(keyType, opts...)
}
}
Loading

0 comments on commit aab94d2

Please sign in to comment.