Compare commits
9
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
cc4e4727c2
|
||
|
|
56e82a3866
|
||
|
|
8d462be1f7
|
||
|
|
201fb57d9f
|
||
|
|
ef59638de0
|
||
|
|
313f1b66bb
|
||
|
|
0bbf8fbfb5
|
||
|
|
1451f937ca
|
||
|
|
eb00b86000
|
@@ -16,7 +16,7 @@ jobs:
|
|||||||
name: cargo fmt
|
name: cargo fmt
|
||||||
runs-on: linux_amd64
|
runs-on: linux_amd64
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7
|
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
|
||||||
- uses: dtolnay/rust-toolchain@stable
|
- uses: dtolnay/rust-toolchain@stable
|
||||||
with:
|
with:
|
||||||
components: rustfmt
|
components: rustfmt
|
||||||
@@ -27,7 +27,7 @@ jobs:
|
|||||||
name: cargo clippy
|
name: cargo clippy
|
||||||
runs-on: linux_amd64
|
runs-on: linux_amd64
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7
|
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
|
||||||
- uses: dtolnay/rust-toolchain@stable
|
- uses: dtolnay/rust-toolchain@stable
|
||||||
with:
|
with:
|
||||||
components: clippy
|
components: clippy
|
||||||
@@ -55,7 +55,7 @@ jobs:
|
|||||||
- stable
|
- stable
|
||||||
- "1.87.0"
|
- "1.87.0"
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7
|
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
|
||||||
- uses: dtolnay/rust-toolchain@${{ matrix.toolchain }}
|
- uses: dtolnay/rust-toolchain@${{ matrix.toolchain }}
|
||||||
- name: Run cargo test
|
- name: Run cargo test
|
||||||
run: cargo test --no-default-features --lib --tests ${{ matrix.backend_feature }}
|
run: cargo test --no-default-features --lib --tests ${{ matrix.backend_feature }}
|
||||||
@@ -83,7 +83,7 @@ jobs:
|
|||||||
- --features danger
|
- --features danger
|
||||||
- --features serde
|
- --features serde
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7
|
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
|
||||||
- uses: dtolnay/rust-toolchain@stable
|
- uses: dtolnay/rust-toolchain@stable
|
||||||
with:
|
with:
|
||||||
targets: ${{ matrix.target }}
|
targets: ${{ matrix.target }}
|
||||||
@@ -94,7 +94,7 @@ jobs:
|
|||||||
name: cargo audit
|
name: cargo audit
|
||||||
runs-on: linux_amd64
|
runs-on: linux_amd64
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7
|
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
|
||||||
- uses: dtolnay/rust-toolchain@stable
|
- uses: dtolnay/rust-toolchain@stable
|
||||||
- name: Install cargo-audit
|
- name: Install cargo-audit
|
||||||
run: cargo install cargo-audit
|
run: cargo install cargo-audit
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ jobs:
|
|||||||
publish:
|
publish:
|
||||||
runs-on: linux_amd64
|
runs-on: linux_amd64
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7
|
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
|
||||||
|
|
||||||
- uses: dtolnay/rust-toolchain@stable
|
- uses: dtolnay/rust-toolchain@stable
|
||||||
|
|
||||||
|
|||||||
+7
-5
@@ -1,10 +1,12 @@
|
|||||||
# Generated by Cargo
|
# Generated by Cargo
|
||||||
# will have compiled files and executables
|
# will have compiled files and executables
|
||||||
/target/
|
debug/
|
||||||
|
target/
|
||||||
# Remove Cargo.lock from gitignore if creating an executable, leave it for libraries
|
pkg/
|
||||||
# More information here https://doc.rust-lang.org/cargo/guide/cargo-toml-vs-cargo-lock.html
|
demo/
|
||||||
Cargo.lock
|
|
||||||
|
|
||||||
# These are backup files generated by rustfmt
|
# These are backup files generated by rustfmt
|
||||||
**/*.rs.bk
|
**/*.rs.bk
|
||||||
|
|
||||||
|
# MSVC Windows builds of rustc generate these, which store debugging information
|
||||||
|
*.pdb
|
||||||
|
|||||||
@@ -1,5 +1,29 @@
|
|||||||
# Changelog
|
# Changelog
|
||||||
|
|
||||||
|
## 1.0.0 (July 8, 2026)
|
||||||
|
|
||||||
|
* Deduplicated serialization with `impl_serde_scalar`, `impl_serde_elem`, and `impl_serde_scalar_elem` macros
|
||||||
|
* Moved `finalize_after_unblind` to `common.rs`, shared by OPRF and VOPRF
|
||||||
|
* Added shared test helpers (`test_all_curves` macro, `prf` function)
|
||||||
|
* Updated dependencies to stable releases
|
||||||
|
|
||||||
|
## 1.0.0-rc.1 (July 3, 2026)
|
||||||
|
|
||||||
|
* Reject trailing bytes in all `deserialize` methods
|
||||||
|
* Reject identity element in `deterministic_blind_unchecked` to prevent blinding bypass
|
||||||
|
* Added roundtrip, trailing bytes, truncated, and empty input tests for serialization
|
||||||
|
|
||||||
|
## 1.0.0-rc.0 (July 2, 2026)
|
||||||
|
|
||||||
|
* Added missing license in Cargo manifest
|
||||||
|
* Implement `zeroize` feature for `digest`, `hybrid-array` and `sha2`
|
||||||
|
* Replaced license appendix in files while keeping original copyright
|
||||||
|
|
||||||
|
## 1.0.0-pre.1 (July 2, 2026)
|
||||||
|
|
||||||
|
* Simplified ciphersuite trait
|
||||||
|
* Moved multiplication operator to SecurityLevel type in Group trait
|
||||||
|
|
||||||
## 1.0.0-pre.0 (June 29, 2026)
|
## 1.0.0-pre.0 (June 29, 2026)
|
||||||
|
|
||||||
Forked from [facebook/voprf](https://github.com/facebook/voprf/) at `0.6.0-pre.1`.
|
Forked from [facebook/voprf](https://github.com/facebook/voprf/) at `0.6.0-pre.1`.
|
||||||
|
|||||||
Generated
+855
@@ -0,0 +1,855 @@
|
|||||||
|
# This file is automatically @generated by Cargo.
|
||||||
|
# It is not intended for manual editing.
|
||||||
|
version = 4
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "aho-corasick"
|
||||||
|
version = "1.1.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ddd31a130427c27518df266943a5308ed92d4b226cc639f5a8f1002816174301"
|
||||||
|
dependencies = [
|
||||||
|
"memchr",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "autocfg"
|
||||||
|
version = "1.5.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f2032f911046de80f0a198e0901378627c33f59ea0ac00e363d481118bd70a53"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "base16ct"
|
||||||
|
version = "1.0.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "fd307490d624467aa6f74b0eabb77633d1f758a7b25f12bceb0b22e08d9726f6"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "bit-set"
|
||||||
|
version = "0.8.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "08807e080ed7f9d5433fa9b275196cfc35414f66a0c79d864dc51a0d825231a3"
|
||||||
|
dependencies = [
|
||||||
|
"bit-vec",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "bit-vec"
|
||||||
|
version = "0.8.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "5e764a1d40d510daf35e07be9eb06e75770908c27d411ee6c92109c9840eaaf7"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "bitflags"
|
||||||
|
version = "2.13.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "b4388bee8683e3d04af747c73422af53102d2bd24d9eadb6cbc100baef4b43f8"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "block-buffer"
|
||||||
|
version = "0.12.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "d2f6c7dbe95a6ed67ad9f18e57daf93a2f034c524b99fd2b76d18fdfeb6660aa"
|
||||||
|
dependencies = [
|
||||||
|
"hybrid-array",
|
||||||
|
"zeroize",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "cfg-if"
|
||||||
|
version = "1.0.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "chacha20"
|
||||||
|
version = "0.10.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "d524456ba66e72eb8b115ff89e01e497f8e6d11d78b70b1aa13c0fbd97540a81"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if",
|
||||||
|
"cpufeatures",
|
||||||
|
"rand_core 0.10.1",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "cmov"
|
||||||
|
version = "0.5.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "0c9ea0ac24bc397ab3c98583a3c9ba74fa56b09a4449bbe172b9b1ddb016027a"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "const-oid"
|
||||||
|
version = "0.10.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "a6ef517f0926dd24a1582492c791b6a4818a4d94e789a334894aa15b0d12f55c"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "cpubits"
|
||||||
|
version = "0.1.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "15b85f9c39137c3a891689859392b1bd49812121d0d61c9caf00d46ed5ce06ae"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "cpufeatures"
|
||||||
|
version = "0.3.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "8b2a41393f66f16b0823bb79094d54ac5fbd34ab292ddafb9a0456ac9f87d201"
|
||||||
|
dependencies = [
|
||||||
|
"libc",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "crypto-bigint"
|
||||||
|
version = "0.7.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "1a52aa3fcda4e6302a9f48734f234d35d4721b96f8fe07d073f07ce9df4f0271"
|
||||||
|
dependencies = [
|
||||||
|
"cpubits",
|
||||||
|
"ctutils",
|
||||||
|
"hybrid-array",
|
||||||
|
"num-traits",
|
||||||
|
"rand_core 0.10.1",
|
||||||
|
"subtle",
|
||||||
|
"zeroize",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "crypto-common"
|
||||||
|
version = "0.2.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ce6e4c961d6cd6c9a86db418387425e8bdeaf05b3c8bc1411e6dca4c252f1453"
|
||||||
|
dependencies = [
|
||||||
|
"hybrid-array",
|
||||||
|
"rand_core 0.10.1",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "ctutils"
|
||||||
|
version = "0.4.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "7d5515a3834141de9eafb9717ad39eea8247b5674e6066c404e8c4b365d2a29e"
|
||||||
|
dependencies = [
|
||||||
|
"cmov",
|
||||||
|
"subtle",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "curve25519-dalek"
|
||||||
|
version = "5.0.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "b5eed333089e2e1c1ac8c6c0398e5e2497b4c9926ca6d0365ed1e099afa5bc23"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if",
|
||||||
|
"cpufeatures",
|
||||||
|
"curve25519-dalek-derive",
|
||||||
|
"digest",
|
||||||
|
"fiat-crypto",
|
||||||
|
"rand_core 0.10.1",
|
||||||
|
"rustc_version",
|
||||||
|
"serde",
|
||||||
|
"subtle",
|
||||||
|
"zeroize",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "curve25519-dalek-derive"
|
||||||
|
version = "0.1.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f46882e17999c6cc590af592290432be3bce0428cb0d5f8b6715e4dc7b383eb3"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn 2.0.118",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "der"
|
||||||
|
version = "0.8.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "a69dedd701da44b0536442edf09c81a64b0ab97a7a4a5e3d1971f00027cbc63d"
|
||||||
|
dependencies = [
|
||||||
|
"const-oid",
|
||||||
|
"zeroize",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "derive-where"
|
||||||
|
version = "1.6.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "d08b3a0bcc0d079199cd476b2cae8435016ec11d1c0986c6901c5ac223041534"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn 2.0.118",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "digest"
|
||||||
|
version = "0.11.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f1dd6dbb5841937940781866fa1281a1ff7bd3bf827091440879f9994983d5c2"
|
||||||
|
dependencies = [
|
||||||
|
"block-buffer",
|
||||||
|
"const-oid",
|
||||||
|
"crypto-common",
|
||||||
|
"zeroize",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "displaydoc"
|
||||||
|
version = "0.2.7"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "c6232dd377dcc64799954cbd3a9bb882e9cdc1308ccd87b1c098f1fb2eaf82a8"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn 3.0.3",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "elliptic-curve"
|
||||||
|
version = "0.14.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "9d65aa39b3a5c1c9c1b745c9a019234bb7a21b77abcb4f4d266d706e2d577d65"
|
||||||
|
dependencies = [
|
||||||
|
"base16ct",
|
||||||
|
"crypto-bigint",
|
||||||
|
"crypto-common",
|
||||||
|
"digest",
|
||||||
|
"ff",
|
||||||
|
"group",
|
||||||
|
"hybrid-array",
|
||||||
|
"rand_core 0.10.1",
|
||||||
|
"sec1",
|
||||||
|
"subtle",
|
||||||
|
"zeroize",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "errno"
|
||||||
|
version = "0.3.14"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb"
|
||||||
|
dependencies = [
|
||||||
|
"libc",
|
||||||
|
"windows-sys",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "fastrand"
|
||||||
|
version = "2.4.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "9f1f227452a390804cdb637b74a86990f2a7d7ba4b7d5693aac9b4dd6defd8d6"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "ff"
|
||||||
|
version = "0.14.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "a1f686ab92a9fb0eaf188f6c6c87b89490baa6fdb0db4544ba4dc47f7942489f"
|
||||||
|
dependencies = [
|
||||||
|
"rand_core 0.10.1",
|
||||||
|
"subtle",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "fiat-crypto"
|
||||||
|
version = "0.3.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "64cd1e32ddd350061ae6edb1b082d7c54915b5c672c389143b9a63403a109f24"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "fnv"
|
||||||
|
version = "1.0.7"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "getrandom"
|
||||||
|
version = "0.3.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "899def5c37c4fd7b2664648c28120ecec138e4d395b459e5ca34f9cce2dd77fd"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if",
|
||||||
|
"libc",
|
||||||
|
"r-efi 5.3.0",
|
||||||
|
"wasip2",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "getrandom"
|
||||||
|
version = "0.4.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "300e883d756b2e4ec94e02791f39b04b522276138852cfc41d9fb7e904106099"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if",
|
||||||
|
"libc",
|
||||||
|
"r-efi 6.0.0",
|
||||||
|
"rand_core 0.10.1",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "group"
|
||||||
|
version = "0.14.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "7fd1a1c7a5206c5b7a3f5a0d7ccd3ff85d0c8f5133d62a02680255b0004af5f4"
|
||||||
|
dependencies = [
|
||||||
|
"ff",
|
||||||
|
"rand_core 0.10.1",
|
||||||
|
"subtle",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "hash2curve"
|
||||||
|
version = "0.14.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "1eaf40612d7d854743e7189228a6d528f0f6e8502cf6a0cb831d28a218b7f3f6"
|
||||||
|
dependencies = [
|
||||||
|
"digest",
|
||||||
|
"elliptic-curve",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "hex"
|
||||||
|
version = "0.4.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "hybrid-array"
|
||||||
|
version = "0.4.14"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "707114b52a152fa7bdb290cd7cd5912d9467273b6d74e21b8d81aca1f8533f6b"
|
||||||
|
dependencies = [
|
||||||
|
"serde",
|
||||||
|
"subtle",
|
||||||
|
"typenum",
|
||||||
|
"zeroize",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "itoa"
|
||||||
|
version = "1.0.18"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "8f42a60cbdf9a97f5d2305f08a87dc4e09308d1276d28c869c684d7777685682"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "libc"
|
||||||
|
version = "0.2.186"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "68ab91017fe16c622486840e4c83c9a37afeff978bd239b5293d61ece587de66"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "linux-raw-sys"
|
||||||
|
version = "0.12.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "32a66949e030da00e8c7d4434b251670a91556f4144941d37452769c25d58a53"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "memchr"
|
||||||
|
version = "2.8.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "cf8baf1c55e62ffcace7a9f06f4bd9cd3f0c4beb022d3b367256b91b87513d98"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "num-traits"
|
||||||
|
version = "0.2.19"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841"
|
||||||
|
dependencies = [
|
||||||
|
"autocfg",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "once_cell"
|
||||||
|
version = "1.21.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "p256"
|
||||||
|
version = "0.14.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "d2c9239b2dbc807adbbe147e8cf72ea7450c3a0aabe62cb8e75ff4ec22e1f72a"
|
||||||
|
dependencies = [
|
||||||
|
"elliptic-curve",
|
||||||
|
"hash2curve",
|
||||||
|
"primefield",
|
||||||
|
"primeorder",
|
||||||
|
"sha2",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "p384"
|
||||||
|
version = "0.14.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "d17b851e6b3e378ab4ecb07fa2ed23f4d15f075735f8fec9fa1e7bdce5f8301f"
|
||||||
|
dependencies = [
|
||||||
|
"elliptic-curve",
|
||||||
|
"fiat-crypto",
|
||||||
|
"hash2curve",
|
||||||
|
"primefield",
|
||||||
|
"primeorder",
|
||||||
|
"sha2",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "p521"
|
||||||
|
version = "0.14.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "4ad64cc32c2dc466317c12ee5853e61f159f9eab1fe7efade0395dc2e7b43449"
|
||||||
|
dependencies = [
|
||||||
|
"base16ct",
|
||||||
|
"elliptic-curve",
|
||||||
|
"hash2curve",
|
||||||
|
"primefield",
|
||||||
|
"primeorder",
|
||||||
|
"sha2",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "ppv-lite86"
|
||||||
|
version = "0.2.21"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "85eae3c4ed2f50dcfe72643da4befc30deadb458a9b590d720cde2f2b1e97da9"
|
||||||
|
dependencies = [
|
||||||
|
"zerocopy",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "primefield"
|
||||||
|
version = "0.14.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "c555a6e4eb7d4e158fcb028c835c3b8642206ddc279b5c6b202ef9a8bdb592f4"
|
||||||
|
dependencies = [
|
||||||
|
"crypto-bigint",
|
||||||
|
"crypto-common",
|
||||||
|
"ff",
|
||||||
|
"rand_core 0.10.1",
|
||||||
|
"subtle",
|
||||||
|
"zeroize",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "primeorder"
|
||||||
|
version = "0.14.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "5c9f42978c78a00e3d68f69fc03e57a234debae69da4020a4fb588fcdcd07b06"
|
||||||
|
dependencies = [
|
||||||
|
"elliptic-curve",
|
||||||
|
"primefield",
|
||||||
|
"wnaf",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "proc-macro2"
|
||||||
|
version = "1.0.106"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "8fd00f0bb2e90d81d1044c2b32617f68fcb9fa3bb7640c23e9c748e53fb30934"
|
||||||
|
dependencies = [
|
||||||
|
"unicode-ident",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "proptest"
|
||||||
|
version = "1.11.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "4b45fcc2344c680f5025fe57779faef368840d0bd1f42f216291f0dc4ace4744"
|
||||||
|
dependencies = [
|
||||||
|
"bit-set",
|
||||||
|
"bit-vec",
|
||||||
|
"bitflags",
|
||||||
|
"num-traits",
|
||||||
|
"rand 0.9.4",
|
||||||
|
"rand_chacha",
|
||||||
|
"rand_xorshift",
|
||||||
|
"regex-syntax",
|
||||||
|
"rusty-fork",
|
||||||
|
"tempfile",
|
||||||
|
"unarray",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "quick-error"
|
||||||
|
version = "1.2.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "quote"
|
||||||
|
version = "1.0.46"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "dfbc457d0c7a0759a614551b11a6409e5951f6c7537be1f1b7682b9ae9230368"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "r-efi"
|
||||||
|
version = "5.3.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "r-efi"
|
||||||
|
version = "6.0.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f8dcc9c7d52a811697d2151c701e0d08956f92b0e24136cf4cf27b57a6a0d9bf"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rand"
|
||||||
|
version = "0.9.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "44c5af06bb1b7d3216d91932aed5265164bf384dc89cd6ba05cf59a35f5f76ea"
|
||||||
|
dependencies = [
|
||||||
|
"rand_chacha",
|
||||||
|
"rand_core 0.9.5",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rand"
|
||||||
|
version = "0.10.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "c7f5fa3a058cd35567ef9bfa5e75732bee0f9e4c55fa90477bef2dfcdbc4be80"
|
||||||
|
dependencies = [
|
||||||
|
"chacha20",
|
||||||
|
"getrandom 0.4.3",
|
||||||
|
"rand_core 0.10.1",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rand_chacha"
|
||||||
|
version = "0.9.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "d3022b5f1df60f26e1ffddd6c66e8aa15de382ae63b3a0c1bfc0e4d3e3f325cb"
|
||||||
|
dependencies = [
|
||||||
|
"ppv-lite86",
|
||||||
|
"rand_core 0.9.5",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rand_core"
|
||||||
|
version = "0.9.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "76afc826de14238e6e8c374ddcc1fa19e374fd8dd986b0d2af0d02377261d83c"
|
||||||
|
dependencies = [
|
||||||
|
"getrandom 0.3.4",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rand_core"
|
||||||
|
version = "0.10.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "63b8176103e19a2643978565ca18b50549f6101881c443590420e4dc998a3c69"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rand_xorshift"
|
||||||
|
version = "0.4.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "513962919efc330f829edb2535844d1b912b0fbe2ca165d613e4e8788bb05a5a"
|
||||||
|
dependencies = [
|
||||||
|
"rand_core 0.9.5",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "regex"
|
||||||
|
version = "1.13.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f020237b6c8eed93db2e2cb53c00c60a8e1bc73da7d073199a1180401450218d"
|
||||||
|
dependencies = [
|
||||||
|
"aho-corasick",
|
||||||
|
"memchr",
|
||||||
|
"regex-automata",
|
||||||
|
"regex-syntax",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "regex-automata"
|
||||||
|
version = "0.4.18"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ad8553b9b26413251cbf30e620595c7a41b3887f03da04579c0e6b0d6a06b4b2"
|
||||||
|
dependencies = [
|
||||||
|
"aho-corasick",
|
||||||
|
"memchr",
|
||||||
|
"regex-syntax",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "regex-syntax"
|
||||||
|
version = "0.8.11"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "d6f6ff9a378485b298a5286656da665ba74413d36db0979633275d2e708145d4"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rustc_version"
|
||||||
|
version = "0.4.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "cfcb3a22ef46e85b45de6ee7e79d063319ebb6594faafcf1c225ea92ab6e9b92"
|
||||||
|
dependencies = [
|
||||||
|
"semver",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rustix"
|
||||||
|
version = "1.1.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "b6fe4565b9518b83ef4f91bb47ce29620ca828bd32cb7e408f0062e9930ba190"
|
||||||
|
dependencies = [
|
||||||
|
"bitflags",
|
||||||
|
"errno",
|
||||||
|
"libc",
|
||||||
|
"linux-raw-sys",
|
||||||
|
"windows-sys",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rusty-fork"
|
||||||
|
version = "0.3.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "cc6bf79ff24e648f6da1f8d1f011e9cac26491b619e6b9280f2b47f1774e6ee2"
|
||||||
|
dependencies = [
|
||||||
|
"fnv",
|
||||||
|
"quick-error",
|
||||||
|
"tempfile",
|
||||||
|
"wait-timeout",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "sec1"
|
||||||
|
version = "0.8.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "d56d437c2f19203ce5f7122e507831de96f3d2d4d3be5af44a0b0a09d8a80e4d"
|
||||||
|
dependencies = [
|
||||||
|
"base16ct",
|
||||||
|
"ctutils",
|
||||||
|
"der",
|
||||||
|
"hybrid-array",
|
||||||
|
"subtle",
|
||||||
|
"zeroize",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "semver"
|
||||||
|
version = "1.0.28"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "8a7852d02fc848982e0c167ef163aaff9cd91dc640ba85e263cb1ce46fae51cd"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "serde"
|
||||||
|
version = "1.0.229"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "4148590afebada386688f18773da617792bf2ef03ffc1e4cbd2b1d45b023e0ba"
|
||||||
|
dependencies = [
|
||||||
|
"serde_core",
|
||||||
|
"serde_derive",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "serde_core"
|
||||||
|
version = "1.0.229"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "67dca2c9c51e58a4791a4b1ed58308b39c64224d349a935ab5039aa360942a48"
|
||||||
|
dependencies = [
|
||||||
|
"serde_derive",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "serde_derive"
|
||||||
|
version = "1.0.229"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e7a5d71263a5a7d47b41f6b3f06ba276f10cc18b0931f1799f710578e2309348"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn 3.0.3",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "serde_json"
|
||||||
|
version = "1.0.151"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "c841b55ecdae098c80dcae9cf767f6f8a0c2cdb3416bbef72181df4d0fe73f14"
|
||||||
|
dependencies = [
|
||||||
|
"itoa",
|
||||||
|
"memchr",
|
||||||
|
"serde",
|
||||||
|
"serde_core",
|
||||||
|
"zmij",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "sha2"
|
||||||
|
version = "0.11.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "446ba717509524cb3f22f17ecc096f10f4822d76ab5c0b9822c5f9c284e825f4"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if",
|
||||||
|
"cpufeatures",
|
||||||
|
"digest",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "subtle"
|
||||||
|
version = "2.6.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "syn"
|
||||||
|
version = "2.0.118"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "1b9ae57f904213ebb649ce6895b8a66c66f0203b9319718f69a5612a065b1422"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"unicode-ident",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "syn"
|
||||||
|
version = "3.0.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "53e9bae58849f64dfa4f5d5ae372c8341f7305f82a3868709269343628b659a3"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"unicode-ident",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "tempfile"
|
||||||
|
version = "3.27.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "32497e9a4c7b38532efcdebeef879707aa9f794296a4f0244f6f69e9bc8574bd"
|
||||||
|
dependencies = [
|
||||||
|
"fastrand",
|
||||||
|
"getrandom 0.4.3",
|
||||||
|
"once_cell",
|
||||||
|
"rustix",
|
||||||
|
"windows-sys",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "typenum"
|
||||||
|
version = "1.20.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "b6f5e870be6c3b371b77fe0ee0bafb859fa4964b4404c27de1d380043c4dda20"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "unarray"
|
||||||
|
version = "0.1.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "eaea85b334db583fe3274d12b4cd1880032beab409c0d774be044d4480ab9a94"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "unicode-ident"
|
||||||
|
version = "1.0.24"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "voprf-vx"
|
||||||
|
version = "1.0.0"
|
||||||
|
dependencies = [
|
||||||
|
"curve25519-dalek",
|
||||||
|
"derive-where",
|
||||||
|
"digest",
|
||||||
|
"displaydoc",
|
||||||
|
"elliptic-curve",
|
||||||
|
"hash2curve",
|
||||||
|
"hex",
|
||||||
|
"hybrid-array",
|
||||||
|
"p256",
|
||||||
|
"p384",
|
||||||
|
"p521",
|
||||||
|
"proptest",
|
||||||
|
"rand 0.10.2",
|
||||||
|
"rand_core 0.10.1",
|
||||||
|
"regex",
|
||||||
|
"serde",
|
||||||
|
"serde_json",
|
||||||
|
"sha2",
|
||||||
|
"subtle",
|
||||||
|
"zeroize",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "wait-timeout"
|
||||||
|
version = "0.2.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "09ac3b126d3914f9849036f826e054cbabdc8519970b8998ddaf3b5bd3c65f11"
|
||||||
|
dependencies = [
|
||||||
|
"libc",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "wasip2"
|
||||||
|
version = "1.0.4+wasi-0.2.12"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "b67efb37e106e55ce722a510d6b5f9c17f083e5fc79afc2badeb12cc313d9487"
|
||||||
|
dependencies = [
|
||||||
|
"wit-bindgen",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows-link"
|
||||||
|
version = "0.2.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows-sys"
|
||||||
|
version = "0.61.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ae137229bcbd6cdf0f7b80a31df61766145077ddf49416a728b02cb3921ff3fc"
|
||||||
|
dependencies = [
|
||||||
|
"windows-link",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "wit-bindgen"
|
||||||
|
version = "0.57.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "1ebf944e87a7c253233ad6766e082e3cd714b5d03812acc24c318f549614536e"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "wnaf"
|
||||||
|
version = "0.14.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ab12e7090f27e2ffd9322651492942d50c2926094af30601e1964337db39daf1"
|
||||||
|
dependencies = [
|
||||||
|
"ff",
|
||||||
|
"group",
|
||||||
|
"hybrid-array",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "zerocopy"
|
||||||
|
version = "0.8.54"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "b7cbbc0a705a0fd05cc3676525980d2bf5a9bc4adac6d6475209a7887cf59d19"
|
||||||
|
dependencies = [
|
||||||
|
"zerocopy-derive",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "zerocopy-derive"
|
||||||
|
version = "0.8.54"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e2e817b7b52d0c7358d3246da9d69935ebb18116b2b102b4230dac079b4862f5"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn 2.0.118",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "zeroize"
|
||||||
|
version = "1.9.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e13c156562582aa81c60cb29407084cdb54c4164760106ab78e6c5b0858cf64e"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "zmij"
|
||||||
|
version = "1.0.21"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "b8848ee67ecc8aedbaf3e4122217aff892639231befc6a1b58d29fff4c2cabaa"
|
||||||
+11
-11
@@ -4,12 +4,12 @@ categories = ["no-std", "algorithms", "cryptography"]
|
|||||||
description = "An implementation of a verifiable oblivious pseudorandom function (VOPRF)"
|
description = "An implementation of a verifiable oblivious pseudorandom function (VOPRF)"
|
||||||
edition = "2024"
|
edition = "2024"
|
||||||
keywords = ["oprf", "voprf", "cryptography", "oblivious-prf"]
|
keywords = ["oprf", "voprf", "cryptography", "oblivious-prf"]
|
||||||
license = "MIT"
|
license = "MIT OR Apache-2.0"
|
||||||
name = "voprf-vx"
|
name = "voprf-vx"
|
||||||
readme = "README.md"
|
readme = "README.md"
|
||||||
repository = "https://github.com/vexahub/voprf-vx/"
|
repository = "https://github.com/vexahub/voprf-vx/"
|
||||||
rust-version = "1.87"
|
rust-version = "1.87"
|
||||||
version = "1.0.0-pre.0"
|
version = "1.0.0"
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
alloc = []
|
alloc = []
|
||||||
@@ -22,35 +22,35 @@ serde = ["curve25519-dalek?/serde", "hybrid-array/serde", "dep:serde"]
|
|||||||
std = ["alloc"]
|
std = ["alloc"]
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
curve25519-dalek = { version = "5.0.0-rc", default-features = false, features = ["rand_core", "zeroize"], optional = true }
|
curve25519-dalek = { version = "5", default-features = false, features = ["rand_core", "zeroize"], optional = true }
|
||||||
derive-where = { version = "1", features = ["zeroize-on-drop"] }
|
derive-where = { version = "1", features = ["zeroize-on-drop"] }
|
||||||
digest = "0.11"
|
digest = { version = "0.11", features = ["zeroize"] }
|
||||||
displaydoc = { version = "0.2", default-features = false }
|
displaydoc = { version = "0.2", default-features = false }
|
||||||
elliptic-curve = { version = "0.14", features = [
|
elliptic-curve = { version = "0.14", features = [
|
||||||
"sec1",
|
"sec1",
|
||||||
] }
|
] }
|
||||||
hash2curve = "0.14"
|
hash2curve = "0.14"
|
||||||
hybrid-array = "0.4"
|
hybrid-array = { version = "0.4", features = ["zeroize"] }
|
||||||
rand_core = { version = "0.10", default-features = false, features = [] }
|
rand_core = { version = "0.10", default-features = false }
|
||||||
serde = { version = "1", default-features = false, features = [
|
serde = { version = "1", default-features = false, features = [
|
||||||
"derive",
|
"derive",
|
||||||
], optional = true }
|
], optional = true }
|
||||||
sha2 = { version = "0.11", default-features = false, optional = true }
|
sha2 = { version = "0.11", default-features = false, features = ["zeroize"], optional = true }
|
||||||
p256 = { version = "0.14.0-rc", default-features = false, features = ["hash2curve", "oprf"], optional = true }
|
p256 = { version = "0.14", default-features = false, features = ["hash2curve", "oprf"], optional = true }
|
||||||
subtle = { version = "2.6", default-features = false }
|
subtle = { version = "2.6", default-features = false }
|
||||||
zeroize = { version = "1.5", default-features = false }
|
zeroize = { version = "1.5", default-features = false }
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
hex = "0.4"
|
hex = "0.4"
|
||||||
p256 = { version = "0.14.0-rc", default-features = false, features = [
|
p256 = { version = "0.14", default-features = false, features = [
|
||||||
"hash2curve",
|
"hash2curve",
|
||||||
"oprf",
|
"oprf",
|
||||||
] }
|
] }
|
||||||
p384 = { version = "0.14.0-rc", default-features = false, features = [
|
p384 = { version = "0.14", default-features = false, features = [
|
||||||
"hash2curve",
|
"hash2curve",
|
||||||
"oprf",
|
"oprf",
|
||||||
] }
|
] }
|
||||||
p521 = { version = "0.14.0-rc", default-features = false, features = [
|
p521 = { version = "0.14", default-features = false, features = [
|
||||||
"hash2curve",
|
"hash2curve",
|
||||||
"oprf",
|
"oprf",
|
||||||
] }
|
] }
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ Installation
|
|||||||
Add the following line to the dependencies of your `Cargo.toml`:
|
Add the following line to the dependencies of your `Cargo.toml`:
|
||||||
|
|
||||||
```
|
```
|
||||||
voprf = { package = "voprf-vx", version = "1.0.0-pre.0" }
|
voprf-vx = "1.0.0"
|
||||||
```
|
```
|
||||||
|
|
||||||
### Minimum Supported Rust Version
|
### Minimum Supported Rust Version
|
||||||
|
|||||||
+2
-9
@@ -1,15 +1,10 @@
|
|||||||
|
// SPDX-License-Identifier: MIT OR Apache-2.0
|
||||||
|
// Copyright (c) VexaHub and contributors.
|
||||||
// Copyright (c) Meta Platforms, Inc. and affiliates.
|
// Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||||
//
|
|
||||||
// This source code is dual-licensed under either the MIT license found in the
|
|
||||||
// LICENSE-MIT file in the root directory of this source tree or the Apache
|
|
||||||
// License, Version 2.0 found in the LICENSE-APACHE file in the root directory
|
|
||||||
// of this source tree. You may select, at your option, one of the above-listed
|
|
||||||
// licenses.
|
|
||||||
|
|
||||||
//! Defines the CipherSuite trait to specify the underlying primitives for VOPRF
|
//! Defines the CipherSuite trait to specify the underlying primitives for VOPRF
|
||||||
|
|
||||||
use crate::Group;
|
use crate::Group;
|
||||||
use core::ops::Mul;
|
|
||||||
use digest::block_api::BlockSizeUser;
|
use digest::block_api::BlockSizeUser;
|
||||||
use digest::typenum::{IsLess, IsLessOrEqual, U256};
|
use digest::typenum::{IsLess, IsLessOrEqual, U256};
|
||||||
use digest::{FixedOutput, HashMarker, OutputSizeUser};
|
use digest::{FixedOutput, HashMarker, OutputSizeUser};
|
||||||
@@ -20,7 +15,6 @@ use hybrid_array::typenum::{IsGreaterOrEqual, Prod, True, U2};
|
|||||||
/// Configures the underlying primitives used in VOPRF
|
/// Configures the underlying primitives used in VOPRF
|
||||||
pub trait CipherSuite
|
pub trait CipherSuite
|
||||||
where
|
where
|
||||||
<Self::Group as Group>::SecurityLevel: Mul<U2>,
|
|
||||||
<Self::Hash as OutputSizeUser>::OutputSize: ArraySize
|
<Self::Hash as OutputSizeUser>::OutputSize: ArraySize
|
||||||
+ IsLess<U256>
|
+ IsLess<U256>
|
||||||
+ IsLessOrEqual<<Self::Hash as BlockSizeUser>::BlockSize, Output = True>
|
+ IsLessOrEqual<<Self::Hash as BlockSizeUser>::BlockSize, Output = True>
|
||||||
@@ -46,7 +40,6 @@ type OprfHash<T> =
|
|||||||
impl<T: OprfParameters> CipherSuite for T
|
impl<T: OprfParameters> CipherSuite for T
|
||||||
where
|
where
|
||||||
T: Group,
|
T: Group,
|
||||||
<T as Group>::SecurityLevel: Mul<U2>,
|
|
||||||
OprfHash<T>: BlockSizeUser + Default + FixedOutput + HashMarker,
|
OprfHash<T>: BlockSizeUser + Default + FixedOutput + HashMarker,
|
||||||
<OprfHash<T> as OutputSizeUser>::OutputSize: ArraySize
|
<OprfHash<T> as OutputSizeUser>::OutputSize: ArraySize
|
||||||
+ IsLess<U256>
|
+ IsLess<U256>
|
||||||
|
|||||||
+37
-7
@@ -1,14 +1,11 @@
|
|||||||
|
// SPDX-License-Identifier: MIT OR Apache-2.0
|
||||||
|
// Copyright (c) VexaHub and contributors.
|
||||||
// Copyright (c) Meta Platforms, Inc. and affiliates.
|
// Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||||
//
|
|
||||||
// This source code is dual-licensed under either the MIT license found in the
|
|
||||||
// LICENSE-MIT file in the root directory of this source tree or the Apache
|
|
||||||
// License, Version 2.0 found in the LICENSE-APACHE file in the root directory
|
|
||||||
// of this source tree. You may select, at your option, one of the above-listed
|
|
||||||
// licenses.
|
|
||||||
|
|
||||||
//! Common functionality between multiple OPRF modes.
|
//! Common functionality between multiple OPRF modes.
|
||||||
|
|
||||||
use core::convert::TryFrom;
|
use core::convert::TryFrom;
|
||||||
|
use core::iter::Map;
|
||||||
use core::ops::Add;
|
use core::ops::Add;
|
||||||
|
|
||||||
use derive_where::derive_where;
|
use derive_where::derive_where;
|
||||||
@@ -401,6 +398,12 @@ pub(crate) fn deterministic_blind_unchecked<CS: CipherSuite>(
|
|||||||
mode: Mode,
|
mode: Mode,
|
||||||
) -> Result<<CS::Group as Group>::Elem> {
|
) -> Result<<CS::Group as Group>::Elem> {
|
||||||
let hashed_point = hash_to_group::<CS>(input, mode)?;
|
let hashed_point = hash_to_group::<CS>(input, mode)?;
|
||||||
|
|
||||||
|
// Identity element would nullify blinding, revealing the input.
|
||||||
|
if CS::Group::is_identity_elem(hashed_point).into() {
|
||||||
|
return Err(Error::Input);
|
||||||
|
}
|
||||||
|
|
||||||
Ok(hashed_point * blind)
|
Ok(hashed_point * blind)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -447,6 +450,33 @@ pub(crate) fn server_evaluate_hash_input<CS: CipherSuite>(
|
|||||||
.finalize())
|
.finalize())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub(crate) type FinalizeAfterUnblindResult<'a, C, I, IE> = Map<
|
||||||
|
IE,
|
||||||
|
fn((I, <<C as CipherSuite>::Group as Group>::Elem)) -> Result<Output<<C as CipherSuite>::Hash>>,
|
||||||
|
>;
|
||||||
|
|
||||||
|
/// Returned values can only fail with [`Error::Input`].
|
||||||
|
pub(crate) fn finalize_after_unblind<
|
||||||
|
'a,
|
||||||
|
CS: CipherSuite,
|
||||||
|
I: AsRef<[u8]>,
|
||||||
|
IE: 'a + Iterator<Item = (I, <CS::Group as Group>::Elem)>,
|
||||||
|
>(
|
||||||
|
inputs_and_unblinded_elements: IE,
|
||||||
|
) -> FinalizeAfterUnblindResult<'a, CS, I, IE> {
|
||||||
|
inputs_and_unblinded_elements.map(|(input, unblinded_element)| {
|
||||||
|
let elem_len = <CS::Group as Group>::ElemLen::U16.to_be_bytes();
|
||||||
|
|
||||||
|
Ok(CS::Hash::new()
|
||||||
|
.chain_update(i2osp_2(input.as_ref().len()).map_err(|_| Error::Input)?)
|
||||||
|
.chain_update(input.as_ref())
|
||||||
|
.chain_update(elem_len)
|
||||||
|
.chain_update(CS::Group::serialize_elem(unblinded_element))
|
||||||
|
.chain_update(STR_FINALIZE)
|
||||||
|
.finalize())
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
pub(crate) struct Dst<L: ArraySize> {
|
pub(crate) struct Dst<L: ArraySize> {
|
||||||
dst_1: Array<u8, L>,
|
dst_1: Array<u8, L>,
|
||||||
dst_2: &'static [u8],
|
dst_2: &'static [u8],
|
||||||
@@ -462,7 +492,7 @@ impl<L: ArraySize> Dst<L> {
|
|||||||
// <https://www.rfc-editor.org/rfc/rfc9497#section-3.1>
|
// <https://www.rfc-editor.org/rfc/rfc9497#section-3.1>
|
||||||
let par_2 = ArrayN::<u8, 7>::from(STR_OPRF)
|
let par_2 = ArrayN::<u8, 7>::from(STR_OPRF)
|
||||||
.concat(ArrayN::<u8, 1>::from([mode.to_u8()]))
|
.concat(ArrayN::<u8, 1>::from([mode.to_u8()]))
|
||||||
.concat(ArrayN::<u8, 1>::from([b'-']));
|
.concat(ArrayN::<u8, 1>::from(*b"-"));
|
||||||
|
|
||||||
let dst_1 = par_1.concat(par_2);
|
let dst_1 = par_1.concat(par_2);
|
||||||
let dst_2 = CS::ID;
|
let dst_2 = CS::ID;
|
||||||
|
|||||||
+3
-7
@@ -1,10 +1,6 @@
|
|||||||
|
// SPDX-License-Identifier: MIT OR Apache-2.0
|
||||||
|
// Copyright (c) VexaHub and contributors.
|
||||||
// Copyright (c) Meta Platforms, Inc. and affiliates.
|
// Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||||
//
|
|
||||||
// This source code is dual-licensed under either the MIT license found in the
|
|
||||||
// LICENSE-MIT file in the root directory of this source tree or the Apache
|
|
||||||
// License, Version 2.0 found in the LICENSE-APACHE file in the root directory
|
|
||||||
// of this source tree. You may select, at your option, one of the above-listed
|
|
||||||
// licenses.
|
|
||||||
|
|
||||||
//! Errors which are produced during an execution of the protocol
|
//! Errors which are produced during an execution of the protocol
|
||||||
|
|
||||||
@@ -22,7 +18,7 @@ pub enum Error {
|
|||||||
DeriveKeyPair,
|
DeriveKeyPair,
|
||||||
/// Failure to deserialize bytes
|
/// Failure to deserialize bytes
|
||||||
Deserialization,
|
Deserialization,
|
||||||
/// Batched items are more then [`u16::MAX`] or length don't match.
|
/// Batched items are more than [`u16::MAX`] or length don't match.
|
||||||
Batch,
|
Batch,
|
||||||
/// In verifiable mode, occurs when the proof failed to verify
|
/// In verifiable mode, occurs when the proof failed to verify
|
||||||
ProofVerification,
|
ProofVerification,
|
||||||
|
|||||||
@@ -1,10 +1,6 @@
|
|||||||
|
// SPDX-License-Identifier: MIT OR Apache-2.0
|
||||||
|
// Copyright (c) VexaHub and contributors.
|
||||||
// Copyright (c) Meta Platforms, Inc. and affiliates.
|
// Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||||
//
|
|
||||||
// This source code is dual-licensed under either the MIT license found in the
|
|
||||||
// LICENSE-MIT file in the root directory of this source tree or the Apache
|
|
||||||
// License, Version 2.0 found in the LICENSE-APACHE file in the root directory
|
|
||||||
// of this source tree. You may select, at your option, one of the above-listed
|
|
||||||
// licenses.
|
|
||||||
|
|
||||||
use core::ops::{Add, Mul};
|
use core::ops::{Add, Mul};
|
||||||
use digest::block_api::BlockSizeUser;
|
use digest::block_api::BlockSizeUser;
|
||||||
@@ -67,9 +63,9 @@ where
|
|||||||
fn hash_to_scalar<H>(input: &[&[u8]], dst: &[&[u8]]) -> Result<Self::Scalar, InternalError>
|
fn hash_to_scalar<H>(input: &[&[u8]], dst: &[&[u8]]) -> Result<Self::Scalar, InternalError>
|
||||||
where
|
where
|
||||||
H: BlockSizeUser + Default + FixedOutput + HashMarker,
|
H: BlockSizeUser + Default + FixedOutput + HashMarker,
|
||||||
H::OutputSize: IsLess<U256> + IsLessOrEqual<H::BlockSize, Output = True>,
|
H::OutputSize: IsLess<U256>
|
||||||
C::SecurityLevel: Mul<U2>,
|
+ IsLessOrEqual<H::BlockSize, Output = True>
|
||||||
H::OutputSize: IsGreaterOrEqual<Prod<C::SecurityLevel, U2>, Output = True>,
|
+ IsGreaterOrEqual<Prod<C::SecurityLevel, U2>, Output = True>,
|
||||||
{
|
{
|
||||||
hash_to_scalar::<C, ExpandMsgXmd<H>, <C as MapToCurve>::Length>(input, dst)
|
hash_to_scalar::<C, ExpandMsgXmd<H>, <C as MapToCurve>::Length>(input, dst)
|
||||||
.map_err(|_| InternalError::Input)
|
.map_err(|_| InternalError::Input)
|
||||||
|
|||||||
+9
-13
@@ -1,10 +1,6 @@
|
|||||||
|
// SPDX-License-Identifier: MIT OR Apache-2.0
|
||||||
|
// Copyright (c) VexaHub and contributors.
|
||||||
// Copyright (c) Meta Platforms, Inc. and affiliates.
|
// Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||||
//
|
|
||||||
// This source code is dual-licensed under either the MIT license found in the
|
|
||||||
// LICENSE-MIT file in the root directory of this source tree or the Apache
|
|
||||||
// License, Version 2.0 found in the LICENSE-APACHE file in the root directory
|
|
||||||
// of this source tree. You may select, at your option, one of the above-listed
|
|
||||||
// licenses.
|
|
||||||
|
|
||||||
//! Defines the Group trait to specify the underlying prime order group
|
//! Defines the Group trait to specify the underlying prime order group
|
||||||
|
|
||||||
@@ -64,7 +60,7 @@ where
|
|||||||
/// Used to enforce `H::OutputSize >= 2 * SecurityLevel` in
|
/// Used to enforce `H::OutputSize >= 2 * SecurityLevel` in
|
||||||
/// `hash_to_curve` and `hash_to_scalar`, which corresponds to the
|
/// `hash_to_curve` and `hash_to_scalar`, which corresponds to the
|
||||||
/// `expand_message` requirement `len_in_bytes = 2 * k / 8`.
|
/// `expand_message` requirement `len_in_bytes = 2 * k / 8`.
|
||||||
type SecurityLevel: ArraySize;
|
type SecurityLevel: ArraySize + Mul<U2>;
|
||||||
|
|
||||||
/// Transforms a password and domain separation tag (DST) into a curve point
|
/// Transforms a password and domain separation tag (DST) into a curve point
|
||||||
///
|
///
|
||||||
@@ -74,9 +70,9 @@ where
|
|||||||
fn hash_to_curve<H>(input: &[&[u8]], dst: &[&[u8]]) -> Result<Self::Elem, InternalError>
|
fn hash_to_curve<H>(input: &[&[u8]], dst: &[&[u8]]) -> Result<Self::Elem, InternalError>
|
||||||
where
|
where
|
||||||
H: BlockSizeUser + Default + FixedOutput + HashMarker,
|
H: BlockSizeUser + Default + FixedOutput + HashMarker,
|
||||||
H::OutputSize: IsLess<U256> + IsLessOrEqual<H::BlockSize, Output = True>,
|
H::OutputSize: IsLess<U256>
|
||||||
Self::SecurityLevel: Mul<U2>,
|
+ IsLessOrEqual<H::BlockSize, Output = True>
|
||||||
H::OutputSize: IsGreaterOrEqual<Prod<Self::SecurityLevel, U2>, Output = True>;
|
+ IsGreaterOrEqual<Prod<Self::SecurityLevel, U2>, Output = True>;
|
||||||
|
|
||||||
/// Hashes a slice of pseudo-random bytes to a scalar
|
/// Hashes a slice of pseudo-random bytes to a scalar
|
||||||
///
|
///
|
||||||
@@ -86,9 +82,9 @@ where
|
|||||||
fn hash_to_scalar<H>(input: &[&[u8]], dst: &[&[u8]]) -> Result<Self::Scalar, InternalError>
|
fn hash_to_scalar<H>(input: &[&[u8]], dst: &[&[u8]]) -> Result<Self::Scalar, InternalError>
|
||||||
where
|
where
|
||||||
H: BlockSizeUser + Default + FixedOutput + HashMarker,
|
H: BlockSizeUser + Default + FixedOutput + HashMarker,
|
||||||
H::OutputSize: IsLess<U256> + IsLessOrEqual<H::BlockSize, Output = True>,
|
H::OutputSize: IsLess<U256>
|
||||||
Self::SecurityLevel: Mul<U2>,
|
+ IsLessOrEqual<H::BlockSize, Output = True>
|
||||||
H::OutputSize: IsGreaterOrEqual<Prod<Self::SecurityLevel, U2>, Output = True>;
|
+ IsGreaterOrEqual<Prod<Self::SecurityLevel, U2>, Output = True>;
|
||||||
|
|
||||||
/// Get the base point for the group
|
/// Get the base point for the group
|
||||||
fn base_elem() -> Self::Elem;
|
fn base_elem() -> Self::Elem;
|
||||||
|
|||||||
+30
-33
@@ -1,13 +1,9 @@
|
|||||||
|
// SPDX-License-Identifier: MIT OR Apache-2.0
|
||||||
|
// Copyright (c) VexaHub and contributors.
|
||||||
// Copyright (c) Meta Platforms, Inc. and affiliates.
|
// Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||||
//
|
|
||||||
// This source code is dual-licensed under either the MIT license found in the
|
|
||||||
// LICENSE-MIT file in the root directory of this source tree or the Apache
|
|
||||||
// License, Version 2.0 found in the LICENSE-APACHE file in the root directory
|
|
||||||
// of this source tree. You may select, at your option, one of the above-listed
|
|
||||||
// licenses.
|
|
||||||
|
|
||||||
use core::num::NonZeroU16;
|
use core::num::NonZeroU16;
|
||||||
use core::ops::Mul;
|
|
||||||
use curve25519_dalek::constants::RISTRETTO_BASEPOINT_POINT;
|
use curve25519_dalek::constants::RISTRETTO_BASEPOINT_POINT;
|
||||||
use curve25519_dalek::ristretto::{CompressedRistretto, RistrettoPoint};
|
use curve25519_dalek::ristretto::{CompressedRistretto, RistrettoPoint};
|
||||||
use curve25519_dalek::scalar::Scalar;
|
use curve25519_dalek::scalar::Scalar;
|
||||||
@@ -54,20 +50,11 @@ impl Group for Ristretto255 {
|
|||||||
fn hash_to_curve<H>(input: &[&[u8]], dst: &[&[u8]]) -> Result<Self::Elem, InternalError>
|
fn hash_to_curve<H>(input: &[&[u8]], dst: &[&[u8]]) -> Result<Self::Elem, InternalError>
|
||||||
where
|
where
|
||||||
H: BlockSizeUser + Default + FixedOutput + HashMarker,
|
H: BlockSizeUser + Default + FixedOutput + HashMarker,
|
||||||
H::OutputSize: IsLess<U256> + IsLessOrEqual<H::BlockSize, Output = True>,
|
H::OutputSize: IsLess<U256>
|
||||||
Self::SecurityLevel: Mul<U2>,
|
+ IsLessOrEqual<H::BlockSize, Output = True>
|
||||||
H::OutputSize: IsGreaterOrEqual<Prod<Self::SecurityLevel, U2>, Output = True>,
|
+ IsGreaterOrEqual<Prod<Self::SecurityLevel, U2>, Output = True>,
|
||||||
{
|
{
|
||||||
let mut uniform_bytes = [0u8; 64];
|
let uniform_bytes = expand_uniform_bytes::<H>(input, dst)?;
|
||||||
|
|
||||||
<ExpandMsgXmd<H> as ExpandMsg<U16>>::expand_message(
|
|
||||||
input,
|
|
||||||
dst,
|
|
||||||
NonZeroU16::new(64).unwrap(),
|
|
||||||
)
|
|
||||||
.map_err(|_| InternalError::Input)?
|
|
||||||
.fill_bytes(&mut uniform_bytes)
|
|
||||||
.map_err(|_| InternalError::Input)?;
|
|
||||||
|
|
||||||
Ok(RistrettoPoint::from_uniform_bytes(&uniform_bytes))
|
Ok(RistrettoPoint::from_uniform_bytes(&uniform_bytes))
|
||||||
}
|
}
|
||||||
@@ -77,20 +64,11 @@ impl Group for Ristretto255 {
|
|||||||
fn hash_to_scalar<H>(input: &[&[u8]], dst: &[&[u8]]) -> Result<Self::Scalar, InternalError>
|
fn hash_to_scalar<H>(input: &[&[u8]], dst: &[&[u8]]) -> Result<Self::Scalar, InternalError>
|
||||||
where
|
where
|
||||||
H: BlockSizeUser + Default + FixedOutput + HashMarker,
|
H: BlockSizeUser + Default + FixedOutput + HashMarker,
|
||||||
H::OutputSize: IsLess<U256> + IsLessOrEqual<H::BlockSize, Output = True>,
|
H::OutputSize: IsLess<U256>
|
||||||
Self::SecurityLevel: Mul<U2>,
|
+ IsLessOrEqual<H::BlockSize, Output = True>
|
||||||
H::OutputSize: IsGreaterOrEqual<Prod<Self::SecurityLevel, U2>, Output = True>,
|
+ IsGreaterOrEqual<Prod<Self::SecurityLevel, U2>, Output = True>,
|
||||||
{
|
{
|
||||||
let mut uniform_bytes = [0u8; 64];
|
let uniform_bytes = expand_uniform_bytes::<H>(input, dst)?;
|
||||||
|
|
||||||
<ExpandMsgXmd<H> as ExpandMsg<U16>>::expand_message(
|
|
||||||
input,
|
|
||||||
dst,
|
|
||||||
NonZeroU16::new(64).unwrap(),
|
|
||||||
)
|
|
||||||
.map_err(|_| InternalError::Input)?
|
|
||||||
.fill_bytes(&mut uniform_bytes)
|
|
||||||
.map_err(|_| InternalError::Input)?;
|
|
||||||
|
|
||||||
Ok(Scalar::from_bytes_mod_order_wide(&uniform_bytes))
|
Ok(Scalar::from_bytes_mod_order_wide(&uniform_bytes))
|
||||||
}
|
}
|
||||||
@@ -154,3 +132,22 @@ impl Group for Ristretto255 {
|
|||||||
.ok_or(Error::Deserialization)
|
.ok_or(Error::Deserialization)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// HELPERS
|
||||||
|
|
||||||
|
fn expand_uniform_bytes<H>(input: &[&[u8]], dst: &[&[u8]]) -> Result<[u8; 64], InternalError>
|
||||||
|
where
|
||||||
|
H: BlockSizeUser + Default + FixedOutput + HashMarker,
|
||||||
|
H::OutputSize: IsLess<U256>
|
||||||
|
+ IsLessOrEqual<H::BlockSize, Output = True>
|
||||||
|
+ IsGreaterOrEqual<Prod<U16, U2>, Output = True>,
|
||||||
|
{
|
||||||
|
let mut uniform_bytes = [0u8; 64];
|
||||||
|
|
||||||
|
<ExpandMsgXmd<H> as ExpandMsg<U16>>::expand_message(input, dst, NonZeroU16::new(64).unwrap())
|
||||||
|
.map_err(|_| InternalError::Input)?
|
||||||
|
.fill_bytes(&mut uniform_bytes)
|
||||||
|
.map_err(|_| InternalError::Input)?;
|
||||||
|
|
||||||
|
Ok(uniform_bytes)
|
||||||
|
}
|
||||||
|
|||||||
+2
-6
@@ -1,10 +1,6 @@
|
|||||||
|
// SPDX-License-Identifier: MIT OR Apache-2.0
|
||||||
|
// Copyright (c) VexaHub and contributors.
|
||||||
// Copyright (c) Meta Platforms, Inc. and affiliates.
|
// Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||||
//
|
|
||||||
// This source code is dual-licensed under either the MIT license found in the
|
|
||||||
// LICENSE-MIT file in the root directory of this source tree or the Apache
|
|
||||||
// License, Version 2.0 found in the LICENSE-APACHE file in the root directory
|
|
||||||
// of this source tree. You may select, at your option, one of the above-listed
|
|
||||||
// licenses.
|
|
||||||
|
|
||||||
//! Includes a series of tests for the group implementations
|
//! Includes a series of tests for the group implementations
|
||||||
|
|
||||||
|
|||||||
+2
-6
@@ -1,10 +1,6 @@
|
|||||||
|
// SPDX-License-Identifier: MIT OR Apache-2.0
|
||||||
|
// Copyright (c) VexaHub and contributors.
|
||||||
// Copyright (c) Meta Platforms, Inc. and affiliates.
|
// Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||||
//
|
|
||||||
// This source code is dual-licensed under either the MIT license found in the
|
|
||||||
// LICENSE-MIT file in the root directory of this source tree or the Apache
|
|
||||||
// License, Version 2.0 found in the LICENSE-APACHE file in the root directory
|
|
||||||
// of this source tree. You may select, at your option, one of the above-listed
|
|
||||||
// licenses.
|
|
||||||
|
|
||||||
//! An implementation of a verifiable oblivious pseudorandom function (VOPRF)
|
//! An implementation of a verifiable oblivious pseudorandom function (VOPRF)
|
||||||
//!
|
//!
|
||||||
|
|||||||
+17
-109
@@ -1,24 +1,19 @@
|
|||||||
|
// SPDX-License-Identifier: MIT OR Apache-2.0
|
||||||
|
// Copyright (c) VexaHub and contributors.
|
||||||
// Copyright (c) Meta Platforms, Inc. and affiliates.
|
// Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||||
//
|
|
||||||
// This source code is dual-licensed under either the MIT license found in the
|
|
||||||
// LICENSE-MIT file in the root directory of this source tree or the Apache
|
|
||||||
// License, Version 2.0 found in the LICENSE-APACHE file in the root directory
|
|
||||||
// of this source tree. You may select, at your option, one of the above-listed
|
|
||||||
// licenses.
|
|
||||||
|
|
||||||
//! Contains the main OPRF API
|
//! Contains the main OPRF API
|
||||||
|
|
||||||
use core::iter::{self, Map};
|
use core::iter::{self};
|
||||||
|
|
||||||
use derive_where::derive_where;
|
use derive_where::derive_where;
|
||||||
use digest::{Digest, Output};
|
use digest::Output;
|
||||||
use hybrid_array::Array;
|
use hybrid_array::Array;
|
||||||
use hybrid_array::typenum::Unsigned;
|
|
||||||
use rand_core::{TryCryptoRng, TryRng};
|
use rand_core::{TryCryptoRng, TryRng};
|
||||||
|
|
||||||
use crate::common::{
|
use crate::common::{
|
||||||
BlindedElement, EvaluationElement, Mode, STR_FINALIZE, derive_key_internal,
|
BlindedElement, EvaluationElement, Mode, derive_key_internal, deterministic_blind_unchecked,
|
||||||
deterministic_blind_unchecked, hash_to_group, i2osp_2, server_evaluate_hash_input,
|
finalize_after_unblind, hash_to_group, server_evaluate_hash_input,
|
||||||
};
|
};
|
||||||
#[cfg(feature = "serde")]
|
#[cfg(feature = "serde")]
|
||||||
use crate::serialization::serde::Scalar;
|
use crate::serialization::serde::Scalar;
|
||||||
@@ -124,7 +119,7 @@ impl<CS: CipherSuite> OprfClient<CS> {
|
|||||||
) -> Result<Output<CS::Hash>> {
|
) -> Result<Output<CS::Hash>> {
|
||||||
let unblinded_element = evaluation_element.0 * &CS::Group::invert_scalar(self.blind);
|
let unblinded_element = evaluation_element.0 * &CS::Group::invert_scalar(self.blind);
|
||||||
let mut outputs =
|
let mut outputs =
|
||||||
finalize_after_unblind::<CS, _, _>(iter::once((input, unblinded_element)), &[]);
|
finalize_after_unblind::<CS, _, _>(iter::once((input, unblinded_element)));
|
||||||
outputs.next().unwrap()
|
outputs.next().unwrap()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -221,43 +216,6 @@ pub struct OprfClientBlindResult<CS: CipherSuite> {
|
|||||||
pub message: BlindedElement<CS>,
|
pub message: BlindedElement<CS>,
|
||||||
}
|
}
|
||||||
|
|
||||||
/////////////////////
|
|
||||||
// Inner functions //
|
|
||||||
// =============== //
|
|
||||||
/////////////////////
|
|
||||||
|
|
||||||
type FinalizeAfterUnblindResult<'a, C, I, IE> = Map<
|
|
||||||
IE,
|
|
||||||
fn((I, <<C as CipherSuite>::Group as Group>::Elem)) -> Result<Output<<C as CipherSuite>::Hash>>,
|
|
||||||
>;
|
|
||||||
|
|
||||||
/// Returned values can only fail with [`Error::Input`].
|
|
||||||
fn finalize_after_unblind<
|
|
||||||
'a,
|
|
||||||
CS: CipherSuite,
|
|
||||||
I: AsRef<[u8]>,
|
|
||||||
IE: 'a + Iterator<Item = (I, <CS::Group as Group>::Elem)>,
|
|
||||||
>(
|
|
||||||
inputs_and_unblinded_elements: IE,
|
|
||||||
_unused: &'a [u8],
|
|
||||||
) -> FinalizeAfterUnblindResult<'a, CS, I, IE> {
|
|
||||||
inputs_and_unblinded_elements.map(|(input, unblinded_element)| {
|
|
||||||
let elem_len = <CS::Group as Group>::ElemLen::U16.to_be_bytes();
|
|
||||||
|
|
||||||
// hashInput = I2OSP(len(input), 2) || input ||
|
|
||||||
// I2OSP(len(unblindedElement), 2) || unblindedElement ||
|
|
||||||
// "Finalize"
|
|
||||||
// return Hash(hashInput)
|
|
||||||
Ok(CS::Hash::new()
|
|
||||||
.chain_update(i2osp_2(input.as_ref().len()).map_err(|_| Error::Input)?)
|
|
||||||
.chain_update(input.as_ref())
|
|
||||||
.chain_update(elem_len)
|
|
||||||
.chain_update(CS::Group::serialize_elem(unblinded_element))
|
|
||||||
.chain_update(STR_FINALIZE)
|
|
||||||
.finalize())
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
///////////
|
///////////
|
||||||
// Tests //
|
// Tests //
|
||||||
// ===== //
|
// ===== //
|
||||||
@@ -273,23 +231,7 @@ mod tests {
|
|||||||
use super::*;
|
use super::*;
|
||||||
use crate::Group;
|
use crate::Group;
|
||||||
use crate::common::{Dst, STR_HASH_TO_GROUP};
|
use crate::common::{Dst, STR_HASH_TO_GROUP};
|
||||||
|
use crate::tests::helpers::prf;
|
||||||
fn prf<CS: CipherSuite>(
|
|
||||||
input: &[u8],
|
|
||||||
key: <CS::Group as Group>::Scalar,
|
|
||||||
info: &[u8],
|
|
||||||
mode: Mode,
|
|
||||||
) -> Output<CS::Hash> {
|
|
||||||
let dst = Dst::new::<CS, _>(STR_HASH_TO_GROUP, mode);
|
|
||||||
let point = CS::Group::hash_to_curve::<CS::Hash>(&[input], &dst.as_dst()).unwrap();
|
|
||||||
|
|
||||||
let res = point * &key;
|
|
||||||
|
|
||||||
finalize_after_unblind::<CS, _, _>(iter::once((input, res)), info)
|
|
||||||
.next()
|
|
||||||
.unwrap()
|
|
||||||
.unwrap()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn base_retrieval<CS: CipherSuite>() {
|
fn base_retrieval<CS: CipherSuite>() {
|
||||||
let input = b"input";
|
let input = b"input";
|
||||||
@@ -298,7 +240,7 @@ mod tests {
|
|||||||
let server = OprfServer::<CS>::new(&mut rng).unwrap();
|
let server = OprfServer::<CS>::new(&mut rng).unwrap();
|
||||||
let message = server.blind_evaluate(&client_blind_result.message);
|
let message = server.blind_evaluate(&client_blind_result.message);
|
||||||
let client_finalize_result = client_blind_result.state.finalize(input, &message).unwrap();
|
let client_finalize_result = client_blind_result.state.finalize(input, &message).unwrap();
|
||||||
let res2 = prf::<CS>(input, server.get_private_key(), &[], Mode::Oprf);
|
let res2 = prf::<CS>(input, server.get_private_key(), Mode::Oprf);
|
||||||
assert_eq!(client_finalize_result, res2);
|
assert_eq!(client_finalize_result, res2);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -314,7 +256,7 @@ mod tests {
|
|||||||
|
|
||||||
let dst = Dst::new::<CS, _>(STR_HASH_TO_GROUP, Mode::Oprf);
|
let dst = Dst::new::<CS, _>(STR_HASH_TO_GROUP, Mode::Oprf);
|
||||||
let point = CS::Group::hash_to_curve::<CS::Hash>(&[&input], &dst.as_dst()).unwrap();
|
let point = CS::Group::hash_to_curve::<CS::Hash>(&[&input], &dst.as_dst()).unwrap();
|
||||||
let res2 = finalize_after_unblind::<CS, _, _>(iter::once((input.as_ref(), point)), &[])
|
let res2 = finalize_after_unblind::<CS, _, _>(iter::once((input.as_ref(), point)))
|
||||||
.next()
|
.next()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.unwrap();
|
.unwrap();
|
||||||
@@ -375,45 +317,11 @@ mod tests {
|
|||||||
assert!(message.serialize().iter().all(|&x| x == 0));
|
assert!(message.serialize().iter().all(|&x| x == 0));
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
crate::tests::test_all_curves!(
|
||||||
fn test_functionality() -> Result<()> {
|
base_retrieval,
|
||||||
use p256::NistP256;
|
base_inversion_unsalted,
|
||||||
use p384::NistP384;
|
server_evaluate,
|
||||||
use p521::NistP521;
|
zeroize_oprf_client,
|
||||||
|
zeroize_oprf_server,
|
||||||
#[cfg(feature = "ristretto255")]
|
);
|
||||||
{
|
|
||||||
use crate::Ristretto255;
|
|
||||||
|
|
||||||
base_retrieval::<Ristretto255>();
|
|
||||||
base_inversion_unsalted::<Ristretto255>();
|
|
||||||
server_evaluate::<Ristretto255>();
|
|
||||||
|
|
||||||
zeroize_oprf_client::<Ristretto255>();
|
|
||||||
zeroize_oprf_server::<Ristretto255>();
|
|
||||||
}
|
|
||||||
|
|
||||||
base_retrieval::<NistP256>();
|
|
||||||
base_inversion_unsalted::<NistP256>();
|
|
||||||
server_evaluate::<NistP256>();
|
|
||||||
|
|
||||||
zeroize_oprf_client::<NistP256>();
|
|
||||||
zeroize_oprf_server::<NistP256>();
|
|
||||||
|
|
||||||
base_retrieval::<NistP384>();
|
|
||||||
base_inversion_unsalted::<NistP384>();
|
|
||||||
server_evaluate::<NistP384>();
|
|
||||||
|
|
||||||
zeroize_oprf_client::<NistP384>();
|
|
||||||
zeroize_oprf_server::<NistP384>();
|
|
||||||
|
|
||||||
base_retrieval::<NistP521>();
|
|
||||||
base_inversion_unsalted::<NistP521>();
|
|
||||||
server_evaluate::<NistP521>();
|
|
||||||
|
|
||||||
zeroize_oprf_client::<NistP521>();
|
|
||||||
zeroize_oprf_server::<NistP521>();
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
+9
-47
@@ -1,10 +1,6 @@
|
|||||||
|
// SPDX-License-Identifier: MIT OR Apache-2.0
|
||||||
|
// Copyright (c) VexaHub and contributors.
|
||||||
// Copyright (c) Meta Platforms, Inc. and affiliates.
|
// Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||||
//
|
|
||||||
// This source code is dual-licensed under either the MIT license found in the
|
|
||||||
// LICENSE-MIT file in the root directory of this source tree or the Apache
|
|
||||||
// License, Version 2.0 found in the LICENSE-APACHE file in the root directory
|
|
||||||
// of this source tree. You may select, at your option, one of the above-listed
|
|
||||||
// licenses.
|
|
||||||
|
|
||||||
//! Contains the main POPRF API
|
//! Contains the main POPRF API
|
||||||
|
|
||||||
@@ -877,45 +873,11 @@ mod tests {
|
|||||||
assert!(proof.serialize().iter().all(|&x| x == 0));
|
assert!(proof.serialize().iter().all(|&x| x == 0));
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
crate::tests::test_all_curves!(
|
||||||
fn test_functionality() -> Result<()> {
|
verifiable_retrieval,
|
||||||
use p256::NistP256;
|
verifiable_bad_public_key,
|
||||||
use p384::NistP384;
|
verifiable_server_evaluate,
|
||||||
use p521::NistP521;
|
zeroize_verifiable_client,
|
||||||
|
zeroize_verifiable_server,
|
||||||
#[cfg(feature = "ristretto255")]
|
);
|
||||||
{
|
|
||||||
use crate::Ristretto255;
|
|
||||||
|
|
||||||
verifiable_retrieval::<Ristretto255>();
|
|
||||||
verifiable_bad_public_key::<Ristretto255>();
|
|
||||||
verifiable_server_evaluate::<Ristretto255>();
|
|
||||||
|
|
||||||
zeroize_verifiable_client::<Ristretto255>();
|
|
||||||
zeroize_verifiable_server::<Ristretto255>();
|
|
||||||
}
|
|
||||||
|
|
||||||
verifiable_retrieval::<NistP256>();
|
|
||||||
verifiable_bad_public_key::<NistP256>();
|
|
||||||
verifiable_server_evaluate::<NistP256>();
|
|
||||||
|
|
||||||
zeroize_verifiable_client::<NistP256>();
|
|
||||||
zeroize_verifiable_server::<NistP256>();
|
|
||||||
|
|
||||||
verifiable_retrieval::<NistP384>();
|
|
||||||
verifiable_bad_public_key::<NistP384>();
|
|
||||||
verifiable_server_evaluate::<NistP384>();
|
|
||||||
|
|
||||||
zeroize_verifiable_client::<NistP384>();
|
|
||||||
zeroize_verifiable_server::<NistP384>();
|
|
||||||
|
|
||||||
verifiable_retrieval::<NistP521>();
|
|
||||||
verifiable_bad_public_key::<NistP521>();
|
|
||||||
verifiable_server_evaluate::<NistP521>();
|
|
||||||
|
|
||||||
zeroize_verifiable_client::<NistP521>();
|
|
||||||
zeroize_verifiable_server::<NistP521>();
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
+292
-222
@@ -1,10 +1,6 @@
|
|||||||
|
// SPDX-License-Identifier: MIT OR Apache-2.0
|
||||||
|
// Copyright (c) VexaHub and contributors.
|
||||||
// Copyright (c) Meta Platforms, Inc. and affiliates.
|
// Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||||
//
|
|
||||||
// This source code is dual-licensed under either the MIT license found in the
|
|
||||||
// LICENSE-MIT file in the root directory of this source tree or the Apache
|
|
||||||
// License, Version 2.0 found in the LICENSE-APACHE file in the root directory
|
|
||||||
// of this source tree. You may select, at your option, one of the above-listed
|
|
||||||
// licenses.
|
|
||||||
|
|
||||||
//! Handles the serialization of each of the components used in the VOPRF
|
//! Handles the serialization of each of the components used in the VOPRF
|
||||||
//! protocol
|
//! protocol
|
||||||
@@ -17,219 +13,10 @@ use crate::{
|
|||||||
PoprfClient, PoprfServer, Proof, Result, VoprfClient, VoprfServer,
|
PoprfClient, PoprfServer, Proof, Result, VoprfClient, VoprfServer,
|
||||||
};
|
};
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////
|
/////////////////////////////
|
||||||
// Serialization and Deserialization for High-Level API //
|
// Deserialization Helpers //
|
||||||
// ==================================================== //
|
// ======================= //
|
||||||
//////////////////////////////////////////////////////////
|
/////////////////////////////
|
||||||
|
|
||||||
/// Length of [`OprfClient`] in bytes for serialization.
|
|
||||||
pub type OprfClientLen<CS> = <<CS as CipherSuite>::Group as Group>::ScalarLen;
|
|
||||||
|
|
||||||
impl<CS: CipherSuite> OprfClient<CS> {
|
|
||||||
/// Serialization into bytes
|
|
||||||
pub fn serialize(&self) -> Array<u8, OprfClientLen<CS>> {
|
|
||||||
CS::Group::serialize_scalar(self.blind)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Deserialization from bytes
|
|
||||||
///
|
|
||||||
/// # Errors
|
|
||||||
/// [`Error::Deserialization`] if failed to deserialize `input`.
|
|
||||||
pub fn deserialize(mut input: &[u8]) -> Result<Self> {
|
|
||||||
let blind = deserialize_scalar::<CS::Group>(&mut input)?;
|
|
||||||
|
|
||||||
Ok(Self { blind })
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Length of [`VoprfClient`] in bytes for serialization.
|
|
||||||
pub type VoprfClientLen<CS> = Sum<
|
|
||||||
<<CS as CipherSuite>::Group as Group>::ScalarLen,
|
|
||||||
<<CS as CipherSuite>::Group as Group>::ElemLen,
|
|
||||||
>;
|
|
||||||
|
|
||||||
impl<CS: CipherSuite> VoprfClient<CS> {
|
|
||||||
/// Serialization into bytes
|
|
||||||
pub fn serialize(&self) -> Array<u8, VoprfClientLen<CS>> {
|
|
||||||
<CS::Group as Group>::serialize_scalar(self.blind)
|
|
||||||
.concat(<CS::Group as Group>::serialize_elem(self.blinded_element))
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Deserialization from bytes
|
|
||||||
///
|
|
||||||
/// # Errors
|
|
||||||
/// [`Error::Deserialization`] if failed to deserialize `input`.
|
|
||||||
pub fn deserialize(mut input: &[u8]) -> Result<Self> {
|
|
||||||
let blind = deserialize_scalar::<CS::Group>(&mut input)?;
|
|
||||||
let blinded_element = deserialize_elem::<CS::Group>(&mut input)?;
|
|
||||||
|
|
||||||
Ok(Self {
|
|
||||||
blind,
|
|
||||||
blinded_element,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Length of [`PoprfClient`] in bytes for serialization.
|
|
||||||
pub type PoprfClientLen<CS> = Sum<
|
|
||||||
<<CS as CipherSuite>::Group as Group>::ScalarLen,
|
|
||||||
<<CS as CipherSuite>::Group as Group>::ElemLen,
|
|
||||||
>;
|
|
||||||
|
|
||||||
impl<CS: CipherSuite> PoprfClient<CS> {
|
|
||||||
/// Serialization into bytes
|
|
||||||
pub fn serialize(&self) -> Array<u8, PoprfClientLen<CS>> {
|
|
||||||
<CS::Group as Group>::serialize_scalar(self.blind)
|
|
||||||
.concat(<CS::Group as Group>::serialize_elem(self.blinded_element))
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Deserialization from bytes
|
|
||||||
///
|
|
||||||
/// # Errors
|
|
||||||
/// [`Error::Deserialization`] if failed to deserialize `input`.
|
|
||||||
pub fn deserialize(mut input: &[u8]) -> Result<Self> {
|
|
||||||
let blind = deserialize_scalar::<CS::Group>(&mut input)?;
|
|
||||||
let blinded_element = deserialize_elem::<CS::Group>(&mut input)?;
|
|
||||||
|
|
||||||
Ok(Self {
|
|
||||||
blind,
|
|
||||||
blinded_element,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Length of [`OprfServer`] in bytes for serialization.
|
|
||||||
pub type OprfServerLen<CS> = <<CS as CipherSuite>::Group as Group>::ScalarLen;
|
|
||||||
|
|
||||||
impl<CS: CipherSuite> OprfServer<CS> {
|
|
||||||
/// Serialization into bytes
|
|
||||||
pub fn serialize(&self) -> Array<u8, OprfServerLen<CS>> {
|
|
||||||
CS::Group::serialize_scalar(self.sk)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Deserialization from bytes
|
|
||||||
///
|
|
||||||
/// # Errors
|
|
||||||
/// [`Error::Deserialization`] if failed to deserialize `input`.
|
|
||||||
pub fn deserialize(mut input: &[u8]) -> Result<Self> {
|
|
||||||
let sk = deserialize_scalar::<CS::Group>(&mut input)?;
|
|
||||||
|
|
||||||
Ok(Self { sk })
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Length of [`VoprfServer`] in bytes for serialization.
|
|
||||||
pub type VoprfServerLen<CS> = Sum<
|
|
||||||
<<CS as CipherSuite>::Group as Group>::ScalarLen,
|
|
||||||
<<CS as CipherSuite>::Group as Group>::ElemLen,
|
|
||||||
>;
|
|
||||||
|
|
||||||
impl<CS: CipherSuite> VoprfServer<CS> {
|
|
||||||
/// Serialization into bytes
|
|
||||||
pub fn serialize(&self) -> Array<u8, VoprfServerLen<CS>> {
|
|
||||||
CS::Group::serialize_scalar(self.sk).concat(CS::Group::serialize_elem(self.pk))
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Deserialization from bytes
|
|
||||||
///
|
|
||||||
/// # Errors
|
|
||||||
/// [`Error::Deserialization`] if failed to deserialize `input`.
|
|
||||||
pub fn deserialize(mut input: &[u8]) -> Result<Self> {
|
|
||||||
let sk = deserialize_scalar::<CS::Group>(&mut input)?;
|
|
||||||
let pk = deserialize_elem::<CS::Group>(&mut input)?;
|
|
||||||
|
|
||||||
Ok(Self { sk, pk })
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Length of [`PoprfServer`] in bytes for serialization.
|
|
||||||
pub type PoprfServerLen<CS> = Sum<
|
|
||||||
<<CS as CipherSuite>::Group as Group>::ScalarLen,
|
|
||||||
<<CS as CipherSuite>::Group as Group>::ElemLen,
|
|
||||||
>;
|
|
||||||
|
|
||||||
impl<CS: CipherSuite> PoprfServer<CS> {
|
|
||||||
/// Serialization into bytes
|
|
||||||
pub fn serialize(&self) -> Array<u8, PoprfServerLen<CS>> {
|
|
||||||
CS::Group::serialize_scalar(self.sk).concat(CS::Group::serialize_elem(self.pk))
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Deserialization from bytes
|
|
||||||
///
|
|
||||||
/// # Errors
|
|
||||||
/// [`Error::Deserialization`] if failed to deserialize `input`.
|
|
||||||
pub fn deserialize(mut input: &[u8]) -> Result<Self> {
|
|
||||||
let sk = deserialize_scalar::<CS::Group>(&mut input)?;
|
|
||||||
let pk = deserialize_elem::<CS::Group>(&mut input)?;
|
|
||||||
|
|
||||||
Ok(Self { sk, pk })
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Length of [`Proof`] in bytes for serialization.
|
|
||||||
pub type ProofLen<CS> = Sum<
|
|
||||||
<<CS as CipherSuite>::Group as Group>::ScalarLen,
|
|
||||||
<<CS as CipherSuite>::Group as Group>::ScalarLen,
|
|
||||||
>;
|
|
||||||
|
|
||||||
impl<CS: CipherSuite> Proof<CS> {
|
|
||||||
/// Serialization into bytes
|
|
||||||
pub fn serialize(&self) -> Array<u8, ProofLen<CS>> {
|
|
||||||
CS::Group::serialize_scalar(self.c_scalar)
|
|
||||||
.concat(CS::Group::serialize_scalar(self.s_scalar))
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Deserialization from bytes
|
|
||||||
///
|
|
||||||
/// # Errors
|
|
||||||
/// [`Error::Deserialization`] if failed to deserialize `input`.
|
|
||||||
pub fn deserialize(mut input: &[u8]) -> Result<Self> {
|
|
||||||
let c_scalar = deserialize_scalar::<CS::Group>(&mut input)?;
|
|
||||||
let s_scalar = deserialize_scalar::<CS::Group>(&mut input)?;
|
|
||||||
|
|
||||||
Ok(Proof { c_scalar, s_scalar })
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Length of [`BlindedElement`] in bytes for serialization.
|
|
||||||
pub type BlindedElementLen<CS> = <<CS as CipherSuite>::Group as Group>::ElemLen;
|
|
||||||
|
|
||||||
impl<CS: CipherSuite> BlindedElement<CS> {
|
|
||||||
/// Serialization into bytes
|
|
||||||
pub fn serialize(&self) -> Array<u8, BlindedElementLen<CS>> {
|
|
||||||
CS::Group::serialize_elem(self.0)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Deserialization from bytes
|
|
||||||
///
|
|
||||||
/// # Errors
|
|
||||||
/// [`Error::Deserialization`] if failed to deserialize `input`.
|
|
||||||
pub fn deserialize(mut input: &[u8]) -> Result<Self> {
|
|
||||||
let value = deserialize_elem::<CS::Group>(&mut input)?;
|
|
||||||
|
|
||||||
Ok(Self(value))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Length of [`EvaluationElement`] in bytes for serialization.
|
|
||||||
pub type EvaluationElementLen<CS> = <<CS as CipherSuite>::Group as Group>::ElemLen;
|
|
||||||
|
|
||||||
impl<CS: CipherSuite> EvaluationElement<CS> {
|
|
||||||
/// Serialization into bytes
|
|
||||||
pub fn serialize(&self) -> Array<u8, EvaluationElementLen<CS>> {
|
|
||||||
CS::Group::serialize_elem(self.0)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Deserialization from bytes
|
|
||||||
///
|
|
||||||
/// # Errors
|
|
||||||
/// [`Error::Deserialization`] if failed to deserialize `input`.
|
|
||||||
pub fn deserialize(mut input: &[u8]) -> Result<Self> {
|
|
||||||
let value = deserialize_elem::<CS::Group>(&mut input)?;
|
|
||||||
|
|
||||||
Ok(Self(value))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn deserialize_elem<G: Group>(input: &mut &[u8]) -> Result<G::Elem> {
|
fn deserialize_elem<G: Group>(input: &mut &[u8]) -> Result<G::Elem> {
|
||||||
let input = input
|
let input = input
|
||||||
@@ -261,6 +48,158 @@ impl<T> SliceExt for [T] {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//////////////////////////////
|
||||||
|
// Serialization Macros //
|
||||||
|
// ======================== //
|
||||||
|
//////////////////////////////
|
||||||
|
|
||||||
|
macro_rules! impl_serde_scalar {
|
||||||
|
($ty:ident, $len:ident, $field:ident) => {
|
||||||
|
/// Length in bytes for serialization.
|
||||||
|
pub type $len<CS> = <<CS as CipherSuite>::Group as Group>::ScalarLen;
|
||||||
|
|
||||||
|
impl<CS: CipherSuite> $ty<CS> {
|
||||||
|
/// Serialization into bytes
|
||||||
|
pub fn serialize(&self) -> Array<u8, $len<CS>> {
|
||||||
|
CS::Group::serialize_scalar(self.$field)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Deserialization from bytes
|
||||||
|
///
|
||||||
|
/// # Errors
|
||||||
|
/// [`Error::Deserialization`] if failed to deserialize `input`.
|
||||||
|
pub fn deserialize(mut input: &[u8]) -> Result<Self> {
|
||||||
|
let $field = deserialize_scalar::<CS::Group>(&mut input)?;
|
||||||
|
|
||||||
|
if !input.is_empty() {
|
||||||
|
return Err(Error::Deserialization);
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(Self { $field })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
macro_rules! impl_serde_scalar_elem {
|
||||||
|
($ty:ident, $len:ident, $scalar_field:ident, $elem_field:ident) => {
|
||||||
|
/// Length in bytes for serialization.
|
||||||
|
pub type $len<CS> = Sum<
|
||||||
|
<<CS as CipherSuite>::Group as Group>::ScalarLen,
|
||||||
|
<<CS as CipherSuite>::Group as Group>::ElemLen,
|
||||||
|
>;
|
||||||
|
|
||||||
|
impl<CS: CipherSuite> $ty<CS> {
|
||||||
|
/// Serialization into bytes
|
||||||
|
pub fn serialize(&self) -> Array<u8, $len<CS>> {
|
||||||
|
<CS::Group as Group>::serialize_scalar(self.$scalar_field)
|
||||||
|
.concat(<CS::Group as Group>::serialize_elem(self.$elem_field))
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Deserialization from bytes
|
||||||
|
///
|
||||||
|
/// # Errors
|
||||||
|
/// [`Error::Deserialization`] if failed to deserialize `input`.
|
||||||
|
pub fn deserialize(mut input: &[u8]) -> Result<Self> {
|
||||||
|
let $scalar_field = deserialize_scalar::<CS::Group>(&mut input)?;
|
||||||
|
let $elem_field = deserialize_elem::<CS::Group>(&mut input)?;
|
||||||
|
|
||||||
|
if !input.is_empty() {
|
||||||
|
return Err(Error::Deserialization);
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(Self {
|
||||||
|
$scalar_field,
|
||||||
|
$elem_field,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
macro_rules! impl_serde_elem {
|
||||||
|
($ty:ident, $len:ident) => {
|
||||||
|
/// Length in bytes for serialization.
|
||||||
|
pub type $len<CS> = <<CS as CipherSuite>::Group as Group>::ElemLen;
|
||||||
|
|
||||||
|
impl<CS: CipherSuite> $ty<CS> {
|
||||||
|
/// Serialization into bytes
|
||||||
|
pub fn serialize(&self) -> Array<u8, $len<CS>> {
|
||||||
|
CS::Group::serialize_elem(self.0)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Deserialization from bytes
|
||||||
|
///
|
||||||
|
/// # Errors
|
||||||
|
/// [`Error::Deserialization`] if failed to deserialize `input`.
|
||||||
|
pub fn deserialize(mut input: &[u8]) -> Result<Self> {
|
||||||
|
let value = deserialize_elem::<CS::Group>(&mut input)?;
|
||||||
|
|
||||||
|
if !input.is_empty() {
|
||||||
|
return Err(Error::Deserialization);
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(Self(value))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////
|
||||||
|
// Serialization and Deserialization for High-Level API //
|
||||||
|
// ==================================================== //
|
||||||
|
//////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
impl_serde_scalar!(OprfClient, OprfClientLen, blind);
|
||||||
|
impl_serde_scalar!(OprfServer, OprfServerLen, sk);
|
||||||
|
|
||||||
|
impl_serde_elem!(BlindedElement, BlindedElementLen);
|
||||||
|
impl_serde_elem!(EvaluationElement, EvaluationElementLen);
|
||||||
|
|
||||||
|
impl_serde_scalar_elem!(VoprfClient, VoprfClientLen, blind, blinded_element);
|
||||||
|
impl_serde_scalar_elem!(PoprfClient, PoprfClientLen, blind, blinded_element);
|
||||||
|
impl_serde_scalar_elem!(VoprfServer, VoprfServerLen, sk, pk);
|
||||||
|
impl_serde_scalar_elem!(PoprfServer, PoprfServerLen, sk, pk);
|
||||||
|
|
||||||
|
/////////////////////
|
||||||
|
// Proof (One-Off) //
|
||||||
|
// =============== //
|
||||||
|
/////////////////////
|
||||||
|
|
||||||
|
/// Length of [`Proof`] in bytes for serialization.
|
||||||
|
pub type ProofLen<CS> = Sum<
|
||||||
|
<<CS as CipherSuite>::Group as Group>::ScalarLen,
|
||||||
|
<<CS as CipherSuite>::Group as Group>::ScalarLen,
|
||||||
|
>;
|
||||||
|
|
||||||
|
impl<CS: CipherSuite> Proof<CS> {
|
||||||
|
/// Serialization into bytes
|
||||||
|
pub fn serialize(&self) -> Array<u8, ProofLen<CS>> {
|
||||||
|
CS::Group::serialize_scalar(self.c_scalar)
|
||||||
|
.concat(CS::Group::serialize_scalar(self.s_scalar))
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Deserialization from bytes
|
||||||
|
///
|
||||||
|
/// # Errors
|
||||||
|
/// [`Error::Deserialization`] if failed to deserialize `input`.
|
||||||
|
pub fn deserialize(mut input: &[u8]) -> Result<Self> {
|
||||||
|
let c_scalar = deserialize_scalar::<CS::Group>(&mut input)?;
|
||||||
|
let s_scalar = deserialize_scalar::<CS::Group>(&mut input)?;
|
||||||
|
|
||||||
|
if !input.is_empty() {
|
||||||
|
return Err(Error::Deserialization);
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(Proof { c_scalar, s_scalar })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
///////////////////////////
|
||||||
|
// Serde Support //
|
||||||
|
// ===================== //
|
||||||
|
///////////////////////////
|
||||||
|
|
||||||
#[cfg(feature = "serde")]
|
#[cfg(feature = "serde")]
|
||||||
pub(crate) mod serde {
|
pub(crate) mod serde {
|
||||||
use core::marker::PhantomData;
|
use core::marker::PhantomData;
|
||||||
@@ -321,6 +260,7 @@ mod test {
|
|||||||
VoprfClient, VoprfServer,
|
VoprfClient, VoprfServer,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Fuzz: no panics on arbitrary input
|
||||||
macro_rules! test_deserialize {
|
macro_rules! test_deserialize {
|
||||||
($item:ident, $bytes:ident) => {
|
($item:ident, $bytes:ident) => {
|
||||||
#[cfg(feature = "ristretto255")]
|
#[cfg(feature = "ristretto255")]
|
||||||
@@ -328,12 +268,43 @@ mod test {
|
|||||||
let _ = $item::<crate::Ristretto255>::deserialize(&$bytes[..]);
|
let _ = $item::<crate::Ristretto255>::deserialize(&$bytes[..]);
|
||||||
}
|
}
|
||||||
|
|
||||||
let _ = $item::<p256::NistP256>::deserialize(&$bytes[..]);
|
let _ = $item::<::p256::NistP256>::deserialize(&$bytes[..]);
|
||||||
let _ = $item::<p384::NistP384>::deserialize(&$bytes[..]);
|
let _ = $item::<::p384::NistP384>::deserialize(&$bytes[..]);
|
||||||
let _ = $item::<p521::NistP521>::deserialize(&$bytes[..]);
|
let _ = $item::<::p521::NistP521>::deserialize(&$bytes[..]);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Roundtrip: serialize to deserialize == original
|
||||||
|
macro_rules! test_roundtrip {
|
||||||
|
($item:ident, $cs:ty, $constructor:expr) => {{
|
||||||
|
let original = $constructor;
|
||||||
|
let bytes = original.serialize();
|
||||||
|
let recovered = $item::<$cs>::deserialize(&bytes).expect("roundtrip deserialize");
|
||||||
|
assert_eq!(original.serialize(), recovered.serialize());
|
||||||
|
}};
|
||||||
|
}
|
||||||
|
|
||||||
|
// Trailing bytes: valid serialization + extra byte must fail
|
||||||
|
macro_rules! test_trailing {
|
||||||
|
($item:ident, $cs:ty, $constructor:expr) => {{
|
||||||
|
let original = $constructor;
|
||||||
|
let bytes = original.serialize();
|
||||||
|
let mut extended = bytes.to_vec();
|
||||||
|
extended.push(0x00);
|
||||||
|
assert!($item::<$cs>::deserialize(&extended).is_err());
|
||||||
|
}};
|
||||||
|
}
|
||||||
|
|
||||||
|
// Truncated: valid serialization minus one byte must fail
|
||||||
|
macro_rules! test_truncated {
|
||||||
|
($item:ident, $cs:ty, $constructor:expr) => {{
|
||||||
|
let original = $constructor;
|
||||||
|
let bytes = original.serialize();
|
||||||
|
let truncated = &bytes[..bytes.len() - 1];
|
||||||
|
assert!($item::<$cs>::deserialize(truncated).is_err());
|
||||||
|
}};
|
||||||
|
}
|
||||||
|
|
||||||
proptest! {
|
proptest! {
|
||||||
#[test]
|
#[test]
|
||||||
fn test_nocrash_oprf_client(bytes in vec(any::<u8>(), 0..200)) {
|
fn test_nocrash_oprf_client(bytes in vec(any::<u8>(), 0..200)) {
|
||||||
@@ -381,4 +352,103 @@ mod test {
|
|||||||
test_deserialize!(Proof, bytes);
|
test_deserialize!(Proof, bytes);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
macro_rules! structured_tests {
|
||||||
|
($cs:ty, $mod:ident) => {
|
||||||
|
mod $mod {
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
use rand::rngs::SysRng;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn roundtrip_oprf_client() {
|
||||||
|
let client = OprfClient::<$cs>::blind(b"input", &mut SysRng)
|
||||||
|
.expect("blind")
|
||||||
|
.state;
|
||||||
|
test_roundtrip!(OprfClient, $cs, client);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn roundtrip_oprf_server() {
|
||||||
|
let server = OprfServer::<$cs>::new(&mut SysRng).expect("new");
|
||||||
|
test_roundtrip!(OprfServer, $cs, server);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn roundtrip_voprf_client() {
|
||||||
|
let client = VoprfClient::<$cs>::blind(b"input", &mut SysRng)
|
||||||
|
.expect("blind")
|
||||||
|
.state;
|
||||||
|
test_roundtrip!(VoprfClient, $cs, client);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn roundtrip_voprf_server() {
|
||||||
|
let server = VoprfServer::<$cs>::new(&mut SysRng).expect("new");
|
||||||
|
test_roundtrip!(VoprfServer, $cs, server);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn roundtrip_poprf_client() {
|
||||||
|
let client = PoprfClient::<$cs>::blind(b"input", &mut SysRng)
|
||||||
|
.expect("blind")
|
||||||
|
.state;
|
||||||
|
test_roundtrip!(PoprfClient, $cs, client);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn roundtrip_poprf_server() {
|
||||||
|
let server = PoprfServer::<$cs>::new(&mut SysRng).expect("new");
|
||||||
|
test_roundtrip!(PoprfServer, $cs, server);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn trailing_oprf_client() {
|
||||||
|
let client = OprfClient::<$cs>::blind(b"input", &mut SysRng)
|
||||||
|
.expect("blind")
|
||||||
|
.state;
|
||||||
|
test_trailing!(OprfClient, $cs, client);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn trailing_oprf_server() {
|
||||||
|
let server = OprfServer::<$cs>::new(&mut SysRng).expect("new");
|
||||||
|
test_trailing!(OprfServer, $cs, server);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn truncated_oprf_client() {
|
||||||
|
let client = OprfClient::<$cs>::blind(b"input", &mut SysRng)
|
||||||
|
.expect("blind")
|
||||||
|
.state;
|
||||||
|
test_truncated!(OprfClient, $cs, client);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn truncated_oprf_server() {
|
||||||
|
let server = OprfServer::<$cs>::new(&mut SysRng).expect("new");
|
||||||
|
test_truncated!(OprfServer, $cs, server);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn empty_input_fails() {
|
||||||
|
assert!(OprfClient::<$cs>::deserialize(&[]).is_err());
|
||||||
|
assert!(OprfServer::<$cs>::deserialize(&[]).is_err());
|
||||||
|
assert!(VoprfClient::<$cs>::deserialize(&[]).is_err());
|
||||||
|
assert!(VoprfServer::<$cs>::deserialize(&[]).is_err());
|
||||||
|
assert!(PoprfClient::<$cs>::deserialize(&[]).is_err());
|
||||||
|
assert!(PoprfServer::<$cs>::deserialize(&[]).is_err());
|
||||||
|
assert!(BlindedElement::<$cs>::deserialize(&[]).is_err());
|
||||||
|
assert!(EvaluationElement::<$cs>::deserialize(&[]).is_err());
|
||||||
|
assert!(Proof::<$cs>::deserialize(&[]).is_err());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "ristretto255")]
|
||||||
|
structured_tests!(crate::Ristretto255, ristretto255);
|
||||||
|
structured_tests!(::p256::NistP256, p256);
|
||||||
|
structured_tests!(::p384::NistP384, p384);
|
||||||
|
structured_tests!(::p521::NistP521, p521);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,10 +1,6 @@
|
|||||||
|
// SPDX-License-Identifier: MIT OR Apache-2.0
|
||||||
|
// Copyright (c) VexaHub and contributors.
|
||||||
// Copyright (c) Meta Platforms, Inc. and affiliates.
|
// Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||||
//
|
|
||||||
// This source code is dual-licensed under either the MIT license found in the
|
|
||||||
// LICENSE-MIT file in the root directory of this source tree or the Apache
|
|
||||||
// License, Version 2.0 found in the LICENSE-APACHE file in the root directory
|
|
||||||
// of this source tree. You may select, at your option, one of the above-listed
|
|
||||||
// licenses.
|
|
||||||
|
|
||||||
//! The VOPRF test vectors taken from:
|
//! The VOPRF test vectors taken from:
|
||||||
//! https://www.rfc-editor.org/rfc/rfc9497#appendix-A
|
//! https://www.rfc-editor.org/rfc/rfc9497#appendix-A
|
||||||
|
|||||||
@@ -0,0 +1,25 @@
|
|||||||
|
// SPDX-License-Identifier: MIT OR Apache-2.0
|
||||||
|
// Copyright (c) VexaHub and contributors.
|
||||||
|
|
||||||
|
use core::iter;
|
||||||
|
|
||||||
|
use digest::Output;
|
||||||
|
|
||||||
|
use crate::common::{Dst, Mode, STR_HASH_TO_GROUP, finalize_after_unblind};
|
||||||
|
use crate::{CipherSuite, Group};
|
||||||
|
|
||||||
|
pub(crate) fn prf<CS: CipherSuite>(
|
||||||
|
input: &[u8],
|
||||||
|
key: <CS::Group as Group>::Scalar,
|
||||||
|
mode: Mode,
|
||||||
|
) -> Output<CS::Hash> {
|
||||||
|
let dst = Dst::new::<CS, _>(STR_HASH_TO_GROUP, mode);
|
||||||
|
let point = CS::Group::hash_to_curve::<CS::Hash>(&[input], &dst.as_dst()).unwrap();
|
||||||
|
|
||||||
|
let res = point * &key;
|
||||||
|
|
||||||
|
finalize_after_unblind::<CS, _, _>(iter::once((input, res)))
|
||||||
|
.next()
|
||||||
|
.unwrap()
|
||||||
|
.unwrap()
|
||||||
|
}
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
// SPDX-License-Identifier: MIT OR Apache-2.0
|
||||||
|
// Copyright (c) VexaHub and contributors.
|
||||||
|
|
||||||
|
macro_rules! test_all_curves {
|
||||||
|
($($test_fn:ident),+ $(,)?) => {
|
||||||
|
#[test]
|
||||||
|
fn test_functionality() -> $crate::Result<()> {
|
||||||
|
#[cfg(feature = "ristretto255")]
|
||||||
|
{
|
||||||
|
$( $test_fn::<$crate::Ristretto255>(); )+
|
||||||
|
}
|
||||||
|
$( $test_fn::<::p256::NistP256>(); )+
|
||||||
|
$( $test_fn::<::p384::NistP384>(); )+
|
||||||
|
$( $test_fn::<::p521::NistP521>(); )+
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) use test_all_curves;
|
||||||
@@ -1,10 +1,6 @@
|
|||||||
|
// SPDX-License-Identifier: MIT OR Apache-2.0
|
||||||
|
// Copyright (c) VexaHub and contributors.
|
||||||
// Copyright (c) Meta Platforms, Inc. and affiliates.
|
// Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||||
//
|
|
||||||
// This source code is dual-licensed under either the MIT license found in the
|
|
||||||
// LICENSE-MIT file in the root directory of this source tree or the Apache
|
|
||||||
// License, Version 2.0 found in the LICENSE-APACHE file in the root directory
|
|
||||||
// of this source tree. You may select, at your option, one of the above-listed
|
|
||||||
// licenses.
|
|
||||||
|
|
||||||
use alloc::vec::Vec;
|
use alloc::vec::Vec;
|
||||||
use core::cmp::min;
|
use core::cmp::min;
|
||||||
|
|||||||
+7
-6
@@ -1,12 +1,13 @@
|
|||||||
|
// SPDX-License-Identifier: MIT OR Apache-2.0
|
||||||
|
// Copyright (c) VexaHub and contributors.
|
||||||
// Copyright (c) Meta Platforms, Inc. and affiliates.
|
// Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||||
//
|
|
||||||
// This source code is dual-licensed under either the MIT license found in the
|
|
||||||
// LICENSE-MIT file in the root directory of this source tree or the Apache
|
|
||||||
// License, Version 2.0 found in the LICENSE-APACHE file in the root directory
|
|
||||||
// of this source tree. You may select, at your option, one of the above-listed
|
|
||||||
// licenses.
|
|
||||||
|
|
||||||
mod cfrg_vectors;
|
mod cfrg_vectors;
|
||||||
|
mod macros;
|
||||||
mod mock_rng;
|
mod mock_rng;
|
||||||
mod parser;
|
mod parser;
|
||||||
mod test_cfrg_vectors;
|
mod test_cfrg_vectors;
|
||||||
|
|
||||||
|
pub(crate) mod helpers;
|
||||||
|
|
||||||
|
pub(crate) use macros::test_all_curves;
|
||||||
|
|||||||
+2
-6
@@ -1,10 +1,6 @@
|
|||||||
|
// SPDX-License-Identifier: MIT OR Apache-2.0
|
||||||
|
// Copyright (c) VexaHub and contributors.
|
||||||
// Copyright (c) Meta Platforms, Inc. and affiliates.
|
// Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||||
//
|
|
||||||
// This source code is dual-licensed under either the MIT license found in the
|
|
||||||
// LICENSE-MIT file in the root directory of this source tree or the Apache
|
|
||||||
// License, Version 2.0 found in the LICENSE-APACHE file in the root directory
|
|
||||||
// of this source tree. You may select, at your option, one of the above-listed
|
|
||||||
// licenses.
|
|
||||||
|
|
||||||
use alloc::string::{String, ToString};
|
use alloc::string::{String, ToString};
|
||||||
use alloc::vec::Vec;
|
use alloc::vec::Vec;
|
||||||
|
|||||||
@@ -1,10 +1,6 @@
|
|||||||
|
// SPDX-License-Identifier: MIT OR Apache-2.0
|
||||||
|
// Copyright (c) VexaHub and contributors.
|
||||||
// Copyright (c) Meta Platforms, Inc. and affiliates.
|
// Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||||
//
|
|
||||||
// This source code is dual-licensed under either the MIT license found in the
|
|
||||||
// LICENSE-MIT file in the root directory of this source tree or the Apache
|
|
||||||
// License, Version 2.0 found in the LICENSE-APACHE file in the root directory
|
|
||||||
// of this source tree. You may select, at your option, one of the above-listed
|
|
||||||
// licenses.
|
|
||||||
|
|
||||||
use alloc::string::String;
|
use alloc::string::String;
|
||||||
use alloc::vec;
|
use alloc::vec;
|
||||||
|
|||||||
+17
-108
@@ -1,10 +1,6 @@
|
|||||||
|
// SPDX-License-Identifier: MIT OR Apache-2.0
|
||||||
|
// Copyright (c) VexaHub and contributors.
|
||||||
// Copyright (c) Meta Platforms, Inc. and affiliates.
|
// Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||||
//
|
|
||||||
// This source code is dual-licensed under either the MIT license found in the
|
|
||||||
// LICENSE-MIT file in the root directory of this source tree or the Apache
|
|
||||||
// License, Version 2.0 found in the LICENSE-APACHE file in the root directory
|
|
||||||
// of this source tree. You may select, at your option, one of the above-listed
|
|
||||||
// licenses.
|
|
||||||
|
|
||||||
//! Contains the main VOPRF API
|
//! Contains the main VOPRF API
|
||||||
|
|
||||||
@@ -13,15 +9,14 @@ use alloc::vec::Vec;
|
|||||||
use core::iter::{self, Map, Repeat, Zip};
|
use core::iter::{self, Map, Repeat, Zip};
|
||||||
|
|
||||||
use derive_where::derive_where;
|
use derive_where::derive_where;
|
||||||
use digest::{Digest, Output};
|
use digest::Output;
|
||||||
use hybrid_array::Array;
|
use hybrid_array::Array;
|
||||||
use hybrid_array::typenum::Unsigned;
|
|
||||||
use rand_core::{TryCryptoRng, TryRng};
|
use rand_core::{TryCryptoRng, TryRng};
|
||||||
|
|
||||||
use crate::common::{
|
use crate::common::{
|
||||||
BlindedElement, EvaluationElement, Mode, PreparedEvaluationElement, Proof, STR_FINALIZE,
|
BlindedElement, EvaluationElement, FinalizeAfterUnblindResult, Mode, PreparedEvaluationElement,
|
||||||
derive_keypair, deterministic_blind_unchecked, generate_proof, hash_to_group, i2osp_2,
|
Proof, derive_keypair, deterministic_blind_unchecked, finalize_after_unblind, generate_proof,
|
||||||
server_evaluate_hash_input, verify_proof,
|
hash_to_group, server_evaluate_hash_input, verify_proof,
|
||||||
};
|
};
|
||||||
#[cfg(feature = "serde")]
|
#[cfg(feature = "serde")]
|
||||||
use crate::serialization::serde::{Element, Scalar};
|
use crate::serialization::serde::{Element, Scalar};
|
||||||
@@ -508,37 +503,6 @@ where
|
|||||||
.map(|(blind, x)| x.0 * &CS::Group::invert_scalar(blind)))
|
.map(|(blind, x)| x.0 * &CS::Group::invert_scalar(blind)))
|
||||||
}
|
}
|
||||||
|
|
||||||
type FinalizeAfterUnblindResult<'a, C, I, IE> = Map<
|
|
||||||
IE,
|
|
||||||
fn((I, <<C as CipherSuite>::Group as Group>::Elem)) -> Result<Output<<C as CipherSuite>::Hash>>,
|
|
||||||
>;
|
|
||||||
|
|
||||||
/// Returned values can only fail with [`Error::Input`].
|
|
||||||
fn finalize_after_unblind<
|
|
||||||
'a,
|
|
||||||
CS: CipherSuite,
|
|
||||||
I: AsRef<[u8]>,
|
|
||||||
IE: 'a + Iterator<Item = (I, <CS::Group as Group>::Elem)>,
|
|
||||||
>(
|
|
||||||
inputs_and_unblinded_elements: IE,
|
|
||||||
) -> FinalizeAfterUnblindResult<'a, CS, I, IE> {
|
|
||||||
inputs_and_unblinded_elements.map(|(input, unblinded_element)| {
|
|
||||||
let elem_len = <CS::Group as Group>::ElemLen::U16.to_be_bytes();
|
|
||||||
|
|
||||||
// hashInput = I2OSP(len(input), 2) || input ||
|
|
||||||
// I2OSP(len(unblindedElement), 2) || unblindedElement ||
|
|
||||||
// "Finalize"
|
|
||||||
// return Hash(hashInput)
|
|
||||||
Ok(CS::Hash::new()
|
|
||||||
.chain_update(i2osp_2(input.as_ref().len()).map_err(|_| Error::Input)?)
|
|
||||||
.chain_update(input.as_ref())
|
|
||||||
.chain_update(elem_len)
|
|
||||||
.chain_update(CS::Group::serialize_elem(unblinded_element))
|
|
||||||
.chain_update(STR_FINALIZE)
|
|
||||||
.finalize())
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
///////////
|
///////////
|
||||||
// Tests //
|
// Tests //
|
||||||
// ===== //
|
// ===== //
|
||||||
@@ -555,22 +519,7 @@ mod tests {
|
|||||||
use super::*;
|
use super::*;
|
||||||
use crate::Group;
|
use crate::Group;
|
||||||
use crate::common::{Dst, STR_HASH_TO_GROUP};
|
use crate::common::{Dst, STR_HASH_TO_GROUP};
|
||||||
|
use crate::tests::helpers::prf;
|
||||||
fn prf<CS: CipherSuite>(
|
|
||||||
input: &[u8],
|
|
||||||
key: <CS::Group as Group>::Scalar,
|
|
||||||
mode: Mode,
|
|
||||||
) -> Output<CS::Hash> {
|
|
||||||
let dst = Dst::new::<CS, _>(STR_HASH_TO_GROUP, mode);
|
|
||||||
let point = CS::Group::hash_to_curve::<CS::Hash>(&[input], &dst.as_dst()).unwrap();
|
|
||||||
|
|
||||||
let res = point * &key;
|
|
||||||
|
|
||||||
finalize_after_unblind::<CS, _, _>(iter::once((input, res)))
|
|
||||||
.next()
|
|
||||||
.unwrap()
|
|
||||||
.unwrap()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn verifiable_retrieval<CS: CipherSuite>() {
|
fn verifiable_retrieval<CS: CipherSuite>() {
|
||||||
let input = b"input";
|
let input = b"input";
|
||||||
@@ -717,7 +666,7 @@ mod tests {
|
|||||||
// inputs
|
// inputs
|
||||||
let wrong_input = b"wrong input";
|
let wrong_input = b"wrong input";
|
||||||
let server_evaluate = server.evaluate(wrong_input).unwrap();
|
let server_evaluate = server.evaluate(wrong_input).unwrap();
|
||||||
assert!(client_finalize != server_evaluate);
|
assert_ne!(client_finalize, server_evaluate);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn zeroize_voprf_client<CS: CipherSuite>() {
|
fn zeroize_voprf_client<CS: CipherSuite>() {
|
||||||
@@ -754,53 +703,13 @@ mod tests {
|
|||||||
assert!(proof.serialize().iter().all(|&x| x == 0));
|
assert!(proof.serialize().iter().all(|&x| x == 0));
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
crate::tests::test_all_curves!(
|
||||||
fn test_functionality() -> Result<()> {
|
verifiable_retrieval,
|
||||||
use p256::NistP256;
|
verifiable_batch_retrieval,
|
||||||
use p384::NistP384;
|
verifiable_bad_public_key,
|
||||||
use p521::NistP521;
|
verifiable_batch_bad_public_key,
|
||||||
|
verifiable_server_evaluate,
|
||||||
#[cfg(feature = "ristretto255")]
|
zeroize_voprf_client,
|
||||||
{
|
zeroize_voprf_server,
|
||||||
use crate::Ristretto255;
|
);
|
||||||
|
|
||||||
verifiable_retrieval::<Ristretto255>();
|
|
||||||
verifiable_batch_retrieval::<Ristretto255>();
|
|
||||||
verifiable_bad_public_key::<Ristretto255>();
|
|
||||||
verifiable_batch_bad_public_key::<Ristretto255>();
|
|
||||||
verifiable_server_evaluate::<Ristretto255>();
|
|
||||||
|
|
||||||
zeroize_voprf_client::<Ristretto255>();
|
|
||||||
zeroize_voprf_server::<Ristretto255>();
|
|
||||||
}
|
|
||||||
|
|
||||||
verifiable_retrieval::<NistP256>();
|
|
||||||
verifiable_batch_retrieval::<NistP256>();
|
|
||||||
verifiable_bad_public_key::<NistP256>();
|
|
||||||
verifiable_batch_bad_public_key::<NistP256>();
|
|
||||||
verifiable_server_evaluate::<NistP256>();
|
|
||||||
|
|
||||||
zeroize_voprf_client::<NistP256>();
|
|
||||||
zeroize_voprf_server::<NistP256>();
|
|
||||||
|
|
||||||
verifiable_retrieval::<NistP384>();
|
|
||||||
verifiable_batch_retrieval::<NistP384>();
|
|
||||||
verifiable_bad_public_key::<NistP384>();
|
|
||||||
verifiable_batch_bad_public_key::<NistP384>();
|
|
||||||
verifiable_server_evaluate::<NistP384>();
|
|
||||||
|
|
||||||
zeroize_voprf_client::<NistP384>();
|
|
||||||
zeroize_voprf_server::<NistP384>();
|
|
||||||
|
|
||||||
verifiable_retrieval::<NistP521>();
|
|
||||||
verifiable_batch_retrieval::<NistP521>();
|
|
||||||
verifiable_bad_public_key::<NistP521>();
|
|
||||||
verifiable_batch_bad_public_key::<NistP521>();
|
|
||||||
verifiable_server_evaluate::<NistP521>();
|
|
||||||
|
|
||||||
zeroize_voprf_client::<NistP521>();
|
|
||||||
zeroize_voprf_server::<NistP521>();
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user