Skip to content

Instantly share code, notes, and snippets.

@unwosu
Last active November 27, 2022 23:14
Show Gist options
  • Save unwosu/9ef4ac5c7c5ed4c989900732e7a2e729 to your computer and use it in GitHub Desktop.
Save unwosu/9ef4ac5c7c5ed4c989900732e7a2e729 to your computer and use it in GitHub Desktop.
Using mmap to perform encryption of files on disk in golang
package main
import (
"crypto/cipher"
"crypto/rand"
"encoding/binary"
"io"
"io/ioutil"
"net/http"
"os"
"golang.org/x/sys/unix"
)
const (
Magic = 0xacd740cdb98a52a8
Version = 1
HeaderSize = 4096
IVOffset = 12
)
var MyGCM cipher.AEAD
func HandleIncoming(r *http.Request, w http.ResponseWriter) {
f, err := ioutil.TempFile("", "incoming-")
if err != nil {
http.Error(w, "could not create file",
http.StatusInternalServerError)
return
}
defer f.Close()
defer os.Remove(f.Name())
hdr := make([]byte, HeaderSize)
if _, err := f.Write(hdr); err != nil {
http.Error(w, "could not write to file",
http.StatusInternalServerError)
return
}
fileLen, err := io.Copy(f, r.Body)
if err != nil {
http.Error(w, "could not copy to file",
http.StatusInternalServerError)
return
}
trailer := make([]byte, MyGCM.Overhead())
if _, err := f.Write(trailer); err != nil {
http.Error(w, "could not write trailer to file",
http.StatusInternalServerError)
return
}
// NB: at this point you can actually return from the handler and
// finish the rest asynchronously, though you lose the abilite to
// propagate errors back to the caller
fullFile, err := unix.Mmap(int(f.Fd()), 0,
int(fileLen)+HeaderSize+len(trailer),
unix.PROT_READ|unix.PROT_WRITE, unix.MAP_SHARED)
if err != nil {
http.Error(w, "could not mmap file",
http.StatusInternalServerError)
return
}
hdr = fullFile[:HeaderSize]
plaintext := fullFile[HeaderSize : HeaderSize+fileLen]
binary.LittleEndian.PutUint64(hdr, Magic)
binary.LittleEndian.PutUint32(hdr[8:], Version)
iv := hdr[IVOffset : IVOffset+MyGCM.NonceSize()]
rand.Read(iv)
ciphertext := MyGCM.Seal(plaintext[:0], iv, plaintext, fullFile[:IVOffset])
// TODO
_ = ciphertext
w.WriteHeader(http.StatusOK)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment