add gamma signatures

This commit is contained in:
Geoffroy Couprie 2019-09-03 15:29:10 +02:00
parent 5f55b60a0e
commit d2b18c900f
6 changed files with 905 additions and 1 deletions

View File

@ -175,6 +175,40 @@ It has som slight differences in behaviour with the other methods, though:
- generating a verif token requires access to the token (ie no HttpOnly cookies)
- once a challenge token is generated, it cannot be attenuated again (might be a good thing or bad thing depending on the context)
### Aggregated gamma signatures
implementation of the scheme from https://eprint.iacr.org/2018/414.pdf
#### Performance
Performance is on par with the VRF solution (it can be further optimized):
```
test bench::sign_first_block ... bench: 104,957 ns/iter (+/- 14,308)
test bench::sign_second_block ... bench: 106,246 ns/iter (+/- 17,039)
test bench::sign_third_block ... bench: 106,122 ns/iter (+/- 10,631)
test bench::verify_one_block ... bench: 280,323 ns/iter (+/- 48,385)
test bench::verify_two_blocks ... bench: 466,553 ns/iter (+/- 136,446)
test bench::verify_three_blocks ... bench: 644,827 ns/iter (+/- 108,173)
```
#### Signature overhead
a Ristretto point can be stored in 32 bytes, a Scalar can be stored in 32 bytes
we will store 2 points (public key and "A" parameter) per block,
and one scalar in the signature
So, for the first method:
- 1 block: 1 * 64 + 32 = 96 bytes
- 2 blocks: 2 * 64 + 32 = 160 bytes
- 5 blocks: 5 * 64 + 32 = 352 bytes
- 10 blocks: 10 * 64 + 32 = 672 bytes
- 20 blocks: 20 * 64 + 32 = 1312 bytes
## Benchmarks summary
### Signing
@ -185,6 +219,7 @@ It has som slight differences in behaviour with the other methods, though:
| VRF 1 | 254 μs | 690 μs | 844 μs |
| VRF 2 | 325 μs | 678 μs | 866 μs |
| challenge | 325 μs | 402 μs | 405 μs |
| gamma | 104 μs | 106 μs | 106 μs |
### Verifying
@ -194,6 +229,7 @@ It has som slight differences in behaviour with the other methods, though:
| VRF 1 | 322 μs | 548 μs | 748 μs |
| VRF 2 | 264 μs | 322 μs | 418 μs |
| challenge | 308 μs | 472 μs | 624 μs |
| gamma | 280 μs | 466 μs | 644 μs |
### Size overhead
@ -205,4 +241,5 @@ It has som slight differences in behaviour with the other methods, though:
| VRF 1 | 160 | 256 | 544 | 1024 | 1984 |
| VRF 2 | 160 | 224 | 416 | 736 | 1376 |
| challenge (base token) | 128 | 224 | 512 | 992 | 1952 |
| challenge (challenge token) | 192 | 288 | 576 | 1056 | 2016 |
| challenge (challenge token) | 192 | 288 | 576 | 1056 | 2016 |
| gamma | 96 | 160 | 352 | 672 | 1312 |

View File

@ -0,0 +1 @@
target/

View File

@ -0,0 +1,381 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
[[package]]
name = "autocfg"
version = "0.1.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "biscuit-gamma"
version = "0.1.0"
dependencies = [
"curve25519-dalek 1.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
"hmac 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)",
"rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 1.0.99 (registry+https://github.com/rust-lang/crates.io-index)",
"sha2 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "bitflags"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "block-buffer"
version = "0.7.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"block-padding 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
"byte-tools 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
"byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
"generic-array 0.12.3 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "block-padding"
version = "0.1.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"byte-tools 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "byte-tools"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "byteorder"
version = "1.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "cc"
version = "1.0.41"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "clear_on_drop"
version = "0.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"cc 1.0.41 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "cloudabi"
version = "0.0.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"bitflags 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "crypto-mac"
version = "0.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"generic-array 0.12.3 (registry+https://github.com/rust-lang/crates.io-index)",
"subtle 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "curve25519-dalek"
version = "1.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
"clear_on_drop 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
"digest 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)",
"rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 1.0.99 (registry+https://github.com/rust-lang/crates.io-index)",
"subtle 2.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "digest"
version = "0.8.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"generic-array 0.12.3 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "fake-simd"
version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "fuchsia-cprng"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "generic-array"
version = "0.12.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"typenum 1.11.2 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "hmac"
version = "0.7.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"crypto-mac 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
"digest 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "libc"
version = "0.2.62"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "opaque-debug"
version = "0.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "proc-macro2"
version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "quote"
version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"proc-macro2 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "rand"
version = "0.6.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"autocfg 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)",
"rand_chacha 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
"rand_core 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
"rand_hc 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"rand_isaac 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
"rand_jitter 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
"rand_os 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
"rand_pcg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
"rand_xorshift 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "rand_chacha"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"autocfg 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
"rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "rand_core"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"rand_core 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "rand_core"
version = "0.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "rand_hc"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "rand_isaac"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "rand_jitter"
version = "0.1.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)",
"rand_core 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "rand_os"
version = "0.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
"fuchsia-cprng 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)",
"rand_core 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
"rdrand 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "rand_pcg"
version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"autocfg 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
"rand_core 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "rand_xorshift"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "rdrand"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "serde"
version = "1.0.99"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"serde_derive 1.0.99 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "serde_derive"
version = "1.0.99"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"proc-macro2 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
"quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
"syn 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "sha2"
version = "0.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"block-buffer 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)",
"digest 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)",
"fake-simd 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
"opaque-debug 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "subtle"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "subtle"
version = "2.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "syn"
version = "1.0.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"proc-macro2 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
"quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
"unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "typenum"
version = "1.11.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "unicode-xid"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "winapi"
version = "0.3.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "winapi-i686-pc-windows-gnu"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "winapi-x86_64-pc-windows-gnu"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[metadata]
"checksum autocfg 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "b671c8fb71b457dd4ae18c4ba1e59aa81793daacc361d82fcd410cef0d491875"
"checksum bitflags 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3d155346769a6855b86399e9bc3814ab343cd3d62c7e985113d46a0ec3c281fd"
"checksum block-buffer 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)" = "c0940dc441f31689269e10ac70eb1002a3a1d3ad1390e030043662eb7fe4688b"
"checksum block-padding 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "6d4dc3af3ee2e12f3e5d224e5e1e3d73668abbeb69e566d361f7d5563a4fdf09"
"checksum byte-tools 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "e3b5ca7a04898ad4bcd41c90c5285445ff5b791899bb1b0abdd2a2aa791211d7"
"checksum byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a7c3dd8985a7111efc5c80b44e23ecdd8c007de8ade3b96595387e812b957cf5"
"checksum cc 1.0.41 (registry+https://github.com/rust-lang/crates.io-index)" = "8dae9c4b8fedcae85592ba623c4fd08cfdab3e3b72d6df780c6ead964a69bfff"
"checksum clear_on_drop 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "97276801e127ffb46b66ce23f35cc96bd454fa311294bced4bbace7baa8b1d17"
"checksum cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f"
"checksum crypto-mac 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4434400df11d95d556bac068ddfedd482915eb18fe8bea89bc80b6e4b1c179e5"
"checksum curve25519-dalek 1.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "8b7dcd30ba50cdf88b55b033456138b7c0ac4afdc436d82e1b79f370f24cc66d"
"checksum digest 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f3d0c8c8752312f9713efd397ff63acb9f85585afbf179282e720e7704954dd5"
"checksum fake-simd 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e88a8acf291dafb59c2d96e8f59828f3838bb1a70398823ade51a84de6a6deed"
"checksum fuchsia-cprng 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a06f77d526c1a601b7c4cdd98f54b5eaabffc14d5f2f0296febdc7f357c6d3ba"
"checksum generic-array 0.12.3 (registry+https://github.com/rust-lang/crates.io-index)" = "c68f0274ae0e023facc3c97b2e00f076be70e254bc851d972503b328db79b2ec"
"checksum hmac 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "5dcb5e64cda4c23119ab41ba960d1e170a774c8e4b9d9e6a9bc18aabf5e59695"
"checksum libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)" = "34fcd2c08d2f832f376f4173a231990fa5aef4e99fb569867318a227ef4c06ba"
"checksum opaque-debug 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2839e79665f131bdb5782e51f2c6c9599c133c6098982a54c794358bf432529c"
"checksum proc-macro2 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "175a40b9cf564ce9bf050654633dbf339978706b8ead1a907bb970b63185dd95"
"checksum quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "053a8c8bcc71fcce321828dc897a98ab9760bef03a4fc36693c231e5b3216cfe"
"checksum rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)" = "6d71dacdc3c88c1fde3885a3be3fbab9f35724e6ce99467f7d9c5026132184ca"
"checksum rand_chacha 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "556d3a1ca6600bfcbab7c7c91ccb085ac7fbbcd70e008a98742e7847f4f7bcef"
"checksum rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6fdeb83b075e8266dcc8762c22776f6877a63111121f5f8c7411e5be7eed4b"
"checksum rand_core 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9c33a3c44ca05fa6f1807d8e6743f3824e8509beca625669633be0acbdf509dc"
"checksum rand_hc 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7b40677c7be09ae76218dc623efbf7b18e34bced3f38883af07bb75630a21bc4"
"checksum rand_isaac 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ded997c9d5f13925be2a6fd7e66bf1872597f759fd9dd93513dd7e92e5a5ee08"
"checksum rand_jitter 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "1166d5c91dc97b88d1decc3285bb0a99ed84b05cfd0bc2341bdf2d43fc41e39b"
"checksum rand_os 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "7b75f676a1e053fc562eafbb47838d67c84801e38fc1ba459e8f180deabd5071"
"checksum rand_pcg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "abf9b09b01790cfe0364f52bf32995ea3c39f4d2dd011eac241d2914146d0b44"
"checksum rand_xorshift 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cbf7e9e623549b0e21f6e97cf8ecf247c1a8fd2e8a992ae265314300b2455d5c"
"checksum rdrand 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "678054eb77286b51581ba43620cc911abf02758c91f93f479767aed0f90458b2"
"checksum serde 1.0.99 (registry+https://github.com/rust-lang/crates.io-index)" = "fec2851eb56d010dc9a21b89ca53ee75e6528bab60c11e89d38390904982da9f"
"checksum serde_derive 1.0.99 (registry+https://github.com/rust-lang/crates.io-index)" = "cb4dc18c61206b08dc98216c98faa0232f4337e1e1b8574551d5bad29ea1b425"
"checksum sha2 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7b4d8bfd0e469f417657573d8451fb33d16cfe0989359b93baf3a1ffc639543d"
"checksum subtle 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2d67a5a62ba6e01cb2192ff309324cb4875d0c451d55fe2319433abe7a05a8ee"
"checksum subtle 2.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "01f40907d9ffc762709e4ff3eb4a6f6b41b650375a3f09ac92b641942b7fb082"
"checksum syn 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "66850e97125af79138385e9b88339cbcd037e3f28ceab8c5ad98e64f0f1f80bf"
"checksum typenum 1.11.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6d2783fe2d6b8c1101136184eb41be8b1ad379e4657050b8aaff0c79ee7575f9"
"checksum unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "826e7639553986605ec5979c7dd957c7895e93eabed50ab2ffa7f6128a75097c"
"checksum winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)" = "8093091eeb260906a183e6ae1abdba2ef5ef2257a21801128899c3fc699229c6"
"checksum winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
"checksum winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"

View File

@ -0,0 +1,13 @@
[package]
name = "biscuit-gamma"
version = "0.1.0"
authors = ["Geoffroy Couprie <geo.couprie@gmail.com>"]
edition = "2018"
[dependencies]
curve25519-dalek = { version = "^1.0", features = ["serde"] }
rand = "^0.6"
sha2 = "^0.8"
hmac = "^0.7"
serde = { version = "1.0", features = ["derive"] }

View File

@ -0,0 +1,165 @@
#![feature(test)]
extern crate test;
extern crate biscuit_gamma;
extern crate rand;
use rand::rngs::OsRng;
use biscuit_gamma::{KeyPair, Token, TokenSignature};
mod bench {
use super::*;
use test::Bencher;
#[bench]
fn sign_first_block(b: &mut Bencher) {
let mut rng: OsRng = OsRng::new().unwrap();
let message1 = b"hello";
let keypair1 = KeyPair::new(&mut rng);
let token1 = Token::new(&mut rng, &keypair1, &message1[..]);
assert!(token1.verify(), "cannot verify first token");
b.iter(||{
Token::new(&mut rng, &keypair1, &message1[..])
});
}
#[bench]
fn sign_second_block(b: &mut Bencher) {
let mut rng: OsRng = OsRng::new().unwrap();
let message1 = b"hello";
let keypair1 = KeyPair::new(&mut rng);
let token1 = Token::new(&mut rng, &keypair1, &message1[..]);
assert!(token1.verify(), "cannot verify first token");
println!("will derive a second token");
let message2 = b"world";
let keypair2 = KeyPair::new(&mut rng);
let token2 = token1.append(&mut rng, &keypair2, &message2[..]);
assert!(token2.verify(), "cannot verify second token");
b.iter(||{
token1.append(&mut rng, &keypair2, &message2[..])
});
}
#[bench]
fn sign_third_block(b: &mut Bencher) {
let mut rng: OsRng = OsRng::new().unwrap();
let message1 = b"hello";
let keypair1 = KeyPair::new(&mut rng);
let token1 = Token::new(&mut rng, &keypair1, &message1[..]);
assert!(token1.verify(), "cannot verify first token");
println!("will derive a second token");
let message2 = b"world";
let keypair2 = KeyPair::new(&mut rng);
let token2 = token1.append(&mut rng, &keypair2, &message2[..]);
assert!(token2.verify(), "cannot verify second token");
println!("will derive a third token");
let message3 = b"!!!";
let keypair3 = KeyPair::new(&mut rng);
let token3 = token2.append(&mut rng, &keypair3, &message3[..]);
assert!(token3.verify(), "cannot verify third token");
b.iter(||{
token2.append(&mut rng, &keypair3, &message3[..])
});
}
#[bench]
fn verify_one_block(b: &mut Bencher) {
let mut rng: OsRng = OsRng::new().unwrap();
let message1 = b"hello";
let keypair1 = KeyPair::new(&mut rng);
let token1 = Token::new(&mut rng, &keypair1, &message1[..]);
assert!(token1.verify(), "cannot verify first token");
b.iter(||{
token1.verify()
});
}
#[bench]
fn verify_two_blocks(b: &mut Bencher) {
let mut rng: OsRng = OsRng::new().unwrap();
let message1 = b"hello";
let keypair1 = KeyPair::new(&mut rng);
let token1 = Token::new(&mut rng, &keypair1, &message1[..]);
assert!(token1.verify(), "cannot verify first token");
println!("will derive a second token");
let message2 = b"world";
let keypair2 = KeyPair::new(&mut rng);
let token2 = token1.append(&mut rng, &keypair2, &message2[..]);
assert!(token2.verify(), "cannot verify second token");
b.iter(||{
token2.verify()
});
}
#[bench]
fn verify_three_blocks(b: &mut Bencher) {
let mut rng: OsRng = OsRng::new().unwrap();
let message1 = b"hello";
let keypair1 = KeyPair::new(&mut rng);
let token1 = Token::new(&mut rng, &keypair1, &message1[..]);
assert!(token1.verify(), "cannot verify first token");
println!("will derive a second token");
let message2 = b"world";
let keypair2 = KeyPair::new(&mut rng);
let token2 = token1.append(&mut rng, &keypair2, &message2[..]);
assert!(token2.verify(), "cannot verify second token");
println!("will derive a third token");
let message3 = b"!!!";
let keypair3 = KeyPair::new(&mut rng);
let token3 = token2.append(&mut rng, &keypair3, &message3[..]);
assert!(token3.verify(), "cannot verify third token");
b.iter(||{
token3.verify()
});
}
}

