initial aead
Signed-off-by: Jess Frazelle <jess@mesosphere.com>
This commit is contained in:
parent
dc8799e280
commit
f11dd855bc
5 changed files with 127 additions and 8 deletions
2
Makefile
2
Makefile
|
@ -48,7 +48,7 @@ image.tar:
|
||||||
docker export $(shell docker create $(DOCKER_ROOTFS_IMAGE) sh) > $@
|
docker export $(shell docker create $(DOCKER_ROOTFS_IMAGE) sh) > $@
|
||||||
|
|
||||||
rootfs.go: image.tar
|
rootfs.go: image.tar
|
||||||
GOMAXPROCS=1 go generate
|
GOMAXPROCS=1 go run generate.go
|
||||||
|
|
||||||
fmt:
|
fmt:
|
||||||
@echo "+ $@"
|
@echo "+ $@"
|
||||||
|
|
91
cryptar/cryptar.go
Normal file
91
cryptar/cryptar.go
Normal file
|
@ -0,0 +1,91 @@
|
||||||
|
package cryptar
|
||||||
|
|
||||||
|
import (
|
||||||
|
"crypto/aes"
|
||||||
|
"crypto/cipher"
|
||||||
|
"crypto/rand"
|
||||||
|
"encoding/base64"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Encrypt takes the contents of a tarball and a key and seals it.
|
||||||
|
func Encrypt(tarball, key []byte) (string, error) {
|
||||||
|
gcm, err := keyToGCM(key)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
nonce, err := generateNonce(gcm.NonceSize())
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
out := gcm.Seal(nonce, nonce, tarball, nil)
|
||||||
|
|
||||||
|
enctar := base64.StdEncoding.EncodeToString(out)
|
||||||
|
|
||||||
|
return enctar, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Decrypt takes an encrypted tarball and key and unseals it.
|
||||||
|
func Decrypt(enctar string, key []byte) ([]byte, error) {
|
||||||
|
out, err := base64.StdEncoding.DecodeString(enctar)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
gcm, err := keyToGCM(key)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
size := gcm.NonceSize()
|
||||||
|
nonce := make([]byte, size)
|
||||||
|
copy(nonce, out[:])
|
||||||
|
|
||||||
|
tarball, err := gcm.Open(nil, nonce, out[size:], nil)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return tarball, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func keyToGCM(key []byte) (cipher.AEAD, error) {
|
||||||
|
/*hash := sha256.New()
|
||||||
|
if _, err := hash.Write([]byte(key)); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
md := hash.Sum(nil)
|
||||||
|
mdkey := hex.EncodeToString(md)*/
|
||||||
|
|
||||||
|
// encrypt the tar with the key
|
||||||
|
block, err := aes.NewCipher(key)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
gcm, err := cipher.NewGCM(block)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return gcm, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// generateNonce creates a new random nonce.
|
||||||
|
func generateNonce(size int) ([]byte, error) {
|
||||||
|
// Create the nonce.
|
||||||
|
nonce, err := randBytes(size)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nonce, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// randBytes returns n bytes of random data.
|
||||||
|
func randBytes(n int) ([]byte, error) {
|
||||||
|
b := make([]byte, n)
|
||||||
|
_, err := rand.Read(b)
|
||||||
|
return b, err
|
||||||
|
}
|
26
generate.go
26
generate.go
|
@ -3,14 +3,22 @@
|
||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"crypto/rand"
|
||||||
"encoding/base64"
|
"encoding/base64"
|
||||||
|
"fmt"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
|
||||||
|
"github.com/jfrazelle/binctr/cryptar"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
nonceSize = 24
|
||||||
)
|
)
|
||||||
|
|
||||||
// Reads static/index.html and saves as a constant in static.go
|
|
||||||
func main() {
|
func main() {
|
||||||
|
// prompt for key
|
||||||
wd, err := os.Getwd()
|
wd, err := os.Getwd()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
|
@ -22,15 +30,27 @@ func main() {
|
||||||
tarPath := filepath.Join(wd, "image.tar")
|
tarPath := filepath.Join(wd, "image.tar")
|
||||||
|
|
||||||
out.Write([]byte("// This file is autogenerated; DO NOT EDIT DIRECTLY\n// See generate.go for more info\npackage main\n\nconst (\n"))
|
out.Write([]byte("// This file is autogenerated; DO NOT EDIT DIRECTLY\n// See generate.go for more info\npackage main\n\nconst (\n"))
|
||||||
|
out.Write([]byte("\t// DATA is the encrypted tarball data\n"))
|
||||||
out.Write([]byte("\tDATA = `"))
|
out.Write([]byte("\tDATA = `"))
|
||||||
f, err := ioutil.ReadFile(tarPath)
|
f, err := ioutil.ReadFile(tarPath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
tar := base64.StdEncoding.EncodeToString(f)
|
key := make([]byte, 32)
|
||||||
out.Write([]byte(tar))
|
if _, err := rand.Read(key); err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
gcmOut, err := cryptar.Encrypt(f, key)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
out.Write([]byte(gcmOut))
|
||||||
|
|
||||||
out.Write([]byte("`\n"))
|
out.Write([]byte("`\n"))
|
||||||
out.Write([]byte(")\n"))
|
out.Write([]byte(")\n"))
|
||||||
|
|
||||||
|
fmt.Println("key is: ", base64.StdEncoding.EncodeToString(key))
|
||||||
}
|
}
|
||||||
|
|
6
main.go
6
main.go
|
@ -34,7 +34,7 @@ const (
|
||||||
|
|
||||||
`
|
`
|
||||||
|
|
||||||
defaultRoot = "/run/binctr"
|
defaultRoot = "/tmp/binctr"
|
||||||
defaultRootfsDir = "rootfs"
|
defaultRootfsDir = "rootfs"
|
||||||
defaultApparmorProfile = "docker-default"
|
defaultApparmorProfile = "docker-default"
|
||||||
)
|
)
|
||||||
|
@ -44,6 +44,7 @@ var (
|
||||||
containerID string
|
containerID string
|
||||||
pidFile string
|
pidFile string
|
||||||
root string
|
root string
|
||||||
|
passkey string
|
||||||
|
|
||||||
allocateTty bool
|
allocateTty bool
|
||||||
detach bool
|
detach bool
|
||||||
|
@ -116,6 +117,7 @@ func init() {
|
||||||
flag.StringVar(&console, "console", console, "the pty slave path for use with the container")
|
flag.StringVar(&console, "console", console, "the pty slave path for use with the container")
|
||||||
flag.StringVar(&pidFile, "pid-file", "", "specify the file to write the process id to")
|
flag.StringVar(&pidFile, "pid-file", "", "specify the file to write the process id to")
|
||||||
flag.StringVar(&root, "root", defaultRoot, "root directory of container state, should be tmpfs")
|
flag.StringVar(&root, "root", defaultRoot, "root directory of container state, should be tmpfs")
|
||||||
|
flag.StringVar(&passkey, "key", "", "key to decrypt the embedded tarball")
|
||||||
|
|
||||||
flag.Var(&hookflags, "hook", "Hooks to prefill into spec file. (ex. --hook prestart:netns)")
|
flag.Var(&hookflags, "hook", "Hooks to prefill into spec file. (ex. --hook prestart:netns)")
|
||||||
|
|
||||||
|
@ -215,7 +217,7 @@ func main() {
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := unpackRootfs(spec); err != nil {
|
if err := unpackRootfs(spec, passkey); err != nil {
|
||||||
logrus.Fatal(err)
|
logrus.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -6,11 +6,17 @@ import (
|
||||||
"os"
|
"os"
|
||||||
|
|
||||||
"github.com/docker/docker/pkg/archive"
|
"github.com/docker/docker/pkg/archive"
|
||||||
|
"github.com/jfrazelle/binctr/cryptar"
|
||||||
"github.com/opencontainers/runtime-spec/specs-go"
|
"github.com/opencontainers/runtime-spec/specs-go"
|
||||||
)
|
)
|
||||||
|
|
||||||
func unpackRootfs(spec *specs.Spec) error {
|
func unpackRootfs(spec *specs.Spec, keyin string) error {
|
||||||
data, err := base64.StdEncoding.DecodeString(DATA)
|
key, err := base64.StdEncoding.DecodeString(keyin)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
data, err := cryptar.Decrypt(DATA, key)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue