|
@@ -0,0 +1,105 @@
|
|
|
+package ncutils
|
|
|
+
|
|
|
+import (
|
|
|
+ "bytes"
|
|
|
+ "crypto/rand"
|
|
|
+ "fmt"
|
|
|
+ "io"
|
|
|
+
|
|
|
+ "golang.org/x/crypto/nacl/box"
|
|
|
+)
|
|
|
+
|
|
|
+const (
|
|
|
+ chunkSize = 16000 // 16000 bytes max message size
|
|
|
+)
|
|
|
+
|
|
|
+// 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 {
|
|
|
+ return nil, fmt.Errorf("could not decrypt message, %v", encrypted)
|
|
|
+ }
|
|
|
+ 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) {
|
|
|
+ chunks, err := convertMsgToBytes(chunkedMsg) // convert the message to it's original chunks form
|
|
|
+ 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 ==
|
|
|
+
|
|
|
+var splitKey = []byte("|(,)(,)|")
|
|
|
+
|
|
|
+// ConvertMsgToBytes - converts a message (MQ) to it's chunked version
|
|
|
+// decode action
|
|
|
+func convertMsgToBytes(msg []byte) ([][]byte, error) {
|
|
|
+ splitMsg := bytes.Split(msg, splitKey)
|
|
|
+ return splitMsg, nil
|
|
|
+}
|
|
|
+
|
|
|
+// ConvertBytesToMsg - converts the chunked message into a MQ message
|
|
|
+// encode action
|
|
|
+func convertBytesToMsg(b [][]byte) ([]byte, error) {
|
|
|
+
|
|
|
+ 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...)
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return buffer, nil
|
|
|
+}
|