// HashReader hashes the given reader with the specified hash, // returning the final sum. This is done in blocks, so reading // from large files or other out-of-memory sources should not // cause memory issues. func HashReader(h hash.Hash, r io.Reader) (gocrypt.Hash, error) { block := make([]byte, h.BlockSize()) for { cnt, err := r.Read(block) h.Write(block[:cnt]) if err == io.EOF { break } else if err != nil { return nil, err } } return h.Sum(nil), nil }
// NIST SP 800-56 Concatenation Key Derivation Function (see section 5.8.1). func concatKDF(hash hash.Hash, z, s1 []byte, kdLen int) (k []byte, err error) { if s1 == nil { s1 = make([]byte, 0) } reps := ((kdLen + 7) * 8) / (hash.BlockSize() * 8) if big.NewInt(int64(reps)).Cmp(big2To32M1) > 0 { fmt.Println(big2To32M1) return nil, ErrKeyDataTooLong } counter := []byte{0, 0, 0, 1} k = make([]byte, 0) for i := 0; i <= reps; i++ { hash.Write(counter) hash.Write(z) hash.Write(s1) k = append(k, hash.Sum(nil)...) hash.Reset() incCounter(counter) } k = k[:kdLen] return }
// Encode a message with fixed salt, return the encoded message and random salt func Encode(hash hash.Hash, msg, salt []byte) ([]byte, []byte, error) { if hash == nil { hash = sha256.New() } rand, err := rand.B.Alphanumeric(hash.BlockSize()) if err != nil { return nil, nil, err } return SaltEncode(hash, msg, salt, rand), rand, err }
func Hash(hashname string, filename string) (sum string, err error) { f, err := os.Open(filename) if err != nil { return } var h hash.Hash switch hashname { case "md5": h = md5.New() case "sha1": h = sha1.New() case "sha2", "sha256": h = sha256.New() case "sha5", "sha512": h = sha512.New() default: err = errors.New("unknown hash: " + hashname) return } var nr int buf := make([]byte, h.BlockSize()) bf := bufio.NewReader(f) for { nr, _ = bf.Read(buf) h.Write(buf[0:nr]) if nr < len(buf) { break } } f.Close() sum = fmt.Sprintf("%0x", h.Sum(nil)) return }
func (t *HashTest) BlockSize() { var h hash.Hash var err error // AES-128 h, err = cmac.New(make([]byte, 16)) AssertEq(nil, err) ExpectEq(16, h.BlockSize()) // AES-192 h, err = cmac.New(make([]byte, 24)) AssertEq(nil, err) ExpectEq(16, h.BlockSize()) // AES-256 h, err = cmac.New(make([]byte, 32)) AssertEq(nil, err) ExpectEq(16, h.BlockSize()) }
func (this HashFile) Exec(input types.Value) (out types.Value, err error) { var inputMap types.Map if i, ok := input.(types.Map); ok { inputMap = i } else { err = errors.New(fmt.Sprintf("expected a map as input, got a %T", input)) return } var hashName string var hashNameElement = inputMap[types.Keyword("hash")] if hashNameElement == nil { hashName = "sha256" } else if h, ok := hashNameElement.(types.String); ok { hashName = string(h) } else if k, ok := hashNameElement.(types.Keyword); ok { hashName = string(k) } else if s, ok := hashNameElement.(types.Symbol); ok { hashName = string(s) } else { err = errors.New(":hash must be a string, keyword, or symbol if specified") return } hashName = strings.ToLower(hashName) var hash hash.Hash if hashName == "md5" { hash = md5.New() } else if hashName == "sha" || hashName == "sha1" || hashName == "sha-1" { hash = sha1.New() } else if hashName == "sha224" || hashName == "sha-224" { hash = sha256.New224() } else if hashName == "sha256" || hashName == "sha-256" { hash = sha256.New() } else if hashName == "sha384" || hashName == "sha-384" { hash = sha512.New384() } else if hashName == "sha512/224" || hashName == "sha-512/224" { hash = sha512.New512_224() } else if hashName == "sha512/256" || hashName == "sha-512/256" { hash = sha512.New512_256() } else if hashName == "sha512" || hashName == "sha-512" { hash = sha512.New() } else { err = errors.New(fmt.Sprint("unknown hash name: ", hashName)) return } var fileName string var fileElem = inputMap[types.Keyword("file")] if fileElem == nil { err = errors.New(":file argument is required") return } else if f, ok := fileElem.(types.String); ok { fileName = string(f) } else { err = errors.New(":file argument must be a string") return } file, err := os.Open(fileName) if err != nil { return } hashOut := bufio.NewWriterSize(hash, hash.BlockSize()) wrote, err := io.Copy(hashOut, file) hashOut.Flush() if err != nil { return } out = types.Map{ types.Keyword("success"): types.Bool(true), types.Keyword("size"): types.Int(wrote), types.Keyword("file"): types.String(fileName), types.Keyword("hash"): types.Keyword(hashName), types.Keyword("digest"): types.String(fmt.Sprintf("%x", hash.Sum(nil))), } return }