cryptowrap

package module
v0.2.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: May 23, 2020 License: MIT Imports: 15 Imported by: 0

README

# cryptowrap image:https://godoc.org/github.com/Djarvur/go-cryptowrap?status.svg["GoDoc",link="http://godoc.org/github.com/Djarvur/go-cryptowrap"] image:https://github.com/Djarvur/go-cryptowrap/workflows/Test/badge.svg?branch=master["Build Status"] image:https://coveralls.io/repos/Djarvur/go-cryptowrap/badge.svg?branch=master&service=github["Coverage Status",link="https://coveralls.io/github/Djarvur/go-cryptowrap?branch=master"]

JSON/Gob/MsgPack-based Marshaler/Unmarshaler with AES/RSA encryption

cryptowrap.Wrapper is a struct with custom JSON/Gob/Binary marshaler and unmarshaler.

Marshaler will encrypt Payload with AES using first value from Keys as a key
and provided IV as an initialisation vector.
Random string will be used if no IV provided.

Actual AES form will be chosen based on first Keys value length.

Serialised data are protected by checksum.

Unmarshaler will decrypt Payload with the Keys provided.
Keys will be tryied one by one until success decryption. Success means checksum check satisfied.
ErrUndecryptable will be returned in case no one key is suitable.

RSA Marshaler will encrypt Payload with RSA using public key provided as a key using RSA-OAEP.

RSA Unmarshaler will decrypt Payload with the private keys provided.
Keys will be tryied one by one until success decryption.
ErrUndecryptable will be returned in case no one key is suitable.

## Example

```
	type toPass struct {
		Insecure string
		Secure   cryptowrap.Wrapper
	}

	type toPassSecure struct {
		Field string
	}

	key := []byte("0123456789ABCDEF")

	srcSecure := toPassSecure{"world!"}

	src := toPass{
		Insecure: "hello",
		Secure: cryptowrap.Wrapper{
			Keys:    [][]byte{key},
			Payload: &srcSecure,
		},
	}

	data, err := json.Marshal(&src)
	if err != nil {
		panic(err)
	}

	//	var onTheGo interface{}
	//
	//	err = json.Unmarshal(data, &onTheGo)
	//	if err != nil {
	//		panic(err)
	//	}
	//
	//	log.Printf("payload is encrypted: %v\n", onTheGo)

	var dstSecure toPassSecure

	dst := toPass{
		Secure: cryptowrap.Wrapper{
			Keys:    [][]byte{key},
			Payload: &dstSecure,
		},
	}

	err = json.Unmarshal(data, &dst)
	if err != nil {
		panic(err)
	}

	fmt.Printf("%v\n", dst.Secure.Payload.(*toPassSecure).Field)
	// Output: world!
```

## Benchmark

Raw is no-encryption wrapper, just to compare with crypto.

