//frodo provides an API to use the frodo key encryption mechanism.
// Frodo is a quantum-resistant key encapsulation cryptosystem.
// Circl's package frodo640shake implements the variant FrodoKEM-640 with SHAKE.

package frodo

// Public key is 9616 bytes long
// Private key is 19888 bytes long
// Encrypted key is 9720 bytes long
// The key which is encrypted is 16 bytes long

// When the keys need to be encoded as strings:
// Frodo Public keys are encoded Base64
// Frodo private keys are encoded Hex

import "github.com/cloudflare/circl/kem/frodo/frodo640shake"


// Outputs:
//	-[9616]byte: Public Key bytes
//	-[19888]byte: Private key bytes
//	-error
func GetNewRandomPublicPrivateFrodoKeys()([9616]byte, [19888]byte, error){

	newSchemeObject := frodo640shake.Scheme()

	publicKeyObject, privateKeyObject, err := newSchemeObject.GenerateKeyPair()
	if (err != nil) { return [9616]byte{}, [19888]byte{}, err }

	publicKeyBytes, err := publicKeyObject.MarshalBinary()
	if (err != nil) { return [9616]byte{}, [19888]byte{}, err }

	privateKeyBytes, err := privateKeyObject.MarshalBinary()
	if (err != nil) { return [9616]byte{}, [19888]byte{}, err }

	publicKeyArray := [9616]byte(publicKeyBytes)
	privateKeyArray := [19888]byte(privateKeyBytes)

	return publicKeyArray, privateKeyArray, nil
}


//Outputs:
//	-[16]byte: Newly generated key (unencrypted)
//	-[9720]byte: Frodo Encrypted Key
//	-error
func EncryptNewRandomKeyWithFrodo(recipientPublicKey [9616]byte)([16]byte, [9720]byte, error){

	var publicKeyObject frodo640shake.PublicKey

	publicKeyObject.Unpack(recipientPublicKey[:])

	var newKey [16]byte
	var ciphertext [9720]byte

	publicKeyObject.EncapsulateTo(ciphertext[:], newKey[:], nil)

	return newKey, ciphertext, nil
}


//Outputs:
//	-bool: Able to decrypt
//	-[16]byte: Decrypted key
//	-error
func DecryptFrodoEncryptedKey(inputEncryptedKey [9720]byte, privateKey [19888]byte)(bool, [16]byte, error){

	var privateKeyObject frodo640shake.PrivateKey

	privateKeyObject.Unpack(privateKey[:])

	var sharedKey [16]byte

	privateKeyObject.DecapsulateTo(sharedKey[:], inputEncryptedKey[:])

	return true, sharedKey, nil
}

