package multihash

  1. Overview
  2. Docs
Self-describing Hash Functions

Install

Dune Dependency

Authors

Maintainers

Sources

multihash-0.1.0.tbz
sha256=cb6887fa2e31dc06d95b15d678ca9a0fa258be4c32d06db9df0b7981bdb8a5f6
sha512=364de8a501ae3a10cb9d12693c985546bb2a43ee8e229d12e6a120b1a666c54af976f08727f39f6bea62728a7499b302bd8d4641da92ab0eeef419e77738be1a

README.md.html

ocaml-multihash

Multihashes are self-describing hashes. That means that they encode both the hash digest of some value and also the digest length and the hash function identifier as per the multicodec.

# #require "multihash";;
# #require "digestif.ocaml";;
# #require "multihash-digestif";;

Usage

The following section explains how to use multihash and multihash-digestif.

Multihash

The multihash library is implementation-agnostic. It provides a functor for creating a new module which can actually perform the digesting of values. This might be useful because OCaml has quite a few hashing libraries including:

# #show_module_type Multihash__Multihash_intf.Hasher;;
module type Hasher =
  sig
    val digest :
      Multicodec.multihash ->
      Cstruct.t -> (Cstruct.t, [ `Msg of string | `Unsupported ]) result
    val digest_string :
      Multicodec.multihash ->
      string -> (string, [ `Msg of string | `Unsupported ]) result
    val iter :
      Multicodec.multihash ->
      ((Cstruct.t -> unit) -> unit) ->
      (Cstruct.t, [ `Msg of string | `Unsupported ]) result
    val iter_string :
      Multicodec.multihash ->
      ((string -> unit) -> unit) ->
      (string, [ `Msg of string | `Unsupported ]) result
    val is_supported : Multicodec.multihash -> bool
  end

An implementation must provide a means to digest a value and also a function detailing which hash functions are supported by the implementation.

Multihash-digestif

multihash-digestif is a multihash library implemented with digestif. Note this library will force you to decide between the C and OCaml implementation of digestif just like any other library with a digestif dependency.

module Md = Multihash_digestif
let s = "Merkle–Damgård"

It might be nice to alias the library as we've done here to Md. Creating a new multihash from some string is as simple as.

# let v = Md.of_string `Sha2_256 s |> Result.get_ok;;
val v : string Md.t = <abstr>

Note that a multihash is also "tagged" with the internal representation of the digest. We expose two main representations, string and Cstruct.t. This is mainly to help with avoiding copying bytes when using this library with other libraries. So Md.of_string keeps the digest in the string representation. Note that there are copying conversion functions in Md.Conv.

Having now digested the data, it can be converted to the full sequence of bytes. We write the bytes out as the internal representation. Unfortunately the bytes aren't necessarily UTF-8 and that breaks MDX for some reason, so we'll convert them to Cstructs.

# let data = Md.write v |> Cstruct.of_string;;
val data : Cstruct.t = {Cstruct.buffer = <abstr>; off = 0; len = 34}
# let () = hexdump data;;
12 20 41 dd 7b 64 43 54  2e 75 70 1a a9 8a 0c 23
59 51 a2 8a 0d 85 1b 11  56 4d 20 02 2a b1 1d 25
89 a8

And of course the hash function used and the length are recoverable from the data by reading it back in.

# let v = Md.read_buff data |> Result.get_ok;;
val v : Cstruct.t Md.t = <abstr>
# let (ident, length, digest) = 
  let ident = Multicodec.multihash_to_string (Md.get_hash v) in
  (ident, Md.get_length v, Md.get_digest v);;
val ident : string = "sha2-256"
val length : int = 32
val digest : Cstruct.t = {Cstruct.buffer = <abstr>; off = 2; len = 32}
# let () = hexdump digest;;
41 dd 7b 64 43 54 2e 75  70 1a a9 8a 0c 23 59 51
a2 8a 0d 85 1b 11 56 4d  20 02 2a b1 1d 25 89 a8