
// nacl provides functions to encrypt and decrypt data using Nacl

package nacl

// Public/Private keys are 32 bytes long
// Encrypted key is 80 bytes long

// When the keys need to be encoded as strings:
// Nacl public keys are encoded Base64
// Nacl private keys are encoded hex

import "seekia/internal/encoding"

import "golang.org/x/crypto/nacl/box"

import "crypto/rand"
import "errors"

func VerifyNaclPublicKeyString(inputKey string)bool{

	_, err := ReadNaclPublicKeyString(inputKey)
	if (err != nil){
		return false
	}
	return true
}

func ReadNaclPublicKeyString(inputKey string)([32]byte, error){

	decodedBytes, err := encoding.DecodeBase64StringToBytes(inputKey)
	if (err != nil) {
		return [32]byte{}, errors.New("ReadNaclPublicKeyString called with invalid key: " + inputKey)
	}

	if (len(decodedBytes) != 32){
		return [32]byte{}, errors.New("ReadNaclPublicKeyString called with invalid key: " + inputKey)
	}
	
	publicKey := [32]byte(decodedBytes)

	return publicKey, nil
}

func GetNewRandomPublicNaclKey()([32]byte, error){

	var naclPublicKeyArray [32]byte

	_, err := rand.Read(naclPublicKeyArray[:])
	if (err != nil) { return [32]byte{}, err }

	return naclPublicKeyArray, nil
}

func GetNewRandomPublicPrivateNaclKeys()([32]byte, [32]byte, error){

	publicKeyArray, privateKeyArray, err := box.GenerateKey(rand.Reader)
	if (err != nil) { return [32]byte{}, [32]byte{}, err }

	return *publicKeyArray, *privateKeyArray, nil
}

//Outputs:
//	-[80]byte: Nacl Encrypted Key
//	-error
func EncryptKeyWithNacl(recipientPublicKey [32]byte, keyToEncrypt [32]byte)([80]byte, error){

	encryptedKeyBytes, err := box.SealAnonymous(nil, keyToEncrypt[:], &recipientPublicKey, nil)
	if (err != nil) { return [80]byte{}, err }

	if (len(encryptedKeyBytes) != 80){
		return [80]byte{}, errors.New("box.SealAnonymous returning invalid length encryptedKey.")
	}

	encryptedKeyArray := [80]byte(encryptedKeyBytes)

	return encryptedKeyArray, nil
}

//Outputs:
//	-bool: Able to decrypt
//	-[32]byte: Decrypted key
//	-error
func DecryptNaclEncryptedKey(encryptedKey [80]byte, recipientPublicKey [32]byte, recipientPrivateKey [32]byte)(bool, [32]byte, error) {

	decryptedKey, success := box.OpenAnonymous(nil, encryptedKey[:], &recipientPublicKey, &recipientPrivateKey)
	if (success == false) {
		return false, [32]byte{}, nil
	}

	if (len(decryptedKey) != 32){
		return false, [32]byte{}, errors.New("Invalid Nacl encrypted key length after decrypt.")
	}

	decryptedKeyArray := [32]byte(decryptedKey)

	return true, decryptedKeyArray, nil
}


