diff --git a/src/git.xdrm.io/schastsp/lib/hash/hash.go b/src/git.xdrm.io/schastsp/lib/CyclicHash/CyclicHash.go similarity index 59% rename from src/git.xdrm.io/schastsp/lib/hash/hash.go rename to src/git.xdrm.io/schastsp/lib/CyclicHash/CyclicHash.go index 926d705..ccf82f8 100644 --- a/src/git.xdrm.io/schastsp/lib/hash/hash.go +++ b/src/git.xdrm.io/schastsp/lib/CyclicHash/CyclicHash.go @@ -1,13 +1,16 @@ -package hash +package CyclicHash -import "crypto/sha512" -import "git.xdrm.io/schastsp/lib/xor" +import ( + "errors" + "crypto/sha512" + "git.xdrm.io/schastsp/lib/xor" +) /* (0) Constants ---------------------------------------------------------*/ /* (1) Hash size */ const HBITSIZE uint = 512; -const HSIZE uint = HBITSIZE / 8; +const HSIZE uint = HBITSIZE / 8; @@ -40,22 +43,41 @@ func hash(input []byte) []byte{ * @input<[]byte> Byte array input * * @return digest<[]byte]> Byte array digest +* @return err If consistence error * ---------------------------------------------------------*/ -func Hash(input []byte, depth uint, salt []byte, pepper []byte) []byte { +func Hash(input []byte, depth uint, salt []byte, pepper []byte) ([]byte, error) { + + /* (1) Manage errors errors + ---------------------------------------------------------*/ + /* (1) Avoid no depth (no hash at all) */ + if( depth < 1 ){ + return nil, errors.New("Cannot use a 'depth' of zero. This is inconsistent and means that no hash will be processed"); + } + + /* (2) Avoir empty input */ + if( len(input) < 1 ){ + return nil, errors.New("Cannot use an empty 'input'. This is inconsistent"); + } + + + + /* (2) Process cyclic hash + ---------------------------------------------------------*/ /* (1) Initialise digest */ digest := make([]byte, 0, HSIZE) - /* (2) Process first hash with @salt */ + /* (2) Process first hash + salt */ digest = hash( xor.ByteArray(input, salt) ) - depth-- + if depth > 0 { depth-- } /* (3) Iterate @depth times */ for depth > 0 { // 1. Add Pepper for last time if( depth == 1 ){ + digest = hash( xor.ByteArray(digest, pepper) ) // 2. Else only hash @@ -64,9 +86,9 @@ func Hash(input []byte, depth uint, salt []byte, pepper []byte) []byte { } - depth-- + depth--; } - return digest + return digest, nil } diff --git a/src/git.xdrm.io/schastsp/lib/CyclicHash/CyclicHash_test.go b/src/git.xdrm.io/schastsp/lib/CyclicHash/CyclicHash_test.go new file mode 100644 index 0000000..2d81be8 --- /dev/null +++ b/src/git.xdrm.io/schastsp/lib/CyclicHash/CyclicHash_test.go @@ -0,0 +1,156 @@ +package CyclicHash + +import "testing" + +func TestSimpleHash(t *testing.T){ + + input := []byte("somePlainText"); + expected := []byte{ + 0x4c, 0xcb, 0x0e, 0xf6, 0x81, 0x99, 0x2e, 0xd6, 0xb8, 0x17, 0x52, 0x1d, 0x09, + 0x6e, 0x99, 0x19, 0xe7, 0xda, 0x50, 0xc8, 0xbf, 0x64, 0xae, 0xc1, 0x4f, 0xaa, + 0x47, 0x06, 0xf3, 0x49, 0x30, 0x8a, 0x90, 0x8e, 0xd2, 0xff, 0xc2, 0x6d, 0xee, + 0xaa, 0xd6, 0x45, 0xd8, 0xb3, 0x17, 0xe3, 0xb9, 0x45, 0x29, 0x26, 0xe2, 0x8e, + 0x99, 0x50, 0x94, 0x49, 0x90, 0x02, 0xa5, 0x61, 0x4a, 0x3f, 0x5e, 0xfa}; + got, err := Hash(input, 1, nil, nil); + digestLength := uint(len(got)); + + /* (2) Fail on errors */ + if err != nil { + t.Errorf("Expected no errors, got: %s", err); + } + + /* (2) Fail on wrong size */ + if digestLength != HSIZE { + t.Errorf("Expected hash digest of %d bytes ; %d bytes received", HSIZE, digestLength); + } + + /* (3) Check each byte */ + for k, v := range got{ + + if v != expected[k] { + t.Errorf("Expected sha[%d] of '%x' to be '%x' ; received '%x'", HSIZE, input, expected, got); + return; + } + + } + +} + + + +func TestDepth1Plus1Equals2(t *testing.T){ + + input := []byte("someOtherPlainText"); + + /* (1) Calculate H1 */ + h1, err := Hash(input, 1, nil, nil) + + if err != nil { + t.Errorf("Expected no error"); + return; + } + + /* (2) Calculate H1(H1) */ + h11, err := Hash(h1, 1, nil, nil); + + if err != nil { + t.Errorf("Expected no error"); + return; + } + + /* (3) Calculate H2 */ + h2, err := Hash(input, 1+1, nil, nil); + + if err != nil { + t.Errorf("Expected no error"); + return; + } + + /* (4) Manage different length */ + if len(h11) != len(h2) || len(h11) != int(HSIZE) { + t.Errorf("Expected digest lengths to be %d, got %d and %d", HSIZE, len(h11), len(h2)); + return; + } + + /* (5) Compare the 2 strings */ + for k, v := range h11 { + if v != h2[k] { + t.Errorf("Expected h2() to be equal to h1(h1())\n got '%x'\n expected '%x'", h2, h11) + return; + } + } + +} + + + +func TestDepth52Plus64Equals116(t *testing.T){ + + input := []byte("someOtherPlainText"); + + /* (1) Calculate H52 */ + h52, err := Hash(input, 52, nil, nil) + + if err != nil { + t.Errorf("Expected no error"); + return; + } + + /* (2) Calculate H52(H64) */ + h5264, err := Hash(h52, 64, nil, nil); + + if err != nil { + t.Errorf("Expected no error"); + return; + } + + /* (3) Calculate H116 */ + h116, err := Hash(input, 52+64, nil, nil); + + if err != nil { + t.Errorf("Expected no error"); + return; + } + + /* (4) Manage different length */ + if len(h5264) != len(h116) || len(h5264) != int(HSIZE) { + t.Errorf("Expected digest lengths to be %d, got %d and %d", HSIZE, len(h5264), len(h116)); + return; + } + + /* (5) Compare the 2 strings */ + for k, v := range h5264 { + if v != h116[k] { + t.Errorf("Expected h116() to be equal to h52(h64())\n got '%x'\n expected '%x'", h116, h5264) + return; + } + } + +} + + + +func TestDepthError(t *testing.T){ + + input := []byte("somePlainText"); + _, err := Hash(input, 0, nil, nil); + + /* (2) Fail on errors */ + if err == nil { + t.Errorf("Expected an error for depth of 0"); + } + +} + + + +func TestEmptyInputError(t *testing.T){ + + _, err := Hash(nil, 1, nil, nil); + + /* (2) Fail on errors */ + if err == nil { + t.Errorf("Expected an error for empty input"); + } + +} \ No newline at end of file diff --git a/src/git.xdrm.io/schastsp/lib/hash/hash_test.go b/src/git.xdrm.io/schastsp/lib/hash/hash_test.go deleted file mode 100644 index fe91168..0000000 --- a/src/git.xdrm.io/schastsp/lib/hash/hash_test.go +++ /dev/null @@ -1,70 +0,0 @@ -package hash - -import "testing" - -func TestSimpleHash(t *testing.T){ - - input := []byte("somePlainText"); - expected := []byte{ - 0x4c, 0xcb, 0x0e, 0xf6, 0x81, 0x99, 0x2e, 0xd6, 0xb8, 0x17, 0x52, 0x1d, 0x09, - 0x6e, 0x99, 0x19, 0xe7, 0xda, 0x50, 0xc8, 0xbf, 0x64, 0xae, 0xc1, 0x4f, 0xaa, - 0x47, 0x06, 0xf3, 0x49, 0x30, 0x8a, 0x90, 0x8e, 0xd2, 0xff, 0xc2, 0x6d, 0xee, - 0xaa, 0xd6, 0x45, 0xd8, 0xb3, 0x17, 0xe3, 0xb9, 0x45, 0x29, 0x26, 0xe2, 0x8e, - 0x99, 0x50, 0x94, 0x49, 0x90, 0x02, 0xa5, 0x61, 0x4a, 0x3f, 0x5e, 0xfa}; - byte0 := make([]byte, 0); - got := Hash(input, 1, byte0, byte0); - got_len := uint(len(got)); - - /* (1) Error if wrong size */ - if got_len != HSIZE { - - t.Errorf("Expected hash digest of %d bytes ; %d bytes received", HSIZE, got_len); - - } - - - /* (2) Check each byte */ - for k, v := range got{ - - if v != expected[k] { - t.Errorf("Expected sha[%d] of '%x' to be '%x' ; received '%x'", HSIZE, input, expected, got); - return; - } - - } - -} - - - -func TestDepthConsistence(t *testing.T){ - - input := []byte("someOtherPlainText"); - byte0 := make([]byte, 0); - - var tests = []struct { - got []byte - expected []byte - }{ - { Hash(Hash(input, 1, byte0, byte0), 1, byte0, byte0), Hash(input, 2, byte0, byte0) }, - { Hash(Hash(input, 1, byte0, byte0), 1000, byte0, byte0), Hash(input, 1001, byte0, byte0) }, - { Hash(Hash(input, 1000, byte0, byte0), 1, byte0, byte0), Hash(input, 1001, byte0, byte0) }, - }; - - - /* (1) For each case */ - for _, test := range tests{ - - /* (2) Check each byte */ - for k, v := range test.got{ - - if v != test.expected[k] { - t.Errorf("Expected '%x' ; received '%x'", test.expected, test.got); - return; - } - - } - - } - -} \ No newline at end of file