payload almost done
This commit is contained in:
1 parent
77bfcba5b1
commit
09d0f237d5
16 files changed
+688
-116
No files matched your search
+3
-3
@@ -34,7 +34,7 @@ else than a zip file containing the following shit.
|
|||||||
|
|
|
|
||||||
| _________________________________________________________________________
|
| _________________________________________________________________________
|
||||||
| |
|
| |
|
||||||
| | Envelop meta data: encryption type, mode, Paiload signature (yaml)
|
| | Envelop meta data: encryption type, mode, Paiload signature (yaml), IV,..
|
||||||
| |__________________________________________________________________________
|
| |__________________________________________________________________________
|
||||||
|
|
|
|
||||||
| __________________________________________________________________________
|
| __________________________________________________________________________
|
||||||
@@ -42,12 +42,12 @@ else than a zip file containing the following shit.
|
|||||||
| | Paiload: Zip file, no compression, symetrcally encrypted
|
| | Paiload: Zip file, no compression, symetrcally encrypted
|
||||||
| | _____________________________________________________________________
|
| | _____________________________________________________________________
|
||||||
| | |
|
| | |
|
||||||
| | | paiload intern metadata: Data signature, sender, message, IV, ...
|
| | | paiload intern metadata: Data signature, sender, message ...
|
||||||
| | |______________________________________________________________________
|
| | |______________________________________________________________________
|
||||||
| |
|
| |
|
||||||
| | _______________________________________________________________________
|
| | _______________________________________________________________________
|
||||||
| | |
|
| | |
|
||||||
| | | Data: Zip file, high compression
|
| | | Data: Can be anything. But for file and folders, it will be zipped
|
||||||
| | |
|
| | |
|
||||||
| | |
|
| | |
|
||||||
| | |
|
| | |
|
||||||
|
|||||||
+19
-1
@@ -4,6 +4,7 @@ import (
|
|||||||
"bytes"
|
"bytes"
|
||||||
"crypto/rsa"
|
"crypto/rsa"
|
||||||
"encoding/binary"
|
"encoding/binary"
|
||||||
|
"encoding/json"
|
||||||
"io"
|
"io"
|
||||||
"math/big"
|
"math/big"
|
||||||
"math/rand"
|
"math/rand"
|
||||||
@@ -14,11 +15,12 @@ func B(x int64) *big.Int {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type MockRandomReader struct {
|
type MockRandomReader struct {
|
||||||
|
readLength int
|
||||||
random *rand.Rand
|
random *rand.Rand
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewMockRandomReader() *MockRandomReader {
|
func NewMockRandomReader() *MockRandomReader {
|
||||||
return &MockRandomReader{rand.New(rand.NewSource(99))}
|
return &MockRandomReader{0, rand.New(rand.NewSource(99))}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (this *MockRandomReader) getNextFourRandomBytes() []byte {
|
func (this *MockRandomReader) getNextFourRandomBytes() []byte {
|
||||||
@@ -31,9 +33,14 @@ func (this *MockRandomReader) Read(p []byte) (n int, err error) {
|
|||||||
for i := 0; i < len(p); i += 4 {
|
for i := 0; i < len(p); i += 4 {
|
||||||
copy(p[i:], this.getNextFourRandomBytes())
|
copy(p[i:], this.getNextFourRandomBytes())
|
||||||
}
|
}
|
||||||
|
this.readLength += len(p)
|
||||||
return len(p), nil
|
return len(p), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (this *MockRandomReader) GetReadLength() int {
|
||||||
|
return this.readLength
|
||||||
|
}
|
||||||
|
|
||||||
func (this *MockRandomReader) GetRandomBytes(size int) []byte {
|
func (this *MockRandomReader) GetRandomBytes(size int) []byte {
|
||||||
ret := make([]byte, size)
|
ret := make([]byte, size)
|
||||||
this.Read(ret)
|
this.Read(ret)
|
||||||
@@ -74,6 +81,17 @@ func (this *MockIoWriter) ReaderAt() io.ReaderAt {
|
|||||||
return bytes.NewReader(this.state)
|
return bytes.NewReader(this.state)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (this *MockIoWriter) IsValidJson() bool {
|
||||||
|
m := make(map[string]interface{})
|
||||||
|
l := make([]interface{}, 0, 100)
|
||||||
|
if json.Unmarshal(this.Bytes(), &m) == nil {
|
||||||
|
return true
|
||||||
|
} else if json.Unmarshal(this.Bytes(), &l) == nil {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
func Range(length int) []byte {
|
func Range(length int) []byte {
|
||||||
ret := make([]byte, length)
|
ret := make([]byte, length)
|
||||||
for i, _ := range ret {
|
for i, _ := range ret {
|
||||||
|
|||||||
@@ -43,6 +43,26 @@ func TestMockIoWriter(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestIsValidJson(t *testing.T) {
|
||||||
|
m := make(map[string]bool)
|
||||||
|
m[`{}`] = true
|
||||||
|
m[`[]`] = true
|
||||||
|
m[`[1, "abc", {"aa": true, "2": [1,2,3]}]`] = true
|
||||||
|
m[`{"aa": true, "2": [1,2,3]}`] = true
|
||||||
|
|
||||||
|
m[`regular string`] = false
|
||||||
|
m[`{"aa": true "2": [1,2,3]}`] = false // malformed json
|
||||||
|
for json_, isJSON := range m {
|
||||||
|
w := &MockIoWriter{[]byte(json_)}
|
||||||
|
ok := w.IsValidJson()
|
||||||
|
if ok && !isJSON {
|
||||||
|
t.Error(json_, "is not json but has been detected as json")
|
||||||
|
} else if !ok && isJSON {
|
||||||
|
t.Error(json_, "is json but has not been detected as json")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestGetRSAPublicKeyAndGetRSAPrivateKey(t *testing.T) {
|
func TestGetRSAPublicKeyAndGetRSAPrivateKey(t *testing.T) {
|
||||||
privateKey := GetRSAPrivateKey(50)
|
privateKey := GetRSAPrivateKey(50)
|
||||||
if err := privateKey.Validate(); err != nil {
|
if err := privateKey.Validate(); err != nil {
|
||||||
@@ -60,7 +80,7 @@ func TestGetRSAPublicKeyAndGetRSAPrivateKey(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestGetNextFourRandomBytes(t *testing.T) {
|
func TestGetNextFourRandomBytes(t *testing.T) {
|
||||||
m := &MockRandomReader{rand.New(rand.NewSource(22))}
|
m := &MockRandomReader{0, rand.New(rand.NewSource(22))}
|
||||||
rb := m.getNextFourRandomBytes()
|
rb := m.getNextFourRandomBytes()
|
||||||
var expt []byte = []byte{233, 237, 107, 32}
|
var expt []byte = []byte{233, 237, 107, 32}
|
||||||
if len(rb) != 4 {
|
if len(rb) != 4 {
|
||||||
@@ -103,3 +123,15 @@ func TestGetRandomBytes(t *testing.T) {
|
|||||||
t.Fail()
|
t.Fail()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestGetReadLength(t *testing.T) {
|
||||||
|
m := NewMockRandomReader()
|
||||||
|
dump := make([]byte, 4*10+3)
|
||||||
|
if _, err := m.Read(dump); err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if m.GetReadLength() != 4*10+3 {
|
||||||
|
t.Error("bad read length")
|
||||||
|
}
|
||||||
|
}
|
||||||
+4
-3
@@ -36,11 +36,12 @@ func createRandomKey(lengthInBits int, rd io.Reader) ([]byte, error) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (this Block) CreateBlock(rd io.Reader) (cipher.Block, error) {
|
func (this Block) CreateBlock(rd io.Reader) (cipher.Block, []byte, error) {
|
||||||
var err error
|
var err error
|
||||||
key := make([]byte, 256/8)
|
key := make([]byte, 256/8)
|
||||||
if _, err = rd.Read(key); err != nil {
|
if _, err = rd.Read(key); err != nil {
|
||||||
return nil, err
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
return aes.NewCipher(key)
|
block, err := aes.NewCipher(key)
|
||||||
|
return block, key, err
|
||||||
}
|
}
|
||||||
+33
-5
@@ -2,16 +2,42 @@ package payload
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"crypto"
|
"crypto"
|
||||||
|
"crypto/aes"
|
||||||
|
"crypto/cipher"
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
"github.com/didiercrunch/ecrypto/helper"
|
"github.com/didiercrunch/ecrypto/helper"
|
||||||
|
"reflect"
|
||||||
"testing"
|
"testing"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
type Blocker func([]byte) (cipher.Block, error)
|
||||||
|
|
||||||
|
func assertBlockOkay(block cipher.Block, key []byte, blocker Blocker) error {
|
||||||
|
expectedBlock, err := blocker(key)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if expectedBlock.BlockSize() != block.BlockSize() {
|
||||||
|
return errors.New(fmt.Sprintf("bad block size. Expected %v but was %v", expectedBlock.BlockSize(), block.BlockSize()))
|
||||||
|
}
|
||||||
|
src := helper.Range(block.BlockSize())
|
||||||
|
encrypt := make([]byte, block.BlockSize())
|
||||||
|
decrypt := make([]byte, block.BlockSize())
|
||||||
|
block.Encrypt(encrypt, src)
|
||||||
|
expectedBlock.Decrypt(decrypt, encrypt)
|
||||||
|
if !reflect.DeepEqual(decrypt, src) {
|
||||||
|
return errors.New("expected encryption is wrong")
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func TestCreateBlock(t *testing.T) {
|
func TestCreateBlock(t *testing.T) {
|
||||||
random := helper.NewMockRandomReader()
|
random := helper.NewMockRandomReader()
|
||||||
if block, err := AES256.CreateBlock(random); err != nil {
|
if block, key, err := AES256.CreateBlock(random); err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
} else if err := assertBlockOkay(block, key, aes.NewCipher); err != nil {
|
||||||
t.Error(err)
|
t.Error(err)
|
||||||
} else {
|
|
||||||
_ = block
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -19,11 +45,13 @@ func Testhash512BytesOfData(t *testing.T) {
|
|||||||
if _, err := hash512BytesOfData(crypto.MD5, helper.NewMockRandomReader()); err == nil {
|
if _, err := hash512BytesOfData(crypto.MD5, helper.NewMockRandomReader()); err == nil {
|
||||||
t.Error("should never allow MD5 hash")
|
t.Error("should never allow MD5 hash")
|
||||||
}
|
}
|
||||||
rd := helper.NewMockRandomReader()
|
randomGenerator := helper.NewMockRandomReader()
|
||||||
if rd, err := hash512BytesOfData(crypto.SHA512, rd); err != nil {
|
if rd, err := hash512BytesOfData(crypto.SHA512, randomGenerator); err != nil {
|
||||||
t.Error(err)
|
t.Error(err)
|
||||||
} else if len(rd) != 512/8 {
|
} else if len(rd) != 512/8 {
|
||||||
t.Fail()
|
t.Fail()
|
||||||
|
} else if l := randomGenerator.GetReadLength(); l != 512 {
|
||||||
|
t.Error(fmt.Sprint("Was suppose to read 512 bytes of data but read", l, "bytes of data"))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,45 @@
|
|||||||
|
package payload
|
||||||
|
|
||||||
|
import (
|
||||||
|
"crypto/cipher"
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
)
|
||||||
|
|
||||||
|
type BlockStream func(block cipher.Block, iv []byte) cipher.Stream
|
||||||
|
|
||||||
|
type BlockMode string
|
||||||
|
|
||||||
|
const OFB BlockMode = "ofb"
|
||||||
|
|
||||||
|
func (this BlockMode) GetEncryptorStream() (BlockStream, error) {
|
||||||
|
switch this {
|
||||||
|
case OFB:
|
||||||
|
return cipher.NewOFB, nil
|
||||||
|
default:
|
||||||
|
err := fmt.Sprintf("BlockMode '%s' is not available", this)
|
||||||
|
return nil, errors.New(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func createIV(b cipher.Block, rd io.Reader) ([]byte, error) {
|
||||||
|
ret := make([]byte, b.BlockSize())
|
||||||
|
if _, err := rd.Read(ret); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return ret, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this BlockMode) GetCipherStream(block cipher.Block, rd io.Reader) (stream cipher.Stream, iv []byte, err error) {
|
||||||
|
iv, err = createIV(block, rd)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
streamCreator, err := this.GetEncryptorStream()
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
return streamCreator(block, iv), iv, nil
|
||||||
|
}
|
||||||
@@ -0,0 +1,48 @@
|
|||||||
|
package payload
|
||||||
|
|
||||||
|
import (
|
||||||
|
"crypto/cipher"
|
||||||
|
"crypto/des"
|
||||||
|
"github.com/didiercrunch/ecrypto/helper"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func getAnyBlock() cipher.Block {
|
||||||
|
block, err := des.NewTripleDESCipher(helper.Range(24))
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
return block
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestGetEncryptorStreamError(t *testing.T) {
|
||||||
|
var foo BlockMode = "some_shit"
|
||||||
|
if _, err := foo.GetEncryptorStream(); err == nil {
|
||||||
|
t.Error("should have an error here")
|
||||||
|
} else if err.Error() != "BlockMode 'some_shit' is not available" {
|
||||||
|
t.Error("bad error message")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestOFB(t *testing.T) {
|
||||||
|
_, err := OFB.GetEncryptorStream()
|
||||||
|
if err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestCreateIV(t *testing.T) {
|
||||||
|
block := getAnyBlock()
|
||||||
|
if iv, err := createIV(block, helper.NewMockRandomReader()); err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
} else if len(iv) != block.BlockSize() {
|
||||||
|
t.Error("bad iv length")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestGetCipherStream(t *testing.T) {
|
||||||
|
block := getAnyBlock()
|
||||||
|
if _, _, err := OFB.GetCipherStream(block, helper.NewMockRandomReader()); err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,56 @@
|
|||||||
|
package payload
|
||||||
|
|
||||||
|
import (
|
||||||
|
"io"
|
||||||
|
)
|
||||||
|
|
||||||
|
type CopyOutput struct {
|
||||||
|
Err error
|
||||||
|
Written int64
|
||||||
|
}
|
||||||
|
|
||||||
|
func copyAndUpdate(dst io.Writer, data []byte, copyOutput *CopyOutput) {
|
||||||
|
if copyOutput.Err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
nw, ew := dst.Write(data)
|
||||||
|
if nw > 0 {
|
||||||
|
copyOutput.Written += int64(nw)
|
||||||
|
}
|
||||||
|
if ew != nil {
|
||||||
|
copyOutput.Err = ew
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if len(data) != nw {
|
||||||
|
copyOutput.Err = io.ErrShortWrite
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func CopyToTwoWriters(dst1 io.Writer, dst2 io.Writer, src io.Reader) (copyOutput1 *CopyOutput, copyOutput2 *CopyOutput) {
|
||||||
|
// TODO: if necessary, implements the speedup methods if src implements *WriterTo*
|
||||||
|
// or if both dst implement ReaderFrom. See
|
||||||
|
// http://golang.org/src/pkg/io/io.go for example
|
||||||
|
copyOutput1, copyOutput2 = new(CopyOutput), new(CopyOutput)
|
||||||
|
var nr int
|
||||||
|
var er error
|
||||||
|
buf := make([]byte, 32*1024)
|
||||||
|
for {
|
||||||
|
nr, er = src.Read(buf)
|
||||||
|
if nr > 0 {
|
||||||
|
copyAndUpdate(dst1, buf[0:nr], copyOutput1)
|
||||||
|
copyAndUpdate(dst2, buf[0:nr], copyOutput2)
|
||||||
|
}
|
||||||
|
if copyOutput1.Err != nil && copyOutput2.Err != nil {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
if er == io.EOF {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
if er != nil {
|
||||||
|
copyOutput1.Err = er
|
||||||
|
copyOutput2.Err = er
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
@@ -0,0 +1,29 @@
|
|||||||
|
package payload
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"io"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Buffer struct {
|
||||||
|
bytes.Buffer
|
||||||
|
io.ReaderFrom // conflicts with and hides bytes.Buffer's ReaderFrom.
|
||||||
|
io.WriterTo // conflicts with and hides bytes.Buffer's WriterTo.
|
||||||
|
}
|
||||||
|
|
||||||
|
// Simple tests, primarily to verify the ReadFrom and WriteTo callouts inside Copy and CopyN.
|
||||||
|
|
||||||
|
func TestCopy(t *testing.T) {
|
||||||
|
rb := new(Buffer)
|
||||||
|
wb1 := new(Buffer)
|
||||||
|
wb2 := new(Buffer)
|
||||||
|
rb.WriteString("hello, world.")
|
||||||
|
CopyToTwoWriters(wb1, wb2, rb)
|
||||||
|
if wb1.String() != "hello, world." {
|
||||||
|
t.Errorf("Copy did not work properly")
|
||||||
|
}
|
||||||
|
if wb2.String() != "hello, world." {
|
||||||
|
t.Errorf("Copy did not work properly")
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,45 @@
|
|||||||
|
package payload
|
||||||
|
|
||||||
|
import (
|
||||||
|
cryptoSHA512 "crypto/sha512"
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"hash"
|
||||||
|
"io"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Hash string
|
||||||
|
|
||||||
|
const SHA512 Hash = "sha512"
|
||||||
|
|
||||||
|
func (this Hash) New() (hash.Hash, error) {
|
||||||
|
switch this {
|
||||||
|
case SHA512:
|
||||||
|
return cryptoSHA512.New(), nil
|
||||||
|
default:
|
||||||
|
msg := fmt.Sprintf("hash '%s' is not supported")
|
||||||
|
return nil, errors.New(msg)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this Hash) HashOnTheWay(data io.Reader, resultingHash chan []byte) (io.Reader, error) {
|
||||||
|
h, err := this.New()
|
||||||
|
pipeReader, pipeWriter := io.Pipe()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
go func(resultingHash chan []byte) {
|
||||||
|
ou1, ou2 := CopyToTwoWriters(h, pipeWriter, data)
|
||||||
|
if ou1.Err != nil {
|
||||||
|
panic(ou1.Err)
|
||||||
|
}
|
||||||
|
if ou2.Err != nil {
|
||||||
|
panic(ou2.Err)
|
||||||
|
}
|
||||||
|
if err := pipeWriter.Close(); err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
resultingHash <- h.Sum(nil)
|
||||||
|
}(resultingHash)
|
||||||
|
return pipeReader, nil
|
||||||
|
}
|
||||||
@@ -0,0 +1,78 @@
|
|||||||
|
package payload
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
cryptoSHA512 "crypto/sha512"
|
||||||
|
"encoding/hex"
|
||||||
|
"errors"
|
||||||
|
"github.com/didiercrunch/ecrypto/helper"
|
||||||
|
"hash"
|
||||||
|
"io"
|
||||||
|
"io/ioutil"
|
||||||
|
"reflect"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
var __ = ioutil.Discard
|
||||||
|
|
||||||
|
func TestUnsupportedHash(t *testing.T) {
|
||||||
|
unsupportedHashes := []Hash{"md5"}
|
||||||
|
for _, h := range unsupportedHashes {
|
||||||
|
if _, err := h.New(); err == nil {
|
||||||
|
t.Error("should have an error here")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func assertHashIsOkay(h hash.Hash, expectedHash hash.Hash) error {
|
||||||
|
h.Reset()
|
||||||
|
expectedHash.Reset()
|
||||||
|
h.Write(helper.Range(1025))
|
||||||
|
expectedHash.Write(helper.Range(1025))
|
||||||
|
if !reflect.DeepEqual(h.Sum(nil), expectedHash.Sum(nil)) {
|
||||||
|
return errors.New("bad hash")
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSHA512(t *testing.T) {
|
||||||
|
if h, err := SHA512.New(); err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
return
|
||||||
|
} else if err = assertHashIsOkay(h, cryptoSHA512.New()); err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestHashOnTheWay(t *testing.T) {
|
||||||
|
data := bytes.NewBufferString("some data to hash")
|
||||||
|
expectedHash, err := hex.DecodeString("c874e4001dbd67d770c47bc1bac090be069" +
|
||||||
|
"2ffcd5bb995de7df96a7100f05e061b85307657e6595d25ffd6931793892dd0215e64" +
|
||||||
|
"da97bb73c969b5fcfd2aed49")
|
||||||
|
_ = expectedHash
|
||||||
|
if err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
outputHash := make(chan []byte)
|
||||||
|
var outputReader io.Reader
|
||||||
|
if outputReader, err = SHA512.HashOnTheWay(data, outputHash); err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
}
|
||||||
|
errorC := make(chan error)
|
||||||
|
go func(errorC chan error) {
|
||||||
|
if output, err := ioutil.ReadAll(outputReader); err != nil {
|
||||||
|
errorC <- err
|
||||||
|
} else if string(output) != "some data to hash" {
|
||||||
|
errorC <- errors.New("output is not 'some data to hash' but: " + string(output))
|
||||||
|
}
|
||||||
|
errorC <- nil
|
||||||
|
|
||||||
|
}(errorC)
|
||||||
|
if err := <-errorC; err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
}
|
||||||
|
if !reflect.DeepEqual(<-outputHash, expectedHash) {
|
||||||
|
t.Error("bad hash\nexpected: ", expectedHash, "\nreceived:", outputHash)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,37 @@
|
|||||||
|
package payload
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/hex"
|
||||||
|
"encoding/json"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Metadata struct {
|
||||||
|
IV []byte
|
||||||
|
Key []byte
|
||||||
|
}
|
||||||
|
|
||||||
|
type jsonMetada struct {
|
||||||
|
IV string
|
||||||
|
Key string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *Metadata) MarshalJSON() ([]byte, error) {
|
||||||
|
ret := &jsonMetada{
|
||||||
|
IV: hex.EncodeToString(this.IV),
|
||||||
|
Key: hex.EncodeToString(this.Key),
|
||||||
|
}
|
||||||
|
return json.Marshal(ret)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *Metadata) UnmarshalJSON(data []byte) (err error) {
|
||||||
|
ret := &jsonMetada{}
|
||||||
|
if err = json.Unmarshal(data, ret); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if this.IV, err = hex.DecodeString(ret.IV); err != nil {
|
||||||
|
return
|
||||||
|
} else if this.Key, err = hex.DecodeString(ret.Key); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
@@ -0,0 +1,30 @@
|
|||||||
|
package payload
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"github.com/didiercrunch/ecrypto/helper"
|
||||||
|
"reflect"
|
||||||
|
"strings"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestJsonifyMetadata(t *testing.T) {
|
||||||
|
m := &Metadata{helper.Range(10), helper.Range(12)}
|
||||||
|
marshaled, err := json.Marshal(m)
|
||||||
|
if err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if !strings.Contains(string(marshaled), `"000102030405060708090a0b"`) {
|
||||||
|
t.Error(`marshaled data should containe "000102030405060708090a0b"`, "\n", string(marshaled))
|
||||||
|
}
|
||||||
|
um := new(Metadata)
|
||||||
|
if err := json.Unmarshal(marshaled, um); err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if !reflect.DeepEqual(m, um) {
|
||||||
|
t.Error(m, " is not ", um)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
+113
-56
@@ -1,84 +1,141 @@
|
|||||||
package payload
|
package payload
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"crypto"
|
"archive/zip"
|
||||||
"crypto/cipher"
|
"crypto/cipher"
|
||||||
"fmt"
|
"encoding/json"
|
||||||
"io"
|
"io"
|
||||||
)
|
)
|
||||||
|
|
||||||
var _ = fmt.Print
|
|
||||||
|
|
||||||
/*
|
|
||||||
type Payload interface {
|
|
||||||
GetHash() []byte
|
|
||||||
GetKey() []byte
|
|
||||||
GetAlgorithm() string
|
|
||||||
GetMode() string
|
|
||||||
GetHashMethod() string
|
|
||||||
GetPayloadData() io.Reader
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
type BlockMode string
|
|
||||||
|
|
||||||
const OFB BlockMode = "ofb"
|
|
||||||
|
|
||||||
type BlockModeStream func(block cipher.Block, iv []byte) cipher.Stream
|
type BlockModeStream func(block cipher.Block, iv []byte) cipher.Stream
|
||||||
|
|
||||||
type Payload struct {
|
type Payload struct {
|
||||||
DataSource io.Reader
|
DataSource io.Reader
|
||||||
Hash crypto.Hash
|
Random io.Reader
|
||||||
|
HashMethod Hash
|
||||||
Block Block
|
Block Block
|
||||||
BlockMode BlockMode
|
BlockMode BlockMode
|
||||||
|
|
||||||
|
IV []byte
|
||||||
|
Key []byte
|
||||||
|
Hash []byte
|
||||||
|
}
|
||||||
|
|
||||||
|
type payloadWriter struct {
|
||||||
|
Reader io.Reader
|
||||||
|
Pipewriter io.WriteCloser
|
||||||
|
ZipWriter *zip.Writer
|
||||||
|
}
|
||||||
|
|
||||||
|
func getPayloadWriter() *payloadWriter {
|
||||||
|
p := new(payloadWriter)
|
||||||
|
p.Reader, p.Pipewriter = io.Pipe()
|
||||||
|
p.ZipWriter = zip.NewWriter(p.Pipewriter)
|
||||||
|
return p
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *payloadWriter) getDataWriter() (io.Writer, error) {
|
||||||
|
return this.ZipWriter.Create("data")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *payloadWriter) getMetadataWriter() (io.Writer, error) {
|
||||||
|
return this.ZipWriter.Create("metadata")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *payloadWriter) Close() error {
|
||||||
|
if err := this.ZipWriter.Close(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return this.Pipewriter.Close()
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *Payload) GetMode() string {
|
||||||
|
return string(this.BlockMode)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *Payload) GetHash() []byte {
|
||||||
|
return this.Hash
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *Payload) GetKey() []byte {
|
||||||
|
return this.Key
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *Payload) GetAlgorithm() string {
|
||||||
|
return string(this.Block)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (this *Payload) GetHashMethod() string {
|
func (this *Payload) GetHashMethod() string {
|
||||||
switch this.Hash {
|
return string(this.HashMethod)
|
||||||
case crypto.MD5:
|
}
|
||||||
return "md5"
|
|
||||||
case crypto.MD4:
|
func (this *Payload) GetPayloadData() (io.Reader, error) {
|
||||||
return "md4"
|
pw := getPayloadWriter()
|
||||||
case crypto.SHA1:
|
stream, err := this.getStreamAndCreateMetadata()
|
||||||
return "sha1"
|
if err != nil {
|
||||||
case crypto.MD5SHA1:
|
return nil, err
|
||||||
return "md5sha1"
|
|
||||||
case crypto.RIPEMD160:
|
|
||||||
return "ripemd160"
|
|
||||||
case crypto.SHA224:
|
|
||||||
return "sha224"
|
|
||||||
case crypto.SHA256:
|
|
||||||
return "sha256"
|
|
||||||
case crypto.SHA384:
|
|
||||||
return "sha384"
|
|
||||||
case crypto.SHA512:
|
|
||||||
return "sha512"
|
|
||||||
default:
|
|
||||||
panic("unknown hash method")
|
|
||||||
}
|
}
|
||||||
|
go func(payload *Payload, pw *payloadWriter) {
|
||||||
|
if mdw, err := pw.getMetadataWriter(); err != nil {
|
||||||
|
panic(err)
|
||||||
|
} else if err := payload.writeMetadata(mdw); err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if mw, err := pw.getDataWriter(); err != nil {
|
||||||
|
panic(err)
|
||||||
|
} else if _, err := io.Copy(mw, payload.DataSource); err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
if err := pw.Close(); err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
}(this, pw)
|
||||||
|
|
||||||
|
return this.encrypt(pw.Reader, stream)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (this *Payload) GetPayloadData() io.Reader {
|
func (this *Payload) writeMetadata(w io.Writer) error {
|
||||||
// zip data source
|
e := json.NewEncoder(w)
|
||||||
|
return e.Encode(this.getMetadata())
|
||||||
// create metadata
|
|
||||||
// zip the zipped data and metadata
|
|
||||||
|
|
||||||
// encryptp everything togeter
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (this *Payload) getStream() cipher.Stream {
|
func (this *Payload) getMetadata() *Metadata {
|
||||||
return nil //this.BlockMode
|
return &Metadata{IV: this.IV, Key: this.Key}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (this *Payload) encrypt(reader io.Reader) io.Reader {
|
func (this *Payload) getStreamAndCreateMetadata() (stream cipher.Stream, err error) {
|
||||||
|
var block cipher.Block
|
||||||
|
block, this.Key, err = this.Block.CreateBlock(this.Random)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
stream, this.IV, err = this.BlockMode.GetCipherStream(block, this.Random)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *Payload) computeHash(reader io.Reader) (io.Reader, error) {
|
||||||
|
readerHash := make(chan []byte)
|
||||||
|
read, err := this.HashMethod.HashOnTheWay(reader, readerHash)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
go func(readerHash chan []byte) {
|
||||||
|
this.Hash = <-readerHash
|
||||||
|
}(readerHash)
|
||||||
|
|
||||||
|
return read, nil
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *Payload) encrypt(reader io.Reader, stream cipher.Stream) (io.Reader, error) {
|
||||||
ret, writer := io.Pipe()
|
ret, writer := io.Pipe()
|
||||||
go func() {
|
go func(stream cipher.Stream) {
|
||||||
cipherWriter := &cipher.StreamWriter{S: this.getStream(), W: writer}
|
cipherWriter := &cipher.StreamWriter{S: stream, W: writer}
|
||||||
io.Copy(cipherWriter, reader)
|
io.Copy(cipherWriter, reader)
|
||||||
cipherWriter.Close()
|
cipherWriter.Close()
|
||||||
}()
|
}(stream)
|
||||||
return ret
|
return this.computeHash(ret)
|
||||||
|
|
||||||
}
|
}
|
||||||
+115
-20
@@ -2,49 +2,144 @@ package payload
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"crypto"
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"github.com/didiercrunch/ecrypto/helper"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
|
"reflect"
|
||||||
"testing"
|
"testing"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestPayloadGetHashMethod(t *testing.T) {
|
func TestPayloadGetHashMethod(t *testing.T) {
|
||||||
p := new(Payload)
|
p := new(Payload)
|
||||||
testCases := make(map[string]crypto.Hash)
|
testCases := make(map[string]Hash)
|
||||||
testCases["md4"] = crypto.MD4
|
testCases["sha512"] = SHA512
|
||||||
testCases["md5"] = crypto.MD5
|
|
||||||
testCases["sha1"] = crypto.SHA1
|
|
||||||
testCases["sha224"] = crypto.SHA224
|
|
||||||
testCases["sha256"] = crypto.SHA256
|
|
||||||
testCases["sha384"] = crypto.SHA384
|
|
||||||
testCases["sha512"] = crypto.SHA512
|
|
||||||
testCases["md5sha1"] = crypto.MD5SHA1
|
|
||||||
testCases["ripemd160"] = crypto.RIPEMD160
|
|
||||||
for name, hashfunc := range testCases {
|
for name, hashfunc := range testCases {
|
||||||
p.Hash = hashfunc
|
p.HashMethod = hashfunc
|
||||||
if returnedName := p.GetHashMethod(); returnedName != name {
|
if returnedName := p.GetHashMethod(); returnedName != name {
|
||||||
t.Error("bad hash name. supposed to be ", name, " but received", returnedName)
|
t.Error("bad hash name. supposed to be ", name, " but received", returnedName)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestGetStream(t *testing.T) {
|
func TestGetStreamAndCreateMetadata(t *testing.T) {
|
||||||
p := new(Payload)
|
p := new(Payload)
|
||||||
if s := p.getStream(); s != nil {
|
p.Block = AES256
|
||||||
|
p.BlockMode = OFB
|
||||||
|
p.Random = helper.NewMockRandomReader()
|
||||||
|
if _, err := p.getStreamAndCreateMetadata(); err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
} else if len(p.Key) != 256/8 {
|
||||||
|
t.Fail()
|
||||||
|
} else if len(p.IV) != 128/8 {
|
||||||
t.Fail()
|
t.Fail()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestEncrypt(t *testing.T) {
|
func TestEncrypt(t *testing.T) {
|
||||||
if true {
|
p := new(Payload)
|
||||||
|
p.Block = AES256
|
||||||
|
p.HashMethod = SHA512
|
||||||
|
p.BlockMode = OFB
|
||||||
|
p.Random = helper.NewMockRandomReader()
|
||||||
|
data := bytes.NewBufferString("nice string")
|
||||||
|
stream, err := p.getStreamAndCreateMetadata()
|
||||||
|
if err != nil {
|
||||||
|
t.Error(err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
p := new(Payload)
|
reader, err := p.encrypt(data, stream)
|
||||||
data := bytes.NewBufferString("nice string")
|
if err != nil {
|
||||||
reader := p.encrypt(data)
|
t.Error(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
go func(t *testing.T) {
|
||||||
if outputdata, err := ioutil.ReadAll(reader); err != nil {
|
if outputdata, err := ioutil.ReadAll(reader); err != nil {
|
||||||
t.Error(err)
|
t.Error(err)
|
||||||
} else if string(outputdata) != "nice string" {
|
} else if !reflect.DeepEqual(outputdata, []byte{0, 124, 45, 17, 57, 48, 19, 154, 180, 15, 43}) {
|
||||||
t.Fail()
|
t.Error("bad output data")
|
||||||
|
}
|
||||||
|
}(t)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestGetMode(t *testing.T) {
|
||||||
|
p := new(Payload)
|
||||||
|
p.BlockMode = OFB
|
||||||
|
if p.GetMode() != "ofb" {
|
||||||
|
t.Error("bad block mode")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestGetAlgorithm(t *testing.T) {
|
||||||
|
p := new(Payload)
|
||||||
|
p.Block = AES256
|
||||||
|
if p.GetAlgorithm() != "aes256" {
|
||||||
|
t.Error("bad block")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestPayloadWriter(t *testing.T) {
|
||||||
|
pw := getPayloadWriter()
|
||||||
|
go func(t *testing.T) { // Need this section!
|
||||||
|
if _, err := ioutil.ReadAll(pw.Reader); err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
}
|
||||||
|
}(t)
|
||||||
|
if w, err := pw.getDataWriter(); err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
} else {
|
||||||
|
fmt.Fprint(w, "some data")
|
||||||
|
}
|
||||||
|
|
||||||
|
if w, err := pw.getMetadataWriter(); err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
} else {
|
||||||
|
fmt.Fprint(w, "some meta data")
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := pw.Close(); err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestWriteMetadata(t *testing.T) {
|
||||||
|
p := new(Payload)
|
||||||
|
p.Key = []byte{0, 1, 0, 1}
|
||||||
|
p.IV = []byte{10, 11, 10, 11}
|
||||||
|
w := helper.NewMockIoWriter()
|
||||||
|
if err := p.writeMetadata(w); err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
return
|
||||||
|
} else if !w.IsValidJson() {
|
||||||
|
t.Error(w, "is not valid json")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestGetPayloadData(t *testing.T) {
|
||||||
|
p := new(Payload)
|
||||||
|
p.DataSource = bytes.NewBufferString("some data to encrypt")
|
||||||
|
p.Block = AES256
|
||||||
|
p.BlockMode = OFB
|
||||||
|
p.HashMethod = SHA512
|
||||||
|
p.Random = helper.NewMockRandomReader()
|
||||||
|
r, err := p.GetPayloadData()
|
||||||
|
if err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
errorC := make(chan error)
|
||||||
|
go func(errorC chan error) {
|
||||||
|
if _, err := ioutil.ReadAll(r); err != nil {
|
||||||
|
errorC <- err
|
||||||
|
}
|
||||||
|
errorC <- nil
|
||||||
|
}(errorC)
|
||||||
|
|
||||||
|
if err := <-errorC; err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
} else if len(p.GetHash()) != 512/8 {
|
||||||
|
fmt.Println(p.GetHash())
|
||||||
|
errorC <- errors.New("hash has not been computed")
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -1,27 +0,0 @@
|
|||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"io"
|
|
||||||
)
|
|
||||||
|
|
||||||
type Params struct {
|
|
||||||
}
|
|
||||||
|
|
||||||
type Envelop struct {
|
|
||||||
err error
|
|
||||||
params *Params
|
|
||||||
}
|
|
||||||
|
|
||||||
func ZipIoReader(reader io.Reader) {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
func createEnvelop(reader io.Reader, writer io.WriteCloser, params *Params) error {
|
|
||||||
env := &Envelop{nil, params}
|
|
||||||
env.ZipDataForPayload()
|
|
||||||
env.CreatePayloadMetadata()
|
|
||||||
env.EncryptPayload()
|
|
||||||
env.CreateEnvelopMetadata()
|
|
||||||
env.EncryptPayloadKeyAndAddItToEncelop()
|
|
||||||
return env.getError()
|
|
||||||
}
|
|
||||||
Reference in new issue
Block a user