Crypto: Only extract checksum when there's one
Specifically, check that there are enough characters to extract the 4-characters checksum of safe-encoded strings. The commit also introduces new tests for some parts of the crypto library.
This commit is contained in:
parent
92ee761451
commit
cd8a63f543
@ -126,10 +126,12 @@ let safe_encode ?alphabet s =
|
||||
let safe_decode ?alphabet s =
|
||||
raw_decode ?alphabet s |> Option.apply ~f:begin fun s ->
|
||||
let len = String.length s in
|
||||
let msg = String.sub s 0 (len-4) in
|
||||
let msg_hash = String.sub s (len-4) 4 in
|
||||
if msg_hash <> checksum msg then None
|
||||
else Some msg
|
||||
if len < 4 then None else
|
||||
(* only if the string is long enough to extract a checksum do we check it *)
|
||||
let msg = String.sub s 0 (len-4) in
|
||||
let msg_hash = String.sub s (len-4) 4 in
|
||||
if msg_hash <> checksum msg then None
|
||||
else Some msg
|
||||
end
|
||||
|
||||
type data = ..
|
||||
|
@ -1,7 +1,10 @@
|
||||
(jbuild_version 1)
|
||||
|
||||
(executables
|
||||
((names (test_merkle))
|
||||
((names (test_merkle
|
||||
test_base58
|
||||
test_ed25519
|
||||
test_blake2b))
|
||||
(libraries (tezos-stdlib
|
||||
tezos-crypto
|
||||
alcotest))
|
||||
@ -12,15 +15,33 @@
|
||||
|
||||
(alias
|
||||
((name buildtest)
|
||||
(deps (test_merkle.exe))))
|
||||
(deps (test_merkle.exe
|
||||
test_base58.exe
|
||||
test_ed25519.exe
|
||||
test_blake2b.exe))))
|
||||
|
||||
(alias
|
||||
((name runtest_merkle)
|
||||
(action (run ${exe:test_merkle.exe}))))
|
||||
|
||||
(alias
|
||||
((name runtest_base58)
|
||||
(action (run ${exe:test_base58.exe}))))
|
||||
|
||||
(alias
|
||||
((name runtest_ed25519)
|
||||
(action (run ${exe:test_ed25519.exe}))))
|
||||
|
||||
(alias
|
||||
((name runtest_blake2b)
|
||||
(action (run ${exe:test_blake2b.exe}))))
|
||||
|
||||
(alias
|
||||
((name runtest)
|
||||
(deps ((alias runtest_merkle)))))
|
||||
(deps ((alias runtest_merkle)
|
||||
(alias runtest_base58)
|
||||
(alias runtest_ed25519)
|
||||
(alias runtest_blake2b)))))
|
||||
|
||||
(alias
|
||||
((name runtest_indent)
|
||||
|
46
src/lib_crypto/test/roundtrips.ml
Normal file
46
src/lib_crypto/test/roundtrips.ml
Normal file
@ -0,0 +1,46 @@
|
||||
(**************************************************************************)
|
||||
(* *)
|
||||
(* Copyright (c) 2014 - 2018. *)
|
||||
(* Dynamic Ledger Solutions, Inc. <contact@tezos.com> *)
|
||||
(* *)
|
||||
(* All rights reserved. No warranty, explicit or implicit, provided. *)
|
||||
(* *)
|
||||
(**************************************************************************)
|
||||
|
||||
|
||||
let test_rt_opt name pp enc dec input =
|
||||
let encoded = enc input in
|
||||
match dec encoded with
|
||||
| Some output ->
|
||||
if output = input then
|
||||
()
|
||||
else
|
||||
Format.kasprintf failwith
|
||||
"%s failed for %a: got %a" name pp input pp output
|
||||
| None ->
|
||||
Format.kasprintf failwith
|
||||
"%s failed for %a: unable to decode" name pp input
|
||||
| exception exc ->
|
||||
Format.kasprintf failwith
|
||||
"%s failed for %a: exception whilst decoding: %s"
|
||||
name pp input (Printexc.to_string exc)
|
||||
|
||||
let test_decode_opt_safe name pp dec encoded =
|
||||
match dec encoded with
|
||||
| Some _ | None -> ()
|
||||
| exception exc ->
|
||||
Format.kasprintf failwith
|
||||
"%s failed for %a: exception whilst decoding: %s"
|
||||
name pp encoded (Printexc.to_string exc)
|
||||
|
||||
let test_decode_opt_fail name pp dec encoded =
|
||||
match dec encoded with
|
||||
| Some _ ->
|
||||
Format.kasprintf failwith
|
||||
"%s failed for %a: successful decoding of invalid input"
|
||||
name pp encoded
|
||||
| None -> ()
|
||||
| exception exc ->
|
||||
Format.kasprintf failwith
|
||||
"%s failed for %a: exception whilst decoding: %s"
|
||||
name pp encoded (Printexc.to_string exc)
|
77
src/lib_crypto/test/test_base58.ml
Normal file
77
src/lib_crypto/test/test_base58.ml
Normal file
@ -0,0 +1,77 @@
|
||||
(**************************************************************************)
|
||||
(* *)
|
||||
(* Copyright (c) 2014 - 2018. *)
|
||||
(* Dynamic Ledger Solutions, Inc. <contact@tezos.com> *)
|
||||
(* *)
|
||||
(* All rights reserved. No warranty, explicit or implicit, provided. *)
|
||||
(* *)
|
||||
(**************************************************************************)
|
||||
|
||||
let test_roundtrip_safe input =
|
||||
Roundtrips.test_rt_opt
|
||||
"safe base58"
|
||||
Format.pp_print_string
|
||||
Base58.safe_encode
|
||||
Base58.safe_decode
|
||||
input
|
||||
|
||||
let test_roundtrip_raw input =
|
||||
Roundtrips.test_rt_opt
|
||||
"raw base58"
|
||||
Format.pp_print_string
|
||||
Base58.raw_encode
|
||||
Base58.raw_decode
|
||||
input
|
||||
|
||||
let inputs = [
|
||||
"abc";
|
||||
(string_of_int max_int);
|
||||
"0";
|
||||
"00";
|
||||
"000";
|
||||
"0000";
|
||||
"0000000000000000";
|
||||
(String.make 64 '0');
|
||||
"1";
|
||||
"11";
|
||||
"111";
|
||||
"1111";
|
||||
(String.make 2048 '0');
|
||||
"2";
|
||||
"22";
|
||||
"5";
|
||||
"Z";
|
||||
(String.make 2048 'Z');
|
||||
"z";
|
||||
"zz";
|
||||
"zzzzzzzz";
|
||||
(String.make 2048 'z');
|
||||
(*loads of ascii characters: codes between 32 and 126 *)
|
||||
(String.init 1000 (fun i -> (Char.chr (32 + (i mod (126 - 32))))));
|
||||
"";
|
||||
]
|
||||
|
||||
let test_roundtrip_safes () = List.iter test_roundtrip_safe inputs
|
||||
|
||||
let test_roundtrip_raws () = List.iter test_roundtrip_raw inputs
|
||||
|
||||
|
||||
let test_safety input =
|
||||
Roundtrips.test_decode_opt_safe
|
||||
"safe base58"
|
||||
Format.pp_print_string
|
||||
Base58.safe_decode
|
||||
input
|
||||
|
||||
let test_safetys () = List.iter test_safety inputs
|
||||
|
||||
let tests = [
|
||||
"safe decoding", `Quick, test_safetys;
|
||||
"safe encoding/decoding", `Quick, test_roundtrip_safes;
|
||||
"raw encoding/decoding", `Quick, test_roundtrip_raws;
|
||||
]
|
||||
|
||||
let () =
|
||||
Alcotest.run "tezos-crypto" [
|
||||
"base58", tests
|
||||
]
|
51
src/lib_crypto/test/test_blake2b.ml
Normal file
51
src/lib_crypto/test/test_blake2b.ml
Normal file
@ -0,0 +1,51 @@
|
||||
(**************************************************************************)
|
||||
(* *)
|
||||
(* Copyright (c) 2014 - 2018. *)
|
||||
(* Dynamic Ledger Solutions, Inc. <contact@tezos.com> *)
|
||||
(* *)
|
||||
(* All rights reserved. No warranty, explicit or implicit, provided. *)
|
||||
(* *)
|
||||
(**************************************************************************)
|
||||
|
||||
let test_hashed_roundtrip name enc dec input =
|
||||
(* this wrapper to start with hashing *)
|
||||
Roundtrips.test_rt_opt
|
||||
name
|
||||
(fun fmt (input, _) -> Format.fprintf fmt "%s" input)
|
||||
(fun (_, hashed) -> enc hashed)
|
||||
(fun encoded -> match dec encoded with
|
||||
| None -> None
|
||||
| Some decoded -> Some (input, decoded)
|
||||
)
|
||||
(input, Blake2B.hash_string [input])
|
||||
|
||||
let test_roundtrip_hex input =
|
||||
test_hashed_roundtrip "Hex" Blake2B.to_hex Blake2B.of_hex_opt input
|
||||
|
||||
let test_roundtrip_string input =
|
||||
test_hashed_roundtrip "String" Blake2B.to_string Blake2B.of_string_opt input
|
||||
|
||||
let inputs = [
|
||||
"abc";
|
||||
(string_of_int max_int);
|
||||
"0";
|
||||
"00";
|
||||
(String.make 64 '0');
|
||||
(*loads of ascii characters: codes between 32 and 126 *)
|
||||
(String.init 1000 (fun i -> (Char.chr (32 + (i mod (126 - 32))))));
|
||||
"";
|
||||
]
|
||||
|
||||
let test_roundtrip_hexs () = List.iter test_roundtrip_hex inputs
|
||||
|
||||
let test_roundtrip_strings () = List.iter test_roundtrip_string inputs
|
||||
|
||||
let tests = [
|
||||
"hash hex/dehex", `Quick, test_roundtrip_hexs;
|
||||
"hash print/parse", `Quick, test_roundtrip_strings;
|
||||
]
|
||||
|
||||
let () =
|
||||
Alcotest.run "tezos-crypto" [
|
||||
"blake2b", tests
|
||||
]
|
58
src/lib_crypto/test/test_ed25519.ml
Normal file
58
src/lib_crypto/test/test_ed25519.ml
Normal file
@ -0,0 +1,58 @@
|
||||
(**************************************************************************)
|
||||
(* *)
|
||||
(* Copyright (c) 2014 - 2018. *)
|
||||
(* Dynamic Ledger Solutions, Inc. <contact@tezos.com> *)
|
||||
(* *)
|
||||
(* All rights reserved. No warranty, explicit or implicit, provided. *)
|
||||
(* *)
|
||||
(**************************************************************************)
|
||||
|
||||
let get_keys () =
|
||||
let seed = Ed25519.Seed.generate () in
|
||||
Ed25519.generate_seeded_key seed
|
||||
|
||||
module type B58CHECK = sig
|
||||
type t
|
||||
val pp: Format.formatter -> t -> unit
|
||||
include S.B58_DATA with type t := t
|
||||
end
|
||||
|
||||
let test_b58check_roundtrip
|
||||
: type t. (module B58CHECK with type t = t) -> t -> unit
|
||||
= fun m input ->
|
||||
let module M = (val m) in
|
||||
Roundtrips.test_rt_opt "b58check" M.pp M.to_b58check M.of_b58check_opt input
|
||||
|
||||
let test_b58check_roundtrips () =
|
||||
let (pubkey_hash, pubkey, seckey) = get_keys () in
|
||||
test_b58check_roundtrip (module Ed25519.Public_key_hash) pubkey_hash;
|
||||
test_b58check_roundtrip (module Ed25519.Public_key) pubkey;
|
||||
test_b58check_roundtrip (module Ed25519.Secret_key) seckey
|
||||
|
||||
|
||||
let test_b58check_invalid input =
|
||||
Roundtrips.test_decode_opt_fail
|
||||
"b58check"
|
||||
Format.pp_print_string
|
||||
Ed25519.Public_key_hash.of_b58check_opt
|
||||
input
|
||||
|
||||
let test_b58check_invalids () =
|
||||
List.iter test_b58check_invalid [
|
||||
"ThisIsGarbageNotACheck";
|
||||
"\x00";
|
||||
(String.make 1000 '\x00');
|
||||
(String.make 2048 'a');
|
||||
(String.init 2048 (fun _ -> Char.chr (Random.int 256)));
|
||||
"";
|
||||
]
|
||||
|
||||
let tests = [
|
||||
"b58check.roundtrip", `Quick, test_b58check_roundtrips;
|
||||
"b58check.invalid", `Slow, test_b58check_invalids;
|
||||
]
|
||||
|
||||
let () =
|
||||
Alcotest.run "tezos-crypto" [
|
||||
"ed25519", tests
|
||||
]
|
Loading…
Reference in New Issue
Block a user