Files
hsp.go/hsp/crypt.go

91 lines
1.7 KiB
Go

package hsp
import (
"crypto/aes"
"crypto/cipher"
"crypto/rand"
"io"
"golang.org/x/crypto/curve25519"
)
type KeyPair struct {
Private [32]byte
Public [32]byte
}
func NewKeyPair(publicKey, privateKey [32]byte) *KeyPair {
return &KeyPair{
Public: publicKey,
Private: privateKey,
}
}
func GenerateKeyPair() (pair *KeyPair, err error) {
privateKey := make([]byte, 32)
publicKey := make([]byte, 32)
_, err = rand.Read(privateKey[:])
if err != nil {
return
}
privateKey[0] &= 248
privateKey[31] &= 127
privateKey[31] |= 64
curve25519.ScalarBaseMult((*[32]byte)(publicKey), (*[32]byte)(privateKey))
return NewKeyPair([32]byte(publicKey), [32]byte(privateKey)), nil
}
func DeriveSharedKey(privateKey, peerPublicKey [32]byte) (sharedKey [32]byte, err error) {
generated, err := curve25519.X25519(privateKey[:], peerPublicKey[:])
if err != nil {
return
}
sharedKey = [32]byte(generated)
return
}
func Encrypt(key []byte, data []byte) (encrypted []byte, nonce []byte, err error) {
block, err := aes.NewCipher(key)
if err != nil {
return nil, nil, err
}
aesGCM, err := cipher.NewGCM(block)
if err != nil {
return nil, nil, err
}
nonce = make([]byte, aesGCM.NonceSize())
_, err = io.ReadFull(rand.Reader, nonce)
if err != nil {
return nil, nil, err
}
encrypted = aesGCM.Seal(nil, nonce, data, nil)
return encrypted, nonce, nil
}
func Decrypt(key []byte, nonce []byte, encrypted []byte) (data []byte, err error) {
block, err := aes.NewCipher(key)
if err != nil {
return nil, err
}
aesGCM, err := cipher.NewGCM(block)
if err != nil {
return nil, err
}
data, err = aesGCM.Open(nil, nonce, encrypted, nil)
if err != nil {
return nil, err
}
return data, nil
}