2022-02-15 03:21:56 +08:00
|
|
|
package ncutils
|
|
|
|
|
|
|
|
import (
|
|
|
|
"bytes"
|
|
|
|
"crypto/rand"
|
|
|
|
"fmt"
|
|
|
|
"io"
|
|
|
|
|
|
|
|
"golang.org/x/crypto/nacl/box"
|
|
|
|
)
|
|
|
|
|
|
|
|
const (
|
2022-02-15 09:07:22 +08:00
|
|
|
chunkSize = 16000 // 16000 bytes max message size
|
2022-02-15 03:21:56 +08:00
|
|
|
)
|
|
|
|
|
|
|
|
// BoxEncrypt - encrypts traffic box
|
|
|
|
func BoxEncrypt(message []byte, recipientPubKey *[32]byte, senderPrivateKey *[32]byte) ([]byte, error) {
|
|
|
|
var nonce [24]byte // 192 bits of randomization
|
|
|
|
if _, err := io.ReadFull(rand.Reader, nonce[:]); err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
encrypted := box.Seal(nonce[:], message, &nonce, recipientPubKey, senderPrivateKey)
|
|
|
|
return encrypted, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// BoxDecrypt - decrypts traffic box
|
|
|
|
func BoxDecrypt(encrypted []byte, senderPublicKey *[32]byte, recipientPrivateKey *[32]byte) ([]byte, error) {
|
|
|
|
var decryptNonce [24]byte
|
|
|
|
copy(decryptNonce[:], encrypted[:24])
|
|
|
|
decrypted, ok := box.Open(nil, encrypted[24:], &decryptNonce, senderPublicKey, recipientPrivateKey)
|
|
|
|
if !ok {
|
2022-02-15 09:07:22 +08:00
|
|
|
return nil, fmt.Errorf("could not decrypt message, %v", encrypted)
|
2022-02-15 03:21:56 +08:00
|
|
|
}
|
|
|
|
return decrypted, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// Chunk - chunks a message and encrypts each chunk
|
|
|
|
func Chunk(message []byte, recipientPubKey *[32]byte, senderPrivateKey *[32]byte) ([]byte, error) {
|
|
|
|
var chunks [][]byte
|
|
|
|
for i := 0; i < len(message); i += chunkSize {
|
|
|
|
end := i + chunkSize
|
|
|
|
|
|
|
|
if end > len(message) {
|
|
|
|
end = len(message)
|
|
|
|
}
|
|
|
|
|
|
|
|
encryptedMsgSlice, err := BoxEncrypt(message[i:end], recipientPubKey, senderPrivateKey)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
chunks = append(chunks, encryptedMsgSlice)
|
|
|
|
}
|
|
|
|
|
|
|
|
chunkedMsg, err := convertBytesToMsg(chunks) // encode the array into some bytes to decode on receiving end
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
return chunkedMsg, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// DeChunk - "de" chunks and decrypts a message
|
|
|
|
func DeChunk(chunkedMsg []byte, senderPublicKey *[32]byte, recipientPrivateKey *[32]byte) ([]byte, error) {
|
2022-02-15 09:04:30 +08:00
|
|
|
chunks, err := convertMsgToBytes(chunkedMsg) // convert the message to it's original chunks form
|
2022-02-15 03:21:56 +08:00
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
var totalMsg []byte
|
|
|
|
for i := range chunks {
|
|
|
|
decodedMsg, err := BoxDecrypt(chunks[i], senderPublicKey, recipientPrivateKey)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
totalMsg = append(totalMsg, decodedMsg...)
|
|
|
|
}
|
|
|
|
return totalMsg, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// == private ==
|
|
|
|
|
2022-02-15 09:04:30 +08:00
|
|
|
var splitKey = []byte("|(,)(,)|")
|
|
|
|
|
2022-02-15 03:21:56 +08:00
|
|
|
// ConvertMsgToBytes - converts a message (MQ) to it's chunked version
|
|
|
|
// decode action
|
|
|
|
func convertMsgToBytes(msg []byte) ([][]byte, error) {
|
2022-02-15 09:04:30 +08:00
|
|
|
splitMsg := bytes.Split(msg, splitKey)
|
|
|
|
return splitMsg, nil
|
2022-02-15 03:21:56 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
// ConvertBytesToMsg - converts the chunked message into a MQ message
|
|
|
|
// encode action
|
|
|
|
func convertBytesToMsg(b [][]byte) ([]byte, error) {
|
2022-02-15 09:07:22 +08:00
|
|
|
|
2022-02-15 09:04:30 +08:00
|
|
|
var buffer []byte // allocate a buffer with adequate sizing
|
|
|
|
for i := range b { // append bytes to it with key
|
|
|
|
buffer = append(buffer, b[i]...)
|
|
|
|
if i != len(b)-1 {
|
|
|
|
buffer = append(buffer, splitKey...)
|
|
|
|
}
|
2022-02-15 03:21:56 +08:00
|
|
|
}
|
2022-02-15 09:04:30 +08:00
|
|
|
return buffer, nil
|
2022-02-15 03:21:56 +08:00
|
|
|
}
|