From 9db7f5dee76a19fe613e69d8f00d60e4f3faab80 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marco=20Aur=C3=A9lio=20da=20Silva?= Date: Sun, 25 Nov 2018 16:53:20 -0200 Subject: [PATCH 01/29] refactor: :running_man: :fire: :camel: bytes over strings [+] MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit this is an ongoing refactor process, aiming to optimize the whole algorithm performance and memory consumption as well. Signed-off-by: Marco Aurélio da Silva --- lib/encryption.ml | 4 ++-- lib/hash.ml | 9 +++++++ lib/hash.mli | 2 ++ lib/hieroglyphs.ml | 12 ++++------ lib/keys.ml | 27 +++++++++++++++++---- lib/random.ml | 17 +++++++++---- lib/random.mli | 2 +- lib/serialization.ml | 15 +++++++----- lib/serialization.mli | 6 ++--- lib/signing.ml | 1 + lib/signing.mli | 2 +- lib/utils.ml | 14 +++++++---- lib/utils.mli | 4 ++++ lib/verification.ml | 13 +++++++++- lib/verification.mli | 2 +- test/bench/bench.expected | 34 +++++++++++++------------- test/bench/hiero.ml | 50 +++++++++++++++++++++++---------------- test/bench/rsa_pss.ml | 33 +++++++++++++++++--------- test/bench/secp.ml | 34 ++++++++++++++++---------- test/spec/sign.ml | 2 +- test/spec/spec.ml | 14 +++++++---- 21 files changed, 195 insertions(+), 102 deletions(-) diff --git a/lib/encryption.ml b/lib/encryption.ml index cbf9437..ce31456 100644 --- a/lib/encryption.ml +++ b/lib/encryption.ml @@ -3,13 +3,13 @@ module Option = Core.Option module Base64 = Nocrypto.Base64 let encrypt msg ~pass = - let key = of_secret (Hash.mine pass ~difficulty:6) in + let key = of_secret (Hash.mine pass ~difficulty:5) in let result = encrypt ~key (Utils.pad ~basis:16 msg) in result |> Base64.encode |> Cstruct.to_string let decrypt cipher ~pass = - let key = of_secret (Hash.mine pass ~difficulty:6) in + let key = of_secret (Hash.mine pass ~difficulty:5) in let result = cipher |> Cstruct.of_string |> Base64.decode in let open Option in result diff --git a/lib/hash.ml b/lib/hash.ml index 42a4fbb..2ef4a9e 100644 --- a/lib/hash.ml +++ b/lib/hash.ml @@ -1,7 +1,16 @@ +module Bytes = Core.Bytes + let digest text = text |> Digestif.BLAKE2B.digest_string |> Digestif.BLAKE2B.to_hex +let digest_bytes bytes = + bytes + |> Digestif.BLAKE2B.digest_bytes + |> Digestif.BLAKE2B.to_raw_string + |> Bytes.of_string + + let rec __mining input pattern nonce = let length = Core.String.length pattern in let salt = Nocrypto.Numeric.Z.to_cstruct_be nonce in diff --git a/lib/hash.mli b/lib/hash.mli index 8686d70..02ed249 100644 --- a/lib/hash.mli +++ b/lib/hash.mli @@ -1,3 +1,5 @@ val digest : string -> string +val digest_bytes : bytes -> bytes + val mine : difficulty:int -> string -> Cstruct.t diff --git a/lib/hieroglyphs.ml b/lib/hieroglyphs.ml index a312a23..f2f1336 100644 --- a/lib/hieroglyphs.ml +++ b/lib/hieroglyphs.ml @@ -1,11 +1,13 @@ module Option = Core.Option -type priv = string list +type priv = bytes list -type pub = string list +type pub = bytes list let derive = Keys.derive +let pair = Keys.pair + let import = Keys.import let export = Keys.export @@ -50,9 +52,3 @@ let rec generate () = let option = __check priv in let step = Option.value_map option ~default:generate ~f:const in step () - - -let pair () = - let priv = generate () in - let pub = derive priv in - (priv, pub) diff --git a/lib/keys.ml b/lib/keys.ml index f4ead02..fd4fbb7 100644 --- a/lib/keys.ml +++ b/lib/keys.ml @@ -4,6 +4,7 @@ module Float = Core.Float module Int64 = Core.Int64 module Option = Core.Option +(* let populate time _ = () |> Random.generate @@ -11,27 +12,45 @@ let populate time _ = |> String.( ^ ) time |> Hash.digest |> Hash.digest - +*) let length = Utils._KEY_LENGTH +(* let timestamp () = () |> Unix.gettimeofday |> Float.to_string let generate () = let time = timestamp () in List.init length ~f:(populate time) +*) + +let _random_hex _ = Random.generate512 () + +let generate () = List.init length ~f:_random_hex + +let derive priv = List.map priv ~f:Hash.digest_bytes +let pair () = + let priv = generate () in + let pub = derive priv in + (priv, pub) -let derive priv = List.map priv ~f:Hash.digest let export ~priv ~pass = - priv |> List.reduce_exn ~f:Utils.concat_hashes |> Encryption.encrypt ~pass + priv + |> List.map ~f:Utils.bytes_to_string + |> List.reduce_exn ~f:Utils.concat_hashes + |> Encryption.encrypt ~pass let import ~cipher ~pass = let open Option in Encryption.decrypt ~pass cipher - >>= fun result -> result |> String.split ~on:'-' |> Utils.validate_key + >>= fun result -> + result + |> String.split ~on:'-' + |> Utils.validate_key + >>= fun list -> some @@ List.map list ~f:Utils.bytes_of_string let load = Serialization.load diff --git a/lib/random.ml b/lib/random.ml index 4d47652..d43bc90 100644 --- a/lib/random.ml +++ b/lib/random.ml @@ -1,5 +1,14 @@ -let generate ( ) = - Nocrypto.Rng.Int64.gen Core.Int64.max_value +let _MIN_RANDOM = "1" ^ Core.String.init 511 ~f:(Core.const '0') -let _ = - Nocrypto_entropy_unix.initialize ( ) +let _MAX_RANDOM = Core.String.init 512 ~f:(Core.const '1') + +let _min_random = Z.of_string_base 2 _MIN_RANDOM + +let _max_random = Z.of_string_base 2 _MAX_RANDOM + +let generate512 () = + let number = Nocrypto.Rng.Z.gen_r _min_random _max_random in + Cstruct.to_bytes @@ Nocrypto.Numeric.Z.to_cstruct_be number + + +let _ = Nocrypto_entropy_unix.initialize () diff --git a/lib/random.mli b/lib/random.mli index 945c45f..8f76ba9 100644 --- a/lib/random.mli +++ b/lib/random.mli @@ -1 +1 @@ -val generate : unit -> int64 +val generate512 : unit -> bytes diff --git a/lib/serialization.ml b/lib/serialization.ml index eb67d44..e99d828 100644 --- a/lib/serialization.ml +++ b/lib/serialization.ml @@ -1,15 +1,18 @@ module List = Core.List module String = Core.String +module Option = Core.Option let show pub = - List.reduce_exn pub ~f:Utils.concat_hashes + pub + |> List.map ~f:Utils.bytes_to_string + |> List.reduce_exn ~f:Utils.concat_hashes + let load text = let list = String.split text ~on:'-' in + let open Option in Utils.validate_key list + >>= fun list -> some @@ List.map ~f:Utils.bytes_of_string list -let address pub = - pub - |> show - |> Hash.digest - |> Utils.to_hex + +let address pub = pub |> show |> Hash.digest |> Utils.to_hex diff --git a/lib/serialization.mli b/lib/serialization.mli index 548887a..469b6c3 100644 --- a/lib/serialization.mli +++ b/lib/serialization.mli @@ -1,5 +1,5 @@ -val address : string list -> string +val address : bytes list -> string -val show : string list -> string +val show : bytes list -> string -val load : string -> string list option +val load : string -> bytes list option diff --git a/lib/signing.ml b/lib/signing.ml index bfa723f..e7ed1a1 100644 --- a/lib/signing.ml +++ b/lib/signing.ml @@ -1,6 +1,7 @@ module List = Core.List let sign ~priv ~msg = + let priv = List.map priv ~f:Utils.bytes_to_string in msg |> Utils.indexed_keys |> Utils.replace_index ~matrix:priv diff --git a/lib/signing.mli b/lib/signing.mli index e68dd7a..b21f8cf 100644 --- a/lib/signing.mli +++ b/lib/signing.mli @@ -1 +1 @@ -val sign : priv:string list -> msg:string -> string +val sign : priv:bytes list -> msg:string -> string diff --git a/lib/utils.ml b/lib/utils.ml index 5eec036..d3b4a14 100644 --- a/lib/utils.ml +++ b/lib/utils.ml @@ -40,7 +40,8 @@ let replace_index ~matrix pairs = pairs |> List.map ~f:(index_at ~list:matrix) let verify_at ~digest ~list (position, hash) = let commitment = List.nth_exn list position in - digest hash = commitment + let opening = digest hash in + opening = commitment let verify_with ~matrix ~digest pairs = @@ -51,13 +52,13 @@ let verify_with ~matrix ~digest pairs = let concat_hashes left right = left ^ "-" ^ right +let char_to_hex_int char = char |> Char.to_string |> to_hex |> Int.of_string + let indexed_keys msg = msg |> Hash.digest |> String.to_list - |> List.map ~f:Char.to_string - |> List.map ~f:to_hex - |> List.map ~f:Int.of_string + |> List.map ~f:char_to_hex_int |> tag_index |> List.map ~f:calculate_index @@ -74,3 +75,8 @@ let pad ~basis msg = let nonzero char = char != nullchar let unpad msg = String.filter ~f:nonzero msg + +let bytes_of_string string = Cstruct.to_bytes @@ Cstruct.of_hex string + +let bytes_to_string bytes = + Hex.show @@ Hex.of_cstruct @@ Cstruct.of_bytes bytes diff --git a/lib/utils.mli b/lib/utils.mli index 6d59ff9..5ed0b53 100644 --- a/lib/utils.mli +++ b/lib/utils.mli @@ -21,3 +21,7 @@ val verify_with : val pad : basis:int -> string -> Cstruct.t val unpad : string -> string + +val bytes_of_string : string -> bytes + +val bytes_to_string : bytes -> string diff --git a/lib/verification.ml b/lib/verification.ml index 30475f6..c6f7de3 100644 --- a/lib/verification.ml +++ b/lib/verification.ml @@ -1,8 +1,19 @@ module String = Core.String module List = Core.List +let digest message = + message + |> Cstruct.of_hex + |> Cstruct.to_bytes + |> Hash.digest_bytes + |> Cstruct.of_bytes + |> Hex.of_cstruct + |> Hex.show + + let verify ~pub ~msg ~signature = + let pub = List.map ~f:Utils.bytes_to_string pub in let indexed_keys = Utils.indexed_keys msg in let hashes = String.split signature ~on:'-' in let proofs = List.zip_exn indexed_keys hashes in - Utils.verify_with ~matrix:pub ~digest:Hash.digest proofs + Utils.verify_with ~matrix:pub ~digest proofs diff --git a/lib/verification.mli b/lib/verification.mli index 7180e3e..d2e4629 100644 --- a/lib/verification.mli +++ b/lib/verification.mli @@ -1 +1 @@ -val verify : pub:string list -> msg:string -> signature:string -> bool +val verify : pub:bytes list -> msg:string -> signature:string -> bool diff --git a/test/bench/bench.expected b/test/bench/bench.expected index 3dae249..498863e 100644 --- a/test/bench/bench.expected +++ b/test/bench/bench.expected @@ -1,19 +1,17 @@ Estimated testing time 2m (12 benchmarks x 10s). Change using -quota SECS. -┌─────────────────────────────────────────────────────┬────────────────────┬───────────────┬─────────────────┬─────────────┬────────────┐ -│ Name │ Time/Run │ mWd/Run │ mjWd/Run │ Prom/Run │ Percentage │ -├─────────────────────────────────────────────────────┼────────────────────┼───────────────┼─────────────────┼─────────────┼────────────┤ -│ hieroglyphs + blake2b ------ private key generation │ 376_317_374.97ns │ 1_037_742.79w │ 33_922_480.27w │ 88_405.27w │ 28.36% │ -│ hieroglyphs + blake2b ------ message signing │ 1_326_859_831.73ns │ 7_161_043.30w │ 102_462_832.00w │ 689_212.00w │ 100.00% │ -│ hieroglyphs + blake2b ------ public key derivation │ 6_672_776.35ns │ 206_848.86w │ 15_337.63w │ 15_337.63w │ 0.50% │ -│ hieroglyphs + blake2b ------ signature verification │ 1_896_086.08ns │ 21_148.32w │ 115.42w │ 115.42w │ 0.14% │ -│ rsa pss/sha256 1024 bits --- private key generation │ 35_003_683.96ns │ 870.97w │ -0.23w │ -0.23w │ 2.64% │ -│ rsa pss/sha256 1024 bits --- public key derivation │ 10.18ns │ 3.00w │ │ │ │ -│ rsa pss/sha256 1024 bits --- message signing │ 709_147.00ns │ 1_715.04w │ 0.56w │ 0.56w │ 0.05% │ -│ rsa pss/sha256 1024 bits --- signature verification │ 81_176.42ns │ 1_547.02w │ 0.34w │ 0.34w │ │ -│ secp256k1 + sha256 hash ---- private key generation │ 13_894.85ns │ 355.67w │ │ │ │ -│ secp256k1 + sha256 hash ---- public key derivation │ 259_270.15ns │ 13.00w │ │ │ 0.02% │ -│ secp256k1 + sha256 hash ---- message signing │ 336_969.12ns │ 585.77w │ 0.15w │ 0.15w │ 0.03% │ -│ secp256k1 + sha256 hash ---- signature verification │ 363_144.00ns │ 214.00w │ │ │ 0.03% │ -└─────────────────────────────────────────────────────┴────────────────────┴───────────────┴─────────────────┴─────────────┴────────────┘ -Benchmarks that take 1ns to 100ms can be estimated precisely. For more reliable -estimates, redesign your benchmark to have a shorter execution time. +┌─────────────────────────────────────────────────────┬─────────────────┬───────────────┬─────────────┬────────────┬────────────┐ +│ Name │ Time/Run │ mWd/Run │ mjWd/Run │ Prom/Run │ Percentage │ +├─────────────────────────────────────────────────────┼─────────────────┼───────────────┼─────────────┼────────────┼────────────┤ +│ hieroglyphs + blake2b ------ private key generation │ 36_115_048.25ns │ 1_257_186.16w │ 24_212.48w │ 24_212.48w │ 100.00% │ +│ hieroglyphs + blake2b ------ message signing │ 11_213_663.99ns │ 552_974.77w │ 160_025.25w │ 28_670.25w │ 31.05% │ +│ hieroglyphs + blake2b ------ public key derivation │ 3_008_022.90ns │ 190_464.86w │ 7_971.99w │ 7_971.99w │ 8.33% │ +│ hieroglyphs + blake2b ------ signature verification │ 12_598_340.69ns │ 865_711.60w │ 44_975.21w │ 44_975.21w │ 34.88% │ +│ rsa pss/sha256 1024 bits --- private key generation │ 35_080_509.59ns │ 870.80w │ 0.35w │ 0.35w │ 97.14% │ +│ rsa pss/sha256 1024 bits --- public key derivation │ 11.46ns │ 3.00w │ │ │ │ +│ rsa pss/sha256 1024 bits --- message signing │ 771_613.48ns │ 1_713.42w │ 0.63w │ 0.63w │ 2.14% │ +│ rsa pss/sha256 1024 bits --- signature verification │ 142_191.97ns │ 1_547.02w │ 0.36w │ 0.36w │ 0.39% │ +│ secp256k1 + sha256 hash ---- private key generation │ 12_920.47ns │ 355.71w │ │ │ 0.04% │ +│ secp256k1 + sha256 hash ---- public key derivation │ 214_130.84ns │ 13.00w │ │ │ 0.59% │ +│ secp256k1 + sha256 hash ---- message signing │ 302_456.71ns │ 230.00w │ │ │ 0.84% │ +│ secp256k1 + sha256 hash ---- signature verification │ 361_341.90ns │ 214.00w │ │ │ 1.00% │ +└─────────────────────────────────────────────────────┴─────────────────┴───────────────┴─────────────┴────────────┴────────────┘ diff --git a/test/bench/hiero.ml b/test/bench/hiero.ml index 2219786..b9a0153 100644 --- a/test/bench/hiero.ml +++ b/test/bench/hiero.ml @@ -1,24 +1,21 @@ open Core_bench.Bench -module Hg = Hieroglyphs +module Hg = Hieroglyphs__Keys let generate () = ignore @@ Hg.generate () let priv = Hg.generate () +let priv' = Hg.generate () + let signing () = - let priv = Hg.generate () in - ignore @@ Hg.sign ~priv ~msg:"Benchmark signing test." + (* TODO: it's safe to sign the same message twice and many times, I should + fix and cover that on the test specification *) + ignore @@ Hg.sign ~priv:priv' ~msg:"Benchmark signing test." let derive () = ignore @@ Hg.derive priv -let sign ~priv ~msg = - match Hg.sign ~priv ~msg with - | None -> - failwith "Expected a generated message signature!" - | Some signature -> - signature - +let sign ~priv ~msg = Hg.sign ~priv ~msg let signature = sign ~priv ~msg:"Benchmark signed message." @@ -28,14 +25,25 @@ let verification () = ignore @@ Hg.verify ~pub ~signature ~msg:"Benchmark signed message." -let suite = - [ Test.create - ~name:"hieroglyphs + blake2b ------ private key generation" - generate - ; Test.create ~name:"hieroglyphs + blake2b ------ message signing" signing - ; Test.create - ~name:"hieroglyphs + blake2b ------ public key derivation" - derive - ; Test.create - ~name:"hieroglyphs + blake2b ------ signature verification" - verification ] +(*** test cases ***************************************************************) +let __generation = + let name = "hieroglyphs + blake2b ------ private key generation" in + Test.create ~name generate + + +let __signing = + let name = "hieroglyphs + blake2b ------ message signing" in + Test.create ~name signing + + +let __derivation = + let name = "hieroglyphs + blake2b ------ public key derivation" in + Test.create ~name derive + + +let __verification = + let name = "hieroglyphs + blake2b ------ signature verification" in + Test.create ~name verification + + +let suite = [__generation; __signing; __derivation; __verification] diff --git a/test/bench/rsa_pss.ml b/test/bench/rsa_pss.ml index 4f64eea..ecf6822 100644 --- a/test/bench/rsa_pss.ml +++ b/test/bench/rsa_pss.ml @@ -32,14 +32,25 @@ let verification () = |> ignore -let suite = - [ Test.create - ~name:"rsa pss/sha256 1024 bits --- private key generation" - generate - ; Test.create - ~name:"rsa pss/sha256 1024 bits --- public key derivation" - derive - ; Test.create ~name:"rsa pss/sha256 1024 bits --- message signing" signing - ; Test.create - ~name:"rsa pss/sha256 1024 bits --- signature verification" - verification ] +(*** test cases ***************************************************************) +let __generation = + let name = "rsa pss/sha256 1024 bits --- private key generation" in + Test.create ~name generate + + +let __derivation = + let name = "rsa pss/sha256 1024 bits --- public key derivation" in + Test.create ~name derive + + +let __signing = + let name = "rsa pss/sha256 1024 bits --- message signing" in + Test.create ~name signing + + +let __verification = + let name = "rsa pss/sha256 1024 bits --- signature verification" in + Test.create ~name verification + + +let suite = [__generation; __derivation; __signing; __verification] diff --git a/test/bench/secp.ml b/test/bench/secp.ml index 7c58088..2352d8b 100644 --- a/test/bench/secp.ml +++ b/test/bench/secp.ml @@ -22,7 +22,7 @@ let derive () = let signing () = - let priv = ECC.generate () in + (* let priv = ECC.generate () in *) ignore @@ ECC.sign ~priv ~msg:"Benchmark signing test." @@ -35,17 +35,27 @@ let verification () = assert result -let suite = - [ Test.create - ~name:"secp256k1 + sha256 hash ---- private key generation" - generate - ; Test.create - ~name:"secp256k1 + sha256 hash ---- public key derivation" - derive - ; Test.create ~name:"secp256k1 + sha256 hash ---- message signing" signing - ; Test.create - ~name:"secp256k1 + sha256 hash ---- signature verification" - verification ] +(*** test cases ***************************************************************) +let __generation = + let name = "secp256k1 + sha256 hash ---- private key generation" in + Test.create ~name generate +let __derivation = + let name = "secp256k1 + sha256 hash ---- public key derivation" in + Test.create ~name derive + + +let __signing = + let name = "secp256k1 + sha256 hash ---- message signing" in + Test.create ~name signing + + +let __verification = + let name = "secp256k1 + sha256 hash ---- signature verification" in + Test.create ~name verification + + +let suite = [__generation; __derivation; __signing; __verification] + let () = Nocrypto_entropy_unix.initialize () diff --git a/test/spec/sign.ml b/test/spec/sign.ml index 0f8e76e..8cd0587 100644 --- a/test/spec/sign.ml +++ b/test/spec/sign.ml @@ -85,4 +85,4 @@ let __one_time_signing () = let suite = [ ("signature validation size and format", `Quick, __signature_validation) ; ("signing and verification must match", `Quick, __signing_and_verification) - ; ("signing must be performed only once", `Quick, __one_time_signing) ] + ; ("signing must be performed only once", `Slow, __one_time_signing) ] diff --git a/test/spec/spec.ml b/test/spec/spec.ml index 70ae50a..2367476 100644 --- a/test/spec/spec.ml +++ b/test/spec/spec.ml @@ -1,4 +1,10 @@ -Alcotest.run "hieroglyphs specification" [ - "keys-management", Keys.suite; - "signing-and-verification", Sign.suite -] +(* Environment Variables: + - ALCOTEST_QUICK_TESTS + - ALCOTEST_SHOW_ERRORS + - ALCOTEST_VERBOSE +*) + +;; +Alcotest.run + "hieroglyphs specification" + [("keys-management", Keys.suite); ("signing-and-verification", Sign.suite)] From 50d910ece2bb8caf7f3f9489210b00172bdfbebe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marco=20Aur=C3=A9lio=20da=20Silva?= Date: Sun, 25 Nov 2018 16:55:47 -0200 Subject: [PATCH 02/29] docs: :book: :rocket: :anchor: bumping/updating documentation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Marco Aurélio da Silva --- .../hieroglyphs/Hieroglyphs__/Hash/index.html | 2 +- .../Bisect_visit___lib___keys___ml/index.html | 2 - .../hieroglyphs/Hieroglyphs__/Keys/index.html | 2 +- .../Hieroglyphs__/Random/index.html | 2 +- .../Hieroglyphs__/Serialization/index.html | 2 +- .../Hieroglyphs__/Signing/index.html | 2 +- .../Hieroglyphs__/Utils/index.html | 2 +- .../Hieroglyphs__/Verification/index.html | 2 +- .../hieroglyphs/Hieroglyphs__Hash/index.html | 2 +- .../Bisect_visit___lib___keys___ml/index.html | 2 - .../hieroglyphs/Hieroglyphs__Keys/index.html | 2 +- .../Hieroglyphs__Random/index.html | 2 +- .../Hieroglyphs__Serialization/index.html | 2 +- .../Hieroglyphs__Signing/index.html | 2 +- .../hieroglyphs/Hieroglyphs__Utils/index.html | 2 +- .../Hieroglyphs__Verification/index.html | 2 +- docs/coverage/index.html | 2 +- docs/coverage/lib/blacklist.ml.html | 6 +- docs/coverage/lib/encryption.ml.html | 6 +- docs/coverage/lib/hash.ml.html | 59 +++++---- docs/coverage/lib/hieroglyphs.ml.html | 68 ++++------ docs/coverage/lib/keys.ml.html | 123 +++++++++++++----- docs/coverage/lib/random.ml.html | 41 ++++-- docs/coverage/lib/serialization.ml.html | 43 ++++-- docs/coverage/lib/signing.ml.html | 5 +- docs/coverage/lib/store.ml.html | 12 +- docs/coverage/lib/utils.ml.html | 83 ++++++++---- docs/coverage/lib/verification.ml.html | 50 +++++-- 28 files changed, 341 insertions(+), 189 deletions(-) delete mode 100644 docs/apiref/hieroglyphs/Hieroglyphs__/Keys/Bisect_visit___lib___keys___ml/index.html delete mode 100644 docs/apiref/hieroglyphs/Hieroglyphs__Keys/Bisect_visit___lib___keys___ml/index.html diff --git a/docs/apiref/hieroglyphs/Hieroglyphs__/Hash/index.html b/docs/apiref/hieroglyphs/Hieroglyphs__/Hash/index.html index 20727fd..6e4705f 100644 --- a/docs/apiref/hieroglyphs/Hieroglyphs__/Hash/index.html +++ b/docs/apiref/hieroglyphs/Hieroglyphs__/Hash/index.html @@ -1,2 +1,2 @@ -Hash (hieroglyphs.Hieroglyphs__.Hash)

Module Hieroglyphs__.Hash

val digest : string -> string
val sha256 : string -> string
\ No newline at end of file +Hash (hieroglyphs.Hieroglyphs__.Hash)

Module Hieroglyphs__.Hash

val digest : string -> string
val digest_bytes : bytes -> bytes
val mine : difficulty:int -> string -> Cstruct.t
\ No newline at end of file diff --git a/docs/apiref/hieroglyphs/Hieroglyphs__/Keys/Bisect_visit___lib___keys___ml/index.html b/docs/apiref/hieroglyphs/Hieroglyphs__/Keys/Bisect_visit___lib___keys___ml/index.html deleted file mode 100644 index 392a120..0000000 --- a/docs/apiref/hieroglyphs/Hieroglyphs__/Keys/Bisect_visit___lib___keys___ml/index.html +++ /dev/null @@ -1,2 +0,0 @@ - -Bisect_visit___lib___keys___ml (hieroglyphs.Hieroglyphs__.Keys.Bisect_visit___lib___keys___ml)

Module Keys.Bisect_visit___lib___keys___ml

val ___bisect_visit___ : int -> unit
\ No newline at end of file diff --git a/docs/apiref/hieroglyphs/Hieroglyphs__/Keys/index.html b/docs/apiref/hieroglyphs/Hieroglyphs__/Keys/index.html index 60f2915..ae151b6 100644 --- a/docs/apiref/hieroglyphs/Hieroglyphs__/Keys/index.html +++ b/docs/apiref/hieroglyphs/Hieroglyphs__/Keys/index.html @@ -1,2 +1,2 @@ -Keys (hieroglyphs.Hieroglyphs__.Keys)

Module Hieroglyphs__.Keys

module Bisect_visit___lib___keys___ml : sig ... end
module List = Core.List
module String = Core.String
module Float = Core.Float
module Int64 = Core.Int64
module Option = Core.Option
val populate : String.t -> 'a -> string
val length : int
val timestamp : unit -> Core_kernel__.Import.string
val generate : unit -> string List.t
val derive : string List.t -> string List.t
val export : priv:string List.t -> pass:string -> string
val import : cipher:string -> pass:string -> string list Option.t
val load : string -> string list option
val show : string list -> string
val address : string list -> string
val sign : priv:string list -> msg:string -> string
val verify : pub:string list -> msg:string -> signature:string -> bool
\ No newline at end of file +Keys (hieroglyphs.Hieroglyphs__.Keys)

Module Hieroglyphs__.Keys

module List = Core.List
module String = Core.String
module Float = Core.Float
module Int64 = Core.Int64
module Option = Core.Option
val length : int
val _random_hex : 'a -> bytes
val generate : unit -> bytes List.t
val derive : bytes List.t -> bytes List.t
val pair : unit -> bytes List.t * bytes List.t
val export : priv:bytes List.t -> pass:string -> string
val import : cipher:string -> pass:string -> bytes List.t Option.t
val load : string -> bytes list option
val show : bytes list -> string
val address : bytes list -> string
val sign : priv:bytes list -> msg:string -> string
val verify : pub:bytes list -> msg:string -> signature:string -> bool
\ No newline at end of file diff --git a/docs/apiref/hieroglyphs/Hieroglyphs__/Random/index.html b/docs/apiref/hieroglyphs/Hieroglyphs__/Random/index.html index c85eba3..17b441b 100644 --- a/docs/apiref/hieroglyphs/Hieroglyphs__/Random/index.html +++ b/docs/apiref/hieroglyphs/Hieroglyphs__/Random/index.html @@ -1,2 +1,2 @@ -Random (hieroglyphs.Hieroglyphs__.Random)

Module Hieroglyphs__.Random

val generate : unit -> int64
\ No newline at end of file +Random (hieroglyphs.Hieroglyphs__.Random)

Module Hieroglyphs__.Random

val generate512 : unit -> bytes
\ No newline at end of file diff --git a/docs/apiref/hieroglyphs/Hieroglyphs__/Serialization/index.html b/docs/apiref/hieroglyphs/Hieroglyphs__/Serialization/index.html index 1175a00..190a0ef 100644 --- a/docs/apiref/hieroglyphs/Hieroglyphs__/Serialization/index.html +++ b/docs/apiref/hieroglyphs/Hieroglyphs__/Serialization/index.html @@ -1,2 +1,2 @@ -Serialization (hieroglyphs.Hieroglyphs__.Serialization)

Module Hieroglyphs__.Serialization

val address : string list -> string
val show : string list -> string
val load : string -> string list option
\ No newline at end of file +Serialization (hieroglyphs.Hieroglyphs__.Serialization)

Module Hieroglyphs__.Serialization

val address : bytes list -> string
val show : bytes list -> string
val load : string -> bytes list option
\ No newline at end of file diff --git a/docs/apiref/hieroglyphs/Hieroglyphs__/Signing/index.html b/docs/apiref/hieroglyphs/Hieroglyphs__/Signing/index.html index ed09f61..b54c9dc 100644 --- a/docs/apiref/hieroglyphs/Hieroglyphs__/Signing/index.html +++ b/docs/apiref/hieroglyphs/Hieroglyphs__/Signing/index.html @@ -1,2 +1,2 @@ -Signing (hieroglyphs.Hieroglyphs__.Signing)

Module Hieroglyphs__.Signing

val sign : priv:string list -> msg:string -> string
\ No newline at end of file +Signing (hieroglyphs.Hieroglyphs__.Signing)

Module Hieroglyphs__.Signing

val sign : priv:bytes list -> msg:string -> string
\ No newline at end of file diff --git a/docs/apiref/hieroglyphs/Hieroglyphs__/Utils/index.html b/docs/apiref/hieroglyphs/Hieroglyphs__/Utils/index.html index a4a476b..8371d9d 100644 --- a/docs/apiref/hieroglyphs/Hieroglyphs__/Utils/index.html +++ b/docs/apiref/hieroglyphs/Hieroglyphs__/Utils/index.html @@ -1,2 +1,2 @@ -Utils (hieroglyphs.Hieroglyphs__.Utils)

Module Hieroglyphs__.Utils

val _HASH_LENGTH : int
val _KEY_LENGTH : int
val to_hex : string -> string
val concat_hashes : string -> string -> string
val validate_key : string list -> string list option
val replace_index : matrix:string list -> int list -> string list
val indexed_keys : string -> int list
val verify_with : matrix:string list -> digest:(string -> string) -> (int * string) list -> bool
val pad : basis:int -> string -> Cstruct.t
val unpad : string -> string
\ No newline at end of file +Utils (hieroglyphs.Hieroglyphs__.Utils)

Module Hieroglyphs__.Utils

val _HASH_LENGTH : int
val _KEY_LENGTH : int
val to_hex : string -> string
val concat_hashes : string -> string -> string
val validate_key : string list -> string list option
val replace_index : matrix:string list -> int list -> string list
val indexed_keys : string -> int list
val verify_with : matrix:string list -> digest:(string -> string) -> (int * string) list -> bool
val pad : basis:int -> string -> Cstruct.t
val unpad : string -> string
val bytes_of_string : string -> bytes
val bytes_to_string : bytes -> string
\ No newline at end of file diff --git a/docs/apiref/hieroglyphs/Hieroglyphs__/Verification/index.html b/docs/apiref/hieroglyphs/Hieroglyphs__/Verification/index.html index 39634ae..dd035ba 100644 --- a/docs/apiref/hieroglyphs/Hieroglyphs__/Verification/index.html +++ b/docs/apiref/hieroglyphs/Hieroglyphs__/Verification/index.html @@ -1,2 +1,2 @@ -Verification (hieroglyphs.Hieroglyphs__.Verification)

Module Hieroglyphs__.Verification

val verify : pub:string list -> msg:string -> signature:string -> bool
\ No newline at end of file +Verification (hieroglyphs.Hieroglyphs__.Verification)

Module Hieroglyphs__.Verification

val verify : pub:bytes list -> msg:string -> signature:string -> bool
\ No newline at end of file diff --git a/docs/apiref/hieroglyphs/Hieroglyphs__Hash/index.html b/docs/apiref/hieroglyphs/Hieroglyphs__Hash/index.html index 24163e4..9bfb529 100644 --- a/docs/apiref/hieroglyphs/Hieroglyphs__Hash/index.html +++ b/docs/apiref/hieroglyphs/Hieroglyphs__Hash/index.html @@ -1,2 +1,2 @@ -Hieroglyphs__Hash (hieroglyphs.Hieroglyphs__Hash)

Module Hieroglyphs__Hash

val digest : string -> string
val sha256 : string -> string
\ No newline at end of file +Hieroglyphs__Hash (hieroglyphs.Hieroglyphs__Hash)

Module Hieroglyphs__Hash

val digest : string -> string
val digest_bytes : bytes -> bytes
val mine : difficulty:int -> string -> Cstruct.t
\ No newline at end of file diff --git a/docs/apiref/hieroglyphs/Hieroglyphs__Keys/Bisect_visit___lib___keys___ml/index.html b/docs/apiref/hieroglyphs/Hieroglyphs__Keys/Bisect_visit___lib___keys___ml/index.html deleted file mode 100644 index 35acb61..0000000 --- a/docs/apiref/hieroglyphs/Hieroglyphs__Keys/Bisect_visit___lib___keys___ml/index.html +++ /dev/null @@ -1,2 +0,0 @@ - -Bisect_visit___lib___keys___ml (hieroglyphs.Hieroglyphs__Keys.Bisect_visit___lib___keys___ml)

Module Hieroglyphs__Keys.Bisect_visit___lib___keys___ml

val ___bisect_visit___ : int -> unit
\ No newline at end of file diff --git a/docs/apiref/hieroglyphs/Hieroglyphs__Keys/index.html b/docs/apiref/hieroglyphs/Hieroglyphs__Keys/index.html index 762cc46..df7ab51 100644 --- a/docs/apiref/hieroglyphs/Hieroglyphs__Keys/index.html +++ b/docs/apiref/hieroglyphs/Hieroglyphs__Keys/index.html @@ -1,2 +1,2 @@ -Hieroglyphs__Keys (hieroglyphs.Hieroglyphs__Keys)

Module Hieroglyphs__Keys

module Bisect_visit___lib___keys___ml : sig ... end
module List = Core.List
module String = Core.String
module Float = Core.Float
module Int64 = Core.Int64
module Option = Core.Option
val populate : String.t -> 'a -> string
val length : int
val timestamp : unit -> Core_kernel__.Import.string
val generate : unit -> string List.t
val derive : string List.t -> string List.t
val export : priv:string List.t -> pass:string -> string
val import : cipher:string -> pass:string -> string list Option.t
val load : string -> string list option
val show : string list -> string
val address : string list -> string
val sign : priv:string list -> msg:string -> string
val verify : pub:string list -> msg:string -> signature:string -> bool
\ No newline at end of file +Hieroglyphs__Keys (hieroglyphs.Hieroglyphs__Keys)

Module Hieroglyphs__Keys

module List = Core.List
module String = Core.String
module Float = Core.Float
module Int64 = Core.Int64
module Option = Core.Option
val length : int
val _random_hex : 'a -> bytes
val generate : unit -> bytes List.t
val derive : bytes List.t -> bytes List.t
val pair : unit -> bytes List.t * bytes List.t
val export : priv:bytes List.t -> pass:string -> string
val import : cipher:string -> pass:string -> bytes List.t Option.t
val load : string -> bytes list option
val show : bytes list -> string
val address : bytes list -> string
val sign : priv:bytes list -> msg:string -> string
val verify : pub:bytes list -> msg:string -> signature:string -> bool
\ No newline at end of file diff --git a/docs/apiref/hieroglyphs/Hieroglyphs__Random/index.html b/docs/apiref/hieroglyphs/Hieroglyphs__Random/index.html index 171bace..cfb1010 100644 --- a/docs/apiref/hieroglyphs/Hieroglyphs__Random/index.html +++ b/docs/apiref/hieroglyphs/Hieroglyphs__Random/index.html @@ -1,2 +1,2 @@ -Hieroglyphs__Random (hieroglyphs.Hieroglyphs__Random)

Module Hieroglyphs__Random

val generate : unit -> int64
\ No newline at end of file +Hieroglyphs__Random (hieroglyphs.Hieroglyphs__Random)

Module Hieroglyphs__Random

val generate512 : unit -> bytes
\ No newline at end of file diff --git a/docs/apiref/hieroglyphs/Hieroglyphs__Serialization/index.html b/docs/apiref/hieroglyphs/Hieroglyphs__Serialization/index.html index 75cc5d8..809e6b8 100644 --- a/docs/apiref/hieroglyphs/Hieroglyphs__Serialization/index.html +++ b/docs/apiref/hieroglyphs/Hieroglyphs__Serialization/index.html @@ -1,2 +1,2 @@ -Hieroglyphs__Serialization (hieroglyphs.Hieroglyphs__Serialization)

Module Hieroglyphs__Serialization

val address : string list -> string
val show : string list -> string
val load : string -> string list option
\ No newline at end of file +Hieroglyphs__Serialization (hieroglyphs.Hieroglyphs__Serialization)

Module Hieroglyphs__Serialization

val address : bytes list -> string
val show : bytes list -> string
val load : string -> bytes list option
\ No newline at end of file diff --git a/docs/apiref/hieroglyphs/Hieroglyphs__Signing/index.html b/docs/apiref/hieroglyphs/Hieroglyphs__Signing/index.html index 40f3c18..4b70946 100644 --- a/docs/apiref/hieroglyphs/Hieroglyphs__Signing/index.html +++ b/docs/apiref/hieroglyphs/Hieroglyphs__Signing/index.html @@ -1,2 +1,2 @@ -Hieroglyphs__Signing (hieroglyphs.Hieroglyphs__Signing)

Module Hieroglyphs__Signing

val sign : priv:string list -> msg:string -> string
\ No newline at end of file +Hieroglyphs__Signing (hieroglyphs.Hieroglyphs__Signing)

Module Hieroglyphs__Signing

val sign : priv:bytes list -> msg:string -> string
\ No newline at end of file diff --git a/docs/apiref/hieroglyphs/Hieroglyphs__Utils/index.html b/docs/apiref/hieroglyphs/Hieroglyphs__Utils/index.html index d77f80a..810c334 100644 --- a/docs/apiref/hieroglyphs/Hieroglyphs__Utils/index.html +++ b/docs/apiref/hieroglyphs/Hieroglyphs__Utils/index.html @@ -1,2 +1,2 @@ -Hieroglyphs__Utils (hieroglyphs.Hieroglyphs__Utils)

Module Hieroglyphs__Utils

val _HASH_LENGTH : int
val _KEY_LENGTH : int
val to_hex : string -> string
val concat_hashes : string -> string -> string
val validate_key : string list -> string list option
val replace_index : matrix:string list -> int list -> string list
val indexed_keys : string -> int list
val verify_with : matrix:string list -> digest:(string -> string) -> (int * string) list -> bool
val pad : basis:int -> string -> Cstruct.t
val unpad : string -> string
\ No newline at end of file +Hieroglyphs__Utils (hieroglyphs.Hieroglyphs__Utils)

Module Hieroglyphs__Utils

val _HASH_LENGTH : int
val _KEY_LENGTH : int
val to_hex : string -> string
val concat_hashes : string -> string -> string
val validate_key : string list -> string list option
val replace_index : matrix:string list -> int list -> string list
val indexed_keys : string -> int list
val verify_with : matrix:string list -> digest:(string -> string) -> (int * string) list -> bool
val pad : basis:int -> string -> Cstruct.t
val unpad : string -> string
val bytes_of_string : string -> bytes
val bytes_to_string : bytes -> string
\ No newline at end of file diff --git a/docs/apiref/hieroglyphs/Hieroglyphs__Verification/index.html b/docs/apiref/hieroglyphs/Hieroglyphs__Verification/index.html index 99e3bcb..b7d903d 100644 --- a/docs/apiref/hieroglyphs/Hieroglyphs__Verification/index.html +++ b/docs/apiref/hieroglyphs/Hieroglyphs__Verification/index.html @@ -1,2 +1,2 @@ -Hieroglyphs__Verification (hieroglyphs.Hieroglyphs__Verification)

Module Hieroglyphs__Verification

val verify : pub:string list -> msg:string -> signature:string -> bool
\ No newline at end of file +Hieroglyphs__Verification (hieroglyphs.Hieroglyphs__Verification)

Module Hieroglyphs__Verification

val verify : pub:bytes list -> msg:string -> signature:string -> bool
\ No newline at end of file diff --git a/docs/coverage/index.html b/docs/coverage/index.html index c14d7aa..35a02ab 100644 --- a/docs/coverage/index.html +++ b/docs/coverage/index.html @@ -110,6 +110,6 @@

100.00%

- + diff --git a/docs/coverage/lib/blacklist.ml.html b/docs/coverage/lib/blacklist.ml.html index a67cb7f..7c86783 100644 --- a/docs/coverage/lib/blacklist.ml.html +++ b/docs/coverage/lib/blacklist.ml.html @@ -49,12 +49,12 @@

100.00%

let exists address = - let key = "blacklist/" ^ address in - match Store.get ~key with None -> false | Some _ -> true + let key = "blacklist/" ^ address in + match Store.get ~key with None -> false | Some _ -> true - + diff --git a/docs/coverage/lib/encryption.ml.html b/docs/coverage/lib/encryption.ml.html index c1a07ed..4979af2 100644 --- a/docs/coverage/lib/encryption.ml.html +++ b/docs/coverage/lib/encryption.ml.html @@ -63,13 +63,13 @@

100.00%

module Base64 = Nocrypto.Base64 let encrypt msg ~pass = - let key = of_secret (Hash.mine pass ~difficulty:6) in + let key = of_secret (Hash.mine pass ~difficulty:5) in let result = encrypt ~key (Utils.pad ~basis:16 msg) in result |> Base64.encode |> Cstruct.to_string let decrypt cipher ~pass = - let key = of_secret (Hash.mine pass ~difficulty:6) in + let key = of_secret (Hash.mine pass ~difficulty:5) in let result = cipher |> Cstruct.of_string |> Base64.decode in let open Option in result @@ -78,7 +78,7 @@

100.00%

- + diff --git a/docs/coverage/lib/hash.ml.html b/docs/coverage/lib/hash.ml.html index ad8c753..eb97916 100644 --- a/docs/coverage/lib/hash.ml.html +++ b/docs/coverage/lib/hash.ml.html @@ -19,25 +19,30 @@

100.00%

  
- 
+ 
  
- 
- 
- 
+ 
+ 
+ 
  
  
  
  
- 
- 
- 
+ 
+ 
+ 
  
- 
- 
+ 
+ 
  
  
  
- 
+ 
+ 
+ 
+ 
+ 
+ 
 
@@ -62,22 +67,32 @@

100.00%

18 19 20 +21 +22 +23 +24 +25
+module Bytes = Core.Bytes
+
 let digest text =
-  text |> Digestif.BLAKE2B.digest_string |> Digestif.BLAKE2B.to_hex
+  text |> Digestif.BLAKE2B.digest_string |> Digestif.BLAKE2B.to_hex
+
+let digest_bytes bytes =
+  bytes
+  |> Digestif.BLAKE2B.digest_bytes
+  |> Digestif.BLAKE2B.to_raw_string
+  |> Bytes.of_string
 
 let rec __mining input pattern nonce =
-  let length = Core.String.length pattern in
-  let salt = Nocrypto.Numeric.Z.to_cstruct_be nonce in
-  let message = Cstruct.append input salt in
-  let result = Nocrypto.Hash.SHA256.digest message in
-  let digest = Hex.show @@ Hex.of_cstruct result in
-  let part = Core.String.sub ~pos:0 ~len:length digest in
-  if pattern = part then
-    result
-  else
-    __mining input pattern @@ Z.succ nonce
+  let length = Core.String.length pattern in
+  let salt = Nocrypto.Numeric.Z.to_cstruct_be nonce in
+  let message = Cstruct.append input salt in
+  let result = Nocrypto.Hash.SHA256.digest message in
+  let digest = Hex.show @@ Hex.of_cstruct result in
+  let part = Core.String.sub ~pos:0 ~len:length digest in
+  if pattern = part then result else __mining input pattern @@ Z.succ nonce
 
 let mine ~difficulty text =
   let input = Cstruct.of_string text in
@@ -87,7 +102,7 @@ 

100.00%

- + diff --git a/docs/coverage/lib/hieroglyphs.ml.html b/docs/coverage/lib/hieroglyphs.ml.html index fea0f83..9a2064e 100644 --- a/docs/coverage/lib/hieroglyphs.ml.html +++ b/docs/coverage/lib/hieroglyphs.ml.html @@ -40,42 +40,38 @@

100.00%

- + - - + + - - + + - - + + - + - + - + - + - - + + - - - - - - + +
@@ -134,20 +130,18 @@

100.00%

52 53 54 -55 -56 -57 -58
 module Option = Core.Option
 
-type priv = string list
+type priv = bytes list
 
-type pub = string list
+type pub = bytes list
 
 let derive = Keys.derive
 
+let pair = Keys.pair
+
 let import = Keys.import
 
 let export = Keys.export
@@ -165,9 +159,9 @@ 

100.00%

(*** wrappers *****************************************************************) let __check priv = - let pub = derive priv in - let id = address pub in - if Blacklist.exists id then None else Some pub + let pub = derive priv in + let id = address pub in + if Blacklist.exists id then None else Some pub let sign ~priv ~msg = @@ -187,21 +181,15 @@

100.00%

let rec generate () = - let priv = Keys.generate () in - let const _ _ = priv in - let option = __check priv in - let step = Option.value_map option ~default:generate ~f:const in - step () - - -let pair () = - let priv = generate () in - let pub = derive priv in - (priv, pub) + let priv = Keys.generate () in + let const _ _ = priv in + let option = __check priv in + let step = Option.value_map option ~default:generate ~f:const in + step ()
- + diff --git a/docs/coverage/lib/keys.ml.html b/docs/coverage/lib/keys.ml.html index 3f8c29a..c8b1b39 100644 --- a/docs/coverage/lib/keys.ml.html +++ b/docs/coverage/lib/keys.ml.html @@ -25,44 +25,61 @@

100.00%

- - - - - - + + + + + + - - - + + + - - + + - + - - - - + + + + - + - - + + - + - - + + + + + + + + + + + + + + + + + + +
@@ -112,6 +129,23 @@

100.00%

43 44 45 +46 +47 +48 +49 +50 +51 +52 +53 +54 +55 +56 +57 +58 +59 +60 +61 +62
 module List = Core.List
@@ -120,34 +154,51 @@ 

100.00%

module Int64 = Core.Int64 module Option = Core.Option +(* let populate time _ = - () - |> Random.generate - |> Int64.to_string - |> String.( ^ ) time - |> Hash.digest - |> Hash.digest - + () + |> Random.generate + |> Int64.to_string + |> String.( ^ ) time + |> Hash.digest + |> Hash.digest +*) let length = Utils._KEY_LENGTH -let timestamp () = () |> Unix.gettimeofday |> Float.to_string +(* +let timestamp () = () |> Unix.gettimeofday |> Float.to_string let generate () = - let time = timestamp () in - List.init length ~f:(populate time) + let time = timestamp () in + List.init length ~f:(populate time) +*) + +let _random_hex _ = + Random.generate512 ( ) + +let generate ( ) = + List.init length ~f:_random_hex +let derive priv = List.map priv ~f:Hash.digest_bytes -let derive priv = List.map priv ~f:Hash.digest +let pair () = + let priv = generate () in + let pub = derive priv in + (priv, pub) let export ~priv ~pass = - priv |> List.reduce_exn ~f:Utils.concat_hashes |> Encryption.encrypt ~pass + priv + |> List.map ~f:Utils.bytes_to_string + |> List.reduce_exn ~f:Utils.concat_hashes + |> Encryption.encrypt ~pass let import ~cipher ~pass = let open Option in Encryption.decrypt ~pass cipher - >>= fun result -> result |> String.split ~on:'-' |> Utils.validate_key + >>= fun result -> result |> String.split ~on:'-' |> Utils.validate_key >>= fun list -> + some @@ List.map list ~f:Utils.bytes_of_string let load = Serialization.load @@ -162,7 +213,7 @@

100.00%

- + diff --git a/docs/coverage/lib/random.ml.html b/docs/coverage/lib/random.ml.html index 267ca41..1b8aa75 100644 --- a/docs/coverage/lib/random.ml.html +++ b/docs/coverage/lib/random.ml.html @@ -18,31 +18,52 @@

100.00%

- 
+ 
  
  
- 
+ 
  
+ 
+ 
+ 
+ 
+ 
+ 
+ 
 
-1
-2
-3
-4
-5
+ 1
+ 2
+ 3
+ 4
+ 5
+ 6
+ 7
+ 8
+ 9
+10
+11
+12
 
-let generate ( ) =
-  Nocrypto.Rng.Int64.gen Core.Int64.max_value
+let _MIN_RANDOM = "1" ^ Core.String.init 511 ~f:(Core.const '0')
+let _MAX_RANDOM = Core.String.init 512 ~f:(Core.const '1')
+
+let _min_random = Z.of_string_base 2 _MIN_RANDOM
+let _max_random = Z.of_string_base 2 _MAX_RANDOM
+
+let generate512 ( ) =
+  let number = Nocrypto.Rng.Z.gen_r _min_random _max_random in
+  Cstruct.to_bytes @@ Nocrypto.Numeric.Z.to_cstruct_be number
 
 let _ =
   Nocrypto_entropy_unix.initialize ( )
 
- + diff --git a/docs/coverage/lib/serialization.ml.html b/docs/coverage/lib/serialization.ml.html index 5c614d6..df17111 100644 --- a/docs/coverage/lib/serialization.ml.html +++ b/docs/coverage/lib/serialization.ml.html @@ -22,17 +22,22 @@

100.00%

- - - + + + - + - + - + - + + + + + +
@@ -52,27 +57,37 @@

100.00%

13 14 15 +16 +17 +18 +19 +20
 module List = Core.List
 module String = Core.String
+module Option = Core.Option
 
 let show pub =
- List.reduce_exn pub ~f:Utils.concat_hashes
+  pub
+  |> List.map ~f:Utils.bytes_to_string
+  |> List.reduce_exn ~f:Utils.concat_hashes
 
 let load text =
   let list = String.split text ~on:'-' in
-  Utils.validate_key list
+  let open Option in
+  Utils.validate_key list >>= fun list ->
+  some @@ List.map ~f:Utils.bytes_of_string list
 
 let address pub =
-  pub
-  |> show
-  |> Hash.digest
-  |> Utils.to_hex
+  pub
+  |> show
+  |> Hash.digest
+  |> Utils.to_hex
 
- + diff --git a/docs/coverage/lib/signing.ml.html b/docs/coverage/lib/signing.ml.html index d25587a..916784f 100644 --- a/docs/coverage/lib/signing.ml.html +++ b/docs/coverage/lib/signing.ml.html @@ -25,6 +25,7 @@

100.00%

+
@@ -36,11 +37,13 @@

100.00%

5 6 7 +8
 module List = Core.List
 
 let sign ~priv ~msg =
+  let priv = List.map priv ~f:Utils.bytes_to_string in
   msg
   |> Utils.indexed_keys
   |> Utils.replace_index ~matrix:priv
@@ -48,7 +51,7 @@ 

100.00%

- + diff --git a/docs/coverage/lib/store.ml.html b/docs/coverage/lib/store.ml.html index 498f415..f823a0f 100644 --- a/docs/coverage/lib/store.ml.html +++ b/docs/coverage/lib/store.ml.html @@ -175,13 +175,13 @@

100.00%

let get ~key = - let path = String.split ~on:'/' key in - let transaction () = - GitStore.Repo.v config + let path = String.split ~on:'/' key in + let transaction () = + GitStore.Repo.v config >>= fun repo -> - GitStore.master repo >>= fun branch -> GitStore.get branch path + GitStore.master repo >>= fun branch -> GitStore.get branch path in - try Some (Lwt_main.run (transaction ())) with Invalid_argument _ -> None + try Some (Lwt_main.run (transaction ())) with Invalid_argument _ -> None let boot () = @@ -204,7 +204,7 @@

100.00%

- + diff --git a/docs/coverage/lib/utils.ml.html b/docs/coverage/lib/utils.ml.html index 99596bd..406727e 100644 --- a/docs/coverage/lib/utils.ml.html +++ b/docs/coverage/lib/utils.ml.html @@ -61,39 +61,50 @@

100.00%

- + - + - + - - + + - + - - + + - - + + - - - - + + + + - + - + - + + + + + + + + + + + +
@@ -174,6 +185,17 @@

100.00%

74 75 76 +77 +78 +79 +80 +81 +82 +83 +84 +85 +86 +87
 module List = Core.List
@@ -194,7 +216,7 @@ 

100.00%

let id value = value let is_hash text = - Str.string_match regexp text 0 && String.length text = _HASH_LENGTH + Str.string_match regexp text 0 && String.length text = _HASH_LENGTH let validate_key list = @@ -202,7 +224,7 @@

100.00%

if List.length filtered = _KEY_LENGTH then Some list else None -let to_hex text = "0x" ^ text +let to_hex text = "0x" ^ text let tag_index entries = let length = List.length entries in @@ -218,7 +240,8 @@

100.00%

let verify_at ~digest ~list (position, hash) = let commitment = List.nth_exn list position in - digest hash = commitment + let opening = digest hash in + opening = commitment let verify_with ~matrix ~digest pairs = @@ -227,15 +250,19 @@

100.00%

|> List.reduce_exn ~f:( && ) -let concat_hashes left right = left ^ "-" ^ right +let concat_hashes left right = left ^ "-" ^ right + +let char_to_hex_int char = + char + |> Char.to_string + |> to_hex + |> Int.of_string let indexed_keys msg = msg |> Hash.digest |> String.to_list - |> List.map ~f:Char.to_string - |> List.map ~f:to_hex - |> List.map ~f:Int.of_string + |> List.map ~f:char_to_hex_int |> tag_index |> List.map ~f:calculate_index @@ -252,10 +279,16 @@

100.00%

let nonzero char = char != nullchar let unpad msg = String.filter ~f:nonzero msg + +let bytes_of_string string = + Cstruct.to_bytes @@ Cstruct.of_hex string + +let bytes_to_string bytes = + Hex.show @@ Hex.of_cstruct @@ Cstruct.of_bytes bytes
- + diff --git a/docs/coverage/lib/verification.ml.html b/docs/coverage/lib/verification.ml.html index bb41112..504925c 100644 --- a/docs/coverage/lib/verification.ml.html +++ b/docs/coverage/lib/verification.ml.html @@ -26,32 +26,62 @@

100.00%

+ + + + + + + + + +
-1
-2
-3
-4
-5
-6
-7
-8
+ 1
+ 2
+ 3
+ 4
+ 5
+ 6
+ 7
+ 8
+ 9
+10
+11
+12
+13
+14
+15
+16
+17
+18
 
 module String = Core.String
 module List = Core.List
 
+let digest message =
+  message
+  |> Cstruct.of_hex
+  |> Cstruct.to_bytes
+  |> Hash.digest_bytes
+  |> Cstruct.of_bytes
+  |> Hex.of_cstruct
+  |> Hex.show
+
 let verify ~pub ~msg ~signature =
+  let pub = List.map ~f:Utils.bytes_to_string pub in
   let indexed_keys = Utils.indexed_keys msg in
   let hashes = String.split signature ~on:'-' in
   let proofs = List.zip_exn indexed_keys hashes in
-  Utils.verify_with ~matrix:pub ~digest:Hash.digest proofs
+  Utils.verify_with ~matrix:pub ~digest proofs
 
- + From df28d0d9fc4fe043b53e8993b6e9fa0e47b46462 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marco=20Aur=C3=A9lio=20da=20Silva?= Date: Sat, 2 Mar 2019 14:13:53 -0300 Subject: [PATCH 03/29] refactor: :zap: :recycle: :fist_oncoming: dropped many PRNG calls from private key generation [+] MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit it now uses HD-wallet-alike hashing to generate all the private key pieces Signed-off-by: Marco Aurélio da Silva --- Makefile | 10 +- .../Bisect_visit___lib___keys___ml/index.html | 2 + .../hieroglyphs/Hieroglyphs__/Keys/index.html | 2 +- .../Bisect_visit___lib___keys___ml/index.html | 2 + .../hieroglyphs/Hieroglyphs__Keys/index.html | 2 +- docs/coverage/index.html | 2 +- docs/coverage/lib/blacklist.ml.html | 4 +- docs/coverage/lib/encryption.ml.html | 2 +- docs/coverage/lib/hash.ml.html | 45 ++++++--- docs/coverage/lib/hieroglyphs.ml.html | 2 +- docs/coverage/lib/keys.ml.html | 99 +++++++++++++------ docs/coverage/lib/random.ml.html | 36 ++++--- docs/coverage/lib/serialization.ml.html | 28 +++--- docs/coverage/lib/signing.ml.html | 2 +- docs/coverage/lib/store.ml.html | 4 +- docs/coverage/lib/utils.ml.html | 57 ++++------- docs/coverage/lib/verification.ml.html | 7 +- lib/blacklist.ml | 2 +- lib/hash.ml | 4 +- lib/keys.ml | 14 ++- lib/store.ml | 2 +- test/bench/bench.expected | 32 +++--- 22 files changed, 212 insertions(+), 148 deletions(-) create mode 100644 docs/apiref/hieroglyphs/Hieroglyphs__/Keys/Bisect_visit___lib___keys___ml/index.html create mode 100644 docs/apiref/hieroglyphs/Hieroglyphs__Keys/Bisect_visit___lib___keys___ml/index.html diff --git a/Makefile b/Makefile index 6dd5fce..837d058 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,12 @@ # Frontend to dune. +OCAML_VERSION := $(shell opam var switch) + .PHONY: default vendor build doc install uninstall test coverage report clean +addon: + opam install merlin ocp-indent ocamlformat utop --yes + vendor: opam install . --deps-only --yes @@ -23,7 +28,8 @@ doc: build mkdir -p docs/apiref dune build @doc make doc-index - mv _build/default/_doc/_html/* docs/apiref/ + mv _build/$(OCAML_VERSION)/_doc/_html/* docs/apiref/ || \ + mv _build/default/_doc/_html/* docs/apiref/ ### Alcotest environment variables: # @@ -36,7 +42,7 @@ test: build bench: clean build opam install core_bench --yes - opam depext conf-secp256k1 secp256k1 --install + opam depext conf-secp256k1 secp256k1 --install --yes dune build @test/bench/runtest -f --no-buffer -j 1 --auto-promote \ --diff-command="git diff --unified=10 --break-rewrites --no-index --exit-code --histogram --word-diff=none --color --no-prefix" || echo \ "\n\n=== Differences detected! ===\n\n" diff --git a/docs/apiref/hieroglyphs/Hieroglyphs__/Keys/Bisect_visit___lib___keys___ml/index.html b/docs/apiref/hieroglyphs/Hieroglyphs__/Keys/Bisect_visit___lib___keys___ml/index.html new file mode 100644 index 0000000..392a120 --- /dev/null +++ b/docs/apiref/hieroglyphs/Hieroglyphs__/Keys/Bisect_visit___lib___keys___ml/index.html @@ -0,0 +1,2 @@ + +Bisect_visit___lib___keys___ml (hieroglyphs.Hieroglyphs__.Keys.Bisect_visit___lib___keys___ml)

Module Keys.Bisect_visit___lib___keys___ml

val ___bisect_visit___ : int -> unit
\ No newline at end of file diff --git a/docs/apiref/hieroglyphs/Hieroglyphs__/Keys/index.html b/docs/apiref/hieroglyphs/Hieroglyphs__/Keys/index.html index ae151b6..26ec051 100644 --- a/docs/apiref/hieroglyphs/Hieroglyphs__/Keys/index.html +++ b/docs/apiref/hieroglyphs/Hieroglyphs__/Keys/index.html @@ -1,2 +1,2 @@ -Keys (hieroglyphs.Hieroglyphs__.Keys)

Module Hieroglyphs__.Keys

module List = Core.List
module String = Core.String
module Float = Core.Float
module Int64 = Core.Int64
module Option = Core.Option
val length : int
val _random_hex : 'a -> bytes
val generate : unit -> bytes List.t
val derive : bytes List.t -> bytes List.t
val pair : unit -> bytes List.t * bytes List.t
val export : priv:bytes List.t -> pass:string -> string
val import : cipher:string -> pass:string -> bytes List.t Option.t
val load : string -> bytes list option
val show : bytes list -> string
val address : bytes list -> string
val sign : priv:bytes list -> msg:string -> string
val verify : pub:bytes list -> msg:string -> signature:string -> bool
\ No newline at end of file +Keys (hieroglyphs.Hieroglyphs__.Keys)

Module Hieroglyphs__.Keys

module Bisect_visit___lib___keys___ml : sig ... end
module List = Core.List
module String = Core.String
module Float = Core.Float
module Int64 = Core.Int64
module Option = Core.Option
val length : int
val _random_hex : 'a -> Cstruct.t
val _int_to_cstruct : int -> Cstruct.t
val _hash_both : Cstruct.t -> Cstruct.t -> bytes
val generate : unit -> bytes List.t
val derive : bytes List.t -> bytes List.t
val pair : unit -> bytes List.t * bytes List.t
val export : priv:bytes List.t -> pass:string -> string
val import : cipher:string -> pass:string -> bytes List.t Option.t
val load : string -> bytes list option
val show : bytes list -> string
val address : bytes list -> string
val sign : priv:bytes list -> msg:string -> string
val verify : pub:bytes list -> msg:string -> signature:string -> bool
\ No newline at end of file diff --git a/docs/apiref/hieroglyphs/Hieroglyphs__Keys/Bisect_visit___lib___keys___ml/index.html b/docs/apiref/hieroglyphs/Hieroglyphs__Keys/Bisect_visit___lib___keys___ml/index.html new file mode 100644 index 0000000..35acb61 --- /dev/null +++ b/docs/apiref/hieroglyphs/Hieroglyphs__Keys/Bisect_visit___lib___keys___ml/index.html @@ -0,0 +1,2 @@ + +Bisect_visit___lib___keys___ml (hieroglyphs.Hieroglyphs__Keys.Bisect_visit___lib___keys___ml)

Module Hieroglyphs__Keys.Bisect_visit___lib___keys___ml

val ___bisect_visit___ : int -> unit
\ No newline at end of file diff --git a/docs/apiref/hieroglyphs/Hieroglyphs__Keys/index.html b/docs/apiref/hieroglyphs/Hieroglyphs__Keys/index.html index df7ab51..8f2cb46 100644 --- a/docs/apiref/hieroglyphs/Hieroglyphs__Keys/index.html +++ b/docs/apiref/hieroglyphs/Hieroglyphs__Keys/index.html @@ -1,2 +1,2 @@ -Hieroglyphs__Keys (hieroglyphs.Hieroglyphs__Keys)

Module Hieroglyphs__Keys

module List = Core.List
module String = Core.String
module Float = Core.Float
module Int64 = Core.Int64
module Option = Core.Option
val length : int
val _random_hex : 'a -> bytes
val generate : unit -> bytes List.t
val derive : bytes List.t -> bytes List.t
val pair : unit -> bytes List.t * bytes List.t
val export : priv:bytes List.t -> pass:string -> string
val import : cipher:string -> pass:string -> bytes List.t Option.t
val load : string -> bytes list option
val show : bytes list -> string
val address : bytes list -> string
val sign : priv:bytes list -> msg:string -> string
val verify : pub:bytes list -> msg:string -> signature:string -> bool
\ No newline at end of file +Hieroglyphs__Keys (hieroglyphs.Hieroglyphs__Keys)

Module Hieroglyphs__Keys

module Bisect_visit___lib___keys___ml : sig ... end
module List = Core.List
module String = Core.String
module Float = Core.Float
module Int64 = Core.Int64
module Option = Core.Option
val length : int
val _random_hex : 'a -> Cstruct.t
val _int_to_cstruct : int -> Cstruct.t
val _hash_both : Cstruct.t -> Cstruct.t -> bytes
val generate : unit -> bytes List.t
val derive : bytes List.t -> bytes List.t
val pair : unit -> bytes List.t * bytes List.t
val export : priv:bytes List.t -> pass:string -> string
val import : cipher:string -> pass:string -> bytes List.t Option.t
val load : string -> bytes list option
val show : bytes list -> string
val address : bytes list -> string
val sign : priv:bytes list -> msg:string -> string
val verify : pub:bytes list -> msg:string -> signature:string -> bool
\ No newline at end of file diff --git a/docs/coverage/index.html b/docs/coverage/index.html index 35a02ab..1a7c9ac 100644 --- a/docs/coverage/index.html +++ b/docs/coverage/index.html @@ -110,6 +110,6 @@

100.00%

- + diff --git a/docs/coverage/lib/blacklist.ml.html b/docs/coverage/lib/blacklist.ml.html index 7c86783..1c3c980 100644 --- a/docs/coverage/lib/blacklist.ml.html +++ b/docs/coverage/lib/blacklist.ml.html @@ -44,7 +44,7 @@

100.00%

 let add address =
   let key = "blacklist/" ^ address in
-  let msg = "Revoking private key " ^ address ^ "." in
+  let msg = "Revoking private key ID " ^ address ^ "." in
   Store.set ~msg ~key ""
 
 
@@ -54,7 +54,7 @@ 

100.00%

- + diff --git a/docs/coverage/lib/encryption.ml.html b/docs/coverage/lib/encryption.ml.html index 4979af2..e98d73f 100644 --- a/docs/coverage/lib/encryption.ml.html +++ b/docs/coverage/lib/encryption.ml.html @@ -78,7 +78,7 @@

100.00%

- + diff --git a/docs/coverage/lib/hash.ml.html b/docs/coverage/lib/hash.ml.html index eb97916..8df4783 100644 --- a/docs/coverage/lib/hash.ml.html +++ b/docs/coverage/lib/hash.ml.html @@ -24,25 +24,30 @@

100.00%

- + - + - + - - + + - - + + - - + + + + + + +
@@ -72,6 +77,11 @@

100.00%

23 24 25 +26 +27 +28 +29 +30
 module Bytes = Core.Bytes
@@ -79,21 +89,26 @@ 

100.00%

let digest text = text |> Digestif.BLAKE2B.digest_string |> Digestif.BLAKE2B.to_hex + let digest_bytes bytes = - bytes - |> Digestif.BLAKE2B.digest_bytes - |> Digestif.BLAKE2B.to_raw_string - |> Bytes.of_string + bytes + |> Digestif.BLAKE2B.digest_bytes + |> Digestif.BLAKE2B.to_raw_string + |> Bytes.of_string + +let __digest message = + Nocrypto.Hash.SHA256.digest message let rec __mining input pattern nonce = let length = Core.String.length pattern in let salt = Nocrypto.Numeric.Z.to_cstruct_be nonce in let message = Cstruct.append input salt in - let result = Nocrypto.Hash.SHA256.digest message in + let result = __digest message in let digest = Hex.show @@ Hex.of_cstruct result in let part = Core.String.sub ~pos:0 ~len:length digest in if pattern = part then result else __mining input pattern @@ Z.succ nonce + let mine ~difficulty text = let input = Cstruct.of_string text in let nonce = Z.zero in @@ -102,7 +117,7 @@

100.00%

- + diff --git a/docs/coverage/lib/hieroglyphs.ml.html b/docs/coverage/lib/hieroglyphs.ml.html index 9a2064e..5c2a8e3 100644 --- a/docs/coverage/lib/hieroglyphs.ml.html +++ b/docs/coverage/lib/hieroglyphs.ml.html @@ -189,7 +189,7 @@

100.00%

- + diff --git a/docs/coverage/lib/keys.ml.html b/docs/coverage/lib/keys.ml.html index c8b1b39..e78e080 100644 --- a/docs/coverage/lib/keys.ml.html +++ b/docs/coverage/lib/keys.ml.html @@ -44,42 +44,55 @@

100.00%

- - + + - - + + - - - - + + + + - - - + + + - - - - - - + + + + + + - + - - + + - + - - + + + + + + + + + + + + + + +
@@ -146,6 +159,19 @@

100.00%

60 61 62 +63 +64 +65 +66 +67 +68 +69 +70 +71 +72 +73 +74 +75
 module List = Core.List
@@ -174,11 +200,20 @@ 

100.00%

List.init length ~f:(populate time) *) -let _random_hex _ = - Random.generate512 ( ) +let _random_hex _ = Cstruct.of_bytes @@ Random.generate512 () -let generate ( ) = - List.init length ~f:_random_hex +let _int_to_cstruct number = + Cstruct.of_string @@ string_of_int number + +let _hash_both prefix suffix = + (Cstruct.append prefix suffix) + |> Cstruct.to_bytes + |> Hash.digest_bytes + +let generate () = + let nums = List.init length ~f:_int_to_cstruct in + let rand = _random_hex ( ) in + List.map nums ~f:(_hash_both rand) let derive priv = List.map priv ~f:Hash.digest_bytes @@ -187,6 +222,7 @@

100.00%

let pub = derive priv in (priv, pub) + let export ~priv ~pass = priv |> List.map ~f:Utils.bytes_to_string @@ -197,8 +233,11 @@

100.00%

let import ~cipher ~pass = let open Option in Encryption.decrypt ~pass cipher - >>= fun result -> result |> String.split ~on:'-' |> Utils.validate_key >>= fun list -> - some @@ List.map list ~f:Utils.bytes_of_string + >>= fun result -> + result + |> String.split ~on:'-' + |> Utils.validate_key + >>= fun list -> some @@ List.map list ~f:Utils.bytes_of_string let load = Serialization.load @@ -213,7 +252,7 @@

100.00%

- + diff --git a/docs/coverage/lib/random.ml.html b/docs/coverage/lib/random.ml.html index 1b8aa75..ee68558 100644 --- a/docs/coverage/lib/random.ml.html +++ b/docs/coverage/lib/random.ml.html @@ -19,17 +19,19 @@

100.00%

  
- 
- 
- 
+ 
+ 
+ 
  
  
- 
- 
- 
- 
- 
- 
+ 
+ 
+ 
+ 
+ 
+ 
+ 
+ 
 
@@ -46,24 +48,28 @@

100.00%

10 11 12 +13 +14
 let _MIN_RANDOM = "1" ^ Core.String.init 511 ~f:(Core.const '0')
+
 let _MAX_RANDOM = Core.String.init 512 ~f:(Core.const '1')
 
 let _min_random = Z.of_string_base 2 _MIN_RANDOM
+
 let _max_random = Z.of_string_base 2 _MAX_RANDOM
 
-let generate512 ( ) =
-  let number = Nocrypto.Rng.Z.gen_r _min_random _max_random in
-  Cstruct.to_bytes @@ Nocrypto.Numeric.Z.to_cstruct_be number
+let generate512 () =
+  let number = Nocrypto.Rng.Z.gen_r _min_random _max_random in
+  Cstruct.to_bytes @@ Nocrypto.Numeric.Z.to_cstruct_be number
+
 
-let _ =
-  Nocrypto_entropy_unix.initialize ( )
+let _ = Nocrypto_entropy_unix.initialize ()
 
- + diff --git a/docs/coverage/lib/serialization.ml.html b/docs/coverage/lib/serialization.ml.html index df17111..00f29f7 100644 --- a/docs/coverage/lib/serialization.ml.html +++ b/docs/coverage/lib/serialization.ml.html @@ -28,16 +28,14 @@

100.00%

- + - - - + + + - + - -
@@ -60,8 +58,6 @@

100.00%

16 17 18 -19 -20
 module List = Core.List
@@ -73,21 +69,19 @@ 

100.00%

|> List.map ~f:Utils.bytes_to_string |> List.reduce_exn ~f:Utils.concat_hashes + let load text = let list = String.split text ~on:'-' in let open Option in - Utils.validate_key list >>= fun list -> - some @@ List.map ~f:Utils.bytes_of_string list + Utils.validate_key list + >>= fun list -> some @@ List.map ~f:Utils.bytes_of_string list + -let address pub = - pub - |> show - |> Hash.digest - |> Utils.to_hex +let address pub = pub |> show |> Hash.digest |> Utils.to_hex
- + diff --git a/docs/coverage/lib/signing.ml.html b/docs/coverage/lib/signing.ml.html index 916784f..f19807d 100644 --- a/docs/coverage/lib/signing.ml.html +++ b/docs/coverage/lib/signing.ml.html @@ -51,7 +51,7 @@

100.00%

- + diff --git a/docs/coverage/lib/store.ml.html b/docs/coverage/lib/store.ml.html index f823a0f..b00755f 100644 --- a/docs/coverage/lib/store.ml.html +++ b/docs/coverage/lib/store.ml.html @@ -188,7 +188,7 @@

100.00%

let date = 946684800L (* Sat Jan 1 00:00:00 2000 +0000 *) in let address = "0x" ^ String.make Utils._HASH_LENGTH '0' in let path = ["blacklist"; address] in - let msg = "Revoking private key " ^ address ^ "." in + let msg = "Revoking private key ID " ^ address ^ "." in let info = Core.const (Irmin.Info.v ~date ~author msg) in let transaction () = GitStore.Repo.v config @@ -204,7 +204,7 @@

100.00%

- + diff --git a/docs/coverage/lib/utils.ml.html b/docs/coverage/lib/utils.ml.html index 406727e..dd04012 100644 --- a/docs/coverage/lib/utils.ml.html +++ b/docs/coverage/lib/utils.ml.html @@ -72,39 +72,34 @@

100.00%

- - - + + + - - + + - - + + - + - + - - - - + + + + - - + + - - - - - - - + +
@@ -191,11 +186,6 @@

100.00%

80 81 82 -83 -84 -85 -86 -87
 module List = Core.List
@@ -216,7 +206,7 @@ 

100.00%

let id value = value let is_hash text = - Str.string_match regexp text 0 && String.length text = _HASH_LENGTH + Str.string_match regexp text 0 && String.length text = _HASH_LENGTH let validate_key list = @@ -252,11 +242,7 @@

100.00%

let concat_hashes left right = left ^ "-" ^ right -let char_to_hex_int char = - char - |> Char.to_string - |> to_hex - |> Int.of_string +let char_to_hex_int char = char |> Char.to_string |> to_hex |> Int.of_string let indexed_keys msg = msg @@ -280,15 +266,14 @@

100.00%

let unpad msg = String.filter ~f:nonzero msg -let bytes_of_string string = - Cstruct.to_bytes @@ Cstruct.of_hex string +let bytes_of_string string = Cstruct.to_bytes @@ Cstruct.of_hex string let bytes_to_string bytes = Hex.show @@ Hex.of_cstruct @@ Cstruct.of_bytes bytes
- + diff --git a/docs/coverage/lib/verification.ml.html b/docs/coverage/lib/verification.ml.html index 504925c..00a14b9 100644 --- a/docs/coverage/lib/verification.ml.html +++ b/docs/coverage/lib/verification.ml.html @@ -31,11 +31,12 @@

100.00%

- + +
@@ -58,6 +59,7 @@

100.00%

16 17 18 +19
 module String = Core.String
@@ -72,6 +74,7 @@ 

100.00%

|> Hex.of_cstruct |> Hex.show + let verify ~pub ~msg ~signature = let pub = List.map ~f:Utils.bytes_to_string pub in let indexed_keys = Utils.indexed_keys msg in @@ -81,7 +84,7 @@

100.00%

- + diff --git a/lib/blacklist.ml b/lib/blacklist.ml index e9e3ab8..06ac25c 100644 --- a/lib/blacklist.ml +++ b/lib/blacklist.ml @@ -1,6 +1,6 @@ let add address = let key = "blacklist/" ^ address in - let msg = "Revoking private key " ^ address ^ "." in + let msg = "Revoking private key ID " ^ address ^ "." in Store.set ~msg ~key "" diff --git a/lib/hash.ml b/lib/hash.ml index 2ef4a9e..6df465c 100644 --- a/lib/hash.ml +++ b/lib/hash.ml @@ -11,11 +11,13 @@ let digest_bytes bytes = |> Bytes.of_string +let __digest message = Nocrypto.Hash.SHA256.digest message + let rec __mining input pattern nonce = let length = Core.String.length pattern in let salt = Nocrypto.Numeric.Z.to_cstruct_be nonce in let message = Cstruct.append input salt in - let result = Nocrypto.Hash.SHA256.digest message in + let result = __digest message in let digest = Hex.show @@ Hex.of_cstruct result in let part = Core.String.sub ~pos:0 ~len:length digest in if pattern = part then result else __mining input pattern @@ Z.succ nonce diff --git a/lib/keys.ml b/lib/keys.ml index fd4fbb7..1b3ef29 100644 --- a/lib/keys.ml +++ b/lib/keys.ml @@ -24,9 +24,19 @@ let generate () = List.init length ~f:(populate time) *) -let _random_hex _ = Random.generate512 () +let _random_hex _ = Cstruct.of_bytes @@ Random.generate512 () + +let _int_to_cstruct number = Cstruct.of_string @@ string_of_int number + +let _hash_both prefix suffix = + Cstruct.append prefix suffix |> Cstruct.to_bytes |> Hash.digest_bytes + + +let generate () = + let nums = List.init length ~f:_int_to_cstruct in + let rand = _random_hex () in + List.map nums ~f:(_hash_both rand) -let generate () = List.init length ~f:_random_hex let derive priv = List.map priv ~f:Hash.digest_bytes diff --git a/lib/store.ml b/lib/store.ml index 2f38d1a..c34c142 100644 --- a/lib/store.ml +++ b/lib/store.ml @@ -44,7 +44,7 @@ let boot () = let date = 946684800L (* Sat Jan 1 00:00:00 2000 +0000 *) in let address = "0x" ^ String.make Utils._HASH_LENGTH '0' in let path = ["blacklist"; address] in - let msg = "Revoking private key " ^ address ^ "." in + let msg = "Revoking private key ID " ^ address ^ "." in let info = Core.const (Irmin.Info.v ~date ~author msg) in let transaction () = GitStore.Repo.v config diff --git a/test/bench/bench.expected b/test/bench/bench.expected index 498863e..88f7e33 100644 --- a/test/bench/bench.expected +++ b/test/bench/bench.expected @@ -1,17 +1,17 @@ Estimated testing time 2m (12 benchmarks x 10s). Change using -quota SECS. -┌─────────────────────────────────────────────────────┬─────────────────┬───────────────┬─────────────┬────────────┬────────────┐ -│ Name │ Time/Run │ mWd/Run │ mjWd/Run │ Prom/Run │ Percentage │ -├─────────────────────────────────────────────────────┼─────────────────┼───────────────┼─────────────┼────────────┼────────────┤ -│ hieroglyphs + blake2b ------ private key generation │ 36_115_048.25ns │ 1_257_186.16w │ 24_212.48w │ 24_212.48w │ 100.00% │ -│ hieroglyphs + blake2b ------ message signing │ 11_213_663.99ns │ 552_974.77w │ 160_025.25w │ 28_670.25w │ 31.05% │ -│ hieroglyphs + blake2b ------ public key derivation │ 3_008_022.90ns │ 190_464.86w │ 7_971.99w │ 7_971.99w │ 8.33% │ -│ hieroglyphs + blake2b ------ signature verification │ 12_598_340.69ns │ 865_711.60w │ 44_975.21w │ 44_975.21w │ 34.88% │ -│ rsa pss/sha256 1024 bits --- private key generation │ 35_080_509.59ns │ 870.80w │ 0.35w │ 0.35w │ 97.14% │ -│ rsa pss/sha256 1024 bits --- public key derivation │ 11.46ns │ 3.00w │ │ │ │ -│ rsa pss/sha256 1024 bits --- message signing │ 771_613.48ns │ 1_713.42w │ 0.63w │ 0.63w │ 2.14% │ -│ rsa pss/sha256 1024 bits --- signature verification │ 142_191.97ns │ 1_547.02w │ 0.36w │ 0.36w │ 0.39% │ -│ secp256k1 + sha256 hash ---- private key generation │ 12_920.47ns │ 355.71w │ │ │ 0.04% │ -│ secp256k1 + sha256 hash ---- public key derivation │ 214_130.84ns │ 13.00w │ │ │ 0.59% │ -│ secp256k1 + sha256 hash ---- message signing │ 302_456.71ns │ 230.00w │ │ │ 0.84% │ -│ secp256k1 + sha256 hash ---- signature verification │ 361_341.90ns │ 214.00w │ │ │ 1.00% │ -└─────────────────────────────────────────────────────┴─────────────────┴───────────────┴─────────────┴────────────┴────────────┘ +┌─────────────────────────────────────────────────────┬─────────────────┬─────────────┬─────────────┬────────────┬────────────┐ +│ Name │ Time/Run │ mWd/Run │ mjWd/Run │ Prom/Run │ Percentage │ +├─────────────────────────────────────────────────────┼─────────────────┼─────────────┼─────────────┼────────────┼────────────┤ +│ hieroglyphs + blake2b ------ private key generation │ 6_952_726.97ns │ 275_068.02w │ 24_239.21w │ 24_239.21w │ 17.11% │ +│ hieroglyphs + blake2b ------ message signing │ 12_302_250.23ns │ 552_974.78w │ 160_031.31w │ 28_676.31w │ 30.28% │ +│ hieroglyphs + blake2b ------ public key derivation │ 3_167_539.72ns │ 190_464.87w │ 7_976.50w │ 7_976.50w │ 7.80% │ +│ hieroglyphs + blake2b ------ signature verification │ 18_234_267.33ns │ 865_711.50w │ 44_985.63w │ 44_985.63w │ 44.88% │ +│ rsa pss/sha256 1024 bits --- private key generation │ 40_629_482.92ns │ 870.95w │ -0.25w │ -0.25w │ 100.00% │ +│ rsa pss/sha256 1024 bits --- public key derivation │ 14.20ns │ 3.00w │ │ │ │ +│ rsa pss/sha256 1024 bits --- message signing │ 846_542.56ns │ 1_714.96w │ 0.59w │ 0.59w │ 2.08% │ +│ rsa pss/sha256 1024 bits --- signature verification │ 102_568.59ns │ 1_543.02w │ 0.34w │ 0.34w │ 0.25% │ +│ secp256k1 + sha256 hash ---- private key generation │ 19_958.41ns │ 355.77w │ │ │ 0.05% │ +│ secp256k1 + sha256 hash ---- public key derivation │ 261_015.99ns │ 13.00w │ │ │ 0.64% │ +│ secp256k1 + sha256 hash ---- message signing │ 407_385.47ns │ 230.00w │ │ │ 1.00% │ +│ secp256k1 + sha256 hash ---- signature verification │ 440_845.54ns │ 214.00w │ │ │ 1.09% │ +└─────────────────────────────────────────────────────┴─────────────────┴─────────────┴─────────────┴────────────┴────────────┘ From dda1014b81c15d98289d6097e61a0f0da04d2b3f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marco=20Aur=C3=A9lio=20da=20Silva?= Date: Wed, 6 Mar 2019 23:00:11 -0300 Subject: [PATCH 04/29] refactor: :recycle: generating private key pieces on-demand MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Marco Aurélio da Silva --- docs/coverage/index.html | 2 +- docs/coverage/lib/blacklist.ml.html | 2 +- docs/coverage/lib/encryption.ml.html | 2 +- docs/coverage/lib/hash.ml.html | 14 +-- docs/coverage/lib/hieroglyphs.ml.html | 4 +- docs/coverage/lib/keys.ml.html | 154 +++++------------------- docs/coverage/lib/random.ml.html | 2 +- docs/coverage/lib/serialization.ml.html | 2 +- docs/coverage/lib/signing.ml.html | 26 ++-- docs/coverage/lib/store.ml.html | 2 +- docs/coverage/lib/utils.ml.html | 112 ++++++++++------- docs/coverage/lib/verification.ml.html | 2 +- lib/hieroglyphs.ml | 2 +- lib/keys.ml | 51 ++------ lib/signing.ml | 2 + lib/signing.mli | 2 +- lib/utils.ml | 12 ++ lib/utils.mli | 2 + test/bench/bench.expected | 24 ++-- 19 files changed, 174 insertions(+), 245 deletions(-) diff --git a/docs/coverage/index.html b/docs/coverage/index.html index 1a7c9ac..1febb60 100644 --- a/docs/coverage/index.html +++ b/docs/coverage/index.html @@ -110,6 +110,6 @@

100.00%

- + diff --git a/docs/coverage/lib/blacklist.ml.html b/docs/coverage/lib/blacklist.ml.html index 1c3c980..fce5595 100644 --- a/docs/coverage/lib/blacklist.ml.html +++ b/docs/coverage/lib/blacklist.ml.html @@ -54,7 +54,7 @@

100.00%

- + diff --git a/docs/coverage/lib/encryption.ml.html b/docs/coverage/lib/encryption.ml.html index e98d73f..4570cb2 100644 --- a/docs/coverage/lib/encryption.ml.html +++ b/docs/coverage/lib/encryption.ml.html @@ -78,7 +78,7 @@

100.00%

- + diff --git a/docs/coverage/lib/hash.ml.html b/docs/coverage/lib/hash.ml.html index 8df4783..4398e80 100644 --- a/docs/coverage/lib/hash.ml.html +++ b/docs/coverage/lib/hash.ml.html @@ -91,13 +91,13 @@

100.00%

let digest_bytes bytes = - bytes - |> Digestif.BLAKE2B.digest_bytes - |> Digestif.BLAKE2B.to_raw_string - |> Bytes.of_string + bytes + |> Digestif.BLAKE2B.digest_bytes + |> Digestif.BLAKE2B.to_raw_string + |> Bytes.of_string -let __digest message = - Nocrypto.Hash.SHA256.digest message + +let __digest message = Nocrypto.Hash.SHA256.digest message let rec __mining input pattern nonce = let length = Core.String.length pattern in @@ -117,7 +117,7 @@

100.00%

- + diff --git a/docs/coverage/lib/hieroglyphs.ml.html b/docs/coverage/lib/hieroglyphs.ml.html index 5c2a8e3..079456b 100644 --- a/docs/coverage/lib/hieroglyphs.ml.html +++ b/docs/coverage/lib/hieroglyphs.ml.html @@ -134,7 +134,7 @@

100.00%

 module Option = Core.Option
 
-type priv = bytes list
+type priv = bytes
 
 type pub = bytes list
 
@@ -189,7 +189,7 @@ 

100.00%

- + diff --git a/docs/coverage/lib/keys.ml.html b/docs/coverage/lib/keys.ml.html index e78e080..c01fb04 100644 --- a/docs/coverage/lib/keys.ml.html +++ b/docs/coverage/lib/keys.ml.html @@ -24,75 +24,45 @@

100.00%

- + - + - - + + - - + + - + - + - + - - + + - - - + + + - - + + - - - - + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@@ -142,36 +112,6 @@

100.00%

43 44 45 -46 -47 -48 -49 -50 -51 -52 -53 -54 -55 -56 -57 -58 -59 -60 -61 -62 -63 -64 -65 -66 -67 -68 -69 -70 -71 -72 -73 -74 -75
 module List = Core.List
@@ -180,42 +120,14 @@ 

100.00%

module Int64 = Core.Int64 module Option = Core.Option -(* -let populate time _ = - () - |> Random.generate - |> Int64.to_string - |> String.( ^ ) time - |> Hash.digest - |> Hash.digest -*) - let length = Utils._KEY_LENGTH -(* -let timestamp () = () |> Unix.gettimeofday |> Float.to_string - -let generate () = - let time = timestamp () in - List.init length ~f:(populate time) -*) - -let _random_hex _ = Cstruct.of_bytes @@ Random.generate512 () - -let _int_to_cstruct number = - Cstruct.of_string @@ string_of_int number - -let _hash_both prefix suffix = - (Cstruct.append prefix suffix) - |> Cstruct.to_bytes - |> Hash.digest_bytes - let generate () = - let nums = List.init length ~f:_int_to_cstruct in - let rand = _random_hex ( ) in - List.map nums ~f:(_hash_both rand) + Random.generate512() -let derive priv = List.map priv ~f:Hash.digest_bytes +let derive priv = + let pieces = Utils.generate_pieces ~digest:Hash.digest_bytes priv in + List.map pieces ~f:Hash.digest_bytes let pair () = let priv = generate () in @@ -224,20 +136,18 @@

100.00%

let export ~priv ~pass = - priv - |> List.map ~f:Utils.bytes_to_string - |> List.reduce_exn ~f:Utils.concat_hashes - |> Encryption.encrypt ~pass + Encryption.encrypt ~pass @@ Utils.bytes_to_string priv +let validate_key plain = + if String.length plain == Utils._HASH_LENGTH then + Some plain + else None let import ~cipher ~pass = let open Option in Encryption.decrypt ~pass cipher - >>= fun result -> - result - |> String.split ~on:'-' - |> Utils.validate_key - >>= fun list -> some @@ List.map list ~f:Utils.bytes_of_string + >>= validate_key + >>| Utils.bytes_of_string let load = Serialization.load @@ -252,7 +162,7 @@

100.00%

- + diff --git a/docs/coverage/lib/random.ml.html b/docs/coverage/lib/random.ml.html index ee68558..2fd5536 100644 --- a/docs/coverage/lib/random.ml.html +++ b/docs/coverage/lib/random.ml.html @@ -69,7 +69,7 @@

100.00%

- + diff --git a/docs/coverage/lib/serialization.ml.html b/docs/coverage/lib/serialization.ml.html index 00f29f7..ae57223 100644 --- a/docs/coverage/lib/serialization.ml.html +++ b/docs/coverage/lib/serialization.ml.html @@ -81,7 +81,7 @@

100.00%

- + diff --git a/docs/coverage/lib/signing.ml.html b/docs/coverage/lib/signing.ml.html index f19807d..fa163cc 100644 --- a/docs/coverage/lib/signing.ml.html +++ b/docs/coverage/lib/signing.ml.html @@ -21,28 +21,34 @@

100.00%

- + + +
-1
-2
-3
-4
-5
-6
-7
-8
+ 1
+ 2
+ 3
+ 4
+ 5
+ 6
+ 7
+ 8
+ 9
+10
 
 module List = Core.List
 
 let sign ~priv ~msg =
+  (* yeah, I know that it's really bad smell code *)
+  let priv = Utils.generate_pieces ~digest:Hash.digest_bytes priv in
   let priv = List.map priv ~f:Utils.bytes_to_string in
   msg
   |> Utils.indexed_keys
@@ -51,7 +57,7 @@ 

100.00%

- + diff --git a/docs/coverage/lib/store.ml.html b/docs/coverage/lib/store.ml.html index b00755f..f352ae1 100644 --- a/docs/coverage/lib/store.ml.html +++ b/docs/coverage/lib/store.ml.html @@ -204,7 +204,7 @@

100.00%

- + diff --git a/docs/coverage/lib/utils.ml.html b/docs/coverage/lib/utils.ml.html index dd04012..8da7d74 100644 --- a/docs/coverage/lib/utils.ml.html +++ b/docs/coverage/lib/utils.ml.html @@ -38,68 +38,78 @@

100.00%

- + - + - - - - - - - - + + + + + + + + - - - + + + - - - + + + - - + + - + - + - - + + - - + + - - + + - + - + - - - + + + - - + + + + + + + + + + + +
@@ -186,6 +196,16 @@

100.00%

80 81 82 +83 +84 +85 +86 +87 +88 +89 +90 +91 +92
 module List = Core.List
@@ -206,12 +226,22 @@ 

100.00%

let id value = value let is_hash text = - Str.string_match regexp text 0 && String.length text = _HASH_LENGTH + Str.string_match regexp text 0 && String.length text = _HASH_LENGTH + +let _int_to_cstruct number = Cstruct.of_string @@ string_of_int number + +let _hash_both ~digest prefix suffix = + Cstruct.append prefix suffix |> Cstruct.to_bytes |> digest + +let generate_pieces ~digest random = + let blob = Cstruct.of_bytes random in + let nums = List.init _KEY_LENGTH ~f:_int_to_cstruct in + List.map nums ~f:(_hash_both ~digest blob) let validate_key list = - let filtered = List.filter list ~f:is_hash in - if List.length filtered = _KEY_LENGTH then Some list else None + let filtered = List.filter list ~f:is_hash in + if List.length filtered = _KEY_LENGTH then Some list else None let to_hex text = "0x" ^ text @@ -240,7 +270,7 @@

100.00%

|> List.reduce_exn ~f:( && ) -let concat_hashes left right = left ^ "-" ^ right +let concat_hashes left right = left ^ "-" ^ right let char_to_hex_int char = char |> Char.to_string |> to_hex |> Int.of_string @@ -262,18 +292,18 @@

100.00%

Cstruct.of_string (msg ^ zerofill) -let nonzero char = char != nullchar +let nonzero char = char != nullchar let unpad msg = String.filter ~f:nonzero msg -let bytes_of_string string = Cstruct.to_bytes @@ Cstruct.of_hex string +let bytes_of_string string = Cstruct.to_bytes @@ Cstruct.of_hex string let bytes_to_string bytes = - Hex.show @@ Hex.of_cstruct @@ Cstruct.of_bytes bytes + Hex.show @@ Hex.of_cstruct @@ Cstruct.of_bytes bytes
- + diff --git a/docs/coverage/lib/verification.ml.html b/docs/coverage/lib/verification.ml.html index 00a14b9..05eace6 100644 --- a/docs/coverage/lib/verification.ml.html +++ b/docs/coverage/lib/verification.ml.html @@ -84,7 +84,7 @@

100.00%

- + diff --git a/lib/hieroglyphs.ml b/lib/hieroglyphs.ml index f2f1336..50353dd 100644 --- a/lib/hieroglyphs.ml +++ b/lib/hieroglyphs.ml @@ -1,6 +1,6 @@ module Option = Core.Option -type priv = bytes list +type priv = bytes type pub = bytes list diff --git a/lib/keys.ml b/lib/keys.ml index 1b3ef29..72670e2 100644 --- a/lib/keys.ml +++ b/lib/keys.ml @@ -4,63 +4,30 @@ module Float = Core.Float module Int64 = Core.Int64 module Option = Core.Option -(* -let populate time _ = - () - |> Random.generate - |> Int64.to_string - |> String.( ^ ) time - |> Hash.digest - |> Hash.digest -*) - let length = Utils._KEY_LENGTH -(* -let timestamp () = () |> Unix.gettimeofday |> Float.to_string - -let generate () = - let time = timestamp () in - List.init length ~f:(populate time) -*) - -let _random_hex _ = Cstruct.of_bytes @@ Random.generate512 () - -let _int_to_cstruct number = Cstruct.of_string @@ string_of_int number +let generate () = Random.generate512 () -let _hash_both prefix suffix = - Cstruct.append prefix suffix |> Cstruct.to_bytes |> Hash.digest_bytes +let derive priv = + let pieces = Utils.generate_pieces ~digest:Hash.digest_bytes priv in + List.map pieces ~f:Hash.digest_bytes -let generate () = - let nums = List.init length ~f:_int_to_cstruct in - let rand = _random_hex () in - List.map nums ~f:(_hash_both rand) - - -let derive priv = List.map priv ~f:Hash.digest_bytes - let pair () = let priv = generate () in let pub = derive priv in (priv, pub) -let export ~priv ~pass = - priv - |> List.map ~f:Utils.bytes_to_string - |> List.reduce_exn ~f:Utils.concat_hashes - |> Encryption.encrypt ~pass +let export ~priv ~pass = Encryption.encrypt ~pass @@ Utils.bytes_to_string priv + +let validate_key plain = + if String.length plain == Utils._HASH_LENGTH then Some plain else None let import ~cipher ~pass = let open Option in - Encryption.decrypt ~pass cipher - >>= fun result -> - result - |> String.split ~on:'-' - |> Utils.validate_key - >>= fun list -> some @@ List.map list ~f:Utils.bytes_of_string + Encryption.decrypt ~pass cipher >>= validate_key >>| Utils.bytes_of_string let load = Serialization.load diff --git a/lib/signing.ml b/lib/signing.ml index e7ed1a1..39a99bd 100644 --- a/lib/signing.ml +++ b/lib/signing.ml @@ -1,6 +1,8 @@ module List = Core.List let sign ~priv ~msg = + (* yeah, I know that it's really bad smell code *) + let priv = Utils.generate_pieces ~digest:Hash.digest_bytes priv in let priv = List.map priv ~f:Utils.bytes_to_string in msg |> Utils.indexed_keys diff --git a/lib/signing.mli b/lib/signing.mli index b21f8cf..79b32d3 100644 --- a/lib/signing.mli +++ b/lib/signing.mli @@ -1 +1 @@ -val sign : priv:bytes list -> msg:string -> string +val sign : priv:bytes -> msg:string -> string diff --git a/lib/utils.ml b/lib/utils.ml index d3b4a14..e688e21 100644 --- a/lib/utils.ml +++ b/lib/utils.ml @@ -19,6 +19,18 @@ let is_hash text = Str.string_match regexp text 0 && String.length text = _HASH_LENGTH +let _int_to_cstruct number = Cstruct.of_string @@ string_of_int number + +let _hash_both ~digest prefix suffix = + Cstruct.append prefix suffix |> Cstruct.to_bytes |> digest + + +let generate_pieces ~digest random = + let blob = Cstruct.of_bytes random in + let nums = List.init _KEY_LENGTH ~f:_int_to_cstruct in + List.map nums ~f:(_hash_both ~digest blob) + + let validate_key list = let filtered = List.filter list ~f:is_hash in if List.length filtered = _KEY_LENGTH then Some list else None diff --git a/lib/utils.mli b/lib/utils.mli index 5ed0b53..2258416 100644 --- a/lib/utils.mli +++ b/lib/utils.mli @@ -8,6 +8,8 @@ val concat_hashes : string -> string -> string val validate_key : string list -> string list option +val generate_pieces : digest:(bytes -> bytes) -> bytes -> bytes list + val replace_index : matrix:string list -> int list -> string list val indexed_keys : string -> int list diff --git a/test/bench/bench.expected b/test/bench/bench.expected index 88f7e33..de8c9da 100644 --- a/test/bench/bench.expected +++ b/test/bench/bench.expected @@ -2,16 +2,16 @@ Estimated testing time 2m (12 benchmarks x 10s). Change using -quota SECS. ┌─────────────────────────────────────────────────────┬─────────────────┬─────────────┬─────────────┬────────────┬────────────┐ │ Name │ Time/Run │ mWd/Run │ mjWd/Run │ Prom/Run │ Percentage │ ├─────────────────────────────────────────────────────┼─────────────────┼─────────────┼─────────────┼────────────┼────────────┤ -│ hieroglyphs + blake2b ------ private key generation │ 6_952_726.97ns │ 275_068.02w │ 24_239.21w │ 24_239.21w │ 17.11% │ -│ hieroglyphs + blake2b ------ message signing │ 12_302_250.23ns │ 552_974.78w │ 160_031.31w │ 28_676.31w │ 30.28% │ -│ hieroglyphs + blake2b ------ public key derivation │ 3_167_539.72ns │ 190_464.87w │ 7_976.50w │ 7_976.50w │ 7.80% │ -│ hieroglyphs + blake2b ------ signature verification │ 18_234_267.33ns │ 865_711.50w │ 44_985.63w │ 44_985.63w │ 44.88% │ -│ rsa pss/sha256 1024 bits --- private key generation │ 40_629_482.92ns │ 870.95w │ -0.25w │ -0.25w │ 100.00% │ -│ rsa pss/sha256 1024 bits --- public key derivation │ 14.20ns │ 3.00w │ │ │ │ -│ rsa pss/sha256 1024 bits --- message signing │ 846_542.56ns │ 1_714.96w │ 0.59w │ 0.59w │ 2.08% │ -│ rsa pss/sha256 1024 bits --- signature verification │ 102_568.59ns │ 1_543.02w │ 0.34w │ 0.34w │ 0.25% │ -│ secp256k1 + sha256 hash ---- private key generation │ 19_958.41ns │ 355.77w │ │ │ 0.05% │ -│ secp256k1 + sha256 hash ---- public key derivation │ 261_015.99ns │ 13.00w │ │ │ 0.64% │ -│ secp256k1 + sha256 hash ---- message signing │ 407_385.47ns │ 230.00w │ │ │ 1.00% │ -│ secp256k1 + sha256 hash ---- signature verification │ 440_845.54ns │ 214.00w │ │ │ 1.09% │ +│ hieroglyphs + blake2b ------ private key generation │ 15_274.58ns │ 610.85w │ 0.12w │ 0.12w │ 0.04% │ +│ hieroglyphs + blake2b ------ message signing │ 19_095_133.16ns │ 827_432.56w │ 201_696.20w │ 70_341.20w │ 46.48% │ +│ hieroglyphs + blake2b ------ public key derivation │ 11_211_926.50ns │ 464_922.99w │ 41_060.12w │ 41_060.12w │ 27.29% │ +│ hieroglyphs + blake2b ------ signature verification │ 13_771_316.54ns │ 865_711.29w │ 44_975.73w │ 44_975.73w │ 33.52% │ +│ rsa pss/sha256 1024 bits --- private key generation │ 41_080_520.75ns │ 870.94w │ -0.25w │ -0.25w │ 100.00% │ +│ rsa pss/sha256 1024 bits --- public key derivation │ 11.44ns │ 3.00w │ │ │ │ +│ rsa pss/sha256 1024 bits --- message signing │ 821_579.08ns │ 1_714.97w │ 0.56w │ 0.56w │ 2.00% │ +│ rsa pss/sha256 1024 bits --- signature verification │ 89_740.97ns │ 1_547.02w │ 0.34w │ 0.34w │ 0.22% │ +│ secp256k1 + sha256 hash ---- private key generation │ 14_261.81ns │ 355.66w │ │ │ 0.03% │ +│ secp256k1 + sha256 hash ---- public key derivation │ 213_010.17ns │ 13.00w │ │ │ 0.52% │ +│ secp256k1 + sha256 hash ---- message signing │ 320_362.44ns │ 230.00w │ │ │ 0.78% │ +│ secp256k1 + sha256 hash ---- signature verification │ 380_186.52ns │ 214.00w │ │ │ 0.93% │ └─────────────────────────────────────────────────────┴─────────────────┴─────────────┴─────────────┴────────────┴────────────┘ From 9982fbd9f377ec01166c5ceb8c66bfbfeb0878e4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marco=20Aur=C3=A9lio=20da=20Silva?= Date: Sun, 10 Mar 2019 20:38:45 -0300 Subject: [PATCH 05/29] refactor: :recycle: short public key size at the expense of huge signature size MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Marco Aurélio da Silva --- .../hieroglyphs/Hieroglyphs__/Keys/index.html | 2 +- .../index.html | 2 +- .../hieroglyphs/Hieroglyphs__/Main/index.html | 2 + .../Hieroglyphs__/Serialization/index.html | 2 +- .../Hieroglyphs__/Signing/index.html | 2 +- .../Hieroglyphs__/Utils/index.html | 2 +- .../Hieroglyphs__/Verification/index.html | 2 +- .../hieroglyphs/Hieroglyphs__/index.html | 2 +- .../hieroglyphs/Hieroglyphs__Keys/index.html | 2 +- .../hieroglyphs/Hieroglyphs__Main/.dune-keep | 0 .../index.html | 2 +- .../hieroglyphs/Hieroglyphs__Main/index.html | 2 + .../Hieroglyphs__Serialization/index.html | 2 +- .../Hieroglyphs__Signing/index.html | 2 +- .../hieroglyphs/Hieroglyphs__Utils/index.html | 2 +- .../Hieroglyphs__Verification/index.html | 2 +- docs/coverage/index.html | 11 +- docs/coverage/lib/blacklist.ml.html | 8 +- docs/coverage/lib/encryption.ml.html | 2 +- docs/coverage/lib/hash.ml.html | 12 +- docs/coverage/lib/hieroglyphs.ml.html | 165 +------------- docs/coverage/lib/keys.ml.html | 82 +++---- docs/coverage/lib/main.ml.html | 204 ++++++++++++++++++ docs/coverage/lib/random.ml.html | 2 +- docs/coverage/lib/serialization.ml.html | 21 +- docs/coverage/lib/signing.ml.html | 42 +++- docs/coverage/lib/store.ml.html | 14 +- docs/coverage/lib/utils.ml.html | 114 +++++----- docs/coverage/lib/verification.ml.html | 57 ++++- lib/blacklist.ml | 2 +- lib/hieroglyphs.ml | 55 +---- lib/keys.ml | 21 +- lib/keys.mli | 17 ++ lib/main.ml | 58 +++++ lib/serialization.ml | 2 +- lib/serialization.mli | 4 +- lib/signing.ml | 21 +- lib/store.ml | 2 +- lib/utils.ml | 28 +-- lib/utils.mli | 4 +- lib/verification.ml | 22 +- lib/verification.mli | 2 +- test/bench/bench.expected | 24 +-- test/spec/keys.ml | 8 +- test/spec/sign.ml | 25 ++- 45 files changed, 599 insertions(+), 460 deletions(-) rename docs/apiref/hieroglyphs/Hieroglyphs__/{Keys/Bisect_visit___lib___keys___ml => Main/Bisect_visit___lib___main___ml}/index.html (67%) create mode 100644 docs/apiref/hieroglyphs/Hieroglyphs__/Main/index.html create mode 100644 docs/apiref/hieroglyphs/Hieroglyphs__Main/.dune-keep rename docs/apiref/hieroglyphs/{Hieroglyphs__Keys/Bisect_visit___lib___keys___ml => Hieroglyphs__Main/Bisect_visit___lib___main___ml}/index.html (66%) create mode 100644 docs/apiref/hieroglyphs/Hieroglyphs__Main/index.html create mode 100644 docs/coverage/lib/main.ml.html create mode 100644 lib/keys.mli create mode 100644 lib/main.ml diff --git a/docs/apiref/hieroglyphs/Hieroglyphs__/Keys/index.html b/docs/apiref/hieroglyphs/Hieroglyphs__/Keys/index.html index 26ec051..8bf2ba7 100644 --- a/docs/apiref/hieroglyphs/Hieroglyphs__/Keys/index.html +++ b/docs/apiref/hieroglyphs/Hieroglyphs__/Keys/index.html @@ -1,2 +1,2 @@ -Keys (hieroglyphs.Hieroglyphs__.Keys)

Module Hieroglyphs__.Keys

module Bisect_visit___lib___keys___ml : sig ... end
module List = Core.List
module String = Core.String
module Float = Core.Float
module Int64 = Core.Int64
module Option = Core.Option
val length : int
val _random_hex : 'a -> Cstruct.t
val _int_to_cstruct : int -> Cstruct.t
val _hash_both : Cstruct.t -> Cstruct.t -> bytes
val generate : unit -> bytes List.t
val derive : bytes List.t -> bytes List.t
val pair : unit -> bytes List.t * bytes List.t
val export : priv:bytes List.t -> pass:string -> string
val import : cipher:string -> pass:string -> bytes List.t Option.t
val load : string -> bytes list option
val show : bytes list -> string
val address : bytes list -> string
val sign : priv:bytes list -> msg:string -> string
val verify : pub:bytes list -> msg:string -> signature:string -> bool
\ No newline at end of file +Keys (hieroglyphs.Hieroglyphs__.Keys)

Module Hieroglyphs__.Keys

val sign : priv:bytes -> msg:string -> string
val verify : pub:bytes -> msg:string -> signature:string -> bool
val show : bytes -> string
val load : string -> bytes option
val import : cipher:string -> pass:string -> bytes option
val export : priv:bytes -> pass:string -> string
val generate : unit -> bytes
val derive : bytes -> bytes
val address : bytes -> string
\ No newline at end of file diff --git a/docs/apiref/hieroglyphs/Hieroglyphs__/Keys/Bisect_visit___lib___keys___ml/index.html b/docs/apiref/hieroglyphs/Hieroglyphs__/Main/Bisect_visit___lib___main___ml/index.html similarity index 67% rename from docs/apiref/hieroglyphs/Hieroglyphs__/Keys/Bisect_visit___lib___keys___ml/index.html rename to docs/apiref/hieroglyphs/Hieroglyphs__/Main/Bisect_visit___lib___main___ml/index.html index 392a120..5e59f21 100644 --- a/docs/apiref/hieroglyphs/Hieroglyphs__/Keys/Bisect_visit___lib___keys___ml/index.html +++ b/docs/apiref/hieroglyphs/Hieroglyphs__/Main/Bisect_visit___lib___main___ml/index.html @@ -1,2 +1,2 @@ -Bisect_visit___lib___keys___ml (hieroglyphs.Hieroglyphs__.Keys.Bisect_visit___lib___keys___ml)

Module Keys.Bisect_visit___lib___keys___ml

val ___bisect_visit___ : int -> unit
\ No newline at end of file +Bisect_visit___lib___main___ml (hieroglyphs.Hieroglyphs__.Main.Bisect_visit___lib___main___ml)

Module Main.Bisect_visit___lib___main___ml

val ___bisect_visit___ : int -> unit
\ No newline at end of file diff --git a/docs/apiref/hieroglyphs/Hieroglyphs__/Main/index.html b/docs/apiref/hieroglyphs/Hieroglyphs__/Main/index.html new file mode 100644 index 0000000..bbd6247 --- /dev/null +++ b/docs/apiref/hieroglyphs/Hieroglyphs__/Main/index.html @@ -0,0 +1,2 @@ + +Main (hieroglyphs.Hieroglyphs__.Main)

Module Hieroglyphs__.Main

module Bisect_visit___lib___main___ml : sig ... end
module Option = Core.Option
type priv = bytes
type pub = bytes
val derive : bytes -> bytes
val import : cipher:string -> pass:string -> bytes option
val export : priv:bytes -> pass:string -> string
val show : bytes -> string
val load : string -> bytes option
val address : bytes -> string
val sign : priv:bytes -> msg:string -> string
val verify : pub:bytes -> msg:string -> signature:string -> bool
val __check : bytes -> bytes option
val sign : priv:bytes -> msg:string -> string Option.t
val import : cipher:string -> pass:string -> bytes Option.t
val generate : unit -> bytes
val pair : unit -> bytes * bytes
\ No newline at end of file diff --git a/docs/apiref/hieroglyphs/Hieroglyphs__/Serialization/index.html b/docs/apiref/hieroglyphs/Hieroglyphs__/Serialization/index.html index 190a0ef..67034d2 100644 --- a/docs/apiref/hieroglyphs/Hieroglyphs__/Serialization/index.html +++ b/docs/apiref/hieroglyphs/Hieroglyphs__/Serialization/index.html @@ -1,2 +1,2 @@ -Serialization (hieroglyphs.Hieroglyphs__.Serialization)

Module Hieroglyphs__.Serialization

val address : bytes list -> string
val show : bytes list -> string
val load : string -> bytes list option
\ No newline at end of file +Serialization (hieroglyphs.Hieroglyphs__.Serialization)

Module Hieroglyphs__.Serialization

val show : bytes list -> string
val load : string -> bytes list option
val digest : bytes list -> string
\ No newline at end of file diff --git a/docs/apiref/hieroglyphs/Hieroglyphs__/Signing/index.html b/docs/apiref/hieroglyphs/Hieroglyphs__/Signing/index.html index b54c9dc..ecaedc1 100644 --- a/docs/apiref/hieroglyphs/Hieroglyphs__/Signing/index.html +++ b/docs/apiref/hieroglyphs/Hieroglyphs__/Signing/index.html @@ -1,2 +1,2 @@ -Signing (hieroglyphs.Hieroglyphs__.Signing)

Module Hieroglyphs__.Signing

val sign : priv:bytes list -> msg:string -> string
\ No newline at end of file +Signing (hieroglyphs.Hieroglyphs__.Signing)

Module Hieroglyphs__.Signing

val sign : priv:bytes -> msg:string -> string
\ No newline at end of file diff --git a/docs/apiref/hieroglyphs/Hieroglyphs__/Utils/index.html b/docs/apiref/hieroglyphs/Hieroglyphs__/Utils/index.html index 8371d9d..76f026e 100644 --- a/docs/apiref/hieroglyphs/Hieroglyphs__/Utils/index.html +++ b/docs/apiref/hieroglyphs/Hieroglyphs__/Utils/index.html @@ -1,2 +1,2 @@ -Utils (hieroglyphs.Hieroglyphs__.Utils)

Module Hieroglyphs__.Utils

val _HASH_LENGTH : int
val _KEY_LENGTH : int
val to_hex : string -> string
val concat_hashes : string -> string -> string
val validate_key : string list -> string list option
val replace_index : matrix:string list -> int list -> string list
val indexed_keys : string -> int list
val verify_with : matrix:string list -> digest:(string -> string) -> (int * string) list -> bool
val pad : basis:int -> string -> Cstruct.t
val unpad : string -> string
val bytes_of_string : string -> bytes
val bytes_to_string : bytes -> string
\ No newline at end of file +Utils (hieroglyphs.Hieroglyphs__.Utils)

Module Hieroglyphs__.Utils

val _HASH_LENGTH : int
val _KEY_LENGTH : int
val is_hash : string -> bool
val to_hex : string -> string
val concat_hashes : string -> string -> string
val validate_key : string list -> string list option
val generate_pieces : digest:(bytes -> bytes) -> bytes -> bytes list
val replace_index : matrix:'a list -> int list -> 'a list
val indexed_keys : string -> int list
val verify_with : matrix:string list -> digest:(string -> string) -> (int * string) list -> bool
val pad : basis:int -> string -> Cstruct.t
val unpad : string -> string
val bytes_of_string : string -> bytes
val bytes_to_string : bytes -> string
\ No newline at end of file diff --git a/docs/apiref/hieroglyphs/Hieroglyphs__/Verification/index.html b/docs/apiref/hieroglyphs/Hieroglyphs__/Verification/index.html index dd035ba..33525ee 100644 --- a/docs/apiref/hieroglyphs/Hieroglyphs__/Verification/index.html +++ b/docs/apiref/hieroglyphs/Hieroglyphs__/Verification/index.html @@ -1,2 +1,2 @@ -Verification (hieroglyphs.Hieroglyphs__.Verification)

Module Hieroglyphs__.Verification

val verify : pub:bytes list -> msg:string -> signature:string -> bool
\ No newline at end of file +Verification (hieroglyphs.Hieroglyphs__.Verification)

Module Hieroglyphs__.Verification

val verify : pub:bytes -> msg:string -> signature:string -> bool
\ No newline at end of file diff --git a/docs/apiref/hieroglyphs/Hieroglyphs__/index.html b/docs/apiref/hieroglyphs/Hieroglyphs__/index.html index 08ca231..d8593a9 100644 --- a/docs/apiref/hieroglyphs/Hieroglyphs__/index.html +++ b/docs/apiref/hieroglyphs/Hieroglyphs__/index.html @@ -1,2 +1,2 @@ -Hieroglyphs__ (hieroglyphs.Hieroglyphs__)

Module Hieroglyphs__

module Blacklist : sig ... end
module Encryption : sig ... end
module Hash : sig ... end
module Hieroglyphs = Hieroglyphs
module Keys : sig ... end
module Random : sig ... end
module Serialization : sig ... end
module Signing : sig ... end
module Store : sig ... end
module Utils : sig ... end
module Verification : sig ... end
\ No newline at end of file +Hieroglyphs__ (hieroglyphs.Hieroglyphs__)

Module Hieroglyphs__

module Blacklist : sig ... end
module Encryption : sig ... end
module Hash : sig ... end
module Hieroglyphs = Hieroglyphs
module Keys : sig ... end
module Main : sig ... end
module Random : sig ... end
module Serialization : sig ... end
module Signing : sig ... end
module Store : sig ... end
module Utils : sig ... end
module Verification : sig ... end
\ No newline at end of file diff --git a/docs/apiref/hieroglyphs/Hieroglyphs__Keys/index.html b/docs/apiref/hieroglyphs/Hieroglyphs__Keys/index.html index 8f2cb46..4691108 100644 --- a/docs/apiref/hieroglyphs/Hieroglyphs__Keys/index.html +++ b/docs/apiref/hieroglyphs/Hieroglyphs__Keys/index.html @@ -1,2 +1,2 @@ -Hieroglyphs__Keys (hieroglyphs.Hieroglyphs__Keys)

Module Hieroglyphs__Keys

module Bisect_visit___lib___keys___ml : sig ... end
module List = Core.List
module String = Core.String
module Float = Core.Float
module Int64 = Core.Int64
module Option = Core.Option
val length : int
val _random_hex : 'a -> Cstruct.t
val _int_to_cstruct : int -> Cstruct.t
val _hash_both : Cstruct.t -> Cstruct.t -> bytes
val generate : unit -> bytes List.t
val derive : bytes List.t -> bytes List.t
val pair : unit -> bytes List.t * bytes List.t
val export : priv:bytes List.t -> pass:string -> string
val import : cipher:string -> pass:string -> bytes List.t Option.t
val load : string -> bytes list option
val show : bytes list -> string
val address : bytes list -> string
val sign : priv:bytes list -> msg:string -> string
val verify : pub:bytes list -> msg:string -> signature:string -> bool
\ No newline at end of file +Hieroglyphs__Keys (hieroglyphs.Hieroglyphs__Keys)

Module Hieroglyphs__Keys

val sign : priv:bytes -> msg:string -> string
val verify : pub:bytes -> msg:string -> signature:string -> bool
val show : bytes -> string
val load : string -> bytes option
val import : cipher:string -> pass:string -> bytes option
val export : priv:bytes -> pass:string -> string
val generate : unit -> bytes
val derive : bytes -> bytes
val address : bytes -> string
\ No newline at end of file diff --git a/docs/apiref/hieroglyphs/Hieroglyphs__Main/.dune-keep b/docs/apiref/hieroglyphs/Hieroglyphs__Main/.dune-keep new file mode 100644 index 0000000..e69de29 diff --git a/docs/apiref/hieroglyphs/Hieroglyphs__Keys/Bisect_visit___lib___keys___ml/index.html b/docs/apiref/hieroglyphs/Hieroglyphs__Main/Bisect_visit___lib___main___ml/index.html similarity index 66% rename from docs/apiref/hieroglyphs/Hieroglyphs__Keys/Bisect_visit___lib___keys___ml/index.html rename to docs/apiref/hieroglyphs/Hieroglyphs__Main/Bisect_visit___lib___main___ml/index.html index 35acb61..c814b82 100644 --- a/docs/apiref/hieroglyphs/Hieroglyphs__Keys/Bisect_visit___lib___keys___ml/index.html +++ b/docs/apiref/hieroglyphs/Hieroglyphs__Main/Bisect_visit___lib___main___ml/index.html @@ -1,2 +1,2 @@ -Bisect_visit___lib___keys___ml (hieroglyphs.Hieroglyphs__Keys.Bisect_visit___lib___keys___ml)

Module Hieroglyphs__Keys.Bisect_visit___lib___keys___ml

val ___bisect_visit___ : int -> unit
\ No newline at end of file +Bisect_visit___lib___main___ml (hieroglyphs.Hieroglyphs__Main.Bisect_visit___lib___main___ml)

Module Hieroglyphs__Main.Bisect_visit___lib___main___ml

val ___bisect_visit___ : int -> unit
\ No newline at end of file diff --git a/docs/apiref/hieroglyphs/Hieroglyphs__Main/index.html b/docs/apiref/hieroglyphs/Hieroglyphs__Main/index.html new file mode 100644 index 0000000..255c778 --- /dev/null +++ b/docs/apiref/hieroglyphs/Hieroglyphs__Main/index.html @@ -0,0 +1,2 @@ + +Hieroglyphs__Main (hieroglyphs.Hieroglyphs__Main)

Module Hieroglyphs__Main

module Bisect_visit___lib___main___ml : sig ... end
module Option = Core.Option
type priv = bytes
type pub = bytes
val derive : bytes -> bytes
val import : cipher:string -> pass:string -> bytes option
val export : priv:bytes -> pass:string -> string
val show : bytes -> string
val load : string -> bytes option
val address : bytes -> string
val sign : priv:bytes -> msg:string -> string
val verify : pub:bytes -> msg:string -> signature:string -> bool
val __check : bytes -> bytes option
val sign : priv:bytes -> msg:string -> string Option.t
val import : cipher:string -> pass:string -> bytes Option.t
val generate : unit -> bytes
val pair : unit -> bytes * bytes
\ No newline at end of file diff --git a/docs/apiref/hieroglyphs/Hieroglyphs__Serialization/index.html b/docs/apiref/hieroglyphs/Hieroglyphs__Serialization/index.html index 809e6b8..7802caa 100644 --- a/docs/apiref/hieroglyphs/Hieroglyphs__Serialization/index.html +++ b/docs/apiref/hieroglyphs/Hieroglyphs__Serialization/index.html @@ -1,2 +1,2 @@ -Hieroglyphs__Serialization (hieroglyphs.Hieroglyphs__Serialization)

Module Hieroglyphs__Serialization

val address : bytes list -> string
val show : bytes list -> string
val load : string -> bytes list option
\ No newline at end of file +Hieroglyphs__Serialization (hieroglyphs.Hieroglyphs__Serialization)

Module Hieroglyphs__Serialization

val show : bytes list -> string
val load : string -> bytes list option
val digest : bytes list -> string
\ No newline at end of file diff --git a/docs/apiref/hieroglyphs/Hieroglyphs__Signing/index.html b/docs/apiref/hieroglyphs/Hieroglyphs__Signing/index.html index 4b70946..91827f7 100644 --- a/docs/apiref/hieroglyphs/Hieroglyphs__Signing/index.html +++ b/docs/apiref/hieroglyphs/Hieroglyphs__Signing/index.html @@ -1,2 +1,2 @@ -Hieroglyphs__Signing (hieroglyphs.Hieroglyphs__Signing)

Module Hieroglyphs__Signing

val sign : priv:bytes list -> msg:string -> string
\ No newline at end of file +Hieroglyphs__Signing (hieroglyphs.Hieroglyphs__Signing)

Module Hieroglyphs__Signing

val sign : priv:bytes -> msg:string -> string
\ No newline at end of file diff --git a/docs/apiref/hieroglyphs/Hieroglyphs__Utils/index.html b/docs/apiref/hieroglyphs/Hieroglyphs__Utils/index.html index 810c334..a0f31c8 100644 --- a/docs/apiref/hieroglyphs/Hieroglyphs__Utils/index.html +++ b/docs/apiref/hieroglyphs/Hieroglyphs__Utils/index.html @@ -1,2 +1,2 @@ -Hieroglyphs__Utils (hieroglyphs.Hieroglyphs__Utils)

Module Hieroglyphs__Utils

val _HASH_LENGTH : int
val _KEY_LENGTH : int
val to_hex : string -> string
val concat_hashes : string -> string -> string
val validate_key : string list -> string list option
val replace_index : matrix:string list -> int list -> string list
val indexed_keys : string -> int list
val verify_with : matrix:string list -> digest:(string -> string) -> (int * string) list -> bool
val pad : basis:int -> string -> Cstruct.t
val unpad : string -> string
val bytes_of_string : string -> bytes
val bytes_to_string : bytes -> string
\ No newline at end of file +Hieroglyphs__Utils (hieroglyphs.Hieroglyphs__Utils)

Module Hieroglyphs__Utils

val _HASH_LENGTH : int
val _KEY_LENGTH : int
val is_hash : string -> bool
val to_hex : string -> string
val concat_hashes : string -> string -> string
val validate_key : string list -> string list option
val generate_pieces : digest:(bytes -> bytes) -> bytes -> bytes list
val replace_index : matrix:'a list -> int list -> 'a list
val indexed_keys : string -> int list
val verify_with : matrix:string list -> digest:(string -> string) -> (int * string) list -> bool
val pad : basis:int -> string -> Cstruct.t
val unpad : string -> string
val bytes_of_string : string -> bytes
val bytes_to_string : bytes -> string
\ No newline at end of file diff --git a/docs/apiref/hieroglyphs/Hieroglyphs__Verification/index.html b/docs/apiref/hieroglyphs/Hieroglyphs__Verification/index.html index b7d903d..cca00da 100644 --- a/docs/apiref/hieroglyphs/Hieroglyphs__Verification/index.html +++ b/docs/apiref/hieroglyphs/Hieroglyphs__Verification/index.html @@ -1,2 +1,2 @@ -Hieroglyphs__Verification (hieroglyphs.Hieroglyphs__Verification)

Module Hieroglyphs__Verification

val verify : pub:bytes list -> msg:string -> signature:string -> bool
\ No newline at end of file +Hieroglyphs__Verification (hieroglyphs.Hieroglyphs__Verification)

Module Hieroglyphs__Verification

val verify : pub:bytes -> msg:string -> signature:string -> bool
\ No newline at end of file diff --git a/docs/coverage/index.html b/docs/coverage/index.html index 1febb60..984be32 100644 --- a/docs/coverage/index.html +++ b/docs/coverage/index.html @@ -55,6 +55,15 @@

100.00%

lib/keys.ml +
+ + + + 100% + + lib/main.ml + +
@@ -110,6 +119,6 @@

100.00%

- + diff --git a/docs/coverage/lib/blacklist.ml.html b/docs/coverage/lib/blacklist.ml.html index fce5595..358a211 100644 --- a/docs/coverage/lib/blacklist.ml.html +++ b/docs/coverage/lib/blacklist.ml.html @@ -44,17 +44,17 @@

100.00%

 let add address =
   let key = "blacklist/" ^ address in
-  let msg = "Revoking private key ID " ^ address ^ "." in
+  let msg = "Revoking private key for public key " ^ address ^ "." in
   Store.set ~msg ~key ""
 
 
 let exists address =
-  let key = "blacklist/" ^ address in
-  match Store.get ~key with None -> false | Some _ -> true
+  let key = "blacklist/" ^ address in
+  match Store.get ~key with None -> false | Some _ -> true
 
- + diff --git a/docs/coverage/lib/encryption.ml.html b/docs/coverage/lib/encryption.ml.html index 4570cb2..f4e4a09 100644 --- a/docs/coverage/lib/encryption.ml.html +++ b/docs/coverage/lib/encryption.ml.html @@ -78,7 +78,7 @@

100.00%

- + diff --git a/docs/coverage/lib/hash.ml.html b/docs/coverage/lib/hash.ml.html index 4398e80..3f36f56 100644 --- a/docs/coverage/lib/hash.ml.html +++ b/docs/coverage/lib/hash.ml.html @@ -87,14 +87,14 @@

100.00%

module Bytes = Core.Bytes let digest text = - text |> Digestif.BLAKE2B.digest_string |> Digestif.BLAKE2B.to_hex + text |> Digestif.BLAKE2B.digest_string |> Digestif.BLAKE2B.to_hex let digest_bytes bytes = - bytes - |> Digestif.BLAKE2B.digest_bytes - |> Digestif.BLAKE2B.to_raw_string - |> Bytes.of_string + bytes + |> Digestif.BLAKE2B.digest_bytes + |> Digestif.BLAKE2B.to_raw_string + |> Bytes.of_string let __digest message = Nocrypto.Hash.SHA256.digest message @@ -117,7 +117,7 @@

100.00%

- + diff --git a/docs/coverage/lib/hieroglyphs.ml.html b/docs/coverage/lib/hieroglyphs.ml.html index 079456b..bfe8c5a 100644 --- a/docs/coverage/lib/hieroglyphs.ml.html +++ b/docs/coverage/lib/hieroglyphs.ml.html @@ -19,177 +19,18 @@

100.00%

  
- 
- 
- 
- 
- 
- 
- 
- 
- 
- 
- 
- 
- 
- 
- 
- 
- 
- 
- 
- 
- 
- 
- 
- 
- 
- 
- 
- 
- 
- 
- 
- 
- 
- 
- 
- 
- 
- 
- 
- 
- 
- 
- 
- 
- 
- 
- 
- 
- 
- 
- 
- 
- 
 
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
-10
-11
-12
-13
-14
-15
-16
-17
-18
-19
-20
-21
-22
-23
-24
-25
-26
-27
-28
-29
-30
-31
-32
-33
-34
-35
-36
-37
-38
-39
-40
-41
-42
-43
-44
-45
-46
-47
-48
-49
-50
-51
-52
-53
-54
+1
 
-module Option = Core.Option
-
-type priv = bytes
-
-type pub = bytes list
-
-let derive = Keys.derive
-
-let pair = Keys.pair
-
-let import = Keys.import
-
-let export = Keys.export
-
-let show = Keys.show
-
-let load = Keys.load
-
-let address = Keys.address
-
-let sign = Keys.sign
-
-let verify = Keys.verify
-
-(*** wrappers *****************************************************************)
-
-let __check priv =
-  let pub = derive priv in
-  let id = address pub in
-  if Blacklist.exists id then None else Some pub
-
-
-let sign ~priv ~msg =
-  let success pub =
-    let signature = sign ~priv ~msg in
-    Blacklist.add (address pub) ;
-    Some signature
-  in
-  let open Option in
-  __check priv >>= success
-
-
-let import ~cipher ~pass =
-  let open Option in
-  import ~cipher ~pass
-  >>= function priv -> __check priv >>= (function _ -> Some priv)
-
-
-let rec generate () =
-  let priv = Keys.generate () in
-  let const _ _ = priv in
-  let option = __check priv in
-  let step = Option.value_map option ~default:generate ~f:const in
-  step ()
+include Main
 
- + diff --git a/docs/coverage/lib/keys.ml.html b/docs/coverage/lib/keys.ml.html index c01fb04..63f1d92 100644 --- a/docs/coverage/lib/keys.ml.html +++ b/docs/coverage/lib/keys.ml.html @@ -28,41 +28,35 @@

100.00%

- + - + - - - + + + - - + + - - + + - - - + + + - + - + - - - - - -
@@ -106,12 +100,6 @@

100.00%

37 38 39 -40 -41 -42 -43 -44 -45
 module List = Core.List
@@ -120,49 +108,43 @@ 

100.00%

module Int64 = Core.Int64 module Option = Core.Option -let length = Utils._KEY_LENGTH +let generate () = Random.generate512 () -let generate () = - Random.generate512() +let genpub priv = + let pieces = Utils.generate_pieces ~digest:Hash.digest_bytes priv in + List.map pieces ~f:Hash.digest_bytes let derive priv = - let pieces = Utils.generate_pieces ~digest:Hash.digest_bytes priv in - List.map pieces ~f:Hash.digest_bytes + Utils.bytes_of_string @@ Serialization.digest @@ genpub priv -let pair () = - let priv = generate () in - let pub = derive priv in - (priv, pub) - -let export ~priv ~pass = - Encryption.encrypt ~pass @@ Utils.bytes_to_string priv +let export ~priv ~pass = Encryption.encrypt ~pass @@ Utils.bytes_to_string priv let validate_key plain = - if String.length plain == Utils._HASH_LENGTH then - Some plain - else None + if String.length plain == Utils._HASH_LENGTH then Some plain else None + let import ~cipher ~pass = let open Option in - Encryption.decrypt ~pass cipher - >>= validate_key - >>| Utils.bytes_of_string - + Encryption.decrypt ~pass cipher >>= validate_key >>| Utils.bytes_of_string -let load = Serialization.load -let show = Serialization.show - -let address = Serialization.address +let address pub = Utils.to_hex @@ Utils.bytes_to_string pub let sign = Signing.sign let verify = Verification.verify + +let show = Utils.bytes_to_string + +let load dump = + if Utils.is_hash dump then + Some (Utils.bytes_of_string dump) + else None
- + diff --git a/docs/coverage/lib/main.ml.html b/docs/coverage/lib/main.ml.html new file mode 100644 index 0000000..90dd6db --- /dev/null +++ b/docs/coverage/lib/main.ml.html @@ -0,0 +1,204 @@ + + + Coverage report + + + + + + +
+
+
+ 
+ 
+ 
+ 
+ 
+ 
+ 
+ 
+ 
+ 
+ 
+ 
+ 
+ 
+ 
+ 
+ 
+ 
+ 
+ 
+ 
+ 
+ 
+ 
+ 
+ 
+ 
+ 
+ 
+ 
+ 
+ 
+ 
+ 
+ 
+ 
+ 
+ 
+ 
+ 
+ 
+ 
+ 
+ 
+ 
+ 
+ 
+ 
+ 
+ 
+ 
+ 
+ 
+ 
+ 
+ 
+ 
+
+
+
+
+ 1
+ 2
+ 3
+ 4
+ 5
+ 6
+ 7
+ 8
+ 9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+20
+21
+22
+23
+24
+25
+26
+27
+28
+29
+30
+31
+32
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
+45
+46
+47
+48
+49
+50
+51
+52
+53
+54
+55
+56
+57
+
+
+module Option = Core.Option
+
+type priv = bytes
+
+type pub = bytes
+
+let derive = Keys.derive
+
+let import = Keys.import
+
+let export = Keys.export
+
+let show = Keys.show
+
+let load = Keys.load
+
+let address = Keys.address
+
+let sign = Keys.sign
+
+let verify = Keys.verify
+
+(*** wrappers *****************************************************************)
+
+let __check priv =
+  let pub = derive priv in
+  let id = "0x" ^ Utils.bytes_to_string pub in
+  if Blacklist.exists id then None else Some pub
+
+
+let sign ~priv ~msg =
+  let success pub =
+    let signature = sign ~priv ~msg in
+    Blacklist.add @@ "0x" ^ Utils.bytes_to_string pub ;
+    Some signature
+  in
+  let open Option in
+  __check priv >>= success
+
+
+let import ~cipher ~pass =
+  let open Option in
+  import ~cipher ~pass
+  >>= function priv -> __check priv >>= (function _ -> Some priv)
+
+
+let rec generate () =
+  let priv = Keys.generate () in
+  let const _ _ = priv in
+  let option = __check priv in
+  let step = Option.value_map option ~default:generate ~f:const in
+  step ()
+
+let pair () =
+  let priv = generate () in
+  let pub = derive priv in
+  (priv, pub)
+
+
+
+ + + + diff --git a/docs/coverage/lib/random.ml.html b/docs/coverage/lib/random.ml.html index 2fd5536..7aa20bc 100644 --- a/docs/coverage/lib/random.ml.html +++ b/docs/coverage/lib/random.ml.html @@ -69,7 +69,7 @@

100.00%

- + diff --git a/docs/coverage/lib/serialization.ml.html b/docs/coverage/lib/serialization.ml.html index ae57223..0330a36 100644 --- a/docs/coverage/lib/serialization.ml.html +++ b/docs/coverage/lib/serialization.ml.html @@ -34,8 +34,7 @@

100.00%

- - +
@@ -57,7 +56,6 @@

100.00%

15 16 17 -18
 module List = Core.List
@@ -65,23 +63,22 @@ 

100.00%

module Option = Core.Option let show pub = - pub - |> List.map ~f:Utils.bytes_to_string - |> List.reduce_exn ~f:Utils.concat_hashes + pub + |> List.map ~f:Utils.bytes_to_string + |> List.reduce_exn ~f:Utils.concat_hashes let load text = - let list = String.split text ~on:'-' in - let open Option in + let list = String.split text ~on:'-' in + let open Option in Utils.validate_key list - >>= fun list -> some @@ List.map ~f:Utils.bytes_of_string list + >>= fun list -> some @@ List.map ~f:Utils.bytes_of_string list - -let address pub = pub |> show |> Hash.digest |> Utils.to_hex +let digest pub = pub |> show |> Hash.digest
- + diff --git a/docs/coverage/lib/signing.ml.html b/docs/coverage/lib/signing.ml.html index fa163cc..be8bb00 100644 --- a/docs/coverage/lib/signing.ml.html +++ b/docs/coverage/lib/signing.ml.html @@ -21,13 +21,21 @@

100.00%

- - - - + + + + + + + + + + + +
@@ -42,22 +50,38 @@

100.00%

8 9 10 +11 +12 +13 +14 +15 +16 +17 +18
 module List = Core.List
 
+let digest_to_string bytes =
+  Utils.bytes_to_string @@ Hash.digest_bytes bytes
+
 let sign ~priv ~msg =
   (* yeah, I know that it's really bad smell code *)
-  let priv = Utils.generate_pieces ~digest:Hash.digest_bytes priv in
-  let priv = List.map priv ~f:Utils.bytes_to_string in
-  msg
+  let priv' = Utils.generate_pieces ~digest:Hash.digest_bytes priv in
+  let ver_key = List.map priv' ~f:digest_to_string
+  |> List.reduce_exn ~f:Utils.concat_hashes
+  in
+  let ver_text = msg
   |> Utils.indexed_keys
-  |> Utils.replace_index ~matrix:priv
+  |> Utils.replace_index ~matrix:priv'
+  |> List.map ~f:Utils.bytes_to_string
   |> List.reduce_exn ~f:Utils.concat_hashes
+  in
+  ver_text ^ "\n" ^ ver_key
 
- + diff --git a/docs/coverage/lib/store.ml.html b/docs/coverage/lib/store.ml.html index f352ae1..63de9fb 100644 --- a/docs/coverage/lib/store.ml.html +++ b/docs/coverage/lib/store.ml.html @@ -175,20 +175,20 @@

100.00%

let get ~key = - let path = String.split ~on:'/' key in - let transaction () = - GitStore.Repo.v config + let path = String.split ~on:'/' key in + let transaction () = + GitStore.Repo.v config >>= fun repo -> - GitStore.master repo >>= fun branch -> GitStore.get branch path + GitStore.master repo >>= fun branch -> GitStore.get branch path in - try Some (Lwt_main.run (transaction ())) with Invalid_argument _ -> None + try Some (Lwt_main.run (transaction ())) with Invalid_argument _ -> None let boot () = let date = 946684800L (* Sat Jan 1 00:00:00 2000 +0000 *) in let address = "0x" ^ String.make Utils._HASH_LENGTH '0' in let path = ["blacklist"; address] in - let msg = "Revoking private key ID " ^ address ^ "." in + let msg = "Revoking private key for public key " ^ address ^ "." in let info = Core.const (Irmin.Info.v ~date ~author msg) in let transaction () = GitStore.Repo.v config @@ -204,7 +204,7 @@

100.00%

- + diff --git a/docs/coverage/lib/utils.ml.html b/docs/coverage/lib/utils.ml.html index 8da7d74..9d895b0 100644 --- a/docs/coverage/lib/utils.ml.html +++ b/docs/coverage/lib/utils.ml.html @@ -33,15 +33,15 @@

100.00%

- - + + - - - + + + - - + + @@ -58,29 +58,29 @@

100.00%

- + - - + + - + - + - + - - - - - + + + + + @@ -89,27 +89,25 @@

100.00%

- - - + + + - - - + + + - - - + + + - - - - + +
@@ -204,8 +202,6 @@

100.00%

88 89 90 -91 -92
 module List = Core.List
@@ -223,33 +219,28 @@ 

100.00%

let regexp = Str.regexp "^[a-f0-9]+$" -let id value = value - let is_hash text = - Str.string_match regexp text 0 && String.length text = _HASH_LENGTH + Str.string_match regexp text 0 && String.length text = _HASH_LENGTH + -let _int_to_cstruct number = Cstruct.of_string @@ string_of_int number +let _int_to_cstruct number = Cstruct.of_string @@ string_of_int number let _hash_both ~digest prefix suffix = - Cstruct.append prefix suffix |> Cstruct.to_bytes |> digest + Cstruct.append prefix suffix |> Cstruct.to_bytes |> digest + let generate_pieces ~digest random = - let blob = Cstruct.of_bytes random in - let nums = List.init _KEY_LENGTH ~f:_int_to_cstruct in - List.map nums ~f:(_hash_both ~digest blob) + let blob = Cstruct.of_bytes random in + let nums = List.init _KEY_LENGTH ~f:_int_to_cstruct in + List.map nums ~f:(_hash_both ~digest blob) let validate_key list = - let filtered = List.filter list ~f:is_hash in - if List.length filtered = _KEY_LENGTH then Some list else None + let filtered = List.filter list ~f:is_hash in + if List.length filtered = _KEY_LENGTH then Some list else None -let to_hex text = "0x" ^ text - -let tag_index entries = - let length = List.length entries in - let indexes = List.init length ~f:id in - List.zip_exn indexes entries +let to_hex text = "0x" ^ text let calculate_index (position, key) = (position * _HEX_SPACE) + key @@ -258,10 +249,10 @@

100.00%

let replace_index ~matrix pairs = pairs |> List.map ~f:(index_at ~list:matrix) -let verify_at ~digest ~list (position, hash) = +let verify_at ~digest ~list (position, opening) = let commitment = List.nth_exn list position in - let opening = digest hash in - opening = commitment + let hash = digest opening in + hash = commitment let verify_with ~matrix ~digest pairs = @@ -270,17 +261,20 @@

100.00%

|> List.reduce_exn ~f:( && ) -let concat_hashes left right = left ^ "-" ^ right +let concat_hashes left right = left ^ "-" ^ right + +let char_to_hex_int index char = + let value = char |> Char.to_string |> to_hex |> Int.of_string in + (index, value) -let char_to_hex_int char = char |> Char.to_string |> to_hex |> Int.of_string +let chained_index index value = + calculate_index @@ char_to_hex_int index value let indexed_keys msg = msg |> Hash.digest |> String.to_list - |> List.map ~f:char_to_hex_int - |> tag_index - |> List.map ~f:calculate_index + |> List.mapi ~f:chained_index let nullchar = Char.of_int_exn 0 @@ -296,14 +290,14 @@

100.00%

let unpad msg = String.filter ~f:nonzero msg -let bytes_of_string string = Cstruct.to_bytes @@ Cstruct.of_hex string +let bytes_of_string string = Cstruct.to_bytes @@ Cstruct.of_hex string let bytes_to_string bytes = - Hex.show @@ Hex.of_cstruct @@ Cstruct.of_bytes bytes + Hex.show @@ Hex.of_cstruct @@ Cstruct.of_bytes bytes
- + diff --git a/docs/coverage/lib/verification.ml.html b/docs/coverage/lib/verification.ml.html index 05eace6..b4592a8 100644 --- a/docs/coverage/lib/verification.ml.html +++ b/docs/coverage/lib/verification.ml.html @@ -22,21 +22,34 @@

100.00%

- + - + - + + + + + + + + + + + + + +
@@ -60,10 +73,24 @@

100.00%

17 18 19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32
 module String = Core.String
 module List = Core.List
+module Option = Core.Option
 
 let digest message =
   message
@@ -76,15 +103,27 @@ 

100.00%

let verify ~pub ~msg ~signature = - let pub = List.map ~f:Utils.bytes_to_string pub in - let indexed_keys = Utils.indexed_keys msg in - let hashes = String.split signature ~on:'-' in - let proofs = List.zip_exn indexed_keys hashes in - Utils.verify_with ~matrix:pub ~digest proofs + try + let parts = String.split signature ~on:'\n' in + let ver_text = List.nth_exn parts 0 + |> String.split ~on:'-' + in + let ver_key_bytes = Option.value_exn ( + Serialization.load @@ List.nth_exn parts 1 + ) in + let ver_key = List.map ~f:Utils.bytes_to_string ver_key_bytes in + let indexed_keys = Utils.indexed_keys msg in + let proofs = List.zip_exn indexed_keys ver_text in + let verified = Utils.verify_with ~matrix:ver_key ~digest proofs in + if verified then + let fingerprint = Serialization.digest ver_key_bytes in + fingerprint = Utils.bytes_to_string pub + else false + with _ -> false
- + diff --git a/lib/blacklist.ml b/lib/blacklist.ml index 06ac25c..50aacd7 100644 --- a/lib/blacklist.ml +++ b/lib/blacklist.ml @@ -1,6 +1,6 @@ let add address = let key = "blacklist/" ^ address in - let msg = "Revoking private key ID " ^ address ^ "." in + let msg = "Revoking private key for public key " ^ address ^ "." in Store.set ~msg ~key "" diff --git a/lib/hieroglyphs.ml b/lib/hieroglyphs.ml index 50353dd..1e27a74 100644 --- a/lib/hieroglyphs.ml +++ b/lib/hieroglyphs.ml @@ -1,54 +1 @@ -module Option = Core.Option - -type priv = bytes - -type pub = bytes list - -let derive = Keys.derive - -let pair = Keys.pair - -let import = Keys.import - -let export = Keys.export - -let show = Keys.show - -let load = Keys.load - -let address = Keys.address - -let sign = Keys.sign - -let verify = Keys.verify - -(*** wrappers *****************************************************************) - -let __check priv = - let pub = derive priv in - let id = address pub in - if Blacklist.exists id then None else Some pub - - -let sign ~priv ~msg = - let success pub = - let signature = sign ~priv ~msg in - Blacklist.add (address pub) ; - Some signature - in - let open Option in - __check priv >>= success - - -let import ~cipher ~pass = - let open Option in - import ~cipher ~pass - >>= function priv -> __check priv >>= (function _ -> Some priv) - - -let rec generate () = - let priv = Keys.generate () in - let const _ _ = priv in - let option = __check priv in - let step = Option.value_map option ~default:generate ~f:const in - step () +include Main diff --git a/lib/keys.ml b/lib/keys.ml index 72670e2..33063cb 100644 --- a/lib/keys.ml +++ b/lib/keys.ml @@ -4,20 +4,14 @@ module Float = Core.Float module Int64 = Core.Int64 module Option = Core.Option -let length = Utils._KEY_LENGTH - let generate () = Random.generate512 () -let derive priv = +let genpub priv = let pieces = Utils.generate_pieces ~digest:Hash.digest_bytes priv in List.map pieces ~f:Hash.digest_bytes -let pair () = - let priv = generate () in - let pub = derive priv in - (priv, pub) - +let derive priv = Utils.bytes_of_string @@ Serialization.digest @@ genpub priv let export ~priv ~pass = Encryption.encrypt ~pass @@ Utils.bytes_to_string priv @@ -30,12 +24,13 @@ let import ~cipher ~pass = Encryption.decrypt ~pass cipher >>= validate_key >>| Utils.bytes_of_string -let load = Serialization.load - -let show = Serialization.show - -let address = Serialization.address +let address pub = Utils.to_hex @@ Utils.bytes_to_string pub let sign = Signing.sign let verify = Verification.verify + +let show = Utils.bytes_to_string + +let load dump = + if Utils.is_hash dump then Some (Utils.bytes_of_string dump) else None diff --git a/lib/keys.mli b/lib/keys.mli new file mode 100644 index 0000000..2f9a025 --- /dev/null +++ b/lib/keys.mli @@ -0,0 +1,17 @@ +val sign : priv:bytes -> msg:string -> string + +val verify : pub:bytes -> msg:string -> signature:string -> bool + +val show : bytes -> string + +val load : string -> bytes option + +val import : cipher:string -> pass:string -> bytes option + +val export : priv:bytes -> pass:string -> string + +val generate : unit -> bytes + +val derive : bytes -> bytes + +val address : bytes -> string diff --git a/lib/main.ml b/lib/main.ml new file mode 100644 index 0000000..3844223 --- /dev/null +++ b/lib/main.ml @@ -0,0 +1,58 @@ +module Option = Core.Option + +type priv = bytes + +type pub = bytes + +let derive = Keys.derive + +let import = Keys.import + +let export = Keys.export + +let show = Keys.show + +let load = Keys.load + +let address = Keys.address + +let sign = Keys.sign + +let verify = Keys.verify + +(*** wrappers *****************************************************************) + +let __check priv = + let pub = derive priv in + let id = "0x" ^ Utils.bytes_to_string pub in + if Blacklist.exists id then None else Some pub + + +let sign ~priv ~msg = + let success pub = + let signature = sign ~priv ~msg in + Blacklist.add @@ "0x" ^ Utils.bytes_to_string pub ; + Some signature + in + let open Option in + __check priv >>= success + + +let import ~cipher ~pass = + let open Option in + import ~cipher ~pass + >>= function priv -> __check priv >>= (function _ -> Some priv) + + +let rec generate () = + let priv = Keys.generate () in + let const _ _ = priv in + let option = __check priv in + let step = Option.value_map option ~default:generate ~f:const in + step () + + +let pair () = + let priv = generate () in + let pub = derive priv in + (priv, pub) diff --git a/lib/serialization.ml b/lib/serialization.ml index e99d828..b7f407a 100644 --- a/lib/serialization.ml +++ b/lib/serialization.ml @@ -15,4 +15,4 @@ let load text = >>= fun list -> some @@ List.map ~f:Utils.bytes_of_string list -let address pub = pub |> show |> Hash.digest |> Utils.to_hex +let digest pub = pub |> show |> Hash.digest diff --git a/lib/serialization.mli b/lib/serialization.mli index 469b6c3..7ccb2f4 100644 --- a/lib/serialization.mli +++ b/lib/serialization.mli @@ -1,5 +1,5 @@ -val address : bytes list -> string - val show : bytes list -> string val load : string -> bytes list option + +val digest : bytes list -> string diff --git a/lib/signing.ml b/lib/signing.ml index 39a99bd..17fb8b1 100644 --- a/lib/signing.ml +++ b/lib/signing.ml @@ -1,10 +1,19 @@ module List = Core.List +let digest_to_string bytes = Utils.bytes_to_string @@ Hash.digest_bytes bytes + let sign ~priv ~msg = (* yeah, I know that it's really bad smell code *) - let priv = Utils.generate_pieces ~digest:Hash.digest_bytes priv in - let priv = List.map priv ~f:Utils.bytes_to_string in - msg - |> Utils.indexed_keys - |> Utils.replace_index ~matrix:priv - |> List.reduce_exn ~f:Utils.concat_hashes + let priv' = Utils.generate_pieces ~digest:Hash.digest_bytes priv in + let ver_key = + List.map priv' ~f:digest_to_string + |> List.reduce_exn ~f:Utils.concat_hashes + in + let ver_text = + msg + |> Utils.indexed_keys + |> Utils.replace_index ~matrix:priv' + |> List.map ~f:Utils.bytes_to_string + |> List.reduce_exn ~f:Utils.concat_hashes + in + ver_text ^ "\n" ^ ver_key diff --git a/lib/store.ml b/lib/store.ml index c34c142..c18e7a7 100644 --- a/lib/store.ml +++ b/lib/store.ml @@ -44,7 +44,7 @@ let boot () = let date = 946684800L (* Sat Jan 1 00:00:00 2000 +0000 *) in let address = "0x" ^ String.make Utils._HASH_LENGTH '0' in let path = ["blacklist"; address] in - let msg = "Revoking private key ID " ^ address ^ "." in + let msg = "Revoking private key for public key " ^ address ^ "." in let info = Core.const (Irmin.Info.v ~date ~author msg) in let transaction () = GitStore.Repo.v config diff --git a/lib/utils.ml b/lib/utils.ml index e688e21..56a5ece 100644 --- a/lib/utils.ml +++ b/lib/utils.ml @@ -13,8 +13,6 @@ let _KEY_LENGTH = _HEX_SPACE * _HASH_LENGTH let regexp = Str.regexp "^[a-f0-9]+$" -let id value = value - let is_hash text = Str.string_match regexp text 0 && String.length text = _HASH_LENGTH @@ -38,22 +36,16 @@ let validate_key list = let to_hex text = "0x" ^ text -let tag_index entries = - let length = List.length entries in - let indexes = List.init length ~f:id in - List.zip_exn indexes entries - - let calculate_index (position, key) = (position * _HEX_SPACE) + key let index_at ~list position = List.nth_exn list position let replace_index ~matrix pairs = pairs |> List.map ~f:(index_at ~list:matrix) -let verify_at ~digest ~list (position, hash) = +let verify_at ~digest ~list (position, opening) = let commitment = List.nth_exn list position in - let opening = digest hash in - opening = commitment + let hash = digest opening in + hash = commitment let verify_with ~matrix ~digest pairs = @@ -64,15 +56,15 @@ let verify_with ~matrix ~digest pairs = let concat_hashes left right = left ^ "-" ^ right -let char_to_hex_int char = char |> Char.to_string |> to_hex |> Int.of_string +let char_to_hex_int index char = + let value = char |> Char.to_string |> to_hex |> Int.of_string in + (index, value) + + +let chained_index index value = calculate_index @@ char_to_hex_int index value let indexed_keys msg = - msg - |> Hash.digest - |> String.to_list - |> List.map ~f:char_to_hex_int - |> tag_index - |> List.map ~f:calculate_index + msg |> Hash.digest |> String.to_list |> List.mapi ~f:chained_index let nullchar = Char.of_int_exn 0 diff --git a/lib/utils.mli b/lib/utils.mli index 2258416..48e14f8 100644 --- a/lib/utils.mli +++ b/lib/utils.mli @@ -2,6 +2,8 @@ val _HASH_LENGTH : int val _KEY_LENGTH : int +val is_hash : string -> bool + val to_hex : string -> string val concat_hashes : string -> string -> string @@ -10,7 +12,7 @@ val validate_key : string list -> string list option val generate_pieces : digest:(bytes -> bytes) -> bytes -> bytes list -val replace_index : matrix:string list -> int list -> string list +val replace_index : matrix:'a list -> int list -> 'a list val indexed_keys : string -> int list diff --git a/lib/verification.ml b/lib/verification.ml index c6f7de3..38833e4 100644 --- a/lib/verification.ml +++ b/lib/verification.ml @@ -1,5 +1,6 @@ module String = Core.String module List = Core.List +module Option = Core.Option let digest message = message @@ -12,8 +13,19 @@ let digest message = let verify ~pub ~msg ~signature = - let pub = List.map ~f:Utils.bytes_to_string pub in - let indexed_keys = Utils.indexed_keys msg in - let hashes = String.split signature ~on:'-' in - let proofs = List.zip_exn indexed_keys hashes in - Utils.verify_with ~matrix:pub ~digest proofs + try + let parts = String.split signature ~on:'\n' in + let ver_text = List.nth_exn parts 0 |> String.split ~on:'-' in + let ver_key_bytes = + Option.value_exn (Serialization.load @@ List.nth_exn parts 1) + in + let ver_key = List.map ~f:Utils.bytes_to_string ver_key_bytes in + let indexed_keys = Utils.indexed_keys msg in + let proofs = List.zip_exn indexed_keys ver_text in + let verified = Utils.verify_with ~matrix:ver_key ~digest proofs in + if verified + then + let fingerprint = Serialization.digest ver_key_bytes in + fingerprint = Utils.bytes_to_string pub + else false + with _ -> false diff --git a/lib/verification.mli b/lib/verification.mli index d2e4629..9c8f232 100644 --- a/lib/verification.mli +++ b/lib/verification.mli @@ -1 +1 @@ -val verify : pub:bytes list -> msg:string -> signature:string -> bool +val verify : pub:bytes -> msg:string -> signature:string -> bool diff --git a/test/bench/bench.expected b/test/bench/bench.expected index de8c9da..3be2b92 100644 --- a/test/bench/bench.expected +++ b/test/bench/bench.expected @@ -2,16 +2,16 @@ Estimated testing time 2m (12 benchmarks x 10s). Change using -quota SECS. ┌─────────────────────────────────────────────────────┬─────────────────┬─────────────┬─────────────┬────────────┬────────────┐ │ Name │ Time/Run │ mWd/Run │ mjWd/Run │ Prom/Run │ Percentage │ ├─────────────────────────────────────────────────────┼─────────────────┼─────────────┼─────────────┼────────────┼────────────┤ -│ hieroglyphs + blake2b ------ private key generation │ 15_274.58ns │ 610.85w │ 0.12w │ 0.12w │ 0.04% │ -│ hieroglyphs + blake2b ------ message signing │ 19_095_133.16ns │ 827_432.56w │ 201_696.20w │ 70_341.20w │ 46.48% │ -│ hieroglyphs + blake2b ------ public key derivation │ 11_211_926.50ns │ 464_922.99w │ 41_060.12w │ 41_060.12w │ 27.29% │ -│ hieroglyphs + blake2b ------ signature verification │ 13_771_316.54ns │ 865_711.29w │ 44_975.73w │ 44_975.73w │ 33.52% │ -│ rsa pss/sha256 1024 bits --- private key generation │ 41_080_520.75ns │ 870.94w │ -0.25w │ -0.25w │ 100.00% │ -│ rsa pss/sha256 1024 bits --- public key derivation │ 11.44ns │ 3.00w │ │ │ │ -│ rsa pss/sha256 1024 bits --- message signing │ 821_579.08ns │ 1_714.97w │ 0.56w │ 0.56w │ 2.00% │ -│ rsa pss/sha256 1024 bits --- signature verification │ 89_740.97ns │ 1_547.02w │ 0.34w │ 0.34w │ 0.22% │ -│ secp256k1 + sha256 hash ---- private key generation │ 14_261.81ns │ 355.66w │ │ │ 0.03% │ -│ secp256k1 + sha256 hash ---- public key derivation │ 213_010.17ns │ 13.00w │ │ │ 0.52% │ -│ secp256k1 + sha256 hash ---- message signing │ 320_362.44ns │ 230.00w │ │ │ 0.78% │ -│ secp256k1 + sha256 hash ---- signature verification │ 380_186.52ns │ 214.00w │ │ │ 0.93% │ +│ hieroglyphs + blake2b ------ private key generation │ 14_478.23ns │ 610.86w │ 0.13w │ 0.13w │ 0.04% │ +│ hieroglyphs + blake2b ------ message signing │ 17_191_378.34ns │ 827_432.53w │ 202_018.20w │ 70_663.20w │ 47.19% │ +│ hieroglyphs + blake2b ------ public key derivation │ 10_744_165.74ns │ 464_922.96w │ 40_998.95w │ 40_998.95w │ 29.50% │ +│ hieroglyphs + blake2b ------ signature verification │ 14_133_862.03ns │ 865_711.40w │ 44_959.17w │ 44_959.17w │ 38.80% │ +│ rsa pss/sha256 1024 bits --- private key generation │ 36_426_323.11ns │ 870.85w │ -0.23w │ -0.23w │ 100.00% │ +│ rsa pss/sha256 1024 bits --- public key derivation │ 11.51ns │ 3.00w │ │ │ │ +│ rsa pss/sha256 1024 bits --- message signing │ 876_060.34ns │ 1_715.16w │ 0.57w │ 0.57w │ 2.41% │ +│ rsa pss/sha256 1024 bits --- signature verification │ 96_039.80ns │ 1_547.02w │ 0.35w │ 0.35w │ 0.26% │ +│ secp256k1 + sha256 hash ---- private key generation │ 12_305.12ns │ 355.74w │ │ │ 0.03% │ +│ secp256k1 + sha256 hash ---- public key derivation │ 215_967.91ns │ 13.00w │ │ │ 0.59% │ +│ secp256k1 + sha256 hash ---- message signing │ 351_285.84ns │ 230.00w │ │ │ 0.96% │ +│ secp256k1 + sha256 hash ---- signature verification │ 397_957.75ns │ 214.00w │ │ │ 1.09% │ └─────────────────────────────────────────────────────┴─────────────────┴─────────────┴─────────────┴────────────┴────────────┘ diff --git a/test/spec/keys.ml b/test/spec/keys.ml index c06f2c7..ba90e50 100644 --- a/test/spec/keys.ml +++ b/test/spec/keys.ml @@ -5,13 +5,7 @@ module List = Core.List let __public_key_validation () = let _, pub = Hg.pair () in let result = Hg.show pub in - let chunks = String.split ~on:'-' result in - let filtered = List.filter ~f:Utils.is_hash chunks in - Alcotest.(check int) "valid public key size" (List.length chunks) (128 * 16) ; - Alcotest.(check int) - "valid chunks in public key" - (List.length filtered) - (128 * 16) + Alcotest.(check bool) "valid public key hash" true @@ Utils.is_hash result let __public_key_derivation () = diff --git a/test/spec/sign.ml b/test/spec/sign.ml index 8cd0587..22dd50f 100644 --- a/test/spec/sign.ml +++ b/test/spec/sign.ml @@ -15,10 +15,23 @@ let __signature_validation () = let msg = "Yadda yadda yadda" in let priv = Hg.generate () in let signature = sign ~priv ~msg in - let chunks = String.split ~on:'-' signature in + let parts = String.split ~on:'\n' signature in + let vertext = List.nth_exn parts 0 in + let verkey = List.nth_exn parts 1 in + let chunks = String.split ~on:'-' vertext in let filtered = List.filter ~f:Utils.is_hash chunks in Alcotest.(check int) "valid signature size" (List.length chunks) 128 ; - Alcotest.(check int) "valid chunks in signature" (List.length filtered) 128 + Alcotest.(check int) "valid chunks in signature" (List.length filtered) 128 ; + let chunks = String.split ~on:'-' verkey in + let filtered = List.filter ~f:Utils.is_hash chunks in + Alcotest.(check int) + "valid verification key size" + (List.length chunks) + (128 * 16) ; + Alcotest.(check int) + "valid chunks in verification key" + (List.length filtered) + (128 * 16) let __signing_and_verification () = @@ -28,12 +41,14 @@ let __signing_and_verification () = let priv2, pub2 = Hg.pair () in let sign1 = sign ~priv:priv1 ~msg:msg1 in let sign2 = sign ~priv:priv2 ~msg:msg2 in + let invalid = "This is an invalid signature...\ndeadbeefdeadbeef" in let resultA = Hg.verify ~pub:pub1 ~signature:sign1 ~msg:msg1 in let resultB = Hg.verify ~pub:pub2 ~signature:sign2 ~msg:msg2 in let resultC = Hg.verify ~pub:pub2 ~signature:sign1 ~msg:msg1 in let resultD = Hg.verify ~pub:pub1 ~signature:sign2 ~msg:msg2 in let resultE = Hg.verify ~pub:pub2 ~signature:sign2 ~msg:msg1 in let resultF = Hg.verify ~pub:pub1 ~signature:sign1 ~msg:msg2 in + let resultG = Hg.verify ~pub:pub2 ~signature:invalid ~msg:msg2 in Alcotest.(check bool) "verification for public key 1, signature 1 and message 1 pass" true @@ -57,7 +72,11 @@ let __signing_and_verification () = Alcotest.(check bool) "verification for public key 1, signature 1 and message 2 fail" false - resultF + resultF ; + Alcotest.(check bool) + "verification for public key 2, invalid signature and message 2 fail" + false + resultG let __one_time_signing () = From 6efc8b02356d1a755f2d53d33a9f6e8a8db2273f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marco=20Aur=C3=A9lio=20da=20Silva?= Date: Sat, 16 Mar 2019 22:40:29 -0300 Subject: [PATCH 06/29] refactor: :recycle: :closed_lock_with_key: :eyes: dropping AES ECB by AES CBC for private key encryption MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Marco Aurélio da Silva --- README.md | 2 +- docs/coverage/index.html | 2 +- docs/coverage/lib/blacklist.ml.html | 2 +- docs/coverage/lib/encryption.ml.html | 55 +++++++++++++---- docs/coverage/lib/hash.ml.html | 2 +- docs/coverage/lib/hieroglyphs.ml.html | 2 +- docs/coverage/lib/keys.ml.html | 45 ++++++-------- docs/coverage/lib/main.ml.html | 7 ++- docs/coverage/lib/random.ml.html | 2 +- docs/coverage/lib/serialization.ml.html | 7 ++- docs/coverage/lib/signing.ml.html | 33 ++++++----- docs/coverage/lib/store.ml.html | 2 +- docs/coverage/lib/utils.ml.html | 78 +++++++++++-------------- docs/coverage/lib/verification.ml.html | 25 ++++---- docs/index.md | 2 +- lib/encryption.ml | 21 +++++-- test/bench/bench.expected | 34 ++++++----- 17 files changed, 176 insertions(+), 145 deletions(-) diff --git a/README.md b/README.md index ec5a606..5341e8f 100644 --- a/README.md +++ b/README.md @@ -24,7 +24,7 @@ For further information, see: This library uses the Blake2B hash algorithm, but further / additional hashes are planned as well. Currently, the following things are implemented now: -- [x] Importing/exporting encrypted private key (by now using AES ECB). +- [x] Importing/exporting encrypted private key (by now using AES CBC). - [x] Public Key serialization+validation (to share and receive such key for verification). - [x] Built-in one-time invariant protected by a blacklist of used private keys. - [x] Tests covering the things here and there. diff --git a/docs/coverage/index.html b/docs/coverage/index.html index 984be32..a516972 100644 --- a/docs/coverage/index.html +++ b/docs/coverage/index.html @@ -119,6 +119,6 @@

100.00%

- + diff --git a/docs/coverage/lib/blacklist.ml.html b/docs/coverage/lib/blacklist.ml.html index 358a211..40f3918 100644 --- a/docs/coverage/lib/blacklist.ml.html +++ b/docs/coverage/lib/blacklist.ml.html @@ -54,7 +54,7 @@

100.00%

- + diff --git a/docs/coverage/lib/encryption.ml.html b/docs/coverage/lib/encryption.ml.html index f4e4a09..f936018 100644 --- a/docs/coverage/lib/encryption.ml.html +++ b/docs/coverage/lib/encryption.ml.html @@ -25,16 +25,27 @@

100.00%

- - + + - + - - + + + + + + + + + + + + +
@@ -56,29 +67,51 @@

100.00%

15 16 17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28
-open Nocrypto.Cipher_block.AES.ECB
+open Nocrypto.Cipher_block.AES.CBC
 module Option = Core.Option
 module Base64 = Nocrypto.Base64
 
+let digest cstruct =
+  let digest = Nocrypto.Hash.SHA256.digest cstruct in
+  let left, right = Cstruct.split digest 16 in
+  (* split 32 bytes into a pair of 16 *)
+  Nocrypto.Uncommon.Cs.xor left right
+
+
 let encrypt msg ~pass =
-  let key = of_secret (Hash.mine pass ~difficulty:5) in
-  let result = encrypt ~key (Utils.pad ~basis:16 msg) in
+  let proof = Hash.mine pass ~difficulty:5 in
+  let key = of_secret proof in
+  let iv = digest proof in
+  let result = encrypt ~iv ~key (Utils.pad ~basis:16 msg) in
   result |> Base64.encode |> Cstruct.to_string
 
 
 let decrypt cipher ~pass =
-  let key = of_secret (Hash.mine pass ~difficulty:5) in
+  let proof = Hash.mine pass ~difficulty:5 in
+  let key = of_secret proof in
+  let iv = digest proof in
   let result = cipher |> Cstruct.of_string |> Base64.decode in
   let open Option in
   result
   >>= fun msg ->
-  msg |> decrypt ~key |> Cstruct.to_string |> Utils.unpad |> some
+  msg |> decrypt ~iv ~key |> Cstruct.to_string |> Utils.unpad |> some
 
- + diff --git a/docs/coverage/lib/hash.ml.html b/docs/coverage/lib/hash.ml.html index 3f36f56..3ec6439 100644 --- a/docs/coverage/lib/hash.ml.html +++ b/docs/coverage/lib/hash.ml.html @@ -117,7 +117,7 @@

100.00%

- + diff --git a/docs/coverage/lib/hieroglyphs.ml.html b/docs/coverage/lib/hieroglyphs.ml.html index bfe8c5a..2f91eeb 100644 --- a/docs/coverage/lib/hieroglyphs.ml.html +++ b/docs/coverage/lib/hieroglyphs.ml.html @@ -30,7 +30,7 @@

100.00%

- + diff --git a/docs/coverage/lib/keys.ml.html b/docs/coverage/lib/keys.ml.html index 63f1d92..6e0c70c 100644 --- a/docs/coverage/lib/keys.ml.html +++ b/docs/coverage/lib/keys.ml.html @@ -33,30 +33,27 @@

100.00%

- - + + - - + + - - + + - - - - - - - - + + + + + + + + - - - - +
@@ -97,9 +94,6 @@

100.00%

34 35 36 -37 -38 -39
 module List = Core.List
@@ -114,9 +108,8 @@ 

100.00%

let pieces = Utils.generate_pieces ~digest:Hash.digest_bytes priv in List.map pieces ~f:Hash.digest_bytes -let derive priv = - Utils.bytes_of_string @@ Serialization.digest @@ genpub priv +let derive priv = Utils.bytes_of_string @@ Serialization.digest @@ genpub priv let export ~priv ~pass = Encryption.encrypt ~pass @@ Utils.bytes_to_string priv @@ -138,13 +131,11 @@

100.00%

let show = Utils.bytes_to_string let load dump = - if Utils.is_hash dump then - Some (Utils.bytes_of_string dump) - else None + if Utils.is_hash dump then Some (Utils.bytes_of_string dump) else None
- + diff --git a/docs/coverage/lib/main.ml.html b/docs/coverage/lib/main.ml.html index 90dd6db..6dc1d1d 100644 --- a/docs/coverage/lib/main.ml.html +++ b/docs/coverage/lib/main.ml.html @@ -72,9 +72,10 @@

100.00%

- + +
@@ -136,6 +137,7 @@

100.00%

55 56 57 +58
 module Option = Core.Option
@@ -191,6 +193,7 @@ 

100.00%

let step = Option.value_map option ~default:generate ~f:const in step () + let pair () = let priv = generate () in let pub = derive priv in @@ -198,7 +201,7 @@

100.00%

- + diff --git a/docs/coverage/lib/random.ml.html b/docs/coverage/lib/random.ml.html index 7aa20bc..1a2133a 100644 --- a/docs/coverage/lib/random.ml.html +++ b/docs/coverage/lib/random.ml.html @@ -69,7 +69,7 @@

100.00%

- + diff --git a/docs/coverage/lib/serialization.ml.html b/docs/coverage/lib/serialization.ml.html index 0330a36..76594e1 100644 --- a/docs/coverage/lib/serialization.ml.html +++ b/docs/coverage/lib/serialization.ml.html @@ -34,7 +34,8 @@

100.00%

- + +
@@ -56,6 +57,7 @@

100.00%

15 16 17 +18
 module List = Core.List
@@ -74,11 +76,12 @@ 

100.00%

Utils.validate_key list >>= fun list -> some @@ List.map ~f:Utils.bytes_of_string list + let digest pub = pub |> show |> Hash.digest
- + diff --git a/docs/coverage/lib/signing.ml.html b/docs/coverage/lib/signing.ml.html index be8bb00..821506d 100644 --- a/docs/coverage/lib/signing.ml.html +++ b/docs/coverage/lib/signing.ml.html @@ -20,11 +20,11 @@

100.00%

  
  
- 
- 
+ 
+ 
  
  
- 
+ 
  
  
  
@@ -34,8 +34,9 @@ 

100.00%

- - + + +
@@ -58,30 +59,32 @@

100.00%

16 17 18 +19
 module List = Core.List
 
-let digest_to_string bytes =
-  Utils.bytes_to_string @@ Hash.digest_bytes bytes
+let digest_to_string bytes = Utils.bytes_to_string @@ Hash.digest_bytes bytes
 
 let sign ~priv ~msg =
   (* yeah, I know that it's really bad smell code *)
   let priv' = Utils.generate_pieces ~digest:Hash.digest_bytes priv in
-  let ver_key = List.map priv' ~f:digest_to_string
-  |> List.reduce_exn ~f:Utils.concat_hashes
+  let ver_key =
+    List.map priv' ~f:digest_to_string
+    |> List.reduce_exn ~f:Utils.concat_hashes
   in
-  let ver_text = msg
-  |> Utils.indexed_keys
-  |> Utils.replace_index ~matrix:priv'
-  |> List.map ~f:Utils.bytes_to_string
-  |> List.reduce_exn ~f:Utils.concat_hashes
+  let ver_text =
+    msg
+    |> Utils.indexed_keys
+    |> Utils.replace_index ~matrix:priv'
+    |> List.map ~f:Utils.bytes_to_string
+    |> List.reduce_exn ~f:Utils.concat_hashes
   in
   ver_text ^ "\n" ^ ver_key
 
- + diff --git a/docs/coverage/lib/store.ml.html b/docs/coverage/lib/store.ml.html index 63de9fb..3d36005 100644 --- a/docs/coverage/lib/store.ml.html +++ b/docs/coverage/lib/store.ml.html @@ -204,7 +204,7 @@

100.00%

- + diff --git a/docs/coverage/lib/utils.ml.html b/docs/coverage/lib/utils.ml.html index 9d895b0..7cda548 100644 --- a/docs/coverage/lib/utils.ml.html +++ b/docs/coverage/lib/utils.ml.html @@ -56,58 +56,54 @@

100.00%

- - - - - - + + + + + + - + - + - + - + - - + + - + - + - - + + - - - + + + - + - + - - - - + + + + - - + + - - - - - - + +
@@ -198,10 +194,6 @@

100.00%

84 85 86 -87 -88 -89 -90
 module List = Core.List
@@ -242,7 +234,6 @@ 

100.00%

let to_hex text = "0x" ^ text - let calculate_index (position, key) = (position * _HEX_SPACE) + key let index_at ~list position = List.nth_exn list position @@ -267,14 +258,11 @@

100.00%

let value = char |> Char.to_string |> to_hex |> Int.of_string in (index, value) -let chained_index index value = - calculate_index @@ char_to_hex_int index value + +let chained_index index value = calculate_index @@ char_to_hex_int index value let indexed_keys msg = - msg - |> Hash.digest - |> String.to_list - |> List.mapi ~f:chained_index + msg |> Hash.digest |> String.to_list |> List.mapi ~f:chained_index let nullchar = Char.of_int_exn 0 @@ -297,7 +285,7 @@

100.00%

- + diff --git a/docs/coverage/lib/verification.ml.html b/docs/coverage/lib/verification.ml.html index b4592a8..91ecdd0 100644 --- a/docs/coverage/lib/verification.ml.html +++ b/docs/coverage/lib/verification.ml.html @@ -37,19 +37,18 @@

100.00%

- - - - + + + + - + -
@@ -85,7 +84,6 @@

100.00%

29 30 31 -32
 module String = Core.String
@@ -105,17 +103,16 @@ 

100.00%

let verify ~pub ~msg ~signature = try let parts = String.split signature ~on:'\n' in - let ver_text = List.nth_exn parts 0 - |> String.split ~on:'-' + let ver_text = List.nth_exn parts 0 |> String.split ~on:'-' in + let ver_key_bytes = + Option.value_exn (Serialization.load @@ List.nth_exn parts 1) in - let ver_key_bytes = Option.value_exn ( - Serialization.load @@ List.nth_exn parts 1 - ) in let ver_key = List.map ~f:Utils.bytes_to_string ver_key_bytes in let indexed_keys = Utils.indexed_keys msg in let proofs = List.zip_exn indexed_keys ver_text in let verified = Utils.verify_with ~matrix:ver_key ~digest proofs in - if verified then + if verified + then let fingerprint = Serialization.digest ver_key_bytes in fingerprint = Utils.bytes_to_string pub else false @@ -123,7 +120,7 @@

100.00%

- + diff --git a/docs/index.md b/docs/index.md index ec5a606..5341e8f 100644 --- a/docs/index.md +++ b/docs/index.md @@ -24,7 +24,7 @@ For further information, see: This library uses the Blake2B hash algorithm, but further / additional hashes are planned as well. Currently, the following things are implemented now: -- [x] Importing/exporting encrypted private key (by now using AES ECB). +- [x] Importing/exporting encrypted private key (by now using AES CBC). - [x] Public Key serialization+validation (to share and receive such key for verification). - [x] Built-in one-time invariant protected by a blacklist of used private keys. - [x] Tests covering the things here and there. diff --git a/lib/encryption.ml b/lib/encryption.ml index ce31456..3c04fe8 100644 --- a/lib/encryption.ml +++ b/lib/encryption.ml @@ -1,17 +1,28 @@ -open Nocrypto.Cipher_block.AES.ECB +open Nocrypto.Cipher_block.AES.CBC module Option = Core.Option module Base64 = Nocrypto.Base64 +let digest cstruct = + let digest = Nocrypto.Hash.SHA256.digest cstruct in + let left, right = Cstruct.split digest 16 in + (* split 32 bytes into a pair of 16 *) + Nocrypto.Uncommon.Cs.xor left right + + let encrypt msg ~pass = - let key = of_secret (Hash.mine pass ~difficulty:5) in - let result = encrypt ~key (Utils.pad ~basis:16 msg) in + let proof = Hash.mine pass ~difficulty:5 in + let key = of_secret proof in + let iv = digest proof in + let result = encrypt ~iv ~key (Utils.pad ~basis:16 msg) in result |> Base64.encode |> Cstruct.to_string let decrypt cipher ~pass = - let key = of_secret (Hash.mine pass ~difficulty:5) in + let proof = Hash.mine pass ~difficulty:5 in + let key = of_secret proof in + let iv = digest proof in let result = cipher |> Cstruct.of_string |> Base64.decode in let open Option in result >>= fun msg -> - msg |> decrypt ~key |> Cstruct.to_string |> Utils.unpad |> some + msg |> decrypt ~iv ~key |> Cstruct.to_string |> Utils.unpad |> some diff --git a/test/bench/bench.expected b/test/bench/bench.expected index 3be2b92..2890e80 100644 --- a/test/bench/bench.expected +++ b/test/bench/bench.expected @@ -1,17 +1,19 @@ Estimated testing time 2m (12 benchmarks x 10s). Change using -quota SECS. -┌─────────────────────────────────────────────────────┬─────────────────┬─────────────┬─────────────┬────────────┬────────────┐ -│ Name │ Time/Run │ mWd/Run │ mjWd/Run │ Prom/Run │ Percentage │ -├─────────────────────────────────────────────────────┼─────────────────┼─────────────┼─────────────┼────────────┼────────────┤ -│ hieroglyphs + blake2b ------ private key generation │ 14_478.23ns │ 610.86w │ 0.13w │ 0.13w │ 0.04% │ -│ hieroglyphs + blake2b ------ message signing │ 17_191_378.34ns │ 827_432.53w │ 202_018.20w │ 70_663.20w │ 47.19% │ -│ hieroglyphs + blake2b ------ public key derivation │ 10_744_165.74ns │ 464_922.96w │ 40_998.95w │ 40_998.95w │ 29.50% │ -│ hieroglyphs + blake2b ------ signature verification │ 14_133_862.03ns │ 865_711.40w │ 44_959.17w │ 44_959.17w │ 38.80% │ -│ rsa pss/sha256 1024 bits --- private key generation │ 36_426_323.11ns │ 870.85w │ -0.23w │ -0.23w │ 100.00% │ -│ rsa pss/sha256 1024 bits --- public key derivation │ 11.51ns │ 3.00w │ │ │ │ -│ rsa pss/sha256 1024 bits --- message signing │ 876_060.34ns │ 1_715.16w │ 0.57w │ 0.57w │ 2.41% │ -│ rsa pss/sha256 1024 bits --- signature verification │ 96_039.80ns │ 1_547.02w │ 0.35w │ 0.35w │ 0.26% │ -│ secp256k1 + sha256 hash ---- private key generation │ 12_305.12ns │ 355.74w │ │ │ 0.03% │ -│ secp256k1 + sha256 hash ---- public key derivation │ 215_967.91ns │ 13.00w │ │ │ 0.59% │ -│ secp256k1 + sha256 hash ---- message signing │ 351_285.84ns │ 230.00w │ │ │ 0.96% │ -│ secp256k1 + sha256 hash ---- signature verification │ 397_957.75ns │ 214.00w │ │ │ 1.09% │ -└─────────────────────────────────────────────────────┴─────────────────┴─────────────┴─────────────┴────────────┴────────────┘ +┌─────────────────────────────────────────────────────┬──────────────────┬───────────────┬────────────────┬─────────────┬────────────┐ +│ Name │ Time/Run │ mWd/Run │ mjWd/Run │ Prom/Run │ Percentage │ +├─────────────────────────────────────────────────────┼──────────────────┼───────────────┼────────────────┼─────────────┼────────────┤ +│ hieroglyphs + blake2b ------ private key generation │ 17_525.88ns │ 610.86w │ 0.13w │ 0.13w │ │ +│ hieroglyphs + blake2b ------ message signing │ 817_123_209.18ns │ 1_083_435.49w │ 34_105_687.00w │ 72_142.00w │ 100.00% │ +│ hieroglyphs + blake2b ------ public key derivation │ 725_470_742.16ns │ 1_050_688.71w │ 33_925_498.14w │ 91_423.14w │ 88.78% │ +│ hieroglyphs + blake2b ------ signature verification │ 784_232_620.65ns │ 5_855_944.94w │ 34_029_307.97w │ 160_142.97w │ 95.97% │ +│ rsa pss/sha256 1024 bits --- private key generation │ 37_672_015.30ns │ 870.67w │ -0.23w │ -0.23w │ 4.61% │ +│ rsa pss/sha256 1024 bits --- public key derivation │ 10.60ns │ 3.00w │ │ │ │ +│ rsa pss/sha256 1024 bits --- message signing │ 803_344.15ns │ 1_715.18w │ 0.59w │ 0.59w │ 0.10% │ +│ rsa pss/sha256 1024 bits --- signature verification │ 113_583.97ns │ 1_544.02w │ 0.34w │ 0.34w │ 0.01% │ +│ secp256k1 + sha256 hash ---- private key generation │ 12_656.23ns │ 355.66w │ │ │ │ +│ secp256k1 + sha256 hash ---- public key derivation │ 207_689.41ns │ 13.00w │ │ │ 0.03% │ +│ secp256k1 + sha256 hash ---- message signing │ 322_686.25ns │ 230.00w │ │ │ 0.04% │ +│ secp256k1 + sha256 hash ---- signature verification │ 385_461.70ns │ 214.00w │ │ │ 0.05% │ +└─────────────────────────────────────────────────────┴──────────────────┴───────────────┴────────────────┴─────────────┴────────────┘ +Benchmarks that take 1ns to 100ms can be estimated precisely. For more reliable +estimates, redesign your benchmark to have a shorter execution time. From d23fb9a46a1c29510b76e5e850571304a88e735c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marco=20Aur=C3=A9lio=20da=20Silva?= Date: Sun, 7 Apr 2019 22:15:40 -0300 Subject: [PATCH 07/29] :recycle: refactor: ongoing refactor process to add laziness in some points MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Marco Aurélio da Silva --- docs/coverage/index.html | 2 +- docs/coverage/lib/blacklist.ml.html | 2 +- docs/coverage/lib/encryption.ml.html | 2 +- docs/coverage/lib/hash.ml.html | 2 +- docs/coverage/lib/hieroglyphs.ml.html | 2 +- docs/coverage/lib/keys.ml.html | 47 +++++--- docs/coverage/lib/main.ml.html | 2 +- docs/coverage/lib/random.ml.html | 2 +- docs/coverage/lib/serialization.ml.html | 2 +- docs/coverage/lib/signing.ml.html | 18 +-- docs/coverage/lib/store.ml.html | 2 +- docs/coverage/lib/utils.ml.html | 146 +++++++++++++++--------- docs/coverage/lib/verification.ml.html | 34 ++++-- lib/keys.ml | 5 +- lib/signing.ml | 7 +- lib/utils.ml | 32 ++++-- lib/utils.mli | 12 +- lib/verification.ml | 5 +- test/bench/bench.expected | 24 ++-- 19 files changed, 214 insertions(+), 134 deletions(-) diff --git a/docs/coverage/index.html b/docs/coverage/index.html index a516972..e0d3d22 100644 --- a/docs/coverage/index.html +++ b/docs/coverage/index.html @@ -119,6 +119,6 @@

100.00%

- + diff --git a/docs/coverage/lib/blacklist.ml.html b/docs/coverage/lib/blacklist.ml.html index 40f3918..527a927 100644 --- a/docs/coverage/lib/blacklist.ml.html +++ b/docs/coverage/lib/blacklist.ml.html @@ -54,7 +54,7 @@

100.00%

- + diff --git a/docs/coverage/lib/encryption.ml.html b/docs/coverage/lib/encryption.ml.html index f936018..0e09dc6 100644 --- a/docs/coverage/lib/encryption.ml.html +++ b/docs/coverage/lib/encryption.ml.html @@ -111,7 +111,7 @@

100.00%

- + diff --git a/docs/coverage/lib/hash.ml.html b/docs/coverage/lib/hash.ml.html index 3ec6439..7b09d1e 100644 --- a/docs/coverage/lib/hash.ml.html +++ b/docs/coverage/lib/hash.ml.html @@ -117,7 +117,7 @@

100.00%

- + diff --git a/docs/coverage/lib/hieroglyphs.ml.html b/docs/coverage/lib/hieroglyphs.ml.html index 2f91eeb..b6a3a6c 100644 --- a/docs/coverage/lib/hieroglyphs.ml.html +++ b/docs/coverage/lib/hieroglyphs.ml.html @@ -30,7 +30,7 @@

100.00%

- + diff --git a/docs/coverage/lib/keys.ml.html b/docs/coverage/lib/keys.ml.html index 6e0c70c..2ae1d2d 100644 --- a/docs/coverage/lib/keys.ml.html +++ b/docs/coverage/lib/keys.ml.html @@ -24,36 +24,39 @@

100.00%

- - + + - + - - - + + + - - + + - - + + - - - - - - + + + + + + + + +
@@ -94,6 +97,9 @@

100.00%

34 35 36 +37 +38 +39
 module List = Core.List
@@ -101,13 +107,16 @@ 

100.00%

module Float = Core.Float module Int64 = Core.Int64 module Option = Core.Option +module Defer = Utils.Defer let generate () = Random.generate512 () +let __force_digest lazy_piece = + Hash.digest_bytes @@ Defer.force lazy_piece + let genpub priv = let pieces = Utils.generate_pieces ~digest:Hash.digest_bytes priv in - List.map pieces ~f:Hash.digest_bytes - + List.map pieces ~f:(__force_digest) let derive priv = Utils.bytes_of_string @@ Serialization.digest @@ genpub priv @@ -135,7 +144,7 @@

100.00%

- + diff --git a/docs/coverage/lib/main.ml.html b/docs/coverage/lib/main.ml.html index 6dc1d1d..8a6388b 100644 --- a/docs/coverage/lib/main.ml.html +++ b/docs/coverage/lib/main.ml.html @@ -201,7 +201,7 @@

100.00%

- + diff --git a/docs/coverage/lib/random.ml.html b/docs/coverage/lib/random.ml.html index 1a2133a..e089b26 100644 --- a/docs/coverage/lib/random.ml.html +++ b/docs/coverage/lib/random.ml.html @@ -69,7 +69,7 @@

100.00%

- + diff --git a/docs/coverage/lib/serialization.ml.html b/docs/coverage/lib/serialization.ml.html index 76594e1..7f0c160 100644 --- a/docs/coverage/lib/serialization.ml.html +++ b/docs/coverage/lib/serialization.ml.html @@ -81,7 +81,7 @@

100.00%

- + diff --git a/docs/coverage/lib/signing.ml.html b/docs/coverage/lib/signing.ml.html index 821506d..a3edf4b 100644 --- a/docs/coverage/lib/signing.ml.html +++ b/docs/coverage/lib/signing.ml.html @@ -20,16 +20,16 @@

100.00%

  
  
- 
+ 
  
- 
+ 
  
- 
+ 
  
  
  
- 
- 
+ 
+ 
  
  
  
@@ -63,11 +63,12 @@ 

100.00%

 module List = Core.List
+module Defer = Utils.Defer
 
-let digest_to_string bytes = Utils.bytes_to_string @@ Hash.digest_bytes bytes
+let digest_to_string lazy_bytes =
+  Utils.bytes_to_string @@ Hash.digest_bytes @@ Defer.force lazy_bytes
 
 let sign ~priv ~msg =
-  (* yeah, I know that it's really bad smell code *)
   let priv' = Utils.generate_pieces ~digest:Hash.digest_bytes priv in
   let ver_key =
     List.map priv' ~f:digest_to_string
@@ -77,14 +78,13 @@ 

100.00%

msg |> Utils.indexed_keys |> Utils.replace_index ~matrix:priv' - |> List.map ~f:Utils.bytes_to_string |> List.reduce_exn ~f:Utils.concat_hashes in ver_text ^ "\n" ^ ver_key
- + diff --git a/docs/coverage/lib/store.ml.html b/docs/coverage/lib/store.ml.html index 3d36005..3c0cd78 100644 --- a/docs/coverage/lib/store.ml.html +++ b/docs/coverage/lib/store.ml.html @@ -204,7 +204,7 @@

100.00%

- + diff --git a/docs/coverage/lib/utils.ml.html b/docs/coverage/lib/utils.ml.html index 7cda548..1fd28df 100644 --- a/docs/coverage/lib/utils.ml.html +++ b/docs/coverage/lib/utils.ml.html @@ -25,52 +25,52 @@

100.00%

- - - + + + - - + + - - + + - + - - - + + + - - + + - + - + - - - + + + - - - + + + - - + + - + - - + + - + - + @@ -78,32 +78,44 @@

100.00%

- + - + - + - + - + - + - + - - - - - + + + + + - - + + - + + + + + + + + + + + + +
@@ -194,14 +206,40 @@

100.00%

84 85 86 +87 +88 +89 +90 +91 +92 +93 +94 +95 +96 +97 +98
 module List = Core.List
 module String = Core.String
 module Char = Core.Char
 module Int = Core.Int
+module Lazy = Core.Lazy
 module Str = Re.Str
 
+module Defer = struct
+  let force = Lazy.force_val
+
+  let bind deferred ~f =
+    lazy (force @@ f @@ force deferred)
+end
+
+let bytes_of_string string = Cstruct.to_bytes @@ Cstruct.of_hex string
+
+let bytes_to_string bytes =
+  Hex.show @@ Hex.of_cstruct @@ Cstruct.of_bytes bytes
+
+
 (* 16 hex chars and 128 chars/string length for hash under hex string format *)
 let _HASH_LENGTH = 128
 
@@ -215,16 +253,17 @@ 

100.00%

Str.string_match regexp text 0 && String.length text = _HASH_LENGTH -let _int_to_cstruct number = Cstruct.of_string @@ string_of_int number +let _int_to_cstruct number = + lazy (Cstruct.of_string @@ string_of_int number) let _hash_both ~digest prefix suffix = - Cstruct.append prefix suffix |> Cstruct.to_bytes |> digest + lazy (digest @@ Cstruct.to_bytes @@ Cstruct.append prefix suffix) let generate_pieces ~digest random = let blob = Cstruct.of_bytes random in let nums = List.init _KEY_LENGTH ~f:_int_to_cstruct in - List.map nums ~f:(_hash_both ~digest blob) + List.map nums ~f:(Defer.bind ~f:(_hash_both ~digest blob)) let validate_key list = @@ -236,12 +275,14 @@

100.00%

let calculate_index (position, key) = (position * _HEX_SPACE) + key -let index_at ~list position = List.nth_exn list position +let index_at ~list position = + bytes_to_string @@ Defer.force @@ List.nth_exn list position -let replace_index ~matrix pairs = pairs |> List.map ~f:(index_at ~list:matrix) +let replace_index ~matrix pairs = + List.map pairs ~f:(index_at ~list:matrix) let verify_at ~digest ~list (position, opening) = - let commitment = List.nth_exn list position in + let commitment = Defer.force @@ List.nth_exn list position in let hash = digest opening in hash = commitment @@ -277,15 +318,10 @@

100.00%

let nonzero char = char != nullchar let unpad msg = String.filter ~f:nonzero msg - -let bytes_of_string string = Cstruct.to_bytes @@ Cstruct.of_hex string - -let bytes_to_string bytes = - Hex.show @@ Hex.of_cstruct @@ Cstruct.of_bytes bytes
- + diff --git a/docs/coverage/lib/verification.ml.html b/docs/coverage/lib/verification.ml.html index 91ecdd0..681d104 100644 --- a/docs/coverage/lib/verification.ml.html +++ b/docs/coverage/lib/verification.ml.html @@ -23,32 +23,36 @@

100.00%

- + - + - + - - + + - + - + - + - + + + + +
@@ -84,11 +88,16 @@

100.00%

29 30 31 +32 +33 +34 +35
 module String = Core.String
 module List = Core.List
 module Option = Core.Option
+module Defer = Utils.Defer
 
 let digest message =
   message
@@ -100,6 +109,9 @@ 

100.00%

|> Hex.show +let delay_string_cast bytes = + lazy (Utils.bytes_to_string bytes) + let verify ~pub ~msg ~signature = try let parts = String.split signature ~on:'\n' in @@ -107,7 +119,7 @@

100.00%

let ver_key_bytes = Option.value_exn (Serialization.load @@ List.nth_exn parts 1) in - let ver_key = List.map ~f:Utils.bytes_to_string ver_key_bytes in + let ver_key = List.map ~f:delay_string_cast ver_key_bytes in let indexed_keys = Utils.indexed_keys msg in let proofs = List.zip_exn indexed_keys ver_text in let verified = Utils.verify_with ~matrix:ver_key ~digest proofs in @@ -120,7 +132,7 @@

100.00%

- + diff --git a/lib/keys.ml b/lib/keys.ml index 33063cb..8d87051 100644 --- a/lib/keys.ml +++ b/lib/keys.ml @@ -3,12 +3,15 @@ module String = Core.String module Float = Core.Float module Int64 = Core.Int64 module Option = Core.Option +module Defer = Utils.Defer let generate () = Random.generate512 () +let __force_digest lazy_piece = Hash.digest_bytes @@ Defer.force lazy_piece + let genpub priv = let pieces = Utils.generate_pieces ~digest:Hash.digest_bytes priv in - List.map pieces ~f:Hash.digest_bytes + List.map pieces ~f:__force_digest let derive priv = Utils.bytes_of_string @@ Serialization.digest @@ genpub priv diff --git a/lib/signing.ml b/lib/signing.ml index 17fb8b1..8dd5898 100644 --- a/lib/signing.ml +++ b/lib/signing.ml @@ -1,9 +1,11 @@ module List = Core.List +module Defer = Utils.Defer + +let digest_to_string lazy_bytes = + Utils.bytes_to_string @@ Hash.digest_bytes @@ Defer.force lazy_bytes -let digest_to_string bytes = Utils.bytes_to_string @@ Hash.digest_bytes bytes let sign ~priv ~msg = - (* yeah, I know that it's really bad smell code *) let priv' = Utils.generate_pieces ~digest:Hash.digest_bytes priv in let ver_key = List.map priv' ~f:digest_to_string @@ -13,7 +15,6 @@ let sign ~priv ~msg = msg |> Utils.indexed_keys |> Utils.replace_index ~matrix:priv' - |> List.map ~f:Utils.bytes_to_string |> List.reduce_exn ~f:Utils.concat_hashes in ver_text ^ "\n" ^ ver_key diff --git a/lib/utils.ml b/lib/utils.ml index 56a5ece..805066f 100644 --- a/lib/utils.ml +++ b/lib/utils.ml @@ -2,8 +2,21 @@ module List = Core.List module String = Core.String module Char = Core.Char module Int = Core.Int +module Lazy = Core.Lazy module Str = Re.Str +module Defer = struct + let force = Lazy.force_val + + let bind deferred ~f = lazy (force @@ f @@ force deferred) +end + +let bytes_of_string string = Cstruct.to_bytes @@ Cstruct.of_hex string + +let bytes_to_string bytes = + Hex.show @@ Hex.of_cstruct @@ Cstruct.of_bytes bytes + + (* 16 hex chars and 128 chars/string length for hash under hex string format *) let _HASH_LENGTH = 128 @@ -17,16 +30,16 @@ let is_hash text = Str.string_match regexp text 0 && String.length text = _HASH_LENGTH -let _int_to_cstruct number = Cstruct.of_string @@ string_of_int number +let _int_to_cstruct number = lazy (Cstruct.of_string @@ string_of_int number) let _hash_both ~digest prefix suffix = - Cstruct.append prefix suffix |> Cstruct.to_bytes |> digest + lazy (digest @@ Cstruct.to_bytes @@ Cstruct.append prefix suffix) let generate_pieces ~digest random = let blob = Cstruct.of_bytes random in let nums = List.init _KEY_LENGTH ~f:_int_to_cstruct in - List.map nums ~f:(_hash_both ~digest blob) + List.map nums ~f:(Defer.bind ~f:(_hash_both ~digest blob)) let validate_key list = @@ -38,12 +51,14 @@ let to_hex text = "0x" ^ text let calculate_index (position, key) = (position * _HEX_SPACE) + key -let index_at ~list position = List.nth_exn list position +let index_at ~list position = + bytes_to_string @@ Defer.force @@ List.nth_exn list position + -let replace_index ~matrix pairs = pairs |> List.map ~f:(index_at ~list:matrix) +let replace_index ~matrix pairs = List.map pairs ~f:(index_at ~list:matrix) let verify_at ~digest ~list (position, opening) = - let commitment = List.nth_exn list position in + let commitment = Defer.force @@ List.nth_exn list position in let hash = digest opening in hash = commitment @@ -79,8 +94,3 @@ let pad ~basis msg = let nonzero char = char != nullchar let unpad msg = String.filter ~f:nonzero msg - -let bytes_of_string string = Cstruct.to_bytes @@ Cstruct.of_hex string - -let bytes_to_string bytes = - Hex.show @@ Hex.of_cstruct @@ Cstruct.of_bytes bytes diff --git a/lib/utils.mli b/lib/utils.mli index 48e14f8..1d8d2cd 100644 --- a/lib/utils.mli +++ b/lib/utils.mli @@ -1,3 +1,9 @@ +module Defer : sig + val force : 'a Lazy.t -> 'a + + val bind : 'a Lazy.t -> f:('a -> 'b Lazy.t) -> 'b Lazy.t +end + val _HASH_LENGTH : int val _KEY_LENGTH : int @@ -10,14 +16,14 @@ val concat_hashes : string -> string -> string val validate_key : string list -> string list option -val generate_pieces : digest:(bytes -> bytes) -> bytes -> bytes list +val generate_pieces : digest:(bytes -> bytes) -> bytes -> bytes Lazy.t list -val replace_index : matrix:'a list -> int list -> 'a list +val replace_index : matrix:bytes Lazy.t list -> int list -> string list val indexed_keys : string -> int list val verify_with : - matrix:string list + matrix:string Lazy.t list -> digest:(string -> string) -> (int * string) list -> bool diff --git a/lib/verification.ml b/lib/verification.ml index 38833e4..a793ae7 100644 --- a/lib/verification.ml +++ b/lib/verification.ml @@ -1,6 +1,7 @@ module String = Core.String module List = Core.List module Option = Core.Option +module Defer = Utils.Defer let digest message = message @@ -12,6 +13,8 @@ let digest message = |> Hex.show +let delay_string_cast bytes = lazy (Utils.bytes_to_string bytes) + let verify ~pub ~msg ~signature = try let parts = String.split signature ~on:'\n' in @@ -19,7 +22,7 @@ let verify ~pub ~msg ~signature = let ver_key_bytes = Option.value_exn (Serialization.load @@ List.nth_exn parts 1) in - let ver_key = List.map ~f:Utils.bytes_to_string ver_key_bytes in + let ver_key = List.map ~f:delay_string_cast ver_key_bytes in let indexed_keys = Utils.indexed_keys msg in let proofs = List.zip_exn indexed_keys ver_text in let verified = Utils.verify_with ~matrix:ver_key ~digest proofs in diff --git a/test/bench/bench.expected b/test/bench/bench.expected index 2890e80..e1319e0 100644 --- a/test/bench/bench.expected +++ b/test/bench/bench.expected @@ -2,18 +2,18 @@ Estimated testing time 2m (12 benchmarks x 10s). Change using -quota SECS. ┌─────────────────────────────────────────────────────┬──────────────────┬───────────────┬────────────────┬─────────────┬────────────┐ │ Name │ Time/Run │ mWd/Run │ mjWd/Run │ Prom/Run │ Percentage │ ├─────────────────────────────────────────────────────┼──────────────────┼───────────────┼────────────────┼─────────────┼────────────┤ -│ hieroglyphs + blake2b ------ private key generation │ 17_525.88ns │ 610.86w │ 0.13w │ 0.13w │ │ -│ hieroglyphs + blake2b ------ message signing │ 817_123_209.18ns │ 1_083_435.49w │ 34_105_687.00w │ 72_142.00w │ 100.00% │ -│ hieroglyphs + blake2b ------ public key derivation │ 725_470_742.16ns │ 1_050_688.71w │ 33_925_498.14w │ 91_423.14w │ 88.78% │ -│ hieroglyphs + blake2b ------ signature verification │ 784_232_620.65ns │ 5_855_944.94w │ 34_029_307.97w │ 160_142.97w │ 95.97% │ -│ rsa pss/sha256 1024 bits --- private key generation │ 37_672_015.30ns │ 870.67w │ -0.23w │ -0.23w │ 4.61% │ -│ rsa pss/sha256 1024 bits --- public key derivation │ 10.60ns │ 3.00w │ │ │ │ -│ rsa pss/sha256 1024 bits --- message signing │ 803_344.15ns │ 1_715.18w │ 0.59w │ 0.59w │ 0.10% │ -│ rsa pss/sha256 1024 bits --- signature verification │ 113_583.97ns │ 1_544.02w │ 0.34w │ 0.34w │ 0.01% │ -│ secp256k1 + sha256 hash ---- private key generation │ 12_656.23ns │ 355.66w │ │ │ │ -│ secp256k1 + sha256 hash ---- public key derivation │ 207_689.41ns │ 13.00w │ │ │ 0.03% │ -│ secp256k1 + sha256 hash ---- message signing │ 322_686.25ns │ 230.00w │ │ │ 0.04% │ -│ secp256k1 + sha256 hash ---- signature verification │ 385_461.70ns │ 214.00w │ │ │ 0.05% │ +│ hieroglyphs + blake2b ------ private key generation │ 18_250.29ns │ 610.86w │ 0.13w │ 0.13w │ │ +│ hieroglyphs + blake2b ------ message signing │ 830_777_285.22ns │ 1_126_055.43w │ 34_143_882.57w │ 110_337.57w │ 84.82% │ +│ hieroglyphs + blake2b ------ public key derivation │ 762_818_024.31ns │ 1_093_699.54w │ 33_944_068.46w │ 109_993.46w │ 77.88% │ +│ hieroglyphs + blake2b ------ signature verification │ 979_464_860.27ns │ 5_363_258.26w │ 34_006_904.17w │ 137_739.17w │ 100.00% │ +│ rsa pss/sha256 1024 bits --- private key generation │ 43_341_991.32ns │ 870.83w │ -0.27w │ -0.27w │ 4.43% │ +│ rsa pss/sha256 1024 bits --- public key derivation │ 13.52ns │ 3.00w │ │ │ │ +│ rsa pss/sha256 1024 bits --- message signing │ 884_425.40ns │ 1_715.01w │ 0.54w │ 0.54w │ 0.09% │ +│ rsa pss/sha256 1024 bits --- signature verification │ 99_468.45ns │ 1_547.02w │ 0.35w │ 0.35w │ 0.01% │ +│ secp256k1 + sha256 hash ---- private key generation │ 15_107.13ns │ 355.80w │ │ │ │ +│ secp256k1 + sha256 hash ---- public key derivation │ 251_762.39ns │ 13.00w │ │ │ 0.03% │ +│ secp256k1 + sha256 hash ---- message signing │ 364_347.26ns │ 230.00w │ │ │ 0.04% │ +│ secp256k1 + sha256 hash ---- signature verification │ 424_337.89ns │ 214.00w │ │ │ 0.04% │ └─────────────────────────────────────────────────────┴──────────────────┴───────────────┴────────────────┴─────────────┴────────────┘ Benchmarks that take 1ns to 100ms can be estimated precisely. For more reliable estimates, redesign your benchmark to have a shorter execution time. From f55fb4380367544cfd1698b15ea2cce172a03d15 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marco=20Aur=C3=A9lio=20da=20Silva?= Date: Sat, 13 Jul 2019 17:39:29 -0300 Subject: [PATCH 08/29] docs: :book: bumping license year MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Marco Aurélio da Silva --- LICENSE | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/LICENSE b/LICENSE index 1aa8bb0..91dfcd9 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ MIT License -Copyright (c) 2018 Marco Aurélio da Silva +Copyright (c) 2019 Marco Aurélio da Silva Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal From c9657a1e15288e08cabb875f229bcd7d31472468 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marco=20Aur=C3=A9lio=20da=20Silva?= Date: Sat, 13 Jul 2019 17:42:42 -0300 Subject: [PATCH 09/29] refactor: :recycle: using Blake2B instead of SHA256 to derive IV from proof-of-work pass on Encryption module MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Marco Aurélio da Silva --- lib/encryption.ml | 23 ++++++++++++++++------- 1 file changed, 16 insertions(+), 7 deletions(-) diff --git a/lib/encryption.ml b/lib/encryption.ml index 3c04fe8..6533979 100644 --- a/lib/encryption.ml +++ b/lib/encryption.ml @@ -2,17 +2,26 @@ open Nocrypto.Cipher_block.AES.CBC module Option = Core.Option module Base64 = Nocrypto.Base64 -let digest cstruct = - let digest = Nocrypto.Hash.SHA256.digest cstruct in - let left, right = Cstruct.split digest 16 in - (* split 32 bytes into a pair of 16 *) - Nocrypto.Uncommon.Cs.xor left right +let __digest cstruct = + Cstruct.of_hex @@ Hash.digest @@ Cstruct.to_string cstruct + + +let __compute_iv cstruct = + let digest = __digest cstruct in + (* split 64 bytes into a pair of 32 *) + let blob1, blob2 = Cstruct.split digest 32 in + (* then split 32 bytes into a pair of 16 *) + let blob3, blob4 = Cstruct.split blob1 16 in + let blob5, blob6 = Cstruct.split blob2 16 in + let blob7 = Nocrypto.Uncommon.Cs.xor blob3 blob4 in + let blob8 = Nocrypto.Uncommon.Cs.xor blob5 blob6 in + Nocrypto.Uncommon.Cs.xor blob7 blob8 let encrypt msg ~pass = let proof = Hash.mine pass ~difficulty:5 in let key = of_secret proof in - let iv = digest proof in + let iv = __compute_iv proof in let result = encrypt ~iv ~key (Utils.pad ~basis:16 msg) in result |> Base64.encode |> Cstruct.to_string @@ -20,7 +29,7 @@ let encrypt msg ~pass = let decrypt cipher ~pass = let proof = Hash.mine pass ~difficulty:5 in let key = of_secret proof in - let iv = digest proof in + let iv = __compute_iv proof in let result = cipher |> Cstruct.of_string |> Base64.decode in let open Option in result From 5b96550c1cbb216a30f93bb5715209bf28258b19 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marco=20Aur=C3=A9lio=20da=20Silva?= Date: Sat, 13 Jul 2019 18:57:18 -0300 Subject: [PATCH 10/29] refactor: :recycle: changing split character to not collide with our planned base64 characters MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Marco Aurélio da Silva --- lib/serialization.ml | 2 +- lib/utils.ml | 2 +- lib/verification.ml | 2 +- test/spec/sign.ml | 4 ++-- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/lib/serialization.ml b/lib/serialization.ml index b7f407a..92e145a 100644 --- a/lib/serialization.ml +++ b/lib/serialization.ml @@ -9,7 +9,7 @@ let show pub = let load text = - let list = String.split text ~on:'-' in + let list = String.split text ~on:':' in let open Option in Utils.validate_key list >>= fun list -> some @@ List.map ~f:Utils.bytes_of_string list diff --git a/lib/utils.ml b/lib/utils.ml index 805066f..a9d1392 100644 --- a/lib/utils.ml +++ b/lib/utils.ml @@ -69,7 +69,7 @@ let verify_with ~matrix ~digest pairs = |> List.reduce_exn ~f:( && ) -let concat_hashes left right = left ^ "-" ^ right +let concat_hashes left right = left ^ ":" ^ right let char_to_hex_int index char = let value = char |> Char.to_string |> to_hex |> Int.of_string in diff --git a/lib/verification.ml b/lib/verification.ml index a793ae7..2513226 100644 --- a/lib/verification.ml +++ b/lib/verification.ml @@ -18,7 +18,7 @@ let delay_string_cast bytes = lazy (Utils.bytes_to_string bytes) let verify ~pub ~msg ~signature = try let parts = String.split signature ~on:'\n' in - let ver_text = List.nth_exn parts 0 |> String.split ~on:'-' in + let ver_text = List.nth_exn parts 0 |> String.split ~on:':' in let ver_key_bytes = Option.value_exn (Serialization.load @@ List.nth_exn parts 1) in diff --git a/test/spec/sign.ml b/test/spec/sign.ml index 22dd50f..51045e4 100644 --- a/test/spec/sign.ml +++ b/test/spec/sign.ml @@ -18,11 +18,11 @@ let __signature_validation () = let parts = String.split ~on:'\n' signature in let vertext = List.nth_exn parts 0 in let verkey = List.nth_exn parts 1 in - let chunks = String.split ~on:'-' vertext in + let chunks = String.split ~on:':' vertext in let filtered = List.filter ~f:Utils.is_hash chunks in Alcotest.(check int) "valid signature size" (List.length chunks) 128 ; Alcotest.(check int) "valid chunks in signature" (List.length filtered) 128 ; - let chunks = String.split ~on:'-' verkey in + let chunks = String.split ~on:':' verkey in let filtered = List.filter ~f:Utils.is_hash chunks in Alcotest.(check int) "valid verification key size" From 993852e96ddc1f93697a07cda81254d9daafd068 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marco=20Aur=C3=A9lio=20da=20Silva?= Date: Sat, 13 Jul 2019 19:05:58 -0300 Subject: [PATCH 11/29] refactor: :recycle: moving out the digest hash function used to verify/match hex payload pieces MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Marco Aurélio da Silva --- lib/utils.ml | 9 +++++++++ lib/utils.mli | 2 ++ lib/verification.ml | 10 +--------- 3 files changed, 12 insertions(+), 9 deletions(-) diff --git a/lib/utils.ml b/lib/utils.ml index a9d1392..4f2b195 100644 --- a/lib/utils.ml +++ b/lib/utils.ml @@ -94,3 +94,12 @@ let pad ~basis msg = let nonzero char = char != nullchar let unpad msg = String.filter ~f:nonzero msg + +let digest_hex_string hex = + hex + |> Cstruct.of_hex + |> Cstruct.to_bytes + |> Hash.digest_bytes + |> Cstruct.of_bytes + |> Hex.of_cstruct + |> Hex.show diff --git a/lib/utils.mli b/lib/utils.mli index 1d8d2cd..eec9d7e 100644 --- a/lib/utils.mli +++ b/lib/utils.mli @@ -35,3 +35,5 @@ val unpad : string -> string val bytes_of_string : string -> bytes val bytes_to_string : bytes -> string + +val digest_hex_string : string -> string diff --git a/lib/verification.ml b/lib/verification.ml index 2513226..f75e34c 100644 --- a/lib/verification.ml +++ b/lib/verification.ml @@ -3,15 +3,7 @@ module List = Core.List module Option = Core.Option module Defer = Utils.Defer -let digest message = - message - |> Cstruct.of_hex - |> Cstruct.to_bytes - |> Hash.digest_bytes - |> Cstruct.of_bytes - |> Hex.of_cstruct - |> Hex.show - +let digest = Utils.digest_hex_string let delay_string_cast bytes = lazy (Utils.bytes_to_string bytes) From 9a7c2ee4a7cb2cebe5ffbe5c630b9ad93047ece5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marco=20Aur=C3=A9lio=20da=20Silva?= Date: Sat, 13 Jul 2019 19:34:00 -0300 Subject: [PATCH 12/29] docs: :book: bump due minor change on entry-point interface / module type [+] MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit this all was cause the FOSSA service parsing the project as public domain, due the text '... key ...' on this file Signed-off-by: Marco Aurélio da Silva --- .../apiref/hieroglyphs/Hieroglyphs/index.html | 2 +- .../Hieroglyphs__/Blacklist/index.html | 2 +- .../Hieroglyphs__/Encryption/index.html | 2 +- .../hieroglyphs/Hieroglyphs__/Hash/index.html | 2 +- .../hieroglyphs/Hieroglyphs__/Keys/index.html | 2 +- .../Bisect_visit___lib___main___ml/index.html | 2 - .../hieroglyphs/Hieroglyphs__/Main/index.html | 2 +- .../Hieroglyphs__/Random/index.html | 2 +- .../Hieroglyphs__/Serialization/index.html | 2 +- .../Hieroglyphs__/Signing/index.html | 2 +- .../Hieroglyphs__/Store/index.html | 2 +- .../Hieroglyphs__/Utils/Defer/index.html | 2 + .../Hieroglyphs__/Utils/index.html | 2 +- .../Hieroglyphs__/Verification/index.html | 2 +- .../hieroglyphs/Hieroglyphs__/index.html | 2 +- .../Hieroglyphs__Blacklist/index.html | 2 +- .../Hieroglyphs__Encryption/index.html | 2 +- .../hieroglyphs/Hieroglyphs__Hash/index.html | 2 +- .../hieroglyphs/Hieroglyphs__Keys/index.html | 2 +- .../Bisect_visit___lib___main___ml/index.html | 2 - .../hieroglyphs/Hieroglyphs__Main/index.html | 2 +- .../Hieroglyphs__Random/index.html | 2 +- .../Hieroglyphs__Serialization/index.html | 2 +- .../Hieroglyphs__Signing/index.html | 2 +- .../hieroglyphs/Hieroglyphs__Store/index.html | 2 +- .../Hieroglyphs__Utils/Defer/index.html | 2 + .../hieroglyphs/Hieroglyphs__Utils/index.html | 2 +- .../Hieroglyphs__Verification/index.html | 2 +- docs/apiref/hieroglyphs/index.html | 2 +- docs/apiref/odoc.css | 49 +++++++++---------- lib/hieroglyphs.mli | 2 +- 31 files changed, 53 insertions(+), 56 deletions(-) delete mode 100644 docs/apiref/hieroglyphs/Hieroglyphs__/Main/Bisect_visit___lib___main___ml/index.html create mode 100644 docs/apiref/hieroglyphs/Hieroglyphs__/Utils/Defer/index.html delete mode 100644 docs/apiref/hieroglyphs/Hieroglyphs__Main/Bisect_visit___lib___main___ml/index.html create mode 100644 docs/apiref/hieroglyphs/Hieroglyphs__Utils/Defer/index.html diff --git a/docs/apiref/hieroglyphs/Hieroglyphs/index.html b/docs/apiref/hieroglyphs/Hieroglyphs/index.html index fb566b8..be19d49 100644 --- a/docs/apiref/hieroglyphs/Hieroglyphs/index.html +++ b/docs/apiref/hieroglyphs/Hieroglyphs/index.html @@ -1,2 +1,2 @@ -Hieroglyphs (hieroglyphs.Hieroglyphs)

Module Hieroglyphs

Quantum-resistant, purely Hash-based, Stateful, One-Time Digital Signatures for OCaml.

author
Marco Aurélio da Silva
version
0.0.1
type priv

The opaque/abstract type for our private keys.

type pub

The opaque/abstract type for our public keys.

val generate : unit -> priv

Generates an unique private key.

val derive : priv -> pub

Derives an unique public key from private key.

val pair : unit -> priv * pub

Helper function which generates a signature key pair.

val export : priv:priv -> pass:string -> string

export ~priv ~pass dumps an encrypted version of the private key.

val import : cipher:string -> pass:string -> priv option

import ~cipher ~pass tries to load a previously exported private key, only if the cipher text and the password yield a valid, internally parseable private key.

val load : string -> pub option

load text parses a valid public key, otherwise, returns None.

val show : pub -> string

show pubkey dumps/serialize a public key under string format.

val address : pub -> string

address pubkey generates an unique, deterministic ID for given public key. It's useful, for instance, to externally track the used/consumed private keys with a maintained state under a blacklist, cause there's an unique mapping from priv to pub, and therefore, from priv to id : string (the composition of derive with address.

val sign : priv:priv -> msg:string -> string option

sign ~priv ~msg creates a deterministic string signature given the same private key and same message. Fails if the private key was already used previously to sign a message, even if the message was the same (TODO: it's safe to sign many times the same message, 'cause it still makes inversion/prediction attacks impossible).

val verify : pub:pub -> msg:string -> signature:string -> bool

verify ~pub ~msg ~signature succeeds if the signature is valid for given message and was generated by the private key which generated the given public key.

\ No newline at end of file +Hieroglyphs (hieroglyphs.Hieroglyphs)

Module Hieroglyphs

Quantum-resistant, purely Hash-based, Stateful, One-Time Digital Signatures for OCaml.

author
Marco Aurélio da Silva
version
0.0.1
type priv

The opaque/abstract type for our private keys.

type pub

The opaque/abstract type for our public keys.

val generate : unit -> priv

Generates an unique private key.

val derive : priv -> pub

Derives an unique public key from private key.

val pair : unit -> priv * pub

Helper function which generates a signature key pair.

val export : priv:priv -> pass:string -> string

export ~priv ~pass dumps an encrypted version of the private key.

val import : cipher:string -> pass:string -> priv option

import ~cipher ~pass tries to load a previously exported private key, only if the cipher text and the password yield a valid, internally parseable private key.

val load : string -> pub option

load text parses a valid public key, otherwise, returns None.

val show : pub -> string

show pubkey dumps/serialize a public key under string format.

val address : pub -> string

address pubkey generates an unique, deterministic ID for given public key. It's useful, for instance, to externally track the used/consumed private keys with a maintained state under a blacklist, cause there's an unique mapping from priv to pub, and therefore, from priv to id : string (the composition of derive with address.

val sign : priv:priv -> msg:string -> string option

sign ~priv ~msg creates a deterministic string signature given the same private key and same message. Fails if the private key was already used previously to sign a message, even if the message was the same (TODO: it's safe to sign many times the same message, 'cause it still makes inversion/prediction attacks impossible).

val verify : pub:pub -> msg:string -> signature:string -> bool

verify ~pub ~msg ~signature succeeds if the signature is valid for given message and was generated by the private key which generated the given public key.

\ No newline at end of file diff --git a/docs/apiref/hieroglyphs/Hieroglyphs__/Blacklist/index.html b/docs/apiref/hieroglyphs/Hieroglyphs__/Blacklist/index.html index 4daba4e..1edfe1a 100644 --- a/docs/apiref/hieroglyphs/Hieroglyphs__/Blacklist/index.html +++ b/docs/apiref/hieroglyphs/Hieroglyphs__/Blacklist/index.html @@ -1,2 +1,2 @@ -Blacklist (hieroglyphs.Hieroglyphs__.Blacklist)

Module Hieroglyphs__.Blacklist

val add : string -> unit
val exists : string -> bool
\ No newline at end of file +Blacklist (hieroglyphs.Hieroglyphs__.Blacklist)

Module Hieroglyphs__.Blacklist

val add : string -> unit
val exists : string -> bool
\ No newline at end of file diff --git a/docs/apiref/hieroglyphs/Hieroglyphs__/Encryption/index.html b/docs/apiref/hieroglyphs/Hieroglyphs__/Encryption/index.html index af306eb..dec964f 100644 --- a/docs/apiref/hieroglyphs/Hieroglyphs__/Encryption/index.html +++ b/docs/apiref/hieroglyphs/Hieroglyphs__/Encryption/index.html @@ -1,2 +1,2 @@ -Encryption (hieroglyphs.Hieroglyphs__.Encryption)

Module Hieroglyphs__.Encryption

val encrypt : string -> pass:string -> string
val decrypt : string -> pass:string -> string option
\ No newline at end of file +Encryption (hieroglyphs.Hieroglyphs__.Encryption)

Module Hieroglyphs__.Encryption

val encrypt : string -> pass:string -> string
val decrypt : string -> pass:string -> string option
\ No newline at end of file diff --git a/docs/apiref/hieroglyphs/Hieroglyphs__/Hash/index.html b/docs/apiref/hieroglyphs/Hieroglyphs__/Hash/index.html index 6e4705f..2455673 100644 --- a/docs/apiref/hieroglyphs/Hieroglyphs__/Hash/index.html +++ b/docs/apiref/hieroglyphs/Hieroglyphs__/Hash/index.html @@ -1,2 +1,2 @@ -Hash (hieroglyphs.Hieroglyphs__.Hash)

Module Hieroglyphs__.Hash

val digest : string -> string
val digest_bytes : bytes -> bytes
val mine : difficulty:int -> string -> Cstruct.t
\ No newline at end of file +Hash (hieroglyphs.Hieroglyphs__.Hash)

Module Hieroglyphs__.Hash

val digest : string -> string
val digest_bytes : bytes -> bytes
val mine : difficulty:int -> string -> Cstruct.t
\ No newline at end of file diff --git a/docs/apiref/hieroglyphs/Hieroglyphs__/Keys/index.html b/docs/apiref/hieroglyphs/Hieroglyphs__/Keys/index.html index 8bf2ba7..cb89a28 100644 --- a/docs/apiref/hieroglyphs/Hieroglyphs__/Keys/index.html +++ b/docs/apiref/hieroglyphs/Hieroglyphs__/Keys/index.html @@ -1,2 +1,2 @@ -Keys (hieroglyphs.Hieroglyphs__.Keys)

Module Hieroglyphs__.Keys

val sign : priv:bytes -> msg:string -> string
val verify : pub:bytes -> msg:string -> signature:string -> bool
val show : bytes -> string
val load : string -> bytes option
val import : cipher:string -> pass:string -> bytes option
val export : priv:bytes -> pass:string -> string
val generate : unit -> bytes
val derive : bytes -> bytes
val address : bytes -> string
\ No newline at end of file +Keys (hieroglyphs.Hieroglyphs__.Keys)

Module Hieroglyphs__.Keys

val sign : priv:bytes -> msg:string -> string
val verify : pub:bytes -> msg:string -> signature:string -> bool
val show : bytes -> string
val load : string -> bytes option
val import : cipher:string -> pass:string -> bytes option
val export : priv:bytes -> pass:string -> string
val generate : unit -> bytes
val derive : bytes -> bytes
val address : bytes -> string
\ No newline at end of file diff --git a/docs/apiref/hieroglyphs/Hieroglyphs__/Main/Bisect_visit___lib___main___ml/index.html b/docs/apiref/hieroglyphs/Hieroglyphs__/Main/Bisect_visit___lib___main___ml/index.html deleted file mode 100644 index 5e59f21..0000000 --- a/docs/apiref/hieroglyphs/Hieroglyphs__/Main/Bisect_visit___lib___main___ml/index.html +++ /dev/null @@ -1,2 +0,0 @@ - -Bisect_visit___lib___main___ml (hieroglyphs.Hieroglyphs__.Main.Bisect_visit___lib___main___ml)

Module Main.Bisect_visit___lib___main___ml

val ___bisect_visit___ : int -> unit
\ No newline at end of file diff --git a/docs/apiref/hieroglyphs/Hieroglyphs__/Main/index.html b/docs/apiref/hieroglyphs/Hieroglyphs__/Main/index.html index bbd6247..4d64aec 100644 --- a/docs/apiref/hieroglyphs/Hieroglyphs__/Main/index.html +++ b/docs/apiref/hieroglyphs/Hieroglyphs__/Main/index.html @@ -1,2 +1,2 @@ -Main (hieroglyphs.Hieroglyphs__.Main)

Module Hieroglyphs__.Main

module Bisect_visit___lib___main___ml : sig ... end
module Option = Core.Option
type priv = bytes
type pub = bytes
val derive : bytes -> bytes
val import : cipher:string -> pass:string -> bytes option
val export : priv:bytes -> pass:string -> string
val show : bytes -> string
val load : string -> bytes option
val address : bytes -> string
val sign : priv:bytes -> msg:string -> string
val verify : pub:bytes -> msg:string -> signature:string -> bool
val __check : bytes -> bytes option
val sign : priv:bytes -> msg:string -> string Option.t
val import : cipher:string -> pass:string -> bytes Option.t
val generate : unit -> bytes
val pair : unit -> bytes * bytes
\ No newline at end of file +Main (hieroglyphs.Hieroglyphs__.Main)

Module Hieroglyphs__.Main

module Option = Core.Option
type priv = bytes
type pub = bytes
val derive : bytes -> bytes
val import : cipher:string -> pass:string -> bytes option
val export : priv:bytes -> pass:string -> string
val show : bytes -> string
val load : string -> bytes option
val address : bytes -> string
val sign : priv:bytes -> msg:string -> string
val verify : pub:bytes -> msg:string -> signature:string -> bool
val __check : bytes -> bytes option
val sign : priv:bytes -> msg:string -> string Option.t
val import : cipher:string -> pass:string -> bytes Option.t
val generate : unit -> bytes
val pair : unit -> bytes * bytes
\ No newline at end of file diff --git a/docs/apiref/hieroglyphs/Hieroglyphs__/Random/index.html b/docs/apiref/hieroglyphs/Hieroglyphs__/Random/index.html index 17b441b..d501407 100644 --- a/docs/apiref/hieroglyphs/Hieroglyphs__/Random/index.html +++ b/docs/apiref/hieroglyphs/Hieroglyphs__/Random/index.html @@ -1,2 +1,2 @@ -Random (hieroglyphs.Hieroglyphs__.Random)

Module Hieroglyphs__.Random

val generate512 : unit -> bytes
\ No newline at end of file +Random (hieroglyphs.Hieroglyphs__.Random)

Module Hieroglyphs__.Random

val generate512 : unit -> bytes
\ No newline at end of file diff --git a/docs/apiref/hieroglyphs/Hieroglyphs__/Serialization/index.html b/docs/apiref/hieroglyphs/Hieroglyphs__/Serialization/index.html index 67034d2..3d0eab8 100644 --- a/docs/apiref/hieroglyphs/Hieroglyphs__/Serialization/index.html +++ b/docs/apiref/hieroglyphs/Hieroglyphs__/Serialization/index.html @@ -1,2 +1,2 @@ -Serialization (hieroglyphs.Hieroglyphs__.Serialization)

Module Hieroglyphs__.Serialization

val show : bytes list -> string
val load : string -> bytes list option
val digest : bytes list -> string
\ No newline at end of file +Serialization (hieroglyphs.Hieroglyphs__.Serialization)

Module Hieroglyphs__.Serialization

val show : bytes list -> string
val load : string -> bytes list option
val digest : bytes list -> string
\ No newline at end of file diff --git a/docs/apiref/hieroglyphs/Hieroglyphs__/Signing/index.html b/docs/apiref/hieroglyphs/Hieroglyphs__/Signing/index.html index ecaedc1..573c9b3 100644 --- a/docs/apiref/hieroglyphs/Hieroglyphs__/Signing/index.html +++ b/docs/apiref/hieroglyphs/Hieroglyphs__/Signing/index.html @@ -1,2 +1,2 @@ -Signing (hieroglyphs.Hieroglyphs__.Signing)

Module Hieroglyphs__.Signing

val sign : priv:bytes -> msg:string -> string
\ No newline at end of file +Signing (hieroglyphs.Hieroglyphs__.Signing)

Module Hieroglyphs__.Signing

val sign : priv:bytes -> msg:string -> string
\ No newline at end of file diff --git a/docs/apiref/hieroglyphs/Hieroglyphs__/Store/index.html b/docs/apiref/hieroglyphs/Hieroglyphs__/Store/index.html index 1d8bac6..822b6d5 100644 --- a/docs/apiref/hieroglyphs/Hieroglyphs__/Store/index.html +++ b/docs/apiref/hieroglyphs/Hieroglyphs__/Store/index.html @@ -1,2 +1,2 @@ -Store (hieroglyphs.Hieroglyphs__.Store)

Module Hieroglyphs__.Store

val get : key:string -> string option
val set : msg:string -> key:string -> string -> unit
\ No newline at end of file +Store (hieroglyphs.Hieroglyphs__.Store)

Module Hieroglyphs__.Store

val get : key:string -> string option
val set : msg:string -> key:string -> string -> unit
\ No newline at end of file diff --git a/docs/apiref/hieroglyphs/Hieroglyphs__/Utils/Defer/index.html b/docs/apiref/hieroglyphs/Hieroglyphs__/Utils/Defer/index.html new file mode 100644 index 0000000..a02cfce --- /dev/null +++ b/docs/apiref/hieroglyphs/Hieroglyphs__/Utils/Defer/index.html @@ -0,0 +1,2 @@ + +Defer (hieroglyphs.Hieroglyphs__.Utils.Defer)

Module Utils.Defer

val force : 'a Stdlib.Lazy.t -> 'a
val bind : 'a Stdlib.Lazy.t -> f:('a -> 'b Stdlib.Lazy.t) -> 'b Stdlib.Lazy.t
\ No newline at end of file diff --git a/docs/apiref/hieroglyphs/Hieroglyphs__/Utils/index.html b/docs/apiref/hieroglyphs/Hieroglyphs__/Utils/index.html index 76f026e..2d561f6 100644 --- a/docs/apiref/hieroglyphs/Hieroglyphs__/Utils/index.html +++ b/docs/apiref/hieroglyphs/Hieroglyphs__/Utils/index.html @@ -1,2 +1,2 @@ -Utils (hieroglyphs.Hieroglyphs__.Utils)

Module Hieroglyphs__.Utils

val _HASH_LENGTH : int
val _KEY_LENGTH : int
val is_hash : string -> bool
val to_hex : string -> string
val concat_hashes : string -> string -> string
val validate_key : string list -> string list option
val generate_pieces : digest:(bytes -> bytes) -> bytes -> bytes list
val replace_index : matrix:'a list -> int list -> 'a list
val indexed_keys : string -> int list
val verify_with : matrix:string list -> digest:(string -> string) -> (int * string) list -> bool
val pad : basis:int -> string -> Cstruct.t
val unpad : string -> string
val bytes_of_string : string -> bytes
val bytes_to_string : bytes -> string
\ No newline at end of file +Utils (hieroglyphs.Hieroglyphs__.Utils)

Module Hieroglyphs__.Utils

module Defer : sig ... end
val _HASH_LENGTH : int
val _KEY_LENGTH : int
val is_hash : string -> bool
val to_hex : string -> string
val concat_hashes : string -> string -> string
val validate_key : string list -> string list option
val generate_pieces : digest:(bytes -> bytes) -> bytes -> bytes Stdlib.Lazy.t list
val replace_index : matrix:bytes Stdlib.Lazy.t list -> int list -> string list
val indexed_keys : string -> int list
val verify_with : matrix:string Stdlib.Lazy.t list -> digest:(string -> string) -> (int * string) list -> bool
val pad : basis:int -> string -> Cstruct.t
val unpad : string -> string
val bytes_of_string : string -> bytes
val bytes_to_string : bytes -> string
val hex_to_b64 : string -> string
val b64_to_hex : string -> string option
val digest_hex_string : string -> string
\ No newline at end of file diff --git a/docs/apiref/hieroglyphs/Hieroglyphs__/Verification/index.html b/docs/apiref/hieroglyphs/Hieroglyphs__/Verification/index.html index 33525ee..49d88a5 100644 --- a/docs/apiref/hieroglyphs/Hieroglyphs__/Verification/index.html +++ b/docs/apiref/hieroglyphs/Hieroglyphs__/Verification/index.html @@ -1,2 +1,2 @@ -Verification (hieroglyphs.Hieroglyphs__.Verification)

Module Hieroglyphs__.Verification

val verify : pub:bytes -> msg:string -> signature:string -> bool
\ No newline at end of file +Verification (hieroglyphs.Hieroglyphs__.Verification)

Module Hieroglyphs__.Verification

val verify : pub:bytes -> msg:string -> signature:string -> bool
\ No newline at end of file diff --git a/docs/apiref/hieroglyphs/Hieroglyphs__/index.html b/docs/apiref/hieroglyphs/Hieroglyphs__/index.html index d8593a9..08929db 100644 --- a/docs/apiref/hieroglyphs/Hieroglyphs__/index.html +++ b/docs/apiref/hieroglyphs/Hieroglyphs__/index.html @@ -1,2 +1,2 @@ -Hieroglyphs__ (hieroglyphs.Hieroglyphs__)

Module Hieroglyphs__

module Blacklist : sig ... end
module Encryption : sig ... end
module Hash : sig ... end
module Hieroglyphs = Hieroglyphs
module Keys : sig ... end
module Main : sig ... end
module Random : sig ... end
module Serialization : sig ... end
module Signing : sig ... end
module Store : sig ... end
module Utils : sig ... end
module Verification : sig ... end
\ No newline at end of file +Hieroglyphs__ (hieroglyphs.Hieroglyphs__)

Module Hieroglyphs__

module Blacklist : sig ... end
module Encryption : sig ... end
module Hash : sig ... end
module Hieroglyphs = Hieroglyphs
module Keys : sig ... end
module Main : sig ... end
module Random : sig ... end
module Serialization : sig ... end
module Signing : sig ... end
module Store : sig ... end
module Utils : sig ... end
module Verification : sig ... end
\ No newline at end of file diff --git a/docs/apiref/hieroglyphs/Hieroglyphs__Blacklist/index.html b/docs/apiref/hieroglyphs/Hieroglyphs__Blacklist/index.html index f0852a8..ad12a25 100644 --- a/docs/apiref/hieroglyphs/Hieroglyphs__Blacklist/index.html +++ b/docs/apiref/hieroglyphs/Hieroglyphs__Blacklist/index.html @@ -1,2 +1,2 @@ -Hieroglyphs__Blacklist (hieroglyphs.Hieroglyphs__Blacklist)

Module Hieroglyphs__Blacklist

val add : string -> unit
val exists : string -> bool
\ No newline at end of file +Hieroglyphs__Blacklist (hieroglyphs.Hieroglyphs__Blacklist)

Module Hieroglyphs__Blacklist

val add : string -> unit
val exists : string -> bool
\ No newline at end of file diff --git a/docs/apiref/hieroglyphs/Hieroglyphs__Encryption/index.html b/docs/apiref/hieroglyphs/Hieroglyphs__Encryption/index.html index f7affc4..b36bbe6 100644 --- a/docs/apiref/hieroglyphs/Hieroglyphs__Encryption/index.html +++ b/docs/apiref/hieroglyphs/Hieroglyphs__Encryption/index.html @@ -1,2 +1,2 @@ -Hieroglyphs__Encryption (hieroglyphs.Hieroglyphs__Encryption)

Module Hieroglyphs__Encryption

val encrypt : string -> pass:string -> string
val decrypt : string -> pass:string -> string option
\ No newline at end of file +Hieroglyphs__Encryption (hieroglyphs.Hieroglyphs__Encryption)

Module Hieroglyphs__Encryption

val encrypt : string -> pass:string -> string
val decrypt : string -> pass:string -> string option
\ No newline at end of file diff --git a/docs/apiref/hieroglyphs/Hieroglyphs__Hash/index.html b/docs/apiref/hieroglyphs/Hieroglyphs__Hash/index.html index 9bfb529..501f7cf 100644 --- a/docs/apiref/hieroglyphs/Hieroglyphs__Hash/index.html +++ b/docs/apiref/hieroglyphs/Hieroglyphs__Hash/index.html @@ -1,2 +1,2 @@ -Hieroglyphs__Hash (hieroglyphs.Hieroglyphs__Hash)

Module Hieroglyphs__Hash

val digest : string -> string
val digest_bytes : bytes -> bytes
val mine : difficulty:int -> string -> Cstruct.t
\ No newline at end of file +Hieroglyphs__Hash (hieroglyphs.Hieroglyphs__Hash)

Module Hieroglyphs__Hash

val digest : string -> string
val digest_bytes : bytes -> bytes
val mine : difficulty:int -> string -> Cstruct.t
\ No newline at end of file diff --git a/docs/apiref/hieroglyphs/Hieroglyphs__Keys/index.html b/docs/apiref/hieroglyphs/Hieroglyphs__Keys/index.html index 4691108..a1ceea8 100644 --- a/docs/apiref/hieroglyphs/Hieroglyphs__Keys/index.html +++ b/docs/apiref/hieroglyphs/Hieroglyphs__Keys/index.html @@ -1,2 +1,2 @@ -Hieroglyphs__Keys (hieroglyphs.Hieroglyphs__Keys)

Module Hieroglyphs__Keys

val sign : priv:bytes -> msg:string -> string
val verify : pub:bytes -> msg:string -> signature:string -> bool
val show : bytes -> string
val load : string -> bytes option
val import : cipher:string -> pass:string -> bytes option
val export : priv:bytes -> pass:string -> string
val generate : unit -> bytes
val derive : bytes -> bytes
val address : bytes -> string
\ No newline at end of file +Hieroglyphs__Keys (hieroglyphs.Hieroglyphs__Keys)

Module Hieroglyphs__Keys

val sign : priv:bytes -> msg:string -> string
val verify : pub:bytes -> msg:string -> signature:string -> bool
val show : bytes -> string
val load : string -> bytes option
val import : cipher:string -> pass:string -> bytes option
val export : priv:bytes -> pass:string -> string
val generate : unit -> bytes
val derive : bytes -> bytes
val address : bytes -> string
\ No newline at end of file diff --git a/docs/apiref/hieroglyphs/Hieroglyphs__Main/Bisect_visit___lib___main___ml/index.html b/docs/apiref/hieroglyphs/Hieroglyphs__Main/Bisect_visit___lib___main___ml/index.html deleted file mode 100644 index c814b82..0000000 --- a/docs/apiref/hieroglyphs/Hieroglyphs__Main/Bisect_visit___lib___main___ml/index.html +++ /dev/null @@ -1,2 +0,0 @@ - -Bisect_visit___lib___main___ml (hieroglyphs.Hieroglyphs__Main.Bisect_visit___lib___main___ml)

Module Hieroglyphs__Main.Bisect_visit___lib___main___ml

val ___bisect_visit___ : int -> unit
\ No newline at end of file diff --git a/docs/apiref/hieroglyphs/Hieroglyphs__Main/index.html b/docs/apiref/hieroglyphs/Hieroglyphs__Main/index.html index 255c778..f60b337 100644 --- a/docs/apiref/hieroglyphs/Hieroglyphs__Main/index.html +++ b/docs/apiref/hieroglyphs/Hieroglyphs__Main/index.html @@ -1,2 +1,2 @@ -Hieroglyphs__Main (hieroglyphs.Hieroglyphs__Main)

Module Hieroglyphs__Main

module Bisect_visit___lib___main___ml : sig ... end
module Option = Core.Option
type priv = bytes
type pub = bytes
val derive : bytes -> bytes
val import : cipher:string -> pass:string -> bytes option
val export : priv:bytes -> pass:string -> string
val show : bytes -> string
val load : string -> bytes option
val address : bytes -> string
val sign : priv:bytes -> msg:string -> string
val verify : pub:bytes -> msg:string -> signature:string -> bool
val __check : bytes -> bytes option
val sign : priv:bytes -> msg:string -> string Option.t
val import : cipher:string -> pass:string -> bytes Option.t
val generate : unit -> bytes
val pair : unit -> bytes * bytes
\ No newline at end of file +Hieroglyphs__Main (hieroglyphs.Hieroglyphs__Main)

Module Hieroglyphs__Main

module Option = Core.Option
type priv = bytes
type pub = bytes
val derive : bytes -> bytes
val import : cipher:string -> pass:string -> bytes option
val export : priv:bytes -> pass:string -> string
val show : bytes -> string
val load : string -> bytes option
val address : bytes -> string
val sign : priv:bytes -> msg:string -> string
val verify : pub:bytes -> msg:string -> signature:string -> bool
val __check : bytes -> bytes option
val sign : priv:bytes -> msg:string -> string Option.t
val import : cipher:string -> pass:string -> bytes Option.t
val generate : unit -> bytes
val pair : unit -> bytes * bytes
\ No newline at end of file diff --git a/docs/apiref/hieroglyphs/Hieroglyphs__Random/index.html b/docs/apiref/hieroglyphs/Hieroglyphs__Random/index.html index cfb1010..ec3fc08 100644 --- a/docs/apiref/hieroglyphs/Hieroglyphs__Random/index.html +++ b/docs/apiref/hieroglyphs/Hieroglyphs__Random/index.html @@ -1,2 +1,2 @@ -Hieroglyphs__Random (hieroglyphs.Hieroglyphs__Random)

Module Hieroglyphs__Random

val generate512 : unit -> bytes
\ No newline at end of file +Hieroglyphs__Random (hieroglyphs.Hieroglyphs__Random)

Module Hieroglyphs__Random

val generate512 : unit -> bytes
\ No newline at end of file diff --git a/docs/apiref/hieroglyphs/Hieroglyphs__Serialization/index.html b/docs/apiref/hieroglyphs/Hieroglyphs__Serialization/index.html index 7802caa..a981366 100644 --- a/docs/apiref/hieroglyphs/Hieroglyphs__Serialization/index.html +++ b/docs/apiref/hieroglyphs/Hieroglyphs__Serialization/index.html @@ -1,2 +1,2 @@ -Hieroglyphs__Serialization (hieroglyphs.Hieroglyphs__Serialization)

Module Hieroglyphs__Serialization

val show : bytes list -> string
val load : string -> bytes list option
val digest : bytes list -> string
\ No newline at end of file +Hieroglyphs__Serialization (hieroglyphs.Hieroglyphs__Serialization)

Module Hieroglyphs__Serialization

val show : bytes list -> string
val load : string -> bytes list option
val digest : bytes list -> string
\ No newline at end of file diff --git a/docs/apiref/hieroglyphs/Hieroglyphs__Signing/index.html b/docs/apiref/hieroglyphs/Hieroglyphs__Signing/index.html index 91827f7..339f59b 100644 --- a/docs/apiref/hieroglyphs/Hieroglyphs__Signing/index.html +++ b/docs/apiref/hieroglyphs/Hieroglyphs__Signing/index.html @@ -1,2 +1,2 @@ -Hieroglyphs__Signing (hieroglyphs.Hieroglyphs__Signing)

Module Hieroglyphs__Signing

val sign : priv:bytes -> msg:string -> string
\ No newline at end of file +Hieroglyphs__Signing (hieroglyphs.Hieroglyphs__Signing)

Module Hieroglyphs__Signing

val sign : priv:bytes -> msg:string -> string
\ No newline at end of file diff --git a/docs/apiref/hieroglyphs/Hieroglyphs__Store/index.html b/docs/apiref/hieroglyphs/Hieroglyphs__Store/index.html index c975060..4078d97 100644 --- a/docs/apiref/hieroglyphs/Hieroglyphs__Store/index.html +++ b/docs/apiref/hieroglyphs/Hieroglyphs__Store/index.html @@ -1,2 +1,2 @@ -Hieroglyphs__Store (hieroglyphs.Hieroglyphs__Store)

Module Hieroglyphs__Store

val get : key:string -> string option
val set : msg:string -> key:string -> string -> unit
\ No newline at end of file +Hieroglyphs__Store (hieroglyphs.Hieroglyphs__Store)

Module Hieroglyphs__Store

val get : key:string -> string option
val set : msg:string -> key:string -> string -> unit
\ No newline at end of file diff --git a/docs/apiref/hieroglyphs/Hieroglyphs__Utils/Defer/index.html b/docs/apiref/hieroglyphs/Hieroglyphs__Utils/Defer/index.html new file mode 100644 index 0000000..0885fbd --- /dev/null +++ b/docs/apiref/hieroglyphs/Hieroglyphs__Utils/Defer/index.html @@ -0,0 +1,2 @@ + +Defer (hieroglyphs.Hieroglyphs__Utils.Defer)

Module Hieroglyphs__Utils.Defer

val force : 'a Stdlib.Lazy.t -> 'a
val bind : 'a Stdlib.Lazy.t -> f:('a -> 'b Stdlib.Lazy.t) -> 'b Stdlib.Lazy.t
\ No newline at end of file diff --git a/docs/apiref/hieroglyphs/Hieroglyphs__Utils/index.html b/docs/apiref/hieroglyphs/Hieroglyphs__Utils/index.html index a0f31c8..e5aec42 100644 --- a/docs/apiref/hieroglyphs/Hieroglyphs__Utils/index.html +++ b/docs/apiref/hieroglyphs/Hieroglyphs__Utils/index.html @@ -1,2 +1,2 @@ -Hieroglyphs__Utils (hieroglyphs.Hieroglyphs__Utils)

Module Hieroglyphs__Utils

val _HASH_LENGTH : int
val _KEY_LENGTH : int
val is_hash : string -> bool
val to_hex : string -> string
val concat_hashes : string -> string -> string
val validate_key : string list -> string list option
val generate_pieces : digest:(bytes -> bytes) -> bytes -> bytes list
val replace_index : matrix:'a list -> int list -> 'a list
val indexed_keys : string -> int list
val verify_with : matrix:string list -> digest:(string -> string) -> (int * string) list -> bool
val pad : basis:int -> string -> Cstruct.t
val unpad : string -> string
val bytes_of_string : string -> bytes
val bytes_to_string : bytes -> string
\ No newline at end of file +Hieroglyphs__Utils (hieroglyphs.Hieroglyphs__Utils)

Module Hieroglyphs__Utils

module Defer : sig ... end
val _HASH_LENGTH : int
val _KEY_LENGTH : int
val is_hash : string -> bool
val to_hex : string -> string
val concat_hashes : string -> string -> string
val validate_key : string list -> string list option
val generate_pieces : digest:(bytes -> bytes) -> bytes -> bytes Stdlib.Lazy.t list
val replace_index : matrix:bytes Stdlib.Lazy.t list -> int list -> string list
val indexed_keys : string -> int list
val verify_with : matrix:string Stdlib.Lazy.t list -> digest:(string -> string) -> (int * string) list -> bool
val pad : basis:int -> string -> Cstruct.t
val unpad : string -> string
val bytes_of_string : string -> bytes
val bytes_to_string : bytes -> string
val hex_to_b64 : string -> string
val b64_to_hex : string -> string option
val digest_hex_string : string -> string
\ No newline at end of file diff --git a/docs/apiref/hieroglyphs/Hieroglyphs__Verification/index.html b/docs/apiref/hieroglyphs/Hieroglyphs__Verification/index.html index cca00da..175bd0c 100644 --- a/docs/apiref/hieroglyphs/Hieroglyphs__Verification/index.html +++ b/docs/apiref/hieroglyphs/Hieroglyphs__Verification/index.html @@ -1,2 +1,2 @@ -Hieroglyphs__Verification (hieroglyphs.Hieroglyphs__Verification)

Module Hieroglyphs__Verification

val verify : pub:bytes -> msg:string -> signature:string -> bool
\ No newline at end of file +Hieroglyphs__Verification (hieroglyphs.Hieroglyphs__Verification)

Module Hieroglyphs__Verification

val verify : pub:bytes -> msg:string -> signature:string -> bool
\ No newline at end of file diff --git a/docs/apiref/hieroglyphs/index.html b/docs/apiref/hieroglyphs/index.html index d221def..8e67773 100644 --- a/docs/apiref/hieroglyphs/index.html +++ b/docs/apiref/hieroglyphs/index.html @@ -1,2 +1,2 @@ -index (hieroglyphs.index)

Library hieroglyphs

The entry point of this library is the module: Hieroglyphs.

\ No newline at end of file +index (hieroglyphs.index)

Library hieroglyphs

The entry point of this library is the module: Hieroglyphs.

\ No newline at end of file diff --git a/docs/apiref/odoc.css b/docs/apiref/odoc.css index 3d60b5d..c86c417 100644 --- a/docs/apiref/odoc.css +++ b/docs/apiref/odoc.css @@ -1,7 +1,7 @@ @charset "UTF-8"; -/* Copyright (c) 2016 Daniel C. Bünzli. All rights reserved. +/* Copyright (c) 2016 The odoc contributors. All rights reserved. Distributed under the ISC license, see terms at the end of the file. - odoc 1.3.0 */ + odoc 1.4.0 */ /* Fonts */ @import url('https://fonts.googleapis.com/css?family=Fira+Mono:400,500'); @@ -202,17 +202,17 @@ h1 { margin-top: 1.214em; } -h2 { +h1 { font-weight: 500; font-size: 1.953em; box-shadow: 0 1px 0 0 #ddd; } -h3 { +h2 { font-size: 1.563em; } -h4 { +h3 { font-size: 1.25em; } @@ -235,15 +235,20 @@ h3 code, h3 tt { font-weight: inherit; } -h4 code, h4 tt { +h3 code, h3 tt { font-size: inherit; font-weight: inherit; } +h4 { + font-size: 1.12em; +} + + /* Preformatted and code */ tt, code, pre { - font-family: "Fira Code", "Fira Mono", courier; + font-family: "Fira Mono", courier; font-weight: 400; } @@ -274,7 +279,7 @@ pre code { /* Code lexemes */ .keyword { - font-weight: 700; + font-weight: 500; } /* Module member specification */ @@ -295,17 +300,6 @@ dl, div.spec, .doc, aside { margin-bottom: 20px; } -/* Indent the second line in multiline spec definitions. */ -.spec:not(.type) > code { - display: block; - padding-left: 4ex; - text-indent: -4ex; -} - -.spec.exception > code { - display: inline-block; -} - dl > dd { padding: 0.5em; } @@ -333,6 +327,13 @@ section+section, section > header + dl { margin: 0; font-style: italic; } +.spec.type .record { + margin-left: 2ch; +} +.spec.type .record p { + margin: 0; + font-style: italic; +} div.def { margin-top: 0; @@ -447,7 +448,7 @@ span.at-tag { .heading { margin-top: 10px; - border-top: solid; + border-bottom: solid; border-width: 1px; border-color: #DDD; text-align: right; @@ -578,7 +579,7 @@ h1+.modules, h1+.sel { .toc:before { display: block; - content: "Topics"; + content: "Contents"; text-transform: uppercase; font-size: 1em; margin: 1.414em 0 0.5em; @@ -675,10 +676,6 @@ h1+.modules, h1+.sel { /* Syntax highlighting (based on github-gist) */ -.keyword { - font-weight: 500; -} - .hljs { display: block; background: white; @@ -751,7 +748,7 @@ h1+.modules, h1+.sel { } /*--------------------------------------------------------------------------- - Copyright (c) 2016 Daniel C. Bünzli + Copyright (c) 2016 The odoc contributors Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above diff --git a/lib/hieroglyphs.mli b/lib/hieroglyphs.mli index cbc39ca..0fd2496 100644 --- a/lib/hieroglyphs.mli +++ b/lib/hieroglyphs.mli @@ -5,7 +5,7 @@ (** Hieroglyphs is a hash-based signature scheme, which, in so far, is resistant to Quantum machine attacks (unlike RSA and Elliptic Curves, which can be broken). - This "Quantum attack" is a mean to obtain the private key given the public key, that + This "Quantum attack" is a mean to obtain the private key with just the public key, that is, this break the said hard/infeasible public key inversion theorem, as proved on classical machines. From d6f7b5064f53b0f1c2dafe82e5791d85c7ac3dc4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marco=20Aur=C3=A9lio=20da=20Silva?= Date: Sat, 14 Sep 2019 22:28:43 -0300 Subject: [PATCH 13/29] optimization: :zap: pre-computed public key embedded on private key itself - public key derivation is O(1) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Marco Aurélio da Silva --- lib/encoding.ml | 10 +++++++++ lib/encoding.mli | 3 +++ lib/encryption.ml | 7 +++---- lib/keys.ml | 42 ++++++++++++++++++++++++++++++-------- lib/main.ml | 48 +++++++++++++++++++++++++++++++++++--------- lib/serialization.ml | 4 ++-- lib/signing.ml | 2 +- lib/utils.ml | 16 +++++++-------- lib/utils.mli | 8 ++++---- lib/verification.ml | 8 +++++--- 10 files changed, 108 insertions(+), 40 deletions(-) create mode 100644 lib/encoding.ml create mode 100644 lib/encoding.mli diff --git a/lib/encoding.ml b/lib/encoding.ml new file mode 100644 index 0000000..20d2498 --- /dev/null +++ b/lib/encoding.ml @@ -0,0 +1,10 @@ +module Base64 = Nocrypto.Base64 +module Option = Core.Option + +let encode payload = + Cstruct.to_string @@ Base64.encode @@ Cstruct.of_string payload + + +let decode blob = + let open Option in + blob |> Cstruct.of_string |> Base64.decode >>| Cstruct.to_string diff --git a/lib/encoding.mli b/lib/encoding.mli new file mode 100644 index 0000000..7fa7229 --- /dev/null +++ b/lib/encoding.mli @@ -0,0 +1,3 @@ +val encode : string -> string + +val decode : string -> string option diff --git a/lib/encryption.ml b/lib/encryption.ml index 6533979..6c9014d 100644 --- a/lib/encryption.ml +++ b/lib/encryption.ml @@ -22,7 +22,8 @@ let encrypt msg ~pass = let proof = Hash.mine pass ~difficulty:5 in let key = of_secret proof in let iv = __compute_iv proof in - let result = encrypt ~iv ~key (Utils.pad ~basis:16 msg) in + let blob = Utils.pad ~basis:16 msg in + let result = encrypt ~iv ~key blob in result |> Base64.encode |> Cstruct.to_string @@ -32,6 +33,4 @@ let decrypt cipher ~pass = let iv = __compute_iv proof in let result = cipher |> Cstruct.of_string |> Base64.decode in let open Option in - result - >>= fun msg -> - msg |> decrypt ~iv ~key |> Cstruct.to_string |> Utils.unpad |> some + result >>= fun msg -> msg |> decrypt ~iv ~key |> Utils.unpad |> some diff --git a/lib/keys.ml b/lib/keys.ml index 8d87051..c94b556 100644 --- a/lib/keys.ml +++ b/lib/keys.ml @@ -3,6 +3,7 @@ module String = Core.String module Float = Core.Float module Int64 = Core.Int64 module Option = Core.Option +module Base64 = Nocrypto.Base64 module Defer = Utils.Defer let generate () = Random.generate512 () @@ -14,26 +15,51 @@ let genpub priv = List.map pieces ~f:__force_digest -let derive priv = Utils.bytes_of_string @@ Serialization.digest @@ genpub priv +let derive priv = Utils.bytes_of_hex @@ Serialization.digest @@ genpub priv -let export ~priv ~pass = Encryption.encrypt ~pass @@ Utils.bytes_to_string priv +let export ~priv ~pass = + let priv' = Bytes.to_string priv in + let payload = Encoding.encode priv' in + Encryption.encrypt ~pass payload -let validate_key plain = - if String.length plain == Utils._HASH_LENGTH then Some plain else None + +let validate_key blob = + try + let plain = + blob + |> Cstruct.of_string + |> Base64.decode + |> (fun opt -> Option.value_exn opt) + |> Cstruct.to_string + in + let parts = + String.split ~on:'\n' plain + |> List.map ~f:Cstruct.of_string + |> List.map ~f:Base64.decode + |> List.map ~f:(fun opt -> Option.value_exn opt) + |> List.map ~f:Cstruct.to_bytes + |> List.map ~f:Utils.bytes_to_hex + in + assert (Utils._HASH_LENGTH == String.length @@ List.nth_exn parts 0) ; + assert (Utils._HASH_LENGTH == String.length @@ List.nth_exn parts 1) ; + Some plain + with + | _ -> + None let import ~cipher ~pass = let open Option in - Encryption.decrypt ~pass cipher >>= validate_key >>| Utils.bytes_of_string + Encryption.decrypt ~pass cipher >>= validate_key >>| Bytes.of_string -let address pub = Utils.to_hex @@ Utils.bytes_to_string pub +let address pub = Utils.with_hex_prefix @@ Utils.bytes_to_hex pub let sign = Signing.sign let verify = Verification.verify -let show = Utils.bytes_to_string +let show = Utils.bytes_to_hex let load dump = - if Utils.is_hash dump then Some (Utils.bytes_of_string dump) else None + if Utils.is_hash dump then Some (Utils.bytes_of_hex dump) else None diff --git a/lib/main.ml b/lib/main.ml index 3844223..9b04975 100644 --- a/lib/main.ml +++ b/lib/main.ml @@ -1,10 +1,13 @@ module Option = Core.Option +module String = Core.String +module List = Core.List +module Bytes = Core.Bytes type priv = bytes type pub = bytes -let derive = Keys.derive +let __derive = Keys.derive let import = Keys.import @@ -22,36 +25,61 @@ let verify = Keys.verify (*** wrappers *****************************************************************) -let __check priv = - let pub = derive priv in - let id = "0x" ^ Utils.bytes_to_string pub in +let __decode blob = + let payload = Encoding.decode blob in + Option.value_exn payload + + +let __split priv = + let parts = String.split ~on:'\n' @@ Bytes.to_string priv in + List.map ~f:__decode parts + + +let derive priv = Bytes.of_string @@ List.nth_exn (__split priv) 1 + +let __check_tail pub = + let id = "0x" ^ Utils.bytes_to_hex pub in if Blacklist.exists id then None else Some pub -let sign ~priv ~msg = +let __check priv = __check_tail @@ __derive priv + +let check priv = __check_tail @@ derive priv + +let sign ~priv:priv' ~msg = + let priv = Bytes.of_string @@ List.nth_exn (__split priv') 0 in let success pub = let signature = sign ~priv ~msg in - Blacklist.add @@ "0x" ^ Utils.bytes_to_string pub ; + Blacklist.add @@ "0x" ^ Utils.bytes_to_hex pub ; Some signature in let open Option in - __check priv >>= success + check priv' >>= success let import ~cipher ~pass = let open Option in import ~cipher ~pass - >>= function priv -> __check priv >>= (function _ -> Some priv) + >>= function priv -> check priv >>= (function _ -> Some priv) -let rec generate () = +let rec __generate () = let priv = Keys.generate () in let const _ _ = priv in let option = __check priv in - let step = Option.value_map option ~default:generate ~f:const in + let step = Option.value_map option ~default:__generate ~f:const in step () +(* precomputed public key together with private key *) +let generate () = + let priv = __generate () in + let pub = __derive priv in + let priv' = Encoding.encode @@ Bytes.to_string priv in + let pub' = Encoding.encode @@ Bytes.to_string pub in + Bytes.of_string (priv' ^ "\n" ^ pub') + + let pair () = let priv = generate () in let pub = derive priv in diff --git a/lib/serialization.ml b/lib/serialization.ml index 92e145a..84bb081 100644 --- a/lib/serialization.ml +++ b/lib/serialization.ml @@ -4,7 +4,7 @@ module Option = Core.Option let show pub = pub - |> List.map ~f:Utils.bytes_to_string + |> List.map ~f:Utils.bytes_to_hex |> List.reduce_exn ~f:Utils.concat_hashes @@ -12,7 +12,7 @@ let load text = let list = String.split text ~on:':' in let open Option in Utils.validate_key list - >>= fun list -> some @@ List.map ~f:Utils.bytes_of_string list + >>= fun list -> some @@ List.map ~f:Utils.bytes_of_hex list let digest pub = pub |> show |> Hash.digest diff --git a/lib/signing.ml b/lib/signing.ml index 8dd5898..214e944 100644 --- a/lib/signing.ml +++ b/lib/signing.ml @@ -2,7 +2,7 @@ module List = Core.List module Defer = Utils.Defer let digest_to_string lazy_bytes = - Utils.bytes_to_string @@ Hash.digest_bytes @@ Defer.force lazy_bytes + Utils.bytes_to_hex @@ Hash.digest_bytes @@ Defer.force lazy_bytes let sign ~priv ~msg = diff --git a/lib/utils.ml b/lib/utils.ml index 4f2b195..1f11fcd 100644 --- a/lib/utils.ml +++ b/lib/utils.ml @@ -4,6 +4,8 @@ module Char = Core.Char module Int = Core.Int module Lazy = Core.Lazy module Str = Re.Str +module Option = Core.Option +module Base64 = Nocrypto.Base64 module Defer = struct let force = Lazy.force_val @@ -11,11 +13,9 @@ module Defer = struct let bind deferred ~f = lazy (force @@ f @@ force deferred) end -let bytes_of_string string = Cstruct.to_bytes @@ Cstruct.of_hex string - -let bytes_to_string bytes = - Hex.show @@ Hex.of_cstruct @@ Cstruct.of_bytes bytes +let bytes_of_hex string = Cstruct.to_bytes @@ Cstruct.of_hex string +let bytes_to_hex bytes = Hex.show @@ Hex.of_cstruct @@ Cstruct.of_bytes bytes (* 16 hex chars and 128 chars/string length for hash under hex string format *) let _HASH_LENGTH = 128 @@ -47,12 +47,12 @@ let validate_key list = if List.length filtered = _KEY_LENGTH then Some list else None -let to_hex text = "0x" ^ text +let with_hex_prefix text = "0x" ^ text let calculate_index (position, key) = (position * _HEX_SPACE) + key let index_at ~list position = - bytes_to_string @@ Defer.force @@ List.nth_exn list position + bytes_to_hex @@ Defer.force @@ List.nth_exn list position let replace_index ~matrix pairs = List.map pairs ~f:(index_at ~list:matrix) @@ -72,7 +72,7 @@ let verify_with ~matrix ~digest pairs = let concat_hashes left right = left ^ ":" ^ right let char_to_hex_int index char = - let value = char |> Char.to_string |> to_hex |> Int.of_string in + let value = char |> Char.to_string |> with_hex_prefix |> Int.of_string in (index, value) @@ -93,7 +93,7 @@ let pad ~basis msg = let nonzero char = char != nullchar -let unpad msg = String.filter ~f:nonzero msg +let unpad msg = String.filter ~f:nonzero @@ Cstruct.to_string msg let digest_hex_string hex = hex diff --git a/lib/utils.mli b/lib/utils.mli index eec9d7e..b954cb2 100644 --- a/lib/utils.mli +++ b/lib/utils.mli @@ -10,7 +10,7 @@ val _KEY_LENGTH : int val is_hash : string -> bool -val to_hex : string -> string +val with_hex_prefix : string -> string val concat_hashes : string -> string -> string @@ -30,10 +30,10 @@ val verify_with : val pad : basis:int -> string -> Cstruct.t -val unpad : string -> string +val unpad : Cstruct.t -> string -val bytes_of_string : string -> bytes +val bytes_of_hex : string -> bytes -val bytes_to_string : bytes -> string +val bytes_to_hex : bytes -> string val digest_hex_string : string -> string diff --git a/lib/verification.ml b/lib/verification.ml index f75e34c..d310d2b 100644 --- a/lib/verification.ml +++ b/lib/verification.ml @@ -5,7 +5,7 @@ module Defer = Utils.Defer let digest = Utils.digest_hex_string -let delay_string_cast bytes = lazy (Utils.bytes_to_string bytes) +let delay_string_cast bytes = lazy (Utils.bytes_to_hex bytes) let verify ~pub ~msg ~signature = try @@ -21,6 +21,8 @@ let verify ~pub ~msg ~signature = if verified then let fingerprint = Serialization.digest ver_key_bytes in - fingerprint = Utils.bytes_to_string pub + fingerprint = Utils.bytes_to_hex pub else false - with _ -> false + with + | _ -> + false From 5b2246da8ae8ece407aa1beb340f13ab2fe5b1f9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marco=20Aur=C3=A9lio=20da=20Silva?= Date: Sat, 14 Sep 2019 23:02:39 -0300 Subject: [PATCH 14/29] refactor: :recycle: separated module Constants to deal with configuration and environment variables MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Marco Aurélio da Silva --- Makefile | 9 +++++++-- lib/constants.ml | 15 +++++++++++++++ lib/constants.mli | 3 +++ lib/encryption.ml | 4 ++-- lib/store.ml | 8 ++------ 5 files changed, 29 insertions(+), 10 deletions(-) create mode 100644 lib/constants.ml create mode 100644 lib/constants.mli diff --git a/Makefile b/Makefile index 837d058..0a00a17 100644 --- a/Makefile +++ b/Makefile @@ -37,9 +37,12 @@ doc: build # - ALCOTEST_QUICK_TESTS=1 # - ALCOTEST_SHOW_ERRORS=1 # -test: build +spec-test: build dune build @test/spec/runtest -f --no-buffer -j 1 +test: + HIEROGLYPHS_KEY_DIFFICULTY=3 make spec-test + bench: clean build opam install core_bench --yes opam depext conf-secp256k1 secp256k1 --install --yes @@ -57,7 +60,9 @@ coverage: clean rm -rf docs/coverage rm -vf `find . -name 'bisect*.out'` mkdir -p docs/coverage - BISECT_ENABLE=YES make test + BISECT_ENABLE=YES \ + HIEROGLYPHS_KEY_DIFFICULTY=3 \ + make spec-test bisect-ppx-report -html coverage/ -I _build/default `find . -name 'bisect*.out'` make doc-index mv coverage/* docs/coverage/ diff --git a/lib/constants.ml b/lib/constants.ml new file mode 100644 index 0000000..091315e --- /dev/null +++ b/lib/constants.ml @@ -0,0 +1,15 @@ +module Sys = Core.Sys +module Option = Core.Option +module Int = Core.Int + +let get variable default = + let optional = Sys.getenv variable in + Option.value optional ~default + + +let _ROOT = + let default = Sys.getenv_exn "HOME" ^ "/.hieroglyphs" in + get "HIEROGLYPHS_ROOT" default + + +let _KEY_DIFFICULTY = get "HIEROGLYPHS_KEY_DIFFICULTY" "5" |> Int.of_string diff --git a/lib/constants.mli b/lib/constants.mli new file mode 100644 index 0000000..0eb592a --- /dev/null +++ b/lib/constants.mli @@ -0,0 +1,3 @@ +val _ROOT : string + +val _KEY_DIFFICULTY : int diff --git a/lib/encryption.ml b/lib/encryption.ml index 6c9014d..a2639fe 100644 --- a/lib/encryption.ml +++ b/lib/encryption.ml @@ -19,7 +19,7 @@ let __compute_iv cstruct = let encrypt msg ~pass = - let proof = Hash.mine pass ~difficulty:5 in + let proof = Hash.mine pass ~difficulty:Constants._KEY_DIFFICULTY in let key = of_secret proof in let iv = __compute_iv proof in let blob = Utils.pad ~basis:16 msg in @@ -28,7 +28,7 @@ let encrypt msg ~pass = let decrypt cipher ~pass = - let proof = Hash.mine pass ~difficulty:5 in + let proof = Hash.mine pass ~difficulty:Constants._KEY_DIFFICULTY in let key = of_secret proof in let iv = __compute_iv proof in let result = cipher |> Cstruct.of_string |> Base64.decode in diff --git a/lib/store.ml b/lib/store.ml index c18e7a7..10299a5 100644 --- a/lib/store.ml +++ b/lib/store.ml @@ -4,11 +4,7 @@ module Sys = Core.Sys open Lwt.Infix module GitStore = Irmin_unix.Git.FS.KV (Irmin.Contents.String) -let _HIEROGLYPHS_ROOT = - let root = Sys.getenv "HIEROGLYPHS_ROOT" in - let default = Sys.getenv_exn "HOME" ^ "/.hieroglyphs" in - Option.value root ~default - +let _HIEROGLYPHS_ROOT = Constants._ROOT let _HIEROGLYPHS_STORE = _HIEROGLYPHS_ROOT ^ "/state" @@ -43,7 +39,7 @@ let get ~key = let boot () = let date = 946684800L (* Sat Jan 1 00:00:00 2000 +0000 *) in let address = "0x" ^ String.make Utils._HASH_LENGTH '0' in - let path = ["blacklist"; address] in + let path = [ "blacklist"; address ] in let msg = "Revoking private key for public key " ^ address ^ "." in let info = Core.const (Irmin.Info.v ~date ~author msg) in let transaction () = From 61cbbee0acdcafdc84bb61851b85cf2f2603779f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marco=20Aur=C3=A9lio=20da=20Silva?= Date: Sat, 28 Sep 2019 20:29:34 -0300 Subject: [PATCH 15/29] refactor: :recycle: moving pieces verification/comparison procedure from Utils module into Verification module itself MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Marco Aurélio da Silva --- lib/utils.ml | 12 ------------ lib/utils.mli | 6 ------ lib/verification.ml | 14 +++++++++++++- 3 files changed, 13 insertions(+), 19 deletions(-) diff --git a/lib/utils.ml b/lib/utils.ml index 1f11fcd..a5b9793 100644 --- a/lib/utils.ml +++ b/lib/utils.ml @@ -57,18 +57,6 @@ let index_at ~list position = let replace_index ~matrix pairs = List.map pairs ~f:(index_at ~list:matrix) -let verify_at ~digest ~list (position, opening) = - let commitment = Defer.force @@ List.nth_exn list position in - let hash = digest opening in - hash = commitment - - -let verify_with ~matrix ~digest pairs = - pairs - |> List.map ~f:(verify_at ~digest ~list:matrix) - |> List.reduce_exn ~f:( && ) - - let concat_hashes left right = left ^ ":" ^ right let char_to_hex_int index char = diff --git a/lib/utils.mli b/lib/utils.mli index b954cb2..e0c4977 100644 --- a/lib/utils.mli +++ b/lib/utils.mli @@ -22,12 +22,6 @@ val replace_index : matrix:bytes Lazy.t list -> int list -> string list val indexed_keys : string -> int list -val verify_with : - matrix:string Lazy.t list - -> digest:(string -> string) - -> (int * string) list - -> bool - val pad : basis:int -> string -> Cstruct.t val unpad : Cstruct.t -> string diff --git a/lib/verification.ml b/lib/verification.ml index d310d2b..c999ebd 100644 --- a/lib/verification.ml +++ b/lib/verification.ml @@ -3,6 +3,18 @@ module List = Core.List module Option = Core.Option module Defer = Utils.Defer +let __verify_at ~digest ~list (position, opening) = + let commitment = Defer.force @@ List.nth_exn list position in + let hash = digest opening in + hash = commitment + + +let __verify_with ~matrix ~digest pairs = + pairs + |> List.map ~f:(__verify_at ~digest ~list:matrix) + |> List.reduce_exn ~f:( && ) + + let digest = Utils.digest_hex_string let delay_string_cast bytes = lazy (Utils.bytes_to_hex bytes) @@ -17,7 +29,7 @@ let verify ~pub ~msg ~signature = let ver_key = List.map ~f:delay_string_cast ver_key_bytes in let indexed_keys = Utils.indexed_keys msg in let proofs = List.zip_exn indexed_keys ver_text in - let verified = Utils.verify_with ~matrix:ver_key ~digest proofs in + let verified = __verify_with ~matrix:ver_key ~digest proofs in if verified then let fingerprint = Serialization.digest ver_key_bytes in From bacf7f2849e88923bb6bcc3d78d756c825b009a1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marco=20Aur=C3=A9lio=20da=20Silva?= Date: Sat, 28 Sep 2019 23:25:45 -0300 Subject: [PATCH 16/29] refactor: :recycle: improved xor usage in specific and safe contexts MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Marco Aurélio da Silva --- lib/encryption.ml | 6 +++--- lib/utils.ml | 8 ++++++-- lib/utils.mli | 2 ++ 3 files changed, 11 insertions(+), 5 deletions(-) diff --git a/lib/encryption.ml b/lib/encryption.ml index a2639fe..e7d7d57 100644 --- a/lib/encryption.ml +++ b/lib/encryption.ml @@ -13,9 +13,9 @@ let __compute_iv cstruct = (* then split 32 bytes into a pair of 16 *) let blob3, blob4 = Cstruct.split blob1 16 in let blob5, blob6 = Cstruct.split blob2 16 in - let blob7 = Nocrypto.Uncommon.Cs.xor blob3 blob4 in - let blob8 = Nocrypto.Uncommon.Cs.xor blob5 blob6 in - Nocrypto.Uncommon.Cs.xor blob7 blob8 + let blob7 = Utils.cxor blob3 blob4 in + let blob8 = Utils.cxor blob5 blob6 in + Utils.cxor blob7 blob8 let encrypt msg ~pass = diff --git a/lib/utils.ml b/lib/utils.ml index a5b9793..c6291af 100644 --- a/lib/utils.ml +++ b/lib/utils.ml @@ -13,6 +13,8 @@ module Defer = struct let bind deferred ~f = lazy (force @@ f @@ force deferred) end +let cxor = Nocrypto.Uncommon.Cs.xor + let bytes_of_hex string = Cstruct.to_bytes @@ Cstruct.of_hex string let bytes_to_hex bytes = Hex.show @@ Hex.of_cstruct @@ Cstruct.of_bytes bytes @@ -30,10 +32,12 @@ let is_hash text = Str.string_match regexp text 0 && String.length text = _HASH_LENGTH -let _int_to_cstruct number = lazy (Cstruct.of_string @@ string_of_int number) +let _int_to_cstruct number = + lazy (Nocrypto.Numeric.Z.to_cstruct_be @@ Z.of_int number) + let _hash_both ~digest prefix suffix = - lazy (digest @@ Cstruct.to_bytes @@ Cstruct.append prefix suffix) + lazy (digest @@ Cstruct.to_bytes @@ cxor prefix suffix) let generate_pieces ~digest random = diff --git a/lib/utils.mli b/lib/utils.mli index e0c4977..8403429 100644 --- a/lib/utils.mli +++ b/lib/utils.mli @@ -4,6 +4,8 @@ module Defer : sig val bind : 'a Lazy.t -> f:('a -> 'b Lazy.t) -> 'b Lazy.t end +val cxor : Cstruct.t -> Cstruct.t -> Cstruct.t + val _HASH_LENGTH : int val _KEY_LENGTH : int From f1622392a89a33472406518a60e4e22d9fa768ef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marco=20Aur=C3=A9lio=20da=20Silva?= Date: Sun, 29 Sep 2019 11:57:13 -0300 Subject: [PATCH 17/29] wip: :construction: adding winternitz compression with parameter w = 8 bits (still needs winternitz checksum to protect against byte flip attacks) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Marco Aurélio da Silva --- lib/hash.ml | 20 +++++++++++------- lib/hash.mli | 4 ++-- lib/keys.ml | 5 ++++- lib/signing.ml | 23 ++++++--------------- lib/utils.ml | 49 +++++++++++++++++++++++---------------------- lib/utils.mli | 13 +++++++----- lib/verification.ml | 37 ++++++++++------------------------ test/spec/sign.ml | 22 +++++--------------- 8 files changed, 74 insertions(+), 99 deletions(-) diff --git a/lib/hash.ml b/lib/hash.ml index 6df465c..7ebe12c 100644 --- a/lib/hash.ml +++ b/lib/hash.ml @@ -1,18 +1,24 @@ module Bytes = Core.Bytes -let digest text = - text |> Digestif.BLAKE2B.digest_string |> Digestif.BLAKE2B.to_hex +let rec __digest_string_steps count message = + if count <= 0 + then message + else + let digest = Digestif.BLAKE2B.digest_string message in + __digest_string_steps (count - 1) @@ Digestif.BLAKE2B.to_raw_string digest -let digest_bytes bytes = - bytes - |> Digestif.BLAKE2B.digest_bytes - |> Digestif.BLAKE2B.to_raw_string - |> Bytes.of_string +let digest ?(steps = 1) text = + text |> __digest_string_steps steps |> Hex.of_string |> Hex.show + + +let digest_bytes ~steps bytes = + bytes |> Bytes.to_string |> __digest_string_steps steps |> Bytes.of_string let __digest message = Nocrypto.Hash.SHA256.digest message +(* TODO: use scrypt KDF here *) let rec __mining input pattern nonce = let length = Core.String.length pattern in let salt = Nocrypto.Numeric.Z.to_cstruct_be nonce in diff --git a/lib/hash.mli b/lib/hash.mli index 02ed249..bebdc03 100644 --- a/lib/hash.mli +++ b/lib/hash.mli @@ -1,5 +1,5 @@ -val digest : string -> string +val digest : ?steps:int -> string -> string -val digest_bytes : bytes -> bytes +val digest_bytes : steps:int -> bytes -> bytes val mine : difficulty:int -> string -> Cstruct.t diff --git a/lib/keys.ml b/lib/keys.ml index c94b556..95fa102 100644 --- a/lib/keys.ml +++ b/lib/keys.ml @@ -8,7 +8,9 @@ module Defer = Utils.Defer let generate () = Random.generate512 () -let __force_digest lazy_piece = Hash.digest_bytes @@ Defer.force lazy_piece +let __force_digest lazy_piece = + Hash.digest_bytes ~steps:255 @@ Defer.force lazy_piece + let genpub priv = let pieces = Utils.generate_pieces ~digest:Hash.digest_bytes priv in @@ -23,6 +25,7 @@ let export ~priv ~pass = Encryption.encrypt ~pass payload +(* validates both private and public keys *) let validate_key blob = try let plain = diff --git a/lib/signing.ml b/lib/signing.ml index 214e944..00a6f2f 100644 --- a/lib/signing.ml +++ b/lib/signing.ml @@ -1,20 +1,9 @@ module List = Core.List module Defer = Utils.Defer -let digest_to_string lazy_bytes = - Utils.bytes_to_hex @@ Hash.digest_bytes @@ Defer.force lazy_bytes - - -let sign ~priv ~msg = - let priv' = Utils.generate_pieces ~digest:Hash.digest_bytes priv in - let ver_key = - List.map priv' ~f:digest_to_string - |> List.reduce_exn ~f:Utils.concat_hashes - in - let ver_text = - msg - |> Utils.indexed_keys - |> Utils.replace_index ~matrix:priv' - |> List.reduce_exn ~f:Utils.concat_hashes - in - ver_text ^ "\n" ^ ver_key +let sign ~priv:seed ~msg = + let priv = Utils.generate_pieces ~digest:Hash.digest_bytes seed in + msg + |> Utils.indexed_keys + |> Utils.replace_index ~digest:Hash.digest_bytes ~matrix:priv + |> List.reduce_exn ~f:Utils.concat_hashes diff --git a/lib/utils.ml b/lib/utils.ml index c6291af..f020915 100644 --- a/lib/utils.ml +++ b/lib/utils.ml @@ -26,6 +26,8 @@ let _HEX_SPACE = 16 let _KEY_LENGTH = _HEX_SPACE * _HASH_LENGTH +let _BYTES_LENGTH = 64 + let regexp = Str.regexp "^[a-f0-9]+$" let is_hash text = @@ -40,38 +42,46 @@ let _hash_both ~digest prefix suffix = lazy (digest @@ Cstruct.to_bytes @@ cxor prefix suffix) -let generate_pieces ~digest random = +type digest = steps:int -> bytes -> bytes + +(* random is our seed for the signing keys *) +(* TODO: use HMAC/BLAKE-MAC here for a perfect PRF *) +let generate_pieces ~(digest : digest) random = + let digest' = digest ~steps:1 in let blob = Cstruct.of_bytes random in - let nums = List.init _KEY_LENGTH ~f:_int_to_cstruct in - List.map nums ~f:(Defer.bind ~f:(_hash_both ~digest blob)) + let nums = List.init _BYTES_LENGTH ~f:_int_to_cstruct in + List.map nums ~f:(Defer.bind ~f:(_hash_both ~digest:digest' blob)) let validate_key list = let filtered = List.filter list ~f:is_hash in - if List.length filtered = _KEY_LENGTH then Some list else None + if List.length filtered = _BYTES_LENGTH then Some list else None let with_hex_prefix text = "0x" ^ text -let calculate_index (position, key) = (position * _HEX_SPACE) + key +let index_at ~(digest : digest) ~list (position, code) = + bytes_to_hex + @@ digest ~steps:code + @@ Defer.force + @@ List.nth_exn list position -let index_at ~list position = - bytes_to_hex @@ Defer.force @@ List.nth_exn list position +let replace_index ~(digest : digest) ~matrix pairs = + List.map pairs ~f:(index_at ~digest ~list:matrix) -let replace_index ~matrix pairs = List.map pairs ~f:(index_at ~list:matrix) let concat_hashes left right = left ^ ":" ^ right -let char_to_hex_int index char = - let value = char |> Char.to_string |> with_hex_prefix |> Int.of_string in - (index, value) - - -let chained_index index value = calculate_index @@ char_to_hex_int index value +let chained_index index value = (index, Char.to_int value) let indexed_keys msg = - msg |> Hash.digest |> String.to_list |> List.mapi ~f:chained_index + msg + |> Bytes.of_string + |> Hash.digest_bytes ~steps:1 + |> Bytes.to_string + |> String.to_list + |> List.mapi ~f:chained_index let nullchar = Char.of_int_exn 0 @@ -86,12 +96,3 @@ let pad ~basis msg = let nonzero char = char != nullchar let unpad msg = String.filter ~f:nonzero @@ Cstruct.to_string msg - -let digest_hex_string hex = - hex - |> Cstruct.of_hex - |> Cstruct.to_bytes - |> Hash.digest_bytes - |> Cstruct.of_bytes - |> Hex.of_cstruct - |> Hex.show diff --git a/lib/utils.mli b/lib/utils.mli index 8403429..a0d506c 100644 --- a/lib/utils.mli +++ b/lib/utils.mli @@ -18,11 +18,16 @@ val concat_hashes : string -> string -> string val validate_key : string list -> string list option -val generate_pieces : digest:(bytes -> bytes) -> bytes -> bytes Lazy.t list +val generate_pieces : + digest:(steps:int -> bytes -> bytes) -> bytes -> bytes Lazy.t list -val replace_index : matrix:bytes Lazy.t list -> int list -> string list +val replace_index : + digest:(steps:int -> bytes -> bytes) + -> matrix:bytes Lazy.t list + -> (int * int) list + -> string list -val indexed_keys : string -> int list +val indexed_keys : string -> (int * int) list val pad : basis:int -> string -> Cstruct.t @@ -31,5 +36,3 @@ val unpad : Cstruct.t -> string val bytes_of_hex : string -> bytes val bytes_to_hex : bytes -> string - -val digest_hex_string : string -> string diff --git a/lib/verification.ml b/lib/verification.ml index c999ebd..50256fd 100644 --- a/lib/verification.ml +++ b/lib/verification.ml @@ -3,38 +3,23 @@ module List = Core.List module Option = Core.Option module Defer = Utils.Defer -let __verify_at ~digest ~list (position, opening) = - let commitment = Defer.force @@ List.nth_exn list position in - let hash = digest opening in - hash = commitment +let __compute_digest (cell, (_, value)) = + Hash.digest_bytes ~steps:(255 - value) cell -let __verify_with ~matrix ~digest pairs = - pairs - |> List.map ~f:(__verify_at ~digest ~list:matrix) - |> List.reduce_exn ~f:( && ) +let __compute_root cells pairs = + List.zip_exn cells pairs + |> List.map ~f:__compute_digest + |> Serialization.digest -let digest = Utils.digest_hex_string - -let delay_string_cast bytes = lazy (Utils.bytes_to_hex bytes) - let verify ~pub ~msg ~signature = try - let parts = String.split signature ~on:'\n' in - let ver_text = List.nth_exn parts 0 |> String.split ~on:':' in - let ver_key_bytes = - Option.value_exn (Serialization.load @@ List.nth_exn parts 1) - in - let ver_key = List.map ~f:delay_string_cast ver_key_bytes in - let indexed_keys = Utils.indexed_keys msg in - let proofs = List.zip_exn indexed_keys ver_text in - let verified = __verify_with ~matrix:ver_key ~digest proofs in - if verified - then - let fingerprint = Serialization.digest ver_key_bytes in - fingerprint = Utils.bytes_to_hex pub - else false + let cells = Option.value_exn (Serialization.load signature) in + let pairs = Utils.indexed_keys msg in + let root = __compute_root cells pairs in + let fingerprint = Utils.bytes_to_hex pub in + root = fingerprint with | _ -> false diff --git a/test/spec/sign.ml b/test/spec/sign.ml index 51045e4..5b7f318 100644 --- a/test/spec/sign.ml +++ b/test/spec/sign.ml @@ -15,23 +15,10 @@ let __signature_validation () = let msg = "Yadda yadda yadda" in let priv = Hg.generate () in let signature = sign ~priv ~msg in - let parts = String.split ~on:'\n' signature in - let vertext = List.nth_exn parts 0 in - let verkey = List.nth_exn parts 1 in - let chunks = String.split ~on:':' vertext in + let chunks = String.split ~on:':' signature in let filtered = List.filter ~f:Utils.is_hash chunks in - Alcotest.(check int) "valid signature size" (List.length chunks) 128 ; - Alcotest.(check int) "valid chunks in signature" (List.length filtered) 128 ; - let chunks = String.split ~on:':' verkey in - let filtered = List.filter ~f:Utils.is_hash chunks in - Alcotest.(check int) - "valid verification key size" - (List.length chunks) - (128 * 16) ; - Alcotest.(check int) - "valid chunks in verification key" - (List.length filtered) - (128 * 16) + Alcotest.(check int) "valid signature size" (List.length chunks) 64 ; + Alcotest.(check int) "valid chunks in signature" (List.length filtered) 64 let __signing_and_verification () = @@ -104,4 +91,5 @@ let __one_time_signing () = let suite = [ ("signature validation size and format", `Quick, __signature_validation) ; ("signing and verification must match", `Quick, __signing_and_verification) - ; ("signing must be performed only once", `Slow, __one_time_signing) ] + ; ("signing must be performed only once", `Slow, __one_time_signing) + ] From 21a1d75a7cbd01deecf3d855b2dc710134a63496 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marco=20Aur=C3=A9lio=20da=20Silva?= Date: Sun, 29 Sep 2019 15:27:33 -0300 Subject: [PATCH 18/29] refactor: :recycle: padding "PRF" indexes with leading zeroes prior xoring-and-hashing against secret seed MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Marco Aurélio da Silva --- lib/utils.ml | 21 ++++++++++++++------- lib/utils.mli | 4 +++- 2 files changed, 17 insertions(+), 8 deletions(-) diff --git a/lib/utils.ml b/lib/utils.ml index f020915..fd3b654 100644 --- a/lib/utils.ml +++ b/lib/utils.ml @@ -13,6 +13,8 @@ module Defer = struct let bind deferred ~f = lazy (force @@ f @@ force deferred) end +let nullchar = Char.of_int_exn 0 + let cxor = Nocrypto.Uncommon.Cs.xor let bytes_of_hex string = Cstruct.to_bytes @@ Cstruct.of_hex string @@ -22,10 +24,6 @@ let bytes_to_hex bytes = Hex.show @@ Hex.of_cstruct @@ Cstruct.of_bytes bytes (* 16 hex chars and 128 chars/string length for hash under hex string format *) let _HASH_LENGTH = 128 -let _HEX_SPACE = 16 - -let _KEY_LENGTH = _HEX_SPACE * _HASH_LENGTH - let _BYTES_LENGTH = 64 let regexp = Str.regexp "^[a-f0-9]+$" @@ -34,8 +32,19 @@ let is_hash text = Str.string_match regexp text 0 && String.length text = _HASH_LENGTH +let pad_cstruct size input = + let padding = String.make size nullchar in + let blob = Cstruct.to_string input in + let padded = String.rev (padding ^ blob) in + let strip = String.sub ~pos:0 ~len:size padded in + Cstruct.of_string @@ String.rev strip + + let _int_to_cstruct number = - lazy (Nocrypto.Numeric.Z.to_cstruct_be @@ Z.of_int number) + lazy + ( pad_cstruct _BYTES_LENGTH + @@ Nocrypto.Numeric.Z.to_cstruct_be + @@ Z.of_int number ) let _hash_both ~digest prefix suffix = @@ -84,8 +93,6 @@ let indexed_keys msg = |> List.mapi ~f:chained_index -let nullchar = Char.of_int_exn 0 - let pad ~basis msg = let length = String.length msg in let remainder = Int.( % ) length basis in diff --git a/lib/utils.mli b/lib/utils.mli index a0d506c..7a1763a 100644 --- a/lib/utils.mli +++ b/lib/utils.mli @@ -8,7 +8,7 @@ val cxor : Cstruct.t -> Cstruct.t -> Cstruct.t val _HASH_LENGTH : int -val _KEY_LENGTH : int +val _BYTES_LENGTH : int val is_hash : string -> bool @@ -29,6 +29,8 @@ val replace_index : val indexed_keys : string -> (int * int) list +val pad_cstruct : int -> Cstruct.t -> Cstruct.t + val pad : basis:int -> string -> Cstruct.t val unpad : Cstruct.t -> string From 526ad348087e73b654f2105f1efa1ddbc7539c35 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marco=20Aur=C3=A9lio=20da=20Silva?= Date: Sun, 29 Sep 2019 16:13:17 -0300 Subject: [PATCH 19/29] ft: :star: adding winternitz checksum by adding more 2 bytes into signing keys, signature and verification keys (64 bytes of message plus 2 checksum bytes to protect against byte flip attacks) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Marco Aurélio da Silva --- lib/checksum.ml | 27 +++++++++++++++++++++++++++ lib/checksum.mli | 1 + lib/signing.ml | 2 ++ lib/utils.ml | 17 ++++++++--------- lib/utils.mli | 2 +- lib/verification.ml | 3 ++- test/spec/sign.ml | 4 ++-- 7 files changed, 43 insertions(+), 13 deletions(-) create mode 100644 lib/checksum.ml create mode 100644 lib/checksum.mli diff --git a/lib/checksum.ml b/lib/checksum.ml new file mode 100644 index 0000000..19af6cf --- /dev/null +++ b/lib/checksum.ml @@ -0,0 +1,27 @@ +module List = Core.List +module Bytes = Core.Bytes +module Char = Core.Char +module Int = Core.Int + +let __compute_diff byte = 255 - Char.to_int byte + +let __compute_sum input = + input + |> Bytes.to_list + |> List.map ~f:__compute_diff + |> List.reduce_exn ~f:( + ) + + +let __generate input = + let number = Z.of_int @@ __compute_sum input in + Cstruct.to_bytes + @@ Utils.pad_cstruct 2 + @@ Nocrypto.Numeric.Z.to_cstruct_be number + + +let make_payload input = + let digest = Hash.digest_bytes ~steps:1 input in + let checksum = Bytes.to_string @@ __generate digest in + let blob = Bytes.to_string digest in + let payload = Bytes.of_string (blob ^ checksum) in + payload diff --git a/lib/checksum.mli b/lib/checksum.mli new file mode 100644 index 0000000..c3e2ef9 --- /dev/null +++ b/lib/checksum.mli @@ -0,0 +1 @@ +val make_payload : bytes -> bytes diff --git a/lib/signing.ml b/lib/signing.ml index 00a6f2f..706cb41 100644 --- a/lib/signing.ml +++ b/lib/signing.ml @@ -4,6 +4,8 @@ module Defer = Utils.Defer let sign ~priv:seed ~msg = let priv = Utils.generate_pieces ~digest:Hash.digest_bytes seed in msg + |> Bytes.of_string + |> Checksum.make_payload |> Utils.indexed_keys |> Utils.replace_index ~digest:Hash.digest_bytes ~matrix:priv |> List.reduce_exn ~f:Utils.concat_hashes diff --git a/lib/utils.ml b/lib/utils.ml index fd3b654..6761ba9 100644 --- a/lib/utils.ml +++ b/lib/utils.ml @@ -24,8 +24,12 @@ let bytes_to_hex bytes = Hex.show @@ Hex.of_cstruct @@ Cstruct.of_bytes bytes (* 16 hex chars and 128 chars/string length for hash under hex string format *) let _HASH_LENGTH = 128 +let _CHECKSUM_LENGTH = 2 + let _BYTES_LENGTH = 64 +let _KEYS_LENGTH = _BYTES_LENGTH + _CHECKSUM_LENGTH + let regexp = Str.regexp "^[a-f0-9]+$" let is_hash text = @@ -58,13 +62,13 @@ type digest = steps:int -> bytes -> bytes let generate_pieces ~(digest : digest) random = let digest' = digest ~steps:1 in let blob = Cstruct.of_bytes random in - let nums = List.init _BYTES_LENGTH ~f:_int_to_cstruct in + let nums = List.init _KEYS_LENGTH ~f:_int_to_cstruct in List.map nums ~f:(Defer.bind ~f:(_hash_both ~digest:digest' blob)) let validate_key list = let filtered = List.filter list ~f:is_hash in - if List.length filtered = _BYTES_LENGTH then Some list else None + if List.length filtered = _KEYS_LENGTH then Some list else None let with_hex_prefix text = "0x" ^ text @@ -84,13 +88,8 @@ let concat_hashes left right = left ^ ":" ^ right let chained_index index value = (index, Char.to_int value) -let indexed_keys msg = - msg - |> Bytes.of_string - |> Hash.digest_bytes ~steps:1 - |> Bytes.to_string - |> String.to_list - |> List.mapi ~f:chained_index +let indexed_keys payload = + payload |> Bytes.to_string |> String.to_list |> List.mapi ~f:chained_index let pad ~basis msg = diff --git a/lib/utils.mli b/lib/utils.mli index 7a1763a..66a7f10 100644 --- a/lib/utils.mli +++ b/lib/utils.mli @@ -27,7 +27,7 @@ val replace_index : -> (int * int) list -> string list -val indexed_keys : string -> (int * int) list +val indexed_keys : bytes -> (int * int) list val pad_cstruct : int -> Cstruct.t -> Cstruct.t diff --git a/lib/verification.ml b/lib/verification.ml index 50256fd..ababada 100644 --- a/lib/verification.ml +++ b/lib/verification.ml @@ -16,7 +16,8 @@ let __compute_root cells pairs = let verify ~pub ~msg ~signature = try let cells = Option.value_exn (Serialization.load signature) in - let pairs = Utils.indexed_keys msg in + let payload = Checksum.make_payload @@ Bytes.of_string msg in + let pairs = Utils.indexed_keys payload in let root = __compute_root cells pairs in let fingerprint = Utils.bytes_to_hex pub in root = fingerprint diff --git a/test/spec/sign.ml b/test/spec/sign.ml index 5b7f318..34ba1c5 100644 --- a/test/spec/sign.ml +++ b/test/spec/sign.ml @@ -17,8 +17,8 @@ let __signature_validation () = let signature = sign ~priv ~msg in let chunks = String.split ~on:':' signature in let filtered = List.filter ~f:Utils.is_hash chunks in - Alcotest.(check int) "valid signature size" (List.length chunks) 64 ; - Alcotest.(check int) "valid chunks in signature" (List.length filtered) 64 + Alcotest.(check int) "valid signature size" (List.length chunks) 66 ; + Alcotest.(check int) "valid chunks in signature" (List.length filtered) 66 let __signing_and_verification () = From b34d44b0a14b0ab84af34088a573937a20504104 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marco=20Aur=C3=A9lio=20da=20Silva?= Date: Sun, 29 Sep 2019 20:00:02 -0300 Subject: [PATCH 20/29] refactor: :recycle: dropping laziness 'cause it isn't useful anymore due Winternitz compression MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Marco Aurélio da Silva --- lib/keys.ml | 7 ++----- lib/signing.ml | 1 - lib/utils.ml | 22 ++++++---------------- lib/utils.mli | 10 ++-------- lib/verification.ml | 1 - 5 files changed, 10 insertions(+), 31 deletions(-) diff --git a/lib/keys.ml b/lib/keys.ml index 95fa102..809e842 100644 --- a/lib/keys.ml +++ b/lib/keys.ml @@ -4,17 +4,14 @@ module Float = Core.Float module Int64 = Core.Int64 module Option = Core.Option module Base64 = Nocrypto.Base64 -module Defer = Utils.Defer let generate () = Random.generate512 () -let __force_digest lazy_piece = - Hash.digest_bytes ~steps:255 @@ Defer.force lazy_piece - +let __digest piece = Hash.digest_bytes ~steps:255 piece let genpub priv = let pieces = Utils.generate_pieces ~digest:Hash.digest_bytes priv in - List.map pieces ~f:__force_digest + List.map pieces ~f:__digest let derive priv = Utils.bytes_of_hex @@ Serialization.digest @@ genpub priv diff --git a/lib/signing.ml b/lib/signing.ml index 706cb41..3b37a78 100644 --- a/lib/signing.ml +++ b/lib/signing.ml @@ -1,5 +1,4 @@ module List = Core.List -module Defer = Utils.Defer let sign ~priv:seed ~msg = let priv = Utils.generate_pieces ~digest:Hash.digest_bytes seed in diff --git a/lib/utils.ml b/lib/utils.ml index 6761ba9..5f994ce 100644 --- a/lib/utils.ml +++ b/lib/utils.ml @@ -7,12 +7,6 @@ module Str = Re.Str module Option = Core.Option module Base64 = Nocrypto.Base64 -module Defer = struct - let force = Lazy.force_val - - let bind deferred ~f = lazy (force @@ f @@ force deferred) -end - let nullchar = Char.of_int_exn 0 let cxor = Nocrypto.Uncommon.Cs.xor @@ -45,14 +39,13 @@ let pad_cstruct size input = let _int_to_cstruct number = - lazy - ( pad_cstruct _BYTES_LENGTH - @@ Nocrypto.Numeric.Z.to_cstruct_be - @@ Z.of_int number ) + pad_cstruct _BYTES_LENGTH + @@ Nocrypto.Numeric.Z.to_cstruct_be + @@ Z.of_int number let _hash_both ~digest prefix suffix = - lazy (digest @@ Cstruct.to_bytes @@ cxor prefix suffix) + digest @@ Cstruct.to_bytes @@ cxor prefix suffix type digest = steps:int -> bytes -> bytes @@ -63,7 +56,7 @@ let generate_pieces ~(digest : digest) random = let digest' = digest ~steps:1 in let blob = Cstruct.of_bytes random in let nums = List.init _KEYS_LENGTH ~f:_int_to_cstruct in - List.map nums ~f:(Defer.bind ~f:(_hash_both ~digest:digest' blob)) + List.map nums ~f:(_hash_both ~digest:digest' blob) let validate_key list = @@ -74,10 +67,7 @@ let validate_key list = let with_hex_prefix text = "0x" ^ text let index_at ~(digest : digest) ~list (position, code) = - bytes_to_hex - @@ digest ~steps:code - @@ Defer.force - @@ List.nth_exn list position + bytes_to_hex @@ digest ~steps:code @@ List.nth_exn list position let replace_index ~(digest : digest) ~matrix pairs = diff --git a/lib/utils.mli b/lib/utils.mli index 66a7f10..4b7d0bd 100644 --- a/lib/utils.mli +++ b/lib/utils.mli @@ -1,9 +1,3 @@ -module Defer : sig - val force : 'a Lazy.t -> 'a - - val bind : 'a Lazy.t -> f:('a -> 'b Lazy.t) -> 'b Lazy.t -end - val cxor : Cstruct.t -> Cstruct.t -> Cstruct.t val _HASH_LENGTH : int @@ -19,11 +13,11 @@ val concat_hashes : string -> string -> string val validate_key : string list -> string list option val generate_pieces : - digest:(steps:int -> bytes -> bytes) -> bytes -> bytes Lazy.t list + digest:(steps:int -> bytes -> bytes) -> bytes -> bytes list val replace_index : digest:(steps:int -> bytes -> bytes) - -> matrix:bytes Lazy.t list + -> matrix:bytes list -> (int * int) list -> string list diff --git a/lib/verification.ml b/lib/verification.ml index ababada..fea2b4b 100644 --- a/lib/verification.ml +++ b/lib/verification.ml @@ -1,7 +1,6 @@ module String = Core.String module List = Core.List module Option = Core.Option -module Defer = Utils.Defer let __compute_digest (cell, (_, value)) = Hash.digest_bytes ~steps:(255 - value) cell From a558b10623fb3708f83d28eb668e196cac00a75d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marco=20Aur=C3=A9lio=20da=20Silva?= Date: Sun, 13 Oct 2019 17:34:05 -0300 Subject: [PATCH 21/29] refactor: :recycle: precomputed null-hash and null-address MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Marco Aurélio da Silva --- lib/store.ml | 2 +- lib/utils.ml | 4 ++++ lib/utils.mli | 4 ++++ 3 files changed, 9 insertions(+), 1 deletion(-) diff --git a/lib/store.ml b/lib/store.ml index 10299a5..0066689 100644 --- a/lib/store.ml +++ b/lib/store.ml @@ -38,7 +38,7 @@ let get ~key = let boot () = let date = 946684800L (* Sat Jan 1 00:00:00 2000 +0000 *) in - let address = "0x" ^ String.make Utils._HASH_LENGTH '0' in + let address = Utils._NULL_ADDRESS in let path = [ "blacklist"; address ] in let msg = "Revoking private key for public key " ^ address ^ "." in let info = Core.const (Irmin.Info.v ~date ~author msg) in diff --git a/lib/utils.ml b/lib/utils.ml index 5f994ce..d9bbb37 100644 --- a/lib/utils.ml +++ b/lib/utils.ml @@ -92,3 +92,7 @@ let pad ~basis msg = let nonzero char = char != nullchar let unpad msg = String.filter ~f:nonzero @@ Cstruct.to_string msg + +let _NULL_HASH = String.make _HASH_LENGTH '0' + +let _NULL_ADDRESS = with_hex_prefix _NULL_HASH diff --git a/lib/utils.mli b/lib/utils.mli index 4b7d0bd..7331e62 100644 --- a/lib/utils.mli +++ b/lib/utils.mli @@ -32,3 +32,7 @@ val unpad : Cstruct.t -> string val bytes_of_hex : string -> bytes val bytes_to_hex : bytes -> string + +val _NULL_HASH : string + +val _NULL_ADDRESS : string From 19537066de5b0adb6bef33b5ddfc1b904f2a95da Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marco=20Aur=C3=A9lio=20da=20Silva?= Date: Sun, 13 Oct 2019 18:27:56 -0300 Subject: [PATCH 22/29] refactor: :recycle: inline List.map closure steps MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Marco Aurélio da Silva --- lib/checksum.ml | 7 +++---- lib/keys.ml | 27 ++++++++++++++++----------- 2 files changed, 19 insertions(+), 15 deletions(-) diff --git a/lib/checksum.ml b/lib/checksum.ml index 19af6cf..b5e9119 100644 --- a/lib/checksum.ml +++ b/lib/checksum.ml @@ -5,11 +5,10 @@ module Int = Core.Int let __compute_diff byte = 255 - Char.to_int byte +let __sum_diff x y = x + __compute_diff y + let __compute_sum input = - input - |> Bytes.to_list - |> List.map ~f:__compute_diff - |> List.reduce_exn ~f:( + ) + input |> Bytes.to_list |> List.fold ~init:0 ~f:__sum_diff let __generate input = diff --git a/lib/keys.ml b/lib/keys.ml index 809e842..e092430 100644 --- a/lib/keys.ml +++ b/lib/keys.ml @@ -22,6 +22,17 @@ let export ~priv ~pass = Encryption.encrypt ~pass payload +let __extract_optional opt = Option.value_exn opt + +let __process_parts input = + input + |> Cstruct.of_string + |> Base64.decode + |> __extract_optional + |> Cstruct.to_bytes + |> Utils.bytes_to_hex + + (* validates both private and public keys *) let validate_key blob = try @@ -29,19 +40,13 @@ let validate_key blob = blob |> Cstruct.of_string |> Base64.decode - |> (fun opt -> Option.value_exn opt) + |> __extract_optional |> Cstruct.to_string in - let parts = - String.split ~on:'\n' plain - |> List.map ~f:Cstruct.of_string - |> List.map ~f:Base64.decode - |> List.map ~f:(fun opt -> Option.value_exn opt) - |> List.map ~f:Cstruct.to_bytes - |> List.map ~f:Utils.bytes_to_hex - in - assert (Utils._HASH_LENGTH == String.length @@ List.nth_exn parts 0) ; - assert (Utils._HASH_LENGTH == String.length @@ List.nth_exn parts 1) ; + let parts = String.split ~on:'\n' plain |> List.map ~f:__process_parts in + assert ( + Utils._HASH_LENGTH == String.length @@ List.nth_exn parts 0 + && Utils._HASH_LENGTH == String.length @@ List.nth_exn parts 1 ) ; Some plain with | _ -> From faadc839a3565842495c402a09164e97a89930c2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marco=20Aur=C3=A9lio=20da=20Silva?= Date: Sun, 13 Oct 2019 19:26:35 -0300 Subject: [PATCH 23/29] refactor: :recycle: dropping recursive hashchain function in favor of a loop implementation being more GC-friendly MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Marco Aurélio da Silva --- lib/hash.ml | 16 +-- package.json | 5 +- yarn.lock | 292 +++++++++++++++++++++++++++++++++------------------ 3 files changed, 204 insertions(+), 109 deletions(-) diff --git a/lib/hash.ml b/lib/hash.ml index 7ebe12c..2ae404b 100644 --- a/lib/hash.ml +++ b/lib/hash.ml @@ -1,11 +1,15 @@ module Bytes = Core.Bytes -let rec __digest_string_steps count message = - if count <= 0 - then message - else - let digest = Digestif.BLAKE2B.digest_string message in - __digest_string_steps (count - 1) @@ Digestif.BLAKE2B.to_raw_string digest +let blake2b input = + Digestif.BLAKE2B.to_raw_string @@ Digestif.BLAKE2B.digest_string input + + +let __digest_string_steps count message = + let payload = ref message in + for _ = count downto 1 do + payload := blake2b !payload + done ; + !payload let digest ?(steps = 1) text = diff --git a/package.json b/package.json index c489abe..57d68f9 100644 --- a/package.json +++ b/package.json @@ -16,7 +16,8 @@ }, "husky": { "hooks": { - "pre-commit": "lint-staged" + "pre-commit": "lint-staged", + "pre-push": "make test" } }, "lint-staged": { @@ -41,7 +42,7 @@ }, "homepage": "https://github.com/marcoonroad/hieroglyphs#readme", "devDependencies": { - "husky": "^1.1.4", + "husky": "^3.0.9", "lint-staged": "^8.0.4" }, "dependencies": {} diff --git a/yarn.lock b/yarn.lock index 39c6edb..b227a73 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2,6 +2,22 @@ # yarn lockfile v1 +"@babel/code-frame@^7.0.0": + version "7.5.5" + resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.5.5.tgz#bc0782f6d69f7b7d49531219699b988f669a8f9d" + integrity sha512-27d4lZoomVyo51VegxI20xZPuSHusqbQag/ztrBC7wegWoQ1nLREPVSKSW8byhTlzTKyNE4ifaTA6lCp7JjpFw== + dependencies: + "@babel/highlight" "^7.0.0" + +"@babel/highlight@^7.0.0": + version "7.5.0" + resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.5.0.tgz#56d11312bd9248fa619591d02472be6e8cb32540" + integrity sha512-7dV4eu9gBxoM0dAnj/BCFDW9LFU0zvTrkq0ugM7pnHEgguOEeOz1so2ZghEdzviYzQEED0r4EAgpsBChKy1TRQ== + dependencies: + chalk "^2.0.0" + esutils "^2.0.2" + js-tokens "^4.0.0" + "@samverschueren/stream-to-observable@^0.3.0": version "0.3.0" resolved "https://registry.yarnpkg.com/@samverschueren/stream-to-observable/-/stream-to-observable-0.3.0.tgz#ecdf48d532c58ea477acfcab80348424f8d0662f" @@ -9,6 +25,11 @@ dependencies: any-observable "^0.3.0" +"@types/normalize-package-data@^2.4.0": + version "2.4.0" + resolved "https://registry.yarnpkg.com/@types/normalize-package-data/-/normalize-package-data-2.4.0.tgz#e486d0d97396d79beedd0a6e33f4534ff6b4973e" + integrity sha512-f5j5b/Gf71L+dbqxIpQ4Z2WlmI/mPJ0fOkGGmFgtb6sAu97EPczzbS3/tJKxmcYDj55OX6ssqwDAWOHIYDRDGA== + ansi-escapes@^3.0.0: version "3.1.0" resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-3.1.0.tgz#f73207bb81207d75fd6c83f125af26eea378ca30" @@ -137,11 +158,6 @@ braces@^2.3.1: split-string "^3.0.2" to-regex "^3.0.1" -builtin-modules@^1.0.0: - version "1.1.1" - resolved "https://registry.yarnpkg.com/builtin-modules/-/builtin-modules-1.1.1.tgz#270f076c5a72c02f5b65a47df94c5fe3a278892f" - integrity sha1-Jw8HbFpywC9bZaR9+Uxf46J4iS8= - cache-base@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/cache-base/-/cache-base-1.0.1.tgz#0a7f46416831c8b662ee36fe4e7c59d76f666ab2" @@ -187,6 +203,15 @@ chalk@^1.0.0, chalk@^1.1.3: strip-ansi "^3.0.0" supports-color "^2.0.0" +chalk@^2.0.0, chalk@^2.4.2: + version "2.4.2" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424" + integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ== + dependencies: + ansi-styles "^3.2.1" + escape-string-regexp "^1.0.5" + supports-color "^5.3.0" + chalk@^2.0.1, chalk@^2.3.1: version "2.4.1" resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.1.tgz#18c49ab16a037b6eb0152cc83e3471338215b66e" @@ -196,10 +221,10 @@ chalk@^2.0.1, chalk@^2.3.1: escape-string-regexp "^1.0.5" supports-color "^5.3.0" -ci-info@^1.5.0: - version "1.6.0" - resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-1.6.0.tgz#2ca20dbb9ceb32d4524a683303313f0304b1e497" - integrity sha512-vsGdkwSCDpWmP80ncATX7iea5DWQemg1UgCW5J8tqjU3lYw4FBYuj89J0CTVomA7BEfvSZd84GmHko+MxFQU2A== +ci-info@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-2.0.0.tgz#67a9e964be31a51e15e5010d58e6f12834002f46" + integrity sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ== class-utils@^0.3.5: version "0.3.6" @@ -278,7 +303,7 @@ copy-descriptor@^0.1.0: resolved "https://registry.yarnpkg.com/copy-descriptor/-/copy-descriptor-0.1.1.tgz#676f6eb3c39997c2ee1ac3a924fd6124748f578d" integrity sha1-Z29us8OZl8LuGsOpJP1hJHSPV40= -cosmiconfig@^5.0.2, cosmiconfig@^5.0.6: +cosmiconfig@^5.0.2: version "5.0.7" resolved "https://registry.yarnpkg.com/cosmiconfig/-/cosmiconfig-5.0.7.tgz#39826b292ee0d78eda137dfa3173bd1c21a43b04" integrity sha512-PcLqxTKiDmNT6pSpy4N6KtuPwb53W+2tzNvwOZw0WH9N6O0vLIBq0x8aj8Oj75ere4YcGi48bDFCL+3fRJdlNA== @@ -288,6 +313,16 @@ cosmiconfig@^5.0.2, cosmiconfig@^5.0.6: js-yaml "^3.9.0" parse-json "^4.0.0" +cosmiconfig@^5.2.1: + version "5.2.1" + resolved "https://registry.yarnpkg.com/cosmiconfig/-/cosmiconfig-5.2.1.tgz#040f726809c591e77a17c0a3626ca45b4f168b1a" + integrity sha512-H65gsXo1SKjf8zmrJ67eJk8aIRKV5ff2D4uKZIBZShbhGSpEmsQOPW/SKMKYhSTrqR7ufy6RP69rPogdaPh/kA== + dependencies: + import-fresh "^2.0.0" + is-directory "^0.3.1" + js-yaml "^3.13.1" + parse-json "^4.0.0" + cross-spawn@^6.0.0: version "6.0.5" resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-6.0.5.tgz#4a5ec7c64dfae22c3a14124dbacdee846d80cbc4" @@ -398,6 +433,11 @@ esprima@^4.0.0: resolved "https://registry.yarnpkg.com/esprima/-/esprima-4.0.1.tgz#13b04cdb3e6c5d19df91ab6987a8695619b0aa71" integrity sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A== +esutils@^2.0.2: + version "2.0.3" + resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.3.tgz#74d2eb4de0b8da1293711910d50775b9b710ef64" + integrity sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g== + execa@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/execa/-/execa-1.0.0.tgz#c6236a5bb4df6d6f15e88e7f017798216749ddd8" @@ -481,12 +521,13 @@ find-parent-dir@^0.3.0: resolved "https://registry.yarnpkg.com/find-parent-dir/-/find-parent-dir-0.3.0.tgz#33c44b429ab2b2f0646299c5f9f718f376ff8d54" integrity sha1-M8RLQpqysvBkYpnF+fcY83b/jVQ= -find-up@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/find-up/-/find-up-3.0.0.tgz#49169f1d7993430646da61ecc5ae355c21c97b73" - integrity sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg== +find-up@^4.0.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/find-up/-/find-up-4.1.0.tgz#97afe7d6cdc0bc5928584b7c8d7b16e8a9aa5d19" + integrity sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw== dependencies: - locate-path "^3.0.0" + locate-path "^5.0.0" + path-exists "^4.0.0" for-in@^1.0.2: version "1.0.2" @@ -519,10 +560,10 @@ get-own-enumerable-property-symbols@^3.0.0: resolved "https://registry.yarnpkg.com/get-own-enumerable-property-symbols/-/get-own-enumerable-property-symbols-3.0.0.tgz#b877b49a5c16aefac3655f2ed2ea5b684df8d203" integrity sha512-CIJYJC4GGF06TakLg8z4GQKvDsx9EMspVxOYih7LerEL/WosUnFIww45CGfxfeKHqlg3twgUrYRT1O3WQqjGCg== -get-stdin@^6.0.0: - version "6.0.0" - resolved "https://registry.yarnpkg.com/get-stdin/-/get-stdin-6.0.0.tgz#9e09bf712b360ab9225e812048f71fde9c89657b" - integrity sha512-jp4tHawyV7+fkkSKyvjuLZswblUtz+SQKzSWnBbii16BuZksJlU1wuBYXY75r+duh/llF1ur6oNwi+2ZzjKZ7g== +get-stdin@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/get-stdin/-/get-stdin-7.0.0.tgz#8d5de98f15171a125c5e516643c7a6d0ea8a96f6" + integrity sha512-zRKcywvrXlXsA0v0i9Io4KDRaAw7+a1ZpjRwl9Wox8PFlVCCHra7E9c4kqXCoCM9nR5tBkaTTZRBoCm60bFqTQ== get-stream@^4.0.0: version "4.1.0" @@ -603,25 +644,26 @@ has-values@^1.0.0: kind-of "^4.0.0" hosted-git-info@^2.1.4: - version "2.7.1" - resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-2.7.1.tgz#97f236977bd6e125408930ff6de3eec6281ec047" - integrity sha512-7T/BxH19zbcCTa8XkMlbK5lTo1WtgkFi3GvdWEyNuc4Vex7/9Dqbnpsf4JMydcfj9HCg4zUWFTL3Za6lapg5/w== - -husky@^1.1.4: - version "1.1.4" - resolved "https://registry.yarnpkg.com/husky/-/husky-1.1.4.tgz#92f61383527d2571e9586234e5864356bfaceaa9" - integrity sha512-cZjGpS7qsaBSo3fOMUuR7erQloX3l5XzL1v/RkIqU6zrQImDdU70z5Re9fGDp7+kbYlM2EtS4aYMlahBeiCUGw== - dependencies: - cosmiconfig "^5.0.6" + version "2.8.5" + resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-2.8.5.tgz#759cfcf2c4d156ade59b0b2dfabddc42a6b9c70c" + integrity sha512-kssjab8CvdXfcXMXVcvsXum4Hwdq9XGtRD3TteMEvEbq0LXyiNQr6AprqKqfeaDXze7SxWvRxdpwE6ku7ikLkg== + +husky@^3.0.9: + version "3.0.9" + resolved "https://registry.yarnpkg.com/husky/-/husky-3.0.9.tgz#a2c3e9829bfd6b4957509a9500d2eef5dbfc8044" + integrity sha512-Yolhupm7le2/MqC1VYLk/cNmYxsSsqKkTyBhzQHhPK1jFnC89mmmNVuGtLNabjDI6Aj8UNIr0KpRNuBkiC4+sg== + dependencies: + chalk "^2.4.2" + ci-info "^2.0.0" + cosmiconfig "^5.2.1" execa "^1.0.0" - find-up "^3.0.0" - get-stdin "^6.0.0" - is-ci "^1.2.1" - pkg-dir "^3.0.0" - please-upgrade-node "^3.1.1" - read-pkg "^4.0.1" + get-stdin "^7.0.0" + opencollective-postinstall "^2.0.2" + pkg-dir "^4.2.0" + please-upgrade-node "^3.2.0" + read-pkg "^5.2.0" run-node "^1.0.0" - slash "^2.0.0" + slash "^3.0.0" import-fresh@^2.0.0: version "2.0.0" @@ -673,20 +715,6 @@ is-buffer@^1.1.5: resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-1.1.6.tgz#efaa2ea9daa0d7ab2ea13a97b2b8ad51fefbe8be" integrity sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w== -is-builtin-module@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/is-builtin-module/-/is-builtin-module-1.0.0.tgz#540572d34f7ac3119f8f76c30cbc1b1e037affbe" - integrity sha1-VAVy0096wxGfj3bDDLwbHgN6/74= - dependencies: - builtin-modules "^1.0.0" - -is-ci@^1.2.1: - version "1.2.1" - resolved "https://registry.yarnpkg.com/is-ci/-/is-ci-1.2.1.tgz#e3779c8ee17fccf428488f6e281187f2e632841c" - integrity sha512-s6tfsaQaQi3JNciBH6shVqEDvhGut0SUXr31ag8Pd8BBbVVlcGfWhpPmEOoM6RJ5TFhbypvf5yyRw/VXW1IiWg== - dependencies: - ci-info "^1.5.0" - is-data-descriptor@^0.1.4: version "0.1.4" resolved "https://registry.yarnpkg.com/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz#0b5ee648388e2c860282e793f1856fec3f301b56" @@ -862,6 +890,19 @@ jest-validate@^23.5.0: leven "^2.1.0" pretty-format "^23.6.0" +js-tokens@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" + integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ== + +js-yaml@^3.13.1: + version "3.13.1" + resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.13.1.tgz#aff151b30bfdfa8e49e05da22e7415e9dfa37847" + integrity sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw== + dependencies: + argparse "^1.0.7" + esprima "^4.0.0" + js-yaml@^3.9.0: version "3.12.0" resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.12.0.tgz#eaed656ec8344f10f527c6bfa1b6e2244de167d1" @@ -904,6 +945,11 @@ leven@^2.1.0: resolved "https://registry.yarnpkg.com/leven/-/leven-2.1.0.tgz#c2e7a9f772094dee9d34202ae8acce4687875580" integrity sha1-wuep93IJTe6dNCAq6KzORoeHVYA= +lines-and-columns@^1.1.6: + version "1.1.6" + resolved "https://registry.yarnpkg.com/lines-and-columns/-/lines-and-columns-1.1.6.tgz#1c00c743b433cd0a4e80758f7b64a57440d9ff00" + integrity sha1-HADHQ7QzzQpOgHWPe2SldEDZ/wA= + lint-staged@^8.0.4: version "8.0.4" resolved "https://registry.yarnpkg.com/lint-staged/-/lint-staged-8.0.4.tgz#d3c909fcf7897152cdce2d6e42500cd9b5b41a0d" @@ -978,13 +1024,12 @@ listr@^0.14.2: p-map "^1.1.1" rxjs "^6.1.0" -locate-path@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-3.0.0.tgz#dbec3b3ab759758071b58fe59fc41871af21400e" - integrity sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A== +locate-path@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-5.0.0.tgz#1afba396afd676a6d42504d0a67a3a7eb9f62aa0" + integrity sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g== dependencies: - p-locate "^3.0.0" - path-exists "^3.0.0" + p-locate "^4.1.0" lodash@^4.17.5: version "4.17.11" @@ -1104,13 +1149,13 @@ nice-try@^1.0.4: resolved "https://registry.yarnpkg.com/nice-try/-/nice-try-1.0.5.tgz#a3378a7696ce7d223e88fc9b764bd7ef1089e366" integrity sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ== -normalize-package-data@^2.3.2: - version "2.4.0" - resolved "https://registry.yarnpkg.com/normalize-package-data/-/normalize-package-data-2.4.0.tgz#12f95a307d58352075a04907b84ac8be98ac012f" - integrity sha512-9jjUFbTPfEy3R/ad/2oNbKtW9Hgovl5O1FvFWKkKblNXoN/Oou6+9+KKohPK13Yc3/TyunyWhJp6gvRNR/PPAw== +normalize-package-data@^2.5.0: + version "2.5.0" + resolved "https://registry.yarnpkg.com/normalize-package-data/-/normalize-package-data-2.5.0.tgz#e66db1838b200c1dfc233225d12cb36520e234a8" + integrity sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA== dependencies: hosted-git-info "^2.1.4" - is-builtin-module "^1.0.0" + resolve "^1.10.0" semver "2 || 3 || 4 || 5" validate-npm-package-license "^3.0.1" @@ -1189,24 +1234,29 @@ onetime@^2.0.0: dependencies: mimic-fn "^1.0.0" +opencollective-postinstall@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/opencollective-postinstall/-/opencollective-postinstall-2.0.2.tgz#5657f1bede69b6e33a45939b061eb53d3c6c3a89" + integrity sha512-pVOEP16TrAO2/fjej1IdOyupJY8KDUM1CvsaScRbw6oddvpQoOfGk4ywha0HKKVAD6RkW4x6Q+tNBwhf3Bgpuw== + p-finally@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/p-finally/-/p-finally-1.0.0.tgz#3fbcfb15b899a44123b34b6dcc18b724336a2cae" integrity sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4= -p-limit@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-2.0.0.tgz#e624ed54ee8c460a778b3c9f3670496ff8a57aec" - integrity sha512-fl5s52lI5ahKCernzzIyAP0QAZbGIovtVHGwpcu1Jr/EpzLVDI2myISHwGqK7m8uQFugVWSrbxH7XnhGtvEc+A== +p-limit@^2.2.0: + version "2.2.1" + resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-2.2.1.tgz#aa07a788cc3151c939b5131f63570f0dd2009537" + integrity sha512-85Tk+90UCVWvbDavCLKPOLC9vvY8OwEX/RtKF+/1OADJMVlFfEHOiMTPVyxg7mk/dKa+ipdHm0OUkTvCpMTuwg== dependencies: p-try "^2.0.0" -p-locate@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-3.0.0.tgz#322d69a05c0264b25997d9f40cd8a891ab0064a4" - integrity sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ== +p-locate@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-4.1.0.tgz#a3428bb7088b3a60292f66919278b7c297ad4f07" + integrity sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A== dependencies: - p-limit "^2.0.0" + p-limit "^2.2.0" p-map@^1.1.1: version "1.2.0" @@ -1214,9 +1264,9 @@ p-map@^1.1.1: integrity sha512-r6zKACMNhjPJMTl8KcFH4li//gkrXWfbD6feV8l6doRHlzljFWGJ2AP6iKaCJXyZmAUMOPtvbW7EXkbWO/pLEA== p-try@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/p-try/-/p-try-2.0.0.tgz#85080bb87c64688fa47996fe8f7dfbe8211760b1" - integrity sha512-hMp0onDKIajHfIkdRk3P4CdCmErkYAxxDtP3Wx/4nZ3aGlau2VKh3mZpcuFkH27WQkL/3WBCPOktzA9ZOAnMQQ== + version "2.2.0" + resolved "https://registry.yarnpkg.com/p-try/-/p-try-2.2.0.tgz#cb2868540e313d61de58fafbe35ce9004d5540e6" + integrity sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ== parse-json@^4.0.0: version "4.0.0" @@ -1226,15 +1276,25 @@ parse-json@^4.0.0: error-ex "^1.3.1" json-parse-better-errors "^1.0.1" +parse-json@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-5.0.0.tgz#73e5114c986d143efa3712d4ea24db9a4266f60f" + integrity sha512-OOY5b7PAEFV0E2Fir1KOkxchnZNCdowAJgQ5NuxjpBKTRP3pQhwkrkxqQjeoKJ+fO7bCpmIZaogI4eZGDMEGOw== + dependencies: + "@babel/code-frame" "^7.0.0" + error-ex "^1.3.1" + json-parse-better-errors "^1.0.1" + lines-and-columns "^1.1.6" + pascalcase@^0.1.1: version "0.1.1" resolved "https://registry.yarnpkg.com/pascalcase/-/pascalcase-0.1.1.tgz#b363e55e8006ca6fe21784d2db22bd15d7917f14" integrity sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ= -path-exists@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-3.0.0.tgz#ce0ebeaa5f78cb18925ea7d810d7b59b010fd515" - integrity sha1-zg6+ql94yxiSXqfYENe1mwEP1RU= +path-exists@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-4.0.0.tgz#513bdbe2d3b95d7762e8c1137efa195c6c61b5b3" + integrity sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w== path-is-absolute@^1.0.0: version "1.0.1" @@ -1251,6 +1311,11 @@ path-key@^2.0.0, path-key@^2.0.1: resolved "https://registry.yarnpkg.com/path-key/-/path-key-2.0.1.tgz#411cadb574c5a140d3a4b1910d40d80cc9f40b40" integrity sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A= +path-parse@^1.0.6: + version "1.0.6" + resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.6.tgz#d62dbb5679405d72c4737ec58600e9ddcf06d24c" + integrity sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw== + pify@^2.0.0: version "2.3.0" resolved "https://registry.yarnpkg.com/pify/-/pify-2.3.0.tgz#ed141a6ac043a849ea588498e7dca8b15330e90c" @@ -1273,20 +1338,27 @@ pinkie@^2.0.0: resolved "https://registry.yarnpkg.com/pinkie/-/pinkie-2.0.4.tgz#72556b80cfa0d48a974e80e77248e80ed4f7f870" integrity sha1-clVrgM+g1IqXToDnckjoDtT3+HA= -pkg-dir@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-3.0.0.tgz#2749020f239ed990881b1f71210d51eb6523bea3" - integrity sha512-/E57AYkoeQ25qkxMj5PBOVgF8Kiu/h7cYS30Z5+R7WaiCCBfLq58ZI/dSeaEKb9WVJV5n/03QwrN3IeWIFllvw== +pkg-dir@^4.2.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-4.2.0.tgz#f099133df7ede422e81d1d8448270eeb3e4261f3" + integrity sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ== dependencies: - find-up "^3.0.0" + find-up "^4.0.0" -please-upgrade-node@^3.0.2, please-upgrade-node@^3.1.1: +please-upgrade-node@^3.0.2: version "3.1.1" resolved "https://registry.yarnpkg.com/please-upgrade-node/-/please-upgrade-node-3.1.1.tgz#ed320051dfcc5024fae696712c8288993595e8ac" integrity sha512-KY1uHnQ2NlQHqIJQpnh/i54rKkuxCEBx+voJIS/Mvb+L2iYd2NMotwduhKTMjfC1uKoX3VXOxLjIYG66dfJTVQ== dependencies: semver-compare "^1.0.0" +please-upgrade-node@^3.2.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/please-upgrade-node/-/please-upgrade-node-3.2.0.tgz#aeddd3f994c933e4ad98b99d9a556efa0e2fe942" + integrity sha512-gQR3WpIgNIKwBMVLkpMUeR3e1/E1y42bqDQZfql+kDeXd8COYfM8PQA4X6y7a8u9Ua9FHmsrrmirW2vHs45hWg== + dependencies: + semver-compare "^1.0.0" + posix-character-classes@^0.1.0: version "0.1.1" resolved "https://registry.yarnpkg.com/posix-character-classes/-/posix-character-classes-0.1.1.tgz#01eac0fe3b5af71a2a6c02feabb8c1fef7e00eab" @@ -1308,14 +1380,15 @@ pump@^3.0.0: end-of-stream "^1.1.0" once "^1.3.1" -read-pkg@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/read-pkg/-/read-pkg-4.0.1.tgz#963625378f3e1c4d48c85872b5a6ec7d5d093237" - integrity sha1-ljYlN48+HE1IyFhytabsfV0JMjc= +read-pkg@^5.2.0: + version "5.2.0" + resolved "https://registry.yarnpkg.com/read-pkg/-/read-pkg-5.2.0.tgz#7bf295438ca5a33e56cd30e053b34ee7250c93cc" + integrity sha512-Ug69mNOpfvKDAc2Q8DRpMjjzdtrnv9HcSMX+4VsZxD1aZ6ZzrIE7rlzXBtWTyhULSMKg076AW6WR5iZpD0JiOg== dependencies: - normalize-package-data "^2.3.2" - parse-json "^4.0.0" - pify "^3.0.0" + "@types/normalize-package-data" "^2.4.0" + normalize-package-data "^2.5.0" + parse-json "^5.0.0" + type-fest "^0.6.0" regex-not@^1.0.0, regex-not@^1.0.2: version "1.0.2" @@ -1345,6 +1418,13 @@ resolve-url@^0.2.1: resolved "https://registry.yarnpkg.com/resolve-url/-/resolve-url-0.2.1.tgz#2c637fe77c893afd2a663fe21aa9080068e2052a" integrity sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo= +resolve@^1.10.0: + version "1.12.0" + resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.12.0.tgz#3fc644a35c84a48554609ff26ec52b66fa577df6" + integrity sha512-B/dOmuoAik5bKcD6s6nXDCjzUKnaDvdkRyAk6rsmsKLipWj4797iothd7jmmUhWTfinVMU+wc56rYKsit2Qy4w== + dependencies: + path-parse "^1.0.6" + restore-cursor@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/restore-cursor/-/restore-cursor-1.0.1.tgz#34661f46886327fed2991479152252df92daa541" @@ -1397,7 +1477,12 @@ semver-compare@^1.0.0: resolved "https://registry.yarnpkg.com/semver-compare/-/semver-compare-1.0.0.tgz#0dee216a1c941ab37e9efb1788f6afc5ff5537fc" integrity sha1-De4hahyUGrN+nvsXiPavxf9VN/w= -"semver@2 || 3 || 4 || 5", semver@^5.5.0: +"semver@2 || 3 || 4 || 5": + version "5.7.1" + resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7" + integrity sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ== + +semver@^5.5.0: version "5.6.0" resolved "https://registry.yarnpkg.com/semver/-/semver-5.6.0.tgz#7e74256fbaa49c75aa7c7a205cc22799cac80004" integrity sha512-RS9R6R35NYgQn++fkDWaOmqGoj4Ek9gGs+DPxNUZKuwE183xjJroKvyo1IzVFeXvUrvmALy6FWD5xrdJT25gMg== @@ -1446,10 +1531,10 @@ simple-git@^1.85.0: dependencies: debug "^4.0.1" -slash@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/slash/-/slash-2.0.0.tgz#de552851a1759df3a8f206535442f5ec4ddeab44" - integrity sha512-ZYKh3Wh2z1PpEXWr0MpSBZ0V6mZHAQfYevttO11c51CaWjGTaadiKZ+wVt1PbMlDV5qhMFslpZCemhwOK7C89A== +slash@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/slash/-/slash-3.0.0.tgz#6539be870c165adbd5240220dbe361f1bc4d4634" + integrity sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q== slice-ansi@0.0.4: version "0.0.4" @@ -1508,9 +1593,9 @@ source-map@^0.5.6: integrity sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w= spdx-correct@^3.0.0: - version "3.0.2" - resolved "https://registry.yarnpkg.com/spdx-correct/-/spdx-correct-3.0.2.tgz#19bb409e91b47b1ad54159243f7312a858db3c2e" - integrity sha512-q9hedtzyXHr5S0A1vEPoK/7l8NpfkFYTq6iCY+Pno2ZbdZR6WexZFtqeVGkGxW3TEJMN914Z55EnAGMmenlIQQ== + version "3.1.0" + resolved "https://registry.yarnpkg.com/spdx-correct/-/spdx-correct-3.1.0.tgz#fb83e504445268f154b074e218c87c003cd31df4" + integrity sha512-lr2EZCctC2BNR7j7WzJ2FpDznxky1sjfxvvYEyzxNyb6lZXHODmEoJeFu4JupYlkfha1KZpJyoqiJ7pgA1qq8Q== dependencies: spdx-expression-parse "^3.0.0" spdx-license-ids "^3.0.0" @@ -1529,9 +1614,9 @@ spdx-expression-parse@^3.0.0: spdx-license-ids "^3.0.0" spdx-license-ids@^3.0.0: - version "3.0.2" - resolved "https://registry.yarnpkg.com/spdx-license-ids/-/spdx-license-ids-3.0.2.tgz#a59efc09784c2a5bada13cfeaf5c75dd214044d2" - integrity sha512-qky9CVt0lVIECkEsYbNILVnPvycuEBkXoMFLRWsREkomQLevYhtRKC+R91a5TOAQ3bCMjikRwhyaRqj1VYatYg== + version "3.0.5" + resolved "https://registry.yarnpkg.com/spdx-license-ids/-/spdx-license-ids-3.0.5.tgz#3694b5804567a458d3c8045842a6358632f62654" + integrity sha512-J+FWzZoynJEXGphVIS+XEh3kFSjZX/1i9gFBaWQcB+/tmpe2qUsSBABpcxqxnAxFdiUFEgAX1bjYGQvIZmoz9Q== split-string@^3.0.1, split-string@^3.0.2: version "3.1.0" @@ -1655,6 +1740,11 @@ tslib@^1.9.0: resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.9.3.tgz#d7e4dd79245d85428c4d7e4822a79917954ca286" integrity sha512-4krF8scpejhaOgqzBEcGM7yDIEfi0/8+8zDRZhNZZ2kjmHJ4hv3zCbQWxoJGz1iw5U0Jl0nma13xzHXcncMavQ== +type-fest@^0.6.0: + version "0.6.0" + resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.6.0.tgz#8d2a2370d3df886eb5c90ada1c5bf6188acf838b" + integrity sha512-q+MB8nYR1KDLrgr4G5yemftpMC7/QLqVndBmEEdqzmNj5dcFOO4Oo8qlwZE3ULT3+Zim1F8Kq4cBnikNhlCMlg== + union-value@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/union-value/-/union-value-1.0.0.tgz#5c71c34cb5bad5dcebe3ea0cd08207ba5aa1aea4" From de7b9e3437fcf5324e51161b9adf8a6fa9297e1e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marco=20Aur=C3=A9lio=20da=20Silva?= Date: Sun, 13 Oct 2019 20:07:51 -0300 Subject: [PATCH 24/29] refactor: :recycle: using native digestif function to hash a sequence of texts instead of manually hashing them after string concatenation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Marco Aurélio da Silva --- lib/hash.ml | 5 +++++ lib/hash.mli | 4 ++++ lib/keys.ml | 7 ++++++- lib/serialization.ml | 9 +-------- lib/serialization.mli | 4 +--- lib/verification.ml | 4 ++-- test/bench/bench.expected | 36 +++++++++++++++++------------------- 7 files changed, 36 insertions(+), 33 deletions(-) diff --git a/lib/hash.ml b/lib/hash.ml index 2ae404b..9e654c7 100644 --- a/lib/hash.ml +++ b/lib/hash.ml @@ -20,6 +20,8 @@ let digest_bytes ~steps bytes = bytes |> Bytes.to_string |> __digest_string_steps steps |> Bytes.of_string +let hash_bytes_seq list = Digestif.BLAKE2B.digestv_bytes list + let __digest message = Nocrypto.Hash.SHA256.digest message (* TODO: use scrypt KDF here *) @@ -38,3 +40,6 @@ let mine ~difficulty text = let nonce = Z.zero in let pattern = Core.String.init difficulty ~f:(Core.const '0') in __mining input pattern nonce + + +let same left right = Digestif.BLAKE2B.equal left right diff --git a/lib/hash.mli b/lib/hash.mli index bebdc03..68efff8 100644 --- a/lib/hash.mli +++ b/lib/hash.mli @@ -3,3 +3,7 @@ val digest : ?steps:int -> string -> string val digest_bytes : steps:int -> bytes -> bytes val mine : difficulty:int -> string -> Cstruct.t + +val hash_bytes_seq : bytes list -> Digestif.BLAKE2B.t + +val same : Digestif.BLAKE2B.t -> Digestif.BLAKE2B.t -> bool diff --git a/lib/keys.ml b/lib/keys.ml index e092430..ce43cd8 100644 --- a/lib/keys.ml +++ b/lib/keys.ml @@ -14,7 +14,12 @@ let genpub priv = List.map pieces ~f:__digest -let derive priv = Utils.bytes_of_hex @@ Serialization.digest @@ genpub priv +let derive priv = + Bytes.of_string + @@ Digestif.BLAKE2B.to_raw_string + @@ Serialization.digest + @@ genpub priv + let export ~priv ~pass = let priv' = Bytes.to_string priv in diff --git a/lib/serialization.ml b/lib/serialization.ml index 84bb081..5941c10 100644 --- a/lib/serialization.ml +++ b/lib/serialization.ml @@ -2,17 +2,10 @@ module List = Core.List module String = Core.String module Option = Core.Option -let show pub = - pub - |> List.map ~f:Utils.bytes_to_hex - |> List.reduce_exn ~f:Utils.concat_hashes - +let digest = Hash.hash_bytes_seq let load text = let list = String.split text ~on:':' in let open Option in Utils.validate_key list >>= fun list -> some @@ List.map ~f:Utils.bytes_of_hex list - - -let digest pub = pub |> show |> Hash.digest diff --git a/lib/serialization.mli b/lib/serialization.mli index 7ccb2f4..2d3a4d3 100644 --- a/lib/serialization.mli +++ b/lib/serialization.mli @@ -1,5 +1,3 @@ -val show : bytes list -> string - val load : string -> bytes list option -val digest : bytes list -> string +val digest : bytes list -> Digestif.BLAKE2B.t diff --git a/lib/verification.ml b/lib/verification.ml index fea2b4b..24f9961 100644 --- a/lib/verification.ml +++ b/lib/verification.ml @@ -18,8 +18,8 @@ let verify ~pub ~msg ~signature = let payload = Checksum.make_payload @@ Bytes.of_string msg in let pairs = Utils.indexed_keys payload in let root = __compute_root cells pairs in - let fingerprint = Utils.bytes_to_hex pub in - root = fingerprint + let fingerprint = Digestif.BLAKE2B.of_raw_string @@ Bytes.to_string pub in + Hash.same root fingerprint with | _ -> false diff --git a/test/bench/bench.expected b/test/bench/bench.expected index e1319e0..948a806 100644 --- a/test/bench/bench.expected +++ b/test/bench/bench.expected @@ -1,19 +1,17 @@ -Estimated testing time 2m (12 benchmarks x 10s). Change using -quota SECS. -┌─────────────────────────────────────────────────────┬──────────────────┬───────────────┬────────────────┬─────────────┬────────────┐ -│ Name │ Time/Run │ mWd/Run │ mjWd/Run │ Prom/Run │ Percentage │ -├─────────────────────────────────────────────────────┼──────────────────┼───────────────┼────────────────┼─────────────┼────────────┤ -│ hieroglyphs + blake2b ------ private key generation │ 18_250.29ns │ 610.86w │ 0.13w │ 0.13w │ │ -│ hieroglyphs + blake2b ------ message signing │ 830_777_285.22ns │ 1_126_055.43w │ 34_143_882.57w │ 110_337.57w │ 84.82% │ -│ hieroglyphs + blake2b ------ public key derivation │ 762_818_024.31ns │ 1_093_699.54w │ 33_944_068.46w │ 109_993.46w │ 77.88% │ -│ hieroglyphs + blake2b ------ signature verification │ 979_464_860.27ns │ 5_363_258.26w │ 34_006_904.17w │ 137_739.17w │ 100.00% │ -│ rsa pss/sha256 1024 bits --- private key generation │ 43_341_991.32ns │ 870.83w │ -0.27w │ -0.27w │ 4.43% │ -│ rsa pss/sha256 1024 bits --- public key derivation │ 13.52ns │ 3.00w │ │ │ │ -│ rsa pss/sha256 1024 bits --- message signing │ 884_425.40ns │ 1_715.01w │ 0.54w │ 0.54w │ 0.09% │ -│ rsa pss/sha256 1024 bits --- signature verification │ 99_468.45ns │ 1_547.02w │ 0.35w │ 0.35w │ 0.01% │ -│ secp256k1 + sha256 hash ---- private key generation │ 15_107.13ns │ 355.80w │ │ │ │ -│ secp256k1 + sha256 hash ---- public key derivation │ 251_762.39ns │ 13.00w │ │ │ 0.03% │ -│ secp256k1 + sha256 hash ---- message signing │ 364_347.26ns │ 230.00w │ │ │ 0.04% │ -│ secp256k1 + sha256 hash ---- signature verification │ 424_337.89ns │ 214.00w │ │ │ 0.04% │ -└─────────────────────────────────────────────────────┴──────────────────┴───────────────┴────────────────┴─────────────┴────────────┘ -Benchmarks that take 1ns to 100ms can be estimated precisely. For more reliable -estimates, redesign your benchmark to have a shorter execution time. +Estimated testing time 2m (12 benchmarks x 10s). Change using '-quota'. +┌─────────────────────────────────────────────────────┬─────────────────┬───────────────┬────────────┬───────────┬────────────┐ +│ Name │ Time/Run │ mWd/Run │ mjWd/Run │ Prom/Run │ Percentage │ +├─────────────────────────────────────────────────────┼─────────────────┼───────────────┼────────────┼───────────┼────────────┤ +│ hieroglyphs + blake2b ------ private key generation │ 14_168.25ns │ 610.86w │ 0.12w │ 0.12w │ 0.04% │ +│ hieroglyphs + blake2b ------ message signing │ 9_464_803.94ns │ 638_898.85w │ 36_005.59w │ 2_214.59w │ 26.54% │ +│ hieroglyphs + blake2b ------ public key derivation │ 17_062_757.26ns │ 1_297_597.15w │ 1_485.40w │ 1_485.40w │ 47.84% │ +│ hieroglyphs + blake2b ------ signature verification │ 9_770_490.21ns │ 824_026.67w │ 2_102.90w │ 2_102.90w │ 27.40% │ +│ rsa pss/sha256 1024 bits --- private key generation │ 35_665_150.48ns │ 870.82w │ 0.45w │ 0.45w │ 100.00% │ +│ rsa pss/sha256 1024 bits --- public key derivation │ 9.92ns │ 3.00w │ │ │ │ +│ rsa pss/sha256 1024 bits --- message signing │ 714_195.12ns │ 1_714.57w │ 0.58w │ 0.58w │ 2.00% │ +│ rsa pss/sha256 1024 bits --- signature verification │ 81_259.61ns │ 1_547.02w │ 0.34w │ 0.34w │ 0.23% │ +│ secp256k1 + sha256 hash ---- private key generation │ 12_522.57ns │ 355.72w │ │ │ 0.04% │ +│ secp256k1 + sha256 hash ---- public key derivation │ 201_243.30ns │ 13.00w │ │ │ 0.56% │ +│ secp256k1 + sha256 hash ---- message signing │ 295_076.97ns │ 230.00w │ │ │ 0.83% │ +│ secp256k1 + sha256 hash ---- signature verification │ 332_174.62ns │ 214.00w │ │ │ 0.93% │ +└─────────────────────────────────────────────────────┴─────────────────┴───────────────┴────────────┴───────────┴────────────┘ From d8bc751be0542a35e0e490c859b1aa803b356c46 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marco=20Aur=C3=A9lio=20da=20Silva?= Date: Sun, 27 Oct 2019 15:10:55 -0300 Subject: [PATCH 25/29] refactor: :recycle: precomputed list of seed suffixes/keys for signing keys generation from private key/seed MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Marco Aurélio da Silva --- lib/utils.ml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/lib/utils.ml b/lib/utils.ml index d9bbb37..d11d163 100644 --- a/lib/utils.ml +++ b/lib/utils.ml @@ -50,13 +50,14 @@ let _hash_both ~digest prefix suffix = type digest = steps:int -> bytes -> bytes +let _NUMS = List.init _KEYS_LENGTH ~f:_int_to_cstruct + (* random is our seed for the signing keys *) (* TODO: use HMAC/BLAKE-MAC here for a perfect PRF *) let generate_pieces ~(digest : digest) random = let digest' = digest ~steps:1 in let blob = Cstruct.of_bytes random in - let nums = List.init _KEYS_LENGTH ~f:_int_to_cstruct in - List.map nums ~f:(_hash_both ~digest:digest' blob) + List.map _NUMS ~f:(_hash_both ~digest:digest' blob) let validate_key list = From f4ff4fe0504cf8cfbe2777eb34a19400bddbb49b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marco=20Aur=C3=A9lio=20da=20Silva?= Date: Sun, 27 Oct 2019 15:12:10 -0300 Subject: [PATCH 26/29] refactor: :recycle: blacklist prefix MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Marco Aurélio da Silva --- lib/blacklist.ml | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/lib/blacklist.ml b/lib/blacklist.ml index 50aacd7..548dc70 100644 --- a/lib/blacklist.ml +++ b/lib/blacklist.ml @@ -1,9 +1,11 @@ +let _PREFIX = "blacklist/" + let add address = - let key = "blacklist/" ^ address in + let key = _PREFIX ^ address in let msg = "Revoking private key for public key " ^ address ^ "." in Store.set ~msg ~key "" let exists address = - let key = "blacklist/" ^ address in + let key = _PREFIX ^ address in match Store.get ~key with None -> false | Some _ -> true From 0d62fa34f88ab209157c6d34c6f2b713c3f1f93d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marco=20Aur=C3=A9lio=20da=20Silva?= Date: Sun, 27 Oct 2019 15:20:30 -0300 Subject: [PATCH 27/29] refactor: :recycle: adding Blake2B Keyed Mode (a.k.a MAC) as PRF for signing keys and now signature is under base-64 format instead concatenated hex-strings MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Marco Aurélio da Silva --- lib/hash.ml | 11 +++++++++ lib/hash.mli | 4 +++ lib/keys.ml | 2 +- lib/serialization.ml | 11 ++++++--- lib/signing.ml | 6 ++++- lib/utils.ml | 58 +++++++++++++++++++++++++++++--------------- lib/utils.mli | 9 ++++--- test/spec/sign.ml | 4 +-- test/spec/utils.ml | 35 ++++++++++++++++++++++++++ 9 files changed, 109 insertions(+), 31 deletions(-) diff --git a/lib/hash.ml b/lib/hash.ml index 9e654c7..cae9b91 100644 --- a/lib/hash.ml +++ b/lib/hash.ml @@ -43,3 +43,14 @@ let mine ~difficulty text = let same left right = Digestif.BLAKE2B.equal left right + +let mac ~key message = + let digest = Digestif.BLAKE2B.Keyed.mac_string ~key message in + Digestif.BLAKE2B.to_raw_string digest + + +let mac_bytes ~key message = + let message' = Bytes.to_string message in + let key' = Bytes.to_string key in + let tag = mac ~key:key' message' in + Bytes.of_string tag diff --git a/lib/hash.mli b/lib/hash.mli index 68efff8..af573e5 100644 --- a/lib/hash.mli +++ b/lib/hash.mli @@ -7,3 +7,7 @@ val mine : difficulty:int -> string -> Cstruct.t val hash_bytes_seq : bytes list -> Digestif.BLAKE2B.t val same : Digestif.BLAKE2B.t -> Digestif.BLAKE2B.t -> bool + +val mac : key:string -> string -> string + +val mac_bytes : key:bytes -> bytes -> bytes diff --git a/lib/keys.ml b/lib/keys.ml index ce43cd8..d2e1a23 100644 --- a/lib/keys.ml +++ b/lib/keys.ml @@ -10,7 +10,7 @@ let generate () = Random.generate512 () let __digest piece = Hash.digest_bytes ~steps:255 piece let genpub priv = - let pieces = Utils.generate_pieces ~digest:Hash.digest_bytes priv in + let pieces = Utils.generate_pieces ~prf:Hash.mac_bytes priv in List.map pieces ~f:__digest diff --git a/lib/serialization.ml b/lib/serialization.ml index 5941c10..85bf6df 100644 --- a/lib/serialization.ml +++ b/lib/serialization.ml @@ -4,8 +4,11 @@ module Option = Core.Option let digest = Hash.hash_bytes_seq -let load text = - let list = String.split text ~on:':' in +let load signature = let open Option in - Utils.validate_key list - >>= fun list -> some @@ List.map ~f:Utils.bytes_of_hex list + Encoding.decode signature + >>= fun signature' -> + let decoded = Cstruct.of_string signature' in + let pieces = Utils.__split_cstruct decoded in + Utils.validate_blob_key pieces + >>= fun validated -> some @@ List.map ~f:Cstruct.to_bytes validated diff --git a/lib/signing.ml b/lib/signing.ml index 3b37a78..fb7a09e 100644 --- a/lib/signing.ml +++ b/lib/signing.ml @@ -1,10 +1,14 @@ module List = Core.List +let raw_of_hex hex = Cstruct.to_string @@ Cstruct.of_hex hex + let sign ~priv:seed ~msg = - let priv = Utils.generate_pieces ~digest:Hash.digest_bytes seed in + let priv = Utils.generate_pieces ~prf:Hash.mac_bytes seed in msg |> Bytes.of_string |> Checksum.make_payload |> Utils.indexed_keys |> Utils.replace_index ~digest:Hash.digest_bytes ~matrix:priv + |> List.map ~f:raw_of_hex |> List.reduce_exn ~f:Utils.concat_hashes + |> Encoding.encode diff --git a/lib/utils.ml b/lib/utils.ml index d11d163..baa6193 100644 --- a/lib/utils.ml +++ b/lib/utils.ml @@ -38,31 +38,27 @@ let pad_cstruct size input = Cstruct.of_string @@ String.rev strip -let _int_to_cstruct number = - pad_cstruct _BYTES_LENGTH - @@ Nocrypto.Numeric.Z.to_cstruct_be - @@ Z.of_int number - - -let _hash_both ~digest prefix suffix = - digest @@ Cstruct.to_bytes @@ cxor prefix suffix +let _int_to_bytes number = + let cstruct = + pad_cstruct _BYTES_LENGTH + @@ Nocrypto.Numeric.Z.to_cstruct_be + @@ Z.of_int number + in + Cstruct.set_uint8 cstruct 0 255 ; + Cstruct.to_bytes cstruct type digest = steps:int -> bytes -> bytes -let _NUMS = List.init _KEYS_LENGTH ~f:_int_to_cstruct +type prf = key:bytes -> bytes -> bytes -(* random is our seed for the signing keys *) -(* TODO: use HMAC/BLAKE-MAC here for a perfect PRF *) -let generate_pieces ~(digest : digest) random = - let digest' = digest ~steps:1 in - let blob = Cstruct.of_bytes random in - List.map _NUMS ~f:(_hash_both ~digest:digest' blob) +let _hash_both ~(prf : prf) prefix suffix = prf prefix ~key:suffix +let _NUMS = List.init _KEYS_LENGTH ~f:_int_to_bytes -let validate_key list = - let filtered = List.filter list ~f:is_hash in - if List.length filtered = _KEYS_LENGTH then Some list else None +(* random is our seed for the signing keys *) +let generate_pieces ~(prf : prf) random = + List.map _NUMS ~f:(_hash_both ~prf random) let with_hex_prefix text = "0x" ^ text @@ -75,7 +71,7 @@ let replace_index ~(digest : digest) ~matrix pairs = List.map pairs ~f:(index_at ~digest ~list:matrix) -let concat_hashes left right = left ^ ":" ^ right +let concat_hashes left right = left ^ right let chained_index index value = (index, Char.to_int value) @@ -97,3 +93,27 @@ let unpad msg = String.filter ~f:nonzero @@ Cstruct.to_string msg let _NULL_HASH = String.make _HASH_LENGTH '0' let _NULL_ADDRESS = with_hex_prefix _NULL_HASH + +let rec __split_cstruct_loop _LENGTH index splits blob = + let position = index * _BYTES_LENGTH in + let difference = _LENGTH - position in + if difference <= 0 + then List.rev splits + else + let split = Cstruct.sub blob position _BYTES_LENGTH in + let splits' = split :: splits in + let index' = index + 1 in + __split_cstruct_loop _LENGTH index' splits' blob + + +let __split_cstruct blob = + let length = Cstruct.len blob in + __split_cstruct_loop length 0 [] blob + + +let is_blob_hash hash = Cstruct.len hash = _BYTES_LENGTH + +let validate_blob_key list = + let filtered = List.filter list ~f:is_blob_hash in + assert (List.length filtered = _KEYS_LENGTH) ; + Some list diff --git a/lib/utils.mli b/lib/utils.mli index 7331e62..373de79 100644 --- a/lib/utils.mli +++ b/lib/utils.mli @@ -10,10 +10,7 @@ val with_hex_prefix : string -> string val concat_hashes : string -> string -> string -val validate_key : string list -> string list option - -val generate_pieces : - digest:(steps:int -> bytes -> bytes) -> bytes -> bytes list +val generate_pieces : prf:(key:bytes -> bytes -> bytes) -> bytes -> bytes list val replace_index : digest:(steps:int -> bytes -> bytes) @@ -36,3 +33,7 @@ val bytes_to_hex : bytes -> string val _NULL_HASH : string val _NULL_ADDRESS : string + +val __split_cstruct : Cstruct.t -> Cstruct.t list + +val validate_blob_key : Cstruct.t list -> Cstruct.t list option diff --git a/test/spec/sign.ml b/test/spec/sign.ml index 34ba1c5..32b45f4 100644 --- a/test/spec/sign.ml +++ b/test/spec/sign.ml @@ -15,8 +15,8 @@ let __signature_validation () = let msg = "Yadda yadda yadda" in let priv = Hg.generate () in let signature = sign ~priv ~msg in - let chunks = String.split ~on:':' signature in - let filtered = List.filter ~f:Utils.is_hash chunks in + let chunks = Utils.split_signature signature in + let filtered = List.filter ~f:Utils.is_blob_hash chunks in Alcotest.(check int) "valid signature size" (List.length chunks) 66 ; Alcotest.(check int) "valid chunks in signature" (List.length filtered) 66 diff --git a/test/spec/utils.ml b/test/spec/utils.ml index e038662..69cacfd 100644 --- a/test/spec/utils.ml +++ b/test/spec/utils.ml @@ -1,9 +1,44 @@ module String = Core.String module Str = Re.Str +module Option = Core.Option +module Base64 = Nocrypto.Base64 let _HASH_LENGTH = 128 +let _BYTES_LENGTH = 64 + let regexp = Str.regexp "^[a-f0-9]+$" let is_hash text = Str.string_match regexp text 0 && String.length text = _HASH_LENGTH + + +let is_blob_hash text = Cstruct.len text = _BYTES_LENGTH + +let rec __split_cstruct_loop _LENGTH index splits blob = + let position = index * _BYTES_LENGTH in + let difference = _LENGTH - position in + if difference <= 0 + then List.rev splits + else + let split = Cstruct.sub blob position _BYTES_LENGTH in + let splits' = split :: splits in + let index' = index + 1 in + __split_cstruct_loop _LENGTH index' splits' blob + + +let __split_cstruct blob = + let length = Cstruct.len blob in + __split_cstruct_loop length 0 [] blob + + +let decode blob = + let open Option in + blob |> Cstruct.of_string |> Base64.decode >>| Cstruct.to_string + + +let split_signature signature = + let signature' = Option.value_exn (decode signature) in + let decoded = Cstruct.of_string signature' in + let pieces = __split_cstruct decoded in + pieces From a646e9d5fd8ad8d3c406fe32295e16d118b9eb23 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marco=20Aur=C3=A9lio=20da=20Silva?= Date: Wed, 16 Sep 2020 17:58:09 -0300 Subject: [PATCH 28/29] bugfix: :beetle: fixing unnecessary/bogus padding --- lib/utils.ml | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/utils.ml b/lib/utils.ml index baa6193..21b88e4 100644 --- a/lib/utils.ml +++ b/lib/utils.ml @@ -82,6 +82,7 @@ let indexed_keys payload = let pad ~basis msg = let length = String.length msg in let remainder = Int.( % ) length basis in + if remainder = 0 then msg else let zerofill = String.make (basis - remainder) nullchar in Cstruct.of_string (msg ^ zerofill) From 18e54c4254baf8c61bfdd51a3a28d49bcb3dd022 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marco=20Aur=C3=A9lio=20da=20Silva?= Date: Sun, 7 Nov 2021 19:02:00 -0300 Subject: [PATCH 29/29] chore: :gear: some adjustments for dune build with higher dependencies versions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Marco Aurélio da Silva --- hieroglyphs.opam | 1 + lib/dune | 4 ++-- lib/store.ml | 12 +++++++++--- lib/utils.ml | 4 ++-- 4 files changed, 14 insertions(+), 7 deletions(-) diff --git a/hieroglyphs.opam b/hieroglyphs.opam index 13e2c39..21a9b20 100644 --- a/hieroglyphs.opam +++ b/hieroglyphs.opam @@ -17,6 +17,7 @@ depends: [ "lwt" {>= "4.1.0"} "irmin-unix" {>= "1.3.3"} "irmin-watcher" {>= "0.4.0"} + "hex" {>= "1.4.0"} "re" {>= "1.8.0"} "core" {>= "v0.11.3"} "digestif" {>= "0.7.1"} diff --git a/lib/dune b/lib/dune index 5b590b1..ec3186d 100644 --- a/lib/dune +++ b/lib/dune @@ -2,7 +2,7 @@ (name hieroglyphs) (wrapped true) (public_name hieroglyphs) - (preprocess (pps bisect_ppx -conditional)) + (preprocess (pps bisect_ppx)) (libraries - core unix digestif.c nocrypto.unix nocrypto re irmin-unix irmin-git lwt.unix) + core unix digestif.c nocrypto.unix nocrypto re irmin-unix irmin-git lwt.unix hex) (synopsis "Core / kernel module for the Hash-based signatures algorithm")) diff --git a/lib/store.ml b/lib/store.ml index 0066689..5ee6e65 100644 --- a/lib/store.ml +++ b/lib/store.ml @@ -14,7 +14,7 @@ let author = "Hieroglyphs library" let info fmt = Irmin_unix.info ~author fmt -let set ~msg ~key value = +let __set ~msg ~key value = let path = String.split ~on:'/' key in let msg = info (format_of_string "%s") msg in let transaction () = @@ -25,6 +25,10 @@ let set ~msg ~key value = in Lwt_main.run (transaction ()) +let set ~msg ~key value = + match __set ~msg ~key value with + | Error _ -> failwith "GitStore WRITE ERROR: Failed to set key-value pair on .git repository as a commit!" + | Ok () -> () let get ~key = let path = String.split ~on:'/' key in @@ -51,5 +55,7 @@ let boot () = let () = - boot () ; - Irmin_unix.set_listen_dir_hook () + match boot () with + | Error _ -> failwith "GitStore WRITE ERROR: Failed to initialize .git repository with deterministic initial commit!" + | Ok () -> Irmin_unix.set_listen_dir_hook () + diff --git a/lib/utils.ml b/lib/utils.ml index 21b88e4..af46bac 100644 --- a/lib/utils.ml +++ b/lib/utils.ml @@ -79,10 +79,10 @@ let indexed_keys payload = payload |> Bytes.to_string |> String.to_list |> List.mapi ~f:chained_index -let pad ~basis msg = +let pad ~basis:(basis:int) (msg : string) : Cstruct.t = let length = String.length msg in let remainder = Int.( % ) length basis in - if remainder = 0 then msg else + if remainder = 0 then Cstruct.of_string msg else let zerofill = String.make (basis - remainder) nullchar in Cstruct.of_string (msg ^ zerofill)