Skip to content

Commit

Permalink
ft: PoW as a password-based key derivation fun. (see #1) [+]
Browse files Browse the repository at this point in the history
proof-of-work is used for the hardening of the encryption process.
AES-256 bits (32 bytes) is quantum-safe (by now?), but the password
as defined by the user/client might be vulnerable to brute-force and
dictionary attacks. therefore, the proof-of-work ensures that the
derived encryption key from the password plain text takes a long time,
thus, slowing down such attacks. it turns the client encryption process
really slow, a good approach might be to store such encrypted private
keys with a less CPU-expensive difficulty, but whenever the user wants
to backup or restore her private keys outside her computer, she must
pass through this more CPU-expensive difficulty.

a planned / future command line interface may deal with that, for instance,
to load encrypted private keys from filesystem, the command-line may take
30-60 seconds by some certain PoW's difficulty, but whenever the user
wants to dump or load base-64 versions of the encrypted private keys,
5-6 minutes is a good/secure backup time (really? must re-check that --)

Signed-off-by: Marco Aurélio da Silva <[email protected]>
  • Loading branch information
marcoonroad committed Nov 24, 2018
1 parent 0482cdf commit dc29e67
Show file tree
Hide file tree
Showing 17 changed files with 98 additions and 46 deletions.
7 changes: 2 additions & 5 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,6 @@

.PHONY: default vendor build doc install uninstall test coverage report clean

os-vendor:
sudo apt-get install libsecp256k1-dev --yes

vendor:
opam install . --deps-only --yes

Expand Down Expand Up @@ -37,9 +34,9 @@ doc: build
test: build
dune build @test/spec/runtest -f --no-buffer -j 1

bench: os-vendor clean build
bench: clean build
opam install core_bench --yes
opam install secp256k1 --yes
opam depext conf-secp256k1 secp256k1 --install
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"
Expand Down
2 changes: 1 addition & 1 deletion docs/coverage/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,6 @@ <h2>100.00%</h2>
</a>
</div>
</div>
<div id="footer">Generated on 2018-11-22 13:00:36 by <a href="https://github.com/aantron/bisect_ppx">Bisect_ppx</a> 1.3.4</div>
<div id="footer">Generated on 2018-11-24 20:15:12 by <a href="https://github.com/aantron/bisect_ppx">Bisect_ppx</a> 1.3.4</div>
</body>
</html>
2 changes: 1 addition & 1 deletion docs/coverage/lib/blacklist.ml.html
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ <h2>100.00%</h2>
</pre>
</div>
</div>
<div id="footer">Generated on 2018-11-22 13:00:36 by <a href="https://github.com/aantron/bisect_ppx">Bisect_ppx</a> 1.3.4</div>
<div id="footer">Generated on 2018-11-24 20:15:12 by <a href="https://github.com/aantron/bisect_ppx">Bisect_ppx</a> 1.3.4</div>
<script src="../coverage.js"></script>
</body>
</html>
6 changes: 3 additions & 3 deletions docs/coverage/lib/encryption.ml.html
Original file line number Diff line number Diff line change
Expand Up @@ -63,13 +63,13 @@ <h2>100.00%</h2>
module Base64 = Nocrypto.Base64

let encrypt msg ~pass =
<span data-count="2">l</span>et key = <span data-count="2">o</span>f_secret (Cstruct.of_string (Hash.sha256 pass)) in
<span data-count="2">l</span>et key = <span data-count="2">o</span>f_secret (Hash.mine pass ~difficulty:6) in
<span data-count="2">l</span>et result = <span data-count="2">e</span>ncrypt ~key (Utils.pad ~basis:16 msg) in
<span data-count="2">r</span>esult |&gt; <span data-count="2">B</span>ase64.encode |&gt; <span data-count="2">C</span>struct.to_string


let decrypt cipher ~pass =
<span data-count="3">l</span>et key = <span data-count="3">o</span>f_secret (Cstruct.of_string (Hash.sha256 pass)) in
<span data-count="3">l</span>et key = <span data-count="3">o</span>f_secret (Hash.mine pass ~difficulty:6) in
<span data-count="3">l</span>et result = <span data-count="3">c</span>ipher |&gt; <span data-count="3">C</span>struct.of_string |&gt; <span data-count="3">B</span>ase64.decode in
<span data-count="3">l</span>et open Option in
result
Expand All @@ -78,7 +78,7 @@ <h2>100.00%</h2>
</pre>
</div>
</div>
<div id="footer">Generated on 2018-11-22 13:00:36 by <a href="https://github.com/aantron/bisect_ppx">Bisect_ppx</a> 1.3.4</div>
<div id="footer">Generated on 2018-11-24 20:15:12 by <a href="https://github.com/aantron/bisect_ppx">Bisect_ppx</a> 1.3.4</div>
<script src="../coverage.js"></script>
</body>
</html>
62 changes: 52 additions & 10 deletions docs/coverage/lib/hash.ml.html
Original file line number Diff line number Diff line change
Expand Up @@ -22,30 +22,72 @@ <h2>100.00%</h2>
<a id="L2"></a><span class="visited"> </span>
<a id="L3"></a><span > </span>
<a id="L4"></a><span > </span>
<a id="L5"></a><span > </span>
<a id="L5"></a><span class="visited"> </span>
<a id="L6"></a><span class="visited"> </span>
<a id="L7"></a><span class="visited"> </span>
<a id="L8"></a><span class="visited"> </span>
<a id="L9"></a><span class="visited"> </span>
<a id="L10"></a><span class="visited"> </span>
<a id="L11"></a><span class="visited"> </span>
<a id="L12"></a><span class="visited"> </span>
<a id="L13"></a><span > </span>
<a id="L14"></a><span class="visited"> </span>
<a id="L15"></a><span > </span>
<a id="L16"></a><span > </span>
<a id="L17"></a><span class="visited"> </span>
<a id="L18"></a><span class="visited"> </span>
<a id="L19"></a><span class="visited"> </span>
<a id="L20"></a><span class="visited"> </span>
</pre>
</div>
<div id="text-layer">
<pre id="line-numbers">
<a href="#L1">1</a>
<a href="#L2">2</a>
<a href="#L3">3</a>
<a href="#L4">4</a>
<a href="#L5">5</a>
<a href="#L6">6</a>
<a href="#L1"> 1</a>
<a href="#L2"> 2</a>
<a href="#L3"> 3</a>
<a href="#L4"> 4</a>
<a href="#L5"> 5</a>
<a href="#L6"> 6</a>
<a href="#L7"> 7</a>
<a href="#L8"> 8</a>
<a href="#L9"> 9</a>
<a href="#L10">10</a>
<a href="#L11">11</a>
<a href="#L12">12</a>
<a href="#L13">13</a>
<a href="#L14">14</a>
<a href="#L15">15</a>
<a href="#L16">16</a>
<a href="#L17">17</a>
<a href="#L18">18</a>
<a href="#L19">19</a>
<a href="#L20">20</a>
</pre>
<pre id="code">
let digest text =
<span data-count="88869">t</span>ext |&gt; <span data-count="88869">D</span>igestif.BLAKE2B.digest_string |&gt; <span data-count="88869">D</span>igestif.BLAKE2B.to_hex

let rec __mining input pattern nonce =
<span data-count="71866060">l</span>et length = <span data-count="71866060">C</span>ore.String.length pattern in
<span data-count="71866060">l</span>et salt = <span data-count="71866060">N</span>ocrypto.Numeric.Z.to_cstruct_be nonce in
<span data-count="71866060">l</span>et message = <span data-count="71866060">C</span>struct.append input salt in
<span data-count="71866060">l</span>et result = <span data-count="71866060">N</span>ocrypto.Hash.SHA256.digest message in
<span data-count="71866060">l</span>et digest = <span data-count="71866060">H</span>ex.show @@ Hex.of_cstruct result in
<span data-count="71866060">l</span>et part = <span data-count="71866060">C</span>ore.String.sub ~pos:0 ~len:length digest in
<span data-count="71866060">i</span>f pattern = part then
<span data-count="5">r</span>esult
else
<span data-count="71866055">_</span>_mining input pattern @@ Z.succ nonce

let sha256 text =
<span data-count="5">t</span>ext |&gt; <span data-count="5">D</span>igestif.SHA256.digest_string |&gt; <span data-count="5">D</span>igestif.SHA256.to_raw_string
let mine ~difficulty text =
<span data-count="5">l</span>et input = <span data-count="5">C</span>struct.of_string text in
<span data-count="5">l</span>et nonce = <span data-count="5">Z</span>.zero in
<span data-count="5">l</span>et pattern = <span data-count="5">C</span>ore.String.init difficulty ~f:(Core.const '0') in
<span data-count="5">_</span>_mining input pattern nonce
</pre>
</div>
</div>
<div id="footer">Generated on 2018-11-22 13:00:36 by <a href="https://github.com/aantron/bisect_ppx">Bisect_ppx</a> 1.3.4</div>
<div id="footer">Generated on 2018-11-24 20:15:12 by <a href="https://github.com/aantron/bisect_ppx">Bisect_ppx</a> 1.3.4</div>
<script src="../coverage.js"></script>
</body>
</html>
2 changes: 1 addition & 1 deletion docs/coverage/lib/hieroglyphs.ml.html
Original file line number Diff line number Diff line change
Expand Up @@ -201,7 +201,7 @@ <h2>100.00%</h2>
</pre>
</div>
</div>
<div id="footer">Generated on 2018-11-22 13:00:36 by <a href="https://github.com/aantron/bisect_ppx">Bisect_ppx</a> 1.3.4</div>
<div id="footer">Generated on 2018-11-24 20:15:12 by <a href="https://github.com/aantron/bisect_ppx">Bisect_ppx</a> 1.3.4</div>
<script src="../coverage.js"></script>
</body>
</html>
2 changes: 1 addition & 1 deletion docs/coverage/lib/keys.ml.html
Original file line number Diff line number Diff line change
Expand Up @@ -162,7 +162,7 @@ <h2>100.00%</h2>
</pre>
</div>
</div>
<div id="footer">Generated on 2018-11-22 13:00:36 by <a href="https://github.com/aantron/bisect_ppx">Bisect_ppx</a> 1.3.4</div>
<div id="footer">Generated on 2018-11-24 20:15:12 by <a href="https://github.com/aantron/bisect_ppx">Bisect_ppx</a> 1.3.4</div>
<script src="../coverage.js"></script>
</body>
</html>
2 changes: 1 addition & 1 deletion docs/coverage/lib/random.ml.html
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ <h2>100.00%</h2>
</pre>
</div>
</div>
<div id="footer">Generated on 2018-11-22 13:00:36 by <a href="https://github.com/aantron/bisect_ppx">Bisect_ppx</a> 1.3.4</div>
<div id="footer">Generated on 2018-11-24 20:15:12 by <a href="https://github.com/aantron/bisect_ppx">Bisect_ppx</a> 1.3.4</div>
<script src="../coverage.js"></script>
</body>
</html>
2 changes: 1 addition & 1 deletion docs/coverage/lib/serialization.ml.html
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ <h2>100.00%</h2>
</pre>
</div>
</div>
<div id="footer">Generated on 2018-11-22 13:00:36 by <a href="https://github.com/aantron/bisect_ppx">Bisect_ppx</a> 1.3.4</div>
<div id="footer">Generated on 2018-11-24 20:15:12 by <a href="https://github.com/aantron/bisect_ppx">Bisect_ppx</a> 1.3.4</div>
<script src="../coverage.js"></script>
</body>
</html>
2 changes: 1 addition & 1 deletion docs/coverage/lib/signing.ml.html
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ <h2>100.00%</h2>
</pre>
</div>
</div>
<div id="footer">Generated on 2018-11-22 13:00:36 by <a href="https://github.com/aantron/bisect_ppx">Bisect_ppx</a> 1.3.4</div>
<div id="footer">Generated on 2018-11-24 20:15:12 by <a href="https://github.com/aantron/bisect_ppx">Bisect_ppx</a> 1.3.4</div>
<script src="../coverage.js"></script>
</body>
</html>
2 changes: 1 addition & 1 deletion docs/coverage/lib/store.ml.html
Original file line number Diff line number Diff line change
Expand Up @@ -204,7 +204,7 @@ <h2>100.00%</h2>
</pre>
</div>
</div>
<div id="footer">Generated on 2018-11-22 13:00:36 by <a href="https://github.com/aantron/bisect_ppx">Bisect_ppx</a> 1.3.4</div>
<div id="footer">Generated on 2018-11-24 20:15:12 by <a href="https://github.com/aantron/bisect_ppx">Bisect_ppx</a> 1.3.4</div>
<script src="../coverage.js"></script>
</body>
</html>
4 changes: 2 additions & 2 deletions docs/coverage/lib/utils.ml.html
Original file line number Diff line number Diff line change
Expand Up @@ -194,7 +194,7 @@ <h2>100.00%</h2>
let id value = <span data-count="1280">v</span>alue

let is_hash text =
<span data-count="14496">S</span>tr.string_match regexp text 0 &amp;&amp; <span data-count="6145">S</span>tring.length text = _HASH_LENGTH
<span data-count="14330">S</span>tr.string_match regexp text 0 &amp;&amp; <span data-count="6145">S</span>tring.length text = _HASH_LENGTH


let validate_key list =
Expand Down Expand Up @@ -255,7 +255,7 @@ <h2>100.00%</h2>
</pre>
</div>
</div>
<div id="footer">Generated on 2018-11-22 13:00:36 by <a href="https://github.com/aantron/bisect_ppx">Bisect_ppx</a> 1.3.4</div>
<div id="footer">Generated on 2018-11-24 20:15:12 by <a href="https://github.com/aantron/bisect_ppx">Bisect_ppx</a> 1.3.4</div>
<script src="../coverage.js"></script>
</body>
</html>
2 changes: 1 addition & 1 deletion docs/coverage/lib/verification.ml.html
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ <h2>100.00%</h2>
</pre>
</div>
</div>
<div id="footer">Generated on 2018-11-22 13:00:36 by <a href="https://github.com/aantron/bisect_ppx">Bisect_ppx</a> 1.3.4</div>
<div id="footer">Generated on 2018-11-24 20:15:12 by <a href="https://github.com/aantron/bisect_ppx">Bisect_ppx</a> 1.3.4</div>
<script src="../coverage.js"></script>
</body>
</html>
4 changes: 2 additions & 2 deletions lib/encryption.ml
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,13 @@ module Option = Core.Option
module Base64 = Nocrypto.Base64

let encrypt msg ~pass =
let key = of_secret (Cstruct.of_string (Hash.sha256 pass)) in
let key = of_secret (Hash.mine pass ~difficulty:6) 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 (Cstruct.of_string (Hash.sha256 pass)) in
let key = of_secret (Hash.mine pass ~difficulty:6) in
let result = cipher |> Cstruct.of_string |> Base64.decode in
let open Option in
result
Expand Down
17 changes: 15 additions & 2 deletions lib/hash.ml
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,18 @@ let digest text =
text |> Digestif.BLAKE2B.digest_string |> Digestif.BLAKE2B.to_hex


let sha256 text =
text |> Digestif.SHA256.digest_string |> Digestif.SHA256.to_raw_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 mine ~difficulty text =
let input = Cstruct.of_string text in
let nonce = Z.zero in
let pattern = Core.String.init difficulty ~f:(Core.const '0') in
__mining input pattern nonce
2 changes: 1 addition & 1 deletion lib/hash.mli
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
val digest : string -> string

val sha256 : string -> string
val mine : difficulty:int -> string -> Cstruct.t
24 changes: 12 additions & 12 deletions test/bench/bench.expected
Original file line number Diff line number Diff line change
Expand Up @@ -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 │ 426_575_117.35ns1_027_102.98w33_922_454.02w88_379.02w23.10% │
│ hieroglyphs + blake2b ------ message signing │ 1_846_300_673.37ns6_296_025.80w102_379_701.20w610_674.40w │ 100.00% │
│ hieroglyphs + blake2b ------ public key derivation │ 9_932_526.22ns │ 206_848.85w15_398.83w15_398.83w │ 0.54% │
│ hieroglyphs + blake2b ------ signature verification │ 2_162_206.86ns │ 21_148.32w │ 114.85w114.85w │ 0.12% │
│ rsa pss/sha256 1024 bits --- private key generation │ 37_738_427.50ns │ 870.88w │ -0.23w │ -0.23w │ 2.04% │
│ rsa pss/sha256 1024 bits --- public key derivation │ 9.88ns │ 3.00w │ │ │ │
│ rsa pss/sha256 1024 bits --- message signing │ 788_808.95ns │ 1_715.19w │ 0.59w │ 0.59w │ 0.04% │
│ rsa pss/sha256 1024 bits --- signature verification │ 90_419.45ns │ 1_547.02w │ 0.34w │ 0.34w │ │
│ secp256k1 + sha256 hash ---- private key generation │ 13_287.47ns │ 355.70w │ │ │ │
│ secp256k1 + sha256 hash ---- public key derivation │ 217_163.38ns │ 13.00w │ │ │ 0.01% │
│ secp256k1 + sha256 hash ---- message signing │ 469_056.14ns │ 585.39w │ 0.15w │ 0.15w │ 0.03% │
│ secp256k1 + sha256 hash ---- signature verification │ 456_386.78ns │ 214.00w │ │ │ 0.02% │
│ hieroglyphs + blake2b ------ private key generation │ 376_317_374.97ns1_037_742.79w33_922_480.27w88_405.27w28.36% │
│ hieroglyphs + blake2b ------ message signing │ 1_326_859_831.73ns7_161_043.30w102_462_832.00w689_212.00w │ 100.00% │
│ hieroglyphs + blake2b ------ public key derivation │ 6_672_776.35ns │ 206_848.86w15_337.63w15_337.63w │ 0.50% │
│ hieroglyphs + blake2b ------ signature verification │ 1_896_086.08ns │ 21_148.32w │ 115.42w115.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.

0 comments on commit dc29e67

Please sign in to comment.