diff --git a/src/rsa.ml b/src/rsa.ml index 0163f2c7..f7da9a12 100644 --- a/src/rsa.ml +++ b/src/rsa.ml @@ -197,7 +197,7 @@ let blind_msg pub ~bks msg = let data_r_e = Z.rem (Z.mul data r_e) pub.n in Mirage_crypto_pk.Z_extra.to_octets_be data_r_e -let unblind_sig pub ~bks bsig = +let unblind_sig pub ~bks (Sig bsig) = let data = Mirage_crypto_pk.Z_extra.of_octets_be bsig in let bkey = rsa_blinding_key_derive pub bks in let r_inv = @@ -207,7 +207,8 @@ let unblind_sig pub ~bks bsig = assert false in let data = Z.rem (Z.mul data r_inv) pub.n in - Mirage_crypto_pk.Z_extra.to_octets_be data + let sig_ = Mirage_crypto_pk.Z_extra.to_octets_be data in + Sig sig_ let verify ~key (Sig s) ~msg = let msg_fdh = rsa_full_domain_hash key msg in diff --git a/test/dune b/test/dune index a906ce1d..21fb4bb1 100644 --- a/test/dune +++ b/test/dune @@ -1,14 +1,9 @@ (test (name test) (modules test) - (libraries mte fmt)) - -(test - (name test_crypto) - (modules test_crypto) - (libraries mte fmt)) + (libraries mte mirage-crypto-rng.unix)) (executable (name validate_response) (modules validate_response) - (libraries mte fmt bos)) + (libraries mte bos cmdliner)) diff --git a/test/test.ml b/test/test.ml index 2baf4edf..697ba7cf 100644 --- a/test/test.ml +++ b/test/test.ml @@ -1,67 +1,200 @@ -let () = Mirage_crypto_rng_unix.use_default () +let get_ok = Result.get_ok +let encode = B32.encode +let decode s = B32.decode s |> get_ok -let () = - let priv = Mirage_crypto_pk.Rsa.generate ~bits:2048 () in - let pub = Mirage_crypto_pk.Rsa.pub_of_priv priv in - let () = - let open Crypto.RsaPrivateKey in - let priv' = priv |> to_octets |> of_octets |> Result.get_ok in - assert (to_octets priv = to_octets priv') - in - let () = - let open Crypto.RsaPublicKey in - let pub' = pub |> to_octets |> of_octets |> Result.get_ok in - assert (to_octets pub = to_octets pub') - in - () - -let () = - let open Api in - let check jsont s = - let encode v = encode jsont v |> Result.get_ok in - let decode v = decode jsont v |> Result.get_ok in - let ts = decode s in - let s' = encode ts in - let ts' = decode s' in - let s'' = encode ts' in - assert (String.equal s' s'') - in - let check_bad jsont s = - let decode = decode jsont in - assert (Result.is_error (decode s)) - in - check Timestamp.jsont {|{"t_s": 123456780}|}; - check Timestamp.jsont {|{"t_s": "never"}|}; - check_bad Timestamp.jsont {|{"t_s": "123456780"}|}; - check_bad Timestamp.jsont {|{"t_s": "agagou"}|}; - check_bad DenominationKey.jsont - {|{"cipher": "CS", "age_mask": 18, "cs_pub": "ouhagag"}|}; - () - -let () = - let open Amount in - let v = - make ~sign:(Some Sign_plus) ~currency:"KUDO" ~value:(Int64.of_int 25) - ~fraction:(Int32.of_int 678) - |> Result.get_ok - in - let s = to_string v in - let v' = of_string s |> Result.get_ok in - assert (v = v'); - let r = of_string {|~KUDO:4.9|} in - assert (Result.is_error r); - let r = of_string {|+KUDO:4.99999999999999999999999|} in - assert (Result.is_error r); - () - -let () = +let test_b32 () = let round_trip s = - let s' = s |> B32.encode |> B32.decode |> Result.get_ok in + let s' = s |> encode |> decode in assert (s = s') in let s = String.init 0xff Char.chr in round_trip s; let s_l = List.init 0x0f (fun i -> String.init i Char.chr) in - List.iter round_trip s_l; + List.iter round_trip s_l +let test_eddsa () = + let open Eddsa in + let priv, pub = generate () in + let priv' = priv |> priv_to_octets |> priv_of_octets |> get_ok in + assert (priv_to_octets priv = priv_to_octets priv'); + let pub' = pub |> pub_to_octets |> pub_of_octets |> get_ok in + assert (pub_to_octets pub = pub_to_octets pub'); + () + +let test_rsa () = + let open Rsa in + let priv, pub = generate ~bits:2048 () in + let priv' = priv |> priv_to_octets |> priv_of_octets |> get_ok in + assert (priv_to_octets priv = priv_to_octets priv'); + let pub' = pub |> pub_to_octets |> pub_of_octets |> get_ok in + assert (pub_to_octets pub = pub_to_octets pub'); + () + +let test_json () = + let open Time in + let open Api in + let check_ok jsont s = + let encode v = encode jsont v |> get_ok in + let decode v = decode jsont v |> get_ok in + let s' = s |> decode |> encode in + let s'' = s' |> decode |> encode in + assert (String.equal s' s'') + in + let check_err jsont s = + let decode = decode jsont in + assert (Result.is_error (decode s)) + in + check_ok Timestamp.jsont {|{"t_s": 123456780}|}; + check_ok Timestamp.jsont {|{"t_s": "never"}|}; + check_err Timestamp.jsont {|{"t_s": "123456780"}|}; + check_err Timestamp.jsont {|{"t_s": "agagou"}|}; + () + +let test_amount () = + let open Amount in + let v = + make ~sign:(Some Sign_plus) ~currency:"KUDOS" ~value:(Int64.of_int 25) + ~fraction:(Int32.of_int 678) + |> get_ok + in + let v' = v |> to_string |> of_string |> get_ok in + assert (v = v'); + let r = of_string {|~KUDOS:4.9|} in + assert (Result.is_error r); + let r = of_string {|+KUDOS:4.99999999999999999999999|} in + assert (Result.is_error r); + () + +(* test against GNUnet crypto test vectors + taken from: https://git.gnunet.org/gnunet/gnunet/file/src/cli/util/crypto-test-vectors.json.html *) +module Test_crypto = struct + let test_hash64 () = + let open Hash in + let input = "91JPRV3F5GG4EKJNDSJQ8" in + let expected = + "D0R24RZ1TPASVQ2NY56CT8AJDYZE9ZGDB0GVZ05E9D4YGZQW2RC5YFPQ0Q86EPW836DY7VYQTNFFJT3ZR2K508F4JVS5JNJKYN2MMFR" + in + let output = input |> decode |> H64.hash |> H64.to_octets |> encode in + assert (output = expected) + + let test_eddsa () = + let pub = "3M9KK1WSNM1RTY5P72HKFA264V4B7MVHVJ08Y90CV06DYHV8XPP0" in + let priv = "8QC2VNF8443S5KPNKMB4XMV58BTHWAKZ7SVW5WG3KRB37567XS90" in + let pub' = + priv + |> decode + |> Eddsa.priv_of_octets + |> get_ok + |> Eddsa.pub_of_priv + |> Eddsa.pub_to_octets + |> encode + in + assert (pub = pub') + + let test_eddsa_signing () = + let priv = "5077XJR9AMH4T97ACKFBVBJD0KFENHPV66B2Y1JBSKXBJKNZJ4E0" in + let pub = "6E2F03JJ8AEDANTTZZ4SBZDFEEZSF8A9DVGTS6VFBCVZQYQ46RRG" in + let data = "00000300000000000000" in + let sig_ = + "XCNJGJ96WPDH60YVMH6C74NGQSGJE3BC1TYMGX6BHY5DMZZZKTB373QTXJ507K5EBSG9YS2EYKHCX3ATRQ6P5MY9MXC4ZB1XSZ2X23G" + in + let msg = decode data in + let eddsa_priv = priv |> decode |> Eddsa.priv_of_octets |> get_ok in + let sig_' = + Eddsa.sign ~key:eddsa_priv msg |> Eddsa.sig_to_octets |> encode + in + assert (sig_ = sig_'); + let eddsa_pub = pub |> decode |> Eddsa.pub_of_octets |> get_ok in + let eddsa_sig = sig_ |> decode |> Eddsa.sig_of_octets |> get_ok in + let res = Eddsa.verify ~key:eddsa_pub eddsa_sig ~msg in + get_ok res + + let test_kdf () = + let salt = "94KPT83PCNS7J83KC5P78Y8" in + let ikm = "94KPT83MD1JJ0WV5CDS6AX10D5Q70XBM41NPAY90DNGQ8SBJD5GPR" in + let ctx = + "94KPT83141HPYVKMCNW78833D1TPWTSC41GPRWVF41NPWVVQDRG62WS04XMPWSKF4WG6JVH0EHM6A82J8S1G" + in + let out_len = 64 in + let out = + "GTMR4QT05Z9WF5HKVG0WK9RPXGHSMHJNW377G9GJXCA8B0FEKPF4D27RJMSJZYWSQNTBJ5EYVV7ZW18B48Z0JVJJ80RHB706Y96Q358" + in + let xts = salt |> decode in + let ikm = ikm |> decode in + let ctx = ctx |> decode in + let okm = Rsa.Kdf.kdf ~xts ~ikm ~ctx ~len:out_len in + let okm = okm |> encode in + assert (okm = out) + + (* rsa_private_key test data is given in gcrypt's sexpr format + we would need to parse it to read and use the private-key... + so we only test [blind_msg] here *) + let test_rsa_blind_msg () = + let message_hash = + "XKQMJ4CNTXBFE1V2WR6JS063J7PZQE4XMB5JH3RS5X0THQ1JQSQ69Y7KDBC9TYRJEZH48MEPY2SF4QHQ4VHXC0YQX5935MQEGP0AX6R" + in + let rsa_public_key = + "040000YRN1NVJ68RS6RJF52PGRCQG19ZKWQPSTJX2G7ZDCKSZFE2VW3HHA81YF5C639JHJF5TX8YTEE2FW2WQCG1PTKNBSPPJEJGA032CN3E8QZ27VWY0K6JFT8ZSYWRH2SKDMXW56A4QKY46JJBWJ6T0ZRVBW6S1HTHXVE2RW8MXRW5T801077MDY13N5F8Z1JZVKBJ06TK3S0YPEDBXK0VEHRHEQJ5X5XYKR4KQTFAZNBMKXY8836VCHBXTK4YNX6AJ1CK29SMJH3Z3QRM16A2TNQGFR0HSMV446BF7FMT2E379ZAT5ST4G3BM2NWZYW545S2SW5MG5S6M88XZZ7SKFD48YVXNZ205GGSEYJPVBMR76WG4ZG30WBCPC1N54XE12RMAG81D8C09WG22PKGGDHYXX68N04002" + in + let blinding_key_secret = + "3SWF49XZPHQMENTSBZQR7Z0B8ZSZ2JRARE79Q4VXZMQ7W6QABXMG" + in + let blinded_message = + "3KHKZJZ30ABB4E56MA2V0EQWGCWH0QQG9P2ZHYHR186C5HZXJMM4N9WXAQTKS94QSV9Y17GGNXN5MB1PZZFG7Q0FY88QPKKRG4MYCPSMTZK5W59R0MJVNJ4P4AQM96TDG5W7RV8GSNR1QQZ1GNHW3CX6D6ZRTMXB2NKB5SSYTDJS79F5ZFBRZ4HVED9JBBPWSR79KVV5QQ4APBGHBCKGMF9NJJS53A1BVYHDEVYAGFYF2SNEP827ZP50FKJ5GKGV8NQ15ESEZ69AT7GJG0T3TZVENY2YN9CVR98W3BKEZ53J7VTANARG8SJS8AMJQ7S23P5HRJ7XE9KTNRNXKH49MXV9JHHYE5535N7AGWEKR47SBCGNF44Z7XJ9RV5BQV12ZRJKN4HBZQHDNCMH3QKX9Z6G64" + in + let pub = rsa_public_key |> Rsa.pub_of_b32 |> get_ok in + assert (Rsa.pub_to_b32 pub = rsa_public_key); + let bks = blinding_key_secret |> decode in + let msg = decode message_hash in + let bmsg = Rsa.blind_msg pub ~bks msg |> encode in + assert (bmsg = blinded_message) + + (* test rsa blind signature, but with a generated key *) + let test_rsa_blind_signing () = + let priv, pub = Rsa.generate ~bits:2048 () in + let bks = "deadbeaf" in + let msg = "uhuh." in + let bmsg = Rsa.blind_msg pub ~bks msg in + let bsig = Rsa.sign ~key:priv bmsg in + let sig_ = Rsa.unblind_sig pub ~bks bsig in + let res = Rsa.verify ~key:pub sig_ ~msg in + get_ok res + + (* test value generated by using taler-typescript-core (taler-util/src/taler-crypto.ts) + at SUPPORTED_EXCHANGE_PROTOCOL_VERSION = "31:0:6" *) + let test_denomination_hash () = + let open Hash in + let rsa_pub = + "040000Y0EAK8KAVYJ3GBT5EJHEE6PQ843PDRPRNBFTPEPQEYCXZ30M0S7B80303C75D1CMK74ZJT7WA7DGWTEK7C26J6GVPR93FX99BWX48HGSN8R9C2V104X6WECY6TYPDCAM3FXEVFVVE610P1C8DPV2GKGWYJ5K91A470CBZ00EASZ6A013B7CZ6SAF7MJS20TBYTVWHN7CPJFV5Q7Q0AXGED999E1G3JC3PY5W4MVC16J5SG2SPRJMW5YGM0N1C64NCZBDBTA9HW009TEV5NBCNRQ9GK54AEDY84SVEF4V43ZCPMQ6M3ZWZGQNBX8EF19NCKVQN7MMRCDCY7A9MVJSDEBRZDQ4ZKRVT2C35225KM660ZQ731B9ZYH9JQ35WQ93MKH4PH4AWCJ8EH38JJA93R73M704002" + in + let h_pub = + "X1WDZ01CAP3V8ZRQMXX1CCWNKYDMYYKA6RG3X61N7RBARX85QCDJCDEAEDZNFYC2J22P2C930A13BAGQNVZMFG4M1YM28TCS2WK0T6R" + in + let h_pub' = + rsa_pub + |> Rsa.pub_of_b32 + |> get_ok + |> DenominationHash.hash_of_rsa + |> DenominationHash.to_b32 + in + assert (h_pub' = h_pub) +end + +let () = + (* ! init RNG *) + Mirage_crypto_rng_unix.use_default (); + test_b32 (); + test_eddsa (); + test_rsa (); + test_json (); + test_amount (); + + let open Test_crypto in + test_hash64 (); + test_eddsa (); + test_eddsa_signing (); + test_kdf (); + test_rsa_blind_msg (); + test_rsa_blind_signing (); + test_denomination_hash (); () diff --git a/test/test_crypto.ml b/test/test_crypto.ml deleted file mode 100644 index 7b4e7417..00000000 --- a/test/test_crypto.ml +++ /dev/null @@ -1,145 +0,0 @@ -(* Test vectors taken from GNUnet: - https://git.gnunet.org/gnunet/gnunet/file/src/cli/util/crypto-test-vectors.json.html *) - -let encode = B32.encode -let decode s = B32.decode s |> Result.get_ok - -let () = - (* hash *) - let input = "91JPRV3F5GG4EKJNDSJQ8" in - let expected = - "D0R24RZ1TPASVQ2NY56CT8AJDYZE9ZGDB0GVZ05E9D4YGZQW2RC5YFPQ0Q86EPW836DY7VYQTNFFJT3ZR2K508F4JVS5JNJKYN2MMFR" - in - let output = - input |> decode |> Hash.H64.hash |> Hash.H64.to_octets |> encode - in - assert (output = expected); - - () - -let () = - (* eddsa_key_derivation *) - let pub = "3M9KK1WSNM1RTY5P72HKFA264V4B7MVHVJ08Y90CV06DYHV8XPP0" in - let priv = "8QC2VNF8443S5KPNKMB4XMV58BTHWAKZ7SVW5WG3KRB37567XS90" in - let pub' = - let open Crypto in - priv - |> decode - |> EddsaPrivateKey.of_octets - |> Result.get_ok - |> EddsaPrivateKey.pub_of_priv - |> EddsaPublicKey.to_octets - |> encode - in - assert (pub = pub'); - - () - -let () = - (* eddsa_signing *) - let priv = "5077XJR9AMH4T97ACKFBVBJD0KFENHPV66B2Y1JBSKXBJKNZJ4E0" in - let pub = "6E2F03JJ8AEDANTTZZ4SBZDFEEZSF8A9DVGTS6VFBCVZQYQ46RRG" in - let data = "00000300000000000000" in - let sig_ = - "XCNJGJ96WPDH60YVMH6C74NGQSGJE3BC1TYMGX6BHY5DMZZZKTB373QTXJ507K5EBSG9YS2EYKHCX3ATRQ6P5MY9MXC4ZB1XSZ2X23G" - in - let open Crypto in - let msg = decode data in - let eddsa_priv = - priv |> decode |> EddsaPrivateKey.of_octets |> Result.get_ok - in - let sig_' = - EddsaSignature.sign ~key:eddsa_priv msg - |> EddsaSignature.to_octets - |> encode - in - assert (sig_ = sig_'); - let eddsa_pub = pub |> decode |> EddsaPublicKey.of_octets |> Result.get_ok in - let eddsa_sig = sig_ |> decode |> EddsaSignature.of_octets |> Result.get_ok in - let () = - EddsaSignature.verify ~key:eddsa_pub eddsa_sig ~msg |> Result.get_ok - in - - () - -let () = - (* kdf *) - let salt = "94KPT83PCNS7J83KC5P78Y8" in - let ikm = "94KPT83MD1JJ0WV5CDS6AX10D5Q70XBM41NPAY90DNGQ8SBJD5GPR" in - let ctx = - "94KPT83141HPYVKMCNW78833D1TPWTSC41GPRWVF41NPWVVQDRG62WS04XMPWSKF4WG6JVH0EHM6A82J8S1G" - in - let out_len = 64 in - let out = - "GTMR4QT05Z9WF5HKVG0WK9RPXGHSMHJNW377G9GJXCA8B0FEKPF4D27RJMSJZYWSQNTBJ5EYVV7ZW18B48Z0JVJJ80RHB706Y96Q358" - in - - let xts = salt |> decode in - let ikm = ikm |> decode in - let ctx = ctx |> decode in - let okm = Fdh_rsa.Kdf.kdf ~xts ~ikm ~ctx ~len:out_len in - let okm = okm |> encode in - assert (okm = out); - - () - -let () = - (* rsa_blind_signing *) - (* rsa_private_key data is given in gcrypt sexpr format.. *) - let message_hash = - "XKQMJ4CNTXBFE1V2WR6JS063J7PZQE4XMB5JH3RS5X0THQ1JQSQ69Y7KDBC9TYRJEZH48MEPY2SF4QHQ4VHXC0YQX5935MQEGP0AX6R" - in - let rsa_public_key = - "040000YRN1NVJ68RS6RJF52PGRCQG19ZKWQPSTJX2G7ZDCKSZFE2VW3HHA81YF5C639JHJF5TX8YTEE2FW2WQCG1PTKNBSPPJEJGA032CN3E8QZ27VWY0K6JFT8ZSYWRH2SKDMXW56A4QKY46JJBWJ6T0ZRVBW6S1HTHXVE2RW8MXRW5T801077MDY13N5F8Z1JZVKBJ06TK3S0YPEDBXK0VEHRHEQJ5X5XYKR4KQTFAZNBMKXY8836VCHBXTK4YNX6AJ1CK29SMJH3Z3QRM16A2TNQGFR0HSMV446BF7FMT2E379ZAT5ST4G3BM2NWZYW545S2SW5MG5S6M88XZZ7SKFD48YVXNZ205GGSEYJPVBMR76WG4ZG30WBCPC1N54XE12RMAG81D8C09WG22PKGGDHYXX68N04002" - in - let blinding_key_secret = - "3SWF49XZPHQMENTSBZQR7Z0B8ZSZ2JRARE79Q4VXZMQ7W6QABXMG" - in - let blinded_message = - "3KHKZJZ30ABB4E56MA2V0EQWGCWH0QQG9P2ZHYHR186C5HZXJMM4N9WXAQTKS94QSV9Y17GGNXN5MB1PZZFG7Q0FY88QPKKRG4MYCPSMTZK5W59R0MJVNJ4P4AQM96TDG5W7RV8GSNR1QQZ1GNHW3CX6D6ZRTMXB2NKB5SSYTDJS79F5ZFBRZ4HVED9JBBPWSR79KVV5QQ4APBGHBCKGMF9NJJS53A1BVYHDEVYAGFYF2SNEP827ZP50FKJ5GKGV8NQ15ESEZ69AT7GJG0T3TZVENY2YN9CVR98W3BKEZ53J7VTANARG8SJS8AMJQ7S23P5HRJ7XE9KTNRNXKH49MXV9JHHYE5535N7AGWEKR47SBCGNF44Z7XJ9RV5BQV12ZRJKN4HBZQHDNCMH3QKX9Z6G64" - in - let open Crypto in - let pub = rsa_public_key |> RsaPublicKey.of_b32 |> Result.get_ok in - assert (RsaPublicKey.to_b32 pub = rsa_public_key); - let bks = blinding_key_secret |> decode in - let msg = decode message_hash in - let bmsg = Fdh_rsa.blind_msg pub ~bks msg in - assert (encode bmsg = blinded_message); - - () - -let () = Mirage_crypto_rng_unix.use_default () - -let () = - let open Crypto in - let priv, pub = RsaPrivateKey.generate ~bits:2048 () in - let bks = "deadbeaf" in - let msg = "uhuh." in - let bmsg = Fdh_rsa.blind_msg pub ~bks msg in - let bsig = Fdh_rsa.sign ~key:priv bmsg in - let sig_ = Fdh_rsa.unblind_sig pub ~bks bsig in - let res = Fdh_rsa.verify ~key:pub sig_ ~msg in - assert (Result.is_ok res); - - () - -let () = - (* denomination-hash *) - (* test value generated by using taler-typescript-core (taler-util/src/taler-crypto.ts) - at SUPPORTED_EXCHANGE_PROTOCOL_VERSION = "31:0:6" *) - let rsa_pub = - "040000Y0EAK8KAVYJ3GBT5EJHEE6PQ843PDRPRNBFTPEPQEYCXZ30M0S7B80303C75D1CMK74ZJT7WA7DGWTEK7C26J6GVPR93FX99BWX48HGSN8R9C2V104X6WECY6TYPDCAM3FXEVFVVE610P1C8DPV2GKGWYJ5K91A470CBZ00EASZ6A013B7CZ6SAF7MJS20TBYTVWHN7CPJFV5Q7Q0AXGED999E1G3JC3PY5W4MVC16J5SG2SPRJMW5YGM0N1C64NCZBDBTA9HW009TEV5NBCNRQ9GK54AEDY84SVEF4V43ZCPMQ6M3ZWZGQNBX8EF19NCKVQN7MMRCDCY7A9MVJSDEBRZDQ4ZKRVT2C35225KM660ZQ731B9ZYH9JQ35WQ93MKH4PH4AWCJ8EH38JJA93R73M704002" - in - let h_pub = - "X1WDZ01CAP3V8ZRQMXX1CCWNKYDMYYKA6RG3X61N7RBARX85QCDJCDEAEDZNFYC2J22P2C930A13BAGQNVZMFG4M1YM28TCS2WK0T6R" - in - let open Crypto in - let h_pub' = - RsaPublicKey.of_b32 rsa_pub - |> Result.get_ok - |> DenominationHash.hash_of_rsa - |> DenominationHash.to_b32 - in - assert (h_pub' = h_pub); - - () diff --git a/test/validate_response.ml b/test/validate_response.ml index 77a3c718..eaa5f741 100644 --- a/test/validate_response.ml +++ b/test/validate_response.ml @@ -1,4 +1,5 @@ open Syntax +open Hash let keys content = let open Api in @@ -27,7 +28,7 @@ let keys content = let open Signatures.MasterWireFee in verify v.master_public_key sig_ { - h_wire_method= Hash.Cstring.H64.hash wire_method; + h_wire_method= H64_cstring.hash wire_method; start_date; end_date; wire_fee; @@ -84,7 +85,7 @@ let keys content = AuditorKeys. { auditor_pub; auditor_url; auditor_name= _; denomination_keys } -> - let auditor_url_hash = Hash.H64.hash auditor_url in + let auditor_url_hash = H64_cstring.hash auditor_url in denomination_keys |> List.map (fun AuditorDenominationKey.{ denom_pub_h; auditor_sig } ->