From e80f2601ab091d0c363dec5d4701ab9472ffb6f3 Mon Sep 17 00:00:00 2001 From: "didier.amyot" Date: Sat, 1 Nov 2014 16:00:06 -0700 Subject: [PATCH] my computer is about to die!!! --- contract/best_contract.go | 12 ++------ files/doc.go | 3 ++ files/encrypt_file.go | 15 ++++++++++ files/files.go | 39 ++++++++++++++++++++++++ files/files_test.go | 63 +++++++++++++++++++++++++++++++++++++++ helper/helper.go | 13 ++++++++ helper/helper_test.go | 21 +++++++++++++ helper/test_helper.go | 18 +++++++++++ payload/block.go | 8 +++++ payload/hash.go | 8 +++++ payload/hash_test.go | 20 +++++++++++-- payload/payload.go | 13 ++++++++ payload/payload_test.go | 22 ++++++++++++++ 13 files changed, 244 insertions(+), 11 deletions(-) create mode 100644 files/doc.go create mode 100644 files/encrypt_file.go create mode 100644 files/files.go create mode 100644 files/files_test.go create mode 100644 helper/helper.go create mode 100644 helper/helper_test.go diff --git a/contract/best_contract.go b/contract/best_contract.go index ebe8bc0..1be60c0 100644 --- a/contract/best_contract.go +++ b/contract/best_contract.go @@ -2,7 +2,8 @@ package contract import ( "errors" - "strings" + + "github.com/didiercrunch/filou/helper" ) type AcceptedContract struct { @@ -21,13 +22,6 @@ func listContains(lst []string, elm string) bool { return false } -func joinAsError(msg []string) error { - if len(msg) > 0 { - return errors.New(strings.Join(msg, "\n")) - } - return nil -} - func getFirstItemInList1ThatIsAlsoInList2(lst1, lst2 []string) (string, error) { for _, elm := range lst1 { if listContains(lst2, elm) { @@ -75,5 +69,5 @@ func GetAcceptedContract(prvCtr *PrivateContract, pubCtr *PublicContract) (*Acce errs = append(errs, err.Error()) } - return ret, joinAsError(errs) + return ret, helper.JoinAsError(errs) } diff --git a/files/doc.go b/files/doc.go new file mode 100644 index 0000000..4a101fc --- /dev/null +++ b/files/doc.go @@ -0,0 +1,3 @@ +package files + +// package that manage the encryption of files and directory diff --git a/files/encrypt_file.go b/files/encrypt_file.go new file mode 100644 index 0000000..c466eed --- /dev/null +++ b/files/encrypt_file.go @@ -0,0 +1,15 @@ +package files + +import ( + "io" + + "github.com/didiercrunch/filou/contract" + "github.com/didiercrunch/filou/envelop" + "github.com/didiercrunch/filou/payload" +) + +func EncryptFile(reader io.Reader, writer io.Writer, acceptedContract *contract.AcceptedContract) error { + payload_ := payload.GetDefaultPayload(reader) + envelop := envelop.NewEnveloper(nil, payload_, nil) + return envelop.WriteToWriter(writer) +} diff --git a/files/files.go b/files/files.go new file mode 100644 index 0000000..6997388 --- /dev/null +++ b/files/files.go @@ -0,0 +1,39 @@ +package files + +import ( + "fmt" + "io" + "os" + + "github.com/didiercrunch/filou/contract" +) + +var _ = fmt.Print + +type encryptor func(reader io.Reader, writer io.Writer, acceptedContract *contract.AcceptedContract) error + +type PathEncryptor struct { + EncryptFile encryptor + EncryptDirectory encryptor +} + +func (this *PathEncryptor) EncryptPath(path string, writer io.Writer, acceptedContract *contract.AcceptedContract) error { + f, err := os.Open(path) + if err != nil { + return err + } + + defer func() { + if err := f.Close(); err != nil { + panic(err) + } + }() + + if fd, err := f.Stat(); err != nil { + return err + } else if fd.IsDir() { + return this.EncryptDirectory(f, writer, acceptedContract) + } else { + return this.EncryptFile(f, writer, acceptedContract) + } +} diff --git a/files/files_test.go b/files/files_test.go new file mode 100644 index 0000000..3bda913 --- /dev/null +++ b/files/files_test.go @@ -0,0 +1,63 @@ +package files + +import ( + "fmt" + "io" + "testing" + + "github.com/didiercrunch/filou/contract" + "github.com/didiercrunch/filou/helper" +) + +var _ = fmt.Print + +type mockEncryptor struct { + N int +} + +func (this *mockEncryptor) Encrypt(reader io.Reader, writer io.Writer, acceptedContract *contract.AcceptedContract) error { + this.N += 1 + return nil +} + +func TestEncryptPathWrongPath(t *testing.T) { + pe := new(PathEncryptor) + + filePath := "/something_that_does_not_exists" + if err := pe.EncryptPath(filePath, nil, nil); err == nil { + t.Error("should say the file does not exists") + } +} + +func TestEncryptPathForDirectory(t *testing.T) { + dirName := helper.GetTmpEmptyDir() + fileEncryptor, dirEncryptor := new(mockEncryptor), new(mockEncryptor) + pe := &PathEncryptor{fileEncryptor.Encrypt, dirEncryptor.Encrypt} + + if err := pe.EncryptPath(dirName, nil, nil); err != nil { + t.Error(err) + } else if fileEncryptor.N != 0 { + t.Error("should have 0", fileEncryptor.N) + } else if dirEncryptor.N != 1 { + t.Error("should have 1", dirEncryptor.N) + } +} + +func TestEncryptPathForFile(t *testing.T) { + file := helper.GetTmpEmptyFile() + defer func() { + if err := file.Close(); err != nil { + t.Error(err) + } + }() + fileEncryptor, dirEncryptor := new(mockEncryptor), new(mockEncryptor) + pe := &PathEncryptor{fileEncryptor.Encrypt, dirEncryptor.Encrypt} + + if err := pe.EncryptPath(file.Name(), nil, nil); err != nil { + t.Error(err) + } else if fileEncryptor.N != 1 { + t.Error("should have 1", fileEncryptor.N) + } else if dirEncryptor.N != 0 { + t.Error("should have 0", dirEncryptor.N) + } +} diff --git a/helper/helper.go b/helper/helper.go new file mode 100644 index 0000000..a9f38d0 --- /dev/null +++ b/helper/helper.go @@ -0,0 +1,13 @@ +package helper + +import ( + "errors" + "strings" +) + +func JoinAsError(msg []string) error { + if len(msg) > 0 { + return errors.New(strings.Join(msg, "\n")) + } + return nil +} diff --git a/helper/helper_test.go b/helper/helper_test.go new file mode 100644 index 0000000..27d491c --- /dev/null +++ b/helper/helper_test.go @@ -0,0 +1,21 @@ +package helper + +import ( + "testing" +) + +func TestJoinAsError(t *testing.T) { + var errs []string = nil + if JoinAsError(errs) != nil { + t.Error("expected no errors") + } + errs = make([]string, 0) + if JoinAsError(errs) != nil { + t.Error("expected no errors") + } + + errs = []string{"a", "b"} + if JoinAsError(errs).Error() != "a\nb" { + t.Error("bad error") + } +} diff --git a/helper/test_helper.go b/helper/test_helper.go index 881eff1..6506092 100644 --- a/helper/test_helper.go +++ b/helper/test_helper.go @@ -6,8 +6,10 @@ import ( "encoding/binary" "encoding/json" "io" + "io/ioutil" "math/big" "math/rand" + "os" ) func B(x int64) *big.Int { @@ -120,3 +122,19 @@ func GetRSAPrivateKey(size int) *rsa.PrivateKey { return key } + +func GetTmpEmptyFile() *os.File { + if f, err := ioutil.TempFile("", ""); err != nil { + panic(err) + } else { + return f + } +} + +func GetTmpEmptyDir() string { + if dirName, err := ioutil.TempDir("", ""); err != nil { + panic(err) + } else { + return dirName + } +} diff --git a/payload/block.go b/payload/block.go index a827107..396d53b 100644 --- a/payload/block.go +++ b/payload/block.go @@ -45,3 +45,11 @@ func (this Block) CreateBlock(rd io.Reader) (cipher.Block, []byte, error) { block, err := aes.NewCipher(key) return block, key, err } + +func GetBlockByBlockName(blockName string) (Block, error) { + ret := Hash(hashName) + if _, err := ret.New(); err != nil { + return "", errors.New("block encryption " + blockName + " is not supported") + } + return ret, nil +} diff --git a/payload/hash.go b/payload/hash.go index 073f2fc..ad9fa58 100644 --- a/payload/hash.go +++ b/payload/hash.go @@ -12,6 +12,14 @@ type Hash string const SHA512 Hash = "sha512" +func GetHashByHashName(hashName string) (Hash, error) { + ret := Hash(hashName) + if _, err := ret.New(); err != nil { + return "", errors.New("unsupported hash function " + hashName) + } + return ret, nil +} + func (this Hash) New() (hash.Hash, error) { switch this { case SHA512: diff --git a/payload/hash_test.go b/payload/hash_test.go index a89ff15..030b8ff 100644 --- a/payload/hash_test.go +++ b/payload/hash_test.go @@ -14,8 +14,6 @@ import ( "github.com/didiercrunch/filou/helper" ) -var __ = ioutil.Discard - func TestUnsupportedHash(t *testing.T) { unsupportedHashes := []Hash{"md5"} for _, h := range unsupportedHashes { @@ -77,3 +75,21 @@ func TestHashOnTheWay(t *testing.T) { t.Error("bad hash\nexpected: ", expectedHash, "\nreceived:", outputHash) } } + +func TestGetHashByHashNameForAcceptedHashFunctions(t *testing.T) { + acceptedHashFunctions := []string{"sha512"} + for _, h := range acceptedHashFunctions { + if _, err := GetHashByHashName(h); err != nil { + t.Error(err) + } + } +} + +func TestGetHashByHashNameForNotAcceptedHashFunctions(t *testing.T) { + unaccepterHashFunctions := []string{"md5"} + for _, h := range unaccepterHashFunctions { + if _, err := GetHashByHashName(h); err == nil { + t.Error("should never accept hash function " + h) + } + } +} diff --git a/payload/payload.go b/payload/payload.go index 7b64931..f9ef5c8 100644 --- a/payload/payload.go +++ b/payload/payload.go @@ -6,6 +6,8 @@ import ( "crypto/rand" "encoding/json" "io" + + "github.com/didiercrunch/filou/contract" ) type BlockModeStream func(block cipher.Block, iv []byte) cipher.Stream @@ -32,6 +34,17 @@ func GetDefaultPayload(dataSource io.Reader) *Payload { } } +func GetPayload(dataSource io.Reader, acceptedContract *contract.AcceptedContract) (*Payload, error) { + ret := &Payload{DataSource: dataSource, Random: rand.Reader} + errs := make([]error, 0) + var err error + if ret.HashMethod, err = GetHashByHashName(acceptedContract.Hash); err != nil { + errs = append(errs, err) + } + + return ret, nil +} + type payloadWriter struct { Reader io.Reader Pipewriter io.WriteCloser diff --git a/payload/payload_test.go b/payload/payload_test.go index 1452e0b..e2543d8 100644 --- a/payload/payload_test.go +++ b/payload/payload_test.go @@ -2,12 +2,14 @@ package payload import ( "bytes" + "crypto/rand" "errors" "fmt" "io/ioutil" "reflect" "testing" + "github.com/didiercrunch/filou/contract" "github.com/didiercrunch/filou/helper" ) @@ -166,3 +168,23 @@ func TestGetDefaultPayload(t *testing.T) { errorC <- errors.New("hash has not been computed") } } + +func TestGetPayload(t *testing.T) { + c := &contract.AcceptedContract{Hash: "sha512"} + p, err := GetPayload(nil, c) + if err != nil { + t.Error(err) + return + } + expectedPayload := &Payload{ + DataSource: nil, + Random: rand.Reader, + HashMethod: SHA512, + Block: AES256, + BlockMode: OFB, + } + if p.HashMethod != expectedPayload.HashMethod { + t.Error("bad hash method") + } + +}