diff --git a/Cargo.lock b/Cargo.lock index 5398e0f..90d03ca 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -15,27 +15,27 @@ dependencies = [ [[package]] name = "autocfg" -version = "1.0.1" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a" +checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" [[package]] name = "az" -version = "1.1.1" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "822d7d63e0c0260a050f6b1f0d316f5c79b9eab830aca526ed904e1011bd64ca" +checksum = "f771a5d1f5503f7f4279a30f3643d3421ba149848b89ecaaec0ea2acf04a5ac4" [[package]] name = "bitflags" -version = "1.2.1" +version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693" +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "bstr" -version = "0.2.16" +version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90682c8d613ad3373e66de8c6411e0ae2ab2571e879d2efbf73558cc66f21279" +checksum = "ba3569f383e8f1598449f1a423e72e99569137b47740b1da11ef19af3d5c3223" dependencies = [ "lazy_static", "memchr", @@ -45,9 +45,9 @@ dependencies = [ [[package]] name = "bumpalo" -version = "3.7.0" +version = "3.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c59e7af012c713f529e7a3ee57ce9b31ddd858d4b512923602f74608b009631" +checksum = "a4a45a46ab1f2412e53d3a0ade76ffad2025804294569aae387231a0cd6e0899" [[package]] name = "byteorder" @@ -78,9 +78,9 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "clap" -version = "2.33.3" +version = "2.34.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "37e58ac78573c40708d45522f0d80fa2f01cc4f9b4e2bf749807255454312002" +checksum = "a0610544180c38b88101fecf2dd634b174a62eef6946f84dfc6a7127512b381c" dependencies = [ "bitflags", "textwrap", @@ -89,16 +89,16 @@ dependencies = [ [[package]] name = "criterion" -version = "0.3.4" +version = "0.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ab327ed7354547cc2ef43cbe20ef68b988e70b4b593cbd66a2a61733123a3d23" +checksum = "1604dafd25fba2fe2d5895a9da139f8dc9b319a5fe5354ca137cbbce4e178d10" dependencies = [ "atty", "cast", "clap", "criterion-plot", "csv", - "itertools 0.10.1", + "itertools", "lazy_static", "num-traits", "oorandom", @@ -115,19 +115,19 @@ dependencies = [ [[package]] name = "criterion-plot" -version = "0.4.3" +version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e022feadec601fba1649cfa83586381a4ad31c6bf3a9ab7d408118b05dd9889d" +checksum = "d00996de9f2f7559f7f4dc286073197f83e92256a59ed395f9aac01fe717da57" dependencies = [ "cast", - "itertools 0.9.0", + "itertools", ] [[package]] name = "crossbeam-channel" -version = "0.5.1" +version = "0.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "06ed27e177f16d65f0f0c22a213e17c696ace5dd64b14258b52f9417ccb52db4" +checksum = "5aaa7bd5fb665c6864b5f963dd9097905c54125909c7aa94c9e18507cdbe6c53" dependencies = [ "cfg-if", "crossbeam-utils", @@ -135,9 +135,9 @@ dependencies = [ [[package]] name = "crossbeam-deque" -version = "0.8.0" +version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94af6efb46fef72616855b036a624cf27ba656ffc9be1b9a3c931cfc7749a9a9" +checksum = "6455c0ca19f0d2fbf751b908d5c55c1f5cbc65e03c4225427254b46890bdde1e" dependencies = [ "cfg-if", "crossbeam-epoch", @@ -146,10 +146,11 @@ dependencies = [ [[package]] name = "crossbeam-epoch" -version = "0.9.5" +version = "0.9.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ec02e091aa634e2c3ada4a392989e7c3116673ef0ac5b72232439094d73b7fd" +checksum = "1145cf131a2c6ba0615079ab6a638f7e1973ac9c2634fcbeaaad6114246efe8c" dependencies = [ + "autocfg", "cfg-if", "crossbeam-utils", "lazy_static", @@ -159,9 +160,9 @@ dependencies = [ [[package]] name = "crossbeam-utils" -version = "0.8.5" +version = "0.8.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d82cfc11ce7f2c3faef78d8a684447b40d503d9681acebed6cb728d45940c4db" +checksum = "0bf124c720b7686e3c2663cf54062ab0f68a88af2fb6a030e87e30bf721fcb38" dependencies = [ "cfg-if", "lazy_static", @@ -185,7 +186,7 @@ checksum = "22813a6dc45b335f9bade10bf7271dc477e81113e89eb251a0bc2a8a81c536e1" dependencies = [ "bstr", "csv-core", - "itoa", + "itoa 0.4.8", "ryu", "serde", ] @@ -244,9 +245,9 @@ checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" [[package]] name = "generic-array" -version = "0.14.4" +version = "0.14.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "501466ecc8a30d1d3b7fc9229b122b2ce8ed6e9d9223f1138d4babb253e51817" +checksum = "fd48d33ec7f05fbfa152300fdad764757cbded343c1aa1cff2fbaf4134851803" dependencies = [ "typenum", "version_check", @@ -254,9 +255,9 @@ dependencies = [ [[package]] name = "getrandom" -version = "0.2.3" +version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7fcd999463524c52659517fe2cea98493cfe485d10565e7b0fb07dbba7ad2753" +checksum = "9be70c98951c83b8d2f8f60d7065fa6d5146873094452a1008da8c2f1e4205ad" dependencies = [ "cfg-if", "libc", @@ -265,9 +266,9 @@ dependencies = [ [[package]] name = "glass_pumpkin" -version = "1.0.0" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d55fd8f24d22f64a8a2c2fbf828a8e4d55b16310aa2dfb852cbd8bcfca84233" +checksum = "1f8e0619ae5be682a4103c95df5713341a76c16c3e882e4847381a82461226e5" dependencies = [ "lazy_static", "num-bigint", @@ -278,9 +279,9 @@ dependencies = [ [[package]] name = "gmp-mpfr-sys" -version = "1.4.5" +version = "1.4.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "18e70045792b1d584ef8d8ac5e890a98d9d6499d2d709cf2b23725b6dcb10064" +checksum = "b3d00b0ef965511028498a1668c4a6ef9b0b2501a4a5ab26fb8156408869306e" dependencies = [ "libc", "winapi", @@ -288,9 +289,9 @@ dependencies = [ [[package]] name = "half" -version = "1.7.1" +version = "1.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62aca2aba2d62b4a7f5b33f3712cb1b0692779a56fb510499d5c0aa594daeaf3" +checksum = "eabb4a44450da02c90444cf74558da904edde8fb4e9035a9a6a4e15445af0bd7" [[package]] name = "hamming" @@ -309,33 +310,30 @@ dependencies = [ [[package]] name = "itertools" -version = "0.9.0" +version = "0.10.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "284f18f85651fe11e8a991b2adb42cb078325c996ed026d994719efcfca1d54b" +checksum = "a9a9d19fa1e79b6215ff29b9d6880b706147f16e9b1dbb1e4e5947b5b02bc5e3" dependencies = [ "either", ] [[package]] -name = "itertools" -version = "0.10.1" +name = "itoa" +version = "0.4.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "69ddb889f9d0d08a67338271fa9b62996bc788c7796a5c18cf057420aaed5eaf" -dependencies = [ - "either", -] +checksum = "b71991ff56294aa922b450139ee08b3bfc70982c6b2c7562771375cf73542dd4" [[package]] name = "itoa" -version = "0.4.7" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd25036021b0de88a0aff6b850051563c6516d0bf53f8638938edbb9de732736" +checksum = "1aab8fc367588b89dcee83ab0fd66b72b50b72fa1904d7095045ace2b0c81c35" [[package]] name = "js-sys" -version = "0.3.51" +version = "0.3.57" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "83bdfbace3a0e81a4253f73b49e960b053e396a11012cbd49b9b74d6a2b67062" +checksum = "671a26f820db17c2a2750743f1dd03bafd15b98c9f30c7c2628c024c05d73397" dependencies = [ "wasm-bindgen", ] @@ -348,39 +346,39 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" [[package]] name = "libc" -version = "0.2.97" +version = "0.2.125" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "12b8adadd720df158f4d70dfe7ccc6adb0472d7c55ca83445f6a5ab3e36f8fb6" +checksum = "5916d2ae698f6de9bfb891ad7a8d65c09d232dc58cc4ac433c7da3b2fd84bc2b" [[package]] name = "log" -version = "0.4.14" +version = "0.4.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "51b9bbe6c47d51fc3e1a9b945965946b4c44142ab8792c50835a980d362c2710" +checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e" dependencies = [ "cfg-if", ] [[package]] name = "memchr" -version = "2.4.0" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b16bd47d9e329435e309c58469fe0791c2d0d1ba96ec0954152a5ae2b04387dc" +checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" [[package]] name = "memoffset" -version = "0.6.4" +version = "0.6.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "59accc507f1338036a0477ef61afdae33cde60840f4dfe481319ce3ad116ddf9" +checksum = "5aa361d4faea93603064a027415f07bd8e1d5c88c9fbf68bf56a285428fd79ce" dependencies = [ "autocfg", ] [[package]] name = "num-bigint" -version = "0.4.0" +version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4e0d047c1062aa51e256408c560894e5251f08925980e53cf1aa5bd00eec6512" +checksum = "f93ab6289c7b344a8a9f60f88d80aa20032336fe78da341afc91c8a2341fc75f" dependencies = [ "autocfg", "num-integer", @@ -390,9 +388,9 @@ dependencies = [ [[package]] name = "num-integer" -version = "0.1.44" +version = "0.1.45" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d2cc698a63b549a70bc047073d2949cce27cd1c7b0a4a862d08a8031bc2801db" +checksum = "225d3389fb3509a24c93f5c29eb6bde2586b98d9f016636dff58d7c6f7569cd9" dependencies = [ "autocfg", "num-traits", @@ -400,18 +398,18 @@ dependencies = [ [[package]] name = "num-traits" -version = "0.2.14" +version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a64b1ec5cda2586e284722486d802acf1f7dbdc623e2bfc57e65ca1cd099290" +checksum = "578ede34cf02f8924ab9447f50c28075b4d3e5b269972345e7e0372b38c6cdcd" dependencies = [ "autocfg", ] [[package]] name = "num_cpus" -version = "1.13.0" +version = "1.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05499f3756671c15885fee9034446956fff3f243d6077b91e5767df161f766b3" +checksum = "19e64526ebdee182341572e50e9ad03965aa510cd94427a4549448f285e957a1" dependencies = [ "hermit-abi", "libc", @@ -419,9 +417,9 @@ dependencies = [ [[package]] name = "once_cell" -version = "1.9.0" +version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da32515d9f6e6e489d7bc9d84c71b060db7247dc035bbe44eac88cf87486d8d5" +checksum = "87f3e037eac156d1775da914196f0f37741a274155e34a0b7e427c35d2a2ecb9" [[package]] name = "oorandom" @@ -431,23 +429,35 @@ checksum = "0ab1bc2a289d34bd04a330323ac98a1b4bc82c9d9fcb1e66b63caa84da26b575" [[package]] name = "openssl" -version = "0.10.38" +version = "0.10.40" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c7ae222234c30df141154f159066c5093ff73b63204dcda7121eb082fc56a95" +checksum = "fb81a6430ac911acb25fe5ac8f1d2af1b4ea8a4fdfda0f1ee4292af2e2d8eb0e" dependencies = [ "bitflags", "cfg-if", "foreign-types", "libc", "once_cell", + "openssl-macros", "openssl-sys", ] +[[package]] +name = "openssl-macros" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b501e44f11665960c7e7fcf062c7d96a14ade4aa98116c004b2e37b5be7d736c" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "openssl-sys" -version = "0.9.72" +version = "0.9.73" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7e46109c383602735fa0a2e48dd2b7c892b048e1bf69e5c3b1d804b7d9c203cb" +checksum = "9d5fd19fb3e0a8191c1e34935718976a3e70c112ab9a24af6d7cadccd9d90bc0" dependencies = [ "autocfg", "cc", @@ -458,9 +468,9 @@ dependencies = [ [[package]] name = "pkg-config" -version = "0.3.24" +version = "0.3.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "58893f751c9b0412871a09abd62ecd2a00298c6c83befa223ef98c52aef40cbe" +checksum = "1df8c4ec4b0627e53bdf214615ad287367e482558cf84b109250b37464dc03ae" [[package]] name = "plotters" @@ -492,9 +502,9 @@ dependencies = [ [[package]] name = "ppv-lite86" -version = "0.2.10" +version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac74c624d6b2d21f425f752262f42188365d7b8ff1aff74c82e45136510a4857" +checksum = "eb9f9e6e233e5c4a35559a617bf40a4ec447db2e84c20b55a6f83167b7e57872" [[package]] name = "primal" @@ -533,9 +543,9 @@ checksum = "12e07b550a7cbfcaa567bcd28042919548016ad615b5731633fa5239992d853f" [[package]] name = "primal-sieve" -version = "0.3.1" +version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd0113d948c8f955a7ae96520023fe1e730eadbf26e67c4452f801a485e9d357" +checksum = "70534ba41dd05a43504de90bd27437442aa4a0067187e3c09725d14b0ada4e5b" dependencies = [ "primal-bit", "primal-estimate", @@ -544,32 +554,31 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.27" +version = "1.0.38" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f0d8caf72986c1a598726adc988bb5984792ef84f5ee5aa50209145ee8077038" +checksum = "9027b48e9d4c9175fa2218adf3557f91c1137021739951d4932f5f8268ac48aa" dependencies = [ "unicode-xid", ] [[package]] name = "quote" -version = "1.0.9" +version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3d0b9745dc2debf507c8422de05d7226cc1f0644216dfdfead988f9b1ab32a7" +checksum = "a1feb54ed693b93a84e14094943b84b7c4eae204c512b7ccb95ab0c66d278ad1" dependencies = [ "proc-macro2", ] [[package]] name = "rand" -version = "0.8.4" +version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2e7573632e6454cf6b99d7aac4ccca54be06da05aca2ef7423d22d27d4d4bcd8" +checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" dependencies = [ "libc", "rand_chacha", "rand_core", - "rand_hc", ] [[package]] @@ -591,20 +600,11 @@ dependencies = [ "getrandom", ] -[[package]] -name = "rand_hc" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d51e9f596de227fda2ea6c84607f5558e196eeaf43c986b724ba4fb8fdf497e7" -dependencies = [ - "rand_core", -] - [[package]] name = "rayon" -version = "1.5.1" +version = "1.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c06aca804d41dbc8ba42dfd964f0d01334eceb64314b9ecf7c5fad5188a06d90" +checksum = "fd249e82c21598a9a426a4e00dd7adc1d640b22445ec8545feef801d1a74c221" dependencies = [ "autocfg", "crossbeam-deque", @@ -614,22 +614,21 @@ dependencies = [ [[package]] name = "rayon-core" -version = "1.9.1" +version = "1.9.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d78120e2c850279833f1dd3582f730c4ab53ed95aeaaaa862a2a5c71b1656d8e" +checksum = "9f51245e1e62e1f1629cbfec37b5793bbabcaeb90f30e94d2ba03564687353e4" dependencies = [ "crossbeam-channel", "crossbeam-deque", "crossbeam-utils", - "lazy_static", "num_cpus", ] [[package]] name = "regex" -version = "1.5.4" +version = "1.5.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d07a8629359eb56f1e2fb1652bb04212c072a87ba68546a04065d525673ac461" +checksum = "1a11647b6b25ff05a515cb92c365cec08801e83423a235b51e231e1808747286" dependencies = [ "regex-syntax", ] @@ -648,9 +647,9 @@ checksum = "f497285884f3fcff424ffc933e56d7cbca511def0c9831a7f9b5f6153e3cc89b" [[package]] name = "rug" -version = "1.13.0" +version = "1.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ee0c6e98de59509e62e09f3456b23cebb75dad21928882016f169bb628843459" +checksum = "f829d980ca193fa33fdd1decaebe72ec07cf2d8afdd0be60b3e5391f18014c91" dependencies = [ "az", "gmp-mpfr-sys", @@ -668,9 +667,9 @@ dependencies = [ [[package]] name = "ryu" -version = "1.0.5" +version = "1.0.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "71d301d4193d031abdd79ff7e3dd721168a9572ef3fe51a1517aba235bd8f86e" +checksum = "73b4b750c782965c211b42f022f59af1fbceabdd026623714f104152f1ec149f" [[package]] name = "same-file" @@ -732,21 +731,21 @@ checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" [[package]] name = "semver" -version = "1.0.3" +version = "1.0.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f3aac57ee7f3272d8395c6e4f502f434f0e289fcd62876f70daa008c20dcabe" +checksum = "8cb243bdfdb5936c8dc3c45762a19d12ab4550cdc753bc247637d4ec35a040fd" [[package]] name = "serde" -version = "1.0.126" +version = "1.0.137" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec7505abeacaec74ae4778d9d9328fe5a5d04253220a85c4ee022239fc996d03" +checksum = "61ea8d54c77f8315140a05f4c7237403bf38b72704d031543aa1d16abbf517d1" [[package]] name = "serde_cbor" -version = "0.11.1" +version = "0.11.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e18acfa2f90e8b735b2836ab8d538de304cbb6729a7360729ea5a895d15a622" +checksum = "2bef2ebfde456fb76bbcf9f59315333decc4fda0b2b44b420243c11e0f5ec1f5" dependencies = [ "half", "serde", @@ -754,9 +753,9 @@ dependencies = [ [[package]] name = "serde_derive" -version = "1.0.126" +version = "1.0.137" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "963a7dbc9895aeac7ac90e74f34a5d5261828f79df35cbed41e10189d3804d43" +checksum = "1f26faba0c3959972377d3b2d306ee9f71faee9714294e41bb777f83f88578be" dependencies = [ "proc-macro2", "quote", @@ -765,32 +764,32 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.64" +version = "1.0.81" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "799e97dc9fdae36a5c8b8f2cae9ce2ee9fdce2058c57a93e6099d919fd982f79" +checksum = "9b7ce2b32a1aed03c558dc61a5cd328f15aff2dbc17daad8fb8af04d2100e15c" dependencies = [ - "itoa", + "itoa 1.0.1", "ryu", "serde", ] [[package]] name = "smallvec" -version = "1.6.1" +version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fe0f37c9e8f3c5a4a66ad655a93c74daac4ad00c441533bf5c6e7990bb42604e" +checksum = "f2dd574626839106c320a323308629dcb1acfc96e32a8cba364ddc61ac23ee83" [[package]] name = "subtle" -version = "2.4.0" +version = "2.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e81da0851ada1f3e9d4312c704aa4f8806f0f9d69faaf8df2f3464b4a9437c2" +checksum = "6bdef32e8150c2a081110b42772ffe7d7c9032b606bc226c8260fd97e0976601" [[package]] name = "syn" -version = "1.0.73" +version = "1.0.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f71489ff30030d2ae598524f61326b902466f72a0fb1a8564c001cc63425bcc7" +checksum = "7ff7c592601f11445996a06f8ad0c27f094a58857c2f89e97974ab9235b92c52" dependencies = [ "proc-macro2", "quote", @@ -824,15 +823,15 @@ checksum = "dcf81ac59edc17cc8697ff311e8f5ef2d99fcbd9817b34cec66f90b6c3dfd987" [[package]] name = "unicode-width" -version = "0.1.8" +version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9337591893a19b88d8d87f2cec1e73fad5cdfd10e5a6f349f498ad6ea2ffb1e3" +checksum = "3ed742d4ea2bd1176e236172c8429aaf54486e7ac098db29ffe6529e0ce50973" [[package]] name = "unicode-xid" -version = "0.2.2" +version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ccb82d61f80a663efe1f787a51b16b5a51e3314d6ac365b08639f52387b33f3" +checksum = "957e51f3646910546462e67d5f7599b9e4fb8acdd304b087a6494730f9eebf04" [[package]] name = "vcpkg" @@ -842,9 +841,9 @@ checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" [[package]] name = "version_check" -version = "0.9.3" +version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5fecdca9a5291cc2b8dcf7dc02453fee791a280f3743cb0905f8822ae463b3fe" +checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" [[package]] name = "walkdir" @@ -865,9 +864,9 @@ checksum = "fd6fbd9a79829dd1ad0cc20627bf1ed606756a7f77edff7b66b7064f9cb327c6" [[package]] name = "wasm-bindgen" -version = "0.2.74" +version = "0.2.80" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d54ee1d4ed486f78874278e63e4069fc1ab9f6a18ca492076ffb90c5eb2997fd" +checksum = "27370197c907c55e3f1a9fbe26f44e937fe6451368324e009cba39e139dc08ad" dependencies = [ "cfg-if", "wasm-bindgen-macro", @@ -875,9 +874,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-backend" -version = "0.2.74" +version = "0.2.80" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b33f6a0694ccfea53d94db8b2ed1c3a8a4c86dd936b13b9f0a15ec4a451b900" +checksum = "53e04185bfa3a779273da532f5025e33398409573f348985af9a1cbf3774d3f4" dependencies = [ "bumpalo", "lazy_static", @@ -890,9 +889,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.74" +version = "0.2.80" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "088169ca61430fe1e58b8096c24975251700e7b1f6fd91cc9d59b04fb9b18bd4" +checksum = "17cae7ff784d7e83a2fe7611cfe766ecf034111b49deb850a3dc7699c08251f5" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -900,9 +899,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.74" +version = "0.2.80" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be2241542ff3d9f241f5e2cb6dd09b37efe786df8851c54957683a49f0987a97" +checksum = "99ec0dc7a4756fffc231aab1b9f2f578d23cd391390ab27f952ae0c9b3ece20b" dependencies = [ "proc-macro2", "quote", @@ -913,15 +912,15 @@ dependencies = [ [[package]] name = "wasm-bindgen-shared" -version = "0.2.74" +version = "0.2.80" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d7cff876b8f18eed75a66cf49b65e7f967cb354a7aa16003fb55dbfd25b44b4f" +checksum = "d554b7f530dee5964d9a9468d95c1f8b8acae4f282807e7d27d4b03099a46744" [[package]] name = "web-sys" -version = "0.3.51" +version = "0.3.57" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e828417b379f3df7111d3a2a9e5753706cae29c41f7c4029ee9fd77f3e09e582" +checksum = "7b17e741662c70c8bd24ac5c5b18de314a2c26c32bf8346ee1e6f53de919c283" dependencies = [ "js-sys", "wasm-bindgen", diff --git a/scicrypt-he/src/cryptosystems/curve_el_gamal.rs b/scicrypt-he/src/cryptosystems/curve_el_gamal.rs index aa3879a..a1e6ada 100644 --- a/scicrypt-he/src/cryptosystems/curve_el_gamal.rs +++ b/scicrypt-he/src/cryptosystems/curve_el_gamal.rs @@ -4,11 +4,11 @@ use curve25519_dalek::scalar::Scalar; use scicrypt_traits::cryptosystems::{ Associable, AsymmetricCryptosystem, DecryptionKey, EncryptionKey, }; +use scicrypt_traits::homomorphic::HomomorphicAddition; use scicrypt_traits::randomness::GeneralRng; use scicrypt_traits::randomness::SecureRng; use scicrypt_traits::security::BitsOfSecurity; use std::fmt::{Debug, Formatter}; -use std::ops::{Add, Mul}; /// ElGamal over the Ristretto-encoded Curve25519 elliptic curve. The curve is provided by the /// `curve25519-dalek` crate. ElGamal is a partially homomorphic cryptosystem. @@ -23,41 +23,20 @@ pub struct CurveElGamalCiphertext { pub(crate) c2: RistrettoPoint, } +impl Associable for CurveElGamalCiphertext {} +impl Associable for CurveElGamalCiphertext {} + /// Encryption key for curve-based ElGamal -#[derive(Debug)] +#[derive(PartialEq, Debug)] pub struct CurveElGamalPK { pub(crate) point: RistrettoPoint, } -/// Ciphertext for curve-based ElGamal with the associated public key -#[derive(Debug)] -pub struct AssociatedCurveElGamalCiphertext<'pk> { - pub(crate) ciphertext: CurveElGamalCiphertext, - pub(crate) public_key: &'pk CurveElGamalPK, -} - -impl<'pk> PartialEq for AssociatedPrecomputedCurveElGamalCiphertext<'pk> { - fn eq(&self, other: &Self) -> bool { - self.ciphertext == other.ciphertext - } -} - /// Decryption key for curve-based ElGamal pub struct CurveElGamalSK { key: Scalar, } -impl<'pk> Associable<'pk, CurveElGamalPK, AssociatedCurveElGamalCiphertext<'pk>, RistrettoPoint> - for CurveElGamalCiphertext -{ - fn associate(self, public_key: &CurveElGamalPK) -> AssociatedCurveElGamalCiphertext { - AssociatedCurveElGamalCiphertext { - ciphertext: self, - public_key, - } - } -} - impl CurveElGamalPK { /// Precompute values for the encryption key to speed-up future encryptions pub fn precompute(self) -> PrecomputedCurveElGamalPK { @@ -73,15 +52,10 @@ impl CurveElGamalSK { } } -impl<'pk> - AsymmetricCryptosystem< - 'pk, - PrecomputedCurveElGamalPK, - CurveElGamalSK, - RistrettoPoint, - AssociatedPrecomputedCurveElGamalCiphertext<'pk>, - > for CurveElGamal -{ +impl AsymmetricCryptosystem for CurveElGamal { + type PublicKey = PrecomputedCurveElGamalPK; + type SecretKey = CurveElGamalSK; + fn setup(security_param: &BitsOfSecurity) -> Self { match security_param { BitsOfSecurity::AES128 => (), @@ -107,21 +81,22 @@ impl<'pk> } } -impl<'pk> EncryptionKey<'pk, RistrettoPoint, AssociatedCurveElGamalCiphertext<'pk>> - for CurveElGamalPK -{ - fn encrypt, R: SecureRng>( - &'pk self, - plaintext: IntoP, +impl EncryptionKey for CurveElGamalPK { + type Input = Scalar; + type Plaintext = RistrettoPoint; + type Ciphertext = CurveElGamalCiphertext; + + fn encrypt_raw( + &self, + plaintext: &RistrettoPoint, rng: &mut GeneralRng, - ) -> AssociatedCurveElGamalCiphertext { + ) -> CurveElGamalCiphertext { let y = Scalar::random(rng.rng()); CurveElGamalCiphertext { c1: &y * &RISTRETTO_BASEPOINT_TABLE, - c2: plaintext.into() + y * self.point, + c2: plaintext + y * self.point, } - .associate(self) } } @@ -136,124 +111,95 @@ impl Debug for PrecomputedCurveElGamalPK { } } -/// Associated ciphertext for a precomputed public key -#[derive(Debug)] -pub struct AssociatedPrecomputedCurveElGamalCiphertext<'pk> { - ciphertext: CurveElGamalCiphertext, - #[allow(dead_code)] - public_key: &'pk PrecomputedCurveElGamalPK, -} - -impl<'pk> - Associable< - 'pk, - PrecomputedCurveElGamalPK, - AssociatedPrecomputedCurveElGamalCiphertext<'pk>, - RistrettoPoint, - > for CurveElGamalCiphertext -{ - fn associate( - self, - public_key: &PrecomputedCurveElGamalPK, - ) -> AssociatedPrecomputedCurveElGamalCiphertext { - AssociatedPrecomputedCurveElGamalCiphertext { - ciphertext: self, - public_key, - } +impl PartialEq for PrecomputedCurveElGamalPK { + fn eq(&self, other: &Self) -> bool { + self.point.basepoint() == other.point.basepoint() } } -impl<'pk> EncryptionKey<'pk, RistrettoPoint, AssociatedPrecomputedCurveElGamalCiphertext<'pk>> - for PrecomputedCurveElGamalPK -{ - fn encrypt, R: SecureRng>( - &'pk self, - plaintext: IntoP, +impl EncryptionKey for PrecomputedCurveElGamalPK { + type Input = Scalar; + type Plaintext = RistrettoPoint; + type Ciphertext = CurveElGamalCiphertext; + + fn encrypt_raw( + &self, + plaintext: &RistrettoPoint, rng: &mut GeneralRng, - ) -> AssociatedPrecomputedCurveElGamalCiphertext { + ) -> CurveElGamalCiphertext { let y = Scalar::random(rng.rng()); CurveElGamalCiphertext { c1: &y * &RISTRETTO_BASEPOINT_TABLE, - c2: plaintext.into() + &y * &self.point, + c2: plaintext + &y * &self.point, } - .associate(self) } } // TODO: These double definitions can be made into one generic if associated ciphertexts have a trait -impl DecryptionKey> for CurveElGamalSK { - fn decrypt(&self, associated_ciphertext: &AssociatedCurveElGamalCiphertext) -> RistrettoPoint { - self.decrypt_directly(&associated_ciphertext.ciphertext) +impl DecryptionKey for CurveElGamalSK { + fn decrypt_raw( + &self, + _public_key: &CurveElGamalPK, + ciphertext: &CurveElGamalCiphertext, + ) -> RistrettoPoint { + self.decrypt_directly(ciphertext) } } -impl DecryptionKey> - for CurveElGamalSK -{ - fn decrypt( +impl DecryptionKey for CurveElGamalSK { + fn decrypt_raw( &self, - associated_ciphertext: &AssociatedPrecomputedCurveElGamalCiphertext, + _public_key: &PrecomputedCurveElGamalPK, + ciphertext: &CurveElGamalCiphertext, ) -> RistrettoPoint { - self.decrypt_directly(&associated_ciphertext.ciphertext) + self.decrypt_directly(ciphertext) } } -impl<'pk> Add for &AssociatedCurveElGamalCiphertext<'pk> { - type Output = AssociatedCurveElGamalCiphertext<'pk>; - - /// Homomorphic operation between two ElGamal ciphertexts. - fn add(self, rhs: Self) -> Self::Output { +impl HomomorphicAddition for CurveElGamalPK { + fn add( + &self, + ciphertext_a: Self::Ciphertext, + ciphertext_b: Self::Ciphertext, + ) -> Self::Ciphertext { CurveElGamalCiphertext { - c1: self.ciphertext.c1 + rhs.ciphertext.c1, - c2: self.ciphertext.c2 + rhs.ciphertext.c2, + c1: ciphertext_a.c1 + ciphertext_b.c1, + c2: ciphertext_a.c2 + ciphertext_b.c2, } - .associate(self.public_key) } -} -impl<'pk> Add for &AssociatedPrecomputedCurveElGamalCiphertext<'pk> { - type Output = AssociatedPrecomputedCurveElGamalCiphertext<'pk>; - - /// Homomorphic operation between two ElGamal ciphertexts. - fn add(self, rhs: Self) -> Self::Output { + fn mul(&self, ciphertext: Self::Ciphertext, input: Self::Input) -> Self::Ciphertext { CurveElGamalCiphertext { - c1: self.ciphertext.c1 + rhs.ciphertext.c1, - c2: self.ciphertext.c2 + rhs.ciphertext.c2, + c1: ciphertext.c1 * input, + c2: ciphertext.c2 * input, } - .associate(self.public_key) } } -impl<'pk> Mul<&Scalar> for &AssociatedCurveElGamalCiphertext<'pk> { - type Output = AssociatedCurveElGamalCiphertext<'pk>; - - fn mul(self, rhs: &Scalar) -> Self::Output { +impl HomomorphicAddition for PrecomputedCurveElGamalPK { + fn add( + &self, + ciphertext_a: Self::Ciphertext, + ciphertext_b: Self::Ciphertext, + ) -> Self::Ciphertext { CurveElGamalCiphertext { - c1: self.ciphertext.c1 * rhs, - c2: self.ciphertext.c2 * rhs, + c1: ciphertext_a.c1 + ciphertext_b.c1, + c2: ciphertext_a.c2 + ciphertext_b.c2, } - .associate(self.public_key) } -} - -impl<'pk> Mul<&Scalar> for &AssociatedPrecomputedCurveElGamalCiphertext<'pk> { - type Output = AssociatedPrecomputedCurveElGamalCiphertext<'pk>; - fn mul(self, rhs: &Scalar) -> Self::Output { + fn mul(&self, ciphertext: Self::Ciphertext, input: Self::Input) -> Self::Ciphertext { CurveElGamalCiphertext { - c1: self.ciphertext.c1 * rhs, - c2: self.ciphertext.c2 * rhs, + c1: ciphertext.c1 * input, + c2: ciphertext.c2 * input, } - .associate(self.public_key) } } #[cfg(test)] mod tests { - use crate::cryptosystems::curve_el_gamal::{ - AssociatedPrecomputedCurveElGamalCiphertext, CurveElGamal, - }; + use crate::cryptosystems::curve_el_gamal::CurveElGamal; use curve25519_dalek::constants::RISTRETTO_BASEPOINT_POINT; use curve25519_dalek::scalar::Scalar; use rand_core::OsRng; @@ -267,8 +213,7 @@ mod tests { let el_gamal = CurveElGamal::setup(&Default::default()); let (pk, sk) = el_gamal.generate_keys(&mut rng); - let ciphertext: AssociatedPrecomputedCurveElGamalCiphertext = - pk.encrypt(RISTRETTO_BASEPOINT_POINT, &mut rng); + let ciphertext = pk.encrypt(&RISTRETTO_BASEPOINT_POINT, &mut rng); assert_eq!(RISTRETTO_BASEPOINT_POINT, sk.decrypt(&ciphertext)); } @@ -280,8 +225,8 @@ mod tests { let el_gamal = CurveElGamal::setup(&Default::default()); let (pk, _) = el_gamal.generate_keys(&mut rng); - let ciphertext1 = pk.encrypt(RISTRETTO_BASEPOINT_POINT, &mut rng); - let ciphertext2 = pk.encrypt(RISTRETTO_BASEPOINT_POINT, &mut rng); + let ciphertext1 = pk.encrypt(&RISTRETTO_BASEPOINT_POINT, &mut rng); + let ciphertext2 = pk.encrypt(&RISTRETTO_BASEPOINT_POINT, &mut rng); assert_ne!(ciphertext1, ciphertext2); } @@ -293,8 +238,9 @@ mod tests { let el_gamal = CurveElGamal::setup(&Default::default()); let (pk, sk) = el_gamal.generate_keys(&mut rng); - let ciphertext = pk.encrypt(RISTRETTO_BASEPOINT_POINT, &mut rng); - let ciphertext_twice = &ciphertext + &ciphertext; + let ciphertext_a = pk.encrypt(&RISTRETTO_BASEPOINT_POINT, &mut rng); + let ciphertext_b = pk.encrypt(&RISTRETTO_BASEPOINT_POINT, &mut rng); + let ciphertext_twice = ciphertext_a + ciphertext_b; assert_eq!( &Scalar::from(2u64) * &RISTRETTO_BASEPOINT_POINT, @@ -309,8 +255,8 @@ mod tests { let el_gamal = CurveElGamal::setup(&Default::default()); let (pk, sk) = el_gamal.generate_keys(&mut rng); - let ciphertext = pk.encrypt(RISTRETTO_BASEPOINT_POINT, &mut rng); - let ciphertext_thrice = &ciphertext * &Scalar::from(3u64); + let ciphertext = pk.encrypt(&RISTRETTO_BASEPOINT_POINT, &mut rng); + let ciphertext_thrice = ciphertext * Scalar::from(3u64); assert_eq!( &Scalar::from(3u64) * &RISTRETTO_BASEPOINT_POINT, diff --git a/scicrypt-he/src/cryptosystems/integer_el_gamal.rs b/scicrypt-he/src/cryptosystems/integer_el_gamal.rs index 29b94b9..812548e 100644 --- a/scicrypt-he/src/cryptosystems/integer_el_gamal.rs +++ b/scicrypt-he/src/cryptosystems/integer_el_gamal.rs @@ -1,10 +1,13 @@ use crate::constants::{SAFE_PRIME_1024, SAFE_PRIME_2048, SAFE_PRIME_3072}; use rug::Integer; -use scicrypt_traits::cryptosystems::{AsymmetricCryptosystem, DecryptionKey, EncryptionKey}; +use scicrypt_traits::cryptosystems::{ + Associable, AsymmetricCryptosystem, DecryptionKey, EncryptionKey, +}; +use scicrypt_traits::homomorphic::HomomorphicMultiplication; use scicrypt_traits::randomness::GeneralRng; use scicrypt_traits::randomness::SecureRng; use scicrypt_traits::security::BitsOfSecurity; -use std::ops::{Mul, Rem}; +use std::ops::Rem; /// Multiplicatively homomorphic ElGamal over a safe prime group where the generator is 4. /// @@ -20,10 +23,10 @@ use std::ops::{Mul, Rem}; /// let el_gamal = IntegerElGamal::setup(&Default::default()); /// let (public_key, secret_key) = el_gamal.generate_keys(&mut rng); /// -/// let ciphertext_1 = public_key.encrypt(4, &mut rng); -/// let ciphertext_2 = public_key.encrypt(6, &mut rng); +/// let ciphertext_1 = public_key.encrypt(&Integer::from(4), &mut rng); +/// let ciphertext_2 = public_key.encrypt(&Integer::from(6), &mut rng); /// -/// println!("[4] * [6] = [{}]", secret_key.decrypt(&(&ciphertext_1 * &ciphertext_2))); +/// println!("[4] * [6] = [{}]", secret_key.decrypt(&(ciphertext_1 * ciphertext_2))); /// // Prints: "[4] * [6] = [24]". /// ``` #[derive(Clone)] @@ -32,6 +35,7 @@ pub struct IntegerElGamal { } /// Public key containing the ElGamal encryption key and the modulus of the group. +#[derive(PartialEq, Debug)] pub struct IntegerElGamalPK { pub(crate) h: Integer, pub(crate) modulus: Integer, @@ -43,36 +47,17 @@ pub struct IntegerElGamalCiphertext { pub(crate) c2: Integer, } -/// ElGamal ciphertext of integers, associated with a public key -pub struct AssociatedIntegerElGamalCiphertext<'pk> { - pub(crate) ciphertext: IntegerElGamalCiphertext, - pub(crate) public_key: &'pk IntegerElGamalPK, -} - -impl IntegerElGamalCiphertext { - //Associable> for - fn associate(self, public_key: &IntegerElGamalPK) -> AssociatedIntegerElGamalCiphertext { - AssociatedIntegerElGamalCiphertext { - ciphertext: self, - public_key, - } - } -} +impl Associable for IntegerElGamalCiphertext {} /// Decryption key for Integer-based ElGamal pub struct IntegerElGamalSK { pub(crate) key: Integer, } -impl<'pk> - AsymmetricCryptosystem< - 'pk, - IntegerElGamalPK, - IntegerElGamalSK, - Integer, - AssociatedIntegerElGamalCiphertext<'pk>, - > for IntegerElGamal -{ +impl AsymmetricCryptosystem for IntegerElGamal { + type PublicKey = IntegerElGamalPK; + type SecretKey = IntegerElGamalSK; + /// Uses previously randomly generated safe primes as the modulus for pre-set modulus sizes. fn setup(security_param: &BitsOfSecurity) -> Self { IntegerElGamal { @@ -119,9 +104,11 @@ impl<'pk> } } -impl<'pk> EncryptionKey<'pk, Integer, AssociatedIntegerElGamalCiphertext<'pk>> - for IntegerElGamalPK -{ +impl EncryptionKey for IntegerElGamalPK { + type Input = Integer; + type Plaintext = Integer; + type Ciphertext = IntegerElGamalCiphertext; + /// Encrypts an integer using the public key. /// ``` /// # use scicrypt_traits::randomness::GeneralRng; @@ -133,26 +120,25 @@ impl<'pk> EncryptionKey<'pk, Integer, AssociatedIntegerElGamalCiphertext<'pk>> /// # let mut rng = GeneralRng::new(OsRng); /// # let el_gamal = IntegerElGamal::setup(&Default::default()); /// # let (public_key, secret_key) = el_gamal.generate_keys(&mut rng); - /// let ciphertext = public_key.encrypt(5, &mut rng); + /// let ciphertext = public_key.encrypt(&Integer::from(5), &mut rng); /// ``` - fn encrypt, R: SecureRng>( - &'pk self, - plaintext: IntoP, + fn encrypt_raw( + &self, + plaintext: &Integer, rng: &mut GeneralRng, - ) -> AssociatedIntegerElGamalCiphertext { + ) -> IntegerElGamalCiphertext { let q = Integer::from(&self.modulus >> 1); let y = q.random_below(&mut rng.rug_rng()); IntegerElGamalCiphertext { c1: Integer::from(Integer::from(4).secure_pow_mod_ref(&y, &self.modulus)), - c2: (plaintext.into() * Integer::from(self.h.secure_pow_mod_ref(&y, &self.modulus))) + c2: (plaintext * Integer::from(self.h.secure_pow_mod_ref(&y, &self.modulus))) .rem(&self.modulus), } - .associate(self) } } -impl DecryptionKey> for IntegerElGamalSK { +impl DecryptionKey for IntegerElGamalSK { /// Decrypts an ElGamal ciphertext using the secret key. /// ``` /// # use scicrypt_traits::randomness::GeneralRng; @@ -164,58 +150,44 @@ impl DecryptionKey> for IntegerE /// # let mut rng = GeneralRng::new(OsRng); /// # let el_gamal = IntegerElGamal::setup(&Default::default()); /// # let (public_key, secret_key) = el_gamal.generate_keys(&mut rng); - /// # let ciphertext = public_key.encrypt(5, &mut rng); + /// # let ciphertext = public_key.encrypt(&Integer::from(5), &mut rng); /// println!("The decrypted message is {}", secret_key.decrypt(&ciphertext)); /// // Prints: "The decrypted message is 5". /// ``` - fn decrypt(&self, associated_ciphertext: &AssociatedIntegerElGamalCiphertext) -> Integer { - (&associated_ciphertext.ciphertext.c2 + fn decrypt_raw( + &self, + public_key: &IntegerElGamalPK, + ciphertext: &IntegerElGamalCiphertext, + ) -> Integer { + (&ciphertext.c2 * Integer::from( - associated_ciphertext - .ciphertext + ciphertext .c1 - .secure_pow_mod_ref(&self.key, &associated_ciphertext.public_key.modulus), + .secure_pow_mod_ref(&self.key, &public_key.modulus), ) - .invert(&associated_ciphertext.public_key.modulus) + .invert(&public_key.modulus) .unwrap()) - .rem(&associated_ciphertext.public_key.modulus) + .rem(&public_key.modulus) } } -impl<'pk> Mul for &AssociatedIntegerElGamalCiphertext<'pk> { - type Output = AssociatedIntegerElGamalCiphertext<'pk>; - - fn mul(self, rhs: Self) -> Self::Output { - AssociatedIntegerElGamalCiphertext { - ciphertext: IntegerElGamalCiphertext { - c1: Integer::from(&self.ciphertext.c1 * &rhs.ciphertext.c1) - .rem(&self.public_key.modulus), - c2: Integer::from(&self.ciphertext.c2 * &rhs.ciphertext.c2) - .rem(&self.public_key.modulus), - }, - public_key: self.public_key, +impl HomomorphicMultiplication for IntegerElGamalPK { + fn mul( + &self, + ciphertext_a: Self::Ciphertext, + ciphertext_b: Self::Ciphertext, + ) -> Self::Ciphertext { + IntegerElGamalCiphertext { + c1: Integer::from(&ciphertext_a.c1 * &ciphertext_b.c1).rem(&self.modulus), + c2: Integer::from(&ciphertext_a.c2 * &ciphertext_b.c2).rem(&self.modulus), } } -} -impl<'pk> AssociatedIntegerElGamalCiphertext<'pk> { - /// Computes the ciphertext corresponding to the plaintext raised to a scalar power. - pub fn pow(&self, rhs: &Integer) -> AssociatedIntegerElGamalCiphertext { + fn pow(&self, ciphertext: Self::Ciphertext, input: Self::Input) -> Self::Ciphertext { IntegerElGamalCiphertext { - c1: Integer::from( - self.ciphertext - .c1 - .pow_mod_ref(rhs, &self.public_key.modulus) - .unwrap(), - ), - c2: Integer::from( - self.ciphertext - .c2 - .pow_mod_ref(rhs, &self.public_key.modulus) - .unwrap(), - ), + c1: Integer::from(ciphertext.c1.pow_mod_ref(&input, &self.modulus).unwrap()), + c2: Integer::from(ciphertext.c2.pow_mod_ref(&input, &self.modulus).unwrap()), } - .associate(self.public_key) } } @@ -234,7 +206,7 @@ mod tests { let el_gamal = IntegerElGamal::setup(&Default::default()); let (pk, sk) = el_gamal.generate_keys(&mut rng); - let ciphertext = pk.encrypt(19, &mut rng); + let ciphertext = pk.encrypt(&Integer::from(19), &mut rng); assert_eq!(19, sk.decrypt(&ciphertext)); } @@ -246,8 +218,9 @@ mod tests { let el_gamal = IntegerElGamal::setup(&Default::default()); let (pk, sk) = el_gamal.generate_keys(&mut rng); - let ciphertext = pk.encrypt(7, &mut rng); - let ciphertext_twice = &ciphertext * &ciphertext; + let ciphertext_a = pk.encrypt(&Integer::from(7), &mut rng); + let ciphertext_b = pk.encrypt(&Integer::from(7), &mut rng); + let ciphertext_twice = ciphertext_a * ciphertext_b; assert_eq!(49, sk.decrypt(&ciphertext_twice)); } @@ -259,8 +232,8 @@ mod tests { let el_gamal = IntegerElGamal::setup(&Default::default()); let (pk, sk) = el_gamal.generate_keys(&mut rng); - let ciphertext = pk.encrypt(9, &mut rng); - let ciphertext_twice = ciphertext.pow(&Integer::from(4)); + let ciphertext = pk.encrypt(&Integer::from(9), &mut rng); + let ciphertext_twice = ciphertext.pow(Integer::from(4)); assert_eq!(6561, sk.decrypt(&ciphertext_twice)); } diff --git a/scicrypt-he/src/cryptosystems/paillier.rs b/scicrypt-he/src/cryptosystems/paillier.rs index 7ac4f0c..9e5ab67 100644 --- a/scicrypt-he/src/cryptosystems/paillier.rs +++ b/scicrypt-he/src/cryptosystems/paillier.rs @@ -1,10 +1,13 @@ use rug::Integer; use scicrypt_numbertheory::{gen_coprime, gen_rsa_modulus}; -use scicrypt_traits::cryptosystems::{AsymmetricCryptosystem, DecryptionKey, EncryptionKey}; +use scicrypt_traits::cryptosystems::{ + Associable, AsymmetricCryptosystem, DecryptionKey, EncryptionKey, +}; +use scicrypt_traits::homomorphic::HomomorphicAddition; use scicrypt_traits::randomness::GeneralRng; use scicrypt_traits::randomness::SecureRng; use scicrypt_traits::security::BitsOfSecurity; -use std::ops::{Add, Mul, Rem}; +use std::ops::Rem; /// The Paillier cryptosystem. #[derive(Copy, Clone)] @@ -13,6 +16,7 @@ pub struct Paillier { } /// Public key for the Paillier cryptosystem. +#[derive(PartialEq, Debug)] pub struct PaillierPK { n: Integer, g: Integer, @@ -29,26 +33,12 @@ pub struct PaillierCiphertext { c: Integer, } -/// Ciphertext of the Paillier cryptosystem, with an associated public key -pub struct AssociatedPaillierCiphertext<'pk> { - ciphertext: PaillierCiphertext, - public_key: &'pk PaillierPK, -} +impl Associable for PaillierCiphertext {} -impl PaillierCiphertext { - // Associable> for - fn associate(self, public_key: &PaillierPK) -> AssociatedPaillierCiphertext { - AssociatedPaillierCiphertext { - ciphertext: self, - public_key, - } - } -} +impl AsymmetricCryptosystem for Paillier { + type PublicKey = PaillierPK; + type SecretKey = PaillierSK; -impl<'pk> - AsymmetricCryptosystem<'pk, PaillierPK, PaillierSK, Integer, AssociatedPaillierCiphertext<'pk>> - for Paillier -{ fn setup(security_param: &BitsOfSecurity) -> Self { Paillier { modulus_size: security_param.to_public_key_bit_length(), @@ -76,7 +66,11 @@ impl<'pk> } } -impl<'pk> EncryptionKey<'pk, Integer, AssociatedPaillierCiphertext<'pk>> for PaillierPK { +impl EncryptionKey for PaillierPK { + type Input = Integer; + type Plaintext = Integer; + type Ciphertext = PaillierCiphertext; + /// Encrypts a plaintext integer using the Paillier public key. /// ``` /// # use scicrypt_traits::randomness::GeneralRng; @@ -88,13 +82,13 @@ impl<'pk> EncryptionKey<'pk, Integer, AssociatedPaillierCiphertext<'pk>> for Pai /// # let mut rng = GeneralRng::new(OsRng); /// # let paillier = Paillier::setup(&BitsOfSecurity::Other {pk_bits: 160}); /// # let (public_key, secret_key) = paillier.generate_keys(&mut rng); - /// let ciphertext = public_key.encrypt(5, &mut rng); + /// let ciphertext = public_key.encrypt(&Integer::from(5), &mut rng); /// ``` - fn encrypt, R: SecureRng>( - &'pk self, - plaintext: IntoP, + fn encrypt_raw( + &self, + plaintext: &Integer, rng: &mut GeneralRng, - ) -> AssociatedPaillierCiphertext { + ) -> PaillierCiphertext { let n_squared = Integer::from(self.n.square_ref()); let r = gen_coprime(&n_squared, rng); @@ -104,11 +98,10 @@ impl<'pk> EncryptionKey<'pk, Integer, AssociatedPaillierCiphertext<'pk>> for Pai PaillierCiphertext { c: (first * second).rem(&n_squared), } - .associate(self) } } -impl DecryptionKey> for PaillierSK { +impl DecryptionKey for PaillierSK { /// Decrypts a rich Paillier ciphertext using the secret key. /// ``` /// # use scicrypt_traits::randomness::GeneralRng; @@ -120,53 +113,39 @@ impl DecryptionKey> for PaillierSK { /// # let mut rng = GeneralRng::new(OsRng); /// # let paillier = Paillier::setup(&BitsOfSecurity::Other {pk_bits: 160}); /// # let (public_key, secret_key) = paillier.generate_keys(&mut rng); - /// # let ciphertext = public_key.encrypt(5, &mut rng); + /// # let ciphertext = public_key.encrypt(&Integer::from(5), &mut rng); /// println!("The decrypted message is {}", secret_key.decrypt(&ciphertext)); /// // Prints: "The decrypted message is 5". /// ``` - fn decrypt(&self, associated_ciphertext: &AssociatedPaillierCiphertext) -> Integer { - let n_squared = Integer::from(associated_ciphertext.public_key.n.square_ref()); - - let mut inner = Integer::from( - associated_ciphertext - .ciphertext - .c - .secure_pow_mod_ref(&self.lambda, &n_squared), - ); + fn decrypt_raw(&self, public_key: &PaillierPK, ciphertext: &PaillierCiphertext) -> Integer { + let n_squared = Integer::from(public_key.n.square_ref()); + + let mut inner = Integer::from(ciphertext.c.secure_pow_mod_ref(&self.lambda, &n_squared)); inner -= 1; - inner /= &associated_ciphertext.public_key.n; + inner /= &public_key.n; inner *= &self.mu; - inner.rem(&associated_ciphertext.public_key.n) + inner.rem(&public_key.n) } } -#[allow(clippy::suspicious_arithmetic_impl)] -impl<'pk> Add for &AssociatedPaillierCiphertext<'pk> { - type Output = AssociatedPaillierCiphertext<'pk>; - - fn add(self, rhs: Self) -> Self::Output { - AssociatedPaillierCiphertext { - ciphertext: PaillierCiphertext { - c: Integer::from(&self.ciphertext.c * &rhs.ciphertext.c) - .rem(Integer::from(self.public_key.n.square_ref())), - }, - public_key: self.public_key, +impl HomomorphicAddition for PaillierPK { + fn add( + &self, + ciphertext_a: Self::Ciphertext, + ciphertext_b: Self::Ciphertext, + ) -> Self::Ciphertext { + PaillierCiphertext { + c: Integer::from(&ciphertext_a.c * &ciphertext_b.c) + .rem(Integer::from(self.n.square_ref())), } } -} -impl<'pk> Mul<&Integer> for &AssociatedPaillierCiphertext<'pk> { - type Output = AssociatedPaillierCiphertext<'pk>; + fn mul(&self, ciphertext: Self::Ciphertext, input: Self::Input) -> Self::Ciphertext { + let modulus = Integer::from(self.n.square_ref()); - fn mul(self, rhs: &Integer) -> Self::Output { - let modulus = Integer::from(self.public_key.n.square_ref()); - - AssociatedPaillierCiphertext { - ciphertext: PaillierCiphertext { - c: Integer::from(self.ciphertext.c.pow_mod_ref(rhs, &modulus).unwrap()), - }, - public_key: self.public_key, + PaillierCiphertext { + c: Integer::from(ciphertext.c.pow_mod_ref(&input, &modulus).unwrap()), } } } @@ -187,7 +166,7 @@ mod tests { let paillier = Paillier::setup(&BitsOfSecurity::Other { pk_bits: 160 }); let (pk, sk) = paillier.generate_keys(&mut rng); - let ciphertext = pk.encrypt(15, &mut rng); + let ciphertext = pk.encrypt(&Integer::from(15), &mut rng); assert_eq!(15, sk.decrypt(&ciphertext)); } @@ -199,8 +178,9 @@ mod tests { let paillier = Paillier::setup(&BitsOfSecurity::Other { pk_bits: 160 }); let (pk, sk) = paillier.generate_keys(&mut rng); - let ciphertext = pk.encrypt(7, &mut rng); - let ciphertext_twice = &ciphertext + &ciphertext; + let ciphertext_a = pk.encrypt(&Integer::from(7), &mut rng); + let ciphertext_b = pk.encrypt(&Integer::from(7), &mut rng); + let ciphertext_twice = ciphertext_a + ciphertext_b; assert_eq!(Integer::from(14), sk.decrypt(&ciphertext_twice)); } @@ -212,8 +192,8 @@ mod tests { let paillier = Paillier::setup(&BitsOfSecurity::Other { pk_bits: 160 }); let (pk, sk) = paillier.generate_keys(&mut rng); - let ciphertext = pk.encrypt(9, &mut rng); - let ciphertext_twice = &ciphertext * &Integer::from(16); + let ciphertext = pk.encrypt(&Integer::from(9), &mut rng); + let ciphertext_twice = ciphertext * Integer::from(16); assert_eq!(144, sk.decrypt(&ciphertext_twice)); } diff --git a/scicrypt-he/src/cryptosystems/rsa.rs b/scicrypt-he/src/cryptosystems/rsa.rs index 9bfea57..22bb489 100644 --- a/scicrypt-he/src/cryptosystems/rsa.rs +++ b/scicrypt-he/src/cryptosystems/rsa.rs @@ -1,10 +1,13 @@ use rug::Integer; use scicrypt_numbertheory::gen_rsa_modulus; -use scicrypt_traits::cryptosystems::{AsymmetricCryptosystem, DecryptionKey, EncryptionKey}; +use scicrypt_traits::cryptosystems::{ + Associable, AsymmetricCryptosystem, DecryptionKey, EncryptionKey, +}; +use scicrypt_traits::homomorphic::HomomorphicMultiplication; use scicrypt_traits::randomness::GeneralRng; use scicrypt_traits::randomness::SecureRng; use scicrypt_traits::security::BitsOfSecurity; -use std::ops::{Mul, Rem}; +use std::ops::Rem; /// The RSA cryptosystem. #[derive(Copy, Clone)] @@ -13,6 +16,7 @@ pub struct Rsa { } /// Public key for the RSA cryptosystem. +#[derive(PartialEq, Debug)] pub struct RsaPK { n: Integer, e: Integer, @@ -28,23 +32,12 @@ pub struct RsaCiphertext { c: Integer, } -/// Ciphertext of the RSA cryptosystem, with an associated public key -pub struct AssociatedRsaCiphertext<'pk> { - ciphertext: RsaCiphertext, - public_key: &'pk RsaPK, -} +impl Associable for RsaCiphertext {} -impl RsaCiphertext { - /// Associate the ciphertext with a public key - pub fn associate(self, public_key: &RsaPK) -> AssociatedRsaCiphertext { - AssociatedRsaCiphertext { - ciphertext: self, - public_key, - } - } -} +impl AsymmetricCryptosystem for Rsa { + type PublicKey = RsaPK; + type SecretKey = RsaSK; -impl<'pk> AsymmetricCryptosystem<'pk, RsaPK, RsaSK, Integer, AssociatedRsaCiphertext<'pk>> for Rsa { fn setup(security_param: &BitsOfSecurity) -> Self { Rsa { modulus_size: security_param.to_public_key_bit_length(), @@ -61,55 +54,43 @@ impl<'pk> AsymmetricCryptosystem<'pk, RsaPK, RsaSK, Integer, AssociatedRsaCipher } } -impl<'pk> EncryptionKey<'pk, Integer, AssociatedRsaCiphertext<'pk>> for RsaPK { - fn encrypt, R: SecureRng>( - &'pk self, - plaintext: IntoP, +impl EncryptionKey for RsaPK { + type Input = Integer; + type Plaintext = Integer; + type Ciphertext = RsaCiphertext; + + fn encrypt_raw( + &self, + plaintext: &Integer, _rng: &mut GeneralRng, - ) -> AssociatedRsaCiphertext { + ) -> RsaCiphertext { RsaCiphertext { - c: Integer::from(plaintext.into().pow_mod_ref(&self.e, &self.n).unwrap()), + c: Integer::from(plaintext.pow_mod_ref(&self.e, &self.n).unwrap()), } - .associate(self) } } -impl DecryptionKey> for RsaSK { - fn decrypt(&self, associated_ciphertext: &AssociatedRsaCiphertext) -> Integer { - Integer::from( - associated_ciphertext - .ciphertext - .c - .secure_pow_mod_ref(&self.d, &associated_ciphertext.public_key.n), - ) +impl DecryptionKey for RsaSK { + fn decrypt_raw(&self, public_key: &RsaPK, ciphertext: &RsaCiphertext) -> Integer { + Integer::from(ciphertext.c.secure_pow_mod_ref(&self.d, &public_key.n)) } } -impl<'pk> Mul for &AssociatedRsaCiphertext<'pk> { - type Output = AssociatedRsaCiphertext<'pk>; - - fn mul(self, rhs: Self) -> Self::Output { - AssociatedRsaCiphertext { - ciphertext: RsaCiphertext { - c: Integer::from(&self.ciphertext.c * &rhs.ciphertext.c).rem(&self.public_key.n), - }, - public_key: self.public_key, +impl HomomorphicMultiplication for RsaPK { + fn mul( + &self, + ciphertext_a: Self::Ciphertext, + ciphertext_b: Self::Ciphertext, + ) -> Self::Ciphertext { + RsaCiphertext { + c: Integer::from(&ciphertext_a.c * &ciphertext_b.c).rem(&self.n), } } -} -impl<'pk> AssociatedRsaCiphertext<'pk> { - /// Computes the ciphertext corresponding to the plaintext raised to a scalar power. - pub fn pow(&self, rhs: &Integer) -> AssociatedRsaCiphertext { + fn pow(&self, ciphertext: Self::Ciphertext, input: Self::Input) -> Self::Ciphertext { RsaCiphertext { - c: Integer::from( - self.ciphertext - .c - .pow_mod_ref(rhs, &self.public_key.n) - .unwrap(), - ), + c: Integer::from(ciphertext.c.pow_mod_ref(&input, &self.n).unwrap()), } - .associate(self.public_key) } } @@ -129,7 +110,7 @@ mod tests { let rsa = Rsa::setup(&BitsOfSecurity::Other { pk_bits: 160 }); let (pk, sk) = rsa.generate_keys(&mut rng); - let ciphertext = pk.encrypt(15, &mut rng); + let ciphertext = pk.encrypt(&Integer::from(15), &mut rng); assert_eq!(15, sk.decrypt(&ciphertext)); } @@ -141,8 +122,9 @@ mod tests { let rsa = Rsa::setup(&BitsOfSecurity::Other { pk_bits: 160 }); let (pk, sk) = rsa.generate_keys(&mut rng); - let ciphertext = pk.encrypt(7, &mut rng); - let ciphertext_twice = &ciphertext * &ciphertext; + let ciphertext_a = pk.encrypt(&Integer::from(7), &mut rng); + let ciphertext_b = pk.encrypt(&Integer::from(7), &mut rng); + let ciphertext_twice = ciphertext_a * ciphertext_b; assert_eq!(49, sk.decrypt(&ciphertext_twice)); } @@ -154,8 +136,8 @@ mod tests { let rsa = Rsa::setup(&BitsOfSecurity::Other { pk_bits: 160 }); let (pk, sk) = rsa.generate_keys(&mut rng); - let ciphertext = pk.encrypt(9, &mut rng); - let ciphertext_twice = ciphertext.pow(&Integer::from(4)); + let ciphertext = pk.encrypt(&Integer::from(9), &mut rng); + let ciphertext_twice = ciphertext.pow(Integer::from(4)); assert_eq!(Integer::from(6561), sk.decrypt(&ciphertext_twice)); } diff --git a/scicrypt-he/src/threshold_cryptosystems/curve_el_gamal.rs b/scicrypt-he/src/threshold_cryptosystems/curve_el_gamal.rs index 59df6c5..1a0f025 100644 --- a/scicrypt-he/src/threshold_cryptosystems/curve_el_gamal.rs +++ b/scicrypt-he/src/threshold_cryptosystems/curve_el_gamal.rs @@ -1,13 +1,11 @@ -use crate::cryptosystems::curve_el_gamal::{ - AssociatedCurveElGamalCiphertext, CurveElGamalCiphertext, CurveElGamalPK, -}; +use crate::cryptosystems::curve_el_gamal::{CurveElGamalCiphertext, CurveElGamalPK}; use curve25519_dalek::constants::RISTRETTO_BASEPOINT_TABLE; use curve25519_dalek::ristretto::RistrettoPoint; use curve25519_dalek::scalar::Scalar; -use scicrypt_traits::cryptosystems::DecryptionKey; use scicrypt_traits::randomness::GeneralRng; use scicrypt_traits::randomness::SecureRng; use scicrypt_traits::security::BitsOfSecurity; +use scicrypt_traits::threshold_cryptosystems::PartialDecryptionKey; use scicrypt_traits::threshold_cryptosystems::{ DecryptionShare, NOfNCryptosystem, TOfNCryptosystem, }; @@ -26,16 +24,10 @@ pub struct NOfNCurveElGamalSK { /// Decryption share of N-out-of-N curve-based ElGamal pub struct NOfNCurveElGamalShare(CurveElGamalCiphertext); -impl<'pk> - NOfNCryptosystem< - 'pk, - CurveElGamalPK, - NOfNCurveElGamalSK, - RistrettoPoint, - NOfNCurveElGamalShare, - AssociatedCurveElGamalCiphertext<'pk>, - > for NOfNCurveElGamal -{ +impl NOfNCryptosystem for NOfNCurveElGamal { + type PublicKey = CurveElGamalPK; + type SecretKey = NOfNCurveElGamalSK; + fn setup(security_param: &BitsOfSecurity) -> Self { match security_param { BitsOfSecurity::AES128 => (), @@ -65,29 +57,27 @@ impl<'pk> } } -impl DecryptionKey> - for NOfNCurveElGamalSK -{ - fn decrypt( +impl PartialDecryptionKey for NOfNCurveElGamalSK { + type DecryptionShare = NOfNCurveElGamalShare; + + fn partial_decrypt_raw( &self, - associated_ciphertext: &AssociatedCurveElGamalCiphertext, + _public_key: &CurveElGamalPK, + ciphertext: &CurveElGamalCiphertext, ) -> NOfNCurveElGamalShare { NOfNCurveElGamalShare(CurveElGamalCiphertext { - c1: self.key * associated_ciphertext.ciphertext.c1, - c2: associated_ciphertext.ciphertext.c2, + c1: self.key * ciphertext.c1, + c2: ciphertext.c2, }) } } -impl DecryptionShare for NOfNCurveElGamalShare { - type Plaintext = RistrettoPoint; - type PublicKey = CurveElGamalPK; - +impl DecryptionShare for NOfNCurveElGamalShare { #[allow(clippy::op_ref)] fn combine( decryption_shares: &[Self], - _public_key: &Self::PublicKey, - ) -> Result { + _public_key: &CurveElGamalPK, + ) -> Result { Ok(decryption_shares[0].0.c2 - &decryption_shares.iter().map(|share| share.0.c1).sum()) } } @@ -104,16 +94,10 @@ pub struct TOfNCurveElGamalShare { c2: RistrettoPoint, } -impl<'pk> - TOfNCryptosystem< - 'pk, - CurveElGamalPK, - TOfNCurveElGamalSK, - RistrettoPoint, - TOfNCurveElGamalShare, - AssociatedCurveElGamalCiphertext<'pk>, - > for TOfNCurveElGamal -{ +impl TOfNCryptosystem for TOfNCurveElGamal { + type PublicKey = CurveElGamalPK; + type SecretKey = TOfNCurveElGamalSK; + fn setup(security_param: &BitsOfSecurity) -> Self { match security_param { BitsOfSecurity::AES128 => (), @@ -159,34 +143,32 @@ impl<'pk> } /// One of the partial keys, of which t must be used to decrypt successfully. -struct TOfNCurveElGamalSK { +pub struct TOfNCurveElGamalSK { id: i32, key: Scalar, } -impl DecryptionKey> - for TOfNCurveElGamalSK -{ - fn decrypt( +impl PartialDecryptionKey for TOfNCurveElGamalSK { + type DecryptionShare = TOfNCurveElGamalShare; + + fn partial_decrypt_raw( &self, - associated_ciphertext: &AssociatedCurveElGamalCiphertext, + _public_key: &CurveElGamalPK, + ciphertext: &CurveElGamalCiphertext, ) -> TOfNCurveElGamalShare { TOfNCurveElGamalShare { id: self.id, - c1: self.key * associated_ciphertext.ciphertext.c1, - c2: associated_ciphertext.ciphertext.c2, + c1: self.key * ciphertext.c1, + c2: ciphertext.c2, } } } -impl DecryptionShare for TOfNCurveElGamalShare { - type Plaintext = RistrettoPoint; - type PublicKey = CurveElGamalPK; - +impl DecryptionShare for TOfNCurveElGamalShare { fn combine( decryption_shares: &[Self], - _public_key: &Self::PublicKey, - ) -> Result { + _public_key: &CurveElGamalPK, + ) -> Result { let summed: RistrettoPoint = decryption_shares .iter() .enumerate() @@ -224,11 +206,11 @@ mod tests { use curve25519_dalek::constants::RISTRETTO_BASEPOINT_TABLE; use curve25519_dalek::scalar::Scalar; use rand_core::OsRng; - use scicrypt_traits::cryptosystems::{DecryptionKey, EncryptionKey}; + use scicrypt_traits::cryptosystems::EncryptionKey; use scicrypt_traits::randomness::GeneralRng; use scicrypt_traits::security::BitsOfSecurity; use scicrypt_traits::threshold_cryptosystems::{ - DecryptionShare, NOfNCryptosystem, TOfNCryptosystem, + DecryptionShare, NOfNCryptosystem, PartialDecryptionKey, TOfNCryptosystem, }; #[test] @@ -240,11 +222,11 @@ mod tests { let plaintext = &Scalar::from(19u64) * &RISTRETTO_BASEPOINT_TABLE; - let ciphertext = pk.encrypt(plaintext, &mut rng); + let ciphertext = pk.encrypt(&plaintext, &mut rng); - let share_1 = sks[0].decrypt(&ciphertext); - let share_2 = sks[1].decrypt(&ciphertext); - let share_3 = sks[2].decrypt(&ciphertext); + let share_1 = sks[0].partial_decrypt(&ciphertext); + let share_2 = sks[1].partial_decrypt(&ciphertext); + let share_3 = sks[2].partial_decrypt(&ciphertext); assert_eq!( plaintext, @@ -261,10 +243,10 @@ mod tests { let plaintext = &Scalar::from(21u64) * &RISTRETTO_BASEPOINT_TABLE; - let ciphertext = pk.encrypt(plaintext, &mut rng); + let ciphertext = pk.encrypt(&plaintext, &mut rng); - let share_1 = sks[0].decrypt(&ciphertext); - let share_3 = sks[2].decrypt(&ciphertext); + let share_1 = sks[0].partial_decrypt(&ciphertext); + let share_3 = sks[2].partial_decrypt(&ciphertext); assert_eq!( plaintext, diff --git a/scicrypt-he/src/threshold_cryptosystems/integer_el_gamal.rs b/scicrypt-he/src/threshold_cryptosystems/integer_el_gamal.rs index ec47bda..c8cfaac 100644 --- a/scicrypt-he/src/threshold_cryptosystems/integer_el_gamal.rs +++ b/scicrypt-he/src/threshold_cryptosystems/integer_el_gamal.rs @@ -1,14 +1,11 @@ use crate::constants::{SAFE_PRIME_1024, SAFE_PRIME_2048, SAFE_PRIME_3072}; -use crate::cryptosystems::integer_el_gamal::{ - AssociatedIntegerElGamalCiphertext, IntegerElGamalCiphertext, IntegerElGamalPK, -}; +use crate::cryptosystems::integer_el_gamal::{IntegerElGamalCiphertext, IntegerElGamalPK}; use rug::Integer; -use scicrypt_traits::cryptosystems::DecryptionKey; use scicrypt_traits::randomness::GeneralRng; use scicrypt_traits::randomness::SecureRng; use scicrypt_traits::security::BitsOfSecurity; use scicrypt_traits::threshold_cryptosystems::{ - DecryptionShare, NOfNCryptosystem, TOfNCryptosystem, + DecryptionShare, NOfNCryptosystem, PartialDecryptionKey, TOfNCryptosystem, }; use scicrypt_traits::DecryptionError; use std::ops::Rem; @@ -25,16 +22,10 @@ pub struct NOfNIntegerElGamalSK { key: Integer, } -impl<'pk> - NOfNCryptosystem< - 'pk, - IntegerElGamalPK, - NOfNIntegerElGamalSK, - Integer, - NOfNIntegerElGamalShare, - AssociatedIntegerElGamalCiphertext<'pk>, - > for NOfNIntegerElGamal -{ +impl NOfNCryptosystem for NOfNIntegerElGamal { + type PublicKey = IntegerElGamalPK; + type SecretKey = NOfNIntegerElGamalSK; + /// Uses previously randomly generated safe primes as the modulus for pre-set modulus sizes. fn setup(security_param: &BitsOfSecurity) -> Self { NOfNIntegerElGamal { @@ -79,33 +70,30 @@ impl<'pk> /// Decryption share of N-out-of-N integer-based ElGamal pub struct NOfNIntegerElGamalShare(IntegerElGamalCiphertext); -impl DecryptionKey> - for NOfNIntegerElGamalSK -{ - fn decrypt( +impl PartialDecryptionKey for NOfNIntegerElGamalSK { + type DecryptionShare = NOfNIntegerElGamalShare; + + fn partial_decrypt_raw( &self, - associated_ciphertext: &AssociatedIntegerElGamalCiphertext, + public_key: &IntegerElGamalPK, + ciphertext: &IntegerElGamalCiphertext, ) -> NOfNIntegerElGamalShare { NOfNIntegerElGamalShare(IntegerElGamalCiphertext { c1: Integer::from( - associated_ciphertext - .ciphertext + ciphertext .c1 - .secure_pow_mod_ref(&self.key, &associated_ciphertext.public_key.modulus), + .secure_pow_mod_ref(&self.key, &public_key.modulus), ), - c2: Integer::from(&associated_ciphertext.ciphertext.c2), + c2: Integer::from(&ciphertext.c2), }) } } -impl DecryptionShare for NOfNIntegerElGamalShare { - type Plaintext = Integer; - type PublicKey = IntegerElGamalPK; - +impl DecryptionShare for NOfNIntegerElGamalShare { fn combine( decryption_shares: &[Self], - public_key: &Self::PublicKey, - ) -> Result { + public_key: &IntegerElGamalPK, + ) -> Result { Ok((Integer::from( &decryption_shares[0].0.c2 * &decryption_shares @@ -139,16 +127,10 @@ pub struct TOfNIntegerElGamalShare { c2: Integer, } -impl<'pk> - TOfNCryptosystem< - 'pk, - IntegerElGamalPK, - TOfNIntegerElGamalSK, - Integer, - TOfNIntegerElGamalShare, - AssociatedIntegerElGamalCiphertext<'pk>, - > for TOfNIntegerElGamal -{ +impl TOfNCryptosystem for TOfNIntegerElGamal { + type PublicKey = IntegerElGamalPK; + type SecretKey = TOfNIntegerElGamalSK; + /// Uses previously randomly generated safe primes as the modulus for pre-set modulus sizes. fn setup(security_param: &BitsOfSecurity) -> Self { TOfNIntegerElGamal { @@ -206,34 +188,31 @@ impl<'pk> } } -impl DecryptionKey> - for TOfNIntegerElGamalSK -{ - fn decrypt( +impl PartialDecryptionKey for TOfNIntegerElGamalSK { + type DecryptionShare = TOfNIntegerElGamalShare; + + fn partial_decrypt_raw( &self, - associated_ciphertext: &AssociatedIntegerElGamalCiphertext, + public_key: &IntegerElGamalPK, + ciphertext: &IntegerElGamalCiphertext, ) -> TOfNIntegerElGamalShare { TOfNIntegerElGamalShare { id: self.id, c1: Integer::from( - associated_ciphertext - .ciphertext + ciphertext .c1 - .secure_pow_mod_ref(&self.key, &associated_ciphertext.public_key.modulus), + .secure_pow_mod_ref(&self.key, &public_key.modulus), ), - c2: associated_ciphertext.ciphertext.c2.clone(), + c2: ciphertext.c2.clone(), } } } -impl DecryptionShare for TOfNIntegerElGamalShare { - type Plaintext = Integer; - type PublicKey = IntegerElGamalPK; - +impl DecryptionShare for TOfNIntegerElGamalShare { fn combine( decryption_shares: &[Self], - public_key: &Self::PublicKey, - ) -> Result { + public_key: &IntegerElGamalPK, + ) -> Result { let q = Integer::from(&public_key.modulus >> 1); let multiplied: Integer = decryption_shares @@ -279,10 +258,10 @@ mod tests { }; use rand_core::OsRng; use rug::Integer; - use scicrypt_traits::cryptosystems::{DecryptionKey, EncryptionKey}; + use scicrypt_traits::cryptosystems::EncryptionKey; use scicrypt_traits::randomness::GeneralRng; use scicrypt_traits::threshold_cryptosystems::{ - DecryptionShare, NOfNCryptosystem, TOfNCryptosystem, + DecryptionShare, NOfNCryptosystem, PartialDecryptionKey, TOfNCryptosystem, }; #[test] @@ -294,11 +273,11 @@ mod tests { let plaintext = Integer::from(25); - let ciphertext = pk.encrypt(Integer::from(&plaintext), &mut rng); + let ciphertext = pk.encrypt(&Integer::from(&plaintext), &mut rng); - let share_1 = sks[0].decrypt(&ciphertext); - let share_2 = sks[1].decrypt(&ciphertext); - let share_3 = sks[2].decrypt(&ciphertext); + let share_1 = sks[0].partial_decrypt(&ciphertext); + let share_2 = sks[1].partial_decrypt(&ciphertext); + let share_3 = sks[2].partial_decrypt(&ciphertext); assert_eq!( plaintext, @@ -315,10 +294,10 @@ mod tests { let plaintext = Integer::from(2100u64); - let ciphertext = pk.encrypt(Integer::from(&plaintext), &mut rng); + let ciphertext = pk.encrypt(&plaintext, &mut rng); - let share_1 = sks[0].decrypt(&ciphertext); - let share_3 = sks[2].decrypt(&ciphertext); + let share_1 = sks[0].partial_decrypt(&ciphertext); + let share_3 = sks[2].partial_decrypt(&ciphertext); assert_eq!( plaintext, diff --git a/scicrypt-he/src/threshold_cryptosystems/paillier.rs b/scicrypt-he/src/threshold_cryptosystems/paillier.rs index 4d2e2f1..c372b82 100644 --- a/scicrypt-he/src/threshold_cryptosystems/paillier.rs +++ b/scicrypt-he/src/threshold_cryptosystems/paillier.rs @@ -1,10 +1,12 @@ use rug::Integer; use scicrypt_numbertheory::{gen_coprime, gen_safe_prime}; -use scicrypt_traits::cryptosystems::{DecryptionKey, EncryptionKey}; +use scicrypt_traits::cryptosystems::{Associable, EncryptionKey}; use scicrypt_traits::randomness::GeneralRng; use scicrypt_traits::randomness::SecureRng; use scicrypt_traits::security::BitsOfSecurity; -use scicrypt_traits::threshold_cryptosystems::{DecryptionShare, TOfNCryptosystem}; +use scicrypt_traits::threshold_cryptosystems::{ + DecryptionShare, PartialDecryptionKey, TOfNCryptosystem, +}; use scicrypt_traits::DecryptionError; use std::ops::Rem; @@ -16,6 +18,7 @@ pub struct ThresholdPaillier { } /// The public key for encryption. +#[derive(PartialEq, Debug)] pub struct ThresholdPaillierPK { generator: Integer, modulus: Integer, @@ -34,11 +37,7 @@ pub struct ThresholdPaillierCiphertext { c: Integer, } -/// A ciphertext for T-out-of-N paillier with an associated public key -pub struct AssociatedThresholdPaillierCiphertext<'pk> { - ciphertext: ThresholdPaillierCiphertext, - public_key: &'pk ThresholdPaillierPK, -} +impl Associable for ThresholdPaillierCiphertext {} /// A partially decrypted ciphertext, of which t must be combined to decrypt successfully. pub struct ThresholdPaillierShare { @@ -46,16 +45,10 @@ pub struct ThresholdPaillierShare { share: Integer, } -impl<'pk> - TOfNCryptosystem< - 'pk, - ThresholdPaillierPK, - ThresholdPaillierSK, - Integer, - ThresholdPaillierShare, - AssociatedThresholdPaillierCiphertext<'pk>, - > for ThresholdPaillier -{ +impl TOfNCryptosystem for ThresholdPaillier { + type PublicKey = ThresholdPaillierPK; + type SecretKey = ThresholdPaillierSK; + fn setup(security_param: &BitsOfSecurity) -> Self { ThresholdPaillier { modulus_size: security_param.to_public_key_bit_length(), @@ -115,27 +108,16 @@ impl<'pk> } } -impl ThresholdPaillierCiphertext { - /// Associates the ciphertext with a public key - pub fn associate( - self, - public_key: &ThresholdPaillierPK, - ) -> AssociatedThresholdPaillierCiphertext { - AssociatedThresholdPaillierCiphertext { - ciphertext: self, - public_key, - } - } -} +impl EncryptionKey for ThresholdPaillierPK { + type Input = Integer; + type Plaintext = Integer; + type Ciphertext = ThresholdPaillierCiphertext; -impl<'pk> EncryptionKey<'pk, Integer, AssociatedThresholdPaillierCiphertext<'pk>> - for ThresholdPaillierPK -{ - fn encrypt, R: SecureRng>( - &'pk self, - plaintext: IntoP, + fn encrypt_raw( + &self, + plaintext: &Integer, rng: &mut GeneralRng, - ) -> AssociatedThresholdPaillierCiphertext + ) -> ThresholdPaillierCiphertext where Self: Sized, { @@ -152,36 +134,33 @@ impl<'pk> EncryptionKey<'pk, Integer, AssociatedThresholdPaillierCiphertext<'pk> ThresholdPaillierCiphertext { c: (first * second).rem(&n_squared), } - .associate(self) } } -impl DecryptionKey> - for ThresholdPaillierSK -{ - fn decrypt( +impl PartialDecryptionKey for ThresholdPaillierSK { + type DecryptionShare = ThresholdPaillierShare; + + fn partial_decrypt_raw( &self, - associated_ciphertext: &AssociatedThresholdPaillierCiphertext, + public_key: &ThresholdPaillierPK, + ciphertext: &ThresholdPaillierCiphertext, ) -> ThresholdPaillierShare { - let n_squared = Integer::from(associated_ciphertext.public_key.modulus.square_ref()); + let n_squared = Integer::from(public_key.modulus.square_ref()); ThresholdPaillierShare { id: self.id, - share: Integer::from(associated_ciphertext.ciphertext.c.secure_pow_mod_ref( - &(Integer::from(2) * &associated_ciphertext.public_key.delta * &self.key), + share: Integer::from(ciphertext.c.secure_pow_mod_ref( + &(Integer::from(2) * &public_key.delta * &self.key), &n_squared, )), } } } -impl DecryptionShare for ThresholdPaillierShare { - type Plaintext = Integer; - type PublicKey = ThresholdPaillierPK; - +impl DecryptionShare for ThresholdPaillierShare { fn combine( decryption_shares: &[Self], - public_key: &Self::PublicKey, - ) -> Result { + public_key: &ThresholdPaillierPK, + ) -> Result { let lambdas: Vec = (0..decryption_shares.len()) .map(|i| { let mut lambda = Integer::from(&public_key.delta); @@ -230,14 +209,19 @@ impl DecryptionShare for ThresholdPaillierShare { } } +// TODO: Implement homomorphism / simply use standard PaillierCiphertexts + #[cfg(test)] mod tests { use crate::threshold_cryptosystems::paillier::{ThresholdPaillier, ThresholdPaillierShare}; use rand_core::OsRng; - use scicrypt_traits::cryptosystems::{DecryptionKey, EncryptionKey}; + use rug::Integer; + use scicrypt_traits::cryptosystems::EncryptionKey; use scicrypt_traits::randomness::GeneralRng; use scicrypt_traits::security::BitsOfSecurity; - use scicrypt_traits::threshold_cryptosystems::{DecryptionShare, TOfNCryptosystem}; + use scicrypt_traits::threshold_cryptosystems::{ + DecryptionShare, PartialDecryptionKey, TOfNCryptosystem, + }; #[test] fn test_encrypt_decrypt_2_of_3() { @@ -246,13 +230,13 @@ mod tests { let paillier = ThresholdPaillier::setup(&BitsOfSecurity::Other { pk_bits: 160 }); let (pk, sks) = paillier.generate_keys(2, 3, &mut rng); - let ciphertext = pk.encrypt(19, &mut rng); + let ciphertext = pk.encrypt(&Integer::from(19), &mut rng); - let share_1 = sks[0].decrypt(&ciphertext); - let share_3 = sks[2].decrypt(&ciphertext); + let share_1 = sks[0].partial_decrypt(&ciphertext); + let share_3 = sks[2].partial_decrypt(&ciphertext); assert_eq!( - 19, + Integer::from(19), ThresholdPaillierShare::combine(&[share_1, share_3], &pk).unwrap() ); } diff --git a/scicrypt-traits/src/cryptosystems.rs b/scicrypt-traits/src/cryptosystems.rs index 80b6c6a..3511f02 100644 --- a/scicrypt-traits/src/cryptosystems.rs +++ b/scicrypt-traits/src/cryptosystems.rs @@ -1,6 +1,7 @@ use crate::randomness::GeneralRng; use crate::randomness::SecureRng; use crate::security::BitsOfSecurity; +use std::fmt::Debug; /// An asymmetric cryptosystem is a system of methods to encrypt plaintexts into ciphertexts, and /// decrypt those ciphertexts back into plaintexts. Anyone who has access to the public key can @@ -9,37 +10,81 @@ use crate::security::BitsOfSecurity; /// The struct that implements an `AsymmetricCryptosystem` will hold the general parameters of that /// cryptosystem. Depending on the cryptosystem, those parameters could play an important role in /// deciding the level of security. As such, each cryptosystem should clearly indicate these. -pub trait AsymmetricCryptosystem<'pk, PK: EncryptionKey<'pk, P, C>, SK: DecryptionKey, P, C>: - Clone -{ +pub trait AsymmetricCryptosystem { + /// The public key, used for encrypting plaintexts. + type PublicKey: EncryptionKey; + /// The secret key, used for decrypting ciphertexts. + type SecretKey: DecryptionKey; + /// Sets up an instance of this cryptosystem with parameters satisfying the security parameter. fn setup(security_parameter: &BitsOfSecurity) -> Self; /// Generate a public and private key pair using a cryptographic RNG. The level of security is /// determined by the computational `security_parameter`. - fn generate_keys(&self, rng: &mut GeneralRng) -> (PK, SK); + fn generate_keys( + &self, + rng: &mut GeneralRng, + ) -> (Self::PublicKey, Self::SecretKey); } /// The encryption key. -pub trait EncryptionKey<'pk, P, C>: Sized { - /// Encrypt the plaintext using the public key and a cryptographic RNG. - fn encrypt, R: SecureRng>( +pub trait EncryptionKey: Sized + Debug + PartialEq { + /// Input is the type used to multiply additive ciphertexts or exponentiate multiplicative ciphertexts. + type Input; + + /// The type of the plaintext to be encrypted. + type Plaintext; + + /// The type of an encrypted plaintext, i.e. a ciphertext. + type Ciphertext: Associable; + + /// Encrypt the plaintext using the public key and a cryptographic RNG and immediately associate it with the public key. + fn encrypt<'pk, R: SecureRng>( &'pk self, - plaintext: IntoP, + plaintext: &Self::Plaintext, rng: &mut GeneralRng, - ) -> C - where - C: 'pk; + ) -> AssociatedCiphertext<'pk, Self::Ciphertext, Self> { + self.encrypt_raw(plaintext, rng).associate(self) + } + + /// Encrypt the plaintext using the public key and a cryptographic RNG. + fn encrypt_raw( + &self, + plaintext: &Self::Plaintext, + rng: &mut GeneralRng, + ) -> Self::Ciphertext; } /// The decryption key. -pub trait DecryptionKey { +pub trait DecryptionKey { + /// Decrypt the associated ciphertext using the secret key. + fn decrypt<'pk>( + &self, + ciphertext: &AssociatedCiphertext<'pk, PK::Ciphertext, PK>, + ) -> PK::Plaintext { + self.decrypt_raw(ciphertext.public_key, &ciphertext.ciphertext) + } + /// Decrypt the ciphertext using the secret key and its related public key. - fn decrypt(&self, associated_ciphertext: &C) -> P; + fn decrypt_raw(&self, public_key: &PK, ciphertext: &PK::Ciphertext) -> PK::Plaintext; +} + +#[derive(PartialEq, Debug)] +/// An AssociatedCiphertext associates a ciphertext with a reference to the corresponding public key to make homomorphic operations and decrypting more ergonomic. +pub struct AssociatedCiphertext<'pk, C: Associable, PK: EncryptionKey> { + /// A potentially homomorphic ciphertext + pub ciphertext: C, + /// The related public key + pub public_key: &'pk PK, } /// Functionality to easily turn a ciphertext into an associated ciphertext -pub trait Associable<'pk, PK: EncryptionKey<'pk, P, AC>, AC: 'pk, P>: Sized { - /// Enriches a ciphertext by associating it with a corresponding public key. - fn associate(self, public_key: &'pk PK) -> AC; +pub trait Associable>: Sized { + /// 'Enriches' a ciphertext by associating it with a corresponding public key. This allows to overlead operators for homomorphic operations. + fn associate(self, public_key: &PK) -> AssociatedCiphertext<'_, Self, PK> { + AssociatedCiphertext { + ciphertext: self, + public_key, + } + } } diff --git a/scicrypt-traits/src/homomorphic.rs b/scicrypt-traits/src/homomorphic.rs new file mode 100644 index 0000000..6104705 --- /dev/null +++ b/scicrypt-traits/src/homomorphic.rs @@ -0,0 +1,85 @@ +use std::ops::{Add, Mul}; + +use crate::cryptosystems::{Associable, AssociatedCiphertext, EncryptionKey}; + +auto trait PotentialInput {} + +impl<'pk, C, PK> !PotentialInput for AssociatedCiphertext<'pk, C, PK> {} + +/// Trait implemented by additively homomorphic cryptosystems +pub trait HomomorphicAddition: EncryptionKey { + /// Combines two ciphertexts so that their decrypted value reflects some addition operation + fn add( + &self, + ciphertext_a: Self::Ciphertext, + ciphertext_b: Self::Ciphertext, + ) -> Self::Ciphertext; + /// Applies some operation on a ciphertext so that the decrypted value reflects some multiplication with `input` + fn mul(&self, ciphertext: Self::Ciphertext, input: Self::Input) -> Self::Ciphertext; +} + +impl<'pk, C: Associable, PK: EncryptionKey + HomomorphicAddition> Add + for AssociatedCiphertext<'pk, C, PK> +{ + type Output = AssociatedCiphertext<'pk, C, PK>; + + fn add(self, rhs: Self) -> Self::Output { + debug_assert_eq!(self.public_key, rhs.public_key); + self.public_key + .add(self.ciphertext, rhs.ciphertext) + .associate(self.public_key) + } +} + +impl< + 'pk, + P: PotentialInput, + C: Associable, + PK: EncryptionKey + HomomorphicAddition, + > Mul

for AssociatedCiphertext<'pk, C, PK> +{ + type Output = AssociatedCiphertext<'pk, C, PK>; + + fn mul(self, rhs: PK::Input) -> Self::Output { + self.public_key + .mul(self.ciphertext, rhs) + .associate(self.public_key) + } +} + +/// Trait implemented by multiplicatively homomorphic cryptosystems +pub trait HomomorphicMultiplication: EncryptionKey { + /// Combines two ciphertexts so that their decrypted value reflects some multiplication operation + fn mul( + &self, + ciphertext_a: Self::Ciphertext, + ciphertext_b: Self::Ciphertext, + ) -> Self::Ciphertext; + /// Applies some operation on a ciphertext so that the decrypted value reflects some exponentiation with `input` + fn pow(&self, ciphertext: Self::Ciphertext, input: Self::Input) -> Self::Ciphertext; +} + +// TODO: This leads to problems because PK::Plaintext can be AssociatedCiphertext<'pk, C, PK> +impl<'pk, C: Associable, PK: EncryptionKey + HomomorphicMultiplication> Mul + for AssociatedCiphertext<'pk, C, PK> +{ + type Output = AssociatedCiphertext<'pk, C, PK>; + + fn mul(self, rhs: Self) -> Self::Output { + debug_assert_eq!(self.public_key, rhs.public_key); + self.public_key + .mul(self.ciphertext, rhs.ciphertext) + .associate(self.public_key) + } +} + +impl<'pk, C: Associable, PK: EncryptionKey + HomomorphicMultiplication> + AssociatedCiphertext<'pk, C, PK> +{ + /// Applies some operation on this ciphertext so that the decrypted value reflects some exponentiation with `input` + pub fn pow(self, rhs: PK::Input) -> AssociatedCiphertext<'pk, C, PK> { + self.public_key + .pow(self.ciphertext, rhs) + .associate(self.public_key) + } +} diff --git a/scicrypt-traits/src/lib.rs b/scicrypt-traits/src/lib.rs index 8e4c37c..a77f916 100644 --- a/scicrypt-traits/src/lib.rs +++ b/scicrypt-traits/src/lib.rs @@ -1,4 +1,7 @@ #![feature(trait_alias)] +// These features are necessary to prevent the operator overloading for AssociatedCiphertext to clash between additive and multiplicative, +// so we restrict the AssociatedCiphertext to never be a plaintext. +#![feature(auto_traits, negative_impls)] #![warn(missing_docs, unused_imports)] //! _This is a part of **scicrypt**. For more information, head to the @@ -26,3 +29,6 @@ pub mod secret_sharing; /// distinct decryption shares to decrypt a threshold ciphertext. #[derive(Debug)] pub struct DecryptionError; + +/// Homomorphic properties of homomorphic encryption schemes +pub mod homomorphic; diff --git a/scicrypt-traits/src/threshold_cryptosystems.rs b/scicrypt-traits/src/threshold_cryptosystems.rs index b0c4715..dd81524 100644 --- a/scicrypt-traits/src/threshold_cryptosystems.rs +++ b/scicrypt-traits/src/threshold_cryptosystems.rs @@ -1,4 +1,4 @@ -use crate::cryptosystems::{DecryptionKey, EncryptionKey}; +use crate::cryptosystems::{AssociatedCiphertext, EncryptionKey}; use crate::randomness::GeneralRng; use crate::randomness::SecureRng; use crate::security::BitsOfSecurity; @@ -18,15 +18,12 @@ use crate::DecryptionError; /// of that cryptosystem. Depending on the cryptosystem, those parameters could play an important /// role in deciding the level of security. As such, each cryptosystem should clearly indicate /// these. -pub trait NOfNCryptosystem< - 'pk, - PK: EncryptionKey<'pk, P, C>, - SK: DecryptionKey, - P, - DS: DecryptionShare, - C, ->: Clone -{ +pub trait NOfNCryptosystem { + /// The public key used to encrypt plaintexts. + type PublicKey: EncryptionKey; + /// The secret key used to partially decrypt ciphertexts. + type SecretKey: PartialDecryptionKey; + /// Sets up an instance of this cryptosystem with parameters satisfying the security parameter. fn setup(security_parameter: &BitsOfSecurity) -> Self; @@ -35,24 +32,39 @@ pub trait NOfNCryptosystem< &self, key_count_n: usize, rng: &mut GeneralRng, - ) -> (PK, Vec); + ) -> (Self::PublicKey, Vec); +} + +/// A partial decryption key partially decrypts ciphertexts to return a decryption share. If enough decryption shares of different keys are combined, they output the correct decryption. +pub trait PartialDecryptionKey { + /// The type of the decryption share. If enough decryption shares of different keys are combined, they output the correct decryption. + type DecryptionShare: DecryptionShare; + + /// Partially decrypts a ciphertext, returning a valid decryption share. + fn partial_decrypt<'pk>( + &self, + ciphertext: &AssociatedCiphertext<'pk, PK::Ciphertext, PK>, + ) -> Self::DecryptionShare { + self.partial_decrypt_raw(ciphertext.public_key, &ciphertext.ciphertext) + } + /// Partially decrypts a ciphertext, returning a valid decryption share. + fn partial_decrypt_raw( + &self, + public_key: &PK, + ciphertext: &PK::Ciphertext, + ) -> Self::DecryptionShare; } /// A `DecryptionShare` is the result of decrypting with a partial key. When enough of these shares /// are combined, they reveal the actual decryption. -pub trait DecryptionShare: Sized { - /// The type of the plaintext retrieved when decryption shares are combined. - type Plaintext; - /// The public key that created the original ciphertexts. - type PublicKey; - +pub trait DecryptionShare: Sized { /// Combine $t$ decryption shares belonging to distinct partial keys to finish decryption. It is /// the responsibility of the programmer to supply the right number of decryption shares to /// this function. fn combine( decryption_shares: &[Self], - public_key: &Self::PublicKey, - ) -> Result; + public_key: &PK, + ) -> Result; } /// An asymmetric threshold cryptosystem is a system of methods to encrypt plaintexts into @@ -68,15 +80,12 @@ pub trait DecryptionShare: Sized { /// of that cryptosystem. Depending on the cryptosystem, those parameters could play an important /// role in deciding the level of security. As such, each cryptosystem should clearly indicate /// these. -pub trait TOfNCryptosystem< - 'pk, - PK: EncryptionKey<'pk, P, C>, - SK: DecryptionKey, - P, - DS: DecryptionShare, - C, ->: Clone -{ +pub trait TOfNCryptosystem { + /// The public key used to encrypt plaintexts. + type PublicKey: EncryptionKey; + /// The secret key used to partially decrypt ciphertexts. + type SecretKey: PartialDecryptionKey; + /// Sets up an instance of this cryptosystem with parameters satisfying the security parameter. fn setup(security_parameter: &BitsOfSecurity) -> Self; @@ -86,5 +95,5 @@ pub trait TOfNCryptosystem< threshold_t: usize, key_count_n: usize, rng: &mut GeneralRng, - ) -> (PK, Vec); + ) -> (Self::PublicKey, Vec); }