Skip to content

Instantly share code, notes, and snippets.

@ykcab
Created August 28, 2020 15:16
Show Gist options
  • Save ykcab/b5815cce8672778a57b344b6b691baf2 to your computer and use it in GitHub Desktop.
Save ykcab/b5815cce8672778a57b344b6b691baf2 to your computer and use it in GitHub Desktop.
package main
import (
"crypto/cipher"
"crypto/rand"
"fmt"
"io"
"log"
"os"
"strings"
"sync"
"golang.org/x/crypto/chacha20poly1305"
)
type wrapeEncryptor struct {
c cipher.AEAD
w io.Writer
errChan chan error
wg sync.WaitGroup
operation string
}
type wrapDecryptor struct {
c cipher.AEAD
w io.Writer
errChan chan error
wg sync.WaitGroup
}
type fileProcessor struct {
we wrapeEncryptor
wd wrapDecryptor
operation string
}
func (we *wrapeEncryptor) concurentencryptwrite(jobs <-chan []byte, result chan<- int, wg *sync.WaitGroup) {
defer wg.Done()
nonce := make([]byte, we.c.NonceSize())
_, err := rand.Read(nonce)
if err != nil {
we.errChan <- err
result <- 1
}
for j := range jobs {
enc := we.c.Seal(nil, nonce, j, nil)
e := append(nonce, enc...)
n, werr := we.w.Write(e)
if err != nil {
we.errChan <- werr
}
result <- n
}
}
func (wd *wrapDecryptor) concurentdecryptwrite(jobs <-chan []byte, result chan<- int, wg *sync.WaitGroup) {
defer wg.Done()
for j := range jobs {
nonce, ct := j[:wd.c.NonceSize()], j[wd.c.NonceSize():]
dec, err := wd.c.Open(nil, nonce, ct, nil)
if err != nil {
log.Fatal(err)
}
n, werr := wd.w.Write(dec)
if err != nil {
log.Fatal(werr)
}
result <- n
}
}
func (fp *fileProcessor) processFile(file io.Reader) int {
jobs := make(chan []byte)
results := make(chan int)
wg := new(sync.WaitGroup)
switch fp.operation {
case "ENCRYPT":
for w := 1; w <= 3; w++ {
wg.Add(1)
go fp.we.concurentencryptwrite(jobs, results, wg)
}
case "DECRYPT":
for w := 1; w <= 3; w++ {
wg.Add(1)
go fp.wd.concurentdecryptwrite(jobs, results, wg)
}
}
buf := make([]byte, 64*1024)
go func() {
defer close(jobs)
for {
n, err := file.Read(buf)
if err != nil && err != io.EOF {
log.Fatalln(err)
}
if err == io.EOF {
break
}
jobs <- buf[:n]
}
}()
go func() {
wg.Wait()
close(results)
}()
// Add up the results from the results channel.
counts := 0
for v := range results {
counts += v
}
return counts
}
func main() {
fp := &fileProcessor{}
key := make([]byte, 32)
_, err := rand.Read(key)
if err != nil {
log.Fatal(err)
}
fp.we.w, err = os.Create("file.enc")
if err != nil {
fmt.Println(err)
return
}
fp.we.c, err = chacha20poly1305.NewX(key)
if err != nil {
log.Fatal(err)
}
// b, err := os.Open("/etc/dictionaries-common/words")
// if err != nil {
// log.Fatal(err)
// }
b := strings.NewReader("Hello, world!")
fp.operation = "ENCRYPT"
_ = fp.processFile(b)
//decrypt the file
encfile, err := os.Open("file.enc")
if err != nil {
log.Fatal(err)
}
fp.operation = "DECRYPT"
fp.wd.w, err = os.Create("decrypted.txt")
if err != nil {
log.Fatal(err)
}
fp.wd.c, err = chacha20poly1305.NewX(key)
if err != nil {
log.Fatal(err)
}
i2 := fp.processFile(encfile)
fmt.Println("decrypted size: ", i2)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment