sophuwu.site > seks   
              132
            
             package seks

import (
	"crypto/rand"
	"encoding/base64"
	"encoding/hex"
	"errors"
	"golang.org/x/crypto/nacl/box"
	"strings"
)

func KeyGen() (string, string) {
	pub, priv, err := box.GenerateKey(rand.Reader)
	if err != nil {
		return "", ""
	}
	pubs := "public-key-" + hex.EncodeToString(pub[:])
	privs := "SECRET-KEY-" + strings.ToUpper(hex.EncodeToString(priv[:]))
	return pubs, privs
}

func ReadKey(s string) ([32]byte, error) {
	s = strings.ToLower(s)
	s = strings.TrimPrefix(s, "public-key-")
	s = strings.TrimPrefix(s, "secret-key-")
	b, err := hex.DecodeString(s)
	if err != nil {
		return [32]byte{}, errors.New("invalid key")
	}
	return [32]byte(b[0:32]), nil
}

func ran() [24]byte {
	var b [24]byte
	_, err := rand.Reader.Read(b[:])
	if err != nil {
		panic(err)
	}
	return b
}

const seksHeader = "-----BEGIN SOME ENCRYPTION KEY STUFF-----\n\n"
const seksFooter = "\n------END SOME ENCRYPTION KEY STUFF------"

func armour(b []byte) string {
	var s string
	s = base64.StdEncoding.EncodeToString(b)
	for i := 64; i < len(s); i += 64 {
		s = s[:i] + "\n" + s[i:]
	}
	return seksHeader + s + seksFooter
}

func unArmour(s string) ([]byte, error) {
	start := strings.Index(s, seksHeader) + len(seksHeader)
	end := strings.Index(s, seksFooter)
	s = s[start:end]
	s = strings.ReplaceAll(s, "\n", "")
	s = strings.ReplaceAll(s, " ", "")
	return base64.StdEncoding.DecodeString(s)
}

func EncryptString(data string, toPubKey string, fromPrivKey string) (string, error) {
	b, err := EncryptBytes([]byte(data), toPubKey, fromPrivKey)
	if err != nil {
		return "", err
	}
	return armour(b), nil
}

func EncryptArmour(b []byte, toPubKey string, fromPrivKey string) ([]byte, error) {
	b, err := EncryptBytes(b, toPubKey, fromPrivKey)
	if err != nil {
		return nil, err
	}
	return []byte(armour(b)), nil
}

func EncryptBytes(data []byte, toPubKey string, fromPrivKey string) ([]byte, error) {
	var nonce = ran()
	pubKey, err := ReadKey(toPubKey)
	if err != nil {
		return nil, err
	}
	privKey, err := ReadKey(fromPrivKey)
	if err != nil {
		return nil, err
	}
	var out []byte = nonce[:]
	return box.Seal(out, data, &nonce, &pubKey, &privKey), nil
}

func DecryptString(data string, fromPubKey string, toPrivKey string) (string, error) {
	b, err := unArmour(data)
	if err != nil {
		return "", err
	}
	out, err := DecryptBytes(b, fromPubKey, toPrivKey)
	if err != nil {
		return "", err
	}
	return string(out), nil
}

func DecryptBytes(data []byte, fromPubKey string, toPrivKey string) ([]byte, error) {
	nonce := [24]byte(data[0:24])
	pubKey, err := ReadKey(fromPubKey)
	if err != nil {
		return nil, err
	}
	privKey, err := ReadKey(toPrivKey)
	if err != nil {
		return nil, err
	}
	out, ok := box.Open(nil, data[24:], &nonce, &pubKey, &privKey)
	if !ok {
		return nil, errors.New("decryption failed")
	}
	return out, nil
}

func DecryptArmour(data []byte, fromPubKey string, toPrivKey string) ([]byte, error) {
	b, err := unArmour(string(data))
	if err != nil {
		return nil, err
	}
	out, err := DecryptBytes(b, fromPubKey, toPrivKey)
	if err != nil {
		return nil, err
	}
	return out, nil
}