Skip to content

Instantly share code, notes, and snippets.

@honmaple
Created July 16, 2023 03:25
Show Gist options
  • Save honmaple/8b4bc8498af4a6a4fdd7e9789090391a to your computer and use it in GitHub Desktop.
Save honmaple/8b4bc8498af4a6a4fdd7e9789090391a to your computer and use it in GitHub Desktop.
large file compression, encryption with io.Reader and io.Writer
package main
import (
"bytes"
"compress/gzip"
"crypto/aes"
"crypto/cipher"
"crypto/md5"
"crypto/rand"
"fmt"
"io"
"log"
"os"
"sync"
)
func deriveKey(key string) []byte {
has := md5.Sum([]byte(key))
return []byte(fmt.Sprintf("%x", has))
}
func encrypt(in io.Reader, out io.Writer, keyAes []byte) error {
block, err := aes.NewCipher(keyAes)
if err != nil {
return err
}
iv := make([]byte, block.BlockSize())
if _, err := rand.Read(iv); err != nil {
return err
}
stream := &cipher.StreamWriter{S: cipher.NewCFBEncrypter(block, iv), W: out}
_, err = out.Write(iv)
if err != nil {
return err
}
_, err = io.Copy(stream, in)
return err
}
func decrypt(in io.Reader, out io.Writer, keyAes []byte) error {
block, err := aes.NewCipher(keyAes)
if err != nil {
return err
}
iv := make([]byte, block.BlockSize())
if _, err := in.Read(iv); err != nil {
return err
}
stream := &cipher.StreamWriter{S: cipher.NewCFBDecrypter(block, iv), W: out}
_, err = io.Copy(stream, in)
return err
}
func compress(in io.Reader, out io.Writer) error {
zw := gzip.NewWriter(out)
defer zw.Close()
_, err := io.Copy(zw, in)
return err
}
func uncompress(in io.Reader, out io.Writer) error {
zr, err := gzip.NewReader(in)
if err != nil {
return err
}
defer zr.Close()
_, err = io.Copy(out, zr)
return err
}
func dFile(src io.Reader, useEncrypt, useCompress bool) {
var fr io.Reader = src
var wg sync.WaitGroup
if useEncrypt {
er, ew := io.Pipe()
wg.Add(1)
go func(in io.Reader) {
defer wg.Done()
defer ew.Close()
if err := decrypt(in, ew, deriveKey("123456")); err != nil {
log.Println(err.Error())
}
}(fr)
defer er.Close()
fr = er
}
if useCompress {
gr, gw := io.Pipe()
wg.Add(1)
go func(in io.Reader) {
defer wg.Done()
defer gw.Close()
if err := uncompress(in, gw); err != nil {
log.Println(err.Error())
}
}(fr)
defer gr.Close()
fr = gr
}
_, err := io.Copy(os.Stdout, fr)
if err != nil {
log.Fatal(err.Error())
}
wg.Wait()
fmt.Println()
}
func main() {
useEncrypt := true
useCompress := true
src := bytes.NewBuffer([]byte("This is a plainText"))
var fr io.Reader = src
var wg sync.WaitGroup
if useCompress {
gr, gw := io.Pipe()
wg.Add(1)
go func(in io.Reader) {
defer wg.Done()
defer gw.Close()
if err := compress(in, gw); err != nil {
log.Println(err.Error())
}
}(fr)
defer gr.Close()
fr = gr
}
if useEncrypt {
er, ew := io.Pipe()
wg.Add(1)
go func(in io.Reader) {
defer wg.Done()
defer ew.Close()
if err := encrypt(in, ew, deriveKey("123456")); err != nil {
log.Println(err.Error())
}
}(fr)
defer er.Close()
fr = er
}
var dst bytes.Buffer
_, err := io.Copy(&dst, fr)
if err != nil {
log.Fatal(err.Error())
}
wg.Wait()
fmt.Println(dst.String())
dFile(&dst, useEncrypt, useCompress)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment