126 lines
2.2 KiB
Go
126 lines
2.2 KiB
Go
|
package cryptojs
|
||
|
|
||
|
import (
|
||
|
"encoding/base64"
|
||
|
"crypto/md5"
|
||
|
"crypto/aes"
|
||
|
"crypto/cipher"
|
||
|
"math/rand"
|
||
|
"errors"
|
||
|
|
||
|
"git.meow.tf/tyler/go-pastee/evpkdf"
|
||
|
"bytes"
|
||
|
)
|
||
|
|
||
|
const (
|
||
|
keySize = 32
|
||
|
)
|
||
|
|
||
|
func Encrypt(data, passphrase string) (string, error) {
|
||
|
salt := make([]byte, 8)
|
||
|
|
||
|
if _, err := rand.Read(salt); err != nil {
|
||
|
return "", err
|
||
|
}
|
||
|
|
||
|
key := make([]byte, keySize)
|
||
|
iv := make([]byte, aes.BlockSize)
|
||
|
|
||
|
keymat := evpkdf.New(md5.New, []byte(passphrase), salt, keySize + aes.BlockSize, 1)
|
||
|
keymatbuf := bytes.NewReader(keymat)
|
||
|
|
||
|
n, err := keymatbuf.Read(key)
|
||
|
|
||
|
if n != keySize || err != nil {
|
||
|
return "", err
|
||
|
}
|
||
|
|
||
|
n, err = keymatbuf.Read(iv)
|
||
|
|
||
|
if n != aes.BlockSize || err != nil {
|
||
|
return "", err
|
||
|
}
|
||
|
|
||
|
block, err := aes.NewCipher(key)
|
||
|
|
||
|
if err != nil {
|
||
|
return "", err
|
||
|
}
|
||
|
|
||
|
padded, err := pkcs7Pad([]byte(data), block.BlockSize())
|
||
|
|
||
|
if err != nil {
|
||
|
return "", err
|
||
|
}
|
||
|
|
||
|
ciphertext := make([]byte, len(padded))
|
||
|
|
||
|
cbc := cipher.NewCBCEncrypter(block, iv)
|
||
|
cbc.CryptBlocks(ciphertext, padded)
|
||
|
|
||
|
return encode(ciphertext, salt), nil
|
||
|
}
|
||
|
|
||
|
func Decrypt(b64, passphrase string) ([]byte, error) {
|
||
|
salt, ct, err := decode(b64)
|
||
|
|
||
|
if err != nil {
|
||
|
return nil, err
|
||
|
}
|
||
|
|
||
|
key := make([]byte, keySize)
|
||
|
iv := make([]byte, aes.BlockSize)
|
||
|
|
||
|
keymat := evpkdf.New(md5.New, []byte(passphrase), salt, keySize + aes.BlockSize, 1)
|
||
|
keymatbuf := bytes.NewReader(keymat)
|
||
|
|
||
|
n, err := keymatbuf.Read(key)
|
||
|
|
||
|
if n != keySize || err != nil {
|
||
|
return nil, err
|
||
|
}
|
||
|
|
||
|
n, err = keymatbuf.Read(iv)
|
||
|
|
||
|
if n != aes.BlockSize || err != nil {
|
||
|
return nil, err
|
||
|
}
|
||
|
|
||
|
block, err := aes.NewCipher(key)
|
||
|
|
||
|
if err != nil {
|
||
|
return nil, err
|
||
|
}
|
||
|
|
||
|
cbc := cipher.NewCBCDecrypter(block, iv)
|
||
|
cbc.CryptBlocks(ct, ct)
|
||
|
|
||
|
plain, err := pkcs7Unpad(ct, block.BlockSize())
|
||
|
|
||
|
if err != nil {
|
||
|
return nil, err
|
||
|
}
|
||
|
|
||
|
return plain, nil
|
||
|
}
|
||
|
|
||
|
func encode(ct []byte, salt []byte) string {
|
||
|
b := []byte("Salted__")
|
||
|
b = append(b, salt...)
|
||
|
b = append(b, ct...)
|
||
|
return base64.StdEncoding.EncodeToString(b)
|
||
|
}
|
||
|
|
||
|
func decode(b64 string) ([]byte, []byte, error) {
|
||
|
decoded, err := base64.StdEncoding.DecodeString(b64)
|
||
|
|
||
|
if err != nil {
|
||
|
return nil, nil, err
|
||
|
}
|
||
|
|
||
|
if string(decoded[0:8]) != "Salted__" {
|
||
|
return nil, nil, errors.New("invalid data")
|
||
|
}
|
||
|
|
||
|
return decoded[8:16], decoded[16:], nil
|
||
|
}
|