// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
////////////////////////////////////////////////////////////////////////////////

// Package testutil provides test utilities.
package testutil

import (
	"crypto/ecdsa"
	"crypto/rand"
	"fmt"

	"github.com/golang/protobuf/proto"
	"github.com/google/tink/go/aead"
	"github.com/google/tink/go/mac"
	"github.com/google/tink/go/signature"
	"github.com/google/tink/go/subtle/random"
	"github.com/google/tink/go/subtle"
	"github.com/google/tink/go/tink"
	gcmpb "github.com/google/tink/proto/aes_gcm_go_proto"
	commonpb "github.com/google/tink/proto/common_go_proto"
	ecdsapb "github.com/google/tink/proto/ecdsa_go_proto"
	hmacpb "github.com/google/tink/proto/hmac_go_proto"
	tinkpb "github.com/google/tink/proto/tink_go_proto"
)

// DummyAeadKeyManager is a dummy implementation of the KeyManager interface.
// It returns DummyAead when GetPrimitive() functions are called.
type DummyAeadKeyManager struct{}

var _ tink.KeyManager = (*DummyAeadKeyManager)(nil)

// GetPrimitiveFromSerializedKey constructs a primitive instance for the key given in
// serializedKey, which must be a serialized key protocol buffer handled by this manager.
func (km *DummyAeadKeyManager) GetPrimitiveFromSerializedKey(serializedKey []byte) (interface{}, error) {
	return new(DummyAead), nil
}

// GetPrimitiveFromKey constructs a primitive instance for the key given in {@code key}.
func (km *DummyAeadKeyManager) GetPrimitiveFromKey(m proto.Message) (interface{}, error) {
	return new(DummyAead), nil
}

// NewKeyFromSerializedKeyFormat Generates a new key according to specification in {@code serializedKeyFormat},
// which must be a serialized key format protocol buffer handled by this manager.
func (km *DummyAeadKeyManager) NewKeyFromSerializedKeyFormat(serializedKeyFormat []byte) (proto.Message, error) {
	return nil, fmt.Errorf("not implemented")
}

// NewKeyFromKeyFormat generates a new key according to specification in {@code keyFormat}.
func (km *DummyAeadKeyManager) NewKeyFromKeyFormat(m proto.Message) (proto.Message, error) {
	return nil, fmt.Errorf("not implemented")
}

// NewKeyData generates a new {@code KeyData} according to specification in {@code serializedkeyFormat}.
func (km *DummyAeadKeyManager) NewKeyData(serializedKeyFormat []byte) (*tinkpb.KeyData, error) {
	return nil, fmt.Errorf("not implemented")
}

// DoesSupport returns true iff this KeyManager supports key type identified by {@code typeURL}.
func (km *DummyAeadKeyManager) DoesSupport(typeURL string) bool {
	return typeURL == aead.AesGcmTypeURL
}

// GetKeyType returns the type URL.
func (km *DummyAeadKeyManager) GetKeyType() string {
	return aead.AesGcmTypeURL
}

// DummyAead is a dummy implementation of Aead interface.
type DummyAead struct{}

// Encrypt encrypts the plaintext.
func (a *DummyAead) Encrypt(plaintext []byte, additionalData []byte) ([]byte, error) {
	return nil, fmt.Errorf("dummy aead encrypt")
}

// Decrypt decrypts the ciphertext.
func (a *DummyAead) Decrypt(ciphertext []byte, additionalData []byte) ([]byte, error) {
	return nil, fmt.Errorf("dummy aead decrypt")
}

// DummyMac is a dummy implementation of Mac interface.
type DummyMac struct {
	Name string
}

// ComputeMac Computes message authentication code (MAC) for {@code data}.
func (h *DummyMac) ComputeMac(data []byte) ([]byte, error) {
	var m []byte
	m = append(m, data...)
	m = append(m, h.Name...)
	return m, nil
}

// VerifyMac verifies whether {@code mac} is a correct authentication code (MAC) for {@code data}.
func (h *DummyMac) VerifyMac(mac []byte, data []byte) (bool, error) {
	return true, nil
}

// NewTestAesGcmKeyset creates a new Keyset containing an AesGcmKey.
func NewTestAesGcmKeyset(primaryOutputPrefixType tinkpb.OutputPrefixType) *tinkpb.Keyset {
	keyData := NewAesGcmKeyData(16)
	return NewTestKeyset(keyData, primaryOutputPrefixType)
}

// NewTestHmacKeyset creates a new Keyset containing a HmacKey.
func NewTestHmacKeyset(tagSize uint32,
	primaryOutputPrefixType tinkpb.OutputPrefixType) *tinkpb.Keyset {
	keyData := NewHmacKeyData(commonpb.HashType_SHA256, tagSize)
	return NewTestKeyset(keyData, primaryOutputPrefixType)
}

// NewTestKeyset creates a new test Keyset.
func NewTestKeyset(keyData *tinkpb.KeyData,
	primaryOutputPrefixType tinkpb.OutputPrefixType) *tinkpb.Keyset {
	primaryKey := tink.CreateKey(keyData, tinkpb.KeyStatusType_ENABLED, 42, primaryOutputPrefixType)
	rawKey := tink.CreateKey(keyData, tinkpb.KeyStatusType_ENABLED, 43, tinkpb.OutputPrefixType_RAW)
	legacyKey := tink.CreateKey(keyData, tinkpb.KeyStatusType_ENABLED, 44, tinkpb.OutputPrefixType_LEGACY)
	tinkKey := tink.CreateKey(keyData, tinkpb.KeyStatusType_ENABLED, 45, tinkpb.OutputPrefixType_TINK)
	crunchyKey := tink.CreateKey(keyData, tinkpb.KeyStatusType_ENABLED, 46, tinkpb.OutputPrefixType_CRUNCHY)
	keys := []*tinkpb.Keyset_Key{primaryKey, rawKey, legacyKey, tinkKey, crunchyKey}
	return tink.CreateKeyset(primaryKey.KeyId, keys)
}