```
$go test -bench=. -benchmem
goos: darwin
goarch: amd64
pkg: github.com/Djarvur/cryptowrap
BenchmarkRawJSON-4                     485701       2338 ns/op        520 B/op     14 allocs/op
BenchmarkRawGob-4                       39633      40585 ns/op      10455 B/op    255 allocs/op
BenchmarkRawMsgp-4                     273661       4983 ns/op       3728 B/op     41 allocs/op
BenchmarkWrapperJSON128-4               67701      16755 ns/op       4194 B/op     59 allocs/op
BenchmarkWrapperJSON256-4               67858      18140 ns/op       4834 B/op     59 allocs/op
BenchmarkWrapperJSON128Compress-4        1215     889562 ns/op   10704018 B/op     76 allocs/op
BenchmarkWrapperJSON256Compress-4        1456     916625 ns/op   10900791 B/op     76 allocs/op
BenchmarkWrapperGob128-4                10000     104950 ns/op      39948 B/op    890 allocs/op
BenchmarkWrapperGob256-4                10660     109298 ns/op      40444 B/op    890 allocs/op
BenchmarkWrapperGob128Compress-4         1174    1049825 ns/op   11165423 B/op    903 allocs/op
BenchmarkWrapperGob256Compress-4         1076    1120460 ns/op   11241674 B/op    903 allocs/op
BenchmarkWrapperMsgp128-4               64138      17068 ns/op      15472 B/op    151 allocs/op
BenchmarkWrapperMsgp256-4               63519      18474 ns/op      15904 B/op    151 allocs/op
BenchmarkWrapperMsgp128Compress-4        1124     949707 ns/op   11163512 B/op    161 allocs/op
BenchmarkWrapperMsgp256Compress-4        1190     998931 ns/op   11294580 B/op    162 allocs/op
BenchmarkWrapperRSAJSON2048-4             753    1612366 ns/op      34908 B/op    160 allocs/op
BenchmarkWrapperRSAJSON4096-4             123    9537172 ns/op      82904 B/op    175 allocs/op
BenchmarkWrapperRSAJSON2048Compress-4     440    2736445 ns/op   10905212 B/op    180 allocs/op
BenchmarkWrapperRSAJSON4096Compress-4     100   10528565 ns/op   11106407 B/op    194 allocs/op
BenchmarkWrapperRSAGob4096-4              121    9742681 ns/op     123466 B/op   1081 allocs/op
BenchmarkWrapperRSAGob4096Compress-4      100   10695575 ns/op   11649910 B/op   1098 allocs/op
BenchmarkWrapperRSAMsgp2048-4             742    1705802 ns/op      45843 B/op    246 allocs/op
BenchmarkWrapperRSAMsgp4096-4             121    9712414 ns/op      93347 B/op    260 allocs/op
BenchmarkWrapperRSAMsgp2048Compress-4     367    2806277 ns/op   11644800 B/op    261 allocs/op
BenchmarkWrapperRSAMsgp4096Compress-4     100   10353704 ns/op   12122667 B/op    276 allocs/op
PASS
ok  	github.com/Djarvur/cryptowrap	39.306s
```

Documentation

Overview

Package cryptowrap JSON/Gob/MsgPack-based Marshaler/Unmarshaler with AES encryption

Package cryptowrap JSON/Gob/MsgPack-based Marshaler/Unmarshaler with AES encryption

Example (Direct)
package main

import (
	"encoding/json"
	"fmt"

	"github.com/Djarvur/cryptowrap"
)

func main() {
	key := []byte("0123456789ABCDEF")

	src := "hello!"

	data, err := json.Marshal(&cryptowrap.Wrapper{Keys: [][]byte{key}, Payload: &src})
	if err != nil {
		panic(err)
	}

	//	var onTheGo interface{}
	//
	//	err = json.Unmarshal(data, &onTheGo)
	//	if err != nil {
	//		panic(err)
	//	}
	//
	//	log.Printf("payload is encrypted: %v\n", onTheGo)

	var dst string

	err = json.Unmarshal(data, &cryptowrap.Wrapper{Keys: [][]byte{key}, Payload: &dst})
	if err != nil {
		panic(err)
	}

	fmt.Printf("%v\n", dst)
}
Output:

hello!
Example (Embeded)
package main

import (
	"encoding/json"
	"fmt"

	"github.com/Djarvur/cryptowrap"
)

func main() {
	type toPass struct {
		Insecure string
		Secure   cryptowrap.Wrapper
	}

	type toPassSecure struct {
		Field string
	}

	key := []byte("0123456789ABCDEF")

	srcSecure := toPassSecure{"world!"}

	src := toPass{
		Insecure: "hello",
		Secure: cryptowrap.Wrapper{
			Keys:    [][]byte{key},
			Payload: &srcSecure,
		},
	}

	data, err := json.Marshal(&src)
	if err != nil {
		panic(err)
	}

	//	var onTheGo interface{}
	//
	//	err = json.Unmarshal(data, &onTheGo)
	//	if err != nil {
	//		panic(err)
	//	}
	//
	//	log.Printf("payload is encrypted: %v\n", onTheGo)

	var dstSecure toPassSecure

	dst := toPass{
		Secure: cryptowrap.Wrapper{
			Keys:    [][]byte{key},
			Payload: &dstSecure,
		},
	}

	err = json.Unmarshal(data, &dst)
	if err != nil {
		panic(err)
	}

	fmt.Printf("%v\n", dst.Secure.Payload.(*toPassSecure).Field)
}
Output:

world!
Example (Gob)
package main

import (
	"bytes"
	"encoding/gob"
	"fmt"

	"github.com/Djarvur/cryptowrap"
)

func main() {
	type toPass struct {
		Insecure string
		Secure   cryptowrap.Wrapper
	}

	type toPassSecure struct {
		Field string
	}

	key := []byte("0123456789ABCDEF")

	srcSecure := toPassSecure{"hello world!"}

	src := toPass{
		Insecure: "hello",
		Secure: cryptowrap.Wrapper{
			Keys:    [][]byte{key},
			Payload: &srcSecure,
		},
	}

	gob.Register(&srcSecure)

	var b bytes.Buffer

	err := gob.NewEncoder(&b).Encode(&src)
	if err != nil {
		panic(err)
	}

	data := b.Bytes()

	var dstSecure toPassSecure

	dst := toPass{
		Secure: cryptowrap.Wrapper{
			Keys:    [][]byte{key},
			Payload: &dstSecure,
		},
	}

	err = gob.NewDecoder(bytes.NewBuffer(data)).Decode(&dst)
	if err != nil {
		panic(err)
	}

	fmt.Printf("%v\n", dst.Secure.Payload.(*toPassSecure).Field)
}
Output:

hello world!
Example (Msgpack)
package main

import (
	"bytes"
	"fmt"

	"github.com/Djarvur/cryptowrap"
	"github.com/ugorji/go/codec"
)

func main() {
	type toPass struct {
		Insecure string
		Secure   cryptowrap.Wrapper
	}

	type toPassSecure struct {
		Field string
	}

	key := []byte("0123456789ABCDEF")

	srcSecure := toPassSecure{"hello world!"}

	src := toPass{
		Insecure: "hello",
		Secure: cryptowrap.Wrapper{
			Keys:    [][]byte{key},
			Payload: &srcSecure,
		},
	}

	var b bytes.Buffer

	err := codec.NewEncoder(&b, new(codec.MsgpackHandle)).Encode(&src)
	if err != nil {
		panic(err)
	}

	data := b.Bytes()

	var dstSecure toPassSecure

	dst := toPass{
		Secure: cryptowrap.Wrapper{
			Keys:    [][]byte{key},
			Payload: &dstSecure,
		},
	}

	err = codec.NewDecoderBytes(data, new(codec.MsgpackHandle)).Decode(&dst)
	if err != nil {
		panic(err)
	}

	fmt.Printf("%v\n", dst.Secure.Payload.(*toPassSecure).Field)
}
Output:

hello world!
Example (Rsa)
package main

import (
	"crypto/rand"
	"crypto/rsa"
	"encoding/json"
	"fmt"

	"github.com/Djarvur/cryptowrap"
)

func main() {
	type toPass struct {
		Insecure string
		Secure   cryptowrap.WrapperRSA
	}

	type toPassSecure struct {
		Field string
	}

	key, err := rsa.GenerateKey(rand.Reader, 2048)
	if err != nil {
		panic(err)
	}

	srcSecure := toPassSecure{"world!"}

	src := toPass{
		Insecure: "hello",
		Secure: cryptowrap.WrapperRSA{
			EncKey:  &key.PublicKey,
			Payload: &srcSecure,
		},
	}

	data, err := json.Marshal(&src)
	if err != nil {
		panic(err)
	}

	var dstSecure toPassSecure

	dst := toPass{
		Secure: cryptowrap.WrapperRSA{
			DecKeys: []*rsa.PrivateKey{key},
			Payload: &dstSecure,
		},
	}

	err = json.Unmarshal(data, &dst)
	if err != nil {
		panic(err)
	}

	fmt.Printf("%v\n", dst.Secure.Payload.(*toPassSecure).Field)
}
Output:

world!

Index

Examples

Constants

This section is empty.

Variables

View Source
var (
	ErrUndecryptable = errors.New("data could not be decrypted")
	ErrNoKey         = errors.New("key has to be provided")
)

Errors might be returned. They will be wrapped with stacktrace at least, of course.

Functions

This section is empty.

Types

type Wrapper

type Wrapper struct {
	Keys     [][]byte
	IV       []byte
	Payload  interface{}
	Compress bool
}

Wrapper is a struct with custom JSON/Gob/Binary marshaler and unmarshaler.

Marshaler will encrypt Payload with AES using first value from Keys as a key and provided IV as an initialisation vector. Random string will be used if no IV provided.

Actual AES form will be chosen based on first Keys value length.

Serialised data are protected by checksum.

Unmarshaler will decrypt Payload with the Keys provided. Keys will be tryied one by one until success decryption. Success means checksum check satisfied. ErrUndecryptable will be returned in case no one key is suitable.

If Compress is true serialized Payload wil be compressed with LZ4.

func (*Wrapper) GobDecode added in v0.1.1

func (w *Wrapper) GobDecode(data []byte) error

GobDecode is a custom unmarshaler.

func (*Wrapper) GobEncode added in v0.1.1

func (w *Wrapper) GobEncode() ([]byte, error)

GobEncode is a custom marshaler.

func (*Wrapper) MarshalBinary added in v0.1.1

func (w *Wrapper) MarshalBinary() (data []byte, err error)

MarshalBinary is a custom marshaler to be used with MsgPack (github.com/ugorji/go/codec).

func (*Wrapper) MarshalJSON

func (w *Wrapper) MarshalJSON() ([]byte, error)

MarshalJSON is a custom marshaler.

func (*Wrapper) UnmarshalBinary added in v0.1.1

func (w *Wrapper) UnmarshalBinary(data []byte) error

UnmarshalBinary is a custom unmarshaler to be used with MsgPack (github.com/ugorji/go/codec).

func (*Wrapper) UnmarshalJSON

func (w *Wrapper) UnmarshalJSON(data []byte) error

UnmarshalJSON is a custom unmarshaler.

type WrapperRSA added in v0.2.0

type WrapperRSA struct {
	DecKeys  []*rsa.PrivateKey
	EncKey   *rsa.PublicKey
	Hash     hash.Hash
	Label    []byte
	Payload  interface{}
	Compress bool
}

WrapperRSA is a struct with custom JSON/Gob/Binary marshaler and unmarshaler.

Marshaler will encrypt Payload with RSA using EncKey as a public key. and hash function provided in Hash. sha256.New() will be used if no Hash provided.

Serialised data are protected by checksum.

Unmarshaler will decrypt Payload with the DecKeys provided. Keys will be tryied one by one until success decryption. Success means checksum check satisfied. ErrUndecryptable will be returned in case no one key is suitable.

Label must be the same for Marshaling and Umarshaling. If no label provided empty one is used.

If Compress is true serialized Payload wil be compressed with LZ4.

Note: there is a limit for the length of data could be encrypted with RSA: The message must be no longer than the length of the public modulus minus twice the hash length, minus a further 2. See https://golang.ir/pkg/crypto/rsa/#EncryptOAEP for details (there no much though).

func (*WrapperRSA) GobDecode added in v0.2.0

func (w *WrapperRSA) GobDecode(data []byte) error

GobDecode is a custom unmarshaler.

func (*WrapperRSA) GobEncode added in v0.2.0

func (w *WrapperRSA) GobEncode() ([]byte, error)

GobEncode is a custom marshaler.

func (*WrapperRSA) MarshalBinary added in v0.2.0

func (w *WrapperRSA) MarshalBinary() (data []byte, err error)

MarshalBinary is a custom marshaler to be used with MsgPack (github.com/ugorji/go/codec).

func (*WrapperRSA) MarshalJSON added in v0.2.0

func (w *WrapperRSA) MarshalJSON() ([]byte, error)

MarshalJSON is a custom marshaler.

func (*WrapperRSA) UnmarshalBinary added in v0.2.0

func (w *WrapperRSA) UnmarshalBinary(data []byte) error

UnmarshalBinary is a custom unmarshaler to be used with MsgPack (github.com/ugorji/go/codec).

func (*WrapperRSA) UnmarshalJSON added in v0.2.0

func (w *WrapperRSA) UnmarshalJSON(data []byte) error

UnmarshalJSON is a custom unmarshaler.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL