schastsp/internal/scha/hash.go

101 lines
2.3 KiB
Go

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<uint> 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<error> 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
}