payload almost done
This commit is contained in:
1 parent
77bfcba5b1
commit
09d0f237d5
16 files changed
+690
-118
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 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
|
||||
| | |
|
||||
| | |
|
||||
| | |
|
||||
|
||||
+20
-2
@@ -4,6 +4,7 @@ import (
|
||||
"bytes"
|
||||
"crypto/rsa"
|
||||
"encoding/binary"
|
||||
"encoding/json"
|
||||
"io"
|
||||
"math/big"
|
||||
"math/rand"
|
||||
@@ -14,11 +15,12 @@ func B(x int64) *big.Int {
|
||||
}
|
||||
|
||||
type MockRandomReader struct {
|
||||
random *rand.Rand
|
||||
readLength int
|
||||
random *rand.Rand
|
||||
}
|
||||
|
||||
func NewMockRandomReader() *MockRandomReader {
|
||||
return &MockRandomReader{rand.New(rand.NewSource(99))}
|
||||
return &MockRandomReader{0, rand.New(rand.NewSource(99))}
|
||||
}
|
||||
|
||||
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 {
|
||||
copy(p[i:], this.getNextFourRandomBytes())
|
||||
}
|
||||
this.readLength += len(p)
|
||||
return len(p), nil
|
||||
}
|
||||
|
||||
func (this *MockRandomReader) GetReadLength() int {
|
||||
return this.readLength
|
||||
}
|
||||
|
||||
func (this *MockRandomReader) GetRandomBytes(size int) []byte {
|
||||
ret := make([]byte, size)
|
||||
this.Read(ret)
|
||||
@@ -74,6 +81,17 @@ func (this *MockIoWriter) ReaderAt() io.ReaderAt {
|
||||
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 {
|
||||
ret := make([]byte, length)
|
||||
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) {
|
||||
privateKey := GetRSAPrivateKey(50)
|
||||
if err := privateKey.Validate(); err != nil {
|
||||
@@ -60,7 +80,7 @@ func TestGetRSAPublicKeyAndGetRSAPrivateKey(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()
|
||||
var expt []byte = []byte{233, 237, 107, 32}
|
||||
if len(rb) != 4 {
|
||||
@@ -103,3 +123,15 @@ func TestGetRandomBytes(t *testing.T) {
|
||||
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
|
||||
key := make([]byte, 256/8)
|
||||
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 (
|
||||
"crypto"
|
||||
"crypto/aes"
|
||||
"crypto/cipher"
|
||||
"errors"
|
||||
"fmt"
|
||||
"github.com/didiercrunch/ecrypto/helper"
|
||||
"reflect"
|
||||
"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) {
|
||||
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)
|
||||
} else {
|
||||
_ = block
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,11 +45,13 @@ func Testhash512BytesOfData(t *testing.T) {
|
||||
if _, err := hash512BytesOfData(crypto.MD5, helper.NewMockRandomReader()); err == nil {
|
||||
t.Error("should never allow MD5 hash")
|
||||
}
|
||||
rd := helper.NewMockRandomReader()
|
||||
if rd, err := hash512BytesOfData(crypto.SHA512, rd); err != nil {
|
||||
randomGenerator := helper.NewMockRandomReader()
|
||||
if rd, err := hash512BytesOfData(crypto.SHA512, randomGenerator); err != nil {
|
||||
t.Error(err)
|
||||
} else if len(rd) != 512/8 {
|
||||
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
|
||||
|
||||
import (
|
||||
"crypto"
|
||||
"archive/zip"
|
||||
"crypto/cipher"
|
||||
"fmt"
|
||||
"encoding/json"
|
||||
"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 Payload struct {
|
||||
DataSource io.Reader
|
||||
Hash crypto.Hash
|
||||
Random io.Reader
|
||||
HashMethod Hash
|
||||
Block Block
|
||||
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 {
|
||||
switch this.Hash {
|
||||
case crypto.MD5:
|
||||
return "md5"
|
||||
case crypto.MD4:
|
||||
return "md4"
|
||||
case crypto.SHA1:
|
||||
return "sha1"
|
||||
case crypto.MD5SHA1:
|
||||
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")
|
||||
return string(this.HashMethod)
|
||||
}
|
||||
|
||||
func (this *Payload) GetPayloadData() (io.Reader, error) {
|
||||
pw := getPayloadWriter()
|
||||
stream, err := this.getStreamAndCreateMetadata()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
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 {
|
||||
// zip data source
|
||||
|
||||
// create metadata
|
||||
// zip the zipped data and metadata
|
||||
|
||||
// encryptp everything togeter
|
||||
return nil
|
||||
func (this *Payload) writeMetadata(w io.Writer) error {
|
||||
e := json.NewEncoder(w)
|
||||
return e.Encode(this.getMetadata())
|
||||
}
|
||||
|
||||
func (this *Payload) getStream() cipher.Stream {
|
||||
return nil //this.BlockMode
|
||||
func (this *Payload) getMetadata() *Metadata {
|
||||
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()
|
||||
go func() {
|
||||
cipherWriter := &cipher.StreamWriter{S: this.getStream(), W: writer}
|
||||
go func(stream cipher.Stream) {
|
||||
cipherWriter := &cipher.StreamWriter{S: stream, W: writer}
|
||||
io.Copy(cipherWriter, reader)
|
||||
cipherWriter.Close()
|
||||
}()
|
||||
return ret
|
||||
}(stream)
|
||||
return this.computeHash(ret)
|
||||
|
||||
}
|
||||
+116
-21
@@ -2,49 +2,144 @@ package payload
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"crypto"
|
||||
"errors"
|
||||
"fmt"
|
||||
"github.com/didiercrunch/ecrypto/helper"
|
||||
"io/ioutil"
|
||||
"reflect"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestPayloadGetHashMethod(t *testing.T) {
|
||||
p := new(Payload)
|
||||
testCases := make(map[string]crypto.Hash)
|
||||
testCases["md4"] = crypto.MD4
|
||||
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
|
||||
testCases := make(map[string]Hash)
|
||||
testCases["sha512"] = SHA512
|
||||
for name, hashfunc := range testCases {
|
||||
p.Hash = hashfunc
|
||||
p.HashMethod = hashfunc
|
||||
if returnedName := p.GetHashMethod(); returnedName != name {
|
||||
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)
|
||||
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()
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
p := new(Payload)
|
||||
data := bytes.NewBufferString("nice string")
|
||||
reader := p.encrypt(data)
|
||||
if outputdata, err := ioutil.ReadAll(reader); err != nil {
|
||||
reader, err := p.encrypt(data, stream)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
} else if string(outputdata) != "nice string" {
|
||||
t.Fail()
|
||||
return
|
||||
}
|
||||
go func(t *testing.T) {
|
||||
if outputdata, err := ioutil.ReadAll(reader); err != nil {
|
||||
t.Error(err)
|
||||
} else if !reflect.DeepEqual(outputdata, []byte{0, 124, 45, 17, 57, 48, 19, 154, 180, 15, 43}) {
|
||||
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