74 lines
1.5 KiB
Go
74 lines
1.5 KiB
Go
package linkpearl
|
|
|
|
import (
|
|
"crypto/aes"
|
|
"crypto/cipher"
|
|
"crypto/rand"
|
|
"encoding/base64"
|
|
"errors"
|
|
"io"
|
|
)
|
|
|
|
// Crypter is special object that handles data encryption and decryption
|
|
// apart from Matrix' standard encryption.
|
|
// It can encrypt and decrypt arbitrary data using secret key (password)
|
|
type Crypter struct {
|
|
cipher cipher.AEAD
|
|
nonceSize int
|
|
}
|
|
|
|
// ErrInvalidData returned in provided encrypted data (ciphertext) is invalid
|
|
var ErrInvalidData = errors.New("invalid data")
|
|
|
|
// NewCrypter creates new Crypter
|
|
func NewCrypter(secretkey string) (*Crypter, error) {
|
|
block, err := aes.NewCipher([]byte(secretkey))
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
aesGCM, err := cipher.NewGCM(block)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return &Crypter{
|
|
cipher: aesGCM,
|
|
nonceSize: aesGCM.NonceSize(),
|
|
}, nil
|
|
}
|
|
|
|
// Decrypt data
|
|
func (c *Crypter) Decrypt(data string) (string, error) {
|
|
datab, err := base64.StdEncoding.DecodeString(data)
|
|
if err != nil {
|
|
return data, err
|
|
}
|
|
|
|
if len(datab) < c.nonceSize {
|
|
return data, ErrInvalidData
|
|
}
|
|
|
|
nonce := datab[:c.nonceSize]
|
|
ciphertext := datab[c.nonceSize:]
|
|
|
|
plaintext, err := c.cipher.Open(nil, nonce, ciphertext, nil)
|
|
if err != nil {
|
|
return data, err
|
|
}
|
|
|
|
return string(plaintext), nil
|
|
}
|
|
|
|
// Encrypt data
|
|
func (c *Crypter) Encrypt(data string) (string, error) {
|
|
nonce := make([]byte, c.nonceSize)
|
|
_, err := io.ReadFull(rand.Reader, nonce)
|
|
if err != nil {
|
|
return data, err
|
|
}
|
|
|
|
encrypted := c.cipher.Seal(nonce, nonce, []byte(data), nil)
|
|
return base64.StdEncoding.EncodeToString(encrypted), nil
|
|
}
|