diff --git a/.cargo/mutants.toml b/.cargo/mutants.toml index 8ef34de7d..59d2ca276 100644 --- a/.cargo/mutants.toml +++ b/.cargo/mutants.toml @@ -85,9 +85,10 @@ exclude_re = [ # the empty list (`dynamic::target::NoTargets`), which a test asserts on # and `resolve` turns into `TargetError::NoTargets`; `vec![]` is the body. 'stack-encrypt/src/dynamic/target\.rs:\d+:\d+: replace ::targets -> Vec with vec!\[\]$', - # A passthrough has no kind: `KindOf::passthrough` returns `Ok(None)`, - # which is `Ok(Default::default())`. `a_frame_names_its_kind` asserts it. - 'stack-encrypt/src/dynamic/value_frame\.rs:\d+:\d+: replace ::passthrough -> Result with Ok\(Default::default\(\)\)$', + # A passthrough, and a typed null as any null, has no kind: + # `KindOf::passthrough` and `KindOf::typed_null` return `Ok(None)`, which + # is `Ok(Default::default())`. `a_frame_names_its_kind` asserts the first. + 'stack-encrypt/src/dynamic/value_frame\.rs:\d+:\d+: replace ::(passthrough|typed_null) -> Result with Ok\(Default::default\(\)\)$', # `model`'s `admits` guard on a date, decimal or undefined value is checked # again by vitaminc on every path that reaches it: the frame writer behind # `Modeled` and `ModelOnly` refuses an inadmissible logical value diff --git a/.github/dependabot.yml b/.github/dependabot.yml index 3b16d3955..438ae208c 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -226,8 +226,8 @@ updates: # stack-encrypt behind its optional `stack-encrypt` feature. Those crates # declare these `{ workspace = true }`, so their requirements come from # the root Cargo.toml even when built here. The root entry below ignores - # them because they move by hand with cipherstash-suite: the root - # manifest pins recipher and cllw-ore with `=`, and so does the Go guest. + # them because they move by hand: the root manifest pins recipher, + # clww-ore and ore-rs with `=`, and the Go guest pins recipher with `=`. # Without these lines this entry bumped them in this lockfile and, to # satisfy the exact pins, rewrote the root Cargo.toml without touching # the root Cargo.lock or the guest's pin, breaking every root `--locked` @@ -238,7 +238,8 @@ updates: # scripts/__tests__/dependabot-eql-inherited-ignores.test.mjs fails when # the root entry ignores a crate this entry does not. - dependency-name: "recipher" - - dependency-name: "cllw-ore" + - dependency-name: "clww-ore" + - dependency-name: "ore-rs" - dependency-name: "zerokms-protocol" - dependency-name: "vitaminc*" # Major bumps are reviewed and applied manually, not by Dependabot. @@ -292,14 +293,18 @@ updates: ignore: # Released from cipherstash-suite: stack-auth's API carries their types, # so they move in lockstep with the suite, by hand. The guests pin them - # with `=`; the root Cargo.toml pins recipher and cllw-ore with `=`, and - # gives cts-common and zerokms-protocol caret requirements. + # with `=`; the root Cargo.toml pins recipher with `=`, and gives + # cts-common and zerokms-protocol caret requirements. - dependency-name: "cts-common" - dependency-name: "zerokms-protocol" - dependency-name: "recipher" - - dependency-name: "cllw-ore" - # vitaminc is pinned at 0.5.0 across the crates and the guests; the - # guests' `ValueFrame: Decrypt` bound fails if two versions resolve. + # The order schemes, from cipherstash/ore.rs, moved by hand with + # vitaminc: a new release can change every stored order term. + - dependency-name: "clww-ore" + - dependency-name: "ore-rs" + # vitaminc is pinned at 0.8.0 across the crates. The encrypt guest + # takes it only through stack-encrypt's re-exports, so it cannot + # resolve a second version; one would fail at `ValueFrame: Decrypt`. - dependency-name: "vitaminc*" # Major bumps are reviewed and applied manually, not by Dependabot. - dependency-name: "*" diff --git a/AGENTS.md b/AGENTS.md index 6e0c3a090..3d2527481 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -685,10 +685,12 @@ monorepo, which is where the silent failures are. ## Working on the Rust crates The stack-* crates came from `cipherstash/cipherstash-suite`, which still owns -`cipherstash-client`, `cts-common`, `zerokms-protocol`, `recipher` and -`cllw-ore`. Here those come from crates.io, and `Cargo.lock` holds their -exact versions. In the root `Cargo.toml`, `recipher` and `cllw-ore` are -pinned with `=`. `cts-common` and `zerokms-protocol` take caret +`cipherstash-client`, `cts-common`, `zerokms-protocol` and `recipher`. Here +those come from crates.io, and `Cargo.lock` holds their exact versions. In the +root `Cargo.toml`, `recipher` is pinned with `=`, and so are the order +schemes `clww-ore` (formerly `cllw-ore`) and `ore-rs`, which live in +`cipherstash/ore.rs`: a new release of either can change every stored order +term. `cts-common` and `zerokms-protocol` take caret requirements, because the published `stack-auth` inherits them, and an exact pin would stop the suite sharing one `cts-common` with it. diff --git a/Cargo.lock b/Cargo.lock index 8f144b18b..946a9fc37 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -521,18 +521,17 @@ dependencies = [ ] [[package]] -name = "cllw-ore" -version = "0.5.2-rc.1" +name = "clww-ore" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "24eb4a774d070a6c2b52175b98273cd7193c61e1bda39c1a98b50b7a2d91375a" +checksum = "b95747f5724666cb973b2ca0659e10b6083c11f99877c4727b4c9f534a591c74" dependencies = [ "blake3", "hex", "subtle", "thiserror 1.0.69", - "unicode-normalization", "vitaminc-ore", - "vitaminc-protected 0.6.1", + "vitaminc-protected 0.8.0", "zeroize", ] @@ -981,7 +980,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb" dependencies = [ "libc", - "windows-sys 0.52.0", + "windows-sys 0.61.2", ] [[package]] @@ -1480,7 +1479,7 @@ dependencies = [ "libc", "percent-encoding", "pin-project-lite", - "socket2 0.5.10", + "socket2 0.6.2", "tokio", "tower-service", "tracing", @@ -2138,7 +2137,7 @@ version = "0.50.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7957b9740744892f114936ab4a57b3f487491bbeafaf8083688b16841a4240e5" dependencies = [ - "windows-sys 0.60.2", + "windows-sys 0.61.2", ] [[package]] @@ -2258,32 +2257,26 @@ version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7c87def4c32ab89d880effc9e097653c8da5d6ef28e6b539d313baaacfbafcbe" -[[package]] -name = "orderable-bytes" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c7d30b72ffca73d9936fe5fc80a9c9520c73f5b4f64839a810211903d5ace3c" - [[package]] name = "ore-rs" -version = "0.9.0" +version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0e1d6cb8c1249643266bd60269547c93d3cd263d5385f1262902bbb295ff9a5e" +checksum = "8bd65962ec1409c09d20e1e016f4fe1b4ae2e2e58dba38c155538b2c0801a185" dependencies = [ "aes", "block-modes", "byteorder", "hex", "num", - "orderable-bytes", - "rand 0.8.6", - "rand_chacha 0.3.1", + "rand 0.10.1", "subtle-ng", "thiserror 1.0.69", + "vitaminc-context 0.8.0", "vitaminc-hmac", "vitaminc-ore", "vitaminc-prf", - "vitaminc-protected 0.6.1", + "vitaminc-protected 0.8.0", + "vitaminc-random 0.8.0", "zeroize", ] @@ -2508,7 +2501,7 @@ dependencies = [ "quinn-udp", "rustc-hash", "rustls", - "socket2 0.5.10", + "socket2 0.6.2", "thiserror 2.0.18", "tokio", "tracing", @@ -2547,7 +2540,7 @@ dependencies = [ "cfg_aliases", "libc", "once_cell", - "socket2 0.5.10", + "socket2 0.6.2", "tracing", "windows-sys 0.60.2", ] @@ -2864,7 +2857,7 @@ dependencies = [ "errno", "libc", "linux-raw-sys 0.12.1", - "windows-sys 0.52.0", + "windows-sys 0.61.2", ] [[package]] @@ -2921,7 +2914,7 @@ dependencies = [ "security-framework", "security-framework-sys", "webpki-root-certs", - "windows-sys 0.52.0", + "windows-sys 0.61.2", ] [[package]] @@ -3310,8 +3303,8 @@ dependencies = [ "tracing-subscriber", "url", "uuid", - "vitaminc 0.6.1", - "vitaminc-protected 0.6.1", + "vitaminc 0.8.0", + "vitaminc-protected 0.8.0", "web-time", "zeroize", "zerokms-protocol", @@ -3333,7 +3326,7 @@ dependencies = [ "tempfile", "tokio", "url", - "vitaminc-protected 0.6.1", + "vitaminc-protected 0.8.0", "zeroize", ] @@ -3361,7 +3354,7 @@ name = "stack-encrypt" version = "0.3.0" dependencies = [ "base64ct", - "cllw-ore", + "clww-ore", "miette", "ore-rs", "serde", @@ -3373,14 +3366,14 @@ dependencies = [ "tokio", "trybuild", "uuid", - "vitaminc-aead 0.6.1", + "vitaminc-aead 0.8.0", "vitaminc-aead-frame", - "vitaminc-encrypt 0.6.1", + "vitaminc-encrypt 0.8.0", "vitaminc-hmac", "vitaminc-normalize", "vitaminc-ore", "vitaminc-prf", - "vitaminc-protected 0.6.1", + "vitaminc-protected 0.8.0", "zeroize", "zerokms-protocol", ] @@ -3406,9 +3399,9 @@ dependencies = [ "proptest", "serde_json", "thiserror 1.0.69", - "vitaminc-aead 0.6.1", + "vitaminc-aead 0.8.0", "vitaminc-aead-frame", - "vitaminc-protected 0.6.1", + "vitaminc-protected 0.8.0", "zeroize", ] @@ -3441,8 +3434,8 @@ dependencies = [ "tracing", "url", "uuid", - "vitaminc 0.6.1", - "vitaminc-protected 0.6.1", + "vitaminc 0.8.0", + "vitaminc-protected 0.8.0", "zeroize", "zerokms-protocol", ] @@ -3595,7 +3588,7 @@ dependencies = [ "getrandom 0.4.2", "once_cell", "rustix 1.1.5", - "windows-sys 0.52.0", + "windows-sys 0.61.2", ] [[package]] @@ -4204,16 +4197,16 @@ dependencies = [ [[package]] name = "vitaminc" -version = "0.6.1" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac5c15b6c25efcb9a6111f7108ab8101947a7bf7e9af3ff6d6a73358a1ace0da" +checksum = "ea37168a603d605732d0bf0672586139ab91736f767d7b85e173c84dcee19054" dependencies = [ - "vitaminc-aead 0.6.1", - "vitaminc-context 0.6.1", - "vitaminc-encrypt 0.6.1", - "vitaminc-protected 0.6.1", - "vitaminc-random 0.6.1", - "vitaminc-traits 0.6.1", + "vitaminc-aead 0.8.0", + "vitaminc-context 0.8.0", + "vitaminc-encrypt 0.8.0", + "vitaminc-protected 0.8.0", + "vitaminc-random 0.8.0", + "vitaminc-traits 0.8.0", ] [[package]] @@ -4233,18 +4226,18 @@ dependencies = [ [[package]] name = "vitaminc-aead" -version = "0.6.1" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "71b8c5c4ced92545dce5fd7cf04581d08210def174cc81475cf227fa2506c5b7" +checksum = "e9bb97fd543ee6a2b168e257ec69d0d274a775b1eaa3f856b5ac2941b01891c1" dependencies = [ "bytes", "futures-util", "serde", "thiserror 2.0.18", - "vitaminc-aead-derive 0.6.1", - "vitaminc-context 0.6.1", - "vitaminc-protected 0.6.1", - "vitaminc-random 0.6.1", + "vitaminc-aead-derive 0.8.0", + "vitaminc-context 0.8.0", + "vitaminc-protected 0.8.0", + "vitaminc-random 0.8.0", "zeroize", ] @@ -4261,9 +4254,9 @@ dependencies = [ [[package]] name = "vitaminc-aead-derive" -version = "0.6.1" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c546497a972d0f0498f2f8d5f537c514bad82df8662951c63d0c80023808900" +checksum = "0845a44c07ddc882ed47a0e92e04fc83496220f054b589ad0cbd215c5009e5b7" dependencies = [ "proc-macro2", "quote", @@ -4272,12 +4265,12 @@ dependencies = [ [[package]] name = "vitaminc-aead-frame" -version = "0.6.1" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e35992a269bcaa5b201f1938e54bfbf167bfa6fe975d83cbdbdb54c2a363c5ef" +checksum = "3b0299777255171712a296d59164691dc1e93d10bddaab6e248fede1790dfd2e" dependencies = [ "serde", - "vitaminc-aead 0.6.1", + "vitaminc-aead 0.8.0", "zeroize", ] @@ -4293,12 +4286,12 @@ dependencies = [ [[package]] name = "vitaminc-context" -version = "0.6.1" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa4c4bc2bd9811253eb427657565a45bd4826e2379e93ee1c4d00c808a769882" +checksum = "a630079ba2d50680ee5048addd430eda30613559809dd6d383551e6d3d299826" dependencies = [ "mutants", - "vitaminc-protected 0.6.1", + "vitaminc-protected 0.8.0", ] [[package]] @@ -4317,71 +4310,72 @@ dependencies = [ [[package]] name = "vitaminc-encrypt" -version = "0.6.1" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f0923694602855b33a296d9af473e282e8096c1cfe1b30b8695d3b6651717fc5" +checksum = "db45e073f92ae8ca27f8fe14270bc34c75e767559c2347098dacca95180d1ddd" dependencies = [ "aes-gcm", "aws-lc-rs", - "vitaminc-aead 0.6.1", - "vitaminc-protected 0.6.1", - "vitaminc-random 0.6.1", + "vitaminc-aead 0.8.0", + "vitaminc-protected 0.8.0", + "vitaminc-random 0.8.0", "zeroize", ] [[package]] name = "vitaminc-hmac" -version = "0.6.1" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd361f626e95cbe770b9d012e4a86c43cfefe4aefb3d5b3ed9339a83085bdc53" +checksum = "b5fa0ae8bbad85ae30fb5c91b0b72b694d59bf2c2c1e7ad799eda66fdbd67e7c" dependencies = [ "hmac", "sha2 0.11.0", "vitaminc-prf", - "vitaminc-protected 0.6.1", + "vitaminc-protected 0.8.0", "zeroize", ] [[package]] name = "vitaminc-normalize" -version = "0.6.1" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "214b2a9d085924c3bc3c91f3ba74238e8848bf54990e5f48f170c71fbacea07a" +checksum = "f5a2d8875e0b8b35b7a4f9dd698bbd13c989837cea564b5a4cbb5371b78fa937" dependencies = [ "thiserror 2.0.18", "unicode-general-category", "unicode-normalization", - "vitaminc-aead 0.6.1", - "vitaminc-protected 0.6.1", + "vitaminc-aead 0.8.0", + "vitaminc-protected 0.8.0", ] [[package]] name = "vitaminc-ore" -version = "0.6.1" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed88c54b5f06f2177ecbfb7666812adf645406f6fb555f4e2f0fd7fa218e71c4" +checksum = "f05518b4d35cb0c592dad59afb11b8e883ea252449b9ae47ff5ddeff0ed49f75" dependencies = [ "thiserror 2.0.18", "unicode-general-category", "unicode-normalization", - "vitaminc-aead 0.6.1", - "vitaminc-context 0.6.1", + "vitaminc-aead 0.8.0", + "vitaminc-context 0.8.0", "vitaminc-normalize", - "vitaminc-protected 0.6.1", + "vitaminc-protected 0.8.0", + "zeroize", ] [[package]] name = "vitaminc-prf" -version = "0.6.1" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c2715cca25006b4656223bc932ab4fd7f70d387aa4ec63a4e2ef33aa8cd2b3a5" +checksum = "916688478273ca3e5c6805b355534ce9263688391cd4ab23b08bef760039d325" dependencies = [ "mutants", "thiserror 2.0.18", - "vitaminc-aead 0.6.1", - "vitaminc-context 0.6.1", + "vitaminc-aead 0.8.0", + "vitaminc-context 0.8.0", "vitaminc-normalize", - "vitaminc-protected 0.6.1", + "vitaminc-protected 0.8.0", ] [[package]] @@ -4403,9 +4397,9 @@ dependencies = [ [[package]] name = "vitaminc-protected" -version = "0.6.1" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1bb76dd473f5aa89b844f92018ebe3041deb8e5390e7061cca4283d959ff855" +checksum = "a6edc22562a9bbff0ba9704a2c43670b2c7cb1637524c045c3ba6436ed00917f" dependencies = [ "bitvec", "digest 0.11.3", @@ -4414,7 +4408,7 @@ dependencies = [ "serde_bytes", "subtle", "thiserror 2.0.18", - "vitaminc-protected-derive 0.6.1", + "vitaminc-protected-derive 0.8.0", "zeroize", ] @@ -4431,9 +4425,9 @@ dependencies = [ [[package]] name = "vitaminc-protected-derive" -version = "0.6.1" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7478ed160c019059746e75fc613563dcdcd5266d155a34601d29377a1c4afc3" +checksum = "a7cce3a7d0ce6f57c0e82345f20e87f3737cccd3a70aec2a2ab49f68a3a5e24a" dependencies = [ "proc-macro-crate", "proc-macro2", @@ -4458,16 +4452,16 @@ dependencies = [ [[package]] name = "vitaminc-random" -version = "0.6.1" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b477af7c01c3d9ef2647e46952ad3df7f246b3f806b1d4009ee83beecec613a" +checksum = "8bb253f783ce6f31a55a92f5a9f0526109b8caa6a465edb94244fd344a078c11" dependencies = [ "chacha20", "getrandom 0.4.2", "rand 0.10.1", "thiserror 2.0.18", - "vitaminc-protected 0.6.1", - "vitaminc-random-derives 0.6.1", + "vitaminc-protected 0.8.0", + "vitaminc-random-derives 0.8.0", "zeroize", ] @@ -4484,9 +4478,9 @@ dependencies = [ [[package]] name = "vitaminc-random-derives" -version = "0.6.1" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ab5a0de8da428c6789dc067a578a0462e411099721d616736cf29e1622230c35" +checksum = "df0b3615936d6dded4b775856f4b0fa229d745d183f0b3754ac80035f16c27d9" dependencies = [ "proc-macro2", "quote", @@ -4511,17 +4505,17 @@ dependencies = [ [[package]] name = "vitaminc-traits" -version = "0.6.1" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a900f0edcacd49c8557ab54722175869fec66926054a6fbdc53a05069db3c922" +checksum = "1e9098ee4b13446ef959583ee2f3c384df571b453179104f7b4960ffddf65ee9" dependencies = [ "anyhow", "bytes", "rmp-serde", "serde", "thiserror 2.0.18", - "vitaminc-protected 0.6.1", - "vitaminc-random 0.6.1", + "vitaminc-protected 0.8.0", + "vitaminc-random 0.8.0", "zeroize", ] @@ -4779,7 +4773,7 @@ version = "0.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22" dependencies = [ - "windows-sys 0.52.0", + "windows-sys 0.61.2", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index 01b7861bc..0d0ec9100 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -76,20 +76,21 @@ stack-profile = { path = "./packages/stack-profile", version = "0.43.0" } # cts-common and zerokms-protocol take caret requirements because the # published stack-auth inherits them: an exact pin would stop the suite # unifying stack-auth with a later compatible cts-common, and a second copy -# breaks the shared Crn, Region and WorkspaceId types. recipher and cllw-ore -# feed only unpublished crates, so they stay exact. +# breaks the shared Crn, Region and WorkspaceId types. recipher feeds +# only unpublished crates, so it stays exact. cts-common = { version = "0.43.0", default-features = false } zerokms-protocol = "0.12.31" recipher = "=0.3.1" -# cllw-ore's `vitaminc` feature implements vitaminc-ore's `OrderScheme`, -# which Stack Encrypt's order terms are encrypted through. It first ships -# in a pre-release, and Cargo resolves a pre-release only when named. -cllw-ore = { version = "=0.5.2-rc.1", default-features = false, features = ["vitaminc"] } -# ore-rs's `vitaminc` feature implements the same traits for block ORE: -# `Bit6BlockOre` (fixed width up to ten bytes) and `ChainedBlockOre` -# (variable length), the 6-bit schemes EQL v4's `_ord_ore` domains store. -# Both wire formats are frozen as of 0.9.0. ore-rs feeds only stack-encrypt. -ore-rs = { version = "0.9.0", default-features = false, features = ["vitaminc"] } +# The two order-preserving schemes Stack Encrypt's order terms encrypt +# through. Both implement vitaminc-ore's `OrderScheme` against vitaminc 0.8: +# `clww-ore` (cllw-ore renamed) for CLWW ORE and OPE, and ore-rs's +# `BlockOre` for block ORE, which routes a value to its 6-bit fixed-width +# engine (up to ten bytes) or its chained one (wider, or variable length), +# the terms EQL v4's `_ord_ore` domains store. +# vitaminc is a plain dependency of both from here, not a feature. Both are +# pinned exactly: a new release can change every stored order term. +clww-ore = { version = "=0.6.0", default-features = false } +ore-rs = { version = "=0.10.0", default-features = false } # External dependencies, with the suite's feature lists. base64 = "0.22.0" @@ -136,18 +137,18 @@ web-time = "1.1" zeroize = { version = "1.8.1", features = ["derive"] } # This is needed because lock_api 0.4.6 was breaking things and the branch forces the use of 0.4.12 temp-env = { git = "https://github.com/cipherstash/temp-env", branch = "main" } -vitaminc = { version = "0.6.1", features = ["random", "protected", "encrypt"] } -vitaminc-aead = "0.6.1" +vitaminc = { version = "0.8.0", features = ["random", "protected", "encrypt"] } +vitaminc-aead = "0.8.0" # The transport frame and ciphertext codec every language binding carries # across its FFI boundary. Optional in stack-encrypt (the `dynamic` feature). -vitaminc-aead-frame = "0.6.1" -vitaminc-encrypt = "0.6.1" -vitaminc-hmac = "0.6.1" +vitaminc-aead-frame = "0.8.0" +vitaminc-encrypt = "0.8.0" +vitaminc-hmac = "0.8.0" # Normalized equality terms (Unicode 16 NFC text, one integer encoding for # every width), which `vitaminc-prf`'s `normalize` feature derives over. -vitaminc-normalize = "0.6.1" +vitaminc-normalize = "0.8.0" # The text order key: the system ADR-0002's fold, pinned to Unicode 16, # which text ORE and OPE terms are derived over (ADR-0009). -vitaminc-ore = "0.6.1" -vitaminc-prf = { version = "0.6.1", features = ["normalize"] } -vitaminc-protected = "0.6.1" +vitaminc-ore = "0.8.0" +vitaminc-prf = { version = "0.8.0", features = ["normalize"] } +vitaminc-protected = "0.8.0" diff --git a/languages/golang/CHANGELOG.md b/languages/golang/CHANGELOG.md index 68a877461..ac917da20 100644 --- a/languages/golang/CHANGELOG.md +++ b/languages/golang/CHANGELOG.md @@ -12,6 +12,12 @@ listed under **Breaking**. Releases are tagged `languages/golang/vX.Y.Z`. ### Breaking +- **Every order term changes: re-derive stored `ore`, `ope` and + `ore_block` index terms.** The engine moved to vitaminc 0.8, clww-ore 0.6 + (formerly cllw-ore) and ore-rs 0.10, and both order schemes now derive + different terms for the same value, so a query term no longer compares + with an order term stored before. Ciphertexts and equality terms are + unchanged. - **An `int8`, `int16`, `uint8` or `uint16` sealed field seals at its own width; run stashgen again.** It used to seal as a 32-bit integer. Values stored before do not decrypt under the regenerated declaration: the diff --git a/languages/golang/auth/guest/Cargo.lock b/languages/golang/auth/guest/Cargo.lock index ce1a5e7eb..fd1ccb4c5 100644 --- a/languages/golang/auth/guest/Cargo.lock +++ b/languages/golang/auth/guest/Cargo.lock @@ -1847,8 +1847,8 @@ dependencies = [ "tracing", "url", "uuid", - "vitaminc 0.6.1", - "vitaminc-protected 0.6.1", + "vitaminc 0.8.0", + "vitaminc-protected 0.8.0", "web-time", "zeroize", "zerokms-protocol", @@ -1867,7 +1867,7 @@ dependencies = [ "stack-profile", "tempfile", "url", - "vitaminc-protected 0.6.1", + "vitaminc-protected 0.8.0", "zeroize", ] @@ -1878,9 +1878,9 @@ dependencies = [ "miette", "serde_json", "thiserror 1.0.69", - "vitaminc-aead 0.6.1", + "vitaminc-aead 0.8.0", "vitaminc-aead-frame", - "vitaminc-protected 0.6.1", + "vitaminc-protected 0.8.0", "zeroize", ] @@ -2299,16 +2299,16 @@ dependencies = [ [[package]] name = "vitaminc" -version = "0.6.1" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac5c15b6c25efcb9a6111f7108ab8101947a7bf7e9af3ff6d6a73358a1ace0da" +checksum = "ea37168a603d605732d0bf0672586139ab91736f767d7b85e173c84dcee19054" dependencies = [ - "vitaminc-aead 0.6.1", - "vitaminc-context 0.6.1", - "vitaminc-encrypt 0.6.1", - "vitaminc-protected 0.6.1", - "vitaminc-random 0.6.1", - "vitaminc-traits 0.6.1", + "vitaminc-aead 0.8.0", + "vitaminc-context 0.8.0", + "vitaminc-encrypt 0.8.0", + "vitaminc-protected 0.8.0", + "vitaminc-random 0.8.0", + "vitaminc-traits 0.8.0", ] [[package]] @@ -2328,18 +2328,18 @@ dependencies = [ [[package]] name = "vitaminc-aead" -version = "0.6.1" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "71b8c5c4ced92545dce5fd7cf04581d08210def174cc81475cf227fa2506c5b7" +checksum = "e9bb97fd543ee6a2b168e257ec69d0d274a775b1eaa3f856b5ac2941b01891c1" dependencies = [ "bytes", "futures-util", "serde", "thiserror 2.0.20", - "vitaminc-aead-derive 0.6.1", - "vitaminc-context 0.6.1", - "vitaminc-protected 0.6.1", - "vitaminc-random 0.6.1", + "vitaminc-aead-derive 0.8.0", + "vitaminc-context 0.8.0", + "vitaminc-protected 0.8.0", + "vitaminc-random 0.8.0", "zeroize", ] @@ -2356,9 +2356,9 @@ dependencies = [ [[package]] name = "vitaminc-aead-derive" -version = "0.6.1" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c546497a972d0f0498f2f8d5f537c514bad82df8662951c63d0c80023808900" +checksum = "0845a44c07ddc882ed47a0e92e04fc83496220f054b589ad0cbd215c5009e5b7" dependencies = [ "proc-macro2", "quote", @@ -2367,11 +2367,11 @@ dependencies = [ [[package]] name = "vitaminc-aead-frame" -version = "0.6.1" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e35992a269bcaa5b201f1938e54bfbf167bfa6fe975d83cbdbdb54c2a363c5ef" +checksum = "3b0299777255171712a296d59164691dc1e93d10bddaab6e248fede1790dfd2e" dependencies = [ - "vitaminc-aead 0.6.1", + "vitaminc-aead 0.8.0", ] [[package]] @@ -2386,12 +2386,12 @@ dependencies = [ [[package]] name = "vitaminc-context" -version = "0.6.1" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa4c4bc2bd9811253eb427657565a45bd4826e2379e93ee1c4d00c808a769882" +checksum = "a630079ba2d50680ee5048addd430eda30613559809dd6d383551e6d3d299826" dependencies = [ "mutants", - "vitaminc-protected 0.6.1", + "vitaminc-protected 0.8.0", ] [[package]] @@ -2410,15 +2410,15 @@ dependencies = [ [[package]] name = "vitaminc-encrypt" -version = "0.6.1" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f0923694602855b33a296d9af473e282e8096c1cfe1b30b8695d3b6651717fc5" +checksum = "db45e073f92ae8ca27f8fe14270bc34c75e767559c2347098dacca95180d1ddd" dependencies = [ "aes-gcm", "aws-lc-rs", - "vitaminc-aead 0.6.1", - "vitaminc-protected 0.6.1", - "vitaminc-random 0.6.1", + "vitaminc-aead 0.8.0", + "vitaminc-protected 0.8.0", + "vitaminc-random 0.8.0", "zeroize", ] @@ -2441,9 +2441,9 @@ dependencies = [ [[package]] name = "vitaminc-protected" -version = "0.6.1" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1bb76dd473f5aa89b844f92018ebe3041deb8e5390e7061cca4283d959ff855" +checksum = "a6edc22562a9bbff0ba9704a2c43670b2c7cb1637524c045c3ba6436ed00917f" dependencies = [ "bitvec", "digest 0.11.3", @@ -2452,7 +2452,7 @@ dependencies = [ "serde_bytes", "subtle", "thiserror 2.0.20", - "vitaminc-protected-derive 0.6.1", + "vitaminc-protected-derive 0.8.0", "zeroize", ] @@ -2469,9 +2469,9 @@ dependencies = [ [[package]] name = "vitaminc-protected-derive" -version = "0.6.1" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7478ed160c019059746e75fc613563dcdcd5266d155a34601d29377a1c4afc3" +checksum = "a7cce3a7d0ce6f57c0e82345f20e87f3737cccd3a70aec2a2ab49f68a3a5e24a" dependencies = [ "proc-macro-crate", "proc-macro2", @@ -2496,16 +2496,16 @@ dependencies = [ [[package]] name = "vitaminc-random" -version = "0.6.1" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b477af7c01c3d9ef2647e46952ad3df7f246b3f806b1d4009ee83beecec613a" +checksum = "8bb253f783ce6f31a55a92f5a9f0526109b8caa6a465edb94244fd344a078c11" dependencies = [ "chacha20", "getrandom 0.4.3", "rand 0.10.3", "thiserror 2.0.20", - "vitaminc-protected 0.6.1", - "vitaminc-random-derives 0.6.1", + "vitaminc-protected 0.8.0", + "vitaminc-random-derives 0.8.0", "zeroize", ] @@ -2522,9 +2522,9 @@ dependencies = [ [[package]] name = "vitaminc-random-derives" -version = "0.6.1" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ab5a0de8da428c6789dc067a578a0462e411099721d616736cf29e1622230c35" +checksum = "df0b3615936d6dded4b775856f4b0fa229d745d183f0b3754ac80035f16c27d9" dependencies = [ "proc-macro2", "quote", @@ -2549,17 +2549,17 @@ dependencies = [ [[package]] name = "vitaminc-traits" -version = "0.6.1" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a900f0edcacd49c8557ab54722175869fec66926054a6fbdc53a05069db3c922" +checksum = "1e9098ee4b13446ef959583ee2f3c384df571b453179104f7b4960ffddf65ee9" dependencies = [ "anyhow", "bytes", "rmp-serde", "serde", "thiserror 2.0.20", - "vitaminc-protected 0.6.1", - "vitaminc-random 0.6.1", + "vitaminc-protected 0.8.0", + "vitaminc-random 0.8.0", "zeroize", ] diff --git a/languages/golang/auth/guest/Cargo.toml b/languages/golang/auth/guest/Cargo.toml index df3ce1563..8ffa0937d 100644 --- a/languages/golang/auth/guest/Cargo.toml +++ b/languages/golang/auth/guest/Cargo.toml @@ -48,7 +48,7 @@ zeroize = { version = "1", features = ["derive"] } serde_json = "1" tempfile = "3" # `Controlled::risky_ref`, to read a codec value back in the tests. -vitaminc-protected = "0.6.0" +vitaminc-protected = "0.8.0" [profile.release] # Smaller .wasm; the guest is IO-bound on the FFI copy and the file reads, diff --git a/languages/golang/cmd/stashgen/README.md b/languages/golang/cmd/stashgen/README.md index 36788edd3..3162fe90f 100644 --- a/languages/golang/cmd/stashgen/README.md +++ b/languages/golang/cmd/stashgen/README.md @@ -256,7 +256,7 @@ An `opaque` struct crosses as one JSON document and is one column, decoded back A float in an opaque struct must be finite: `encoding/json` refuses NaN and the infinities, so `Encrypt` fails for the batch with `encrypt.ErrEncoding`. A sealed float field outside an opaque struct carries them. A sealed field outside an opaque struct is one scalar, or a type defined over one; a struct, slice or map field seals only inside an opaque struct. The scalars are `string`, `[]byte`, `bool`, every integer type (each sealed at its own width, `int` and `uint` as 64-bit), `encrypt.Int128` and `encrypt.Uint128`, `float32`, `float64`, `encrypt.Decimal`, `encrypt.Date` and `time.Time` (a timestamp). The wire type `stashgen` writes for each is the field's own: `int8` is `gensupport.Int8`, `time.Time` is `gensupport.Timestamp`, and so on. -An order index (`ore`, `ope`) on a decimal, date or timestamp is refused: those order terms wait for new cllw-ore and ore-rs releases (#1236). +An order index (`ore`, `ope`) on a decimal, date or timestamp is refused: those order terms are not supported yet (#1236). The zero `encrypt.Date` is not a date: a date field must be set, and `Encrypt` refuses a zero one with `encrypt.ErrEncoding`, naming the field. A sealed field cannot be a pointer (`*encrypt.Date` is refused as a composite), so an optional date has no sealed form yet: keep it in an opaque struct, or store a sentinel date. A nil `[]byte` in a sealed field, or a nil slice of a type defined over `[]byte`, comes back from `Decrypt` as an empty, non-nil slice; inside an opaque struct, nil comes back as nil. A protobuf message with a `oneof` cannot be generated from a policy: protoc-gen-go puts its members in wrapper types, not in the message struct, and `Generate` refuses it. diff --git a/languages/golang/encrypt/doc.go b/languages/golang/encrypt/doc.go index e29d052b6..821937099 100644 --- a/languages/golang/encrypt/doc.go +++ b/languages/golang/encrypt/doc.go @@ -123,9 +123,10 @@ // or [Int128] and [Uint128]), a float32 or float64, a [Decimal], a [Date] or a // time.Time (a timestamp), or a type defined over one of the built-in types. // Each integer seals at its own width. Equality applies to every one but a -// bool; ORE and OPE to the integers, text, bytes and floats, and not yet to a -// decimal, date or timestamp, whose order terms wait for new cllw-ore and -// ore-rs releases (#1236). +// bool. ORE and OPE apply to integers of 16 bits or more, floats, text and +// bytes. A bool or an 8-bit integer takes no order index, since over so few +// values its order terms would show which rows hold which value. Decimals, +// dates and timestamps cannot take an order index yet. // // Passthrough fields never cross the binding: the engine does nothing to a // passthrough value that a program could observe, and the FFI codec cannot diff --git a/languages/golang/encrypt/guest/Cargo.lock b/languages/golang/encrypt/guest/Cargo.lock index f9bc1224b..b5903fa5b 100644 --- a/languages/golang/encrypt/guest/Cargo.lock +++ b/languages/golang/encrypt/guest/Cargo.lock @@ -350,18 +350,17 @@ dependencies = [ ] [[package]] -name = "cllw-ore" -version = "0.5.2-rc.1" +name = "clww-ore" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "24eb4a774d070a6c2b52175b98273cd7193c61e1bda39c1a98b50b7a2d91375a" +checksum = "b95747f5724666cb973b2ca0659e10b6083c11f99877c4727b4c9f534a591c74" dependencies = [ "blake3", "hex", "subtle", "thiserror 1.0.69", - "unicode-normalization", "vitaminc-ore", - "vitaminc-protected 0.6.1", + "vitaminc-protected 0.8.0", "zeroize", ] @@ -724,7 +723,7 @@ dependencies = [ "stack-encrypt", "thiserror 2.0.20", "ts-rs", - "vitaminc-aead 0.6.1", + "vitaminc-aead 0.8.0", "zeroize", ] @@ -1457,32 +1456,26 @@ dependencies = [ "libc", ] -[[package]] -name = "orderable-bytes" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c7d30b72ffca73d9936fe5fc80a9c9520c73f5b4f64839a810211903d5ace3c" - [[package]] name = "ore-rs" -version = "0.9.0" +version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0e1d6cb8c1249643266bd60269547c93d3cd263d5385f1262902bbb295ff9a5e" +checksum = "8bd65962ec1409c09d20e1e016f4fe1b4ae2e2e58dba38c155538b2c0801a185" dependencies = [ "aes", "block-modes", "byteorder", "hex", "num", - "orderable-bytes", - "rand 0.8.8", - "rand_chacha 0.3.1", + "rand 0.10.2", "subtle-ng", "thiserror 1.0.69", + "vitaminc-context 0.8.0", "vitaminc-hmac", "vitaminc-ore", "vitaminc-prf", - "vitaminc-protected 0.6.1", + "vitaminc-protected 0.8.0", + "vitaminc-random 0.8.0", "zeroize", ] @@ -2151,8 +2144,8 @@ dependencies = [ "tracing", "url", "uuid", - "vitaminc 0.6.1", - "vitaminc-protected 0.6.1", + "vitaminc 0.8.0", + "vitaminc-protected 0.8.0", "web-time", "zeroize", "zerokms-protocol", @@ -2163,7 +2156,7 @@ name = "stack-encrypt" version = "0.3.0" dependencies = [ "base64ct", - "cllw-ore", + "clww-ore", "miette", "ore-rs", "serde", @@ -2172,14 +2165,14 @@ dependencies = [ "stack-kms", "thiserror 1.0.69", "uuid", - "vitaminc-aead 0.6.1", + "vitaminc-aead 0.8.0", "vitaminc-aead-frame", - "vitaminc-encrypt 0.6.1", + "vitaminc-encrypt 0.8.0", "vitaminc-hmac", "vitaminc-normalize", "vitaminc-ore", "vitaminc-prf", - "vitaminc-protected 0.6.1", + "vitaminc-protected 0.8.0", "zeroize", ] @@ -2208,9 +2201,6 @@ dependencies = [ "stack-guest-abi", "stack-kms", "uuid", - "vitaminc-aead 0.6.1", - "vitaminc-aead-frame", - "vitaminc-protected 0.6.1", "zeroize", "zerokms-protocol", ] @@ -2222,9 +2212,9 @@ dependencies = [ "miette", "serde_json", "thiserror 1.0.69", - "vitaminc-aead 0.6.1", + "vitaminc-aead 0.8.0", "vitaminc-aead-frame", - "vitaminc-protected 0.6.1", + "vitaminc-protected 0.8.0", "zeroize", ] @@ -2250,8 +2240,8 @@ dependencies = [ "tracing", "url", "uuid", - "vitaminc 0.6.1", - "vitaminc-protected 0.6.1", + "vitaminc 0.8.0", + "vitaminc-protected 0.8.0", "zeroize", "zerokms-protocol", ] @@ -2726,16 +2716,16 @@ dependencies = [ [[package]] name = "vitaminc" -version = "0.6.1" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac5c15b6c25efcb9a6111f7108ab8101947a7bf7e9af3ff6d6a73358a1ace0da" +checksum = "ea37168a603d605732d0bf0672586139ab91736f767d7b85e173c84dcee19054" dependencies = [ - "vitaminc-aead 0.6.1", - "vitaminc-context 0.6.1", - "vitaminc-encrypt 0.6.1", - "vitaminc-protected 0.6.1", - "vitaminc-random 0.6.1", - "vitaminc-traits 0.6.1", + "vitaminc-aead 0.8.0", + "vitaminc-context 0.8.0", + "vitaminc-encrypt 0.8.0", + "vitaminc-protected 0.8.0", + "vitaminc-random 0.8.0", + "vitaminc-traits 0.8.0", ] [[package]] @@ -2755,18 +2745,18 @@ dependencies = [ [[package]] name = "vitaminc-aead" -version = "0.6.1" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "71b8c5c4ced92545dce5fd7cf04581d08210def174cc81475cf227fa2506c5b7" +checksum = "e9bb97fd543ee6a2b168e257ec69d0d274a775b1eaa3f856b5ac2941b01891c1" dependencies = [ "bytes", "futures-util", "serde", "thiserror 2.0.20", - "vitaminc-aead-derive 0.6.1", - "vitaminc-context 0.6.1", - "vitaminc-protected 0.6.1", - "vitaminc-random 0.6.1", + "vitaminc-aead-derive 0.8.0", + "vitaminc-context 0.8.0", + "vitaminc-protected 0.8.0", + "vitaminc-random 0.8.0", "zeroize", ] @@ -2783,9 +2773,9 @@ dependencies = [ [[package]] name = "vitaminc-aead-derive" -version = "0.6.1" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c546497a972d0f0498f2f8d5f537c514bad82df8662951c63d0c80023808900" +checksum = "0845a44c07ddc882ed47a0e92e04fc83496220f054b589ad0cbd215c5009e5b7" dependencies = [ "proc-macro2", "quote", @@ -2794,12 +2784,12 @@ dependencies = [ [[package]] name = "vitaminc-aead-frame" -version = "0.6.1" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e35992a269bcaa5b201f1938e54bfbf167bfa6fe975d83cbdbdb54c2a363c5ef" +checksum = "3b0299777255171712a296d59164691dc1e93d10bddaab6e248fede1790dfd2e" dependencies = [ "serde", - "vitaminc-aead 0.6.1", + "vitaminc-aead 0.8.0", "zeroize", ] @@ -2815,12 +2805,12 @@ dependencies = [ [[package]] name = "vitaminc-context" -version = "0.6.1" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa4c4bc2bd9811253eb427657565a45bd4826e2379e93ee1c4d00c808a769882" +checksum = "a630079ba2d50680ee5048addd430eda30613559809dd6d383551e6d3d299826" dependencies = [ "mutants", - "vitaminc-protected 0.6.1", + "vitaminc-protected 0.8.0", ] [[package]] @@ -2839,71 +2829,72 @@ dependencies = [ [[package]] name = "vitaminc-encrypt" -version = "0.6.1" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f0923694602855b33a296d9af473e282e8096c1cfe1b30b8695d3b6651717fc5" +checksum = "db45e073f92ae8ca27f8fe14270bc34c75e767559c2347098dacca95180d1ddd" dependencies = [ "aes-gcm", "aws-lc-rs", - "vitaminc-aead 0.6.1", - "vitaminc-protected 0.6.1", - "vitaminc-random 0.6.1", + "vitaminc-aead 0.8.0", + "vitaminc-protected 0.8.0", + "vitaminc-random 0.8.0", "zeroize", ] [[package]] name = "vitaminc-hmac" -version = "0.6.1" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd361f626e95cbe770b9d012e4a86c43cfefe4aefb3d5b3ed9339a83085bdc53" +checksum = "b5fa0ae8bbad85ae30fb5c91b0b72b694d59bf2c2c1e7ad799eda66fdbd67e7c" dependencies = [ "hmac", "sha2 0.11.0", "vitaminc-prf", - "vitaminc-protected 0.6.1", + "vitaminc-protected 0.8.0", "zeroize", ] [[package]] name = "vitaminc-normalize" -version = "0.6.1" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "214b2a9d085924c3bc3c91f3ba74238e8848bf54990e5f48f170c71fbacea07a" +checksum = "f5a2d8875e0b8b35b7a4f9dd698bbd13c989837cea564b5a4cbb5371b78fa937" dependencies = [ "thiserror 2.0.20", "unicode-general-category", "unicode-normalization", - "vitaminc-aead 0.6.1", - "vitaminc-protected 0.6.1", + "vitaminc-aead 0.8.0", + "vitaminc-protected 0.8.0", ] [[package]] name = "vitaminc-ore" -version = "0.6.1" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed88c54b5f06f2177ecbfb7666812adf645406f6fb555f4e2f0fd7fa218e71c4" +checksum = "f05518b4d35cb0c592dad59afb11b8e883ea252449b9ae47ff5ddeff0ed49f75" dependencies = [ "thiserror 2.0.20", "unicode-general-category", "unicode-normalization", - "vitaminc-aead 0.6.1", - "vitaminc-context 0.6.1", + "vitaminc-aead 0.8.0", + "vitaminc-context 0.8.0", "vitaminc-normalize", - "vitaminc-protected 0.6.1", + "vitaminc-protected 0.8.0", + "zeroize", ] [[package]] name = "vitaminc-prf" -version = "0.6.1" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c2715cca25006b4656223bc932ab4fd7f70d387aa4ec63a4e2ef33aa8cd2b3a5" +checksum = "916688478273ca3e5c6805b355534ce9263688391cd4ab23b08bef760039d325" dependencies = [ "mutants", "thiserror 2.0.20", - "vitaminc-aead 0.6.1", - "vitaminc-context 0.6.1", + "vitaminc-aead 0.8.0", + "vitaminc-context 0.8.0", "vitaminc-normalize", - "vitaminc-protected 0.6.1", + "vitaminc-protected 0.8.0", ] [[package]] @@ -2925,9 +2916,9 @@ dependencies = [ [[package]] name = "vitaminc-protected" -version = "0.6.1" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1bb76dd473f5aa89b844f92018ebe3041deb8e5390e7061cca4283d959ff855" +checksum = "a6edc22562a9bbff0ba9704a2c43670b2c7cb1637524c045c3ba6436ed00917f" dependencies = [ "bitvec", "digest 0.11.3", @@ -2936,7 +2927,7 @@ dependencies = [ "serde_bytes", "subtle", "thiserror 2.0.20", - "vitaminc-protected-derive 0.6.1", + "vitaminc-protected-derive 0.8.0", "zeroize", ] @@ -2953,9 +2944,9 @@ dependencies = [ [[package]] name = "vitaminc-protected-derive" -version = "0.6.1" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7478ed160c019059746e75fc613563dcdcd5266d155a34601d29377a1c4afc3" +checksum = "a7cce3a7d0ce6f57c0e82345f20e87f3737cccd3a70aec2a2ab49f68a3a5e24a" dependencies = [ "proc-macro-crate", "proc-macro2", @@ -2980,16 +2971,16 @@ dependencies = [ [[package]] name = "vitaminc-random" -version = "0.6.1" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b477af7c01c3d9ef2647e46952ad3df7f246b3f806b1d4009ee83beecec613a" +checksum = "8bb253f783ce6f31a55a92f5a9f0526109b8caa6a465edb94244fd344a078c11" dependencies = [ "chacha20", "getrandom 0.4.3", "rand 0.10.2", "thiserror 2.0.20", - "vitaminc-protected 0.6.1", - "vitaminc-random-derives 0.6.1", + "vitaminc-protected 0.8.0", + "vitaminc-random-derives 0.8.0", "zeroize", ] @@ -3006,9 +2997,9 @@ dependencies = [ [[package]] name = "vitaminc-random-derives" -version = "0.6.1" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ab5a0de8da428c6789dc067a578a0462e411099721d616736cf29e1622230c35" +checksum = "df0b3615936d6dded4b775856f4b0fa229d745d183f0b3754ac80035f16c27d9" dependencies = [ "proc-macro2", "quote", @@ -3033,17 +3024,17 @@ dependencies = [ [[package]] name = "vitaminc-traits" -version = "0.6.1" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a900f0edcacd49c8557ab54722175869fec66926054a6fbdc53a05069db3c922" +checksum = "1e9098ee4b13446ef959583ee2f3c384df571b453179104f7b4960ffddf65ee9" dependencies = [ "anyhow", "bytes", "rmp-serde", "serde", "thiserror 2.0.20", - "vitaminc-protected 0.6.1", - "vitaminc-random 0.6.1", + "vitaminc-protected 0.8.0", + "vitaminc-random 0.8.0", "zeroize", ] diff --git a/languages/golang/encrypt/guest/Cargo.toml b/languages/golang/encrypt/guest/Cargo.toml index e39ab37b0..4df0b70ba 100644 --- a/languages/golang/encrypt/guest/Cargo.toml +++ b/languages/golang/encrypt/guest/Cargo.toml @@ -61,13 +61,11 @@ stack-kms = { path = "../../../../packages/stack-kms", default-features = false eql-bindings = { path = "../../../../packages/eql/crates/eql-bindings", features = ["targets"], optional = true } zerokms-protocol = "=0.12.31" -# The transport frame and ciphertext codec, shared with vitaminc's own -# guest — one codec, not a fork. Same vitaminc version stack-encrypt builds -# against (see the comment in packages/stack-encrypt/Cargo.toml). A -# different version here fails at the `ValueFrame: Decrypt` bound, since the -# aead crate would be duplicated. -vitaminc-aead-frame = { version = "0.6.1", features = ["serde"] } -vitaminc-protected = "0.6.1" +# No vitaminc dependency of its own: the transport frame and ciphertext +# codec (`stack_encrypt::dynamic::frame`, vitaminc's own, shared with its +# guest), the value model and `Protected` all come through stack-encrypt's +# re-exports, so the guest cannot build against another vitaminc. Two +# versions would fail only at the `ValueFrame: Decrypt` bound. futures = { version = "0.3", default-features = false, features = ["executor"] } serde = "1" @@ -76,8 +74,6 @@ uuid = "1" zeroize = "1" [dev-dependencies] -# The test tree (`tests/support`) walks values through vitaminc's sinks. -vitaminc-aead = "0.6.1" stack-kms = { path = "../../../../packages/stack-kms", default-features = false, features = ["test-support"] } # For minting a valid client-key fixture in the config tests. recipher = "=0.3.1" diff --git a/languages/golang/encrypt/guest/src/abi.rs b/languages/golang/encrypt/guest/src/abi.rs index 2d6e47e52..e1df6095c 100644 --- a/languages/golang/encrypt/guest/src/abi.rs +++ b/languages/golang/encrypt/guest/src/abi.rs @@ -390,7 +390,7 @@ pub unsafe extern "C" fn se_keyset(sel_ptr: *const u8, sel_len: u32) -> u64 { /// /// The context is one part — a string, bytes, or an `i32`/`i64`/`u32`/`u64` /// — or an array of parts, which may nest as deep as the transport codec -/// allows (`vitaminc_aead_frame::MAX_DEPTH` levels, counted from +/// allows (`stack_encrypt::dynamic::frame::MAX_DEPTH` levels, counted from /// the root of the encoded value; deeper is refused as `STATUS_ENCODING` /// before the context is parsed). [`stack_encrypt::dynamic::context`] is the one home of /// that grammar and of which Rust context each shape spells. diff --git a/languages/golang/encrypt/guest/src/config.rs b/languages/golang/encrypt/guest/src/config.rs index a08f576ce..44f77c218 100644 --- a/languages/golang/encrypt/guest/src/config.rs +++ b/languages/golang/encrypt/guest/src/config.rs @@ -33,10 +33,10 @@ use std::num::NonZeroUsize; use serde::{Deserialize, Deserializer}; +use stack_encrypt::dynamic::frame::serde::from_slice; use stack_guest_abi::last_error::malformed; use stack_kms::{ClientKey, ZeroKmsEndpoint}; use uuid::Uuid; -use vitaminc_aead_frame::serde::from_slice; /// Everything `se_cipher_init` needs to build the cipher. pub struct CipherConfig { diff --git a/languages/golang/encrypt/guest/src/deterministic.rs b/languages/golang/encrypt/guest/src/deterministic.rs index 88a789d51..15567525a 100644 --- a/languages/golang/encrypt/guest/src/deterministic.rs +++ b/languages/golang/encrypt/guest/src/deterministic.rs @@ -13,8 +13,8 @@ pub use stack_kms::DeterministicSource; use serde::Deserialize; +use stack_encrypt::dynamic::frame::serde::from_slice; use stack_guest_abi::last_error::malformed; -use vitaminc_aead_frame::serde::from_slice; use zeroize::Zeroize; /// The `deterministic-kms` build's whole config: the source's 32-byte seed, @@ -57,7 +57,7 @@ impl Seed { mod tests { use super::Seed; use crate::test_frame::{frame, V}; - use vitaminc_aead_frame::serde::from_slice; + use stack_encrypt::dynamic::frame::serde::from_slice; /// A seed is 32 bytes, and only bytes: 32 characters of text are refused. #[test] diff --git a/languages/golang/encrypt/guest/src/io.rs b/languages/golang/encrypt/guest/src/io.rs index 13618e8d2..29206fd83 100644 --- a/languages/golang/encrypt/guest/src/io.rs +++ b/languages/golang/encrypt/guest/src/io.rs @@ -28,9 +28,9 @@ //! copies, and the host wipes the buffers with `se_dealloc`. use serde::{Deserialize, Serialize, Serializer}; +use stack_encrypt::dynamic::frame::serde::{from_slice, to_vec}; use stack_guest_abi::last_error::malformed; use stack_guest_abi::step::{Request, Response}; -use vitaminc_aead_frame::serde::{from_slice, to_vec}; use zeroize::Zeroizing; use crate::status::STATUS_ENCODING; diff --git a/languages/golang/encrypt/guest/src/ops.rs b/languages/golang/encrypt/guest/src/ops.rs index c30b5430b..e08a46696 100644 --- a/languages/golang/encrypt/guest/src/ops.rs +++ b/languages/golang/encrypt/guest/src/ops.rs @@ -45,13 +45,13 @@ //! the output. Control data (a plan, a context, an options object, query //! statistics) carries no secret and is read from its frame with serde. +use stack_encrypt::dynamic::frame::{decode_ciphertext, encode_ciphertext, Frame}; use stack_encrypt::dynamic::{self, Scope, ValueFrame}; use stack_encrypt::sem::MatchOptions; use stack_encrypt::target::IndexSpec; use stack_encrypt::ErrorPayload; use stack_encrypt::{CipherText, KeysetCipher, Label, Node, SealedValue, StackCipherText}; use stack_kms::DataKeySource; -use vitaminc_aead_frame::{decode_ciphertext, encode_ciphertext, Frame}; use zeroize::Zeroizing; use stack_guest_abi::last_error; @@ -86,7 +86,7 @@ type BytesTree = Node>; /// /// The context is one part — a string, bytes, or an `i32`/`i64`/`u32`/`u64` /// — or an array of parts, nested as deep as the transport codec allows -/// ([`MAX_DEPTH`](vitaminc_aead_frame::MAX_DEPTH) levels from the root of the frame; deeper +/// ([`MAX_DEPTH`](stack_encrypt::dynamic::frame::MAX_DEPTH) levels from the root of the frame; deeper /// is [`STATUS_ENCODING`] before the context is read), exactly as a plan /// field's; [`dynamic::context`] is the one home of that grammar. Shape is identity: /// `[x]` is a PAE-framed list and `x` is not, so a probe takes the context @@ -559,8 +559,9 @@ fn not_a_frame() -> u32 { /// is sized as every other output is. A query term's search tokens are /// derived from plaintext, so the staging buffer is wiped once copied. fn encode_answer(answer: &T) -> Result, u32> { - let frame = - Zeroizing::new(vitaminc_aead_frame::serde::to_vec(answer).map_err(|_| STATUS_ENCODING)?); + let frame = Zeroizing::new( + stack_encrypt::dynamic::frame::serde::to_vec(answer).map_err(|_| STATUS_ENCODING)?, + ); let mut out = exact_buffer(Some(frame.len()))?; out.extend_from_slice(&frame); Ok(out) @@ -654,7 +655,7 @@ fn tree_encoded_len(tree: &BytesTree) -> Option { mod tests { use super::*; use crate::support::Tree; - use vitaminc_protected::Controlled; + use stack_encrypt::Controlled; // `tree_encoded_len` re-derives the codec's arithmetic; the codec exports // no `encoded_len` of its own, so this pin is the only thing that fails if diff --git a/languages/golang/encrypt/guest/src/options.rs b/languages/golang/encrypt/guest/src/options.rs index d3bb9f5fb..74dc15c73 100644 --- a/languages/golang/encrypt/guest/src/options.rs +++ b/languages/golang/encrypt/guest/src/options.rs @@ -47,8 +47,8 @@ use stack_kms::{IdentifiedBy, IndexKeySource}; use uuid::Uuid; use zerokms_protocol::Name; +use stack_encrypt::dynamic::frame::serde::from_slice; use stack_guest_abi::last_error::malformed; -use vitaminc_aead_frame::serde::from_slice; use crate::status::fail_error; #[cfg(any(doc, test))] diff --git a/languages/golang/encrypt/guest/src/test_frame.rs b/languages/golang/encrypt/guest/src/test_frame.rs index dc4e77943..58e492663 100644 --- a/languages/golang/encrypt/guest/src/test_frame.rs +++ b/languages/golang/encrypt/guest/src/test_frame.rs @@ -2,7 +2,7 @@ //! send what no writer would (a repeated key, an integer of any width). use serde::{Serialize, Serializer}; -use vitaminc_aead_frame::serde::to_vec; +use stack_encrypt::dynamic::frame::serde::to_vec; /// A test input, written as raw frame bytes by [`frame`]. pub(crate) enum V { @@ -35,7 +35,7 @@ pub(crate) fn frame(v: &V) -> Vec { }; match v { V::Obj(entries) => { - let mut out = container(vitaminc_aead_frame::OBJECT, entries.len()); + let mut out = container(stack_encrypt::dynamic::frame::OBJECT, entries.len()); for (key, value) in entries { out.extend_from_slice(&u32::try_from(key.len()).expect("short").to_le_bytes()); out.extend_from_slice(key.as_bytes()); @@ -44,7 +44,7 @@ pub(crate) fn frame(v: &V) -> Vec { out } V::Arr(items) => { - let mut out = container(vitaminc_aead_frame::ARRAY, items.len()); + let mut out = container(stack_encrypt::dynamic::frame::ARRAY, items.len()); for item in items { out.extend_from_slice(&frame(item)); } diff --git a/languages/golang/encrypt/guest/tests/leak.rs b/languages/golang/encrypt/guest/tests/leak.rs index d16656f38..ffc2aa9d5 100644 --- a/languages/golang/encrypt/guest/tests/leak.rs +++ b/languages/golang/encrypt/guest/tests/leak.rs @@ -24,6 +24,8 @@ use std::future::IntoFuture; use stack_auth::{SecretToken, ServiceToken}; mod support; +use stack_encrypt::dynamic::frame::encode_ciphertext; +use stack_encrypt::dynamic::plaintext::Logical; use stack_encrypt::dynamic::Scope; use stack_encrypt::{CipherText, Descriptor, Node, PassthroughFrame, StackCipher}; use stack_encrypt_guest::options::{parse_options, Side}; @@ -36,8 +38,6 @@ use stack_kms::{ }; use support::Tree; use uuid::Uuid; -use vitaminc_aead::plaintext::Logical; -use vitaminc_aead_frame::encode_ciphertext; use zerokms_protocol::{IdentifiedBy, UnverifiedContext, ViturRequestError}; const PLAINTEXT: &str = "leak-marker-plaintext"; @@ -132,7 +132,7 @@ fn failing() -> StackCipher { // ============================================================================= fn encode(value: Tree) -> Vec { - use vitaminc_protected::Controlled; + use stack_encrypt::Controlled; value.to_frame().expect("encode").risky_unwrap() } diff --git a/languages/golang/encrypt/guest/tests/native_ops.rs b/languages/golang/encrypt/guest/tests/native_ops.rs index c386c6e37..9ab2c4d3a 100644 --- a/languages/golang/encrypt/guest/tests/native_ops.rs +++ b/languages/golang/encrypt/guest/tests/native_ops.rs @@ -19,12 +19,14 @@ use std::future::IntoFuture; mod support; +use stack_encrypt::dynamic::frame::{decode_ciphertext, encode_ciphertext}; use stack_encrypt::dynamic::Scope; use stack_encrypt::sem::DefaultMatch; use stack_encrypt::{ nonempty, CipherText, Label, Node, PassthroughFrame, PendingStackCipherText, SealedValue, StackCipher, }; +use stack_encrypt::{Controlled, Protected}; use stack_encrypt_guest::ops::{self, TERM_EQUALITY, TERM_MATCH, TERM_OPE, TERM_ORE}; use stack_encrypt_guest::status::{ STATUS_AUTH, STATUS_CONTEXT_MISMATCH, STATUS_ENCODING, STATUS_FOREIGN_KEYSET, STATUS_TERM, @@ -35,8 +37,6 @@ use stack_kms::{ }; use support::Tree; use uuid::Uuid; -use vitaminc_aead_frame::{decode_ciphertext, encode_ciphertext}; -use vitaminc_protected::{Controlled, Protected}; use zerokms_protocol::{IdentifiedBy, UnverifiedContext}; /// `futures::executor::block_on` over anything awaitable: the term API @@ -330,7 +330,7 @@ fn guest_terms_match_the_native_sem_derivations() { .expect("native"); assert_eq!(eq_bytes, native_bytes.as_bytes()); - // Variable-width CLLW output for strings: the text behind cllw-ore's + // Variable-width CLLW output for strings: the text behind clww-ore's // one marker byte, eight bytes a plaintext byte. let ore_s = block_on(ops::term( &cipher.default_keyset(), diff --git a/languages/golang/encrypt/guest/tests/support/mod.rs b/languages/golang/encrypt/guest/tests/support/mod.rs index 37a91fa3b..e21c00bcb 100644 --- a/languages/golang/encrypt/guest/tests/support/mod.rs +++ b/languages/golang/encrypt/guest/tests/support/mod.rs @@ -9,13 +9,14 @@ #![allow(dead_code)] -use vitaminc_aead::frame::{FrameError, FrameWriteError}; -use vitaminc_aead::plaintext::{ - visit_map, visit_seq, Error as _, Float, Int, Logical, MapSink, Physical, SeqSink, Sink, - SourceError, +use stack_encrypt::dynamic::frame::{to_frame, Frame}; +use stack_encrypt::dynamic::frame::{FrameError, FrameWriteError}; +use stack_encrypt::dynamic::plaintext::{ + visit_map, visit_seq, Error as _, FixedType, Float, Int, Logical, MapSink, Physical, SeqSink, + Sink, SourceError, }; -use vitaminc_aead::{to_frame, DecodeError, Decrypt, Encrypt, Frame}; -use vitaminc_protected::{Controlled, Protected}; +use stack_encrypt::{Controlled, Protected}; +use stack_encrypt::{DecodeError, Decrypt, Encrypt}; /// A value as a test spells it: each scalar at its own width, a logical /// scalar under its type. Equality is structural and variable-time, which @@ -117,7 +118,7 @@ fn write(value: &Tree, out: &mut Vec) { let count = |len: usize| u32::try_from(len).expect("short").to_le_bytes(); match value { Tree::Object(entries) => { - out.push(vitaminc_aead::frame::OBJECT); + out.push(stack_encrypt::dynamic::frame::OBJECT); out.extend_from_slice(&count(entries.len())); for (key, value) in entries { out.extend_from_slice(&count(key.len())); @@ -126,7 +127,7 @@ fn write(value: &Tree, out: &mut Vec) { } } Tree::Array(items) => { - out.push(vitaminc_aead::frame::ARRAY); + out.push(stack_encrypt::dynamic::frame::ARRAY); out.extend_from_slice(&count(items.len())); for item in items { write(item, out); @@ -139,7 +140,7 @@ fn write(value: &Tree, out: &mut Vec) { /// What a binding reads back from an answer the engine writes: its frame, /// read back. pub(crate) fn value_of(answer: &T) -> Tree { - let frame = vitaminc_aead_frame::serde::to_vec(answer).expect("frames"); + let frame = stack_encrypt::dynamic::frame::serde::to_vec(answer).expect("frames"); Tree::from_frame(&frame).expect("a value") } @@ -273,6 +274,10 @@ impl Sink for TreeSink { Ok(self.0.put(value)) } + fn typed_null(self, _: FixedType) -> Result { + Ok(self.0.put(Tree::Null)) + } + fn seq(self, _: Option) -> Result, DecodeError> { Ok(TreeSeq { out: self.0, diff --git a/languages/golang/stashgen/enginetest/enginetest.go b/languages/golang/stashgen/enginetest/enginetest.go index 61be14f85..9b0793f01 100644 --- a/languages/golang/stashgen/enginetest/enginetest.go +++ b/languages/golang/stashgen/enginetest/enginetest.go @@ -241,7 +241,7 @@ func eightBit(t stashgen.GoType) bool { // floats, text and bytes. Not over a boolean or an 8-bit integer, whose // order term would reveal which rows are true, or each row's rank among 256 // values; and not yet over a decimal, date or timestamp, whose order terms -// wait for new cllw-ore and ore-rs releases (#1236). The JSON index is not +// are not built yet (#1236). The JSON index is not // in the engine yet. func indexApplies(name stashgen.IndexName, t stashgen.GoType) error { switch name { @@ -263,7 +263,7 @@ func indexApplies(name stashgen.IndexName, t stashgen.GoType) error { case stashgen.KindString, stashgen.KindBytes, stashgen.KindFloat: return nil case stashgen.KindDecimal, stashgen.KindDate, stashgen.KindTimestamp: - return fmt.Errorf("an order index on a decimal, date or timestamp waits for new cllw-ore and ore-rs releases (#1236)") + return fmt.Errorf("an order index on a decimal, date or timestamp is not supported yet (#1236)") } if integer(t) && !eightBit(t) { return nil diff --git a/packages/eql/Cargo.lock b/packages/eql/Cargo.lock index a7012b2a1..63773fcc4 100644 --- a/packages/eql/Cargo.lock +++ b/packages/eql/Cargo.lock @@ -570,7 +570,7 @@ dependencies = [ "chrono", "cipherstash-config", "cipherstash-core", - "cllw-ore 0.4.2", + "cllw-ore", "cts-common 0.42.3", "derive_more 1.0.0", "dirs", @@ -582,7 +582,7 @@ dependencies = [ "log", "miette", "opaque-debug", - "orderable-bytes 0.1.1", + "orderable-bytes", "ore-rs 0.8.3", "percent-encoding", "rand 0.8.6", @@ -650,7 +650,7 @@ dependencies = [ "blake3", "chrono", "hex", - "orderable-bytes 0.1.1", + "orderable-bytes", "rust_decimal", "subtle", "thiserror 1.0.69", @@ -658,18 +658,17 @@ dependencies = [ ] [[package]] -name = "cllw-ore" -version = "0.5.2-rc.1" +name = "clww-ore" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "24eb4a774d070a6c2b52175b98273cd7193c61e1bda39c1a98b50b7a2d91375a" +checksum = "b95747f5724666cb973b2ca0659e10b6083c11f99877c4727b4c9f534a591c74" dependencies = [ "blake3", "hex", "subtle", "thiserror 1.0.69", - "unicode-normalization", "vitaminc-ore", - "vitaminc-protected 0.6.1", + "vitaminc-protected 0.8.0", "zeroize", ] @@ -1209,7 +1208,7 @@ dependencies = [ "stack-encrypt", "thiserror 2.0.20", "ts-rs", - "vitaminc-aead 0.6.1", + "vitaminc-aead 0.8.0", "zeroize", ] @@ -1252,7 +1251,7 @@ dependencies = [ "stack-kms", "tokio", "uuid", - "vitaminc-aead 0.6.1", + "vitaminc-aead 0.8.0", ] [[package]] @@ -2667,12 +2666,6 @@ dependencies = [ "rust_decimal", ] -[[package]] -name = "orderable-bytes" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c7d30b72ffca73d9936fe5fc80a9c9520c73f5b4f64839a810211903d5ace3c" - [[package]] name = "ore-rs" version = "0.8.3" @@ -2686,7 +2679,7 @@ dependencies = [ "hex", "lazy_static", "num", - "orderable-bytes 0.1.1", + "orderable-bytes", "rand 0.8.6", "rand_chacha 0.3.1", "rust_decimal", @@ -2697,24 +2690,24 @@ dependencies = [ [[package]] name = "ore-rs" -version = "0.9.0" +version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0e1d6cb8c1249643266bd60269547c93d3cd263d5385f1262902bbb295ff9a5e" +checksum = "8bd65962ec1409c09d20e1e016f4fe1b4ae2e2e58dba38c155538b2c0801a185" dependencies = [ "aes", "block-modes", "byteorder", "hex", "num", - "orderable-bytes 0.2.1", - "rand 0.8.6", - "rand_chacha 0.3.1", + "rand 0.10.1", "subtle-ng", "thiserror 1.0.69", + "vitaminc-context 0.8.0", "vitaminc-hmac", "vitaminc-ore", "vitaminc-prf", - "vitaminc-protected 0.6.1", + "vitaminc-protected 0.8.0", + "vitaminc-random 0.8.0", "zeroize", ] @@ -4254,8 +4247,8 @@ dependencies = [ "tracing", "url", "uuid", - "vitaminc 0.6.1", - "vitaminc-protected 0.6.1", + "vitaminc 0.8.0", + "vitaminc-protected 0.8.0", "web-time", "zeroize", "zerokms-protocol", @@ -4266,23 +4259,23 @@ name = "stack-encrypt" version = "0.3.0" dependencies = [ "base64ct", - "cllw-ore 0.5.2-rc.1", + "clww-ore", "miette", - "ore-rs 0.9.0", + "ore-rs 0.10.0", "serde", "serde_json", "stack-encrypt-derive", "stack-kms", "thiserror 1.0.69", "uuid", - "vitaminc-aead 0.6.1", + "vitaminc-aead 0.8.0", "vitaminc-aead-frame", - "vitaminc-encrypt 0.6.1", + "vitaminc-encrypt 0.8.0", "vitaminc-hmac", "vitaminc-normalize", "vitaminc-ore", "vitaminc-prf", - "vitaminc-protected 0.6.1", + "vitaminc-protected 0.8.0", "zeroize", ] @@ -4317,8 +4310,8 @@ dependencies = [ "tracing", "url", "uuid", - "vitaminc 0.6.1", - "vitaminc-protected 0.6.1", + "vitaminc 0.8.0", + "vitaminc-protected 0.8.0", "zeroize", "zerokms-protocol", ] @@ -5083,16 +5076,16 @@ dependencies = [ [[package]] name = "vitaminc" -version = "0.6.1" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac5c15b6c25efcb9a6111f7108ab8101947a7bf7e9af3ff6d6a73358a1ace0da" +checksum = "ea37168a603d605732d0bf0672586139ab91736f767d7b85e173c84dcee19054" dependencies = [ - "vitaminc-aead 0.6.1", - "vitaminc-context 0.6.1", - "vitaminc-encrypt 0.6.1", - "vitaminc-protected 0.6.1", - "vitaminc-random 0.6.1", - "vitaminc-traits 0.6.1", + "vitaminc-aead 0.8.0", + "vitaminc-context 0.8.0", + "vitaminc-encrypt 0.8.0", + "vitaminc-protected 0.8.0", + "vitaminc-random 0.8.0", + "vitaminc-traits 0.8.0", ] [[package]] @@ -5125,9 +5118,9 @@ dependencies = [ [[package]] name = "vitaminc-aead" -version = "0.6.1" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "71b8c5c4ced92545dce5fd7cf04581d08210def174cc81475cf227fa2506c5b7" +checksum = "e9bb97fd543ee6a2b168e257ec69d0d274a775b1eaa3f856b5ac2941b01891c1" dependencies = [ "bytes", "chrono", @@ -5135,10 +5128,10 @@ dependencies = [ "rust_decimal", "serde", "thiserror 2.0.20", - "vitaminc-aead-derive 0.6.1", - "vitaminc-context 0.6.1", - "vitaminc-protected 0.6.1", - "vitaminc-random 0.6.1", + "vitaminc-aead-derive 0.8.0", + "vitaminc-context 0.8.0", + "vitaminc-protected 0.8.0", + "vitaminc-random 0.8.0", "zeroize", ] @@ -5155,9 +5148,9 @@ dependencies = [ [[package]] name = "vitaminc-aead-derive" -version = "0.6.1" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c546497a972d0f0498f2f8d5f537c514bad82df8662951c63d0c80023808900" +checksum = "0845a44c07ddc882ed47a0e92e04fc83496220f054b589ad0cbd215c5009e5b7" dependencies = [ "proc-macro2", "quote", @@ -5166,12 +5159,12 @@ dependencies = [ [[package]] name = "vitaminc-aead-frame" -version = "0.6.1" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e35992a269bcaa5b201f1938e54bfbf167bfa6fe975d83cbdbdb54c2a363c5ef" +checksum = "3b0299777255171712a296d59164691dc1e93d10bddaab6e248fede1790dfd2e" dependencies = [ "serde", - "vitaminc-aead 0.6.1", + "vitaminc-aead 0.8.0", "zeroize", ] @@ -5187,12 +5180,12 @@ dependencies = [ [[package]] name = "vitaminc-context" -version = "0.6.1" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa4c4bc2bd9811253eb427657565a45bd4826e2379e93ee1c4d00c808a769882" +checksum = "a630079ba2d50680ee5048addd430eda30613559809dd6d383551e6d3d299826" dependencies = [ "mutants", - "vitaminc-protected 0.6.1", + "vitaminc-protected 0.8.0", ] [[package]] @@ -5225,71 +5218,72 @@ dependencies = [ [[package]] name = "vitaminc-encrypt" -version = "0.6.1" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f0923694602855b33a296d9af473e282e8096c1cfe1b30b8695d3b6651717fc5" +checksum = "db45e073f92ae8ca27f8fe14270bc34c75e767559c2347098dacca95180d1ddd" dependencies = [ "aes-gcm", "aws-lc-rs", - "vitaminc-aead 0.6.1", - "vitaminc-protected 0.6.1", - "vitaminc-random 0.6.1", + "vitaminc-aead 0.8.0", + "vitaminc-protected 0.8.0", + "vitaminc-random 0.8.0", "zeroize", ] [[package]] name = "vitaminc-hmac" -version = "0.6.1" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd361f626e95cbe770b9d012e4a86c43cfefe4aefb3d5b3ed9339a83085bdc53" +checksum = "b5fa0ae8bbad85ae30fb5c91b0b72b694d59bf2c2c1e7ad799eda66fdbd67e7c" dependencies = [ "hmac 0.13.0", "sha2 0.11.0", "vitaminc-prf", - "vitaminc-protected 0.6.1", + "vitaminc-protected 0.8.0", "zeroize", ] [[package]] name = "vitaminc-normalize" -version = "0.6.1" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "214b2a9d085924c3bc3c91f3ba74238e8848bf54990e5f48f170c71fbacea07a" +checksum = "f5a2d8875e0b8b35b7a4f9dd698bbd13c989837cea564b5a4cbb5371b78fa937" dependencies = [ "thiserror 2.0.20", "unicode-general-category", "unicode-normalization", - "vitaminc-aead 0.6.1", - "vitaminc-protected 0.6.1", + "vitaminc-aead 0.8.0", + "vitaminc-protected 0.8.0", ] [[package]] name = "vitaminc-ore" -version = "0.6.1" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed88c54b5f06f2177ecbfb7666812adf645406f6fb555f4e2f0fd7fa218e71c4" +checksum = "f05518b4d35cb0c592dad59afb11b8e883ea252449b9ae47ff5ddeff0ed49f75" dependencies = [ "thiserror 2.0.20", "unicode-general-category", "unicode-normalization", - "vitaminc-aead 0.6.1", - "vitaminc-context 0.6.1", + "vitaminc-aead 0.8.0", + "vitaminc-context 0.8.0", "vitaminc-normalize", - "vitaminc-protected 0.6.1", + "vitaminc-protected 0.8.0", + "zeroize", ] [[package]] name = "vitaminc-prf" -version = "0.6.1" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c2715cca25006b4656223bc932ab4fd7f70d387aa4ec63a4e2ef33aa8cd2b3a5" +checksum = "916688478273ca3e5c6805b355534ce9263688391cd4ab23b08bef760039d325" dependencies = [ "mutants", "thiserror 2.0.20", - "vitaminc-aead 0.6.1", - "vitaminc-context 0.6.1", + "vitaminc-aead 0.8.0", + "vitaminc-context 0.8.0", "vitaminc-normalize", - "vitaminc-protected 0.6.1", + "vitaminc-protected 0.8.0", ] [[package]] @@ -5326,9 +5320,9 @@ dependencies = [ [[package]] name = "vitaminc-protected" -version = "0.6.1" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1bb76dd473f5aa89b844f92018ebe3041deb8e5390e7061cca4283d959ff855" +checksum = "a6edc22562a9bbff0ba9704a2c43670b2c7cb1637524c045c3ba6436ed00917f" dependencies = [ "bitvec", "digest 0.11.3", @@ -5337,7 +5331,7 @@ dependencies = [ "serde_bytes", "subtle", "thiserror 2.0.20", - "vitaminc-protected-derive 0.6.1", + "vitaminc-protected-derive 0.8.0", "zeroize", ] @@ -5365,9 +5359,9 @@ dependencies = [ [[package]] name = "vitaminc-protected-derive" -version = "0.6.1" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7478ed160c019059746e75fc613563dcdcd5266d155a34601d29377a1c4afc3" +checksum = "a7cce3a7d0ce6f57c0e82345f20e87f3737cccd3a70aec2a2ab49f68a3a5e24a" dependencies = [ "proc-macro-crate", "proc-macro2", @@ -5406,16 +5400,16 @@ dependencies = [ [[package]] name = "vitaminc-random" -version = "0.6.1" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b477af7c01c3d9ef2647e46952ad3df7f246b3f806b1d4009ee83beecec613a" +checksum = "8bb253f783ce6f31a55a92f5a9f0526109b8caa6a465edb94244fd344a078c11" dependencies = [ "chacha20", "getrandom 0.4.2", "rand 0.10.1", "thiserror 2.0.20", - "vitaminc-protected 0.6.1", - "vitaminc-random-derives 0.6.1", + "vitaminc-protected 0.8.0", + "vitaminc-random-derives 0.8.0", "zeroize", ] @@ -5443,9 +5437,9 @@ dependencies = [ [[package]] name = "vitaminc-random-derives" -version = "0.6.1" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ab5a0de8da428c6789dc067a578a0462e411099721d616736cf29e1622230c35" +checksum = "df0b3615936d6dded4b775856f4b0fa229d745d183f0b3754ac80035f16c27d9" dependencies = [ "proc-macro2", "quote", @@ -5486,17 +5480,17 @@ dependencies = [ [[package]] name = "vitaminc-traits" -version = "0.6.1" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a900f0edcacd49c8557ab54722175869fec66926054a6fbdc53a05069db3c922" +checksum = "1e9098ee4b13446ef959583ee2f3c384df571b453179104f7b4960ffddf65ee9" dependencies = [ "anyhow", "bytes", "rmp-serde", "serde", "thiserror 2.0.20", - "vitaminc-protected 0.6.1", - "vitaminc-random 0.6.1", + "vitaminc-protected 0.8.0", + "vitaminc-random 0.8.0", "zeroize", ] diff --git a/packages/eql/crates/eql-bindings/Cargo.toml b/packages/eql/crates/eql-bindings/Cargo.toml index 0e4be7dab..4e12db75c 100644 --- a/packages/eql/crates/eql-bindings/Cargo.toml +++ b/packages/eql/crates/eql-bindings/Cargo.toml @@ -57,7 +57,7 @@ thiserror = { version = "2", optional = true } # and decimal plaintexts (`v4::plaintext`) describe themselves with, and # vitaminc's range checks for them. The version Stack Encrypt uses, so the # traits are the ones it calls. -vitaminc-aead = { version = "0.6.0", optional = true } +vitaminc-aead = { version = "0.8.0", optional = true } # The `chrono` and `rust_decimal` features: conversions between those # crates' types and `v4::plaintext`'s. chrono = { version = "0.4.44", optional = true, default-features = false } diff --git a/packages/eql/crates/eql-bindings/src/v4/plaintext.rs b/packages/eql/crates/eql-bindings/src/v4/plaintext.rs index de602810c..7af87f6ad 100644 --- a/packages/eql/crates/eql-bindings/src/v4/plaintext.rs +++ b/packages/eql/crates/eql-bindings/src/v4/plaintext.rs @@ -481,6 +481,9 @@ mod tests { }, )) } + fn typed_null(self, ty: vitaminc_aead::FixedType) -> Result { + Ok((ty.logical(), None)) + } fn seq(self, _: Option) -> Result { unreachable!("a plaintext here is a scalar") } diff --git a/packages/eql/tests/encryption/Cargo.toml b/packages/eql/tests/encryption/Cargo.toml index 6ee6ec13c..8ee6acd08 100644 --- a/packages/eql/tests/encryption/Cargo.toml +++ b/packages/eql/tests/encryption/Cargo.toml @@ -31,7 +31,7 @@ stack-encrypt = { path = "../../../stack-encrypt", default-features = false, fea # `plaintext::Sink`, for a plaintext type with its own `Encrypt` impl; and # chrono's and rust_decimal's own sources, which seal the leaf a date, # timestamp or decimal from any other producer seals. -vitaminc-aead = { version = "0.6.0", features = ["chrono", "rust_decimal"] } +vitaminc-aead = { version = "0.8.0", features = ["chrono", "rust_decimal"] } chrono = { version = "0.4.44", default-features = false, features = ["std"] } rust_decimal = { version = "1", default-features = false, features = ["std"] } stack-kms = { path = "../../../stack-kms", default-features = false, features = ["test-support"] } diff --git a/packages/eql/tests/encryption/fixtures/v4_ordered_queries.json b/packages/eql/tests/encryption/fixtures/v4_ordered_queries.json index a494c0791..f0e20d5a3 100644 --- a/packages/eql/tests/encryption/fixtures/v4_ordered_queries.json +++ b/packages/eql/tests/encryption/fixtures/v4_ordered_queries.json @@ -2,43 +2,43 @@ "_comment": "The v4 query operands eql-bindings derives for one plaintext of each OPE-ordered type under FakeDataKeySource's index key (keyset nil), read by the Go SDK's hermetic test; regenerate with EQL_UPDATE_FIXTURES=1, do not edit.", "floor": { "plaintext": -3, - "query": "{\"v\":4,\"i\":{\"t\":\"rankings\",\"c\":\"floor\"},\"op\":\"0068773fbf20d83c18c9e2c158d14a9601d12eab933e59d10e163110e4f030377b\"}" + "query": "{\"v\":4,\"i\":{\"t\":\"rankings\",\"c\":\"floor\"},\"op\":\"00ef8ea3833a80e22d0add60fdbcf250c26a3ce5ca10d6bb890804e19e4458fb1b\"}" }, "handle": { "plaintext": "carol", - "query": "{\"v\":4,\"i\":{\"t\":\"rankings\",\"c\":\"handle\"},\"hm\":\"30fca14a65e5695fc96bd9fc7e3747afe79c7ff2993d532e3ad97f8e8b95ffac\",\"op\":\"00e169c8297d7be0a24e597d20e140b6a098c488dda2a5fab8b1a7071ff703df7f0880519d1ea23890b5c6a01066f62633\"}" + "query": "{\"v\":4,\"i\":{\"t\":\"rankings\",\"c\":\"handle\"},\"hm\":\"30fca14a65e5695fc96bd9fc7e3747afe79c7ff2993d532e3ad97f8e8b95ffac\",\"op\":\"0050d344117a1ebd003b5c7a95186c8d46a9bb20ff555f86bdd726ffb033a113b8daae3b210a878df9b37e0f48f6cd9b97\"}" }, "level": { "plaintext": 10, - "query": "{\"v\":4,\"i\":{\"t\":\"rankings\",\"c\":\"level\"},\"op\":\"0159d19c111791f639ba0638692ca6f6c53ecac713e356a7e8bf95fc2d839691f4\"}" + "query": "{\"v\":4,\"i\":{\"t\":\"rankings\",\"c\":\"level\"},\"op\":\"0175ce2d2193c247e19cdeeaf00c3aa33f8f41ae2ae07ea8f54907726ef81d76c6\"}" }, "mean": { "plaintext": 0.0, - "query": "{\"v\":4,\"i\":{\"t\":\"rankings\",\"c\":\"mean\"},\"op\":\"017bc9729378e320ff0c1504dc995074a7db7b05d24bed8a923f6944899e4517d213bba21ee639bb01063902e92cad61b3f3b0755b0dacc66fa5188b434c455360\"}" + "query": "{\"v\":4,\"i\":{\"t\":\"rankings\",\"c\":\"mean\"},\"op\":\"0092c35e5c06045d306925d152beb010ac631de046e645a8fc36d9809494f97d17931a4e97b083f7725796c282b7aaa3c6a483634026a4ef01c14c9ec5f7d48743\"}" }, "pace": { "plaintext": -0.5, - "query": "{\"v\":4,\"i\":{\"t\":\"rankings\",\"c\":\"pace\"},\"op\":\"00028af974e429d69504e291c6615487c98d3abbaf6a36a012b22bd60ddb569ba83f09243bb5f22d9df419926a7b9e31c7c4411c822471fd427c7a74ac57df0482\"}" + "query": "{\"v\":4,\"i\":{\"t\":\"rankings\",\"c\":\"pace\"},\"op\":\"00fc1eaf0613a705488a607f2415941128f4675696e63176b0747adb930727be4c77852c13c8ecf605cffa93d0ae8c0a39e23d295e17f8d87e78996a4d49fd9ea0\"}" }, "points": { "plaintext": 5000000000, - "query": "{\"v\":4,\"i\":{\"t\":\"rankings\",\"c\":\"points\"},\"op\":\"0124da6c76e6a9d3572f27a08b17b843e6581a23213f34fea500706db6d0edf539fee6624d544ab352bbfcd0987056c61e7e2b808fcb36eef07e673ec3639e4235\"}" + "query": "{\"v\":4,\"i\":{\"t\":\"rankings\",\"c\":\"points\"},\"op\":\"00cee5592b12ad2e56642aea465a82520c4975a84e5e423871fd8c293684946167de3bf467704da5d857f93dd27c836494e7a208adad194349f0c37e05a0f60156\"}" }, "score": { "plaintext": 9.75, - "query": "{\"v\":4,\"i\":{\"t\":\"rankings\",\"c\":\"score\"},\"op\":\"00cf2820721cd8c187f434f8986fd01c7eb126c713b0619086b0ca6d0b2120f8d322bbc60d5e40ac640ec49f271c0894a6965ab22b7da190f2e2af8f157a7b503f\"}" + "query": "{\"v\":4,\"i\":{\"t\":\"rankings\",\"c\":\"score\"},\"op\":\"0130440c006ce9cfd5eaae7c256850391359737687b73654638245f850c248cdc5b048baf4ea157de1a7ba1da432b34ce8db6242944a1487c8650b12ed349aff2d\"}" }, "speed": { "plaintext": 2.5, - "query": "{\"v\":4,\"i\":{\"t\":\"rankings\",\"c\":\"speed\"},\"op\":\"00bbc2ac417a8cb6a4b5b69c9f81223f9016f7ffc9e250417dd5afa5cfd4844dac6f9f72bf972a4aba57ae0f7e64bc7ce315095aab620f1f0f7a567d525837af8c\"}" + "query": "{\"v\":4,\"i\":{\"t\":\"rankings\",\"c\":\"speed\"},\"op\":\"00eb900ca25552ce78eaef5e2496345a98454225f1b19c906a2e7aeb3c52c3fe559b518926897a71ef5b835ae2d445d30274ac3b4bca05c2cba135065fd0581e42\"}" }, "table": "rankings", "title": { "plaintext": "Mango", - "query": "{\"v\":4,\"i\":{\"t\":\"rankings\",\"c\":\"title\"},\"hm\":\"5d14d6d4a7e93c15cf6b7a0e92dc102adbfcbfb7c0492ad09d6b1938bafb748b\",\"op\":\"00344fe120b7abb89fdad4d2ace56e65d225dc12e1f08841a86ad18728afb74d36c3bdd298ed9a2e94e98a2e9328a2fa76\"}" + "query": "{\"v\":4,\"i\":{\"t\":\"rankings\",\"c\":\"title\"},\"hm\":\"5d14d6d4a7e93c15cf6b7a0e92dc102adbfcbfb7c0492ad09d6b1938bafb748b\",\"op\":\"00e162e4c13c10a383ee7c6728a616e1e72458a7cc35c5204061bf8f01800520009adea5aca7256ecb6b5a1f95ebfa4fcd\"}" }, "total": { "plaintext": -1, - "query": "{\"v\":4,\"i\":{\"t\":\"rankings\",\"c\":\"total\"},\"op\":\"007152e605e2cc13823bd1379c7733939403474f5dfe1a65fa73eb63ea134f4a0505668fc80076fb24aaefd4763b1d1a2be9bf875178cf8f4abdbdce276f071ed9\"}" + "query": "{\"v\":4,\"i\":{\"t\":\"rankings\",\"c\":\"total\"},\"op\":\"00fd575c3250caeb1c5e8c45e48cd4ad8ef38eec0d52d6fd9fcf6f53c01dc212fcb747d609ddf4585907072d7fbd9bf29b59314a2d30ef33f1ac857c803ac46bfb\"}" } } diff --git a/packages/eql/tests/encryption/fixtures/v4_ordered_rows.json b/packages/eql/tests/encryption/fixtures/v4_ordered_rows.json index 4fa6224dc..df4e74565 100644 --- a/packages/eql/tests/encryption/fixtures/v4_ordered_rows.json +++ b/packages/eql/tests/encryption/fixtures/v4_ordered_rows.json @@ -24,8 +24,8 @@ "t": "rankings", "c": "floor" }, - "c": "stack-encrypt:1:AQAAAAAAAAAAAAAAAAAAAABn4yMF67G89OFjQZZuk7z/IAAPy1eGXRyPxy1IfAwzQCPlOMdditoc/8fNRNI2Iw3VQwJX+YR4eii1fcxB+KJtUD2cDQHwylkneQqa8OgbYJYiWTc=", - "op": "0068773fbf20d83c18c9e2c158d14a9601d12eab933e59d10e16311064f92eac47" + "c": "stack-encrypt:1:AQAAAAAAAAAAAAAAAAAAAABn4yMF67G89OFjQZZuk7z/IAAPy1eGXRyPxy1IfAwzQCPlOMdditoc/8fNRNI2Iw3VQwIhfD8X+LyBXblvBGC1Q/kdEYIykJtiVAHJNsxdd1zYZa4=", + "op": "00ef8ea3833a80e22d0add60fdbcf250c26a3ce5ca10d6bb890804e11d195873ca" }, "handle": { "v": 4, @@ -33,9 +33,9 @@ "t": "rankings", "c": "handle" }, - "c": "stack-encrypt:1:AQAAAAAAAAAAAAAAAAAAAACao1GJ/o4L0iCBtDrzF6P4IADDycFng7kuIpwyCSaqaE7ZJDE3q+nAEKaMK9GelLdntgK3RJEIWuJIwJoaqe10CfLP0ObM8l+bgj/harYScfipBL4g", + "c": "stack-encrypt:1:AQAAAAAAAAAAAAAAAAAAAACao1GJ/o4L0iCBtDrzF6P4IADDycFng7kuIpwyCSaqaE7ZJDE3q+nAEKaMK9GelLdntgLJdSlPOHWMhcHTWO+5eJy3AF44nkyCWMGGQKN/Qed7/tIM", "hm": "fd9e4ef66848b4dada73e4262e85c9994af16aff271638ef9ec695d460e55076", - "op": "00e169c8297d7be0a24e597d20e14036df866a797b2cf54c44b7ae8b5540f7055f407ed6f91137efd272331b242fbe1ba1" + "op": "0050d344117a1ebd003b5c7a95186c0cce8cae73d41b805057c1556cc9f73db8a1f22dcacb3e5ab8338ecc626442777727" }, "level": { "v": 4, @@ -43,8 +43,8 @@ "t": "rankings", "c": "level" }, - "c": "stack-encrypt:1:AQAAAAAAAAAAAAAAAAAAAADOELB7oFk4gGnte9gWUzX+IAA/eO5LaKSJjCCWDqc30OLhtVNEMuxqU8YpeFdvKCq/zwJuoJAKC6CVvRXxddKK93rVWrvRV5ZLBIdjTRO5wEkx4/M=", - "op": "00da028bda7156e277d149180f09a615bb7f3f45efabe00137a04f5514176bc162" + "c": "stack-encrypt:1:AQAAAAAAAAAAAAAAAAAAAADOELB7oFk4gGnte9gWUzX+IAA/eO5LaKSJjCCWDqc30OLhtVNEMuxqU8YpeFdvKCq/zwLuB6l4GFEiXv/2htTgSFpLfaI2cRPk9M+9B3ok7lo6rkw=", + "op": "00f5d91a01200de0844df8783c2d15dfdf97f7c4f87e8f6ad805176cebd107229c" }, "mean": { "v": 4, @@ -52,8 +52,8 @@ "t": "rankings", "c": "mean" }, - "c": "stack-encrypt:1:AQAAAAAAAAAAAAAAAAAAAAAXtGGpXlAfrs+IrloNwZO2IACelhdo3FYPTm2Ee6gu3+WpSHxU3IZtSHO2tiiQdtYltALT0WMwiFSu9v/C372nHnQ9Y2F5lQ+SJ9a6UGl7q1Wnzg6OavYb", - "op": "00fbce95d005970edd747e9dbff02f9824d8fedff874593ae7ddceabb8034978ead8b5f3a99c55793ed7912cb85f2cb5b600cc608ead9edfbf551e4d1544fff0d7" + "c": "stack-encrypt:1:AQAAAAAAAAAAAAAAAAAAAAAXtGGpXlAfrs+IrloNwZO2IACelhdo3FYPTm2Ee6gu3+WpSHxU3IZtSHO2tiiQdtYltAJX+0j9IhUaijB4dqlS+SG3qGRRu1nri+3gV41uMGoMoOUbAwFf", + "op": "00133b8c54873d85f5eaf7c183624349adc12dcbbcc4291a6f8e31094f14060c103eeb3c7d545c62cfa70dd25f653e2da48780132093791404f2c976705ee3bc21" }, "pace": { "v": 4, @@ -61,8 +61,8 @@ "t": "rankings", "c": "pace" }, - "c": "stack-encrypt:1:AQAAAAAAAAAAAAAAAAAAAADbT5WtnwkRYMqrlrr5MYHyIAB3uJpHJLZ4qKadvcMBxL3zAMxDkh86LddqQyvJSQAvugKLD9zlce2vNCOnYmInd4TrsCm94ahuAenaAUtKbFc5Fhk=", - "op": "00020a960d8eb4ca100a36cdccaca4b2685bcd7b343e092f8133a320b1d0cb6ec85408fb3485228c62b3512f97dc9b86ff4021b728ce7aec0b99f5bbe72a3fd870" + "c": "stack-encrypt:1:AQAAAAAAAAAAAAAAAAAAAADbT5WtnwkRYMqrlrr5MYHyIAB3uJpHJLZ4qKadvcMBxL3zAMxDkh86LddqQyvJSQAvugJ669D9q6TZ1FI15X6hAVDOQZuAdyz7Ay4wXuY36yN7TFk=", + "op": "00fb9f213ea5a10eb43eaef0edc90db2a3f576a0a8901321fbb89c943817c02fa904d20cad736d408a5481a3887e00887a136216bb81087d454fbdaad8b3e8b8b4" }, "points": { "v": 4, @@ -70,8 +70,8 @@ "t": "rankings", "c": "points" }, - "c": "stack-encrypt:1:AQAAAAAAAAAAAAAAAAAAAADE2rUct3jjTKCWivCCCvn+IACDxItrcNhNJjpoOqJKOryPLgDOg+vvfrH4031ThcjDcgL2v4cWtT1QKjil3dECXavlyHzUuyoinNxTfIYEdhSNTtbKxK1z", - "op": "00a53e38612eddc330547218dda2f5ee376e718061a8ea3af479e8473fadca71aef7476bd681e502cb239d515f23f7ef925e386904bfa7dcea145d06c9bcec551b" + "c": "stack-encrypt:1:AQAAAAAAAAAAAAAAAAAAAADE2rUct3jjTKCWivCCCvn+IACDxItrcNhNJjpoOqJKOryPLgDOg+vvfrH4031ThcjDcgI7lsGi2gJ2KZcFANTqV9hLIjpOKOiAYp2WvSBa0GEN51Paq4Qn", + "op": "004ecb0a9b8bd21d9848013f225125ec9d37cea82e538107d3db76018ec8c2e7e69cc93c308135012b6c6ee70fcc1034f0f4321531a15eba19077e1ed4befca8f9" }, "score": { "v": 4, @@ -79,8 +79,8 @@ "t": "rankings", "c": "score" }, - "c": "stack-encrypt:1:AQAAAAAAAAAAAAAAAAAAAAAdcnRvoEEyjJO4SJ0QoQxyIAAWeon6kK0bnzHkJPNFV77QcE9ws0SBOC8udyFu1wQVVQJ2t+3/Rkek59/J7fRQYHVLNvDLxukNBbokL5IOQCiE/3SVDWb0", - "op": "004e3516c0d33a94c4ba52f438645a422d570ec9e8ff91214f13848b1eb09310c1a23351ac149e998374c4baea8eaf9247fcf7465dd3a946be01332c42889aeb49" + "c": "stack-encrypt:1:AQAAAAAAAAAAAAAAAAAAAAAdcnRvoEEyjJO4SJ0QoQxyIAAWeon6kK0bnzHkJPNFV77QcE9ws0SBOC8udyFu1wQVVQLtGJGpfzsg2eTZUQL4htIucnQL62igrzjSlzDNXG80DniqHFV9", + "op": "00afc8f4046464970d69b4b34bc9303e7866cd00efeb86f8fd6976d2c00ac383945a7b54d8a621a2638789295b09b260425c29a6d014946d998e60240ad879f82d" }, "speed": { "v": 4, @@ -88,8 +88,8 @@ "t": "rankings", "c": "speed" }, - "c": "stack-encrypt:1:AQAAAAAAAAAAAAAAAAAAAACQhhB1srtFMhmPGNU3YdsWIADsfyGa4Tr54eU6CvZPZuGD26cBMDuzAO68y/GPMEqBTALILPPKyY05f6gsuB1SdbmqiH4qDmgFT5U58X3BsRGNNfM=", - "op": "003c173a74a6502886339a78c9c32c6aae7ebde1d06257855d71e33b84651ef15d77ddbbc7980a6fa7634fb604fd5b2f52c248e3531b61f181a2a9662ae051aaff" + "c": "stack-encrypt:1:AQAAAAAAAAAAAAAAAAAAAACQhhB1srtFMhmPGNU3YdsWIADsfyGa4Tr54eU6CvZPZuGD26cBMDuzAO68y/GPMEqBTAJLKQ3WrwQrp0BbNSrDN3OP5DzjCYO63Vhk9wp7YQn2AnU=", + "op": "006bcb16a0ca276cd520f79e701a76fe4b1a06b2f8ecd90c6487fc940c6a63ff747c349d78adddd438e89a3e768c78b6f3e4e302376b3a3de2c92c310badd1fdc7" }, "title": { "v": 4, @@ -97,9 +97,9 @@ "t": "rankings", "c": "title" }, - "c": "stack-encrypt:1:AQAAAAAAAAAAAAAAAAAAAABDsM58wLdL/OmzeE1bqk6fIAAZc0G+IFRon1pJAfT2YQm7ENl+LSkdnO6ABKfec8JJOwIZax/COEcTjpdSfUvH35SFQKaypGbuq36W7Qkriuu7eEkm", + "c": "stack-encrypt:1:AQAAAAAAAAAAAAAAAAAAAABDsM58wLdL/OmzeE1bqk6fIAAZc0G+IFRon1pJAfT2YQm7ENl+LSkdnO6ABKfec8JJOwJZgVaehkmapHYafVjSDwng75pAJ8YDT9Kv7DmeKEPM1hpK", "hm": "3bb29d6ed8db30040350b25bdb47263cb156666c5214d96f991850a4672eefc0", - "op": "00344fe120b7abb89fdad4d2ac644367e74b2ca4e6a9b6d4115e85b5966136c35ca2f2645bf578d8d1fe730b1465312f27" + "op": "00e162e4c13c10a383ee7c6728250b0eb0c36a318747a05e1e7d6ff33cb6f61ab79572440b6621f4ce04239540926a68ae" }, "total": { "v": 4, @@ -107,8 +107,8 @@ "t": "rankings", "c": "total" }, - "c": "stack-encrypt:1:AQAAAAAAAAAAAAAAAAAAAAATWgrbBtfjqeFUZIJyCg/TIADRzWl3oad1fwHQ28RfJWb4tEsJ+2+pskxX7xjJHYOtxwKaanS7nY7gY/0rP/z1BlJQivmSTGhqkM8GGU3HYF54RbD163HI", - "op": "007152e605e2cc13823bd1379c7733939403474f5dfe1a65fa73eb63ea134f4a0505668fc80076fb24aaefd4763b1d1a2be9bf875178cf8f4abdbdce26ef1e3d98" + "c": "stack-encrypt:1:AQAAAAAAAAAAAAAAAAAAAAATWgrbBtfjqeFUZIJyCg/TIADRzWl3oad1fwHQ28RfJWb4tEsJ+2+pskxX7xjJHYOtxwLdAPtpEOMcAXRDIR9kmKUiRe73mn23YxY+3BtvYCI8++G436N7", + "op": "00fd575c3250caeb1c5e8c45e48cd4ad8ef38eec0d52d6fd9fcf6f53c01dc212fcb747d609ddf4585907072d7fbd9bf29b59314a2d30ef33f1ac857c7fbad66d47" } } }, @@ -133,8 +133,8 @@ "t": "rankings", "c": "floor" }, - "c": "stack-encrypt:1:AQAAAAAAAAAAAAAAAAAAAAD8EXObyO8iZAsGLtyoF8OzIAAUnZe1c/yU3tUu7btj/FmcuWh0G3VlpdjE4Y1DYkuXYwKjI6FNx98wap6YRPYq0Pr6xumDkjkem3g1aD9Bd15gGJE=", - "op": "0068773fbf20d83c18c9e2c158d14a9601d12eab933e59d10e163110e4f030377b" + "c": "stack-encrypt:1:AQAAAAAAAAAAAAAAAAAAAAD8EXObyO8iZAsGLtyoF8OzIAAUnZe1c/yU3tUu7btj/FmcuWh0G3VlpdjE4Y1DYkuXYwLl8xnxSTGfLOWZDiGjdF0qIcjcXXOvmIP1m7tLH4LJpcg=", + "op": "00ef8ea3833a80e22d0add60fdbcf250c26a3ce5ca10d6bb890804e19e4458fb1b" }, "handle": { "v": 4, @@ -142,9 +142,9 @@ "t": "rankings", "c": "handle" }, - "c": "stack-encrypt:1:AQAAAAAAAAAAAAAAAAAAAAAJSAHc0qCJ5PzM6mX2ijrQIAAOAb/DTu0ioK8DD+OJLmo37ro6p5goGfRbZvv+4GZmmwLyq1pNP+xziI6NvqEt7inQUrLLPhDVG8j3/FIywLlE/SJx", + "c": "stack-encrypt:1:AQAAAAAAAAAAAAAAAAAAAAAJSAHc0qCJ5PzM6mX2ijrQIAAOAb/DTu0ioK8DD+OJLmo37ro6p5goGfRbZvv+4GZmmwKTQzbkIcjT3E5PAkhfC5UHbKSYYb0TCfy7/EORy+L7cDey", "hm": "28fe3661678ecdba7c98355d901c9a8a591c1175c1d7b403bd3d1ec949c8b2e0", - "op": "00e169c8297d7be0a24e597d20e140b6a098c488dda2a5fab8b1a7071ff703df7f0880519d1ea23890b5c6a01066f62633" + "op": "0050d344117a1ebd003b5c7a95186c8d46a9bb20ff555f86bdd726ffb033a113b8daae3b210a878df9b37e0f48f6cd9b97" }, "level": { "v": 4, @@ -152,8 +152,8 @@ "t": "rankings", "c": "level" }, - "c": "stack-encrypt:1:AQAAAAAAAAAAAAAAAAAAAAAhOR6KLBknqtSBVRnlASoSIAAkxpt5V1/27p77EpAoxlp3ceWsCtSnFCzVx1mJZ9TRkwK8xMXduV+d2TMvfn7+P2QF8EnlLYAiRPNnN29ANmoVSts=", - "op": "0159d19c111791f639ba0638692ca6f6c53ecac713e356a7e8bf95fc2d839691f4" + "c": "stack-encrypt:1:AQAAAAAAAAAAAAAAAAAAAAAhOR6KLBknqtSBVRnlASoSIAAkxpt5V1/27p77EpAoxlp3ceWsCtSnFCzVx1mJZ9TRkwLr8RWhmJeqR5s8BUwbq3sR5N2gvxQYgbkhFLM9axg+RhM=", + "op": "0175ce2d2193c247e19cdeeaf00c3aa33f8f41ae2ae07ea8f54907726ef81d76c6" }, "mean": { "v": 4, @@ -161,8 +161,8 @@ "t": "rankings", "c": "mean" }, - "c": "stack-encrypt:1:AQAAAAAAAAAAAAAAAAAAAAAipqSO612avBu8ILwcZ4zfIAClyVXmOu93Sq1j8QZEePtr9Yn/DaGkc/jIzWIJfzRtqwJ1jc06IDRZmX8wTBKbh4NQUgAPFduL3qFTTmzXxfzmMverhaSn", - "op": "017bc9729378e320ff0c1504dc995074a7db7b05d24bed8a923f6944899e4517d213bba21ee639bb01063902e92cad61b3f3b0755b0dacc66fa5188b434c455360" + "c": "stack-encrypt:1:AQAAAAAAAAAAAAAAAAAAAAAipqSO612avBu8ILwcZ4zfIAClyVXmOu93Sq1j8QZEePtr9Yn/DaGkc/jIzWIJfzRtqwIbCtmwIzeVEc2VCTj+1xGmguNhfULa/iNUFBEUAbtUUyiRuBer", + "op": "0092c35e5c06045d306925d152beb010ac631de046e645a8fc36d9809494f97d17931a4e97b083f7725796c282b7aaa3c6a483634026a4ef01c14c9ec5f7d48743" }, "pace": { "v": 4, @@ -170,8 +170,8 @@ "t": "rankings", "c": "pace" }, - "c": "stack-encrypt:1:AQAAAAAAAAAAAAAAAAAAAACSUbSNa21Cz2EdccB0dU93IAB5ZsgjlyQaH70IyAEmbajCC+g5pPkdckAlAyLzt31TpwJZCCAoMewAOd8y+7jLdEfzU5mQ3zdV4dpjHzvMNoIl6q0=", - "op": "00028af974e429d69504e291c6615487c98d3abbaf6a36a012b22bd60ddb569ba83f09243bb5f22d9df419926a7b9e31c7c4411c822471fd427c7a74ac57df0482" + "c": "stack-encrypt:1:AQAAAAAAAAAAAAAAAAAAAACSUbSNa21Cz2EdccB0dU93IAB5ZsgjlyQaH70IyAEmbajCC+g5pPkdckAlAyLzt31TpwJ5G3FdyU2ViJtvOmzHefh/cXKnbGvYLKSexOEZugwjayw=", + "op": "00fc1eaf0613a705488a607f2415941128f4675696e63176b0747adb930727be4c77852c13c8ecf605cffa93d0ae8c0a39e23d295e17f8d87e78996a4d49fd9ea0" }, "points": { "v": 4, @@ -179,8 +179,8 @@ "t": "rankings", "c": "points" }, - "c": "stack-encrypt:1:AQAAAAAAAAAAAAAAAAAAAAD7BDP9k+0Hn5JvKavkeIEeIACwwz3ffvBIoUS+WhQi678dNUBCkgT8GduW9s20XVgb7AKy1BxwBvFhYdWu8TjON31J/XFZE6F1lgnSVZLat6Po+utVYHS2", - "op": "0124da6c76e6a9d3572f27a08b17b843e6581a23213f34fea500706db6d0edf539fee6624d544ab352bbfcd0987056c61e7e2b808fcb36eef07e673ec3639e4235" + "c": "stack-encrypt:1:AQAAAAAAAAAAAAAAAAAAAAD7BDP9k+0Hn5JvKavkeIEeIACwwz3ffvBIoUS+WhQi678dNUBCkgT8GduW9s20XVgb7AJ6q3dJ6UqJVclXtZWuwlUcdyULkPBZCBjiuTHchJ3nMD26EXv7", + "op": "00cee5592b12ad2e56642aea465a82520c4975a84e5e423871fd8c293684946167de3bf467704da5d857f93dd27c836494e7a208adad194349f0c37e05a0f60156" }, "score": { "v": 4, @@ -188,8 +188,8 @@ "t": "rankings", "c": "score" }, - "c": "stack-encrypt:1:AQAAAAAAAAAAAAAAAAAAAAC8mEb7pUk1HxVAoAej3DB3IABYatmLY126M9pYkSV/txgFWt8Dn0gqikv85rJxYY3DsAK7P9SKYcuFN3NNXWdqAQ301cj85RYYFUnxeu9PUP6Hv3Rc0TAf", - "op": "00cf2820721cd8c187f434f8986fd01c7eb126c713b0619086b0ca6d0b2120f8d322bbc60d5e40ac640ec49f271c0894a6965ab22b7da190f2e2af8f157a7b503f" + "c": "stack-encrypt:1:AQAAAAAAAAAAAAAAAAAAAAC8mEb7pUk1HxVAoAej3DB3IABYatmLY126M9pYkSV/txgFWt8Dn0gqikv85rJxYY3DsAI8PIShjXpBDo4onnXH7fmRbS8SHt3bd1H+PDezRvi+nk8obBa5", + "op": "0130440c006ce9cfd5eaae7c256850391359737687b73654638245f850c248cdc5b048baf4ea157de1a7ba1da432b34ce8db6242944a1487c8650b12ed349aff2d" }, "speed": { "v": 4, @@ -197,8 +197,8 @@ "t": "rankings", "c": "speed" }, - "c": "stack-encrypt:1:AQAAAAAAAAAAAAAAAAAAAAAu+yQLbuCeiI1Kc93l5gM9IABDnI3BuN2mIRVGQNCz+OT9g1NBNpy73iq+RyQMrDq2SgLdiotIJVKFxL7zjyPD19PobupEvKh4GhfipnC5MhqxmUc=", - "op": "00bbc2ac417a8cb6a4b5b69c9f81223f9016f7ffc9e250417dd5afa5cfd4844dac6f9f72bf972a4aba57ae0f7e64bc7ce315095aab620f1f0f7a567d525837af8c" + "c": "stack-encrypt:1:AQAAAAAAAAAAAAAAAAAAAAAu+yQLbuCeiI1Kc93l5gM9IABDnI3BuN2mIRVGQNCz+OT9g1NBNpy73iq+RyQMrDq2SgImHrG0RwQ2frkco90AQLcPjtI91WY0YiqoX6uJeqJ8Lbw=", + "op": "00eb900ca25552ce78eaef5e2496345a98454225f1b19c906a2e7aeb3c52c3fe559b518926897a71ef5b835ae2d445d30274ac3b4bca05c2cba135065fd0581e42" }, "title": { "v": 4, @@ -206,9 +206,9 @@ "t": "rankings", "c": "title" }, - "c": "stack-encrypt:1:AQAAAAAAAAAAAAAAAAAAAAB8xVf2YzyG2GIJsjlxprEhIAARLofbMnEJkC3zRNC1Liyue93ywxEK707OQBNyU3GRRAIR6N/Yy+L9m18gSMba81M6XZu9nnwSMGCjCFmC6FtEdAC0", + "c": "stack-encrypt:1:AQAAAAAAAAAAAAAAAAAAAAB8xVf2YzyG2GIJsjlxprEhIAARLofbMnEJkC3zRNC1Liyue93ywxEK707OQBNyU3GRRAI/IBd/bqkuJs3D5EnYeLpVziX7o356LElM+8Q6HJy7eCFL", "hm": "96c9b4169dddc5b00a92aca4f2141eaa81586bb3c0459c9621c6152a938bccc2", - "op": "00344fe120b7abb89fdad4d2ace56e65d225dc12e1f08841a86ad18728afb74d36c3bdd298ed9a2e94e98a2e9328a2fa76" + "op": "00e162e4c13c10a383ee7c6728a616e1e72458a7cc35c5204061bf8f01800520009adea5aca7256ecb6b5a1f95ebfa4fcd" }, "total": { "v": 4, @@ -216,8 +216,8 @@ "t": "rankings", "c": "total" }, - "c": "stack-encrypt:1:AQAAAAAAAAAAAAAAAAAAAABsGQzdwhlf/5JQSTVnel1lIADu5SaW0n7eTUy2k1WrssfM1qoPuD3RSy12zQc69AvRNwKYqTPivNDeEnZygzTBpFhBGNtG92Y0Kltt9qEE0OEUYseWMu0H", - "op": "007152e605e2cc13823bd1379c7733939403474f5dfe1a65fa73eb63ea134f4a0505668fc80076fb24aaefd4763b1d1a2be9bf875178cf8f4abdbdce276f071ed9" + "c": "stack-encrypt:1:AQAAAAAAAAAAAAAAAAAAAABsGQzdwhlf/5JQSTVnel1lIADu5SaW0n7eTUy2k1WrssfM1qoPuD3RSy12zQc69AvRNwKOzeJ9+3J/ByVsOrY7S30QJL9A+FlCiaAdoPf2VktL+Lb9ry+a", + "op": "00fd575c3250caeb1c5e8c45e48cd4ad8ef38eec0d52d6fd9fcf6f53c01dc212fcb747d609ddf4585907072d7fbd9bf29b59314a2d30ef33f1ac857c803ac46bfb" } } }, @@ -242,8 +242,8 @@ "t": "rankings", "c": "floor" }, - "c": "stack-encrypt:1:AQAAAAAAAAAAAAAAAAAAAAAahRXPLhcOhZalhxaRKtwfIACZJ24pqBpQ/xkQSjuIcUV0/DY8mrP3JugbZIjLooy/agJXmfRZQv8gd+32H9A96zYw31oM8RyIVpR/HrQbVP/a6vM=", - "op": "00e7a865a4a6a28052352a8eb6c1265f682958013daa3f37fce5f07022a097aa85" + "c": "stack-encrypt:1:AQAAAAAAAAAAAAAAAAAAAAAahRXPLhcOhZalhxaRKtwfIACZJ24pqBpQ/xkQSjuIcUV0/DY8mrP3JugbZIjLooy/agKO2U99zlAApptBhithXBT1INauyAg+b7UXv1msrRVyvZ0=", + "op": "016f0e9c2c834418ca75f76b50bb475005bdf8e0aa1a1df3f57756822461aef5e7" }, "handle": { "v": 4, @@ -251,9 +251,9 @@ "t": "rankings", "c": "handle" }, - "c": "stack-encrypt:1:AQAAAAAAAAAAAAAAAAAAAACAaXkgSLAngfKw540Hh/cyIABUzHBgSmtLU4FEA1PiYLaeQb+T1nu8+sQyX6e1dXFFnAJ8t2RiTgBT5L5jai/lA/1J1ipI8gx72xi4G78HNRc8LzU=", + "c": "stack-encrypt:1:AQAAAAAAAAAAAAAAAAAAAACAaXkgSLAngfKw540Hh/cyIABUzHBgSmtLU4FEA1PiYLaeQb+T1nu8+sQyX6e1dXFFnALMyqIxYkgj8YN7szI+qQheecz6RZOqkNsTb44XAPK6/+0=", "hm": "ec1d4753450fceec15afd623ce671fff76c236cbbbc81af81cef9e694a493ac8", - "op": "00e169c8297d7be0a24e597d20e1c094556c47b21bced759dd8e83e5a075f1b02cf50ad54f524ee158" + "op": "0050d344117a1ebd003b5c7a9518ec8c749ab82d4dff1c76f829db088f31bc9d8d38bb1e156aa75fd9" }, "level": { "v": 4, @@ -261,8 +261,8 @@ "t": "rankings", "c": "level" }, - "c": "stack-encrypt:1:AQAAAAAAAAAAAAAAAAAAAAAxIHgvAEtydMinzMsMC9maIABcXRm4Ec9fNHs/VMPHO2YcFzhLBtvGDaO5/vL94Up4DwKIvL/fnqO4f4Bu9W6FNibpKRmt9aQmi/P+igsXeqf1LXc=", - "op": "0159d19c111791f639ba0638692ca6f6c53ecac713e356a7e8c016099dca23df54" + "c": "stack-encrypt:1:AQAAAAAAAAAAAAAAAAAAAAAxIHgvAEtydMinzMsMC9maIABcXRm4Ec9fNHs/VMPHO2YcFzhLBtvGDaO5/vL94Up4DwK6DcVon2MqGVSmg/n+w2hAqzujhL73JzDK3/HLvog0TOw=", + "op": "0175ce2d2193c247e19cdeeaf00c3aa33f8f41ae2ae07ea8f549881a7c90d46b04" }, "mean": { "v": 4, @@ -270,8 +270,8 @@ "t": "rankings", "c": "mean" }, - "c": "stack-encrypt:1:AQAAAAAAAAAAAAAAAAAAAAA3MuHYMxBxol/l3CWUUdMwIACBix0i7ecA6Ldg1y72uB17y+CSAZFHm7KMBeJIDB9SSQJr4639om/GxjhRNe96mH/k6IVqzDKdy1vQcaiHL6M/rhySzCh1", - "op": "017c49c16621a2476ed2e40c07fd2d0b35d8f722f0b0e7bca5a4681d69a349806e3554d39f0d13392b43cfe477aed64f8d13ba4fb8e786dbb8c60b454a8a50197c" + "c": "stack-encrypt:1:AQAAAAAAAAAAAAAAAAAAAAA3MuHYMxBxol/l3CWUUdMwIACBix0i7ecA6Ldg1y72uB17y+CSAZFHm7KMBeJIDB9SSQJ/4geqcL6NU2f9TlBQcromWddycp68Qm1ctDG0x0tDOxgDPy98", + "op": "009343d48b97e8026b9fe25b8c3b2393370d2ccc79dd58a123e184f7b005e3a7370ab0c27eb4cfabc90a1b6ad2ec43d0d1d6916fc62f15bd516a5c892a9030d9a8" }, "pace": { "v": 4, @@ -279,8 +279,8 @@ "t": "rankings", "c": "pace" }, - "c": "stack-encrypt:1:AQAAAAAAAAAAAAAAAAAAAADsocba1ACUuZab/S3cR0ewIACbWZ1UAMwA6rnu+PuFd4RCwsXLXgkmZwavUB2HQ5lIMAKNgBydDXntlpuWxH4iE3ALX8ukrBS2pqIyrliA+pyNHzI=", - "op": "00822a022b1129809c146cada9cd22fa5208b482279f0e58376d67e7619bf3c39ab962520422fd56d4c43422be205365bfe363bf466ba709ced360af209fdf2c8c" + "c": "stack-encrypt:1:AQAAAAAAAAAAAAAAAAAAAADsocba1ACUuZab/S3cR0ewIACbWZ1UAMwA6rnu+PuFd4RCwsXLXgkmZwavUB2HQ5lIMAKhysHRdK+xHkMRf4AzRjvhY7aQh2Ou3lveRx7rFtlUVj0=", + "op": "017b1ab81d18c03ddbf803bc41253de9e293609ab35dc3f700c0689973d65e0ae063f07959247b4033650e9a21afa5298fe9a1e39254a94de0634a097fc1f3a9c0" }, "points": { "v": 4, @@ -288,8 +288,8 @@ "t": "rankings", "c": "points" }, - "c": "stack-encrypt:1:AQAAAAAAAAAAAAAAAAAAAACyINaK+oMYBWGqilpz+Y8WIAAAAwXxsCfja/ehP5So7kKPSpDckgOjdWAFkQ0JFNatGgIjwqEjrceceNJS9EXjqbF+syMBx0UeigKdwBZvpKg1VJUetU8L", - "op": "0124da6c76e6a9d3572f27a08b17b843e6581a23213f34fea500706db6d0edf539ff65903adb0c33d49877a8393f339203152f20ddbf199339e4e940bf5754b804" + "c": "stack-encrypt:1:AQAAAAAAAAAAAAAAAAAAAACyINaK+oMYBWGqilpz+Y8WIAAAAwXxsCfja/ehP5So7kKPSpDckgOjdWAFkQ0JFNatGgIfCpCjNW8aci+3rkdftjLwPVl6fRHGf6wv/rudqQMtQEvmvEUU", + "op": "00cee5592b12ad2e56642aea465a82520c4975a84e5e423871fd8c293684946167debc28206a3fcea85fcfe571cf1a01a65f3d51c5aac8a3e2ebe865a37132398f" }, "score": { "v": 4, @@ -297,8 +297,8 @@ "t": "rankings", "c": "score" }, - "c": "stack-encrypt:1:AQAAAAAAAAAAAAAAAAAAAADLJrDpNuSIT1MzDrC3NqkdIADeidZb+K23yM3QNYs+J9lmB9ImCm/0mFW58UkeELUnfgLrLahFD5GGGpELE5j98cbiAvLw/UzqRHXRZdjAzrhSGvAhJpcP", - "op": "00cf2820721cd8c187f4b49ef818bca2626025cd2725b90a8daab1fff0d28e46031a6cf188bff7fd4095aac4fd74613c395a909cb2f6ee863ff59d364234862a3a" + "c": "stack-encrypt:1:AQAAAAAAAAAAAAAAAAAAAADLJrDpNuSIT1MzDrC3NqkdIADeidZb+K23yM3QNYs+J9lmB9ImCm/0mFW58UkeELUnfgJWtZCvurIZKVjUreUpZbPutDYzXJvwyIAEiSaMDQsgpwFsvCPa", + "op": "0130440c006ce9cfd5eb2d2edfd7836896f991265d5e67513a2a1476e8da2275d206a174a6ce14b5a72f94f6bc4966db9495725e6a997237e7e75548ea926e5899" }, "speed": { "v": 4, @@ -306,8 +306,8 @@ "t": "rankings", "c": "speed" }, - "c": "stack-encrypt:1:AQAAAAAAAAAAAAAAAAAAAACgW67nY8FTYuEOauFB2JqpIAB5N3v5rvteb1kWiSLlblOJ9Bvwa4mzUHOFsJbqvqlsrQL8ByKpYorieYyq9NnIkuVxcznI5zABTlD5OzN1KGkjl+M=", - "op": "00bbc2ac417a8cb6a4b5b71c87a011af4b942767664acfa469bbd491bf66466451a9ee3aac2b56a2f81fcdb0a2b6c84725f60ad5bb727b2c14eda1eb054fb92592" + "c": "stack-encrypt:1:AQAAAAAAAAAAAAAAAAAAAACgW67nY8FTYuEOauFB2JqpIAB5N3v5rvteb1kWiSLlblOJ9Bvwa4mzUHOFsJbqvqlsrQJmEl1nhMbRkyf7S99+hyGQk0RG2UQ34c9Z6LsTgVgjAWw=", + "op": "00eb900ca25552ce78eaefde93eb9ebe09ef5cdb3ca91e12f8e706c381ab05982150cfc83d382b9917822162f9cf5d6d9d23c4530f3d833ab0409948390d4e6a64" }, "title": { "v": 4, @@ -315,9 +315,9 @@ "t": "rankings", "c": "title" }, - "c": "stack-encrypt:1:AQAAAAAAAAAAAAAAAAAAAACoLw9QzYPeYb2lWmo5koQrIAAWqW7Qj+fimzpnYilKdFOpSi5wedGlAhzFUlLDVfQXrgI200vJrAyvuyAWRolG7M4tS7aNYBt3umCJUE7DlkMSjIO3fe+U", + "c": "stack-encrypt:1:AQAAAAAAAAAAAAAAAAAAAACoLw9QzYPeYb2lWmo5koQrIAAWqW7Qj+fimzpnYilKdFOpSi5wedGlAhzFUlLDVfQXrgJhR0LzF3WwvU7TFJI7z/16xtPBFEO2wXC6fEz2XODBz9SjPqBd", "hm": "0784eaafee80c50e6a9856e256e99dd536f50c9668cba8bfef433b7bf75e22d0", - "op": "00344fe120b7abb89fdad4d32c82054f71be09c4ac588f34f122f9c53b1fdf516a7cd4f4017f13ffd88a1757c19da753ff8eb398b6832378da3944d7e286e6cb345a82887f75e76591" + "op": "00e162e4c13c10a383ee7c67a933435cadea8adcd88446abcafaf146d817a68b7e423e6efbc2f3ef98d1eae17bacf00f8a3f4439769da3bcabc60d1de9b3ccb95b9f8b1a7996cebf75" }, "total": { "v": 4, @@ -325,8 +325,8 @@ "t": "rankings", "c": "total" }, - "c": "stack-encrypt:1:AQAAAAAAAAAAAAAAAAAAAADqzuNSUCG8WYJqEd0qG67nIAAN5uG4KA4yAHLXuPwfwCvXit4ti1MjxU/VymYIyK+Q9AKCtwW2fHKhvHt8T3IIrxXZAUpi7B02kqV6TuyK+8SRr5pGIgLH", - "op": "00f029fe2d68c79a0ca72ec21e5352a77673be1b39fae030898356ddae1d2cf9f0d771411be2b36c41f5215db20a3f965b37a8a6f7ff1e80c3be894eeb226759a2" + "c": "stack-encrypt:1:AQAAAAAAAAAAAAAAAAAAAADqzuNSUCG8WYJqEd0qG67nIAAN5uG4KA4yAHLXuPwfwCvXit4ti1MjxU/VymYIyK+Q9AJcWBbxC+8wtEUUWOrss1eS/RTvqSlS5Qx72TSTWC/tVwxgg4St", + "op": "017c32c0ff05fac9eda05acbab7e34f5b0cdcfe16e60ec414b9180b114241969a3384bbc2c96a02606bca28486b3d83c00b044eaee11b23a6a3f60e4dcb9616ea6" } } } diff --git a/packages/eql/tests/timing/ore_block_v2/README.md b/packages/eql/tests/timing/ore_block_v2/README.md index f90bbc6f1..4d1c8594b 100644 --- a/packages/eql/tests/timing/ore_block_v2/README.md +++ b/packages/eql/tests/timing/ore_block_v2/README.md @@ -49,17 +49,21 @@ that schema already exists, it refuses to run rather than touch it. ## Method -`ctgen` produces real ore-rs 0.9.0 ciphertexts, one term per side, in four -kinds of two classes each, plus a correctness set: +`ctgen` produces real ore-rs ciphertexts, one term per side, in four kinds +of two classes each, plus a correctness set. It encrypts through ore-rs's +`BlockOre` and vitaminc-ore, as stack-encrypt does, so text is encoded as a +marker byte and then the text: - **fixed**: `u64` terms of the fixed-width scheme (11 blocks), differing in the first block against differing only in the last; - **equal**: a `u64` against a second encryption of the same value (a different nonce, no block differs), against a first-block difference; -- **chained**: 31-byte text of the chained scheme (a 32-byte bucket, 43 - blocks), differing in the first character against only the last; -- **prefix**: 10-byte text (a 16-byte bucket, 22 blocks) against 26-byte - text (a 32-byte bucket, 43 blocks) whose first 22 blocks equal it, so the +- **chained**: 31-character text of the chained scheme (32 bytes encoded, + a 32-byte bucket, 43 blocks), differing in the first character against + only the last; +- **prefix**: 10-character text (11 bytes encoded, a 16-byte bucket, 22 + blocks) against 26 encoded bytes (a 32-byte bucket, 43 blocks) whose first + 22 blocks equal it, so the block counts settle the order, against the same shapes differing in the first block; - **checks**: 1,500 random pairs of either scheme with shared prefixes of @@ -84,6 +88,11 @@ counts as no detectable difference. ## Results +These were measured with ore-rs 0.9.0's ciphertexts, before `ctgen` moved to +0.10. The wire format the comparator reads (the headers, the block counts, +the halves) did not change, and the text shapes above give the same block +counts as they did. + PostgreSQL 17.5 run natively on macOS, Apple silicon, 100,000 samples per kind, two runs. The machine was shared with other builds, which shows in the difference between the runs' means; classes are drawn at random per diff --git a/packages/eql/tests/timing/ore_block_v2/ctgen/Cargo.lock b/packages/eql/tests/timing/ore_block_v2/ctgen/Cargo.lock index 16d2dfbc8..a600d1a03 100644 --- a/packages/eql/tests/timing/ore_block_v2/ctgen/Cargo.lock +++ b/packages/eql/tests/timing/ore_block_v2/ctgen/Cargo.lock @@ -10,7 +10,7 @@ checksum = "b169f7a6d4742236a0a00c541b845991d0ac43e546831af1249753ab4c3aa3a0" dependencies = [ "cfg-if", "cipher", - "cpufeatures", + "cpufeatures 0.2.17", "zeroize", ] @@ -20,34 +20,95 @@ version = "1.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f2032f911046de80f0a198e0901378627c33f59ea0ac00e363d481118bd70a53" +[[package]] +name = "bitvec" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ddcec3d12c579d40898fe0a9a358a803c23e9c52ca3c425707f81c9436211837" +dependencies = [ + "funty", + "radium", + "tap", + "wyz", +] + +[[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 = "block-modes" version = "0.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9e2211b0817f061502a8dd9f11a37e879e79763e3c698d2418cf824d8cb2f21e" +[[package]] +name = "bumpalo" +version = "3.20.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72f5acc6cb2ba439de613abc23857ec3d78374d8ed5ac84e9d11336e87da8649" + [[package]] name = "byteorder" version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" +[[package]] +name = "bytes" +version = "1.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc652a48c352aef3ea3aed32080501cf3ef6ed5da78602a020c991775b0aff04" +dependencies = [ + "serde", +] + [[package]] name = "cfg-if" version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4e7648175b45a9a48536d676f68d918270699102aa8dab5496df06904c914600" +[[package]] +name = "chacha20" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "65c35e4b699c7e15ccbe7ee35c005e4fc0a278d22238a2857e6ce2dadeda1b06" +dependencies = [ + "cfg-if", + "cpufeatures 0.3.1", + "rand_core 0.10.1", + "zeroize", +] + [[package]] name = "cipher" version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "773f3b9af64447d2ce9850330c473515014aa235e6a783b02db81ff39e4a3dad" dependencies = [ - "crypto-common", + "crypto-common 0.1.7", "inout", ] +[[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 = "cpufeatures" version = "0.2.17" @@ -57,6 +118,15 @@ dependencies = [ "libc", ] +[[package]] +name = "cpufeatures" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5ca28b0ae3115b884660db4118d803791fd6756b6e88f39c0f3f7859060d7566" +dependencies = [ + "libc", +] + [[package]] name = "crypto-common" version = "0.1.7" @@ -67,6 +137,73 @@ dependencies = [ "typenum", ] +[[package]] +name = "crypto-common" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce6e4c961d6cd6c9a86db418387425e8bdeaf05b3c8bc1411e6dca4c252f1453" +dependencies = [ + "hybrid-array", +] + +[[package]] +name = "ctutils" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "12218662ccac37d9714f2191252553d67585b97df8c839cbe49e0bde278dc865" +dependencies = [ + "cmov", +] + +[[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 0.2.2", + "ctutils", + "zeroize", +] + +[[package]] +name = "equivalent" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "00d174d5400e5e8fd687ad1049e2f578285fa914201b1af7e8b112a4546bd826" + +[[package]] +name = "funty" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6d5a32815ae3f33302d95fdcb2ce17862f8c65363dcfd29360480ba1001fc9c" + +[[package]] +name = "futures-core" +version = "0.3.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "92d699e522242e69e3003b94ecc1f960f3a5e015aa7c5d7486e65ad01dd94f5e" + +[[package]] +name = "futures-task" +version = "0.3.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd417de3d1d015fc3bfd2b1ea46dfc7bab72ef86f1cc7cc9c78e728b34a6d1fd" + +[[package]] +name = "futures-util" +version = "0.3.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0d50a92467f8ba5dd6e3ee5d4bd04d73ab2e4e1c44474a0674821dfce14b79bc" +dependencies = [ + "futures-core", + "futures-task", + "pin-project-lite", + "slab", +] + [[package]] name = "generic-array" version = "0.14.7" @@ -88,12 +225,60 @@ dependencies = [ "wasi", ] +[[package]] +name = "getrandom" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "300e883d756b2e4ec94e02791f39b04b522276138852cfc41d9fb7e904106099" +dependencies = [ + "cfg-if", + "js-sys", + "libc", + "r-efi", + "rand_core 0.10.1", + "wasm-bindgen", +] + +[[package]] +name = "hashbrown" +version = "0.17.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed5909b6e89a2db4456e54cd5f673791d7eca6732202bbf2a9cc504fe2f9b84a" + [[package]] name = "hex" version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" +[[package]] +name = "hmac" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6303bc9732ae41b04cb554b844a762b4115a61bfaa81e3e83050991eeb56863f" +dependencies = [ + "digest", +] + +[[package]] +name = "hybrid-array" +version = "0.4.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "27f864f10dfb56725ce5ce5472bc52252c8f93a4ab86327122cebf62c5f59a17" +dependencies = [ + "typenum", +] + +[[package]] +name = "indexmap" +version = "2.14.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cc4e190f5d26ca7051642629da2c52fc03bde85a03197c99408dcd291734c855" +dependencies = [ + "equivalent", + "hashbrown", +] + [[package]] name = "inout" version = "0.1.4" @@ -103,12 +288,34 @@ dependencies = [ "generic-array", ] +[[package]] +name = "js-sys" +version = "0.3.106" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7883d941dae510fb2d978fc3fe018c71c9e2892fd38854de3e8b92c2e5ad9cc5" +dependencies = [ + "cfg-if", + "wasm-bindgen", +] + [[package]] name = "libc" version = "0.2.191" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "65cd87c9a6d60536580b316ad985726104730a5151c99845f2490428ef91240a" +[[package]] +name = "memchr" +version = "2.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf8baf1c55e62ffcace7a9f06f4bd9cd3f0c4beb022d3b367256b91b87513d98" + +[[package]] +name = "mutants" +version = "0.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "add0ac067452ff1aca8c5002111bd6b1c895baee6e45fcbc44e0193aea17be56" + [[package]] name = "num" version = "0.4.3" @@ -182,10 +389,10 @@ dependencies = [ ] [[package]] -name = "orderable-bytes" -version = "0.2.1" +name = "once_cell" +version = "1.21.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c7d30b72ffca73d9936fe5fc80a9c9520c73f5b4f64839a810211903d5ace3c" +checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" [[package]] name = "ore-block-v2-timing-ctgen" @@ -193,28 +400,40 @@ version = "0.0.0" dependencies = [ "hex", "ore-rs", - "rand", + "rand 0.8.8", + "vitaminc-ore", + "vitaminc-protected", ] [[package]] name = "ore-rs" -version = "0.9.0" +version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0e1d6cb8c1249643266bd60269547c93d3cd263d5385f1262902bbb295ff9a5e" +checksum = "8bd65962ec1409c09d20e1e016f4fe1b4ae2e2e58dba38c155538b2c0801a185" dependencies = [ "aes", "block-modes", "byteorder", "hex", "num", - "orderable-bytes", - "rand", - "rand_chacha", + "rand 0.10.3", "subtle-ng", - "thiserror", + "thiserror 1.0.69", + "vitaminc-context", + "vitaminc-hmac", + "vitaminc-ore", + "vitaminc-prf", + "vitaminc-protected", + "vitaminc-random", "zeroize", ] +[[package]] +name = "pin-project-lite" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a89322df9ebe1c1578d689c92318e070967d1042b512afbe49518723f4e6d5cd" + [[package]] name = "ppv-lite86" version = "0.2.21" @@ -224,6 +443,15 @@ dependencies = [ "zerocopy", ] +[[package]] +name = "proc-macro-crate" +version = "3.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e67ba7e9b2b56446f1d419b1d807906278ffa1a658a8a5d8a39dcb1f5a78614f" +dependencies = [ + "toml_edit", +] + [[package]] name = "proc-macro2" version = "1.0.107" @@ -242,6 +470,18 @@ dependencies = [ "proc-macro2", ] +[[package]] +name = "r-efi" +version = "6.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8dcc9c7d52a811697d2151c701e0d08956f92b0e24136cf4cf27b57a6a0d9bf" + +[[package]] +name = "radium" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc33ff2d4973d518d823d61aa239014831e521c75da58e3df4840d3f47749d09" + [[package]] name = "rand" version = "0.8.8" @@ -250,7 +490,18 @@ checksum = "e058c7de0b26af77780c769414d6257830bb240f3c38477dbc2c16e5f54d6d4c" dependencies = [ "libc", "rand_chacha", - "rand_core", + "rand_core 0.6.4", +] + +[[package]] +name = "rand" +version = "0.10.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "65c9fb96cbc91e3478eaae79a69fcd3f1ae4ad052e471fe6732fff548984b4af" +dependencies = [ + "chacha20", + "getrandom 0.4.3", + "rand_core 0.10.1", ] [[package]] @@ -260,7 +511,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" dependencies = [ "ppv-lite86", - "rand_core", + "rand_core 0.6.4", ] [[package]] @@ -269,9 +520,84 @@ version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" dependencies = [ - "getrandom", + "getrandom 0.2.17", +] + +[[package]] +name = "rand_core" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "63b8176103e19a2643978565ca18b50549f6101881c443590420e4dc998a3c69" + +[[package]] +name = "rustversion" +version = "1.0.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf54715a573b99ac80df0bc206da022bcd442c974952c7b9720069370852e21f" + +[[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_bytes" +version = "0.11.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a5d440709e79d88e51ac01c4b72fc6cb7314017bb7da9eeff678aa94c10e3ea8" +dependencies = [ + "serde", + "serde_core", +] + +[[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.9", +] + +[[package]] +name = "sha2" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "47d7069beb7d6ac7b9acd1039986e73443f24234f41074da099d6f994ac9ad19" +dependencies = [ + "cfg-if", + "cpufeatures 0.3.1", + "digest", ] +[[package]] +name = "slab" +version = "0.4.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c790de23124f9ab44544d7ac05d60440adc586479ce501c1d6d7da3cd8c9cf5" + +[[package]] +name = "subtle" +version = "2.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" + [[package]] name = "subtle-ng" version = "2.5.0" @@ -289,13 +615,39 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "syn" +version = "3.0.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d78c8dee4c7bf0e14673097256fed6142ce9d3b85a408189d07482442145823b" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "tap" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369" + [[package]] name = "thiserror" version = "1.0.69" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52" dependencies = [ - "thiserror-impl", + "thiserror-impl 1.0.69", +] + +[[package]] +name = "thiserror" +version = "2.0.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09e52cb86a36cede5cb101bf8908837b3e4c6e5e59fe7fd85c23fb56200d189e" +dependencies = [ + "thiserror-impl 2.0.21", ] [[package]] @@ -306,7 +658,54 @@ checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.119", +] + +[[package]] +name = "thiserror-impl" +version = "2.0.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fe5197923287db20a58125f0bc85c062f7f2c892de97b18c356f9efb14b28524" +dependencies = [ + "proc-macro2", + "quote", + "syn 3.0.9", +] + +[[package]] +name = "tinyvec" +version = "1.13.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fd3ca314f692efd6c868f8408f53fe444634a845f96c028b97d35f6a1f79f0ee" + +[[package]] +name = "toml_datetime" +version = "1.1.2+spec-1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b86d767906c6c42421dcba507eb9d203e779497710a47782a224bb871653053" +dependencies = [ + "serde_core", +] + +[[package]] +name = "toml_edit" +version = "0.25.17+spec-1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3641d5bbb5349a79e1020a242d251efbc546ad8048d133958323ce9c40a9c9c" +dependencies = [ + "indexmap", + "toml_datetime", + "toml_parser", + "winnow", +] + +[[package]] +name = "toml_parser" +version = "1.1.5+spec-1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baa693a8032d7e1cada7d0041e96126df243179ff061456783ac7f12bda4744c" +dependencies = [ + "winnow", ] [[package]] @@ -315,24 +714,249 @@ version = "1.20.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b6f5e870be6c3b371b77fe0ee0bafb859fa4964b4404c27de1d380043c4dda20" +[[package]] +name = "unicode-general-category" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b993bddc193ae5bd0d623b49ec06ac3e9312875fdae725a975c51db1cc1677f" + [[package]] name = "unicode-ident" version = "1.0.27" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a2c754d6c33795a1c324727428e5a7dedb5b06195f9890bdbcba760d3e246563" +[[package]] +name = "unicode-normalization" +version = "0.1.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75cd3fb03d5288b3ba9a1ee103ac7e9cbb59f0b03d64f8ddfcc04dd42758a85d" +dependencies = [ + "tinyvec", +] + [[package]] name = "version_check" version = "0.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" +[[package]] +name = "vitaminc-aead" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e9bb97fd543ee6a2b168e257ec69d0d274a775b1eaa3f856b5ac2941b01891c1" +dependencies = [ + "bytes", + "futures-util", + "serde", + "thiserror 2.0.21", + "vitaminc-aead-derive", + "vitaminc-context", + "vitaminc-protected", + "vitaminc-random", + "zeroize", +] + +[[package]] +name = "vitaminc-aead-derive" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0845a44c07ddc882ed47a0e92e04fc83496220f054b589ad0cbd215c5009e5b7" +dependencies = [ + "proc-macro2", + "quote", + "syn 3.0.9", +] + +[[package]] +name = "vitaminc-context" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a630079ba2d50680ee5048addd430eda30613559809dd6d383551e6d3d299826" +dependencies = [ + "mutants", + "vitaminc-protected", +] + +[[package]] +name = "vitaminc-hmac" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5fa0ae8bbad85ae30fb5c91b0b72b694d59bf2c2c1e7ad799eda66fdbd67e7c" +dependencies = [ + "hmac", + "sha2", + "vitaminc-prf", + "vitaminc-protected", + "zeroize", +] + +[[package]] +name = "vitaminc-normalize" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f5a2d8875e0b8b35b7a4f9dd698bbd13c989837cea564b5a4cbb5371b78fa937" +dependencies = [ + "thiserror 2.0.21", + "unicode-general-category", + "unicode-normalization", + "vitaminc-aead", + "vitaminc-protected", +] + +[[package]] +name = "vitaminc-ore" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f05518b4d35cb0c592dad59afb11b8e883ea252449b9ae47ff5ddeff0ed49f75" +dependencies = [ + "thiserror 2.0.21", + "unicode-general-category", + "unicode-normalization", + "vitaminc-aead", + "vitaminc-context", + "vitaminc-normalize", + "vitaminc-protected", + "zeroize", +] + +[[package]] +name = "vitaminc-prf" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "916688478273ca3e5c6805b355534ce9263688391cd4ab23b08bef760039d325" +dependencies = [ + "mutants", + "thiserror 2.0.21", + "vitaminc-context", + "vitaminc-protected", +] + +[[package]] +name = "vitaminc-protected" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a6edc22562a9bbff0ba9704a2c43670b2c7cb1637524c045c3ba6436ed00917f" +dependencies = [ + "bitvec", + "digest", + "libc", + "serde", + "serde_bytes", + "subtle", + "thiserror 2.0.21", + "vitaminc-protected-derive", + "zeroize", +] + +[[package]] +name = "vitaminc-protected-derive" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a7cce3a7d0ce6f57c0e82345f20e87f3737cccd3a70aec2a2ab49f68a3a5e24a" +dependencies = [ + "proc-macro-crate", + "proc-macro2", + "quote", + "syn 3.0.9", +] + +[[package]] +name = "vitaminc-random" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8bb253f783ce6f31a55a92f5a9f0526109b8caa6a465edb94244fd344a078c11" +dependencies = [ + "chacha20", + "getrandom 0.4.3", + "rand 0.10.3", + "thiserror 2.0.21", + "vitaminc-protected", + "vitaminc-random-derives", + "zeroize", +] + +[[package]] +name = "vitaminc-random-derives" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df0b3615936d6dded4b775856f4b0fa229d745d183f0b3754ac80035f16c27d9" +dependencies = [ + "proc-macro2", + "quote", + "syn 3.0.9", +] + [[package]] name = "wasi" version = "0.11.1+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b" +[[package]] +name = "wasm-bindgen" +version = "0.2.129" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9bb54f33acc68fd454578d9820b0bde1a1a3d17aa17bb7b6595806d02886d409" +dependencies = [ + "cfg-if", + "once_cell", + "rustversion", + "wasm-bindgen-macro", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-macro" +version = "0.2.129" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2e29d0c35b16e224a7eeb5cd2d25e3e1968fbd65604117b44d3b789d00ee8535" +dependencies = [ + "quote", + "wasm-bindgen-macro-support", +] + +[[package]] +name = "wasm-bindgen-macro-support" +version = "0.2.129" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6f501a8bc3719dba86ef8ae4728879c08001bea749eb1333ac5b91e040e2a6b7" +dependencies = [ + "bumpalo", + "proc-macro2", + "quote", + "syn 3.0.9", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-shared" +version = "0.2.129" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "23f0c9c52aa7cd7d77769a4cfe2a9adb1b331f489a41d912ce14513d5ab995c6" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "winnow" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "23b97319f7b8343df12cc98938e5c3eb436064524c8d2b4e30a1d3a36eecdf81" +dependencies = [ + "memchr", +] + +[[package]] +name = "wyz" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05f360fc0b24296329c78fda852a1e9ae82de9cf7b27dae4b7f62f118f77b9ed" +dependencies = [ + "tap", +] + [[package]] name = "zerocopy" version = "0.8.63" @@ -350,7 +974,7 @@ checksum = "863ad3ac83293fb4d740aedbfdc9240dd8d1a50c1099acd76ce80ce7c7230c7f" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.119", ] [[package]] @@ -370,5 +994,5 @@ checksum = "3c50655cbb0fe3fc43170059e702f1ce5e19b84cec58dc87b037a09935c2f328" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.119", ] diff --git a/packages/eql/tests/timing/ore_block_v2/ctgen/Cargo.toml b/packages/eql/tests/timing/ore_block_v2/ctgen/Cargo.toml index c9a31f8ff..b5e23206e 100644 --- a/packages/eql/tests/timing/ore_block_v2/ctgen/Cargo.toml +++ b/packages/eql/tests/timing/ore_block_v2/ctgen/Cargo.toml @@ -12,9 +12,13 @@ edition = "2021" publish = false [dependencies] -# The 6-bit fixed-width and chained schemes behind EQL v4's `ore_block_v2`; -# the same version as the root Cargo.lock. -ore-rs = { version = "=0.9.0", default-features = false } +# ore-rs's `BlockOre`, whose 6-bit fixed-width and chained engines are what +# EQL v4's `ore_block_v2` compares; the same version as the root Cargo.lock. +# Since 0.10 a value reaches the engines only through vitaminc-ore, as it +# does in stack-encrypt. +ore-rs = { version = "=0.10.0", default-features = false } +vitaminc-ore = "=0.8.0" +vitaminc-protected = "=0.8.0" rand = "0.8" hex = "0.4" diff --git a/packages/eql/tests/timing/ore_block_v2/ctgen/src/main.rs b/packages/eql/tests/timing/ore_block_v2/ctgen/src/main.rs index 203fbef0e..79b37daa9 100644 --- a/packages/eql/tests/timing/ore_block_v2/ctgen/src/main.rs +++ b/packages/eql/tests/timing/ore_block_v2/ctgen/src/main.rs @@ -3,22 +3,26 @@ //! //! fixed u64, 11 blocks; differ in block 0 / only block 10 //! equal u64; a second encryption of a / differ in block 0 -//! chained 31-byte text, 43 blocks; differ in the first -//! character / only the last +//! chained 31-character text (32 bytes encoded), 43 blocks; +//! differ in the first character / only the last //! prefix text in a 16-byte bucket against text in a //! 32-byte bucket: every block a has equals b's //! (the block counts settle it) / the first differs -//! check random pairs of either scheme with shared +//! check random pairs of either engine with shared //! prefixes; expected = sign(a cmp b) //! +//! `BlockOre` sends a `u64` to the fixed-width engine and text to the chained +//! one. vitaminc-ore encodes text as a marker byte and then the text (lower +//! case ASCII folds to itself), so the byte offsets below count the marker. +//! //! Every expected sign is the plaintext order, and ore-rs's own comparator //! is asserted to agree before a row is written. use std::cmp::Ordering; -use ore_rs::scheme::bit2_w6::OreAes128Bit6ChaCha20; -use ore_rs::scheme::chained::OreAes128Bit6ChainedChaCha20; -use ore_rs::{OreCipher, OreEncrypt, OreOutput}; +use ore_rs::{BlockOre, Term}; use rand::Rng; +use vitaminc_ore::{OrderEncrypt, OrderKeyInit, OrderScheme, OrderTarget}; +use vitaminc_protected::Protected; fn sign(o: Ordering) -> i32 { match o { @@ -34,11 +38,20 @@ fn lower(rng: &mut impl Rng, n: usize) -> String { fn main() { let mut rng = rand::thread_rng(); - let key: [u8; 16] = rng.gen(); - let fixed = OreAes128Bit6ChaCha20::init(&key).unwrap(); - let chained = OreAes128Bit6ChainedChaCha20::init(&key).unwrap(); - let ct = |x: u64| x.encrypt(&fixed).unwrap().to_bytes(); - let st = |s: &str| chained.encrypt_str(s).unwrap().to_bytes(); + let key: [u8; 32] = rng.gen(); + let scheme = BlockOre::new(Protected::new(key)); + let fixed = scheme.target(OrderTarget::U64); + let text = scheme.target(OrderTarget::Text); + let ct = |x: u64| fixed.encrypt_checked(&x).unwrap().into_raw().into_bytes(); + let st = |s: &str| { + text.encrypt_checked(&s.to_owned()) + .unwrap() + .into_raw() + .into_bytes() + }; + let compare = |a: &[u8], b: &[u8]| { + BlockOre::compare(&Term::from_bytes(a.to_vec()), &Term::from_bytes(b.to_vec())) + }; let pairs: usize = std::env::args() .nth(1) .map(|s| s.parse().unwrap()) @@ -71,18 +84,15 @@ fn main() { &st(std::str::from_utf8(&last).unwrap()), ); - // 10 bytes pads with NULs to a 16-byte bucket: 22 blocks, the last - // holding two bits of byte 15 and four of byte 16. The longer text - // repeats the padding and puts a byte whose top four bits are clear - // at 16, so all 22 of the shorter text's blocks match it, and its - // 26 bytes take a 32-byte bucket. + // 10 characters encode as 11 bytes, padded with NULs to a 16-byte + // bucket: 22 blocks, the last holding two bits of byte 15 and four + // of byte 16. The longer text repeats the padding and puts a byte + // whose top four bits are clear at 16, so all 22 of the shorter + // text's blocks match it, and its 26 bytes take a 32-byte bucket. let short = lower(&mut rng, 10); - let long = format!("{short}\0\0\0\0\0\0\u{5}{}", lower(&mut rng, 9)); + let long = format!("{short}\0\0\0\0\0\u{5}{}", lower(&mut rng, 9)); let (a, b) = (st(&short), st(&long)); - assert_eq!( - OreAes128Bit6ChainedChaCha20::compare_raw_slices(&a, &b), - Some(Ordering::Less) - ); + assert_eq!(compare(&a, &b), Some(Ordering::Less)); row("prefix", "prefix", &a, &b); let mut other = long.clone().into_bytes(); other[0] = b'a' + (other[0] - b'a' + 1) % 26; @@ -109,10 +119,7 @@ fn main() { }; let (a, b) = (ct(x), ct(y)); let expected = x.cmp(&y); - assert_eq!( - OreAes128Bit6ChaCha20::compare_raw_slices(&a, &b), - Some(expected) - ); + assert_eq!(compare(&a, &b), Some(expected)); println!( "check\t{}\t{}\t{}", sign(expected), @@ -131,10 +138,7 @@ fn main() { }; let (a, b) = (st(&s), st(&t)); let expected = s.as_bytes().cmp(t.as_bytes()); - assert_eq!( - OreAes128Bit6ChainedChaCha20::compare_raw_slices(&a, &b), - Some(expected) - ); + assert_eq!(compare(&a, &b), Some(expected)); println!( "check\t{}\t{}\t{}", sign(expected), diff --git a/packages/stack-encrypt/CHANGELOG.md b/packages/stack-encrypt/CHANGELOG.md index 76a369a06..8d812938e 100644 --- a/packages/stack-encrypt/CHANGELOG.md +++ b/packages/stack-encrypt/CHANGELOG.md @@ -9,6 +9,15 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Added +- **The vitaminc a binding speaks through is re-exported.** `dynamic::frame` + is `vitaminc-aead-frame` (the transport frame and ciphertext codec, with + its `serde` module), `dynamic::plaintext` is vitaminc-aead's value model, + for implementing `Encrypt` on a binding's own values, and the crate root + adds `DecodeError`, `Protected` and `Controlled`. A binding that takes + these from stack-encrypt cannot resolve a second vitaminc, which would + fail only at a `ValueFrame: Decrypt` bound. The Go guest now takes + vitaminc only this way. + - **A block ORE index, `OreBlock`** (ADR-0002 and ADR-0009, amended 2026-10-19). It derives ore-rs 0.9.0's 6-bit block ORE under its own key domain, over the same order keys as the CLLW indexes: @@ -218,6 +227,36 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Breaking +- **stack-encrypt requires the vitaminc 0.8 crates, clww-ore 0.6 and + ore-rs 0.10.** A crate that names a vitaminc type stack-encrypt takes or + returns moves to 0.8 with it. What changes for a caller: + - **Every order term changes.** cllw-ore is now `clww-ore`. Its + keystream was fixed, and its schemes' names (`clww-ore`, `clww-ope`), + which every term's salt binds, changed, so ORE and OPE terms written + before do not compare with new ones. Block ORE goes through ore-rs's + single `BlockOre` scheme, which keys its 6-bit and chained engines + under a new label, so its terms change too. The wire formats, the key + domains of this crate and every sealed ciphertext and equality term are + unchanged: a stored row still opens, and its order terms are re-derived. + `tests/fixtures/stored_rows_v1.json`'s order terms were re-frozen. + - `sem::OreCllw8VariableV1` and `sem::OpeCllw8VariableV1` are renamed + `OreClww8VariableV1` and `OpeClww8VariableV1`, as clww-ore names them. + - **A sealed `None` of a fixed-width type is as long as a `Some`.** + vitaminc 0.8 seals it as a typed null, padded to the type's leaf length, + so absent values no longer show in the length of their ciphertexts. A + reader on vitaminc 0.7 or older refuses a typed null, so upgrade + readers before writers; every null written before still opens. The + `dynamic` feature's sinks carry a typed null through the value model, + and the frame a binding receives holds the plain null. + - **A null still has no equality term.** vitaminc-normalize 0.8 derives + one; this crate drops it, so an absent value keeps a SQL `NULL` in its + equality column, as before, until the index terms of a null are decided + (#1298). + - **Block ORE's text ceiling is unchanged, but counted the new way.** + `vitaminc-ore` puts the marker byte in front of text itself now, and + ore-rs's 1024-byte ceiling counts it, so the fold is still at most 1023 + bytes. + - **`IndexSpec` has a fifth variant, `OreBlock`** (the block ORE index above). The enum is exhaustive on purpose, since a binding has to be taught each index, so a `match` over it needs an arm for `OreBlock`. The diff --git a/packages/stack-encrypt/Cargo.toml b/packages/stack-encrypt/Cargo.toml index 2cfc02e0a..7334e521f 100644 --- a/packages/stack-encrypt/Cargo.toml +++ b/packages/stack-encrypt/Cargo.toml @@ -37,8 +37,8 @@ vitaminc-hmac = { workspace = true } # number whatever its width, text in Unicode 16 NFC. Match text is # normalized by the same crate before it is tokenized. vitaminc-normalize = { workspace = true } -# The order targets (`OrderTarget`) and the scheme traits cllw-ore's -# `vitaminc` feature implements, which order terms encrypt through. +# The order targets (`OrderTarget`) and the scheme traits clww-ore and +# ore-rs implement, which order terms encrypt through. vitaminc-ore = { workspace = true } vitaminc-prf = { workspace = true } vitaminc-protected = { workspace = true } @@ -49,9 +49,9 @@ serde = { workspace = true } # `Descriptor`: the base64 rendering of a non-textual context for ZeroKMS. base64ct = { version = "1.7", features = ["alloc"] } -cllw-ore = { workspace = true } -# Block ORE (`OreBlock`): ore-rs's 6-bit schemes through the same -# vitaminc-ore traits cllw-ore implements. +clww-ore = { workspace = true } +# Block ORE (`OreBlock`): ore-rs's `BlockOre`, its 6-bit schemes behind +# the same vitaminc-ore traits clww-ore implements. ore-rs = { workspace = true } # Every error derives `miette::Diagnostic` (a code, and help where a caller # can act) and gives its structured fields as a `serde_json` map through diff --git a/packages/stack-encrypt/fuzz/Cargo.lock b/packages/stack-encrypt/fuzz/Cargo.lock index ac5eabd82..cde185181 100644 --- a/packages/stack-encrypt/fuzz/Cargo.lock +++ b/packages/stack-encrypt/fuzz/Cargo.lock @@ -359,18 +359,17 @@ dependencies = [ ] [[package]] -name = "cllw-ore" -version = "0.5.2-rc.1" +name = "clww-ore" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "24eb4a774d070a6c2b52175b98273cd7193c61e1bda39c1a98b50b7a2d91375a" +checksum = "b95747f5724666cb973b2ca0659e10b6083c11f99877c4727b4c9f534a591c74" dependencies = [ "blake3", "hex", "subtle", "thiserror 1.0.69", - "unicode-normalization", "vitaminc-ore", - "vitaminc-protected 0.6.1", + "vitaminc-protected 0.8.0", "zeroize", ] @@ -1468,32 +1467,26 @@ dependencies = [ "libc", ] -[[package]] -name = "orderable-bytes" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c7d30b72ffca73d9936fe5fc80a9c9520c73f5b4f64839a810211903d5ace3c" - [[package]] name = "ore-rs" -version = "0.9.0" +version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0e1d6cb8c1249643266bd60269547c93d3cd263d5385f1262902bbb295ff9a5e" +checksum = "8bd65962ec1409c09d20e1e016f4fe1b4ae2e2e58dba38c155538b2c0801a185" dependencies = [ "aes", "block-modes", "byteorder", "hex", "num", - "orderable-bytes", - "rand 0.8.6", - "rand_chacha 0.3.1", + "rand 0.10.1", "subtle-ng", "thiserror 1.0.69", + "vitaminc-context 0.8.0", "vitaminc-hmac", "vitaminc-ore", "vitaminc-prf", - "vitaminc-protected 0.6.1", + "vitaminc-protected 0.8.0", + "vitaminc-random 0.8.0", "zeroize", ] @@ -2067,8 +2060,8 @@ dependencies = [ "tracing", "url", "uuid", - "vitaminc 0.6.1", - "vitaminc-protected 0.6.1", + "vitaminc 0.8.0", + "vitaminc-protected 0.8.0", "web-time", "zeroize", "zerokms-protocol", @@ -2079,7 +2072,7 @@ name = "stack-encrypt" version = "0.3.0" dependencies = [ "base64ct", - "cllw-ore", + "clww-ore", "miette", "ore-rs", "serde", @@ -2088,14 +2081,14 @@ dependencies = [ "stack-kms", "thiserror 1.0.69", "uuid", - "vitaminc-aead 0.6.1", + "vitaminc-aead 0.8.0", "vitaminc-aead-frame", - "vitaminc-encrypt 0.6.1", + "vitaminc-encrypt 0.8.0", "vitaminc-hmac", "vitaminc-normalize", "vitaminc-ore", "vitaminc-prf", - "vitaminc-protected 0.6.1", + "vitaminc-protected 0.8.0", "zeroize", ] @@ -2116,8 +2109,8 @@ dependencies = [ "libfuzzer-sys", "stack-encrypt", "uuid", - "vitaminc-aead 0.6.1", - "vitaminc-protected 0.6.1", + "vitaminc-aead 0.8.0", + "vitaminc-protected 0.8.0", ] [[package]] @@ -2142,8 +2135,8 @@ dependencies = [ "tracing", "url", "uuid", - "vitaminc 0.6.1", - "vitaminc-protected 0.6.1", + "vitaminc 0.8.0", + "vitaminc-protected 0.8.0", "zeroize", "zerokms-protocol", ] @@ -2588,16 +2581,16 @@ dependencies = [ [[package]] name = "vitaminc" -version = "0.6.1" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac5c15b6c25efcb9a6111f7108ab8101947a7bf7e9af3ff6d6a73358a1ace0da" +checksum = "ea37168a603d605732d0bf0672586139ab91736f767d7b85e173c84dcee19054" dependencies = [ - "vitaminc-aead 0.6.1", - "vitaminc-context 0.6.1", - "vitaminc-encrypt 0.6.1", - "vitaminc-protected 0.6.1", - "vitaminc-random 0.6.1", - "vitaminc-traits 0.6.1", + "vitaminc-aead 0.8.0", + "vitaminc-context 0.8.0", + "vitaminc-encrypt 0.8.0", + "vitaminc-protected 0.8.0", + "vitaminc-random 0.8.0", + "vitaminc-traits 0.8.0", ] [[package]] @@ -2617,18 +2610,18 @@ dependencies = [ [[package]] name = "vitaminc-aead" -version = "0.6.1" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "71b8c5c4ced92545dce5fd7cf04581d08210def174cc81475cf227fa2506c5b7" +checksum = "e9bb97fd543ee6a2b168e257ec69d0d274a775b1eaa3f856b5ac2941b01891c1" dependencies = [ "bytes", "futures-util", "serde", "thiserror 2.0.18", - "vitaminc-aead-derive 0.6.1", - "vitaminc-context 0.6.1", - "vitaminc-protected 0.6.1", - "vitaminc-random 0.6.1", + "vitaminc-aead-derive 0.8.0", + "vitaminc-context 0.8.0", + "vitaminc-protected 0.8.0", + "vitaminc-random 0.8.0", "zeroize", ] @@ -2645,9 +2638,9 @@ dependencies = [ [[package]] name = "vitaminc-aead-derive" -version = "0.6.1" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c546497a972d0f0498f2f8d5f537c514bad82df8662951c63d0c80023808900" +checksum = "0845a44c07ddc882ed47a0e92e04fc83496220f054b589ad0cbd215c5009e5b7" dependencies = [ "proc-macro2", "quote", @@ -2656,12 +2649,12 @@ dependencies = [ [[package]] name = "vitaminc-aead-frame" -version = "0.6.1" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e35992a269bcaa5b201f1938e54bfbf167bfa6fe975d83cbdbdb54c2a363c5ef" +checksum = "3b0299777255171712a296d59164691dc1e93d10bddaab6e248fede1790dfd2e" dependencies = [ "serde", - "vitaminc-aead 0.6.1", + "vitaminc-aead 0.8.0", "zeroize", ] @@ -2677,12 +2670,12 @@ dependencies = [ [[package]] name = "vitaminc-context" -version = "0.6.1" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa4c4bc2bd9811253eb427657565a45bd4826e2379e93ee1c4d00c808a769882" +checksum = "a630079ba2d50680ee5048addd430eda30613559809dd6d383551e6d3d299826" dependencies = [ "mutants", - "vitaminc-protected 0.6.1", + "vitaminc-protected 0.8.0", ] [[package]] @@ -2701,71 +2694,72 @@ dependencies = [ [[package]] name = "vitaminc-encrypt" -version = "0.6.1" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f0923694602855b33a296d9af473e282e8096c1cfe1b30b8695d3b6651717fc5" +checksum = "db45e073f92ae8ca27f8fe14270bc34c75e767559c2347098dacca95180d1ddd" dependencies = [ "aes-gcm", "aws-lc-rs", - "vitaminc-aead 0.6.1", - "vitaminc-protected 0.6.1", - "vitaminc-random 0.6.1", + "vitaminc-aead 0.8.0", + "vitaminc-protected 0.8.0", + "vitaminc-random 0.8.0", "zeroize", ] [[package]] name = "vitaminc-hmac" -version = "0.6.1" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd361f626e95cbe770b9d012e4a86c43cfefe4aefb3d5b3ed9339a83085bdc53" +checksum = "b5fa0ae8bbad85ae30fb5c91b0b72b694d59bf2c2c1e7ad799eda66fdbd67e7c" dependencies = [ "hmac", "sha2 0.11.0", "vitaminc-prf", - "vitaminc-protected 0.6.1", + "vitaminc-protected 0.8.0", "zeroize", ] [[package]] name = "vitaminc-normalize" -version = "0.6.1" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "214b2a9d085924c3bc3c91f3ba74238e8848bf54990e5f48f170c71fbacea07a" +checksum = "f5a2d8875e0b8b35b7a4f9dd698bbd13c989837cea564b5a4cbb5371b78fa937" dependencies = [ "thiserror 2.0.18", "unicode-general-category", "unicode-normalization", - "vitaminc-aead 0.6.1", - "vitaminc-protected 0.6.1", + "vitaminc-aead 0.8.0", + "vitaminc-protected 0.8.0", ] [[package]] name = "vitaminc-ore" -version = "0.6.1" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed88c54b5f06f2177ecbfb7666812adf645406f6fb555f4e2f0fd7fa218e71c4" +checksum = "f05518b4d35cb0c592dad59afb11b8e883ea252449b9ae47ff5ddeff0ed49f75" dependencies = [ "thiserror 2.0.18", "unicode-general-category", "unicode-normalization", - "vitaminc-aead 0.6.1", - "vitaminc-context 0.6.1", + "vitaminc-aead 0.8.0", + "vitaminc-context 0.8.0", "vitaminc-normalize", - "vitaminc-protected 0.6.1", + "vitaminc-protected 0.8.0", + "zeroize", ] [[package]] name = "vitaminc-prf" -version = "0.6.1" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c2715cca25006b4656223bc932ab4fd7f70d387aa4ec63a4e2ef33aa8cd2b3a5" +checksum = "916688478273ca3e5c6805b355534ce9263688391cd4ab23b08bef760039d325" dependencies = [ "mutants", "thiserror 2.0.18", - "vitaminc-aead 0.6.1", - "vitaminc-context 0.6.1", + "vitaminc-aead 0.8.0", + "vitaminc-context 0.8.0", "vitaminc-normalize", - "vitaminc-protected 0.6.1", + "vitaminc-protected 0.8.0", ] [[package]] @@ -2787,9 +2781,9 @@ dependencies = [ [[package]] name = "vitaminc-protected" -version = "0.6.1" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1bb76dd473f5aa89b844f92018ebe3041deb8e5390e7061cca4283d959ff855" +checksum = "a6edc22562a9bbff0ba9704a2c43670b2c7cb1637524c045c3ba6436ed00917f" dependencies = [ "bitvec", "digest 0.11.3", @@ -2798,7 +2792,7 @@ dependencies = [ "serde_bytes", "subtle", "thiserror 2.0.18", - "vitaminc-protected-derive 0.6.1", + "vitaminc-protected-derive 0.8.0", "zeroize", ] @@ -2815,9 +2809,9 @@ dependencies = [ [[package]] name = "vitaminc-protected-derive" -version = "0.6.1" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7478ed160c019059746e75fc613563dcdcd5266d155a34601d29377a1c4afc3" +checksum = "a7cce3a7d0ce6f57c0e82345f20e87f3737cccd3a70aec2a2ab49f68a3a5e24a" dependencies = [ "proc-macro-crate", "proc-macro2", @@ -2842,16 +2836,16 @@ dependencies = [ [[package]] name = "vitaminc-random" -version = "0.6.1" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b477af7c01c3d9ef2647e46952ad3df7f246b3f806b1d4009ee83beecec613a" +checksum = "8bb253f783ce6f31a55a92f5a9f0526109b8caa6a465edb94244fd344a078c11" dependencies = [ "chacha20", "getrandom 0.4.2", "rand 0.10.1", "thiserror 2.0.18", - "vitaminc-protected 0.6.1", - "vitaminc-random-derives 0.6.1", + "vitaminc-protected 0.8.0", + "vitaminc-random-derives 0.8.0", "zeroize", ] @@ -2868,9 +2862,9 @@ dependencies = [ [[package]] name = "vitaminc-random-derives" -version = "0.6.1" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ab5a0de8da428c6789dc067a578a0462e411099721d616736cf29e1622230c35" +checksum = "df0b3615936d6dded4b775856f4b0fa229d745d183f0b3754ac80035f16c27d9" dependencies = [ "proc-macro2", "quote", @@ -2895,17 +2889,17 @@ dependencies = [ [[package]] name = "vitaminc-traits" -version = "0.6.1" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a900f0edcacd49c8557ab54722175869fec66926054a6fbdc53a05069db3c922" +checksum = "1e9098ee4b13446ef959583ee2f3c384df571b453179104f7b4960ffddf65ee9" dependencies = [ "anyhow", "bytes", "rmp-serde", "serde", "thiserror 2.0.18", - "vitaminc-protected 0.6.1", - "vitaminc-random 0.6.1", + "vitaminc-protected 0.8.0", + "vitaminc-random 0.8.0", "zeroize", ] diff --git a/packages/stack-encrypt/fuzz/Cargo.toml b/packages/stack-encrypt/fuzz/Cargo.toml index 90a6eaebc..f04dcd487 100644 --- a/packages/stack-encrypt/fuzz/Cargo.toml +++ b/packages/stack-encrypt/fuzz/Cargo.toml @@ -17,9 +17,9 @@ cargo-fuzz = true [dependencies] # `Controlled`, to take a passthrough node's frame out of its wrapper: the # same line stack-encrypt builds on. -vitaminc-protected = "0.6.1" +vitaminc-protected = "0.8.0" # The sinks the record harness writes its plans and passthroughs through. -vitaminc-aead = "0.6.1" +vitaminc-aead = "0.8.0" libfuzzer-sys = "0.4" # Structure-aware inputs for `check_record` and `plan_build`: the mirror # types derive `Arbitrary`, so the fuzzer mutates trees and plans, not bytes. diff --git a/packages/stack-encrypt/src/codes.rs b/packages/stack-encrypt/src/codes.rs index 5cf19530a..2e136ed56 100644 --- a/packages/stack-encrypt/src/codes.rs +++ b/packages/stack-encrypt/src/codes.rs @@ -78,7 +78,7 @@ mod tests { ])); errors.extend(boxed(variants![ TermError::Prf(_) => TermError::Prf(cause()), - TermError::Ore(_) => TermError::Ore(cllw_ore::Error), + TermError::Ore(_) => TermError::Ore(clww_ore::Error), TermError::OreBlockTooLong => TermError::OreBlockTooLong, TermError::OreBlockTrailingNul => TermError::OreBlockTrailingNul, TermError::OreBlock(_) => TermError::OreBlock(cause()), diff --git a/packages/stack-encrypt/src/dynamic/kind.rs b/packages/stack-encrypt/src/dynamic/kind.rs index 039d47b7e..3606b9c3a 100644 --- a/packages/stack-encrypt/src/dynamic/kind.rs +++ b/packages/stack-encrypt/src/dynamic/kind.rs @@ -59,8 +59,8 @@ use crate::target::IndexSpec; /// wider, both floats, text and bytes. A boolean and an 8-bit integer have /// no order term: over so small a domain it would reveal which rows are /// `true`, or each row's rank among 256 values. -/// A decimal, a date and a timestamp have none yet: their order encodings -/// wait for new cllw-ore and ore-rs releases (#1236), and [`not_admitted`] +/// A decimal, a date and a timestamp have none yet: their order terms are +/// tracked in #1236, and [`not_admitted`] /// names that reason. A composite (`array`, `object`) has no term. Only the /// index's kind matters: a match index's options do not change what it /// applies to. @@ -87,8 +87,8 @@ pub fn admits(kind: ValueKind, index: &IndexSpec) -> bool { /// plan that declares the pair is refused with. /// /// [`Reason::OrderTermPending`] for an order index on a decimal, date -/// or timestamp, whose order terms wait for new cllw-ore and ore-rs -/// releases (#1236). [`Reason::IndexNotAdmitted`] for every other pair +/// or timestamp, whose order terms are not built yet (#1236). +/// [`Reason::IndexNotAdmitted`] for every other pair /// [`admits`] refuses. /// /// ``` diff --git a/packages/stack-encrypt/src/dynamic/mod.rs b/packages/stack-encrypt/src/dynamic/mod.rs index 7ccaabf08..1cdd8164d 100644 --- a/packages/stack-encrypt/src/dynamic/mod.rs +++ b/packages/stack-encrypt/src/dynamic/mod.rs @@ -111,6 +111,19 @@ pub use target::{NoTargets, TargetDescriptor, TargetError, TargetResolver}; pub use term::{term, TermBytes}; pub use value_frame::{Children, FromFrameError, Modeled, Opening, ValueFrame}; +/// vitaminc's value model, the sinks and scalar types a value describes +/// itself through. A binding implements [`Encrypt`](crate::Encrypt) for its +/// own values with it, as [`read`] takes them. Re-exported so a binding +/// builds against the vitaminc this crate does. Two versions of vitaminc in +/// one build do not fail loudly: a [`ValueFrame`] stops meeting the other +/// version's `Decrypt` bound. +pub use vitaminc_aead::plaintext; +/// vitaminc's transport frame and ciphertext codec (`vitaminc-aead-frame`, +/// with its `serde` module): the bytes a binding hands this module, and the +/// codec its ciphertexts cross in. Re-exported for the same reason as +/// [`plaintext`]. +pub use vitaminc_aead_frame as frame; + use crate::target::IndexSpec; use crate::{KeysetCipher, StackCipher}; @@ -530,10 +543,9 @@ reasons! { /// equality or an order index on a boolean, any index on a composite. IndexNotAdmitted => "index_not_admitted", "the declared type has no such index"; /// The field declares an ORE or OPE index on a decimal, date or - /// timestamp. Their order terms wait for cllw-ore and ore-rs - /// releases that encode them the ADR-0002 way (#1236); equality on - /// them works today. - OrderTermPending => "order_term_pending", "an order index on a decimal, date or timestamp waits for new cllw-ore and ore-rs releases (#1236)"; + /// timestamp. Their order terms are not supported yet (#1236); + /// equality on them works today. + OrderTermPending => "order_term_pending", "an order index on a decimal, date or timestamp is not supported yet (#1236)"; /// Two fields are keyed under one identity. SharedIdentity => "shared_identity", "two fields are keyed under one identity"; /// The plan has no field of the name asked for. diff --git a/packages/stack-encrypt/src/dynamic/term.rs b/packages/stack-encrypt/src/dynamic/term.rs index 48f360461..bad1e63ba 100644 --- a/packages/stack-encrypt/src/dynamic/term.rs +++ b/packages/stack-encrypt/src/dynamic/term.rs @@ -16,14 +16,14 @@ //! a domain of its own. A boolean has none. //! - **Match** takes text only, cut in Unicode 16 NFC. //! - **ORE, OPE and block ORE** take an integer of 16 bits or wider, a -//! float, text or bytes, each handed to cllw-ore (ORE, OPE) or ore-rs +//! float, text or bytes, each handed to clww-ore (ORE, OPE) or ore-rs //! (block ORE) as the Rust type the typed path would have named: an `i16` //! as an `i16`, a `u128` as a `u128`. A boolean, a `u8` and an `i8` have //! no order term: over a domain that small (two values, or 256) it would //! tell anyone holding the column which rows are `true`, or rank every //! row among 256. A decimal, a date and a timestamp -//! have none yet: cllw-ore 0.5 does not encode them the ADR-0002 way, and -//! their order terms wait for new cllw-ore and ore-rs releases (#1236). +//! have none yet: their order terms are tracked in #1236, and +//! vitaminc-ore 0.8 and ore-rs's `BlockOre` now support those targets. //! //! # These are the query-probe path //! @@ -38,9 +38,10 @@ use std::marker::PhantomData; use super::ValueFrame; use stack_kms::DataKeySource; use vitaminc_aead::plaintext::{ - Error as SinkError, Float, Int, Logical, MapSink, Physical, SeqSink, Sink, SourceError, + Error as SinkError, FixedType, Float, Int, Logical, MapSink, Physical, SeqSink, Sink, + SourceError, }; -use vitaminc_normalize::{domain_of, normalize, NormalizeError}; +use vitaminc_normalize::{domain, domain_of, normalize, NormalizeError}; use serde::{Deserialize, Serialize, Serializer}; @@ -149,8 +150,10 @@ impl IndexSpec { /// The table [`defines`](Self::defines) reads, over one scalar. pub(super) fn takes(&self, ty: Option, value: &Physical<'_>) -> bool { match self { - // vitaminc's table: a kind with an equality domain. - IndexSpec::Equality => domain_of(ty, value).is_some(), + // vitaminc's table: a kind with an equality domain. A null has + // one from `vitaminc-normalize` 0.8, and no term here, as before: + // see `sem::normalized`. + IndexSpec::Equality => domain_of(ty, value).is_some_and(|d| d != domain::NULL), IndexSpec::Match(_) => ty.is_none() && matches!(value, Physical::Text(_)), IndexSpec::Ore | IndexSpec::Ope | IndexSpec::OreBlock => ty.is_none() && ordered(value), } @@ -163,7 +166,7 @@ impl IndexSpec { /// reveals too much, which rows hold `true`, or each row's rank among 256 /// values, which a few known rows resolve to the values. Not a null. The /// caller has already refused a scalar under a logical type: a decimal, -/// date or timestamp's order term waits for a later release. +/// date or timestamp's order term is not built yet (#1236). fn ordered(value: &Physical<'_>) -> bool { match value { Physical::Int(Int::I8(_) | Int::U8(_)) | Physical::Null | Physical::Bool(_) => false, @@ -604,6 +607,12 @@ where (self.0)(ty, value).map_err(Refused) } + /// A typed null is a null to a term: its type hides its length when + /// sealed, which a term does not seal. + fn typed_null(self, _: FixedType) -> Result { + self.scalar(None, Physical::Null) + } + fn seq(self, _: Option) -> Result, Refused> { Err(Refused(None)) } @@ -643,6 +652,10 @@ impl Sink for NoContainer { self.unreachable() } + fn typed_null(self, _: FixedType) -> Result { + self.unreachable() + } + fn seq(self, _: Option) -> Result { self.unreachable() } @@ -1332,9 +1345,8 @@ mod tests { } /// A decimal, a date and a timestamp have an equality term, from - /// vitaminc, and no order term yet: their order encodings wait for - /// new cllw-ore and ore-rs releases (#1236), and the engine does not - /// shim around cllw-ore 0.5. + /// vitaminc, and no order term yet: their order terms are tracked in + /// #1236. #[tokio::test] async fn a_decimal_date_or_timestamp_has_no_order_term_yet() { let cipher = cipher().await; diff --git a/packages/stack-encrypt/src/dynamic/test_frame.rs b/packages/stack-encrypt/src/dynamic/test_frame.rs index 4c4129041..2f57c7f06 100644 --- a/packages/stack-encrypt/src/dynamic/test_frame.rs +++ b/packages/stack-encrypt/src/dynamic/test_frame.rs @@ -9,8 +9,8 @@ use vitaminc_aead::frame::{FrameError, FrameWriteError}; use vitaminc_aead::plaintext::{ - visit_map, visit_seq, Error as _, Float, Int, Logical, MapSink, Physical, SeqSink, Sink, - SourceError, + visit_map, visit_seq, Error as _, FixedType, Float, Int, Logical, MapSink, Physical, SeqSink, + Sink, SourceError, }; use vitaminc_aead::{to_frame, DecodeError, Decrypt, Encrypt, Frame}; use vitaminc_protected::{Controlled, Protected}; @@ -271,6 +271,10 @@ impl Sink for TreeSink { Ok(self.0.put(value)) } + fn typed_null(self, _: FixedType) -> Result { + Ok(self.0.put(Tree::Null)) + } + fn seq(self, _: Option) -> Result, DecodeError> { Ok(TreeSeq { out: self.0, diff --git a/packages/stack-encrypt/src/dynamic/value_frame.rs b/packages/stack-encrypt/src/dynamic/value_frame.rs index e0c0ff6d8..453fbc039 100644 --- a/packages/stack-encrypt/src/dynamic/value_frame.rs +++ b/packages/stack-encrypt/src/dynamic/value_frame.rs @@ -33,7 +33,8 @@ use std::sync::Arc; use vitaminc_aead::frame::{Frame, FrameError, FrameMap, FrameSeq, FrameWriteError, FrameWriter}; use vitaminc_aead::plaintext::kinds::timestamp_nanos; use vitaminc_aead::plaintext::{ - Error as _, Float, Int, Logical, MapSink, Physical, SeqSink, Sink, SourceError, TimeUnit, + Error as _, FixedType, Float, Int, Logical, MapSink, Physical, SeqSink, Sink, SourceError, + TimeUnit, Width, }; use vitaminc_aead::{DecodeError, Decrypt, Encrypt}; use vitaminc_protected::{Controlled, OpaqueDebug, Protected}; @@ -100,6 +101,10 @@ impl ValueFrame { /// Read one value from frame bytes a host handed over. /// + /// A typed null in the bytes reads as a plain null: the value this + /// returns does not remember the type, so sealing it does not pad it to + /// the type's length. + /// /// # Errors /// /// [`FromFrameError::Frame`] when the @@ -200,6 +205,12 @@ impl Sink for Check { .ok_or(DecodeError::Expected(EXPECTED)) } + fn typed_null(self, ty: FixedType) -> Result<(), DecodeError> { + model_null(ty) + .map(drop) + .ok_or(DecodeError::Expected(EXPECTED)) + } + fn seq(self, _: Option) -> Result { Ok(Check) } @@ -331,6 +342,20 @@ fn model(ty: Option, value: Physical<'_>) -> Option<(Option, P }) } +/// A typed null in the value model: a timestamp's as a nanosecond +/// timestamp's, as [`model`] reads the timestamp it stands in for, every +/// other type of the model as it is, or `None` for a type outside the model +/// (a uuid, or a logical type this crate does not know). +fn model_null(ty: FixedType) -> Option { + match ty.logical() { + None | Some(Logical::Date | Logical::Decimal { .. }) => Some(ty), + Some(Logical::Timestamp(_)) => { + FixedType::new(Some(Logical::Timestamp(TimeUnit::Nanos)), Width::I128) + } + _ => None, + } +} + /// A frame writer that holds the [value model](ValueFrame#the-value-model): /// each scalar is read through the model before it is written, and every /// error is a [`DecodeError`], the error a [`Decrypt`] target reports. A @@ -420,6 +445,16 @@ impl<'o> Sink for Modeled> { .map_err(|error| Modeled { inner: (), field }.written(error)) } + fn typed_null(self, ty: FixedType) -> Result<(), DecodeError> { + let Some(ty) = model_null(ty) else { + return Err(self.fault(DecodeError::Expected(EXPECTED))); + }; + let Self { inner, field } = self; + inner + .typed_null(ty) + .map_err(|error| Modeled { inner: (), field }.written(error)) + } + fn seq(self, len: Option) -> Result { let Self { inner, field } = self; let at = Modeled { inner: (), field }; @@ -542,6 +577,15 @@ impl Sink for ModelOnly { } } + fn typed_null(self, ty: FixedType) -> Result { + match model_null(ty) { + Some(ty) => self.0.typed_null(ty), + None => Err(S::Error::source(SourceError::new(DecodeError::Expected( + EXPECTED, + )))), + } + } + fn seq(self, len: Option) -> Result { self.0.seq(len).map(ModelOnly) } @@ -629,6 +673,11 @@ impl Sink for Split { Ok(Parts::Scalar) } + fn typed_null(self, ty: FixedType) -> Result { + let _ = model_null(ty).ok_or(DecodeError::Expected(EXPECTED))?; + Ok(Parts::Scalar) + } + fn seq(self, _: Option) -> Result, DecodeError> { Ok(Children::new(false, parts)) } @@ -748,6 +797,10 @@ impl Sink for Opening { write(|writer| Modeled::new(writer).scalar(ty, value)) } + fn typed_null(self, ty: FixedType) -> Result { + write(|writer| Modeled::new(writer).typed_null(ty)) + } + fn seq(self, _: Option) -> Result, DecodeError> { Ok(Children::new(false, join)) } @@ -835,6 +888,10 @@ impl Sink for Skip { self.done() } + fn typed_null(self, _: FixedType) -> Result { + self.done() + } + fn seq(self, _: Option) -> Result { Ok(self) } @@ -899,6 +956,11 @@ impl Sink for KindOf { Ok(scalar_kind(ty, &value)) } + /// A typed null is a null, which has no kind. + fn typed_null(self, _: FixedType) -> Result { + self.scalar(None, Physical::Null) + } + fn seq(self, _: Option) -> Result { Ok(Skip::ending(Some(ValueKind::Array), false)) } @@ -1006,6 +1068,10 @@ impl Sink for RowsSink { Ok(SourceRows::One(None)) } + fn typed_null(self, _: FixedType) -> Result { + Ok(SourceRows::One(None)) + } + fn seq(self, _: Option) -> Result { Ok(BatchSink(Vec::new())) } @@ -1054,6 +1120,11 @@ impl<'s> Sink for RowSink<'s> { Ok(()) } + fn typed_null(self, _: FixedType) -> Result<(), DecodeError> { + self.0.put(None); + Ok(()) + } + fn seq(self, _: Option) -> Result, DecodeError> { Ok(NotARow(self.0)) } @@ -1173,6 +1244,153 @@ mod tests { ]) } + /// A null that says what it stands in for, as vitaminc walks a `None` + /// of a fixed-width type and as a host may send one in a frame. + #[derive(Clone)] + struct TypedNull(FixedType); + + impl Encrypt for TypedNull { + fn visit(self, sink: S) -> Result { + sink.typed_null(self.0) + } + } + + fn fixed(ty: Option, width: Width) -> FixedType { + FixedType::new(ty, width).expect("a fixed-width type") + } + + /// A typed null of each kind of type the value model holds: a plain + /// int and float, and the three logical types, a timestamp of another + /// unit than the model's among them. + fn typed_nulls_in_the_model() -> Vec { + vec![ + fixed(None, Width::I64), + fixed(None, Width::F32), + fixed(Some(Logical::Date), Width::I32), + fixed(Some(Logical::Decimal { scale: 2 }), Width::I128), + fixed(Some(Logical::Timestamp(TimeUnit::Micros)), Width::I64), + fixed(Some(Logical::Timestamp(TimeUnit::Nanos)), Width::I128), + ] + } + + /// A uuid has a typed null, and no place in the value model. + fn uuid_null() -> FixedType { + fixed(Some(Logical::Uuid), Width::Bytes16) + } + + /// The frame a host sends for a typed null: the leaf alone. + fn typed_null_frame(ty: FixedType) -> Vec { + let mut out = Vec::new(); + vitaminc_aead::leaf::write_typed_null(ty, &mut out); + out + } + + /// A typed null of a type in the model is a null in a frame: written, + /// read from a host's bytes, or opened. Its padding belongs to a sealed + /// leaf, not to a frame, and a null has no kind. So a host's typed null + /// is not padded by this path. + #[test] + fn a_typed_null_in_the_model_is_a_null_in_its_frame() { + let null = frame_of(&Tree::Null); + for ty in typed_nulls_in_the_model() { + let written = ValueFrame::of(TypedNull(ty)).expect("in the model"); + assert_eq!(written.risky_ref(), null.risky_ref(), "{ty:?} written"); + let bytes = typed_null_frame(ty); + assert!(ValueFrame::check(&bytes).is_ok(), "{ty:?} checks"); + let read = ValueFrame::from_bytes(&bytes).expect("reads"); + assert_eq!(read.risky_ref(), null.risky_ref(), "{ty:?} read"); + let opened = TypedNull(ty).visit(Opening).expect("opens"); + assert_eq!(opened.risky_ref(), null.risky_ref(), "{ty:?} opened"); + assert_eq!(read.kind(), None, "{ty:?} has no kind"); + } + } + + /// A typed null of a type outside the model is refused wherever a + /// value of that type is. + #[test] + fn a_typed_null_outside_the_model_is_refused() { + let uuid = uuid_null(); + assert!(matches!( + ValueFrame::of(TypedNull(uuid)), + Err(DecodeError::Expected(EXPECTED)) + )); + let bytes = typed_null_frame(uuid); + for refused in [ + ValueFrame::check(&bytes).map(drop), + ValueFrame::from_bytes(&bytes).map(drop), + ] { + assert!( + matches!( + refused, + Err(FromFrameError::Value(DecodeError::Expected(EXPECTED))) + ), + "{refused:?}" + ); + } + assert!(matches!( + TypedNull(uuid).visit(Opening), + Err(DecodeError::Expected(EXPECTED)) + )); + } + + /// A host's frame of a typed null inside a passthrough. + fn hidden_typed_null_frame(ty: FixedType) -> Vec { + let mut out = vec![vitaminc_aead::frame::PASSTHROUGH]; + out.extend(typed_null_frame(ty)); + out + } + + /// A passthrough holds a typed null to the same rules: one in the model + /// is a null, written or read from a host's bytes, and a uuid's is + /// refused. + #[test] + fn a_typed_null_in_a_passthrough_is_held_to_the_model() { + let null = frame_of(&Tree::Passthrough(Box::new(Tree::Null))); + for ty in typed_nulls_in_the_model() { + let written = ValueFrame::of(Hidden(TypedNull(ty))).expect("in the model"); + assert_eq!(written.risky_ref(), null.risky_ref(), "{ty:?} written"); + let bytes = hidden_typed_null_frame(ty); + assert!(ValueFrame::check(&bytes).is_ok(), "{ty:?} checks"); + let read = ValueFrame::from_bytes(&bytes).expect("reads"); + assert_eq!(read.risky_ref(), null.risky_ref(), "{ty:?} read"); + } + assert!(matches!( + ValueFrame::of(Hidden(TypedNull(uuid_null()))), + Err(DecodeError::Expected(EXPECTED)) + )); + let bytes = hidden_typed_null_frame(uuid_null()); + for refused in [ + ValueFrame::check(&bytes).map(drop), + ValueFrame::from_bytes(&bytes).map(drop), + ] { + assert!( + matches!( + refused, + Err(FromFrameError::Value(DecodeError::Expected(EXPECTED))) + ), + "{refused:?}" + ); + } + } + + /// A record source that is a typed null, or holds one as a batch + /// element, is a row that is not a map, as a null is. + #[test] + fn a_typed_null_record_source_is_no_row() { + let ty = fixed(Some(Logical::Date), Width::I32); + let one = typed_null_frame(ty); + let one = Frame::parse(&one).expect("a frame"); + assert!(matches!(split_rows(one), Ok(SourceRows::One(None)))); + let mut batch = vec![vitaminc_aead::frame::ARRAY, 2, 0, 0, 0]; + batch.extend(typed_null_frame(ty)); + batch.extend(typed_null_frame(ty)); + let batch = Frame::parse(&batch).expect("a frame"); + assert!(matches!( + split_rows(batch), + Ok(SourceRows::Batch(rows)) if rows.len() == 2 && rows.iter().all(Option::is_none) + )); + } + /// A value's frame is the frame vitaminc writes for it, byte for byte, /// and reads back as the value. #[test] diff --git a/packages/stack-encrypt/src/lib.rs b/packages/stack-encrypt/src/lib.rs index 8d523019a..761c650f8 100644 --- a/packages/stack-encrypt/src/lib.rs +++ b/packages/stack-encrypt/src/lib.rs @@ -311,8 +311,8 @@ pub use target::{ // `IntoAad` and `IntoPrfContext` are vitaminc's blankets over it, so both // derivations see the same bytes. pub use vitaminc_aead::{ - CipherText, Context, ContextPiece, ContextTag, Decrypt, Encrypt, IntoAad, IntoContext, Node, - PassthroughFrame, Unspecified, + CipherText, Context, ContextPiece, ContextTag, DecodeError, Decrypt, Encrypt, IntoAad, + IntoContext, Node, PassthroughFrame, Unspecified, }; // The vitaminc 0.4 names, deprecated there; re-exported for one transition so // a caller that spelled them keeps compiling with a warning. @@ -331,3 +331,7 @@ pub use vitaminc_prf::PrfContext; // checked once); `MaybeEmpty` is what a context type of your own implements // to be wrapped. `#[derive(EncryptFrom)]` names these through this crate. pub use vitaminc_protected::{nonempty, nonempty_bytes, EmptyError, MaybeEmpty, NonEmpty}; + +// And the wrapper plaintext comes back in (`ValueFrame::into_inner`, a +// decrypted `Protected`), with the trait that reads it. +pub use vitaminc_protected::{Controlled, Protected}; diff --git a/packages/stack-encrypt/src/op/mod.rs b/packages/stack-encrypt/src/op/mod.rs index 8e849f80a..0ec303432 100644 --- a/packages/stack-encrypt/src/op/mod.rs +++ b/packages/stack-encrypt/src/op/mod.rs @@ -343,7 +343,7 @@ impl Input for (S, S) { /// [`Between`]) are answered over: the integers of 16 bits and wider, the /// floats (`f32` and `f64`) and text (`String`). Not `u8` or `i8`, which /// have no order term ([`Orderable`] says why), as `bool` has none. Each is -/// encoded as its [`Orderable`] target and its terms order as cllw-ore +/// encoded as its [`Orderable`] target and its terms order as clww-ore /// orders that encoding: integers as numbers; floats as Postgres's `float8` /// does, `-0.0` tied with `0.0` and every NaN one value above `+Infinity`, /// an `f32` as the `f64` it widens to; text by the system ADR-0002's fold, diff --git a/packages/stack-encrypt/src/sem/mod.rs b/packages/stack-encrypt/src/sem/mod.rs index 8910dcda2..70f5e70af 100644 --- a/packages/stack-encrypt/src/sem/mod.rs +++ b/packages/stack-encrypt/src/sem/mod.rs @@ -135,13 +135,13 @@ use std::marker::PhantomData; // Re-exported because they appear in this module's public signatures // ([`KeysetCipher::ore_term`], [`OreTerm::inner`], ...): a caller can name -// the ciphertext types without depending on `cllw-ore` directly. -use cllw_ore::vitaminc::{Ope, Ore}; -pub use cllw_ore::{OpeCllw8VariableV1, OreCllw8VariableV1}; +// the ciphertext types without depending on `clww-ore` directly. +use clww_ore::{ClwwOpe, ClwwOre}; +pub use clww_ore::{OpeClww8VariableV1, OreClww8VariableV1}; use vitaminc_aead::Encrypt; use vitaminc_hmac::HmacSha256Prf; -use vitaminc_normalize::{terms, NormalizeError, Normalized}; -use vitaminc_ore::{OrderColumn, OrderEncrypt, OrderError, OrderKeyInit, OrderScheme, OrderTarget}; +use vitaminc_normalize::{domain, terms, NormalizeError, Normalized}; +use vitaminc_ore::{OrderEncrypt, OrderError, OrderKeyInit, OrderScheme, OrderTarget}; use vitaminc_prf::{ BlockVisitor, Context, IntoPrfContext, MapAccess, PrfError, PrfValue, PrfVisitor, PrfVisitorError, SeqAccess, @@ -174,9 +174,9 @@ const EQUALITY_DOMAIN: &[u8] = b"stack-encrypt/sem/equality/v2"; const MATCH_DOMAIN: &[u8] = b"stack-encrypt/sem/match/v2"; /// PAE domain for ORE key derivation. /// -/// `v2`: the key keys cllw-ore's vitaminc ORE scheme, which encrypts the +/// `v2`: the key keys clww-ore's vitaminc ORE scheme, which encrypts the /// value's `vitaminc-ore` order encoding at its [`Orderable`] target, where -/// `v1` keyed cllw-ore's own per-type encryption. +/// `v1` keyed clww-ore's own per-type encryption. const ORE_KEY_DOMAIN: &[u8] = b"stack-encrypt/sem/ore-key/v2"; /// PAE domain for OPE key derivation (distinct from ORE: OPE ciphertexts are /// encrypt-only, so the two schemes must never share a key). `v2` as for @@ -200,18 +200,18 @@ pub enum TermError { #[error("PRF failed")] #[diagnostic(code(stack_encrypt::prf_failed))] Prf(#[source] Box), - /// CLLW ORE/OPE encryption failed. (`cllw_ore::Error` is deliberately + /// CLLW ORE/OPE encryption failed. (`clww_ore::Error` is deliberately /// contentless, so its message is fixed text.) #[error("ORE/OPE encryption failed: {0}")] #[diagnostic(code(stack_encrypt::ore_failed))] - Ore(#[from] cllw_ore::Error), - /// Block ORE ([`OreBlockTerm`]) orders text and bytes of at most 1023 - /// bytes, counted after the order encoding (text folded): the chained - /// scheme's 1024-byte ceiling, less the one marker byte it puts in - /// front of a variable-width value. The ceiling bounds what one value - /// costs: a term of 1023 bytes is already about 34 KB. + Ore(#[from] clww_ore::Error), + /// Block ORE ([`OreBlockTerm`]) orders text whose fold is at most 1023 + /// bytes, and bytes of at most 1023: the chained engine's 1024-byte + /// ceiling, less the one marker byte `vitaminc-ore` puts in front of a + /// variable-width value. The ceiling bounds what one value costs: a term + /// of 1023 bytes is already about 34 KB. #[error( - "the value is too long for a block ORE term: its order encoding is longer than 1023 bytes" + "the value is too long for a block ORE term: it is longer than 1023 bytes, text counted by its fold" )] #[diagnostic( code(stack_encrypt::ore_block_too_long), @@ -341,7 +341,7 @@ pub enum TermBytesError { filter_size: u32, }, /// The buffer's length is not one this CLLW ciphertext shape can have. - /// (The length is all there is to report: `cllw_ore::Error` is + /// (The length is all there is to report: `clww_ore::Error` is /// deliberately contentless, so its message would say strictly less.) #[error("{0} bytes do not fit this CLLW ciphertext shape")] #[diagnostic(code(stack_encrypt::cllw_ciphertext_length))] @@ -505,9 +505,16 @@ pub(crate) fn normalized(value: T) -> Result })?; match (terms.pop(), terms.is_empty()) { // One term, and at the root: the value is that scalar. A container - // with one indexable scalar inside is not a scalar, and a null or a - // boolean produces no term at all. - (Some(term), true) if term.path.steps().is_empty() => Ok(term.normalized), + // with one indexable scalar inside is not a scalar, and a boolean + // produces no term at all. A null has one under `vitaminc-normalize` + // 0.8, and it is dropped here: an absent value keeps a SQL `NULL` + // in its equality column until a null's index terms are decided + // (#1298). + (Some(term), true) + if term.path.steps().is_empty() && term.normalized.domain != domain::NULL => + { + Ok(term.normalized) + } _ => Err(TermError::NoEqualityTerm), } } @@ -1137,7 +1144,7 @@ where /// A plaintext type an order term ([`OreTerm`], [`OpeTerm`]) is derived /// over, and the `vitaminc-ore` order target its values are encoded as. /// This crate is the layer above the order schemes: it names each type's -/// target, and cllw-ore encodes the value as that target and encrypts it. +/// target, and clww-ore encodes the value as that target and encrypts it. /// The encoding (integer width, the canonical float, text's fold) is the /// scheme's, through `vitaminc-ore`, and never this crate's. The value goes /// to the scheme as a `vitaminc-aead` [`Encrypt`] source, by reference, so @@ -1161,9 +1168,8 @@ where /// one of 256 ranks, which a few known rows resolve to the values. So /// `OreTerm`, `OreTerm` and `OreTerm` do not compile (nor /// the `OpeTerm`s), as the dynamic path refuses the same scalars -/// (`dynamic::admits`); each keeps its equality term. `vitaminc-ore` still -/// offers the one-byte targets; their removal is tracked at -/// . +/// (`dynamic::admits`); each keeps its equality term. `vitaminc-ore` has +/// no one-byte target either, since 0.7. /// /// ```compile_fail /// use stack_encrypt::sem::OreTerm; @@ -1192,18 +1198,18 @@ pub trait Orderable: sealed::Sealed + Zeroize + Send + 'static { } mod sealed { - use vitaminc_ore::{OrderColumn, OrderError, OrderScheme}; + use vitaminc_ore::{OrderError, OrderScheme, OrderSpace, OrderTarget, Supports}; - /// Hands `&self` to the column as the `vitaminc-aead` `Encrypt` source + /// Hands `&self` to the space as the `vitaminc-aead` `Encrypt` source /// it is (`&String`, `&i32`, ...), so the owner keeps the one copy and /// wipes it. Not public, and one body for every type: it is here, and /// not a `&Self: Encrypt` bound on `Orderable`, because such a bound is /// not implied at the trait's use sites and would have to be repeated on /// each. pub trait Sealed { - fn encrypt_in( + fn encrypt_in>( &self, - column: &OrderColumn<'_, S>, + space: &OrderSpace<'_, S>, ) -> Result>; } } @@ -1211,11 +1217,11 @@ mod sealed { macro_rules! orderable { ($($ty:ty => $target:ident),* $(,)?) => {$( impl sealed::Sealed for $ty { - fn encrypt_in( + fn encrypt_in>( &self, - column: &OrderColumn<'_, S>, + space: &vitaminc_ore::OrderSpace<'_, S>, ) -> Result> { - column.encrypt(self) + space.encrypt_checked(self).map(vitaminc_ore::OrderTerm::into_raw) } } impl Orderable for $ty { @@ -1230,33 +1236,33 @@ orderable!( String => Text, Vec => Bytes, ); -/// Why cllw-ore produced no order term, as a [`TermError`]: the value's -/// encoding refused it, or the scheme failed. `cllw_ore::Error` carries +/// Why clww-ore produced no order term, as a [`TermError`]: the value's +/// encoding refused it, or the scheme failed. `clww_ore::Error` carries /// nothing, so a scheme failure is that one value whichever way it /// arrives. A scalar of an [`Orderable`] type is never a container and /// never unsupported by a CLLW scheme, so those refusals cannot occur; /// they read as a scheme failure rather than a panic. -fn order_error(error: OrderError) -> TermError { +fn order_error(error: OrderError) -> TermError { match error { OrderError::Term(error) => TermError::Normalize(error), - _ => TermError::Ore(cllw_ore::Error), + _ => TermError::Ore(clww_ore::Error), } } /// An order-revealing (CLLW ORE) index term for a source value of type `T`: -/// cllw-ore's encryption of the value's `vitaminc-ore` order encoding at +/// clww-ore's encryption of the value's `vitaminc-ore` order encoding at /// `T`'s [`Orderable`] target. Comparisons order like the plaintexts, within /// one index. /// /// The type parameter is the *source* type: `OreTerm` in a record type /// declares "this field is the ORE term of a `u64`". Every source type's -/// term is the same ciphertext type, [`OreCllw8VariableV1`]. -pub struct OreTerm(OreCllw8VariableV1, PhantomData T>); +/// term is the same ciphertext type, [`OreClww8VariableV1`]. +pub struct OreTerm(OreClww8VariableV1, PhantomData T>); /// An order-preserving (CLLW OPE) index term for a source value of type `T` -/// (see [`OreTerm`]): [`OpeCllw8VariableV1`], which compares with plain +/// (see [`OreTerm`]): [`OpeClww8VariableV1`], which compares with plain /// lexicographic byte order. -pub struct OpeTerm(OpeCllw8VariableV1, PhantomData T>); +pub struct OpeTerm(OpeClww8VariableV1, PhantomData T>); /// Index terms are one-way: decryption passes over them. `Decryptable` and /// `DecryptField` say so, which is how a derived record finds its ciphertext @@ -1377,21 +1383,22 @@ macro_rules! term_wrapper { }; } -term_wrapper!(OreTerm, OreCllw8VariableV1); -term_wrapper!(OpeTerm, OpeCllw8VariableV1); +term_wrapper!(OreTerm, OreClww8VariableV1); +term_wrapper!(OpeTerm, OpeClww8VariableV1); /// A block ORE index term for a source value of type `T`: ore-rs's 6-bit /// block ORE encryption of the value's `vitaminc-ore` order encoding at /// `T`'s [`Orderable`] target, the scheme EQL v4's `_ord_ore` domains /// store (`ob`). Comparisons order like the plaintexts, within one index. /// -/// Which of ore-rs's two 6-bit schemes encrypts it is fixed by the target: +/// ore-rs's one scheme, `BlockOre`, routes the target to one of its two +/// 6-bit engines when the space is opened: /// -/// - **`Bit6BlockOre`** for a target of at most ten bytes: the integers to +/// - **`OreAes128Bit6`** for a target of at most ten bytes: the integers to /// 64 bits and floats (as the `f64` they widen to). Wire header /// `02 02`, then the block count; one block per six bits of the /// encoding, so an `i32` is six blocks and an `i64` eleven. -/// - **`ChainedBlockOre`** for text, bytes and the 128-bit integers. Wire +/// - **`OreAes128Bit6Chained`** for text, bytes and the 128-bit integers. Wire /// header `02 03`, the block count, then the padding policy. Text is /// padded with NUL bytes to a power of two of at least 16 bytes, so a /// term reveals its text's length bucket rather than its length; bytes @@ -1415,32 +1422,18 @@ term_wrapper!(OpeTerm, OpeCllw8VariableV1); /// ciphertext carries its deterministic left half, so anyone holding two /// stored terms learns their order and, for the chained scheme, the length /// of their common prefix in six-bit blocks. -pub struct OreBlockTerm(Vec, PhantomData T>); - -/// Which of ore-rs's 6-bit schemes encrypts a target's terms: the -/// fixed-width scheme for a target of at most ten bytes, the chained one -/// for the rest, text and bytes among them. -fn ore_block_is_bit6(target: OrderTarget) -> bool { - target.width().is_some_and(|width| width <= 10) -} +pub struct OreBlockTerm(ore_rs::Term, PhantomData T>); /// The order of two block ORE ciphertexts, by the comparator of the scheme /// their header names; `None` if either is not a well-formed ciphertext of /// that scheme, if they name different schemes, or (chained) if they were /// padded under different policies. /// -/// These are the comparators `Bit6BlockOre` and `ChainedBlockOre` compare -/// with. ore-rs's `bit2_w6` module is its 6-bit scheme; the legacy 8-bit -/// scheme (`BlockOre`, module `bit2`) is not used here. -fn ore_block_compare(a: &[u8], b: &[u8]) -> Option { - use ore_rs::scheme::bit2_w6::OreAes128Bit6ChaCha20; - use ore_rs::scheme::chained::OreAes128Bit6ChainedChaCha20; - use ore_rs::OreCipher; - match (a.get(..2)?, b.get(..2)?) { - ([0x02, 0x02], [0x02, 0x02]) => OreAes128Bit6ChaCha20::compare_raw_slices(a, b), - ([0x02, 0x03], [0x02, 0x03]) => OreAes128Bit6ChainedChaCha20::compare_raw_slices(a, b), - _ => None, - } +/// `BlockOre::compare` reads the header and compares with that engine's +/// comparator, `OreAes128Bit6` or `OreAes128Bit6Chained`. ore-rs's legacy +/// 8-bit engine (module `bit2`) is not used here. +fn ore_block_compare(a: &ore_rs::Term, b: &ore_rs::Term) -> Option { + ore_rs::BlockOre::compare(a, b) } impl OreBlockTerm { @@ -1451,27 +1444,28 @@ impl OreBlockTerm { /// caller asserts they were generated for this source type `T` and /// under the same context. pub fn from_bytes(bytes: &[u8]) -> Result { - if ore_block_compare(bytes, bytes).is_none() { + let term = ore_rs::Term::from_bytes(bytes.to_vec()); + if ore_block_compare(&term, &term).is_none() { return Err(TermBytesError::MalformedOreBlockCiphertext(bytes.len())); } - Ok(Self(bytes.to_vec(), PhantomData)) + Ok(Self(term, PhantomData)) } /// The frozen byte encoding: the serialised ore-rs ciphertext, header /// first, unframed. EQL v4 stores it hex-encoded as the one element of /// `ob`. pub fn as_bytes(&self) -> &[u8] { - &self.0 + self.0.as_bytes() } /// Owned copy of [`as_bytes`](Self::as_bytes). pub fn to_bytes(&self) -> Vec { - self.0.clone() + self.0.as_bytes().to_vec() } /// Unwrap into the serialised ciphertext. pub fn into_bytes(self) -> Vec { - self.0 + self.0.into_bytes() } /// The order of the two values, by the scheme's comparator. `None` @@ -1496,7 +1490,7 @@ impl TryFrom<&[u8]> for OreBlockTerm { /// The frozen byte encoding — the same bytes as the inherent `as_bytes`. impl AsRef<[u8]> for OreBlockTerm { fn as_ref(&self) -> &[u8] { - &self.0 + self.0.as_bytes() } } @@ -1504,7 +1498,7 @@ impl AsRef<[u8]> for OreBlockTerm { impl fmt::Debug for OreBlockTerm { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_struct("OreBlockTerm") - .field("len", &self.0.len()) + .field("len", &self.0.as_bytes().len()) .finish() } } @@ -1531,7 +1525,7 @@ impl PartialOrd for OreBlockTerm { } /// A [`PrfVisitor`] that carries the plaintext in and hands the CLLW ORE -/// ciphertext out. The PRF block keys cllw-ore's vitaminc ORE scheme +/// ciphertext out. The PRF block keys clww-ore's vitaminc ORE scheme /// *inside* `visit_block` and dies there: the block arrives by value, is /// copied into the scheme's key (wiped when the scheme drops) and wiped /// here, the value is encrypted, and only the ciphertext leaves. No key is @@ -1555,7 +1549,7 @@ impl PartialOrd for OreBlockTerm { /// /// The plaintext is held in a [`Zeroizing`], so it is wiped when the /// visitor drops: after `visit_block`, or unvisited if the PRF fails first. -/// `encrypt_in` reads it by reference and cllw-ore copies nothing out of it +/// `encrypt_in` reads it by reference and clww-ore copies nothing out of it /// unwiped, so that drop is the last place its bytes live. struct OreVisitor(Zeroizing); @@ -1564,13 +1558,13 @@ where T: Orderable, P: Send + 'static, { - type Value = Result; + type Value = Result; fn visit_block(self, mut block: [u8; 32]) -> Result { - let scheme = Ore::new(Protected::new(block)); + let scheme = ClwwOre::new(Protected::new(block)); block.zeroize(); - let column = scheme.column(T::TARGET, ()); - Ok(sealed::Sealed::encrypt_in(&*self.0, &column).map_err(order_error)) + let space = scheme.target(T::TARGET); + Ok(sealed::Sealed::encrypt_in(&*self.0, &space).map_err(order_error)) } } @@ -1583,20 +1577,20 @@ where T: Orderable, P: Send + 'static, { - type Value = Result; + type Value = Result; fn visit_block(self, mut block: [u8; 32]) -> Result { - let scheme = Ope::new(Protected::new(block)); + let scheme = ClwwOpe::new(Protected::new(block)); block.zeroize(); - let column = scheme.column(T::TARGET, ()); - Ok(sealed::Sealed::encrypt_in(&*self.0, &column).map_err(order_error)) + let space = scheme.target(T::TARGET); + Ok(sealed::Sealed::encrypt_in(&*self.0, &space).map_err(order_error)) } } /// The block ORE twin of [`OreVisitor`]: same key handling, under its own -/// domain, and the scheme chosen by the target ([`ore_block_is_bit6`]). -/// Both schemes are keyed from the one block; ore-rs derives each one's -/// ORE key from it under a label of its own. The plaintext is held in a +/// domain. ore-rs's `BlockOre` routes the space to its 6-bit or chained +/// engine by the target's width, and derives the one ORE key both use from +/// the block under a label of its own. The plaintext is held in a /// [`Zeroizing`], as [`OreVisitor`]'s is: ore-rs reads it by reference and /// works on scrubbed copies, so that drop is the last place its bytes live. struct OreBlockVisitor(Zeroizing); @@ -1606,21 +1600,12 @@ where T: Orderable, P: Send + 'static, { - type Value = Result, TermError>; + type Value = Result; fn visit_block(self, mut block: [u8; 32]) -> Result { - use ore_rs::vitaminc::{Bit6BlockOre, ChainedBlockOre}; - let key = Protected::new(block); + let scheme = ore_rs::BlockOre::new(Protected::new(block)); block.zeroize(); - let term = if ore_block_is_bit6(T::TARGET) { - let scheme = Bit6BlockOre::new(key); - sealed::Sealed::encrypt_in(&*self.0, &scheme.column(T::TARGET, ())) - .map(|term| term.as_ref().to_vec()) - } else { - let scheme = ChainedBlockOre::new(key); - sealed::Sealed::encrypt_in(&*self.0, &scheme.column(T::TARGET, ())) - .map(|term| term.as_ref().to_vec()) - }; + let term = sealed::Sealed::encrypt_in(&*self.0, &scheme.target(T::TARGET)); Ok(term.map_err(ore_block_error)) } } @@ -1628,9 +1613,8 @@ where /// Why ore-rs produced no block ORE term, as a [`TermError`]: the value's /// encoding refused it, the value is too long, text ends in NUL, or the /// scheme failed. ore-rs's errors name no part of the value. A target the -/// scheme does not take cannot occur ([`ore_block_is_bit6`] sends every -/// other target to the chained scheme, which takes them all), and reads as -/// a scheme failure rather than a panic. +/// scheme does not take cannot occur (`BlockOre` takes every target), and +/// reads as a scheme failure rather than a panic. fn ore_block_error(error: OrderError) -> TermError { use ore_rs::OreError; match error { @@ -1707,29 +1691,31 @@ fn ore_block( ) .into_result() .map_err(TermError::from_prf)? - .map(|bytes| OreBlockTerm(bytes, PhantomData)) + .map(|term| OreBlockTerm(term, PhantomData)) } -/// Whether block ORE takes `text` as order text: its fold (the order -/// encoding a [`OreBlockTerm`] encrypts) must exist, fit the chained -/// scheme's 1023 bytes, and not end in NUL. The refusals derivation makes, -/// stated without a key, so a binding can refuse a query at its boundary. +/// Whether block ORE takes `text` as order text: its order encoding (the +/// marker byte, then the fold, which a [`OreBlockTerm`] encrypts) must +/// exist, fit the chained scheme's 1024 bytes, and not end in NUL. These +/// are the refusals derivation makes, stated without a key, so a binding +/// can refuse a query at its boundary. #[cfg_attr(not(feature = "dynamic"), allow(dead_code))] pub(crate) fn ore_block_text(text: &str) -> Result<(), TermError> { - let folded = vitaminc_ore::text(text)?; - let folded = vitaminc_protected::Controlled::risky_ref(&folded); - if folded.len() > ORE_BLOCK_MAX_BYTES { + let encoded = vitaminc_ore::text(text)?; + let encoded = vitaminc_protected::Controlled::risky_ref(&encoded); + if encoded.len() > ORE_BLOCK_MAX_BYTES { return Err(TermError::OreBlockTooLong); } - if folded.last() == Some(&0) { + if encoded.last() == Some(&0) { return Err(TermError::OreBlockTrailingNul); } Ok(()) } /// The longest text or bytes order encoding block ORE takes: ore-rs's -/// chained ceiling (1024 bytes) less the marker byte it puts in front. -const ORE_BLOCK_MAX_BYTES: usize = ore_rs::scheme::chained::DEFAULT_MAX_STR_BYTES - 1; +/// chained ceiling, 1024 bytes, which counts the marker byte `vitaminc-ore` +/// puts in front of the fold, so the fold itself is at most 1023. +const ORE_BLOCK_MAX_BYTES: usize = ore_rs::scheme::chained::DEFAULT_MAX_STR_BYTES.get(); /// An ORE term of any [`Orderable`] source. Under the local HMAC /// backend, derived during the synchronous build — the returned [`Pending`] @@ -1953,7 +1939,7 @@ impl KeysetCipher<'_, K> { &self, value: T, descriptor: NonEmpty>, - ) -> Pending<'_, OreCllw8VariableV1, K> { + ) -> Pending<'_, OreClww8VariableV1, K> { let term = ore(self.prf(), value, descriptor.into_prf_context()).map(OreTerm::into_inner); Pending::ready(self, term.map_err(Error::from)) } @@ -1966,7 +1952,7 @@ impl KeysetCipher<'_, K> { &self, value: T, descriptor: NonEmpty>, - ) -> Pending<'_, OpeCllw8VariableV1, K> { + ) -> Pending<'_, OpeClww8VariableV1, K> { let term = ope(self.prf(), value, descriptor.into_prf_context()).map(OpeTerm::into_inner); Pending::ready(self, term.map_err(Error::from)) } diff --git a/packages/stack-encrypt/tests/fixtures/README.md b/packages/stack-encrypt/tests/fixtures/README.md index 6fb6ac18c..d75cc2be5 100644 --- a/packages/stack-encrypt/tests/fixtures/README.md +++ b/packages/stack-encrypt/tests/fixtures/README.md @@ -131,7 +131,7 @@ file changes only when a derivation does: regenerate it with form `QueryTerm::to_value` writes, the bytes in hex: one term, or for `between` the low bound's then the high's. An input is JSON, read as the field's declared type, so `40` queries the `uint32` field `age` and - `1.5` the `float64` field `score`, whose terms are cllw-ore's + `1.5` the `float64` field `score`, whose terms are clww-ore's encryption of the float's ADR-0002 order key. - **`verify`.** A page of decrypted values, null for an empty field, and the boolean `verify` answers for each, which is what the typed `MatchQuery` diff --git a/packages/stack-encrypt/tests/fixtures/query_operators.json b/packages/stack-encrypt/tests/fixtures/query_operators.json index d0630eba4..cb850311e 100644 --- a/packages/stack-encrypt/tests/fixtures/query_operators.json +++ b/packages/stack-encrypt/tests/fixtures/query_operators.json @@ -86,7 +86,7 @@ "fidelity": "exact", "index": "ore", "operator": "lt", - "term": "758821c792265d942f89fa1dad016fb71b326f756e62950367e5d12f636d8b78" + "term": "f18256adef15adefb7ed6dea76d0de5418257a7406b06cb9b73fbd5bd75a8d17" } }, { @@ -98,7 +98,7 @@ "fidelity": "exact", "index": "ore", "operator": "lte", - "term": "758821c792265d942f89fa1dad016fb71b326f756e62950367e5d12f636d8b78" + "term": "f18256adef15adefb7ed6dea76d0de5418257a7406b06cb9b73fbd5bd75a8d17" } }, { @@ -110,7 +110,7 @@ "fidelity": "exact", "index": "ore", "operator": "gt", - "term": "758821c792265d942f89fa1dad016fb71b326f756e62950367e5d060dbfcceb5" + "term": "f18256adef15adefb7ed6dea76d0de5418257a7406b06cb9b73fbcbb958af97f" } }, { @@ -122,7 +122,7 @@ "fidelity": "exact", "index": "ore", "operator": "gte", - "term": "758821c792265d942f89fa1dad016fb71b326f756e62950367e5d060dbfcceb5" + "term": "f18256adef15adefb7ed6dea76d0de5418257a7406b06cb9b73fbcbb958af97f" } }, { @@ -138,8 +138,8 @@ "index": "ore", "operator": "between", "term": [ - "758821c792265d942f89fa1dad016fb71b326f756e62950367e5d060dbfcceb5", - "758821c792265d942f89fa1dad016fb71b326f756e62950367e6377200eec06b" + "f18256adef15adefb7ed6dea76d0de5418257a7406b06cb9b73fbcbb958af97f", + "f18256adef15adefb7ed6dea76d0de5418257a7406b06cb9b7404de8dd94a9f9" ] } }, @@ -176,7 +176,7 @@ "fidelity": "exact", "index": "ore", "operator": "lt", - "term": "d86769e4203df9a878dfb084014ea9df2ac9e74b1cef394f5042a6a88e4b81ab7d678eb59f8d27089e5e988fe8130bf9ea2707ab35e341d60c19c9836360eb21" + "term": "9129fe70c2594324aa169a5a9b5a5cbb6069d6574e65017fd005c8bd524bc9d72b923c40c2ec4b3b0e7505ebe58dc929288e836aade49c2680591d17ca9c9989" } }, { @@ -192,8 +192,8 @@ "index": "ore", "operator": "between", "term": [ - "d73ffdebc829eff390b70c5e169f58bf4b2aa664817584cc01f5e114eb7d91d2b6fe729db0f85f0df93d0487a2888f0a1865ca8946912ec33493cb18c5abb183", - "d8688e0201b46fefe8147f16e4011433e428361b12b70e40fed58a526bcdad72208619a7f90e617d22ddda3df8de4ccc224672bc0ea650ad64e30fb253851039" + "90a140c66cc77328cd49e57126a8802c821b5a85713adc8aa79f5ceb311703b3cb788a110494d03fa232c37a2da71ba7f0c20c1f67265dd39b770131ff52ef69", + "912aa94b90269735f38220cfde3773a20658a7990105503ac2d01974a3fb247193566f5cca1bad36337511634befbf6068bd264336df7ea45bf3665bfbe0c124" ] } } diff --git a/packages/stack-encrypt/tests/fixtures/record_lowering.json b/packages/stack-encrypt/tests/fixtures/record_lowering.json index 45ec0cca3..ad2033a38 100644 --- a/packages/stack-encrypt/tests/fixtures/record_lowering.json +++ b/packages/stack-encrypt/tests/fixtures/record_lowering.json @@ -125,12 +125,12 @@ "records": { "lowering": { "age": { - "c": "01000000000000000000000000000000004d5626148f77c4c6d9da0ddbdf7663a2200021162641133485216f389886cbd7c6e9b25afa0f5f166f985b23384e81ffcfac02ec48f08e1f2c79b55251885601527a0226a754a797eaa77131f9c7f2d6157f2098", + "c": "01000000000000000000000000000000004d5626148f77c4c6d9da0ddbdf7663a2200021162641133485216f389886cbd7c6e9b25afa0f5f166f985b23384e81ffcfac02b8a4ba034bed62ff824a3fe900c54478386f337ae9d2c48fef5d0e3b8038b50a47", "eq": "cc854fd5c7e3f4bb28cb15cae47d866b65b7012c06df43b4b9a6c51adff4710a", - "ore": "758821c792265d942f89fa1dad016fb71b326f756e62950367e5d12f62824807" + "ore": "f18256adef15adefb7ed6dea76d0de5418257a7406b06cb9b73fbd5bd6b95899" }, "email": { - "c": "0100000000000000000000000000000000b2afa77357a61488146c0edaa0246f65200043956c4f4bba857028c28165dfce9c63d904b738bbb039b6e11c805112d4a1ee025de4969eb5509d9cb7d2ef0ea827c2b6bf09d7b73ff165ad68d6fe1136f254f9accc930118490a162a1f829b", + "c": "0100000000000000000000000000000000b2afa77357a61488146c0edaa0246f65200043956c4f4bba857028c28165dfce9c63d904b738bbb039b6e11c805112d4a1ee02d5caa00b343d83eb68dc193f7a8c078ecef211cd2761ed97b15579147bfc0937d2c9f59a5bbacd7ce72a5167", "eq": "0cf708c07acaaa169e84e4adf7081f0433d87760bd7e9c63bd7a58c000b8d33b", "match": "030005000900100012001a001c0027002a002e003000340042004b0068006d007100750083009200a800b200b400b700ba00c200c500dc00e500ea00f200f300f900fe00" }, @@ -138,17 +138,17 @@ "passthrough": 42 }, "notes": { - "c": "0100000000000000000000000000000000723f7a7f14b07197168aa13bc52010b3200072a73194b45af604cc6201b5a57554b05cc7ed6ad22b9102cbcb71bd90678496021b7a7da71f40bec0f7d93f6bb3a8f32da41d7eac589e1063c90e7d18e397a81b88d966861810b8" + "c": "0100000000000000000000000000000000723f7a7f14b07197168aa13bc52010b3200072a73194b45af604cc6201b5a57554b05cc7ed6ad22b9102cbcb71bd9067849602fd852f9aa4e30c6a3d583c8c5283ec1210b53c274c3e037cd13b0462c79694f2ca4153cd59d959" } }, "typed_chain": { "age": { - "c": "010000000000000000000000000000000092e427c5e176b60261add6ce80fd02df20008d231453c97fdec97a0b6559ac8f509129d20163f262d40ce5d77cf1ebe0cad50248c801def074dfd0d34b7f34a04479875a7df403a3b12bd8ca475d4f377a86394f", + "c": "010000000000000000000000000000000092e427c5e176b60261add6ce80fd02df20008d231453c97fdec97a0b6559ac8f509129d20163f262d40ce5d77cf1ebe0cad5022075c95245d04dd7b21c1130d28607d36857b296b75ee506a84df8ef2bd9b73336", "eq": "cc854fd5c7e3f4bb28cb15cae47d866b65b7012c06df43b4b9a6c51adff4710a", - "ore": "758821c792265d942f89fa1dad016fb71b326f756e62950367e5d12f62824807" + "ore": "f18256adef15adefb7ed6dea76d0de5418257a7406b06cb9b73fbd5bd6b95899" }, "email": { - "c": "0100000000000000000000000000000000cf92191950409f9fe82a2b11888ffc1d2000ca4d5bbafbff919af4d3a95c7cc046d632fd4c28785b238f4b6f7ea3aa08482902a278c63260694db784fbb3361b95717b08851fa7bf6cce35e45ac115dbaffb9f93dac5cd53939eae0cba0832", + "c": "0100000000000000000000000000000000cf92191950409f9fe82a2b11888ffc1d2000ca4d5bbafbff919af4d3a95c7cc046d632fd4c28785b238f4b6f7ea3aa08482902b82f3961528a67647fb28f394328c2025a2d170fb16ef83779b0478f1e2649c87be3c5953dfac5a9688244c8", "eq": "0cf708c07acaaa169e84e4adf7081f0433d87760bd7e9c63bd7a58c000b8d33b", "match": "030005000900100012001a001c0027002a002e003000340042004b0068006d007100750083009200a800b200b400b700ba00c200c500dc00e500ea00f200f300f900fe00" }, @@ -156,7 +156,7 @@ "passthrough": 42 }, "notes": { - "c": "0100000000000000000000000000000000562a41e032316ff2d1264a9e9f5c3b842000de33c8d1f2caaab8b90f691161a57eeb1328f7f1c9b5be76dec83e8a53765f1102bdeeaf5aa37fa829e7519021baaa76584778ece652b6b881054d4f5c9203662309001de93e044a" + "c": "0100000000000000000000000000000000562a41e032316ff2d1264a9e9f5c3b842000de33c8d1f2caaab8b90f691161a57eeb1328f7f1c9b5be76dec83e8a53765f1102ef67a5276edc137d864f7ddc443911539b36bc6b9209bcc1dc0a8f25dec298557c6ed356901642" } } } diff --git a/packages/stack-encrypt/tests/fixtures/stored_rows_v1.json b/packages/stack-encrypt/tests/fixtures/stored_rows_v1.json index 75c77df16..cb231e0aa 100644 --- a/packages/stack-encrypt/tests/fixtures/stored_rows_v1.json +++ b/packages/stack-encrypt/tests/fixtures/stored_rows_v1.json @@ -485,7 +485,7 @@ [ "ore", { - "passthrough": "0b280000008bb663d8b4c006682148c9277bc5e57d411fba769c6414c115d538247d2949371e0c5aad377dc8a7" + "passthrough": "0b280000009a8ad7f813cc32d1fb89fe1c14a45d57655c0e52d6c3677801a1c80abffcff0e2ce64d6622f740e0" } ] ] @@ -498,7 +498,7 @@ [ "ope", { - "passthrough": "0b290000000060d402259cb39497228b893f5e0a87a0c7800b2a0fa773b681dea30ac939d570cd945da2ec1f7c44" + "passthrough": "0b29000000000bbe8e366aaefdf2ba27bdef9176db2d23f7f50a22d6b39d0b5fa83a5e369f80f3af1d31cc294f62" } ] ] @@ -548,7 +548,7 @@ [ "ore", { - "passthrough": "0bc0000000e4596b725e0c386758533cd6e735152740b9af9bd6e96019ac18a724e079479d43caad7e83ce14f737ca246ae6ba5ad0c0a2e5f7f0a2101c1831bc6aee4ccc2a22292816e36cc8938536d59d689be229b0d0210e0354900ba200b04f93545a06098d2edb7531e590da3dc5cd393261d54f60574a127e198bfc752099b1cfd5f4fe44666963b4e5b3e0c8e7623c8eae478d05c0513e5554be89ca7f1248fd52e23e23974da8052807e49f4782d6d42e0d5690c37d1242ba62fdc4200434be1593" + "passthrough": "0bc00000000cdf4b4c993712153fe8007ccd5f4f3e495a9041d31bc68604f2b73aad04160d7924ce0cd737ca11ce3cb781c035b03a666e8f3972ed867fdd41a2b79eab6a9879e9e54ea22c0e2c25f6bd508e5d145d41d23470a4285bccfbaf2d48f024dd5888038175cd65324640f080b9c45bed2e95f08d9033707b88fb45b41014b7ec9196a05aa7ac3376b9d85b0577f8cac62e26d259dfa55d1a471c69ee454be8dc9007cdecae62f2b4995a353d6d7a36aceba19c2d1987309633cad0c39ea9c8c095" } ] ] @@ -561,7 +561,7 @@ [ "ope", { - "passthrough": "0bc100000000849552987a983ba140e5c8fa0eac802885238b8fcd80f3e55e95f286f24ba7b93c67dfc7501c82b3bad61452b7a8e3b1adbeb99526f990ea8f8e0570666ba91ce7be424ecd14712dd2f96518e26605f14440805a241dd14b28497fb3ed6cf0bfabab60848d2871bdb87377deae6a313c0f6485ce91f103c7f309044f8cf03a3a8aca48dce15500126d1dd2de74674f6e11fc02cf46075ef6c6f09d8b797ade427d3bbd5807e3e066dfee5a3eff31b6698c5a6e6640d70987838d373c39ce7df3" + "passthrough": "0bc100000000b68f3ecc27ba3c18dd2b9443ac9ef6738ee9f0a8cf0ac940da750e708206b2deece11785edc533afed8c3933402115be70afedb2e8c9a63c9b73dff7df85eca922db44e52832a73634b9bcc8bd25090695e540f3acf5902fd064fa246a3b868e126dd2b56e34898b9c22131e2d3e80cc5f2dcb066ba67ff3f1cb9a00e14d41c9930105ae716b1edb449b0891f08eabd6e0aac2ec58fe59067b1e619214f7355df280b5ff2b9f091a465a765805d31714cb25b3ddcc4c43f55166f0f2782d48b8" } ] ] @@ -586,7 +586,7 @@ [ "ore", { - "passthrough": "0b400000003a83168a330a190579e7a0dce23066fc5bf762b1b10a0fd4b5add6be7f76c09f027a39deaaf81c35050751ef258433a5e79bb0835ffa705b1660cf0439ae4813" + "passthrough": "0b40000000ae483a7f5defe9fd696a1ebd1d1a927e94f16542b2434eaacd81aa389bb5993f09c4a56fb21c9d6d2cb598cd11fea4ccd646dbb596543126f79840afd62bcdd5" } ] ] @@ -599,7 +599,7 @@ [ "ope", { - "passthrough": "0b41000000010713d30a44fad510839aa637489c19b56062ffb692d964261640079e31e321728559526c51454b6d827518b8b47c64f9875b6864e62edc62e328d0e0598f1f10" + "passthrough": "0b4100000000f7c004b44504216d9907bf9e1e72cab855bded9848a49430427b1b93c88b0400728c4d67a9a4455c66a37e0915fc2b49690481e6208534f01b6df0ec04eaf71a" } ] ] @@ -624,7 +624,7 @@ [ "ore", { - "passthrough": "0b40000000bdcc3110154be791c3148934d9a7b2bb1082581099dcd46dd44719e6db2b192cb455bec8ee6c2632e0e1b1b322fe419ba72a4c34aec7a543fd93e67fd553f763" + "passthrough": "0b40000000f0420be99f95a537de3161a6cee6c390c7d3ba87d8bd9af602e9a31135d914f3d9f3206d80f44d040631d6971f05975683fd01f783be096a2c9bb29d40c0ba6c" } ] ] @@ -637,7 +637,7 @@ [ "ope", { - "passthrough": "0b4100000000c8228ef43865b325619e4992b56db2acd73e6305a23db7b01c1087c865c6a921ff4b8439def81446aae4e1852ed4e38bbe194701b5d2924ac50c9407f3159a52" + "passthrough": "0b410000000152284d4a6f5a77d5c623651887ba617a05a6b5e9dda3224c244fcde2f6aa1c07261a406a66225484333e23559ab2c36a2f689f8757f484687efcf5932ff80c0b" } ] ] @@ -675,7 +675,7 @@ [ "ore", { - "passthrough": "0b80000000515b9aa9f37d24e2f041da7e424739cc232b81f85e6c6ef07829cea2434ff599f0d83ba6cad9cd71909d8b6d5bbe3bfcb61a234edac0b41ff728e98e9ab633f1d6ccecf4aa5ab288e74eaddd2b899c8952a025f7097117654c3d0eadd7278f5bd770689692b810f1c0de8d2f7ad9def60dc124d78f5360ebd2aee7a028aa4c0d" + "passthrough": "0b80000000d07b956b59e55e4fe46de19da96a9f46342bf2c8c5185632579fc09c35927f7de262f0c0dd2811add117fb73e752e4310c1012c9e1ce9d0263491bd43e78b3d8ac8f9130626327d49bcd341a061ac24d3fb540542b7527d5427b57cdd6038b125f7aaa23fb62d8ee34b91118a06262cc2a32cc102da823f0a3d49927bc04037e" } ] ] @@ -688,7 +688,7 @@ [ "ope", { - "passthrough": "0b81000000007f3e0dbb3cb4371fee47438dd52f3f96c5395a75a8c6f97500af1feae03fc587960db5137bc84733c3e26c6cece4572b5068ffbd237b7959edd8b1a7ca5d317ff1869f73b29e157eeb4a0e12cc20f148c2f0f9fd00c127fe6e392f047f0f4ae84d5f03c29340cce05cd83e9baa7b5e78d4e0933ab9c943ffe49d62d5e6ba8727" + "passthrough": "0b8100000000fcd75a25f22a0f976fb0691700c111679d9ae5807b7bdd69be6c5154437190b9f327efaeaf95b6f7279c3fc1a5f71fa4298984bddfcec1eeb3ce7f10bed6a459089d5de948fc9e236e4f179cdc5bebd22590ee097df0c1eb16de6acc85181f42e5c6d005b2ab1f97d2b8d5861804815b22b9d2da17ee7c428c6208ed12ac05b3" } ] ] @@ -713,7 +713,7 @@ [ "ore", { - "passthrough": "0b10000000be1fd669d8a2cae089e62262c8f163f8" + "passthrough": "0b1000000076beb2c335e8d902eceac35139e55eda" } ] ] @@ -726,7 +726,7 @@ [ "ope", { - "passthrough": "0b11000000003f039dde79c7dd4ccffd191d5544c2ed" + "passthrough": "0b11000000003abd4e8ece83ec95aafd466a98d30fa4" } ] ] @@ -751,7 +751,7 @@ [ "ore", { - "passthrough": "0b20000000f366ce2845fadc799d60dd73190baaa1e79444a558aeb2454490483c76cdfc01" + "passthrough": "0b20000000a3183396975476acc1d0f11df0d5de324f4feb8d9a5f8ed00d963732a9ef418f" } ] ] @@ -764,7 +764,7 @@ [ "ope", { - "passthrough": "0b2100000000c61f2fc35629dcad1b5b22bd86c54a908409b2921d7362d2fe21c2a93c604916" + "passthrough": "0b2100000000c0b07e08ab5a32002b85c4b5f6f7772c14f653452f186ea13c371815983a7a75" } ] ] @@ -789,7 +789,7 @@ [ "ore", { - "passthrough": "0b4000000076f1db359db6b05234937ef37330e9b839c9b5653d16602b7871b1277981065ade1de6ee1ce10dd832f0affcd3b92ddaf75e1db9c619ee8cea18cd89425113a4" + "passthrough": "0b40000000cdf3883765bac44a78dab78be97cac096c219645e64b4718a0efc8ec12740eca2523b7e68d14878b35d2f084845025d94eb5c033fe97f0be5fe410f755e6d29c" } ] ] @@ -802,7 +802,7 @@ [ "ope", { - "passthrough": "0b41000000006e4cb9aaf3e0ed8761ffd0b74ccf91aeabfccabc8f5fc8b4deb29d757dcaba7c063006eb92a5b572dc86349f270ab3e1d3f08bd4372d8660f37ea5725d7a159e" + "passthrough": "0b4100000000925deb04bf2246c26ca7fa3deac9a51bfe24b1d37730225d73dba7169aa6845c486aa397714c58e9954a39ca4bf6532be6b0af020b7f936b9a679856ea0ca7d5" } ] ] @@ -946,7 +946,7 @@ [ "ore", { - "passthrough": "0b800000008e3c2cd1cb101f207b6ff8e0c736294fd32c7c9d8a27532cb8629d31d923c9b04e43c711c3e6a7a25758e6a2e957743d407c29a0944421a3d9e259d0b180a019c008e9f339a6db877ba8245ea8f3964db0f4f866e8f19cc0d6351e772aebe54d2ab6fe33efd6f8a0655edc64f1d1c6263294bbb39e27fda896aa1c09273afa30" + "passthrough": "0b800000004b813a291f8e04f8567e18a4e2aaeef57902dde07827bf115844d18d36de06d172697e0c0163517e0b421e2730667039de012175f31b111e50f084c480b8ea8e3a3b0833e12e7a5488f9ec0d73b22ac23998aaf05e7644e55f6acff6d9d19ae8c1cad515177bc1448a7d05d2d3e51894107085b3f09976e8f306e8072f6efcef" } ] ] @@ -959,7 +959,7 @@ [ "ope", { - "passthrough": "0b8100000000dc8f1d8a4159d905191e10403e38ba67be0dd69bc3f15471400e72115d4224f61674727ab8bac56ad6e99f309ba95f8886fa085f81e5647f2aeb5a5d2142fa087fee560c7d8df14bf85699eb34236cd8b2e6fc83f2ed7b6dd17f05978ad09bdeb6ccf1efc1afb975ccd49fa52b00b844bee0341b115f03b8d427cfe9399320b8" + "passthrough": "0b8100000000a824e89c4282c329a4d96069f158cdbef67de3e449b01363b50f1ceb166703a2c58decef5c3a765c3b7508049feb63adff64b36b739cd22143f4eee6c8aa5f173c8075b94ea8644174106a29608bd60655df143b36c7a20012beddce41d7fbb8954ee66d4bcc42000456cbaa168b2ccb788bdb29714a31f74566999989506d15" } ] ] @@ -984,7 +984,7 @@ [ "ore", { - "passthrough": "0b10000000a082c2300d1f28ce56a8d1388100342a" + "passthrough": "0b1000000049cf67d1f40428bf49576be3e3df43ce" } ] ] @@ -997,7 +997,7 @@ [ "ope", { - "passthrough": "0b1100000000fd45295f100d24e193e7c3b4a3afe6a4" + "passthrough": "0b110000000149691c6a3367ee8478c871c9f4cf4c15" } ] ] @@ -1022,7 +1022,7 @@ [ "ore", { - "passthrough": "0b20000000c3d8d9e15a3c67b2e7b050406e424c86c4427ddc55cd7e94beccf06d4e1aa3af" + "passthrough": "0b20000000fb88f2e243b1334a797a06ebea79b15a820dc5ae1668344bfa58d758f880fd17" } ] ] @@ -1035,7 +1035,7 @@ [ "ope", { - "passthrough": "0b21000000013910babdb9df995bf6cd8b8c3809ff96c20ce7272170cbf4a2e6f192df48ae94" + "passthrough": "0b21000000014d0e72ec6d02fc43651247bd9ca84c5323bc1813a4c68bc69aa8d1acef496c71" } ] ] @@ -1060,7 +1060,7 @@ [ "ore", { - "passthrough": "0b4000000024581d4b396284a673cc04e73d565077e3f6a56e9c178e95fc41a8665e910c0a1ece9482a38b82beee4d17d8b82639cd68390dc14fc03900f57f47023ebcdb36" + "passthrough": "0b40000000da9451a858c81d33242f92cd4b71b93d35661645e793298ae127defe2648db050e0b9bb3509a018f84f4266bc0020f26813c76fc764953da64e734c40659ae9d" } ] ] @@ -1073,7 +1073,7 @@ [ "ope", { - "passthrough": "0b4100000000c65d9da62cb7b3a4841db8ff0fa6304ab8117e40683d26f02557379f122be04b674dafce8618496ee2fe39aa3b5d3ad12f1d8c2230d100078aa11defc16e0867" + "passthrough": "0b410000000137677c48013326e34edee99462e9927217b3b2c63029db38ce33034fd6ed28e9687f1726a49a2a046638f88b9998c62a689a5334b5d198a72a6523aa1053522b" } ] ] @@ -1235,7 +1235,7 @@ [ "ore", { - "passthrough": "0b200000003b66bacffee6b5c0633c4623c3845f7344545bb4c7d02ecaa5bcd9b5f87eca41" + "passthrough": "0b20000000beca9415e2d54831e6daf42acef5bed3bdcd8b5b669061bccab1491a70954fd3" } ] ] @@ -1334,7 +1334,7 @@ [ "ore", { - "passthrough": "0b2000000031a055cf0ff7e82d73fc9711b26536ea18f8ea4be2328cd0c3b17c94b3d39c9d" + "passthrough": "0b200000003c0639c42b4bc6198d8c0f6d0c1020cc257af118db43564bcefd87d3440ea180" } ] ] @@ -1421,7 +1421,7 @@ [ "ore", { - "passthrough": "0b2000000056a202f641a9a81c5f9c179ae587fa6fb846342ba97fe605bc3bb4d55068e23f" + "passthrough": "0b20000000e35fc7559e7ae9856a8e6438987a9fc176e5b14000eef0bbdca5332b138689e7" } ] ] @@ -1517,7 +1517,7 @@ [ "ore", { - "passthrough": "0b20000000758821c792265d942f89fa1dad016fb71b326f756e62950367e5d060dcbc3be9" + "passthrough": "0b20000000f18256adef15adefb7ed6dea76d0de5418257a7406b06cb9b73fbcbb967139c2" } ] ] @@ -1571,7 +1571,7 @@ [ "ore", { - "passthrough": "0b20000000758821c792265d942f89fa1dad016fb71b326f756e62950367e5d130a8115eff" + "passthrough": "0b20000000f18256adef15adefb7ed6dea76d0de5418257a7406b06cb9b73fbd5c5b36f775" } ] ] diff --git a/packages/stack-encrypt/tests/fixtures/value_kinds.json b/packages/stack-encrypt/tests/fixtures/value_kinds.json index fc98e70b6..77459ed77 100644 --- a/packages/stack-encrypt/tests/fixtures/value_kinds.json +++ b/packages/stack-encrypt/tests/fixtures/value_kinds.json @@ -128,43 +128,43 @@ ], "record": { "amount": { - "c": "01000000000000000000000000000000007a4428d606d70760a6ab09137b7998952000aa5c98df7b5db708dec28195dbfa196953ce941a9404e7c315e14856139917c702fa91de3a39604b362861966bda65a4e16e141bc7046d59627ff4f9e9c24114cca0afcf08713a2d350e1c06ebf6", + "c": "01000000000000000000000000000000007a4428d606d70760a6ab09137b7998952000aa5c98df7b5db708dec28195dbfa196953ce941a9404e7c315e14856139917c70272c8dd6e66ca1aebf1bda57062842a1f595b44e43f77add307090df793ac67fef91ff48822172d43744a613b6e", "eq": "93a9395ae5d9581921a3fc2cdd9e0f3cc731d37e8f39f516f3dc3e3a6f0e8514" }, "at": { - "c": "01000000000000000000000000000000003df5051c44f189118ff062fc589189362000c144eccd9336ad2098131bc1ccebd36780eafd132f5d9a7900964b441fbedd240238762eca5b766e057a875482b286a420c4df7d043545869c76ca56f829638f723e412b58915cb8a63e", + "c": "01000000000000000000000000000000003df5051c44f189118ff062fc589189362000c144eccd9336ad2098131bc1ccebd36780eafd132f5d9a7900964b441fbedd2402318d67a00b552d3ffb67264c13652700bc974d4e36962448bc944fed7fea3eb87bfd0297be8cc51e37", "eq": "448bc4271a535ec475e50404c800746fb71cbac46567396bc0873546e5498f4a" }, "date": { - "c": "010000000000000000000000000000000081a52593eddb4ccba009332c41f7173d200048bbb91aa1c0c890d54de6fcd6b404e91d6a8272390ab807c78820543d49ef86025f781af6120f255debe98eaf4c53b4d5915d3702e8b97562b5e3f10ee2fea810ff", + "c": "010000000000000000000000000000000081a52593eddb4ccba009332c41f7173d200048bbb91aa1c0c890d54de6fcd6b404e91d6a8272390ab807c78820543d49ef8602115918d12a10db2ff74868d6a6c52dd8350aacfaaaf3138680210728b2670388b0", "eq": "03226ad4425267b31f8316c513d7155cfc2fd33bbf8992d14ea26cfc64311481" }, "i128": { - "c": "0100000000000000000000000000000000f5bdd6ce34bc69330093fa760c6f6d8120001a9f80b14abd281d94e5139ba66a8744314abdde415fa182d4ad961c4dbf1dc002a391e960daff92e0968960819cd41c2f8ef67887f8395e3d0aae1e968d74bf8af5c7e092e7461e332b019c8eed", + "c": "0100000000000000000000000000000000f5bdd6ce34bc69330093fa760c6f6d8120001a9f80b14abd281d94e5139ba66a8744314abdde415fa182d4ad961c4dbf1dc002a6675c402fefbff35039c68dfad19349a5cb056b9b6ed569bcad642a115f9424d878fc8276ee13f512c712ba05", "eq": "19fb32f017fe269cb2703fe732acd8c1673e49174e5492ea8c372c487d08ce2f", - "ore": "eed82f673c37aac97130e682bffa8fedda8f50a6adbaaf22b995fe84050870ce82de1dc185d9280cab61088b382a6d297ace288376e87b222ba9580bc9235643c35333131a01da66205fc770bbfa5fd84171034d75c4952231c1652cd0b8545c80a55907f2813cf4330528bca3cca7efce20ebe69eec29ec5bf6439c236d69c8" + "ore": "3f76e777c16d34f916957007b50af4aa1d75d991bdc6b341f2115b6293fdff630c0529b8cea701a9a8d42b1fd7eafb142db7b1145ba19b244bbf121fb43af47f8ef86f8a99384afb3412e97c69bbc0c76ea8b10a2d505a5720ba38591fada1a4decbec19b7932ed5275d317d58974eea640237f94cfba032715f97c641dd6a7a" }, "i16": { - "c": "0100000000000000000000000000000000b1739f40d4486c2af05aac240fae06e72000a9313873aaecad5b7a40ed810a0dd870304d8fb8d4ea88949606dce6384dbb660293761ddd2d762e68068488cec8f049f106623550927d770552f9a2c3610508", + "c": "0100000000000000000000000000000000b1739f40d4486c2af05aac240fae06e72000a9313873aaecad5b7a40ed810a0dd870304d8fb8d4ea88949606dce6384dbb66028e2aacdd7526cd36c4219d479ac8e026f9a9d782cb3e14b1140d25067f5474", "eq": "b902e228c35b328eef12f0b8df397d48ee63b81e944e3dfb0855b6006426e012", - "ore": "83bcefa8b71d264f84ac4f346c9427ae" + "ore": "2db94b40090bf95b461165503e3d7890" }, "i8": { - "c": "01000000000000000000000000000000005151a6cfdd1a51bf3a1ea0e85de41428200008a7fb000a5365b240cb064def02dedb57434897a756ae6216259ae26419f45d02da466dd320e4afd377fc28edda0282feb6be40f896dbd6334bcb881925d0", + "c": "01000000000000000000000000000000005151a6cfdd1a51bf3a1ea0e85de41428200008a7fb000a5365b240cb064def02dedb57434897a756ae6216259ae26419f45d023c5ec5b04c5ac5c332af086f71feecb4b960635f505b6573fb39307bfa9a", "eq": "15e37adf2fa39067953df8988ef98fb5ca354599495b23230133d525e62e6768" }, "u128": { - "c": "010000000000000000000000000000000095b0c11aba5068ed6e8b76bcf85967a92000b74f8acb3cdefa94b9fdea95725157aad875dfdb1f567c293638e84dc7872c42022d2c6fa96ddcaa15ec1b96f7e23807d47595491c0bb036791048ec4eb99fe41a7c7958b707ed9c284896af5e82", + "c": "010000000000000000000000000000000095b0c11aba5068ed6e8b76bcf85967a92000b74f8acb3cdefa94b9fdea95725157aad875dfdb1f567c293638e84dc7872c4202ac3b26bb1a24bb6ddc55fcb32275406299464bc0278d8daa3a929203abf1972a4c87cecfc8fded5ef80e22eca9", "eq": "761458346368c5f42c19a00ec9d8849021dfb28d6d6768c75d4290fef986bb9f", - "ope": "00deb76379b2d69b53e21b4468419eec6f1fd3a6338232d3f8acfb94779c95e9751d084cc759f92744b2389e1fc60b93ab3566bf061a00a9dd103329c5ad003628129935ab04d1b586ec506e986f4529f2b33f339b22aa8355971814735f9ebd6d48965546739e193cdfd5b0c6d0f550049f552698b39bbea76fc03527d775a28e" + "ope": "00ba8bbfe22d11c1fe973af9e0f10a54cabca5a5f822ac01283178975a61f6e899ce926cc10058fced231ce768887509a78b43ab08ae170b2becd7856de2e3df69c133357c64fd23535d2098a6b741fbd2d7c30b2de27c3f4bccb97064684b2aa441eee9c93aa3e653490fa907d8e0dd5691867382c13fdfad3628bab0301a2e1d" }, "u16": { - "c": "0100000000000000000000000000000000c40545f440c7f3e3f81f3fa4bbdc13152000c1aa04095f495b7cf8e1022d2e73a5d653616c157249914dc212e5c2c9eed16402aed0aa5806118a7ab9278e6e621f621b8daf665c3f97cc112a6a97c8d234e1", + "c": "0100000000000000000000000000000000c40545f440c7f3e3f81f3fa4bbdc13152000c1aa04095f495b7cf8e1022d2e73a5d653616c157249914dc212e5c2c9eed1640249c170478f583195b0f455fd8f532b321b26548e98adbbcb7fd073d28caf9d", "eq": "f9ec131d5dcf5739ac3a928108e1b50fc51e9f87bcd92f9e6e052b19b5f6b86d", - "ope": "008dd5395c0f5a63bc69d2c01d8ea32e3a" + "ope": "009011bc88ee527a131504f2f495ed03d7" }, "u8": { - "c": "0100000000000000000000000000000000bf3b588776242c390761ddd7097e0ae22000fd2f9eb1bb2712deff3805ba2af81cb31ea5c1fc8ef8e0f058c256e3b170e5d302af00af685f24c50ef4e7df040a92e4aa5d5093567923e759dce513e57116", + "c": "0100000000000000000000000000000000bf3b588776242c390761ddd7097e0ae22000fd2f9eb1bb2712deff3805ba2af81cb31ea5c1fc8ef8e0f058c256e3b170e5d302d3c582ab3b26f8fe22b9de6d9fac079b9a91f1cb5a8f67d654675e5cbb3c", "eq": "ce2278b04c84191451e85ffcbe67f1e7c8585f86583cdbcef68d2dd466fa7b0e" } }, diff --git a/packages/stack-encrypt/tests/frozen_bytes.rs b/packages/stack-encrypt/tests/frozen_bytes.rs index 12c629c1e..d5f63e7f6 100644 --- a/packages/stack-encrypt/tests/frozen_bytes.rs +++ b/packages/stack-encrypt/tests/frozen_bytes.rs @@ -470,7 +470,7 @@ async fn ore_term_encoding_is_the_raw_cllw_bytes() { // differ (see the `sem` module docs). assert_eq!( hex(term.as_bytes()), - "b8291f846d8028ad4e3a67ef95e541ca3c6d1a2b145f49af3135876ae75c5d7b" + "1ba4d59ccb15d505519ad854229ec0c106644fa8b8944ec54c68a1f324499d82" ); assert_eq!(term.to_bytes(), term.as_bytes()); assert_eq!(term.as_ref(), term.as_bytes()); @@ -496,7 +496,7 @@ async fn ope_term_encoding_is_the_raw_cllw_bytes() { assert_eq!( hex(term.as_bytes()), - "00d7a25b801c909f3cb9d177315ba4da7802b9e62eba8c07aab2ad9d64e1a0cfa7" + "00a77ed973ff1af2e5d5e3779471df246d17a515f0131eb87e35e02e7a80aa5292" ); assert_eq!( OpeTerm::::from_bytes(term.as_bytes()).expect("decode ope term"), @@ -510,7 +510,7 @@ async fn ope_term_encoding_is_the_raw_cllw_bytes() { #[test] fn ore_term_from_bytes_rejects_wrong_length() { - // Every order term is cllw-ore's variable-length ciphertext: ORE is + // Every order term is clww-ore's variable-length ciphertext: ORE is // one byte per plaintext bit (a multiple of 8, a u32's 32 here), OPE // that plus a leading carry byte. The length checks are structural: // the type parameter names the source, and nothing in the bytes does. @@ -530,9 +530,9 @@ fn ore_term_from_bytes_rejects_wrong_length() { #[tokio::test] async fn variable_length_ore_and_ope_terms_decode() { - // Text is encoded behind cllw-ore's one marker byte, so `alice` is six + // Text is encoded behind vitaminc-ore's one marker byte, so `alice` is six // plaintext bytes: 48 ORE bytes, and 49 for OPE with its leading carry - // byte. The decode path is the length-validating TryFrom in cllw-ore. + // byte. The decode path is the length-validating TryFrom in clww-ore. let cipher = cipher().await; let keyset = cipher.default_keyset(); let ore: OreTerm = "alice" diff --git a/packages/stack-encrypt/tests/ore_block.rs b/packages/stack-encrypt/tests/ore_block.rs index 2168cf10c..56bd88d81 100644 --- a/packages/stack-encrypt/tests/ore_block.rs +++ b/packages/stack-encrypt/tests/ore_block.rs @@ -245,6 +245,24 @@ async fn bytes_order_as_bytes() { assert_sorted(&terms, "bytes"); } +/// Bytes take a term up to 1023 bytes, as text's fold does: ore-rs's +/// 1024-byte ceiling counts the marker byte in front of them. +#[tokio::test] +async fn bytes_of_more_than_1023_bytes_have_no_term() { + let cipher = cipher().await; + let keyset = cipher.default_keyset(); + let longest = term(&keyset, vec![7u8; 1023]).await; + assert!(blocks(longest.as_bytes()) > 1023, "every byte is ordered"); + let too_long = keyset + .ore_block_term(vec![7u8; 1024], nonempty!("users/n")) + .await + .unwrap_err(); + assert!( + matches!(too_long, Error::Term(TermError::OreBlockTooLong)), + "{too_long:?}" + ); +} + /// One value encrypts to different bytes each time (the right half's /// nonce), and those terms compare equal; the left half is deterministic. #[tokio::test] @@ -325,9 +343,9 @@ async fn left_halves_are_pinned() { ); } -const PINNED_I32: &str = "020200060c0a0a1f37375535b8d860bd115a46292e8aac8ef6571e4ab59087b3b4c68d4621980b5633ca7f5a6d0da5d7d9d683003c2bfcc4630697cbce320a75f61b0875bc8d63c530d74c515d0ee6fc1b5303f5ff16e767ad905a95a1e5fbfebfb047d2f959b91b9b3d"; -const PINNED_F64: &str = "0202000b1501163b2a0a33341205014148b5ed0af663b698a1e4727de4a2f9749c116d8be814ed51540319016cc48b5c9ca000d776bf2aa438a615f84fe4c8856567731aebe1d043dcee1cf0a62e1995e3247033d370b0c7b24e6c043d33ecff732552dacfd13cad5b7b11f5c90f6480e05c5d75b04d605a7522c5102491999f35690dcd5ae228b08e812766bf35f8622307ffce17091ad737af98f1c82a9caa2fa556156c52ee7caee7b97d2b6a8f6e0e1ac247e006dae5d61fee390b39e2"; -const PINNED_TEXT: &str = "0203001601001039201c002d22313e3625260c211a36351e3507391835d9cec533ab14188edbe7bb248118b82ff3a1635b1469dd20ab6021b66d5d957893d251ad85f93322d5d445a149f4cea13a7be3692c56241a6cf438a1b6f3353bac005c4eabbeb193ee467a15d7b5cf6d171d8347f4fe2a9d87694bcc86db61747b9e4a1f76c078331be8e57291969b4c6a9e38d6efa1500d921c712888fa953fc94099f0cc0a5852c1decc45563122685a3c07184f4f49ed2b98abb2682e22fcb42140d0a0ff51cca79c678a0b0077c7de2f6690b6e63957e433a96e4f42b2f6e8eb15180349c8d3a4aa9e3663e11e90267b22428407a5f051095113a0ac0bbcbf99e0c4fc41fe2f1c233cf27af369a5f956f29813a6a153f78ab56af7e60f06f3a8fc7a637e6749d44218c0a58d5541944c85a970aff3ca00dbe3bc6be3fdd1944ccab358071e8baac6aeec381c2a2fdac3ba2d69b3c09f7694abf699f6a652da1a2510df98ac20716dd7c25f834d412c0617d195922952942187e399bb6b6d"; +const PINNED_I32: &str = "020200062422373e222f96362b6599fc5183c20804eeddd52d41890dc85341958dc7329d18a521c1d74f76fed42c7517b4e8cdfc74cbc6f9e521a72658dc177b73e9fa5a2d8a661bf3ef7117ecef8aeca900b3465c3640ebddfc8d5887729387bcdc64486801f99d2dda"; +const PINNED_F64: &str = "0202000b0b033912381600140628353cede9c0b7d2aebfd0b81f922c34bb5faa5cd0f3723ab63db491c0f20f47873e7a28d2cde32d31b9ddc8ffb2708429b2432d25b6c806a06cd6efe7021e9c965388064ca5493283cc499209b81c212593869c9baca7cf007f21a318ba7c3932ea23448843d69cb7f79c952cf4bb986a42ddb795a01b558f97fcf9ef5eba7efe87bcb51c10fbe80a7997aa55963596e851c858f014c9408b15ad2762c2a02b32db5bd58e5d3f85651ee7d2d43869d3b09d"; +const PINNED_TEXT: &str = "02030016010010172510373d14172510363017212d163e161a10341620b9ce74f6d4e48df255a31928333790bb04fffdcf1c73688b642c450bfd649429589029e048f81f6b746af7306d8c88833d5e3cd1dca9d109b48203a44e1be8cad4717a7072aeb2c694c4c7952bb117fc89635665a8c4023aed2b84e8652849986c7a4b6fd64d22012154868ba39ac5a7f55cfb26fee81c0b419ab238dc435cb5ac7475b496bb6fae32b60aa38855d425126a44fa59342dfb2d114e74d059399ab0b526d856e0f96f59a7740eef99a787001ebc2d1b6ca5d9bf600bc43f1452250ce58dd8f1e0590f1030c9bbacc31b9f2d984d19bbe6a35a0fd156871d39ff9d55e05f3b497efbfa358f17e32a7b96e3585f3d8a83308693ce3ed3d2dac7268c4570b10910fc73d0937f100ef31a7c7b70c1469984fad0be135ca4e00dcedc4242d1327c73746d3e90db658f48561f4f0572dc65dff246102e9875d98aa0dbdc5e079e76e3d3999f8a10766fcb034119794e333d82ba81db0692dbc93745204b"; /// The block ORE key is the index's own: its terms share no left half with /// another context's, and none with CLLW ORE's key (a CLLW term is a diff --git a/packages/stack-encrypt/tests/roundtrip.rs b/packages/stack-encrypt/tests/roundtrip.rs index def78a5a3..9afa770e8 100644 --- a/packages/stack-encrypt/tests/roundtrip.rs +++ b/packages/stack-encrypt/tests/roundtrip.rs @@ -122,6 +122,76 @@ async fn option_none_roundtrips() { assert_eq!(pt, None); } +/// A plain null opens as `None` of a fixed-width type too. Before vitaminc +/// 0.8 every `None` was sealed as a plain null, and the dynamic path still +/// seals one, so rows stored that way must keep opening into an `i64` or an +/// `f64` field. +#[tokio::test] +async fn a_plain_null_opens_as_a_fixed_width_none() { + let cipher = cipher().await; + let keyset = cipher.default_keyset(); + let ct = keyset + .encrypt(Option::::None, ()) + .await + .expect("encrypt"); + let pt: Option = cipher.decrypt(ct, ()).await.expect("decrypt"); + assert_eq!(pt, None, "i64"); + let ct = keyset + .encrypt(Option::::None, ()) + .await + .expect("encrypt"); + let pt: Option = cipher.decrypt(ct, ()).await.expect("decrypt"); + assert_eq!(pt, None, "f64"); +} + +/// A sealed `None` of a fixed-width type is as long as a sealed `Some`: +/// vitaminc 0.8 seals it as a typed null padded to the type's leaf, so the +/// length of a ciphertext does not say whether its value was there. It opens +/// as `None`. Text has no fixed width, so its `None` stays the short null. +#[tokio::test] +async fn a_fixed_width_none_is_as_long_as_a_some() { + let cipher = cipher().await; + let keyset = cipher.default_keyset(); + async fn sealed_len( + keyset: &stack_encrypt::KeysetCipher<'_, FakeDataKeySource>, + value: T, + ) -> usize + where + T: Encrypt + Send + 'static, + { + match keyset.encrypt(value, ()).await.expect("encrypt") { + CipherText::Single(leaf) => leaf.to_bytes().len(), + other => panic!("a scalar seals as one leaf: {other:?}"), + } + } + assert_eq!( + sealed_len(&keyset, Option::::None).await, + sealed_len(&keyset, Some(-7i64)).await, + "i64" + ); + assert_eq!( + sealed_len(&keyset, Option::::None).await, + sealed_len(&keyset, Some(7u32)).await, + "u32" + ); + assert_eq!( + sealed_len(&keyset, Option::::None).await, + sealed_len(&keyset, Some(1.5f64)).await, + "f64" + ); + assert!( + sealed_len(&keyset, Option::::None).await + < sealed_len(&keyset, Some("x".to_string())).await, + "text has no width to pad to" + ); + let ct = keyset + .encrypt(Option::::None, ()) + .await + .expect("encrypt"); + let pt: Option = cipher.decrypt(ct, ()).await.expect("decrypt"); + assert_eq!(pt, None); +} + #[tokio::test] async fn protected_roundtrip() { // Exercises the `Protected` Decrypt impl, which builds the value inside diff --git a/packages/stack-encrypt/tests/term_bytes.rs b/packages/stack-encrypt/tests/term_bytes.rs index e4c2c1d05..98d72cb82 100644 --- a/packages/stack-encrypt/tests/term_bytes.rs +++ b/packages/stack-encrypt/tests/term_bytes.rs @@ -32,6 +32,14 @@ //! these (the CHANGELOG says so). Floats are ordered by the same path: //! `F64`'s encoding folds `-0.0` into `0.0` and every NaN into one, which //! cllw-ore's own float encoding did not. +//! +//! The ORE and OPE pins moved again, with no label of this crate's moving, +//! when cllw-ore became `clww-ore` 0.6 on vitaminc 0.8. Its keystream was +//! fixed and its schemes' names, which every term's salt binds, became +//! `clww-ore` and `clww-ope`, so every order term changed. The marker byte +//! in front of text moved from the scheme to `vitaminc-ore` without +//! changing the bytes encrypted. As with vitaminc 0.5, nothing of this +//! crate's own derivation moved, so the `/v2` suffixes stay. use stack_encrypt::nonempty; use stack_encrypt::sem::{DefaultMatch, MatchConfig, MatchOptions}; @@ -124,7 +132,7 @@ async fn ore_term_bytes_are_pinned() { assert_eq!( hex(term.as_ref()), - "b8291f846d8028ad4e3a67ef95e541ca3c6d1a2b145f49af3135876ae75c5d7b" + "1ba4d59ccb15d505519ad854229ec0c106644fa8b8944ec54c68a1f324499d82" ); } @@ -142,7 +150,7 @@ async fn ope_term_bytes_are_pinned() { assert_eq!( hex(term.as_ref()), - "00d7a25b801c909f3cb9d177315ba4da7802b9e62eba8c07aab2ad9d64e1a0cfa7" + "00a77ed973ff1af2e5d5e3779471df246d17a515f0131eb87e35e02e7a80aa5292" ); } @@ -181,7 +189,7 @@ async fn match_term_positions_are_pinned_for_a_wide_filter() { } /// Text orders by the system ADR-0002's fold (`Ab` is encoded as `ab`, -/// behind cllw-ore's marker byte, so three bytes), under the column salt +/// behind `vitaminc-ore`'s marker byte, so three bytes), under the column salt /// of the `Text` target. Pins the fold, the salt and the CLLW encryption /// together. #[tokio::test] @@ -198,11 +206,11 @@ async fn text_order_term_bytes_are_pinned() { .unwrap(); assert_eq!( hex(ore.as_ref()), - "bc164005ea4d0f86e537d6829de90b2809ac20f460beffeb" + "b05ac63e0d2816d83868f90110b5226ad3c976f75e3a4b24" ); assert_eq!( hex(ope.as_ref()), - "00ff16eecb69b4f14c05a50b5a1249b8ad7cb63f376cbbb998" + "00bfac54f18ed40b78b19468df90f4e3550a5c046f3f283e89" ); } @@ -256,7 +264,7 @@ async fn text_with_no_fold_has_no_order_term() { .is_err()); } -/// A float's order term: cllw-ore's encryption of its ADR-0002 order key, +/// A float's order term: clww-ore's encryption of its ADR-0002 order key, /// the `f64` with zero signs and NaN payloads folded, under the column salt /// of the `F64` target. Pins the key, the salt and the encryption. #[tokio::test] @@ -271,8 +279,8 @@ async fn float_order_term_bytes_are_pinned() { .ope_term(1.5f64, nonempty!("users/score")) .await .unwrap(); - assert_eq!(hex(ore.as_ref()), "f591a4bf7663b9ffcaf021d87de0d10dad925b7663e33de47966c05dab4f76ff1e8bc5537162088c01be03b4db4d3fe980b111f46e7d4da445ec19d2f7445ef0"); - assert_eq!(hex(ope.as_ref()), "01501c6dd5f9a769811461eadfd54631ea58f3f051e7603117396add6c79e5fe4fd2f549c92f0afeaf94cd6c49fc33a9a0657c812132bea46779b2f19f10ce36ae"); + assert_eq!(hex(ore.as_ref()), "6c487f77b33ab3b4e0d37e79f84b24b92843d9cb591d492fd8d092afebba96e50e7d6733935a6e94faa8e7945f04471385553a35aa00ca30fb77d0b7a7a9a9a3"); + assert_eq!(hex(ope.as_ref()), "00836260f898d58c06c8e23b8754e05d7d352c676b714e8523582c930f9e83640ad87d56aa35b7c3ecdc44dfb29a7378fb95738bca93f5ee9ca2a066c63ecb6aaf"); } /// Floats order as Postgres's `float8` does: `-0.0` ties `0.0`, every NaN is diff --git a/packages/stack-encrypt/tests/ui/order_term_of_an_8_bit_integer.stderr b/packages/stack-encrypt/tests/ui/order_term_of_an_8_bit_integer.stderr index dee586b74..4ccf28147 100644 --- a/packages/stack-encrypt/tests/ui/order_term_of_an_8_bit_integer.stderr +++ b/packages/stack-encrypt/tests/ui/order_term_of_an_8_bit_integer.stderr @@ -17,7 +17,7 @@ error[E0277]: the trait bound `u8: Orderable` is not satisfied note: required by a bound in `OreTerm` --> src/sem/mod.rs | - | pub struct OreTerm(OreCllw8VariableV1, PhantomData T>); + | pub struct OreTerm(OreClww8VariableV1, PhantomData T>); | ^^^^^^^^^ required by this bound in `OreTerm` error[E0277]: the trait bound `i8: Orderable` is not satisfied @@ -39,7 +39,7 @@ error[E0277]: the trait bound `i8: Orderable` is not satisfied note: required by a bound in `OpeTerm` --> src/sem/mod.rs | - | pub struct OpeTerm(OpeCllw8VariableV1, PhantomData T>); + | pub struct OpeTerm(OpeClww8VariableV1, PhantomData T>); | ^^^^^^^^^ required by this bound in `OpeTerm` error[E0277]: the trait bound `i8: Orderable` is not satisfied diff --git a/packages/stack-encrypt/tests/ui/plaintext_needs_encrypt.stderr b/packages/stack-encrypt/tests/ui/plaintext_needs_encrypt.stderr index a8539066c..d357fbec3 100644 --- a/packages/stack-encrypt/tests/ui/plaintext_needs_encrypt.stderr +++ b/packages/stack-encrypt/tests/ui/plaintext_needs_encrypt.stderr @@ -26,10 +26,10 @@ note: there are multiple different versions of crate `vitaminc_aead` in the depe &&'b T &'a BTreeMap &'a HashMap + &'a Protected &'a Vec &'a [T] &'a std::option::Option - &'a vitaminc_protected::protected::Protected &PassthroughFrame and $N others = note: required for `CipherText` to implement `EncryptFrom` diff --git a/packages/stack-guest-abi/src/value.rs b/packages/stack-guest-abi/src/value.rs index a350c3cde..7da2ff542 100644 --- a/packages/stack-guest-abi/src/value.rs +++ b/packages/stack-guest-abi/src/value.rs @@ -10,7 +10,8 @@ //! through a [`Sink`], for the tests that check what a host is given. use vitaminc_aead::plaintext::{ - visit_map, visit_seq, Encrypt, Float, Logical, MapSink, Physical, SeqSink, Sink, SourceError, + visit_map, visit_seq, Encrypt, FixedType, Float, Logical, MapSink, Physical, SeqSink, Sink, + SourceError, }; use vitaminc_aead_frame::{to_frame, Frame, FrameError, FrameWriteError}; use vitaminc_protected::{Controlled, Protected}; @@ -231,6 +232,12 @@ impl Sink for ValueSink { Ok(self.0.put(value)) } + /// A typed null is a null to the host: its type only hides its length + /// once sealed. + fn typed_null(self, _: FixedType) -> Result { + Ok(self.0.put(HostValue::Null)) + } + fn seq(self, _: Option) -> Result, DecodeError> { Ok(ValueSeq { out: self.0, @@ -361,6 +368,26 @@ mod tests { assert!(matches!(back.get("ids"), Some(HostValue::List(items)) if items.len() == 2)); } + /// A typed null (vitaminc's null of a fixed-width type, padded to the + /// type's length) reads as a null: the host has no typed nulls. A guest + /// writes none itself, but a frame may hold one. + #[test] + fn a_typed_null_reads_back_as_a_null() { + use vitaminc_aead::plaintext::Width; + for ty in [ + FixedType::new(None, Width::I64), + FixedType::new(Some(Logical::Date), Width::I32), + ] { + let ty = ty.expect("a fixed-width type"); + let mut frame = Vec::new(); + vitaminc_aead::leaf::write_typed_null(ty, &mut frame); + assert!( + matches!(HostValue::decode(&frame), Ok(HostValue::Null)), + "{ty:?}" + ); + } + } + #[test] fn a_map_with_a_repeated_key_does_not_encode() { let value = HostValue::Map(vec![ diff --git a/scripts/__tests__/dependabot-eql-inherited-ignores.test.mjs b/scripts/__tests__/dependabot-eql-inherited-ignores.test.mjs index 16d80a139..21fe1dec2 100644 --- a/scripts/__tests__/dependabot-eql-inherited-ignores.test.mjs +++ b/scripts/__tests__/dependabot-eql-inherited-ignores.test.mjs @@ -13,11 +13,11 @@ import { REPO_ROOT } from './lib/repo-root.mjs' * The EQL workspace is a separate Cargo workspace, but not an independent one: * `tests/encryption` depends by path on `stack-kms` and `stack-encrypt`, and * `eql-bindings` on `stack-encrypt` (behind its optional `stack-encrypt` - * feature). Those crates declare `recipher`, `cllw-ore` and `vitaminc-*` as + * feature). Those crates declare `recipher`, `clww-ore` and `vitaminc-*` as * `{ workspace = true }`. Built inside the EQL workspace, those requirements * still come from the ROOT `Cargo.toml`. The root entry ignores these crates - * because they move by hand with cipherstash-suite: the root manifest pins - * `recipher` and `cllw-ore` with `=`, and so does the Go guest. With no + * because they move by hand: the root manifest pins `recipher` with `=`, and + * so does the Go guest. With no * matching ignore, the EQL entry's monthly PR bumped them in the EQL lock and, * to satisfy the exact pins, edited the root `Cargo.toml` without updating the * root `Cargo.lock` or the guest's pin (#1205). Every root `--locked` build and