69 lines
1.4 KiB
Go
69 lines
1.4 KiB
Go
package crypto
|
|
|
|
import (
|
|
"crypto/rand"
|
|
"encoding/hex"
|
|
|
|
"golang.org/x/crypto/chacha20"
|
|
"golang.org/x/crypto/nacl/box"
|
|
)
|
|
|
|
func GenerateKey() ([]byte, []byte, error) {
|
|
public, private, err := box.GenerateKey(rand.Reader)
|
|
if err != nil {
|
|
return nil, nil, err
|
|
}
|
|
return public[:], private[:], err
|
|
}
|
|
|
|
func CalcSharedKey(devicePublicB64, clientPrivateB64 string) ([]byte, error) {
|
|
var sharedKey, publicKey, privateKey [32]byte
|
|
if _, err := hex.Decode(publicKey[:], []byte(devicePublicB64)); err != nil {
|
|
return nil, err
|
|
}
|
|
if _, err := hex.Decode(privateKey[:], []byte(clientPrivateB64)); err != nil {
|
|
return nil, err
|
|
}
|
|
box.Precompute(&sharedKey, &publicKey, &privateKey)
|
|
return sharedKey[:], nil
|
|
}
|
|
|
|
func Encode(src, key32 []byte) ([]byte, error) {
|
|
dst := make([]byte, len(src)+8)
|
|
|
|
if _, err := rand.Read(dst[:8]); err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
nonce12 := make([]byte, 12)
|
|
copy(nonce12[4:], dst[:8])
|
|
|
|
c, err := chacha20.NewUnauthenticatedCipher(key32, nonce12)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
c.XORKeyStream(dst[8:], src)
|
|
|
|
return dst, nil
|
|
}
|
|
|
|
func Decode(src, key32 []byte) ([]byte, error) {
|
|
return DecodeNonce(src[8:], src[:8], key32)
|
|
}
|
|
|
|
func DecodeNonce(src, nonce8, key32 []byte) ([]byte, error) {
|
|
nonce12 := make([]byte, 12)
|
|
copy(nonce12[4:], nonce8)
|
|
|
|
c, err := chacha20.NewUnauthenticatedCipher(key32, nonce12)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
dst := make([]byte, len(src))
|
|
c.XORKeyStream(dst, src)
|
|
|
|
return dst, nil
|
|
}
|