sophuwu.site > seks   
              131
            
             package seks

import (
	"crypto/rand"
	"crypto/sha256"
	"fmt"
	"golang.org/x/crypto/nacl/secretbox"
	"strings"
)

func ran() []byte {
	var b [32]byte
	_, err := rand.Reader.Read(b[:])
	if err != nil {
		panic(err)
	}
	return b[:]
}
func hashPasswd(salt []byte, passwd []byte) [32]byte {
	hash := sha256.New()
	hash.Write(passwd)
	hash.Write(salt)
	var key [32]byte
	copy(key[:], hash.Sum(nil))
	return key
}

const seksArmour = `0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz-_`
const seksHeader = `-----BEGIN SOME ENCRYPTION KEY STUFF-----`
const seksFooter = `------END SOME ENCRYPTION KEY STUFF------`

func armour(b []byte) string {
	var s string
	var n uint = 0
	var m uint = 0
	for i := 0; i < 3-len(b)%3; i++ {
		b = append(b, 0)
	}
	for _, c := range b {
		n |= uint(c) << uint(m*8)
		m++
		if m == 3 {
			for j := 0; j < 4; j++ {
				s += string(seksArmour[n&63])
				n >>= 6
			}
			m = 0
			n = 0
		}
	}
	// add newlines
	for i := 0; i < len(s); i += len(seksHeader) {
		s = s[:i] + "\n" + s[i:]
	}
	return seksHeader + s + "\n" + seksFooter + "\n"
}

func Encrypt(data string, password string) string {
	return armour(encryptBytes([]byte(data), password))
}
func encryptBytes(data []byte, password string) []byte {
	salt := ran()
	key := hashPasswd(salt, []byte(password))
	var nonce = [24]byte(ran()[0:24])
	salt = append(salt[:], nonce[:]...)
	return secretbox.Seal(salt, data, &nonce, &key)
}

func Decrypt(data string, password string) (string, error) {
	b, err := unArmour(data)
	if err != nil {
		return "", err
	}
	return string(decryptBytes(b, password)), nil
}

func decryptBytes(encrypted []byte, pass string) []byte {
	salt := encrypted[:32]
	nonce := [24]byte(encrypted[32 : 32+24])
	key := hashPasswd(salt[:], []byte(pass))
	decrypted := make([]byte, len(encrypted)-32-24)
	decrypted, boolEnlon := secretbox.Open(nil, encrypted[32+24:], &nonce, &key)
	if boolEnlon != true {
		return nil
	}
	return decrypted
}

func unArmour(s string) ([]byte, error) {
	s = strings.ReplaceAll(s, "\t", "")
	s = strings.ReplaceAll(s, "\n", "")
	s = strings.TrimPrefix(s, seksHeader)
	s = strings.TrimSuffix(s, seksFooter)
	s = strings.ReplaceAll(s, " ", "")
	var b []byte
	var n uint = 0
	var m uint = 0
	for _, c := range s {
		i := index(c)
		if i < 0 {
			return nil, fmt.Errorf("SEKS UnMarshall: invalid character")
		}
		n |= uint(i) << uint(m*6)
		m++
		if m == 4 {
			for j := 0; j < 3; j++ {
				b = append(b, byte(n&255))
				n >>= 8
			}
			m = 0
			n = 0
		}
	}
	if len(b) > 0 { // remove padding
		for i := 0; i < 3; i++ {
			if b[len(b)-1] == 0 {
				b = b[:len(b)-1]
			}
		}
	}
	return b, nil
}

func index(c rune) (j int) {
	for j, v := range seksArmour {
		if v == c {
			return j
		}
	}
	return -1
}