[lib.CyclicHash] added unit tests + managed errors in multi-value return (returns <hash, err>)
This commit is contained in:
parent
6363cd41aa
commit
064b66660c
|
@ -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<error> 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
|
||||
}
|
|
@ -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");
|
||||
}
|
||||
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
Loading…
Reference in New Issue