mirror of https://github.com/nucypher/pyUmbral.git
commit
18e868ceb2
8
Pipfile
8
Pipfile
|
@ -13,23 +13,19 @@ bumpversion = "*"
|
|||
# Pytest Plugins
|
||||
pytest = "*"
|
||||
pytest-mypy = "*"
|
||||
pytest-mock = "*"
|
||||
pytest-cov = "*"
|
||||
pytest-benchmark = {version = "*",extras = ["histogram"]}
|
||||
# Pytest Plugin Subdeps
|
||||
mock = "*"
|
||||
mypy = "*"
|
||||
monkeytype = "*"
|
||||
coverage = "*"
|
||||
codecov = "*"
|
||||
# Testing libraries
|
||||
hypothesis = "*"
|
||||
# Testing libraries
|
||||
nbval = "*"
|
||||
# Docs
|
||||
sphinx = "*"
|
||||
sphinx-autobuild = "*"
|
||||
sphinx_rtd_theme = "*"
|
||||
# Overrides vulnerable versions allowed by codecov and sphinx:
|
||||
# Overrides vulnerable versions allowed by codecov and sphinx:
|
||||
requests = ">=2.20.0"
|
||||
|
||||
[pipenv]
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
{
|
||||
"_meta": {
|
||||
"hash": {
|
||||
"sha256": "55db9d5f9de5a65ef3a43b7931e19d8a1ee2cb9cbfa9e616fa2c512f8576116b"
|
||||
"sha256": "5046c797bf7733818d480d0c9df2934393dbd080d847a85d03221cff74ec7907"
|
||||
},
|
||||
"pipfile-spec": 6,
|
||||
"requires": {},
|
||||
|
@ -17,14 +17,23 @@
|
|||
"cffi": {
|
||||
"hashes": [
|
||||
"sha256:005a36f41773e148deac64b08f233873a4d0c18b053d37da83f6af4d9087b813",
|
||||
"sha256:04c468b622ed31d408fea2346bec5bbffba2cc44226302a0de1ade9f5ea3d373",
|
||||
"sha256:06d7cd1abac2ffd92e65c0609661866709b4b2d82dd15f611e602b9b188b0b69",
|
||||
"sha256:06db6321b7a68b2bd6df96d08a5adadc1fa0e8f419226e25b2a5fbf6ccc7350f",
|
||||
"sha256:0857f0ae312d855239a55c81ef453ee8fd24136eaba8e87a2eceba644c0d4c06",
|
||||
"sha256:0f861a89e0043afec2a51fd177a567005847973be86f709bbb044d7f42fc4e05",
|
||||
"sha256:1071534bbbf8cbb31b498d5d9db0f274f2f7a865adca4ae429e147ba40f73dea",
|
||||
"sha256:158d0d15119b4b7ff6b926536763dc0714313aa59e320ddf787502c70c4d4bee",
|
||||
"sha256:1bf1ac1984eaa7675ca8d5745a8cb87ef7abecb5592178406e55858d411eadc0",
|
||||
"sha256:1f436816fc868b098b0d63b8920de7d208c90a67212546d02f84fe78a9c26396",
|
||||
"sha256:24a570cd11895b60829e941f2613a4f79df1a27344cbbb82164ef2e0116f09c7",
|
||||
"sha256:24ec4ff2c5c0c8f9c6b87d5bb53555bf267e1e6f70e52e5a9740d32861d36b6f",
|
||||
"sha256:2894f2df484ff56d717bead0a5c2abb6b9d2bf26d6960c4604d5c48bbc30ee73",
|
||||
"sha256:29314480e958fd8aab22e4a58b355b629c59bf5f2ac2492b61e3dc06d8c7a315",
|
||||
"sha256:293e7ea41280cb28c6fcaaa0b1aa1f533b8ce060b9e701d78511e1e6c4a1de76",
|
||||
"sha256:34eff4b97f3d982fb93e2831e6750127d1355a923ebaeeb565407b3d2f8d41a1",
|
||||
"sha256:35f27e6eb43380fa080dccf676dece30bef72e4a67617ffda586641cd4508d49",
|
||||
"sha256:3c3f39fa737542161d8b0d680df2ec249334cd70a8f420f71c9304bd83c3cbed",
|
||||
"sha256:3d3dd4c9e559eb172ecf00a2a7517e97d1e96de2a5e610bd9b68cea3925b4892",
|
||||
"sha256:43e0b9d9e2c9e5d152946b9c5fe062c151614b262fda2e7b201204de0b99e482",
|
||||
"sha256:48e1c69bbacfc3d932221851b39d49e81567a4d4aac3b21258d9c24578280058",
|
||||
|
@ -32,6 +41,7 @@
|
|||
"sha256:58e3f59d583d413809d60779492342801d6e82fefb89c86a38e040c16883be53",
|
||||
"sha256:5de7970188bb46b7bf9858eb6890aad302577a5f6f75091fd7cdd3ef13ef3045",
|
||||
"sha256:65fa59693c62cf06e45ddbb822165394a288edce9e276647f0046e1ec26920f3",
|
||||
"sha256:681d07b0d1e3c462dd15585ef5e33cb021321588bebd910124ef4f4fb71aef55",
|
||||
"sha256:69e395c24fc60aad6bb4fa7e583698ea6cc684648e1ffb7fe85e3c1ca131a7d5",
|
||||
"sha256:6c97d7350133666fbb5cf4abdc1178c812cb205dc6f41d174a7b0f18fb93337e",
|
||||
"sha256:6e4714cc64f474e4d6e37cfff31a814b509a35cb17de4fb1999907575684479c",
|
||||
|
@ -49,8 +59,10 @@
|
|||
"sha256:b85eb46a81787c50650f2392b9b4ef23e1f126313b9e0e9013b35c15e4288e2e",
|
||||
"sha256:bb89f306e5da99f4d922728ddcd6f7fcebb3241fc40edebcb7284d7514741991",
|
||||
"sha256:cbde590d4faaa07c72bf979734738f328d239913ba3e043b1e98fe9a39f8b2b6",
|
||||
"sha256:cc5a8e069b9ebfa22e26d0e6b97d6f9781302fe7f4f2b8776c3e1daea35f1adc",
|
||||
"sha256:cd2868886d547469123fadc46eac7ea5253ea7fcb139f12e1dfc2bbd406427d1",
|
||||
"sha256:d42b11d692e11b6634f7613ad8df5d6d5f8875f5d48939520d351007b3c13406",
|
||||
"sha256:df5052c5d867c1ea0b311fb7c3cd28b19df469c056f7fdcfe88c7473aa63e333",
|
||||
"sha256:f2d45f97ab6bb54753eab54fffe75aaf3de4ff2341c9daee1987ee1837636f1d",
|
||||
"sha256:fd78e5fee591709f32ef6edb9a015b4aa1a5022598e36227500c8f4e02328d9c"
|
||||
],
|
||||
|
@ -58,21 +70,21 @@
|
|||
},
|
||||
"cryptography": {
|
||||
"hashes": [
|
||||
"sha256:066bc53f052dfeda2f2d7c195cf16fb3e5ff13e1b6b7415b468514b40b381a5b",
|
||||
"sha256:0923ba600d00718d63a3976f23cab19aef10c1765038945628cd9be047ad0336",
|
||||
"sha256:2d32223e5b0ee02943f32b19245b61a62db83a882f0e76cc564e1cec60d48f87",
|
||||
"sha256:4169a27b818de4a1860720108b55a2801f32b6ae79e7f99c00d79f2a2822eeb7",
|
||||
"sha256:57ad77d32917bc55299b16d3b996ffa42a1c73c6cfa829b14043c561288d2799",
|
||||
"sha256:5ecf2bcb34d17415e89b546dbb44e73080f747e504273e4d4987630493cded1b",
|
||||
"sha256:600cf9bfe75e96d965509a4c0b2b183f74a4fa6f5331dcb40fb7b77b7c2484df",
|
||||
"sha256:66b57a9ca4b3221d51b237094b0303843b914b7d5afd4349970bb26518e350b0",
|
||||
"sha256:93cfe5b7ff006de13e1e89830810ecbd014791b042cbe5eec253be11ac2b28f3",
|
||||
"sha256:9e98b452132963678e3ac6c73f7010fe53adf72209a32854d55690acac3f6724",
|
||||
"sha256:df186fcbf86dc1ce56305becb8434e4b6b7504bc724b71ad7a3239e0c9d14ef2",
|
||||
"sha256:fec7fb46b10da10d9e1d078d1ff8ed9e05ae14f431fdbd11145edd0550b9a964"
|
||||
"sha256:0f1212a66329c80d68aeeb39b8a16d54ef57071bf22ff4e521657b27372e327d",
|
||||
"sha256:1e056c28420c072c5e3cb36e2b23ee55e260cb04eee08f702e0edfec3fb51959",
|
||||
"sha256:240f5c21aef0b73f40bb9f78d2caff73186700bf1bc6b94285699aff98cc16c6",
|
||||
"sha256:26965837447f9c82f1855e0bc8bc4fb910240b6e0d16a664bb722df3b5b06873",
|
||||
"sha256:37340614f8a5d2fb9aeea67fd159bfe4f5f4ed535b1090ce8ec428b2f15a11f2",
|
||||
"sha256:3d10de8116d25649631977cb37da6cbdd2d6fa0e0281d014a5b7d337255ca713",
|
||||
"sha256:3d8427734c781ea5f1b41d6589c293089704d4759e34597dce91014ac125aad1",
|
||||
"sha256:7ec5d3b029f5fa2b179325908b9cd93db28ab7b85bb6c1db56b10e0b54235177",
|
||||
"sha256:8e56e16617872b0957d1c9742a3f94b43533447fd78321514abbe7db216aa250",
|
||||
"sha256:de4e5f7f68220d92b7637fc99847475b59154b7a1b3868fb7385337af54ac9ca",
|
||||
"sha256:eb8cc2afe8b05acbd84a43905832ec78e7b3873fb124ca190f574dca7389a87d",
|
||||
"sha256:ee77aa129f481be46f8d92a1a7db57269a2f23052d5f2433b4621bb457081cc9"
|
||||
],
|
||||
"index": "pypi",
|
||||
"version": "==3.4.6"
|
||||
"version": "==3.4.7"
|
||||
},
|
||||
"pycparser": {
|
||||
"hashes": [
|
||||
|
@ -108,11 +120,11 @@
|
|||
},
|
||||
"six": {
|
||||
"hashes": [
|
||||
"sha256:30639c035cdb23534cd4aa2dd52c3bf48f06e5f4a941509c8bafd8ce11080259",
|
||||
"sha256:8b74bedcbbbaca38ff6d7491d76f2b06b3592611af620f8426e82dddb04a5ced"
|
||||
"sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926",
|
||||
"sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254"
|
||||
],
|
||||
"markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'",
|
||||
"version": "==1.15.0"
|
||||
"version": "==1.16.0"
|
||||
}
|
||||
},
|
||||
"develop": {
|
||||
|
@ -133,19 +145,19 @@
|
|||
},
|
||||
"attrs": {
|
||||
"hashes": [
|
||||
"sha256:31b2eced602aa8423c2aea9c76a724617ed67cf9513173fd3a4f03e3a929c7e6",
|
||||
"sha256:832aa3cde19744e49938b91fea06d69ecb9e649c93ba974535d08ad92164f700"
|
||||
"sha256:149e90d6d8ac20db7a955ad60cf0e6881a3f20d37096140088356da6c716b0b1",
|
||||
"sha256:ef6aaac3ca6cd92904cdd0d83f629a15f18053ec84e6432106f7a4d04ae4f5fb"
|
||||
],
|
||||
"markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'",
|
||||
"version": "==20.3.0"
|
||||
"markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4'",
|
||||
"version": "==21.2.0"
|
||||
},
|
||||
"babel": {
|
||||
"hashes": [
|
||||
"sha256:9d35c22fcc79893c3ecc85ac4a56cde1ecf3f19c540bba0922308a6c06ca6fa5",
|
||||
"sha256:da031ab54472314f210b0adcff1588ee5d1d1d0ba4dbd07b94dba82bde791e05"
|
||||
"sha256:ab49e12b91d937cd11f0b67cb259a57ab4ad2b59ac7a3b41d6c06c0ac5b0def9",
|
||||
"sha256:bc0c176f9f6a994582230df350aa6e05ba2ebe4b3ac317eab29d9be5d2768da0"
|
||||
],
|
||||
"markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'",
|
||||
"version": "==2.9.0"
|
||||
"version": "==2.9.1"
|
||||
},
|
||||
"backcall": {
|
||||
"hashes": [
|
||||
|
@ -172,10 +184,10 @@
|
|||
},
|
||||
"certifi": {
|
||||
"hashes": [
|
||||
"sha256:1a4995114262bffbc2413b159f2a1a480c969de6e6eb13ee966d470af86af59c",
|
||||
"sha256:719a74fb9e33b9bd44cc7f3a8d94bc35e4049deebe19ba7d8e108280cfd59830"
|
||||
"sha256:2bbf76fd432960138b3ef6dda3dde0544f27cbf8546c458e60baf371917ba9ee",
|
||||
"sha256:50b1e4f8446b06f41be7dd6338db18e0990601dce795c2b1686458aa7e8fa7d8"
|
||||
],
|
||||
"version": "==2020.12.5"
|
||||
"version": "==2021.5.30"
|
||||
},
|
||||
"chardet": {
|
||||
"hashes": [
|
||||
|
@ -262,10 +274,11 @@
|
|||
},
|
||||
"decorator": {
|
||||
"hashes": [
|
||||
"sha256:41fa54c2a0cc4ba648be4fd43cff00aedf5b9465c9bf18d64325bc225f08f760",
|
||||
"sha256:e3a62f0520172440ca0dcc823749319382e377f37f140a0b99ef45fecb84bfe7"
|
||||
"sha256:6e5c199c16f7a9f0e3a61a4a54b3d27e7dad0dbdde92b944426cb20914376323",
|
||||
"sha256:72ecfba4320a893c53f9706bebb2d55c270c1e51a28789361aa93e4a21319ed5"
|
||||
],
|
||||
"version": "==4.4.2"
|
||||
"markers": "python_version >= '3.5'",
|
||||
"version": "==5.0.9"
|
||||
},
|
||||
"docutils": {
|
||||
"hashes": [
|
||||
|
@ -282,14 +295,6 @@
|
|||
],
|
||||
"version": "==3.0.12"
|
||||
},
|
||||
"hypothesis": {
|
||||
"hashes": [
|
||||
"sha256:2dd38676402d1c218225210cde0cf19f286352279f32631ac5c801f5d767bc94",
|
||||
"sha256:3b7d9f7e40e406b550d4fd26fef0ce3fad216f163a3400ab701329b865e25876"
|
||||
],
|
||||
"index": "pypi",
|
||||
"version": "==6.8.1"
|
||||
},
|
||||
"idna": {
|
||||
"hashes": [
|
||||
"sha256:b307872f855b18632ce0c21c5e45be78c0ea7ae4c15c828c20788b26921eb3f6",
|
||||
|
@ -315,19 +320,19 @@
|
|||
},
|
||||
"ipykernel": {
|
||||
"hashes": [
|
||||
"sha256:98321abefdf0505fb3dc7601f60fc4087364d394bd8fad53107eb1adee9ff475",
|
||||
"sha256:efd07253b54d84d26e0878d268c8c3a41582a18750da633c2febfd2ece0d467d"
|
||||
"sha256:29eee66548ee7c2edb7941de60c0ccf0a7a8dd957341db0a49c5e8e6a0fcb712",
|
||||
"sha256:e976751336b51082a89fc2099fb7f96ef20f535837c398df6eab1283c2070884"
|
||||
],
|
||||
"markers": "python_version >= '3.5'",
|
||||
"version": "==5.5.0"
|
||||
"version": "==5.5.5"
|
||||
},
|
||||
"ipython": {
|
||||
"hashes": [
|
||||
"sha256:04323f72d5b85b606330b6d7e2dc8d2683ad46c3905e955aa96ecc7a99388e70",
|
||||
"sha256:34207ffb2f653bced2bc8e3756c1db86e7d93e44ed049daae9814fed66d408ec"
|
||||
"sha256:a171caa3d3d4c819a1c0742e3abecfd5a2b8ab525ca1c9f114b40b76b0679ab1",
|
||||
"sha256:f86788eef439891438af3498525094cc2acbdbea4f2aa2f8895782d4ff471341"
|
||||
],
|
||||
"markers": "python_version >= '3.7'",
|
||||
"version": "==7.21.0"
|
||||
"version": "==7.24.0"
|
||||
},
|
||||
"ipython-genutils": {
|
||||
"hashes": [
|
||||
|
@ -346,11 +351,11 @@
|
|||
},
|
||||
"jinja2": {
|
||||
"hashes": [
|
||||
"sha256:03e47ad063331dd6a3f04a43eddca8a966a26ba0c5b7207a9a9e4e08f1b29419",
|
||||
"sha256:a6d58433de0ae800347cab1fa3043cebbabe8baa9d29e668f1c768cb87a333c6"
|
||||
"sha256:1f06f2da51e7b56b8f238affdd6b4e2c61e39598a378cc49345bc1bd42a978a4",
|
||||
"sha256:703f484b47a6af502e743c9122595cc812b0271f661722403114f71a79d0f5a4"
|
||||
],
|
||||
"markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4'",
|
||||
"version": "==2.11.3"
|
||||
"markers": "python_version >= '3.6'",
|
||||
"version": "==3.0.1"
|
||||
},
|
||||
"jsonschema": {
|
||||
"hashes": [
|
||||
|
@ -375,14 +380,6 @@
|
|||
"markers": "python_version >= '3.6'",
|
||||
"version": "==4.7.1"
|
||||
},
|
||||
"libcst": {
|
||||
"hashes": [
|
||||
"sha256:2766671c107263daa3fc34e39d55134a6fe253701564d7670586f30eee2c201c",
|
||||
"sha256:4638e4e8f166f4c74df399222d347ce3e1d316e206b550d8a6254d51b4cf7275"
|
||||
],
|
||||
"markers": "python_version >= '3.6'",
|
||||
"version": "==0.3.17"
|
||||
},
|
||||
"livereload": {
|
||||
"hashes": [
|
||||
"sha256:776f2f865e59fde56490a56bcc6773b6917366bce0c267c60ee8aaf1a0959869"
|
||||
|
@ -391,77 +388,51 @@
|
|||
},
|
||||
"markupsafe": {
|
||||
"hashes": [
|
||||
"sha256:00bc623926325b26bb9605ae9eae8a215691f33cae5df11ca5424f06f2d1f473",
|
||||
"sha256:09027a7803a62ca78792ad89403b1b7a73a01c8cb65909cd876f7fcebd79b161",
|
||||
"sha256:09c4b7f37d6c648cb13f9230d847adf22f8171b1ccc4d5682398e77f40309235",
|
||||
"sha256:1027c282dad077d0bae18be6794e6b6b8c91d58ed8a8d89a89d59693b9131db5",
|
||||
"sha256:13d3144e1e340870b25e7b10b98d779608c02016d5184cfb9927a9f10c689f42",
|
||||
"sha256:195d7d2c4fbb0ee8139a6cf67194f3973a6b3042d742ebe0a9ed36d8b6f0c07f",
|
||||
"sha256:22c178a091fc6630d0d045bdb5992d2dfe14e3259760e713c490da5323866c39",
|
||||
"sha256:24982cc2533820871eba85ba648cd53d8623687ff11cbb805be4ff7b4c971aff",
|
||||
"sha256:29872e92839765e546828bb7754a68c418d927cd064fd4708fab9fe9c8bb116b",
|
||||
"sha256:2beec1e0de6924ea551859edb9e7679da6e4870d32cb766240ce17e0a0ba2014",
|
||||
"sha256:3b8a6499709d29c2e2399569d96719a1b21dcd94410a586a18526b143ec8470f",
|
||||
"sha256:43a55c2930bbc139570ac2452adf3d70cdbb3cfe5912c71cdce1c2c6bbd9c5d1",
|
||||
"sha256:46c99d2de99945ec5cb54f23c8cd5689f6d7177305ebff350a58ce5f8de1669e",
|
||||
"sha256:500d4957e52ddc3351cabf489e79c91c17f6e0899158447047588650b5e69183",
|
||||
"sha256:535f6fc4d397c1563d08b88e485c3496cf5784e927af890fb3c3aac7f933ec66",
|
||||
"sha256:596510de112c685489095da617b5bcbbac7dd6384aeebeda4df6025d0256a81b",
|
||||
"sha256:62fe6c95e3ec8a7fad637b7f3d372c15ec1caa01ab47926cfdf7a75b40e0eac1",
|
||||
"sha256:6788b695d50a51edb699cb55e35487e430fa21f1ed838122d722e0ff0ac5ba15",
|
||||
"sha256:6dd73240d2af64df90aa7c4e7481e23825ea70af4b4922f8ede5b9e35f78a3b1",
|
||||
"sha256:6f1e273a344928347c1290119b493a1f0303c52f5a5eae5f16d74f48c15d4a85",
|
||||
"sha256:6fffc775d90dcc9aed1b89219549b329a9250d918fd0b8fa8d93d154918422e1",
|
||||
"sha256:717ba8fe3ae9cc0006d7c451f0bb265ee07739daf76355d06366154ee68d221e",
|
||||
"sha256:79855e1c5b8da654cf486b830bd42c06e8780cea587384cf6545b7d9ac013a0b",
|
||||
"sha256:7c1699dfe0cf8ff607dbdcc1e9b9af1755371f92a68f706051cc8c37d447c905",
|
||||
"sha256:7fed13866cf14bba33e7176717346713881f56d9d2bcebab207f7a036f41b850",
|
||||
"sha256:84dee80c15f1b560d55bcfe6d47b27d070b4681c699c572af2e3c7cc90a3b8e0",
|
||||
"sha256:88e5fcfb52ee7b911e8bb6d6aa2fd21fbecc674eadd44118a9cc3863f938e735",
|
||||
"sha256:8defac2f2ccd6805ebf65f5eeb132adcf2ab57aa11fdf4c0dd5169a004710e7d",
|
||||
"sha256:98bae9582248d6cf62321dcb52aaf5d9adf0bad3b40582925ef7c7f0ed85fceb",
|
||||
"sha256:98c7086708b163d425c67c7a91bad6e466bb99d797aa64f965e9d25c12111a5e",
|
||||
"sha256:9add70b36c5666a2ed02b43b335fe19002ee5235efd4b8a89bfcf9005bebac0d",
|
||||
"sha256:9bf40443012702a1d2070043cb6291650a0841ece432556f784f004937f0f32c",
|
||||
"sha256:a6a744282b7718a2a62d2ed9d993cad6f5f585605ad352c11de459f4108df0a1",
|
||||
"sha256:acf08ac40292838b3cbbb06cfe9b2cb9ec78fce8baca31ddb87aaac2e2dc3bc2",
|
||||
"sha256:ade5e387d2ad0d7ebf59146cc00c8044acbd863725f887353a10df825fc8ae21",
|
||||
"sha256:b00c1de48212e4cc9603895652c5c410df699856a2853135b3967591e4beebc2",
|
||||
"sha256:b1282f8c00509d99fef04d8ba936b156d419be841854fe901d8ae224c59f0be5",
|
||||
"sha256:b1dba4527182c95a0db8b6060cc98ac49b9e2f5e64320e2b56e47cb2831978c7",
|
||||
"sha256:b2051432115498d3562c084a49bba65d97cf251f5a331c64a12ee7e04dacc51b",
|
||||
"sha256:b7d644ddb4dbd407d31ffb699f1d140bc35478da613b441c582aeb7c43838dd8",
|
||||
"sha256:ba59edeaa2fc6114428f1637ffff42da1e311e29382d81b339c1817d37ec93c6",
|
||||
"sha256:bf5aa3cbcfdf57fa2ee9cd1822c862ef23037f5c832ad09cfea57fa846dec193",
|
||||
"sha256:c8716a48d94b06bb3b2524c2b77e055fb313aeb4ea620c8dd03a105574ba704f",
|
||||
"sha256:caabedc8323f1e93231b52fc32bdcde6db817623d33e100708d9a68e1f53b26b",
|
||||
"sha256:cd5df75523866410809ca100dc9681e301e3c27567cf498077e8551b6d20e42f",
|
||||
"sha256:cdb132fc825c38e1aeec2c8aa9338310d29d337bebbd7baa06889d09a60a1fa2",
|
||||
"sha256:d53bc011414228441014aa71dbec320c66468c1030aae3a6e29778a3382d96e5",
|
||||
"sha256:d73a845f227b0bfe8a7455ee623525ee656a9e2e749e4742706d80a6065d5e2c",
|
||||
"sha256:d9be0ba6c527163cbed5e0857c451fcd092ce83947944d6c14bc95441203f032",
|
||||
"sha256:e249096428b3ae81b08327a63a485ad0878de3fb939049038579ac0ef61e17e7",
|
||||
"sha256:e8313f01ba26fbbe36c7be1966a7b7424942f670f38e666995b88d012765b9be",
|
||||
"sha256:feb7b34d6325451ef96bc0e36e1a6c0c1c64bc1fbec4b854f4529e51887b1621"
|
||||
"sha256:01a9b8ea66f1658938f65b93a85ebe8bc016e6769611be228d797c9d998dd298",
|
||||
"sha256:023cb26ec21ece8dc3907c0e8320058b2e0cb3c55cf9564da612bc325bed5e64",
|
||||
"sha256:0446679737af14f45767963a1a9ef7620189912317d095f2d9ffa183a4d25d2b",
|
||||
"sha256:0717a7390a68be14b8c793ba258e075c6f4ca819f15edfc2a3a027c823718567",
|
||||
"sha256:0955295dd5eec6cb6cc2fe1698f4c6d84af2e92de33fbcac4111913cd100a6ff",
|
||||
"sha256:10f82115e21dc0dfec9ab5c0223652f7197feb168c940f3ef61563fc2d6beb74",
|
||||
"sha256:1d609f577dc6e1aa17d746f8bd3c31aa4d258f4070d61b2aa5c4166c1539de35",
|
||||
"sha256:2ef54abee730b502252bcdf31b10dacb0a416229b72c18b19e24a4509f273d26",
|
||||
"sha256:3c112550557578c26af18a1ccc9e090bfe03832ae994343cfdacd287db6a6ae7",
|
||||
"sha256:47ab1e7b91c098ab893b828deafa1203de86d0bc6ab587b160f78fe6c4011f75",
|
||||
"sha256:49e3ceeabbfb9d66c3aef5af3a60cc43b85c33df25ce03d0031a608b0a8b2e3f",
|
||||
"sha256:4efca8f86c54b22348a5467704e3fec767b2db12fc39c6d963168ab1d3fc9135",
|
||||
"sha256:53edb4da6925ad13c07b6d26c2a852bd81e364f95301c66e930ab2aef5b5ddd8",
|
||||
"sha256:594c67807fb16238b30c44bdf74f36c02cdf22d1c8cda91ef8a0ed8dabf5620a",
|
||||
"sha256:611d1ad9a4288cf3e3c16014564df047fe08410e628f89805e475368bd304914",
|
||||
"sha256:6557b31b5e2c9ddf0de32a691f2312a32f77cd7681d8af66c2692efdbef84c18",
|
||||
"sha256:693ce3f9e70a6cf7d2fb9e6c9d8b204b6b39897a2c4a1aa65728d5ac97dcc1d8",
|
||||
"sha256:6a7fae0dd14cf60ad5ff42baa2e95727c3d81ded453457771d02b7d2b3f9c0c2",
|
||||
"sha256:6c4ca60fa24e85fe25b912b01e62cb969d69a23a5d5867682dd3e80b5b02581d",
|
||||
"sha256:7d91275b0245b1da4d4cfa07e0faedd5b0812efc15b702576d103293e252af1b",
|
||||
"sha256:905fec760bd2fa1388bb5b489ee8ee5f7291d692638ea5f67982d968366bef9f",
|
||||
"sha256:97383d78eb34da7e1fa37dd273c20ad4320929af65d156e35a5e2d89566d9dfb",
|
||||
"sha256:984d76483eb32f1bcb536dc27e4ad56bba4baa70be32fa87152832cdd9db0833",
|
||||
"sha256:a30e67a65b53ea0a5e62fe23682cfe22712e01f453b95233b25502f7c61cb415",
|
||||
"sha256:ab3ef638ace319fa26553db0624c4699e31a28bb2a835c5faca8f8acf6a5a902",
|
||||
"sha256:b2f4bf27480f5e5e8ce285a8c8fd176c0b03e93dcc6646477d4630e83440c6a9",
|
||||
"sha256:b7f2d075102dc8c794cbde1947378051c4e5180d52d276987b8d28a3bd58c17d",
|
||||
"sha256:be98f628055368795d818ebf93da628541e10b75b41c559fdf36d104c5787066",
|
||||
"sha256:d7f9850398e85aba693bb640262d3611788b1f29a79f0c93c565694658f4071f",
|
||||
"sha256:f5653a225f31e113b152e56f154ccbe59eeb1c7487b39b9d9f9cdb58e6c79dc5",
|
||||
"sha256:f826e31d18b516f653fe296d967d700fddad5901ae07c622bb3705955e1faa94",
|
||||
"sha256:f8ba0e8349a38d3001fae7eadded3f6606f0da5d748ee53cc1dab1d6527b9509",
|
||||
"sha256:f9081981fe268bd86831e5c75f7de206ef275defcb82bc70740ae6dc507aee51",
|
||||
"sha256:fa130dd50c57d53368c9d59395cb5526eda596d3ffe36666cd81a44d56e48872"
|
||||
],
|
||||
"markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'",
|
||||
"version": "==1.1.1"
|
||||
"markers": "python_version >= '3.6'",
|
||||
"version": "==2.0.1"
|
||||
},
|
||||
"mock": {
|
||||
"matplotlib-inline": {
|
||||
"hashes": [
|
||||
"sha256:122fcb64ee37cfad5b3f48d7a7d51875d7031aaf3d8be7c42e2bee25044eee62",
|
||||
"sha256:7d3fbbde18228f4ff2f1f119a45cdffa458b4c0dee32eb4d2bb2f82554bac7bc"
|
||||
"sha256:5cf1176f554abb4fa98cb362aa2b55c500147e4bdbb07e3fda359143e1da0811",
|
||||
"sha256:f41d5ff73c9f5385775d5c0bc13b424535c8402fe70ea8210f93e11f3683993e"
|
||||
],
|
||||
"index": "pypi",
|
||||
"version": "==4.0.3"
|
||||
},
|
||||
"monkeytype": {
|
||||
"hashes": [
|
||||
"sha256:b8ed88485d2ffb05fb1597a6e5eacb05ba5420de682054403c06fac84fdc4038",
|
||||
"sha256:fe596bebc5e1b6a64eae71a40b880688de433e4f70507a31ada48510195251dd"
|
||||
],
|
||||
"index": "pypi",
|
||||
"version": "==20.5.0"
|
||||
"markers": "python_version >= '3.5'",
|
||||
"version": "==0.1.2"
|
||||
},
|
||||
"mypy": {
|
||||
"hashes": [
|
||||
|
@ -500,11 +471,11 @@
|
|||
},
|
||||
"nbformat": {
|
||||
"hashes": [
|
||||
"sha256:1d223e64a18bfa7cdf2db2e9ba8a818312fc2a0701d2e910b58df66809385a56",
|
||||
"sha256:3949fdc8f5fa0b1afca16fb307546e78494fa7a7bceff880df8168eafda0e7ac"
|
||||
"sha256:b516788ad70771c6250977c1374fcca6edebe6126fd2adb5a69aa5c2356fd1c8",
|
||||
"sha256:eb8447edd7127d043361bc17f2f5a807626bc8e878c7709a1c647abda28a9171"
|
||||
],
|
||||
"markers": "python_version >= '3.5'",
|
||||
"version": "==5.1.2"
|
||||
"version": "==5.1.3"
|
||||
},
|
||||
"nbval": {
|
||||
"hashes": [
|
||||
|
@ -524,11 +495,11 @@
|
|||
},
|
||||
"parso": {
|
||||
"hashes": [
|
||||
"sha256:15b00182f472319383252c18d5913b69269590616c947747bc50bf4ac768f410",
|
||||
"sha256:8519430ad07087d4c997fda3a7918f7cfa27cb58972a8c89c2a0295a1c940e9e"
|
||||
"sha256:12b83492c6239ce32ff5eed6d3639d6a536170723c6f3f1506869f1ace413398",
|
||||
"sha256:a8c4922db71e4fdb90e0d0bc6e50f9b273d3397925e5e60a717e719201778d22"
|
||||
],
|
||||
"markers": "python_version >= '3.6'",
|
||||
"version": "==0.8.1"
|
||||
"version": "==0.8.2"
|
||||
},
|
||||
"pexpect": {
|
||||
"hashes": [
|
||||
|
@ -555,11 +526,11 @@
|
|||
},
|
||||
"prompt-toolkit": {
|
||||
"hashes": [
|
||||
"sha256:4cea7d09e46723885cb8bc54678175453e5071e9449821dce6f017b1d1fbfc1a",
|
||||
"sha256:9397a7162cf45449147ad6042fa37983a081b8a73363a5253dd4072666333137"
|
||||
"sha256:bf00f22079f5fadc949f42ae8ff7f05702826a97059ffcc6281036ad40ac6f04",
|
||||
"sha256:e1b4f11b9336a28fa11810bc623c357420f69dfdb6d2dac41ca2c21a55c033bc"
|
||||
],
|
||||
"markers": "python_full_version >= '3.6.1'",
|
||||
"version": "==3.0.17"
|
||||
"version": "==3.0.18"
|
||||
},
|
||||
"ptyprocess": {
|
||||
"hashes": [
|
||||
|
@ -578,9 +549,9 @@
|
|||
},
|
||||
"py-cpuinfo": {
|
||||
"hashes": [
|
||||
"sha256:9aa2e49675114959697d25cf57fec41c29b55887bff3bc4809b44ac6f5730097"
|
||||
"sha256:5f269be0e08e33fd959de96b34cd4aeeeacac014dd8305f70eb28d06de2345c5"
|
||||
],
|
||||
"version": "==7.0.0"
|
||||
"version": "==8.0.0"
|
||||
},
|
||||
"pygal": {
|
||||
"hashes": [
|
||||
|
@ -598,11 +569,11 @@
|
|||
},
|
||||
"pygments": {
|
||||
"hashes": [
|
||||
"sha256:2656e1a6edcdabf4275f9a3640db59fd5de107d88e8663c5d4e9a0fa62f77f94",
|
||||
"sha256:534ef71d539ae97d4c3a4cf7d6f110f214b0e687e92f9cb9d2a3b0d3101289c8"
|
||||
"sha256:a18f47b506a429f6f4b9df81bb02beab9ca21d0a5fee38ed15aef65f0545519f",
|
||||
"sha256:d66e804411278594d764fc69ec36ec13d9ae9147193a1740cd34d272ca383b8e"
|
||||
],
|
||||
"markers": "python_version >= '3.5'",
|
||||
"version": "==2.8.1"
|
||||
"version": "==2.9.0"
|
||||
},
|
||||
"pyparsing": {
|
||||
"hashes": [
|
||||
|
@ -621,46 +592,38 @@
|
|||
},
|
||||
"pytest": {
|
||||
"hashes": [
|
||||
"sha256:9d1edf9e7d0b84d72ea3dbcdfd22b35fb543a5e8f2a60092dd578936bf63d7f9",
|
||||
"sha256:b574b57423e818210672e07ca1fa90aaf194a4f63f3ab909a2c67ebb22913839"
|
||||
"sha256:50bcad0a0b9c5a72c8e4e7c9855a3ad496ca6a881a3641b4260605450772c54b",
|
||||
"sha256:91ef2131a9bd6be8f76f1f08eac5c5317221d6ad1e143ae03894b862e8976890"
|
||||
],
|
||||
"index": "pypi",
|
||||
"version": "==6.2.2"
|
||||
"version": "==6.2.4"
|
||||
},
|
||||
"pytest-benchmark": {
|
||||
"extras": [
|
||||
"histogram"
|
||||
],
|
||||
"hashes": [
|
||||
"sha256:01f79d38d506f5a3a0a9ada22ded714537bbdfc8147a881a35c1655db07289d9",
|
||||
"sha256:ad4314d093a3089701b24c80a05121994c7765ce373478c8f4ba8d23c9ba9528"
|
||||
"sha256:36d2b08c4882f6f997fd3126a3d6dfd70f3249cde178ed8bbc0b73db7c20f809",
|
||||
"sha256:40e263f912de5a81d891619032983557d62a3d85843f9a9f30b98baea0cd7b47"
|
||||
],
|
||||
"index": "pypi",
|
||||
"version": "==3.2.3"
|
||||
"version": "==3.4.1"
|
||||
},
|
||||
"pytest-cov": {
|
||||
"hashes": [
|
||||
"sha256:359952d9d39b9f822d9d29324483e7ba04a3a17dd7d05aa6beb7ea01e359e5f7",
|
||||
"sha256:bdb9fdb0b85a7cc825269a4c56b48ccaa5c7e365054b6038772c32ddcdc969da"
|
||||
"sha256:261bb9e47e65bd099c89c3edf92972865210c36813f80ede5277dceb77a4a62a",
|
||||
"sha256:261ceeb8c227b726249b376b8526b600f38667ee314f910353fa318caa01f4d7"
|
||||
],
|
||||
"index": "pypi",
|
||||
"version": "==2.11.1"
|
||||
},
|
||||
"pytest-mock": {
|
||||
"hashes": [
|
||||
"sha256:379b391cfad22422ea2e252bdfc008edd08509029bcde3c25b2c0bd741e0424e",
|
||||
"sha256:a1e2aba6af9560d313c642dae7e00a2a12b022b80301d9d7fc8ec6858e1dd9fc"
|
||||
],
|
||||
"index": "pypi",
|
||||
"version": "==3.5.1"
|
||||
"version": "==2.12.1"
|
||||
},
|
||||
"pytest-mypy": {
|
||||
"hashes": [
|
||||
"sha256:63d418a4fea7d598ac40b659723c00804d16a251d90a5cfbca213eeba5aaf01c",
|
||||
"sha256:8d2112972c1debf087943f48963a0daf04f3424840aea0cf437cc97053b1b0ef"
|
||||
"sha256:1fa55723a4bf1d054fcba1c3bd694215a2a65cc95ab10164f5808afd893f3b11",
|
||||
"sha256:6e68e8eb7ceeb7d1c83a1590912f784879f037b51adfb9c17b95c6b2fc57466b"
|
||||
],
|
||||
"index": "pypi",
|
||||
"version": "==0.8.0"
|
||||
"version": "==0.8.1"
|
||||
},
|
||||
"python-dateutil": {
|
||||
"hashes": [
|
||||
|
@ -677,78 +640,43 @@
|
|||
],
|
||||
"version": "==2021.1"
|
||||
},
|
||||
"pyyaml": {
|
||||
"hashes": [
|
||||
"sha256:08682f6b72c722394747bddaf0aa62277e02557c0fd1c42cb853016a38f8dedf",
|
||||
"sha256:0f5f5786c0e09baddcd8b4b45f20a7b5d61a7e7e99846e3c799b05c7c53fa696",
|
||||
"sha256:129def1b7c1bf22faffd67b8f3724645203b79d8f4cc81f674654d9902cb4393",
|
||||
"sha256:294db365efa064d00b8d1ef65d8ea2c3426ac366c0c4368d930bf1c5fb497f77",
|
||||
"sha256:3b2b1824fe7112845700f815ff6a489360226a5609b96ec2190a45e62a9fc922",
|
||||
"sha256:3bd0e463264cf257d1ffd2e40223b197271046d09dadf73a0fe82b9c1fc385a5",
|
||||
"sha256:4465124ef1b18d9ace298060f4eccc64b0850899ac4ac53294547536533800c8",
|
||||
"sha256:49d4cdd9065b9b6e206d0595fee27a96b5dd22618e7520c33204a4a3239d5b10",
|
||||
"sha256:4e0583d24c881e14342eaf4ec5fbc97f934b999a6828693a99157fde912540cc",
|
||||
"sha256:5accb17103e43963b80e6f837831f38d314a0495500067cb25afab2e8d7a4018",
|
||||
"sha256:607774cbba28732bfa802b54baa7484215f530991055bb562efbed5b2f20a45e",
|
||||
"sha256:6c78645d400265a062508ae399b60b8c167bf003db364ecb26dcab2bda048253",
|
||||
"sha256:72a01f726a9c7851ca9bfad6fd09ca4e090a023c00945ea05ba1638c09dc3347",
|
||||
"sha256:74c1485f7707cf707a7aef42ef6322b8f97921bd89be2ab6317fd782c2d53183",
|
||||
"sha256:895f61ef02e8fed38159bb70f7e100e00f471eae2bc838cd0f4ebb21e28f8541",
|
||||
"sha256:8c1be557ee92a20f184922c7b6424e8ab6691788e6d86137c5d93c1a6ec1b8fb",
|
||||
"sha256:bb4191dfc9306777bc594117aee052446b3fa88737cd13b7188d0e7aa8162185",
|
||||
"sha256:bfb51918d4ff3d77c1c856a9699f8492c612cde32fd3bcd344af9be34999bfdc",
|
||||
"sha256:c20cfa2d49991c8b4147af39859b167664f2ad4561704ee74c1de03318e898db",
|
||||
"sha256:cb333c16912324fd5f769fff6bc5de372e9e7a202247b48870bc251ed40239aa",
|
||||
"sha256:d2d9808ea7b4af864f35ea216be506ecec180628aced0704e34aca0b040ffe46",
|
||||
"sha256:d483ad4e639292c90170eb6f7783ad19490e7a8defb3e46f97dfe4bacae89122",
|
||||
"sha256:dd5de0646207f053eb0d6c74ae45ba98c3395a571a2891858e87df7c9b9bd51b",
|
||||
"sha256:e1d4970ea66be07ae37a3c2e48b5ec63f7ba6804bdddfdbd3cfd954d25a82e63",
|
||||
"sha256:e4fac90784481d221a8e4b1162afa7c47ed953be40d31ab4629ae917510051df",
|
||||
"sha256:fa5ae20527d8e831e8230cbffd9f8fe952815b2b7dae6ffec25318803a7528fc",
|
||||
"sha256:fd7f6999a8070df521b6384004ef42833b9bd62cfee11a09bda1079b4b704247",
|
||||
"sha256:fdc842473cd33f45ff6bce46aea678a54e3d21f1b61a7750ce3c498eedfe25d6",
|
||||
"sha256:fe69978f3f768926cfa37b867e3843918e012cf83f680806599ddce33c2c68b0"
|
||||
],
|
||||
"markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4, 3.5'",
|
||||
"version": "==5.4.1"
|
||||
},
|
||||
"pyzmq": {
|
||||
"hashes": [
|
||||
"sha256:13465c1ff969cab328bc92f7015ce3843f6e35f8871ad79d236e4fbc85dbe4cb",
|
||||
"sha256:23a74de4b43c05c3044aeba0d1f3970def8f916151a712a3ac1e5cd9c0bc2902",
|
||||
"sha256:26380487eae4034d6c2a3fb8d0f2dff6dd0d9dd711894e8d25aa2d1938950a33",
|
||||
"sha256:279cc9b51db48bec2db146f38e336049ac5a59e5f12fb3a8ad864e238c1c62e3",
|
||||
"sha256:2f971431aaebe0a8b54ac018e041c2f0b949a43745444e4dadcc80d0f0ef8457",
|
||||
"sha256:30df70f81fe210506aa354d7fd486a39b87d9f7f24c3d3f4f698ec5d96b8c084",
|
||||
"sha256:33acd2b9790818b9d00526135acf12790649d8d34b2b04d64558b469c9d86820",
|
||||
"sha256:38e3dca75d81bec4f2defa14b0a65b74545812bb519a8e89c8df96bbf4639356",
|
||||
"sha256:3e29f9cf85a40d521d048b55c63f59d6c772ac1c4bf51cdfc23b62a62e377c33",
|
||||
"sha256:3ef50d74469b03725d781a2a03c57537d86847ccde587130fe35caafea8f75c6",
|
||||
"sha256:4231943514812dfb74f44eadcf85e8dd8cf302b4d0bce450ce1357cac88dbfdc",
|
||||
"sha256:4f34a173f813b38b83f058e267e30465ed64b22cd0cf6bad21148d3fa718f9bb",
|
||||
"sha256:532af3e6dddea62d9c49062ece5add998c9823c2419da943cf95589f56737de0",
|
||||
"sha256:581787c62eaa0e0db6c5413cedc393ebbadac6ddfd22e1cf9a60da23c4f1a4b2",
|
||||
"sha256:60e63577b85055e4cc43892fecd877b86695ee3ef12d5d10a3c5d6e77a7cc1a3",
|
||||
"sha256:61e4bb6cd60caf1abcd796c3f48395e22c5b486eeca6f3a8797975c57d94b03e",
|
||||
"sha256:6d4163704201fff0f3ab0cd5d7a0ea1514ecfffd3926d62ec7e740a04d2012c7",
|
||||
"sha256:7026f0353977431fc884abd4ac28268894bd1a780ba84bb266d470b0ec26d2ed",
|
||||
"sha256:763c175294d861869f18eb42901d500eda7d3fa4565f160b3b2fd2678ea0ebab",
|
||||
"sha256:81e7df0da456206201e226491aa1fc449da85328bf33bbeec2c03bb3a9f18324",
|
||||
"sha256:9221783dacb419604d5345d0e097bddef4459a9a95322de6c306bf1d9896559f",
|
||||
"sha256:a558c5bc89d56d7253187dccc4e81b5bb0eac5ae9511eb4951910a1245d04622",
|
||||
"sha256:b25e5d339550a850f7e919fe8cb4c8eabe4c917613db48dab3df19bfb9a28969",
|
||||
"sha256:b62ea18c0458a65ccd5be90f276f7a5a3f26a6dea0066d948ce2fa896051420f",
|
||||
"sha256:c0cde362075ee8f3d2b0353b283e203c2200243b5a15d5c5c03b78112a17e7d4",
|
||||
"sha256:c5e29fe4678f97ce429f076a2a049a3d0b2660ada8f2c621e5dc9939426056dd",
|
||||
"sha256:d18ddc6741b51f3985978f2fda57ddcdae359662d7a6b395bc8ff2292fca14bd",
|
||||
"sha256:da7d4d4c778c86b60949d17531e60c54ed3726878de8a7f8a6d6e7f8cc8c3205",
|
||||
"sha256:f52070871a0fd90a99130babf21f8af192304ec1e995bec2a9533efc21ea4452",
|
||||
"sha256:f5831eff6b125992ec65d973f5151c48003b6754030094723ac4c6e80a97c8c4",
|
||||
"sha256:f7f63ce127980d40f3e6a5fdb87abf17ce1a7c2bd8bf2c7560e1bbce8ab1f92d",
|
||||
"sha256:ff1ea14075bbddd6f29bf6beb8a46d0db779bcec6b9820909584081ec119f8fd"
|
||||
"sha256:089b974ec04d663b8685ac90e86bfe0e4da9d911ff3cf52cb765ff22408b102d",
|
||||
"sha256:0ea7f4237991b0f745a4432c63e888450840bf8cb6c48b93fb7d62864f455529",
|
||||
"sha256:0f0f27eaab9ba7b92d73d71c51d1a04464a1da6097a252d007922103253d2313",
|
||||
"sha256:12ffcf33db6ba7c0e5aaf901e65517f5e2b719367b80bcbfad692f546a297c7a",
|
||||
"sha256:1389b615917d4196962a9b469e947ba862a8ec6f5094a47da5e7a8d404bc07a4",
|
||||
"sha256:18dd2ca4540c476558099891c129e6f94109971d110b549db2a9775c817cedbd",
|
||||
"sha256:24fb5bb641f0b2aa25fc3832f4b6fc62430f14a7d328229fe994b2bcdc07c93a",
|
||||
"sha256:285514956c08c7830da9d94e01f5414661a987831bd9f95e4d89cc8aaae8da10",
|
||||
"sha256:41049cff5265e9cd75606aa2c90a76b9c80b98d8fe70ee08cf4af3cedb113358",
|
||||
"sha256:461ed80d741692d9457ab820b1cc057ba9c37c394e67b647b639f623c8b321f6",
|
||||
"sha256:4b8fb1b3174b56fd020e4b10232b1764e52cf7f3babcfb460c5253bdc48adad0",
|
||||
"sha256:4c4fe69c7dc0d13d4ae180ad650bb900854367f3349d3c16f0569f6c6447f698",
|
||||
"sha256:4e9b9a2f6944acdaf57316436c1acdcb30b8df76726bcf570ad9342bc5001654",
|
||||
"sha256:6355f81947e1fe6e7bb9e123aeb3067264391d3ebe8402709f824ef8673fa6f3",
|
||||
"sha256:68be16107f41563b9f67d93dff1c9f5587e0f76aa8fd91dc04c83d813bcdab1f",
|
||||
"sha256:68e2c4505992ab5b89f976f89a9135742b18d60068f761bef994a6805f1cae0c",
|
||||
"sha256:7040d6dd85ea65703904d023d7f57fab793d7ffee9ba9e14f3b897f34ff2415d",
|
||||
"sha256:734ea6565c71fc2d03d5b8c7d0d7519c96bb5567e0396da1b563c24a4ac66f0c",
|
||||
"sha256:9ee48413a2d3cd867fd836737b4c89c24cea1150a37f4856d82d20293fa7519f",
|
||||
"sha256:a1c77796f395804d6002ff56a6a8168c1f98579896897ad7e35665a9b4a9eec5",
|
||||
"sha256:b2f707b52e09098a7770503e39294ca6e22ae5138ffa1dd36248b6436d23d78e",
|
||||
"sha256:bf80b2cec42d96117248b99d3c86e263a00469c840a778e6cb52d916f4fdf82c",
|
||||
"sha256:c4674004ed64685a38bee222cd75afa769424ec603f9329f0dd4777138337f48",
|
||||
"sha256:c6a81c9e6754465d09a87e3acd74d9bb1f0039b2d785c6899622f0afdb41d760",
|
||||
"sha256:c6d0c32532a0519997e1ded767e184ebb8543bdb351f8eff8570bd461e874efc",
|
||||
"sha256:c8fff75af4c7af92dce9f81fa2a83ed009c3e1f33ee8b5222db2ef80b94e242e",
|
||||
"sha256:cb9f9fe1305ef69b65794655fd89b2209b11bff3e837de981820a8aa051ef914",
|
||||
"sha256:d3ecfee2ee8d91ab2e08d2d8e89302c729b244e302bbc39c5b5dde42306ff003",
|
||||
"sha256:d5e5be93e1714a59a535bbbc086b9e4fd2448c7547c5288548f6fd86353cad9e",
|
||||
"sha256:de5806be66c9108e4dcdaced084e8ceae14100aa559e2d57b4f0cceb98c462de",
|
||||
"sha256:f49755684a963731479ff3035d45a8185545b4c9f662d368bd349c419839886d",
|
||||
"sha256:fc712a90401bcbf3fa25747f189d6dcfccbecc32712701cad25c6355589dac57"
|
||||
],
|
||||
"markers": "python_version >= '3.6'",
|
||||
"version": "==22.0.3"
|
||||
"version": "==22.1.0"
|
||||
},
|
||||
"requests": {
|
||||
"hashes": [
|
||||
|
@ -760,11 +688,11 @@
|
|||
},
|
||||
"six": {
|
||||
"hashes": [
|
||||
"sha256:30639c035cdb23534cd4aa2dd52c3bf48f06e5f4a941509c8bafd8ce11080259",
|
||||
"sha256:8b74bedcbbbaca38ff6d7491d76f2b06b3592611af620f8426e82dddb04a5ced"
|
||||
"sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926",
|
||||
"sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254"
|
||||
],
|
||||
"markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'",
|
||||
"version": "==1.15.0"
|
||||
"version": "==1.16.0"
|
||||
},
|
||||
"snowballstemmer": {
|
||||
"hashes": [
|
||||
|
@ -773,20 +701,13 @@
|
|||
],
|
||||
"version": "==2.1.0"
|
||||
},
|
||||
"sortedcontainers": {
|
||||
"hashes": [
|
||||
"sha256:37257a32add0a3ee490bb170b599e93095eed89a55da91fa9f48753ea12fd73f",
|
||||
"sha256:59cc937650cf60d677c16775597c89a960658a09cf7c1a668f86e1e4464b10a1"
|
||||
],
|
||||
"version": "==2.3.0"
|
||||
},
|
||||
"sphinx": {
|
||||
"hashes": [
|
||||
"sha256:672cfcc24b6b69235c97c750cb190a44ecd72696b4452acaf75c2d9cc78ca5ff",
|
||||
"sha256:ef64a814576f46ec7de06adf11b433a0d6049be007fefe7fd0d183d28b581fac"
|
||||
"sha256:b5c2ae4120bf00c799ba9b3699bc895816d272d120080fbc967292f29b52b48c",
|
||||
"sha256:d1cb10bee9c4231f1700ec2e24a91be3f3a3aba066ea4ca9f3bbe47e59d5a1d4"
|
||||
],
|
||||
"index": "pypi",
|
||||
"version": "==3.5.2"
|
||||
"version": "==4.0.2"
|
||||
},
|
||||
"sphinx-autobuild": {
|
||||
"hashes": [
|
||||
|
@ -798,11 +719,11 @@
|
|||
},
|
||||
"sphinx-rtd-theme": {
|
||||
"hashes": [
|
||||
"sha256:eda689eda0c7301a80cf122dad28b1861e5605cbf455558f3775e1e8200e83a5",
|
||||
"sha256:fa6bebd5ab9a73da8e102509a86f3fcc36dec04a0b52ea80e5a033b2aba00113"
|
||||
"sha256:32bd3b5d13dc8186d7a42fc816a23d32e83a4827d7d9882948e7b837c232da5a",
|
||||
"sha256:4a05bdbe8b1446d77a01e20a23ebc6777c74f43237035e76be89699308987d6f"
|
||||
],
|
||||
"index": "pypi",
|
||||
"version": "==0.5.1"
|
||||
"version": "==0.5.2"
|
||||
},
|
||||
"sphinxcontrib-applehelp": {
|
||||
"hashes": [
|
||||
|
@ -822,11 +743,11 @@
|
|||
},
|
||||
"sphinxcontrib-htmlhelp": {
|
||||
"hashes": [
|
||||
"sha256:3c0bc24a2c41e340ac37c85ced6dafc879ab485c095b1d65d2461ac2f7cca86f",
|
||||
"sha256:e8f5bb7e31b2dbb25b9cc435c8ab7a79787ebf7f906155729338f3156d93659b"
|
||||
"sha256:d412243dfb797ae3ec2b59eca0e52dac12e75a241bf0e4eb861e450d06c6ed07",
|
||||
"sha256:f5f8bb2d0d629f398bf47d0d69c07bc13b65f75a81ad9e2f71a63d4b7a2f6db2"
|
||||
],
|
||||
"markers": "python_version >= '3.5'",
|
||||
"version": "==1.0.3"
|
||||
"markers": "python_version >= '3.6'",
|
||||
"version": "==2.0.0"
|
||||
},
|
||||
"sphinxcontrib-jsmath": {
|
||||
"hashes": [
|
||||
|
@ -846,11 +767,11 @@
|
|||
},
|
||||
"sphinxcontrib-serializinghtml": {
|
||||
"hashes": [
|
||||
"sha256:eaa0eccc86e982a9b939b2b82d12cc5d013385ba5eadcc7e4fed23f4405f77bc",
|
||||
"sha256:f242a81d423f59617a8e5cf16f5d4d74e28ee9a66f9e5b637a18082991db5a9a"
|
||||
"sha256:352a9a00ae864471d3a7ead8d7d79f5fc0b57e8b3f95e9867eb9eb28999b92fd",
|
||||
"sha256:aa5f6de5dfdf809ef505c4895e51ef5c9eac17d0f287933eb49ec495280b6952"
|
||||
],
|
||||
"markers": "python_version >= '3.5'",
|
||||
"version": "==1.1.4"
|
||||
"version": "==1.1.5"
|
||||
},
|
||||
"toml": {
|
||||
"hashes": [
|
||||
|
@ -917,62 +838,54 @@
|
|||
},
|
||||
"typed-ast": {
|
||||
"hashes": [
|
||||
"sha256:07d49388d5bf7e863f7fa2f124b1b1d89d8aa0e2f7812faff0a5658c01c59aa1",
|
||||
"sha256:14bf1522cdee369e8f5581238edac09150c765ec1cb33615855889cf33dcb92d",
|
||||
"sha256:240296b27397e4e37874abb1df2a608a92df85cf3e2a04d0d4d61055c8305ba6",
|
||||
"sha256:36d829b31ab67d6fcb30e185ec996e1f72b892255a745d3a82138c97d21ed1cd",
|
||||
"sha256:37f48d46d733d57cc70fd5f30572d11ab8ed92da6e6b28e024e4a3edfb456e37",
|
||||
"sha256:4c790331247081ea7c632a76d5b2a265e6d325ecd3179d06e9cf8d46d90dd151",
|
||||
"sha256:5dcfc2e264bd8a1db8b11a892bd1647154ce03eeba94b461effe68790d8b8e07",
|
||||
"sha256:7147e2a76c75f0f64c4319886e7639e490fee87c9d25cb1d4faef1d8cf83a440",
|
||||
"sha256:7703620125e4fb79b64aa52427ec192822e9f45d37d4b6625ab37ef403e1df70",
|
||||
"sha256:8368f83e93c7156ccd40e49a783a6a6850ca25b556c0fa0240ed0f659d2fe496",
|
||||
"sha256:84aa6223d71012c68d577c83f4e7db50d11d6b1399a9c779046d75e24bed74ea",
|
||||
"sha256:85f95aa97a35bdb2f2f7d10ec5bbdac0aeb9dafdaf88e17492da0504de2e6400",
|
||||
"sha256:8db0e856712f79c45956da0c9a40ca4246abc3485ae0d7ecc86a20f5e4c09abc",
|
||||
"sha256:9044ef2df88d7f33692ae3f18d3be63dec69c4fb1b5a4a9ac950f9b4ba571606",
|
||||
"sha256:963c80b583b0661918718b095e02303d8078950b26cc00b5e5ea9ababe0de1fc",
|
||||
"sha256:987f15737aba2ab5f3928c617ccf1ce412e2e321c77ab16ca5a293e7bbffd581",
|
||||
"sha256:9ec45db0c766f196ae629e509f059ff05fc3148f9ffd28f3cfe75d4afb485412",
|
||||
"sha256:9fc0b3cb5d1720e7141d103cf4819aea239f7d136acf9ee4a69b047b7986175a",
|
||||
"sha256:a2c927c49f2029291fbabd673d51a2180038f8cd5a5b2f290f78c4516be48be2",
|
||||
"sha256:a38878a223bdd37c9709d07cd357bb79f4c760b29210e14ad0fb395294583787",
|
||||
"sha256:b4fcdcfa302538f70929eb7b392f536a237cbe2ed9cba88e3bf5027b39f5f77f",
|
||||
"sha256:c0c74e5579af4b977c8b932f40a5464764b2f86681327410aa028a22d2f54937",
|
||||
"sha256:c1c876fd795b36126f773db9cbb393f19808edd2637e00fd6caba0e25f2c7b64",
|
||||
"sha256:c9aadc4924d4b5799112837b226160428524a9a45f830e0d0f184b19e4090487",
|
||||
"sha256:cc7b98bf58167b7f2db91a4327da24fb93368838eb84a44c472283778fc2446b",
|
||||
"sha256:cf54cfa843f297991b7388c281cb3855d911137223c6b6d2dd82a47ae5125a41",
|
||||
"sha256:d003156bb6a59cda9050e983441b7fa2487f7800d76bdc065566b7d728b4581a",
|
||||
"sha256:d175297e9533d8d37437abc14e8a83cbc68af93cc9c1c59c2c292ec59a0697a3",
|
||||
"sha256:d746a437cdbca200622385305aedd9aef68e8a645e385cc483bdc5e488f07166",
|
||||
"sha256:e683e409e5c45d5c9082dc1daf13f6374300806240719f95dc783d1fc942af10"
|
||||
"sha256:01ae5f73431d21eead5015997ab41afa53aa1fbe252f9da060be5dad2c730ace",
|
||||
"sha256:067a74454df670dcaa4e59349a2e5c81e567d8d65458d480a5b3dfecec08c5ff",
|
||||
"sha256:0fb71b8c643187d7492c1f8352f2c15b4c4af3f6338f21681d3681b3dc31a266",
|
||||
"sha256:1b3ead4a96c9101bef08f9f7d1217c096f31667617b58de957f690c92378b528",
|
||||
"sha256:2068531575a125b87a41802130fa7e29f26c09a2833fea68d9a40cf33902eba6",
|
||||
"sha256:209596a4ec71d990d71d5e0d312ac935d86930e6eecff6ccc7007fe54d703808",
|
||||
"sha256:2c726c276d09fc5c414693a2de063f521052d9ea7c240ce553316f70656c84d4",
|
||||
"sha256:398e44cd480f4d2b7ee8d98385ca104e35c81525dd98c519acff1b79bdaac363",
|
||||
"sha256:52b1eb8c83f178ab787f3a4283f68258525f8d70f778a2f6dd54d3b5e5fb4341",
|
||||
"sha256:5feca99c17af94057417d744607b82dd0a664fd5e4ca98061480fd8b14b18d04",
|
||||
"sha256:7538e495704e2ccda9b234b82423a4038f324f3a10c43bc088a1636180f11a41",
|
||||
"sha256:760ad187b1041a154f0e4d0f6aae3e40fdb51d6de16e5c99aedadd9246450e9e",
|
||||
"sha256:777a26c84bea6cd934422ac2e3b78863a37017618b6e5c08f92ef69853e765d3",
|
||||
"sha256:95431a26309a21874005845c21118c83991c63ea800dd44843e42a916aec5899",
|
||||
"sha256:9ad2c92ec681e02baf81fdfa056fe0d818645efa9af1f1cd5fd6f1bd2bdfd805",
|
||||
"sha256:9c6d1a54552b5330bc657b7ef0eae25d00ba7ffe85d9ea8ae6540d2197a3788c",
|
||||
"sha256:aee0c1256be6c07bd3e1263ff920c325b59849dc95392a05f258bb9b259cf39c",
|
||||
"sha256:af3d4a73793725138d6b334d9d247ce7e5f084d96284ed23f22ee626a7b88e39",
|
||||
"sha256:b36b4f3920103a25e1d5d024d155c504080959582b928e91cb608a65c3a49e1a",
|
||||
"sha256:b9574c6f03f685070d859e75c7f9eeca02d6933273b5e69572e5ff9d5e3931c3",
|
||||
"sha256:bff6ad71c81b3bba8fa35f0f1921fb24ff4476235a6e94a26ada2e54370e6da7",
|
||||
"sha256:c190f0899e9f9f8b6b7863debfb739abcb21a5c054f911ca3596d12b8a4c4c7f",
|
||||
"sha256:c907f561b1e83e93fad565bac5ba9c22d96a54e7ea0267c708bffe863cbe4075",
|
||||
"sha256:cae53c389825d3b46fb37538441f75d6aecc4174f615d048321b716df2757fb0",
|
||||
"sha256:dd4a21253f42b8d2b48410cb31fe501d32f8b9fbeb1f55063ad102fe9c425e40",
|
||||
"sha256:dde816ca9dac1d9c01dd504ea5967821606f02e510438120091b84e852367428",
|
||||
"sha256:f2362f3cb0f3172c42938946dbc5b7843c2a28aec307c49100c8b38764eb6927",
|
||||
"sha256:f328adcfebed9f11301eaedfa48e15bdece9b519fb27e6a8c01aa52a17ec31b3",
|
||||
"sha256:f8afcf15cc511ada719a88e013cec87c11aff7b91f019295eb4530f96fe5ef2f",
|
||||
"sha256:fb1bbeac803adea29cedd70781399c99138358c26d05fcbd23c13016b7f5ec65"
|
||||
],
|
||||
"version": "==1.4.2"
|
||||
"version": "==1.4.3"
|
||||
},
|
||||
"typing-extensions": {
|
||||
"hashes": [
|
||||
"sha256:7cb407020f00f7bfc3cb3e7881628838e69d8f3fcab2f64742a5e76b2f841918",
|
||||
"sha256:99d4073b617d30288f569d3f13d2bd7548c3a7e4c8de87db09a9d29bb3a4a60c",
|
||||
"sha256:dafc7639cde7f1b6e1acc0f457842a83e722ccca8eef5270af2d74792619a89f"
|
||||
"sha256:0ac0f89795dd19de6b97debb0c6af1c70987fd80a2d62d1958f7e56fcc31b497",
|
||||
"sha256:50b6f157849174217d0656f99dc82fe932884fb250826c18350e159ec6cdf342",
|
||||
"sha256:779383f6086d90c99ae41cf0ff39aac8a7937a9283ce0a414e5dd782f4c94a84"
|
||||
],
|
||||
"version": "==3.7.4.3"
|
||||
},
|
||||
"typing-inspect": {
|
||||
"hashes": [
|
||||
"sha256:3b98390df4d999a28cf5b35d8b333425af5da2ece8a4ea9e98f71e7591347b4f",
|
||||
"sha256:8f1b1dd25908dbfd81d3bebc218011531e7ab614ba6e5bf7826d887c834afab7",
|
||||
"sha256:de08f50a22955ddec353876df7b2545994d6df08a2f45d54ac8c05e530372ca0"
|
||||
],
|
||||
"version": "==0.6.0"
|
||||
"version": "==3.10.0.0"
|
||||
},
|
||||
"urllib3": {
|
||||
"hashes": [
|
||||
"sha256:2f4da4594db7e1e110a944bb1b551fdf4e6c136ad42e4234131391e21eb5b0df",
|
||||
"sha256:e7b021f7241115872f92f43c6508082facffbd1c048e3c6e2bb9c2a157e28937"
|
||||
"sha256:753a0374df26658f99d826cfe40394a686d05985786d946fbe4165b5148f5a7c",
|
||||
"sha256:a7acd0977125325f516bda9735fa7142b909a8d01e8b2e4c8108d0984e6e0098"
|
||||
],
|
||||
"markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4' and python_version < '4'",
|
||||
"version": "==1.26.4"
|
||||
"version": "==1.26.5"
|
||||
},
|
||||
"wcwidth": {
|
||||
"hashes": [
|
||||
|
|
|
@ -147,7 +147,7 @@ and then decrypts the re-encrypted ciphertext.
|
|||
|
||||
from umbral import decrypt_reencrypted
|
||||
|
||||
bob_cleartext = pre.decrypt_reencrypted(decrypting_sk=bobs_secret_key,
|
||||
bob_cleartext = pre.decrypt_reencrypted(receiving_sk=bobs_secret_key,
|
||||
delegating_pk=alices_public_key,
|
||||
capsule=capsule,
|
||||
cfrags=cfrags,
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import random
|
||||
from umbral import (
|
||||
SecretKey, PublicKey, Signer, GenericError, CapsuleFrag,
|
||||
SecretKey, PublicKey, Signer, CapsuleFrag,
|
||||
encrypt, generate_kfrags, reencrypt, decrypt_original, decrypt_reencrypted)
|
||||
|
||||
# Generate an Umbral key pair
|
||||
|
@ -46,7 +46,7 @@ bob_capsule = capsule
|
|||
# Attempt Bob's decryption (fail)
|
||||
try:
|
||||
fail_decrypted_data = decrypt_original(bobs_secret_key, bob_capsule, ciphertext)
|
||||
except GenericError:
|
||||
except ValueError:
|
||||
print("Decryption failed! Bob doesn't has access granted yet.")
|
||||
|
||||
# Alice grants access to Bob by generating kfrags
|
||||
|
@ -103,7 +103,7 @@ cfrags = [cfrag.verify(capsule,
|
|||
# ------------------------------------
|
||||
# Finally, Bob decrypts the re-encrypted ciphertext using his key.
|
||||
|
||||
bob_cleartext = decrypt_reencrypted(decrypting_sk=bobs_secret_key,
|
||||
bob_cleartext = decrypt_reencrypted(receiving_sk=bobs_secret_key,
|
||||
delegating_pk=alices_public_key,
|
||||
capsule=bob_capsule,
|
||||
verified_cfrags=cfrags,
|
||||
|
|
|
@ -94,7 +94,7 @@
|
|||
"from umbral import decrypt_original\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"cleartext = decrypt_original(sk=alices_private_key,\n",
|
||||
"cleartext = decrypt_original(delegating_sk=alices_private_key,\n",
|
||||
" capsule=capsule,\n",
|
||||
" ciphertext=ciphertext)\n",
|
||||
"print(cleartext)"
|
||||
|
@ -141,13 +141,11 @@
|
|||
}
|
||||
],
|
||||
"source": [
|
||||
"from umbral import GenericError\n",
|
||||
"\n",
|
||||
"try:\n",
|
||||
" fail_decrypted_data = decrypt_original(sk=bobs_private_key,\n",
|
||||
" fail_decrypted_data = decrypt_original(delegating_sk=bobs_private_key,\n",
|
||||
" capsule=capsule,\n",
|
||||
" ciphertext=ciphertext)\n",
|
||||
"except GenericError:\n",
|
||||
"except ValueError:\n",
|
||||
" print(\"Decryption failed! Bob doesn't has access granted yet.\")\n"
|
||||
]
|
||||
},
|
||||
|
@ -266,7 +264,7 @@
|
|||
"source": [
|
||||
"from umbral import decrypt_reencrypted\n",
|
||||
"\n",
|
||||
"bob_cleartext = decrypt_reencrypted(decrypting_sk=bobs_private_key,\n",
|
||||
"bob_cleartext = decrypt_reencrypted(receiving_sk=bobs_private_key,\n",
|
||||
" delegating_pk=alices_public_key,\n",
|
||||
" capsule=capsule,\n",
|
||||
" verified_cfrags=cfrags,\n",
|
||||
|
|
|
@ -40,7 +40,9 @@ Intermediate objects
|
|||
:show-inheritance:
|
||||
|
||||
.. autoclass:: VerifiedKeyFrag()
|
||||
:members:
|
||||
:special-members: __eq__, __hash__
|
||||
:show-inheritance:
|
||||
|
||||
.. autoclass:: CapsuleFrag()
|
||||
:members:
|
||||
|
@ -49,6 +51,7 @@ Intermediate objects
|
|||
|
||||
.. autoclass:: VerifiedCapsuleFrag()
|
||||
:special-members: __eq__, __hash__
|
||||
:show-inheritance:
|
||||
|
||||
Encryption, re-encryption and decryption
|
||||
----------------------------------------
|
||||
|
@ -66,12 +69,16 @@ Encryption, re-encryption and decryption
|
|||
Utilities
|
||||
---------
|
||||
|
||||
.. autoclass:: umbral.GenericError
|
||||
:show-inheritance:
|
||||
|
||||
.. autoclass:: umbral.VerificationError
|
||||
:show-inheritance:
|
||||
|
||||
.. autoclass:: umbral.serializable.HasSerializedSize
|
||||
:members: serialized_size
|
||||
|
||||
.. autoclass:: umbral.serializable.Serializable
|
||||
:members: from_bytes
|
||||
:special-members: __bytes__
|
||||
:show-inheritance:
|
||||
|
||||
.. autoclass:: umbral.serializable.Deserializable
|
||||
:members: from_bytes
|
||||
:show-inheritance:
|
||||
|
|
|
@ -130,12 +130,12 @@ or re-encrypted for him by Ursula, he will not be able to open it.
|
|||
|
||||
.. doctest:: capsule_story
|
||||
|
||||
>>> fail = decrypt_original(sk=bobs_secret_key,
|
||||
>>> fail = decrypt_original(delegating_sk=bobs_secret_key,
|
||||
... capsule=capsule,
|
||||
... ciphertext=ciphertext)
|
||||
Traceback (most recent call last):
|
||||
...
|
||||
umbral.GenericError
|
||||
ValueError
|
||||
|
||||
|
||||
Ursulas perform re-encryption
|
||||
|
@ -196,7 +196,7 @@ Finally, Bob decrypts the re-encrypted ciphertext using his key.
|
|||
.. doctest:: capsule_story
|
||||
|
||||
>>> from umbral import decrypt_reencrypted
|
||||
>>> cleartext = decrypt_reencrypted(decrypting_sk=bobs_secret_key,
|
||||
>>> cleartext = decrypt_reencrypted(receiving_sk=bobs_secret_key,
|
||||
... delegating_pk=alices_public_key,
|
||||
... capsule=capsule,
|
||||
... verified_cfrags=cfrags,
|
||||
|
|
4
setup.py
4
setup.py
|
@ -65,13 +65,9 @@ INSTALL_REQUIRES = [
|
|||
DEV_INSTALL_REQUIRES = [
|
||||
'pytest',
|
||||
'pytest-mypy',
|
||||
'pytest-mock',
|
||||
'pytest-cov',
|
||||
'mock',
|
||||
'hypothesis',
|
||||
'coverage',
|
||||
'codecov',
|
||||
'monkeytype',
|
||||
'nbval',
|
||||
'mypy',
|
||||
'bumpversion',
|
||||
|
|
|
@ -5,7 +5,6 @@ from umbral import (
|
|||
SecretKey,
|
||||
PublicKey,
|
||||
Signer,
|
||||
GenericError,
|
||||
encrypt,
|
||||
decrypt_original,
|
||||
reencrypt,
|
||||
|
@ -29,7 +28,7 @@ def test_capsule_serialization(alices_keys):
|
|||
capsule.point_e = CurvePoint.random()
|
||||
capsule_bytes = bytes(capsule)
|
||||
|
||||
with pytest.raises(GenericError):
|
||||
with pytest.raises(ValueError):
|
||||
Capsule.from_bytes(capsule_bytes)
|
||||
|
||||
|
||||
|
@ -86,7 +85,7 @@ def test_open_reencrypted(alices_keys, bobs_keys):
|
|||
capsule.open_reencrypted(receiving_sk, delegating_pk, [])
|
||||
|
||||
# Not enough cfrags
|
||||
with pytest.raises(GenericError, match="Internal validation failed"):
|
||||
with pytest.raises(ValueError, match="Internal validation failed"):
|
||||
capsule.open_reencrypted(receiving_sk, delegating_pk, cfrags[:threshold-1])
|
||||
|
||||
# Repeating cfrags
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import pytest
|
||||
|
||||
from umbral import reencrypt, CapsuleFrag, PublicKey, Capsule, VerificationError
|
||||
from umbral import encrypt, reencrypt, CapsuleFrag, PublicKey, Capsule, VerificationError
|
||||
from umbral.curve_point import CurvePoint
|
||||
|
||||
|
||||
|
@ -8,9 +8,8 @@ def test_cfrag_serialization(verification_keys, capsule, kfrags):
|
|||
|
||||
verifying_pk, delegating_pk, receiving_pk = verification_keys
|
||||
|
||||
metadata = b'This is an example of metadata for re-encryption request'
|
||||
for kfrag in kfrags:
|
||||
cfrag = reencrypt(capsule, kfrag, metadata=metadata)
|
||||
cfrag = reencrypt(capsule, kfrag)
|
||||
cfrag_bytes = bytes(cfrag)
|
||||
|
||||
new_cfrag = CapsuleFrag.from_bytes(cfrag_bytes)
|
||||
|
@ -19,34 +18,15 @@ def test_cfrag_serialization(verification_keys, capsule, kfrags):
|
|||
verifying_pk=verifying_pk,
|
||||
delegating_pk=delegating_pk,
|
||||
receiving_pk=receiving_pk,
|
||||
metadata=metadata,
|
||||
)
|
||||
assert verified_cfrag == cfrag
|
||||
|
||||
# No metadata
|
||||
with pytest.raises(VerificationError):
|
||||
new_cfrag.verify(capsule,
|
||||
verifying_pk=verifying_pk,
|
||||
delegating_pk=delegating_pk,
|
||||
receiving_pk=receiving_pk,
|
||||
)
|
||||
|
||||
# Wrong metadata
|
||||
with pytest.raises(VerificationError):
|
||||
new_cfrag.verify(capsule,
|
||||
verifying_pk=verifying_pk,
|
||||
delegating_pk=delegating_pk,
|
||||
receiving_pk=receiving_pk,
|
||||
metadata=b'Not the same metadata',
|
||||
)
|
||||
|
||||
# Wrong delegating key
|
||||
with pytest.raises(VerificationError):
|
||||
new_cfrag.verify(capsule,
|
||||
verifying_pk=verifying_pk,
|
||||
delegating_pk=receiving_pk,
|
||||
receiving_pk=receiving_pk,
|
||||
metadata=metadata,
|
||||
)
|
||||
|
||||
# Wrong receiving key
|
||||
|
@ -55,7 +35,6 @@ def test_cfrag_serialization(verification_keys, capsule, kfrags):
|
|||
verifying_pk=verifying_pk,
|
||||
delegating_pk=delegating_pk,
|
||||
receiving_pk=delegating_pk,
|
||||
metadata=metadata,
|
||||
)
|
||||
|
||||
# Wrong signing key
|
||||
|
@ -64,34 +43,6 @@ def test_cfrag_serialization(verification_keys, capsule, kfrags):
|
|||
verifying_pk=receiving_pk,
|
||||
delegating_pk=delegating_pk,
|
||||
receiving_pk=receiving_pk,
|
||||
metadata=metadata,
|
||||
)
|
||||
|
||||
|
||||
def test_cfrag_serialization_no_metadata(verification_keys, capsule, kfrags):
|
||||
|
||||
verifying_pk, delegating_pk, receiving_pk = verification_keys
|
||||
|
||||
for kfrag in kfrags:
|
||||
|
||||
# Create with no metadata
|
||||
cfrag = reencrypt(capsule, kfrag)
|
||||
cfrag_bytes = bytes(cfrag)
|
||||
new_cfrag = CapsuleFrag.from_bytes(cfrag_bytes)
|
||||
|
||||
verified_cfrag = new_cfrag.verify(capsule,
|
||||
verifying_pk=verifying_pk,
|
||||
delegating_pk=delegating_pk,
|
||||
receiving_pk=receiving_pk,
|
||||
)
|
||||
assert verified_cfrag == cfrag
|
||||
|
||||
with pytest.raises(VerificationError):
|
||||
new_cfrag.verify(capsule,
|
||||
verifying_pk=verifying_pk,
|
||||
delegating_pk=delegating_pk,
|
||||
receiving_pk=receiving_pk,
|
||||
metadata=b'some metadata',
|
||||
)
|
||||
|
||||
|
||||
|
@ -103,8 +54,7 @@ def test_cfrag_with_wrong_capsule(verification_keys, kfrags, capsule_and_ciphert
|
|||
capsule_alice1 = capsule
|
||||
capsule_alice2, _unused_key2 = Capsule.from_public_key(delegating_pk)
|
||||
|
||||
metadata = b"some metadata"
|
||||
cfrag = reencrypt(capsule_alice2, kfrags[0], metadata=metadata)
|
||||
cfrag = reencrypt(capsule_alice2, kfrags[0])
|
||||
cfrag = CapsuleFrag.from_bytes(bytes(cfrag)) # de-verify
|
||||
|
||||
with pytest.raises(VerificationError):
|
||||
|
@ -112,7 +62,6 @@ def test_cfrag_with_wrong_capsule(verification_keys, kfrags, capsule_and_ciphert
|
|||
verifying_pk=verifying_pk,
|
||||
delegating_pk=delegating_pk,
|
||||
receiving_pk=receiving_pk,
|
||||
metadata=metadata,
|
||||
)
|
||||
|
||||
|
||||
|
@ -121,8 +70,7 @@ def test_cfrag_with_wrong_data(verification_keys, kfrags, capsule_and_ciphertext
|
|||
capsule, ciphertext = capsule_and_ciphertext
|
||||
verifying_pk, delegating_pk, receiving_pk = verification_keys
|
||||
|
||||
metadata = b"some metadata"
|
||||
cfrag = reencrypt(capsule, kfrags[0], metadata=metadata)
|
||||
cfrag = reencrypt(capsule, kfrags[0])
|
||||
|
||||
# Let's put random garbage in one of the cfrags
|
||||
cfrag = CapsuleFrag.from_bytes(bytes(cfrag)) # de-verify
|
||||
|
@ -134,7 +82,6 @@ def test_cfrag_with_wrong_data(verification_keys, kfrags, capsule_and_ciphertext
|
|||
verifying_pk=verifying_pk,
|
||||
delegating_pk=delegating_pk,
|
||||
receiving_pk=receiving_pk,
|
||||
metadata=metadata,
|
||||
)
|
||||
|
||||
|
||||
|
@ -142,8 +89,8 @@ def test_cfrag_is_hashable(verification_keys, capsule, kfrags):
|
|||
|
||||
verifying_pk, delegating_pk, receiving_pk = verification_keys
|
||||
|
||||
cfrag0 = reencrypt(capsule, kfrags[0], metadata=b'abcdef')
|
||||
cfrag1 = reencrypt(capsule, kfrags[1], metadata=b'abcdef')
|
||||
cfrag0 = reencrypt(capsule, kfrags[0])
|
||||
cfrag1 = reencrypt(capsule, kfrags[1])
|
||||
|
||||
assert hash(cfrag0) != hash(cfrag1)
|
||||
|
||||
|
@ -154,16 +101,22 @@ def test_cfrag_is_hashable(verification_keys, capsule, kfrags):
|
|||
verifying_pk=verifying_pk,
|
||||
delegating_pk=delegating_pk,
|
||||
receiving_pk=receiving_pk,
|
||||
metadata=b'abcdef')
|
||||
)
|
||||
|
||||
assert hash(verified_cfrag) == hash(cfrag0)
|
||||
|
||||
|
||||
def test_cfrag_str(capsule, kfrags):
|
||||
cfrag0 = reencrypt(capsule, kfrags[0], metadata=b'abcdef')
|
||||
cfrag0 = reencrypt(capsule, kfrags[0])
|
||||
s = str(cfrag0)
|
||||
assert 'VerifiedCapsuleFrag' in s
|
||||
|
||||
s = str(CapsuleFrag.from_bytes(bytes(cfrag0)))
|
||||
assert "VerifiedCapsuleFrag" not in s
|
||||
assert "CapsuleFrag" in s
|
||||
|
||||
|
||||
def test_serialized_size(capsule, kfrags):
|
||||
verified_cfrag = reencrypt(capsule, kfrags[0])
|
||||
cfrag = CapsuleFrag.from_bytes(bytes(verified_cfrag))
|
||||
assert verified_cfrag.serialized_size() == cfrag.serialized_size()
|
||||
|
|
|
@ -143,16 +143,16 @@ def test_kfrags(implementations):
|
|||
|
||||
|
||||
def _reencrypt(umbral, verifying_pk_bytes, delegating_pk_bytes, receiving_pk_bytes,
|
||||
capsule_bytes, kfrags_bytes, threshold, metadata):
|
||||
capsule_bytes, kfrags_bytes, threshold):
|
||||
capsule = umbral.Capsule.from_bytes(bytes(capsule_bytes))
|
||||
verified_kfrags = _verify_kfrags(umbral, kfrags_bytes,
|
||||
verifying_pk_bytes, delegating_pk_bytes, receiving_pk_bytes)
|
||||
cfrags = [umbral.reencrypt(capsule, kfrag, metadata=metadata) for kfrag in verified_kfrags[:threshold]]
|
||||
cfrags = [umbral.reencrypt(capsule, kfrag) for kfrag in verified_kfrags[:threshold]]
|
||||
return [bytes(cfrag) for cfrag in cfrags]
|
||||
|
||||
|
||||
def _decrypt_reencrypted(umbral, receiving_sk_bytes, delegating_pk_bytes, verifying_pk_bytes,
|
||||
capsule_bytes, cfrags_bytes, ciphertext, metadata):
|
||||
capsule_bytes, cfrags_bytes, ciphertext):
|
||||
|
||||
receiving_sk = umbral.SecretKey.from_bytes(receiving_sk_bytes)
|
||||
receiving_pk = umbral.PublicKey.from_secret_key(receiving_sk)
|
||||
|
@ -166,11 +166,11 @@ def _decrypt_reencrypted(umbral, receiving_sk_bytes, delegating_pk_bytes, verify
|
|||
verifying_pk=verifying_pk,
|
||||
delegating_pk=delegating_pk,
|
||||
receiving_pk=receiving_pk,
|
||||
metadata=metadata)
|
||||
)
|
||||
for cfrag in cfrags]
|
||||
|
||||
# Decryption by Bob
|
||||
plaintext = umbral.decrypt_reencrypted(decrypting_sk=receiving_sk,
|
||||
plaintext = umbral.decrypt_reencrypted(receiving_sk=receiving_sk,
|
||||
delegating_pk=delegating_pk,
|
||||
capsule=capsule,
|
||||
verified_cfrags=verified_cfrags,
|
||||
|
@ -184,7 +184,6 @@ def test_reencrypt(implementations):
|
|||
|
||||
umbral1, umbral2 = implementations
|
||||
|
||||
metadata = b'metadata'
|
||||
threshold = 2
|
||||
num_kfrags = 3
|
||||
plaintext = b'peace at dawn'
|
||||
|
@ -203,13 +202,13 @@ def test_reencrypt(implementations):
|
|||
# On client 2
|
||||
|
||||
cfrags_bytes = _reencrypt(umbral2, verifying_pk_bytes, delegating_pk_bytes, receiving_pk_bytes,
|
||||
capsule_bytes, kfrags_bytes, threshold, metadata)
|
||||
capsule_bytes, kfrags_bytes, threshold)
|
||||
|
||||
# On client 1
|
||||
|
||||
plaintext_reencrypted = _decrypt_reencrypted(umbral1,
|
||||
receiving_sk_bytes, delegating_pk_bytes, verifying_pk_bytes,
|
||||
capsule_bytes, cfrags_bytes, ciphertext, metadata)
|
||||
capsule_bytes, cfrags_bytes, ciphertext)
|
||||
|
||||
assert plaintext_reencrypted == plaintext
|
||||
|
||||
|
@ -243,3 +242,30 @@ def test_signer(implementations):
|
|||
|
||||
assert _verify_message(umbral1, pk_bytes, signature2_bytes, message)
|
||||
assert _verify_message(umbral2, pk_bytes, signature1_bytes, message)
|
||||
|
||||
|
||||
def _measure_sizes(umbral):
|
||||
|
||||
sized_types = [
|
||||
umbral.SecretKey,
|
||||
umbral.SecretKeyFactory,
|
||||
umbral.PublicKey,
|
||||
umbral.Signature,
|
||||
umbral.Capsule,
|
||||
umbral.KeyFrag,
|
||||
umbral.VerifiedKeyFrag,
|
||||
umbral.CapsuleFrag,
|
||||
umbral.VerifiedCapsuleFrag,
|
||||
]
|
||||
|
||||
return {tp.__name__: tp.serialized_size() for tp in sized_types}
|
||||
|
||||
|
||||
def test_serialization_size(implementations):
|
||||
|
||||
umbral1, umbral2 = implementations
|
||||
|
||||
sizes1 = _measure_sizes(umbral1)
|
||||
sizes2 = _measure_sizes(umbral1)
|
||||
|
||||
assert sizes1 == sizes2
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
import pytest
|
||||
import os
|
||||
|
||||
from umbral import GenericError
|
||||
from umbral.dem import DEM
|
||||
|
||||
|
||||
|
@ -48,7 +47,7 @@ def test_malformed_ciphertext():
|
|||
dem.decrypt(ciphertext[:DEM.NONCE_SIZE + DEM.TAG_SIZE - 1])
|
||||
|
||||
# Too long
|
||||
with pytest.raises(GenericError):
|
||||
with pytest.raises(ValueError):
|
||||
dem.decrypt(ciphertext + b'abcd')
|
||||
|
||||
|
||||
|
@ -77,5 +76,5 @@ def test_encrypt_decrypt_associated_data():
|
|||
assert cleartext1 == plaintext
|
||||
|
||||
# Attempt decryption with invalid associated data
|
||||
with pytest.raises(GenericError):
|
||||
with pytest.raises(ValueError):
|
||||
cleartext2 = dem.decrypt(ciphertext0, authenticated_data=b'wrong data')
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import pytest
|
||||
|
||||
from umbral import KeyFrag, PublicKey, Signer, VerificationError
|
||||
from umbral.key_frag import KeyFragID, KeyFragBase
|
||||
from umbral.key_frag import KeyFragID, KeyFragBase, VerifiedKeyFrag
|
||||
from umbral.curve_scalar import CurveScalar
|
||||
|
||||
|
||||
|
@ -124,3 +124,15 @@ def test_kfrag_str(kfrags):
|
|||
s = str(KeyFrag.from_bytes(bytes(kfrags[0])))
|
||||
assert "VerifiedKeyFrag" not in s
|
||||
assert "KeyFrag" in s
|
||||
|
||||
|
||||
def test_from_verified_bytes(kfrags):
|
||||
kfrag_bytes = bytes(kfrags[0])
|
||||
verified_kfrag = VerifiedKeyFrag.from_verified_bytes(kfrag_bytes)
|
||||
assert verified_kfrag == kfrags[0]
|
||||
|
||||
|
||||
def test_serialized_size(kfrags):
|
||||
verified_kfrag = kfrags[0]
|
||||
kfrag = KeyFrag.from_bytes(bytes(verified_kfrag))
|
||||
assert verified_kfrag.serialized_size() == kfrag.serialized_size()
|
||||
|
|
|
@ -4,7 +4,6 @@ from umbral import (
|
|||
SecretKey,
|
||||
PublicKey,
|
||||
Signer,
|
||||
GenericError,
|
||||
KeyFrag,
|
||||
CapsuleFrag,
|
||||
encrypt,
|
||||
|
@ -25,7 +24,7 @@ def test_public_key_encryption(alices_keys):
|
|||
|
||||
# Wrong secret key
|
||||
sk = SecretKey.random()
|
||||
with pytest.raises(GenericError):
|
||||
with pytest.raises(ValueError):
|
||||
decrypt_original(sk, capsule, ciphertext)
|
||||
|
||||
|
||||
|
@ -81,7 +80,7 @@ def test_simple_api(num_kfrags, threshold):
|
|||
cfrags = [reencrypt(capsule, kfrag) for kfrag in kfrags]
|
||||
|
||||
# Decryption by Bob
|
||||
plaintext_reenc = decrypt_reencrypted(decrypting_sk=receiving_sk,
|
||||
plaintext_reenc = decrypt_reencrypted(receiving_sk=receiving_sk,
|
||||
delegating_pk=delegating_pk,
|
||||
capsule=capsule,
|
||||
verified_cfrags=cfrags[:threshold],
|
||||
|
@ -105,7 +104,7 @@ def test_decrypt_unverified_cfrag(verification_keys, bobs_keys, capsule_and_ciph
|
|||
cfrags = [reencrypt(capsule, kfrag) for kfrag in kfrags]
|
||||
cfrags[0] = CapsuleFrag.from_bytes(bytes(cfrags[0]))
|
||||
with pytest.raises(TypeError):
|
||||
plaintext_reenc = decrypt_reencrypted(decrypting_sk=receiving_sk,
|
||||
plaintext_reenc = decrypt_reencrypted(receiving_sk=receiving_sk,
|
||||
delegating_pk=delegating_pk,
|
||||
capsule=capsule,
|
||||
verified_cfrags=cfrags,
|
||||
|
|
|
@ -2,55 +2,65 @@ import re
|
|||
|
||||
import pytest
|
||||
|
||||
from umbral.serializable import Serializable, serialize_bool, take_bool
|
||||
from umbral.serializable import Serializable, Deserializable, bool_bytes, bool_from_exact_bytes
|
||||
|
||||
|
||||
class A(Serializable):
|
||||
class A(Serializable, Deserializable):
|
||||
|
||||
def __init__(self, val: int):
|
||||
assert 0 <= val < 2**32
|
||||
self.val = val
|
||||
|
||||
@classmethod
|
||||
def __take__(cls, data):
|
||||
val_bytes, data = cls.__take_bytes__(data, 4)
|
||||
return cls(int.from_bytes(val_bytes, byteorder='big')), data
|
||||
def serialized_size(cls):
|
||||
return 4
|
||||
|
||||
@classmethod
|
||||
def _from_exact_bytes(cls, data):
|
||||
return cls(int.from_bytes(data, byteorder='big'))
|
||||
|
||||
def __bytes__(self):
|
||||
return self.val.to_bytes(4, byteorder='big')
|
||||
return self.val.to_bytes(self.serialized_size(), byteorder='big')
|
||||
|
||||
def __eq__(self, other):
|
||||
return isinstance(other, A) and self.val == other.val
|
||||
|
||||
|
||||
class B(Serializable):
|
||||
class B(Serializable, Deserializable):
|
||||
|
||||
def __init__(self, val: int):
|
||||
assert 0 <= val < 2**16
|
||||
self.val = val
|
||||
|
||||
@classmethod
|
||||
def __take__(cls, data):
|
||||
val_bytes, data = cls.__take_bytes__(data, 2)
|
||||
return cls(int.from_bytes(val_bytes, byteorder='big')), data
|
||||
def serialized_size(cls):
|
||||
return 2
|
||||
|
||||
@classmethod
|
||||
def _from_exact_bytes(cls, data):
|
||||
return cls(int.from_bytes(data, byteorder='big'))
|
||||
|
||||
def __bytes__(self):
|
||||
return self.val.to_bytes(2, byteorder='big')
|
||||
return self.val.to_bytes(self.serialized_size(), byteorder='big')
|
||||
|
||||
def __eq__(self, other):
|
||||
return isinstance(other, B) and self.val == other.val
|
||||
|
||||
|
||||
class C(Serializable):
|
||||
class C(Serializable, Deserializable):
|
||||
|
||||
def __init__(self, a: A, b: B):
|
||||
self.a = a
|
||||
self.b = b
|
||||
|
||||
@classmethod
|
||||
def __take__(cls, data):
|
||||
components, data = cls.__take_types__(data, A, B)
|
||||
return cls(*components), data
|
||||
def serialized_size(cls):
|
||||
return A.serialized_size() + B.serialized_size()
|
||||
|
||||
@classmethod
|
||||
def _from_exact_bytes(cls, data):
|
||||
components = cls._split(data, A, B)
|
||||
return cls(*components)
|
||||
|
||||
def __bytes__(self):
|
||||
return bytes(self.a) + bytes(self.b)
|
||||
|
@ -71,7 +81,7 @@ def test_too_many_bytes():
|
|||
a = A(2**32 - 123)
|
||||
b = B(2**16 - 456)
|
||||
c = C(a, b)
|
||||
with pytest.raises(ValueError, match="1 bytes remaining after deserializing"):
|
||||
with pytest.raises(ValueError, match="Expected 6 bytes, got 7"):
|
||||
C.from_bytes(bytes(c) + b'\x00')
|
||||
|
||||
|
||||
|
@ -80,13 +90,22 @@ def test_not_enough_bytes():
|
|||
b = B(2**16 - 456)
|
||||
c = C(a, b)
|
||||
# Will happen on deserialization of B - 1 byte missing
|
||||
with pytest.raises(ValueError, match="cannot take 2 bytes from a bytestring of size 1"):
|
||||
with pytest.raises(ValueError, match="Expected 6 bytes, got 5"):
|
||||
C.from_bytes(bytes(c)[:-1])
|
||||
|
||||
|
||||
def test_serialize_bool():
|
||||
assert take_bool(serialize_bool(True) + b'1234') == (True, b'1234')
|
||||
assert take_bool(serialize_bool(False) + b'12') == (False, b'12')
|
||||
def test_bool_bytes():
|
||||
assert bool_from_exact_bytes(bool_bytes(True)) == True
|
||||
assert bool_from_exact_bytes(bool_bytes(False)) == False
|
||||
error_msg = re.escape("Incorrectly serialized boolean; expected b'\\x00' or b'\\x01', got b'z'")
|
||||
with pytest.raises(ValueError, match=error_msg):
|
||||
take_bool(b'z1234')
|
||||
bool_from_exact_bytes(b'z')
|
||||
|
||||
|
||||
def test_split_bool():
|
||||
a = A(2**32 - 123)
|
||||
b = True
|
||||
data = bytes(a) + bool_bytes(b)
|
||||
a_back, b_back = Deserializable._split(data, A, bool)
|
||||
assert a_back == a
|
||||
assert b_back == b
|
||||
|
|
|
@ -147,14 +147,12 @@ def test_cfrags():
|
|||
CapsuleFrag.from_bytes(bytes.fromhex(json_kfrag['cfrag'])))
|
||||
for json_kfrag in vector_suite['vectors']]
|
||||
|
||||
metadata = bytes.fromhex(vector_suite['metadata'])
|
||||
|
||||
for kfrag, cfrag in kfrags_n_cfrags:
|
||||
verified_kfrag = kfrag.verify(verifying_pk=verifying_pk,
|
||||
delegating_pk=delegating_pk,
|
||||
receiving_pk=receiving_pk)
|
||||
|
||||
new_cfrag = reencrypt(capsule, verified_kfrag, metadata=metadata).cfrag
|
||||
new_cfrag = reencrypt(capsule, verified_kfrag).cfrag
|
||||
assert new_cfrag.point_e1 == cfrag.point_e1
|
||||
assert new_cfrag.point_v1 == cfrag.point_v1
|
||||
assert new_cfrag.kfrag_id == cfrag.kfrag_id
|
||||
|
@ -163,4 +161,4 @@ def test_cfrags():
|
|||
verifying_pk=verifying_pk,
|
||||
delegating_pk=delegating_pk,
|
||||
receiving_pk=receiving_pk,
|
||||
metadata=metadata)
|
||||
)
|
||||
|
|
|
@ -4,7 +4,7 @@ from .__about__ import (
|
|||
|
||||
from .capsule import Capsule
|
||||
from .capsule_frag import CapsuleFrag, VerifiedCapsuleFrag
|
||||
from .errors import GenericError, VerificationError
|
||||
from .errors import VerificationError
|
||||
from .key_frag import KeyFrag, VerifiedKeyFrag
|
||||
from .keys import SecretKey, PublicKey, SecretKeyFactory
|
||||
from .pre import encrypt, decrypt_original, decrypt_reencrypted, reencrypt, generate_kfrags
|
||||
|
@ -21,7 +21,6 @@ __all__ = [
|
|||
"VerifiedKeyFrag",
|
||||
"CapsuleFrag",
|
||||
"VerifiedCapsuleFrag",
|
||||
"GenericError",
|
||||
"VerificationError",
|
||||
"encrypt",
|
||||
"decrypt_original",
|
||||
|
|
|
@ -2,10 +2,9 @@ from typing import TYPE_CHECKING, Tuple, Sequence
|
|||
|
||||
from .curve_point import CurvePoint
|
||||
from .curve_scalar import CurveScalar
|
||||
from .errors import GenericError
|
||||
from .hashing import hash_capsule_points, hash_to_polynomial_arg, hash_to_shared_secret
|
||||
from .keys import PublicKey, SecretKey
|
||||
from .serializable import Serializable
|
||||
from .serializable import Serializable, Deserializable
|
||||
if TYPE_CHECKING: # pragma: no cover
|
||||
from .capsule_frag import CapsuleFrag
|
||||
|
||||
|
@ -19,7 +18,7 @@ def lambda_coeff(xs: Sequence[CurveScalar], i: int) -> CurveScalar:
|
|||
return res
|
||||
|
||||
|
||||
class Capsule(Serializable):
|
||||
class Capsule(Serializable, Deserializable):
|
||||
"""
|
||||
Encapsulated symmetric key.
|
||||
"""
|
||||
|
@ -29,21 +28,25 @@ class Capsule(Serializable):
|
|||
self.point_v = point_v
|
||||
self.signature = signature
|
||||
|
||||
_COMPONENT_TYPES = CurvePoint, CurvePoint, CurveScalar
|
||||
_SERIALIZED_SIZE = sum(tp.serialized_size() for tp in _COMPONENT_TYPES)
|
||||
|
||||
@classmethod
|
||||
def __take__(cls, data: bytes) -> Tuple['Capsule', bytes]:
|
||||
(e, v, sig), data = cls.__take_types__(data, CurvePoint, CurvePoint, CurveScalar)
|
||||
def serialized_size(cls):
|
||||
return cls._SERIALIZED_SIZE
|
||||
|
||||
capsule = cls(e, v, sig)
|
||||
@classmethod
|
||||
def _from_exact_bytes(cls, data: bytes):
|
||||
capsule = cls(*cls._split(data, *cls._COMPONENT_TYPES))
|
||||
if not capsule._verify():
|
||||
raise GenericError("Capsule self-verification failed. Serialized data may be damaged.")
|
||||
raise ValueError("Capsule self-verification failed. Serialized data may be damaged.")
|
||||
return capsule
|
||||
|
||||
return capsule, data
|
||||
|
||||
def __bytes__(self) -> bytes:
|
||||
def __bytes__(self):
|
||||
return bytes(self.point_e) + bytes(self.point_v) + bytes(self.signature)
|
||||
|
||||
@classmethod
|
||||
def from_public_key(cls, pk: PublicKey) -> Tuple['Capsule', CurvePoint]:
|
||||
def from_public_key(cls, delegating_pk: PublicKey) -> Tuple['Capsule', CurvePoint]:
|
||||
g = CurvePoint.generator()
|
||||
|
||||
priv_r = CurveScalar.random_nonzero()
|
||||
|
@ -55,12 +58,12 @@ class Capsule(Serializable):
|
|||
h = hash_capsule_points(pub_r, pub_u)
|
||||
s = priv_u + (priv_r * h)
|
||||
|
||||
shared_key = pk._point_key * (priv_r + priv_u)
|
||||
shared_key = delegating_pk._point_key * (priv_r + priv_u)
|
||||
|
||||
return cls(point_e=pub_r, point_v=pub_u, signature=s), shared_key
|
||||
|
||||
def open_original(self, sk: SecretKey) -> CurvePoint:
|
||||
return (self.point_e + self.point_v) * sk.secret_scalar()
|
||||
def open_original(self, delegating_sk: SecretKey) -> CurvePoint:
|
||||
return (self.point_e + self.point_v) * delegating_sk.secret_scalar()
|
||||
|
||||
def open_reencrypted(self,
|
||||
receiving_sk: SecretKey,
|
||||
|
@ -106,7 +109,7 @@ class Capsule(Serializable):
|
|||
# TODO: check for d == 0? Or just let if fail?
|
||||
inv_d = d.invert()
|
||||
if orig_pub_key * (s * inv_d) != (e_prime * h) + v_prime:
|
||||
raise GenericError("Internal validation failed")
|
||||
raise ValueError("Internal validation failed")
|
||||
|
||||
return (e_prime + v_prime) * d
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
from typing import Optional, Tuple
|
||||
from typing import Optional, Tuple, Type
|
||||
|
||||
from .capsule import Capsule
|
||||
from .curve_point import CurvePoint
|
||||
|
@ -8,11 +8,11 @@ from .hashing import hash_to_cfrag_verification, kfrag_signature_message
|
|||
from .keys import PublicKey
|
||||
from .key_frag import KeyFrag, KeyFragID
|
||||
from .params import PARAMETERS
|
||||
from .serializable import Serializable
|
||||
from .serializable import Serializable, Deserializable, HasSerializedSize
|
||||
from .signing import Signature
|
||||
|
||||
|
||||
class CapsuleFragProof(Serializable):
|
||||
class CapsuleFragProof(Serializable, Deserializable):
|
||||
|
||||
def __init__(self,
|
||||
point_e2: CurvePoint,
|
||||
|
@ -34,23 +34,23 @@ class CapsuleFragProof(Serializable):
|
|||
return (self.point_e2, self.point_v2, self.kfrag_commitment,
|
||||
self.kfrag_pok, self.signature, self.kfrag_signature)
|
||||
|
||||
_COMPONENT_TYPES: Tuple[Type[HasSerializedSize], ...] = (
|
||||
CurvePoint, CurvePoint, CurvePoint, CurvePoint, CurveScalar, Signature)
|
||||
_SERIALIZED_SIZE = sum(tp.serialized_size() for tp in _COMPONENT_TYPES)
|
||||
|
||||
def __eq__(self, other):
|
||||
return self._components() == other._components()
|
||||
|
||||
@classmethod
|
||||
def __take__(cls, data):
|
||||
types = [CurvePoint, CurvePoint, CurvePoint, CurvePoint, CurveScalar, Signature]
|
||||
components, data = cls.__take_types__(data, *types)
|
||||
return cls(*components), data
|
||||
def serialized_size(cls):
|
||||
return cls._SERIALIZED_SIZE
|
||||
|
||||
@classmethod
|
||||
def _from_exact_bytes(cls, data):
|
||||
return cls(*cls._split(data, *cls._COMPONENT_TYPES))
|
||||
|
||||
def __bytes__(self):
|
||||
return (bytes(self.point_e2) +
|
||||
bytes(self.point_v2) +
|
||||
bytes(self.kfrag_commitment) +
|
||||
bytes(self.kfrag_pok) +
|
||||
bytes(self.signature) +
|
||||
bytes(self.kfrag_signature)
|
||||
)
|
||||
return b''.join(bytes(comp) for comp in self._components())
|
||||
|
||||
@classmethod
|
||||
def from_kfrag_and_cfrag(cls,
|
||||
|
@ -58,7 +58,6 @@ class CapsuleFragProof(Serializable):
|
|||
kfrag: KeyFrag,
|
||||
cfrag_e1: CurvePoint,
|
||||
cfrag_v1: CurvePoint,
|
||||
metadata: Optional[bytes],
|
||||
) -> 'CapsuleFragProof':
|
||||
|
||||
params = PARAMETERS
|
||||
|
@ -81,7 +80,7 @@ class CapsuleFragProof(Serializable):
|
|||
v2 = v * t
|
||||
u2 = u * t
|
||||
|
||||
h = hash_to_cfrag_verification([e, e1, e2, v, v1, v2, u, u1, u2], metadata)
|
||||
h = hash_to_cfrag_verification([e, e1, e2, v, v1, v2, u, u1, u2])
|
||||
|
||||
###
|
||||
|
||||
|
@ -96,7 +95,7 @@ class CapsuleFragProof(Serializable):
|
|||
)
|
||||
|
||||
|
||||
class CapsuleFrag(Serializable):
|
||||
class CapsuleFrag(Serializable, Deserializable):
|
||||
"""
|
||||
Re-encrypted fragment of :py:class:`Capsule`.
|
||||
"""
|
||||
|
@ -118,6 +117,10 @@ class CapsuleFrag(Serializable):
|
|||
def _components(self):
|
||||
return (self.point_e1, self.point_v1, self.kfrag_id, self.precursor, self.proof)
|
||||
|
||||
_COMPONENT_TYPES: Tuple[Type[HasSerializedSize], ...] = (
|
||||
CurvePoint, CurvePoint, KeyFragID, CurvePoint, CapsuleFragProof)
|
||||
_SERIALIZED_SIZE = sum(tp.serialized_size() for tp in _COMPONENT_TYPES)
|
||||
|
||||
def __eq__(self, other):
|
||||
return self._components() == other._components()
|
||||
|
||||
|
@ -128,28 +131,22 @@ class CapsuleFrag(Serializable):
|
|||
return f"{self.__class__.__name__}:{bytes(self).hex()[:16]}"
|
||||
|
||||
@classmethod
|
||||
def __take__(cls, data):
|
||||
types = CurvePoint, CurvePoint, KeyFragID, CurvePoint, CapsuleFragProof
|
||||
components, data = cls.__take_types__(data, *types)
|
||||
return cls(*components), data
|
||||
|
||||
def __bytes__(self):
|
||||
return (bytes(self.point_e1) +
|
||||
bytes(self.point_v1) +
|
||||
bytes(self.kfrag_id) +
|
||||
bytes(self.precursor) +
|
||||
bytes(self.proof))
|
||||
def serialized_size(cls):
|
||||
return cls._SERIALIZED_SIZE
|
||||
|
||||
@classmethod
|
||||
def reencrypted(cls,
|
||||
capsule: Capsule,
|
||||
kfrag: KeyFrag,
|
||||
metadata: Optional[bytes] = None,
|
||||
) -> 'CapsuleFrag':
|
||||
def _from_exact_bytes(cls, data):
|
||||
return cls(*cls._split(data, *cls._COMPONENT_TYPES))
|
||||
|
||||
def __bytes__(self):
|
||||
return b''.join(bytes(comp) for comp in self._components())
|
||||
|
||||
@classmethod
|
||||
def reencrypted(cls, capsule: Capsule, kfrag: KeyFrag) -> 'CapsuleFrag':
|
||||
rk = kfrag.key
|
||||
e1 = capsule.point_e * rk
|
||||
v1 = capsule.point_v * rk
|
||||
proof = CapsuleFragProof.from_kfrag_and_cfrag(capsule, kfrag, e1, v1, metadata)
|
||||
proof = CapsuleFragProof.from_kfrag_and_cfrag(capsule, kfrag, e1, v1)
|
||||
|
||||
return cls(point_e1=e1,
|
||||
point_v1=v1,
|
||||
|
@ -163,12 +160,9 @@ class CapsuleFrag(Serializable):
|
|||
verifying_pk: PublicKey,
|
||||
delegating_pk: PublicKey,
|
||||
receiving_pk: PublicKey,
|
||||
metadata: Optional[bytes] = None,
|
||||
) -> 'VerifiedCapsuleFrag':
|
||||
"""
|
||||
Verifies the validity of this fragment.
|
||||
|
||||
``metadata`` should coincide with the one given to :py:func:`reencrypt`.
|
||||
"""
|
||||
|
||||
params = PARAMETERS
|
||||
|
@ -189,7 +183,7 @@ class CapsuleFrag(Serializable):
|
|||
v2 = self.proof.point_v2
|
||||
u2 = self.proof.kfrag_pok
|
||||
|
||||
h = hash_to_cfrag_verification([e, e1, e2, v, v1, v2, u, u1, u2], metadata)
|
||||
h = hash_to_cfrag_verification([e, e1, e2, v, v1, v2, u, u1, u2])
|
||||
|
||||
###
|
||||
|
||||
|
@ -221,7 +215,7 @@ class CapsuleFrag(Serializable):
|
|||
return VerifiedCapsuleFrag(self)
|
||||
|
||||
|
||||
class VerifiedCapsuleFrag:
|
||||
class VerifiedCapsuleFrag(Serializable):
|
||||
"""
|
||||
Verified capsule frag, good for decryption.
|
||||
Can be cast to ``bytes``, but cannot be deserialized from bytes directly.
|
||||
|
@ -234,6 +228,10 @@ class VerifiedCapsuleFrag:
|
|||
def __bytes__(self):
|
||||
return bytes(self.cfrag)
|
||||
|
||||
@classmethod
|
||||
def serialized_size(cls):
|
||||
return CapsuleFrag.serialized_size()
|
||||
|
||||
def __eq__(self, other):
|
||||
return self.cfrag == other.cfrag
|
||||
|
||||
|
|
|
@ -3,10 +3,10 @@ from typing import Tuple
|
|||
from . import openssl
|
||||
from .curve import CURVE
|
||||
from .curve_scalar import CurveScalar
|
||||
from .serializable import Serializable
|
||||
from .serializable import Serializable, Deserializable
|
||||
|
||||
|
||||
class CurvePoint(Serializable):
|
||||
class CurvePoint(Serializable, Deserializable):
|
||||
"""
|
||||
Represents an OpenSSL EC_POINT except more Pythonic.
|
||||
"""
|
||||
|
@ -34,14 +34,15 @@ class CurvePoint(Serializable):
|
|||
return openssl.point_to_affine_coords(CURVE, self._backend_point)
|
||||
|
||||
@classmethod
|
||||
def __take__(cls, data: bytes) -> Tuple['CurvePoint', bytes]:
|
||||
def serialized_size(cls):
|
||||
return CURVE.field_element_size + 1 # compressed point size
|
||||
|
||||
@classmethod
|
||||
def _from_exact_bytes(cls, data: bytes):
|
||||
"""
|
||||
Returns a CurvePoint object from the given byte data on the curve provided.
|
||||
"""
|
||||
size = CURVE.field_element_size + 1 # compressed point size
|
||||
point_data, data = cls.__take_bytes__(data, size)
|
||||
point = openssl.point_from_bytes(CURVE, point_data)
|
||||
return cls(point), data
|
||||
return cls(openssl.point_from_bytes(CURVE, data))
|
||||
|
||||
def __bytes__(self) -> bytes:
|
||||
"""
|
||||
|
|
|
@ -2,12 +2,12 @@ from typing import TYPE_CHECKING, Union, Tuple
|
|||
|
||||
from . import openssl
|
||||
from .curve import CURVE
|
||||
from .serializable import Serializable
|
||||
from .serializable import Serializable, Deserializable
|
||||
if TYPE_CHECKING: # pragma: no cover
|
||||
from .hashing import Hash
|
||||
|
||||
|
||||
class CurveScalar(Serializable):
|
||||
class CurveScalar(Serializable, Deserializable):
|
||||
"""
|
||||
Represents an OpenSSL Bignum modulo the order of a curve. Some of these
|
||||
operations will only work with prime numbers.
|
||||
|
@ -45,10 +45,12 @@ class CurveScalar(Serializable):
|
|||
return cls(openssl.bn_from_bytes(digest.finalize(), apply_modulus=CURVE.bn_order))
|
||||
|
||||
@classmethod
|
||||
def __take__(cls, data: bytes) -> Tuple['CurveScalar', bytes]:
|
||||
scalar_data, data = cls.__take_bytes__(data, CURVE.scalar_size)
|
||||
bignum = openssl.bn_from_bytes(scalar_data, check_modulus=CURVE.bn_order)
|
||||
return cls(bignum), data
|
||||
def serialized_size(cls):
|
||||
return CURVE.scalar_size
|
||||
|
||||
@classmethod
|
||||
def _from_exact_bytes(cls, data: bytes):
|
||||
return cls(openssl.bn_from_bytes(data, check_modulus=CURVE.bn_order))
|
||||
|
||||
def __bytes__(self) -> bytes:
|
||||
"""
|
||||
|
|
|
@ -14,7 +14,6 @@ from nacl.bindings.crypto_aead import (
|
|||
)
|
||||
|
||||
from . import openssl
|
||||
from .errors import GenericError
|
||||
|
||||
|
||||
def kdf(data: bytes,
|
||||
|
@ -64,6 +63,6 @@ class DEM:
|
|||
try:
|
||||
return xchacha_decrypt(ciphertext, authenticated_data, nonce, self._key)
|
||||
except nacl.exceptions.CryptoError as e:
|
||||
raise GenericError("Decryption of ciphertext failed: "
|
||||
raise ValueError("Decryption of ciphertext failed: "
|
||||
"either someone tampered with the ciphertext or "
|
||||
"you are using an incorrect decryption key.") from e
|
||||
|
|
|
@ -1,10 +1,4 @@
|
|||
class GenericError(Exception):
|
||||
"""
|
||||
An interal Umbral error, see the message for details.
|
||||
"""
|
||||
|
||||
|
||||
class VerificationError(GenericError):
|
||||
class VerificationError(Exception):
|
||||
"""
|
||||
Integrity of the data cannot be verified, see the message for details.
|
||||
"""
|
||||
|
|
|
@ -6,7 +6,7 @@ from .openssl import backend, ErrorInvalidCompressedPoint
|
|||
from .curve import CURVE
|
||||
from .curve_scalar import CurveScalar
|
||||
from .curve_point import CurvePoint
|
||||
from .serializable import Serializable, serialize_bool
|
||||
from .serializable import Serializable, bool_bytes
|
||||
|
||||
if TYPE_CHECKING: # pragma: no cover
|
||||
from .key_frag import KeyFragID
|
||||
|
@ -63,14 +63,10 @@ def hash_to_shared_secret(precursor: CurvePoint,
|
|||
return CurveScalar.from_digest(digest)
|
||||
|
||||
|
||||
def hash_to_cfrag_verification(points: Iterable[CurvePoint],
|
||||
metadata: Optional[bytes] = None
|
||||
) -> CurveScalar:
|
||||
def hash_to_cfrag_verification(points: Iterable[CurvePoint]) -> CurveScalar:
|
||||
digest = Hash(b"CFRAG_VERIFICATION")
|
||||
for point in points:
|
||||
digest.update(point)
|
||||
if metadata is not None:
|
||||
digest.update(metadata)
|
||||
return CurveScalar.from_digest(digest)
|
||||
|
||||
|
||||
|
@ -83,14 +79,14 @@ def kfrag_signature_message(kfrag_id: 'KeyFragID',
|
|||
|
||||
# Have to convert to bytes manually because `mypy` is not smart enough to resolve types.
|
||||
|
||||
delegating_part = ([serialize_bool(True), bytes(maybe_delegating_pk)]
|
||||
delegating_part = ([bool_bytes(True), bytes(maybe_delegating_pk)]
|
||||
if maybe_delegating_pk
|
||||
else [serialize_bool(False)])
|
||||
else [bool_bytes(False)])
|
||||
cast(List[Serializable], delegating_part)
|
||||
|
||||
receiving_part = ([serialize_bool(True), bytes(maybe_receiving_pk)]
|
||||
receiving_part = ([bool_bytes(True), bytes(maybe_receiving_pk)]
|
||||
if maybe_receiving_pk
|
||||
else [serialize_bool(False)])
|
||||
else [bool_bytes(False)])
|
||||
|
||||
components = ([bytes(kfrag_id), bytes(commitment), bytes(precursor)] +
|
||||
delegating_part +
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import os
|
||||
from typing import List, Optional
|
||||
from typing import List, Optional, Tuple, Type
|
||||
|
||||
from .curve_point import CurvePoint
|
||||
from .curve_scalar import CurveScalar
|
||||
|
@ -7,11 +7,13 @@ from .errors import VerificationError
|
|||
from .hashing import hash_to_shared_secret, kfrag_signature_message, hash_to_polynomial_arg
|
||||
from .keys import PublicKey, SecretKey
|
||||
from .params import PARAMETERS
|
||||
from .serializable import Serializable, serialize_bool, take_bool
|
||||
from .serializable import (
|
||||
Serializable, Deserializable, HasSerializedSize,
|
||||
bool_bytes, bool_serialized_size)
|
||||
from .signing import Signature, Signer
|
||||
|
||||
|
||||
class KeyFragID(Serializable):
|
||||
class KeyFragID(Serializable, Deserializable):
|
||||
|
||||
__SIZE = 32
|
||||
|
||||
|
@ -26,15 +28,18 @@ class KeyFragID(Serializable):
|
|||
return cls(os.urandom(cls.__SIZE))
|
||||
|
||||
@classmethod
|
||||
def __take__(cls, data):
|
||||
id_, data = cls.__take_bytes__(data, cls.__SIZE)
|
||||
return cls(id_), data
|
||||
def serialized_size(cls):
|
||||
return cls.__SIZE
|
||||
|
||||
@classmethod
|
||||
def _from_exact_bytes(cls, data):
|
||||
return cls(data)
|
||||
|
||||
def __bytes__(self):
|
||||
return self._id
|
||||
|
||||
|
||||
class KeyFragProof(Serializable):
|
||||
class KeyFragProof(Serializable, Deserializable):
|
||||
|
||||
@classmethod
|
||||
def from_base(cls,
|
||||
|
@ -102,22 +107,25 @@ class KeyFragProof(Serializable):
|
|||
def __eq__(self, other):
|
||||
return self._components() == other._components()
|
||||
|
||||
@classmethod
|
||||
def __take__(cls, data):
|
||||
types = [CurvePoint, Signature, Signature]
|
||||
(commitment, sig_proxy, sig_bob), data = cls.__take_types__(data, *types)
|
||||
delegating_key_signed, data = take_bool(data)
|
||||
receiving_key_signed, data = take_bool(data)
|
||||
_SERIALIZED_SIZE = (CurvePoint.serialized_size() +
|
||||
Signature.serialized_size() * 2 +
|
||||
bool_serialized_size() * 2)
|
||||
|
||||
obj = cls(commitment, sig_proxy, sig_bob, delegating_key_signed, receiving_key_signed)
|
||||
return obj, data
|
||||
@classmethod
|
||||
def serialized_size(cls):
|
||||
return cls._SERIALIZED_SIZE
|
||||
|
||||
@classmethod
|
||||
def _from_exact_bytes(cls, data):
|
||||
types = [CurvePoint, Signature, Signature, bool, bool]
|
||||
return cls(*cls._split(data, *types))
|
||||
|
||||
def __bytes__(self):
|
||||
return (bytes(self.commitment) +
|
||||
bytes(self.signature_for_proxy) +
|
||||
bytes(self.signature_for_receiver) +
|
||||
serialize_bool(self.delegating_key_signed) +
|
||||
serialize_bool(self.receiving_key_signed)
|
||||
bool_bytes(self.delegating_key_signed) +
|
||||
bool_bytes(self.receiving_key_signed)
|
||||
)
|
||||
|
||||
|
||||
|
@ -129,7 +137,7 @@ def poly_eval(coeffs: List[CurveScalar], x: CurveScalar) -> CurveScalar:
|
|||
return result
|
||||
|
||||
|
||||
class KeyFrag(Serializable):
|
||||
class KeyFrag(Serializable, Deserializable):
|
||||
"""
|
||||
A signed fragment of the delegating key.
|
||||
"""
|
||||
|
@ -144,18 +152,24 @@ class KeyFrag(Serializable):
|
|||
self.precursor = precursor
|
||||
self.proof = proof
|
||||
|
||||
@classmethod
|
||||
def __take__(cls, data):
|
||||
types = [KeyFragID, CurveScalar, CurvePoint, KeyFragProof]
|
||||
components, data = cls.__take_types__(data, *types)
|
||||
return cls(*components), data
|
||||
|
||||
def __bytes__(self):
|
||||
return bytes(self.id) + bytes(self.key) + bytes(self.precursor) + bytes(self.proof)
|
||||
|
||||
def _components(self):
|
||||
return self.id, self.key, self.precursor, self.proof
|
||||
|
||||
_COMPONENT_TYPES: Tuple[Type[HasSerializedSize], ...] = (
|
||||
KeyFragID, CurveScalar, CurvePoint, KeyFragProof)
|
||||
_SERIALIZED_SIZE = sum(tp.serialized_size() for tp in _COMPONENT_TYPES)
|
||||
|
||||
@classmethod
|
||||
def serialized_size(cls):
|
||||
return cls._SERIALIZED_SIZE
|
||||
|
||||
@classmethod
|
||||
def _from_exact_bytes(cls, data):
|
||||
return cls(*cls._split(data, *cls._COMPONENT_TYPES))
|
||||
|
||||
def __bytes__(self):
|
||||
return b''.join(bytes(comp) for comp in self._components())
|
||||
|
||||
def __eq__(self, other):
|
||||
return self._components() == other._components()
|
||||
|
||||
|
@ -240,7 +254,7 @@ class KeyFrag(Serializable):
|
|||
return VerifiedKeyFrag(self)
|
||||
|
||||
|
||||
class VerifiedKeyFrag:
|
||||
class VerifiedKeyFrag(Serializable):
|
||||
"""
|
||||
Verified kfrag, good for reencryption.
|
||||
Can be cast to ``bytes``, but cannot be deserialized from bytes directly.
|
||||
|
@ -253,6 +267,22 @@ class VerifiedKeyFrag:
|
|||
def __bytes__(self):
|
||||
return bytes(self.kfrag)
|
||||
|
||||
@classmethod
|
||||
def serialized_size(cls):
|
||||
return KeyFrag.serialized_size()
|
||||
|
||||
@classmethod
|
||||
def from_verified_bytes(cls, data) -> 'VerifiedKeyFrag':
|
||||
"""
|
||||
Restores a verified keyfrag directly from serialized bytes,
|
||||
skipping :py:meth:`KeyFrag.verify` call.
|
||||
|
||||
Intended for internal storage;
|
||||
make sure that the bytes come from a trusted source.
|
||||
"""
|
||||
kfrag = KeyFrag.from_bytes(data)
|
||||
return cls(kfrag)
|
||||
|
||||
def __eq__(self, other):
|
||||
return self.kfrag == other.kfrag
|
||||
|
||||
|
|
|
@ -5,10 +5,10 @@ from .curve_scalar import CurveScalar
|
|||
from .curve_point import CurvePoint
|
||||
from .dem import kdf
|
||||
from .hashing import Hash
|
||||
from .serializable import Serializable
|
||||
from .serializable import Serializable, Deserializable
|
||||
|
||||
|
||||
class SecretKey(Serializable):
|
||||
class SecretKey(Serializable, Deserializable):
|
||||
"""
|
||||
Umbral secret (private) key.
|
||||
"""
|
||||
|
@ -43,15 +43,18 @@ class SecretKey(Serializable):
|
|||
return self._scalar_key
|
||||
|
||||
@classmethod
|
||||
def __take__(cls, data: bytes) -> Tuple['SecretKey', bytes]:
|
||||
(scalar_key,), data = cls.__take_types__(data, CurveScalar)
|
||||
return cls(scalar_key), data
|
||||
def serialized_size(cls):
|
||||
return CurveScalar.serialized_size()
|
||||
|
||||
@classmethod
|
||||
def _from_exact_bytes(cls, data: bytes):
|
||||
return cls(CurveScalar._from_exact_bytes(data))
|
||||
|
||||
def __bytes__(self) -> bytes:
|
||||
return bytes(self._scalar_key)
|
||||
|
||||
|
||||
class PublicKey(Serializable):
|
||||
class PublicKey(Serializable, Deserializable):
|
||||
"""
|
||||
Umbral public key.
|
||||
"""
|
||||
|
@ -70,9 +73,12 @@ class PublicKey(Serializable):
|
|||
return cls(sk._public_key_point)
|
||||
|
||||
@classmethod
|
||||
def __take__(cls, data: bytes) -> Tuple['PublicKey', bytes]:
|
||||
(point_key,), data = cls.__take_types__(data, CurvePoint)
|
||||
return cls(point_key), data
|
||||
def serialized_size(cls):
|
||||
return CurvePoint.serialized_size()
|
||||
|
||||
@classmethod
|
||||
def _from_exact_bytes(cls, data: bytes):
|
||||
return cls(CurvePoint._from_exact_bytes(data))
|
||||
|
||||
def __bytes__(self) -> bytes:
|
||||
return bytes(self._point_key)
|
||||
|
@ -87,7 +93,7 @@ class PublicKey(Serializable):
|
|||
return hash((self.__class__, bytes(self)))
|
||||
|
||||
|
||||
class SecretKeyFactory(Serializable):
|
||||
class SecretKeyFactory(Serializable, Deserializable):
|
||||
"""
|
||||
This class handles keyring material for Umbral, by allowing deterministic
|
||||
derivation of :py:class:`SecretKey` objects based on labels.
|
||||
|
@ -122,9 +128,12 @@ class SecretKeyFactory(Serializable):
|
|||
return SecretKey(scalar_key)
|
||||
|
||||
@classmethod
|
||||
def __take__(cls, data: bytes) -> Tuple['SecretKeyFactory', bytes]:
|
||||
key_seed, data = cls.__take_bytes__(data, cls._KEY_SEED_SIZE)
|
||||
return cls(key_seed), data
|
||||
def serialized_size(cls):
|
||||
return cls._KEY_SEED_SIZE
|
||||
|
||||
@classmethod
|
||||
def _from_exact_bytes(cls, data: bytes):
|
||||
return cls(data)
|
||||
|
||||
def __bytes__(self) -> bytes:
|
||||
return bytes(self.__key_seed)
|
||||
|
|
|
@ -8,25 +8,25 @@ from .key_frag import VerifiedKeyFrag, KeyFrag, KeyFragBase
|
|||
from .signing import Signer
|
||||
|
||||
|
||||
def encrypt(pk: PublicKey, plaintext: bytes) -> Tuple[Capsule, bytes]:
|
||||
def encrypt(delegating_pk: PublicKey, plaintext: bytes) -> Tuple[Capsule, bytes]:
|
||||
"""
|
||||
Generates and encapsulates a symmetric key and uses it to encrypt the given plaintext.
|
||||
|
||||
Returns the KEM Capsule and the ciphertext.
|
||||
"""
|
||||
capsule, key_seed = Capsule.from_public_key(pk)
|
||||
capsule, key_seed = Capsule.from_public_key(delegating_pk)
|
||||
dem = DEM(bytes(key_seed))
|
||||
ciphertext = dem.encrypt(plaintext, authenticated_data=bytes(capsule))
|
||||
return capsule, ciphertext
|
||||
|
||||
|
||||
def decrypt_original(sk: SecretKey, capsule: Capsule, ciphertext: bytes) -> bytes:
|
||||
def decrypt_original(delegating_sk: SecretKey, capsule: Capsule, ciphertext: bytes) -> bytes:
|
||||
"""
|
||||
Opens the capsule using the original (Alice's) key used for encryption and gets what's inside.
|
||||
Opens the capsule using the delegator's key used for encryption and gets what's inside.
|
||||
We hope that's a symmetric key, which we use to decrypt the ciphertext
|
||||
and return the resulting cleartext.
|
||||
"""
|
||||
key_seed = capsule.open_original(sk)
|
||||
key_seed = capsule.open_original(delegating_sk)
|
||||
dem = DEM(bytes(key_seed))
|
||||
return dem.decrypt(ciphertext, authenticated_data=bytes(capsule))
|
||||
|
||||
|
@ -60,26 +60,20 @@ def generate_kfrags(delegating_sk: SecretKey,
|
|||
return [VerifiedKeyFrag(kfrag) for kfrag in kfrags]
|
||||
|
||||
|
||||
def reencrypt(capsule: Capsule,
|
||||
kfrag: VerifiedKeyFrag,
|
||||
metadata: Optional[bytes] = None
|
||||
) -> VerifiedCapsuleFrag:
|
||||
def reencrypt(capsule: Capsule, kfrag: VerifiedKeyFrag) -> VerifiedCapsuleFrag:
|
||||
"""
|
||||
Creates a capsule fragment using the given key fragment.
|
||||
Capsule fragments can later be used to decrypt the ciphertext.
|
||||
|
||||
If `metadata` is provided, it will have to be used for verification in
|
||||
:py:meth:`CapsuleFrag.verify`.
|
||||
"""
|
||||
# We could let duck typing do its work,
|
||||
# but it's better to make a common error more understandable.
|
||||
if isinstance(kfrag, KeyFrag) and not isinstance(kfrag, VerifiedKeyFrag):
|
||||
raise TypeError("KeyFrag must be verified before reencryption")
|
||||
|
||||
return VerifiedCapsuleFrag(CapsuleFrag.reencrypted(capsule, kfrag.kfrag, metadata))
|
||||
return VerifiedCapsuleFrag(CapsuleFrag.reencrypted(capsule, kfrag.kfrag))
|
||||
|
||||
|
||||
def decrypt_reencrypted(decrypting_sk: SecretKey,
|
||||
def decrypt_reencrypted(receiving_sk: SecretKey,
|
||||
delegating_pk: PublicKey,
|
||||
capsule: Capsule,
|
||||
verified_cfrags: Sequence[VerifiedCapsuleFrag],
|
||||
|
@ -95,6 +89,6 @@ def decrypt_reencrypted(decrypting_sk: SecretKey,
|
|||
raise TypeError("All CapsuleFrags must be verified before decryption")
|
||||
|
||||
cfrags = [vcfrag.cfrag for vcfrag in verified_cfrags]
|
||||
key_seed = capsule.open_reencrypted(decrypting_sk, delegating_pk, cfrags)
|
||||
key_seed = capsule.open_reencrypted(receiving_sk, delegating_pk, cfrags)
|
||||
dem = DEM(bytes(key_seed))
|
||||
return dem.decrypt(ciphertext, authenticated_data=bytes(capsule))
|
||||
|
|
|
@ -2,56 +2,81 @@ from abc import abstractmethod, ABC
|
|||
from typing import Tuple, Type, List, Any, TypeVar
|
||||
|
||||
|
||||
class Serializable(ABC):
|
||||
class HasSerializedSize(ABC):
|
||||
"""
|
||||
A mixin for composable serialization.
|
||||
A base serialization mixin, denoting a type with a constant-size serialized representation.
|
||||
"""
|
||||
|
||||
_T = TypeVar('_T', bound='Serializable')
|
||||
@classmethod
|
||||
@abstractmethod
|
||||
def serialized_size(cls) -> int:
|
||||
"""
|
||||
Returns the size in bytes of the serialized representation of this object
|
||||
(obtained with ``bytes()``).
|
||||
"""
|
||||
raise NotImplementedError
|
||||
|
||||
|
||||
class Deserializable(HasSerializedSize):
|
||||
"""
|
||||
A mixin for composable deserialization.
|
||||
"""
|
||||
|
||||
_T = TypeVar('_T', bound='Deserializable')
|
||||
|
||||
@classmethod
|
||||
def from_bytes(cls: Type[_T], data: bytes) -> _T:
|
||||
"""
|
||||
Restores the object from serialized bytes.
|
||||
"""
|
||||
obj, remainder = cls.__take__(data)
|
||||
if len(remainder) != 0:
|
||||
raise ValueError(f"{len(remainder)} bytes remaining after deserializing {cls}")
|
||||
return obj
|
||||
expected_size = cls.serialized_size()
|
||||
if len(data) != expected_size:
|
||||
raise ValueError(f"Expected {expected_size} bytes, got {len(data)}")
|
||||
return cls._from_exact_bytes(data)
|
||||
|
||||
@classmethod
|
||||
def __take_bytes__(cls, data: bytes, size: int) -> Tuple[bytes, bytes]:
|
||||
@staticmethod
|
||||
def _split(data: bytes, *types: Type) -> List[Any]:
|
||||
"""
|
||||
Takes ``size`` bytes from the bytestring and returns them along with the remainder.
|
||||
"""
|
||||
if len(data) < size:
|
||||
raise ValueError(f"{cls} cannot take {size} bytes "
|
||||
f"from a bytestring of size {len(data)}")
|
||||
return data[:size], data[size:]
|
||||
|
||||
@classmethod
|
||||
def __take_types__(cls, data: bytes, *types: Type) -> Tuple[List[Any], bytes]:
|
||||
"""
|
||||
Given a list of ``Serializable`` types, attempts to deserialize them from the bytestring
|
||||
Given a list of ``Deserializable`` types, attempts to deserialize them from the bytestring
|
||||
one by one and returns the list of the resulting objects and the remaining bytestring.
|
||||
"""
|
||||
objs = []
|
||||
pos = 0
|
||||
|
||||
for tp in types:
|
||||
obj, data = tp.__take__(data)
|
||||
|
||||
if issubclass(tp, bool):
|
||||
size = bool_serialized_size()
|
||||
else:
|
||||
size = tp.serialized_size()
|
||||
|
||||
chunk = data[pos:pos+size]
|
||||
|
||||
if issubclass(tp, bool):
|
||||
obj = bool_from_exact_bytes(chunk)
|
||||
else:
|
||||
obj = tp._from_exact_bytes(chunk)
|
||||
|
||||
objs.append(obj)
|
||||
return objs, data
|
||||
pos += size
|
||||
|
||||
return objs
|
||||
|
||||
@classmethod
|
||||
@abstractmethod
|
||||
def __take__(cls: Type[_T], data: bytes) -> Tuple[_T, bytes]:
|
||||
def _from_exact_bytes(cls: Type[_T], data: bytes) -> _T:
|
||||
"""
|
||||
Take however much is necessary from ``data`` and instantiate the object,
|
||||
returning it and the remaining bytestring.
|
||||
|
||||
Must be implemented by the derived class.
|
||||
Deserializes the object from a bytestring of exactly the expected length
|
||||
(defined by ``serialized_size()``).
|
||||
"""
|
||||
raise NotImplementedError
|
||||
|
||||
|
||||
class Serializable(HasSerializedSize):
|
||||
"""
|
||||
A mixin for composable serialization.
|
||||
"""
|
||||
|
||||
@abstractmethod
|
||||
def __bytes__(self):
|
||||
"""
|
||||
|
@ -60,17 +85,20 @@ class Serializable(ABC):
|
|||
raise NotImplementedError
|
||||
|
||||
|
||||
def serialize_bool(b: bool) -> bytes:
|
||||
def bool_serialized_size() -> int:
|
||||
return 1
|
||||
|
||||
|
||||
def bool_bytes(b: bool) -> bytes:
|
||||
return b'\x01' if b else b'\x00'
|
||||
|
||||
|
||||
def take_bool(data: bytes) -> Tuple[bool, bytes]:
|
||||
bool_bytes, data = Serializable.__take_bytes__(data, 1)
|
||||
if bool_bytes == b'\x01':
|
||||
def bool_from_exact_bytes(data: bytes) -> bool:
|
||||
if data == b'\x01':
|
||||
b = True
|
||||
elif bool_bytes == b'\x00':
|
||||
elif data == b'\x00':
|
||||
b = False
|
||||
else:
|
||||
raise ValueError("Incorrectly serialized boolean; "
|
||||
f"expected b'\\x00' or b'\\x01', got {repr(bool_bytes)}")
|
||||
return b, data
|
||||
f"expected b'\\x00' or b'\\x01', got {repr(data)}")
|
||||
return b
|
||||
|
|
|
@ -3,7 +3,7 @@ from .curve import CURVE
|
|||
from .curve_scalar import CurveScalar
|
||||
from .hashing import Hash
|
||||
from .keys import SecretKey, PublicKey
|
||||
from .serializable import Serializable
|
||||
from .serializable import Serializable, Deserializable
|
||||
|
||||
|
||||
def digest_for_signing(message: bytes) -> Hash:
|
||||
|
@ -66,7 +66,7 @@ class Signer:
|
|||
raise RuntimeError(f"{self.__class__.__name__} objects do not support serialization")
|
||||
|
||||
|
||||
class Signature(Serializable):
|
||||
class Signature(Serializable, Deserializable):
|
||||
"""
|
||||
Wrapper for ECDSA signatures.
|
||||
"""
|
||||
|
@ -92,9 +92,12 @@ class Signature(Serializable):
|
|||
return self.verify_digest(verifying_key, digest)
|
||||
|
||||
@classmethod
|
||||
def __take__(cls, data):
|
||||
(r, s), data = cls.__take_types__(data, CurveScalar, CurveScalar)
|
||||
return cls(r, s), data
|
||||
def serialized_size(cls):
|
||||
return CurveScalar.serialized_size() * 2
|
||||
|
||||
@classmethod
|
||||
def _from_exact_bytes(cls, data: bytes):
|
||||
return cls(*cls._split(data, CurveScalar, CurveScalar))
|
||||
|
||||
def __bytes__(self):
|
||||
return bytes(self.r) + bytes(self.s)
|
||||
|
|
|
@ -237,9 +237,8 @@ create_test_vector_file(vector_suite, 'vectors_kfrags.json', generate_again=gene
|
|||
|
||||
vectors = list()
|
||||
|
||||
metadata = b'kfrag_metadata'
|
||||
for kfrag in kfrags:
|
||||
cfrag = reencrypt(capsule, kfrag, metadata)
|
||||
cfrag = reencrypt(capsule, kfrag)
|
||||
json_input = {'kfrag': hexlify(kfrag), 'cfrag': hexlify(cfrag)}
|
||||
vectors.append(json_input)
|
||||
|
||||
|
@ -249,10 +248,9 @@ vector_suite = {
|
|||
'enclosed Capsule, under the enclosed delegating, '
|
||||
'verifying and receiving keys. Each CFrag must deserialize '
|
||||
'correctly and can be replicated with a call to '
|
||||
'`reencrypt(kfrag, capsule, , b\'kfrag_metadata\')`'),
|
||||
'`reencrypt(kfrag, capsule)`'),
|
||||
'params': 'default',
|
||||
'capsule': hexlify(capsule),
|
||||
'metadata': hexlify(metadata),
|
||||
'verifying_pk': hexlify(verifying_pk),
|
||||
'delegating_pk': hexlify(delegating_pk),
|
||||
'receiving_pk': hexlify(receiving_pk),
|
||||
|
|
|
@ -1,9 +1,8 @@
|
|||
{
|
||||
"name": "Test vectors for CFrags",
|
||||
"description": "This is a collection of CFrags, originated from the enclosed Capsule, under the enclosed delegating, verifying and receiving keys. Each CFrag must deserialize correctly and can be replicated with a call to `reencrypt(kfrag, capsule, , b'kfrag_metadata')`",
|
||||
"description": "This is a collection of CFrags, originated from the enclosed Capsule, under the enclosed delegating, verifying and receiving keys. Each CFrag must deserialize correctly and can be replicated with a call to `reencrypt(kfrag, capsule)`",
|
||||
"params": "default",
|
||||
"capsule": "02558f1de19a58e73a94e8fbbc6d3b1de2d312d90746ea74cb29f046943bf5787102906780e9484aec2102a01a157f10ced5aec952cd00631d94d5ea2edfa9b6808361b109353b0827b7e4013ab92a70eb3337a37f6fe34b3ccb058592caa246c974",
|
||||
"metadata": "6b667261675f6d65746164617461",
|
||||
"verifying_pk": "030b95b3f249297824b32d3391392d62a9aff32e8698fa78c7e8ce4a9d17071f56",
|
||||
"delegating_pk": "02d67029bb92522059225d190038230c23466e28d132d48f714f9098168a562b8a",
|
||||
"receiving_pk": "03b0d0243e8954b408047eee3b09b5ed132ccc25ec70e99fc74b6e9f54e5ecf9c7",
|
||||
|
|
Loading…
Reference in New Issue