View File

@ -0,0 +1,307 @@
#![allow(non_snake_case)]
extern crate curve25519_dalek;
extern crate rand;
extern crate sha2;
extern crate hmac;
extern crate serde;
use sha2::{Digest, Sha512};
use hmac::{Hmac, Mac};
use rand::prelude::*;
use serde::{Serialize, Deserialize};
use curve25519_dalek::{
constants::RISTRETTO_BASEPOINT_POINT,
ristretto::{RistrettoPoint},
scalar::Scalar,
traits::Identity
};
use std::ops::{Deref, Neg};
type HmacSha512 = Hmac<Sha512>;
pub struct KeyPair {
private: Scalar,
pub public: RistrettoPoint,
}
impl KeyPair {
pub fn new<T: Rng + CryptoRng>(rng: &mut T) -> Self {
let private = Scalar::random(rng);
let public = private * RISTRETTO_BASEPOINT_POINT;
KeyPair { private, public }
}
pub fn sign<T: Rng + CryptoRng>(&self, rng: &mut T, message: &[u8]) -> (Scalar, Scalar) {
let r = Scalar::random(rng);
let A = r * RISTRETTO_BASEPOINT_POINT;
let d = ECVRF_hash_points(&[A]);
// FIXME: maybe there's a simpler hashing process
let e = ECVRF_hash_points(&[self.public, ECVRF_hash_to_curve(RISTRETTO_BASEPOINT_POINT, message)]);
let z = r*d - e*self.private;
(d, z)
}
}
pub fn verify(public: &RistrettoPoint, message: &[u8], signature: &(Scalar, Scalar)) -> bool {
let (d, z) = signature;
let e = ECVRF_hash_points(&[*public, ECVRF_hash_to_curve(RISTRETTO_BASEPOINT_POINT, message)]);
let d_inv = d.invert();
let A = z * d_inv * RISTRETTO_BASEPOINT_POINT + e * d_inv * public;
ECVRF_hash_points(&[A]) == *d
}
pub struct Token {
pub messages: Vec<Vec<u8>>,
pub keys: Vec<RistrettoPoint>,
pub signature: TokenSignature,
}
impl Token {
pub fn new<T: Rng + CryptoRng>(rng: &mut T, keypair: &KeyPair, message: &[u8]) -> Self {
let signature = TokenSignature::new(rng, keypair, message);
Token {
messages: vec![message.to_owned()],
keys: vec![keypair.public],
signature
}
}
pub fn append<T: Rng + CryptoRng>(&self, rng: &mut T, keypair: &KeyPair, message: &[u8]) -> Self {
let signature = self.signature.sign(rng, &self.keys, &self.messages, keypair, message);
let mut t = Token {
messages: self.messages.clone(),
keys: self.keys.clone(),
signature
};
t.messages.push(message.to_owned());
t.keys.push(keypair.public);
t
}
pub fn verify(&self) -> bool {
self.signature.verify(&self.keys, &self.messages)
}
}
#[derive(Clone,Debug,Serialize,Deserialize)]
pub struct TokenSignature {
parameters: Vec<RistrettoPoint>,
z: Scalar
}
impl TokenSignature {
pub fn new<T: Rng + CryptoRng>(rng: &mut T, keypair: &KeyPair, message: &[u8]) -> Self {
let r = Scalar::random(rng);
let A = r * RISTRETTO_BASEPOINT_POINT;
let d = ECVRF_hash_points(&[A]);
// FIXME: maybe there's a simpler hashing process
let e = ECVRF_hash_points(&[keypair.public, ECVRF_hash_to_curve(RISTRETTO_BASEPOINT_POINT, message)]);
let z = r*d - e * keypair.private;
TokenSignature {
parameters: vec![A],
z: z,
}
}
pub fn sign<M: Deref<Target=[u8]>, T: Rng + CryptoRng>(&self, rng: &mut T, public_keys: &[RistrettoPoint],
messages: &[M], keypair: &KeyPair, message: &[u8]) -> Self {
let r = Scalar::random(rng);
let A = r * RISTRETTO_BASEPOINT_POINT;
let d = ECVRF_hash_points(&[A]);
// FIXME: maybe there's a simpler hashing process
let e = ECVRF_hash_points(&[keypair.public, ECVRF_hash_to_curve(RISTRETTO_BASEPOINT_POINT, message)]);
let z = r*d - e * keypair.private;
let mut t = TokenSignature {
parameters: self.parameters.clone(),
z: self.z + z,
};
t.parameters.push(A);
t
}
pub fn verify<M: Deref<Target=[u8]>>(&self, public_keys: &[RistrettoPoint], messages: &[M]) -> bool {
if !(public_keys.len() == messages.len()
&& public_keys.len() == self.parameters.len()) {
println!("invalid data");
return false;
}
let zP = self.z * RISTRETTO_BASEPOINT_POINT;
let eiXi = public_keys.iter().zip(messages).map(|(pubkey, message)| {
let e = ECVRF_hash_points(&[*pubkey, ECVRF_hash_to_curve(RISTRETTO_BASEPOINT_POINT, message)]);
e * pubkey
}).fold(RistrettoPoint::identity(), |acc, point| acc + point);
let diAi = self.parameters.iter().map(|A| {
let d = ECVRF_hash_points(&[*A]);
d * A
}).fold(RistrettoPoint::identity(), |acc, point| acc + point);
let res = zP + eiXi - diAi;
println!("verify identity={:?}", RistrettoPoint::identity());
println!("verify res={:?}", res);
println!("verify identity={:?}", RistrettoPoint::identity().compress());
println!("verify res={:?}", res.compress());
println!("returning: {:?}", RistrettoPoint::identity() == res);
RistrettoPoint::identity() == res
}
}
//FIXME: the ECVRF_hash_to_curve1 looks like a hash and pray, but since
// curve25519-dalek already has a hash to curve function, we can reuse it instead?
pub fn ECVRF_hash_to_curve(point: RistrettoPoint, data: &[u8]) -> RistrettoPoint {
let h = Sha512::new()
.chain(point.compress().as_bytes())
.chain(data);
RistrettoPoint::from_hash(h)
}
//FIXME: is the output value in the right set?
pub fn ECVRF_hash_points(points: &[RistrettoPoint]) -> Scalar {
let mut h = Sha512::new();
for point in points.iter() {
h.input(point.compress().as_bytes());
}
Scalar::from_hash(h)
}
pub fn add_points(points: &[RistrettoPoint]) -> RistrettoPoint {
assert!(points.len() > 0);
if points.len() == 1 {
points[0]
} else {
let mut it = points.iter();
let first = it.next().unwrap();
it.fold(*first, |acc, pk| acc + pk)
}
}
pub fn ECVRF_nonce(sk: Scalar, point: RistrettoPoint) -> Scalar {
let k = [0u8; 64];
let v = [1u8; 64];
let mut mac = HmacSha512::new_varkey(&k[..]).unwrap();
mac.input(&v[..]);
mac.input(&[0]);
mac.input(&sk.as_bytes()[..]);
mac.input(point.compress().as_bytes());
let k = mac.result().code();
let mut mac = HmacSha512::new_varkey(&k[..]).unwrap();
mac.input(&v[..]);
mac.input(&[1]);
mac.input(&sk.as_bytes()[..]);
mac.input(point.compress().as_bytes());
let k = mac.result().code();
// the process in RFC 6979 is a bit ore complex than that
let mut h = Sha512::new();
h.input(k);
Scalar::from_hash(h)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn basic_signature() {
let mut rng: StdRng = SeedableRng::seed_from_u64(0);
let message = b"hello world";
let keypair = KeyPair::new(&mut rng);
let signature = keypair.sign(&mut rng, message);
assert!(verify(&keypair.public, message, &signature));
assert!(!verify(&keypair.public, b"AAAA", &signature));
}
#[test]
fn three_messages() {
//let mut rng: OsRng = OsRng::new().unwrap();
//keep the same values in tests
let mut rng: StdRng = SeedableRng::seed_from_u64(0);
let message1 = b"hello";
let keypair1 = KeyPair::new(&mut rng);
let token1 = Token::new(&mut rng, &keypair1, &message1[..]);
assert!(token1.verify(), "cannot verify first token");
println!("will derive a second token");
let message2 = b"world";
let keypair2 = KeyPair::new(&mut rng);
let token2 = token1.append(&mut rng, &keypair2, &message2[..]);
assert!(token2.verify(), "cannot verify second token");
println!("will derive a third token");
let message3 = b"!!!";
let keypair3 = KeyPair::new(&mut rng);
let token3 = token2.append(&mut rng, &keypair3, &message3[..]);
assert!(token3.verify(), "cannot verify third token");
}
#[test]
fn change_message() {
//let mut rng: OsRng = OsRng::new().unwrap();
//keep the same values in tests
let mut rng: StdRng = SeedableRng::seed_from_u64(0);
let message1 = b"hello";
let keypair1 = KeyPair::new(&mut rng);
let token1 = Token::new(&mut rng, &keypair1, &message1[..]);
assert!(token1.verify(), "cannot verify first token");
println!("will derive a second token");
let message2 = b"world";
let keypair2 = KeyPair::new(&mut rng);
let mut token2 = token1.append(&mut rng, &keypair2, &message2[..]);
token2.messages[1] = Vec::from(&b"you"[..]);
assert!(!token2.verify(), "second token should not be valid");
println!("will derive a third token");
let message3 = b"!!!";
let keypair3 = KeyPair::new(&mut rng);
let token3 = token2.append(&mut rng, &keypair3, &message3[..]);
assert!(!token3.verify(), "cannot verify third token");
}
}