// NewDummyKey returns a dummy key that doesn't contain actual key material.
func NewDummyKey(keyID int, status tinkpb.KeyStatusType, outputPrefixType tinkpb.OutputPrefixType) *tinkpb.Keyset_Key {
	return &tinkpb.Keyset_Key{
		KeyData:          new(tinkpb.KeyData),
		Status:           status,
		KeyId:            uint32(keyID),
		OutputPrefixType: outputPrefixType,
	}
}

// NewEcdsaPrivateKey creates an EcdsaPrivateKey with a randomly generated key material.
func NewEcdsaPrivateKey(hashType commonpb.HashType, curve commonpb.EllipticCurveType) *ecdsapb.EcdsaPrivateKey {
	curveName := commonpb.EllipticCurveType_name[int32(curve)]
	priv, _ := ecdsa.GenerateKey(subtle.GetCurve(curveName), rand.Reader)
	params := signature.NewEcdsaParams(hashType,
		curve,
		ecdsapb.EcdsaSignatureEncoding_DER)
	publicKey := signature.NewEcdsaPublicKey(signature.EcdsaVerifyKeyVersion,
		params, priv.X.Bytes(), priv.Y.Bytes())
	return signature.NewEcdsaPrivateKey(signature.EcdsaSignKeyVersion,
		publicKey, priv.D.Bytes())
}

// NewEcdsaPrivateKeyData creates a KeyData containing an EcdsaPrivateKey with a randomly generated key material.
func NewEcdsaPrivateKeyData(hashType commonpb.HashType, curve commonpb.EllipticCurveType) *tinkpb.KeyData {
	key := NewEcdsaPrivateKey(hashType, curve)
	serializedKey, _ := proto.Marshal(key)
	return &tinkpb.KeyData{
		TypeUrl:         signature.EcdsaSignTypeURL,
		Value:           serializedKey,
		KeyMaterialType: tinkpb.KeyData_ASYMMETRIC_PRIVATE,
	}
}

// NewEcdsaPublicKey creates an EcdsaPublicKey with the specified parameters.
func NewEcdsaPublicKey(hashType commonpb.HashType, curve commonpb.EllipticCurveType) *ecdsapb.EcdsaPublicKey {
	return NewEcdsaPrivateKey(hashType, curve).PublicKey
}

// NewAesGcmKey creates a randomly generated AesGcmKey.
func NewAesGcmKey(keySize uint32) *gcmpb.AesGcmKey {
	keyValue := random.GetRandomBytes(keySize)
	return aead.NewAesGcmKey(aead.AesGcmKeyVersion, keyValue)
}

// NewAesGcmKeyData creates a KeyData containing a randomly generated AesGcmKey.
func NewAesGcmKeyData(keySize uint32) *tinkpb.KeyData {
	keyValue := random.GetRandomBytes(keySize)
	key := aead.NewAesGcmKey(aead.AesGcmKeyVersion, keyValue)
	serializedKey, _ := proto.Marshal(key)
	return tink.CreateKeyData(aead.AesGcmTypeURL, serializedKey, tinkpb.KeyData_SYMMETRIC)
}

// NewSerializedAesGcmKey creates a AesGcmKey with randomly generated key material.
func NewSerializedAesGcmKey(keySize uint32) []byte {
	key := NewAesGcmKey(keySize)
	serializedKey, err := proto.Marshal(key)
	if err != nil {
		panic(fmt.Sprintf("cannot marshal AesGcmKey: %s", err))
	}
	return serializedKey
}

// NewHmacKey creates a new HmacKey with the specified parameters.
func NewHmacKey(hashType commonpb.HashType, tagSize uint32) *hmacpb.HmacKey {
	params := mac.NewHmacParams(hashType, tagSize)
	keyValue := random.GetRandomBytes(20)
	return mac.NewHmacKey(params, mac.HmacKeyVersion, keyValue)
}

// NewHmacKeyFormat creates a new HmacKeyFormat with the specified parameters.
func NewHmacKeyFormat(hashType commonpb.HashType, tagSize uint32) *hmacpb.HmacKeyFormat {
	params := mac.NewHmacParams(hashType, tagSize)
	keySize := uint32(20)
	return mac.NewHmacKeyFormat(params, keySize)
}

// NewHmacKeysetManager returns a new KeysetManager that contains a HmacKey.
func NewHmacKeysetManager() *tink.KeysetManager {
	macTemplate := mac.HmacSha256Tag128KeyTemplate()
	manager := tink.NewKeysetManager(macTemplate, nil, nil)
	err := manager.Rotate()
	if err != nil {
		panic(fmt.Sprintf("cannot rotate keyset manager: %s", err))
	}
	return manager
}

// NewHmacKeyData returns a new KeyData that contains a HmacKey.
func NewHmacKeyData(hashType commonpb.HashType, tagSize uint32) *tinkpb.KeyData {
	key := NewHmacKey(hashType, tagSize)
	serializedKey, _ := proto.Marshal(key)
	return &tinkpb.KeyData{
		TypeUrl:         mac.HmacTypeURL,
		Value:           serializedKey,
		KeyMaterialType: tinkpb.KeyData_SYMMETRIC,
	}
}
