1package export23import (4 "crypto/rand"5 "errors"6 "golang.org/x/crypto/nacl/secretbox"7 "io"8)910const (11 // From the secretbox example code.12 nonceSize = 241314 // From `go doc secretbox`:15 // If in doubt, 16KB is a reasonable chunk size.16 maxChunkSize = 16 * 102417)1819func Encrypt(in io.Reader, inLen int64, out io.Writer, key *[32]byte) (int, error) {20 nwritten := 021 remaining := inLen2223 for remaining > 0 {24 // From `go doc secretbox`:25 // You must use a different nonce for each message you encrypt26 // with the same key. Since the nonce here is 192 bits long, a27 // random value provides a sufficiently small probability of28 // repeats.29 var nonce [nonceSize]byte30 if _, err := io.ReadFull(rand.Reader, nonce[:]); err != nil {31 return nwritten, err32 }3334 chunckLen := min(maxChunkSize, remaining)35 remaining -= chunckLen3637 plain := make([]byte, chunckLen)38 _, err := io.ReadFull(in, plain)39 if err != nil {40 return nwritten, err41 }4243 cipher := secretbox.Seal(nonce[:], plain, &nonce, key)44 n, err := out.Write(cipher)45 if err != nil {46 return nwritten, err47 }4849 nwritten += n50 }5152 return nwritten, nil53}5455func Decrypt(in io.Reader, inLen int64, out io.Writer, key *[32]byte) (int, error) {56 nwritten := 057 remaining := inLen5859 for remaining > nonceSize {60 var nonce [nonceSize]byte61 if _, err := io.ReadFull(in, nonce[:]); err != nil {62 return nwritten, err63 }64 remaining -= nonceSize6566 chunckLen := min(maxChunkSize, remaining)67 remaining -= chunckLen6869 chunck := make([]byte, chunckLen)70 if _, err := io.ReadFull(in, chunck); err != nil {71 return nwritten, err72 }7374 decrypted, ok := secretbox.Open(nil, chunck, &nonce, key)75 if !ok {76 return nwritten, errors.New("decryption error")77 }78 n, err := out.Write(decrypted)79 if err != nil {80 return nwritten, err81 }8283 nwritten += n84 }8586 return nwritten, nil87}