Bug 1924577 - vendor clubcard-crlite 0.3.0. a=RyanVM

Original Revision: https://phabricator.services.mozilla.com/D225552

Differential Revision: https://phabricator.services.mozilla.com/D225724
This commit is contained in:
John Schanck 2024-10-15 22:24:07 +00:00
parent 0b8dda408a
commit 903a5f7036
22 changed files with 3404 additions and 100 deletions

9
Cargo.lock generated
View File

@ -886,19 +886,20 @@ checksum = "1462739cb27611015575c0c11df5df7601141071f07518d56fcc1be504cbec97"
[[package]]
name = "clubcard"
version = "0.3.1"
version = "0.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3d413adde685b0ec7e867186296768474efc2aa952063f40a5198baf760ca983"
checksum = "8ec3fe691cfeac642b45d2acee55f4c745fe9eed548380fd41d1fb7daf54297c"
dependencies = [
"serde",
]
[[package]]
name = "clubcard-crlite"
version = "0.2.1"
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a85947de44196eb8effe46a2af1ac43e9309b7add92d805b411b7b98254935c9"
checksum = "dd2c6f668aeaab6cf4c9637400ce5bc1f7ab1cf9b424dd0125273f16bd26ca25"
dependencies = [
"base64 0.21.3",
"bincode",
"clubcard",
"serde",

View File

@ -8,7 +8,7 @@ license = "MPL-2.0"
base64 = "0.21.0"
byteorder = "1.2.7"
clubcard = "0.3"
clubcard-crlite = "0.2"
clubcard-crlite = "0.3"
crossbeam-utils = "0.8"
cstr = "0.2"
firefox-on-glean = { path = "../../../../toolkit/components/glean/api" }

View File

@ -315,6 +315,7 @@ impl Filter {
}
}
Filter::Clubcard(clubcard) => {
let crlite_key = clubcard_crlite::CRLiteKey::new(issuer_spki_hash.as_ref(), serial);
let timestamps = timestamps
.iter()
.map(|timestamp| {
@ -324,7 +325,7 @@ impl Filter {
.map(|log_id| (log_id, timestamp.timestamp))
})
.flatten();
match clubcard.contains(issuer_spki_hash.as_ref(), serial, timestamps) {
match clubcard.contains(&crlite_key, timestamps) {
CRLiteStatus::Good => nsICertStorage::STATE_UNSET,
CRLiteStatus::NotCovered => nsICertStorage::STATE_NOT_COVERED,
CRLiteStatus::NotEnrolled => nsICertStorage::STATE_NOT_ENROLLED,

View File

@ -52,6 +52,22 @@ start = "2021-06-21"
end = "2024-04-21"
notes = "No unsafe code, rather straight-forward parser."
[[wildcard-audits.clubcard]]
who = "John M. Schanck <jschanck@mozilla.com>"
criteria = "safe-to-deploy"
user-id = 175410 # John Schanck (jschanck)
start = "2024-10-01"
end = "2025-10-01"
notes = "Maintained by the CryptoEng team at Mozilla."
[[wildcard-audits.clubcard-crlite]]
who = "John M. Schanck <jschanck@mozilla.com>"
criteria = "safe-to-deploy"
user-id = 175410 # John Schanck (jschanck)
start = "2024-10-01"
end = "2025-10-01"
notes = "Maintained by the CryptoEng team at Mozilla."
[[wildcard-audits.cocoa]]
who = "Bobby Holley <bobbyholley@gmail.com>"
criteria = "safe-to-deploy"

View File

@ -135,6 +135,20 @@ user-id = 6743
user-login = "epage"
user-name = "Ed Page"
[[publisher.clubcard]]
version = "0.3.2"
when = "2024-10-08"
user-id = 175410
user-login = "jschanck"
user-name = "John Schanck"
[[publisher.clubcard-crlite]]
version = "0.3.0"
when = "2024-10-14"
user-id = 175410
user-login = "jschanck"
user-name = "John Schanck"
[[publisher.core-foundation]]
version = "0.9.3"
when = "2022-02-07"

View File

@ -1 +1 @@
{"files":{"Cargo.toml":"2e4c5d706d89b5698d11925df54df4049f3f501af31154fd2dcc2411c4fd3307","LICENSE":"1f256ecad192880510e84ad60474eab7589218784b9a50bc7ceee34c2b91f1d5","src/builder.rs":"616f7aa1ea6e88bdc0c939c24b0e432e40fa553535ff88098fb8967d32b339a5","src/lib.rs":"d939278e06b1dca0bf827d491213d7ebadc7be6cc89bc53c608af42872e3378d","src/query.rs":"aceac54c20c384f54fe5d345af3e59acb4c7a59552e197f033969fab505db0b0"},"package":"a85947de44196eb8effe46a2af1ac43e9309b7add92d805b411b7b98254935c9"}
{"files":{"Cargo.lock":"8f68f70084f64ceb9e6171033963b987ce34826ac873322fead61159ea7183bd","Cargo.toml":"59a923c9e3896fe1f516228ff6b7d915cd7d87a896f2760220be0bcc28962618","LICENSE":"1f256ecad192880510e84ad60474eab7589218784b9a50bc7ceee34c2b91f1d5","examples/inspect.rs":"e8406a230da643e9dc45260ac496926eaddec4c1f606fb69c566409019e3b20e","examples/query.rs":"6bb7386a032a3c0ed9d31fdc4a4443c90ba52347ea972427cc36a5c798ffeed4","src/builder.rs":"23450a3465cfba6daef0bec643ea1cfbc52c16e3e820c7d795988f5d50c7eec6","src/lib.rs":"3788c6d816abd13f41b17c2134ac47ebacf8d9d6413adf6847925a3194a9ca03","src/query.rs":"9898913516f75c64ee85560571fe131d550db3a046057ab50dced3db87b1db45"},"package":"dd2c6f668aeaab6cf4c9637400ce5bc1f7ab1cf9b424dd0125273f16bd26ca25"}

653
third_party/rust/clubcard-crlite/Cargo.lock generated vendored Normal file
View File

@ -0,0 +1,653 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
version = 3
[[package]]
name = "asn1-rs"
version = "0.6.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5493c3bedbacf7fd7382c6346bbd66687d12bbaad3a89a2d2c303ee6cf20b048"
dependencies = [
"asn1-rs-derive",
"asn1-rs-impl",
"displaydoc",
"nom",
"num-traits",
"rusticata-macros",
"thiserror",
"time",
]
[[package]]
name = "asn1-rs-derive"
version = "0.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "965c2d33e53cb6b267e148a4cb0760bc01f4904c1cd4bb4002a085bb016d1490"
dependencies = [
"proc-macro2",
"quote",
"syn",
"synstructure",
]
[[package]]
name = "asn1-rs-impl"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7b18050c2cd6fe86c3a76584ef5e0baf286d038cda203eb6223df2cc413565f7"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "autocfg"
version = "1.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26"
[[package]]
name = "base64"
version = "0.21.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9d297deb1925b89f2ccc13d7635fa0714f12c87adce1c75356b39ca9b7178567"
[[package]]
name = "bincode"
version = "1.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b1f45e9417d87227c7a56d22e471c6206462cba514c7590c09aff4cf6d1ddcad"
dependencies = [
"serde",
]
[[package]]
name = "block-buffer"
version = "0.10.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71"
dependencies = [
"generic-array",
]
[[package]]
name = "byteorder"
version = "1.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b"
[[package]]
name = "cc"
version = "1.1.22"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9540e661f81799159abee814118cc139a2004b3a3aa3ea37724a1b66530b90e0"
dependencies = [
"shlex",
]
[[package]]
name = "cfg-if"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
[[package]]
name = "clubcard"
version = "0.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8ec3fe691cfeac642b45d2acee55f4c745fe9eed548380fd41d1fb7daf54297c"
dependencies = [
"rand",
"serde",
]
[[package]]
name = "clubcard-crlite"
version = "0.3.0"
dependencies = [
"base64",
"bincode",
"clubcard",
"rand",
"serde",
"serde_json",
"sha2",
"x509-parser",
]
[[package]]
name = "cpufeatures"
version = "0.2.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "608697df725056feaccfa42cffdaeeec3fccc4ffc38358ecd19b243e716a78e0"
dependencies = [
"libc",
]
[[package]]
name = "crypto-common"
version = "0.1.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3"
dependencies = [
"generic-array",
"typenum",
]
[[package]]
name = "data-encoding"
version = "2.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e8566979429cf69b49a5c740c60791108e86440e8be149bbea4fe54d2c32d6e2"
[[package]]
name = "der-parser"
version = "9.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5cd0a5c643689626bec213c4d8bd4d96acc8ffdb4ad4bb6bc16abf27d5f4b553"
dependencies = [
"asn1-rs",
"displaydoc",
"nom",
"num-bigint",
"num-traits",
"rusticata-macros",
]
[[package]]
name = "deranged"
version = "0.3.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b42b6fa04a440b495c8b04d0e71b707c585f83cb9cb28cf8cd0d976c315e31b4"
dependencies = [
"powerfmt",
]
[[package]]
name = "digest"
version = "0.10.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292"
dependencies = [
"block-buffer",
"crypto-common",
]
[[package]]
name = "displaydoc"
version = "0.2.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "generic-array"
version = "0.14.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a"
dependencies = [
"typenum",
"version_check",
]
[[package]]
name = "getrandom"
version = "0.2.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7"
dependencies = [
"cfg-if",
"libc",
"wasi",
]
[[package]]
name = "itoa"
version = "1.0.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b"
[[package]]
name = "lazy_static"
version = "1.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe"
[[package]]
name = "libc"
version = "0.2.158"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d8adc4bb1803a324070e64a98ae98f38934d91957a99cfb3a43dcbc01bc56439"
[[package]]
name = "memchr"
version = "2.7.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3"
[[package]]
name = "minimal-lexical"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a"
[[package]]
name = "nom"
version = "7.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a"
dependencies = [
"memchr",
"minimal-lexical",
]
[[package]]
name = "num-bigint"
version = "0.4.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a5e44f723f1133c9deac646763579fdb3ac745e418f2a7af9cd0c431da1f20b9"
dependencies = [
"num-integer",
"num-traits",
]
[[package]]
name = "num-conv"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9"
[[package]]
name = "num-integer"
version = "0.1.46"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f"
dependencies = [
"num-traits",
]
[[package]]
name = "num-traits"
version = "0.2.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841"
dependencies = [
"autocfg",
]
[[package]]
name = "oid-registry"
version = "0.7.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a8d8034d9489cdaf79228eb9f6a3b8d7bb32ba00d6645ebd48eef4077ceb5bd9"
dependencies = [
"asn1-rs",
]
[[package]]
name = "powerfmt"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391"
[[package]]
name = "ppv-lite86"
version = "0.2.20"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "77957b295656769bb8ad2b6a6b09d897d94f05c41b069aede1fcdaa675eaea04"
dependencies = [
"zerocopy",
]
[[package]]
name = "proc-macro2"
version = "1.0.86"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5e719e8df665df0d1c8fbfd238015744736151d4445ec0836b8e628aae103b77"
dependencies = [
"unicode-ident",
]
[[package]]
name = "quote"
version = "1.0.37"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b5b9d34b8991d19d98081b46eacdd8eb58c6f2b201139f7c5f643cc155a633af"
dependencies = [
"proc-macro2",
]
[[package]]
name = "rand"
version = "0.8.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404"
dependencies = [
"libc",
"rand_chacha",
"rand_core",
]
[[package]]
name = "rand_chacha"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88"
dependencies = [
"ppv-lite86",
"rand_core",
]
[[package]]
name = "rand_core"
version = "0.6.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c"
dependencies = [
"getrandom",
]
[[package]]
name = "ring"
version = "0.17.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c17fa4cb658e3583423e915b9f3acc01cceaee1860e33d59ebae66adc3a2dc0d"
dependencies = [
"cc",
"cfg-if",
"getrandom",
"libc",
"spin",
"untrusted",
"windows-sys",
]
[[package]]
name = "rusticata-macros"
version = "4.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "faf0c4a6ece9950b9abdb62b1cfcf2a68b3b67a10ba445b3bb85be2a293d0632"
dependencies = [
"nom",
]
[[package]]
name = "ryu"
version = "1.0.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f"
[[package]]
name = "serde"
version = "1.0.210"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c8e3592472072e6e22e0a54d5904d9febf8508f65fb8552499a1abc7d1078c3a"
dependencies = [
"serde_derive",
]
[[package]]
name = "serde_derive"
version = "1.0.210"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "243902eda00fad750862fc144cea25caca5e20d615af0a81bee94ca738f1df1f"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "serde_json"
version = "1.0.128"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6ff5456707a1de34e7e37f2a6fd3d3f808c318259cbd01ab6377795054b483d8"
dependencies = [
"itoa",
"memchr",
"ryu",
"serde",
]
[[package]]
name = "sha2"
version = "0.10.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8"
dependencies = [
"cfg-if",
"cpufeatures",
"digest",
]
[[package]]
name = "shlex"
version = "1.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64"
[[package]]
name = "spin"
version = "0.9.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67"
[[package]]
name = "syn"
version = "2.0.77"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9f35bcdf61fd8e7be6caf75f429fdca8beb3ed76584befb503b1569faee373ed"
dependencies = [
"proc-macro2",
"quote",
"unicode-ident",
]
[[package]]
name = "synstructure"
version = "0.13.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c8af7666ab7b6390ab78131fb5b0fce11d6b7a6951602017c35fa82800708971"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "thiserror"
version = "1.0.64"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d50af8abc119fb8bb6dbabcfa89656f46f84aa0ac7688088608076ad2b459a84"
dependencies = [
"thiserror-impl",
]
[[package]]
name = "thiserror-impl"
version = "1.0.64"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "08904e7672f5eb876eaaf87e0ce17857500934f4981c4a0ab2b4aa98baac7fc3"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "time"
version = "0.3.36"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5dfd88e563464686c916c7e46e623e520ddc6d79fa6641390f2e3fa86e83e885"
dependencies = [
"deranged",
"itoa",
"num-conv",
"powerfmt",
"serde",
"time-core",
"time-macros",
]
[[package]]
name = "time-core"
version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ef927ca75afb808a4d64dd374f00a2adf8d0fcff8e7b184af886c3c87ec4a3f3"
[[package]]
name = "time-macros"
version = "0.2.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3f252a68540fde3a3877aeea552b832b40ab9a69e318efd078774a01ddee1ccf"
dependencies = [
"num-conv",
"time-core",
]
[[package]]
name = "typenum"
version = "1.17.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825"
[[package]]
name = "unicode-ident"
version = "1.0.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e91b56cd4cadaeb79bbf1a5645f6b4f8dc5bde8834ad5894a8db35fda9efa1fe"
[[package]]
name = "untrusted"
version = "0.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1"
[[package]]
name = "version_check"
version = "0.9.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a"
[[package]]
name = "wasi"
version = "0.11.0+wasi-snapshot-preview1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
[[package]]
name = "windows-sys"
version = "0.52.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d"
dependencies = [
"windows-targets",
]
[[package]]
name = "windows-targets"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973"
dependencies = [
"windows_aarch64_gnullvm",
"windows_aarch64_msvc",
"windows_i686_gnu",
"windows_i686_gnullvm",
"windows_i686_msvc",
"windows_x86_64_gnu",
"windows_x86_64_gnullvm",
"windows_x86_64_msvc",
]
[[package]]
name = "windows_aarch64_gnullvm"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3"
[[package]]
name = "windows_aarch64_msvc"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469"
[[package]]
name = "windows_i686_gnu"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b"
[[package]]
name = "windows_i686_gnullvm"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66"
[[package]]
name = "windows_i686_msvc"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66"
[[package]]
name = "windows_x86_64_gnu"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78"
[[package]]
name = "windows_x86_64_gnullvm"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d"
[[package]]
name = "windows_x86_64_msvc"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec"
[[package]]
name = "x509-parser"
version = "0.16.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fcbc162f30700d6f3f82a24bf7cc62ffe7caea42c0b2cba8bf7f3ae50cf51f69"
dependencies = [
"asn1-rs",
"data-encoding",
"der-parser",
"lazy_static",
"nom",
"oid-registry",
"ring",
"rusticata-macros",
"thiserror",
"time",
]
[[package]]
name = "zerocopy"
version = "0.7.35"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1b9b4fd18abc82b8136838da5d50bae7bdea537c574d8dc1a34ed098d6c166f0"
dependencies = [
"byteorder",
"zerocopy-derive",
]
[[package]]
name = "zerocopy-derive"
version = "0.7.35"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e"
dependencies = [
"proc-macro2",
"quote",
"syn",
]

View File

@ -12,15 +12,32 @@
[package]
edition = "2021"
name = "clubcard-crlite"
version = "0.2.1"
version = "0.3.0"
authors = ["John M. Schanck <jschanck@mozilla.com>"]
build = false
autobins = false
autoexamples = false
autotests = false
autobenches = false
description = "An instantiation of Clubcard for use in CRLite"
readme = false
license = "MPL-2.0"
repository = "https://github.com/mozilla/clubcard-crlite/"
[lib]
name = "clubcard_crlite"
path = "src/lib.rs"
[[example]]
name = "inspect"
path = "examples/inspect.rs"
[[example]]
name = "query"
path = "examples/query.rs"
[dependencies.base64]
version = "0.22"
optional = true
version = "0.21"
[dependencies.bincode]
version = "1.3"
@ -49,10 +66,13 @@ version = "0.8"
[dev-dependencies.sha2]
version = "0.10"
[dev-dependencies.x509-parser]
version = "0.16"
features = ["verify"]
[features]
builder = [
"dep:rand",
"dep:base64",
"dep:serde_json",
"clubcard/builder",
]

View File

@ -0,0 +1,35 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
use clubcard_crlite::CRLiteClubcard;
use std::env::args;
use std::path::PathBuf;
use std::process::ExitCode;
fn parse_args() -> Option<PathBuf> {
let mut args = args().map(PathBuf::from);
let _name = args.next()?;
Some(args.next()?)
}
fn main() -> std::process::ExitCode {
let Some(filter_path) = parse_args() else {
eprintln!("Usage: {} <filter>", args().next().unwrap());
return ExitCode::FAILURE;
};
let Ok(filter_bytes) = std::fs::read(&filter_path) else {
eprintln!("Could not read filter");
return ExitCode::FAILURE;
};
let Ok(filter) = CRLiteClubcard::from_bytes(&filter_bytes) else {
eprintln!("Could not parse filter");
return ExitCode::FAILURE;
};
println!("{}", filter);
ExitCode::SUCCESS
}

View File

@ -0,0 +1,99 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
use clubcard_crlite::{CRLiteClubcard, CRLiteKey, CRLiteStatus};
use sha2::{Digest, Sha256};
use std::env::args;
use std::path::PathBuf;
use std::process::ExitCode;
use x509_parser::prelude::*;
fn read_as_der(path: &PathBuf) -> Result<Vec<u8>, std::io::Error> {
let bytes = std::fs::read(&path)?;
match parse_x509_pem(&bytes) {
Ok((_, pem)) => Ok(pem.contents),
_ => Ok(bytes),
}
}
fn parse_args() -> Option<(PathBuf, PathBuf, PathBuf)> {
let mut args = args().map(PathBuf::from);
let _name = args.next()?;
Some((args.next()?, args.next()?, args.next()?))
}
fn main() -> std::process::ExitCode {
let Some((filter_path, issuer_cert_path, end_entity_cert_path)) = parse_args() else {
eprintln!(
"Usage: {} <filter> <issuer certificate> <end entity certificate>",
args().next().unwrap()
);
return ExitCode::FAILURE;
};
let Ok(filter_bytes) = std::fs::read(&filter_path) else {
eprintln!("Could not read filter");
return ExitCode::FAILURE;
};
let Ok(filter) = CRLiteClubcard::from_bytes(&filter_bytes) else {
eprintln!("Could not parse filter");
return ExitCode::FAILURE;
};
let Ok(issuer_bytes) = read_as_der(&issuer_cert_path) else {
eprintln!("Could not read issuer certificate");
return ExitCode::FAILURE;
};
let Ok((_, issuer)) = X509Certificate::from_der(&issuer_bytes) else {
eprintln!("Could not parse issuer certificate");
return ExitCode::FAILURE;
};
let Ok(cert_bytes) = read_as_der(&end_entity_cert_path) else {
eprintln!("Could not read end-entity certificate");
return ExitCode::FAILURE;
};
let Ok((_, cert)) = X509Certificate::from_der(&cert_bytes) else {
eprintln!("Could not parse end-entity certificate");
return ExitCode::FAILURE;
};
if cert.verify_signature(Some(issuer.public_key())).is_err() {
eprintln!("Invalid signature (wrong issuer certificate?)");
return ExitCode::FAILURE;
}
if !cert.tbs_certificate.validity.is_valid() {
eprintln!("End-entity certificate is expired");
return ExitCode::FAILURE;
}
let Ok(Some(sct_extension)) = cert
.tbs_certificate
.get_extension_unique(&x509_parser::oid_registry::OID_CT_LIST_SCT)
else {
eprintln!("End entity certificate has no SCTs");
return ExitCode::FAILURE;
};
let ParsedExtension::SCT(scts) = sct_extension.parsed_extension() else {
eprintln!("End entity certificate has no SCTs");
return ExitCode::FAILURE;
};
let issuer_spki_hash: [u8; 32] = Sha256::digest(issuer.tbs_certificate.subject_pki.raw).into();
let serial = cert.tbs_certificate.raw_serial();
let key = CRLiteKey::new(&issuer_spki_hash, &serial);
match filter.contains(&key, scts.iter().map(|sct| (sct.id.key_id, sct.timestamp))) {
CRLiteStatus::Good => println!("Good"),
CRLiteStatus::Revoked => println!("Revoked"),
CRLiteStatus::NotEnrolled | CRLiteStatus::NotCovered => println!("Unknown"),
};
ExitCode::SUCCESS
}

View File

@ -2,7 +2,7 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
use crate::query::{CRLiteCoverage, CRLiteQuery};
use crate::query::{CRLiteCoverage, CRLiteKey, CRLiteQuery};
use clubcard::{AsQuery, Equation, Filterable};
use serde::Deserialize;
use std::collections::HashMap;
@ -101,19 +101,11 @@ impl CRLiteBuilderItem {
}
}
impl<'a> From<&'a CRLiteBuilderItem> for CRLiteQuery<'a> {
fn from(item: &'a CRLiteBuilderItem) -> Self {
Self {
issuer: &item.issuer,
serial: &item.serial,
log_timestamp: None,
}
}
}
impl AsQuery<4> for CRLiteBuilderItem {
fn as_query(&self, m: usize) -> Equation<4> {
CRLiteQuery::from(self).as_query(m)
let crlite_key = CRLiteKey::new(&self.issuer, &self.serial);
let crlite_query = CRLiteQuery::new(&crlite_key, None);
crlite_query.as_query(m)
}
fn block(&self) -> &[u8] {
@ -216,12 +208,8 @@ mod tests {
let issuer = [i as u8; 32];
for j in 0..universe_size {
let serial = j.to_le_bytes();
let item = CRLiteQuery {
issuer: &issuer,
serial: &serial,
log_timestamp: None,
};
if clubcard.unchecked_contains(&item) {
let key = CRLiteKey::new(&issuer, &serial);
if clubcard.unchecked_contains(&CRLiteQuery::new(&key, None)) {
included += 1;
} else {
excluded += 1;
@ -235,61 +223,43 @@ mod tests {
// Test that querying a serial from a never-before-seen issuer results in a non-member return.
let issuer = [subset_sizes.len() as u8; 32];
let serial = 0usize.to_le_bytes();
let item = CRLiteQuery {
issuer: &issuer,
serial: &serial,
log_timestamp: None,
};
assert!(!clubcard.unchecked_contains(&item));
let key = CRLiteKey::new(&issuer, &serial);
assert!(!clubcard.unchecked_contains(&CRLiteQuery::new(&key, None)));
assert!(subset_sizes.len() > 0 && subset_sizes[0] > 0 && subset_sizes[0] < universe_size);
let issuer = [0u8; 32];
let revoked_serial = 0usize.to_le_bytes();
let nonrevoked_serial = (universe_size - 1).to_le_bytes();
// Test that calling contains() a without a timestamp results in a NotInUniverse return
let item = CRLiteQuery {
issuer: &issuer,
serial: &revoked_serial,
log_timestamp: None,
};
// Test that calling contains() without a timestamp results in a NotInUniverse return
let revoked_serial_key = CRLiteKey::new(&issuer, &revoked_serial);
let query = CRLiteQuery::new(&revoked_serial_key, None);
assert!(matches!(
clubcard.contains(&item),
clubcard.contains(&query),
Membership::NotInUniverse
));
// Test that calling contains() without a timestamp in a covered interval results in a
// Test that calling contains() with a timestamp in a covered interval results in a
// Member return.
let log_id = [0u8; 32];
let timestamp = (&log_id, 100);
let item = CRLiteQuery {
issuer: &issuer,
serial: &revoked_serial,
log_timestamp: Some(timestamp),
};
assert!(matches!(clubcard.contains(&item), Membership::Member));
let query = CRLiteQuery::new(&revoked_serial_key, Some(timestamp));
assert!(matches!(clubcard.contains(&query), Membership::Member));
// Test that calling contains() without a timestamp in a covered interval results in a
// Member return.
let timestamp = (&log_id, 100);
let item = CRLiteQuery {
issuer: &issuer,
serial: &nonrevoked_serial,
log_timestamp: Some(timestamp),
};
assert!(matches!(clubcard.contains(&item), Membership::Nonmember));
let nonrevoked_serial_key = CRLiteKey::new(&issuer, &nonrevoked_serial);
let query = CRLiteQuery::new(&nonrevoked_serial_key, Some(timestamp));
assert!(matches!(clubcard.contains(&query), Membership::Nonmember));
// Test that calling contains() without a timestamp in a covered interval results in a
// Member return.
let log_id = [1u8; 32];
let timestamp = (&log_id, 100);
let item = CRLiteQuery {
issuer: &issuer,
serial: &revoked_serial,
log_timestamp: Some(timestamp),
};
let query = CRLiteQuery::new(&revoked_serial_key, Some(timestamp));
assert!(matches!(
clubcard.contains(&item),
clubcard.contains(&query),
Membership::NotInUniverse
));
}

View File

@ -6,4 +6,4 @@
pub mod builder;
mod query;
pub use query::{CRLiteClubcard, CRLiteCoverage, CRLiteQuery, CRLiteStatus};
pub use query::{CRLiteClubcard, CRLiteCoverage, CRLiteKey, CRLiteQuery, CRLiteStatus};

View File

@ -2,7 +2,10 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
use clubcard::{ApproximateSizeOf, AsQuery, Clubcard, Equation, Membership, Queryable};
use base64::Engine;
use clubcard::{
ApproximateSizeOf, AsQuery, Clubcard, ClubcardIndex, Equation, Membership, Queryable,
};
use serde::{Deserialize, Serialize};
use sha2::{Digest, Sha256};
use std::cmp::max;
@ -20,41 +23,50 @@ type TimestampInterval = (Timestamp, Timestamp);
#[derive(Serialize, Deserialize)]
pub struct CRLiteCoverage(pub(crate) HashMap<LogId, TimestampInterval>);
#[derive(Clone, Debug)]
pub struct CRLiteQuery<'a> {
#[derive(Debug)]
pub struct CRLiteKey<'a> {
pub(crate) issuer: &'a IssuerSpkiHash,
pub(crate) serial: &'a [u8],
pub(crate) issuer_serial_hash: [u8; 32],
}
impl<'a> CRLiteKey<'a> {
pub fn new(issuer: &'a IssuerSpkiHash, serial: &'a [u8]) -> CRLiteKey<'a> {
let mut issuer_serial_hash = [0u8; 32];
let mut hasher = Sha256::new();
hasher.update(issuer);
hasher.update(serial);
hasher.finalize_into((&mut issuer_serial_hash).into());
CRLiteKey {
issuer,
serial,
issuer_serial_hash,
}
}
}
#[derive(Clone, Debug)]
pub struct CRLiteQuery<'a> {
pub(crate) key: &'a CRLiteKey<'a>,
pub(crate) log_timestamp: Option<(&'a LogId, Timestamp)>,
}
impl<'a> CRLiteQuery<'a> {
pub fn new(
issuer: &'a IssuerSpkiHash,
serial: &'a [u8],
log_timestamp: Option<(&'a LogId, u64)>,
) -> CRLiteQuery<'a> {
CRLiteQuery {
issuer,
serial,
log_timestamp,
}
pub fn new(key: &'a CRLiteKey<'a>, log_timestamp: Option<(&'a LogId, u64)>) -> CRLiteQuery<'a> {
CRLiteQuery { key, log_timestamp }
}
}
impl<'a> AsQuery<W> for CRLiteQuery<'a> {
fn block(&self) -> &[u8] {
self.issuer.as_ref()
self.key.issuer.as_ref()
}
fn as_query(&self, m: usize) -> Equation<W> {
let mut digest = [0u8; 32];
let mut hasher = Sha256::new();
hasher.update(self.issuer);
hasher.update(self.serial);
hasher.finalize_into((&mut digest).into());
let mut a = [0u64; 4];
for (i, x) in digest
for (i, x) in self
.key
.issuer_serial_hash
.chunks_exact(8) // TODO: use array_chunks::<8>() when stable
.map(|x| TryInto::<[u8; 8]>::try_into(x).unwrap())
.map(u64::from_le_bytes)
@ -63,12 +75,12 @@ impl<'a> AsQuery<W> for CRLiteQuery<'a> {
a[i] = x;
}
a[0] |= 1;
let s = (a[3] as usize) % max(1, m);
let s = (a[3] % (max(1, m) as u64)) as usize;
Equation::homogeneous(s, a)
}
fn discriminant(&self) -> &[u8] {
self.serial
self.key.serial
}
}
@ -135,7 +147,59 @@ impl AsRef<Clubcard<W, CRLiteCoverage, ()>> for CRLiteClubcard {
impl std::fmt::Display for CRLiteClubcard {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
self.0.fmt(f)
writeln!(f, "{}", self.0)?;
writeln!(f, "{:=^80}", " Coverage ")?;
writeln!(
f,
"{: ^46} {: >16}{: >16}",
"CT Log ID", "Min Time", "Max Time"
)?;
writeln!(f, "{:-<80}", "")?;
let mut coverage_data = self
.universe()
.0
.iter()
.map(|(log_id, (low, high))| {
(base64::prelude::BASE64_STANDARD.encode(log_id), *low, *high)
})
.collect::<Vec<(String, u64, u64)>>();
coverage_data.sort_by_key(|x| u64::MAX - x.2);
for (log_id, low, high) in coverage_data {
writeln!(f, "{: >46},{: >16},{: >16}", log_id, low, high)?;
}
writeln!(f)?;
writeln!(f, "{:=^80}", " Index ")?;
writeln!(
f,
"{: ^46}{: >10}{: >10}{: >14}",
"Issuer ID", "Exceptions", "Rank", "Bits"
)?;
writeln!(f, "{:-<80}", "")?;
let mut index_data = self
.0
.index()
.iter()
.map(|(block, entry)| {
let filter_size =
entry.approx_filter_m * entry.approx_filter_rank + entry.exact_filter_m;
(
base64::prelude::BASE64_URL_SAFE.encode(block),
entry.approx_filter_rank,
entry.exceptions.len(),
filter_size,
)
})
.collect::<Vec<(String, usize, usize, usize)>>();
index_data.sort_by_key(|x| usize::MAX - x.3);
for (issuer, rank, exceptions, filter_size) in &index_data {
writeln!(
f,
"{: >46},{: >9},{: >9},{: >13}",
issuer, exceptions, rank, filter_size
)?;
}
Ok(())
}
}
@ -168,15 +232,22 @@ impl CRLiteClubcard {
.map_err(|_| ClubcardError::Deserialize)
}
pub fn universe(&self) -> &CRLiteCoverage {
self.0.universe()
}
pub fn index(&self) -> &ClubcardIndex {
self.0.index()
}
pub fn contains<'a>(
&self,
issuer_spki_hash: &'a IssuerSpkiHash,
serial: &'a [u8],
key: &'a CRLiteKey<'a>,
timestamps: impl Iterator<Item = (&'a LogId, Timestamp)>,
) -> CRLiteStatus {
for (log_id, timestamp) in timestamps {
let crlite_key = CRLiteQuery::new(issuer_spki_hash, serial, Some((log_id, timestamp)));
let status = self.0.contains(&crlite_key).into();
let crlite_query = CRLiteQuery::new(key, Some((log_id, timestamp)));
let status = self.0.contains(&crlite_query).into();
if status == CRLiteStatus::NotCovered {
continue;
}

View File

@ -1 +1 @@
{"files":{"Cargo.toml":"f171458a2a360bb0386b23346bc42b16ce372fe2b90c8844cebc83a3e0b72ed3","LICENSE":"1f256ecad192880510e84ad60474eab7589218784b9a50bc7ceee34c2b91f1d5","README.md":"cb41e528a187cc241c4d7a27a77fc49416f74ee16fd1a576cdb173e0155ce384","src/builder.rs":"36043cdf45e77b93c9ac0f8573cdc9d584fb3159ea78e77b425001ab210df279","src/clubcard.rs":"f0b12ed08f0625d46a31377b44275c854c4a98f27c42f71aee37d51e39f57e45","src/equation.rs":"00c8b782a3398a296281acaa942e29d2fa89cafda525ba1ff2cc7142fe6780bf","src/lib.rs":"79701c7179054a801800576868d7eb3a812ca87c4a345b092d16790f92364764","src/query.rs":"23c397a4e20f8009716e7fc5081f3f1473294a49d16713c44087c229eabc4412"},"package":"3d413adde685b0ec7e867186296768474efc2aa952063f40a5198baf760ca983"}
{"files":{"Cargo.lock":"17c365f9dce6301dd7aaa47f4fd13de08b952789f7fca4fec9bacc9f1720a6a2","Cargo.toml":"ca58492dfe5151abc97e002b7dd32b891de16fe257460aa10d7190492002714b","LICENSE":"1f256ecad192880510e84ad60474eab7589218784b9a50bc7ceee34c2b91f1d5","README.md":"cb41e528a187cc241c4d7a27a77fc49416f74ee16fd1a576cdb173e0155ce384","examples/uint_no_partition/2000_nums.in":"a7e6da56ec72abdc807406137a957e0663935dede2fb9b1a542b067ab4b50157","examples/uint_no_partition/generate_test.py":"944a061d3fbe9e01b651c2bf848ad91d90bff371821573ce680d9e00a6d152a2","examples/uint_no_partition/main.rs":"582887b9e98001df7fd1605f0ed062f158dba9233e5b4e9c912842b0a79a75ed","src/builder.rs":"b4fe5fc2131443a18cc09eaa26416627eef9cca76bb55910392084d8b4dd6aa4","src/clubcard.rs":"2bab32f0f0b12ad976b0ef4cbff67fa1586cce68560da008a5b4527de02aad0e","src/equation.rs":"00c8b782a3398a296281acaa942e29d2fa89cafda525ba1ff2cc7142fe6780bf","src/lib.rs":"1135583c2e74ae82c194fd49c07f4a685034ff516ddaa6fa897740e3f4b38b49","src/query.rs":"23c397a4e20f8009716e7fc5081f3f1473294a49d16713c44087c229eabc4412"},"package":"8ec3fe691cfeac642b45d2acee55f4c745fe9eed548380fd41d1fb7daf54297c"}

233
third_party/rust/clubcard/Cargo.lock generated vendored Normal file
View File

@ -0,0 +1,233 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
version = 3
[[package]]
name = "block-buffer"
version = "0.10.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71"
dependencies = [
"generic-array",
]
[[package]]
name = "byteorder"
version = "1.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b"
[[package]]
name = "cfg-if"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
[[package]]
name = "clubcard"
version = "0.3.2"
dependencies = [
"rand",
"serde",
"sha2",
]
[[package]]
name = "cpufeatures"
version = "0.2.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "608697df725056feaccfa42cffdaeeec3fccc4ffc38358ecd19b243e716a78e0"
dependencies = [
"libc",
]
[[package]]
name = "crypto-common"
version = "0.1.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3"
dependencies = [
"generic-array",
"typenum",
]
[[package]]
name = "digest"
version = "0.10.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292"
dependencies = [
"block-buffer",
"crypto-common",
]
[[package]]
name = "generic-array"
version = "0.14.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a"
dependencies = [
"typenum",
"version_check",
]
[[package]]
name = "getrandom"
version = "0.2.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7"
dependencies = [
"cfg-if",
"libc",
"wasi",
]
[[package]]
name = "libc"
version = "0.2.158"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d8adc4bb1803a324070e64a98ae98f38934d91957a99cfb3a43dcbc01bc56439"
[[package]]
name = "ppv-lite86"
version = "0.2.20"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "77957b295656769bb8ad2b6a6b09d897d94f05c41b069aede1fcdaa675eaea04"
dependencies = [
"zerocopy",
]
[[package]]
name = "proc-macro2"
version = "1.0.86"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5e719e8df665df0d1c8fbfd238015744736151d4445ec0836b8e628aae103b77"
dependencies = [
"unicode-ident",
]
[[package]]
name = "quote"
version = "1.0.37"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b5b9d34b8991d19d98081b46eacdd8eb58c6f2b201139f7c5f643cc155a633af"
dependencies = [
"proc-macro2",
]
[[package]]
name = "rand"
version = "0.8.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404"
dependencies = [
"libc",
"rand_chacha",
"rand_core",
]
[[package]]
name = "rand_chacha"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88"
dependencies = [
"ppv-lite86",
"rand_core",
]
[[package]]
name = "rand_core"
version = "0.6.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c"
dependencies = [
"getrandom",
]
[[package]]
name = "serde"
version = "1.0.210"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c8e3592472072e6e22e0a54d5904d9febf8508f65fb8552499a1abc7d1078c3a"
dependencies = [
"serde_derive",
]
[[package]]
name = "serde_derive"
version = "1.0.210"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "243902eda00fad750862fc144cea25caca5e20d615af0a81bee94ca738f1df1f"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "sha2"
version = "0.10.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8"
dependencies = [
"cfg-if",
"cpufeatures",
"digest",
]
[[package]]
name = "syn"
version = "2.0.76"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "578e081a14e0cefc3279b0472138c513f37b41a08d5a3cca9b6e4e8ceb6cd525"
dependencies = [
"proc-macro2",
"quote",
"unicode-ident",
]
[[package]]
name = "typenum"
version = "1.17.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825"
[[package]]
name = "unicode-ident"
version = "1.0.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b"
[[package]]
name = "version_check"
version = "0.9.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a"
[[package]]
name = "wasi"
version = "0.11.0+wasi-snapshot-preview1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
[[package]]
name = "zerocopy"
version = "0.7.35"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1b9b4fd18abc82b8136838da5d50bae7bdea537c574d8dc1a34ed098d6c166f0"
dependencies = [
"byteorder",
"zerocopy-derive",
]
[[package]]
name = "zerocopy-derive"
version = "0.7.35"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e"
dependencies = [
"proc-macro2",
"quote",
"syn",
]

View File

@ -12,7 +12,7 @@
[package]
edition = "2021"
name = "clubcard"
version = "0.3.1"
version = "0.3.2"
authors = ["John M. Schanck <jschanck@mozilla.com>"]
description = "Clubcard is an exact membership query filter for static sets"
readme = "README.md"
@ -27,5 +27,8 @@ optional = true
version = "1.0"
features = ["derive"]
[dev-dependencies.sha2]
version = "0.10"
[features]
builder = ["dep:rand"]

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,17 @@
import sys
from numpy.random import randint;
ARGV = sys.argv
FILENAME = ARGV[1] if len(ARGV) >= 2 else "input.txt"
MAX = (1 << 24)
LEN = 2000
file = open(FILENAME, "w")
file.write(str(LEN) + "\n")
for num in range(LEN):
file.write(str(randint(0, MAX)) + "\n")
file.close()
print("Generate {} numbers within range [0, {}].".format(LEN, MAX))

View File

@ -0,0 +1,157 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
/// Compress a set of u32 integers and output the (approximate) size of compressed bytes.
/// # Arguments
///
/// * `filepath` - The input file containing integers in range [0, max(a_i)].
/// ```txt
/// a_1 \n
/// ...
/// a_n \n
/// ```
/// The universe size will be the maximum value of the input file.
///
/// # Usage
///
/// To run this example, use the following command:
/// ```bash
/// cargo run --features builder --example uint_no_partition
/// ```
///
use clubcard::*;
use sha2::{Digest, Sha256};
use std::cmp::max;
use std::collections::HashSet;
use std::{env, fs, io, process};
use std::io::BufRead;
use clubcard::builder::{ApproximateRibbon, ClubcardBuilder, ExactRibbon};
struct Universe {
bound: u32,
}
const W: usize = 4;
const BLOCK: [u8; 0] = [];
struct Int {
val: [u8; 4], // u32
included: bool, // whether it's in the subset
}
impl Int {
fn new(num: u32, included: bool) -> Int {
Int {
val: num.to_le_bytes(),
included,
}
}
}
impl ApproximateSizeOf for Universe {}
impl AsQuery<W> for Int {
fn as_query(&self, m: usize) -> Equation<W> {
let mut digest = [0u8; 32];
let mut hasher = Sha256::new();
hasher.update(&self.val);
hasher.finalize_into((&mut digest).into());
let mut a = [0u64; W]; // block of columns
for (i, x) in digest
.chunks_exact(8)
.map(|x| TryInto::<[u8; 8]>::try_into(x).unwrap())
.map(u64::from_le_bytes)
.enumerate()
{
a[i] = x;
}
a[0] |= 1;
let s = (a[W - 1] as usize) % max(1, m); //
let b = if self.included { 0 } else { 1 };
Equation::inhomogeneous(s, a, b)
}
fn block(&self) -> &[u8] {
&BLOCK
}
fn discriminant(&self) -> &[u8] {
&self.val
}
}
impl Filterable<W> for Int {
fn included(&self) -> bool {
self.included
}
}
impl Queryable<W> for Int {
type UniverseMetadata = Universe;
type PartitionMetadata = ();
fn in_universe(&self, meta: &Self::UniverseMetadata) -> bool {
u32::from_le_bytes(self.val) < meta.bound
}
}
// Parse the file into a set of integers, return the hash set and maximum element + 1 in set
fn parse_args() -> (u32, HashSet<u32>) {
let args: Vec<String> = env::args().collect();
if args.len() < 2 {
println!("Please specify the name of input file.");
process::exit(1);
}
let file_path = &args[1];
let file = fs::File::open(file_path).expect("Error opening the file.");
let mut lines = io::BufReader::new(file).lines();
let mut numbers = HashSet::new();
let mut max_val = 0;
while let Some(Ok(line)) = lines.next() {
let number = line.trim().parse::<u32>().expect("Failed to parse 32-bit integer");
if number > max_val {
max_val = number;
}
numbers.insert(number);
}
(max_val + 1, numbers)
}
fn main() {
let (universe_size, numbers) = parse_args();
let mut clubcard_builder = ClubcardBuilder::new();
let mut approx_builder = clubcard_builder.new_approx_builder(&BLOCK);
// Build approx filter
for num in &numbers {
let int = Int::new(num.clone(), true);
approx_builder.insert(int)
}
approx_builder.set_universe_size(universe_size.try_into().unwrap());
clubcard_builder.collect_approx_ribbons(vec![ApproximateRibbon::from(approx_builder)]);
// Build exact filter
let mut exact_builder = clubcard_builder.new_exact_builder(&BLOCK);
for num in 0..universe_size {
let int = Int::new(num.clone(), numbers.contains(&num));
exact_builder.insert(int);
}
clubcard_builder.collect_exact_ribbons(vec![ExactRibbon::from(exact_builder)]);
let clubcard = clubcard_builder.build::<Int>(
Universe { bound: universe_size },
(),
);
println!("Generated {}", clubcard);
println!("The size of compressed set (of {} elements) with max value {} is {} bytes.",
numbers.len(), universe_size - 1, clubcard.approximate_size_of());
}

View File

@ -388,14 +388,22 @@ impl<const W: usize, T: Filterable<W>, ApproxOrExact> From<Vec<Ribbon<W, T, Appr
// Since we serialize the block identifiers, offsets, and ranks in the final filter, we
// don't need to encode the zeros.
let mut solution = vec![];
for i in 0..blocks.first().map_or(0, |first| first.rank) {
let max_rank = blocks.first().map_or(0, |first| first.rank);
for i in 0..max_rank {
// Back substitution across blocks.
let mut tail = vec![];
if max_rank > 1 {
// randomizing the tail increases the odds that the solutions will be distinct
tail.push(thread_rng().gen::<u64>());
}
for j in (0..blocks.len()).rev() {
if blocks[j].rank > i {
tail = blocks[j].solve(&tail);
}
}
while let Some(0) = tail.last() {
tail.pop();
}
solution.push(tail);
}

View File

@ -75,12 +75,12 @@ impl<const W: usize, UniverseMetadata, PartitionMetadata> fmt::Display
.sum::<usize>();
writeln!(
f,
"Clubcard of size {} ({} + {})",
"Clubcard of size {} ({} + {}) with {} exceptions",
approx_size + exact_size,
approx_size,
exact_size
)?;
writeln!(f, "- exceptions: {}", exceptions)
exact_size,
exceptions
)
}
}
@ -154,6 +154,10 @@ impl<const W: usize, UniverseMetadata, PartitionMetadata>
pub fn partition(&self) -> &PartitionMetadata {
&self.partition
}
pub fn index(&self) -> &ClubcardIndex {
&self.index
}
}
/// Helper trait for (approximate) heap memory usage analysis in Firefox
@ -184,7 +188,9 @@ where
self.universe.approximate_size_of()
+ self.partition.approximate_size_of()
+ self.index.approximate_size_of()
+ self.approx_filter.iter().map(|x| x.len()).sum::<usize>()
+ self.exact_filter.len()
+ size_of::<Vec<Vec<u8>>>()
+ 8 * self.approx_filter.iter().map(|x| x.len()).sum::<usize>()
+ size_of::<Vec<u8>>()
+ 8 * self.exact_filter.len()
}
}

View File

@ -44,7 +44,7 @@
pub mod builder;
mod clubcard;
pub use clubcard::{ApproximateSizeOf, Clubcard, ClubcardIndexEntry, Membership};
pub use clubcard::{ApproximateSizeOf, Clubcard, ClubcardIndex, ClubcardIndexEntry, Membership};
mod equation;
pub use equation::Equation;