package scha import ( "errors" "crypto/sha512" "git.xdrm.io/schastsp/internal/xor" ) /* (0) Static ---------------------------------------------------------*/ /* (1) Constants */ const HSIZE uint16 = sha512.Size; const HBITSIZE uint32 = uint32(HSIZE) * 8; /* (1) Basic hash function * * @input<[]byte> Byte array input * * @return digest<[]byte]> Byte array digest * ---------------------------------------------------------*/ func hash(input []byte) []byte{ /* (1) Create sha512 hasher */ hasher := sha512.New(); /* (2) Defer memory cleanup */ defer hasher.Reset(); /* (3) Set input to be hashed */ hasher.Write(input); /* (4) Extract digest */ return hasher.Sum(nil); } /* (2) Public hashing interface * * @input<[]byte> Byte array input * @depth Number of time to hash recursively (must be > 1) * @salt<[]byte> [OPT] Optional salt * @pepper<[]byte> [OPT] Optional pepper * * @return digest<[]byte]> Byte array digest * @return err If consistence error * ---------------------------------------------------------*/ func Hash(input []byte, depth uint16, options... []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) Extract optional arguments ---------------------------------------------------------*/ /* (1) Optional salt */ salt := make([]byte, 0) if len(options) > 0 { salt = options[0] } /* (2) Optional pepper */ pepper := make([]byte, 0) if len(options) > 0 { pepper = options[0] } /* (3) Process cyclic hash ---------------------------------------------------------*/ /* (1) Initialise digest */ digest := make([]byte, 0, HSIZE) /* (2) Process first hash + salt */ digest = hash( xor.ByteArray(input, salt) ) /* (3) Iterate @depth times */ for depth--; depth > 0; depth-- { // Add Pepper only for last time if( depth == 1 ){ digest = hash( xor.ByteArray(digest, pepper) ) } else { digest = hash(digest) } } return digest, nil }