From 4219dd481502a57729caca2347b7943418503578 Mon Sep 17 00:00:00 2001 From: c0dev0id Date: Sun, 20 Nov 2022 12:36:32 +0100 Subject: [PATCH] [gurk-rs] Update to 0.3.0 --- net/gurk-rs/Makefile | 31 +- net/gurk-rs/crates.inc | 434 +- net/gurk-rs/distinfo | 874 +- net/gurk-rs/files/config | 32 +- .../.cargo-checksum.json | 1 - .../curve25519-dalek-2.0.0/CHANGELOG.md | 104 - .../curve25519-dalek-2.0.0/CONTRIBUTING.md | 28 - .../vendor/curve25519-dalek-2.0.0/Cargo.toml | 61 - .../vendor/curve25519-dalek-2.0.0/LICENSE | 64 - .../vendor/curve25519-dalek-2.0.0/Makefile | 8 - .../vendor/curve25519-dalek-2.0.0/README.md | 207 - .../benches/dalek_benchmarks.rs | 339 - .../docs/assets/dalek-logo-clear.png | Bin 113085 -> 0 bytes .../docs/assets/dalek-logo.png | Bin 109731 -> 0 bytes .../docs/assets/dalek-logo.svg | 1 - .../assets/rustdoc-include-katex-header.html | 10 - .../curve25519-dalek-2.0.0/docs/avx2-notes.md | 140 - .../curve25519-dalek-2.0.0/docs/ifma-notes.md | 580 -- .../docs/parallel-formulas.md | 333 - .../curve25519-dalek-2.0.0/src/backend/mod.rs | 62 - .../src/backend/serial/curve_models/mod.rs | 550 -- .../src/backend/serial/mod.rs | 43 - .../src/backend/serial/scalar_mul/mod.rs | 30 - .../backend/serial/scalar_mul/pippenger.rs | 202 - .../serial/scalar_mul/precomputed_straus.rs | 110 - .../src/backend/serial/scalar_mul/straus.rs | 195 - .../serial/scalar_mul/variable_base.rs | 46 - .../serial/scalar_mul/vartime_double_base.rs | 61 - .../src/backend/serial/u32/constants.rs | 4776 ---------- .../src/backend/serial/u32/field.rs | 577 -- .../src/backend/serial/u32/mod.rs | 21 - .../src/backend/serial/u32/scalar.rs | 529 -- .../src/backend/serial/u64/constants.rs | 7743 ---------------- .../src/backend/serial/u64/field.rs | 563 -- .../src/backend/serial/u64/mod.rs | 26 - .../src/backend/serial/u64/scalar.rs | 451 - .../src/backend/vector/avx2/constants.rs | 3427 -------- .../src/backend/vector/avx2/edwards.rs | 524 -- .../src/backend/vector/avx2/field.rs | 985 --- .../src/backend/vector/avx2/mod.rs | 20 - .../src/backend/vector/ifma/constants.rs | 2062 ----- .../src/backend/vector/ifma/edwards.rs | 315 - .../src/backend/vector/ifma/field.rs | 824 -- .../src/backend/vector/ifma/mod.rs | 19 - .../src/backend/vector/mod.rs | 42 - .../src/backend/vector/scalar_mul/mod.rs | 22 - .../backend/vector/scalar_mul/pippenger.rs | 164 - .../vector/scalar_mul/precomputed_straus.rs | 107 - .../src/backend/vector/scalar_mul/straus.rs | 107 - .../vector/scalar_mul/variable_base.rs | 32 - .../vector/scalar_mul/vartime_double_base.rs | 60 - .../curve25519-dalek-2.0.0/src/constants.rs | 176 - .../curve25519-dalek-2.0.0/src/edwards.rs | 1435 --- .../curve25519-dalek-2.0.0/src/field.rs | 460 - .../vendor/curve25519-dalek-2.0.0/src/lib.rs | 100 - .../curve25519-dalek-2.0.0/src/lizard/LICENSE | 21 - .../src/lizard/jacobi_quartic.rs | 74 - .../src/lizard/lizard_constants.rs | 54 - .../src/lizard/lizard_ristretto.rs | 305 - .../curve25519-dalek-2.0.0/src/lizard/mod.rs | 13 - .../src/lizard/u32_constants.rs | 33 - .../src/lizard/u64_constants.rs | 18 - .../curve25519-dalek-2.0.0/src/macros.rs | 123 - .../curve25519-dalek-2.0.0/src/montgomery.rs | 403 - .../curve25519-dalek-2.0.0/src/prelude.rs | 8 - .../curve25519-dalek-2.0.0/src/ristretto.rs | 1365 --- .../curve25519-dalek-2.0.0/src/scalar.rs | 1739 ---- .../curve25519-dalek-2.0.0/src/traits.rs | 378 - .../curve25519-dalek-2.0.0/src/window.rs | 206 - .../vendor/ristretto.sage | 857 -- .../curve25519-dalek/.cargo-checksum.json | 1 - .../vendor/curve25519-dalek/CHANGELOG.md | 169 - .../curve25519-dalek/CODE_OF_CONDUCT.md | 8 - .../vendor/curve25519-dalek/CONTRIBUTING.md | 19 - .../files/vendor/curve25519-dalek/Cargo.toml | 97 - .../files/vendor/curve25519-dalek/LICENSE | 65 - .../files/vendor/curve25519-dalek/Makefile | 8 - .../files/vendor/curve25519-dalek/README.md | 220 - .../benches/dalek_benchmarks.rs | 363 - .../docs/assets/dalek-logo-clear.png | Bin 113085 -> 0 bytes .../docs/assets/dalek-logo.png | Bin 109731 -> 0 bytes .../docs/assets/dalek-logo.svg | 1 - .../assets/rustdoc-include-katex-header.html | 10 - .../curve25519-dalek/docs/avx2-notes.md | 140 - .../curve25519-dalek/docs/ifma-notes.md | 580 -- .../docs/parallel-formulas.md | 333 - .../curve25519-dalek/src/backend/mod.rs | 65 - .../src/backend/serial/curve_models/mod.rs | 551 -- .../src/backend/serial/fiat_u32/field.rs | 260 - .../src/backend/serial/fiat_u32/mod.rs | 26 - .../src/backend/serial/fiat_u64/field.rs | 249 - .../src/backend/serial/fiat_u64/mod.rs | 28 - .../src/backend/serial/mod.rs | 55 - .../src/backend/serial/scalar_mul/mod.rs | 31 - .../backend/serial/scalar_mul/pippenger.rs | 202 - .../serial/scalar_mul/precomputed_straus.rs | 110 - .../src/backend/serial/scalar_mul/straus.rs | 196 - .../serial/scalar_mul/variable_base.rs | 46 - .../serial/scalar_mul/vartime_double_base.rs | 62 - .../src/backend/serial/u32/constants.rs | 4789 ---------- .../src/backend/serial/u32/field.rs | 578 -- .../src/backend/serial/u32/mod.rs | 22 - .../src/backend/serial/u32/scalar.rs | 529 -- .../src/backend/serial/u64/constants.rs | 7759 ----------------- .../src/backend/serial/u64/field.rs | 564 -- .../src/backend/serial/u64/mod.rs | 27 - .../src/backend/serial/u64/scalar.rs | 450 - .../src/backend/vector/avx2/constants.rs | 3428 -------- .../src/backend/vector/avx2/edwards.rs | 545 -- .../src/backend/vector/avx2/field.rs | 986 --- .../src/backend/vector/avx2/mod.rs | 21 - .../src/backend/vector/ifma/constants.rs | 2062 ----- .../src/backend/vector/ifma/edwards.rs | 315 - .../src/backend/vector/ifma/field.rs | 826 -- .../src/backend/vector/ifma/mod.rs | 19 - .../src/backend/vector/mod.rs | 43 - .../src/backend/vector/scalar_mul/mod.rs | 23 - .../backend/vector/scalar_mul/pippenger.rs | 164 - .../vector/scalar_mul/precomputed_straus.rs | 107 - .../src/backend/vector/scalar_mul/straus.rs | 108 - .../vector/scalar_mul/variable_base.rs | 32 - .../vector/scalar_mul/vartime_double_base.rs | 62 - .../vendor/curve25519-dalek/src/constants.rs | 181 - .../vendor/curve25519-dalek/src/edwards.rs | 1699 ---- .../vendor/curve25519-dalek/src/field.rs | 476 - .../files/vendor/curve25519-dalek/src/lib.rs | 101 - .../vendor/curve25519-dalek/src/macros.rs | 124 - .../vendor/curve25519-dalek/src/montgomery.rs | 459 - .../vendor/curve25519-dalek/src/prelude.rs | 19 - .../vendor/curve25519-dalek/src/ristretto.rs | 1366 --- .../vendor/curve25519-dalek/src/scalar.rs | 1754 ---- .../vendor/curve25519-dalek/src/traits.rs | 394 - .../vendor/curve25519-dalek/src/window.rs | 228 - .../curve25519-dalek/vendor/ristretto.sage | 857 -- .../libsignal-protocol/.cargo-checksum.json | 1 - .../vendor/libsignal-protocol/Cargo.toml | 56 - .../libsignal-protocol/benches/ratchet.rs | 103 - .../benches/sealed_sender.rs | 287 - .../libsignal-protocol/benches/session.rs | 249 - .../files/vendor/libsignal-protocol/build.rs | 18 - .../vendor/libsignal-protocol/src/address.rs | 73 - .../vendor/libsignal-protocol/src/consts.rs | 10 - .../vendor/libsignal-protocol/src/crypto.rs | 147 - .../vendor/libsignal-protocol/src/curve.rs | 402 - .../src/curve/curve25519.rs | 284 - .../vendor/libsignal-protocol/src/error.rs | 108 - .../libsignal-protocol/src/fingerprint.rs | 545 -- .../libsignal-protocol/src/group_cipher.rs | 237 - .../libsignal-protocol/src/identity_key.rs | 179 - .../vendor/libsignal-protocol/src/lib.rs | 82 - .../vendor/libsignal-protocol/src/proto.rs | 10 - .../src/proto/fingerprint.proto | 19 - .../src/proto/fingerprint.rs | 6 - .../src/proto/sealed_sender.proto | 62 - .../src/proto/sealed_sender.rs | 6 - .../src/proto/service.proto | 24 - .../libsignal-protocol/src/proto/service.rs | 6 - .../src/proto/storage.proto | 108 - .../libsignal-protocol/src/proto/storage.rs | 6 - .../libsignal-protocol/src/proto/wire.proto | 39 - .../libsignal-protocol/src/proto/wire.rs | 6 - .../vendor/libsignal-protocol/src/protocol.rs | 1059 --- .../vendor/libsignal-protocol/src/ratchet.rs | 168 - .../libsignal-protocol/src/ratchet/keys.rs | 210 - .../libsignal-protocol/src/ratchet/params.rs | 126 - .../libsignal-protocol/src/sealed_sender.rs | 1712 ---- .../libsignal-protocol/src/sender_keys.rs | 631 -- .../vendor/libsignal-protocol/src/session.rs | 205 - .../libsignal-protocol/src/session_cipher.rs | 636 -- .../vendor/libsignal-protocol/src/state.rs | 15 - .../libsignal-protocol/src/state/bundle.rs | 79 - .../libsignal-protocol/src/state/prekey.rs | 55 - .../libsignal-protocol/src/state/session.rs | 640 -- .../src/state/signed_prekey.rs | 69 - .../vendor/libsignal-protocol/src/storage.rs | 18 - .../libsignal-protocol/src/storage/inmem.rs | 454 - .../libsignal-protocol/src/storage/traits.rs | 115 - .../vendor/libsignal-protocol/src/utils.rs | 141 - .../vendor/libsignal-protocol/tests/groups.rs | 874 -- .../libsignal-protocol/tests/ratchet.rs | 173 - .../libsignal-protocol/tests/sealed_sender.rs | 1005 --- .../libsignal-protocol/tests/session.rs | 1990 ----- .../libsignal-protocol/tests/support/mod.rs | 142 - .../.cargo-checksum.json | 1 - .../vendor/libsignal-service-hyper/Cargo.toml | 42 - .../examples/registering.rs | 138 - .../vendor/libsignal-service-hyper/src/lib.rs | 8 - .../src/provisioning.rs | 150 - .../src/push_service.rs | 493 -- .../libsignal-service-hyper/src/websocket.rs | 221 - .../libsignal-service/.cargo-checksum.json | 1 - .../files/vendor/libsignal-service/Cargo.toml | 49 - .../files/vendor/libsignal-service/build.rs | 32 - .../protobuf/DecryptedGroups.proto | 109 - .../libsignal-service/protobuf/Groups.proto | 226 - .../protobuf/Provisioning.proto | 40 - .../protobuf/SignalService.proto | 625 -- .../protobuf/StickerResources.proto | 25 - .../protobuf/UnidentifiedDelivery.proto | 48 - .../protobuf/WebSocketResources.proto | 39 - .../libsignal-service/src/account_manager.rs | 409 - .../src/attachment_cipher.rs | 163 - .../vendor/libsignal-service/src/cipher.rs | 372 - .../libsignal-service/src/configuration.rs | 180 - .../vendor/libsignal-service/src/content.rs | 112 - .../libsignal-service/src/digeststream.rs | 31 - .../vendor/libsignal-service/src/envelope.rs | 246 - .../src/groups_v2/manager.rs | 230 - .../libsignal-service/src/groups_v2/mod.rs | 10 - .../src/groups_v2/operations.rs | 229 - .../libsignal-service/src/groups_v2/utils.rs | 18 - .../vendor/libsignal-service/src/kat.bin.rs | 44 - .../files/vendor/libsignal-service/src/lib.rs | 93 - .../libsignal-service/src/messagepipe.rs | 306 - .../vendor/libsignal-service/src/models.rs | 78 - .../vendor/libsignal-service/src/pre_keys.rs | 70 - .../libsignal-service/src/profile_cipher.rs | 276 - .../libsignal-service/src/profile_name.rs | 106 - .../vendor/libsignal-service/src/proto.rs | 61 - .../src/provisioning/cipher.rs | 221 - .../src/provisioning/manager.rs | 369 - .../libsignal-service/src/provisioning/mod.rs | 40 - .../src/provisioning/pipe.rs | 214 - .../libsignal-service/src/push_service.rs | 799 -- .../vendor/libsignal-service/src/receiver.rs | 157 - .../src/sealed_session_cipher.rs | 1118 --- .../vendor/libsignal-service/src/sender.rs | 765 -- .../libsignal-service/src/service_address.rs | 119 - .../libsignal-service/src/session_store.rs | 69 - .../vendor/libsignal-service/src/utils.rs | 145 - .../files/vendor/poksho/.cargo-checksum.json | 1 - net/gurk-rs/files/vendor/poksho/Cargo.toml | 30 - net/gurk-rs/files/vendor/poksho/LICENSE | 628 -- net/gurk-rs/files/vendor/poksho/README.md | 10 - net/gurk-rs/files/vendor/poksho/src/args.rs | 38 - net/gurk-rs/files/vendor/poksho/src/errors.rs | 17 - net/gurk-rs/files/vendor/poksho/src/lib.rs | 27 - net/gurk-rs/files/vendor/poksho/src/proof.rs | 43 - net/gurk-rs/files/vendor/poksho/src/scalar.rs | 22 - net/gurk-rs/files/vendor/poksho/src/shoapi.rs | 33 - .../files/vendor/poksho/src/shohmacsha256.rs | 162 - .../files/vendor/poksho/src/shosha256.rs | 168 - net/gurk-rs/files/vendor/poksho/src/sign.rs | 92 - .../files/vendor/poksho/src/simple_types.rs | 12 - .../files/vendor/poksho/src/statement.rs | 600 -- .../files/vendor/presage/.cargo-checksum.json | 1 - .../vendor/presage/.github/workflows/ci.yaml | 54 - net/gurk-rs/files/vendor/presage/Cargo.toml | 49 - net/gurk-rs/files/vendor/presage/LICENSE.md | 661 -- net/gurk-rs/files/vendor/presage/README.md | 40 - .../files/vendor/presage/examples/cli.rs | 349 - .../files/vendor/presage/examples/link.rs | 18 - .../files/vendor/presage/examples/register.rs | 53 - net/gurk-rs/files/vendor/presage/rustfmt.toml | 1 - net/gurk-rs/files/vendor/presage/src/cache.rs | 75 - .../files/vendor/presage/src/config/mod.rs | 32 - .../files/vendor/presage/src/config/sled.rs | 604 -- .../files/vendor/presage/src/errors.rs | 52 - net/gurk-rs/files/vendor/presage/src/lib.rs | 34 - .../files/vendor/presage/src/manager.rs | 807 -- .../files/vendor/zkgroup/.cargo-checksum.json | 1 - net/gurk-rs/files/vendor/zkgroup/Cargo.toml | 53 - .../zkgroup/benches/zkgroup_benchmarks.rs | 219 - .../vendor/zkgroup/rustfmt.license-template | 6 - net/gurk-rs/files/vendor/zkgroup/rustfmt.toml | 12 - .../files/vendor/zkgroup/scripts/format-code | 7 - .../zkgroup/src/api/auth/auth_credential.rs | 22 - .../api/auth/auth_credential_presentation.rs | 34 - .../src/api/auth/auth_credential_response.rs | 19 - .../files/vendor/zkgroup/src/api/auth/mod.rs | 14 - .../zkgroup/src/api/groups/group_params.rs | 318 - .../vendor/zkgroup/src/api/groups/mod.rs | 16 - .../src/api/groups/profile_key_ciphertext.rs | 18 - .../zkgroup/src/api/groups/uuid_ciphertext.rs | 18 - .../files/vendor/zkgroup/src/api/mod.rs | 15 - .../vendor/zkgroup/src/api/profiles/mod.rs | 24 - .../zkgroup/src/api/profiles/profile_key.rs | 68 - .../api/profiles/profile_key_commitment.rs | 18 - .../api/profiles/profile_key_credential.rs | 20 - .../profile_key_credential_presentation.rs | 37 - .../profile_key_credential_request.rs | 20 - .../profile_key_credential_request_context.rs | 37 - .../profile_key_credential_response.rs | 19 - .../src/api/profiles/profile_key_version.rs | 30 - .../vendor/zkgroup/src/api/server_params.rs | 351 - .../vendor/zkgroup/src/common/constants.rs | 75 - .../files/vendor/zkgroup/src/common/errors.rs | 16 - .../files/vendor/zkgroup/src/common/mod.rs | 11 - .../files/vendor/zkgroup/src/common/sho.rs | 44 - .../vendor/zkgroup/src/common/simple_types.rs | 37 - .../vendor/zkgroup/src/crypto/credentials.rs | 363 - .../files/vendor/zkgroup/src/crypto/mod.rs | 16 - .../src/crypto/profile_key_commitment.rs | 120 - .../crypto/profile_key_credential_request.rs | 190 - .../src/crypto/profile_key_encryption.rs | 228 - .../zkgroup/src/crypto/profile_key_struct.rs | 75 - .../files/vendor/zkgroup/src/crypto/proofs.rs | 731 -- .../vendor/zkgroup/src/crypto/signature.rs | 120 - .../zkgroup/src/crypto/uid_encryption.rs | 160 - .../vendor/zkgroup/src/crypto/uid_struct.rs | 49 - .../files/vendor/zkgroup/src/ffi/constants.rs | 12 - .../files/vendor/zkgroup/src/ffi/ffiapi.rs | 1324 --- .../vendor/zkgroup/src/ffi/ffiapijava.rs | 1563 ---- .../files/vendor/zkgroup/src/ffi/mod.rs | 13 - .../files/vendor/zkgroup/src/ffi/simpleapi.rs | 901 -- net/gurk-rs/files/vendor/zkgroup/src/lib.rs | 15 - .../vendor/zkgroup/tests/integration_tests.rs | 348 - 307 files changed, 706 insertions(+), 105423 deletions(-) delete mode 100644 net/gurk-rs/files/vendor/curve25519-dalek-2.0.0/.cargo-checksum.json delete mode 100644 net/gurk-rs/files/vendor/curve25519-dalek-2.0.0/CHANGELOG.md delete mode 100644 net/gurk-rs/files/vendor/curve25519-dalek-2.0.0/CONTRIBUTING.md delete mode 100644 net/gurk-rs/files/vendor/curve25519-dalek-2.0.0/Cargo.toml delete mode 100644 net/gurk-rs/files/vendor/curve25519-dalek-2.0.0/LICENSE delete mode 100644 net/gurk-rs/files/vendor/curve25519-dalek-2.0.0/Makefile delete mode 100644 net/gurk-rs/files/vendor/curve25519-dalek-2.0.0/README.md delete mode 100644 net/gurk-rs/files/vendor/curve25519-dalek-2.0.0/benches/dalek_benchmarks.rs delete mode 100644 net/gurk-rs/files/vendor/curve25519-dalek-2.0.0/docs/assets/dalek-logo-clear.png delete mode 100644 net/gurk-rs/files/vendor/curve25519-dalek-2.0.0/docs/assets/dalek-logo.png delete mode 100644 net/gurk-rs/files/vendor/curve25519-dalek-2.0.0/docs/assets/dalek-logo.svg delete mode 100644 net/gurk-rs/files/vendor/curve25519-dalek-2.0.0/docs/assets/rustdoc-include-katex-header.html delete mode 100644 net/gurk-rs/files/vendor/curve25519-dalek-2.0.0/docs/avx2-notes.md delete mode 100644 net/gurk-rs/files/vendor/curve25519-dalek-2.0.0/docs/ifma-notes.md delete mode 100644 net/gurk-rs/files/vendor/curve25519-dalek-2.0.0/docs/parallel-formulas.md delete mode 100644 net/gurk-rs/files/vendor/curve25519-dalek-2.0.0/src/backend/mod.rs delete mode 100644 net/gurk-rs/files/vendor/curve25519-dalek-2.0.0/src/backend/serial/curve_models/mod.rs delete mode 100644 net/gurk-rs/files/vendor/curve25519-dalek-2.0.0/src/backend/serial/mod.rs delete mode 100644 net/gurk-rs/files/vendor/curve25519-dalek-2.0.0/src/backend/serial/scalar_mul/mod.rs delete mode 100644 net/gurk-rs/files/vendor/curve25519-dalek-2.0.0/src/backend/serial/scalar_mul/pippenger.rs delete mode 100644 net/gurk-rs/files/vendor/curve25519-dalek-2.0.0/src/backend/serial/scalar_mul/precomputed_straus.rs delete mode 100644 net/gurk-rs/files/vendor/curve25519-dalek-2.0.0/src/backend/serial/scalar_mul/straus.rs delete mode 100644 net/gurk-rs/files/vendor/curve25519-dalek-2.0.0/src/backend/serial/scalar_mul/variable_base.rs delete mode 100644 net/gurk-rs/files/vendor/curve25519-dalek-2.0.0/src/backend/serial/scalar_mul/vartime_double_base.rs delete mode 100644 net/gurk-rs/files/vendor/curve25519-dalek-2.0.0/src/backend/serial/u32/constants.rs delete mode 100644 net/gurk-rs/files/vendor/curve25519-dalek-2.0.0/src/backend/serial/u32/field.rs delete mode 100644 net/gurk-rs/files/vendor/curve25519-dalek-2.0.0/src/backend/serial/u32/mod.rs delete mode 100644 net/gurk-rs/files/vendor/curve25519-dalek-2.0.0/src/backend/serial/u32/scalar.rs delete mode 100644 net/gurk-rs/files/vendor/curve25519-dalek-2.0.0/src/backend/serial/u64/constants.rs delete mode 100644 net/gurk-rs/files/vendor/curve25519-dalek-2.0.0/src/backend/serial/u64/field.rs delete mode 100644 net/gurk-rs/files/vendor/curve25519-dalek-2.0.0/src/backend/serial/u64/mod.rs delete mode 100644 net/gurk-rs/files/vendor/curve25519-dalek-2.0.0/src/backend/serial/u64/scalar.rs delete mode 100644 net/gurk-rs/files/vendor/curve25519-dalek-2.0.0/src/backend/vector/avx2/constants.rs delete mode 100644 net/gurk-rs/files/vendor/curve25519-dalek-2.0.0/src/backend/vector/avx2/edwards.rs delete mode 100644 net/gurk-rs/files/vendor/curve25519-dalek-2.0.0/src/backend/vector/avx2/field.rs delete mode 100644 net/gurk-rs/files/vendor/curve25519-dalek-2.0.0/src/backend/vector/avx2/mod.rs delete mode 100644 net/gurk-rs/files/vendor/curve25519-dalek-2.0.0/src/backend/vector/ifma/constants.rs delete mode 100644 net/gurk-rs/files/vendor/curve25519-dalek-2.0.0/src/backend/vector/ifma/edwards.rs delete mode 100644 net/gurk-rs/files/vendor/curve25519-dalek-2.0.0/src/backend/vector/ifma/field.rs delete mode 100644 net/gurk-rs/files/vendor/curve25519-dalek-2.0.0/src/backend/vector/ifma/mod.rs delete mode 100644 net/gurk-rs/files/vendor/curve25519-dalek-2.0.0/src/backend/vector/mod.rs delete mode 100644 net/gurk-rs/files/vendor/curve25519-dalek-2.0.0/src/backend/vector/scalar_mul/mod.rs delete mode 100644 net/gurk-rs/files/vendor/curve25519-dalek-2.0.0/src/backend/vector/scalar_mul/pippenger.rs delete mode 100644 net/gurk-rs/files/vendor/curve25519-dalek-2.0.0/src/backend/vector/scalar_mul/precomputed_straus.rs delete mode 100644 net/gurk-rs/files/vendor/curve25519-dalek-2.0.0/src/backend/vector/scalar_mul/straus.rs delete mode 100644 net/gurk-rs/files/vendor/curve25519-dalek-2.0.0/src/backend/vector/scalar_mul/variable_base.rs delete mode 100644 net/gurk-rs/files/vendor/curve25519-dalek-2.0.0/src/backend/vector/scalar_mul/vartime_double_base.rs delete mode 100644 net/gurk-rs/files/vendor/curve25519-dalek-2.0.0/src/constants.rs delete mode 100644 net/gurk-rs/files/vendor/curve25519-dalek-2.0.0/src/edwards.rs delete mode 100644 net/gurk-rs/files/vendor/curve25519-dalek-2.0.0/src/field.rs delete mode 100644 net/gurk-rs/files/vendor/curve25519-dalek-2.0.0/src/lib.rs delete mode 100644 net/gurk-rs/files/vendor/curve25519-dalek-2.0.0/src/lizard/LICENSE delete mode 100644 net/gurk-rs/files/vendor/curve25519-dalek-2.0.0/src/lizard/jacobi_quartic.rs delete mode 100644 net/gurk-rs/files/vendor/curve25519-dalek-2.0.0/src/lizard/lizard_constants.rs delete mode 100644 net/gurk-rs/files/vendor/curve25519-dalek-2.0.0/src/lizard/lizard_ristretto.rs delete mode 100644 net/gurk-rs/files/vendor/curve25519-dalek-2.0.0/src/lizard/mod.rs delete mode 100644 net/gurk-rs/files/vendor/curve25519-dalek-2.0.0/src/lizard/u32_constants.rs delete mode 100644 net/gurk-rs/files/vendor/curve25519-dalek-2.0.0/src/lizard/u64_constants.rs delete mode 100644 net/gurk-rs/files/vendor/curve25519-dalek-2.0.0/src/macros.rs delete mode 100644 net/gurk-rs/files/vendor/curve25519-dalek-2.0.0/src/montgomery.rs delete mode 100644 net/gurk-rs/files/vendor/curve25519-dalek-2.0.0/src/prelude.rs delete mode 100644 net/gurk-rs/files/vendor/curve25519-dalek-2.0.0/src/ristretto.rs delete mode 100644 net/gurk-rs/files/vendor/curve25519-dalek-2.0.0/src/scalar.rs delete mode 100644 net/gurk-rs/files/vendor/curve25519-dalek-2.0.0/src/traits.rs delete mode 100644 net/gurk-rs/files/vendor/curve25519-dalek-2.0.0/src/window.rs delete mode 100644 net/gurk-rs/files/vendor/curve25519-dalek-2.0.0/vendor/ristretto.sage delete mode 100644 net/gurk-rs/files/vendor/curve25519-dalek/.cargo-checksum.json delete mode 100644 net/gurk-rs/files/vendor/curve25519-dalek/CHANGELOG.md delete mode 100644 net/gurk-rs/files/vendor/curve25519-dalek/CODE_OF_CONDUCT.md delete mode 100644 net/gurk-rs/files/vendor/curve25519-dalek/CONTRIBUTING.md delete mode 100644 net/gurk-rs/files/vendor/curve25519-dalek/Cargo.toml delete mode 100644 net/gurk-rs/files/vendor/curve25519-dalek/LICENSE delete mode 100644 net/gurk-rs/files/vendor/curve25519-dalek/Makefile delete mode 100644 net/gurk-rs/files/vendor/curve25519-dalek/README.md delete mode 100644 net/gurk-rs/files/vendor/curve25519-dalek/benches/dalek_benchmarks.rs delete mode 100644 net/gurk-rs/files/vendor/curve25519-dalek/docs/assets/dalek-logo-clear.png delete mode 100644 net/gurk-rs/files/vendor/curve25519-dalek/docs/assets/dalek-logo.png delete mode 100644 net/gurk-rs/files/vendor/curve25519-dalek/docs/assets/dalek-logo.svg delete mode 100644 net/gurk-rs/files/vendor/curve25519-dalek/docs/assets/rustdoc-include-katex-header.html delete mode 100644 net/gurk-rs/files/vendor/curve25519-dalek/docs/avx2-notes.md delete mode 100644 net/gurk-rs/files/vendor/curve25519-dalek/docs/ifma-notes.md delete mode 100644 net/gurk-rs/files/vendor/curve25519-dalek/docs/parallel-formulas.md delete mode 100644 net/gurk-rs/files/vendor/curve25519-dalek/src/backend/mod.rs delete mode 100644 net/gurk-rs/files/vendor/curve25519-dalek/src/backend/serial/curve_models/mod.rs delete mode 100644 net/gurk-rs/files/vendor/curve25519-dalek/src/backend/serial/fiat_u32/field.rs delete mode 100644 net/gurk-rs/files/vendor/curve25519-dalek/src/backend/serial/fiat_u32/mod.rs delete mode 100644 net/gurk-rs/files/vendor/curve25519-dalek/src/backend/serial/fiat_u64/field.rs delete mode 100644 net/gurk-rs/files/vendor/curve25519-dalek/src/backend/serial/fiat_u64/mod.rs delete mode 100644 net/gurk-rs/files/vendor/curve25519-dalek/src/backend/serial/mod.rs delete mode 100644 net/gurk-rs/files/vendor/curve25519-dalek/src/backend/serial/scalar_mul/mod.rs delete mode 100644 net/gurk-rs/files/vendor/curve25519-dalek/src/backend/serial/scalar_mul/pippenger.rs delete mode 100644 net/gurk-rs/files/vendor/curve25519-dalek/src/backend/serial/scalar_mul/precomputed_straus.rs delete mode 100644 net/gurk-rs/files/vendor/curve25519-dalek/src/backend/serial/scalar_mul/straus.rs delete mode 100644 net/gurk-rs/files/vendor/curve25519-dalek/src/backend/serial/scalar_mul/variable_base.rs delete mode 100644 net/gurk-rs/files/vendor/curve25519-dalek/src/backend/serial/scalar_mul/vartime_double_base.rs delete mode 100644 net/gurk-rs/files/vendor/curve25519-dalek/src/backend/serial/u32/constants.rs delete mode 100644 net/gurk-rs/files/vendor/curve25519-dalek/src/backend/serial/u32/field.rs delete mode 100644 net/gurk-rs/files/vendor/curve25519-dalek/src/backend/serial/u32/mod.rs delete mode 100644 net/gurk-rs/files/vendor/curve25519-dalek/src/backend/serial/u32/scalar.rs delete mode 100644 net/gurk-rs/files/vendor/curve25519-dalek/src/backend/serial/u64/constants.rs delete mode 100644 net/gurk-rs/files/vendor/curve25519-dalek/src/backend/serial/u64/field.rs delete mode 100644 net/gurk-rs/files/vendor/curve25519-dalek/src/backend/serial/u64/mod.rs delete mode 100644 net/gurk-rs/files/vendor/curve25519-dalek/src/backend/serial/u64/scalar.rs delete mode 100644 net/gurk-rs/files/vendor/curve25519-dalek/src/backend/vector/avx2/constants.rs delete mode 100644 net/gurk-rs/files/vendor/curve25519-dalek/src/backend/vector/avx2/edwards.rs delete mode 100644 net/gurk-rs/files/vendor/curve25519-dalek/src/backend/vector/avx2/field.rs delete mode 100644 net/gurk-rs/files/vendor/curve25519-dalek/src/backend/vector/avx2/mod.rs delete mode 100644 net/gurk-rs/files/vendor/curve25519-dalek/src/backend/vector/ifma/constants.rs delete mode 100644 net/gurk-rs/files/vendor/curve25519-dalek/src/backend/vector/ifma/edwards.rs delete mode 100644 net/gurk-rs/files/vendor/curve25519-dalek/src/backend/vector/ifma/field.rs delete mode 100644 net/gurk-rs/files/vendor/curve25519-dalek/src/backend/vector/ifma/mod.rs delete mode 100644 net/gurk-rs/files/vendor/curve25519-dalek/src/backend/vector/mod.rs delete mode 100644 net/gurk-rs/files/vendor/curve25519-dalek/src/backend/vector/scalar_mul/mod.rs delete mode 100644 net/gurk-rs/files/vendor/curve25519-dalek/src/backend/vector/scalar_mul/pippenger.rs delete mode 100644 net/gurk-rs/files/vendor/curve25519-dalek/src/backend/vector/scalar_mul/precomputed_straus.rs delete mode 100644 net/gurk-rs/files/vendor/curve25519-dalek/src/backend/vector/scalar_mul/straus.rs delete mode 100644 net/gurk-rs/files/vendor/curve25519-dalek/src/backend/vector/scalar_mul/variable_base.rs delete mode 100644 net/gurk-rs/files/vendor/curve25519-dalek/src/backend/vector/scalar_mul/vartime_double_base.rs delete mode 100644 net/gurk-rs/files/vendor/curve25519-dalek/src/constants.rs delete mode 100644 net/gurk-rs/files/vendor/curve25519-dalek/src/edwards.rs delete mode 100644 net/gurk-rs/files/vendor/curve25519-dalek/src/field.rs delete mode 100644 net/gurk-rs/files/vendor/curve25519-dalek/src/lib.rs delete mode 100644 net/gurk-rs/files/vendor/curve25519-dalek/src/macros.rs delete mode 100644 net/gurk-rs/files/vendor/curve25519-dalek/src/montgomery.rs delete mode 100644 net/gurk-rs/files/vendor/curve25519-dalek/src/prelude.rs delete mode 100644 net/gurk-rs/files/vendor/curve25519-dalek/src/ristretto.rs delete mode 100644 net/gurk-rs/files/vendor/curve25519-dalek/src/scalar.rs delete mode 100644 net/gurk-rs/files/vendor/curve25519-dalek/src/traits.rs delete mode 100644 net/gurk-rs/files/vendor/curve25519-dalek/src/window.rs delete mode 100644 net/gurk-rs/files/vendor/curve25519-dalek/vendor/ristretto.sage delete mode 100644 net/gurk-rs/files/vendor/libsignal-protocol/.cargo-checksum.json delete mode 100644 net/gurk-rs/files/vendor/libsignal-protocol/Cargo.toml delete mode 100644 net/gurk-rs/files/vendor/libsignal-protocol/benches/ratchet.rs delete mode 100644 net/gurk-rs/files/vendor/libsignal-protocol/benches/sealed_sender.rs delete mode 100644 net/gurk-rs/files/vendor/libsignal-protocol/benches/session.rs delete mode 100644 net/gurk-rs/files/vendor/libsignal-protocol/build.rs delete mode 100644 net/gurk-rs/files/vendor/libsignal-protocol/src/address.rs delete mode 100644 net/gurk-rs/files/vendor/libsignal-protocol/src/consts.rs delete mode 100644 net/gurk-rs/files/vendor/libsignal-protocol/src/crypto.rs delete mode 100644 net/gurk-rs/files/vendor/libsignal-protocol/src/curve.rs delete mode 100644 net/gurk-rs/files/vendor/libsignal-protocol/src/curve/curve25519.rs delete mode 100644 net/gurk-rs/files/vendor/libsignal-protocol/src/error.rs delete mode 100644 net/gurk-rs/files/vendor/libsignal-protocol/src/fingerprint.rs delete mode 100644 net/gurk-rs/files/vendor/libsignal-protocol/src/group_cipher.rs delete mode 100644 net/gurk-rs/files/vendor/libsignal-protocol/src/identity_key.rs delete mode 100644 net/gurk-rs/files/vendor/libsignal-protocol/src/lib.rs delete mode 100644 net/gurk-rs/files/vendor/libsignal-protocol/src/proto.rs delete mode 100644 net/gurk-rs/files/vendor/libsignal-protocol/src/proto/fingerprint.proto delete mode 100644 net/gurk-rs/files/vendor/libsignal-protocol/src/proto/fingerprint.rs delete mode 100644 net/gurk-rs/files/vendor/libsignal-protocol/src/proto/sealed_sender.proto delete mode 100644 net/gurk-rs/files/vendor/libsignal-protocol/src/proto/sealed_sender.rs delete mode 100644 net/gurk-rs/files/vendor/libsignal-protocol/src/proto/service.proto delete mode 100644 net/gurk-rs/files/vendor/libsignal-protocol/src/proto/service.rs delete mode 100644 net/gurk-rs/files/vendor/libsignal-protocol/src/proto/storage.proto delete mode 100644 net/gurk-rs/files/vendor/libsignal-protocol/src/proto/storage.rs delete mode 100644 net/gurk-rs/files/vendor/libsignal-protocol/src/proto/wire.proto delete mode 100644 net/gurk-rs/files/vendor/libsignal-protocol/src/proto/wire.rs delete mode 100644 net/gurk-rs/files/vendor/libsignal-protocol/src/protocol.rs delete mode 100644 net/gurk-rs/files/vendor/libsignal-protocol/src/ratchet.rs delete mode 100644 net/gurk-rs/files/vendor/libsignal-protocol/src/ratchet/keys.rs delete mode 100644 net/gurk-rs/files/vendor/libsignal-protocol/src/ratchet/params.rs delete mode 100644 net/gurk-rs/files/vendor/libsignal-protocol/src/sealed_sender.rs delete mode 100644 net/gurk-rs/files/vendor/libsignal-protocol/src/sender_keys.rs delete mode 100644 net/gurk-rs/files/vendor/libsignal-protocol/src/session.rs delete mode 100644 net/gurk-rs/files/vendor/libsignal-protocol/src/session_cipher.rs delete mode 100644 net/gurk-rs/files/vendor/libsignal-protocol/src/state.rs delete mode 100644 net/gurk-rs/files/vendor/libsignal-protocol/src/state/bundle.rs delete mode 100644 net/gurk-rs/files/vendor/libsignal-protocol/src/state/prekey.rs delete mode 100644 net/gurk-rs/files/vendor/libsignal-protocol/src/state/session.rs delete mode 100644 net/gurk-rs/files/vendor/libsignal-protocol/src/state/signed_prekey.rs delete mode 100644 net/gurk-rs/files/vendor/libsignal-protocol/src/storage.rs delete mode 100644 net/gurk-rs/files/vendor/libsignal-protocol/src/storage/inmem.rs delete mode 100644 net/gurk-rs/files/vendor/libsignal-protocol/src/storage/traits.rs delete mode 100644 net/gurk-rs/files/vendor/libsignal-protocol/src/utils.rs delete mode 100644 net/gurk-rs/files/vendor/libsignal-protocol/tests/groups.rs delete mode 100644 net/gurk-rs/files/vendor/libsignal-protocol/tests/ratchet.rs delete mode 100644 net/gurk-rs/files/vendor/libsignal-protocol/tests/sealed_sender.rs delete mode 100644 net/gurk-rs/files/vendor/libsignal-protocol/tests/session.rs delete mode 100644 net/gurk-rs/files/vendor/libsignal-protocol/tests/support/mod.rs delete mode 100644 net/gurk-rs/files/vendor/libsignal-service-hyper/.cargo-checksum.json delete mode 100644 net/gurk-rs/files/vendor/libsignal-service-hyper/Cargo.toml delete mode 100644 net/gurk-rs/files/vendor/libsignal-service-hyper/examples/registering.rs delete mode 100644 net/gurk-rs/files/vendor/libsignal-service-hyper/src/lib.rs delete mode 100644 net/gurk-rs/files/vendor/libsignal-service-hyper/src/provisioning.rs delete mode 100644 net/gurk-rs/files/vendor/libsignal-service-hyper/src/push_service.rs delete mode 100644 net/gurk-rs/files/vendor/libsignal-service-hyper/src/websocket.rs delete mode 100644 net/gurk-rs/files/vendor/libsignal-service/.cargo-checksum.json delete mode 100644 net/gurk-rs/files/vendor/libsignal-service/Cargo.toml delete mode 100644 net/gurk-rs/files/vendor/libsignal-service/build.rs delete mode 100644 net/gurk-rs/files/vendor/libsignal-service/protobuf/DecryptedGroups.proto delete mode 100644 net/gurk-rs/files/vendor/libsignal-service/protobuf/Groups.proto delete mode 100644 net/gurk-rs/files/vendor/libsignal-service/protobuf/Provisioning.proto delete mode 100644 net/gurk-rs/files/vendor/libsignal-service/protobuf/SignalService.proto delete mode 100644 net/gurk-rs/files/vendor/libsignal-service/protobuf/StickerResources.proto delete mode 100644 net/gurk-rs/files/vendor/libsignal-service/protobuf/UnidentifiedDelivery.proto delete mode 100644 net/gurk-rs/files/vendor/libsignal-service/protobuf/WebSocketResources.proto delete mode 100644 net/gurk-rs/files/vendor/libsignal-service/src/account_manager.rs delete mode 100644 net/gurk-rs/files/vendor/libsignal-service/src/attachment_cipher.rs delete mode 100644 net/gurk-rs/files/vendor/libsignal-service/src/cipher.rs delete mode 100644 net/gurk-rs/files/vendor/libsignal-service/src/configuration.rs delete mode 100644 net/gurk-rs/files/vendor/libsignal-service/src/content.rs delete mode 100644 net/gurk-rs/files/vendor/libsignal-service/src/digeststream.rs delete mode 100644 net/gurk-rs/files/vendor/libsignal-service/src/envelope.rs delete mode 100644 net/gurk-rs/files/vendor/libsignal-service/src/groups_v2/manager.rs delete mode 100644 net/gurk-rs/files/vendor/libsignal-service/src/groups_v2/mod.rs delete mode 100644 net/gurk-rs/files/vendor/libsignal-service/src/groups_v2/operations.rs delete mode 100644 net/gurk-rs/files/vendor/libsignal-service/src/groups_v2/utils.rs delete mode 100644 net/gurk-rs/files/vendor/libsignal-service/src/kat.bin.rs delete mode 100644 net/gurk-rs/files/vendor/libsignal-service/src/lib.rs delete mode 100644 net/gurk-rs/files/vendor/libsignal-service/src/messagepipe.rs delete mode 100644 net/gurk-rs/files/vendor/libsignal-service/src/models.rs delete mode 100644 net/gurk-rs/files/vendor/libsignal-service/src/pre_keys.rs delete mode 100644 net/gurk-rs/files/vendor/libsignal-service/src/profile_cipher.rs delete mode 100644 net/gurk-rs/files/vendor/libsignal-service/src/profile_name.rs delete mode 100644 net/gurk-rs/files/vendor/libsignal-service/src/proto.rs delete mode 100644 net/gurk-rs/files/vendor/libsignal-service/src/provisioning/cipher.rs delete mode 100644 net/gurk-rs/files/vendor/libsignal-service/src/provisioning/manager.rs delete mode 100644 net/gurk-rs/files/vendor/libsignal-service/src/provisioning/mod.rs delete mode 100644 net/gurk-rs/files/vendor/libsignal-service/src/provisioning/pipe.rs delete mode 100644 net/gurk-rs/files/vendor/libsignal-service/src/push_service.rs delete mode 100644 net/gurk-rs/files/vendor/libsignal-service/src/receiver.rs delete mode 100644 net/gurk-rs/files/vendor/libsignal-service/src/sealed_session_cipher.rs delete mode 100644 net/gurk-rs/files/vendor/libsignal-service/src/sender.rs delete mode 100644 net/gurk-rs/files/vendor/libsignal-service/src/service_address.rs delete mode 100644 net/gurk-rs/files/vendor/libsignal-service/src/session_store.rs delete mode 100644 net/gurk-rs/files/vendor/libsignal-service/src/utils.rs delete mode 100644 net/gurk-rs/files/vendor/poksho/.cargo-checksum.json delete mode 100644 net/gurk-rs/files/vendor/poksho/Cargo.toml delete mode 100644 net/gurk-rs/files/vendor/poksho/LICENSE delete mode 100644 net/gurk-rs/files/vendor/poksho/README.md delete mode 100644 net/gurk-rs/files/vendor/poksho/src/args.rs delete mode 100644 net/gurk-rs/files/vendor/poksho/src/errors.rs delete mode 100644 net/gurk-rs/files/vendor/poksho/src/lib.rs delete mode 100644 net/gurk-rs/files/vendor/poksho/src/proof.rs delete mode 100644 net/gurk-rs/files/vendor/poksho/src/scalar.rs delete mode 100644 net/gurk-rs/files/vendor/poksho/src/shoapi.rs delete mode 100644 net/gurk-rs/files/vendor/poksho/src/shohmacsha256.rs delete mode 100644 net/gurk-rs/files/vendor/poksho/src/shosha256.rs delete mode 100644 net/gurk-rs/files/vendor/poksho/src/sign.rs delete mode 100644 net/gurk-rs/files/vendor/poksho/src/simple_types.rs delete mode 100644 net/gurk-rs/files/vendor/poksho/src/statement.rs delete mode 100644 net/gurk-rs/files/vendor/presage/.cargo-checksum.json delete mode 100644 net/gurk-rs/files/vendor/presage/.github/workflows/ci.yaml delete mode 100644 net/gurk-rs/files/vendor/presage/Cargo.toml delete mode 100644 net/gurk-rs/files/vendor/presage/LICENSE.md delete mode 100644 net/gurk-rs/files/vendor/presage/README.md delete mode 100644 net/gurk-rs/files/vendor/presage/examples/cli.rs delete mode 100644 net/gurk-rs/files/vendor/presage/examples/link.rs delete mode 100644 net/gurk-rs/files/vendor/presage/examples/register.rs delete mode 100644 net/gurk-rs/files/vendor/presage/rustfmt.toml delete mode 100644 net/gurk-rs/files/vendor/presage/src/cache.rs delete mode 100644 net/gurk-rs/files/vendor/presage/src/config/mod.rs delete mode 100644 net/gurk-rs/files/vendor/presage/src/config/sled.rs delete mode 100644 net/gurk-rs/files/vendor/presage/src/errors.rs delete mode 100644 net/gurk-rs/files/vendor/presage/src/lib.rs delete mode 100644 net/gurk-rs/files/vendor/presage/src/manager.rs delete mode 100644 net/gurk-rs/files/vendor/zkgroup/.cargo-checksum.json delete mode 100644 net/gurk-rs/files/vendor/zkgroup/Cargo.toml delete mode 100644 net/gurk-rs/files/vendor/zkgroup/benches/zkgroup_benchmarks.rs delete mode 100644 net/gurk-rs/files/vendor/zkgroup/rustfmt.license-template delete mode 100644 net/gurk-rs/files/vendor/zkgroup/rustfmt.toml delete mode 100755 net/gurk-rs/files/vendor/zkgroup/scripts/format-code delete mode 100644 net/gurk-rs/files/vendor/zkgroup/src/api/auth/auth_credential.rs delete mode 100644 net/gurk-rs/files/vendor/zkgroup/src/api/auth/auth_credential_presentation.rs delete mode 100644 net/gurk-rs/files/vendor/zkgroup/src/api/auth/auth_credential_response.rs delete mode 100644 net/gurk-rs/files/vendor/zkgroup/src/api/auth/mod.rs delete mode 100644 net/gurk-rs/files/vendor/zkgroup/src/api/groups/group_params.rs delete mode 100644 net/gurk-rs/files/vendor/zkgroup/src/api/groups/mod.rs delete mode 100644 net/gurk-rs/files/vendor/zkgroup/src/api/groups/profile_key_ciphertext.rs delete mode 100644 net/gurk-rs/files/vendor/zkgroup/src/api/groups/uuid_ciphertext.rs delete mode 100644 net/gurk-rs/files/vendor/zkgroup/src/api/mod.rs delete mode 100644 net/gurk-rs/files/vendor/zkgroup/src/api/profiles/mod.rs delete mode 100644 net/gurk-rs/files/vendor/zkgroup/src/api/profiles/profile_key.rs delete mode 100644 net/gurk-rs/files/vendor/zkgroup/src/api/profiles/profile_key_commitment.rs delete mode 100644 net/gurk-rs/files/vendor/zkgroup/src/api/profiles/profile_key_credential.rs delete mode 100644 net/gurk-rs/files/vendor/zkgroup/src/api/profiles/profile_key_credential_presentation.rs delete mode 100644 net/gurk-rs/files/vendor/zkgroup/src/api/profiles/profile_key_credential_request.rs delete mode 100644 net/gurk-rs/files/vendor/zkgroup/src/api/profiles/profile_key_credential_request_context.rs delete mode 100644 net/gurk-rs/files/vendor/zkgroup/src/api/profiles/profile_key_credential_response.rs delete mode 100644 net/gurk-rs/files/vendor/zkgroup/src/api/profiles/profile_key_version.rs delete mode 100644 net/gurk-rs/files/vendor/zkgroup/src/api/server_params.rs delete mode 100644 net/gurk-rs/files/vendor/zkgroup/src/common/constants.rs delete mode 100644 net/gurk-rs/files/vendor/zkgroup/src/common/errors.rs delete mode 100644 net/gurk-rs/files/vendor/zkgroup/src/common/mod.rs delete mode 100644 net/gurk-rs/files/vendor/zkgroup/src/common/sho.rs delete mode 100644 net/gurk-rs/files/vendor/zkgroup/src/common/simple_types.rs delete mode 100644 net/gurk-rs/files/vendor/zkgroup/src/crypto/credentials.rs delete mode 100644 net/gurk-rs/files/vendor/zkgroup/src/crypto/mod.rs delete mode 100644 net/gurk-rs/files/vendor/zkgroup/src/crypto/profile_key_commitment.rs delete mode 100644 net/gurk-rs/files/vendor/zkgroup/src/crypto/profile_key_credential_request.rs delete mode 100644 net/gurk-rs/files/vendor/zkgroup/src/crypto/profile_key_encryption.rs delete mode 100644 net/gurk-rs/files/vendor/zkgroup/src/crypto/profile_key_struct.rs delete mode 100644 net/gurk-rs/files/vendor/zkgroup/src/crypto/proofs.rs delete mode 100644 net/gurk-rs/files/vendor/zkgroup/src/crypto/signature.rs delete mode 100644 net/gurk-rs/files/vendor/zkgroup/src/crypto/uid_encryption.rs delete mode 100644 net/gurk-rs/files/vendor/zkgroup/src/crypto/uid_struct.rs delete mode 100644 net/gurk-rs/files/vendor/zkgroup/src/ffi/constants.rs delete mode 100644 net/gurk-rs/files/vendor/zkgroup/src/ffi/ffiapi.rs delete mode 100644 net/gurk-rs/files/vendor/zkgroup/src/ffi/ffiapijava.rs delete mode 100644 net/gurk-rs/files/vendor/zkgroup/src/ffi/mod.rs delete mode 100644 net/gurk-rs/files/vendor/zkgroup/src/ffi/simpleapi.rs delete mode 100644 net/gurk-rs/files/vendor/zkgroup/src/lib.rs delete mode 100644 net/gurk-rs/files/vendor/zkgroup/tests/integration_tests.rs diff --git a/net/gurk-rs/Makefile b/net/gurk-rs/Makefile index 33f6b87..246b3d4 100644 --- a/net/gurk-rs/Makefile +++ b/net/gurk-rs/Makefile @@ -1,41 +1,36 @@ COMMENT = Signal Messenger client for terminal -V = 0.2.5 GH_ACCOUNT = boxdot GH_PROJECT = gurk-rs -GH_TAGNAME = v${V} +GH_TAGNAME = v0.3.0 CATEGORIES = net MAINTAINER = Stefan Hagen -# LICENSE +# AGPL 3.0 PERMIT_PACKAGE = Yes -# as devel/cargo MODULES adds DISTFILES, GH_* didn't -DISTFILES += ${DISTNAME}${EXTRACT_SUFX} +DISTFILES = ${DISTNAME}{master}${EXTRACT_SUFX} + +# vendor files (see $FILESDIR/config) +MASTER_SITES0 = https://codevoid.de/h/ +DISTFILES += ${DISTNAME}-vendorfiles${EXTRACT_SUFX}:0 MODULES = devel/cargo -.include "crates.inc" +#MODCARGO_NO_DEFAULT_FEATURES = Yes WANTLIB = c c++abi pthread -#LIB_DEPENDS = -#RUN_DEPENDS = -#BUILD_DEPENDS = - -#TEST_DEPENDS = - CONFIGURE_STYLE = cargo -#MAKE_FLAGS = - -#NO_TEST = Yes -#TEST_TARGET = +post-extract: + mv ${WRKDIR}/vendor ${WRKSRC}/vendor; pre-configure: - cat ${FILESDIR}/config >> ${WRKSRC}/.cargo/config.toml; \ - cp -rf ${FILESDIR}/vendor ${WRKSRC}/ + cat ${FILESDIR}/config >> ${WRKSRC}/.cargo/config + +.include "crates.inc" .include diff --git a/net/gurk-rs/crates.inc b/net/gurk-rs/crates.inc index 2c12dd6..51f9073 100644 --- a/net/gurk-rs/crates.inc +++ b/net/gurk-rs/crates.inc @@ -1,360 +1,378 @@ # run: make modcargo-gen-crates-licenses MODCARGO_CRATES += adler 1.0.2 -MODCARGO_CRATES += aead 0.4.2 -MODCARGO_CRATES += aes 0.7.4 -MODCARGO_CRATES += aes-gcm 0.9.2 -MODCARGO_CRATES += aes-gcm-siv 0.10.1 -MODCARGO_CRATES += aho-corasick 0.7.18 +MODCARGO_CRATES += aead 0.4.3 +MODCARGO_CRATES += aes 0.7.5 +MODCARGO_CRATES += aes-gcm 0.9.4 +MODCARGO_CRATES += aes-gcm-siv 0.10.3 +MODCARGO_CRATES += aho-corasick 0.7.19 MODCARGO_CRATES += android_system_properties 0.1.5 -MODCARGO_CRATES += ansi_term 0.11.0 +MODCARGO_CRATES += anes 0.1.6 MODCARGO_CRATES += ansi_term 0.12.1 -MODCARGO_CRATES += anyhow 1.0.42 +MODCARGO_CRATES += anyhow 1.0.64 MODCARGO_CRATES += arrayref 0.3.6 MODCARGO_CRATES += arrayvec 0.5.2 -MODCARGO_CRATES += ascii 0.9.3 -MODCARGO_CRATES += async-broadcast 0.3.4 -MODCARGO_CRATES += async-channel 1.6.1 +MODCARGO_CRATES += async-broadcast 0.4.1 +MODCARGO_CRATES += async-channel 1.7.1 MODCARGO_CRATES += async-executor 1.4.1 -MODCARGO_CRATES += async-io 1.6.0 +MODCARGO_CRATES += async-io 1.9.0 MODCARGO_CRATES += async-lock 2.5.0 MODCARGO_CRATES += async-recursion 0.3.2 -MODCARGO_CRATES += async-task 4.2.0 -MODCARGO_CRATES += async-trait 0.1.51 -MODCARGO_CRATES += async-tungstenite 0.15.0 +MODCARGO_CRATES += async-task 4.3.0 +MODCARGO_CRATES += async-trait 0.1.57 +MODCARGO_CRATES += async-tungstenite 0.17.2 MODCARGO_CRATES += atty 0.2.14 MODCARGO_CRATES += autocfg 1.1.0 MODCARGO_CRATES += base64 0.12.3 MODCARGO_CRATES += base64 0.13.0 MODCARGO_CRATES += bincode 1.3.3 -MODCARGO_CRATES += bitflags 1.2.1 +MODCARGO_CRATES += bitflags 1.3.2 MODCARGO_CRATES += block 0.1.6 -MODCARGO_CRATES += block-buffer 0.7.3 MODCARGO_CRATES += block-buffer 0.9.0 +MODCARGO_CRATES += block-buffer 0.10.3 MODCARGO_CRATES += block-modes 0.8.1 -MODCARGO_CRATES += block-padding 0.1.5 MODCARGO_CRATES += block-padding 0.2.1 -MODCARGO_CRATES += bstr 0.2.16 -MODCARGO_CRATES += bumpalo 3.7.0 -MODCARGO_CRATES += byte-tools 0.3.1 +MODCARGO_CRATES += bstr 0.2.17 +MODCARGO_CRATES += bumpalo 3.11.0 MODCARGO_CRATES += byteorder 1.4.3 -MODCARGO_CRATES += bytes 1.0.1 -MODCARGO_CRATES += cache-padded 1.1.1 +MODCARGO_CRATES += bytes 1.2.1 +MODCARGO_CRATES += cache-padded 1.2.0 MODCARGO_CRATES += cassowary 0.3.0 -MODCARGO_CRATES += cc 1.0.69 -MODCARGO_CRATES += cesu8 1.1.0 +MODCARGO_CRATES += cast 0.3.0 +MODCARGO_CRATES += cc 1.0.73 MODCARGO_CRATES += cfg-if 1.0.0 MODCARGO_CRATES += checked_int_cast 1.0.0 MODCARGO_CRATES += chrono 0.4.22 +MODCARGO_CRATES += ciborium 0.2.0 +MODCARGO_CRATES += ciborium-io 0.2.0 +MODCARGO_CRATES += ciborium-ll 0.2.0 MODCARGO_CRATES += cipher 0.3.0 -MODCARGO_CRATES += clap 2.33.3 -MODCARGO_CRATES += combine 3.8.1 -MODCARGO_CRATES += concurrent-queue 1.2.2 -MODCARGO_CRATES += core-foundation 0.9.1 +MODCARGO_CRATES += clap 3.2.23 +MODCARGO_CRATES += clap 4.0.18 +MODCARGO_CRATES += clap_derive 4.0.18 +MODCARGO_CRATES += clap_lex 0.2.4 +MODCARGO_CRATES += clap_lex 0.3.0 +MODCARGO_CRATES += cmake 0.1.48 +MODCARGO_CRATES += concurrent-queue 1.2.4 +MODCARGO_CRATES += core-foundation 0.9.3 MODCARGO_CRATES += core-foundation-sys 0.8.3 -MODCARGO_CRATES += cpufeatures 0.1.5 -MODCARGO_CRATES += crc32fast 1.2.1 -MODCARGO_CRATES += crossbeam-channel 0.5.5 -MODCARGO_CRATES += crossbeam-epoch 0.9.5 -MODCARGO_CRATES += crossbeam-utils 0.8.9 +MODCARGO_CRATES += cpufeatures 0.2.5 +MODCARGO_CRATES += crc32fast 1.3.2 +MODCARGO_CRATES += criterion 0.4.0 +MODCARGO_CRATES += criterion-plot 0.5.0 +MODCARGO_CRATES += crossbeam-channel 0.5.6 +MODCARGO_CRATES += crossbeam-deque 0.8.2 +MODCARGO_CRATES += crossbeam-epoch 0.9.10 +MODCARGO_CRATES += crossbeam-utils 0.8.11 MODCARGO_CRATES += crossterm 0.19.0 +MODCARGO_CRATES += crossterm 0.23.2 MODCARGO_CRATES += crossterm_winapi 0.7.0 -MODCARGO_CRATES += crypto-mac 0.7.0 +MODCARGO_CRATES += crossterm_winapi 0.9.0 +MODCARGO_CRATES += crypto-common 0.1.6 MODCARGO_CRATES += crypto-mac 0.11.1 -MODCARGO_CRATES += ct-logs 0.8.0 -MODCARGO_CRATES += ctr 0.7.0 -MODCARGO_CRATES += curve25519-dalek 3.1.0 +MODCARGO_CRATES += ctr 0.8.0 MODCARGO_CRATES += derivative 2.2.0 -MODCARGO_CRATES += digest 0.8.1 MODCARGO_CRATES += digest 0.9.0 +MODCARGO_CRATES += digest 0.10.3 MODCARGO_CRATES += dirs 3.0.2 +MODCARGO_CRATES += dirs 4.0.0 MODCARGO_CRATES += dirs-next 2.0.0 -MODCARGO_CRATES += dirs-sys 0.3.6 +MODCARGO_CRATES += dirs-sys 0.3.7 MODCARGO_CRATES += dirs-sys-next 0.1.2 MODCARGO_CRATES += displaydoc 0.2.3 -MODCARGO_CRATES += easy-parallel 3.2.0 -MODCARGO_CRATES += either 1.6.1 +MODCARGO_CRATES += either 1.8.0 MODCARGO_CRATES += emoji 0.2.1 MODCARGO_CRATES += enumflags2 0.7.5 MODCARGO_CRATES += enumflags2_derive 0.7.4 MODCARGO_CRATES += env_logger 0.8.4 -MODCARGO_CRATES += error-chain 0.12.4 -MODCARGO_CRATES += event-listener 2.5.2 -MODCARGO_CRATES += fake-simd 0.1.2 -MODCARGO_CRATES += fastrand 1.4.1 -MODCARGO_CRATES += filetime 0.2.14 -MODCARGO_CRATES += fixedbitset 0.2.0 -MODCARGO_CRATES += fixedbitset 0.4.1 -MODCARGO_CRATES += flate2 1.0.20 +MODCARGO_CRATES += event-listener 2.5.3 +MODCARGO_CRATES += fastrand 1.8.0 +MODCARGO_CRATES += filetime 0.2.17 +MODCARGO_CRATES += fixedbitset 0.4.2 +MODCARGO_CRATES += flate2 1.0.24 MODCARGO_CRATES += fnv 1.0.7 MODCARGO_CRATES += form_urlencoded 1.0.1 MODCARGO_CRATES += fs2 0.4.3 -MODCARGO_CRATES += futures 0.3.15 -MODCARGO_CRATES += futures-channel 0.3.15 -MODCARGO_CRATES += futures-core 0.3.15 -MODCARGO_CRATES += futures-executor 0.3.15 -MODCARGO_CRATES += futures-io 0.3.15 +MODCARGO_CRATES += futures 0.3.24 +MODCARGO_CRATES += futures-channel 0.3.24 +MODCARGO_CRATES += futures-core 0.3.24 +MODCARGO_CRATES += futures-executor 0.3.24 +MODCARGO_CRATES += futures-io 0.3.24 MODCARGO_CRATES += futures-lite 1.12.0 -MODCARGO_CRATES += futures-macro 0.3.15 -MODCARGO_CRATES += futures-sink 0.3.15 -MODCARGO_CRATES += futures-task 0.3.15 -MODCARGO_CRATES += futures-util 0.3.15 +MODCARGO_CRATES += futures-macro 0.3.24 +MODCARGO_CRATES += futures-sink 0.3.24 +MODCARGO_CRATES += futures-task 0.3.24 +MODCARGO_CRATES += futures-util 0.3.24 MODCARGO_CRATES += fuzzy-matcher 0.3.7 MODCARGO_CRATES += fxhash 0.2.1 -MODCARGO_CRATES += generic-array 0.12.4 -MODCARGO_CRATES += generic-array 0.14.4 +MODCARGO_CRATES += generic-array 0.14.6 MODCARGO_CRATES += getopts 0.2.21 MODCARGO_CRATES += getrandom 0.1.16 -MODCARGO_CRATES += getrandom 0.2.3 -MODCARGO_CRATES += gh-emoji 1.0.3 -MODCARGO_CRATES += ghash 0.4.2 -MODCARGO_CRATES += hashbrown 0.11.2 -MODCARGO_CRATES += headers 0.3.4 +MODCARGO_CRATES += getrandom 0.2.7 +MODCARGO_CRATES += gh-emoji 1.0.7 +MODCARGO_CRATES += ghash 0.4.4 +MODCARGO_CRATES += half 1.8.2 +MODCARGO_CRATES += hashbrown 0.12.3 +MODCARGO_CRATES += headers 0.3.8 MODCARGO_CRATES += headers-core 0.2.0 MODCARGO_CRATES += heck 0.3.3 +MODCARGO_CRATES += heck 0.4.0 MODCARGO_CRATES += hermit-abi 0.1.19 MODCARGO_CRATES += hex 0.4.3 MODCARGO_CRATES += hkdf 0.11.0 -MODCARGO_CRATES += hmac 0.7.1 +MODCARGO_CRATES += hkdf 0.12.3 MODCARGO_CRATES += hmac 0.11.0 +MODCARGO_CRATES += hmac 0.12.1 MODCARGO_CRATES += hostname 0.3.1 -MODCARGO_CRATES += http 0.2.4 -MODCARGO_CRATES += http-body 0.4.2 -MODCARGO_CRATES += httparse 1.4.1 -MODCARGO_CRATES += httpdate 1.0.1 -MODCARGO_CRATES += hyper 0.14.11 -MODCARGO_CRATES += hyper-rustls 0.22.1 +MODCARGO_CRATES += http 0.2.8 +MODCARGO_CRATES += http-body 0.4.5 +MODCARGO_CRATES += httparse 1.8.0 +MODCARGO_CRATES += httpdate 1.0.2 +MODCARGO_CRATES += hyper 0.14.20 +MODCARGO_CRATES += hyper-rustls 0.23.0 MODCARGO_CRATES += hyper-timeout 0.4.1 MODCARGO_CRATES += iana-time-zone 0.1.47 MODCARGO_CRATES += idna 0.2.3 -MODCARGO_CRATES += indexmap 1.7.0 -MODCARGO_CRATES += instant 0.1.10 +MODCARGO_CRATES += indexmap 1.9.1 +MODCARGO_CRATES += instant 0.1.12 MODCARGO_CRATES += itertools 0.9.0 -MODCARGO_CRATES += itertools 0.10.1 -MODCARGO_CRATES += itoa 0.4.7 -MODCARGO_CRATES += itoa 1.0.2 -MODCARGO_CRATES += jni 0.16.0 -MODCARGO_CRATES += jni-sys 0.3.0 +MODCARGO_CRATES += itertools 0.10.3 +MODCARGO_CRATES += itoa 1.0.3 MODCARGO_CRATES += js-sys 0.3.59 MODCARGO_CRATES += lazy_static 1.4.0 MODCARGO_CRATES += lexical-core 0.7.6 -MODCARGO_CRATES += libc 0.2.126 -MODCARGO_CRATES += linked-hash-map 0.5.4 -MODCARGO_CRATES += lock_api 0.4.7 -MODCARGO_CRATES += log 0.4.14 -MODCARGO_CRATES += log-panics 2.0.0 +MODCARGO_CRATES += libc 0.2.132 +MODCARGO_CRATES += linked-hash-map 0.5.6 +MODCARGO_CRATES += lock_api 0.4.8 +MODCARGO_CRATES += log 0.4.17 +MODCARGO_CRATES += log-panics 2.1.0 MODCARGO_CRATES += lru-cache 0.1.2 -MODCARGO_CRATES += mac-notification-sys 0.5.2 +MODCARGO_CRATES += mac-notification-sys 0.5.6 MODCARGO_CRATES += malloc_buf 0.0.6 MODCARGO_CRATES += match_cfg 0.1.0 -MODCARGO_CRATES += matches 0.1.8 -MODCARGO_CRATES += memchr 2.4.0 -MODCARGO_CRATES += memoffset 0.6.4 +MODCARGO_CRATES += matches 0.1.9 +MODCARGO_CRATES += memchr 2.5.0 +MODCARGO_CRATES += memoffset 0.6.5 MODCARGO_CRATES += mime 0.3.16 -MODCARGO_CRATES += mime_guess 2.0.3 -MODCARGO_CRATES += miniz_oxide 0.4.4 -MODCARGO_CRATES += mio 0.7.13 +MODCARGO_CRATES += mime_guess 2.0.4 +MODCARGO_CRATES += miniz_oxide 0.5.4 +MODCARGO_CRATES += mio 0.7.14 +MODCARGO_CRATES += mio 0.8.4 MODCARGO_CRATES += miow 0.3.7 -MODCARGO_CRATES += mpart-async 0.5.0 +MODCARGO_CRATES += mpart-async 0.6.1 MODCARGO_CRATES += multimap 0.8.3 MODCARGO_CRATES += nix 0.23.1 MODCARGO_CRATES += nom 5.1.2 -MODCARGO_CRATES += notify-rust 4.5.8 -MODCARGO_CRATES += ntapi 0.3.6 -MODCARGO_CRATES += num-integer 0.1.44 -MODCARGO_CRATES += num-traits 0.2.14 -MODCARGO_CRATES += num_cpus 1.13.0 -MODCARGO_CRATES += num_enum 0.5.2 -MODCARGO_CRATES += num_enum_derive 0.5.2 +MODCARGO_CRATES += notify-rust 4.5.10 +MODCARGO_CRATES += ntapi 0.3.7 +MODCARGO_CRATES += num-integer 0.1.45 +MODCARGO_CRATES += num-traits 0.2.15 +MODCARGO_CRATES += num_cpus 1.13.1 +MODCARGO_CRATES += num_enum 0.5.7 +MODCARGO_CRATES += num_enum_derive 0.5.7 MODCARGO_CRATES += num_threads 0.1.6 MODCARGO_CRATES += objc 0.2.7 MODCARGO_CRATES += objc-foundation 0.1.1 MODCARGO_CRATES += objc_id 0.1.1 -MODCARGO_CRATES += once_cell 1.13.1 +MODCARGO_CRATES += once_cell 1.14.0 MODCARGO_CRATES += oncemutex 0.1.1 -MODCARGO_CRATES += opaque-debug 0.2.3 +MODCARGO_CRATES += oorandom 11.1.3 MODCARGO_CRATES += opaque-debug 0.3.0 MODCARGO_CRATES += opener 0.5.0 -MODCARGO_CRATES += openssl-probe 0.1.4 +MODCARGO_CRATES += openssl-probe 0.1.5 MODCARGO_CRATES += ordered-stream 0.0.1 +MODCARGO_CRATES += os_str_bytes 6.3.1 MODCARGO_CRATES += parking 2.0.0 -MODCARGO_CRATES += parking_lot 0.11.1 -MODCARGO_CRATES += parking_lot_core 0.8.3 +MODCARGO_CRATES += parking_lot 0.11.2 +MODCARGO_CRATES += parking_lot 0.12.1 +MODCARGO_CRATES += parking_lot_core 0.8.5 +MODCARGO_CRATES += parking_lot_core 0.9.3 MODCARGO_CRATES += percent-encoding 2.1.0 -MODCARGO_CRATES += petgraph 0.5.1 -MODCARGO_CRATES += petgraph 0.6.0 +MODCARGO_CRATES += petgraph 0.6.2 MODCARGO_CRATES += phf 0.8.0 +MODCARGO_CRATES += phf 0.11.1 MODCARGO_CRATES += phf_generator 0.8.0 MODCARGO_CRATES += phf_macros 0.8.0 MODCARGO_CRATES += phf_shared 0.8.0 +MODCARGO_CRATES += phf_shared 0.11.1 MODCARGO_CRATES += phonenumber 0.3.1+8.12.9 -MODCARGO_CRATES += pin-project 1.0.7 -MODCARGO_CRATES += pin-project-internal 1.0.7 -MODCARGO_CRATES += pin-project-lite 0.2.7 +MODCARGO_CRATES += pin-project-lite 0.2.9 MODCARGO_CRATES += pin-utils 0.1.0 -MODCARGO_CRATES += polling 2.1.0 -MODCARGO_CRATES += polyval 0.5.1 -MODCARGO_CRATES += ppv-lite86 0.2.10 -MODCARGO_CRATES += proc-macro-crate 1.0.0 +MODCARGO_CRATES += plotters 0.3.4 +MODCARGO_CRATES += plotters-backend 0.3.4 +MODCARGO_CRATES += plotters-svg 0.3.3 +MODCARGO_CRATES += polling 2.3.0 +MODCARGO_CRATES += polyval 0.5.3 +MODCARGO_CRATES += ppv-lite86 0.2.16 +MODCARGO_CRATES += proc-macro-crate 1.2.1 MODCARGO_CRATES += proc-macro-error 1.0.4 MODCARGO_CRATES += proc-macro-error-attr 1.0.4 MODCARGO_CRATES += proc-macro-hack 0.5.19 -MODCARGO_CRATES += proc-macro-nested 0.1.7 -MODCARGO_CRATES += proc-macro2 1.0.27 -MODCARGO_CRATES += prost 0.8.0 +MODCARGO_CRATES += proc-macro2 1.0.43 MODCARGO_CRATES += prost 0.9.0 -MODCARGO_CRATES += prost-build 0.8.0 +MODCARGO_CRATES += prost 0.10.4 MODCARGO_CRATES += prost-build 0.9.0 -MODCARGO_CRATES += prost-derive 0.8.0 +MODCARGO_CRATES += prost-build 0.10.4 MODCARGO_CRATES += prost-derive 0.9.0 -MODCARGO_CRATES += prost-types 0.8.0 +MODCARGO_CRATES += prost-derive 0.10.1 MODCARGO_CRATES += prost-types 0.9.0 +MODCARGO_CRATES += prost-types 0.10.1 MODCARGO_CRATES += pulldown-cmark 0.8.0 -MODCARGO_CRATES += qr2term 0.2.2 +MODCARGO_CRATES += qr2term 0.3.0 MODCARGO_CRATES += qrcode 0.12.0 MODCARGO_CRATES += quick-xml 0.18.1 +MODCARGO_CRATES += quick-xml 0.23.1 MODCARGO_CRATES += quickcheck 1.0.3 MODCARGO_CRATES += quickcheck_macros 1.0.0 -MODCARGO_CRATES += quote 1.0.9 +MODCARGO_CRATES += quote 1.0.21 MODCARGO_CRATES += rand 0.7.3 -MODCARGO_CRATES += rand 0.8.4 +MODCARGO_CRATES += rand 0.8.5 MODCARGO_CRATES += rand_chacha 0.2.2 MODCARGO_CRATES += rand_chacha 0.3.1 MODCARGO_CRATES += rand_core 0.5.1 MODCARGO_CRATES += rand_core 0.6.3 MODCARGO_CRATES += rand_hc 0.2.0 -MODCARGO_CRATES += rand_hc 0.3.1 MODCARGO_CRATES += rand_pcg 0.2.1 -MODCARGO_CRATES += redox_syscall 0.2.9 -MODCARGO_CRATES += redox_users 0.4.0 -MODCARGO_CRATES += regex 1.5.6 +MODCARGO_CRATES += rayon 1.5.3 +MODCARGO_CRATES += rayon-core 1.9.3 +MODCARGO_CRATES += redox_syscall 0.2.16 +MODCARGO_CRATES += redox_users 0.4.3 +MODCARGO_CRATES += regex 1.6.0 MODCARGO_CRATES += regex-automata 0.1.10 MODCARGO_CRATES += regex-cache 0.2.1 -MODCARGO_CRATES += regex-syntax 0.6.26 +MODCARGO_CRATES += regex-syntax 0.6.27 MODCARGO_CRATES += remove_dir_all 0.5.3 MODCARGO_CRATES += ring 0.16.20 -MODCARGO_CRATES += rustls 0.19.1 -MODCARGO_CRATES += rustls-native-certs 0.5.0 -MODCARGO_CRATES += ryu 1.0.5 +MODCARGO_CRATES += rustls 0.20.6 +MODCARGO_CRATES += rustls-native-certs 0.6.2 +MODCARGO_CRATES += rustls-pemfile 0.3.0 +MODCARGO_CRATES += rustls-pemfile 1.0.1 +MODCARGO_CRATES += ryu 1.0.11 MODCARGO_CRATES += same-file 1.0.6 -MODCARGO_CRATES += schannel 0.1.19 +MODCARGO_CRATES += schannel 0.1.20 MODCARGO_CRATES += scopeguard 1.1.0 -MODCARGO_CRATES += sct 0.6.1 -MODCARGO_CRATES += security-framework 2.3.1 -MODCARGO_CRATES += security-framework-sys 2.3.0 -MODCARGO_CRATES += semver 1.0.3 -MODCARGO_CRATES += serde 1.0.126 -MODCARGO_CRATES += serde_derive 1.0.126 -MODCARGO_CRATES += serde_json 1.0.64 -MODCARGO_CRATES += serde_repr 0.1.7 -MODCARGO_CRATES += sha-1 0.9.6 +MODCARGO_CRATES += sct 0.7.0 +MODCARGO_CRATES += security-framework 2.7.0 +MODCARGO_CRATES += security-framework-sys 2.6.1 +MODCARGO_CRATES += semver 1.0.13 +MODCARGO_CRATES += serde 1.0.144 +MODCARGO_CRATES += serde_derive 1.0.144 +MODCARGO_CRATES += serde_json 1.0.85 +MODCARGO_CRATES += serde_repr 0.1.9 +MODCARGO_CRATES += sha-1 0.10.0 MODCARGO_CRATES += sha1 0.6.1 +MODCARGO_CRATES += sha1 0.10.4 MODCARGO_CRATES += sha1_smol 1.0.0 -MODCARGO_CRATES += sha2 0.8.2 -MODCARGO_CRATES += sha2 0.9.5 +MODCARGO_CRATES += sha2 0.9.9 +MODCARGO_CRATES += sha2 0.10.5 MODCARGO_CRATES += sharded-slab 0.1.4 MODCARGO_CRATES += signal-hook 0.1.17 +MODCARGO_CRATES += signal-hook 0.3.14 +MODCARGO_CRATES += signal-hook-mio 0.2.3 MODCARGO_CRATES += signal-hook-registry 1.4.0 -MODCARGO_CRATES += siphasher 0.3.5 -MODCARGO_CRATES += slab 0.4.3 -MODCARGO_CRATES += sled 0.34.6 -MODCARGO_CRATES += smallvec 1.6.1 +MODCARGO_CRATES += siphasher 0.3.10 +MODCARGO_CRATES += slab 0.4.7 +MODCARGO_CRATES += sled 0.34.7 +MODCARGO_CRATES += smallvec 1.9.0 MODCARGO_CRATES += smawk 0.3.1 -MODCARGO_CRATES += socket2 0.4.0 +MODCARGO_CRATES += socket2 0.4.7 MODCARGO_CRATES += spin 0.5.2 MODCARGO_CRATES += static_assertions 1.1.0 -MODCARGO_CRATES += strsim 0.8.0 -MODCARGO_CRATES += structopt 0.3.22 -MODCARGO_CRATES += structopt-derive 0.4.15 +MODCARGO_CRATES += strsim 0.10.0 MODCARGO_CRATES += strum 0.22.0 MODCARGO_CRATES += strum_macros 0.22.0 -MODCARGO_CRATES += subtle 1.0.0 MODCARGO_CRATES += subtle 2.4.1 -MODCARGO_CRATES += syn 1.0.73 -MODCARGO_CRATES += synstructure 0.12.5 +MODCARGO_CRATES += syn 1.0.99 +MODCARGO_CRATES += synstructure 0.12.6 MODCARGO_CRATES += tar 0.4.38 -MODCARGO_CRATES += tempfile 3.2.0 -MODCARGO_CRATES += textwrap 0.11.0 +MODCARGO_CRATES += tauri-winrt-notification 0.1.0 +MODCARGO_CRATES += tempfile 3.3.0 +MODCARGO_CRATES += termcolor 1.1.3 MODCARGO_CRATES += textwrap 0.14.2 -MODCARGO_CRATES += thiserror 1.0.30 -MODCARGO_CRATES += thiserror-impl 1.0.30 +MODCARGO_CRATES += textwrap 0.16.0 +MODCARGO_CRATES += thiserror 1.0.34 +MODCARGO_CRATES += thiserror-impl 1.0.34 MODCARGO_CRATES += thread_local 1.1.4 MODCARGO_CRATES += time 0.1.44 -MODCARGO_CRATES += time 0.3.9 -MODCARGO_CRATES += tinyvec 1.2.0 +MODCARGO_CRATES += time 0.3.14 +MODCARGO_CRATES += tinytemplate 1.2.1 +MODCARGO_CRATES += tinyvec 1.6.0 MODCARGO_CRATES += tinyvec_macros 0.1.0 -MODCARGO_CRATES += tokio 1.16.1 -MODCARGO_CRATES += tokio-io-timeout 1.1.1 +MODCARGO_CRATES += tokio 1.21.0 +MODCARGO_CRATES += tokio-io-timeout 1.2.0 MODCARGO_CRATES += tokio-macros 1.8.0 -MODCARGO_CRATES += tokio-rustls 0.22.0 -MODCARGO_CRATES += tokio-stream 0.1.7 -MODCARGO_CRATES += tokio-util 0.6.7 -MODCARGO_CRATES += toml 0.5.8 -MODCARGO_CRATES += tower-service 0.3.1 -MODCARGO_CRATES += tracing 0.1.35 +MODCARGO_CRATES += tokio-rustls 0.23.4 +MODCARGO_CRATES += tokio-stream 0.1.9 +MODCARGO_CRATES += tokio-util 0.6.10 +MODCARGO_CRATES += toml 0.5.9 +MODCARGO_CRATES += tower-service 0.3.2 +MODCARGO_CRATES += tracing 0.1.36 MODCARGO_CRATES += tracing-appender 0.2.2 -MODCARGO_CRATES += tracing-attributes 0.1.21 -MODCARGO_CRATES += tracing-core 0.1.27 +MODCARGO_CRATES += tracing-attributes 0.1.22 +MODCARGO_CRATES += tracing-core 0.1.29 MODCARGO_CRATES += tracing-log 0.1.3 -MODCARGO_CRATES += tracing-subscriber 0.3.11 +MODCARGO_CRATES += tracing-subscriber 0.3.15 MODCARGO_CRATES += try-lock 0.2.3 MODCARGO_CRATES += tui 0.15.0 -MODCARGO_CRATES += tungstenite 0.15.0 -MODCARGO_CRATES += twoway 0.2.2 -MODCARGO_CRATES += typenum 1.13.0 -MODCARGO_CRATES += unchecked-index 0.2.2 +MODCARGO_CRATES += tungstenite 0.17.3 +MODCARGO_CRATES += typenum 1.15.0 +MODCARGO_CRATES += uds_windows 1.0.2 MODCARGO_CRATES += unicase 2.6.0 -MODCARGO_CRATES += unicode-bidi 0.3.5 -MODCARGO_CRATES += unicode-linebreak 0.1.1 -MODCARGO_CRATES += unicode-normalization 0.1.19 -MODCARGO_CRATES += unicode-segmentation 1.8.0 -MODCARGO_CRATES += unicode-width 0.1.8 -MODCARGO_CRATES += unicode-xid 0.2.2 -MODCARGO_CRATES += universal-hash 0.4.0 -MODCARGO_CRATES += unreachable 1.0.0 +MODCARGO_CRATES += unicode-bidi 0.3.8 +MODCARGO_CRATES += unicode-ident 1.0.3 +MODCARGO_CRATES += unicode-linebreak 0.1.2 +MODCARGO_CRATES += unicode-normalization 0.1.21 +MODCARGO_CRATES += unicode-segmentation 1.9.0 +MODCARGO_CRATES += unicode-width 0.1.9 +MODCARGO_CRATES += unicode-xid 0.2.3 +MODCARGO_CRATES += universal-hash 0.4.1 MODCARGO_CRATES += untrusted 0.7.1 MODCARGO_CRATES += url 2.2.2 MODCARGO_CRATES += utf-8 0.7.6 -MODCARGO_CRATES += uuid 0.8.2 +MODCARGO_CRATES += uuid 1.2.1 MODCARGO_CRATES += valuable 0.1.0 -MODCARGO_CRATES += vec_map 0.8.2 -MODCARGO_CRATES += version_check 0.9.3 -MODCARGO_CRATES += void 1.0.2 +MODCARGO_CRATES += version_check 0.9.4 MODCARGO_CRATES += waker-fn 1.1.0 MODCARGO_CRATES += walkdir 2.3.2 MODCARGO_CRATES += want 0.3.0 MODCARGO_CRATES += wasi 0.9.0+wasi-snapshot-preview1 MODCARGO_CRATES += wasi 0.10.0+wasi-snapshot-preview1 +MODCARGO_CRATES += wasi 0.11.0+wasi-snapshot-preview1 MODCARGO_CRATES += wasm-bindgen 0.2.82 MODCARGO_CRATES += wasm-bindgen-backend 0.2.82 MODCARGO_CRATES += wasm-bindgen-macro 0.2.82 MODCARGO_CRATES += wasm-bindgen-macro-support 0.2.82 MODCARGO_CRATES += wasm-bindgen-shared 0.2.82 -MODCARGO_CRATES += web-sys 0.3.51 -MODCARGO_CRATES += webpki 0.21.4 +MODCARGO_CRATES += web-sys 0.3.59 +MODCARGO_CRATES += webpki 0.22.0 MODCARGO_CRATES += wepoll-ffi 0.1.2 -MODCARGO_CRATES += which 4.1.0 -MODCARGO_CRATES += whoami 1.1.2 +MODCARGO_CRATES += which 4.3.0 +MODCARGO_CRATES += whoami 1.2.1 MODCARGO_CRATES += winapi 0.3.9 MODCARGO_CRATES += winapi-i686-pc-windows-gnu 0.4.0 MODCARGO_CRATES += winapi-util 0.1.5 MODCARGO_CRATES += winapi-x86_64-pc-windows-gnu 0.4.0 -MODCARGO_CRATES += windows 0.24.0 -MODCARGO_CRATES += windows_i686_gnu 0.24.0 -MODCARGO_CRATES += windows_i686_msvc 0.24.0 -MODCARGO_CRATES += windows_x86_64_gnu 0.24.0 -MODCARGO_CRATES += windows_x86_64_msvc 0.24.0 -MODCARGO_CRATES += winrt-notification 0.5.1 -MODCARGO_CRATES += x25519-dalek 1.1.1 -MODCARGO_CRATES += xattr 0.2.2 -MODCARGO_CRATES += xflags 0.2.2 -MODCARGO_CRATES += xflags-macros 0.2.2 -MODCARGO_CRATES += xml-rs 0.8.4 -MODCARGO_CRATES += xshell 0.1.14 -MODCARGO_CRATES += xshell-macros 0.1.14 -MODCARGO_CRATES += zbus 2.1.1 -MODCARGO_CRATES += zbus_macros 2.1.1 -MODCARGO_CRATES += zbus_names 2.1.0 +MODCARGO_CRATES += windows 0.39.0 +MODCARGO_CRATES += windows-sys 0.36.1 +MODCARGO_CRATES += windows_aarch64_msvc 0.36.1 +MODCARGO_CRATES += windows_aarch64_msvc 0.39.0 +MODCARGO_CRATES += windows_i686_gnu 0.36.1 +MODCARGO_CRATES += windows_i686_gnu 0.39.0 +MODCARGO_CRATES += windows_i686_msvc 0.36.1 +MODCARGO_CRATES += windows_i686_msvc 0.39.0 +MODCARGO_CRATES += windows_x86_64_gnu 0.36.1 +MODCARGO_CRATES += windows_x86_64_gnu 0.39.0 +MODCARGO_CRATES += windows_x86_64_msvc 0.36.1 +MODCARGO_CRATES += windows_x86_64_msvc 0.39.0 +MODCARGO_CRATES += x25519-dalek 1.2.0 +MODCARGO_CRATES += xattr 0.2.3 +MODCARGO_CRATES += xflags 0.2.4 +MODCARGO_CRATES += xflags-macros 0.2.4 +MODCARGO_CRATES += xshell 0.1.17 +MODCARGO_CRATES += xshell-macros 0.1.17 +MODCARGO_CRATES += zbus 2.3.2 +MODCARGO_CRATES += zbus_macros 2.3.2 +MODCARGO_CRATES += zbus_names 2.2.0 MODCARGO_CRATES += zeroize 1.3.0 MODCARGO_CRATES += zeroize_derive 1.3.2 -MODCARGO_CRATES += zvariant 3.3.0 -MODCARGO_CRATES += zvariant_derive 3.3.0 +MODCARGO_CRATES += zvariant 3.6.0 +MODCARGO_CRATES += zvariant_derive 3.6.0 diff --git a/net/gurk-rs/distinfo b/net/gurk-rs/distinfo index 8eac37f..5aa70cf 100644 --- a/net/gurk-rs/distinfo +++ b/net/gurk-rs/distinfo @@ -1,720 +1,758 @@ SHA256 (cargo/adler-1.0.2.tar.gz) = 8mIBYEyHseAb09mPjV2aj8u4FejO20H/zL60v1k6Nf4= -SHA256 (cargo/aead-0.4.2.tar.gz) = bj55iqDII5d29UQVvAbz10sYUPP4MLRcNc/IBVaXP3A= -SHA256 (cargo/aes-0.7.4.tar.gz) = SV7maUE7++noys6A9NPXjm2MjZlXn5f7k73jUbGF8tQ= -SHA256 (cargo/aes-gcm-0.9.2.tar.gz) = vDvpLhmn70dFe45vkHB+ErasXSDG84ZlhPo74Hh9g58= -SHA256 (cargo/aes-gcm-siv-0.10.1.tar.gz) = z96BRnYvPF88XNQaoXpx8xiN8J1YVxkrZYUQ2FDhYGg= -SHA256 (cargo/aho-corasick-0.7.18.tar.gz) = HjfP1edletpF90LW6ZyleIWAtcUp3Hj68R7ObccCZW8= +SHA256 (cargo/aead-0.4.3.tar.gz) = C2E7jh48+RGghvU/A78ob1L9enJY5Ppgbw7yINOdiHc= +SHA256 (cargo/aes-0.7.5.tar.gz) = notH9S6puuQiKNB+wJ62dkM9fE7R698PHRwp7URvGrg= +SHA256 (cargo/aes-gcm-0.9.4.tar.gz) = 31+FqDp9iwRCtqp7UEuCEsFzPaB7mKrkPUvCGyyzzfY= +SHA256 (cargo/aes-gcm-siv-0.10.3.tar.gz) = WJxjfw5oyHe71ZpFmbvoScrI5fPktaPrro9SjNIY3Nw= +SHA256 (cargo/aho-corasick-0.7.19.tar.gz) = tPVb2RoJeMv9kcRXoWS6uLQAHIM7fzIxMsCk4ZIt1E4= SHA256 (cargo/android_system_properties-0.1.5.tar.gz) = gZ5yGdvUEEOsJ5sZgw8u/IlxVkkNf9bqkWcgEX7mYxE= -SHA256 (cargo/ansi_term-0.11.0.tar.gz) = 7km69sthe4U6qNk79CDbI4P6tG0xRILKKAO0DV/el5s= +SHA256 (cargo/anes-0.1.6.tar.gz) = S0bLs2Krh1KSHJfgQfXjZu5il71CijEnW5/PHjgPcpk= SHA256 (cargo/ansi_term-0.12.1.tar.gz) = 1Sqbt+wM9ITFUYMKfOJ70g1n6sZH4b77VrC+TuOaVdI= -SHA256 (cargo/anyhow-1.0.42.tar.gz) = WV08+npg1FVctQZ7mfBxQqCOp3jeXPmT97dcfY+rxIY= +SHA256 (cargo/anyhow-1.0.64.tar.gz) = uaj2Irz2/z30eOneuj4D5OBLMA+OahOeGSwF+jSQr8c= SHA256 (cargo/arrayref-0.3.6.tar.gz) = pMUnFS43z3V6P3iq5aBvvu/bB8zFNcmAoyCO4wYN1UQ= SHA256 (cargo/arrayvec-0.5.2.tar.gz) = I7Yvxl3o5Of1JTT7UrDz7QR0auJnUZ7vKoOUHoCFBos= -SHA256 (cargo/ascii-0.9.3.tar.gz) = 6rHASlcYQRAvU0Wo/A9rs9McMV3sh5tcbkLkDOf/o04= -SHA256 (cargo/async-broadcast-0.3.4.tar.gz) = kGImmKEhjgsvuEbJe18ZoIMfa63e5z2UVBVjZcz6Rzs= -SHA256 (cargo/async-channel-1.6.1.tar.gz) = IRTWRnIVHAxeql4THshKdPBuHlWYMNq7oByjBgXWYxk= +SHA256 (cargo/async-broadcast-0.4.1.tar.gz) = bSYAT+g7LRzTqXYJsh45+aMVNYIiEP6DIF0s5Ihm6mE= +SHA256 (cargo/async-channel-1.7.1.tar.gz) = 4USFNkIUkS07Gcw0Nd3k32YGUSfwX6DXXHEvNvEsLyg= SHA256 (cargo/async-executor-1.4.1.tar.gz) = hx+bteCiLut+jPFmQf64fJ3GcDLM+P9J53LrmUHTqWU= -SHA256 (cargo/async-io-1.6.0.tar.gz) = qBHmpHnyQ58MBAOHlrXPs9KtVsIw4PLT97BNaM/uYHs= +SHA256 (cargo/async-io-1.9.0.tar.gz) = g+IfOkkMcrOwz0SWIYDmAEXeKSXY3/l5GPfuQ8j2N8c= SHA256 (cargo/async-lock-2.5.0.tar.gz) = 6XoXHRkXgvujG7kCsUrZTiSmgUUDK37t+HGrC8DQd7Y= SHA256 (cargo/async-recursion-0.3.2.tar.gz) = 19eGVroB8bkwJLfDoEZ/FgjkvmfXJXSf3NfSx2eP16I= -SHA256 (cargo/async-task-4.2.0.tar.gz) = MGlqhNgXEH/AKOBJmA4J1eFA6NqPHK6xfo6VBlijzqk= -SHA256 (cargo/async-trait-0.1.51.tar.gz) = RDGOd232gRWogd6aj9G55TNo16SlzkzEhRfaM5MjOl4= -SHA256 (cargo/async-tungstenite-0.15.0.tar.gz) = dCzH3LILL4SkL0aRqpmQcOx+ePjn50OL8UvnAXtEkH4= +SHA256 (cargo/async-task-4.3.0.tar.gz) = ekBynSEzhG2e0OpgqLlUG8zdq0nNMPBxWh2mcv6aJSQ= +SHA256 (cargo/async-trait-0.1.57.tar.gz) = dkZERri8MnWNfojuGoBNmRTNmxyyZMApiZaAsL4pgm8= +SHA256 (cargo/async-tungstenite-0.17.2.tar.gz) = obcbMVYWQ6qOffPv/ihPqDqxqEDlIpTF9L17/Ysr7Ls= SHA256 (cargo/atty-0.2.14.tar.gz) = 2bOb4Ydw0RQhzbG5lHpF3T836TCSy/N3YUgooxnV/ug= SHA256 (cargo/autocfg-1.1.0.tar.gz) = 1GiAK6sXy8DMV16bBT9B5yqja/prf1XjUp/6QxYbl/o= SHA256 (cargo/base64-0.12.3.tar.gz) = NEHw97AniOlI5H9FfKAfHX5tksaTvBMsIrCH0xQcA/8= SHA256 (cargo/base64-0.13.0.tar.gz) = kE3+rFDzzauij8b1f9zdt19J7WE0ZnanjE/+VYd4Av0= SHA256 (cargo/bincode-1.3.3.tar.gz) = sfRelBfYcifHpW0i5HHGIGRiy6UUx1kMCa/0z20d3K0= -SHA256 (cargo/bitflags-1.2.1.tar.gz) = zx3i/ox1vBRaL1d63ZUfgTSIm0eV1HRmpUpchG1pFpM= +SHA256 (cargo/bitflags-1.3.2.tar.gz) = vvONRRY8Lx3eCUp9/TPM9ZXJKQXI+PT9wY0G+xA3cYo= SHA256 (cargo/block-0.1.6.tar.gz) = DYwf72kJQdPneI0yhRdZH+zGhMCECEcC1v8WQemTaZo= -SHA256 (cargo/block-buffer-0.7.3.tar.gz) = wJQNxEHzFokmnhCscOsQAqOh060TkOAwBDZi63/kaIs= +SHA256 (cargo/block-buffer-0.10.3.tar.gz) = acziBzdJj5e5k0cKblNrhSPwr3iSpPkozOsaxeUuvn4= SHA256 (cargo/block-buffer-0.9.0.tar.gz) = QVIRb9bp2tspGuGPwew1de1thMKWQtl4kPS0o0Fyl+Q= SHA256 (cargo/block-modes-0.8.1.tar.gz) = LLA9G+0VXYnc4PhFt4mbGKmhY+FI/QBOHChCGng+LY4= -SHA256 (cargo/block-padding-0.1.5.tar.gz) = +nne27CR9Enx855T7fiNXb6V+JXa5hNajXuIH7Wvc/U= SHA256 (cargo/block-padding-0.2.1.tar.gz) = jWlsNwx1DJSK2mHGmg7iy7ucULEBnduG2TFxV6mcLK4= -SHA256 (cargo/bstr-0.2.16.tar.gz) = kGgsjWE60zc+Zt6MZBHgriqyVx6HnS779zVYzGbyEnk= -SHA256 (cargo/bumpalo-3.7.0.tar.gz) = nFnnrwEscT9Snno+5Xzpsx3dhY1LUSkjYC90YIsAljE= -SHA256 (cargo/byte-tools-0.3.1.tar.gz) = 47XKegSJitS81ByQxShURf9beRiZuxsKvdKiqnkSEdc= +SHA256 (cargo/bstr-0.2.17.tar.gz) = ujVp84Po8VmESfGkI+cumVaRN7R3QLHaEe8Zrz1cMiM= +SHA256 (cargo/bumpalo-3.11.0.tar.gz) = wa2CIRjSDSwjT0JwANWsw26r4eKaNIyJtj3WCxPyjl0= SHA256 (cargo/byteorder-1.4.3.tar.gz) = FMGJxT0JiUVJnN+n7MY1Z884hrMzKzEqW0WF2NOmphA= -SHA256 (cargo/bytes-1.0.1.tar.gz) = twDOQ3YEHc0KMn/QCXxBCVdDxMiviIcmWUL68RAL0EA= -SHA256 (cargo/cache-padded-1.1.1.tar.gz) = YxrlGYyb5edT5cwhXhvXPCtGajVlFz20M/UrudPmbbo= +SHA256 (cargo/bytes-1.2.1.tar.gz) = 7Ip7anD96ANyFUxlcC8AoPVvPhw2q7xsRASEviSIVts= +SHA256 (cargo/cache-padded-1.2.0.tar.gz) = wdtZYh7HDwnF6bWXsiDHorQ2EfRxDcA864dIY3d1aSw= SHA256 (cargo/cassowary-0.3.0.tar.gz) = 34ZwuMe52uF5M2Tq+t9yOcQNZpkEZgxZYNdM/YC0alM= -SHA256 (cargo/cc-1.0.69.tar.gz) = 5wzC9ixs4YaJY4J71nd2TGLQfD2aPh+xF37hqasZnrI= -SHA256 (cargo/cesu8-1.1.0.tar.gz) = bUOgTYdT81JYyR+Oxjn3kokfdIoe29dZzx3Oozgq2Dw= +SHA256 (cargo/cast-0.3.0.tar.gz) = N7KmcqLLEpouQcELEiS7No+fN6Kxa2ElmBOL79ezfrU= +SHA256 (cargo/cc-1.0.73.tar.gz) = L/8qaSezu4f5WV1nGWpwST9idoenHYeg1pIkLDP1jBE= SHA256 (cargo/cfg-if-1.0.0.tar.gz) = uvHeQzl2FYi8Bhnjy8ASDuWC67dLU7Tvv3kRe9LaQP0= SHA256 (cargo/checked_int_cast-1.0.0.tar.gz) = F8xea1qwYzHDNYmEIHBBa6oTfosOuRKwCM/Up4raeRk= SHA256 (cargo/chrono-0.4.22.tar.gz) = v9TRsx+qo6ideTTb3tMRHaDS7yjj68zbTwF59ZKdHvE= +SHA256 (cargo/ciborium-0.2.0.tar.gz) = sME3VozGC5BKdyQAGzXOJjD9ANXYSAX7tgiriVCdeI8= +SHA256 (cargo/ciborium-io-0.2.0.tar.gz) = NG3nU68HPMh7UrIIOlBrOKwXakTPsFSXtiLie+iZs2k= +SHA256 (cargo/ciborium-ll-0.2.0.tar.gz) = ITAworWk4MCJK2ZSJgz2zKyEgnuDqFpTTheOOQbEzxs= SHA256 (cargo/cipher-0.3.0.tar.gz) = fuUgcuwVOG93CAWv0YmgHIhBvoaWvtJQ+i8TxMDW37c= -SHA256 (cargo/clap-2.33.3.tar.gz) = N+WKx4VzxAcI1FUi8NgPovAcxPm04r90mAclVFQxIAI= -SHA256 (cargo/combine-3.8.1.tar.gz) = 2j2muqMh7BnhzEHTG/WZ8Ax4PQUXCVza8DMuP+jSBoA= -SHA256 (cargo/concurrent-queue-1.2.2.tar.gz) = MO0HVQvgFZTGAmz/Kh1/6cj2g8qnmOEraGlKyeiChqM= -SHA256 (cargo/core-foundation-0.9.1.tar.gz) = ConirkJuqDFV3M8QwPprFGPvbV/LRM7gsiSkCPpkCmI= +SHA256 (cargo/clap-3.2.23.tar.gz) = cWVcRcuYRdMnDJ1t+E6+crTa08K6P3AjrUfBROTkc6U= +SHA256 (cargo/clap-4.0.18.tar.gz) = M1hndk7S3kIyX6/m0YuK90upfuDFkPoBbxV1NbQqsEs= +SHA256 (cargo/clap_derive-4.0.18.tar.gz) = FqGw9kIq8y1doMWOJwMyDzeSFu5wGYJByEFzqMWsKPM= +SHA256 (cargo/clap_lex-0.2.4.tar.gz) = KFDy9agsv0N91a9NSYSPvfwnwVfD0BA0V3b5UnZSYcU= +SHA256 (cargo/clap_lex-0.3.0.tar.gz) = DUGY9z5CtJNrNbW7JI2B0rWV7LFw2gusdlXFTu36jag= +SHA256 (cargo/cmake-0.1.48.tar.gz) = 6K2M7xBKxXtouJ3zIIFk0ihQOrvc5w9ogP+j2XDnRDo= +SHA256 (cargo/concurrent-queue-1.2.4.tar.gz) = r0eApEq1aW6p4oKUUX8f/7QhqDolr1ITM8g4Y1UJ25w= +SHA256 (cargo/core-foundation-0.9.3.tar.gz) = GUp6nm3lP6VRFpNAZ8hE2ddJMS91xvbQmA6MJS+MIUY= SHA256 (cargo/core-foundation-sys-0.8.3.tar.gz) = WCfOv0ZwRouHct0ZGFZ2iu3LGwJ4oE+Yn3dmNRkXudw= -SHA256 (cargo/cpufeatures-0.1.5.tar.gz) = ZsmWlvbJ3X811Ia50E1+biAqo+jEDVU/L99efgxqce8= -SHA256 (cargo/crc32fast-1.2.1.tar.gz) = gRVv7OhKtqnyr9sQnOOuV35CsSKEQe3tmb139ieVOxo= -SHA256 (cargo/crossbeam-channel-0.5.5.tar.gz) = TAKk1xgZAJwZLPSHImU5FWP9aoTIH/LA8qcCbKTB2Fw= -SHA256 (cargo/crossbeam-epoch-0.9.5.tar.gz) = TsAuCRqmNOLDraSjkpiefDEWZz7wrFtyIyQ5CU1zt/0= -SHA256 (cargo/crossbeam-utils-0.8.9.tar.gz) = j/H5gJV3hyhqVUBS0Dx67pjZnMMuCfbUXwqBQTPIeXg= +SHA256 (cargo/cpufeatures-0.2.5.tar.gz) = KNmXvV4kpZKN1D5G3FKYZ+IHkH/gsjnDR32ST38soyA= +SHA256 (cargo/crc32fast-1.3.2.tar.gz) = tUC9i8gQ04hcbqkeIBgwL2i6uiEpqz6I8yOJ7pNwiA0= +SHA256 (cargo/criterion-0.4.0.tar.gz) = 58duCcGq4rxSs9LynhPGVyVTswxKobikn9cN5kEmVMs= +SHA256 (cargo/criterion-plot-0.5.0.tar.gz) = a1CCY0J4alGoni2joo8cMrBuOHIBvC0ZeR9iLGc3BrE= +SHA256 (cargo/crossbeam-channel-0.5.6.tar.gz) = wt0E3a+II33DuNj5o8EAS1BrVLMxNAOUQFTSPAhwxSE= +SHA256 (cargo/crossbeam-deque-0.8.2.tar.gz) = cV6BUraSu6LTdLU9SHVEU2j98hqUdRQQr2B6WsZ30fw= +SHA256 (cargo/crossbeam-epoch-0.9.10.tar.gz) = BF6+J2ZkcbtUk3C0sLPlGwf1YyW++kKE22X8icAlEbE= +SHA256 (cargo/crossbeam-utils-0.8.11.tar.gz) = UYh9Stx7VkU3sVrc+zB5NvgHXfzV8A3emp8dKTg2grw= SHA256 (cargo/crossterm-0.19.0.tar.gz) = fDbBATDfQksvNVL8wt3Nmyiiex5Us1i0WHT4jRymiIw= +SHA256 (cargo/crossterm-0.23.2.tar.gz) = ohAupPeBkQ+KW5jdBh9MICP0ec57sSNjMAmc61qTzxc= SHA256 (cargo/crossterm_winapi-0.7.0.tar.gz) = DaiWSs5NPkoET9AnkZsiNwALJDFaN8kW9hgJ8f8hQLk= +SHA256 (cargo/crossterm_winapi-0.9.0.tar.gz) = KuGzWkhKoQ4H/gY40CMBxa0k3oLTEMy9LzaT2l8Jvxw= +SHA256 (cargo/crypto-common-0.1.6.tar.gz) = G/sSUC8/xGzKG7Uawo351hjYE83D0vJbn+d1o0rya7M= SHA256 (cargo/crypto-mac-0.11.1.tar.gz) = sdGob0kjbCFfJx1AiS1fyVBJBVFACwLvNgaSwpgVxxQ= -SHA256 (cargo/crypto-mac-0.7.0.tar.gz) = RDRADfEdldVWusBo3f7dSCkV6xj+i+qJvIC25LHBeeU= -SHA256 (cargo/ct-logs-0.8.0.tar.gz) = wagWGG+mjZ5Cbjy0rk3/H82OSiw0t4G/eoIldKDQqsg= -SHA256 (cargo/ctr-0.7.0.tar.gz) = ojL5KgPzfdfX3SrcZxZsd+nNiN5bAZuanuz66ve/1IE= -SHA256 (cargo/curve25519-dalek-3.1.0.tar.gz) = Y5iR/eDb6oI/w9eYoP350vlECkLWSnirNIiwygJRF7M= +SHA256 (cargo/ctr-0.8.0.tar.gz) = BJu5H7Sq8OPH76bNXvh327vRWzna0G2ZSN5OyKdXYeo= SHA256 (cargo/derivative-2.2.0.tar.gz) = /MPdXp6cCyldbh5NgR+28VfV/9eEuNIC/GLqyANadws= -SHA256 (cargo/digest-0.8.1.tar.gz) = 89DIyHUjEvlxPv05f/Y6y5+FWFr78XkoLnIOdwSVTdU= +SHA256 (cargo/digest-0.10.3.tar.gz) = 8vuGDKb6+lVS+20OgWppyOSfCQi/Uk4wqQ2XyFiS1QY= SHA256 (cargo/digest-0.9.0.tar.gz) = 091g0QgKV6BasDI3cEngWRQV0rMa/XAoNW2/PMbcsGY= SHA256 (cargo/dirs-3.0.2.tar.gz) = MLqgQxA8nQwqV89TfMLzViOIncDUBebDzM+tvIHHEwk= +SHA256 (cargo/dirs-4.0.0.tar.gz) = yjqnKm+W6je7xaqRL2eIJCgy91Npvf2tyw44Qj8QAFk= SHA256 (cargo/dirs-next-2.0.0.tar.gz) = uYz46/GcPRsiPhUfmaT58GkNykFBR3M5D8gkGErIM+E= -SHA256 (cargo/dirs-sys-0.3.6.tar.gz) = A9hlNO02emdUjcaBE6D121VDL9+7bm+dd3BDl9ldV4A= +SHA256 (cargo/dirs-sys-0.3.7.tar.gz) = Gx0dkcky70HA8mY6qLDKA0LURNhCwGkUqgp+NS0LraY= SHA256 (cargo/dirs-sys-next-0.1.2.tar.gz) = Tr2hRMT+AtH36hp9lkG2/GtYCtz6Akrkh5fs3raCW00= SHA256 (cargo/displaydoc-0.2.3.tar.gz) = O/ldw/BGudpPLVGDPA01R9hWTvaRD1we0TAwanW5KIY= -SHA256 (cargo/easy-parallel-3.2.0.tar.gz) = aQfiU5PNzB9PP1E9mqwehA6xzDQaD8ywEXH30U0QuUY= -SHA256 (cargo/either-1.6.1.tar.gz) = 541PHMSuM7v8FX7V1aXvO8KSJzA9WVhh3rI4/OxOlFc= +SHA256 (cargo/either-1.8.0.tar.gz) = kOXByDaIAxE78MlYT8SVpYuG3Iop7b+P6HfSHZUH55c= SHA256 (cargo/emoji-0.2.1.tar.gz) = MukwmHA3H3+ndndS5QSPwMBnWwF6J9nGAd/+mh7+AwE= SHA256 (cargo/enumflags2-0.7.5.tar.gz) = 511M0huVODREgxU5kJ+7FLncP9zrKm9dNldzKaH1XMs= SHA256 (cargo/enumflags2_derive-0.7.4.tar.gz) = 9Y3DxeRoJZ8Z8tRjBKayjxw9A0RC4UsyLSuFDjb21a4= SHA256 (cargo/env_logger-0.8.4.tar.gz) = oZGH/qOsfoTafaz0jeDEXWPGp2+UkNrjia6tFsJD/OM= -SHA256 (cargo/error-chain-0.12.4.tar.gz) = LS8GucrBUG7OmP4yMePMnEQQ7D1bHySuHIlG8HQs3vw= -SHA256 (cargo/event-listener-2.5.2.tar.gz) = d/MwlBeTjyi/gij8/3mko3EDmB4+GG0szRnHSzj063E= -SHA256 (cargo/fake-simd-0.1.2.tar.gz) = 6IqKzykdr7WcLZbo9Zgo84OLsacDmII63lGoTeam3u0= -SHA256 (cargo/fastrand-1.4.1.tar.gz) = d7cFgp0eh/diwt9toUCyavWDnhAzqoSqX1a7aI5OG9s= -SHA256 (cargo/filetime-0.2.14.tar.gz) = HTTPoTpjrgWL+mAf6eMTu9s3RkJ8FFkYVGTOD89i4eg= -SHA256 (cargo/fixedbitset-0.2.0.tar.gz) = N6s0dBboAt5ITk0DxzFsSPHstWV039SkaoDxc84d4E0= -SHA256 (cargo/fixedbitset-0.4.1.tar.gz) = J5+wKOILPEwyAxeVW3fF4MlwHwWh0wmQXW/HAs3FBT4= -SHA256 (cargo/flate2-1.0.20.tar.gz) = zTrsU94Q/pbX2MVl6xfyxoe7VRii7EU7WxJSlkUmq+A= +SHA256 (cargo/event-listener-2.5.3.tar.gz) = AgYXX4K41r9mUv99caHif9Lk795Yf9NoZigU1uwdnOA= +SHA256 (cargo/fastrand-1.8.0.tar.gz) = p6QHz6ozhcSuayPoRiPUjCeY0G4+ahh49/WfF7P4ZJk= +SHA256 (cargo/filetime-0.2.17.tar.gz) = 6Up7uqWTVLwg3XW2fyPieXtEkOnWkoID+xBceeRIyGw= +SHA256 (cargo/fixedbitset-0.4.2.tar.gz) = DOcTS5mZ7K+LzWVULkNnNu8y3cobPgYJTLbsV1UgO4A= +SHA256 (cargo/flate2-1.0.24.tar.gz) = +CsPTCetn4v9HzII2ILaKwnDAbwcgo/ToA0CFtL7v/Y= SHA256 (cargo/fnv-1.0.7.tar.gz) = P57skY0/JAad7LmvFVTK18iA4tokqa/YisoABTGrgsE= SHA256 (cargo/form_urlencoded-1.0.1.tar.gz) = X8Jah/pP0glL/7BpJYUgNNkKF/DR4FGX1JVtNVV1IZE= SHA256 (cargo/fs2-0.4.3.tar.gz) = lWT8dY4VAltGqmZDsbd9BH0aVqGupuAQAqwMcCaHYhM= -SHA256 (cargo/futures-0.3.15.tar.gz) = Dn5DqAPa4vo3wfao/hIeH3v5VItN/AUipC80FF2t/Cc= -SHA256 (cargo/futures-channel-0.3.15.tar.gz) = 5oKmiymogt8FRcFD3DZG2u/oC6R5vN7elNWnA94oceI= -SHA256 (cargo/futures-core-0.3.15.tar.gz) = BAL3ZdiomiYEO4ibJs48RnnSaPprsizXxqrZg0DhedE= -SHA256 (cargo/futures-executor-0.3.15.tar.gz) = utqmqQn6yecjbQYgovV/dmRkDFZXW3GnVS+9aN6vq3k= -SHA256 (cargo/futures-io-0.3.15.tar.gz) = rMSZ3vs7NI+Njz9mQVg1qRMYVv93FL8Q2t/E7EvbKaE= +SHA256 (cargo/futures-0.3.24.tar.gz) = fyHtpZmTf7o22utYoi6PXO4tFMShe1t3OcfI5eO4Iww= +SHA256 (cargo/futures-channel-0.3.24.tar.gz) = ML3SDCj63VBdD9ZxLN/LDUtWSLr0X673+FKvsjmbsFA= +SHA256 (cargo/futures-core-0.3.24.tar.gz) = Tlqj3gU2LD+4jeZTHmKW6FzedznMytS53+639uvOVr8= +SHA256 (cargo/futures-executor-0.3.24.tar.gz) = n/Y8I4VL7mG26c0zHVI5CfI4/HY2KQuWgm6c+l+qAKs= +SHA256 (cargo/futures-io-0.3.24.tar.gz) = u/TSp6MI/UV4Y3wLF8fhx7oSe49roAsp9xfpZV2F62g= SHA256 (cargo/futures-lite-1.12.0.tar.gz) = dpRIms05RSx32qSFFriUwVPxksNXjVqDm2LFgJn8v0g= -SHA256 (cargo/futures-macro-0.3.15.tar.gz) = pMQCmEhs31LMAM1taYeJK6UCx2VqFqQZKpmSsczt0SE= -SHA256 (cargo/futures-sink-0.3.15.tar.gz) = pXvq0M7/DW3ej0ZezZbJM4Ehu3cX0+exCAWVMYcMQoI= -SHA256 (cargo/futures-task-0.3.15.tar.gz) = iha++fwaTd21vuUcmJ4/u6Jlacuw4x9bMDwYTj3TPa4= -SHA256 (cargo/futures-util-0.3.15.tar.gz) = /rXCONJ+K/lP/f0nssKePfSmjEGTu2QnOEJZ4r8ZGWc= +SHA256 (cargo/futures-macro-0.3.24.tar.gz) = Qs0V0cdFbATb336IvNaXYNdPOnmNZEThaXS1BbDmLxc= +SHA256 (cargo/futures-sink-0.3.24.tar.gz) = IbILpakucnujDnKDRwZiPZSsk6clQQtqa2+8Gwf3ulY= +SHA256 (cargo/futures-task-0.3.24.tar.gz) = plCMRnxzhRKT85BHbUSRz00ifbq81BcPO7YESVmylPE= +SHA256 (cargo/futures-util-0.3.24.tar.gz) = RPtssb5hzB0uQ7JiUWqvz2OyQc/9sdP6EV+R2cewnJA= SHA256 (cargo/fuzzy-matcher-0.3.7.tar.gz) = VGFKMxKTTQZnAagPIPFfo7VtZ6x3IrOe6ltMndHWbJQ= SHA256 (cargo/fxhash-0.2.1.tar.gz) = wxttdRrix/ETIEAtNOQTSd0QFvjV1F5IxDEryGJa9Qw= -SHA256 (cargo/generic-array-0.12.4.tar.gz) = /9+fNPFEdEPTc5PMbCuDE6693NlpBsrzTlTGjY5X170= -SHA256 (cargo/generic-array-0.14.4.tar.gz) = UBRm7MijDR07f8kimxIrLOjtbp2SI/ETjUurslPlGBc= +SHA256 (cargo/generic-array-0.14.6.tar.gz) = v/SelHKX8zEkR6vcp59F9HOAl8yCsG5yBU0iI/YB8bk= SHA256 (cargo/getopts-0.2.21.tar.gz) = FNu/1ccdcCQez55vE3N/e1zoI4IQYxiNfkbEHTce69U= SHA256 (cargo/getrandom-0.1.16.tar.gz) = j8PLTZH1O1AVW9z9I/akw5rhlpwq6FmCsTV1DMyvX84= -SHA256 (cargo/getrandom-0.2.3.tar.gz) = f82ZlGNSTFJllRf+LOqYSTz+SF0QVl57D7B9u6etJ1M= -SHA256 (cargo/gh-emoji-1.0.3.tar.gz) = oXoFC360IFUzROHPHbZI6LWEx56Yt05ubRGe7t2d3Lw= -SHA256 (cargo/ghash-0.4.2.tar.gz) = e71gyqMRI31QiSfbunWUtIPbPvBfqlUXL8+JsbzaeFM= -SHA256 (cargo/hashbrown-0.11.2.tar.gz) = q17w1JCe83JMyMzmzMhXLFyBdZLpKF9UZPjob4vTcm4= -SHA256 (cargo/headers-0.3.4.tar.gz) = 8LdZH7YpAnBq6Oeq/0FrGw+iwP0IeLRtwTuqNxLYqFU= +SHA256 (cargo/getrandom-0.2.7.tar.gz) = TrGoZKUBYpaR7fbBWlk7elHuuqHoRo6d3GI958m1jsY= +SHA256 (cargo/gh-emoji-1.0.7.tar.gz) = MK1ktD1IwXRcAFnluiI4FutZnuyJVsZo/Aox9rnNeZ4= +SHA256 (cargo/ghash-0.4.4.tar.gz) = FYPMFlbXg5/TcyuAz084hQM2zbm43tHNOZymKVjePJk= +SHA256 (cargo/half-1.8.2.tar.gz) = 6rtKREUNoCyQREz3RVjakE7d6PtOkDWppqThVEWvC9c= +SHA256 (cargo/hashbrown-0.12.3.tar.gz) = ip7nDEOq9BfJFDlmRaD6hSYkgBsk67eueP6CcoiayIg= +SHA256 (cargo/headers-0.3.8.tar.gz) = 8+Ny245cDSE+DNC5vhi+Kso9RM8v4wqdRqZVgc1FRYQ= SHA256 (cargo/headers-core-0.2.0.tar.gz) = 5/Zkgb/uJzlXsfIEhaT/M2KYf4WywjZYDYG063oyZCk= SHA256 (cargo/heck-0.3.3.tar.gz) = bWIe+yaGPw6ZJMasV36CdeXmt3RV22T/psZckE6eEyw= +SHA256 (cargo/heck-0.4.0.tar.gz) = JUB3HmX8jLg81uiiN/cMMZvVwp947RCEul1Q7qyG9/k= SHA256 (cargo/hermit-abi-0.1.19.tar.gz) = YrRnNDuUukdtyyUA0kLa27OVV9+IkxCsd8XZkQCqrDM= SHA256 (cargo/hex-0.4.3.tar.gz) = fyQlSqmlS1yFjq7i9bzNtGqvDkhqWV7V/Y+GulUjKnA= SHA256 (cargo/hkdf-0.11.0.tar.gz) = AXBtV41cKBBYSA5nOuQIap9HENjfGtgKWwPjns5fiGs= +SHA256 (cargo/hkdf-0.12.3.tar.gz) = eRoCn2ufwnZX9vGI7G5eQ/aRH2+Hjg3FUBOW4JgJ1Dc= SHA256 (cargo/hmac-0.11.0.tar.gz) = KiojIOt+wOvo2o90TXgS2fxMtNCTRKwBiY28tqIK5ps= -SHA256 (cargo/hmac-0.7.1.tar.gz) = XcteZM2kwjEZq0G6lg0eFwp3TI5LnZ5qm8GKq/XllpU= +SHA256 (cargo/hmac-0.12.1.tar.gz) = bEnDfAnBelPZN9+7dC6zqWHWWplOa83PN+c5nQzIq14= SHA256 (cargo/hostname-0.3.1.tar.gz) = PHMcPhBQTMjtNc/i8dtMknTD01+khuOzHfRvBo7z6Gc= -SHA256 (cargo/http-0.2.4.tar.gz) = Un6MmsdH4oVCaZqVFReqmmlFr1Bs0fLhtTpXbBe2zBE= -SHA256 (cargo/http-body-0.4.2.tar.gz) = YNqhS+DgeG2w8DqeV8tATJ11bu0rbGK56pjsV0Psdak= -SHA256 (cargo/httparse-1.4.1.tar.gz) = 86h7YW436Twi+xm804bwLzr16piiVnCtD853PeI8Xmg= -SHA256 (cargo/httpdate-1.0.1.tar.gz) = ZFa4psjzP+59lY/NG2DVWxGUCnnmOuhwE+bSLiYDREA= -SHA256 (cargo/hyper-0.14.11.tar.gz) = C2HPLRrrz25jUsl7gdwiRMopGUvhsnb12K1cYzD/+xE= -SHA256 (cargo/hyper-rustls-0.22.1.tar.gz) = X596lzFtRMCvmwMB5lAQVzqFOp/JcEbXMx1/a8D9WmQ= +SHA256 (cargo/http-0.2.8.tar.gz) = dfQ9QeJplcF+ce4SZFHdOUEBCwUUqBqdEfOzQd68I5k= +SHA256 (cargo/http-body-0.4.5.tar.gz) = 1fOPFtGE428kCKVSgc1ljsvTygXM5tZRChduyjk+JtE= +SHA256 (cargo/httparse-1.8.0.tar.gz) = 2JfzlLrWpwXV9BBHYuEWp1Y55HDYCQHu0FqGCpXLGQQ= +SHA256 (cargo/httpdate-1.0.2.tar.gz) = xKHjbIIdvgRXT2AoSKGfdC9Ps8mNQESfEbytGNaxdCE= +SHA256 (cargo/hyper-0.14.20.tar.gz) = Askp3Fw54zWgPEBSknKBGIYHIbEBkNmMKg8O/Vuq+6w= +SHA256 (cargo/hyper-rustls-0.23.0.tar.gz) = 2HxIwC4NxeO4SaIEHbMCn9BmZQ+PcXwHv47XjMuJXKw= SHA256 (cargo/hyper-timeout-0.4.1.tar.gz) = u7lYSC6Me+S8PPJyp2aisL8aZ1Xnpq53fwF6MdEbE7E= SHA256 (cargo/iana-time-zone-0.1.47.tar.gz) = TElfFirwvxdlbQAUoO3tXzzS82X90gRUjChp24k1ncc= SHA256 (cargo/idna-0.2.3.tar.gz) = QYoKb6uCFHX2NO/jzMRcAT90Lv4D2FPo0zVdXLhQ7Pg= -SHA256 (cargo/indexmap-1.7.0.tar.gz) = vGM2BUVBJd7EtmhDZz8Bx98riUebMuDtY05DqRz/YqU= -SHA256 (cargo/instant-0.1.10.tar.gz) = vuAyixIJ0VfvAByU3YW0+PZBOa2w6sJln0sIOCsvR00= -SHA256 (cargo/itertools-0.10.1.tar.gz) = ad24ifnQ0IpnM4Jx+ptimWvHiMd5alwYzwV0IKrtXq8= +SHA256 (cargo/indexmap-1.9.1.tar.gz) = EKNal3MDIP/o4tQQtdO2knm5jSwUvbi3Dqiez3iI1B4= +SHA256 (cargo/instant-0.1.12.tar.gz) = elu+gkxQfF2llWNV6Gp0bYLg4UZPZdhizF5x2nDpSyw= +SHA256 (cargo/itertools-0.10.3.tar.gz) = qanRn6Hnm2IV/ym51ogLcGFH8W6bHbseTllHtbArxeM= SHA256 (cargo/itertools-0.9.0.tar.gz) = KE8Y+FZR/hHoqZGyrbQssHgyXJlu0CbZlHGe/Pyh1Us= -SHA256 (cargo/itoa-0.4.7.tar.gz) = 3SUDYCGw3oigr/a4UAUVY8ZRbQv1P4Y4k47bud5zJzY= -SHA256 (cargo/itoa-1.0.2.tar.gz) = ESxnjUBQr84jP08oUrsutRkjCzzxLzNYUnVTfX5BV40= -SHA256 (cargo/jni-0.16.0.tar.gz) = IrvcJbSTQLxPw9nJbdhNh4xL7so142Ue+lPbUaaNfU0= -SHA256 (cargo/jni-sys-0.3.0.tar.gz) = jq9LwC0Xy91/9MdDjK/N9/uaRhMxOtEbT4/v59P6ATA= +SHA256 (cargo/itoa-1.0.3.tar.gz) = bIr4RnT+HyI6mCyTOg7hCGrE1AUqoPuAYMEsatg451Q= SHA256 (cargo/js-sys-0.3.59.tar.gz) = JYRRqxCzT4r1NBbR/atywi6AXwySoRNtWUcOwLEROLI= SHA256 (cargo/lazy_static-1.4.0.tar.gz) = 4qutI/vEKzcA8vJ5hE3IMq2ysusGmy35GPRVxOGMxkY= SHA256 (cargo/lexical-core-0.7.6.tar.gz) = ZgfGKqFh0j0XqQcsxdoL5nzfyJ06+x6NnIQr68JSX/4= -SHA256 (cargo/libc-0.2.126.tar.gz) = NJ1aWRzSi0nh0QN0cWF6Mt3NpXMbmUGQCAhfctWlODY= -SHA256 (cargo/linked-hash-map-0.5.4.tar.gz) = f7mzivkmCBQLhraTYEuf/MWCQkCkhNHs1HlbrLL+iPM= -SHA256 (cargo/lock_api-0.4.7.tar.gz) = Mn+ltqaUDkaZ7Empvq4epIRca6uTFOT4SsaHQhOdjFM= -SHA256 (cargo/log-0.4.14.tar.gz) = Ubm75sR9Ufw+GpuUWWWUa0xEFCq4eSxQg1qYDTYsJxA= -SHA256 (cargo/log-panics-2.0.0.tar.gz) = rgE2JX3yCSYdqhjWwWOUdXxj4DLieq/YsHeIsFEIK+8= +SHA256 (cargo/libc-0.2.132.tar.gz) = g3Hk5TQcOpbbEn6yRlrGgc7UxDPgHdDpOK2+8mupO6U= +SHA256 (cargo/linked-hash-map-0.5.6.tar.gz) = BxfO8byLY2xuHBu978CeYyLaipMhlm6JKO+A0g9/dw8= +SHA256 (cargo/lock_api-0.4.8.tar.gz) = n4C/WqyvJcv8ghDRz7cY8r87EcTFTlr+NsI2hTqOw5A= +SHA256 (cargo/log-0.4.17.tar.gz) = q7EuaHz7RKpA9B/Dl473ZEj5tgOMrWrvQlnTwJWiOC4= +SHA256 (cargo/log-panics-2.1.0.tar.gz) = aPndhUYZHBhQ7PZ9IvX/AKk1uJDQ6EcTFZpVSVzCrF8= SHA256 (cargo/lru-cache-0.1.2.tar.gz) = MeJPGtgyHKDooeCsE/I8tmjm9UZsLFcxn2pc8cyOOxw= -SHA256 (cargo/mac-notification-sys-0.5.2.tar.gz) = BC90pgYXXXLKSD4U4Ic/4PbAA/evRYZbF7Fv2vrOcgM= +SHA256 (cargo/mac-notification-sys-0.5.6.tar.gz) = PnLVDtsXdWSJ551S6xRpJ77I66ndSPqt+e8IvKN5GtU= SHA256 (cargo/malloc_buf-0.0.6.tar.gz) = YruQf+iNVNjZzjKjzOq0IY7S9rfTVhfK/prfhOQ5Gcs= SHA256 (cargo/match_cfg-0.1.0.tar.gz) = /77oY04NRdJYrLRI5+qrP856CkZzldTZ8ijjwfAfsuQ= -SHA256 (cargo/matches-0.1.8.tar.gz) = f/xcUzhGnU0+oX0mn6jqNRKtJHJHwwvS32nmgwntCgg= -SHA256 (cargo/memchr-2.4.0.tar.gz) = sWvUfZ4ylDXjCcWEaf4HkcLQ0bqW7AlUFSpa4rBDh9w= -SHA256 (cargo/memoffset-0.6.4.tar.gz) = WazMUH8TOANqBHfvYa/a4zzeYIQPTf5IExnOOtEW3fk= +SHA256 (cargo/matches-0.1.9.tar.gz) = o+N4tmoGDUiUe1kHN7MKG+dnBsjde4ug8v45icaKhT8= +SHA256 (cargo/memchr-2.5.0.tar.gz) = Lf/lLs8ndy5gGQW3Uiy073kNLMIDSIu9Di/oX8t0Vm0= +SHA256 (cargo/memoffset-0.6.5.tar.gz) = WqNh1Prqk2AwZKAnQV8HvY4dXIjJ+/aL9WooVCj9ec4= SHA256 (cargo/mime-0.3.16.tar.gz) = KmDHzlAcceA6nJwNNbhhQTrpJb2XnMek4w0GAGmqrI0= -SHA256 (cargo/mime_guess-2.0.3.tar.gz) = JoTUwul9mYSNMLMksAyPzH5ciXt8u1gZsJ58kOi68hI= -SHA256 (cargo/miniz_oxide-0.4.4.tar.gz) = qSUY6YwHhYa8bJNAKK3MpMkqU9apWBlt6DUXCgHYTks= -SHA256 (cargo/mio-0.7.13.tar.gz) = jCvbYxTsEINc0yk90mhHOoNcArezUueIvniLPGymuxY= +SHA256 (cargo/mime_guess-2.0.4.tar.gz) = QZImPCOKXw0Ma/0h8zajE6TOHEUFQkScoZG7ZXtGQu8= +SHA256 (cargo/miniz_oxide-0.5.4.tar.gz) = llkLqPF1IiZDqFaT8z0m6cigFfWZwhZQmxpolK9nXTQ= +SHA256 (cargo/mio-0.7.14.tar.gz) = gGe0BP6Xxwgp8ILeyLz09xIl1+rqHYZFNJy3b6BiBcw= +SHA256 (cargo/mio-0.8.4.tar.gz) = V+4cI8fGOwySUMM5/9xpJV8RCymLkBufbIJUe3uHyq8= SHA256 (cargo/miow-0.3.7.tar.gz) = ufHFsCXNqHb2bvQ6ET+R68n0zO80hDAA4K3267q4TiE= -SHA256 (cargo/mpart-async-0.5.0.tar.gz) = d9sv6n2EOcfmpiFhiQJjXLGEHmLV47F/f8SOLsymtGc= +SHA256 (cargo/mpart-async-0.6.1.tar.gz) = fqarI1nUXSQBvXulzlpnWC8qu4cuqewX9477asNZGGQ= SHA256 (cargo/multimap-0.8.3.tar.gz) = 5c5G/mSp1zvgfcvmkKOM4bKTvkSP2M4ebBuAYsn3LGo= SHA256 (cargo/nix-0.23.1.tar.gz) = n4ZjF6y9OiQHEMY/Bl/7Hk/UZiWQRcy1BBMLf2aPNcY= SHA256 (cargo/nom-5.1.2.tar.gz) = /7QmLSbtg6HAozo4/iuxV5cynIV3DaBea4KN23gmJ68= -SHA256 (cargo/notify-rust-4.5.8.tar.gz) = qZWj0oNM76OJIY56NRVujOVEvJX4NpANoB7gsmoH6dQ= -SHA256 (cargo/ntapi-0.3.6.tar.gz) = P2u5AuQ3tthuA8zhCn4q9mIpLF3+8jtliZ6jrJNUrUQ= -SHA256 (cargo/num-integer-0.1.44.tar.gz) = 0sxpimO1SacLwEcHPSlJzOJ80cewpKhi0IqAMbwoAds= -SHA256 (cargo/num-traits-0.2.14.tar.gz) = mmSx7FzaJYbihHIkhtgCrPH329xiPiv8V+Zcoc0JkpA= -SHA256 (cargo/num_cpus-1.13.0.tar.gz) = BUmfN1ZnHBWIX+6QNERpVv/z8kPWB3uR5XZ98WH3ZrM= -SHA256 (cargo/num_enum-0.5.2.tar.gz) = 5a3wGY1CfuUVM1Y58nXoBsoBrPnwfXzxS7NqEFMqYWk= -SHA256 (cargo/num_enum_derive-0.5.2.tar.gz) = sd71o/adRwfYoECxJ4W5gCmjnoxhCuaFx/YmVml2dII= +SHA256 (cargo/notify-rust-4.5.10.tar.gz) = No6J6ljfdHzoi+ZprkTnl4PB0wv9VArQ/FILP0Hws7A= +SHA256 (cargo/ntapi-0.3.7.tar.gz) = wod0p/0vu08Lq9gjfOVUtzr2gCG19pWjzr1sWbrAmA8= +SHA256 (cargo/num-integer-0.1.45.tar.gz) = Il0zifs1CaJMk/XCnra94lhrmNnwFmNt/1jXxvdWnNk= +SHA256 (cargo/num-traits-0.2.15.tar.gz) = V47eNM8C+JJKuUR/UMKAdbTT5bJplyNF5+A3KzjGzc0= +SHA256 (cargo/num_cpus-1.13.1.tar.gz) = GeZFJuve4YI0FXLlDprQOWWqUQzZRCekVJRI8oXpV6E= +SHA256 (cargo/num_enum-0.5.7.tar.gz) = z1OVZlZi70V5ak/1SGxdQdKeDAlkCvTF8X/ZTuLBGck= +SHA256 (cargo/num_enum_derive-0.5.7.tar.gz) = OwSYZB5T3WrBpPIlR1SMqmhkzEkzeEMZzRd1JxxaRs4= SHA256 (cargo/num_threads-0.1.6.tar.gz) = KBnOBB0u4TEDb0/J1q564SWjpA6XumTQT+eZrZ2ru0Q= SHA256 (cargo/objc-0.2.7.tar.gz) = kVsbRyvCHFNGTWyEYcnTr4Bboe+DfhysJUQo9Kdxd7E= SHA256 (cargo/objc-foundation-0.1.1.tar.gz) = Gt0bZZ42yWB8equGSnbHpMJ2DNDNLhIPP7i5UsfiK/k= SHA256 (cargo/objc_id-0.1.1.tar.gz) = yS1N20vXtQ1zDCFf+HF1TQ2msheISfiioqtpcS0MBzs= -SHA256 (cargo/once_cell-1.13.1.tar.gz) = B0hk2iBrSXO4TrkWgwINvv1qjD8POOBU2TlU6JGTXk4= +SHA256 (cargo/once_cell-1.14.0.tar.gz) = L3JUuZ4xytd9oksI6/YoiCc5pghXi7G838H5whJg18A= SHA256 (cargo/oncemutex-0.1.1.tar.gz) = RNEd5Gb0owBv6KXn7ITpO3nHDLmSrgqg62Ma0t+Kv+I= -SHA256 (cargo/opaque-debug-0.2.3.tar.gz) = KDnnlmXxMb21eC5R8sbJWZwTPGCYmCpUx5Q1i/QyUpw= +SHA256 (cargo/oorandom-11.1.3.tar.gz) = CrG8KiidNL0EozAyOsmKG0vILJ2fyx5mtjyqhNomtXU= SHA256 (cargo/opaque-debug-0.3.0.tar.gz) = YkqDQMOMG4D9VJCHhi2kukPgiFivAlsjblCbZkn8E9U= SHA256 (cargo/opener-0.5.0.tar.gz) = TqPrzXKlRwH1Y0XxZ4Wm06wt9+mG0nPrQ5XAsB2xeVI= -SHA256 (cargo/openssl-probe-0.1.4.tar.gz) = KJiNhyq3YJWm5qyI2ZtU/SZ3AnNP1//mEMon9TPduVo= +SHA256 (cargo/openssl-probe-0.1.5.tar.gz) = /wEaMCw5alGXaSQx/BlIAZFUr8F4uvfY43NnRCpGAc8= SHA256 (cargo/ordered-stream-0.0.1.tar.gz) = RGMMBZ6s/W4IvapRsdss4zEZyqTdwSNekjEJql8lzLE= +SHA256 (cargo/os_str_bytes-6.3.1.tar.gz) = O6+W45xTWdLrDdbMtCxiuR2WeKpoFg0mG54My/np3qk= SHA256 (cargo/parking-2.0.0.tar.gz) = Qnw4kvnng9kcwSgoUofnClniBspFJ3Ds6Ip296Pt3XI= -SHA256 (cargo/parking_lot-0.11.1.tar.gz) = bXdErAKd8i3KYoTv5OiYmR0o4whccGyXK819pKJ6Fes= -SHA256 (cargo/parking_lot_core-0.8.3.tar.gz) = +np4KTjnRXY/5pB/xrqGlG1y9J/n4h3gdOCBKKmfsBg= +SHA256 (cargo/parking_lot-0.11.2.tar.gz) = fRe3gDamBmO3l63q7kb1yd/ruGlI0SVQB6HWvgJx/5k= +SHA256 (cargo/parking_lot-0.12.1.tar.gz) = N0KywQO58GvJ//Cjf/SRKTWFG+5tNvPAK8x1W8/sIo8= +SHA256 (cargo/parking_lot_core-0.8.5.tar.gz) = 126OFJO8rA0nZsQnN/NEWPHIxQwNI7yyTqlTr/snMhY= +SHA256 (cargo/parking_lot_core-0.9.3.tar.gz) = CaJ5y/JcsHV4EDlPvB41mUm1njSBRcZDqTmlJWkuaSk= SHA256 (cargo/percent-encoding-2.1.0.tar.gz) = 1P1WQdAcjxiiPae2/ikpj/S1WvzM33iXOyTPMXX+4y4= -SHA256 (cargo/petgraph-0.5.1.tar.gz) = Rn0WSm3lYnC9fE0HDfgdB76s4lAS1RA87U6f8I1q/bc= -SHA256 (cargo/petgraph-0.6.0.tar.gz) = ShOi+p0LY+XyIyiCh0HlI3Zv/w7p53kxaQIpDf8/gk8= +SHA256 (cargo/petgraph-0.6.2.tar.gz) = 5tUBQlOhMxV5zmKqZ0Q7SmWMXn3QPUvG0wK5RHSIgUM= +SHA256 (cargo/phf-0.11.1.tar.gz) = koxlNd6TVIGI72O7fEA2vUFc2PNq0lr0S5eJsu5ypIw= SHA256 (cargo/phf-0.8.0.tar.gz) = PfthIy40/LYz9D0SxY+Dwd+Cli3N+lZaToZv/Bfa/hI= SHA256 (cargo/phf_generator-0.8.0.tar.gz) = FzZ/DMhvLSWAKywm7linsj+uzPeKOWCUwT3O0NAYJSY= SHA256 (cargo/phf_macros-0.8.0.tar.gz) = f2/eGP9Cn/yP544r9/i3paWm4qi1i8WprGkZi72pGJw= +SHA256 (cargo/phf_shared-0.11.1.tar.gz) = 4ftfb4JrdyqNTAOUIJRB59N8u7lnrpx+DoE0Nlye5nY= SHA256 (cargo/phf_shared-0.8.0.tar.gz) = wAz4uer+aN3l6eqizvjuhKkzakfVZuxVyhZYljO2Wvc= SHA256 (cargo/phonenumber-0.3.1+8.12.9.tar.gz) = EmGgFOX14Ei/LG8acvpeTCIwCdxfKWo4W5X+GbRkYI8= -SHA256 (cargo/pin-project-1.0.7.tar.gz) = x1CcwQYEHECkUY0q96YVMOHu0OYoUpaj2MVHKAbMxKQ= -SHA256 (cargo/pin-project-internal-1.0.7.tar.gz) = SMlQEyWDtQBVax79cdRbMZAp8rcVGNl5/MII4WtCQm8= -SHA256 (cargo/pin-project-lite-0.2.7.tar.gz) = jTHRHGmmtSoXS0K9wMMOXhFnD5B4iyxHHDHB0X1ElEM= +SHA256 (cargo/pin-project-lite-0.2.9.tar.gz) = 4KeuOsLxFzCF05hTHHBXVslKTFaEN4XfhaYMGgr6wRY= SHA256 (cargo/pin-utils-0.1.0.tar.gz) = i4cNjBUbby+5PoShMUYTjwXQLtEcfnxU+IJqqvfJ8YQ= -SHA256 (cargo/polling-2.1.0.tar.gz) = kjQdd5+jTqhDfvTYLUQNXhzj8/9/gkqmRCTNSB+aHyU= -SHA256 (cargo/polyval-0.5.1.tar.gz) = 5ZdFDL8gl4fw5t6AvzeVxrI1ajgO6Hg3tUWt7Y28GCM= -SHA256 (cargo/ppv-lite86-0.2.10.tar.gz) = rHTGJNay0h9CX3UiYvQhiDZde4/xr/dMguRRNlEKSFc= -SHA256 (cargo/proc-macro-crate-1.0.0.tar.gz) = Qf29HfYhVvvFlF9HYmMlZNfQOBUwkcP88QZ/au98/5I= +SHA256 (cargo/plotters-0.3.4.tar.gz) = JTi2OeZCKVVGxQ/NVFGYydZO4qOGIKYocko7Jm1fv5c= +SHA256 (cargo/plotters-backend-0.3.4.tar.gz) = GTIoYWOB/s3BIkxi6WlG37xz/0OE+6V24FL/jBvqgUI= +SHA256 (cargo/plotters-svg-0.3.3.tar.gz) = +agdJ1mq4drmaPeDwwi8XI69GR/0GEqqGzf2WmrlpW8= +SHA256 (cargo/polling-2.3.0.tar.gz) = iZsAucirVTx0Oz4R6HxcfUI7Ki3iKbqVskp1Y0R0gBE= +SHA256 (cargo/polyval-0.5.3.tar.gz) = hBnStiPHwIlv8tXZbiy07eWQ/tKPzDSTT0wzwDbmIKE= +SHA256 (cargo/ppv-lite86-0.2.16.tar.gz) = 65+ebiM+XEo1VZphe/QKTsRH2y6EwgtVpvgxZ7fleHI= +SHA256 (cargo/proc-macro-crate-1.2.1.tar.gz) = 7aD8Ow+3yXVjF1fhTZBJ2hc3QGPttuu8vFTYgNT+lOk= SHA256 (cargo/proc-macro-error-1.0.4.tar.gz) = 2iVJD/mJKqs/z3w28Iz7kC3T5xyg+flRe+oCpzpc44w= SHA256 (cargo/proc-macro-error-attr-1.0.4.tar.gz) = ob5AGA5S7MmK2AsYSTS689DSn5eVdOQ5r1pVJ0s1+Gk= SHA256 (cargo/proc-macro-hack-0.5.19.tar.gz) = 2/DEi8HZE3WuXDzYHjci3/Grz4GjCWAkBkDSI/Wf4OU= -SHA256 (cargo/proc-macro-nested-0.1.7.tar.gz) = vIgbLCJoE3DGp4DkevmEDvhBg3vJgRhDHU4YaL0MEIY= -SHA256 (cargo/proc-macro2-1.0.27.tar.gz) = 8NjK9ymGwaWYcmrcmIu1mEeS74T17lqlAgkUXugHcDg= -SHA256 (cargo/prost-0.8.0.tar.gz) = 3l4lM/WdCPzzZP03Tr2gaSpwvW1+Zu+X8wb0XGxdgCA= +SHA256 (cargo/proc-macro2-1.0.43.tar.gz) = CiyixhvJ89dNKIYpSre5hTq9nBrZA6OseBXFiYm7e6s= +SHA256 (cargo/prost-0.10.4.tar.gz) = ca30HbaKoNqu/Gm7MLzWje2bmrqtXR+7YwTE+zkOCD4= SHA256 (cargo/prost-0.9.0.tar.gz) = REh5J1y0/YSVixodVCDRXm/PfCNf5H8FPJwqgKzrYAE= -SHA256 (cargo/prost-build-0.8.0.tar.gz) = NV9jS0PN2Ack7nhI+Vdw5+cO76bc8U/qZ2IWVzuP1gM= +SHA256 (cargo/prost-build-0.10.4.tar.gz) = iuWkOIdi1YFan8DeozxWsCHNyN3gxV4MnKVxlyVLDKs= SHA256 (cargo/prost-build-0.9.0.tar.gz) = YpQXIvtnXUY2WeScTz/h/nkv8k/lu6qcCM07mKHDVPU= -SHA256 (cargo/prost-derive-0.8.0.tar.gz) = YA0vM0qgWssCp1XiF+8att6k1RtYt4RliLdH7ewE77o= +SHA256 (cargo/prost-derive-0.10.1.tar.gz) = e2cPRdpX+4VC69u2EFqSX+Vxtn+eftn0egaoTnK058w= SHA256 (cargo/prost-derive-0.9.0.tar.gz) = +cwaMmPgfgv2jpYmjzdmUge0lWDZhzlmLN+q4hXHIP4= -SHA256 (cargo/prost-types-0.8.0.tar.gz) = YDu9Y5RwHRPz8lqtpZx96dNaaliHz8FWGBI0pEACdxs= +SHA256 (cargo/prost-types-0.10.1.tar.gz) = LQoBQik2EBHcjmnIoexsLo0PKvfJHj6j9bIXAphGHmg= SHA256 (cargo/prost-types-0.9.0.tar.gz) = U0t6DoNuPEgtJpMHD5guOedhHalpXU0fWksYa1H67wo= SHA256 (cargo/pulldown-cmark-0.8.0.tar.gz) = /63gJJXyJFPNWTFZ6i9Zgnquf1P6gyP3VnmbZwiB3Pg= -SHA256 (cargo/qr2term-0.2.2.tar.gz) = ljRHjodNQVPFLRDW+GYK0bF75dWkiqcobz1S/SybfDQ= +SHA256 (cargo/qr2term-0.3.0.tar.gz) = 3Aq7j694IdMO4N6holywpMcBXdKOvJNWoCxygXlutOk= SHA256 (cargo/qrcode-0.12.0.tar.gz) = FtLxRV82MMblEHtPK5TnTXbeqAc23gmB/SdkQhbP9X8= SHA256 (cargo/quick-xml-0.18.1.tar.gz) = PMRA7kgCqG41cWUCHj4lWpFDck2jHbHi6lQCFMlqD4I= +SHA256 (cargo/quick-xml-0.23.1.tar.gz) = Ebr8hZxoFfuv+7v0Ip7LdnrJE/7LJ/mtQ0NmLp7wmeo= SHA256 (cargo/quickcheck-1.0.3.tar.gz) = WI9jeOTdmUWLYOwnW0R3rdQc5PqfZNy6bxWtzLGbUNY= SHA256 (cargo/quickcheck_macros-1.0.0.tar.gz) = sippMiLXFqlYd4bzesP2tPrttbgMI5FOcwP/Wh2AFuk= -SHA256 (cargo/quote-1.0.9.tar.gz) = w9C5dF3C3r9QfIQi3gXXImzB8GRCFt/f6tmI+bGrMqc= +SHA256 (cargo/quote-1.0.21.tar.gz) = u+RI83en1pYeMPWVX5uNEGw/XkSdST7hsSXB1DwrUXk= SHA256 (cargo/rand-0.7.3.tar.gz) = amsWedSbJLv+DIA0KaoYdEcvUNmzYxMfDon8NWtUTQM= -SHA256 (cargo/rand-0.8.4.tar.gz) = LnVzYy5kVM9rmdeqxMzKVL4G2gWsou90I9ItJ9TUvNg= +SHA256 (cargo/rand-0.8.5.tar.gz) = NK+NGg4lkkvFt8Q8B5yUIznY8Ki1fDkEm+9YG0YydAQ= SHA256 (cargo/rand_chacha-0.2.2.tar.gz) = 9MjthWJ5yXNyBr9yW/NpNdhmbq16pptSvlWvNp0ZNAI= SHA256 (cargo/rand_chacha-0.3.1.tar.gz) = 5sEKY6D6MiUr5J0h53CdTUuvjSMcLbzh6qgUG5sSfYg= SHA256 (cargo/rand_core-0.5.1.tar.gz) = kL3lKW/IkbDO8SptA93MwWLOeyr/VBYK+TOPjUDfbRk= SHA256 (cargo/rand_core-0.6.3.tar.gz) = 008UCPVSlEU3kMSLLx67scW0t1Y+sfQYvPz9uwbrtOc= SHA256 (cargo/rand_hc-0.2.0.tar.gz) = yjEpr3uSoXES1ZrUmMb4Hq9GMlN2a5A5bTnqejnWYTw= -SHA256 (cargo/rand_hc-0.3.1.tar.gz) = 1R6fWW3iJ/2i6myEYH9VWOGW7q9DyYa3JLpPuP30l+c= SHA256 (cargo/rand_pcg-0.2.1.tar.gz) = FqvQwbY56etNfFDAuBALDQ+Em+I0mCnHQP6ObrSBZCk= -SHA256 (cargo/redox_syscall-0.2.9.tar.gz) = WrSaut8/nhxLxJnohF4VKth9KtLTA3GEEXEWnp11/u4= -SHA256 (cargo/redox_users-0.4.0.tar.gz) = UoUy89gByHrsne8q3ZyoAv5WnkSlRK/mM3ZSZ4QKvmQ= -SHA256 (cargo/regex-1.5.6.tar.gz) = 2D8SfZS9vNpMjMLlD2+E9LYR9pyQJpnKOFo5w6dfn/E= +SHA256 (cargo/rayon-1.5.3.tar.gz) = vZnldy6ti6pSFSeMmxW/kgh3CenBstH5fNtaGDyTOn0= +SHA256 (cargo/rayon-core-1.9.3.tar.gz) = JYvNtaxtrUhJG7KZLba3z3SHiwOEkIrxJII9EYyZaD8= +SHA256 (cargo/redox_syscall-0.2.16.tar.gz) = +1pYwYVbS2gZ1ZASFVYD8LIq0wytdSYAqt/LaVJlUZo= +SHA256 (cargo/redox_users-0.4.3.tar.gz) = sDPYN6fPFi15k63tkwTjCoMhPGSLbjidsjMZH4keXCs= +SHA256 (cargo/regex-1.6.0.tar.gz) = TE6zJnF0uMbC9lQRZiORCg/vCcR1P43YPbKcSKDfmIs= SHA256 (cargo/regex-automata-0.1.10.tar.gz) = bCMNc/uNjBucCzE1xRQqis7joFWPuNtc8ctl+NeGITI= SHA256 (cargo/regex-cache-0.2.1.tar.gz) = L3ti1pdDuLlPNTtrfD3rTFWCgoMovLjV/t8hQ3OAh5M= -SHA256 (cargo/regex-syntax-0.6.26.tar.gz) = SbPensXcCjQX2jcaqxfXKZl8FQEOf9JP9wd3OjO922Q= +SHA256 (cargo/regex-syntax-0.6.27.tar.gz) = o/h7c84RsWGaPGMy9FNB4ARxc3cei4tz+Hv+77e1YkQ= SHA256 (cargo/remove_dir_all-0.5.3.tar.gz) = Os0SVmVCKXOjOsnT3S34XtrQ9K6bANr7GgXkOp9e+Oc= SHA256 (cargo/ring-0.16.20.tar.gz) = MFPPUuI2o+10bfx0WqnKzxt5HYRr2vQS9gqNfW4XyPw= -SHA256 (cargo/rustls-0.19.1.tar.gz) = Ne22df7uOa7JyZ+l/5hQgZlaBtWUEUrhTL55ete3ptc= -SHA256 (cargo/rustls-native-certs-0.5.0.tar.gz) = Wge3wYhb2O04McKJt4cLE+9G/g6FbSiMMNnMF9daIJI= -SHA256 (cargo/ryu-1.0.5.tar.gz) = cdMB1Bk9Axq915/3491yEWipVy7z/lGhUXq6I1vY+G4= +SHA256 (cargo/rustls-0.20.6.tar.gz) = WquO5scJftYFf0PBh6YkGNDAWkvV8Ys1cdtQ7g+c4DM= +SHA256 (cargo/rustls-native-certs-0.6.2.tar.gz) = AWe6x6n0kElfPDMBPncitTywh+y+CC+wxjh8lvY06lA= +SHA256 (cargo/rustls-pemfile-0.3.0.tar.gz) = HuhtY5cqfGYdFTb+/ow8hAcyHD32aIkSht4oq80Ic2A= +SHA256 (cargo/rustls-pemfile-1.0.1.tar.gz) = CGSu/1P4wFqgjYbl74OdPfzweuui2zLxLbDvcW6HvVU= +SHA256 (cargo/ryu-1.0.11.tar.gz) = RQGr3/OugqHBtHehclLrac7p5m65FcGrqk9E2HPfnwk= SHA256 (cargo/same-file-1.0.6.tar.gz) = k/wdw6qpv+2V4C5urau0uvfjB4sL0bTXtrC2g3iQBQI= -SHA256 (cargo/schannel-0.1.19.tar.gz) = jwW6YJwjTmC+4NVH/pSkx+nacz0cliz25Z76TNnIvHU= +SHA256 (cargo/schannel-0.1.20.tar.gz) = iNZzEUZGLqJdkkSy7V/R1xbSXFLk1Uqk+w88TphU2+I= SHA256 (cargo/scopeguard-1.1.0.tar.gz) = 0pqwxtP8Dukv5m4tmfcA6rF6jVfRwdO3SDgPsguqeM0= -SHA256 (cargo/sct-0.6.1.tar.gz) = s2K4OJjg5p84UVuC7hWqgGNr7+R8O209iakR54/CKM4= -SHA256 (cargo/security-framework-2.3.1.tar.gz) = I6KshRR6OhHXfs8bxxZuwLkv6/pEYcN5ROGA8xns5Gc= -SHA256 (cargo/security-framework-sys-2.3.0.tar.gz) = fk7/uRtLi2+3cy5nC2zuFgJ4/45r9IXHgF2eMZ124oQ= -SHA256 (cargo/semver-1.0.3.tar.gz) = XzqsV+5/MnLYOVxuT1AvQ08OKJ/NYodvcNqgCMINyr4= -SHA256 (cargo/serde-1.0.126.tar.gz) = 7HUFq+rK7HSuR3jZ2TKP5aXQQlMiCoXE7gIiOfyZbQM= -SHA256 (cargo/serde_derive-1.0.126.tar.gz) = ljp9vJiVrqx6yQ5080pdUmGCj3nfNcvtQeEBidOATUM= -SHA256 (cargo/serde_json-1.0.64.tar.gz) = eZ6X3J/a42pci48srpzi7p/c4gWMV6k+YJnZGf2YL3k= -SHA256 (cargo/serde_repr-0.1.7.tar.gz) = mNBRaQBRjCnvohfCmPofTmxv/IWuKf1/TuSPF24antU= -SHA256 (cargo/sha-1-0.9.6.tar.gz) = jEz6dBxYMtDvf6tGyr7SnCqukm2wsRuyBp7djbXmThY= +SHA256 (cargo/sct-0.7.0.tar.gz) = 1T3Nt8n4FYk3p5gbSKzP05pDr0GFkaXQCMeyK14bfKQ= +SHA256 (cargo/security-framework-2.7.0.tar.gz) = K8G7l4BK9mMYE8VXOfdxBx4PLtM+4gtoyG7FBdkGNWw= +SHA256 (cargo/security-framework-sys-2.6.1.tar.gz) = AWChOhd6Rb+0POccAVgJmEdPVWrYVNy8qTbdKEGlxVY= +SHA256 (cargo/semver-1.0.13.tar.gz) = k/aEHnCQA9aLst7ujDQ1cr9EYAPsIKWD5297Fc6/NxE= +SHA256 (cargo/serde-1.0.144.tar.gz) = D3R3EN49zUO4jJFodzJU6AnY3b35ZTuE4lVKshnxeGA= +SHA256 (cargo/serde_derive-1.0.144.tar.gz) = lO06gW+x0QGBL4PnifiIMiw04pH4lPGVkNwxCWPoegA= +SHA256 (cargo/serde_json-1.0.85.tar.gz) = 5Voo46rvnVzgUG0KFNu6gFTdx+SZ71It2LJoWeydSkQ= +SHA256 (cargo/serde_repr-0.1.9.tar.gz) = H+Odn7sOv16yx8t+Kkfk9GL60TefEWa4rkmtnq6Jp8o= +SHA256 (cargo/sha-1-0.10.0.tar.gz) = Ao9I1RP5Z4zaKPbkBkdVs/uyr2rNZy8sIJtiMj966g8= +SHA256 (cargo/sha1-0.10.4.tar.gz) = AGdpuoPpIbMIXKqDNBhrAM+StMsabPRjL7zMjv9cdUk= SHA256 (cargo/sha1-0.6.1.tar.gz) = wdoFyXRFyqEtBehIxKT8u+op50isKPfoDpsBA5IGN3A= SHA256 (cargo/sha1_smol-1.0.0.tar.gz) = rhpHGGwDoyF3BC5V28X9Wu6QC44AaajXD7qWqTdc0BI= -SHA256 (cargo/sha2-0.8.2.tar.gz) = olb0bqeKDA2f8AB3UEkDrIgaHa/cINpmVFaZ53drPmk= -SHA256 (cargo/sha2-0.9.5.tar.gz) = s2KuV1L9ITdzH5+iX9TZBYrzRmbKGWb7lpEZzDVxnxI= +SHA256 (cargo/sha2-0.10.5.tar.gz) = z52wNTTf+ZMYcGTE4MBaVwjSqXKKzpqJWbd77fQV2sU= +SHA256 (cargo/sha2-0.9.9.tar.gz) = TVih4b85dJgH2Jzy2YrC36D/HLP6o4+7ZN2IrIAT2AA= SHA256 (cargo/sharded-slab-0.1.4.tar.gz) = kA+6gG9wxjCwo4LQ2CXheg8Z/NBZoq3h/yN7zd9EazE= SHA256 (cargo/signal-hook-0.1.17.tar.gz) = fjHUQsFvBHpnG1px4hYdbmiBQBK39TedJp69kV+sJyk= +SHA256 (cargo/signal-hook-0.3.14.tar.gz) = olO16J4mmEZPwmtUXJ7c6zOOGKie/+7s/qGSwwJb4p0= +SHA256 (cargo/signal-hook-mio-0.2.3.tar.gz) = Ka0uFfN+yabMVECXt4oeyQAB6fcbgTOMo59DCtrKma8= SHA256 (cargo/signal-hook-registry-1.4.0.tar.gz) = 5R5zMo3ErAx8y9o6SU36A98d4vRgGBJ/YMaT8mSEVbA= -SHA256 (cargo/siphasher-0.3.5.tar.gz) = y85tRQfH5KOWIJFDblbpUpDLcfowLQ0nDjITC3X7/yc= -SHA256 (cargo/slab-0.4.3.tar.gz) = 8XOsPRp+OygAP0DeC1zn/icQ+bncP8OGZM6+5Gs7ZSc= -SHA256 (cargo/sled-0.34.6.tar.gz) = HQEy8+OTvLc5DGC7RXaUmM9FULy3oh1/lcArafY2LNw= -SHA256 (cargo/smallvec-1.6.1.tar.gz) = /g83yejzxaSmatZVqTx02qxK0AxEFTO/XG55kLtCYE4= +SHA256 (cargo/siphasher-0.3.10.tar.gz) = e9PjIGiZrz+LEq8oT6/AOMwdwrQdG4ndFylyIcXSJd4= +SHA256 (cargo/slab-0.4.7.tar.gz) = RhSnayqL4AWMqp27r2bZiFJ9htADwRqU+9M112Ye3O8= +SHA256 (cargo/sled-0.34.7.tar.gz) = f5a0c3ws5ZhzVIVa7TeXJ53vTr9zRDbGqkVSz44WmTU= +SHA256 (cargo/smallvec-1.9.0.tar.gz) = L9DbdJWX2R/4Yv0dVeqH94VadEqEJaZGlbb8ojfR2tE= SHA256 (cargo/smawk-0.3.1.tar.gz) = 9nrSJHZ/qjx9i22RmFt45woTJECKvLHPzCvkwGvAYEM= -SHA256 (cargo/socket2-0.4.0.tar.gz) = nj38IHxSYBXGMkcqd74JzxtuRoZlga7K5cw4+0I13qI= +SHA256 (cargo/socket2-0.4.7.tar.gz) = AuLS25Az0ToVZxId3XoJXuFE204cobG9o0GbwNopTr0= SHA256 (cargo/spin-0.5.2.tar.gz) = bmPP8yCuLFeQRnm6fLYygKPcRhOIW+r7FI7nv5qpBC0= SHA256 (cargo/static_assertions-1.1.0.tar.gz) = ouuTSbZESzJocuFA6xz158UiFU1p56D/sPuBwGs3VD8= -SHA256 (cargo/strsim-0.8.0.tar.gz) = jqURnNtMVbVdQyq7UToEKThIeMFd3mDMd7HJneGpWmo= -SHA256 (cargo/structopt-0.3.22.tar.gz) = abBBzctnImrKMH5ue+RMiAZCPYPgGL1mI2CpPavOTXE= -SHA256 (cargo/structopt-derive-0.4.15.tar.gz) = eBOTSuz19RpUd14ABowjfemEiUY5aCMaUXRru8A/nBA= +SHA256 (cargo/strsim-0.10.0.tar.gz) = c0c8Dlnm1YEsXf4qBkpkRJSfCJ4g7smi5VBllklORiM= SHA256 (cargo/strum-0.22.0.tar.gz) = 96yJPH1HHIoh8xz+IT7E9tmv7tJVN8dy4I7z8AX4cp4= SHA256 (cargo/strum_macros-0.22.0.tar.gz) = M595nYtUnjdEx6x/6yFjg+QAXZS9siVhs6uPO4CK6fs= -SHA256 (cargo/subtle-1.0.0.tar.gz) = LWelpium4ByyGS/zCTJMtIddDEUdVf4jGUM6vnoFqO4= SHA256 (cargo/subtle-2.4.1.tar.gz) = a97zLoFQwqCBEQtCdy/+fXyQMrYGvCJsgmD9l+CXZgE= -SHA256 (cargo/syn-1.0.73.tar.gz) = 9xSJ/zADDSrlmFJPYTJrkCRm9yoPsahWTAAcxjQlvMc= -SHA256 (cargo/synstructure-0.12.5.tar.gz) = R0qqkm+qFgPEC3iFqerqKbRE0csoUMt8Dje7GkGC9Po= +SHA256 (cargo/syn-1.0.99.tar.gz) = WNvvbsZVBV4guGsVqMxtQ5zKGbZnU3rGoTaVctFRqxM= +SHA256 (cargo/synstructure-0.12.6.tar.gz) = 82vapgqDrKOSG1JZ1UAMv16Q/FGTE3apvUoOt5qnIQ8= SHA256 (cargo/tar-0.4.38.tar.gz) = S1WAfANE4ebATXyWX1KJw5qNlK4j7VwLV6q6xUn4ccY= -SHA256 (cargo/tempfile-3.2.0.tar.gz) = 2sHGY8/JOBD4iu2biUHUjKv4VqGxEcKaQEOQGNhw6yI= -SHA256 (cargo/textwrap-0.11.0.tar.gz) = 0yZhD0CMek629Rw3wzDklrCFBslFfJ00KH7MOICfsGA= +SHA256 (cargo/tauri-winrt-notification-0.1.0.tar.gz) = xY3gNsTS4gcXAk3io8S/VsMB8HshvI75tXGJ/OBvHzs= +SHA256 (cargo/tempfile-3.3.0.tar.gz) = XNse9OrurdyPvTceUBcFcGSvCRGQLvNrOYAfZ8xteeQ= +SHA256 (cargo/termcolor-1.1.3.tar.gz) = urJNMLkRsjdvOhPMLNRDFC8Mgd2gTBGGk+NbODV1d1U= SHA256 (cargo/textwrap-0.14.2.tar.gz) = AGbI0Sr4tazSHgBUfDeX/eToZ3JUp+5CkXbM676T3YA= -SHA256 (cargo/thiserror-1.0.30.tar.gz) = hUur5S5N8WU3BrmPz8BYQwEAObQGh1kwpw5NlkTlxBc= -SHA256 (cargo/thiserror-impl-1.0.30.tar.gz) = qjL9P2J/Nn/hb4k+JZeuPAUCD4u6Jmak5upz03flcUs= +SHA256 (cargo/textwrap-0.16.0.tar.gz) = IioiKlv+G7pKd7RexIinQbPLiHLl5JlFH9fQEpycfD0= +SHA256 (cargo/thiserror-1.0.34.tar.gz) = jBsFyp0Qa6fS4xqdq0pk574szkFTIZZuoxMsSaZW4lI= +SHA256 (cargo/thiserror-impl-1.0.34.tar.gz) = 6PJZGYNkLehckhAV8/BwxmWhl+1p5BevQ2EV46FAdIc= SHA256 (cargo/thread_local-1.1.4.tar.gz) = VRbCe3gxHFC/QsBxQlxWCseZsRwwsx+H4wgZZf5eAYA= SHA256 (cargo/time-0.1.44.tar.gz) = bbnmkUq4sa4cJgpK56SbbFYRtAMopzWyGGJWdoXnMlU= -SHA256 (cargo/time-0.3.9.tar.gz) = wnAuCKeoYPAFgmxoFdysEBsZteszDCf+Slko/sHSDd0= -SHA256 (cargo/tinyvec-1.2.0.tar.gz) = W1Ig8Fu33n8/U8fAZeEZmzFyaW/i25+cTYrZtO50w0I= +SHA256 (cargo/time-0.3.14.tar.gz) = PD+aKLYYw6a5JRtpCOnJngS55cAuZYHMu2fVnDTvf5s= +SHA256 (cargo/tinytemplate-1.2.1.tar.gz) = vk1rXxn/dmToyY0D4hOctRDbmwpgtV+Ohwm2idk5trw= +SHA256 (cargo/tinyvec-1.6.0.tar.gz) = h8xc6zh1uyDCiQAFpOImpGUSZKXHXtskIbUoYaCgy1A= SHA256 (cargo/tinyvec_macros-0.1.0.tar.gz) = zadNp+GmZPeVux+Kh+xAb7iaAlIs9uUGINAWrdbbv1w= -SHA256 (cargo/tokio-1.16.1.tar.gz) = DCemS2Jd5tMJ6MV3FrqTAh3M8bO1yX7dbT3S0hNa/Ao= -SHA256 (cargo/tokio-io-timeout-1.1.1.tar.gz) = kMSfEGviQN4VRXHdMfvkissQumxt1vZRetYDq/+kLek= +SHA256 (cargo/tokio-1.21.0.tar.gz) = iXl6/WnSBszRH7DqVgpEu7h3MdAgZw55QW1EKRklfUI= +SHA256 (cargo/tokio-io-timeout-1.2.0.tar.gz) = MLdAIq2mFKG0g03nZfm7Q4d/kQzIzkvkDokELJIjqL8= SHA256 (cargo/tokio-macros-1.8.0.tar.gz) = lyT5qXX7mH73o82b4DUO3L4TBpivW496Yx4j1C0FJIQ= -SHA256 (cargo/tokio-rustls-0.22.0.tar.gz) = vGhE3nLlffGYAFSzi+Op9HAqukhYvmTdcAGBqKbQ4bY= -SHA256 (cargo/tokio-stream-0.1.7.tar.gz) = ey8/aYJT8DEZrAECvqpk9npn4IB00Doi0YeEEEVDcn8= -SHA256 (cargo/tokio-util-0.6.7.tar.gz) = HKoLDI2UoEnbVrWs+MupncBiOqsbJtW19eLZRYRrNZI= -SHA256 (cargo/toml-0.5.8.tar.gz) = oxFClwgmcz34JB7zXcBA75jGeasU18PlTYJwmbOs7Ko= -SHA256 (cargo/tower-service-0.3.1.tar.gz) = Ng39HW0w4F/aMqziyMcOnAqdpxMnV3f1pNu4oYk5MMY= -SHA256 (cargo/tracing-0.1.35.tar.gz) = pADjGqYLnUSlKo7gNDtbGFZrA6gyHg0yH2lc9W6UAWA= +SHA256 (cargo/tokio-rustls-0.23.4.tar.gz) = xD7oOQMRPgOYTLnlzr5sBKURYmnpAOPduo8GimKt2lk= +SHA256 (cargo/tokio-stream-0.1.9.tar.gz) = 31TVQRfW/cTk/qQP4eTlZrNQVwDhSKaCflmzSw0mANk= +SHA256 (cargo/tokio-util-0.6.10.tar.gz) = NpQ+4BptZ5d90/hKWh0u/rSto6Gudxyt+qU12dn8ZQc= +SHA256 (cargo/toml-0.5.9.tar.gz) = jYLhp3WGIqRl+M7gd2FMc0hNrFuDbAL/akDV0QEDJNc= +SHA256 (cargo/tower-service-0.3.2.tar.gz) = trwcnOK1E1rH+TxykY/Df+uHK9xqVTOouF60uGv9rlI= +SHA256 (cargo/tracing-0.1.36.tar.gz) = L86VZ71gpn0IoWSIdWchujkvJPKQBkAogeQ7GarGQwc= SHA256 (cargo/tracing-appender-0.2.2.tar.gz) = CdSPcaeRY4UZUFzvr+FiYG9wbCVZLkveTZdgDAGVMS4= -SHA256 (cargo/tracing-attributes-0.1.21.tar.gz) = zGuK01Z0mfmKHbenUrB6fIx8fDTDMuwA7/srACeXS3w= -SHA256 (cargo/tracing-core-0.1.27.tar.gz) = dwlZW4h4pJZc5eh+v4gKfTnJr8aDdyGyGlqBaoEX2SE= +SHA256 (cargo/tracing-attributes-0.1.22.tar.gz) = EcdYk69Vm8jhBxZUi971yyuYP45jfbnQ4VEmthtITuI= +SHA256 (cargo/tracing-core-0.1.29.tar.gz) = Wu6kMDB2VYoAcUuCP5rWfViju9od+D2IJ9IRkxVuIvc= SHA256 (cargo/tracing-log-0.1.3.tar.gz) = eN2tM9LRCx7X650fUYpWdHE4dul+W7m3NFp5hPu0+SI= -SHA256 (cargo/tracing-subscriber-0.3.11.tar.gz) = S8KPk7r/OAN/ZOb0PTTPoWBfJ6ScNOigTF54sLq/JZY= +SHA256 (cargo/tracing-subscriber-0.3.15.tar.gz) = YNuGAyLaGRtAlSrZr/5l6iPn3WpcRCwsQoZYEMarjms= SHA256 (cargo/try-lock-0.2.3.tar.gz) = WVR7znHZw4uD2cDpK2BmxCUzcfFQBd7www2WV/UMdkI= SHA256 (cargo/tui-0.15.0.tar.gz) = hh2POtMU7eYhm8squEQFSx3iee43qbw449YG+dP7KnE= -SHA256 (cargo/tungstenite-0.15.0.tar.gz) = mD1AdHvOh40vtn2RDcuL0+yisjWFQMPMG5jAJ0B6OuM= -SHA256 (cargo/twoway-0.2.2.tar.gz) = xX/7Rg18JM1u2kNpQRAYkDCj0d/kGEFtlGj9HB0pC0c= -SHA256 (cargo/typenum-1.13.0.tar.gz) = h59pBkkqfNIVv6TPWVtgAUbM+sDHm8vR8wABYq9eiwY= -SHA256 (cargo/unchecked-index-0.2.2.tar.gz) = 7rqG1CLOGBpxlEXlGHL6MPH3QTtivstS6V7JGqJi2Fw= +SHA256 (cargo/tungstenite-0.17.3.tar.gz) = 4nmS/WqMKe5+7yj8eDSaokQTThCtRHzjufCsDtD6TOA= +SHA256 (cargo/typenum-1.15.0.tar.gz) = 3PgaxZ7cF8yGl/8xHo9e8tmfy9mBezTOxm+QtsPf2Yc= +SHA256 (cargo/uds_windows-1.0.2.tar.gz) = zmVgQyTTzOm5ZnAUifvQzzGMsfe9ndB6yaTub7eRkw0= SHA256 (cargo/unicase-2.6.0.tar.gz) = UPN75hd5RgKqu+7gvk8lncF3j6vgXi1n7o95Mm1ctPY= -SHA256 (cargo/unicode-bidi-0.3.5.tar.gz) = 7ri+IJuxyWt8F3x0INJuBOzKyw7q5rmA41/LdGeBB+A= -SHA256 (cargo/unicode-linebreak-0.1.1.tar.gz) = BaMfRdGKMhO5GAGfeP5qc6FKuJaAfwqvViKqBoR0lFU= -SHA256 (cargo/unicode-normalization-0.1.19.tar.gz) = 1UWQkylBqekmbwgy3u2E6+G/LkyeSjVU05PRj16FS/k= -SHA256 (cargo/unicode-segmentation-1.8.0.tar.gz) = iJWEmpSeeEXga9bcGqUXMaEDxCcHAQpbWRwAOPtzOFs= -SHA256 (cargo/unicode-width-0.1.8.tar.gz) = kzdZGJOhm4jY2H8s7B5z+tXN/RDlpvNJ9JitbqL/seM= -SHA256 (cargo/unicode-xid-0.2.2.tar.gz) = jMuC1h+ApmPv4feHpRsWtaUeMxTWrDZbCGOfUjh7M/M= -SHA256 (cargo/universal-hash-0.4.0.tar.gz) = gyayxlSTLj5PkZbmnQj998/XGOHcb2azR+YCSgyWFAI= -SHA256 (cargo/unreachable-1.0.0.tar.gz) = OCgQh3/kSJkd/H8N1uOuXVgIj9DqXjUYllX4TmgU+lY= +SHA256 (cargo/unicode-bidi-0.3.8.tar.gz) = CZtxKDAdKF953dVbmoPV5rnpfJLg6g2uvucmPpMt6ZI= +SHA256 (cargo/unicode-ident-1.0.3.tar.gz) = xPWzehVJmajz+YzCOmKNhQ4VRHnNlN7PNBRpbhLjGq8= +SHA256 (cargo/unicode-linebreak-0.1.2.tar.gz) = OlLcqrDEjZMffMjvgm+lFpCgjh6lURfvJviYZPUyOD8= +SHA256 (cargo/unicode-normalization-0.1.21.tar.gz) = hUy9xPe8auGcgg1Eq9wyd6w+GyuT2yCmNoJdkyL7YOY= +SHA256 (cargo/unicode-segmentation-1.9.0.tar.gz) = fogg9dd39iJNxL42MiIpcawwFk1KJY1ZVkB5lVTr/Zk= +SHA256 (cargo/unicode-width-0.1.9.tar.gz) = PtdC1Oor0RduI2FyyEKar1RIbnrAmNsp/+ZSngzlCXM= +SHA256 (cargo/unicode-xid-0.2.3.tar.gz) = lX5R82RpEFRkYuZ9X3WZueT7is3TBLCHpklHMPnuvwQ= +SHA256 (cargo/universal-hash-0.4.1.tar.gz) = nyFOj2l+klAB5m7CxuN6Tvk/D3jC7teBQ5ThDGICWwU= SHA256 (cargo/untrusted-0.7.1.tar.gz) = oVbGhMkep9YmJlCbzjy04dntXE2Xj3tDUmWPlqTCa0o= SHA256 (cargo/url-2.2.2.tar.gz) = pQfDg7LTO1/DXRhh535rOD0Viy2l4U/lG4Pf7fb9V4w= SHA256 (cargo/utf-8-0.7.6.tar.gz) = CcyO5y0qm+zy8v6+AgW77Y/GYVt8tCmtBi3Ht93QNqk= -SHA256 (cargo/uuid-0.8.2.tar.gz) = vFz5jYGGJEQUyEgBfw4mdrP8tGgH9maKl9/mc1mjxLc= +SHA256 (cargo/uuid-1.2.1.tar.gz) = /rQeePkzY7st+LDoaiyjDu14BuoW6gx5DXV8+T95voM= SHA256 (cargo/valuable-0.1.0.tar.gz) = gwt+XU2QA0AylA5Kzg2amgV+ekXNlObAB4MuOe24L20= -SHA256 (cargo/vec_map-0.8.2.tar.gz) = 8b3fEYe+aS55xf/quJETLfsPI27TakPH7TnxFl7iAZE= -SHA256 (cargo/version_check-0.9.3.tar.gz) = X+zcqaUpHMK43PfcAkU/7nkaKA83Q8sJBfiCKuRjs/4= -SHA256 (cargo/void-1.0.2.tar.gz) = agLkiF7TvA8t6Q6m3UXry7ZtrP/gNUf627DuridwiH0= +SHA256 (cargo/version_check-0.9.4.tar.gz) = SYdLUWe2XXGTuKuhVn9cfZPQAcr8NGAM7gA+2nh+SD8= SHA256 (cargo/waker-fn-1.1.0.tar.gz) = nVssYrQBKj4eylp+B30Ts79JjEBz4zzNWGJmB3SM7so= SHA256 (cargo/walkdir-2.3.2.tar.gz) = gIzyc1zUtoZhE/ZIt5HGrcVxRTe8Ii2TR7sgM4b/2lY= SHA256 (cargo/want-0.3.0.tar.gz) = HOipaMsc0RDRNv+LgZpVbW+22Rk2PGFTT2hgx+sXK6A= SHA256 (cargo/wasi-0.10.0+wasi-snapshot-preview1.tar.gz) = GhQ1l8p8d5Pv95Te81LUF5KpPEgesQQkI/9/9yuiwx8= +SHA256 (cargo/wasi-0.11.0+wasi-snapshot-preview1.tar.gz) = nI2H5ytko7TbKNEc4pI3wkYYj09RBX1lp+q2O3mH5CM= SHA256 (cargo/wasi-0.9.0+wasi-snapshot-preview1.tar.gz) = zM3fMlVP7MastYX4KjKnLii0j4xMGIPd/u6qlvfY5Rk= SHA256 (cargo/wasm-bindgen-0.2.82.tar.gz) = /HZS4/bEcGyNnNVIMsSkzLm1M24sO9FU1czPvxwfX30= SHA256 (cargo/wasm-bindgen-backend-0.2.82.tar.gz) = ZizUSAVYa9UpcblYax34XNu9kRLk702PQVWcM03GrD8= SHA256 (cargo/wasm-bindgen-macro-0.2.82.tar.gz) = smDxPTASBx37FRKEnAM7GSUDg3OupIztMBLAnflSxgI= SHA256 (cargo/wasm-bindgen-macro-support-0.2.82.tar.gz) = W+jmVL3Zt5IWwpKauQchqoL69lxIzfCL3E5/UTV7gNo= SHA256 (cargo/wasm-bindgen-shared-0.2.82.tar.gz) = ZZjdC9PH1RCV/2UxpbI+AqzcgYBOMNjwevt3tyFaFAo= -SHA256 (cargo/web-sys-0.3.51.tar.gz) = 6ChBezefPfcRHToqnldTcGyuKcQffEAp7p/Xfz4J5YI= -SHA256 (cargo/webpki-0.21.4.tar.gz) = uOOMBggmLEbUpWIC66vesJTO9+VgynoibGvwVRiKpOo= +SHA256 (cargo/web-sys-0.3.59.tar.gz) = 7QVasn+UFCMZfrhrIDVyCxo85AUE3wgsrC7MbtczNaE= +SHA256 (cargo/webpki-0.22.0.tar.gz) = 8JXXgZLiCBgwgcwHvFUV71UhY5evSLhz5e3NcmN/ob0= SHA256 (cargo/wepoll-ffi-0.1.2.tar.gz) = 10P97cXGQ3e1/CvANrAcf9ZCIFoNljVgNK40BNSet/s= -SHA256 (cargo/which-4.1.0.tar.gz) = tVVR5Cy98s4r7dIgPQzAjboALCdRD4battDOMEy6Pf4= -SHA256 (cargo/whoami-1.1.2.tar.gz) = SrrPMlyVjf6vEEaTHTfyqQG23+CWjullop6UxnZrKvY= +SHA256 (cargo/which-4.3.0.tar.gz) = HIMfu+6eEpqM+T53R6gtqdlbqOFmIcrmDsLNyEm6y3s= +SHA256 (cargo/whoami-1.2.1.tar.gz) = UktY+logovswFN1jWLcOZXlpKlbvb86SiDTkiPQvZeg= SHA256 (cargo/winapi-0.3.9.tar.gz) = XIOaZ0/NepiVLlkyQupACr6TmSdGdh44ZBQF0osA9Bk= SHA256 (cargo/winapi-i686-pc-windows-gnu-0.4.0.tar.gz) = rDuHxjYgQm3ZuZHlzgMp7/VFvMu7NPO+Cf9vtqtRt7Y= SHA256 (cargo/winapi-util-0.1.5.tar.gz) = cOxs6FuxWBUcrl5ch/lajpfSwMSwASI/M6M0485d4Xg= SHA256 (cargo/winapi-x86_64-pc-windows-gnu-0.4.0.tar.gz) = cS4ieEHQV8HuHNL7Ivp+WlRhro5I+iynnsQs/BkxGD8= -SHA256 (cargo/windows-0.24.0.tar.gz) = qfOTRa4MirBywKx/6Ki0EWNqo0+Jvhnd0NkiZUTxOUQ= -SHA256 (cargo/windows_i686_gnu-0.24.0.tar.gz) = wIZlEKPsqa7XOgd0kLu/A+XqrE4f1whJ2JU55YMFAf0= -SHA256 (cargo/windows_i686_msvc-0.24.0.tar.gz) = vw/+1Wt+k2mikHjSqzquzupI61iZnSz/OqJJSidblcY= -SHA256 (cargo/windows_x86_64_gnu-0.24.0.tar.gz) = OEoXNjBYgEQgWimTtoZKL1blqMHnZowHuT7BjPSIjcQ= -SHA256 (cargo/windows_x86_64_msvc-0.24.0.tar.gz) = m9jwYtjKVEY1gVnXmpC+EsVDs6llyEfI8+7fFLMh05k= -SHA256 (cargo/winrt-notification-0.5.1.tar.gz) = AHoDU4QLI+DG3HPluWL/WO1/a8nO/zzn/m+62NSW7fQ= -SHA256 (cargo/x25519-dalek-1.1.1.tar.gz) = WgwQUVIQfjuW9qAKZehs6C2bElIw4cQwKUDspY/3H08= -SHA256 (cargo/xattr-0.2.2.tar.gz) = JEw3QfQkDvRidIYDl8fHTlDrI2JJlpMOSEwWZ5YzpUw= -SHA256 (cargo/xflags-0.2.2.tar.gz) = oluFyg/PLQA/Kwz9znOJfFTsPXk9/gCKZN5QQCCTY8k= -SHA256 (cargo/xflags-macros-0.2.2.tar.gz) = AAVSCNiDnxFokBL+y0K7wCTiW/OvkbO5h5c5082mW/A= -SHA256 (cargo/xml-rs-0.8.4.tar.gz) = 0tfTlIYT91yY/ZMoz9zEWsxNNgZVKJ0KfU7JMTkiAKM= -SHA256 (cargo/xshell-0.1.14.tar.gz) = xkA2LxsVDhhrduiGBuSwGnsvHVbMUPzBhN22g/tWfCM= -SHA256 (cargo/xshell-macros-0.1.14.tar.gz) = BgfAlclsHYQgzkoBiglU+xXXPV61m1IaBaDwTP/AUFk= -SHA256 (cargo/zbus-2.1.1.tar.gz) = e7hvPUWS4mpIsnGXQq7JT4rmI4694g2YGD7hhdEnXpo= -SHA256 (cargo/zbus_macros-2.1.1.tar.gz) = NoI8wQ/dw8axnwSJAyYtrK+CdBcOmiVXhL3YtFcKgEA= -SHA256 (cargo/zbus_names-2.1.0.tar.gz) = Rd/Nz4e3Ha1QXTDMJ7G3uIpkttHENWSPSPnbwf3Et+E= +SHA256 (cargo/windows-0.39.0.tar.gz) = 8cS9ClCsYCD2UYRyH3WNuke7n7whM99xXsdKI3smeUo= +SHA256 (cargo/windows-sys-0.36.1.tar.gz) = 6gQVWhaln56reG/hKkpFDnXNsXX54NgNoeF9sJ9VuNI= +SHA256 (cargo/windows_aarch64_msvc-0.36.1.tar.gz) = m7jD/Tmt4tZ+mHSsTz2yHw1xC+4A/nyrFpSewYTuqkc= +SHA256 (cargo/windows_aarch64_msvc-0.39.0.tar.gz) = 7HcRZmCWvUCW/6g1I4kFuzP7hyZ5EOFUsYtE6quzQPI= +SHA256 (cargo/windows_i686_gnu-0.36.1.tar.gz) = GA5szwHa9MQmuEbfxm2x/FGPB0uqeTqn2bmq7/rWo7Y= +SHA256 (cargo/windows_i686_gnu-0.39.0.tar.gz) = dj/FcQCl9wQuMFfn6Nm914YNMwBwJRpz0ANWOju0nhs= +SHA256 (cargo/windows_i686_msvc-0.36.1.tar.gz) = 4ueRcUiygS0e6vrrIql+SBPfpgo/j3jr4gS8yI8S8CQ= +SHA256 (cargo/windows_i686_msvc-0.39.0.tar.gz) = e8fL/liCiSHhCp9Eb8qvZJIE3P5sHd1xLF7rrmvaEQY= +SHA256 (cargo/windows_x86_64_gnu-0.36.1.tar.gz) = Tc0XG4d2xBuXUh5doSei2GrSgBFIB9Cyqx5GK8dk2eE= +SHA256 (cargo/windows_x86_64_gnu-0.39.0.tar.gz) = aGjBZWN9ZTrh6NxNgsJdT5fdZgXqqNeEtcbgqyolK2U= +SHA256 (cargo/windows_x86_64_msvc-0.36.1.tar.gz) = yBHKSoyFPvQgq9hZK6U927rJBBD6tpA7PnmXKmMfdoA= +SHA256 (cargo/windows_x86_64_msvc-0.39.0.tar.gz) = Xk1AiDrpyulieHyna6djkP+ikhRmehEdueChrYN36Ak= +SHA256 (cargo/x25519-dalek-1.2.0.tar.gz) = I5K2uUpXa04r88WydX1j8QragCCi5NCKyEnrz26o4Hc= +SHA256 (cargo/xattr-0.2.3.tar.gz) = bRUmu+Wq616waIX02Ye836XiMYcFXem4P+ABVqgh+rw= +SHA256 (cargo/xflags-0.2.4.tar.gz) = PxT+HtQaWite8/VlWGxKilWe5V05U/qrNgp3ETW97gA= +SHA256 (cargo/xflags-macros-0.2.4.tar.gz) = RdEdX8Kpcoft7YsXDKgFM7PEJkbdf6OGpesEWBeSECI= +SHA256 (cargo/xshell-0.1.17.tar.gz) = 6q0gNSRMVtoFVz1Nf9pfkDxgpfNbkRDhV6FKHfRanxQ= +SHA256 (cargo/xshell-macros-0.1.17.tar.gz) = SRako8rXWeSZo2IFI7+VRcwWLXoGFjcn3el86aqkzzk= +SHA256 (cargo/zbus-2.3.2.tar.gz) = LY8aA3ssSmfZZU3HvfqP8ugFVbvv3TwYM8HRsnyWOms= +SHA256 (cargo/zbus_macros-2.3.2.tar.gz) = H4+1GG0ch66IzyNJdMJAZxI4tKZ5FYrTuU7EZSNzSaY= +SHA256 (cargo/zbus_names-2.2.0.tar.gz) = QaQI/Yo1JpVpD1OQbcf9A2vpJOxR6l4FZm/0JoXtCvU= SHA256 (cargo/zeroize-1.3.0.tar.gz) = R1b32z97VXSTjD6xwRcDi44H+V7mcYwO+tSsIVCPHv0= SHA256 (cargo/zeroize_derive-1.3.2.tar.gz) = P48YdkHa1PaA0lxL/EIltBgWWYQXnybKduxPtkQdOhc= -SHA256 (cargo/zvariant-3.3.0.tar.gz) = 43TG/IyEvVOSKBKF7JrAA7ChFZ2YXY6T6hfIeW0DNU0= -SHA256 (cargo/zvariant_derive-3.3.0.tar.gz) = r0BiVSsT8Ql7XlOsc2nDTv7lkS/cGcdoBSRPXk7V+g4= -SHA256 (gurk-rs-0.2.5.tar.gz) = 6kVJP1rLAd/+F+Snq/j/mYAqgHP3ffafQG/pphpxLWM= +SHA256 (cargo/zvariant-3.6.0.tar.gz) = G9aOTmQy7xnfR9fpDi5ytefj13jgrjut3xK5USZcx1g= +SHA256 (cargo/zvariant_derive-3.6.0.tar.gz) = COl36qOvZS9j1HnOUNkkJUrXZyKmKJ7BoerDIxyjBDA= +SHA256 (gurk-rs-0.3.0-vendorfiles.tar.gz) = hsgl94Oi3MT3dy7rgDXHAb4txSO9AoNQW9tIlVSaU6A= +SHA256 (gurk-rs-0.3.0.tar.gz) = dZQN2tcH1SU3Yc/qkgUNs5zLj5PZk7FVdq2LraykV4Y= SIZE (cargo/adler-1.0.2.tar.gz) = 12778 -SIZE (cargo/aead-0.4.2.tar.gz) = 14654 -SIZE (cargo/aes-0.7.4.tar.gz) = 128509 -SIZE (cargo/aes-gcm-0.9.2.tar.gz) = 148403 -SIZE (cargo/aes-gcm-siv-0.10.1.tar.gz) = 26723 -SIZE (cargo/aho-corasick-0.7.18.tar.gz) = 112923 +SIZE (cargo/aead-0.4.3.tar.gz) = 14717 +SIZE (cargo/aes-0.7.5.tar.gz) = 128544 +SIZE (cargo/aes-gcm-0.9.4.tar.gz) = 148477 +SIZE (cargo/aes-gcm-siv-0.10.3.tar.gz) = 26809 +SIZE (cargo/aho-corasick-0.7.19.tar.gz) = 113070 SIZE (cargo/android_system_properties-0.1.5.tar.gz) = 5243 -SIZE (cargo/ansi_term-0.11.0.tar.gz) = 17087 +SIZE (cargo/anes-0.1.6.tar.gz) = 23857 SIZE (cargo/ansi_term-0.12.1.tar.gz) = 24838 -SIZE (cargo/anyhow-1.0.42.tar.gz) = 34827 +SIZE (cargo/anyhow-1.0.64.tar.gz) = 43549 SIZE (cargo/arrayref-0.3.6.tar.gz) = 10035 SIZE (cargo/arrayvec-0.5.2.tar.gz) = 27838 -SIZE (cargo/ascii-0.9.3.tar.gz) = 28283 -SIZE (cargo/async-broadcast-0.3.4.tar.gz) = 18539 -SIZE (cargo/async-channel-1.6.1.tar.gz) = 12574 +SIZE (cargo/async-broadcast-0.4.1.tar.gz) = 19732 +SIZE (cargo/async-channel-1.7.1.tar.gz) = 12855 SIZE (cargo/async-executor-1.4.1.tar.gz) = 15490 -SIZE (cargo/async-io-1.6.0.tar.gz) = 32282 +SIZE (cargo/async-io-1.9.0.tar.gz) = 36394 SIZE (cargo/async-lock-2.5.0.tar.gz) = 15656 SIZE (cargo/async-recursion-0.3.2.tar.gz) = 10774 -SIZE (cargo/async-task-4.2.0.tar.gz) = 28496 -SIZE (cargo/async-trait-0.1.51.tar.gz) = 25531 -SIZE (cargo/async-tungstenite-0.15.0.tar.gz) = 31533 +SIZE (cargo/async-task-4.3.0.tar.gz) = 29544 +SIZE (cargo/async-trait-0.1.57.tar.gz) = 26793 +SIZE (cargo/async-tungstenite-0.17.2.tar.gz) = 33625 SIZE (cargo/atty-0.2.14.tar.gz) = 5470 SIZE (cargo/autocfg-1.1.0.tar.gz) = 13272 SIZE (cargo/base64-0.12.3.tar.gz) = 57545 SIZE (cargo/base64-0.13.0.tar.gz) = 62070 SIZE (cargo/bincode-1.3.3.tar.gz) = 28958 -SIZE (cargo/bitflags-1.2.1.tar.gz) = 16745 +SIZE (cargo/bitflags-1.3.2.tar.gz) = 23021 SIZE (cargo/block-0.1.6.tar.gz) = 4077 -SIZE (cargo/block-buffer-0.7.3.tar.gz) = 7179 +SIZE (cargo/block-buffer-0.10.3.tar.gz) = 10465 SIZE (cargo/block-buffer-0.9.0.tar.gz) = 7108 SIZE (cargo/block-modes-0.8.1.tar.gz) = 16961 -SIZE (cargo/block-padding-0.1.5.tar.gz) = 7342 SIZE (cargo/block-padding-0.2.1.tar.gz) = 7672 -SIZE (cargo/bstr-0.2.16.tar.gz) = 330346 -SIZE (cargo/bumpalo-3.7.0.tar.gz) = 134261 -SIZE (cargo/byte-tools-0.3.1.tar.gz) = 5526 +SIZE (cargo/bstr-0.2.17.tar.gz) = 330350 +SIZE (cargo/bumpalo-3.11.0.tar.gz) = 80945 SIZE (cargo/byteorder-1.4.3.tar.gz) = 22512 -SIZE (cargo/bytes-1.0.1.tar.gz) = 48142 -SIZE (cargo/cache-padded-1.1.1.tar.gz) = 8798 +SIZE (cargo/bytes-1.2.1.tar.gz) = 54857 +SIZE (cargo/cache-padded-1.2.0.tar.gz) = 9125 SIZE (cargo/cassowary-0.3.0.tar.gz) = 22876 -SIZE (cargo/cc-1.0.69.tar.gz) = 56044 -SIZE (cargo/cesu8-1.1.0.tar.gz) = 10555 +SIZE (cargo/cast-0.3.0.tar.gz) = 11452 +SIZE (cargo/cc-1.0.73.tar.gz) = 57880 SIZE (cargo/cfg-if-1.0.0.tar.gz) = 7934 SIZE (cargo/checked_int_cast-1.0.0.tar.gz) = 2669 SIZE (cargo/chrono-0.4.22.tar.gz) = 185570 +SIZE (cargo/ciborium-0.2.0.tar.gz) = 30130 +SIZE (cargo/ciborium-io-0.2.0.tar.gz) = 2738 +SIZE (cargo/ciborium-ll-0.2.0.tar.gz) = 10740 SIZE (cargo/cipher-0.3.0.tar.gz) = 12756 -SIZE (cargo/clap-2.33.3.tar.gz) = 201925 -SIZE (cargo/combine-3.8.1.tar.gz) = 103773 -SIZE (cargo/concurrent-queue-1.2.2.tar.gz) = 15859 -SIZE (cargo/core-foundation-0.9.1.tar.gz) = 25985 +SIZE (cargo/clap-3.2.23.tar.gz) = 219435 +SIZE (cargo/clap-4.0.18.tar.gz) = 204914 +SIZE (cargo/clap_derive-4.0.18.tar.gz) = 27348 +SIZE (cargo/clap_lex-0.2.4.tar.gz) = 9652 +SIZE (cargo/clap_lex-0.3.0.tar.gz) = 9671 +SIZE (cargo/cmake-0.1.48.tar.gz) = 15142 +SIZE (cargo/concurrent-queue-1.2.4.tar.gz) = 15375 +SIZE (cargo/core-foundation-0.9.3.tar.gz) = 27059 SIZE (cargo/core-foundation-sys-0.8.3.tar.gz) = 17519 -SIZE (cargo/cpufeatures-0.1.5.tar.gz) = 10419 -SIZE (cargo/crc32fast-1.2.1.tar.gz) = 38172 -SIZE (cargo/crossbeam-channel-0.5.5.tar.gz) = 90326 -SIZE (cargo/crossbeam-epoch-0.9.5.tar.gz) = 43883 -SIZE (cargo/crossbeam-utils-0.8.9.tar.gz) = 39818 +SIZE (cargo/cpufeatures-0.2.5.tar.gz) = 11251 +SIZE (cargo/crc32fast-1.3.2.tar.gz) = 38661 +SIZE (cargo/criterion-0.4.0.tar.gz) = 108978 +SIZE (cargo/criterion-plot-0.5.0.tar.gz) = 22706 +SIZE (cargo/crossbeam-channel-0.5.6.tar.gz) = 90292 +SIZE (cargo/crossbeam-deque-0.8.2.tar.gz) = 21237 +SIZE (cargo/crossbeam-epoch-0.9.10.tar.gz) = 46918 +SIZE (cargo/crossbeam-utils-0.8.11.tar.gz) = 40887 SIZE (cargo/crossterm-0.19.0.tar.gz) = 104572 +SIZE (cargo/crossterm-0.23.2.tar.gz) = 106712 SIZE (cargo/crossterm_winapi-0.7.0.tar.gz) = 15187 +SIZE (cargo/crossterm_winapi-0.9.0.tar.gz) = 15561 +SIZE (cargo/crypto-common-0.1.6.tar.gz) = 8760 SIZE (cargo/crypto-mac-0.11.1.tar.gz) = 9551 -SIZE (cargo/crypto-mac-0.7.0.tar.gz) = 7636 -SIZE (cargo/ct-logs-0.8.0.tar.gz) = 19766 -SIZE (cargo/ctr-0.7.0.tar.gz) = 16949 -SIZE (cargo/curve25519-dalek-3.1.0.tar.gz) = 511442 +SIZE (cargo/ctr-0.8.0.tar.gz) = 17740 SIZE (cargo/derivative-2.2.0.tar.gz) = 48076 -SIZE (cargo/digest-0.8.1.tar.gz) = 9449 +SIZE (cargo/digest-0.10.3.tar.gz) = 18990 SIZE (cargo/digest-0.9.0.tar.gz) = 13247 SIZE (cargo/dirs-3.0.2.tar.gz) = 12184 +SIZE (cargo/dirs-4.0.0.tar.gz) = 12503 SIZE (cargo/dirs-next-2.0.0.tar.gz) = 11689 -SIZE (cargo/dirs-sys-0.3.6.tar.gz) = 10626 +SIZE (cargo/dirs-sys-0.3.7.tar.gz) = 10597 SIZE (cargo/dirs-sys-next-0.1.2.tar.gz) = 10681 SIZE (cargo/displaydoc-0.2.3.tar.gz) = 17060 -SIZE (cargo/easy-parallel-3.2.0.tar.gz) = 9276 -SIZE (cargo/either-1.6.1.tar.gz) = 13641 +SIZE (cargo/either-1.8.0.tar.gz) = 15992 SIZE (cargo/emoji-0.2.1.tar.gz) = 6475871 SIZE (cargo/enumflags2-0.7.5.tar.gz) = 15117 SIZE (cargo/enumflags2_derive-0.7.4.tar.gz) = 8166 SIZE (cargo/env_logger-0.8.4.tar.gz) = 33342 -SIZE (cargo/error-chain-0.12.4.tar.gz) = 29274 -SIZE (cargo/event-listener-2.5.2.tar.gz) = 15225 -SIZE (cargo/fake-simd-0.1.2.tar.gz) = 5398 -SIZE (cargo/fastrand-1.4.1.tar.gz) = 11224 -SIZE (cargo/filetime-0.2.14.tar.gz) = 14358 -SIZE (cargo/fixedbitset-0.2.0.tar.gz) = 13597 -SIZE (cargo/fixedbitset-0.4.1.tar.gz) = 15551 -SIZE (cargo/flate2-1.0.20.tar.gz) = 74036 +SIZE (cargo/event-listener-2.5.3.tar.gz) = 15392 +SIZE (cargo/fastrand-1.8.0.tar.gz) = 11369 +SIZE (cargo/filetime-0.2.17.tar.gz) = 14484 +SIZE (cargo/fixedbitset-0.4.2.tar.gz) = 15954 +SIZE (cargo/flate2-1.0.24.tar.gz) = 70191 SIZE (cargo/fnv-1.0.7.tar.gz) = 11266 SIZE (cargo/form_urlencoded-1.0.1.tar.gz) = 8773 SIZE (cargo/fs2-0.4.3.tar.gz) = 13138 -SIZE (cargo/futures-0.3.15.tar.gz) = 46425 -SIZE (cargo/futures-channel-0.3.15.tar.gz) = 31867 -SIZE (cargo/futures-core-0.3.15.tar.gz) = 14514 -SIZE (cargo/futures-executor-0.3.15.tar.gz) = 17166 -SIZE (cargo/futures-io-0.3.15.tar.gz) = 9058 +SIZE (cargo/futures-0.3.24.tar.gz) = 51399 +SIZE (cargo/futures-channel-0.3.24.tar.gz) = 31963 +SIZE (cargo/futures-core-0.3.24.tar.gz) = 14618 +SIZE (cargo/futures-executor-0.3.24.tar.gz) = 17745 +SIZE (cargo/futures-io-0.3.24.tar.gz) = 8910 SIZE (cargo/futures-lite-1.12.0.tar.gz) = 36032 -SIZE (cargo/futures-macro-0.3.15.tar.gz) = 10872 -SIZE (cargo/futures-sink-0.3.15.tar.gz) = 7672 -SIZE (cargo/futures-task-0.3.15.tar.gz) = 11811 -SIZE (cargo/futures-util-0.3.15.tar.gz) = 141962 +SIZE (cargo/futures-macro-0.3.24.tar.gz) = 11252 +SIZE (cargo/futures-sink-0.3.24.tar.gz) = 7854 +SIZE (cargo/futures-task-0.3.24.tar.gz) = 11836 +SIZE (cargo/futures-util-0.3.24.tar.gz) = 155823 SIZE (cargo/fuzzy-matcher-0.3.7.tar.gz) = 18047 SIZE (cargo/fxhash-0.2.1.tar.gz) = 4102 -SIZE (cargo/generic-array-0.12.4.tar.gz) = 18212 -SIZE (cargo/generic-array-0.14.4.tar.gz) = 28916 +SIZE (cargo/generic-array-0.14.6.tar.gz) = 15889 SIZE (cargo/getopts-0.2.21.tar.gz) = 18457 SIZE (cargo/getrandom-0.1.16.tar.gz) = 25077 -SIZE (cargo/getrandom-0.2.3.tar.gz) = 26261 -SIZE (cargo/gh-emoji-1.0.3.tar.gz) = 21768 -SIZE (cargo/ghash-0.4.2.tar.gz) = 8865 -SIZE (cargo/hashbrown-0.11.2.tar.gz) = 85713 -SIZE (cargo/headers-0.3.4.tar.gz) = 67384 +SIZE (cargo/getrandom-0.2.7.tar.gz) = 28854 +SIZE (cargo/gh-emoji-1.0.7.tar.gz) = 21780 +SIZE (cargo/ghash-0.4.4.tar.gz) = 9005 +SIZE (cargo/half-1.8.2.tar.gz) = 41874 +SIZE (cargo/hashbrown-0.12.3.tar.gz) = 102968 +SIZE (cargo/headers-0.3.8.tar.gz) = 67904 SIZE (cargo/headers-core-0.2.0.tar.gz) = 2380 SIZE (cargo/heck-0.3.3.tar.gz) = 10260 +SIZE (cargo/heck-0.4.0.tar.gz) = 11161 SIZE (cargo/hermit-abi-0.1.19.tar.gz) = 9979 SIZE (cargo/hex-0.4.3.tar.gz) = 13299 SIZE (cargo/hkdf-0.11.0.tar.gz) = 171707 +SIZE (cargo/hkdf-0.12.3.tar.gz) = 170910 SIZE (cargo/hmac-0.11.0.tar.gz) = 11385 -SIZE (cargo/hmac-0.7.1.tar.gz) = 9765 +SIZE (cargo/hmac-0.12.1.tar.gz) = 42657 SIZE (cargo/hostname-0.3.1.tar.gz) = 9272 -SIZE (cargo/http-0.2.4.tar.gz) = 105489 -SIZE (cargo/http-body-0.4.2.tar.gz) = 7603 -SIZE (cargo/httparse-1.4.1.tar.gz) = 25592 -SIZE (cargo/httpdate-1.0.1.tar.gz) = 10293 -SIZE (cargo/hyper-0.14.11.tar.gz) = 169467 -SIZE (cargo/hyper-rustls-0.22.1.tar.gz) = 26718 +SIZE (cargo/http-0.2.8.tar.gz) = 105591 +SIZE (cargo/http-body-0.4.5.tar.gz) = 9242 +SIZE (cargo/httparse-1.8.0.tar.gz) = 29954 +SIZE (cargo/httpdate-1.0.2.tar.gz) = 10673 +SIZE (cargo/hyper-0.14.20.tar.gz) = 183885 +SIZE (cargo/hyper-rustls-0.23.0.tar.gz) = 29432 SIZE (cargo/hyper-timeout-0.4.1.tar.gz) = 13805 SIZE (cargo/iana-time-zone-0.1.47.tar.gz) = 16974 SIZE (cargo/idna-0.2.3.tar.gz) = 271023 -SIZE (cargo/indexmap-1.7.0.tar.gz) = 50363 -SIZE (cargo/instant-0.1.10.tar.gz) = 5218 -SIZE (cargo/itertools-0.10.1.tar.gz) = 116219 +SIZE (cargo/indexmap-1.9.1.tar.gz) = 54114 +SIZE (cargo/instant-0.1.12.tar.gz) = 6128 +SIZE (cargo/itertools-0.10.3.tar.gz) = 118661 SIZE (cargo/itertools-0.9.0.tar.gz) = 96429 -SIZE (cargo/itoa-0.4.7.tar.gz) = 12099 -SIZE (cargo/itoa-1.0.2.tar.gz) = 11112 -SIZE (cargo/jni-0.16.0.tar.gz) = 59922 -SIZE (cargo/jni-sys-0.3.0.tar.gz) = 10232 +SIZE (cargo/itoa-1.0.3.tar.gz) = 10481 SIZE (cargo/js-sys-0.3.59.tar.gz) = 78849 SIZE (cargo/lazy_static-1.4.0.tar.gz) = 10443 SIZE (cargo/lexical-core-0.7.6.tar.gz) = 494385 -SIZE (cargo/libc-0.2.126.tar.gz) = 590481 -SIZE (cargo/linked-hash-map-0.5.4.tar.gz) = 16166 -SIZE (cargo/lock_api-0.4.7.tar.gz) = 25371 -SIZE (cargo/log-0.4.14.tar.gz) = 34582 -SIZE (cargo/log-panics-2.0.0.tar.gz) = 6781 +SIZE (cargo/libc-0.2.132.tar.gz) = 595317 +SIZE (cargo/linked-hash-map-0.5.6.tar.gz) = 15049 +SIZE (cargo/lock_api-0.4.8.tar.gz) = 25677 +SIZE (cargo/log-0.4.17.tar.gz) = 38028 +SIZE (cargo/log-panics-2.1.0.tar.gz) = 9464 SIZE (cargo/lru-cache-0.1.2.tar.gz) = 9307 -SIZE (cargo/mac-notification-sys-0.5.2.tar.gz) = 10585 +SIZE (cargo/mac-notification-sys-0.5.6.tar.gz) = 11921 SIZE (cargo/malloc_buf-0.0.6.tar.gz) = 1239 SIZE (cargo/match_cfg-0.1.0.tar.gz) = 7153 -SIZE (cargo/matches-0.1.8.tar.gz) = 2216 -SIZE (cargo/memchr-2.4.0.tar.gz) = 63392 -SIZE (cargo/memoffset-0.6.4.tar.gz) = 7664 +SIZE (cargo/matches-0.1.9.tar.gz) = 2246 +SIZE (cargo/memchr-2.5.0.tar.gz) = 65812 +SIZE (cargo/memoffset-0.6.5.tar.gz) = 7686 SIZE (cargo/mime-0.3.16.tar.gz) = 15206 -SIZE (cargo/mime_guess-2.0.3.tar.gz) = 27437 -SIZE (cargo/miniz_oxide-0.4.4.tar.gz) = 49938 -SIZE (cargo/mio-0.7.13.tar.gz) = 87027 +SIZE (cargo/mime_guess-2.0.4.tar.gz) = 26399 +SIZE (cargo/miniz_oxide-0.5.4.tar.gz) = 53485 +SIZE (cargo/mio-0.7.14.tar.gz) = 87429 +SIZE (cargo/mio-0.8.4.tar.gz) = 93013 SIZE (cargo/miow-0.3.7.tar.gz) = 24563 -SIZE (cargo/mpart-async-0.5.0.tar.gz) = 30154 +SIZE (cargo/mpart-async-0.6.1.tar.gz) = 29656 SIZE (cargo/multimap-0.8.3.tar.gz) = 13518 SIZE (cargo/nix-0.23.1.tar.gz) = 240531 SIZE (cargo/nom-5.1.2.tar.gz) = 136174 -SIZE (cargo/notify-rust-4.5.8.tar.gz) = 48098 -SIZE (cargo/ntapi-0.3.6.tar.gz) = 127221 -SIZE (cargo/num-integer-0.1.44.tar.gz) = 22216 -SIZE (cargo/num-traits-0.2.14.tar.gz) = 45476 -SIZE (cargo/num_cpus-1.13.0.tar.gz) = 14704 -SIZE (cargo/num_enum-0.5.2.tar.gz) = 10479 -SIZE (cargo/num_enum_derive-0.5.2.tar.gz) = 7670 +SIZE (cargo/notify-rust-4.5.10.tar.gz) = 48994 +SIZE (cargo/ntapi-0.3.7.tar.gz) = 126994 +SIZE (cargo/num-integer-0.1.45.tar.gz) = 22529 +SIZE (cargo/num-traits-0.2.15.tar.gz) = 49262 +SIZE (cargo/num_cpus-1.13.1.tar.gz) = 14752 +SIZE (cargo/num_enum-0.5.7.tar.gz) = 15199 +SIZE (cargo/num_enum_derive-0.5.7.tar.gz) = 12225 SIZE (cargo/num_threads-0.1.6.tar.gz) = 7334 SIZE (cargo/objc-0.2.7.tar.gz) = 22036 SIZE (cargo/objc-foundation-0.1.1.tar.gz) = 9063 SIZE (cargo/objc_id-0.1.1.tar.gz) = 3258 -SIZE (cargo/once_cell-1.13.1.tar.gz) = 31335 +SIZE (cargo/once_cell-1.14.0.tar.gz) = 31614 SIZE (cargo/oncemutex-0.1.1.tar.gz) = 2476 -SIZE (cargo/opaque-debug-0.2.3.tar.gz) = 5643 +SIZE (cargo/oorandom-11.1.3.tar.gz) = 10068 SIZE (cargo/opaque-debug-0.3.0.tar.gz) = 5767 SIZE (cargo/opener-0.5.0.tar.gz) = 12350 -SIZE (cargo/openssl-probe-0.1.4.tar.gz) = 7066 +SIZE (cargo/openssl-probe-0.1.5.tar.gz) = 7227 SIZE (cargo/ordered-stream-0.0.1.tar.gz) = 9081 +SIZE (cargo/os_str_bytes-6.3.1.tar.gz) = 22934 SIZE (cargo/parking-2.0.0.tar.gz) = 9714 -SIZE (cargo/parking_lot-0.11.1.tar.gz) = 39854 -SIZE (cargo/parking_lot_core-0.8.3.tar.gz) = 32147 +SIZE (cargo/parking_lot-0.11.2.tar.gz) = 39869 +SIZE (cargo/parking_lot-0.12.1.tar.gz) = 40967 +SIZE (cargo/parking_lot_core-0.8.5.tar.gz) = 32466 +SIZE (cargo/parking_lot_core-0.9.3.tar.gz) = 32256 SIZE (cargo/percent-encoding-2.1.0.tar.gz) = 9748 -SIZE (cargo/petgraph-0.5.1.tar.gz) = 147173 -SIZE (cargo/petgraph-0.6.0.tar.gz) = 182063 +SIZE (cargo/petgraph-0.6.2.tar.gz) = 182513 +SIZE (cargo/phf-0.11.1.tar.gz) = 17232 SIZE (cargo/phf-0.8.0.tar.gz) = 3902 SIZE (cargo/phf_generator-0.8.0.tar.gz) = 7604 SIZE (cargo/phf_macros-0.8.0.tar.gz) = 5814 +SIZE (cargo/phf_shared-0.11.1.tar.gz) = 10320 SIZE (cargo/phf_shared-0.8.0.tar.gz) = 2860 SIZE (cargo/phonenumber-0.3.1+8.12.9.tar.gz) = 2362619 -SIZE (cargo/pin-project-1.0.7.tar.gz) = 54847 -SIZE (cargo/pin-project-internal-1.0.7.tar.gz) = 27884 -SIZE (cargo/pin-project-lite-0.2.7.tar.gz) = 27212 +SIZE (cargo/pin-project-lite-0.2.9.tar.gz) = 27713 SIZE (cargo/pin-utils-0.1.0.tar.gz) = 7580 -SIZE (cargo/polling-2.1.0.tar.gz) = 17682 -SIZE (cargo/polyval-0.5.1.tar.gz) = 17257 -SIZE (cargo/ppv-lite86-0.2.10.tar.gz) = 20915 -SIZE (cargo/proc-macro-crate-1.0.0.tar.gz) = 8442 +SIZE (cargo/plotters-0.3.4.tar.gz) = 143219 +SIZE (cargo/plotters-backend-0.3.4.tar.gz) = 13416 +SIZE (cargo/plotters-svg-0.3.3.tar.gz) = 6916 +SIZE (cargo/polling-2.3.0.tar.gz) = 21678 +SIZE (cargo/polyval-0.5.3.tar.gz) = 17368 +SIZE (cargo/ppv-lite86-0.2.16.tar.gz) = 22245 +SIZE (cargo/proc-macro-crate-1.2.1.tar.gz) = 9161 SIZE (cargo/proc-macro-error-1.0.4.tar.gz) = 25293 SIZE (cargo/proc-macro-error-attr-1.0.4.tar.gz) = 7971 SIZE (cargo/proc-macro-hack-0.5.19.tar.gz) = 15556 -SIZE (cargo/proc-macro-nested-0.1.7.tar.gz) = 6495 -SIZE (cargo/proc-macro2-1.0.27.tar.gz) = 38625 -SIZE (cargo/prost-0.8.0.tar.gz) = 25532 +SIZE (cargo/proc-macro2-1.0.43.tar.gz) = 41512 +SIZE (cargo/prost-0.10.4.tar.gz) = 26192 SIZE (cargo/prost-0.9.0.tar.gz) = 25584 -SIZE (cargo/prost-build-0.8.0.tar.gz) = 8407464 +SIZE (cargo/prost-build-0.10.4.tar.gz) = 6351284 SIZE (cargo/prost-build-0.9.0.tar.gz) = 9947797 -SIZE (cargo/prost-derive-0.8.0.tar.gz) = 15203 +SIZE (cargo/prost-derive-0.10.1.tar.gz) = 19128 SIZE (cargo/prost-derive-0.9.0.tar.gz) = 15266 -SIZE (cargo/prost-types-0.8.0.tar.gz) = 27271 +SIZE (cargo/prost-types-0.10.1.tar.gz) = 31215 SIZE (cargo/prost-types-0.9.0.tar.gz) = 27403 SIZE (cargo/pulldown-cmark-0.8.0.tar.gz) = 106330 -SIZE (cargo/qr2term-0.2.2.tar.gz) = 42424 +SIZE (cargo/qr2term-0.3.0.tar.gz) = 42718 SIZE (cargo/qrcode-0.12.0.tar.gz) = 58072 SIZE (cargo/quick-xml-0.18.1.tar.gz) = 103957 +SIZE (cargo/quick-xml-0.23.1.tar.gz) = 161488 SIZE (cargo/quickcheck-1.0.3.tar.gz) = 28069 SIZE (cargo/quickcheck_macros-1.0.0.tar.gz) = 5275 -SIZE (cargo/quote-1.0.9.tar.gz) = 25042 +SIZE (cargo/quote-1.0.21.tar.gz) = 28030 SIZE (cargo/rand-0.7.3.tar.gz) = 112246 -SIZE (cargo/rand-0.8.4.tar.gz) = 87406 +SIZE (cargo/rand-0.8.5.tar.gz) = 87113 SIZE (cargo/rand_chacha-0.2.2.tar.gz) = 13267 SIZE (cargo/rand_chacha-0.3.1.tar.gz) = 15251 SIZE (cargo/rand_core-0.5.1.tar.gz) = 21116 SIZE (cargo/rand_core-0.6.3.tar.gz) = 21938 SIZE (cargo/rand_hc-0.2.0.tar.gz) = 11670 -SIZE (cargo/rand_hc-0.3.1.tar.gz) = 11891 SIZE (cargo/rand_pcg-0.2.1.tar.gz) = 11291 -SIZE (cargo/redox_syscall-0.2.9.tar.gz) = 23533 -SIZE (cargo/redox_users-0.4.0.tar.gz) = 13023 -SIZE (cargo/regex-1.5.6.tar.gz) = 238593 +SIZE (cargo/rayon-1.5.3.tar.gz) = 167246 +SIZE (cargo/rayon-core-1.9.3.tar.gz) = 65300 +SIZE (cargo/redox_syscall-0.2.16.tar.gz) = 24012 +SIZE (cargo/redox_users-0.4.3.tar.gz) = 15353 +SIZE (cargo/regex-1.6.0.tar.gz) = 239329 SIZE (cargo/regex-automata-0.1.10.tar.gz) = 114533 SIZE (cargo/regex-cache-0.2.1.tar.gz) = 6346 -SIZE (cargo/regex-syntax-0.6.26.tar.gz) = 293912 +SIZE (cargo/regex-syntax-0.6.27.tar.gz) = 297300 SIZE (cargo/remove_dir_all-0.5.3.tar.gz) = 9184 SIZE (cargo/ring-0.16.20.tar.gz) = 5082615 -SIZE (cargo/rustls-0.19.1.tar.gz) = 208143 -SIZE (cargo/rustls-native-certs-0.5.0.tar.gz) = 18482 -SIZE (cargo/ryu-1.0.5.tar.gz) = 49570 +SIZE (cargo/rustls-0.20.6.tar.gz) = 259289 +SIZE (cargo/rustls-native-certs-0.6.2.tar.gz) = 22089 +SIZE (cargo/rustls-pemfile-0.3.0.tar.gz) = 14487 +SIZE (cargo/rustls-pemfile-1.0.1.tar.gz) = 19171 +SIZE (cargo/ryu-1.0.11.tar.gz) = 47007 SIZE (cargo/same-file-1.0.6.tar.gz) = 10183 -SIZE (cargo/schannel-0.1.19.tar.gz) = 42755 +SIZE (cargo/schannel-0.1.20.tar.gz) = 41579 SIZE (cargo/scopeguard-1.1.0.tar.gz) = 11470 -SIZE (cargo/sct-0.6.1.tar.gz) = 26825 -SIZE (cargo/security-framework-2.3.1.tar.gz) = 61581 -SIZE (cargo/security-framework-sys-2.3.0.tar.gz) = 12561 -SIZE (cargo/semver-1.0.3.tar.gz) = 28918 -SIZE (cargo/serde-1.0.126.tar.gz) = 75138 -SIZE (cargo/serde_derive-1.0.126.tar.gz) = 54189 -SIZE (cargo/serde_json-1.0.64.tar.gz) = 115138 -SIZE (cargo/serde_repr-0.1.7.tar.gz) = 10173 -SIZE (cargo/sha-1-0.9.6.tar.gz) = 13758 +SIZE (cargo/sct-0.7.0.tar.gz) = 27502 +SIZE (cargo/security-framework-2.7.0.tar.gz) = 72601 +SIZE (cargo/security-framework-sys-2.6.1.tar.gz) = 17717 +SIZE (cargo/semver-1.0.13.tar.gz) = 29653 +SIZE (cargo/serde-1.0.144.tar.gz) = 76387 +SIZE (cargo/serde_derive-1.0.144.tar.gz) = 54867 +SIZE (cargo/serde_json-1.0.85.tar.gz) = 144635 +SIZE (cargo/serde_repr-0.1.9.tar.gz) = 9695 +SIZE (cargo/sha-1-0.10.0.tar.gz) = 12239 +SIZE (cargo/sha1-0.10.4.tar.gz) = 11915 SIZE (cargo/sha1-0.6.1.tar.gz) = 2931 SIZE (cargo/sha1_smol-1.0.0.tar.gz) = 9782 -SIZE (cargo/sha2-0.8.2.tar.gz) = 19851 -SIZE (cargo/sha2-0.9.5.tar.gz) = 19912 +SIZE (cargo/sha2-0.10.5.tar.gz) = 20325 +SIZE (cargo/sha2-0.9.9.tar.gz) = 22247 SIZE (cargo/sharded-slab-0.1.4.tar.gz) = 52479 SIZE (cargo/signal-hook-0.1.17.tar.gz) = 27085 +SIZE (cargo/signal-hook-0.3.14.tar.gz) = 49446 +SIZE (cargo/signal-hook-mio-0.2.3.tar.gz) = 9064 SIZE (cargo/signal-hook-registry-1.4.0.tar.gz) = 17912 -SIZE (cargo/siphasher-0.3.5.tar.gz) = 9455 -SIZE (cargo/slab-0.4.3.tar.gz) = 15681 -SIZE (cargo/sled-0.34.6.tar.gz) = 485861 -SIZE (cargo/smallvec-1.6.1.tar.gz) = 26444 +SIZE (cargo/siphasher-0.3.10.tar.gz) = 9889 +SIZE (cargo/slab-0.4.7.tar.gz) = 16647 +SIZE (cargo/sled-0.34.7.tar.gz) = 485296 +SIZE (cargo/smallvec-1.9.0.tar.gz) = 28396 SIZE (cargo/smawk-0.3.1.tar.gz) = 12840 -SIZE (cargo/socket2-0.4.0.tar.gz) = 37949 +SIZE (cargo/socket2-0.4.7.tar.gz) = 44619 SIZE (cargo/spin-0.5.2.tar.gz) = 12004 SIZE (cargo/static_assertions-1.1.0.tar.gz) = 18480 -SIZE (cargo/strsim-0.8.0.tar.gz) = 9309 -SIZE (cargo/structopt-0.3.22.tar.gz) = 51665 -SIZE (cargo/structopt-derive-0.4.15.tar.gz) = 20861 +SIZE (cargo/strsim-0.10.0.tar.gz) = 11355 SIZE (cargo/strum-0.22.0.tar.gz) = 5413 SIZE (cargo/strum_macros-0.22.0.tar.gz) = 16501 -SIZE (cargo/subtle-1.0.0.tar.gz) = 8097 SIZE (cargo/subtle-2.4.1.tar.gz) = 12630 -SIZE (cargo/syn-1.0.73.tar.gz) = 232706 -SIZE (cargo/synstructure-0.12.5.tar.gz) = 18020 +SIZE (cargo/syn-1.0.99.tar.gz) = 236084 +SIZE (cargo/synstructure-0.12.6.tar.gz) = 18429 SIZE (cargo/tar-0.4.38.tar.gz) = 49158 -SIZE (cargo/tempfile-3.2.0.tar.gz) = 25892 -SIZE (cargo/textwrap-0.11.0.tar.gz) = 17322 +SIZE (cargo/tauri-winrt-notification-0.1.0.tar.gz) = 41529 +SIZE (cargo/tempfile-3.3.0.tar.gz) = 27578 +SIZE (cargo/termcolor-1.1.3.tar.gz) = 17242 SIZE (cargo/textwrap-0.14.2.tar.gz) = 52016 -SIZE (cargo/thiserror-1.0.30.tar.gz) = 17748 -SIZE (cargo/thiserror-impl-1.0.30.tar.gz) = 15230 +SIZE (cargo/textwrap-0.16.0.tar.gz) = 53722 +SIZE (cargo/thiserror-1.0.34.tar.gz) = 17329 +SIZE (cargo/thiserror-impl-1.0.34.tar.gz) = 15437 SIZE (cargo/thread_local-1.1.4.tar.gz) = 13106 SIZE (cargo/time-0.1.44.tar.gz) = 28885 -SIZE (cargo/time-0.3.9.tar.gz) = 81412 -SIZE (cargo/tinyvec-1.2.0.tar.gz) = 41625 +SIZE (cargo/time-0.3.14.tar.gz) = 93111 +SIZE (cargo/tinytemplate-1.2.1.tar.gz) = 26490 +SIZE (cargo/tinyvec-1.6.0.tar.gz) = 45991 SIZE (cargo/tinyvec_macros-0.1.0.tar.gz) = 1817 -SIZE (cargo/tokio-1.16.1.tar.gz) = 552194 -SIZE (cargo/tokio-io-timeout-1.1.1.tar.gz) = 8853 +SIZE (cargo/tokio-1.21.0.tar.gz) = 605527 +SIZE (cargo/tokio-io-timeout-1.2.0.tar.gz) = 8993 SIZE (cargo/tokio-macros-1.8.0.tar.gz) = 9346 -SIZE (cargo/tokio-rustls-0.22.0.tar.gz) = 22706 -SIZE (cargo/tokio-stream-0.1.7.tar.gz) = 30323 -SIZE (cargo/tokio-util-0.6.7.tar.gz) = 73201 -SIZE (cargo/toml-0.5.8.tar.gz) = 54219 -SIZE (cargo/tower-service-0.3.1.tar.gz) = 6299 -SIZE (cargo/tracing-0.1.35.tar.gz) = 72680 +SIZE (cargo/tokio-rustls-0.23.4.tar.gz) = 27024 +SIZE (cargo/tokio-stream-0.1.9.tar.gz) = 31779 +SIZE (cargo/tokio-util-0.6.10.tar.gz) = 71140 +SIZE (cargo/toml-0.5.9.tar.gz) = 55667 +SIZE (cargo/tower-service-0.3.2.tar.gz) = 6847 +SIZE (cargo/tracing-0.1.36.tar.gz) = 73238 SIZE (cargo/tracing-appender-0.2.2.tar.gz) = 17208 -SIZE (cargo/tracing-attributes-0.1.21.tar.gz) = 27552 -SIZE (cargo/tracing-core-0.1.27.tar.gz) = 58328 +SIZE (cargo/tracing-attributes-0.1.22.tar.gz) = 28199 +SIZE (cargo/tracing-core-0.1.29.tar.gz) = 58969 SIZE (cargo/tracing-log-0.1.3.tar.gz) = 20549 -SIZE (cargo/tracing-subscriber-0.3.11.tar.gz) = 184827 +SIZE (cargo/tracing-subscriber-0.3.15.tar.gz) = 187713 SIZE (cargo/try-lock-0.2.3.tar.gz) = 4158 SIZE (cargo/tui-0.15.0.tar.gz) = 139975 -SIZE (cargo/tungstenite-0.15.0.tar.gz) = 59529 -SIZE (cargo/twoway-0.2.2.tar.gz) = 30454 -SIZE (cargo/typenum-1.13.0.tar.gz) = 40238 -SIZE (cargo/unchecked-index-0.2.2.tar.gz) = 8325 +SIZE (cargo/tungstenite-0.17.3.tar.gz) = 53478 +SIZE (cargo/typenum-1.15.0.tar.gz) = 40741 +SIZE (cargo/uds_windows-1.0.2.tar.gz) = 16206 SIZE (cargo/unicase-2.6.0.tar.gz) = 23478 -SIZE (cargo/unicode-bidi-0.3.5.tar.gz) = 33423 -SIZE (cargo/unicode-linebreak-0.1.1.tar.gz) = 65230 -SIZE (cargo/unicode-normalization-0.1.19.tar.gz) = 107353 -SIZE (cargo/unicode-segmentation-1.8.0.tar.gz) = 94011 -SIZE (cargo/unicode-width-0.1.8.tar.gz) = 16732 -SIZE (cargo/unicode-xid-0.2.2.tar.gz) = 14955 -SIZE (cargo/universal-hash-0.4.0.tar.gz) = 8386 -SIZE (cargo/unreachable-1.0.0.tar.gz) = 6355 +SIZE (cargo/unicode-bidi-0.3.8.tar.gz) = 36575 +SIZE (cargo/unicode-ident-1.0.3.tar.gz) = 35031 +SIZE (cargo/unicode-linebreak-0.1.2.tar.gz) = 69293 +SIZE (cargo/unicode-normalization-0.1.21.tar.gz) = 121745 +SIZE (cargo/unicode-segmentation-1.9.0.tar.gz) = 93241 +SIZE (cargo/unicode-width-0.1.9.tar.gz) = 16745 +SIZE (cargo/unicode-xid-0.2.3.tar.gz) = 15174 +SIZE (cargo/universal-hash-0.4.1.tar.gz) = 8503 SIZE (cargo/untrusted-0.7.1.tar.gz) = 7924 SIZE (cargo/url-2.2.2.tar.gz) = 68555 SIZE (cargo/utf-8-0.7.6.tar.gz) = 10422 -SIZE (cargo/uuid-0.8.2.tar.gz) = 37909 +SIZE (cargo/uuid-1.2.1.tar.gz) = 53789 SIZE (cargo/valuable-0.1.0.tar.gz) = 27718 -SIZE (cargo/vec_map-0.8.2.tar.gz) = 14466 -SIZE (cargo/version_check-0.9.3.tar.gz) = 12547 -SIZE (cargo/void-1.0.2.tar.gz) = 2356 +SIZE (cargo/version_check-0.9.4.tar.gz) = 14895 SIZE (cargo/waker-fn-1.1.0.tar.gz) = 7114 SIZE (cargo/walkdir-2.3.2.tar.gz) = 23516 SIZE (cargo/want-0.3.0.tar.gz) = 6550 SIZE (cargo/wasi-0.10.0+wasi-snapshot-preview1.tar.gz) = 26964 +SIZE (cargo/wasi-0.11.0+wasi-snapshot-preview1.tar.gz) = 28131 SIZE (cargo/wasi-0.9.0+wasi-snapshot-preview1.tar.gz) = 31521 SIZE (cargo/wasm-bindgen-0.2.82.tar.gz) = 166376 SIZE (cargo/wasm-bindgen-backend-0.2.82.tar.gz) = 25764 SIZE (cargo/wasm-bindgen-macro-0.2.82.tar.gz) = 11808 SIZE (cargo/wasm-bindgen-macro-support-0.2.82.tar.gz) = 18529 SIZE (cargo/wasm-bindgen-shared-0.2.82.tar.gz) = 7197 -SIZE (cargo/web-sys-0.3.51.tar.gz) = 651133 -SIZE (cargo/webpki-0.21.4.tar.gz) = 58505 +SIZE (cargo/web-sys-0.3.59.tar.gz) = 697461 +SIZE (cargo/webpki-0.22.0.tar.gz) = 58663 SIZE (cargo/wepoll-ffi-0.1.2.tar.gz) = 31309 -SIZE (cargo/which-4.1.0.tar.gz) = 7684 -SIZE (cargo/whoami-1.1.2.tar.gz) = 10583 +SIZE (cargo/which-4.3.0.tar.gz) = 9635 +SIZE (cargo/whoami-1.2.1.tar.gz) = 10963 SIZE (cargo/winapi-0.3.9.tar.gz) = 1200382 SIZE (cargo/winapi-i686-pc-windows-gnu-0.4.0.tar.gz) = 2918815 SIZE (cargo/winapi-util-0.1.5.tar.gz) = 10164 SIZE (cargo/winapi-x86_64-pc-windows-gnu-0.4.0.tar.gz) = 2947998 -SIZE (cargo/windows-0.24.0.tar.gz) = 12674875 -SIZE (cargo/windows_i686_gnu-0.24.0.tar.gz) = 774447 -SIZE (cargo/windows_i686_msvc-0.24.0.tar.gz) = 732279 -SIZE (cargo/windows_x86_64_gnu-0.24.0.tar.gz) = 743223 -SIZE (cargo/windows_x86_64_msvc-0.24.0.tar.gz) = 668947 -SIZE (cargo/winrt-notification-0.5.1.tar.gz) = 34163 -SIZE (cargo/x25519-dalek-1.1.1.tar.gz) = 84499 -SIZE (cargo/xattr-0.2.2.tar.gz) = 11750 -SIZE (cargo/xflags-0.2.2.tar.gz) = 10099 -SIZE (cargo/xflags-macros-0.2.2.tar.gz) = 10624 -SIZE (cargo/xml-rs-0.8.4.tar.gz) = 52690 -SIZE (cargo/xshell-0.1.14.tar.gz) = 20415 -SIZE (cargo/xshell-macros-0.1.14.tar.gz) = 2677 -SIZE (cargo/zbus-2.1.1.tar.gz) = 103818 -SIZE (cargo/zbus_macros-2.1.1.tar.gz) = 23945 -SIZE (cargo/zbus_names-2.1.0.tar.gz) = 8481 +SIZE (cargo/windows-0.39.0.tar.gz) = 12776691 +SIZE (cargo/windows-sys-0.36.1.tar.gz) = 3347053 +SIZE (cargo/windows_aarch64_msvc-0.36.1.tar.gz) = 661960 +SIZE (cargo/windows_aarch64_msvc-0.39.0.tar.gz) = 661960 +SIZE (cargo/windows_i686_gnu-0.36.1.tar.gz) = 818115 +SIZE (cargo/windows_i686_gnu-0.39.0.tar.gz) = 818115 +SIZE (cargo/windows_i686_msvc-0.36.1.tar.gz) = 724575 +SIZE (cargo/windows_i686_msvc-0.39.0.tar.gz) = 724575 +SIZE (cargo/windows_x86_64_gnu-0.36.1.tar.gz) = 790934 +SIZE (cargo/windows_x86_64_gnu-0.39.0.tar.gz) = 790933 +SIZE (cargo/windows_x86_64_msvc-0.36.1.tar.gz) = 661999 +SIZE (cargo/windows_x86_64_msvc-0.39.0.tar.gz) = 662005 +SIZE (cargo/x25519-dalek-1.2.0.tar.gz) = 88676 +SIZE (cargo/xattr-0.2.3.tar.gz) = 11959 +SIZE (cargo/xflags-0.2.4.tar.gz) = 9932 +SIZE (cargo/xflags-macros-0.2.4.tar.gz) = 10740 +SIZE (cargo/xshell-0.1.17.tar.gz) = 21019 +SIZE (cargo/xshell-macros-0.1.17.tar.gz) = 2682 +SIZE (cargo/zbus-2.3.2.tar.gz) = 113900 +SIZE (cargo/zbus_macros-2.3.2.tar.gz) = 25540 +SIZE (cargo/zbus_names-2.2.0.tar.gz) = 9216 SIZE (cargo/zeroize-1.3.0.tar.gz) = 15913 SIZE (cargo/zeroize_derive-1.3.2.tar.gz) = 10299 -SIZE (cargo/zvariant-3.3.0.tar.gz) = 67332 -SIZE (cargo/zvariant_derive-3.3.0.tar.gz) = 10932 -SIZE (gurk-rs-0.2.5.tar.gz) = 243867 +SIZE (cargo/zvariant-3.6.0.tar.gz) = 68075 +SIZE (cargo/zvariant_derive-3.6.0.tar.gz) = 10957 +SIZE (gurk-rs-0.3.0-vendorfiles.tar.gz) = 767295 +SIZE (gurk-rs-0.3.0.tar.gz) = 246873 diff --git a/net/gurk-rs/files/config b/net/gurk-rs/files/config index 61c95e0..1d30ff5 100644 --- a/net/gurk-rs/files/config +++ b/net/gurk-rs/files/config @@ -1,31 +1,21 @@ -[source."https://github.com/boxdot/libsignal-service-rs"] -git = "https://github.com/boxdot/libsignal-service-rs" -rev = "8be91da2" -replace-with = "vendored-sources" - -[source."https://github.com/boxdot/presage.git"] -git = "https://github.com/boxdot/presage.git" -rev = "f908e8f" -replace-with = "vendored-sources" - -[source."https://github.com/signalapp/curve25519-dalek.git"] -git = "https://github.com/signalapp/curve25519-dalek.git" +[source."https://github.com/signalapp/curve25519-dalek"] +git = "https://github.com/signalapp/curve25519-dalek" branch = "lizard2" replace-with = "vendored-sources" -[source."https://github.com/signalapp/libsignal-client"] -git = "https://github.com/signalapp/libsignal-client" -tag = "v0.11.0" +[source."https://github.com/signalapp/libsignal"] +git = "https://github.com/signalapp/libsignal" +tag = "v0.20.0" replace-with = "vendored-sources" -[source."https://github.com/signalapp/poksho.git"] -git = "https://github.com/signalapp/poksho.git" -tag = "v0.7.0" +[source."https://github.com/whisperfish/libsignal-service-rs"] +git = "https://github.com/whisperfish/libsignal-service-rs" +rev = "8666ba56f47e405aaf8ed243be6e2ad1b5ad68c1" replace-with = "vendored-sources" -[source."https://github.com/signalapp/zkgroup"] -git = "https://github.com/signalapp/zkgroup" -tag = "v0.7.3" +[source."https://github.com/whisperfish/presage"] +git = "https://github.com/whisperfish/presage" +rev = "f84d958" replace-with = "vendored-sources" [source.vendored-sources] diff --git a/net/gurk-rs/files/vendor/curve25519-dalek-2.0.0/.cargo-checksum.json b/net/gurk-rs/files/vendor/curve25519-dalek-2.0.0/.cargo-checksum.json deleted file mode 100644 index 8c26b50..0000000 --- a/net/gurk-rs/files/vendor/curve25519-dalek-2.0.0/.cargo-checksum.json +++ /dev/null @@ -1 +0,0 @@ -{"files":{"CHANGELOG.md":"90461f680fbff6e35854621055254d473ce1e7fca887b74e74ccbce3e7610e4e","CONTRIBUTING.md":"10b88528724037ed24627bf7ed3fe4e9efc615309dfb37ebc3ff6f4493f6def5","Cargo.toml":"566b415d6fb7a8f7e92e74c2acbbf4e072fa5e4f92bd7bcc568aada50b5bc8b6","LICENSE":"aa9c248214cbbc0cfef3e2037cdc27d7fad62908caaa0eefdc6e372b43df7bd1","Makefile":"3bdd6d7b89b2a1d0e69feab4b8f11514aef2b14c180726750e5de413b728d544","README.md":"e84e25ff7c25f45b9af235568bc2f9b4a35e5296c59b72d1296a295211eeeabf","benches/dalek_benchmarks.rs":"e7aef2227fa024b4d211cd867fbc5c1301bcb085e0eeaac8e6114b29793e167f","docs/assets/dalek-logo-clear.png":"6babf6c1cdb10af05142501af2c4947765ef7839f87b91bc683165a8369fc3f4","docs/assets/dalek-logo.png":"a4a0451c5a2c0417584dc7d7d1388283b3bf9aeef89ee64ee073cdcd83c1a0f1","docs/assets/dalek-logo.svg":"22534b6935cfb8ccd6512ee13006700c451b28feb13acc137668caf00901633f","docs/assets/rustdoc-include-katex-header.html":"348752aa412e1dc774427f20d8d51ca0b2923979d4829cbd493d76e499f2674e","docs/avx2-notes.md":"5aa2bc7462c26631cc18d7b8f62e83caa9479672efc34046db7c78f650fb03aa","docs/ifma-notes.md":"7ca18607cafca402b832c313de42763df9cf1f8c9ca0ac58621322b5e33e8461","docs/parallel-formulas.md":"df2f4633055ba7d0594d3e6b53252ac3f5ca0454e20d7a971527b6509d136e43","src/backend/mod.rs":"667288065b88b72e320cfb9c77061f03df5b21193effbf1eacf8e5cf37956bdd","src/backend/serial/curve_models/mod.rs":"207b0669ab38fa00417d03e80c61f014b9232aa6f9827832950032fb057df179","src/backend/serial/mod.rs":"8d64f8575e7d7fe71614ca83702bf4dd2473dc7e35edf65dbe3e64ab4f6e6241","src/backend/serial/scalar_mul/mod.rs":"ac3359bd199ab18eebad34bb8abe6e83831c489ed4f0e62fdde32e284ba7409a","src/backend/serial/scalar_mul/pippenger.rs":"bfab409306c0f88bbbe0bffedf3f66ccc011e9c1f6caa46aef1ce9727c48d3b6","src/backend/serial/scalar_mul/precomputed_straus.rs":"b735367646cd08a31d127882b623d22e77fda4197557d2e5f1bbf34e8da587db","src/backend/serial/scalar_mul/straus.rs":"7c0e5d9218c51397de3d43e6bc173784a900336cf57f079c028fd893938ea2af","src/backend/serial/scalar_mul/variable_base.rs":"8511829f2324d1483a98bbd1fa9fe7fd6920bedb39ba5facfc380690289c612a","src/backend/serial/scalar_mul/vartime_double_base.rs":"24d3fdd1d8c957d02e513fec446726038ead042f59ec33b705d6645a030321d9","src/backend/serial/u32/constants.rs":"841c98daa3f08713b5544c9b1d361541498b811df85b69edb453929fd33e7218","src/backend/serial/u32/field.rs":"c1e1e097335f3b0e0cd84d726e43e1b2123fc73c4f5d926d5982ea225ff452b5","src/backend/serial/u32/mod.rs":"c3694fd2a4324ee1a1889d29b3d08fd472afcbf9358227d10a68ddf98f46a167","src/backend/serial/u32/scalar.rs":"a797284c92f36626e70c877cf32da6b79b44c0ca634a3bc8754803f0cae7f600","src/backend/serial/u64/constants.rs":"c0ee51f1300a5b3b7178a74acddcabed06ff05353e83e78fcf50a98033b93ddd","src/backend/serial/u64/field.rs":"e51b138c298099042584ae2d59433f4daed703a995d87ae35ac909eb5c188327","src/backend/serial/u64/mod.rs":"e310c81ec51f08f6824b3ef4378d6e492c4b46b36351de918438fa33e6db552a","src/backend/serial/u64/scalar.rs":"75c7f05daafea7778c6a44a448edcac8330f813787314b9b03b61b46e9b07384","src/backend/vector/avx2/constants.rs":"1bf0d0c1749cc4f0c95025ba13f9ed0cd6820f05135e52b457e1219843129d7d","src/backend/vector/avx2/edwards.rs":"57cc5cd12b4c20c0254a66686c98d62536f0ac4d79ae880f337f3a578d6b0dc6","src/backend/vector/avx2/field.rs":"30ae1c7ea1c03aae24dea971480d1921d621df2abf009104fc651d46b14aa842","src/backend/vector/avx2/mod.rs":"532e755195caa53b6acf21cfc39341b570f37553c77ad19c2908d5fa8d1e4a9a","src/backend/vector/ifma/constants.rs":"b1acd2c8674a5e710d753dfb159f0ea507585f2903f49f6f97802e53f5584bcf","src/backend/vector/ifma/edwards.rs":"c3b55fa23b117a83dee32201131f64bc4a050d3e96de29be345ef41b0291ea39","src/backend/vector/ifma/field.rs":"b95de5f0140f043b31cac506b713d3d3359f052092760e06effb2b743b2531ea","src/backend/vector/ifma/mod.rs":"385c894444884ec90052143502b8e37d7f36416e1dfd7e31ec588914d1a26527","src/backend/vector/mod.rs":"2c9121c1907a5a7fe34e130a3c21ef537a7abcd900df1b0c072d12e9eae0295b","src/backend/vector/scalar_mul/mod.rs":"e7a4980586ef8527ec4ddfe22e0c3128f6407d2cd54a24c5756975e8e3ae8d4f","src/backend/vector/scalar_mul/pippenger.rs":"e87703ea516006fadc567fa5b75b6c5fee6ec5a9ad27368726fae0747e471368","src/backend/vector/scalar_mul/precomputed_straus.rs":"982acacbf478c5ee0f7e0bc5650b22960655550ac08b888e3477fc786ce0c959","src/backend/vector/scalar_mul/straus.rs":"e2b65fae01d77433ccf54cc6994ba2e59701527d8ff721e8b223e784bb4f6285","src/backend/vector/scalar_mul/variable_base.rs":"c638bb2975b421d2bb6f29589c2e9b46831592b835851fed43569a8a5204c36e","src/backend/vector/scalar_mul/vartime_double_base.rs":"47ec101016a9c2126f934060bef57a5aef77a7ad05bff183cd13e56bf782e49f","src/constants.rs":"deeb7a7eef8ab83ce9777aaf30c901c273c4b2e6172b39d1febc2210affc290c","src/edwards.rs":"ab9f2ef59be48282d791556a25ef07d5b8c5da6a5f23c3790ea5bbc47bba757f","src/field.rs":"db8b3ccd985a691db290ca4ad9e765c166003906caf1c5f2dfc103a55d6686ce","src/lib.rs":"f9e5e3d31d10cac9a230d17f268b04546f9080ec27916ebd3f0c452ad152e8c9","src/lizard/LICENSE":"84da1cdd704d51e2ca03719df50c4e5b400fde68eb39dd70a976ab6122283f29","src/lizard/jacobi_quartic.rs":"8beb8b33dda13a76a376e0af51930b7beee95aa986c65ba844fb895404e1cf19","src/lizard/lizard_constants.rs":"feefcbfc0f3958ed2c2e089c255d1c68c639d6f5e5939c6996080a33a7189a65","src/lizard/lizard_ristretto.rs":"7e260163ea6bd7d26f5c34fe902d512f6ed23d3a73032e66cf2c82fb49bd44be","src/lizard/mod.rs":"cab61bc4f15f10370f3b378eddf3083650b95aead44d91549a210dbcf0fa5a0a","src/lizard/u32_constants.rs":"443b9b4755625a7f939f09138d1c1fe9664a49fc33272186df02e5d2e193490a","src/lizard/u64_constants.rs":"915218db4cf072a000c26bb6e0d7690b76480dd3f906571a321970cfc04e0471","src/macros.rs":"e2df1086f1b1c72ab72eb5a1153938a3d02cd92d4cb20629fd072ff79b886ffe","src/montgomery.rs":"b5c2244b0fe69fee3f0167aa6641eadfb2fb786f1047c358eda33298ed7f8c82","src/prelude.rs":"2a4cbed499e17a2aff657f6287abe0f6d242414f5fdbf40e15668691b680ad3e","src/ristretto.rs":"742088bfa780c4fe9ed82a25e481c335733335b3ce6a855e04fe125165502023","src/scalar.rs":"e14450460b7bda95bfcdae92e6e4b68fc9346482a444770ce8c909c8d4c14da3","src/traits.rs":"795e88e021efd3beb1a4ff1c137369ecf5ac13c4ed0e2559d67a486259ee3c75","src/window.rs":"2176f6b40306b4b4b02c302b227c4a0f1ef0062dd1535438cc5a905666241433","vendor/ristretto.sage":"a2f4309ada0afa4156f5a660be4384a0f1f332c12f836199124f48e89310344d"},"package":null} \ No newline at end of file diff --git a/net/gurk-rs/files/vendor/curve25519-dalek-2.0.0/CHANGELOG.md b/net/gurk-rs/files/vendor/curve25519-dalek-2.0.0/CHANGELOG.md deleted file mode 100644 index a46b2ff..0000000 --- a/net/gurk-rs/files/vendor/curve25519-dalek-2.0.0/CHANGELOG.md +++ /dev/null @@ -1,104 +0,0 @@ -# Changelog - -Entries are listed in reverse chronological order. - -## 2.0.0 - -* Fix a data modeling error in the `serde` feature pointed out by Trevor Perrin - which caused points and scalars to be serialized with length fields rather - than as fixed-size 32-byte arrays. This is a breaking change, but it fixes - compatibility with `serde-json` and ensures that the `serde-bincode` encoding - matches the conventional encoding for X/Ed25519. -* Update `rand_core` to `0.5`, allowing use with new `rand` versions. -* Switch from `clear_on_drop` to `zeroize` (by Tony Arcieri). -* Require `subtle = ^2.2.1` and remove the note advising nightly Rust, which is - no longer required as of that version of `subtle`. See the `subtle` - changelog for more details. -* Update `README.md` for `2.x` series. -* Remove the `build.rs` hack which loaded the entire crate into its own - `build.rs` to generate constants, and keep the constants in the source code. - -The only significant change is the data model change to the `serde` feature; -besides the `rand_core` version bump, there are no other user-visible changes. - -## 1.2.3 - -* Fix an issue identified by a Quarkslab audit (and Jack Grigg), where manually - constructing unreduced `Scalar` values, as needed for X/Ed25519, and then - performing scalar/scalar arithmetic could compute incorrect results. -* Switch to upstream Rust intrinsics for the IFMA backend now that they exist in - Rust and don't need to be defined locally. -* Ensure that the NAF computation works correctly, even for parameters never - used elsewhere in the codebase. -* Minor refactoring to EdwardsPoint decompression. -* Fix broken links in documentation. -* Fix compilation on nightly broken due to changes to the `#[doc(include)]` path - root (not quite correctly done in 1.2.2). - -## 1.2.2 - -* Fix a typo in an internal doc-comment. -* Add the "crypto" tag to crate metadata. -* Fix compilation on nightly broken due to changes to the `#[doc(include)]` path - root. - -## 1.2.1 - -* Fix a bug in bucket index calculations in the Pippenger multiscalar algorithm - for very large input sizes. -* Add a more extensive randomized multiscalar multiplication consistency check - to the test suite to prevent regressions. -* Ensure that that multiscalar and NAF computations work correctly on extremal - `Scalar` values constructed via `from_bits`. - -## 1.2.0 - -* New multiscalar multiplication algorithm with better performance for - large problem sizes. The backend algorithm is selected - transparently using the size hints of the input iterators, so no - changes are required for client crates to start using it. -* Equality of Edwards points is now checked in projective coordinates. -* Serde can now be used with `no_std`. - -## 1.1.4 - -* Fix typos in documentation comments. -* Remove unnecessary `Default` bound on `Scalar::from_hash`. - -## 1.1.3 - -* Reverts the change in 1.1.0 to allow owned and borrowed RNGs, which caused a breakage due to a subtle interaction with ownership rules. (The `RngCore` change is retained). - -## 1.1.2 - -* Disabled KaTeX on `docs.rs` pending proper [support upstream](https://github.com/rust-lang/docs.rs/issues/302). - -## 1.1.1 - -* Fixed an issue related to `#[cfg(rustdoc)]` which prevented documenting multiple backends. - -## 1.1.0 - -* Adds support for precomputation for multiscalar multiplication. -* Restructures the internal source tree into `serial` and `vector` backends (no change to external API). -* Adds a new IFMA backend which sets speed records. -* The `avx2_backend` feature is now an alias for the `simd_backend` feature, which autoselects an appropriate vector backend (currently AVX2 or IFMA). -* Replaces the `rand` dependency with `rand_core`. -* Generalizes trait bounds on `RistrettoPoint::random()` and `Scalar::random()` to allow owned and borrowed RNGs and to allow `RngCore` instead of `Rng`. - -## 1.0.3 - -* Adds `ConstantTimeEq` implementation for compressed points. - -## 1.0.2 - -* Fixes a typo in the naming of variables in Ristretto formulas (no change to functionality). - -## 1.0.1 - -* Depends on the stable `2.0` version of `subtle` instead of `2.0.0-pre.0`. - -## 1.0.0 - -Initial stable release. Yanked due to a dependency mistake (see above). - diff --git a/net/gurk-rs/files/vendor/curve25519-dalek-2.0.0/CONTRIBUTING.md b/net/gurk-rs/files/vendor/curve25519-dalek-2.0.0/CONTRIBUTING.md deleted file mode 100644 index 86622d4..0000000 --- a/net/gurk-rs/files/vendor/curve25519-dalek-2.0.0/CONTRIBUTING.md +++ /dev/null @@ -1,28 +0,0 @@ -# Contributing to curve25519-dalek - -If you have questions or comments, please feel free to email the -authors. - -For feature requests, suggestions, and bug reports, please open an issue on -[our Github](https://github.com/dalek-cryptography/curve25519-dalek). (Or, send us -an email if you're opposed to using Github for whatever reason.) - -Patches are welcomed as pull requests on -[our Github](https://github.com/dalek-cryptography/curve25519-dalek), as well as by -email (preferably sent to all of the authors listed in `Cargo.toml`). - -All issues on curve25519-dalek are mentored, if you want help with a bug just -ask @isislovecruft or @hdevalence. - -Some issues are easier than others. The `easy` label can be used to find the -easy issues. If you want to work on an issue, please leave a comment so that we -can assign it to you! - -# Code of Conduct - -We follow the [Rust Code of Conduct](http://www.rust-lang.org/conduct.html), -with the following additional clauses: - -* We respect the rights to privacy and anonymity for contributors and people in - the community. If someone wishes to contribute under a pseudonym different to - their primary identity, that wish is to be respected by all contributors. diff --git a/net/gurk-rs/files/vendor/curve25519-dalek-2.0.0/Cargo.toml b/net/gurk-rs/files/vendor/curve25519-dalek-2.0.0/Cargo.toml deleted file mode 100644 index bbc354f..0000000 --- a/net/gurk-rs/files/vendor/curve25519-dalek-2.0.0/Cargo.toml +++ /dev/null @@ -1,61 +0,0 @@ -[package] -name = "curve25519-dalek" -version = "2.0.0" -authors = ["Isis Lovecruft ", - "Henry de Valence "] -readme = "README.md" -license = "BSD-3-Clause" -repository = "https://github.com/dalek-cryptography/curve25519-dalek" -homepage = "https://dalek.rs/curve25519-dalek" -documentation = "https://docs.rs/curve25519-dalek" -categories = ["cryptography", "no-std"] -keywords = ["cryptography", "crypto", "ristretto", "curve25519", "ristretto255"] -description = "A pure-Rust implementation of group operations on ristretto255 and Curve25519" -exclude = [ - "**/.gitignore", - ".gitignore", - ".travis.yml", -] - -[package.metadata.docs.rs] -# Disabled for now since this is borked; tracking https://github.com/rust-lang/docs.rs/issues/302 -# rustdoc-args = ["--html-in-header", ".cargo/registry/src/github.com-1ecc6299db9ec823/curve25519-dalek-0.13.2/rustdoc-include-katex-header.html"] -features = ["nightly", "simd_backend"] - -[badges] -travis-ci = { repository = "dalek-cryptography/curve25519-dalek", branch = "master"} - -[dev-dependencies] -sha2 = { version = "0.8", default-features = false } -bincode = "1" -criterion = "0.3" -rand = "0.7" - -[[bench]] -name = "dalek_benchmarks" -harness = false - -[dependencies] -rand_core = { version = "0.5", default-features = false } -byteorder = { version = "^1.2.3", default-features = false, features = ["i128"] } -digest = { version = "0.8", default-features = false } -subtle = { version = "^2.2.1", default-features = false } -serde = { version = "1.0", default-features = false, optional = true, features = ["derive"] } -packed_simd = { version = "0.3", features = ["into_bits"], optional = true } -zeroize = { version = "1", default-features = false } - -[features] -nightly = ["subtle/nightly"] -default = ["std", "u64_backend"] -std = ["alloc", "subtle/std", "rand_core/std"] -alloc = ["zeroize/alloc"] - -# The u32 backend uses u32s with u64 products. -u32_backend = [] -# The u64 backend uses u64s with u128 products. -u64_backend = [] -# The SIMD backend uses parallel formulas, using either AVX2 or AVX512-IFMA. -simd_backend = ["nightly", "u64_backend", "packed_simd"] -# DEPRECATED: this is now an alias for `simd_backend` and may be removed -# in some future release. -avx2_backend = ["simd_backend"] diff --git a/net/gurk-rs/files/vendor/curve25519-dalek-2.0.0/LICENSE b/net/gurk-rs/files/vendor/curve25519-dalek-2.0.0/LICENSE deleted file mode 100644 index 2501697..0000000 --- a/net/gurk-rs/files/vendor/curve25519-dalek-2.0.0/LICENSE +++ /dev/null @@ -1,64 +0,0 @@ -Copyright (c) 2016-2019 Isis Agora Lovecruft, Henry de Valence. All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are -met: - -1. Redistributions of source code must retain the above copyright -notice, this list of conditions and the following disclaimer. - -2. Redistributions in binary form must reproduce the above copyright -notice, this list of conditions and the following disclaimer in the -documentation and/or other materials provided with the distribution. - -3. Neither the name of the copyright holder nor the names of its -contributors may be used to endorse or promote products derived from -this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS -IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED -TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A -PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED -TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR -PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF -LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -======================================================================== - -Portions of curve25519-dalek were originally derived from Adam Langley's -Go ed25519 implementation, found at , -under the following licence: - -======================================================================== - -Copyright (c) 2012 The Go Authors. All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are -met: - - * Redistributions of source code must retain the above copyright -notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above -copyright notice, this list of conditions and the following disclaimer -in the documentation and/or other materials provided with the -distribution. - * Neither the name of Google Inc. nor the names of its -contributors may be used to endorse or promote products derived from -this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS -IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED -TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A -PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER -OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, -EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR -PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF -LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/net/gurk-rs/files/vendor/curve25519-dalek-2.0.0/Makefile b/net/gurk-rs/files/vendor/curve25519-dalek-2.0.0/Makefile deleted file mode 100644 index e447175..0000000 --- a/net/gurk-rs/files/vendor/curve25519-dalek-2.0.0/Makefile +++ /dev/null @@ -1,8 +0,0 @@ -FEATURES := nightly yolocrypto avx2_backend - -doc: - cargo rustdoc --features "$(FEATURES)" -- --html-in-header docs/assets/rustdoc-include-katex-header.html - -doc-internal: - cargo rustdoc --features "$(FEATURES)" -- --html-in-header docs/assets/rustdoc-include-katex-header.html --document-private-items - diff --git a/net/gurk-rs/files/vendor/curve25519-dalek-2.0.0/README.md b/net/gurk-rs/files/vendor/curve25519-dalek-2.0.0/README.md deleted file mode 100644 index e3363f5..0000000 --- a/net/gurk-rs/files/vendor/curve25519-dalek-2.0.0/README.md +++ /dev/null @@ -1,207 +0,0 @@ - -# curve25519-dalek [![](https://img.shields.io/crates/v/curve25519-dalek.svg)](https://crates.io/crates/curve25519-dalek) [![](https://img.shields.io/badge/dynamic/json.svg?label=docs&uri=https%3A%2F%2Fcrates.io%2Fapi%2Fv1%2Fcrates%2Fcurve25519-dalek%2Fversions&query=%24.versions%5B0%5D.num&colorB=4F74A6)](https://doc.dalek.rs) [![](https://travis-ci.org/dalek-cryptography/curve25519-dalek.svg?branch=master)](https://travis-ci.org/dalek-cryptography/curve25519-dalek) - - - -**A pure-Rust implementation of group operations on Ristretto and Curve25519.** - -`curve25519-dalek` is a library providing group operations on the Edwards and -Montgomery forms of Curve25519, and on the prime-order Ristretto group. - -`curve25519-dalek` is not intended to provide implementations of any particular -crypto protocol. Rather, implementations of those protocols (such as -[`x25519-dalek`][x25519-dalek] and [`ed25519-dalek`][ed25519-dalek]) should use -`curve25519-dalek` as a library. - -`curve25519-dalek` is intended to provide a clean and safe _mid-level_ API for use -implementing a wide range of ECC-based crypto protocols, such as key agreement, -signatures, anonymous credentials, rangeproofs, and zero-knowledge proof -systems. - -In particular, `curve25519-dalek` implements Ristretto, which constructs a -prime-order group from a non-prime-order Edwards curve. This provides the -speed and safety benefits of Edwards curve arithmetic, without the pitfalls of -cofactor-related abstraction mismatches. - -# Documentation - -The semver-stable, public-facing `curve25519-dalek` API is documented -[here][docs-external]. In addition, the unstable internal implementation -details are documented [here][docs-internal]. - -The `curve25519-dalek` documentation requires a custom HTML header to include -KaTeX for math support. Unfortunately `cargo doc` does not currently support -this, but docs can be built using -```sh -make doc -make doc-internal -``` - -# Use - -To import `curve25519-dalek`, add the following to the dependencies section of -your project's `Cargo.toml`: -```toml -curve25519-dalek = "2" -``` - -The `2.x` series has API almost entirely unchanged from the `1.x` series, -except that: - -* an error in the data modeling for the (optional) `serde` feature was - corrected, so that when the `2.x`-series `serde` implementation is used - with `serde-bincode`, the derived serialization matches the usual X/Ed25519 - formats; - -* the `rand` version was updated. - -See `CHANGELOG.md` for more details. - -# Backends and Features - -The `nightly` feature enables features available only when using a Rust nightly -compiler. In particular, it is required for rendering documentation and for -the SIMD backends. - -Curve arithmetic is implemented using one of the following backends: - -* a `u32` backend using serial formulas and `u64` products; -* a `u64` backend using serial formulas and `u128` products; -* an `avx2` backend using [parallel formulas][parallel_doc] and `avx2` instructions (sets speed records); -* an `ifma` backend using [parallel formulas][parallel_doc] and `ifma` instructions (sets speed records); - -By default the `u64` backend is selected. To select a specific backend, use: -```sh -cargo build --no-default-features --features "std u32_backend" -cargo build --no-default-features --features "std u64_backend" -# Requires nightly, RUSTFLAGS="-C target_feature=+avx2" to use avx2 -cargo build --no-default-features --features "std simd_backend" -# Requires nightly, RUSTFLAGS="-C target_feature=+avx512ifma" to use ifma -cargo build --no-default-features --features "std simd_backend" -``` -Crates using `curve25519-dalek` can either select a backend on behalf of their -users, or expose feature flags that control the `curve25519-dalek` backend. - -The `std` feature is enabled by default, but it can be disabled for no-`std` -builds using `--no-default-features`. Note that this requires explicitly -selecting an arithmetic backend using one of the `_backend` features. -If no backend is selected, compilation will fail. - -# Safety - -The `curve25519-dalek` types are designed to make illegal states -unrepresentable. For example, any instance of an `EdwardsPoint` is -guaranteed to hold a point on the Edwards curve, and any instance of a -`RistrettoPoint` is guaranteed to hold a valid point in the Ristretto -group. - -All operations are implemented using constant-time logic (no -secret-dependent branches, no secret-dependent memory accesses), -unless specifically marked as being variable-time code. -We believe that our constant-time logic is lowered to constant-time -assembly, at least on `x86_64` targets. - -As an additional guard against possible future compiler optimizations, -the `subtle` crate places an optimization barrier before every -conditional move or assignment. More details can be found in [the -documentation for the `subtle` crate][subtle_doc]. - -Some functionality (e.g., multiscalar multiplication or batch -inversion) requires heap allocation for temporary buffers. All -heap-allocated buffers of potentially secret data are explicitly -zeroed before release. - -However, we do not attempt to zero stack data, for two reasons. -First, it's not possible to do so correctly: we don't have control -over stack allocations, so there's no way to know how much data to -wipe. Second, because `curve25519-dalek` provides a mid-level API, -the correct place to start zeroing stack data is likely not at the -entrypoints of `curve25519-dalek` functions, but at the entrypoints of -functions in other crates. - -The implementation is memory-safe, and contains no significant -`unsafe` code. The SIMD backend uses `unsafe` internally to call SIMD -intrinsics. These are marked `unsafe` only because invoking them on an -inappropriate CPU would cause `SIGILL`, but the entire backend is only -compiled with appropriate `target_feature`s, so this cannot occur. - -# Performance - -Benchmarks are run using [`criterion.rs`][criterion]: - -```sh -cargo bench --no-default-features --features "std u32_backend" -cargo bench --no-default-features --features "std u64_backend" -# Uses avx2 or ifma only if compiled for an appropriate target. -export RUSTFLAGS="-C target_cpu=native" -cargo bench --no-default-features --features "std simd_backend" -``` - -Performance is a secondary goal behind correctness, safety, and -clarity, but we aim to be competitive with other implementations. - -# FFI - -Unfortunately, we have no plans to add FFI to `curve25519-dalek` directly. The -reason is that we use Rust features to provide an API that maintains safety -invariants, which are not possible to maintain across an FFI boundary. For -instance, as described in the _Safety_ section above, invalid points are -impossible to construct, and this would not be the case if we exposed point -operations over FFI. - -However, `curve25519-dalek` is designed as a *mid-level* API, aimed at -implementing other, higher-level primitives. Instead of providing FFI at the -mid-level, our suggestion is to implement the higher-level primitive (a -signature, PAKE, ZKP, etc) in Rust, using `curve25519-dalek` as a dependency, -and have that crate provide a minimal, byte-buffer-oriented FFI specific to -that primitive. - -# Contributing - -Please see [CONTRIBUTING.md][contributing]. - -Patches and pull requests should be make against the `develop` -branch, **not** `master`. - -# About - -**SPOILER ALERT:** *The Twelfth Doctor's first encounter with the Daleks is in -his second full episode, "Into the Dalek". A beleaguered ship of the "Combined -Galactic Resistance" has discovered a broken Dalek that has turned "good", -desiring to kill all other Daleks. The Doctor, Clara and a team of soldiers -are miniaturized and enter the Dalek, which the Doctor names Rusty. They -repair the damage, but accidentally restore it to its original nature, causing -it to go on the rampage and alert the Dalek fleet to the whereabouts of the -rebel ship. However, the Doctor manages to return Rusty to its previous state -by linking his mind with the Dalek's: Rusty shares the Doctor's view of the -universe's beauty, but also his deep hatred of the Daleks. Rusty destroys the -other Daleks and departs the ship, determined to track down and bring an end -to the Dalek race.* - -`curve25519-dalek` is authored by Isis Agora Lovecruft and Henry de Valence. - -Portions of this library were originally a port of [Adam Langley's -Golang ed25519 library](https://github.com/agl/ed25519), which was in -turn a port of the reference `ref10` implementation. Most of this code, -including the 32-bit field arithmetic, has since been rewritten. - -The fast `u32` and `u64` scalar arithmetic was implemented by Andrew Moon, and -the addition chain for scalar inversion was provided by Brian Smith. The -optimised batch inversion was contributed by Sean Bowe and Daira Hopwood. - -The `no_std` and `zeroize` support was contributed by Tony Arcieri. - -Thanks also to Ashley Hauck, Lucas Salibian, and Manish Goregaokar for their -contributions. - -[ed25519-dalek]: https://github.com/dalek-cryptography/ed25519-dalek -[x25519-dalek]: https://github.com/dalek-cryptography/x25519-dalek -[contributing]: https://github.com/dalek-cryptography/curve25519-dalek/blob/master/CONTRIBUTING.md -[docs-external]: https://doc.dalek.rs/curve25519_dalek/ -[docs-internal]: https://doc-internal.dalek.rs/curve25519_dalek/ -[criterion]: https://github.com/japaric/criterion.rs -[parallel_doc]: https://doc-internal.dalek.rs/curve25519_dalek/backend/vector/avx2/index.html -[subtle_doc]: https://doc.dalek.rs/subtle/ diff --git a/net/gurk-rs/files/vendor/curve25519-dalek-2.0.0/benches/dalek_benchmarks.rs b/net/gurk-rs/files/vendor/curve25519-dalek-2.0.0/benches/dalek_benchmarks.rs deleted file mode 100644 index 15d87a2..0000000 --- a/net/gurk-rs/files/vendor/curve25519-dalek-2.0.0/benches/dalek_benchmarks.rs +++ /dev/null @@ -1,339 +0,0 @@ -#![allow(non_snake_case)] - -extern crate rand; -use rand::rngs::OsRng; -use rand::thread_rng; - -#[macro_use] -extern crate criterion; - -use criterion::BatchSize; -use criterion::Criterion; - -extern crate curve25519_dalek; - -use curve25519_dalek::constants; -use curve25519_dalek::scalar::Scalar; -use curve25519_dalek::field::FieldElement; - -static BATCH_SIZES: [usize; 5] = [1, 2, 4, 8, 16]; -static MULTISCALAR_SIZES: [usize; 13] = [1, 2, 4, 8, 16, 32, 64, 128, 256, 384, 512, 768, 1024]; - -mod edwards_benches { - use super::*; - - use curve25519_dalek::edwards::EdwardsPoint; - - fn compress(c: &mut Criterion) { - let B = &constants::ED25519_BASEPOINT_POINT; - c.bench_function("EdwardsPoint compression", move |b| b.iter(|| B.compress())); - } - - fn decompress(c: &mut Criterion) { - let B_comp = &constants::ED25519_BASEPOINT_COMPRESSED; - c.bench_function("EdwardsPoint decompression", move |b| { - b.iter(|| B_comp.decompress().unwrap()) - }); - } - - fn consttime_fixed_base_scalar_mul(c: &mut Criterion) { - let B = &constants::ED25519_BASEPOINT_TABLE; - let s = Scalar::from(897987897u64).invert(); - c.bench_function("Constant-time fixed-base scalar mul", move |b| { - b.iter(|| B * &s) - }); - } - - fn consttime_variable_base_scalar_mul(c: &mut Criterion) { - let B = &constants::ED25519_BASEPOINT_POINT; - let s = Scalar::from(897987897u64).invert(); - c.bench_function("Constant-time variable-base scalar mul", move |b| { - b.iter(|| B * s) - }); - } - - fn vartime_double_base_scalar_mul(c: &mut Criterion) { - c.bench_function("Variable-time aA+bB, A variable, B fixed", |bench| { - let mut rng = thread_rng(); - let A = &Scalar::random(&mut rng) * &constants::ED25519_BASEPOINT_TABLE; - bench.iter_batched( - || (Scalar::random(&mut rng), Scalar::random(&mut rng)), - |(a, b)| EdwardsPoint::vartime_double_scalar_mul_basepoint(&a, &A, &b), - BatchSize::SmallInput, - ); - }); - } - - criterion_group! { - name = edwards_benches; - config = Criterion::default(); - targets = - compress, - decompress, - consttime_fixed_base_scalar_mul, - consttime_variable_base_scalar_mul, - vartime_double_base_scalar_mul, - } -} - -mod multiscalar_benches { - use super::*; - - use curve25519_dalek::edwards::EdwardsPoint; - use curve25519_dalek::edwards::VartimeEdwardsPrecomputation; - use curve25519_dalek::traits::MultiscalarMul; - use curve25519_dalek::traits::VartimeMultiscalarMul; - use curve25519_dalek::traits::VartimePrecomputedMultiscalarMul; - - fn construct_scalars(n: usize) -> Vec { - let mut rng = thread_rng(); - (0..n).map(|_| Scalar::random(&mut rng)).collect() - } - - fn construct_points(n: usize) -> Vec { - let mut rng = thread_rng(); - (0..n) - .map(|_| &Scalar::random(&mut rng) * &constants::ED25519_BASEPOINT_TABLE) - .collect() - } - - fn construct(n: usize) -> (Vec, Vec) { - (construct_scalars(n), construct_points(n)) - } - - fn consttime_multiscalar_mul(c: &mut Criterion) { - c.bench_function_over_inputs( - "Constant-time variable-base multiscalar multiplication", - |b, &&size| { - let points = construct_points(size); - // This is supposed to be constant-time, but we might as well - // rerandomize the scalars for every call just in case. - b.iter_batched( - || construct_scalars(size), - |scalars| EdwardsPoint::multiscalar_mul(&scalars, &points), - BatchSize::SmallInput, - ); - }, - &MULTISCALAR_SIZES, - ); - } - - fn vartime_multiscalar_mul(c: &mut Criterion) { - c.bench_function_over_inputs( - "Variable-time variable-base multiscalar multiplication", - |b, &&size| { - let points = construct_points(size); - // Rerandomize the scalars for every call to prevent - // false timings from better caching (e.g., the CPU - // cache lifts exactly the right table entries for the - // benchmark into the highest cache levels). - b.iter_batched( - || construct_scalars(size), - |scalars| EdwardsPoint::vartime_multiscalar_mul(&scalars, &points), - BatchSize::SmallInput, - ); - }, - &MULTISCALAR_SIZES, - ); - } - - fn vartime_precomputed_pure_static(c: &mut Criterion) { - c.bench_function_over_inputs( - "Variable-time fixed-base multiscalar multiplication", - move |b, &&total_size| { - let static_size = total_size; - - let static_points = construct_points(static_size); - let precomp = VartimeEdwardsPrecomputation::new(&static_points); - // Rerandomize the scalars for every call to prevent - // false timings from better caching (e.g., the CPU - // cache lifts exactly the right table entries for the - // benchmark into the highest cache levels). - b.iter_batched( - || construct_scalars(static_size), - |scalars| precomp.vartime_multiscalar_mul(&scalars), - BatchSize::SmallInput, - ); - }, - &MULTISCALAR_SIZES, - ); - } - - fn vartime_precomputed_helper(c: &mut Criterion, dynamic_fraction: f64) { - let label = format!( - "Variable-time mixed-base multiscalar multiplication ({:.0}pct dyn)", - 100.0 * dynamic_fraction, - ); - c.bench_function_over_inputs( - &label, - move |b, &&total_size| { - let dynamic_size = ((total_size as f64) * dynamic_fraction) as usize; - let static_size = total_size - dynamic_size; - - let static_points = construct_points(static_size); - let dynamic_points = construct_points(dynamic_size); - let precomp = VartimeEdwardsPrecomputation::new(&static_points); - // Rerandomize the scalars for every call to prevent - // false timings from better caching (e.g., the CPU - // cache lifts exactly the right table entries for the - // benchmark into the highest cache levels). Timings - // should be independent of points so we don't - // randomize them. - b.iter_batched( - || { - ( - construct_scalars(static_size), - construct_scalars(dynamic_size), - ) - }, - |(static_scalars, dynamic_scalars)| { - precomp.vartime_mixed_multiscalar_mul( - &static_scalars, - &dynamic_scalars, - &dynamic_points, - ) - }, - BatchSize::SmallInput, - ); - }, - &MULTISCALAR_SIZES, - ); - } - - fn vartime_precomputed_00_pct_dynamic(c: &mut Criterion) { - vartime_precomputed_helper(c, 0.0); - } - - fn vartime_precomputed_20_pct_dynamic(c: &mut Criterion) { - vartime_precomputed_helper(c, 0.2); - } - - fn vartime_precomputed_50_pct_dynamic(c: &mut Criterion) { - vartime_precomputed_helper(c, 0.5); - } - - criterion_group! { - name = multiscalar_benches; - // Lower the sample size to run the benchmarks faster - config = Criterion::default().sample_size(15); - targets = - consttime_multiscalar_mul, - vartime_multiscalar_mul, - vartime_precomputed_pure_static, - vartime_precomputed_00_pct_dynamic, - vartime_precomputed_20_pct_dynamic, - vartime_precomputed_50_pct_dynamic, - } -} - -mod ristretto_benches { - use super::*; - use curve25519_dalek::ristretto::RistrettoPoint; - - fn compress(c: &mut Criterion) { - c.bench_function("RistrettoPoint compression", |b| { - let B = &constants::RISTRETTO_BASEPOINT_POINT; - b.iter(|| B.compress()) - }); - } - - fn decompress(c: &mut Criterion) { - c.bench_function("RistrettoPoint decompression", |b| { - let B_comp = &constants::RISTRETTO_BASEPOINT_COMPRESSED; - b.iter(|| B_comp.decompress().unwrap()) - }); - } - - fn elligator(c: &mut Criterion) { - let fe_bytes = [0u8; 32]; - let fe = FieldElement::from_bytes(&fe_bytes); - - c.bench_function("RistrettoPoint Elligator", |b| { - b.iter(|| RistrettoPoint::elligator_ristretto_flavor(&fe)); - }); - } - - fn double_and_compress_batch(c: &mut Criterion) { - c.bench_function_over_inputs( - "Batch Ristretto double-and-encode", - |b, &&size| { - let mut rng = OsRng; - let points: Vec = (0..size) - .map(|_| RistrettoPoint::random(&mut rng)) - .collect(); - b.iter(|| RistrettoPoint::double_and_compress_batch(&points)); - }, - &BATCH_SIZES, - ); - } - - criterion_group! { - name = ristretto_benches; - config = Criterion::default(); - targets = - compress, - decompress, - elligator, - double_and_compress_batch, - } -} - -mod montgomery_benches { - use super::*; - - fn montgomery_ladder(c: &mut Criterion) { - c.bench_function("Montgomery pseudomultiplication", |b| { - let B = constants::X25519_BASEPOINT; - let s = Scalar::from(897987897u64).invert(); - b.iter(|| B * s); - }); - } - - criterion_group! { - name = montgomery_benches; - config = Criterion::default(); - targets = montgomery_ladder, - } -} - -mod scalar_benches { - use super::*; - - fn scalar_inversion(c: &mut Criterion) { - c.bench_function("Scalar inversion", |b| { - let s = Scalar::from(897987897u64).invert(); - b.iter(|| s.invert()); - }); - } - - fn batch_scalar_inversion(c: &mut Criterion) { - c.bench_function_over_inputs( - "Batch scalar inversion", - |b, &&size| { - let mut rng = OsRng; - let scalars: Vec = (0..size).map(|_| Scalar::random(&mut rng)).collect(); - b.iter(|| { - let mut s = scalars.clone(); - Scalar::batch_invert(&mut s); - }); - }, - &BATCH_SIZES, - ); - } - - criterion_group! { - name = scalar_benches; - config = Criterion::default(); - targets = - scalar_inversion, - batch_scalar_inversion, - } -} - -criterion_main!( - scalar_benches::scalar_benches, - montgomery_benches::montgomery_benches, - ristretto_benches::ristretto_benches, - edwards_benches::edwards_benches, - multiscalar_benches::multiscalar_benches, -); diff --git a/net/gurk-rs/files/vendor/curve25519-dalek-2.0.0/docs/assets/dalek-logo-clear.png b/net/gurk-rs/files/vendor/curve25519-dalek-2.0.0/docs/assets/dalek-logo-clear.png deleted file mode 100644 index d3170d80b21501ba3325a66e2dd7186446cb4944..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 113085 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 SJpPLO-62g~jnsW7uKj=Qh`hQ0 diff --git a/net/gurk-rs/files/vendor/curve25519-dalek-2.0.0/docs/assets/dalek-logo.png b/net/gurk-rs/files/vendor/curve25519-dalek-2.0.0/docs/assets/dalek-logo.png deleted file mode 100644 index 83d6a0c52776e03c7c56efcffdbaa8b0584d881f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 109731 zcmeFZcRbc_{6Bh2DG`xMcA_Oan+S=FqU^2gmAx|hl$9+RS&_Z7H<_XAy@jldvO+ko z>(=-8JLiw{*E#3E)1%MhllSd?jo0;>&)4(1eILo)KXaPmGzNn?BPA)WfWaJ}LI0h? zgC}1*FI7z`aoO8o8<$C#gEF1Ed!v4_8uPo2$)`cz~; z^5AN}Gy%@J&SK%09KIEU{RH@A56hl}su+J#C+zC+GdJhWkSOqgFxe?a=EoK~e0b9^RLhNDKZ}x^0kT4#Jasq6euNQeHF^7Fkhb;AaqGi*|B)X$y8oVM49A6p$kWHtd^yp; zt$6gX_U1j9qguXO#DPi|2^Ie6#BxYcYzA4Lre?xDdLl{8Nc!@BKE0^SKzd`Ic;+`X z^NIiYctt)$vSHcw{L#-M@2^uarq?dqJo?eYmVNPO#L>SoYy|&npex7tjvm(D@jPz* z?{@=E!8v39P?CH(+AM~fKKS24%*5$V9(_9KBSLiauRN0fH6pF>|N3YA+5h#=|2>by z|2xzC{{te)d;C8-s{e0fc&op!Z`KwcEsykzQ7QpA1jSgJc0TKhG3zpo&?HZSiw{B{ zNK3zqj$YEyN52+>G|J-y1tn$Q&`^4Nd;81ys^6_lp$xeL(pX(fVlU1*hS7PsJW?W{ zc?{n0IDQYk(juA=3~$AXshY1!G|7C6u|23}+>GTnoN^GEv& z#UKU0svC*s_b@t(#{BQm^`!9d3#o1Bjo{MIuHt-oP@v(5jFoa*~{<@6M76S+iG`g)ot$IMowX$n3$T{ zl%v-$Qm?_ZJ$Pezt?Jf>@ z=yVvw&`PLyg^_#kkU#qL>?z*=%cn<9h8(*kDlOMd#eXO947;cL5zCt8e~TkTi(`Ld zSg|->yXkQXBw8$6HUBFIpscVF!?BBe(sx7xdhNyzBD+-LH00T2@Z| zn+vNS?7I_(``Z83^BOzc-Rop;cE+chgQ8WCYI{7xZjtb>Tg^XxQNS*NE{+K6P!|HQ za~2jA{f|hn`y`yldeO5?==}B0c3iR^8ymZNbpAtF*}hWNcIEovvbVe2+tsD3#|3j? zLh-QzaNJuinJzyJ;2CF2Cq>U&ypaEWb?l|bzcuKgHIS28(hUp@7|I=;H8yDAHF9>| z)k{Na8oYw`!VBb*HWSU!LAc{4EP^@FeD=H~zuEHBp z0yXp4z?$A&%jzA2QB$@-qX8l3<}QVgwMd@9N?j@|X!%8JF+Y$O0rxRiEpV_z-XV*Xd>^?_9kz|IWMNC<+>j3O;{Q&gXWp8 zj#o)YV

wBujqx>C=yLF}x(3nWiC2 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 U`|&OIdalek \ No newline at end of file diff --git a/net/gurk-rs/files/vendor/curve25519-dalek-2.0.0/docs/assets/rustdoc-include-katex-header.html b/net/gurk-rs/files/vendor/curve25519-dalek-2.0.0/docs/assets/rustdoc-include-katex-header.html deleted file mode 100644 index bc4e3d8..0000000 --- a/net/gurk-rs/files/vendor/curve25519-dalek-2.0.0/docs/assets/rustdoc-include-katex-header.html +++ /dev/null @@ -1,10 +0,0 @@ - - - - - diff --git a/net/gurk-rs/files/vendor/curve25519-dalek-2.0.0/docs/avx2-notes.md b/net/gurk-rs/files/vendor/curve25519-dalek-2.0.0/docs/avx2-notes.md deleted file mode 100644 index 87992b3..0000000 --- a/net/gurk-rs/files/vendor/curve25519-dalek-2.0.0/docs/avx2-notes.md +++ /dev/null @@ -1,140 +0,0 @@ -An AVX2 implementation of the vectorized point operation strategy. - -# Field element representation - -Our strategy is to implement 4-wide multiplication and squaring by -wordslicing, using one 64-bit AVX2 lane for each field element. Field -elements are represented in the usual way as 10 `u32` limbs in radix -\\(25.5\\) (i.e., alternating between \\(2\^{26}\\) for even limbs and -\\(2\^{25}\\) for odd limbs). This has the effect that passing between -the parallel 32-bit AVX2 representation and the serial 64-bit -representation (which uses radix \\(2^{51}\\)) amounts to regrouping -digits. - -The field element representation is oriented around the AVX2 -`vpmuluqdq` instruction, which multiplies the low 32 bits of each -64-bit lane of each operand to produce a 64-bit result. - -```text,no_run -(a1 ?? b1 ?? c1 ?? d1 ??) -(a2 ?? b2 ?? c2 ?? d2 ??) - -(a1*a2 b1*b2 c1*c2 d1*d2) -``` - -To unpack 32-bit values into 64-bit lanes for use in multiplication -it would be convenient to use the `vpunpck[lh]dq` instructions, -which unpack and interleave the low and high 32-bit lanes of two -source vectors. -However, the AVX2 versions of these instructions are designed to -operate only within 128-bit lanes of the 256-bit vectors, so that -interleaving the low lanes of `(a0 b0 c0 d0 a1 b1 c1 d1)` with zero -gives `(a0 00 b0 00 a1 00 b1 00)`. Instead, we pre-shuffle the data -layout as `(a0 b0 a1 b1 c0 d0 c1 d1)` so that we can unpack the -"low" and "high" parts as - -```text,no_run -(a0 00 b0 00 c0 00 d0 00) -(a1 00 b1 00 c1 00 d1 00) -``` - -The data layout for a vector of four field elements \\( (a,b,c,d) -\\) with limbs \\( a_0, a_1, \ldots, a_9 \\) is as `[u32x8; 5]` in -the form - -```text,no_run -(a0 b0 a1 b1 c0 d0 c1 d1) -(a2 b2 a3 b3 c2 d2 c3 d3) -(a4 b4 a5 b5 c4 d4 c5 d5) -(a6 b6 a7 b7 c6 d6 c7 d7) -(a8 b8 a9 b9 c8 d8 c9 d9) -``` - -Since this breaks cleanly into two 128-bit lanes, it may be possible -to adapt it to 128-bit vector instructions such as NEON without too -much difficulty. - -# Avoiding Overflow in Doubling - -To analyze the size of the field element coefficients during the -computations, we can parameterize the bounds on the limbs of each -field element by \\( b \in \mathbb R \\) representing the excess bits -above that limb's radix, so that each limb is bounded by either -\\(2\^{25+b} \\) or \\( 2\^{26+b} \\), as appropriate. - -The multiplication routine requires that its inputs are bounded with -\\( b < 1.75 \\), in order to fit a multiplication by \\( 19 \\) -into 32 bits. Since \\( \lg 19 < 4.25 \\), \\( 19x < 2\^{32} \\) -when \\( x < 2\^{27.75} = 2\^{26 + 1.75} \\). However, this is only -required for one of the inputs; the other can grow up to \\( b < 2.5 -\\). - -In addition, the multiplication and squaring routines do not -canonically reduce their outputs, but can leave some small uncarried -excesses, so that their reduced outputs are bounded with -\\( b < 0.007 \\). - -The non-parallel portion of the doubling formulas is -$$ -\begin{aligned} -(S\_5 &&,&& S\_6 &&,&& S\_8 &&,&& S\_9 ) -&\gets -(S\_1 + S\_2 &&,&& S\_1 - S\_2 &&,&& S\_1 + 2S\_3 - S\_2 &&,&& S\_1 + S\_2 - S\_4) -\end{aligned} -$$ - -Computing \\( (S\_5, S\_6, S\_8, S\_9 ) \\) as -$$ -\begin{matrix} - & S\_1 & S\_1 & S\_1 & S\_1 \\\\ -+& S\_2 & & & S\_2 \\\\ -+& & & S\_3 & \\\\ -+& & & S\_3 & \\\\ -+& & 2p & 2p & 2p \\\\ --& & S\_2 & S\_2 & \\\\ --& & & & S\_4 \\\\ -=& S\_5 & S\_6 & S\_8 & S\_9 -\end{matrix} -$$ -results in bit-excesses \\( < (1.01, 1.60, 2.33, 2.01)\\) for -\\( (S\_5, S\_6, S\_8, S\_9 ) \\). The products we want to compute -are then -$$ -\begin{aligned} -X\_3 &\gets S\_8 S\_9 \leftrightarrow (2.33, 2.01) \\\\ -Y\_3 &\gets S\_5 S\_6 \leftrightarrow (1.01, 1.60) \\\\ -Z\_3 &\gets S\_8 S\_6 \leftrightarrow (2.33, 1.60) \\\\ -T\_3 &\gets S\_5 S\_9 \leftrightarrow (1.01, 2.01) -\end{aligned} -$$ -which are too large: it's not possible to arrange the multiplicands so -that one vector has \\(b < 2.5\\) and the other has \\( b < 1.75 \\). -However, if we flip the sign of \\( S\_4 = S\_0\^2 \\) during -squaring, so that we output \\(S\_4' = -S\_4 \pmod p\\), then we can -compute -$$ -\begin{matrix} - & S\_1 & S\_1 & S\_1 & S\_1 \\\\ -+& S\_2 & & & S\_2 \\\\ -+& & & S\_3 & \\\\ -+& & & S\_3 & \\\\ -+& & & & S\_4' \\\\ -+& & 2p & 2p & \\\\ --& & S\_2 & S\_2 & \\\\ -=& S\_5 & S\_6 & S\_8 & S\_9 -\end{matrix} -$$ -resulting in bit-excesses \\( < (1.01, 1.60, 2.33, 1.60)\\) for -\\( (S\_5, S\_6, S\_8, S\_9 ) \\). The products we want to compute -are then -$$ -\begin{aligned} -X\_3 &\gets S\_8 S\_9 \leftrightarrow (2.33, 1.60) \\\\ -Y\_3 &\gets S\_5 S\_6 \leftrightarrow (1.01, 1.60) \\\\ -Z\_3 &\gets S\_8 S\_6 \leftrightarrow (2.33, 1.60) \\\\ -T\_3 &\gets S\_5 S\_9 \leftrightarrow (1.01, 1.60) -\end{aligned} -$$ -whose right-hand sides are all bounded with \\( b < 1.75 \\) and -whose left-hand sides are all bounded with \\( b < 2.5 \\), -so that we can avoid any intermediate reductions. diff --git a/net/gurk-rs/files/vendor/curve25519-dalek-2.0.0/docs/ifma-notes.md b/net/gurk-rs/files/vendor/curve25519-dalek-2.0.0/docs/ifma-notes.md deleted file mode 100644 index c6fd3b3..0000000 --- a/net/gurk-rs/files/vendor/curve25519-dalek-2.0.0/docs/ifma-notes.md +++ /dev/null @@ -1,580 +0,0 @@ -An AVX512-IFMA implementation of the vectorized point operation -strategy. - -# IFMA instructions - -AVX512-IFMA is an extension to AVX-512 consisting of two instructions: - -* `vpmadd52luq`: packed multiply of unsigned 52-bit integers and add - the low 52 product bits to 64-bit accumulators; -* `vpmadd52huq`: packed multiply of unsigned 52-bit integers and add - the high 52 product bits to 64-bit accumulators; - -These operate on 64-bit lanes of their source vectors, taking the low -52 bits of each lane of each source vector, computing the 104-bit -products of each pair, and then adding either the high or low 52 bits -of the 104-bit products to the 64-bit lanes of the destination vector. -The multiplication is performed internally by reusing circuitry for -floating-point arithmetic. Although these instructions are part of -AVX512, the AVX512VL (vector length) extension (present whenever IFMA -is) allows using them with 512, 256, or 128-bit operands. - -This provides a major advantage to vectorized integer operations: -previously, vector operations could only use a \\(32 \times 32 -\rightarrow 64\\)-bit multiplier, while serial code could use a -\\(64\times 64 \rightarrow 128\\)-bit multiplier. - -## IFMA for big-integer multiplications - -A detailed example of the intended use of the IFMA instructions can be -found in a 2016 paper by Gueron and Krasnov, [_Accelerating Big -Integer Arithmetic Using Intel IFMA Extensions_][2016_gueron_krasnov]. -The basic idea is that multiplication of large integers (such as 1024, -2048, or more bits) can be performed as follows. - -First, convert a “packed” 64-bit representation -\\[ -\begin{aligned} -x &= x'_0 + x'_1 2^{64} + x'_2 2^{128} + \cdots \\\\ -y &= y'_0 + y'_1 2^{64} + y'_2 2^{128} + \cdots -\end{aligned} -\\] -into a “redundant” 52-bit representation -\\[ -\begin{aligned} -x &= x_0 + x_1 2^{52} + x_2 2^{104} + \cdots \\\\ -y &= y_0 + y_1 2^{52} + y_2 2^{104} + \cdots -\end{aligned} -\\] -with each \\(x_i, y_j\\) in a 64-bit lane. - -Writing the product as \\(z = z_0 + z_1 2^{52} + z_2 2^{104} + \cdots\\), -the “schoolbook” multiplication strategy gives -\\[ -\begin{aligned} -&z_0 &&=& x_0 & y_0 & & & & & & & & \\\\ -&z_1 &&=& x_1 & y_0 &+ x_0 & y_1 & & & & & & \\\\ -&z_2 &&=& x_2 & y_0 &+ x_1 & y_1 &+ x_0 & y_2 & & & & \\\\ -&z_3 &&=& x_3 & y_0 &+ x_2 & y_1 &+ x_1 & y_2 &+ x_0 & y_3 & & \\\\ -&z_4 &&=& \vdots\\;&\\;\vdots &+ x_3 & y_1 &+ x_2 & y_2 &+ x_1 & y_3 &+ \cdots& \\\\ -&z_5 &&=& & & \vdots\\;&\\;\vdots &+ x_3 & y_2 &+ x_2 & y_3 &+ \cdots& \\\\ -&z_6 &&=& & & & & \vdots\\;&\\;\vdots &+ x_3 & y_3 &+ \cdots& \\\\ -&z_7 &&=& & & & & & & \vdots\\;&\\;\vdots &+ \cdots& \\\\ -&\vdots&&=& & & & & & & & & \ddots& \\\\ -\end{aligned} -\\] -Notice that the product coefficient \\(z_k\\), representing the value -\\(z_k 2^{52k}\\), is the sum of all product terms -\\( -(x_i 2^{52 i}) (y_j 2^{52 j}) -\\) -with \\(k = i + j\\). -Write the IFMA operators \\(\mathrm{lo}(a,b)\\), denoting the low -\\(52\\) bits of \\(ab\\), and -\\(\mathrm{hi}(a,b)\\), denoting the high \\(52\\) bits of -\\(ab\\). -Now we can rewrite the product terms as -\\[ -\begin{aligned} -(x_i 2^{52 i}) (y_j 2^{52 j}) -&= -2^{52 (i+j)}( -\mathrm{lo}(x_i, y_j) + -\mathrm{hi}(x_i, y_j) 2^{52} -) -\\\\ -&= -\mathrm{lo}(x_i, y_j) 2^{52 (i+j)} + -\mathrm{hi}(x_i, y_j) 2^{52 (i+j+1)}. -\end{aligned} -\\] -This means that the low half of \\(x_i y_j\\) can be accumulated onto -the product limb \\(z_{i+j}\\) and the high half can be directly -accumulated onto the next-higher product limb \\(z_{i+j+1}\\) with no -additional operations. This allows rewriting the schoolbook -multiplication into the form -\\[ -\begin{aligned} -&z_0 &&=& \mathrm{lo}(x_0,&y_0) & & & & & & & & & & \\\\ -&z_1 &&=& \mathrm{lo}(x_1,&y_0) &+\mathrm{hi}(x_0,&y_0) &+\mathrm{lo}(x_0,&y_1) & & & & & & \\\\ -&z_2 &&=& \mathrm{lo}(x_2,&y_0) &+\mathrm{hi}(x_1,&y_0) &+\mathrm{lo}(x_1,&y_1) &+\mathrm{hi}(x_0,&y_1) &+\mathrm{lo}(x_0,&y_2) & & \\\\ -&z_3 &&=& \mathrm{lo}(x_3,&y_0) &+\mathrm{hi}(x_2,&y_0) &+\mathrm{lo}(x_2,&y_1) &+\mathrm{hi}(x_1,&y_1) &+\mathrm{lo}(x_1,&y_2) &+ \cdots& \\\\ -&z_4 &&=& \vdots\\;&\\;\vdots &+\mathrm{hi}(x_3,&y_0) &+\mathrm{lo}(x_3,&y_1) &+\mathrm{hi}(x_2,&y_1) &+\mathrm{lo}(x_2,&y_2) &+ \cdots& \\\\ -&z_5 &&=& & & \vdots\\;&\\;\vdots & \vdots\\;&\\;\vdots &+\mathrm{hi}(x_3,&y_1) &+\mathrm{lo}(x_3,&y_2) &+ \cdots& \\\\ -&z_6 &&=& & & & & & & \vdots\\;&\\;\vdots & \vdots\\;&\\;\vdots &+ \cdots& \\\\ -&\vdots&&=& & & & & & & & & & & \ddots& \\\\ -\end{aligned} -\\] -Gueron and Krasnov implement multiplication by constructing vectors -out of the columns of this diagram, so that the source operands for -the IFMA instructions are of the form \\((x_0, x_1, x_2, \ldots)\\) -and \\((y_i, y_i, y_i, \ldots)\\). -After performing the multiplication, -the product terms \\(z_i\\) are then repacked into a 64-bit representation. - -## An alternative strategy - -The strategy described above is aimed at big-integer multiplications, -such as 1024, 2048, or 4096 bits, which would be used for applications -like RSA. However, elliptic curve cryptography uses much smaller field -sizes, such as 256 or 384 bits, so a different strategy is needed. - -The parallel Edwards formulas provide parallelism at the level of the -formulas for curve operations. This means that instead of scanning -through the terms of the source operands and parallelizing *within* a -field element (as described above), we can arrange the computation in -product-scanning form and parallelize *across* field elements (as -described below). - -The parallel Edwards -formulas provide 4-way parallelism, so they can be implemented using -256-bit vectors using a single 64-bit lane for each element, or using -512-bit vectors using two 64-bit lanes. -The only available CPU supporting IFMA (the -i3-8121U) executes 512-bit IFMA instructions at half rate compared to -256-bit instructions, so for now there's no throughput advantage to -using 512-bit IFMA instructions, and this implementation uses 256-bit -vectors. - -To extend this to 512-bit vectors, it's only only necessary to achieve -2-way parallelism, and it's possible (with a small amount of overhead) -to create a hybrid strategy that operates entirely within 128-bit -lanes. This means that cross-lane operations can use the faster -`vpshufd` (1c latency) instead of a general shuffle instruction (3c -latency). - -# Choice of radix - -The inputs to IFMA instructions are 52 bits wide, so the radix \\(r\\) -used to represent a multiprecision integer must be \\( r \leq 52 \\). -The obvious choice is the "native" radix \\(r = 52\\). - -As described above, this choice -has the advantage that for \\(x_i, y_j \in [0,2^{52})\\), the product term -\\[ -\begin{aligned} -(x_i 2^{52 i}) (y_j 2^{52 j}) -&= -2^{52 (i+j)}( -\mathrm{lo}(x_i, y_j) + -\mathrm{hi}(x_i, y_j) 2^{52} -) -\\\\ -&= -\mathrm{lo}(x_i, y_j) 2^{52 (i+j)} + -\mathrm{hi}(x_i, y_j) 2^{52 (i+j+1)}, -\end{aligned} -\\] -so that the low and high halves of the product can be directly accumulated -onto the product limbs. -In contrast, when using a smaller radix \\(r = 52 - k\\), -the product term has the form -\\[ -\begin{aligned} -(x_i 2^{r i}) (y_j 2^{r j}) -&= -2^{r (i+j)}( -\mathrm{lo}(x_i, y_j) + -\mathrm{hi}(x_i, y_j) 2^{52} -) -\\\\ -&= -\mathrm{lo}(x_i, y_j) 2^{r (i+j)} + -( -\mathrm{hi}(x_i, y_j) 2^k -) -2^{r (i+j+1)}. -\end{aligned} -\\] -What's happening is that the product \\(x_i y_j\\) of size \\(2r\\) -bits is split not at \\(r\\) but at \\(52\\), so \\(k\\) product bits -are placed into the low half instead of the high half. This means -that the high half of the product cannot be directly accumulated onto -\\(z_{i+j+1}\\), but must first be multiplied by \\(2^k\\) (i.e., left -shifted by \\(k\\)). In addition, the low half of the product is -\\(52\\) bits large instead of \\(r\\) bits. - -## Handling offset product terms - -[Drucker and Gueron][2018_drucker_gueron] analyze the choice of radix -in the context of big-integer squaring, outlining three ways to handle -the offset product terms, before concluding that all of them are -suboptimal: - -1. Shift the results after accumulation; -2. Shift the input operands before multiplication; -3. Split the MAC operation, accumulating into a zeroed register, - shifting the result, and then adding. - -The first option is rejected because it could double-shift some -previously accumulated terms, the second doesn't work because the -inputs could become larger than \\(52\\) bits, and the third requires -additional instructions to handle the shifting and adding. - -Based on an analysis of total number of instructions, they suggest an -addition to the instruction set, which they call `FMSA` (fused -multiply-shift-add). This would shift the result according to an 8-bit -immediate value before accumulating it into the destination register. - -However, this change to the instruction set doesn't seem to be -necessary. Instead, the product terms can be grouped according to -their coefficients, accumulated together, then shifted once before -adding them to the final sum. This uses an extra register, shift, and -add, but only once per product term (accumulation target), not once -per source term (as in the Drucker-Gueron paper). - -Moreover, because IFMA instructions execute only on two ports -(presumably 0 and 1), while adds and shifts can execute on three ports -(0, 1, and 5), the adds and shifts can execute independently of the -IFMA operations, as long as there is not too much pressure on port 5. -This means that, although the total number of instructions increases, -the shifts and adds do not necessarily increase the execution time, as -long as throughput is limited by IFMA operations. - -Finally, because IFMA instructions have 4 cycle latency and 0.5/1 -cycle throughput (for 256/512 bit vectors), maximizing IFMA throughput -requires either 8 (for 256) or 4 (for 512) independent operations. So -accumulating groups of terms independently before adding them at the -end may be necessary anyways, in order to prevent long chains of -dependent instructions. - -## Advantages of a smaller radix - -Using a smaller radix has other advantages. Although radix \\(52\\) -is an unsaturated representation from the point of view of the -\\(64\\)-bit accumulators (because up to 4096 product terms can be -accumulated without carries), it's a saturated representation from the -point of view of the multiplier (since \\(52\\)-bit values are the -maximum input size). - -Because the inputs to a multiplication must have all of their limbs -bounded by \\(2^{52}\\), limbs in excess of \\(2^{52}\\) must be -reduced before they can be used as an input. The -[Gueron-Krasnov][2016_gueron_krasnov] paper suggests normalizing -values using a standard, sequential carry chain: for each limb, add -the carryin from reducing the previous limb, compute the carryout and -reduce the current limb, then move to the next limb. - -However, when using a smaller radix, such as \\(51\\), each limb can -store a carry bit and still be used as the input to a multiplication. -This means that the inputs do not need to be normalized, and instead -of using a sequential carry chain, we can compute all carryouts in -parallel, reduce all limbs in parallel, and then add the carryins in -parallel (possibly growing the limb values by one bit). - -Because the output of this partial reduction is an acceptable -multiplication input, we can "close the loop" using partial reductions -and never have to normalize to a canonical representation through the -entire computation, in contrast to the Gueron-Krasnov approach, which -converts back to a packed representation after every operation. (This -idea seems to trace back to at least as early as [this 1999 -paper][1999_walter]). - -Using \\(r = 51\\) is enough to keep a carry bit in each limb and -avoid normalizations. What about an even smaller radix? One reason -to choose a smaller radix would be to align the limb boundaries with -an inline reduction (for instance, choosing \\(r = 43\\) for the -Mersenne field \\(p = 2^{127} - 1\\)), but for \\(p = 2^{255 - 19}\\), -\\(r = 51 = 255/5\\) is the natural choice. - -# Multiplication - -The inputs to a multiplication are two field elements -\\[ -\begin{aligned} -x &= x_0 + x_1 2^{51} + x_2 2^{102} + x_3 2^{153} + x_4 2^{204} \\\\ -y &= y_0 + y_1 2^{51} + y_2 2^{102} + y_3 2^{153} + y_4 2^{204}, -\end{aligned} -\\] -with limbs in range \\([0,2^{52})\\). - -Writing the product terms as -\\[ -\begin{aligned} -z &= z_0 + z_1 2^{51} + z_2 2^{102} + z_3 2^{153} + z_4 2^{204} \\\\ - &+ z_5 2^{255} + z_6 2^{306} + z_7 2^{357} + z_8 2^{408} + z_9 2^{459}, -\end{aligned} -\\] -a schoolbook multiplication in product scanning form takes the form -\\[ -\begin{aligned} -z_0 &= x_0 y_0 \\\\ -z_1 &= x_1 y_0 + x_0 y_1 \\\\ -z_2 &= x_2 y_0 + x_1 y_1 + x_0 y_2 \\\\ -z_3 &= x_3 y_0 + x_2 y_1 + x_1 y_2 + x_0 y_3 \\\\ -z_4 &= x_4 y_0 + x_3 y_1 + x_2 y_2 + x_1 y_3 + x_0 y_4 \\\\ -z_5 &= x_4 y_1 + x_3 y_2 + x_2 y_3 + x_1 y_4 \\\\ -z_6 &= x_4 y_2 + x_3 y_3 + x_2 y_4 \\\\ -z_7 &= x_4 y_3 + x_3 y_4 \\\\ -z_8 &= x_4 y_4 \\\\ -z_9 &= 0 \\\\ -\end{aligned} -\\] -Each term \\(x_i y_j\\) can be written in terms of IFMA operations as -\\[ -x_i y_j = \mathrm{lo}(x_i,y_j) + 2\mathrm{hi}(x_i,y_j)2^{51}. -\\] -Substituting this equation into the schoolbook multiplication, then -moving terms to eliminate the \\(2^{51}\\) factors gives -\\[ -\begin{aligned} -z_0 &= \mathrm{lo}(x_0, y_0) \\\\ - &+ \qquad 0 \\\\ -z_1 &= \mathrm{lo}(x_1, y_0) + \mathrm{lo}(x_0, y_1) \\\\ - &+ \qquad 2( \mathrm{hi}(x_0, y_0) )\\\\ -z_2 &= \mathrm{lo}(x_2, y_0) + \mathrm{lo}(x_1, y_1) + \mathrm{lo}(x_0, y_2) \\\\ - &+ \qquad 2( \mathrm{hi}(x_1, y_0) + \mathrm{hi}(x_0, y_1) )\\\\ -z_3 &= \mathrm{lo}(x_3, y_0) + \mathrm{lo}(x_2, y_1) + \mathrm{lo}(x_1, y_2) + \mathrm{lo}(x_0, y_3) \\\\ - &+ \qquad 2( \mathrm{hi}(x_2, y_0) + \mathrm{hi}(x_1, y_1) + \mathrm{hi}(x_0, y_2) )\\\\ -z_4 &= \mathrm{lo}(x_4, y_0) + \mathrm{lo}(x_3, y_1) + \mathrm{lo}(x_2, y_2) + \mathrm{lo}(x_1, y_3) + \mathrm{lo}(x_0, y_4) \\\\ - &+ \qquad 2( \mathrm{hi}(x_3, y_0) + \mathrm{hi}(x_2, y_1) + \mathrm{hi}(x_1, y_2) + \mathrm{hi}(x_0, y_3) )\\\\ -z_5 &= \mathrm{lo}(x_4, y_1) + \mathrm{lo}(x_3, y_2) + \mathrm{lo}(x_2, y_3) + \mathrm{lo}(x_1, y_4) \\\\ - &+ \qquad 2( \mathrm{hi}(x_4, y_0) + \mathrm{hi}(x_3, y_1) + \mathrm{hi}(x_2, y_2) + \mathrm{hi}(x_1, y_3) + \mathrm{hi}(x_0, y_4) )\\\\ -z_6 &= \mathrm{lo}(x_4, y_2) + \mathrm{lo}(x_3, y_3) + \mathrm{lo}(x_2, y_4) \\\\ - &+ \qquad 2( \mathrm{hi}(x_4, y_1) + \mathrm{hi}(x_3, y_2) + \mathrm{hi}(x_2, y_3) + \mathrm{hi}(x_1, y_4) )\\\\ -z_7 &= \mathrm{lo}(x_4, y_3) + \mathrm{lo}(x_3, y_4) \\\\ - &+ \qquad 2( \mathrm{hi}(x_4, y_2) + \mathrm{hi}(x_3, y_3) + \mathrm{hi}(x_2, y_4) )\\\\ -z_8 &= \mathrm{lo}(x_4, y_4) \\\\ - &+ \qquad 2( \mathrm{hi}(x_4, y_3) + \mathrm{hi}(x_3, y_4) )\\\\ -z_9 &= 0 \\\\ - &+ \qquad 2( \mathrm{hi}(x_4, y_4) )\\\\ -\end{aligned} -\\] -As noted above, our strategy will be to multiply and accumulate the -terms with coefficient \\(2\\) separately from those with coefficient -\\(1\\), before combining them at the end. This can alternately be -thought of as accumulating product terms into a *doubly-redundant* -representation, with two limbs for each digit, before collapsing -the doubly-redundant representation by shifts and adds. - -This computation requires 25 `vpmadd52luq` and 25 `vpmadd52huq` -operations. For 256-bit vectors, IFMA operations execute on an -i3-8121U with latency 4 cycles, throughput 0.5 cycles, so executing 50 -instructions requires 25 cycles' worth of throughput. Accumulating -terms with coefficient \\(1\\) and \\(2\\) seperately means that the -longest dependency chain has length 5, so the critical path has length -20 cycles and the bottleneck is throughput. - -# Reduction modulo \\(p\\) - -The next question is how to handle the reduction modulo \\(p\\). -Because \\(p = 2^{255} - 19\\), \\(2^{255} = 19 \pmod p\\), so we can -alternately write -\\[ -\begin{aligned} -z &= z_0 + z_1 2^{51} + z_2 2^{102} + z_3 2^{153} + z_4 2^{204} \\\\ - &+ z_5 2^{255} + z_6 2^{306} + z_7 2^{357} + z_8 2^{408} + z_9 2^{459} -\end{aligned} -\\] -as -\\[ -\begin{aligned} -z &= (z_0 + 19z_5) + (z_1 + 19z_6) 2^{51} + (z_2 + 19z_7) 2^{102} + (z_3 + 19z_8) 2^{153} + (z_4 + 19z_9) 2^{204}. -\end{aligned} -\\] -When using a \\(64 \times 64 \rightarrow 128\\)-bit multiplier, this -can be handled (as in [Ed25519][ed25519_paper]) by premultiplying -source terms by \\(19\\). Since \\(\lg(19) < 4.25\\), this increases -their size by less than \\(4.25\\) bits, and the rest of the -multiplication can be shown to work out. - -Here, we have at most \\(1\\) bit of headroom. In order to allow -premultiplication, we would need to use radix \\(2^{47}\\), which -would require six limbs instead of five. Instead, we compute the high -terms \\(z_5, \ldots, z_9\\), each using two chains of IFMA -operations, then multiply by \\(19\\) and combine with the lower terms -\\(z_0, \ldots, z_4\\). There are two ways to perform the -multiplication by \\(19\\): using more IFMA operations, or using the -`vpmullq` instruction, which computes the low \\(64\\) bits of a \\(64 -\times 64\\)-bit product. However, `vpmullq` has 15c/1.5c -latency/throughput, in contrast to the 4c/0.5c latency/throughput of -IFMA operations, so it seems like a worse choice. - -The high terms \\(z_5, \ldots, z_9\\) are sums of \\(52\\)-bit terms, -so they are larger than \\(52\\) bits. Write these terms in radix \\(52\\) as -\\[ -z_{5+i} = z_{5+i}' + z_{5+i}'' 2^{52}, \qquad z_{5+i}' < 2^{52}. -\\] -Then the contribution of \\(z_{5+i}\\), taken modulo \\(p\\), is -\\[ -\begin{aligned} -z_{5+i} 2^{255} 2^{51 i} -&= -19 (z_{5+i}' + z_{5+i}'' 2^{52}) 2^{51 i} -\\\\ -&= -19 z_{5+i}' 2^{51 i} + 2 \cdot 19 z_{5+i}'' 2^{51 (i+1)} -\\\\ -\end{aligned} -\\] -The products \\(19 z_{5+i}', 19 z_{5+i}''\\) can be written in terms of IFMA operations as -\\[ -\begin{aligned} -19 z_{5+i}' &= \mathrm{lo}(19, z_{5+i}') + 2 \mathrm{hi}(19, z_{5+i}') 2^{51}, \\\\ -19 z_{5+i}'' &= \mathrm{lo}(19, z_{5+i}'') + 2 \mathrm{hi}(19, z_{5+i}'') 2^{51}. \\\\ -\end{aligned} -\\] -Because \\(z_{5+i} < 2^{64}\\), \\(z_{5+i}'' < 2^{12} \\), so \\(19 -z_{5+i}'' < 2^{17} < 2^{52} \\) and \\(\mathrm{hi}(19, z_{5+i}'') = 0\\). -Because IFMA operations ignore the high bits of their source -operands, we do not need to compute \\(z\_{5+i}'\\) explicitly: -the high bits will be ignored. -Combining these observations, we can write -\\[ -\begin{aligned} -z_{5+i} 2^{255} 2^{51 i} -&= -19 z_{5+i}' 2^{51 i} + 2 \cdot 19 z_{5+i}'' 2^{51 (i+1)} -\\\\ -&= -\mathrm{lo}(19, z_{5+i}) 2^{51 i} -\+ 2 \mathrm{hi}(19, z_{5+i}) 2^{51 (i+1)} -\+ 2 \mathrm{lo}(19, z_{5+i}/2^{52}) 2^{51 (i+1)}. -\end{aligned} -\\] - -For \\(i = 0,1,2,3\\), this allows reducing \\(z_{5+i}\\) onto -\\(z_{i}, z_{i+1}\\), and if the low terms are computed using a -doubly-redundant representation, no additional shifts are needed to -handle the \\(2\\) coefficients. For \\(i = 4\\), there's a -complication: the contribution becomes -\\[ -\begin{aligned} -z_{9} 2^{255} 2^{204} -&= -\mathrm{lo}(19, z_{9}) 2^{204} -\+ 2 \mathrm{hi}(19, z_{9}) 2^{255} -\+ 2 \mathrm{lo}(19, z_{9}/2^{52}) 2^{255} -\\\\ -&= -\mathrm{lo}(19, z_{9}) 2^{204} -\+ 2 \mathrm{hi}(19, z_{9}) 19 -\+ 2 \mathrm{lo}(19, z_{9}/2^{52}) 19 -\\\\ -&= -\mathrm{lo}(19, z_{9}) 2^{204} -\+ 2 -\mathrm{lo}(19, \mathrm{hi}(19, z_{9}) + \mathrm{lo}(19, z_{9}/2^{52})). -\\\\ -\end{aligned} -\\] - -It would be possible to cut the number of multiplications from 3 to 2 -by carrying the high part of each \\(z_i\\) onto \\(z_{i+1}\\). This -would eliminate 5 multiplications, clearing 2.5 cycles of port -pressure, at the cost of 5 additions, adding 1.66 cycles of port -pressure. But doing this would create a dependency between terms -(e.g., \\(z_{5}\\) must be computed before the reduction of -\\(z_{6}\\) can begin), whereas with the approach above, all -contributions to all terms are computed independently, to maximize ILP -and flexibility for the processor to schedule instructions. - -This strategy performs 16 IFMA operations, adding two IFMA operations -to each of the \\(2\\)-coefficient terms and one to each of the -\\(1\\)-coefficient terms. Considering the multiplication and -reduction together, we use 66 IFMA operations, requiring 33 cycles' -throughput, while the longest chain of IFMA operations is in the -reduction of \\(z_5\\) onto \\(z_1\\), of length 7 (so 28 cycles, plus -2 cycles to combine the two parts of \\(z_5\\), and the bottleneck is -again throughput. - -Once this is done, we have computed the product terms -\\[ -z = z_0 + z_1 2^{51} + z_2 2^{102} + z_3 2^{153} + z_4 2^{204}, -\\] -without reducing the \\(z_i\\) to fit in \\(52\\) bits. Because the -overall flow of operations alternates multiplications and additions or -subtractions, we would have to perform a reduction after an addition -but before the next multiplication anyways, so there's no benefit to -fully reducing the limbs at the end of a multiplication. Instead, we -leave them unreduced, and track the reduction state using the type -system to ensure that unreduced limbs are not accidentally used as an -input to a multiplication. - -# Squaring - -Squaring operates similarly to multiplication, but with the -possibility to combine identical terms. -As before, we write the input as -\\[ -\begin{aligned} -x &= x_0 + x_1 2^{51} + x_2 2^{102} + x_3 2^{153} + x_4 2^{204} -\end{aligned} -\\] -with limbs in range \\([0,2^{52})\\). -Writing the product terms as -\\[ -\begin{aligned} -z &= z_0 + z_1 2^{51} + z_2 2^{102} + z_3 2^{153} + z_4 2^{204} \\\\ - &+ z_5 2^{255} + z_6 2^{306} + z_7 2^{357} + z_8 2^{408} + z_9 2^{459}, -\end{aligned} -\\] -a schoolbook squaring in product scanning form takes the form -\\[ -\begin{aligned} -z_0 &= x_0 x_0 \\\\ -z_1 &= 2 x_1 x_0 \\\\ -z_2 &= 2 x_2 x_0 + x_1 x_1 \\\\ -z_3 &= 2 x_3 x_0 + 2 x_2 x_1 \\\\ -z_4 &= 2 x_4 x_0 + 2 x_3 x_1 + x_2 x_2 \\\\ -z_5 &= 2 x_4 x_1 + 2 x_3 x_2 \\\\ -z_6 &= 2 x_4 x_2 + x_3 x_3 \\\\ -z_7 &= 2 x_4 x_3 \\\\ -z_8 &= x_4 x_4 \\\\ -z_9 &= 0 \\\\ -\end{aligned} -\\] -As before, we write \\(x_i x_j\\) as -\\[ -x_i x_j = \mathrm{lo}(x_i,x_j) + 2\mathrm{hi}(x_i,x_j)2^{51}, -\\] -and substitute to obtain -\\[ -\begin{aligned} -z_0 &= \mathrm{lo}(x_0, x_0) + 0 \\\\ -z_1 &= 2 \mathrm{lo}(x_1, x_0) + 2 \mathrm{hi}(x_0, x_0) \\\\ -z_2 &= 2 \mathrm{lo}(x_2, x_0) + \mathrm{lo}(x_1, x_1) + 4 \mathrm{hi}(x_1, x_0) \\\\ -z_3 &= 2 \mathrm{lo}(x_3, x_0) + 2 \mathrm{lo}(x_2, x_1) + 4 \mathrm{hi}(x_2, x_0) + 2 \mathrm{hi}(x_1, x_1) \\\\ -z_4 &= 2 \mathrm{lo}(x_4, x_0) + 2 \mathrm{lo}(x_3, x_1) + \mathrm{lo}(x_2, x_2) + 4 \mathrm{hi}(x_3, x_0) + 4 \mathrm{hi}(x_2, x_1) \\\\ -z_5 &= 2 \mathrm{lo}(x_4, x_1) + 2 \mathrm{lo}(x_3, x_2) + 4 \mathrm{hi}(x_4, x_0) + 4 \mathrm{hi}(x_3, x_1) + 2 \mathrm{hi}(x_2, x_2) \\\\ -z_6 &= 2 \mathrm{lo}(x_4, x_2) + \mathrm{lo}(x_3, x_3) + 4 \mathrm{hi}(x_4, x_1) + 4 \mathrm{hi}(x_3, x_2) \\\\ -z_7 &= 2 \mathrm{lo}(x_4, x_3) + 4 \mathrm{hi}(x_4, x_2) + 2 \mathrm{hi}(x_3, x_3) \\\\ -z_8 &= \mathrm{lo}(x_4, x_4) + 4 \mathrm{hi}(x_4, x_3) \\\\ -z_9 &= 0 + 2 \mathrm{hi}(x_4, x_4) \\\\ -\end{aligned} -\\] -To implement these, we group terms by their coefficient, computing -those with coefficient \\(2\\) on set of IFMA chains, and on another -set of chains, we begin with coefficient-\\(4\\) terms, then shift -left before continuing with the coefficient-\\(1\\) terms. -The reduction strategy is the same as for multiplication. - -# Future improvements - -LLVM won't use blend operations on [256-bit vectors yet][llvm_blend], -so there's a bunch of blend instructions that could be omitted. - -Although the multiplications and squarings are much faster, there's no -speedup to the additions and subtractions, so there are diminishing -returns. In fact, the complications in the doubling formulas mean -that doubling is actually slower than readdition. This also suggests -that moving to 512-bit vectors won't be much help for a strategy aimed -at parallelism within a group operation, so to extract performance -gains from 512-bit vectors it will probably be necessary to create a -parallel-friendly multiscalar multiplication algorithm. This could -also help with reducing shuffle pressure. - -The squaring implementation could probably be optimized, but without -`perf` support on Cannonlake it's difficult to make actual -measurements. - -Another improvement would be to implement vectorized square root -computations, which would allow creating an iterator adaptor for point -decompression that bunched decompression operations and executed them -in parallel. This would accelerate batch verification. - -[2016_gueron_krasnov]: https://ieeexplore.ieee.org/document/7563269 -[2018_drucker_gueron]: https://eprint.iacr.org/2018/335 -[1999_walter]: https://pdfs.semanticscholar.org/0e6a/3e8f30b63b556679f5dff2cbfdfe9523f4fa.pdf -[ed25519_paper]: https://ed25519.cr.yp.to/ed25519-20110926.pdf -[llvm_blend]: https://bugs.llvm.org/show_bug.cgi?id=38343 diff --git a/net/gurk-rs/files/vendor/curve25519-dalek-2.0.0/docs/parallel-formulas.md b/net/gurk-rs/files/vendor/curve25519-dalek-2.0.0/docs/parallel-formulas.md deleted file mode 100644 index 22f59cd..0000000 --- a/net/gurk-rs/files/vendor/curve25519-dalek-2.0.0/docs/parallel-formulas.md +++ /dev/null @@ -1,333 +0,0 @@ -Vectorized implementations of field and point operations, using a -modification of the 4-way parallel formulas of Hisil, Wong, Carter, -and Dawson. - -These notes explain the parallel formulas and our strategy for using -them with SIMD operations. There are two backend implementations: one -using AVX2, and the other using AVX512-IFMA. - -# Overview - -The 2008 paper [_Twisted Edwards Curves Revisited_][hwcd08] by Hisil, -Wong, Carter, and Dawson (HWCD) introduced the “extended coordinates” -and mixed-model representations which are used by most Edwards curve -implementations. - -However, they also describe 4-way parallel formulas for point addition -and doubling: a unified addition algorithm taking an effective -\\(2\mathbf M + 1\mathbf D\\), a doubling algorithm taking an -effective \\(1\mathbf M + 1\mathbf S\\), and a dedicated (i.e., for -distinct points) addition algorithm taking an effective \\(2 \mathbf M -\\). They compare these formulas with a 2-way parallel variant of the -Montgomery ladder. - -Unlike their serial formulas, which are used widely, their parallel -formulas do not seem to have been implemented in software before. The -2-way parallel Montgomery ladder was used in 2015 by Tung Chou's -`sandy2x` implementation. Curiously, however, although the [`sandy2x` -paper][sandy2x] also implements Edwards arithmetic, and cites HWCD08, -it doesn't mention their parallel Edwards formulas. -A 2015 paper by Hernández and López describes an AVX2 implementation -of X25519. Neither the paper nor the code are publicly available, but -it apparently gives only a [slight speedup][avx2trac], suggesting that -it uses a 4-way parallel Montgomery ladder rather than parallel -Edwards formulas. - -The reason may be that HWCD08 describe their formulas as operating on -four independent processors, which would make a software -implementation impractical: all of the operations are too low-latency -to effectively synchronize. But a closer inspection reveals that the -(more expensive) multiplication and squaring steps are uniform, while -the instruction divergence occurs in the (much cheaper) addition and -subtraction steps. This means that a SIMD implementation can perform -the expensive steps uniformly, and handle divergence in the -inexpensive steps using masking. - -These notes describe modifications to the original parallel formulas -to allow a SIMD implementation, and this module contains -implementations of the modified formulas targeting either AVX2 or -AVX512-IFMA. - -# Parallel formulas in HWCD'08 - -The doubling formula is presented in the HWCD paper as follows: - -| Cost | Processor 1 | Processor 2 | Processor 3 | Processor 4 | -|------------------|--------------------------------|--------------------------------|--------------------------------|--------------------------------| -| | idle | idle | idle | \\( R\_1 \gets X\_1 + Y\_1 \\) | -| \\(1\mathbf S\\) | \\( R\_2 \gets X\_1\^2 \\) | \\( R\_3 \gets Y\_1\^2 \\) | \\( R\_4 \gets Z\_1\^2 \\) | \\( R\_5 \gets R\_1\^2 \\) | -| | \\( R\_6 \gets R\_2 + R\_3 \\) | \\( R\_7 \gets R\_2 - R\_3 \\) | \\( R\_4 \gets 2 R\_4 \\) | idle | -| | idle | \\( R\_1 \gets R\_4 + R\_7 \\) | idle | \\( R\_2 \gets R\_6 - R\_5 \\) | -| \\(1\mathbf M\\) | \\( X\_3 \gets R\_1 R\_2 \\) | \\( Y\_3 \gets R\_6 R\_7 \\) | \\( T\_3 \gets R\_2 R\_6 \\) | \\( Z\_3 \gets R\_1 R\_7 \\) | - -and the unified addition algorithm is presented as follows: - -| Cost | Processor 1 | Processor 2 | Processor 3 | Processor 4 | -|------------------|--------------------------------|--------------------------------|--------------------------------|--------------------------------| -| | \\( R\_1 \gets Y\_1 - X\_1 \\) | \\( R\_2 \gets Y\_2 - X\_2 \\) | \\( R\_3 \gets Y\_1 + X\_1 \\) | \\( R\_4 \gets Y\_2 + X\_2 \\) | -| \\(1\mathbf M\\) | \\( R\_5 \gets R\_1 R\_2 \\) | \\( R\_6 \gets R\_3 R\_4 \\) | \\( R\_7 \gets T\_1 T\_2 \\) | \\( R\_8 \gets Z\_1 Z\_2 \\) | -| \\(1\mathbf D\\) | idle | idle | \\( R\_7 \gets k R\_7 \\) | \\( R\_8 \gets 2 R\_8 \\) | -| | \\( R\_1 \gets R\_6 - R\_5 \\) | \\( R\_2 \gets R\_8 - R\_7 \\) | \\( R\_3 \gets R\_8 + R\_7 \\) | \\( R\_4 \gets R\_6 + R\_5 \\) | -| \\(1\mathbf M\\) | \\( X\_3 \gets R\_1 R\_2 \\) | \\( Y\_3 \gets R\_3 R\_4 \\) | \\( T\_3 \gets R\_1 R\_4 \\) | \\( Z\_3 \gets R\_2 R\_3 \\) | - -Here \\(\mathbf M\\) and \\(\mathbf S\\) represent the cost of -multiplication and squaring of generic field elements, \\(\mathbf D\\) -represents the cost of multiplication by a curve constant (in this -case \\( k = 2d \\)). - -Notice that the \\(1\mathbf M\\) and \\(1\mathbf S\\) steps are -uniform. The non-uniform steps are all inexpensive additions or -subtractions, with the exception of the multiplication by the curve -constant \\(k = 2d\\): -$$ -R\_7 \gets 2 d R\_7. -$$ - -HWCD suggest parallelising this step by breaking \\(k = 2d\\) into four -parts as \\(k = k_0 + 2\^n k_1 + 2\^{2n} k_2 + 2\^{3n} k_3 \\) and -computing \\(k_i R_7 \\) in parallel. This is quite awkward, but if -the curve constant is a ratio \\( d = d\_1/d\_2 \\), then projective -coordinates allow us to instead compute -$$ -(R\_5, R\_6, R\_7, R\_8) \gets (d\_2 R\_5, d\_2 R\_6, 2d\_1 R\_7, d\_2 R\_8). -$$ -This can be performed as a uniform multiplication by a vector of -constants, and if \\(d\_1, d\_2\\) are small, it is relatively -inexpensive. (This trick was suggested by Mike Hamburg). -In the Curve25519 case, we have -$$ -d = \frac{d\_1}{d\_2} = \frac{-121665}{121666}; -$$ -Since \\(2 \cdot 121666 < 2\^{18}\\), all the constants above fit (up -to sign) in 32 bits, so this can be done in parallel as four -multiplications by small constants \\( (121666, 121666, 2\cdot 121665, -2\cdot 121666) \\), followed by a negation to compute \\( - 2\cdot 121665\\). - -# Modified parallel formulas - -Using the modifications sketched above, we can write SIMD-friendly -versions of the parallel formulas as follows. To avoid confusion with -the original formulas, temporary variables are named \\(S\\) instead -of \\(R\\) and are in static single-assignment form. - -## Addition - -To add points -\\(P_1 = (X_1 : Y_1 : Z_1 : T_1) \\) -and -\\(P_2 = (X_2 : Y_2 : Z_2 : T_2 ) \\), -we compute -$$ -\begin{aligned} -(S\_0 &&,&& S\_1 &&,&& S\_2 &&,&& S\_3 ) -&\gets -(Y\_1 - X\_1&&,&& Y\_1 + X\_1&&,&& Y\_2 - X\_2&&,&& Y\_2 + X\_2) -\\\\ -(S\_4 &&,&& S\_5 &&,&& S\_6 &&,&& S\_7 ) -&\gets -(S\_0 \cdot S\_2&&,&& S\_1 \cdot S\_3&&,&& Z\_1 \cdot Z\_2&&,&& T\_1 \cdot T\_2) -\\\\ -(S\_8 &&,&& S\_9 &&,&& S\_{10} &&,&& S\_{11} ) -&\gets -(d\_2 \cdot S\_4 &&,&& d\_2 \cdot S\_5 &&,&& 2 d\_2 \cdot S\_6 &&,&& 2 d\_1 \cdot S\_7 ) -\\\\ -(S\_{12} &&,&& S\_{13} &&,&& S\_{14} &&,&& S\_{15}) -&\gets -(S\_9 - S\_8&&,&& S\_9 + S\_8&&,&& S\_{10} - S\_{11}&&,&& S\_{10} + S\_{11}) -\\\\ -(X\_3&&,&& Y\_3&&,&& Z\_3&&,&& T\_3) -&\gets -(S\_{12} \cdot S\_{14}&&,&& S\_{15} \cdot S\_{13}&&,&& S\_{15} \cdot S\_{14}&&,&& S\_{12} \cdot S\_{13}) -\end{aligned} -$$ -to obtain \\( P\_3 = (X\_3 : Y\_3 : Z\_3 : T\_3) = P\_1 + P\_2 \\). -This costs \\( 2\mathbf M + 1 \mathbf D\\). - -## Readdition - -If the point \\( P_2 = (X\_2 : Y\_2 : Z\_2 : T\_2) \\) is fixed, we -can cache the multiplication of the curve constants by computing -$$ -\begin{aligned} -(S\_2' &&,&& S\_3' &&,&& Z\_2' &&,&& T\_2' ) -&\gets -(d\_2 \cdot (Y\_2 - X\_2)&&,&& d\_2 \cdot (Y\_1 + X\_1)&&,&& 2d\_2 \cdot Z\_2 &&,&& 2d\_1 \cdot T\_2). -\end{aligned} -$$ -This costs \\( 1\mathbf D\\); with \\( (S\_2', S\_3', Z\_2', T\_2')\\) -in hand, the addition formulas above become -$$ -\begin{aligned} -(S\_0 &&,&& S\_1 &&,&& Z\_1 &&,&& T\_1 ) -&\gets -(Y\_1 - X\_1&&,&& Y\_1 + X\_1&&,&& Z\_1 &&,&& T\_1) -\\\\ -(S\_8 &&,&& S\_9 &&,&& S\_{10} &&,&& S\_{11} ) -&\gets -(S\_0 \cdot S\_2' &&,&& S\_1 \cdot S\_3'&&,&& Z\_1 \cdot Z\_2' &&,&& T\_1 \cdot T\_2') -\\\\ -(S\_{12} &&,&& S\_{13} &&,&& S\_{14} &&,&& S\_{15}) -&\gets -(S\_9 - S\_8&&,&& S\_9 + S\_8&&,&& S\_{10} - S\_{11}&&,&& S\_{10} + S\_{11}) -\\\\ -(X\_3&&,&& Y\_3&&,&& Z\_3&&,&& T\_3) -&\gets -(S\_{12} \cdot S\_{14}&&,&& S\_{15} \cdot S\_{13}&&,&& S\_{15} \cdot S\_{14}&&,&& S\_{12} \cdot S\_{13}) -\end{aligned} -$$ -which costs only \\( 2\mathbf M \\). This precomputation is -essentially similar to the precomputation that HWCD suggest for their -serial formulas. Because the cost of precomputation and then -readdition is the same as addition, it's sufficient to only -implement caching and readdition. - -## Doubling - -The non-uniform portions of the (re)addition formulas have a fairly -regular structure. Unfortunately, this is not the case for the -doubling formulas, which are much less nice. - -To double a point \\( P = (X\_1 : Y\_1 : Z\_1 : T\_1) \\), we compute -$$ -\begin{aligned} -(X\_1 &&,&& Y\_1 &&,&& Z\_1 &&,&& S\_0) -&\gets -(X\_1 &&,&& Y\_1 &&,&& Z\_1 &&,&& X\_1 + Y\_1) -\\\\ -(S\_1 &&,&& S\_2 &&,&& S\_3 &&,&& S\_4 ) -&\gets -(X\_1\^2 &&,&& Y\_1\^2&&,&& Z\_1\^2 &&,&& S\_0\^2) -\\\\ -(S\_5 &&,&& S\_6 &&,&& S\_8 &&,&& S\_9 ) -&\gets -(S\_1 + S\_2 &&,&& S\_1 - S\_2 &&,&& S\_1 + 2S\_3 - S\_2 &&,&& S\_1 + S\_2 - S\_4) -\\\\ -(X\_3 &&,&& Y\_3 &&,&& Z\_3 &&,&& T\_3 ) -&\gets -(S\_8 \cdot S\_9 &&,&& S\_5 \cdot S\_6 &&,&& S\_8 \cdot S\_6 &&,&& S\_5 \cdot S\_9) -\end{aligned} -$$ -to obtain \\( P\_3 = (X\_3 : Y\_3 : Z\_3 : T\_3) = [2]P\_1 \\). - -The intermediate step between the squaring and multiplication requires -a long chain of additions. For the IFMA-based implementation, this is not a problem; for the AVX2-based implementation, it is, but with some care and finesse, it's possible to arrange the computation without requiring an intermediate reduction. - -# Implementation - -These formulas aren't specific to a particular representation of field -element vectors, whose optimum choice is determined by the details of -the instruction set. However, it's not possible to perfectly separate -the implementation of the field element vectors from the -implementation of the point operations. Instead, the [`avx2`] and -[`ifma`] backends provide `ExtendedPoint` and `CachedPoint` types, and -the [`scalar_mul`] code uses one of the backend types by a type alias. - -# Comparison to non-vectorized formulas - -In theory, the parallel Edwards formulas seem to allow a \\(4\\)-way -speedup from parallelism. However, an actual vectorized -implementation has several slowdowns that cut into this speedup. - -First, the parallel formulas can only use the available vector -multiplier. For AVX2, this is a \\( 32 \times 32 \rightarrow 64 -\\)-bit integer multiplier, so the speedup from vectorization must -overcome the disadvantage of losing the \\( 64 \times 64 \rightarrow -128\\)-bit (serial) integer multiplier. The effect of this slowdown -is microarchitecture-dependent, since it requires accounting for the -total number of multiplications and additions and their relative -costs. IFMA allows using a \\( 52 \times 52 \rightarrow 104 \\)-bit -multiplier, but the high and low halves need to be computed -separately, and the reduction requires extra work because it's not -possible to pre-multiply by \\(19\\). - -Second, the parallel doubling formulas incur both a theoretical and -practical slowdown. The parallel formulas described above work on the -\\( \mathbb P\^3 \\) “extended” coordinates. The \\( \mathbb P\^2 \\) -model introduced earlier by [Bernstein, Birkner, Joye, Lange, and -Peters][bbjlp08] allows slightly faster doublings, so HWCD suggest -mixing coordinate systems while performing scalar multiplication -(attributing the idea to [a 1998 paper][cmo98] by Cohen, Miyagi, and -Ono). The \\( T \\) coordinate is not required for doublings, so when -doublings are followed by doublings, its computation can be skipped. -More details on this approach and the different coordinate systems can -be found in the [`curve_models` module documentation][curve_models]. - -Unfortunately, this optimization is not compatible with the parallel -formulas, which cannot save time by skipping a single variable, so the -parallel doubling formulas do slightly more work when counting the -total number of field multiplications and squarings. - -In addition, the parallel doubling formulas have a less regular -pattern of additions and subtractions than the parallel addition -formulas, so the vectorization overhead is proportionately greater. -Both the parallel addition and parallel doubling formulas also require -some shuffling to rearrange data within the vectors, which places more -pressure on the shuffle unit than is desirable. - -This means that the speedup from using a vectorized implementation of -parallel Edwards formulas is likely to be greatest in applications -that do fewer doublings and more additions (like a large multiscalar -multiplication) rather than applications that do fewer additions and -more doublings (like a double-base scalar multiplication). - -Third, Amdahl's law says that the speedup is limited to the portion -which can be parallelized. Normally, the field multiplications -dominate the cost of point operations, but with the IFMA backend, the -multiplications are so fast that the non-parallel additions end up as -a significant portion of the total time. - -Fourth, current Intel CPUs perform thermal throttling when using wide -vector instructions. A detailed description can be found in §15.26 of -[the Intel Optimization Manual][intel], but using wide vector -instructions prevents the core from operating at higher frequencies. -The core can return to the higher-frequency state after 2 -milliseconds, but this timer is reset every time high-power -instructions are used. - -Any speedup from vectorization therefore has to be weighed against a -slowdown for the next few million instructions. For a mixed workload, -where point operations are interspersed with other tasks, this can -reduce overall performance. This implementation is therefore probably -not suitable for basic applications, like signatures, but is -worthwhile for complex applications, like zero-knowledge proofs, which -do sustained work. - -# Future work - -There are several directions for future improvement: - -* Using the vectorized field arithmetic code to parallelize across - point operations rather than within a single point operation. This - is less flexible, but would give a speedup both from allowing use of - the faster mixed-model arithmetic and from reducing shuffle - pressure. One approach in this direction would be to implement - batched scalar-point operations using vectors of points (AoSoA - layout). This less generally useful but would give a speedup for - Bulletproofs. - -* Extending the IFMA implementation to use the full width of AVX512, - either handling the extra parallelism internally to a single point - operation (by using a 2-way parallel implementation of field - arithmetic instead of a wordsliced one), or externally, - parallelizing across point operations. Internal parallelism would - be preferable but might require too much shuffle pressure. For now, - the only available CPU which runs IFMA operations executes them at - 256-bits wide anyways, so this isn't yet important. - -* Generalizing the implementation to NEON instructions. The current - point arithmetic code is written in terms of field element vectors, - which are in turn implemented using platform SIMD vectors. It - should be possible to write an alternate implementation of the - `FieldElement2625x4` using NEON without changing the point - arithmetic. NEON has 128-bit vectors rather than 256-bit vectors, - but this may still be worthwhile compared to a serial - implementation. - - -[sandy2x]: https://eprint.iacr.org/2015/943.pdf -[avx2trac]: https://trac.torproject.org/projects/tor/ticket/8897#comment:28 -[hwcd08]: https://www.iacr.org/archive/asiacrypt2008/53500329/53500329.pdf -[curve_models]: https://doc-internal.dalek.rs/curve25519_dalek/curve_models/index.html -[bbjlp08]: https://eprint.iacr.org/2008/013 -[cmo98]: https://link.springer.com/content/pdf/10.1007%2F3-540-49649-1_6.pdf -[intel]: https://software.intel.com/sites/default/files/managed/9e/bc/64-ia-32-architectures-optimization-manual.pdf diff --git a/net/gurk-rs/files/vendor/curve25519-dalek-2.0.0/src/backend/mod.rs b/net/gurk-rs/files/vendor/curve25519-dalek-2.0.0/src/backend/mod.rs deleted file mode 100644 index f761eaa..0000000 --- a/net/gurk-rs/files/vendor/curve25519-dalek-2.0.0/src/backend/mod.rs +++ /dev/null @@ -1,62 +0,0 @@ -// -*- mode: rust; -*- -// -// This file is part of curve25519-dalek. -// Copyright (c) 2016-2019 Isis Lovecruft, Henry de Valence -// See LICENSE for licensing information. -// -// Authors: -// - Isis Agora Lovecruft -// - Henry de Valence - -//! Pluggable implementations for different architectures. -//! -//! The backend code is split into two parts: a serial backend, -//! and a vector backend. -//! -//! The [`serial`] backend contains 32- and 64-bit implementations of -//! field arithmetic and scalar arithmetic, as well as implementations -//! of point operations using the mixed-model strategy (passing -//! between different curve models depending on the operation). -//! -//! The [`vector`] backend contains implementations of vectorized -//! field arithmetic, used to implement point operations using a novel -//! implementation strategy derived from parallel formulas of Hisil, -//! Wong, Carter, and Dawson. -//! -//! Because the two strategies give rise to different curve models, -//! it's not possible to reuse exactly the same scalar multiplication -//! code (or to write it generically), so both serial and vector -//! backends contain matching implementations of scalar multiplication -//! algorithms. These are intended to be selected by a `#[cfg]`-based -//! type alias. -//! -//! The [`vector`] backend is selected by the `simd_backend` cargo -//! feature; it uses the [`serial`] backend for non-vectorized operations. - -#[cfg(not(any( - feature = "u32_backend", - feature = "u64_backend", - feature = "simd_backend", -)))] -compile_error!( - "no curve25519-dalek backend cargo feature enabled! \ - please enable one of: u32_backend, u64_backend, simd_backend" -); - -pub mod serial; - -#[cfg(any( - all( - feature = "simd_backend", - any(target_feature = "avx2", target_feature = "avx512ifma") - ), - all(feature = "nightly", rustdoc) -))] -#[cfg_attr( - feature = "nightly", - doc(cfg(any(all( - feature = "simd_backend", - any(target_feature = "avx2", target_feature = "avx512ifma") - )))) -)] -pub mod vector; diff --git a/net/gurk-rs/files/vendor/curve25519-dalek-2.0.0/src/backend/serial/curve_models/mod.rs b/net/gurk-rs/files/vendor/curve25519-dalek-2.0.0/src/backend/serial/curve_models/mod.rs deleted file mode 100644 index 5d5850f..0000000 --- a/net/gurk-rs/files/vendor/curve25519-dalek-2.0.0/src/backend/serial/curve_models/mod.rs +++ /dev/null @@ -1,550 +0,0 @@ -// -*- mode: rust; -*- -// -// This file is part of curve25519-dalek. -// Copyright (c) 2016-2019 Isis Lovecruft, Henry de Valence -// See LICENSE for licensing information. -// -// Authors: -// - Isis Agora Lovecruft -// - Henry de Valence - -//! Internal curve representations which are not part of the public API. -//! -//! # Curve representations -//! -//! Internally, we use several different models for the curve. Here -//! is a sketch of the relationship between the models, following [a -//! post][smith-moderncrypto] -//! by Ben Smith on the `moderncrypto` mailing list. This is also briefly -//! discussed in section 2.5 of [_Montgomery curves and their -//! arithmetic_][costello-smith-2017] by Costello and Smith. -//! -//! Begin with the affine equation for the curve, -//! $$ -//! -x\^2 + y\^2 = 1 + dx\^2y\^2. -//! $$ -//! Next, pass to the projective closure \\(\mathbb P\^1 \times \mathbb -//! P\^1 \\) by setting \\(x=X/Z\\), \\(y=Y/T.\\) Clearing denominators -//! gives the model -//! $$ -//! -X\^2T\^2 + Y\^2Z\^2 = Z\^2T\^2 + dX\^2Y\^2. -//! $$ -//! In `curve25519-dalek`, this is represented as the `CompletedPoint` -//! struct. -//! To map from \\(\mathbb P\^1 \times \mathbb P\^1 \\), a product of -//! two lines, to \\(\mathbb P\^3\\), we use the [Segre -//! embedding](https://en.wikipedia.org/wiki/Segre_embedding) -//! $$ -//! \sigma : ((X:Z),(Y:T)) \mapsto (XY:XT:ZY:ZT). -//! $$ -//! Using coordinates \\( (W_0:W_1:W_2:W_3) \\) for \\(\mathbb P\^3\\), -//! the image \\(\sigma (\mathbb P\^1 \times \mathbb P\^1) \\) is the -//! surface defined by \\( W_0 W_3 = W_1 W_2 \\), and under \\( -//! \sigma\\), the equation above becomes -//! $$ -//! -W\_1\^2 + W\_2\^2 = W\_3\^2 + dW\_0\^2, -//! $$ -//! so that the curve is given by the pair of equations -//! $$ -//! \begin{aligned} -//! -W\_1\^2 + W\_2\^2 &= W\_3\^2 + dW\_0\^2, \\\\ W_0 W_3 &= W_1 W_2. -//! \end{aligned} -//! $$ -//! Up to variable naming, this is exactly the "extended" curve model -//! introduced in [_Twisted Edwards Curves -//! Revisited_][hisil-wong-carter-dawson-2008] by Hisil, Wong, Carter, -//! and Dawson. In `curve25519-dalek`, it is represented as the -//! `EdwardsPoint` struct. We can map from \\(\mathbb P\^3 \\) to -//! \\(\mathbb P\^2 \\) by sending \\( (W\_0:W\_1:W\_2:W\_3) \\) to \\( -//! (W\_1:W\_2:W\_3) \\). Notice that -//! $$ -//! \frac {W\_1} {W\_3} = \frac {XT} {ZT} = \frac X Z = x, -//! $$ -//! and -//! $$ -//! \frac {W\_2} {W\_3} = \frac {YZ} {ZT} = \frac Y T = y, -//! $$ -//! so this is the same as if we had started with the affine model -//! and passed to \\( \mathbb P\^2 \\) by setting \\( x = W\_1 / W\_3 -//! \\), \\(y = W\_2 / W\_3 \\). -//! Up to variable naming, this is the projective representation -//! introduced in in [_Twisted Edwards -//! Curves_][bernstein-birkner-joye-lange-peters-2008] by Bernstein, -//! Birkner, Joye, Lange, and Peters. In `curve25519-dalek`, it is -//! represented by the `ProjectivePoint` struct. -//! -//! # Passing between curve models -//! -//! Although the \\( \mathbb P\^3 \\) model provides faster addition -//! formulas, the \\( \mathbb P\^2 \\) model provides faster doubling -//! formulas. Hisil, Wong, Carter, and Dawson therefore suggest mixing -//! coordinate systems for scalar multiplication, attributing the idea -//! to [a 1998 paper][cohen-miyaji-ono-1998] of Cohen, Miyagi, and Ono. -//! -//! Their suggestion is to vary the formulas used by context, using a -//! \\( \mathbb P\^2 \rightarrow \mathbb P\^2 \\) doubling formula when -//! a doubling is followed -//! by another doubling, a \\( \mathbb P\^2 \rightarrow \mathbb P\^3 \\) -//! doubling formula when a doubling is followed by an addition, and -//! computing point additions using a \\( \mathbb P\^3 \times \mathbb P\^3 -//! \rightarrow \mathbb P\^2 \\) formula. -//! -//! The `ref10` reference implementation of [Ed25519][ed25519], by -//! Bernstein, Duif, Lange, Schwabe, and Yang, tweaks -//! this strategy, factoring the addition formulas through the -//! completion \\( \mathbb P\^1 \times \mathbb P\^1 \\), so that the -//! output of an addition or doubling always lies in \\( \mathbb P\^1 \times -//! \mathbb P\^1\\), and the choice of which formula to use is replaced -//! by a choice of whether to convert the result to \\( \mathbb P\^2 \\) -//! or \\(\mathbb P\^3 \\). However, this tweak is not described in -//! their paper, only in their software. -//! -//! Our naming for the `CompletedPoint` (\\(\mathbb P\^1 \times \mathbb -//! P\^1 \\)), `ProjectivePoint` (\\(\mathbb P\^2 \\)), and -//! `EdwardsPoint` (\\(\mathbb P\^3 \\)) structs follows the naming in -//! Adam Langley's [Golang ed25519][agl-ed25519] implementation, which -//! `curve25519-dalek` was originally derived from. -//! -//! Finally, to accelerate readditions, we use two cached point formats -//! in "Niels coordinates", named for Niels Duif, -//! one for the affine model and one for the \\( \mathbb P\^3 \\) model: -//! -//! * `AffineNielsPoint`: \\( (y+x, y-x, 2dxy) \\) -//! * `ProjectiveNielsPoint`: \\( (Y+X, Y-X, Z, 2dXY) \\) -//! -//! [smith-moderncrypto]: https://moderncrypto.org/mail-archive/curves/2016/000807.html -//! [costello-smith-2017]: https://eprint.iacr.org/2017/212 -//! [hisil-wong-carter-dawson-2008]: https://www.iacr.org/archive/asiacrypt2008/53500329/53500329.pdf -//! [bernstein-birkner-joye-lange-peters-2008]: https://eprint.iacr.org/2008/013 -//! [cohen-miyaji-ono-1998]: https://link.springer.com/content/pdf/10.1007%2F3-540-49649-1_6.pdf -//! [ed25519]: https://eprint.iacr.org/2011/368 -//! [agl-ed25519]: https://github.com/agl/ed25519 - -#![allow(non_snake_case)] - -use core::fmt::Debug; -use core::ops::{Add, Neg, Sub}; - -use subtle::Choice; -use subtle::ConditionallySelectable; - -use zeroize::Zeroize; - -use constants; - -use edwards::EdwardsPoint; -use field::FieldElement; -use traits::ValidityCheck; - -// ------------------------------------------------------------------------ -// Internal point representations -// ------------------------------------------------------------------------ - -/// A `ProjectivePoint` is a point \\((X:Y:Z)\\) on the \\(\mathbb -/// P\^2\\) model of the curve. -/// A point \\((x,y)\\) in the affine model corresponds to -/// \\((x:y:1)\\). -/// -/// More details on the relationships between the different curve models -/// can be found in the module-level documentation. -#[derive(Copy, Clone)] -pub struct ProjectivePoint { - pub X: FieldElement, - pub Y: FieldElement, - pub Z: FieldElement, -} - -/// A `CompletedPoint` is a point \\(((X:Z), (Y:T))\\) on the \\(\mathbb -/// P\^1 \times \mathbb P\^1 \\) model of the curve. -/// A point (x,y) in the affine model corresponds to \\( ((x:1),(y:1)) -/// \\). -/// -/// More details on the relationships between the different curve models -/// can be found in the module-level documentation. -#[derive(Copy, Clone)] -#[allow(missing_docs)] -pub struct CompletedPoint { - pub X: FieldElement, - pub Y: FieldElement, - pub Z: FieldElement, - pub T: FieldElement, -} - -/// A pre-computed point in the affine model for the curve, represented as -/// \\((y+x, y-x, 2dxy)\\) in "Niels coordinates". -/// -/// More details on the relationships between the different curve models -/// can be found in the module-level documentation. -// Safe to derive Eq because affine coordinates. -#[derive(Copy, Clone, Eq, PartialEq)] -#[allow(missing_docs)] -pub struct AffineNielsPoint { - pub y_plus_x: FieldElement, - pub y_minus_x: FieldElement, - pub xy2d: FieldElement, -} - -impl Zeroize for AffineNielsPoint { - fn zeroize(&mut self) { - self.y_plus_x.zeroize(); - self.y_minus_x.zeroize(); - self.xy2d.zeroize(); - } -} - -/// A pre-computed point on the \\( \mathbb P\^3 \\) model for the -/// curve, represented as \\((Y+X, Y-X, Z, 2dXY)\\) in "Niels coordinates". -/// -/// More details on the relationships between the different curve models -/// can be found in the module-level documentation. -#[derive(Copy, Clone)] -pub struct ProjectiveNielsPoint { - pub Y_plus_X: FieldElement, - pub Y_minus_X: FieldElement, - pub Z: FieldElement, - pub T2d: FieldElement, -} - -impl Zeroize for ProjectiveNielsPoint { - fn zeroize(&mut self) { - self.Y_plus_X.zeroize(); - self.Y_minus_X.zeroize(); - self.Z.zeroize(); - self.T2d.zeroize(); - } -} - -// ------------------------------------------------------------------------ -// Constructors -// ------------------------------------------------------------------------ - -use traits::Identity; - -impl Identity for ProjectivePoint { - fn identity() -> ProjectivePoint { - ProjectivePoint { - X: FieldElement::zero(), - Y: FieldElement::one(), - Z: FieldElement::one(), - } - } -} - -impl Identity for ProjectiveNielsPoint { - fn identity() -> ProjectiveNielsPoint { - ProjectiveNielsPoint{ - Y_plus_X: FieldElement::one(), - Y_minus_X: FieldElement::one(), - Z: FieldElement::one(), - T2d: FieldElement::zero(), - } - } -} - -impl Default for ProjectiveNielsPoint { - fn default() -> ProjectiveNielsPoint { - ProjectiveNielsPoint::identity() - } -} - -impl Identity for AffineNielsPoint { - fn identity() -> AffineNielsPoint { - AffineNielsPoint{ - y_plus_x: FieldElement::one(), - y_minus_x: FieldElement::one(), - xy2d: FieldElement::zero(), - } - } -} - -impl Default for AffineNielsPoint { - fn default() -> AffineNielsPoint { - AffineNielsPoint::identity() - } -} - -// ------------------------------------------------------------------------ -// Validity checks (for debugging, not CT) -// ------------------------------------------------------------------------ - -impl ValidityCheck for ProjectivePoint { - fn is_valid(&self) -> bool { - // Curve equation is -x^2 + y^2 = 1 + d*x^2*y^2, - // homogenized as (-X^2 + Y^2)*Z^2 = Z^4 + d*X^2*Y^2 - let XX = self.X.square(); - let YY = self.Y.square(); - let ZZ = self.Z.square(); - let ZZZZ = ZZ.square(); - let lhs = &(&YY - &XX) * &ZZ; - let rhs = &ZZZZ + &(&constants::EDWARDS_D * &(&XX * &YY)); - - lhs == rhs - } -} - -// ------------------------------------------------------------------------ -// Constant-time assignment -// ------------------------------------------------------------------------ - -impl ConditionallySelectable for ProjectiveNielsPoint { - fn conditional_select(a: &Self, b: &Self, choice: Choice) -> Self { - ProjectiveNielsPoint { - Y_plus_X: FieldElement::conditional_select(&a.Y_plus_X, &b.Y_plus_X, choice), - Y_minus_X: FieldElement::conditional_select(&a.Y_minus_X, &b.Y_minus_X, choice), - Z: FieldElement::conditional_select(&a.Z, &b.Z, choice), - T2d: FieldElement::conditional_select(&a.T2d, &b.T2d, choice), - } - } - - fn conditional_assign(&mut self, other: &Self, choice: Choice) { - self.Y_plus_X.conditional_assign(&other.Y_plus_X, choice); - self.Y_minus_X.conditional_assign(&other.Y_minus_X, choice); - self.Z.conditional_assign(&other.Z, choice); - self.T2d.conditional_assign(&other.T2d, choice); - } -} - -impl ConditionallySelectable for AffineNielsPoint { - fn conditional_select(a: &Self, b: &Self, choice: Choice) -> Self { - AffineNielsPoint { - y_plus_x: FieldElement::conditional_select(&a.y_plus_x, &b.y_plus_x, choice), - y_minus_x: FieldElement::conditional_select(&a.y_minus_x, &b.y_minus_x, choice), - xy2d: FieldElement::conditional_select(&a.xy2d, &b.xy2d, choice), - } - } - - fn conditional_assign(&mut self, other: &Self, choice: Choice) { - self.y_plus_x.conditional_assign(&other.y_plus_x, choice); - self.y_minus_x.conditional_assign(&other.y_minus_x, choice); - self.xy2d.conditional_assign(&other.xy2d, choice); - } -} - -// ------------------------------------------------------------------------ -// Point conversions -// ------------------------------------------------------------------------ - -impl ProjectivePoint { - /// Convert this point from the \\( \mathbb P\^2 \\) model to the - /// \\( \mathbb P\^3 \\) model. - /// - /// This costs \\(3 \mathrm M + 1 \mathrm S\\). - pub fn to_extended(&self) -> EdwardsPoint { - EdwardsPoint { - X: &self.X * &self.Z, - Y: &self.Y * &self.Z, - Z: self.Z.square(), - T: &self.X * &self.Y, - } - } -} - -impl CompletedPoint { - /// Convert this point from the \\( \mathbb P\^1 \times \mathbb P\^1 - /// \\) model to the \\( \mathbb P\^2 \\) model. - /// - /// This costs \\(3 \mathrm M \\). - pub fn to_projective(&self) -> ProjectivePoint { - ProjectivePoint { - X: &self.X * &self.T, - Y: &self.Y * &self.Z, - Z: &self.Z * &self.T, - } - } - - /// Convert this point from the \\( \mathbb P\^1 \times \mathbb P\^1 - /// \\) model to the \\( \mathbb P\^3 \\) model. - /// - /// This costs \\(4 \mathrm M \\). - pub fn to_extended(&self) -> EdwardsPoint { - EdwardsPoint { - X: &self.X * &self.T, - Y: &self.Y * &self.Z, - Z: &self.Z * &self.T, - T: &self.X * &self.Y, - } - } -} - -// ------------------------------------------------------------------------ -// Doubling -// ------------------------------------------------------------------------ - -impl ProjectivePoint { - /// Double this point: return self + self - pub fn double(&self) -> CompletedPoint { // Double() - let XX = self.X.square(); - let YY = self.Y.square(); - let ZZ2 = self.Z.square2(); - let X_plus_Y = &self.X + &self.Y; - let X_plus_Y_sq = X_plus_Y.square(); - let YY_plus_XX = &YY + &XX; - let YY_minus_XX = &YY - &XX; - - CompletedPoint{ - X: &X_plus_Y_sq - &YY_plus_XX, - Y: YY_plus_XX, - Z: YY_minus_XX, - T: &ZZ2 - &YY_minus_XX - } - } -} - -// ------------------------------------------------------------------------ -// Addition and Subtraction -// ------------------------------------------------------------------------ - -// XXX(hdevalence) These were doc(hidden) so they don't appear in the -// public API docs. -// However, that prevents them being used with --document-private-items, -// so comment out the doc(hidden) for now until this is resolved -// -// upstream rust issue: https://github.com/rust-lang/rust/issues/46380 -//#[doc(hidden)] -impl<'a, 'b> Add<&'b ProjectiveNielsPoint> for &'a EdwardsPoint { - type Output = CompletedPoint; - - fn add(self, other: &'b ProjectiveNielsPoint) -> CompletedPoint { - let Y_plus_X = &self.Y + &self.X; - let Y_minus_X = &self.Y - &self.X; - let PP = &Y_plus_X * &other.Y_plus_X; - let MM = &Y_minus_X * &other.Y_minus_X; - let TT2d = &self.T * &other.T2d; - let ZZ = &self.Z * &other.Z; - let ZZ2 = &ZZ + &ZZ; - - CompletedPoint{ - X: &PP - &MM, - Y: &PP + &MM, - Z: &ZZ2 + &TT2d, - T: &ZZ2 - &TT2d - } - } -} - -//#[doc(hidden)] -impl<'a, 'b> Sub<&'b ProjectiveNielsPoint> for &'a EdwardsPoint { - type Output = CompletedPoint; - - fn sub(self, other: &'b ProjectiveNielsPoint) -> CompletedPoint { - let Y_plus_X = &self.Y + &self.X; - let Y_minus_X = &self.Y - &self.X; - let PM = &Y_plus_X * &other.Y_minus_X; - let MP = &Y_minus_X * &other.Y_plus_X; - let TT2d = &self.T * &other.T2d; - let ZZ = &self.Z * &other.Z; - let ZZ2 = &ZZ + &ZZ; - - CompletedPoint{ - X: &PM - &MP, - Y: &PM + &MP, - Z: &ZZ2 - &TT2d, - T: &ZZ2 + &TT2d - } - } -} - -//#[doc(hidden)] -impl<'a, 'b> Add<&'b AffineNielsPoint> for &'a EdwardsPoint { - type Output = CompletedPoint; - - fn add(self, other: &'b AffineNielsPoint) -> CompletedPoint { - let Y_plus_X = &self.Y + &self.X; - let Y_minus_X = &self.Y - &self.X; - let PP = &Y_plus_X * &other.y_plus_x; - let MM = &Y_minus_X * &other.y_minus_x; - let Txy2d = &self.T * &other.xy2d; - let Z2 = &self.Z + &self.Z; - - CompletedPoint{ - X: &PP - &MM, - Y: &PP + &MM, - Z: &Z2 + &Txy2d, - T: &Z2 - &Txy2d - } - } -} - -//#[doc(hidden)] -impl<'a, 'b> Sub<&'b AffineNielsPoint> for &'a EdwardsPoint { - type Output = CompletedPoint; - - fn sub(self, other: &'b AffineNielsPoint) -> CompletedPoint { - let Y_plus_X = &self.Y + &self.X; - let Y_minus_X = &self.Y - &self.X; - let PM = &Y_plus_X * &other.y_minus_x; - let MP = &Y_minus_X * &other.y_plus_x; - let Txy2d = &self.T * &other.xy2d; - let Z2 = &self.Z + &self.Z; - - CompletedPoint{ - X: &PM - &MP, - Y: &PM + &MP, - Z: &Z2 - &Txy2d, - T: &Z2 + &Txy2d - } - } -} - -// ------------------------------------------------------------------------ -// Negation -// ------------------------------------------------------------------------ - -impl<'a> Neg for &'a ProjectiveNielsPoint { - type Output = ProjectiveNielsPoint; - - fn neg(self) -> ProjectiveNielsPoint { - ProjectiveNielsPoint{ - Y_plus_X: self.Y_minus_X, - Y_minus_X: self.Y_plus_X, - Z: self.Z, - T2d: -(&self.T2d), - } - } -} - -impl<'a> Neg for &'a AffineNielsPoint { - type Output = AffineNielsPoint; - - fn neg(self) -> AffineNielsPoint { - AffineNielsPoint{ - y_plus_x: self.y_minus_x, - y_minus_x: self.y_plus_x, - xy2d: -(&self.xy2d) - } - } -} - -// ------------------------------------------------------------------------ -// Debug traits -// ------------------------------------------------------------------------ - -impl Debug for ProjectivePoint { - fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { - write!(f, "ProjectivePoint{{\n\tX: {:?},\n\tY: {:?},\n\tZ: {:?}\n}}", - &self.X, &self.Y, &self.Z) - } -} - -impl Debug for CompletedPoint { - fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { - write!(f, "CompletedPoint{{\n\tX: {:?},\n\tY: {:?},\n\tZ: {:?},\n\tT: {:?}\n}}", - &self.X, &self.Y, &self.Z, &self.T) - } -} - -impl Debug for AffineNielsPoint { - fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { - write!(f, "AffineNielsPoint{{\n\ty_plus_x: {:?},\n\ty_minus_x: {:?},\n\txy2d: {:?}\n}}", - &self.y_plus_x, &self.y_minus_x, &self.xy2d) - } -} - -impl Debug for ProjectiveNielsPoint { - fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { - write!(f, "ProjectiveNielsPoint{{\n\tY_plus_X: {:?},\n\tY_minus_X: {:?},\n\tZ: {:?},\n\tT2d: {:?}\n}}", - &self.Y_plus_X, &self.Y_minus_X, &self.Z, &self.T2d) - } -} - - diff --git a/net/gurk-rs/files/vendor/curve25519-dalek-2.0.0/src/backend/serial/mod.rs b/net/gurk-rs/files/vendor/curve25519-dalek-2.0.0/src/backend/serial/mod.rs deleted file mode 100644 index fc6b320..0000000 --- a/net/gurk-rs/files/vendor/curve25519-dalek-2.0.0/src/backend/serial/mod.rs +++ /dev/null @@ -1,43 +0,0 @@ -// -*- mode: rust; -*- -// -// This file is part of curve25519-dalek. -// Copyright (c) 2016-2019 Isis Lovecruft, Henry de Valence -// See LICENSE for licensing information. -// -// Authors: -// - Isis Agora Lovecruft -// - Henry de Valence - -//! Serial implementations of field, scalar, point arithmetic. -//! -//! When the vector backend is disabled, the crate uses the -//! mixed-model strategy for implementing point operations and scalar -//! multiplication; see the [`curve_models`](self::curve_models) and -//! [`scalar_mul`](self::scalar_mul) documentation for more -//! information. -//! -//! When the vector backend is enabled, the field and scalar -//! implementations are still used for non-vectorized operations. -//! -//! Note: at this time the `u32` and `u64` backends cannot be built -//! together. - -#[cfg(not(any(feature = "u32_backend", feature = "u64_backend")))] -compile_error!( - "no curve25519-dalek backend cargo feature enabled! \ - please enable one of: u32_backend, u64_backend" -); - -#[cfg(feature = "u32_backend")] -pub mod u32; - -#[cfg(feature = "u64_backend")] -pub mod u64; - -pub mod curve_models; - -#[cfg(not(all( - feature = "simd_backend", - any(target_feature = "avx2", target_feature = "avx512ifma") -)))] -pub mod scalar_mul; diff --git a/net/gurk-rs/files/vendor/curve25519-dalek-2.0.0/src/backend/serial/scalar_mul/mod.rs b/net/gurk-rs/files/vendor/curve25519-dalek-2.0.0/src/backend/serial/scalar_mul/mod.rs deleted file mode 100644 index 544725a..0000000 --- a/net/gurk-rs/files/vendor/curve25519-dalek-2.0.0/src/backend/serial/scalar_mul/mod.rs +++ /dev/null @@ -1,30 +0,0 @@ -// -*- mode: rust; -*- -// -// This file is part of curve25519-dalek. -// Copyright (c) 2016-2019 Isis Lovecruft, Henry de Valence -// See LICENSE for licensing information. -// -// Authors: -// - Isis Agora Lovecruft -// - Henry de Valence - -//! Implementations of various scalar multiplication algorithms. -//! -//! Note that all of these implementations use serial code for field -//! arithmetic with the multi-model strategy described in the -//! `curve_models` module. The vectorized AVX2 backend has its own -//! scalar multiplication implementations, since it only uses one -//! curve model. - -pub mod variable_base; - -pub mod vartime_double_base; - -#[cfg(feature = "alloc")] -pub mod straus; - -#[cfg(feature = "alloc")] -pub mod precomputed_straus; - -#[cfg(feature = "alloc")] -pub mod pippenger; diff --git a/net/gurk-rs/files/vendor/curve25519-dalek-2.0.0/src/backend/serial/scalar_mul/pippenger.rs b/net/gurk-rs/files/vendor/curve25519-dalek-2.0.0/src/backend/serial/scalar_mul/pippenger.rs deleted file mode 100644 index bffe140..0000000 --- a/net/gurk-rs/files/vendor/curve25519-dalek-2.0.0/src/backend/serial/scalar_mul/pippenger.rs +++ /dev/null @@ -1,202 +0,0 @@ -// -*- mode: rust; -*- -// -// This file is part of curve25519-dalek. -// Copyright (c) 2019 Oleg Andreev -// See LICENSE for licensing information. -// -// Authors: -// - Oleg Andreev - -//! Implementation of a variant of Pippenger's algorithm. - -#![allow(non_snake_case)] - -use core::borrow::Borrow; - -use edwards::EdwardsPoint; -use scalar::Scalar; -use traits::VartimeMultiscalarMul; - -#[allow(unused_imports)] -use prelude::*; - -/// Implements a version of Pippenger's algorithm. -/// -/// The algorithm works as follows: -/// -/// Let `n` be a number of point-scalar pairs. -/// Let `w` be a window of bits (6..8, chosen based on `n`, see cost factor). -/// -/// 1. Prepare `2^(w-1) - 1` buckets with indices `[1..2^(w-1))` initialized with identity points. -/// Bucket 0 is not needed as it would contain points multiplied by 0. -/// 2. Convert scalars to a radix-`2^w` representation with signed digits in `[-2^w/2, 2^w/2]`. -/// Note: only the last digit may equal `2^w/2`. -/// 3. Starting with the last window, for each point `i=[0..n)` add it to a a bucket indexed by -/// the point's scalar's value in the window. -/// 4. Once all points in a window are sorted into buckets, add buckets by multiplying each -/// by their index. Efficient way of doing it is to start with the last bucket and compute two sums: -/// intermediate sum from the last to the first, and the full sum made of all intermediate sums. -/// 5. Shift the resulting sum of buckets by `w` bits by using `w` doublings. -/// 6. Add to the return value. -/// 7. Repeat the loop. -/// -/// Approximate cost w/o wNAF optimizations (A = addition, D = doubling): -/// -/// ```ascii -/// cost = (n*A + 2*(2^w/2)*A + w*D + A)*256/w -/// | | | | | -/// | | | | looping over 256/w windows -/// | | | adding to the result -/// sorting points | shifting the sum by w bits (to the next window, starting from last window) -/// one by one | -/// into buckets adding/subtracting all buckets -/// multiplied by their indexes -/// using a sum of intermediate sums -/// ``` -/// -/// For large `n`, dominant factor is (n*256/w) additions. -/// However, if `w` is too big and `n` is not too big, then `(2^w/2)*A` could dominate. -/// Therefore, the optimal choice of `w` grows slowly as `n` grows. -/// -/// This algorithm is adapted from section 4 of https://eprint.iacr.org/2012/549.pdf. -pub struct Pippenger; - -#[cfg(any(feature = "alloc", feature = "std"))] -impl VartimeMultiscalarMul for Pippenger { - type Point = EdwardsPoint; - - fn optional_multiscalar_mul(scalars: I, points: J) -> Option - where - I: IntoIterator, - I::Item: Borrow, - J: IntoIterator>, - { - use traits::Identity; - - let mut scalars = scalars.into_iter(); - let size = scalars.by_ref().size_hint().0; - - // Digit width in bits. As digit width grows, - // number of point additions goes down, but amount of - // buckets and bucket additions grows exponentially. - let w = if size < 500 { - 6 - } else if size < 800 { - 7 - } else { - 8 - }; - - let max_digit: usize = 1 << w; - let digits_count: usize = Scalar::to_radix_2w_size_hint(w); - let buckets_count: usize = max_digit / 2; // digits are signed+centered hence 2^w/2, excluding 0-th bucket - - // Collect optimized scalars and points in buffers for repeated access - // (scanning the whole set per digit position). - let scalars = scalars - .map(|s| s.borrow().to_radix_2w(w)); - - let points = points - .into_iter() - .map(|p| p.map(|P| P.to_projective_niels())); - - let scalars_points = scalars - .zip(points) - .map(|(s, maybe_p)| maybe_p.map(|p| (s, p))) - .collect::>>()?; - - // Prepare 2^w/2 buckets. - // buckets[i] corresponds to a multiplication factor (i+1). - let mut buckets: Vec<_> = (0..buckets_count) - .map(|_| EdwardsPoint::identity()) - .collect(); - - let mut columns = (0..digits_count).rev().map(|digit_index| { - // Clear the buckets when processing another digit. - for i in 0..buckets_count { - buckets[i] = EdwardsPoint::identity(); - } - - // Iterate over pairs of (point, scalar) - // and add/sub the point to the corresponding bucket. - // Note: if we add support for precomputed lookup tables, - // we'll be adding/subtracting point premultiplied by `digits[i]` to buckets[0]. - for (digits, pt) in scalars_points.iter() { - // Widen digit so that we don't run into edge cases when w=8. - let digit = digits[digit_index] as i16; - if digit > 0 { - let b = (digit - 1) as usize; - buckets[b] = (&buckets[b] + pt).to_extended(); - } else if digit < 0 { - let b = (-digit - 1) as usize; - buckets[b] = (&buckets[b] - pt).to_extended(); - } - } - - // Add the buckets applying the multiplication factor to each bucket. - // The most efficient way to do that is to have a single sum with two running sums: - // an intermediate sum from last bucket to the first, and a sum of intermediate sums. - // - // For example, to add buckets 1*A, 2*B, 3*C we need to add these points: - // C - // C B - // C B A Sum = C + (C+B) + (C+B+A) - let mut buckets_intermediate_sum = buckets[buckets_count - 1]; - let mut buckets_sum = buckets[buckets_count - 1]; - for i in (0..(buckets_count - 1)).rev() { - buckets_intermediate_sum += buckets[i]; - buckets_sum += buckets_intermediate_sum; - } - - buckets_sum - }); - - // Take the high column as an initial value to avoid wasting time doubling the identity element in `fold()`. - // `unwrap()` always succeeds because we know we have more than zero digits. - let hi_column = columns.next().unwrap(); - - Some( - columns - .fold(hi_column, |total, p| total.mul_by_pow_2(w as u32) + p), - ) - } -} - -#[cfg(test)] -mod test { - use super::*; - use constants; - use scalar::Scalar; - - #[test] - fn test_vartime_pippenger() { - // Reuse points across different tests - let mut n = 512; - let x = Scalar::from(2128506u64).invert(); - let y = Scalar::from(4443282u64).invert(); - let points: Vec<_> = (0..n) - .map(|i| constants::ED25519_BASEPOINT_POINT * Scalar::from(1 + i as u64)) - .collect(); - let scalars: Vec<_> = (0..n) - .map(|i| x + (Scalar::from(i as u64) * y)) // fast way to make ~random but deterministic scalars - .collect(); - - let premultiplied: Vec = scalars - .iter() - .zip(points.iter()) - .map(|(sc, pt)| sc * pt) - .collect(); - - while n > 0 { - let scalars = &scalars[0..n].to_vec(); - let points = &points[0..n].to_vec(); - let control: EdwardsPoint = premultiplied[0..n].iter().sum(); - - let subject = Pippenger::vartime_multiscalar_mul(scalars.clone(), points.clone()); - - assert_eq!(subject.compress(), control.compress()); - - n = n / 2; - } - } -} diff --git a/net/gurk-rs/files/vendor/curve25519-dalek-2.0.0/src/backend/serial/scalar_mul/precomputed_straus.rs b/net/gurk-rs/files/vendor/curve25519-dalek-2.0.0/src/backend/serial/scalar_mul/precomputed_straus.rs deleted file mode 100644 index 97f5e86..0000000 --- a/net/gurk-rs/files/vendor/curve25519-dalek-2.0.0/src/backend/serial/scalar_mul/precomputed_straus.rs +++ /dev/null @@ -1,110 +0,0 @@ -// -*- mode: rust; -*- -// -// This file is part of curve25519-dalek. -// Copyright (c) 2019 Henry de Valence. -// See LICENSE for licensing information. -// -// Authors: -// - Henry de Valence - -//! Precomputation for Straus's method. - -#![allow(non_snake_case)] - -use core::borrow::Borrow; - -use backend::serial::curve_models::{ - AffineNielsPoint, CompletedPoint, ProjectiveNielsPoint, ProjectivePoint, -}; -use edwards::EdwardsPoint; -use scalar::Scalar; -use traits::Identity; -use traits::VartimePrecomputedMultiscalarMul; -use window::{NafLookupTable5, NafLookupTable8}; - -#[allow(unused_imports)] -use prelude::*; - -pub struct VartimePrecomputedStraus { - static_lookup_tables: Vec>, -} - -impl VartimePrecomputedMultiscalarMul for VartimePrecomputedStraus { - type Point = EdwardsPoint; - - fn new(static_points: I) -> Self - where - I: IntoIterator, - I::Item: Borrow, - { - Self { - static_lookup_tables: static_points - .into_iter() - .map(|P| NafLookupTable8::::from(P.borrow())) - .collect(), - } - } - - fn optional_mixed_multiscalar_mul( - &self, - static_scalars: I, - dynamic_scalars: J, - dynamic_points: K, - ) -> Option - where - I: IntoIterator, - I::Item: Borrow, - J: IntoIterator, - J::Item: Borrow, - K: IntoIterator>, - { - let static_nafs = static_scalars - .into_iter() - .map(|c| c.borrow().non_adjacent_form(5)) - .collect::>(); - let dynamic_nafs: Vec<_> = dynamic_scalars - .into_iter() - .map(|c| c.borrow().non_adjacent_form(5)) - .collect::>(); - - let dynamic_lookup_tables = dynamic_points - .into_iter() - .map(|P_opt| P_opt.map(|P| NafLookupTable5::::from(&P))) - .collect::>>()?; - - let sp = self.static_lookup_tables.len(); - let dp = dynamic_lookup_tables.len(); - assert_eq!(sp, static_nafs.len()); - assert_eq!(dp, dynamic_nafs.len()); - - // We could save some doublings by looking for the highest - // nonzero NAF coefficient, but since we might have a lot of - // them to search, it's not clear it's worthwhile to check. - let mut S = ProjectivePoint::identity(); - for j in (0..256).rev() { - let mut R: CompletedPoint = S.double(); - - for i in 0..dp { - let t_ij = dynamic_nafs[i][j]; - if t_ij > 0 { - R = &R.to_extended() + &dynamic_lookup_tables[i].select(t_ij as usize); - } else if t_ij < 0 { - R = &R.to_extended() - &dynamic_lookup_tables[i].select(-t_ij as usize); - } - } - - for i in 0..sp { - let t_ij = static_nafs[i][j]; - if t_ij > 0 { - R = &R.to_extended() + &self.static_lookup_tables[i].select(t_ij as usize); - } else if t_ij < 0 { - R = &R.to_extended() - &self.static_lookup_tables[i].select(-t_ij as usize); - } - } - - S = R.to_projective(); - } - - Some(S.to_extended()) - } -} diff --git a/net/gurk-rs/files/vendor/curve25519-dalek-2.0.0/src/backend/serial/scalar_mul/straus.rs b/net/gurk-rs/files/vendor/curve25519-dalek-2.0.0/src/backend/serial/scalar_mul/straus.rs deleted file mode 100644 index b63e162..0000000 --- a/net/gurk-rs/files/vendor/curve25519-dalek-2.0.0/src/backend/serial/scalar_mul/straus.rs +++ /dev/null @@ -1,195 +0,0 @@ -// -*- mode: rust; -*- -// -// This file is part of curve25519-dalek. -// Copyright (c) 2016-2019 Isis Lovecruft, Henry de Valence -// See LICENSE for licensing information. -// -// Authors: -// - Isis Agora Lovecruft -// - Henry de Valence - -//! Implementation of the interleaved window method, also known as Straus' method. - -#![allow(non_snake_case)] - -use core::borrow::Borrow; - -use edwards::EdwardsPoint; -use scalar::Scalar; -use traits::MultiscalarMul; -use traits::VartimeMultiscalarMul; - -#[allow(unused_imports)] -use prelude::*; - -/// Perform multiscalar multiplication by the interleaved window -/// method, also known as Straus' method (since it was apparently -/// [first published][solution] by Straus in 1964, as a solution to [a -/// problem][problem] posted in the American Mathematical Monthly in -/// 1963). -/// -/// It is easy enough to reinvent, and has been repeatedly. The basic -/// idea is that when computing -/// \\[ -/// Q = s_1 P_1 + \cdots + s_n P_n -/// \\] -/// by means of additions and doublings, the doublings can be shared -/// across the \\( P_i \\\). -/// -/// We implement two versions, a constant-time algorithm using fixed -/// windows and a variable-time algorithm using sliding windows. They -/// are slight variations on the same idea, and are described in more -/// detail in the respective implementations. -/// -/// [solution]: https://www.jstor.org/stable/2310929 -/// [problem]: https://www.jstor.org/stable/2312273 -pub struct Straus {} - -impl MultiscalarMul for Straus { - type Point = EdwardsPoint; - - /// Constant-time Straus using a fixed window of size \\(4\\). - /// - /// Our goal is to compute - /// \\[ - /// Q = s_1 P_1 + \cdots + s_n P_n. - /// \\] - /// - /// For each point \\( P_i \\), precompute a lookup table of - /// \\[ - /// P_i, 2P_i, 3P_i, 4P_i, 5P_i, 6P_i, 7P_i, 8P_i. - /// \\] - /// - /// For each scalar \\( s_i \\), compute its radix-\\(2^4\\) - /// signed digits \\( s_{i,j} \\), i.e., - /// \\[ - /// s_i = s_{i,0} + s_{i,1} 16^1 + ... + s_{i,63} 16^{63}, - /// \\] - /// with \\( -8 \leq s_{i,j} < 8 \\). Since \\( 0 \leq |s_{i,j}| - /// \leq 8 \\), we can retrieve \\( s_{i,j} P_i \\) from the - /// lookup table with a conditional negation: using signed - /// digits halves the required table size. - /// - /// Then as in the single-base fixed window case, we have - /// \\[ - /// \begin{aligned} - /// s_i P_i &= P_i (s_{i,0} + s_{i,1} 16^1 + \cdots + s_{i,63} 16^{63}) \\\\ - /// s_i P_i &= P_i s_{i,0} + P_i s_{i,1} 16^1 + \cdots + P_i s_{i,63} 16^{63} \\\\ - /// s_i P_i &= P_i s_{i,0} + 16(P_i s_{i,1} + 16( \cdots +16P_i s_{i,63})\cdots ) - /// \end{aligned} - /// \\] - /// so each \\( s_i P_i \\) can be computed by alternately adding - /// a precomputed multiple \\( P_i s_{i,j} \\) of \\( P_i \\) and - /// repeatedly doubling. - /// - /// Now consider the two-dimensional sum - /// \\[ - /// \begin{aligned} - /// s\_1 P\_1 &=& P\_1 s\_{1,0} &+& 16 (P\_1 s\_{1,1} &+& 16 ( \cdots &+& 16 P\_1 s\_{1,63}&) \cdots ) \\\\ - /// + & & + & & + & & & & + & \\\\ - /// s\_2 P\_2 &=& P\_2 s\_{2,0} &+& 16 (P\_2 s\_{2,1} &+& 16 ( \cdots &+& 16 P\_2 s\_{2,63}&) \cdots ) \\\\ - /// + & & + & & + & & & & + & \\\\ - /// \vdots & & \vdots & & \vdots & & & & \vdots & \\\\ - /// + & & + & & + & & & & + & \\\\ - /// s\_n P\_n &=& P\_n s\_{n,0} &+& 16 (P\_n s\_{n,1} &+& 16 ( \cdots &+& 16 P\_n s\_{n,63}&) \cdots ) - /// \end{aligned} - /// \\] - /// The sum of the left-hand column is the result \\( Q \\); by - /// computing the two-dimensional sum on the right column-wise, - /// top-to-bottom, then right-to-left, we need to multiply by \\( - /// 16\\) only once per column, sharing the doublings across all - /// of the input points. - fn multiscalar_mul(scalars: I, points: J) -> EdwardsPoint - where - I: IntoIterator, - I::Item: Borrow, - J: IntoIterator, - J::Item: Borrow, - { - use zeroize::Zeroizing; - - use backend::serial::curve_models::ProjectiveNielsPoint; - use window::LookupTable; - use traits::Identity; - - let lookup_tables: Vec<_> = points - .into_iter() - .map(|point| LookupTable::::from(point.borrow())) - .collect(); - - // This puts the scalar digits into a heap-allocated Vec. - // To ensure that these are erased, pass ownership of the Vec into a - // Zeroizing wrapper. - let scalar_digits_vec: Vec<_> = scalars - .into_iter() - .map(|s| s.borrow().to_radix_16()) - .collect(); - let scalar_digits = Zeroizing::new(scalar_digits_vec); - - let mut Q = EdwardsPoint::identity(); - for j in (0..64).rev() { - Q = Q.mul_by_pow_2(4); - let it = scalar_digits.iter().zip(lookup_tables.iter()); - for (s_i, lookup_table_i) in it { - // R_i = s_{i,j} * P_i - let R_i = lookup_table_i.select(s_i[j]); - // Q = Q + R_i - Q = (&Q + &R_i).to_extended(); - } - } - - Q - } -} - -impl VartimeMultiscalarMul for Straus { - type Point = EdwardsPoint; - - /// Variable-time Straus using a non-adjacent form of width \\(5\\). - /// - /// This is completely similar to the constant-time code, but we - /// use a non-adjacent form for the scalar, and do not do table - /// lookups in constant time. - /// - /// The non-adjacent form has signed, odd digits. Using only odd - /// digits halves the table size (since we only need odd - /// multiples), or gives fewer additions for the same table size. - fn optional_multiscalar_mul(scalars: I, points: J) -> Option - where - I: IntoIterator, - I::Item: Borrow, - J: IntoIterator>, - { - use backend::serial::curve_models::{CompletedPoint, ProjectiveNielsPoint, ProjectivePoint}; - use window::NafLookupTable5; - use traits::Identity; - - let nafs: Vec<_> = scalars - .into_iter() - .map(|c| c.borrow().non_adjacent_form(5)) - .collect(); - - let lookup_tables = points - .into_iter() - .map(|P_opt| P_opt.map(|P| NafLookupTable5::::from(&P))) - .collect::>>()?; - - let mut r = ProjectivePoint::identity(); - - for i in (0..256).rev() { - let mut t: CompletedPoint = r.double(); - - for (naf, lookup_table) in nafs.iter().zip(lookup_tables.iter()) { - if naf[i] > 0 { - t = &t.to_extended() + &lookup_table.select(naf[i] as usize); - } else if naf[i] < 0 { - t = &t.to_extended() - &lookup_table.select(-naf[i] as usize); - } - } - - r = t.to_projective(); - } - - Some(r.to_extended()) - } -} diff --git a/net/gurk-rs/files/vendor/curve25519-dalek-2.0.0/src/backend/serial/scalar_mul/variable_base.rs b/net/gurk-rs/files/vendor/curve25519-dalek-2.0.0/src/backend/serial/scalar_mul/variable_base.rs deleted file mode 100644 index c69e48c..0000000 --- a/net/gurk-rs/files/vendor/curve25519-dalek-2.0.0/src/backend/serial/scalar_mul/variable_base.rs +++ /dev/null @@ -1,46 +0,0 @@ -#![allow(non_snake_case)] - -use traits::Identity; -use scalar::Scalar; -use edwards::EdwardsPoint; -use backend::serial::curve_models::{ProjectiveNielsPoint, ProjectivePoint}; -use window::LookupTable; - -/// Perform constant-time, variable-base scalar multiplication. -pub(crate) fn mul(point: &EdwardsPoint, scalar: &Scalar) -> EdwardsPoint { - // Construct a lookup table of [P,2P,3P,4P,5P,6P,7P,8P] - let lookup_table = LookupTable::::from(point); - // Setting s = scalar, compute - // - // s = s_0 + s_1*16^1 + ... + s_63*16^63, - // - // with `-8 ≤ s_i < 8` for `0 ≤ i < 63` and `-8 ≤ s_63 ≤ 8`. - let scalar_digits = scalar.to_radix_16(); - // Compute s*P as - // - // s*P = P*(s_0 + s_1*16^1 + s_2*16^2 + ... + s_63*16^63) - // s*P = P*s_0 + P*s_1*16^1 + P*s_2*16^2 + ... + P*s_63*16^63 - // s*P = P*s_0 + 16*(P*s_1 + 16*(P*s_2 + 16*( ... + P*s_63)...)) - // - // We sum right-to-left. - - // Unwrap first loop iteration to save computing 16*identity - let mut tmp2; - let mut tmp3 = EdwardsPoint::identity(); - let mut tmp1 = &tmp3 + &lookup_table.select(scalar_digits[63]); - // Now tmp1 = s_63*P in P1xP1 coords - for i in (0..63).rev() { - tmp2 = tmp1.to_projective(); // tmp2 = (prev) in P2 coords - tmp1 = tmp2.double(); // tmp1 = 2*(prev) in P1xP1 coords - tmp2 = tmp1.to_projective(); // tmp2 = 2*(prev) in P2 coords - tmp1 = tmp2.double(); // tmp1 = 4*(prev) in P1xP1 coords - tmp2 = tmp1.to_projective(); // tmp2 = 4*(prev) in P2 coords - tmp1 = tmp2.double(); // tmp1 = 8*(prev) in P1xP1 coords - tmp2 = tmp1.to_projective(); // tmp2 = 8*(prev) in P2 coords - tmp1 = tmp2.double(); // tmp1 = 16*(prev) in P1xP1 coords - tmp3 = tmp1.to_extended(); // tmp3 = 16*(prev) in P3 coords - tmp1 = &tmp3 + &lookup_table.select(scalar_digits[i]); - // Now tmp1 = s_i*P + 16*(prev) in P1xP1 coords - } - tmp1.to_extended() -} diff --git a/net/gurk-rs/files/vendor/curve25519-dalek-2.0.0/src/backend/serial/scalar_mul/vartime_double_base.rs b/net/gurk-rs/files/vendor/curve25519-dalek-2.0.0/src/backend/serial/scalar_mul/vartime_double_base.rs deleted file mode 100644 index ef8c0ca..0000000 --- a/net/gurk-rs/files/vendor/curve25519-dalek-2.0.0/src/backend/serial/scalar_mul/vartime_double_base.rs +++ /dev/null @@ -1,61 +0,0 @@ -// -*- mode: rust; -*- -// -// This file is part of curve25519-dalek. -// Copyright (c) 2016-2019 Isis Lovecruft, Henry de Valence -// See LICENSE for licensing information. -// -// Authors: -// - Isis Agora Lovecruft -// - Henry de Valence -#![allow(non_snake_case)] - -use constants; -use traits::Identity; -use scalar::Scalar; -use edwards::EdwardsPoint; -use backend::serial::curve_models::{ProjectiveNielsPoint, ProjectivePoint}; -use window::NafLookupTable5; - -/// Compute \\(aA + bB\\) in variable time, where \\(B\\) is the Ed25519 basepoint. -pub fn mul(a: &Scalar, A: &EdwardsPoint, b: &Scalar) -> EdwardsPoint { - let a_naf = a.non_adjacent_form(5); - let b_naf = b.non_adjacent_form(8); - - // Find starting index - let mut i: usize = 255; - for j in (0..256).rev() { - i = j; - if a_naf[i] != 0 || b_naf[i] != 0 { - break; - } - } - - let table_A = NafLookupTable5::::from(A); - let table_B = &constants::AFFINE_ODD_MULTIPLES_OF_BASEPOINT; - - let mut r = ProjectivePoint::identity(); - loop { - let mut t = r.double(); - - if a_naf[i] > 0 { - t = &t.to_extended() + &table_A.select(a_naf[i] as usize); - } else if a_naf[i] < 0 { - t = &t.to_extended() - &table_A.select(-a_naf[i] as usize); - } - - if b_naf[i] > 0 { - t = &t.to_extended() + &table_B.select(b_naf[i] as usize); - } else if b_naf[i] < 0 { - t = &t.to_extended() - &table_B.select(-b_naf[i] as usize); - } - - r = t.to_projective(); - - if i == 0 { - break; - } - i -= 1; - } - - r.to_extended() -} diff --git a/net/gurk-rs/files/vendor/curve25519-dalek-2.0.0/src/backend/serial/u32/constants.rs b/net/gurk-rs/files/vendor/curve25519-dalek-2.0.0/src/backend/serial/u32/constants.rs deleted file mode 100644 index 73f353f..0000000 --- a/net/gurk-rs/files/vendor/curve25519-dalek-2.0.0/src/backend/serial/u32/constants.rs +++ /dev/null @@ -1,4776 +0,0 @@ -// -*- mode: rust; -*- -// -// This file is part of curve25519-dalek. -// Copyright (c) 2016-2019 Isis Lovecruft, Henry de Valence -// See LICENSE for licensing information. -// -// Authors: -// - Isis Agora Lovecruft -// - Henry de Valence - -//! This module contains various constants (such as curve parameters -//! and useful field elements like `sqrt(-1)`), as well as -//! lookup tables of pre-computed points. - -use backend::serial::curve_models::AffineNielsPoint; -use backend::serial::u32::field::FieldElement2625; -use backend::serial::u32::scalar::Scalar29; -use edwards::{EdwardsBasepointTable, EdwardsPoint}; -use window::{LookupTable, NafLookupTable8}; - -/// The value of minus one, equal to `-&FieldElement::one()` -pub(crate) const MINUS_ONE: FieldElement2625 = FieldElement2625([ - 67108844, 33554431, 67108863, 33554431, 67108863, 33554431, 67108863, 33554431, 67108863, 33554431 -]); - -/// Edwards `d` value, equal to `-121665/121666 mod p`. -pub(crate) const EDWARDS_D: FieldElement2625 = FieldElement2625([ - 56195235, 13857412, 51736253, 6949390, 114729, 24766616, 60832955, 30306712, 48412415, 21499315, -]); - -/// Edwards `2*d` value, equal to `2*(-121665/121666) mod p`. -pub(crate) const EDWARDS_D2: FieldElement2625 = FieldElement2625([ - 45281625, 27714825, 36363642, 13898781, 229458, 15978800, 54557047, 27058993, 29715967, 9444199, -]); - -/// One minus edwards `d` value squared, equal to `(1 - (-121665/121666) mod p) pow 2` -pub(crate) const ONE_MINUS_EDWARDS_D_SQUARED: FieldElement2625 = FieldElement2625([ - 6275446, 16937061, 44170319, 29780721, 11667076, 7397348, 39186143, 1766194, 42675006, 672202 -]); - -/// Edwards `d` value minus one squared, equal to `(((-121665/121666) mod p) - 1) pow 2` -pub(crate) const EDWARDS_D_MINUS_ONE_SQUARED: FieldElement2625 = FieldElement2625([ - 15551776, 22456977, 53683765, 23429360, 55212328, 10178283, 40474537, 4729243, 61826754, 23438029 -]); - -/// `= sqrt(a*d - 1)`, where `a = -1 (mod p)`, `d` are the Edwards curve parameters. -pub(crate) const SQRT_AD_MINUS_ONE: FieldElement2625 = FieldElement2625([ - 24849947, 33400850, 43495378, 6347714, 46036536, 32887293, 41837720, 18186727, 66238516, - 14525638, -]); - -/// `= 1/sqrt(a-d)`, where `a = -1 (mod p)`, `d` are the Edwards curve parameters. -pub(crate) const INVSQRT_A_MINUS_D: FieldElement2625 = FieldElement2625([ - 6111466, 4156064, 39310137, 12243467, 41204824, 120896, 20826367, 26493656, 6093567, 31568420, -]); - -/// Precomputed value of one of the square roots of -1 (mod p) -pub(crate) const SQRT_M1: FieldElement2625 = FieldElement2625([ - 34513072, 25610706, 9377949, 3500415, 12389472, 33281959, 41962654, 31548777, 326685, 11406482, -]); - -/// `APLUS2_OVER_FOUR` is (A+2)/4. (This is used internally within the Montgomery ladder.) -pub(crate) const APLUS2_OVER_FOUR: FieldElement2625 = - FieldElement2625([121666, 0, 0, 0, 0, 0, 0, 0, 0, 0]); - -/// `L` is the order of base point, i.e. 2^252 + -/// 27742317777372353535851937790883648493 -pub(crate) const L: Scalar29 = Scalar29([ - 0x1cf5d3ed, 0x009318d2, 0x1de73596, 0x1df3bd45, 0x0000014d, 0x00000000, 0x00000000, 0x00000000, - 0x00100000, -]); - -/// `L` * `LFACTOR` = -1 (mod 2^29) -pub(crate) const LFACTOR: u32 = 0x12547e1b; - -/// `R` = R % L where R = 2^261 -pub(crate) const R: Scalar29 = Scalar29([ - 0x114df9ed, 0x1a617303, 0x0f7c098c, 0x16793167, 0x1ffd656e, 0x1fffffff, 0x1fffffff, 0x1fffffff, - 0x000fffff, -]); - -/// `RR` = (R^2) % L where R = 2^261 -pub(crate) const RR: Scalar29 = Scalar29([ - 0x0b5f9d12, 0x1e141b17, 0x158d7f3d, 0x143f3757, 0x1972d781, 0x042feb7c, 0x1ceec73d, 0x1e184d1e, - 0x0005046d, -]); - -/// The Ed25519 basepoint, as an `EdwardsPoint`. -/// -/// This is called `_POINT` to distinguish it from -/// `ED25519_BASEPOINT_TABLE`, which should be used for scalar -/// multiplication (it's much faster). -pub const ED25519_BASEPOINT_POINT: EdwardsPoint = EdwardsPoint { - X: FieldElement2625([ - 52811034, 25909283, 16144682, 17082669, 27570973, 30858332, 40966398, 8378388, 20764389, - 8758491, - ]), - Y: FieldElement2625([ - 40265304, 26843545, 13421772, 20132659, 26843545, 6710886, 53687091, 13421772, 40265318, - 26843545, - ]), - Z: FieldElement2625([1, 0, 0, 0, 0, 0, 0, 0, 0, 0]), - T: FieldElement2625([ - 28827043, 27438313, 39759291, 244362, 8635006, 11264893, 19351346, 13413597, 16611511, - 27139452, - ]), -}; - -/// The 8-torsion subgroup \\(\mathcal E [8]\\). -/// -/// In the case of Curve25519, it is cyclic; the \\(i\\)-th element of -/// the array is \\([i]P\\), where \\(P\\) is a point of order \\(8\\) -/// generating \\(\mathcal E[8]\\). -/// -/// Thus \\(\mathcal E[4]\\) is the points indexed by `0,2,4,6`, and -/// \\(\mathcal E[2]\\) is the points indexed by `0,4`. -/// The Ed25519 basepoint has y = 4/5. This is called `_POINT` to -/// distinguish it from `_TABLE`, which should be used for scalar -/// multiplication (it's much faster). -pub const EIGHT_TORSION: [EdwardsPoint; 8] = EIGHT_TORSION_INNER_DOC_HIDDEN; - -/// Inner item used to hide limb constants from cargo doc output. -#[doc(hidden)] -pub const EIGHT_TORSION_INNER_DOC_HIDDEN: [EdwardsPoint; 8] = [ - EdwardsPoint { - X: FieldElement2625([0, 0, 0, 0, 0, 0, 0, 0, 0, 0]), - Y: FieldElement2625([1, 0, 0, 0, 0, 0, 0, 0, 0, 0]), - Z: FieldElement2625([1, 0, 0, 0, 0, 0, 0, 0, 0, 0]), - T: FieldElement2625([0, 0, 0, 0, 0, 0, 0, 0, 0, 0]), - }, - EdwardsPoint { - X: FieldElement2625([ - 21352778, 5345713, 4660180, 25206575, 24143089, 14568123, 30185756, 21306662, 33579924, - 8345318, - ]), - Y: FieldElement2625([ - 6952903, 1265500, 60246523, 7057497, 4037696, 5447722, 35427965, 15325401, 19365852, - 31985330, - ]), - Z: FieldElement2625([1, 0, 0, 0, 0, 0, 0, 0, 0, 0]), - T: FieldElement2625([ - 41846657, 21581751, 11716001, 27684820, 48915701, 16297738, 20670665, 24995334, - 3541542, 28543251, - ]), - }, - EdwardsPoint { - X: FieldElement2625([ - 32595773, 7943725, 57730914, 30054016, 54719391, 272472, 25146209, 2005654, 66782178, - 22147949, - ]), - Y: FieldElement2625([0, 0, 0, 0, 0, 0, 0, 0, 0, 0]), - Z: FieldElement2625([1, 0, 0, 0, 0, 0, 0, 0, 0, 0]), - T: FieldElement2625([0, 0, 0, 0, 0, 0, 0, 0, 0, 0]), - }, - EdwardsPoint { - X: FieldElement2625([ - 21352778, 5345713, 4660180, 25206575, 24143089, 14568123, 30185756, 21306662, 33579924, - 8345318, - ]), - Y: FieldElement2625([ - 60155942, 32288931, 6862340, 26496934, 63071167, 28106709, 31680898, 18229030, - 47743011, 1569101, - ]), - Z: FieldElement2625([1, 0, 0, 0, 0, 0, 0, 0, 0, 0]), - T: FieldElement2625([ - 25262188, 11972680, 55392862, 5869611, 18193162, 17256693, 46438198, 8559097, 63567321, - 5011180, - ]), - }, - EdwardsPoint { - X: FieldElement2625([0, 0, 0, 0, 0, 0, 0, 0, 0, 0]), - Y: FieldElement2625([ - 67108844, 33554431, 67108863, 33554431, 67108863, 33554431, 67108863, 33554431, - 67108863, 33554431, - ]), - Z: FieldElement2625([1, 0, 0, 0, 0, 0, 0, 0, 0, 0]), - T: FieldElement2625([0, 0, 0, 0, 0, 0, 0, 0, 0, 0]), - }, - EdwardsPoint { - X: FieldElement2625([ - 45756067, 28208718, 62448683, 8347856, 42965774, 18986308, 36923107, 12247769, - 33528939, 25209113, - ]), - Y: FieldElement2625([ - 60155942, 32288931, 6862340, 26496934, 63071167, 28106709, 31680898, 18229030, - 47743011, 1569101, - ]), - Z: FieldElement2625([1, 0, 0, 0, 0, 0, 0, 0, 0, 0]), - T: FieldElement2625([ - 41846657, 21581751, 11716001, 27684820, 48915701, 16297738, 20670665, 24995334, - 3541542, 28543251, - ]), - }, - EdwardsPoint { - X: FieldElement2625([ - 34513072, 25610706, 9377949, 3500415, 12389472, 33281959, 41962654, 31548777, 326685, - 11406482, - ]), - Y: FieldElement2625([0, 0, 0, 0, 0, 0, 0, 0, 0, 0]), - Z: FieldElement2625([1, 0, 0, 0, 0, 0, 0, 0, 0, 0]), - T: FieldElement2625([0, 0, 0, 0, 0, 0, 0, 0, 0, 0]), - }, - EdwardsPoint { - X: FieldElement2625([ - 45756067, 28208718, 62448683, 8347856, 42965774, 18986308, 36923107, 12247769, - 33528939, 25209113, - ]), - Y: FieldElement2625([ - 6952903, 1265500, 60246523, 7057497, 4037696, 5447722, 35427965, 15325401, 19365852, - 31985330, - ]), - Z: FieldElement2625([1, 0, 0, 0, 0, 0, 0, 0, 0, 0]), - T: FieldElement2625([ - 25262188, 11972680, 55392862, 5869611, 18193162, 17256693, 46438198, 8559097, 63567321, - 5011180, - ]), - }, -]; - -/// Table containing precomputed multiples of the Ed25519 basepoint \\(B = (x, 4/5)\\). -pub const ED25519_BASEPOINT_TABLE: EdwardsBasepointTable = ED25519_BASEPOINT_TABLE_INNER_DOC_HIDDEN; - -/// Inner constant, used to avoid filling the docs with precomputed points. -#[doc(hidden)] -pub const ED25519_BASEPOINT_TABLE_INNER_DOC_HIDDEN: EdwardsBasepointTable = - EdwardsBasepointTable([ - LookupTable([ - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 93076338, 52752828, 29566454, 37215328, 54414518, 37569218, 94653489, 21800160, - 61029707, 35602036, - ]), - y_minus_x: FieldElement2625([ - 54563134, 934261, 64385954, 3049989, 66381436, 9406985, 12720692, 5043384, - 19500929, 18085054, - ]), - xy2d: FieldElement2625([ - 58370664, 4489569, 9688441, 18769238, 10184608, 21191052, 29287918, 11864899, - 42594502, 29115885, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 54292951, 54132516, 45527619, 11784319, 41753206, 30803714, 55390960, 29739860, - 66750418, 23343128, - ]), - y_minus_x: FieldElement2625([ - 45405608, 6903824, 27185491, 6451973, 37531140, 24000426, 51492312, 11189267, - 40279186, 28235350, - ]), - xy2d: FieldElement2625([ - 26966623, 11152617, 32442495, 15396054, 14353839, 20802097, 63980037, 24013313, - 51636816, 29387734, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 82745136, 23865874, 24204772, 25642034, 67725840, 16869169, 94896463, 52336674, - 28944398, 32004408, - ]), - y_minus_x: FieldElement2625([ - 16568933, 4717097, 55552716, 32452109, 15682895, 21747389, 16354576, 21778470, - 7689661, 11199574, - ]), - xy2d: FieldElement2625([ - 30464137, 27578307, 55329429, 17883566, 23220364, 15915852, 7512774, 10017326, - 49359771, 23634074, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 50071967, 13921891, 78054670, 27521000, 27105051, 17470053, 105291517, - 15006021, 70393432, 27277891, - ]), - y_minus_x: FieldElement2625([ - 23599295, 25248385, 55915199, 25867015, 13236773, 10506355, 7464579, 9656445, - 13059162, 10374397, - ]), - xy2d: FieldElement2625([ - 7798537, 16710257, 3033922, 2874086, 28997861, 2835604, 32406664, 29715387, - 66467155, 33453106, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 77970208, 11473153, 27284546, 35535607, 37044514, 46132292, 99976748, 48069538, - 118779423, 44373810, - ]), - y_minus_x: FieldElement2625([ - 4708026, 6336745, 20377586, 9066809, 55836755, 6594695, 41455196, 12483687, - 54440373, 5581305, - ]), - xy2d: FieldElement2625([ - 19563141, 16186464, 37722007, 4097518, 10237984, 29206317, 28542349, 13850243, - 43430843, 17738489, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 51736881, 20691677, 32573249, 4720197, 107781206, 39429941, 115029100, - 18329611, 124398787, 21468653, - ]), - y_minus_x: FieldElement2625([ - 58559652, 109982, 15149363, 2178705, 22900618, 4543417, 3044240, 17864545, - 1762327, 14866737, - ]), - xy2d: FieldElement2625([ - 48909169, 17603008, 56635573, 1707277, 49922944, 3916100, 38872452, 3959420, - 27914454, 4383652, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 72262591, 43463716, 68832610, 30776557, 97632468, 39071304, 86589715, 38784565, - 43156424, 18378665, - ]), - y_minus_x: FieldElement2625([ - 36839857, 30090922, 7665485, 10083793, 28475525, 1649722, 20654025, 16520125, - 30598449, 7715701, - ]), - xy2d: FieldElement2625([ - 28881826, 14381568, 9657904, 3680757, 46927229, 7843315, 35708204, 1370707, - 29794553, 32145132, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 14499452, 64379265, 33917749, 62854211, 95603724, 14271266, 97399599, 10876453, - 33954766, 35936157, - ]), - y_minus_x: FieldElement2625([ - 59913433, 30899068, 52378708, 462250, 39384538, 3941371, 60872247, 3696004, - 34808032, 15351954, - ]), - xy2d: FieldElement2625([ - 27431194, 8222322, 16448760, 29646437, 48401861, 11938354, 34147463, 30583916, - 29551812, 10109425, - ]), - }, - ]), - LookupTable([ - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 53451805, 20399000, 102933977, 45331528, 88556249, 40073815, 64730579, - 31926875, 77201646, 28790260, - ]), - y_minus_x: FieldElement2625([ - 27939166, 14210322, 4677035, 16277044, 44144402, 21156292, 34600109, 12005537, - 49298737, 12803509, - ]), - xy2d: FieldElement2625([ - 17228999, 17892808, 65875336, 300139, 65883994, 21839654, 30364212, 24516238, - 18016356, 4397660, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 56150002, 25864224, 4776340, 18600194, 27850027, 17952220, 40489757, 14544524, - 49631360, 34537070, - ]), - y_minus_x: FieldElement2625([ - 29253598, 15796703, 64244882, 23645547, 10057022, 3163536, 7332899, 29434304, - 46061167, 9934962, - ]), - xy2d: FieldElement2625([ - 5793284, 16271923, 42977250, 23438027, 29188559, 1206517, 52360934, 4559894, - 36984942, 22656481, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 39464893, 55615857, 83391519, 22517938, 28414020, 52096600, 24191032, 38096129, - 53770554, 39054999, - ]), - y_minus_x: FieldElement2625([ - 12650548, 32057319, 9052870, 11355358, 49428827, 25154267, 49678271, 12264342, - 10874051, 13524335, - ]), - xy2d: FieldElement2625([ - 25556948, 30508442, 714650, 2510400, 23394682, 23139102, 33119037, 5080568, - 44580805, 5376627, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 108129445, 29543378, 50095164, 30016803, 60382070, 35475328, 44787558, - 57661420, 71644630, 35123438, - ]), - y_minus_x: FieldElement2625([ - 64853442, 14606629, 45416424, 25514613, 28430648, 8775819, 36614302, 3044289, - 31848280, 12543772, - ]), - xy2d: FieldElement2625([ - 45080285, 2943892, 35251351, 6777305, 13784462, 29262229, 39731668, 31491700, - 7718481, 14474653, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 69494160, 36008644, 44477543, 33601034, 62670928, 51428448, 67765827, 26317766, - 91425031, 28300864, - ]), - y_minus_x: FieldElement2625([ - 13741529, 10911568, 33875447, 24950694, 46931033, 32521134, 33040650, 20129900, - 46379407, 8321685, - ]), - xy2d: FieldElement2625([ - 21060490, 31341688, 15712756, 29218333, 1639039, 10656336, 23845965, 21679594, - 57124405, 608371, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 53436113, 18466845, 56219170, 25997372, 61071954, 11305546, 68232832, 60328286, - 94338261, 33578318, - ]), - y_minus_x: FieldElement2625([ - 43864724, 33260226, 55364135, 14712570, 37643165, 31524814, 12797023, 27114124, - 65475458, 16678953, - ]), - xy2d: FieldElement2625([ - 37608244, 4770661, 51054477, 14001337, 7830047, 9564805, 65600720, 28759386, - 49939598, 4904952, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 91168402, 48171434, 86146020, 18514523, 86874956, 18648002, 72278074, 16191879, - 69237100, 29227598, - ]), - y_minus_x: FieldElement2625([ - 50127693, 4124965, 58568254, 22900634, 30336521, 19449185, 37302527, 916032, - 60226322, 30567899, - ]), - xy2d: FieldElement2625([ - 44477957, 12419371, 59974635, 26081060, 50629959, 16739174, 285431, 2763829, - 15736322, 4143876, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 69488197, 11839344, 62998462, 27565766, 78383161, 34349388, 67321664, 18959768, - 23527083, 17096164, - ]), - y_minus_x: FieldElement2625([ - 33431108, 22423954, 49269897, 17927531, 8909498, 8376530, 34483524, 4087880, - 51919953, 19138217, - ]), - xy2d: FieldElement2625([ - 1767664, 7197987, 53903638, 31531796, 54017513, 448825, 5799055, 4357868, - 62334673, 17231393, - ]), - }, - ]), - LookupTable([ - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 6721947, 47388255, 43585475, 32003117, 93463156, 21691110, 90474010, 29604699, - 74499753, 36314231, - ]), - y_minus_x: FieldElement2625([ - 4409022, 2052381, 23373853, 10530217, 7676779, 20668478, 21302352, 29290375, - 1244379, 20634787, - ]), - xy2d: FieldElement2625([ - 62687625, 7169618, 4982368, 30596842, 30256824, 30776892, 14086412, 9208236, - 15886429, 16489664, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 69104920, 43930080, 81455230, 46865633, 60234728, 17116020, 120524529, - 33952799, 36502408, 32841498, - ]), - y_minus_x: FieldElement2625([ - 41801399, 9795879, 64331450, 14878808, 33577029, 14780362, 13348553, 12076947, - 36272402, 5113181, - ]), - xy2d: FieldElement2625([ - 49338080, 11797795, 31950843, 13929123, 41220562, 12288343, 36767763, 26218045, - 13847710, 5387222, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 48526682, 30138214, 84933706, 64767897, 89853205, 56666252, 75871923, 37172217, - 47508201, 43925422, - ]), - y_minus_x: FieldElement2625([ - 20246567, 19185054, 22358228, 33010720, 18507282, 23140436, 14554436, 24808340, - 32232923, 16763880, - ]), - xy2d: FieldElement2625([ - 9648486, 10094563, 26416693, 14745928, 36734546, 27081810, 11094160, 15689506, - 3140038, 17044340, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 50948773, 39027126, 31895587, 38299426, 75932378, 43920116, 39884063, 43003044, - 38334409, 33920726, - ]), - y_minus_x: FieldElement2625([ - 19153450, 11523972, 56012374, 27051289, 42461232, 5420646, 28344573, 8041113, - 719605, 11671788, - ]), - xy2d: FieldElement2625([ - 8678006, 2694440, 60300850, 2517371, 4964326, 11152271, 51675948, 18287915, - 27000812, 23358879, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 119059805, 40688742, 75748150, 30739554, 59873175, 43976173, 67672928, - 38890528, 73859840, 19033405, - ]), - y_minus_x: FieldElement2625([ - 11836410, 29574944, 26297893, 16080799, 23455045, 15735944, 1695823, 24735310, - 8169719, 16220347, - ]), - xy2d: FieldElement2625([ - 48993007, 8653646, 17578566, 27461813, 59083086, 17541668, 55964556, 30926767, - 61118155, 19388398, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 43800347, 22586119, 82322091, 23473217, 36255258, 22504427, 27884328, 36401716, - 69764724, 35292826, - ]), - y_minus_x: FieldElement2625([ - 39571412, 19301410, 41772562, 25551651, 57738101, 8129820, 21651608, 30315096, - 48021414, 22549153, - ]), - xy2d: FieldElement2625([ - 1533110, 3437855, 23735889, 459276, 29970501, 11335377, 26030092, 5821408, - 10478196, 8544890, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 32173083, 50979553, 24896205, 37475929, 22579055, 63698010, 19270447, 45771905, - 84897880, 63712868, - ]), - y_minus_x: FieldElement2625([ - 36555903, 31326030, 51530034, 23407230, 13243888, 517024, 15479401, 29701199, - 30460519, 1052596, - ]), - xy2d: FieldElement2625([ - 55493970, 13323617, 32618793, 8175907, 51878691, 12596686, 27491595, 28942073, - 3179267, 24075541, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 99055914, 52742212, 62468279, 18214510, 51982886, 27514722, 52352086, 17142691, - 19072639, 24043372, - ]), - y_minus_x: FieldElement2625([ - 11685058, 11822410, 3158003, 19601838, 33402193, 29389366, 5977895, 28339415, - 473098, 5040608, - ]), - xy2d: FieldElement2625([ - 46817982, 8198641, 39698732, 11602122, 1290375, 30754672, 28326861, 1721092, - 47550222, 30422825, - ]), - }, - ]), - LookupTable([ - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 74990396, 10687936, 74687587, 7738377, 48157852, 31000479, 88929649, 8076148, - 39240368, 11538388, - ]), - y_minus_x: FieldElement2625([ - 47173198, 3899860, 18283497, 26752864, 51380203, 22305220, 8754524, 7446702, - 61432810, 5797015, - ]), - xy2d: FieldElement2625([ - 55813245, 29760862, 51326753, 25589858, 12708868, 25098233, 2014098, 24503858, - 64739691, 27677090, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 111745333, 55540121, 106535706, 34700805, 86065554, 50194990, 68301593, - 29840232, 82232482, 44365936, - ]), - y_minus_x: FieldElement2625([ - 14352079, 30134717, 48166819, 10822654, 32750596, 4699007, 67038501, 15776355, - 38222085, 21579878, - ]), - xy2d: FieldElement2625([ - 38867681, 25481956, 62129901, 28239114, 29416930, 1847569, 46454691, 17069576, - 4714546, 23953777, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 15200313, 41923004, 86787964, 15970073, 35236190, 35513882, 24611598, 29010600, - 55362987, 45894651, - ]), - y_minus_x: FieldElement2625([ - 12876937, 23074376, 33134380, 6590940, 60801088, 14872439, 9613953, 8241152, - 15370987, 9608631, - ]), - xy2d: FieldElement2625([ - 62965568, 21540023, 8446280, 33162829, 4407737, 13629032, 59383996, 15866073, - 38898243, 24740332, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 26660609, 51431209, 75502596, 33912478, 59707572, 34547419, 43204630, 34413128, - 87680086, 41974987, - ]), - y_minus_x: FieldElement2625([ - 14620696, 13067227, 51661590, 8264466, 14106269, 15080814, 33531827, 12516406, - 45534429, 21077682, - ]), - xy2d: FieldElement2625([ - 236881, 10476226, 57258, 18877408, 6472997, 2466984, 17258519, 7256740, - 8791136, 15069930, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 68385255, 24182513, 90058498, 17231624, 43615824, 61406677, 81820737, 38428660, - 36445723, 31223040, - ]), - y_minus_x: FieldElement2625([ - 5855666, 4990204, 53397016, 7294283, 59304582, 1924646, 65685689, 25642053, - 34039526, 9234252, - ]), - xy2d: FieldElement2625([ - 20590503, 24535444, 31529743, 26201766, 64402029, 10650547, 31559055, 21944845, - 18979185, 13396066, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 24474268, 38522535, 22267081, 37961786, 91172745, 25229251, 48291976, 13594781, - 33514650, 40576390, - ]), - y_minus_x: FieldElement2625([ - 55541958, 26988926, 45743778, 15928891, 40950559, 4315420, 41160136, 29637754, - 45628383, 12868081, - ]), - xy2d: FieldElement2625([ - 38473832, 13504660, 19988037, 31421671, 21078224, 6443208, 45662757, 2244499, - 54653067, 25465048, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 36513317, 13793478, 61256044, 33873567, 41385691, 60844964, 100195408, 8957936, - 51875216, 39094952, - ]), - y_minus_x: FieldElement2625([ - 55478669, 22050529, 58989363, 25911358, 2620055, 1022908, 43398120, 31985447, - 50980335, 18591624, - ]), - xy2d: FieldElement2625([ - 23152952, 775386, 27395463, 14006635, 57407746, 4649511, 1689819, 892185, - 55595587, 18348483, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 76878974, 43141169, 93604957, 37878551, 68665374, 30004407, 94562682, 38317558, - 47929249, 39421565, - ]), - y_minus_x: FieldElement2625([ - 34343820, 1927589, 31726409, 28801137, 23962433, 17534932, 27846558, 5931263, - 37359161, 17445976, - ]), - xy2d: FieldElement2625([ - 27461885, 30576896, 22380809, 1815854, 44075111, 30522493, 7283489, 18406359, - 47582163, 7734628, - ]), - }, - ]), - LookupTable([ - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 59098581, 57518046, 55988459, 39750469, 29344157, 20123547, 74694158, 30377805, - 85658360, 48856500, - ]), - y_minus_x: FieldElement2625([ - 34450527, 27383209, 59436070, 22502750, 6258877, 13504381, 10458790, 27135971, - 58236621, 8424745, - ]), - xy2d: FieldElement2625([ - 24687186, 8613276, 36441818, 30320886, 1863891, 31723888, 19206233, 7134917, - 55824382, 32725512, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 11334880, 24336410, 75134156, 46261950, 84632755, 23078360, 77352601, 18868970, - 62042829, 50053268, - ]), - y_minus_x: FieldElement2625([ - 8911542, 6887158, 57524604, 26595841, 11145640, 24010752, 17303924, 19430194, - 6536640, 10543906, - ]), - xy2d: FieldElement2625([ - 38162480, 15479762, 49642029, 568875, 65611181, 11223453, 64439674, 16928857, - 39873154, 8876770, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 41365946, 54541999, 118567760, 32707823, 101191041, 32758142, 33627041, - 15824473, 66504438, 24514614, - ]), - y_minus_x: FieldElement2625([ - 10330056, 70051, 7957388, 24551765, 9764901, 15609756, 27698697, 28664395, - 1657393, 3084098, - ]), - xy2d: FieldElement2625([ - 10477963, 26084172, 12119565, 20303627, 29016246, 28188843, 31280318, 14396151, - 36875289, 15272408, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 54820536, 36723894, 28813182, 16658753, 92225296, 27923965, 109043770, - 54472724, 42094105, 35504935, - ]), - y_minus_x: FieldElement2625([ - 40928506, 9489186, 11053416, 18808271, 36055143, 5825629, 58724558, 24786899, - 15341278, 8373727, - ]), - xy2d: FieldElement2625([ - 28685821, 7759505, 52730348, 21551571, 35137043, 4079241, 298136, 23321830, - 64230656, 15190419, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 34175950, 47360767, 52771378, 51314432, 110213106, 10940926, 75778582, - 36296824, 108184414, 60233859, - ]), - y_minus_x: FieldElement2625([ - 65528476, 21825014, 41129205, 22109408, 49696989, 22641577, 9291593, 17306653, - 54954121, 6048604, - ]), - xy2d: FieldElement2625([ - 36803549, 14843443, 1539301, 11864366, 20201677, 1900163, 13934231, 5128323, - 11213262, 9168384, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 40828313, 44562278, 19408959, 32613674, 115624762, 29225850, 62020803, - 22449281, 20470156, 50710163, - ]), - y_minus_x: FieldElement2625([ - 43972811, 9282191, 14855179, 18164354, 59746048, 19145871, 44324911, 14461607, - 14042978, 5230683, - ]), - xy2d: FieldElement2625([ - 29969548, 30812838, 50396996, 25001989, 9175485, 31085458, 21556950, 3506042, - 61174973, 21104723, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 63964099, 42299092, 19704002, 38135710, 46678177, 6830682, 45824694, 42525944, - 38569674, 48880994, - ]), - y_minus_x: FieldElement2625([ - 47644235, 10110287, 49846336, 30050539, 43608476, 1355668, 51585814, 15300987, - 46594746, 9168259, - ]), - xy2d: FieldElement2625([ - 61755510, 4488612, 43305616, 16314346, 7780487, 17915493, 38160505, 9601604, - 33087103, 24543045, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 47665675, 18041531, 46311396, 21109108, 104393280, 43783891, 39664534, - 52108332, 61111992, 49219103, - ]), - y_minus_x: FieldElement2625([ - 23294591, 16921819, 44458082, 25083453, 27844203, 11461195, 13099750, 31094076, - 18151675, 13417686, - ]), - xy2d: FieldElement2625([ - 42385932, 29377914, 35958184, 5988918, 40250079, 6685064, 1661597, 21002991, - 15271675, 18101767, - ]), - }, - ]), - LookupTable([ - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 78541887, 20325766, 75348494, 28274914, 65123427, 32828713, 48410099, 35721975, - 60187562, 20114249, - ]), - y_minus_x: FieldElement2625([ - 35672693, 15575145, 30436815, 12192228, 44645511, 9395378, 57191156, 24915434, - 12215109, 12028277, - ]), - xy2d: FieldElement2625([ - 14098381, 6555944, 23007258, 5757252, 51681032, 20603929, 30123439, 4617780, - 50208775, 32898803, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 63082644, 51868028, 79002030, 47273095, 52299401, 35401816, 51288864, 43708440, - 91082124, 20869957, - ]), - y_minus_x: FieldElement2625([ - 40577025, 29858441, 65199965, 2534300, 35238307, 17004076, 18341389, 22134481, - 32013173, 23450893, - ]), - xy2d: FieldElement2625([ - 41629544, 10876442, 55337778, 18929291, 54739296, 1838103, 21911214, 6354752, - 4425632, 32716610, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 56675456, 18941465, 89338721, 30463384, 53917697, 34331160, 116802352, - 55088400, 71833867, 47599401, - ]), - y_minus_x: FieldElement2625([ - 19268631, 26250011, 1555348, 8692754, 45634805, 23643767, 6347389, 32142648, - 47586572, 17444675, - ]), - xy2d: FieldElement2625([ - 42244775, 12986007, 56209986, 27995847, 55796492, 33405905, 19541417, 8180106, - 9282262, 10282508, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 108012627, 37982977, 58447667, 20360168, 71207265, 52943606, 15522533, 8372215, - 72651459, 22851748, - ]), - y_minus_x: FieldElement2625([ - 56546323, 14895632, 26814552, 16880582, 49628109, 31065071, 64326972, 6993760, - 49014979, 10114654, - ]), - xy2d: FieldElement2625([ - 47001790, 32625013, 31422703, 10427861, 59998115, 6150668, 38017109, 22025285, - 25953724, 33448274, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 62874448, 59069571, 57989737, 36600431, 69210472, 54501569, 86498882, 39648727, - 63793584, 46385556, - ]), - y_minus_x: FieldElement2625([ - 51110167, 7578151, 5310217, 14408357, 33560244, 33329692, 31575953, 6326196, - 7381791, 31132593, - ]), - xy2d: FieldElement2625([ - 46206085, 3296810, 24736065, 17226043, 18374253, 7318640, 6295303, 8082724, - 51746375, 12339663, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 27724736, 35845589, 73197064, 19369633, 68901590, 39412065, 80957277, 15768921, - 92200031, 14856293, - ]), - y_minus_x: FieldElement2625([ - 48242193, 8331042, 24373479, 8541013, 66406866, 24284974, 12927299, 20858939, - 44926390, 24541532, - ]), - xy2d: FieldElement2625([ - 55685435, 28132841, 11632844, 3405020, 30536730, 21880393, 39848098, 13866389, - 30146206, 9142070, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 71032974, 18246915, 120400605, 23499470, 79400683, 32886065, 39406089, 9326383, - 58871006, 37725725, - ]), - y_minus_x: FieldElement2625([ - 51186905, 16037936, 6713787, 16606682, 45496729, 2790943, 26396185, 3731949, - 345228, 28091483, - ]), - xy2d: FieldElement2625([ - 45781307, 13448258, 25284571, 1143661, 20614966, 24705045, 2031538, 21163201, - 50855680, 19972348, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 98125037, 16832002, 93480255, 52657630, 62081513, 14854136, 17477601, 37397089, - 28012649, 50703444, - ]), - y_minus_x: FieldElement2625([ - 62033029, 9368965, 58546785, 28953529, 51858910, 6970559, 57918991, 16292056, - 58241707, 3507939, - ]), - xy2d: FieldElement2625([ - 29439664, 3537914, 23333589, 6997794, 49553303, 22536363, 51899661, 18503164, - 57943934, 6580395, - ]), - }, - ]), - LookupTable([ - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 54922984, 59429075, 83547131, 10826159, 58412047, 27318820, 84969307, 24280585, - 65013061, 42858998, - ]), - y_minus_x: FieldElement2625([ - 20714545, 29217521, 29088194, 7406487, 11426967, 28458727, 14792666, 18945815, - 5289420, 33077305, - ]), - xy2d: FieldElement2625([ - 50443312, 22903641, 60948518, 20248671, 9192019, 31751970, 17271489, 12349094, - 26939669, 29802138, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 54218947, 9373457, 98704712, 16374214, 21471720, 13221525, 39825369, 54760304, - 63410056, 33672318, - ]), - y_minus_x: FieldElement2625([ - 22263325, 26994382, 3984569, 22379786, 51994855, 32987646, 28311252, 5358056, - 43789084, 541963, - ]), - xy2d: FieldElement2625([ - 16259200, 3261970, 2309254, 18019958, 50223152, 28972515, 24134069, 16848603, - 53771797, 20002236, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 76487005, 20414245, 111371745, 20809166, 95307144, 59864765, 64709178, - 32837080, 67799289, 48430675, - ]), - y_minus_x: FieldElement2625([ - 24977353, 33240048, 58884894, 20089345, 28432342, 32378079, 54040059, 21257083, - 44727879, 6618998, - ]), - xy2d: FieldElement2625([ - 65570671, 11685645, 12944378, 13682314, 42719353, 19141238, 8044828, 19737104, - 32239828, 27901670, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 48505798, 38317421, 66182613, 42439735, 105805247, 30367115, 76890510, - 23204372, 32779358, 5095274, - ]), - y_minus_x: FieldElement2625([ - 34100715, 28339925, 34843976, 29869215, 9460460, 24227009, 42507207, 14506723, - 21639561, 30924196, - ]), - xy2d: FieldElement2625([ - 50707921, 20442216, 25239337, 15531969, 3987758, 29055114, 65819361, 26690896, - 17874573, 558605, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 53508716, 10240080, 76280747, 16131052, 46239610, 43154131, 100608350, - 38634582, 69194755, 38674192, - ]), - y_minus_x: FieldElement2625([ - 44903700, 31034903, 50727262, 414690, 42089314, 2170429, 30634760, 25190818, - 35108870, 27794547, - ]), - xy2d: FieldElement2625([ - 60263160, 15791201, 8550074, 32241778, 29928808, 21462176, 27534429, 26362287, - 44757485, 12961481, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 42616785, 57538092, 10368192, 11582341, 110820435, 31309143, 83642793, 8206995, - 104023076, 28394792, - ]), - y_minus_x: FieldElement2625([ - 55987368, 30172197, 2307365, 6362031, 66973409, 8868176, 50273234, 7031274, - 7589640, 8945490, - ]), - xy2d: FieldElement2625([ - 34956097, 8917966, 6661220, 21876816, 65916803, 17761038, 7251488, 22372252, - 24099108, 19098262, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 72128384, 25646961, 71352990, 18840075, 107284455, 40007595, 47990681, - 20265406, 127985831, 56828126, - ]), - y_minus_x: FieldElement2625([ - 10853575, 10721687, 26480089, 5861829, 44113045, 1972174, 65242217, 22996533, - 63745412, 27113307, - ]), - xy2d: FieldElement2625([ - 50106456, 5906789, 221599, 26991285, 7828207, 20305514, 24362660, 31546264, - 53242455, 7421391, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 75248772, 27007934, 99366509, 27663885, 97484582, 1886180, 113042620, 48995682, - 95935221, 29431402, - ]), - y_minus_x: FieldElement2625([ - 6267067, 9695052, 7709135, 16950835, 34239795, 31668296, 14795159, 25714308, - 13746020, 31812384, - ]), - xy2d: FieldElement2625([ - 28584883, 7787108, 60375922, 18503702, 22846040, 25983196, 63926927, 33190907, - 4771361, 25134474, - ]), - }, - ]), - LookupTable([ - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 92058101, 6376278, 39642383, 25379823, 48462709, 23623825, 100652432, 54967168, - 70678489, 44897024, - ]), - y_minus_x: FieldElement2625([ - 26514970, 4740088, 27912651, 3697550, 19331575, 22082093, 6809885, 4608608, - 7325975, 18753361, - ]), - xy2d: FieldElement2625([ - 55490446, 19000001, 42787651, 7655127, 65739590, 5214311, 39708324, 10258389, - 49462170, 25367739, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 11431185, 49377439, 93679108, 47883555, 85138853, 38350513, 35662684, 49135095, - 76389221, 29580744, - ]), - y_minus_x: FieldElement2625([ - 66948081, 23228174, 44253547, 29249434, 46247496, 19933429, 34297962, 22372809, - 51563772, 4387440, - ]), - xy2d: FieldElement2625([ - 46309467, 12194511, 3937617, 27748540, 39954043, 9340369, 42594872, 8548136, - 20617071, 26072431, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 66170039, 29623845, 58394552, 49679149, 91711988, 27329038, 53333511, 55233041, - 91454545, 10325459, - ]), - y_minus_x: FieldElement2625([ - 47253587, 31985546, 44906155, 8714033, 14007766, 6928528, 16318175, 32543743, - 4766742, 3552007, - ]), - xy2d: FieldElement2625([ - 45357481, 16823515, 1351762, 32751011, 63099193, 3950934, 3217514, 14481909, - 10988822, 29559670, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 15564288, 19242862, 70210106, 39238579, 97555643, 25503075, 79785990, 27049088, - 58813011, 46850436, - ]), - y_minus_x: FieldElement2625([ - 57666574, 6624295, 36809900, 21640754, 62437882, 31497052, 31521203, 9614054, - 37108040, 12074673, - ]), - xy2d: FieldElement2625([ - 4771172, 33419193, 14290748, 20464580, 27992297, 14998318, 65694928, 31997715, - 29832612, 17163397, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 7064865, 59567690, 115055764, 62041325, 48217593, 30641695, 92934105, 38847728, - 39986203, 46656021, - ]), - y_minus_x: FieldElement2625([ - 64810282, 2439669, 59642254, 1719964, 39841323, 17225986, 32512468, 28236839, - 36752793, 29363474, - ]), - xy2d: FieldElement2625([ - 37102324, 10162315, 33928688, 3981722, 50626726, 20484387, 14413973, 9515896, - 19568978, 9628812, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 33053784, 33753789, 83003454, 35137490, 94489106, 28973996, 49269969, 61002024, - 60817076, 36992171, - ]), - y_minus_x: FieldElement2625([ - 48129987, 3884492, 19469877, 12726490, 15913552, 13614290, 44147131, 70103, - 7463304, 4176122, - ]), - xy2d: FieldElement2625([ - 39984863, 10659916, 11482427, 17484051, 12771466, 26919315, 34389459, 28231680, - 24216881, 5944158, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 76002989, 41005405, 64444714, 57343111, 106137209, 21165315, 19345745, - 48235228, 78741856, 5847884, - ]), - y_minus_x: FieldElement2625([ - 26942781, 31239115, 9129563, 28647825, 26024104, 11769399, 55590027, 6367193, - 57381634, 4782139, - ]), - xy2d: FieldElement2625([ - 19916442, 28726022, 44198159, 22140040, 25606323, 27581991, 33253852, 8220911, - 6358847, 31680575, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 67910273, 31472729, 16569427, 44619599, 29875703, 33651059, 75017251, 29073951, - 53570360, 34941586, - ]), - y_minus_x: FieldElement2625([ - 19646058, 5720633, 55692158, 12814208, 11607948, 12749789, 14147075, 15156355, - 45242033, 11835259, - ]), - xy2d: FieldElement2625([ - 19299512, 1155910, 28703737, 14890794, 2925026, 7269399, 26121523, 15467869, - 40548314, 5052482, - ]), - }, - ]), - LookupTable([ - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 64091413, 43612637, 69089700, 37518674, 22160965, 12322533, 60677741, 20936246, - 12228556, 26550755, - ]), - y_minus_x: FieldElement2625([ - 32944382, 14922211, 44263970, 5188527, 21913450, 24834489, 4001464, 13238564, - 60994061, 8653814, - ]), - xy2d: FieldElement2625([ - 22865569, 28901697, 27603667, 21009037, 14348957, 8234005, 24808405, 5719875, - 28483275, 2841751, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 117796741, 32441125, 66781144, 21446575, 21886281, 51556090, 65220896, - 33238773, 87040921, 20815228, - ]), - y_minus_x: FieldElement2625([ - 55452759, 10087520, 58243976, 28018288, 47830290, 30498519, 3999227, 13239134, - 62331395, 19644223, - ]), - xy2d: FieldElement2625([ - 1382174, 21859713, 17266789, 9194690, 53784508, 9720080, 20403944, 11284705, - 53095046, 3093229, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 83759766, 56070931, 66044684, 35125060, 58779117, 40907184, 66806439, 16271224, - 43059443, 26862581, - ]), - y_minus_x: FieldElement2625([ - 45197768, 27626490, 62497547, 27994275, 35364760, 22769138, 24123613, 15193618, - 45456747, 16815042, - ]), - xy2d: FieldElement2625([ - 57172930, 29264984, 41829040, 4372841, 2087473, 10399484, 31870908, 14690798, - 17361620, 11864968, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 55801216, 39764803, 80315437, 39360751, 105200035, 19587230, 54777658, - 26067830, 41530403, 50868174, - ]), - y_minus_x: FieldElement2625([ - 14668443, 21284197, 26039038, 15305210, 25515617, 4542480, 10453892, 6577524, - 9145645, 27110552, - ]), - xy2d: FieldElement2625([ - 5974855, 3053895, 57675815, 23169240, 35243739, 3225008, 59136222, 3936127, - 61456591, 30504127, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 97734231, 28825031, 41552902, 20761565, 46624288, 41249530, 17097187, 50805368, - 106217947, 35358062, - ]), - y_minus_x: FieldElement2625([ - 63555773, 9865098, 61880298, 4272700, 61435032, 16864731, 14911343, 12196514, - 45703375, 7047411, - ]), - xy2d: FieldElement2625([ - 20093258, 9920966, 55970670, 28210574, 13161586, 12044805, 34252013, 4124600, - 34765036, 23296865, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 46320021, 14084653, 53577151, 41396578, 19119037, 19731827, 71861240, 24839791, - 45429205, 35842469, - ]), - y_minus_x: FieldElement2625([ - 40289628, 30270716, 29965058, 3039786, 52635099, 2540456, 29457502, 14625692, - 42289247, 12570231, - ]), - xy2d: FieldElement2625([ - 66045306, 22002608, 16920317, 12494842, 1278292, 27685323, 45948920, 30055751, - 55134159, 4724942, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 85069815, 21778897, 62967895, 23851901, 58232301, 32143814, 54201480, 24894499, - 104641427, 35458286, - ]), - y_minus_x: FieldElement2625([ - 23134274, 19275300, 56426866, 31942495, 20684484, 15770816, 54119114, 3190295, - 26955097, 14109738, - ]), - xy2d: FieldElement2625([ - 15308788, 5320727, 36995055, 19235554, 22902007, 7767164, 29425325, 22276870, - 31960941, 11934971, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 39713134, 41990227, 71218507, 12222638, 109589860, 14818667, 87747037, - 38429459, 77600255, 34934149, - ]), - y_minus_x: FieldElement2625([ - 53949449, 9197840, 3875503, 24618324, 65725151, 27674630, 33518458, 16176658, - 21432314, 12180697, - ]), - xy2d: FieldElement2625([ - 55321537, 11500837, 13787581, 19721842, 44678184, 10140204, 1465425, 12689540, - 56807545, 19681548, - ]), - }, - ]), - LookupTable([ - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 72522936, 18168390, 46101199, 43198001, 79943833, 34740580, 64485947, 32212200, - 26128230, 39587344, - ]), - y_minus_x: FieldElement2625([ - 40771450, 19788269, 32496024, 19900513, 17847800, 20885276, 3604024, 8316894, - 41233830, 23117073, - ]), - xy2d: FieldElement2625([ - 3296484, 6223048, 24680646, 21307972, 44056843, 5903204, 58246567, 28915267, - 12376616, 3188849, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 29190450, 18895386, 27549112, 32370916, 70628929, 22857130, 32049514, 26245319, - 50999629, 57256556, - ]), - y_minus_x: FieldElement2625([ - 52364359, 24245275, 735817, 32955454, 46701176, 28496527, 25246077, 17758763, - 18640740, 32593455, - ]), - xy2d: FieldElement2625([ - 60180029, 17123636, 10361373, 5642961, 4910474, 12345252, 35470478, 33060001, - 10530746, 1053335, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 104951742, 52922057, 120679510, 54991489, 47651803, 56453479, 102755357, - 30605445, 24018830, 48581076, - ]), - y_minus_x: FieldElement2625([ - 44516310, 30409154, 64819587, 5953842, 53668675, 9425630, 25310643, 13003497, - 64794073, 18408815, - ]), - xy2d: FieldElement2625([ - 39688860, 32951110, 59064879, 31885314, 41016598, 13987818, 39811242, 187898, - 43942445, 31022696, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 45364447, 19743956, 68953703, 38575859, 123783328, 17642957, 76825530, - 49821353, 62038646, 34280530, - ]), - y_minus_x: FieldElement2625([ - 29370903, 27500434, 7334070, 18212173, 9385286, 2247707, 53446902, 28714970, - 30007387, 17731091, - ]), - xy2d: FieldElement2625([ - 66172485, 16086690, 23751945, 33011114, 65941325, 28365395, 9137108, 730663, - 9835848, 4555336, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 43732410, 34964877, 44855110, 54209249, 97976497, 49381408, 17693929, 34099128, - 55123565, 45977077, - ]), - y_minus_x: FieldElement2625([ - 31117226, 21338698, 53606025, 6561946, 57231997, 20796761, 61990178, 29457725, - 29120152, 13924425, - ]), - xy2d: FieldElement2625([ - 49707966, 19321222, 19675798, 30819676, 56101901, 27695611, 57724924, 22236731, - 7240930, 33317044, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 35747087, 22207651, 119210280, 27698212, 111764387, 54956091, 68331198, - 37943914, 70402500, 51557120, - ]), - y_minus_x: FieldElement2625([ - 50424044, 19110186, 11038543, 11054958, 53307689, 30215898, 42789283, 7733546, - 12796905, 27218610, - ]), - xy2d: FieldElement2625([ - 58349431, 22736595, 41689999, 10783768, 36493307, 23807620, 38855524, 3647835, - 3222231, 22393970, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 85714958, 35247531, 108769341, 51938590, 71221215, 43599452, 23603892, - 31506198, 59558087, 36039416, - ]), - y_minus_x: FieldElement2625([ - 9255298, 30423235, 54952701, 32550175, 13098012, 24339566, 16377219, 31451620, - 47306788, 30519729, - ]), - xy2d: FieldElement2625([ - 44379556, 7496159, 61366665, 11329248, 19991973, 30206930, 35390715, 9936965, - 37011176, 22935634, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 88987435, 28553134, 71447199, 47198328, 64071998, 13160959, 86817760, 5415496, - 59748361, 29445138, - ]), - y_minus_x: FieldElement2625([ - 27736842, 10103576, 12500508, 8502413, 63695848, 23920873, 10436917, 32004156, - 43449720, 25422331, - ]), - xy2d: FieldElement2625([ - 19492550, 21450067, 37426887, 32701801, 63900692, 12403436, 30066266, 8367329, - 13243957, 8709688, - ]), - }, - ]), - LookupTable([ - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 79123950, 36355692, 95306994, 10151020, 91926984, 28811298, 55914672, 27908697, - 72259831, 40828617, - ]), - y_minus_x: FieldElement2625([ - 2831347, 21062286, 1478974, 6122054, 23825128, 20820846, 31097298, 6083058, - 31021603, 23760822, - ]), - xy2d: FieldElement2625([ - 64578913, 31324785, 445612, 10720828, 53259337, 22048494, 43601132, 16354464, - 15067285, 19406725, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 74949787, 47592304, 100852864, 49488446, 66380650, 29911725, 88512851, - 34612017, 47729401, 21151211, - ]), - y_minus_x: FieldElement2625([ - 915865, 17085158, 15608284, 24765302, 42751837, 6060029, 49737545, 8410996, - 59888403, 16527024, - ]), - xy2d: FieldElement2625([ - 32922597, 32997445, 20336073, 17369864, 10903704, 28169945, 16957573, 52992, - 23834301, 6588044, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 32752011, 44787382, 70490858, 24839565, 22652987, 22810329, 17159698, 50243539, - 46794283, 32248439, - ]), - y_minus_x: FieldElement2625([ - 62419196, 9166775, 41398568, 22707125, 11576751, 12733943, 7924251, 30802151, - 1976122, 26305405, - ]), - xy2d: FieldElement2625([ - 21251203, 16309901, 64125849, 26771309, 30810596, 12967303, 156041, 30183180, - 12331344, 25317235, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 75760459, 29077399, 118132091, 28557436, 80111370, 36505236, 96163290, - 28447461, 77116999, 28886530, - ]), - y_minus_x: FieldElement2625([ - 31486061, 15114593, 52847614, 12951353, 14369431, 26166587, 16347320, 19892343, - 8684154, 23021480, - ]), - xy2d: FieldElement2625([ - 19443825, 11385320, 24468943, 23895364, 43189605, 2187568, 40845657, 27467510, - 31316347, 14219878, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 38514355, 1193784, 99354083, 11392484, 31092169, 49277233, 94254877, 40546840, - 29126554, 42761822, - ]), - y_minus_x: FieldElement2625([ - 32382916, 1110093, 18477781, 11028262, 39697101, 26006320, 62128346, 10843781, - 59151264, 19118701, - ]), - xy2d: FieldElement2625([ - 2814918, 7836403, 27519878, 25686276, 46214848, 22000742, 45614304, 8550129, - 28346258, 1994730, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 47530546, 41639976, 53108344, 29605809, 69894701, 17323124, 47591912, 40729325, - 22628101, 41669612, - ]), - y_minus_x: FieldElement2625([ - 36703732, 955510, 55975026, 18476362, 34661776, 20276352, 41457285, 3317159, - 57165847, 930271, - ]), - xy2d: FieldElement2625([ - 51805164, 26720662, 28856489, 1357446, 23421993, 1057177, 24091212, 32165462, - 44343487, 22903716, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 44357614, 28250434, 54201256, 54339997, 51297351, 25757378, 52269845, 50554643, - 65241844, 41953401, - ]), - y_minus_x: FieldElement2625([ - 35139535, 2106402, 62372504, 1362500, 12813763, 16200670, 22981545, 27263159, - 18009407, 17781660, - ]), - xy2d: FieldElement2625([ - 49887941, 24009210, 39324209, 14166834, 29815394, 7444469, 29551787, 29827013, - 19288548, 1325865, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 82209002, 51273111, 110293748, 32549332, 107767535, 49063838, 79485593, - 30075285, 100274970, 25511681, - ]), - y_minus_x: FieldElement2625([ - 20909212, 13023121, 57899112, 16251777, 61330449, 25459517, 12412150, 10018715, - 2213263, 19676059, - ]), - xy2d: FieldElement2625([ - 32529814, 22479743, 30361438, 16864679, 57972923, 1513225, 22922121, 6382134, - 61341936, 8371347, - ]), - }, - ]), - LookupTable([ - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 77032307, 44825931, 79725657, 37099153, 104219359, 31832804, 12891686, - 25361300, 40665920, 44040575, - ]), - y_minus_x: FieldElement2625([ - 44511638, 26541766, 8587002, 25296571, 4084308, 20584370, 361725, 2610596, - 43187334, 22099236, - ]), - xy2d: FieldElement2625([ - 5408392, 32417741, 62139741, 10561667, 24145918, 14240566, 31319731, 29318891, - 19985174, 30118346, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 53114388, 50171252, 81658109, 36895530, 99264821, 13648975, 49531796, 8849296, - 67173894, 41925115, - ]), - y_minus_x: FieldElement2625([ - 58787919, 21504805, 31204562, 5839400, 46481576, 32497154, 47665921, 6922163, - 12743482, 23753914, - ]), - xy2d: FieldElement2625([ - 64747493, 12678784, 28815050, 4759974, 43215817, 4884716, 23783145, 11038569, - 18800704, 255233, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 61839168, 31780545, 13957885, 41545147, 23132994, 34283205, 80502710, 42621388, - 86367551, 52355070, - ]), - y_minus_x: FieldElement2625([ - 64172210, 22726896, 56676774, 14516792, 63468078, 4372540, 35173943, 2209389, - 65584811, 2055793, - ]), - xy2d: FieldElement2625([ - 580882, 16705327, 5468415, 30871414, 36182444, 18858431, 59905517, 24560042, - 37087844, 7394434, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 90947654, 35377159, 118479284, 48797157, 75426955, 29821327, 45436683, - 30062226, 62287122, 48354352, - ]), - y_minus_x: FieldElement2625([ - 13345610, 9759151, 3371034, 17416641, 16353038, 8577942, 31129804, 13496856, - 58052846, 7402517, - ]), - xy2d: FieldElement2625([ - 2286874, 29118501, 47066405, 31546095, 53412636, 5038121, 11006906, 17794080, - 8205060, 1607563, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 81522931, 25552299, 70440693, 63900646, 89358013, 27960243, 85473524, 30647473, - 30019586, 24525154, - ]), - y_minus_x: FieldElement2625([ - 39420813, 1585952, 56333811, 931068, 37988643, 22552112, 52698034, 12029092, - 9944378, 8024, - ]), - xy2d: FieldElement2625([ - 4368715, 29844802, 29874199, 18531449, 46878477, 22143727, 50994269, 32555346, - 58966475, 5640029, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 77408455, 13746482, 11661824, 16234854, 74739102, 5998373, 76918751, 16859867, - 82328661, 19226648, - ]), - y_minus_x: FieldElement2625([ - 27425505, 27835351, 3055005, 10660664, 23458024, 595578, 51710259, 32381236, - 48766680, 9742716, - ]), - xy2d: FieldElement2625([ - 6744077, 2427284, 26042789, 2720740, 66260958, 1118973, 32324614, 7406442, - 12420155, 1994844, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 81121366, 62084143, 115833273, 23975961, 107732385, 29617991, 121184249, - 22644627, 91428792, 27108098, - ]), - y_minus_x: FieldElement2625([ - 16412671, 29047065, 10772640, 15929391, 50040076, 28895810, 10555944, 23070383, - 37006495, 28815383, - ]), - xy2d: FieldElement2625([ - 22397363, 25786748, 57815702, 20761563, 17166286, 23799296, 39775798, 6199365, - 21880021, 21303672, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 62825538, 5368522, 35991846, 41717820, 103894664, 36763558, 83666014, 42445160, - 75949308, 38512191, - ]), - y_minus_x: FieldElement2625([ - 51661137, 709326, 60189418, 22684253, 37330941, 6522331, 45388683, 12130071, - 52312361, 5005756, - ]), - xy2d: FieldElement2625([ - 64994094, 19246303, 23019041, 15765735, 41839181, 6002751, 10183197, 20315106, - 50713577, 31378319, - ]), - }, - ]), - LookupTable([ - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 115191953, 35186435, 80575154, 59113763, 110577275, 16573535, 35094956, - 30497327, 22208661, 35554900, - ]), - y_minus_x: FieldElement2625([ - 3065054, 32141671, 41510189, 33192999, 49425798, 27851016, 58944651, 11248526, - 63417650, 26140247, - ]), - xy2d: FieldElement2625([ - 10379208, 27508878, 8877318, 1473647, 37817580, 21046851, 16690914, 2553332, - 63976176, 16400288, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 82825513, 34808697, 115745037, 41000704, 58659945, 6344163, 45011593, 26268851, - 26894936, 42686498, - ]), - y_minus_x: FieldElement2625([ - 24158868, 12938817, 11085297, 25376834, 39045385, 29097348, 36532400, 64451, - 60291780, 30861549, - ]), - xy2d: FieldElement2625([ - 13488534, 7794716, 22236231, 5989356, 25426474, 20976224, 2350709, 30135921, - 62420857, 2364225, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 83443897, 9132433, 92749446, 40233319, 68834491, 42072368, 55301839, 21856974, - 15445874, 25756331, - ]), - y_minus_x: FieldElement2625([ - 29004188, 25687351, 28661401, 32914020, 54314860, 25611345, 31863254, 29418892, - 66830813, 17795152, - ]), - xy2d: FieldElement2625([ - 60986784, 18687766, 38493958, 14569918, 56250865, 29962602, 10343411, 26578142, - 37280576, 22738620, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 94190495, 37018415, 14099041, 29036828, 68725166, 27348827, 96651499, 15372178, - 84402661, 34515140, - ]), - y_minus_x: FieldElement2625([ - 20263915, 11434237, 61343429, 11236809, 13505955, 22697330, 50997518, 6493121, - 47724353, 7639713, - ]), - xy2d: FieldElement2625([ - 64278047, 18715199, 25403037, 25339236, 58791851, 17380732, 18006286, 17510682, - 29994676, 17746311, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 76878673, 38757082, 110060329, 19923038, 106166724, 21992806, 42495722, - 53248081, 35924287, 34263895, - ]), - y_minus_x: FieldElement2625([ - 12286395, 13076066, 45333675, 32377809, 42105665, 4057651, 35090736, 24663557, - 16102006, 13205847, - ]), - xy2d: FieldElement2625([ - 13733362, 5599946, 10557076, 3195751, 61550873, 8536969, 41568694, 8525971, - 10151379, 10394400, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 71133505, 17416880, 89545125, 12276533, 58009849, 64422764, 86807091, 11743038, - 100915394, 42488844, - ]), - y_minus_x: FieldElement2625([ - 51229064, 29029191, 58528116, 30620370, 14634844, 32856154, 57659786, 3137093, - 55571978, 11721157, - ]), - xy2d: FieldElement2625([ - 17555920, 28540494, 8268605, 2331751, 44370049, 9761012, 9319229, 8835153, - 57903375, 32274386, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 66647436, 25724417, 87722981, 16688287, 59594098, 28747312, 89409167, 34059860, - 73217325, 27371016, - ]), - y_minus_x: FieldElement2625([ - 62038564, 12367916, 36445330, 3234472, 32617080, 25131790, 29880582, 20071101, - 40210373, 25686972, - ]), - xy2d: FieldElement2625([ - 35133562, 5726538, 26934134, 10237677, 63935147, 32949378, 24199303, 3795095, - 7592688, 18562353, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 21594413, 18590204, 84575271, 63031641, 32537082, 36294330, 73516586, 12018832, - 38852812, 37852843, - ]), - y_minus_x: FieldElement2625([ - 46458361, 21592935, 39872588, 570497, 3767144, 31836892, 13891941, 31985238, - 13717173, 10805743, - ]), - xy2d: FieldElement2625([ - 52432215, 17910135, 15287173, 11927123, 24177847, 25378864, 66312432, 14860608, - 40169934, 27690595, - ]), - }, - ]), - LookupTable([ - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 80071405, 38866230, 57048095, 45212711, 85964149, 25600230, 80395126, 54300159, - 62727806, 9882021, - ]), - y_minus_x: FieldElement2625([ - 18512060, 11319350, 46985740, 15090308, 18818594, 5271736, 44380960, 3666878, - 43141434, 30255002, - ]), - xy2d: FieldElement2625([ - 60319844, 30408388, 16192428, 13241070, 15898607, 19348318, 57023983, 26893321, - 64705764, 5276064, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 97278672, 28236783, 93415069, 55358004, 94923826, 40623698, 74261714, 37239413, - 68558087, 13082860, - ]), - y_minus_x: FieldElement2625([ - 10342807, 3098505, 2119311, 193222, 25702612, 12233820, 23697382, 15056736, - 46092426, 25352431, - ]), - xy2d: FieldElement2625([ - 33958735, 3261607, 22745853, 7948688, 19370557, 18376767, 40936887, 6482813, - 56808784, 22494330, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 32869439, 61700319, 25609741, 49233102, 56421094, 51637792, 26112419, 36075440, - 44444575, 40459246, - ]), - y_minus_x: FieldElement2625([ - 29506904, 4457497, 3377935, 23757988, 36598817, 12935079, 1561737, 3841096, - 38105225, 26896789, - ]), - xy2d: FieldElement2625([ - 10340844, 26924055, 48452231, 31276001, 12621150, 20215377, 30878496, 21730062, - 41524312, 5181965, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 25940096, 20896407, 17324187, 56801490, 58437394, 15029093, 91505116, 17103509, - 64786011, 21165857, - ]), - y_minus_x: FieldElement2625([ - 45343161, 9916822, 65808455, 4079497, 66080518, 11909558, 1782390, 12641087, - 20603771, 26992690, - ]), - xy2d: FieldElement2625([ - 48226577, 21881051, 24849421, 11501709, 13161720, 28785558, 1925522, 11914390, - 4662781, 7820689, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 79349895, 33128449, 75241554, 42948365, 32846759, 31954812, 29749455, 45727356, - 83245615, 48818451, - ]), - y_minus_x: FieldElement2625([ - 56758909, 18873868, 58896884, 2330219, 49446315, 19008651, 10658212, 6671822, - 19012087, 3772772, - ]), - xy2d: FieldElement2625([ - 3753511, 30133366, 10617073, 2028709, 14841030, 26832768, 28718731, 17791548, - 20527770, 12988982, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 52286341, 27757162, 63400876, 12689772, 66209881, 22639565, 110034681, - 56543919, 70408527, 54683910, - ]), - y_minus_x: FieldElement2625([ - 50331161, 18301130, 57466446, 4978982, 3308785, 8755439, 6943197, 6461331, - 41525717, 8991217, - ]), - xy2d: FieldElement2625([ - 49882601, 1816361, 65435576, 27467992, 31783887, 25378441, 34160718, 7417949, - 36866577, 1507264, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 29692644, 40384323, 56610063, 37889327, 88054838, 21647935, 38221255, 41763822, - 14606361, 22907359, - ]), - y_minus_x: FieldElement2625([ - 63627275, 8707080, 32188102, 5672294, 22096700, 1711240, 34088169, 9761486, - 4170404, 31469107, - ]), - xy2d: FieldElement2625([ - 55521375, 14855944, 62981086, 32022574, 40459774, 15084045, 22186522, 16002000, - 52832027, 25153633, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 62297389, 47315460, 35404986, 31070512, 63796392, 41423478, 59995291, 23934339, - 80349708, 44520301, - ]), - y_minus_x: FieldElement2625([ - 59366301, 25297669, 52340529, 19898171, 43876480, 12387165, 4498947, 14147411, - 29514390, 4302863, - ]), - xy2d: FieldElement2625([ - 53695440, 21146572, 20757301, 19752600, 14785142, 8976368, 62047588, 31410058, - 17846987, 19582505, - ]), - }, - ]), - LookupTable([ - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 64864393, 32799703, 62511833, 32488122, 60861691, 35009730, 112569999, - 24339641, 61886162, 46204698, - ]), - y_minus_x: FieldElement2625([ - 57202067, 17484121, 21134159, 12198166, 40044289, 708125, 387813, 13770293, - 47974538, 10958662, - ]), - xy2d: FieldElement2625([ - 22470984, 12369526, 23446014, 28113323, 45588061, 23855708, 55336367, 21979976, - 42025033, 4271861, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 109048144, 57055220, 47199530, 48916026, 61124505, 35713623, 67184238, - 62830334, 101691505, 42024103, - ]), - y_minus_x: FieldElement2625([ - 15854951, 4148314, 58214974, 7259001, 11666551, 13824734, 36577666, 2697371, - 24154791, 24093489, - ]), - xy2d: FieldElement2625([ - 15446137, 17747788, 29759746, 14019369, 30811221, 23944241, 35526855, 12840103, - 24913809, 9815020, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 62399559, 27940162, 35267365, 21265538, 52665326, 44353845, 125114051, - 46993199, 85843991, 43020669, - ]), - y_minus_x: FieldElement2625([ - 11933045, 9281483, 5081055, 28370608, 64480701, 28648802, 59381042, 22658328, - 44380208, 16199063, - ]), - xy2d: FieldElement2625([ - 14576810, 379472, 40322331, 25237195, 37682355, 22741457, 67006097, 1876698, - 30801119, 2164795, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 15995067, 36754305, 13672554, 13712240, 47730029, 62461217, 121136116, - 51612593, 53616055, 34822483, - ]), - y_minus_x: FieldElement2625([ - 56818250, 29895392, 63822271, 10948817, 23037027, 3794475, 63638526, 20954210, - 50053494, 3565903, - ]), - xy2d: FieldElement2625([ - 29210069, 24135095, 61189071, 28601646, 10834810, 20226706, 50596761, 22733718, - 39946641, 19523900, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 121055819, 49063018, 83772567, 25398281, 38758921, 42573554, 37925442, - 29785008, 69352974, 19552452, - ]), - y_minus_x: FieldElement2625([ - 61955989, 29753495, 57802388, 27482848, 16243068, 14684434, 41435776, 17373631, - 13491505, 4641841, - ]), - xy2d: FieldElement2625([ - 10813398, 643330, 47920349, 32825515, 30292061, 16954354, 27548446, 25833190, - 14476988, 20787001, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 77400943, 9984944, 73590300, 41834336, 59857349, 40587174, 27282936, 31910173, - 106304917, 12651322, - ]), - y_minus_x: FieldElement2625([ - 35923332, 32741048, 22271203, 11835308, 10201545, 15351028, 17099662, 3988035, - 21721536, 30405492, - ]), - xy2d: FieldElement2625([ - 10202177, 27008593, 35735631, 23979793, 34958221, 25434748, 54202543, 3852693, - 13216206, 14842320, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 51293205, 22953365, 60569911, 26295436, 60124204, 26972653, 35608016, 47320255, - 106783330, 43454614, - ]), - y_minus_x: FieldElement2625([ - 14465486, 19721101, 34974879, 18815558, 39665676, 12990491, 33046193, 15796406, - 60056998, 25514317, - ]), - xy2d: FieldElement2625([ - 30924398, 25274812, 6359015, 20738097, 16508376, 9071735, 41620263, 15413634, - 9524356, 26535554, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 12274182, 20378885, 99736504, 65323537, 73845487, 13267304, 72346523, 28444948, - 82772379, 37590215, - ]), - y_minus_x: FieldElement2625([ - 64157555, 8903984, 17349946, 601635, 50676049, 28941875, 53376124, 17665097, - 44850385, 4659090, - ]), - xy2d: FieldElement2625([ - 50192582, 28601458, 36715152, 18395610, 20774811, 15897498, 5736189, 15026997, - 64930608, 20098846, - ]), - }, - ]), - LookupTable([ - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 58249865, 31335375, 28571665, 56953346, 66634395, 23448733, 63307367, 33832526, - 23440561, 33264224, - ]), - y_minus_x: FieldElement2625([ - 10226222, 27625730, 15139955, 120818, 52241171, 5218602, 32937275, 11551483, - 50536904, 26111567, - ]), - xy2d: FieldElement2625([ - 17932739, 21117156, 43069306, 10749059, 11316803, 7535897, 22503767, 5561594, - 63462240, 3898660, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 74858752, 32584864, 50769132, 33537967, 42090752, 15122142, 65535333, 40706961, - 88940025, 34799664, - ]), - y_minus_x: FieldElement2625([ - 26958440, 18896406, 4314585, 8346991, 61431100, 11960071, 34519569, 32934396, - 36706772, 16838219, - ]), - xy2d: FieldElement2625([ - 54942968, 9166946, 33491384, 13673479, 29787085, 13096535, 6280834, 14587357, - 44770839, 13987524, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 109867800, 7778773, 88224864, 49127028, 62275597, 28196653, 62807965, 28429792, - 59639082, 30696363, - ]), - y_minus_x: FieldElement2625([ - 9681908, 26817309, 35157219, 13591837, 60225043, 386949, 31622781, 6439245, - 52527852, 4091396, - ]), - xy2d: FieldElement2625([ - 58682418, 1470726, 38999185, 31957441, 3978626, 28430809, 47486180, 12092162, - 29077877, 18812444, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 72378032, 26694705, 120987516, 25533715, 25932562, 35317984, 61502753, - 28048550, 47091016, 2357888, - ]), - y_minus_x: FieldElement2625([ - 32264008, 18146780, 61721128, 32394338, 65017541, 29607531, 23104803, 20684524, - 5727337, 189038, - ]), - xy2d: FieldElement2625([ - 14609104, 24599962, 61108297, 16931650, 52531476, 25810533, 40363694, 10942114, - 41219933, 18669734, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 87622345, 39112362, 51504250, 41383962, 93522806, 31535027, 45729895, 41026212, - 13913676, 28416557, - ]), - y_minus_x: FieldElement2625([ - 41534488, 11967825, 29233242, 12948236, 60354399, 4713226, 58167894, 14059179, - 12878652, 8511905, - ]), - xy2d: FieldElement2625([ - 41452044, 3393630, 64153449, 26478905, 64858154, 9366907, 36885446, 6812973, - 5568676, 30426776, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 78738868, 12144453, 69225203, 47160468, 94487748, 49231348, 49700110, 20050058, - 119822531, 8070816, - ]), - y_minus_x: FieldElement2625([ - 27117677, 23547054, 35826092, 27984343, 1127281, 12772488, 37262958, 10483305, - 55556115, 32525717, - ]), - xy2d: FieldElement2625([ - 10637467, 27866368, 5674780, 1072708, 40765276, 26572129, 65424888, 9177852, - 39615702, 15431202, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 87633990, 44446997, 121475255, 12779441, 104724694, 16150073, 105977209, - 14943140, 52052074, 25618500, - ]), - y_minus_x: FieldElement2625([ - 37084402, 5626925, 66557297, 23573344, 753597, 11981191, 25244767, 30314666, - 63752313, 9594023, - ]), - xy2d: FieldElement2625([ - 43356201, 2636869, 61944954, 23450613, 585133, 7877383, 11345683, 27062142, - 13352334, 22577348, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 65177046, 28146973, 70413512, 54223994, 84124668, 62231772, 104433876, - 25801948, 53893326, 33235227, - ]), - y_minus_x: FieldElement2625([ - 20239939, 6607058, 6203985, 3483793, 48721888, 32775202, 46385121, 15077869, - 44358105, 14523816, - ]), - xy2d: FieldElement2625([ - 27406023, 27512775, 27423595, 29057038, 4996213, 10002360, 38266833, 29008937, - 36936121, 28748764, - ]), - }, - ]), - LookupTable([ - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 78483087, 12660714, 17861383, 21013599, 78044431, 34653658, 53222787, 24462691, - 106490683, 44912934, - ]), - y_minus_x: FieldElement2625([ - 54378055, 10311866, 1510375, 10778093, 64989409, 24408729, 32676002, 11149336, - 40985213, 4985767, - ]), - xy2d: FieldElement2625([ - 48012542, 341146, 60911379, 33315398, 15756972, 24757770, 66125820, 13794113, - 47694557, 17933176, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 73598907, 45494717, 25495922, 59382504, 75777235, 24803115, 70476466, 40524436, - 65417798, 58104073, - ]), - y_minus_x: FieldElement2625([ - 1656478, 13457317, 15370807, 6364910, 13605745, 8362338, 47934242, 28078708, - 50312267, 28522993, - ]), - xy2d: FieldElement2625([ - 44835530, 20030007, 67044178, 29220208, 48503227, 22632463, 46537798, 26546453, - 67009010, 23317098, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 84856310, 43593691, 86477162, 29503840, 46478228, 51067577, 99101545, 17696455, - 104957364, 28042459, - ]), - y_minus_x: FieldElement2625([ - 31932008, 28568291, 47496481, 16366579, 22023614, 88450, 11371999, 29810185, - 4882241, 22927527, - ]), - xy2d: FieldElement2625([ - 29796488, 37186, 19818052, 10115756, 55279832, 3352735, 18551198, 3272828, - 61917932, 29392022, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 12501267, 4044383, 58495907, 53716478, 101787674, 38691029, 47878485, 30024734, - 330069, 29895023, - ]), - y_minus_x: FieldElement2625([ - 6384877, 2899513, 17807477, 7663917, 64749976, 12363164, 25366522, 24980540, - 66837568, 12071498, - ]), - xy2d: FieldElement2625([ - 58743349, 29511910, 25133447, 29037077, 60897836, 2265926, 34339246, 1936674, - 61949167, 3829362, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 28425947, 27718999, 66531773, 28857233, 120000172, 40425360, 75030413, - 26986644, 26333139, 47822096, - ]), - y_minus_x: FieldElement2625([ - 56041645, 11871230, 27385719, 22994888, 62522949, 22365119, 10004785, 24844944, - 45347639, 8930323, - ]), - xy2d: FieldElement2625([ - 45911060, 17158396, 25654215, 31829035, 12282011, 11008919, 1541940, 4757911, - 40617363, 17145491, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 80646107, 25794941, 113612887, 44516357, 61186043, 20336366, 53952279, - 39771685, 118274028, 47369420, - ]), - y_minus_x: FieldElement2625([ - 49686272, 15157789, 18705543, 29619, 24409717, 33293956, 27361680, 9257833, - 65152338, 31777517, - ]), - xy2d: FieldElement2625([ - 42063564, 23362465, 15366584, 15166509, 54003778, 8423555, 37937324, 12361134, - 48422886, 4578289, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 91688613, 3711569, 68451186, 22374305, 107212592, 47679386, 44564334, 14074918, - 21964432, 41789689, - ]), - y_minus_x: FieldElement2625([ - 60580251, 31142934, 9442965, 27628844, 12025639, 32067012, 64127349, 31885225, - 13006805, 2355433, - ]), - xy2d: FieldElement2625([ - 50803946, 19949172, 60476436, 28412082, 16974358, 22643349, 27202043, 1719366, - 1141648, 20758196, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 54244901, 53888877, 58790596, 56090772, 60298717, 28710537, 13475065, 30420460, - 32674894, 47269477, - ]), - y_minus_x: FieldElement2625([ - 11423316, 28086373, 32344215, 8962751, 24989809, 9241752, 53843611, 16086211, - 38367983, 17912338, - ]), - xy2d: FieldElement2625([ - 65699196, 12530727, 60740138, 10847386, 19531186, 19422272, 55399715, 7791793, - 39862921, 4383346, - ]), - }, - ]), - LookupTable([ - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 38137947, 38825878, 65842854, 23817442, 121762491, 50287029, 62246456, - 62202414, 27193555, 39799623, - ]), - y_minus_x: FieldElement2625([ - 51914908, 5362277, 65324971, 2695833, 4960227, 12840725, 23061898, 3260492, - 22510453, 8577507, - ]), - xy2d: FieldElement2625([ - 54476394, 11257345, 34415870, 13548176, 66387860, 10879010, 31168030, 13952092, - 37537372, 29918525, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 70986166, 23981692, 99525555, 38959755, 56104456, 19897796, 70868632, 45489751, - 72720723, 41718449, - ]), - y_minus_x: FieldElement2625([ - 50833043, 14667796, 15906460, 12155291, 44997715, 24514713, 32003001, 24722143, - 5773084, 25132323, - ]), - xy2d: FieldElement2625([ - 43320746, 25300131, 1950874, 8937633, 18686727, 16459170, 66203139, 12376319, - 31632953, 190926, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 109624102, 17415545, 58684872, 13378745, 81271271, 6901327, 58820115, 38062995, - 41767308, 29926903, - ]), - y_minus_x: FieldElement2625([ - 8884438, 27670423, 6023973, 10104341, 60227295, 28612898, 18722940, 18768427, - 65436375, 827624, - ]), - xy2d: FieldElement2625([ - 34388281, 17265135, 34605316, 7101209, 13354605, 2659080, 65308289, 19446395, - 42230385, 1541285, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 70010192, 32436744, 70989239, 57049475, 116596786, 29941649, 45306746, - 29986950, 87565708, 31669398, - ]), - y_minus_x: FieldElement2625([ - 27019610, 12299467, 53450576, 31951197, 54247203, 28692960, 47568713, 28538373, - 29439640, 15138866, - ]), - xy2d: FieldElement2625([ - 21536104, 26928012, 34661045, 22864223, 44700786, 5175813, 61688824, 17193268, - 7779327, 109896, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 97388589, 48203181, 59063992, 39979989, 80748484, 32810922, 28698389, 45734550, - 23177718, 33000357, - ]), - y_minus_x: FieldElement2625([ - 26572828, 3405927, 35407164, 12890904, 47843196, 5335865, 60615096, 2378491, - 4439158, 20275085, - ]), - xy2d: FieldElement2625([ - 44392139, 3489069, 57883598, 33221678, 18875721, 32414337, 14819433, 20822905, - 49391106, 28092994, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 62052362, 50120982, 83062524, 37322183, 56672364, 49181491, 66287909, 35731656, - 75658945, 18440266, - ]), - y_minus_x: FieldElement2625([ - 48635543, 16596774, 66727204, 15663610, 22860960, 15585581, 39264755, 29971692, - 43848403, 25125843, - ]), - xy2d: FieldElement2625([ - 34628313, 15707274, 58902952, 27902350, 29464557, 2713815, 44383727, 15860481, - 45206294, 1494192, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 47546754, 53021470, 41524990, 24254879, 80236705, 34314140, 21923481, 16529112, - 75851568, 46521448, - ]), - y_minus_x: FieldElement2625([ - 38643965, 1553204, 32536856, 23080703, 42417258, 33148257, 58194238, 30620535, - 37205105, 15553882, - ]), - xy2d: FieldElement2625([ - 21877890, 3230008, 9881174, 10539357, 62311749, 2841331, 11543572, 14513274, - 19375923, 20906471, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 75941133, 52613378, 80362373, 38692006, 72146734, 37633208, 24880817, 60886148, - 69971515, 9455042, - ]), - y_minus_x: FieldElement2625([ - 29306751, 5123106, 20245049, 19404543, 9592565, 8447059, 65031740, 30564351, - 15511448, 4789663, - ]), - xy2d: FieldElement2625([ - 46429108, 7004546, 8824831, 24119455, 63063159, 29803695, 61354101, 108892, - 23513200, 16652362, - ]), - }, - ]), - LookupTable([ - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 100961536, 37699212, 62632834, 26975308, 77878902, 26398889, 60458447, - 54172563, 115898528, 43767290, - ]), - y_minus_x: FieldElement2625([ - 2756062, 8598110, 7383731, 26694540, 22312758, 32449420, 21179800, 2600940, - 57120566, 21047965, - ]), - xy2d: FieldElement2625([ - 42463153, 13317461, 36659605, 17900503, 21365573, 22684775, 11344423, 864440, - 64609187, 16844368, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 107784906, 6148327, 49924452, 19080277, 85891792, 33278434, 44547329, 33765731, - 69828620, 38495428, - ]), - y_minus_x: FieldElement2625([ - 65784982, 3911312, 60160120, 14759764, 37081714, 7851206, 21690126, 8518463, - 26699843, 5276295, - ]), - xy2d: FieldElement2625([ - 53958991, 27125364, 9396248, 365013, 24703301, 23065493, 1321585, 149635, - 51656090, 7159368, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 77096625, 30149672, 84616825, 43059961, 76840398, 31388917, 89464872, 41866607, - 89586081, 25151046, - ]), - y_minus_x: FieldElement2625([ - 18155857, 17049442, 19744715, 9006923, 15154154, 23015456, 24256459, 28689437, - 44560690, 9334108, - ]), - xy2d: FieldElement2625([ - 2986088, 28642539, 10776627, 30080588, 10620589, 26471229, 45695018, 14253544, - 44521715, 536905, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 71486582, 41670267, 91675941, 15495313, 78733938, 46619030, 74499414, 44144056, - 77946923, 51688439, - ]), - y_minus_x: FieldElement2625([ - 47766460, 867879, 9277171, 30335973, 52677291, 31567988, 19295825, 17757482, - 6378259, 699185, - ]), - xy2d: FieldElement2625([ - 7895007, 4057113, 60027092, 20476675, 49222032, 33231305, 66392824, 15693154, - 62063800, 20180469, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 59371282, 27685029, 119651408, 26147511, 78494517, 46756047, 31730677, - 22591592, 63190227, 23885106, - ]), - y_minus_x: FieldElement2625([ - 10188286, 17783598, 59772502, 13427542, 22223443, 14896287, 30743455, 7116568, - 45322357, 5427592, - ]), - xy2d: FieldElement2625([ - 696102, 13206899, 27047647, 22922350, 15285304, 23701253, 10798489, 28975712, - 19236242, 12477404, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 55879406, 44798227, 50054593, 25513566, 66320635, 58940896, 63211193, 44734935, - 43939347, 41288075, - ]), - y_minus_x: FieldElement2625([ - 17800790, 19518253, 40108434, 21787760, 23887826, 3149671, 23466177, 23016261, - 10322026, 15313801, - ]), - xy2d: FieldElement2625([ - 26246234, 11968874, 32263343, 28085704, 6830754, 20231401, 51314159, 33452449, - 42659621, 10890803, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 35743198, 43825794, 54448238, 27287163, 83799070, 54046319, 119235514, - 50039361, 92289660, 28219547, - ]), - y_minus_x: FieldElement2625([ - 66522290, 10376443, 34522450, 22268075, 19801892, 10997610, 2276632, 9482883, - 316878, 13820577, - ]), - xy2d: FieldElement2625([ - 57226037, 29044064, 64993357, 16457135, 56008783, 11674995, 30756178, 26039378, - 30696929, 29841583, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 100097781, 23951019, 12499365, 41465219, 56491606, 21622917, 59766047, - 57123466, 34759345, 7392472, - ]), - y_minus_x: FieldElement2625([ - 58253184, 15927860, 9866406, 29905021, 64711949, 16898650, 36699387, 24419436, - 25112946, 30627788, - ]), - xy2d: FieldElement2625([ - 64604801, 33117465, 25621773, 27875660, 15085041, 28074555, 42223985, 20028237, - 5537437, 19640113, - ]), - }, - ]), - LookupTable([ - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 55883261, 2320284, 57524584, 10149186, 100773065, 5808646, 119341477, 31824763, - 98343453, 39645030, - ]), - y_minus_x: FieldElement2625([ - 57475529, 116425, 26083934, 2897444, 60744427, 30866345, 609720, 15878753, - 60138459, 24519663, - ]), - xy2d: FieldElement2625([ - 39351007, 247743, 51914090, 24551880, 23288160, 23542496, 43239268, 6503645, - 20650474, 1804084, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 106627923, 49010854, 76081380, 42024039, 82749485, 37994278, 70230858, - 56779150, 94951478, 33352103, - ]), - y_minus_x: FieldElement2625([ - 51801891, 2839643, 22530074, 10026331, 4602058, 5048462, 28248656, 5031932, - 55733782, 12714368, - ]), - xy2d: FieldElement2625([ - 20807691, 26283607, 29286140, 11421711, 39232341, 19686201, 45881388, 1035545, - 47375635, 12796919, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 79185725, 52807577, 58323861, 21705509, 42096072, 49955115, 49517368, 20654993, - 70589528, 51926048, - ]), - y_minus_x: FieldElement2625([ - 34747315, 5457596, 28548107, 7833186, 7303070, 21600887, 42745799, 17632556, - 33734809, 2771024, - ]), - xy2d: FieldElement2625([ - 45719598, 421931, 26597266, 6860826, 22486084, 26817260, 49971378, 29344205, - 42556581, 15673396, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 46924223, 35892647, 19788684, 57487908, 63107597, 24813538, 46837679, 38287685, - 70836007, 20619983, - ]), - y_minus_x: FieldElement2625([ - 6120100, 814863, 55314462, 32931715, 6812204, 17806661, 2019593, 7975683, - 31123697, 22595451, - ]), - xy2d: FieldElement2625([ - 30069250, 22119100, 30434653, 2958439, 18399564, 32578143, 12296868, 9204260, - 50676426, 9648164, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 32705413, 32003455, 97814521, 41005496, 55303257, 43186244, 70414129, 38803035, - 108209395, 22176929, - ]), - y_minus_x: FieldElement2625([ - 17219846, 2375039, 35537917, 27978816, 47649184, 9219902, 294711, 15298639, - 2662509, 17257359, - ]), - xy2d: FieldElement2625([ - 65935918, 25995736, 62742093, 29266687, 45762450, 25120105, 32087528, 32331655, - 32247247, 19164571, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 14312609, 34775988, 17395389, 58408721, 62163121, 58424228, 106019982, - 23916613, 51081240, 20175586, - ]), - y_minus_x: FieldElement2625([ - 65680039, 23875441, 57873182, 6549686, 59725795, 33085767, 23046501, 9803137, - 17597934, 2346211, - ]), - xy2d: FieldElement2625([ - 18510781, 15337574, 26171504, 981392, 44867312, 7827555, 43617730, 22231079, - 3059832, 21771562, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 77250443, 39637338, 84938156, 31606788, 76938955, 13613135, 41552228, 28009845, - 33606651, 37146527, - ]), - y_minus_x: FieldElement2625([ - 33114149, 17665080, 40583177, 20211034, 33076704, 8716171, 1151462, 1521897, - 66126199, 26716628, - ]), - xy2d: FieldElement2625([ - 34169699, 29298616, 23947180, 33230254, 34035889, 21248794, 50471177, 3891703, - 26353178, 693168, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 97483084, 35150011, 117333688, 46741361, 71709207, 33961335, 76694157, - 33153763, 31375463, 47924397, - ]), - y_minus_x: FieldElement2625([ - 52738210, 25781902, 1510300, 6434173, 48324075, 27291703, 32732229, 20445593, - 17901440, 16011505, - ]), - xy2d: FieldElement2625([ - 18171223, 21619806, 54608461, 15197121, 56070717, 18324396, 47936623, 17508055, - 8764034, 12309598, - ]), - }, - ]), - LookupTable([ - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 73084753, 28311243, 47649501, 23872684, 55567586, 14015781, 110551971, - 34782749, 17544095, 22960650, - ]), - y_minus_x: FieldElement2625([ - 5811932, 31839139, 3442886, 31285122, 48741515, 25194890, 49064820, 18144304, - 61543482, 12348899, - ]), - xy2d: FieldElement2625([ - 35709185, 11407554, 25755363, 6891399, 63851926, 14872273, 42259511, 8141294, - 56476330, 32968952, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 121542424, 34248456, 62032718, 46854775, 81124121, 19103037, 124519055, - 22225380, 30944592, 1130208, - ]), - y_minus_x: FieldElement2625([ - 8247747, 26843490, 40546482, 25845122, 52706924, 18905521, 4652151, 2488540, - 23550156, 33283200, - ]), - xy2d: FieldElement2625([ - 17294297, 29765994, 7026747, 15626851, 22990044, 113481, 2267737, 27646286, - 66700045, 33416712, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 83199930, 17300505, 85708115, 40895109, 69246500, 32332774, 63744702, 48105367, - 70369388, 26388160, - ]), - y_minus_x: FieldElement2625([ - 62198760, 20221544, 18550886, 10864893, 50649539, 26262835, 44079994, 20349526, - 54360141, 2701325, - ]), - xy2d: FieldElement2625([ - 58534169, 16099414, 4629974, 17213908, 46322650, 27548999, 57090500, 9276970, - 11329923, 1862132, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 14763057, 17650824, 103299457, 3689865, 70620756, 43867957, 45157775, 45773662, - 58070900, 32614131, - ]), - y_minus_x: FieldElement2625([ - 8894987, 30108338, 6150752, 3013931, 301220, 15693451, 35127648, 30644714, - 51670695, 11595569, - ]), - xy2d: FieldElement2625([ - 15214943, 3537601, 40870142, 19495559, 4418656, 18323671, 13947275, 10730794, - 53619402, 29190761, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 64570539, 41237224, 99867876, 33817540, 104232996, 25598978, 111885603, - 23365795, 68085971, 34254425, - ]), - y_minus_x: FieldElement2625([ - 54642373, 4195083, 57897332, 550903, 51543527, 12917919, 19118110, 33114591, - 36574330, 19216518, - ]), - xy2d: FieldElement2625([ - 31788442, 19046775, 4799988, 7372237, 8808585, 18806489, 9408236, 23502657, - 12493931, 28145115, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 41428258, 5260743, 47873055, 27269961, 63412921, 16566086, 94327144, 36161552, - 29375954, 6024730, - ]), - y_minus_x: FieldElement2625([ - 842132, 30759739, 62345482, 24831616, 26332017, 21148791, 11831879, 6985184, - 57168503, 2854095, - ]), - xy2d: FieldElement2625([ - 62261602, 25585100, 2516241, 27706719, 9695690, 26333246, 16512644, 960770, - 12121869, 16648078, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 51890193, 48221527, 53772634, 35568148, 97707150, 33090294, 35603941, 25672367, - 20237805, 36392843, - ]), - y_minus_x: FieldElement2625([ - 47820798, 4453151, 15298546, 17376044, 22115042, 17581828, 12544293, 20083975, - 1068880, 21054527, - ]), - xy2d: FieldElement2625([ - 57549981, 17035596, 33238497, 13506958, 30505848, 32439836, 58621956, 30924378, - 12521377, 4845654, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 106019188, 44298538, 64150483, 43754095, 74868174, 54020263, 70518210, - 32681031, 127735421, 20668560, - ]), - y_minus_x: FieldElement2625([ - 43547042, 6230155, 46726851, 10655313, 43068279, 21933259, 10477733, 32314216, - 63995636, 13974497, - ]), - xy2d: FieldElement2625([ - 12966261, 15550616, 35069916, 31939085, 21025979, 32924988, 5642324, 7188737, - 18895762, 12629579, - ]), - }, - ]), - LookupTable([ - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 14741860, 18607545, 89286071, 21833194, 68388604, 41613031, 11758139, 34343875, - 32195180, 37450109, - ]), - y_minus_x: FieldElement2625([ - 10758205, 15755439, 62598914, 9243697, 62229442, 6879878, 64904289, 29988312, - 58126794, 4429646, - ]), - xy2d: FieldElement2625([ - 64654951, 15725972, 46672522, 23143759, 61304955, 22514211, 59972993, 21911536, - 18047435, 18272689, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 41935825, 55801698, 29759954, 45331216, 111955344, 51288407, 78101976, - 54258026, 49488161, 57700395, - ]), - y_minus_x: FieldElement2625([ - 21987233, 700364, 42603816, 14972007, 59334599, 27836036, 32155025, 2581431, - 37149879, 8773374, - ]), - xy2d: FieldElement2625([ - 41540495, 454462, 53896929, 16126714, 25240068, 8594567, 20656846, 12017935, - 59234475, 19634276, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 73137027, 39817509, 103205921, 55807152, 66289943, 36016203, 102376553, - 61640820, 65387074, 30777706, - ]), - y_minus_x: FieldElement2625([ - 54829870, 16624276, 987579, 27631834, 32908202, 1248608, 7719845, 29387734, - 28408819, 6816612, - ]), - xy2d: FieldElement2625([ - 56750770, 25316602, 19549650, 21385210, 22082622, 16147817, 20613181, 13982702, - 56769294, 5067942, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 36602859, 29732664, 79183544, 13582411, 47230892, 35998382, 47389577, 12746131, - 72440074, 57002919, - ]), - y_minus_x: FieldElement2625([ - 30528792, 3601899, 65151774, 4619784, 39747042, 18118043, 24180792, 20984038, - 27679907, 31905504, - ]), - xy2d: FieldElement2625([ - 9402385, 19597367, 32834042, 10838634, 40528714, 20317236, 26653273, 24868867, - 22611443, 20839026, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 89299435, 34672460, 22736440, 48684895, 103757035, 27563109, 86298488, - 62459921, 71963721, 40176570, - ]), - y_minus_x: FieldElement2625([ - 58798126, 30600981, 58846284, 30166382, 56707132, 33282502, 13424425, 29987205, - 26404408, 13001963, - ]), - xy2d: FieldElement2625([ - 35867026, 18138731, 64114613, 8939345, 11562230, 20713762, 41044498, 21932711, - 51703708, 11020692, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 68974887, 59159374, 59210213, 23253421, 12483314, 47031979, 70284499, 21130268, - 28761761, 34961166, - ]), - y_minus_x: FieldElement2625([ - 66660290, 31776765, 13018550, 3194501, 57528444, 22392694, 24760584, 29207344, - 25577410, 20175752, - ]), - xy2d: FieldElement2625([ - 42818486, 4759344, 66418211, 31701615, 2066746, 10693769, 37513074, 9884935, - 57739938, 4745409, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 57967561, 39604145, 47577802, 29213020, 102956929, 43498706, 51646855, - 55797011, 78040786, 21622500, - ]), - y_minus_x: FieldElement2625([ - 50547351, 14112679, 59096219, 4817317, 59068400, 22139825, 44255434, 10856640, - 46638094, 13434653, - ]), - xy2d: FieldElement2625([ - 22759470, 23480998, 50342599, 31683009, 13637441, 23386341, 1765143, 20900106, - 28445306, 28189722, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 29875044, 46048045, 69904399, 63322533, 68819482, 48735613, 56913146, 24765756, - 9074233, 34721612, - ]), - y_minus_x: FieldElement2625([ - 40903181, 11014232, 57266213, 30918946, 40200743, 7532293, 48391976, 24018933, - 3843902, 9367684, - ]), - xy2d: FieldElement2625([ - 56139269, 27150720, 9591133, 9582310, 11349256, 108879, 16235123, 8601684, - 66969667, 4242894, - ]), - }, - ]), - LookupTable([ - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 89201818, 53917740, 65066069, 21585919, 99295616, 55591475, 60534521, 36025091, - 106800361, 16625499, - ]), - y_minus_x: FieldElement2625([ - 56051142, 3042015, 13770083, 24296510, 584235, 33009577, 59338006, 2602724, - 39757248, 14247412, - ]), - xy2d: FieldElement2625([ - 6314156, 23289540, 34336361, 15957556, 56951134, 168749, 58490057, 14290060, - 27108877, 32373552, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 58522248, 26383465, 80350645, 44514587, 34117848, 19759835, 100656839, - 22495542, 107069276, 34536304, - ]), - y_minus_x: FieldElement2625([ - 22833421, 9293594, 34459416, 19935764, 57971897, 14756818, 44180005, 19583651, - 56629059, 17356469, - ]), - xy2d: FieldElement2625([ - 59340277, 3326785, 38997067, 10783823, 19178761, 14905060, 22680049, 13906969, - 51175174, 3797898, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 88830182, 29341685, 54902740, 42864613, 63226624, 19901321, 90849087, 30845199, - 87600846, 59066711, - ]), - y_minus_x: FieldElement2625([ - 9209251, 18419377, 53852306, 27386633, 66377847, 15289672, 25947805, 15286587, - 30997318, 26851369, - ]), - xy2d: FieldElement2625([ - 7392013, 16618386, 23946583, 25514540, 53843699, 32020573, 52911418, 31232855, - 17649997, 33304352, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 57807757, 52915036, 97718388, 30504888, 41933794, 32270679, 51867297, 24028707, - 64875610, 41216577, - ]), - y_minus_x: FieldElement2625([ - 49550191, 1763593, 33994528, 15908609, 37067994, 21380136, 7335079, 25082233, - 63934189, 3440182, - ]), - xy2d: FieldElement2625([ - 47219164, 27577423, 42997570, 23865561, 10799742, 16982475, 40449, 29122597, - 4862399, 1133, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 34252636, 25680474, 61686474, 48415381, 50789832, 41510573, 74366924, 33866292, - 36513872, 26175010, - ]), - y_minus_x: FieldElement2625([ - 63335436, 31988495, 28985339, 7499440, 24445838, 9325937, 29727763, 16527196, - 18278453, 15405622, - ]), - xy2d: FieldElement2625([ - 62726958, 8508651, 47210498, 29880007, 61124410, 15149969, 53795266, 843522, - 45233802, 13626196, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 69390312, 20067376, 56193445, 30944521, 68988221, 49718638, 56324981, 37508223, - 80449702, 15928662, - ]), - y_minus_x: FieldElement2625([ - 31727126, 26374577, 48671360, 25270779, 2875792, 17164102, 41838969, 26539605, - 43656557, 5964752, - ]), - xy2d: FieldElement2625([ - 4100401, 27594980, 49929526, 6017713, 48403027, 12227140, 40424029, 11344143, - 2538215, 25983677, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 57675240, 6123112, 78268667, 31397823, 97125143, 48520672, 46633880, 35039852, - 66479607, 17595569, - ]), - y_minus_x: FieldElement2625([ - 40304287, 4260918, 11851389, 9658551, 35091757, 16367491, 46903439, 20363143, - 11659921, 22439314, - ]), - xy2d: FieldElement2625([ - 26180377, 10015009, 36264640, 24973138, 5418196, 9480663, 2231568, 23384352, - 33100371, 32248261, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 82229958, 28352560, 56718958, 48982252, 39598926, 17561924, 88779810, 38041106, - 61177053, 19088051, - ]), - y_minus_x: FieldElement2625([ - 16166467, 24070699, 56004733, 6023907, 35182066, 32189508, 2340059, 17299464, - 56373093, 23514607, - ]), - xy2d: FieldElement2625([ - 28042865, 29997343, 54982337, 12259705, 63391366, 26608532, 6766452, 24864833, - 18036435, 5803270, - ]), - }, - ]), - LookupTable([ - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 66291264, 40318343, 78912424, 35140016, 78067310, 30883266, 23855390, 4598332, - 60949433, 19436993, - ]), - y_minus_x: FieldElement2625([ - 36077558, 19298237, 17332028, 31170912, 31312681, 27587249, 696308, 50292, - 47013125, 11763583, - ]), - xy2d: FieldElement2625([ - 66514282, 31040148, 34874710, 12643979, 12650761, 14811489, 665117, 20940800, - 47335652, 22840869, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 97573435, 55845991, 62981386, 20819953, 86944190, 60003250, 109821551, - 35630203, 50088706, 34546902, - ]), - y_minus_x: FieldElement2625([ - 18357166, 26559999, 7766381, 16342475, 37783946, 411173, 14578841, 8080033, - 55534529, 22952821, - ]), - xy2d: FieldElement2625([ - 19598397, 10334610, 12555054, 2555664, 18821899, 23214652, 21873262, 16014234, - 26224780, 16452269, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 36884920, 5145195, 73053412, 49940397, 71085598, 35564328, 122839923, 25936244, - 46575034, 37253081, - ]), - y_minus_x: FieldElement2625([ - 14187449, 3448569, 56472628, 22743496, 44444983, 30120835, 7268409, 22663988, - 27394300, 12015369, - ]), - xy2d: FieldElement2625([ - 19695742, 16087646, 28032085, 12999827, 6817792, 11427614, 20244189, 32241655, - 53849736, 30151970, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 97968948, 12735207, 65220619, 28854697, 50133957, 35811371, 126051714, - 45852742, 58558339, 23160969, - ]), - y_minus_x: FieldElement2625([ - 61389038, 22309106, 65198214, 15569034, 26642876, 25966672, 61319509, 18435777, - 62132699, 12651792, - ]), - xy2d: FieldElement2625([ - 64260450, 9953420, 11531313, 28271553, 26895122, 20857343, 53990043, 17036529, - 9768697, 31021214, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 109498250, 35449081, 66821165, 28850346, 82457582, 25397901, 32767512, - 46319882, 72048958, 44232657, - ]), - y_minus_x: FieldElement2625([ - 18860224, 15980149, 48121624, 31991861, 40875851, 22482575, 59264981, 13944023, - 42736516, 16582018, - ]), - xy2d: FieldElement2625([ - 51604604, 4970267, 37215820, 4175592, 46115652, 31354675, 55404809, 15444559, - 56105103, 7989036, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 98599278, 39122492, 64696060, 35736814, 34772016, 38086117, 35030594, 39754637, - 47422750, 52308692, - ]), - y_minus_x: FieldElement2625([ - 49800177, 17674491, 35586086, 33551600, 34221481, 16375548, 8680158, 17182719, - 28550067, 26697300, - ]), - xy2d: FieldElement2625([ - 38981977, 27866340, 16837844, 31733974, 60258182, 12700015, 37068883, 4364037, - 1155602, 5988841, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 88999280, 20281524, 121593716, 12154347, 59276991, 48854927, 90257846, - 29083950, 91727270, 41837612, - ]), - y_minus_x: FieldElement2625([ - 33972757, 23041680, 9975415, 6841041, 35549071, 16356535, 3070187, 26528504, - 1466168, 10740210, - ]), - xy2d: FieldElement2625([ - 65599446, 18066246, 53605478, 22898515, 32799043, 909394, 53169961, 27774712, - 34944214, 18227391, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 71069668, 19286628, 39082773, 51190812, 47704004, 46701299, 82676190, 34505938, - 63848542, 32980496, - ]), - y_minus_x: FieldElement2625([ - 24740822, 5052253, 37014733, 8961360, 25877428, 6165135, 42740684, 14397371, - 59728495, 27410326, - ]), - xy2d: FieldElement2625([ - 38220480, 3510802, 39005586, 32395953, 55870735, 22922977, 51667400, 19101303, - 65483377, 27059617, - ]), - }, - ]), - LookupTable([ - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 67902144, 24323953, 75945165, 27318724, 39747955, 31184838, 100261706, - 62223612, 57202662, 32932579, - ]), - y_minus_x: FieldElement2625([ - 5666214, 525582, 20782575, 25516013, 42570364, 14657739, 16099374, 1468826, - 60937436, 18367850, - ]), - xy2d: FieldElement2625([ - 62249590, 29775088, 64191105, 26806412, 7778749, 11688288, 36704511, 23683193, - 65549940, 23690785, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 10896313, 25834728, 67933138, 34027032, 114757419, 36564017, 25248957, - 48337770, 36527387, 17796587, - ]), - y_minus_x: FieldElement2625([ - 10566929, 12612572, 35164652, 11118702, 54475488, 12362878, 21752402, 8822496, - 24003793, 14264025, - ]), - xy2d: FieldElement2625([ - 27713843, 26198459, 56100623, 9227529, 27050101, 2504721, 23886875, 20436907, - 13958494, 27821979, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 110736080, 38421656, 39861735, 37454952, 29838368, 25342141, 102328328, - 23512649, 74449384, 51698795, - ]), - y_minus_x: FieldElement2625([ - 4646495, 25543308, 44342840, 22021777, 23184552, 8566613, 31366726, 32173371, - 52042079, 23179239, - ]), - xy2d: FieldElement2625([ - 49838347, 12723031, 50115803, 14878793, 21619651, 27356856, 27584816, 3093888, - 58265170, 3849920, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 58043933, 35657603, 92670503, 51983125, 61869038, 43137389, 99585908, 24536476, - 72111157, 18004172, - ]), - y_minus_x: FieldElement2625([ - 55051311, 22376525, 21115584, 20189277, 8808711, 21523724, 16489529, 13378448, - 41263148, 12741425, - ]), - xy2d: FieldElement2625([ - 61162478, 10645102, 36197278, 15390283, 63821882, 26435754, 24306471, 15852464, - 28834118, 25908360, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 49773097, 24447374, 109686448, 42989383, 58636779, 32971069, 54018092, - 34010272, 87570721, 39045736, - ]), - y_minus_x: FieldElement2625([ - 13669229, 17458950, 54626889, 23351392, 52539093, 21661233, 42112877, 11293806, - 38520660, 24132599, - ]), - xy2d: FieldElement2625([ - 28497909, 6272777, 34085870, 14470569, 8906179, 32328802, 18504673, 19389266, - 29867744, 24758489, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 50901822, 47071627, 39309233, 19856633, 24009063, 60734973, 60741262, 53933471, - 22853427, 29542421, - ]), - y_minus_x: FieldElement2625([ - 24191359, 16712145, 53177067, 15217830, 14542237, 1646131, 18603514, 22516545, - 12876622, 31441985, - ]), - xy2d: FieldElement2625([ - 17902668, 4518229, 66697162, 30725184, 26878216, 5258055, 54248111, 608396, - 16031844, 3723494, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 105584936, 12763726, 46662418, 41131935, 33001347, 54091119, 17558840, - 59235974, 23896952, 29240187, - ]), - y_minus_x: FieldElement2625([ - 47103464, 21542479, 31520463, 605201, 2543521, 5991821, 64163800, 7229063, - 57189218, 24727572, - ]), - xy2d: FieldElement2625([ - 28816026, 298879, 38943848, 17633493, 19000927, 31888542, 54428030, 30605106, - 49057085, 31471516, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 16000882, 33209536, 70601955, 55661665, 37604267, 20394642, 79686603, 49595699, - 47393623, 7847706, - ]), - y_minus_x: FieldElement2625([ - 10151868, 10572098, 27312476, 7922682, 14825339, 4723128, 34252933, 27035413, - 57088296, 3852847, - ]), - xy2d: FieldElement2625([ - 55678375, 15697595, 45987307, 29133784, 5386313, 15063598, 16514493, 17622322, - 29330898, 18478208, - ]), - }, - ]), - LookupTable([ - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 41609110, 29175637, 51885955, 26653220, 83724594, 35606215, 70412565, 33569921, - 106668931, 45868821, - ]), - y_minus_x: FieldElement2625([ - 15683501, 27551389, 18109119, 23573784, 15337967, 27556609, 50391428, 15921865, - 16103996, 29823217, - ]), - xy2d: FieldElement2625([ - 43939021, 22773182, 13588191, 31925625, 63310306, 32479502, 47835256, 5402698, - 37293151, 23713330, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 90299521, 35939014, 34394523, 37016585, 104314072, 32025298, 55842007, 8911516, - 109011869, 36294143, - ]), - y_minus_x: FieldElement2625([ - 21374101, 30000182, 33584214, 9874410, 15377179, 11831242, 33578960, 6134906, - 4931255, 11987849, - ]), - xy2d: FieldElement2625([ - 67101132, 30575573, 50885377, 7277596, 105524, 33232381, 35628324, 13861387, - 37032554, 10117929, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 37607694, 22809559, 40945095, 13051538, 41483300, 38644074, 127892224, - 40258509, 79998882, 15728939, - ]), - y_minus_x: FieldElement2625([ - 45136504, 21783052, 66157804, 29135591, 14704839, 2695116, 903376, 23126293, - 12885166, 8311031, - ]), - xy2d: FieldElement2625([ - 49592363, 5352193, 10384213, 19742774, 7506450, 13453191, 26423267, 4384730, - 1888765, 28119028, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 108400371, 64001550, 120723127, 30371924, 98005322, 19632702, 101966083, - 20846561, 47644429, 30214188, - ]), - y_minus_x: FieldElement2625([ - 43500868, 30888657, 66582772, 4651135, 5765089, 4618330, 6092245, 14845197, - 17151279, 23700316, - ]), - xy2d: FieldElement2625([ - 42278406, 20820711, 51942885, 10367249, 37577956, 33289075, 22825804, 26467153, - 50242379, 16176524, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 43525570, 40119392, 87172552, 37352659, 129477549, 40913655, 69115045, - 23191005, 38362610, 56911354, - ]), - y_minus_x: FieldElement2625([ - 56482264, 29068029, 53788301, 28429114, 3432135, 27161203, 23632036, 31613822, - 32808309, 1099883, - ]), - xy2d: FieldElement2625([ - 15030958, 5768825, 39657628, 30667132, 60681485, 18193060, 51830967, 26745081, - 2051440, 18328567, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 63746522, 26315059, 74626753, 43379423, 90664713, 33849800, 72257261, 52954675, - 44422508, 50188091, - ]), - y_minus_x: FieldElement2625([ - 4577067, 16802144, 13249840, 18250104, 19958762, 19017158, 18559669, 22794883, - 8402477, 23690159, - ]), - xy2d: FieldElement2625([ - 38702534, 32502850, 40318708, 32646733, 49896449, 22523642, 9453450, 18574360, - 17983009, 9967138, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 41346351, 40079153, 93694351, 43523701, 24709297, 34774792, 65430873, 7806336, - 84616260, 37205991, - ]), - y_minus_x: FieldElement2625([ - 56688388, 29436320, 14584638, 15971087, 51340543, 8861009, 26556809, 27979875, - 48555541, 22197296, - ]), - xy2d: FieldElement2625([ - 2839082, 14284142, 4029895, 3472686, 14402957, 12689363, 40466743, 8459446, - 61503401, 25932490, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 62269556, 30018987, 76853824, 2871047, 92222842, 36741449, 109106914, 32705364, - 84366947, 25576692, - ]), - y_minus_x: FieldElement2625([ - 18164541, 22959256, 49953981, 32012014, 19237077, 23809137, 23357532, 18337424, - 26908269, 12150756, - ]), - xy2d: FieldElement2625([ - 36843994, 25906566, 5112248, 26517760, 65609056, 26580174, 43167, 28016731, - 34806789, 16215818, - ]), - }, - ]), - LookupTable([ - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 60209940, 43378825, 54804084, 29153342, 102820586, 27277595, 99683352, - 46087336, 59605791, 24879084, - ]), - y_minus_x: FieldElement2625([ - 39765323, 17038963, 39957339, 22831480, 946345, 16291093, 254968, 7168080, - 21676107, 31611404, - ]), - xy2d: FieldElement2625([ - 21260942, 25129680, 50276977, 21633609, 43430902, 3968120, 63456915, 27338965, - 63552672, 25641356, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 16544735, 46804798, 50304435, 49100673, 62525860, 46311689, 64646555, 24874095, - 48201831, 23891632, - ]), - y_minus_x: FieldElement2625([ - 64693606, 17976703, 18312302, 4964443, 51836334, 20900867, 26820650, 16690659, - 25459437, 28989823, - ]), - xy2d: FieldElement2625([ - 41964155, 11425019, 28423002, 22533875, 60963942, 17728207, 9142794, 31162830, - 60676445, 31909614, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 44004193, 39807907, 16964146, 29785560, 109103755, 54812425, 39651637, - 50764205, 73444554, 40804420, - ]), - y_minus_x: FieldElement2625([ - 36775618, 13979674, 7503222, 21186118, 55152142, 28932738, 36836594, 2682241, - 25993170, 21075909, - ]), - xy2d: FieldElement2625([ - 4364628, 5930691, 32304656, 23509878, 59054082, 15091130, 22857016, 22955477, - 31820367, 15075278, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 98987979, 24635738, 84367624, 33645057, 126175891, 28636721, 91271651, - 23903545, 116247489, 46387475, - ]), - y_minus_x: FieldElement2625([ - 19073683, 14851414, 42705695, 21694263, 7625277, 11091125, 47489674, 2074448, - 57694925, 14905376, - ]), - xy2d: FieldElement2625([ - 24483648, 21618865, 64589997, 22007013, 65555733, 15355505, 41826784, 9253128, - 27628530, 25998952, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 84706452, 41895034, 86464480, 34106618, 26198469, 30377849, 71702187, 24396849, - 120106852, 48851446, - ]), - y_minus_x: FieldElement2625([ - 510886, 14337390, 35323607, 16638631, 6328095, 2713355, 46891447, 21690211, - 8683220, 2921426, - ]), - xy2d: FieldElement2625([ - 18606791, 11874196, 27155355, 28272950, 43077121, 6265445, 41930624, 32275507, - 4674689, 13890525, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 13609605, 13069022, 106845367, 20498522, 91469449, 43147405, 82086020, - 43389536, 71498550, 33842827, - ]), - y_minus_x: FieldElement2625([ - 9922506, 33035038, 13613106, 5883594, 48350519, 33120168, 54804801, 8317627, - 23388070, 16052080, - ]), - xy2d: FieldElement2625([ - 12719997, 11937594, 35138804, 28525742, 26900119, 8561328, 46953177, 21921452, - 52354592, 22741539, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 83070703, 47704840, 93825794, 32888599, 111423399, 47157999, 78938436, - 41022275, 38286735, 34483706, - ]), - y_minus_x: FieldElement2625([ - 11038231, 21972036, 39798381, 26237869, 56610336, 17246600, 43629330, 24182562, - 45715720, 2465073, - ]), - xy2d: FieldElement2625([ - 20017144, 29231206, 27915241, 1529148, 12396362, 15675764, 13817261, 23896366, - 2463390, 28932292, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 50749967, 20890520, 122152544, 38550884, 65852441, 34628003, 76692421, - 12851106, 71112760, 46228148, - ]), - y_minus_x: FieldElement2625([ - 65377275, 18398561, 63845933, 16143081, 19294135, 13385325, 14741514, 24450706, - 7903885, 2348101, - ]), - xy2d: FieldElement2625([ - 24536016, 17039225, 12715591, 29692277, 1511292, 10047386, 63266518, 26425272, - 38731325, 10048126, - ]), - }, - ]), - LookupTable([ - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 54486638, 27349611, 97827688, 2591311, 56491836, 12192839, 85982162, 59811773, - 34811106, 15221631, - ]), - y_minus_x: FieldElement2625([ - 40630742, 22450567, 11546243, 31701949, 9180879, 7656409, 45764914, 2095754, - 29769758, 6593415, - ]), - xy2d: FieldElement2625([ - 35114656, 30646970, 4176911, 3264766, 12538965, 32686321, 26312344, 27435754, - 30958053, 8292160, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 98538667, 53149747, 96282394, 15632447, 12174511, 64348770, 99917693, 37531617, - 93251999, 30405555, - ]), - y_minus_x: FieldElement2625([ - 22648882, 1402143, 44308880, 13746058, 7936347, 365344, 58440231, 31879998, - 63350620, 31249806, - ]), - xy2d: FieldElement2625([ - 51616947, 8012312, 64594134, 20851969, 43143017, 23300402, 65496150, 32018862, - 50444388, 8194477, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 27338047, 26047012, 59694639, 10140404, 48082437, 26964542, 94386054, 42409807, - 95681149, 36559595, - ]), - y_minus_x: FieldElement2625([ - 26287105, 4821776, 25476601, 29408529, 63344350, 17765447, 49100281, 1182478, - 41014043, 20474836, - ]), - xy2d: FieldElement2625([ - 59937691, 3178079, 23970071, 6201893, 49913287, 29065239, 45232588, 19571804, - 32208682, 32356184, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 50451143, 36372074, 56822501, 14811297, 73133531, 46903936, 39793359, 56611021, - 39436277, 22014573, - ]), - y_minus_x: FieldElement2625([ - 15941010, 24148500, 45741813, 8062054, 31876073, 33315803, 51830470, 32110002, - 15397330, 29424239, - ]), - xy2d: FieldElement2625([ - 8934485, 20068965, 43822466, 20131190, 34662773, 14047985, 31170398, 32113411, - 39603297, 15087183, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 115860466, 31397939, 24524912, 16876564, 82629290, 27193655, 118715321, - 11461894, 83897392, 27685489, - ]), - y_minus_x: FieldElement2625([ - 65161459, 16013772, 21750665, 3714552, 49707082, 17498998, 63338576, 23231111, - 31322513, 21938797, - ]), - xy2d: FieldElement2625([ - 21426636, 27904214, 53460576, 28206894, 38296674, 28633461, 48833472, 18933017, - 13040861, 21441484, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 78402740, 46032517, 107081326, 48638180, 104910306, 14748870, 14555558, - 20137329, 68722574, 38451366, - ]), - y_minus_x: FieldElement2625([ - 41213962, 15323293, 58619073, 25496531, 25967125, 20128972, 2825959, 28657387, - 43137087, 22287016, - ]), - xy2d: FieldElement2625([ - 51184079, 28324551, 49665331, 6410663, 3622847, 10243618, 20615400, 12405433, - 43355834, 25118015, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 127126414, 46110638, 114026375, 9025185, 50036385, 4333800, 71487300, 35986461, - 23097948, 32988414, - ]), - y_minus_x: FieldElement2625([ - 4565804, 17528778, 20084411, 25711615, 1724998, 189254, 24767264, 10103221, - 48596551, 2424777, - ]), - xy2d: FieldElement2625([ - 366633, 21577626, 8173089, 26664313, 30788633, 5745705, 59940186, 1344108, - 63466311, 12412658, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 110215918, 41244716, 82038279, 33386174, 102006892, 53695876, 91271559, - 51782359, 63967361, 44733816, - ]), - y_minus_x: FieldElement2625([ - 18289503, 18829478, 8056944, 16430056, 45379140, 7842513, 61107423, 32067534, - 48424218, 22110928, - ]), - xy2d: FieldElement2625([ - 476239, 6601091, 60956074, 23831056, 17503544, 28690532, 27672958, 13403813, - 11052904, 5219329, - ]), - }, - ]), - LookupTable([ - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 87787372, 25178693, 34436965, 42403554, 129207969, 48129182, 98295834, - 29580701, 9014761, 58529808, - ]), - y_minus_x: FieldElement2625([ - 53464795, 23204192, 51146355, 5075807, 65594203, 22019831, 34006363, 9160279, - 8473550, 30297594, - ]), - xy2d: FieldElement2625([ - 24900749, 14435722, 17209120, 18261891, 44516588, 9878982, 59419555, 17218610, - 42540382, 11788947, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 63990690, 22159237, 53306774, 48351872, 76761311, 26708527, 47071426, 43965164, - 42540393, 32095740, - ]), - y_minus_x: FieldElement2625([ - 51449703, 16736705, 44641714, 10215877, 58011687, 7563910, 11871841, 21049238, - 48595538, 8464117, - ]), - xy2d: FieldElement2625([ - 43708233, 8348506, 52522913, 32692717, 63158658, 27181012, 14325288, 8628612, - 33313881, 25183915, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 46921853, 28586496, 89476219, 38825978, 66011746, 28765593, 109412060, - 23317576, 58168128, 61290594, - ]), - y_minus_x: FieldElement2625([ - 60160060, 31759219, 34483180, 17533252, 32635413, 26180187, 15989196, 20716244, - 28358191, 29300528, - ]), - xy2d: FieldElement2625([ - 43547083, 30755372, 34757181, 31892468, 57961144, 10429266, 50471180, 4072015, - 61757200, 5596588, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 105981130, 30164382, 79421759, 39767609, 3117141, 49632997, 29266238, 36111653, - 68877164, 15373192, - ]), - y_minus_x: FieldElement2625([ - 59865506, 30307471, 62515396, 26001078, 66980936, 32642186, 66017961, 29049440, - 42448372, 3442909, - ]), - xy2d: FieldElement2625([ - 36898293, 5124042, 14181784, 8197961, 18964734, 21615339, 22597930, 7176455, - 48523386, 13365929, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 59231455, 32054473, 75433536, 38244510, 73370723, 34444877, 24538106, 24984246, - 57419264, 30522764, - ]), - y_minus_x: FieldElement2625([ - 25008885, 22782833, 62803832, 23916421, 16265035, 15721635, 683793, 21730648, - 15723478, 18390951, - ]), - xy2d: FieldElement2625([ - 57448220, 12374378, 40101865, 26528283, 59384749, 21239917, 11879681, 5400171, - 519526, 32318556, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 22258378, 50776631, 59239045, 14613015, 44588609, 30603508, 46754982, 40870398, - 16648396, 41160072, - ]), - y_minus_x: FieldElement2625([ - 59027556, 25089834, 58885552, 9719709, 19259459, 18206220, 23994941, 28272877, - 57640015, 4763277, - ]), - xy2d: FieldElement2625([ - 45409620, 9220968, 51378240, 1084136, 41632757, 30702041, 31088446, 25789909, - 55752334, 728111, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 26047201, 55357393, 127317403, 50587064, 91200930, 9158118, 62835319, 20998873, - 104852291, 28056158, - ]), - y_minus_x: FieldElement2625([ - 17510331, 33231575, 5854288, 8403524, 17133918, 30441820, 38997856, 12327944, - 10750447, 10014012, - ]), - xy2d: FieldElement2625([ - 56796096, 3936951, 9156313, 24656749, 16498691, 32559785, 39627812, 32887699, - 3424690, 7540221, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 97431206, 26590321, 78469868, 29411114, 74542167, 4989747, 127146306, 50791643, - 57864597, 48812477, - ]), - y_minus_x: FieldElement2625([ - 13054543, 30774935, 19155473, 469045, 54626067, 4566041, 5631406, 2711395, - 1062915, 28418087, - ]), - xy2d: FieldElement2625([ - 47868616, 22299832, 37599834, 26054466, 61273100, 13005410, 61042375, 12194496, - 32960380, 1459310, - ]), - }, - ]), - LookupTable([ - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 86960860, 40582355, 90778216, 43574797, 75695366, 26896524, 67503060, 27452546, - 85746866, 55933926, - ]), - y_minus_x: FieldElement2625([ - 31395515, 15098109, 26581030, 8030562, 50580950, 28547297, 9012485, 25970078, - 60465776, 28111795, - ]), - xy2d: FieldElement2625([ - 57916680, 31207054, 65111764, 4529533, 25766844, 607986, 67095642, 9677542, - 34813975, 27098423, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 64664330, 33404494, 96457765, 8186664, 68982624, 12489862, 103283149, 25714738, - 59256019, 58970434, - ]), - y_minus_x: FieldElement2625([ - 51872508, 18120922, 7766469, 746860, 26346930, 23332670, 39775412, 10754587, - 57677388, 5203575, - ]), - xy2d: FieldElement2625([ - 31834314, 14135496, 66338857, 5159117, 20917671, 16786336, 59640890, 26216907, - 31809242, 7347066, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 57502122, 21680191, 87523322, 46588417, 80825387, 21862550, 86906833, 21343176, - 82301739, 31466941, - ]), - y_minus_x: FieldElement2625([ - 54445282, 31372712, 1168161, 29749623, 26747876, 19416341, 10609329, 12694420, - 33473243, 20172328, - ]), - xy2d: FieldElement2625([ - 33184999, 11180355, 15832085, 22169002, 65475192, 225883, 15089336, 22530529, - 60973201, 14480052, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 98417562, 27934433, 98139703, 31657332, 82783410, 26971548, 72605071, 13685226, - 27595050, 42291707, - ]), - y_minus_x: FieldElement2625([ - 46790012, 18404192, 10933842, 17376410, 8335351, 26008410, 36100512, 20943827, - 26498113, 66511, - ]), - xy2d: FieldElement2625([ - 22644435, 24792703, 50437087, 4884561, 64003250, 19995065, 30540765, 29267685, - 53781076, 26039336, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 106199862, 9834843, 85726071, 30873119, 63706907, 53801357, 75314402, 13585436, - 117090263, 48669869, - ]), - y_minus_x: FieldElement2625([ - 23711543, 32881517, 31206560, 25191721, 6164646, 23844445, 33572981, 32128335, - 8236920, 16492939, - ]), - xy2d: FieldElement2625([ - 43198286, 20038905, 40809380, 29050590, 25005589, 25867162, 19574901, 10071562, - 6708380, 27332008, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 69210217, 28624377, 86811594, 35922006, 118790560, 34602105, 72409880, - 42883131, 29955600, 55430554, - ]), - y_minus_x: FieldElement2625([ - 3096359, 9271816, 45488000, 18032587, 52260867, 25961494, 41216721, 20918836, - 57191288, 6216607, - ]), - xy2d: FieldElement2625([ - 34493015, 338662, 41913253, 2510421, 37895298, 19734218, 24822829, 27407865, - 40341383, 7525078, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 44042196, 53123240, 83242349, 25658253, 130828162, 34333218, 66198527, - 30771936, 47722230, 45548532, - ]), - y_minus_x: FieldElement2625([ - 21691500, 19929806, 66467532, 19187410, 3285880, 30070836, 42044197, 9718257, - 59631427, 13381417, - ]), - xy2d: FieldElement2625([ - 18445390, 29352196, 14979845, 11622458, 65381754, 29971451, 23111647, 27179185, - 28535281, 15779576, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 30098034, 36644094, 124983340, 16662133, 45801924, 44862842, 53040409, - 12021729, 77064149, 17251075, - ]), - y_minus_x: FieldElement2625([ - 9734894, 18977602, 59635230, 24415696, 2060391, 11313496, 48682835, 9924398, - 20194861, 13380996, - ]), - xy2d: FieldElement2625([ - 40730762, 25589224, 44941042, 15789296, 49053522, 27385639, 65123949, 15707770, - 26342023, 10146099, - ]), - }, - ]), - LookupTable([ - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 41091971, 33334488, 88448054, 33513043, 86854119, 30675731, 37471583, 35781471, - 21612325, 33008704, - ]), - y_minus_x: FieldElement2625([ - 54031477, 1184227, 23562814, 27583990, 46757619, 27205717, 25764460, 12243797, - 46252298, 11649657, - ]), - xy2d: FieldElement2625([ - 57077370, 11262625, 27384172, 2271902, 26947504, 17556661, 39943, 6114064, - 33514190, 2333242, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 112784121, 54687041, 75228644, 40774344, 45278341, 58092729, 60429112, - 54438225, 91459440, 20104430, - ]), - y_minus_x: FieldElement2625([ - 62992557, 22282898, 43222677, 4843614, 37020525, 690622, 35572776, 23147595, - 8317859, 12352766, - ]), - xy2d: FieldElement2625([ - 18200138, 19078521, 34021104, 30857812, 43406342, 24451920, 43556767, 31266881, - 20712162, 6719373, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 26656189, 39629685, 59250307, 35440503, 105873684, 37816756, 78226393, - 29791221, 26224234, 30256974, - ]), - y_minus_x: FieldElement2625([ - 49939907, 18700334, 63713187, 17184554, 47154818, 14050419, 21728352, 9493610, - 18620611, 17125804, - ]), - xy2d: FieldElement2625([ - 53785524, 13325348, 11432106, 5964811, 18609221, 6062965, 61839393, 23828875, - 36407290, 17074774, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 43248307, 55875704, 94070219, 35195292, 34695751, 16816491, 79357372, 28313792, - 80844205, 35488493, - ]), - y_minus_x: FieldElement2625([ - 25089769, 6742589, 17081145, 20148166, 21909292, 17486451, 51972569, 29789085, - 45830866, 5473615, - ]), - xy2d: FieldElement2625([ - 31883658, 25593331, 1083431, 21982029, 22828470, 13290673, 59983779, 12469655, - 29111212, 28103418, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 91353792, 52058456, 107954750, 36345970, 52111264, 50221109, 91476329, - 39943270, 56813276, 34006814, - ]), - y_minus_x: FieldElement2625([ - 41468082, 30136590, 5217915, 16224624, 19987036, 29472163, 42872612, 27639183, - 15766061, 8407814, - ]), - xy2d: FieldElement2625([ - 46701865, 13990230, 15495425, 16395525, 5377168, 15166495, 58191841, 29165478, - 59040954, 2276717, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 30157899, 46478498, 116505677, 42800183, 87003891, 36922573, 43281276, - 38650650, 89849239, 26251014, - ]), - y_minus_x: FieldElement2625([ - 2041139, 19298082, 7783686, 13876377, 41161879, 20201972, 24051123, 13742383, - 51471265, 13295221, - ]), - xy2d: FieldElement2625([ - 33338218, 25048699, 12532112, 7977527, 9106186, 31839181, 49388668, 28941459, - 62657506, 18884987, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 47063564, 39008528, 52762315, 40001577, 28862070, 35438083, 64639597, 29412551, - 74879432, 43175028, - ]), - y_minus_x: FieldElement2625([ - 23208049, 7979712, 33071466, 8149229, 1758231, 22719437, 30945527, 31860109, - 33606523, 18786461, - ]), - xy2d: FieldElement2625([ - 1439939, 17283952, 66028874, 32760649, 4625401, 10647766, 62065063, 1220117, - 30494170, 22113633, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 62071265, 20526136, 64138304, 30492664, 82749837, 26852765, 40369837, 34480481, - 65424524, 20220784, - ]), - y_minus_x: FieldElement2625([ - 13908495, 30005160, 30919927, 27280607, 45587000, 7989038, 9021034, 9078865, - 3353509, 4033511, - ]), - xy2d: FieldElement2625([ - 37445433, 18440821, 32259990, 33209950, 24295848, 20642309, 23161162, 8839127, - 27485041, 7356032, - ]), - }, - ]), - LookupTable([ - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 76769853, 34259874, 79088928, 28184277, 65480320, 14661172, 60762722, 36179446, - 95539899, 50337029, - ]), - y_minus_x: FieldElement2625([ - 43269631, 25243016, 41163352, 7480957, 49427195, 25200248, 44562891, 14150564, - 15970762, 4099461, - ]), - xy2d: FieldElement2625([ - 29262576, 16756590, 26350592, 24760869, 8529670, 22346382, 13617292, 23617289, - 11465738, 8317062, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 41615764, 26591503, 99609063, 24135380, 44070139, 31252209, 82007500, 37402886, - 88078197, 28396915, - ]), - y_minus_x: FieldElement2625([ - 46724414, 19206718, 48772458, 13884721, 34069410, 2842113, 45498038, 29904543, - 11177094, 14989547, - ]), - xy2d: FieldElement2625([ - 42612143, 21838415, 16959895, 2278463, 12066309, 10137771, 13515641, 2581286, - 38621356, 9930239, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 49357223, 31456605, 83653163, 54099563, 118302919, 18605349, 18345766, - 53705111, 83400343, 28240393, - ]), - y_minus_x: FieldElement2625([ - 33879670, 2553287, 32678213, 9875984, 8534129, 6889387, 57432090, 6957616, - 4368891, 9788741, - ]), - xy2d: FieldElement2625([ - 16660737, 7281060, 56278106, 12911819, 20108584, 25452756, 45386327, 24941283, - 16250551, 22443329, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 47343357, 35944957, 117666696, 14161978, 69014150, 39969338, 71798447, - 10604806, 104027325, 4782745, - ]), - y_minus_x: FieldElement2625([ - 65754325, 14736940, 59741422, 20261545, 7710541, 19398842, 57127292, 4383044, - 22546403, 437323, - ]), - xy2d: FieldElement2625([ - 31665558, 21373968, 50922033, 1491338, 48740239, 3294681, 27343084, 2786261, - 36475274, 19457415, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 52641566, 32870716, 33734756, 41002983, 19294359, 14334329, 47418233, 35909750, - 47824192, 27440058, - ]), - y_minus_x: FieldElement2625([ - 15121312, 17758270, 6377019, 27523071, 56310752, 20596586, 18952176, 15496498, - 37728731, 11754227, - ]), - xy2d: FieldElement2625([ - 64471568, 20071356, 8488726, 19250536, 12728760, 31931939, 7141595, 11724556, - 22761615, 23420291, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 16918416, 11729663, 49025285, 36577418, 103201995, 53769203, 38367677, - 21327038, 32851221, 11717399, - ]), - y_minus_x: FieldElement2625([ - 11166615, 7338049, 60386341, 4531519, 37640192, 26252376, 31474878, 3483633, - 65915689, 29523600, - ]), - xy2d: FieldElement2625([ - 66923210, 9921304, 31456609, 20017994, 55095045, 13348922, 33142652, 6546660, - 47123585, 29606055, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 101757113, 44821142, 55911756, 25655328, 31703693, 37410335, 58571732, - 20721383, 36336829, 18068118, - ]), - y_minus_x: FieldElement2625([ - 49102387, 12709067, 3991746, 27075244, 45617340, 23004006, 35973516, 17504552, - 10928916, 3011958, - ]), - xy2d: FieldElement2625([ - 60151107, 17960094, 31696058, 334240, 29576716, 14796075, 36277808, 20749251, - 18008030, 10258577, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 44660220, 49210000, 74127342, 29144428, 36794597, 32352840, 65255398, 34921551, - 92236737, 6671742, - ]), - y_minus_x: FieldElement2625([ - 29701166, 19180498, 56230743, 9279287, 67091296, 13127209, 21382910, 11042292, - 25838796, 4642684, - ]), - xy2d: FieldElement2625([ - 46678630, 14955536, 42982517, 8124618, 61739576, 27563961, 30468146, 19653792, - 18423288, 4177476, - ]), - }, - ]), - ]); - -/// Odd multiples of the basepoint `[B, 3B, 5B, 7B, 9B, 11B, 13B, 15B, ..., 127B]`. -pub(crate) const AFFINE_ODD_MULTIPLES_OF_BASEPOINT: NafLookupTable8 = - NafLookupTable8([ - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 93076338, 52752828, 29566454, 37215328, 54414518, 37569218, 94653489, 21800160, - 61029707, 35602036, - ]), - y_minus_x: FieldElement2625([ - 54563134, 934261, 64385954, 3049989, 66381436, 9406985, 12720692, 5043384, - 19500929, 18085054, - ]), - xy2d: FieldElement2625([ - 58370664, 4489569, 9688441, 18769238, 10184608, 21191052, 29287918, 11864899, - 42594502, 29115885, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 82745136, 23865874, 24204772, 25642034, 67725840, 16869169, 94896463, 52336674, - 28944398, 32004408, - ]), - y_minus_x: FieldElement2625([ - 16568933, 4717097, 55552716, 32452109, 15682895, 21747389, 16354576, 21778470, - 7689661, 11199574, - ]), - xy2d: FieldElement2625([ - 30464137, 27578307, 55329429, 17883566, 23220364, 15915852, 7512774, 10017326, - 49359771, 23634074, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 77970208, 11473153, 27284546, 35535607, 37044514, 46132292, 99976748, 48069538, - 118779423, 44373810, - ]), - y_minus_x: FieldElement2625([ - 4708026, 6336745, 20377586, 9066809, 55836755, 6594695, 41455196, 12483687, - 54440373, 5581305, - ]), - xy2d: FieldElement2625([ - 19563141, 16186464, 37722007, 4097518, 10237984, 29206317, 28542349, 13850243, - 43430843, 17738489, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 72262591, 43463716, 68832610, 30776557, 97632468, 39071304, 86589715, 38784565, - 43156424, 18378665, - ]), - y_minus_x: FieldElement2625([ - 36839857, 30090922, 7665485, 10083793, 28475525, 1649722, 20654025, 16520125, - 30598449, 7715701, - ]), - xy2d: FieldElement2625([ - 28881826, 14381568, 9657904, 3680757, 46927229, 7843315, 35708204, 1370707, - 29794553, 32145132, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 44589852, 26862249, 14201701, 24808930, 43598457, 42399157, 85583074, 32192981, - 54046167, 47376308, - ]), - y_minus_x: FieldElement2625([ - 60653668, 25714560, 3374701, 28813570, 40010246, 22982724, 31655027, 26342105, - 18853321, 19333481, - ]), - xy2d: FieldElement2625([ - 4566811, 20590564, 38133974, 21313742, 59506191, 30723862, 58594505, 23123294, - 2207752, 30344648, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 41954014, 62923042, 96790006, 41423232, 60254202, 24130566, 121780363, 32891430, - 103106264, 17421994, - ]), - y_minus_x: FieldElement2625([ - 25576264, 30851218, 7349803, 21739588, 16472781, 9300885, 3844789, 15725684, - 171356, 6466918, - ]), - xy2d: FieldElement2625([ - 23103977, 13316479, 9739013, 17404951, 817874, 18515490, 8965338, 19466374, - 36393951, 16193876, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 100695917, 36735143, 64714733, 47558118, 50205389, 17283591, 84347261, 38283886, - 49034350, 9256799, - ]), - y_minus_x: FieldElement2625([ - 41926547, 29380300, 32336397, 5036987, 45872047, 11360616, 22616405, 9761698, - 47281666, 630304, - ]), - xy2d: FieldElement2625([ - 53388152, 2639452, 42871404, 26147950, 9494426, 27780403, 60554312, 17593437, - 64659607, 19263131, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 63957664, 28508356, 76391577, 40420576, 102310665, 32691407, 48168288, 15033783, - 92213982, 25659555, - ]), - y_minus_x: FieldElement2625([ - 42782475, 15950225, 35307649, 18961608, 55446126, 28463506, 1573891, 30928545, - 2198789, 17749813, - ]), - xy2d: FieldElement2625([ - 64009494, 10324966, 64867251, 7453182, 61661885, 30818928, 53296841, 17317989, - 34647629, 21263748, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 17735022, 27114469, 76149336, 40765111, 43325570, 26153544, 26948151, 45905235, - 38656900, 62179684, - ]), - y_minus_x: FieldElement2625([ - 2154119, 14782993, 28737794, 11906199, 36205504, 26488101, 19338132, 16910143, - 50209922, 29794297, - ]), - xy2d: FieldElement2625([ - 29935700, 6336041, 20999566, 30405369, 13628497, 24612108, 61639745, 22359641, - 56973806, 18684690, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 29792811, 31379227, 113441390, 20675662, 58452680, 54138549, 42892249, 32958636, - 31674345, 24275271, - ]), - y_minus_x: FieldElement2625([ - 7606599, 22131225, 17376912, 15235046, 32822971, 7512882, 30227203, 14344178, - 9952094, 8804749, - ]), - xy2d: FieldElement2625([ - 32575079, 3961822, 36404898, 17773250, 67073898, 1319543, 30641032, 7823672, - 63309858, 18878784, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 77823924, 52933642, 26572931, 18690221, 109143683, 23989794, 79129572, 53326100, - 38888709, 55889506, - ]), - y_minus_x: FieldElement2625([ - 37146997, 554126, 63326061, 20925660, 49205290, 8620615, 53375504, 25938867, - 8752612, 31225894, - ]), - xy2d: FieldElement2625([ - 4529887, 12416158, 60388162, 30157900, 15427957, 27628808, 61150927, 12724463, - 23658330, 23690055, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 102043267, 54823614, 45810225, 19657305, 54297192, 7413280, 66851983, 39718512, - 25005048, 18002658, - ]), - y_minus_x: FieldElement2625([ - 5403481, 24654166, 61855580, 13522652, 14989680, 1879017, 43913069, 25724172, - 20315901, 421248, - ]), - xy2d: FieldElement2625([ - 34818947, 1705239, 25347020, 7938434, 51632025, 1720023, 54809726, 32655885, - 64907986, 5517607, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 88543525, 16557377, 80359887, 30047148, 91602876, 27723948, 62710290, 52707861, - 7715736, 61648232, - ]), - y_minus_x: FieldElement2625([ - 14461032, 6393639, 22681353, 14533514, 52493587, 3544717, 57780998, 24657863, - 59891807, 31628125, - ]), - xy2d: FieldElement2625([ - 60864886, 31199953, 18524951, 11247802, 43517645, 21165456, 26204394, 27268421, - 63221077, 29979135, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 97491378, 10077555, 94805128, 42472719, 30231379, 17961119, 76201413, 41182329, - 41405214, 31798052, - ]), - y_minus_x: FieldElement2625([ - 13670592, 720327, 7131696, 19360499, 66651570, 16947532, 3061924, 22871019, - 39814495, 20141336, - ]), - xy2d: FieldElement2625([ - 44847187, 28379568, 38472030, 23697331, 49441718, 3215393, 1669253, 30451034, - 62323912, 29368533, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 74923758, 35244493, 27222384, 30715870, 48444195, 28125622, 116052444, 32330148, - 92609232, 35372537, - ]), - y_minus_x: FieldElement2625([ - 39340596, 15199968, 52787715, 18781603, 18787729, 5464578, 11652644, 8722118, - 57056621, 5153960, - ]), - xy2d: FieldElement2625([ - 5733861, 14534448, 59480402, 15892910, 30737296, 188529, 491756, 17646733, - 33071791, 15771063, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 85239571, 21331573, 119690709, 30172286, 44350959, 55826224, 68258766, 16209406, - 20222151, 32139086, - ]), - y_minus_x: FieldElement2625([ - 52372801, 13847470, 52690845, 3802477, 48387139, 10595589, 13745896, 3112846, - 50361463, 2761905, - ]), - xy2d: FieldElement2625([ - 45982696, 12273933, 15897066, 704320, 31367969, 3120352, 11710867, 16405685, - 19410991, 10591627, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 82008850, 34439758, 89319886, 49124188, 34309215, 29866047, 80308709, 27738519, - 71739865, 46909287, - ]), - y_minus_x: FieldElement2625([ - 36631997, 23300851, 59535242, 27474493, 59924914, 29067704, 17551261, 13583017, - 37580567, 31071178, - ]), - xy2d: FieldElement2625([ - 22641770, 21277083, 10843473, 1582748, 37504588, 634914, 15612385, 18139122, - 59415250, 22563863, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 76721854, 52814714, 41722368, 35285867, 53022548, 38255176, 93163883, 27627617, - 87963092, 33729456, - ]), - y_minus_x: FieldElement2625([ - 61915349, 11733561, 59403492, 31381562, 29521830, 16845409, 54973419, 26057054, - 49464700, 796779, - ]), - xy2d: FieldElement2625([ - 3855018, 8248512, 12652406, 88331, 2948262, 971326, 15614761, 9441028, 29507685, - 8583792, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 76968870, 14808584, 76708906, 57649718, 23400175, 24077237, 63783137, 37471119, - 56750251, 30681804, - ]), - y_minus_x: FieldElement2625([ - 33709664, 3740344, 52888604, 25059045, 46197996, 22678812, 45207164, 6431243, - 21300862, 27646257, - ]), - xy2d: FieldElement2625([ - 49811511, 9216232, 25043921, 18738174, 29145960, 3024227, 65580502, 530149, - 66809973, 22275500, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 23499366, 24936714, 38355445, 35908587, 82540167, 39280880, 46809413, 41143783, - 72530804, 49676198, - ]), - y_minus_x: FieldElement2625([ - 45162189, 23851397, 9380591, 15192763, 36034862, 15525765, 5277811, 25040629, - 33286237, 31693326, - ]), - xy2d: FieldElement2625([ - 62424427, 13336013, 49368582, 1581264, 30884213, 15048226, 66823504, 4736577, - 53805192, 29608355, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 25190215, 26304748, 58928336, 42665707, 64280342, 38580230, 61299598, 20659504, - 30387592, 32519377, - ]), - y_minus_x: FieldElement2625([ - 14480213, 17057820, 2286692, 32980967, 14693157, 22197912, 49247898, 9909859, - 236428, 16857435, - ]), - xy2d: FieldElement2625([ - 7877514, 29872867, 45886243, 25902853, 41998762, 6241604, 35694938, 15657879, - 56797932, 8609105, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 54245189, 32562161, 57887697, 19509733, 45323534, 37472546, 27606727, 59528498, - 74398957, 44973176, - ]), - y_minus_x: FieldElement2625([ - 28964163, 20950093, 44929966, 26145892, 34786807, 18058153, 18187179, 27016486, - 42438836, 14869174, - ]), - xy2d: FieldElement2625([ - 55703901, 1222455, 64329400, 24533246, 11330890, 9135834, 3589529, 19555234, - 53275553, 1207212, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 33323313, 35603165, 79328585, 6017848, 71286345, 23804207, 86644124, 44008367, - 55775078, 31816581, - ]), - y_minus_x: FieldElement2625([ - 64814718, 27217688, 29891310, 4504619, 8548709, 21986323, 62140656, 12555980, - 34377058, 21436823, - ]), - xy2d: FieldElement2625([ - 49069441, 9880212, 33350825, 24576421, 24446077, 15616561, 19302117, 9370836, - 55172180, 28526191, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 95404934, 26757208, 123864063, 4572839, 69249194, 43584425, 53559055, 41742046, - 41167331, 24643278, - ]), - y_minus_x: FieldElement2625([ - 35101859, 30958612, 66105296, 3168612, 22836264, 10055966, 22893634, 13045780, - 28576558, 30704591, - ]), - xy2d: FieldElement2625([ - 59987873, 21166324, 43296694, 15387892, 39447987, 19996270, 5059183, 19972934, - 30207804, 29631666, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 67444156, 16132892, 88330413, 37924284, 68147855, 57949418, 91481571, 24889160, - 62329722, 50712214, - ]), - y_minus_x: FieldElement2625([ - 56922508, 1347520, 23300731, 27393371, 42651667, 8512932, 27610931, 24436993, - 3998295, 3835244, - ]), - xy2d: FieldElement2625([ - 16327050, 22776956, 14746360, 22599650, 23700920, 11727222, 25900154, 21823218, - 34907363, 25105813, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 59807886, 12089757, 115624210, 41476837, 67589715, 26361580, 71355762, 44268661, - 67753061, 13128476, - ]), - y_minus_x: FieldElement2625([ - 7174885, 26592113, 59892333, 6465478, 4145835, 17673606, 38764952, 22293290, - 1360980, 25805937, - ]), - xy2d: FieldElement2625([ - 40179568, 6331649, 42386021, 20205884, 15635073, 6103612, 56391180, 6789942, - 7597240, 24095312, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 54776568, 36935932, 18757261, 41429535, 67215081, 34700142, 86560976, 61204154, - 26496794, 19612129, - ]), - y_minus_x: FieldElement2625([ - 46701540, 24101444, 49515651, 25946994, 45338156, 9941093, 55509371, 31298943, - 1347425, 15381335, - ]), - xy2d: FieldElement2625([ - 53576449, 26135856, 17092785, 3684747, 57829121, 27109516, 2987881, 10987137, - 52269096, 15465522, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 80033010, 26264316, 72380996, 10039544, 94605936, 30615493, 60406855, 30400829, - 120765849, 45301372, - ]), - y_minus_x: FieldElement2625([ - 35668062, 24246990, 47788280, 25128298, 37456967, 19518969, 43459670, 10724644, - 7294162, 4471290, - ]), - xy2d: FieldElement2625([ - 33813988, 3549109, 101112, 21464449, 4858392, 3029943, 59999440, 21424738, - 34313875, 1512799, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 29494960, 28240930, 51093230, 28823678, 92791151, 54796794, 77571888, 37795542, - 75765856, 10649531, - ]), - y_minus_x: FieldElement2625([ - 63536751, 7572551, 62249759, 25202639, 32046232, 32318941, 29315141, 15424555, - 24706712, 28857648, - ]), - xy2d: FieldElement2625([ - 47618751, 5819839, 19528172, 20715950, 40655763, 20611047, 4960954, 6496879, - 2790858, 28045273, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 85174457, 55843901, 111946683, 31021158, 32797785, 48944265, 78338887, 31144772, - 82688001, 38470222, - ]), - y_minus_x: FieldElement2625([ - 49664705, 3638040, 57888693, 19234931, 40104182, 28143840, 28667142, 18386877, - 18584835, 3592929, - ]), - xy2d: FieldElement2625([ - 12065039, 18867394, 6430594, 17107159, 1727094, 13096957, 61520237, 27056604, - 27026997, 13543966, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 68512926, 37577278, 94695528, 14209106, 95849194, 30038709, 51818051, 20241476, - 68980056, 42251074, - ]), - y_minus_x: FieldElement2625([ - 17325298, 33376175, 65271265, 4931225, 31708266, 6292284, 23064744, 22072792, - 43945505, 9236924, - ]), - xy2d: FieldElement2625([ - 51955585, 20268063, 61151838, 26383348, 4766519, 20788033, 21173534, 27030753, - 9509140, 7790046, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 24124086, 38918775, 28620390, 10538620, 59433851, 19581010, 60862718, 43500219, - 77600721, 32213801, - ]), - y_minus_x: FieldElement2625([ - 7062127, 13930079, 2259902, 6463144, 32137099, 24748848, 41557343, 29331342, - 47345194, 13022814, - ]), - xy2d: FieldElement2625([ - 18921826, 392002, 55817981, 6420686, 8000611, 22415972, 14722962, 26246290, - 20604450, 8079345, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 67710253, 26257798, 51499391, 46550521, 30228769, 53940987, 76234206, 43362242, - 77953697, 21034392, - ]), - y_minus_x: FieldElement2625([ - 25817710, 8020883, 50134679, 21244805, 47057788, 8766556, 29308546, 22307963, - 49449920, 23874253, - ]), - xy2d: FieldElement2625([ - 11081015, 13522660, 12474691, 29260223, 48687631, 9341946, 16850694, 18637605, - 6199839, 14303642, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 64518173, 19894035, 117213833, 43031641, 79641718, 39533880, 66531934, 41205092, - 117735515, 13989682, - ]), - y_minus_x: FieldElement2625([ - 6921800, 4421166, 59739491, 30510778, 43106355, 30941531, 9363541, 3394240, - 50874187, 23872585, - ]), - xy2d: FieldElement2625([ - 54293979, 23466866, 47184247, 20627378, 8313211, 5865878, 5948507, 32290343, - 52583140, 23139870, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 111574723, 24134616, 49842442, 23485580, 34844037, 45228427, 67103167, 25858409, - 38508586, 35097070, - ]), - y_minus_x: FieldElement2625([ - 19879846, 15259900, 25020018, 14261729, 22075205, 25189303, 787540, 31325033, - 62422289, 16131171, - ]), - xy2d: FieldElement2625([ - 39487053, 27893575, 34654176, 25620816, 60209846, 23603919, 8931189, 12275052, - 38626469, 33438928, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 105416367, 9568747, 62672739, 49685015, 106242995, 4547918, 18403901, 38581738, - 60829966, 33150322, - ]), - y_minus_x: FieldElement2625([ - 7950033, 25841033, 47276506, 3884935, 62418883, 2342083, 50269031, 14194015, - 27013685, 3320257, - ]), - xy2d: FieldElement2625([ - 35270691, 18076829, 46994271, 4273335, 43595882, 31742297, 58328702, 4594760, - 49180851, 18144010, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 30194115, 50068680, 49746331, 27470090, 40428285, 23271051, 70252167, 16153483, - 123511881, 27809602, - ]), - y_minus_x: FieldElement2625([ - 27113466, 6865046, 4512771, 29327742, 29021084, 7405965, 33302911, 9322435, - 4307527, 32438240, - ]), - xy2d: FieldElement2625([ - 29337813, 24673346, 10359233, 30347534, 57709483, 9930840, 60607771, 24076133, - 20985293, 22480923, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 14579237, 33467236, 85745988, 15769997, 101228358, 21649866, 82685456, 59023858, - 86175344, 24337101, - ]), - y_minus_x: FieldElement2625([ - 4472119, 14702190, 10432042, 22460027, 708461, 18783996, 34234374, 30870323, - 63796457, 10370850, - ]), - xy2d: FieldElement2625([ - 36957127, 19555637, 16244231, 24367549, 58999881, 13440043, 35147632, 8718974, - 43101064, 18487380, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 21818223, 34477173, 23913863, 22441963, 129271975, 14842154, 43035020, 9485973, - 53819529, 22318987, - ]), - y_minus_x: FieldElement2625([ - 10874834, 4351765, 66252340, 17269436, 64427034, 30735311, 5883785, 28998531, - 44403022, 26064601, - ]), - xy2d: FieldElement2625([ - 64017630, 9755550, 37507935, 22752543, 4031638, 29903925, 47267417, 32706846, - 39147952, 21635901, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 81365001, 44927611, 97395185, 43985591, 66242539, 38517499, 52937891, 37374973, - 73352483, 38476849, - ]), - y_minus_x: FieldElement2625([ - 43460763, 24260930, 21493330, 30888969, 23329454, 24545577, 58286855, 12750266, - 22391140, 26198125, - ]), - xy2d: FieldElement2625([ - 20477567, 24078713, 1674568, 4102219, 25208396, 13972305, 30389482, 19572626, - 1485666, 17679765, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 100511110, 23887606, 116505658, 30877106, 45483774, 25222431, 67931340, 37154158, - 32618865, 18610785, - ]), - y_minus_x: FieldElement2625([ - 48647066, 166413, 55454758, 8889513, 21027475, 32728181, 43100067, 4690060, - 7520989, 16421303, - ]), - xy2d: FieldElement2625([ - 14868391, 20996450, 64836606, 1042490, 27060176, 10253541, 53431276, 19516737, - 41808946, 2239538, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 50228416, 29594943, 62030348, 10307368, 70970997, 20292574, 126292474, 51543890, - 67827181, 15848795, - ]), - y_minus_x: FieldElement2625([ - 5548701, 17911007, 33137864, 32764443, 31146554, 17931096, 64023370, 7290289, - 6361313, 32861205, - ]), - xy2d: FieldElement2625([ - 63374742, 30320053, 4091667, 30955480, 44819449, 2212055, 52638826, 22391938, - 38484599, 7051029, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 50485560, 7033600, 57711425, 10740562, 72347547, 42328739, 7593987, 46950560, - 85560721, 41970063, - ]), - y_minus_x: FieldElement2625([ - 40930651, 3776911, 39108529, 2508077, 19371703, 7626128, 4092943, 15778278, - 42044145, 24540103, - ]), - xy2d: FieldElement2625([ - 44128555, 8867576, 8645499, 22222278, 11497130, 4344907, 10788462, 23382703, - 3547104, 15368835, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 81786515, 51902785, 74560130, 22753403, 52379722, 41395524, 57994925, 6818020, - 57707296, 16352835, - ]), - y_minus_x: FieldElement2625([ - 21622574, 18581624, 36511951, 1212467, 36930308, 7910192, 20622927, 2438677, - 52628762, 29068327, - ]), - xy2d: FieldElement2625([ - 6797431, 2854059, 4269865, 8037366, 32016522, 15223213, 34765784, 15297582, - 3559197, 26425254, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 107761639, 61759660, 79235166, 8794359, 48418924, 60111631, 87862210, 33613219, - 68436482, 40229362, - ]), - y_minus_x: FieldElement2625([ - 52388944, 32880897, 37676257, 8253690, 32826330, 2707379, 25088512, 17182878, - 15053907, 11601568, - ]), - xy2d: FieldElement2625([ - 43894091, 25425955, 50962615, 28097648, 30129084, 13258436, 39364589, 8197601, - 58181660, 15003422, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 13470722, 47835674, 31012390, 30525035, 89789519, 50713267, 39648035, 13815677, - 94028755, 62582101, - ]), - y_minus_x: FieldElement2625([ - 54478677, 14782829, 56712503, 7094748, 41775828, 29409658, 9084386, 30179063, - 64014926, 32519086, - ]), - xy2d: FieldElement2625([ - 6314429, 20018828, 12535891, 19610611, 10074031, 28087963, 50489447, 26314252, - 24553876, 32746308, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 105768482, 46629424, 103418946, 65789027, 85765355, 28316167, 56299027, 22780838, - 122676432, 32376204, - ]), - y_minus_x: FieldElement2625([ - 5654403, 26425050, 39347935, 963424, 5032477, 19850195, 30011537, 11153401, - 63182039, 13343989, - ]), - xy2d: FieldElement2625([ - 1130444, 29814849, 40569426, 8144467, 24179188, 6267924, 63847147, 2912740, - 63870704, 29186744, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 49722534, 11073633, 52865263, 50829611, 33921405, 38614719, 32360242, 35465390, - 50107050, 45035301, - ]), - y_minus_x: FieldElement2625([ - 2003571, 2472803, 46902183, 1716406, 58609069, 15922982, 43766122, 27456369, - 33468339, 29346282, - ]), - xy2d: FieldElement2625([ - 18834217, 8245144, 29896065, 3490830, 62967493, 7220277, 146130, 18459164, - 57533060, 30070422, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 77805507, 38474121, 73459597, 18553340, 107508318, 52705654, 33655873, 27331956, - 44498407, 13768350, - ]), - y_minus_x: FieldElement2625([ - 23652128, 27647291, 43351590, 13262712, 65238054, 26296349, 11902126, 2949002, - 34445239, 25602117, - ]), - xy2d: FieldElement2625([ - 55906958, 19046111, 28501158, 28224561, 14495533, 14714956, 32929972, 2643566, - 17034893, 11645825, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 38181639, 29751709, 73650473, 17760526, 80753587, 17992258, 72670209, 41214427, - 87524152, 37630124, - ]), - y_minus_x: FieldElement2625([ - 6498441, 12053607, 10375600, 14764370, 24795955, 16159258, 57849421, 16071837, - 31008329, 3792564, - ]), - xy2d: FieldElement2625([ - 47930485, 9176956, 54248931, 8732776, 58000258, 10333519, 96092, 29273884, - 13051277, 20121493, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 54190492, 49837594, 61282066, 10734597, 67926686, 36967416, 115462142, 30339271, - 37200685, 30036936, - ]), - y_minus_x: FieldElement2625([ - 21193614, 19929501, 18841215, 29565554, 64002173, 11123558, 14111648, 6069945, - 30307604, 25935103, - ]), - xy2d: FieldElement2625([ - 58539773, 2098685, 38301131, 15844175, 41633654, 16934366, 15145895, 5543861, - 64050790, 6595361, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 34107945, 34731353, 51956038, 5614778, 79079051, 30288154, 47460410, 22186730, - 30689695, 19628976, - ]), - y_minus_x: FieldElement2625([ - 25043248, 19224237, 46048097, 32289319, 29339134, 12397721, 37385860, 12978240, - 57951631, 31419653, - ]), - xy2d: FieldElement2625([ - 46038439, 28501736, 62566522, 12609283, 35236982, 30457796, 64113609, 14800343, - 6412849, 6276813, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 124528774, 39505727, 83050803, 41361190, 116071796, 37845759, 61633481, 38385016, - 71255100, 31629488, - ]), - y_minus_x: FieldElement2625([ - 249426, 17196749, 35434953, 13884216, 11701636, 24553269, 51821986, 12900910, - 34844073, 16150118, - ]), - xy2d: FieldElement2625([ - 2520516, 14697628, 15319213, 22684490, 62866663, 29666431, 13872507, 7473319, - 12419515, 2958466, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 101517167, 22298305, 98222207, 59471046, 61547444, 50370568, 97111094, 42539051, - 14298448, 49873561, - ]), - y_minus_x: FieldElement2625([ - 19427905, 12004555, 9971383, 28189868, 32306269, 23648270, 34176633, 10760437, - 53354280, 5634974, - ]), - xy2d: FieldElement2625([ - 30044319, 23677863, 60273406, 14563839, 9734978, 19808149, 30899064, 30835691, - 22828539, 23633348, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 25513026, 37111929, 37113703, 29589233, 77394412, 34745965, 95889446, 61766763, - 92876242, 37566563, - ]), - y_minus_x: FieldElement2625([ - 42139852, 9176396, 16274786, 33467453, 52558621, 7190768, 1490604, 31312359, - 44767199, 18491072, - ]), - xy2d: FieldElement2625([ - 4272877, 21431483, 45594743, 13027605, 59232641, 24151956, 38390319, 12906718, - 45915869, 15503563, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 29874396, 35808736, 25494239, 37976524, 43036007, 37144111, 18198811, 35141252, - 53490316, 47742788, - ]), - y_minus_x: FieldElement2625([ - 59518553, 28520621, 59946871, 29462027, 3630300, 29398589, 60425462, 24588735, - 53129947, 28399367, - ]), - xy2d: FieldElement2625([ - 18192774, 12787801, 32021061, 9158184, 48389348, 16385092, 11799402, 9492011, - 43154220, 15950102, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 68768204, 54638026, 33464925, 53430209, 66037964, 35360373, 22565155, 39168685, - 46605438, 51897954, - ]), - y_minus_x: FieldElement2625([ - 57660336, 29715319, 64414626, 32753338, 16894121, 935644, 53848937, 22684138, - 10541713, 14174330, - ]), - xy2d: FieldElement2625([ - 22888141, 12700209, 40301697, 6435658, 56329485, 5524686, 56715961, 6520808, - 15754965, 9355803, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 79549820, 26746924, 54931884, 38547877, 49672847, 19708985, 52599424, 12757151, - 93328625, 39524327, - ]), - y_minus_x: FieldElement2625([ - 33888606, 13911610, 18921581, 1162763, 46616901, 13799218, 29525142, 21929286, - 59295464, 503508, - ]), - xy2d: FieldElement2625([ - 57865531, 22043577, 17998312, 3038439, 52838371, 9832208, 43311531, 660991, - 25265267, 18977724, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 64010269, 23727746, 42277281, 48089313, 102316973, 34946803, 127880577, 38411468, - 114816699, 43712746, - ]), - y_minus_x: FieldElement2625([ - 56859315, 32558245, 41017090, 22610758, 13704990, 23215119, 2475037, 32344984, - 12799418, 11135856, - ]), - xy2d: FieldElement2625([ - 1867214, 27167702, 19772099, 16925005, 15366693, 25797692, 10829276, 15372827, - 26582557, 31642714, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 57265197, 20059797, 107314987, 30587501, 60553812, 25602102, 29690666, 37127097, - 103070929, 51772159, - ]), - y_minus_x: FieldElement2625([ - 56432653, 6329655, 42770975, 4187982, 30677076, 9335071, 60103332, 14755050, - 9451294, 574767, - ]), - xy2d: FieldElement2625([ - 52859018, 2867107, 56258365, 15719081, 5959372, 8703738, 29137781, 21575537, - 20249840, 31808689, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 74749335, 47235127, 9995910, 52200224, 92069015, 8964515, 33248715, 21201554, - 57573145, 31605506, - ]), - y_minus_x: FieldElement2625([ - 56307055, 23891752, 3613811, 30787942, 49031222, 26667524, 26985478, 31973510, - 26785294, 29587427, - ]), - xy2d: FieldElement2625([ - 30891460, 5254655, 47414930, 12769216, 42912782, 11830405, 7411958, 1394027, - 18778535, 18209370, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 61227949, 26179350, 57501473, 13585864, 102855675, 40344975, 54134826, 59707765, - 74122694, 12256219, - ]), - y_minus_x: FieldElement2625([ - 5975515, 16302413, 24341148, 28270615, 18786096, 22405501, 28243950, 28328004, - 53412289, 4381960, - ]), - xy2d: FieldElement2625([ - 9394648, 8758552, 26189703, 16642536, 35993528, 5117040, 5977877, 13955594, - 19244020, 24493735, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 111388362, 51822507, 30193028, 3993472, 110736308, 44014764, 107346699, 48464072, - 92830877, 56442511, - ]), - y_minus_x: FieldElement2625([ - 7236795, 30433657, 63588571, 620817, 11118384, 24979014, 66780154, 19877679, - 16217590, 26311105, - ]), - xy2d: FieldElement2625([ - 42540794, 21657271, 16455973, 23630199, 3992015, 21894417, 44876052, 19291718, - 55429803, 30442389, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 69421833, 26972132, 58859271, 20240912, 119664007, 29643940, 93968457, 34515112, - 110902491, 44996669, - ]), - y_minus_x: FieldElement2625([ - 3428668, 27807272, 41139948, 24786894, 4167808, 21423270, 52199622, 8021269, - 53172251, 18070808, - ]), - xy2d: FieldElement2625([ - 30631113, 26363656, 21279866, 23275794, 18311406, 466071, 42527968, 7989982, - 29641567, 29446694, - ]), - }, - ]); diff --git a/net/gurk-rs/files/vendor/curve25519-dalek-2.0.0/src/backend/serial/u32/field.rs b/net/gurk-rs/files/vendor/curve25519-dalek-2.0.0/src/backend/serial/u32/field.rs deleted file mode 100644 index 603ed3f..0000000 --- a/net/gurk-rs/files/vendor/curve25519-dalek-2.0.0/src/backend/serial/u32/field.rs +++ /dev/null @@ -1,577 +0,0 @@ -// -*- mode: rust; coding: utf-8; -*- -// -// This file is part of curve25519-dalek. -// Copyright (c) 2016-2019 Isis Lovecruft, Henry de Valence -// See LICENSE for licensing information. -// -// Authors: -// - Isis Agora Lovecruft -// - Henry de Valence - -//! Field arithmetic modulo \\(p = 2\^{255} - 19\\), using \\(32\\)-bit -//! limbs with \\(64\\)-bit products. -//! -//! This code was originally derived from Adam Langley's Golang ed25519 -//! implementation, and was then rewritten to use unsigned limbs instead -//! of signed limbs. - -use core::fmt::Debug; -use core::ops::Neg; -use core::ops::{Add, AddAssign}; -use core::ops::{Mul, MulAssign}; -use core::ops::{Sub, SubAssign}; - -use subtle::Choice; -use subtle::ConditionallySelectable; - -use zeroize::Zeroize; - -/// A `FieldElement2625` represents an element of the field -/// \\( \mathbb Z / (2\^{255} - 19)\\). -/// -/// In the 32-bit implementation, a `FieldElement` is represented in -/// radix \\(2\^{25.5}\\) as ten `u32`s. This means that a field -/// element \\(x\\) is represented as -/// $$ -/// x = \sum\_{i=0}\^9 x\_i 2\^{\lceil i \frac {51} 2 \rceil} -/// = x\_0 + x\_1 2\^{26} + x\_2 2\^{51} + x\_3 2\^{77} + \cdots + x\_9 2\^{230}; -/// $$ -/// the coefficients are alternately bounded by \\(2\^{25}\\) and -/// \\(2\^{26}\\). The limbs are allowed to grow between reductions up -/// to \\(2\^{25+b}\\) or \\(2\^{26+b}\\), where \\(b = 1.75\\). -/// -/// # Note -/// -/// The `curve25519_dalek::field` module provides a type alias -/// `curve25519_dalek::field::FieldElement` to either `FieldElement51` -/// or `FieldElement2625`. -/// -/// The backend-specific type `FieldElement2625` should not be used -/// outside of the `curve25519_dalek::field` module. -#[derive(Copy, Clone)] -pub struct FieldElement2625(pub (crate) [u32; 10]); - -impl Debug for FieldElement2625 { - fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { - write!(f, "FieldElement2625({:?})", &self.0[..]) - } -} - -impl Zeroize for FieldElement2625 { - fn zeroize(&mut self) { - self.0.zeroize(); - } -} - -impl<'b> AddAssign<&'b FieldElement2625> for FieldElement2625 { - fn add_assign(&mut self, _rhs: &'b FieldElement2625) { - for i in 0..10 { - self.0[i] += _rhs.0[i]; - } - } -} - -impl<'a, 'b> Add<&'b FieldElement2625> for &'a FieldElement2625 { - type Output = FieldElement2625; - fn add(self, _rhs: &'b FieldElement2625) -> FieldElement2625 { - let mut output = *self; - output += _rhs; - output - } -} - -impl<'b> SubAssign<&'b FieldElement2625> for FieldElement2625 { - fn sub_assign(&mut self, _rhs: &'b FieldElement2625) { - // See comment in FieldElement51::Sub - // - // Compute a - b as ((a + 2^4 * p) - b) to avoid underflow. - let b = &_rhs.0; - self.0 = FieldElement2625::reduce([ - ((self.0[0] + (0x3ffffed << 4)) - b[0]) as u64, - ((self.0[1] + (0x1ffffff << 4)) - b[1]) as u64, - ((self.0[2] + (0x3ffffff << 4)) - b[2]) as u64, - ((self.0[3] + (0x1ffffff << 4)) - b[3]) as u64, - ((self.0[4] + (0x3ffffff << 4)) - b[4]) as u64, - ((self.0[5] + (0x1ffffff << 4)) - b[5]) as u64, - ((self.0[6] + (0x3ffffff << 4)) - b[6]) as u64, - ((self.0[7] + (0x1ffffff << 4)) - b[7]) as u64, - ((self.0[8] + (0x3ffffff << 4)) - b[8]) as u64, - ((self.0[9] + (0x1ffffff << 4)) - b[9]) as u64, - ]).0; - } -} - -impl<'a, 'b> Sub<&'b FieldElement2625> for &'a FieldElement2625 { - type Output = FieldElement2625; - fn sub(self, _rhs: &'b FieldElement2625) -> FieldElement2625 { - let mut output = *self; - output -= _rhs; - output - } -} - -impl<'b> MulAssign<&'b FieldElement2625> for FieldElement2625 { - fn mul_assign(&mut self, _rhs: &'b FieldElement2625) { - let result = (self as &FieldElement2625) * _rhs; - self.0 = result.0; - } -} - -impl<'a, 'b> Mul<&'b FieldElement2625> for &'a FieldElement2625 { - type Output = FieldElement2625; - fn mul(self, _rhs: &'b FieldElement2625) -> FieldElement2625 { - /// Helper function to multiply two 32-bit integers with 64 bits - /// of output. - #[inline(always)] - fn m(x: u32, y: u32) -> u64 { (x as u64) * (y as u64) } - - // Alias self, _rhs for more readable formulas - let x: &[u32;10] = &self.0; let y: &[u32;10] = &_rhs.0; - - // We assume that the input limbs x[i], y[i] are bounded by: - // - // x[i], y[i] < 2^(26 + b) if i even - // x[i], y[i] < 2^(25 + b) if i odd - // - // where b is a (real) parameter representing the excess bits of - // the limbs. We track the bitsizes of all variables through - // the computation and solve at the end for the allowable - // headroom bitsize b (which determines how many additions we - // can perform between reductions or multiplications). - - let y1_19 = 19 * y[1]; // This fits in a u32 - let y2_19 = 19 * y[2]; // iff 26 + b + lg(19) < 32 - let y3_19 = 19 * y[3]; // if b < 32 - 26 - 4.248 = 1.752 - let y4_19 = 19 * y[4]; - let y5_19 = 19 * y[5]; // below, b<2.5: this is a bottleneck, - let y6_19 = 19 * y[6]; // could be avoided by promoting to - let y7_19 = 19 * y[7]; // u64 here instead of in m() - let y8_19 = 19 * y[8]; - let y9_19 = 19 * y[9]; - - // What happens when we multiply x[i] with y[j] and place the - // result into the (i+j)-th limb? - // - // x[i] represents the value x[i]*2^ceil(i*51/2) - // y[j] represents the value y[j]*2^ceil(j*51/2) - // z[i+j] represents the value z[i+j]*2^ceil((i+j)*51/2) - // x[i]*y[j] represents the value x[i]*y[i]*2^(ceil(i*51/2)+ceil(j*51/2)) - // - // Since the radix is already accounted for, the result placed - // into the (i+j)-th limb should be - // - // x[i]*y[i]*2^(ceil(i*51/2)+ceil(j*51/2) - ceil((i+j)*51/2)). - // - // The value of ceil(i*51/2)+ceil(j*51/2) - ceil((i+j)*51/2) is - // 1 when both i and j are odd, and 0 otherwise. So we add - // - // x[i]*y[j] if either i or j is even - // 2*x[i]*y[j] if i and j are both odd - // - // by using precomputed multiples of x[i] for odd i: - - let x1_2 = 2 * x[1]; // This fits in a u32 iff 25 + b + 1 < 32 - let x3_2 = 2 * x[3]; // iff b < 6 - let x5_2 = 2 * x[5]; - let x7_2 = 2 * x[7]; - let x9_2 = 2 * x[9]; - - let z0 = m(x[0],y[0]) + m(x1_2,y9_19) + m(x[2],y8_19) + m(x3_2,y7_19) + m(x[4],y6_19) + m(x5_2,y5_19) + m(x[6],y4_19) + m(x7_2,y3_19) + m(x[8],y2_19) + m(x9_2,y1_19); - let z1 = m(x[0],y[1]) + m(x[1],y[0]) + m(x[2],y9_19) + m(x[3],y8_19) + m(x[4],y7_19) + m(x[5],y6_19) + m(x[6],y5_19) + m(x[7],y4_19) + m(x[8],y3_19) + m(x[9],y2_19); - let z2 = m(x[0],y[2]) + m(x1_2,y[1]) + m(x[2],y[0]) + m(x3_2,y9_19) + m(x[4],y8_19) + m(x5_2,y7_19) + m(x[6],y6_19) + m(x7_2,y5_19) + m(x[8],y4_19) + m(x9_2,y3_19); - let z3 = m(x[0],y[3]) + m(x[1],y[2]) + m(x[2],y[1]) + m(x[3],y[0]) + m(x[4],y9_19) + m(x[5],y8_19) + m(x[6],y7_19) + m(x[7],y6_19) + m(x[8],y5_19) + m(x[9],y4_19); - let z4 = m(x[0],y[4]) + m(x1_2,y[3]) + m(x[2],y[2]) + m(x3_2,y[1]) + m(x[4],y[0]) + m(x5_2,y9_19) + m(x[6],y8_19) + m(x7_2,y7_19) + m(x[8],y6_19) + m(x9_2,y5_19); - let z5 = m(x[0],y[5]) + m(x[1],y[4]) + m(x[2],y[3]) + m(x[3],y[2]) + m(x[4],y[1]) + m(x[5],y[0]) + m(x[6],y9_19) + m(x[7],y8_19) + m(x[8],y7_19) + m(x[9],y6_19); - let z6 = m(x[0],y[6]) + m(x1_2,y[5]) + m(x[2],y[4]) + m(x3_2,y[3]) + m(x[4],y[2]) + m(x5_2,y[1]) + m(x[6],y[0]) + m(x7_2,y9_19) + m(x[8],y8_19) + m(x9_2,y7_19); - let z7 = m(x[0],y[7]) + m(x[1],y[6]) + m(x[2],y[5]) + m(x[3],y[4]) + m(x[4],y[3]) + m(x[5],y[2]) + m(x[6],y[1]) + m(x[7],y[0]) + m(x[8],y9_19) + m(x[9],y8_19); - let z8 = m(x[0],y[8]) + m(x1_2,y[7]) + m(x[2],y[6]) + m(x3_2,y[5]) + m(x[4],y[4]) + m(x5_2,y[3]) + m(x[6],y[2]) + m(x7_2,y[1]) + m(x[8],y[0]) + m(x9_2,y9_19); - let z9 = m(x[0],y[9]) + m(x[1],y[8]) + m(x[2],y[7]) + m(x[3],y[6]) + m(x[4],y[5]) + m(x[5],y[4]) + m(x[6],y[3]) + m(x[7],y[2]) + m(x[8],y[1]) + m(x[9],y[0]); - - // How big is the contribution to z[i+j] from x[i], y[j]? - // - // Using the bounds above, we get: - // - // i even, j even: x[i]*y[j] < 2^(26+b)*2^(26+b) = 2*2^(51+2*b) - // i odd, j even: x[i]*y[j] < 2^(25+b)*2^(26+b) = 1*2^(51+2*b) - // i even, j odd: x[i]*y[j] < 2^(26+b)*2^(25+b) = 1*2^(51+2*b) - // i odd, j odd: 2*x[i]*y[j] < 2*2^(25+b)*2^(25+b) = 1*2^(51+2*b) - // - // We perform inline reduction mod p by replacing 2^255 by 19 - // (since 2^255 - 19 = 0 mod p). This adds a factor of 19, so - // we get the bounds (z0 is the biggest one, but calculated for - // posterity here in case finer estimation is needed later): - // - // z0 < ( 2 + 1*19 + 2*19 + 1*19 + 2*19 + 1*19 + 2*19 + 1*19 + 2*19 + 1*19 )*2^(51 + 2b) = 249*2^(51 + 2*b) - // z1 < ( 1 + 1 + 1*19 + 1*19 + 1*19 + 1*19 + 1*19 + 1*19 + 1*19 + 1*19 )*2^(51 + 2b) = 154*2^(51 + 2*b) - // z2 < ( 2 + 1 + 2 + 1*19 + 2*19 + 1*19 + 2*19 + 1*19 + 2*19 + 1*19 )*2^(51 + 2b) = 195*2^(51 + 2*b) - // z3 < ( 1 + 1 + 1 + 1 + 1*19 + 1*19 + 1*19 + 1*19 + 1*19 + 1*19 )*2^(51 + 2b) = 118*2^(51 + 2*b) - // z4 < ( 2 + 1 + 2 + 1 + 2 + 1*19 + 2*19 + 1*19 + 2*19 + 1*19 )*2^(51 + 2b) = 141*2^(51 + 2*b) - // z5 < ( 1 + 1 + 1 + 1 + 1 + 1 + 1*19 + 1*19 + 1*19 + 1*19 )*2^(51 + 2b) = 82*2^(51 + 2*b) - // z6 < ( 2 + 1 + 2 + 1 + 2 + 1 + 2 + 1*19 + 2*19 + 1*19 )*2^(51 + 2b) = 87*2^(51 + 2*b) - // z7 < ( 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1*19 + 1*19 )*2^(51 + 2b) = 46*2^(51 + 2*b) - // z6 < ( 2 + 1 + 2 + 1 + 2 + 1 + 2 + 1 + 2 + 1*19 )*2^(51 + 2b) = 33*2^(51 + 2*b) - // z7 < ( 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 )*2^(51 + 2b) = 10*2^(51 + 2*b) - // - // So z[0] fits into a u64 if 51 + 2*b + lg(249) < 64 - // if b < 2.5. - FieldElement2625::reduce([z0, z1, z2, z3, z4, z5, z6, z7, z8, z9]) - } -} - -impl<'a> Neg for &'a FieldElement2625 { - type Output = FieldElement2625; - fn neg(self) -> FieldElement2625 { - let mut output = *self; - output.negate(); - output - } -} - -impl ConditionallySelectable for FieldElement2625 { - fn conditional_select( - a: &FieldElement2625, - b: &FieldElement2625, - choice: Choice, - ) -> FieldElement2625 { - FieldElement2625([ - u32::conditional_select(&a.0[0], &b.0[0], choice), - u32::conditional_select(&a.0[1], &b.0[1], choice), - u32::conditional_select(&a.0[2], &b.0[2], choice), - u32::conditional_select(&a.0[3], &b.0[3], choice), - u32::conditional_select(&a.0[4], &b.0[4], choice), - u32::conditional_select(&a.0[5], &b.0[5], choice), - u32::conditional_select(&a.0[6], &b.0[6], choice), - u32::conditional_select(&a.0[7], &b.0[7], choice), - u32::conditional_select(&a.0[8], &b.0[8], choice), - u32::conditional_select(&a.0[9], &b.0[9], choice), - ]) - } - - fn conditional_assign(&mut self, other: &FieldElement2625, choice: Choice) { - self.0[0].conditional_assign(&other.0[0], choice); - self.0[1].conditional_assign(&other.0[1], choice); - self.0[2].conditional_assign(&other.0[2], choice); - self.0[3].conditional_assign(&other.0[3], choice); - self.0[4].conditional_assign(&other.0[4], choice); - self.0[5].conditional_assign(&other.0[5], choice); - self.0[6].conditional_assign(&other.0[6], choice); - self.0[7].conditional_assign(&other.0[7], choice); - self.0[8].conditional_assign(&other.0[8], choice); - self.0[9].conditional_assign(&other.0[9], choice); - } - - fn conditional_swap(a: &mut FieldElement2625, b: &mut FieldElement2625, choice: Choice) { - u32::conditional_swap(&mut a.0[0], &mut b.0[0], choice); - u32::conditional_swap(&mut a.0[1], &mut b.0[1], choice); - u32::conditional_swap(&mut a.0[2], &mut b.0[2], choice); - u32::conditional_swap(&mut a.0[3], &mut b.0[3], choice); - u32::conditional_swap(&mut a.0[4], &mut b.0[4], choice); - u32::conditional_swap(&mut a.0[5], &mut b.0[5], choice); - u32::conditional_swap(&mut a.0[6], &mut b.0[6], choice); - u32::conditional_swap(&mut a.0[7], &mut b.0[7], choice); - u32::conditional_swap(&mut a.0[8], &mut b.0[8], choice); - u32::conditional_swap(&mut a.0[9], &mut b.0[9], choice); - } -} - -impl FieldElement2625 { - /// Invert the sign of this field element - pub fn negate(&mut self) { - // Compute -b as ((2^4 * p) - b) to avoid underflow. - let neg = FieldElement2625::reduce([ - ((0x3ffffed << 4) - self.0[0]) as u64, - ((0x1ffffff << 4) - self.0[1]) as u64, - ((0x3ffffff << 4) - self.0[2]) as u64, - ((0x1ffffff << 4) - self.0[3]) as u64, - ((0x3ffffff << 4) - self.0[4]) as u64, - ((0x1ffffff << 4) - self.0[5]) as u64, - ((0x3ffffff << 4) - self.0[6]) as u64, - ((0x1ffffff << 4) - self.0[7]) as u64, - ((0x3ffffff << 4) - self.0[8]) as u64, - ((0x1ffffff << 4) - self.0[9]) as u64, - ]); - self.0 = neg.0; - } - - /// Construct zero. - pub fn zero() -> FieldElement2625 { - FieldElement2625([ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ]) - } - - /// Construct one. - pub fn one() -> FieldElement2625 { - FieldElement2625([ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0 ]) - } - - /// Construct -1. - pub fn minus_one() -> FieldElement2625 { - FieldElement2625([ - 0x3ffffec, 0x1ffffff, 0x3ffffff, 0x1ffffff, 0x3ffffff, - 0x1ffffff, 0x3ffffff, 0x1ffffff, 0x3ffffff, 0x1ffffff, - ]) - } - - /// Given `k > 0`, return `self^(2^k)`. - pub fn pow2k(&self, k: u32) -> FieldElement2625 { - debug_assert!( k > 0 ); - let mut z = self.square(); - for _ in 1..k { - z = z.square(); - } - z - } - - /// Given unreduced coefficients `z[0], ..., z[9]` of any size, - /// carry and reduce them mod p to obtain a `FieldElement2625` - /// whose coefficients have excess `b < 0.007`. - /// - /// In other words, each coefficient of the result is bounded by - /// either `2^(25 + 0.007)` or `2^(26 + 0.007)`, as appropriate. - fn reduce(mut z: [u64; 10]) -> FieldElement2625 { - - const LOW_25_BITS: u64 = (1 << 25) - 1; - const LOW_26_BITS: u64 = (1 << 26) - 1; - - /// Carry the value from limb i = 0..8 to limb i+1 - #[inline(always)] - fn carry(z: &mut [u64; 10], i: usize) { - debug_assert!(i < 9); - if i % 2 == 0 { - // Even limbs have 26 bits - z[i+1] += z[i] >> 26; - z[i] &= LOW_26_BITS; - } else { - // Odd limbs have 25 bits - z[i+1] += z[i] >> 25; - z[i] &= LOW_25_BITS; - } - } - - // Perform two halves of the carry chain in parallel. - carry(&mut z, 0); carry(&mut z, 4); - carry(&mut z, 1); carry(&mut z, 5); - carry(&mut z, 2); carry(&mut z, 6); - carry(&mut z, 3); carry(&mut z, 7); - // Since z[3] < 2^64, c < 2^(64-25) = 2^39, - // so z[4] < 2^26 + 2^39 < 2^39.0002 - carry(&mut z, 4); carry(&mut z, 8); - // Now z[4] < 2^26 - // and z[5] < 2^25 + 2^13.0002 < 2^25.0004 (good enough) - - // Last carry has a multiplication by 19: - z[0] += 19*(z[9] >> 25); - z[9] &= LOW_25_BITS; - - // Since z[9] < 2^64, c < 2^(64-25) = 2^39, - // so z[0] + 19*c < 2^26 + 2^43.248 < 2^43.249. - carry(&mut z, 0); - // Now z[1] < 2^25 - 2^(43.249 - 26) - // < 2^25.007 (good enough) - // and we're done. - - FieldElement2625([ - z[0] as u32, z[1] as u32, z[2] as u32, z[3] as u32, z[4] as u32, - z[5] as u32, z[6] as u32, z[7] as u32, z[8] as u32, z[9] as u32, - ]) - } - - /// Load a `FieldElement51` from the low 255 bits of a 256-bit - /// input. - /// - /// # Warning - /// - /// This function does not check that the input used the canonical - /// representative. It masks the high bit, but it will happily - /// decode 2^255 - 18 to 1. Applications that require a canonical - /// encoding of every field element should decode, re-encode to - /// the canonical encoding, and check that the input was - /// canonical. - pub fn from_bytes(data: &[u8; 32]) -> FieldElement2625 { //FeFromBytes - #[inline] - fn load3(b: &[u8]) -> u64 { - (b[0] as u64) | ((b[1] as u64) << 8) | ((b[2] as u64) << 16) - } - - #[inline] - fn load4(b: &[u8]) -> u64 { - (b[0] as u64) | ((b[1] as u64) << 8) | ((b[2] as u64) << 16) | ((b[3] as u64) << 24) - } - - let mut h = [0u64;10]; - const LOW_23_BITS: u64 = (1 << 23) - 1; - h[0] = load4(&data[ 0..]); - h[1] = load3(&data[ 4..]) << 6; - h[2] = load3(&data[ 7..]) << 5; - h[3] = load3(&data[10..]) << 3; - h[4] = load3(&data[13..]) << 2; - h[5] = load4(&data[16..]); - h[6] = load3(&data[20..]) << 7; - h[7] = load3(&data[23..]) << 5; - h[8] = load3(&data[26..]) << 4; - h[9] = (load3(&data[29..]) & LOW_23_BITS) << 2; - - FieldElement2625::reduce(h) - } - - /// Serialize this `FieldElement51` to a 32-byte array. The - /// encoding is canonical. - pub fn to_bytes(&self) -> [u8; 32] { - - let inp = &self.0; - // Reduce the value represented by `in` to the range [0,2*p) - let mut h: [u32; 10] = FieldElement2625::reduce([ - // XXX this cast is annoying - inp[0] as u64, inp[1] as u64, inp[2] as u64, inp[3] as u64, inp[4] as u64, - inp[5] as u64, inp[6] as u64, inp[7] as u64, inp[8] as u64, inp[9] as u64, - ]).0; - - // Let h be the value to encode. - // - // Write h = pq + r with 0 <= r < p. We want to compute r = h mod p. - // - // Since h < 2*p, q = 0 or 1, with q = 0 when h < p and q = 1 when h >= p. - // - // Notice that h >= p <==> h + 19 >= p + 19 <==> h + 19 >= 2^255. - // Therefore q can be computed as the carry bit of h + 19. - - let mut q: u32 = (h[0] + 19) >> 26; - q = (h[1] + q) >> 25; - q = (h[2] + q) >> 26; - q = (h[3] + q) >> 25; - q = (h[4] + q) >> 26; - q = (h[5] + q) >> 25; - q = (h[6] + q) >> 26; - q = (h[7] + q) >> 25; - q = (h[8] + q) >> 26; - q = (h[9] + q) >> 25; - - debug_assert!( q == 0 || q == 1 ); - - // Now we can compute r as r = h - pq = r - (2^255-19)q = r + 19q - 2^255q - - const LOW_25_BITS: u32 = (1 << 25) - 1; - const LOW_26_BITS: u32 = (1 << 26) - 1; - - h[0] += 19*q; - - // Now carry the result to compute r + 19q... - h[1] += h[0] >> 26; - h[0] = h[0] & LOW_26_BITS; - h[2] += h[1] >> 25; - h[1] = h[1] & LOW_25_BITS; - h[3] += h[2] >> 26; - h[2] = h[2] & LOW_26_BITS; - h[4] += h[3] >> 25; - h[3] = h[3] & LOW_25_BITS; - h[5] += h[4] >> 26; - h[4] = h[4] & LOW_26_BITS; - h[6] += h[5] >> 25; - h[5] = h[5] & LOW_25_BITS; - h[7] += h[6] >> 26; - h[6] = h[6] & LOW_26_BITS; - h[8] += h[7] >> 25; - h[7] = h[7] & LOW_25_BITS; - h[9] += h[8] >> 26; - h[8] = h[8] & LOW_26_BITS; - - // ... but instead of carrying the value - // (h[9] >> 25) = q*2^255 into another limb, - // discard it, subtracting the value from h. - debug_assert!( (h[9] >> 25) == 0 || (h[9] >> 25) == 1); - h[9] = h[9] & LOW_25_BITS; - - let mut s = [0u8; 32]; - s[0] = (h[0] >> 0) as u8; - s[1] = (h[0] >> 8) as u8; - s[2] = (h[0] >> 16) as u8; - s[3] = ((h[0] >> 24) | (h[1] << 2)) as u8; - s[4] = (h[1] >> 6) as u8; - s[5] = (h[1] >> 14) as u8; - s[6] = ((h[1] >> 22) | (h[2] << 3)) as u8; - s[7] = (h[2] >> 5) as u8; - s[8] = (h[2] >> 13) as u8; - s[9] = ((h[2] >> 21) | (h[3] << 5)) as u8; - s[10] = (h[3] >> 3) as u8; - s[11] = (h[3] >> 11) as u8; - s[12] = ((h[3] >> 19) | (h[4] << 6)) as u8; - s[13] = (h[4] >> 2) as u8; - s[14] = (h[4] >> 10) as u8; - s[15] = (h[4] >> 18) as u8; - s[16] = (h[5] >> 0) as u8; - s[17] = (h[5] >> 8) as u8; - s[18] = (h[5] >> 16) as u8; - s[19] = ((h[5] >> 24) | (h[6] << 1)) as u8; - s[20] = (h[6] >> 7) as u8; - s[21] = (h[6] >> 15) as u8; - s[22] = ((h[6] >> 23) | (h[7] << 3)) as u8; - s[23] = (h[7] >> 5) as u8; - s[24] = (h[7] >> 13) as u8; - s[25] = ((h[7] >> 21) | (h[8] << 4)) as u8; - s[26] = (h[8] >> 4) as u8; - s[27] = (h[8] >> 12) as u8; - s[28] = ((h[8] >> 20) | (h[9] << 6)) as u8; - s[29] = (h[9] >> 2) as u8; - s[30] = (h[9] >> 10) as u8; - s[31] = (h[9] >> 18) as u8; - - // Check that high bit is cleared - debug_assert!((s[31] & 0b1000_0000u8) == 0u8); - - s - } - - fn square_inner(&self) -> [u64; 10] { - // Optimized version of multiplication for the case of squaring. - // Pre- and post- conditions identical to multiplication function. - let x = &self.0; - let x0_2 = 2 * x[0]; - let x1_2 = 2 * x[1]; - let x2_2 = 2 * x[2]; - let x3_2 = 2 * x[3]; - let x4_2 = 2 * x[4]; - let x5_2 = 2 * x[5]; - let x6_2 = 2 * x[6]; - let x7_2 = 2 * x[7]; - let x5_19 = 19 * x[5]; - let x6_19 = 19 * x[6]; - let x7_19 = 19 * x[7]; - let x8_19 = 19 * x[8]; - let x9_19 = 19 * x[9]; - - /// Helper function to multiply two 32-bit integers with 64 bits - /// of output. - #[inline(always)] - fn m(x: u32, y: u32) -> u64 { (x as u64) * (y as u64) } - - // This block is rearranged so that instead of doing a 32-bit multiplication by 38, we do a - // 64-bit multiplication by 2 on the results. This is because lg(38) is too big: we would - // have less than 1 bit of headroom left, which is too little. - let mut z = [0u64;10]; - z[0] = m(x[0],x[0]) + m(x2_2,x8_19) + m(x4_2,x6_19) + (m(x1_2,x9_19) + m(x3_2,x7_19) + m(x[5],x5_19))*2; - z[1] = m(x0_2,x[1]) + m(x3_2,x8_19) + m(x5_2,x6_19) + (m(x[2],x9_19) + m(x[4],x7_19))*2; - z[2] = m(x0_2,x[2]) + m(x1_2,x[1]) + m(x4_2,x8_19) + m(x[6],x6_19) + (m(x3_2,x9_19) + m(x5_2,x7_19))*2; - z[3] = m(x0_2,x[3]) + m(x1_2,x[2]) + m(x5_2,x8_19) + (m(x[4],x9_19) + m(x[6],x7_19))*2; - z[4] = m(x0_2,x[4]) + m(x1_2,x3_2) + m(x[2],x[2]) + m(x6_2,x8_19) + (m(x5_2,x9_19) + m(x[7],x7_19))*2; - z[5] = m(x0_2,x[5]) + m(x1_2,x[4]) + m(x2_2,x[3]) + m(x7_2,x8_19) + m(x[6],x9_19)*2; - z[6] = m(x0_2,x[6]) + m(x1_2,x5_2) + m(x2_2,x[4]) + m(x3_2,x[3]) + m(x[8],x8_19) + m(x7_2,x9_19)*2; - z[7] = m(x0_2,x[7]) + m(x1_2,x[6]) + m(x2_2,x[5]) + m(x3_2,x[4]) + m(x[8],x9_19)*2; - z[8] = m(x0_2,x[8]) + m(x1_2,x7_2) + m(x2_2,x[6]) + m(x3_2,x5_2) + m(x[4],x[4]) + m(x[9],x9_19)*2; - z[9] = m(x0_2,x[9]) + m(x1_2,x[8]) + m(x2_2,x[7]) + m(x3_2,x[6]) + m(x4_2,x[5]) ; - - z - } - - /// Compute `self^2`. - pub fn square(&self) -> FieldElement2625 { - FieldElement2625::reduce(self.square_inner()) - } - - /// Compute `2*self^2`. - pub fn square2(&self) -> FieldElement2625 { - let mut coeffs = self.square_inner(); - for i in 0..self.0.len() { - coeffs[i] += coeffs[i]; - } - FieldElement2625::reduce(coeffs) - } -} diff --git a/net/gurk-rs/files/vendor/curve25519-dalek-2.0.0/src/backend/serial/u32/mod.rs b/net/gurk-rs/files/vendor/curve25519-dalek-2.0.0/src/backend/serial/u32/mod.rs deleted file mode 100644 index e0f344f..0000000 --- a/net/gurk-rs/files/vendor/curve25519-dalek-2.0.0/src/backend/serial/u32/mod.rs +++ /dev/null @@ -1,21 +0,0 @@ -// -*- mode: rust; -*- -// -// This file is part of curve25519-dalek. -// Copyright (c) 2016-2019 Isis Lovecruft, Henry de Valence -// See LICENSE for licensing information. -// -// Authors: -// - Isis Agora Lovecruft -// - Henry de Valence - -//! The `u32` backend uses `u32`s and a `(u32, u32) -> u64` multiplier. -//! -//! This code is intended to be portable, but it requires that -//! multiplication of two \\(32\\)-bit values to a \\(64\\)-bit result -//! is constant-time on the target platform. - -pub mod field; - -pub mod scalar; - -pub mod constants; diff --git a/net/gurk-rs/files/vendor/curve25519-dalek-2.0.0/src/backend/serial/u32/scalar.rs b/net/gurk-rs/files/vendor/curve25519-dalek-2.0.0/src/backend/serial/u32/scalar.rs deleted file mode 100644 index 8dd54bd..0000000 --- a/net/gurk-rs/files/vendor/curve25519-dalek-2.0.0/src/backend/serial/u32/scalar.rs +++ /dev/null @@ -1,529 +0,0 @@ -//! Arithmetic mod 2^252 + 27742317777372353535851937790883648493 -//! with 9 29-bit unsigned limbs -//! -//! To see that this is safe for intermediate results, note that -//! the largest limb in a 9 by 9 product of 29-bit limbs will be -//! (0x1fffffff^2) * 9 = 0x23fffffdc0000009 (62 bits). -//! -//! For a one level Karatsuba decomposition, the specific ranges -//! depend on how the limbs are combined, but will stay within -//! -0x1ffffffe00000008 (62 bits with sign bit) to -//! 0x43fffffbc0000011 (63 bits), which is still safe. - -use core::fmt::Debug; -use core::ops::{Index, IndexMut}; - -use zeroize::Zeroize; - -use constants; - -/// The `Scalar29` struct represents an element in ℤ/lℤ as 9 29-bit limbs -#[derive(Copy,Clone)] -pub struct Scalar29(pub [u32; 9]); - -impl Debug for Scalar29 { - fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { - write!(f, "Scalar29: {:?}", &self.0[..]) - } -} - -impl Zeroize for Scalar29 { - fn zeroize(&mut self) { - self.0.zeroize(); - } -} - -impl Index for Scalar29 { - type Output = u32; - fn index(&self, _index: usize) -> &u32 { - &(self.0[_index]) - } -} - -impl IndexMut for Scalar29 { - fn index_mut(&mut self, _index: usize) -> &mut u32 { - &mut (self.0[_index]) - } -} - -/// u32 * u32 = u64 multiply helper -#[inline(always)] -fn m(x: u32, y: u32) -> u64 { - (x as u64) * (y as u64) -} - -impl Scalar29 { - /// Return the zero scalar. - pub fn zero() -> Scalar29 { - Scalar29([0,0,0,0,0,0,0,0,0]) - } - - /// Unpack a 32 byte / 256 bit scalar into 9 29-bit limbs. - pub fn from_bytes(bytes: &[u8; 32]) -> Scalar29 { - let mut words = [0u32; 8]; - for i in 0..8 { - for j in 0..4 { - words[i] |= (bytes[(i * 4) + j] as u32) << (j * 8); - } - } - - let mask = (1u32 << 29) - 1; - let top_mask = (1u32 << 24) - 1; - let mut s = Scalar29::zero(); - - s[ 0] = words[0] & mask; - s[ 1] = ((words[0] >> 29) | (words[1] << 3)) & mask; - s[ 2] = ((words[1] >> 26) | (words[2] << 6)) & mask; - s[ 3] = ((words[2] >> 23) | (words[3] << 9)) & mask; - s[ 4] = ((words[3] >> 20) | (words[4] << 12)) & mask; - s[ 5] = ((words[4] >> 17) | (words[5] << 15)) & mask; - s[ 6] = ((words[5] >> 14) | (words[6] << 18)) & mask; - s[ 7] = ((words[6] >> 11) | (words[7] << 21)) & mask; - s[ 8] = (words[7] >> 8) & top_mask; - - s - } - - /// Reduce a 64 byte / 512 bit scalar mod l. - pub fn from_bytes_wide(bytes: &[u8; 64]) -> Scalar29 { - let mut words = [0u32; 16]; - for i in 0..16 { - for j in 0..4 { - words[i] |= (bytes[(i * 4) + j] as u32) << (j * 8); - } - } - - let mask = (1u32 << 29) - 1; - let mut lo = Scalar29::zero(); - let mut hi = Scalar29::zero(); - - lo[0] = words[ 0] & mask; - lo[1] = ((words[ 0] >> 29) | (words[ 1] << 3)) & mask; - lo[2] = ((words[ 1] >> 26) | (words[ 2] << 6)) & mask; - lo[3] = ((words[ 2] >> 23) | (words[ 3] << 9)) & mask; - lo[4] = ((words[ 3] >> 20) | (words[ 4] << 12)) & mask; - lo[5] = ((words[ 4] >> 17) | (words[ 5] << 15)) & mask; - lo[6] = ((words[ 5] >> 14) | (words[ 6] << 18)) & mask; - lo[7] = ((words[ 6] >> 11) | (words[ 7] << 21)) & mask; - lo[8] = ((words[ 7] >> 8) | (words[ 8] << 24)) & mask; - hi[0] = ((words[ 8] >> 5) | (words[ 9] << 27)) & mask; - hi[1] = (words[ 9] >> 2) & mask; - hi[2] = ((words[ 9] >> 31) | (words[10] << 1)) & mask; - hi[3] = ((words[10] >> 28) | (words[11] << 4)) & mask; - hi[4] = ((words[11] >> 25) | (words[12] << 7)) & mask; - hi[5] = ((words[12] >> 22) | (words[13] << 10)) & mask; - hi[6] = ((words[13] >> 19) | (words[14] << 13)) & mask; - hi[7] = ((words[14] >> 16) | (words[15] << 16)) & mask; - hi[8] = words[15] >> 13 ; - - lo = Scalar29::montgomery_mul(&lo, &constants::R); // (lo * R) / R = lo - hi = Scalar29::montgomery_mul(&hi, &constants::RR); // (hi * R^2) / R = hi * R - - Scalar29::add(&hi, &lo) // (hi * R) + lo - } - - /// Pack the limbs of this `Scalar29` into 32 bytes. - pub fn to_bytes(&self) -> [u8; 32] { - let mut s = [0u8; 32]; - - s[0] = (self.0[ 0] >> 0) as u8; - s[1] = (self.0[ 0] >> 8) as u8; - s[2] = (self.0[ 0] >> 16) as u8; - s[3] = ((self.0[ 0] >> 24) | (self.0[ 1] << 5)) as u8; - s[4] = (self.0[ 1] >> 3) as u8; - s[5] = (self.0[ 1] >> 11) as u8; - s[6] = (self.0[ 1] >> 19) as u8; - s[7] = ((self.0[ 1] >> 27) | (self.0[ 2] << 2)) as u8; - s[8] = (self.0[ 2] >> 6) as u8; - s[9] = (self.0[ 2] >> 14) as u8; - s[10] = ((self.0[ 2] >> 22) | (self.0[ 3] << 7)) as u8; - s[11] = (self.0[ 3] >> 1) as u8; - s[12] = (self.0[ 3] >> 9) as u8; - s[13] = (self.0[ 3] >> 17) as u8; - s[14] = ((self.0[ 3] >> 25) | (self.0[ 4] << 4)) as u8; - s[15] = (self.0[ 4] >> 4) as u8; - s[16] = (self.0[ 4] >> 12) as u8; - s[17] = (self.0[ 4] >> 20) as u8; - s[18] = ((self.0[ 4] >> 28) | (self.0[ 5] << 1)) as u8; - s[19] = (self.0[ 5] >> 7) as u8; - s[20] = (self.0[ 5] >> 15) as u8; - s[21] = ((self.0[ 5] >> 23) | (self.0[ 6] << 6)) as u8; - s[22] = (self.0[ 6] >> 2) as u8; - s[23] = (self.0[ 6] >> 10) as u8; - s[24] = (self.0[ 6] >> 18) as u8; - s[25] = ((self.0[ 6] >> 26) | (self.0[ 7] << 3)) as u8; - s[26] = (self.0[ 7] >> 5) as u8; - s[27] = (self.0[ 7] >> 13) as u8; - s[28] = (self.0[ 7] >> 21) as u8; - s[29] = (self.0[ 8] >> 0) as u8; - s[30] = (self.0[ 8] >> 8) as u8; - s[31] = (self.0[ 8] >> 16) as u8; - - s - } - - /// Compute `a + b` (mod l). - pub fn add(a: &Scalar29, b: &Scalar29) -> Scalar29 { - let mut sum = Scalar29::zero(); - let mask = (1u32 << 29) - 1; - - // a + b - let mut carry: u32 = 0; - for i in 0..9 { - carry = a[i] + b[i] + (carry >> 29); - sum[i] = carry & mask; - } - - // subtract l if the sum is >= l - Scalar29::sub(&sum, &constants::L) - } - - /// Compute `a - b` (mod l). - pub fn sub(a: &Scalar29, b: &Scalar29) -> Scalar29 { - let mut difference = Scalar29::zero(); - let mask = (1u32 << 29) - 1; - - // a - b - let mut borrow: u32 = 0; - for i in 0..9 { - borrow = a[i].wrapping_sub(b[i] + (borrow >> 31)); - difference[i] = borrow & mask; - } - - // conditionally add l if the difference is negative - let underflow_mask = ((borrow >> 31) ^ 1).wrapping_sub(1); - let mut carry: u32 = 0; - for i in 0..9 { - carry = (carry >> 29) + difference[i] + (constants::L[i] & underflow_mask); - difference[i] = carry & mask; - } - - difference - } - - /// Compute `a * b`. - /// - /// This is implemented with a one-level refined Karatsuba decomposition - #[inline(always)] - pub (crate) fn mul_internal(a: &Scalar29, b: &Scalar29) -> [u64; 17] { - let mut z = [0u64; 17]; - - z[0] = m(a[0],b[0]); // c00 - z[1] = m(a[0],b[1]) + m(a[1],b[0]); // c01 - z[2] = m(a[0],b[2]) + m(a[1],b[1]) + m(a[2],b[0]); // c02 - z[3] = m(a[0],b[3]) + m(a[1],b[2]) + m(a[2],b[1]) + m(a[3],b[0]); // c03 - z[4] = m(a[0],b[4]) + m(a[1],b[3]) + m(a[2],b[2]) + m(a[3],b[1]) + m(a[4],b[0]); // c04 - z[5] = m(a[1],b[4]) + m(a[2],b[3]) + m(a[3],b[2]) + m(a[4],b[1]); // c05 - z[6] = m(a[2],b[4]) + m(a[3],b[3]) + m(a[4],b[2]); // c06 - z[7] = m(a[3],b[4]) + m(a[4],b[3]); // c07 - z[8] = (m(a[4],b[4])).wrapping_sub(z[3]); // c08 - c03 - - z[10] = z[5].wrapping_sub(m(a[5],b[5])); // c05mc10 - z[11] = z[6].wrapping_sub(m(a[5],b[6]) + m(a[6],b[5])); // c06mc11 - z[12] = z[7].wrapping_sub(m(a[5],b[7]) + m(a[6],b[6]) + m(a[7],b[5])); // c07mc12 - z[13] = m(a[5],b[8]) + m(a[6],b[7]) + m(a[7],b[6]) + m(a[8],b[5]); // c13 - z[14] = m(a[6],b[8]) + m(a[7],b[7]) + m(a[8],b[6]); // c14 - z[15] = m(a[7],b[8]) + m(a[8],b[7]); // c15 - z[16] = m(a[8],b[8]); // c16 - - z[ 5] = z[10].wrapping_sub(z[ 0]); // c05mc10 - c00 - z[ 6] = z[11].wrapping_sub(z[ 1]); // c06mc11 - c01 - z[ 7] = z[12].wrapping_sub(z[ 2]); // c07mc12 - c02 - z[ 8] = z[ 8].wrapping_sub(z[13]); // c08mc13 - c03 - z[ 9] = z[14].wrapping_add(z[ 4]); // c14 + c04 - z[10] = z[15].wrapping_add(z[10]); // c15 + c05mc10 - z[11] = z[16].wrapping_add(z[11]); // c16 + c06mc11 - - let aa = [ - a[0]+a[5], - a[1]+a[6], - a[2]+a[7], - a[3]+a[8] - ]; - - let bb = [ - b[0]+b[5], - b[1]+b[6], - b[2]+b[7], - b[3]+b[8] - ]; - - z[ 5] = (m(aa[0],bb[0])) .wrapping_add(z[ 5]); // c20 + c05mc10 - c00 - z[ 6] = (m(aa[0],bb[1]) + m(aa[1],bb[0])) .wrapping_add(z[ 6]); // c21 + c06mc11 - c01 - z[ 7] = (m(aa[0],bb[2]) + m(aa[1],bb[1]) + m(aa[2],bb[0])) .wrapping_add(z[ 7]); // c22 + c07mc12 - c02 - z[ 8] = (m(aa[0],bb[3]) + m(aa[1],bb[2]) + m(aa[2],bb[1]) + m(aa[3],bb[0])) .wrapping_add(z[ 8]); // c23 + c08mc13 - c03 - z[ 9] = (m(aa[0], b[4]) + m(aa[1],bb[3]) + m(aa[2],bb[2]) + m(aa[3],bb[1]) + m(a[4],bb[0])).wrapping_sub(z[ 9]); // c24 - c14 - c04 - z[10] = ( m(aa[1], b[4]) + m(aa[2],bb[3]) + m(aa[3],bb[2]) + m(a[4],bb[1])).wrapping_sub(z[10]); // c25 - c15 - c05mc10 - z[11] = ( m(aa[2], b[4]) + m(aa[3],bb[3]) + m(a[4],bb[2])).wrapping_sub(z[11]); // c26 - c16 - c06mc11 - z[12] = ( m(aa[3], b[4]) + m(a[4],bb[3])).wrapping_sub(z[12]); // c27 - c07mc12 - - z - } - - /// Compute `a^2`. - #[inline(always)] - fn square_internal(a: &Scalar29) -> [u64; 17] { - let aa = [ - a[0]*2, - a[1]*2, - a[2]*2, - a[3]*2, - a[4]*2, - a[5]*2, - a[6]*2, - a[7]*2 - ]; - - [ - m( a[0],a[0]), - m(aa[0],a[1]), - m(aa[0],a[2]) + m( a[1],a[1]), - m(aa[0],a[3]) + m(aa[1],a[2]), - m(aa[0],a[4]) + m(aa[1],a[3]) + m( a[2],a[2]), - m(aa[0],a[5]) + m(aa[1],a[4]) + m(aa[2],a[3]), - m(aa[0],a[6]) + m(aa[1],a[5]) + m(aa[2],a[4]) + m( a[3],a[3]), - m(aa[0],a[7]) + m(aa[1],a[6]) + m(aa[2],a[5]) + m(aa[3],a[4]), - m(aa[0],a[8]) + m(aa[1],a[7]) + m(aa[2],a[6]) + m(aa[3],a[5]) + m( a[4],a[4]), - m(aa[1],a[8]) + m(aa[2],a[7]) + m(aa[3],a[6]) + m(aa[4],a[5]), - m(aa[2],a[8]) + m(aa[3],a[7]) + m(aa[4],a[6]) + m( a[5],a[5]), - m(aa[3],a[8]) + m(aa[4],a[7]) + m(aa[5],a[6]), - m(aa[4],a[8]) + m(aa[5],a[7]) + m( a[6],a[6]), - m(aa[5],a[8]) + m(aa[6],a[7]), - m(aa[6],a[8]) + m( a[7],a[7]), - m(aa[7],a[8]), - m( a[8],a[8]), - ] - } - - /// Compute `limbs/R` (mod l), where R is the Montgomery modulus 2^261 - #[inline(always)] - pub (crate) fn montgomery_reduce(limbs: &[u64; 17]) -> Scalar29 { - - #[inline(always)] - fn part1(sum: u64) -> (u64, u32) { - let p = (sum as u32).wrapping_mul(constants::LFACTOR) & ((1u32 << 29) - 1); - ((sum + m(p,constants::L[0])) >> 29, p) - } - - #[inline(always)] - fn part2(sum: u64) -> (u64, u32) { - let w = (sum as u32) & ((1u32 << 29) - 1); - (sum >> 29, w) - } - - // note: l5,l6,l7 are zero, so their multiplies can be skipped - let l = &constants::L; - - // the first half computes the Montgomery adjustment factor n, and begins adding n*l to make limbs divisible by R - let (carry, n0) = part1( limbs[ 0]); - let (carry, n1) = part1(carry + limbs[ 1] + m(n0,l[1])); - let (carry, n2) = part1(carry + limbs[ 2] + m(n0,l[2]) + m(n1,l[1])); - let (carry, n3) = part1(carry + limbs[ 3] + m(n0,l[3]) + m(n1,l[2]) + m(n2,l[1])); - let (carry, n4) = part1(carry + limbs[ 4] + m(n0,l[4]) + m(n1,l[3]) + m(n2,l[2]) + m(n3,l[1])); - let (carry, n5) = part1(carry + limbs[ 5] + m(n1,l[4]) + m(n2,l[3]) + m(n3,l[2]) + m(n4,l[1])); - let (carry, n6) = part1(carry + limbs[ 6] + m(n2,l[4]) + m(n3,l[3]) + m(n4,l[2]) + m(n5,l[1])); - let (carry, n7) = part1(carry + limbs[ 7] + m(n3,l[4]) + m(n4,l[3]) + m(n5,l[2]) + m(n6,l[1])); - let (carry, n8) = part1(carry + limbs[ 8] + m(n0,l[8]) + m(n4,l[4]) + m(n5,l[3]) + m(n6,l[2]) + m(n7,l[1])); - - // limbs is divisible by R now, so we can divide by R by simply storing the upper half as the result - let (carry, r0) = part2(carry + limbs[ 9] + m(n1,l[8]) + m(n5,l[4]) + m(n6,l[3]) + m(n7,l[2]) + m(n8,l[1])); - let (carry, r1) = part2(carry + limbs[10] + m(n2,l[8]) + m(n6,l[4]) + m(n7,l[3]) + m(n8,l[2])); - let (carry, r2) = part2(carry + limbs[11] + m(n3,l[8]) + m(n7,l[4]) + m(n8,l[3])); - let (carry, r3) = part2(carry + limbs[12] + m(n4,l[8]) + m(n8,l[4])); - let (carry, r4) = part2(carry + limbs[13] + m(n5,l[8]) ); - let (carry, r5) = part2(carry + limbs[14] + m(n6,l[8]) ); - let (carry, r6) = part2(carry + limbs[15] + m(n7,l[8]) ); - let (carry, r7) = part2(carry + limbs[16] + m(n8,l[8])); - let r8 = carry as u32; - - // result may be >= l, so attempt to subtract l - Scalar29::sub(&Scalar29([r0,r1,r2,r3,r4,r5,r6,r7,r8]), l) - } - - /// Compute `a * b` (mod l). - #[inline(never)] - pub fn mul(a: &Scalar29, b: &Scalar29) -> Scalar29 { - let ab = Scalar29::montgomery_reduce(&Scalar29::mul_internal(a, b)); - Scalar29::montgomery_reduce(&Scalar29::mul_internal(&ab, &constants::RR)) - } - - /// Compute `a^2` (mod l). - #[inline(never)] - #[allow(dead_code)] // XXX we don't expose square() via the Scalar API - pub fn square(&self) -> Scalar29 { - let aa = Scalar29::montgomery_reduce(&Scalar29::square_internal(self)); - Scalar29::montgomery_reduce(&Scalar29::mul_internal(&aa, &constants::RR)) - } - - /// Compute `(a * b) / R` (mod l), where R is the Montgomery modulus 2^261 - #[inline(never)] - pub fn montgomery_mul(a: &Scalar29, b: &Scalar29) -> Scalar29 { - Scalar29::montgomery_reduce(&Scalar29::mul_internal(a, b)) - } - - /// Compute `(a^2) / R` (mod l) in Montgomery form, where R is the Montgomery modulus 2^261 - #[inline(never)] - pub fn montgomery_square(&self) -> Scalar29 { - Scalar29::montgomery_reduce(&Scalar29::square_internal(self)) - } - - /// Puts a Scalar29 in to Montgomery form, i.e. computes `a*R (mod l)` - #[inline(never)] - pub fn to_montgomery(&self) -> Scalar29 { - Scalar29::montgomery_mul(self, &constants::RR) - } - - /// Takes a Scalar29 out of Montgomery form, i.e. computes `a/R (mod l)` - pub fn from_montgomery(&self) -> Scalar29 { - let mut limbs = [0u64; 17]; - for i in 0..9 { - limbs[i] = self[i] as u64; - } - Scalar29::montgomery_reduce(&limbs) - } -} - -#[cfg(test)] -mod test { - use super::*; - - /// Note: x is 2^253-1 which is slightly larger than the largest scalar produced by - /// this implementation (l-1), and should verify there are no overflows for valid scalars - /// - /// x = 2^253-1 = 14474011154664524427946373126085988481658748083205070504932198000989141204991 - /// x = 7237005577332262213973186563042994240801631723825162898930247062703686954002 mod l - /// x = 5147078182513738803124273553712992179887200054963030844803268920753008712037*R mod l in Montgomery form - pub static X: Scalar29 = Scalar29( - [0x1fffffff, 0x1fffffff, 0x1fffffff, 0x1fffffff, - 0x1fffffff, 0x1fffffff, 0x1fffffff, 0x1fffffff, - 0x001fffff]); - - /// x^2 = 3078544782642840487852506753550082162405942681916160040940637093560259278169 mod l - pub static XX: Scalar29 = Scalar29( - [0x00217559, 0x000b3401, 0x103ff43b, 0x1462a62c, - 0x1d6f9f38, 0x18e7a42f, 0x09a3dcee, 0x008dbe18, - 0x0006ce65]); - - /// x^2 = 2912514428060642753613814151688322857484807845836623976981729207238463947987*R mod l in Montgomery form - pub static XX_MONT: Scalar29 = Scalar29( - [0x152b4d2e, 0x0571d53b, 0x1da6d964, 0x188663b6, - 0x1d1b5f92, 0x19d50e3f, 0x12306c29, 0x0c6f26fe, - 0x00030edb]); - - /// y = 6145104759870991071742105800796537629880401874866217824609283457819451087098 - pub static Y: Scalar29 = Scalar29( - [0x1e1458fa, 0x165ba838, 0x1d787b36, 0x0e577f3a, - 0x1d2baf06, 0x1d689a19, 0x1fff3047, 0x117704ab, - 0x000d9601]); - - /// x*y = 36752150652102274958925982391442301741 - pub static XY: Scalar29 = Scalar29( - [0x0ba7632d, 0x017736bb, 0x15c76138, 0x0c69daa1, - 0x000001ba, 0x00000000, 0x00000000, 0x00000000, - 0x00000000]); - - /// x*y = 3783114862749659543382438697751927473898937741870308063443170013240655651591*R mod l in Montgomery form - pub static XY_MONT: Scalar29 = Scalar29( - [0x077b51e1, 0x1c64e119, 0x02a19ef5, 0x18d2129e, - 0x00de0430, 0x045a7bc8, 0x04cfc7c9, 0x1c002681, - 0x000bdc1c]); - - /// a = 2351415481556538453565687241199399922945659411799870114962672658845158063753 - pub static A: Scalar29 = Scalar29( - [0x07b3be89, 0x02291b60, 0x14a99f03, 0x07dc3787, - 0x0a782aae, 0x16262525, 0x0cfdb93f, 0x13f5718d, - 0x000532da]); - - /// b = 4885590095775723760407499321843594317911456947580037491039278279440296187236 - pub static B: Scalar29 = Scalar29( - [0x15421564, 0x1e69fd72, 0x093d9692, 0x161785be, - 0x1587d69f, 0x09d9dada, 0x130246c0, 0x0c0a8e72, - 0x000acd25]); - - /// a+b = 0 - /// a-b = 4702830963113076907131374482398799845891318823599740229925345317690316127506 - pub static AB: Scalar29 = Scalar29( - [0x0f677d12, 0x045236c0, 0x09533e06, 0x0fb86f0f, - 0x14f0555c, 0x0c4c4a4a, 0x19fb727f, 0x07eae31a, - 0x000a65b5]); - - // c = (2^512 - 1) % l = 1627715501170711445284395025044413883736156588369414752970002579683115011840 - pub static C: Scalar29 = Scalar29( - [0x049c0f00, 0x00308f1a, 0x0164d1e9, 0x1c374ed1, - 0x1be65d00, 0x19e90bfa, 0x08f73bb1, 0x036f8613, - 0x00039941]); - - #[test] - fn mul_max() { - let res = Scalar29::mul(&X, &X); - for i in 0..9 { - assert!(res[i] == XX[i]); - } - } - - #[test] - fn square_max() { - let res = X.square(); - for i in 0..9 { - assert!(res[i] == XX[i]); - } - } - - #[test] - fn montgomery_mul_max() { - let res = Scalar29::montgomery_mul(&X, &X); - for i in 0..9 { - assert!(res[i] == XX_MONT[i]); - } - } - - #[test] - fn montgomery_square_max() { - let res = X.montgomery_square(); - for i in 0..9 { - assert!(res[i] == XX_MONT[i]); - } - } - - #[test] - fn mul() { - let res = Scalar29::mul(&X, &Y); - for i in 0..9 { - assert!(res[i] == XY[i]); - } - } - - #[test] - fn montgomery_mul() { - let res = Scalar29::montgomery_mul(&X, &Y); - for i in 0..9 { - assert!(res[i] == XY_MONT[i]); - } - } - - #[test] - fn add() { - let res = Scalar29::add(&A, &B); - let zero = Scalar29::zero(); - for i in 0..9 { - assert!(res[i] == zero[i]); - } - } - - #[test] - fn sub() { - let res = Scalar29::sub(&A, &B); - for i in 0..9 { - assert!(res[i] == AB[i]); - } - } - - #[test] - fn from_bytes_wide() { - let bignum = [255u8; 64]; // 2^512 - 1 - let reduced = Scalar29::from_bytes_wide(&bignum); - for i in 0..9 { - assert!(reduced[i] == C[i]); - } - } -} diff --git a/net/gurk-rs/files/vendor/curve25519-dalek-2.0.0/src/backend/serial/u64/constants.rs b/net/gurk-rs/files/vendor/curve25519-dalek-2.0.0/src/backend/serial/u64/constants.rs deleted file mode 100644 index fc8c6da..0000000 --- a/net/gurk-rs/files/vendor/curve25519-dalek-2.0.0/src/backend/serial/u64/constants.rs +++ /dev/null @@ -1,7743 +0,0 @@ -// -*- mode: rust; -*- -// -// This file is part of curve25519-dalek. -// Copyright (c) 2016-2019 Isis Lovecruft, Henry de Valence -// See LICENSE for licensing information. -// -// Authors: -// - Isis Agora Lovecruft -// - Henry de Valence - -//! This module contains backend-specific constant values, such as the 64-bit limbs of curve constants. - -use backend::serial::curve_models::AffineNielsPoint; -use backend::serial::u64::field::FieldElement51; -use backend::serial::u64::scalar::Scalar52; -use edwards::{EdwardsBasepointTable, EdwardsPoint}; -use window::{LookupTable, NafLookupTable8}; - -/// The value of minus one, equal to `-&FieldElement::one()` -pub(crate) const MINUS_ONE: FieldElement51 = FieldElement51([ - 2251799813685228, - 2251799813685247, - 2251799813685247, - 2251799813685247, - 2251799813685247 -]); - -/// Edwards `d` value, equal to `-121665/121666 mod p`. -pub(crate) const EDWARDS_D: FieldElement51 = FieldElement51([ - 929955233495203, - 466365720129213, - 1662059464998953, - 2033849074728123, - 1442794654840575, -]); - -/// Edwards `2*d` value, equal to `2*(-121665/121666) mod p`. -pub(crate) const EDWARDS_D2: FieldElement51 = FieldElement51([ - 1859910466990425, - 932731440258426, - 1072319116312658, - 1815898335770999, - 633789495995903, -]); - -/// One minus edwards `d` value squared, equal to `(1 - (-121665/121666) mod p) pow 2` -pub(crate) const ONE_MINUS_EDWARDS_D_SQUARED: FieldElement51 = FieldElement51([ - 1136626929484150, - 1998550399581263, - 496427632559748, - 118527312129759, - 45110755273534 -]); - -/// Edwards `d` value minus one squared, equal to `(((-121665/121666) mod p) - 1) pow 2` -pub(crate) const EDWARDS_D_MINUS_ONE_SQUARED: FieldElement51 = FieldElement51([ - 1507062230895904, - 1572317787530805, - 683053064812840, - 317374165784489, - 1572899562415810 -]); - -/// `= sqrt(a*d - 1)`, where `a = -1 (mod p)`, `d` are the Edwards curve parameters. -pub(crate) const SQRT_AD_MINUS_ONE: FieldElement51 = FieldElement51([ - 2241493124984347, - 425987919032274, - 2207028919301688, - 1220490630685848, - 974799131293748, -]); - -/// `= 1/sqrt(a-d)`, where `a = -1 (mod p)`, `d` are the Edwards curve parameters. -pub(crate) const INVSQRT_A_MINUS_D: FieldElement51 = FieldElement51([ - 278908739862762, - 821645201101625, - 8113234426968, - 1777959178193151, - 2118520810568447, -]); - -/// Precomputed value of one of the square roots of -1 (mod p) -pub(crate) const SQRT_M1: FieldElement51 = FieldElement51([ - 1718705420411056, - 234908883556509, - 2233514472574048, - 2117202627021982, - 765476049583133, -]); - -/// `APLUS2_OVER_FOUR` is (A+2)/4. (This is used internally within the Montgomery ladder.) -pub(crate) const APLUS2_OVER_FOUR: FieldElement51 = FieldElement51([121666, 0, 0, 0, 0]); - -/// `L` is the order of base point, i.e. 2^252 + 27742317777372353535851937790883648493 -pub(crate) const L: Scalar52 = Scalar52([ - 0x0002631a5cf5d3ed, - 0x000dea2f79cd6581, - 0x000000000014def9, - 0x0000000000000000, - 0x0000100000000000, -]); - -/// `L` * `LFACTOR` = -1 (mod 2^52) -pub(crate) const LFACTOR: u64 = 0x51da312547e1b; - -/// `R` = R % L where R = 2^260 -pub(crate) const R: Scalar52 = Scalar52([ - 0x000f48bd6721e6ed, - 0x0003bab5ac67e45a, - 0x000fffffeb35e51b, - 0x000fffffffffffff, - 0x00000fffffffffff, -]); - -/// `RR` = (R^2) % L where R = 2^260 -pub(crate) const RR: Scalar52 = Scalar52([ - 0x0009d265e952d13b, - 0x000d63c715bea69f, - 0x0005be65cb687604, - 0x0003dceec73d217f, - 0x000009411b7c309a, -]); - -/// The Ed25519 basepoint, as an `EdwardsPoint`. -/// -/// This is called `_POINT` to distinguish it from -/// `ED25519_BASEPOINT_TABLE`, which should be used for scalar -/// multiplication (it's much faster). -pub const ED25519_BASEPOINT_POINT: EdwardsPoint = EdwardsPoint { - X: FieldElement51([ - 1738742601995546, - 1146398526822698, - 2070867633025821, - 562264141797630, - 587772402128613, - ]), - Y: FieldElement51([ - 1801439850948184, - 1351079888211148, - 450359962737049, - 900719925474099, - 1801439850948198, - ]), - Z: FieldElement51([1, 0, 0, 0, 0]), - T: FieldElement51([ - 1841354044333475, - 16398895984059, - 755974180946558, - 900171276175154, - 1821297809914039, - ]), -}; - -/// The 8-torsion subgroup \\(\mathcal E [8]\\). -/// -/// In the case of Curve25519, it is cyclic; the \\(i\\)-th element of -/// the array is \\([i]P\\), where \\(P\\) is a point of order \\(8\\) -/// generating \\(\mathcal E[8]\\). -/// -/// Thus \\(\mathcal E[4]\\) is the points indexed by `0,2,4,6`, and -/// \\(\mathcal E[2]\\) is the points indexed by `0,4`. -pub const EIGHT_TORSION: [EdwardsPoint; 8] = EIGHT_TORSION_INNER_DOC_HIDDEN; - -/// Inner item used to hide limb constants from cargo doc output. -#[doc(hidden)] -pub const EIGHT_TORSION_INNER_DOC_HIDDEN: [EdwardsPoint; 8] = [ - EdwardsPoint { - X: FieldElement51([0, 0, 0, 0, 0]), - Y: FieldElement51([1, 0, 0, 0, 0]), - Z: FieldElement51([1, 0, 0, 0, 0]), - T: FieldElement51([0, 0, 0, 0, 0]), - }, - EdwardsPoint { - X: FieldElement51([ - 358744748052810, - 1691584618240980, - 977650209285361, - 1429865912637724, - 560044844278676, - ]), - Y: FieldElement51([ - 84926274344903, - 473620666599931, - 365590438845504, - 1028470286882429, - 2146499180330972, - ]), - Z: FieldElement51([1, 0, 0, 0, 0]), - T: FieldElement51([ - 1448326834587521, - 1857896831960481, - 1093722731865333, - 1677408490711241, - 1915505153018406, - ]), - }, - EdwardsPoint { - X: FieldElement51([ - 533094393274173, - 2016890930128738, - 18285341111199, - 134597186663265, - 1486323764102114, - ]), - Y: FieldElement51([0, 0, 0, 0, 0]), - Z: FieldElement51([1, 0, 0, 0, 0]), - T: FieldElement51([0, 0, 0, 0, 0]), - }, - EdwardsPoint { - X: FieldElement51([ - 358744748052810, - 1691584618240980, - 977650209285361, - 1429865912637724, - 560044844278676, - ]), - Y: FieldElement51([ - 2166873539340326, - 1778179147085316, - 1886209374839743, - 1223329526802818, - 105300633354275, - ]), - Z: FieldElement51([1, 0, 0, 0, 0]), - T: FieldElement51([ - 803472979097708, - 393902981724766, - 1158077081819914, - 574391322974006, - 336294660666841, - ]), - }, - EdwardsPoint { - X: FieldElement51([0, 0, 0, 0, 0]), - Y: FieldElement51([ - 2251799813685228, - 2251799813685247, - 2251799813685247, - 2251799813685247, - 2251799813685247, - ]), - Z: FieldElement51([1, 0, 0, 0, 0]), - T: FieldElement51([0, 0, 0, 0, 0]), - }, - EdwardsPoint { - X: FieldElement51([ - 1893055065632419, - 560215195444267, - 1274149604399886, - 821933901047523, - 1691754969406571, - ]), - Y: FieldElement51([ - 2166873539340326, - 1778179147085316, - 1886209374839743, - 1223329526802818, - 105300633354275, - ]), - Z: FieldElement51([1, 0, 0, 0, 0]), - T: FieldElement51([ - 1448326834587521, - 1857896831960481, - 1093722731865333, - 1677408490711241, - 1915505153018406, - ]), - }, - EdwardsPoint { - X: FieldElement51([ - 1718705420411056, - 234908883556509, - 2233514472574048, - 2117202627021982, - 765476049583133, - ]), - Y: FieldElement51([0, 0, 0, 0, 0]), - Z: FieldElement51([1, 0, 0, 0, 0]), - T: FieldElement51([0, 0, 0, 0, 0]), - }, - EdwardsPoint { - X: FieldElement51([ - 1893055065632419, - 560215195444267, - 1274149604399886, - 821933901047523, - 1691754969406571, - ]), - Y: FieldElement51([ - 84926274344903, - 473620666599931, - 365590438845504, - 1028470286882429, - 2146499180330972, - ]), - Z: FieldElement51([1, 0, 0, 0, 0]), - T: FieldElement51([ - 803472979097708, - 393902981724766, - 1158077081819914, - 574391322974006, - 336294660666841, - ]), - }, -]; - -/// Table containing precomputed multiples of the Ed25519 basepoint \\(B = (x, 4/5)\\). -pub const ED25519_BASEPOINT_TABLE: EdwardsBasepointTable = ED25519_BASEPOINT_TABLE_INNER_DOC_HIDDEN; - -/// Inner constant, used to avoid filling the docs with precomputed points. -#[doc(hidden)] -pub const ED25519_BASEPOINT_TABLE_INNER_DOC_HIDDEN: EdwardsBasepointTable = - EdwardsBasepointTable([ - LookupTable([ - AffineNielsPoint { - y_plus_x: FieldElement51([ - 3540182452943730, - 2497478415033846, - 2521227595762870, - 1462984067271729, - 2389212253076811, - ]), - y_minus_x: FieldElement51([ - 62697248952638, - 204681361388450, - 631292143396476, - 338455783676468, - 1213667448819585, - ]), - xy2d: FieldElement51([ - 301289933810280, - 1259582250014073, - 1422107436869536, - 796239922652654, - 1953934009299142, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 3632771708514775, - 790832306631235, - 2067202295274102, - 1995808275510000, - 1566530869037010, - ]), - y_minus_x: FieldElement51([ - 463307831301544, - 432984605774163, - 1610641361907204, - 750899048855000, - 1894842303421586, - ]), - xy2d: FieldElement51([ - 748439484463711, - 1033211726465151, - 1396005112841647, - 1611506220286469, - 1972177495910992, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 1601611775252272, - 1720807796594148, - 1132070835939856, - 3512254832574799, - 2147779492816910, - ]), - y_minus_x: FieldElement51([ - 316559037616741, - 2177824224946892, - 1459442586438991, - 1461528397712656, - 751590696113597, - ]), - xy2d: FieldElement51([ - 1850748884277385, - 1200145853858453, - 1068094770532492, - 672251375690438, - 1586055907191707, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 934282339813791, - 1846903124198670, - 1172395437954843, - 1007037127761661, - 1830588347719256, - ]), - y_minus_x: FieldElement51([ - 1694390458783935, - 1735906047636159, - 705069562067493, - 648033061693059, - 696214010414170, - ]), - xy2d: FieldElement51([ - 1121406372216585, - 192876649532226, - 190294192191717, - 1994165897297032, - 2245000007398739, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 769950342298400, - 2384754244604994, - 3095885746880802, - 3225892188161580, - 2977876099231263, - ]), - y_minus_x: FieldElement51([ - 425251763115706, - 608463272472562, - 442562545713235, - 837766094556764, - 374555092627893, - ]), - xy2d: FieldElement51([ - 1086255230780037, - 274979815921559, - 1960002765731872, - 929474102396301, - 1190409889297339, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 1388594989461809, - 316767091099457, - 2646098655878230, - 1230079486801004, - 1440737038838979, - ]), - y_minus_x: FieldElement51([ - 7380825640100, - 146210432690483, - 304903576448906, - 1198869323871120, - 997689833219095, - ]), - xy2d: FieldElement51([ - 1181317918772081, - 114573476638901, - 262805072233344, - 265712217171332, - 294181933805782, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 2916800678241215, - 2065379846933858, - 2622030924071124, - 2602788184473875, - 1233371373142984, - ]), - y_minus_x: FieldElement51([ - 2019367628972465, - 676711900706637, - 110710997811333, - 1108646842542025, - 517791959672113, - ]), - xy2d: FieldElement51([ - 965130719900578, - 247011430587952, - 526356006571389, - 91986625355052, - 2157223321444601, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 4320419353804412, - 4218074731744053, - 957728544705548, - 729906502578991, - 2411634706750414, - ]), - y_minus_x: FieldElement51([ - 2073601412052185, - 31021124762708, - 264500969797082, - 248034690651703, - 1030252227928288, - ]), - xy2d: FieldElement51([ - 551790716293402, - 1989538725166328, - 801169423371717, - 2052451893578887, - 678432056995012, - ]), - }, - ]), - LookupTable([ - AffineNielsPoint { - y_plus_x: FieldElement51([ - 1368953770187805, - 3042147450398169, - 2689308289352409, - 2142576377050579, - 1932081720066286, - ]), - y_minus_x: FieldElement51([ - 953638594433374, - 1092333936795051, - 1419774766716690, - 805677984380077, - 859228993502513, - ]), - xy2d: FieldElement51([ - 1200766035879111, - 20142053207432, - 1465634435977050, - 1645256912097844, - 295121984874596, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 1735718747031538, - 1248237894295956, - 1204753118328107, - 976066523550493, - 2317743583219840, - ]), - y_minus_x: FieldElement51([ - 1060098822528990, - 1586825862073490, - 212301317240126, - 1975302711403555, - 666724059764335, - ]), - xy2d: FieldElement51([ - 1091990273418756, - 1572899409348578, - 80968014455247, - 306009358661350, - 1520450739132526, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 3732317023121341, - 1511153322193951, - 3496143672676420, - 2556587964178488, - 2620936670181690, - ]), - y_minus_x: FieldElement51([ - 2151330273626164, - 762045184746182, - 1688074332551515, - 823046109005759, - 907602769079491, - ]), - xy2d: FieldElement51([ - 2047386910586836, - 168470092900250, - 1552838872594810, - 340951180073789, - 360819374702533, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 1982622644432037, - 2014393600336956, - 2380709022489462, - 3869592437614438, - 2357094095599062, - ]), - y_minus_x: FieldElement51([ - 980234343912898, - 1712256739246056, - 588935272190264, - 204298813091998, - 841798321043288, - ]), - xy2d: FieldElement51([ - 197561292938973, - 454817274782871, - 1963754960082318, - 2113372252160468, - 971377527342673, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 2416499262514576, - 2254927265442919, - 3451304785234000, - 1766155447043651, - 1899238924683527, - ]), - y_minus_x: FieldElement51([ - 732262946680281, - 1674412764227063, - 2182456405662809, - 1350894754474250, - 558458873295247, - ]), - xy2d: FieldElement51([ - 2103305098582922, - 1960809151316468, - 715134605001343, - 1454892949167181, - 40827143824949, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 1239289043050193, - 1744654158124578, - 758702410031698, - 4048562808759936, - 2253402870349013, - ]), - y_minus_x: FieldElement51([ - 2232056027107988, - 987343914584615, - 2115594492994461, - 1819598072792159, - 1119305654014850, - ]), - xy2d: FieldElement51([ - 320153677847348, - 939613871605645, - 641883205761567, - 1930009789398224, - 329165806634126, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 3232730304159378, - 1242488692177892, - 1251446316964684, - 1086618677993530, - 1961430968465772, - ]), - y_minus_x: FieldElement51([ - 276821765317453, - 1536835591188030, - 1305212741412361, - 61473904210175, - 2051377036983058, - ]), - xy2d: FieldElement51([ - 833449923882501, - 1750270368490475, - 1123347002068295, - 185477424765687, - 278090826653186, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 794524995833413, - 1849907304548286, - 2305148486158393, - 1272368559505216, - 1147304168324779, - ]), - y_minus_x: FieldElement51([ - 1504846112759364, - 1203096289004681, - 562139421471418, - 274333017451844, - 1284344053775441, - ]), - xy2d: FieldElement51([ - 483048732424432, - 2116063063343382, - 30120189902313, - 292451576741007, - 1156379271702225, - ]), - }, - ]), - LookupTable([ - AffineNielsPoint { - y_plus_x: FieldElement51([ - 3180171966714267, - 2147692869914563, - 1455665844462196, - 1986737809425946, - 2437006863943337, - ]), - y_minus_x: FieldElement51([ - 137732961814206, - 706670923917341, - 1387038086865771, - 1965643813686352, - 1384777115696347, - ]), - xy2d: FieldElement51([ - 481144981981577, - 2053319313589856, - 2065402289827512, - 617954271490316, - 1106602634668125, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 2948097833334040, - 3145099472726142, - 1148636718636008, - 2278533891034865, - 2203955659340680, - ]), - y_minus_x: FieldElement51([ - 657390353372855, - 998499966885562, - 991893336905797, - 810470207106761, - 343139804608786, - ]), - xy2d: FieldElement51([ - 791736669492960, - 934767652997115, - 824656780392914, - 1759463253018643, - 361530362383518, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 2022541353055578, - 4346500076272714, - 3802807888710933, - 2494585331103411, - 2947785218648809, - ]), - y_minus_x: FieldElement51([ - 1287487199965223, - 2215311941380308, - 1552928390931986, - 1664859529680196, - 1125004975265243, - ]), - xy2d: FieldElement51([ - 677434665154918, - 989582503122485, - 1817429540898386, - 1052904935475344, - 1143826298169798, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 2619066141993637, - 2570231002607651, - 2947429167440602, - 2885885471266079, - 2276381426249673, - ]), - y_minus_x: FieldElement51([ - 773360688841258, - 1815381330538070, - 363773437667376, - 539629987070205, - 783280434248437, - ]), - xy2d: FieldElement51([ - 180820816194166, - 168937968377394, - 748416242794470, - 1227281252254508, - 1567587861004268, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 2730575372268893, - 2062896624554806, - 2951191072970647, - 2609899222113120, - 1277310261461760, - ]), - y_minus_x: FieldElement51([ - 1984740906540026, - 1079164179400229, - 1056021349262661, - 1659958556483663, - 1088529069025527, - ]), - xy2d: FieldElement51([ - 580736401511151, - 1842931091388998, - 1177201471228238, - 2075460256527244, - 1301133425678027, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 1515728832059163, - 1575261009617579, - 1510246567196186, - 2442877836294952, - 2368461529974388, - ]), - y_minus_x: FieldElement51([ - 1295295738269652, - 1714742313707026, - 545583042462581, - 2034411676262552, - 1513248090013606, - ]), - xy2d: FieldElement51([ - 230710545179830, - 30821514358353, - 760704303452229, - 390668103790604, - 573437871383156, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 3421179921230875, - 2514967047430861, - 4274701112739695, - 3071700566936367, - 4275698278559832, - ]), - y_minus_x: FieldElement51([ - 2102254323485823, - 1570832666216754, - 34696906544624, - 1993213739807337, - 70638552271463, - ]), - xy2d: FieldElement51([ - 894132856735058, - 548675863558441, - 845349339503395, - 1942269668326667, - 1615682209874691, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 3539470031223082, - 1222355136884919, - 1846481788678694, - 1150426571265110, - 1613523400722047, - ]), - y_minus_x: FieldElement51([ - 793388516527298, - 1315457083650035, - 1972286999342417, - 1901825953052455, - 338269477222410, - ]), - xy2d: FieldElement51([ - 550201530671806, - 778605267108140, - 2063911101902983, - 115500557286349, - 2041641272971022, - ]), - }, - ]), - LookupTable([ - AffineNielsPoint { - y_plus_x: FieldElement51([ - 717255318455100, - 519313764361315, - 2080406977303708, - 541981206705521, - 774328150311600, - ]), - y_minus_x: FieldElement51([ - 261715221532238, - 1795354330069993, - 1496878026850283, - 499739720521052, - 389031152673770, - ]), - xy2d: FieldElement51([ - 1997217696294013, - 1717306351628065, - 1684313917746180, - 1644426076011410, - 1857378133465451, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 3727234538477877, - 2328731709971226, - 3368528843456914, - 2002544139318041, - 2977347647489186, - ]), - y_minus_x: FieldElement51([ - 2022306639183567, - 726296063571875, - 315345054448644, - 1058733329149221, - 1448201136060677, - ]), - xy2d: FieldElement51([ - 1710065158525665, - 1895094923036397, - 123988286168546, - 1145519900776355, - 1607510767693874, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 2813405189107769, - 1071733543815036, - 2383296312486238, - 1946868434569998, - 3079937947649451, - ]), - y_minus_x: FieldElement51([ - 1548495173745801, - 442310529226540, - 998072547000384, - 553054358385281, - 644824326376171, - ]), - xy2d: FieldElement51([ - 1445526537029440, - 2225519789662536, - 914628859347385, - 1064754194555068, - 1660295614401091, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 3451490036797185, - 2275827949507588, - 2318438102929588, - 2309425969971222, - 2816893781664854, - ]), - y_minus_x: FieldElement51([ - 876926774220824, - 554618976488214, - 1012056309841565, - 839961821554611, - 1414499340307677, - ]), - xy2d: FieldElement51([ - 703047626104145, - 1266841406201770, - 165556500219173, - 486991595001879, - 1011325891650656, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 1622861044480487, - 1156394801573634, - 4120932379100752, - 2578903799462977, - 2095342781472283, - ]), - y_minus_x: FieldElement51([ - 334886927423922, - 489511099221528, - 129160865966726, - 1720809113143481, - 619700195649254, - ]), - xy2d: FieldElement51([ - 1646545795166119, - 1758370782583567, - 714746174550637, - 1472693650165135, - 898994790308209, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 2585203586724508, - 2547572356138185, - 1693106465353609, - 912330357530760, - 2723035471635610, - ]), - y_minus_x: FieldElement51([ - 1811196219982022, - 1068969825533602, - 289602974833439, - 1988956043611592, - 863562343398367, - ]), - xy2d: FieldElement51([ - 906282429780072, - 2108672665779781, - 432396390473936, - 150625823801893, - 1708930497638539, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 925664675702309, - 2273216662253932, - 4083236455546587, - 601157008940112, - 2623617868729744, - ]), - y_minus_x: FieldElement51([ - 1479786007267725, - 1738881859066675, - 68646196476567, - 2146507056100328, - 1247662817535471, - ]), - xy2d: FieldElement51([ - 52035296774456, - 939969390708103, - 312023458773250, - 59873523517659, - 1231345905848899, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 2895154920100990, - 2541986621181021, - 2013561737429022, - 2571447883196794, - 2645536492181409, - ]), - y_minus_x: FieldElement51([ - 129358342392716, - 1932811617704777, - 1176749390799681, - 398040349861790, - 1170779668090425, - ]), - xy2d: FieldElement51([ - 2051980782668029, - 121859921510665, - 2048329875753063, - 1235229850149665, - 519062146124755, - ]), - }, - ]), - LookupTable([ - AffineNielsPoint { - y_plus_x: FieldElement51([ - 3859970785658325, - 2667608874045675, - 1350468408164765, - 2038620059057678, - 3278704299674360, - ]), - y_minus_x: FieldElement51([ - 1837656083115103, - 1510134048812070, - 906263674192061, - 1821064197805734, - 565375124676301, - ]), - xy2d: FieldElement51([ - 578027192365650, - 2034800251375322, - 2128954087207123, - 478816193810521, - 2196171989962750, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 1633188840273120, - 3104586986058956, - 1548762607215795, - 1266275218902681, - 3359018017010381, - ]), - y_minus_x: FieldElement51([ - 462189358480054, - 1784816734159228, - 1611334301651368, - 1303938263943540, - 707589560319424, - ]), - xy2d: FieldElement51([ - 1038829280972848, - 38176604650029, - 753193246598573, - 1136076426528122, - 595709990562434, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 3660251634545082, - 2194984964010832, - 2198361797561729, - 1061962440055713, - 1645147963442934, - ]), - y_minus_x: FieldElement51([ - 4701053362120, - 1647641066302348, - 1047553002242085, - 1923635013395977, - 206970314902065, - ]), - xy2d: FieldElement51([ - 1750479161778571, - 1362553355169293, - 1891721260220598, - 966109370862782, - 1024913988299801, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 2464498862816952, - 1117950018299774, - 1873945661751056, - 3655602735669306, - 2382695896337945, - ]), - y_minus_x: FieldElement51([ - 636808533673210, - 1262201711667560, - 390951380330599, - 1663420692697294, - 561951321757406, - ]), - xy2d: FieldElement51([ - 520731594438141, - 1446301499955692, - 273753264629267, - 1565101517999256, - 1019411827004672, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 3178327305714638, - 3443653291096626, - 734233225181170, - 2435838701226518, - 4042225960010590, - ]), - y_minus_x: FieldElement51([ - 1464651961852572, - 1483737295721717, - 1519450561335517, - 1161429831763785, - 405914998179977, - ]), - xy2d: FieldElement51([ - 996126634382301, - 796204125879525, - 127517800546509, - 344155944689303, - 615279846169038, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 2990523894660505, - 2188666632415295, - 1961313708559162, - 1506545807547587, - 3403101452654988, - ]), - y_minus_x: FieldElement51([ - 622917337413835, - 1218989177089035, - 1284857712846592, - 970502061709359, - 351025208117090, - ]), - xy2d: FieldElement51([ - 2067814584765580, - 1677855129927492, - 2086109782475197, - 235286517313238, - 1416314046739645, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 2838644076315587, - 2559244195637442, - 458399356043425, - 2853867838192310, - 3280348017100490, - ]), - y_minus_x: FieldElement51([ - 678489922928203, - 2016657584724032, - 90977383049628, - 1026831907234582, - 615271492942522, - ]), - xy2d: FieldElement51([ - 301225714012278, - 1094837270268560, - 1202288391010439, - 644352775178361, - 1647055902137983, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 1210746697896459, - 1416608304244708, - 2938287290903104, - 3496931005119382, - 3303038150540984, - ]), - y_minus_x: FieldElement51([ - 1135604073198207, - 1683322080485474, - 769147804376683, - 2086688130589414, - 900445683120379, - ]), - xy2d: FieldElement51([ - 1971518477615628, - 401909519527336, - 448627091057375, - 1409486868273821, - 1214789035034363, - ]), - }, - ]), - LookupTable([ - AffineNielsPoint { - y_plus_x: FieldElement51([ - 1364039144731711, - 1897497433586190, - 2203097701135459, - 2397261210496499, - 1349844460790698, - ]), - y_minus_x: FieldElement51([ - 1045230323257973, - 818206601145807, - 630513189076103, - 1672046528998132, - 807204017562437, - ]), - xy2d: FieldElement51([ - 439961968385997, - 386362664488986, - 1382706320807688, - 309894000125359, - 2207801346498567, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 3480804500082836, - 3172443782216110, - 2375775707596425, - 2933223806901024, - 1400559197080972, - ]), - y_minus_x: FieldElement51([ - 2003766096898049, - 170074059235165, - 1141124258967971, - 1485419893480973, - 1573762821028725, - ]), - xy2d: FieldElement51([ - 729905708611432, - 1270323270673202, - 123353058984288, - 426460209632942, - 2195574535456672, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 1271140255321216, - 2044363183174497, - 2303925201319937, - 3696920060379952, - 3194341800024331, - ]), - y_minus_x: FieldElement51([ - 1761608437466135, - 583360847526804, - 1586706389685493, - 2157056599579261, - 1170692369685772, - ]), - xy2d: FieldElement51([ - 871476219910823, - 1878769545097794, - 2241832391238412, - 548957640601001, - 690047440233174, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 2548994545820755, - 1366347803776819, - 3552985325930849, - 561849853336293, - 1533554921345731, - ]), - y_minus_x: FieldElement51([ - 999628998628371, - 1132836708493400, - 2084741674517453, - 469343353015612, - 678782988708035, - ]), - xy2d: FieldElement51([ - 2189427607417022, - 699801937082607, - 412764402319267, - 1478091893643349, - 2244675696854460, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 3964091869651792, - 2456213404310121, - 3657538451018088, - 2660781114515010, - 3112882032961968, - ]), - y_minus_x: FieldElement51([ - 508561155940631, - 966928475686665, - 2236717801150132, - 424543858577297, - 2089272956986143, - ]), - xy2d: FieldElement51([ - 221245220129925, - 1156020201681217, - 491145634799213, - 542422431960839, - 828100817819207, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 2405556784925632, - 1299874139923976, - 2644898978945750, - 1058234455773021, - 996989038681183, - ]), - y_minus_x: FieldElement51([ - 559086812798481, - 573177704212711, - 1629737083816402, - 1399819713462595, - 1646954378266038, - ]), - xy2d: FieldElement51([ - 1887963056288059, - 228507035730124, - 1468368348640282, - 930557653420194, - 613513962454686, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 1224529808187534, - 1577022856702685, - 2206946542980843, - 625883007765001, - 2531730607197406, - ]), - y_minus_x: FieldElement51([ - 1076287717051609, - 1114455570543035, - 187297059715481, - 250446884292121, - 1885187512550540, - ]), - xy2d: FieldElement51([ - 902497362940219, - 76749815795675, - 1657927525633846, - 1420238379745202, - 1340321636548352, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 1129576631190765, - 3533793823712575, - 996844254743017, - 2509676177174497, - 3402650555740265, - ]), - y_minus_x: FieldElement51([ - 628740660038789, - 1943038498527841, - 467786347793886, - 1093341428303375, - 235413859513003, - ]), - xy2d: FieldElement51([ - 237425418909360, - 469614029179605, - 1512389769174935, - 1241726368345357, - 441602891065214, - ]), - }, - ]), - LookupTable([ - AffineNielsPoint { - y_plus_x: FieldElement51([ - 3988217766743784, - 726531315520507, - 1833335034432527, - 1629442561574747, - 2876218732971333, - ]), - y_minus_x: FieldElement51([ - 1960754663920689, - 497040957888962, - 1909832851283095, - 1271432136996826, - 2219780368020940, - ]), - xy2d: FieldElement51([ - 1537037379417136, - 1358865369268262, - 2130838645654099, - 828733687040705, - 1999987652890901, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 629042105241795, - 1098854999137608, - 887281544569320, - 3674901833560025, - 2259711072636808, - ]), - y_minus_x: FieldElement51([ - 1811562332665373, - 1501882019007673, - 2213763501088999, - 359573079719636, - 36370565049116, - ]), - xy2d: FieldElement51([ - 218907117361280, - 1209298913016966, - 1944312619096112, - 1130690631451061, - 1342327389191701, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 1369976867854685, - 1396479602419169, - 4017456468084104, - 2203659200586298, - 3250127649802489, - ]), - y_minus_x: FieldElement51([ - 2230701885562825, - 1348173180338974, - 2172856128624598, - 1426538746123771, - 444193481326151, - ]), - xy2d: FieldElement51([ - 784210426627951, - 918204562375674, - 1284546780452985, - 1324534636134684, - 1872449409642708, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 2571438643225542, - 2848082470493653, - 2037902696412607, - 1557219121643918, - 341938082688094, - ]), - y_minus_x: FieldElement51([ - 1901860206695915, - 2004489122065736, - 1625847061568236, - 973529743399879, - 2075287685312905, - ]), - xy2d: FieldElement51([ - 1371853944110545, - 1042332820512553, - 1949855697918254, - 1791195775521505, - 37487364849293, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 687200189577836, - 1082536651125675, - 2896024754556794, - 2592723009743198, - 2595381160432643, - ]), - y_minus_x: FieldElement51([ - 2082717129583892, - 27829425539422, - 145655066671970, - 1690527209845512, - 1865260509673478, - ]), - xy2d: FieldElement51([ - 1059729620568824, - 2163709103470266, - 1440302280256872, - 1769143160546397, - 869830310425069, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 3861316033464273, - 777277757338816, - 2101121130363987, - 550762194946473, - 1905542338659364, - ]), - y_minus_x: FieldElement51([ - 2024821921041576, - 426948675450149, - 595133284085473, - 471860860885970, - 600321679413000, - ]), - xy2d: FieldElement51([ - 598474602406721, - 1468128276358244, - 1191923149557635, - 1501376424093216, - 1281662691293476, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 1721138489890688, - 1264336102277790, - 2684864359106535, - 1359988423149465, - 3813671107094695, - ]), - y_minus_x: FieldElement51([ - 719520245587143, - 393380711632345, - 132350400863381, - 1543271270810729, - 1819543295798660, - ]), - xy2d: FieldElement51([ - 396397949784152, - 1811354474471839, - 1362679985304303, - 2117033964846756, - 498041172552279, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 1812471844975748, - 1856491995543149, - 126579494584102, - 3288044672967868, - 1975108050082549, - ]), - y_minus_x: FieldElement51([ - 650623932407995, - 1137551288410575, - 2125223403615539, - 1725658013221271, - 2134892965117796, - ]), - xy2d: FieldElement51([ - 522584000310195, - 1241762481390450, - 1743702789495384, - 2227404127826575, - 1686746002148897, - ]), - }, - ]), - LookupTable([ - AffineNielsPoint { - y_plus_x: FieldElement51([ - 427904865186293, - 1703211129693455, - 1585368107547509, - 3688784302429584, - 3012988348299225, - ]), - y_minus_x: FieldElement51([ - 318101947455002, - 248138407995851, - 1481904195303927, - 309278454311197, - 1258516760217879, - ]), - xy2d: FieldElement51([ - 1275068538599310, - 513726919533379, - 349926553492294, - 688428871968420, - 1702400196000666, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 3313663849950481, - 3213411074010628, - 2573659446386085, - 3297400443644764, - 1985130202504037, - ]), - y_minus_x: FieldElement51([ - 1558816436882417, - 1962896332636523, - 1337709822062152, - 1501413830776938, - 294436165831932, - ]), - xy2d: FieldElement51([ - 818359826554971, - 1862173000996177, - 626821592884859, - 573655738872376, - 1749691246745455, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 1988022651432119, - 3333911312271288, - 1834020786104820, - 3706626690108935, - 692929915223121, - ]), - y_minus_x: FieldElement51([ - 2146513703733331, - 584788900394667, - 464965657279958, - 2183973639356127, - 238371159456790, - ]), - xy2d: FieldElement51([ - 1129007025494441, - 2197883144413266, - 265142755578169, - 971864464758890, - 1983715884903702, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 1291366624493056, - 2633256531874362, - 1711482489312443, - 1815233647702022, - 3144079596677715, - ]), - y_minus_x: FieldElement51([ - 444548969917454, - 1452286453853356, - 2113731441506810, - 645188273895859, - 810317625309512, - ]), - xy2d: FieldElement51([ - 2242724082797924, - 1373354730327868, - 1006520110883049, - 2147330369940688, - 1151816104883620, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 3997520014069025, - 4163522956860564, - 2056329390702073, - 2607026987995097, - 3131032608056347, - ]), - y_minus_x: FieldElement51([ - 163723479936298, - 115424889803150, - 1156016391581227, - 1894942220753364, - 1970549419986329, - ]), - xy2d: FieldElement51([ - 681981452362484, - 267208874112496, - 1374683991933094, - 638600984916117, - 646178654558546, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 2265178468539480, - 2358037120714814, - 1944412051589650, - 4093776581610705, - 2482502633520820, - ]), - y_minus_x: FieldElement51([ - 260683893467075, - 854060306077237, - 913639551980112, - 4704576840123, - 280254810808712, - ]), - xy2d: FieldElement51([ - 715374893080287, - 1173334812210491, - 1806524662079626, - 1894596008000979, - 398905715033393, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 2751826223412909, - 3848231101880618, - 1420380351989369, - 3237011375206737, - 392444930785632, - ]), - y_minus_x: FieldElement51([ - 2096421546958141, - 1922523000950363, - 789831022876840, - 427295144688779, - 320923973161730, - ]), - xy2d: FieldElement51([ - 1927770723575450, - 1485792977512719, - 1850996108474547, - 551696031508956, - 2126047405475647, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 2112099158080129, - 2994370617594963, - 2258284371762679, - 1951119898618915, - 2344890196388664, - ]), - y_minus_x: FieldElement51([ - 383905201636970, - 859946997631870, - 855623867637644, - 1017125780577795, - 794250831877809, - ]), - xy2d: FieldElement51([ - 77571826285752, - 999304298101753, - 487841111777762, - 1038031143212339, - 339066367948762, - ]), - }, - ]), - LookupTable([ - AffineNielsPoint { - y_plus_x: FieldElement51([ - 2926794589205781, - 2517835660016036, - 826951213393477, - 1405007746162285, - 1781791018620876, - ]), - y_minus_x: FieldElement51([ - 1001412661522686, - 348196197067298, - 1666614366723946, - 888424995032760, - 580747687801357, - ]), - xy2d: FieldElement51([ - 1939560076207777, - 1409892634407635, - 552574736069277, - 383854338280405, - 190706709864139, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 2177087163428741, - 1439255351721944, - 3459870654068041, - 2230616362004768, - 1396886392021913, - ]), - y_minus_x: FieldElement51([ - 676962063230039, - 1880275537148808, - 2046721011602706, - 888463247083003, - 1318301552024067, - ]), - xy2d: FieldElement51([ - 1466980508178206, - 617045217998949, - 652303580573628, - 757303753529064, - 207583137376902, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 3762856566592150, - 2357202940576524, - 2745234706458093, - 1091943425335975, - 1802717338077427, - ]), - y_minus_x: FieldElement51([ - 1853982405405128, - 1878664056251147, - 1528011020803992, - 1019626468153565, - 1128438412189035, - ]), - xy2d: FieldElement51([ - 1963939888391106, - 293456433791664, - 697897559513649, - 985882796904380, - 796244541237972, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 2668570812315008, - 2641455366112301, - 1314476859406755, - 1749382513022778, - 3413705412424739, - ]), - y_minus_x: FieldElement51([ - 1428358296490651, - 1027115282420478, - 304840698058337, - 441410174026628, - 1819358356278573, - ]), - xy2d: FieldElement51([ - 204943430200135, - 1554861433819175, - 216426658514651, - 264149070665950, - 2047097371738319, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 1934415182909015, - 1393285083565062, - 2768209145458208, - 3409490548679139, - 2372839480279515, - ]), - y_minus_x: FieldElement51([ - 662035583584445, - 286736105093098, - 1131773000510616, - 818494214211439, - 472943792054479, - ]), - xy2d: FieldElement51([ - 665784778135882, - 1893179629898606, - 808313193813106, - 276797254706413, - 1563426179676396, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 945205108984213, - 2778077376644543, - 1324180513733565, - 1666970227868664, - 2405347422974421, - ]), - y_minus_x: FieldElement51([ - 2031433403516252, - 203996615228162, - 170487168837083, - 981513604791390, - 843573964916831, - ]), - xy2d: FieldElement51([ - 1476570093962618, - 838514669399805, - 1857930577281364, - 2017007352225784, - 317085545220047, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 1461557121912823, - 1600674043318359, - 2157134900399597, - 1670641601940616, - 2379565397488531, - ]), - y_minus_x: FieldElement51([ - 1293543509393474, - 2143624609202546, - 1058361566797508, - 214097127393994, - 946888515472729, - ]), - xy2d: FieldElement51([ - 357067959932916, - 1290876214345711, - 521245575443703, - 1494975468601005, - 800942377643885, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 2817916472785262, - 820247422481739, - 994464017954148, - 2578957425371613, - 2344391131796991, - ]), - y_minus_x: FieldElement51([ - 617256647603209, - 1652107761099439, - 1857213046645471, - 1085597175214970, - 817432759830522, - ]), - xy2d: FieldElement51([ - 771808161440705, - 1323510426395069, - 680497615846440, - 851580615547985, - 1320806384849017, - ]), - }, - ]), - LookupTable([ - AffineNielsPoint { - y_plus_x: FieldElement51([ - 1219260086131896, - 2898968820282063, - 2331400938444953, - 2161724213426747, - 2656661710745446, - ]), - y_minus_x: FieldElement51([ - 1327968293887866, - 1335500852943256, - 1401587164534264, - 558137311952440, - 1551360549268902, - ]), - xy2d: FieldElement51([ - 417621685193956, - 1429953819744454, - 396157358457099, - 1940470778873255, - 214000046234152, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 1268047918491954, - 2172375426948536, - 1533916099229249, - 1761293575457130, - 3842422480712013, - ]), - y_minus_x: FieldElement51([ - 1627072914981959, - 2211603081280073, - 1912369601616504, - 1191770436221309, - 2187309757525860, - ]), - xy2d: FieldElement51([ - 1149147819689533, - 378692712667677, - 828475842424202, - 2218619146419342, - 70688125792186, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 3551539230764990, - 3690416477138006, - 3788528892189659, - 2053896748919837, - 3260220846276494, - ]), - y_minus_x: FieldElement51([ - 2040723824657366, - 399555637875075, - 632543375452995, - 872649937008051, - 1235394727030233, - ]), - xy2d: FieldElement51([ - 2211311599327900, - 2139787259888175, - 938706616835350, - 12609661139114, - 2081897930719789, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 1324994503390431, - 2588782144267879, - 1183998925654176, - 3343454479598522, - 2300527487656566, - ]), - y_minus_x: FieldElement51([ - 1845522914617879, - 1222198248335542, - 150841072760134, - 1927029069940982, - 1189913404498011, - ]), - xy2d: FieldElement51([ - 1079559557592645, - 2215338383666441, - 1903569501302605, - 49033973033940, - 305703433934152, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 2346453219102138, - 3637921163538246, - 3313930291577009, - 2288353761164521, - 3085469462634093, - ]), - y_minus_x: FieldElement51([ - 1432015813136298, - 440364795295369, - 1395647062821501, - 1976874522764578, - 934452372723352, - ]), - xy2d: FieldElement51([ - 1296625309219774, - 2068273464883862, - 1858621048097805, - 1492281814208508, - 2235868981918946, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 1490330266465551, - 1858795661361448, - 3688040948655011, - 2546373032584894, - 3459939824714180, - ]), - y_minus_x: FieldElement51([ - 1282462923712748, - 741885683986255, - 2027754642827561, - 518989529541027, - 1826610009555945, - ]), - xy2d: FieldElement51([ - 1525827120027511, - 723686461809551, - 1597702369236987, - 244802101764964, - 1502833890372311, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 2365421849929742, - 3485539881431101, - 2925909765963743, - 2114345180342964, - 2418564326541511, - ]), - y_minus_x: FieldElement51([ - 2041668749310338, - 2184405322203901, - 1633400637611036, - 2110682505536899, - 2048144390084644, - ]), - xy2d: FieldElement51([ - 503058759232932, - 760293024620937, - 2027152777219493, - 666858468148475, - 1539184379870952, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 1916168475367211, - 3167426246226591, - 883217071712574, - 363427871374304, - 1976029821251593, - ]), - y_minus_x: FieldElement51([ - 678039535434506, - 570587290189340, - 1605302676614120, - 2147762562875701, - 1706063797091704, - ]), - xy2d: FieldElement51([ - 1439489648586438, - 2194580753290951, - 832380563557396, - 561521973970522, - 584497280718389, - ]), - }, - ]), - LookupTable([ - AffineNielsPoint { - y_plus_x: FieldElement51([ - 2439789269177838, - 681223515948274, - 1933493571072456, - 1872921007304880, - 2739962177820919, - ]), - y_minus_x: FieldElement51([ - 1413466089534451, - 410844090765630, - 1397263346404072, - 408227143123410, - 1594561803147811, - ]), - xy2d: FieldElement51([ - 2102170800973153, - 719462588665004, - 1479649438510153, - 1097529543970028, - 1302363283777685, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 3193865531532443, - 3321113493038208, - 2007341951411050, - 2322773230131539, - 1419433790163705, - ]), - y_minus_x: FieldElement51([ - 1146565545556377, - 1661971299445212, - 406681704748893, - 564452436406089, - 1109109865829139, - ]), - xy2d: FieldElement51([ - 2214421081775077, - 1165671861210569, - 1890453018796184, - 3556249878661, - 442116172656317, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 3005630360306059, - 1666955059895018, - 1530775289309243, - 3371786842789394, - 2164156153857579, - ]), - y_minus_x: FieldElement51([ - 615171919212796, - 1523849404854568, - 854560460547503, - 2067097370290715, - 1765325848586042, - ]), - xy2d: FieldElement51([ - 1094538949313667, - 1796592198908825, - 870221004284388, - 2025558921863561, - 1699010892802384, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 1951351290725195, - 1916457206844795, - 2449824998123274, - 1909076887557594, - 1938542290318919, - ]), - y_minus_x: FieldElement51([ - 1014323197538413, - 869150639940606, - 1756009942696599, - 1334952557375672, - 1544945379082874, - ]), - xy2d: FieldElement51([ - 764055910920305, - 1603590757375439, - 146805246592357, - 1843313433854297, - 954279890114939, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 80113526615731, - 764536758732259, - 3306939158785481, - 2721052465444637, - 2869697326116762, - ]), - y_minus_x: FieldElement51([ - 74497112547268, - 740094153192149, - 1745254631717581, - 727713886503130, - 1283034364416928, - ]), - xy2d: FieldElement51([ - 525892105991110, - 1723776830270342, - 1476444848991936, - 573789489857760, - 133864092632978, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 2794411533877810, - 1986812262899320, - 1162535242465837, - 2733298779828712, - 2796400347268869, - ]), - y_minus_x: FieldElement51([ - 64123227344372, - 1239927720647794, - 1360722983445904, - 222610813654661, - 62429487187991, - ]), - xy2d: FieldElement51([ - 1793193323953132, - 91096687857833, - 70945970938921, - 2158587638946380, - 1537042406482111, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 1895854577604590, - 3646695522634664, - 1728548428495943, - 3392664713925397, - 2815445147288308, - ]), - y_minus_x: FieldElement51([ - 141358280486863, - 91435889572504, - 1087208572552643, - 1829599652522921, - 1193307020643647, - ]), - xy2d: FieldElement51([ - 1611230858525381, - 950720175540785, - 499589887488610, - 2001656988495019, - 88977313255908, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 3440880315164906, - 2184348804772596, - 3292618539427567, - 2018318290311833, - 1712060030915354, - ]), - y_minus_x: FieldElement51([ - 873966876953756, - 1090638350350440, - 1708559325189137, - 672344594801910, - 1320437969700239, - ]), - xy2d: FieldElement51([ - 1508590048271766, - 1131769479776094, - 101550868699323, - 428297785557897, - 561791648661744, - ]), - }, - ]), - LookupTable([ - AffineNielsPoint { - y_plus_x: FieldElement51([ - 3008217384184691, - 2489682092917849, - 2136263418594015, - 1701968045454886, - 2955512998822720, - ]), - y_minus_x: FieldElement51([ - 1781187809325462, - 1697624151492346, - 1381393690939988, - 175194132284669, - 1483054666415238, - ]), - xy2d: FieldElement51([ - 2175517777364616, - 708781536456029, - 955668231122942, - 1967557500069555, - 2021208005604118, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 3366935780292116, - 2476017186636029, - 915967306279221, - 593866251291540, - 2813546907893254, - ]), - y_minus_x: FieldElement51([ - 1443163092879439, - 391875531646162, - 2180847134654632, - 464538543018753, - 1594098196837178, - ]), - xy2d: FieldElement51([ - 850858855888869, - 319436476624586, - 327807784938441, - 740785849558761, - 17128415486016, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 2132756334090048, - 2788047633840893, - 2300706964962114, - 2860273011285942, - 3513489358708031, - ]), - y_minus_x: FieldElement51([ - 1525176236978354, - 974205476721062, - 293436255662638, - 148269621098039, - 137961998433963, - ]), - xy2d: FieldElement51([ - 1121075518299410, - 2071745529082111, - 1265567917414828, - 1648196578317805, - 496232102750820, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 2374121042985030, - 3274721891178932, - 2001275453369483, - 2017441881607947, - 3245005694463250, - ]), - y_minus_x: FieldElement51([ - 654925550560074, - 1168810995576858, - 575655959430926, - 905758704861388, - 496774564663534, - ]), - xy2d: FieldElement51([ - 1954109525779738, - 2117022646152485, - 338102630417180, - 1194140505732026, - 107881734943492, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 1714785840001267, - 4288299832366837, - 1876380234251965, - 2056717182974196, - 1645855254384642, - ]), - y_minus_x: FieldElement51([ - 106431476499341, - 62482972120563, - 1513446655109411, - 807258751769522, - 538491469114, - ]), - xy2d: FieldElement51([ - 2002850762893643, - 1243624520538135, - 1486040410574605, - 2184752338181213, - 378495998083531, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 922510868424903, - 1089502620807680, - 402544072617374, - 1131446598479839, - 1290278588136533, - ]), - y_minus_x: FieldElement51([ - 1867998812076769, - 715425053580701, - 39968586461416, - 2173068014586163, - 653822651801304, - ]), - xy2d: FieldElement51([ - 162892278589453, - 182585796682149, - 75093073137630, - 497037941226502, - 133871727117371, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 4166396390264918, - 1608999621851577, - 1987629837704609, - 1519655314857977, - 1819193753409464, - ]), - y_minus_x: FieldElement51([ - 1949315551096831, - 1069003344994464, - 1939165033499916, - 1548227205730856, - 1933767655861407, - ]), - xy2d: FieldElement51([ - 1730519386931635, - 1393284965610134, - 1597143735726030, - 416032382447158, - 1429665248828629, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 360275475604546, - 2799635544748326, - 2467160717872776, - 2848446553564254, - 2584509464110332, - ]), - y_minus_x: FieldElement51([ - 47602113726801, - 1522314509708010, - 437706261372925, - 814035330438027, - 335930650933545, - ]), - xy2d: FieldElement51([ - 1291597595523886, - 1058020588994081, - 402837842324045, - 1363323695882781, - 2105763393033193, - ]), - }, - ]), - LookupTable([ - AffineNielsPoint { - y_plus_x: FieldElement51([ - 2361321796251793, - 3967057562270386, - 1112231216891515, - 2046641005101484, - 2386048970842261, - ]), - y_minus_x: FieldElement51([ - 2156991030936798, - 2227544497153325, - 1869050094431622, - 754875860479115, - 1754242344267058, - ]), - xy2d: FieldElement51([ - 1846089562873800, - 98894784984326, - 1412430299204844, - 171351226625762, - 1100604760929008, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 2335972195815721, - 2751510784385293, - 425749630620777, - 1762872794206857, - 2864642415813208, - ]), - y_minus_x: FieldElement51([ - 868309334532756, - 1703010512741873, - 1952690008738057, - 4325269926064, - 2071083554962116, - ]), - xy2d: FieldElement51([ - 523094549451158, - 401938899487815, - 1407690589076010, - 2022387426254453, - 158660516411257, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 612867287630009, - 2700012425789062, - 2823428891104443, - 1466796750919375, - 1728478129663858, - ]), - y_minus_x: FieldElement51([ - 1723848973783452, - 2208822520534681, - 1718748322776940, - 1974268454121942, - 1194212502258141, - ]), - xy2d: FieldElement51([ - 1254114807944608, - 977770684047110, - 2010756238954993, - 1783628927194099, - 1525962994408256, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 2484263871921055, - 1948628555342433, - 1835348780427694, - 1031609499437291, - 2316271920603621, - ]), - y_minus_x: FieldElement51([ - 767338676040683, - 754089548318405, - 1523192045639075, - 435746025122062, - 512692508440385, - ]), - xy2d: FieldElement51([ - 1255955808701983, - 1700487367990941, - 1166401238800299, - 1175121994891534, - 1190934801395380, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 2600943821853521, - 1337012557669161, - 1475912332999108, - 3573418268585706, - 2299411105589567, - ]), - y_minus_x: FieldElement51([ - 877519947135419, - 2172838026132651, - 272304391224129, - 1655143327559984, - 886229406429814, - ]), - xy2d: FieldElement51([ - 375806028254706, - 214463229793940, - 572906353144089, - 572168269875638, - 697556386112979, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 1168827102357825, - 823864273033637, - 4323338565789945, - 788062026895923, - 2851378154428610, - ]), - y_minus_x: FieldElement51([ - 1948116082078088, - 2054898304487796, - 2204939184983900, - 210526805152138, - 786593586607626, - ]), - xy2d: FieldElement51([ - 1915320147894736, - 156481169009469, - 655050471180417, - 592917090415421, - 2165897438660879, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 1726336468579724, - 1119932070398949, - 1929199510967666, - 2285718602008207, - 1836837863503149, - ]), - y_minus_x: FieldElement51([ - 829996854845988, - 217061778005138, - 1686565909803640, - 1346948817219846, - 1723823550730181, - ]), - xy2d: FieldElement51([ - 384301494966394, - 687038900403062, - 2211195391021739, - 254684538421383, - 1245698430589680, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 1247567493562669, - 4229981908141095, - 2435671288478202, - 806570235643434, - 2540261331753164, - ]), - y_minus_x: FieldElement51([ - 1449077384734201, - 38285445457996, - 2136537659177832, - 2146493000841573, - 725161151123125, - ]), - xy2d: FieldElement51([ - 1201928866368855, - 800415690605445, - 1703146756828343, - 997278587541744, - 1858284414104014, - ]), - }, - ]), - LookupTable([ - AffineNielsPoint { - y_plus_x: FieldElement51([ - 2608268623334125, - 3034173730618399, - 1718002439402869, - 3644022065904502, - 663171266061950, - ]), - y_minus_x: FieldElement51([ - 759628738230460, - 1012693474275852, - 353780233086498, - 246080061387552, - 2030378857679162, - ]), - xy2d: FieldElement51([ - 2040672435071076, - 888593182036908, - 1298443657189359, - 1804780278521327, - 354070726137060, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 1894938527423184, - 3715012855162525, - 2726210319182898, - 2499094776718546, - 877975941029127, - ]), - y_minus_x: FieldElement51([ - 207937160991127, - 12966911039119, - 820997788283092, - 1010440472205286, - 1701372890140810, - ]), - xy2d: FieldElement51([ - 218882774543183, - 533427444716285, - 1233243976733245, - 435054256891319, - 1509568989549904, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 4140638349397055, - 3303977572025869, - 3465353617009382, - 2420981822812579, - 2715174081801119, - ]), - y_minus_x: FieldElement51([ - 299137589460312, - 1594371588983567, - 868058494039073, - 257771590636681, - 1805012993142921, - ]), - xy2d: FieldElement51([ - 1806842755664364, - 2098896946025095, - 1356630998422878, - 1458279806348064, - 347755825962072, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 1402334161391744, - 3811883484731547, - 1008585416617746, - 1147797150908892, - 1420416683642459, - ]), - y_minus_x: FieldElement51([ - 665506704253369, - 273770475169863, - 799236974202630, - 848328990077558, - 1811448782807931, - ]), - xy2d: FieldElement51([ - 1468412523962641, - 771866649897997, - 1931766110147832, - 799561180078482, - 524837559150077, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 2223212657821831, - 2882216061048914, - 2144451165500327, - 3068710944633039, - 3276150872095279, - ]), - y_minus_x: FieldElement51([ - 1266603897524861, - 156378408858100, - 1275649024228779, - 447738405888420, - 253186462063095, - ]), - xy2d: FieldElement51([ - 2022215964509735, - 136144366993649, - 1800716593296582, - 1193970603800203, - 871675847064218, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 1862751661970309, - 851596246739884, - 1519315554814041, - 3794598280232697, - 3669775149586767, - ]), - y_minus_x: FieldElement51([ - 1228168094547481, - 334133883362894, - 587567568420081, - 433612590281181, - 603390400373205, - ]), - xy2d: FieldElement51([ - 121893973206505, - 1843345804916664, - 1703118377384911, - 497810164760654, - 101150811654673, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 2710146069631716, - 2542709749304591, - 1452768413850678, - 2802722688939463, - 1537286854336537, - ]), - y_minus_x: FieldElement51([ - 584322311184395, - 380661238802118, - 114839394528060, - 655082270500073, - 2111856026034852, - ]), - xy2d: FieldElement51([ - 996965581008991, - 2148998626477022, - 1012273164934654, - 1073876063914522, - 1688031788934939, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 3175286832534829, - 2085106799623354, - 2779882615305384, - 1606206360876187, - 2987706905397772, - ]), - y_minus_x: FieldElement51([ - 1697697887804317, - 1335343703828273, - 831288615207040, - 949416685250051, - 288760277392022, - ]), - xy2d: FieldElement51([ - 1419122478109648, - 1325574567803701, - 602393874111094, - 2107893372601700, - 1314159682671307, - ]), - }, - ]), - LookupTable([ - AffineNielsPoint { - y_plus_x: FieldElement51([ - 2201150872731785, - 2180241023425241, - 2349463270108411, - 1633405770247823, - 3100744856129234, - ]), - y_minus_x: FieldElement51([ - 1173339555550611, - 818605084277583, - 47521504364289, - 924108720564965, - 735423405754506, - ]), - xy2d: FieldElement51([ - 830104860549448, - 1886653193241086, - 1600929509383773, - 1475051275443631, - 286679780900937, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 3828911108518224, - 3282698983453994, - 2396700729978777, - 4216472406664814, - 2820189914640497, - ]), - y_minus_x: FieldElement51([ - 278388655910247, - 487143369099838, - 927762205508727, - 181017540174210, - 1616886700741287, - ]), - xy2d: FieldElement51([ - 1191033906638969, - 940823957346562, - 1606870843663445, - 861684761499847, - 658674867251089, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 1875032594195527, - 1427106132796197, - 2976536204647406, - 3153660325729987, - 2887068310954007, - ]), - y_minus_x: FieldElement51([ - 622869792298357, - 1903919278950367, - 1922588621661629, - 1520574711600434, - 1087100760174640, - ]), - xy2d: FieldElement51([ - 25465949416618, - 1693639527318811, - 1526153382657203, - 125943137857169, - 145276964043999, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 2466539671654587, - 920212862967914, - 4191701364657517, - 3463662605460468, - 2336897329405367, - ]), - y_minus_x: FieldElement51([ - 2006245852772938, - 734762734836159, - 254642929763427, - 1406213292755966, - 239303749517686, - ]), - xy2d: FieldElement51([ - 1619678837192149, - 1919424032779215, - 1357391272956794, - 1525634040073113, - 1310226789796241, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 3292563523447371, - 1704449869235351, - 2857062884141577, - 1998838089036354, - 1312142911487502, - ]), - y_minus_x: FieldElement51([ - 1996723311435669, - 1844342766567060, - 985455700466044, - 1165924681400960, - 311508689870129, - ]), - xy2d: FieldElement51([ - 43173156290518, - 2202883069785309, - 1137787467085917, - 1733636061944606, - 1394992037553852, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 670078326344559, - 2807454838744604, - 2723759199967685, - 2141455487356408, - 849015953823125, - ]), - y_minus_x: FieldElement51([ - 2197214573372804, - 794254097241315, - 1030190060513737, - 267632515541902, - 2040478049202624, - ]), - xy2d: FieldElement51([ - 1812516004670529, - 1609256702920783, - 1706897079364493, - 258549904773295, - 996051247540686, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 1540374301420565, - 1764656898914615, - 1810104162020396, - 3175608592848336, - 2916189887881826, - ]), - y_minus_x: FieldElement51([ - 1323460699404750, - 1262690757880991, - 871777133477900, - 1060078894988977, - 1712236889662886, - ]), - xy2d: FieldElement51([ - 1696163952057966, - 1391710137550823, - 608793846867416, - 1034391509472039, - 1780770894075012, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 1367603834210822, - 4383788460268472, - 890353773628143, - 1908908219165595, - 2522636708938139, - ]), - y_minus_x: FieldElement51([ - 597536315471731, - 40375058742586, - 1942256403956049, - 1185484645495932, - 312666282024145, - ]), - xy2d: FieldElement51([ - 1919411405316294, - 1234508526402192, - 1066863051997083, - 1008444703737597, - 1348810787701552, - ]), - }, - ]), - LookupTable([ - AffineNielsPoint { - y_plus_x: FieldElement51([ - 2102881477513865, - 3822074379630609, - 1573617900503707, - 2270462449417831, - 2232324307922097, - ]), - y_minus_x: FieldElement51([ - 1853931367696942, - 8107973870707, - 350214504129299, - 775206934582587, - 1752317649166792, - ]), - xy2d: FieldElement51([ - 1417148368003523, - 721357181628282, - 505725498207811, - 373232277872983, - 261634707184480, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 2186733281493248, - 2250694917008620, - 1014829812957440, - 2731797975137637, - 2335366007561721, - ]), - y_minus_x: FieldElement51([ - 1268116367301224, - 560157088142809, - 802626839600444, - 2210189936605713, - 1129993785579988, - ]), - xy2d: FieldElement51([ - 615183387352312, - 917611676109240, - 878893615973325, - 978940963313282, - 938686890583575, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 522024729211672, - 3296859129001056, - 1892245413707789, - 1907891107684253, - 2059998109500714, - ]), - y_minus_x: FieldElement51([ - 1799679152208884, - 912132775900387, - 25967768040979, - 432130448590461, - 274568990261996, - ]), - xy2d: FieldElement51([ - 98698809797682, - 2144627600856209, - 1907959298569602, - 811491302610148, - 1262481774981493, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 1791451399743152, - 1713538728337276, - 2370149810942738, - 1882306388849953, - 158235232210248, - ]), - y_minus_x: FieldElement51([ - 1217809823321928, - 2173947284933160, - 1986927836272325, - 1388114931125539, - 12686131160169, - ]), - xy2d: FieldElement51([ - 1650875518872272, - 1136263858253897, - 1732115601395988, - 734312880662190, - 1252904681142109, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 2624786269799113, - 2777230729143418, - 2116279931702134, - 2753222527273063, - 1907002872974924, - ]), - y_minus_x: FieldElement51([ - 803147181835288, - 868941437997146, - 316299302989663, - 943495589630550, - 571224287904572, - ]), - xy2d: FieldElement51([ - 227742695588364, - 1776969298667369, - 628602552821802, - 457210915378118, - 2041906378111140, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 815000523470260, - 3164885502413555, - 3303859931956420, - 1345536665214222, - 541623413135555, - ]), - y_minus_x: FieldElement51([ - 1580216071604333, - 1877997504342444, - 857147161260913, - 703522726778478, - 2182763974211603, - ]), - xy2d: FieldElement51([ - 1870080310923419, - 71988220958492, - 1783225432016732, - 615915287105016, - 1035570475990230, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 2982787564515398, - 857613889540279, - 1083813157271766, - 1002817255970169, - 1719228484436074, - ]), - y_minus_x: FieldElement51([ - 377616581647602, - 1581980403078513, - 804044118130621, - 2034382823044191, - 643844048472185, - ]), - xy2d: FieldElement51([ - 176957326463017, - 1573744060478586, - 528642225008045, - 1816109618372371, - 1515140189765006, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 1888911448245718, - 3638910709296328, - 4176303607751676, - 1731539523700948, - 2230378382645454, - ]), - y_minus_x: FieldElement51([ - 443392177002051, - 233793396845137, - 2199506622312416, - 1011858706515937, - 974676837063129, - ]), - xy2d: FieldElement51([ - 1846351103143623, - 1949984838808427, - 671247021915253, - 1946756846184401, - 1929296930380217, - ]), - }, - ]), - LookupTable([ - AffineNielsPoint { - y_plus_x: FieldElement51([ - 849646212451983, - 1410198775302919, - 2325567699868943, - 1641663456615811, - 3014056086137659, - ]), - y_minus_x: FieldElement51([ - 692017667358279, - 723305578826727, - 1638042139863265, - 748219305990306, - 334589200523901, - ]), - xy2d: FieldElement51([ - 22893968530686, - 2235758574399251, - 1661465835630252, - 925707319443452, - 1203475116966621, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 3053098849470395, - 3985092410411378, - 1664508947088595, - 2719548934677170, - 3899298398220870, - ]), - y_minus_x: FieldElement51([ - 903105258014366, - 427141894933047, - 561187017169777, - 1884330244401954, - 1914145708422219, - ]), - xy2d: FieldElement51([ - 1344191060517578, - 1960935031767890, - 1518838929955259, - 1781502350597190, - 1564784025565682, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 2925523165433334, - 1979969272514922, - 3427087126180756, - 1187589090978665, - 1881897672213940, - ]), - y_minus_x: FieldElement51([ - 1917185587363432, - 1098342571752737, - 5935801044414, - 2000527662351839, - 1538640296181569, - ]), - xy2d: FieldElement51([ - 2495540013192, - 678856913479236, - 224998292422872, - 219635787698590, - 1972465269000940, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 271413961212179, - 3604851875156899, - 2596511104968730, - 2014925838520661, - 2006221033113941, - ]), - y_minus_x: FieldElement51([ - 194583029968109, - 514316781467765, - 829677956235672, - 1676415686873082, - 810104584395840, - ]), - xy2d: FieldElement51([ - 1980510813313589, - 1948645276483975, - 152063780665900, - 129968026417582, - 256984195613935, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 1860190562533083, - 1936576191345085, - 2712900106391212, - 1811043097042829, - 3209286562992083, - ]), - y_minus_x: FieldElement51([ - 796664815624365, - 1543160838872951, - 1500897791837765, - 1667315977988401, - 599303877030711, - ]), - xy2d: FieldElement51([ - 1151480509533204, - 2136010406720455, - 738796060240027, - 319298003765044, - 1150614464349587, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 1731069268103131, - 2987442261301335, - 1364750481334267, - 2669032653668119, - 3178908082812908, - ]), - y_minus_x: FieldElement51([ - 1017222050227968, - 1987716148359, - 2234319589635701, - 621282683093392, - 2132553131763026, - ]), - xy2d: FieldElement51([ - 1567828528453324, - 1017807205202360, - 565295260895298, - 829541698429100, - 307243822276582, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 249079270936229, - 1501514259790706, - 3199709537890096, - 944551802437486, - 2804458577667728, - ]), - y_minus_x: FieldElement51([ - 2089966982947227, - 1854140343916181, - 2151980759220007, - 2139781292261749, - 158070445864917, - ]), - xy2d: FieldElement51([ - 1338766321464554, - 1906702607371284, - 1519569445519894, - 115384726262267, - 1393058953390992, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 3616421371950629, - 3764188048593604, - 1926731583198685, - 2041482526432505, - 3172200936019022, - ]), - y_minus_x: FieldElement51([ - 1884844597333588, - 601480070269079, - 620203503079537, - 1079527400117915, - 1202076693132015, - ]), - xy2d: FieldElement51([ - 840922919763324, - 727955812569642, - 1303406629750194, - 522898432152867, - 294161410441865, - ]), - }, - ]), - LookupTable([ - AffineNielsPoint { - y_plus_x: FieldElement51([ - 2605560604520539, - 1598361541848742, - 3374705511887547, - 4174333403844152, - 2670907514351827, - ]), - y_minus_x: FieldElement51([ - 359856369838236, - 180914355488683, - 861726472646627, - 218807937262986, - 575626773232501, - ]), - xy2d: FieldElement51([ - 755467689082474, - 909202735047934, - 730078068932500, - 936309075711518, - 2007798262842972, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 1609384177904054, - 2614544999293875, - 1335318541768200, - 3052765584121496, - 2799677792952659, - ]), - y_minus_x: FieldElement51([ - 984339177776787, - 815727786505884, - 1645154585713747, - 1659074964378553, - 1686601651984156, - ]), - xy2d: FieldElement51([ - 1697863093781930, - 599794399429786, - 1104556219769607, - 830560774794755, - 12812858601017, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 1168737550514982, - 897832437380552, - 463140296333799, - 2554364413707795, - 2008360505135500, - ]), - y_minus_x: FieldElement51([ - 1856930662813910, - 678090852002597, - 1920179140755167, - 1259527833759868, - 55540971895511, - ]), - xy2d: FieldElement51([ - 1158643631044921, - 476554103621892, - 178447851439725, - 1305025542653569, - 103433927680625, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 2176793111709008, - 3828525530035639, - 2009350167273522, - 2012390194631546, - 2125297410909580, - ]), - y_minus_x: FieldElement51([ - 825403285195098, - 2144208587560784, - 1925552004644643, - 1915177840006985, - 1015952128947864, - ]), - xy2d: FieldElement51([ - 1807108316634472, - 1534392066433717, - 347342975407218, - 1153820745616376, - 7375003497471, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 3234860815484973, - 2683011703586488, - 2201903782961092, - 3069193724749589, - 2214616493042166, - ]), - y_minus_x: FieldElement51([ - 228567918409756, - 865093958780220, - 358083886450556, - 159617889659320, - 1360637926292598, - ]), - xy2d: FieldElement51([ - 234147501399755, - 2229469128637390, - 2175289352258889, - 1397401514549353, - 1885288963089922, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 3363562226636810, - 2504649386192636, - 3300514047508588, - 2397910909286693, - 1237505378776769, - ]), - y_minus_x: FieldElement51([ - 1113790697840279, - 1051167139966244, - 1045930658550944, - 2011366241542643, - 1686166824620755, - ]), - xy2d: FieldElement51([ - 1054097349305049, - 1872495070333352, - 182121071220717, - 1064378906787311, - 100273572924182, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 3558210666856834, - 1627717417672446, - 2302783034773665, - 1109249951172249, - 3122001602766640, - ]), - y_minus_x: FieldElement51([ - 104233794644221, - 1548919791188248, - 2224541913267306, - 2054909377116478, - 1043803389015153, - ]), - xy2d: FieldElement51([ - 216762189468802, - 707284285441622, - 190678557969733, - 973969342604308, - 1403009538434867, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 3530824104723725, - 2596576648903557, - 2525521909702446, - 4086000250496689, - 634517197663803, - ]), - y_minus_x: FieldElement51([ - 343805853118335, - 1302216857414201, - 566872543223541, - 2051138939539004, - 321428858384280, - ]), - xy2d: FieldElement51([ - 470067171324852, - 1618629234173951, - 2000092177515639, - 7307679772789, - 1117521120249968, - ]), - }, - ]), - LookupTable([ - AffineNielsPoint { - y_plus_x: FieldElement51([ - 2529951391976704, - 1810282338562946, - 1771599529530998, - 3635459223356879, - 2937173228157088, - ]), - y_minus_x: FieldElement51([ - 577009397403102, - 1791440261786291, - 2177643735971638, - 174546149911960, - 1412505077782326, - ]), - xy2d: FieldElement51([ - 893719721537457, - 1201282458018197, - 1522349501711173, - 58011597740583, - 1130406465887139, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 412607348255434, - 1280455764199780, - 2233277987330768, - 2265979894086913, - 2583384512102412, - ]), - y_minus_x: FieldElement51([ - 262483770854550, - 990511055108216, - 526885552771698, - 571664396646158, - 354086190278723, - ]), - xy2d: FieldElement51([ - 1820352417585487, - 24495617171480, - 1547899057533253, - 10041836186225, - 480457105094042, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 2023310314989233, - 2889705151211129, - 2106474638900686, - 2809620524769320, - 1687858215057825, - ]), - y_minus_x: FieldElement51([ - 1144168702609745, - 604444390410187, - 1544541121756138, - 1925315550126027, - 626401428894002, - ]), - xy2d: FieldElement51([ - 1922168257351784, - 2018674099908659, - 1776454117494445, - 956539191509034, - 36031129147635, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 2796444352433270, - 1039872944430373, - 3128550222815858, - 2962457525011798, - 3468752501170219, - ]), - y_minus_x: FieldElement51([ - 58242421545916, - 2035812695641843, - 2118491866122923, - 1191684463816273, - 46921517454099, - ]), - xy2d: FieldElement51([ - 272268252444639, - 1374166457774292, - 2230115177009552, - 1053149803909880, - 1354288411641016, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 1857910905368338, - 1754729879288912, - 3137745277795125, - 1516096106802165, - 1602902393369811, - ]), - y_minus_x: FieldElement51([ - 1193437069800958, - 901107149704790, - 999672920611411, - 477584824802207, - 364239578697845, - ]), - xy2d: FieldElement51([ - 886299989548838, - 1538292895758047, - 1590564179491896, - 1944527126709657, - 837344427345298, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 3006358179063534, - 1712186480903617, - 3955456640022779, - 3002110732175033, - 2770795853936147, - ]), - y_minus_x: FieldElement51([ - 1309847803895382, - 1462151862813074, - 211370866671570, - 1544595152703681, - 1027691798954090, - ]), - xy2d: FieldElement51([ - 803217563745370, - 1884799722343599, - 1357706345069218, - 2244955901722095, - 730869460037413, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 2941099284981214, - 1831210565161070, - 3626987155270686, - 3358084791231418, - 1893781834054268, - ]), - y_minus_x: FieldElement51([ - 696351368613042, - 1494385251239250, - 738037133616932, - 636385507851544, - 927483222611406, - ]), - xy2d: FieldElement51([ - 1949114198209333, - 1104419699537997, - 783495707664463, - 1747473107602770, - 2002634765788641, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 1607325776830197, - 2782683755100581, - 1451089452727894, - 3833490970768671, - 496100432831153, - ]), - y_minus_x: FieldElement51([ - 1068900648804224, - 2006891997072550, - 1134049269345549, - 1638760646180091, - 2055396084625778, - ]), - xy2d: FieldElement51([ - 2222475519314561, - 1870703901472013, - 1884051508440561, - 1344072275216753, - 1318025677799069, - ]), - }, - ]), - LookupTable([ - AffineNielsPoint { - y_plus_x: FieldElement51([ - 155711679280637, - 681100400509288, - 389811735211209, - 2135723811340709, - 2660533024889373, - ]), - y_minus_x: FieldElement51([ - 7813206966729, - 194444201427550, - 2071405409526507, - 1065605076176312, - 1645486789731291, - ]), - xy2d: FieldElement51([ - 16625790644959, - 1647648827778410, - 1579910185572704, - 436452271048548, - 121070048451050, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 3289062842237779, - 2820185594063076, - 2549752917829677, - 3810384325616458, - 2238221839292470, - ]), - y_minus_x: FieldElement51([ - 190565267697443, - 672855706028058, - 338796554369226, - 337687268493904, - 853246848691734, - ]), - xy2d: FieldElement51([ - 1763863028400139, - 766498079432444, - 1321118624818005, - 69494294452268, - 858786744165651, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 3543856582248253, - 1456632109855637, - 3352431060735432, - 1386133165675320, - 3484698163879000, - ]), - y_minus_x: FieldElement51([ - 366253102478259, - 525676242508811, - 1449610995265438, - 1183300845322183, - 185960306491545, - ]), - xy2d: FieldElement51([ - 28315355815982, - 460422265558930, - 1799675876678724, - 1969256312504498, - 1051823843138725, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 2408714813047231, - 3857948219405196, - 1665208410108429, - 2569443092377519, - 1383783705665319, - ]), - y_minus_x: FieldElement51([ - 54684536365732, - 2210010038536222, - 1194984798155308, - 535239027773705, - 1516355079301361, - ]), - xy2d: FieldElement51([ - 1484387703771650, - 198537510937949, - 2186282186359116, - 617687444857508, - 647477376402122, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 2147715541830533, - 2751832352131065, - 2898179830570073, - 2604027669016369, - 1488268620408051, - ]), - y_minus_x: FieldElement51([ - 159386186465542, - 1877626593362941, - 618737197060512, - 1026674284330807, - 1158121760792685, - ]), - xy2d: FieldElement51([ - 1744544377739822, - 1964054180355661, - 1685781755873170, - 2169740670377448, - 1286112621104591, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 2333777063470241, - 3919742931398333, - 3920783633320113, - 1605016835177614, - 1353960708075544, - ]), - y_minus_x: FieldElement51([ - 1602253788689063, - 439542044889886, - 2220348297664483, - 657877410752869, - 157451572512238, - ]), - xy2d: FieldElement51([ - 1029287186166717, - 65860128430192, - 525298368814832, - 1491902500801986, - 1461064796385400, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 2660016802414475, - 2121095722306988, - 913562102267595, - 1879708920318308, - 2492861262121979, - ]), - y_minus_x: FieldElement51([ - 1185483484383269, - 1356339572588553, - 584932367316448, - 102132779946470, - 1792922621116791, - ]), - xy2d: FieldElement51([ - 1966196870701923, - 2230044620318636, - 1425982460745905, - 261167817826569, - 46517743394330, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 2358877405280588, - 3136759755857592, - 2279106683482647, - 2224911448949389, - 3216151871930471, - ]), - y_minus_x: FieldElement51([ - 1730194207717538, - 431790042319772, - 1831515233279467, - 1372080552768581, - 1074513929381760, - ]), - xy2d: FieldElement51([ - 1450880638731607, - 1019861580989005, - 1229729455116861, - 1174945729836143, - 826083146840706, - ]), - }, - ]), - LookupTable([ - AffineNielsPoint { - y_plus_x: FieldElement51([ - 1899935429242705, - 1602068751520477, - 940583196550370, - 2334230882739107, - 1540863155745695, - ]), - y_minus_x: FieldElement51([ - 2136688454840028, - 2099509000964294, - 1690800495246475, - 1217643678575476, - 828720645084218, - ]), - xy2d: FieldElement51([ - 765548025667841, - 462473984016099, - 998061409979798, - 546353034089527, - 2212508972466858, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 2298375097456408, - 3144370785258318, - 1281983193144089, - 1491520128287375, - 75847005908304, - ]), - y_minus_x: FieldElement51([ - 1801436127943107, - 1734436817907890, - 1268728090345068, - 167003097070711, - 2233597765834956, - ]), - xy2d: FieldElement51([ - 1997562060465113, - 1048700225534011, - 7615603985628, - 1855310849546841, - 2242557647635213, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 1161017320376250, - 2744424393854291, - 2169815802355236, - 3228296595417790, - 1770879511019628, - ]), - y_minus_x: FieldElement51([ - 1357044908364776, - 729130645262438, - 1762469072918979, - 1365633616878458, - 181282906404941, - ]), - xy2d: FieldElement51([ - 1080413443139865, - 1155205815510486, - 1848782073549786, - 622566975152580, - 124965574467971, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 1184526762066993, - 247622751762817, - 2943928830891604, - 3071818503097743, - 2188697339828084, - ]), - y_minus_x: FieldElement51([ - 2020536369003019, - 202261491735136, - 1053169669150884, - 2056531979272544, - 778165514694311, - ]), - xy2d: FieldElement51([ - 237404399610207, - 1308324858405118, - 1229680749538400, - 720131409105291, - 1958958863624906, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 2767383321724075, - 2269456792542436, - 1717918437373988, - 1568052070792483, - 2298775616809171, - ]), - y_minus_x: FieldElement51([ - 281527309158085, - 36970532401524, - 866906920877543, - 2222282602952734, - 1289598729589882, - ]), - xy2d: FieldElement51([ - 1278207464902042, - 494742455008756, - 1262082121427081, - 1577236621659884, - 1888786707293291, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 353042527954210, - 1830056151907359, - 1111731275799225, - 2426760769524072, - 404312815582674, - ]), - y_minus_x: FieldElement51([ - 2064251142068628, - 1666421603389706, - 1419271365315441, - 468767774902855, - 191535130366583, - ]), - xy2d: FieldElement51([ - 1716987058588002, - 1859366439773457, - 1767194234188234, - 64476199777924, - 1117233614485261, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 3236091949205521, - 2386938060636506, - 2220652137473166, - 1722843421165029, - 2442282371698157, - ]), - y_minus_x: FieldElement51([ - 298845952651262, - 1166086588952562, - 1179896526238434, - 1347812759398693, - 1412945390096208, - ]), - xy2d: FieldElement51([ - 1143239552672925, - 906436640714209, - 2177000572812152, - 2075299936108548, - 325186347798433, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 2972824668060020, - 2936287674948563, - 3625238557779406, - 2193186935276994, - 1387043709851261, - ]), - y_minus_x: FieldElement51([ - 418098668140962, - 715065997721283, - 1471916138376055, - 2168570337288357, - 937812682637044, - ]), - xy2d: FieldElement51([ - 1043584187226485, - 2143395746619356, - 2209558562919611, - 482427979307092, - 847556718384018, - ]), - }, - ]), - LookupTable([ - AffineNielsPoint { - y_plus_x: FieldElement51([ - 1248731221520740, - 1465200936117687, - 2792603306395388, - 2304778448366139, - 2513234303861356, - ]), - y_minus_x: FieldElement51([ - 1057329623869501, - 620334067429122, - 461700859268034, - 2012481616501857, - 297268569108938, - ]), - xy2d: FieldElement51([ - 1055352180870759, - 1553151421852298, - 1510903185371259, - 1470458349428097, - 1226259419062731, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 3744788603986897, - 3042126439258578, - 3441906842094992, - 3641194565844440, - 3872208010289441, - ]), - y_minus_x: FieldElement51([ - 47000654413729, - 1004754424173864, - 1868044813557703, - 173236934059409, - 588771199737015, - ]), - xy2d: FieldElement51([ - 30498470091663, - 1082245510489825, - 576771653181956, - 806509986132686, - 1317634017056939, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 2672107869436803, - 3745154677001249, - 2417006535213335, - 4136645508605033, - 2065456951573058, - ]), - y_minus_x: FieldElement51([ - 1115636332012334, - 1854340990964155, - 83792697369514, - 1972177451994021, - 457455116057587, - ]), - xy2d: FieldElement51([ - 1698968457310898, - 1435137169051090, - 1083661677032510, - 938363267483709, - 340103887207182, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 1995325341336555, - 911500251774648, - 2415810569088940, - 855378419194761, - 3825401211214090, - ]), - y_minus_x: FieldElement51([ - 241719380661528, - 310028521317150, - 1215881323380194, - 1408214976493624, - 2141142156467363, - ]), - xy2d: FieldElement51([ - 1315157046163473, - 727368447885818, - 1363466668108618, - 1668921439990361, - 1398483384337907, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 2326829491984875, - 3267188020145720, - 1849729037055211, - 4191614430138232, - 2696204044080201, - ]), - y_minus_x: FieldElement51([ - 2053597130993710, - 2024431685856332, - 2233550957004860, - 2012407275509545, - 872546993104440, - ]), - xy2d: FieldElement51([ - 1217269667678610, - 599909351968693, - 1390077048548598, - 1471879360694802, - 739586172317596, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 3970118453066023, - 1560510726633957, - 3156262694845170, - 1418028351780051, - 2346204163137185, - ]), - y_minus_x: FieldElement51([ - 2132502667405250, - 214379346175414, - 1502748313768060, - 1960071701057800, - 1353971822643138, - ]), - xy2d: FieldElement51([ - 319394212043702, - 2127459436033571, - 717646691535162, - 663366796076914, - 318459064945314, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 2657789238608841, - 1960452633787082, - 2919148848086913, - 3744474074452359, - 1451061489880786, - ]), - y_minus_x: FieldElement51([ - 947085906234007, - 323284730494107, - 1485778563977200, - 728576821512394, - 901584347702286, - ]), - xy2d: FieldElement51([ - 1575783124125742, - 2126210792434375, - 1569430791264065, - 1402582372904727, - 1891780248341114, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 3090232019245924, - 4249503325136911, - 3270591693593114, - 1662001808174330, - 2330127946643001, - ]), - y_minus_x: FieldElement51([ - 739152638255629, - 2074935399403557, - 505483666745895, - 1611883356514088, - 628654635394878, - ]), - xy2d: FieldElement51([ - 1822054032121349, - 643057948186973, - 7306757352712, - 577249257962099, - 284735863382083, - ]), - }, - ]), - LookupTable([ - AffineNielsPoint { - y_plus_x: FieldElement51([ - 3618358370049178, - 1448606567552085, - 3730680834630016, - 2417602993041145, - 1115718458123497, - ]), - y_minus_x: FieldElement51([ - 204146226972102, - 1630511199034723, - 2215235214174763, - 174665910283542, - 956127674017216, - ]), - xy2d: FieldElement51([ - 1562934578796716, - 1070893489712745, - 11324610642270, - 958989751581897, - 2172552325473805, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 1770564423056008, - 2987323445349813, - 1326060113795288, - 1509650369341127, - 2317692235267932, - ]), - y_minus_x: FieldElement51([ - 623682558650637, - 1337866509471512, - 990313350206649, - 1314236615762469, - 1164772974270275, - ]), - xy2d: FieldElement51([ - 223256821462517, - 723690150104139, - 1000261663630601, - 933280913953265, - 254872671543046, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 1969087237026022, - 2876595539132372, - 1335555107635968, - 2069986355593023, - 3963899963027150, - ]), - y_minus_x: FieldElement51([ - 1236103475266979, - 1837885883267218, - 1026072585230455, - 1025865513954973, - 1801964901432134, - ]), - xy2d: FieldElement51([ - 1115241013365517, - 1712251818829143, - 2148864332502771, - 2096001471438138, - 2235017246626125, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 3551068012286861, - 2047148477845620, - 2165648650132450, - 1612539282026145, - 2765997725314138, - ]), - y_minus_x: FieldElement51([ - 118352772338543, - 1067608711804704, - 1434796676193498, - 1683240170548391, - 230866769907437, - ]), - xy2d: FieldElement51([ - 1850689576796636, - 1601590730430274, - 1139674615958142, - 1954384401440257, - 76039205311, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 1723387471374172, - 3249101280723658, - 2785727448808904, - 2272728458379212, - 1756575222802512, - ]), - y_minus_x: FieldElement51([ - 2146711623855116, - 503278928021499, - 625853062251406, - 1109121378393107, - 1033853809911861, - ]), - xy2d: FieldElement51([ - 571005965509422, - 2005213373292546, - 1016697270349626, - 56607856974274, - 914438579435146, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 1346698876211176, - 2076651707527589, - 3336561384795453, - 2517134292513653, - 1068954492309670, - ]), - y_minus_x: FieldElement51([ - 1769967932677654, - 1695893319756416, - 1151863389675920, - 1781042784397689, - 400287774418285, - ]), - xy2d: FieldElement51([ - 1851867764003121, - 403841933237558, - 820549523771987, - 761292590207581, - 1743735048551143, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 410915148140008, - 2107072311871739, - 3256167275561751, - 2351484709082008, - 1180818713503223, - ]), - y_minus_x: FieldElement51([ - 285945406881439, - 648174397347453, - 1098403762631981, - 1366547441102991, - 1505876883139217, - ]), - xy2d: FieldElement51([ - 672095903120153, - 1675918957959872, - 636236529315028, - 1569297300327696, - 2164144194785875, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 1902708175321798, - 3287143344600686, - 1178560808893262, - 2552895497743394, - 1280977479761117, - ]), - y_minus_x: FieldElement51([ - 1615357281742403, - 404257611616381, - 2160201349780978, - 1160947379188955, - 1578038619549541, - ]), - xy2d: FieldElement51([ - 2013087639791217, - 822734930507457, - 1785668418619014, - 1668650702946164, - 389450875221715, - ]), - }, - ]), - LookupTable([ - AffineNielsPoint { - y_plus_x: FieldElement51([ - 2705718263383616, - 2358206633614248, - 2072540975937134, - 308588860670238, - 1304394580755385, - ]), - y_minus_x: FieldElement51([ - 1295082798350326, - 2091844511495996, - 1851348972587817, - 3375039684596, - 789440738712837, - ]), - xy2d: FieldElement51([ - 2083069137186154, - 848523102004566, - 993982213589257, - 1405313299916317, - 1532824818698468, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 3747761112537659, - 1397203457344778, - 4026750030752190, - 2391102557240943, - 2318403398028034, - ]), - y_minus_x: FieldElement51([ - 1782411379088302, - 1096724939964781, - 27593390721418, - 542241850291353, - 1540337798439873, - ]), - xy2d: FieldElement51([ - 693543956581437, - 171507720360750, - 1557908942697227, - 1074697073443438, - 1104093109037196, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 345288228393400, - 3351443383432420, - 2386681722088990, - 1740551994106739, - 2500011992985018, - ]), - y_minus_x: FieldElement51([ - 231429562203065, - 1526290236421172, - 2021375064026423, - 1520954495658041, - 806337791525116, - ]), - xy2d: FieldElement51([ - 1079623667189886, - 872403650198613, - 766894200588288, - 2163700860774109, - 2023464507911816, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 854645372543796, - 1936406001954827, - 2403260476226501, - 3077125552956802, - 1554306377287555, - ]), - y_minus_x: FieldElement51([ - 1497138821904622, - 1044820250515590, - 1742593886423484, - 1237204112746837, - 849047450816987, - ]), - xy2d: FieldElement51([ - 667962773375330, - 1897271816877105, - 1399712621683474, - 1143302161683099, - 2081798441209593, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 2378947665252234, - 1936114012888109, - 1704424366552046, - 3108474694401560, - 2968403435020606, - ]), - y_minus_x: FieldElement51([ - 1072409664800960, - 2146937497077528, - 1508780108920651, - 935767602384853, - 1112800433544068, - ]), - xy2d: FieldElement51([ - 333549023751292, - 280219272863308, - 2104176666454852, - 1036466864875785, - 536135186520207, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 2625466093568366, - 2398257055215356, - 2555916080813104, - 2667888562832962, - 3510376944868638, - ]), - y_minus_x: FieldElement51([ - 1186115062588401, - 2251609796968486, - 1098944457878953, - 1153112761201374, - 1791625503417267, - ]), - xy2d: FieldElement51([ - 1870078460219737, - 2129630962183380, - 852283639691142, - 292865602592851, - 401904317342226, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 1361070124828016, - 815664541425524, - 3278598711049919, - 1951790935390646, - 2807674705520038, - ]), - y_minus_x: FieldElement51([ - 1546301003424277, - 459094500062839, - 1097668518375311, - 1780297770129643, - 720763293687608, - ]), - xy2d: FieldElement51([ - 1212405311403990, - 1536693382542438, - 61028431067459, - 1863929423417129, - 1223219538638038, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 1294303766540260, - 3435357279640341, - 3134071170918340, - 2315654383110622, - 2213283684565086, - ]), - y_minus_x: FieldElement51([ - 339050984211414, - 601386726509773, - 413735232134068, - 966191255137228, - 1839475899458159, - ]), - xy2d: FieldElement51([ - 235605972169408, - 2174055643032978, - 1538335001838863, - 1281866796917192, - 1815940222628465, - ]), - }, - ]), - LookupTable([ - AffineNielsPoint { - y_plus_x: FieldElement51([ - 1632352921721536, - 1833328609514701, - 2092779091951987, - 4175756015558474, - 2210068022482918, - ]), - y_minus_x: FieldElement51([ - 35271216625062, - 1712350667021807, - 983664255668860, - 98571260373038, - 1232645608559836, - ]), - xy2d: FieldElement51([ - 1998172393429622, - 1798947921427073, - 784387737563581, - 1589352214827263, - 1589861734168180, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 1733739258725305, - 2283515530744786, - 2453769758904107, - 3243892858242237, - 1194308773174555, - ]), - y_minus_x: FieldElement51([ - 846415389605137, - 746163495539180, - 829658752826080, - 592067705956946, - 957242537821393, - ]), - xy2d: FieldElement51([ - 1758148849754419, - 619249044817679, - 168089007997045, - 1371497636330523, - 1867101418880350, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 2578433797894864, - 2513559319756263, - 1700682323676192, - 1577907266349064, - 3469447477068264, - ]), - y_minus_x: FieldElement51([ - 1714182387328607, - 1477856482074168, - 574895689942184, - 2159118410227270, - 1555532449716575, - ]), - xy2d: FieldElement51([ - 853828206885131, - 998498946036955, - 1835887550391235, - 207627336608048, - 258363815956050, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 2392941288336925, - 3488528558590503, - 2894901233585134, - 1646615130509172, - 1208239602291765, - ]), - y_minus_x: FieldElement51([ - 1501663228068911, - 1354879465566912, - 1444432675498247, - 897812463852601, - 855062598754348, - ]), - xy2d: FieldElement51([ - 714380763546606, - 1032824444965790, - 1774073483745338, - 1063840874947367, - 1738680636537158, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 1640635546696233, - 2884968766877360, - 2212651044092395, - 2282390772269100, - 2620315074574625, - ]), - y_minus_x: FieldElement51([ - 1171650314802029, - 1567085444565577, - 1453660792008405, - 757914533009261, - 1619511342778196, - ]), - xy2d: FieldElement51([ - 420958967093237, - 971103481109486, - 2169549185607107, - 1301191633558497, - 1661514101014240, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 3158923465503550, - 1332556122804145, - 4075855067109735, - 3619414031128206, - 1982558335973171, - ]), - y_minus_x: FieldElement51([ - 1121533090144639, - 1021251337022187, - 110469995947421, - 1511059774758394, - 2110035908131662, - ]), - xy2d: FieldElement51([ - 303213233384524, - 2061932261128138, - 352862124777736, - 40828818670255, - 249879468482660, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 856559257852200, - 2760317478634258, - 3629993581580163, - 3975258940632376, - 1962275756614520, - ]), - y_minus_x: FieldElement51([ - 1445691340537320, - 40614383122127, - 402104303144865, - 485134269878232, - 1659439323587426, - ]), - xy2d: FieldElement51([ - 20057458979482, - 1183363722525800, - 2140003847237215, - 2053873950687614, - 2112017736174909, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 2228654250927986, - 3735391177100515, - 1368661293910955, - 3328311098862539, - 526650682059607, - ]), - y_minus_x: FieldElement51([ - 709481497028540, - 531682216165724, - 316963769431931, - 1814315888453765, - 258560242424104, - ]), - xy2d: FieldElement51([ - 1053447823660455, - 1955135194248683, - 1010900954918985, - 1182614026976701, - 1240051576966610, - ]), - }, - ]), - LookupTable([ - AffineNielsPoint { - y_plus_x: FieldElement51([ - 1957943897155478, - 1788667368028035, - 2389492723714354, - 2252839333292309, - 3078204576998275, - ]), - y_minus_x: FieldElement51([ - 1848942433095597, - 1582009882530495, - 1849292741020143, - 1068498323302788, - 2001402229799484, - ]), - xy2d: FieldElement51([ - 1528282417624269, - 2142492439828191, - 2179662545816034, - 362568973150328, - 1591374675250271, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 2411826493119617, - 2484141002903963, - 2149181472355544, - 598041771119831, - 2435658815595421, - ]), - y_minus_x: FieldElement51([ - 2013278155187349, - 662660471354454, - 793981225706267, - 411706605985744, - 804490933124791, - ]), - xy2d: FieldElement51([ - 2051892037280204, - 488391251096321, - 2230187337030708, - 930221970662692, - 679002758255210, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 1530723630438670, - 875873929577927, - 2593359947955236, - 2701702933216000, - 1055551308214178, - ]), - y_minus_x: FieldElement51([ - 1461835919309432, - 1955256480136428, - 180866187813063, - 1551979252664528, - 557743861963950, - ]), - xy2d: FieldElement51([ - 359179641731115, - 1324915145732949, - 902828372691474, - 294254275669987, - 1887036027752957, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 4295071423139571, - 2038225437857463, - 1317528426475850, - 1398989128982787, - 2027639881006861, - ]), - y_minus_x: FieldElement51([ - 2072902725256516, - 312132452743412, - 309930885642209, - 996244312618453, - 1590501300352303, - ]), - xy2d: FieldElement51([ - 1397254305160710, - 695734355138021, - 2233992044438756, - 1776180593969996, - 1085588199351115, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 2692366865016258, - 2506694600041928, - 2745669038615469, - 1556322069683365, - 3819256354004466, - ]), - y_minus_x: FieldElement51([ - 1950722461391320, - 1907845598854797, - 1822757481635527, - 2121567704750244, - 73811931471221, - ]), - xy2d: FieldElement51([ - 387139307395758, - 2058036430315676, - 1220915649965325, - 1794832055328951, - 1230009312169328, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 1765973779329498, - 2911143873132225, - 2271621715291913, - 3553728154996461, - 3368065817761132, - ]), - y_minus_x: FieldElement51([ - 1127572801181483, - 1224743760571696, - 1276219889847274, - 1529738721702581, - 1589819666871853, - ]), - xy2d: FieldElement51([ - 2181229378964934, - 2190885205260020, - 1511536077659137, - 1246504208580490, - 668883326494241, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 2689666469258543, - 2920826224880015, - 2333696811665585, - 523874406393177, - 2496851874620484, - ]), - y_minus_x: FieldElement51([ - 1975438052228868, - 1071801519999806, - 594652299224319, - 1877697652668809, - 1489635366987285, - ]), - xy2d: FieldElement51([ - 958592545673770, - 233048016518599, - 851568750216589, - 567703851596087, - 1740300006094761, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 2014540178270324, - 192672779514432, - 2465676996326778, - 2194819933853410, - 1716422829364835, - ]), - y_minus_x: FieldElement51([ - 1540769606609725, - 2148289943846077, - 1597804156127445, - 1230603716683868, - 815423458809453, - ]), - xy2d: FieldElement51([ - 1738560251245018, - 1779576754536888, - 1783765347671392, - 1880170990446751, - 1088225159617541, - ]), - }, - ]), - LookupTable([ - AffineNielsPoint { - y_plus_x: FieldElement51([ - 2911103727614740, - 1956447718227572, - 1830568515922666, - 3092868863429656, - 1669607124206367, - ]), - y_minus_x: FieldElement51([ - 1143465490433355, - 1532194726196059, - 1093276745494697, - 481041706116088, - 2121405433561163, - ]), - xy2d: FieldElement51([ - 1686424298744462, - 1451806974487153, - 266296068846582, - 1834686947542675, - 1720762336132256, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 3141016840074207, - 3295090436969907, - 3107924901237156, - 1669272323124635, - 1603340330827879, - ]), - y_minus_x: FieldElement51([ - 1206396181488998, - 333158148435054, - 1402633492821422, - 1120091191722026, - 1945474114550509, - ]), - xy2d: FieldElement51([ - 766720088232571, - 1512222781191002, - 1189719893490790, - 2091302129467914, - 2141418006894941, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 2671463460991841, - 1998875112167986, - 3678399683938955, - 3406728169064757, - 2738338345823434, - ]), - y_minus_x: FieldElement51([ - 938160078005954, - 1421776319053174, - 1941643234741774, - 180002183320818, - 1414380336750546, - ]), - xy2d: FieldElement51([ - 398001940109652, - 1577721237663248, - 1012748649830402, - 1540516006905144, - 1011684812884559, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 1653276489969611, - 2257881638852872, - 1921777941170835, - 1604139841794531, - 3113010867325889, - ]), - y_minus_x: FieldElement51([ - 996661541407379, - 1455877387952927, - 744312806857277, - 139213896196746, - 1000282908547789, - ]), - xy2d: FieldElement51([ - 1450817495603008, - 1476865707053229, - 1030490562252053, - 620966950353376, - 1744760161539058, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 2811528223687828, - 2288856475326432, - 2038622963352005, - 1637244893271723, - 3278365165924196, - ]), - y_minus_x: FieldElement51([ - 962165956135846, - 1116599660248791, - 182090178006815, - 1455605467021751, - 196053588803284, - ]), - xy2d: FieldElement51([ - 796863823080135, - 1897365583584155, - 420466939481601, - 2165972651724672, - 932177357788289, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 877047233620613, - 1375632631944375, - 2895573425567369, - 2911822552533124, - 2271153746017078, - ]), - y_minus_x: FieldElement51([ - 2216943882299338, - 394841323190322, - 2222656898319671, - 558186553950529, - 1077236877025190, - ]), - xy2d: FieldElement51([ - 801118384953213, - 1914330175515892, - 574541023311511, - 1471123787903705, - 1526158900256288, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 3201417702772463, - 2207116611267330, - 3164719852826535, - 2752958352884036, - 2314162374456719, - ]), - y_minus_x: FieldElement51([ - 1474518386765335, - 1760793622169197, - 1157399790472736, - 1622864308058898, - 165428294422792, - ]), - xy2d: FieldElement51([ - 1961673048027128, - 102619413083113, - 1051982726768458, - 1603657989805485, - 1941613251499678, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 1401939116319247, - 2587106153588320, - 2323846009771033, - 862423201496005, - 3102318568216632, - ]), - y_minus_x: FieldElement51([ - 1234706593321979, - 1083343891215917, - 898273974314935, - 1640859118399498, - 157578398571149, - ]), - xy2d: FieldElement51([ - 1143483057726416, - 1992614991758919, - 674268662140796, - 1773370048077526, - 674318359920189, - ]), - }, - ]), - LookupTable([ - AffineNielsPoint { - y_plus_x: FieldElement51([ - 1835401379538542, - 173900035308392, - 818247630716732, - 4013900225838034, - 1021506399448290, - ]), - y_minus_x: FieldElement51([ - 1506632088156630, - 2127481795522179, - 513812919490255, - 140643715928370, - 442476620300318, - ]), - xy2d: FieldElement51([ - 2056683376856736, - 219094741662735, - 2193541883188309, - 1841182310235800, - 556477468664293, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 3566819241596075, - 1049075855992602, - 4318372866671791, - 2518704280870781, - 2040482348591519, - ]), - y_minus_x: FieldElement51([ - 94096246544434, - 922482381166992, - 24517828745563, - 2139430508542503, - 2097139044231004, - ]), - xy2d: FieldElement51([ - 537697207950515, - 1399352016347350, - 1563663552106345, - 2148749520888918, - 549922092988516, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 1747985413252415, - 680511052635695, - 1809559829982725, - 2846074064615302, - 2453472984431229, - ]), - y_minus_x: FieldElement51([ - 323583936109569, - 1973572998577657, - 1192219029966558, - 79354804385273, - 1374043025560347, - ]), - xy2d: FieldElement51([ - 213277331329947, - 416202017849623, - 1950535221091783, - 1313441578103244, - 2171386783823658, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 2440888617915079, - 993969372859109, - 3147669935222235, - 3799101348983503, - 1477373024911349, - ]), - y_minus_x: FieldElement51([ - 1620578418245010, - 541035331188469, - 2235785724453865, - 2154865809088198, - 1974627268751826, - ]), - xy2d: FieldElement51([ - 1346805451740245, - 1350981335690626, - 942744349501813, - 2155094562545502, - 1012483751693409, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 2107080134091762, - 1132567062788208, - 1824935377687210, - 769194804343737, - 1857941799971888, - ]), - y_minus_x: FieldElement51([ - 1074666112436467, - 249279386739593, - 1174337926625354, - 1559013532006480, - 1472287775519121, - ]), - xy2d: FieldElement51([ - 1872620123779532, - 1892932666768992, - 1921559078394978, - 1270573311796160, - 1438913646755037, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 3089190001333428, - 3264053113908846, - 989780015893986, - 1351393287739814, - 2580427560230798, - ]), - y_minus_x: FieldElement51([ - 1028328827183114, - 1711043289969857, - 1350832470374933, - 1923164689604327, - 1495656368846911, - ]), - xy2d: FieldElement51([ - 1900828492104143, - 430212361082163, - 687437570852799, - 832514536673512, - 1685641495940794, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 3094432661621646, - 605670026766215, - 290836444839585, - 2415010588577604, - 2213815011799644, - ]), - y_minus_x: FieldElement51([ - 1176336383453996, - 1725477294339771, - 12700622672454, - 678015708818208, - 162724078519879, - ]), - xy2d: FieldElement51([ - 1448049969043497, - 1789411762943521, - 385587766217753, - 90201620913498, - 832999441066823, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 2767886146978542, - 2240508292484615, - 3603469341851756, - 3475055379001735, - 3002035638112385, - ]), - y_minus_x: FieldElement51([ - 1263624896582495, - 1102602401673328, - 526302183714372, - 2152015839128799, - 1483839308490010, - ]), - xy2d: FieldElement51([ - 442991718646863, - 1599275157036458, - 1925389027579192, - 899514691371390, - 350263251085160, - ]), - }, - ]), - LookupTable([ - AffineNielsPoint { - y_plus_x: FieldElement51([ - 1689713572022124, - 2845654372939621, - 3229894858477217, - 1985127338729498, - 3927868934032873, - ]), - y_minus_x: FieldElement51([ - 1557207018622683, - 340631692799603, - 1477725909476187, - 614735951619419, - 2033237123746766, - ]), - xy2d: FieldElement51([ - 968764929340557, - 1225534776710944, - 662967304013036, - 1155521416178595, - 791142883466590, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 1487081286167458, - 3244839255500182, - 1792378982844639, - 2950452258685122, - 2153908693179753, - ]), - y_minus_x: FieldElement51([ - 1123181311102823, - 685575944875442, - 507605465509927, - 1412590462117473, - 568017325228626, - ]), - xy2d: FieldElement51([ - 560258797465417, - 2193971151466401, - 1824086900849026, - 579056363542056, - 1690063960036441, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 1918407319222397, - 2605567366745211, - 1930426334528098, - 1564816146005724, - 4113142195393344, - ]), - y_minus_x: FieldElement51([ - 2131325168777276, - 1176636658428908, - 1756922641512981, - 1390243617176012, - 1966325177038383, - ]), - xy2d: FieldElement51([ - 2063958120364491, - 2140267332393533, - 699896251574968, - 273268351312140, - 375580724713232, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 2024297515263178, - 2668759143407935, - 3330814048702549, - 2423412039258430, - 1031677520051052, - ]), - y_minus_x: FieldElement51([ - 2033900009388450, - 1744902869870788, - 2190580087917640, - 1949474984254121, - 231049754293748, - ]), - xy2d: FieldElement51([ - 343868674606581, - 550155864008088, - 1450580864229630, - 481603765195050, - 896972360018042, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 2151139328380127, - 2566545695770176, - 2311556639460451, - 1676664391494650, - 2048348075599360, - ]), - y_minus_x: FieldElement51([ - 1528930066340597, - 1605003907059576, - 1055061081337675, - 1458319101947665, - 1234195845213142, - ]), - xy2d: FieldElement51([ - 830430507734812, - 1780282976102377, - 1425386760709037, - 362399353095425, - 2168861579799910, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 3407562046415562, - 980662895504005, - 2053766700883521, - 2742766027762854, - 2762205690726604, - ]), - y_minus_x: FieldElement51([ - 1683750316716132, - 652278688286128, - 1221798761193539, - 1897360681476669, - 319658166027343, - ]), - xy2d: FieldElement51([ - 618808732869972, - 72755186759744, - 2060379135624181, - 1730731526741822, - 48862757828238, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 3714971784278753, - 3394840525452699, - 614590986558882, - 1409210575145591, - 1882816996436803, - ]), - y_minus_x: FieldElement51([ - 2230133264691131, - 563950955091024, - 2042915975426398, - 827314356293472, - 672028980152815, - ]), - xy2d: FieldElement51([ - 264204366029760, - 1654686424479449, - 2185050199932931, - 2207056159091748, - 506015669043634, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 1784446333136550, - 1973746527984364, - 334856327359575, - 3408569589569858, - 3275749938360725, - ]), - y_minus_x: FieldElement51([ - 2065270940578383, - 31477096270353, - 306421879113491, - 181958643936686, - 1907105536686083, - ]), - xy2d: FieldElement51([ - 1496516440779464, - 1748485652986458, - 872778352227340, - 818358834654919, - 97932669284220, - ]), - }, - ]), - LookupTable([ - AffineNielsPoint { - y_plus_x: FieldElement51([ - 2723435829455580, - 2924255216478824, - 1804995246884102, - 1842309243470804, - 3753662318666930, - ]), - y_minus_x: FieldElement51([ - 1013216974933691, - 538921919682598, - 1915776722521558, - 1742822441583877, - 1886550687916656, - ]), - xy2d: FieldElement51([ - 2094270000643336, - 303971879192276, - 40801275554748, - 649448917027930, - 1818544418535447, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 2241737709499146, - 549397817447461, - 838180519319392, - 1725686958520781, - 3957438894582995, - ]), - y_minus_x: FieldElement51([ - 1216074541925116, - 50120933933509, - 1565829004133810, - 721728156134580, - 349206064666188, - ]), - xy2d: FieldElement51([ - 948617110470858, - 346222547451945, - 1126511960599975, - 1759386906004538, - 493053284802266, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 1454933046815146, - 3126495827951610, - 1467170975468587, - 1432316382418897, - 2111710746366763, - ]), - y_minus_x: FieldElement51([ - 2105387117364450, - 1996463405126433, - 1303008614294500, - 851908115948209, - 1353742049788635, - ]), - xy2d: FieldElement51([ - 750300956351719, - 1487736556065813, - 15158817002104, - 1511998221598392, - 971739901354129, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 1874648163531674, - 2124487685930551, - 1810030029384882, - 918400043048335, - 2838148440985898, - ]), - y_minus_x: FieldElement51([ - 1235084464747900, - 1166111146432082, - 1745394857881591, - 1405516473883040, - 4463504151617, - ]), - xy2d: FieldElement51([ - 1663810156463827, - 327797390285791, - 1341846161759410, - 1964121122800605, - 1747470312055380, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 660005247548214, - 2071860029952887, - 3610548013635355, - 911703252219106, - 3266179736709079, - ]), - y_minus_x: FieldElement51([ - 2206641276178231, - 1690587809721504, - 1600173622825126, - 2156096097634421, - 1106822408548216, - ]), - xy2d: FieldElement51([ - 1344788193552206, - 1949552134239140, - 1735915881729557, - 675891104100469, - 1834220014427292, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 1920949492387945, - 2410685102072778, - 2322108077349280, - 2877838278583064, - 3719881539786256, - ]), - y_minus_x: FieldElement51([ - 622221042073383, - 1210146474039168, - 1742246422343683, - 1403839361379025, - 417189490895736, - ]), - xy2d: FieldElement51([ - 22727256592983, - 168471543384997, - 1324340989803650, - 1839310709638189, - 504999476432775, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 3565040332441556, - 1721896294296941, - 2304063388272514, - 2065069734239231, - 3056710287109878, - ]), - y_minus_x: FieldElement51([ - 1337466662091884, - 1287645354669772, - 2018019646776184, - 652181229374245, - 898011753211715, - ]), - xy2d: FieldElement51([ - 1969792547910734, - 779969968247557, - 2011350094423418, - 1823964252907487, - 1058949448296945, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 2459143550747250, - 1118176942430252, - 3010694408233412, - 806764629546265, - 1157700123092949, - ]), - y_minus_x: FieldElement51([ - 1273565321399022, - 1638509681964574, - 759235866488935, - 666015124346707, - 897983460943405, - ]), - xy2d: FieldElement51([ - 1717263794012298, - 1059601762860786, - 1837819172257618, - 1054130665797229, - 680893204263559, - ]), - }, - ]), - LookupTable([ - AffineNielsPoint { - y_plus_x: FieldElement51([ - 2237039662793603, - 2249022333361206, - 2058613546633703, - 2401253908530527, - 2215176649164581, - ]), - y_minus_x: FieldElement51([ - 79472182719605, - 1851130257050174, - 1825744808933107, - 821667333481068, - 781795293511946, - ]), - xy2d: FieldElement51([ - 755822026485370, - 152464789723500, - 1178207602290608, - 410307889503239, - 156581253571278, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 3669985309815545, - 2736319981413860, - 3898537095128197, - 3653287498355512, - 1349185550126960, - ]), - y_minus_x: FieldElement51([ - 1495380034400429, - 325049476417173, - 46346894893933, - 1553408840354856, - 828980101835683, - ]), - xy2d: FieldElement51([ - 1280337889310282, - 2070832742866672, - 1640940617225222, - 2098284908289951, - 450929509534434, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 2659503167684029, - 2378371955168899, - 2537839641198868, - 1999255076709337, - 2030511179441770, - ]), - y_minus_x: FieldElement51([ - 1254958221100483, - 1153235960999843, - 942907704968834, - 637105404087392, - 1149293270147267, - ]), - xy2d: FieldElement51([ - 894249020470196, - 400291701616810, - 406878712230981, - 1599128793487393, - 1145868722604026, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 3749755063888563, - 2361916158338507, - 1128535642171975, - 1900106496009660, - 2381592531146157, - ]), - y_minus_x: FieldElement51([ - 452487513298665, - 1352120549024569, - 1173495883910956, - 1999111705922009, - 367328130454226, - ]), - xy2d: FieldElement51([ - 1717539401269642, - 1475188995688487, - 891921989653942, - 836824441505699, - 1885988485608364, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 3493583935107776, - 2439136865632830, - 3370281625921440, - 2680547565621609, - 2282158712612572, - ]), - y_minus_x: FieldElement51([ - 2022432361201842, - 1088816090685051, - 1977843398539868, - 1854834215890724, - 564238862029357, - ]), - xy2d: FieldElement51([ - 938868489100585, - 1100285072929025, - 1017806255688848, - 1957262154788833, - 152787950560442, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 3119119231364171, - 2872271776627789, - 2477832016990963, - 2593801257642876, - 1761675818237335, - ]), - y_minus_x: FieldElement51([ - 1295072362439987, - 931227904689414, - 1355731432641687, - 922235735834035, - 892227229410209, - ]), - xy2d: FieldElement51([ - 1680989767906154, - 535362787031440, - 2136691276706570, - 1942228485381244, - 1267350086882274, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 2617818047455756, - 2684460443440843, - 2378209521329782, - 1973842949591661, - 2897427157127624, - ]), - y_minus_x: FieldElement51([ - 535509430575217, - 546885533737322, - 1524675609547799, - 2138095752851703, - 1260738089896827, - ]), - xy2d: FieldElement51([ - 1159906385590467, - 2198530004321610, - 714559485023225, - 81880727882151, - 1484020820037082, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 1377485731340769, - 2046328105512000, - 1802058637158797, - 2313945950453421, - 1356993908853900, - ]), - y_minus_x: FieldElement51([ - 2013612215646735, - 1830770575920375, - 536135310219832, - 609272325580394, - 270684344495013, - ]), - xy2d: FieldElement51([ - 1237542585982777, - 2228682050256790, - 1385281931622824, - 593183794882890, - 493654978552689, - ]), - }, - ]), - LookupTable([ - AffineNielsPoint { - y_plus_x: FieldElement51([ - 2299141301692989, - 1891414891220256, - 983894663308928, - 2427961581972066, - 3378060928864955, - ]), - y_minus_x: FieldElement51([ - 1694030170963455, - 502038567066200, - 1691160065225467, - 949628319562187, - 275110186693066, - ]), - xy2d: FieldElement51([ - 1124515748676336, - 1661673816593408, - 1499640319059718, - 1584929449166988, - 558148594103306, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 1784525599998356, - 1619698033617383, - 2097300287550715, - 2510065271789004, - 1905684794832757, - ]), - y_minus_x: FieldElement51([ - 1288941072872766, - 931787902039402, - 190731008859042, - 2006859954667190, - 1005931482221702, - ]), - xy2d: FieldElement51([ - 1465551264822703, - 152905080555927, - 680334307368453, - 173227184634745, - 666407097159852, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 2111017076203943, - 3630560299479595, - 1248583954016455, - 3604089008549670, - 1895180776543895, - ]), - y_minus_x: FieldElement51([ - 171348223915638, - 662766099800389, - 462338943760497, - 466917763340314, - 656911292869115, - ]), - xy2d: FieldElement51([ - 488623681976577, - 866497561541722, - 1708105560937768, - 1673781214218839, - 1506146329818807, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 2412225278142205, - 950394373239688, - 2682296937026182, - 711676555398831, - 320964687779005, - ]), - y_minus_x: FieldElement51([ - 988979367990485, - 1359729327576302, - 1301834257246029, - 294141160829308, - 29348272277475, - ]), - xy2d: FieldElement51([ - 1434382743317910, - 100082049942065, - 221102347892623, - 186982837860588, - 1305765053501834, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 2205916462268190, - 2751663643476068, - 961960554686615, - 2409862576442233, - 1841471168298304, - ]), - y_minus_x: FieldElement51([ - 1191737341426592, - 1847042034978363, - 1382213545049056, - 1039952395710448, - 788812858896859, - ]), - xy2d: FieldElement51([ - 1346965964571152, - 1291881610839830, - 2142916164336056, - 786821641205979, - 1571709146321039, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 787164375951248, - 2454669019058437, - 3608390234717387, - 1431233331032509, - 786341368775957, - ]), - y_minus_x: FieldElement51([ - 492448143532951, - 304105152670757, - 1761767168301056, - 233782684697790, - 1981295323106089, - ]), - xy2d: FieldElement51([ - 665807507761866, - 1343384868355425, - 895831046139653, - 439338948736892, - 1986828765695105, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 3007896024559801, - 1721699973539148, - 2510565115413133, - 1390588532210644, - 1212530909934781, - ]), - y_minus_x: FieldElement51([ - 852891097972275, - 1816988871354562, - 1543772755726524, - 1174710635522444, - 202129090724628, - ]), - xy2d: FieldElement51([ - 1205281565824323, - 22430498399418, - 992947814485516, - 1392458699738672, - 688441466734558, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 3302427242100220, - 1955849529137134, - 2171162376368357, - 2343545681983462, - 447733118757825, - ]), - y_minus_x: FieldElement51([ - 1287181461435438, - 622722465530711, - 880952150571872, - 741035693459198, - 311565274989772, - ]), - xy2d: FieldElement51([ - 1003649078149734, - 545233927396469, - 1849786171789880, - 1318943684880434, - 280345687170552, - ]), - }, - ]), - ]); - -/// Odd multiples of the basepoint `[B, 3B, 5B, 7B, 9B, 11B, 13B, 15B, ..., 127B]`. -pub(crate) const AFFINE_ODD_MULTIPLES_OF_BASEPOINT: NafLookupTable8 = - NafLookupTable8([ - AffineNielsPoint { - y_plus_x: FieldElement51([ - 3540182452943730, - 2497478415033846, - 2521227595762870, - 1462984067271729, - 2389212253076811, - ]), - y_minus_x: FieldElement51([ - 62697248952638, - 204681361388450, - 631292143396476, - 338455783676468, - 1213667448819585, - ]), - xy2d: FieldElement51([ - 301289933810280, - 1259582250014073, - 1422107436869536, - 796239922652654, - 1953934009299142, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 1601611775252272, - 1720807796594148, - 1132070835939856, - 3512254832574799, - 2147779492816910, - ]), - y_minus_x: FieldElement51([ - 316559037616741, - 2177824224946892, - 1459442586438991, - 1461528397712656, - 751590696113597, - ]), - xy2d: FieldElement51([ - 1850748884277385, - 1200145853858453, - 1068094770532492, - 672251375690438, - 1586055907191707, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 769950342298400, - 2384754244604994, - 3095885746880802, - 3225892188161580, - 2977876099231263, - ]), - y_minus_x: FieldElement51([ - 425251763115706, - 608463272472562, - 442562545713235, - 837766094556764, - 374555092627893, - ]), - xy2d: FieldElement51([ - 1086255230780037, - 274979815921559, - 1960002765731872, - 929474102396301, - 1190409889297339, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 2916800678241215, - 2065379846933858, - 2622030924071124, - 2602788184473875, - 1233371373142984, - ]), - y_minus_x: FieldElement51([ - 2019367628972465, - 676711900706637, - 110710997811333, - 1108646842542025, - 517791959672113, - ]), - xy2d: FieldElement51([ - 965130719900578, - 247011430587952, - 526356006571389, - 91986625355052, - 2157223321444601, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 1802695059464988, - 1664899123557221, - 2845359304426105, - 2160434469266658, - 3179370264440279, - ]), - y_minus_x: FieldElement51([ - 1725674970513508, - 1933645953859181, - 1542344539275782, - 1767788773573747, - 1297447965928905, - ]), - xy2d: FieldElement51([ - 1381809363726107, - 1430341051343062, - 2061843536018959, - 1551778050872521, - 2036394857967624, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 4222693909998302, - 2779866139518454, - 1619374932191226, - 2207306624415883, - 1169170329061080, - ]), - y_minus_x: FieldElement51([ - 2070390218572616, - 1458919061857835, - 624171843017421, - 1055332792707765, - 433987520732508, - ]), - xy2d: FieldElement51([ - 893653801273833, - 1168026499324677, - 1242553501121234, - 1306366254304474, - 1086752658510815, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 2465253816303469, - 3191571337672685, - 1159882208056013, - 2569188183312765, - 621213314200686, - ]), - y_minus_x: FieldElement51([ - 1971678598905747, - 338026507889165, - 762398079972271, - 655096486107477, - 42299032696322, - ]), - xy2d: FieldElement51([ - 177130678690680, - 1754759263300204, - 1864311296286618, - 1180675631479880, - 1292726903152791, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 1913163449625248, - 2712579013977241, - 2193883288642313, - 1008900146920800, - 1721983679009502, - ]), - y_minus_x: FieldElement51([ - 1070401523076875, - 1272492007800961, - 1910153608563310, - 2075579521696771, - 1191169788841221, - ]), - xy2d: FieldElement51([ - 692896803108118, - 500174642072499, - 2068223309439677, - 1162190621851337, - 1426986007309901, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 1819621230288238, - 2735700366193240, - 1755134670739586, - 3080648199451191, - 4172807995775876, - ]), - y_minus_x: FieldElement51([ - 992069868904071, - 799011518185730, - 1777586403832768, - 1134820506145684, - 1999461475558530, - ]), - xy2d: FieldElement51([ - 425204543703124, - 2040469794090382, - 1651690622153809, - 1500530168597569, - 1253908377065966, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 2105824306960939, - 1387520302709358, - 3633176580451016, - 2211816663841753, - 1629085891776489, - ]), - y_minus_x: FieldElement51([ - 1485201376284999, - 1022406647424656, - 504181009209019, - 962621520820995, - 590876713147230, - ]), - xy2d: FieldElement51([ - 265873406365287, - 1192742653492898, - 88553098803050, - 525037770869640, - 1266933811251234, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 3552316659826612, - 1254279525791875, - 1609927932077699, - 3578654071679972, - 3750681296069893, - ]), - y_minus_x: FieldElement51([ - 37186803519861, - 1404297334376301, - 578519728836650, - 1740727951192592, - 2095534282477028, - ]), - xy2d: FieldElement51([ - 833234263154399, - 2023862470013762, - 1854137933982069, - 853924318090959, - 1589812702805850, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 3679150557957763, - 1319179453661745, - 497496853611112, - 2665464286942351, - 1208137952365560, - ]), - y_minus_x: FieldElement51([ - 1654513078530905, - 907489875842908, - 126098711296368, - 1726320004173677, - 28269495058173, - ]), - xy2d: FieldElement51([ - 114436686957443, - 532739313025996, - 115428841215897, - 2191499400074366, - 370280402676434, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 1111146849833253, - 2016430049079759, - 1860522747477948, - 3537164738290194, - 4137142824844184, - ]), - y_minus_x: FieldElement51([ - 429069864577128, - 975327637149449, - 237881983565075, - 1654761232378630, - 2122527599091807, - ]), - xy2d: FieldElement51([ - 2093793463548278, - 754827233241879, - 1420389751719629, - 1829952782588138, - 2011865756773717, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 676293365438898, - 2850296017886344, - 1205350322490195, - 2763699392265669, - 2133931188538142, - ]), - y_minus_x: FieldElement51([ - 48340340349120, - 1299261101494832, - 1137329686775218, - 1534848106674340, - 1351662218216799, - ]), - xy2d: FieldElement51([ - 1904520614137939, - 1590301001714014, - 215781420985270, - 2043534301034629, - 1970888949300424, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 2365217962409710, - 2061307169694064, - 1887478590157603, - 2169639621284316, - 2373810867477200, - ]), - y_minus_x: FieldElement51([ - 1020052624656948, - 1260412094216707, - 366721640607121, - 585331442306596, - 345876457758061, - ]), - xy2d: FieldElement51([ - 975390299880933, - 1066555195234642, - 12651997758352, - 1184252205433068, - 1058378155074223, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 1431537716602643, - 2024827957433813, - 3746434518400495, - 1087794891033550, - 2156817571680455, - ]), - y_minus_x: FieldElement51([ - 929288033346881, - 255179964546973, - 711057989588035, - 208899572612840, - 185348357387383, - ]), - xy2d: FieldElement51([ - 823689746424808, - 47266130989546, - 209403309368097, - 1100966895202707, - 710792075292719, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 2311213117823762, - 3296668540922318, - 2004276520649823, - 1861500579441125, - 3148029033359833, - ]), - y_minus_x: FieldElement51([ - 1563693677475261, - 1843782073741194, - 1950700654453170, - 911540858113949, - 2085151496302359, - ]), - xy2d: FieldElement51([ - 1427880892005482, - 106216431121745, - 42608394782284, - 1217295886989793, - 1514235272796882, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 3544335535746750, - 2367994491347456, - 2567261456502612, - 1854058085060971, - 2263545563461076, - ]), - y_minus_x: FieldElement51([ - 787426011300053, - 2105981035769060, - 1130476291127206, - 1748659348100075, - 53470983013756, - ]), - xy2d: FieldElement51([ - 553548273865386, - 5927805718390, - 65184587381926, - 633576679686953, - 576048559439973, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 993787326657446, - 3868807161609258, - 1615796046728943, - 2514644292681953, - 2059021068660907, - ]), - y_minus_x: FieldElement51([ - 251010270518880, - 1681684095763484, - 1521949356387564, - 431593457045116, - 1855308922422910, - ]), - xy2d: FieldElement51([ - 618490909691959, - 1257497595618257, - 202952467594088, - 35577762721238, - 1494883566841973, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 1673474571932262, - 2409784519770613, - 2636095316260487, - 2761112584601925, - 3333713288149876, - ]), - y_minus_x: FieldElement51([ - 1600640202645197, - 1019569075331823, - 1041916487915822, - 1680448171313267, - 2126903137527901, - ]), - xy2d: FieldElement51([ - 894964745143659, - 106116880092678, - 1009869382959477, - 317866368542032, - 1986983122763912, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 1765281781276487, - 2863247187455184, - 2589075472439062, - 1386435905543054, - 2182338478845320, - ]), - y_minus_x: FieldElement51([ - 1144730936996693, - 2213315231278180, - 1489676672185125, - 665039429138074, - 1131283313040268, - ]), - xy2d: FieldElement51([ - 2004734176670602, - 1738311085075235, - 418866995976618, - 1050782508034394, - 577747313404652, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 2185209688340293, - 1309276076461009, - 2514740038571278, - 3994889904012999, - 3018098826231021, - ]), - y_minus_x: FieldElement51([ - 1405936970888515, - 1754621155316654, - 1211862168554999, - 1813045702919083, - 997853418197172, - ]), - xy2d: FieldElement51([ - 82037622045021, - 1646398333621944, - 613095452763466, - 1312329542583705, - 81014679202721, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 2389287991277873, - 403851022333257, - 1597473361477193, - 2953351602509212, - 2135174663049062, - ]), - y_minus_x: FieldElement51([ - 1826548187201150, - 302299893734126, - 1475477168615781, - 842617616347376, - 1438600873676130, - ]), - xy2d: FieldElement51([ - 663049852468609, - 1649295727846569, - 1048009692742781, - 628866177992421, - 1914360327429204, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 1795645928096646, - 306878154408959, - 2924901319092394, - 2801261341654799, - 1653782432983523, - ]), - y_minus_x: FieldElement51([ - 2077597317438627, - 212642017882064, - 674844477518888, - 875487498687554, - 2060550250171182, - ]), - xy2d: FieldElement51([ - 1420448018683809, - 1032663994771382, - 1341927003385267, - 1340360916546159, - 1988547473895228, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 1082660122598844, - 2545055705583789, - 3888919679589007, - 1670283344995811, - 3403239134794618, - ]), - y_minus_x: FieldElement51([ - 90430593339788, - 1838338032241275, - 571293238480915, - 1639938867416883, - 257378872001111, - ]), - xy2d: FieldElement51([ - 1528535658865034, - 1516636853043960, - 787000569996728, - 1464531394704506, - 1684822625133795, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 811329918113934, - 2783463529007378, - 1769095754634835, - 2970819621866866, - 881037178164325, - ]), - y_minus_x: FieldElement51([ - 1784566501964517, - 433890943689325, - 1186055625589419, - 1496077405487512, - 1731807117886548, - ]), - xy2d: FieldElement51([ - 424909811816304, - 1355993963741797, - 409606483251841, - 455665350637068, - 1617009023642808, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 2478728492077816, - 2780289048655501, - 2328687177473769, - 4107341333582032, - 1316147724308250, - ]), - y_minus_x: FieldElement51([ - 1617420574301156, - 1741273341070467, - 667135503486508, - 2100436564640123, - 1032223920000865, - ]), - xy2d: FieldElement51([ - 1753947659404033, - 247279202390193, - 1819288880178945, - 737334285670249, - 1037873664856104, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 1762568490530034, - 673742465299012, - 2054571050635888, - 2040165159255111, - 3040123733327257, - ]), - y_minus_x: FieldElement51([ - 1627187989987422, - 1686331580821752, - 1309895873498183, - 719718719104086, - 300063199808722, - ]), - xy2d: FieldElement51([ - 238176707016164, - 1440454788877048, - 203336037573144, - 1437789888677072, - 101522256664211, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 1895216760098480, - 1934324337975022, - 3677350688973167, - 2536415965456176, - 714678003308640, - ]), - y_minus_x: FieldElement51([ - 508185358728815, - 1691320535341855, - 2168887448239256, - 1035124393070661, - 1936603999698584, - ]), - xy2d: FieldElement51([ - 390562831571647, - 1390223890708972, - 1383183990676371, - 435998174196410, - 1882086414390730, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 3747620842612921, - 2081794785291195, - 3284594056262745, - 2090090346797895, - 2581692978935809, - ]), - y_minus_x: FieldElement51([ - 244144781251265, - 1290834426417077, - 1888701171101942, - 1233922456644870, - 241117402207491, - ]), - xy2d: FieldElement51([ - 1266169390045455, - 1148042013187970, - 878921907853942, - 1815738019658093, - 908920199341621, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 2521768507305118, - 953557056811112, - 2015863732865770, - 1358382511861315, - 2835421647899992, - ]), - y_minus_x: FieldElement51([ - 2239837206240498, - 330928973149665, - 422268062913642, - 1481280019493032, - 619879520439841, - ]), - xy2d: FieldElement51([ - 1360166735366017, - 1770556573948510, - 1395061284191031, - 1814003148068126, - 522781147076884, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 2611794802645686, - 707234844948070, - 1314059396506491, - 2919250341703934, - 2161831667832785, - ]), - y_minus_x: FieldElement51([ - 934831784182383, - 433734253968318, - 1660867106725771, - 1968393082772831, - 873946300968490, - ]), - xy2d: FieldElement51([ - 26306827827554, - 430884999378685, - 1504310424376419, - 1761358720837522, - 542195685418530, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 1762131062631725, - 3123952634417535, - 3619918390837537, - 2909990877347294, - 1411594230004385, - ]), - y_minus_x: FieldElement51([ - 538272372224622, - 1425714779586199, - 588313661410172, - 1497062084392578, - 1602174047128512, - ]), - xy2d: FieldElement51([ - 907490361939255, - 1963620338391363, - 626927432296975, - 1250748516081414, - 959901171882527, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 1335066153744413, - 2887804660779657, - 2653073855954038, - 2765226981667422, - 938831784476763, - ]), - y_minus_x: FieldElement51([ - 296699434737224, - 2047543711075683, - 2076451038937139, - 227783599906901, - 1602062110967627, - ]), - xy2d: FieldElement51([ - 1574834773194203, - 1384279952062839, - 393652417255803, - 2166968242848859, - 1552890441390820, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 1619646774410947, - 1576090644023562, - 3035228391320965, - 1735328519940543, - 2355324535937066, - ]), - y_minus_x: FieldElement51([ - 1024074573633446, - 957088456885874, - 1690425531356997, - 2102187380180052, - 1082544623222033, - ]), - xy2d: FieldElement51([ - 1871906170635853, - 1719383891167200, - 1584032250247862, - 823764804192117, - 2244048510084261, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 642147846489775, - 3334304977145699, - 305205716788147, - 2589176626729533, - 2224680511484174, - ]), - y_minus_x: FieldElement51([ - 1734162377166545, - 260713621840346, - 157174591942595, - 952544272517991, - 222818702471733, - ]), - xy2d: FieldElement51([ - 1213115494182947, - 286778704335711, - 2130189536016490, - 308349182281342, - 1217623948685491, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 3360052266973635, - 1843486583624091, - 1561693837124349, - 1084041964025479, - 1866270922024009, - ]), - y_minus_x: FieldElement51([ - 460705465481210, - 1968151453817859, - 497005926994844, - 625618055866751, - 2176893440866887, - ]), - xy2d: FieldElement51([ - 1655800250476757, - 2036588542300609, - 666447448675243, - 1615721995750683, - 1508669225186765, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 2245948203759141, - 1058306669699396, - 1452898014240582, - 3961024141962768, - 1633235287338608, - ]), - y_minus_x: FieldElement51([ - 986647273684279, - 1507266907811370, - 1260572633649005, - 2071672342077446, - 695976026010857, - ]), - xy2d: FieldElement51([ - 1312356620823495, - 1635278548098567, - 901946076841033, - 585120475533168, - 1240667113237384, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 2313723935779695, - 1506054666773895, - 996040223525031, - 636592914999692, - 1497801917020297, - ]), - y_minus_x: FieldElement51([ - 292042016419794, - 1158932298133044, - 2062611870323738, - 1946058478962569, - 1749165808126286, - ]), - xy2d: FieldElement51([ - 654683942212830, - 1526897351349087, - 2006818439922838, - 2194919327350361, - 1451960776874416, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 3015041017808905, - 2951823141773809, - 2584865668253675, - 2508192032998563, - 2582137700042019, - ]), - y_minus_x: FieldElement51([ - 1628123495344283, - 2072923641214546, - 1647225812023982, - 855655925244679, - 1758126430071140, - ]), - xy2d: FieldElement51([ - 1615895096489599, - 275295258643784, - 937665541219916, - 1313496726746346, - 1186468946422626, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 1603070202850694, - 2072127623773242, - 1692648737212158, - 2493373404187852, - 1248948672117105, - ]), - y_minus_x: FieldElement51([ - 11167836031898, - 596565174397990, - 2196351068723859, - 314744641791907, - 1102014997250781, - ]), - xy2d: FieldElement51([ - 1409047922401191, - 69960384467966, - 688103515547600, - 1309746102488044, - 150292892873778, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 1986083055103168, - 691715819340300, - 1361811659746933, - 3459052030333434, - 1063594696046061, - ]), - y_minus_x: FieldElement51([ - 1201987338414749, - 2198784582460616, - 1203335513981498, - 489243077045066, - 2205278143582433, - ]), - xy2d: FieldElement51([ - 2034744376624534, - 2077387101466387, - 148448542974969, - 1502697574577258, - 473186584705655, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 472016956315960, - 720786972252993, - 2840633661190043, - 3150798753357827, - 2816563335499153, - ]), - y_minus_x: FieldElement51([ - 253464247569755, - 168314237403057, - 511780806170295, - 1058862316549135, - 1646858476817137, - ]), - xy2d: FieldElement51([ - 595092995922219, - 1491311840717691, - 291581784452778, - 1569186646367854, - 1031385061400544, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 3483137021572755, - 1526955102024322, - 2778006642704458, - 457549634924205, - 1097420237736736, - ]), - y_minus_x: FieldElement51([ - 1246991699537710, - 81367319519439, - 530844036072196, - 163656863755855, - 1950742455979290, - ]), - xy2d: FieldElement51([ - 191532664076407, - 539378506082089, - 1021612562876554, - 1026603384732632, - 1773368780410653, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 4144620731387879, - 590179521333342, - 4034023318016108, - 2255745030335426, - 2699746851701250, - ]), - y_minus_x: FieldElement51([ - 2206599697359952, - 553895797384417, - 181689161933786, - 1153123447919104, - 778568064152659, - ]), - xy2d: FieldElement51([ - 1706307000059211, - 1885601289314487, - 889758608505788, - 550131729999853, - 1006862664714268, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 3210197754285058, - 2048500453422630, - 3403309827888207, - 927154428508963, - 4199813798872019, - ]), - y_minus_x: FieldElement51([ - 992058915374933, - 476120535358775, - 1973648780784340, - 2025282643598818, - 2182318983793230, - ]), - xy2d: FieldElement51([ - 1343440812005821, - 1316045839091795, - 1884951299078063, - 1765919609219175, - 2197567554627988, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 3129247779382818, - 4415026969054274, - 1900265885969643, - 1528796215447059, - 2172730393748688, - ]), - y_minus_x: FieldElement51([ - 1773355092297603, - 64654329538271, - 1332124041660957, - 748492100858001, - 895500006200535, - ]), - xy2d: FieldElement51([ - 2000840647851980, - 546565968824914, - 420633283457524, - 195470736374507, - 1958689297569520, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 743138980705446, - 3411117504637167, - 2591389959690621, - 2380042066577202, - 3022267940115114, - ]), - y_minus_x: FieldElement51([ - 165947002229363, - 115186103724967, - 1068573292121517, - 1842565776920938, - 1969395681111987, - ]), - xy2d: FieldElement51([ - 553322266190633, - 234265665613185, - 484544650202821, - 1238773526575826, - 2017991917953668, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 2581954631514051, - 1245093644265357, - 3537016673825374, - 1834216551713857, - 923978372152807, - ]), - y_minus_x: FieldElement51([ - 1855378315339552, - 890045579230758, - 1764718173975590, - 197904186055854, - 1718129022310327, - ]), - xy2d: FieldElement51([ - 1278162928734862, - 1894118254109862, - 987503995465517, - 177406744098996, - 781538103127693, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 1996603431230215, - 1191888797552937, - 1207440075928499, - 2765853449051137, - 2525314961343288, - ]), - y_minus_x: FieldElement51([ - 808903879370889, - 990820108751280, - 1084429472258867, - 1078562781312589, - 254514692695625, - ]), - xy2d: FieldElement51([ - 615855140068469, - 586046731175395, - 693470779212674, - 1964537100203868, - 1350330550265229, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 3344544372023708, - 720386671449874, - 2480841360702110, - 2036034126860286, - 2015744690201389, - ]), - y_minus_x: FieldElement51([ - 1337446193390478, - 1984110761311871, - 746489405020285, - 407347127604128, - 1740475330360596, - ]), - xy2d: FieldElement51([ - 140840424783613, - 1063284623568331, - 1136446106453878, - 372042229029799, - 442607248430694, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 2330781679120937, - 376801425148230, - 2032603686676107, - 1488926293635130, - 1317278311532959, - ]), - y_minus_x: FieldElement51([ - 1290116731380016, - 2166899563471713, - 831997001838078, - 870954980505220, - 2108537278055823, - ]), - xy2d: FieldElement51([ - 1912719171026343, - 846194720551034, - 2043988124740726, - 993234269653961, - 421229796383281, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 2651184584992902, - 2775702557638963, - 2539786009779572, - 2575974880015305, - 2122619079836732, - ]), - y_minus_x: FieldElement51([ - 1154054290132562, - 931753998725577, - 1647742001778052, - 865765466488226, - 1083816107290025, - ]), - xy2d: FieldElement51([ - 986341121095108, - 1522330369638573, - 1990880546211047, - 501525962272123, - 198539304862139, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 1496414019192687, - 3991034436173951, - 3380311659062196, - 2854747485359158, - 3346958036643152, - ]), - y_minus_x: FieldElement51([ - 805612068303425, - 1891790027761335, - 1587008567571549, - 722120737390201, - 378156757163816, - ]), - xy2d: FieldElement51([ - 1588994517921951, - 977362751042302, - 1329302387067714, - 2069348224564088, - 1586007159625211, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 2490539421551682, - 1985699850375015, - 2331762317128172, - 4145097393776678, - 2521049460190674, - ]), - y_minus_x: FieldElement51([ - 615817553313996, - 2245962768078178, - 482564324326173, - 2101336843140780, - 1240914880829407, - ]), - xy2d: FieldElement51([ - 1438242482238189, - 874267817785463, - 1620810389770625, - 866155221338671, - 1040426546798301, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 2403083624110300, - 2548561409802975, - 2492699136535911, - 2358289519456539, - 3203964320363148, - ]), - y_minus_x: FieldElement51([ - 1913986535403097, - 1977163223054199, - 1972905914623196, - 1650122133472502, - 1905849310819035, - ]), - xy2d: FieldElement51([ - 858174816360838, - 614595356564037, - 1099584959044836, - 636998087084906, - 1070393269058348, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 3666695924830668, - 3585640662737501, - 2372994528684236, - 2628565977288995, - 3482812783469694, - ]), - y_minus_x: FieldElement51([ - 1994161359147952, - 2198039369802658, - 62790022842537, - 1522306785848169, - 951223194802833, - ]), - xy2d: FieldElement51([ - 852296621440717, - 431889737774209, - 370755457746189, - 437604073958073, - 627857326892757, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 1794955764684156, - 2586904290013612, - 1322647643615887, - 856117964085888, - 2652432778663153, - ]), - y_minus_x: FieldElement51([ - 933592377399646, - 78031722952813, - 926049890685253, - 1471649501316246, - 33789909190376, - ]), - xy2d: FieldElement51([ - 1479319468832059, - 203906207621608, - 659828362330083, - 44358398435755, - 1273573524210803, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 1592342143350813, - 3227219208247713, - 2345240352078765, - 2577750109932929, - 2933512841197243, - ]), - y_minus_x: FieldElement51([ - 2184946892642995, - 1517382324576002, - 1557940277419806, - 2170635134813213, - 747314658627002, - ]), - xy2d: FieldElement51([ - 1823193620577742, - 1135817878516419, - 1731253819308581, - 1031652967267804, - 2123506616999453, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 1346190246005805, - 2052692552023851, - 1718128041785940, - 2491557332978474, - 3474370880388305, - ]), - y_minus_x: FieldElement51([ - 424776012994573, - 281050757243423, - 626466040846420, - 990194703866532, - 38571969885982, - ]), - xy2d: FieldElement51([ - 192408346595466, - 1054889725292349, - 584097975693004, - 1447909807397749, - 2134645004369136, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 3169895788615063, - 3503097743181446, - 601598510029975, - 1422812237223371, - 2121009661378329, - ]), - y_minus_x: FieldElement51([ - 1603348391996783, - 2066143816131699, - 1789627290363958, - 2145705961178118, - 1985578641438222, - ]), - xy2d: FieldElement51([ - 352633958653380, - 856927627345554, - 793925083122702, - 93551575767286, - 1222010153634215, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 1756866499986349, - 911731956999969, - 2707505543214075, - 4006920335263786, - 822501008147910, - ]), - y_minus_x: FieldElement51([ - 1094036422864347, - 1897208881572508, - 1503607738246960, - 1901060196071406, - 294068411105729, - ]), - xy2d: FieldElement51([ - 587776484399576, - 1116861711228807, - 343398777436088, - 936544065763093, - 1643746750211060, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 3477749685790410, - 267997399528836, - 2953780922004404, - 3252368924080907, - 3787792887348381, - ]), - y_minus_x: FieldElement51([ - 2042368155872443, - 41662387210459, - 1676313264498480, - 1333968523426810, - 1765708383352310, - ]), - xy2d: FieldElement51([ - 1453394896690938, - 1585795827439909, - 1469309456804303, - 1294645324464404, - 2042954198665899, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 1810069207599881, - 1358344669503239, - 1989371257548167, - 2316270051121225, - 3019675451276507, - ]), - y_minus_x: FieldElement51([ - 1866114438287676, - 1663420339568364, - 1437691317033088, - 538298302628038, - 1212711449614363, - ]), - xy2d: FieldElement51([ - 1769235035677897, - 1562012115317882, - 31277513664750, - 536198657928416, - 1976134212537183, - ]), - }, - ]); diff --git a/net/gurk-rs/files/vendor/curve25519-dalek-2.0.0/src/backend/serial/u64/field.rs b/net/gurk-rs/files/vendor/curve25519-dalek-2.0.0/src/backend/serial/u64/field.rs deleted file mode 100644 index 1cb7778..0000000 --- a/net/gurk-rs/files/vendor/curve25519-dalek-2.0.0/src/backend/serial/u64/field.rs +++ /dev/null @@ -1,563 +0,0 @@ -// -*- mode: rust; coding: utf-8; -*- -// -// This file is part of curve25519-dalek. -// Copyright (c) 2016-2019 Isis Lovecruft, Henry de Valence -// See LICENSE for licensing information. -// -// Authors: -// - Isis Agora Lovecruft -// - Henry de Valence - -//! Field arithmetic modulo \\(p = 2\^{255} - 19\\), using \\(64\\)-bit -//! limbs with \\(128\\)-bit products. - -use core::fmt::Debug; -use core::ops::Neg; -use core::ops::{Add, AddAssign}; -use core::ops::{Mul, MulAssign}; -use core::ops::{Sub, SubAssign}; - -use subtle::Choice; -use subtle::ConditionallySelectable; - -use zeroize::Zeroize; - -/// A `FieldElement51` represents an element of the field -/// \\( \mathbb Z / (2\^{255} - 19)\\). -/// -/// In the 64-bit implementation, a `FieldElement` is represented in -/// radix \\(2\^{51}\\) as five `u64`s; the coefficients are allowed to -/// grow up to \\(2\^{54}\\) between reductions modulo \\(p\\). -/// -/// # Note -/// -/// The `curve25519_dalek::field` module provides a type alias -/// `curve25519_dalek::field::FieldElement` to either `FieldElement51` -/// or `FieldElement2625`. -/// -/// The backend-specific type `FieldElement51` should not be used -/// outside of the `curve25519_dalek::field` module. -#[derive(Copy, Clone)] -pub struct FieldElement51(pub (crate) [u64; 5]); - -impl Debug for FieldElement51 { - fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { - write!(f, "FieldElement51({:?})", &self.0[..]) - } -} - -impl Zeroize for FieldElement51 { - fn zeroize(&mut self) { - self.0.zeroize(); - } -} - -impl<'b> AddAssign<&'b FieldElement51> for FieldElement51 { - fn add_assign(&mut self, _rhs: &'b FieldElement51) { - for i in 0..5 { - self.0[i] += _rhs.0[i]; - } - } -} - -impl<'a, 'b> Add<&'b FieldElement51> for &'a FieldElement51 { - type Output = FieldElement51; - fn add(self, _rhs: &'b FieldElement51) -> FieldElement51 { - let mut output = *self; - output += _rhs; - output - } -} - -impl<'b> SubAssign<&'b FieldElement51> for FieldElement51 { - fn sub_assign(&mut self, _rhs: &'b FieldElement51) { - let result = (self as &FieldElement51) - _rhs; - self.0 = result.0; - } -} - -impl<'a, 'b> Sub<&'b FieldElement51> for &'a FieldElement51 { - type Output = FieldElement51; - fn sub(self, _rhs: &'b FieldElement51) -> FieldElement51 { - // To avoid underflow, first add a multiple of p. - // Choose 16*p = p << 4 to be larger than 54-bit _rhs. - // - // If we could statically track the bitlengths of the limbs - // of every FieldElement51, we could choose a multiple of p - // just bigger than _rhs and avoid having to do a reduction. - // - // Since we don't yet have type-level integers to do this, we - // have to add an explicit reduction call here. - FieldElement51::reduce([ - (self.0[0] + 36028797018963664u64) - _rhs.0[0], - (self.0[1] + 36028797018963952u64) - _rhs.0[1], - (self.0[2] + 36028797018963952u64) - _rhs.0[2], - (self.0[3] + 36028797018963952u64) - _rhs.0[3], - (self.0[4] + 36028797018963952u64) - _rhs.0[4], - ]) - } -} - -impl<'b> MulAssign<&'b FieldElement51> for FieldElement51 { - fn mul_assign(&mut self, _rhs: &'b FieldElement51) { - let result = (self as &FieldElement51) * _rhs; - self.0 = result.0; - } -} - -impl<'a, 'b> Mul<&'b FieldElement51> for &'a FieldElement51 { - type Output = FieldElement51; - fn mul(self, _rhs: &'b FieldElement51) -> FieldElement51 { - /// Helper function to multiply two 64-bit integers with 128 - /// bits of output. - #[inline(always)] - fn m(x: u64, y: u64) -> u128 { (x as u128) * (y as u128) } - - // Alias self, _rhs for more readable formulas - let a: &[u64; 5] = &self.0; - let b: &[u64; 5] = &_rhs.0; - - // Precondition: assume input limbs a[i], b[i] are bounded as - // - // a[i], b[i] < 2^(51 + b) - // - // where b is a real parameter measuring the "bit excess" of the limbs. - - // 64-bit precomputations to avoid 128-bit multiplications. - // - // This fits into a u64 whenever 51 + b + lg(19) < 64. - // - // Since 51 + b + lg(19) < 51 + 4.25 + b - // = 55.25 + b, - // this fits if b < 8.75. - let b1_19 = b[1] * 19; - let b2_19 = b[2] * 19; - let b3_19 = b[3] * 19; - let b4_19 = b[4] * 19; - - // Multiply to get 128-bit coefficients of output - let c0: u128 = m(a[0],b[0]) + m(a[4],b1_19) + m(a[3],b2_19) + m(a[2],b3_19) + m(a[1],b4_19); - let mut c1: u128 = m(a[1],b[0]) + m(a[0],b[1]) + m(a[4],b2_19) + m(a[3],b3_19) + m(a[2],b4_19); - let mut c2: u128 = m(a[2],b[0]) + m(a[1],b[1]) + m(a[0],b[2]) + m(a[4],b3_19) + m(a[3],b4_19); - let mut c3: u128 = m(a[3],b[0]) + m(a[2],b[1]) + m(a[1],b[2]) + m(a[0],b[3]) + m(a[4],b4_19); - let mut c4: u128 = m(a[4],b[0]) + m(a[3],b[1]) + m(a[2],b[2]) + m(a[1],b[3]) + m(a[0],b[4]); - - // How big are the c[i]? We have - // - // c[i] < 2^(102 + 2*b) * (1+i + (4-i)*19) - // < 2^(102 + lg(1 + 4*19) + 2*b) - // < 2^(108.27 + 2*b) - // - // The carry (c[i] >> 51) fits into a u64 when - // 108.27 + 2*b - 51 < 64 - // 2*b < 6.73 - // b < 3.365. - // - // So we require b < 3 to ensure this fits. - debug_assert!(a[0] < (1 << 54)); debug_assert!(b[0] < (1 << 54)); - debug_assert!(a[1] < (1 << 54)); debug_assert!(b[1] < (1 << 54)); - debug_assert!(a[2] < (1 << 54)); debug_assert!(b[2] < (1 << 54)); - debug_assert!(a[3] < (1 << 54)); debug_assert!(b[3] < (1 << 54)); - debug_assert!(a[4] < (1 << 54)); debug_assert!(b[4] < (1 << 54)); - - // Casting to u64 and back tells the compiler that the carry is - // bounded by 2^64, so that the addition is a u128 + u64 rather - // than u128 + u128. - - const LOW_51_BIT_MASK: u64 = (1u64 << 51) - 1; - let mut out = [0u64; 5]; - - c1 += ((c0 >> 51) as u64) as u128; - out[0] = (c0 as u64) & LOW_51_BIT_MASK; - - c2 += ((c1 >> 51) as u64) as u128; - out[1] = (c1 as u64) & LOW_51_BIT_MASK; - - c3 += ((c2 >> 51) as u64) as u128; - out[2] = (c2 as u64) & LOW_51_BIT_MASK; - - c4 += ((c3 >> 51) as u64) as u128; - out[3] = (c3 as u64) & LOW_51_BIT_MASK; - - let carry: u64 = (c4 >> 51) as u64; - out[4] = (c4 as u64) & LOW_51_BIT_MASK; - - // To see that this does not overflow, we need out[0] + carry * 19 < 2^64. - // - // c4 < a0*b4 + a1*b3 + a2*b2 + a3*b1 + a4*b0 + (carry from c3) - // < 5*(2^(51 + b) * 2^(51 + b)) + (carry from c3) - // < 2^(102 + 2*b + lg(5)) + 2^64. - // - // When b < 3 we get - // - // c4 < 2^110.33 so that carry < 2^59.33 - // - // so that - // - // out[0] + carry * 19 < 2^51 + 19 * 2^59.33 < 2^63.58 - // - // and there is no overflow. - out[0] = out[0] + carry * 19; - - // Now out[1] < 2^51 + 2^(64 -51) = 2^51 + 2^13 < 2^(51 + epsilon). - out[1] += out[0] >> 51; - out[0] &= LOW_51_BIT_MASK; - - // Now out[i] < 2^(51 + epsilon) for all i. - FieldElement51(out) - } -} - -impl<'a> Neg for &'a FieldElement51 { - type Output = FieldElement51; - fn neg(self) -> FieldElement51 { - let mut output = *self; - output.negate(); - output - } -} - -impl ConditionallySelectable for FieldElement51 { - fn conditional_select( - a: &FieldElement51, - b: &FieldElement51, - choice: Choice, - ) -> FieldElement51 { - FieldElement51([ - u64::conditional_select(&a.0[0], &b.0[0], choice), - u64::conditional_select(&a.0[1], &b.0[1], choice), - u64::conditional_select(&a.0[2], &b.0[2], choice), - u64::conditional_select(&a.0[3], &b.0[3], choice), - u64::conditional_select(&a.0[4], &b.0[4], choice), - ]) - } - - fn conditional_swap(a: &mut FieldElement51, b: &mut FieldElement51, choice: Choice) { - u64::conditional_swap(&mut a.0[0], &mut b.0[0], choice); - u64::conditional_swap(&mut a.0[1], &mut b.0[1], choice); - u64::conditional_swap(&mut a.0[2], &mut b.0[2], choice); - u64::conditional_swap(&mut a.0[3], &mut b.0[3], choice); - u64::conditional_swap(&mut a.0[4], &mut b.0[4], choice); - } - - fn conditional_assign(&mut self, other: &FieldElement51, choice: Choice) { - self.0[0].conditional_assign(&other.0[0], choice); - self.0[1].conditional_assign(&other.0[1], choice); - self.0[2].conditional_assign(&other.0[2], choice); - self.0[3].conditional_assign(&other.0[3], choice); - self.0[4].conditional_assign(&other.0[4], choice); - } -} - -impl FieldElement51 { - /// Invert the sign of this field element - pub fn negate(&mut self) { - // See commentary in the Sub impl - let neg = FieldElement51::reduce([ - 36028797018963664u64 - self.0[0], - 36028797018963952u64 - self.0[1], - 36028797018963952u64 - self.0[2], - 36028797018963952u64 - self.0[3], - 36028797018963952u64 - self.0[4], - ]); - self.0 = neg.0; - } - - /// Construct zero. - pub fn zero() -> FieldElement51 { - FieldElement51([ 0, 0, 0, 0, 0 ]) - } - - /// Construct one. - pub fn one() -> FieldElement51 { - FieldElement51([ 1, 0, 0, 0, 0 ]) - } - - /// Construct -1. - pub fn minus_one() -> FieldElement51 { - FieldElement51([2251799813685228, 2251799813685247, 2251799813685247, 2251799813685247, 2251799813685247]) - } - - /// Given 64-bit input limbs, reduce to enforce the bound 2^(51 + epsilon). - #[inline(always)] - fn reduce(mut limbs: [u64; 5]) -> FieldElement51 { - const LOW_51_BIT_MASK: u64 = (1u64 << 51) - 1; - - // Since the input limbs are bounded by 2^64, the biggest - // carry-out is bounded by 2^13. - // - // The biggest carry-in is c4 * 19, resulting in - // - // 2^51 + 19*2^13 < 2^51.0000000001 - // - // Because we don't need to canonicalize, only to reduce the - // limb sizes, it's OK to do a "weak reduction", where we - // compute the carry-outs in parallel. - - let c0 = limbs[0] >> 51; - let c1 = limbs[1] >> 51; - let c2 = limbs[2] >> 51; - let c3 = limbs[3] >> 51; - let c4 = limbs[4] >> 51; - - limbs[0] &= LOW_51_BIT_MASK; - limbs[1] &= LOW_51_BIT_MASK; - limbs[2] &= LOW_51_BIT_MASK; - limbs[3] &= LOW_51_BIT_MASK; - limbs[4] &= LOW_51_BIT_MASK; - - limbs[0] += c4 * 19; - limbs[1] += c0; - limbs[2] += c1; - limbs[3] += c2; - limbs[4] += c3; - - FieldElement51(limbs) - } - - /// Load a `FieldElement51` from the low 255 bits of a 256-bit - /// input. - /// - /// # Warning - /// - /// This function does not check that the input used the canonical - /// representative. It masks the high bit, but it will happily - /// decode 2^255 - 18 to 1. Applications that require a canonical - /// encoding of every field element should decode, re-encode to - /// the canonical encoding, and check that the input was - /// canonical. - /// - pub fn from_bytes(bytes: &[u8; 32]) -> FieldElement51 { - let load8 = |input: &[u8]| -> u64 { - (input[0] as u64) - | ((input[1] as u64) << 8) - | ((input[2] as u64) << 16) - | ((input[3] as u64) << 24) - | ((input[4] as u64) << 32) - | ((input[5] as u64) << 40) - | ((input[6] as u64) << 48) - | ((input[7] as u64) << 56) - }; - - let low_51_bit_mask = (1u64 << 51) - 1; - FieldElement51( - // load bits [ 0, 64), no shift - [ load8(&bytes[ 0..]) & low_51_bit_mask - // load bits [ 48,112), shift to [ 51,112) - , (load8(&bytes[ 6..]) >> 3) & low_51_bit_mask - // load bits [ 96,160), shift to [102,160) - , (load8(&bytes[12..]) >> 6) & low_51_bit_mask - // load bits [152,216), shift to [153,216) - , (load8(&bytes[19..]) >> 1) & low_51_bit_mask - // load bits [192,256), shift to [204,112) - , (load8(&bytes[24..]) >> 12) & low_51_bit_mask - ]) - } - - /// Serialize this `FieldElement51` to a 32-byte array. The - /// encoding is canonical. - pub fn to_bytes(&self) -> [u8; 32] { - // Let h = limbs[0] + limbs[1]*2^51 + ... + limbs[4]*2^204. - // - // Write h = pq + r with 0 <= r < p. - // - // We want to compute r = h mod p. - // - // If h < 2*p = 2^256 - 38, - // then q = 0 or 1, - // - // with q = 0 when h < p - // and q = 1 when h >= p. - // - // Notice that h >= p <==> h + 19 >= p + 19 <==> h + 19 >= 2^255. - // Therefore q can be computed as the carry bit of h + 19. - - // First, reduce the limbs to ensure h < 2*p. - let mut limbs = FieldElement51::reduce(self.0).0; - - let mut q = (limbs[0] + 19) >> 51; - q = (limbs[1] + q) >> 51; - q = (limbs[2] + q) >> 51; - q = (limbs[3] + q) >> 51; - q = (limbs[4] + q) >> 51; - - // Now we can compute r as r = h - pq = r - (2^255-19)q = r + 19q - 2^255q - - limbs[0] += 19*q; - - // Now carry the result to compute r + 19q ... - let low_51_bit_mask = (1u64 << 51) - 1; - limbs[1] += limbs[0] >> 51; - limbs[0] = limbs[0] & low_51_bit_mask; - limbs[2] += limbs[1] >> 51; - limbs[1] = limbs[1] & low_51_bit_mask; - limbs[3] += limbs[2] >> 51; - limbs[2] = limbs[2] & low_51_bit_mask; - limbs[4] += limbs[3] >> 51; - limbs[3] = limbs[3] & low_51_bit_mask; - // ... but instead of carrying (limbs[4] >> 51) = 2^255q - // into another limb, discard it, subtracting the value - limbs[4] = limbs[4] & low_51_bit_mask; - - // Now arrange the bits of the limbs. - let mut s = [0u8;32]; - s[ 0] = limbs[0] as u8; - s[ 1] = (limbs[0] >> 8) as u8; - s[ 2] = (limbs[0] >> 16) as u8; - s[ 3] = (limbs[0] >> 24) as u8; - s[ 4] = (limbs[0] >> 32) as u8; - s[ 5] = (limbs[0] >> 40) as u8; - s[ 6] = ((limbs[0] >> 48) | (limbs[1] << 3)) as u8; - s[ 7] = (limbs[1] >> 5) as u8; - s[ 8] = (limbs[1] >> 13) as u8; - s[ 9] = (limbs[1] >> 21) as u8; - s[10] = (limbs[1] >> 29) as u8; - s[11] = (limbs[1] >> 37) as u8; - s[12] = ((limbs[1] >> 45) | (limbs[2] << 6)) as u8; - s[13] = (limbs[2] >> 2) as u8; - s[14] = (limbs[2] >> 10) as u8; - s[15] = (limbs[2] >> 18) as u8; - s[16] = (limbs[2] >> 26) as u8; - s[17] = (limbs[2] >> 34) as u8; - s[18] = (limbs[2] >> 42) as u8; - s[19] = ((limbs[2] >> 50) | (limbs[3] << 1)) as u8; - s[20] = (limbs[3] >> 7) as u8; - s[21] = (limbs[3] >> 15) as u8; - s[22] = (limbs[3] >> 23) as u8; - s[23] = (limbs[3] >> 31) as u8; - s[24] = (limbs[3] >> 39) as u8; - s[25] = ((limbs[3] >> 47) | (limbs[4] << 4)) as u8; - s[26] = (limbs[4] >> 4) as u8; - s[27] = (limbs[4] >> 12) as u8; - s[28] = (limbs[4] >> 20) as u8; - s[29] = (limbs[4] >> 28) as u8; - s[30] = (limbs[4] >> 36) as u8; - s[31] = (limbs[4] >> 44) as u8; - - // High bit should be zero. - debug_assert!((s[31] & 0b1000_0000u8) == 0u8); - - s - } - - /// Given `k > 0`, return `self^(2^k)`. - pub fn pow2k(&self, mut k: u32) -> FieldElement51 { - - debug_assert!( k > 0 ); - - /// Multiply two 64-bit integers with 128 bits of output. - #[inline(always)] - fn m(x: u64, y: u64) -> u128 { (x as u128) * (y as u128) } - - let mut a: [u64; 5] = self.0; - - loop { - // Precondition: assume input limbs a[i] are bounded as - // - // a[i] < 2^(51 + b) - // - // where b is a real parameter measuring the "bit excess" of the limbs. - - // Precomputation: 64-bit multiply by 19. - // - // This fits into a u64 whenever 51 + b + lg(19) < 64. - // - // Since 51 + b + lg(19) < 51 + 4.25 + b - // = 55.25 + b, - // this fits if b < 8.75. - let a3_19 = 19 * a[3]; - let a4_19 = 19 * a[4]; - - // Multiply to get 128-bit coefficients of output. - // - // The 128-bit multiplications by 2 turn into 1 slr + 1 slrd each, - // which doesn't seem any better or worse than doing them as precomputations - // on the 64-bit inputs. - let c0: u128 = m(a[0], a[0]) + 2*( m(a[1], a4_19) + m(a[2], a3_19) ); - let mut c1: u128 = m(a[3], a3_19) + 2*( m(a[0], a[1]) + m(a[2], a4_19) ); - let mut c2: u128 = m(a[1], a[1]) + 2*( m(a[0], a[2]) + m(a[4], a3_19) ); - let mut c3: u128 = m(a[4], a4_19) + 2*( m(a[0], a[3]) + m(a[1], a[2]) ); - let mut c4: u128 = m(a[2], a[2]) + 2*( m(a[0], a[4]) + m(a[1], a[3]) ); - - // Same bound as in multiply: - // c[i] < 2^(102 + 2*b) * (1+i + (4-i)*19) - // < 2^(102 + lg(1 + 4*19) + 2*b) - // < 2^(108.27 + 2*b) - // - // The carry (c[i] >> 51) fits into a u64 when - // 108.27 + 2*b - 51 < 64 - // 2*b < 6.73 - // b < 3.365. - // - // So we require b < 3 to ensure this fits. - debug_assert!(a[0] < (1 << 54)); - debug_assert!(a[1] < (1 << 54)); - debug_assert!(a[2] < (1 << 54)); - debug_assert!(a[3] < (1 << 54)); - debug_assert!(a[4] < (1 << 54)); - - const LOW_51_BIT_MASK: u64 = (1u64 << 51) - 1; - - // Casting to u64 and back tells the compiler that the carry is bounded by 2^64, so - // that the addition is a u128 + u64 rather than u128 + u128. - c1 += ((c0 >> 51) as u64) as u128; - a[0] = (c0 as u64) & LOW_51_BIT_MASK; - - c2 += ((c1 >> 51) as u64) as u128; - a[1] = (c1 as u64) & LOW_51_BIT_MASK; - - c3 += ((c2 >> 51) as u64) as u128; - a[2] = (c2 as u64) & LOW_51_BIT_MASK; - - c4 += ((c3 >> 51) as u64) as u128; - a[3] = (c3 as u64) & LOW_51_BIT_MASK; - - let carry: u64 = (c4 >> 51) as u64; - a[4] = (c4 as u64) & LOW_51_BIT_MASK; - - // To see that this does not overflow, we need a[0] + carry * 19 < 2^64. - // - // c4 < a2^2 + 2*a0*a4 + 2*a1*a3 + (carry from c3) - // < 2^(102 + 2*b + lg(5)) + 2^64. - // - // When b < 3 we get - // - // c4 < 2^110.33 so that carry < 2^59.33 - // - // so that - // - // a[0] + carry * 19 < 2^51 + 19 * 2^59.33 < 2^63.58 - // - // and there is no overflow. - a[0] = a[0] + carry * 19; - - // Now a[1] < 2^51 + 2^(64 -51) = 2^51 + 2^13 < 2^(51 + epsilon). - a[1] += a[0] >> 51; - a[0] &= LOW_51_BIT_MASK; - - // Now all a[i] < 2^(51 + epsilon) and a = self^(2^k). - - k = k - 1; - if k == 0 { - break; - } - } - - FieldElement51(a) - } - - /// Returns the square of this field element. - pub fn square(&self) -> FieldElement51 { - self.pow2k(1) - } - - /// Returns 2 times the square of this field element. - pub fn square2(&self) -> FieldElement51 { - let mut square = self.pow2k(1); - for i in 0..5 { - square.0[i] *= 2; - } - - square - } -} diff --git a/net/gurk-rs/files/vendor/curve25519-dalek-2.0.0/src/backend/serial/u64/mod.rs b/net/gurk-rs/files/vendor/curve25519-dalek-2.0.0/src/backend/serial/u64/mod.rs deleted file mode 100644 index d329a89..0000000 --- a/net/gurk-rs/files/vendor/curve25519-dalek-2.0.0/src/backend/serial/u64/mod.rs +++ /dev/null @@ -1,26 +0,0 @@ -// -*- mode: rust; -*- -// -// This file is part of curve25519-dalek. -// Copyright (c) 2016-2018 Isis Lovecruft, Henry de Valence -// See LICENSE for licensing information. -// -// Authors: -// - Isis Agora Lovecruft -// - Henry de Valence - -//! The `u64` backend uses `u64`s and a `(u64, u64) -> u128` multiplier. -//! -//! On x86_64, the idiom `(x as u128) * (y as u128)` lowers to `MUL` -//! instructions taking 64-bit inputs and producing 128-bit outputs. On -//! other platforms, this implementation is not recommended. -//! -//! On Haswell and newer, the BMI2 extension provides `MULX`, and on -//! Broadwell and newer, the ADX extension provides `ADCX` and `ADOX` -//! (allowing the CPU to compute two carry chains in parallel). These -//! will be used if available. - -pub mod field; - -pub mod scalar; - -pub mod constants; diff --git a/net/gurk-rs/files/vendor/curve25519-dalek-2.0.0/src/backend/serial/u64/scalar.rs b/net/gurk-rs/files/vendor/curve25519-dalek-2.0.0/src/backend/serial/u64/scalar.rs deleted file mode 100644 index 97069ad..0000000 --- a/net/gurk-rs/files/vendor/curve25519-dalek-2.0.0/src/backend/serial/u64/scalar.rs +++ /dev/null @@ -1,451 +0,0 @@ -//! Arithmetic mod \\(2\^{252} + 27742317777372353535851937790883648493\\) -//! with five \\(52\\)-bit unsigned limbs. -//! -//! \\(51\\)-bit limbs would cover the desired bit range (\\(253\\) -//! bits), but isn't large enough to reduce a \\(512\\)-bit number with -//! Montgomery multiplication, so \\(52\\) bits is used instead. To see -//! that this is safe for intermediate results, note that the largest -//! limb in a \\(5\times 5\\) product of \\(52\\)-bit limbs will be -//! -//! ```text -//! (0xfffffffffffff^2) * 5 = 0x4ffffffffffff60000000000005 (107 bits). -//! ``` - -use core::fmt::Debug; -use core::ops::{Index, IndexMut}; - -use zeroize::Zeroize; - -use constants; - -/// The `Scalar52` struct represents an element in -/// \\(\mathbb Z / \ell \mathbb Z\\) as 5 \\(52\\)-bit limbs. -#[derive(Copy,Clone)] -pub struct Scalar52(pub [u64; 5]); - -impl Debug for Scalar52 { - fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { - write!(f, "Scalar52: {:?}", &self.0[..]) - } -} - -impl Zeroize for Scalar52 { - fn zeroize(&mut self) { - self.0.zeroize(); - } -} - -impl Index for Scalar52 { - type Output = u64; - fn index(&self, _index: usize) -> &u64 { - &(self.0[_index]) - } -} - -impl IndexMut for Scalar52 { - fn index_mut(&mut self, _index: usize) -> &mut u64 { - &mut (self.0[_index]) - } -} - -/// u64 * u64 = u128 multiply helper -#[inline(always)] -fn m(x: u64, y: u64) -> u128 { - (x as u128) * (y as u128) -} - -impl Scalar52 { - /// Return the zero scalar - pub fn zero() -> Scalar52 { - Scalar52([0,0,0,0,0]) - } - - /// Unpack a 32 byte / 256 bit scalar into 5 52-bit limbs. - pub fn from_bytes(bytes: &[u8; 32]) -> Scalar52 { - let mut words = [0u64; 4]; - for i in 0..4 { - for j in 0..8 { - words[i] |= (bytes[(i * 8) + j] as u64) << (j * 8); - } - } - - let mask = (1u64 << 52) - 1; - let top_mask = (1u64 << 48) - 1; - let mut s = Scalar52::zero(); - - s[ 0] = words[0] & mask; - s[ 1] = ((words[0] >> 52) | (words[1] << 12)) & mask; - s[ 2] = ((words[1] >> 40) | (words[2] << 24)) & mask; - s[ 3] = ((words[2] >> 28) | (words[3] << 36)) & mask; - s[ 4] = (words[3] >> 16) & top_mask; - - s - } - - /// Reduce a 64 byte / 512 bit scalar mod l - pub fn from_bytes_wide(bytes: &[u8; 64]) -> Scalar52 { - let mut words = [0u64; 8]; - for i in 0..8 { - for j in 0..8 { - words[i] |= (bytes[(i * 8) + j] as u64) << (j * 8); - } - } - - let mask = (1u64 << 52) - 1; - let mut lo = Scalar52::zero(); - let mut hi = Scalar52::zero(); - - lo[0] = words[ 0] & mask; - lo[1] = ((words[ 0] >> 52) | (words[ 1] << 12)) & mask; - lo[2] = ((words[ 1] >> 40) | (words[ 2] << 24)) & mask; - lo[3] = ((words[ 2] >> 28) | (words[ 3] << 36)) & mask; - lo[4] = ((words[ 3] >> 16) | (words[ 4] << 48)) & mask; - hi[0] = (words[ 4] >> 4) & mask; - hi[1] = ((words[ 4] >> 56) | (words[ 5] << 8)) & mask; - hi[2] = ((words[ 5] >> 44) | (words[ 6] << 20)) & mask; - hi[3] = ((words[ 6] >> 32) | (words[ 7] << 32)) & mask; - hi[4] = words[ 7] >> 20 ; - - lo = Scalar52::montgomery_mul(&lo, &constants::R); // (lo * R) / R = lo - hi = Scalar52::montgomery_mul(&hi, &constants::RR); // (hi * R^2) / R = hi * R - - Scalar52::add(&hi, &lo) - } - - /// Pack the limbs of this `Scalar52` into 32 bytes - pub fn to_bytes(&self) -> [u8; 32] { - let mut s = [0u8; 32]; - - s[0] = (self.0[ 0] >> 0) as u8; - s[1] = (self.0[ 0] >> 8) as u8; - s[2] = (self.0[ 0] >> 16) as u8; - s[3] = (self.0[ 0] >> 24) as u8; - s[4] = (self.0[ 0] >> 32) as u8; - s[5] = (self.0[ 0] >> 40) as u8; - s[6] = ((self.0[ 0] >> 48) | (self.0[ 1] << 4)) as u8; - s[7] = (self.0[ 1] >> 4) as u8; - s[8] = (self.0[ 1] >> 12) as u8; - s[9] = (self.0[ 1] >> 20) as u8; - s[10] = (self.0[ 1] >> 28) as u8; - s[11] = (self.0[ 1] >> 36) as u8; - s[12] = (self.0[ 1] >> 44) as u8; - s[13] = (self.0[ 2] >> 0) as u8; - s[14] = (self.0[ 2] >> 8) as u8; - s[15] = (self.0[ 2] >> 16) as u8; - s[16] = (self.0[ 2] >> 24) as u8; - s[17] = (self.0[ 2] >> 32) as u8; - s[18] = (self.0[ 2] >> 40) as u8; - s[19] = ((self.0[ 2] >> 48) | (self.0[ 3] << 4)) as u8; - s[20] = (self.0[ 3] >> 4) as u8; - s[21] = (self.0[ 3] >> 12) as u8; - s[22] = (self.0[ 3] >> 20) as u8; - s[23] = (self.0[ 3] >> 28) as u8; - s[24] = (self.0[ 3] >> 36) as u8; - s[25] = (self.0[ 3] >> 44) as u8; - s[26] = (self.0[ 4] >> 0) as u8; - s[27] = (self.0[ 4] >> 8) as u8; - s[28] = (self.0[ 4] >> 16) as u8; - s[29] = (self.0[ 4] >> 24) as u8; - s[30] = (self.0[ 4] >> 32) as u8; - s[31] = (self.0[ 4] >> 40) as u8; - - s - } - - /// Compute `a + b` (mod l) - pub fn add(a: &Scalar52, b: &Scalar52) -> Scalar52 { - let mut sum = Scalar52::zero(); - let mask = (1u64 << 52) - 1; - - // a + b - let mut carry: u64 = 0; - for i in 0..5 { - carry = a[i] + b[i] + (carry >> 52); - sum[i] = carry & mask; - } - - // subtract l if the sum is >= l - Scalar52::sub(&sum, &constants::L) - } - - /// Compute `a - b` (mod l) - pub fn sub(a: &Scalar52, b: &Scalar52) -> Scalar52 { - let mut difference = Scalar52::zero(); - let mask = (1u64 << 52) - 1; - - // a - b - let mut borrow: u64 = 0; - for i in 0..5 { - borrow = a[i].wrapping_sub(b[i] + (borrow >> 63)); - difference[i] = borrow & mask; - } - - // conditionally add l if the difference is negative - let underflow_mask = ((borrow >> 63) ^ 1).wrapping_sub(1); - let mut carry: u64 = 0; - for i in 0..5 { - carry = (carry >> 52) + difference[i] + (constants::L[i] & underflow_mask); - difference[i] = carry & mask; - } - - difference - } - - /// Compute `a * b` - #[inline(always)] - pub (crate) fn mul_internal(a: &Scalar52, b: &Scalar52) -> [u128; 9] { - let mut z = [0u128; 9]; - - z[0] = m(a[0],b[0]); - z[1] = m(a[0],b[1]) + m(a[1],b[0]); - z[2] = m(a[0],b[2]) + m(a[1],b[1]) + m(a[2],b[0]); - z[3] = m(a[0],b[3]) + m(a[1],b[2]) + m(a[2],b[1]) + m(a[3],b[0]); - z[4] = m(a[0],b[4]) + m(a[1],b[3]) + m(a[2],b[2]) + m(a[3],b[1]) + m(a[4],b[0]); - z[5] = m(a[1],b[4]) + m(a[2],b[3]) + m(a[3],b[2]) + m(a[4],b[1]); - z[6] = m(a[2],b[4]) + m(a[3],b[3]) + m(a[4],b[2]); - z[7] = m(a[3],b[4]) + m(a[4],b[3]); - z[8] = m(a[4],b[4]); - - z - } - - /// Compute `a^2` - #[inline(always)] - fn square_internal(a: &Scalar52) -> [u128; 9] { - let aa = [ - a[0]*2, - a[1]*2, - a[2]*2, - a[3]*2, - ]; - - [ - m( a[0],a[0]), - m(aa[0],a[1]), - m(aa[0],a[2]) + m( a[1],a[1]), - m(aa[0],a[3]) + m(aa[1],a[2]), - m(aa[0],a[4]) + m(aa[1],a[3]) + m( a[2],a[2]), - m(aa[1],a[4]) + m(aa[2],a[3]), - m(aa[2],a[4]) + m( a[3],a[3]), - m(aa[3],a[4]), - m(a[4],a[4]) - ] - } - - /// Compute `limbs/R` (mod l), where R is the Montgomery modulus 2^260 - #[inline(always)] - pub (crate) fn montgomery_reduce(limbs: &[u128; 9]) -> Scalar52 { - - #[inline(always)] - fn part1(sum: u128) -> (u128, u64) { - let p = (sum as u64).wrapping_mul(constants::LFACTOR) & ((1u64 << 52) - 1); - ((sum + m(p,constants::L[0])) >> 52, p) - } - - #[inline(always)] - fn part2(sum: u128) -> (u128, u64) { - let w = (sum as u64) & ((1u64 << 52) - 1); - (sum >> 52, w) - } - - // note: l[3] is zero, so its multiples can be skipped - let l = &constants::L; - - // the first half computes the Montgomery adjustment factor n, and begins adding n*l to make limbs divisible by R - let (carry, n0) = part1( limbs[0]); - let (carry, n1) = part1(carry + limbs[1] + m(n0,l[1])); - let (carry, n2) = part1(carry + limbs[2] + m(n0,l[2]) + m(n1,l[1])); - let (carry, n3) = part1(carry + limbs[3] + m(n1,l[2]) + m(n2,l[1])); - let (carry, n4) = part1(carry + limbs[4] + m(n0,l[4]) + m(n2,l[2]) + m(n3,l[1])); - - // limbs is divisible by R now, so we can divide by R by simply storing the upper half as the result - let (carry, r0) = part2(carry + limbs[5] + m(n1,l[4]) + m(n3,l[2]) + m(n4,l[1])); - let (carry, r1) = part2(carry + limbs[6] + m(n2,l[4]) + m(n4,l[2])); - let (carry, r2) = part2(carry + limbs[7] + m(n3,l[4]) ); - let (carry, r3) = part2(carry + limbs[8] + m(n4,l[4])); - let r4 = carry as u64; - - // result may be >= l, so attempt to subtract l - Scalar52::sub(&Scalar52([r0,r1,r2,r3,r4]), l) - } - - /// Compute `a * b` (mod l) - #[inline(never)] - pub fn mul(a: &Scalar52, b: &Scalar52) -> Scalar52 { - let ab = Scalar52::montgomery_reduce(&Scalar52::mul_internal(a, b)); - Scalar52::montgomery_reduce(&Scalar52::mul_internal(&ab, &constants::RR)) - } - - /// Compute `a^2` (mod l) - #[inline(never)] - #[allow(dead_code)] // XXX we don't expose square() via the Scalar API - pub fn square(&self) -> Scalar52 { - let aa = Scalar52::montgomery_reduce(&Scalar52::square_internal(self)); - Scalar52::montgomery_reduce(&Scalar52::mul_internal(&aa, &constants::RR)) - } - - /// Compute `(a * b) / R` (mod l), where R is the Montgomery modulus 2^260 - #[inline(never)] - pub fn montgomery_mul(a: &Scalar52, b: &Scalar52) -> Scalar52 { - Scalar52::montgomery_reduce(&Scalar52::mul_internal(a, b)) - } - - /// Compute `(a^2) / R` (mod l) in Montgomery form, where R is the Montgomery modulus 2^260 - #[inline(never)] - pub fn montgomery_square(&self) -> Scalar52 { - Scalar52::montgomery_reduce(&Scalar52::square_internal(self)) - } - - /// Puts a Scalar52 in to Montgomery form, i.e. computes `a*R (mod l)` - #[inline(never)] - pub fn to_montgomery(&self) -> Scalar52 { - Scalar52::montgomery_mul(self, &constants::RR) - } - - /// Takes a Scalar52 out of Montgomery form, i.e. computes `a/R (mod l)` - #[inline(never)] - pub fn from_montgomery(&self) -> Scalar52 { - let mut limbs = [0u128; 9]; - for i in 0..5 { - limbs[i] = self[i] as u128; - } - Scalar52::montgomery_reduce(&limbs) - } -} - - -#[cfg(test)] -mod test { - use super::*; - - /// Note: x is 2^253-1 which is slightly larger than the largest scalar produced by - /// this implementation (l-1), and should show there are no overflows for valid scalars - /// - /// x = 14474011154664524427946373126085988481658748083205070504932198000989141204991 - /// x = 7237005577332262213973186563042994240801631723825162898930247062703686954002 mod l - /// x = 3057150787695215392275360544382990118917283750546154083604586903220563173085*R mod l in Montgomery form - pub static X: Scalar52 = Scalar52( - [0x000fffffffffffff, 0x000fffffffffffff, 0x000fffffffffffff, 0x000fffffffffffff, - 0x00001fffffffffff]); - - /// x^2 = 3078544782642840487852506753550082162405942681916160040940637093560259278169 mod l - pub static XX: Scalar52 = Scalar52( - [0x0001668020217559, 0x000531640ffd0ec0, 0x00085fd6f9f38a31, 0x000c268f73bb1cf4, - 0x000006ce65046df0]); - - /// x^2 = 4413052134910308800482070043710297189082115023966588301924965890668401540959*R mod l in Montgomery form - pub static XX_MONT: Scalar52 = Scalar52( - [0x000c754eea569a5c, 0x00063b6ed36cb215, 0x0008ffa36bf25886, 0x000e9183614e7543, - 0x0000061db6c6f26f]); - - /// y = 6145104759870991071742105800796537629880401874866217824609283457819451087098 - pub static Y: Scalar52 = Scalar52( - [0x000b75071e1458fa, 0x000bf9d75e1ecdac, 0x000433d2baf0672b, 0x0005fffcc11fad13, - 0x00000d96018bb825]); - - /// x*y = 36752150652102274958925982391442301741 mod l - pub static XY: Scalar52 = Scalar52( - [0x000ee6d76ba7632d, 0x000ed50d71d84e02, 0x00000000001ba634, 0x0000000000000000, - 0x0000000000000000]); - - /// x*y = 658448296334113745583381664921721413881518248721417041768778176391714104386*R mod l in Montgomery form - pub static XY_MONT: Scalar52 = Scalar52( - [0x0006d52bf200cfd5, 0x00033fb1d7021570, 0x000f201bc07139d8, 0x0001267e3e49169e, - 0x000007b839c00268]); - - /// a = 2351415481556538453565687241199399922945659411799870114962672658845158063753 - pub static A: Scalar52 = Scalar52( - [0x0005236c07b3be89, 0x0001bc3d2a67c0c4, 0x000a4aa782aae3ee, 0x0006b3f6e4fec4c4, - 0x00000532da9fab8c]); - - /// b = 4885590095775723760407499321843594317911456947580037491039278279440296187236 - pub static B: Scalar52 = Scalar52( - [0x000d3fae55421564, 0x000c2df24f65a4bc, 0x0005b5587d69fb0b, 0x00094c091b013b3b, - 0x00000acd25605473]); - - /// a+b = 0 - /// a-b = 4702830963113076907131374482398799845891318823599740229925345317690316127506 - pub static AB: Scalar52 = Scalar52( - [0x000a46d80f677d12, 0x0003787a54cf8188, 0x0004954f0555c7dc, 0x000d67edc9fd8989, - 0x00000a65b53f5718]); - - // c = (2^512 - 1) % l = 1627715501170711445284395025044413883736156588369414752970002579683115011840 - pub static C: Scalar52 = Scalar52( - [0x000611e3449c0f00, 0x000a768859347a40, 0x0007f5be65d00e1b, 0x0009a3dceec73d21, - 0x00000399411b7c30]); - - #[test] - fn mul_max() { - let res = Scalar52::mul(&X, &X); - for i in 0..5 { - assert!(res[i] == XX[i]); - } - } - - #[test] - fn square_max() { - let res = X.square(); - for i in 0..5 { - assert!(res[i] == XX[i]); - } - } - - #[test] - fn montgomery_mul_max() { - let res = Scalar52::montgomery_mul(&X, &X); - for i in 0..5 { - assert!(res[i] == XX_MONT[i]); - } - } - - #[test] - fn montgomery_square_max() { - let res = X.montgomery_square(); - for i in 0..5 { - assert!(res[i] == XX_MONT[i]); - } - } - - #[test] - fn mul() { - let res = Scalar52::mul(&X, &Y); - for i in 0..5 { - assert!(res[i] == XY[i]); - } - } - - #[test] - fn montgomery_mul() { - let res = Scalar52::montgomery_mul(&X, &Y); - for i in 0..5 { - assert!(res[i] == XY_MONT[i]); - } - } - - #[test] - fn add() { - let res = Scalar52::add(&A, &B); - let zero = Scalar52::zero(); - for i in 0..5 { - assert!(res[i] == zero[i]); - } - } - - #[test] - fn sub() { - let res = Scalar52::sub(&A, &B); - for i in 0..5 { - assert!(res[i] == AB[i]); - } - } - - #[test] - fn from_bytes_wide() { - let bignum = [255u8; 64]; // 2^512 - 1 - let reduced = Scalar52::from_bytes_wide(&bignum); - println!("{:?}", reduced); - for i in 0..5 { - assert!(reduced[i] == C[i]); - } - } -} diff --git a/net/gurk-rs/files/vendor/curve25519-dalek-2.0.0/src/backend/vector/avx2/constants.rs b/net/gurk-rs/files/vendor/curve25519-dalek-2.0.0/src/backend/vector/avx2/constants.rs deleted file mode 100644 index 73e5ba3..0000000 --- a/net/gurk-rs/files/vendor/curve25519-dalek-2.0.0/src/backend/vector/avx2/constants.rs +++ /dev/null @@ -1,3427 +0,0 @@ -// -*- mode: rust; -*- -// -// This file is part of curve25519-dalek. -// Copyright (c) 2016-2019 Isis Lovecruft, Henry de Valence -// See LICENSE for licensing information. -// -// Authors: -// - Isis Agora Lovecruft -// - Henry de Valence - -//! This module contains constants used by the AVX2 backend. - -use packed_simd::u32x8; - -use backend::vector::avx2::edwards::{CachedPoint, ExtendedPoint}; -use backend::vector::avx2::field::FieldElement2625x4; -use window::NafLookupTable8; - -/// The identity element as an `ExtendedPoint`. -pub(crate) static EXTENDEDPOINT_IDENTITY: ExtendedPoint = ExtendedPoint(FieldElement2625x4([ - u32x8::new(0, 1, 0, 0, 1, 0, 0, 0), - u32x8::splat(0), - u32x8::splat(0), - u32x8::splat(0), - u32x8::splat(0), -])); - -/// The identity element as a `CachedPoint`. -pub(crate) static CACHEDPOINT_IDENTITY: CachedPoint = CachedPoint(FieldElement2625x4([ - u32x8::new(121647, 121666, 0, 0, 243332, 67108845, 0, 33554431), - u32x8::new(67108864, 0, 33554431, 0, 0, 67108863, 0, 33554431), - u32x8::new(67108863, 0, 33554431, 0, 0, 67108863, 0, 33554431), - u32x8::new(67108863, 0, 33554431, 0, 0, 67108863, 0, 33554431), - u32x8::new(67108863, 0, 33554431, 0, 0, 67108863, 0, 33554431), -])); - -/// The low limbs of (2p, 2p, 2p, 2p), so that -/// ```ascii,no_run -/// (2p, 2p, 2p, 2p) = [P_TIMES_2_LO, P_TIMES_2_HI, P_TIMES_2_HI, P_TIMES_2_HI, P_TIMES_2_HI] -/// ``` -pub(crate) static P_TIMES_2_LO: u32x8 = u32x8::new( - 67108845 << 1, - 67108845 << 1, - 33554431 << 1, - 33554431 << 1, - 67108845 << 1, - 67108845 << 1, - 33554431 << 1, - 33554431 << 1, -); - -/// The high limbs of (2p, 2p, 2p, 2p), so that -/// ```ascii,no_run -/// (2p, 2p, 2p, 2p) = [P_TIMES_2_LO, P_TIMES_2_HI, P_TIMES_2_HI, P_TIMES_2_HI, P_TIMES_2_HI] -/// ``` -pub(crate) static P_TIMES_2_HI: u32x8 = u32x8::new( - 67108863 << 1, - 67108863 << 1, - 33554431 << 1, - 33554431 << 1, - 67108863 << 1, - 67108863 << 1, - 33554431 << 1, - 33554431 << 1, -); - -/// The low limbs of (16p, 16p, 16p, 16p), so that -/// ```ascii,no_run -/// (16p, 16p, 16p, 16p) = [P_TIMES_16_LO, P_TIMES_16_HI, P_TIMES_16_HI, P_TIMES_16_HI, P_TIMES_16_HI] -/// ``` -pub(crate) static P_TIMES_16_LO: u32x8 = u32x8::new( - 67108845 << 4, - 67108845 << 4, - 33554431 << 4, - 33554431 << 4, - 67108845 << 4, - 67108845 << 4, - 33554431 << 4, - 33554431 << 4, -); - -/// The high limbs of (16p, 16p, 16p, 16p), so that -/// ```ascii,no_run -/// (16p, 16p, 16p, 16p) = [P_TIMES_16_LO, P_TIMES_16_HI, P_TIMES_16_HI, P_TIMES_16_HI, P_TIMES_16_HI] -/// ``` -pub(crate) static P_TIMES_16_HI: u32x8 = u32x8::new( - 67108863 << 4, - 67108863 << 4, - 33554431 << 4, - 33554431 << 4, - 67108863 << 4, - 67108863 << 4, - 33554431 << 4, - 33554431 << 4, -); - -/// Odd multiples of the Ed25519 basepoint: -pub(crate) static BASEPOINT_ODD_LOOKUP_TABLE: NafLookupTable8 = NafLookupTable8([ - CachedPoint(FieldElement2625x4([ - u32x8::new( - 3571425, - 10045002, - 19036563, - 1096096, - 243332, - 65897020, - 0, - 28963681, - ), - u32x8::new( - 30896895, - 63055514, - 1614915, - 5095970, - 0, - 53791688, - 0, - 31258312, - ), - u32x8::new( - 13347627, - 40339464, - 2236269, - 11185503, - 0, - 22520087, - 0, - 8659512, - ), - u32x8::new( - 11125413, - 29139905, - 32037254, - 28360723, - 0, - 64556417, - 0, - 9635759, - ), - u32x8::new( - 33268144, - 47262491, - 4336918, - 15795740, - 0, - 22027545, - 0, - 4846528, - ), - ])), - CachedPoint(FieldElement2625x4([ - u32x8::new( - 47099681, - 31447946, - 29365447, - 24740513, - 42991046, - 18317844, - 16051644, - 21404226, - ), - u32x8::new( - 31708133, - 28909527, - 2366091, - 13703791, - 469246, - 54159622, - 2601402, - 32988002, - ), - u32x8::new( - 63432457, - 30251794, - 15163516, - 18491340, - 28144087, - 35605455, - 13682295, - 18474872, - ), - u32x8::new( - 12221607, - 4967598, - 26061980, - 26008006, - 20226147, - 9726961, - 17410, - 18051083, - ), - u32x8::new( - 60569645, - 62487085, - 11911242, - 21920922, - 4092105, - 38186967, - 22431483, - 31366585, - ), - ])), - CachedPoint(FieldElement2625x4([ - u32x8::new( - 18147205, - 62587998, - 2554617, - 536692, - 11924528, - 26674131, - 17645433, - 24341419, - ), - u32x8::new( - 11573357, - 27579485, - 31491870, - 29000885, - 10800976, - 51902791, - 28076395, - 20464029, - ), - u32x8::new( - 56031649, - 10856669, - 11791193, - 26769430, - 25306956, - 5922200, - 6630685, - 9385098, - ), - u32x8::new( - 31319348, - 23906711, - 16290213, - 32142166, - 61106354, - 17181823, - 3548308, - 12022566, - ), - u32x8::new( - 5904298, - 50218605, - 11826440, - 5492249, - 10379071, - 3472255, - 172742, - 31948344, - ), - ])), - CachedPoint(FieldElement2625x4([ - u32x8::new( - 10625852, - 15193821, - 22918394, - 23676410, - 53695416, - 54987793, - 10067515, - 11747680, - ), - u32x8::new( - 65013325, - 1309652, - 29616320, - 28922974, - 60360891, - 19621771, - 9938982, - 30406429, - ), - u32x8::new( - 54967954, - 65931918, - 5595602, - 25719523, - 64909864, - 30566415, - 15945272, - 8495317, - ), - u32x8::new( - 1167157, - 55265018, - 11507029, - 31641054, - 43497904, - 2367338, - 12937761, - 27517066, - ), - u32x8::new( - 656704, - 2544994, - 13006713, - 480979, - 38471594, - 62541240, - 25353597, - 11531760, - ), - ])), - CachedPoint(FieldElement2625x4([ - u32x8::new( - 22176662, - 3984313, - 27495285, - 4110608, - 2909584, - 30594106, - 15677919, - 2549183, - ), - u32x8::new( - 33979105, - 62269905, - 2071511, - 6894756, - 53189950, - 47232857, - 6408191, - 6123225, - ), - u32x8::new( - 32553873, - 63948030, - 12612401, - 3633166, - 24054373, - 37626618, - 14481327, - 8520484, - ), - u32x8::new( - 56552486, - 10749438, - 12034813, - 28811946, - 1445640, - 36755601, - 12104575, - 10257833, - ), - u32x8::new( - 22795808, - 48761311, - 1136056, - 9380768, - 1411523, - 5341811, - 27318329, - 9686767, - ), - ])), - CachedPoint(FieldElement2625x4([ - u32x8::new( - 21157200, - 39156966, - 20473176, - 4934657, - 61478183, - 45121537, - 5429856, - 13035023, - ), - u32x8::new( - 7954529, - 58789246, - 31440083, - 7054221, - 38438565, - 36856107, - 1364112, - 14548122, - ), - u32x8::new( - 26120083, - 36321360, - 4919997, - 31687496, - 33757765, - 36237559, - 15243054, - 32163861, - ), - u32x8::new( - 25878307, - 46544824, - 19455951, - 2414935, - 16844726, - 56521560, - 32680554, - 26660660, - ), - u32x8::new( - 48360220, - 43407178, - 12187042, - 24925816, - 7423722, - 25746484, - 12814654, - 17395963, - ), - ])), - CachedPoint(FieldElement2625x4([ - u32x8::new( - 63153652, - 32195955, - 4087908, - 8431689, - 30392384, - 47203165, - 8986649, - 9053039, - ), - u32x8::new( - 63659241, - 47988767, - 2931872, - 19953600, - 11747107, - 51610101, - 20952181, - 13364887, - ), - u32x8::new( - 3659197, - 58790649, - 5930099, - 2605312, - 28477896, - 580728, - 20579735, - 2610622, - ), - u32x8::new( - 41781607, - 17161358, - 10690531, - 24368015, - 47027031, - 36742339, - 5414694, - 13156365, - ), - u32x8::new( - 13237853, - 51182423, - 8954802, - 29006542, - 22643989, - 56896541, - 22830593, - 10289708, - ), - ])), - CachedPoint(FieldElement2625x4([ - u32x8::new( - 1401265, - 58846825, - 30911620, - 32239180, - 15391552, - 15200821, - 6339309, - 16403588, - ), - u32x8::new( - 55913797, - 29541724, - 1664461, - 21709410, - 38470488, - 47097092, - 17674945, - 32666066, - ), - u32x8::new( - 22844482, - 10797709, - 27548106, - 31638735, - 34500968, - 26611503, - 19727211, - 13160873, - ), - u32x8::new( - 31485204, - 14496164, - 13981208, - 10276888, - 5748808, - 35024436, - 2740987, - 7479021, - ), - u32x8::new( - 58541207, - 14866135, - 32344041, - 545930, - 62661488, - 6941250, - 27940205, - 11976112, - ), - ])), - CachedPoint(FieldElement2625x4([ - u32x8::new( - 39849808, - 44781685, - 15697329, - 24387845, - 12501486, - 50260092, - 23199481, - 31929024, - ), - u32x8::new( - 24823070, - 27956017, - 27034296, - 10316465, - 47664045, - 11152446, - 15719183, - 30181617, - ), - u32x8::new( - 20771189, - 19969144, - 31433937, - 19185213, - 27565920, - 10384445, - 2893359, - 9255362, - ), - u32x8::new( - 42894974, - 11925545, - 32134441, - 32738810, - 55916336, - 32479272, - 19563550, - 5511385, - ), - u32x8::new( - 17857161, - 47809169, - 14564114, - 27997751, - 33024640, - 38669671, - 31956536, - 27313245, - ), - ])), - CachedPoint(FieldElement2625x4([ - u32x8::new( - 58237774, - 15917425, - 18872208, - 19394230, - 17374297, - 6101419, - 4839741, - 6596900, - ), - u32x8::new( - 66947393, - 15744215, - 18368993, - 17750160, - 41006525, - 9205497, - 2629667, - 32170865, - ), - u32x8::new( - 66481381, - 1919414, - 28338762, - 7372967, - 33819153, - 4156199, - 27126309, - 12739816, - ), - u32x8::new( - 44117158, - 58545296, - 22521371, - 11809712, - 28998792, - 50731010, - 30215699, - 25748377, - ), - u32x8::new( - 23561284, - 4160244, - 9035405, - 24895184, - 39761639, - 59253416, - 8684759, - 22487864, - ), - ])), - CachedPoint(FieldElement2625x4([ - u32x8::new( - 12671134, - 56419053, - 16092401, - 30038207, - 4002647, - 47822606, - 7151311, - 28430768, - ), - u32x8::new( - 61041684, - 35765374, - 30598048, - 19666539, - 44150175, - 40140037, - 290469, - 28442674, - ), - u32x8::new( - 18847796, - 1371617, - 33316881, - 13199936, - 43646578, - 17068881, - 12074900, - 1537415, - ), - u32x8::new( - 10052225, - 38316070, - 27469797, - 5297537, - 50725570, - 20435349, - 10339121, - 2779737, - ), - u32x8::new( - 18372189, - 15466385, - 24762130, - 22217964, - 23503887, - 47844464, - 10415034, - 2606889, - ), - ])), - CachedPoint(FieldElement2625x4([ - u32x8::new( - 55082775, - 45300503, - 16032654, - 5964396, - 17743504, - 24634761, - 19493066, - 5184611, - ), - u32x8::new( - 50172633, - 35093294, - 10040575, - 23616256, - 4543900, - 61852191, - 4049821, - 7423669, - ), - u32x8::new( - 20295398, - 40009376, - 10487190, - 15670429, - 51972856, - 58649552, - 20436392, - 3432497, - ), - u32x8::new( - 35189420, - 54117751, - 12825868, - 6283038, - 27540739, - 30648758, - 22658912, - 9466689, - ), - u32x8::new( - 51737549, - 40725785, - 17409814, - 25201086, - 21156239, - 34176168, - 26814520, - 5956424, - ), - ])), - CachedPoint(FieldElement2625x4([ - u32x8::new( - 8211442, - 8014184, - 6260823, - 22108096, - 32182620, - 51844847, - 2466270, - 28582231, - ), - u32x8::new( - 27199739, - 3848333, - 31738017, - 10892045, - 4963982, - 65391770, - 32551997, - 28906469, - ), - u32x8::new( - 16606846, - 32207068, - 26404535, - 7614129, - 45416902, - 65584718, - 13821785, - 2646060, - ), - u32x8::new( - 36090634, - 57981287, - 32247670, - 22837502, - 31003861, - 55448117, - 6062915, - 20369975, - ), - u32x8::new( - 27381403, - 50578107, - 522631, - 29521058, - 31137497, - 40220737, - 27628049, - 1824195, - ), - ])), - CachedPoint(FieldElement2625x4([ - u32x8::new( - 59402443, - 17056879, - 29262689, - 6131785, - 52551472, - 43367471, - 29423199, - 18899208, - ), - u32x8::new( - 5749414, - 43514612, - 11365899, - 21514624, - 65591890, - 60945892, - 19841732, - 5628567, - ), - u32x8::new( - 19334369, - 52500268, - 12307673, - 5267367, - 3212103, - 9035822, - 29142161, - 30520954, - ), - u32x8::new( - 57261330, - 6819646, - 22089161, - 9800373, - 55155453, - 62250856, - 13766735, - 25244545, - ), - u32x8::new( - 54370226, - 61888301, - 24496089, - 2540581, - 65637506, - 60274355, - 18154273, - 11687259, - ), - ])), - CachedPoint(FieldElement2625x4([ - u32x8::new( - 12521903, - 26014045, - 13995625, - 33360175, - 23605474, - 7376434, - 27229267, - 17195036, - ), - u32x8::new( - 59482891, - 10074423, - 574357, - 3857753, - 61377787, - 50306685, - 5241065, - 20234396, - ), - u32x8::new( - 23674717, - 6997172, - 20771841, - 16858511, - 40565304, - 29973136, - 7049812, - 14585010, - ), - u32x8::new( - 1427477, - 13295732, - 31762066, - 31499740, - 60419925, - 54666164, - 22009424, - 8089609, - ), - u32x8::new( - 58154031, - 41593020, - 15342328, - 957047, - 38937260, - 37037498, - 24871992, - 32973409, - ), - ])), - CachedPoint(FieldElement2625x4([ - u32x8::new( - 30654745, - 51286025, - 21206982, - 2433562, - 12780105, - 31732574, - 33087964, - 33081189, - ), - u32x8::new( - 66640017, - 42720009, - 16567620, - 15300745, - 1530367, - 33001123, - 20930247, - 21042661, - ), - u32x8::new( - 15003356, - 5294119, - 22985605, - 18928772, - 32628461, - 18230172, - 14773298, - 27193722, - ), - u32x8::new( - 27555, - 65346287, - 17017174, - 7837720, - 21499787, - 42855613, - 22474984, - 13675085, - ), - u32x8::new( - 24164369, - 50130116, - 5973149, - 24152073, - 1577334, - 25400030, - 18648484, - 32228854, - ), - ])), - CachedPoint(FieldElement2625x4([ - u32x8::new( - 49518649, - 59119280, - 31670678, - 20396561, - 61728330, - 651402, - 176032, - 9529498, - ), - u32x8::new( - 61765532, - 9082232, - 32794568, - 15526956, - 48543100, - 32614212, - 19001206, - 25680229, - ), - u32x8::new( - 32086091, - 10373081, - 8996131, - 31822823, - 35788988, - 49973190, - 30542040, - 17858455, - ), - u32x8::new( - 48130197, - 58121889, - 27753291, - 29923268, - 54448075, - 43300790, - 9336565, - 15770022, - ), - u32x8::new( - 57725546, - 20557498, - 9366233, - 16023566, - 16189031, - 2837363, - 24315301, - 27003505, - ), - ])), - CachedPoint(FieldElement2625x4([ - u32x8::new( - 28286608, - 10767548, - 18220739, - 5413236, - 48253387, - 58255702, - 11864864, - 28527159, - ), - u32x8::new( - 45038176, - 58655197, - 25648758, - 10951484, - 42564382, - 34542843, - 23146954, - 22234334, - ), - u32x8::new( - 14858710, - 24978793, - 15040559, - 4379220, - 47621477, - 40271440, - 15650420, - 1998736, - ), - u32x8::new( - 24106391, - 9626149, - 344505, - 25253814, - 34579800, - 59687089, - 25718289, - 25904133, - ), - u32x8::new( - 1981195, - 37751302, - 26132048, - 1764722, - 13288231, - 28808622, - 12531301, - 18292949, - ), - ])), - CachedPoint(FieldElement2625x4([ - u32x8::new( - 13869851, - 31448904, - 14963539, - 7581293, - 20536485, - 35021083, - 21257574, - 33356609, - ), - u32x8::new( - 36903364, - 18429241, - 11097857, - 5943856, - 60583077, - 40015815, - 30509523, - 31915271, - ), - u32x8::new( - 49161801, - 40681915, - 67892, - 25454357, - 22779677, - 25798439, - 15964829, - 5863227, - ), - u32x8::new( - 60810637, - 4496471, - 5217137, - 14095116, - 50942411, - 50712663, - 2507380, - 26844507, - ), - u32x8::new( - 34579752, - 53519385, - 10859797, - 18816024, - 42552864, - 39478521, - 6783896, - 17277037, - ), - ])), - CachedPoint(FieldElement2625x4([ - u32x8::new( - 43287109, - 27900723, - 33182187, - 2766754, - 17041989, - 1018260, - 33392790, - 4830032, - ), - u32x8::new( - 60194178, - 30788903, - 24728888, - 14513195, - 20897010, - 28843233, - 20111980, - 17475240, - ), - u32x8::new( - 46042274, - 19257042, - 4628173, - 31649727, - 27388316, - 66631493, - 11541886, - 6408028, - ), - u32x8::new( - 57024680, - 49536568, - 32050358, - 31321917, - 17437691, - 49672356, - 2884755, - 20493991, - ), - u32x8::new( - 59553007, - 46782643, - 29001173, - 1814088, - 21930692, - 51319706, - 14965872, - 30748046, - ), - ])), - CachedPoint(FieldElement2625x4([ - u32x8::new( - 16441817, - 36111849, - 6900424, - 602234, - 46522199, - 16441484, - 8135070, - 21726541, - ), - u32x8::new( - 37711225, - 32701959, - 11679112, - 13125533, - 32154135, - 9407918, - 26554289, - 620848, - ), - u32x8::new( - 19233407, - 30086864, - 14679568, - 2797374, - 4892806, - 7993077, - 247658, - 5632804, - ), - u32x8::new( - 37427262, - 26675495, - 27125659, - 13496131, - 50718473, - 40115609, - 28505351, - 27837393, - ), - u32x8::new( - 196819, - 18410429, - 7070012, - 21691388, - 29763371, - 24754123, - 9727048, - 10930179, - ), - ])), - CachedPoint(FieldElement2625x4([ - u32x8::new( - 28319289, - 40734650, - 16225680, - 24739184, - 64272368, - 35356897, - 7866648, - 13635853, - ), - u32x8::new( - 34165295, - 48328447, - 27041670, - 23643655, - 48949950, - 52963288, - 30411133, - 6045174, - ), - u32x8::new( - 18583559, - 41649834, - 9813585, - 26098520, - 25682734, - 26733526, - 19276490, - 10654728, - ), - u32x8::new( - 34867476, - 52715968, - 5694571, - 13380978, - 15134994, - 1831255, - 8608001, - 17266401, - ), - u32x8::new( - 59925903, - 44282172, - 27802465, - 1855069, - 14234749, - 36635487, - 11302294, - 10938429, - ), - ])), - CachedPoint(FieldElement2625x4([ - u32x8::new( - 8373273, - 49064494, - 4932071, - 32997499, - 38472880, - 29335908, - 14504412, - 22460029, - ), - u32x8::new( - 31795930, - 50785923, - 25835990, - 25790073, - 65669841, - 11360450, - 9969157, - 9008164, - ), - u32x8::new( - 50262498, - 45869261, - 16124434, - 15336007, - 882762, - 42522623, - 11277198, - 26296377, - ), - u32x8::new( - 42332732, - 59129236, - 14452816, - 567985, - 208061, - 34722729, - 32008143, - 14828749, - ), - u32x8::new( - 17937794, - 36846032, - 32102665, - 4442466, - 19745435, - 31633451, - 7146411, - 15812027, - ), - ])), - CachedPoint(FieldElement2625x4([ - u32x8::new( - 30741269, - 38648744, - 12562645, - 30092623, - 25073992, - 28730659, - 27911745, - 30000958, - ), - u32x8::new( - 2859794, - 25991700, - 17776078, - 27091930, - 2328322, - 60061146, - 18581824, - 18039008, - ), - u32x8::new( - 58206333, - 17917354, - 1972306, - 11853766, - 2655376, - 60543390, - 18416710, - 13287440, - ), - u32x8::new( - 62746330, - 61423885, - 21246577, - 2266675, - 60099139, - 14804707, - 14772234, - 20679434, - ), - u32x8::new( - 26987698, - 15488817, - 715616, - 2339565, - 51980752, - 17333865, - 21965103, - 10839820, - ), - ])), - CachedPoint(FieldElement2625x4([ - u32x8::new( - 18672548, - 57660959, - 16042910, - 19519287, - 62865851, - 17580961, - 26628347, - 23774759, - ), - u32x8::new( - 368070, - 3464471, - 25888304, - 30370559, - 52396053, - 45426828, - 28745251, - 9246829, - ), - u32x8::new( - 29090099, - 57950037, - 23104657, - 4903923, - 10987778, - 56163684, - 23621539, - 10332760, - ), - u32x8::new( - 53338235, - 44851161, - 21606845, - 31069622, - 4243630, - 34464392, - 11286454, - 5802022, - ), - u32x8::new( - 46710757, - 63389067, - 11642865, - 1980986, - 12967337, - 28162061, - 3854192, - 30432268, - ), - ])), - CachedPoint(FieldElement2625x4([ - u32x8::new( - 12179834, - 41005450, - 12809619, - 33525228, - 4624405, - 46957889, - 16968743, - 11827816, - ), - u32x8::new( - 51521162, - 12466775, - 31791271, - 15303651, - 49798465, - 62714504, - 6509600, - 12918560, - ), - u32x8::new( - 20445559, - 1756449, - 28848701, - 7920171, - 9835040, - 5900071, - 28757409, - 12376688, - ), - u32x8::new( - 18259496, - 14281012, - 21767026, - 10232236, - 20000226, - 12400540, - 4104902, - 23570543, - ), - u32x8::new( - 3687440, - 26546648, - 13328821, - 26841081, - 49822734, - 22334054, - 244496, - 24862543, - ), - ])), - CachedPoint(FieldElement2625x4([ - u32x8::new( - 59523541, - 62195428, - 3853227, - 13954801, - 12387708, - 47627615, - 27221350, - 17899572, - ), - u32x8::new( - 63193587, - 36343307, - 14595132, - 6880795, - 1364792, - 37648434, - 3259017, - 20536046, - ), - u32x8::new( - 30362834, - 10440372, - 9574624, - 11729232, - 63861613, - 21748389, - 5530846, - 2721586, - ), - u32x8::new( - 18339760, - 1550632, - 17170271, - 25732971, - 28459263, - 63142237, - 21642345, - 31557672, - ), - u32x8::new( - 10611282, - 5204623, - 18049257, - 214175, - 19432723, - 49809070, - 26010406, - 27449522, - ), - ])), - CachedPoint(FieldElement2625x4([ - u32x8::new( - 19770733, - 26478685, - 9464541, - 29158041, - 28604307, - 45196604, - 7586524, - 6641859, - ), - u32x8::new( - 65654484, - 52230498, - 30886612, - 19112823, - 47271809, - 38942611, - 16020035, - 10773481, - ), - u32x8::new( - 27464323, - 54451016, - 20646645, - 17732915, - 23008717, - 53626684, - 3253189, - 15614410, - ), - u32x8::new( - 52381752, - 40693008, - 7063024, - 28469981, - 51159478, - 44543211, - 19941777, - 5985451, - ), - u32x8::new( - 13553668, - 35524849, - 14788737, - 1883845, - 12385775, - 47958835, - 29135466, - 1776722, - ), - ])), - CachedPoint(FieldElement2625x4([ - u32x8::new( - 36719806, - 20827965, - 23175373, - 32996806, - 42041892, - 65708790, - 5467143, - 20884008, - ), - u32x8::new( - 43256281, - 40770646, - 17244063, - 31959819, - 64366384, - 43544617, - 25057754, - 12628720, - ), - u32x8::new( - 17337782, - 58472057, - 27906934, - 15305274, - 30292418, - 39284317, - 16946773, - 24806712, - ), - u32x8::new( - 6485126, - 32447403, - 16261486, - 13561940, - 49439635, - 10738368, - 16419889, - 8897231, - ), - u32x8::new( - 44812203, - 40122262, - 25496058, - 2759794, - 25295304, - 52178368, - 24154195, - 29334408, - ), - ])), - CachedPoint(FieldElement2625x4([ - u32x8::new( - 42307254, - 57217102, - 1088936, - 3832827, - 33905401, - 23130334, - 6958056, - 12622851, - ), - u32x8::new( - 3881189, - 14870059, - 19712830, - 6071598, - 38147944, - 60776394, - 3427938, - 13765703, - ), - u32x8::new( - 7666911, - 24227591, - 17077136, - 22967588, - 6874639, - 30915523, - 11451695, - 24292224, - ), - u32x8::new( - 13659529, - 31984463, - 28764736, - 20506164, - 64729627, - 49321636, - 28284636, - 25472371, - ), - u32x8::new( - 39360308, - 42281399, - 9446504, - 868960, - 49227724, - 21351115, - 30561851, - 11292096, - ), - ])), - CachedPoint(FieldElement2625x4([ - u32x8::new( - 7071115, - 46444090, - 5387916, - 15432877, - 27226682, - 41506862, - 2398278, - 3978240, - ), - u32x8::new( - 51009614, - 54216973, - 24368938, - 31392616, - 38456150, - 62313644, - 6729154, - 99724, - ), - u32x8::new( - 17474332, - 62857913, - 2619930, - 30659308, - 18268181, - 32809239, - 22826292, - 24561895, - ), - u32x8::new( - 38187020, - 67003092, - 14118280, - 16500577, - 18808560, - 64983716, - 25712929, - 32518261, - ), - u32x8::new( - 25735813, - 62284262, - 10824872, - 20558596, - 48149681, - 31162667, - 22608274, - 26285185, - ), - ])), - CachedPoint(FieldElement2625x4([ - u32x8::new( - 963440, - 63742255, - 10230323, - 25515008, - 32506414, - 6105697, - 25980317, - 24645129, - ), - u32x8::new( - 7162189, - 8101249, - 14679265, - 33443386, - 2002396, - 8541405, - 19442276, - 4795881, - ), - u32x8::new( - 8116694, - 51463069, - 4415528, - 25599140, - 55805721, - 39582709, - 6719436, - 30033839, - ), - u32x8::new( - 14468202, - 42181869, - 25188826, - 9639755, - 47546189, - 62711146, - 32762447, - 18338064, - ), - u32x8::new( - 33880058, - 32810909, - 8969931, - 13095238, - 38360605, - 40138517, - 9246134, - 4928058, - ), - ])), - CachedPoint(FieldElement2625x4([ - u32x8::new( - 63655588, - 17883670, - 9410246, - 26162761, - 5000571, - 7349225, - 23785252, - 32751089, - ), - u32x8::new( - 28568737, - 10733123, - 9342397, - 21570673, - 54096560, - 32467591, - 20494687, - 21511513, - ), - u32x8::new( - 47675157, - 47932807, - 29250946, - 15672208, - 59760469, - 9945465, - 14939287, - 18437405, - ), - u32x8::new( - 37985267, - 8609815, - 31573002, - 3373596, - 47828883, - 20834216, - 13248616, - 24154292, - ), - u32x8::new( - 5543543, - 29553242, - 3386453, - 30501150, - 25058089, - 15236571, - 8814395, - 32462955, - ), - ])), - CachedPoint(FieldElement2625x4([ - u32x8::new( - 39158670, - 15322548, - 20495103, - 3312736, - 14557171, - 12985179, - 8044741, - 3176899, - ), - u32x8::new( - 24673290, - 29693310, - 21412266, - 18324699, - 2154518, - 40329021, - 17500543, - 3954277, - ), - u32x8::new( - 36758685, - 38738957, - 165513, - 14691866, - 3070475, - 10424235, - 17096536, - 16896898, - ), - u32x8::new( - 59790459, - 43094586, - 8720681, - 10423589, - 1122030, - 31545615, - 4463786, - 31811293, - ), - u32x8::new( - 49778992, - 60881044, - 20509974, - 5832494, - 64155961, - 31483358, - 4511231, - 20307815, - ), - ])), - CachedPoint(FieldElement2625x4([ - u32x8::new( - 2863373, - 40876242, - 26865913, - 24067353, - 15726407, - 40919070, - 12953902, - 9931535, - ), - u32x8::new( - 60934877, - 42512204, - 21649141, - 21945190, - 52211954, - 60984193, - 7046207, - 5363493, - ), - u32x8::new( - 4205971, - 64068464, - 18197273, - 7327176, - 51527794, - 21166920, - 20669933, - 11828242, - ), - u32x8::new( - 59782815, - 49617225, - 15379924, - 457923, - 9320508, - 21498914, - 3242540, - 31563182, - ), - u32x8::new( - 27714753, - 8664670, - 3366162, - 26338598, - 56775518, - 25796006, - 13129151, - 21388876, - ), - ])), - CachedPoint(FieldElement2625x4([ - u32x8::new( - 59276548, - 49972346, - 16795002, - 33455915, - 48430097, - 53857205, - 18627071, - 32474471, - ), - u32x8::new( - 42160315, - 50705892, - 13530540, - 28012698, - 19833221, - 55886870, - 20191784, - 9644313, - ), - u32x8::new( - 20372416, - 28414713, - 24084234, - 31804096, - 33815377, - 36131001, - 17251241, - 18291088, - ), - u32x8::new( - 56234667, - 14920441, - 2033267, - 29572003, - 1724043, - 45519699, - 17873735, - 501988, - ), - u32x8::new( - 50031659, - 31517850, - 15697583, - 1016845, - 43104661, - 54769582, - 8008601, - 27257051, - ), - ])), - CachedPoint(FieldElement2625x4([ - u32x8::new( - 52951491, - 66542164, - 14853573, - 30444631, - 12045973, - 24321813, - 16545674, - 18160646, - ), - u32x8::new( - 60107911, - 1126003, - 5947677, - 19486116, - 41119984, - 30860440, - 7935395, - 13354438, - ), - u32x8::new( - 17841328, - 11063269, - 1664538, - 26687568, - 6268968, - 22280371, - 17275484, - 4523163, - ), - u32x8::new( - 15886041, - 56799482, - 15446552, - 21712778, - 1005290, - 17827215, - 4978741, - 6854882, - ), - u32x8::new( - 34319277, - 47731002, - 20321804, - 28544575, - 29591814, - 63376351, - 24754545, - 26001714, - ), - ])), - CachedPoint(FieldElement2625x4([ - u32x8::new( - 66783087, - 5234346, - 46102, - 8566476, - 19947339, - 20180418, - 25398238, - 3726678, - ), - u32x8::new( - 63890180, - 46380965, - 20674069, - 5366544, - 59661487, - 48406612, - 31533614, - 7071217, - ), - u32x8::new( - 13104676, - 1406631, - 24326736, - 19854367, - 61039528, - 11019904, - 31967425, - 19219275, - ), - u32x8::new( - 39003597, - 30143957, - 15351834, - 8639435, - 57309582, - 61436794, - 15830475, - 10090318, - ), - u32x8::new( - 45923044, - 6700175, - 99413, - 21263025, - 23762647, - 53905481, - 6063914, - 10065424, - ), - ])), - CachedPoint(FieldElement2625x4([ - u32x8::new( - 42822326, - 57678669, - 4052879, - 25452667, - 54049411, - 2373092, - 22337016, - 7701046, - ), - u32x8::new( - 44382355, - 43307377, - 16761537, - 30373573, - 49790216, - 23230748, - 25655306, - 10519391, - ), - u32x8::new( - 919475, - 59371245, - 1273450, - 25558666, - 9724711, - 8556709, - 25755845, - 10887647, - ), - u32x8::new( - 25465699, - 44651158, - 17658392, - 11257418, - 29735193, - 22885150, - 7094716, - 26828565, - ), - u32x8::new( - 48237389, - 47661599, - 27054393, - 7328070, - 27280193, - 65616691, - 23062005, - 4170709, - ), - ])), - CachedPoint(FieldElement2625x4([ - u32x8::new( - 26535281, - 60238317, - 30343788, - 25790743, - 37993933, - 24614372, - 9523840, - 10401918, - ), - u32x8::new( - 2783987, - 29468958, - 4697011, - 19804475, - 37246678, - 46797720, - 10261254, - 18942252, - ), - u32x8::new( - 58135580, - 60247753, - 25301938, - 6844561, - 20949454, - 39844754, - 4552026, - 919057, - ), - u32x8::new( - 6694071, - 44126261, - 32285330, - 31370180, - 24603698, - 53328179, - 13971149, - 5325636, - ), - u32x8::new( - 64879487, - 582094, - 17982081, - 19190425, - 24951286, - 26923842, - 29077174, - 33286062, - ), - ])), - CachedPoint(FieldElement2625x4([ - u32x8::new( - 54863941, - 67016431, - 1224043, - 23371240, - 62940074, - 52101083, - 13523637, - 30366406, - ), - u32x8::new( - 36324581, - 25407485, - 18258623, - 4698602, - 50300544, - 2658516, - 26300935, - 2611030, - ), - u32x8::new( - 27183975, - 21791014, - 18105064, - 9875199, - 58118912, - 54198635, - 6400311, - 14767984, - ), - u32x8::new( - 33918318, - 42937962, - 14809334, - 22136592, - 10636588, - 29082337, - 29829692, - 28549776, - ), - u32x8::new( - 61080905, - 854212, - 12202487, - 20004503, - 9256495, - 6903981, - 20567109, - 347423, - ), - ])), - CachedPoint(FieldElement2625x4([ - u32x8::new( - 41391822, - 34336880, - 22362564, - 14247996, - 12115604, - 41583344, - 7639288, - 28910945, - ), - u32x8::new( - 62066617, - 59758859, - 26665947, - 11614812, - 65737664, - 45704543, - 30324810, - 12868376, - ), - u32x8::new( - 17491771, - 43589814, - 9454919, - 26047850, - 52629282, - 39304244, - 3868968, - 19296062, - ), - u32x8::new( - 17826638, - 30413590, - 32534225, - 32741469, - 15012391, - 14365713, - 33039233, - 14791399, - ), - u32x8::new( - 64115596, - 59197067, - 32739005, - 23275744, - 32954320, - 22241406, - 20788442, - 4942942, - ), - ])), - CachedPoint(FieldElement2625x4([ - u32x8::new( - 31956192, - 59570132, - 2784352, - 4237732, - 47222312, - 4860927, - 18658867, - 15279314, - ), - u32x8::new( - 63240583, - 28160478, - 23524941, - 13390861, - 66437406, - 57718120, - 33345312, - 28896298, - ), - u32x8::new( - 39026193, - 46239965, - 21440243, - 25070488, - 64012383, - 60999016, - 16517060, - 29565907, - ), - u32x8::new( - 18118181, - 60161496, - 4212092, - 23976240, - 36277753, - 62363144, - 5816868, - 16964362, - ), - u32x8::new( - 18196138, - 62490693, - 281468, - 7934713, - 56027312, - 62015725, - 4837237, - 32932252, - ), - ])), - CachedPoint(FieldElement2625x4([ - u32x8::new( - 29885826, - 51028067, - 30418143, - 33438769, - 62542283, - 39442528, - 31535876, - 143299, - ), - u32x8::new( - 17143063, - 56709783, - 14451852, - 15782104, - 32762665, - 14047066, - 26295037, - 5432487, - ), - u32x8::new( - 75151, - 533606, - 7539077, - 30926189, - 38410914, - 23771680, - 4872443, - 29199566, - ), - u32x8::new( - 61522396, - 48934708, - 16223126, - 207380, - 11171993, - 47975147, - 14164574, - 352966, - ), - u32x8::new( - 15449006, - 56530757, - 26796528, - 12045834, - 63738697, - 40667227, - 33001582, - 9101885, - ), - ])), - CachedPoint(FieldElement2625x4([ - u32x8::new( - 43331297, - 18431341, - 25801195, - 17267698, - 19365485, - 57295202, - 22218985, - 21284590, - ), - u32x8::new( - 2429849, - 19152559, - 10762172, - 22564684, - 21880390, - 66866426, - 20357935, - 22641906, - ), - u32x8::new( - 19771185, - 31652693, - 3666117, - 28136958, - 23624283, - 55101502, - 6313920, - 6783662, - ), - u32x8::new( - 3487137, - 7092443, - 11001876, - 26196524, - 47319246, - 44542068, - 17594073, - 15027760, - ), - u32x8::new( - 49563607, - 32191113, - 4991283, - 25400512, - 46539152, - 4155103, - 32368171, - 201203, - ), - ])), - CachedPoint(FieldElement2625x4([ - u32x8::new( - 20548943, - 14334571, - 4073874, - 6368588, - 53208883, - 56484515, - 15970071, - 25561889, - ), - u32x8::new( - 49915097, - 44030795, - 11202344, - 29284344, - 60258023, - 66225712, - 8075764, - 12383512, - ), - u32x8::new( - 45248912, - 4933668, - 9592153, - 5819559, - 31030983, - 38174071, - 32435814, - 7442522, - ), - u32x8::new( - 62688129, - 48218381, - 22089545, - 12897361, - 21050881, - 34278889, - 7569163, - 3225449, - ), - u32x8::new( - 19050183, - 51089071, - 32935757, - 22640195, - 66122318, - 47144608, - 18743677, - 25177079, - ), - ])), - CachedPoint(FieldElement2625x4([ - u32x8::new( - 41186817, - 46681702, - 31819867, - 32997133, - 38559207, - 27147015, - 30293819, - 16762988, - ), - u32x8::new( - 24154689, - 51762873, - 23883879, - 13510519, - 55338250, - 61224161, - 11663149, - 30803960, - ), - u32x8::new( - 18104238, - 14117824, - 11724021, - 21362053, - 65704761, - 35530242, - 13498058, - 33522849, - ), - u32x8::new( - 63812888, - 23995539, - 28920539, - 24005193, - 26412223, - 36582218, - 4251418, - 26160309, - ), - u32x8::new( - 16822053, - 66064082, - 3482145, - 31979593, - 45937188, - 54475379, - 612917, - 7976478, - ), - ])), - CachedPoint(FieldElement2625x4([ - u32x8::new( - 46509314, - 55327128, - 8944536, - 274914, - 26432930, - 53829300, - 21192572, - 3569894, - ), - u32x8::new( - 20919764, - 64356651, - 30642344, - 17215170, - 20335124, - 11203745, - 18663316, - 19024174, - ), - u32x8::new( - 59297055, - 53842463, - 3680204, - 9806710, - 54004169, - 51484914, - 29807998, - 20134199, - ), - u32x8::new( - 14781592, - 22628010, - 26877930, - 25880359, - 30434803, - 190607, - 30184292, - 8991040, - ), - u32x8::new( - 64400983, - 64591751, - 854562, - 28216111, - 20010398, - 50414793, - 9803872, - 22687008, - ), - ])), - CachedPoint(FieldElement2625x4([ - u32x8::new( - 15091184, - 32550863, - 8818643, - 4244752, - 43123513, - 64565526, - 408838, - 13206998, - ), - u32x8::new( - 16405061, - 60379639, - 31489017, - 20949281, - 27568751, - 38734986, - 8364264, - 12451020, - ), - u32x8::new( - 16005217, - 58008076, - 1406778, - 26546927, - 39571784, - 56365493, - 31274296, - 8918790, - ), - u32x8::new( - 23271122, - 19453469, - 27718201, - 32742670, - 234332, - 36785342, - 22601675, - 14331046, - ), - u32x8::new( - 40636025, - 22442705, - 22115403, - 23745859, - 41164945, - 61012, - 12499614, - 542137, - ), - ])), - CachedPoint(FieldElement2625x4([ - u32x8::new( - 62776018, - 32835413, - 17373246, - 17187309, - 54469193, - 21770290, - 15923753, - 28996575, - ), - u32x8::new( - 59385210, - 63082298, - 12568449, - 8509004, - 9483342, - 16105238, - 5756054, - 26890758, - ), - u32x8::new( - 53987996, - 38201748, - 5521661, - 19060159, - 18663191, - 9093637, - 27786835, - 31189196, - ), - u32x8::new( - 65872678, - 43635130, - 27903055, - 25020300, - 65772737, - 38110437, - 5213502, - 21909342, - ), - u32x8::new( - 4438979, - 9680838, - 10212446, - 4764184, - 13235684, - 58245995, - 20264570, - 21024049, - ), - ])), - CachedPoint(FieldElement2625x4([ - u32x8::new( - 60835961, - 48209103, - 31049052, - 4688268, - 12426713, - 59829045, - 22302488, - 29008521, - ), - u32x8::new( - 50401667, - 29716596, - 23531224, - 7581281, - 49071895, - 6952617, - 14934683, - 8218256, - ), - u32x8::new( - 1601446, - 36631413, - 31774811, - 29625330, - 56786114, - 8331539, - 23129509, - 19783344, - ), - u32x8::new( - 59514327, - 64513110, - 1772300, - 5701338, - 5737511, - 16147555, - 9461515, - 5703271, - ), - u32x8::new( - 33072974, - 54300426, - 11940114, - 1308663, - 15627555, - 4931627, - 28443714, - 20924342, - ), - ])), - CachedPoint(FieldElement2625x4([ - u32x8::new( - 18135013, - 20358426, - 4922557, - 10015355, - 65729669, - 34786528, - 26248549, - 29194359, - ), - u32x8::new( - 797666, - 34997544, - 24316856, - 25107230, - 24612576, - 4761401, - 15307321, - 32404252, - ), - u32x8::new( - 16501152, - 60565831, - 9487105, - 9316022, - 24986054, - 31917592, - 3962024, - 2501883, - ), - u32x8::new( - 63356796, - 50432342, - 18044926, - 30566881, - 42032028, - 31415202, - 13524600, - 16119907, - ), - u32x8::new( - 3927286, - 57022374, - 9265437, - 21620772, - 19481940, - 3806938, - 24836192, - 14572399, - ), - ])), - CachedPoint(FieldElement2625x4([ - u32x8::new( - 10785787, - 46564798, - 368445, - 33181384, - 5319843, - 52687136, - 30347110, - 29837357, - ), - u32x8::new( - 56436732, - 47859251, - 24141084, - 22250712, - 59046084, - 4963427, - 33463413, - 17168859, - ), - u32x8::new( - 15512044, - 6366740, - 4737504, - 27644548, - 30307977, - 25037929, - 14593903, - 12836490, - ), - u32x8::new( - 63878897, - 34013023, - 5860752, - 7244096, - 3689461, - 57012135, - 18389096, - 11589351, - ), - u32x8::new( - 4682110, - 36302830, - 653422, - 22316819, - 14081831, - 5657024, - 11088376, - 24110612, - ), - ])), - CachedPoint(FieldElement2625x4([ - u32x8::new( - 39907267, - 45940262, - 24887471, - 18342609, - 878445, - 40456159, - 12019082, - 345107, - ), - u32x8::new( - 12794982, - 28893944, - 9447505, - 11387200, - 16961963, - 13916996, - 10893728, - 25898006, - ), - u32x8::new( - 44934162, - 53465865, - 3583620, - 1102334, - 53917811, - 63478576, - 2426066, - 10389549, - ), - u32x8::new( - 45096036, - 37595344, - 19367718, - 20257175, - 10280866, - 41653449, - 27665642, - 375926, - ), - u32x8::new( - 45847901, - 24064074, - 32494820, - 32204556, - 10720704, - 51079060, - 1297436, - 29853825, - ), - ])), - CachedPoint(FieldElement2625x4([ - u32x8::new( - 66303987, - 36060363, - 16494578, - 24962147, - 11971403, - 49538586, - 25060560, - 1964341, - ), - u32x8::new( - 25988481, - 27641502, - 24909517, - 27237087, - 66646363, - 52777626, - 16360849, - 10459972, - ), - u32x8::new( - 43930529, - 34374176, - 31225968, - 8807030, - 10394758, - 35904854, - 25325589, - 19335583, - ), - u32x8::new( - 25094697, - 34380951, - 20051185, - 32287161, - 11739332, - 53887441, - 30517319, - 26601892, - ), - u32x8::new( - 8868546, - 35635502, - 32513071, - 28248087, - 51946989, - 14222744, - 19198839, - 23261841, - ), - ])), - CachedPoint(FieldElement2625x4([ - u32x8::new( - 51218008, - 5070126, - 11046681, - 5320810, - 61212079, - 34104447, - 23895089, - 6460727, - ), - u32x8::new( - 39843528, - 46278671, - 10426120, - 25624792, - 66658766, - 37140083, - 28933107, - 12969597, - ), - u32x8::new( - 59635793, - 40220191, - 5751421, - 173680, - 58321825, - 740337, - 1412847, - 7682623, - ), - u32x8::new( - 975962, - 56440763, - 20812276, - 22631115, - 49095824, - 19883130, - 2419746, - 31043648, - ), - u32x8::new( - 66208703, - 39669328, - 22525915, - 3748897, - 65994776, - 34533552, - 8126286, - 18326047, - ), - ])), - CachedPoint(FieldElement2625x4([ - u32x8::new( - 64176557, - 3912400, - 19351673, - 30068471, - 31190055, - 24221683, - 33142424, - 28698542, - ), - u32x8::new( - 34784792, - 4109933, - 3867193, - 19557314, - 2112512, - 32715890, - 24550117, - 16595976, - ), - u32x8::new( - 35542761, - 48024875, - 10925431, - 31526577, - 66577735, - 23189821, - 13375709, - 1735095, - ), - u32x8::new( - 59699254, - 43854093, - 29783239, - 24777271, - 19600372, - 39924461, - 2896720, - 1472185, - ), - u32x8::new( - 56389656, - 35980854, - 33172342, - 1370336, - 23707480, - 57654949, - 7850973, - 12655016, - ), - ])), - CachedPoint(FieldElement2625x4([ - u32x8::new( - 38372660, - 57101970, - 7044964, - 12732710, - 57535705, - 6043201, - 30858914, - 10946592, - ), - u32x8::new( - 21023468, - 6946992, - 26403324, - 23901823, - 35695559, - 23440687, - 4763891, - 6514074, - ), - u32x8::new( - 28662273, - 30933699, - 9352242, - 26354829, - 37402243, - 3145176, - 8770289, - 525937, - ), - u32x8::new( - 54933102, - 36695832, - 3281859, - 4755022, - 23043294, - 32794379, - 15618886, - 23602412, - ), - u32x8::new( - 9931565, - 29897140, - 2480737, - 24193701, - 7833615, - 2284939, - 893926, - 13421882, - ), - ])), - CachedPoint(FieldElement2625x4([ - u32x8::new( - 22917795, - 22088359, - 28978099, - 19794863, - 60542318, - 29878494, - 31053731, - 9080720, - ), - u32x8::new( - 23679072, - 52547035, - 28424916, - 20647332, - 4008761, - 28267029, - 12961289, - 1589095, - ), - u32x8::new( - 55616194, - 26678929, - 14998265, - 23274397, - 54625466, - 46244264, - 28627706, - 33030665, - ), - u32x8::new( - 11527330, - 6449415, - 26531607, - 3472938, - 41541592, - 62607682, - 19862690, - 20564723, - ), - u32x8::new( - 32843805, - 49066843, - 28425824, - 19521495, - 48792073, - 48242878, - 27392443, - 13175986, - ), - ])), - CachedPoint(FieldElement2625x4([ - u32x8::new( - 16185025, - 61537525, - 2961305, - 1492442, - 25123147, - 3095034, - 31896958, - 33089615, - ), - u32x8::new( - 64748157, - 18336595, - 16522231, - 25426312, - 65718949, - 35485695, - 30554083, - 10205918, - ), - u32x8::new( - 39626934, - 39271045, - 16420458, - 9826240, - 56483981, - 27128085, - 3783403, - 13360006, - ), - u32x8::new( - 30793778, - 66771960, - 17241420, - 6564573, - 61102581, - 29974476, - 32385512, - 9011754, - ), - u32x8::new( - 28068166, - 11862220, - 14323567, - 12380617, - 52090465, - 16029056, - 24495309, - 21409233, - ), - ])), - CachedPoint(FieldElement2625x4([ - u32x8::new( - 59411973, - 57437124, - 11695483, - 17586857, - 16108987, - 43449109, - 31098002, - 6248476, - ), - u32x8::new( - 42258047, - 61595931, - 29308533, - 11742653, - 43042345, - 27373650, - 30165249, - 21929989, - ), - u32x8::new( - 49907221, - 9620337, - 21888081, - 20981082, - 56288861, - 61562203, - 33223566, - 3582446, - ), - u32x8::new( - 57535017, - 41003416, - 22080416, - 14463796, - 65518565, - 18127889, - 24370863, - 33332664, - ), - u32x8::new( - 66655380, - 6430175, - 471782, - 11947673, - 30596400, - 18898659, - 15930721, - 4211851, - ), - ])), - CachedPoint(FieldElement2625x4([ - u32x8::new( - 6757410, - 65455566, - 13584784, - 11362173, - 10797127, - 24451471, - 19541370, - 29309435, - ), - u32x8::new( - 40360156, - 17685025, - 18326181, - 3846903, - 13693365, - 63049479, - 31900359, - 23385063, - ), - u32x8::new( - 52455038, - 57513503, - 22163311, - 27095042, - 48610726, - 66454160, - 12085341, - 26357004, - ), - u32x8::new( - 22097042, - 14063840, - 6705778, - 14342902, - 66139825, - 20702105, - 31279090, - 7495745, - ), - u32x8::new( - 27360710, - 49314837, - 18774847, - 7146436, - 37066216, - 42004961, - 22409916, - 10524446, - ), - ])), - CachedPoint(FieldElement2625x4([ - u32x8::new( - 1497507, - 33054449, - 11839906, - 2960428, - 40538463, - 18884538, - 25018820, - 4073970, - ), - u32x8::new( - 54484385, - 43640735, - 2808257, - 20710708, - 39840730, - 27222424, - 21783544, - 11848522, - ), - u32x8::new( - 45765237, - 48200555, - 9299019, - 9393151, - 34818188, - 56098995, - 13575233, - 21012731, - ), - u32x8::new( - 4265428, - 49627650, - 24960282, - 9425650, - 47883651, - 2797524, - 11853190, - 22877329, - ), - u32x8::new( - 25008173, - 64199503, - 380047, - 12107343, - 12329448, - 11914399, - 764281, - 29687002, - ), - ])), - CachedPoint(FieldElement2625x4([ - u32x8::new( - 35889734, - 23047226, - 4022841, - 7017445, - 7274086, - 53316179, - 25100176, - 15310676, - ), - u32x8::new( - 42409427, - 30270106, - 6823853, - 31551384, - 40645017, - 66489807, - 18021817, - 32669351, - ), - u32x8::new( - 39827134, - 43680850, - 28297996, - 20258133, - 26058742, - 52643238, - 22238331, - 21690533, - ), - u32x8::new( - 60808002, - 17499995, - 30042246, - 29310584, - 48219954, - 29389518, - 8680514, - 17844709, - ), - u32x8::new( - 6452896, - 50116553, - 9532047, - 26821214, - 44524351, - 50428429, - 21904953, - 12608048, - ), - ])), -]); diff --git a/net/gurk-rs/files/vendor/curve25519-dalek-2.0.0/src/backend/vector/avx2/edwards.rs b/net/gurk-rs/files/vendor/curve25519-dalek-2.0.0/src/backend/vector/avx2/edwards.rs deleted file mode 100644 index 8465720..0000000 --- a/net/gurk-rs/files/vendor/curve25519-dalek-2.0.0/src/backend/vector/avx2/edwards.rs +++ /dev/null @@ -1,524 +0,0 @@ -// -*- mode: rust; -*- -// -// This file is part of curve25519-dalek. -// Copyright (c) 2016-2019 Isis Lovecruft, Henry de Valence -// See LICENSE for licensing information. -// -// Authors: -// - Isis Agora Lovecruft -// - Henry de Valence - -//! Parallel Edwards Arithmetic for Curve25519. -//! -//! This module currently has two point types: -//! -//! * `ExtendedPoint`: a point stored in vector-friendly format, with -//! vectorized doubling and addition; -//! -//! * `CachedPoint`: used for readdition. -//! -//! Details on the formulas can be found in the documentation for the -//! parent `avx2` module. -//! -//! This API is designed to be safe: vectorized points can only be -//! created from serial points (which do validation on decompression), -//! and operations on valid points return valid points, so invalid -//! point states should be unrepresentable. -//! -//! This design goal is met, with one exception: the `Neg` -//! implementation for the `CachedPoint` performs a lazy negation, so -//! that subtraction can be efficiently implemented as a negation and -//! an addition. Repeatedly negating a `CachedPoint` will cause its -//! coefficients to grow and eventually overflow. Repeatedly negating -//! a point should not be necessary anyways. - -#![allow(non_snake_case)] - -use core::convert::From; -use core::ops::{Add, Neg, Sub}; - -use subtle::Choice; -use subtle::ConditionallySelectable; - -use edwards; -use window::{LookupTable, NafLookupTable5, NafLookupTable8}; - -use traits::Identity; - -use super::constants; -use super::field::{FieldElement2625x4, Lanes, Shuffle}; - -/// A point on Curve25519, using parallel Edwards formulas for curve -/// operations. -/// -/// # Invariant -/// -/// The coefficients of an `ExtendedPoint` are bounded with -/// \\( b < 0.007 \\). -#[derive(Copy, Clone, Debug)] -pub struct ExtendedPoint(pub(super) FieldElement2625x4); - -impl From for ExtendedPoint { - fn from(P: edwards::EdwardsPoint) -> ExtendedPoint { - ExtendedPoint(FieldElement2625x4::new(&P.X, &P.Y, &P.Z, &P.T)) - } -} - -impl From for edwards::EdwardsPoint { - fn from(P: ExtendedPoint) -> edwards::EdwardsPoint { - let tmp = P.0.split(); - edwards::EdwardsPoint { - X: tmp[0], - Y: tmp[1], - Z: tmp[2], - T: tmp[3], - } - } -} - -impl ConditionallySelectable for ExtendedPoint { - fn conditional_select(a: &Self, b: &Self, choice: Choice) -> Self { - ExtendedPoint(FieldElement2625x4::conditional_select(&a.0, &b.0, choice)) - } - - fn conditional_assign(&mut self, other: &Self, choice: Choice) { - self.0.conditional_assign(&other.0, choice); - } -} - -impl Default for ExtendedPoint { - fn default() -> ExtendedPoint { - ExtendedPoint::identity() - } -} - -impl Identity for ExtendedPoint { - fn identity() -> ExtendedPoint { - constants::EXTENDEDPOINT_IDENTITY - } -} - -impl ExtendedPoint { - /// Compute the double of this point. - pub fn double(&self) -> ExtendedPoint { - // Want to compute (X1 Y1 Z1 X1+Y1). - // Not sure how to do this less expensively than computing - // (X1 Y1 Z1 T1) --(256bit shuffle)--> (X1 Y1 X1 Y1) - // (X1 Y1 X1 Y1) --(2x128b shuffle)--> (Y1 X1 Y1 X1) - // and then adding. - - // Set tmp0 = (X1 Y1 X1 Y1) - let mut tmp0 = self.0.shuffle(Shuffle::ABAB); - - // Set tmp1 = (Y1 X1 Y1 X1) - let mut tmp1 = tmp0.shuffle(Shuffle::BADC); - - // Set tmp0 = (X1 Y1 Z1 X1+Y1) - tmp0 = self.0.blend(tmp0 + tmp1, Lanes::D); - - // Set tmp1 = tmp0^2, negating the D values - tmp1 = tmp0.square_and_negate_D(); - // Now tmp1 = (S1 S2 S3 -S4) with b < 0.007 - - // See discussion of bounds in the module-level documentation. - // We want to compute - // - // + | S1 | S1 | S1 | S1 | - // + | S2 | | | S2 | - // + | | | S3 | | - // + | | | S3 | | - // + | | | |-S4 | - // + | | 2p | 2p | | - // - | | S2 | S2 | | - // ======================= - // S5 S6 S8 S9 - - let zero = FieldElement2625x4::zero(); - let S_1 = tmp1.shuffle(Shuffle::AAAA); - let S_2 = tmp1.shuffle(Shuffle::BBBB); - - tmp0 = zero.blend(tmp1 + tmp1, Lanes::C); - // tmp0 = (0, 0, 2S_3, 0) - tmp0 = tmp0.blend(tmp1, Lanes::D); - // tmp0 = (0, 0, 2S_3, -S_4) - tmp0 = tmp0 + S_1; - // tmp0 = ( S_1, S_1, S_1 + 2S_3, S_1 - S_4) - tmp0 = tmp0 + zero.blend(S_2, Lanes::AD); - // tmp0 = (S_1 + S_2, S_1, S_1 + 2S_3, S_1 + S_2 - S_4) - tmp0 = tmp0 + zero.blend(S_2.negate_lazy(), Lanes::BC); - // tmp0 = (S_1 + S_2, S_1 - S_2, S_1 - S_2 + 2S_3, S_1 + S_2 - S_4) - // b < ( 1.01, 1.6, 2.33, 1.6) - // Now tmp0 = (S_5, S_6, S_8, S_9) - - // Set tmp1 = ( S_9, S_6, S_6, S_9) - // b < ( 1.6, 1.6, 1.6, 1.6) - tmp1 = tmp0.shuffle(Shuffle::DBBD); - // Set tmp1 = ( S_8, S_5, S_8, S_5) - // b < (2.33, 1.01, 2.33, 1.01) - tmp0 = tmp0.shuffle(Shuffle::CACA); - - // Bounds on (tmp0, tmp1) are (2.33, 1.6) < (2.5, 1.75). - ExtendedPoint(&tmp0 * &tmp1) - } - - pub fn mul_by_pow_2(&self, k: u32) -> ExtendedPoint { - let mut tmp: ExtendedPoint = *self; - for _ in 0..k { - tmp = tmp.double(); - } - tmp - } -} - -/// A cached point with some precomputed variables used for readdition. -/// -/// # Warning -/// -/// It is not safe to negate this point more than once. -/// -/// # Invariant -/// -/// As long as the `CachedPoint` is not repeatedly negated, its -/// coefficients will be bounded with \\( b < 1.0 \\). -#[derive(Copy, Clone, Debug)] -pub struct CachedPoint(pub(super) FieldElement2625x4); - -impl From for CachedPoint { - fn from(P: ExtendedPoint) -> CachedPoint { - let mut x = P.0; - - x = x.blend(x.diff_sum(), Lanes::AB); - // x = (X1 - Y1, X2 + Y2, Z2, T2) = (S2 S3 Z2 T2) - - x = x * (121666, 121666, 2 * 121666, 2 * 121665); - // x = (121666*S2 121666*S3 2*121666*Z2 2*121665*T2) - - x = x.blend(-x, Lanes::D); - // x = (121666*S2 121666*S3 2*121666*Z2 -2*121665*T2) - - // The coefficients of the output are bounded with b < 0.007. - CachedPoint(x) - } -} - -impl Default for CachedPoint { - fn default() -> CachedPoint { - CachedPoint::identity() - } -} - -impl Identity for CachedPoint { - fn identity() -> CachedPoint { - constants::CACHEDPOINT_IDENTITY - } -} - -impl ConditionallySelectable for CachedPoint { - fn conditional_select(a: &Self, b: &Self, choice: Choice) -> Self { - CachedPoint(FieldElement2625x4::conditional_select(&a.0, &b.0, choice)) - } - - fn conditional_assign(&mut self, other: &Self, choice: Choice) { - self.0.conditional_assign(&other.0, choice); - } -} - -impl<'a> Neg for &'a CachedPoint { - type Output = CachedPoint; - /// Lazily negate the point. - /// - /// # Warning - /// - /// Because this method does not perform a reduction, it is not - /// safe to repeatedly negate a point. - fn neg(self) -> CachedPoint { - let swapped = self.0.shuffle(Shuffle::BACD); - CachedPoint(swapped.blend(swapped.negate_lazy(), Lanes::D)) - } -} - -impl<'a, 'b> Add<&'b CachedPoint> for &'a ExtendedPoint { - type Output = ExtendedPoint; - - /// Add an `ExtendedPoint` and a `CachedPoint`. - fn add(self, other: &'b CachedPoint) -> ExtendedPoint { - // The coefficients of an `ExtendedPoint` are reduced after - // every operation. If the `CachedPoint` was negated, its - // coefficients grow by one bit. So on input, `self` is - // bounded with `b < 0.007` and `other` is bounded with - // `b < 1.0`. - - let mut tmp = self.0; - - tmp = tmp.blend(tmp.diff_sum(), Lanes::AB); - // tmp = (Y1-X1 Y1+X1 Z1 T1) = (S0 S1 Z1 T1) with b < 1.6 - - // (tmp, other) bounded with b < (1.6, 1.0) < (2.5, 1.75). - tmp = &tmp * &other.0; - // tmp = (S0*S2' S1*S3' Z1*Z2' T1*T2') = (S8 S9 S10 S11) - - tmp = tmp.shuffle(Shuffle::ABDC); - // tmp = (S8 S9 S11 S10) - - tmp = tmp.diff_sum(); - // tmp = (S9-S8 S9+S8 S10-S11 S10+S11) = (S12 S13 S14 S15) - - let t0 = tmp.shuffle(Shuffle::ADDA); - // t0 = (S12 S15 S15 S12) - let t1 = tmp.shuffle(Shuffle::CBCB); - // t1 = (S14 S13 S14 S13) - - // All coefficients of t0, t1 are bounded with b < 1.6. - // Return (S12*S14 S15*S13 S15*S14 S12*S13) = (X3 Y3 Z3 T3) - ExtendedPoint(&t0 * &t1) - } -} - -impl<'a, 'b> Sub<&'b CachedPoint> for &'a ExtendedPoint { - type Output = ExtendedPoint; - - /// Implement subtraction by negating the point and adding. - /// - /// Empirically, this seems about the same cost as a custom - /// subtraction impl (maybe because the benefit is cancelled by - /// increased code size?) - fn sub(self, other: &'b CachedPoint) -> ExtendedPoint { - self + &(-other) - } -} - -impl<'a> From<&'a edwards::EdwardsPoint> for LookupTable { - fn from(point: &'a edwards::EdwardsPoint) -> Self { - let P = ExtendedPoint::from(*point); - let mut points = [CachedPoint::from(P); 8]; - for i in 0..7 { - points[i + 1] = (&P + &points[i]).into(); - } - LookupTable(points) - } -} - -impl<'a> From<&'a edwards::EdwardsPoint> for NafLookupTable5 { - fn from(point: &'a edwards::EdwardsPoint) -> Self { - let A = ExtendedPoint::from(*point); - let mut Ai = [CachedPoint::from(A); 8]; - let A2 = A.double(); - for i in 0..7 { - Ai[i + 1] = (&A2 + &Ai[i]).into(); - } - // Now Ai = [A, 3A, 5A, 7A, 9A, 11A, 13A, 15A] - NafLookupTable5(Ai) - } -} - -impl<'a> From<&'a edwards::EdwardsPoint> for NafLookupTable8 { - fn from(point: &'a edwards::EdwardsPoint) -> Self { - let A = ExtendedPoint::from(*point); - let mut Ai = [CachedPoint::from(A); 64]; - let A2 = A.double(); - for i in 0..63 { - Ai[i + 1] = (&A2 + &Ai[i]).into(); - } - // Now Ai = [A, 3A, 5A, 7A, 9A, 11A, 13A, 15A, ..., 127A] - NafLookupTable8(Ai) - } -} - -#[cfg(test)] -mod test { - use super::*; - - fn serial_add(P: edwards::EdwardsPoint, Q: edwards::EdwardsPoint) -> edwards::EdwardsPoint { - use backend::serial::u64::field::FieldElement51; - - let (X1, Y1, Z1, T1) = (P.X, P.Y, P.Z, P.T); - let (X2, Y2, Z2, T2) = (Q.X, Q.Y, Q.Z, Q.T); - - macro_rules! print_var { - ($x:ident) => { - println!("{} = {:?}", stringify!($x), $x.to_bytes()); - }; - } - - let S0 = &Y1 - &X1; // R1 - let S1 = &Y1 + &X1; // R3 - let S2 = &Y2 - &X2; // R2 - let S3 = &Y2 + &X2; // R4 - print_var!(S0); - print_var!(S1); - print_var!(S2); - print_var!(S3); - println!(""); - - let S4 = &S0 * &S2; // R5 = R1 * R2 - let S5 = &S1 * &S3; // R6 = R3 * R4 - let S6 = &Z1 * &Z2; // R8 - let S7 = &T1 * &T2; // R7 - print_var!(S4); - print_var!(S5); - print_var!(S6); - print_var!(S7); - println!(""); - - let S8 = &S4 * &FieldElement51([ 121666,0,0,0,0]); // R5 - let S9 = &S5 * &FieldElement51([ 121666,0,0,0,0]); // R6 - let S10 = &S6 * &FieldElement51([2*121666,0,0,0,0]); // R8 - let S11 = &S7 * &(-&FieldElement51([2*121665,0,0,0,0])); // R7 - print_var!(S8); - print_var!(S9); - print_var!(S10); - print_var!(S11); - println!(""); - - let S12 = &S9 - &S8; // R1 - let S13 = &S9 + &S8; // R4 - let S14 = &S10 - &S11; // R2 - let S15 = &S10 + &S11; // R3 - print_var!(S12); - print_var!(S13); - print_var!(S14); - print_var!(S15); - println!(""); - - let X3 = &S12 * &S14; // R1 * R2 - let Y3 = &S15 * &S13; // R3 * R4 - let Z3 = &S15 * &S14; // R2 * R3 - let T3 = &S12 * &S13; // R1 * R4 - - edwards::EdwardsPoint { - X: X3, - Y: Y3, - Z: Z3, - T: T3, - } - } - - fn addition_test_helper(P: edwards::EdwardsPoint, Q: edwards::EdwardsPoint) { - // Test the serial implementation of the parallel addition formulas - let R_serial: edwards::EdwardsPoint = serial_add(P.into(), Q.into()).into(); - - // Test the vector implementation of the parallel readdition formulas - let cached_Q = CachedPoint::from(ExtendedPoint::from(Q)); - let R_vector: edwards::EdwardsPoint = (&ExtendedPoint::from(P) + &cached_Q).into(); - let S_vector: edwards::EdwardsPoint = (&ExtendedPoint::from(P) - &cached_Q).into(); - - println!("Testing point addition:"); - println!("P = {:?}", P); - println!("Q = {:?}", Q); - println!("cached Q = {:?}", cached_Q); - println!("R = P + Q = {:?}", &P + &Q); - println!("R_serial = {:?}", R_serial); - println!("R_vector = {:?}", R_vector); - println!("S = P - Q = {:?}", &P - &Q); - println!("S_vector = {:?}", S_vector); - assert_eq!(R_serial.compress(), (&P + &Q).compress()); - assert_eq!(R_vector.compress(), (&P + &Q).compress()); - assert_eq!(S_vector.compress(), (&P - &Q).compress()); - println!("OK!\n"); - } - - #[test] - fn vector_addition_vs_serial_addition_vs_edwards_extendedpoint() { - use constants; - use scalar::Scalar; - - println!("Testing id +- id"); - let P = edwards::EdwardsPoint::identity(); - let Q = edwards::EdwardsPoint::identity(); - addition_test_helper(P, Q); - - println!("Testing id +- B"); - let P = edwards::EdwardsPoint::identity(); - let Q = constants::ED25519_BASEPOINT_POINT; - addition_test_helper(P, Q); - - println!("Testing B +- B"); - let P = constants::ED25519_BASEPOINT_POINT; - let Q = constants::ED25519_BASEPOINT_POINT; - addition_test_helper(P, Q); - - println!("Testing B +- kB"); - let P = constants::ED25519_BASEPOINT_POINT; - let Q = &constants::ED25519_BASEPOINT_TABLE * &Scalar::from(8475983829u64); - addition_test_helper(P, Q); - } - - fn serial_double(P: edwards::EdwardsPoint) -> edwards::EdwardsPoint { - let (X1, Y1, Z1, _T1) = (P.X, P.Y, P.Z, P.T); - - macro_rules! print_var { - ($x:ident) => { - println!("{} = {:?}", stringify!($x), $x.to_bytes()); - }; - } - - let S0 = &X1 + &Y1; // R1 - print_var!(S0); - println!(""); - - let S1 = X1.square(); - let S2 = Y1.square(); - let S3 = Z1.square(); - let S4 = S0.square(); - print_var!(S1); - print_var!(S2); - print_var!(S3); - print_var!(S4); - println!(""); - - let S5 = &S1 + &S2; - let S6 = &S1 - &S2; - let S7 = &S3 + &S3; - let S8 = &S7 + &S6; - let S9 = &S5 - &S4; - print_var!(S5); - print_var!(S6); - print_var!(S7); - print_var!(S8); - print_var!(S9); - println!(""); - - let X3 = &S8 * &S9; - let Y3 = &S5 * &S6; - let Z3 = &S8 * &S6; - let T3 = &S5 * &S9; - - edwards::EdwardsPoint { - X: X3, - Y: Y3, - Z: Z3, - T: T3, - } - } - - fn doubling_test_helper(P: edwards::EdwardsPoint) { - let R1: edwards::EdwardsPoint = serial_double(P.into()).into(); - let R2: edwards::EdwardsPoint = ExtendedPoint::from(P).double().into(); - println!("Testing point doubling:"); - println!("P = {:?}", P); - println!("(serial) R1 = {:?}", R1); - println!("(vector) R2 = {:?}", R2); - println!("P + P = {:?}", &P + &P); - assert_eq!(R1.compress(), (&P + &P).compress()); - assert_eq!(R2.compress(), (&P + &P).compress()); - println!("OK!\n"); - } - - #[test] - fn vector_doubling_vs_serial_doubling_vs_edwards_extendedpoint() { - use constants; - use scalar::Scalar; - - println!("Testing [2]id"); - let P = edwards::EdwardsPoint::identity(); - doubling_test_helper(P); - - println!("Testing [2]B"); - let P = constants::ED25519_BASEPOINT_POINT; - doubling_test_helper(P); - - println!("Testing [2]([k]B)"); - let P = &constants::ED25519_BASEPOINT_TABLE * &Scalar::from(8475983829u64); - doubling_test_helper(P); - } -} diff --git a/net/gurk-rs/files/vendor/curve25519-dalek-2.0.0/src/backend/vector/avx2/field.rs b/net/gurk-rs/files/vendor/curve25519-dalek-2.0.0/src/backend/vector/avx2/field.rs deleted file mode 100644 index edd1fa6..0000000 --- a/net/gurk-rs/files/vendor/curve25519-dalek-2.0.0/src/backend/vector/avx2/field.rs +++ /dev/null @@ -1,985 +0,0 @@ -// -*- mode: rust; coding: utf-8; -*- -// -// This file is part of curve25519-dalek. -// Copyright (c) 2016-2019 Isis Lovecruft, Henry de Valence -// See LICENSE for licensing information. -// -// Authors: -// - Isis Agora Lovecruft -// - Henry de Valence - -//! An implementation of 4-way vectorized 32bit field arithmetic using -//! AVX2. -//! -//! The `FieldElement2625x4` struct provides a vector of four field -//! elements, implemented using AVX2 operations. Its API is designed -//! to abstract away the platform-dependent details, so that point -//! arithmetic can be implemented only in terms of a vector of field -//! elements. -//! -//! At this level, the API is optimized for speed and not safety. The -//! `FieldElement2625x4` does not always perform reductions. The pre- -//! and post-conditions on the bounds of the coefficients are -//! documented for each method, but it is the caller's responsibility -//! to ensure that there are no overflows. - -#![allow(non_snake_case)] - -const A_LANES: u8 = 0b0000_0101; -const B_LANES: u8 = 0b0000_1010; -const C_LANES: u8 = 0b0101_0000; -const D_LANES: u8 = 0b1010_0000; - -#[allow(unused)] -const A_LANES64: u8 = 0b00_00_00_11; -#[allow(unused)] -const B_LANES64: u8 = 0b00_00_11_00; -#[allow(unused)] -const C_LANES64: u8 = 0b00_11_00_00; -#[allow(unused)] -const D_LANES64: u8 = 0b11_00_00_00; - -use core::ops::{Add, Mul, Neg}; -use packed_simd::{i32x8, u32x8, u64x4, IntoBits}; - -use backend::vector::avx2::constants::{P_TIMES_16_HI, P_TIMES_16_LO, P_TIMES_2_HI, P_TIMES_2_LO}; -use backend::serial::u64::field::FieldElement51; - -/// Unpack 32-bit lanes into 64-bit lanes: -/// ```ascii,no_run -/// (a0, b0, a1, b1, c0, d0, c1, d1) -/// ``` -/// into -/// ```ascii,no_run -/// (a0, 0, b0, 0, c0, 0, d0, 0) -/// (a1, 0, b1, 0, c1, 0, d1, 0) -/// ``` -#[inline(always)] -fn unpack_pair(src: u32x8) -> (u32x8, u32x8) { - let a: u32x8; - let b: u32x8; - let zero = i32x8::new(0, 0, 0, 0, 0, 0, 0, 0); - unsafe { - use core::arch::x86_64::_mm256_unpackhi_epi32; - use core::arch::x86_64::_mm256_unpacklo_epi32; - a = _mm256_unpacklo_epi32(src.into_bits(), zero.into_bits()).into_bits(); - b = _mm256_unpackhi_epi32(src.into_bits(), zero.into_bits()).into_bits(); - } - (a, b) -} - -/// Repack 64-bit lanes into 32-bit lanes: -/// ```ascii,no_run -/// (a0, 0, b0, 0, c0, 0, d0, 0) -/// (a1, 0, b1, 0, c1, 0, d1, 0) -/// ``` -/// into -/// ```ascii,no_run -/// (a0, b0, a1, b1, c0, d0, c1, d1) -/// ``` -#[inline(always)] -fn repack_pair(x: u32x8, y: u32x8) -> u32x8 { - unsafe { - use core::arch::x86_64::_mm256_blend_epi32; - use core::arch::x86_64::_mm256_shuffle_epi32; - - // Input: x = (a0, 0, b0, 0, c0, 0, d0, 0) - // Input: y = (a1, 0, b1, 0, c1, 0, d1, 0) - - let x_shuffled = _mm256_shuffle_epi32(x.into_bits(), 0b11_01_10_00); - let y_shuffled = _mm256_shuffle_epi32(y.into_bits(), 0b10_00_11_01); - - // x' = (a0, b0, 0, 0, c0, d0, 0, 0) - // y' = ( 0, 0, a1, b1, 0, 0, c1, d1) - - return _mm256_blend_epi32(x_shuffled, y_shuffled, 0b11001100).into_bits(); - } -} - -/// The `Lanes` enum represents a subset of the lanes `A,B,C,D` of a -/// `FieldElement2625x4`. -/// -/// It's used to specify blend operations without -/// having to know details about the data layout of the -/// `FieldElement2625x4`. -#[derive(Copy, Clone, Debug)] -pub enum Lanes { - C, - D, - AB, - AC, - CD, - AD, - BC, - ABCD, -} - -/// The `Shuffle` enum represents a shuffle of a `FieldElement2625x4`. -/// -/// The enum variants are named by what they do to a vector \\( -/// (A,B,C,D) \\); for instance, `Shuffle::BADC` turns \\( (A, B, C, -/// D) \\) into \\( (B, A, D, C) \\). -#[derive(Copy, Clone, Debug)] -pub enum Shuffle { - AAAA, - BBBB, - CACA, - DBBD, - ADDA, - CBCB, - ABAB, - BADC, - BACD, - ABDC, -} - -/// A vector of four field elements. -/// -/// Each operation on a `FieldElement2625x4` has documented effects on -/// the bounds of the coefficients. This API is designed for speed -/// and not safety; it is the caller's responsibility to ensure that -/// the post-conditions of one operation are compatible with the -/// pre-conditions of the next. -#[derive(Clone, Copy, Debug)] -pub struct FieldElement2625x4(pub(crate) [u32x8; 5]); - -use subtle::Choice; -use subtle::ConditionallySelectable; - -impl ConditionallySelectable for FieldElement2625x4 { - fn conditional_select( - a: &FieldElement2625x4, - b: &FieldElement2625x4, - choice: Choice, - ) -> FieldElement2625x4 { - let mask = (-(choice.unwrap_u8() as i32)) as u32; - let mask_vec = u32x8::splat(mask); - FieldElement2625x4([ - a.0[0] ^ (mask_vec & (a.0[0] ^ b.0[0])), - a.0[1] ^ (mask_vec & (a.0[1] ^ b.0[1])), - a.0[2] ^ (mask_vec & (a.0[2] ^ b.0[2])), - a.0[3] ^ (mask_vec & (a.0[3] ^ b.0[3])), - a.0[4] ^ (mask_vec & (a.0[4] ^ b.0[4])), - ]) - } - - fn conditional_assign( - &mut self, - other: &FieldElement2625x4, - choice: Choice, - ) { - let mask = (-(choice.unwrap_u8() as i32)) as u32; - let mask_vec = u32x8::splat(mask); - self.0[0] ^= mask_vec & (self.0[0] ^ other.0[0]); - self.0[1] ^= mask_vec & (self.0[1] ^ other.0[1]); - self.0[2] ^= mask_vec & (self.0[2] ^ other.0[2]); - self.0[3] ^= mask_vec & (self.0[3] ^ other.0[3]); - self.0[4] ^= mask_vec & (self.0[4] ^ other.0[4]); - } -} - -impl FieldElement2625x4 { - /// Split this vector into an array of four (serial) field - /// elements. - pub fn split(&self) -> [FieldElement51; 4] { - let mut out = [FieldElement51::zero(); 4]; - for i in 0..5 { - let a_2i = self.0[i].extract(0) as u64; // - let b_2i = self.0[i].extract(1) as u64; // - let a_2i_1 = self.0[i].extract(2) as u64; // `. - let b_2i_1 = self.0[i].extract(3) as u64; // | pre-swapped to avoid - let c_2i = self.0[i].extract(4) as u64; // | a cross lane shuffle - let d_2i = self.0[i].extract(5) as u64; // .' - let c_2i_1 = self.0[i].extract(6) as u64; // - let d_2i_1 = self.0[i].extract(7) as u64; // - - out[0].0[i] = a_2i + (a_2i_1 << 26); - out[1].0[i] = b_2i + (b_2i_1 << 26); - out[2].0[i] = c_2i + (c_2i_1 << 26); - out[3].0[i] = d_2i + (d_2i_1 << 26); - } - - out - } - - /// Rearrange the elements of this vector according to `control`. - /// - /// The `control` parameter should be a compile-time constant, so - /// that when this function is inlined, LLVM is able to lower the - /// shuffle using an immediate. - #[inline] - pub fn shuffle(&self, control: Shuffle) -> FieldElement2625x4 { - #[inline(always)] - fn shuffle_lanes(x: u32x8, control: Shuffle) -> u32x8 { - unsafe { - use core::arch::x86_64::_mm256_permutevar8x32_epi32; - - let c: u32x8 = match control { - Shuffle::AAAA => u32x8::new(0, 0, 2, 2, 0, 0, 2, 2), - Shuffle::BBBB => u32x8::new(1, 1, 3, 3, 1, 1, 3, 3), - Shuffle::CACA => u32x8::new(4, 0, 6, 2, 4, 0, 6, 2), - Shuffle::DBBD => u32x8::new(5, 1, 7, 3, 1, 5, 3, 7), - Shuffle::ADDA => u32x8::new(0, 5, 2, 7, 5, 0, 7, 2), - Shuffle::CBCB => u32x8::new(4, 1, 6, 3, 4, 1, 6, 3), - Shuffle::ABAB => u32x8::new(0, 1, 2, 3, 0, 1, 2, 3), - Shuffle::BADC => u32x8::new(1, 0, 3, 2, 5, 4, 7, 6), - Shuffle::BACD => u32x8::new(1, 0, 3, 2, 4, 5, 6, 7), - Shuffle::ABDC => u32x8::new(0, 1, 2, 3, 5, 4, 7, 6), - }; - // Note that this gets turned into a generic LLVM - // shuffle-by-constants, which can be lowered to a simpler - // instruction than a generic permute. - _mm256_permutevar8x32_epi32(x.into_bits(), c.into_bits()).into_bits() - } - } - - FieldElement2625x4([ - shuffle_lanes(self.0[0], control), - shuffle_lanes(self.0[1], control), - shuffle_lanes(self.0[2], control), - shuffle_lanes(self.0[3], control), - shuffle_lanes(self.0[4], control), - ]) - } - - /// Blend `self` with `other`, taking lanes specified in `control` from `other`. - /// - /// The `control` parameter should be a compile-time constant, so - /// that this function can be inlined and LLVM can lower it to a - /// blend instruction using an immediate. - #[inline] - pub fn blend(&self, other: FieldElement2625x4, control: Lanes) -> FieldElement2625x4 { - #[inline(always)] - fn blend_lanes(x: u32x8, y: u32x8, control: Lanes) -> u32x8 { - unsafe { - use core::arch::x86_64::_mm256_blend_epi32; - - // This would be much cleaner if we could factor out the match - // statement on the control. Unfortunately, rustc forgets - // constant-info very quickly, so we can't even write - // ``` - // match control { - // Lanes::C => { - // let imm = C_LANES as i32; - // _mm256_blend_epi32(..., imm) - // ``` - // let alone - // ``` - // let imm = match control { - // Lanes::C => C_LANES as i32, - // } - // _mm256_blend_epi32(..., imm) - // ``` - // even though both of these would be constant-folded by LLVM - // at a lower level (as happens in the shuffle implementation, - // which does not require a shuffle immediate but *is* lowered - // to immediate shuffles anyways). - match control { - Lanes::C => { - _mm256_blend_epi32(x.into_bits(), y.into_bits(), C_LANES as i32).into_bits() - } - Lanes::D => { - _mm256_blend_epi32(x.into_bits(), y.into_bits(), D_LANES as i32).into_bits() - } - Lanes::AD => { - _mm256_blend_epi32(x.into_bits(), y.into_bits(), (A_LANES | D_LANES) as i32) - .into_bits() - } - Lanes::AB => { - _mm256_blend_epi32(x.into_bits(), y.into_bits(), (A_LANES | B_LANES) as i32) - .into_bits() - } - Lanes::AC => { - _mm256_blend_epi32(x.into_bits(), y.into_bits(), (A_LANES | C_LANES) as i32) - .into_bits() - } - Lanes::CD => { - _mm256_blend_epi32(x.into_bits(), y.into_bits(), (C_LANES | D_LANES) as i32) - .into_bits() - } - Lanes::BC => { - _mm256_blend_epi32(x.into_bits(), y.into_bits(), (B_LANES | C_LANES) as i32) - .into_bits() - } - Lanes::ABCD => _mm256_blend_epi32( - x.into_bits(), - y.into_bits(), - (A_LANES | B_LANES | C_LANES | D_LANES) as i32, - ).into_bits(), - } - } - } - - FieldElement2625x4([ - blend_lanes(self.0[0], other.0[0], control), - blend_lanes(self.0[1], other.0[1], control), - blend_lanes(self.0[2], other.0[2], control), - blend_lanes(self.0[3], other.0[3], control), - blend_lanes(self.0[4], other.0[4], control), - ]) - } - - /// Construct a vector of zeros. - pub fn zero() -> FieldElement2625x4 { - FieldElement2625x4([u32x8::splat(0); 5]) - } - - /// Convenience wrapper around `new(x,x,x,x)`. - pub fn splat(x: &FieldElement51) -> FieldElement2625x4 { - FieldElement2625x4::new(x, x, x, x) - } - - /// Create a `FieldElement2625x4` from four `FieldElement51`s. - /// - /// # Postconditions - /// - /// The resulting `FieldElement2625x4` is bounded with \\( b < 0.0002 \\). - pub fn new( - x0: &FieldElement51, - x1: &FieldElement51, - x2: &FieldElement51, - x3: &FieldElement51, - ) -> FieldElement2625x4 { - let mut buf = [u32x8::splat(0); 5]; - let low_26_bits = (1 << 26) - 1; - for i in 0..5 { - let a_2i = (x0.0[i] & low_26_bits) as u32; - let a_2i_1 = (x0.0[i] >> 26) as u32; - let b_2i = (x1.0[i] & low_26_bits) as u32; - let b_2i_1 = (x1.0[i] >> 26) as u32; - let c_2i = (x2.0[i] & low_26_bits) as u32; - let c_2i_1 = (x2.0[i] >> 26) as u32; - let d_2i = (x3.0[i] & low_26_bits) as u32; - let d_2i_1 = (x3.0[i] >> 26) as u32; - - buf[i] = u32x8::new(a_2i, b_2i, a_2i_1, b_2i_1, c_2i, d_2i, c_2i_1, d_2i_1); - } - - // We don't know that the original `FieldElement51`s were - // fully reduced, so the odd limbs may exceed 2^25. - // Reduce them to be sure. - FieldElement2625x4(buf).reduce() - } - - /// Given \\((A,B,C,D)\\), compute \\((-A,-B,-C,-D)\\), without - /// performing a reduction. - /// - /// # Preconditions - /// - /// The coefficients of `self` must be bounded with \\( b < 0.999 \\). - /// - /// # Postconditions - /// - /// The coefficients of the result are bounded with \\( b < 1 \\). - #[inline] - pub fn negate_lazy(&self) -> FieldElement2625x4 { - // The limbs of self are bounded with b < 0.999, while the - // smallest limb of 2*p is 67108845 > 2^{26+0.9999}, so - // underflows are not possible. - FieldElement2625x4([ - P_TIMES_2_LO - self.0[0], - P_TIMES_2_HI - self.0[1], - P_TIMES_2_HI - self.0[2], - P_TIMES_2_HI - self.0[3], - P_TIMES_2_HI - self.0[4], - ]) - } - - /// Given `self = (A,B,C,D)`, compute `(B - A, B + A, D - C, D + C)`. - /// - /// # Preconditions - /// - /// The coefficients of `self` must be bounded with \\( b < 0.01 \\). - /// - /// # Postconditions - /// - /// The coefficients of the result are bounded with \\( b < 1.6 \\). - #[inline] - pub fn diff_sum(&self) -> FieldElement2625x4 { - // tmp1 = (B, A, D, C) - let tmp1 = self.shuffle(Shuffle::BADC); - // tmp2 = (-A, B, -C, D) - let tmp2 = self.blend(self.negate_lazy(), Lanes::AC); - // (B - A, B + A, D - C, D + C) bounded with b < 1.6 - tmp1 + tmp2 - } - - /// Reduce this vector of field elements \\(\mathrm{mod} p\\). - /// - /// # Postconditions - /// - /// The coefficients of the result are bounded with \\( b < 0.0002 \\). - #[inline] - pub fn reduce(&self) -> FieldElement2625x4 { - let shifts = i32x8::new(26, 26, 25, 25, 26, 26, 25, 25); - let masks = u32x8::new( - (1 << 26) - 1, - (1 << 26) - 1, - (1 << 25) - 1, - (1 << 25) - 1, - (1 << 26) - 1, - (1 << 26) - 1, - (1 << 25) - 1, - (1 << 25) - 1, - ); - - // Let c(x) denote the carryout of the coefficient x. - // - // Given ( x0, y0, x1, y1, z0, w0, z1, w1), - // compute (c(x1), c(y1), c(x0), c(y0), c(z1), c(w1), c(z0), c(w0)). - // - // The carryouts are bounded by 2^(32 - 25) = 2^7. - let rotated_carryout = |v: u32x8| -> u32x8 { - unsafe { - use core::arch::x86_64::_mm256_srlv_epi32; - use core::arch::x86_64::_mm256_shuffle_epi32; - - let c = _mm256_srlv_epi32(v.into_bits(), shifts.into_bits()); - _mm256_shuffle_epi32(c, 0b01_00_11_10).into_bits() - } - }; - - // Combine (lo, lo, lo, lo, lo, lo, lo, lo) - // with (hi, hi, hi, hi, hi, hi, hi, hi) - // to (lo, lo, hi, hi, lo, lo, hi, hi) - // - // This allows combining carryouts, e.g., - // - // lo (c(x1), c(y1), c(x0), c(y0), c(z1), c(w1), c(z0), c(w0)) - // hi (c(x3), c(y3), c(x2), c(y2), c(z3), c(w3), c(z2), c(w2)) - // -> (c(x1), c(y1), c(x2), c(y2), c(z1), c(w1), c(z2), c(w2)) - // - // which is exactly the vector of carryins for - // - // ( x2, y2, x3, y3, z2, w2, z3, w3). - // - let combine = |v_lo: u32x8, v_hi: u32x8| -> u32x8 { - unsafe { - use core::arch::x86_64::_mm256_blend_epi32; - _mm256_blend_epi32(v_lo.into_bits(), v_hi.into_bits(), 0b11_00_11_00).into_bits() - } - }; - - let mut v = self.0; - - let c10 = rotated_carryout(v[0]); - v[0] = (v[0] & masks) + combine(u32x8::splat(0), c10); - - let c32 = rotated_carryout(v[1]); - v[1] = (v[1] & masks) + combine(c10, c32); - - let c54 = rotated_carryout(v[2]); - v[2] = (v[2] & masks) + combine(c32, c54); - - let c76 = rotated_carryout(v[3]); - v[3] = (v[3] & masks) + combine(c54, c76); - - let c98 = rotated_carryout(v[4]); - v[4] = (v[4] & masks) + combine(c76, c98); - - let c9_19: u32x8 = unsafe { - use core::arch::x86_64::_mm256_mul_epu32; - use core::arch::x86_64::_mm256_shuffle_epi32; - - // Need to rearrange c98, since vpmuludq uses the low - // 32-bits of each 64-bit lane to compute the product: - // - // c98 = (c(x9), c(y9), c(x8), c(y8), c(z9), c(w9), c(z8), c(w8)); - // c9_spread = (c(x9), c(x8), c(y9), c(y8), c(z9), c(z8), c(w9), c(w8)). - let c9_spread = _mm256_shuffle_epi32(c98.into_bits(), 0b11_01_10_00); - - // Since the carryouts are bounded by 2^7, their products with 19 - // are bounded by 2^11.25. This means that - // - // c9_19_spread = (19*c(x9), 0, 19*c(y9), 0, 19*c(z9), 0, 19*c(w9), 0). - let c9_19_spread = _mm256_mul_epu32(c9_spread, u64x4::splat(19).into_bits()); - - // Unshuffle: - // c9_19 = (19*c(x9), 19*c(y9), 0, 0, 19*c(z9), 19*c(w9), 0, 0). - _mm256_shuffle_epi32(c9_19_spread, 0b11_01_10_00).into_bits() - }; - - // Add the final carryin. - v[0] = v[0] + c9_19; - - // Each output coefficient has exactly one carryin, which is - // bounded by 2^11.25, so they are bounded as - // - // c_even < 2^26 + 2^11.25 < 26.00006 < 2^{26+b} - // c_odd < 2^25 + 2^11.25 < 25.0001 < 2^{25+b} - // - // where b = 0.0002. - FieldElement2625x4(v) - } - - /// Given an array of wide coefficients, reduce them to a `FieldElement2625x4`. - /// - /// # Postconditions - /// - /// The coefficients of the result are bounded with \\( b < 0.007 \\). - #[inline] - fn reduce64(mut z: [u64x4; 10]) -> FieldElement2625x4 { - // These aren't const because splat isn't a const fn - let LOW_25_BITS: u64x4 = u64x4::splat((1 << 25) - 1); - let LOW_26_BITS: u64x4 = u64x4::splat((1 << 26) - 1); - - // Carry the value from limb i = 0..8 to limb i+1 - let carry = |z: &mut [u64x4; 10], i: usize| { - debug_assert!(i < 9); - if i % 2 == 0 { - // Even limbs have 26 bits - z[i + 1] = z[i + 1] + (z[i] >> 26); - z[i] = z[i] & LOW_26_BITS; - } else { - // Odd limbs have 25 bits - z[i + 1] = z[i + 1] + (z[i] >> 25); - z[i] = z[i] & LOW_25_BITS; - } - }; - - // Perform two halves of the carry chain in parallel. - carry(&mut z, 0); carry(&mut z, 4); - carry(&mut z, 1); carry(&mut z, 5); - carry(&mut z, 2); carry(&mut z, 6); - carry(&mut z, 3); carry(&mut z, 7); - // Since z[3] < 2^64, c < 2^(64-25) = 2^39, - // so z[4] < 2^26 + 2^39 < 2^39.0002 - carry(&mut z, 4); carry(&mut z, 8); - // Now z[4] < 2^26 - // and z[5] < 2^25 + 2^13.0002 < 2^25.0004 (good enough) - - // Last carry has a multiplication by 19. In the serial case we - // do a 64-bit multiplication by 19, but here we want to do a - // 32-bit multiplication. However, if we only know z[9] < 2^64, - // the carry is bounded as c < 2^(64-25) = 2^39, which is too - // big. To ensure c < 2^32, we would need z[9] < 2^57. - // Instead, we split the carry in two, with c = c_0 + c_1*2^26. - - let c = z[9] >> 25; - z[9] = z[9] & LOW_25_BITS; - let mut c0: u64x4 = c & LOW_26_BITS; // c0 < 2^26; - let mut c1: u64x4 = c >> 26; // c1 < 2^(39-26) = 2^13; - - unsafe { - use core::arch::x86_64::_mm256_mul_epu32; - let x19 = u64x4::splat(19); - c0 = _mm256_mul_epu32(c0.into_bits(), x19.into_bits()).into_bits(); // c0 < 2^30.25 - c1 = _mm256_mul_epu32(c1.into_bits(), x19.into_bits()).into_bits(); // c1 < 2^17.25 - } - - z[0] = z[0] + c0; // z0 < 2^26 + 2^30.25 < 2^30.33 - z[1] = z[1] + c1; // z1 < 2^25 + 2^17.25 < 2^25.0067 - carry(&mut z, 0); // z0 < 2^26, z1 < 2^25.0067 + 2^4.33 = 2^25.007 - - // The output coefficients are bounded with - // - // b = 0.007 for z[1] - // b = 0.0004 for z[5] - // b = 0 for other z[i]. - // - // So the packed result is bounded with b = 0.007. - FieldElement2625x4([ - repack_pair(z[0].into_bits(), z[1].into_bits()), - repack_pair(z[2].into_bits(), z[3].into_bits()), - repack_pair(z[4].into_bits(), z[5].into_bits()), - repack_pair(z[6].into_bits(), z[7].into_bits()), - repack_pair(z[8].into_bits(), z[9].into_bits()), - ]) - } - - /// Square this field element, and negate the result's \\(D\\) value. - /// - /// # Preconditions - /// - /// The coefficients of `self` must be bounded with \\( b < 1.5 \\). - /// - /// # Postconditions - /// - /// The coefficients of the result are bounded with \\( b < 0.007 \\). - pub fn square_and_negate_D(&self) -> FieldElement2625x4 { - #[inline(always)] - fn m(x: u32x8, y: u32x8) -> u64x4 { - use core::arch::x86_64::_mm256_mul_epu32; - unsafe { _mm256_mul_epu32(x.into_bits(), y.into_bits()).into_bits() } - } - - #[inline(always)] - fn m_lo(x: u32x8, y: u32x8) -> u32x8 { - use core::arch::x86_64::_mm256_mul_epu32; - unsafe { _mm256_mul_epu32(x.into_bits(), y.into_bits()).into_bits() } - } - - let v19 = u32x8::new(19, 0, 19, 0, 19, 0, 19, 0); - - let (x0, x1) = unpack_pair(self.0[0]); - let (x2, x3) = unpack_pair(self.0[1]); - let (x4, x5) = unpack_pair(self.0[2]); - let (x6, x7) = unpack_pair(self.0[3]); - let (x8, x9) = unpack_pair(self.0[4]); - - let x0_2 = x0 << 1; - let x1_2 = x1 << 1; - let x2_2 = x2 << 1; - let x3_2 = x3 << 1; - let x4_2 = x4 << 1; - let x5_2 = x5 << 1; - let x6_2 = x6 << 1; - let x7_2 = x7 << 1; - - let x5_19 = m_lo(v19, x5); - let x6_19 = m_lo(v19, x6); - let x7_19 = m_lo(v19, x7); - let x8_19 = m_lo(v19, x8); - let x9_19 = m_lo(v19, x9); - - let mut z0 = m(x0, x0) + m(x2_2,x8_19) + m(x4_2,x6_19) + ((m(x1_2,x9_19) + m(x3_2,x7_19) + m(x5,x5_19)) << 1); - let mut z1 = m(x0_2,x1) + m(x3_2,x8_19) + m(x5_2,x6_19) + ((m(x2,x9_19) + m(x4,x7_19)) << 1); - let mut z2 = m(x0_2,x2) + m(x1_2,x1) + m(x4_2,x8_19) + m(x6,x6_19) + ((m(x3_2,x9_19) + m(x5_2,x7_19)) << 1); - let mut z3 = m(x0_2,x3) + m(x1_2,x2) + m(x5_2,x8_19) + ((m(x4,x9_19) + m(x6,x7_19)) << 1); - let mut z4 = m(x0_2,x4) + m(x1_2,x3_2) + m(x2, x2) + m(x6_2,x8_19) + ((m(x5_2,x9_19) + m(x7,x7_19)) << 1); - let mut z5 = m(x0_2,x5) + m(x1_2,x4) + m(x2_2,x3) + m(x7_2,x8_19) + ((m(x6,x9_19)) << 1); - let mut z6 = m(x0_2,x6) + m(x1_2,x5_2) + m(x2_2,x4) + m(x3_2,x3) + m(x8,x8_19) + ((m(x7_2,x9_19)) << 1); - let mut z7 = m(x0_2,x7) + m(x1_2,x6) + m(x2_2,x5) + m(x3_2,x4) + ((m(x8,x9_19)) << 1); - let mut z8 = m(x0_2,x8) + m(x1_2,x7_2) + m(x2_2,x6) + m(x3_2,x5_2) + m(x4,x4) + ((m(x9,x9_19)) << 1); - let mut z9 = m(x0_2,x9) + m(x1_2,x8) + m(x2_2,x7) + m(x3_2,x6) + m(x4_2,x5); - - // The biggest z_i is bounded as z_i < 249*2^(51 + 2*b); - // if b < 1.5 we get z_i < 4485585228861014016. - // - // The limbs of the multiples of p are bounded above by - // - // 0x3fffffff << 37 = 9223371899415822336 < 2^63 - // - // and below by - // - // 0x1fffffff << 37 = 4611685880988434432 - // > 4485585228861014016 - // - // So these multiples of p are big enough to avoid underflow - // in subtraction, and small enough to fit within u64 - // with room for a carry. - - let low__p37 = u64x4::splat(0x3ffffed << 37); - let even_p37 = u64x4::splat(0x3ffffff << 37); - let odd__p37 = u64x4::splat(0x1ffffff << 37); - - let negate_D = |x: u64x4, p: u64x4| -> u64x4 { - unsafe { - use core::arch::x86_64::_mm256_blend_epi32; - _mm256_blend_epi32(x.into_bits(), (p - x).into_bits(), D_LANES64 as i32).into_bits() - } - }; - - z0 = negate_D(z0, low__p37); - z1 = negate_D(z1, odd__p37); - z2 = negate_D(z2, even_p37); - z3 = negate_D(z3, odd__p37); - z4 = negate_D(z4, even_p37); - z5 = negate_D(z5, odd__p37); - z6 = negate_D(z6, even_p37); - z7 = negate_D(z7, odd__p37); - z8 = negate_D(z8, even_p37); - z9 = negate_D(z9, odd__p37); - - FieldElement2625x4::reduce64([z0, z1, z2, z3, z4, z5, z6, z7, z8, z9]) - } -} - -impl Neg for FieldElement2625x4 { - type Output = FieldElement2625x4; - - /// Negate this field element, performing a reduction. - /// - /// If the coefficients are known to be small, use `negate_lazy` - /// to avoid performing a reduction. - /// - /// # Preconditions - /// - /// The coefficients of `self` must be bounded with \\( b < 4.0 \\). - /// - /// # Postconditions - /// - /// The coefficients of the result are bounded with \\( b < 0.0002 \\). - #[inline] - fn neg(self) -> FieldElement2625x4 { - FieldElement2625x4([ - P_TIMES_16_LO - self.0[0], - P_TIMES_16_HI - self.0[1], - P_TIMES_16_HI - self.0[2], - P_TIMES_16_HI - self.0[3], - P_TIMES_16_HI - self.0[4], - ]).reduce() - } -} - -impl Add for FieldElement2625x4 { - type Output = FieldElement2625x4; - /// Add two `FieldElement2625x4`s, without performing a reduction. - #[inline] - fn add(self, rhs: FieldElement2625x4) -> FieldElement2625x4 { - FieldElement2625x4([ - self.0[0] + rhs.0[0], - self.0[1] + rhs.0[1], - self.0[2] + rhs.0[2], - self.0[3] + rhs.0[3], - self.0[4] + rhs.0[4], - ]) - } -} - -impl Mul<(u32, u32, u32, u32)> for FieldElement2625x4 { - type Output = FieldElement2625x4; - /// Perform a multiplication by a vector of small constants. - /// - /// # Postconditions - /// - /// The coefficients of the result are bounded with \\( b < 0.007 \\). - #[inline] - fn mul(self, scalars: (u32, u32, u32, u32)) -> FieldElement2625x4 { - unsafe { - use core::arch::x86_64::_mm256_mul_epu32; - - let consts = u32x8::new(scalars.0, 0, scalars.1, 0, scalars.2, 0, scalars.3, 0); - - let (b0, b1) = unpack_pair(self.0[0]); - let (b2, b3) = unpack_pair(self.0[1]); - let (b4, b5) = unpack_pair(self.0[2]); - let (b6, b7) = unpack_pair(self.0[3]); - let (b8, b9) = unpack_pair(self.0[4]); - - FieldElement2625x4::reduce64([ - _mm256_mul_epu32(b0.into_bits(), consts.into_bits()).into_bits(), - _mm256_mul_epu32(b1.into_bits(), consts.into_bits()).into_bits(), - _mm256_mul_epu32(b2.into_bits(), consts.into_bits()).into_bits(), - _mm256_mul_epu32(b3.into_bits(), consts.into_bits()).into_bits(), - _mm256_mul_epu32(b4.into_bits(), consts.into_bits()).into_bits(), - _mm256_mul_epu32(b5.into_bits(), consts.into_bits()).into_bits(), - _mm256_mul_epu32(b6.into_bits(), consts.into_bits()).into_bits(), - _mm256_mul_epu32(b7.into_bits(), consts.into_bits()).into_bits(), - _mm256_mul_epu32(b8.into_bits(), consts.into_bits()).into_bits(), - _mm256_mul_epu32(b9.into_bits(), consts.into_bits()).into_bits(), - ]) - } - } -} - -impl<'a, 'b> Mul<&'b FieldElement2625x4> for &'a FieldElement2625x4 { - type Output = FieldElement2625x4; - /// Multiply `self` by `rhs`. - /// - /// # Preconditions - /// - /// The coefficients of `self` must be bounded with \\( b < 2.5 \\). - /// - /// The coefficients of `rhs` must be bounded with \\( b < 1.75 \\). - /// - /// # Postconditions - /// - /// The coefficients of the result are bounded with \\( b < 0.007 \\). - /// - fn mul(self, rhs: &'b FieldElement2625x4) -> FieldElement2625x4 { - #[inline(always)] - fn m(x: u32x8, y: u32x8) -> u64x4 { - use core::arch::x86_64::_mm256_mul_epu32; - unsafe { _mm256_mul_epu32(x.into_bits(), y.into_bits()).into_bits() } - } - - #[inline(always)] - fn m_lo(x: u32x8, y: u32x8) -> u32x8 { - use core::arch::x86_64::_mm256_mul_epu32; - unsafe { _mm256_mul_epu32(x.into_bits(), y.into_bits()).into_bits() } - } - - let (x0, x1) = unpack_pair(self.0[0]); - let (x2, x3) = unpack_pair(self.0[1]); - let (x4, x5) = unpack_pair(self.0[2]); - let (x6, x7) = unpack_pair(self.0[3]); - let (x8, x9) = unpack_pair(self.0[4]); - - let (y0, y1) = unpack_pair(rhs.0[0]); - let (y2, y3) = unpack_pair(rhs.0[1]); - let (y4, y5) = unpack_pair(rhs.0[2]); - let (y6, y7) = unpack_pair(rhs.0[3]); - let (y8, y9) = unpack_pair(rhs.0[4]); - - let v19 = u32x8::new(19, 0, 19, 0, 19, 0, 19, 0); - - let y1_19 = m_lo(v19, y1); // This fits in a u32 - let y2_19 = m_lo(v19, y2); // iff 26 + b + lg(19) < 32 - let y3_19 = m_lo(v19, y3); // if b < 32 - 26 - 4.248 = 1.752 - let y4_19 = m_lo(v19, y4); - let y5_19 = m_lo(v19, y5); - let y6_19 = m_lo(v19, y6); - let y7_19 = m_lo(v19, y7); - let y8_19 = m_lo(v19, y8); - let y9_19 = m_lo(v19, y9); - - let x1_2 = x1 + x1; // This fits in a u32 iff 25 + b + 1 < 32 - let x3_2 = x3 + x3; // iff b < 6 - let x5_2 = x5 + x5; - let x7_2 = x7 + x7; - let x9_2 = x9 + x9; - - let z0 = m(x0,y0) + m(x1_2,y9_19) + m(x2,y8_19) + m(x3_2,y7_19) + m(x4,y6_19) + m(x5_2,y5_19) + m(x6,y4_19) + m(x7_2,y3_19) + m(x8,y2_19) + m(x9_2,y1_19); - let z1 = m(x0,y1) + m(x1,y0) + m(x2,y9_19) + m(x3,y8_19) + m(x4,y7_19) + m(x5,y6_19) + m(x6,y5_19) + m(x7,y4_19) + m(x8,y3_19) + m(x9,y2_19); - let z2 = m(x0,y2) + m(x1_2,y1) + m(x2,y0) + m(x3_2,y9_19) + m(x4,y8_19) + m(x5_2,y7_19) + m(x6,y6_19) + m(x7_2,y5_19) + m(x8,y4_19) + m(x9_2,y3_19); - let z3 = m(x0,y3) + m(x1,y2) + m(x2,y1) + m(x3,y0) + m(x4,y9_19) + m(x5,y8_19) + m(x6,y7_19) + m(x7,y6_19) + m(x8,y5_19) + m(x9,y4_19); - let z4 = m(x0,y4) + m(x1_2,y3) + m(x2,y2) + m(x3_2,y1) + m(x4,y0) + m(x5_2,y9_19) + m(x6,y8_19) + m(x7_2,y7_19) + m(x8,y6_19) + m(x9_2,y5_19); - let z5 = m(x0,y5) + m(x1,y4) + m(x2,y3) + m(x3,y2) + m(x4,y1) + m(x5,y0) + m(x6,y9_19) + m(x7,y8_19) + m(x8,y7_19) + m(x9,y6_19); - let z6 = m(x0,y6) + m(x1_2,y5) + m(x2,y4) + m(x3_2,y3) + m(x4,y2) + m(x5_2,y1) + m(x6,y0) + m(x7_2,y9_19) + m(x8,y8_19) + m(x9_2,y7_19); - let z7 = m(x0,y7) + m(x1,y6) + m(x2,y5) + m(x3,y4) + m(x4,y3) + m(x5,y2) + m(x6,y1) + m(x7,y0) + m(x8,y9_19) + m(x9,y8_19); - let z8 = m(x0,y8) + m(x1_2,y7) + m(x2,y6) + m(x3_2,y5) + m(x4,y4) + m(x5_2,y3) + m(x6,y2) + m(x7_2,y1) + m(x8,y0) + m(x9_2,y9_19); - let z9 = m(x0,y9) + m(x1,y8) + m(x2,y7) + m(x3,y6) + m(x4,y5) + m(x5,y4) + m(x6,y3) + m(x7,y2) + m(x8,y1) + m(x9,y0); - - // The bounds on z[i] are the same as in the serial 32-bit code - // and the comment below is copied from there: - - // How big is the contribution to z[i+j] from x[i], y[j]? - // - // Using the bounds above, we get: - // - // i even, j even: x[i]*y[j] < 2^(26+b)*2^(26+b) = 2*2^(51+2*b) - // i odd, j even: x[i]*y[j] < 2^(25+b)*2^(26+b) = 1*2^(51+2*b) - // i even, j odd: x[i]*y[j] < 2^(26+b)*2^(25+b) = 1*2^(51+2*b) - // i odd, j odd: 2*x[i]*y[j] < 2*2^(25+b)*2^(25+b) = 1*2^(51+2*b) - // - // We perform inline reduction mod p by replacing 2^255 by 19 - // (since 2^255 - 19 = 0 mod p). This adds a factor of 19, so - // we get the bounds (z0 is the biggest one, but calculated for - // posterity here in case finer estimation is needed later): - // - // z0 < ( 2 + 1*19 + 2*19 + 1*19 + 2*19 + 1*19 + 2*19 + 1*19 + 2*19 + 1*19 )*2^(51 + 2b) = 249*2^(51 + 2*b) - // z1 < ( 1 + 1 + 1*19 + 1*19 + 1*19 + 1*19 + 1*19 + 1*19 + 1*19 + 1*19 )*2^(51 + 2b) = 154*2^(51 + 2*b) - // z2 < ( 2 + 1 + 2 + 1*19 + 2*19 + 1*19 + 2*19 + 1*19 + 2*19 + 1*19 )*2^(51 + 2b) = 195*2^(51 + 2*b) - // z3 < ( 1 + 1 + 1 + 1 + 1*19 + 1*19 + 1*19 + 1*19 + 1*19 + 1*19 )*2^(51 + 2b) = 118*2^(51 + 2*b) - // z4 < ( 2 + 1 + 2 + 1 + 2 + 1*19 + 2*19 + 1*19 + 2*19 + 1*19 )*2^(51 + 2b) = 141*2^(51 + 2*b) - // z5 < ( 1 + 1 + 1 + 1 + 1 + 1 + 1*19 + 1*19 + 1*19 + 1*19 )*2^(51 + 2b) = 82*2^(51 + 2*b) - // z6 < ( 2 + 1 + 2 + 1 + 2 + 1 + 2 + 1*19 + 2*19 + 1*19 )*2^(51 + 2b) = 87*2^(51 + 2*b) - // z7 < ( 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1*19 + 1*19 )*2^(51 + 2b) = 46*2^(51 + 2*b) - // z8 < ( 2 + 1 + 2 + 1 + 2 + 1 + 2 + 1 + 2 + 1*19 )*2^(51 + 2b) = 33*2^(51 + 2*b) - // z9 < ( 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 )*2^(51 + 2b) = 10*2^(51 + 2*b) - // - // So z[0] fits into a u64 if 51 + 2*b + lg(249) < 64 - // if b < 2.5. - - // In fact this bound is slightly sloppy, since it treats both - // inputs x and y as being bounded by the same parameter b, - // while they are in fact bounded by b_x and b_y, and we - // already require that b_y < 1.75 in order to fit the - // multiplications by 19 into a u32. The tighter bound on b_y - // means we could get a tighter bound on the outputs, or a - // looser bound on b_x. - FieldElement2625x4::reduce64([z0, z1, z2, z3, z4, z5, z6, z7, z8, z9]) - } -} - -#[cfg(test)] -mod test { - use super::*; - - #[test] - fn scale_by_curve_constants() { - let mut x = FieldElement2625x4::splat(&FieldElement51::one()); - - x = x * (121666, 121666, 2*121666, 2*121665); - - let xs = x.split(); - assert_eq!(xs[0], FieldElement51([121666, 0, 0, 0, 0])); - assert_eq!(xs[1], FieldElement51([121666, 0, 0, 0, 0])); - assert_eq!(xs[2], FieldElement51([2 * 121666, 0, 0, 0, 0])); - assert_eq!(xs[3], FieldElement51([2 * 121665, 0, 0, 0, 0])); - } - - #[test] - fn diff_sum_vs_serial() { - let x0 = FieldElement51([10000, 10001, 10002, 10003, 10004]); - let x1 = FieldElement51([10100, 10101, 10102, 10103, 10104]); - let x2 = FieldElement51([10200, 10201, 10202, 10203, 10204]); - let x3 = FieldElement51([10300, 10301, 10302, 10303, 10304]); - - let vec = FieldElement2625x4::new(&x0, &x1, &x2, &x3).diff_sum(); - - let result = vec.split(); - - assert_eq!(result[0], &x1 - &x0); - assert_eq!(result[1], &x1 + &x0); - assert_eq!(result[2], &x3 - &x2); - assert_eq!(result[3], &x3 + &x2); - } - - #[test] - fn square_vs_serial() { - let x0 = FieldElement51([10000, 10001, 10002, 10003, 10004]); - let x1 = FieldElement51([10100, 10101, 10102, 10103, 10104]); - let x2 = FieldElement51([10200, 10201, 10202, 10203, 10204]); - let x3 = FieldElement51([10300, 10301, 10302, 10303, 10304]); - - let vec = FieldElement2625x4::new(&x0, &x1, &x2, &x3); - - let result = vec.square_and_negate_D().split(); - - assert_eq!(result[0], &x0 * &x0); - assert_eq!(result[1], &x1 * &x1); - assert_eq!(result[2], &x2 * &x2); - assert_eq!(result[3], -&(&x3 * &x3)); - } - - #[test] - fn multiply_vs_serial() { - let x0 = FieldElement51([10000, 10001, 10002, 10003, 10004]); - let x1 = FieldElement51([10100, 10101, 10102, 10103, 10104]); - let x2 = FieldElement51([10200, 10201, 10202, 10203, 10204]); - let x3 = FieldElement51([10300, 10301, 10302, 10303, 10304]); - - let vec = FieldElement2625x4::new(&x0, &x1, &x2, &x3); - let vecprime = vec.clone(); - - let result = (&vec * &vecprime).split(); - - assert_eq!(result[0], &x0 * &x0); - assert_eq!(result[1], &x1 * &x1); - assert_eq!(result[2], &x2 * &x2); - assert_eq!(result[3], &x3 * &x3); - } - - #[test] - fn test_unpack_repack_pair() { - let x0 = FieldElement51([10000 + (10001 << 26), 0, 0, 0, 0]); - let x1 = FieldElement51([10100 + (10101 << 26), 0, 0, 0, 0]); - let x2 = FieldElement51([10200 + (10201 << 26), 0, 0, 0, 0]); - let x3 = FieldElement51([10300 + (10301 << 26), 0, 0, 0, 0]); - - let vec = FieldElement2625x4::new(&x0, &x1, &x2, &x3); - - let src = vec.0[0]; - - let (a, b) = unpack_pair(src); - - let expected_a = u32x8::new(10000, 0, 10100, 0, 10200, 0, 10300, 0); - let expected_b = u32x8::new(10001, 0, 10101, 0, 10201, 0, 10301, 0); - - assert_eq!(a, expected_a); - assert_eq!(b, expected_b); - - let expected_src = repack_pair(a, b); - - assert_eq!(src, expected_src); - } - - #[test] - fn new_split_roundtrips() { - let x0 = FieldElement51::from_bytes(&[0x10; 32]); - let x1 = FieldElement51::from_bytes(&[0x11; 32]); - let x2 = FieldElement51::from_bytes(&[0x12; 32]); - let x3 = FieldElement51::from_bytes(&[0x13; 32]); - - let vec = FieldElement2625x4::new(&x0, &x1, &x2, &x3); - - let splits = vec.split(); - - assert_eq!(x0, splits[0]); - assert_eq!(x1, splits[1]); - assert_eq!(x2, splits[2]); - assert_eq!(x3, splits[3]); - } -} diff --git a/net/gurk-rs/files/vendor/curve25519-dalek-2.0.0/src/backend/vector/avx2/mod.rs b/net/gurk-rs/files/vendor/curve25519-dalek-2.0.0/src/backend/vector/avx2/mod.rs deleted file mode 100644 index 175b7eb..0000000 --- a/net/gurk-rs/files/vendor/curve25519-dalek-2.0.0/src/backend/vector/avx2/mod.rs +++ /dev/null @@ -1,20 +0,0 @@ -// -*- mode: rust; -*- -// -// This file is part of curve25519-dalek. -// Copyright (c) 2016-2019 Isis Lovecruft, Henry de Valence -// See LICENSE for licensing information. -// -// Authors: -// - Isis Agora Lovecruft -// - Henry de Valence - -#![cfg_attr( - feature = "nightly", - doc(include = "../../../../docs/avx2-notes.md") -)] - -pub(crate) mod field; - -pub(crate) mod edwards; - -pub(crate) mod constants; diff --git a/net/gurk-rs/files/vendor/curve25519-dalek-2.0.0/src/backend/vector/ifma/constants.rs b/net/gurk-rs/files/vendor/curve25519-dalek-2.0.0/src/backend/vector/ifma/constants.rs deleted file mode 100644 index fd89058..0000000 --- a/net/gurk-rs/files/vendor/curve25519-dalek-2.0.0/src/backend/vector/ifma/constants.rs +++ /dev/null @@ -1,2062 +0,0 @@ -// -*- mode: rust; -*- -// -// This file is part of curve25519-dalek. -// Copyright (c) 2018-2019 Henry de Valence -// See LICENSE for licensing information. -// -// Authors: -// - Henry de Valence - -//! This module contains constants used by the IFMA backend. - -use packed_simd::u64x4; - -use window::NafLookupTable8; - -use super::edwards::{CachedPoint, ExtendedPoint}; -use super::field::{F51x4Reduced, F51x4Unreduced}; - -/// The identity element as an `ExtendedPoint`. -pub(crate) static EXTENDEDPOINT_IDENTITY: ExtendedPoint = ExtendedPoint(F51x4Unreduced([ - u64x4::new(0, 1, 1, 0), - u64x4::new(0, 0, 0, 0), - u64x4::new(0, 0, 0, 0), - u64x4::new(0, 0, 0, 0), - u64x4::new(0, 0, 0, 0), -])); - -/// The identity element as a `CachedPoint`. -pub(crate) static CACHEDPOINT_IDENTITY: CachedPoint = CachedPoint(F51x4Reduced([ - u64x4::new(121647, 121666, 243332, 2251799813685229), - u64x4::new(2251799813685248, 0, 0, 2251799813685247), - u64x4::new(2251799813685247, 0, 0, 2251799813685247), - u64x4::new(2251799813685247, 0, 0, 2251799813685247), - u64x4::new(2251799813685247, 0, 0, 2251799813685247), -])); - -/// Odd multiples of the Ed25519 basepoint: -pub(crate) static BASEPOINT_ODD_LOOKUP_TABLE: NafLookupTable8 = NafLookupTable8([ - CachedPoint(F51x4Reduced([ - u64x4::new(1277522120965857, 73557767439946, 243332, 1943719795065404), - u64x4::new(108375142003455, 341984820733594, 0, 2097709862669256), - u64x4::new(150073485536043, 750646439938056, 0, 581130035634455), - u64x4::new(2149983732744869, 1903255931888577, 0, 646644904824193), - u64x4::new(291045673509296, 1060034214701851, 0, 325245010451737), - ])), - CachedPoint(F51x4Reduced([ - u64x4::new( - 1970681836121889, - 1660307753655178, - 1077207637163462, - 1436413309977108, - ), - u64x4::new( - 158785710838757, - 919645875412951, - 174577133496574, - 2213787394009350, - ), - u64x4::new( - 1017606396438281, - 1240932851489554, - 918203302506967, - 1239827708070863, - ), - u64x4::new( - 1748989883612327, - 1745367742532782, - 1168385548387, - 1211387683826673, - ), - u64x4::new( - 799349980018733, - 1471088235739693, - 1505351346057417, - 2104975925096407, - ), - ])), - CachedPoint(F51x4Reduced([ - u64x4::new( - 171437462972293, - 36016853025886, - 1184164975342640, - 1633525003912147, - ), - u64x4::new( - 2113383632509037, - 1946216474924125, - 1884174984466256, - 1373317790955847, - ), - u64x4::new( - 791293623466401, - 1796466048084189, - 444977763198796, - 629823271230872, - ), - u64x4::new( - 1093217720067380, - 2157024270666135, - 238122980108466, - 806820763806847, - ), - u64x4::new( - 793658959468458, - 368578641413741, - 11592529764159, - 2144017075993471, - ), - ])), - CachedPoint(F51x4Reduced([ - u64x4::new( - 1538027396670268, - 1588896993892061, - 675619548648376, - 788373514423313, - ), - u64x4::new( - 1987517656073805, - 1940987929951188, - 666993851697339, - 2040540928108427, - ), - u64x4::new( - 375514548584082, - 1726008037083790, - 1070069155000872, - 570111103756303, - ), - u64x4::new( - 772223645372213, - 2123395244967674, - 868238486911408, - 1846639042240362, - ), - u64x4::new( - 872865734460736, - 32277956842850, - 1701451131455402, - 773883376061880, - ), - ])), - CachedPoint(F51x4Reduced([ - u64x4::new( - 1845177363882902, - 275858237213625, - 1052127336883600, - 171072805852218, - ), - u64x4::new( - 139016783952609, - 462699304987089, - 430046471494974, - 410922720999257, - ), - u64x4::new( - 846403935976337, - 243817706931454, - 971825428236901, - 571800039596794, - ), - u64x4::new( - 807642685434918, - 1933536976438782, - 812324278898440, - 688391556487313, - ), - u64x4::new( - 76239450396192, - 629532732688863, - 1833302026979779, - 650067934544499, - ), - ])), - CachedPoint(F51x4Reduced([ - u64x4::new( - 1373931604989264, - 331159264656614, - 364391529321767, - 874765630865409, - ), - u64x4::new( - 2109908262150241, - 473400816504190, - 91544045127333, - 976307977609515, - ), - u64x4::new( - 330175435673491, - 2126511895885904, - 1022944071588421, - 2158480209801463, - ), - u64x4::new( - 1305666795527971, - 162063591028664, - 2193154870675382, - 1789166662611800, - ), - u64x4::new( - 817858592500508, - 1672743239440202, - 859976879916778, - 1167423340862516, - ), - ])), - CachedPoint(F51x4Reduced([ - u64x4::new( - 274334925170164, - 565841102587251, - 603083835949120, - 607539210240861, - ), - u64x4::new( - 196754662972649, - 1339063476699167, - 1406077076979491, - 896902435668469, - ), - u64x4::new( - 397962210956733, - 174839587476217, - 1381082665748936, - 175195877334136, - ), - u64x4::new( - 717429432748391, - 1635309821746318, - 363374010274647, - 882908746261699, - ), - u64x4::new( - 600946602802781, - 1946596133370711, - 1532135183320341, - 690530671668253, - ), - ])), - CachedPoint(F51x4Reduced([ - u64x4::new( - 2074443704000945, - 2163534804938345, - 425423840926528, - 1100826171404853, - ), - u64x4::new( - 111700142796101, - 1456893872751964, - 1186145518682968, - 2192182627706116, - ), - u64x4::new( - 1848722121856066, - 2123239575044749, - 1323870754599272, - 883211262889775, - ), - u64x4::new( - 938263017712916, - 689670293631396, - 183944529557576, - 501908638166580, - ), - u64x4::new( - 2170571907220631, - 36636756989655, - 1875035480138608, - 803703278398018, - ), - ])), - CachedPoint(F51x4Reduced([ - u64x4::new( - 1053429956874064, - 1636640618139765, - 1556890827801070, - 2142720579528828, - ), - u64x4::new( - 1814240918422814, - 692326274601777, - 1054896561802157, - 2025454041705534, - ), - u64x4::new( - 2109495823888757, - 1287497869997176, - 194170063200096, - 621116840113213, - ), - u64x4::new( - 2156505873679998, - 2197064359737385, - 1312887672223536, - 369862818895912, - ), - u64x4::new( - 977381163563657, - 1878897311974033, - 2144566861359744, - 1832960882773351, - ), - ])), - CachedPoint(F51x4Reduced([ - u64x4::new( - 1266492498289486, - 1301524759372145, - 324789537938521, - 442710471023019, - ), - u64x4::new( - 1232722320001345, - 1191193089162455, - 176474006074813, - 2158950213252857, - ), - u64x4::new( - 1901782191467749, - 494791441598902, - 1820415815322129, - 854954583485223, - ), - u64x4::new( - 1511383667649702, - 792536415032464, - 2027741263854728, - 1727944381044738, - ), - u64x4::new( - 606355788891204, - 1670687521471220, - 582824350365415, - 1509135066079912, - ), - ])), - CachedPoint(F51x4Reduced([ - u64x4::new( - 1079942762813598, - 2015830004785901, - 479916361323351, - 1907956590950158, - ), - u64x4::new( - 2053400302939156, - 1319799126867070, - 19493088767391, - 1908755581402373, - ), - u64x4::new( - 2235858054780980, - 885832711204321, - 810332865560178, - 103174191215441, - ), - u64x4::new( - 1843466881032833, - 355511728384038, - 693846715794114, - 186545012724117, - ), - u64x4::new( - 1661758432892509, - 1491022339899281, - 698941123765263, - 174945407208560, - ), - ])), - CachedPoint(F51x4Reduced([ - u64x4::new( - 1075933251927831, - 400263885306647, - 1308157532880528, - 347933379126665, - ), - u64x4::new( - 673811632329433, - 1584860147186478, - 271778891257244, - 498194055154207, - ), - u64x4::new( - 703783427747558, - 1051624728592032, - 1371463103351544, - 230351033002960, - ), - u64x4::new( - 860729466483372, - 421647596766583, - 1520613871336707, - 635298775280054, - ), - u64x4::new( - 1168352891728845, - 1691216293752089, - 1799491997061519, - 399728882318504, - ), - ])), - CachedPoint(F51x4Reduced([ - u64x4::new( - 420156727446514, - 1483649215777128, - 165508610199900, - 1918121104840431, - ), - u64x4::new( - 2129902293682427, - 730952770435213, - 2184527544565390, - 1939880362232986, - ), - u64x4::new( - 1771978364905086, - 510975579746524, - 927564335219142, - 177574146260558, - ), - u64x4::new( - 2164104536437514, - 1532598873799015, - 406875369182421, - 1367005937406517, - ), - u64x4::new( - 35073200082587, - 1981124717036219, - 1854087014063833, - 122419694385217, - ), - ])), - CachedPoint(F51x4Reduced([ - u64x4::new( - 1963785875777739, - 411497142699119, - 1974557512687408, - 1268304422747183, - ), - u64x4::new( - 762752575978150, - 1443822019541748, - 1331556159904338, - 377726798263780, - ), - u64x4::new( - 825953972847841, - 353487068141356, - 1955697322427207, - 2048226560172078, - ), - u64x4::new( - 1482378558684434, - 657691905625918, - 923870001994493, - 1694132799397736, - ), - u64x4::new( - 1643904759603122, - 170495566698285, - 1218312703413378, - 784318735038131, - ), - ])), - CachedPoint(F51x4Reduced([ - u64x4::new( - 939230507241903, - 2238763473105245, - 1827325199528162, - 1153939339775538, - ), - u64x4::new( - 38544505283339, - 258889431497015, - 351721979677947, - 1357907379592829, - ), - u64x4::new( - 1393974676373341, - 1131355528938676, - 473104915298872, - 978783482501776, - ), - u64x4::new( - 2131516168980501, - 2113911780991092, - 1477027502354261, - 542884524860340, - ), - u64x4::new( - 1029606261349423, - 64226378557628, - 1669131167474348, - 2212808057234874, - ), - ])), - CachedPoint(F51x4Reduced([ - u64x4::new( - 1423176501543193, - 163313632579593, - 2220495688893001, - 2220041045291870, - ), - u64x4::new( - 1111834224023697, - 1026815658023689, - 1404605100939775, - 1412149108248227, - ), - u64x4::new( - 1542537854906076, - 1270288391129127, - 991419278941933, - 1824939809581980, - ), - u64x4::new( - 1142003215657891, - 525980550896367, - 1508270666157963, - 917719462309053, - ), - u64x4::new( - 400851268057105, - 1620818232405188, - 1251478578139510, - 2162841805361886, - ), - ])), - CachedPoint(F51x4Reduced([ - u64x4::new( - 2125383272208441, - 1368790097335984, - 11813369275978, - 639513785921674, - ), - u64x4::new( - 2200806265616284, - 1041996387620216, - 1275149397833084, - 1723371028064068, - ), - u64x4::new( - 603720163891275, - 2135593511176153, - 2049641644431548, - 1198460677818310, - ), - u64x4::new( - 1862491879401621, - 2008116580769441, - 626566325260235, - 1058308304975798, - ), - u64x4::new( - 628557314314858, - 1075323332046522, - 1631772244117095, - 1812174547405683, - ), - ])), - CachedPoint(F51x4Reduced([ - u64x4::new( - 1222773123817104, - 363276129291452, - 796237592807883, - 1914425291893078, - ), - u64x4::new( - 1721259057429088, - 734941709009373, - 1553365830564638, - 1492120931079419, - ), - u64x4::new( - 1009354843273686, - 293884504384873, - 1050281954944357, - 134132942667344, - ), - u64x4::new( - 23119363298711, - 1694754778833445, - 1725925193393496, - 1738396998222001, - ), - u64x4::new( - 1753692057254667, - 118428526447110, - 840961387840295, - 1227619055408558, - ), - ])), - CachedPoint(F51x4Reduced([ - u64x4::new( - 1004186117579547, - 508771992330056, - 1426571663072421, - 2238524171903259, - ), - u64x4::new( - 744764613007812, - 398885442368825, - 2047459490294949, - 2141797621077959, - ), - u64x4::new( - 4556204156489, - 1708213022802363, - 1071381560923933, - 393474529142567, - ), - u64x4::new( - 350116198213005, - 945907227204695, - 168267474358731, - 1801504420122711, - ), - u64x4::new( - 728788674520360, - 1262722049156121, - 455259596607008, - 1159442365834489, - ), - ])), - CachedPoint(F51x4Reduced([ - u64x4::new( - 2226818917892677, - 185673745808179, - 2240952219732549, - 324137961621908, - ), - u64x4::new( - 1659527641857410, - 973964060249383, - 1349692151487730, - 1172743533370593, - ), - u64x4::new( - 310591478467746, - 2123977244137170, - 774562885265820, - 430035546191685, - ), - u64x4::new( - 2150863173197992, - 2101978317708856, - 193592648406011, - 1375328504508580, - ), - u64x4::new( - 1946235834250479, - 121741431658675, - 1004342690620100, - 2063466488599450, - ), - ])), - CachedPoint(F51x4Reduced([ - u64x4::new( - 463079632200153, - 40415275714025, - 545935352782679, - 1458043501600908, - ), - u64x4::new( - 783771976559993, - 880839641726471, - 1782028201271831, - 41664413404590, - ), - u64x4::new( - 985129151724159, - 187728621410000, - 16620051933318, - 378011085567733, - ), - u64x4::new( - 1820372198168638, - 905710046480679, - 1912961774249737, - 1868135861067161, - ), - u64x4::new( - 474460473983187, - 1455684425673661, - 652771171116843, - 733511920760779, - ), - ])), - CachedPoint(F51x4Reduced([ - u64x4::new( - 1088886980746809, - 1660218575261626, - 527921875040240, - 915086639857889, - ), - u64x4::new( - 1814735788528175, - 1586698876186367, - 2040856637532862, - 405684812785624, - ), - u64x4::new( - 658578559700999, - 1751442070931114, - 1293623371490094, - 715026719042518, - ), - u64x4::new( - 382156225644820, - 897982285504960, - 577673183555858, - 1158728558309719, - ), - u64x4::new( - 1865791902475663, - 124491617513788, - 758484125168765, - 734065580770143, - ), - ])), - CachedPoint(F51x4Reduced([ - u64x4::new( - 330985690350617, - 2214424721795630, - 973374650780848, - 1507267060932964, - ), - u64x4::new( - 1733823971011290, - 1730742552292995, - 669018866977489, - 604527664126146, - ), - u64x4::new( - 1082092498645474, - 1029182053935309, - 756799947765834, - 1764720030308351, - ), - u64x4::new( - 969912105693756, - 38116887248276, - 2148030115687613, - 995140534653865, - ), - u64x4::new( - 2154373397460354, - 298128883464656, - 479587543632539, - 1061127201140779, - ), - ])), - CachedPoint(F51x4Reduced([ - u64x4::new( - 843064865526549, - 2019481782959016, - 1873125524281672, - 2013330239022371, - ), - u64x4::new( - 1192932403815186, - 1818108671859220, - 1247005102016258, - 1210577394628058, - ), - u64x4::new( - 132359273326717, - 795492788299178, - 1235924489372816, - 891705064411550, - ), - u64x4::new( - 1425833709104858, - 152114045731085, - 991347902581315, - 1387773338707683, - ), - u64x4::new( - 48024203807922, - 157005564892977, - 1474053161953744, - 727448023498345, - ), - ])), - CachedPoint(F51x4Reduced([ - u64x4::new( - 1076621484026788, - 1309917234320927, - 1786998180233659, - 1595497085944737, - ), - u64x4::new( - 1737334672694726, - 2038133716999447, - 1929061192400917, - 620544235219084, - ), - u64x4::new( - 1550527313469747, - 329096759623509, - 1585214659209474, - 693419841748324, - ), - u64x4::new( - 1450010875912315, - 2085047082180569, - 757421110771886, - 389367139787400, - ), - u64x4::new( - 781339490566117, - 132941783448971, - 258650459725225, - 2042274962585613, - ), - ])), - CachedPoint(F51x4Reduced([ - u64x4::new( - 859638991542650, - 2249840007426442, - 1138753070862357, - 793751342318913, - ), - u64x4::new( - 2133476133447306, - 1027010646129239, - 436851910892865, - 866949948830344, - ), - u64x4::new( - 1936003572431223, - 531513680252193, - 1929877059408416, - 830585477662503, - ), - u64x4::new( - 1460760405777960, - 686673748420916, - 275475330051554, - 1581792376993692, - ), - u64x4::new( - 894482039456784, - 1801274480988632, - 16407898635278, - 1668497039215206, - ), - ])), - CachedPoint(F51x4Reduced([ - u64x4::new( - 258585746227669, - 936490904651492, - 1826793887434108, - 1201219990633823, - ), - u64x4::new( - 979462791643635, - 461762372210187, - 218708929991480, - 1378150755760178, - ), - u64x4::new( - 642542170229970, - 787135445552820, - 371168855880557, - 182642566486693, - ), - u64x4::new( - 1152277399721904, - 1726910452705576, - 1452393215705343, - 2117799581546845, - ), - u64x4::new( - 1211265143925330, - 14373046151823, - 1745528818271507, - 1842106288572078, - ), - ])), - CachedPoint(F51x4Reduced([ - u64x4::new( - 635154614562157, - 1956763034454109, - 509123035953043, - 445727657534780, - ), - u64x4::new( - 2072765509783252, - 1282639891593570, - 1075086397362049, - 722996110178195, - ), - u64x4::new( - 1385572918825603, - 1190035835509576, - 218317841176013, - 1047865370756924, - ), - u64x4::new( - 473991569426488, - 1910588123704592, - 1338270051770806, - 401676861680875, - ), - u64x4::new( - 992455353618436, - 126422733426929, - 1955248037756399, - 119233843022643, - ), - ])), - CachedPoint(F51x4Reduced([ - u64x4::new( - 1555272991526078, - 2214378187116349, - 366893798097444, - 1401502118355702, - ), - u64x4::new( - 1157229521930713, - 2144787187506262, - 1681597469697840, - 847499096518697, - ), - u64x4::new( - 1872802655800758, - 1027119609820793, - 1137278714788290, - 1664750301179485, - ), - u64x4::new( - 1091289858897030, - 910126419483563, - 1101920147235731, - 597083075893952, - ), - u64x4::new( - 1711011533670315, - 185206680336278, - 1620960612579784, - 1968598849170880, - ), - ])), - CachedPoint(F51x4Reduced([ - u64x4::new( - 73077300235958, - 257216723095630, - 466947267713785, - 847105214181598, - ), - u64x4::new( - 1322905631406309, - 407458059314731, - 230045063190376, - 923800751267786, - ), - u64x4::new( - 1146027205000415, - 1541328763727623, - 768510249199119, - 1630223587589059, - ), - u64x4::new( - 1930368769879433, - 1376145403022159, - 1898149855343131, - 1709421930518180, - ), - u64x4::new( - 633944191571764, - 58314960742839, - 2050971151574988, - 757799756090059, - ), - ])), - CachedPoint(F51x4Reduced([ - u64x4::new( - 361576929158539, - 1035682890165818, - 160945739362874, - 266975208626222, - ), - u64x4::new( - 1635371797076046, - 2106722851965197, - 451585919077206, - 6692426667180, - ), - u64x4::new( - 175820543533852, - 2057511393764025, - 1531846543720469, - 1648320903946519, - ), - u64x4::new( - 947461770620940, - 1107335044817620, - 1725565474111216, - 2182263619949220, - ), - u64x4::new( - 726444888601221, - 1379664085279206, - 1517215633290417, - 1763968936542507, - ), - ])), - CachedPoint(F51x4Reduced([ - u64x4::new( - 686545355846512, - 1712283265573167, - 1743509592736302, - 1653906616429153, - ), - u64x4::new( - 985108805667149, - 2244347650874753, - 1304749057936860, - 321846134330589, - ), - u64x4::new( - 296321076156886, - 1717929256240029, - 450933772486425, - 2015536856431605, - ), - u64x4::new( - 1690393512821866, - 646913049470189, - 2198650647576397, - 1230646705710442, - ), - u64x4::new( - 601961913448442, - 878806578800541, - 620497587492381, - 330716414244629, - ), - ])), - CachedPoint(F51x4Reduced([ - u64x4::new( - 631510982676132, - 1755753187697174, - 1596201246674299, - 2197888384902121, - ), - u64x4::new( - 626957678275745, - 1447583371478595, - 1375375216702128, - 1443613232818823, - ), - u64x4::new( - 1962997804660501, - 1051744123184519, - 1002558639300437, - 1237313314603385, - ), - u64x4::new( - 2118828335274995, - 226398203764759, - 889099617161107, - 1620967117678504, - ), - u64x4::new( - 227261019362935, - 2046897556746842, - 591524060355369, - 2178552047369691, - ), - ])), - CachedPoint(F51x4Reduced([ - u64x4::new( - 1375403119051662, - 222313965014452, - 539873444241395, - 213198095917915, - ), - u64x4::new( - 1436952871599114, - 1229749762725246, - 1174441562267670, - 265367077740349, - ), - u64x4::new( - 11107426165917, - 985954476039181, - 1147329112365579, - 1133931640328107, - ), - u64x4::new( - 585235055006843, - 699515259687482, - 299559608721134, - 2134819767146767, - ), - u64x4::new( - 1376401105588528, - 391412107507860, - 302743651807545, - 1362834426455518, - ), - ])), - CachedPoint(F51x4Reduced([ - u64x4::new( - 1802940904616205, - 1615132760193234, - 869321663313735, - 666494072545310, - ), - u64x4::new( - 1452849320020701, - 1472716813676364, - 472862999490802, - 359937983286145, - ), - u64x4::new( - 1221198323133843, - 491718521756528, - 1387135774113906, - 793779904904008, - ), - u64x4::new( - 1032129287829151, - 30730741946697, - 217603185195068, - 2118169309744162, - ), - u64x4::new( - 225899335574721, - 1767553399797342, - 881082465669982, - 1435383196392870, - ), - ])), - CachedPoint(F51x4Reduced([ - u64x4::new( - 1127093564374276, - 2245188499702906, - 1250041622887441, - 2179324911668149, - ), - u64x4::new( - 908019210866875, - 1879900391060964, - 1355047706206597, - 647218945377302, - ), - u64x4::new( - 1616265604422592, - 2134336781521657, - 1157711219915601, - 1227494173135033, - ), - u64x4::new( - 136450294813355, - 1984543542455033, - 1199486053011083, - 33687889941331, - ), - u64x4::new( - 1053447012707371, - 68239344331930, - 537448158443925, - 1829189783369646, - ), - ])), - CachedPoint(F51x4Reduced([ - u64x4::new( - 996806463322563, - 2043104667851348, - 1110361398300309, - 1218740346887957, - ), - u64x4::new( - 399141907016839, - 1307691109658227, - 532535384961264, - 896201194398872, - ), - u64x4::new( - 111705272106160, - 1790972382466021, - 1159338112559144, - 303544352897203, - ), - u64x4::new( - 1036600573322969, - 1457119922663674, - 334117653665514, - 460023361701263, - ), - u64x4::new( - 1363773215189933, - 1915594049343802, - 1661249423378694, - 1744945551969247, - ), - ])), - CachedPoint(F51x4Reduced([ - u64x4::new( - 3093919631215, - 574886478077610, - 1704446919728971, - 250093147254210, - ), - u64x4::new( - 1387413348737796, - 360142717826981, - 2116185073015983, - 474541388374100, - ), - u64x4::new( - 1632539630892580, - 1332404016215719, - 2145297637794728, - 1289783723173504, - ), - u64x4::new( - 1030244179060173, - 579782698595797, - 1062365251139982, - 677149839815546, - ), - u64x4::new( - 6671539419876, - 1426937459653775, - 406942403696343, - 675479224223817, - ), - ])), - CachedPoint(F51x4Reduced([ - u64x4::new( - 271984148441782, - 1708099625818957, - 1499011822959235, - 516808451044836, - ), - u64x4::new( - 1124847751346323, - 2038336022958449, - 1721698491022600, - 705944403212572, - ), - u64x4::new( - 85459783780275, - 1715213099986669, - 1728445509034791, - 730657630359717, - ), - u64x4::new( - 1185034652652387, - 755472578204310, - 476118360897817, - 1800434542785310, - ), - u64x4::new( - 1815589628676941, - 491778500674079, - 1547664984392513, - 279891608681267, - ), - ])), - CachedPoint(F51x4Reduced([ - u64x4::new( - 2036337168672113, - 1730787524684269, - 639134121311693, - 698060925015524, - ), - u64x4::new( - 315211075189491, - 1329055848835358, - 688621136402134, - 1271193060119448, - ), - u64x4::new( - 1697984374314012, - 459330773536457, - 305481314707918, - 61676911066002, - ), - u64x4::new( - 2166631826859191, - 2105217187401781, - 937587962768434, - 357397435365683, - ), - u64x4::new( - 1206757093145471, - 1287847622009294, - 1951336140421622, - 2233789834777410, - ), - ])), - CachedPoint(F51x4Reduced([ - u64x4::new( - 82144190081093, - 1568417433687791, - 907555979158442, - 2037855062523867, - ), - u64x4::new( - 1225315484058853, - 315317868015613, - 1765025920288384, - 175223259828436, - ), - u64x4::new( - 1215010304871271, - 662713408454950, - 429517658575616, - 991062684008811, - ), - u64x4::new( - 993837615254894, - 1485561584889450, - 2001836754226476, - 1915943063896801, - ), - u64x4::new( - 818895101625673, - 1342479472068804, - 1380235330010671, - 23315169761453, - ), - ])), - CachedPoint(F51x4Reduced([ - u64x4::new( - 1500726307559118, - 956166860173424, - 512663951564436, - 1940180717699824, - ), - u64x4::new( - 1789521472720825, - 779456898652427, - 2035063615853504, - 863582140589407, - ), - u64x4::new( - 634508890793787, - 1748041666732214, - 259642099961634, - 1294936839797812, - ), - u64x4::new( - 2183334898697038, - 2197242820694806, - 2217225409073703, - 992633998226449, - ), - u64x4::new( - 2197077498155916, - 1562008797791883, - 1395088759904208, - 331715244679294, - ), - ])), - CachedPoint(F51x4Reduced([ - u64x4::new( - 186854731652320, - 284389440026580, - 1252175415119400, - 1025377410100223, - ), - u64x4::new( - 1578732129417607, - 898645497852382, - 2237766074482974, - 1939197790303592, - ), - u64x4::new( - 1438830390640145, - 1682452015845597, - 1108441197232223, - 1984134492898664, - ), - u64x4::new( - 282668727301669, - 1609018289552856, - 390363439795705, - 1138459124667912, - ), - u64x4::new( - 18889015928490, - 532489638086725, - 324621535996080, - 2210046082697453, - ), - ])), - CachedPoint(F51x4Reduced([ - u64x4::new( - 2041327051605378, - 2244037852176483, - 2116336876147147, - 9616672544864, - ), - u64x4::new( - 969847387559191, - 1059119127679639, - 1764630094670633, - 364568045311834, - ), - u64x4::new( - 505938893153679, - 2075421412172902, - 326984153045666, - 1959549727324704, - ), - u64x4::new( - 1088715617911260, - 13917085151028, - 950568481355929, - 23687195265771, - ), - u64x4::new( - 1798284568673198, - 808382292203333, - 2214698741961545, - 610817203275867, - ), - ])), - CachedPoint(F51x4Reduced([ - u64x4::new( - 1731488929623777, - 1158815615106413, - 1491090861948525, - 1428384712900962, - ), - u64x4::new( - 722237139522457, - 1514290328911535, - 1366197913116230, - 1519472657321210, - ), - u64x4::new( - 246028966932273, - 1888239319448405, - 423720022211163, - 455243905681470, - ), - u64x4::new( - 738323403716001, - 1758018973481179, - 1180718299482318, - 1008495946606708, - ), - u64x4::new( - 334959381596119, - 1704599537529481, - 2172191232106896, - 13502508918495, - ), - ])), - CachedPoint(F51x4Reduced([ - u64x4::new( - 273393076768079, - 427388720298603, - 1071733376018227, - 1715429388968611, - ), - u64x4::new( - 751776629892313, - 1965239102856011, - 541955408230119, - 831043488876080, - ), - u64x4::new( - 643718536393104, - 390543998404644, - 2176730661486279, - 499459234889079, - ), - u64x4::new( - 1482404333915009, - 865527293526285, - 507957951411713, - 216456252558825, - ), - u64x4::new( - 2210281256300231, - 1519357818277551, - 1257866936775246, - 1689605217672864, - ), - ])), - CachedPoint(F51x4Reduced([ - u64x4::new( - 2135395168187905, - 2214400157568614, - 2032983817870823, - 1124945109072647, - ), - u64x4::new( - 1602820011758145, - 906675633903289, - 782700735390986, - 2067218823525601, - ), - u64x4::new( - 786785748926382, - 1433583123655616, - 905839404290873, - 2249680349963778, - ), - u64x4::new( - 1940824582370584, - 1610961256326291, - 285307858781375, - 1755588655461194, - ), - u64x4::new( - 233682812055333, - 2146114223476434, - 41132209533476, - 535292431776371, - ), - ])), - CachedPoint(F51x4Reduced([ - u64x4::new( - 600257696476418, - 18449221564824, - 1422209458591138, - 239571584769716, - ), - u64x4::new( - 2056372917056980, - 1155290566623531, - 1252473955568148, - 1276690716882081, - ), - u64x4::new( - 246974369025311, - 658117221519903, - 2000380937898441, - 1351183273924850, - ), - u64x4::new( - 1803747363753112, - 1736801515030186, - 2025633577199091, - 603378480769167, - ), - u64x4::new( - 57348749438551, - 1893551220299655, - 657926732731806, - 1522499384853705, - ), - ])), - CachedPoint(F51x4Reduced([ - u64x4::new( - 591809128842736, - 284860517232591, - 27436696863545, - 886306697195798, - ), - u64x4::new( - 2113192175751749, - 1405882509906423, - 561316282804847, - 835573846576266, - ), - u64x4::new( - 94407289485409, - 1781534171669004, - 2098782516531528, - 598529921520053, - ), - u64x4::new( - 1860137004504786, - 2197323407480349, - 1516772733981532, - 961740253777086, - ), - u64x4::new( - 1484139612868217, - 1593557644636881, - 838834937143441, - 36382198263380, - ), - ])), - CachedPoint(F51x4Reduced([ - u64x4::new( - 1165898865828562, - 1153420815042389, - 1068625028915785, - 1945927229911090, - ), - u64x4::new( - 843454394017146, - 571029655293754, - 386282254545998, - 1804608237584150, - ), - u64x4::new( - 370552451091100, - 1279105656351124, - 1864742949668631, - 2093071521726981, - ), - u64x4::new( - 1872542389052198, - 1679083953574330, - 349872262454465, - 1470311090717925, - ), - u64x4::new( - 685345654160323, - 319718985807814, - 1359932285384164, - 1410900103316331, - ), - ])), - CachedPoint(F51x4Reduced([ - u64x4::new( - 2083666668832889, - 314624387816655, - 1496694646480345, - 1946728950459189, - ), - u64x4::new( - 1579153761571203, - 508771185291380, - 1002249659402007, - 551517831173801, - ), - u64x4::new( - 2132371471626150, - 1988122278556533, - 1552195130653890, - 1327637750292755, - ), - u64x4::new( - 118937099181527, - 382610380973142, - 634951529106471, - 382740054041699, - ), - u64x4::new( - 801287519643470, - 87822941589258, - 1908825350108451, - 1404208826499115, - ), - ])), - CachedPoint(F51x4Reduced([ - u64x4::new( - 330347226380261, - 672119116965146, - 1761510370768005, - 1959200302484704, - ), - u64x4::new( - 1631876583009250, - 1684917718484264, - 1027256947805920, - 2174612545251129, - ), - u64x4::new( - 636668855699872, - 625187713984839, - 265886954766790, - 167898557908504, - ), - u64x4::new( - 1210974548180860, - 2051308710365526, - 907620584086428, - 1081788677970850, - ), - u64x4::new( - 621792955460854, - 1450945504745382, - 1666728650687828, - 977937146451674, - ), - ])), - CachedPoint(F51x4Reduced([ - u64x4::new( - 24725936182267, - 2226765032752574, - 2036560083102883, - 2002351185719584, - ), - u64x4::new( - 1620080779405308, - 1493220053370419, - 2245691691038916, - 1152182628629603, - ), - u64x4::new( - 317928527147500, - 1855194218440212, - 979380281964169, - 861442286685289, - ), - u64x4::new( - 393308472784625, - 486143087279967, - 1234071346236405, - 777748237119399, - ), - u64x4::new( - 43850412814718, - 1497656407486446, - 744128331046695, - 1618035787321792, - ), - ])), - CachedPoint(F51x4Reduced([ - u64x4::new( - 1670169946550211, - 1230951698726438, - 806586940221293, - 23159779184607, - ), - u64x4::new( - 634011340979302, - 764182085034744, - 731065727766955, - 1737985776442180, - ), - u64x4::new( - 240492712141842, - 73976435954441, - 162810587166835, - 697230894340912, - ), - u64x4::new( - 1299745598348388, - 1359436039694544, - 1856609816731554, - 25228008461513, - ), - u64x4::new( - 2180690501932381, - 2161211192848458, - 87069466793408, - 2003456332883860, - ), - ])), - CachedPoint(F51x4Reduced([ - u64x4::new( - 1106932458043379, - 1675181364231371, - 1681785724775243, - 131824742557210, - ), - u64x4::new( - 1671649414647169, - 1827849994880670, - 1097958057111899, - 701956891169434, - ), - u64x4::new( - 2095539283710881, - 591029812888096, - 1699571518315654, - 1297589045812566, - ), - u64x4::new( - 1345612272298537, - 2166754730876055, - 2047982622154948, - 1785222806258129, - ), - u64x4::new( - 2181915268829890, - 1895697064378670, - 1288412327355885, - 1561075738281368, - ), - ])), - CachedPoint(F51x4Reduced([ - u64x4::new( - 741330264098392, - 357073519729966, - 1603572339180975, - 433572083688575, - ), - u64x4::new( - 699685108971208, - 1719650727634959, - 1941668009419214, - 870374958347891, - ), - u64x4::new( - 385971389331537, - 11655507719711, - 94814615497633, - 515572102810609, - ), - u64x4::new( - 1396688200590426, - 1518748475144123, - 162386454324368, - 2083303971579002, - ), - u64x4::new( - 1511688632419263, - 251584258592336, - 545345887993880, - 1229840230314160, - ), - ])), - CachedPoint(F51x4Reduced([ - u64x4::new( - 1298668855706029, - 2017860934939344, - 2224150456036391, - 1925926576297971, - ), - u64x4::new( - 259522963883544, - 1312469129541229, - 1647530465049600, - 1113737129047154, - ), - u64x4::new( - 733193298663145, - 2115712816303403, - 897628702762311, - 116440277571901, - ), - u64x4::new( - 1998719395229750, - 1662774553684237, - 194395608126452, - 98796702872301, - ), - u64x4::new( - 2226158244229144, - 91961728239158, - 526869903032152, - 849263805316773, - ), - ])), - CachedPoint(F51x4Reduced([ - u64x4::new( - 472779569333556, - 854477760843410, - 2070906720349401, - 734613359834689, - ), - u64x4::new( - 1771897100487404, - 1604024196006064, - 319699348925383, - 437152129592623, - ), - u64x4::new( - 627618365135361, - 1768642666037955, - 588564169143939, - 35295037750744, - ), - u64x4::new( - 220241884231278, - 319104161410840, - 1048165719448798, - 1583931089774347, - ), - u64x4::new( - 166479451884333, - 1623611819962804, - 59990366193679, - 900727256046987, - ), - ])), - CachedPoint(F51x4Reduced([ - u64x4::new( - 1944687327687331, - 1328410791053991, - 2083980670913902, - 609396833380574, - ), - u64x4::new( - 1907563845734496, - 1385619047697883, - 869817384774457, - 106642388505109, - ), - u64x4::new( - 1006516581737154, - 1561918369633937, - 1921172883211450, - 2216650451558824, - ), - u64x4::new( - 1780506017391778, - 233064930371847, - 1332962603425752, - 1380075261612354, - ), - u64x4::new( - 1907624789747741, - 1310065402098523, - 1838275780706825, - 884225500782782, - ), - ])), - CachedPoint(F51x4Reduced([ - u64x4::new( - 198729830692545, - 100156148743413, - 2140568641558859, - 2220606475942394, - ), - u64x4::new( - 1108788217903741, - 1706330932366163, - 2050449866410661, - 684907598542847, - ), - u64x4::new( - 1101958322366646, - 659427843062405, - 253899933868173, - 896574852821269, - ), - u64x4::new( - 1157052140740658, - 440541103447032, - 2173354981480949, - 604768603561932, - ), - u64x4::new( - 961238337866054, - 830849154351308, - 1643852412409441, - 1436749321770368, - ), - ])), - CachedPoint(F51x4Reduced([ - u64x4::new( - 784870637473285, - 1180234052037572, - 2086951602998715, - 419328169540373, - ), - u64x4::new( - 1966862397394559, - 788036164772123, - 2024355635709481, - 1471696676696146, - ), - u64x4::new( - 1468884300957205, - 1408016588131185, - 2229595828577885, - 240413942963547, - ), - u64x4::new( - 1481791691942441, - 970648959691160, - 1635500996148197, - 2236917233261585, - ), - u64x4::new( - 31660820731028, - 801794768903647, - 1069092619607344, - 282652554845923, - ), - ])), - CachedPoint(F51x4Reduced([ - u64x4::new( - 911659428682786, - 762502588057038, - 1311399152500807, - 1966922911783311, - ), - u64x4::new( - 1229849228728540, - 258161307933217, - 2140796867375541, - 1569345075547911, - ), - u64x4::new( - 1487354676143742, - 1818317546165791, - 811033554173350, - 1768788663337616, - ), - u64x4::new( - 450017165913234, - 962535873747168, - 2099104262993585, - 503030952485785, - ), - u64x4::new( - 1259958681304518, - 479589250923541, - 1503904042161640, - 706283657294305, - ), - ])), - CachedPoint(F51x4Reduced([ - u64x4::new( - 794562643024291, - 198670993088241, - 1678984629358943, - 273399517554618, - ), - u64x4::new( - 188458991574433, - 1389872130156447, - 1461868931574746, - 795140878721432, - ), - u64x4::new( - 624046647169653, - 630363741191019, - 911018499983500, - 1410140563046579, - ), - u64x4::new( - 1675056174405076, - 632544713589250, - 795454163559811, - 1535271563341780, - ), - u64x4::new( - 25504547444781, - 812510098987855, - 51290042016232, - 1992260991700127, - ), - ])), - CachedPoint(F51x4Reduced([ - u64x4::new( - 269968325452358, - 470932785179706, - 1684444304834150, - 1027482126748243, - ), - u64x4::new( - 457941065342419, - 2117377568137882, - 1209423706730905, - 2192403099717071, - ), - u64x4::new( - 1899046404863678, - 1359500336071762, - 1492389156724726, - 1455627081827750, - ), - u64x4::new( - 2016101061876546, - 1967000012916571, - 582539481696050, - 1197538178790094, - ), - u64x4::new( - 639684852217504, - 1799941252757449, - 1470016556327743, - 846111828965901, - ), - ])), -]); diff --git a/net/gurk-rs/files/vendor/curve25519-dalek-2.0.0/src/backend/vector/ifma/edwards.rs b/net/gurk-rs/files/vendor/curve25519-dalek-2.0.0/src/backend/vector/ifma/edwards.rs deleted file mode 100644 index 5c8d819..0000000 --- a/net/gurk-rs/files/vendor/curve25519-dalek-2.0.0/src/backend/vector/ifma/edwards.rs +++ /dev/null @@ -1,315 +0,0 @@ -// -*- mode: rust; -*- -// -// This file is part of curve25519-dalek. -// Copyright (c) 2018-2019 Henry de Valence -// See LICENSE for licensing information. -// -// Authors: -// - Henry de Valence - -#![allow(non_snake_case)] - -use traits::Identity; - -use std::ops::{Add, Neg, Sub}; - -use subtle::Choice; -use subtle::ConditionallySelectable; - -use edwards; -use window::{LookupTable, NafLookupTable5, NafLookupTable8}; - -use super::constants; -use super::field::{F51x4Reduced, F51x4Unreduced, Lanes, Shuffle}; - -#[derive(Copy, Clone, Debug)] -pub struct ExtendedPoint(pub(super) F51x4Unreduced); - -#[derive(Copy, Clone, Debug)] -pub struct CachedPoint(pub(super) F51x4Reduced); - -impl From for ExtendedPoint { - fn from(P: edwards::EdwardsPoint) -> ExtendedPoint { - ExtendedPoint(F51x4Unreduced::new(&P.X, &P.Y, &P.Z, &P.T)) - } -} - -impl From for edwards::EdwardsPoint { - fn from(P: ExtendedPoint) -> edwards::EdwardsPoint { - let reduced = F51x4Reduced::from(P.0); - let tmp = F51x4Unreduced::from(reduced).split(); - edwards::EdwardsPoint { - X: tmp[0], - Y: tmp[1], - Z: tmp[2], - T: tmp[3], - } - } -} - -impl From for CachedPoint { - fn from(P: ExtendedPoint) -> CachedPoint { - let mut x = P.0; - - x = x.blend(&x.diff_sum(), Lanes::AB); - x = &F51x4Reduced::from(x) * (121666, 121666, 2 * 121666, 2 * 121665); - x = x.blend(&x.negate_lazy(), Lanes::D); - - CachedPoint(F51x4Reduced::from(x)) - } -} - -impl Default for ExtendedPoint { - fn default() -> ExtendedPoint { - ExtendedPoint::identity() - } -} - -impl Identity for ExtendedPoint { - fn identity() -> ExtendedPoint { - constants::EXTENDEDPOINT_IDENTITY - } -} - -impl ExtendedPoint { - pub fn double(&self) -> ExtendedPoint { - // (Y1 X1 T1 Z1) -- uses vpshufd (1c latency @ 1/c) - let mut tmp0 = self.0.shuffle(Shuffle::BADC); - - // (X1+Y1 X1+Y1 X1+Y1 X1+Y1) -- can use vpinserti128 - let mut tmp1 = (self.0 + tmp0).shuffle(Shuffle::ABAB); - - // (X1 Y1 Z1 X1+Y1) - tmp0 = self.0.blend(&tmp1, Lanes::D); - - tmp1 = F51x4Reduced::from(tmp0).square(); - // Now tmp1 = (S1 S2 S3 S4) - - // We want to compute - // - // + | S1 | S1 | S1 | S1 | - // + | S2 | | | S2 | - // + | | | S3 | | - // + | | | S3 | | - // + | |16p |16p |16p | - // - | | S2 | S2 | | - // - | | | | S4 | - // ======================= - // S5 S6 S8 S9 - - let zero = F51x4Unreduced::zero(); - - let S1_S1_S1_S1 = tmp1.shuffle(Shuffle::AAAA); - let S2_S2_S2_S2 = tmp1.shuffle(Shuffle::BBBB); - - let S2_S2_S2_S4 = S2_S2_S2_S2.blend(&tmp1, Lanes::D).negate_lazy(); - - tmp0 = S1_S1_S1_S1 + zero.blend(&(tmp1 + tmp1), Lanes::C); - tmp0 = tmp0 + zero.blend(&S2_S2_S2_S2, Lanes::AD); - tmp0 = tmp0 + zero.blend(&S2_S2_S2_S4, Lanes::BCD); - - let tmp2 = F51x4Reduced::from(tmp0); - - ExtendedPoint(&tmp2.shuffle(Shuffle::DBBD) * &tmp2.shuffle(Shuffle::CACA)) - } - - pub fn mul_by_pow_2(&self, k: u32) -> ExtendedPoint { - let mut tmp: ExtendedPoint = *self; - for _ in 0..k { - tmp = tmp.double(); - } - tmp - } -} - -impl<'a, 'b> Add<&'b CachedPoint> for &'a ExtendedPoint { - type Output = ExtendedPoint; - - /// Add an `ExtendedPoint` and a `CachedPoint`. - fn add(self, other: &'b CachedPoint) -> ExtendedPoint { - let mut tmp = self.0; - - tmp = tmp.blend(&tmp.diff_sum(), Lanes::AB); - // tmp = (Y1-X1 Y1+X1 Z1 T1) = (S0 S1 Z1 T1) - - tmp = &F51x4Reduced::from(tmp) * &other.0; - // tmp = (S0*S2' S1*S3' Z1*Z2' T1*T2') = (S8 S9 S10 S11) - - tmp = tmp.shuffle(Shuffle::ABDC); - // tmp = (S8 S9 S11 S10) - - let tmp = F51x4Reduced::from(tmp.diff_sum()); - // tmp = (S9-S8 S9+S8 S10-S11 S10+S11) = (S12 S13 S14 S15) - - let t0 = tmp.shuffle(Shuffle::ADDA); - // t0 = (S12 S15 S15 S12) - let t1 = tmp.shuffle(Shuffle::CBCB); - // t1 = (S14 S13 S14 S13) - - // Return (S12*S14 S15*S13 S15*S14 S12*S13) = (X3 Y3 Z3 T3) - ExtendedPoint(&t0 * &t1) - } -} - -impl Default for CachedPoint { - fn default() -> CachedPoint { - CachedPoint::identity() - } -} - -impl Identity for CachedPoint { - fn identity() -> CachedPoint { - constants::CACHEDPOINT_IDENTITY - } -} - -impl ConditionallySelectable for CachedPoint { - fn conditional_select(a: &Self, b: &Self, choice: Choice) -> Self { - CachedPoint(F51x4Reduced::conditional_select(&a.0, &b.0, choice)) - } - - fn conditional_assign(&mut self, other: &Self, choice: Choice) { - self.0.conditional_assign(&other.0, choice); - } -} - -impl<'a> Neg for &'a CachedPoint { - type Output = CachedPoint; - - fn neg(self) -> CachedPoint { - let swapped = self.0.shuffle(Shuffle::BACD); - CachedPoint(swapped.blend(&(-self.0), Lanes::D)) - } -} - -impl<'a, 'b> Sub<&'b CachedPoint> for &'a ExtendedPoint { - type Output = ExtendedPoint; - - /// Implement subtraction by negating the point and adding. - fn sub(self, other: &'b CachedPoint) -> ExtendedPoint { - self + &(-other) - } -} - -impl<'a> From<&'a edwards::EdwardsPoint> for LookupTable { - fn from(point: &'a edwards::EdwardsPoint) -> Self { - let P = ExtendedPoint::from(*point); - let mut points = [CachedPoint::from(P); 8]; - for i in 0..7 { - points[i + 1] = (&P + &points[i]).into(); - } - LookupTable(points) - } -} - -impl<'a> From<&'a edwards::EdwardsPoint> for NafLookupTable5 { - fn from(point: &'a edwards::EdwardsPoint) -> Self { - let A = ExtendedPoint::from(*point); - let mut Ai = [CachedPoint::from(A); 8]; - let A2 = A.double(); - for i in 0..7 { - Ai[i + 1] = (&A2 + &Ai[i]).into(); - } - // Now Ai = [A, 3A, 5A, 7A, 9A, 11A, 13A, 15A] - NafLookupTable5(Ai) - } -} - -impl<'a> From<&'a edwards::EdwardsPoint> for NafLookupTable8 { - fn from(point: &'a edwards::EdwardsPoint) -> Self { - let A = ExtendedPoint::from(*point); - let mut Ai = [CachedPoint::from(A); 64]; - let A2 = A.double(); - for i in 0..63 { - Ai[i + 1] = (&A2 + &Ai[i]).into(); - } - // Now Ai = [A, 3A, 5A, 7A, 9A, 11A, 13A, 15A, ..., 127A] - NafLookupTable8(Ai) - } -} - -#[cfg(test)] -mod test { - use super::*; - - fn addition_test_helper(P: edwards::EdwardsPoint, Q: edwards::EdwardsPoint) { - // Test the serial implementation of the parallel addition formulas - //let R_serial: edwards::EdwardsPoint = serial_add(P.into(), Q.into()).into(); - - // Test the vector implementation of the parallel readdition formulas - let cached_Q = CachedPoint::from(ExtendedPoint::from(Q)); - let R_vector: edwards::EdwardsPoint = (&ExtendedPoint::from(P) + &cached_Q).into(); - let S_vector: edwards::EdwardsPoint = (&ExtendedPoint::from(P) - &cached_Q).into(); - - println!("Testing point addition:"); - println!("P = {:?}", P); - println!("Q = {:?}", Q); - println!("cached Q = {:?}", cached_Q); - println!("R = P + Q = {:?}", &P + &Q); - //println!("R_serial = {:?}", R_serial); - println!("R_vector = {:?}", R_vector); - println!("S = P - Q = {:?}", &P - &Q); - println!("S_vector = {:?}", S_vector); - //assert_eq!(R_serial.compress(), (&P + &Q).compress()); - assert_eq!(R_vector.compress(), (&P + &Q).compress()); - assert_eq!(S_vector.compress(), (&P - &Q).compress()); - println!("OK!\n"); - } - - #[test] - fn vector_addition_vs_serial_addition_vs_edwards_extendedpoint() { - use constants; - use scalar::Scalar; - - println!("Testing id +- id"); - let P = edwards::EdwardsPoint::identity(); - let Q = edwards::EdwardsPoint::identity(); - addition_test_helper(P, Q); - - println!("Testing id +- B"); - let P = edwards::EdwardsPoint::identity(); - let Q = constants::ED25519_BASEPOINT_POINT; - addition_test_helper(P, Q); - - println!("Testing B +- B"); - let P = constants::ED25519_BASEPOINT_POINT; - let Q = constants::ED25519_BASEPOINT_POINT; - addition_test_helper(P, Q); - - println!("Testing B +- kB"); - let P = constants::ED25519_BASEPOINT_POINT; - let Q = &constants::ED25519_BASEPOINT_TABLE * &Scalar::from(8475983829u64); - addition_test_helper(P, Q); - } - - fn doubling_test_helper(P: edwards::EdwardsPoint) { - //let R1: edwards::EdwardsPoint = serial_double(P.into()).into(); - let R2: edwards::EdwardsPoint = ExtendedPoint::from(P).double().into(); - println!("Testing point doubling:"); - println!("P = {:?}", P); - //println!("(serial) R1 = {:?}", R1); - println!("(vector) R2 = {:?}", R2); - println!("P + P = {:?}", &P + &P); - //assert_eq!(R1.compress(), (&P + &P).compress()); - assert_eq!(R2.compress(), (&P + &P).compress()); - println!("OK!\n"); - } - - #[test] - fn vector_doubling_vs_serial_doubling_vs_edwards_extendedpoint() { - use constants; - use scalar::Scalar; - - println!("Testing [2]id"); - let P = edwards::EdwardsPoint::identity(); - doubling_test_helper(P); - - println!("Testing [2]B"); - let P = constants::ED25519_BASEPOINT_POINT; - doubling_test_helper(P); - - println!("Testing [2]([k]B)"); - let P = &constants::ED25519_BASEPOINT_TABLE * &Scalar::from(8475983829u64); - doubling_test_helper(P); - } -} diff --git a/net/gurk-rs/files/vendor/curve25519-dalek-2.0.0/src/backend/vector/ifma/field.rs b/net/gurk-rs/files/vendor/curve25519-dalek-2.0.0/src/backend/vector/ifma/field.rs deleted file mode 100644 index 5b7c092..0000000 --- a/net/gurk-rs/files/vendor/curve25519-dalek-2.0.0/src/backend/vector/ifma/field.rs +++ /dev/null @@ -1,824 +0,0 @@ -// -*- mode: rust; coding: utf-8; -*- -// -// This file is part of curve25519-dalek. -// Copyright (c) 2018-2019 Henry de Valence -// See LICENSE for licensing information. -// -// Authors: -// - Henry de Valence - -#![allow(non_snake_case)] - -use core::ops::{Add, Mul, Neg}; -use packed_simd::{u64x4, IntoBits}; - -use backend::serial::u64::field::FieldElement51; - -/// A wrapper around `vpmadd52luq` that works on `u64x4`. -#[inline(always)] -unsafe fn madd52lo(z: u64x4, x: u64x4, y: u64x4) -> u64x4 { - use core::arch::x86_64::_mm256_madd52lo_epu64; - _mm256_madd52lo_epu64(z.into_bits(), x.into_bits(), y.into_bits()).into_bits() -} - -/// A wrapper around `vpmadd52huq` that works on `u64x4`. -#[inline(always)] -unsafe fn madd52hi(z: u64x4, x: u64x4, y: u64x4) -> u64x4 { - use core::arch::x86_64::_mm256_madd52hi_epu64; - _mm256_madd52hi_epu64(z.into_bits(), x.into_bits(), y.into_bits()).into_bits() -} - -/// A vector of four field elements in radix 2^51, with unreduced coefficients. -#[derive(Copy, Clone, Debug)] -pub struct F51x4Unreduced(pub(crate) [u64x4; 5]); - -/// A vector of four field elements in radix 2^51, with reduced coefficients. -#[derive(Copy, Clone, Debug)] -pub struct F51x4Reduced(pub(crate) [u64x4; 5]); - -#[derive(Copy, Clone)] -pub enum Shuffle { - AAAA, - BBBB, - BADC, - BACD, - ADDA, - CBCB, - ABDC, - ABAB, - DBBD, - CACA, -} - -#[inline(always)] -fn shuffle_lanes(x: u64x4, control: Shuffle) -> u64x4 { - unsafe { - use core::arch::x86_64::_mm256_permute4x64_epi64 as perm; - - match control { - Shuffle::AAAA => perm(x.into_bits(), 0b00_00_00_00).into_bits(), - Shuffle::BBBB => perm(x.into_bits(), 0b01_01_01_01).into_bits(), - Shuffle::BADC => perm(x.into_bits(), 0b10_11_00_01).into_bits(), - Shuffle::BACD => perm(x.into_bits(), 0b11_10_00_01).into_bits(), - Shuffle::ADDA => perm(x.into_bits(), 0b00_11_11_00).into_bits(), - Shuffle::CBCB => perm(x.into_bits(), 0b01_10_01_10).into_bits(), - Shuffle::ABDC => perm(x.into_bits(), 0b10_11_01_00).into_bits(), - Shuffle::ABAB => perm(x.into_bits(), 0b01_00_01_00).into_bits(), - Shuffle::DBBD => perm(x.into_bits(), 0b11_01_01_11).into_bits(), - Shuffle::CACA => perm(x.into_bits(), 0b00_10_00_10).into_bits(), - } - } -} - -#[derive(Copy, Clone)] -pub enum Lanes { - D, - C, - AB, - AC, - AD, - BCD, -} - -#[inline] -fn blend_lanes(x: u64x4, y: u64x4, control: Lanes) -> u64x4 { - unsafe { - use core::arch::x86_64::_mm256_blend_epi32 as blend; - - match control { - Lanes::D => blend(x.into_bits(), y.into_bits(), 0b11_00_00_00).into_bits(), - Lanes::C => blend(x.into_bits(), y.into_bits(), 0b00_11_00_00).into_bits(), - Lanes::AB => blend(x.into_bits(), y.into_bits(), 0b00_00_11_11).into_bits(), - Lanes::AC => blend(x.into_bits(), y.into_bits(), 0b00_11_00_11).into_bits(), - Lanes::AD => blend(x.into_bits(), y.into_bits(), 0b11_00_00_11).into_bits(), - Lanes::BCD => blend(x.into_bits(), y.into_bits(), 0b11_11_11_00).into_bits(), - } - } -} - -impl F51x4Unreduced { - pub fn zero() -> F51x4Unreduced { - F51x4Unreduced([u64x4::splat(0); 5]) - } - - pub fn new( - x0: &FieldElement51, - x1: &FieldElement51, - x2: &FieldElement51, - x3: &FieldElement51, - ) -> F51x4Unreduced { - F51x4Unreduced([ - u64x4::new(x0.0[0], x1.0[0], x2.0[0], x3.0[0]), - u64x4::new(x0.0[1], x1.0[1], x2.0[1], x3.0[1]), - u64x4::new(x0.0[2], x1.0[2], x2.0[2], x3.0[2]), - u64x4::new(x0.0[3], x1.0[3], x2.0[3], x3.0[3]), - u64x4::new(x0.0[4], x1.0[4], x2.0[4], x3.0[4]), - ]) - } - - pub fn split(&self) -> [FieldElement51; 4] { - let x = &self.0; - [ - FieldElement51([ - x[0].extract(0), - x[1].extract(0), - x[2].extract(0), - x[3].extract(0), - x[4].extract(0), - ]), - FieldElement51([ - x[0].extract(1), - x[1].extract(1), - x[2].extract(1), - x[3].extract(1), - x[4].extract(1), - ]), - FieldElement51([ - x[0].extract(2), - x[1].extract(2), - x[2].extract(2), - x[3].extract(2), - x[4].extract(2), - ]), - FieldElement51([ - x[0].extract(3), - x[1].extract(3), - x[2].extract(3), - x[3].extract(3), - x[4].extract(3), - ]), - ] - } - - #[inline] - pub fn diff_sum(&self) -> F51x4Unreduced { - // tmp1 = (B, A, D, C) - let tmp1 = self.shuffle(Shuffle::BADC); - // tmp2 = (-A, B, -C, D) - let tmp2 = self.blend(&self.negate_lazy(), Lanes::AC); - // (B - A, B + A, D - C, D + C) - tmp1 + tmp2 - } - - #[inline] - pub fn negate_lazy(&self) -> F51x4Unreduced { - let lo = u64x4::splat(36028797018963664u64); - let hi = u64x4::splat(36028797018963952u64); - F51x4Unreduced([ - lo - self.0[0], - hi - self.0[1], - hi - self.0[2], - hi - self.0[3], - hi - self.0[4], - ]) - } - - #[inline] - pub fn shuffle(&self, control: Shuffle) -> F51x4Unreduced { - F51x4Unreduced([ - shuffle_lanes(self.0[0], control), - shuffle_lanes(self.0[1], control), - shuffle_lanes(self.0[2], control), - shuffle_lanes(self.0[3], control), - shuffle_lanes(self.0[4], control), - ]) - } - - #[inline] - pub fn blend(&self, other: &F51x4Unreduced, control: Lanes) -> F51x4Unreduced { - F51x4Unreduced([ - blend_lanes(self.0[0], other.0[0], control), - blend_lanes(self.0[1], other.0[1], control), - blend_lanes(self.0[2], other.0[2], control), - blend_lanes(self.0[3], other.0[3], control), - blend_lanes(self.0[4], other.0[4], control), - ]) - } -} - -impl Neg for F51x4Reduced { - type Output = F51x4Reduced; - - fn neg(self) -> F51x4Reduced { - F51x4Unreduced::from(self).negate_lazy().into() - } -} - -use subtle::Choice; -use subtle::ConditionallySelectable; - -impl ConditionallySelectable for F51x4Reduced { - #[inline] - fn conditional_select(a: &F51x4Reduced, b: &F51x4Reduced, choice: Choice) -> F51x4Reduced { - let mask = (-(choice.unwrap_u8() as i64)) as u64; - let mask_vec = u64x4::splat(mask); - F51x4Reduced([ - a.0[0] ^ (mask_vec & (a.0[0] ^ b.0[0])), - a.0[1] ^ (mask_vec & (a.0[1] ^ b.0[1])), - a.0[2] ^ (mask_vec & (a.0[2] ^ b.0[2])), - a.0[3] ^ (mask_vec & (a.0[3] ^ b.0[3])), - a.0[4] ^ (mask_vec & (a.0[4] ^ b.0[4])), - ]) - } - - #[inline] - fn conditional_assign(&mut self, other: &F51x4Reduced, choice: Choice) { - let mask = (-(choice.unwrap_u8() as i64)) as u64; - let mask_vec = u64x4::splat(mask); - self.0[0] ^= mask_vec & (self.0[0] ^ other.0[0]); - self.0[1] ^= mask_vec & (self.0[1] ^ other.0[1]); - self.0[2] ^= mask_vec & (self.0[2] ^ other.0[2]); - self.0[3] ^= mask_vec & (self.0[3] ^ other.0[3]); - self.0[4] ^= mask_vec & (self.0[4] ^ other.0[4]); - } -} - -impl F51x4Reduced { - #[inline] - pub fn shuffle(&self, control: Shuffle) -> F51x4Reduced { - F51x4Reduced([ - shuffle_lanes(self.0[0], control), - shuffle_lanes(self.0[1], control), - shuffle_lanes(self.0[2], control), - shuffle_lanes(self.0[3], control), - shuffle_lanes(self.0[4], control), - ]) - } - - #[inline] - pub fn blend(&self, other: &F51x4Reduced, control: Lanes) -> F51x4Reduced { - F51x4Reduced([ - blend_lanes(self.0[0], other.0[0], control), - blend_lanes(self.0[1], other.0[1], control), - blend_lanes(self.0[2], other.0[2], control), - blend_lanes(self.0[3], other.0[3], control), - blend_lanes(self.0[4], other.0[4], control), - ]) - } - - #[inline] - pub fn square(&self) -> F51x4Unreduced { - unsafe { - let x = &self.0; - - // Represent values with coeff. 2 - let mut z0_2 = u64x4::splat(0); - let mut z1_2 = u64x4::splat(0); - let mut z2_2 = u64x4::splat(0); - let mut z3_2 = u64x4::splat(0); - let mut z4_2 = u64x4::splat(0); - let mut z5_2 = u64x4::splat(0); - let mut z6_2 = u64x4::splat(0); - let mut z7_2 = u64x4::splat(0); - let mut z9_2 = u64x4::splat(0); - - // Represent values with coeff. 4 - let mut z2_4 = u64x4::splat(0); - let mut z3_4 = u64x4::splat(0); - let mut z4_4 = u64x4::splat(0); - let mut z5_4 = u64x4::splat(0); - let mut z6_4 = u64x4::splat(0); - let mut z7_4 = u64x4::splat(0); - let mut z8_4 = u64x4::splat(0); - - let mut z0_1 = u64x4::splat(0); - z0_1 = madd52lo(z0_1, x[0], x[0]); - - let mut z1_1 = u64x4::splat(0); - z1_2 = madd52lo(z1_2, x[0], x[1]); - z1_2 = madd52hi(z1_2, x[0], x[0]); - - z2_4 = madd52hi(z2_4, x[0], x[1]); - let mut z2_1 = z2_4 << 2; - z2_2 = madd52lo(z2_2, x[0], x[2]); - z2_1 = madd52lo(z2_1, x[1], x[1]); - - z3_4 = madd52hi(z3_4, x[0], x[2]); - let mut z3_1 = z3_4 << 2; - z3_2 = madd52lo(z3_2, x[1], x[2]); - z3_2 = madd52lo(z3_2, x[0], x[3]); - z3_2 = madd52hi(z3_2, x[1], x[1]); - - z4_4 = madd52hi(z4_4, x[1], x[2]); - z4_4 = madd52hi(z4_4, x[0], x[3]); - let mut z4_1 = z4_4 << 2; - z4_2 = madd52lo(z4_2, x[1], x[3]); - z4_2 = madd52lo(z4_2, x[0], x[4]); - z4_1 = madd52lo(z4_1, x[2], x[2]); - - z5_4 = madd52hi(z5_4, x[1], x[3]); - z5_4 = madd52hi(z5_4, x[0], x[4]); - let mut z5_1 = z5_4 << 2; - z5_2 = madd52lo(z5_2, x[2], x[3]); - z5_2 = madd52lo(z5_2, x[1], x[4]); - z5_2 = madd52hi(z5_2, x[2], x[2]); - - z6_4 = madd52hi(z6_4, x[2], x[3]); - z6_4 = madd52hi(z6_4, x[1], x[4]); - let mut z6_1 = z6_4 << 2; - z6_2 = madd52lo(z6_2, x[2], x[4]); - z6_1 = madd52lo(z6_1, x[3], x[3]); - - z7_4 = madd52hi(z7_4, x[2], x[4]); - let mut z7_1 = z7_4 << 2; - z7_2 = madd52lo(z7_2, x[3], x[4]); - z7_2 = madd52hi(z7_2, x[3], x[3]); - - z8_4 = madd52hi(z8_4, x[3], x[4]); - let mut z8_1 = z8_4 << 2; - z8_1 = madd52lo(z8_1, x[4], x[4]); - - let mut z9_1 = u64x4::splat(0); - z9_2 = madd52hi(z9_2, x[4], x[4]); - - z5_1 += z5_2 << 1; - z6_1 += z6_2 << 1; - z7_1 += z7_2 << 1; - z9_1 += z9_2 << 1; - - let mut t0 = u64x4::splat(0); - let mut t1 = u64x4::splat(0); - let r19 = u64x4::splat(19); - - t0 = madd52hi(t0, r19, z9_1); - t1 = madd52lo(t1, r19, z9_1 >> 52); - - z4_2 = madd52lo(z4_2, r19, z8_1 >> 52); - z3_2 = madd52lo(z3_2, r19, z7_1 >> 52); - z2_2 = madd52lo(z2_2, r19, z6_1 >> 52); - z1_2 = madd52lo(z1_2, r19, z5_1 >> 52); - - z0_2 = madd52lo(z0_2, r19, t0 + t1); - z1_2 = madd52hi(z1_2, r19, z5_1); - z2_2 = madd52hi(z2_2, r19, z6_1); - z3_2 = madd52hi(z3_2, r19, z7_1); - z4_2 = madd52hi(z4_2, r19, z8_1); - - z0_1 = madd52lo(z0_1, r19, z5_1); - z1_1 = madd52lo(z1_1, r19, z6_1); - z2_1 = madd52lo(z2_1, r19, z7_1); - z3_1 = madd52lo(z3_1, r19, z8_1); - z4_1 = madd52lo(z4_1, r19, z9_1); - - F51x4Unreduced([ - z0_1 + z0_2 + z0_2, - z1_1 + z1_2 + z1_2, - z2_1 + z2_2 + z2_2, - z3_1 + z3_2 + z3_2, - z4_1 + z4_2 + z4_2, - ]) - } - } -} - -impl From for F51x4Unreduced { - #[inline] - fn from(x: F51x4Reduced) -> F51x4Unreduced { - F51x4Unreduced(x.0) - } -} - -impl From for F51x4Reduced { - #[inline] - fn from(x: F51x4Unreduced) -> F51x4Reduced { - let mask = u64x4::splat((1 << 51) - 1); - let r19 = u64x4::splat(19); - - // Compute carryouts in parallel - let c0 = x.0[0] >> 51; - let c1 = x.0[1] >> 51; - let c2 = x.0[2] >> 51; - let c3 = x.0[3] >> 51; - let c4 = x.0[4] >> 51; - - unsafe { - F51x4Reduced([ - madd52lo(x.0[0] & mask, c4, r19), - (x.0[1] & mask) + c0, - (x.0[2] & mask) + c1, - (x.0[3] & mask) + c2, - (x.0[4] & mask) + c3, - ]) - } - } -} - -impl Add for F51x4Unreduced { - type Output = F51x4Unreduced; - #[inline] - fn add(self, rhs: F51x4Unreduced) -> F51x4Unreduced { - F51x4Unreduced([ - self.0[0] + rhs.0[0], - self.0[1] + rhs.0[1], - self.0[2] + rhs.0[2], - self.0[3] + rhs.0[3], - self.0[4] + rhs.0[4], - ]) - } -} - -impl<'a> Mul<(u32, u32, u32, u32)> for &'a F51x4Reduced { - type Output = F51x4Unreduced; - #[inline] - fn mul(self, scalars: (u32, u32, u32, u32)) -> F51x4Unreduced { - unsafe { - let x = &self.0; - let y = u64x4::new( - scalars.0 as u64, - scalars.1 as u64, - scalars.2 as u64, - scalars.3 as u64, - ); - let r19 = u64x4::splat(19); - - let mut z0_1 = u64x4::splat(0); - let mut z1_1 = u64x4::splat(0); - let mut z2_1 = u64x4::splat(0); - let mut z3_1 = u64x4::splat(0); - let mut z4_1 = u64x4::splat(0); - let mut z1_2 = u64x4::splat(0); - let mut z2_2 = u64x4::splat(0); - let mut z3_2 = u64x4::splat(0); - let mut z4_2 = u64x4::splat(0); - let mut z5_2 = u64x4::splat(0); - - // Wave 0 - z4_2 = madd52hi(z4_2, y, x[3]); - z5_2 = madd52hi(z5_2, y, x[4]); - z4_1 = madd52lo(z4_1, y, x[4]); - z0_1 = madd52lo(z0_1, y, x[0]); - z3_1 = madd52lo(z3_1, y, x[3]); - z2_1 = madd52lo(z2_1, y, x[2]); - z1_1 = madd52lo(z1_1, y, x[1]); - z3_2 = madd52hi(z3_2, y, x[2]); - - // Wave 2 - z2_2 = madd52hi(z2_2, y, x[1]); - z1_2 = madd52hi(z1_2, y, x[0]); - z0_1 = madd52lo(z0_1, z5_2 + z5_2, r19); - - F51x4Unreduced([ - z0_1, - z1_1 + z1_2 + z1_2, - z2_1 + z2_2 + z2_2, - z3_1 + z3_2 + z3_2, - z4_1 + z4_2 + z4_2, - ]) - } - } -} - -impl<'a, 'b> Mul<&'b F51x4Reduced> for &'a F51x4Reduced { - type Output = F51x4Unreduced; - #[inline] - fn mul(self, rhs: &'b F51x4Reduced) -> F51x4Unreduced { - unsafe { - // Inputs - let x = &self.0; - let y = &rhs.0; - - // Accumulators for terms with coeff 1 - let mut z0_1 = u64x4::splat(0); - let mut z1_1 = u64x4::splat(0); - let mut z2_1 = u64x4::splat(0); - let mut z3_1 = u64x4::splat(0); - let mut z4_1 = u64x4::splat(0); - let mut z5_1 = u64x4::splat(0); - let mut z6_1 = u64x4::splat(0); - let mut z7_1 = u64x4::splat(0); - let mut z8_1 = u64x4::splat(0); - - // Accumulators for terms with coeff 2 - let mut z0_2 = u64x4::splat(0); - let mut z1_2 = u64x4::splat(0); - let mut z2_2 = u64x4::splat(0); - let mut z3_2 = u64x4::splat(0); - let mut z4_2 = u64x4::splat(0); - let mut z5_2 = u64x4::splat(0); - let mut z6_2 = u64x4::splat(0); - let mut z7_2 = u64x4::splat(0); - let mut z8_2 = u64x4::splat(0); - let mut z9_2 = u64x4::splat(0); - - // LLVM doesn't seem to do much work reordering IFMA - // instructions, so try to organize them into "waves" of 8 - // independent operations (4c latency, 0.5 c throughput - // means 8 in flight) - - // Wave 0 - z4_1 = madd52lo(z4_1, x[2], y[2]); - z5_2 = madd52hi(z5_2, x[2], y[2]); - z5_1 = madd52lo(z5_1, x[4], y[1]); - z6_2 = madd52hi(z6_2, x[4], y[1]); - z6_1 = madd52lo(z6_1, x[4], y[2]); - z7_2 = madd52hi(z7_2, x[4], y[2]); - z7_1 = madd52lo(z7_1, x[4], y[3]); - z8_2 = madd52hi(z8_2, x[4], y[3]); - - // Wave 1 - z4_1 = madd52lo(z4_1, x[3], y[1]); - z5_2 = madd52hi(z5_2, x[3], y[1]); - z5_1 = madd52lo(z5_1, x[3], y[2]); - z6_2 = madd52hi(z6_2, x[3], y[2]); - z6_1 = madd52lo(z6_1, x[3], y[3]); - z7_2 = madd52hi(z7_2, x[3], y[3]); - z7_1 = madd52lo(z7_1, x[3], y[4]); - z8_2 = madd52hi(z8_2, x[3], y[4]); - - // Wave 2 - z8_1 = madd52lo(z8_1, x[4], y[4]); - z9_2 = madd52hi(z9_2, x[4], y[4]); - z4_1 = madd52lo(z4_1, x[4], y[0]); - z5_2 = madd52hi(z5_2, x[4], y[0]); - z5_1 = madd52lo(z5_1, x[2], y[3]); - z6_2 = madd52hi(z6_2, x[2], y[3]); - z6_1 = madd52lo(z6_1, x[2], y[4]); - z7_2 = madd52hi(z7_2, x[2], y[4]); - - let z8 = z8_1 + z8_2 + z8_2; - let z9 = z9_2 + z9_2; - - // Wave 3 - z3_1 = madd52lo(z3_1, x[3], y[0]); - z4_2 = madd52hi(z4_2, x[3], y[0]); - z4_1 = madd52lo(z4_1, x[1], y[3]); - z5_2 = madd52hi(z5_2, x[1], y[3]); - z5_1 = madd52lo(z5_1, x[1], y[4]); - z6_2 = madd52hi(z6_2, x[1], y[4]); - z2_1 = madd52lo(z2_1, x[2], y[0]); - z3_2 = madd52hi(z3_2, x[2], y[0]); - - let z6 = z6_1 + z6_2 + z6_2; - let z7 = z7_1 + z7_2 + z7_2; - - // Wave 4 - z3_1 = madd52lo(z3_1, x[2], y[1]); - z4_2 = madd52hi(z4_2, x[2], y[1]); - z4_1 = madd52lo(z4_1, x[0], y[4]); - z5_2 = madd52hi(z5_2, x[0], y[4]); - z1_1 = madd52lo(z1_1, x[1], y[0]); - z2_2 = madd52hi(z2_2, x[1], y[0]); - z2_1 = madd52lo(z2_1, x[1], y[1]); - z3_2 = madd52hi(z3_2, x[1], y[1]); - - let z5 = z5_1 + z5_2 + z5_2; - - // Wave 5 - z3_1 = madd52lo(z3_1, x[1], y[2]); - z4_2 = madd52hi(z4_2, x[1], y[2]); - z0_1 = madd52lo(z0_1, x[0], y[0]); - z1_2 = madd52hi(z1_2, x[0], y[0]); - z1_1 = madd52lo(z1_1, x[0], y[1]); - z2_1 = madd52lo(z2_1, x[0], y[2]); - z2_2 = madd52hi(z2_2, x[0], y[1]); - z3_2 = madd52hi(z3_2, x[0], y[2]); - - let mut t0 = u64x4::splat(0); - let mut t1 = u64x4::splat(0); - let r19 = u64x4::splat(19); - - // Wave 6 - t0 = madd52hi(t0, r19, z9); - t1 = madd52lo(t1, r19, z9 >> 52); - z3_1 = madd52lo(z3_1, x[0], y[3]); - z4_2 = madd52hi(z4_2, x[0], y[3]); - z1_2 = madd52lo(z1_2, r19, z5 >> 52); - z2_2 = madd52lo(z2_2, r19, z6 >> 52); - z3_2 = madd52lo(z3_2, r19, z7 >> 52); - z0_1 = madd52lo(z0_1, r19, z5); - - // Wave 7 - z4_1 = madd52lo(z4_1, r19, z9); - z1_1 = madd52lo(z1_1, r19, z6); - z0_2 = madd52lo(z0_2, r19, t0 + t1); - z4_2 = madd52hi(z4_2, r19, z8); - z2_1 = madd52lo(z2_1, r19, z7); - z1_2 = madd52hi(z1_2, r19, z5); - z2_2 = madd52hi(z2_2, r19, z6); - z3_2 = madd52hi(z3_2, r19, z7); - - // Wave 8 - z3_1 = madd52lo(z3_1, r19, z8); - z4_2 = madd52lo(z4_2, r19, z8 >> 52); - - F51x4Unreduced([ - z0_1 + z0_2 + z0_2, - z1_1 + z1_2 + z1_2, - z2_1 + z2_2 + z2_2, - z3_1 + z3_2 + z3_2, - z4_1 + z4_2 + z4_2, - ]) - } - } -} - -#[cfg(test)] -mod test { - use super::*; - - #[test] - fn vpmadd52luq() { - let x = u64x4::splat(2); - let y = u64x4::splat(3); - let mut z = u64x4::splat(5); - - z = unsafe { madd52lo(z, x, y) }; - - assert_eq!(z, u64x4::splat(5 + 2 * 3)); - } - - #[test] - fn new_split_round_trip_on_reduced_input() { - // Invert a small field element to get a big one - let a = FieldElement51([2438, 24, 243, 0, 0]).invert(); - - let ax4 = F51x4Unreduced::new(&a, &a, &a, &a); - let splits = ax4.split(); - - for i in 0..4 { - assert_eq!(a, splits[i]); - } - } - - #[test] - fn new_split_round_trip_on_unreduced_input() { - // Invert a small field element to get a big one - let a = FieldElement51([2438, 24, 243, 0, 0]).invert(); - // ... but now multiply it by 16 without reducing coeffs - let a16 = FieldElement51([ - a.0[0] << 4, - a.0[1] << 4, - a.0[2] << 4, - a.0[3] << 4, - a.0[4] << 4, - ]); - - let a16x4 = F51x4Unreduced::new(&a16, &a16, &a16, &a16); - let splits = a16x4.split(); - - for i in 0..4 { - assert_eq!(a16, splits[i]); - } - } - - #[test] - fn test_reduction() { - // Invert a small field element to get a big one - let a = FieldElement51([2438, 24, 243, 0, 0]).invert(); - // ... but now multiply it by 128 without reducing coeffs - let abig = FieldElement51([ - a.0[0] << 4, - a.0[1] << 4, - a.0[2] << 4, - a.0[3] << 4, - a.0[4] << 4, - ]); - - let abigx4: F51x4Reduced = F51x4Unreduced::new(&abig, &abig, &abig, &abig).into(); - - let splits = F51x4Unreduced::from(abigx4).split(); - let c = &a * &FieldElement51([(1 << 4), 0, 0, 0, 0]); - - for i in 0..4 { - assert_eq!(c, splits[i]); - } - } - - #[test] - fn mul_matches_serial() { - // Invert a small field element to get a big one - let a = FieldElement51([2438, 24, 243, 0, 0]).invert(); - let b = FieldElement51([98098, 87987897, 0, 1, 0]).invert(); - let c = &a * &b; - - let ax4: F51x4Reduced = F51x4Unreduced::new(&a, &a, &a, &a).into(); - let bx4: F51x4Reduced = F51x4Unreduced::new(&b, &b, &b, &b).into(); - let cx4 = &ax4 * &bx4; - - let splits = cx4.split(); - - for i in 0..4 { - assert_eq!(c, splits[i]); - } - } - - #[test] - fn iterated_mul_matches_serial() { - // Invert a small field element to get a big one - let a = FieldElement51([2438, 24, 243, 0, 0]).invert(); - let b = FieldElement51([98098, 87987897, 0, 1, 0]).invert(); - let mut c = &a * &b; - for _i in 0..1024 { - c = &a * &c; - c = &b * &c; - } - - let ax4: F51x4Reduced = F51x4Unreduced::new(&a, &a, &a, &a).into(); - let bx4: F51x4Reduced = F51x4Unreduced::new(&b, &b, &b, &b).into(); - let mut cx4 = &ax4 * &bx4; - for _i in 0..1024 { - cx4 = &ax4 * &F51x4Reduced::from(cx4); - cx4 = &bx4 * &F51x4Reduced::from(cx4); - } - - let splits = cx4.split(); - - for i in 0..4 { - assert_eq!(c, splits[i]); - } - } - - #[test] - fn square_matches_mul() { - // Invert a small field element to get a big one - let a = FieldElement51([2438, 24, 243, 0, 0]).invert(); - - let ax4: F51x4Reduced = F51x4Unreduced::new(&a, &a, &a, &a).into(); - let cx4 = &ax4 * &ax4; - let cx4_sq = ax4.square(); - - let splits = cx4.split(); - let splits_sq = cx4_sq.split(); - - for i in 0..4 { - assert_eq!(splits_sq[i], splits[i]); - } - } - - #[test] - fn iterated_square_matches_serial() { - // Invert a small field element to get a big one - let mut a = FieldElement51([2438, 24, 243, 0, 0]).invert(); - let mut ax4 = F51x4Unreduced::new(&a, &a, &a, &a); - for _j in 0..1024 { - a = a.square(); - ax4 = F51x4Reduced::from(ax4).square(); - - let splits = ax4.split(); - for i in 0..4 { - assert_eq!(a, splits[i]); - } - } - } - - #[test] - fn iterated_u32_mul_matches_serial() { - // Invert a small field element to get a big one - let a = FieldElement51([2438, 24, 243, 0, 0]).invert(); - let b = FieldElement51([121665, 0, 0, 0, 0]); - let mut c = &a * &b; - for _i in 0..1024 { - c = &b * &c; - } - - let ax4 = F51x4Unreduced::new(&a, &a, &a, &a); - let bx4 = (121665u32, 121665u32, 121665u32, 121665u32); - let mut cx4 = &F51x4Reduced::from(ax4) * bx4; - for _i in 0..1024 { - cx4 = &F51x4Reduced::from(cx4) * bx4; - } - - let splits = cx4.split(); - - for i in 0..4 { - assert_eq!(c, splits[i]); - } - } - - #[test] - fn shuffle_AAAA() { - let x0 = FieldElement51::from_bytes(&[0x10; 32]); - let x1 = FieldElement51::from_bytes(&[0x11; 32]); - let x2 = FieldElement51::from_bytes(&[0x12; 32]); - let x3 = FieldElement51::from_bytes(&[0x13; 32]); - - let x = F51x4Unreduced::new(&x0, &x1, &x2, &x3); - - let y = x.shuffle(Shuffle::AAAA); - let splits = y.split(); - - assert_eq!(splits[0], x0); - assert_eq!(splits[1], x0); - assert_eq!(splits[2], x0); - assert_eq!(splits[3], x0); - } - - #[test] - fn blend_AB() { - let x0 = FieldElement51::from_bytes(&[0x10; 32]); - let x1 = FieldElement51::from_bytes(&[0x11; 32]); - let x2 = FieldElement51::from_bytes(&[0x12; 32]); - let x3 = FieldElement51::from_bytes(&[0x13; 32]); - - let x = F51x4Unreduced::new(&x0, &x1, &x2, &x3); - let z = F51x4Unreduced::new(&x3, &x2, &x1, &x0); - - let y = x.blend(&z, Lanes::AB); - let splits = y.split(); - - assert_eq!(splits[0], x3); - assert_eq!(splits[1], x2); - assert_eq!(splits[2], x2); - assert_eq!(splits[3], x3); - } -} diff --git a/net/gurk-rs/files/vendor/curve25519-dalek-2.0.0/src/backend/vector/ifma/mod.rs b/net/gurk-rs/files/vendor/curve25519-dalek-2.0.0/src/backend/vector/ifma/mod.rs deleted file mode 100644 index 6191ecc..0000000 --- a/net/gurk-rs/files/vendor/curve25519-dalek-2.0.0/src/backend/vector/ifma/mod.rs +++ /dev/null @@ -1,19 +0,0 @@ -// -*- mode: rust; -*- -// -// This file is part of curve25519-dalek. -// Copyright (c) 2018-2019 Henry de Valence -// See LICENSE for licensing information. -// -// Authors: -// - Henry de Valence - -#![cfg_attr( - feature = "nightly", - doc(include = "../../../../docs/ifma-notes.md") -)] - -pub mod field; - -pub mod edwards; - -pub mod constants; diff --git a/net/gurk-rs/files/vendor/curve25519-dalek-2.0.0/src/backend/vector/mod.rs b/net/gurk-rs/files/vendor/curve25519-dalek-2.0.0/src/backend/vector/mod.rs deleted file mode 100644 index 9726c71..0000000 --- a/net/gurk-rs/files/vendor/curve25519-dalek-2.0.0/src/backend/vector/mod.rs +++ /dev/null @@ -1,42 +0,0 @@ -// -*- mode: rust; -*- -// -// This file is part of curve25519-dalek. -// Copyright (c) 2016-2019 Isis Lovecruft, Henry de Valence -// See LICENSE for licensing information. -// -// Authors: -// - Isis Agora Lovecruft -// - Henry de Valence - -// Conditionally include the notes if we're on nightly (so we can include docs at all). -#![cfg_attr( - feature = "nightly", - doc(include = "../../../docs/parallel-formulas.md") -)] - -#[cfg(not(any(target_feature = "avx2", target_feature = "avx512ifma", rustdoc)))] -compile_error!("simd_backend selected without target_feature=+avx2 or +avx512ifma"); - -#[cfg(any( - all(target_feature = "avx2", not(target_feature = "avx512ifma")), - rustdoc -))] -#[doc(cfg(all(target_feature = "avx2", not(target_feature = "avx512ifma"))))] -pub mod avx2; -#[cfg(any( - all(target_feature = "avx2", not(target_feature = "avx512ifma")), - rustdoc -))] -pub(crate) use self::avx2::{ - constants::BASEPOINT_ODD_LOOKUP_TABLE, edwards::CachedPoint, edwards::ExtendedPoint, -}; - -#[cfg(any(target_feature = "avx512ifma", rustdoc))] -#[doc(cfg(target_feature = "avx512ifma"))] -pub mod ifma; -#[cfg(target_feature = "avx512ifma")] -pub(crate) use self::ifma::{ - constants::BASEPOINT_ODD_LOOKUP_TABLE, edwards::CachedPoint, edwards::ExtendedPoint, -}; - -pub mod scalar_mul; diff --git a/net/gurk-rs/files/vendor/curve25519-dalek-2.0.0/src/backend/vector/scalar_mul/mod.rs b/net/gurk-rs/files/vendor/curve25519-dalek-2.0.0/src/backend/vector/scalar_mul/mod.rs deleted file mode 100644 index 2fc1b18..0000000 --- a/net/gurk-rs/files/vendor/curve25519-dalek-2.0.0/src/backend/vector/scalar_mul/mod.rs +++ /dev/null @@ -1,22 +0,0 @@ -// -*- mode: rust; -*- -// -// This file is part of curve25519-dalek. -// Copyright (c) 2016-2019 Isis Lovecruft, Henry de Valence -// See LICENSE for licensing information. -// -// Authors: -// - Isis Agora Lovecruft -// - Henry de Valence - -pub mod variable_base; - -pub mod vartime_double_base; - -#[cfg(feature = "alloc")] -pub mod straus; - -#[cfg(feature = "alloc")] -pub mod precomputed_straus; - -#[cfg(feature = "alloc")] -pub mod pippenger; diff --git a/net/gurk-rs/files/vendor/curve25519-dalek-2.0.0/src/backend/vector/scalar_mul/pippenger.rs b/net/gurk-rs/files/vendor/curve25519-dalek-2.0.0/src/backend/vector/scalar_mul/pippenger.rs deleted file mode 100644 index 7f9e241..0000000 --- a/net/gurk-rs/files/vendor/curve25519-dalek-2.0.0/src/backend/vector/scalar_mul/pippenger.rs +++ /dev/null @@ -1,164 +0,0 @@ -// -*- mode: rust; -*- -// -// This file is part of curve25519-dalek. -// Copyright (c) 2019 Oleg Andreev -// See LICENSE for licensing information. -// -// Authors: -// - Oleg Andreev - -#![allow(non_snake_case)] - -use core::borrow::Borrow; - -use backend::vector::{CachedPoint, ExtendedPoint}; -use edwards::EdwardsPoint; -use scalar::Scalar; -use traits::{Identity, VartimeMultiscalarMul}; - -#[allow(unused_imports)] -use prelude::*; - -/// Implements a version of Pippenger's algorithm. -/// -/// See the documentation in the serial `scalar_mul::pippenger` module for details. -pub struct Pippenger; - -#[cfg(any(feature = "alloc", feature = "std"))] -impl VartimeMultiscalarMul for Pippenger { - type Point = EdwardsPoint; - - fn optional_multiscalar_mul(scalars: I, points: J) -> Option - where - I: IntoIterator, - I::Item: Borrow, - J: IntoIterator>, - { - let mut scalars = scalars.into_iter(); - let size = scalars.by_ref().size_hint().0; - let w = if size < 500 { - 6 - } else if size < 800 { - 7 - } else { - 8 - }; - - let max_digit: usize = 1 << w; - let digits_count: usize = Scalar::to_radix_2w_size_hint(w); - let buckets_count: usize = max_digit / 2; // digits are signed+centered hence 2^w/2, excluding 0-th bucket - - // Collect optimized scalars and points in a buffer for repeated access - // (scanning the whole collection per each digit position). - let scalars = scalars - .into_iter() - .map(|s| s.borrow().to_radix_2w(w)); - - let points = points - .into_iter() - .map(|p| p.map(|P| CachedPoint::from(ExtendedPoint::from(P)))); - - let scalars_points = scalars - .zip(points) - .map(|(s, maybe_p)| maybe_p.map(|p| (s, p))) - .collect::>>()?; - - // Prepare 2^w/2 buckets. - // buckets[i] corresponds to a multiplication factor (i+1). - let mut buckets: Vec = (0..buckets_count) - .map(|_| ExtendedPoint::identity()) - .collect(); - - let mut columns = (0..digits_count).rev().map(|digit_index| { - // Clear the buckets when processing another digit. - for i in 0..buckets_count { - buckets[i] = ExtendedPoint::identity(); - } - - // Iterate over pairs of (point, scalar) - // and add/sub the point to the corresponding bucket. - // Note: if we add support for precomputed lookup tables, - // we'll be adding/subtractiong point premultiplied by `digits[i]` to buckets[0]. - for (digits, pt) in scalars_points.iter() { - // Widen digit so that we don't run into edge cases when w=8. - let digit = digits[digit_index] as i16; - if digit > 0 { - let b = (digit - 1) as usize; - buckets[b] = &buckets[b] + pt; - } else if digit < 0 { - let b = (-digit - 1) as usize; - buckets[b] = &buckets[b] - pt; - } - } - - // Add the buckets applying the multiplication factor to each bucket. - // The most efficient way to do that is to have a single sum with two running sums: - // an intermediate sum from last bucket to the first, and a sum of intermediate sums. - // - // For example, to add buckets 1*A, 2*B, 3*C we need to add these points: - // C - // C B - // C B A Sum = C + (C+B) + (C+B+A) - let mut buckets_intermediate_sum = buckets[buckets_count - 1]; - let mut buckets_sum = buckets[buckets_count - 1]; - for i in (0..(buckets_count - 1)).rev() { - buckets_intermediate_sum = - &buckets_intermediate_sum + &CachedPoint::from(buckets[i]); - buckets_sum = &buckets_sum + &CachedPoint::from(buckets_intermediate_sum); - } - - buckets_sum - }); - - // Take the high column as an initial value to avoid wasting time doubling the identity element in `fold()`. - // `unwrap()` always succeeds because we know we have more than zero digits. - let hi_column = columns.next().unwrap(); - - Some( - columns - .fold(hi_column, |total, p| { - &total.mul_by_pow_2(w as u32) + &CachedPoint::from(p) - }) - .into(), - ) - } -} - -#[cfg(test)] -mod test { - use super::*; - use constants; - use scalar::Scalar; - - #[test] - fn test_vartime_pippenger() { - // Reuse points across different tests - let mut n = 512; - let x = Scalar::from(2128506u64).invert(); - let y = Scalar::from(4443282u64).invert(); - let points: Vec<_> = (0..n) - .map(|i| constants::ED25519_BASEPOINT_POINT * Scalar::from(1 + i as u64)) - .collect(); - let scalars: Vec<_> = (0..n) - .map(|i| x + (Scalar::from(i as u64) * y)) // fast way to make ~random but deterministic scalars - .collect(); - - let premultiplied: Vec = scalars - .iter() - .zip(points.iter()) - .map(|(sc, pt)| sc * pt) - .collect(); - - while n > 0 { - let scalars = &scalars[0..n].to_vec(); - let points = &points[0..n].to_vec(); - let control: EdwardsPoint = premultiplied[0..n].iter().sum(); - - let subject = Pippenger::vartime_multiscalar_mul(scalars.clone(), points.clone()); - - assert_eq!(subject.compress(), control.compress()); - - n = n / 2; - } - } -} diff --git a/net/gurk-rs/files/vendor/curve25519-dalek-2.0.0/src/backend/vector/scalar_mul/precomputed_straus.rs b/net/gurk-rs/files/vendor/curve25519-dalek-2.0.0/src/backend/vector/scalar_mul/precomputed_straus.rs deleted file mode 100644 index 2c6fdf5..0000000 --- a/net/gurk-rs/files/vendor/curve25519-dalek-2.0.0/src/backend/vector/scalar_mul/precomputed_straus.rs +++ /dev/null @@ -1,107 +0,0 @@ -// -*- mode: rust; -*- -// -// This file is part of curve25519-dalek. -// Copyright (c) 2019 Henry de Valence. -// See LICENSE for licensing information. -// -// Authors: -// - Henry de Valence - -//! Precomputation for Straus's method. - -#![allow(non_snake_case)] - -use core::borrow::Borrow; - -use backend::vector::{CachedPoint, ExtendedPoint}; -use edwards::EdwardsPoint; -use scalar::Scalar; -use traits::Identity; -use traits::VartimePrecomputedMultiscalarMul; -use window::{NafLookupTable5, NafLookupTable8}; - -#[allow(unused_imports)] -use prelude::*; - - -pub struct VartimePrecomputedStraus { - static_lookup_tables: Vec>, -} - -impl VartimePrecomputedMultiscalarMul for VartimePrecomputedStraus { - type Point = EdwardsPoint; - - fn new(static_points: I) -> Self - where - I: IntoIterator, - I::Item: Borrow, - { - Self { - static_lookup_tables: static_points - .into_iter() - .map(|P| NafLookupTable8::::from(P.borrow())) - .collect(), - } - } - - fn optional_mixed_multiscalar_mul( - &self, - static_scalars: I, - dynamic_scalars: J, - dynamic_points: K, - ) -> Option - where - I: IntoIterator, - I::Item: Borrow, - J: IntoIterator, - J::Item: Borrow, - K: IntoIterator>, - { - let static_nafs = static_scalars - .into_iter() - .map(|c| c.borrow().non_adjacent_form(5)) - .collect::>(); - let dynamic_nafs: Vec<_> = dynamic_scalars - .into_iter() - .map(|c| c.borrow().non_adjacent_form(5)) - .collect::>(); - - let dynamic_lookup_tables = dynamic_points - .into_iter() - .map(|P_opt| P_opt.map(|P| NafLookupTable5::::from(&P))) - .collect::>>()?; - - let sp = self.static_lookup_tables.len(); - let dp = dynamic_lookup_tables.len(); - assert_eq!(sp, static_nafs.len()); - assert_eq!(dp, dynamic_nafs.len()); - - // We could save some doublings by looking for the highest - // nonzero NAF coefficient, but since we might have a lot of - // them to search, it's not clear it's worthwhile to check. - let mut R = ExtendedPoint::identity(); - for j in (0..256).rev() { - R = R.double(); - - for i in 0..dp { - let t_ij = dynamic_nafs[i][j]; - if t_ij > 0 { - R = &R + &dynamic_lookup_tables[i].select(t_ij as usize); - } else if t_ij < 0 { - R = &R - &dynamic_lookup_tables[i].select(-t_ij as usize); - } - } - - for i in 0..sp { - let t_ij = static_nafs[i][j]; - if t_ij > 0 { - R = &R + &self.static_lookup_tables[i].select(t_ij as usize); - } else if t_ij < 0 { - R = &R - &self.static_lookup_tables[i].select(-t_ij as usize); - } - } - } - - Some(R.into()) - } -} diff --git a/net/gurk-rs/files/vendor/curve25519-dalek-2.0.0/src/backend/vector/scalar_mul/straus.rs b/net/gurk-rs/files/vendor/curve25519-dalek-2.0.0/src/backend/vector/scalar_mul/straus.rs deleted file mode 100644 index 7206cf3..0000000 --- a/net/gurk-rs/files/vendor/curve25519-dalek-2.0.0/src/backend/vector/scalar_mul/straus.rs +++ /dev/null @@ -1,107 +0,0 @@ -// -*- mode: rust; -*- -// -// This file is part of curve25519-dalek. -// Copyright (c) 2016-2019 Isis Lovecruft, Henry de Valence -// See LICENSE for licensing information. -// -// Authors: -// - Isis Agora Lovecruft -// - Henry de Valence - -#![allow(non_snake_case)] - -use core::borrow::Borrow; - -use zeroize::Zeroizing; - -use backend::vector::{CachedPoint, ExtendedPoint}; -use edwards::EdwardsPoint; -use scalar::Scalar; -use window::{LookupTable, NafLookupTable5}; -use traits::{Identity, MultiscalarMul, VartimeMultiscalarMul}; - -#[allow(unused_imports)] -use prelude::*; - -/// Multiscalar multiplication using interleaved window / Straus' -/// method. See the `Straus` struct in the serial backend for more -/// details. -/// -/// This exists as a seperate implementation from that one because the -/// AVX2 code uses different curve models (it does not pass between -/// multiple models during scalar mul), and it has to convert the -/// point representation on the fly. -pub struct Straus {} - -impl MultiscalarMul for Straus { - type Point = EdwardsPoint; - - fn multiscalar_mul(scalars: I, points: J) -> EdwardsPoint - where - I: IntoIterator, - I::Item: Borrow, - J: IntoIterator, - J::Item: Borrow, - { - // Construct a lookup table of [P,2P,3P,4P,5P,6P,7P,8P] - // for each input point P - let lookup_tables: Vec<_> = points - .into_iter() - .map(|point| LookupTable::::from(point.borrow())) - .collect(); - - let scalar_digits_vec: Vec<_> = scalars - .into_iter() - .map(|s| s.borrow().to_radix_16()) - .collect(); - // Pass ownership to a `Zeroizing` wrapper - let scalar_digits = Zeroizing::new(scalar_digits_vec); - - let mut Q = ExtendedPoint::identity(); - for j in (0..64).rev() { - Q = Q.mul_by_pow_2(4); - let it = scalar_digits.iter().zip(lookup_tables.iter()); - for (s_i, lookup_table_i) in it { - // Q = Q + s_{i,j} * P_i - Q = &Q + &lookup_table_i.select(s_i[j]); - } - } - Q.into() - } -} - -impl VartimeMultiscalarMul for Straus { - type Point = EdwardsPoint; - - fn optional_multiscalar_mul(scalars: I, points: J) -> Option - where - I: IntoIterator, - I::Item: Borrow, - J: IntoIterator>, - { - let nafs: Vec<_> = scalars - .into_iter() - .map(|c| c.borrow().non_adjacent_form(5)) - .collect(); - let lookup_tables: Vec<_> = points - .into_iter() - .map(|P_opt| P_opt.map(|P| NafLookupTable5::::from(&P))) - .collect::>>()?; - - let mut Q = ExtendedPoint::identity(); - - for i in (0..256).rev() { - Q = Q.double(); - - for (naf, lookup_table) in nafs.iter().zip(lookup_tables.iter()) { - if naf[i] > 0 { - Q = &Q + &lookup_table.select(naf[i] as usize); - } else if naf[i] < 0 { - Q = &Q - &lookup_table.select(-naf[i] as usize); - } - } - } - - Some(Q.into()) - } -} diff --git a/net/gurk-rs/files/vendor/curve25519-dalek-2.0.0/src/backend/vector/scalar_mul/variable_base.rs b/net/gurk-rs/files/vendor/curve25519-dalek-2.0.0/src/backend/vector/scalar_mul/variable_base.rs deleted file mode 100644 index f53c4a0..0000000 --- a/net/gurk-rs/files/vendor/curve25519-dalek-2.0.0/src/backend/vector/scalar_mul/variable_base.rs +++ /dev/null @@ -1,32 +0,0 @@ -#![allow(non_snake_case)] - -use backend::vector::{CachedPoint, ExtendedPoint}; -use edwards::EdwardsPoint; -use scalar::Scalar; -use traits::Identity; -use window::LookupTable; - -/// Perform constant-time, variable-base scalar multiplication. -pub fn mul(point: &EdwardsPoint, scalar: &Scalar) -> EdwardsPoint { - // Construct a lookup table of [P,2P,3P,4P,5P,6P,7P,8P] - let lookup_table = LookupTable::::from(point); - // Setting s = scalar, compute - // - // s = s_0 + s_1*16^1 + ... + s_63*16^63, - // - // with `-8 ≤ s_i < 8` for `0 ≤ i < 63` and `-8 ≤ s_63 ≤ 8`. - let scalar_digits = scalar.to_radix_16(); - // Compute s*P as - // - // s*P = P*(s_0 + s_1*16^1 + s_2*16^2 + ... + s_63*16^63) - // s*P = P*s_0 + P*s_1*16^1 + P*s_2*16^2 + ... + P*s_63*16^63 - // s*P = P*s_0 + 16*(P*s_1 + 16*(P*s_2 + 16*( ... + P*s_63)...)) - // - // We sum right-to-left. - let mut Q = ExtendedPoint::identity(); - for i in (0..64).rev() { - Q = Q.mul_by_pow_2(4); - Q = &Q + &lookup_table.select(scalar_digits[i]); - } - Q.into() -} diff --git a/net/gurk-rs/files/vendor/curve25519-dalek-2.0.0/src/backend/vector/scalar_mul/vartime_double_base.rs b/net/gurk-rs/files/vendor/curve25519-dalek-2.0.0/src/backend/vector/scalar_mul/vartime_double_base.rs deleted file mode 100644 index d78e46d..0000000 --- a/net/gurk-rs/files/vendor/curve25519-dalek-2.0.0/src/backend/vector/scalar_mul/vartime_double_base.rs +++ /dev/null @@ -1,60 +0,0 @@ -// -*- mode: rust; -*- -// -// This file is part of curve25519-dalek. -// Copyright (c) 2016-2019 Isis Lovecruft, Henry de Valence -// See LICENSE for licensing information. -// -// Authors: -// - Isis Agora Lovecruft -// - Henry de Valence -#![allow(non_snake_case)] - -use backend::vector::BASEPOINT_ODD_LOOKUP_TABLE; -use backend::vector::{CachedPoint, ExtendedPoint}; -use edwards::EdwardsPoint; -use scalar::Scalar; -use traits::Identity; -use window::NafLookupTable5; - -/// Compute \\(aA + bB\\) in variable time, where \\(B\\) is the Ed25519 basepoint. -pub fn mul(a: &Scalar, A: &EdwardsPoint, b: &Scalar) -> EdwardsPoint { - let a_naf = a.non_adjacent_form(5); - let b_naf = b.non_adjacent_form(8); - - // Find starting index - let mut i: usize = 255; - for j in (0..256).rev() { - i = j; - if a_naf[i] != 0 || b_naf[i] != 0 { - break; - } - } - - let table_A = NafLookupTable5::::from(A); - let table_B = &BASEPOINT_ODD_LOOKUP_TABLE; - - let mut Q = ExtendedPoint::identity(); - - loop { - Q = Q.double(); - - if a_naf[i] > 0 { - Q = &Q + &table_A.select(a_naf[i] as usize); - } else if a_naf[i] < 0 { - Q = &Q - &table_A.select(-a_naf[i] as usize); - } - - if b_naf[i] > 0 { - Q = &Q + &table_B.select(b_naf[i] as usize); - } else if b_naf[i] < 0 { - Q = &Q - &table_B.select(-b_naf[i] as usize); - } - - if i == 0 { - break; - } - i -= 1; - } - - Q.into() -} diff --git a/net/gurk-rs/files/vendor/curve25519-dalek-2.0.0/src/constants.rs b/net/gurk-rs/files/vendor/curve25519-dalek-2.0.0/src/constants.rs deleted file mode 100644 index e30d35e..0000000 --- a/net/gurk-rs/files/vendor/curve25519-dalek-2.0.0/src/constants.rs +++ /dev/null @@ -1,176 +0,0 @@ -// -*- mode: rust; -*- -// -// This file is part of curve25519-dalek. -// Copyright (c) 2016-2019 Isis Lovecruft, Henry de Valence -// See LICENSE for licensing information. -// -// Authors: -// - Isis Agora Lovecruft -// - Henry de Valence - -//! Various constants, such as the Ristretto and Ed25519 basepoints. -//! -//! Most of the constants are given with -//! `LONG_DESCRIPTIVE_UPPER_CASE_NAMES`, but they can be brought into -//! scope using a `let` binding: -//! -//! ``` -//! use curve25519_dalek::constants; -//! use curve25519_dalek::traits::IsIdentity; -//! -//! let B = &constants::RISTRETTO_BASEPOINT_TABLE; -//! let l = &constants::BASEPOINT_ORDER; -//! -//! let A = l * B; -//! assert!(A.is_identity()); -//! ``` - -#![allow(non_snake_case)] - -use edwards::CompressedEdwardsY; -use ristretto::RistrettoPoint; -use ristretto::CompressedRistretto; -use montgomery::MontgomeryPoint; -use scalar::Scalar; - -#[cfg(feature = "u64_backend")] -pub use backend::serial::u64::constants::*; -#[cfg(feature = "u32_backend")] -pub use backend::serial::u32::constants::*; - -/// The Ed25519 basepoint, in `CompressedEdwardsY` format. -/// -/// This is the little-endian byte encoding of \\( 4/5 \pmod p \\), -/// which is the \\(y\\)-coordinate of the Ed25519 basepoint. -/// -/// The sign bit is 0 since the basepoint has \\(x\\) chosen to be positive. -pub const ED25519_BASEPOINT_COMPRESSED: CompressedEdwardsY = - CompressedEdwardsY([0x58, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, - 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, - 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, - 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66]); - -/// The X25519 basepoint, in `MontgomeryPoint` format. -pub const X25519_BASEPOINT: MontgomeryPoint = - MontgomeryPoint([0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]); - -/// The Ristretto basepoint, in `CompressedRistretto` format. -pub const RISTRETTO_BASEPOINT_COMPRESSED: CompressedRistretto = - CompressedRistretto([0xe2, 0xf2, 0xae, 0x0a, 0x6a, 0xbc, 0x4e, 0x71, - 0xa8, 0x84, 0xa9, 0x61, 0xc5, 0x00, 0x51, 0x5f, - 0x58, 0xe3, 0x0b, 0x6a, 0xa5, 0x82, 0xdd, 0x8d, - 0xb6, 0xa6, 0x59, 0x45, 0xe0, 0x8d, 0x2d, 0x76]); - -/// The Ristretto basepoint, as a `RistrettoPoint`. -/// -/// This is called `_POINT` to distinguish it from `_TABLE`, which -/// provides fast scalar multiplication. -pub const RISTRETTO_BASEPOINT_POINT: RistrettoPoint = RistrettoPoint(ED25519_BASEPOINT_POINT); - -/// `BASEPOINT_ORDER` is the order of the Ristretto group and of the Ed25519 basepoint, i.e., -/// $$ -/// \ell = 2^\{252\} + 27742317777372353535851937790883648493. -/// $$ -pub const BASEPOINT_ORDER: Scalar = Scalar{ - bytes: [ - 0xed, 0xd3, 0xf5, 0x5c, 0x1a, 0x63, 0x12, 0x58, - 0xd6, 0x9c, 0xf7, 0xa2, 0xde, 0xf9, 0xde, 0x14, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, - ], -}; - -use ristretto::RistrettoBasepointTable; -/// The Ristretto basepoint, as a `RistrettoBasepointTable` for scalar multiplication. -pub const RISTRETTO_BASEPOINT_TABLE: RistrettoBasepointTable - = RistrettoBasepointTable(ED25519_BASEPOINT_TABLE); - -#[cfg(test)] -mod test { - use field::FieldElement; - use traits::{IsIdentity, ValidityCheck}; - use constants; - - #[test] - fn test_eight_torsion() { - for i in 0..8 { - let Q = constants::EIGHT_TORSION[i].mul_by_pow_2(3); - assert!(Q.is_valid()); - assert!(Q.is_identity()); - } - } - - #[test] - fn test_four_torsion() { - for i in (0..8).filter(|i| i % 2 == 0) { - let Q = constants::EIGHT_TORSION[i].mul_by_pow_2(2); - assert!(Q.is_valid()); - assert!(Q.is_identity()); - } - } - - #[test] - fn test_two_torsion() { - for i in (0..8).filter(|i| i % 4 == 0) { - let Q = constants::EIGHT_TORSION[i].mul_by_pow_2(1); - assert!(Q.is_valid()); - assert!(Q.is_identity()); - } - } - - /// Test that SQRT_M1 is the positive square root of -1 - #[test] - fn test_sqrt_minus_one() { - let minus_one = FieldElement::minus_one(); - let sqrt_m1_sq = &constants::SQRT_M1 * &constants::SQRT_M1; - assert_eq!(minus_one, sqrt_m1_sq); - assert_eq!(constants::SQRT_M1.is_negative().unwrap_u8(), 0); - } - - #[test] - fn test_sqrt_constants_sign() { - let minus_one = FieldElement::minus_one(); - let (was_nonzero_square, invsqrt_m1) = minus_one.invsqrt(); - assert_eq!(was_nonzero_square.unwrap_u8(), 1u8); - let sign_test_sqrt = &invsqrt_m1 * &constants::SQRT_M1; - assert_eq!(sign_test_sqrt, minus_one); - } - - /// Test that d = -121665/121666 - #[test] - #[cfg(feature = "u32_backend")] - fn test_d_vs_ratio() { - use backend::serial::u32::field::FieldElement2625; - let a = -&FieldElement2625([121665,0,0,0,0,0,0,0,0,0]); - let b = FieldElement2625([121666,0,0,0,0,0,0,0,0,0]); - let d = &a * &b.invert(); - let d2 = &d + &d; - assert_eq!(d, constants::EDWARDS_D); - assert_eq!(d2, constants::EDWARDS_D2); - } - - /// Test that d = -121665/121666 - #[test] - #[cfg(feature = "u64_backend")] - fn test_d_vs_ratio() { - use backend::serial::u64::field::FieldElement51; - let a = -&FieldElement51([121665,0,0,0,0]); - let b = FieldElement51([121666,0,0,0,0]); - let d = &a * &b.invert(); - let d2 = &d + &d; - assert_eq!(d, constants::EDWARDS_D); - assert_eq!(d2, constants::EDWARDS_D2); - } - - #[test] - fn test_sqrt_ad_minus_one() { - let a = FieldElement::minus_one(); - let ad_minus_one = &(&a * &constants::EDWARDS_D) + &a; - let should_be_ad_minus_one = constants::SQRT_AD_MINUS_ONE.square(); - assert_eq!(should_be_ad_minus_one, ad_minus_one); - } - -} diff --git a/net/gurk-rs/files/vendor/curve25519-dalek-2.0.0/src/edwards.rs b/net/gurk-rs/files/vendor/curve25519-dalek-2.0.0/src/edwards.rs deleted file mode 100644 index 998af8d..0000000 --- a/net/gurk-rs/files/vendor/curve25519-dalek-2.0.0/src/edwards.rs +++ /dev/null @@ -1,1435 +0,0 @@ -// -*- mode: rust; -*- -// -// This file is part of curve25519-dalek. -// Copyright (c) 2016-2019 Isis Lovecruft, Henry de Valence -// See LICENSE for licensing information. -// -// Authors: -// - Isis Agora Lovecruft -// - Henry de Valence - -//! Group operations for Curve25519, in Edwards form. -//! -//! ## Encoding and Decoding -//! -//! Encoding is done by converting to and from a `CompressedEdwardsY` -//! struct, which is a typed wrapper around `[u8; 32]`. -//! -//! ## Equality Testing -//! -//! The `EdwardsPoint` struct implements the `subtle::ConstantTimeEq` -//! trait for constant-time equality checking, and the Rust `Eq` trait -//! for variable-time equality checking. -//! -//! ## Cofactor-related functions -//! -//! The order of the group of points on the curve \\(\mathcal E\\) -//! is \\(|\mathcal E| = 8\ell \\), so its structure is \\( \mathcal -//! E = \mathcal E[8] \times \mathcal E[\ell]\\). The torsion -//! subgroup \\( \mathcal E[8] \\) consists of eight points of small -//! order. Technically, all of \\(\mathcal E\\) is torsion, but we -//! use the word only to refer to the small \\(\mathcal E[8]\\) part, not -//! the large prime-order \\(\mathcal E[\ell]\\) part. -//! -//! To test if a point is in \\( \mathcal E[8] \\), use -//! `EdwardsPoint::is_small_order()`. -//! -//! To test if a point is in \\( \mathcal E[\ell] \\), use -//! `EdwardsPoint::is_torsion_free()`. -//! -//! To multiply by the cofactor, use `EdwardsPoint::mul_by_cofactor()`. -//! -//! To avoid dealing with cofactors entirely, consider using Ristretto. -//! -//! ## Scalars -//! -//! Scalars are represented by the `Scalar` struct. To construct a scalar with a specific bit -//! pattern, see `Scalar::from_bits()`. -//! -//! ## Scalar Multiplication -//! -//! Scalar multiplication on Edwards points is provided by: -//! -//! * the `*` operator between a `Scalar` and a `EdwardsPoint`, which -//! performs constant-time variable-base scalar multiplication; -//! -//! * the `*` operator between a `Scalar` and a -//! `EdwardsBasepointTable`, which performs constant-time fixed-base -//! scalar multiplication; -//! -//! * an implementation of the -//! [`MultiscalarMul`](../traits/trait.MultiscalarMul.html) trait for -//! constant-time variable-base multiscalar multiplication; -//! -//! * an implementation of the -//! [`VartimeMultiscalarMul`](../traits/trait.VartimeMultiscalarMul.html) -//! trait for variable-time variable-base multiscalar multiplication; -//! -//! ## Implementation -//! -//! The Edwards arithmetic is implemented using the “extended twisted -//! coordinates” of Hisil, Wong, Carter, and Dawson, and the -//! corresponding complete formulas. For more details, -//! see the [`curve_models` submodule][curve_models] -//! of the internal documentation. -//! -//! ## Validity Checking -//! -//! There is no function for checking whether a point is valid. -//! Instead, the `EdwardsPoint` struct is guaranteed to hold a valid -//! point on the curve. -//! -//! We use the Rust type system to make invalid points -//! unrepresentable: `EdwardsPoint` objects can only be created via -//! successful decompression of a compressed point, or else by -//! operations on other (valid) `EdwardsPoint`s. -//! -//! [curve_models]: https://doc-internal.dalek.rs/curve25519_dalek/backend/serial/curve_models/index.html - -// We allow non snake_case names because coordinates in projective space are -// traditionally denoted by the capitalisation of their respective -// counterparts in affine space. Yeah, you heard me, rustc, I'm gonna have my -// affine and projective cakes and eat both of them too. -#![allow(non_snake_case)] - -use core::borrow::Borrow; -use core::fmt::Debug; -use core::iter::Iterator; -use core::iter::Sum; -use core::ops::{Add, Neg, Sub}; -use core::ops::{AddAssign, SubAssign}; -use core::ops::{Mul, MulAssign}; - -use subtle::Choice; -use subtle::ConditionallyNegatable; -use subtle::ConditionallySelectable; -use subtle::ConstantTimeEq; - -use constants; - -use field::FieldElement; -use scalar::Scalar; - -use montgomery::MontgomeryPoint; - -use backend::serial::curve_models::AffineNielsPoint; -use backend::serial::curve_models::CompletedPoint; -use backend::serial::curve_models::ProjectiveNielsPoint; -use backend::serial::curve_models::ProjectivePoint; - -use window::LookupTable; - -#[allow(unused_imports)] -use prelude::*; - -use traits::ValidityCheck; -use traits::{Identity, IsIdentity}; - -#[cfg(any(feature = "alloc", feature = "std"))] -use traits::MultiscalarMul; -#[cfg(any(feature = "alloc", feature = "std"))] -use traits::{VartimeMultiscalarMul, VartimePrecomputedMultiscalarMul}; - -#[cfg(not(all( - feature = "simd_backend", - any(target_feature = "avx2", target_feature = "avx512ifma") -)))] -use backend::serial::scalar_mul; -#[cfg(all( - feature = "simd_backend", - any(target_feature = "avx2", target_feature = "avx512ifma") -))] -use backend::vector::scalar_mul; - -// ------------------------------------------------------------------------ -// Compressed points -// ------------------------------------------------------------------------ - -/// In "Edwards y" / "Ed25519" format, the curve point \\((x,y)\\) is -/// determined by the \\(y\\)-coordinate and the sign of \\(x\\). -/// -/// The first 255 bits of a `CompressedEdwardsY` represent the -/// \\(y\\)-coordinate. The high bit of the 32nd byte gives the sign of \\(x\\). -#[derive(Copy, Clone, Eq, PartialEq)] -pub struct CompressedEdwardsY(pub [u8; 32]); - -impl ConstantTimeEq for CompressedEdwardsY { - fn ct_eq(&self, other: &CompressedEdwardsY) -> Choice { - self.as_bytes().ct_eq(other.as_bytes()) - } -} - -impl Debug for CompressedEdwardsY { - fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { - write!(f, "CompressedEdwardsY: {:?}", self.as_bytes()) - } -} - -impl CompressedEdwardsY { - /// View this `CompressedEdwardsY` as an array of bytes. - pub fn as_bytes(&self) -> &[u8; 32] { - &self.0 - } - - /// Copy this `CompressedEdwardsY` to an array of bytes. - pub fn to_bytes(&self) -> [u8; 32] { - self.0 - } - - /// Attempt to decompress to an `EdwardsPoint`. - /// - /// Returns `None` if the input is not the \\(y\\)-coordinate of a - /// curve point. - pub fn decompress(&self) -> Option { - let Y = FieldElement::from_bytes(self.as_bytes()); - let Z = FieldElement::one(); - let YY = Y.square(); - let u = &YY - &Z; // u = y²-1 - let v = &(&YY * &constants::EDWARDS_D) + &Z; // v = dy²+1 - let (is_valid_y_coord, mut X) = FieldElement::sqrt_ratio_i(&u, &v); - - if is_valid_y_coord.unwrap_u8() != 1u8 { return None; } - - // FieldElement::sqrt_ratio_i always returns the nonnegative square root, - // so we negate according to the supplied sign bit. - let compressed_sign_bit = Choice::from(self.as_bytes()[31] >> 7); - X.conditional_negate(compressed_sign_bit); - - Some(EdwardsPoint{ X, Y, Z, T: &X * &Y }) - } -} - -// ------------------------------------------------------------------------ -// Serde support -// ------------------------------------------------------------------------ -// Serializes to and from `EdwardsPoint` directly, doing compression -// and decompression internally. This means that users can create -// structs containing `EdwardsPoint`s and use Serde's derived -// serializers to serialize those structures. - -#[cfg(feature = "serde")] -use serde::{self, Serialize, Deserialize, Serializer, Deserializer}; -#[cfg(feature = "serde")] -use serde::de::Visitor; - -#[cfg(feature = "serde")] -impl Serialize for EdwardsPoint { - fn serialize(&self, serializer: S) -> Result - where S: Serializer - { - use serde::ser::SerializeTuple; - let mut tup = serializer.serialize_tuple(32)?; - for byte in self.compress().as_bytes().iter() { - tup.serialize_element(byte)?; - } - tup.end() - } -} - -#[cfg(feature = "serde")] -impl Serialize for CompressedEdwardsY { - fn serialize(&self, serializer: S) -> Result - where S: Serializer - { - use serde::ser::SerializeTuple; - let mut tup = serializer.serialize_tuple(32)?; - for byte in self.as_bytes().iter() { - tup.serialize_element(byte)?; - } - tup.end() - } -} - -#[cfg(feature = "serde")] -impl<'de> Deserialize<'de> for EdwardsPoint { - fn deserialize(deserializer: D) -> Result - where D: Deserializer<'de> - { - struct EdwardsPointVisitor; - - impl<'de> Visitor<'de> for EdwardsPointVisitor { - type Value = EdwardsPoint; - - fn expecting(&self, formatter: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { - formatter.write_str("a valid point in Edwards y + sign format") - } - - fn visit_seq(self, mut seq: A) -> Result - where A: serde::de::SeqAccess<'de> - { - let mut bytes = [0u8; 32]; - for i in 0..32 { - bytes[i] = seq.next_element()? - .ok_or(serde::de::Error::invalid_length(i, &"expected 32 bytes"))?; - } - CompressedEdwardsY(bytes) - .decompress() - .ok_or(serde::de::Error::custom("decompression failed")) - } - } - - deserializer.deserialize_tuple(32, EdwardsPointVisitor) - } -} - -#[cfg(feature = "serde")] -impl<'de> Deserialize<'de> for CompressedEdwardsY { - fn deserialize(deserializer: D) -> Result - where D: Deserializer<'de> - { - struct CompressedEdwardsYVisitor; - - impl<'de> Visitor<'de> for CompressedEdwardsYVisitor { - type Value = CompressedEdwardsY; - - fn expecting(&self, formatter: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { - formatter.write_str("32 bytes of data") - } - - fn visit_seq(self, mut seq: A) -> Result - where A: serde::de::SeqAccess<'de> - { - let mut bytes = [0u8; 32]; - for i in 0..32 { - bytes[i] = seq.next_element()? - .ok_or(serde::de::Error::invalid_length(i, &"expected 32 bytes"))?; - } - Ok(CompressedEdwardsY(bytes)) - } - } - - deserializer.deserialize_tuple(32, CompressedEdwardsYVisitor) - } -} - -// ------------------------------------------------------------------------ -// Internal point representations -// ------------------------------------------------------------------------ - -/// An `EdwardsPoint` represents a point on the Edwards form of Curve25519. -#[derive(Copy, Clone)] -#[allow(missing_docs)] -pub struct EdwardsPoint { - pub(crate) X: FieldElement, - pub(crate) Y: FieldElement, - pub(crate) Z: FieldElement, - pub(crate) T: FieldElement, -} - -// ------------------------------------------------------------------------ -// Constructors -// ------------------------------------------------------------------------ - -impl Identity for CompressedEdwardsY { - fn identity() -> CompressedEdwardsY { - CompressedEdwardsY([1, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0]) - } -} - -impl Default for CompressedEdwardsY { - fn default() -> CompressedEdwardsY { - CompressedEdwardsY::identity() - } -} - -impl CompressedEdwardsY { - /// Construct a `CompressedEdwardsY` from a slice of bytes. - /// - /// # Panics - /// - /// If the input `bytes` slice does not have a length of 32. - pub fn from_slice(bytes: &[u8]) -> CompressedEdwardsY { - let mut tmp = [0u8; 32]; - - tmp.copy_from_slice(bytes); - - CompressedEdwardsY(tmp) - } -} - -impl Identity for EdwardsPoint { - fn identity() -> EdwardsPoint { - EdwardsPoint { - X: FieldElement::zero(), - Y: FieldElement::one(), - Z: FieldElement::one(), - T: FieldElement::zero(), - } - } -} - -impl Default for EdwardsPoint { - fn default() -> EdwardsPoint { - EdwardsPoint::identity() - } -} - -// ------------------------------------------------------------------------ -// Validity checks (for debugging, not CT) -// ------------------------------------------------------------------------ - -impl ValidityCheck for EdwardsPoint { - fn is_valid(&self) -> bool { - let point_on_curve = self.to_projective().is_valid(); - let on_segre_image = (&self.X * &self.Y) == (&self.Z * &self.T); - - point_on_curve && on_segre_image - } -} - -// ------------------------------------------------------------------------ -// Constant-time assignment -// ------------------------------------------------------------------------ - -impl ConditionallySelectable for EdwardsPoint { - fn conditional_select(a: &EdwardsPoint, b: &EdwardsPoint, choice: Choice) -> EdwardsPoint { - EdwardsPoint { - X: FieldElement::conditional_select(&a.X, &b.X, choice), - Y: FieldElement::conditional_select(&a.Y, &b.Y, choice), - Z: FieldElement::conditional_select(&a.Z, &b.Z, choice), - T: FieldElement::conditional_select(&a.T, &b.T, choice), - } - } -} - -// ------------------------------------------------------------------------ -// Equality -// ------------------------------------------------------------------------ - -impl ConstantTimeEq for EdwardsPoint { - fn ct_eq(&self, other: &EdwardsPoint) -> Choice { - // We would like to check that the point (X/Z, Y/Z) is equal to - // the point (X'/Z', Y'/Z') without converting into affine - // coordinates (x, y) and (x', y'), which requires two inversions. - // We have that X = xZ and X' = x'Z'. Thus, x = x' is equivalent to - // (xZ)Z' = (x'Z')Z, and similarly for the y-coordinate. - - (&self.X * &other.Z).ct_eq(&(&other.X * &self.Z)) - & (&self.Y * &other.Z).ct_eq(&(&other.Y * &self.Z)) - } -} - -impl PartialEq for EdwardsPoint { - fn eq(&self, other: &EdwardsPoint) -> bool { - self.ct_eq(other).unwrap_u8() == 1u8 - } -} - -impl Eq for EdwardsPoint {} - -// ------------------------------------------------------------------------ -// Point conversions -// ------------------------------------------------------------------------ - -impl EdwardsPoint { - /// Convert to a ProjectiveNielsPoint - pub(crate) fn to_projective_niels(&self) -> ProjectiveNielsPoint { - ProjectiveNielsPoint{ - Y_plus_X: &self.Y + &self.X, - Y_minus_X: &self.Y - &self.X, - Z: self.Z, - T2d: &self.T * &constants::EDWARDS_D2, - } - } - - /// Convert the representation of this point from extended - /// coordinates to projective coordinates. - /// - /// Free. - pub(crate) fn to_projective(&self) -> ProjectivePoint { - ProjectivePoint{ - X: self.X, - Y: self.Y, - Z: self.Z, - } - } - - /// Dehomogenize to a AffineNielsPoint. - /// Mainly for testing. - pub(crate) fn to_affine_niels(&self) -> AffineNielsPoint { - let recip = self.Z.invert(); - let x = &self.X * &recip; - let y = &self.Y * &recip; - let xy2d = &(&x * &y) * &constants::EDWARDS_D2; - AffineNielsPoint{ - y_plus_x: &y + &x, - y_minus_x: &y - &x, - xy2d - } - } - - /// Convert this `EdwardsPoint` on the Edwards model to the - /// corresponding `MontgomeryPoint` on the Montgomery model. - /// - /// This function has one exceptional case; the identity point of - /// the Edwards curve is sent to the 2-torsion point \\((0,0)\\) - /// on the Montgomery curve. - /// - /// Note that this is a one-way conversion, since the Montgomery - /// model does not retain sign information. - pub fn to_montgomery(&self) -> MontgomeryPoint { - // We have u = (1+y)/(1-y) = (Z+Y)/(Z-Y). - // - // The denominator is zero only when y=1, the identity point of - // the Edwards curve. Since 0.invert() = 0, in this case we - // compute the 2-torsion point (0,0). - let U = &self.Z + &self.Y; - let W = &self.Z - &self.Y; - let u = &U * &W.invert(); - MontgomeryPoint(u.to_bytes()) - } - - /// Compress this point to `CompressedEdwardsY` format. - pub fn compress(&self) -> CompressedEdwardsY { - let recip = self.Z.invert(); - let x = &self.X * &recip; - let y = &self.Y * &recip; - let mut s: [u8; 32]; - - s = y.to_bytes(); - s[31] ^= x.is_negative().unwrap_u8() << 7; - CompressedEdwardsY(s) - } -} - -// ------------------------------------------------------------------------ -// Doubling -// ------------------------------------------------------------------------ - -impl EdwardsPoint { - /// Add this point to itself. - pub(crate) fn double(&self) -> EdwardsPoint { - self.to_projective().double().to_extended() - } -} - -// ------------------------------------------------------------------------ -// Addition and Subtraction -// ------------------------------------------------------------------------ - -impl<'a, 'b> Add<&'b EdwardsPoint> for &'a EdwardsPoint { - type Output = EdwardsPoint; - fn add(self, other: &'b EdwardsPoint) -> EdwardsPoint { - (self + &other.to_projective_niels()).to_extended() - } -} - -define_add_variants!(LHS = EdwardsPoint, RHS = EdwardsPoint, Output = EdwardsPoint); - -impl<'b> AddAssign<&'b EdwardsPoint> for EdwardsPoint { - fn add_assign(&mut self, _rhs: &'b EdwardsPoint) { - *self = (self as &EdwardsPoint) + _rhs; - } -} - -define_add_assign_variants!(LHS = EdwardsPoint, RHS = EdwardsPoint); - -impl<'a, 'b> Sub<&'b EdwardsPoint> for &'a EdwardsPoint { - type Output = EdwardsPoint; - fn sub(self, other: &'b EdwardsPoint) -> EdwardsPoint { - (self - &other.to_projective_niels()).to_extended() - } -} - -define_sub_variants!(LHS = EdwardsPoint, RHS = EdwardsPoint, Output = EdwardsPoint); - -impl<'b> SubAssign<&'b EdwardsPoint> for EdwardsPoint { - fn sub_assign(&mut self, _rhs: &'b EdwardsPoint) { - *self = (self as &EdwardsPoint) - _rhs; - } -} - -define_sub_assign_variants!(LHS = EdwardsPoint, RHS = EdwardsPoint); - -impl Sum for EdwardsPoint -where - T: Borrow -{ - fn sum(iter: I) -> Self - where - I: Iterator - { - iter.fold(EdwardsPoint::identity(), |acc, item| acc + item.borrow()) - } -} - - -// ------------------------------------------------------------------------ -// Negation -// ------------------------------------------------------------------------ - -impl<'a> Neg for &'a EdwardsPoint { - type Output = EdwardsPoint; - - fn neg(self) -> EdwardsPoint { - EdwardsPoint{ - X: -(&self.X), - Y: self.Y, - Z: self.Z, - T: -(&self.T), - } - } -} - -impl Neg for EdwardsPoint { - type Output = EdwardsPoint; - - fn neg(self) -> EdwardsPoint { - -&self - } -} - -// ------------------------------------------------------------------------ -// Scalar multiplication -// ------------------------------------------------------------------------ - -impl<'b> MulAssign<&'b Scalar> for EdwardsPoint { - fn mul_assign(&mut self, scalar: &'b Scalar) { - let result = (self as &EdwardsPoint) * scalar; - *self = result; - } -} - -define_mul_assign_variants!(LHS = EdwardsPoint, RHS = Scalar); - -define_mul_variants!(LHS = EdwardsPoint, RHS = Scalar, Output = EdwardsPoint); -define_mul_variants!(LHS = Scalar, RHS = EdwardsPoint, Output = EdwardsPoint); - -impl<'a, 'b> Mul<&'b Scalar> for &'a EdwardsPoint { - type Output = EdwardsPoint; - /// Scalar multiplication: compute `scalar * self`. - /// - /// For scalar multiplication of a basepoint, - /// `EdwardsBasepointTable` is approximately 4x faster. - fn mul(self, scalar: &'b Scalar) -> EdwardsPoint { - scalar_mul::variable_base::mul(self, scalar) - } -} - -impl<'a, 'b> Mul<&'b EdwardsPoint> for &'a Scalar { - type Output = EdwardsPoint; - - /// Scalar multiplication: compute `scalar * self`. - /// - /// For scalar multiplication of a basepoint, - /// `EdwardsBasepointTable` is approximately 4x faster. - fn mul(self, point: &'b EdwardsPoint) -> EdwardsPoint { - point * self - } -} - -// ------------------------------------------------------------------------ -// Multiscalar Multiplication impls -// ------------------------------------------------------------------------ - -// These use the iterator's size hint and the target settings to -// forward to a specific backend implementation. - -#[cfg(feature = "alloc")] -impl MultiscalarMul for EdwardsPoint { - type Point = EdwardsPoint; - - fn multiscalar_mul(scalars: I, points: J) -> EdwardsPoint - where - I: IntoIterator, - I::Item: Borrow, - J: IntoIterator, - J::Item: Borrow, - { - // Sanity-check lengths of input iterators - let mut scalars = scalars.into_iter(); - let mut points = points.into_iter(); - - // Lower and upper bounds on iterators - let (s_lo, s_hi) = scalars.by_ref().size_hint(); - let (p_lo, p_hi) = points.by_ref().size_hint(); - - // They should all be equal - assert_eq!(s_lo, p_lo); - assert_eq!(s_hi, Some(s_lo)); - assert_eq!(p_hi, Some(p_lo)); - - // Now we know there's a single size. When we do - // size-dependent algorithm dispatch, use this as the hint. - let _size = s_lo; - - scalar_mul::straus::Straus::multiscalar_mul(scalars, points) - } -} - -#[cfg(feature = "alloc")] -impl VartimeMultiscalarMul for EdwardsPoint { - type Point = EdwardsPoint; - - fn optional_multiscalar_mul(scalars: I, points: J) -> Option - where - I: IntoIterator, - I::Item: Borrow, - J: IntoIterator>, - { - // Sanity-check lengths of input iterators - let mut scalars = scalars.into_iter(); - let mut points = points.into_iter(); - - // Lower and upper bounds on iterators - let (s_lo, s_hi) = scalars.by_ref().size_hint(); - let (p_lo, p_hi) = points.by_ref().size_hint(); - - // They should all be equal - assert_eq!(s_lo, p_lo); - assert_eq!(s_hi, Some(s_lo)); - assert_eq!(p_hi, Some(p_lo)); - - // Now we know there's a single size. - // Use this as the hint to decide which algorithm to use. - let size = s_lo; - - if size < 190 { - scalar_mul::straus::Straus::optional_multiscalar_mul(scalars, points) - } else { - scalar_mul::pippenger::Pippenger::optional_multiscalar_mul(scalars, points) - } - } -} - -/// Precomputation for variable-time multiscalar multiplication with `EdwardsPoint`s. -// This wraps the inner implementation in a facade type so that we can -// decouple stability of the inner type from the stability of the -// outer type. -#[cfg(feature = "alloc")] -pub struct VartimeEdwardsPrecomputation(scalar_mul::precomputed_straus::VartimePrecomputedStraus); - -#[cfg(feature = "alloc")] -impl VartimePrecomputedMultiscalarMul for VartimeEdwardsPrecomputation { - type Point = EdwardsPoint; - - fn new(static_points: I) -> Self - where - I: IntoIterator, - I::Item: Borrow, - { - Self(scalar_mul::precomputed_straus::VartimePrecomputedStraus::new(static_points)) - } - - fn optional_mixed_multiscalar_mul( - &self, - static_scalars: I, - dynamic_scalars: J, - dynamic_points: K, - ) -> Option - where - I: IntoIterator, - I::Item: Borrow, - J: IntoIterator, - J::Item: Borrow, - K: IntoIterator>, - { - self.0 - .optional_mixed_multiscalar_mul(static_scalars, dynamic_scalars, dynamic_points) - } -} - -impl EdwardsPoint { - /// Compute \\(aA + bB\\) in variable time, where \\(B\\) is the Ed25519 basepoint. - pub fn vartime_double_scalar_mul_basepoint( - a: &Scalar, - A: &EdwardsPoint, - b: &Scalar, - ) -> EdwardsPoint { - scalar_mul::vartime_double_base::mul(a, A, b) - } -} - -/// A precomputed table of multiples of a basepoint, for accelerating -/// fixed-base scalar multiplication. One table, for the Ed25519 -/// basepoint, is provided in the `constants` module. -/// -/// The basepoint tables are reasonably large (30KB), so they should -/// probably be boxed. -#[derive(Clone)] -pub struct EdwardsBasepointTable(pub(crate) [LookupTable; 32]); - -impl EdwardsBasepointTable { - /// The computation uses Pippeneger's algorithm, as described on - /// page 13 of the Ed25519 paper. Write the scalar \\(a\\) in radix \\(16\\) with - /// coefficients in \\([-8,8)\\), i.e., - /// $$ - /// a = a\_0 + a\_1 16\^1 + \cdots + a\_{63} 16\^{63}, - /// $$ - /// with \\(-8 \leq a_i < 8\\), \\(-8 \leq a\_{63} \leq 8\\). Then - /// $$ - /// a B = a\_0 B + a\_1 16\^1 B + \cdots + a\_{63} 16\^{63} B. - /// $$ - /// Grouping even and odd coefficients gives - /// $$ - /// \begin{aligned} - /// a B = \quad a\_0 16\^0 B +& a\_2 16\^2 B + \cdots + a\_{62} 16\^{62} B \\\\ - /// + a\_1 16\^1 B +& a\_3 16\^3 B + \cdots + a\_{63} 16\^{63} B \\\\ - /// = \quad(a\_0 16\^0 B +& a\_2 16\^2 B + \cdots + a\_{62} 16\^{62} B) \\\\ - /// + 16(a\_1 16\^0 B +& a\_3 16\^2 B + \cdots + a\_{63} 16\^{62} B). \\\\ - /// \end{aligned} - /// $$ - /// For each \\(i = 0 \ldots 31\\), we create a lookup table of - /// $$ - /// [16\^{2i} B, \ldots, 8\cdot16\^{2i} B], - /// $$ - /// and use it to select \\( x \cdot 16\^{2i} \cdot B \\) in constant time. - /// - /// The radix-\\(16\\) representation requires that the scalar is bounded - /// by \\(2\^{255}\\), which is always the case. - fn basepoint_mul(&self, scalar: &Scalar) -> EdwardsPoint { - let a = scalar.to_radix_16(); - - let tables = &self.0; - let mut P = EdwardsPoint::identity(); - - for i in (0..64).filter(|x| x % 2 == 1) { - P = (&P + &tables[i/2].select(a[i])).to_extended(); - } - - P = P.mul_by_pow_2(4); - - for i in (0..64).filter(|x| x % 2 == 0) { - P = (&P + &tables[i/2].select(a[i])).to_extended(); - } - - P - } -} - -impl<'a, 'b> Mul<&'b Scalar> for &'a EdwardsBasepointTable { - type Output = EdwardsPoint; - - /// Construct an `EdwardsPoint` from a `Scalar` \\(a\\) by - /// computing the multiple \\(aB\\) of this basepoint \\(B\\). - fn mul(self, scalar: &'b Scalar) -> EdwardsPoint { - // delegate to a private function so that its documentation appears in internal docs - self.basepoint_mul(scalar) - } -} - -impl<'a, 'b> Mul<&'a EdwardsBasepointTable> for &'b Scalar { - type Output = EdwardsPoint; - - /// Construct an `EdwardsPoint` from a `Scalar` \\(a\\) by - /// computing the multiple \\(aB\\) of this basepoint \\(B\\). - fn mul(self, basepoint_table: &'a EdwardsBasepointTable) -> EdwardsPoint { - basepoint_table * self - } -} - -impl EdwardsBasepointTable { - /// Create a table of precomputed multiples of `basepoint`. - pub fn create(basepoint: &EdwardsPoint) -> EdwardsBasepointTable { - // XXX use init_with - let mut table = EdwardsBasepointTable([LookupTable::default(); 32]); - let mut P = *basepoint; - for i in 0..32 { - // P = (16^2)^i * B - table.0[i] = LookupTable::from(&P); - P = P.mul_by_pow_2(8); - } - table - } - - /// Get the basepoint for this table as an `EdwardsPoint`. - pub fn basepoint(&self) -> EdwardsPoint { - // self.0[0].select(1) = 1*(16^2)^0*B - // but as an `AffineNielsPoint`, so add identity to convert to extended. - (&EdwardsPoint::identity() + &self.0[0].select(1)).to_extended() - } -} - -impl EdwardsPoint { - /// Multiply by the cofactor: return \\([8]P\\). - pub fn mul_by_cofactor(&self) -> EdwardsPoint { - self.mul_by_pow_2(3) - } - - /// Compute \\([2\^k] P \\) by successive doublings. Requires \\( k > 0 \\). - pub(crate) fn mul_by_pow_2(&self, k: u32) -> EdwardsPoint { - debug_assert!( k > 0 ); - let mut r: CompletedPoint; - let mut s = self.to_projective(); - for _ in 0..(k-1) { - r = s.double(); s = r.to_projective(); - } - // Unroll last iteration so we can go directly to_extended() - s.double().to_extended() - } - - /// Determine if this point is of small order. - /// - /// # Return - /// - /// * `true` if `self` is in the torsion subgroup \\( \mathcal E[8] \\); - /// * `false` if `self` is not in the torsion subgroup \\( \mathcal E[8] \\). - /// - /// # Example - /// - /// ``` - /// use curve25519_dalek::constants; - /// - /// // Generator of the prime-order subgroup - /// let P = constants::ED25519_BASEPOINT_POINT; - /// // Generator of the torsion subgroup - /// let Q = constants::EIGHT_TORSION[1]; - /// - /// // P has large order - /// assert_eq!(P.is_small_order(), false); - /// - /// // Q has small order - /// assert_eq!(Q.is_small_order(), true); - /// ``` - pub fn is_small_order(&self) -> bool { - self.mul_by_cofactor().is_identity() - } - - /// Determine if this point is “torsion-free”, i.e., is contained in - /// the prime-order subgroup. - /// - /// # Return - /// - /// * `true` if `self` has zero torsion component and is in the - /// prime-order subgroup; - /// * `false` if `self` has a nonzero torsion component and is not - /// in the prime-order subgroup. - /// - /// # Example - /// - /// ``` - /// use curve25519_dalek::constants; - /// - /// // Generator of the prime-order subgroup - /// let P = constants::ED25519_BASEPOINT_POINT; - /// // Generator of the torsion subgroup - /// let Q = constants::EIGHT_TORSION[1]; - /// - /// // P is torsion-free - /// assert_eq!(P.is_torsion_free(), true); - /// - /// // P + Q is not torsion-free - /// assert_eq!((P+Q).is_torsion_free(), false); - /// ``` - pub fn is_torsion_free(&self) -> bool { - (self * constants::BASEPOINT_ORDER).is_identity() - } -} - -// ------------------------------------------------------------------------ -// Debug traits -// ------------------------------------------------------------------------ - -impl Debug for EdwardsPoint { - fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { - write!(f, "EdwardsPoint{{\n\tX: {:?},\n\tY: {:?},\n\tZ: {:?},\n\tT: {:?}\n}}", - &self.X, &self.Y, &self.Z, &self.T) - } -} - -impl Debug for EdwardsBasepointTable { - fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { - write!(f, "EdwardsBasepointTable([\n")?; - for i in 0..32 { - write!(f, "\t{:?},\n", &self.0[i])?; - } - write!(f, "])") - } -} - -// ------------------------------------------------------------------------ -// Tests -// ------------------------------------------------------------------------ - -#[cfg(test)] -mod test { - use field::FieldElement; - use scalar::Scalar; - use subtle::ConditionallySelectable; - use constants; - use super::*; - - /// X coordinate of the basepoint. - /// = 15112221349535400772501151409588531511454012693041857206046113283949847762202 - static BASE_X_COORD_BYTES: [u8; 32] = - [0x1a, 0xd5, 0x25, 0x8f, 0x60, 0x2d, 0x56, 0xc9, 0xb2, 0xa7, 0x25, 0x95, 0x60, 0xc7, 0x2c, 0x69, - 0x5c, 0xdc, 0xd6, 0xfd, 0x31, 0xe2, 0xa4, 0xc0, 0xfe, 0x53, 0x6e, 0xcd, 0xd3, 0x36, 0x69, 0x21]; - - /// Compressed Edwards Y form of 2*basepoint. - static BASE2_CMPRSSD: CompressedEdwardsY = - CompressedEdwardsY([0xc9, 0xa3, 0xf8, 0x6a, 0xae, 0x46, 0x5f, 0xe, - 0x56, 0x51, 0x38, 0x64, 0x51, 0x0f, 0x39, 0x97, - 0x56, 0x1f, 0xa2, 0xc9, 0xe8, 0x5e, 0xa2, 0x1d, - 0xc2, 0x29, 0x23, 0x09, 0xf3, 0xcd, 0x60, 0x22]); - - /// Compressed Edwards Y form of 16*basepoint. - static BASE16_CMPRSSD: CompressedEdwardsY = - CompressedEdwardsY([0xeb, 0x27, 0x67, 0xc1, 0x37, 0xab, 0x7a, 0xd8, - 0x27, 0x9c, 0x07, 0x8e, 0xff, 0x11, 0x6a, 0xb0, - 0x78, 0x6e, 0xad, 0x3a, 0x2e, 0x0f, 0x98, 0x9f, - 0x72, 0xc3, 0x7f, 0x82, 0xf2, 0x96, 0x96, 0x70]); - - /// 4493907448824000747700850167940867464579944529806937181821189941592931634714 - pub static A_SCALAR: Scalar = Scalar{ - bytes: [ - 0x1a, 0x0e, 0x97, 0x8a, 0x90, 0xf6, 0x62, 0x2d, - 0x37, 0x47, 0x02, 0x3f, 0x8a, 0xd8, 0x26, 0x4d, - 0xa7, 0x58, 0xaa, 0x1b, 0x88, 0xe0, 0x40, 0xd1, - 0x58, 0x9e, 0x7b, 0x7f, 0x23, 0x76, 0xef, 0x09, - ], - }; - - /// 2506056684125797857694181776241676200180934651973138769173342316833279714961 - pub static B_SCALAR: Scalar = Scalar{ - bytes: [ - 0x91, 0x26, 0x7a, 0xcf, 0x25, 0xc2, 0x09, 0x1b, - 0xa2, 0x17, 0x74, 0x7b, 0x66, 0xf0, 0xb3, 0x2e, - 0x9d, 0xf2, 0xa5, 0x67, 0x41, 0xcf, 0xda, 0xc4, - 0x56, 0xa7, 0xd4, 0xaa, 0xb8, 0x60, 0x8a, 0x05, - ], - }; - - /// A_SCALAR * basepoint, computed with ed25519.py - pub static A_TIMES_BASEPOINT: CompressedEdwardsY = CompressedEdwardsY([ - 0xea, 0x27, 0xe2, 0x60, 0x53, 0xdf, 0x1b, 0x59, - 0x56, 0xf1, 0x4d, 0x5d, 0xec, 0x3c, 0x34, 0xc3, - 0x84, 0xa2, 0x69, 0xb7, 0x4c, 0xc3, 0x80, 0x3e, - 0xa8, 0xe2, 0xe7, 0xc9, 0x42, 0x5e, 0x40, 0xa5]); - - /// A_SCALAR * (A_TIMES_BASEPOINT) + B_SCALAR * BASEPOINT - /// computed with ed25519.py - static DOUBLE_SCALAR_MULT_RESULT: CompressedEdwardsY = CompressedEdwardsY([ - 0x7d, 0xfd, 0x6c, 0x45, 0xaf, 0x6d, 0x6e, 0x0e, - 0xba, 0x20, 0x37, 0x1a, 0x23, 0x64, 0x59, 0xc4, - 0xc0, 0x46, 0x83, 0x43, 0xde, 0x70, 0x4b, 0x85, - 0x09, 0x6f, 0xfe, 0x35, 0x4f, 0x13, 0x2b, 0x42]); - - /// Test round-trip decompression for the basepoint. - #[test] - fn basepoint_decompression_compression() { - let base_X = FieldElement::from_bytes(&BASE_X_COORD_BYTES); - let bp = constants::ED25519_BASEPOINT_COMPRESSED.decompress().unwrap(); - assert!(bp.is_valid()); - // Check that decompression actually gives the correct X coordinate - assert_eq!(base_X, bp.X); - assert_eq!(bp.compress(), constants::ED25519_BASEPOINT_COMPRESSED); - } - - /// Test sign handling in decompression - #[test] - fn decompression_sign_handling() { - // Manually set the high bit of the last byte to flip the sign - let mut minus_basepoint_bytes = constants::ED25519_BASEPOINT_COMPRESSED.as_bytes().clone(); - minus_basepoint_bytes[31] |= 1 << 7; - let minus_basepoint = CompressedEdwardsY(minus_basepoint_bytes) - .decompress().unwrap(); - // Test projective coordinates exactly since we know they should - // only differ by a flipped sign. - assert_eq!(minus_basepoint.X, -(&constants::ED25519_BASEPOINT_POINT.X)); - assert_eq!(minus_basepoint.Y, constants::ED25519_BASEPOINT_POINT.Y); - assert_eq!(minus_basepoint.Z, constants::ED25519_BASEPOINT_POINT.Z); - assert_eq!(minus_basepoint.T, -(&constants::ED25519_BASEPOINT_POINT.T)); - } - - /// Test that computing 1*basepoint gives the correct basepoint. - #[test] - fn basepoint_mult_one_vs_basepoint() { - let bp = &constants::ED25519_BASEPOINT_TABLE * &Scalar::one(); - let compressed = bp.compress(); - assert_eq!(compressed, constants::ED25519_BASEPOINT_COMPRESSED); - } - - /// Test that `EdwardsBasepointTable::basepoint()` gives the correct basepoint. - #[test] - fn basepoint_table_basepoint_function_correct() { - let bp = constants::ED25519_BASEPOINT_TABLE.basepoint(); - assert_eq!(bp.compress(), constants::ED25519_BASEPOINT_COMPRESSED); - } - - /// Test `impl Add for EdwardsPoint` - /// using basepoint + basepoint versus the 2*basepoint constant. - #[test] - fn basepoint_plus_basepoint_vs_basepoint2() { - let bp = constants::ED25519_BASEPOINT_POINT; - let bp_added = &bp + &bp; - assert_eq!(bp_added.compress(), BASE2_CMPRSSD); - } - - /// Test `impl Add for EdwardsPoint` - /// using the basepoint, basepoint2 constants - #[test] - fn basepoint_plus_basepoint_projective_niels_vs_basepoint2() { - let bp = constants::ED25519_BASEPOINT_POINT; - let bp_added = (&bp + &bp.to_projective_niels()).to_extended(); - assert_eq!(bp_added.compress(), BASE2_CMPRSSD); - } - - /// Test `impl Add for EdwardsPoint` - /// using the basepoint, basepoint2 constants - #[test] - fn basepoint_plus_basepoint_affine_niels_vs_basepoint2() { - let bp = constants::ED25519_BASEPOINT_POINT; - let bp_affine_niels = bp.to_affine_niels(); - let bp_added = (&bp + &bp_affine_niels).to_extended(); - assert_eq!(bp_added.compress(), BASE2_CMPRSSD); - } - - /// Check that equality of `EdwardsPoints` handles projective - /// coordinates correctly. - #[test] - fn extended_point_equality_handles_scaling() { - let mut two_bytes = [0u8; 32]; two_bytes[0] = 2; - let id1 = EdwardsPoint::identity(); - let id2 = EdwardsPoint{ - X: FieldElement::zero(), - Y: FieldElement::from_bytes(&two_bytes), - Z: FieldElement::from_bytes(&two_bytes), - T: FieldElement::zero() - }; - assert_eq!(id1.ct_eq(&id2).unwrap_u8(), 1u8); - } - - /// Sanity check for conversion to precomputed points - #[test] - fn to_affine_niels_clears_denominators() { - // construct a point as aB so it has denominators (ie. Z != 1) - let aB = &constants::ED25519_BASEPOINT_TABLE * &A_SCALAR; - let aB_affine_niels = aB.to_affine_niels(); - let also_aB = (&EdwardsPoint::identity() + &aB_affine_niels).to_extended(); - assert_eq!( aB.compress(), - also_aB.compress()); - } - - /// Test basepoint_mult versus a known scalar multiple from ed25519.py - #[test] - fn basepoint_mult_vs_ed25519py() { - let aB = &constants::ED25519_BASEPOINT_TABLE * &A_SCALAR; - assert_eq!(aB.compress(), A_TIMES_BASEPOINT); - } - - /// Test that multiplication by the basepoint order kills the basepoint - #[test] - fn basepoint_mult_by_basepoint_order() { - let B = &constants::ED25519_BASEPOINT_TABLE; - let should_be_id = B * &constants::BASEPOINT_ORDER; - assert!(should_be_id.is_identity()); - } - - /// Test precomputed basepoint mult - #[test] - fn test_precomputed_basepoint_mult() { - let aB_1 = &constants::ED25519_BASEPOINT_TABLE * &A_SCALAR; - let aB_2 = &constants::ED25519_BASEPOINT_POINT * &A_SCALAR; - assert_eq!(aB_1.compress(), aB_2.compress()); - } - - /// Test scalar_mul versus a known scalar multiple from ed25519.py - #[test] - fn scalar_mul_vs_ed25519py() { - let aB = &constants::ED25519_BASEPOINT_POINT * &A_SCALAR; - assert_eq!(aB.compress(), A_TIMES_BASEPOINT); - } - - /// Test basepoint.double() versus the 2*basepoint constant. - #[test] - fn basepoint_double_vs_basepoint2() { - assert_eq!(constants::ED25519_BASEPOINT_POINT.double().compress(), - BASE2_CMPRSSD); - } - - /// Test that computing 2*basepoint is the same as basepoint.double() - #[test] - fn basepoint_mult_two_vs_basepoint2() { - let two = Scalar::from(2u64); - let bp2 = &constants::ED25519_BASEPOINT_TABLE * &two; - assert_eq!(bp2.compress(), BASE2_CMPRSSD); - } - - /// Check that converting to projective and then back to extended round-trips. - #[test] - fn basepoint_projective_extended_round_trip() { - assert_eq!(constants::ED25519_BASEPOINT_POINT - .to_projective().to_extended().compress(), - constants::ED25519_BASEPOINT_COMPRESSED); - } - - /// Test computing 16*basepoint vs mul_by_pow_2(4) - #[test] - fn basepoint16_vs_mul_by_pow_2_4() { - let bp16 = constants::ED25519_BASEPOINT_POINT.mul_by_pow_2(4); - assert_eq!(bp16.compress(), BASE16_CMPRSSD); - } - - #[test] - fn impl_sum() { - - // Test that sum works for non-empty iterators - let BASE = constants::ED25519_BASEPOINT_POINT; - - let s1 = Scalar::from(999u64); - let P1 = &BASE * &s1; - - let s2 = Scalar::from(333u64); - let P2 = &BASE * &s2; - - let vec = vec![P1.clone(), P2.clone()]; - let sum: EdwardsPoint = vec.iter().sum(); - - assert_eq!(sum, P1 + P2); - - // Test that sum works for the empty iterator - let empty_vector: Vec = vec![]; - let sum: EdwardsPoint = empty_vector.iter().sum(); - - assert_eq!(sum, EdwardsPoint::identity()); - - // Test that sum works on owning iterators - let s = Scalar::from(2u64); - let mapped = vec.iter().map(|x| x * s); - let sum: EdwardsPoint = mapped.sum(); - - assert_eq!(sum, &P1 * &s + &P2 * &s); - } - - - /// Test that the conditional assignment trait works for AffineNielsPoints. - #[test] - fn conditional_assign_for_affine_niels_point() { - let id = AffineNielsPoint::identity(); - let mut p1 = AffineNielsPoint::identity(); - let bp = constants::ED25519_BASEPOINT_POINT.to_affine_niels(); - - p1.conditional_assign(&bp, Choice::from(0)); - assert_eq!(p1, id); - p1.conditional_assign(&bp, Choice::from(1)); - assert_eq!(p1, bp); - } - - #[test] - fn is_small_order() { - // The basepoint has large prime order - assert!(!constants::ED25519_BASEPOINT_POINT.is_small_order()); - // constants::EIGHT_TORSION has all points of small order. - for torsion_point in &constants::EIGHT_TORSION { - assert!(torsion_point.is_small_order()); - } - } - - #[test] - fn compressed_identity() { - assert_eq!(EdwardsPoint::identity().compress(), - CompressedEdwardsY::identity()); - } - - #[test] - fn is_identity() { - assert!( EdwardsPoint::identity().is_identity()); - assert!(!constants::ED25519_BASEPOINT_POINT.is_identity()); - } - - /// Rust's debug builds have overflow and underflow trapping, - /// and enable `debug_assert!()`. This performs many scalar - /// multiplications to attempt to trigger possible overflows etc. - /// - /// For instance, the `u64` `Mul` implementation for - /// `FieldElements` requires the input `Limb`s to be bounded by - /// 2^54, but we cannot enforce this dynamically at runtime, or - /// statically at compile time (until Rust gets type-level - /// integers, at which point we can encode "bits of headroom" into - /// the type system and prove correctness). - #[test] - fn monte_carlo_overflow_underflow_debug_assert_test() { - let mut P = constants::ED25519_BASEPOINT_POINT; - // N.B. each scalar_mul does 1407 field mults, 1024 field squarings, - // so this does ~ 1M of each operation. - for _ in 0..1_000 { - P *= &A_SCALAR; - } - } - - #[test] - fn scalarmult_extended_point_works_both_ways() { - let G: EdwardsPoint = constants::ED25519_BASEPOINT_POINT; - let s: Scalar = A_SCALAR; - - let P1 = &G * &s; - let P2 = &s * &G; - - assert!(P1.compress().to_bytes() == P2.compress().to_bytes()); - } - - // A single iteration of a consistency check for MSM. - fn multiscalar_consistency_iter(n: usize) { - use core::iter; - let mut rng = rand::thread_rng(); - - // Construct random coefficients x0, ..., x_{n-1}, - // followed by some extra hardcoded ones. - let xs = (0..n) - .map(|_| Scalar::random(&mut rng)) - // The largest scalar allowed by the type system, 2^255-1 - .chain(iter::once(Scalar::from_bits([0xff; 32]))) - .collect::>(); - let check = xs.iter() - .map(|xi| xi * xi) - .sum::(); - - // Construct points G_i = x_i * B - let Gs = xs.iter() - .map(|xi| xi * &constants::ED25519_BASEPOINT_TABLE) - .collect::>(); - - // Compute H1 = (consttime) - let H1 = EdwardsPoint::multiscalar_mul(&xs, &Gs); - // Compute H2 = (vartime) - let H2 = EdwardsPoint::vartime_multiscalar_mul(&xs, &Gs); - // Compute H3 = = sum(xi^2) * B - let H3 = &check * &constants::ED25519_BASEPOINT_TABLE; - - assert_eq!(H1, H3); - assert_eq!(H2, H3); - } - - // Use different multiscalar sizes to hit different internal - // parameters. - - #[test] - fn multiscalar_consistency_n_100() { - let iters = 50; - for _ in 0..iters { - multiscalar_consistency_iter(100); - } - } - - #[test] - fn multiscalar_consistency_n_250() { - let iters = 50; - for _ in 0..iters { - multiscalar_consistency_iter(250); - } - } - - #[test] - fn multiscalar_consistency_n_500() { - let iters = 50; - for _ in 0..iters { - multiscalar_consistency_iter(500); - } - } - - #[test] - fn multiscalar_consistency_n_1000() { - let iters = 50; - for _ in 0..iters { - multiscalar_consistency_iter(1000); - } - } - - #[test] - fn vartime_precomputed_vs_nonprecomputed_multiscalar() { - let mut rng = rand::thread_rng(); - - let B = &::constants::ED25519_BASEPOINT_TABLE; - - let static_scalars = (0..128) - .map(|_| Scalar::random(&mut rng)) - .collect::>(); - - let dynamic_scalars = (0..128) - .map(|_| Scalar::random(&mut rng)) - .collect::>(); - - let check_scalar: Scalar = static_scalars - .iter() - .chain(dynamic_scalars.iter()) - .map(|s| s * s) - .sum(); - - let static_points = static_scalars.iter().map(|s| s * B).collect::>(); - let dynamic_points = dynamic_scalars.iter().map(|s| s * B).collect::>(); - - let precomputation = VartimeEdwardsPrecomputation::new(static_points.iter()); - - let P = precomputation.vartime_mixed_multiscalar_mul( - &static_scalars, - &dynamic_scalars, - &dynamic_points, - ); - - use traits::VartimeMultiscalarMul; - let Q = EdwardsPoint::vartime_multiscalar_mul( - static_scalars.iter().chain(dynamic_scalars.iter()), - static_points.iter().chain(dynamic_points.iter()), - ); - - let R = &check_scalar * B; - - assert_eq!(P.compress(), R.compress()); - assert_eq!(Q.compress(), R.compress()); - } - - mod vartime { - use super::super::*; - use super::{A_SCALAR, B_SCALAR, A_TIMES_BASEPOINT, DOUBLE_SCALAR_MULT_RESULT}; - - /// Test double_scalar_mul_vartime vs ed25519.py - #[test] - fn double_scalar_mul_basepoint_vs_ed25519py() { - let A = A_TIMES_BASEPOINT.decompress().unwrap(); - let result = EdwardsPoint::vartime_double_scalar_mul_basepoint(&A_SCALAR, &A, &B_SCALAR); - assert_eq!(result.compress(), DOUBLE_SCALAR_MULT_RESULT); - } - - #[test] - fn multiscalar_mul_vs_ed25519py() { - let A = A_TIMES_BASEPOINT.decompress().unwrap(); - let result = EdwardsPoint::vartime_multiscalar_mul( - &[A_SCALAR, B_SCALAR], - &[A, constants::ED25519_BASEPOINT_POINT] - ); - assert_eq!(result.compress(), DOUBLE_SCALAR_MULT_RESULT); - } - - #[test] - fn multiscalar_mul_vartime_vs_consttime() { - let A = A_TIMES_BASEPOINT.decompress().unwrap(); - let result_vartime = EdwardsPoint::vartime_multiscalar_mul( - &[A_SCALAR, B_SCALAR], - &[A, constants::ED25519_BASEPOINT_POINT] - ); - let result_consttime = EdwardsPoint::multiscalar_mul( - &[A_SCALAR, B_SCALAR], - &[A, constants::ED25519_BASEPOINT_POINT] - ); - - assert_eq!(result_vartime.compress(), result_consttime.compress()); - } - } - - #[test] - #[cfg(feature = "serde")] - fn serde_bincode_basepoint_roundtrip() { - use bincode; - - let encoded = bincode::serialize(&constants::ED25519_BASEPOINT_POINT).unwrap(); - let enc_compressed = bincode::serialize(&constants::ED25519_BASEPOINT_COMPRESSED).unwrap(); - assert_eq!(encoded, enc_compressed); - - // Check that the encoding is 32 bytes exactly - assert_eq!(encoded.len(), 32); - - let dec_uncompressed: EdwardsPoint = bincode::deserialize(&encoded).unwrap(); - let dec_compressed: CompressedEdwardsY = bincode::deserialize(&encoded).unwrap(); - - assert_eq!(dec_uncompressed, constants::ED25519_BASEPOINT_POINT); - assert_eq!(dec_compressed, constants::ED25519_BASEPOINT_COMPRESSED); - - // Check that the encoding itself matches the usual one - let raw_bytes = constants::ED25519_BASEPOINT_COMPRESSED.as_bytes(); - let bp: EdwardsPoint = bincode::deserialize(raw_bytes).unwrap(); - assert_eq!(bp, constants::ED25519_BASEPOINT_POINT); - } -} diff --git a/net/gurk-rs/files/vendor/curve25519-dalek-2.0.0/src/field.rs b/net/gurk-rs/files/vendor/curve25519-dalek-2.0.0/src/field.rs deleted file mode 100644 index 54d048d..0000000 --- a/net/gurk-rs/files/vendor/curve25519-dalek-2.0.0/src/field.rs +++ /dev/null @@ -1,460 +0,0 @@ -// -*- mode: rust; -*- -// -// This file is part of curve25519-dalek. -// Copyright (c) 2016-2019 Isis Lovecruft, Henry de Valence -// See LICENSE for licensing information. -// -// Authors: -// - Isis Agora Lovecruft -// - Henry de Valence - -//! Field arithmetic modulo \\(p = 2\^{255} - 19\\). -//! -//! The `curve25519_dalek::field` module provides a type alias -//! `curve25519_dalek::field::FieldElement` to a field element type -//! defined in the `backend` module; either `FieldElement51` or -//! `FieldElement2625`. -//! -//! Field operations defined in terms of machine -//! operations, such as field multiplication or squaring, are defined in -//! the backend implementation. -//! -//! Field operations defined in terms of other field operations, such as -//! field inversion or square roots, are defined here. - -use core::cmp::{Eq, PartialEq}; - -use subtle::ConditionallySelectable; -use subtle::ConditionallyNegatable; -use subtle::Choice; -use subtle::ConstantTimeEq; - -use constants; -use backend; - -#[cfg(feature = "u64_backend")] -pub use backend::serial::u64::field::*; -/// A `FieldElement` represents an element of the field -/// \\( \mathbb Z / (2\^{255} - 19)\\). -/// -/// The `FieldElement` type is an alias for one of the platform-specific -/// implementations. -#[cfg(feature = "u64_backend")] -pub type FieldElement = backend::serial::u64::field::FieldElement51; - -#[cfg(feature = "u32_backend")] -pub use backend::serial::u32::field::*; -/// A `FieldElement` represents an element of the field -/// \\( \mathbb Z / (2\^{255} - 19)\\). -/// -/// The `FieldElement` type is an alias for one of the platform-specific -/// implementations. -#[cfg(feature = "u32_backend")] -pub type FieldElement = backend::serial::u32::field::FieldElement2625; - -impl Eq for FieldElement {} - -impl PartialEq for FieldElement { - fn eq(&self, other: &FieldElement) -> bool { - self.ct_eq(other).unwrap_u8() == 1u8 - } -} - -impl ConstantTimeEq for FieldElement { - /// Test equality between two `FieldElement`s. Since the - /// internal representation is not canonical, the field elements - /// are normalized to wire format before comparison. - fn ct_eq(&self, other: &FieldElement) -> Choice { - self.to_bytes().ct_eq(&other.to_bytes()) - } -} - -impl FieldElement { - /// Determine if this `FieldElement` is negative, in the sense - /// used in the ed25519 paper: `x` is negative if the low bit is - /// set. - /// - /// # Return - /// - /// If negative, return `Choice(1)`. Otherwise, return `Choice(0)`. - pub fn is_negative(&self) -> Choice { - let bytes = self.to_bytes(); - (bytes[0] & 1).into() - } - - /// Determine if this `FieldElement` is zero. - /// - /// # Return - /// - /// If zero, return `Choice(1)`. Otherwise, return `Choice(0)`. - pub fn is_zero(&self) -> Choice { - let zero = [0u8; 32]; - let bytes = self.to_bytes(); - - bytes.ct_eq(&zero) - } - - /// Compute (self^(2^250-1), self^11), used as a helper function - /// within invert() and pow22523(). - fn pow22501(&self) -> (FieldElement, FieldElement) { - // Instead of managing which temporary variables are used - // for what, we define as many as we need and leave stack - // allocation to the compiler - // - // Each temporary variable t_i is of the form (self)^e_i. - // Squaring t_i corresponds to multiplying e_i by 2, - // so the pow2k function shifts e_i left by k places. - // Multiplying t_i and t_j corresponds to adding e_i + e_j. - // - // Temporary t_i Nonzero bits of e_i - // - let t0 = self.square(); // 1 e_0 = 2^1 - let t1 = t0.square().square(); // 3 e_1 = 2^3 - let t2 = self * &t1; // 3,0 e_2 = 2^3 + 2^0 - let t3 = &t0 * &t2; // 3,1,0 - let t4 = t3.square(); // 4,2,1 - let t5 = &t2 * &t4; // 4,3,2,1,0 - let t6 = t5.pow2k(5); // 9,8,7,6,5 - let t7 = &t6 * &t5; // 9,8,7,6,5,4,3,2,1,0 - let t8 = t7.pow2k(10); // 19..10 - let t9 = &t8 * &t7; // 19..0 - let t10 = t9.pow2k(20); // 39..20 - let t11 = &t10 * &t9; // 39..0 - let t12 = t11.pow2k(10); // 49..10 - let t13 = &t12 * &t7; // 49..0 - let t14 = t13.pow2k(50); // 99..50 - let t15 = &t14 * &t13; // 99..0 - let t16 = t15.pow2k(100); // 199..100 - let t17 = &t16 * &t15; // 199..0 - let t18 = t17.pow2k(50); // 249..50 - let t19 = &t18 * &t13; // 249..0 - - (t19, t3) - } - - /// Given a slice of public `FieldElements`, replace each with its inverse. - /// - /// All input `FieldElements` **MUST** be nonzero. - #[cfg(feature = "alloc")] - pub fn batch_invert(inputs: &mut [FieldElement]) { - // Montgomery’s Trick and Fast Implementation of Masked AES - // Genelle, Prouff and Quisquater - // Section 3.2 - - let n = inputs.len(); - let mut scratch = vec![FieldElement::one(); n]; - - // Keep an accumulator of all of the previous products - let mut acc = FieldElement::one(); - - // Pass through the input vector, recording the previous - // products in the scratch space - for (input, scratch) in inputs.iter().zip(scratch.iter_mut()) { - *scratch = acc; - acc = &acc * input; - } - - // acc is nonzero iff all inputs are nonzero - assert_eq!(acc.is_zero().unwrap_u8(), 0); - - // Compute the inverse of all products - acc = acc.invert(); - - // Pass through the vector backwards to compute the inverses - // in place - for (input, scratch) in inputs.iter_mut().rev().zip(scratch.into_iter().rev()) { - let tmp = &acc * input; - *input = &acc * &scratch; - acc = tmp; - } - } - - /// Given a nonzero field element, compute its inverse. - /// - /// The inverse is computed as self^(p-2), since - /// x^(p-2)x = x^(p-1) = 1 (mod p). - /// - /// This function returns zero on input zero. - pub fn invert(&self) -> FieldElement { - // The bits of p-2 = 2^255 -19 -2 are 11010111111...11. - // - // nonzero bits of exponent - let (t19, t3) = self.pow22501(); // t19: 249..0 ; t3: 3,1,0 - let t20 = t19.pow2k(5); // 254..5 - let t21 = &t20 * &t3; // 254..5,3,1,0 - - t21 - } - - /// Raise this field element to the power (p-5)/8 = 2^252 -3. - fn pow_p58(&self) -> FieldElement { - // The bits of (p-5)/8 are 101111.....11. - // - // nonzero bits of exponent - let (t19, _) = self.pow22501(); // 249..0 - let t20 = t19.pow2k(2); // 251..2 - let t21 = self * &t20; // 251..2,0 - - t21 - } - - /// Given `FieldElements` `u` and `v`, compute either `sqrt(u/v)` - /// or `sqrt(i*u/v)` in constant time. - /// - /// This function always returns the nonnegative square root. - /// - /// # Return - /// - /// - `(Choice(1), +sqrt(u/v)) ` if `v` is nonzero and `u/v` is square; - /// - `(Choice(1), zero) ` if `u` is zero; - /// - `(Choice(0), zero) ` if `v` is zero and `u` is nonzero; - /// - `(Choice(0), +sqrt(i*u/v))` if `u/v` is nonsquare (so `i*u/v` is square). - /// - pub fn sqrt_ratio_i(u: &FieldElement, v: &FieldElement) -> (Choice, FieldElement) { - // Using the same trick as in ed25519 decoding, we merge the - // inversion, the square root, and the square test as follows. - // - // To compute sqrt(α), we can compute β = α^((p+3)/8). - // Then β^2 = ±α, so multiplying β by sqrt(-1) if necessary - // gives sqrt(α). - // - // To compute 1/sqrt(α), we observe that - // 1/β = α^(p-1 - (p+3)/8) = α^((7p-11)/8) - // = α^3 * (α^7)^((p-5)/8). - // - // We can therefore compute sqrt(u/v) = sqrt(u)/sqrt(v) - // by first computing - // r = u^((p+3)/8) v^(p-1-(p+3)/8) - // = u u^((p-5)/8) v^3 (v^7)^((p-5)/8) - // = (uv^3) (uv^7)^((p-5)/8). - // - // If v is nonzero and u/v is square, then r^2 = ±u/v, - // so vr^2 = ±u. - // If vr^2 = u, then sqrt(u/v) = r. - // If vr^2 = -u, then sqrt(u/v) = r*sqrt(-1). - // - // If v is zero, r is also zero. - - let v3 = &v.square() * v; - let v7 = &v3.square() * v; - let mut r = &(u * &v3) * &(u * &v7).pow_p58(); - let check = v * &r.square(); - - let i = &constants::SQRT_M1; - - let correct_sign_sqrt = check.ct_eq( u); - let flipped_sign_sqrt = check.ct_eq( &(-u)); - let flipped_sign_sqrt_i = check.ct_eq(&(&(-u)*i)); - - let r_prime = &constants::SQRT_M1 * &r; - r.conditional_assign(&r_prime, flipped_sign_sqrt | flipped_sign_sqrt_i); - - // Choose the nonnegative square root. - let r_is_negative = r.is_negative(); - r.conditional_negate(r_is_negative); - - let was_nonzero_square = correct_sign_sqrt | flipped_sign_sqrt; - - (was_nonzero_square, r) - } - - /// Attempt to compute `sqrt(1/self)` in constant time. - /// - /// Convenience wrapper around `sqrt_ratio_i`. - /// - /// This function always returns the nonnegative square root. - /// - /// # Return - /// - /// - `(Choice(1), +sqrt(1/self)) ` if `self` is a nonzero square; - /// - `(Choice(0), zero) ` if `self` is zero; - /// - `(Choice(0), +sqrt(i/self)) ` if `self` is a nonzero nonsquare; - /// - pub fn invsqrt(&self) -> (Choice, FieldElement) { - FieldElement::sqrt_ratio_i(&FieldElement::one(), self) - } -} - -#[cfg(test)] -mod test { - use field::*; - use subtle::ConditionallyNegatable; - - /// Random element a of GF(2^255-19), from Sage - /// a = 1070314506888354081329385823235218444233221\ - /// 2228051251926706380353716438957572 - static A_BYTES: [u8; 32] = - [ 0x04, 0xfe, 0xdf, 0x98, 0xa7, 0xfa, 0x0a, 0x68, - 0x84, 0x92, 0xbd, 0x59, 0x08, 0x07, 0xa7, 0x03, - 0x9e, 0xd1, 0xf6, 0xf2, 0xe1, 0xd9, 0xe2, 0xa4, - 0xa4, 0x51, 0x47, 0x36, 0xf3, 0xc3, 0xa9, 0x17]; - - /// Byte representation of a**2 - static ASQ_BYTES: [u8; 32] = - [ 0x75, 0x97, 0x24, 0x9e, 0xe6, 0x06, 0xfe, 0xab, - 0x24, 0x04, 0x56, 0x68, 0x07, 0x91, 0x2d, 0x5d, - 0x0b, 0x0f, 0x3f, 0x1c, 0xb2, 0x6e, 0xf2, 0xe2, - 0x63, 0x9c, 0x12, 0xba, 0x73, 0x0b, 0xe3, 0x62]; - - /// Byte representation of 1/a - static AINV_BYTES: [u8; 32] = - [0x96, 0x1b, 0xcd, 0x8d, 0x4d, 0x5e, 0xa2, 0x3a, - 0xe9, 0x36, 0x37, 0x93, 0xdb, 0x7b, 0x4d, 0x70, - 0xb8, 0x0d, 0xc0, 0x55, 0xd0, 0x4c, 0x1d, 0x7b, - 0x90, 0x71, 0xd8, 0xe9, 0xb6, 0x18, 0xe6, 0x30]; - - /// Byte representation of a^((p-5)/8) - static AP58_BYTES: [u8; 32] = - [0x6a, 0x4f, 0x24, 0x89, 0x1f, 0x57, 0x60, 0x36, - 0xd0, 0xbe, 0x12, 0x3c, 0x8f, 0xf5, 0xb1, 0x59, - 0xe0, 0xf0, 0xb8, 0x1b, 0x20, 0xd2, 0xb5, 0x1f, - 0x15, 0x21, 0xf9, 0xe3, 0xe1, 0x61, 0x21, 0x55]; - - #[test] - fn a_mul_a_vs_a_squared_constant() { - let a = FieldElement::from_bytes(&A_BYTES); - let asq = FieldElement::from_bytes(&ASQ_BYTES); - assert_eq!(asq, &a * &a); - } - - #[test] - fn a_square_vs_a_squared_constant() { - let a = FieldElement::from_bytes(&A_BYTES); - let asq = FieldElement::from_bytes(&ASQ_BYTES); - assert_eq!(asq, a.square()); - } - - #[test] - fn a_square2_vs_a_squared_constant() { - let a = FieldElement::from_bytes(&A_BYTES); - let asq = FieldElement::from_bytes(&ASQ_BYTES); - assert_eq!(a.square2(), &asq+&asq); - } - - #[test] - fn a_invert_vs_inverse_of_a_constant() { - let a = FieldElement::from_bytes(&A_BYTES); - let ainv = FieldElement::from_bytes(&AINV_BYTES); - let should_be_inverse = a.invert(); - assert_eq!(ainv, should_be_inverse); - assert_eq!(FieldElement::one(), &a * &should_be_inverse); - } - - #[test] - fn batch_invert_a_matches_nonbatched() { - let a = FieldElement::from_bytes(&A_BYTES); - let ap58 = FieldElement::from_bytes(&AP58_BYTES); - let asq = FieldElement::from_bytes(&ASQ_BYTES); - let ainv = FieldElement::from_bytes(&AINV_BYTES); - let a2 = &a + &a; - let a_list = vec![a, ap58, asq, ainv, a2]; - let mut ainv_list = a_list.clone(); - FieldElement::batch_invert(&mut ainv_list[..]); - for i in 0..5 { - assert_eq!(a_list[i].invert(), ainv_list[i]); - } - } - - #[test] - fn sqrt_ratio_behavior() { - let zero = FieldElement::zero(); - let one = FieldElement::one(); - let i = constants::SQRT_M1; - let two = &one + &one; // 2 is nonsquare mod p. - let four = &two + &two; // 4 is square mod p. - - // 0/0 should return (1, 0) since u is 0 - let (choice, sqrt) = FieldElement::sqrt_ratio_i(&zero, &zero); - assert_eq!(choice.unwrap_u8(), 1); - assert_eq!(sqrt, zero); - assert_eq!(sqrt.is_negative().unwrap_u8(), 0); - - // 1/0 should return (0, 0) since v is 0, u is nonzero - let (choice, sqrt) = FieldElement::sqrt_ratio_i(&one, &zero); - assert_eq!(choice.unwrap_u8(), 0); - assert_eq!(sqrt, zero); - assert_eq!(sqrt.is_negative().unwrap_u8(), 0); - - // 2/1 is nonsquare, so we expect (0, sqrt(i*2)) - let (choice, sqrt) = FieldElement::sqrt_ratio_i(&two, &one); - assert_eq!(choice.unwrap_u8(), 0); - assert_eq!(sqrt.square(), &two * &i); - assert_eq!(sqrt.is_negative().unwrap_u8(), 0); - - // 4/1 is square, so we expect (1, sqrt(4)) - let (choice, sqrt) = FieldElement::sqrt_ratio_i(&four, &one); - assert_eq!(choice.unwrap_u8(), 1); - assert_eq!(sqrt.square(), four); - assert_eq!(sqrt.is_negative().unwrap_u8(), 0); - - // 1/4 is square, so we expect (1, 1/sqrt(4)) - let (choice, sqrt) = FieldElement::sqrt_ratio_i(&one, &four); - assert_eq!(choice.unwrap_u8(), 1); - assert_eq!(&sqrt.square() * &four, one); - assert_eq!(sqrt.is_negative().unwrap_u8(), 0); - } - - #[test] - fn a_p58_vs_ap58_constant() { - let a = FieldElement::from_bytes(&A_BYTES); - let ap58 = FieldElement::from_bytes(&AP58_BYTES); - assert_eq!(ap58, a.pow_p58()); - } - - #[test] - fn equality() { - let a = FieldElement::from_bytes(&A_BYTES); - let ainv = FieldElement::from_bytes(&AINV_BYTES); - assert!(a == a); - assert!(a != ainv); - } - - /// Notice that the last element has the high bit set, which - /// should be ignored - static B_BYTES: [u8;32] = - [113, 191, 169, 143, 91, 234, 121, 15, - 241, 131, 217, 36, 230, 101, 92, 234, - 8, 208, 170, 251, 97, 127, 70, 210, - 58, 23, 166, 87, 240, 169, 184, 178]; - - #[test] - fn from_bytes_highbit_is_ignored() { - let mut cleared_bytes = B_BYTES; - cleared_bytes[31] &= 127u8; - let with_highbit_set = FieldElement::from_bytes(&B_BYTES); - let without_highbit_set = FieldElement::from_bytes(&cleared_bytes); - assert_eq!(without_highbit_set, with_highbit_set); - } - - #[test] - fn conditional_negate() { - let one = FieldElement::one(); - let minus_one = FieldElement::minus_one(); - let mut x = one; - x.conditional_negate(Choice::from(1)); - assert_eq!(x, minus_one); - x.conditional_negate(Choice::from(0)); - assert_eq!(x, minus_one); - x.conditional_negate(Choice::from(1)); - assert_eq!(x, one); - } - - #[test] - fn encoding_is_canonical() { - // Encode 1 wrongly as 1 + (2^255 - 19) = 2^255 - 18 - let one_encoded_wrongly_bytes: [u8;32] = [0xee, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f]; - // Decode to a field element - let one = FieldElement::from_bytes(&one_encoded_wrongly_bytes); - // .. then check that the encoding is correct - let one_bytes = one.to_bytes(); - assert_eq!(one_bytes[0], 1); - for i in 1..32 { - assert_eq!(one_bytes[i], 0); - } - } - - #[test] - fn batch_invert_empty() { - FieldElement::batch_invert(&mut []); - } -} diff --git a/net/gurk-rs/files/vendor/curve25519-dalek-2.0.0/src/lib.rs b/net/gurk-rs/files/vendor/curve25519-dalek-2.0.0/src/lib.rs deleted file mode 100644 index 605662a..0000000 --- a/net/gurk-rs/files/vendor/curve25519-dalek-2.0.0/src/lib.rs +++ /dev/null @@ -1,100 +0,0 @@ -// -*- mode: rust; -*- -// -// This file is part of curve25519-dalek. -// Copyright (c) 2016-2019 Isis Lovecruft, Henry de Valence -// See LICENSE for licensing information. -// -// Authors: -// - Isis Agora Lovecruft -// - Henry de Valence - -#![no_std] -#![cfg_attr(feature = "nightly", feature(test))] -#![cfg_attr(all(feature = "alloc", not(feature = "std")), feature(alloc))] -#![cfg_attr(feature = "nightly", feature(external_doc))] -#![cfg_attr(feature = "nightly", feature(doc_cfg))] -#![cfg_attr(feature = "simd_backend", feature(stdsimd))] -// Refuse to compile if documentation is missing, but only on nightly. -// -// This means that missing docs will still fail CI, but means we can use -// README.md as the crate documentation. -//#![cfg_attr(feature = "nightly", deny(missing_docs))] - -#![cfg_attr(feature = "nightly", doc(include = "../README.md"))] -#![doc(html_logo_url = "https://doc.dalek.rs/assets/dalek-logo-clear.png")] - -//! Note that docs will only build on nightly Rust until -//! [RFC 1990 stabilizes](https://github.com/rust-lang/rust/issues/44732). - -//------------------------------------------------------------------------ -// External dependencies: -//------------------------------------------------------------------------ - -#[cfg(all(feature = "alloc", not(feature = "std")))] -#[macro_use] -extern crate alloc; - -#[cfg(feature = "std")] -#[macro_use] -extern crate std; - -#[cfg(all(feature = "nightly", feature = "packed_simd"))] -extern crate packed_simd; - -extern crate byteorder; -pub extern crate digest; -extern crate rand_core; -extern crate zeroize; - -// Used for traits related to constant-time code. -pub extern crate subtle; - -#[cfg(all(test, feature = "serde"))] -extern crate bincode; -#[cfg(feature = "serde")] -extern crate serde; - -// Internal macros. Must come first! -#[macro_use] -pub(crate) mod macros; - -//------------------------------------------------------------------------ -// curve25519-dalek public modules -//------------------------------------------------------------------------ - -// Scalar arithmetic mod l = 2^252 + ..., the order of the Ristretto group -pub mod scalar; - -// Point operations on the Montgomery form of Curve25519 -pub mod montgomery; - -// Point operations on the Edwards form of Curve25519 -pub mod edwards; - -// Group operations on the Ristretto group -pub mod ristretto; - -// Useful constants, like the Ed25519 basepoint -pub mod constants; - -// External (and internal) traits. -pub mod traits; - -// All the lizard code is here, for now -pub mod lizard; - -//------------------------------------------------------------------------ -// curve25519-dalek internal modules -//------------------------------------------------------------------------ - -// Finite field arithmetic mod p = 2^255 - 19 -pub mod field; - -// Arithmetic backends (using u32, u64, etc) live here -pub(crate) mod backend; - -// Crate-local prelude (for alloc-dependent features like `Vec`) -pub(crate) mod prelude; - -// Generic code for window lookups -pub(crate) mod window; diff --git a/net/gurk-rs/files/vendor/curve25519-dalek-2.0.0/src/lizard/LICENSE b/net/gurk-rs/files/vendor/curve25519-dalek-2.0.0/src/lizard/LICENSE deleted file mode 100644 index 2df7c96..0000000 --- a/net/gurk-rs/files/vendor/curve25519-dalek-2.0.0/src/lizard/LICENSE +++ /dev/null @@ -1,21 +0,0 @@ -MIT License - -Copyright (c) 2019 Bas Westerbaan - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. diff --git a/net/gurk-rs/files/vendor/curve25519-dalek-2.0.0/src/lizard/jacobi_quartic.rs b/net/gurk-rs/files/vendor/curve25519-dalek-2.0.0/src/lizard/jacobi_quartic.rs deleted file mode 100644 index 9ede5d3..0000000 --- a/net/gurk-rs/files/vendor/curve25519-dalek-2.0.0/src/lizard/jacobi_quartic.rs +++ /dev/null @@ -1,74 +0,0 @@ -//! Helper functions for use with Lizard - -#![allow(non_snake_case)] - -use subtle::Choice; -use subtle::ConstantTimeEq; -use subtle::ConditionallyNegatable; -use subtle::ConditionallySelectable; - -use constants; -use lizard::lizard_constants; - -use field::FieldElement; - - -/// Represents a point (s,t) on the the Jacobi quartic associated -/// to the Edwards curve. -#[derive(Copy, Clone)] -#[allow(missing_docs)] -pub struct JacobiPoint { - pub S: FieldElement, - pub T: FieldElement, -} - -impl JacobiPoint { - /// Elligator2 is defined in two steps: first a field element is converted - /// to a point (s,t) on the Jacobi quartic associated to the Edwards curve. - /// Then this point is mapped to a point on the Edwards curve. - /// This function computes a field element that is mapped to a given (s,t) - /// with Elligator2 if it exists. - pub(crate) fn elligator_inv(&self) -> (Choice, FieldElement) { - let mut out = FieldElement::zero(); - - // Special case: s = 0. If s is zero, either t = 1 or t = -1. - // If t=1, then sqrt(i*d) is the preimage. Otherwise it's 0. - let s_is_zero = self.S.is_zero(); - let t_equals_one = self.T.ct_eq(&FieldElement::one()); - out.conditional_assign(&lizard_constants::SQRT_ID, t_equals_one); - let mut ret = s_is_zero; - let mut done = s_is_zero; - - // a := (t+1) (d+1)/(d-1) - let a = &(&self.T + &FieldElement::one()) * &lizard_constants::DP1_OVER_DM1; - let a2 = a.square(); - - // y := 1/sqrt(i (s^4 - a^2)). - let s2 = self.S.square(); - let s4 = s2.square(); - let invSqY = &(&s4 - &a2) * &constants::SQRT_M1; - - // There is no preimage if the square root of i*(s^4-a^2) does not exist. - let (sq, y) = invSqY.invsqrt(); - ret |= sq; - done |= !sq; - - // x := (a + sign(s)*s^2) y - let mut pms2 = s2; - pms2.conditional_negate(self.S.is_negative()); - let mut x = &(&a + &pms2) * &y; - let x_is_negative = x.is_negative(); - x.conditional_negate(x_is_negative); - out.conditional_assign(&x, !done); - - (ret, out) - } - - pub(crate) fn dual(&self) -> JacobiPoint { - JacobiPoint { - S: -(&self.S), - T: -(&self.T), - } - } -} - diff --git a/net/gurk-rs/files/vendor/curve25519-dalek-2.0.0/src/lizard/lizard_constants.rs b/net/gurk-rs/files/vendor/curve25519-dalek-2.0.0/src/lizard/lizard_constants.rs deleted file mode 100644 index beb8882..0000000 --- a/net/gurk-rs/files/vendor/curve25519-dalek-2.0.0/src/lizard/lizard_constants.rs +++ /dev/null @@ -1,54 +0,0 @@ -//! Constants for use in Lizard -//! -//! Could be moved into backend/serial/u??/constants.rs - -#[cfg(feature = "u64_backend")] -pub(crate) use lizard::u64_constants::*; - -#[cfg(feature = "u32_backend")] -pub(crate) use lizard::u32_constants::*; - - -// ------------------------------------------------------------------------ -// Tests -// ------------------------------------------------------------------------ - -#[cfg(all(test, feature = "stage2_build"))] -mod test { - - use super::*; - use constants; - use field::FieldElement; - - #[test] - fn test_lizard_constants() { - let (_, sqrt_id) = FieldElement::sqrt_ratio_i( - &(&constants::SQRT_M1 * &constants::EDWARDS_D), - &FieldElement::one() - ); - assert_eq!(sqrt_id, SQRT_ID); - - assert_eq!( - &(&constants::EDWARDS_D + &FieldElement::one()) - * &(&constants::EDWARDS_D - &FieldElement::one()).invert(), - DP1_OVER_DM1 - ); - - assert_eq!( - MDOUBLE_INVSQRT_A_MINUS_D, - -&(&constants::INVSQRT_A_MINUS_D + &constants::INVSQRT_A_MINUS_D) - ); - - assert_eq!( - MIDOUBLE_INVSQRT_A_MINUS_D, - &MDOUBLE_INVSQRT_A_MINUS_D * &constants::SQRT_M1 - ); - - let (_, invsqrt_one_plus_d) = ( - &constants::EDWARDS_D + &FieldElement::one()).invsqrt(); - assert_eq!( - -&invsqrt_one_plus_d, - MINVSQRT_ONE_PLUS_D - ); - } -} diff --git a/net/gurk-rs/files/vendor/curve25519-dalek-2.0.0/src/lizard/lizard_ristretto.rs b/net/gurk-rs/files/vendor/curve25519-dalek-2.0.0/src/lizard/lizard_ristretto.rs deleted file mode 100644 index b240d0e..0000000 --- a/net/gurk-rs/files/vendor/curve25519-dalek-2.0.0/src/lizard/lizard_ristretto.rs +++ /dev/null @@ -1,305 +0,0 @@ -//! Defines additional methods on RistrettoPoint for Lizard - -#![allow(non_snake_case)] - -use digest::Digest; -use digest::generic_array::typenum::U32; - -use constants; -use field::FieldElement; - -use subtle::ConditionallySelectable; -use subtle::ConstantTimeEq; -use subtle::Choice; - -use edwards::EdwardsPoint; - -use lizard::jacobi_quartic::JacobiPoint; -use lizard::lizard_constants; - -#[allow(unused_imports)] -use prelude::*; -use ristretto::RistrettoPoint; - - -impl RistrettoPoint { - - pub fn from_uniform_bytes_single_elligator(bytes: &[u8; 32]) -> RistrettoPoint { - RistrettoPoint::elligator_ristretto_flavor(&FieldElement::from_bytes(&bytes)) - } - - /// Encode 16 bytes of data to a RistrettoPoint, using the Lizard method - pub fn lizard_encode(data: &[u8; 16]) -> RistrettoPoint - where D: Digest - { - let mut fe_bytes: [u8;32] = Default::default(); - - let digest = D::digest(data); - fe_bytes[0..32].copy_from_slice(digest.as_slice()); - fe_bytes[8..24].copy_from_slice(data); - fe_bytes[0] &= 254; // make positive since Elligator on r and -r is the same - fe_bytes[31] &= 63; - let fe = FieldElement::from_bytes(&fe_bytes); - RistrettoPoint::elligator_ristretto_flavor(&fe) - } - - /// Decode 16 bytes of data from a RistrettoPoint, using the Lizard method - pub fn lizard_decode(&self) -> Option<[u8; 16]> - where D: Digest - { - let mut result: [u8; 16] = Default::default(); - let mut h: [u8;32] = Default::default(); - let (mask, fes) = self.elligator_ristretto_flavor_inverse(); - let mut n_found = 0; - for j in 0..8 { - let mut ok = Choice::from((mask >> j) & 1); - let buf2 = fes[j].to_bytes(); // array - h.copy_from_slice(&D::digest(&buf2[8..24])); // array - h[8..24].copy_from_slice(&buf2[8..24]); - h[0] &= 254; - h[31] &= 63; - ok &= h.ct_eq(&buf2); - for i in 0..16 { - result[i] = u8::conditional_select(&result[i], &buf2[8+i], ok); - } - n_found += ok.unwrap_u8(); - } - if n_found == 1 { - return Some(result); - } - else { - return None; - } - } - - pub fn encode_253_bits(data: &[u8; 32]) -> Option - { - if data.len() != 32 { - return None; - } - - let fe = FieldElement::from_bytes(data); - let p = RistrettoPoint::elligator_ristretto_flavor(&fe); - Some(p) - } - - - pub fn decode_253_bits(&self) -> (u8, [[u8; 32]; 8]) - { - let mut ret = [ [0u8; 32]; 8]; - let (mask, fes) = self.elligator_ristretto_flavor_inverse(); - - for j in 0..8 { - ret[j] = fes[j].to_bytes(); - } - (mask, ret) - } - - /// Return the coset self + E[4], for debugging. - pub fn xcoset4(&self) -> [EdwardsPoint; 4] { - [ self.0 - , &self.0 + &constants::EIGHT_TORSION[2] - , &self.0 + &constants::EIGHT_TORSION[4] - , &self.0 + &constants::EIGHT_TORSION[6] - ] - } - - /// Computes the at most 8 positive FieldElements f such that - /// self == elligator_ristretto_flavor(f). - /// Assumes self is even. - /// - /// Returns a bitmask of which elements in fes are set. - pub fn elligator_ristretto_flavor_inverse(&self) -> (u8, [FieldElement; 8]) { - // Elligator2 computes a Point from a FieldElement in two steps: first - // it computes a (s,t) on the Jacobi quartic and then computes the - // corresponding even point on the Edwards curve. - // - // We invert in three steps. Any Ristretto point has four representatives - // as even Edwards points. For each of those even Edwards points, - // there are two points on the Jacobi quartic that map to it. - // Each of those eight points on the Jacobi quartic might have an - // Elligator2 preimage. - // - // Essentially we first loop over the four representatives of our point, - // then for each of them consider both points on the Jacobi quartic and - // check whether they have an inverse under Elligator2. We take the - // following shortcut though. - // - // We can compute two Jacobi quartic points for (x,y) and (-x,-y) - // at the same time. The four Jacobi quartic points are two of - // such pairs. - - let mut mask : u8 = 0; - let jcs = self.to_jacobi_quartic_ristretto(); - let mut ret = [FieldElement::one(); 8]; - - for i in 0..4 { - let (ok, fe) = jcs[i].elligator_inv(); - let mut tmp : u8 = 0; - ret[2*i] = fe; - tmp.conditional_assign(&1, ok); - mask |= tmp << (2 * i); - - let jc = jcs[i].dual(); - let (ok, fe) = jc.elligator_inv(); - let mut tmp : u8 = 0; - ret[2*i+1] = fe; - tmp.conditional_assign(&1, ok); - mask |= tmp << (2 * i + 1); - } - - return (mask, ret) - } - - /// Find a point on the Jacobi quartic associated to each of the four - /// points Ristretto equivalent to p. - /// - /// There is one exception: for (0,-1) there is no point on the quartic and - /// so we repeat one on the quartic equivalent to (0,1). - fn to_jacobi_quartic_ristretto(&self) -> [JacobiPoint; 4] { - let x2 = self.0.X.square(); // X^2 - let y2 = self.0.Y.square(); // Y^2 - let y4 = y2.square(); // Y^4 - let z2 = self.0.Z.square(); // Z^2 - let z_min_y = &self.0.Z - &self.0.Y; // Z - Y - let z_pl_y = &self.0.Z + &self.0.Y; // Z + Y - let z2_min_y2 = &z2 - &y2; // Z^2 - Y^2 - - // gamma := 1/sqrt( Y^4 X^2 (Z^2 - Y^2) ) - let (_, gamma) = (&(&y4 * &x2) * &z2_min_y2).invsqrt(); - - let den = &gamma * &y2; - - let s_over_x = &den * &z_min_y; - let sp_over_xp = &den * &z_pl_y; - - let s0 = &s_over_x * &self.0.X; - let s1 = &(-(&sp_over_xp)) * &self.0.X; - - // t_0 := -2/sqrt(-d-1) * Z * sOverX - // t_1 := -2/sqrt(-d-1) * Z * spOverXp - let tmp = &lizard_constants::MDOUBLE_INVSQRT_A_MINUS_D * &self.0.Z; - let mut t0 = &tmp * &s_over_x; - let mut t1 = &tmp * &sp_over_xp; - - // den := -1/sqrt(1+d) (Y^2 - Z^2) gamma - let den = &(&(-(&z2_min_y2)) * &lizard_constants::MINVSQRT_ONE_PLUS_D) * γ - - // Same as before but with the substitution (X, Y, Z) = (Y, X, i*Z) - let iz = &constants::SQRT_M1 * &self.0.Z; // iZ - let iz_min_x = &iz - &self.0.X; // iZ - X - let iz_pl_x = &iz + &self.0.X; // iZ + X - - let s_over_y = &den * &iz_min_x; - let sp_over_yp = &den * &iz_pl_x; - - let mut s2 = &s_over_y * &self.0.Y; - let mut s3 = &(-(&sp_over_yp)) * &self.0.Y; - - // t_2 := -2/sqrt(-d-1) * i*Z * sOverY - // t_3 := -2/sqrt(-d-1) * i*Z * spOverYp - let tmp = &lizard_constants::MDOUBLE_INVSQRT_A_MINUS_D * &iz; - let mut t2 = &tmp * &s_over_y; - let mut t3 = &tmp * &sp_over_yp; - - // Special case: X=0 or Y=0. Then return - // - // (0,1) (1,-2i/sqrt(-d-1) (-1,-2i/sqrt(-d-1)) - // - // Note that if X=0 or Y=0, then s_i = t_i = 0. - let x_or_y_is_zero = self.0.X.is_zero() | self.0.Y.is_zero(); - t0.conditional_assign(&FieldElement::one(), x_or_y_is_zero); - t1.conditional_assign(&FieldElement::one(), x_or_y_is_zero); - t2.conditional_assign(&lizard_constants::MIDOUBLE_INVSQRT_A_MINUS_D, x_or_y_is_zero); - t3.conditional_assign(&lizard_constants::MIDOUBLE_INVSQRT_A_MINUS_D, x_or_y_is_zero); - s2.conditional_assign(&FieldElement::one(), x_or_y_is_zero); - s3.conditional_assign(&(-(&FieldElement::one())), x_or_y_is_zero); - - return [ - JacobiPoint{S: s0, T: t0}, - JacobiPoint{S: s1, T: t1}, - JacobiPoint{S: s2, T: t2}, - JacobiPoint{S: s3, T: t3}, - ] - } -} - -// ------------------------------------------------------------------------ -// Tests -// ------------------------------------------------------------------------ - -#[cfg(all(test, feature = "stage2_build"))] -mod test { - - extern crate sha2; - - #[cfg(feature = "rand")] - use rand_os::OsRng; - use rand_core::{RngCore}; - use self::sha2::{Sha256}; - use ristretto::CompressedRistretto; - use super::*; - - fn test_lizard_encode_helper(data: &[u8; 16], result: &[u8; 32]) { - let p = RistrettoPoint::lizard_encode::(data).unwrap(); - let p_bytes = p.compress().to_bytes(); - assert!(&p_bytes == result); - let p = CompressedRistretto::from_slice(&p_bytes).decompress().unwrap(); - let data_out = p.lizard_decode::().unwrap(); - assert!(&data_out == data); - } - - #[test] - fn test_lizard_encode() { - test_lizard_encode_helper(&[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], - &[0xf0, 0xb7, 0xe3, 0x44, 0x84, 0xf7, 0x4c, 0xf0, 0xf, 0x15, 0x2, 0x4b, 0x73, 0x85, 0x39, 0x73, 0x86, 0x46, 0xbb, 0xbe, 0x1e, 0x9b, 0xc7, 0x50, 0x9a, 0x67, 0x68, 0x15, 0x22, 0x7e, 0x77, 0x4f]); - - test_lizard_encode_helper(&[1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1], - &[0xcc, 0x92, 0xe8, 0x1f, 0x58, 0x5a, 0xfc, 0x5c, 0xaa, 0xc8, 0x86, 0x60, 0xd8, 0xd1, 0x7e, 0x90, 0x25, 0xa4, 0x44, 0x89, 0xa3, 0x63, 0x4, 0x21, 0x23, 0xf6, 0xaf, 0x7, 0x2, 0x15, 0x6e, 0x65]); - - test_lizard_encode_helper(&[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15], - &[0xc8, 0x30, 0x57, 0x3f, 0x8a, 0x8e, 0x77, 0x78, 0x67, 0x1f, 0x76, 0xcd, 0xc7, 0x96, 0xdc, 0xa, 0x23, 0x5c, 0xf1, 0x77, 0xf1, 0x97, 0xd9, 0xfc, 0xba, 0x6, 0xe8, 0x4e, 0x96, 0x24, 0x74, 0x44]); - } - - #[test] - fn test_elligator_inv() { - let mut rng = rand::thread_rng(); - - for i in 0..100 { - let mut fe_bytes = [0u8; 32]; - - if i == 0 { - // Test for first corner-case: fe = 0 - fe_bytes = [0u8; 32]; - } else if i == 1 { - // Test for second corner-case: fe = +sqrt(i*d) - fe_bytes = [168, 27, 92, 74, 203, 42, 48, 117, 170, 109, 234, - 14, 45, 169, 188, 205, 21, 110, 235, 115, 153, 84, - 52, 117, 151, 235, 123, 244, 88, 85, 179, 5]; - } else { - // For the rest, just generate a random field element to test. - rng.fill_bytes(&mut fe_bytes); - } - fe_bytes[0] &= 254; // positive - fe_bytes[31] &= 127; // < 2^255-19 - let fe = FieldElement::from_bytes(&fe_bytes); - - let pt = RistrettoPoint::elligator_ristretto_flavor(&fe); - for pt2 in &pt.xcoset4() { - let (mask, fes) = RistrettoPoint(*pt2).elligator_ristretto_flavor_inverse(); - - let mut found = false; - for j in 0..8 { - if mask & (1 << j) != 0 { - assert_eq!(RistrettoPoint::elligator_ristretto_flavor(&fes[j]), pt); - if fes[j] == fe { - found = true; - } - } - } - assert!(found); - } - } - } -} - diff --git a/net/gurk-rs/files/vendor/curve25519-dalek-2.0.0/src/lizard/mod.rs b/net/gurk-rs/files/vendor/curve25519-dalek-2.0.0/src/lizard/mod.rs deleted file mode 100644 index ff3f950..0000000 --- a/net/gurk-rs/files/vendor/curve25519-dalek-2.0.0/src/lizard/mod.rs +++ /dev/null @@ -1,13 +0,0 @@ -//! The Lizard method for encoding/decoding 16 bytes into Ristretto points. - -#![allow(non_snake_case)] - -#[cfg(feature = "u32_backend")] -mod u32_constants; - -#[cfg(feature = "u64_backend")] -mod u64_constants; - -pub mod lizard_constants; -pub mod jacobi_quartic; -pub mod lizard_ristretto; diff --git a/net/gurk-rs/files/vendor/curve25519-dalek-2.0.0/src/lizard/u32_constants.rs b/net/gurk-rs/files/vendor/curve25519-dalek-2.0.0/src/lizard/u32_constants.rs deleted file mode 100644 index 388cf0d..0000000 --- a/net/gurk-rs/files/vendor/curve25519-dalek-2.0.0/src/lizard/u32_constants.rs +++ /dev/null @@ -1,33 +0,0 @@ -use backend::serial::u32::field::FieldElement2625; -use edwards::EdwardsPoint; - -/// `= sqrt(i*d)`, where `i = +sqrt(-1)` and `d` is the Edwards curve parameter. -pub const SQRT_ID: FieldElement2625 = FieldElement2625([ - 39590824, 701138, 28659366, 23623507, 53932708, - 32206357, 36326585, 24309414, 26167230, 1494357, -]); - -/// `= (d+1)/(d-1)`, where `d` is the Edwards curve parameter. -pub const DP1_OVER_DM1: FieldElement2625 = FieldElement2625([ - 58833708, 32184294, 62457071, 26110240, 19032991, - 27203620, 7122892, 18068959, 51019405, 3776288, -]); - -/// `= -2/sqrt(a-d)`, where `a = -1 (mod p)`, `d` are the Edwards curve parameters. -pub const MDOUBLE_INVSQRT_A_MINUS_D: FieldElement2625 = FieldElement2625([ - 54885894, 25242303, 55597453, 9067496, 51808079, - 33312638, 25456129, 14121551, 54921728, 3972023, -]); - -/// `= -2i/sqrt(a-d)`, where `a = -1 (mod p)`, `d` are the Edwards curve parameters -/// and `i = +sqrt(-1)`. -pub const MIDOUBLE_INVSQRT_A_MINUS_D: FieldElement2625 = FieldElement2625([ - 58178520, 23970840, 26444491, 29801899, 41064376, - 743696, 2900628, 27920316, 41968995, 5270573, -]); - -/// `= -1/sqrt(1+d)`, where `d` is the Edwards curve parameters. -pub const MINVSQRT_ONE_PLUS_D: FieldElement2625 = FieldElement2625([ - 38019585, 4791795, 20332186, 18653482, 46576675, - 33182583, 65658549, 2817057, 12569934, 30919145, -]); diff --git a/net/gurk-rs/files/vendor/curve25519-dalek-2.0.0/src/lizard/u64_constants.rs b/net/gurk-rs/files/vendor/curve25519-dalek-2.0.0/src/lizard/u64_constants.rs deleted file mode 100644 index 31b0a95..0000000 --- a/net/gurk-rs/files/vendor/curve25519-dalek-2.0.0/src/lizard/u64_constants.rs +++ /dev/null @@ -1,18 +0,0 @@ -use backend::serial::u64::field::FieldElement51; - -/// `= sqrt(i*d)`, where `i = +sqrt(-1)` and `d` is the Edwards curve parameter. -pub const SQRT_ID: FieldElement51 = FieldElement51([2298852427963285, 3837146560810661, 4413131899466403, 3883177008057528, 2352084440532925]); - -/// `= (d+1)/(d-1)`, where `d` is the Edwards curve parameter. -pub const DP1_OVER_DM1: FieldElement51 = FieldElement51([2159851467815724, 1752228607624431, 1825604053920671, 1212587319275468, 253422448836237]); - -/// `= -2/sqrt(a-d)`, where `a = -1 (mod p)`, `d` are the Edwards curve parameters. -pub const MDOUBLE_INVSQRT_A_MINUS_D: FieldElement51 = FieldElement51([1693982333959686, 608509411481997, 2235573344831311, 947681270984193, 266558006233600]); - -/// `= -2i/sqrt(a-d)`, where `a = -1 (mod p)`, `d` are the Edwards curve parameters -/// and `i = +sqrt(-1)`. -pub const MIDOUBLE_INVSQRT_A_MINUS_D: FieldElement51 = FieldElement51([1608655899704280, 1999971613377227, 49908634785720, 1873700692181652, 353702208628067]); - -/// `= -1/sqrt(1+d)`, where `d` is the Edwards curve parameters. -pub const MINVSQRT_ONE_PLUS_D: FieldElement51 = FieldElement51([321571956990465, 1251814006996634, 2226845496292387, 189049560751797, 2074948709371214]); - diff --git a/net/gurk-rs/files/vendor/curve25519-dalek-2.0.0/src/macros.rs b/net/gurk-rs/files/vendor/curve25519-dalek-2.0.0/src/macros.rs deleted file mode 100644 index 5985a5f..0000000 --- a/net/gurk-rs/files/vendor/curve25519-dalek-2.0.0/src/macros.rs +++ /dev/null @@ -1,123 +0,0 @@ -// -*- mode: rust; -*- -// -// This file is part of curve25519-dalek. -// Copyright (c) 2016-2019 Isis Lovecruft, Henry de Valence -// See LICENSE for licensing information. -// -// Authors: -// - Isis Agora Lovecruft -// - Henry de Valence - -//! Internal macros. - -/// Define borrow and non-borrow variants of `Add`. -macro_rules! define_add_variants { - (LHS = $lhs:ty, RHS = $rhs:ty, Output = $out:ty) => { - impl<'b> Add<&'b $rhs> for $lhs { - type Output = $out; - fn add(self, rhs: &'b $rhs) -> $out { - &self + rhs - } - } - - impl<'a> Add<$rhs> for &'a $lhs { - type Output = $out; - fn add(self, rhs: $rhs) -> $out { - self + &rhs - } - } - - impl Add<$rhs> for $lhs { - type Output = $out; - fn add(self, rhs: $rhs) -> $out { - &self + &rhs - } - } - } -} - -/// Define non-borrow variants of `AddAssign`. -macro_rules! define_add_assign_variants { - (LHS = $lhs:ty, RHS = $rhs:ty) => { - impl AddAssign<$rhs> for $lhs { - fn add_assign(&mut self, rhs: $rhs) { - *self += &rhs; - } - } - } -} - -/// Define borrow and non-borrow variants of `Sub`. -macro_rules! define_sub_variants { - (LHS = $lhs:ty, RHS = $rhs:ty, Output = $out:ty) => { - impl<'b> Sub<&'b $rhs> for $lhs { - type Output = $out; - fn sub(self, rhs: &'b $rhs) -> $out { - &self - rhs - } - } - - impl<'a> Sub<$rhs> for &'a $lhs { - type Output = $out; - fn sub(self, rhs: $rhs) -> $out { - self - &rhs - } - } - - impl Sub<$rhs> for $lhs { - type Output = $out; - fn sub(self, rhs: $rhs) -> $out { - &self - &rhs - } - } - } -} - -/// Define non-borrow variants of `SubAssign`. -macro_rules! define_sub_assign_variants { - (LHS = $lhs:ty, RHS = $rhs:ty) => { - impl SubAssign<$rhs> for $lhs { - fn sub_assign(&mut self, rhs: $rhs) { - *self -= &rhs; - } - } - } -} - -/// Define borrow and non-borrow variants of `Mul`. -macro_rules! define_mul_variants { - (LHS = $lhs:ty, RHS = $rhs:ty, Output = $out:ty) => { - impl<'b> Mul<&'b $rhs> for $lhs { - type Output = $out; - fn mul(self, rhs: &'b $rhs) -> $out { - &self * rhs - } - } - - impl<'a> Mul<$rhs> for &'a $lhs { - type Output = $out; - fn mul(self, rhs: $rhs) -> $out { - self * &rhs - } - } - - impl Mul<$rhs> for $lhs { - type Output = $out; - fn mul(self, rhs: $rhs) -> $out { - &self * &rhs - } - } - } -} - -/// Define non-borrow variants of `MulAssign`. -macro_rules! define_mul_assign_variants { - (LHS = $lhs:ty, RHS = $rhs:ty) => { - impl MulAssign<$rhs> for $lhs { - fn mul_assign(&mut self, rhs: $rhs) { - *self *= &rhs; - } - } - } -} - diff --git a/net/gurk-rs/files/vendor/curve25519-dalek-2.0.0/src/montgomery.rs b/net/gurk-rs/files/vendor/curve25519-dalek-2.0.0/src/montgomery.rs deleted file mode 100644 index 4768451..0000000 --- a/net/gurk-rs/files/vendor/curve25519-dalek-2.0.0/src/montgomery.rs +++ /dev/null @@ -1,403 +0,0 @@ -// -*- mode: rust; -*- -// -// This file is part of curve25519-dalek. -// Copyright (c) 2016-2019 Isis Lovecruft, Henry de Valence -// See LICENSE for licensing information. -// -// Authors: -// - Isis Agora Lovecruft -// - Henry de Valence - -//! Scalar multiplication on the Montgomery form of Curve25519. -//! -//! To avoid notational confusion with the Edwards code, we use -//! variables \\( u, v \\) for the Montgomery curve, so that “Montgomery -//! \\(u\\)” here corresponds to “Montgomery \\(x\\)” elsewhere. -//! -//! Montgomery arithmetic works not on the curve itself, but on the -//! \\(u\\)-line, which discards sign information and unifies the curve -//! and its quadratic twist. See [_Montgomery curves and their -//! arithmetic_][costello-smith] by Costello and Smith for more details. -//! -//! The `MontgomeryPoint` struct contains the affine \\(u\\)-coordinate -//! \\(u\_0(P)\\) of a point \\(P\\) on either the curve or the twist. -//! Here the map \\(u\_0 : \mathcal M \rightarrow \mathbb F\_p \\) is -//! defined by \\(u\_0((u,v)) = u\\); \\(u\_0(\mathcal O) = 0\\). See -//! section 5.4 of Costello-Smith for more details. -//! -//! # Scalar Multiplication -//! -//! Scalar multiplication on `MontgomeryPoint`s is provided by the `*` -//! operator, which implements the Montgomery ladder. -//! -//! # Edwards Conversion -//! -//! The \\(2\\)-to-\\(1\\) map from the Edwards model to the Montgomery -//! \\(u\\)-line is provided by `EdwardsPoint::to_montgomery()`. -//! -//! To lift a `MontgomeryPoint` to an `EdwardsPoint`, use -//! `MontgomeryPoint::to_edwards()`, which takes a sign parameter. -//! This function rejects `MontgomeryPoints` which correspond to points -//! on the twist. -//! -//! [costello-smith]: https://eprint.iacr.org/2017/212.pdf - -// We allow non snake_case names because coordinates in projective space are -// traditionally denoted by the capitalisation of their respective -// counterparts in affine space. Yeah, you heard me, rustc, I'm gonna have my -// affine and projective cakes and eat both of them too. -#![allow(non_snake_case)] - -use core::ops::{Mul, MulAssign}; - -use constants::APLUS2_OVER_FOUR; -use edwards::{CompressedEdwardsY, EdwardsPoint}; -use field::FieldElement; -use scalar::Scalar; - -use traits::Identity; - -use subtle::Choice; -use subtle::ConditionallySelectable; -use subtle::ConstantTimeEq; - -use zeroize::Zeroize; - -/// Holds the \\(u\\)-coordinate of a point on the Montgomery form of -/// Curve25519 or its twist. -#[derive(Copy, Clone, Debug)] -#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] -pub struct MontgomeryPoint(pub [u8; 32]); - -/// Equality of `MontgomeryPoint`s is defined mod p. -impl ConstantTimeEq for MontgomeryPoint { - fn ct_eq(&self, other: &MontgomeryPoint) -> Choice { - let self_fe = FieldElement::from_bytes(&self.0); - let other_fe = FieldElement::from_bytes(&other.0); - - self_fe.ct_eq(&other_fe) - } -} - -impl Default for MontgomeryPoint { - fn default() -> MontgomeryPoint { - MontgomeryPoint([0u8; 32]) - } -} - -impl PartialEq for MontgomeryPoint { - fn eq(&self, other: &MontgomeryPoint) -> bool { - self.ct_eq(other).unwrap_u8() == 1u8 - } -} - -impl Eq for MontgomeryPoint {} - -impl Zeroize for MontgomeryPoint { - fn zeroize(&mut self) { - self.0.zeroize(); - } -} - -impl MontgomeryPoint { - /// View this `MontgomeryPoint` as an array of bytes. - pub fn as_bytes<'a>(&'a self) -> &'a [u8; 32] { - &self.0 - } - - /// Convert this `MontgomeryPoint` to an array of bytes. - pub fn to_bytes(&self) -> [u8; 32] { - self.0 - } - - /// Attempt to convert to an `EdwardsPoint`, using the supplied - /// choice of sign for the `EdwardsPoint`. - /// - /// # Inputs - /// - /// * `sign`: a `u8` donating the desired sign of the resulting - /// `EdwardsPoint`. `0` denotes positive and `1` negative. - /// - /// # Return - /// - /// * `Some(EdwardsPoint)` if `self` is the \\(u\\)-coordinate of a - /// point on (the Montgomery form of) Curve25519; - /// - /// * `None` if `self` is the \\(u\\)-coordinate of a point on the - /// twist of (the Montgomery form of) Curve25519; - /// - pub fn to_edwards(&self, sign: u8) -> Option { - // To decompress the Montgomery u coordinate to an - // `EdwardsPoint`, we apply the birational map to obtain the - // Edwards y coordinate, then do Edwards decompression. - // - // The birational map is y = (u-1)/(u+1). - // - // The exceptional points are the zeros of the denominator, - // i.e., u = -1. - // - // But when u = -1, v^2 = u*(u^2+486662*u+1) = 486660. - // - // Since this is nonsquare mod p, u = -1 corresponds to a point - // on the twist, not the curve, so we can reject it early. - - let u = FieldElement::from_bytes(&self.0); - - if u == FieldElement::minus_one() { return None; } - - let one = FieldElement::one(); - - let y = &(&u - &one) * &(&u + &one).invert(); - - let mut y_bytes = y.to_bytes(); - y_bytes[31] ^= sign << 7; - - CompressedEdwardsY(y_bytes).decompress() - } -} - -/// A `ProjectivePoint` holds a point on the projective line -/// \\( \mathbb P(\mathbb F\_p) \\), which we identify with the Kummer -/// line of the Montgomery curve. -#[derive(Copy, Clone, Debug)] -struct ProjectivePoint { - pub U: FieldElement, - pub W: FieldElement, -} - -impl Identity for ProjectivePoint { - fn identity() -> ProjectivePoint { - ProjectivePoint { - U: FieldElement::one(), - W: FieldElement::zero(), - } - } -} - -impl Default for ProjectivePoint { - fn default() -> ProjectivePoint { - ProjectivePoint::identity() - } -} - -impl ConditionallySelectable for ProjectivePoint { - fn conditional_select( - a: &ProjectivePoint, - b: &ProjectivePoint, - choice: Choice, - ) -> ProjectivePoint { - ProjectivePoint { - U: FieldElement::conditional_select(&a.U, &b.U, choice), - W: FieldElement::conditional_select(&a.W, &b.W, choice), - } - } -} - -impl ProjectivePoint { - /// Dehomogenize this point to affine coordinates. - /// - /// # Return - /// - /// * \\( u = U / W \\) if \\( W \neq 0 \\); - /// * \\( 0 \\) if \\( W \eq 0 \\); - pub fn to_affine(&self) -> MontgomeryPoint { - let u = &self.U * &self.W.invert(); - MontgomeryPoint(u.to_bytes()) - } -} - -/// Perform the double-and-add step of the Montgomery ladder. -/// -/// Given projective points -/// \\( (U\_P : W\_P) = u(P) \\), -/// \\( (U\_Q : W\_Q) = u(Q) \\), -/// and the affine difference -/// \\( u\_{P-Q} = u(P-Q) \\), set -/// $$ -/// (U\_P : W\_P) \gets u([2]P) -/// $$ -/// and -/// $$ -/// (U\_Q : W\_Q) \gets u(P + Q). -/// $$ -fn differential_add_and_double( - P: &mut ProjectivePoint, - Q: &mut ProjectivePoint, - affine_PmQ: &FieldElement, -) { - let t0 = &P.U + &P.W; - let t1 = &P.U - &P.W; - let t2 = &Q.U + &Q.W; - let t3 = &Q.U - &Q.W; - - let t4 = t0.square(); // (U_P + W_P)^2 = U_P^2 + 2 U_P W_P + W_P^2 - let t5 = t1.square(); // (U_P - W_P)^2 = U_P^2 - 2 U_P W_P + W_P^2 - - let t6 = &t4 - &t5; // 4 U_P W_P - - let t7 = &t0 * &t3; // (U_P + W_P) (U_Q - W_Q) = U_P U_Q + W_P U_Q - U_P W_Q - W_P W_Q - let t8 = &t1 * &t2; // (U_P - W_P) (U_Q + W_Q) = U_P U_Q - W_P U_Q + U_P W_Q - W_P W_Q - - let t9 = &t7 + &t8; // 2 (U_P U_Q - W_P W_Q) - let t10 = &t7 - &t8; // 2 (W_P U_Q - U_P W_Q) - - let t11 = t9.square(); // 4 (U_P U_Q - W_P W_Q)^2 - let t12 = t10.square(); // 4 (W_P U_Q - U_P W_Q)^2 - - let t13 = &APLUS2_OVER_FOUR * &t6; // (A + 2) U_P U_Q - - let t14 = &t4 * &t5; // ((U_P + W_P)(U_P - W_P))^2 = (U_P^2 - W_P^2)^2 - let t15 = &t13 + &t5; // (U_P - W_P)^2 + (A + 2) U_P W_P - - let t16 = &t6 * &t15; // 4 (U_P W_P) ((U_P - W_P)^2 + (A + 2) U_P W_P) - - let t17 = affine_PmQ * &t12; // U_D * 4 (W_P U_Q - U_P W_Q)^2 - let t18 = t11; // W_D * 4 (U_P U_Q - W_P W_Q)^2 - - P.U = t14; // U_{P'} = (U_P + W_P)^2 (U_P - W_P)^2 - P.W = t16; // W_{P'} = (4 U_P W_P) ((U_P - W_P)^2 + ((A + 2)/4) 4 U_P W_P) - Q.U = t18; // U_{Q'} = W_D * 4 (U_P U_Q - W_P W_Q)^2 - Q.W = t17; // W_{Q'} = U_D * 4 (W_P U_Q - U_P W_Q)^2 -} - -define_mul_assign_variants!(LHS = MontgomeryPoint, RHS = Scalar); - -define_mul_variants!(LHS = MontgomeryPoint, RHS = Scalar, Output = MontgomeryPoint); -define_mul_variants!(LHS = Scalar, RHS = MontgomeryPoint, Output = MontgomeryPoint); - -/// Multiply this `MontgomeryPoint` by a `Scalar`. -impl<'a, 'b> Mul<&'b Scalar> for &'a MontgomeryPoint { - type Output = MontgomeryPoint; - - /// Given `self` \\( = u\_0(P) \\), and a `Scalar` \\(n\\), return \\( u\_0([n]P) \\). - fn mul(self, scalar: &'b Scalar) -> MontgomeryPoint { - // Algorithm 8 of Costello-Smith 2017 - let affine_u = FieldElement::from_bytes(&self.0); - let mut x0 = ProjectivePoint::identity(); - let mut x1 = ProjectivePoint { - U: affine_u, - W: FieldElement::one(), - }; - - let bits: [i8; 256] = scalar.bits(); - - for i in (0..255).rev() { - let choice: u8 = (bits[i + 1] ^ bits[i]) as u8; - - debug_assert!(choice == 0 || choice == 1); - - ProjectivePoint::conditional_swap(&mut x0, &mut x1, choice.into()); - differential_add_and_double(&mut x0, &mut x1, &affine_u); - } - ProjectivePoint::conditional_swap(&mut x0, &mut x1, Choice::from(bits[0] as u8)); - - x0.to_affine() - } -} - -impl<'b> MulAssign<&'b Scalar> for MontgomeryPoint { - fn mul_assign(&mut self, scalar: &'b Scalar) { - *self = (self as &MontgomeryPoint) * scalar; - } -} - -impl<'a, 'b> Mul<&'b MontgomeryPoint> for &'a Scalar { - type Output = MontgomeryPoint; - - fn mul(self, point: &'b MontgomeryPoint) -> MontgomeryPoint { - point * self - } -} - -// ------------------------------------------------------------------------ -// Tests -// ------------------------------------------------------------------------ - -#[cfg(test)] -mod test { - use constants; - use super::*; - - use rand_core::OsRng; - - #[test] - #[cfg(feature = "serde")] - fn serde_bincode_basepoint_roundtrip() { - use bincode; - - let encoded = bincode::serialize(&constants::X25519_BASEPOINT).unwrap(); - let decoded: MontgomeryPoint = bincode::deserialize(&encoded).unwrap(); - - assert_eq!(encoded.len(), 32); - assert_eq!(decoded, constants::X25519_BASEPOINT); - - let raw_bytes = constants::X25519_BASEPOINT.as_bytes(); - let bp: MontgomeryPoint = bincode::deserialize(raw_bytes).unwrap(); - assert_eq!(bp, constants::X25519_BASEPOINT); - } - - /// Test Montgomery -> Edwards on the X/Ed25519 basepoint - #[test] - fn basepoint_montgomery_to_edwards() { - // sign bit = 0 => basepoint - assert_eq!( - constants::ED25519_BASEPOINT_POINT, - constants::X25519_BASEPOINT.to_edwards(0).unwrap() - ); - // sign bit = 1 => minus basepoint - assert_eq!( - - constants::ED25519_BASEPOINT_POINT, - constants::X25519_BASEPOINT.to_edwards(1).unwrap() - ); - } - - /// Test Edwards -> Montgomery on the X/Ed25519 basepoint - #[test] - fn basepoint_edwards_to_montgomery() { - assert_eq!( - constants::ED25519_BASEPOINT_POINT.to_montgomery(), - constants::X25519_BASEPOINT - ); - } - - /// Check that Montgomery -> Edwards fails for points on the twist. - #[test] - fn montgomery_to_edwards_rejects_twist() { - let one = FieldElement::one(); - - // u = 2 corresponds to a point on the twist. - let two = MontgomeryPoint((&one+&one).to_bytes()); - - assert!(two.to_edwards(0).is_none()); - - // u = -1 corresponds to a point on the twist, but should be - // checked explicitly because it's an exceptional point for the - // birational map. For instance, libsignal will accept it. - let minus_one = MontgomeryPoint((-&one).to_bytes()); - - assert!(minus_one.to_edwards(0).is_none()); - } - - #[test] - fn eq_defined_mod_p() { - let mut u18_bytes = [0u8; 32]; u18_bytes[0] = 18; - let u18 = MontgomeryPoint(u18_bytes); - let u18_unred = MontgomeryPoint([255; 32]); - - assert_eq!(u18, u18_unred); - } - - #[test] - fn montgomery_ladder_matches_edwards_scalarmult() { - let mut csprng: OsRng = OsRng; - - let s: Scalar = Scalar::random(&mut csprng); - let p_edwards: EdwardsPoint = &constants::ED25519_BASEPOINT_TABLE * &s; - let p_montgomery: MontgomeryPoint = p_edwards.to_montgomery(); - - let expected = s * p_edwards; - let result = s * p_montgomery; - - assert_eq!(result, expected.to_montgomery()) - } -} diff --git a/net/gurk-rs/files/vendor/curve25519-dalek-2.0.0/src/prelude.rs b/net/gurk-rs/files/vendor/curve25519-dalek-2.0.0/src/prelude.rs deleted file mode 100644 index be2f600..0000000 --- a/net/gurk-rs/files/vendor/curve25519-dalek-2.0.0/src/prelude.rs +++ /dev/null @@ -1,8 +0,0 @@ -//! Crate-local prelude (for alloc-dependent features like `Vec`) - -// TODO: switch to alloc::prelude -#[cfg(all(feature = "alloc", not(feature = "std")))] -pub use alloc::vec::Vec; - -#[cfg(feature = "std")] -pub use std::vec::Vec; diff --git a/net/gurk-rs/files/vendor/curve25519-dalek-2.0.0/src/ristretto.rs b/net/gurk-rs/files/vendor/curve25519-dalek-2.0.0/src/ristretto.rs deleted file mode 100644 index a37cb50..0000000 --- a/net/gurk-rs/files/vendor/curve25519-dalek-2.0.0/src/ristretto.rs +++ /dev/null @@ -1,1365 +0,0 @@ -// -*- mode: rust; -*- -// -// This file is part of curve25519-dalek. -// Copyright (c) 2016-2019 Isis Lovecruft, Henry de Valence -// See LICENSE for licensing information. -// -// Authors: -// - Isis Agora Lovecruft -// - Henry de Valence - -// We allow non snake_case names because coordinates in projective space are -// traditionally denoted by the capitalisation of their respective -// counterparts in affine space. Yeah, you heard me, rustc, I'm gonna have my -// affine and projective cakes and eat both of them too. -#![allow(non_snake_case)] - -//! An implementation of [Ristretto][ristretto_main], which provides a -//! prime-order group. -//! -//! # The Ristretto Group -//! -//! Ristretto is a modification of Mike Hamburg's Decaf scheme to work -//! with cofactor-\\(8\\) curves, such as Curve25519. -//! -//! The introduction of the Decaf paper, [_Decaf: -//! Eliminating cofactors through point -//! compression_](https://eprint.iacr.org/2015/673.pdf), notes that while -//! most cryptographic systems require a group of prime order, most -//! concrete implementations using elliptic curve groups fall short – -//! they either provide a group of prime order, but with incomplete or -//! variable-time addition formulae (for instance, most Weierstrass -//! models), or else they provide a fast and safe implementation of a -//! group whose order is not quite a prime \\(q\\), but \\(hq\\) for a -//! small cofactor \\(h\\) (for instance, Edwards curves, which have -//! cofactor at least \\(4\\)). -//! -//! This abstraction mismatch is commonly “handled” by pushing the -//! complexity upwards, adding ad-hoc protocol modifications. But -//! these modifications require careful analysis and are a recurring -//! source of [vulnerabilities][cryptonote] and [design -//! complications][ed25519_hkd]. -//! -//! Instead, Decaf (and Ristretto) use a quotient group to implement a -//! prime-order group using a non-prime-order curve. This provides -//! the correct abstraction for cryptographic systems, while retaining -//! the speed and safety benefits of an Edwards curve. -//! -//! Decaf is named “after the procedure which divides the effect of -//! coffee by \\(4\\)”. However, Curve25519 has a cofactor of -//! \\(8\\). To eliminate its cofactor, Ristretto restricts further; -//! this [additional restriction][ristretto_coffee] gives the -//! _Ristretto_ encoding. -//! -//! More details on why Ristretto is necessary can be found in the -//! [Why Ristretto?][why_ristretto] section of the Ristretto website. -//! -//! Ristretto -//! points are provided in `curve25519-dalek` by the `RistrettoPoint` -//! struct. -//! -//! ## Encoding and Decoding -//! -//! Encoding is done by converting to and from a `CompressedRistretto` -//! struct, which is a typed wrapper around `[u8; 32]`. -//! -//! The encoding is not batchable, but it is possible to -//! double-and-encode in a batch using -//! `RistrettoPoint::double_and_compress_batch`. -//! -//! ## Equality Testing -//! -//! Testing equality of points on an Edwards curve in projective -//! coordinates requires an expensive inversion. By contrast, equality -//! checking in the Ristretto group can be done in projective -//! coordinates without requiring an inversion, so it is much faster. -//! -//! The `RistrettoPoint` struct implements the -//! `subtle::ConstantTimeEq` trait for constant-time equality -//! checking, and the Rust `Eq` trait for variable-time equality -//! checking. -//! -//! ## Scalars -//! -//! Scalars are represented by the `Scalar` struct. Each scalar has a -//! canonical representative mod the group order. To attempt to load -//! a supposedly-canonical scalar, use -//! `Scalar::from_canonical_bytes()`. To check whether a -//! representative is canonical, use `Scalar::is_canonical()`. -//! -//! ## Scalar Multiplication -//! -//! Scalar multiplication on Ristretto points is provided by: -//! -//! * the `*` operator between a `Scalar` and a `RistrettoPoint`, which -//! performs constant-time variable-base scalar multiplication; -//! -//! * the `*` operator between a `Scalar` and a -//! `RistrettoBasepointTable`, which performs constant-time fixed-base -//! scalar multiplication; -//! -//! * an implementation of the -//! [`MultiscalarMul`](../traits/trait.MultiscalarMul.html) trait for -//! constant-time variable-base multiscalar multiplication; -//! -//! * an implementation of the -//! [`VartimeMultiscalarMul`](../traits/trait.VartimeMultiscalarMul.html) -//! trait for variable-time variable-base multiscalar multiplication; -//! -//! ## Random Points and Hashing to Ristretto -//! -//! The Ristretto group comes equipped with an Elligator map. This is -//! used to implement -//! -//! * `RistrettoPoint::random()`, which generates random points from an -//! RNG; -//! -//! * `RistrettoPoint::from_hash()` and -//! `RistrettoPoint::hash_from_bytes()`, which perform hashing to the -//! group. -//! -//! The Elligator map itself is not currently exposed. -//! -//! ## Implementation -//! -//! The Decaf suggestion is to use a quotient group, such as \\(\mathcal -//! E / \mathcal E[4]\\) or \\(2 \mathcal E / \mathcal E[2] \\), to -//! implement a prime-order group using a non-prime-order curve. -//! -//! This requires only changing -//! -//! 1. the function for equality checking (so that two representatives -//! of the same coset are considered equal); -//! 2. the function for encoding (so that two representatives of the -//! same coset are encoded as identical bitstrings); -//! 3. the function for decoding (so that only the canonical encoding of -//! a coset is accepted). -//! -//! Internally, each coset is represented by a curve point; two points -//! \\( P, Q \\) may represent the same coset in the same way that two -//! points with different \\(X,Y,Z\\) coordinates may represent the -//! same point. The group operations are carried out with no overhead -//! using Edwards formulas. -//! -//! Notes on the details of the encoding can be found in the -//! [Details][ristretto_notes] section of the Ristretto website. -//! -//! [cryptonote]: -//! https://moderncrypto.org/mail-archive/curves/2017/000898.html -//! [ed25519_hkd]: -//! https://moderncrypto.org/mail-archive/curves/2017/000858.html -//! [ristretto_coffee]: -//! https://en.wikipedia.org/wiki/Ristretto -//! [ristretto_notes]: -//! https://ristretto.group/details/index.html -//! [why_ristretto]: -//! https://ristretto.group/why_ristretto.html -//! [ristretto_main]: -//! https://ristretto.group/ - -use core::borrow::Borrow; -use core::fmt::Debug; -use core::iter::Sum; -use core::ops::{Add, Neg, Sub}; -use core::ops::{AddAssign, SubAssign}; -use core::ops::{Mul, MulAssign}; - -use rand_core::{CryptoRng, RngCore}; - -use digest::generic_array::typenum::U64; -use digest::Digest; - -use constants; -use field::FieldElement; - -use subtle::Choice; -use subtle::ConditionallySelectable; -use subtle::ConditionallyNegatable; -use subtle::ConstantTimeEq; - -use edwards::EdwardsBasepointTable; -use edwards::EdwardsPoint; - -#[allow(unused_imports)] -use prelude::*; - -use scalar::Scalar; - -use traits::Identity; -#[cfg(any(feature = "alloc", feature = "std"))] -use traits::{MultiscalarMul, VartimeMultiscalarMul, VartimePrecomputedMultiscalarMul}; - -#[cfg(not(all( - feature = "simd_backend", - any(target_feature = "avx2", target_feature = "avx512ifma") -)))] -use backend::serial::scalar_mul; -#[cfg(all( - feature = "simd_backend", - any(target_feature = "avx2", target_feature = "avx512ifma") -))] -use backend::vector::scalar_mul; - -// ------------------------------------------------------------------------ -// Compressed points -// ------------------------------------------------------------------------ - -/// A Ristretto point, in compressed wire format. -/// -/// The Ristretto encoding is canonical, so two points are equal if and -/// only if their encodings are equal. -#[derive(Copy, Clone, Eq, PartialEq)] -pub struct CompressedRistretto(pub [u8; 32]); - -impl ConstantTimeEq for CompressedRistretto { - fn ct_eq(&self, other: &CompressedRistretto) -> Choice { - self.as_bytes().ct_eq(other.as_bytes()) - } -} - -impl CompressedRistretto { - /// Copy the bytes of this `CompressedRistretto`. - pub fn to_bytes(&self) -> [u8; 32] { - self.0 - } - - /// View this `CompressedRistretto` as an array of bytes. - pub fn as_bytes(&self) -> &[u8; 32] { - &self.0 - } - - /// Construct a `CompressedRistretto` from a slice of bytes. - /// - /// # Panics - /// - /// If the input `bytes` slice does not have a length of 32. - pub fn from_slice(bytes: &[u8]) -> CompressedRistretto { - let mut tmp = [0u8; 32]; - - tmp.copy_from_slice(bytes); - - CompressedRistretto(tmp) - } - - /// Attempt to decompress to an `RistrettoPoint`. - /// - /// # Return - /// - /// - `Some(RistrettoPoint)` if `self` was the canonical encoding of a point; - /// - /// - `None` if `self` was not the canonical encoding of a point. - pub fn decompress(&self) -> Option { - // Step 1. Check s for validity: - // 1.a) s must be 32 bytes (we get this from the type system) - // 1.b) s < p - // 1.c) s is nonnegative - // - // Our decoding routine ignores the high bit, so the only - // possible failure for 1.b) is if someone encodes s in 0..18 - // as s+p in 2^255-19..2^255-1. We can check this by - // converting back to bytes, and checking that we get the - // original input, since our encoding routine is canonical. - - let s = FieldElement::from_bytes(self.as_bytes()); - let s_bytes_check = s.to_bytes(); - let s_encoding_is_canonical = - &s_bytes_check[..].ct_eq(self.as_bytes()); - let s_is_negative = s.is_negative(); - - if s_encoding_is_canonical.unwrap_u8() == 0u8 || s_is_negative.unwrap_u8() == 1u8 { - return None; - } - - // Step 2. Compute (X:Y:Z:T). - let one = FieldElement::one(); - let ss = s.square(); - let u1 = &one - &ss; // 1 + as² - let u2 = &one + &ss; // 1 - as² where a=-1 - let u2_sqr = u2.square(); // (1 - as²)² - - // v == ad(1+as²)² - (1-as²)² where d=-121665/121666 - let v = &(&(-&constants::EDWARDS_D) * &u1.square()) - &u2_sqr; - - let (ok, I) = (&v * &u2_sqr).invsqrt(); // 1/sqrt(v*u_2²) - - let Dx = &I * &u2; // 1/sqrt(v) - let Dy = &I * &(&Dx * &v); // 1/u2 - - // x == | 2s/sqrt(v) | == + sqrt(4s²/(ad(1+as²)² - (1-as²)²)) - let mut x = &(&s + &s) * &Dx; - let x_neg = x.is_negative(); - x.conditional_negate(x_neg); - - // y == (1-as²)/(1+as²) - let y = &u1 * &Dy; - - // t == ((1+as²) sqrt(4s²/(ad(1+as²)² - (1-as²)²)))/(1-as²) - let t = &x * &y; - - if ok.unwrap_u8() == 0u8 || t.is_negative().unwrap_u8() == 1u8 || y.is_zero().unwrap_u8() == 1u8 { - None - } else { - Some(RistrettoPoint(EdwardsPoint{X: x, Y: y, Z: one, T: t})) - } - } -} - -impl Identity for CompressedRistretto { - fn identity() -> CompressedRistretto { - CompressedRistretto([0u8; 32]) - } -} - -impl Default for CompressedRistretto { - fn default() -> CompressedRistretto { - CompressedRistretto::identity() - } -} - -// ------------------------------------------------------------------------ -// Serde support -// ------------------------------------------------------------------------ -// Serializes to and from `RistrettoPoint` directly, doing compression -// and decompression internally. This means that users can create -// structs containing `RistrettoPoint`s and use Serde's derived -// serializers to serialize those structures. - -#[cfg(feature = "serde")] -use serde::{self, Serialize, Deserialize, Serializer, Deserializer}; -#[cfg(feature = "serde")] -use serde::de::Visitor; - -#[cfg(feature = "serde")] -impl Serialize for RistrettoPoint { - fn serialize(&self, serializer: S) -> Result - where S: Serializer - { - use serde::ser::SerializeTuple; - let mut tup = serializer.serialize_tuple(32)?; - for byte in self.compress().as_bytes().iter() { - tup.serialize_element(byte)?; - } - tup.end() - } -} - -#[cfg(feature = "serde")] -impl Serialize for CompressedRistretto { - fn serialize(&self, serializer: S) -> Result - where S: Serializer - { - use serde::ser::SerializeTuple; - let mut tup = serializer.serialize_tuple(32)?; - for byte in self.as_bytes().iter() { - tup.serialize_element(byte)?; - } - tup.end() - } -} - -#[cfg(feature = "serde")] -impl<'de> Deserialize<'de> for RistrettoPoint { - fn deserialize(deserializer: D) -> Result - where D: Deserializer<'de> - { - struct RistrettoPointVisitor; - - impl<'de> Visitor<'de> for RistrettoPointVisitor { - type Value = RistrettoPoint; - - fn expecting(&self, formatter: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { - formatter.write_str("a valid point in Ristretto format") - } - - fn visit_seq(self, mut seq: A) -> Result - where A: serde::de::SeqAccess<'de> - { - let mut bytes = [0u8; 32]; - for i in 0..32 { - bytes[i] = seq.next_element()? - .ok_or(serde::de::Error::invalid_length(i, &"expected 32 bytes"))?; - } - CompressedRistretto(bytes) - .decompress() - .ok_or(serde::de::Error::custom("decompression failed")) - } - } - - deserializer.deserialize_tuple(32, RistrettoPointVisitor) - } -} - -#[cfg(feature = "serde")] -impl<'de> Deserialize<'de> for CompressedRistretto { - fn deserialize(deserializer: D) -> Result - where D: Deserializer<'de> - { - struct CompressedRistrettoVisitor; - - impl<'de> Visitor<'de> for CompressedRistrettoVisitor { - type Value = CompressedRistretto; - - fn expecting(&self, formatter: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { - formatter.write_str("32 bytes of data") - } - - fn visit_seq(self, mut seq: A) -> Result - where A: serde::de::SeqAccess<'de> - { - let mut bytes = [0u8; 32]; - for i in 0..32 { - bytes[i] = seq.next_element()? - .ok_or(serde::de::Error::invalid_length(i, &"expected 32 bytes"))?; - } - Ok(CompressedRistretto(bytes)) - } - } - - deserializer.deserialize_tuple(32, CompressedRistrettoVisitor) - } -} - -// ------------------------------------------------------------------------ -// Internal point representations -// ------------------------------------------------------------------------ - -/// A `RistrettoPoint` represents a point in the Ristretto group for -/// Curve25519. Ristretto, a variant of Decaf, constructs a -/// prime-order group as a quotient group of a subgroup of (the -/// Edwards form of) Curve25519. -/// -/// Internally, a `RistrettoPoint` is implemented as a wrapper type -/// around `EdwardsPoint`, with custom equality, compression, and -/// decompression routines to account for the quotient. This means that -/// operations on `RistrettoPoint`s are exactly as fast as operations on -/// `EdwardsPoint`s. -/// -#[derive(Copy, Clone)] -pub struct RistrettoPoint(pub(crate) EdwardsPoint); - -impl RistrettoPoint { - /// Compress this point using the Ristretto encoding. - pub fn compress(&self) -> CompressedRistretto { - let mut X = self.0.X; - let mut Y = self.0.Y; - let Z = &self.0.Z; - let T = &self.0.T; - - let u1 = &(Z + &Y) * &(Z - &Y); - let u2 = &X * &Y; - // Ignore return value since this is always square - let (_, invsqrt) = (&u1 * &u2.square()).invsqrt(); - let i1 = &invsqrt * &u1; - let i2 = &invsqrt * &u2; - let z_inv = &i1 * &(&i2 * T); - let mut den_inv = i2; - - let iX = &X * &constants::SQRT_M1; - let iY = &Y * &constants::SQRT_M1; - let ristretto_magic = &constants::INVSQRT_A_MINUS_D; - let enchanted_denominator = &i1 * ristretto_magic; - - let rotate = (T * &z_inv).is_negative(); - - X.conditional_assign(&iY, rotate); - Y.conditional_assign(&iX, rotate); - den_inv.conditional_assign(&enchanted_denominator, rotate); - - Y.conditional_negate((&X * &z_inv).is_negative()); - - let mut s = &den_inv * &(Z - &Y); - let s_is_negative = s.is_negative(); - s.conditional_negate(s_is_negative); - - CompressedRistretto(s.to_bytes()) - } - - /// Double-and-compress a batch of points. The Ristretto encoding - /// is not batchable, since it requires an inverse square root. - /// - /// However, given input points \\( P\_1, \ldots, P\_n, \\) - /// it is possible to compute the encodings of their doubles \\( - /// \mathrm{enc}( [2]P\_1), \ldots, \mathrm{enc}( [2]P\_n ) \\) - /// in a batch. - /// - /// ``` - /// # extern crate curve25519_dalek; - /// # use curve25519_dalek::ristretto::RistrettoPoint; - /// extern crate rand_core; - /// use rand_core::OsRng; - /// - /// # // Need fn main() here in comment so the doctest compiles - /// # // See https://doc.rust-lang.org/book/documentation.html#documentation-as-tests - /// # fn main() { - /// let mut rng = OsRng; - /// let points: Vec = - /// (0..32).map(|_| RistrettoPoint::random(&mut rng)).collect(); - /// - /// let compressed = RistrettoPoint::double_and_compress_batch(&points); - /// - /// for (P, P2_compressed) in points.iter().zip(compressed.iter()) { - /// assert_eq!(*P2_compressed, (P + P).compress()); - /// } - /// # } - /// ``` - #[cfg(feature = "alloc")] - pub fn double_and_compress_batch<'a, I>(points: I) -> Vec - where I: IntoIterator - { - #[derive(Copy, Clone, Debug)] - struct BatchCompressState { - e: FieldElement, - f: FieldElement, - g: FieldElement, - h: FieldElement, - eg: FieldElement, - fh: FieldElement, - } - - impl BatchCompressState { - fn efgh(&self) -> FieldElement { - &self.eg * &self.fh - } - } - - impl<'a> From<&'a RistrettoPoint> for BatchCompressState { - fn from(P: &'a RistrettoPoint) -> BatchCompressState { - let XX = P.0.X.square(); - let YY = P.0.Y.square(); - let ZZ = P.0.Z.square(); - let dTT = &P.0.T.square() * &constants::EDWARDS_D; - - let e = &P.0.X * &(&P.0.Y + &P.0.Y); // = 2*X*Y - let f = &ZZ + &dTT; // = Z^2 + d*T^2 - let g = &YY + &XX; // = Y^2 - a*X^2 - let h = &ZZ - &dTT; // = Z^2 - d*T^2 - - let eg = &e * &g; - let fh = &f * &h; - - BatchCompressState{ e, f, g, h, eg, fh } - } - } - - let states: Vec = points.into_iter().map(BatchCompressState::from).collect(); - - let mut invs: Vec = states.iter().map(|state| state.efgh()).collect(); - - FieldElement::batch_invert(&mut invs[..]); - - states.iter().zip(invs.iter()).map(|(state, inv): (&BatchCompressState, &FieldElement)| { - let Zinv = &state.eg * &inv; - let Tinv = &state.fh * &inv; - - let mut magic = constants::INVSQRT_A_MINUS_D; - - let negcheck1 = (&state.eg * &Zinv).is_negative(); - - let mut e = state.e; - let mut g = state.g; - let mut h = state.h; - - let minus_e = -&e; - let f_times_sqrta = &state.f * &constants::SQRT_M1; - - e.conditional_assign(&state.g, negcheck1); - g.conditional_assign(&minus_e, negcheck1); - h.conditional_assign(&f_times_sqrta, negcheck1); - - magic.conditional_assign(&constants::SQRT_M1, negcheck1); - - let negcheck2 = (&(&h * &e) * &Zinv).is_negative(); - - g.conditional_negate(negcheck2); - - let mut s = &(&h - &g) * &(&magic * &(&g * &Tinv)); - - let s_is_negative = s.is_negative(); - s.conditional_negate(s_is_negative); - - CompressedRistretto(s.to_bytes()) - }).collect() - } - - - /// Return the coset self + E[4], for debugging. - fn coset4(&self) -> [EdwardsPoint; 4] { - [ self.0 - , &self.0 + &constants::EIGHT_TORSION[2] - , &self.0 + &constants::EIGHT_TORSION[4] - , &self.0 + &constants::EIGHT_TORSION[6] - ] - } - - /// Computes the Ristretto Elligator map. - /// - /// # Note - /// - /// This method is not public because it's just used for hashing - /// to a point -- proper elligator support is deferred for now. - pub fn elligator_ristretto_flavor(r_0: &FieldElement) -> RistrettoPoint { - let i = &constants::SQRT_M1; - let d = &constants::EDWARDS_D; - let one_minus_d_sq = &constants::ONE_MINUS_EDWARDS_D_SQUARED; - let d_minus_one_sq = &constants::EDWARDS_D_MINUS_ONE_SQUARED; - let mut c = constants::MINUS_ONE; - - let one = FieldElement::one(); - - let r = i * &r_0.square(); - let N_s = &(&r + &one) * &one_minus_d_sq; - let D = &(&c - &(d * &r)) * &(&r + d); - - let (Ns_D_is_sq, mut s) = FieldElement::sqrt_ratio_i(&N_s, &D); - let mut s_prime = &s * r_0; - let s_prime_is_pos = !s_prime.is_negative(); - s_prime.conditional_negate(s_prime_is_pos); - - s.conditional_assign(&s_prime, !Ns_D_is_sq); - c.conditional_assign(&r, !Ns_D_is_sq); - - let N_t = &(&(&c * &(&r - &one)) * &d_minus_one_sq) - &D; - let s_sq = s.square(); - - use backend::serial::curve_models::CompletedPoint; - - // The conversion from W_i is exactly the conversion from P1xP1. - RistrettoPoint(CompletedPoint{ - X: &(&s + &s) * &D, - Z: &N_t * &constants::SQRT_AD_MINUS_ONE, - Y: &FieldElement::one() - &s_sq, - T: &FieldElement::one() + &s_sq, - }.to_extended()) - } - - /// Return a `RistrettoPoint` chosen uniformly at random using a user-provided RNG. - /// - /// # Inputs - /// - /// * `rng`: any RNG which implements the `RngCore + CryptoRng` interface. - /// - /// # Returns - /// - /// A random element of the Ristretto group. - /// - /// # Implementation - /// - /// Uses the Ristretto-flavoured Elligator 2 map, so that the - /// discrete log of the output point with respect to any other - /// point should be unknown. The map is applied twice and the - /// results are added, to ensure a uniform distribution. - pub fn random(rng: &mut R) -> Self { - let mut uniform_bytes = [0u8; 64]; - rng.fill_bytes(&mut uniform_bytes); - - RistrettoPoint::from_uniform_bytes(&uniform_bytes) - } - - /// Hash a slice of bytes into a `RistrettoPoint`. - /// - /// Takes a type parameter `D`, which is any `Digest` producing 64 - /// bytes of output. - /// - /// Convenience wrapper around `from_hash`. - /// - /// # Implementation - /// - /// Uses the Ristretto-flavoured Elligator 2 map, so that the - /// discrete log of the output point with respect to any other - /// point should be unknown. The map is applied twice and the - /// results are added, to ensure a uniform distribution. - /// - /// # Example - /// - /// ``` - /// # extern crate curve25519_dalek; - /// # use curve25519_dalek::ristretto::RistrettoPoint; - /// extern crate sha2; - /// use sha2::Sha512; - /// - /// # // Need fn main() here in comment so the doctest compiles - /// # // See https://doc.rust-lang.org/book/documentation.html#documentation-as-tests - /// # fn main() { - /// let msg = "To really appreciate architecture, you may even need to commit a murder"; - /// let P = RistrettoPoint::hash_from_bytes::(msg.as_bytes()); - /// # } - /// ``` - /// - pub fn hash_from_bytes(input: &[u8]) -> RistrettoPoint - where D: Digest + Default - { - let mut hash = D::default(); - hash.input(input); - RistrettoPoint::from_hash(hash) - } - - /// Construct a `RistrettoPoint` from an existing `Digest` instance. - /// - /// Use this instead of `hash_from_bytes` if it is more convenient - /// to stream data into the `Digest` than to pass a single byte - /// slice. - pub fn from_hash(hash: D) -> RistrettoPoint - where D: Digest + Default - { - // dealing with generic arrays is clumsy, until const generics land - let output = hash.result(); - let mut output_bytes = [0u8; 64]; - output_bytes.copy_from_slice(&output.as_slice()); - - RistrettoPoint::from_uniform_bytes(&output_bytes) - } - - /// Construct a `RistrettoPoint` from 64 bytes of data. - /// - /// If the input bytes are uniformly distributed, the resulting - /// point will be uniformly distributed over the group, and its - /// discrete log with respect to other points should be unknown. - /// - /// # Implementation - /// - /// This function splits the input array into two 32-byte halves, - /// takes the low 255 bits of each half mod p, applies the - /// Ristretto-flavored Elligator map to each, and adds the results. - pub fn from_uniform_bytes(bytes: &[u8; 64]) -> RistrettoPoint { - let mut r_1_bytes = [0u8; 32]; - r_1_bytes.copy_from_slice(&bytes[0..32]); - let r_1 = FieldElement::from_bytes(&r_1_bytes); - let R_1 = RistrettoPoint::elligator_ristretto_flavor(&r_1); - - let mut r_2_bytes = [0u8; 32]; - r_2_bytes.copy_from_slice(&bytes[32..64]); - let r_2 = FieldElement::from_bytes(&r_2_bytes); - let R_2 = RistrettoPoint::elligator_ristretto_flavor(&r_2); - - // Applying Elligator twice and adding the results ensures a - // uniform distribution. - &R_1 + &R_2 - } -} - -impl Identity for RistrettoPoint { - fn identity() -> RistrettoPoint { - RistrettoPoint(EdwardsPoint::identity()) - } -} - -impl Default for RistrettoPoint { - fn default() -> RistrettoPoint { - RistrettoPoint::identity() - } -} - -// ------------------------------------------------------------------------ -// Equality -// ------------------------------------------------------------------------ - -impl PartialEq for RistrettoPoint { - fn eq(&self, other: &RistrettoPoint) -> bool { - self.ct_eq(other).unwrap_u8() == 1u8 - } -} - -impl ConstantTimeEq for RistrettoPoint { - /// Test equality between two `RistrettoPoint`s. - /// - /// # Returns - /// - /// * `Choice(1)` if the two `RistrettoPoint`s are equal; - /// * `Choice(0)` otherwise. - fn ct_eq(&self, other: &RistrettoPoint) -> Choice { - let X1Y2 = &self.0.X * &other.0.Y; - let Y1X2 = &self.0.Y * &other.0.X; - let X1X2 = &self.0.X * &other.0.X; - let Y1Y2 = &self.0.Y * &other.0.Y; - - X1Y2.ct_eq(&Y1X2) | X1X2.ct_eq(&Y1Y2) - } -} - -impl Eq for RistrettoPoint {} - -// ------------------------------------------------------------------------ -// Arithmetic -// ------------------------------------------------------------------------ - -impl<'a, 'b> Add<&'b RistrettoPoint> for &'a RistrettoPoint { - type Output = RistrettoPoint; - - fn add(self, other: &'b RistrettoPoint) -> RistrettoPoint { - RistrettoPoint(&self.0 + &other.0) - } -} - -define_add_variants!(LHS = RistrettoPoint, RHS = RistrettoPoint, Output = RistrettoPoint); - -impl<'b> AddAssign<&'b RistrettoPoint> for RistrettoPoint { - fn add_assign(&mut self, _rhs: &RistrettoPoint) { - *self = (self as &RistrettoPoint) + _rhs; - } -} - -define_add_assign_variants!(LHS = RistrettoPoint, RHS = RistrettoPoint); - -impl<'a, 'b> Sub<&'b RistrettoPoint> for &'a RistrettoPoint { - type Output = RistrettoPoint; - - fn sub(self, other: &'b RistrettoPoint) -> RistrettoPoint { - RistrettoPoint(&self.0 - &other.0) - } -} - -define_sub_variants!(LHS = RistrettoPoint, RHS = RistrettoPoint, Output = RistrettoPoint); - -impl<'b> SubAssign<&'b RistrettoPoint> for RistrettoPoint { - fn sub_assign(&mut self, _rhs: &RistrettoPoint) { - *self = (self as &RistrettoPoint) - _rhs; - } -} - -define_sub_assign_variants!(LHS = RistrettoPoint, RHS = RistrettoPoint); - -impl Sum for RistrettoPoint -where - T: Borrow -{ - fn sum(iter: I) -> Self - where - I: Iterator - { - iter.fold(RistrettoPoint::identity(), |acc, item| acc + item.borrow()) - } -} - -impl<'a> Neg for &'a RistrettoPoint { - type Output = RistrettoPoint; - - fn neg(self) -> RistrettoPoint { - RistrettoPoint(-&self.0) - } -} - -impl Neg for RistrettoPoint { - type Output = RistrettoPoint; - - fn neg(self) -> RistrettoPoint { - -&self - } -} - -impl<'b> MulAssign<&'b Scalar> for RistrettoPoint { - fn mul_assign(&mut self, scalar: &'b Scalar) { - let result = (self as &RistrettoPoint) * scalar; - *self = result; - } -} - -impl<'a, 'b> Mul<&'b Scalar> for &'a RistrettoPoint { - type Output = RistrettoPoint; - /// Scalar multiplication: compute `scalar * self`. - fn mul(self, scalar: &'b Scalar) -> RistrettoPoint { - RistrettoPoint(self.0 * scalar) - } -} - -impl<'a, 'b> Mul<&'b RistrettoPoint> for &'a Scalar { - type Output = RistrettoPoint; - - /// Scalar multiplication: compute `self * scalar`. - fn mul(self, point: &'b RistrettoPoint) -> RistrettoPoint { - RistrettoPoint(self * point.0) - } -} - -define_mul_assign_variants!(LHS = RistrettoPoint, RHS = Scalar); - -define_mul_variants!(LHS = RistrettoPoint, RHS = Scalar, Output = RistrettoPoint); -define_mul_variants!(LHS = Scalar, RHS = RistrettoPoint, Output = RistrettoPoint); - -// ------------------------------------------------------------------------ -// Multiscalar Multiplication impls -// ------------------------------------------------------------------------ - -// These use iterator combinators to unwrap the underlying points and -// forward to the EdwardsPoint implementations. - -#[cfg(feature = "alloc")] -impl MultiscalarMul for RistrettoPoint { - type Point = RistrettoPoint; - - fn multiscalar_mul(scalars: I, points: J) -> RistrettoPoint - where - I: IntoIterator, - I::Item: Borrow, - J: IntoIterator, - J::Item: Borrow, - { - let extended_points = points.into_iter().map(|P| P.borrow().0); - RistrettoPoint( - EdwardsPoint::multiscalar_mul(scalars, extended_points) - ) - } -} - -#[cfg(feature = "alloc")] -impl VartimeMultiscalarMul for RistrettoPoint { - type Point = RistrettoPoint; - - fn optional_multiscalar_mul(scalars: I, points: J) -> Option - where - I: IntoIterator, - I::Item: Borrow, - J: IntoIterator>, - { - let extended_points = points.into_iter().map(|opt_P| opt_P.map(|P| P.borrow().0)); - - EdwardsPoint::optional_multiscalar_mul(scalars, extended_points).map(RistrettoPoint) - } -} - -/// Precomputation for variable-time multiscalar multiplication with `RistrettoPoint`s. -// This wraps the inner implementation in a facade type so that we can -// decouple stability of the inner type from the stability of the -// outer type. -#[cfg(feature = "alloc")] -pub struct VartimeRistrettoPrecomputation(scalar_mul::precomputed_straus::VartimePrecomputedStraus); - -#[cfg(feature = "alloc")] -impl VartimePrecomputedMultiscalarMul for VartimeRistrettoPrecomputation { - type Point = RistrettoPoint; - - fn new(static_points: I) -> Self - where - I: IntoIterator, - I::Item: Borrow, - { - Self( - scalar_mul::precomputed_straus::VartimePrecomputedStraus::new( - static_points.into_iter().map(|P| P.borrow().0), - ), - ) - } - - fn optional_mixed_multiscalar_mul( - &self, - static_scalars: I, - dynamic_scalars: J, - dynamic_points: K, - ) -> Option - where - I: IntoIterator, - I::Item: Borrow, - J: IntoIterator, - J::Item: Borrow, - K: IntoIterator>, - { - self.0 - .optional_mixed_multiscalar_mul( - static_scalars, - dynamic_scalars, - dynamic_points.into_iter().map(|P_opt| P_opt.map(|P| P.0)), - ) - .map(RistrettoPoint) - } -} - -impl RistrettoPoint { - /// Compute \\(aA + bB\\) in variable time, where \\(B\\) is the - /// Ristretto basepoint. - pub fn vartime_double_scalar_mul_basepoint( - a: &Scalar, - A: &RistrettoPoint, - b: &Scalar, - ) -> RistrettoPoint { - RistrettoPoint( - EdwardsPoint::vartime_double_scalar_mul_basepoint(a, &A.0, b) - ) - } -} - -/// A precomputed table of multiples of a basepoint, used to accelerate -/// scalar multiplication. -/// -/// A precomputed table of multiples of the Ristretto basepoint is -/// available in the `constants` module: -/// ``` -/// use curve25519_dalek::constants; -/// use curve25519_dalek::scalar::Scalar; -/// -/// let a = Scalar::from(87329482u64); -/// let P = &a * &constants::RISTRETTO_BASEPOINT_TABLE; -/// ``` -#[derive(Clone)] -pub struct RistrettoBasepointTable(pub(crate) EdwardsBasepointTable); - -impl<'a, 'b> Mul<&'b Scalar> for &'a RistrettoBasepointTable { - type Output = RistrettoPoint; - - fn mul(self, scalar: &'b Scalar) -> RistrettoPoint { - RistrettoPoint(&self.0 * scalar) - } -} - -impl<'a, 'b> Mul<&'a RistrettoBasepointTable> for &'b Scalar { - type Output = RistrettoPoint; - - fn mul(self, basepoint_table: &'a RistrettoBasepointTable) -> RistrettoPoint { - RistrettoPoint(self * &basepoint_table.0) - } -} - -impl RistrettoBasepointTable { - /// Create a precomputed table of multiples of the given `basepoint`. - pub fn create(basepoint: &RistrettoPoint) -> RistrettoBasepointTable { - RistrettoBasepointTable(EdwardsBasepointTable::create(&basepoint.0)) - } - - /// Get the basepoint for this table as a `RistrettoPoint`. - pub fn basepoint(&self) -> RistrettoPoint { - RistrettoPoint(self.0.basepoint()) - } -} - -// ------------------------------------------------------------------------ -// Constant-time conditional selection -// ------------------------------------------------------------------------ - -impl ConditionallySelectable for RistrettoPoint { - /// Conditionally select between `self` and `other`. - /// - /// # Example - /// - /// ``` - /// # extern crate subtle; - /// # extern crate curve25519_dalek; - /// # - /// use subtle::ConditionallySelectable; - /// use subtle::Choice; - /// # - /// # use curve25519_dalek::traits::Identity; - /// # use curve25519_dalek::ristretto::RistrettoPoint; - /// # use curve25519_dalek::constants; - /// # fn main() { - /// - /// let A = RistrettoPoint::identity(); - /// let B = constants::RISTRETTO_BASEPOINT_POINT; - /// - /// let mut P = A; - /// - /// P = RistrettoPoint::conditional_select(&A, &B, Choice::from(0)); - /// assert_eq!(P, A); - /// P = RistrettoPoint::conditional_select(&A, &B, Choice::from(1)); - /// assert_eq!(P, B); - /// # } - /// ``` - fn conditional_select( - a: &RistrettoPoint, - b: &RistrettoPoint, - choice: Choice, - ) -> RistrettoPoint { - RistrettoPoint(EdwardsPoint::conditional_select(&a.0, &b.0, choice)) - } -} - -// ------------------------------------------------------------------------ -// Debug traits -// ------------------------------------------------------------------------ - -impl Debug for CompressedRistretto { - fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { - write!(f, "CompressedRistretto: {:?}", self.as_bytes()) - } -} - -impl Debug for RistrettoPoint { - fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { - let coset = self.coset4(); - write!(f, "RistrettoPoint: coset \n{:?}\n{:?}\n{:?}\n{:?}", - coset[0], coset[1], coset[2], coset[3]) - } -} - -// ------------------------------------------------------------------------ -// Tests -// ------------------------------------------------------------------------ - -#[cfg(test)] -mod test { - use rand_core::OsRng; - - use scalar::Scalar; - use constants; - use edwards::CompressedEdwardsY; - use traits::{Identity}; - use super::*; - - #[test] - #[cfg(feature = "serde")] - fn serde_bincode_basepoint_roundtrip() { - use bincode; - - let encoded = bincode::serialize(&constants::RISTRETTO_BASEPOINT_POINT).unwrap(); - let enc_compressed = bincode::serialize(&constants::RISTRETTO_BASEPOINT_COMPRESSED).unwrap(); - assert_eq!(encoded, enc_compressed); - - // Check that the encoding is 32 bytes exactly - assert_eq!(encoded.len(), 32); - - let dec_uncompressed: RistrettoPoint = bincode::deserialize(&encoded).unwrap(); - let dec_compressed: CompressedRistretto = bincode::deserialize(&encoded).unwrap(); - - assert_eq!(dec_uncompressed, constants::RISTRETTO_BASEPOINT_POINT); - assert_eq!(dec_compressed, constants::RISTRETTO_BASEPOINT_COMPRESSED); - - // Check that the encoding itself matches the usual one - let raw_bytes = constants::RISTRETTO_BASEPOINT_COMPRESSED.as_bytes(); - let bp: RistrettoPoint = bincode::deserialize(raw_bytes).unwrap(); - assert_eq!(bp, constants::RISTRETTO_BASEPOINT_POINT); - } - - #[test] - fn scalarmult_ristrettopoint_works_both_ways() { - let P = constants::RISTRETTO_BASEPOINT_POINT; - let s = Scalar::from(999u64); - - let P1 = &P * &s; - let P2 = &s * &P; - - assert!(P1.compress().as_bytes() == P2.compress().as_bytes()); - } - - #[test] - fn impl_sum() { - - // Test that sum works for non-empty iterators - let BASE = constants::RISTRETTO_BASEPOINT_POINT; - - let s1 = Scalar::from(999u64); - let P1 = &BASE * &s1; - - let s2 = Scalar::from(333u64); - let P2 = &BASE * &s2; - - let vec = vec![P1.clone(), P2.clone()]; - let sum: RistrettoPoint = vec.iter().sum(); - - assert_eq!(sum, P1 + P2); - - // Test that sum works for the empty iterator - let empty_vector: Vec = vec![]; - let sum: RistrettoPoint = empty_vector.iter().sum(); - - assert_eq!(sum, RistrettoPoint::identity()); - - // Test that sum works on owning iterators - let s = Scalar::from(2u64); - let mapped = vec.iter().map(|x| x * s); - let sum: RistrettoPoint = mapped.sum(); - - assert_eq!(sum, &P1 * &s + &P2 * &s); - } - - #[test] - fn decompress_negative_s_fails() { - // constants::d is neg, so decompression should fail as |d| != d. - let bad_compressed = CompressedRistretto(constants::EDWARDS_D.to_bytes()); - assert!(bad_compressed.decompress().is_none()); - } - - #[test] - fn decompress_id() { - let compressed_id = CompressedRistretto::identity(); - let id = compressed_id.decompress().unwrap(); - let mut identity_in_coset = false; - for P in &id.coset4() { - if P.compress() == CompressedEdwardsY::identity() { - identity_in_coset = true; - } - } - assert!(identity_in_coset); - } - - #[test] - fn compress_id() { - let id = RistrettoPoint::identity(); - assert_eq!(id.compress(), CompressedRistretto::identity()); - } - - #[test] - fn basepoint_roundtrip() { - let bp_compressed_ristretto = constants::RISTRETTO_BASEPOINT_POINT.compress(); - let bp_recaf = bp_compressed_ristretto.decompress().unwrap().0; - // Check that bp_recaf differs from bp by a point of order 4 - let diff = &constants::RISTRETTO_BASEPOINT_POINT.0 - &bp_recaf; - let diff4 = diff.mul_by_pow_2(2); - assert_eq!(diff4.compress(), CompressedEdwardsY::identity()); - } - - #[test] - fn encodings_of_small_multiples_of_basepoint() { - // Table of encodings of i*basepoint - // Generated using ristretto.sage - let compressed = [ - CompressedRistretto([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]), - CompressedRistretto([226, 242, 174, 10, 106, 188, 78, 113, 168, 132, 169, 97, 197, 0, 81, 95, 88, 227, 11, 106, 165, 130, 221, 141, 182, 166, 89, 69, 224, 141, 45, 118]), - CompressedRistretto([106, 73, 50, 16, 247, 73, 156, 209, 127, 236, 181, 16, 174, 12, 234, 35, 161, 16, 232, 213, 185, 1, 248, 172, 173, 211, 9, 92, 115, 163, 185, 25]), - CompressedRistretto([148, 116, 31, 93, 93, 82, 117, 94, 206, 79, 35, 240, 68, 238, 39, 213, 209, 234, 30, 43, 209, 150, 180, 98, 22, 107, 22, 21, 42, 157, 2, 89]), - CompressedRistretto([218, 128, 134, 39, 115, 53, 139, 70, 111, 250, 223, 224, 179, 41, 58, 179, 217, 253, 83, 197, 234, 108, 149, 83, 88, 245, 104, 50, 45, 175, 106, 87]), - CompressedRistretto([232, 130, 177, 49, 1, 107, 82, 193, 211, 51, 112, 128, 24, 124, 247, 104, 66, 62, 252, 203, 181, 23, 187, 73, 90, 184, 18, 196, 22, 15, 244, 78]), - CompressedRistretto([246, 71, 70, 211, 201, 43, 19, 5, 14, 216, 216, 2, 54, 167, 240, 0, 124, 59, 63, 150, 47, 91, 167, 147, 209, 154, 96, 30, 187, 29, 244, 3]), - CompressedRistretto([68, 245, 53, 32, 146, 110, 200, 31, 189, 90, 56, 120, 69, 190, 183, 223, 133, 169, 106, 36, 236, 225, 135, 56, 189, 207, 166, 167, 130, 42, 23, 109]), - CompressedRistretto([144, 50, 147, 216, 242, 40, 126, 190, 16, 226, 55, 77, 193, 165, 62, 11, 200, 135, 229, 146, 105, 159, 2, 208, 119, 213, 38, 60, 221, 85, 96, 28]), - CompressedRistretto([2, 98, 42, 206, 143, 115, 3, 163, 28, 175, 198, 63, 143, 196, 143, 220, 22, 225, 200, 200, 210, 52, 178, 240, 214, 104, 82, 130, 169, 7, 96, 49]), - CompressedRistretto([32, 112, 111, 215, 136, 178, 114, 10, 30, 210, 165, 218, 212, 149, 43, 1, 244, 19, 188, 240, 231, 86, 77, 232, 205, 200, 22, 104, 158, 45, 185, 95]), - CompressedRistretto([188, 232, 63, 139, 165, 221, 47, 165, 114, 134, 76, 36, 186, 24, 16, 249, 82, 43, 198, 0, 74, 254, 149, 135, 122, 199, 50, 65, 202, 253, 171, 66]), - CompressedRistretto([228, 84, 158, 225, 107, 154, 160, 48, 153, 202, 32, 140, 103, 173, 175, 202, 250, 76, 63, 62, 78, 83, 3, 222, 96, 38, 227, 202, 143, 248, 68, 96]), - CompressedRistretto([170, 82, 224, 0, 223, 46, 22, 245, 95, 177, 3, 47, 195, 59, 196, 39, 66, 218, 214, 189, 90, 143, 192, 190, 1, 103, 67, 108, 89, 72, 80, 31]), - CompressedRistretto([70, 55, 107, 128, 244, 9, 178, 157, 194, 181, 246, 240, 197, 37, 145, 153, 8, 150, 229, 113, 111, 65, 71, 124, 211, 0, 133, 171, 127, 16, 48, 30]), - CompressedRistretto([224, 196, 24, 247, 200, 217, 196, 205, 215, 57, 91, 147, 234, 18, 79, 58, 217, 144, 33, 187, 104, 29, 252, 51, 2, 169, 217, 154, 46, 83, 230, 78]), - ]; - let mut bp = RistrettoPoint::identity(); - for i in 0..16 { - assert_eq!(bp.compress(), compressed[i]); - bp = &bp + &constants::RISTRETTO_BASEPOINT_POINT; - } - } - - #[test] - fn four_torsion_basepoint() { - let bp = constants::RISTRETTO_BASEPOINT_POINT; - let bp_coset = bp.coset4(); - for i in 0..4 { - assert_eq!(bp, RistrettoPoint(bp_coset[i])); - } - } - - #[test] - fn four_torsion_random() { - let mut rng = OsRng; - let B = &constants::RISTRETTO_BASEPOINT_TABLE; - let P = B * &Scalar::random(&mut rng); - let P_coset = P.coset4(); - for i in 0..4 { - assert_eq!(P, RistrettoPoint(P_coset[i])); - } - } - - #[test] - fn elligator_vs_ristretto_sage() { - // Test vectors extracted from ristretto.sage. - // - // Notice that all of the byte sequences have bit 255 set to 0; this is because - // ristretto.sage does not mask the high bit of a field element. When the high bit is set, - // the ristretto.sage elligator implementation gives different results, since it takes a - // different field element as input. - let bytes: [[u8;32]; 16] = [ - [184, 249, 135, 49, 253, 123, 89, 113, 67, 160, 6, 239, 7, 105, 211, 41, 192, 249, 185, 57, 9, 102, 70, 198, 15, 127, 7, 26, 160, 102, 134, 71], - [229, 14, 241, 227, 75, 9, 118, 60, 128, 153, 226, 21, 183, 217, 91, 136, 98, 0, 231, 156, 124, 77, 82, 139, 142, 134, 164, 169, 169, 62, 250, 52], - [115, 109, 36, 220, 180, 223, 99, 6, 204, 169, 19, 29, 169, 68, 84, 23, 21, 109, 189, 149, 127, 205, 91, 102, 172, 35, 112, 35, 134, 69, 186, 34], - [16, 49, 96, 107, 171, 199, 164, 9, 129, 16, 64, 62, 241, 63, 132, 173, 209, 160, 112, 215, 105, 50, 157, 81, 253, 105, 1, 154, 229, 25, 120, 83], - [156, 131, 161, 162, 236, 251, 5, 187, 167, 171, 17, 178, 148, 210, 90, 207, 86, 21, 79, 161, 167, 215, 234, 1, 136, 242, 182, 248, 38, 85, 79, 86], - [251, 177, 124, 54, 18, 101, 75, 235, 245, 186, 19, 46, 133, 157, 229, 64, 10, 136, 181, 185, 78, 144, 254, 167, 137, 49, 107, 10, 61, 10, 21, 25], - [232, 193, 20, 68, 240, 77, 186, 77, 183, 40, 44, 86, 150, 31, 198, 212, 76, 81, 3, 217, 197, 8, 126, 128, 126, 152, 164, 208, 153, 44, 189, 77], - [173, 229, 149, 177, 37, 230, 30, 69, 61, 56, 172, 190, 219, 115, 167, 194, 71, 134, 59, 75, 28, 244, 118, 26, 162, 97, 64, 16, 15, 189, 30, 64], - [106, 71, 61, 107, 250, 117, 42, 151, 91, 202, 212, 100, 52, 188, 190, 21, 125, 218, 31, 18, 253, 241, 160, 133, 57, 242, 3, 164, 189, 68, 111, 75], - [112, 204, 182, 90, 220, 198, 120, 73, 173, 107, 193, 17, 227, 40, 162, 36, 150, 141, 235, 55, 172, 183, 12, 39, 194, 136, 43, 153, 244, 118, 91, 89], - [111, 24, 203, 123, 254, 189, 11, 162, 51, 196, 163, 136, 204, 143, 10, 222, 33, 112, 81, 205, 34, 35, 8, 66, 90, 6, 164, 58, 170, 177, 34, 25], - [225, 183, 30, 52, 236, 82, 6, 183, 109, 25, 227, 181, 25, 82, 41, 193, 80, 77, 161, 80, 242, 203, 79, 204, 136, 245, 131, 110, 237, 106, 3, 58], - [207, 246, 38, 56, 30, 86, 176, 90, 27, 200, 61, 42, 221, 27, 56, 210, 79, 178, 189, 120, 68, 193, 120, 167, 77, 185, 53, 197, 124, 128, 191, 126], - [1, 136, 215, 80, 240, 46, 63, 147, 16, 244, 230, 207, 82, 189, 74, 50, 106, 169, 138, 86, 30, 131, 214, 202, 166, 125, 251, 228, 98, 24, 36, 21], - [210, 207, 228, 56, 155, 116, 207, 54, 84, 195, 251, 215, 249, 199, 116, 75, 109, 239, 196, 251, 194, 246, 252, 228, 70, 146, 156, 35, 25, 39, 241, 4], - [34, 116, 123, 9, 8, 40, 93, 189, 9, 103, 57, 103, 66, 227, 3, 2, 157, 107, 134, 219, 202, 74, 230, 154, 78, 107, 219, 195, 214, 14, 84, 80], - ]; - let encoded_images: [CompressedRistretto; 16] = [ - CompressedRistretto([176, 157, 237, 97, 66, 29, 140, 166, 168, 94, 26, 157, 212, 216, 229, 160, 195, 246, 232, 239, 169, 112, 63, 193, 64, 32, 152, 69, 11, 190, 246, 86]), - CompressedRistretto([234, 141, 77, 203, 181, 225, 250, 74, 171, 62, 15, 118, 78, 212, 150, 19, 131, 14, 188, 238, 194, 244, 141, 138, 166, 162, 83, 122, 228, 201, 19, 26]), - CompressedRistretto([232, 231, 51, 92, 5, 168, 80, 36, 173, 179, 104, 68, 186, 149, 68, 40, 140, 170, 27, 103, 99, 140, 21, 242, 43, 62, 250, 134, 208, 255, 61, 89]), - CompressedRistretto([208, 120, 140, 129, 177, 179, 237, 159, 252, 160, 28, 13, 206, 5, 211, 241, 192, 218, 1, 97, 130, 241, 20, 169, 119, 46, 246, 29, 79, 80, 77, 84]), - CompressedRistretto([202, 11, 236, 145, 58, 12, 181, 157, 209, 6, 213, 88, 75, 147, 11, 119, 191, 139, 47, 142, 33, 36, 153, 193, 223, 183, 178, 8, 205, 120, 248, 110]), - CompressedRistretto([26, 66, 231, 67, 203, 175, 116, 130, 32, 136, 62, 253, 215, 46, 5, 214, 166, 248, 108, 237, 216, 71, 244, 173, 72, 133, 82, 6, 143, 240, 104, 41]), - CompressedRistretto([40, 157, 102, 96, 201, 223, 200, 197, 150, 181, 106, 83, 103, 126, 143, 33, 145, 230, 78, 6, 171, 146, 210, 143, 112, 5, 245, 23, 183, 138, 18, 120]), - CompressedRistretto([220, 37, 27, 203, 239, 196, 176, 131, 37, 66, 188, 243, 185, 250, 113, 23, 167, 211, 154, 243, 168, 215, 54, 171, 159, 36, 195, 81, 13, 150, 43, 43]), - CompressedRistretto([232, 121, 176, 222, 183, 196, 159, 90, 238, 193, 105, 52, 101, 167, 244, 170, 121, 114, 196, 6, 67, 152, 80, 185, 221, 7, 83, 105, 176, 208, 224, 121]), - CompressedRistretto([226, 181, 183, 52, 241, 163, 61, 179, 221, 207, 220, 73, 245, 242, 25, 236, 67, 84, 179, 222, 167, 62, 167, 182, 32, 9, 92, 30, 165, 127, 204, 68]), - CompressedRistretto([226, 119, 16, 242, 200, 139, 240, 87, 11, 222, 92, 146, 156, 243, 46, 119, 65, 59, 1, 248, 92, 183, 50, 175, 87, 40, 206, 53, 208, 220, 148, 13]), - CompressedRistretto([70, 240, 79, 112, 54, 157, 228, 146, 74, 122, 216, 88, 232, 62, 158, 13, 14, 146, 115, 117, 176, 222, 90, 225, 244, 23, 94, 190, 150, 7, 136, 96]), - CompressedRistretto([22, 71, 241, 103, 45, 193, 195, 144, 183, 101, 154, 50, 39, 68, 49, 110, 51, 44, 62, 0, 229, 113, 72, 81, 168, 29, 73, 106, 102, 40, 132, 24]), - CompressedRistretto([196, 133, 107, 11, 130, 105, 74, 33, 204, 171, 133, 221, 174, 193, 241, 36, 38, 179, 196, 107, 219, 185, 181, 253, 228, 47, 155, 42, 231, 73, 41, 78]), - CompressedRistretto([58, 255, 225, 197, 115, 208, 160, 143, 39, 197, 82, 69, 143, 235, 92, 170, 74, 40, 57, 11, 171, 227, 26, 185, 217, 207, 90, 185, 197, 190, 35, 60]), - CompressedRistretto([88, 43, 92, 118, 223, 136, 105, 145, 238, 186, 115, 8, 214, 112, 153, 253, 38, 108, 205, 230, 157, 130, 11, 66, 101, 85, 253, 110, 110, 14, 148, 112]), - ]; - for i in 0..16 { - let r_0 = FieldElement::from_bytes(&bytes[i]); - let Q = RistrettoPoint::elligator_ristretto_flavor(&r_0); - assert_eq!(Q.compress(), encoded_images[i]); - } - } - - #[test] - fn random_roundtrip() { - let mut rng = OsRng; - let B = &constants::RISTRETTO_BASEPOINT_TABLE; - for _ in 0..100 { - let P = B * &Scalar::random(&mut rng); - let compressed_P = P.compress(); - let Q = compressed_P.decompress().unwrap(); - assert_eq!(P, Q); - } - } - - #[test] - fn double_and_compress_1024_random_points() { - let mut rng = OsRng; - - let points: Vec = - (0..1024).map(|_| RistrettoPoint::random(&mut rng)).collect(); - - let compressed = RistrettoPoint::double_and_compress_batch(&points); - - for (P, P2_compressed) in points.iter().zip(compressed.iter()) { - assert_eq!(*P2_compressed, (P + P).compress()); - } - } - - #[test] - fn vartime_precomputed_vs_nonprecomputed_multiscalar() { - let mut rng = rand::thread_rng(); - - let B = &::constants::RISTRETTO_BASEPOINT_TABLE; - - let static_scalars = (0..128) - .map(|_| Scalar::random(&mut rng)) - .collect::>(); - - let dynamic_scalars = (0..128) - .map(|_| Scalar::random(&mut rng)) - .collect::>(); - - let check_scalar: Scalar = static_scalars - .iter() - .chain(dynamic_scalars.iter()) - .map(|s| s * s) - .sum(); - - let static_points = static_scalars.iter().map(|s| s * B).collect::>(); - let dynamic_points = dynamic_scalars.iter().map(|s| s * B).collect::>(); - - let precomputation = VartimeRistrettoPrecomputation::new(static_points.iter()); - - let P = precomputation.vartime_mixed_multiscalar_mul( - &static_scalars, - &dynamic_scalars, - &dynamic_points, - ); - - use traits::VartimeMultiscalarMul; - let Q = RistrettoPoint::vartime_multiscalar_mul( - static_scalars.iter().chain(dynamic_scalars.iter()), - static_points.iter().chain(dynamic_points.iter()), - ); - - let R = &check_scalar * B; - - assert_eq!(P.compress(), R.compress()); - assert_eq!(Q.compress(), R.compress()); - } -} diff --git a/net/gurk-rs/files/vendor/curve25519-dalek-2.0.0/src/scalar.rs b/net/gurk-rs/files/vendor/curve25519-dalek-2.0.0/src/scalar.rs deleted file mode 100644 index d365d25..0000000 --- a/net/gurk-rs/files/vendor/curve25519-dalek-2.0.0/src/scalar.rs +++ /dev/null @@ -1,1739 +0,0 @@ -// -*- mode: rust; -*- -// -// This file is part of curve25519-dalek. -// Copyright (c) 2016-2019 Isis Lovecruft, Henry de Valence -// Portions Copyright 2017 Brian Smith -// See LICENSE for licensing information. -// -// Authors: -// - Isis Agora Lovecruft -// - Henry de Valence -// - Brian Smith - -//! Arithmetic on scalars (integers mod the group order). -//! -//! Both the Ristretto group and the Ed25519 basepoint have prime order -//! \\( \ell = 2\^{252} + 27742317777372353535851937790883648493 \\). -//! -//! This code is intended to be useful with both the Ristretto group -//! (where everything is done modulo \\( \ell \\)), and the X/Ed25519 -//! setting, which mandates specific bit-twiddles that are not -//! well-defined modulo \\( \ell \\). -//! -//! All arithmetic on `Scalars` is done modulo \\( \ell \\). -//! -//! # Constructing a scalar -//! -//! To create a [`Scalar`](struct.Scalar.html) from a supposedly canonical encoding, use -//! [`Scalar::from_canonical_bytes`](struct.Scalar.html#method.from_canonical_bytes). -//! -//! This function does input validation, ensuring that the input bytes -//! are the canonical encoding of a `Scalar`. -//! If they are, we'll get -//! `Some(Scalar)` in return: -//! -//! ``` -//! use curve25519_dalek::scalar::Scalar; -//! -//! let one_as_bytes: [u8; 32] = Scalar::one().to_bytes(); -//! let a: Option = Scalar::from_canonical_bytes(one_as_bytes); -//! -//! assert!(a.is_some()); -//! ``` -//! -//! However, if we give it bytes representing a scalar larger than \\( \ell \\) -//! (in this case, \\( \ell + 2 \\)), we'll get `None` back: -//! -//! ``` -//! use curve25519_dalek::scalar::Scalar; -//! -//! let l_plus_two_bytes: [u8; 32] = [ -//! 0xef, 0xd3, 0xf5, 0x5c, 0x1a, 0x63, 0x12, 0x58, -//! 0xd6, 0x9c, 0xf7, 0xa2, 0xde, 0xf9, 0xde, 0x14, -//! 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -//! 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, -//! ]; -//! let a: Option = Scalar::from_canonical_bytes(l_plus_two_bytes); -//! -//! assert!(a.is_none()); -//! ``` -//! -//! Another way to create a `Scalar` is by reducing a \\(256\\)-bit integer mod -//! \\( \ell \\), for which one may use the -//! [`Scalar::from_bytes_mod_order`](struct.Scalar.html#method.from_bytes_mod_order) -//! method. In the case of the second example above, this would reduce the -//! resultant scalar \\( \mod \ell \\), producing \\( 2 \\): -//! -//! ``` -//! use curve25519_dalek::scalar::Scalar; -//! -//! let l_plus_two_bytes: [u8; 32] = [ -//! 0xef, 0xd3, 0xf5, 0x5c, 0x1a, 0x63, 0x12, 0x58, -//! 0xd6, 0x9c, 0xf7, 0xa2, 0xde, 0xf9, 0xde, 0x14, -//! 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -//! 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, -//! ]; -//! let a: Scalar = Scalar::from_bytes_mod_order(l_plus_two_bytes); -//! -//! let two: Scalar = Scalar::one() + Scalar::one(); -//! -//! assert!(a == two); -//! ``` -//! -//! There is also a constructor that reduces a \\(512\\)-bit integer, -//! [`Scalar::from_bytes_mod_order_wide`](struct.Scalar.html#method.from_bytes_mod_order_wide). -//! -//! To construct a `Scalar` as the hash of some input data, use -//! [`Scalar::hash_from_bytes`](struct.Scalar.html#method.hash_from_bytes), -//! which takes a buffer, or -//! [`Scalar::from_hash`](struct.Scalar.html#method.from_hash), -//! which allows an IUF API. -//! -//! ``` -//! # extern crate curve25519_dalek; -//! # extern crate sha2; -//! # -//! # fn main() { -//! use sha2::{Digest, Sha512}; -//! use curve25519_dalek::scalar::Scalar; -//! -//! // Hashing a single byte slice -//! let a = Scalar::hash_from_bytes::(b"Abolish ICE"); -//! -//! // Streaming data into a hash object -//! let mut hasher = Sha512::default(); -//! hasher.input(b"Abolish "); -//! hasher.input(b"ICE"); -//! let a2 = Scalar::from_hash(hasher); -//! -//! assert_eq!(a, a2); -//! # } -//! ``` -//! -//! Finally, to create a `Scalar` with a specific bit-pattern -//! (e.g., for compatibility with X/Ed25519 -//! ["clamping"](https://github.com/isislovecruft/ed25519-dalek/blob/f790bd2ce/src/ed25519.rs#L349)), -//! use [`Scalar::from_bits`](struct.Scalar.html#method.from_bits). This -//! constructs a scalar with exactly the bit pattern given, without any -//! assurances as to reduction modulo the group order: -//! -//! ``` -//! use curve25519_dalek::scalar::Scalar; -//! -//! let l_plus_two_bytes: [u8; 32] = [ -//! 0xef, 0xd3, 0xf5, 0x5c, 0x1a, 0x63, 0x12, 0x58, -//! 0xd6, 0x9c, 0xf7, 0xa2, 0xde, 0xf9, 0xde, 0x14, -//! 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -//! 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, -//! ]; -//! let a: Scalar = Scalar::from_bits(l_plus_two_bytes); -//! -//! let two: Scalar = Scalar::one() + Scalar::one(); -//! -//! assert!(a != two); // the scalar is not reduced (mod l)… -//! assert!(! a.is_canonical()); // …and therefore is not canonical. -//! assert!(a.reduce() == two); // if we were to reduce it manually, it would be. -//! ``` -//! -//! The resulting `Scalar` has exactly the specified bit pattern, -//! **except for the highest bit, which will be set to 0**. - -use core::borrow::Borrow; -use core::cmp::{Eq, PartialEq}; -use core::fmt::Debug; -use core::iter::{Product, Sum}; -use core::ops::Index; -use core::ops::Neg; -use core::ops::{Add, AddAssign}; -use core::ops::{Mul, MulAssign}; -use core::ops::{Sub, SubAssign}; - -#[allow(unused_imports)] -use prelude::*; - -use rand_core::{CryptoRng, RngCore}; - -use digest::generic_array::typenum::U64; -use digest::Digest; - -use subtle::Choice; -use subtle::ConditionallySelectable; -use subtle::ConstantTimeEq; - -use zeroize::Zeroize; - -use backend; -use constants; - -/// An `UnpackedScalar` represents an element of the field GF(l), optimized for speed. -/// -/// This is a type alias for one of the scalar types in the `backend` -/// module. -#[cfg(feature = "u64_backend")] -type UnpackedScalar = backend::serial::u64::scalar::Scalar52; - -/// An `UnpackedScalar` represents an element of the field GF(l), optimized for speed. -/// -/// This is a type alias for one of the scalar types in the `backend` -/// module. -#[cfg(feature = "u32_backend")] -type UnpackedScalar = backend::serial::u32::scalar::Scalar29; - - -/// The `Scalar` struct holds an integer \\(s < 2\^{255} \\) which -/// represents an element of \\(\mathbb Z / \ell\\). -#[derive(Copy, Clone)] -pub struct Scalar { - /// `bytes` is a little-endian byte encoding of an integer representing a scalar modulo the - /// group order. - /// - /// # Invariant - /// - /// The integer representing this scalar must be bounded above by \\(2\^{255}\\), or - /// equivalently the high bit of `bytes[31]` must be zero. - /// - /// This ensures that there is room for a carry bit when computing a NAF representation. - // - // XXX This is pub(crate) so we can write literal constants. If const fns were stable, we could - // make the Scalar constructors const fns and use those instead. - pub(crate) bytes: [u8; 32], -} - -impl Scalar { - /// Construct a `Scalar` by reducing a 256-bit little-endian integer - /// modulo the group order \\( \ell \\). - pub fn from_bytes_mod_order(bytes: [u8; 32]) -> Scalar { - // Temporarily allow s_unreduced.bytes > 2^255 ... - let s_unreduced = Scalar{bytes}; - - // Then reduce mod the group order and return the reduced representative. - let s = s_unreduced.reduce(); - debug_assert_eq!(0u8, s[31] >> 7); - - s - } - - /// Construct a `Scalar` by reducing a 512-bit little-endian integer - /// modulo the group order \\( \ell \\). - pub fn from_bytes_mod_order_wide(input: &[u8; 64]) -> Scalar { - UnpackedScalar::from_bytes_wide(input).pack() - } - - /// Attempt to construct a `Scalar` from a canonical byte representation. - /// - /// # Return - /// - /// - `Some(s)`, where `s` is the `Scalar` corresponding to `bytes`, - /// if `bytes` is a canonical byte representation; - /// - `None` if `bytes` is not a canonical byte representation. - pub fn from_canonical_bytes(bytes: [u8; 32]) -> Option { - // Check that the high bit is not set - if (bytes[31] >> 7) != 0u8 { return None; } - let candidate = Scalar::from_bits(bytes); - - if candidate.is_canonical() { - Some(candidate) - } else { - None - } - } - - /// Construct a `Scalar` from the low 255 bits of a 256-bit integer. - /// - /// This function is intended for applications like X25519 which - /// require specific bit-patterns when performing scalar - /// multiplication. - pub fn from_bits(bytes: [u8; 32]) -> Scalar { - let mut s = Scalar{bytes}; - // Ensure that s < 2^255 by masking the high bit - s.bytes[31] &= 0b0111_1111; - - s - } -} - -impl Debug for Scalar { - fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { - write!(f, "Scalar{{\n\tbytes: {:?},\n}}", &self.bytes) - } -} - -impl Eq for Scalar {} -impl PartialEq for Scalar { - fn eq(&self, other: &Self) -> bool { - self.ct_eq(other).unwrap_u8() == 1u8 - } -} - -impl ConstantTimeEq for Scalar { - fn ct_eq(&self, other: &Self) -> Choice { - self.bytes.ct_eq(&other.bytes) - } -} - -impl Index for Scalar { - type Output = u8; - - /// Index the bytes of the representative for this `Scalar`. Mutation is not permitted. - fn index(&self, _index: usize) -> &u8 { - &(self.bytes[_index]) - } -} - -impl<'b> MulAssign<&'b Scalar> for Scalar { - fn mul_assign(&mut self, _rhs: &'b Scalar) { - *self = UnpackedScalar::mul(&self.unpack(), &_rhs.unpack()).pack(); - } -} - -define_mul_assign_variants!(LHS = Scalar, RHS = Scalar); - -impl<'a, 'b> Mul<&'b Scalar> for &'a Scalar { - type Output = Scalar; - fn mul(self, _rhs: &'b Scalar) -> Scalar { - UnpackedScalar::mul(&self.unpack(), &_rhs.unpack()).pack() - } -} - -define_mul_variants!(LHS = Scalar, RHS = Scalar, Output = Scalar); - -impl<'b> AddAssign<&'b Scalar> for Scalar { - fn add_assign(&mut self, _rhs: &'b Scalar) { - *self = *self + _rhs; - } -} - -define_add_assign_variants!(LHS = Scalar, RHS = Scalar); - -impl<'a, 'b> Add<&'b Scalar> for &'a Scalar { - type Output = Scalar; - #[allow(non_snake_case)] - fn add(self, _rhs: &'b Scalar) -> Scalar { - // The UnpackedScalar::add function produces reduced outputs - // if the inputs are reduced. However, these inputs may not - // be reduced -- they might come from Scalar::from_bits. So - // after computing the sum, we explicitly reduce it mod l - // before repacking. - let sum = UnpackedScalar::add(&self.unpack(), &_rhs.unpack()); - let sum_R = UnpackedScalar::mul_internal(&sum, &constants::R); - let sum_mod_l = UnpackedScalar::montgomery_reduce(&sum_R); - sum_mod_l.pack() - } -} - -define_add_variants!(LHS = Scalar, RHS = Scalar, Output = Scalar); - -impl<'b> SubAssign<&'b Scalar> for Scalar { - fn sub_assign(&mut self, _rhs: &'b Scalar) { - *self = *self - _rhs; - } -} - -define_sub_assign_variants!(LHS = Scalar, RHS = Scalar); - -impl<'a, 'b> Sub<&'b Scalar> for &'a Scalar { - type Output = Scalar; - #[allow(non_snake_case)] - fn sub(self, rhs: &'b Scalar) -> Scalar { - // The UnpackedScalar::sub function requires reduced inputs - // and produces reduced output. However, these inputs may not - // be reduced -- they might come from Scalar::from_bits. So - // we explicitly reduce the inputs. - let self_R = UnpackedScalar::mul_internal(&self.unpack(), &constants::R); - let self_mod_l = UnpackedScalar::montgomery_reduce(&self_R); - let rhs_R = UnpackedScalar::mul_internal(&rhs.unpack(), &constants::R); - let rhs_mod_l = UnpackedScalar::montgomery_reduce(&rhs_R); - - UnpackedScalar::sub(&self_mod_l, &rhs_mod_l).pack() - } -} - -define_sub_variants!(LHS = Scalar, RHS = Scalar, Output = Scalar); - -impl<'a> Neg for &'a Scalar { - type Output = Scalar; - #[allow(non_snake_case)] - fn neg(self) -> Scalar { - let self_R = UnpackedScalar::mul_internal(&self.unpack(), &constants::R); - let self_mod_l = UnpackedScalar::montgomery_reduce(&self_R); - UnpackedScalar::sub(&UnpackedScalar::zero(), &self_mod_l).pack() - } -} - -impl<'a> Neg for Scalar { - type Output = Scalar; - fn neg(self) -> Scalar { - -&self - } -} - -impl ConditionallySelectable for Scalar { - fn conditional_select(a: &Self, b: &Self, choice: Choice) -> Self { - let mut bytes = [0u8; 32]; - for i in 0..32 { - bytes[i] = u8::conditional_select(&a.bytes[i], &b.bytes[i], choice); - } - Scalar { bytes } - } -} - -#[cfg(feature = "serde")] -use serde::{self, Serialize, Deserialize, Serializer, Deserializer}; -#[cfg(feature = "serde")] -use serde::de::Visitor; - -#[cfg(feature = "serde")] -impl Serialize for Scalar { - fn serialize(&self, serializer: S) -> Result - where S: Serializer - { - use serde::ser::SerializeTuple; - let mut tup = serializer.serialize_tuple(32)?; - for byte in self.as_bytes().iter() { - tup.serialize_element(byte)?; - } - tup.end() - } -} - -#[cfg(feature = "serde")] -impl<'de> Deserialize<'de> for Scalar { - fn deserialize(deserializer: D) -> Result - where D: Deserializer<'de> - { - struct ScalarVisitor; - - impl<'de> Visitor<'de> for ScalarVisitor { - type Value = Scalar; - - fn expecting(&self, formatter: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { - formatter.write_str("a valid point in Edwards y + sign format") - } - - fn visit_seq(self, mut seq: A) -> Result - where A: serde::de::SeqAccess<'de> - { - let mut bytes = [0u8; 32]; - for i in 0..32 { - bytes[i] = seq.next_element()? - .ok_or(serde::de::Error::invalid_length(i, &"expected 32 bytes"))?; - } - Scalar::from_canonical_bytes(bytes) - .ok_or(serde::de::Error::custom( - &"scalar was not canonically encoded" - )) - } - } - - deserializer.deserialize_tuple(32, ScalarVisitor) - } -} - -impl Product for Scalar -where - T: Borrow -{ - fn product(iter: I) -> Self - where - I: Iterator - { - iter.fold(Scalar::one(), |acc, item| acc * item.borrow()) - } -} - -impl Sum for Scalar -where - T: Borrow -{ - fn sum(iter: I) -> Self - where - I: Iterator - { - iter.fold(Scalar::zero(), |acc, item| acc + item.borrow()) - } -} - -impl Default for Scalar { - fn default() -> Scalar { - Scalar::zero() - } -} - -impl From for Scalar { - fn from(x: u8) -> Scalar { - let mut s_bytes = [0u8; 32]; - s_bytes[0] = x; - Scalar{ bytes: s_bytes } - } -} - -impl From for Scalar { - fn from(x: u16) -> Scalar { - use byteorder::{ByteOrder, LittleEndian}; - let mut s_bytes = [0u8; 32]; - LittleEndian::write_u16(&mut s_bytes, x); - Scalar{ bytes: s_bytes } - } -} - -impl From for Scalar { - fn from(x: u32) -> Scalar { - use byteorder::{ByteOrder, LittleEndian}; - let mut s_bytes = [0u8; 32]; - LittleEndian::write_u32(&mut s_bytes, x); - Scalar{ bytes: s_bytes } - } -} - -impl From for Scalar { - /// Construct a scalar from the given `u64`. - /// - /// # Inputs - /// - /// An `u64` to convert to a `Scalar`. - /// - /// # Returns - /// - /// A `Scalar` corresponding to the input `u64`. - /// - /// # Example - /// - /// ``` - /// use curve25519_dalek::scalar::Scalar; - /// - /// let fourtytwo = Scalar::from(42u64); - /// let six = Scalar::from(6u64); - /// let seven = Scalar::from(7u64); - /// - /// assert!(fourtytwo == six * seven); - /// ``` - fn from(x: u64) -> Scalar { - use byteorder::{ByteOrder, LittleEndian}; - let mut s_bytes = [0u8; 32]; - LittleEndian::write_u64(&mut s_bytes, x); - Scalar{ bytes: s_bytes } - } -} - -impl From for Scalar { - fn from(x: u128) -> Scalar { - use byteorder::{ByteOrder, LittleEndian}; - let mut s_bytes = [0u8; 32]; - LittleEndian::write_u128(&mut s_bytes, x); - Scalar{ bytes: s_bytes } - } -} - -impl Zeroize for Scalar { - fn zeroize(&mut self) { - self.bytes.zeroize(); - } -} - -impl Scalar { - /// Return a `Scalar` chosen uniformly at random using a user-provided RNG. - /// - /// # Inputs - /// - /// * `rng`: any RNG which implements the `RngCore + CryptoRng` interface. - /// - /// # Returns - /// - /// A random scalar within ℤ/lℤ. - /// - /// # Example - /// - /// ``` - /// extern crate rand_core; - /// # extern crate curve25519_dalek; - /// # - /// # fn main() { - /// use curve25519_dalek::scalar::Scalar; - /// - /// use rand_core::OsRng; - /// - /// let mut csprng = OsRng; - /// let a: Scalar = Scalar::random(&mut csprng); - /// # } - pub fn random(rng: &mut R) -> Self { - let mut scalar_bytes = [0u8; 64]; - rng.fill_bytes(&mut scalar_bytes); - Scalar::from_bytes_mod_order_wide(&scalar_bytes) - } - - /// Hash a slice of bytes into a scalar. - /// - /// Takes a type parameter `D`, which is any `Digest` producing 64 - /// bytes (512 bits) of output. - /// - /// Convenience wrapper around `from_hash`. - /// - /// # Example - /// - /// ``` - /// # extern crate curve25519_dalek; - /// # use curve25519_dalek::scalar::Scalar; - /// extern crate sha2; - /// - /// use sha2::Sha512; - /// - /// # // Need fn main() here in comment so the doctest compiles - /// # // See https://doc.rust-lang.org/book/documentation.html#documentation-as-tests - /// # fn main() { - /// let msg = "To really appreciate architecture, you may even need to commit a murder"; - /// let s = Scalar::hash_from_bytes::(msg.as_bytes()); - /// # } - /// ``` - pub fn hash_from_bytes(input: &[u8]) -> Scalar - where D: Digest + Default - { - let mut hash = D::default(); - hash.input(input); - Scalar::from_hash(hash) - } - - /// Construct a scalar from an existing `Digest` instance. - /// - /// Use this instead of `hash_from_bytes` if it is more convenient - /// to stream data into the `Digest` than to pass a single byte - /// slice. - /// - /// # Example - /// - /// ``` - /// # extern crate curve25519_dalek; - /// # use curve25519_dalek::scalar::Scalar; - /// extern crate sha2; - /// - /// use sha2::Digest; - /// use sha2::Sha512; - /// - /// # fn main() { - /// let mut h = Sha512::new() - /// .chain("To really appreciate architecture, you may even need to commit a murder.") - /// .chain("While the programs used for The Manhattan Transcripts are of the most extreme") - /// .chain("nature, they also parallel the most common formula plot: the archetype of") - /// .chain("murder. Other phantasms were occasionally used to underline the fact that") - /// .chain("perhaps all architecture, rather than being about functional standards, is") - /// .chain("about love and death."); - /// - /// let s = Scalar::from_hash(h); - /// - /// println!("{:?}", s.to_bytes()); - /// assert!(s == Scalar::from_bits([ 21, 88, 208, 252, 63, 122, 210, 152, - /// 154, 38, 15, 23, 16, 167, 80, 150, - /// 192, 221, 77, 226, 62, 25, 224, 148, - /// 239, 48, 176, 10, 185, 69, 168, 11, ])); - /// # } - /// ``` - pub fn from_hash(hash: D) -> Scalar - where D: Digest - { - let mut output = [0u8; 64]; - output.copy_from_slice(hash.result().as_slice()); - Scalar::from_bytes_mod_order_wide(&output) - } - - /// Convert this `Scalar` to its underlying sequence of bytes. - /// - /// # Example - /// - /// ``` - /// use curve25519_dalek::scalar::Scalar; - /// - /// let s: Scalar = Scalar::zero(); - /// - /// assert!(s.to_bytes() == [0u8; 32]); - /// ``` - pub fn to_bytes(&self) -> [u8; 32] { - self.bytes - } - - /// View the little-endian byte encoding of the integer representing this Scalar. - /// - /// # Example - /// - /// ``` - /// use curve25519_dalek::scalar::Scalar; - /// - /// let s: Scalar = Scalar::zero(); - /// - /// assert!(s.as_bytes() == &[0u8; 32]); - /// ``` - pub fn as_bytes(&self) -> &[u8; 32] { - &self.bytes - } - - /// Construct the scalar \\( 0 \\). - pub fn zero() -> Self { - Scalar { bytes: [0u8; 32]} - } - - /// Construct the scalar \\( 1 \\). - pub fn one() -> Self { - Scalar { - bytes: [ - 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - ], - } - } - - /// Given a nonzero `Scalar`, compute its multiplicative inverse. - /// - /// # Warning - /// - /// `self` **MUST** be nonzero. If you cannot - /// *prove* that this is the case, you **SHOULD NOT USE THIS - /// FUNCTION**. - /// - /// # Returns - /// - /// The multiplicative inverse of the this `Scalar`. - /// - /// # Example - /// - /// ``` - /// use curve25519_dalek::scalar::Scalar; - /// - /// // x = 2238329342913194256032495932344128051776374960164957527413114840482143558222 - /// let X: Scalar = Scalar::from_bytes_mod_order([ - /// 0x4e, 0x5a, 0xb4, 0x34, 0x5d, 0x47, 0x08, 0x84, - /// 0x59, 0x13, 0xb4, 0x64, 0x1b, 0xc2, 0x7d, 0x52, - /// 0x52, 0xa5, 0x85, 0x10, 0x1b, 0xcc, 0x42, 0x44, - /// 0xd4, 0x49, 0xf4, 0xa8, 0x79, 0xd9, 0xf2, 0x04, - /// ]); - /// // 1/x = 6859937278830797291664592131120606308688036382723378951768035303146619657244 - /// let XINV: Scalar = Scalar::from_bytes_mod_order([ - /// 0x1c, 0xdc, 0x17, 0xfc, 0xe0, 0xe9, 0xa5, 0xbb, - /// 0xd9, 0x24, 0x7e, 0x56, 0xbb, 0x01, 0x63, 0x47, - /// 0xbb, 0xba, 0x31, 0xed, 0xd5, 0xa9, 0xbb, 0x96, - /// 0xd5, 0x0b, 0xcd, 0x7a, 0x3f, 0x96, 0x2a, 0x0f, - /// ]); - /// - /// let inv_X: Scalar = X.invert(); - /// assert!(XINV == inv_X); - /// let should_be_one: Scalar = &inv_X * &X; - /// assert!(should_be_one == Scalar::one()); - /// ``` - pub fn invert(&self) -> Scalar { - self.unpack().invert().pack() - } - - /// Given a slice of nonzero (possibly secret) `Scalar`s, - /// compute their inverses in a batch. - /// - /// # Return - /// - /// Each element of `inputs` is replaced by its inverse. - /// - /// The product of all inverses is returned. - /// - /// # Warning - /// - /// All input `Scalars` **MUST** be nonzero. If you cannot - /// *prove* that this is the case, you **SHOULD NOT USE THIS - /// FUNCTION**. - /// - /// # Example - /// - /// ``` - /// # extern crate curve25519_dalek; - /// # use curve25519_dalek::scalar::Scalar; - /// # fn main() { - /// let mut scalars = [ - /// Scalar::from(3u64), - /// Scalar::from(5u64), - /// Scalar::from(7u64), - /// Scalar::from(11u64), - /// ]; - /// - /// let allinv = Scalar::batch_invert(&mut scalars); - /// - /// assert_eq!(allinv, Scalar::from(3*5*7*11u64).invert()); - /// assert_eq!(scalars[0], Scalar::from(3u64).invert()); - /// assert_eq!(scalars[1], Scalar::from(5u64).invert()); - /// assert_eq!(scalars[2], Scalar::from(7u64).invert()); - /// assert_eq!(scalars[3], Scalar::from(11u64).invert()); - /// # } - /// ``` - #[cfg(feature = "alloc")] - pub fn batch_invert(inputs: &mut [Scalar]) -> Scalar { - // This code is essentially identical to the FieldElement - // implementation, and is documented there. Unfortunately, - // it's not easy to write it generically, since here we want - // to use `UnpackedScalar`s internally, and `Scalar`s - // externally, but there's no corresponding distinction for - // field elements. - - use zeroize::Zeroizing; - - let n = inputs.len(); - let one: UnpackedScalar = Scalar::one().unpack().to_montgomery(); - - // Place scratch storage in a Zeroizing wrapper to wipe it when - // we pass out of scope. - let scratch_vec = vec![one; n]; - let mut scratch = Zeroizing::new(scratch_vec); - - // Keep an accumulator of all of the previous products - let mut acc = Scalar::one().unpack().to_montgomery(); - - // Pass through the input vector, recording the previous - // products in the scratch space - for (input, scratch) in inputs.iter_mut().zip(scratch.iter_mut()) { - *scratch = acc; - - // Avoid unnecessary Montgomery multiplication in second pass by - // keeping inputs in Montgomery form - let tmp = input.unpack().to_montgomery(); - *input = tmp.pack(); - acc = UnpackedScalar::montgomery_mul(&acc, &tmp); - } - - // acc is nonzero iff all inputs are nonzero - debug_assert!(acc.pack() != Scalar::zero()); - - // Compute the inverse of all products - acc = acc.montgomery_invert().from_montgomery(); - - // We need to return the product of all inverses later - let ret = acc.pack(); - - // Pass through the vector backwards to compute the inverses - // in place - for (input, scratch) in inputs.iter_mut().rev().zip(scratch.iter().rev()) { - let tmp = UnpackedScalar::montgomery_mul(&acc, &input.unpack()); - *input = UnpackedScalar::montgomery_mul(&acc, &scratch).pack(); - acc = tmp; - } - - ret - } - - /// Get the bits of the scalar. - pub(crate) fn bits(&self) -> [i8; 256] { - let mut bits = [0i8; 256]; - for i in 0..256 { - // As i runs from 0..256, the bottom 3 bits index the bit, - // while the upper bits index the byte. - bits[i] = ((self.bytes[i>>3] >> (i&7)) & 1u8) as i8; - } - bits - } - - /// Compute a width-\\(w\\) "Non-Adjacent Form" of this scalar. - /// - /// A width-\\(w\\) NAF of a positive integer \\(k\\) is an expression - /// $$ - /// k = \sum_{i=0}\^m n\_i 2\^i, - /// $$ - /// where each nonzero - /// coefficient \\(n\_i\\) is odd and bounded by \\(|n\_i| < 2\^{w-1}\\), - /// \\(n\_{m-1}\\) is nonzero, and at most one of any \\(w\\) consecutive - /// coefficients is nonzero. (Hankerson, Menezes, Vanstone; def 3.32). - /// - /// The length of the NAF is at most one more than the length of - /// the binary representation of \\(k\\). This is why the - /// `Scalar` type maintains an invariant that the top bit is - /// \\(0\\), so that the NAF of a scalar has at most 256 digits. - /// - /// Intuitively, this is like a binary expansion, except that we - /// allow some coefficients to grow in magnitude up to - /// \\(2\^{w-1}\\) so that the nonzero coefficients are as sparse - /// as possible. - /// - /// When doing scalar multiplication, we can then use a lookup - /// table of precomputed multiples of a point to add the nonzero - /// terms \\( k_i P \\). Using signed digits cuts the table size - /// in half, and using odd digits cuts the table size in half - /// again. - /// - /// To compute a \\(w\\)-NAF, we use a modification of Algorithm 3.35 of HMV: - /// - /// 1. \\( i \gets 0 \\) - /// 2. While \\( k \ge 1 \\): - /// 1. If \\(k\\) is odd, \\( n_i \gets k \operatorname{mods} 2^w \\), \\( k \gets k - n_i \\). - /// 2. If \\(k\\) is even, \\( n_i \gets 0 \\). - /// 3. \\( k \gets k / 2 \\), \\( i \gets i + 1 \\). - /// 3. Return \\( n_0, n_1, ... , \\) - /// - /// Here \\( \bar x = x \operatorname{mods} 2^w \\) means the - /// \\( \bar x \\) with \\( \bar x \equiv x \pmod{2^w} \\) and - /// \\( -2^{w-1} \leq \bar x < 2^w \\). - /// - /// We implement this by scanning across the bits of \\(k\\) from - /// least-significant bit to most-significant-bit. - /// Write the bits of \\(k\\) as - /// $$ - /// k = \sum\_{i=0}\^m k\_i 2^i, - /// $$ - /// and split the sum as - /// $$ - /// k = \sum\_{i=0}^{w-1} k\_i 2^i + 2^w \sum\_{i=0} k\_{i+w} 2^i - /// $$ - /// where the first part is \\( k \mod 2^w \\). - /// - /// If \\( k \mod 2^w\\) is odd, and \\( k \mod 2^w < 2^{w-1} \\), then we emit - /// \\( n_0 = k \mod 2^w \\). Instead of computing - /// \\( k - n_0 \\), we just advance \\(w\\) bits and reindex. - /// - /// If \\( k \mod 2^w\\) is odd, and \\( k \mod 2^w \ge 2^{w-1} \\), then - /// \\( n_0 = k \operatorname{mods} 2^w = k \mod 2^w - 2^w \\). - /// The quantity \\( k - n_0 \\) is - /// $$ - /// \begin{aligned} - /// k - n_0 &= \sum\_{i=0}^{w-1} k\_i 2^i + 2^w \sum\_{i=0} k\_{i+w} 2^i - /// - \sum\_{i=0}^{w-1} k\_i 2^i + 2^w \\\\ - /// &= 2^w + 2^w \sum\_{i=0} k\_{i+w} 2^i - /// \end{aligned} - /// $$ - /// so instead of computing the subtraction, we can set a carry - /// bit, advance \\(w\\) bits, and reindex. - /// - /// If \\( k \mod 2^w\\) is even, we emit \\(0\\), advance 1 bit - /// and reindex. In fact, by setting all digits to \\(0\\) - /// initially, we don't need to emit anything. - pub(crate) fn non_adjacent_form(&self, w: usize) -> [i8; 256] { - // required by the NAF definition - debug_assert!( w >= 2 ); - // required so that the NAF digits fit in i8 - debug_assert!( w <= 8 ); - - use byteorder::{ByteOrder, LittleEndian}; - - let mut naf = [0i8; 256]; - - let mut x_u64 = [0u64; 5]; - LittleEndian::read_u64_into(&self.bytes, &mut x_u64[0..4]); - - let width = 1 << w; - let window_mask = width - 1; - - let mut pos = 0; - let mut carry = 0; - while pos < 256 { - // Construct a buffer of bits of the scalar, starting at bit `pos` - let u64_idx = pos / 64; - let bit_idx = pos % 64; - let bit_buf: u64; - if bit_idx < 64 - w { - // This window's bits are contained in a single u64 - bit_buf = x_u64[u64_idx] >> bit_idx; - } else { - // Combine the current u64's bits with the bits from the next u64 - bit_buf = (x_u64[u64_idx] >> bit_idx) | (x_u64[1+u64_idx] << (64 - bit_idx)); - } - - // Add the carry into the current window - let window = carry + (bit_buf & window_mask); - - if window & 1 == 0 { - // If the window value is even, preserve the carry and continue. - // Why is the carry preserved? - // If carry == 0 and window & 1 == 0, then the next carry should be 0 - // If carry == 1 and window & 1 == 0, then bit_buf & 1 == 1 so the next carry should be 1 - pos += 1; - continue; - } - - if window < width/2 { - carry = 0; - naf[pos] = window as i8; - } else { - carry = 1; - naf[pos] = (window as i8).wrapping_sub(width as i8); - } - - pos += w; - } - - naf - } - - /// Write this scalar in radix 16, with coefficients in \\([-8,8)\\), - /// i.e., compute \\(a\_i\\) such that - /// $$ - /// a = a\_0 + a\_1 16\^1 + \cdots + a_{63} 16\^{63}, - /// $$ - /// with \\(-8 \leq a_i < 8\\) for \\(0 \leq i < 63\\) and \\(-8 \leq a_{63} \leq 8\\). - pub(crate) fn to_radix_16(&self) -> [i8; 64] { - debug_assert!(self[31] <= 127); - let mut output = [0i8; 64]; - - // Step 1: change radix. - // Convert from radix 256 (bytes) to radix 16 (nibbles) - #[inline(always)] - fn bot_half(x: u8) -> u8 { (x >> 0) & 15 } - #[inline(always)] - fn top_half(x: u8) -> u8 { (x >> 4) & 15 } - - for i in 0..32 { - output[2*i ] = bot_half(self[i]) as i8; - output[2*i+1] = top_half(self[i]) as i8; - } - // Precondition note: since self[31] <= 127, output[63] <= 7 - - // Step 2: recenter coefficients from [0,16) to [-8,8) - for i in 0..63 { - let carry = (output[i] + 8) >> 4; - output[i ] -= carry << 4; - output[i+1] += carry; - } - // Precondition note: output[63] is not recentered. It - // increases by carry <= 1. Thus output[63] <= 8. - - output - } - - /// Returns a size hint indicating how many entries of the return - /// value of `to_radix_2w` are nonzero. - pub(crate) fn to_radix_2w_size_hint(w: usize) -> usize { - debug_assert!(w >= 6); - debug_assert!(w <= 8); - - let digits_count = match w { - 6 => (256 + w - 1)/w as usize, - 7 => (256 + w - 1)/w as usize, - // See comment in to_radix_2w on handling the terminal carry. - 8 => (256 + w - 1)/w + 1 as usize, - _ => panic!("invalid radix parameter"), - }; - - debug_assert!(digits_count <= 43); - digits_count - } - - /// Creates a representation of a Scalar in radix 64, 128 or 256 for use with the Pippenger algorithm. - /// For lower radix, use `to_radix_16`, which is used by the Straus multi-scalar multiplication. - /// Higher radixes are not supported to save cache space. Radix 256 is near-optimal even for very - /// large inputs. - /// - /// Radix below 64 or above 256 is prohibited. - /// This method returns digits in a fixed-sized array, excess digits are zeroes. - /// The second returned value is the number of digits. - /// - /// ## Scalar representation - /// - /// Radix \\(2\^w\\), with \\(n = ceil(256/w)\\) coefficients in \\([-(2\^w)/2,(2\^w)/2)\\), - /// i.e., scalar is represented using digits \\(a\_i\\) such that - /// $$ - /// a = a\_0 + a\_1 2\^1w + \cdots + a_{n-1} 2\^{w*(n-1)}, - /// $$ - /// with \\(-2\^w/2 \leq a_i < 2\^w/2\\) for \\(0 \leq i < (n-1)\\) and \\(-2\^w/2 \leq a_{n-1} \leq 2\^w/2\\). - /// - pub(crate) fn to_radix_2w(&self, w: usize) -> [i8; 43] { - debug_assert!(w >= 6); - debug_assert!(w <= 8); - - use byteorder::{ByteOrder, LittleEndian}; - - // Scalar formatted as four `u64`s with carry bit packed into the highest bit. - let mut scalar64x4 = [0u64; 4]; - LittleEndian::read_u64_into(&self.bytes, &mut scalar64x4[0..4]); - - let radix: u64 = 1 << w; - let window_mask: u64 = radix - 1; - - let mut carry = 0u64; - let mut digits = [0i8; 43]; - let digits_count = (256 + w - 1)/w as usize; - for i in 0..digits_count { - // Construct a buffer of bits of the scalar, starting at `bit_offset`. - let bit_offset = i*w; - let u64_idx = bit_offset / 64; - let bit_idx = bit_offset % 64; - - // Read the bits from the scalar - let bit_buf: u64; - if bit_idx < 64 - w || u64_idx == 3 { - // This window's bits are contained in a single u64, - // or it's the last u64 anyway. - bit_buf = scalar64x4[u64_idx] >> bit_idx; - } else { - // Combine the current u64's bits with the bits from the next u64 - bit_buf = (scalar64x4[u64_idx] >> bit_idx) | (scalar64x4[1+u64_idx] << (64 - bit_idx)); - } - - // Read the actual coefficient value from the window - let coef = carry + (bit_buf & window_mask); // coef = [0, 2^r) - - // Recenter coefficients from [0,2^w) to [-2^w/2, 2^w/2) - carry = (coef + (radix/2) as u64) >> w; - digits[i] = ((coef as i64) - (carry << w) as i64) as i8; - } - - // When w < 8, we can fold the final carry onto the last digit d, - // because d < 2^w/2 so d + carry*2^w = d + 1*2^w < 2^(w+1) < 2^8. - // - // When w = 8, we can't fit carry*2^w into an i8. This should - // not happen anyways, because the final carry will be 0 for - // reduced scalars, but the Scalar invariant allows 255-bit scalars. - // To handle this, we expand the size_hint by 1 when w=8, - // and accumulate the final carry onto another digit. - match w { - 8 => digits[digits_count] += carry as i8, - _ => digits[digits_count-1] += (carry << w) as i8, - } - - digits - } - - /// Unpack this `Scalar` to an `UnpackedScalar` for faster arithmetic. - pub(crate) fn unpack(&self) -> UnpackedScalar { - UnpackedScalar::from_bytes(&self.bytes) - } - - /// Reduce this `Scalar` modulo \\(\ell\\). - #[allow(non_snake_case)] - pub fn reduce(&self) -> Scalar { - let x = self.unpack(); - let xR = UnpackedScalar::mul_internal(&x, &constants::R); - let x_mod_l = UnpackedScalar::montgomery_reduce(&xR); - x_mod_l.pack() - } - - /// Check whether this `Scalar` is the canonical representative mod \\(\ell\\). - /// - /// This is intended for uses like input validation, where variable-time code is acceptable. - /// - /// ``` - /// # extern crate curve25519_dalek; - /// # extern crate subtle; - /// # use curve25519_dalek::scalar::Scalar; - /// # use subtle::ConditionallySelectable; - /// # fn main() { - /// // 2^255 - 1, since `from_bits` clears the high bit - /// let _2_255_minus_1 = Scalar::from_bits([0xff;32]); - /// assert!(!_2_255_minus_1.is_canonical()); - /// - /// let reduced = _2_255_minus_1.reduce(); - /// assert!(reduced.is_canonical()); - /// # } - /// ``` - pub fn is_canonical(&self) -> bool { - *self == self.reduce() - } -} - -impl UnpackedScalar { - /// Pack the limbs of this `UnpackedScalar` into a `Scalar`. - fn pack(&self) -> Scalar { - Scalar{ bytes: self.to_bytes() } - } - - /// Inverts an UnpackedScalar in Montgomery form. - pub fn montgomery_invert(&self) -> UnpackedScalar { - // Uses the addition chain from - // https://briansmith.org/ecc-inversion-addition-chains-01#curve25519_scalar_inversion - let _1 = self; - let _10 = _1.montgomery_square(); - let _100 = _10.montgomery_square(); - let _11 = UnpackedScalar::montgomery_mul(&_10, &_1); - let _101 = UnpackedScalar::montgomery_mul(&_10, &_11); - let _111 = UnpackedScalar::montgomery_mul(&_10, &_101); - let _1001 = UnpackedScalar::montgomery_mul(&_10, &_111); - let _1011 = UnpackedScalar::montgomery_mul(&_10, &_1001); - let _1111 = UnpackedScalar::montgomery_mul(&_100, &_1011); - - // _10000 - let mut y = UnpackedScalar::montgomery_mul(&_1111, &_1); - - #[inline] - fn square_multiply(y: &mut UnpackedScalar, squarings: usize, x: &UnpackedScalar) { - for _ in 0..squarings { - *y = y.montgomery_square(); - } - *y = UnpackedScalar::montgomery_mul(y, x); - } - - square_multiply(&mut y, 123 + 3, &_101); - square_multiply(&mut y, 2 + 2, &_11); - square_multiply(&mut y, 1 + 4, &_1111); - square_multiply(&mut y, 1 + 4, &_1111); - square_multiply(&mut y, 4, &_1001); - square_multiply(&mut y, 2, &_11); - square_multiply(&mut y, 1 + 4, &_1111); - square_multiply(&mut y, 1 + 3, &_101); - square_multiply(&mut y, 3 + 3, &_101); - square_multiply(&mut y, 3, &_111); - square_multiply(&mut y, 1 + 4, &_1111); - square_multiply(&mut y, 2 + 3, &_111); - square_multiply(&mut y, 2 + 2, &_11); - square_multiply(&mut y, 1 + 4, &_1011); - square_multiply(&mut y, 2 + 4, &_1011); - square_multiply(&mut y, 6 + 4, &_1001); - square_multiply(&mut y, 2 + 2, &_11); - square_multiply(&mut y, 3 + 2, &_11); - square_multiply(&mut y, 3 + 2, &_11); - square_multiply(&mut y, 1 + 4, &_1001); - square_multiply(&mut y, 1 + 3, &_111); - square_multiply(&mut y, 2 + 4, &_1111); - square_multiply(&mut y, 1 + 4, &_1011); - square_multiply(&mut y, 3, &_101); - square_multiply(&mut y, 2 + 4, &_1111); - square_multiply(&mut y, 3, &_101); - square_multiply(&mut y, 1 + 2, &_11); - - y - } - - /// Inverts an UnpackedScalar not in Montgomery form. - pub fn invert(&self) -> UnpackedScalar { - self.to_montgomery().montgomery_invert().from_montgomery() - } -} - -#[cfg(test)] -mod test { - use super::*; - use constants; - - /// x = 2238329342913194256032495932344128051776374960164957527413114840482143558222 - pub static X: Scalar = Scalar{ - bytes: [ - 0x4e, 0x5a, 0xb4, 0x34, 0x5d, 0x47, 0x08, 0x84, - 0x59, 0x13, 0xb4, 0x64, 0x1b, 0xc2, 0x7d, 0x52, - 0x52, 0xa5, 0x85, 0x10, 0x1b, 0xcc, 0x42, 0x44, - 0xd4, 0x49, 0xf4, 0xa8, 0x79, 0xd9, 0xf2, 0x04, - ], - }; - /// 1/x = 6859937278830797291664592131120606308688036382723378951768035303146619657244 - pub static XINV: Scalar = Scalar{ - bytes: [ - 0x1c, 0xdc, 0x17, 0xfc, 0xe0, 0xe9, 0xa5, 0xbb, - 0xd9, 0x24, 0x7e, 0x56, 0xbb, 0x01, 0x63, 0x47, - 0xbb, 0xba, 0x31, 0xed, 0xd5, 0xa9, 0xbb, 0x96, - 0xd5, 0x0b, 0xcd, 0x7a, 0x3f, 0x96, 0x2a, 0x0f, - ], - }; - /// y = 2592331292931086675770238855846338635550719849568364935475441891787804997264 - pub static Y: Scalar = Scalar{ - bytes: [ - 0x90, 0x76, 0x33, 0xfe, 0x1c, 0x4b, 0x66, 0xa4, - 0xa2, 0x8d, 0x2d, 0xd7, 0x67, 0x83, 0x86, 0xc3, - 0x53, 0xd0, 0xde, 0x54, 0x55, 0xd4, 0xfc, 0x9d, - 0xe8, 0xef, 0x7a, 0xc3, 0x1f, 0x35, 0xbb, 0x05, - ], - }; - - /// x*y = 5690045403673944803228348699031245560686958845067437804563560795922180092780 - static X_TIMES_Y: Scalar = Scalar{ - bytes: [ - 0x6c, 0x33, 0x74, 0xa1, 0x89, 0x4f, 0x62, 0x21, - 0x0a, 0xaa, 0x2f, 0xe1, 0x86, 0xa6, 0xf9, 0x2c, - 0xe0, 0xaa, 0x75, 0xc2, 0x77, 0x95, 0x81, 0xc2, - 0x95, 0xfc, 0x08, 0x17, 0x9a, 0x73, 0x94, 0x0c, - ], - }; - - /// sage: l = 2^252 + 27742317777372353535851937790883648493 - /// sage: big = 2^256 - 1 - /// sage: repr((big % l).digits(256)) - static CANONICAL_2_256_MINUS_1: Scalar = Scalar{ - bytes: [ - 28, 149, 152, 141, 116, 49, 236, 214, - 112, 207, 125, 115, 244, 91, 239, 198, - 254, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 15, - ], - }; - - static A_SCALAR: Scalar = Scalar{ - bytes: [ - 0x1a, 0x0e, 0x97, 0x8a, 0x90, 0xf6, 0x62, 0x2d, - 0x37, 0x47, 0x02, 0x3f, 0x8a, 0xd8, 0x26, 0x4d, - 0xa7, 0x58, 0xaa, 0x1b, 0x88, 0xe0, 0x40, 0xd1, - 0x58, 0x9e, 0x7b, 0x7f, 0x23, 0x76, 0xef, 0x09, - ], - }; - - static A_NAF: [i8; 256] = - [0,13,0,0,0,0,0,0,0,7,0,0,0,0,0,0,-9,0,0,0,0,-11,0,0,0,0,3,0,0,0,0,1, - 0,0,0,0,9,0,0,0,0,-5,0,0,0,0,0,0,3,0,0,0,0,11,0,0,0,0,11,0,0,0,0,0, - -9,0,0,0,0,0,-3,0,0,0,0,9,0,0,0,0,0,1,0,0,0,0,0,0,-1,0,0,0,0,0,9,0, - 0,0,0,-15,0,0,0,0,-7,0,0,0,0,-9,0,0,0,0,0,5,0,0,0,0,13,0,0,0,0,0,-3,0, - 0,0,0,-11,0,0,0,0,-7,0,0,0,0,-13,0,0,0,0,11,0,0,0,0,-9,0,0,0,0,0,1,0,0, - 0,0,0,-15,0,0,0,0,1,0,0,0,0,7,0,0,0,0,0,0,0,0,5,0,0,0,0,0,13,0,0,0, - 0,0,0,11,0,0,0,0,0,15,0,0,0,0,0,-9,0,0,0,0,0,0,0,-1,0,0,0,0,0,0,0,7, - 0,0,0,0,0,-15,0,0,0,0,0,15,0,0,0,0,15,0,0,0,0,15,0,0,0,0,0,1,0,0,0,0]; - - static LARGEST_ED25519_S: Scalar = Scalar { - bytes: [ - 0xf8, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, - ], - }; - - static CANONICAL_LARGEST_ED25519_S_PLUS_ONE: Scalar = Scalar { - bytes: [ - 0x7e, 0x34, 0x47, 0x75, 0x47, 0x4a, 0x7f, 0x97, - 0x23, 0xb6, 0x3a, 0x8b, 0xe9, 0x2a, 0xe7, 0x6d, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0f, - ], - }; - - static CANONICAL_LARGEST_ED25519_S_MINUS_ONE: Scalar = Scalar { - bytes: [ - 0x7c, 0x34, 0x47, 0x75, 0x47, 0x4a, 0x7f, 0x97, - 0x23, 0xb6, 0x3a, 0x8b, 0xe9, 0x2a, 0xe7, 0x6d, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0f, - ], - }; - - #[test] - fn fuzzer_testcase_reduction() { - // LE bytes of 24519928653854221733733552434404946937899825954937634815 - let a_bytes = [255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 0, 0, 0, 0, 0, 0, 0, 0, 0]; - // LE bytes of 4975441334397345751130612518500927154628011511324180036903450236863266160640 - let b_bytes = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 210, 210, 210, 255, 255, 255, 255, 10]; - // LE bytes of 6432735165214683820902750800207468552549813371247423777071615116673864412038 - let c_bytes = [134, 171, 119, 216, 180, 128, 178, 62, 171, 132, 32, 62, 34, 119, 104, 193, 47, 215, 181, 250, 14, 207, 172, 93, 75, 207, 211, 103, 144, 204, 56, 14]; - - let a = Scalar::from_bytes_mod_order(a_bytes); - let b = Scalar::from_bytes_mod_order(b_bytes); - let c = Scalar::from_bytes_mod_order(c_bytes); - - let mut tmp = [0u8; 64]; - - // also_a = (a mod l) - tmp[0..32].copy_from_slice(&a_bytes[..]); - let also_a = Scalar::from_bytes_mod_order_wide(&tmp); - - // also_b = (b mod l) - tmp[0..32].copy_from_slice(&b_bytes[..]); - let also_b = Scalar::from_bytes_mod_order_wide(&tmp); - - let expected_c = &a * &b; - let also_expected_c = &also_a * &also_b; - - assert_eq!(c, expected_c); - assert_eq!(c, also_expected_c); - } - - #[test] - fn non_adjacent_form_test_vector() { - let naf = A_SCALAR.non_adjacent_form(5); - for i in 0..256 { - assert_eq!(naf[i], A_NAF[i]); - } - } - - fn non_adjacent_form_iter(w: usize, x: &Scalar) { - let naf = x.non_adjacent_form(w); - - // Reconstruct the scalar from the computed NAF - let mut y = Scalar::zero(); - for i in (0..256).rev() { - y += y; - let digit = if naf[i] < 0 { - -Scalar::from((-naf[i]) as u64) - } else { - Scalar::from(naf[i] as u64) - }; - y += digit; - } - - assert_eq!(*x, y); - } - - #[test] - fn non_adjacent_form_random() { - let mut rng = rand::thread_rng(); - for _ in 0..1_000 { - let x = Scalar::random(&mut rng); - for w in &[5, 6, 7, 8] { - non_adjacent_form_iter(*w, &x); - } - } - } - - #[test] - fn from_u64() { - let val: u64 = 0xdeadbeefdeadbeef; - let s = Scalar::from(val); - assert_eq!(s[7], 0xde); - assert_eq!(s[6], 0xad); - assert_eq!(s[5], 0xbe); - assert_eq!(s[4], 0xef); - assert_eq!(s[3], 0xde); - assert_eq!(s[2], 0xad); - assert_eq!(s[1], 0xbe); - assert_eq!(s[0], 0xef); - } - - #[test] - fn scalar_mul_by_one() { - let test_scalar = &X * &Scalar::one(); - for i in 0..32 { - assert!(test_scalar[i] == X[i]); - } - } - - #[test] - fn add_reduces() { - // Check that the addition works - assert_eq!( - (LARGEST_ED25519_S + Scalar::one()).reduce(), - CANONICAL_LARGEST_ED25519_S_PLUS_ONE - ); - // Check that the addition reduces - assert_eq!( - LARGEST_ED25519_S + Scalar::one(), - CANONICAL_LARGEST_ED25519_S_PLUS_ONE - ); - } - - #[test] - fn sub_reduces() { - // Check that the subtraction works - assert_eq!( - (LARGEST_ED25519_S - Scalar::one()).reduce(), - CANONICAL_LARGEST_ED25519_S_MINUS_ONE - ); - // Check that the subtraction reduces - assert_eq!( - LARGEST_ED25519_S - Scalar::one(), - CANONICAL_LARGEST_ED25519_S_MINUS_ONE - ); - } - - #[test] - fn quarkslab_scalar_overflow_does_not_occur() { - // Check that manually-constructing large Scalars with - // from_bits cannot produce incorrect results. - // - // The from_bits function is required to implement X/Ed25519, - // while all other methods of constructing a Scalar produce - // reduced Scalars. However, this "invariant loophole" allows - // constructing large scalars which are not reduced mod l. - // - // This issue was discovered independently by both Jack - // "str4d" Grigg (issue #238), who noted that reduction was - // not performed on addition, and Laurent Grémy & Nicolas - // Surbayrole of Quarkslab, who noted that it was possible to - // cause an overflow and compute incorrect results. - // - // This test is adapted from the one suggested by Quarkslab. - - let large_bytes = [ - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, - ]; - - let a = Scalar::from_bytes_mod_order(large_bytes); - let b = Scalar::from_bits(large_bytes); - - assert_eq!(a, b.reduce()); - - let a_3 = a + a + a; - let b_3 = b + b + b; - - assert_eq!(a_3, b_3); - - let neg_a = -a; - let neg_b = -b; - - assert_eq!(neg_a, neg_b); - - let minus_a_3 = Scalar::zero() - a - a - a; - let minus_b_3 = Scalar::zero() - b - b - b; - - assert_eq!(minus_a_3, minus_b_3); - assert_eq!(minus_a_3, -a_3); - assert_eq!(minus_b_3, -b_3); - } - - #[test] - fn impl_add() { - let two = Scalar::from(2u64); - let one = Scalar::one(); - let should_be_two = &one + &one; - assert_eq!(should_be_two, two); - } - - #[allow(non_snake_case)] - #[test] - fn impl_mul() { - let should_be_X_times_Y = &X * &Y; - assert_eq!(should_be_X_times_Y, X_TIMES_Y); - } - - #[allow(non_snake_case)] - #[test] - fn impl_product() { - // Test that product works for non-empty iterators - let X_Y_vector = vec![X, Y]; - let should_be_X_times_Y: Scalar = X_Y_vector.iter().product(); - assert_eq!(should_be_X_times_Y, X_TIMES_Y); - - // Test that product works for the empty iterator - let one = Scalar::one(); - let empty_vector = vec![]; - let should_be_one: Scalar = empty_vector.iter().product(); - assert_eq!(should_be_one, one); - - // Test that product works for iterators where Item = Scalar - let xs = [Scalar::from(2u64); 10]; - let ys = [Scalar::from(3u64); 10]; - // now zs is an iterator with Item = Scalar - let zs = xs.iter().zip(ys.iter()).map(|(x,y)| x * y); - - let x_prod: Scalar = xs.iter().product(); - let y_prod: Scalar = ys.iter().product(); - let z_prod: Scalar = zs.product(); - - assert_eq!(x_prod, Scalar::from(1024u64)); - assert_eq!(y_prod, Scalar::from(59049u64)); - assert_eq!(z_prod, Scalar::from(60466176u64)); - assert_eq!(x_prod * y_prod, z_prod); - - } - - #[test] - fn impl_sum() { - - // Test that sum works for non-empty iterators - let two = Scalar::from(2u64); - let one_vector = vec![Scalar::one(), Scalar::one()]; - let should_be_two: Scalar = one_vector.iter().sum(); - assert_eq!(should_be_two, two); - - // Test that sum works for the empty iterator - let zero = Scalar::zero(); - let empty_vector = vec![]; - let should_be_zero: Scalar = empty_vector.iter().sum(); - assert_eq!(should_be_zero, zero); - - // Test that sum works for owned types - let xs = [Scalar::from(1u64); 10]; - let ys = [Scalar::from(2u64); 10]; - // now zs is an iterator with Item = Scalar - let zs = xs.iter().zip(ys.iter()).map(|(x,y)| x + y); - - let x_sum: Scalar = xs.iter().sum(); - let y_sum: Scalar = ys.iter().sum(); - let z_sum: Scalar = zs.sum(); - - assert_eq!(x_sum, Scalar::from(10u64)); - assert_eq!(y_sum, Scalar::from(20u64)); - assert_eq!(z_sum, Scalar::from(30u64)); - assert_eq!(x_sum + y_sum, z_sum); - } - - #[test] - fn square() { - let expected = &X * &X; - let actual = X.unpack().square().pack(); - for i in 0..32 { - assert!(expected[i] == actual[i]); - } - } - - #[test] - fn reduce() { - let biggest = Scalar::from_bytes_mod_order([0xff; 32]); - assert_eq!(biggest, CANONICAL_2_256_MINUS_1); - } - - #[test] - fn from_bytes_mod_order_wide() { - let mut bignum = [0u8; 64]; - // set bignum = x + 2^256x - for i in 0..32 { - bignum[ i] = X[i]; - bignum[32+i] = X[i]; - } - // 3958878930004874126169954872055634648693766179881526445624823978500314864344 - // = x + 2^256x (mod l) - let reduced = Scalar{ - bytes: [ - 216, 154, 179, 139, 210, 121, 2, 71, - 69, 99, 158, 216, 23, 173, 63, 100, - 204, 0, 91, 50, 219, 153, 57, 249, - 28, 82, 31, 197, 100, 165, 192, 8, - ], - }; - let test_red = Scalar::from_bytes_mod_order_wide(&bignum); - for i in 0..32 { - assert!(test_red[i] == reduced[i]); - } - } - - #[allow(non_snake_case)] - #[test] - fn invert() { - let inv_X = X.invert(); - assert_eq!(inv_X, XINV); - let should_be_one = &inv_X * &X; - assert_eq!(should_be_one, Scalar::one()); - } - - // Negating a scalar twice should result in the original scalar. - #[allow(non_snake_case)] - #[test] - fn neg_twice_is_identity() { - let negative_X = -&X; - let should_be_X = -&negative_X; - - assert_eq!(should_be_X, X); - } - - #[test] - fn to_bytes_from_bytes_roundtrips() { - let unpacked = X.unpack(); - let bytes = unpacked.to_bytes(); - let should_be_unpacked = UnpackedScalar::from_bytes(&bytes); - - assert_eq!(should_be_unpacked.0, unpacked.0); - } - - #[test] - fn montgomery_reduce_matches_from_bytes_mod_order_wide() { - let mut bignum = [0u8; 64]; - - // set bignum = x + 2^256x - for i in 0..32 { - bignum[ i] = X[i]; - bignum[32+i] = X[i]; - } - // x + 2^256x (mod l) - // = 3958878930004874126169954872055634648693766179881526445624823978500314864344 - let expected = Scalar{ - bytes: [ - 216, 154, 179, 139, 210, 121, 2, 71, - 69, 99, 158, 216, 23, 173, 63, 100, - 204, 0, 91, 50, 219, 153, 57, 249, - 28, 82, 31, 197, 100, 165, 192, 8 - ], - }; - let reduced = Scalar::from_bytes_mod_order_wide(&bignum); - - // The reduced scalar should match the expected - assert_eq!(reduced.bytes, expected.bytes); - - // (x + 2^256x) * R - let interim = UnpackedScalar::mul_internal(&UnpackedScalar::from_bytes_wide(&bignum), - &constants::R); - // ((x + 2^256x) * R) / R (mod l) - let montgomery_reduced = UnpackedScalar::montgomery_reduce(&interim); - - // The Montgomery reduced scalar should match the reduced one, as well as the expected - assert_eq!(montgomery_reduced.0, reduced.unpack().0); - assert_eq!(montgomery_reduced.0, expected.unpack().0) - } - - #[test] - fn canonical_decoding() { - // canonical encoding of 1667457891 - let canonical_bytes = [99, 99, 99, 99, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,]; - - // encoding of - // 7265385991361016183439748078976496179028704920197054998554201349516117938192 - // = 28380414028753969466561515933501938171588560817147392552250411230663687203 (mod l) - // non_canonical because unreduced mod l - let non_canonical_bytes_because_unreduced = [16; 32]; - - // encoding with high bit set, to check that the parser isn't pre-masking the high bit - let non_canonical_bytes_because_highbit = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128]; - - assert!( Scalar::from_canonical_bytes(canonical_bytes).is_some() ); - assert!( Scalar::from_canonical_bytes(non_canonical_bytes_because_unreduced).is_none() ); - assert!( Scalar::from_canonical_bytes(non_canonical_bytes_because_highbit).is_none() ); - } - - #[test] - #[cfg(feature = "serde")] - fn serde_bincode_scalar_roundtrip() { - use bincode; - let encoded = bincode::serialize(&X).unwrap(); - let parsed: Scalar = bincode::deserialize(&encoded).unwrap(); - assert_eq!(parsed, X); - - // Check that the encoding is 32 bytes exactly - assert_eq!(encoded.len(), 32); - - // Check that the encoding itself matches the usual one - assert_eq!( - X, - bincode::deserialize(X.as_bytes()).unwrap(), - ); - } - - #[cfg(debug_assertions)] - #[test] - #[should_panic] - fn batch_invert_with_a_zero_input_panics() { - let mut xs = vec![Scalar::one(); 16]; - xs[3] = Scalar::zero(); - // This should panic in debug mode. - Scalar::batch_invert(&mut xs); - } - - #[test] - fn batch_invert_empty() { - assert_eq!(Scalar::one(), Scalar::batch_invert(&mut [])); - } - - #[test] - fn batch_invert_consistency() { - let mut x = Scalar::from(1u64); - let mut v1: Vec<_> = (0..16).map(|_| {let tmp = x; x = x + x; tmp}).collect(); - let v2 = v1.clone(); - - let expected: Scalar = v1.iter().product(); - let expected = expected.invert(); - let ret = Scalar::batch_invert(&mut v1); - assert_eq!(ret, expected); - - for (a, b) in v1.iter().zip(v2.iter()) { - assert_eq!(a * b, Scalar::one()); - } - } - - fn test_pippenger_radix_iter(scalar: Scalar, w: usize) { - let digits_count = Scalar::to_radix_2w_size_hint(w); - let digits = scalar.to_radix_2w(w); - - let radix = Scalar::from((1< -// - Henry de Valence - -//! Module for common traits. - -#![allow(non_snake_case)] - -use core::borrow::Borrow; - -use subtle; - -use scalar::Scalar; - -// ------------------------------------------------------------------------ -// Public Traits -// ------------------------------------------------------------------------ - -/// Trait for getting the identity element of a point type. -pub trait Identity { - /// Returns the identity element of the curve. - /// Can be used as a constructor. - fn identity() -> Self; -} - -/// Trait for testing if a curve point is equivalent to the identity point. -pub trait IsIdentity { - /// Return true if this element is the identity element of the curve. - fn is_identity(&self) -> bool; -} - -/// Implement generic identity equality testing for a point representations -/// which have constant-time equality testing and a defined identity -/// constructor. -impl IsIdentity for T -where - T: subtle::ConstantTimeEq + Identity, -{ - fn is_identity(&self) -> bool { - self.ct_eq(&T::identity()).unwrap_u8() == 1u8 - } -} - -/// A trait for constant-time multiscalar multiplication without precomputation. -pub trait MultiscalarMul { - /// The type of point being multiplied, e.g., `RistrettoPoint`. - type Point; - - /// Given an iterator of (possibly secret) scalars and an iterator of - /// public points, compute - /// $$ - /// Q = c\_1 P\_1 + \cdots + c\_n P\_n. - /// $$ - /// - /// It is an error to call this function with two iterators of different lengths. - /// - /// # Examples - /// - /// The trait bound aims for maximum flexibility: the inputs must be - /// convertable to iterators (`I: IntoIter`), and the iterator's items - /// must be `Borrow` (or `Borrow`), to allow - /// iterators returning either `Scalar`s or `&Scalar`s. - /// - /// ``` - /// use curve25519_dalek::constants; - /// use curve25519_dalek::traits::MultiscalarMul; - /// use curve25519_dalek::ristretto::RistrettoPoint; - /// use curve25519_dalek::scalar::Scalar; - /// - /// // Some scalars - /// let a = Scalar::from(87329482u64); - /// let b = Scalar::from(37264829u64); - /// let c = Scalar::from(98098098u64); - /// - /// // Some points - /// let P = constants::RISTRETTO_BASEPOINT_POINT; - /// let Q = P + P; - /// let R = P + Q; - /// - /// // A1 = a*P + b*Q + c*R - /// let abc = [a,b,c]; - /// let A1 = RistrettoPoint::multiscalar_mul(&abc, &[P,Q,R]); - /// // Note: (&abc).into_iter(): Iterator - /// - /// // A2 = (-a)*P + (-b)*Q + (-c)*R - /// let minus_abc = abc.iter().map(|x| -x); - /// let A2 = RistrettoPoint::multiscalar_mul(minus_abc, &[P,Q,R]); - /// // Note: minus_abc.into_iter(): Iterator - /// - /// assert_eq!(A1.compress(), (-A2).compress()); - /// ``` - fn multiscalar_mul(scalars: I, points: J) -> Self::Point - where - I: IntoIterator, - I::Item: Borrow, - J: IntoIterator, - J::Item: Borrow; -} - -/// A trait for variable-time multiscalar multiplication without precomputation. -pub trait VartimeMultiscalarMul { - /// The type of point being multiplied, e.g., `RistrettoPoint`. - type Point; - - /// Given an iterator of public scalars and an iterator of - /// `Option`s of points, compute either `Some(Q)`, where - /// $$ - /// Q = c\_1 P\_1 + \cdots + c\_n P\_n, - /// $$ - /// if all points were `Some(P_i)`, or else return `None`. - /// - /// This function is particularly useful when verifying statements - /// involving compressed points. Accepting `Option` allows - /// inlining point decompression into the multiscalar call, - /// avoiding the need for temporary buffers. - /// ``` - /// use curve25519_dalek::constants; - /// use curve25519_dalek::traits::VartimeMultiscalarMul; - /// use curve25519_dalek::ristretto::RistrettoPoint; - /// use curve25519_dalek::scalar::Scalar; - /// - /// // Some scalars - /// let a = Scalar::from(87329482u64); - /// let b = Scalar::from(37264829u64); - /// let c = Scalar::from(98098098u64); - /// let abc = [a,b,c]; - /// - /// // Some points - /// let P = constants::RISTRETTO_BASEPOINT_POINT; - /// let Q = P + P; - /// let R = P + Q; - /// let PQR = [P, Q, R]; - /// - /// let compressed = [P.compress(), Q.compress(), R.compress()]; - /// - /// // Now we can compute A1 = a*P + b*Q + c*R using P, Q, R: - /// let A1 = RistrettoPoint::vartime_multiscalar_mul(&abc, &PQR); - /// - /// // Or using the compressed points: - /// let A2 = RistrettoPoint::optional_multiscalar_mul( - /// &abc, - /// compressed.iter().map(|pt| pt.decompress()), - /// ); - /// - /// assert_eq!(A2, Some(A1)); - /// - /// // It's also possible to mix compressed and uncompressed points: - /// let A3 = RistrettoPoint::optional_multiscalar_mul( - /// abc.iter() - /// .chain(abc.iter()), - /// compressed.iter().map(|pt| pt.decompress()) - /// .chain(PQR.iter().map(|&pt| Some(pt))), - /// ); - /// - /// assert_eq!(A3, Some(A1+A1)); - /// ``` - fn optional_multiscalar_mul(scalars: I, points: J) -> Option - where - I: IntoIterator, - I::Item: Borrow, - J: IntoIterator>; - - /// Given an iterator of public scalars and an iterator of - /// public points, compute - /// $$ - /// Q = c\_1 P\_1 + \cdots + c\_n P\_n, - /// $$ - /// using variable-time operations. - /// - /// It is an error to call this function with two iterators of different lengths. - /// - /// # Examples - /// - /// The trait bound aims for maximum flexibility: the inputs must be - /// convertable to iterators (`I: IntoIter`), and the iterator's items - /// must be `Borrow` (or `Borrow`), to allow - /// iterators returning either `Scalar`s or `&Scalar`s. - /// - /// ``` - /// use curve25519_dalek::constants; - /// use curve25519_dalek::traits::VartimeMultiscalarMul; - /// use curve25519_dalek::ristretto::RistrettoPoint; - /// use curve25519_dalek::scalar::Scalar; - /// - /// // Some scalars - /// let a = Scalar::from(87329482u64); - /// let b = Scalar::from(37264829u64); - /// let c = Scalar::from(98098098u64); - /// - /// // Some points - /// let P = constants::RISTRETTO_BASEPOINT_POINT; - /// let Q = P + P; - /// let R = P + Q; - /// - /// // A1 = a*P + b*Q + c*R - /// let abc = [a,b,c]; - /// let A1 = RistrettoPoint::vartime_multiscalar_mul(&abc, &[P,Q,R]); - /// // Note: (&abc).into_iter(): Iterator - /// - /// // A2 = (-a)*P + (-b)*Q + (-c)*R - /// let minus_abc = abc.iter().map(|x| -x); - /// let A2 = RistrettoPoint::vartime_multiscalar_mul(minus_abc, &[P,Q,R]); - /// // Note: minus_abc.into_iter(): Iterator - /// - /// assert_eq!(A1.compress(), (-A2).compress()); - /// ``` - fn vartime_multiscalar_mul(scalars: I, points: J) -> Self::Point - where - I: IntoIterator, - I::Item: Borrow, - J: IntoIterator, - J::Item: Borrow, - Self::Point: Clone, - { - Self::optional_multiscalar_mul( - scalars, - points.into_iter().map(|P| Some(P.borrow().clone())), - ) - .unwrap() - } -} - -/// A trait for variable-time multiscalar multiplication with precomputation. -/// -/// A general multiscalar multiplication with precomputation can be written as -/// $$ -/// Q = a_1 A_1 + \cdots + a_n A_n + b_1 B_1 + \cdots + b_m B_m, -/// $$ -/// where the \\(B_i\\) are *static* points, for which precomputation -/// is possible, and the \\(A_j\\) are *dynamic* points, for which -/// precomputation is not possible. -/// -/// This trait has three methods for performing this computation: -/// -/// * [`vartime_multiscalar_mul`], which handles the special case -/// where \\(n = 0\\) and there are no dynamic points; -/// -/// * [`vartime_mixed_multiscalar_mul`], which takes the dynamic -/// points as already-validated `Point`s and is infallible; -/// -/// * [`optional_mixed_multiscalar_mul`], which takes the dynamic -/// points as `Option`s and returns an `Option`, -/// allowing decompression to be composed into the input iterators. -/// -/// All methods require that the lengths of the input iterators be -/// known and matching, as if they were `ExactSizeIterator`s. (It -/// does not require `ExactSizeIterator` only because that trait is -/// broken). -pub trait VartimePrecomputedMultiscalarMul: Sized { - /// The type of point to be multiplied, e.g., `RistrettoPoint`. - type Point: Clone; - - /// Given the static points \\( B_i \\), perform precomputation - /// and return the precomputation data. - fn new(static_points: I) -> Self - where - I: IntoIterator, - I::Item: Borrow; - - /// Given `static_scalars`, an iterator of public scalars - /// \\(b_i\\), compute - /// $$ - /// Q = b_1 B_1 + \cdots + b_m B_m, - /// $$ - /// where the \\(B_j\\) are the points that were supplied to `new`. - /// - /// It is an error to call this function with iterators of - /// inconsistent lengths. - /// - /// The trait bound aims for maximum flexibility: the input must - /// be convertable to iterators (`I: IntoIter`), and the - /// iterator's items must be `Borrow`, to allow iterators - /// returning either `Scalar`s or `&Scalar`s. - fn vartime_multiscalar_mul(&self, static_scalars: I) -> Self::Point - where - I: IntoIterator, - I::Item: Borrow, - { - use core::iter; - - Self::vartime_mixed_multiscalar_mul( - self, - static_scalars, - iter::empty::(), - iter::empty::(), - ) - } - - /// Given `static_scalars`, an iterator of public scalars - /// \\(b_i\\), `dynamic_scalars`, an iterator of public scalars - /// \\(a_i\\), and `dynamic_points`, an iterator of points - /// \\(A_i\\), compute - /// $$ - /// Q = a_1 A_1 + \cdots + a_n A_n + b_1 B_1 + \cdots + b_m B_m, - /// $$ - /// where the \\(B_j\\) are the points that were supplied to `new`. - /// - /// It is an error to call this function with iterators of - /// inconsistent lengths. - /// - /// The trait bound aims for maximum flexibility: the inputs must be - /// convertable to iterators (`I: IntoIter`), and the iterator's items - /// must be `Borrow` (or `Borrow`), to allow - /// iterators returning either `Scalar`s or `&Scalar`s. - fn vartime_mixed_multiscalar_mul( - &self, - static_scalars: I, - dynamic_scalars: J, - dynamic_points: K, - ) -> Self::Point - where - I: IntoIterator, - I::Item: Borrow, - J: IntoIterator, - J::Item: Borrow, - K: IntoIterator, - K::Item: Borrow, - { - Self::optional_mixed_multiscalar_mul( - self, - static_scalars, - dynamic_scalars, - dynamic_points.into_iter().map(|P| Some(P.borrow().clone())), - ) - .unwrap() - } - - /// Given `static_scalars`, an iterator of public scalars - /// \\(b_i\\), `dynamic_scalars`, an iterator of public scalars - /// \\(a_i\\), and `dynamic_points`, an iterator of points - /// \\(A_i\\), compute - /// $$ - /// Q = a_1 A_1 + \cdots + a_n A_n + b_1 B_1 + \cdots + b_m B_m, - /// $$ - /// where the \\(B_j\\) are the points that were supplied to `new`. - /// - /// If any of the dynamic points were `None`, return `None`. - /// - /// It is an error to call this function with iterators of - /// inconsistent lengths. - /// - /// This function is particularly useful when verifying statements - /// involving compressed points. Accepting `Option` allows - /// inlining point decompression into the multiscalar call, - /// avoiding the need for temporary buffers. - fn optional_mixed_multiscalar_mul( - &self, - static_scalars: I, - dynamic_scalars: J, - dynamic_points: K, - ) -> Option - where - I: IntoIterator, - I::Item: Borrow, - J: IntoIterator, - J::Item: Borrow, - K: IntoIterator>; -} - -// ------------------------------------------------------------------------ -// Private Traits -// ------------------------------------------------------------------------ - -/// Trait for checking whether a point is on the curve. -/// -/// This trait is only for debugging/testing, since it should be -/// impossible for a `curve25519-dalek` user to construct an invalid -/// point. -pub(crate) trait ValidityCheck { - /// Checks whether the point is on the curve. Not CT. - fn is_valid(&self) -> bool; -} diff --git a/net/gurk-rs/files/vendor/curve25519-dalek-2.0.0/src/window.rs b/net/gurk-rs/files/vendor/curve25519-dalek-2.0.0/src/window.rs deleted file mode 100644 index 3b01422..0000000 --- a/net/gurk-rs/files/vendor/curve25519-dalek-2.0.0/src/window.rs +++ /dev/null @@ -1,206 +0,0 @@ -// -*- mode: rust; -*- -// -// This file is part of curve25519-dalek. -// Copyright (c) 2016-2019 Isis Lovecruft, Henry de Valence -// See LICENSE for licensing information. -// -// Authors: -// - Isis Agora Lovecruft -// - Henry de Valence - -//! Code for fixed- and sliding-window functionality - -#![allow(non_snake_case)] - -use core::fmt::Debug; - -use subtle::ConditionallyNegatable; -use subtle::ConditionallySelectable; -use subtle::ConstantTimeEq; -use subtle::Choice; - -use traits::Identity; - -use edwards::EdwardsPoint; -use backend::serial::curve_models::ProjectiveNielsPoint; -use backend::serial::curve_models::AffineNielsPoint; - -use zeroize::Zeroize; - -/// A lookup table of precomputed multiples of a point \\(P\\), used to -/// compute \\( xP \\) for \\( -8 \leq x \leq 8 \\). -/// -/// The computation of \\( xP \\) is done in constant time by the `select` function. -/// -/// Since `LookupTable` does not implement `Index`, it's more difficult -/// to accidentally use the table directly. Unfortunately the table is -/// only `pub(crate)` so that we can write hardcoded constants, so it's -/// still technically possible. It would be nice to prevent direct -/// access to the table. -/// -/// XXX make this generic with respect to table size -#[derive(Copy, Clone)] -pub struct LookupTable(pub(crate) [T; 8]); - -impl LookupTable -where - T: Identity + ConditionallySelectable + ConditionallyNegatable, -{ - /// Given \\(-8 \leq x \leq 8\\), return \\(xP\\) in constant time. - pub fn select(&self, x: i8) -> T { - debug_assert!(x >= -8); - debug_assert!(x <= 8); - - // Compute xabs = |x| - let xmask = x >> 7; - let xabs = (x + xmask) ^ xmask; - - // Set t = 0 * P = identity - let mut t = T::identity(); - for j in 1..9 { - // Copy `points[j-1] == j*P` onto `t` in constant time if `|x| == j`. - let c = (xabs as u8).ct_eq(&(j as u8)); - t.conditional_assign(&self.0[j - 1], c); - } - // Now t == |x| * P. - - let neg_mask = Choice::from((xmask & 1) as u8); - t.conditional_negate(neg_mask); - // Now t == x * P. - - t - } -} - -impl Default for LookupTable { - fn default() -> LookupTable { - LookupTable([T::default(); 8]) - } -} - -impl Debug for LookupTable { - fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { - write!(f, "LookupTable({:?})", self.0) - } -} - -impl<'a> From<&'a EdwardsPoint> for LookupTable { - fn from(P: &'a EdwardsPoint) -> Self { - let mut points = [P.to_projective_niels(); 8]; - for j in 0..7 { - points[j + 1] = (P + &points[j]).to_extended().to_projective_niels(); - } - LookupTable(points) - } -} - -impl<'a> From<&'a EdwardsPoint> for LookupTable { - fn from(P: &'a EdwardsPoint) -> Self { - let mut points = [P.to_affine_niels(); 8]; - // XXX batch inversion would be good if perf mattered here - for j in 0..7 { - points[j + 1] = (P + &points[j]).to_extended().to_affine_niels() - } - LookupTable(points) - } -} - -impl Zeroize for LookupTable -where - T: Copy + Default + Zeroize -{ - fn zeroize(&mut self) { - self.0.zeroize(); - } -} - -/// Holds odd multiples 1A, 3A, ..., 15A of a point A. -#[derive(Copy, Clone)] -pub(crate) struct NafLookupTable5(pub(crate) [T; 8]); - -impl NafLookupTable5 { - /// Given public, odd \\( x \\) with \\( 0 < x < 2^4 \\), return \\(xA\\). - pub fn select(&self, x: usize) -> T { - debug_assert_eq!(x & 1, 1); - debug_assert!(x < 16); - - self.0[x / 2] - } -} - -impl Debug for NafLookupTable5 { - fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { - write!(f, "NafLookupTable5({:?})", self.0) - } -} - -impl<'a> From<&'a EdwardsPoint> for NafLookupTable5 { - fn from(A: &'a EdwardsPoint) -> Self { - let mut Ai = [A.to_projective_niels(); 8]; - let A2 = A.double(); - for i in 0..7 { - Ai[i + 1] = (&A2 + &Ai[i]).to_extended().to_projective_niels(); - } - // Now Ai = [A, 3A, 5A, 7A, 9A, 11A, 13A, 15A] - NafLookupTable5(Ai) - } -} - -impl<'a> From<&'a EdwardsPoint> for NafLookupTable5 { - fn from(A: &'a EdwardsPoint) -> Self { - let mut Ai = [A.to_affine_niels(); 8]; - let A2 = A.double(); - for i in 0..7 { - Ai[i + 1] = (&A2 + &Ai[i]).to_extended().to_affine_niels(); - } - // Now Ai = [A, 3A, 5A, 7A, 9A, 11A, 13A, 15A] - NafLookupTable5(Ai) - } -} - -/// Holds stuff up to 8. -#[derive(Copy, Clone)] -pub(crate) struct NafLookupTable8(pub(crate) [T; 64]); - -impl NafLookupTable8 { - pub fn select(&self, x: usize) -> T { - debug_assert_eq!(x & 1, 1); - debug_assert!(x < 128); - - self.0[x / 2] - } -} - -impl Debug for NafLookupTable8 { - fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { - write!(f, "NafLookupTable8([\n")?; - for i in 0..64 { - write!(f, "\t{:?},\n", &self.0[i])?; - } - write!(f, "])") - } -} - -impl<'a> From<&'a EdwardsPoint> for NafLookupTable8 { - fn from(A: &'a EdwardsPoint) -> Self { - let mut Ai = [A.to_projective_niels(); 64]; - let A2 = A.double(); - for i in 0..63 { - Ai[i + 1] = (&A2 + &Ai[i]).to_extended().to_projective_niels(); - } - // Now Ai = [A, 3A, 5A, 7A, 9A, 11A, 13A, 15A, ..., 127A] - NafLookupTable8(Ai) - } -} - -impl<'a> From<&'a EdwardsPoint> for NafLookupTable8 { - fn from(A: &'a EdwardsPoint) -> Self { - let mut Ai = [A.to_affine_niels(); 64]; - let A2 = A.double(); - for i in 0..63 { - Ai[i + 1] = (&A2 + &Ai[i]).to_extended().to_affine_niels(); - } - // Now Ai = [A, 3A, 5A, 7A, 9A, 11A, 13A, 15A, ..., 127A] - NafLookupTable8(Ai) - } -} diff --git a/net/gurk-rs/files/vendor/curve25519-dalek-2.0.0/vendor/ristretto.sage b/net/gurk-rs/files/vendor/curve25519-dalek-2.0.0/vendor/ristretto.sage deleted file mode 100644 index 04cf4f9..0000000 --- a/net/gurk-rs/files/vendor/curve25519-dalek-2.0.0/vendor/ristretto.sage +++ /dev/null @@ -1,857 +0,0 @@ -import binascii -class InvalidEncodingException(Exception): pass -class NotOnCurveException(Exception): pass -class SpecException(Exception): pass - -def lobit(x): return int(x) & 1 -def hibit(x): return lobit(2*x) -def negative(x): return lobit(x) -def enc_le(x,n): return bytearray([int(x)>>(8*i) & 0xFF for i in xrange(n)]) -def dec_le(x): return sum(b<<(8*i) for i,b in enumerate(x)) -def randombytes(n): return bytearray([randint(0,255) for _ in range(n)]) - -def optimized_version_of(spec): - """Decorator: This function is an optimized version of some specification""" - def decorator(f): - def wrapper(self,*args,**kwargs): - def pr(x): - if isinstance(x,bytearray): return binascii.hexlify(x) - else: return str(x) - try: spec_ans = getattr(self,spec,spec)(*args,**kwargs),None - except Exception as e: spec_ans = None,e - try: opt_ans = f(self,*args,**kwargs),None - except Exception as e: opt_ans = None,e - if spec_ans[1] is None and opt_ans[1] is not None: - raise - #raise SpecException("Mismatch in %s: spec returned %s but opt threw %s" - # % (f.__name__,str(spec_ans[0]),str(opt_ans[1]))) - if spec_ans[1] is not None and opt_ans[1] is None: - raise - #raise SpecException("Mismatch in %s: spec threw %s but opt returned %s" - # % (f.__name__,str(spec_ans[1]),str(opt_ans[0]))) - if spec_ans[0] != opt_ans[0]: - raise SpecException("Mismatch in %s: %s != %s" - % (f.__name__,pr(spec_ans[0]),pr(opt_ans[0]))) - if opt_ans[1] is not None: raise - else: return opt_ans[0] - wrapper.__name__ = f.__name__ - return wrapper - return decorator - -def xsqrt(x,exn=InvalidEncodingException("Not on curve")): - """Return sqrt(x)""" - if not is_square(x): raise exn - s = sqrt(x) - if negative(s): s=-s - return s - -def isqrt(x,exn=InvalidEncodingException("Not on curve")): - """Return 1/sqrt(x)""" - if x==0: return 0 - if not is_square(x): raise exn - s = sqrt(x) - #if negative(s): s=-s - return 1/s - -def inv0(x): return 1/x if x != 0 else 0 - -def isqrt_i(x): - """Return 1/sqrt(x) or 1/sqrt(zeta * x)""" - if x==0: return True,0 - gen = x.parent(-1) - while is_square(gen): gen = sqrt(gen) - if is_square(x): return True,1/sqrt(x) - else: return False,1/sqrt(x*gen) - -class QuotientEdwardsPoint(object): - """Abstract class for point an a quotiented Edwards curve; needs F,a,d,cofactor to work""" - def __init__(self,x=0,y=1): - x = self.x = self.F(x) - y = self.y = self.F(y) - if y^2 + self.a*x^2 != 1 + self.d*x^2*y^2: - raise NotOnCurveException(str(self)) - - def __repr__(self): - return "%s(0x%x,0x%x)" % (self.__class__.__name__, self.x, self.y) - - def __iter__(self): - yield self.x - yield self.y - - def __add__(self,other): - x,y = self - X,Y = other - a,d = self.a,self.d - return self.__class__( - (x*Y+y*X)/(1+d*x*y*X*Y), - (y*Y-a*x*X)/(1-d*x*y*X*Y) - ) - - def __neg__(self): return self.__class__(-self.x,self.y) - def __sub__(self,other): return self + (-other) - def __rmul__(self,other): return self*other - def __eq__(self,other): - """NB: this is the only method that is different from the usual one""" - x,y = self - X,Y = other - return x*Y == X*y or (self.cofactor==8 and -self.a*x*X == y*Y) - def __ne__(self,other): return not (self==other) - - def __mul__(self,exp): - exp = int(exp) - if exp < 0: exp,self = -exp,-self - total = self.__class__() - work = self - while exp != 0: - if exp & 1: total += work - work += work - exp >>= 1 - return total - - def xyzt(self): - x,y = self - z = self.F.random_element() - return x*z,y*z,z,x*y*z - - def torque(self): - """Apply cofactor group, except keeping the point even""" - if self.cofactor == 8: - if self.a == -1: return self.__class__(self.y*self.i, self.x*self.i) - if self.a == 1: return self.__class__(-self.y, self.x) - else: - return self.__class__(-self.x, -self.y) - - def doubleAndEncodeSpec(self): - return (self+self).encode() - - # Utility functions - @classmethod - def bytesToGf(cls,bytes,mustBeProper=True,mustBePositive=False,maskHiBits=False): - """Convert little-endian bytes to field element, sanity check length""" - if len(bytes) != cls.encLen: - raise InvalidEncodingException("wrong length %d" % len(bytes)) - s = dec_le(bytes) - if mustBeProper and s >= cls.F.order(): - raise InvalidEncodingException("%d out of range!" % s) - bitlen = int(ceil(log(cls.F.order())/log(2))) - if maskHiBits: s &= 2^bitlen-1 - s = cls.F(s) - if mustBePositive and negative(s): - raise InvalidEncodingException("%d is negative!" % s) - return s - - @classmethod - def gfToBytes(cls,x,mustBePositive=False): - """Convert little-endian bytes to field element, sanity check length""" - if negative(x) and mustBePositive: x = -x - return enc_le(x,cls.encLen) - -class RistrettoPoint(QuotientEdwardsPoint): - """The new Ristretto group""" - def encodeSpec(self): - """Unoptimized specification for encoding""" - x,y = self - if self.cofactor==8 and (negative(x*y) or y==0): (x,y) = self.torque() - if y == -1: y = 1 # Avoid divide by 0; doesn't affect impl - - if negative(x): x,y = -x,-y - s = xsqrt(self.mneg*(1-y)/(1+y),exn=Exception("Unimplemented: point is odd: " + str(self))) - return self.gfToBytes(s) - - @classmethod - def decodeSpec(cls,s): - """Unoptimized specification for decoding""" - s = cls.bytesToGf(s,mustBePositive=True) - - a,d = cls.a,cls.d - x = xsqrt(4*s^2 / (a*d*(1+a*s^2)^2 - (1-a*s^2)^2)) - y = (1+a*s^2) / (1-a*s^2) - - if cls.cofactor==8 and (negative(x*y) or y==0): - raise InvalidEncodingException("x*y has high bit") - - return cls(x,y) - - @optimized_version_of("encodeSpec") - def encode(self): - """Encode, optimized version""" - a,d,mneg = self.a,self.d,self.mneg - x,y,z,t = self.xyzt() - - if self.cofactor==8: - u1 = mneg*(z+y)*(z-y) - u2 = x*y # = t*z - isr = isqrt(u1*u2^2) - i1 = isr*u1 # sqrt(mneg*(z+y)*(z-y))/(x*y) - i2 = isr*u2 # 1/sqrt(a*(y+z)*(y-z)) - z_inv = i1*i2*t # 1/z - - if negative(t*z_inv): - if a==-1: - x,y = y*self.i,x*self.i - den_inv = self.magic * i1 - else: - x,y = -y,x - den_inv = self.i * self.magic * i1 - - else: - den_inv = i2 - - if negative(x*z_inv): y = -y - s = (z-y) * den_inv - else: - num = mneg*(z+y)*(z-y) - isr = isqrt(num*y^2) - if negative(isr^2*num*y*t): y = -y - s = isr*y*(z-y) - - return self.gfToBytes(s,mustBePositive=True) - - @optimized_version_of("doubleAndEncodeSpec") - def doubleAndEncode(self): - X,Y,Z,T = self.xyzt() - a,d,mneg = self.a,self.d,self.mneg - - if self.cofactor==8: - e = 2*X*Y - f = Z^2+d*T^2 - g = Y^2-a*X^2 - h = Z^2-d*T^2 - - inv1 = 1/(e*f*g*h) - z_inv = inv1*e*g # 1 / (f*h) - t_inv = inv1*f*h - - if negative(e*g*z_inv): - if a==-1: sqrta = self.i - else: sqrta = -1 - e,f,g,h = g,h,-e,f*sqrta - factor = self.i - else: - factor = self.magic - - if negative(h*e*z_inv): g=-g - s = (h-g)*factor*g*t_inv - - else: - foo = Y^2+a*X^2 - bar = X*Y - den = 1/(foo*bar) - if negative(2*bar^2*den): tmp = a*X^2 - else: tmp = Y^2 - s = self.magic*(Z^2-tmp)*foo*den - - return self.gfToBytes(s,mustBePositive=True) - - @classmethod - @optimized_version_of("decodeSpec") - def decode(cls,s): - """Decode, optimized version""" - s = cls.bytesToGf(s,mustBePositive=True) - - a,d = cls.a,cls.d - yden = 1-a*s^2 - ynum = 1+a*s^2 - yden_sqr = yden^2 - xden_sqr = a*d*ynum^2 - yden_sqr - - isr = isqrt(xden_sqr * yden_sqr) - - xden_inv = isr * yden - yden_inv = xden_inv * isr * xden_sqr - - x = 2*s*xden_inv - if negative(x): x = -x - y = ynum * yden_inv - - if cls.cofactor==8 and (negative(x*y) or y==0): - raise InvalidEncodingException("x*y is invalid: %d, %d" % (x,y)) - - return cls(x,y) - - @classmethod - def fromJacobiQuartic(cls,s,t,sgn=1): - """Convert point from its Jacobi Quartic representation""" - a,d = cls.a,cls.d - assert s^4 - 2*cls.a*(1-2*d/(d-a))*s^2 + 1 == t^2 - x = 2*s*cls.magic / t - y = (1+a*s^2) / (1-a*s^2) - return cls(sgn*x,y) - - @classmethod - def elligatorSpec(cls,r0): - a,d = cls.a,cls.d - r = cls.qnr * cls.bytesToGf(r0,mustBeProper=False,maskHiBits=True)^2 - den = (d*r-a)*(a*r-d) - if den == 0: return cls() - n1 = cls.a*(r+1)*(a+d)*(d-a)/den - n2 = r*n1 - if is_square(n1): - sgn,s,t = 1, xsqrt(n1), -(r-1)*(a+d)^2 / den - 1 - else: - sgn,s,t = -1,-xsqrt(n2), r*(r-1)*(a+d)^2 / den - 1 - - return cls.fromJacobiQuartic(s,t) - - @classmethod - @optimized_version_of("elligatorSpec") - def elligator(cls,r0): - a,d = cls.a,cls.d - r0 = cls.bytesToGf(r0,mustBeProper=False,maskHiBits=True) - r = cls.qnr * r0^2 - den = (d*r-a)*(a*r-d) - num = cls.a*(r+1)*(a+d)*(d-a) - - iss,isri = isqrt_i(num*den) - if iss: sgn,twiddle = 1,1 - else: sgn,twiddle = -1,r0*cls.qnr - isri *= twiddle - s = isri*num - t = -sgn*isri*s*(r-1)*(d+a)^2 - 1 - if negative(s) == iss: s = -s - return cls.fromJacobiQuartic(s,t) - - -class Decaf_1_1_Point(QuotientEdwardsPoint): - """Like current decaf but tweaked for simplicity""" - def encodeSpec(self): - """Unoptimized specification for encoding""" - a,d = self.a,self.d - x,y = self - if x==0 or y==0: return(self.gfToBytes(0)) - - if self.cofactor==8 and negative(x*y*self.isoMagic): - x,y = self.torque() - - sr = xsqrt(1-a*x^2) - altx = x*y*self.isoMagic / sr - if negative(altx): s = (1+sr)/x - else: s = (1-sr)/x - - return self.gfToBytes(s,mustBePositive=True) - - @classmethod - def decodeSpec(cls,s): - """Unoptimized specification for decoding""" - a,d = cls.a,cls.d - s = cls.bytesToGf(s,mustBePositive=True) - - if s==0: return cls() - t = xsqrt(s^4 + 2*(a-2*d)*s^2 + 1) - altx = 2*s*cls.isoMagic/t - if negative(altx): t = -t - x = 2*s / (1+a*s^2) - y = (1-a*s^2) / t - - if cls.cofactor==8 and (negative(x*y*cls.isoMagic) or y==0): - raise InvalidEncodingException("x*y is invalid: %d, %d" % (x,y)) - - return cls(x,y) - - def toJacobiQuartic(self,toggle_rotation=False,toggle_altx=False,toggle_s=False): - "Return s,t on jacobi curve" - a,d = self.a,self.d - x,y,z,t = self.xyzt() - - if self.cofactor == 8: - # Cofactor 8 version - # Simulate IMAGINE_TWIST because that's how libdecaf does it - x = self.i*x - t = self.i*t - a = -a - d = -d - - # OK, the actual libdecaf code should be here - num = (z+y)*(z-y) - den = x*y - isr = isqrt(num*(a-d)*den^2) - - iden = isr * den * self.isoMagic # 1/sqrt((z+y)(z-y)) = 1/sqrt(1-Y^2) / z - inum = isr * num # sqrt(1-Y^2) * z / xysqrt(a-d) ~ 1/sqrt(1-ax^2)/z - - if negative(iden*inum*self.i*t^2*(d-a)) != toggle_rotation: - iden,inum = inum,iden - fac = x*sqrt(a) - toggle=(a==-1) - else: - fac = y - toggle=False - - imi = self.isoMagic * self.i - altx = inum*t*imi - neg_altx = negative(altx) != toggle_altx - if neg_altx != toggle: inum =- inum - - tmp = fac*(inum*z + 1) - s = iden*tmp*imi - - negm1 = (negative(s) != toggle_s) != neg_altx - if negm1: m1 = a*fac + z - else: m1 = a*fac - z - - swap = toggle_s - - else: - # Much simpler cofactor 4 version - num = (x+t)*(x-t) - isr = isqrt(num*(a-d)*x^2) - ratio = isr*num - altx = ratio*self.isoMagic - - neg_altx = negative(altx) != toggle_altx - if neg_altx: ratio =- ratio - - tmp = ratio*z - t - s = (a-d)*isr*x*tmp - - negx = (negative(s) != toggle_s) != neg_altx - if negx: m1 = -a*t + x - else: m1 = -a*t - x - - swap = toggle_s - - if negative(s): s = -s - - return s,m1,a*tmp,swap - - def invertElligator(self,toggle_r=False,*args,**kwargs): - "Produce preimage of self under elligator, or None" - a,d = self.a,self.d - - rets = [] - - tr = [False,True] if self.cofactor == 8 else [False] - for toggle_rotation in tr: - for toggle_altx in [False,True]: - for toggle_s in [False,True]: - for toggle_r in [False,True]: - s,m1,m12,swap = self.toJacobiQuartic(toggle_rotation,toggle_altx,toggle_s) - - #print - #print toggle_rotation,toggle_altx,toggle_s - #print m1 - #print m12 - - - if self == self.__class__(): - if self.cofactor == 4: - # Hacks for identity! - if toggle_altx: m12 = 1 - elif toggle_s: m1 = 1 - elif toggle_r: continue - ## BOTH??? - - else: - m12 = 1 - imi = self.isoMagic * self.i - if toggle_rotation: - if toggle_altx: m1 = -imi - else: m1 = +imi - else: - if toggle_altx: m1 = 0 - else: m1 = a-d - - rnum = (d*a*m12-m1) - rden = ((d*a-1)*m12+m1) - if swap: rnum,rden = rden,rnum - - ok,sr = isqrt_i(rnum*rden*self.qnr) - if not ok: continue - sr *= rnum - #print "Works! %d %x" % (swap,sr) - - if negative(sr) != toggle_r: sr = -sr - ret = self.gfToBytes(sr) - if self.elligator(ret) != self and self.elligator(ret) != -self: - print "WRONG!",[toggle_rotation,toggle_altx,toggle_s] - if self.elligator(ret) == -self and self != -self: print "Negated!",[toggle_rotation,toggle_altx,toggle_s] - rets.append(bytes(ret)) - return rets - - @optimized_version_of("encodeSpec") - def encode(self): - """Encode, optimized version""" - return self.gfToBytes(self.toJacobiQuartic()[0]) - - @classmethod - @optimized_version_of("decodeSpec") - def decode(cls,s): - """Decode, optimized version""" - a,d = cls.a,cls.d - s = cls.bytesToGf(s,mustBePositive=True) - - #if s==0: return cls() - s2 = s^2 - den = 1+a*s2 - num = den^2 - 4*d*s2 - isr = isqrt(num*den^2) - altx = 2*s*isr*den*cls.isoMagic - if negative(altx): isr = -isr - x = 2*s *isr^2*den*num - y = (1-a*s^2) * isr*den - - if cls.cofactor==8 and (negative(x*y*cls.isoMagic) or y==0): - raise InvalidEncodingException("x*y is invalid: %d, %d" % (x,y)) - - return cls(x,y) - - @classmethod - def fromJacobiQuartic(cls,s,t,sgn=1): - """Convert point from its Jacobi Quartic representation""" - a,d = cls.a,cls.d - if s==0: return cls() - x = 2*s / (1+a*s^2) - y = (1-a*s^2) / t - return cls(x,sgn*y) - - @optimized_version_of("doubleAndEncodeSpec") - def doubleAndEncode(self): - X,Y,Z,T = self.xyzt() - a,d = self.a,self.d - - if self.cofactor == 8: - # Cofactor 8 version - # Simulate IMAGINE_TWIST because that's how libdecaf does it - X = self.i*X - T = self.i*T - a = -a - d = -d - # TODO: This is only being called for a=-1, so could - # be wrong for a=1 - - e = 2*X*Y - f = Y^2+a*X^2 - g = Y^2-a*X^2 - h = Z^2-d*T^2 - - eim = e*self.isoMagic - inv = 1/(eim*g*f*h) - fh_inv = eim*g*inv*self.i - - if negative(eim*g*fh_inv): - idf = g*self.isoMagic*self.i - bar = f - foo = g - test = eim*f - else: - idf = eim - bar = h - foo = -eim - test = g*h - - if negative(test*fh_inv): bar =- bar - s = idf*(foo+bar)*inv*f*h - - else: - xy = X*Y - h = Z^2-d*T^2 - inv = 1/(xy*h) - if negative(inv*2*xy^2*self.isoMagic): tmp = Y - else: tmp = X - s = tmp^2*h*inv # = X/Y or Y/X, interestingly - - return self.gfToBytes(s,mustBePositive=True) - - @classmethod - def elligatorSpec(cls,r0,fromR=False): - a,d = cls.a,cls.d - if fromR: r = r0 - else: r = cls.qnr * cls.bytesToGf(r0,mustBeProper=False,maskHiBits=True)^2 - - den = (d*r-(d-a))*((d-a)*r-d) - if den == 0: return cls() - n1 = (r+1)*(a-2*d)/den - n2 = r*n1 - if is_square(n1): - sgn,s,t = 1, xsqrt(n1), -(r-1)*(a-2*d)^2 / den - 1 - else: - sgn,s,t = -1, -xsqrt(n2), r*(r-1)*(a-2*d)^2 / den - 1 - - return cls.fromJacobiQuartic(s,t) - - @classmethod - @optimized_version_of("elligatorSpec") - def elligator(cls,r0): - a,d = cls.a,cls.d - r0 = cls.bytesToGf(r0,mustBeProper=False,maskHiBits=True) - r = cls.qnr * r0^2 - den = (d*r-(d-a))*((d-a)*r-d) - num = (r+1)*(a-2*d) - - iss,isri = isqrt_i(num*den) - if iss: sgn,twiddle = 1,1 - else: sgn,twiddle = -1,r0*cls.qnr - isri *= twiddle - s = isri*num - t = -sgn*isri*s*(r-1)*(a-2*d)^2 - 1 - if negative(s) == iss: s = -s - return cls.fromJacobiQuartic(s,t) - - def elligatorInverseBruteForce(self): - """Invert Elligator using SAGE's polynomial solver""" - a,d = self.a,self.d - R. = self.F[] - r = self.qnr * r0^2 - den = (d*r-(d-a))*((d-a)*r-d) - n1 = (r+1)*(a-2*d)/den - n2 = r*n1 - ret = set() - for s2,t in [(n1, -(r-1)*(a-2*d)^2 / den - 1), - (n2,r*(r-1)*(a-2*d)^2 / den - 1)]: - x2 = 4*s2/(1+a*s2)^2 - y = (1-a*s2) / t - - selfT = self - for i in xrange(self.cofactor/2): - xT,yT = selfT - polyX = xT^2-x2 - polyY = yT-y - sx = set(r for r,_ in polyX.numerator().roots()) - sy = set(r for r,_ in polyY.numerator().roots()) - ret = ret.union(sx.intersection(sy)) - - selfT = selfT.torque() - - ret = [self.gfToBytes(r) for r in ret] - - for r in ret: - assert self.elligator(r) in [self,-self] - - ret = [r for r in ret if self.elligator(r) == self] - - return ret - -class Ed25519Point(RistrettoPoint): - F = GF(2^255-19) - d = F(-121665/121666) - a = F(-1) - i = sqrt(F(-1)) - mneg = F(1) - qnr = i - magic = isqrt(a*d-1) - cofactor = 8 - encLen = 32 - - @classmethod - def base(cls): - return cls( 15112221349535400772501151409588531511454012693041857206046113283949847762202, 46316835694926478169428394003475163141307993866256225615783033603165251855960 - ) - -class NegEd25519Point(RistrettoPoint): - F = GF(2^255-19) - d = F(121665/121666) - a = F(1) - i = sqrt(F(-1)) - mneg = F(-1) # TODO checkme vs 1-ad or whatever - qnr = i - magic = isqrt(a*d-1) - cofactor = 8 - encLen = 32 - - @classmethod - def base(cls): - y = cls.F(4/5) - x = sqrt((y^2-1)/(cls.d*y^2-cls.a)) - if negative(x): x = -x - return cls(x,y) - -class IsoEd448Point(RistrettoPoint): - F = GF(2^448-2^224-1) - d = F(39082/39081) - a = F(1) - mneg = F(-1) - qnr = -1 - magic = isqrt(a*d-1) - cofactor = 4 - encLen = 56 - - @classmethod - def base(cls): - return cls( # RFC has it wrong - 345397493039729516374008604150537410266655260075183290216406970281645695073672344430481787759340633221708391583424041788924124567700732, - -363419362147803445274661903944002267176820680343659030140745099590306164083365386343198191849338272965044442230921818680526749009182718 - ) - -class TwistedEd448GoldilocksPoint(Decaf_1_1_Point): - F = GF(2^448-2^224-1) - d = F(-39082) - a = F(-1) - qnr = -1 - cofactor = 4 - encLen = 56 - isoMagic = IsoEd448Point.magic - - @classmethod - def base(cls): - return cls.decodeSpec(Ed448GoldilocksPoint.base().encodeSpec()) - -class Ed448GoldilocksPoint(Decaf_1_1_Point): - F = GF(2^448-2^224-1) - d = F(-39081) - a = F(1) - qnr = -1 - cofactor = 4 - encLen = 56 - isoMagic = IsoEd448Point.magic - - @classmethod - def base(cls): - return 2*cls( - 224580040295924300187604334099896036246789641632564134246125461686950415467406032909029192869357953282578032075146446173674602635247710, 298819210078481492676017930443930673437544040154080242095928241372331506189835876003536878655418784733982303233503462500531545062832660 - ) - -class IsoEd25519Point(Decaf_1_1_Point): - # TODO: twisted iso too! - # TODO: twisted iso might have to IMAGINE_TWIST or whatever - F = GF(2^255-19) - d = F(-121665) - a = F(1) - i = sqrt(F(-1)) - qnr = i - magic = isqrt(a*d-1) - cofactor = 8 - encLen = 32 - isoMagic = Ed25519Point.magic - isoA = Ed25519Point.a - - @classmethod - def base(cls): - return cls.decodeSpec(Ed25519Point.base().encode()) - -class TestFailedException(Exception): pass - -def test(cls,n): - print "Testing curve %s" % cls.__name__ - - specials = [1] - ii = cls.F(-1) - while is_square(ii): - specials.append(ii) - ii = sqrt(ii) - specials.append(ii) - for i in specials: - if negative(cls.F(i)): i = -i - i = enc_le(i,cls.encLen) - try: - Q = cls.decode(i) - QE = Q.encode() - if QE != i: - raise TestFailedException("Round trip special %s != %s" % - (binascii.hexlify(QE),binascii.hexlify(i))) - except NotOnCurveException: pass - except InvalidEncodingException: pass - - - P = cls.base() - Q = cls() - for i in xrange(n): - #print binascii.hexlify(Q.encode()) - QE = Q.encode() - QQ = cls.decode(QE) - if QQ != Q: raise TestFailedException("Round trip %s != %s" % (str(QQ),str(Q))) - - # Testing s -> 1/s: encodes -point on cofactor - s = cls.bytesToGf(QE) - if s != 0: - ss = cls.gfToBytes(1/s,mustBePositive=True) - try: - QN = cls.decode(ss) - if cls.cofactor == 8: - raise TestFailedException("1/s shouldnt work for cofactor 8") - if QN != -Q: - raise TestFailedException("s -> 1/s should negate point for cofactor 4") - except InvalidEncodingException as e: - # Should be raised iff cofactor==8 - if cls.cofactor == 4: - raise TestFailedException("s -> 1/s should work for cofactor 4") - - QT = Q - for h in xrange(cls.cofactor): - QT = QT.torque() - if QT.encode() != QE: - raise TestFailedException("Can't torque %s,%d" % (str(Q),h+1)) - - Q0 = Q + P - if Q0 == Q: raise TestFailedException("Addition doesn't work") - if Q0-P != Q: raise TestFailedException("Subtraction doesn't work") - - r = randint(1,1000) - Q1 = Q0*r - Q2 = Q0*(r+1) - if Q1 + Q0 != Q2: raise TestFailedException("Scalarmul doesn't work") - Q = Q1 - -def testElligator(cls,n): - print "Testing elligator on %s" % cls.__name__ - for i in xrange(n): - r = randombytes(cls.encLen) - P = cls.elligator(r) - if hasattr(P,"invertElligator"): - iv = P.invertElligator() - modr = bytes(cls.gfToBytes(cls.bytesToGf(r,mustBeProper=False,maskHiBits=True))) - iv2 = P.torque().invertElligator() - if modr not in iv: print "Failed to invert Elligator!" - if len(iv) != len(set(iv)): - print "Elligator inverses not unique!", len(set(iv)), len(iv) - if iv != iv2: - print "Elligator is untorqueable!" - #print [binascii.hexlify(j) for j in iv] - #print [binascii.hexlify(j) for j in iv2] - #break - else: - pass # TODO - -def gangtest(classes,n): - print "Gang test",[cls.__name__ for cls in classes] - specials = [1] - ii = classes[0].F(-1) - while is_square(ii): - specials.append(ii) - ii = sqrt(ii) - specials.append(ii) - - for i in xrange(n): - rets = [bytes((cls.base()*i).encode()) for cls in classes] - if len(set(rets)) != 1: - print "Divergence in encode at %d" % i - for c,ret in zip(classes,rets): - print c,binascii.hexlify(ret) - print - - if i < len(specials): r0 = enc_le(specials[i],classes[0].encLen) - else: r0 = randombytes(classes[0].encLen) - - rets = [bytes((cls.elligator(r0)*i).encode()) for cls in classes] - if len(set(rets)) != 1: - print "Divergence in elligator at %d" % i - for c,ret in zip(classes,rets): - print c,binascii.hexlify(ret) - print - -def testDoubleAndEncode(cls,n): - print "Testing doubleAndEncode on %s" % cls.__name__ - for i in xrange(n): - r1 = randombytes(cls.encLen) - r2 = randombytes(cls.encLen) - u = cls.elligator(r1) + cls.elligator(r2) - u.doubleAndEncode() - -testDoubleAndEncode(Ed25519Point,100) -testDoubleAndEncode(NegEd25519Point,100) -testDoubleAndEncode(IsoEd25519Point,100) -testDoubleAndEncode(IsoEd448Point,100) -testDoubleAndEncode(TwistedEd448GoldilocksPoint,100) -#test(Ed25519Point,100) -#test(NegEd25519Point,100) -#test(IsoEd25519Point,100) -#test(IsoEd448Point,100) -#test(TwistedEd448GoldilocksPoint,100) -#test(Ed448GoldilocksPoint,100) -#testElligator(Ed25519Point,100) -#testElligator(NegEd25519Point,100) -#testElligator(IsoEd25519Point,100) -#testElligator(IsoEd448Point,100) -#testElligator(Ed448GoldilocksPoint,100) -#testElligator(TwistedEd448GoldilocksPoint,100) -#gangtest([IsoEd448Point,TwistedEd448GoldilocksPoint,Ed448GoldilocksPoint],100) -#gangtest([Ed25519Point,IsoEd25519Point],100) diff --git a/net/gurk-rs/files/vendor/curve25519-dalek/.cargo-checksum.json b/net/gurk-rs/files/vendor/curve25519-dalek/.cargo-checksum.json deleted file mode 100644 index 26ddeea..0000000 --- a/net/gurk-rs/files/vendor/curve25519-dalek/.cargo-checksum.json +++ /dev/null @@ -1 +0,0 @@ -{"files":{"CHANGELOG.md":"7b436de74cc950b84ec3a82b0d77cb144c38ba701029597718d03e156934beff","CODE_OF_CONDUCT.md":"3282ab0de79898b07eff6595f46024f8ddc0e21eef8d61b4912f95998468eb53","CONTRIBUTING.md":"8ef9d405ab43c54787636b9d29b560f61c94773f726694ec37998dc66e43a788","Cargo.toml":"36b91df15a3296bf979467730894b8dac7616d35a34802fd939046a81513988f","LICENSE":"cca0bd3c4fcdba74145ef9d49c62337e2c9fbf9368288f11d0547f1b0273219f","Makefile":"3bdd6d7b89b2a1d0e69feab4b8f11514aef2b14c180726750e5de413b728d544","README.md":"10b65bbebef753a0ad01c8fbc1fc4a7ed309d5b4724cb4ddcbdb0c2f66bc150d","benches/dalek_benchmarks.rs":"f7f91d84391b4b1739e825b5398a85af89d6868c7278e277fb7356e717e0e42f","docs/assets/dalek-logo-clear.png":"6babf6c1cdb10af05142501af2c4947765ef7839f87b91bc683165a8369fc3f4","docs/assets/dalek-logo.png":"a4a0451c5a2c0417584dc7d7d1388283b3bf9aeef89ee64ee073cdcd83c1a0f1","docs/assets/dalek-logo.svg":"22534b6935cfb8ccd6512ee13006700c451b28feb13acc137668caf00901633f","docs/assets/rustdoc-include-katex-header.html":"348752aa412e1dc774427f20d8d51ca0b2923979d4829cbd493d76e499f2674e","docs/avx2-notes.md":"47e41778044529299f78906d99d6dfe9c0400acf5ad32e519fa54b6d6bea36dc","docs/ifma-notes.md":"7ca18607cafca402b832c313de42763df9cf1f8c9ca0ac58621322b5e33e8461","docs/parallel-formulas.md":"c3f63ab62c11b36a917e4d0eeb6392705502910b4ebc8b50d46a9122c6351332","src/backend/mod.rs":"d7529363ef1233548d2497c94eb25508fa776d8a4405a821a20526992a99f6c6","src/backend/serial/curve_models/mod.rs":"089669be41b1972040e16170135c8b758cd88923eccd186581e83cb19482451e","src/backend/serial/fiat_u32/field.rs":"282494af2f9d16a01521aaee1d57c396270b6dbd1b8a1be298248623e2eb2e06","src/backend/serial/fiat_u32/mod.rs":"6e36a757f0f804caaebb5a2f0c04754589740279160890d592287edc7d65efcf","src/backend/serial/fiat_u64/field.rs":"e215d97a0e90ea810fae0ec32be2e20c01f998ae0a8bb4d94dbdb1b1c88b610c","src/backend/serial/fiat_u64/mod.rs":"6e6f773aa9669a740519d2256421734ddfee60cd6ad7f45156b6b5201c10487d","src/backend/serial/mod.rs":"881bc35006031abd792de9cd6c0320e7a3b053d37598271d3be569ba7e71bb12","src/backend/serial/scalar_mul/mod.rs":"396429a4f10e8d1d7851c341781fdafc814f39afc2bef0078ef1dee9dced8a8b","src/backend/serial/scalar_mul/pippenger.rs":"bfab409306c0f88bbbe0bffedf3f66ccc011e9c1f6caa46aef1ce9727c48d3b6","src/backend/serial/scalar_mul/precomputed_straus.rs":"b735367646cd08a31d127882b623d22e77fda4197557d2e5f1bbf34e8da587db","src/backend/serial/scalar_mul/straus.rs":"93b95561304b3f464e2a0866424dfd3770515533d2687ef85ca5519503db02a6","src/backend/serial/scalar_mul/variable_base.rs":"1f04ca6d725ede8135a31ab7335c6d84c6b76ebce2b0ffa52fdf5c52c1fb2ac5","src/backend/serial/scalar_mul/vartime_double_base.rs":"d9a7033c13deb7390d8d34f694336cf648bddab3607d4b4db7e1f2d3d7a678e6","src/backend/serial/u32/constants.rs":"d539cc033568d49c654b73ec24f92a8894a1847182608f8a5ebaaee7363411b9","src/backend/serial/u32/field.rs":"cc42a8f0e573b3fdc73deaf0152361e39f14f6e143064c6c9a470c73312f0cce","src/backend/serial/u32/mod.rs":"14fabb2034c68094df508c19517db14e5e3b956b5dac93bd0dd3c125f47f396e","src/backend/serial/u32/scalar.rs":"a797284c92f36626e70c877cf32da6b79b44c0ca634a3bc8754803f0cae7f600","src/backend/serial/u64/constants.rs":"a6fd2ec0abb985aea30fa320c843e8f5c208d05073f2bde420f100c65e883d07","src/backend/serial/u64/field.rs":"666ea448453b9f72c8b3197fed8c0a0771488425673c48e012d9709a054a922d","src/backend/serial/u64/mod.rs":"b4aab9c62cf39bafc976b2e03bea503f120b125c30eb0e9e5d5f257b08a3eda4","src/backend/serial/u64/scalar.rs":"6a5a76eaf5b560e71310e9d67c8ca9ba2704b4f771760ce83270d85f0cb62a19","src/backend/vector/avx2/constants.rs":"2294ac59a6cc974fc879324cbb1edc7c90b758354669ce3c77ec38f31664b141","src/backend/vector/avx2/edwards.rs":"0f9aae021fa8ef300fa3ec8faf13b0cfc666738a5744a49a4c6f2bb4964a6861","src/backend/vector/avx2/field.rs":"abc7dd5248c8136b7edb94a901bdb24cdc84d243599734b4733ef61b8f4c9f5b","src/backend/vector/avx2/mod.rs":"0fd755b94bcec333bd4ef2bedad13a591d9d785bed47bd809930c74b4c580c06","src/backend/vector/ifma/constants.rs":"b1acd2c8674a5e710d753dfb159f0ea507585f2903f49f6f97802e53f5584bcf","src/backend/vector/ifma/edwards.rs":"c3b55fa23b117a83dee32201131f64bc4a050d3e96de29be345ef41b0291ea39","src/backend/vector/ifma/field.rs":"a291bb40ce2a91ed6e996d99a322ca7198614f81d0f47cdc2c93132139276d62","src/backend/vector/ifma/mod.rs":"385c894444884ec90052143502b8e37d7f36416e1dfd7e31ec588914d1a26527","src/backend/vector/mod.rs":"22324c0c34d9f7276d0f4e0d87e1e6aa3db0a3da1c3b92ffda13cce39ca698ce","src/backend/vector/scalar_mul/mod.rs":"3b339edd3512ea91fc8542dc2b13e72b2c146ef6d3e29a595b62a269c96037be","src/backend/vector/scalar_mul/pippenger.rs":"e87703ea516006fadc567fa5b75b6c5fee6ec5a9ad27368726fae0747e471368","src/backend/vector/scalar_mul/precomputed_straus.rs":"982acacbf478c5ee0f7e0bc5650b22960655550ac08b888e3477fc786ce0c959","src/backend/vector/scalar_mul/straus.rs":"43318d83671748335a518e7e0753457a8be2b1f988b1d7974a09212d1b10c807","src/backend/vector/scalar_mul/variable_base.rs":"c638bb2975b421d2bb6f29589c2e9b46831592b835851fed43569a8a5204c36e","src/backend/vector/scalar_mul/vartime_double_base.rs":"50200972a56ecf2ac6027d8eaa1dc07777c7a935a89756b3f1ffca020cd6313a","src/constants.rs":"e5ddee4e4c905320af32bf1f246fe4092d51f9758b11103569d7778d19d393e0","src/edwards.rs":"415bd2d04c1c2092e95204539396b6f4e7db540568dcc5059743db4a0cabe042","src/field.rs":"7baf29e0dc1a83668831c0fb266593a58e0e327e74b9f67884b396d7679ae501","src/lib.rs":"c022c9fae48b9b97176527298d277b1b14948901304bb8e529e0f63675031dc8","src/macros.rs":"893faee478e19905b54eefafc8d8db38e90084ef185bdfb96e51c10f7038ba6e","src/montgomery.rs":"b2d81976c9f89c2bc3e2b882c46b26297c3926727f841599bc6a9badb3268168","src/prelude.rs":"029695a58dec3a1c97fe0ca7611e81a81c6fb0b5b570f224bcda25f142288a0f","src/ristretto.rs":"d59e62dcef3faf78fc953ec6dd0068f64c6495c873d16d3bbc9bef6b141470e3","src/scalar.rs":"897f9ca64fae7c5739e7e612dee47d17789b2d29acb8c2416384862fe2683b4b","src/traits.rs":"973b467960df61d70a16b646a67c2e7de641ebe5c691bea5ee43e28d1ed65fe4","src/window.rs":"fd593bbee8bb598e96fa198cd7821a132d8baff9efc5e6c33e5f82c111420fe4","vendor/ristretto.sage":"a2f4309ada0afa4156f5a660be4384a0f1f332c12f836199124f48e89310344d"},"package":"639891fde0dbea823fc3d798a0fdf9d2f9440a42d64a78ab3488b0ca025117b3"} \ No newline at end of file diff --git a/net/gurk-rs/files/vendor/curve25519-dalek/CHANGELOG.md b/net/gurk-rs/files/vendor/curve25519-dalek/CHANGELOG.md deleted file mode 100644 index 1d42492..0000000 --- a/net/gurk-rs/files/vendor/curve25519-dalek/CHANGELOG.md +++ /dev/null @@ -1,169 +0,0 @@ -# Changelog - -Entries are listed in reverse chronological order per undeprecated -major series. - -## 3.x series - -### 3.1.0 - -* Add support for the Elligator2 encoding for Edwards points. -* Add two optional formally-verified field arithmetic backends which - use the Fiat Crypto project's Rust code, which is generated from - proofs of functional correctness checked by the Coq theorem proving - system. -* Add support for additional sizes of precomputed tables for basepoint - scalar multiplication. -* Fix an unused import. -* Add support for using the `zeroize` traits with all point types. - Note that points are not automatically zeroized on Drop, but that - consumers of `curve25519-dalek` should call these methods manually - when needed. - -### 3.0.2 - -* Fixes to make using alloc+no_std possible for stable Rust. - -### 3.0.1 - -* Update the optional `packed-simd` dependency to rely on a newer, - maintained version of the `packed-simd-2` crate. - -### 3.0.0 - -* Update the `digest` dependency to `0.9`. This requires a major version - because the `digest` traits are part of the public API, but there are - otherwise no changes to the API. - -## 2.x series - -### 2.1.2 - -* Fixes to make using alloc+no_std possible for stable Rust. - -### 2.1.1 - -* Update the optional `packed-simd` dependency to rely on a newer, - maintained version of the `packed-simd-2` crate. - -### 2.1.0 - -* Make `Scalar::from_bits` a `const fn`, allowing its use in `const` contexts. - -### 2.0.0 - -* Fix a data modeling error in the `serde` feature pointed out by Trevor Perrin - which caused points and scalars to be serialized with length fields rather - than as fixed-size 32-byte arrays. This is a breaking change, but it fixes - compatibility with `serde-json` and ensures that the `serde-bincode` encoding - matches the conventional encoding for X/Ed25519. -* Update `rand_core` to `0.5`, allowing use with new `rand` versions. -* Switch from `clear_on_drop` to `zeroize` (by Tony Arcieri). -* Require `subtle = ^2.2.1` and remove the note advising nightly Rust, which is - no longer required as of that version of `subtle`. See the `subtle` - changelog for more details. -* Update `README.md` for `2.x` series. -* Remove the `build.rs` hack which loaded the entire crate into its own - `build.rs` to generate constants, and keep the constants in the source code. - -The only significant change is the data model change to the `serde` feature; -besides the `rand_core` version bump, there are no other user-visible changes. - -## 1.x series - -### 1.2.6 - -* Fixes to make using alloc+no_std possible for stable Rust. - -### 1.2.5 - -* Update the optional `packed-simd` dependency to rely on a newer, - maintained version of the `packed-simd-2` crate. - -### 1.2.4 - -* Specify a semver bound for `clear_on_drop` rather than an exact version, - addressing an issue where changes to inline assembly in rustc prevented - `clear_on_drop` from working without an update. - -### 1.2.3 - -* Fix an issue identified by a Quarkslab audit (and Jack Grigg), where manually - constructing unreduced `Scalar` values, as needed for X/Ed25519, and then - performing scalar/scalar arithmetic could compute incorrect results. -* Switch to upstream Rust intrinsics for the IFMA backend now that they exist in - Rust and don't need to be defined locally. -* Ensure that the NAF computation works correctly, even for parameters never - used elsewhere in the codebase. -* Minor refactoring to EdwardsPoint decompression. -* Fix broken links in documentation. -* Fix compilation on nightly broken due to changes to the `#[doc(include)]` path - root (not quite correctly done in 1.2.2). - -### 1.2.2 - -* Fix a typo in an internal doc-comment. -* Add the "crypto" tag to crate metadata. -* Fix compilation on nightly broken due to changes to the `#[doc(include)]` path - root. - -### 1.2.1 - -* Fix a bug in bucket index calculations in the Pippenger multiscalar algorithm - for very large input sizes. -* Add a more extensive randomized multiscalar multiplication consistency check - to the test suite to prevent regressions. -* Ensure that that multiscalar and NAF computations work correctly on extremal - `Scalar` values constructed via `from_bits`. - -### 1.2.0 - -* New multiscalar multiplication algorithm with better performance for - large problem sizes. The backend algorithm is selected - transparently using the size hints of the input iterators, so no - changes are required for client crates to start using it. -* Equality of Edwards points is now checked in projective coordinates. -* Serde can now be used with `no_std`. - -### 1.1.4 - -* Fix typos in documentation comments. -* Remove unnecessary `Default` bound on `Scalar::from_hash`. - -### 1.1.3 - -* Reverts the change in 1.1.0 to allow owned and borrowed RNGs, which caused a breakage due to a subtle interaction with ownership rules. (The `RngCore` change is retained). - -### 1.1.2 - -* Disabled KaTeX on `docs.rs` pending proper [support upstream](https://github.com/rust-lang/docs.rs/issues/302). - -## 1.1.1 - -* Fixed an issue related to `#[cfg(rustdoc)]` which prevented documenting multiple backends. - -### 1.1.0 - -* Adds support for precomputation for multiscalar multiplication. -* Restructures the internal source tree into `serial` and `vector` backends (no change to external API). -* Adds a new IFMA backend which sets speed records. -* The `avx2_backend` feature is now an alias for the `simd_backend` feature, which autoselects an appropriate vector backend (currently AVX2 or IFMA). -* Replaces the `rand` dependency with `rand_core`. -* Generalizes trait bounds on `RistrettoPoint::random()` and `Scalar::random()` to allow owned and borrowed RNGs and to allow `RngCore` instead of `Rng`. - -### 1.0.3 - -* Adds `ConstantTimeEq` implementation for compressed points. - -### 1.0.2 - -* Fixes a typo in the naming of variables in Ristretto formulas (no change to functionality). - -### 1.0.1 - -* Depends on the stable `2.0` version of `subtle` instead of `2.0.0-pre.0`. - -### 1.0.0 - -Initial stable release. Yanked due to a dependency mistake (see above). - diff --git a/net/gurk-rs/files/vendor/curve25519-dalek/CODE_OF_CONDUCT.md b/net/gurk-rs/files/vendor/curve25519-dalek/CODE_OF_CONDUCT.md deleted file mode 100644 index a802fde..0000000 --- a/net/gurk-rs/files/vendor/curve25519-dalek/CODE_OF_CONDUCT.md +++ /dev/null @@ -1,8 +0,0 @@ -# Code of Conduct - -We follow the [Rust Code of Conduct](http://www.rust-lang.org/conduct.html), -with the following additional clauses: - -* We respect the rights to privacy and anonymity for contributors and people in - the community. If someone wishes to contribute under a pseudonym different to - their primary identity, that wish is to be respected by all contributors. diff --git a/net/gurk-rs/files/vendor/curve25519-dalek/CONTRIBUTING.md b/net/gurk-rs/files/vendor/curve25519-dalek/CONTRIBUTING.md deleted file mode 100644 index d4e0ff8..0000000 --- a/net/gurk-rs/files/vendor/curve25519-dalek/CONTRIBUTING.md +++ /dev/null @@ -1,19 +0,0 @@ -# Contributing to curve25519-dalek - -If you have questions or comments, please feel free to email the -authors. - -For feature requests, suggestions, and bug reports, please open an issue on -[our Github](https://github.com/dalek-cryptography/curve25519-dalek). (Or, send us -an email if you're opposed to using Github for whatever reason.) - -Patches are welcomed as pull requests on -[our Github](https://github.com/dalek-cryptography/curve25519-dalek), as well as by -email (preferably sent to all of the authors listed in `Cargo.toml`). - -All issues on curve25519-dalek are mentored, if you want help with a bug just -ask @isislovecruft or @hdevalence. - -Some issues are easier than others. The `easy` label can be used to find the -easy issues. If you want to work on an issue, please leave a comment so that we -can assign it to you! diff --git a/net/gurk-rs/files/vendor/curve25519-dalek/Cargo.toml b/net/gurk-rs/files/vendor/curve25519-dalek/Cargo.toml deleted file mode 100644 index cbeb3c9..0000000 --- a/net/gurk-rs/files/vendor/curve25519-dalek/Cargo.toml +++ /dev/null @@ -1,97 +0,0 @@ -# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO -# -# When uploading crates to the registry Cargo will automatically -# "normalize" Cargo.toml files for maximal compatibility -# with all versions of Cargo and also rewrite `path` dependencies -# to registry (e.g., crates.io) dependencies -# -# If you believe there's an error in this file please file an -# issue against the rust-lang/cargo repository. If you're -# editing this file be aware that the upstream Cargo.toml -# will likely look very different (and much more reasonable) - -[package] -name = "curve25519-dalek" -version = "3.1.0" -authors = ["Isis Lovecruft ", "Henry de Valence "] -exclude = ["**/.gitignore", ".gitignore", ".travis.yml"] -description = "A pure-Rust implementation of group operations on ristretto255 and Curve25519" -homepage = "https://dalek.rs/curve25519-dalek" -documentation = "https://docs.rs/curve25519-dalek" -readme = "README.md" -keywords = ["cryptography", "crypto", "ristretto", "curve25519", "ristretto255"] -categories = ["cryptography", "no-std"] -license = "BSD-3-Clause" -repository = "https://github.com/dalek-cryptography/curve25519-dalek" -[package.metadata.docs.rs] -features = ["nightly", "simd_backend"] - -[[bench]] -name = "dalek_benchmarks" -harness = false -[dependencies.byteorder] -version = "^1.2.3" -features = ["i128"] -default-features = false - -[dependencies.digest] -version = "0.9" -default-features = false - -[dependencies.fiat-crypto] -version = "0.1.6" -optional = true - -[dependencies.packed_simd] -version = "0.3.4" -features = ["into_bits"] -optional = true -package = "packed_simd_2" - -[dependencies.rand_core] -version = "0.5" -default-features = false - -[dependencies.serde] -version = "1.0" -features = ["derive"] -optional = true -default-features = false - -[dependencies.subtle] -version = "^2.2.1" -default-features = false - -[dependencies.zeroize] -version = "1" -default-features = false -[dev-dependencies.bincode] -version = "1" - -[dev-dependencies.criterion] -version = "0.3.0" - -[dev-dependencies.hex] -version = "0.4.2" - -[dev-dependencies.rand] -version = "0.7" - -[dev-dependencies.sha2] -version = "0.9" -default-features = false - -[features] -alloc = ["zeroize/alloc"] -avx2_backend = ["simd_backend"] -default = ["std", "u64_backend"] -fiat_u32_backend = ["fiat-crypto"] -fiat_u64_backend = ["fiat-crypto"] -nightly = ["subtle/nightly"] -simd_backend = ["nightly", "u64_backend", "packed_simd"] -std = ["alloc", "subtle/std", "rand_core/std"] -u32_backend = [] -u64_backend = [] -[badges.travis-ci] -branch = "master" -repository = "dalek-cryptography/curve25519-dalek" diff --git a/net/gurk-rs/files/vendor/curve25519-dalek/LICENSE b/net/gurk-rs/files/vendor/curve25519-dalek/LICENSE deleted file mode 100644 index ff34757..0000000 --- a/net/gurk-rs/files/vendor/curve25519-dalek/LICENSE +++ /dev/null @@ -1,65 +0,0 @@ -Copyright (c) 2016-2021 isis agora lovecruft. All rights reserved. -Copyright (c) 2016-2021 Henry de Valence. All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are -met: - -1. Redistributions of source code must retain the above copyright -notice, this list of conditions and the following disclaimer. - -2. Redistributions in binary form must reproduce the above copyright -notice, this list of conditions and the following disclaimer in the -documentation and/or other materials provided with the distribution. - -3. Neither the name of the copyright holder nor the names of its -contributors may be used to endorse or promote products derived from -this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS -IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED -TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A -PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED -TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR -PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF -LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -======================================================================== - -Portions of curve25519-dalek were originally derived from Adam Langley's -Go ed25519 implementation, found at , -under the following licence: - -======================================================================== - -Copyright (c) 2012 The Go Authors. All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are -met: - - * Redistributions of source code must retain the above copyright -notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above -copyright notice, this list of conditions and the following disclaimer -in the documentation and/or other materials provided with the -distribution. - * Neither the name of Google Inc. nor the names of its -contributors may be used to endorse or promote products derived from -this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS -IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED -TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A -PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER -OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, -EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR -PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF -LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/net/gurk-rs/files/vendor/curve25519-dalek/Makefile b/net/gurk-rs/files/vendor/curve25519-dalek/Makefile deleted file mode 100644 index e447175..0000000 --- a/net/gurk-rs/files/vendor/curve25519-dalek/Makefile +++ /dev/null @@ -1,8 +0,0 @@ -FEATURES := nightly yolocrypto avx2_backend - -doc: - cargo rustdoc --features "$(FEATURES)" -- --html-in-header docs/assets/rustdoc-include-katex-header.html - -doc-internal: - cargo rustdoc --features "$(FEATURES)" -- --html-in-header docs/assets/rustdoc-include-katex-header.html --document-private-items - diff --git a/net/gurk-rs/files/vendor/curve25519-dalek/README.md b/net/gurk-rs/files/vendor/curve25519-dalek/README.md deleted file mode 100644 index 19679f9..0000000 --- a/net/gurk-rs/files/vendor/curve25519-dalek/README.md +++ /dev/null @@ -1,220 +0,0 @@ - -# curve25519-dalek [![](https://img.shields.io/crates/v/curve25519-dalek.svg)](https://crates.io/crates/curve25519-dalek) [![](https://img.shields.io/badge/dynamic/json.svg?label=docs&uri=https%3A%2F%2Fcrates.io%2Fapi%2Fv1%2Fcrates%2Fcurve25519-dalek%2Fversions&query=%24.versions%5B0%5D.num&colorB=4F74A6)](https://doc.dalek.rs) [![](https://travis-ci.org/dalek-cryptography/curve25519-dalek.svg?branch=master)](https://travis-ci.org/dalek-cryptography/curve25519-dalek) - - - -**A pure-Rust implementation of group operations on Ristretto and Curve25519.** - -`curve25519-dalek` is a library providing group operations on the Edwards and -Montgomery forms of Curve25519, and on the prime-order Ristretto group. - -`curve25519-dalek` is not intended to provide implementations of any particular -crypto protocol. Rather, implementations of those protocols (such as -[`x25519-dalek`][x25519-dalek] and [`ed25519-dalek`][ed25519-dalek]) should use -`curve25519-dalek` as a library. - -`curve25519-dalek` is intended to provide a clean and safe _mid-level_ API for use -implementing a wide range of ECC-based crypto protocols, such as key agreement, -signatures, anonymous credentials, rangeproofs, and zero-knowledge proof -systems. - -In particular, `curve25519-dalek` implements Ristretto, which constructs a -prime-order group from a non-prime-order Edwards curve. This provides the -speed and safety benefits of Edwards curve arithmetic, without the pitfalls of -cofactor-related abstraction mismatches. - -# Documentation - -The semver-stable, public-facing `curve25519-dalek` API is documented -[here][docs-external]. In addition, the unstable internal implementation -details are documented [here][docs-internal]. - -The `curve25519-dalek` documentation requires a custom HTML header to include -KaTeX for math support. Unfortunately `cargo doc` does not currently support -this, but docs can be built using -```sh -make doc -make doc-internal -``` - -# Use - -To import `curve25519-dalek`, add the following to the dependencies section of -your project's `Cargo.toml`: -```toml -curve25519-dalek = "3" -``` - -The sole breaking change in the `3.x` series was an update to the `digest` -version, and in terms of non-breaking changes it includes: - -* support for using `alloc` instead of `std` on stable Rust, -* the Elligator2 encoding for Edwards points, -* a fix to use `packed_simd2`, -* various documentation fixes and improvements, -* support for configurably-sized, precomputed lookup tables for basepoint scalar - multiplication, -* two new formally-verified field arithmetic backends which use the Fiat Crypto - Rust code, which is generated from proofs of functional correctness checked by - the Coq theorem proving system, and -* support for explicitly calling the `zeroize` traits for all point types. - -The `2.x` series has API almost entirely unchanged from the `1.x` series, -except that: - -* an error in the data modeling for the (optional) `serde` feature was - corrected, so that when the `2.x`-series `serde` implementation is used - with `serde-bincode`, the derived serialization matches the usual X/Ed25519 - formats; -* the `rand` version was updated. - -See `CHANGELOG.md` for more details. - -# Backends and Features - -The `nightly` feature enables features available only when using a Rust nightly -compiler. In particular, it is required for rendering documentation and for -the SIMD backends. - -Curve arithmetic is implemented using one of the following backends: - -* a `u32` backend using serial formulas and `u64` products; -* a `u64` backend using serial formulas and `u128` products; -* an `avx2` backend using [parallel formulas][parallel_doc] and `avx2` instructions (sets speed records); -* an `ifma` backend using [parallel formulas][parallel_doc] and `ifma` instructions (sets speed records); - -By default the `u64` backend is selected. To select a specific backend, use: -```sh -cargo build --no-default-features --features "std u32_backend" -cargo build --no-default-features --features "std u64_backend" -# Requires nightly, RUSTFLAGS="-C target_feature=+avx2" to use avx2 -cargo build --no-default-features --features "std simd_backend" -# Requires nightly, RUSTFLAGS="-C target_feature=+avx512ifma" to use ifma -cargo build --no-default-features --features "std simd_backend" -``` -Crates using `curve25519-dalek` can either select a backend on behalf of their -users, or expose feature flags that control the `curve25519-dalek` backend. - -The `std` feature is enabled by default, but it can be disabled for no-`std` -builds using `--no-default-features`. Note that this requires explicitly -selecting an arithmetic backend using one of the `_backend` features. -If no backend is selected, compilation will fail. - -# Safety - -The `curve25519-dalek` types are designed to make illegal states -unrepresentable. For example, any instance of an `EdwardsPoint` is -guaranteed to hold a point on the Edwards curve, and any instance of a -`RistrettoPoint` is guaranteed to hold a valid point in the Ristretto -group. - -All operations are implemented using constant-time logic (no -secret-dependent branches, no secret-dependent memory accesses), -unless specifically marked as being variable-time code. -We believe that our constant-time logic is lowered to constant-time -assembly, at least on `x86_64` targets. - -As an additional guard against possible future compiler optimizations, -the `subtle` crate places an optimization barrier before every -conditional move or assignment. More details can be found in [the -documentation for the `subtle` crate][subtle_doc]. - -Some functionality (e.g., multiscalar multiplication or batch -inversion) requires heap allocation for temporary buffers. All -heap-allocated buffers of potentially secret data are explicitly -zeroed before release. - -However, we do not attempt to zero stack data, for two reasons. -First, it's not possible to do so correctly: we don't have control -over stack allocations, so there's no way to know how much data to -wipe. Second, because `curve25519-dalek` provides a mid-level API, -the correct place to start zeroing stack data is likely not at the -entrypoints of `curve25519-dalek` functions, but at the entrypoints of -functions in other crates. - -The implementation is memory-safe, and contains no significant -`unsafe` code. The SIMD backend uses `unsafe` internally to call SIMD -intrinsics. These are marked `unsafe` only because invoking them on an -inappropriate CPU would cause `SIGILL`, but the entire backend is only -compiled with appropriate `target_feature`s, so this cannot occur. - -# Performance - -Benchmarks are run using [`criterion.rs`][criterion]: - -```sh -cargo bench --no-default-features --features "std u32_backend" -cargo bench --no-default-features --features "std u64_backend" -# Uses avx2 or ifma only if compiled for an appropriate target. -export RUSTFLAGS="-C target_cpu=native" -cargo bench --no-default-features --features "std simd_backend" -``` - -Performance is a secondary goal behind correctness, safety, and -clarity, but we aim to be competitive with other implementations. - -# FFI - -Unfortunately, we have no plans to add FFI to `curve25519-dalek` directly. The -reason is that we use Rust features to provide an API that maintains safety -invariants, which are not possible to maintain across an FFI boundary. For -instance, as described in the _Safety_ section above, invalid points are -impossible to construct, and this would not be the case if we exposed point -operations over FFI. - -However, `curve25519-dalek` is designed as a *mid-level* API, aimed at -implementing other, higher-level primitives. Instead of providing FFI at the -mid-level, our suggestion is to implement the higher-level primitive (a -signature, PAKE, ZKP, etc) in Rust, using `curve25519-dalek` as a dependency, -and have that crate provide a minimal, byte-buffer-oriented FFI specific to -that primitive. - -# Contributing - -Please see [CONTRIBUTING.md][contributing]. - -Patches and pull requests should be make against the `develop` -branch, **not** `master`. - -# About - -**SPOILER ALERT:** *The Twelfth Doctor's first encounter with the Daleks is in -his second full episode, "Into the Dalek". A beleaguered ship of the "Combined -Galactic Resistance" has discovered a broken Dalek that has turned "good", -desiring to kill all other Daleks. The Doctor, Clara and a team of soldiers -are miniaturized and enter the Dalek, which the Doctor names Rusty. They -repair the damage, but accidentally restore it to its original nature, causing -it to go on the rampage and alert the Dalek fleet to the whereabouts of the -rebel ship. However, the Doctor manages to return Rusty to its previous state -by linking his mind with the Dalek's: Rusty shares the Doctor's view of the -universe's beauty, but also his deep hatred of the Daleks. Rusty destroys the -other Daleks and departs the ship, determined to track down and bring an end -to the Dalek race.* - -`curve25519-dalek` is authored by Isis Agora Lovecruft and Henry de Valence. - -Portions of this library were originally a port of [Adam Langley's -Golang ed25519 library](https://github.com/agl/ed25519), which was in -turn a port of the reference `ref10` implementation. Most of this code, -including the 32-bit field arithmetic, has since been rewritten. - -The fast `u32` and `u64` scalar arithmetic was implemented by Andrew Moon, and -the addition chain for scalar inversion was provided by Brian Smith. The -optimised batch inversion was contributed by Sean Bowe and Daira Hopwood. - -The `no_std` and `zeroize` support was contributed by Tony Arcieri. - -Thanks also to Ashley Hauck, Lucas Salibian, and Manish Goregaokar for their -contributions. - -[ed25519-dalek]: https://github.com/dalek-cryptography/ed25519-dalek -[x25519-dalek]: https://github.com/dalek-cryptography/x25519-dalek -[contributing]: https://github.com/dalek-cryptography/curve25519-dalek/blob/master/CONTRIBUTING.md -[docs-external]: https://doc.dalek.rs/curve25519_dalek/ -[docs-internal]: https://doc-internal.dalek.rs/curve25519_dalek/ -[criterion]: https://github.com/japaric/criterion.rs -[parallel_doc]: https://doc-internal.dalek.rs/curve25519_dalek/backend/vector/avx2/index.html -[subtle_doc]: https://doc.dalek.rs/subtle/ diff --git a/net/gurk-rs/files/vendor/curve25519-dalek/benches/dalek_benchmarks.rs b/net/gurk-rs/files/vendor/curve25519-dalek/benches/dalek_benchmarks.rs deleted file mode 100644 index 136d0e7..0000000 --- a/net/gurk-rs/files/vendor/curve25519-dalek/benches/dalek_benchmarks.rs +++ /dev/null @@ -1,363 +0,0 @@ -#![allow(non_snake_case)] - -extern crate rand; -use rand::rngs::OsRng; -use rand::thread_rng; - -#[macro_use] -extern crate criterion; - -use criterion::measurement::Measurement; -use criterion::BatchSize; -use criterion::Criterion; -use criterion::{BenchmarkGroup, BenchmarkId}; - -extern crate curve25519_dalek; - -use curve25519_dalek::constants; -use curve25519_dalek::scalar::Scalar; - -static BATCH_SIZES: [usize; 5] = [1, 2, 4, 8, 16]; -static MULTISCALAR_SIZES: [usize; 13] = [1, 2, 4, 8, 16, 32, 64, 128, 256, 384, 512, 768, 1024]; - -mod edwards_benches { - use super::*; - - use curve25519_dalek::edwards::EdwardsPoint; - - fn compress(c: &mut Criterion) { - let B = &constants::ED25519_BASEPOINT_POINT; - c.bench_function("EdwardsPoint compression", move |b| b.iter(|| B.compress())); - } - - fn decompress(c: &mut Criterion) { - let B_comp = &constants::ED25519_BASEPOINT_COMPRESSED; - c.bench_function("EdwardsPoint decompression", move |b| { - b.iter(|| B_comp.decompress().unwrap()) - }); - } - - fn consttime_fixed_base_scalar_mul(c: &mut Criterion) { - let B = &constants::ED25519_BASEPOINT_TABLE; - let s = Scalar::from(897987897u64).invert(); - c.bench_function("Constant-time fixed-base scalar mul", move |b| { - b.iter(|| B * &s) - }); - } - - fn consttime_variable_base_scalar_mul(c: &mut Criterion) { - let B = &constants::ED25519_BASEPOINT_POINT; - let s = Scalar::from(897987897u64).invert(); - c.bench_function("Constant-time variable-base scalar mul", move |b| { - b.iter(|| B * s) - }); - } - - fn vartime_double_base_scalar_mul(c: &mut Criterion) { - c.bench_function("Variable-time aA+bB, A variable, B fixed", |bench| { - let mut rng = thread_rng(); - let A = &Scalar::random(&mut rng) * &constants::ED25519_BASEPOINT_TABLE; - bench.iter_batched( - || (Scalar::random(&mut rng), Scalar::random(&mut rng)), - |(a, b)| EdwardsPoint::vartime_double_scalar_mul_basepoint(&a, &A, &b), - BatchSize::SmallInput, - ); - }); - } - - criterion_group! { - name = edwards_benches; - config = Criterion::default(); - targets = - compress, - decompress, - consttime_fixed_base_scalar_mul, - consttime_variable_base_scalar_mul, - vartime_double_base_scalar_mul, - } -} - -mod multiscalar_benches { - use super::*; - - use curve25519_dalek::edwards::EdwardsPoint; - use curve25519_dalek::edwards::VartimeEdwardsPrecomputation; - use curve25519_dalek::traits::MultiscalarMul; - use curve25519_dalek::traits::VartimeMultiscalarMul; - use curve25519_dalek::traits::VartimePrecomputedMultiscalarMul; - - fn construct_scalars(n: usize) -> Vec { - let mut rng = thread_rng(); - (0..n).map(|_| Scalar::random(&mut rng)).collect() - } - - fn construct_points(n: usize) -> Vec { - let mut rng = thread_rng(); - (0..n) - .map(|_| &Scalar::random(&mut rng) * &constants::ED25519_BASEPOINT_TABLE) - .collect() - } - - fn construct(n: usize) -> (Vec, Vec) { - (construct_scalars(n), construct_points(n)) - } - - fn consttime_multiscalar_mul(c: &mut BenchmarkGroup) { - for multiscalar_size in &MULTISCALAR_SIZES { - c.bench_with_input( - BenchmarkId::new( - "Constant-time variable-base multiscalar multiplication", - *multiscalar_size, - ), - &multiscalar_size, - |b, &&size| { - let points = construct_points(size); - // This is supposed to be constant-time, but we might as well - // rerandomize the scalars for every call just in case. - b.iter_batched( - || construct_scalars(size), - |scalars| EdwardsPoint::multiscalar_mul(&scalars, &points), - BatchSize::SmallInput, - ); - }, - ); - } - } - - fn vartime_multiscalar_mul(c: &mut BenchmarkGroup) { - for multiscalar_size in &MULTISCALAR_SIZES { - c.bench_with_input( - BenchmarkId::new( - "Variable-time variable-base multiscalar multiplication", - *multiscalar_size, - ), - &multiscalar_size, - |b, &&size| { - let points = construct_points(size); - // Rerandomize the scalars for every call to prevent - // false timings from better caching (e.g., the CPU - // cache lifts exactly the right table entries for the - // benchmark into the highest cache levels). - b.iter_batched( - || construct_scalars(size), - |scalars| EdwardsPoint::vartime_multiscalar_mul(&scalars, &points), - BatchSize::SmallInput, - ); - }, - ); - } - } - - fn vartime_precomputed_pure_static(c: &mut BenchmarkGroup) { - for multiscalar_size in &MULTISCALAR_SIZES { - c.bench_with_input( - BenchmarkId::new( - "Variable-time fixed-base multiscalar multiplication", - &multiscalar_size, - ), - &multiscalar_size, - move |b, &&total_size| { - let static_size = total_size; - - let static_points = construct_points(static_size); - let precomp = VartimeEdwardsPrecomputation::new(&static_points); - // Rerandomize the scalars for every call to prevent - // false timings from better caching (e.g., the CPU - // cache lifts exactly the right table entries for the - // benchmark into the highest cache levels). - b.iter_batched( - || construct_scalars(static_size), - |scalars| precomp.vartime_multiscalar_mul(&scalars), - BatchSize::SmallInput, - ); - }, - ); - } - } - - fn vartime_precomputed_helper( - c: &mut BenchmarkGroup, - dynamic_fraction: f64, - ) { - for multiscalar_size in &MULTISCALAR_SIZES { - c.bench_with_input( - BenchmarkId::new( - "Variable-time mixed-base multiscalar multiplication ({:.0}pct dyn)", - format!("({:.0}pct dyn)", 100.0 * dynamic_fraction), - ), - &multiscalar_size, - move |b, &&total_size| { - let dynamic_size = ((total_size as f64) * dynamic_fraction) as usize; - let static_size = total_size - dynamic_size; - - let static_points = construct_points(static_size); - let dynamic_points = construct_points(dynamic_size); - let precomp = VartimeEdwardsPrecomputation::new(&static_points); - // Rerandomize the scalars for every call to prevent - // false timings from better caching (e.g., the CPU - // cache lifts exactly the right table entries for the - // benchmark into the highest cache levels). Timings - // should be independent of points so we don't - // randomize them. - b.iter_batched( - || { - ( - construct_scalars(static_size), - construct_scalars(dynamic_size), - ) - }, - |(static_scalars, dynamic_scalars)| { - precomp.vartime_mixed_multiscalar_mul( - &static_scalars, - &dynamic_scalars, - &dynamic_points, - ) - }, - BatchSize::SmallInput, - ); - }, - ); - } - } - - fn multiscalar_multiplications(c: &mut Criterion) { - let mut group: BenchmarkGroup<_> = c.benchmark_group("Multiscalar muls"); - - consttime_multiscalar_mul(&mut group); - vartime_multiscalar_mul(&mut group); - vartime_precomputed_pure_static(&mut group); - - let dynamic_fracs = [0.0, 0.2, 0.5]; - for frac in dynamic_fracs.iter() { - vartime_precomputed_helper(&mut group, *frac); - } - group.finish(); - } - - criterion_group! { - name = multiscalar_benches; - // Lower the sample size to run the benchmarks faster - config = Criterion::default().sample_size(15); - targets = - multiscalar_multiplications, - } -} - -mod ristretto_benches { - use super::*; - use curve25519_dalek::ristretto::RistrettoPoint; - - fn compress(c: &mut Criterion) { - c.bench_function("RistrettoPoint compression", |b| { - let B = &constants::RISTRETTO_BASEPOINT_POINT; - b.iter(|| B.compress()) - }); - } - - fn decompress(c: &mut Criterion) { - c.bench_function("RistrettoPoint decompression", |b| { - let B_comp = &constants::RISTRETTO_BASEPOINT_COMPRESSED; - b.iter(|| B_comp.decompress().unwrap()) - }); - } - - fn double_and_compress_batch(c: &mut BenchmarkGroup) { - for batch_size in &BATCH_SIZES { - c.bench_with_input( - BenchmarkId::new("Batch Ristretto double-and-encode", *batch_size), - &batch_size, - |b, &&size| { - let mut rng = OsRng; - let points: Vec = (0..size) - .map(|_| RistrettoPoint::random(&mut rng)) - .collect(); - b.iter(|| RistrettoPoint::double_and_compress_batch(&points)); - }, - ); - } - } - - fn double_and_compress_group(c: &mut Criterion) { - let mut group: BenchmarkGroup<_> = c.benchmark_group("double & compress batched"); - double_and_compress_batch(&mut group); - group.finish(); - } - - criterion_group! { - name = ristretto_benches; - config = Criterion::default(); - targets = - compress, - decompress, - double_and_compress_group, - } -} - -mod montgomery_benches { - use super::*; - - fn montgomery_ladder(c: &mut Criterion) { - c.bench_function("Montgomery pseudomultiplication", |b| { - let B = constants::X25519_BASEPOINT; - let s = Scalar::from(897987897u64).invert(); - b.iter(|| B * s); - }); - } - - criterion_group! { - name = montgomery_benches; - config = Criterion::default(); - targets = montgomery_ladder, - } -} - -mod scalar_benches { - use super::*; - - fn scalar_inversion(c: &mut Criterion) { - c.bench_function("Scalar inversion", |b| { - let s = Scalar::from(897987897u64).invert(); - b.iter(|| s.invert()); - }); - } - - fn batch_scalar_inversion(c: &mut BenchmarkGroup) { - for batch_size in &BATCH_SIZES { - c.bench_with_input( - BenchmarkId::new("Batch scalar inversion", *batch_size), - &batch_size, - |b, &&size| { - let mut rng = OsRng; - let scalars: Vec = - (0..size).map(|_| Scalar::random(&mut rng)).collect(); - b.iter(|| { - let mut s = scalars.clone(); - Scalar::batch_invert(&mut s); - }); - }, - ); - } - } - - fn batch_scalar_inversion_group(c: &mut Criterion) { - let mut group: BenchmarkGroup<_> = c.benchmark_group("batch scalar inversion"); - batch_scalar_inversion(&mut group); - group.finish(); - } - - criterion_group! { - name = scalar_benches; - config = Criterion::default(); - targets = - scalar_inversion, - batch_scalar_inversion_group, - } -} - -criterion_main!( - scalar_benches::scalar_benches, - montgomery_benches::montgomery_benches, - ristretto_benches::ristretto_benches, - edwards_benches::edwards_benches, - multiscalar_benches::multiscalar_benches, -); diff --git a/net/gurk-rs/files/vendor/curve25519-dalek/docs/assets/dalek-logo-clear.png b/net/gurk-rs/files/vendor/curve25519-dalek/docs/assets/dalek-logo-clear.png deleted file mode 100644 index d3170d80b21501ba3325a66e2dd7186446cb4944..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 113085 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 SJpPLO-62g~jnsW7uKj=Qh`hQ0 diff --git a/net/gurk-rs/files/vendor/curve25519-dalek/docs/assets/dalek-logo.png b/net/gurk-rs/files/vendor/curve25519-dalek/docs/assets/dalek-logo.png deleted file mode 100644 index 83d6a0c52776e03c7c56efcffdbaa8b0584d881f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 109731 zcmeFZcRbc_{6Bh2DG`xMcA_Oan+S=FqU^2gmAx|hl$9+RS&_Z7H<_XAy@jldvO+ko z>(=-8JLiw{*E#3E)1%MhllSd?jo0;>&)4(1eILo)KXaPmGzNn?BPA)WfWaJ}LI0h? zgC}1*FI7z`aoO8o8<$C#gEF1Ed!v4_8uPo2$)`cz~; z^5AN}Gy%@J&SK%09KIEU{RH@A56hl}su+J#C+zC+GdJhWkSOqgFxe?a=EoK~e0b9^RLhNDKZ}x^0kT4#Jasq6euNQeHF^7Fkhb;AaqGi*|B)X$y8oVM49A6p$kWHtd^yp; zt$6gX_U1j9qguXO#DPi|2^Ie6#BxYcYzA4Lre?xDdLl{8Nc!@BKE0^SKzd`Ic;+`X z^NIiYctt)$vSHcw{L#-M@2^uarq?dqJo?eYmVNPO#L>SoYy|&npex7tjvm(D@jPz* z?{@=E!8v39P?CH(+AM~fKKS24%*5$V9(_9KBSLiauRN0fH6pF>|N3YA+5h#=|2>by z|2xzC{{te)d;C8-s{e0fc&op!Z`KwcEsykzQ7QpA1jSgJc0TKhG3zpo&?HZSiw{B{ zNK3zqj$YEyN52+>G|J-y1tn$Q&`^4Nd;81ys^6_lp$xeL(pX(fVlU1*hS7PsJW?W{ zc?{n0IDQYk(juA=3~$AXshY1!G|7C6u|23}+>GTnoN^GEv& z#UKU0svC*s_b@t(#{BQm^`!9d3#o1Bjo{MIuHt-oP@v(5jFoa*~{<@6M76S+iG`g)ot$IMowX$n3$T{ zl%v-$Qm?_ZJ$Pezt?Jf>@ z=yVvw&`PLyg^_#kkU#qL>?z*=%cn<9h8(*kDlOMd#eXO947;cL5zCt8e~TkTi(`Ld zSg|->yXkQXBw8$6HUBFIpscVF!?BBe(sx7xdhNyzBD+-LH00T2@Z| zn+vNS?7I_(``Z83^BOzc-Rop;cE+chgQ8WCYI{7xZjtb>Tg^XxQNS*NE{+K6P!|HQ za~2jA{f|hn`y`yldeO5?==}B0c3iR^8ymZNbpAtF*}hWNcIEovvbVe2+tsD3#|3j? zLh-QzaNJuinJzyJ;2CF2Cq>U&ypaEWb?l|bzcuKgHIS28(hUp@7|I=;H8yDAHF9>| z)k{Na8oYw`!VBb*HWSU!LAc{4EP^@FeD=H~zuEHBp z0yXp4z?$A&%jzA2QB$@-qX8l3<}QVgwMd@9N?j@|X!%8JF+Y$O0rxRiEpV_z-XV*Xd>^?_9kz|IWMNC<+>j3O;{Q&gXWp8 zj#o)YV

wBujqx>C=yLF}x(3nWiC2 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 U`|&OIdalek \ No newline at end of file diff --git a/net/gurk-rs/files/vendor/curve25519-dalek/docs/assets/rustdoc-include-katex-header.html b/net/gurk-rs/files/vendor/curve25519-dalek/docs/assets/rustdoc-include-katex-header.html deleted file mode 100644 index bc4e3d8..0000000 --- a/net/gurk-rs/files/vendor/curve25519-dalek/docs/assets/rustdoc-include-katex-header.html +++ /dev/null @@ -1,10 +0,0 @@ - - - - - diff --git a/net/gurk-rs/files/vendor/curve25519-dalek/docs/avx2-notes.md b/net/gurk-rs/files/vendor/curve25519-dalek/docs/avx2-notes.md deleted file mode 100644 index ccb5022..0000000 --- a/net/gurk-rs/files/vendor/curve25519-dalek/docs/avx2-notes.md +++ /dev/null @@ -1,140 +0,0 @@ -An AVX2 implementation of the vectorized point operation strategy. - -# Field element representation - -Our strategy is to implement 4-wide multiplication and squaring by -wordslicing, using one 64-bit AVX2 lane for each field element. Field -elements are represented in the usual way as 10 `u32` limbs in radix -\\(25.5\\) (i.e., alternating between \\(2\^{26}\\) for even limbs and -\\(2\^{25}\\) for odd limbs). This has the effect that passing between -the parallel 32-bit AVX2 representation and the serial 64-bit -representation (which uses radix \\(2^{51}\\)) amounts to regrouping -digits. - -The field element representation is oriented around the AVX2 -`vpmuludq` instruction, which multiplies the low 32 bits of each -64-bit lane of each operand to produce a 64-bit result. - -```text,no_run -(a1 ?? b1 ?? c1 ?? d1 ??) -(a2 ?? b2 ?? c2 ?? d2 ??) - -(a1*a2 b1*b2 c1*c2 d1*d2) -``` - -To unpack 32-bit values into 64-bit lanes for use in multiplication -it would be convenient to use the `vpunpck[lh]dq` instructions, -which unpack and interleave the low and high 32-bit lanes of two -source vectors. -However, the AVX2 versions of these instructions are designed to -operate only within 128-bit lanes of the 256-bit vectors, so that -interleaving the low lanes of `(a0 b0 c0 d0 a1 b1 c1 d1)` with zero -gives `(a0 00 b0 00 a1 00 b1 00)`. Instead, we pre-shuffle the data -layout as `(a0 b0 a1 b1 c0 d0 c1 d1)` so that we can unpack the -"low" and "high" parts as - -```text,no_run -(a0 00 b0 00 c0 00 d0 00) -(a1 00 b1 00 c1 00 d1 00) -``` - -The data layout for a vector of four field elements \\( (a,b,c,d) -\\) with limbs \\( a_0, a_1, \ldots, a_9 \\) is as `[u32x8; 5]` in -the form - -```text,no_run -(a0 b0 a1 b1 c0 d0 c1 d1) -(a2 b2 a3 b3 c2 d2 c3 d3) -(a4 b4 a5 b5 c4 d4 c5 d5) -(a6 b6 a7 b7 c6 d6 c7 d7) -(a8 b8 a9 b9 c8 d8 c9 d9) -``` - -Since this breaks cleanly into two 128-bit lanes, it may be possible -to adapt it to 128-bit vector instructions such as NEON without too -much difficulty. - -# Avoiding Overflow in Doubling - -To analyze the size of the field element coefficients during the -computations, we can parameterize the bounds on the limbs of each -field element by \\( b \in \mathbb R \\) representing the excess bits -above that limb's radix, so that each limb is bounded by either -\\(2\^{25+b} \\) or \\( 2\^{26+b} \\), as appropriate. - -The multiplication routine requires that its inputs are bounded with -\\( b < 1.75 \\), in order to fit a multiplication by \\( 19 \\) -into 32 bits. Since \\( \lg 19 < 4.25 \\), \\( 19x < 2\^{32} \\) -when \\( x < 2\^{27.75} = 2\^{26 + 1.75} \\). However, this is only -required for one of the inputs; the other can grow up to \\( b < 2.5 -\\). - -In addition, the multiplication and squaring routines do not -canonically reduce their outputs, but can leave some small uncarried -excesses, so that their reduced outputs are bounded with -\\( b < 0.007 \\). - -The non-parallel portion of the doubling formulas is -$$ -\begin{aligned} -(S\_5 &&,&& S\_6 &&,&& S\_8 &&,&& S\_9 ) -&\gets -(S\_1 + S\_2 &&,&& S\_1 - S\_2 &&,&& S\_1 + 2S\_3 - S\_2 &&,&& S\_1 + S\_2 - S\_4) -\end{aligned} -$$ - -Computing \\( (S\_5, S\_6, S\_8, S\_9 ) \\) as -$$ -\begin{matrix} - & S\_1 & S\_1 & S\_1 & S\_1 \\\\ -+& S\_2 & & & S\_2 \\\\ -+& & & S\_3 & \\\\ -+& & & S\_3 & \\\\ -+& & 2p & 2p & 2p \\\\ --& & S\_2 & S\_2 & \\\\ --& & & & S\_4 \\\\ -=& S\_5 & S\_6 & S\_8 & S\_9 -\end{matrix} -$$ -results in bit-excesses \\( < (1.01, 1.60, 2.33, 2.01)\\) for -\\( (S\_5, S\_6, S\_8, S\_9 ) \\). The products we want to compute -are then -$$ -\begin{aligned} -X\_3 &\gets S\_8 S\_9 \leftrightarrow (2.33, 2.01) \\\\ -Y\_3 &\gets S\_5 S\_6 \leftrightarrow (1.01, 1.60) \\\\ -Z\_3 &\gets S\_8 S\_6 \leftrightarrow (2.33, 1.60) \\\\ -T\_3 &\gets S\_5 S\_9 \leftrightarrow (1.01, 2.01) -\end{aligned} -$$ -which are too large: it's not possible to arrange the multiplicands so -that one vector has \\(b < 2.5\\) and the other has \\( b < 1.75 \\). -However, if we flip the sign of \\( S\_4 = S\_0\^2 \\) during -squaring, so that we output \\(S\_4' = -S\_4 \pmod p\\), then we can -compute -$$ -\begin{matrix} - & S\_1 & S\_1 & S\_1 & S\_1 \\\\ -+& S\_2 & & & S\_2 \\\\ -+& & & S\_3 & \\\\ -+& & & S\_3 & \\\\ -+& & & & S\_4' \\\\ -+& & 2p & 2p & \\\\ --& & S\_2 & S\_2 & \\\\ -=& S\_5 & S\_6 & S\_8 & S\_9 -\end{matrix} -$$ -resulting in bit-excesses \\( < (1.01, 1.60, 2.33, 1.60)\\) for -\\( (S\_5, S\_6, S\_8, S\_9 ) \\). The products we want to compute -are then -$$ -\begin{aligned} -X\_3 &\gets S\_8 S\_9 \leftrightarrow (2.33, 1.60) \\\\ -Y\_3 &\gets S\_5 S\_6 \leftrightarrow (1.01, 1.60) \\\\ -Z\_3 &\gets S\_8 S\_6 \leftrightarrow (2.33, 1.60) \\\\ -T\_3 &\gets S\_5 S\_9 \leftrightarrow (1.01, 1.60) -\end{aligned} -$$ -whose right-hand sides are all bounded with \\( b < 1.75 \\) and -whose left-hand sides are all bounded with \\( b < 2.5 \\), -so that we can avoid any intermediate reductions. diff --git a/net/gurk-rs/files/vendor/curve25519-dalek/docs/ifma-notes.md b/net/gurk-rs/files/vendor/curve25519-dalek/docs/ifma-notes.md deleted file mode 100644 index c6fd3b3..0000000 --- a/net/gurk-rs/files/vendor/curve25519-dalek/docs/ifma-notes.md +++ /dev/null @@ -1,580 +0,0 @@ -An AVX512-IFMA implementation of the vectorized point operation -strategy. - -# IFMA instructions - -AVX512-IFMA is an extension to AVX-512 consisting of two instructions: - -* `vpmadd52luq`: packed multiply of unsigned 52-bit integers and add - the low 52 product bits to 64-bit accumulators; -* `vpmadd52huq`: packed multiply of unsigned 52-bit integers and add - the high 52 product bits to 64-bit accumulators; - -These operate on 64-bit lanes of their source vectors, taking the low -52 bits of each lane of each source vector, computing the 104-bit -products of each pair, and then adding either the high or low 52 bits -of the 104-bit products to the 64-bit lanes of the destination vector. -The multiplication is performed internally by reusing circuitry for -floating-point arithmetic. Although these instructions are part of -AVX512, the AVX512VL (vector length) extension (present whenever IFMA -is) allows using them with 512, 256, or 128-bit operands. - -This provides a major advantage to vectorized integer operations: -previously, vector operations could only use a \\(32 \times 32 -\rightarrow 64\\)-bit multiplier, while serial code could use a -\\(64\times 64 \rightarrow 128\\)-bit multiplier. - -## IFMA for big-integer multiplications - -A detailed example of the intended use of the IFMA instructions can be -found in a 2016 paper by Gueron and Krasnov, [_Accelerating Big -Integer Arithmetic Using Intel IFMA Extensions_][2016_gueron_krasnov]. -The basic idea is that multiplication of large integers (such as 1024, -2048, or more bits) can be performed as follows. - -First, convert a “packed” 64-bit representation -\\[ -\begin{aligned} -x &= x'_0 + x'_1 2^{64} + x'_2 2^{128} + \cdots \\\\ -y &= y'_0 + y'_1 2^{64} + y'_2 2^{128} + \cdots -\end{aligned} -\\] -into a “redundant” 52-bit representation -\\[ -\begin{aligned} -x &= x_0 + x_1 2^{52} + x_2 2^{104} + \cdots \\\\ -y &= y_0 + y_1 2^{52} + y_2 2^{104} + \cdots -\end{aligned} -\\] -with each \\(x_i, y_j\\) in a 64-bit lane. - -Writing the product as \\(z = z_0 + z_1 2^{52} + z_2 2^{104} + \cdots\\), -the “schoolbook” multiplication strategy gives -\\[ -\begin{aligned} -&z_0 &&=& x_0 & y_0 & & & & & & & & \\\\ -&z_1 &&=& x_1 & y_0 &+ x_0 & y_1 & & & & & & \\\\ -&z_2 &&=& x_2 & y_0 &+ x_1 & y_1 &+ x_0 & y_2 & & & & \\\\ -&z_3 &&=& x_3 & y_0 &+ x_2 & y_1 &+ x_1 & y_2 &+ x_0 & y_3 & & \\\\ -&z_4 &&=& \vdots\\;&\\;\vdots &+ x_3 & y_1 &+ x_2 & y_2 &+ x_1 & y_3 &+ \cdots& \\\\ -&z_5 &&=& & & \vdots\\;&\\;\vdots &+ x_3 & y_2 &+ x_2 & y_3 &+ \cdots& \\\\ -&z_6 &&=& & & & & \vdots\\;&\\;\vdots &+ x_3 & y_3 &+ \cdots& \\\\ -&z_7 &&=& & & & & & & \vdots\\;&\\;\vdots &+ \cdots& \\\\ -&\vdots&&=& & & & & & & & & \ddots& \\\\ -\end{aligned} -\\] -Notice that the product coefficient \\(z_k\\), representing the value -\\(z_k 2^{52k}\\), is the sum of all product terms -\\( -(x_i 2^{52 i}) (y_j 2^{52 j}) -\\) -with \\(k = i + j\\). -Write the IFMA operators \\(\mathrm{lo}(a,b)\\), denoting the low -\\(52\\) bits of \\(ab\\), and -\\(\mathrm{hi}(a,b)\\), denoting the high \\(52\\) bits of -\\(ab\\). -Now we can rewrite the product terms as -\\[ -\begin{aligned} -(x_i 2^{52 i}) (y_j 2^{52 j}) -&= -2^{52 (i+j)}( -\mathrm{lo}(x_i, y_j) + -\mathrm{hi}(x_i, y_j) 2^{52} -) -\\\\ -&= -\mathrm{lo}(x_i, y_j) 2^{52 (i+j)} + -\mathrm{hi}(x_i, y_j) 2^{52 (i+j+1)}. -\end{aligned} -\\] -This means that the low half of \\(x_i y_j\\) can be accumulated onto -the product limb \\(z_{i+j}\\) and the high half can be directly -accumulated onto the next-higher product limb \\(z_{i+j+1}\\) with no -additional operations. This allows rewriting the schoolbook -multiplication into the form -\\[ -\begin{aligned} -&z_0 &&=& \mathrm{lo}(x_0,&y_0) & & & & & & & & & & \\\\ -&z_1 &&=& \mathrm{lo}(x_1,&y_0) &+\mathrm{hi}(x_0,&y_0) &+\mathrm{lo}(x_0,&y_1) & & & & & & \\\\ -&z_2 &&=& \mathrm{lo}(x_2,&y_0) &+\mathrm{hi}(x_1,&y_0) &+\mathrm{lo}(x_1,&y_1) &+\mathrm{hi}(x_0,&y_1) &+\mathrm{lo}(x_0,&y_2) & & \\\\ -&z_3 &&=& \mathrm{lo}(x_3,&y_0) &+\mathrm{hi}(x_2,&y_0) &+\mathrm{lo}(x_2,&y_1) &+\mathrm{hi}(x_1,&y_1) &+\mathrm{lo}(x_1,&y_2) &+ \cdots& \\\\ -&z_4 &&=& \vdots\\;&\\;\vdots &+\mathrm{hi}(x_3,&y_0) &+\mathrm{lo}(x_3,&y_1) &+\mathrm{hi}(x_2,&y_1) &+\mathrm{lo}(x_2,&y_2) &+ \cdots& \\\\ -&z_5 &&=& & & \vdots\\;&\\;\vdots & \vdots\\;&\\;\vdots &+\mathrm{hi}(x_3,&y_1) &+\mathrm{lo}(x_3,&y_2) &+ \cdots& \\\\ -&z_6 &&=& & & & & & & \vdots\\;&\\;\vdots & \vdots\\;&\\;\vdots &+ \cdots& \\\\ -&\vdots&&=& & & & & & & & & & & \ddots& \\\\ -\end{aligned} -\\] -Gueron and Krasnov implement multiplication by constructing vectors -out of the columns of this diagram, so that the source operands for -the IFMA instructions are of the form \\((x_0, x_1, x_2, \ldots)\\) -and \\((y_i, y_i, y_i, \ldots)\\). -After performing the multiplication, -the product terms \\(z_i\\) are then repacked into a 64-bit representation. - -## An alternative strategy - -The strategy described above is aimed at big-integer multiplications, -such as 1024, 2048, or 4096 bits, which would be used for applications -like RSA. However, elliptic curve cryptography uses much smaller field -sizes, such as 256 or 384 bits, so a different strategy is needed. - -The parallel Edwards formulas provide parallelism at the level of the -formulas for curve operations. This means that instead of scanning -through the terms of the source operands and parallelizing *within* a -field element (as described above), we can arrange the computation in -product-scanning form and parallelize *across* field elements (as -described below). - -The parallel Edwards -formulas provide 4-way parallelism, so they can be implemented using -256-bit vectors using a single 64-bit lane for each element, or using -512-bit vectors using two 64-bit lanes. -The only available CPU supporting IFMA (the -i3-8121U) executes 512-bit IFMA instructions at half rate compared to -256-bit instructions, so for now there's no throughput advantage to -using 512-bit IFMA instructions, and this implementation uses 256-bit -vectors. - -To extend this to 512-bit vectors, it's only only necessary to achieve -2-way parallelism, and it's possible (with a small amount of overhead) -to create a hybrid strategy that operates entirely within 128-bit -lanes. This means that cross-lane operations can use the faster -`vpshufd` (1c latency) instead of a general shuffle instruction (3c -latency). - -# Choice of radix - -The inputs to IFMA instructions are 52 bits wide, so the radix \\(r\\) -used to represent a multiprecision integer must be \\( r \leq 52 \\). -The obvious choice is the "native" radix \\(r = 52\\). - -As described above, this choice -has the advantage that for \\(x_i, y_j \in [0,2^{52})\\), the product term -\\[ -\begin{aligned} -(x_i 2^{52 i}) (y_j 2^{52 j}) -&= -2^{52 (i+j)}( -\mathrm{lo}(x_i, y_j) + -\mathrm{hi}(x_i, y_j) 2^{52} -) -\\\\ -&= -\mathrm{lo}(x_i, y_j) 2^{52 (i+j)} + -\mathrm{hi}(x_i, y_j) 2^{52 (i+j+1)}, -\end{aligned} -\\] -so that the low and high halves of the product can be directly accumulated -onto the product limbs. -In contrast, when using a smaller radix \\(r = 52 - k\\), -the product term has the form -\\[ -\begin{aligned} -(x_i 2^{r i}) (y_j 2^{r j}) -&= -2^{r (i+j)}( -\mathrm{lo}(x_i, y_j) + -\mathrm{hi}(x_i, y_j) 2^{52} -) -\\\\ -&= -\mathrm{lo}(x_i, y_j) 2^{r (i+j)} + -( -\mathrm{hi}(x_i, y_j) 2^k -) -2^{r (i+j+1)}. -\end{aligned} -\\] -What's happening is that the product \\(x_i y_j\\) of size \\(2r\\) -bits is split not at \\(r\\) but at \\(52\\), so \\(k\\) product bits -are placed into the low half instead of the high half. This means -that the high half of the product cannot be directly accumulated onto -\\(z_{i+j+1}\\), but must first be multiplied by \\(2^k\\) (i.e., left -shifted by \\(k\\)). In addition, the low half of the product is -\\(52\\) bits large instead of \\(r\\) bits. - -## Handling offset product terms - -[Drucker and Gueron][2018_drucker_gueron] analyze the choice of radix -in the context of big-integer squaring, outlining three ways to handle -the offset product terms, before concluding that all of them are -suboptimal: - -1. Shift the results after accumulation; -2. Shift the input operands before multiplication; -3. Split the MAC operation, accumulating into a zeroed register, - shifting the result, and then adding. - -The first option is rejected because it could double-shift some -previously accumulated terms, the second doesn't work because the -inputs could become larger than \\(52\\) bits, and the third requires -additional instructions to handle the shifting and adding. - -Based on an analysis of total number of instructions, they suggest an -addition to the instruction set, which they call `FMSA` (fused -multiply-shift-add). This would shift the result according to an 8-bit -immediate value before accumulating it into the destination register. - -However, this change to the instruction set doesn't seem to be -necessary. Instead, the product terms can be grouped according to -their coefficients, accumulated together, then shifted once before -adding them to the final sum. This uses an extra register, shift, and -add, but only once per product term (accumulation target), not once -per source term (as in the Drucker-Gueron paper). - -Moreover, because IFMA instructions execute only on two ports -(presumably 0 and 1), while adds and shifts can execute on three ports -(0, 1, and 5), the adds and shifts can execute independently of the -IFMA operations, as long as there is not too much pressure on port 5. -This means that, although the total number of instructions increases, -the shifts and adds do not necessarily increase the execution time, as -long as throughput is limited by IFMA operations. - -Finally, because IFMA instructions have 4 cycle latency and 0.5/1 -cycle throughput (for 256/512 bit vectors), maximizing IFMA throughput -requires either 8 (for 256) or 4 (for 512) independent operations. So -accumulating groups of terms independently before adding them at the -end may be necessary anyways, in order to prevent long chains of -dependent instructions. - -## Advantages of a smaller radix - -Using a smaller radix has other advantages. Although radix \\(52\\) -is an unsaturated representation from the point of view of the -\\(64\\)-bit accumulators (because up to 4096 product terms can be -accumulated without carries), it's a saturated representation from the -point of view of the multiplier (since \\(52\\)-bit values are the -maximum input size). - -Because the inputs to a multiplication must have all of their limbs -bounded by \\(2^{52}\\), limbs in excess of \\(2^{52}\\) must be -reduced before they can be used as an input. The -[Gueron-Krasnov][2016_gueron_krasnov] paper suggests normalizing -values using a standard, sequential carry chain: for each limb, add -the carryin from reducing the previous limb, compute the carryout and -reduce the current limb, then move to the next limb. - -However, when using a smaller radix, such as \\(51\\), each limb can -store a carry bit and still be used as the input to a multiplication. -This means that the inputs do not need to be normalized, and instead -of using a sequential carry chain, we can compute all carryouts in -parallel, reduce all limbs in parallel, and then add the carryins in -parallel (possibly growing the limb values by one bit). - -Because the output of this partial reduction is an acceptable -multiplication input, we can "close the loop" using partial reductions -and never have to normalize to a canonical representation through the -entire computation, in contrast to the Gueron-Krasnov approach, which -converts back to a packed representation after every operation. (This -idea seems to trace back to at least as early as [this 1999 -paper][1999_walter]). - -Using \\(r = 51\\) is enough to keep a carry bit in each limb and -avoid normalizations. What about an even smaller radix? One reason -to choose a smaller radix would be to align the limb boundaries with -an inline reduction (for instance, choosing \\(r = 43\\) for the -Mersenne field \\(p = 2^{127} - 1\\)), but for \\(p = 2^{255 - 19}\\), -\\(r = 51 = 255/5\\) is the natural choice. - -# Multiplication - -The inputs to a multiplication are two field elements -\\[ -\begin{aligned} -x &= x_0 + x_1 2^{51} + x_2 2^{102} + x_3 2^{153} + x_4 2^{204} \\\\ -y &= y_0 + y_1 2^{51} + y_2 2^{102} + y_3 2^{153} + y_4 2^{204}, -\end{aligned} -\\] -with limbs in range \\([0,2^{52})\\). - -Writing the product terms as -\\[ -\begin{aligned} -z &= z_0 + z_1 2^{51} + z_2 2^{102} + z_3 2^{153} + z_4 2^{204} \\\\ - &+ z_5 2^{255} + z_6 2^{306} + z_7 2^{357} + z_8 2^{408} + z_9 2^{459}, -\end{aligned} -\\] -a schoolbook multiplication in product scanning form takes the form -\\[ -\begin{aligned} -z_0 &= x_0 y_0 \\\\ -z_1 &= x_1 y_0 + x_0 y_1 \\\\ -z_2 &= x_2 y_0 + x_1 y_1 + x_0 y_2 \\\\ -z_3 &= x_3 y_0 + x_2 y_1 + x_1 y_2 + x_0 y_3 \\\\ -z_4 &= x_4 y_0 + x_3 y_1 + x_2 y_2 + x_1 y_3 + x_0 y_4 \\\\ -z_5 &= x_4 y_1 + x_3 y_2 + x_2 y_3 + x_1 y_4 \\\\ -z_6 &= x_4 y_2 + x_3 y_3 + x_2 y_4 \\\\ -z_7 &= x_4 y_3 + x_3 y_4 \\\\ -z_8 &= x_4 y_4 \\\\ -z_9 &= 0 \\\\ -\end{aligned} -\\] -Each term \\(x_i y_j\\) can be written in terms of IFMA operations as -\\[ -x_i y_j = \mathrm{lo}(x_i,y_j) + 2\mathrm{hi}(x_i,y_j)2^{51}. -\\] -Substituting this equation into the schoolbook multiplication, then -moving terms to eliminate the \\(2^{51}\\) factors gives -\\[ -\begin{aligned} -z_0 &= \mathrm{lo}(x_0, y_0) \\\\ - &+ \qquad 0 \\\\ -z_1 &= \mathrm{lo}(x_1, y_0) + \mathrm{lo}(x_0, y_1) \\\\ - &+ \qquad 2( \mathrm{hi}(x_0, y_0) )\\\\ -z_2 &= \mathrm{lo}(x_2, y_0) + \mathrm{lo}(x_1, y_1) + \mathrm{lo}(x_0, y_2) \\\\ - &+ \qquad 2( \mathrm{hi}(x_1, y_0) + \mathrm{hi}(x_0, y_1) )\\\\ -z_3 &= \mathrm{lo}(x_3, y_0) + \mathrm{lo}(x_2, y_1) + \mathrm{lo}(x_1, y_2) + \mathrm{lo}(x_0, y_3) \\\\ - &+ \qquad 2( \mathrm{hi}(x_2, y_0) + \mathrm{hi}(x_1, y_1) + \mathrm{hi}(x_0, y_2) )\\\\ -z_4 &= \mathrm{lo}(x_4, y_0) + \mathrm{lo}(x_3, y_1) + \mathrm{lo}(x_2, y_2) + \mathrm{lo}(x_1, y_3) + \mathrm{lo}(x_0, y_4) \\\\ - &+ \qquad 2( \mathrm{hi}(x_3, y_0) + \mathrm{hi}(x_2, y_1) + \mathrm{hi}(x_1, y_2) + \mathrm{hi}(x_0, y_3) )\\\\ -z_5 &= \mathrm{lo}(x_4, y_1) + \mathrm{lo}(x_3, y_2) + \mathrm{lo}(x_2, y_3) + \mathrm{lo}(x_1, y_4) \\\\ - &+ \qquad 2( \mathrm{hi}(x_4, y_0) + \mathrm{hi}(x_3, y_1) + \mathrm{hi}(x_2, y_2) + \mathrm{hi}(x_1, y_3) + \mathrm{hi}(x_0, y_4) )\\\\ -z_6 &= \mathrm{lo}(x_4, y_2) + \mathrm{lo}(x_3, y_3) + \mathrm{lo}(x_2, y_4) \\\\ - &+ \qquad 2( \mathrm{hi}(x_4, y_1) + \mathrm{hi}(x_3, y_2) + \mathrm{hi}(x_2, y_3) + \mathrm{hi}(x_1, y_4) )\\\\ -z_7 &= \mathrm{lo}(x_4, y_3) + \mathrm{lo}(x_3, y_4) \\\\ - &+ \qquad 2( \mathrm{hi}(x_4, y_2) + \mathrm{hi}(x_3, y_3) + \mathrm{hi}(x_2, y_4) )\\\\ -z_8 &= \mathrm{lo}(x_4, y_4) \\\\ - &+ \qquad 2( \mathrm{hi}(x_4, y_3) + \mathrm{hi}(x_3, y_4) )\\\\ -z_9 &= 0 \\\\ - &+ \qquad 2( \mathrm{hi}(x_4, y_4) )\\\\ -\end{aligned} -\\] -As noted above, our strategy will be to multiply and accumulate the -terms with coefficient \\(2\\) separately from those with coefficient -\\(1\\), before combining them at the end. This can alternately be -thought of as accumulating product terms into a *doubly-redundant* -representation, with two limbs for each digit, before collapsing -the doubly-redundant representation by shifts and adds. - -This computation requires 25 `vpmadd52luq` and 25 `vpmadd52huq` -operations. For 256-bit vectors, IFMA operations execute on an -i3-8121U with latency 4 cycles, throughput 0.5 cycles, so executing 50 -instructions requires 25 cycles' worth of throughput. Accumulating -terms with coefficient \\(1\\) and \\(2\\) seperately means that the -longest dependency chain has length 5, so the critical path has length -20 cycles and the bottleneck is throughput. - -# Reduction modulo \\(p\\) - -The next question is how to handle the reduction modulo \\(p\\). -Because \\(p = 2^{255} - 19\\), \\(2^{255} = 19 \pmod p\\), so we can -alternately write -\\[ -\begin{aligned} -z &= z_0 + z_1 2^{51} + z_2 2^{102} + z_3 2^{153} + z_4 2^{204} \\\\ - &+ z_5 2^{255} + z_6 2^{306} + z_7 2^{357} + z_8 2^{408} + z_9 2^{459} -\end{aligned} -\\] -as -\\[ -\begin{aligned} -z &= (z_0 + 19z_5) + (z_1 + 19z_6) 2^{51} + (z_2 + 19z_7) 2^{102} + (z_3 + 19z_8) 2^{153} + (z_4 + 19z_9) 2^{204}. -\end{aligned} -\\] -When using a \\(64 \times 64 \rightarrow 128\\)-bit multiplier, this -can be handled (as in [Ed25519][ed25519_paper]) by premultiplying -source terms by \\(19\\). Since \\(\lg(19) < 4.25\\), this increases -their size by less than \\(4.25\\) bits, and the rest of the -multiplication can be shown to work out. - -Here, we have at most \\(1\\) bit of headroom. In order to allow -premultiplication, we would need to use radix \\(2^{47}\\), which -would require six limbs instead of five. Instead, we compute the high -terms \\(z_5, \ldots, z_9\\), each using two chains of IFMA -operations, then multiply by \\(19\\) and combine with the lower terms -\\(z_0, \ldots, z_4\\). There are two ways to perform the -multiplication by \\(19\\): using more IFMA operations, or using the -`vpmullq` instruction, which computes the low \\(64\\) bits of a \\(64 -\times 64\\)-bit product. However, `vpmullq` has 15c/1.5c -latency/throughput, in contrast to the 4c/0.5c latency/throughput of -IFMA operations, so it seems like a worse choice. - -The high terms \\(z_5, \ldots, z_9\\) are sums of \\(52\\)-bit terms, -so they are larger than \\(52\\) bits. Write these terms in radix \\(52\\) as -\\[ -z_{5+i} = z_{5+i}' + z_{5+i}'' 2^{52}, \qquad z_{5+i}' < 2^{52}. -\\] -Then the contribution of \\(z_{5+i}\\), taken modulo \\(p\\), is -\\[ -\begin{aligned} -z_{5+i} 2^{255} 2^{51 i} -&= -19 (z_{5+i}' + z_{5+i}'' 2^{52}) 2^{51 i} -\\\\ -&= -19 z_{5+i}' 2^{51 i} + 2 \cdot 19 z_{5+i}'' 2^{51 (i+1)} -\\\\ -\end{aligned} -\\] -The products \\(19 z_{5+i}', 19 z_{5+i}''\\) can be written in terms of IFMA operations as -\\[ -\begin{aligned} -19 z_{5+i}' &= \mathrm{lo}(19, z_{5+i}') + 2 \mathrm{hi}(19, z_{5+i}') 2^{51}, \\\\ -19 z_{5+i}'' &= \mathrm{lo}(19, z_{5+i}'') + 2 \mathrm{hi}(19, z_{5+i}'') 2^{51}. \\\\ -\end{aligned} -\\] -Because \\(z_{5+i} < 2^{64}\\), \\(z_{5+i}'' < 2^{12} \\), so \\(19 -z_{5+i}'' < 2^{17} < 2^{52} \\) and \\(\mathrm{hi}(19, z_{5+i}'') = 0\\). -Because IFMA operations ignore the high bits of their source -operands, we do not need to compute \\(z\_{5+i}'\\) explicitly: -the high bits will be ignored. -Combining these observations, we can write -\\[ -\begin{aligned} -z_{5+i} 2^{255} 2^{51 i} -&= -19 z_{5+i}' 2^{51 i} + 2 \cdot 19 z_{5+i}'' 2^{51 (i+1)} -\\\\ -&= -\mathrm{lo}(19, z_{5+i}) 2^{51 i} -\+ 2 \mathrm{hi}(19, z_{5+i}) 2^{51 (i+1)} -\+ 2 \mathrm{lo}(19, z_{5+i}/2^{52}) 2^{51 (i+1)}. -\end{aligned} -\\] - -For \\(i = 0,1,2,3\\), this allows reducing \\(z_{5+i}\\) onto -\\(z_{i}, z_{i+1}\\), and if the low terms are computed using a -doubly-redundant representation, no additional shifts are needed to -handle the \\(2\\) coefficients. For \\(i = 4\\), there's a -complication: the contribution becomes -\\[ -\begin{aligned} -z_{9} 2^{255} 2^{204} -&= -\mathrm{lo}(19, z_{9}) 2^{204} -\+ 2 \mathrm{hi}(19, z_{9}) 2^{255} -\+ 2 \mathrm{lo}(19, z_{9}/2^{52}) 2^{255} -\\\\ -&= -\mathrm{lo}(19, z_{9}) 2^{204} -\+ 2 \mathrm{hi}(19, z_{9}) 19 -\+ 2 \mathrm{lo}(19, z_{9}/2^{52}) 19 -\\\\ -&= -\mathrm{lo}(19, z_{9}) 2^{204} -\+ 2 -\mathrm{lo}(19, \mathrm{hi}(19, z_{9}) + \mathrm{lo}(19, z_{9}/2^{52})). -\\\\ -\end{aligned} -\\] - -It would be possible to cut the number of multiplications from 3 to 2 -by carrying the high part of each \\(z_i\\) onto \\(z_{i+1}\\). This -would eliminate 5 multiplications, clearing 2.5 cycles of port -pressure, at the cost of 5 additions, adding 1.66 cycles of port -pressure. But doing this would create a dependency between terms -(e.g., \\(z_{5}\\) must be computed before the reduction of -\\(z_{6}\\) can begin), whereas with the approach above, all -contributions to all terms are computed independently, to maximize ILP -and flexibility for the processor to schedule instructions. - -This strategy performs 16 IFMA operations, adding two IFMA operations -to each of the \\(2\\)-coefficient terms and one to each of the -\\(1\\)-coefficient terms. Considering the multiplication and -reduction together, we use 66 IFMA operations, requiring 33 cycles' -throughput, while the longest chain of IFMA operations is in the -reduction of \\(z_5\\) onto \\(z_1\\), of length 7 (so 28 cycles, plus -2 cycles to combine the two parts of \\(z_5\\), and the bottleneck is -again throughput. - -Once this is done, we have computed the product terms -\\[ -z = z_0 + z_1 2^{51} + z_2 2^{102} + z_3 2^{153} + z_4 2^{204}, -\\] -without reducing the \\(z_i\\) to fit in \\(52\\) bits. Because the -overall flow of operations alternates multiplications and additions or -subtractions, we would have to perform a reduction after an addition -but before the next multiplication anyways, so there's no benefit to -fully reducing the limbs at the end of a multiplication. Instead, we -leave them unreduced, and track the reduction state using the type -system to ensure that unreduced limbs are not accidentally used as an -input to a multiplication. - -# Squaring - -Squaring operates similarly to multiplication, but with the -possibility to combine identical terms. -As before, we write the input as -\\[ -\begin{aligned} -x &= x_0 + x_1 2^{51} + x_2 2^{102} + x_3 2^{153} + x_4 2^{204} -\end{aligned} -\\] -with limbs in range \\([0,2^{52})\\). -Writing the product terms as -\\[ -\begin{aligned} -z &= z_0 + z_1 2^{51} + z_2 2^{102} + z_3 2^{153} + z_4 2^{204} \\\\ - &+ z_5 2^{255} + z_6 2^{306} + z_7 2^{357} + z_8 2^{408} + z_9 2^{459}, -\end{aligned} -\\] -a schoolbook squaring in product scanning form takes the form -\\[ -\begin{aligned} -z_0 &= x_0 x_0 \\\\ -z_1 &= 2 x_1 x_0 \\\\ -z_2 &= 2 x_2 x_0 + x_1 x_1 \\\\ -z_3 &= 2 x_3 x_0 + 2 x_2 x_1 \\\\ -z_4 &= 2 x_4 x_0 + 2 x_3 x_1 + x_2 x_2 \\\\ -z_5 &= 2 x_4 x_1 + 2 x_3 x_2 \\\\ -z_6 &= 2 x_4 x_2 + x_3 x_3 \\\\ -z_7 &= 2 x_4 x_3 \\\\ -z_8 &= x_4 x_4 \\\\ -z_9 &= 0 \\\\ -\end{aligned} -\\] -As before, we write \\(x_i x_j\\) as -\\[ -x_i x_j = \mathrm{lo}(x_i,x_j) + 2\mathrm{hi}(x_i,x_j)2^{51}, -\\] -and substitute to obtain -\\[ -\begin{aligned} -z_0 &= \mathrm{lo}(x_0, x_0) + 0 \\\\ -z_1 &= 2 \mathrm{lo}(x_1, x_0) + 2 \mathrm{hi}(x_0, x_0) \\\\ -z_2 &= 2 \mathrm{lo}(x_2, x_0) + \mathrm{lo}(x_1, x_1) + 4 \mathrm{hi}(x_1, x_0) \\\\ -z_3 &= 2 \mathrm{lo}(x_3, x_0) + 2 \mathrm{lo}(x_2, x_1) + 4 \mathrm{hi}(x_2, x_0) + 2 \mathrm{hi}(x_1, x_1) \\\\ -z_4 &= 2 \mathrm{lo}(x_4, x_0) + 2 \mathrm{lo}(x_3, x_1) + \mathrm{lo}(x_2, x_2) + 4 \mathrm{hi}(x_3, x_0) + 4 \mathrm{hi}(x_2, x_1) \\\\ -z_5 &= 2 \mathrm{lo}(x_4, x_1) + 2 \mathrm{lo}(x_3, x_2) + 4 \mathrm{hi}(x_4, x_0) + 4 \mathrm{hi}(x_3, x_1) + 2 \mathrm{hi}(x_2, x_2) \\\\ -z_6 &= 2 \mathrm{lo}(x_4, x_2) + \mathrm{lo}(x_3, x_3) + 4 \mathrm{hi}(x_4, x_1) + 4 \mathrm{hi}(x_3, x_2) \\\\ -z_7 &= 2 \mathrm{lo}(x_4, x_3) + 4 \mathrm{hi}(x_4, x_2) + 2 \mathrm{hi}(x_3, x_3) \\\\ -z_8 &= \mathrm{lo}(x_4, x_4) + 4 \mathrm{hi}(x_4, x_3) \\\\ -z_9 &= 0 + 2 \mathrm{hi}(x_4, x_4) \\\\ -\end{aligned} -\\] -To implement these, we group terms by their coefficient, computing -those with coefficient \\(2\\) on set of IFMA chains, and on another -set of chains, we begin with coefficient-\\(4\\) terms, then shift -left before continuing with the coefficient-\\(1\\) terms. -The reduction strategy is the same as for multiplication. - -# Future improvements - -LLVM won't use blend operations on [256-bit vectors yet][llvm_blend], -so there's a bunch of blend instructions that could be omitted. - -Although the multiplications and squarings are much faster, there's no -speedup to the additions and subtractions, so there are diminishing -returns. In fact, the complications in the doubling formulas mean -that doubling is actually slower than readdition. This also suggests -that moving to 512-bit vectors won't be much help for a strategy aimed -at parallelism within a group operation, so to extract performance -gains from 512-bit vectors it will probably be necessary to create a -parallel-friendly multiscalar multiplication algorithm. This could -also help with reducing shuffle pressure. - -The squaring implementation could probably be optimized, but without -`perf` support on Cannonlake it's difficult to make actual -measurements. - -Another improvement would be to implement vectorized square root -computations, which would allow creating an iterator adaptor for point -decompression that bunched decompression operations and executed them -in parallel. This would accelerate batch verification. - -[2016_gueron_krasnov]: https://ieeexplore.ieee.org/document/7563269 -[2018_drucker_gueron]: https://eprint.iacr.org/2018/335 -[1999_walter]: https://pdfs.semanticscholar.org/0e6a/3e8f30b63b556679f5dff2cbfdfe9523f4fa.pdf -[ed25519_paper]: https://ed25519.cr.yp.to/ed25519-20110926.pdf -[llvm_blend]: https://bugs.llvm.org/show_bug.cgi?id=38343 diff --git a/net/gurk-rs/files/vendor/curve25519-dalek/docs/parallel-formulas.md b/net/gurk-rs/files/vendor/curve25519-dalek/docs/parallel-formulas.md deleted file mode 100644 index f84d1cc..0000000 --- a/net/gurk-rs/files/vendor/curve25519-dalek/docs/parallel-formulas.md +++ /dev/null @@ -1,333 +0,0 @@ -Vectorized implementations of field and point operations, using a -modification of the 4-way parallel formulas of Hisil, Wong, Carter, -and Dawson. - -These notes explain the parallel formulas and our strategy for using -them with SIMD operations. There are two backend implementations: one -using AVX2, and the other using AVX512-IFMA. - -# Overview - -The 2008 paper [_Twisted Edwards Curves Revisited_][hwcd08] by Hisil, -Wong, Carter, and Dawson (HWCD) introduced the “extended coordinates” -and mixed-model representations which are used by most Edwards curve -implementations. - -However, they also describe 4-way parallel formulas for point addition -and doubling: a unified addition algorithm taking an effective -\\(2\mathbf M + 1\mathbf D\\), a doubling algorithm taking an -effective \\(1\mathbf M + 1\mathbf S\\), and a dedicated (i.e., for -distinct points) addition algorithm taking an effective \\(2 \mathbf M -\\). They compare these formulas with a 2-way parallel variant of the -Montgomery ladder. - -Unlike their serial formulas, which are used widely, their parallel -formulas do not seem to have been implemented in software before. The -2-way parallel Montgomery ladder was used in 2015 by Tung Chou's -`sandy2x` implementation. Curiously, however, although the [`sandy2x` -paper][sandy2x] also implements Edwards arithmetic, and cites HWCD08, -it doesn't mention their parallel Edwards formulas. -A 2015 paper by Hernández and López describes an AVX2 implementation -of X25519. Neither the paper nor the code are publicly available, but -it apparently gives only a [slight speedup][avx2trac], suggesting that -it uses a 4-way parallel Montgomery ladder rather than parallel -Edwards formulas. - -The reason may be that HWCD08 describe their formulas as operating on -four independent processors, which would make a software -implementation impractical: all of the operations are too low-latency -to effectively synchronize. But a closer inspection reveals that the -(more expensive) multiplication and squaring steps are uniform, while -the instruction divergence occurs in the (much cheaper) addition and -subtraction steps. This means that a SIMD implementation can perform -the expensive steps uniformly, and handle divergence in the -inexpensive steps using masking. - -These notes describe modifications to the original parallel formulas -to allow a SIMD implementation, and this module contains -implementations of the modified formulas targeting either AVX2 or -AVX512-IFMA. - -# Parallel formulas in HWCD'08 - -The doubling formula is presented in the HWCD paper as follows: - -| Cost | Processor 1 | Processor 2 | Processor 3 | Processor 4 | -|------------------|--------------------------------|--------------------------------|--------------------------------|--------------------------------| -| | idle | idle | idle | \\( R\_1 \gets X\_1 + Y\_1 \\) | -| \\(1\mathbf S\\) | \\( R\_2 \gets X\_1\^2 \\) | \\( R\_3 \gets Y\_1\^2 \\) | \\( R\_4 \gets Z\_1\^2 \\) | \\( R\_5 \gets R\_1\^2 \\) | -| | \\( R\_6 \gets R\_2 + R\_3 \\) | \\( R\_7 \gets R\_2 - R\_3 \\) | \\( R\_4 \gets 2 R\_4 \\) | idle | -| | idle | \\( R\_1 \gets R\_4 + R\_7 \\) | idle | \\( R\_2 \gets R\_6 - R\_5 \\) | -| \\(1\mathbf M\\) | \\( X\_3 \gets R\_1 R\_2 \\) | \\( Y\_3 \gets R\_6 R\_7 \\) | \\( T\_3 \gets R\_2 R\_6 \\) | \\( Z\_3 \gets R\_1 R\_7 \\) | - -and the unified addition algorithm is presented as follows: - -| Cost | Processor 1 | Processor 2 | Processor 3 | Processor 4 | -|------------------|--------------------------------|--------------------------------|--------------------------------|--------------------------------| -| | \\( R\_1 \gets Y\_1 - X\_1 \\) | \\( R\_2 \gets Y\_2 - X\_2 \\) | \\( R\_3 \gets Y\_1 + X\_1 \\) | \\( R\_4 \gets Y\_2 + X\_2 \\) | -| \\(1\mathbf M\\) | \\( R\_5 \gets R\_1 R\_2 \\) | \\( R\_6 \gets R\_3 R\_4 \\) | \\( R\_7 \gets T\_1 T\_2 \\) | \\( R\_8 \gets Z\_1 Z\_2 \\) | -| \\(1\mathbf D\\) | idle | idle | \\( R\_7 \gets k R\_7 \\) | \\( R\_8 \gets 2 R\_8 \\) | -| | \\( R\_1 \gets R\_6 - R\_5 \\) | \\( R\_2 \gets R\_8 - R\_7 \\) | \\( R\_3 \gets R\_8 + R\_7 \\) | \\( R\_4 \gets R\_6 + R\_5 \\) | -| \\(1\mathbf M\\) | \\( X\_3 \gets R\_1 R\_2 \\) | \\( Y\_3 \gets R\_3 R\_4 \\) | \\( T\_3 \gets R\_1 R\_4 \\) | \\( Z\_3 \gets R\_2 R\_3 \\) | - -Here \\(\mathbf M\\) and \\(\mathbf S\\) represent the cost of -multiplication and squaring of generic field elements, \\(\mathbf D\\) -represents the cost of multiplication by a curve constant (in this -case \\( k = 2d \\)). - -Notice that the \\(1\mathbf M\\) and \\(1\mathbf S\\) steps are -uniform. The non-uniform steps are all inexpensive additions or -subtractions, with the exception of the multiplication by the curve -constant \\(k = 2d\\): -$$ -R\_7 \gets 2 d R\_7. -$$ - -HWCD suggest parallelising this step by breaking \\(k = 2d\\) into four -parts as \\(k = k_0 + 2\^n k_1 + 2\^{2n} k_2 + 2\^{3n} k_3 \\) and -computing \\(k_i R_7 \\) in parallel. This is quite awkward, but if -the curve constant is a ratio \\( d = d\_1/d\_2 \\), then projective -coordinates allow us to instead compute -$$ -(R\_5, R\_6, R\_7, R\_8) \gets (d\_2 R\_5, d\_2 R\_6, 2d\_1 R\_7, d\_2 R\_8). -$$ -This can be performed as a uniform multiplication by a vector of -constants, and if \\(d\_1, d\_2\\) are small, it is relatively -inexpensive. (This trick was suggested by Mike Hamburg). -In the Curve25519 case, we have -$$ -d = \frac{d\_1}{d\_2} = \frac{-121665}{121666}; -$$ -Since \\(2 \cdot 121666 < 2\^{18}\\), all the constants above fit (up -to sign) in 32 bits, so this can be done in parallel as four -multiplications by small constants \\( (121666, 121666, 2\cdot 121665, -2\cdot 121666) \\), followed by a negation to compute \\( - 2\cdot 121665\\). - -# Modified parallel formulas - -Using the modifications sketched above, we can write SIMD-friendly -versions of the parallel formulas as follows. To avoid confusion with -the original formulas, temporary variables are named \\(S\\) instead -of \\(R\\) and are in static single-assignment form. - -## Addition - -To add points -\\(P_1 = (X_1 : Y_1 : Z_1 : T_1) \\) -and -\\(P_2 = (X_2 : Y_2 : Z_2 : T_2 ) \\), -we compute -$$ -\begin{aligned} -(S\_0 &&,&& S\_1 &&,&& S\_2 &&,&& S\_3 ) -&\gets -(Y\_1 - X\_1&&,&& Y\_1 + X\_1&&,&& Y\_2 - X\_2&&,&& Y\_2 + X\_2) -\\\\ -(S\_4 &&,&& S\_5 &&,&& S\_6 &&,&& S\_7 ) -&\gets -(S\_0 \cdot S\_2&&,&& S\_1 \cdot S\_3&&,&& Z\_1 \cdot Z\_2&&,&& T\_1 \cdot T\_2) -\\\\ -(S\_8 &&,&& S\_9 &&,&& S\_{10} &&,&& S\_{11} ) -&\gets -(d\_2 \cdot S\_4 &&,&& d\_2 \cdot S\_5 &&,&& 2 d\_2 \cdot S\_6 &&,&& 2 d\_1 \cdot S\_7 ) -\\\\ -(S\_{12} &&,&& S\_{13} &&,&& S\_{14} &&,&& S\_{15}) -&\gets -(S\_9 - S\_8&&,&& S\_9 + S\_8&&,&& S\_{10} - S\_{11}&&,&& S\_{10} + S\_{11}) -\\\\ -(X\_3&&,&& Y\_3&&,&& Z\_3&&,&& T\_3) -&\gets -(S\_{12} \cdot S\_{14}&&,&& S\_{15} \cdot S\_{13}&&,&& S\_{15} \cdot S\_{14}&&,&& S\_{12} \cdot S\_{13}) -\end{aligned} -$$ -to obtain \\( P\_3 = (X\_3 : Y\_3 : Z\_3 : T\_3) = P\_1 + P\_2 \\). -This costs \\( 2\mathbf M + 1 \mathbf D\\). - -## Readdition - -If the point \\( P_2 = (X\_2 : Y\_2 : Z\_2 : T\_2) \\) is fixed, we -can cache the multiplication of the curve constants by computing -$$ -\begin{aligned} -(S\_2' &&,&& S\_3' &&,&& Z\_2' &&,&& T\_2' ) -&\gets -(d\_2 \cdot (Y\_2 - X\_2)&&,&& d\_2 \cdot (Y\_1 + X\_1)&&,&& 2d\_2 \cdot Z\_2 &&,&& 2d\_1 \cdot T\_2). -\end{aligned} -$$ -This costs \\( 1\mathbf D\\); with \\( (S\_2', S\_3', Z\_2', T\_2')\\) -in hand, the addition formulas above become -$$ -\begin{aligned} -(S\_0 &&,&& S\_1 &&,&& Z\_1 &&,&& T\_1 ) -&\gets -(Y\_1 - X\_1&&,&& Y\_1 + X\_1&&,&& Z\_1 &&,&& T\_1) -\\\\ -(S\_8 &&,&& S\_9 &&,&& S\_{10} &&,&& S\_{11} ) -&\gets -(S\_0 \cdot S\_2' &&,&& S\_1 \cdot S\_3'&&,&& Z\_1 \cdot Z\_2' &&,&& T\_1 \cdot T\_2') -\\\\ -(S\_{12} &&,&& S\_{13} &&,&& S\_{14} &&,&& S\_{15}) -&\gets -(S\_9 - S\_8&&,&& S\_9 + S\_8&&,&& S\_{10} - S\_{11}&&,&& S\_{10} + S\_{11}) -\\\\ -(X\_3&&,&& Y\_3&&,&& Z\_3&&,&& T\_3) -&\gets -(S\_{12} \cdot S\_{14}&&,&& S\_{15} \cdot S\_{13}&&,&& S\_{15} \cdot S\_{14}&&,&& S\_{12} \cdot S\_{13}) -\end{aligned} -$$ -which costs only \\( 2\mathbf M \\). This precomputation is -essentially similar to the precomputation that HWCD suggest for their -serial formulas. Because the cost of precomputation and then -readdition is the same as addition, it's sufficient to only -implement caching and readdition. - -## Doubling - -The non-uniform portions of the (re)addition formulas have a fairly -regular structure. Unfortunately, this is not the case for the -doubling formulas, which are much less nice. - -To double a point \\( P = (X\_1 : Y\_1 : Z\_1 : T\_1) \\), we compute -$$ -\begin{aligned} -(X\_1 &&,&& Y\_1 &&,&& Z\_1 &&,&& S\_0) -&\gets -(X\_1 &&,&& Y\_1 &&,&& Z\_1 &&,&& X\_1 + Y\_1) -\\\\ -(S\_1 &&,&& S\_2 &&,&& S\_3 &&,&& S\_4 ) -&\gets -(X\_1\^2 &&,&& Y\_1\^2&&,&& Z\_1\^2 &&,&& S\_0\^2) -\\\\ -(S\_5 &&,&& S\_6 &&,&& S\_8 &&,&& S\_9 ) -&\gets -(S\_1 + S\_2 &&,&& S\_1 - S\_2 &&,&& S\_1 + 2S\_3 - S\_2 &&,&& S\_1 + S\_2 - S\_4) -\\\\ -(X\_3 &&,&& Y\_3 &&,&& Z\_3 &&,&& T\_3 ) -&\gets -(S\_8 \cdot S\_9 &&,&& S\_5 \cdot S\_6 &&,&& S\_8 \cdot S\_6 &&,&& S\_5 \cdot S\_9) -\end{aligned} -$$ -to obtain \\( P\_3 = (X\_3 : Y\_3 : Z\_3 : T\_3) = [2]P\_1 \\). - -The intermediate step between the squaring and multiplication requires -a long chain of additions. For the IFMA-based implementation, this is not a problem; for the AVX2-based implementation, it is, but with some care and finesse, it's possible to arrange the computation without requiring an intermediate reduction. - -# Implementation - -These formulas aren't specific to a particular representation of field -element vectors, whose optimum choice is determined by the details of -the instruction set. However, it's not possible to perfectly separate -the implementation of the field element vectors from the -implementation of the point operations. Instead, the [`avx2`] and -[`ifma`] backends provide `ExtendedPoint` and `CachedPoint` types, and -the [`scalar_mul`] code uses one of the backend types by a type alias. - -# Comparison to non-vectorized formulas - -In theory, the parallel Edwards formulas seem to allow a \\(4\\)-way -speedup from parallelism. However, an actual vectorized -implementation has several slowdowns that cut into this speedup. - -First, the parallel formulas can only use the available vector -multiplier. For AVX2, this is a \\( 32 \times 32 \rightarrow 64 -\\)-bit integer multiplier, so the speedup from vectorization must -overcome the disadvantage of losing the \\( 64 \times 64 \rightarrow -128\\)-bit (serial) integer multiplier. The effect of this slowdown -is microarchitecture-dependent, since it requires accounting for the -total number of multiplications and additions and their relative -costs. IFMA allows using a \\( 52 \times 52 \rightarrow 104 \\)-bit -multiplier, but the high and low halves need to be computed -separately, and the reduction requires extra work because it's not -possible to pre-multiply by \\(19\\). - -Second, the parallel doubling formulas incur both a theoretical and -practical slowdown. The parallel formulas described above work on the -\\( \mathbb P\^3 \\) “extended” coordinates. The \\( \mathbb P\^2 \\) -model introduced earlier by [Bernstein, Birkner, Joye, Lange, and -Peters][bbjlp08] allows slightly faster doublings, so HWCD suggest -mixing coordinate systems while performing scalar multiplication -(attributing the idea to [a 1998 paper][cmo98] by Cohen, Miyagi, and -Ono). The \\( T \\) coordinate is not required for doublings, so when -doublings are followed by doublings, its computation can be skipped. -More details on this approach and the different coordinate systems can -be found in the [`curve_models` module documentation][curve_models]. - -Unfortunately, this optimization is not compatible with the parallel -formulas, which cannot save time by skipping a single variable, so the -parallel doubling formulas do slightly more work when counting the -total number of field multiplications and squarings. - -In addition, the parallel doubling formulas have a less regular -pattern of additions and subtractions than the parallel addition -formulas, so the vectorization overhead is proportionately greater. -Both the parallel addition and parallel doubling formulas also require -some shuffling to rearrange data within the vectors, which places more -pressure on the shuffle unit than is desirable. - -This means that the speedup from using a vectorized implementation of -parallel Edwards formulas is likely to be greatest in applications -that do fewer doublings and more additions (like a large multiscalar -multiplication) rather than applications that do fewer additions and -more doublings (like a double-base scalar multiplication). - -Third, Amdahl's law says that the speedup is limited to the portion -which can be parallelized. Normally, the field multiplications -dominate the cost of point operations, but with the IFMA backend, the -multiplications are so fast that the non-parallel additions end up as -a significant portion of the total time. - -Fourth, current Intel CPUs perform thermal throttling when using wide -vector instructions. A detailed description can be found in §15.26 of -[the Intel Optimization Manual][intel], but using wide vector -instructions prevents the core from operating at higher frequencies. -The core can return to the higher-frequency state after 2 -milliseconds, but this timer is reset every time high-power -instructions are used. - -Any speedup from vectorization therefore has to be weighed against a -slowdown for the next few million instructions. For a mixed workload, -where point operations are interspersed with other tasks, this can -reduce overall performance. This implementation is therefore probably -not suitable for basic applications, like signatures, but is -worthwhile for complex applications, like zero-knowledge proofs, which -do sustained work. - -# Future work - -There are several directions for future improvement: - -* Using the vectorized field arithmetic code to parallelize across - point operations rather than within a single point operation. This - is less flexible, but would give a speedup both from allowing use of - the faster mixed-model arithmetic and from reducing shuffle - pressure. One approach in this direction would be to implement - batched scalar-point operations using vectors of points (AoSoA - layout). This less generally useful but would give a speedup for - Bulletproofs. - -* Extending the IFMA implementation to use the full width of AVX512, - either handling the extra parallelism internally to a single point - operation (by using a 2-way parallel implementation of field - arithmetic instead of a wordsliced one), or externally, - parallelizing across point operations. Internal parallelism would - be preferable but might require too much shuffle pressure. For now, - the only available CPU which runs IFMA operations executes them at - 256-bits wide anyways, so this isn't yet important. - -* Generalizing the implementation to NEON instructions. The current - point arithmetic code is written in terms of field element vectors, - which are in turn implemented using platform SIMD vectors. It - should be possible to write an alternate implementation of the - `FieldElement2625x4` using NEON without changing the point - arithmetic. NEON has 128-bit vectors rather than 256-bit vectors, - but this may still be worthwhile compared to a serial - implementation. - - -[sandy2x]: https://eprint.iacr.org/2015/943.pdf -[avx2trac]: https://trac.torproject.org/projects/tor/ticket/8897#comment:28 -[hwcd08]: https://www.iacr.org/archive/asiacrypt2008/53500329/53500329.pdf -[curve_models]: https://doc-internal.dalek.rs/curve25519_dalek/backend/serial/curve_models/index.html -[bbjlp08]: https://eprint.iacr.org/2008/013 -[cmo98]: https://link.springer.com/content/pdf/10.1007%2F3-540-49649-1_6.pdf -[intel]: https://software.intel.com/sites/default/files/managed/9e/bc/64-ia-32-architectures-optimization-manual.pdf diff --git a/net/gurk-rs/files/vendor/curve25519-dalek/src/backend/mod.rs b/net/gurk-rs/files/vendor/curve25519-dalek/src/backend/mod.rs deleted file mode 100644 index 18f8af7..0000000 --- a/net/gurk-rs/files/vendor/curve25519-dalek/src/backend/mod.rs +++ /dev/null @@ -1,65 +0,0 @@ -// -*- mode: rust; -*- -// -// This file is part of curve25519-dalek. -// Copyright (c) 2016-2021 isis lovecruft -// Copyright (c) 2016-2019 Henry de Valence -// See LICENSE for licensing information. -// -// Authors: -// - isis agora lovecruft -// - Henry de Valence - -//! Pluggable implementations for different architectures. -//! -//! The backend code is split into two parts: a serial backend, -//! and a vector backend. -//! -//! The [`serial`] backend contains 32- and 64-bit implementations of -//! field arithmetic and scalar arithmetic, as well as implementations -//! of point operations using the mixed-model strategy (passing -//! between different curve models depending on the operation). -//! -//! The [`vector`] backend contains implementations of vectorized -//! field arithmetic, used to implement point operations using a novel -//! implementation strategy derived from parallel formulas of Hisil, -//! Wong, Carter, and Dawson. -//! -//! Because the two strategies give rise to different curve models, -//! it's not possible to reuse exactly the same scalar multiplication -//! code (or to write it generically), so both serial and vector -//! backends contain matching implementations of scalar multiplication -//! algorithms. These are intended to be selected by a `#[cfg]`-based -//! type alias. -//! -//! The [`vector`] backend is selected by the `simd_backend` cargo -//! feature; it uses the [`serial`] backend for non-vectorized operations. - -#[cfg(not(any( - feature = "u32_backend", - feature = "u64_backend", - feature = "fiat_u32_backend", - feature = "fiat_u64_backend", - feature = "simd_backend", -)))] -compile_error!( - "no curve25519-dalek backend cargo feature enabled! \ - please enable one of: u32_backend, u64_backend, fiat_u32_backend, fiat_u64_backend, simd_backend" -); - -pub mod serial; - -#[cfg(any( - all( - feature = "simd_backend", - any(target_feature = "avx2", target_feature = "avx512ifma") - ), - all(feature = "nightly", rustdoc) -))] -#[cfg_attr( - feature = "nightly", - doc(cfg(any(all( - feature = "simd_backend", - any(target_feature = "avx2", target_feature = "avx512ifma") - )))) -)] -pub mod vector; diff --git a/net/gurk-rs/files/vendor/curve25519-dalek/src/backend/serial/curve_models/mod.rs b/net/gurk-rs/files/vendor/curve25519-dalek/src/backend/serial/curve_models/mod.rs deleted file mode 100644 index 9d10d92..0000000 --- a/net/gurk-rs/files/vendor/curve25519-dalek/src/backend/serial/curve_models/mod.rs +++ /dev/null @@ -1,551 +0,0 @@ -// -*- mode: rust; -*- -// -// This file is part of curve25519-dalek. -// Copyright (c) 2016-2021 isis lovecruft -// Copyright (c) 2016-2019 Henry de Valence -// See LICENSE for licensing information. -// -// Authors: -// - isis agora lovecruft -// - Henry de Valence - -//! Internal curve representations which are not part of the public API. -//! -//! # Curve representations -//! -//! Internally, we use several different models for the curve. Here -//! is a sketch of the relationship between the models, following [a -//! post][smith-moderncrypto] -//! by Ben Smith on the `moderncrypto` mailing list. This is also briefly -//! discussed in section 2.5 of [_Montgomery curves and their -//! arithmetic_][costello-smith-2017] by Costello and Smith. -//! -//! Begin with the affine equation for the curve, -//! $$ -//! -x\^2 + y\^2 = 1 + dx\^2y\^2. -//! $$ -//! Next, pass to the projective closure \\(\mathbb P\^1 \times \mathbb -//! P\^1 \\) by setting \\(x=X/Z\\), \\(y=Y/T.\\) Clearing denominators -//! gives the model -//! $$ -//! -X\^2T\^2 + Y\^2Z\^2 = Z\^2T\^2 + dX\^2Y\^2. -//! $$ -//! In `curve25519-dalek`, this is represented as the `CompletedPoint` -//! struct. -//! To map from \\(\mathbb P\^1 \times \mathbb P\^1 \\), a product of -//! two lines, to \\(\mathbb P\^3\\), we use the [Segre -//! embedding](https://en.wikipedia.org/wiki/Segre_embedding) -//! $$ -//! \sigma : ((X:Z),(Y:T)) \mapsto (XY:XT:ZY:ZT). -//! $$ -//! Using coordinates \\( (W_0:W_1:W_2:W_3) \\) for \\(\mathbb P\^3\\), -//! the image \\(\sigma (\mathbb P\^1 \times \mathbb P\^1) \\) is the -//! surface defined by \\( W_0 W_3 = W_1 W_2 \\), and under \\( -//! \sigma\\), the equation above becomes -//! $$ -//! -W\_1\^2 + W\_2\^2 = W\_3\^2 + dW\_0\^2, -//! $$ -//! so that the curve is given by the pair of equations -//! $$ -//! \begin{aligned} -//! -W\_1\^2 + W\_2\^2 &= W\_3\^2 + dW\_0\^2, \\\\ W_0 W_3 &= W_1 W_2. -//! \end{aligned} -//! $$ -//! Up to variable naming, this is exactly the "extended" curve model -//! introduced in [_Twisted Edwards Curves -//! Revisited_][hisil-wong-carter-dawson-2008] by Hisil, Wong, Carter, -//! and Dawson. In `curve25519-dalek`, it is represented as the -//! `EdwardsPoint` struct. We can map from \\(\mathbb P\^3 \\) to -//! \\(\mathbb P\^2 \\) by sending \\( (W\_0:W\_1:W\_2:W\_3) \\) to \\( -//! (W\_1:W\_2:W\_3) \\). Notice that -//! $$ -//! \frac {W\_1} {W\_3} = \frac {XT} {ZT} = \frac X Z = x, -//! $$ -//! and -//! $$ -//! \frac {W\_2} {W\_3} = \frac {YZ} {ZT} = \frac Y T = y, -//! $$ -//! so this is the same as if we had started with the affine model -//! and passed to \\( \mathbb P\^2 \\) by setting \\( x = W\_1 / W\_3 -//! \\), \\(y = W\_2 / W\_3 \\). -//! Up to variable naming, this is the projective representation -//! introduced in in [_Twisted Edwards -//! Curves_][bernstein-birkner-joye-lange-peters-2008] by Bernstein, -//! Birkner, Joye, Lange, and Peters. In `curve25519-dalek`, it is -//! represented by the `ProjectivePoint` struct. -//! -//! # Passing between curve models -//! -//! Although the \\( \mathbb P\^3 \\) model provides faster addition -//! formulas, the \\( \mathbb P\^2 \\) model provides faster doubling -//! formulas. Hisil, Wong, Carter, and Dawson therefore suggest mixing -//! coordinate systems for scalar multiplication, attributing the idea -//! to [a 1998 paper][cohen-miyaji-ono-1998] of Cohen, Miyagi, and Ono. -//! -//! Their suggestion is to vary the formulas used by context, using a -//! \\( \mathbb P\^2 \rightarrow \mathbb P\^2 \\) doubling formula when -//! a doubling is followed -//! by another doubling, a \\( \mathbb P\^2 \rightarrow \mathbb P\^3 \\) -//! doubling formula when a doubling is followed by an addition, and -//! computing point additions using a \\( \mathbb P\^3 \times \mathbb P\^3 -//! \rightarrow \mathbb P\^2 \\) formula. -//! -//! The `ref10` reference implementation of [Ed25519][ed25519], by -//! Bernstein, Duif, Lange, Schwabe, and Yang, tweaks -//! this strategy, factoring the addition formulas through the -//! completion \\( \mathbb P\^1 \times \mathbb P\^1 \\), so that the -//! output of an addition or doubling always lies in \\( \mathbb P\^1 \times -//! \mathbb P\^1\\), and the choice of which formula to use is replaced -//! by a choice of whether to convert the result to \\( \mathbb P\^2 \\) -//! or \\(\mathbb P\^3 \\). However, this tweak is not described in -//! their paper, only in their software. -//! -//! Our naming for the `CompletedPoint` (\\(\mathbb P\^1 \times \mathbb -//! P\^1 \\)), `ProjectivePoint` (\\(\mathbb P\^2 \\)), and -//! `EdwardsPoint` (\\(\mathbb P\^3 \\)) structs follows the naming in -//! Adam Langley's [Golang ed25519][agl-ed25519] implementation, which -//! `curve25519-dalek` was originally derived from. -//! -//! Finally, to accelerate readditions, we use two cached point formats -//! in "Niels coordinates", named for Niels Duif, -//! one for the affine model and one for the \\( \mathbb P\^3 \\) model: -//! -//! * `AffineNielsPoint`: \\( (y+x, y-x, 2dxy) \\) -//! * `ProjectiveNielsPoint`: \\( (Y+X, Y-X, Z, 2dXY) \\) -//! -//! [smith-moderncrypto]: https://moderncrypto.org/mail-archive/curves/2016/000807.html -//! [costello-smith-2017]: https://eprint.iacr.org/2017/212 -//! [hisil-wong-carter-dawson-2008]: https://www.iacr.org/archive/asiacrypt2008/53500329/53500329.pdf -//! [bernstein-birkner-joye-lange-peters-2008]: https://eprint.iacr.org/2008/013 -//! [cohen-miyaji-ono-1998]: https://link.springer.com/content/pdf/10.1007%2F3-540-49649-1_6.pdf -//! [ed25519]: https://eprint.iacr.org/2011/368 -//! [agl-ed25519]: https://github.com/agl/ed25519 - -#![allow(non_snake_case)] - -use core::fmt::Debug; -use core::ops::{Add, Neg, Sub}; - -use subtle::Choice; -use subtle::ConditionallySelectable; - -use zeroize::Zeroize; - -use constants; - -use edwards::EdwardsPoint; -use field::FieldElement; -use traits::ValidityCheck; - -// ------------------------------------------------------------------------ -// Internal point representations -// ------------------------------------------------------------------------ - -/// A `ProjectivePoint` is a point \\((X:Y:Z)\\) on the \\(\mathbb -/// P\^2\\) model of the curve. -/// A point \\((x,y)\\) in the affine model corresponds to -/// \\((x:y:1)\\). -/// -/// More details on the relationships between the different curve models -/// can be found in the module-level documentation. -#[derive(Copy, Clone)] -pub struct ProjectivePoint { - pub X: FieldElement, - pub Y: FieldElement, - pub Z: FieldElement, -} - -/// A `CompletedPoint` is a point \\(((X:Z), (Y:T))\\) on the \\(\mathbb -/// P\^1 \times \mathbb P\^1 \\) model of the curve. -/// A point (x,y) in the affine model corresponds to \\( ((x:1),(y:1)) -/// \\). -/// -/// More details on the relationships between the different curve models -/// can be found in the module-level documentation. -#[derive(Copy, Clone)] -#[allow(missing_docs)] -pub struct CompletedPoint { - pub X: FieldElement, - pub Y: FieldElement, - pub Z: FieldElement, - pub T: FieldElement, -} - -/// A pre-computed point in the affine model for the curve, represented as -/// \\((y+x, y-x, 2dxy)\\) in "Niels coordinates". -/// -/// More details on the relationships between the different curve models -/// can be found in the module-level documentation. -// Safe to derive Eq because affine coordinates. -#[derive(Copy, Clone, Eq, PartialEq)] -#[allow(missing_docs)] -pub struct AffineNielsPoint { - pub y_plus_x: FieldElement, - pub y_minus_x: FieldElement, - pub xy2d: FieldElement, -} - -impl Zeroize for AffineNielsPoint { - fn zeroize(&mut self) { - self.y_plus_x.zeroize(); - self.y_minus_x.zeroize(); - self.xy2d.zeroize(); - } -} - -/// A pre-computed point on the \\( \mathbb P\^3 \\) model for the -/// curve, represented as \\((Y+X, Y-X, Z, 2dXY)\\) in "Niels coordinates". -/// -/// More details on the relationships between the different curve models -/// can be found in the module-level documentation. -#[derive(Copy, Clone)] -pub struct ProjectiveNielsPoint { - pub Y_plus_X: FieldElement, - pub Y_minus_X: FieldElement, - pub Z: FieldElement, - pub T2d: FieldElement, -} - -impl Zeroize for ProjectiveNielsPoint { - fn zeroize(&mut self) { - self.Y_plus_X.zeroize(); - self.Y_minus_X.zeroize(); - self.Z.zeroize(); - self.T2d.zeroize(); - } -} - -// ------------------------------------------------------------------------ -// Constructors -// ------------------------------------------------------------------------ - -use traits::Identity; - -impl Identity for ProjectivePoint { - fn identity() -> ProjectivePoint { - ProjectivePoint { - X: FieldElement::zero(), - Y: FieldElement::one(), - Z: FieldElement::one(), - } - } -} - -impl Identity for ProjectiveNielsPoint { - fn identity() -> ProjectiveNielsPoint { - ProjectiveNielsPoint{ - Y_plus_X: FieldElement::one(), - Y_minus_X: FieldElement::one(), - Z: FieldElement::one(), - T2d: FieldElement::zero(), - } - } -} - -impl Default for ProjectiveNielsPoint { - fn default() -> ProjectiveNielsPoint { - ProjectiveNielsPoint::identity() - } -} - -impl Identity for AffineNielsPoint { - fn identity() -> AffineNielsPoint { - AffineNielsPoint{ - y_plus_x: FieldElement::one(), - y_minus_x: FieldElement::one(), - xy2d: FieldElement::zero(), - } - } -} - -impl Default for AffineNielsPoint { - fn default() -> AffineNielsPoint { - AffineNielsPoint::identity() - } -} - -// ------------------------------------------------------------------------ -// Validity checks (for debugging, not CT) -// ------------------------------------------------------------------------ - -impl ValidityCheck for ProjectivePoint { - fn is_valid(&self) -> bool { - // Curve equation is -x^2 + y^2 = 1 + d*x^2*y^2, - // homogenized as (-X^2 + Y^2)*Z^2 = Z^4 + d*X^2*Y^2 - let XX = self.X.square(); - let YY = self.Y.square(); - let ZZ = self.Z.square(); - let ZZZZ = ZZ.square(); - let lhs = &(&YY - &XX) * &ZZ; - let rhs = &ZZZZ + &(&constants::EDWARDS_D * &(&XX * &YY)); - - lhs == rhs - } -} - -// ------------------------------------------------------------------------ -// Constant-time assignment -// ------------------------------------------------------------------------ - -impl ConditionallySelectable for ProjectiveNielsPoint { - fn conditional_select(a: &Self, b: &Self, choice: Choice) -> Self { - ProjectiveNielsPoint { - Y_plus_X: FieldElement::conditional_select(&a.Y_plus_X, &b.Y_plus_X, choice), - Y_minus_X: FieldElement::conditional_select(&a.Y_minus_X, &b.Y_minus_X, choice), - Z: FieldElement::conditional_select(&a.Z, &b.Z, choice), - T2d: FieldElement::conditional_select(&a.T2d, &b.T2d, choice), - } - } - - fn conditional_assign(&mut self, other: &Self, choice: Choice) { - self.Y_plus_X.conditional_assign(&other.Y_plus_X, choice); - self.Y_minus_X.conditional_assign(&other.Y_minus_X, choice); - self.Z.conditional_assign(&other.Z, choice); - self.T2d.conditional_assign(&other.T2d, choice); - } -} - -impl ConditionallySelectable for AffineNielsPoint { - fn conditional_select(a: &Self, b: &Self, choice: Choice) -> Self { - AffineNielsPoint { - y_plus_x: FieldElement::conditional_select(&a.y_plus_x, &b.y_plus_x, choice), - y_minus_x: FieldElement::conditional_select(&a.y_minus_x, &b.y_minus_x, choice), - xy2d: FieldElement::conditional_select(&a.xy2d, &b.xy2d, choice), - } - } - - fn conditional_assign(&mut self, other: &Self, choice: Choice) { - self.y_plus_x.conditional_assign(&other.y_plus_x, choice); - self.y_minus_x.conditional_assign(&other.y_minus_x, choice); - self.xy2d.conditional_assign(&other.xy2d, choice); - } -} - -// ------------------------------------------------------------------------ -// Point conversions -// ------------------------------------------------------------------------ - -impl ProjectivePoint { - /// Convert this point from the \\( \mathbb P\^2 \\) model to the - /// \\( \mathbb P\^3 \\) model. - /// - /// This costs \\(3 \mathrm M + 1 \mathrm S\\). - pub fn to_extended(&self) -> EdwardsPoint { - EdwardsPoint { - X: &self.X * &self.Z, - Y: &self.Y * &self.Z, - Z: self.Z.square(), - T: &self.X * &self.Y, - } - } -} - -impl CompletedPoint { - /// Convert this point from the \\( \mathbb P\^1 \times \mathbb P\^1 - /// \\) model to the \\( \mathbb P\^2 \\) model. - /// - /// This costs \\(3 \mathrm M \\). - pub fn to_projective(&self) -> ProjectivePoint { - ProjectivePoint { - X: &self.X * &self.T, - Y: &self.Y * &self.Z, - Z: &self.Z * &self.T, - } - } - - /// Convert this point from the \\( \mathbb P\^1 \times \mathbb P\^1 - /// \\) model to the \\( \mathbb P\^3 \\) model. - /// - /// This costs \\(4 \mathrm M \\). - pub fn to_extended(&self) -> EdwardsPoint { - EdwardsPoint { - X: &self.X * &self.T, - Y: &self.Y * &self.Z, - Z: &self.Z * &self.T, - T: &self.X * &self.Y, - } - } -} - -// ------------------------------------------------------------------------ -// Doubling -// ------------------------------------------------------------------------ - -impl ProjectivePoint { - /// Double this point: return self + self - pub fn double(&self) -> CompletedPoint { // Double() - let XX = self.X.square(); - let YY = self.Y.square(); - let ZZ2 = self.Z.square2(); - let X_plus_Y = &self.X + &self.Y; - let X_plus_Y_sq = X_plus_Y.square(); - let YY_plus_XX = &YY + &XX; - let YY_minus_XX = &YY - &XX; - - CompletedPoint{ - X: &X_plus_Y_sq - &YY_plus_XX, - Y: YY_plus_XX, - Z: YY_minus_XX, - T: &ZZ2 - &YY_minus_XX - } - } -} - -// ------------------------------------------------------------------------ -// Addition and Subtraction -// ------------------------------------------------------------------------ - -// XXX(hdevalence) These were doc(hidden) so they don't appear in the -// public API docs. -// However, that prevents them being used with --document-private-items, -// so comment out the doc(hidden) for now until this is resolved -// -// upstream rust issue: https://github.com/rust-lang/rust/issues/46380 -//#[doc(hidden)] -impl<'a, 'b> Add<&'b ProjectiveNielsPoint> for &'a EdwardsPoint { - type Output = CompletedPoint; - - fn add(self, other: &'b ProjectiveNielsPoint) -> CompletedPoint { - let Y_plus_X = &self.Y + &self.X; - let Y_minus_X = &self.Y - &self.X; - let PP = &Y_plus_X * &other.Y_plus_X; - let MM = &Y_minus_X * &other.Y_minus_X; - let TT2d = &self.T * &other.T2d; - let ZZ = &self.Z * &other.Z; - let ZZ2 = &ZZ + &ZZ; - - CompletedPoint{ - X: &PP - &MM, - Y: &PP + &MM, - Z: &ZZ2 + &TT2d, - T: &ZZ2 - &TT2d - } - } -} - -//#[doc(hidden)] -impl<'a, 'b> Sub<&'b ProjectiveNielsPoint> for &'a EdwardsPoint { - type Output = CompletedPoint; - - fn sub(self, other: &'b ProjectiveNielsPoint) -> CompletedPoint { - let Y_plus_X = &self.Y + &self.X; - let Y_minus_X = &self.Y - &self.X; - let PM = &Y_plus_X * &other.Y_minus_X; - let MP = &Y_minus_X * &other.Y_plus_X; - let TT2d = &self.T * &other.T2d; - let ZZ = &self.Z * &other.Z; - let ZZ2 = &ZZ + &ZZ; - - CompletedPoint{ - X: &PM - &MP, - Y: &PM + &MP, - Z: &ZZ2 - &TT2d, - T: &ZZ2 + &TT2d - } - } -} - -//#[doc(hidden)] -impl<'a, 'b> Add<&'b AffineNielsPoint> for &'a EdwardsPoint { - type Output = CompletedPoint; - - fn add(self, other: &'b AffineNielsPoint) -> CompletedPoint { - let Y_plus_X = &self.Y + &self.X; - let Y_minus_X = &self.Y - &self.X; - let PP = &Y_plus_X * &other.y_plus_x; - let MM = &Y_minus_X * &other.y_minus_x; - let Txy2d = &self.T * &other.xy2d; - let Z2 = &self.Z + &self.Z; - - CompletedPoint{ - X: &PP - &MM, - Y: &PP + &MM, - Z: &Z2 + &Txy2d, - T: &Z2 - &Txy2d - } - } -} - -//#[doc(hidden)] -impl<'a, 'b> Sub<&'b AffineNielsPoint> for &'a EdwardsPoint { - type Output = CompletedPoint; - - fn sub(self, other: &'b AffineNielsPoint) -> CompletedPoint { - let Y_plus_X = &self.Y + &self.X; - let Y_minus_X = &self.Y - &self.X; - let PM = &Y_plus_X * &other.y_minus_x; - let MP = &Y_minus_X * &other.y_plus_x; - let Txy2d = &self.T * &other.xy2d; - let Z2 = &self.Z + &self.Z; - - CompletedPoint{ - X: &PM - &MP, - Y: &PM + &MP, - Z: &Z2 - &Txy2d, - T: &Z2 + &Txy2d - } - } -} - -// ------------------------------------------------------------------------ -// Negation -// ------------------------------------------------------------------------ - -impl<'a> Neg for &'a ProjectiveNielsPoint { - type Output = ProjectiveNielsPoint; - - fn neg(self) -> ProjectiveNielsPoint { - ProjectiveNielsPoint{ - Y_plus_X: self.Y_minus_X, - Y_minus_X: self.Y_plus_X, - Z: self.Z, - T2d: -(&self.T2d), - } - } -} - -impl<'a> Neg for &'a AffineNielsPoint { - type Output = AffineNielsPoint; - - fn neg(self) -> AffineNielsPoint { - AffineNielsPoint{ - y_plus_x: self.y_minus_x, - y_minus_x: self.y_plus_x, - xy2d: -(&self.xy2d) - } - } -} - -// ------------------------------------------------------------------------ -// Debug traits -// ------------------------------------------------------------------------ - -impl Debug for ProjectivePoint { - fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { - write!(f, "ProjectivePoint{{\n\tX: {:?},\n\tY: {:?},\n\tZ: {:?}\n}}", - &self.X, &self.Y, &self.Z) - } -} - -impl Debug for CompletedPoint { - fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { - write!(f, "CompletedPoint{{\n\tX: {:?},\n\tY: {:?},\n\tZ: {:?},\n\tT: {:?}\n}}", - &self.X, &self.Y, &self.Z, &self.T) - } -} - -impl Debug for AffineNielsPoint { - fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { - write!(f, "AffineNielsPoint{{\n\ty_plus_x: {:?},\n\ty_minus_x: {:?},\n\txy2d: {:?}\n}}", - &self.y_plus_x, &self.y_minus_x, &self.xy2d) - } -} - -impl Debug for ProjectiveNielsPoint { - fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { - write!(f, "ProjectiveNielsPoint{{\n\tY_plus_X: {:?},\n\tY_minus_X: {:?},\n\tZ: {:?},\n\tT2d: {:?}\n}}", - &self.Y_plus_X, &self.Y_minus_X, &self.Z, &self.T2d) - } -} - - diff --git a/net/gurk-rs/files/vendor/curve25519-dalek/src/backend/serial/fiat_u32/field.rs b/net/gurk-rs/files/vendor/curve25519-dalek/src/backend/serial/fiat_u32/field.rs deleted file mode 100644 index 2864c95..0000000 --- a/net/gurk-rs/files/vendor/curve25519-dalek/src/backend/serial/fiat_u32/field.rs +++ /dev/null @@ -1,260 +0,0 @@ -// -*- mode: rust; coding: utf-8; -*- -// -// This file is part of curve25519-dalek. -// Copyright (c) 2016-2018 Isis Lovecruft, Henry de Valence -// See LICENSE for licensing information. -// -// Authors: -// - Isis Agora Lovecruft -// - Henry de Valence - -//! Field arithmetic modulo \\(p = 2\^{255} - 19\\), using \\(32\\)-bit -//! limbs with \\(64\\)-bit products. -//! -//! This code was originally derived from Adam Langley's Golang ed25519 -//! implementation, and was then rewritten to use unsigned limbs instead -//! of signed limbs. -//! -//! This uses the formally-verified field arithmetic generated by the -//! [fiat-crypto project](https://github.com/mit-plv/fiat-crypto) - -use core::fmt::Debug; -use core::ops::Neg; -use core::ops::{Add, AddAssign}; -use core::ops::{Mul, MulAssign}; -use core::ops::{Sub, SubAssign}; - -use subtle::Choice; -use subtle::ConditionallySelectable; - -use zeroize::Zeroize; - -use fiat_crypto::curve25519_32::*; - -/// A `FieldElement2625` represents an element of the field -/// \\( \mathbb Z / (2\^{255} - 19)\\). -/// -/// In the 32-bit implementation, a `FieldElement` is represented in -/// radix \\(2\^{25.5}\\) as ten `u32`s. This means that a field -/// element \\(x\\) is represented as -/// $$ -/// x = \sum\_{i=0}\^9 x\_i 2\^{\lceil i \frac {51} 2 \rceil} -/// = x\_0 + x\_1 2\^{26} + x\_2 2\^{51} + x\_3 2\^{77} + \cdots + x\_9 2\^{230}; -/// $$ -/// the coefficients are alternately bounded by \\(2\^{25}\\) and -/// \\(2\^{26}\\). The limbs are allowed to grow between reductions up -/// to \\(2\^{25+b}\\) or \\(2\^{26+b}\\), where \\(b = 1.75\\). -/// -/// # Note -/// -/// The `curve25519_dalek::field` module provides a type alias -/// `curve25519_dalek::field::FieldElement` to either `FieldElement51` -/// or `FieldElement2625`. -/// -/// The backend-specific type `FieldElement2625` should not be used -/// outside of the `curve25519_dalek::field` module. -#[derive(Copy, Clone)] -pub struct FieldElement2625(pub(crate) [u32; 10]); - -impl Debug for FieldElement2625 { - fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { - write!(f, "FieldElement2625({:?})", &self.0[..]) - } -} - -impl Zeroize for FieldElement2625 { - fn zeroize(&mut self) { - self.0.zeroize(); - } -} - -impl<'b> AddAssign<&'b FieldElement2625> for FieldElement2625 { - fn add_assign(&mut self, _rhs: &'b FieldElement2625) { - let input = self.0; - fiat_25519_add(&mut self.0, &input, &_rhs.0); - let input = self.0; - fiat_25519_carry(&mut self.0, &input); - } -} - -impl<'a, 'b> Add<&'b FieldElement2625> for &'a FieldElement2625 { - type Output = FieldElement2625; - fn add(self, _rhs: &'b FieldElement2625) -> FieldElement2625 { - let mut output = *self; - fiat_25519_add(&mut output.0, &self.0, &_rhs.0); - let input = output.0; - fiat_25519_carry(&mut output.0, &input); - output - } -} - -impl<'b> SubAssign<&'b FieldElement2625> for FieldElement2625 { - fn sub_assign(&mut self, _rhs: &'b FieldElement2625) { - let input = self.0; - fiat_25519_sub(&mut self.0, &input, &_rhs.0); - let input = self.0; - fiat_25519_carry(&mut self.0, &input); - } -} - -impl<'a, 'b> Sub<&'b FieldElement2625> for &'a FieldElement2625 { - type Output = FieldElement2625; - fn sub(self, _rhs: &'b FieldElement2625) -> FieldElement2625 { - let mut output = *self; - fiat_25519_sub(&mut output.0, &self.0, &_rhs.0); - let input = output.0; - fiat_25519_carry(&mut output.0, &input); - output - } -} - -impl<'b> MulAssign<&'b FieldElement2625> for FieldElement2625 { - fn mul_assign(&mut self, _rhs: &'b FieldElement2625) { - let input = self.0; - fiat_25519_carry_mul(&mut self.0, &input, &_rhs.0); - } -} - -impl<'a, 'b> Mul<&'b FieldElement2625> for &'a FieldElement2625 { - type Output = FieldElement2625; - fn mul(self, _rhs: &'b FieldElement2625) -> FieldElement2625 { - let mut output = *self; - fiat_25519_carry_mul(&mut output.0, &self.0, &_rhs.0); - output - } -} - -impl<'a> Neg for &'a FieldElement2625 { - type Output = FieldElement2625; - fn neg(self) -> FieldElement2625 { - let mut output = *self; - fiat_25519_opp(&mut output.0, &self.0); - let input = output.0; - fiat_25519_carry(&mut output.0, &input); - output - } -} - -impl ConditionallySelectable for FieldElement2625 { - fn conditional_select( - a: &FieldElement2625, - b: &FieldElement2625, - choice: Choice, - ) -> FieldElement2625 { - let mut output = [0u32; 10]; - fiat_25519_selectznz(&mut output, choice.unwrap_u8() as fiat_25519_u1, &a.0, &b.0); - FieldElement2625(output) - } - - fn conditional_assign(&mut self, other: &FieldElement2625, choice: Choice) { - let mut output = [0u32; 10]; - let choicebit = choice.unwrap_u8() as fiat_25519_u1; - fiat_25519_cmovznz_u32(&mut output[0], choicebit, self.0[0], other.0[0]); - fiat_25519_cmovznz_u32(&mut output[1], choicebit, self.0[1], other.0[1]); - fiat_25519_cmovznz_u32(&mut output[2], choicebit, self.0[2], other.0[2]); - fiat_25519_cmovznz_u32(&mut output[3], choicebit, self.0[3], other.0[3]); - fiat_25519_cmovznz_u32(&mut output[4], choicebit, self.0[4], other.0[4]); - fiat_25519_cmovznz_u32(&mut output[5], choicebit, self.0[5], other.0[5]); - fiat_25519_cmovznz_u32(&mut output[6], choicebit, self.0[6], other.0[6]); - fiat_25519_cmovznz_u32(&mut output[7], choicebit, self.0[7], other.0[7]); - fiat_25519_cmovznz_u32(&mut output[8], choicebit, self.0[8], other.0[8]); - fiat_25519_cmovznz_u32(&mut output[9], choicebit, self.0[9], other.0[9]); - *self = FieldElement2625(output); - } - - fn conditional_swap(a: &mut FieldElement2625, b: &mut FieldElement2625, choice: Choice) { - u32::conditional_swap(&mut a.0[0], &mut b.0[0], choice); - u32::conditional_swap(&mut a.0[1], &mut b.0[1], choice); - u32::conditional_swap(&mut a.0[2], &mut b.0[2], choice); - u32::conditional_swap(&mut a.0[3], &mut b.0[3], choice); - u32::conditional_swap(&mut a.0[4], &mut b.0[4], choice); - u32::conditional_swap(&mut a.0[5], &mut b.0[5], choice); - u32::conditional_swap(&mut a.0[6], &mut b.0[6], choice); - u32::conditional_swap(&mut a.0[7], &mut b.0[7], choice); - u32::conditional_swap(&mut a.0[8], &mut b.0[8], choice); - u32::conditional_swap(&mut a.0[9], &mut b.0[9], choice); - } -} - -impl FieldElement2625 { - /// Invert the sign of this field element - pub fn negate(&mut self) { - let neg = self.neg(); - self.0 = neg.0; - } - - /// Construct zero. - pub fn zero() -> FieldElement2625 { - FieldElement2625([0, 0, 0, 0, 0, 0, 0, 0, 0, 0]) - } - - /// Construct one. - pub fn one() -> FieldElement2625 { - FieldElement2625([1, 0, 0, 0, 0, 0, 0, 0, 0, 0]) - } - - /// Construct -1. - pub fn minus_one() -> FieldElement2625 { - FieldElement2625([ - 0x3ffffec, 0x1ffffff, 0x3ffffff, 0x1ffffff, 0x3ffffff, 0x1ffffff, 0x3ffffff, 0x1ffffff, - 0x3ffffff, 0x1ffffff, - ]) - } - - /// Given `k > 0`, return `self^(2^k)`. - pub fn pow2k(&self, k: u32) -> FieldElement2625 { - debug_assert!(k > 0); - let mut z = self.square(); - for _ in 1..k { - z = z.square(); - } - z - } - - /// Load a `FieldElement2625` from the low 255 bits of a 256-bit - /// input. - /// - /// # Warning - /// - /// This function does not check that the input used the canonical - /// representative. It masks the high bit, but it will happily - /// decode 2^255 - 18 to 1. Applications that require a canonical - /// encoding of every field element should decode, re-encode to - /// the canonical encoding, and check that the input was - /// canonical. - pub fn from_bytes(data: &[u8; 32]) -> FieldElement2625 { - let mut temp = [0u8; 32]; - temp.copy_from_slice(data); - temp[31] &= 127u8; - let mut output = [0u32; 10]; - fiat_25519_from_bytes(&mut output, &temp); - FieldElement2625(output) - } - - /// Serialize this `FieldElement51` to a 32-byte array. The - /// encoding is canonical. - pub fn to_bytes(&self) -> [u8; 32] { - let mut bytes = [0u8; 32]; - fiat_25519_to_bytes(&mut bytes, &self.0); - return bytes; - } - - /// Compute `self^2`. - pub fn square(&self) -> FieldElement2625 { - let mut output = *self; - fiat_25519_carry_square(&mut output.0, &self.0); - output - } - - /// Compute `2*self^2`. - pub fn square2(&self) -> FieldElement2625 { - let mut output = *self; - let mut temp = *self; - // Void vs return type, measure cost of copying self - fiat_25519_carry_square(&mut temp.0, &self.0); - fiat_25519_add(&mut output.0, &temp.0, &temp.0); - let input = output.0; - fiat_25519_carry(&mut output.0, &input); - output - } -} diff --git a/net/gurk-rs/files/vendor/curve25519-dalek/src/backend/serial/fiat_u32/mod.rs b/net/gurk-rs/files/vendor/curve25519-dalek/src/backend/serial/fiat_u32/mod.rs deleted file mode 100644 index 974316e..0000000 --- a/net/gurk-rs/files/vendor/curve25519-dalek/src/backend/serial/fiat_u32/mod.rs +++ /dev/null @@ -1,26 +0,0 @@ -// -*- mode: rust; -*- -// -// This file is part of curve25519-dalek. -// Copyright (c) 2016-2018 Isis Lovecruft, Henry de Valence -// See LICENSE for licensing information. -// -// Authors: -// - Isis Agora Lovecruft -// - Henry de Valence - -//! The `u32` backend uses `u32`s and a `(u32, u32) -> u64` multiplier. -//! -//! This code is intended to be portable, but it requires that -//! multiplication of two \\(32\\)-bit values to a \\(64\\)-bit result -//! is constant-time on the target platform. -//! -//! This uses the formally-verified field arithmetic generated by the -//! [fiat-crypto project](https://github.com/mit-plv/fiat-crypto) - -#[path = "../u32/scalar.rs"] -pub mod scalar; - -pub mod field; - -#[path = "../u32/constants.rs"] -pub mod constants; diff --git a/net/gurk-rs/files/vendor/curve25519-dalek/src/backend/serial/fiat_u64/field.rs b/net/gurk-rs/files/vendor/curve25519-dalek/src/backend/serial/fiat_u64/field.rs deleted file mode 100644 index 7e381b6..0000000 --- a/net/gurk-rs/files/vendor/curve25519-dalek/src/backend/serial/fiat_u64/field.rs +++ /dev/null @@ -1,249 +0,0 @@ -// -*- mode: rust; coding: utf-8; -*- -// -// This file is part of curve25519-dalek. -// Copyright (c) 2016-2018 Isis Lovecruft, Henry de Valence -// See LICENSE for licensing information. -// -// Authors: -// - Isis Agora Lovecruft -// - Henry de Valence - -//! Field arithmetic modulo \\(p = 2\^{255} - 19\\), using \\(64\\)-bit -//! limbs with \\(128\\)-bit products. -//! -//! This uses the formally-verified field arithmetic generated by the -//! [fiat-crypto project](https://github.com/mit-plv/fiat-crypto) - -use core::fmt::Debug; -use core::ops::Neg; -use core::ops::{Add, AddAssign}; -use core::ops::{Mul, MulAssign}; -use core::ops::{Sub, SubAssign}; - -use subtle::Choice; -use subtle::ConditionallySelectable; - -use zeroize::Zeroize; - -use fiat_crypto::curve25519_64::*; - -/// A `FieldElement51` represents an element of the field -/// \\( \mathbb Z / (2\^{255} - 19)\\). -/// -/// In the 64-bit implementation, a `FieldElement` is represented in -/// radix \\(2\^{51}\\) as five `u64`s; the coefficients are allowed to -/// grow up to \\(2\^{54}\\) between reductions modulo \\(p\\). -/// -/// # Note -/// -/// The `curve25519_dalek::field` module provides a type alias -/// `curve25519_dalek::field::FieldElement` to either `FieldElement51` -/// or `FieldElement2625`. -/// -/// The backend-specific type `FieldElement51` should not be used -/// outside of the `curve25519_dalek::field` module. -#[derive(Copy, Clone)] -pub struct FieldElement51(pub(crate) [u64; 5]); - -impl Debug for FieldElement51 { - fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { - write!(f, "FieldElement51({:?})", &self.0[..]) - } -} - -impl Zeroize for FieldElement51 { - fn zeroize(&mut self) { - self.0.zeroize(); - } -} - -impl<'b> AddAssign<&'b FieldElement51> for FieldElement51 { - fn add_assign(&mut self, _rhs: &'b FieldElement51) { - let input = self.0; - fiat_25519_add(&mut self.0, &input, &_rhs.0); - let input = self.0; - fiat_25519_carry(&mut self.0, &input); - } -} - -impl<'a, 'b> Add<&'b FieldElement51> for &'a FieldElement51 { - type Output = FieldElement51; - fn add(self, _rhs: &'b FieldElement51) -> FieldElement51 { - let mut output = *self; - fiat_25519_add(&mut output.0, &self.0, &_rhs.0); - let input = output.0; - fiat_25519_carry(&mut output.0, &input); - output - } -} - -impl<'b> SubAssign<&'b FieldElement51> for FieldElement51 { - fn sub_assign(&mut self, _rhs: &'b FieldElement51) { - let input = self.0; - fiat_25519_sub(&mut self.0, &input, &_rhs.0); - let input = self.0; - fiat_25519_carry(&mut self.0, &input); - } -} - -impl<'a, 'b> Sub<&'b FieldElement51> for &'a FieldElement51 { - type Output = FieldElement51; - fn sub(self, _rhs: &'b FieldElement51) -> FieldElement51 { - let mut output = *self; - fiat_25519_sub(&mut output.0, &self.0, &_rhs.0); - let input = output.0; - fiat_25519_carry(&mut output.0, &input); - output - } -} - -impl<'b> MulAssign<&'b FieldElement51> for FieldElement51 { - fn mul_assign(&mut self, _rhs: &'b FieldElement51) { - let input = self.0; - fiat_25519_carry_mul(&mut self.0, &input, &_rhs.0); - } -} - -impl<'a, 'b> Mul<&'b FieldElement51> for &'a FieldElement51 { - type Output = FieldElement51; - fn mul(self, _rhs: &'b FieldElement51) -> FieldElement51 { - let mut output = *self; - fiat_25519_carry_mul(&mut output.0, &self.0, &_rhs.0); - output - } -} - -impl<'a> Neg for &'a FieldElement51 { - type Output = FieldElement51; - fn neg(self) -> FieldElement51 { - let mut output = *self; - fiat_25519_opp(&mut output.0, &self.0); - let input = output.0; - fiat_25519_carry(&mut output.0, &input); - output - } -} - -impl ConditionallySelectable for FieldElement51 { - fn conditional_select( - a: &FieldElement51, - b: &FieldElement51, - choice: Choice, - ) -> FieldElement51 { - let mut output = [0u64; 5]; - fiat_25519_selectznz(&mut output, choice.unwrap_u8() as fiat_25519_u1, &a.0, &b.0); - FieldElement51(output) - } - - fn conditional_swap(a: &mut FieldElement51, b: &mut FieldElement51, choice: Choice) { - u64::conditional_swap(&mut a.0[0], &mut b.0[0], choice); - u64::conditional_swap(&mut a.0[1], &mut b.0[1], choice); - u64::conditional_swap(&mut a.0[2], &mut b.0[2], choice); - u64::conditional_swap(&mut a.0[3], &mut b.0[3], choice); - u64::conditional_swap(&mut a.0[4], &mut b.0[4], choice); - } - - fn conditional_assign(&mut self, _rhs: &FieldElement51, choice: Choice) { - let mut output = [0u64; 5]; - let choicebit = choice.unwrap_u8() as fiat_25519_u1; - fiat_25519_cmovznz_u64(&mut output[0], choicebit, self.0[0], _rhs.0[0]); - fiat_25519_cmovznz_u64(&mut output[1], choicebit, self.0[1], _rhs.0[1]); - fiat_25519_cmovznz_u64(&mut output[2], choicebit, self.0[2], _rhs.0[2]); - fiat_25519_cmovznz_u64(&mut output[3], choicebit, self.0[3], _rhs.0[3]); - fiat_25519_cmovznz_u64(&mut output[4], choicebit, self.0[4], _rhs.0[4]); - *self = FieldElement51(output); - } -} - -impl FieldElement51 { - /// Construct zero. - pub fn zero() -> FieldElement51 { - FieldElement51([0, 0, 0, 0, 0]) - } - - /// Construct one. - pub fn one() -> FieldElement51 { - FieldElement51([1, 0, 0, 0, 0]) - } - - /// Construct -1. - pub fn minus_one() -> FieldElement51 { - FieldElement51([ - 2251799813685228, - 2251799813685247, - 2251799813685247, - 2251799813685247, - 2251799813685247, - ]) - } - - /// Given 64-bit input limbs, reduce to enforce the bound 2^(51 + epsilon). - #[inline(always)] - #[allow(dead_code)] // Need this to not complain about reduce not being used - fn reduce(mut limbs: [u64; 5]) -> FieldElement51 { - let input = limbs; - fiat_25519_carry(&mut limbs, &input); - FieldElement51(limbs) - } - - /// Load a `FieldElement51` from the low 255 bits of a 256-bit - /// input. - /// - /// # Warning - /// - /// This function does not check that the input used the canonical - /// representative. It masks the high bit, but it will happily - /// decode 2^255 - 18 to 1. Applications that require a canonical - /// encoding of every field element should decode, re-encode to - /// the canonical encoding, and check that the input was - /// canonical. - /// - pub fn from_bytes(bytes: &[u8; 32]) -> FieldElement51 { - let mut temp = [0u8; 32]; - temp.copy_from_slice(bytes); - temp[31] &= 127u8; - let mut output = [0u64; 5]; - fiat_25519_from_bytes(&mut output, &temp); - FieldElement51(output) - } - - /// Serialize this `FieldElement51` to a 32-byte array. The - /// encoding is canonical. - pub fn to_bytes(&self) -> [u8; 32] { - let mut bytes = [0u8; 32]; - fiat_25519_to_bytes(&mut bytes, &self.0); - return bytes; - } - - /// Given `k > 0`, return `self^(2^k)`. - pub fn pow2k(&self, mut k: u32) -> FieldElement51 { - let mut output = *self; - loop { - let input = output.0; - fiat_25519_carry_square(&mut output.0, &input); - k -= 1; - if k == 0 { - return output; - } - } - } - - /// Returns the square of this field element. - pub fn square(&self) -> FieldElement51 { - let mut output = *self; - fiat_25519_carry_square(&mut output.0, &self.0); - output - } - - /// Returns 2 times the square of this field element. - pub fn square2(&self) -> FieldElement51 { - let mut output = *self; - let mut temp = *self; - // Void vs return type, measure cost of copying self - fiat_25519_carry_square(&mut temp.0, &self.0); - fiat_25519_add(&mut output.0, &temp.0, &temp.0); - let input = output.0; - fiat_25519_carry(&mut output.0, &input); - output - } -} diff --git a/net/gurk-rs/files/vendor/curve25519-dalek/src/backend/serial/fiat_u64/mod.rs b/net/gurk-rs/files/vendor/curve25519-dalek/src/backend/serial/fiat_u64/mod.rs deleted file mode 100644 index 8c83062..0000000 --- a/net/gurk-rs/files/vendor/curve25519-dalek/src/backend/serial/fiat_u64/mod.rs +++ /dev/null @@ -1,28 +0,0 @@ -// -*- mode: rust; -*- -// -// This file is part of curve25519-dalek. -// Copyright (c) 2016-2018 Isis Lovecruft, Henry de Valence -// See LICENSE for licensing information. -// -// Authors: -// - Isis Agora Lovecruft -// - Henry de Valence - -//! The `u64` backend uses `u64`s and a `(u64, u64) -> u128` multiplier. -//! -//! On x86_64, the idiom `(x as u128) * (y as u128)` lowers to `MUL` -//! instructions taking 64-bit inputs and producing 128-bit outputs. On -//! other platforms, this implementation is not recommended. -//! -//! On Haswell and newer, the BMI2 extension provides `MULX`, and on -//! Broadwell and newer, the ADX extension provides `ADCX` and `ADOX` -//! (allowing the CPU to compute two carry chains in parallel). These -//! will be used if available. - -#[path = "../u64/scalar.rs"] -pub mod scalar; - -pub mod field; - -#[path = "../u64/constants.rs"] -pub mod constants; diff --git a/net/gurk-rs/files/vendor/curve25519-dalek/src/backend/serial/mod.rs b/net/gurk-rs/files/vendor/curve25519-dalek/src/backend/serial/mod.rs deleted file mode 100644 index 971afe9..0000000 --- a/net/gurk-rs/files/vendor/curve25519-dalek/src/backend/serial/mod.rs +++ /dev/null @@ -1,55 +0,0 @@ -// -*- mode: rust; -*- -// -// This file is part of curve25519-dalek. -// Copyright (c) 2016-2021 isis lovecruft -// Copyright (c) 2016-2019 Henry de Valence -// See LICENSE for licensing information. -// -// Authors: -// - isis agora lovecruft -// - Henry de Valence - -//! Serial implementations of field, scalar, point arithmetic. -//! -//! When the vector backend is disabled, the crate uses the -//! mixed-model strategy for implementing point operations and scalar -//! multiplication; see the [`curve_models`](self::curve_models) and -//! [`scalar_mul`](self::scalar_mul) documentation for more -//! information. -//! -//! When the vector backend is enabled, the field and scalar -//! implementations are still used for non-vectorized operations. -//! -//! Note: at this time the `u32` and `u64` backends cannot be built -//! together. - -#[cfg(not(any( - feature = "u32_backend", - feature = "u64_backend", - feature = "fiat_u32_backend", - feature = "fiat_u64_backend" -)))] -compile_error!( - "no curve25519-dalek backend cargo feature enabled! \ - please enable one of: u32_backend, u64_backend, fiat_u32_backend, fiat_u64_backend" -); - -#[cfg(feature = "u32_backend")] -pub mod u32; - -#[cfg(feature = "u64_backend")] -pub mod u64; - -#[cfg(feature = "fiat_u32_backend")] -pub mod fiat_u32; - -#[cfg(feature = "fiat_u64_backend")] -pub mod fiat_u64; - -pub mod curve_models; - -#[cfg(not(all( - feature = "simd_backend", - any(target_feature = "avx2", target_feature = "avx512ifma") -)))] -pub mod scalar_mul; diff --git a/net/gurk-rs/files/vendor/curve25519-dalek/src/backend/serial/scalar_mul/mod.rs b/net/gurk-rs/files/vendor/curve25519-dalek/src/backend/serial/scalar_mul/mod.rs deleted file mode 100644 index 8bdad1f..0000000 --- a/net/gurk-rs/files/vendor/curve25519-dalek/src/backend/serial/scalar_mul/mod.rs +++ /dev/null @@ -1,31 +0,0 @@ -// -*- mode: rust; -*- -// -// This file is part of curve25519-dalek. -// Copyright (c) 2016-2021 isis lovecruft -// Copyright (c) 2016-2019 Henry de Valence -// See LICENSE for licensing information. -// -// Authors: -// - isis agora lovecruft -// - Henry de Valence - -//! Implementations of various scalar multiplication algorithms. -//! -//! Note that all of these implementations use serial code for field -//! arithmetic with the multi-model strategy described in the -//! `curve_models` module. The vectorized AVX2 backend has its own -//! scalar multiplication implementations, since it only uses one -//! curve model. - -pub mod variable_base; - -pub mod vartime_double_base; - -#[cfg(feature = "alloc")] -pub mod straus; - -#[cfg(feature = "alloc")] -pub mod precomputed_straus; - -#[cfg(feature = "alloc")] -pub mod pippenger; diff --git a/net/gurk-rs/files/vendor/curve25519-dalek/src/backend/serial/scalar_mul/pippenger.rs b/net/gurk-rs/files/vendor/curve25519-dalek/src/backend/serial/scalar_mul/pippenger.rs deleted file mode 100644 index bffe140..0000000 --- a/net/gurk-rs/files/vendor/curve25519-dalek/src/backend/serial/scalar_mul/pippenger.rs +++ /dev/null @@ -1,202 +0,0 @@ -// -*- mode: rust; -*- -// -// This file is part of curve25519-dalek. -// Copyright (c) 2019 Oleg Andreev -// See LICENSE for licensing information. -// -// Authors: -// - Oleg Andreev - -//! Implementation of a variant of Pippenger's algorithm. - -#![allow(non_snake_case)] - -use core::borrow::Borrow; - -use edwards::EdwardsPoint; -use scalar::Scalar; -use traits::VartimeMultiscalarMul; - -#[allow(unused_imports)] -use prelude::*; - -/// Implements a version of Pippenger's algorithm. -/// -/// The algorithm works as follows: -/// -/// Let `n` be a number of point-scalar pairs. -/// Let `w` be a window of bits (6..8, chosen based on `n`, see cost factor). -/// -/// 1. Prepare `2^(w-1) - 1` buckets with indices `[1..2^(w-1))` initialized with identity points. -/// Bucket 0 is not needed as it would contain points multiplied by 0. -/// 2. Convert scalars to a radix-`2^w` representation with signed digits in `[-2^w/2, 2^w/2]`. -/// Note: only the last digit may equal `2^w/2`. -/// 3. Starting with the last window, for each point `i=[0..n)` add it to a a bucket indexed by -/// the point's scalar's value in the window. -/// 4. Once all points in a window are sorted into buckets, add buckets by multiplying each -/// by their index. Efficient way of doing it is to start with the last bucket and compute two sums: -/// intermediate sum from the last to the first, and the full sum made of all intermediate sums. -/// 5. Shift the resulting sum of buckets by `w` bits by using `w` doublings. -/// 6. Add to the return value. -/// 7. Repeat the loop. -/// -/// Approximate cost w/o wNAF optimizations (A = addition, D = doubling): -/// -/// ```ascii -/// cost = (n*A + 2*(2^w/2)*A + w*D + A)*256/w -/// | | | | | -/// | | | | looping over 256/w windows -/// | | | adding to the result -/// sorting points | shifting the sum by w bits (to the next window, starting from last window) -/// one by one | -/// into buckets adding/subtracting all buckets -/// multiplied by their indexes -/// using a sum of intermediate sums -/// ``` -/// -/// For large `n`, dominant factor is (n*256/w) additions. -/// However, if `w` is too big and `n` is not too big, then `(2^w/2)*A` could dominate. -/// Therefore, the optimal choice of `w` grows slowly as `n` grows. -/// -/// This algorithm is adapted from section 4 of https://eprint.iacr.org/2012/549.pdf. -pub struct Pippenger; - -#[cfg(any(feature = "alloc", feature = "std"))] -impl VartimeMultiscalarMul for Pippenger { - type Point = EdwardsPoint; - - fn optional_multiscalar_mul(scalars: I, points: J) -> Option - where - I: IntoIterator, - I::Item: Borrow, - J: IntoIterator>, - { - use traits::Identity; - - let mut scalars = scalars.into_iter(); - let size = scalars.by_ref().size_hint().0; - - // Digit width in bits. As digit width grows, - // number of point additions goes down, but amount of - // buckets and bucket additions grows exponentially. - let w = if size < 500 { - 6 - } else if size < 800 { - 7 - } else { - 8 - }; - - let max_digit: usize = 1 << w; - let digits_count: usize = Scalar::to_radix_2w_size_hint(w); - let buckets_count: usize = max_digit / 2; // digits are signed+centered hence 2^w/2, excluding 0-th bucket - - // Collect optimized scalars and points in buffers for repeated access - // (scanning the whole set per digit position). - let scalars = scalars - .map(|s| s.borrow().to_radix_2w(w)); - - let points = points - .into_iter() - .map(|p| p.map(|P| P.to_projective_niels())); - - let scalars_points = scalars - .zip(points) - .map(|(s, maybe_p)| maybe_p.map(|p| (s, p))) - .collect::>>()?; - - // Prepare 2^w/2 buckets. - // buckets[i] corresponds to a multiplication factor (i+1). - let mut buckets: Vec<_> = (0..buckets_count) - .map(|_| EdwardsPoint::identity()) - .collect(); - - let mut columns = (0..digits_count).rev().map(|digit_index| { - // Clear the buckets when processing another digit. - for i in 0..buckets_count { - buckets[i] = EdwardsPoint::identity(); - } - - // Iterate over pairs of (point, scalar) - // and add/sub the point to the corresponding bucket. - // Note: if we add support for precomputed lookup tables, - // we'll be adding/subtracting point premultiplied by `digits[i]` to buckets[0]. - for (digits, pt) in scalars_points.iter() { - // Widen digit so that we don't run into edge cases when w=8. - let digit = digits[digit_index] as i16; - if digit > 0 { - let b = (digit - 1) as usize; - buckets[b] = (&buckets[b] + pt).to_extended(); - } else if digit < 0 { - let b = (-digit - 1) as usize; - buckets[b] = (&buckets[b] - pt).to_extended(); - } - } - - // Add the buckets applying the multiplication factor to each bucket. - // The most efficient way to do that is to have a single sum with two running sums: - // an intermediate sum from last bucket to the first, and a sum of intermediate sums. - // - // For example, to add buckets 1*A, 2*B, 3*C we need to add these points: - // C - // C B - // C B A Sum = C + (C+B) + (C+B+A) - let mut buckets_intermediate_sum = buckets[buckets_count - 1]; - let mut buckets_sum = buckets[buckets_count - 1]; - for i in (0..(buckets_count - 1)).rev() { - buckets_intermediate_sum += buckets[i]; - buckets_sum += buckets_intermediate_sum; - } - - buckets_sum - }); - - // Take the high column as an initial value to avoid wasting time doubling the identity element in `fold()`. - // `unwrap()` always succeeds because we know we have more than zero digits. - let hi_column = columns.next().unwrap(); - - Some( - columns - .fold(hi_column, |total, p| total.mul_by_pow_2(w as u32) + p), - ) - } -} - -#[cfg(test)] -mod test { - use super::*; - use constants; - use scalar::Scalar; - - #[test] - fn test_vartime_pippenger() { - // Reuse points across different tests - let mut n = 512; - let x = Scalar::from(2128506u64).invert(); - let y = Scalar::from(4443282u64).invert(); - let points: Vec<_> = (0..n) - .map(|i| constants::ED25519_BASEPOINT_POINT * Scalar::from(1 + i as u64)) - .collect(); - let scalars: Vec<_> = (0..n) - .map(|i| x + (Scalar::from(i as u64) * y)) // fast way to make ~random but deterministic scalars - .collect(); - - let premultiplied: Vec = scalars - .iter() - .zip(points.iter()) - .map(|(sc, pt)| sc * pt) - .collect(); - - while n > 0 { - let scalars = &scalars[0..n].to_vec(); - let points = &points[0..n].to_vec(); - let control: EdwardsPoint = premultiplied[0..n].iter().sum(); - - let subject = Pippenger::vartime_multiscalar_mul(scalars.clone(), points.clone()); - - assert_eq!(subject.compress(), control.compress()); - - n = n / 2; - } - } -} diff --git a/net/gurk-rs/files/vendor/curve25519-dalek/src/backend/serial/scalar_mul/precomputed_straus.rs b/net/gurk-rs/files/vendor/curve25519-dalek/src/backend/serial/scalar_mul/precomputed_straus.rs deleted file mode 100644 index 97f5e86..0000000 --- a/net/gurk-rs/files/vendor/curve25519-dalek/src/backend/serial/scalar_mul/precomputed_straus.rs +++ /dev/null @@ -1,110 +0,0 @@ -// -*- mode: rust; -*- -// -// This file is part of curve25519-dalek. -// Copyright (c) 2019 Henry de Valence. -// See LICENSE for licensing information. -// -// Authors: -// - Henry de Valence - -//! Precomputation for Straus's method. - -#![allow(non_snake_case)] - -use core::borrow::Borrow; - -use backend::serial::curve_models::{ - AffineNielsPoint, CompletedPoint, ProjectiveNielsPoint, ProjectivePoint, -}; -use edwards::EdwardsPoint; -use scalar::Scalar; -use traits::Identity; -use traits::VartimePrecomputedMultiscalarMul; -use window::{NafLookupTable5, NafLookupTable8}; - -#[allow(unused_imports)] -use prelude::*; - -pub struct VartimePrecomputedStraus { - static_lookup_tables: Vec>, -} - -impl VartimePrecomputedMultiscalarMul for VartimePrecomputedStraus { - type Point = EdwardsPoint; - - fn new(static_points: I) -> Self - where - I: IntoIterator, - I::Item: Borrow, - { - Self { - static_lookup_tables: static_points - .into_iter() - .map(|P| NafLookupTable8::::from(P.borrow())) - .collect(), - } - } - - fn optional_mixed_multiscalar_mul( - &self, - static_scalars: I, - dynamic_scalars: J, - dynamic_points: K, - ) -> Option - where - I: IntoIterator, - I::Item: Borrow, - J: IntoIterator, - J::Item: Borrow, - K: IntoIterator>, - { - let static_nafs = static_scalars - .into_iter() - .map(|c| c.borrow().non_adjacent_form(5)) - .collect::>(); - let dynamic_nafs: Vec<_> = dynamic_scalars - .into_iter() - .map(|c| c.borrow().non_adjacent_form(5)) - .collect::>(); - - let dynamic_lookup_tables = dynamic_points - .into_iter() - .map(|P_opt| P_opt.map(|P| NafLookupTable5::::from(&P))) - .collect::>>()?; - - let sp = self.static_lookup_tables.len(); - let dp = dynamic_lookup_tables.len(); - assert_eq!(sp, static_nafs.len()); - assert_eq!(dp, dynamic_nafs.len()); - - // We could save some doublings by looking for the highest - // nonzero NAF coefficient, but since we might have a lot of - // them to search, it's not clear it's worthwhile to check. - let mut S = ProjectivePoint::identity(); - for j in (0..256).rev() { - let mut R: CompletedPoint = S.double(); - - for i in 0..dp { - let t_ij = dynamic_nafs[i][j]; - if t_ij > 0 { - R = &R.to_extended() + &dynamic_lookup_tables[i].select(t_ij as usize); - } else if t_ij < 0 { - R = &R.to_extended() - &dynamic_lookup_tables[i].select(-t_ij as usize); - } - } - - for i in 0..sp { - let t_ij = static_nafs[i][j]; - if t_ij > 0 { - R = &R.to_extended() + &self.static_lookup_tables[i].select(t_ij as usize); - } else if t_ij < 0 { - R = &R.to_extended() - &self.static_lookup_tables[i].select(-t_ij as usize); - } - } - - S = R.to_projective(); - } - - Some(S.to_extended()) - } -} diff --git a/net/gurk-rs/files/vendor/curve25519-dalek/src/backend/serial/scalar_mul/straus.rs b/net/gurk-rs/files/vendor/curve25519-dalek/src/backend/serial/scalar_mul/straus.rs deleted file mode 100644 index a361df5..0000000 --- a/net/gurk-rs/files/vendor/curve25519-dalek/src/backend/serial/scalar_mul/straus.rs +++ /dev/null @@ -1,196 +0,0 @@ -// -*- mode: rust; -*- -// -// This file is part of curve25519-dalek. -// Copyright (c) 2016-2021 isis lovecruft -// Copyright (c) 2016-2019 Henry de Valence -// See LICENSE for licensing information. -// -// Authors: -// - isis agora lovecruft -// - Henry de Valence - -//! Implementation of the interleaved window method, also known as Straus' method. - -#![allow(non_snake_case)] - -use core::borrow::Borrow; - -use edwards::EdwardsPoint; -use scalar::Scalar; -use traits::MultiscalarMul; -use traits::VartimeMultiscalarMul; - -#[allow(unused_imports)] -use prelude::*; - -/// Perform multiscalar multiplication by the interleaved window -/// method, also known as Straus' method (since it was apparently -/// [first published][solution] by Straus in 1964, as a solution to [a -/// problem][problem] posted in the American Mathematical Monthly in -/// 1963). -/// -/// It is easy enough to reinvent, and has been repeatedly. The basic -/// idea is that when computing -/// \\[ -/// Q = s_1 P_1 + \cdots + s_n P_n -/// \\] -/// by means of additions and doublings, the doublings can be shared -/// across the \\( P_i \\\). -/// -/// We implement two versions, a constant-time algorithm using fixed -/// windows and a variable-time algorithm using sliding windows. They -/// are slight variations on the same idea, and are described in more -/// detail in the respective implementations. -/// -/// [solution]: https://www.jstor.org/stable/2310929 -/// [problem]: https://www.jstor.org/stable/2312273 -pub struct Straus {} - -impl MultiscalarMul for Straus { - type Point = EdwardsPoint; - - /// Constant-time Straus using a fixed window of size \\(4\\). - /// - /// Our goal is to compute - /// \\[ - /// Q = s_1 P_1 + \cdots + s_n P_n. - /// \\] - /// - /// For each point \\( P_i \\), precompute a lookup table of - /// \\[ - /// P_i, 2P_i, 3P_i, 4P_i, 5P_i, 6P_i, 7P_i, 8P_i. - /// \\] - /// - /// For each scalar \\( s_i \\), compute its radix-\\(2^4\\) - /// signed digits \\( s_{i,j} \\), i.e., - /// \\[ - /// s_i = s_{i,0} + s_{i,1} 16^1 + ... + s_{i,63} 16^{63}, - /// \\] - /// with \\( -8 \leq s_{i,j} < 8 \\). Since \\( 0 \leq |s_{i,j}| - /// \leq 8 \\), we can retrieve \\( s_{i,j} P_i \\) from the - /// lookup table with a conditional negation: using signed - /// digits halves the required table size. - /// - /// Then as in the single-base fixed window case, we have - /// \\[ - /// \begin{aligned} - /// s_i P_i &= P_i (s_{i,0} + s_{i,1} 16^1 + \cdots + s_{i,63} 16^{63}) \\\\ - /// s_i P_i &= P_i s_{i,0} + P_i s_{i,1} 16^1 + \cdots + P_i s_{i,63} 16^{63} \\\\ - /// s_i P_i &= P_i s_{i,0} + 16(P_i s_{i,1} + 16( \cdots +16P_i s_{i,63})\cdots ) - /// \end{aligned} - /// \\] - /// so each \\( s_i P_i \\) can be computed by alternately adding - /// a precomputed multiple \\( P_i s_{i,j} \\) of \\( P_i \\) and - /// repeatedly doubling. - /// - /// Now consider the two-dimensional sum - /// \\[ - /// \begin{aligned} - /// s\_1 P\_1 &=& P\_1 s\_{1,0} &+& 16 (P\_1 s\_{1,1} &+& 16 ( \cdots &+& 16 P\_1 s\_{1,63}&) \cdots ) \\\\ - /// + & & + & & + & & & & + & \\\\ - /// s\_2 P\_2 &=& P\_2 s\_{2,0} &+& 16 (P\_2 s\_{2,1} &+& 16 ( \cdots &+& 16 P\_2 s\_{2,63}&) \cdots ) \\\\ - /// + & & + & & + & & & & + & \\\\ - /// \vdots & & \vdots & & \vdots & & & & \vdots & \\\\ - /// + & & + & & + & & & & + & \\\\ - /// s\_n P\_n &=& P\_n s\_{n,0} &+& 16 (P\_n s\_{n,1} &+& 16 ( \cdots &+& 16 P\_n s\_{n,63}&) \cdots ) - /// \end{aligned} - /// \\] - /// The sum of the left-hand column is the result \\( Q \\); by - /// computing the two-dimensional sum on the right column-wise, - /// top-to-bottom, then right-to-left, we need to multiply by \\( - /// 16\\) only once per column, sharing the doublings across all - /// of the input points. - fn multiscalar_mul(scalars: I, points: J) -> EdwardsPoint - where - I: IntoIterator, - I::Item: Borrow, - J: IntoIterator, - J::Item: Borrow, - { - use zeroize::Zeroizing; - - use backend::serial::curve_models::ProjectiveNielsPoint; - use window::LookupTable; - use traits::Identity; - - let lookup_tables: Vec<_> = points - .into_iter() - .map(|point| LookupTable::::from(point.borrow())) - .collect(); - - // This puts the scalar digits into a heap-allocated Vec. - // To ensure that these are erased, pass ownership of the Vec into a - // Zeroizing wrapper. - let scalar_digits_vec: Vec<_> = scalars - .into_iter() - .map(|s| s.borrow().to_radix_16()) - .collect(); - let scalar_digits = Zeroizing::new(scalar_digits_vec); - - let mut Q = EdwardsPoint::identity(); - for j in (0..64).rev() { - Q = Q.mul_by_pow_2(4); - let it = scalar_digits.iter().zip(lookup_tables.iter()); - for (s_i, lookup_table_i) in it { - // R_i = s_{i,j} * P_i - let R_i = lookup_table_i.select(s_i[j]); - // Q = Q + R_i - Q = (&Q + &R_i).to_extended(); - } - } - - Q - } -} - -impl VartimeMultiscalarMul for Straus { - type Point = EdwardsPoint; - - /// Variable-time Straus using a non-adjacent form of width \\(5\\). - /// - /// This is completely similar to the constant-time code, but we - /// use a non-adjacent form for the scalar, and do not do table - /// lookups in constant time. - /// - /// The non-adjacent form has signed, odd digits. Using only odd - /// digits halves the table size (since we only need odd - /// multiples), or gives fewer additions for the same table size. - fn optional_multiscalar_mul(scalars: I, points: J) -> Option - where - I: IntoIterator, - I::Item: Borrow, - J: IntoIterator>, - { - use backend::serial::curve_models::{CompletedPoint, ProjectiveNielsPoint, ProjectivePoint}; - use window::NafLookupTable5; - use traits::Identity; - - let nafs: Vec<_> = scalars - .into_iter() - .map(|c| c.borrow().non_adjacent_form(5)) - .collect(); - - let lookup_tables = points - .into_iter() - .map(|P_opt| P_opt.map(|P| NafLookupTable5::::from(&P))) - .collect::>>()?; - - let mut r = ProjectivePoint::identity(); - - for i in (0..256).rev() { - let mut t: CompletedPoint = r.double(); - - for (naf, lookup_table) in nafs.iter().zip(lookup_tables.iter()) { - if naf[i] > 0 { - t = &t.to_extended() + &lookup_table.select(naf[i] as usize); - } else if naf[i] < 0 { - t = &t.to_extended() - &lookup_table.select(-naf[i] as usize); - } - } - - r = t.to_projective(); - } - - Some(r.to_extended()) - } -} diff --git a/net/gurk-rs/files/vendor/curve25519-dalek/src/backend/serial/scalar_mul/variable_base.rs b/net/gurk-rs/files/vendor/curve25519-dalek/src/backend/serial/scalar_mul/variable_base.rs deleted file mode 100644 index a4ff2ed..0000000 --- a/net/gurk-rs/files/vendor/curve25519-dalek/src/backend/serial/scalar_mul/variable_base.rs +++ /dev/null @@ -1,46 +0,0 @@ -#![allow(non_snake_case)] - -use traits::Identity; -use scalar::Scalar; -use edwards::EdwardsPoint; -use backend::serial::curve_models::ProjectiveNielsPoint; -use window::LookupTable; - -/// Perform constant-time, variable-base scalar multiplication. -pub(crate) fn mul(point: &EdwardsPoint, scalar: &Scalar) -> EdwardsPoint { - // Construct a lookup table of [P,2P,3P,4P,5P,6P,7P,8P] - let lookup_table = LookupTable::::from(point); - // Setting s = scalar, compute - // - // s = s_0 + s_1*16^1 + ... + s_63*16^63, - // - // with `-8 ≤ s_i < 8` for `0 ≤ i < 63` and `-8 ≤ s_63 ≤ 8`. - let scalar_digits = scalar.to_radix_16(); - // Compute s*P as - // - // s*P = P*(s_0 + s_1*16^1 + s_2*16^2 + ... + s_63*16^63) - // s*P = P*s_0 + P*s_1*16^1 + P*s_2*16^2 + ... + P*s_63*16^63 - // s*P = P*s_0 + 16*(P*s_1 + 16*(P*s_2 + 16*( ... + P*s_63)...)) - // - // We sum right-to-left. - - // Unwrap first loop iteration to save computing 16*identity - let mut tmp2; - let mut tmp3 = EdwardsPoint::identity(); - let mut tmp1 = &tmp3 + &lookup_table.select(scalar_digits[63]); - // Now tmp1 = s_63*P in P1xP1 coords - for i in (0..63).rev() { - tmp2 = tmp1.to_projective(); // tmp2 = (prev) in P2 coords - tmp1 = tmp2.double(); // tmp1 = 2*(prev) in P1xP1 coords - tmp2 = tmp1.to_projective(); // tmp2 = 2*(prev) in P2 coords - tmp1 = tmp2.double(); // tmp1 = 4*(prev) in P1xP1 coords - tmp2 = tmp1.to_projective(); // tmp2 = 4*(prev) in P2 coords - tmp1 = tmp2.double(); // tmp1 = 8*(prev) in P1xP1 coords - tmp2 = tmp1.to_projective(); // tmp2 = 8*(prev) in P2 coords - tmp1 = tmp2.double(); // tmp1 = 16*(prev) in P1xP1 coords - tmp3 = tmp1.to_extended(); // tmp3 = 16*(prev) in P3 coords - tmp1 = &tmp3 + &lookup_table.select(scalar_digits[i]); - // Now tmp1 = s_i*P + 16*(prev) in P1xP1 coords - } - tmp1.to_extended() -} diff --git a/net/gurk-rs/files/vendor/curve25519-dalek/src/backend/serial/scalar_mul/vartime_double_base.rs b/net/gurk-rs/files/vendor/curve25519-dalek/src/backend/serial/scalar_mul/vartime_double_base.rs deleted file mode 100644 index 03517f9..0000000 --- a/net/gurk-rs/files/vendor/curve25519-dalek/src/backend/serial/scalar_mul/vartime_double_base.rs +++ /dev/null @@ -1,62 +0,0 @@ -// -*- mode: rust; -*- -// -// This file is part of curve25519-dalek. -// Copyright (c) 2016-2021 isis lovecruft -// Copyright (c) 2016-2019 Henry de Valence -// See LICENSE for licensing information. -// -// Authors: -// - isis agora lovecruft -// - Henry de Valence -#![allow(non_snake_case)] - -use constants; -use traits::Identity; -use scalar::Scalar; -use edwards::EdwardsPoint; -use backend::serial::curve_models::{ProjectiveNielsPoint, ProjectivePoint}; -use window::NafLookupTable5; - -/// Compute \\(aA + bB\\) in variable time, where \\(B\\) is the Ed25519 basepoint. -pub fn mul(a: &Scalar, A: &EdwardsPoint, b: &Scalar) -> EdwardsPoint { - let a_naf = a.non_adjacent_form(5); - let b_naf = b.non_adjacent_form(8); - - // Find starting index - let mut i: usize = 255; - for j in (0..256).rev() { - i = j; - if a_naf[i] != 0 || b_naf[i] != 0 { - break; - } - } - - let table_A = NafLookupTable5::::from(A); - let table_B = &constants::AFFINE_ODD_MULTIPLES_OF_BASEPOINT; - - let mut r = ProjectivePoint::identity(); - loop { - let mut t = r.double(); - - if a_naf[i] > 0 { - t = &t.to_extended() + &table_A.select(a_naf[i] as usize); - } else if a_naf[i] < 0 { - t = &t.to_extended() - &table_A.select(-a_naf[i] as usize); - } - - if b_naf[i] > 0 { - t = &t.to_extended() + &table_B.select(b_naf[i] as usize); - } else if b_naf[i] < 0 { - t = &t.to_extended() - &table_B.select(-b_naf[i] as usize); - } - - r = t.to_projective(); - - if i == 0 { - break; - } - i -= 1; - } - - r.to_extended() -} diff --git a/net/gurk-rs/files/vendor/curve25519-dalek/src/backend/serial/u32/constants.rs b/net/gurk-rs/files/vendor/curve25519-dalek/src/backend/serial/u32/constants.rs deleted file mode 100644 index af509cf..0000000 --- a/net/gurk-rs/files/vendor/curve25519-dalek/src/backend/serial/u32/constants.rs +++ /dev/null @@ -1,4789 +0,0 @@ -// -*- mode: rust; -*- -// -// This file is part of curve25519-dalek. -// Copyright (c) 2016-2021 isis lovecruft -// Copyright (c) 2016-2019 Henry de Valence -// See LICENSE for licensing information. -// -// Authors: -// - isis agora lovecruft -// - Henry de Valence - -//! This module contains various constants (such as curve parameters -//! and useful field elements like `sqrt(-1)`), as well as -//! lookup tables of pre-computed points. - -use backend::serial::curve_models::AffineNielsPoint; -use super::field::FieldElement2625; -use super::scalar::Scalar29; -use edwards::{EdwardsBasepointTable, EdwardsPoint}; -use window::{LookupTable, NafLookupTable8}; - -/// The value of minus one, equal to `-&FieldElement::one()` -pub(crate) const MINUS_ONE: FieldElement2625 = FieldElement2625([ - 67108844, 33554431, 67108863, 33554431, 67108863, 33554431, 67108863, 33554431, 67108863, 33554431 -]); - -/// Edwards `d` value, equal to `-121665/121666 mod p`. -pub(crate) const EDWARDS_D: FieldElement2625 = FieldElement2625([ - 56195235, 13857412, 51736253, 6949390, 114729, 24766616, 60832955, 30306712, 48412415, 21499315, -]); - -/// Edwards `2*d` value, equal to `2*(-121665/121666) mod p`. -pub(crate) const EDWARDS_D2: FieldElement2625 = FieldElement2625([ - 45281625, 27714825, 36363642, 13898781, 229458, 15978800, 54557047, 27058993, 29715967, 9444199, -]); - -/// One minus edwards `d` value squared, equal to `(1 - (-121665/121666) mod p) pow 2` -pub(crate) const ONE_MINUS_EDWARDS_D_SQUARED: FieldElement2625 = FieldElement2625([ - 6275446, 16937061, 44170319, 29780721, 11667076, 7397348, 39186143, 1766194, 42675006, 672202 -]); - -/// Edwards `d` value minus one squared, equal to `(((-121665/121666) mod p) - 1) pow 2` -pub(crate) const EDWARDS_D_MINUS_ONE_SQUARED: FieldElement2625 = FieldElement2625([ - 15551776, 22456977, 53683765, 23429360, 55212328, 10178283, 40474537, 4729243, 61826754, 23438029 -]); - -/// `= sqrt(a*d - 1)`, where `a = -1 (mod p)`, `d` are the Edwards curve parameters. -pub(crate) const SQRT_AD_MINUS_ONE: FieldElement2625 = FieldElement2625([ - 24849947, 33400850, 43495378, 6347714, 46036536, 32887293, 41837720, 18186727, 66238516, - 14525638, -]); - -/// `= 1/sqrt(a-d)`, where `a = -1 (mod p)`, `d` are the Edwards curve parameters. -pub(crate) const INVSQRT_A_MINUS_D: FieldElement2625 = FieldElement2625([ - 6111466, 4156064, 39310137, 12243467, 41204824, 120896, 20826367, 26493656, 6093567, 31568420, -]); - -/// Precomputed value of one of the square roots of -1 (mod p) -pub(crate) const SQRT_M1: FieldElement2625 = FieldElement2625([ - 34513072, 25610706, 9377949, 3500415, 12389472, 33281959, 41962654, 31548777, 326685, 11406482, -]); - -/// `APLUS2_OVER_FOUR` is (A+2)/4. (This is used internally within the Montgomery ladder.) -pub(crate) const APLUS2_OVER_FOUR: FieldElement2625 = - FieldElement2625([121666, 0, 0, 0, 0, 0, 0, 0, 0, 0]); - -/// `MONTGOMERY_A` is equal to 486662, which is a constant of the curve equation -/// for Curve25519 in its Montgomery form. (This is used internally within the -/// Elligator map.) -pub(crate) const MONTGOMERY_A: FieldElement2625 = - FieldElement2625([486662, 0, 0, 0, 0, 0, 0, 0, 0, 0]); - -/// `MONTGOMERY_A_NEG` is equal to -486662. (This is used internally within the -/// Elligator map.) -pub(crate) const MONTGOMERY_A_NEG: FieldElement2625 = FieldElement2625([ - 66622183, 33554431, 67108863, 33554431, 67108863, 33554431, 67108863, 33554431, 67108863, 33554431, -]); - -/// `L` is the order of base point, i.e. 2^252 + -/// 27742317777372353535851937790883648493 -pub(crate) const L: Scalar29 = Scalar29([ - 0x1cf5d3ed, 0x009318d2, 0x1de73596, 0x1df3bd45, 0x0000014d, 0x00000000, 0x00000000, 0x00000000, - 0x00100000, -]); - -/// `L` * `LFACTOR` = -1 (mod 2^29) -pub(crate) const LFACTOR: u32 = 0x12547e1b; - -/// `R` = R % L where R = 2^261 -pub(crate) const R: Scalar29 = Scalar29([ - 0x114df9ed, 0x1a617303, 0x0f7c098c, 0x16793167, 0x1ffd656e, 0x1fffffff, 0x1fffffff, 0x1fffffff, - 0x000fffff, -]); - -/// `RR` = (R^2) % L where R = 2^261 -pub(crate) const RR: Scalar29 = Scalar29([ - 0x0b5f9d12, 0x1e141b17, 0x158d7f3d, 0x143f3757, 0x1972d781, 0x042feb7c, 0x1ceec73d, 0x1e184d1e, - 0x0005046d, -]); - -/// The Ed25519 basepoint, as an `EdwardsPoint`. -/// -/// This is called `_POINT` to distinguish it from -/// `ED25519_BASEPOINT_TABLE`, which should be used for scalar -/// multiplication (it's much faster). -pub const ED25519_BASEPOINT_POINT: EdwardsPoint = EdwardsPoint { - X: FieldElement2625([ - 52811034, 25909283, 16144682, 17082669, 27570973, 30858332, 40966398, 8378388, 20764389, - 8758491, - ]), - Y: FieldElement2625([ - 40265304, 26843545, 13421772, 20132659, 26843545, 6710886, 53687091, 13421772, 40265318, - 26843545, - ]), - Z: FieldElement2625([1, 0, 0, 0, 0, 0, 0, 0, 0, 0]), - T: FieldElement2625([ - 28827043, 27438313, 39759291, 244362, 8635006, 11264893, 19351346, 13413597, 16611511, - 27139452, - ]), -}; - -/// The 8-torsion subgroup \\(\mathcal E [8]\\). -/// -/// In the case of Curve25519, it is cyclic; the \\(i\\)-th element of -/// the array is \\([i]P\\), where \\(P\\) is a point of order \\(8\\) -/// generating \\(\mathcal E[8]\\). -/// -/// Thus \\(\mathcal E[4]\\) is the points indexed by `0,2,4,6`, and -/// \\(\mathcal E[2]\\) is the points indexed by `0,4`. -/// The Ed25519 basepoint has y = 4/5. This is called `_POINT` to -/// distinguish it from `_TABLE`, which should be used for scalar -/// multiplication (it's much faster). -pub const EIGHT_TORSION: [EdwardsPoint; 8] = EIGHT_TORSION_INNER_DOC_HIDDEN; - -/// Inner item used to hide limb constants from cargo doc output. -#[doc(hidden)] -pub const EIGHT_TORSION_INNER_DOC_HIDDEN: [EdwardsPoint; 8] = [ - EdwardsPoint { - X: FieldElement2625([0, 0, 0, 0, 0, 0, 0, 0, 0, 0]), - Y: FieldElement2625([1, 0, 0, 0, 0, 0, 0, 0, 0, 0]), - Z: FieldElement2625([1, 0, 0, 0, 0, 0, 0, 0, 0, 0]), - T: FieldElement2625([0, 0, 0, 0, 0, 0, 0, 0, 0, 0]), - }, - EdwardsPoint { - X: FieldElement2625([ - 21352778, 5345713, 4660180, 25206575, 24143089, 14568123, 30185756, 21306662, 33579924, - 8345318, - ]), - Y: FieldElement2625([ - 6952903, 1265500, 60246523, 7057497, 4037696, 5447722, 35427965, 15325401, 19365852, - 31985330, - ]), - Z: FieldElement2625([1, 0, 0, 0, 0, 0, 0, 0, 0, 0]), - T: FieldElement2625([ - 41846657, 21581751, 11716001, 27684820, 48915701, 16297738, 20670665, 24995334, - 3541542, 28543251, - ]), - }, - EdwardsPoint { - X: FieldElement2625([ - 32595773, 7943725, 57730914, 30054016, 54719391, 272472, 25146209, 2005654, 66782178, - 22147949, - ]), - Y: FieldElement2625([0, 0, 0, 0, 0, 0, 0, 0, 0, 0]), - Z: FieldElement2625([1, 0, 0, 0, 0, 0, 0, 0, 0, 0]), - T: FieldElement2625([0, 0, 0, 0, 0, 0, 0, 0, 0, 0]), - }, - EdwardsPoint { - X: FieldElement2625([ - 21352778, 5345713, 4660180, 25206575, 24143089, 14568123, 30185756, 21306662, 33579924, - 8345318, - ]), - Y: FieldElement2625([ - 60155942, 32288931, 6862340, 26496934, 63071167, 28106709, 31680898, 18229030, - 47743011, 1569101, - ]), - Z: FieldElement2625([1, 0, 0, 0, 0, 0, 0, 0, 0, 0]), - T: FieldElement2625([ - 25262188, 11972680, 55392862, 5869611, 18193162, 17256693, 46438198, 8559097, 63567321, - 5011180, - ]), - }, - EdwardsPoint { - X: FieldElement2625([0, 0, 0, 0, 0, 0, 0, 0, 0, 0]), - Y: FieldElement2625([ - 67108844, 33554431, 67108863, 33554431, 67108863, 33554431, 67108863, 33554431, - 67108863, 33554431, - ]), - Z: FieldElement2625([1, 0, 0, 0, 0, 0, 0, 0, 0, 0]), - T: FieldElement2625([0, 0, 0, 0, 0, 0, 0, 0, 0, 0]), - }, - EdwardsPoint { - X: FieldElement2625([ - 45756067, 28208718, 62448683, 8347856, 42965774, 18986308, 36923107, 12247769, - 33528939, 25209113, - ]), - Y: FieldElement2625([ - 60155942, 32288931, 6862340, 26496934, 63071167, 28106709, 31680898, 18229030, - 47743011, 1569101, - ]), - Z: FieldElement2625([1, 0, 0, 0, 0, 0, 0, 0, 0, 0]), - T: FieldElement2625([ - 41846657, 21581751, 11716001, 27684820, 48915701, 16297738, 20670665, 24995334, - 3541542, 28543251, - ]), - }, - EdwardsPoint { - X: FieldElement2625([ - 34513072, 25610706, 9377949, 3500415, 12389472, 33281959, 41962654, 31548777, 326685, - 11406482, - ]), - Y: FieldElement2625([0, 0, 0, 0, 0, 0, 0, 0, 0, 0]), - Z: FieldElement2625([1, 0, 0, 0, 0, 0, 0, 0, 0, 0]), - T: FieldElement2625([0, 0, 0, 0, 0, 0, 0, 0, 0, 0]), - }, - EdwardsPoint { - X: FieldElement2625([ - 45756067, 28208718, 62448683, 8347856, 42965774, 18986308, 36923107, 12247769, - 33528939, 25209113, - ]), - Y: FieldElement2625([ - 6952903, 1265500, 60246523, 7057497, 4037696, 5447722, 35427965, 15325401, 19365852, - 31985330, - ]), - Z: FieldElement2625([1, 0, 0, 0, 0, 0, 0, 0, 0, 0]), - T: FieldElement2625([ - 25262188, 11972680, 55392862, 5869611, 18193162, 17256693, 46438198, 8559097, 63567321, - 5011180, - ]), - }, -]; - -/// Table containing precomputed multiples of the Ed25519 basepoint \\(B = (x, 4/5)\\). -pub const ED25519_BASEPOINT_TABLE: EdwardsBasepointTable = ED25519_BASEPOINT_TABLE_INNER_DOC_HIDDEN; - -/// Inner constant, used to avoid filling the docs with precomputed points. -#[doc(hidden)] -pub const ED25519_BASEPOINT_TABLE_INNER_DOC_HIDDEN: EdwardsBasepointTable = - EdwardsBasepointTable([ - LookupTable([ - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 93076338, 52752828, 29566454, 37215328, 54414518, 37569218, 94653489, 21800160, - 61029707, 35602036, - ]), - y_minus_x: FieldElement2625([ - 54563134, 934261, 64385954, 3049989, 66381436, 9406985, 12720692, 5043384, - 19500929, 18085054, - ]), - xy2d: FieldElement2625([ - 58370664, 4489569, 9688441, 18769238, 10184608, 21191052, 29287918, 11864899, - 42594502, 29115885, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 54292951, 54132516, 45527619, 11784319, 41753206, 30803714, 55390960, 29739860, - 66750418, 23343128, - ]), - y_minus_x: FieldElement2625([ - 45405608, 6903824, 27185491, 6451973, 37531140, 24000426, 51492312, 11189267, - 40279186, 28235350, - ]), - xy2d: FieldElement2625([ - 26966623, 11152617, 32442495, 15396054, 14353839, 20802097, 63980037, 24013313, - 51636816, 29387734, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 82745136, 23865874, 24204772, 25642034, 67725840, 16869169, 94896463, 52336674, - 28944398, 32004408, - ]), - y_minus_x: FieldElement2625([ - 16568933, 4717097, 55552716, 32452109, 15682895, 21747389, 16354576, 21778470, - 7689661, 11199574, - ]), - xy2d: FieldElement2625([ - 30464137, 27578307, 55329429, 17883566, 23220364, 15915852, 7512774, 10017326, - 49359771, 23634074, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 50071967, 13921891, 78054670, 27521000, 27105051, 17470053, 105291517, - 15006021, 70393432, 27277891, - ]), - y_minus_x: FieldElement2625([ - 23599295, 25248385, 55915199, 25867015, 13236773, 10506355, 7464579, 9656445, - 13059162, 10374397, - ]), - xy2d: FieldElement2625([ - 7798537, 16710257, 3033922, 2874086, 28997861, 2835604, 32406664, 29715387, - 66467155, 33453106, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 77970208, 11473153, 27284546, 35535607, 37044514, 46132292, 99976748, 48069538, - 118779423, 44373810, - ]), - y_minus_x: FieldElement2625([ - 4708026, 6336745, 20377586, 9066809, 55836755, 6594695, 41455196, 12483687, - 54440373, 5581305, - ]), - xy2d: FieldElement2625([ - 19563141, 16186464, 37722007, 4097518, 10237984, 29206317, 28542349, 13850243, - 43430843, 17738489, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 51736881, 20691677, 32573249, 4720197, 107781206, 39429941, 115029100, - 18329611, 124398787, 21468653, - ]), - y_minus_x: FieldElement2625([ - 58559652, 109982, 15149363, 2178705, 22900618, 4543417, 3044240, 17864545, - 1762327, 14866737, - ]), - xy2d: FieldElement2625([ - 48909169, 17603008, 56635573, 1707277, 49922944, 3916100, 38872452, 3959420, - 27914454, 4383652, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 72262591, 43463716, 68832610, 30776557, 97632468, 39071304, 86589715, 38784565, - 43156424, 18378665, - ]), - y_minus_x: FieldElement2625([ - 36839857, 30090922, 7665485, 10083793, 28475525, 1649722, 20654025, 16520125, - 30598449, 7715701, - ]), - xy2d: FieldElement2625([ - 28881826, 14381568, 9657904, 3680757, 46927229, 7843315, 35708204, 1370707, - 29794553, 32145132, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 14499452, 64379265, 33917749, 62854211, 95603724, 14271266, 97399599, 10876453, - 33954766, 35936157, - ]), - y_minus_x: FieldElement2625([ - 59913433, 30899068, 52378708, 462250, 39384538, 3941371, 60872247, 3696004, - 34808032, 15351954, - ]), - xy2d: FieldElement2625([ - 27431194, 8222322, 16448760, 29646437, 48401861, 11938354, 34147463, 30583916, - 29551812, 10109425, - ]), - }, - ]), - LookupTable([ - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 53451805, 20399000, 102933977, 45331528, 88556249, 40073815, 64730579, - 31926875, 77201646, 28790260, - ]), - y_minus_x: FieldElement2625([ - 27939166, 14210322, 4677035, 16277044, 44144402, 21156292, 34600109, 12005537, - 49298737, 12803509, - ]), - xy2d: FieldElement2625([ - 17228999, 17892808, 65875336, 300139, 65883994, 21839654, 30364212, 24516238, - 18016356, 4397660, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 56150002, 25864224, 4776340, 18600194, 27850027, 17952220, 40489757, 14544524, - 49631360, 34537070, - ]), - y_minus_x: FieldElement2625([ - 29253598, 15796703, 64244882, 23645547, 10057022, 3163536, 7332899, 29434304, - 46061167, 9934962, - ]), - xy2d: FieldElement2625([ - 5793284, 16271923, 42977250, 23438027, 29188559, 1206517, 52360934, 4559894, - 36984942, 22656481, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 39464893, 55615857, 83391519, 22517938, 28414020, 52096600, 24191032, 38096129, - 53770554, 39054999, - ]), - y_minus_x: FieldElement2625([ - 12650548, 32057319, 9052870, 11355358, 49428827, 25154267, 49678271, 12264342, - 10874051, 13524335, - ]), - xy2d: FieldElement2625([ - 25556948, 30508442, 714650, 2510400, 23394682, 23139102, 33119037, 5080568, - 44580805, 5376627, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 108129445, 29543378, 50095164, 30016803, 60382070, 35475328, 44787558, - 57661420, 71644630, 35123438, - ]), - y_minus_x: FieldElement2625([ - 64853442, 14606629, 45416424, 25514613, 28430648, 8775819, 36614302, 3044289, - 31848280, 12543772, - ]), - xy2d: FieldElement2625([ - 45080285, 2943892, 35251351, 6777305, 13784462, 29262229, 39731668, 31491700, - 7718481, 14474653, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 69494160, 36008644, 44477543, 33601034, 62670928, 51428448, 67765827, 26317766, - 91425031, 28300864, - ]), - y_minus_x: FieldElement2625([ - 13741529, 10911568, 33875447, 24950694, 46931033, 32521134, 33040650, 20129900, - 46379407, 8321685, - ]), - xy2d: FieldElement2625([ - 21060490, 31341688, 15712756, 29218333, 1639039, 10656336, 23845965, 21679594, - 57124405, 608371, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 53436113, 18466845, 56219170, 25997372, 61071954, 11305546, 68232832, 60328286, - 94338261, 33578318, - ]), - y_minus_x: FieldElement2625([ - 43864724, 33260226, 55364135, 14712570, 37643165, 31524814, 12797023, 27114124, - 65475458, 16678953, - ]), - xy2d: FieldElement2625([ - 37608244, 4770661, 51054477, 14001337, 7830047, 9564805, 65600720, 28759386, - 49939598, 4904952, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 91168402, 48171434, 86146020, 18514523, 86874956, 18648002, 72278074, 16191879, - 69237100, 29227598, - ]), - y_minus_x: FieldElement2625([ - 50127693, 4124965, 58568254, 22900634, 30336521, 19449185, 37302527, 916032, - 60226322, 30567899, - ]), - xy2d: FieldElement2625([ - 44477957, 12419371, 59974635, 26081060, 50629959, 16739174, 285431, 2763829, - 15736322, 4143876, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 69488197, 11839344, 62998462, 27565766, 78383161, 34349388, 67321664, 18959768, - 23527083, 17096164, - ]), - y_minus_x: FieldElement2625([ - 33431108, 22423954, 49269897, 17927531, 8909498, 8376530, 34483524, 4087880, - 51919953, 19138217, - ]), - xy2d: FieldElement2625([ - 1767664, 7197987, 53903638, 31531796, 54017513, 448825, 5799055, 4357868, - 62334673, 17231393, - ]), - }, - ]), - LookupTable([ - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 6721947, 47388255, 43585475, 32003117, 93463156, 21691110, 90474010, 29604699, - 74499753, 36314231, - ]), - y_minus_x: FieldElement2625([ - 4409022, 2052381, 23373853, 10530217, 7676779, 20668478, 21302352, 29290375, - 1244379, 20634787, - ]), - xy2d: FieldElement2625([ - 62687625, 7169618, 4982368, 30596842, 30256824, 30776892, 14086412, 9208236, - 15886429, 16489664, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 69104920, 43930080, 81455230, 46865633, 60234728, 17116020, 120524529, - 33952799, 36502408, 32841498, - ]), - y_minus_x: FieldElement2625([ - 41801399, 9795879, 64331450, 14878808, 33577029, 14780362, 13348553, 12076947, - 36272402, 5113181, - ]), - xy2d: FieldElement2625([ - 49338080, 11797795, 31950843, 13929123, 41220562, 12288343, 36767763, 26218045, - 13847710, 5387222, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 48526682, 30138214, 84933706, 64767897, 89853205, 56666252, 75871923, 37172217, - 47508201, 43925422, - ]), - y_minus_x: FieldElement2625([ - 20246567, 19185054, 22358228, 33010720, 18507282, 23140436, 14554436, 24808340, - 32232923, 16763880, - ]), - xy2d: FieldElement2625([ - 9648486, 10094563, 26416693, 14745928, 36734546, 27081810, 11094160, 15689506, - 3140038, 17044340, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 50948773, 39027126, 31895587, 38299426, 75932378, 43920116, 39884063, 43003044, - 38334409, 33920726, - ]), - y_minus_x: FieldElement2625([ - 19153450, 11523972, 56012374, 27051289, 42461232, 5420646, 28344573, 8041113, - 719605, 11671788, - ]), - xy2d: FieldElement2625([ - 8678006, 2694440, 60300850, 2517371, 4964326, 11152271, 51675948, 18287915, - 27000812, 23358879, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 119059805, 40688742, 75748150, 30739554, 59873175, 43976173, 67672928, - 38890528, 73859840, 19033405, - ]), - y_minus_x: FieldElement2625([ - 11836410, 29574944, 26297893, 16080799, 23455045, 15735944, 1695823, 24735310, - 8169719, 16220347, - ]), - xy2d: FieldElement2625([ - 48993007, 8653646, 17578566, 27461813, 59083086, 17541668, 55964556, 30926767, - 61118155, 19388398, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 43800347, 22586119, 82322091, 23473217, 36255258, 22504427, 27884328, 36401716, - 69764724, 35292826, - ]), - y_minus_x: FieldElement2625([ - 39571412, 19301410, 41772562, 25551651, 57738101, 8129820, 21651608, 30315096, - 48021414, 22549153, - ]), - xy2d: FieldElement2625([ - 1533110, 3437855, 23735889, 459276, 29970501, 11335377, 26030092, 5821408, - 10478196, 8544890, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 32173083, 50979553, 24896205, 37475929, 22579055, 63698010, 19270447, 45771905, - 84897880, 63712868, - ]), - y_minus_x: FieldElement2625([ - 36555903, 31326030, 51530034, 23407230, 13243888, 517024, 15479401, 29701199, - 30460519, 1052596, - ]), - xy2d: FieldElement2625([ - 55493970, 13323617, 32618793, 8175907, 51878691, 12596686, 27491595, 28942073, - 3179267, 24075541, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 99055914, 52742212, 62468279, 18214510, 51982886, 27514722, 52352086, 17142691, - 19072639, 24043372, - ]), - y_minus_x: FieldElement2625([ - 11685058, 11822410, 3158003, 19601838, 33402193, 29389366, 5977895, 28339415, - 473098, 5040608, - ]), - xy2d: FieldElement2625([ - 46817982, 8198641, 39698732, 11602122, 1290375, 30754672, 28326861, 1721092, - 47550222, 30422825, - ]), - }, - ]), - LookupTable([ - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 74990396, 10687936, 74687587, 7738377, 48157852, 31000479, 88929649, 8076148, - 39240368, 11538388, - ]), - y_minus_x: FieldElement2625([ - 47173198, 3899860, 18283497, 26752864, 51380203, 22305220, 8754524, 7446702, - 61432810, 5797015, - ]), - xy2d: FieldElement2625([ - 55813245, 29760862, 51326753, 25589858, 12708868, 25098233, 2014098, 24503858, - 64739691, 27677090, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 111745333, 55540121, 106535706, 34700805, 86065554, 50194990, 68301593, - 29840232, 82232482, 44365936, - ]), - y_minus_x: FieldElement2625([ - 14352079, 30134717, 48166819, 10822654, 32750596, 4699007, 67038501, 15776355, - 38222085, 21579878, - ]), - xy2d: FieldElement2625([ - 38867681, 25481956, 62129901, 28239114, 29416930, 1847569, 46454691, 17069576, - 4714546, 23953777, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 15200313, 41923004, 86787964, 15970073, 35236190, 35513882, 24611598, 29010600, - 55362987, 45894651, - ]), - y_minus_x: FieldElement2625([ - 12876937, 23074376, 33134380, 6590940, 60801088, 14872439, 9613953, 8241152, - 15370987, 9608631, - ]), - xy2d: FieldElement2625([ - 62965568, 21540023, 8446280, 33162829, 4407737, 13629032, 59383996, 15866073, - 38898243, 24740332, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 26660609, 51431209, 75502596, 33912478, 59707572, 34547419, 43204630, 34413128, - 87680086, 41974987, - ]), - y_minus_x: FieldElement2625([ - 14620696, 13067227, 51661590, 8264466, 14106269, 15080814, 33531827, 12516406, - 45534429, 21077682, - ]), - xy2d: FieldElement2625([ - 236881, 10476226, 57258, 18877408, 6472997, 2466984, 17258519, 7256740, - 8791136, 15069930, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 68385255, 24182513, 90058498, 17231624, 43615824, 61406677, 81820737, 38428660, - 36445723, 31223040, - ]), - y_minus_x: FieldElement2625([ - 5855666, 4990204, 53397016, 7294283, 59304582, 1924646, 65685689, 25642053, - 34039526, 9234252, - ]), - xy2d: FieldElement2625([ - 20590503, 24535444, 31529743, 26201766, 64402029, 10650547, 31559055, 21944845, - 18979185, 13396066, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 24474268, 38522535, 22267081, 37961786, 91172745, 25229251, 48291976, 13594781, - 33514650, 40576390, - ]), - y_minus_x: FieldElement2625([ - 55541958, 26988926, 45743778, 15928891, 40950559, 4315420, 41160136, 29637754, - 45628383, 12868081, - ]), - xy2d: FieldElement2625([ - 38473832, 13504660, 19988037, 31421671, 21078224, 6443208, 45662757, 2244499, - 54653067, 25465048, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 36513317, 13793478, 61256044, 33873567, 41385691, 60844964, 100195408, 8957936, - 51875216, 39094952, - ]), - y_minus_x: FieldElement2625([ - 55478669, 22050529, 58989363, 25911358, 2620055, 1022908, 43398120, 31985447, - 50980335, 18591624, - ]), - xy2d: FieldElement2625([ - 23152952, 775386, 27395463, 14006635, 57407746, 4649511, 1689819, 892185, - 55595587, 18348483, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 76878974, 43141169, 93604957, 37878551, 68665374, 30004407, 94562682, 38317558, - 47929249, 39421565, - ]), - y_minus_x: FieldElement2625([ - 34343820, 1927589, 31726409, 28801137, 23962433, 17534932, 27846558, 5931263, - 37359161, 17445976, - ]), - xy2d: FieldElement2625([ - 27461885, 30576896, 22380809, 1815854, 44075111, 30522493, 7283489, 18406359, - 47582163, 7734628, - ]), - }, - ]), - LookupTable([ - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 59098581, 57518046, 55988459, 39750469, 29344157, 20123547, 74694158, 30377805, - 85658360, 48856500, - ]), - y_minus_x: FieldElement2625([ - 34450527, 27383209, 59436070, 22502750, 6258877, 13504381, 10458790, 27135971, - 58236621, 8424745, - ]), - xy2d: FieldElement2625([ - 24687186, 8613276, 36441818, 30320886, 1863891, 31723888, 19206233, 7134917, - 55824382, 32725512, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 11334880, 24336410, 75134156, 46261950, 84632755, 23078360, 77352601, 18868970, - 62042829, 50053268, - ]), - y_minus_x: FieldElement2625([ - 8911542, 6887158, 57524604, 26595841, 11145640, 24010752, 17303924, 19430194, - 6536640, 10543906, - ]), - xy2d: FieldElement2625([ - 38162480, 15479762, 49642029, 568875, 65611181, 11223453, 64439674, 16928857, - 39873154, 8876770, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 41365946, 54541999, 118567760, 32707823, 101191041, 32758142, 33627041, - 15824473, 66504438, 24514614, - ]), - y_minus_x: FieldElement2625([ - 10330056, 70051, 7957388, 24551765, 9764901, 15609756, 27698697, 28664395, - 1657393, 3084098, - ]), - xy2d: FieldElement2625([ - 10477963, 26084172, 12119565, 20303627, 29016246, 28188843, 31280318, 14396151, - 36875289, 15272408, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 54820536, 36723894, 28813182, 16658753, 92225296, 27923965, 109043770, - 54472724, 42094105, 35504935, - ]), - y_minus_x: FieldElement2625([ - 40928506, 9489186, 11053416, 18808271, 36055143, 5825629, 58724558, 24786899, - 15341278, 8373727, - ]), - xy2d: FieldElement2625([ - 28685821, 7759505, 52730348, 21551571, 35137043, 4079241, 298136, 23321830, - 64230656, 15190419, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 34175950, 47360767, 52771378, 51314432, 110213106, 10940926, 75778582, - 36296824, 108184414, 60233859, - ]), - y_minus_x: FieldElement2625([ - 65528476, 21825014, 41129205, 22109408, 49696989, 22641577, 9291593, 17306653, - 54954121, 6048604, - ]), - xy2d: FieldElement2625([ - 36803549, 14843443, 1539301, 11864366, 20201677, 1900163, 13934231, 5128323, - 11213262, 9168384, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 40828313, 44562278, 19408959, 32613674, 115624762, 29225850, 62020803, - 22449281, 20470156, 50710163, - ]), - y_minus_x: FieldElement2625([ - 43972811, 9282191, 14855179, 18164354, 59746048, 19145871, 44324911, 14461607, - 14042978, 5230683, - ]), - xy2d: FieldElement2625([ - 29969548, 30812838, 50396996, 25001989, 9175485, 31085458, 21556950, 3506042, - 61174973, 21104723, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 63964099, 42299092, 19704002, 38135710, 46678177, 6830682, 45824694, 42525944, - 38569674, 48880994, - ]), - y_minus_x: FieldElement2625([ - 47644235, 10110287, 49846336, 30050539, 43608476, 1355668, 51585814, 15300987, - 46594746, 9168259, - ]), - xy2d: FieldElement2625([ - 61755510, 4488612, 43305616, 16314346, 7780487, 17915493, 38160505, 9601604, - 33087103, 24543045, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 47665675, 18041531, 46311396, 21109108, 104393280, 43783891, 39664534, - 52108332, 61111992, 49219103, - ]), - y_minus_x: FieldElement2625([ - 23294591, 16921819, 44458082, 25083453, 27844203, 11461195, 13099750, 31094076, - 18151675, 13417686, - ]), - xy2d: FieldElement2625([ - 42385932, 29377914, 35958184, 5988918, 40250079, 6685064, 1661597, 21002991, - 15271675, 18101767, - ]), - }, - ]), - LookupTable([ - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 78541887, 20325766, 75348494, 28274914, 65123427, 32828713, 48410099, 35721975, - 60187562, 20114249, - ]), - y_minus_x: FieldElement2625([ - 35672693, 15575145, 30436815, 12192228, 44645511, 9395378, 57191156, 24915434, - 12215109, 12028277, - ]), - xy2d: FieldElement2625([ - 14098381, 6555944, 23007258, 5757252, 51681032, 20603929, 30123439, 4617780, - 50208775, 32898803, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 63082644, 51868028, 79002030, 47273095, 52299401, 35401816, 51288864, 43708440, - 91082124, 20869957, - ]), - y_minus_x: FieldElement2625([ - 40577025, 29858441, 65199965, 2534300, 35238307, 17004076, 18341389, 22134481, - 32013173, 23450893, - ]), - xy2d: FieldElement2625([ - 41629544, 10876442, 55337778, 18929291, 54739296, 1838103, 21911214, 6354752, - 4425632, 32716610, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 56675456, 18941465, 89338721, 30463384, 53917697, 34331160, 116802352, - 55088400, 71833867, 47599401, - ]), - y_minus_x: FieldElement2625([ - 19268631, 26250011, 1555348, 8692754, 45634805, 23643767, 6347389, 32142648, - 47586572, 17444675, - ]), - xy2d: FieldElement2625([ - 42244775, 12986007, 56209986, 27995847, 55796492, 33405905, 19541417, 8180106, - 9282262, 10282508, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 108012627, 37982977, 58447667, 20360168, 71207265, 52943606, 15522533, 8372215, - 72651459, 22851748, - ]), - y_minus_x: FieldElement2625([ - 56546323, 14895632, 26814552, 16880582, 49628109, 31065071, 64326972, 6993760, - 49014979, 10114654, - ]), - xy2d: FieldElement2625([ - 47001790, 32625013, 31422703, 10427861, 59998115, 6150668, 38017109, 22025285, - 25953724, 33448274, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 62874448, 59069571, 57989737, 36600431, 69210472, 54501569, 86498882, 39648727, - 63793584, 46385556, - ]), - y_minus_x: FieldElement2625([ - 51110167, 7578151, 5310217, 14408357, 33560244, 33329692, 31575953, 6326196, - 7381791, 31132593, - ]), - xy2d: FieldElement2625([ - 46206085, 3296810, 24736065, 17226043, 18374253, 7318640, 6295303, 8082724, - 51746375, 12339663, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 27724736, 35845589, 73197064, 19369633, 68901590, 39412065, 80957277, 15768921, - 92200031, 14856293, - ]), - y_minus_x: FieldElement2625([ - 48242193, 8331042, 24373479, 8541013, 66406866, 24284974, 12927299, 20858939, - 44926390, 24541532, - ]), - xy2d: FieldElement2625([ - 55685435, 28132841, 11632844, 3405020, 30536730, 21880393, 39848098, 13866389, - 30146206, 9142070, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 71032974, 18246915, 120400605, 23499470, 79400683, 32886065, 39406089, 9326383, - 58871006, 37725725, - ]), - y_minus_x: FieldElement2625([ - 51186905, 16037936, 6713787, 16606682, 45496729, 2790943, 26396185, 3731949, - 345228, 28091483, - ]), - xy2d: FieldElement2625([ - 45781307, 13448258, 25284571, 1143661, 20614966, 24705045, 2031538, 21163201, - 50855680, 19972348, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 98125037, 16832002, 93480255, 52657630, 62081513, 14854136, 17477601, 37397089, - 28012649, 50703444, - ]), - y_minus_x: FieldElement2625([ - 62033029, 9368965, 58546785, 28953529, 51858910, 6970559, 57918991, 16292056, - 58241707, 3507939, - ]), - xy2d: FieldElement2625([ - 29439664, 3537914, 23333589, 6997794, 49553303, 22536363, 51899661, 18503164, - 57943934, 6580395, - ]), - }, - ]), - LookupTable([ - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 54922984, 59429075, 83547131, 10826159, 58412047, 27318820, 84969307, 24280585, - 65013061, 42858998, - ]), - y_minus_x: FieldElement2625([ - 20714545, 29217521, 29088194, 7406487, 11426967, 28458727, 14792666, 18945815, - 5289420, 33077305, - ]), - xy2d: FieldElement2625([ - 50443312, 22903641, 60948518, 20248671, 9192019, 31751970, 17271489, 12349094, - 26939669, 29802138, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 54218947, 9373457, 98704712, 16374214, 21471720, 13221525, 39825369, 54760304, - 63410056, 33672318, - ]), - y_minus_x: FieldElement2625([ - 22263325, 26994382, 3984569, 22379786, 51994855, 32987646, 28311252, 5358056, - 43789084, 541963, - ]), - xy2d: FieldElement2625([ - 16259200, 3261970, 2309254, 18019958, 50223152, 28972515, 24134069, 16848603, - 53771797, 20002236, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 76487005, 20414245, 111371745, 20809166, 95307144, 59864765, 64709178, - 32837080, 67799289, 48430675, - ]), - y_minus_x: FieldElement2625([ - 24977353, 33240048, 58884894, 20089345, 28432342, 32378079, 54040059, 21257083, - 44727879, 6618998, - ]), - xy2d: FieldElement2625([ - 65570671, 11685645, 12944378, 13682314, 42719353, 19141238, 8044828, 19737104, - 32239828, 27901670, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 48505798, 38317421, 66182613, 42439735, 105805247, 30367115, 76890510, - 23204372, 32779358, 5095274, - ]), - y_minus_x: FieldElement2625([ - 34100715, 28339925, 34843976, 29869215, 9460460, 24227009, 42507207, 14506723, - 21639561, 30924196, - ]), - xy2d: FieldElement2625([ - 50707921, 20442216, 25239337, 15531969, 3987758, 29055114, 65819361, 26690896, - 17874573, 558605, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 53508716, 10240080, 76280747, 16131052, 46239610, 43154131, 100608350, - 38634582, 69194755, 38674192, - ]), - y_minus_x: FieldElement2625([ - 44903700, 31034903, 50727262, 414690, 42089314, 2170429, 30634760, 25190818, - 35108870, 27794547, - ]), - xy2d: FieldElement2625([ - 60263160, 15791201, 8550074, 32241778, 29928808, 21462176, 27534429, 26362287, - 44757485, 12961481, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 42616785, 57538092, 10368192, 11582341, 110820435, 31309143, 83642793, 8206995, - 104023076, 28394792, - ]), - y_minus_x: FieldElement2625([ - 55987368, 30172197, 2307365, 6362031, 66973409, 8868176, 50273234, 7031274, - 7589640, 8945490, - ]), - xy2d: FieldElement2625([ - 34956097, 8917966, 6661220, 21876816, 65916803, 17761038, 7251488, 22372252, - 24099108, 19098262, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 72128384, 25646961, 71352990, 18840075, 107284455, 40007595, 47990681, - 20265406, 127985831, 56828126, - ]), - y_minus_x: FieldElement2625([ - 10853575, 10721687, 26480089, 5861829, 44113045, 1972174, 65242217, 22996533, - 63745412, 27113307, - ]), - xy2d: FieldElement2625([ - 50106456, 5906789, 221599, 26991285, 7828207, 20305514, 24362660, 31546264, - 53242455, 7421391, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 75248772, 27007934, 99366509, 27663885, 97484582, 1886180, 113042620, 48995682, - 95935221, 29431402, - ]), - y_minus_x: FieldElement2625([ - 6267067, 9695052, 7709135, 16950835, 34239795, 31668296, 14795159, 25714308, - 13746020, 31812384, - ]), - xy2d: FieldElement2625([ - 28584883, 7787108, 60375922, 18503702, 22846040, 25983196, 63926927, 33190907, - 4771361, 25134474, - ]), - }, - ]), - LookupTable([ - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 92058101, 6376278, 39642383, 25379823, 48462709, 23623825, 100652432, 54967168, - 70678489, 44897024, - ]), - y_minus_x: FieldElement2625([ - 26514970, 4740088, 27912651, 3697550, 19331575, 22082093, 6809885, 4608608, - 7325975, 18753361, - ]), - xy2d: FieldElement2625([ - 55490446, 19000001, 42787651, 7655127, 65739590, 5214311, 39708324, 10258389, - 49462170, 25367739, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 11431185, 49377439, 93679108, 47883555, 85138853, 38350513, 35662684, 49135095, - 76389221, 29580744, - ]), - y_minus_x: FieldElement2625([ - 66948081, 23228174, 44253547, 29249434, 46247496, 19933429, 34297962, 22372809, - 51563772, 4387440, - ]), - xy2d: FieldElement2625([ - 46309467, 12194511, 3937617, 27748540, 39954043, 9340369, 42594872, 8548136, - 20617071, 26072431, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 66170039, 29623845, 58394552, 49679149, 91711988, 27329038, 53333511, 55233041, - 91454545, 10325459, - ]), - y_minus_x: FieldElement2625([ - 47253587, 31985546, 44906155, 8714033, 14007766, 6928528, 16318175, 32543743, - 4766742, 3552007, - ]), - xy2d: FieldElement2625([ - 45357481, 16823515, 1351762, 32751011, 63099193, 3950934, 3217514, 14481909, - 10988822, 29559670, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 15564288, 19242862, 70210106, 39238579, 97555643, 25503075, 79785990, 27049088, - 58813011, 46850436, - ]), - y_minus_x: FieldElement2625([ - 57666574, 6624295, 36809900, 21640754, 62437882, 31497052, 31521203, 9614054, - 37108040, 12074673, - ]), - xy2d: FieldElement2625([ - 4771172, 33419193, 14290748, 20464580, 27992297, 14998318, 65694928, 31997715, - 29832612, 17163397, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 7064865, 59567690, 115055764, 62041325, 48217593, 30641695, 92934105, 38847728, - 39986203, 46656021, - ]), - y_minus_x: FieldElement2625([ - 64810282, 2439669, 59642254, 1719964, 39841323, 17225986, 32512468, 28236839, - 36752793, 29363474, - ]), - xy2d: FieldElement2625([ - 37102324, 10162315, 33928688, 3981722, 50626726, 20484387, 14413973, 9515896, - 19568978, 9628812, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 33053784, 33753789, 83003454, 35137490, 94489106, 28973996, 49269969, 61002024, - 60817076, 36992171, - ]), - y_minus_x: FieldElement2625([ - 48129987, 3884492, 19469877, 12726490, 15913552, 13614290, 44147131, 70103, - 7463304, 4176122, - ]), - xy2d: FieldElement2625([ - 39984863, 10659916, 11482427, 17484051, 12771466, 26919315, 34389459, 28231680, - 24216881, 5944158, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 76002989, 41005405, 64444714, 57343111, 106137209, 21165315, 19345745, - 48235228, 78741856, 5847884, - ]), - y_minus_x: FieldElement2625([ - 26942781, 31239115, 9129563, 28647825, 26024104, 11769399, 55590027, 6367193, - 57381634, 4782139, - ]), - xy2d: FieldElement2625([ - 19916442, 28726022, 44198159, 22140040, 25606323, 27581991, 33253852, 8220911, - 6358847, 31680575, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 67910273, 31472729, 16569427, 44619599, 29875703, 33651059, 75017251, 29073951, - 53570360, 34941586, - ]), - y_minus_x: FieldElement2625([ - 19646058, 5720633, 55692158, 12814208, 11607948, 12749789, 14147075, 15156355, - 45242033, 11835259, - ]), - xy2d: FieldElement2625([ - 19299512, 1155910, 28703737, 14890794, 2925026, 7269399, 26121523, 15467869, - 40548314, 5052482, - ]), - }, - ]), - LookupTable([ - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 64091413, 43612637, 69089700, 37518674, 22160965, 12322533, 60677741, 20936246, - 12228556, 26550755, - ]), - y_minus_x: FieldElement2625([ - 32944382, 14922211, 44263970, 5188527, 21913450, 24834489, 4001464, 13238564, - 60994061, 8653814, - ]), - xy2d: FieldElement2625([ - 22865569, 28901697, 27603667, 21009037, 14348957, 8234005, 24808405, 5719875, - 28483275, 2841751, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 117796741, 32441125, 66781144, 21446575, 21886281, 51556090, 65220896, - 33238773, 87040921, 20815228, - ]), - y_minus_x: FieldElement2625([ - 55452759, 10087520, 58243976, 28018288, 47830290, 30498519, 3999227, 13239134, - 62331395, 19644223, - ]), - xy2d: FieldElement2625([ - 1382174, 21859713, 17266789, 9194690, 53784508, 9720080, 20403944, 11284705, - 53095046, 3093229, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 83759766, 56070931, 66044684, 35125060, 58779117, 40907184, 66806439, 16271224, - 43059443, 26862581, - ]), - y_minus_x: FieldElement2625([ - 45197768, 27626490, 62497547, 27994275, 35364760, 22769138, 24123613, 15193618, - 45456747, 16815042, - ]), - xy2d: FieldElement2625([ - 57172930, 29264984, 41829040, 4372841, 2087473, 10399484, 31870908, 14690798, - 17361620, 11864968, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 55801216, 39764803, 80315437, 39360751, 105200035, 19587230, 54777658, - 26067830, 41530403, 50868174, - ]), - y_minus_x: FieldElement2625([ - 14668443, 21284197, 26039038, 15305210, 25515617, 4542480, 10453892, 6577524, - 9145645, 27110552, - ]), - xy2d: FieldElement2625([ - 5974855, 3053895, 57675815, 23169240, 35243739, 3225008, 59136222, 3936127, - 61456591, 30504127, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 97734231, 28825031, 41552902, 20761565, 46624288, 41249530, 17097187, 50805368, - 106217947, 35358062, - ]), - y_minus_x: FieldElement2625([ - 63555773, 9865098, 61880298, 4272700, 61435032, 16864731, 14911343, 12196514, - 45703375, 7047411, - ]), - xy2d: FieldElement2625([ - 20093258, 9920966, 55970670, 28210574, 13161586, 12044805, 34252013, 4124600, - 34765036, 23296865, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 46320021, 14084653, 53577151, 41396578, 19119037, 19731827, 71861240, 24839791, - 45429205, 35842469, - ]), - y_minus_x: FieldElement2625([ - 40289628, 30270716, 29965058, 3039786, 52635099, 2540456, 29457502, 14625692, - 42289247, 12570231, - ]), - xy2d: FieldElement2625([ - 66045306, 22002608, 16920317, 12494842, 1278292, 27685323, 45948920, 30055751, - 55134159, 4724942, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 85069815, 21778897, 62967895, 23851901, 58232301, 32143814, 54201480, 24894499, - 104641427, 35458286, - ]), - y_minus_x: FieldElement2625([ - 23134274, 19275300, 56426866, 31942495, 20684484, 15770816, 54119114, 3190295, - 26955097, 14109738, - ]), - xy2d: FieldElement2625([ - 15308788, 5320727, 36995055, 19235554, 22902007, 7767164, 29425325, 22276870, - 31960941, 11934971, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 39713134, 41990227, 71218507, 12222638, 109589860, 14818667, 87747037, - 38429459, 77600255, 34934149, - ]), - y_minus_x: FieldElement2625([ - 53949449, 9197840, 3875503, 24618324, 65725151, 27674630, 33518458, 16176658, - 21432314, 12180697, - ]), - xy2d: FieldElement2625([ - 55321537, 11500837, 13787581, 19721842, 44678184, 10140204, 1465425, 12689540, - 56807545, 19681548, - ]), - }, - ]), - LookupTable([ - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 72522936, 18168390, 46101199, 43198001, 79943833, 34740580, 64485947, 32212200, - 26128230, 39587344, - ]), - y_minus_x: FieldElement2625([ - 40771450, 19788269, 32496024, 19900513, 17847800, 20885276, 3604024, 8316894, - 41233830, 23117073, - ]), - xy2d: FieldElement2625([ - 3296484, 6223048, 24680646, 21307972, 44056843, 5903204, 58246567, 28915267, - 12376616, 3188849, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 29190450, 18895386, 27549112, 32370916, 70628929, 22857130, 32049514, 26245319, - 50999629, 57256556, - ]), - y_minus_x: FieldElement2625([ - 52364359, 24245275, 735817, 32955454, 46701176, 28496527, 25246077, 17758763, - 18640740, 32593455, - ]), - xy2d: FieldElement2625([ - 60180029, 17123636, 10361373, 5642961, 4910474, 12345252, 35470478, 33060001, - 10530746, 1053335, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 104951742, 52922057, 120679510, 54991489, 47651803, 56453479, 102755357, - 30605445, 24018830, 48581076, - ]), - y_minus_x: FieldElement2625([ - 44516310, 30409154, 64819587, 5953842, 53668675, 9425630, 25310643, 13003497, - 64794073, 18408815, - ]), - xy2d: FieldElement2625([ - 39688860, 32951110, 59064879, 31885314, 41016598, 13987818, 39811242, 187898, - 43942445, 31022696, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 45364447, 19743956, 68953703, 38575859, 123783328, 17642957, 76825530, - 49821353, 62038646, 34280530, - ]), - y_minus_x: FieldElement2625([ - 29370903, 27500434, 7334070, 18212173, 9385286, 2247707, 53446902, 28714970, - 30007387, 17731091, - ]), - xy2d: FieldElement2625([ - 66172485, 16086690, 23751945, 33011114, 65941325, 28365395, 9137108, 730663, - 9835848, 4555336, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 43732410, 34964877, 44855110, 54209249, 97976497, 49381408, 17693929, 34099128, - 55123565, 45977077, - ]), - y_minus_x: FieldElement2625([ - 31117226, 21338698, 53606025, 6561946, 57231997, 20796761, 61990178, 29457725, - 29120152, 13924425, - ]), - xy2d: FieldElement2625([ - 49707966, 19321222, 19675798, 30819676, 56101901, 27695611, 57724924, 22236731, - 7240930, 33317044, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 35747087, 22207651, 119210280, 27698212, 111764387, 54956091, 68331198, - 37943914, 70402500, 51557120, - ]), - y_minus_x: FieldElement2625([ - 50424044, 19110186, 11038543, 11054958, 53307689, 30215898, 42789283, 7733546, - 12796905, 27218610, - ]), - xy2d: FieldElement2625([ - 58349431, 22736595, 41689999, 10783768, 36493307, 23807620, 38855524, 3647835, - 3222231, 22393970, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 85714958, 35247531, 108769341, 51938590, 71221215, 43599452, 23603892, - 31506198, 59558087, 36039416, - ]), - y_minus_x: FieldElement2625([ - 9255298, 30423235, 54952701, 32550175, 13098012, 24339566, 16377219, 31451620, - 47306788, 30519729, - ]), - xy2d: FieldElement2625([ - 44379556, 7496159, 61366665, 11329248, 19991973, 30206930, 35390715, 9936965, - 37011176, 22935634, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 88987435, 28553134, 71447199, 47198328, 64071998, 13160959, 86817760, 5415496, - 59748361, 29445138, - ]), - y_minus_x: FieldElement2625([ - 27736842, 10103576, 12500508, 8502413, 63695848, 23920873, 10436917, 32004156, - 43449720, 25422331, - ]), - xy2d: FieldElement2625([ - 19492550, 21450067, 37426887, 32701801, 63900692, 12403436, 30066266, 8367329, - 13243957, 8709688, - ]), - }, - ]), - LookupTable([ - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 79123950, 36355692, 95306994, 10151020, 91926984, 28811298, 55914672, 27908697, - 72259831, 40828617, - ]), - y_minus_x: FieldElement2625([ - 2831347, 21062286, 1478974, 6122054, 23825128, 20820846, 31097298, 6083058, - 31021603, 23760822, - ]), - xy2d: FieldElement2625([ - 64578913, 31324785, 445612, 10720828, 53259337, 22048494, 43601132, 16354464, - 15067285, 19406725, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 74949787, 47592304, 100852864, 49488446, 66380650, 29911725, 88512851, - 34612017, 47729401, 21151211, - ]), - y_minus_x: FieldElement2625([ - 915865, 17085158, 15608284, 24765302, 42751837, 6060029, 49737545, 8410996, - 59888403, 16527024, - ]), - xy2d: FieldElement2625([ - 32922597, 32997445, 20336073, 17369864, 10903704, 28169945, 16957573, 52992, - 23834301, 6588044, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 32752011, 44787382, 70490858, 24839565, 22652987, 22810329, 17159698, 50243539, - 46794283, 32248439, - ]), - y_minus_x: FieldElement2625([ - 62419196, 9166775, 41398568, 22707125, 11576751, 12733943, 7924251, 30802151, - 1976122, 26305405, - ]), - xy2d: FieldElement2625([ - 21251203, 16309901, 64125849, 26771309, 30810596, 12967303, 156041, 30183180, - 12331344, 25317235, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 75760459, 29077399, 118132091, 28557436, 80111370, 36505236, 96163290, - 28447461, 77116999, 28886530, - ]), - y_minus_x: FieldElement2625([ - 31486061, 15114593, 52847614, 12951353, 14369431, 26166587, 16347320, 19892343, - 8684154, 23021480, - ]), - xy2d: FieldElement2625([ - 19443825, 11385320, 24468943, 23895364, 43189605, 2187568, 40845657, 27467510, - 31316347, 14219878, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 38514355, 1193784, 99354083, 11392484, 31092169, 49277233, 94254877, 40546840, - 29126554, 42761822, - ]), - y_minus_x: FieldElement2625([ - 32382916, 1110093, 18477781, 11028262, 39697101, 26006320, 62128346, 10843781, - 59151264, 19118701, - ]), - xy2d: FieldElement2625([ - 2814918, 7836403, 27519878, 25686276, 46214848, 22000742, 45614304, 8550129, - 28346258, 1994730, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 47530546, 41639976, 53108344, 29605809, 69894701, 17323124, 47591912, 40729325, - 22628101, 41669612, - ]), - y_minus_x: FieldElement2625([ - 36703732, 955510, 55975026, 18476362, 34661776, 20276352, 41457285, 3317159, - 57165847, 930271, - ]), - xy2d: FieldElement2625([ - 51805164, 26720662, 28856489, 1357446, 23421993, 1057177, 24091212, 32165462, - 44343487, 22903716, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 44357614, 28250434, 54201256, 54339997, 51297351, 25757378, 52269845, 50554643, - 65241844, 41953401, - ]), - y_minus_x: FieldElement2625([ - 35139535, 2106402, 62372504, 1362500, 12813763, 16200670, 22981545, 27263159, - 18009407, 17781660, - ]), - xy2d: FieldElement2625([ - 49887941, 24009210, 39324209, 14166834, 29815394, 7444469, 29551787, 29827013, - 19288548, 1325865, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 82209002, 51273111, 110293748, 32549332, 107767535, 49063838, 79485593, - 30075285, 100274970, 25511681, - ]), - y_minus_x: FieldElement2625([ - 20909212, 13023121, 57899112, 16251777, 61330449, 25459517, 12412150, 10018715, - 2213263, 19676059, - ]), - xy2d: FieldElement2625([ - 32529814, 22479743, 30361438, 16864679, 57972923, 1513225, 22922121, 6382134, - 61341936, 8371347, - ]), - }, - ]), - LookupTable([ - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 77032307, 44825931, 79725657, 37099153, 104219359, 31832804, 12891686, - 25361300, 40665920, 44040575, - ]), - y_minus_x: FieldElement2625([ - 44511638, 26541766, 8587002, 25296571, 4084308, 20584370, 361725, 2610596, - 43187334, 22099236, - ]), - xy2d: FieldElement2625([ - 5408392, 32417741, 62139741, 10561667, 24145918, 14240566, 31319731, 29318891, - 19985174, 30118346, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 53114388, 50171252, 81658109, 36895530, 99264821, 13648975, 49531796, 8849296, - 67173894, 41925115, - ]), - y_minus_x: FieldElement2625([ - 58787919, 21504805, 31204562, 5839400, 46481576, 32497154, 47665921, 6922163, - 12743482, 23753914, - ]), - xy2d: FieldElement2625([ - 64747493, 12678784, 28815050, 4759974, 43215817, 4884716, 23783145, 11038569, - 18800704, 255233, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 61839168, 31780545, 13957885, 41545147, 23132994, 34283205, 80502710, 42621388, - 86367551, 52355070, - ]), - y_minus_x: FieldElement2625([ - 64172210, 22726896, 56676774, 14516792, 63468078, 4372540, 35173943, 2209389, - 65584811, 2055793, - ]), - xy2d: FieldElement2625([ - 580882, 16705327, 5468415, 30871414, 36182444, 18858431, 59905517, 24560042, - 37087844, 7394434, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 90947654, 35377159, 118479284, 48797157, 75426955, 29821327, 45436683, - 30062226, 62287122, 48354352, - ]), - y_minus_x: FieldElement2625([ - 13345610, 9759151, 3371034, 17416641, 16353038, 8577942, 31129804, 13496856, - 58052846, 7402517, - ]), - xy2d: FieldElement2625([ - 2286874, 29118501, 47066405, 31546095, 53412636, 5038121, 11006906, 17794080, - 8205060, 1607563, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 81522931, 25552299, 70440693, 63900646, 89358013, 27960243, 85473524, 30647473, - 30019586, 24525154, - ]), - y_minus_x: FieldElement2625([ - 39420813, 1585952, 56333811, 931068, 37988643, 22552112, 52698034, 12029092, - 9944378, 8024, - ]), - xy2d: FieldElement2625([ - 4368715, 29844802, 29874199, 18531449, 46878477, 22143727, 50994269, 32555346, - 58966475, 5640029, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 77408455, 13746482, 11661824, 16234854, 74739102, 5998373, 76918751, 16859867, - 82328661, 19226648, - ]), - y_minus_x: FieldElement2625([ - 27425505, 27835351, 3055005, 10660664, 23458024, 595578, 51710259, 32381236, - 48766680, 9742716, - ]), - xy2d: FieldElement2625([ - 6744077, 2427284, 26042789, 2720740, 66260958, 1118973, 32324614, 7406442, - 12420155, 1994844, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 81121366, 62084143, 115833273, 23975961, 107732385, 29617991, 121184249, - 22644627, 91428792, 27108098, - ]), - y_minus_x: FieldElement2625([ - 16412671, 29047065, 10772640, 15929391, 50040076, 28895810, 10555944, 23070383, - 37006495, 28815383, - ]), - xy2d: FieldElement2625([ - 22397363, 25786748, 57815702, 20761563, 17166286, 23799296, 39775798, 6199365, - 21880021, 21303672, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 62825538, 5368522, 35991846, 41717820, 103894664, 36763558, 83666014, 42445160, - 75949308, 38512191, - ]), - y_minus_x: FieldElement2625([ - 51661137, 709326, 60189418, 22684253, 37330941, 6522331, 45388683, 12130071, - 52312361, 5005756, - ]), - xy2d: FieldElement2625([ - 64994094, 19246303, 23019041, 15765735, 41839181, 6002751, 10183197, 20315106, - 50713577, 31378319, - ]), - }, - ]), - LookupTable([ - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 115191953, 35186435, 80575154, 59113763, 110577275, 16573535, 35094956, - 30497327, 22208661, 35554900, - ]), - y_minus_x: FieldElement2625([ - 3065054, 32141671, 41510189, 33192999, 49425798, 27851016, 58944651, 11248526, - 63417650, 26140247, - ]), - xy2d: FieldElement2625([ - 10379208, 27508878, 8877318, 1473647, 37817580, 21046851, 16690914, 2553332, - 63976176, 16400288, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 82825513, 34808697, 115745037, 41000704, 58659945, 6344163, 45011593, 26268851, - 26894936, 42686498, - ]), - y_minus_x: FieldElement2625([ - 24158868, 12938817, 11085297, 25376834, 39045385, 29097348, 36532400, 64451, - 60291780, 30861549, - ]), - xy2d: FieldElement2625([ - 13488534, 7794716, 22236231, 5989356, 25426474, 20976224, 2350709, 30135921, - 62420857, 2364225, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 83443897, 9132433, 92749446, 40233319, 68834491, 42072368, 55301839, 21856974, - 15445874, 25756331, - ]), - y_minus_x: FieldElement2625([ - 29004188, 25687351, 28661401, 32914020, 54314860, 25611345, 31863254, 29418892, - 66830813, 17795152, - ]), - xy2d: FieldElement2625([ - 60986784, 18687766, 38493958, 14569918, 56250865, 29962602, 10343411, 26578142, - 37280576, 22738620, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 94190495, 37018415, 14099041, 29036828, 68725166, 27348827, 96651499, 15372178, - 84402661, 34515140, - ]), - y_minus_x: FieldElement2625([ - 20263915, 11434237, 61343429, 11236809, 13505955, 22697330, 50997518, 6493121, - 47724353, 7639713, - ]), - xy2d: FieldElement2625([ - 64278047, 18715199, 25403037, 25339236, 58791851, 17380732, 18006286, 17510682, - 29994676, 17746311, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 76878673, 38757082, 110060329, 19923038, 106166724, 21992806, 42495722, - 53248081, 35924287, 34263895, - ]), - y_minus_x: FieldElement2625([ - 12286395, 13076066, 45333675, 32377809, 42105665, 4057651, 35090736, 24663557, - 16102006, 13205847, - ]), - xy2d: FieldElement2625([ - 13733362, 5599946, 10557076, 3195751, 61550873, 8536969, 41568694, 8525971, - 10151379, 10394400, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 71133505, 17416880, 89545125, 12276533, 58009849, 64422764, 86807091, 11743038, - 100915394, 42488844, - ]), - y_minus_x: FieldElement2625([ - 51229064, 29029191, 58528116, 30620370, 14634844, 32856154, 57659786, 3137093, - 55571978, 11721157, - ]), - xy2d: FieldElement2625([ - 17555920, 28540494, 8268605, 2331751, 44370049, 9761012, 9319229, 8835153, - 57903375, 32274386, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 66647436, 25724417, 87722981, 16688287, 59594098, 28747312, 89409167, 34059860, - 73217325, 27371016, - ]), - y_minus_x: FieldElement2625([ - 62038564, 12367916, 36445330, 3234472, 32617080, 25131790, 29880582, 20071101, - 40210373, 25686972, - ]), - xy2d: FieldElement2625([ - 35133562, 5726538, 26934134, 10237677, 63935147, 32949378, 24199303, 3795095, - 7592688, 18562353, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 21594413, 18590204, 84575271, 63031641, 32537082, 36294330, 73516586, 12018832, - 38852812, 37852843, - ]), - y_minus_x: FieldElement2625([ - 46458361, 21592935, 39872588, 570497, 3767144, 31836892, 13891941, 31985238, - 13717173, 10805743, - ]), - xy2d: FieldElement2625([ - 52432215, 17910135, 15287173, 11927123, 24177847, 25378864, 66312432, 14860608, - 40169934, 27690595, - ]), - }, - ]), - LookupTable([ - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 80071405, 38866230, 57048095, 45212711, 85964149, 25600230, 80395126, 54300159, - 62727806, 9882021, - ]), - y_minus_x: FieldElement2625([ - 18512060, 11319350, 46985740, 15090308, 18818594, 5271736, 44380960, 3666878, - 43141434, 30255002, - ]), - xy2d: FieldElement2625([ - 60319844, 30408388, 16192428, 13241070, 15898607, 19348318, 57023983, 26893321, - 64705764, 5276064, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 97278672, 28236783, 93415069, 55358004, 94923826, 40623698, 74261714, 37239413, - 68558087, 13082860, - ]), - y_minus_x: FieldElement2625([ - 10342807, 3098505, 2119311, 193222, 25702612, 12233820, 23697382, 15056736, - 46092426, 25352431, - ]), - xy2d: FieldElement2625([ - 33958735, 3261607, 22745853, 7948688, 19370557, 18376767, 40936887, 6482813, - 56808784, 22494330, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 32869439, 61700319, 25609741, 49233102, 56421094, 51637792, 26112419, 36075440, - 44444575, 40459246, - ]), - y_minus_x: FieldElement2625([ - 29506904, 4457497, 3377935, 23757988, 36598817, 12935079, 1561737, 3841096, - 38105225, 26896789, - ]), - xy2d: FieldElement2625([ - 10340844, 26924055, 48452231, 31276001, 12621150, 20215377, 30878496, 21730062, - 41524312, 5181965, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 25940096, 20896407, 17324187, 56801490, 58437394, 15029093, 91505116, 17103509, - 64786011, 21165857, - ]), - y_minus_x: FieldElement2625([ - 45343161, 9916822, 65808455, 4079497, 66080518, 11909558, 1782390, 12641087, - 20603771, 26992690, - ]), - xy2d: FieldElement2625([ - 48226577, 21881051, 24849421, 11501709, 13161720, 28785558, 1925522, 11914390, - 4662781, 7820689, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 79349895, 33128449, 75241554, 42948365, 32846759, 31954812, 29749455, 45727356, - 83245615, 48818451, - ]), - y_minus_x: FieldElement2625([ - 56758909, 18873868, 58896884, 2330219, 49446315, 19008651, 10658212, 6671822, - 19012087, 3772772, - ]), - xy2d: FieldElement2625([ - 3753511, 30133366, 10617073, 2028709, 14841030, 26832768, 28718731, 17791548, - 20527770, 12988982, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 52286341, 27757162, 63400876, 12689772, 66209881, 22639565, 110034681, - 56543919, 70408527, 54683910, - ]), - y_minus_x: FieldElement2625([ - 50331161, 18301130, 57466446, 4978982, 3308785, 8755439, 6943197, 6461331, - 41525717, 8991217, - ]), - xy2d: FieldElement2625([ - 49882601, 1816361, 65435576, 27467992, 31783887, 25378441, 34160718, 7417949, - 36866577, 1507264, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 29692644, 40384323, 56610063, 37889327, 88054838, 21647935, 38221255, 41763822, - 14606361, 22907359, - ]), - y_minus_x: FieldElement2625([ - 63627275, 8707080, 32188102, 5672294, 22096700, 1711240, 34088169, 9761486, - 4170404, 31469107, - ]), - xy2d: FieldElement2625([ - 55521375, 14855944, 62981086, 32022574, 40459774, 15084045, 22186522, 16002000, - 52832027, 25153633, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 62297389, 47315460, 35404986, 31070512, 63796392, 41423478, 59995291, 23934339, - 80349708, 44520301, - ]), - y_minus_x: FieldElement2625([ - 59366301, 25297669, 52340529, 19898171, 43876480, 12387165, 4498947, 14147411, - 29514390, 4302863, - ]), - xy2d: FieldElement2625([ - 53695440, 21146572, 20757301, 19752600, 14785142, 8976368, 62047588, 31410058, - 17846987, 19582505, - ]), - }, - ]), - LookupTable([ - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 64864393, 32799703, 62511833, 32488122, 60861691, 35009730, 112569999, - 24339641, 61886162, 46204698, - ]), - y_minus_x: FieldElement2625([ - 57202067, 17484121, 21134159, 12198166, 40044289, 708125, 387813, 13770293, - 47974538, 10958662, - ]), - xy2d: FieldElement2625([ - 22470984, 12369526, 23446014, 28113323, 45588061, 23855708, 55336367, 21979976, - 42025033, 4271861, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 109048144, 57055220, 47199530, 48916026, 61124505, 35713623, 67184238, - 62830334, 101691505, 42024103, - ]), - y_minus_x: FieldElement2625([ - 15854951, 4148314, 58214974, 7259001, 11666551, 13824734, 36577666, 2697371, - 24154791, 24093489, - ]), - xy2d: FieldElement2625([ - 15446137, 17747788, 29759746, 14019369, 30811221, 23944241, 35526855, 12840103, - 24913809, 9815020, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 62399559, 27940162, 35267365, 21265538, 52665326, 44353845, 125114051, - 46993199, 85843991, 43020669, - ]), - y_minus_x: FieldElement2625([ - 11933045, 9281483, 5081055, 28370608, 64480701, 28648802, 59381042, 22658328, - 44380208, 16199063, - ]), - xy2d: FieldElement2625([ - 14576810, 379472, 40322331, 25237195, 37682355, 22741457, 67006097, 1876698, - 30801119, 2164795, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 15995067, 36754305, 13672554, 13712240, 47730029, 62461217, 121136116, - 51612593, 53616055, 34822483, - ]), - y_minus_x: FieldElement2625([ - 56818250, 29895392, 63822271, 10948817, 23037027, 3794475, 63638526, 20954210, - 50053494, 3565903, - ]), - xy2d: FieldElement2625([ - 29210069, 24135095, 61189071, 28601646, 10834810, 20226706, 50596761, 22733718, - 39946641, 19523900, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 121055819, 49063018, 83772567, 25398281, 38758921, 42573554, 37925442, - 29785008, 69352974, 19552452, - ]), - y_minus_x: FieldElement2625([ - 61955989, 29753495, 57802388, 27482848, 16243068, 14684434, 41435776, 17373631, - 13491505, 4641841, - ]), - xy2d: FieldElement2625([ - 10813398, 643330, 47920349, 32825515, 30292061, 16954354, 27548446, 25833190, - 14476988, 20787001, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 77400943, 9984944, 73590300, 41834336, 59857349, 40587174, 27282936, 31910173, - 106304917, 12651322, - ]), - y_minus_x: FieldElement2625([ - 35923332, 32741048, 22271203, 11835308, 10201545, 15351028, 17099662, 3988035, - 21721536, 30405492, - ]), - xy2d: FieldElement2625([ - 10202177, 27008593, 35735631, 23979793, 34958221, 25434748, 54202543, 3852693, - 13216206, 14842320, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 51293205, 22953365, 60569911, 26295436, 60124204, 26972653, 35608016, 47320255, - 106783330, 43454614, - ]), - y_minus_x: FieldElement2625([ - 14465486, 19721101, 34974879, 18815558, 39665676, 12990491, 33046193, 15796406, - 60056998, 25514317, - ]), - xy2d: FieldElement2625([ - 30924398, 25274812, 6359015, 20738097, 16508376, 9071735, 41620263, 15413634, - 9524356, 26535554, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 12274182, 20378885, 99736504, 65323537, 73845487, 13267304, 72346523, 28444948, - 82772379, 37590215, - ]), - y_minus_x: FieldElement2625([ - 64157555, 8903984, 17349946, 601635, 50676049, 28941875, 53376124, 17665097, - 44850385, 4659090, - ]), - xy2d: FieldElement2625([ - 50192582, 28601458, 36715152, 18395610, 20774811, 15897498, 5736189, 15026997, - 64930608, 20098846, - ]), - }, - ]), - LookupTable([ - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 58249865, 31335375, 28571665, 56953346, 66634395, 23448733, 63307367, 33832526, - 23440561, 33264224, - ]), - y_minus_x: FieldElement2625([ - 10226222, 27625730, 15139955, 120818, 52241171, 5218602, 32937275, 11551483, - 50536904, 26111567, - ]), - xy2d: FieldElement2625([ - 17932739, 21117156, 43069306, 10749059, 11316803, 7535897, 22503767, 5561594, - 63462240, 3898660, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 74858752, 32584864, 50769132, 33537967, 42090752, 15122142, 65535333, 40706961, - 88940025, 34799664, - ]), - y_minus_x: FieldElement2625([ - 26958440, 18896406, 4314585, 8346991, 61431100, 11960071, 34519569, 32934396, - 36706772, 16838219, - ]), - xy2d: FieldElement2625([ - 54942968, 9166946, 33491384, 13673479, 29787085, 13096535, 6280834, 14587357, - 44770839, 13987524, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 109867800, 7778773, 88224864, 49127028, 62275597, 28196653, 62807965, 28429792, - 59639082, 30696363, - ]), - y_minus_x: FieldElement2625([ - 9681908, 26817309, 35157219, 13591837, 60225043, 386949, 31622781, 6439245, - 52527852, 4091396, - ]), - xy2d: FieldElement2625([ - 58682418, 1470726, 38999185, 31957441, 3978626, 28430809, 47486180, 12092162, - 29077877, 18812444, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 72378032, 26694705, 120987516, 25533715, 25932562, 35317984, 61502753, - 28048550, 47091016, 2357888, - ]), - y_minus_x: FieldElement2625([ - 32264008, 18146780, 61721128, 32394338, 65017541, 29607531, 23104803, 20684524, - 5727337, 189038, - ]), - xy2d: FieldElement2625([ - 14609104, 24599962, 61108297, 16931650, 52531476, 25810533, 40363694, 10942114, - 41219933, 18669734, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 87622345, 39112362, 51504250, 41383962, 93522806, 31535027, 45729895, 41026212, - 13913676, 28416557, - ]), - y_minus_x: FieldElement2625([ - 41534488, 11967825, 29233242, 12948236, 60354399, 4713226, 58167894, 14059179, - 12878652, 8511905, - ]), - xy2d: FieldElement2625([ - 41452044, 3393630, 64153449, 26478905, 64858154, 9366907, 36885446, 6812973, - 5568676, 30426776, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 78738868, 12144453, 69225203, 47160468, 94487748, 49231348, 49700110, 20050058, - 119822531, 8070816, - ]), - y_minus_x: FieldElement2625([ - 27117677, 23547054, 35826092, 27984343, 1127281, 12772488, 37262958, 10483305, - 55556115, 32525717, - ]), - xy2d: FieldElement2625([ - 10637467, 27866368, 5674780, 1072708, 40765276, 26572129, 65424888, 9177852, - 39615702, 15431202, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 87633990, 44446997, 121475255, 12779441, 104724694, 16150073, 105977209, - 14943140, 52052074, 25618500, - ]), - y_minus_x: FieldElement2625([ - 37084402, 5626925, 66557297, 23573344, 753597, 11981191, 25244767, 30314666, - 63752313, 9594023, - ]), - xy2d: FieldElement2625([ - 43356201, 2636869, 61944954, 23450613, 585133, 7877383, 11345683, 27062142, - 13352334, 22577348, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 65177046, 28146973, 70413512, 54223994, 84124668, 62231772, 104433876, - 25801948, 53893326, 33235227, - ]), - y_minus_x: FieldElement2625([ - 20239939, 6607058, 6203985, 3483793, 48721888, 32775202, 46385121, 15077869, - 44358105, 14523816, - ]), - xy2d: FieldElement2625([ - 27406023, 27512775, 27423595, 29057038, 4996213, 10002360, 38266833, 29008937, - 36936121, 28748764, - ]), - }, - ]), - LookupTable([ - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 78483087, 12660714, 17861383, 21013599, 78044431, 34653658, 53222787, 24462691, - 106490683, 44912934, - ]), - y_minus_x: FieldElement2625([ - 54378055, 10311866, 1510375, 10778093, 64989409, 24408729, 32676002, 11149336, - 40985213, 4985767, - ]), - xy2d: FieldElement2625([ - 48012542, 341146, 60911379, 33315398, 15756972, 24757770, 66125820, 13794113, - 47694557, 17933176, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 73598907, 45494717, 25495922, 59382504, 75777235, 24803115, 70476466, 40524436, - 65417798, 58104073, - ]), - y_minus_x: FieldElement2625([ - 1656478, 13457317, 15370807, 6364910, 13605745, 8362338, 47934242, 28078708, - 50312267, 28522993, - ]), - xy2d: FieldElement2625([ - 44835530, 20030007, 67044178, 29220208, 48503227, 22632463, 46537798, 26546453, - 67009010, 23317098, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 84856310, 43593691, 86477162, 29503840, 46478228, 51067577, 99101545, 17696455, - 104957364, 28042459, - ]), - y_minus_x: FieldElement2625([ - 31932008, 28568291, 47496481, 16366579, 22023614, 88450, 11371999, 29810185, - 4882241, 22927527, - ]), - xy2d: FieldElement2625([ - 29796488, 37186, 19818052, 10115756, 55279832, 3352735, 18551198, 3272828, - 61917932, 29392022, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 12501267, 4044383, 58495907, 53716478, 101787674, 38691029, 47878485, 30024734, - 330069, 29895023, - ]), - y_minus_x: FieldElement2625([ - 6384877, 2899513, 17807477, 7663917, 64749976, 12363164, 25366522, 24980540, - 66837568, 12071498, - ]), - xy2d: FieldElement2625([ - 58743349, 29511910, 25133447, 29037077, 60897836, 2265926, 34339246, 1936674, - 61949167, 3829362, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 28425947, 27718999, 66531773, 28857233, 120000172, 40425360, 75030413, - 26986644, 26333139, 47822096, - ]), - y_minus_x: FieldElement2625([ - 56041645, 11871230, 27385719, 22994888, 62522949, 22365119, 10004785, 24844944, - 45347639, 8930323, - ]), - xy2d: FieldElement2625([ - 45911060, 17158396, 25654215, 31829035, 12282011, 11008919, 1541940, 4757911, - 40617363, 17145491, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 80646107, 25794941, 113612887, 44516357, 61186043, 20336366, 53952279, - 39771685, 118274028, 47369420, - ]), - y_minus_x: FieldElement2625([ - 49686272, 15157789, 18705543, 29619, 24409717, 33293956, 27361680, 9257833, - 65152338, 31777517, - ]), - xy2d: FieldElement2625([ - 42063564, 23362465, 15366584, 15166509, 54003778, 8423555, 37937324, 12361134, - 48422886, 4578289, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 91688613, 3711569, 68451186, 22374305, 107212592, 47679386, 44564334, 14074918, - 21964432, 41789689, - ]), - y_minus_x: FieldElement2625([ - 60580251, 31142934, 9442965, 27628844, 12025639, 32067012, 64127349, 31885225, - 13006805, 2355433, - ]), - xy2d: FieldElement2625([ - 50803946, 19949172, 60476436, 28412082, 16974358, 22643349, 27202043, 1719366, - 1141648, 20758196, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 54244901, 53888877, 58790596, 56090772, 60298717, 28710537, 13475065, 30420460, - 32674894, 47269477, - ]), - y_minus_x: FieldElement2625([ - 11423316, 28086373, 32344215, 8962751, 24989809, 9241752, 53843611, 16086211, - 38367983, 17912338, - ]), - xy2d: FieldElement2625([ - 65699196, 12530727, 60740138, 10847386, 19531186, 19422272, 55399715, 7791793, - 39862921, 4383346, - ]), - }, - ]), - LookupTable([ - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 38137947, 38825878, 65842854, 23817442, 121762491, 50287029, 62246456, - 62202414, 27193555, 39799623, - ]), - y_minus_x: FieldElement2625([ - 51914908, 5362277, 65324971, 2695833, 4960227, 12840725, 23061898, 3260492, - 22510453, 8577507, - ]), - xy2d: FieldElement2625([ - 54476394, 11257345, 34415870, 13548176, 66387860, 10879010, 31168030, 13952092, - 37537372, 29918525, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 70986166, 23981692, 99525555, 38959755, 56104456, 19897796, 70868632, 45489751, - 72720723, 41718449, - ]), - y_minus_x: FieldElement2625([ - 50833043, 14667796, 15906460, 12155291, 44997715, 24514713, 32003001, 24722143, - 5773084, 25132323, - ]), - xy2d: FieldElement2625([ - 43320746, 25300131, 1950874, 8937633, 18686727, 16459170, 66203139, 12376319, - 31632953, 190926, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 109624102, 17415545, 58684872, 13378745, 81271271, 6901327, 58820115, 38062995, - 41767308, 29926903, - ]), - y_minus_x: FieldElement2625([ - 8884438, 27670423, 6023973, 10104341, 60227295, 28612898, 18722940, 18768427, - 65436375, 827624, - ]), - xy2d: FieldElement2625([ - 34388281, 17265135, 34605316, 7101209, 13354605, 2659080, 65308289, 19446395, - 42230385, 1541285, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 70010192, 32436744, 70989239, 57049475, 116596786, 29941649, 45306746, - 29986950, 87565708, 31669398, - ]), - y_minus_x: FieldElement2625([ - 27019610, 12299467, 53450576, 31951197, 54247203, 28692960, 47568713, 28538373, - 29439640, 15138866, - ]), - xy2d: FieldElement2625([ - 21536104, 26928012, 34661045, 22864223, 44700786, 5175813, 61688824, 17193268, - 7779327, 109896, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 97388589, 48203181, 59063992, 39979989, 80748484, 32810922, 28698389, 45734550, - 23177718, 33000357, - ]), - y_minus_x: FieldElement2625([ - 26572828, 3405927, 35407164, 12890904, 47843196, 5335865, 60615096, 2378491, - 4439158, 20275085, - ]), - xy2d: FieldElement2625([ - 44392139, 3489069, 57883598, 33221678, 18875721, 32414337, 14819433, 20822905, - 49391106, 28092994, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 62052362, 50120982, 83062524, 37322183, 56672364, 49181491, 66287909, 35731656, - 75658945, 18440266, - ]), - y_minus_x: FieldElement2625([ - 48635543, 16596774, 66727204, 15663610, 22860960, 15585581, 39264755, 29971692, - 43848403, 25125843, - ]), - xy2d: FieldElement2625([ - 34628313, 15707274, 58902952, 27902350, 29464557, 2713815, 44383727, 15860481, - 45206294, 1494192, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 47546754, 53021470, 41524990, 24254879, 80236705, 34314140, 21923481, 16529112, - 75851568, 46521448, - ]), - y_minus_x: FieldElement2625([ - 38643965, 1553204, 32536856, 23080703, 42417258, 33148257, 58194238, 30620535, - 37205105, 15553882, - ]), - xy2d: FieldElement2625([ - 21877890, 3230008, 9881174, 10539357, 62311749, 2841331, 11543572, 14513274, - 19375923, 20906471, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 75941133, 52613378, 80362373, 38692006, 72146734, 37633208, 24880817, 60886148, - 69971515, 9455042, - ]), - y_minus_x: FieldElement2625([ - 29306751, 5123106, 20245049, 19404543, 9592565, 8447059, 65031740, 30564351, - 15511448, 4789663, - ]), - xy2d: FieldElement2625([ - 46429108, 7004546, 8824831, 24119455, 63063159, 29803695, 61354101, 108892, - 23513200, 16652362, - ]), - }, - ]), - LookupTable([ - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 100961536, 37699212, 62632834, 26975308, 77878902, 26398889, 60458447, - 54172563, 115898528, 43767290, - ]), - y_minus_x: FieldElement2625([ - 2756062, 8598110, 7383731, 26694540, 22312758, 32449420, 21179800, 2600940, - 57120566, 21047965, - ]), - xy2d: FieldElement2625([ - 42463153, 13317461, 36659605, 17900503, 21365573, 22684775, 11344423, 864440, - 64609187, 16844368, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 107784906, 6148327, 49924452, 19080277, 85891792, 33278434, 44547329, 33765731, - 69828620, 38495428, - ]), - y_minus_x: FieldElement2625([ - 65784982, 3911312, 60160120, 14759764, 37081714, 7851206, 21690126, 8518463, - 26699843, 5276295, - ]), - xy2d: FieldElement2625([ - 53958991, 27125364, 9396248, 365013, 24703301, 23065493, 1321585, 149635, - 51656090, 7159368, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 77096625, 30149672, 84616825, 43059961, 76840398, 31388917, 89464872, 41866607, - 89586081, 25151046, - ]), - y_minus_x: FieldElement2625([ - 18155857, 17049442, 19744715, 9006923, 15154154, 23015456, 24256459, 28689437, - 44560690, 9334108, - ]), - xy2d: FieldElement2625([ - 2986088, 28642539, 10776627, 30080588, 10620589, 26471229, 45695018, 14253544, - 44521715, 536905, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 71486582, 41670267, 91675941, 15495313, 78733938, 46619030, 74499414, 44144056, - 77946923, 51688439, - ]), - y_minus_x: FieldElement2625([ - 47766460, 867879, 9277171, 30335973, 52677291, 31567988, 19295825, 17757482, - 6378259, 699185, - ]), - xy2d: FieldElement2625([ - 7895007, 4057113, 60027092, 20476675, 49222032, 33231305, 66392824, 15693154, - 62063800, 20180469, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 59371282, 27685029, 119651408, 26147511, 78494517, 46756047, 31730677, - 22591592, 63190227, 23885106, - ]), - y_minus_x: FieldElement2625([ - 10188286, 17783598, 59772502, 13427542, 22223443, 14896287, 30743455, 7116568, - 45322357, 5427592, - ]), - xy2d: FieldElement2625([ - 696102, 13206899, 27047647, 22922350, 15285304, 23701253, 10798489, 28975712, - 19236242, 12477404, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 55879406, 44798227, 50054593, 25513566, 66320635, 58940896, 63211193, 44734935, - 43939347, 41288075, - ]), - y_minus_x: FieldElement2625([ - 17800790, 19518253, 40108434, 21787760, 23887826, 3149671, 23466177, 23016261, - 10322026, 15313801, - ]), - xy2d: FieldElement2625([ - 26246234, 11968874, 32263343, 28085704, 6830754, 20231401, 51314159, 33452449, - 42659621, 10890803, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 35743198, 43825794, 54448238, 27287163, 83799070, 54046319, 119235514, - 50039361, 92289660, 28219547, - ]), - y_minus_x: FieldElement2625([ - 66522290, 10376443, 34522450, 22268075, 19801892, 10997610, 2276632, 9482883, - 316878, 13820577, - ]), - xy2d: FieldElement2625([ - 57226037, 29044064, 64993357, 16457135, 56008783, 11674995, 30756178, 26039378, - 30696929, 29841583, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 100097781, 23951019, 12499365, 41465219, 56491606, 21622917, 59766047, - 57123466, 34759345, 7392472, - ]), - y_minus_x: FieldElement2625([ - 58253184, 15927860, 9866406, 29905021, 64711949, 16898650, 36699387, 24419436, - 25112946, 30627788, - ]), - xy2d: FieldElement2625([ - 64604801, 33117465, 25621773, 27875660, 15085041, 28074555, 42223985, 20028237, - 5537437, 19640113, - ]), - }, - ]), - LookupTable([ - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 55883261, 2320284, 57524584, 10149186, 100773065, 5808646, 119341477, 31824763, - 98343453, 39645030, - ]), - y_minus_x: FieldElement2625([ - 57475529, 116425, 26083934, 2897444, 60744427, 30866345, 609720, 15878753, - 60138459, 24519663, - ]), - xy2d: FieldElement2625([ - 39351007, 247743, 51914090, 24551880, 23288160, 23542496, 43239268, 6503645, - 20650474, 1804084, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 106627923, 49010854, 76081380, 42024039, 82749485, 37994278, 70230858, - 56779150, 94951478, 33352103, - ]), - y_minus_x: FieldElement2625([ - 51801891, 2839643, 22530074, 10026331, 4602058, 5048462, 28248656, 5031932, - 55733782, 12714368, - ]), - xy2d: FieldElement2625([ - 20807691, 26283607, 29286140, 11421711, 39232341, 19686201, 45881388, 1035545, - 47375635, 12796919, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 79185725, 52807577, 58323861, 21705509, 42096072, 49955115, 49517368, 20654993, - 70589528, 51926048, - ]), - y_minus_x: FieldElement2625([ - 34747315, 5457596, 28548107, 7833186, 7303070, 21600887, 42745799, 17632556, - 33734809, 2771024, - ]), - xy2d: FieldElement2625([ - 45719598, 421931, 26597266, 6860826, 22486084, 26817260, 49971378, 29344205, - 42556581, 15673396, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 46924223, 35892647, 19788684, 57487908, 63107597, 24813538, 46837679, 38287685, - 70836007, 20619983, - ]), - y_minus_x: FieldElement2625([ - 6120100, 814863, 55314462, 32931715, 6812204, 17806661, 2019593, 7975683, - 31123697, 22595451, - ]), - xy2d: FieldElement2625([ - 30069250, 22119100, 30434653, 2958439, 18399564, 32578143, 12296868, 9204260, - 50676426, 9648164, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 32705413, 32003455, 97814521, 41005496, 55303257, 43186244, 70414129, 38803035, - 108209395, 22176929, - ]), - y_minus_x: FieldElement2625([ - 17219846, 2375039, 35537917, 27978816, 47649184, 9219902, 294711, 15298639, - 2662509, 17257359, - ]), - xy2d: FieldElement2625([ - 65935918, 25995736, 62742093, 29266687, 45762450, 25120105, 32087528, 32331655, - 32247247, 19164571, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 14312609, 34775988, 17395389, 58408721, 62163121, 58424228, 106019982, - 23916613, 51081240, 20175586, - ]), - y_minus_x: FieldElement2625([ - 65680039, 23875441, 57873182, 6549686, 59725795, 33085767, 23046501, 9803137, - 17597934, 2346211, - ]), - xy2d: FieldElement2625([ - 18510781, 15337574, 26171504, 981392, 44867312, 7827555, 43617730, 22231079, - 3059832, 21771562, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 77250443, 39637338, 84938156, 31606788, 76938955, 13613135, 41552228, 28009845, - 33606651, 37146527, - ]), - y_minus_x: FieldElement2625([ - 33114149, 17665080, 40583177, 20211034, 33076704, 8716171, 1151462, 1521897, - 66126199, 26716628, - ]), - xy2d: FieldElement2625([ - 34169699, 29298616, 23947180, 33230254, 34035889, 21248794, 50471177, 3891703, - 26353178, 693168, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 97483084, 35150011, 117333688, 46741361, 71709207, 33961335, 76694157, - 33153763, 31375463, 47924397, - ]), - y_minus_x: FieldElement2625([ - 52738210, 25781902, 1510300, 6434173, 48324075, 27291703, 32732229, 20445593, - 17901440, 16011505, - ]), - xy2d: FieldElement2625([ - 18171223, 21619806, 54608461, 15197121, 56070717, 18324396, 47936623, 17508055, - 8764034, 12309598, - ]), - }, - ]), - LookupTable([ - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 73084753, 28311243, 47649501, 23872684, 55567586, 14015781, 110551971, - 34782749, 17544095, 22960650, - ]), - y_minus_x: FieldElement2625([ - 5811932, 31839139, 3442886, 31285122, 48741515, 25194890, 49064820, 18144304, - 61543482, 12348899, - ]), - xy2d: FieldElement2625([ - 35709185, 11407554, 25755363, 6891399, 63851926, 14872273, 42259511, 8141294, - 56476330, 32968952, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 121542424, 34248456, 62032718, 46854775, 81124121, 19103037, 124519055, - 22225380, 30944592, 1130208, - ]), - y_minus_x: FieldElement2625([ - 8247747, 26843490, 40546482, 25845122, 52706924, 18905521, 4652151, 2488540, - 23550156, 33283200, - ]), - xy2d: FieldElement2625([ - 17294297, 29765994, 7026747, 15626851, 22990044, 113481, 2267737, 27646286, - 66700045, 33416712, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 83199930, 17300505, 85708115, 40895109, 69246500, 32332774, 63744702, 48105367, - 70369388, 26388160, - ]), - y_minus_x: FieldElement2625([ - 62198760, 20221544, 18550886, 10864893, 50649539, 26262835, 44079994, 20349526, - 54360141, 2701325, - ]), - xy2d: FieldElement2625([ - 58534169, 16099414, 4629974, 17213908, 46322650, 27548999, 57090500, 9276970, - 11329923, 1862132, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 14763057, 17650824, 103299457, 3689865, 70620756, 43867957, 45157775, 45773662, - 58070900, 32614131, - ]), - y_minus_x: FieldElement2625([ - 8894987, 30108338, 6150752, 3013931, 301220, 15693451, 35127648, 30644714, - 51670695, 11595569, - ]), - xy2d: FieldElement2625([ - 15214943, 3537601, 40870142, 19495559, 4418656, 18323671, 13947275, 10730794, - 53619402, 29190761, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 64570539, 41237224, 99867876, 33817540, 104232996, 25598978, 111885603, - 23365795, 68085971, 34254425, - ]), - y_minus_x: FieldElement2625([ - 54642373, 4195083, 57897332, 550903, 51543527, 12917919, 19118110, 33114591, - 36574330, 19216518, - ]), - xy2d: FieldElement2625([ - 31788442, 19046775, 4799988, 7372237, 8808585, 18806489, 9408236, 23502657, - 12493931, 28145115, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 41428258, 5260743, 47873055, 27269961, 63412921, 16566086, 94327144, 36161552, - 29375954, 6024730, - ]), - y_minus_x: FieldElement2625([ - 842132, 30759739, 62345482, 24831616, 26332017, 21148791, 11831879, 6985184, - 57168503, 2854095, - ]), - xy2d: FieldElement2625([ - 62261602, 25585100, 2516241, 27706719, 9695690, 26333246, 16512644, 960770, - 12121869, 16648078, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 51890193, 48221527, 53772634, 35568148, 97707150, 33090294, 35603941, 25672367, - 20237805, 36392843, - ]), - y_minus_x: FieldElement2625([ - 47820798, 4453151, 15298546, 17376044, 22115042, 17581828, 12544293, 20083975, - 1068880, 21054527, - ]), - xy2d: FieldElement2625([ - 57549981, 17035596, 33238497, 13506958, 30505848, 32439836, 58621956, 30924378, - 12521377, 4845654, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 106019188, 44298538, 64150483, 43754095, 74868174, 54020263, 70518210, - 32681031, 127735421, 20668560, - ]), - y_minus_x: FieldElement2625([ - 43547042, 6230155, 46726851, 10655313, 43068279, 21933259, 10477733, 32314216, - 63995636, 13974497, - ]), - xy2d: FieldElement2625([ - 12966261, 15550616, 35069916, 31939085, 21025979, 32924988, 5642324, 7188737, - 18895762, 12629579, - ]), - }, - ]), - LookupTable([ - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 14741860, 18607545, 89286071, 21833194, 68388604, 41613031, 11758139, 34343875, - 32195180, 37450109, - ]), - y_minus_x: FieldElement2625([ - 10758205, 15755439, 62598914, 9243697, 62229442, 6879878, 64904289, 29988312, - 58126794, 4429646, - ]), - xy2d: FieldElement2625([ - 64654951, 15725972, 46672522, 23143759, 61304955, 22514211, 59972993, 21911536, - 18047435, 18272689, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 41935825, 55801698, 29759954, 45331216, 111955344, 51288407, 78101976, - 54258026, 49488161, 57700395, - ]), - y_minus_x: FieldElement2625([ - 21987233, 700364, 42603816, 14972007, 59334599, 27836036, 32155025, 2581431, - 37149879, 8773374, - ]), - xy2d: FieldElement2625([ - 41540495, 454462, 53896929, 16126714, 25240068, 8594567, 20656846, 12017935, - 59234475, 19634276, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 73137027, 39817509, 103205921, 55807152, 66289943, 36016203, 102376553, - 61640820, 65387074, 30777706, - ]), - y_minus_x: FieldElement2625([ - 54829870, 16624276, 987579, 27631834, 32908202, 1248608, 7719845, 29387734, - 28408819, 6816612, - ]), - xy2d: FieldElement2625([ - 56750770, 25316602, 19549650, 21385210, 22082622, 16147817, 20613181, 13982702, - 56769294, 5067942, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 36602859, 29732664, 79183544, 13582411, 47230892, 35998382, 47389577, 12746131, - 72440074, 57002919, - ]), - y_minus_x: FieldElement2625([ - 30528792, 3601899, 65151774, 4619784, 39747042, 18118043, 24180792, 20984038, - 27679907, 31905504, - ]), - xy2d: FieldElement2625([ - 9402385, 19597367, 32834042, 10838634, 40528714, 20317236, 26653273, 24868867, - 22611443, 20839026, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 89299435, 34672460, 22736440, 48684895, 103757035, 27563109, 86298488, - 62459921, 71963721, 40176570, - ]), - y_minus_x: FieldElement2625([ - 58798126, 30600981, 58846284, 30166382, 56707132, 33282502, 13424425, 29987205, - 26404408, 13001963, - ]), - xy2d: FieldElement2625([ - 35867026, 18138731, 64114613, 8939345, 11562230, 20713762, 41044498, 21932711, - 51703708, 11020692, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 68974887, 59159374, 59210213, 23253421, 12483314, 47031979, 70284499, 21130268, - 28761761, 34961166, - ]), - y_minus_x: FieldElement2625([ - 66660290, 31776765, 13018550, 3194501, 57528444, 22392694, 24760584, 29207344, - 25577410, 20175752, - ]), - xy2d: FieldElement2625([ - 42818486, 4759344, 66418211, 31701615, 2066746, 10693769, 37513074, 9884935, - 57739938, 4745409, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 57967561, 39604145, 47577802, 29213020, 102956929, 43498706, 51646855, - 55797011, 78040786, 21622500, - ]), - y_minus_x: FieldElement2625([ - 50547351, 14112679, 59096219, 4817317, 59068400, 22139825, 44255434, 10856640, - 46638094, 13434653, - ]), - xy2d: FieldElement2625([ - 22759470, 23480998, 50342599, 31683009, 13637441, 23386341, 1765143, 20900106, - 28445306, 28189722, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 29875044, 46048045, 69904399, 63322533, 68819482, 48735613, 56913146, 24765756, - 9074233, 34721612, - ]), - y_minus_x: FieldElement2625([ - 40903181, 11014232, 57266213, 30918946, 40200743, 7532293, 48391976, 24018933, - 3843902, 9367684, - ]), - xy2d: FieldElement2625([ - 56139269, 27150720, 9591133, 9582310, 11349256, 108879, 16235123, 8601684, - 66969667, 4242894, - ]), - }, - ]), - LookupTable([ - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 89201818, 53917740, 65066069, 21585919, 99295616, 55591475, 60534521, 36025091, - 106800361, 16625499, - ]), - y_minus_x: FieldElement2625([ - 56051142, 3042015, 13770083, 24296510, 584235, 33009577, 59338006, 2602724, - 39757248, 14247412, - ]), - xy2d: FieldElement2625([ - 6314156, 23289540, 34336361, 15957556, 56951134, 168749, 58490057, 14290060, - 27108877, 32373552, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 58522248, 26383465, 80350645, 44514587, 34117848, 19759835, 100656839, - 22495542, 107069276, 34536304, - ]), - y_minus_x: FieldElement2625([ - 22833421, 9293594, 34459416, 19935764, 57971897, 14756818, 44180005, 19583651, - 56629059, 17356469, - ]), - xy2d: FieldElement2625([ - 59340277, 3326785, 38997067, 10783823, 19178761, 14905060, 22680049, 13906969, - 51175174, 3797898, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 88830182, 29341685, 54902740, 42864613, 63226624, 19901321, 90849087, 30845199, - 87600846, 59066711, - ]), - y_minus_x: FieldElement2625([ - 9209251, 18419377, 53852306, 27386633, 66377847, 15289672, 25947805, 15286587, - 30997318, 26851369, - ]), - xy2d: FieldElement2625([ - 7392013, 16618386, 23946583, 25514540, 53843699, 32020573, 52911418, 31232855, - 17649997, 33304352, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 57807757, 52915036, 97718388, 30504888, 41933794, 32270679, 51867297, 24028707, - 64875610, 41216577, - ]), - y_minus_x: FieldElement2625([ - 49550191, 1763593, 33994528, 15908609, 37067994, 21380136, 7335079, 25082233, - 63934189, 3440182, - ]), - xy2d: FieldElement2625([ - 47219164, 27577423, 42997570, 23865561, 10799742, 16982475, 40449, 29122597, - 4862399, 1133, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 34252636, 25680474, 61686474, 48415381, 50789832, 41510573, 74366924, 33866292, - 36513872, 26175010, - ]), - y_minus_x: FieldElement2625([ - 63335436, 31988495, 28985339, 7499440, 24445838, 9325937, 29727763, 16527196, - 18278453, 15405622, - ]), - xy2d: FieldElement2625([ - 62726958, 8508651, 47210498, 29880007, 61124410, 15149969, 53795266, 843522, - 45233802, 13626196, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 69390312, 20067376, 56193445, 30944521, 68988221, 49718638, 56324981, 37508223, - 80449702, 15928662, - ]), - y_minus_x: FieldElement2625([ - 31727126, 26374577, 48671360, 25270779, 2875792, 17164102, 41838969, 26539605, - 43656557, 5964752, - ]), - xy2d: FieldElement2625([ - 4100401, 27594980, 49929526, 6017713, 48403027, 12227140, 40424029, 11344143, - 2538215, 25983677, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 57675240, 6123112, 78268667, 31397823, 97125143, 48520672, 46633880, 35039852, - 66479607, 17595569, - ]), - y_minus_x: FieldElement2625([ - 40304287, 4260918, 11851389, 9658551, 35091757, 16367491, 46903439, 20363143, - 11659921, 22439314, - ]), - xy2d: FieldElement2625([ - 26180377, 10015009, 36264640, 24973138, 5418196, 9480663, 2231568, 23384352, - 33100371, 32248261, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 82229958, 28352560, 56718958, 48982252, 39598926, 17561924, 88779810, 38041106, - 61177053, 19088051, - ]), - y_minus_x: FieldElement2625([ - 16166467, 24070699, 56004733, 6023907, 35182066, 32189508, 2340059, 17299464, - 56373093, 23514607, - ]), - xy2d: FieldElement2625([ - 28042865, 29997343, 54982337, 12259705, 63391366, 26608532, 6766452, 24864833, - 18036435, 5803270, - ]), - }, - ]), - LookupTable([ - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 66291264, 40318343, 78912424, 35140016, 78067310, 30883266, 23855390, 4598332, - 60949433, 19436993, - ]), - y_minus_x: FieldElement2625([ - 36077558, 19298237, 17332028, 31170912, 31312681, 27587249, 696308, 50292, - 47013125, 11763583, - ]), - xy2d: FieldElement2625([ - 66514282, 31040148, 34874710, 12643979, 12650761, 14811489, 665117, 20940800, - 47335652, 22840869, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 97573435, 55845991, 62981386, 20819953, 86944190, 60003250, 109821551, - 35630203, 50088706, 34546902, - ]), - y_minus_x: FieldElement2625([ - 18357166, 26559999, 7766381, 16342475, 37783946, 411173, 14578841, 8080033, - 55534529, 22952821, - ]), - xy2d: FieldElement2625([ - 19598397, 10334610, 12555054, 2555664, 18821899, 23214652, 21873262, 16014234, - 26224780, 16452269, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 36884920, 5145195, 73053412, 49940397, 71085598, 35564328, 122839923, 25936244, - 46575034, 37253081, - ]), - y_minus_x: FieldElement2625([ - 14187449, 3448569, 56472628, 22743496, 44444983, 30120835, 7268409, 22663988, - 27394300, 12015369, - ]), - xy2d: FieldElement2625([ - 19695742, 16087646, 28032085, 12999827, 6817792, 11427614, 20244189, 32241655, - 53849736, 30151970, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 97968948, 12735207, 65220619, 28854697, 50133957, 35811371, 126051714, - 45852742, 58558339, 23160969, - ]), - y_minus_x: FieldElement2625([ - 61389038, 22309106, 65198214, 15569034, 26642876, 25966672, 61319509, 18435777, - 62132699, 12651792, - ]), - xy2d: FieldElement2625([ - 64260450, 9953420, 11531313, 28271553, 26895122, 20857343, 53990043, 17036529, - 9768697, 31021214, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 109498250, 35449081, 66821165, 28850346, 82457582, 25397901, 32767512, - 46319882, 72048958, 44232657, - ]), - y_minus_x: FieldElement2625([ - 18860224, 15980149, 48121624, 31991861, 40875851, 22482575, 59264981, 13944023, - 42736516, 16582018, - ]), - xy2d: FieldElement2625([ - 51604604, 4970267, 37215820, 4175592, 46115652, 31354675, 55404809, 15444559, - 56105103, 7989036, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 98599278, 39122492, 64696060, 35736814, 34772016, 38086117, 35030594, 39754637, - 47422750, 52308692, - ]), - y_minus_x: FieldElement2625([ - 49800177, 17674491, 35586086, 33551600, 34221481, 16375548, 8680158, 17182719, - 28550067, 26697300, - ]), - xy2d: FieldElement2625([ - 38981977, 27866340, 16837844, 31733974, 60258182, 12700015, 37068883, 4364037, - 1155602, 5988841, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 88999280, 20281524, 121593716, 12154347, 59276991, 48854927, 90257846, - 29083950, 91727270, 41837612, - ]), - y_minus_x: FieldElement2625([ - 33972757, 23041680, 9975415, 6841041, 35549071, 16356535, 3070187, 26528504, - 1466168, 10740210, - ]), - xy2d: FieldElement2625([ - 65599446, 18066246, 53605478, 22898515, 32799043, 909394, 53169961, 27774712, - 34944214, 18227391, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 71069668, 19286628, 39082773, 51190812, 47704004, 46701299, 82676190, 34505938, - 63848542, 32980496, - ]), - y_minus_x: FieldElement2625([ - 24740822, 5052253, 37014733, 8961360, 25877428, 6165135, 42740684, 14397371, - 59728495, 27410326, - ]), - xy2d: FieldElement2625([ - 38220480, 3510802, 39005586, 32395953, 55870735, 22922977, 51667400, 19101303, - 65483377, 27059617, - ]), - }, - ]), - LookupTable([ - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 67902144, 24323953, 75945165, 27318724, 39747955, 31184838, 100261706, - 62223612, 57202662, 32932579, - ]), - y_minus_x: FieldElement2625([ - 5666214, 525582, 20782575, 25516013, 42570364, 14657739, 16099374, 1468826, - 60937436, 18367850, - ]), - xy2d: FieldElement2625([ - 62249590, 29775088, 64191105, 26806412, 7778749, 11688288, 36704511, 23683193, - 65549940, 23690785, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 10896313, 25834728, 67933138, 34027032, 114757419, 36564017, 25248957, - 48337770, 36527387, 17796587, - ]), - y_minus_x: FieldElement2625([ - 10566929, 12612572, 35164652, 11118702, 54475488, 12362878, 21752402, 8822496, - 24003793, 14264025, - ]), - xy2d: FieldElement2625([ - 27713843, 26198459, 56100623, 9227529, 27050101, 2504721, 23886875, 20436907, - 13958494, 27821979, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 110736080, 38421656, 39861735, 37454952, 29838368, 25342141, 102328328, - 23512649, 74449384, 51698795, - ]), - y_minus_x: FieldElement2625([ - 4646495, 25543308, 44342840, 22021777, 23184552, 8566613, 31366726, 32173371, - 52042079, 23179239, - ]), - xy2d: FieldElement2625([ - 49838347, 12723031, 50115803, 14878793, 21619651, 27356856, 27584816, 3093888, - 58265170, 3849920, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 58043933, 35657603, 92670503, 51983125, 61869038, 43137389, 99585908, 24536476, - 72111157, 18004172, - ]), - y_minus_x: FieldElement2625([ - 55051311, 22376525, 21115584, 20189277, 8808711, 21523724, 16489529, 13378448, - 41263148, 12741425, - ]), - xy2d: FieldElement2625([ - 61162478, 10645102, 36197278, 15390283, 63821882, 26435754, 24306471, 15852464, - 28834118, 25908360, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 49773097, 24447374, 109686448, 42989383, 58636779, 32971069, 54018092, - 34010272, 87570721, 39045736, - ]), - y_minus_x: FieldElement2625([ - 13669229, 17458950, 54626889, 23351392, 52539093, 21661233, 42112877, 11293806, - 38520660, 24132599, - ]), - xy2d: FieldElement2625([ - 28497909, 6272777, 34085870, 14470569, 8906179, 32328802, 18504673, 19389266, - 29867744, 24758489, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 50901822, 47071627, 39309233, 19856633, 24009063, 60734973, 60741262, 53933471, - 22853427, 29542421, - ]), - y_minus_x: FieldElement2625([ - 24191359, 16712145, 53177067, 15217830, 14542237, 1646131, 18603514, 22516545, - 12876622, 31441985, - ]), - xy2d: FieldElement2625([ - 17902668, 4518229, 66697162, 30725184, 26878216, 5258055, 54248111, 608396, - 16031844, 3723494, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 105584936, 12763726, 46662418, 41131935, 33001347, 54091119, 17558840, - 59235974, 23896952, 29240187, - ]), - y_minus_x: FieldElement2625([ - 47103464, 21542479, 31520463, 605201, 2543521, 5991821, 64163800, 7229063, - 57189218, 24727572, - ]), - xy2d: FieldElement2625([ - 28816026, 298879, 38943848, 17633493, 19000927, 31888542, 54428030, 30605106, - 49057085, 31471516, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 16000882, 33209536, 70601955, 55661665, 37604267, 20394642, 79686603, 49595699, - 47393623, 7847706, - ]), - y_minus_x: FieldElement2625([ - 10151868, 10572098, 27312476, 7922682, 14825339, 4723128, 34252933, 27035413, - 57088296, 3852847, - ]), - xy2d: FieldElement2625([ - 55678375, 15697595, 45987307, 29133784, 5386313, 15063598, 16514493, 17622322, - 29330898, 18478208, - ]), - }, - ]), - LookupTable([ - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 41609110, 29175637, 51885955, 26653220, 83724594, 35606215, 70412565, 33569921, - 106668931, 45868821, - ]), - y_minus_x: FieldElement2625([ - 15683501, 27551389, 18109119, 23573784, 15337967, 27556609, 50391428, 15921865, - 16103996, 29823217, - ]), - xy2d: FieldElement2625([ - 43939021, 22773182, 13588191, 31925625, 63310306, 32479502, 47835256, 5402698, - 37293151, 23713330, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 90299521, 35939014, 34394523, 37016585, 104314072, 32025298, 55842007, 8911516, - 109011869, 36294143, - ]), - y_minus_x: FieldElement2625([ - 21374101, 30000182, 33584214, 9874410, 15377179, 11831242, 33578960, 6134906, - 4931255, 11987849, - ]), - xy2d: FieldElement2625([ - 67101132, 30575573, 50885377, 7277596, 105524, 33232381, 35628324, 13861387, - 37032554, 10117929, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 37607694, 22809559, 40945095, 13051538, 41483300, 38644074, 127892224, - 40258509, 79998882, 15728939, - ]), - y_minus_x: FieldElement2625([ - 45136504, 21783052, 66157804, 29135591, 14704839, 2695116, 903376, 23126293, - 12885166, 8311031, - ]), - xy2d: FieldElement2625([ - 49592363, 5352193, 10384213, 19742774, 7506450, 13453191, 26423267, 4384730, - 1888765, 28119028, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 108400371, 64001550, 120723127, 30371924, 98005322, 19632702, 101966083, - 20846561, 47644429, 30214188, - ]), - y_minus_x: FieldElement2625([ - 43500868, 30888657, 66582772, 4651135, 5765089, 4618330, 6092245, 14845197, - 17151279, 23700316, - ]), - xy2d: FieldElement2625([ - 42278406, 20820711, 51942885, 10367249, 37577956, 33289075, 22825804, 26467153, - 50242379, 16176524, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 43525570, 40119392, 87172552, 37352659, 129477549, 40913655, 69115045, - 23191005, 38362610, 56911354, - ]), - y_minus_x: FieldElement2625([ - 56482264, 29068029, 53788301, 28429114, 3432135, 27161203, 23632036, 31613822, - 32808309, 1099883, - ]), - xy2d: FieldElement2625([ - 15030958, 5768825, 39657628, 30667132, 60681485, 18193060, 51830967, 26745081, - 2051440, 18328567, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 63746522, 26315059, 74626753, 43379423, 90664713, 33849800, 72257261, 52954675, - 44422508, 50188091, - ]), - y_minus_x: FieldElement2625([ - 4577067, 16802144, 13249840, 18250104, 19958762, 19017158, 18559669, 22794883, - 8402477, 23690159, - ]), - xy2d: FieldElement2625([ - 38702534, 32502850, 40318708, 32646733, 49896449, 22523642, 9453450, 18574360, - 17983009, 9967138, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 41346351, 40079153, 93694351, 43523701, 24709297, 34774792, 65430873, 7806336, - 84616260, 37205991, - ]), - y_minus_x: FieldElement2625([ - 56688388, 29436320, 14584638, 15971087, 51340543, 8861009, 26556809, 27979875, - 48555541, 22197296, - ]), - xy2d: FieldElement2625([ - 2839082, 14284142, 4029895, 3472686, 14402957, 12689363, 40466743, 8459446, - 61503401, 25932490, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 62269556, 30018987, 76853824, 2871047, 92222842, 36741449, 109106914, 32705364, - 84366947, 25576692, - ]), - y_minus_x: FieldElement2625([ - 18164541, 22959256, 49953981, 32012014, 19237077, 23809137, 23357532, 18337424, - 26908269, 12150756, - ]), - xy2d: FieldElement2625([ - 36843994, 25906566, 5112248, 26517760, 65609056, 26580174, 43167, 28016731, - 34806789, 16215818, - ]), - }, - ]), - LookupTable([ - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 60209940, 43378825, 54804084, 29153342, 102820586, 27277595, 99683352, - 46087336, 59605791, 24879084, - ]), - y_minus_x: FieldElement2625([ - 39765323, 17038963, 39957339, 22831480, 946345, 16291093, 254968, 7168080, - 21676107, 31611404, - ]), - xy2d: FieldElement2625([ - 21260942, 25129680, 50276977, 21633609, 43430902, 3968120, 63456915, 27338965, - 63552672, 25641356, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 16544735, 46804798, 50304435, 49100673, 62525860, 46311689, 64646555, 24874095, - 48201831, 23891632, - ]), - y_minus_x: FieldElement2625([ - 64693606, 17976703, 18312302, 4964443, 51836334, 20900867, 26820650, 16690659, - 25459437, 28989823, - ]), - xy2d: FieldElement2625([ - 41964155, 11425019, 28423002, 22533875, 60963942, 17728207, 9142794, 31162830, - 60676445, 31909614, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 44004193, 39807907, 16964146, 29785560, 109103755, 54812425, 39651637, - 50764205, 73444554, 40804420, - ]), - y_minus_x: FieldElement2625([ - 36775618, 13979674, 7503222, 21186118, 55152142, 28932738, 36836594, 2682241, - 25993170, 21075909, - ]), - xy2d: FieldElement2625([ - 4364628, 5930691, 32304656, 23509878, 59054082, 15091130, 22857016, 22955477, - 31820367, 15075278, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 98987979, 24635738, 84367624, 33645057, 126175891, 28636721, 91271651, - 23903545, 116247489, 46387475, - ]), - y_minus_x: FieldElement2625([ - 19073683, 14851414, 42705695, 21694263, 7625277, 11091125, 47489674, 2074448, - 57694925, 14905376, - ]), - xy2d: FieldElement2625([ - 24483648, 21618865, 64589997, 22007013, 65555733, 15355505, 41826784, 9253128, - 27628530, 25998952, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 84706452, 41895034, 86464480, 34106618, 26198469, 30377849, 71702187, 24396849, - 120106852, 48851446, - ]), - y_minus_x: FieldElement2625([ - 510886, 14337390, 35323607, 16638631, 6328095, 2713355, 46891447, 21690211, - 8683220, 2921426, - ]), - xy2d: FieldElement2625([ - 18606791, 11874196, 27155355, 28272950, 43077121, 6265445, 41930624, 32275507, - 4674689, 13890525, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 13609605, 13069022, 106845367, 20498522, 91469449, 43147405, 82086020, - 43389536, 71498550, 33842827, - ]), - y_minus_x: FieldElement2625([ - 9922506, 33035038, 13613106, 5883594, 48350519, 33120168, 54804801, 8317627, - 23388070, 16052080, - ]), - xy2d: FieldElement2625([ - 12719997, 11937594, 35138804, 28525742, 26900119, 8561328, 46953177, 21921452, - 52354592, 22741539, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 83070703, 47704840, 93825794, 32888599, 111423399, 47157999, 78938436, - 41022275, 38286735, 34483706, - ]), - y_minus_x: FieldElement2625([ - 11038231, 21972036, 39798381, 26237869, 56610336, 17246600, 43629330, 24182562, - 45715720, 2465073, - ]), - xy2d: FieldElement2625([ - 20017144, 29231206, 27915241, 1529148, 12396362, 15675764, 13817261, 23896366, - 2463390, 28932292, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 50749967, 20890520, 122152544, 38550884, 65852441, 34628003, 76692421, - 12851106, 71112760, 46228148, - ]), - y_minus_x: FieldElement2625([ - 65377275, 18398561, 63845933, 16143081, 19294135, 13385325, 14741514, 24450706, - 7903885, 2348101, - ]), - xy2d: FieldElement2625([ - 24536016, 17039225, 12715591, 29692277, 1511292, 10047386, 63266518, 26425272, - 38731325, 10048126, - ]), - }, - ]), - LookupTable([ - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 54486638, 27349611, 97827688, 2591311, 56491836, 12192839, 85982162, 59811773, - 34811106, 15221631, - ]), - y_minus_x: FieldElement2625([ - 40630742, 22450567, 11546243, 31701949, 9180879, 7656409, 45764914, 2095754, - 29769758, 6593415, - ]), - xy2d: FieldElement2625([ - 35114656, 30646970, 4176911, 3264766, 12538965, 32686321, 26312344, 27435754, - 30958053, 8292160, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 98538667, 53149747, 96282394, 15632447, 12174511, 64348770, 99917693, 37531617, - 93251999, 30405555, - ]), - y_minus_x: FieldElement2625([ - 22648882, 1402143, 44308880, 13746058, 7936347, 365344, 58440231, 31879998, - 63350620, 31249806, - ]), - xy2d: FieldElement2625([ - 51616947, 8012312, 64594134, 20851969, 43143017, 23300402, 65496150, 32018862, - 50444388, 8194477, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 27338047, 26047012, 59694639, 10140404, 48082437, 26964542, 94386054, 42409807, - 95681149, 36559595, - ]), - y_minus_x: FieldElement2625([ - 26287105, 4821776, 25476601, 29408529, 63344350, 17765447, 49100281, 1182478, - 41014043, 20474836, - ]), - xy2d: FieldElement2625([ - 59937691, 3178079, 23970071, 6201893, 49913287, 29065239, 45232588, 19571804, - 32208682, 32356184, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 50451143, 36372074, 56822501, 14811297, 73133531, 46903936, 39793359, 56611021, - 39436277, 22014573, - ]), - y_minus_x: FieldElement2625([ - 15941010, 24148500, 45741813, 8062054, 31876073, 33315803, 51830470, 32110002, - 15397330, 29424239, - ]), - xy2d: FieldElement2625([ - 8934485, 20068965, 43822466, 20131190, 34662773, 14047985, 31170398, 32113411, - 39603297, 15087183, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 115860466, 31397939, 24524912, 16876564, 82629290, 27193655, 118715321, - 11461894, 83897392, 27685489, - ]), - y_minus_x: FieldElement2625([ - 65161459, 16013772, 21750665, 3714552, 49707082, 17498998, 63338576, 23231111, - 31322513, 21938797, - ]), - xy2d: FieldElement2625([ - 21426636, 27904214, 53460576, 28206894, 38296674, 28633461, 48833472, 18933017, - 13040861, 21441484, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 78402740, 46032517, 107081326, 48638180, 104910306, 14748870, 14555558, - 20137329, 68722574, 38451366, - ]), - y_minus_x: FieldElement2625([ - 41213962, 15323293, 58619073, 25496531, 25967125, 20128972, 2825959, 28657387, - 43137087, 22287016, - ]), - xy2d: FieldElement2625([ - 51184079, 28324551, 49665331, 6410663, 3622847, 10243618, 20615400, 12405433, - 43355834, 25118015, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 127126414, 46110638, 114026375, 9025185, 50036385, 4333800, 71487300, 35986461, - 23097948, 32988414, - ]), - y_minus_x: FieldElement2625([ - 4565804, 17528778, 20084411, 25711615, 1724998, 189254, 24767264, 10103221, - 48596551, 2424777, - ]), - xy2d: FieldElement2625([ - 366633, 21577626, 8173089, 26664313, 30788633, 5745705, 59940186, 1344108, - 63466311, 12412658, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 110215918, 41244716, 82038279, 33386174, 102006892, 53695876, 91271559, - 51782359, 63967361, 44733816, - ]), - y_minus_x: FieldElement2625([ - 18289503, 18829478, 8056944, 16430056, 45379140, 7842513, 61107423, 32067534, - 48424218, 22110928, - ]), - xy2d: FieldElement2625([ - 476239, 6601091, 60956074, 23831056, 17503544, 28690532, 27672958, 13403813, - 11052904, 5219329, - ]), - }, - ]), - LookupTable([ - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 87787372, 25178693, 34436965, 42403554, 129207969, 48129182, 98295834, - 29580701, 9014761, 58529808, - ]), - y_minus_x: FieldElement2625([ - 53464795, 23204192, 51146355, 5075807, 65594203, 22019831, 34006363, 9160279, - 8473550, 30297594, - ]), - xy2d: FieldElement2625([ - 24900749, 14435722, 17209120, 18261891, 44516588, 9878982, 59419555, 17218610, - 42540382, 11788947, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 63990690, 22159237, 53306774, 48351872, 76761311, 26708527, 47071426, 43965164, - 42540393, 32095740, - ]), - y_minus_x: FieldElement2625([ - 51449703, 16736705, 44641714, 10215877, 58011687, 7563910, 11871841, 21049238, - 48595538, 8464117, - ]), - xy2d: FieldElement2625([ - 43708233, 8348506, 52522913, 32692717, 63158658, 27181012, 14325288, 8628612, - 33313881, 25183915, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 46921853, 28586496, 89476219, 38825978, 66011746, 28765593, 109412060, - 23317576, 58168128, 61290594, - ]), - y_minus_x: FieldElement2625([ - 60160060, 31759219, 34483180, 17533252, 32635413, 26180187, 15989196, 20716244, - 28358191, 29300528, - ]), - xy2d: FieldElement2625([ - 43547083, 30755372, 34757181, 31892468, 57961144, 10429266, 50471180, 4072015, - 61757200, 5596588, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 105981130, 30164382, 79421759, 39767609, 3117141, 49632997, 29266238, 36111653, - 68877164, 15373192, - ]), - y_minus_x: FieldElement2625([ - 59865506, 30307471, 62515396, 26001078, 66980936, 32642186, 66017961, 29049440, - 42448372, 3442909, - ]), - xy2d: FieldElement2625([ - 36898293, 5124042, 14181784, 8197961, 18964734, 21615339, 22597930, 7176455, - 48523386, 13365929, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 59231455, 32054473, 75433536, 38244510, 73370723, 34444877, 24538106, 24984246, - 57419264, 30522764, - ]), - y_minus_x: FieldElement2625([ - 25008885, 22782833, 62803832, 23916421, 16265035, 15721635, 683793, 21730648, - 15723478, 18390951, - ]), - xy2d: FieldElement2625([ - 57448220, 12374378, 40101865, 26528283, 59384749, 21239917, 11879681, 5400171, - 519526, 32318556, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 22258378, 50776631, 59239045, 14613015, 44588609, 30603508, 46754982, 40870398, - 16648396, 41160072, - ]), - y_minus_x: FieldElement2625([ - 59027556, 25089834, 58885552, 9719709, 19259459, 18206220, 23994941, 28272877, - 57640015, 4763277, - ]), - xy2d: FieldElement2625([ - 45409620, 9220968, 51378240, 1084136, 41632757, 30702041, 31088446, 25789909, - 55752334, 728111, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 26047201, 55357393, 127317403, 50587064, 91200930, 9158118, 62835319, 20998873, - 104852291, 28056158, - ]), - y_minus_x: FieldElement2625([ - 17510331, 33231575, 5854288, 8403524, 17133918, 30441820, 38997856, 12327944, - 10750447, 10014012, - ]), - xy2d: FieldElement2625([ - 56796096, 3936951, 9156313, 24656749, 16498691, 32559785, 39627812, 32887699, - 3424690, 7540221, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 97431206, 26590321, 78469868, 29411114, 74542167, 4989747, 127146306, 50791643, - 57864597, 48812477, - ]), - y_minus_x: FieldElement2625([ - 13054543, 30774935, 19155473, 469045, 54626067, 4566041, 5631406, 2711395, - 1062915, 28418087, - ]), - xy2d: FieldElement2625([ - 47868616, 22299832, 37599834, 26054466, 61273100, 13005410, 61042375, 12194496, - 32960380, 1459310, - ]), - }, - ]), - LookupTable([ - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 86960860, 40582355, 90778216, 43574797, 75695366, 26896524, 67503060, 27452546, - 85746866, 55933926, - ]), - y_minus_x: FieldElement2625([ - 31395515, 15098109, 26581030, 8030562, 50580950, 28547297, 9012485, 25970078, - 60465776, 28111795, - ]), - xy2d: FieldElement2625([ - 57916680, 31207054, 65111764, 4529533, 25766844, 607986, 67095642, 9677542, - 34813975, 27098423, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 64664330, 33404494, 96457765, 8186664, 68982624, 12489862, 103283149, 25714738, - 59256019, 58970434, - ]), - y_minus_x: FieldElement2625([ - 51872508, 18120922, 7766469, 746860, 26346930, 23332670, 39775412, 10754587, - 57677388, 5203575, - ]), - xy2d: FieldElement2625([ - 31834314, 14135496, 66338857, 5159117, 20917671, 16786336, 59640890, 26216907, - 31809242, 7347066, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 57502122, 21680191, 87523322, 46588417, 80825387, 21862550, 86906833, 21343176, - 82301739, 31466941, - ]), - y_minus_x: FieldElement2625([ - 54445282, 31372712, 1168161, 29749623, 26747876, 19416341, 10609329, 12694420, - 33473243, 20172328, - ]), - xy2d: FieldElement2625([ - 33184999, 11180355, 15832085, 22169002, 65475192, 225883, 15089336, 22530529, - 60973201, 14480052, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 98417562, 27934433, 98139703, 31657332, 82783410, 26971548, 72605071, 13685226, - 27595050, 42291707, - ]), - y_minus_x: FieldElement2625([ - 46790012, 18404192, 10933842, 17376410, 8335351, 26008410, 36100512, 20943827, - 26498113, 66511, - ]), - xy2d: FieldElement2625([ - 22644435, 24792703, 50437087, 4884561, 64003250, 19995065, 30540765, 29267685, - 53781076, 26039336, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 106199862, 9834843, 85726071, 30873119, 63706907, 53801357, 75314402, 13585436, - 117090263, 48669869, - ]), - y_minus_x: FieldElement2625([ - 23711543, 32881517, 31206560, 25191721, 6164646, 23844445, 33572981, 32128335, - 8236920, 16492939, - ]), - xy2d: FieldElement2625([ - 43198286, 20038905, 40809380, 29050590, 25005589, 25867162, 19574901, 10071562, - 6708380, 27332008, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 69210217, 28624377, 86811594, 35922006, 118790560, 34602105, 72409880, - 42883131, 29955600, 55430554, - ]), - y_minus_x: FieldElement2625([ - 3096359, 9271816, 45488000, 18032587, 52260867, 25961494, 41216721, 20918836, - 57191288, 6216607, - ]), - xy2d: FieldElement2625([ - 34493015, 338662, 41913253, 2510421, 37895298, 19734218, 24822829, 27407865, - 40341383, 7525078, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 44042196, 53123240, 83242349, 25658253, 130828162, 34333218, 66198527, - 30771936, 47722230, 45548532, - ]), - y_minus_x: FieldElement2625([ - 21691500, 19929806, 66467532, 19187410, 3285880, 30070836, 42044197, 9718257, - 59631427, 13381417, - ]), - xy2d: FieldElement2625([ - 18445390, 29352196, 14979845, 11622458, 65381754, 29971451, 23111647, 27179185, - 28535281, 15779576, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 30098034, 36644094, 124983340, 16662133, 45801924, 44862842, 53040409, - 12021729, 77064149, 17251075, - ]), - y_minus_x: FieldElement2625([ - 9734894, 18977602, 59635230, 24415696, 2060391, 11313496, 48682835, 9924398, - 20194861, 13380996, - ]), - xy2d: FieldElement2625([ - 40730762, 25589224, 44941042, 15789296, 49053522, 27385639, 65123949, 15707770, - 26342023, 10146099, - ]), - }, - ]), - LookupTable([ - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 41091971, 33334488, 88448054, 33513043, 86854119, 30675731, 37471583, 35781471, - 21612325, 33008704, - ]), - y_minus_x: FieldElement2625([ - 54031477, 1184227, 23562814, 27583990, 46757619, 27205717, 25764460, 12243797, - 46252298, 11649657, - ]), - xy2d: FieldElement2625([ - 57077370, 11262625, 27384172, 2271902, 26947504, 17556661, 39943, 6114064, - 33514190, 2333242, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 112784121, 54687041, 75228644, 40774344, 45278341, 58092729, 60429112, - 54438225, 91459440, 20104430, - ]), - y_minus_x: FieldElement2625([ - 62992557, 22282898, 43222677, 4843614, 37020525, 690622, 35572776, 23147595, - 8317859, 12352766, - ]), - xy2d: FieldElement2625([ - 18200138, 19078521, 34021104, 30857812, 43406342, 24451920, 43556767, 31266881, - 20712162, 6719373, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 26656189, 39629685, 59250307, 35440503, 105873684, 37816756, 78226393, - 29791221, 26224234, 30256974, - ]), - y_minus_x: FieldElement2625([ - 49939907, 18700334, 63713187, 17184554, 47154818, 14050419, 21728352, 9493610, - 18620611, 17125804, - ]), - xy2d: FieldElement2625([ - 53785524, 13325348, 11432106, 5964811, 18609221, 6062965, 61839393, 23828875, - 36407290, 17074774, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 43248307, 55875704, 94070219, 35195292, 34695751, 16816491, 79357372, 28313792, - 80844205, 35488493, - ]), - y_minus_x: FieldElement2625([ - 25089769, 6742589, 17081145, 20148166, 21909292, 17486451, 51972569, 29789085, - 45830866, 5473615, - ]), - xy2d: FieldElement2625([ - 31883658, 25593331, 1083431, 21982029, 22828470, 13290673, 59983779, 12469655, - 29111212, 28103418, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 91353792, 52058456, 107954750, 36345970, 52111264, 50221109, 91476329, - 39943270, 56813276, 34006814, - ]), - y_minus_x: FieldElement2625([ - 41468082, 30136590, 5217915, 16224624, 19987036, 29472163, 42872612, 27639183, - 15766061, 8407814, - ]), - xy2d: FieldElement2625([ - 46701865, 13990230, 15495425, 16395525, 5377168, 15166495, 58191841, 29165478, - 59040954, 2276717, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 30157899, 46478498, 116505677, 42800183, 87003891, 36922573, 43281276, - 38650650, 89849239, 26251014, - ]), - y_minus_x: FieldElement2625([ - 2041139, 19298082, 7783686, 13876377, 41161879, 20201972, 24051123, 13742383, - 51471265, 13295221, - ]), - xy2d: FieldElement2625([ - 33338218, 25048699, 12532112, 7977527, 9106186, 31839181, 49388668, 28941459, - 62657506, 18884987, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 47063564, 39008528, 52762315, 40001577, 28862070, 35438083, 64639597, 29412551, - 74879432, 43175028, - ]), - y_minus_x: FieldElement2625([ - 23208049, 7979712, 33071466, 8149229, 1758231, 22719437, 30945527, 31860109, - 33606523, 18786461, - ]), - xy2d: FieldElement2625([ - 1439939, 17283952, 66028874, 32760649, 4625401, 10647766, 62065063, 1220117, - 30494170, 22113633, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 62071265, 20526136, 64138304, 30492664, 82749837, 26852765, 40369837, 34480481, - 65424524, 20220784, - ]), - y_minus_x: FieldElement2625([ - 13908495, 30005160, 30919927, 27280607, 45587000, 7989038, 9021034, 9078865, - 3353509, 4033511, - ]), - xy2d: FieldElement2625([ - 37445433, 18440821, 32259990, 33209950, 24295848, 20642309, 23161162, 8839127, - 27485041, 7356032, - ]), - }, - ]), - LookupTable([ - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 76769853, 34259874, 79088928, 28184277, 65480320, 14661172, 60762722, 36179446, - 95539899, 50337029, - ]), - y_minus_x: FieldElement2625([ - 43269631, 25243016, 41163352, 7480957, 49427195, 25200248, 44562891, 14150564, - 15970762, 4099461, - ]), - xy2d: FieldElement2625([ - 29262576, 16756590, 26350592, 24760869, 8529670, 22346382, 13617292, 23617289, - 11465738, 8317062, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 41615764, 26591503, 99609063, 24135380, 44070139, 31252209, 82007500, 37402886, - 88078197, 28396915, - ]), - y_minus_x: FieldElement2625([ - 46724414, 19206718, 48772458, 13884721, 34069410, 2842113, 45498038, 29904543, - 11177094, 14989547, - ]), - xy2d: FieldElement2625([ - 42612143, 21838415, 16959895, 2278463, 12066309, 10137771, 13515641, 2581286, - 38621356, 9930239, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 49357223, 31456605, 83653163, 54099563, 118302919, 18605349, 18345766, - 53705111, 83400343, 28240393, - ]), - y_minus_x: FieldElement2625([ - 33879670, 2553287, 32678213, 9875984, 8534129, 6889387, 57432090, 6957616, - 4368891, 9788741, - ]), - xy2d: FieldElement2625([ - 16660737, 7281060, 56278106, 12911819, 20108584, 25452756, 45386327, 24941283, - 16250551, 22443329, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 47343357, 35944957, 117666696, 14161978, 69014150, 39969338, 71798447, - 10604806, 104027325, 4782745, - ]), - y_minus_x: FieldElement2625([ - 65754325, 14736940, 59741422, 20261545, 7710541, 19398842, 57127292, 4383044, - 22546403, 437323, - ]), - xy2d: FieldElement2625([ - 31665558, 21373968, 50922033, 1491338, 48740239, 3294681, 27343084, 2786261, - 36475274, 19457415, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 52641566, 32870716, 33734756, 41002983, 19294359, 14334329, 47418233, 35909750, - 47824192, 27440058, - ]), - y_minus_x: FieldElement2625([ - 15121312, 17758270, 6377019, 27523071, 56310752, 20596586, 18952176, 15496498, - 37728731, 11754227, - ]), - xy2d: FieldElement2625([ - 64471568, 20071356, 8488726, 19250536, 12728760, 31931939, 7141595, 11724556, - 22761615, 23420291, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 16918416, 11729663, 49025285, 36577418, 103201995, 53769203, 38367677, - 21327038, 32851221, 11717399, - ]), - y_minus_x: FieldElement2625([ - 11166615, 7338049, 60386341, 4531519, 37640192, 26252376, 31474878, 3483633, - 65915689, 29523600, - ]), - xy2d: FieldElement2625([ - 66923210, 9921304, 31456609, 20017994, 55095045, 13348922, 33142652, 6546660, - 47123585, 29606055, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 101757113, 44821142, 55911756, 25655328, 31703693, 37410335, 58571732, - 20721383, 36336829, 18068118, - ]), - y_minus_x: FieldElement2625([ - 49102387, 12709067, 3991746, 27075244, 45617340, 23004006, 35973516, 17504552, - 10928916, 3011958, - ]), - xy2d: FieldElement2625([ - 60151107, 17960094, 31696058, 334240, 29576716, 14796075, 36277808, 20749251, - 18008030, 10258577, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 44660220, 49210000, 74127342, 29144428, 36794597, 32352840, 65255398, 34921551, - 92236737, 6671742, - ]), - y_minus_x: FieldElement2625([ - 29701166, 19180498, 56230743, 9279287, 67091296, 13127209, 21382910, 11042292, - 25838796, 4642684, - ]), - xy2d: FieldElement2625([ - 46678630, 14955536, 42982517, 8124618, 61739576, 27563961, 30468146, 19653792, - 18423288, 4177476, - ]), - }, - ]), - ]); - -/// Odd multiples of the basepoint `[B, 3B, 5B, 7B, 9B, 11B, 13B, 15B, ..., 127B]`. -pub(crate) const AFFINE_ODD_MULTIPLES_OF_BASEPOINT: NafLookupTable8 = - NafLookupTable8([ - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 93076338, 52752828, 29566454, 37215328, 54414518, 37569218, 94653489, 21800160, - 61029707, 35602036, - ]), - y_minus_x: FieldElement2625([ - 54563134, 934261, 64385954, 3049989, 66381436, 9406985, 12720692, 5043384, - 19500929, 18085054, - ]), - xy2d: FieldElement2625([ - 58370664, 4489569, 9688441, 18769238, 10184608, 21191052, 29287918, 11864899, - 42594502, 29115885, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 82745136, 23865874, 24204772, 25642034, 67725840, 16869169, 94896463, 52336674, - 28944398, 32004408, - ]), - y_minus_x: FieldElement2625([ - 16568933, 4717097, 55552716, 32452109, 15682895, 21747389, 16354576, 21778470, - 7689661, 11199574, - ]), - xy2d: FieldElement2625([ - 30464137, 27578307, 55329429, 17883566, 23220364, 15915852, 7512774, 10017326, - 49359771, 23634074, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 77970208, 11473153, 27284546, 35535607, 37044514, 46132292, 99976748, 48069538, - 118779423, 44373810, - ]), - y_minus_x: FieldElement2625([ - 4708026, 6336745, 20377586, 9066809, 55836755, 6594695, 41455196, 12483687, - 54440373, 5581305, - ]), - xy2d: FieldElement2625([ - 19563141, 16186464, 37722007, 4097518, 10237984, 29206317, 28542349, 13850243, - 43430843, 17738489, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 72262591, 43463716, 68832610, 30776557, 97632468, 39071304, 86589715, 38784565, - 43156424, 18378665, - ]), - y_minus_x: FieldElement2625([ - 36839857, 30090922, 7665485, 10083793, 28475525, 1649722, 20654025, 16520125, - 30598449, 7715701, - ]), - xy2d: FieldElement2625([ - 28881826, 14381568, 9657904, 3680757, 46927229, 7843315, 35708204, 1370707, - 29794553, 32145132, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 44589852, 26862249, 14201701, 24808930, 43598457, 42399157, 85583074, 32192981, - 54046167, 47376308, - ]), - y_minus_x: FieldElement2625([ - 60653668, 25714560, 3374701, 28813570, 40010246, 22982724, 31655027, 26342105, - 18853321, 19333481, - ]), - xy2d: FieldElement2625([ - 4566811, 20590564, 38133974, 21313742, 59506191, 30723862, 58594505, 23123294, - 2207752, 30344648, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 41954014, 62923042, 96790006, 41423232, 60254202, 24130566, 121780363, 32891430, - 103106264, 17421994, - ]), - y_minus_x: FieldElement2625([ - 25576264, 30851218, 7349803, 21739588, 16472781, 9300885, 3844789, 15725684, - 171356, 6466918, - ]), - xy2d: FieldElement2625([ - 23103977, 13316479, 9739013, 17404951, 817874, 18515490, 8965338, 19466374, - 36393951, 16193876, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 100695917, 36735143, 64714733, 47558118, 50205389, 17283591, 84347261, 38283886, - 49034350, 9256799, - ]), - y_minus_x: FieldElement2625([ - 41926547, 29380300, 32336397, 5036987, 45872047, 11360616, 22616405, 9761698, - 47281666, 630304, - ]), - xy2d: FieldElement2625([ - 53388152, 2639452, 42871404, 26147950, 9494426, 27780403, 60554312, 17593437, - 64659607, 19263131, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 63957664, 28508356, 76391577, 40420576, 102310665, 32691407, 48168288, 15033783, - 92213982, 25659555, - ]), - y_minus_x: FieldElement2625([ - 42782475, 15950225, 35307649, 18961608, 55446126, 28463506, 1573891, 30928545, - 2198789, 17749813, - ]), - xy2d: FieldElement2625([ - 64009494, 10324966, 64867251, 7453182, 61661885, 30818928, 53296841, 17317989, - 34647629, 21263748, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 17735022, 27114469, 76149336, 40765111, 43325570, 26153544, 26948151, 45905235, - 38656900, 62179684, - ]), - y_minus_x: FieldElement2625([ - 2154119, 14782993, 28737794, 11906199, 36205504, 26488101, 19338132, 16910143, - 50209922, 29794297, - ]), - xy2d: FieldElement2625([ - 29935700, 6336041, 20999566, 30405369, 13628497, 24612108, 61639745, 22359641, - 56973806, 18684690, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 29792811, 31379227, 113441390, 20675662, 58452680, 54138549, 42892249, 32958636, - 31674345, 24275271, - ]), - y_minus_x: FieldElement2625([ - 7606599, 22131225, 17376912, 15235046, 32822971, 7512882, 30227203, 14344178, - 9952094, 8804749, - ]), - xy2d: FieldElement2625([ - 32575079, 3961822, 36404898, 17773250, 67073898, 1319543, 30641032, 7823672, - 63309858, 18878784, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 77823924, 52933642, 26572931, 18690221, 109143683, 23989794, 79129572, 53326100, - 38888709, 55889506, - ]), - y_minus_x: FieldElement2625([ - 37146997, 554126, 63326061, 20925660, 49205290, 8620615, 53375504, 25938867, - 8752612, 31225894, - ]), - xy2d: FieldElement2625([ - 4529887, 12416158, 60388162, 30157900, 15427957, 27628808, 61150927, 12724463, - 23658330, 23690055, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 102043267, 54823614, 45810225, 19657305, 54297192, 7413280, 66851983, 39718512, - 25005048, 18002658, - ]), - y_minus_x: FieldElement2625([ - 5403481, 24654166, 61855580, 13522652, 14989680, 1879017, 43913069, 25724172, - 20315901, 421248, - ]), - xy2d: FieldElement2625([ - 34818947, 1705239, 25347020, 7938434, 51632025, 1720023, 54809726, 32655885, - 64907986, 5517607, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 88543525, 16557377, 80359887, 30047148, 91602876, 27723948, 62710290, 52707861, - 7715736, 61648232, - ]), - y_minus_x: FieldElement2625([ - 14461032, 6393639, 22681353, 14533514, 52493587, 3544717, 57780998, 24657863, - 59891807, 31628125, - ]), - xy2d: FieldElement2625([ - 60864886, 31199953, 18524951, 11247802, 43517645, 21165456, 26204394, 27268421, - 63221077, 29979135, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 97491378, 10077555, 94805128, 42472719, 30231379, 17961119, 76201413, 41182329, - 41405214, 31798052, - ]), - y_minus_x: FieldElement2625([ - 13670592, 720327, 7131696, 19360499, 66651570, 16947532, 3061924, 22871019, - 39814495, 20141336, - ]), - xy2d: FieldElement2625([ - 44847187, 28379568, 38472030, 23697331, 49441718, 3215393, 1669253, 30451034, - 62323912, 29368533, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 74923758, 35244493, 27222384, 30715870, 48444195, 28125622, 116052444, 32330148, - 92609232, 35372537, - ]), - y_minus_x: FieldElement2625([ - 39340596, 15199968, 52787715, 18781603, 18787729, 5464578, 11652644, 8722118, - 57056621, 5153960, - ]), - xy2d: FieldElement2625([ - 5733861, 14534448, 59480402, 15892910, 30737296, 188529, 491756, 17646733, - 33071791, 15771063, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 85239571, 21331573, 119690709, 30172286, 44350959, 55826224, 68258766, 16209406, - 20222151, 32139086, - ]), - y_minus_x: FieldElement2625([ - 52372801, 13847470, 52690845, 3802477, 48387139, 10595589, 13745896, 3112846, - 50361463, 2761905, - ]), - xy2d: FieldElement2625([ - 45982696, 12273933, 15897066, 704320, 31367969, 3120352, 11710867, 16405685, - 19410991, 10591627, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 82008850, 34439758, 89319886, 49124188, 34309215, 29866047, 80308709, 27738519, - 71739865, 46909287, - ]), - y_minus_x: FieldElement2625([ - 36631997, 23300851, 59535242, 27474493, 59924914, 29067704, 17551261, 13583017, - 37580567, 31071178, - ]), - xy2d: FieldElement2625([ - 22641770, 21277083, 10843473, 1582748, 37504588, 634914, 15612385, 18139122, - 59415250, 22563863, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 76721854, 52814714, 41722368, 35285867, 53022548, 38255176, 93163883, 27627617, - 87963092, 33729456, - ]), - y_minus_x: FieldElement2625([ - 61915349, 11733561, 59403492, 31381562, 29521830, 16845409, 54973419, 26057054, - 49464700, 796779, - ]), - xy2d: FieldElement2625([ - 3855018, 8248512, 12652406, 88331, 2948262, 971326, 15614761, 9441028, 29507685, - 8583792, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 76968870, 14808584, 76708906, 57649718, 23400175, 24077237, 63783137, 37471119, - 56750251, 30681804, - ]), - y_minus_x: FieldElement2625([ - 33709664, 3740344, 52888604, 25059045, 46197996, 22678812, 45207164, 6431243, - 21300862, 27646257, - ]), - xy2d: FieldElement2625([ - 49811511, 9216232, 25043921, 18738174, 29145960, 3024227, 65580502, 530149, - 66809973, 22275500, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 23499366, 24936714, 38355445, 35908587, 82540167, 39280880, 46809413, 41143783, - 72530804, 49676198, - ]), - y_minus_x: FieldElement2625([ - 45162189, 23851397, 9380591, 15192763, 36034862, 15525765, 5277811, 25040629, - 33286237, 31693326, - ]), - xy2d: FieldElement2625([ - 62424427, 13336013, 49368582, 1581264, 30884213, 15048226, 66823504, 4736577, - 53805192, 29608355, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 25190215, 26304748, 58928336, 42665707, 64280342, 38580230, 61299598, 20659504, - 30387592, 32519377, - ]), - y_minus_x: FieldElement2625([ - 14480213, 17057820, 2286692, 32980967, 14693157, 22197912, 49247898, 9909859, - 236428, 16857435, - ]), - xy2d: FieldElement2625([ - 7877514, 29872867, 45886243, 25902853, 41998762, 6241604, 35694938, 15657879, - 56797932, 8609105, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 54245189, 32562161, 57887697, 19509733, 45323534, 37472546, 27606727, 59528498, - 74398957, 44973176, - ]), - y_minus_x: FieldElement2625([ - 28964163, 20950093, 44929966, 26145892, 34786807, 18058153, 18187179, 27016486, - 42438836, 14869174, - ]), - xy2d: FieldElement2625([ - 55703901, 1222455, 64329400, 24533246, 11330890, 9135834, 3589529, 19555234, - 53275553, 1207212, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 33323313, 35603165, 79328585, 6017848, 71286345, 23804207, 86644124, 44008367, - 55775078, 31816581, - ]), - y_minus_x: FieldElement2625([ - 64814718, 27217688, 29891310, 4504619, 8548709, 21986323, 62140656, 12555980, - 34377058, 21436823, - ]), - xy2d: FieldElement2625([ - 49069441, 9880212, 33350825, 24576421, 24446077, 15616561, 19302117, 9370836, - 55172180, 28526191, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 95404934, 26757208, 123864063, 4572839, 69249194, 43584425, 53559055, 41742046, - 41167331, 24643278, - ]), - y_minus_x: FieldElement2625([ - 35101859, 30958612, 66105296, 3168612, 22836264, 10055966, 22893634, 13045780, - 28576558, 30704591, - ]), - xy2d: FieldElement2625([ - 59987873, 21166324, 43296694, 15387892, 39447987, 19996270, 5059183, 19972934, - 30207804, 29631666, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 67444156, 16132892, 88330413, 37924284, 68147855, 57949418, 91481571, 24889160, - 62329722, 50712214, - ]), - y_minus_x: FieldElement2625([ - 56922508, 1347520, 23300731, 27393371, 42651667, 8512932, 27610931, 24436993, - 3998295, 3835244, - ]), - xy2d: FieldElement2625([ - 16327050, 22776956, 14746360, 22599650, 23700920, 11727222, 25900154, 21823218, - 34907363, 25105813, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 59807886, 12089757, 115624210, 41476837, 67589715, 26361580, 71355762, 44268661, - 67753061, 13128476, - ]), - y_minus_x: FieldElement2625([ - 7174885, 26592113, 59892333, 6465478, 4145835, 17673606, 38764952, 22293290, - 1360980, 25805937, - ]), - xy2d: FieldElement2625([ - 40179568, 6331649, 42386021, 20205884, 15635073, 6103612, 56391180, 6789942, - 7597240, 24095312, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 54776568, 36935932, 18757261, 41429535, 67215081, 34700142, 86560976, 61204154, - 26496794, 19612129, - ]), - y_minus_x: FieldElement2625([ - 46701540, 24101444, 49515651, 25946994, 45338156, 9941093, 55509371, 31298943, - 1347425, 15381335, - ]), - xy2d: FieldElement2625([ - 53576449, 26135856, 17092785, 3684747, 57829121, 27109516, 2987881, 10987137, - 52269096, 15465522, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 80033010, 26264316, 72380996, 10039544, 94605936, 30615493, 60406855, 30400829, - 120765849, 45301372, - ]), - y_minus_x: FieldElement2625([ - 35668062, 24246990, 47788280, 25128298, 37456967, 19518969, 43459670, 10724644, - 7294162, 4471290, - ]), - xy2d: FieldElement2625([ - 33813988, 3549109, 101112, 21464449, 4858392, 3029943, 59999440, 21424738, - 34313875, 1512799, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 29494960, 28240930, 51093230, 28823678, 92791151, 54796794, 77571888, 37795542, - 75765856, 10649531, - ]), - y_minus_x: FieldElement2625([ - 63536751, 7572551, 62249759, 25202639, 32046232, 32318941, 29315141, 15424555, - 24706712, 28857648, - ]), - xy2d: FieldElement2625([ - 47618751, 5819839, 19528172, 20715950, 40655763, 20611047, 4960954, 6496879, - 2790858, 28045273, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 85174457, 55843901, 111946683, 31021158, 32797785, 48944265, 78338887, 31144772, - 82688001, 38470222, - ]), - y_minus_x: FieldElement2625([ - 49664705, 3638040, 57888693, 19234931, 40104182, 28143840, 28667142, 18386877, - 18584835, 3592929, - ]), - xy2d: FieldElement2625([ - 12065039, 18867394, 6430594, 17107159, 1727094, 13096957, 61520237, 27056604, - 27026997, 13543966, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 68512926, 37577278, 94695528, 14209106, 95849194, 30038709, 51818051, 20241476, - 68980056, 42251074, - ]), - y_minus_x: FieldElement2625([ - 17325298, 33376175, 65271265, 4931225, 31708266, 6292284, 23064744, 22072792, - 43945505, 9236924, - ]), - xy2d: FieldElement2625([ - 51955585, 20268063, 61151838, 26383348, 4766519, 20788033, 21173534, 27030753, - 9509140, 7790046, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 24124086, 38918775, 28620390, 10538620, 59433851, 19581010, 60862718, 43500219, - 77600721, 32213801, - ]), - y_minus_x: FieldElement2625([ - 7062127, 13930079, 2259902, 6463144, 32137099, 24748848, 41557343, 29331342, - 47345194, 13022814, - ]), - xy2d: FieldElement2625([ - 18921826, 392002, 55817981, 6420686, 8000611, 22415972, 14722962, 26246290, - 20604450, 8079345, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 67710253, 26257798, 51499391, 46550521, 30228769, 53940987, 76234206, 43362242, - 77953697, 21034392, - ]), - y_minus_x: FieldElement2625([ - 25817710, 8020883, 50134679, 21244805, 47057788, 8766556, 29308546, 22307963, - 49449920, 23874253, - ]), - xy2d: FieldElement2625([ - 11081015, 13522660, 12474691, 29260223, 48687631, 9341946, 16850694, 18637605, - 6199839, 14303642, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 64518173, 19894035, 117213833, 43031641, 79641718, 39533880, 66531934, 41205092, - 117735515, 13989682, - ]), - y_minus_x: FieldElement2625([ - 6921800, 4421166, 59739491, 30510778, 43106355, 30941531, 9363541, 3394240, - 50874187, 23872585, - ]), - xy2d: FieldElement2625([ - 54293979, 23466866, 47184247, 20627378, 8313211, 5865878, 5948507, 32290343, - 52583140, 23139870, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 111574723, 24134616, 49842442, 23485580, 34844037, 45228427, 67103167, 25858409, - 38508586, 35097070, - ]), - y_minus_x: FieldElement2625([ - 19879846, 15259900, 25020018, 14261729, 22075205, 25189303, 787540, 31325033, - 62422289, 16131171, - ]), - xy2d: FieldElement2625([ - 39487053, 27893575, 34654176, 25620816, 60209846, 23603919, 8931189, 12275052, - 38626469, 33438928, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 105416367, 9568747, 62672739, 49685015, 106242995, 4547918, 18403901, 38581738, - 60829966, 33150322, - ]), - y_minus_x: FieldElement2625([ - 7950033, 25841033, 47276506, 3884935, 62418883, 2342083, 50269031, 14194015, - 27013685, 3320257, - ]), - xy2d: FieldElement2625([ - 35270691, 18076829, 46994271, 4273335, 43595882, 31742297, 58328702, 4594760, - 49180851, 18144010, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 30194115, 50068680, 49746331, 27470090, 40428285, 23271051, 70252167, 16153483, - 123511881, 27809602, - ]), - y_minus_x: FieldElement2625([ - 27113466, 6865046, 4512771, 29327742, 29021084, 7405965, 33302911, 9322435, - 4307527, 32438240, - ]), - xy2d: FieldElement2625([ - 29337813, 24673346, 10359233, 30347534, 57709483, 9930840, 60607771, 24076133, - 20985293, 22480923, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 14579237, 33467236, 85745988, 15769997, 101228358, 21649866, 82685456, 59023858, - 86175344, 24337101, - ]), - y_minus_x: FieldElement2625([ - 4472119, 14702190, 10432042, 22460027, 708461, 18783996, 34234374, 30870323, - 63796457, 10370850, - ]), - xy2d: FieldElement2625([ - 36957127, 19555637, 16244231, 24367549, 58999881, 13440043, 35147632, 8718974, - 43101064, 18487380, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 21818223, 34477173, 23913863, 22441963, 129271975, 14842154, 43035020, 9485973, - 53819529, 22318987, - ]), - y_minus_x: FieldElement2625([ - 10874834, 4351765, 66252340, 17269436, 64427034, 30735311, 5883785, 28998531, - 44403022, 26064601, - ]), - xy2d: FieldElement2625([ - 64017630, 9755550, 37507935, 22752543, 4031638, 29903925, 47267417, 32706846, - 39147952, 21635901, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 81365001, 44927611, 97395185, 43985591, 66242539, 38517499, 52937891, 37374973, - 73352483, 38476849, - ]), - y_minus_x: FieldElement2625([ - 43460763, 24260930, 21493330, 30888969, 23329454, 24545577, 58286855, 12750266, - 22391140, 26198125, - ]), - xy2d: FieldElement2625([ - 20477567, 24078713, 1674568, 4102219, 25208396, 13972305, 30389482, 19572626, - 1485666, 17679765, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 100511110, 23887606, 116505658, 30877106, 45483774, 25222431, 67931340, 37154158, - 32618865, 18610785, - ]), - y_minus_x: FieldElement2625([ - 48647066, 166413, 55454758, 8889513, 21027475, 32728181, 43100067, 4690060, - 7520989, 16421303, - ]), - xy2d: FieldElement2625([ - 14868391, 20996450, 64836606, 1042490, 27060176, 10253541, 53431276, 19516737, - 41808946, 2239538, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 50228416, 29594943, 62030348, 10307368, 70970997, 20292574, 126292474, 51543890, - 67827181, 15848795, - ]), - y_minus_x: FieldElement2625([ - 5548701, 17911007, 33137864, 32764443, 31146554, 17931096, 64023370, 7290289, - 6361313, 32861205, - ]), - xy2d: FieldElement2625([ - 63374742, 30320053, 4091667, 30955480, 44819449, 2212055, 52638826, 22391938, - 38484599, 7051029, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 50485560, 7033600, 57711425, 10740562, 72347547, 42328739, 7593987, 46950560, - 85560721, 41970063, - ]), - y_minus_x: FieldElement2625([ - 40930651, 3776911, 39108529, 2508077, 19371703, 7626128, 4092943, 15778278, - 42044145, 24540103, - ]), - xy2d: FieldElement2625([ - 44128555, 8867576, 8645499, 22222278, 11497130, 4344907, 10788462, 23382703, - 3547104, 15368835, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 81786515, 51902785, 74560130, 22753403, 52379722, 41395524, 57994925, 6818020, - 57707296, 16352835, - ]), - y_minus_x: FieldElement2625([ - 21622574, 18581624, 36511951, 1212467, 36930308, 7910192, 20622927, 2438677, - 52628762, 29068327, - ]), - xy2d: FieldElement2625([ - 6797431, 2854059, 4269865, 8037366, 32016522, 15223213, 34765784, 15297582, - 3559197, 26425254, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 107761639, 61759660, 79235166, 8794359, 48418924, 60111631, 87862210, 33613219, - 68436482, 40229362, - ]), - y_minus_x: FieldElement2625([ - 52388944, 32880897, 37676257, 8253690, 32826330, 2707379, 25088512, 17182878, - 15053907, 11601568, - ]), - xy2d: FieldElement2625([ - 43894091, 25425955, 50962615, 28097648, 30129084, 13258436, 39364589, 8197601, - 58181660, 15003422, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 13470722, 47835674, 31012390, 30525035, 89789519, 50713267, 39648035, 13815677, - 94028755, 62582101, - ]), - y_minus_x: FieldElement2625([ - 54478677, 14782829, 56712503, 7094748, 41775828, 29409658, 9084386, 30179063, - 64014926, 32519086, - ]), - xy2d: FieldElement2625([ - 6314429, 20018828, 12535891, 19610611, 10074031, 28087963, 50489447, 26314252, - 24553876, 32746308, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 105768482, 46629424, 103418946, 65789027, 85765355, 28316167, 56299027, 22780838, - 122676432, 32376204, - ]), - y_minus_x: FieldElement2625([ - 5654403, 26425050, 39347935, 963424, 5032477, 19850195, 30011537, 11153401, - 63182039, 13343989, - ]), - xy2d: FieldElement2625([ - 1130444, 29814849, 40569426, 8144467, 24179188, 6267924, 63847147, 2912740, - 63870704, 29186744, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 49722534, 11073633, 52865263, 50829611, 33921405, 38614719, 32360242, 35465390, - 50107050, 45035301, - ]), - y_minus_x: FieldElement2625([ - 2003571, 2472803, 46902183, 1716406, 58609069, 15922982, 43766122, 27456369, - 33468339, 29346282, - ]), - xy2d: FieldElement2625([ - 18834217, 8245144, 29896065, 3490830, 62967493, 7220277, 146130, 18459164, - 57533060, 30070422, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 77805507, 38474121, 73459597, 18553340, 107508318, 52705654, 33655873, 27331956, - 44498407, 13768350, - ]), - y_minus_x: FieldElement2625([ - 23652128, 27647291, 43351590, 13262712, 65238054, 26296349, 11902126, 2949002, - 34445239, 25602117, - ]), - xy2d: FieldElement2625([ - 55906958, 19046111, 28501158, 28224561, 14495533, 14714956, 32929972, 2643566, - 17034893, 11645825, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 38181639, 29751709, 73650473, 17760526, 80753587, 17992258, 72670209, 41214427, - 87524152, 37630124, - ]), - y_minus_x: FieldElement2625([ - 6498441, 12053607, 10375600, 14764370, 24795955, 16159258, 57849421, 16071837, - 31008329, 3792564, - ]), - xy2d: FieldElement2625([ - 47930485, 9176956, 54248931, 8732776, 58000258, 10333519, 96092, 29273884, - 13051277, 20121493, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 54190492, 49837594, 61282066, 10734597, 67926686, 36967416, 115462142, 30339271, - 37200685, 30036936, - ]), - y_minus_x: FieldElement2625([ - 21193614, 19929501, 18841215, 29565554, 64002173, 11123558, 14111648, 6069945, - 30307604, 25935103, - ]), - xy2d: FieldElement2625([ - 58539773, 2098685, 38301131, 15844175, 41633654, 16934366, 15145895, 5543861, - 64050790, 6595361, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 34107945, 34731353, 51956038, 5614778, 79079051, 30288154, 47460410, 22186730, - 30689695, 19628976, - ]), - y_minus_x: FieldElement2625([ - 25043248, 19224237, 46048097, 32289319, 29339134, 12397721, 37385860, 12978240, - 57951631, 31419653, - ]), - xy2d: FieldElement2625([ - 46038439, 28501736, 62566522, 12609283, 35236982, 30457796, 64113609, 14800343, - 6412849, 6276813, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 124528774, 39505727, 83050803, 41361190, 116071796, 37845759, 61633481, 38385016, - 71255100, 31629488, - ]), - y_minus_x: FieldElement2625([ - 249426, 17196749, 35434953, 13884216, 11701636, 24553269, 51821986, 12900910, - 34844073, 16150118, - ]), - xy2d: FieldElement2625([ - 2520516, 14697628, 15319213, 22684490, 62866663, 29666431, 13872507, 7473319, - 12419515, 2958466, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 101517167, 22298305, 98222207, 59471046, 61547444, 50370568, 97111094, 42539051, - 14298448, 49873561, - ]), - y_minus_x: FieldElement2625([ - 19427905, 12004555, 9971383, 28189868, 32306269, 23648270, 34176633, 10760437, - 53354280, 5634974, - ]), - xy2d: FieldElement2625([ - 30044319, 23677863, 60273406, 14563839, 9734978, 19808149, 30899064, 30835691, - 22828539, 23633348, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 25513026, 37111929, 37113703, 29589233, 77394412, 34745965, 95889446, 61766763, - 92876242, 37566563, - ]), - y_minus_x: FieldElement2625([ - 42139852, 9176396, 16274786, 33467453, 52558621, 7190768, 1490604, 31312359, - 44767199, 18491072, - ]), - xy2d: FieldElement2625([ - 4272877, 21431483, 45594743, 13027605, 59232641, 24151956, 38390319, 12906718, - 45915869, 15503563, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 29874396, 35808736, 25494239, 37976524, 43036007, 37144111, 18198811, 35141252, - 53490316, 47742788, - ]), - y_minus_x: FieldElement2625([ - 59518553, 28520621, 59946871, 29462027, 3630300, 29398589, 60425462, 24588735, - 53129947, 28399367, - ]), - xy2d: FieldElement2625([ - 18192774, 12787801, 32021061, 9158184, 48389348, 16385092, 11799402, 9492011, - 43154220, 15950102, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 68768204, 54638026, 33464925, 53430209, 66037964, 35360373, 22565155, 39168685, - 46605438, 51897954, - ]), - y_minus_x: FieldElement2625([ - 57660336, 29715319, 64414626, 32753338, 16894121, 935644, 53848937, 22684138, - 10541713, 14174330, - ]), - xy2d: FieldElement2625([ - 22888141, 12700209, 40301697, 6435658, 56329485, 5524686, 56715961, 6520808, - 15754965, 9355803, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 79549820, 26746924, 54931884, 38547877, 49672847, 19708985, 52599424, 12757151, - 93328625, 39524327, - ]), - y_minus_x: FieldElement2625([ - 33888606, 13911610, 18921581, 1162763, 46616901, 13799218, 29525142, 21929286, - 59295464, 503508, - ]), - xy2d: FieldElement2625([ - 57865531, 22043577, 17998312, 3038439, 52838371, 9832208, 43311531, 660991, - 25265267, 18977724, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 64010269, 23727746, 42277281, 48089313, 102316973, 34946803, 127880577, 38411468, - 114816699, 43712746, - ]), - y_minus_x: FieldElement2625([ - 56859315, 32558245, 41017090, 22610758, 13704990, 23215119, 2475037, 32344984, - 12799418, 11135856, - ]), - xy2d: FieldElement2625([ - 1867214, 27167702, 19772099, 16925005, 15366693, 25797692, 10829276, 15372827, - 26582557, 31642714, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 57265197, 20059797, 107314987, 30587501, 60553812, 25602102, 29690666, 37127097, - 103070929, 51772159, - ]), - y_minus_x: FieldElement2625([ - 56432653, 6329655, 42770975, 4187982, 30677076, 9335071, 60103332, 14755050, - 9451294, 574767, - ]), - xy2d: FieldElement2625([ - 52859018, 2867107, 56258365, 15719081, 5959372, 8703738, 29137781, 21575537, - 20249840, 31808689, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 74749335, 47235127, 9995910, 52200224, 92069015, 8964515, 33248715, 21201554, - 57573145, 31605506, - ]), - y_minus_x: FieldElement2625([ - 56307055, 23891752, 3613811, 30787942, 49031222, 26667524, 26985478, 31973510, - 26785294, 29587427, - ]), - xy2d: FieldElement2625([ - 30891460, 5254655, 47414930, 12769216, 42912782, 11830405, 7411958, 1394027, - 18778535, 18209370, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 61227949, 26179350, 57501473, 13585864, 102855675, 40344975, 54134826, 59707765, - 74122694, 12256219, - ]), - y_minus_x: FieldElement2625([ - 5975515, 16302413, 24341148, 28270615, 18786096, 22405501, 28243950, 28328004, - 53412289, 4381960, - ]), - xy2d: FieldElement2625([ - 9394648, 8758552, 26189703, 16642536, 35993528, 5117040, 5977877, 13955594, - 19244020, 24493735, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 111388362, 51822507, 30193028, 3993472, 110736308, 44014764, 107346699, 48464072, - 92830877, 56442511, - ]), - y_minus_x: FieldElement2625([ - 7236795, 30433657, 63588571, 620817, 11118384, 24979014, 66780154, 19877679, - 16217590, 26311105, - ]), - xy2d: FieldElement2625([ - 42540794, 21657271, 16455973, 23630199, 3992015, 21894417, 44876052, 19291718, - 55429803, 30442389, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement2625([ - 69421833, 26972132, 58859271, 20240912, 119664007, 29643940, 93968457, 34515112, - 110902491, 44996669, - ]), - y_minus_x: FieldElement2625([ - 3428668, 27807272, 41139948, 24786894, 4167808, 21423270, 52199622, 8021269, - 53172251, 18070808, - ]), - xy2d: FieldElement2625([ - 30631113, 26363656, 21279866, 23275794, 18311406, 466071, 42527968, 7989982, - 29641567, 29446694, - ]), - }, - ]); diff --git a/net/gurk-rs/files/vendor/curve25519-dalek/src/backend/serial/u32/field.rs b/net/gurk-rs/files/vendor/curve25519-dalek/src/backend/serial/u32/field.rs deleted file mode 100644 index c8f3e5e..0000000 --- a/net/gurk-rs/files/vendor/curve25519-dalek/src/backend/serial/u32/field.rs +++ /dev/null @@ -1,578 +0,0 @@ -// -*- mode: rust; -*- -// -// This file is part of curve25519-dalek. -// Copyright (c) 2016-2021 isis lovecruft -// Copyright (c) 2016-2019 Henry de Valence -// See LICENSE for licensing information. -// -// Authors: -// - isis agora lovecruft -// - Henry de Valence - -//! Field arithmetic modulo \\(p = 2\^{255} - 19\\), using \\(32\\)-bit -//! limbs with \\(64\\)-bit products. -//! -//! This code was originally derived from Adam Langley's Golang ed25519 -//! implementation, and was then rewritten to use unsigned limbs instead -//! of signed limbs. - -use core::fmt::Debug; -use core::ops::Neg; -use core::ops::{Add, AddAssign}; -use core::ops::{Mul, MulAssign}; -use core::ops::{Sub, SubAssign}; - -use subtle::Choice; -use subtle::ConditionallySelectable; - -use zeroize::Zeroize; - -/// A `FieldElement2625` represents an element of the field -/// \\( \mathbb Z / (2\^{255} - 19)\\). -/// -/// In the 32-bit implementation, a `FieldElement` is represented in -/// radix \\(2\^{25.5}\\) as ten `u32`s. This means that a field -/// element \\(x\\) is represented as -/// $$ -/// x = \sum\_{i=0}\^9 x\_i 2\^{\lceil i \frac {51} 2 \rceil} -/// = x\_0 + x\_1 2\^{26} + x\_2 2\^{51} + x\_3 2\^{77} + \cdots + x\_9 2\^{230}; -/// $$ -/// the coefficients are alternately bounded by \\(2\^{25}\\) and -/// \\(2\^{26}\\). The limbs are allowed to grow between reductions up -/// to \\(2\^{25+b}\\) or \\(2\^{26+b}\\), where \\(b = 1.75\\). -/// -/// # Note -/// -/// The `curve25519_dalek::field` module provides a type alias -/// `curve25519_dalek::field::FieldElement` to either `FieldElement51` -/// or `FieldElement2625`. -/// -/// The backend-specific type `FieldElement2625` should not be used -/// outside of the `curve25519_dalek::field` module. -#[derive(Copy, Clone)] -pub struct FieldElement2625(pub (crate) [u32; 10]); - -impl Debug for FieldElement2625 { - fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { - write!(f, "FieldElement2625({:?})", &self.0[..]) - } -} - -impl Zeroize for FieldElement2625 { - fn zeroize(&mut self) { - self.0.zeroize(); - } -} - -impl<'b> AddAssign<&'b FieldElement2625> for FieldElement2625 { - fn add_assign(&mut self, _rhs: &'b FieldElement2625) { - for i in 0..10 { - self.0[i] += _rhs.0[i]; - } - } -} - -impl<'a, 'b> Add<&'b FieldElement2625> for &'a FieldElement2625 { - type Output = FieldElement2625; - fn add(self, _rhs: &'b FieldElement2625) -> FieldElement2625 { - let mut output = *self; - output += _rhs; - output - } -} - -impl<'b> SubAssign<&'b FieldElement2625> for FieldElement2625 { - fn sub_assign(&mut self, _rhs: &'b FieldElement2625) { - // See comment in FieldElement51::Sub - // - // Compute a - b as ((a + 2^4 * p) - b) to avoid underflow. - let b = &_rhs.0; - self.0 = FieldElement2625::reduce([ - ((self.0[0] + (0x3ffffed << 4)) - b[0]) as u64, - ((self.0[1] + (0x1ffffff << 4)) - b[1]) as u64, - ((self.0[2] + (0x3ffffff << 4)) - b[2]) as u64, - ((self.0[3] + (0x1ffffff << 4)) - b[3]) as u64, - ((self.0[4] + (0x3ffffff << 4)) - b[4]) as u64, - ((self.0[5] + (0x1ffffff << 4)) - b[5]) as u64, - ((self.0[6] + (0x3ffffff << 4)) - b[6]) as u64, - ((self.0[7] + (0x1ffffff << 4)) - b[7]) as u64, - ((self.0[8] + (0x3ffffff << 4)) - b[8]) as u64, - ((self.0[9] + (0x1ffffff << 4)) - b[9]) as u64, - ]).0; - } -} - -impl<'a, 'b> Sub<&'b FieldElement2625> for &'a FieldElement2625 { - type Output = FieldElement2625; - fn sub(self, _rhs: &'b FieldElement2625) -> FieldElement2625 { - let mut output = *self; - output -= _rhs; - output - } -} - -impl<'b> MulAssign<&'b FieldElement2625> for FieldElement2625 { - fn mul_assign(&mut self, _rhs: &'b FieldElement2625) { - let result = (self as &FieldElement2625) * _rhs; - self.0 = result.0; - } -} - -impl<'a, 'b> Mul<&'b FieldElement2625> for &'a FieldElement2625 { - type Output = FieldElement2625; - fn mul(self, _rhs: &'b FieldElement2625) -> FieldElement2625 { - /// Helper function to multiply two 32-bit integers with 64 bits - /// of output. - #[inline(always)] - fn m(x: u32, y: u32) -> u64 { (x as u64) * (y as u64) } - - // Alias self, _rhs for more readable formulas - let x: &[u32;10] = &self.0; let y: &[u32;10] = &_rhs.0; - - // We assume that the input limbs x[i], y[i] are bounded by: - // - // x[i], y[i] < 2^(26 + b) if i even - // x[i], y[i] < 2^(25 + b) if i odd - // - // where b is a (real) parameter representing the excess bits of - // the limbs. We track the bitsizes of all variables through - // the computation and solve at the end for the allowable - // headroom bitsize b (which determines how many additions we - // can perform between reductions or multiplications). - - let y1_19 = 19 * y[1]; // This fits in a u32 - let y2_19 = 19 * y[2]; // iff 26 + b + lg(19) < 32 - let y3_19 = 19 * y[3]; // if b < 32 - 26 - 4.248 = 1.752 - let y4_19 = 19 * y[4]; - let y5_19 = 19 * y[5]; // below, b<2.5: this is a bottleneck, - let y6_19 = 19 * y[6]; // could be avoided by promoting to - let y7_19 = 19 * y[7]; // u64 here instead of in m() - let y8_19 = 19 * y[8]; - let y9_19 = 19 * y[9]; - - // What happens when we multiply x[i] with y[j] and place the - // result into the (i+j)-th limb? - // - // x[i] represents the value x[i]*2^ceil(i*51/2) - // y[j] represents the value y[j]*2^ceil(j*51/2) - // z[i+j] represents the value z[i+j]*2^ceil((i+j)*51/2) - // x[i]*y[j] represents the value x[i]*y[i]*2^(ceil(i*51/2)+ceil(j*51/2)) - // - // Since the radix is already accounted for, the result placed - // into the (i+j)-th limb should be - // - // x[i]*y[i]*2^(ceil(i*51/2)+ceil(j*51/2) - ceil((i+j)*51/2)). - // - // The value of ceil(i*51/2)+ceil(j*51/2) - ceil((i+j)*51/2) is - // 1 when both i and j are odd, and 0 otherwise. So we add - // - // x[i]*y[j] if either i or j is even - // 2*x[i]*y[j] if i and j are both odd - // - // by using precomputed multiples of x[i] for odd i: - - let x1_2 = 2 * x[1]; // This fits in a u32 iff 25 + b + 1 < 32 - let x3_2 = 2 * x[3]; // iff b < 6 - let x5_2 = 2 * x[5]; - let x7_2 = 2 * x[7]; - let x9_2 = 2 * x[9]; - - let z0 = m(x[0],y[0]) + m(x1_2,y9_19) + m(x[2],y8_19) + m(x3_2,y7_19) + m(x[4],y6_19) + m(x5_2,y5_19) + m(x[6],y4_19) + m(x7_2,y3_19) + m(x[8],y2_19) + m(x9_2,y1_19); - let z1 = m(x[0],y[1]) + m(x[1],y[0]) + m(x[2],y9_19) + m(x[3],y8_19) + m(x[4],y7_19) + m(x[5],y6_19) + m(x[6],y5_19) + m(x[7],y4_19) + m(x[8],y3_19) + m(x[9],y2_19); - let z2 = m(x[0],y[2]) + m(x1_2,y[1]) + m(x[2],y[0]) + m(x3_2,y9_19) + m(x[4],y8_19) + m(x5_2,y7_19) + m(x[6],y6_19) + m(x7_2,y5_19) + m(x[8],y4_19) + m(x9_2,y3_19); - let z3 = m(x[0],y[3]) + m(x[1],y[2]) + m(x[2],y[1]) + m(x[3],y[0]) + m(x[4],y9_19) + m(x[5],y8_19) + m(x[6],y7_19) + m(x[7],y6_19) + m(x[8],y5_19) + m(x[9],y4_19); - let z4 = m(x[0],y[4]) + m(x1_2,y[3]) + m(x[2],y[2]) + m(x3_2,y[1]) + m(x[4],y[0]) + m(x5_2,y9_19) + m(x[6],y8_19) + m(x7_2,y7_19) + m(x[8],y6_19) + m(x9_2,y5_19); - let z5 = m(x[0],y[5]) + m(x[1],y[4]) + m(x[2],y[3]) + m(x[3],y[2]) + m(x[4],y[1]) + m(x[5],y[0]) + m(x[6],y9_19) + m(x[7],y8_19) + m(x[8],y7_19) + m(x[9],y6_19); - let z6 = m(x[0],y[6]) + m(x1_2,y[5]) + m(x[2],y[4]) + m(x3_2,y[3]) + m(x[4],y[2]) + m(x5_2,y[1]) + m(x[6],y[0]) + m(x7_2,y9_19) + m(x[8],y8_19) + m(x9_2,y7_19); - let z7 = m(x[0],y[7]) + m(x[1],y[6]) + m(x[2],y[5]) + m(x[3],y[4]) + m(x[4],y[3]) + m(x[5],y[2]) + m(x[6],y[1]) + m(x[7],y[0]) + m(x[8],y9_19) + m(x[9],y8_19); - let z8 = m(x[0],y[8]) + m(x1_2,y[7]) + m(x[2],y[6]) + m(x3_2,y[5]) + m(x[4],y[4]) + m(x5_2,y[3]) + m(x[6],y[2]) + m(x7_2,y[1]) + m(x[8],y[0]) + m(x9_2,y9_19); - let z9 = m(x[0],y[9]) + m(x[1],y[8]) + m(x[2],y[7]) + m(x[3],y[6]) + m(x[4],y[5]) + m(x[5],y[4]) + m(x[6],y[3]) + m(x[7],y[2]) + m(x[8],y[1]) + m(x[9],y[0]); - - // How big is the contribution to z[i+j] from x[i], y[j]? - // - // Using the bounds above, we get: - // - // i even, j even: x[i]*y[j] < 2^(26+b)*2^(26+b) = 2*2^(51+2*b) - // i odd, j even: x[i]*y[j] < 2^(25+b)*2^(26+b) = 1*2^(51+2*b) - // i even, j odd: x[i]*y[j] < 2^(26+b)*2^(25+b) = 1*2^(51+2*b) - // i odd, j odd: 2*x[i]*y[j] < 2*2^(25+b)*2^(25+b) = 1*2^(51+2*b) - // - // We perform inline reduction mod p by replacing 2^255 by 19 - // (since 2^255 - 19 = 0 mod p). This adds a factor of 19, so - // we get the bounds (z0 is the biggest one, but calculated for - // posterity here in case finer estimation is needed later): - // - // z0 < ( 2 + 1*19 + 2*19 + 1*19 + 2*19 + 1*19 + 2*19 + 1*19 + 2*19 + 1*19 )*2^(51 + 2b) = 249*2^(51 + 2*b) - // z1 < ( 1 + 1 + 1*19 + 1*19 + 1*19 + 1*19 + 1*19 + 1*19 + 1*19 + 1*19 )*2^(51 + 2b) = 154*2^(51 + 2*b) - // z2 < ( 2 + 1 + 2 + 1*19 + 2*19 + 1*19 + 2*19 + 1*19 + 2*19 + 1*19 )*2^(51 + 2b) = 195*2^(51 + 2*b) - // z3 < ( 1 + 1 + 1 + 1 + 1*19 + 1*19 + 1*19 + 1*19 + 1*19 + 1*19 )*2^(51 + 2b) = 118*2^(51 + 2*b) - // z4 < ( 2 + 1 + 2 + 1 + 2 + 1*19 + 2*19 + 1*19 + 2*19 + 1*19 )*2^(51 + 2b) = 141*2^(51 + 2*b) - // z5 < ( 1 + 1 + 1 + 1 + 1 + 1 + 1*19 + 1*19 + 1*19 + 1*19 )*2^(51 + 2b) = 82*2^(51 + 2*b) - // z6 < ( 2 + 1 + 2 + 1 + 2 + 1 + 2 + 1*19 + 2*19 + 1*19 )*2^(51 + 2b) = 87*2^(51 + 2*b) - // z7 < ( 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1*19 + 1*19 )*2^(51 + 2b) = 46*2^(51 + 2*b) - // z6 < ( 2 + 1 + 2 + 1 + 2 + 1 + 2 + 1 + 2 + 1*19 )*2^(51 + 2b) = 33*2^(51 + 2*b) - // z7 < ( 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 )*2^(51 + 2b) = 10*2^(51 + 2*b) - // - // So z[0] fits into a u64 if 51 + 2*b + lg(249) < 64 - // if b < 2.5. - FieldElement2625::reduce([z0, z1, z2, z3, z4, z5, z6, z7, z8, z9]) - } -} - -impl<'a> Neg for &'a FieldElement2625 { - type Output = FieldElement2625; - fn neg(self) -> FieldElement2625 { - let mut output = *self; - output.negate(); - output - } -} - -impl ConditionallySelectable for FieldElement2625 { - fn conditional_select( - a: &FieldElement2625, - b: &FieldElement2625, - choice: Choice, - ) -> FieldElement2625 { - FieldElement2625([ - u32::conditional_select(&a.0[0], &b.0[0], choice), - u32::conditional_select(&a.0[1], &b.0[1], choice), - u32::conditional_select(&a.0[2], &b.0[2], choice), - u32::conditional_select(&a.0[3], &b.0[3], choice), - u32::conditional_select(&a.0[4], &b.0[4], choice), - u32::conditional_select(&a.0[5], &b.0[5], choice), - u32::conditional_select(&a.0[6], &b.0[6], choice), - u32::conditional_select(&a.0[7], &b.0[7], choice), - u32::conditional_select(&a.0[8], &b.0[8], choice), - u32::conditional_select(&a.0[9], &b.0[9], choice), - ]) - } - - fn conditional_assign(&mut self, other: &FieldElement2625, choice: Choice) { - self.0[0].conditional_assign(&other.0[0], choice); - self.0[1].conditional_assign(&other.0[1], choice); - self.0[2].conditional_assign(&other.0[2], choice); - self.0[3].conditional_assign(&other.0[3], choice); - self.0[4].conditional_assign(&other.0[4], choice); - self.0[5].conditional_assign(&other.0[5], choice); - self.0[6].conditional_assign(&other.0[6], choice); - self.0[7].conditional_assign(&other.0[7], choice); - self.0[8].conditional_assign(&other.0[8], choice); - self.0[9].conditional_assign(&other.0[9], choice); - } - - fn conditional_swap(a: &mut FieldElement2625, b: &mut FieldElement2625, choice: Choice) { - u32::conditional_swap(&mut a.0[0], &mut b.0[0], choice); - u32::conditional_swap(&mut a.0[1], &mut b.0[1], choice); - u32::conditional_swap(&mut a.0[2], &mut b.0[2], choice); - u32::conditional_swap(&mut a.0[3], &mut b.0[3], choice); - u32::conditional_swap(&mut a.0[4], &mut b.0[4], choice); - u32::conditional_swap(&mut a.0[5], &mut b.0[5], choice); - u32::conditional_swap(&mut a.0[6], &mut b.0[6], choice); - u32::conditional_swap(&mut a.0[7], &mut b.0[7], choice); - u32::conditional_swap(&mut a.0[8], &mut b.0[8], choice); - u32::conditional_swap(&mut a.0[9], &mut b.0[9], choice); - } -} - -impl FieldElement2625 { - /// Invert the sign of this field element - pub fn negate(&mut self) { - // Compute -b as ((2^4 * p) - b) to avoid underflow. - let neg = FieldElement2625::reduce([ - ((0x3ffffed << 4) - self.0[0]) as u64, - ((0x1ffffff << 4) - self.0[1]) as u64, - ((0x3ffffff << 4) - self.0[2]) as u64, - ((0x1ffffff << 4) - self.0[3]) as u64, - ((0x3ffffff << 4) - self.0[4]) as u64, - ((0x1ffffff << 4) - self.0[5]) as u64, - ((0x3ffffff << 4) - self.0[6]) as u64, - ((0x1ffffff << 4) - self.0[7]) as u64, - ((0x3ffffff << 4) - self.0[8]) as u64, - ((0x1ffffff << 4) - self.0[9]) as u64, - ]); - self.0 = neg.0; - } - - /// Construct zero. - pub fn zero() -> FieldElement2625 { - FieldElement2625([ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ]) - } - - /// Construct one. - pub fn one() -> FieldElement2625 { - FieldElement2625([ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0 ]) - } - - /// Construct -1. - pub fn minus_one() -> FieldElement2625 { - FieldElement2625([ - 0x3ffffec, 0x1ffffff, 0x3ffffff, 0x1ffffff, 0x3ffffff, - 0x1ffffff, 0x3ffffff, 0x1ffffff, 0x3ffffff, 0x1ffffff, - ]) - } - - /// Given `k > 0`, return `self^(2^k)`. - pub fn pow2k(&self, k: u32) -> FieldElement2625 { - debug_assert!( k > 0 ); - let mut z = self.square(); - for _ in 1..k { - z = z.square(); - } - z - } - - /// Given unreduced coefficients `z[0], ..., z[9]` of any size, - /// carry and reduce them mod p to obtain a `FieldElement2625` - /// whose coefficients have excess `b < 0.007`. - /// - /// In other words, each coefficient of the result is bounded by - /// either `2^(25 + 0.007)` or `2^(26 + 0.007)`, as appropriate. - fn reduce(mut z: [u64; 10]) -> FieldElement2625 { - - const LOW_25_BITS: u64 = (1 << 25) - 1; - const LOW_26_BITS: u64 = (1 << 26) - 1; - - /// Carry the value from limb i = 0..8 to limb i+1 - #[inline(always)] - fn carry(z: &mut [u64; 10], i: usize) { - debug_assert!(i < 9); - if i % 2 == 0 { - // Even limbs have 26 bits - z[i+1] += z[i] >> 26; - z[i] &= LOW_26_BITS; - } else { - // Odd limbs have 25 bits - z[i+1] += z[i] >> 25; - z[i] &= LOW_25_BITS; - } - } - - // Perform two halves of the carry chain in parallel. - carry(&mut z, 0); carry(&mut z, 4); - carry(&mut z, 1); carry(&mut z, 5); - carry(&mut z, 2); carry(&mut z, 6); - carry(&mut z, 3); carry(&mut z, 7); - // Since z[3] < 2^64, c < 2^(64-25) = 2^39, - // so z[4] < 2^26 + 2^39 < 2^39.0002 - carry(&mut z, 4); carry(&mut z, 8); - // Now z[4] < 2^26 - // and z[5] < 2^25 + 2^13.0002 < 2^25.0004 (good enough) - - // Last carry has a multiplication by 19: - z[0] += 19*(z[9] >> 25); - z[9] &= LOW_25_BITS; - - // Since z[9] < 2^64, c < 2^(64-25) = 2^39, - // so z[0] + 19*c < 2^26 + 2^43.248 < 2^43.249. - carry(&mut z, 0); - // Now z[1] < 2^25 - 2^(43.249 - 26) - // < 2^25.007 (good enough) - // and we're done. - - FieldElement2625([ - z[0] as u32, z[1] as u32, z[2] as u32, z[3] as u32, z[4] as u32, - z[5] as u32, z[6] as u32, z[7] as u32, z[8] as u32, z[9] as u32, - ]) - } - - /// Load a `FieldElement51` from the low 255 bits of a 256-bit - /// input. - /// - /// # Warning - /// - /// This function does not check that the input used the canonical - /// representative. It masks the high bit, but it will happily - /// decode 2^255 - 18 to 1. Applications that require a canonical - /// encoding of every field element should decode, re-encode to - /// the canonical encoding, and check that the input was - /// canonical. - pub fn from_bytes(data: &[u8; 32]) -> FieldElement2625 { //FeFromBytes - #[inline] - fn load3(b: &[u8]) -> u64 { - (b[0] as u64) | ((b[1] as u64) << 8) | ((b[2] as u64) << 16) - } - - #[inline] - fn load4(b: &[u8]) -> u64 { - (b[0] as u64) | ((b[1] as u64) << 8) | ((b[2] as u64) << 16) | ((b[3] as u64) << 24) - } - - let mut h = [0u64;10]; - const LOW_23_BITS: u64 = (1 << 23) - 1; - h[0] = load4(&data[ 0..]); - h[1] = load3(&data[ 4..]) << 6; - h[2] = load3(&data[ 7..]) << 5; - h[3] = load3(&data[10..]) << 3; - h[4] = load3(&data[13..]) << 2; - h[5] = load4(&data[16..]); - h[6] = load3(&data[20..]) << 7; - h[7] = load3(&data[23..]) << 5; - h[8] = load3(&data[26..]) << 4; - h[9] = (load3(&data[29..]) & LOW_23_BITS) << 2; - - FieldElement2625::reduce(h) - } - - /// Serialize this `FieldElement51` to a 32-byte array. The - /// encoding is canonical. - pub fn to_bytes(&self) -> [u8; 32] { - - let inp = &self.0; - // Reduce the value represented by `in` to the range [0,2*p) - let mut h: [u32; 10] = FieldElement2625::reduce([ - // XXX this cast is annoying - inp[0] as u64, inp[1] as u64, inp[2] as u64, inp[3] as u64, inp[4] as u64, - inp[5] as u64, inp[6] as u64, inp[7] as u64, inp[8] as u64, inp[9] as u64, - ]).0; - - // Let h be the value to encode. - // - // Write h = pq + r with 0 <= r < p. We want to compute r = h mod p. - // - // Since h < 2*p, q = 0 or 1, with q = 0 when h < p and q = 1 when h >= p. - // - // Notice that h >= p <==> h + 19 >= p + 19 <==> h + 19 >= 2^255. - // Therefore q can be computed as the carry bit of h + 19. - - let mut q: u32 = (h[0] + 19) >> 26; - q = (h[1] + q) >> 25; - q = (h[2] + q) >> 26; - q = (h[3] + q) >> 25; - q = (h[4] + q) >> 26; - q = (h[5] + q) >> 25; - q = (h[6] + q) >> 26; - q = (h[7] + q) >> 25; - q = (h[8] + q) >> 26; - q = (h[9] + q) >> 25; - - debug_assert!( q == 0 || q == 1 ); - - // Now we can compute r as r = h - pq = r - (2^255-19)q = r + 19q - 2^255q - - const LOW_25_BITS: u32 = (1 << 25) - 1; - const LOW_26_BITS: u32 = (1 << 26) - 1; - - h[0] += 19*q; - - // Now carry the result to compute r + 19q... - h[1] += h[0] >> 26; - h[0] = h[0] & LOW_26_BITS; - h[2] += h[1] >> 25; - h[1] = h[1] & LOW_25_BITS; - h[3] += h[2] >> 26; - h[2] = h[2] & LOW_26_BITS; - h[4] += h[3] >> 25; - h[3] = h[3] & LOW_25_BITS; - h[5] += h[4] >> 26; - h[4] = h[4] & LOW_26_BITS; - h[6] += h[5] >> 25; - h[5] = h[5] & LOW_25_BITS; - h[7] += h[6] >> 26; - h[6] = h[6] & LOW_26_BITS; - h[8] += h[7] >> 25; - h[7] = h[7] & LOW_25_BITS; - h[9] += h[8] >> 26; - h[8] = h[8] & LOW_26_BITS; - - // ... but instead of carrying the value - // (h[9] >> 25) = q*2^255 into another limb, - // discard it, subtracting the value from h. - debug_assert!( (h[9] >> 25) == 0 || (h[9] >> 25) == 1); - h[9] = h[9] & LOW_25_BITS; - - let mut s = [0u8; 32]; - s[0] = (h[0] >> 0) as u8; - s[1] = (h[0] >> 8) as u8; - s[2] = (h[0] >> 16) as u8; - s[3] = ((h[0] >> 24) | (h[1] << 2)) as u8; - s[4] = (h[1] >> 6) as u8; - s[5] = (h[1] >> 14) as u8; - s[6] = ((h[1] >> 22) | (h[2] << 3)) as u8; - s[7] = (h[2] >> 5) as u8; - s[8] = (h[2] >> 13) as u8; - s[9] = ((h[2] >> 21) | (h[3] << 5)) as u8; - s[10] = (h[3] >> 3) as u8; - s[11] = (h[3] >> 11) as u8; - s[12] = ((h[3] >> 19) | (h[4] << 6)) as u8; - s[13] = (h[4] >> 2) as u8; - s[14] = (h[4] >> 10) as u8; - s[15] = (h[4] >> 18) as u8; - s[16] = (h[5] >> 0) as u8; - s[17] = (h[5] >> 8) as u8; - s[18] = (h[5] >> 16) as u8; - s[19] = ((h[5] >> 24) | (h[6] << 1)) as u8; - s[20] = (h[6] >> 7) as u8; - s[21] = (h[6] >> 15) as u8; - s[22] = ((h[6] >> 23) | (h[7] << 3)) as u8; - s[23] = (h[7] >> 5) as u8; - s[24] = (h[7] >> 13) as u8; - s[25] = ((h[7] >> 21) | (h[8] << 4)) as u8; - s[26] = (h[8] >> 4) as u8; - s[27] = (h[8] >> 12) as u8; - s[28] = ((h[8] >> 20) | (h[9] << 6)) as u8; - s[29] = (h[9] >> 2) as u8; - s[30] = (h[9] >> 10) as u8; - s[31] = (h[9] >> 18) as u8; - - // Check that high bit is cleared - debug_assert!((s[31] & 0b1000_0000u8) == 0u8); - - s - } - - fn square_inner(&self) -> [u64; 10] { - // Optimized version of multiplication for the case of squaring. - // Pre- and post- conditions identical to multiplication function. - let x = &self.0; - let x0_2 = 2 * x[0]; - let x1_2 = 2 * x[1]; - let x2_2 = 2 * x[2]; - let x3_2 = 2 * x[3]; - let x4_2 = 2 * x[4]; - let x5_2 = 2 * x[5]; - let x6_2 = 2 * x[6]; - let x7_2 = 2 * x[7]; - let x5_19 = 19 * x[5]; - let x6_19 = 19 * x[6]; - let x7_19 = 19 * x[7]; - let x8_19 = 19 * x[8]; - let x9_19 = 19 * x[9]; - - /// Helper function to multiply two 32-bit integers with 64 bits - /// of output. - #[inline(always)] - fn m(x: u32, y: u32) -> u64 { (x as u64) * (y as u64) } - - // This block is rearranged so that instead of doing a 32-bit multiplication by 38, we do a - // 64-bit multiplication by 2 on the results. This is because lg(38) is too big: we would - // have less than 1 bit of headroom left, which is too little. - let mut z = [0u64;10]; - z[0] = m(x[0],x[0]) + m(x2_2,x8_19) + m(x4_2,x6_19) + (m(x1_2,x9_19) + m(x3_2,x7_19) + m(x[5],x5_19))*2; - z[1] = m(x0_2,x[1]) + m(x3_2,x8_19) + m(x5_2,x6_19) + (m(x[2],x9_19) + m(x[4],x7_19))*2; - z[2] = m(x0_2,x[2]) + m(x1_2,x[1]) + m(x4_2,x8_19) + m(x[6],x6_19) + (m(x3_2,x9_19) + m(x5_2,x7_19))*2; - z[3] = m(x0_2,x[3]) + m(x1_2,x[2]) + m(x5_2,x8_19) + (m(x[4],x9_19) + m(x[6],x7_19))*2; - z[4] = m(x0_2,x[4]) + m(x1_2,x3_2) + m(x[2],x[2]) + m(x6_2,x8_19) + (m(x5_2,x9_19) + m(x[7],x7_19))*2; - z[5] = m(x0_2,x[5]) + m(x1_2,x[4]) + m(x2_2,x[3]) + m(x7_2,x8_19) + m(x[6],x9_19)*2; - z[6] = m(x0_2,x[6]) + m(x1_2,x5_2) + m(x2_2,x[4]) + m(x3_2,x[3]) + m(x[8],x8_19) + m(x7_2,x9_19)*2; - z[7] = m(x0_2,x[7]) + m(x1_2,x[6]) + m(x2_2,x[5]) + m(x3_2,x[4]) + m(x[8],x9_19)*2; - z[8] = m(x0_2,x[8]) + m(x1_2,x7_2) + m(x2_2,x[6]) + m(x3_2,x5_2) + m(x[4],x[4]) + m(x[9],x9_19)*2; - z[9] = m(x0_2,x[9]) + m(x1_2,x[8]) + m(x2_2,x[7]) + m(x3_2,x[6]) + m(x4_2,x[5]) ; - - z - } - - /// Compute `self^2`. - pub fn square(&self) -> FieldElement2625 { - FieldElement2625::reduce(self.square_inner()) - } - - /// Compute `2*self^2`. - pub fn square2(&self) -> FieldElement2625 { - let mut coeffs = self.square_inner(); - for i in 0..self.0.len() { - coeffs[i] += coeffs[i]; - } - FieldElement2625::reduce(coeffs) - } -} diff --git a/net/gurk-rs/files/vendor/curve25519-dalek/src/backend/serial/u32/mod.rs b/net/gurk-rs/files/vendor/curve25519-dalek/src/backend/serial/u32/mod.rs deleted file mode 100644 index 401ce74..0000000 --- a/net/gurk-rs/files/vendor/curve25519-dalek/src/backend/serial/u32/mod.rs +++ /dev/null @@ -1,22 +0,0 @@ -// -*- mode: rust; -*- -// -// This file is part of curve25519-dalek. -// Copyright (c) 2016-2021 isis lovecruft -// Copyright (c) 2016-2019 Henry de Valence -// See LICENSE for licensing information. -// -// Authors: -// - isis agora lovecruft -// - Henry de Valence - -//! The `u32` backend uses `u32`s and a `(u32, u32) -> u64` multiplier. -//! -//! This code is intended to be portable, but it requires that -//! multiplication of two \\(32\\)-bit values to a \\(64\\)-bit result -//! is constant-time on the target platform. - -pub mod field; - -pub mod scalar; - -pub mod constants; diff --git a/net/gurk-rs/files/vendor/curve25519-dalek/src/backend/serial/u32/scalar.rs b/net/gurk-rs/files/vendor/curve25519-dalek/src/backend/serial/u32/scalar.rs deleted file mode 100644 index 8dd54bd..0000000 --- a/net/gurk-rs/files/vendor/curve25519-dalek/src/backend/serial/u32/scalar.rs +++ /dev/null @@ -1,529 +0,0 @@ -//! Arithmetic mod 2^252 + 27742317777372353535851937790883648493 -//! with 9 29-bit unsigned limbs -//! -//! To see that this is safe for intermediate results, note that -//! the largest limb in a 9 by 9 product of 29-bit limbs will be -//! (0x1fffffff^2) * 9 = 0x23fffffdc0000009 (62 bits). -//! -//! For a one level Karatsuba decomposition, the specific ranges -//! depend on how the limbs are combined, but will stay within -//! -0x1ffffffe00000008 (62 bits with sign bit) to -//! 0x43fffffbc0000011 (63 bits), which is still safe. - -use core::fmt::Debug; -use core::ops::{Index, IndexMut}; - -use zeroize::Zeroize; - -use constants; - -/// The `Scalar29` struct represents an element in ℤ/lℤ as 9 29-bit limbs -#[derive(Copy,Clone)] -pub struct Scalar29(pub [u32; 9]); - -impl Debug for Scalar29 { - fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { - write!(f, "Scalar29: {:?}", &self.0[..]) - } -} - -impl Zeroize for Scalar29 { - fn zeroize(&mut self) { - self.0.zeroize(); - } -} - -impl Index for Scalar29 { - type Output = u32; - fn index(&self, _index: usize) -> &u32 { - &(self.0[_index]) - } -} - -impl IndexMut for Scalar29 { - fn index_mut(&mut self, _index: usize) -> &mut u32 { - &mut (self.0[_index]) - } -} - -/// u32 * u32 = u64 multiply helper -#[inline(always)] -fn m(x: u32, y: u32) -> u64 { - (x as u64) * (y as u64) -} - -impl Scalar29 { - /// Return the zero scalar. - pub fn zero() -> Scalar29 { - Scalar29([0,0,0,0,0,0,0,0,0]) - } - - /// Unpack a 32 byte / 256 bit scalar into 9 29-bit limbs. - pub fn from_bytes(bytes: &[u8; 32]) -> Scalar29 { - let mut words = [0u32; 8]; - for i in 0..8 { - for j in 0..4 { - words[i] |= (bytes[(i * 4) + j] as u32) << (j * 8); - } - } - - let mask = (1u32 << 29) - 1; - let top_mask = (1u32 << 24) - 1; - let mut s = Scalar29::zero(); - - s[ 0] = words[0] & mask; - s[ 1] = ((words[0] >> 29) | (words[1] << 3)) & mask; - s[ 2] = ((words[1] >> 26) | (words[2] << 6)) & mask; - s[ 3] = ((words[2] >> 23) | (words[3] << 9)) & mask; - s[ 4] = ((words[3] >> 20) | (words[4] << 12)) & mask; - s[ 5] = ((words[4] >> 17) | (words[5] << 15)) & mask; - s[ 6] = ((words[5] >> 14) | (words[6] << 18)) & mask; - s[ 7] = ((words[6] >> 11) | (words[7] << 21)) & mask; - s[ 8] = (words[7] >> 8) & top_mask; - - s - } - - /// Reduce a 64 byte / 512 bit scalar mod l. - pub fn from_bytes_wide(bytes: &[u8; 64]) -> Scalar29 { - let mut words = [0u32; 16]; - for i in 0..16 { - for j in 0..4 { - words[i] |= (bytes[(i * 4) + j] as u32) << (j * 8); - } - } - - let mask = (1u32 << 29) - 1; - let mut lo = Scalar29::zero(); - let mut hi = Scalar29::zero(); - - lo[0] = words[ 0] & mask; - lo[1] = ((words[ 0] >> 29) | (words[ 1] << 3)) & mask; - lo[2] = ((words[ 1] >> 26) | (words[ 2] << 6)) & mask; - lo[3] = ((words[ 2] >> 23) | (words[ 3] << 9)) & mask; - lo[4] = ((words[ 3] >> 20) | (words[ 4] << 12)) & mask; - lo[5] = ((words[ 4] >> 17) | (words[ 5] << 15)) & mask; - lo[6] = ((words[ 5] >> 14) | (words[ 6] << 18)) & mask; - lo[7] = ((words[ 6] >> 11) | (words[ 7] << 21)) & mask; - lo[8] = ((words[ 7] >> 8) | (words[ 8] << 24)) & mask; - hi[0] = ((words[ 8] >> 5) | (words[ 9] << 27)) & mask; - hi[1] = (words[ 9] >> 2) & mask; - hi[2] = ((words[ 9] >> 31) | (words[10] << 1)) & mask; - hi[3] = ((words[10] >> 28) | (words[11] << 4)) & mask; - hi[4] = ((words[11] >> 25) | (words[12] << 7)) & mask; - hi[5] = ((words[12] >> 22) | (words[13] << 10)) & mask; - hi[6] = ((words[13] >> 19) | (words[14] << 13)) & mask; - hi[7] = ((words[14] >> 16) | (words[15] << 16)) & mask; - hi[8] = words[15] >> 13 ; - - lo = Scalar29::montgomery_mul(&lo, &constants::R); // (lo * R) / R = lo - hi = Scalar29::montgomery_mul(&hi, &constants::RR); // (hi * R^2) / R = hi * R - - Scalar29::add(&hi, &lo) // (hi * R) + lo - } - - /// Pack the limbs of this `Scalar29` into 32 bytes. - pub fn to_bytes(&self) -> [u8; 32] { - let mut s = [0u8; 32]; - - s[0] = (self.0[ 0] >> 0) as u8; - s[1] = (self.0[ 0] >> 8) as u8; - s[2] = (self.0[ 0] >> 16) as u8; - s[3] = ((self.0[ 0] >> 24) | (self.0[ 1] << 5)) as u8; - s[4] = (self.0[ 1] >> 3) as u8; - s[5] = (self.0[ 1] >> 11) as u8; - s[6] = (self.0[ 1] >> 19) as u8; - s[7] = ((self.0[ 1] >> 27) | (self.0[ 2] << 2)) as u8; - s[8] = (self.0[ 2] >> 6) as u8; - s[9] = (self.0[ 2] >> 14) as u8; - s[10] = ((self.0[ 2] >> 22) | (self.0[ 3] << 7)) as u8; - s[11] = (self.0[ 3] >> 1) as u8; - s[12] = (self.0[ 3] >> 9) as u8; - s[13] = (self.0[ 3] >> 17) as u8; - s[14] = ((self.0[ 3] >> 25) | (self.0[ 4] << 4)) as u8; - s[15] = (self.0[ 4] >> 4) as u8; - s[16] = (self.0[ 4] >> 12) as u8; - s[17] = (self.0[ 4] >> 20) as u8; - s[18] = ((self.0[ 4] >> 28) | (self.0[ 5] << 1)) as u8; - s[19] = (self.0[ 5] >> 7) as u8; - s[20] = (self.0[ 5] >> 15) as u8; - s[21] = ((self.0[ 5] >> 23) | (self.0[ 6] << 6)) as u8; - s[22] = (self.0[ 6] >> 2) as u8; - s[23] = (self.0[ 6] >> 10) as u8; - s[24] = (self.0[ 6] >> 18) as u8; - s[25] = ((self.0[ 6] >> 26) | (self.0[ 7] << 3)) as u8; - s[26] = (self.0[ 7] >> 5) as u8; - s[27] = (self.0[ 7] >> 13) as u8; - s[28] = (self.0[ 7] >> 21) as u8; - s[29] = (self.0[ 8] >> 0) as u8; - s[30] = (self.0[ 8] >> 8) as u8; - s[31] = (self.0[ 8] >> 16) as u8; - - s - } - - /// Compute `a + b` (mod l). - pub fn add(a: &Scalar29, b: &Scalar29) -> Scalar29 { - let mut sum = Scalar29::zero(); - let mask = (1u32 << 29) - 1; - - // a + b - let mut carry: u32 = 0; - for i in 0..9 { - carry = a[i] + b[i] + (carry >> 29); - sum[i] = carry & mask; - } - - // subtract l if the sum is >= l - Scalar29::sub(&sum, &constants::L) - } - - /// Compute `a - b` (mod l). - pub fn sub(a: &Scalar29, b: &Scalar29) -> Scalar29 { - let mut difference = Scalar29::zero(); - let mask = (1u32 << 29) - 1; - - // a - b - let mut borrow: u32 = 0; - for i in 0..9 { - borrow = a[i].wrapping_sub(b[i] + (borrow >> 31)); - difference[i] = borrow & mask; - } - - // conditionally add l if the difference is negative - let underflow_mask = ((borrow >> 31) ^ 1).wrapping_sub(1); - let mut carry: u32 = 0; - for i in 0..9 { - carry = (carry >> 29) + difference[i] + (constants::L[i] & underflow_mask); - difference[i] = carry & mask; - } - - difference - } - - /// Compute `a * b`. - /// - /// This is implemented with a one-level refined Karatsuba decomposition - #[inline(always)] - pub (crate) fn mul_internal(a: &Scalar29, b: &Scalar29) -> [u64; 17] { - let mut z = [0u64; 17]; - - z[0] = m(a[0],b[0]); // c00 - z[1] = m(a[0],b[1]) + m(a[1],b[0]); // c01 - z[2] = m(a[0],b[2]) + m(a[1],b[1]) + m(a[2],b[0]); // c02 - z[3] = m(a[0],b[3]) + m(a[1],b[2]) + m(a[2],b[1]) + m(a[3],b[0]); // c03 - z[4] = m(a[0],b[4]) + m(a[1],b[3]) + m(a[2],b[2]) + m(a[3],b[1]) + m(a[4],b[0]); // c04 - z[5] = m(a[1],b[4]) + m(a[2],b[3]) + m(a[3],b[2]) + m(a[4],b[1]); // c05 - z[6] = m(a[2],b[4]) + m(a[3],b[3]) + m(a[4],b[2]); // c06 - z[7] = m(a[3],b[4]) + m(a[4],b[3]); // c07 - z[8] = (m(a[4],b[4])).wrapping_sub(z[3]); // c08 - c03 - - z[10] = z[5].wrapping_sub(m(a[5],b[5])); // c05mc10 - z[11] = z[6].wrapping_sub(m(a[5],b[6]) + m(a[6],b[5])); // c06mc11 - z[12] = z[7].wrapping_sub(m(a[5],b[7]) + m(a[6],b[6]) + m(a[7],b[5])); // c07mc12 - z[13] = m(a[5],b[8]) + m(a[6],b[7]) + m(a[7],b[6]) + m(a[8],b[5]); // c13 - z[14] = m(a[6],b[8]) + m(a[7],b[7]) + m(a[8],b[6]); // c14 - z[15] = m(a[7],b[8]) + m(a[8],b[7]); // c15 - z[16] = m(a[8],b[8]); // c16 - - z[ 5] = z[10].wrapping_sub(z[ 0]); // c05mc10 - c00 - z[ 6] = z[11].wrapping_sub(z[ 1]); // c06mc11 - c01 - z[ 7] = z[12].wrapping_sub(z[ 2]); // c07mc12 - c02 - z[ 8] = z[ 8].wrapping_sub(z[13]); // c08mc13 - c03 - z[ 9] = z[14].wrapping_add(z[ 4]); // c14 + c04 - z[10] = z[15].wrapping_add(z[10]); // c15 + c05mc10 - z[11] = z[16].wrapping_add(z[11]); // c16 + c06mc11 - - let aa = [ - a[0]+a[5], - a[1]+a[6], - a[2]+a[7], - a[3]+a[8] - ]; - - let bb = [ - b[0]+b[5], - b[1]+b[6], - b[2]+b[7], - b[3]+b[8] - ]; - - z[ 5] = (m(aa[0],bb[0])) .wrapping_add(z[ 5]); // c20 + c05mc10 - c00 - z[ 6] = (m(aa[0],bb[1]) + m(aa[1],bb[0])) .wrapping_add(z[ 6]); // c21 + c06mc11 - c01 - z[ 7] = (m(aa[0],bb[2]) + m(aa[1],bb[1]) + m(aa[2],bb[0])) .wrapping_add(z[ 7]); // c22 + c07mc12 - c02 - z[ 8] = (m(aa[0],bb[3]) + m(aa[1],bb[2]) + m(aa[2],bb[1]) + m(aa[3],bb[0])) .wrapping_add(z[ 8]); // c23 + c08mc13 - c03 - z[ 9] = (m(aa[0], b[4]) + m(aa[1],bb[3]) + m(aa[2],bb[2]) + m(aa[3],bb[1]) + m(a[4],bb[0])).wrapping_sub(z[ 9]); // c24 - c14 - c04 - z[10] = ( m(aa[1], b[4]) + m(aa[2],bb[3]) + m(aa[3],bb[2]) + m(a[4],bb[1])).wrapping_sub(z[10]); // c25 - c15 - c05mc10 - z[11] = ( m(aa[2], b[4]) + m(aa[3],bb[3]) + m(a[4],bb[2])).wrapping_sub(z[11]); // c26 - c16 - c06mc11 - z[12] = ( m(aa[3], b[4]) + m(a[4],bb[3])).wrapping_sub(z[12]); // c27 - c07mc12 - - z - } - - /// Compute `a^2`. - #[inline(always)] - fn square_internal(a: &Scalar29) -> [u64; 17] { - let aa = [ - a[0]*2, - a[1]*2, - a[2]*2, - a[3]*2, - a[4]*2, - a[5]*2, - a[6]*2, - a[7]*2 - ]; - - [ - m( a[0],a[0]), - m(aa[0],a[1]), - m(aa[0],a[2]) + m( a[1],a[1]), - m(aa[0],a[3]) + m(aa[1],a[2]), - m(aa[0],a[4]) + m(aa[1],a[3]) + m( a[2],a[2]), - m(aa[0],a[5]) + m(aa[1],a[4]) + m(aa[2],a[3]), - m(aa[0],a[6]) + m(aa[1],a[5]) + m(aa[2],a[4]) + m( a[3],a[3]), - m(aa[0],a[7]) + m(aa[1],a[6]) + m(aa[2],a[5]) + m(aa[3],a[4]), - m(aa[0],a[8]) + m(aa[1],a[7]) + m(aa[2],a[6]) + m(aa[3],a[5]) + m( a[4],a[4]), - m(aa[1],a[8]) + m(aa[2],a[7]) + m(aa[3],a[6]) + m(aa[4],a[5]), - m(aa[2],a[8]) + m(aa[3],a[7]) + m(aa[4],a[6]) + m( a[5],a[5]), - m(aa[3],a[8]) + m(aa[4],a[7]) + m(aa[5],a[6]), - m(aa[4],a[8]) + m(aa[5],a[7]) + m( a[6],a[6]), - m(aa[5],a[8]) + m(aa[6],a[7]), - m(aa[6],a[8]) + m( a[7],a[7]), - m(aa[7],a[8]), - m( a[8],a[8]), - ] - } - - /// Compute `limbs/R` (mod l), where R is the Montgomery modulus 2^261 - #[inline(always)] - pub (crate) fn montgomery_reduce(limbs: &[u64; 17]) -> Scalar29 { - - #[inline(always)] - fn part1(sum: u64) -> (u64, u32) { - let p = (sum as u32).wrapping_mul(constants::LFACTOR) & ((1u32 << 29) - 1); - ((sum + m(p,constants::L[0])) >> 29, p) - } - - #[inline(always)] - fn part2(sum: u64) -> (u64, u32) { - let w = (sum as u32) & ((1u32 << 29) - 1); - (sum >> 29, w) - } - - // note: l5,l6,l7 are zero, so their multiplies can be skipped - let l = &constants::L; - - // the first half computes the Montgomery adjustment factor n, and begins adding n*l to make limbs divisible by R - let (carry, n0) = part1( limbs[ 0]); - let (carry, n1) = part1(carry + limbs[ 1] + m(n0,l[1])); - let (carry, n2) = part1(carry + limbs[ 2] + m(n0,l[2]) + m(n1,l[1])); - let (carry, n3) = part1(carry + limbs[ 3] + m(n0,l[3]) + m(n1,l[2]) + m(n2,l[1])); - let (carry, n4) = part1(carry + limbs[ 4] + m(n0,l[4]) + m(n1,l[3]) + m(n2,l[2]) + m(n3,l[1])); - let (carry, n5) = part1(carry + limbs[ 5] + m(n1,l[4]) + m(n2,l[3]) + m(n3,l[2]) + m(n4,l[1])); - let (carry, n6) = part1(carry + limbs[ 6] + m(n2,l[4]) + m(n3,l[3]) + m(n4,l[2]) + m(n5,l[1])); - let (carry, n7) = part1(carry + limbs[ 7] + m(n3,l[4]) + m(n4,l[3]) + m(n5,l[2]) + m(n6,l[1])); - let (carry, n8) = part1(carry + limbs[ 8] + m(n0,l[8]) + m(n4,l[4]) + m(n5,l[3]) + m(n6,l[2]) + m(n7,l[1])); - - // limbs is divisible by R now, so we can divide by R by simply storing the upper half as the result - let (carry, r0) = part2(carry + limbs[ 9] + m(n1,l[8]) + m(n5,l[4]) + m(n6,l[3]) + m(n7,l[2]) + m(n8,l[1])); - let (carry, r1) = part2(carry + limbs[10] + m(n2,l[8]) + m(n6,l[4]) + m(n7,l[3]) + m(n8,l[2])); - let (carry, r2) = part2(carry + limbs[11] + m(n3,l[8]) + m(n7,l[4]) + m(n8,l[3])); - let (carry, r3) = part2(carry + limbs[12] + m(n4,l[8]) + m(n8,l[4])); - let (carry, r4) = part2(carry + limbs[13] + m(n5,l[8]) ); - let (carry, r5) = part2(carry + limbs[14] + m(n6,l[8]) ); - let (carry, r6) = part2(carry + limbs[15] + m(n7,l[8]) ); - let (carry, r7) = part2(carry + limbs[16] + m(n8,l[8])); - let r8 = carry as u32; - - // result may be >= l, so attempt to subtract l - Scalar29::sub(&Scalar29([r0,r1,r2,r3,r4,r5,r6,r7,r8]), l) - } - - /// Compute `a * b` (mod l). - #[inline(never)] - pub fn mul(a: &Scalar29, b: &Scalar29) -> Scalar29 { - let ab = Scalar29::montgomery_reduce(&Scalar29::mul_internal(a, b)); - Scalar29::montgomery_reduce(&Scalar29::mul_internal(&ab, &constants::RR)) - } - - /// Compute `a^2` (mod l). - #[inline(never)] - #[allow(dead_code)] // XXX we don't expose square() via the Scalar API - pub fn square(&self) -> Scalar29 { - let aa = Scalar29::montgomery_reduce(&Scalar29::square_internal(self)); - Scalar29::montgomery_reduce(&Scalar29::mul_internal(&aa, &constants::RR)) - } - - /// Compute `(a * b) / R` (mod l), where R is the Montgomery modulus 2^261 - #[inline(never)] - pub fn montgomery_mul(a: &Scalar29, b: &Scalar29) -> Scalar29 { - Scalar29::montgomery_reduce(&Scalar29::mul_internal(a, b)) - } - - /// Compute `(a^2) / R` (mod l) in Montgomery form, where R is the Montgomery modulus 2^261 - #[inline(never)] - pub fn montgomery_square(&self) -> Scalar29 { - Scalar29::montgomery_reduce(&Scalar29::square_internal(self)) - } - - /// Puts a Scalar29 in to Montgomery form, i.e. computes `a*R (mod l)` - #[inline(never)] - pub fn to_montgomery(&self) -> Scalar29 { - Scalar29::montgomery_mul(self, &constants::RR) - } - - /// Takes a Scalar29 out of Montgomery form, i.e. computes `a/R (mod l)` - pub fn from_montgomery(&self) -> Scalar29 { - let mut limbs = [0u64; 17]; - for i in 0..9 { - limbs[i] = self[i] as u64; - } - Scalar29::montgomery_reduce(&limbs) - } -} - -#[cfg(test)] -mod test { - use super::*; - - /// Note: x is 2^253-1 which is slightly larger than the largest scalar produced by - /// this implementation (l-1), and should verify there are no overflows for valid scalars - /// - /// x = 2^253-1 = 14474011154664524427946373126085988481658748083205070504932198000989141204991 - /// x = 7237005577332262213973186563042994240801631723825162898930247062703686954002 mod l - /// x = 5147078182513738803124273553712992179887200054963030844803268920753008712037*R mod l in Montgomery form - pub static X: Scalar29 = Scalar29( - [0x1fffffff, 0x1fffffff, 0x1fffffff, 0x1fffffff, - 0x1fffffff, 0x1fffffff, 0x1fffffff, 0x1fffffff, - 0x001fffff]); - - /// x^2 = 3078544782642840487852506753550082162405942681916160040940637093560259278169 mod l - pub static XX: Scalar29 = Scalar29( - [0x00217559, 0x000b3401, 0x103ff43b, 0x1462a62c, - 0x1d6f9f38, 0x18e7a42f, 0x09a3dcee, 0x008dbe18, - 0x0006ce65]); - - /// x^2 = 2912514428060642753613814151688322857484807845836623976981729207238463947987*R mod l in Montgomery form - pub static XX_MONT: Scalar29 = Scalar29( - [0x152b4d2e, 0x0571d53b, 0x1da6d964, 0x188663b6, - 0x1d1b5f92, 0x19d50e3f, 0x12306c29, 0x0c6f26fe, - 0x00030edb]); - - /// y = 6145104759870991071742105800796537629880401874866217824609283457819451087098 - pub static Y: Scalar29 = Scalar29( - [0x1e1458fa, 0x165ba838, 0x1d787b36, 0x0e577f3a, - 0x1d2baf06, 0x1d689a19, 0x1fff3047, 0x117704ab, - 0x000d9601]); - - /// x*y = 36752150652102274958925982391442301741 - pub static XY: Scalar29 = Scalar29( - [0x0ba7632d, 0x017736bb, 0x15c76138, 0x0c69daa1, - 0x000001ba, 0x00000000, 0x00000000, 0x00000000, - 0x00000000]); - - /// x*y = 3783114862749659543382438697751927473898937741870308063443170013240655651591*R mod l in Montgomery form - pub static XY_MONT: Scalar29 = Scalar29( - [0x077b51e1, 0x1c64e119, 0x02a19ef5, 0x18d2129e, - 0x00de0430, 0x045a7bc8, 0x04cfc7c9, 0x1c002681, - 0x000bdc1c]); - - /// a = 2351415481556538453565687241199399922945659411799870114962672658845158063753 - pub static A: Scalar29 = Scalar29( - [0x07b3be89, 0x02291b60, 0x14a99f03, 0x07dc3787, - 0x0a782aae, 0x16262525, 0x0cfdb93f, 0x13f5718d, - 0x000532da]); - - /// b = 4885590095775723760407499321843594317911456947580037491039278279440296187236 - pub static B: Scalar29 = Scalar29( - [0x15421564, 0x1e69fd72, 0x093d9692, 0x161785be, - 0x1587d69f, 0x09d9dada, 0x130246c0, 0x0c0a8e72, - 0x000acd25]); - - /// a+b = 0 - /// a-b = 4702830963113076907131374482398799845891318823599740229925345317690316127506 - pub static AB: Scalar29 = Scalar29( - [0x0f677d12, 0x045236c0, 0x09533e06, 0x0fb86f0f, - 0x14f0555c, 0x0c4c4a4a, 0x19fb727f, 0x07eae31a, - 0x000a65b5]); - - // c = (2^512 - 1) % l = 1627715501170711445284395025044413883736156588369414752970002579683115011840 - pub static C: Scalar29 = Scalar29( - [0x049c0f00, 0x00308f1a, 0x0164d1e9, 0x1c374ed1, - 0x1be65d00, 0x19e90bfa, 0x08f73bb1, 0x036f8613, - 0x00039941]); - - #[test] - fn mul_max() { - let res = Scalar29::mul(&X, &X); - for i in 0..9 { - assert!(res[i] == XX[i]); - } - } - - #[test] - fn square_max() { - let res = X.square(); - for i in 0..9 { - assert!(res[i] == XX[i]); - } - } - - #[test] - fn montgomery_mul_max() { - let res = Scalar29::montgomery_mul(&X, &X); - for i in 0..9 { - assert!(res[i] == XX_MONT[i]); - } - } - - #[test] - fn montgomery_square_max() { - let res = X.montgomery_square(); - for i in 0..9 { - assert!(res[i] == XX_MONT[i]); - } - } - - #[test] - fn mul() { - let res = Scalar29::mul(&X, &Y); - for i in 0..9 { - assert!(res[i] == XY[i]); - } - } - - #[test] - fn montgomery_mul() { - let res = Scalar29::montgomery_mul(&X, &Y); - for i in 0..9 { - assert!(res[i] == XY_MONT[i]); - } - } - - #[test] - fn add() { - let res = Scalar29::add(&A, &B); - let zero = Scalar29::zero(); - for i in 0..9 { - assert!(res[i] == zero[i]); - } - } - - #[test] - fn sub() { - let res = Scalar29::sub(&A, &B); - for i in 0..9 { - assert!(res[i] == AB[i]); - } - } - - #[test] - fn from_bytes_wide() { - let bignum = [255u8; 64]; // 2^512 - 1 - let reduced = Scalar29::from_bytes_wide(&bignum); - for i in 0..9 { - assert!(reduced[i] == C[i]); - } - } -} diff --git a/net/gurk-rs/files/vendor/curve25519-dalek/src/backend/serial/u64/constants.rs b/net/gurk-rs/files/vendor/curve25519-dalek/src/backend/serial/u64/constants.rs deleted file mode 100644 index 6cbc0b5..0000000 --- a/net/gurk-rs/files/vendor/curve25519-dalek/src/backend/serial/u64/constants.rs +++ /dev/null @@ -1,7759 +0,0 @@ -// -*- mode: rust; -*- -// -// This file is part of curve25519-dalek. -// Copyright (c) 2016-2021 isis lovecruft -// Copyright (c) 2016-2019 Henry de Valence -// See LICENSE for licensing information. -// -// Authors: -// - isis agora lovecruft -// - Henry de Valence - -//! This module contains backend-specific constant values, such as the 64-bit limbs of curve constants. - -use backend::serial::curve_models::AffineNielsPoint; -use super::field::FieldElement51; -use super::scalar::Scalar52; -use edwards::{EdwardsBasepointTable, EdwardsPoint}; -use window::{LookupTable, NafLookupTable8}; - -/// The value of minus one, equal to `-&FieldElement::one()` -pub(crate) const MINUS_ONE: FieldElement51 = FieldElement51([ - 2251799813685228, - 2251799813685247, - 2251799813685247, - 2251799813685247, - 2251799813685247 -]); - -/// Edwards `d` value, equal to `-121665/121666 mod p`. -pub(crate) const EDWARDS_D: FieldElement51 = FieldElement51([ - 929955233495203, - 466365720129213, - 1662059464998953, - 2033849074728123, - 1442794654840575, -]); - -/// Edwards `2*d` value, equal to `2*(-121665/121666) mod p`. -pub(crate) const EDWARDS_D2: FieldElement51 = FieldElement51([ - 1859910466990425, - 932731440258426, - 1072319116312658, - 1815898335770999, - 633789495995903, -]); - -/// One minus edwards `d` value squared, equal to `(1 - (-121665/121666) mod p) pow 2` -pub(crate) const ONE_MINUS_EDWARDS_D_SQUARED: FieldElement51 = FieldElement51([ - 1136626929484150, - 1998550399581263, - 496427632559748, - 118527312129759, - 45110755273534 -]); - -/// Edwards `d` value minus one squared, equal to `(((-121665/121666) mod p) - 1) pow 2` -pub(crate) const EDWARDS_D_MINUS_ONE_SQUARED: FieldElement51 = FieldElement51([ - 1507062230895904, - 1572317787530805, - 683053064812840, - 317374165784489, - 1572899562415810 -]); - -/// `= sqrt(a*d - 1)`, where `a = -1 (mod p)`, `d` are the Edwards curve parameters. -pub(crate) const SQRT_AD_MINUS_ONE: FieldElement51 = FieldElement51([ - 2241493124984347, - 425987919032274, - 2207028919301688, - 1220490630685848, - 974799131293748, -]); - -/// `= 1/sqrt(a-d)`, where `a = -1 (mod p)`, `d` are the Edwards curve parameters. -pub(crate) const INVSQRT_A_MINUS_D: FieldElement51 = FieldElement51([ - 278908739862762, - 821645201101625, - 8113234426968, - 1777959178193151, - 2118520810568447, -]); - -/// Precomputed value of one of the square roots of -1 (mod p) -pub(crate) const SQRT_M1: FieldElement51 = FieldElement51([ - 1718705420411056, - 234908883556509, - 2233514472574048, - 2117202627021982, - 765476049583133, -]); - -/// `APLUS2_OVER_FOUR` is (A+2)/4. (This is used internally within the Montgomery ladder.) -pub(crate) const APLUS2_OVER_FOUR: FieldElement51 = FieldElement51([121666, 0, 0, 0, 0]); - -/// `MONTGOMERY_A` is equal to 486662, which is a constant of the curve equation -/// for Curve25519 in its Montgomery form. (This is used internally within the -/// Elligator map.) -pub(crate) const MONTGOMERY_A: FieldElement51 = FieldElement51([486662, 0, 0, 0, 0]); - -/// `MONTGOMERY_A_NEG` is equal to -486662. (This is used internally within the -/// Elligator map.) -pub(crate) const MONTGOMERY_A_NEG: FieldElement51 = FieldElement51([ - 2251799813198567, - 2251799813685247, - 2251799813685247, - 2251799813685247, - 2251799813685247, -]); - -/// `L` is the order of base point, i.e. 2^252 + 27742317777372353535851937790883648493 -pub(crate) const L: Scalar52 = Scalar52([ - 0x0002631a5cf5d3ed, - 0x000dea2f79cd6581, - 0x000000000014def9, - 0x0000000000000000, - 0x0000100000000000, -]); - -/// `L` * `LFACTOR` = -1 (mod 2^52) -pub(crate) const LFACTOR: u64 = 0x51da312547e1b; - -/// `R` = R % L where R = 2^260 -pub(crate) const R: Scalar52 = Scalar52([ - 0x000f48bd6721e6ed, - 0x0003bab5ac67e45a, - 0x000fffffeb35e51b, - 0x000fffffffffffff, - 0x00000fffffffffff, -]); - -/// `RR` = (R^2) % L where R = 2^260 -pub(crate) const RR: Scalar52 = Scalar52([ - 0x0009d265e952d13b, - 0x000d63c715bea69f, - 0x0005be65cb687604, - 0x0003dceec73d217f, - 0x000009411b7c309a, -]); - -/// The Ed25519 basepoint, as an `EdwardsPoint`. -/// -/// This is called `_POINT` to distinguish it from -/// `ED25519_BASEPOINT_TABLE`, which should be used for scalar -/// multiplication (it's much faster). -pub const ED25519_BASEPOINT_POINT: EdwardsPoint = EdwardsPoint { - X: FieldElement51([ - 1738742601995546, - 1146398526822698, - 2070867633025821, - 562264141797630, - 587772402128613, - ]), - Y: FieldElement51([ - 1801439850948184, - 1351079888211148, - 450359962737049, - 900719925474099, - 1801439850948198, - ]), - Z: FieldElement51([1, 0, 0, 0, 0]), - T: FieldElement51([ - 1841354044333475, - 16398895984059, - 755974180946558, - 900171276175154, - 1821297809914039, - ]), -}; - -/// The 8-torsion subgroup \\(\mathcal E [8]\\). -/// -/// In the case of Curve25519, it is cyclic; the \\(i\\)-th element of -/// the array is \\([i]P\\), where \\(P\\) is a point of order \\(8\\) -/// generating \\(\mathcal E[8]\\). -/// -/// Thus \\(\mathcal E[4]\\) is the points indexed by `0,2,4,6`, and -/// \\(\mathcal E[2]\\) is the points indexed by `0,4`. -pub const EIGHT_TORSION: [EdwardsPoint; 8] = EIGHT_TORSION_INNER_DOC_HIDDEN; - -/// Inner item used to hide limb constants from cargo doc output. -#[doc(hidden)] -pub const EIGHT_TORSION_INNER_DOC_HIDDEN: [EdwardsPoint; 8] = [ - EdwardsPoint { - X: FieldElement51([0, 0, 0, 0, 0]), - Y: FieldElement51([1, 0, 0, 0, 0]), - Z: FieldElement51([1, 0, 0, 0, 0]), - T: FieldElement51([0, 0, 0, 0, 0]), - }, - EdwardsPoint { - X: FieldElement51([ - 358744748052810, - 1691584618240980, - 977650209285361, - 1429865912637724, - 560044844278676, - ]), - Y: FieldElement51([ - 84926274344903, - 473620666599931, - 365590438845504, - 1028470286882429, - 2146499180330972, - ]), - Z: FieldElement51([1, 0, 0, 0, 0]), - T: FieldElement51([ - 1448326834587521, - 1857896831960481, - 1093722731865333, - 1677408490711241, - 1915505153018406, - ]), - }, - EdwardsPoint { - X: FieldElement51([ - 533094393274173, - 2016890930128738, - 18285341111199, - 134597186663265, - 1486323764102114, - ]), - Y: FieldElement51([0, 0, 0, 0, 0]), - Z: FieldElement51([1, 0, 0, 0, 0]), - T: FieldElement51([0, 0, 0, 0, 0]), - }, - EdwardsPoint { - X: FieldElement51([ - 358744748052810, - 1691584618240980, - 977650209285361, - 1429865912637724, - 560044844278676, - ]), - Y: FieldElement51([ - 2166873539340326, - 1778179147085316, - 1886209374839743, - 1223329526802818, - 105300633354275, - ]), - Z: FieldElement51([1, 0, 0, 0, 0]), - T: FieldElement51([ - 803472979097708, - 393902981724766, - 1158077081819914, - 574391322974006, - 336294660666841, - ]), - }, - EdwardsPoint { - X: FieldElement51([0, 0, 0, 0, 0]), - Y: FieldElement51([ - 2251799813685228, - 2251799813685247, - 2251799813685247, - 2251799813685247, - 2251799813685247, - ]), - Z: FieldElement51([1, 0, 0, 0, 0]), - T: FieldElement51([0, 0, 0, 0, 0]), - }, - EdwardsPoint { - X: FieldElement51([ - 1893055065632419, - 560215195444267, - 1274149604399886, - 821933901047523, - 1691754969406571, - ]), - Y: FieldElement51([ - 2166873539340326, - 1778179147085316, - 1886209374839743, - 1223329526802818, - 105300633354275, - ]), - Z: FieldElement51([1, 0, 0, 0, 0]), - T: FieldElement51([ - 1448326834587521, - 1857896831960481, - 1093722731865333, - 1677408490711241, - 1915505153018406, - ]), - }, - EdwardsPoint { - X: FieldElement51([ - 1718705420411056, - 234908883556509, - 2233514472574048, - 2117202627021982, - 765476049583133, - ]), - Y: FieldElement51([0, 0, 0, 0, 0]), - Z: FieldElement51([1, 0, 0, 0, 0]), - T: FieldElement51([0, 0, 0, 0, 0]), - }, - EdwardsPoint { - X: FieldElement51([ - 1893055065632419, - 560215195444267, - 1274149604399886, - 821933901047523, - 1691754969406571, - ]), - Y: FieldElement51([ - 84926274344903, - 473620666599931, - 365590438845504, - 1028470286882429, - 2146499180330972, - ]), - Z: FieldElement51([1, 0, 0, 0, 0]), - T: FieldElement51([ - 803472979097708, - 393902981724766, - 1158077081819914, - 574391322974006, - 336294660666841, - ]), - }, -]; - -/// Table containing precomputed multiples of the Ed25519 basepoint \\(B = (x, 4/5)\\). -pub const ED25519_BASEPOINT_TABLE: EdwardsBasepointTable = ED25519_BASEPOINT_TABLE_INNER_DOC_HIDDEN; - -/// Inner constant, used to avoid filling the docs with precomputed points. -#[doc(hidden)] -pub const ED25519_BASEPOINT_TABLE_INNER_DOC_HIDDEN: EdwardsBasepointTable = - EdwardsBasepointTable([ - LookupTable([ - AffineNielsPoint { - y_plus_x: FieldElement51([ - 3540182452943730, - 2497478415033846, - 2521227595762870, - 1462984067271729, - 2389212253076811, - ]), - y_minus_x: FieldElement51([ - 62697248952638, - 204681361388450, - 631292143396476, - 338455783676468, - 1213667448819585, - ]), - xy2d: FieldElement51([ - 301289933810280, - 1259582250014073, - 1422107436869536, - 796239922652654, - 1953934009299142, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 3632771708514775, - 790832306631235, - 2067202295274102, - 1995808275510000, - 1566530869037010, - ]), - y_minus_x: FieldElement51([ - 463307831301544, - 432984605774163, - 1610641361907204, - 750899048855000, - 1894842303421586, - ]), - xy2d: FieldElement51([ - 748439484463711, - 1033211726465151, - 1396005112841647, - 1611506220286469, - 1972177495910992, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 1601611775252272, - 1720807796594148, - 1132070835939856, - 3512254832574799, - 2147779492816910, - ]), - y_minus_x: FieldElement51([ - 316559037616741, - 2177824224946892, - 1459442586438991, - 1461528397712656, - 751590696113597, - ]), - xy2d: FieldElement51([ - 1850748884277385, - 1200145853858453, - 1068094770532492, - 672251375690438, - 1586055907191707, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 934282339813791, - 1846903124198670, - 1172395437954843, - 1007037127761661, - 1830588347719256, - ]), - y_minus_x: FieldElement51([ - 1694390458783935, - 1735906047636159, - 705069562067493, - 648033061693059, - 696214010414170, - ]), - xy2d: FieldElement51([ - 1121406372216585, - 192876649532226, - 190294192191717, - 1994165897297032, - 2245000007398739, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 769950342298400, - 2384754244604994, - 3095885746880802, - 3225892188161580, - 2977876099231263, - ]), - y_minus_x: FieldElement51([ - 425251763115706, - 608463272472562, - 442562545713235, - 837766094556764, - 374555092627893, - ]), - xy2d: FieldElement51([ - 1086255230780037, - 274979815921559, - 1960002765731872, - 929474102396301, - 1190409889297339, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 1388594989461809, - 316767091099457, - 2646098655878230, - 1230079486801004, - 1440737038838979, - ]), - y_minus_x: FieldElement51([ - 7380825640100, - 146210432690483, - 304903576448906, - 1198869323871120, - 997689833219095, - ]), - xy2d: FieldElement51([ - 1181317918772081, - 114573476638901, - 262805072233344, - 265712217171332, - 294181933805782, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 2916800678241215, - 2065379846933858, - 2622030924071124, - 2602788184473875, - 1233371373142984, - ]), - y_minus_x: FieldElement51([ - 2019367628972465, - 676711900706637, - 110710997811333, - 1108646842542025, - 517791959672113, - ]), - xy2d: FieldElement51([ - 965130719900578, - 247011430587952, - 526356006571389, - 91986625355052, - 2157223321444601, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 4320419353804412, - 4218074731744053, - 957728544705548, - 729906502578991, - 2411634706750414, - ]), - y_minus_x: FieldElement51([ - 2073601412052185, - 31021124762708, - 264500969797082, - 248034690651703, - 1030252227928288, - ]), - xy2d: FieldElement51([ - 551790716293402, - 1989538725166328, - 801169423371717, - 2052451893578887, - 678432056995012, - ]), - }, - ]), - LookupTable([ - AffineNielsPoint { - y_plus_x: FieldElement51([ - 1368953770187805, - 3042147450398169, - 2689308289352409, - 2142576377050579, - 1932081720066286, - ]), - y_minus_x: FieldElement51([ - 953638594433374, - 1092333936795051, - 1419774766716690, - 805677984380077, - 859228993502513, - ]), - xy2d: FieldElement51([ - 1200766035879111, - 20142053207432, - 1465634435977050, - 1645256912097844, - 295121984874596, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 1735718747031538, - 1248237894295956, - 1204753118328107, - 976066523550493, - 2317743583219840, - ]), - y_minus_x: FieldElement51([ - 1060098822528990, - 1586825862073490, - 212301317240126, - 1975302711403555, - 666724059764335, - ]), - xy2d: FieldElement51([ - 1091990273418756, - 1572899409348578, - 80968014455247, - 306009358661350, - 1520450739132526, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 3732317023121341, - 1511153322193951, - 3496143672676420, - 2556587964178488, - 2620936670181690, - ]), - y_minus_x: FieldElement51([ - 2151330273626164, - 762045184746182, - 1688074332551515, - 823046109005759, - 907602769079491, - ]), - xy2d: FieldElement51([ - 2047386910586836, - 168470092900250, - 1552838872594810, - 340951180073789, - 360819374702533, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 1982622644432037, - 2014393600336956, - 2380709022489462, - 3869592437614438, - 2357094095599062, - ]), - y_minus_x: FieldElement51([ - 980234343912898, - 1712256739246056, - 588935272190264, - 204298813091998, - 841798321043288, - ]), - xy2d: FieldElement51([ - 197561292938973, - 454817274782871, - 1963754960082318, - 2113372252160468, - 971377527342673, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 2416499262514576, - 2254927265442919, - 3451304785234000, - 1766155447043651, - 1899238924683527, - ]), - y_minus_x: FieldElement51([ - 732262946680281, - 1674412764227063, - 2182456405662809, - 1350894754474250, - 558458873295247, - ]), - xy2d: FieldElement51([ - 2103305098582922, - 1960809151316468, - 715134605001343, - 1454892949167181, - 40827143824949, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 1239289043050193, - 1744654158124578, - 758702410031698, - 4048562808759936, - 2253402870349013, - ]), - y_minus_x: FieldElement51([ - 2232056027107988, - 987343914584615, - 2115594492994461, - 1819598072792159, - 1119305654014850, - ]), - xy2d: FieldElement51([ - 320153677847348, - 939613871605645, - 641883205761567, - 1930009789398224, - 329165806634126, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 3232730304159378, - 1242488692177892, - 1251446316964684, - 1086618677993530, - 1961430968465772, - ]), - y_minus_x: FieldElement51([ - 276821765317453, - 1536835591188030, - 1305212741412361, - 61473904210175, - 2051377036983058, - ]), - xy2d: FieldElement51([ - 833449923882501, - 1750270368490475, - 1123347002068295, - 185477424765687, - 278090826653186, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 794524995833413, - 1849907304548286, - 2305148486158393, - 1272368559505216, - 1147304168324779, - ]), - y_minus_x: FieldElement51([ - 1504846112759364, - 1203096289004681, - 562139421471418, - 274333017451844, - 1284344053775441, - ]), - xy2d: FieldElement51([ - 483048732424432, - 2116063063343382, - 30120189902313, - 292451576741007, - 1156379271702225, - ]), - }, - ]), - LookupTable([ - AffineNielsPoint { - y_plus_x: FieldElement51([ - 3180171966714267, - 2147692869914563, - 1455665844462196, - 1986737809425946, - 2437006863943337, - ]), - y_minus_x: FieldElement51([ - 137732961814206, - 706670923917341, - 1387038086865771, - 1965643813686352, - 1384777115696347, - ]), - xy2d: FieldElement51([ - 481144981981577, - 2053319313589856, - 2065402289827512, - 617954271490316, - 1106602634668125, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 2948097833334040, - 3145099472726142, - 1148636718636008, - 2278533891034865, - 2203955659340680, - ]), - y_minus_x: FieldElement51([ - 657390353372855, - 998499966885562, - 991893336905797, - 810470207106761, - 343139804608786, - ]), - xy2d: FieldElement51([ - 791736669492960, - 934767652997115, - 824656780392914, - 1759463253018643, - 361530362383518, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 2022541353055578, - 4346500076272714, - 3802807888710933, - 2494585331103411, - 2947785218648809, - ]), - y_minus_x: FieldElement51([ - 1287487199965223, - 2215311941380308, - 1552928390931986, - 1664859529680196, - 1125004975265243, - ]), - xy2d: FieldElement51([ - 677434665154918, - 989582503122485, - 1817429540898386, - 1052904935475344, - 1143826298169798, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 2619066141993637, - 2570231002607651, - 2947429167440602, - 2885885471266079, - 2276381426249673, - ]), - y_minus_x: FieldElement51([ - 773360688841258, - 1815381330538070, - 363773437667376, - 539629987070205, - 783280434248437, - ]), - xy2d: FieldElement51([ - 180820816194166, - 168937968377394, - 748416242794470, - 1227281252254508, - 1567587861004268, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 2730575372268893, - 2062896624554806, - 2951191072970647, - 2609899222113120, - 1277310261461760, - ]), - y_minus_x: FieldElement51([ - 1984740906540026, - 1079164179400229, - 1056021349262661, - 1659958556483663, - 1088529069025527, - ]), - xy2d: FieldElement51([ - 580736401511151, - 1842931091388998, - 1177201471228238, - 2075460256527244, - 1301133425678027, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 1515728832059163, - 1575261009617579, - 1510246567196186, - 2442877836294952, - 2368461529974388, - ]), - y_minus_x: FieldElement51([ - 1295295738269652, - 1714742313707026, - 545583042462581, - 2034411676262552, - 1513248090013606, - ]), - xy2d: FieldElement51([ - 230710545179830, - 30821514358353, - 760704303452229, - 390668103790604, - 573437871383156, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 3421179921230875, - 2514967047430861, - 4274701112739695, - 3071700566936367, - 4275698278559832, - ]), - y_minus_x: FieldElement51([ - 2102254323485823, - 1570832666216754, - 34696906544624, - 1993213739807337, - 70638552271463, - ]), - xy2d: FieldElement51([ - 894132856735058, - 548675863558441, - 845349339503395, - 1942269668326667, - 1615682209874691, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 3539470031223082, - 1222355136884919, - 1846481788678694, - 1150426571265110, - 1613523400722047, - ]), - y_minus_x: FieldElement51([ - 793388516527298, - 1315457083650035, - 1972286999342417, - 1901825953052455, - 338269477222410, - ]), - xy2d: FieldElement51([ - 550201530671806, - 778605267108140, - 2063911101902983, - 115500557286349, - 2041641272971022, - ]), - }, - ]), - LookupTable([ - AffineNielsPoint { - y_plus_x: FieldElement51([ - 717255318455100, - 519313764361315, - 2080406977303708, - 541981206705521, - 774328150311600, - ]), - y_minus_x: FieldElement51([ - 261715221532238, - 1795354330069993, - 1496878026850283, - 499739720521052, - 389031152673770, - ]), - xy2d: FieldElement51([ - 1997217696294013, - 1717306351628065, - 1684313917746180, - 1644426076011410, - 1857378133465451, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 3727234538477877, - 2328731709971226, - 3368528843456914, - 2002544139318041, - 2977347647489186, - ]), - y_minus_x: FieldElement51([ - 2022306639183567, - 726296063571875, - 315345054448644, - 1058733329149221, - 1448201136060677, - ]), - xy2d: FieldElement51([ - 1710065158525665, - 1895094923036397, - 123988286168546, - 1145519900776355, - 1607510767693874, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 2813405189107769, - 1071733543815036, - 2383296312486238, - 1946868434569998, - 3079937947649451, - ]), - y_minus_x: FieldElement51([ - 1548495173745801, - 442310529226540, - 998072547000384, - 553054358385281, - 644824326376171, - ]), - xy2d: FieldElement51([ - 1445526537029440, - 2225519789662536, - 914628859347385, - 1064754194555068, - 1660295614401091, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 3451490036797185, - 2275827949507588, - 2318438102929588, - 2309425969971222, - 2816893781664854, - ]), - y_minus_x: FieldElement51([ - 876926774220824, - 554618976488214, - 1012056309841565, - 839961821554611, - 1414499340307677, - ]), - xy2d: FieldElement51([ - 703047626104145, - 1266841406201770, - 165556500219173, - 486991595001879, - 1011325891650656, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 1622861044480487, - 1156394801573634, - 4120932379100752, - 2578903799462977, - 2095342781472283, - ]), - y_minus_x: FieldElement51([ - 334886927423922, - 489511099221528, - 129160865966726, - 1720809113143481, - 619700195649254, - ]), - xy2d: FieldElement51([ - 1646545795166119, - 1758370782583567, - 714746174550637, - 1472693650165135, - 898994790308209, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 2585203586724508, - 2547572356138185, - 1693106465353609, - 912330357530760, - 2723035471635610, - ]), - y_minus_x: FieldElement51([ - 1811196219982022, - 1068969825533602, - 289602974833439, - 1988956043611592, - 863562343398367, - ]), - xy2d: FieldElement51([ - 906282429780072, - 2108672665779781, - 432396390473936, - 150625823801893, - 1708930497638539, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 925664675702309, - 2273216662253932, - 4083236455546587, - 601157008940112, - 2623617868729744, - ]), - y_minus_x: FieldElement51([ - 1479786007267725, - 1738881859066675, - 68646196476567, - 2146507056100328, - 1247662817535471, - ]), - xy2d: FieldElement51([ - 52035296774456, - 939969390708103, - 312023458773250, - 59873523517659, - 1231345905848899, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 2895154920100990, - 2541986621181021, - 2013561737429022, - 2571447883196794, - 2645536492181409, - ]), - y_minus_x: FieldElement51([ - 129358342392716, - 1932811617704777, - 1176749390799681, - 398040349861790, - 1170779668090425, - ]), - xy2d: FieldElement51([ - 2051980782668029, - 121859921510665, - 2048329875753063, - 1235229850149665, - 519062146124755, - ]), - }, - ]), - LookupTable([ - AffineNielsPoint { - y_plus_x: FieldElement51([ - 3859970785658325, - 2667608874045675, - 1350468408164765, - 2038620059057678, - 3278704299674360, - ]), - y_minus_x: FieldElement51([ - 1837656083115103, - 1510134048812070, - 906263674192061, - 1821064197805734, - 565375124676301, - ]), - xy2d: FieldElement51([ - 578027192365650, - 2034800251375322, - 2128954087207123, - 478816193810521, - 2196171989962750, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 1633188840273120, - 3104586986058956, - 1548762607215795, - 1266275218902681, - 3359018017010381, - ]), - y_minus_x: FieldElement51([ - 462189358480054, - 1784816734159228, - 1611334301651368, - 1303938263943540, - 707589560319424, - ]), - xy2d: FieldElement51([ - 1038829280972848, - 38176604650029, - 753193246598573, - 1136076426528122, - 595709990562434, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 3660251634545082, - 2194984964010832, - 2198361797561729, - 1061962440055713, - 1645147963442934, - ]), - y_minus_x: FieldElement51([ - 4701053362120, - 1647641066302348, - 1047553002242085, - 1923635013395977, - 206970314902065, - ]), - xy2d: FieldElement51([ - 1750479161778571, - 1362553355169293, - 1891721260220598, - 966109370862782, - 1024913988299801, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 2464498862816952, - 1117950018299774, - 1873945661751056, - 3655602735669306, - 2382695896337945, - ]), - y_minus_x: FieldElement51([ - 636808533673210, - 1262201711667560, - 390951380330599, - 1663420692697294, - 561951321757406, - ]), - xy2d: FieldElement51([ - 520731594438141, - 1446301499955692, - 273753264629267, - 1565101517999256, - 1019411827004672, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 3178327305714638, - 3443653291096626, - 734233225181170, - 2435838701226518, - 4042225960010590, - ]), - y_minus_x: FieldElement51([ - 1464651961852572, - 1483737295721717, - 1519450561335517, - 1161429831763785, - 405914998179977, - ]), - xy2d: FieldElement51([ - 996126634382301, - 796204125879525, - 127517800546509, - 344155944689303, - 615279846169038, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 2990523894660505, - 2188666632415295, - 1961313708559162, - 1506545807547587, - 3403101452654988, - ]), - y_minus_x: FieldElement51([ - 622917337413835, - 1218989177089035, - 1284857712846592, - 970502061709359, - 351025208117090, - ]), - xy2d: FieldElement51([ - 2067814584765580, - 1677855129927492, - 2086109782475197, - 235286517313238, - 1416314046739645, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 2838644076315587, - 2559244195637442, - 458399356043425, - 2853867838192310, - 3280348017100490, - ]), - y_minus_x: FieldElement51([ - 678489922928203, - 2016657584724032, - 90977383049628, - 1026831907234582, - 615271492942522, - ]), - xy2d: FieldElement51([ - 301225714012278, - 1094837270268560, - 1202288391010439, - 644352775178361, - 1647055902137983, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 1210746697896459, - 1416608304244708, - 2938287290903104, - 3496931005119382, - 3303038150540984, - ]), - y_minus_x: FieldElement51([ - 1135604073198207, - 1683322080485474, - 769147804376683, - 2086688130589414, - 900445683120379, - ]), - xy2d: FieldElement51([ - 1971518477615628, - 401909519527336, - 448627091057375, - 1409486868273821, - 1214789035034363, - ]), - }, - ]), - LookupTable([ - AffineNielsPoint { - y_plus_x: FieldElement51([ - 1364039144731711, - 1897497433586190, - 2203097701135459, - 2397261210496499, - 1349844460790698, - ]), - y_minus_x: FieldElement51([ - 1045230323257973, - 818206601145807, - 630513189076103, - 1672046528998132, - 807204017562437, - ]), - xy2d: FieldElement51([ - 439961968385997, - 386362664488986, - 1382706320807688, - 309894000125359, - 2207801346498567, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 3480804500082836, - 3172443782216110, - 2375775707596425, - 2933223806901024, - 1400559197080972, - ]), - y_minus_x: FieldElement51([ - 2003766096898049, - 170074059235165, - 1141124258967971, - 1485419893480973, - 1573762821028725, - ]), - xy2d: FieldElement51([ - 729905708611432, - 1270323270673202, - 123353058984288, - 426460209632942, - 2195574535456672, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 1271140255321216, - 2044363183174497, - 2303925201319937, - 3696920060379952, - 3194341800024331, - ]), - y_minus_x: FieldElement51([ - 1761608437466135, - 583360847526804, - 1586706389685493, - 2157056599579261, - 1170692369685772, - ]), - xy2d: FieldElement51([ - 871476219910823, - 1878769545097794, - 2241832391238412, - 548957640601001, - 690047440233174, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 2548994545820755, - 1366347803776819, - 3552985325930849, - 561849853336293, - 1533554921345731, - ]), - y_minus_x: FieldElement51([ - 999628998628371, - 1132836708493400, - 2084741674517453, - 469343353015612, - 678782988708035, - ]), - xy2d: FieldElement51([ - 2189427607417022, - 699801937082607, - 412764402319267, - 1478091893643349, - 2244675696854460, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 3964091869651792, - 2456213404310121, - 3657538451018088, - 2660781114515010, - 3112882032961968, - ]), - y_minus_x: FieldElement51([ - 508561155940631, - 966928475686665, - 2236717801150132, - 424543858577297, - 2089272956986143, - ]), - xy2d: FieldElement51([ - 221245220129925, - 1156020201681217, - 491145634799213, - 542422431960839, - 828100817819207, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 2405556784925632, - 1299874139923976, - 2644898978945750, - 1058234455773021, - 996989038681183, - ]), - y_minus_x: FieldElement51([ - 559086812798481, - 573177704212711, - 1629737083816402, - 1399819713462595, - 1646954378266038, - ]), - xy2d: FieldElement51([ - 1887963056288059, - 228507035730124, - 1468368348640282, - 930557653420194, - 613513962454686, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 1224529808187534, - 1577022856702685, - 2206946542980843, - 625883007765001, - 2531730607197406, - ]), - y_minus_x: FieldElement51([ - 1076287717051609, - 1114455570543035, - 187297059715481, - 250446884292121, - 1885187512550540, - ]), - xy2d: FieldElement51([ - 902497362940219, - 76749815795675, - 1657927525633846, - 1420238379745202, - 1340321636548352, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 1129576631190765, - 3533793823712575, - 996844254743017, - 2509676177174497, - 3402650555740265, - ]), - y_minus_x: FieldElement51([ - 628740660038789, - 1943038498527841, - 467786347793886, - 1093341428303375, - 235413859513003, - ]), - xy2d: FieldElement51([ - 237425418909360, - 469614029179605, - 1512389769174935, - 1241726368345357, - 441602891065214, - ]), - }, - ]), - LookupTable([ - AffineNielsPoint { - y_plus_x: FieldElement51([ - 3988217766743784, - 726531315520507, - 1833335034432527, - 1629442561574747, - 2876218732971333, - ]), - y_minus_x: FieldElement51([ - 1960754663920689, - 497040957888962, - 1909832851283095, - 1271432136996826, - 2219780368020940, - ]), - xy2d: FieldElement51([ - 1537037379417136, - 1358865369268262, - 2130838645654099, - 828733687040705, - 1999987652890901, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 629042105241795, - 1098854999137608, - 887281544569320, - 3674901833560025, - 2259711072636808, - ]), - y_minus_x: FieldElement51([ - 1811562332665373, - 1501882019007673, - 2213763501088999, - 359573079719636, - 36370565049116, - ]), - xy2d: FieldElement51([ - 218907117361280, - 1209298913016966, - 1944312619096112, - 1130690631451061, - 1342327389191701, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 1369976867854685, - 1396479602419169, - 4017456468084104, - 2203659200586298, - 3250127649802489, - ]), - y_minus_x: FieldElement51([ - 2230701885562825, - 1348173180338974, - 2172856128624598, - 1426538746123771, - 444193481326151, - ]), - xy2d: FieldElement51([ - 784210426627951, - 918204562375674, - 1284546780452985, - 1324534636134684, - 1872449409642708, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 2571438643225542, - 2848082470493653, - 2037902696412607, - 1557219121643918, - 341938082688094, - ]), - y_minus_x: FieldElement51([ - 1901860206695915, - 2004489122065736, - 1625847061568236, - 973529743399879, - 2075287685312905, - ]), - xy2d: FieldElement51([ - 1371853944110545, - 1042332820512553, - 1949855697918254, - 1791195775521505, - 37487364849293, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 687200189577836, - 1082536651125675, - 2896024754556794, - 2592723009743198, - 2595381160432643, - ]), - y_minus_x: FieldElement51([ - 2082717129583892, - 27829425539422, - 145655066671970, - 1690527209845512, - 1865260509673478, - ]), - xy2d: FieldElement51([ - 1059729620568824, - 2163709103470266, - 1440302280256872, - 1769143160546397, - 869830310425069, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 3861316033464273, - 777277757338816, - 2101121130363987, - 550762194946473, - 1905542338659364, - ]), - y_minus_x: FieldElement51([ - 2024821921041576, - 426948675450149, - 595133284085473, - 471860860885970, - 600321679413000, - ]), - xy2d: FieldElement51([ - 598474602406721, - 1468128276358244, - 1191923149557635, - 1501376424093216, - 1281662691293476, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 1721138489890688, - 1264336102277790, - 2684864359106535, - 1359988423149465, - 3813671107094695, - ]), - y_minus_x: FieldElement51([ - 719520245587143, - 393380711632345, - 132350400863381, - 1543271270810729, - 1819543295798660, - ]), - xy2d: FieldElement51([ - 396397949784152, - 1811354474471839, - 1362679985304303, - 2117033964846756, - 498041172552279, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 1812471844975748, - 1856491995543149, - 126579494584102, - 3288044672967868, - 1975108050082549, - ]), - y_minus_x: FieldElement51([ - 650623932407995, - 1137551288410575, - 2125223403615539, - 1725658013221271, - 2134892965117796, - ]), - xy2d: FieldElement51([ - 522584000310195, - 1241762481390450, - 1743702789495384, - 2227404127826575, - 1686746002148897, - ]), - }, - ]), - LookupTable([ - AffineNielsPoint { - y_plus_x: FieldElement51([ - 427904865186293, - 1703211129693455, - 1585368107547509, - 3688784302429584, - 3012988348299225, - ]), - y_minus_x: FieldElement51([ - 318101947455002, - 248138407995851, - 1481904195303927, - 309278454311197, - 1258516760217879, - ]), - xy2d: FieldElement51([ - 1275068538599310, - 513726919533379, - 349926553492294, - 688428871968420, - 1702400196000666, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 3313663849950481, - 3213411074010628, - 2573659446386085, - 3297400443644764, - 1985130202504037, - ]), - y_minus_x: FieldElement51([ - 1558816436882417, - 1962896332636523, - 1337709822062152, - 1501413830776938, - 294436165831932, - ]), - xy2d: FieldElement51([ - 818359826554971, - 1862173000996177, - 626821592884859, - 573655738872376, - 1749691246745455, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 1988022651432119, - 3333911312271288, - 1834020786104820, - 3706626690108935, - 692929915223121, - ]), - y_minus_x: FieldElement51([ - 2146513703733331, - 584788900394667, - 464965657279958, - 2183973639356127, - 238371159456790, - ]), - xy2d: FieldElement51([ - 1129007025494441, - 2197883144413266, - 265142755578169, - 971864464758890, - 1983715884903702, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 1291366624493056, - 2633256531874362, - 1711482489312443, - 1815233647702022, - 3144079596677715, - ]), - y_minus_x: FieldElement51([ - 444548969917454, - 1452286453853356, - 2113731441506810, - 645188273895859, - 810317625309512, - ]), - xy2d: FieldElement51([ - 2242724082797924, - 1373354730327868, - 1006520110883049, - 2147330369940688, - 1151816104883620, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 3997520014069025, - 4163522956860564, - 2056329390702073, - 2607026987995097, - 3131032608056347, - ]), - y_minus_x: FieldElement51([ - 163723479936298, - 115424889803150, - 1156016391581227, - 1894942220753364, - 1970549419986329, - ]), - xy2d: FieldElement51([ - 681981452362484, - 267208874112496, - 1374683991933094, - 638600984916117, - 646178654558546, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 2265178468539480, - 2358037120714814, - 1944412051589650, - 4093776581610705, - 2482502633520820, - ]), - y_minus_x: FieldElement51([ - 260683893467075, - 854060306077237, - 913639551980112, - 4704576840123, - 280254810808712, - ]), - xy2d: FieldElement51([ - 715374893080287, - 1173334812210491, - 1806524662079626, - 1894596008000979, - 398905715033393, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 2751826223412909, - 3848231101880618, - 1420380351989369, - 3237011375206737, - 392444930785632, - ]), - y_minus_x: FieldElement51([ - 2096421546958141, - 1922523000950363, - 789831022876840, - 427295144688779, - 320923973161730, - ]), - xy2d: FieldElement51([ - 1927770723575450, - 1485792977512719, - 1850996108474547, - 551696031508956, - 2126047405475647, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 2112099158080129, - 2994370617594963, - 2258284371762679, - 1951119898618915, - 2344890196388664, - ]), - y_minus_x: FieldElement51([ - 383905201636970, - 859946997631870, - 855623867637644, - 1017125780577795, - 794250831877809, - ]), - xy2d: FieldElement51([ - 77571826285752, - 999304298101753, - 487841111777762, - 1038031143212339, - 339066367948762, - ]), - }, - ]), - LookupTable([ - AffineNielsPoint { - y_plus_x: FieldElement51([ - 2926794589205781, - 2517835660016036, - 826951213393477, - 1405007746162285, - 1781791018620876, - ]), - y_minus_x: FieldElement51([ - 1001412661522686, - 348196197067298, - 1666614366723946, - 888424995032760, - 580747687801357, - ]), - xy2d: FieldElement51([ - 1939560076207777, - 1409892634407635, - 552574736069277, - 383854338280405, - 190706709864139, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 2177087163428741, - 1439255351721944, - 3459870654068041, - 2230616362004768, - 1396886392021913, - ]), - y_minus_x: FieldElement51([ - 676962063230039, - 1880275537148808, - 2046721011602706, - 888463247083003, - 1318301552024067, - ]), - xy2d: FieldElement51([ - 1466980508178206, - 617045217998949, - 652303580573628, - 757303753529064, - 207583137376902, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 3762856566592150, - 2357202940576524, - 2745234706458093, - 1091943425335975, - 1802717338077427, - ]), - y_minus_x: FieldElement51([ - 1853982405405128, - 1878664056251147, - 1528011020803992, - 1019626468153565, - 1128438412189035, - ]), - xy2d: FieldElement51([ - 1963939888391106, - 293456433791664, - 697897559513649, - 985882796904380, - 796244541237972, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 2668570812315008, - 2641455366112301, - 1314476859406755, - 1749382513022778, - 3413705412424739, - ]), - y_minus_x: FieldElement51([ - 1428358296490651, - 1027115282420478, - 304840698058337, - 441410174026628, - 1819358356278573, - ]), - xy2d: FieldElement51([ - 204943430200135, - 1554861433819175, - 216426658514651, - 264149070665950, - 2047097371738319, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 1934415182909015, - 1393285083565062, - 2768209145458208, - 3409490548679139, - 2372839480279515, - ]), - y_minus_x: FieldElement51([ - 662035583584445, - 286736105093098, - 1131773000510616, - 818494214211439, - 472943792054479, - ]), - xy2d: FieldElement51([ - 665784778135882, - 1893179629898606, - 808313193813106, - 276797254706413, - 1563426179676396, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 945205108984213, - 2778077376644543, - 1324180513733565, - 1666970227868664, - 2405347422974421, - ]), - y_minus_x: FieldElement51([ - 2031433403516252, - 203996615228162, - 170487168837083, - 981513604791390, - 843573964916831, - ]), - xy2d: FieldElement51([ - 1476570093962618, - 838514669399805, - 1857930577281364, - 2017007352225784, - 317085545220047, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 1461557121912823, - 1600674043318359, - 2157134900399597, - 1670641601940616, - 2379565397488531, - ]), - y_minus_x: FieldElement51([ - 1293543509393474, - 2143624609202546, - 1058361566797508, - 214097127393994, - 946888515472729, - ]), - xy2d: FieldElement51([ - 357067959932916, - 1290876214345711, - 521245575443703, - 1494975468601005, - 800942377643885, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 2817916472785262, - 820247422481739, - 994464017954148, - 2578957425371613, - 2344391131796991, - ]), - y_minus_x: FieldElement51([ - 617256647603209, - 1652107761099439, - 1857213046645471, - 1085597175214970, - 817432759830522, - ]), - xy2d: FieldElement51([ - 771808161440705, - 1323510426395069, - 680497615846440, - 851580615547985, - 1320806384849017, - ]), - }, - ]), - LookupTable([ - AffineNielsPoint { - y_plus_x: FieldElement51([ - 1219260086131896, - 2898968820282063, - 2331400938444953, - 2161724213426747, - 2656661710745446, - ]), - y_minus_x: FieldElement51([ - 1327968293887866, - 1335500852943256, - 1401587164534264, - 558137311952440, - 1551360549268902, - ]), - xy2d: FieldElement51([ - 417621685193956, - 1429953819744454, - 396157358457099, - 1940470778873255, - 214000046234152, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 1268047918491954, - 2172375426948536, - 1533916099229249, - 1761293575457130, - 3842422480712013, - ]), - y_minus_x: FieldElement51([ - 1627072914981959, - 2211603081280073, - 1912369601616504, - 1191770436221309, - 2187309757525860, - ]), - xy2d: FieldElement51([ - 1149147819689533, - 378692712667677, - 828475842424202, - 2218619146419342, - 70688125792186, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 3551539230764990, - 3690416477138006, - 3788528892189659, - 2053896748919837, - 3260220846276494, - ]), - y_minus_x: FieldElement51([ - 2040723824657366, - 399555637875075, - 632543375452995, - 872649937008051, - 1235394727030233, - ]), - xy2d: FieldElement51([ - 2211311599327900, - 2139787259888175, - 938706616835350, - 12609661139114, - 2081897930719789, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 1324994503390431, - 2588782144267879, - 1183998925654176, - 3343454479598522, - 2300527487656566, - ]), - y_minus_x: FieldElement51([ - 1845522914617879, - 1222198248335542, - 150841072760134, - 1927029069940982, - 1189913404498011, - ]), - xy2d: FieldElement51([ - 1079559557592645, - 2215338383666441, - 1903569501302605, - 49033973033940, - 305703433934152, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 2346453219102138, - 3637921163538246, - 3313930291577009, - 2288353761164521, - 3085469462634093, - ]), - y_minus_x: FieldElement51([ - 1432015813136298, - 440364795295369, - 1395647062821501, - 1976874522764578, - 934452372723352, - ]), - xy2d: FieldElement51([ - 1296625309219774, - 2068273464883862, - 1858621048097805, - 1492281814208508, - 2235868981918946, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 1490330266465551, - 1858795661361448, - 3688040948655011, - 2546373032584894, - 3459939824714180, - ]), - y_minus_x: FieldElement51([ - 1282462923712748, - 741885683986255, - 2027754642827561, - 518989529541027, - 1826610009555945, - ]), - xy2d: FieldElement51([ - 1525827120027511, - 723686461809551, - 1597702369236987, - 244802101764964, - 1502833890372311, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 2365421849929742, - 3485539881431101, - 2925909765963743, - 2114345180342964, - 2418564326541511, - ]), - y_minus_x: FieldElement51([ - 2041668749310338, - 2184405322203901, - 1633400637611036, - 2110682505536899, - 2048144390084644, - ]), - xy2d: FieldElement51([ - 503058759232932, - 760293024620937, - 2027152777219493, - 666858468148475, - 1539184379870952, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 1916168475367211, - 3167426246226591, - 883217071712574, - 363427871374304, - 1976029821251593, - ]), - y_minus_x: FieldElement51([ - 678039535434506, - 570587290189340, - 1605302676614120, - 2147762562875701, - 1706063797091704, - ]), - xy2d: FieldElement51([ - 1439489648586438, - 2194580753290951, - 832380563557396, - 561521973970522, - 584497280718389, - ]), - }, - ]), - LookupTable([ - AffineNielsPoint { - y_plus_x: FieldElement51([ - 2439789269177838, - 681223515948274, - 1933493571072456, - 1872921007304880, - 2739962177820919, - ]), - y_minus_x: FieldElement51([ - 1413466089534451, - 410844090765630, - 1397263346404072, - 408227143123410, - 1594561803147811, - ]), - xy2d: FieldElement51([ - 2102170800973153, - 719462588665004, - 1479649438510153, - 1097529543970028, - 1302363283777685, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 3193865531532443, - 3321113493038208, - 2007341951411050, - 2322773230131539, - 1419433790163705, - ]), - y_minus_x: FieldElement51([ - 1146565545556377, - 1661971299445212, - 406681704748893, - 564452436406089, - 1109109865829139, - ]), - xy2d: FieldElement51([ - 2214421081775077, - 1165671861210569, - 1890453018796184, - 3556249878661, - 442116172656317, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 3005630360306059, - 1666955059895018, - 1530775289309243, - 3371786842789394, - 2164156153857579, - ]), - y_minus_x: FieldElement51([ - 615171919212796, - 1523849404854568, - 854560460547503, - 2067097370290715, - 1765325848586042, - ]), - xy2d: FieldElement51([ - 1094538949313667, - 1796592198908825, - 870221004284388, - 2025558921863561, - 1699010892802384, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 1951351290725195, - 1916457206844795, - 2449824998123274, - 1909076887557594, - 1938542290318919, - ]), - y_minus_x: FieldElement51([ - 1014323197538413, - 869150639940606, - 1756009942696599, - 1334952557375672, - 1544945379082874, - ]), - xy2d: FieldElement51([ - 764055910920305, - 1603590757375439, - 146805246592357, - 1843313433854297, - 954279890114939, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 80113526615731, - 764536758732259, - 3306939158785481, - 2721052465444637, - 2869697326116762, - ]), - y_minus_x: FieldElement51([ - 74497112547268, - 740094153192149, - 1745254631717581, - 727713886503130, - 1283034364416928, - ]), - xy2d: FieldElement51([ - 525892105991110, - 1723776830270342, - 1476444848991936, - 573789489857760, - 133864092632978, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 2794411533877810, - 1986812262899320, - 1162535242465837, - 2733298779828712, - 2796400347268869, - ]), - y_minus_x: FieldElement51([ - 64123227344372, - 1239927720647794, - 1360722983445904, - 222610813654661, - 62429487187991, - ]), - xy2d: FieldElement51([ - 1793193323953132, - 91096687857833, - 70945970938921, - 2158587638946380, - 1537042406482111, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 1895854577604590, - 3646695522634664, - 1728548428495943, - 3392664713925397, - 2815445147288308, - ]), - y_minus_x: FieldElement51([ - 141358280486863, - 91435889572504, - 1087208572552643, - 1829599652522921, - 1193307020643647, - ]), - xy2d: FieldElement51([ - 1611230858525381, - 950720175540785, - 499589887488610, - 2001656988495019, - 88977313255908, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 3440880315164906, - 2184348804772596, - 3292618539427567, - 2018318290311833, - 1712060030915354, - ]), - y_minus_x: FieldElement51([ - 873966876953756, - 1090638350350440, - 1708559325189137, - 672344594801910, - 1320437969700239, - ]), - xy2d: FieldElement51([ - 1508590048271766, - 1131769479776094, - 101550868699323, - 428297785557897, - 561791648661744, - ]), - }, - ]), - LookupTable([ - AffineNielsPoint { - y_plus_x: FieldElement51([ - 3008217384184691, - 2489682092917849, - 2136263418594015, - 1701968045454886, - 2955512998822720, - ]), - y_minus_x: FieldElement51([ - 1781187809325462, - 1697624151492346, - 1381393690939988, - 175194132284669, - 1483054666415238, - ]), - xy2d: FieldElement51([ - 2175517777364616, - 708781536456029, - 955668231122942, - 1967557500069555, - 2021208005604118, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 3366935780292116, - 2476017186636029, - 915967306279221, - 593866251291540, - 2813546907893254, - ]), - y_minus_x: FieldElement51([ - 1443163092879439, - 391875531646162, - 2180847134654632, - 464538543018753, - 1594098196837178, - ]), - xy2d: FieldElement51([ - 850858855888869, - 319436476624586, - 327807784938441, - 740785849558761, - 17128415486016, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 2132756334090048, - 2788047633840893, - 2300706964962114, - 2860273011285942, - 3513489358708031, - ]), - y_minus_x: FieldElement51([ - 1525176236978354, - 974205476721062, - 293436255662638, - 148269621098039, - 137961998433963, - ]), - xy2d: FieldElement51([ - 1121075518299410, - 2071745529082111, - 1265567917414828, - 1648196578317805, - 496232102750820, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 2374121042985030, - 3274721891178932, - 2001275453369483, - 2017441881607947, - 3245005694463250, - ]), - y_minus_x: FieldElement51([ - 654925550560074, - 1168810995576858, - 575655959430926, - 905758704861388, - 496774564663534, - ]), - xy2d: FieldElement51([ - 1954109525779738, - 2117022646152485, - 338102630417180, - 1194140505732026, - 107881734943492, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 1714785840001267, - 4288299832366837, - 1876380234251965, - 2056717182974196, - 1645855254384642, - ]), - y_minus_x: FieldElement51([ - 106431476499341, - 62482972120563, - 1513446655109411, - 807258751769522, - 538491469114, - ]), - xy2d: FieldElement51([ - 2002850762893643, - 1243624520538135, - 1486040410574605, - 2184752338181213, - 378495998083531, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 922510868424903, - 1089502620807680, - 402544072617374, - 1131446598479839, - 1290278588136533, - ]), - y_minus_x: FieldElement51([ - 1867998812076769, - 715425053580701, - 39968586461416, - 2173068014586163, - 653822651801304, - ]), - xy2d: FieldElement51([ - 162892278589453, - 182585796682149, - 75093073137630, - 497037941226502, - 133871727117371, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 4166396390264918, - 1608999621851577, - 1987629837704609, - 1519655314857977, - 1819193753409464, - ]), - y_minus_x: FieldElement51([ - 1949315551096831, - 1069003344994464, - 1939165033499916, - 1548227205730856, - 1933767655861407, - ]), - xy2d: FieldElement51([ - 1730519386931635, - 1393284965610134, - 1597143735726030, - 416032382447158, - 1429665248828629, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 360275475604546, - 2799635544748326, - 2467160717872776, - 2848446553564254, - 2584509464110332, - ]), - y_minus_x: FieldElement51([ - 47602113726801, - 1522314509708010, - 437706261372925, - 814035330438027, - 335930650933545, - ]), - xy2d: FieldElement51([ - 1291597595523886, - 1058020588994081, - 402837842324045, - 1363323695882781, - 2105763393033193, - ]), - }, - ]), - LookupTable([ - AffineNielsPoint { - y_plus_x: FieldElement51([ - 2361321796251793, - 3967057562270386, - 1112231216891515, - 2046641005101484, - 2386048970842261, - ]), - y_minus_x: FieldElement51([ - 2156991030936798, - 2227544497153325, - 1869050094431622, - 754875860479115, - 1754242344267058, - ]), - xy2d: FieldElement51([ - 1846089562873800, - 98894784984326, - 1412430299204844, - 171351226625762, - 1100604760929008, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 2335972195815721, - 2751510784385293, - 425749630620777, - 1762872794206857, - 2864642415813208, - ]), - y_minus_x: FieldElement51([ - 868309334532756, - 1703010512741873, - 1952690008738057, - 4325269926064, - 2071083554962116, - ]), - xy2d: FieldElement51([ - 523094549451158, - 401938899487815, - 1407690589076010, - 2022387426254453, - 158660516411257, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 612867287630009, - 2700012425789062, - 2823428891104443, - 1466796750919375, - 1728478129663858, - ]), - y_minus_x: FieldElement51([ - 1723848973783452, - 2208822520534681, - 1718748322776940, - 1974268454121942, - 1194212502258141, - ]), - xy2d: FieldElement51([ - 1254114807944608, - 977770684047110, - 2010756238954993, - 1783628927194099, - 1525962994408256, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 2484263871921055, - 1948628555342433, - 1835348780427694, - 1031609499437291, - 2316271920603621, - ]), - y_minus_x: FieldElement51([ - 767338676040683, - 754089548318405, - 1523192045639075, - 435746025122062, - 512692508440385, - ]), - xy2d: FieldElement51([ - 1255955808701983, - 1700487367990941, - 1166401238800299, - 1175121994891534, - 1190934801395380, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 2600943821853521, - 1337012557669161, - 1475912332999108, - 3573418268585706, - 2299411105589567, - ]), - y_minus_x: FieldElement51([ - 877519947135419, - 2172838026132651, - 272304391224129, - 1655143327559984, - 886229406429814, - ]), - xy2d: FieldElement51([ - 375806028254706, - 214463229793940, - 572906353144089, - 572168269875638, - 697556386112979, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 1168827102357825, - 823864273033637, - 4323338565789945, - 788062026895923, - 2851378154428610, - ]), - y_minus_x: FieldElement51([ - 1948116082078088, - 2054898304487796, - 2204939184983900, - 210526805152138, - 786593586607626, - ]), - xy2d: FieldElement51([ - 1915320147894736, - 156481169009469, - 655050471180417, - 592917090415421, - 2165897438660879, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 1726336468579724, - 1119932070398949, - 1929199510967666, - 2285718602008207, - 1836837863503149, - ]), - y_minus_x: FieldElement51([ - 829996854845988, - 217061778005138, - 1686565909803640, - 1346948817219846, - 1723823550730181, - ]), - xy2d: FieldElement51([ - 384301494966394, - 687038900403062, - 2211195391021739, - 254684538421383, - 1245698430589680, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 1247567493562669, - 4229981908141095, - 2435671288478202, - 806570235643434, - 2540261331753164, - ]), - y_minus_x: FieldElement51([ - 1449077384734201, - 38285445457996, - 2136537659177832, - 2146493000841573, - 725161151123125, - ]), - xy2d: FieldElement51([ - 1201928866368855, - 800415690605445, - 1703146756828343, - 997278587541744, - 1858284414104014, - ]), - }, - ]), - LookupTable([ - AffineNielsPoint { - y_plus_x: FieldElement51([ - 2608268623334125, - 3034173730618399, - 1718002439402869, - 3644022065904502, - 663171266061950, - ]), - y_minus_x: FieldElement51([ - 759628738230460, - 1012693474275852, - 353780233086498, - 246080061387552, - 2030378857679162, - ]), - xy2d: FieldElement51([ - 2040672435071076, - 888593182036908, - 1298443657189359, - 1804780278521327, - 354070726137060, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 1894938527423184, - 3715012855162525, - 2726210319182898, - 2499094776718546, - 877975941029127, - ]), - y_minus_x: FieldElement51([ - 207937160991127, - 12966911039119, - 820997788283092, - 1010440472205286, - 1701372890140810, - ]), - xy2d: FieldElement51([ - 218882774543183, - 533427444716285, - 1233243976733245, - 435054256891319, - 1509568989549904, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 4140638349397055, - 3303977572025869, - 3465353617009382, - 2420981822812579, - 2715174081801119, - ]), - y_minus_x: FieldElement51([ - 299137589460312, - 1594371588983567, - 868058494039073, - 257771590636681, - 1805012993142921, - ]), - xy2d: FieldElement51([ - 1806842755664364, - 2098896946025095, - 1356630998422878, - 1458279806348064, - 347755825962072, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 1402334161391744, - 3811883484731547, - 1008585416617746, - 1147797150908892, - 1420416683642459, - ]), - y_minus_x: FieldElement51([ - 665506704253369, - 273770475169863, - 799236974202630, - 848328990077558, - 1811448782807931, - ]), - xy2d: FieldElement51([ - 1468412523962641, - 771866649897997, - 1931766110147832, - 799561180078482, - 524837559150077, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 2223212657821831, - 2882216061048914, - 2144451165500327, - 3068710944633039, - 3276150872095279, - ]), - y_minus_x: FieldElement51([ - 1266603897524861, - 156378408858100, - 1275649024228779, - 447738405888420, - 253186462063095, - ]), - xy2d: FieldElement51([ - 2022215964509735, - 136144366993649, - 1800716593296582, - 1193970603800203, - 871675847064218, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 1862751661970309, - 851596246739884, - 1519315554814041, - 3794598280232697, - 3669775149586767, - ]), - y_minus_x: FieldElement51([ - 1228168094547481, - 334133883362894, - 587567568420081, - 433612590281181, - 603390400373205, - ]), - xy2d: FieldElement51([ - 121893973206505, - 1843345804916664, - 1703118377384911, - 497810164760654, - 101150811654673, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 2710146069631716, - 2542709749304591, - 1452768413850678, - 2802722688939463, - 1537286854336537, - ]), - y_minus_x: FieldElement51([ - 584322311184395, - 380661238802118, - 114839394528060, - 655082270500073, - 2111856026034852, - ]), - xy2d: FieldElement51([ - 996965581008991, - 2148998626477022, - 1012273164934654, - 1073876063914522, - 1688031788934939, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 3175286832534829, - 2085106799623354, - 2779882615305384, - 1606206360876187, - 2987706905397772, - ]), - y_minus_x: FieldElement51([ - 1697697887804317, - 1335343703828273, - 831288615207040, - 949416685250051, - 288760277392022, - ]), - xy2d: FieldElement51([ - 1419122478109648, - 1325574567803701, - 602393874111094, - 2107893372601700, - 1314159682671307, - ]), - }, - ]), - LookupTable([ - AffineNielsPoint { - y_plus_x: FieldElement51([ - 2201150872731785, - 2180241023425241, - 2349463270108411, - 1633405770247823, - 3100744856129234, - ]), - y_minus_x: FieldElement51([ - 1173339555550611, - 818605084277583, - 47521504364289, - 924108720564965, - 735423405754506, - ]), - xy2d: FieldElement51([ - 830104860549448, - 1886653193241086, - 1600929509383773, - 1475051275443631, - 286679780900937, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 3828911108518224, - 3282698983453994, - 2396700729978777, - 4216472406664814, - 2820189914640497, - ]), - y_minus_x: FieldElement51([ - 278388655910247, - 487143369099838, - 927762205508727, - 181017540174210, - 1616886700741287, - ]), - xy2d: FieldElement51([ - 1191033906638969, - 940823957346562, - 1606870843663445, - 861684761499847, - 658674867251089, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 1875032594195527, - 1427106132796197, - 2976536204647406, - 3153660325729987, - 2887068310954007, - ]), - y_minus_x: FieldElement51([ - 622869792298357, - 1903919278950367, - 1922588621661629, - 1520574711600434, - 1087100760174640, - ]), - xy2d: FieldElement51([ - 25465949416618, - 1693639527318811, - 1526153382657203, - 125943137857169, - 145276964043999, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 2466539671654587, - 920212862967914, - 4191701364657517, - 3463662605460468, - 2336897329405367, - ]), - y_minus_x: FieldElement51([ - 2006245852772938, - 734762734836159, - 254642929763427, - 1406213292755966, - 239303749517686, - ]), - xy2d: FieldElement51([ - 1619678837192149, - 1919424032779215, - 1357391272956794, - 1525634040073113, - 1310226789796241, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 3292563523447371, - 1704449869235351, - 2857062884141577, - 1998838089036354, - 1312142911487502, - ]), - y_minus_x: FieldElement51([ - 1996723311435669, - 1844342766567060, - 985455700466044, - 1165924681400960, - 311508689870129, - ]), - xy2d: FieldElement51([ - 43173156290518, - 2202883069785309, - 1137787467085917, - 1733636061944606, - 1394992037553852, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 670078326344559, - 2807454838744604, - 2723759199967685, - 2141455487356408, - 849015953823125, - ]), - y_minus_x: FieldElement51([ - 2197214573372804, - 794254097241315, - 1030190060513737, - 267632515541902, - 2040478049202624, - ]), - xy2d: FieldElement51([ - 1812516004670529, - 1609256702920783, - 1706897079364493, - 258549904773295, - 996051247540686, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 1540374301420565, - 1764656898914615, - 1810104162020396, - 3175608592848336, - 2916189887881826, - ]), - y_minus_x: FieldElement51([ - 1323460699404750, - 1262690757880991, - 871777133477900, - 1060078894988977, - 1712236889662886, - ]), - xy2d: FieldElement51([ - 1696163952057966, - 1391710137550823, - 608793846867416, - 1034391509472039, - 1780770894075012, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 1367603834210822, - 4383788460268472, - 890353773628143, - 1908908219165595, - 2522636708938139, - ]), - y_minus_x: FieldElement51([ - 597536315471731, - 40375058742586, - 1942256403956049, - 1185484645495932, - 312666282024145, - ]), - xy2d: FieldElement51([ - 1919411405316294, - 1234508526402192, - 1066863051997083, - 1008444703737597, - 1348810787701552, - ]), - }, - ]), - LookupTable([ - AffineNielsPoint { - y_plus_x: FieldElement51([ - 2102881477513865, - 3822074379630609, - 1573617900503707, - 2270462449417831, - 2232324307922097, - ]), - y_minus_x: FieldElement51([ - 1853931367696942, - 8107973870707, - 350214504129299, - 775206934582587, - 1752317649166792, - ]), - xy2d: FieldElement51([ - 1417148368003523, - 721357181628282, - 505725498207811, - 373232277872983, - 261634707184480, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 2186733281493248, - 2250694917008620, - 1014829812957440, - 2731797975137637, - 2335366007561721, - ]), - y_minus_x: FieldElement51([ - 1268116367301224, - 560157088142809, - 802626839600444, - 2210189936605713, - 1129993785579988, - ]), - xy2d: FieldElement51([ - 615183387352312, - 917611676109240, - 878893615973325, - 978940963313282, - 938686890583575, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 522024729211672, - 3296859129001056, - 1892245413707789, - 1907891107684253, - 2059998109500714, - ]), - y_minus_x: FieldElement51([ - 1799679152208884, - 912132775900387, - 25967768040979, - 432130448590461, - 274568990261996, - ]), - xy2d: FieldElement51([ - 98698809797682, - 2144627600856209, - 1907959298569602, - 811491302610148, - 1262481774981493, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 1791451399743152, - 1713538728337276, - 2370149810942738, - 1882306388849953, - 158235232210248, - ]), - y_minus_x: FieldElement51([ - 1217809823321928, - 2173947284933160, - 1986927836272325, - 1388114931125539, - 12686131160169, - ]), - xy2d: FieldElement51([ - 1650875518872272, - 1136263858253897, - 1732115601395988, - 734312880662190, - 1252904681142109, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 2624786269799113, - 2777230729143418, - 2116279931702134, - 2753222527273063, - 1907002872974924, - ]), - y_minus_x: FieldElement51([ - 803147181835288, - 868941437997146, - 316299302989663, - 943495589630550, - 571224287904572, - ]), - xy2d: FieldElement51([ - 227742695588364, - 1776969298667369, - 628602552821802, - 457210915378118, - 2041906378111140, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 815000523470260, - 3164885502413555, - 3303859931956420, - 1345536665214222, - 541623413135555, - ]), - y_minus_x: FieldElement51([ - 1580216071604333, - 1877997504342444, - 857147161260913, - 703522726778478, - 2182763974211603, - ]), - xy2d: FieldElement51([ - 1870080310923419, - 71988220958492, - 1783225432016732, - 615915287105016, - 1035570475990230, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 2982787564515398, - 857613889540279, - 1083813157271766, - 1002817255970169, - 1719228484436074, - ]), - y_minus_x: FieldElement51([ - 377616581647602, - 1581980403078513, - 804044118130621, - 2034382823044191, - 643844048472185, - ]), - xy2d: FieldElement51([ - 176957326463017, - 1573744060478586, - 528642225008045, - 1816109618372371, - 1515140189765006, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 1888911448245718, - 3638910709296328, - 4176303607751676, - 1731539523700948, - 2230378382645454, - ]), - y_minus_x: FieldElement51([ - 443392177002051, - 233793396845137, - 2199506622312416, - 1011858706515937, - 974676837063129, - ]), - xy2d: FieldElement51([ - 1846351103143623, - 1949984838808427, - 671247021915253, - 1946756846184401, - 1929296930380217, - ]), - }, - ]), - LookupTable([ - AffineNielsPoint { - y_plus_x: FieldElement51([ - 849646212451983, - 1410198775302919, - 2325567699868943, - 1641663456615811, - 3014056086137659, - ]), - y_minus_x: FieldElement51([ - 692017667358279, - 723305578826727, - 1638042139863265, - 748219305990306, - 334589200523901, - ]), - xy2d: FieldElement51([ - 22893968530686, - 2235758574399251, - 1661465835630252, - 925707319443452, - 1203475116966621, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 3053098849470395, - 3985092410411378, - 1664508947088595, - 2719548934677170, - 3899298398220870, - ]), - y_minus_x: FieldElement51([ - 903105258014366, - 427141894933047, - 561187017169777, - 1884330244401954, - 1914145708422219, - ]), - xy2d: FieldElement51([ - 1344191060517578, - 1960935031767890, - 1518838929955259, - 1781502350597190, - 1564784025565682, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 2925523165433334, - 1979969272514922, - 3427087126180756, - 1187589090978665, - 1881897672213940, - ]), - y_minus_x: FieldElement51([ - 1917185587363432, - 1098342571752737, - 5935801044414, - 2000527662351839, - 1538640296181569, - ]), - xy2d: FieldElement51([ - 2495540013192, - 678856913479236, - 224998292422872, - 219635787698590, - 1972465269000940, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 271413961212179, - 3604851875156899, - 2596511104968730, - 2014925838520661, - 2006221033113941, - ]), - y_minus_x: FieldElement51([ - 194583029968109, - 514316781467765, - 829677956235672, - 1676415686873082, - 810104584395840, - ]), - xy2d: FieldElement51([ - 1980510813313589, - 1948645276483975, - 152063780665900, - 129968026417582, - 256984195613935, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 1860190562533083, - 1936576191345085, - 2712900106391212, - 1811043097042829, - 3209286562992083, - ]), - y_minus_x: FieldElement51([ - 796664815624365, - 1543160838872951, - 1500897791837765, - 1667315977988401, - 599303877030711, - ]), - xy2d: FieldElement51([ - 1151480509533204, - 2136010406720455, - 738796060240027, - 319298003765044, - 1150614464349587, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 1731069268103131, - 2987442261301335, - 1364750481334267, - 2669032653668119, - 3178908082812908, - ]), - y_minus_x: FieldElement51([ - 1017222050227968, - 1987716148359, - 2234319589635701, - 621282683093392, - 2132553131763026, - ]), - xy2d: FieldElement51([ - 1567828528453324, - 1017807205202360, - 565295260895298, - 829541698429100, - 307243822276582, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 249079270936229, - 1501514259790706, - 3199709537890096, - 944551802437486, - 2804458577667728, - ]), - y_minus_x: FieldElement51([ - 2089966982947227, - 1854140343916181, - 2151980759220007, - 2139781292261749, - 158070445864917, - ]), - xy2d: FieldElement51([ - 1338766321464554, - 1906702607371284, - 1519569445519894, - 115384726262267, - 1393058953390992, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 3616421371950629, - 3764188048593604, - 1926731583198685, - 2041482526432505, - 3172200936019022, - ]), - y_minus_x: FieldElement51([ - 1884844597333588, - 601480070269079, - 620203503079537, - 1079527400117915, - 1202076693132015, - ]), - xy2d: FieldElement51([ - 840922919763324, - 727955812569642, - 1303406629750194, - 522898432152867, - 294161410441865, - ]), - }, - ]), - LookupTable([ - AffineNielsPoint { - y_plus_x: FieldElement51([ - 2605560604520539, - 1598361541848742, - 3374705511887547, - 4174333403844152, - 2670907514351827, - ]), - y_minus_x: FieldElement51([ - 359856369838236, - 180914355488683, - 861726472646627, - 218807937262986, - 575626773232501, - ]), - xy2d: FieldElement51([ - 755467689082474, - 909202735047934, - 730078068932500, - 936309075711518, - 2007798262842972, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 1609384177904054, - 2614544999293875, - 1335318541768200, - 3052765584121496, - 2799677792952659, - ]), - y_minus_x: FieldElement51([ - 984339177776787, - 815727786505884, - 1645154585713747, - 1659074964378553, - 1686601651984156, - ]), - xy2d: FieldElement51([ - 1697863093781930, - 599794399429786, - 1104556219769607, - 830560774794755, - 12812858601017, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 1168737550514982, - 897832437380552, - 463140296333799, - 2554364413707795, - 2008360505135500, - ]), - y_minus_x: FieldElement51([ - 1856930662813910, - 678090852002597, - 1920179140755167, - 1259527833759868, - 55540971895511, - ]), - xy2d: FieldElement51([ - 1158643631044921, - 476554103621892, - 178447851439725, - 1305025542653569, - 103433927680625, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 2176793111709008, - 3828525530035639, - 2009350167273522, - 2012390194631546, - 2125297410909580, - ]), - y_minus_x: FieldElement51([ - 825403285195098, - 2144208587560784, - 1925552004644643, - 1915177840006985, - 1015952128947864, - ]), - xy2d: FieldElement51([ - 1807108316634472, - 1534392066433717, - 347342975407218, - 1153820745616376, - 7375003497471, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 3234860815484973, - 2683011703586488, - 2201903782961092, - 3069193724749589, - 2214616493042166, - ]), - y_minus_x: FieldElement51([ - 228567918409756, - 865093958780220, - 358083886450556, - 159617889659320, - 1360637926292598, - ]), - xy2d: FieldElement51([ - 234147501399755, - 2229469128637390, - 2175289352258889, - 1397401514549353, - 1885288963089922, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 3363562226636810, - 2504649386192636, - 3300514047508588, - 2397910909286693, - 1237505378776769, - ]), - y_minus_x: FieldElement51([ - 1113790697840279, - 1051167139966244, - 1045930658550944, - 2011366241542643, - 1686166824620755, - ]), - xy2d: FieldElement51([ - 1054097349305049, - 1872495070333352, - 182121071220717, - 1064378906787311, - 100273572924182, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 3558210666856834, - 1627717417672446, - 2302783034773665, - 1109249951172249, - 3122001602766640, - ]), - y_minus_x: FieldElement51([ - 104233794644221, - 1548919791188248, - 2224541913267306, - 2054909377116478, - 1043803389015153, - ]), - xy2d: FieldElement51([ - 216762189468802, - 707284285441622, - 190678557969733, - 973969342604308, - 1403009538434867, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 3530824104723725, - 2596576648903557, - 2525521909702446, - 4086000250496689, - 634517197663803, - ]), - y_minus_x: FieldElement51([ - 343805853118335, - 1302216857414201, - 566872543223541, - 2051138939539004, - 321428858384280, - ]), - xy2d: FieldElement51([ - 470067171324852, - 1618629234173951, - 2000092177515639, - 7307679772789, - 1117521120249968, - ]), - }, - ]), - LookupTable([ - AffineNielsPoint { - y_plus_x: FieldElement51([ - 2529951391976704, - 1810282338562946, - 1771599529530998, - 3635459223356879, - 2937173228157088, - ]), - y_minus_x: FieldElement51([ - 577009397403102, - 1791440261786291, - 2177643735971638, - 174546149911960, - 1412505077782326, - ]), - xy2d: FieldElement51([ - 893719721537457, - 1201282458018197, - 1522349501711173, - 58011597740583, - 1130406465887139, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 412607348255434, - 1280455764199780, - 2233277987330768, - 2265979894086913, - 2583384512102412, - ]), - y_minus_x: FieldElement51([ - 262483770854550, - 990511055108216, - 526885552771698, - 571664396646158, - 354086190278723, - ]), - xy2d: FieldElement51([ - 1820352417585487, - 24495617171480, - 1547899057533253, - 10041836186225, - 480457105094042, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 2023310314989233, - 2889705151211129, - 2106474638900686, - 2809620524769320, - 1687858215057825, - ]), - y_minus_x: FieldElement51([ - 1144168702609745, - 604444390410187, - 1544541121756138, - 1925315550126027, - 626401428894002, - ]), - xy2d: FieldElement51([ - 1922168257351784, - 2018674099908659, - 1776454117494445, - 956539191509034, - 36031129147635, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 2796444352433270, - 1039872944430373, - 3128550222815858, - 2962457525011798, - 3468752501170219, - ]), - y_minus_x: FieldElement51([ - 58242421545916, - 2035812695641843, - 2118491866122923, - 1191684463816273, - 46921517454099, - ]), - xy2d: FieldElement51([ - 272268252444639, - 1374166457774292, - 2230115177009552, - 1053149803909880, - 1354288411641016, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 1857910905368338, - 1754729879288912, - 3137745277795125, - 1516096106802165, - 1602902393369811, - ]), - y_minus_x: FieldElement51([ - 1193437069800958, - 901107149704790, - 999672920611411, - 477584824802207, - 364239578697845, - ]), - xy2d: FieldElement51([ - 886299989548838, - 1538292895758047, - 1590564179491896, - 1944527126709657, - 837344427345298, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 3006358179063534, - 1712186480903617, - 3955456640022779, - 3002110732175033, - 2770795853936147, - ]), - y_minus_x: FieldElement51([ - 1309847803895382, - 1462151862813074, - 211370866671570, - 1544595152703681, - 1027691798954090, - ]), - xy2d: FieldElement51([ - 803217563745370, - 1884799722343599, - 1357706345069218, - 2244955901722095, - 730869460037413, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 2941099284981214, - 1831210565161070, - 3626987155270686, - 3358084791231418, - 1893781834054268, - ]), - y_minus_x: FieldElement51([ - 696351368613042, - 1494385251239250, - 738037133616932, - 636385507851544, - 927483222611406, - ]), - xy2d: FieldElement51([ - 1949114198209333, - 1104419699537997, - 783495707664463, - 1747473107602770, - 2002634765788641, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 1607325776830197, - 2782683755100581, - 1451089452727894, - 3833490970768671, - 496100432831153, - ]), - y_minus_x: FieldElement51([ - 1068900648804224, - 2006891997072550, - 1134049269345549, - 1638760646180091, - 2055396084625778, - ]), - xy2d: FieldElement51([ - 2222475519314561, - 1870703901472013, - 1884051508440561, - 1344072275216753, - 1318025677799069, - ]), - }, - ]), - LookupTable([ - AffineNielsPoint { - y_plus_x: FieldElement51([ - 155711679280637, - 681100400509288, - 389811735211209, - 2135723811340709, - 2660533024889373, - ]), - y_minus_x: FieldElement51([ - 7813206966729, - 194444201427550, - 2071405409526507, - 1065605076176312, - 1645486789731291, - ]), - xy2d: FieldElement51([ - 16625790644959, - 1647648827778410, - 1579910185572704, - 436452271048548, - 121070048451050, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 3289062842237779, - 2820185594063076, - 2549752917829677, - 3810384325616458, - 2238221839292470, - ]), - y_minus_x: FieldElement51([ - 190565267697443, - 672855706028058, - 338796554369226, - 337687268493904, - 853246848691734, - ]), - xy2d: FieldElement51([ - 1763863028400139, - 766498079432444, - 1321118624818005, - 69494294452268, - 858786744165651, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 3543856582248253, - 1456632109855637, - 3352431060735432, - 1386133165675320, - 3484698163879000, - ]), - y_minus_x: FieldElement51([ - 366253102478259, - 525676242508811, - 1449610995265438, - 1183300845322183, - 185960306491545, - ]), - xy2d: FieldElement51([ - 28315355815982, - 460422265558930, - 1799675876678724, - 1969256312504498, - 1051823843138725, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 2408714813047231, - 3857948219405196, - 1665208410108429, - 2569443092377519, - 1383783705665319, - ]), - y_minus_x: FieldElement51([ - 54684536365732, - 2210010038536222, - 1194984798155308, - 535239027773705, - 1516355079301361, - ]), - xy2d: FieldElement51([ - 1484387703771650, - 198537510937949, - 2186282186359116, - 617687444857508, - 647477376402122, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 2147715541830533, - 2751832352131065, - 2898179830570073, - 2604027669016369, - 1488268620408051, - ]), - y_minus_x: FieldElement51([ - 159386186465542, - 1877626593362941, - 618737197060512, - 1026674284330807, - 1158121760792685, - ]), - xy2d: FieldElement51([ - 1744544377739822, - 1964054180355661, - 1685781755873170, - 2169740670377448, - 1286112621104591, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 2333777063470241, - 3919742931398333, - 3920783633320113, - 1605016835177614, - 1353960708075544, - ]), - y_minus_x: FieldElement51([ - 1602253788689063, - 439542044889886, - 2220348297664483, - 657877410752869, - 157451572512238, - ]), - xy2d: FieldElement51([ - 1029287186166717, - 65860128430192, - 525298368814832, - 1491902500801986, - 1461064796385400, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 2660016802414475, - 2121095722306988, - 913562102267595, - 1879708920318308, - 2492861262121979, - ]), - y_minus_x: FieldElement51([ - 1185483484383269, - 1356339572588553, - 584932367316448, - 102132779946470, - 1792922621116791, - ]), - xy2d: FieldElement51([ - 1966196870701923, - 2230044620318636, - 1425982460745905, - 261167817826569, - 46517743394330, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 2358877405280588, - 3136759755857592, - 2279106683482647, - 2224911448949389, - 3216151871930471, - ]), - y_minus_x: FieldElement51([ - 1730194207717538, - 431790042319772, - 1831515233279467, - 1372080552768581, - 1074513929381760, - ]), - xy2d: FieldElement51([ - 1450880638731607, - 1019861580989005, - 1229729455116861, - 1174945729836143, - 826083146840706, - ]), - }, - ]), - LookupTable([ - AffineNielsPoint { - y_plus_x: FieldElement51([ - 1899935429242705, - 1602068751520477, - 940583196550370, - 2334230882739107, - 1540863155745695, - ]), - y_minus_x: FieldElement51([ - 2136688454840028, - 2099509000964294, - 1690800495246475, - 1217643678575476, - 828720645084218, - ]), - xy2d: FieldElement51([ - 765548025667841, - 462473984016099, - 998061409979798, - 546353034089527, - 2212508972466858, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 2298375097456408, - 3144370785258318, - 1281983193144089, - 1491520128287375, - 75847005908304, - ]), - y_minus_x: FieldElement51([ - 1801436127943107, - 1734436817907890, - 1268728090345068, - 167003097070711, - 2233597765834956, - ]), - xy2d: FieldElement51([ - 1997562060465113, - 1048700225534011, - 7615603985628, - 1855310849546841, - 2242557647635213, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 1161017320376250, - 2744424393854291, - 2169815802355236, - 3228296595417790, - 1770879511019628, - ]), - y_minus_x: FieldElement51([ - 1357044908364776, - 729130645262438, - 1762469072918979, - 1365633616878458, - 181282906404941, - ]), - xy2d: FieldElement51([ - 1080413443139865, - 1155205815510486, - 1848782073549786, - 622566975152580, - 124965574467971, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 1184526762066993, - 247622751762817, - 2943928830891604, - 3071818503097743, - 2188697339828084, - ]), - y_minus_x: FieldElement51([ - 2020536369003019, - 202261491735136, - 1053169669150884, - 2056531979272544, - 778165514694311, - ]), - xy2d: FieldElement51([ - 237404399610207, - 1308324858405118, - 1229680749538400, - 720131409105291, - 1958958863624906, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 2767383321724075, - 2269456792542436, - 1717918437373988, - 1568052070792483, - 2298775616809171, - ]), - y_minus_x: FieldElement51([ - 281527309158085, - 36970532401524, - 866906920877543, - 2222282602952734, - 1289598729589882, - ]), - xy2d: FieldElement51([ - 1278207464902042, - 494742455008756, - 1262082121427081, - 1577236621659884, - 1888786707293291, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 353042527954210, - 1830056151907359, - 1111731275799225, - 2426760769524072, - 404312815582674, - ]), - y_minus_x: FieldElement51([ - 2064251142068628, - 1666421603389706, - 1419271365315441, - 468767774902855, - 191535130366583, - ]), - xy2d: FieldElement51([ - 1716987058588002, - 1859366439773457, - 1767194234188234, - 64476199777924, - 1117233614485261, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 3236091949205521, - 2386938060636506, - 2220652137473166, - 1722843421165029, - 2442282371698157, - ]), - y_minus_x: FieldElement51([ - 298845952651262, - 1166086588952562, - 1179896526238434, - 1347812759398693, - 1412945390096208, - ]), - xy2d: FieldElement51([ - 1143239552672925, - 906436640714209, - 2177000572812152, - 2075299936108548, - 325186347798433, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 2972824668060020, - 2936287674948563, - 3625238557779406, - 2193186935276994, - 1387043709851261, - ]), - y_minus_x: FieldElement51([ - 418098668140962, - 715065997721283, - 1471916138376055, - 2168570337288357, - 937812682637044, - ]), - xy2d: FieldElement51([ - 1043584187226485, - 2143395746619356, - 2209558562919611, - 482427979307092, - 847556718384018, - ]), - }, - ]), - LookupTable([ - AffineNielsPoint { - y_plus_x: FieldElement51([ - 1248731221520740, - 1465200936117687, - 2792603306395388, - 2304778448366139, - 2513234303861356, - ]), - y_minus_x: FieldElement51([ - 1057329623869501, - 620334067429122, - 461700859268034, - 2012481616501857, - 297268569108938, - ]), - xy2d: FieldElement51([ - 1055352180870759, - 1553151421852298, - 1510903185371259, - 1470458349428097, - 1226259419062731, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 3744788603986897, - 3042126439258578, - 3441906842094992, - 3641194565844440, - 3872208010289441, - ]), - y_minus_x: FieldElement51([ - 47000654413729, - 1004754424173864, - 1868044813557703, - 173236934059409, - 588771199737015, - ]), - xy2d: FieldElement51([ - 30498470091663, - 1082245510489825, - 576771653181956, - 806509986132686, - 1317634017056939, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 2672107869436803, - 3745154677001249, - 2417006535213335, - 4136645508605033, - 2065456951573058, - ]), - y_minus_x: FieldElement51([ - 1115636332012334, - 1854340990964155, - 83792697369514, - 1972177451994021, - 457455116057587, - ]), - xy2d: FieldElement51([ - 1698968457310898, - 1435137169051090, - 1083661677032510, - 938363267483709, - 340103887207182, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 1995325341336555, - 911500251774648, - 2415810569088940, - 855378419194761, - 3825401211214090, - ]), - y_minus_x: FieldElement51([ - 241719380661528, - 310028521317150, - 1215881323380194, - 1408214976493624, - 2141142156467363, - ]), - xy2d: FieldElement51([ - 1315157046163473, - 727368447885818, - 1363466668108618, - 1668921439990361, - 1398483384337907, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 2326829491984875, - 3267188020145720, - 1849729037055211, - 4191614430138232, - 2696204044080201, - ]), - y_minus_x: FieldElement51([ - 2053597130993710, - 2024431685856332, - 2233550957004860, - 2012407275509545, - 872546993104440, - ]), - xy2d: FieldElement51([ - 1217269667678610, - 599909351968693, - 1390077048548598, - 1471879360694802, - 739586172317596, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 3970118453066023, - 1560510726633957, - 3156262694845170, - 1418028351780051, - 2346204163137185, - ]), - y_minus_x: FieldElement51([ - 2132502667405250, - 214379346175414, - 1502748313768060, - 1960071701057800, - 1353971822643138, - ]), - xy2d: FieldElement51([ - 319394212043702, - 2127459436033571, - 717646691535162, - 663366796076914, - 318459064945314, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 2657789238608841, - 1960452633787082, - 2919148848086913, - 3744474074452359, - 1451061489880786, - ]), - y_minus_x: FieldElement51([ - 947085906234007, - 323284730494107, - 1485778563977200, - 728576821512394, - 901584347702286, - ]), - xy2d: FieldElement51([ - 1575783124125742, - 2126210792434375, - 1569430791264065, - 1402582372904727, - 1891780248341114, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 3090232019245924, - 4249503325136911, - 3270591693593114, - 1662001808174330, - 2330127946643001, - ]), - y_minus_x: FieldElement51([ - 739152638255629, - 2074935399403557, - 505483666745895, - 1611883356514088, - 628654635394878, - ]), - xy2d: FieldElement51([ - 1822054032121349, - 643057948186973, - 7306757352712, - 577249257962099, - 284735863382083, - ]), - }, - ]), - LookupTable([ - AffineNielsPoint { - y_plus_x: FieldElement51([ - 3618358370049178, - 1448606567552085, - 3730680834630016, - 2417602993041145, - 1115718458123497, - ]), - y_minus_x: FieldElement51([ - 204146226972102, - 1630511199034723, - 2215235214174763, - 174665910283542, - 956127674017216, - ]), - xy2d: FieldElement51([ - 1562934578796716, - 1070893489712745, - 11324610642270, - 958989751581897, - 2172552325473805, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 1770564423056008, - 2987323445349813, - 1326060113795288, - 1509650369341127, - 2317692235267932, - ]), - y_minus_x: FieldElement51([ - 623682558650637, - 1337866509471512, - 990313350206649, - 1314236615762469, - 1164772974270275, - ]), - xy2d: FieldElement51([ - 223256821462517, - 723690150104139, - 1000261663630601, - 933280913953265, - 254872671543046, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 1969087237026022, - 2876595539132372, - 1335555107635968, - 2069986355593023, - 3963899963027150, - ]), - y_minus_x: FieldElement51([ - 1236103475266979, - 1837885883267218, - 1026072585230455, - 1025865513954973, - 1801964901432134, - ]), - xy2d: FieldElement51([ - 1115241013365517, - 1712251818829143, - 2148864332502771, - 2096001471438138, - 2235017246626125, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 3551068012286861, - 2047148477845620, - 2165648650132450, - 1612539282026145, - 2765997725314138, - ]), - y_minus_x: FieldElement51([ - 118352772338543, - 1067608711804704, - 1434796676193498, - 1683240170548391, - 230866769907437, - ]), - xy2d: FieldElement51([ - 1850689576796636, - 1601590730430274, - 1139674615958142, - 1954384401440257, - 76039205311, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 1723387471374172, - 3249101280723658, - 2785727448808904, - 2272728458379212, - 1756575222802512, - ]), - y_minus_x: FieldElement51([ - 2146711623855116, - 503278928021499, - 625853062251406, - 1109121378393107, - 1033853809911861, - ]), - xy2d: FieldElement51([ - 571005965509422, - 2005213373292546, - 1016697270349626, - 56607856974274, - 914438579435146, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 1346698876211176, - 2076651707527589, - 3336561384795453, - 2517134292513653, - 1068954492309670, - ]), - y_minus_x: FieldElement51([ - 1769967932677654, - 1695893319756416, - 1151863389675920, - 1781042784397689, - 400287774418285, - ]), - xy2d: FieldElement51([ - 1851867764003121, - 403841933237558, - 820549523771987, - 761292590207581, - 1743735048551143, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 410915148140008, - 2107072311871739, - 3256167275561751, - 2351484709082008, - 1180818713503223, - ]), - y_minus_x: FieldElement51([ - 285945406881439, - 648174397347453, - 1098403762631981, - 1366547441102991, - 1505876883139217, - ]), - xy2d: FieldElement51([ - 672095903120153, - 1675918957959872, - 636236529315028, - 1569297300327696, - 2164144194785875, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 1902708175321798, - 3287143344600686, - 1178560808893262, - 2552895497743394, - 1280977479761117, - ]), - y_minus_x: FieldElement51([ - 1615357281742403, - 404257611616381, - 2160201349780978, - 1160947379188955, - 1578038619549541, - ]), - xy2d: FieldElement51([ - 2013087639791217, - 822734930507457, - 1785668418619014, - 1668650702946164, - 389450875221715, - ]), - }, - ]), - LookupTable([ - AffineNielsPoint { - y_plus_x: FieldElement51([ - 2705718263383616, - 2358206633614248, - 2072540975937134, - 308588860670238, - 1304394580755385, - ]), - y_minus_x: FieldElement51([ - 1295082798350326, - 2091844511495996, - 1851348972587817, - 3375039684596, - 789440738712837, - ]), - xy2d: FieldElement51([ - 2083069137186154, - 848523102004566, - 993982213589257, - 1405313299916317, - 1532824818698468, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 3747761112537659, - 1397203457344778, - 4026750030752190, - 2391102557240943, - 2318403398028034, - ]), - y_minus_x: FieldElement51([ - 1782411379088302, - 1096724939964781, - 27593390721418, - 542241850291353, - 1540337798439873, - ]), - xy2d: FieldElement51([ - 693543956581437, - 171507720360750, - 1557908942697227, - 1074697073443438, - 1104093109037196, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 345288228393400, - 3351443383432420, - 2386681722088990, - 1740551994106739, - 2500011992985018, - ]), - y_minus_x: FieldElement51([ - 231429562203065, - 1526290236421172, - 2021375064026423, - 1520954495658041, - 806337791525116, - ]), - xy2d: FieldElement51([ - 1079623667189886, - 872403650198613, - 766894200588288, - 2163700860774109, - 2023464507911816, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 854645372543796, - 1936406001954827, - 2403260476226501, - 3077125552956802, - 1554306377287555, - ]), - y_minus_x: FieldElement51([ - 1497138821904622, - 1044820250515590, - 1742593886423484, - 1237204112746837, - 849047450816987, - ]), - xy2d: FieldElement51([ - 667962773375330, - 1897271816877105, - 1399712621683474, - 1143302161683099, - 2081798441209593, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 2378947665252234, - 1936114012888109, - 1704424366552046, - 3108474694401560, - 2968403435020606, - ]), - y_minus_x: FieldElement51([ - 1072409664800960, - 2146937497077528, - 1508780108920651, - 935767602384853, - 1112800433544068, - ]), - xy2d: FieldElement51([ - 333549023751292, - 280219272863308, - 2104176666454852, - 1036466864875785, - 536135186520207, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 2625466093568366, - 2398257055215356, - 2555916080813104, - 2667888562832962, - 3510376944868638, - ]), - y_minus_x: FieldElement51([ - 1186115062588401, - 2251609796968486, - 1098944457878953, - 1153112761201374, - 1791625503417267, - ]), - xy2d: FieldElement51([ - 1870078460219737, - 2129630962183380, - 852283639691142, - 292865602592851, - 401904317342226, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 1361070124828016, - 815664541425524, - 3278598711049919, - 1951790935390646, - 2807674705520038, - ]), - y_minus_x: FieldElement51([ - 1546301003424277, - 459094500062839, - 1097668518375311, - 1780297770129643, - 720763293687608, - ]), - xy2d: FieldElement51([ - 1212405311403990, - 1536693382542438, - 61028431067459, - 1863929423417129, - 1223219538638038, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 1294303766540260, - 3435357279640341, - 3134071170918340, - 2315654383110622, - 2213283684565086, - ]), - y_minus_x: FieldElement51([ - 339050984211414, - 601386726509773, - 413735232134068, - 966191255137228, - 1839475899458159, - ]), - xy2d: FieldElement51([ - 235605972169408, - 2174055643032978, - 1538335001838863, - 1281866796917192, - 1815940222628465, - ]), - }, - ]), - LookupTable([ - AffineNielsPoint { - y_plus_x: FieldElement51([ - 1632352921721536, - 1833328609514701, - 2092779091951987, - 4175756015558474, - 2210068022482918, - ]), - y_minus_x: FieldElement51([ - 35271216625062, - 1712350667021807, - 983664255668860, - 98571260373038, - 1232645608559836, - ]), - xy2d: FieldElement51([ - 1998172393429622, - 1798947921427073, - 784387737563581, - 1589352214827263, - 1589861734168180, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 1733739258725305, - 2283515530744786, - 2453769758904107, - 3243892858242237, - 1194308773174555, - ]), - y_minus_x: FieldElement51([ - 846415389605137, - 746163495539180, - 829658752826080, - 592067705956946, - 957242537821393, - ]), - xy2d: FieldElement51([ - 1758148849754419, - 619249044817679, - 168089007997045, - 1371497636330523, - 1867101418880350, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 2578433797894864, - 2513559319756263, - 1700682323676192, - 1577907266349064, - 3469447477068264, - ]), - y_minus_x: FieldElement51([ - 1714182387328607, - 1477856482074168, - 574895689942184, - 2159118410227270, - 1555532449716575, - ]), - xy2d: FieldElement51([ - 853828206885131, - 998498946036955, - 1835887550391235, - 207627336608048, - 258363815956050, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 2392941288336925, - 3488528558590503, - 2894901233585134, - 1646615130509172, - 1208239602291765, - ]), - y_minus_x: FieldElement51([ - 1501663228068911, - 1354879465566912, - 1444432675498247, - 897812463852601, - 855062598754348, - ]), - xy2d: FieldElement51([ - 714380763546606, - 1032824444965790, - 1774073483745338, - 1063840874947367, - 1738680636537158, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 1640635546696233, - 2884968766877360, - 2212651044092395, - 2282390772269100, - 2620315074574625, - ]), - y_minus_x: FieldElement51([ - 1171650314802029, - 1567085444565577, - 1453660792008405, - 757914533009261, - 1619511342778196, - ]), - xy2d: FieldElement51([ - 420958967093237, - 971103481109486, - 2169549185607107, - 1301191633558497, - 1661514101014240, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 3158923465503550, - 1332556122804145, - 4075855067109735, - 3619414031128206, - 1982558335973171, - ]), - y_minus_x: FieldElement51([ - 1121533090144639, - 1021251337022187, - 110469995947421, - 1511059774758394, - 2110035908131662, - ]), - xy2d: FieldElement51([ - 303213233384524, - 2061932261128138, - 352862124777736, - 40828818670255, - 249879468482660, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 856559257852200, - 2760317478634258, - 3629993581580163, - 3975258940632376, - 1962275756614520, - ]), - y_minus_x: FieldElement51([ - 1445691340537320, - 40614383122127, - 402104303144865, - 485134269878232, - 1659439323587426, - ]), - xy2d: FieldElement51([ - 20057458979482, - 1183363722525800, - 2140003847237215, - 2053873950687614, - 2112017736174909, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 2228654250927986, - 3735391177100515, - 1368661293910955, - 3328311098862539, - 526650682059607, - ]), - y_minus_x: FieldElement51([ - 709481497028540, - 531682216165724, - 316963769431931, - 1814315888453765, - 258560242424104, - ]), - xy2d: FieldElement51([ - 1053447823660455, - 1955135194248683, - 1010900954918985, - 1182614026976701, - 1240051576966610, - ]), - }, - ]), - LookupTable([ - AffineNielsPoint { - y_plus_x: FieldElement51([ - 1957943897155478, - 1788667368028035, - 2389492723714354, - 2252839333292309, - 3078204576998275, - ]), - y_minus_x: FieldElement51([ - 1848942433095597, - 1582009882530495, - 1849292741020143, - 1068498323302788, - 2001402229799484, - ]), - xy2d: FieldElement51([ - 1528282417624269, - 2142492439828191, - 2179662545816034, - 362568973150328, - 1591374675250271, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 2411826493119617, - 2484141002903963, - 2149181472355544, - 598041771119831, - 2435658815595421, - ]), - y_minus_x: FieldElement51([ - 2013278155187349, - 662660471354454, - 793981225706267, - 411706605985744, - 804490933124791, - ]), - xy2d: FieldElement51([ - 2051892037280204, - 488391251096321, - 2230187337030708, - 930221970662692, - 679002758255210, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 1530723630438670, - 875873929577927, - 2593359947955236, - 2701702933216000, - 1055551308214178, - ]), - y_minus_x: FieldElement51([ - 1461835919309432, - 1955256480136428, - 180866187813063, - 1551979252664528, - 557743861963950, - ]), - xy2d: FieldElement51([ - 359179641731115, - 1324915145732949, - 902828372691474, - 294254275669987, - 1887036027752957, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 4295071423139571, - 2038225437857463, - 1317528426475850, - 1398989128982787, - 2027639881006861, - ]), - y_minus_x: FieldElement51([ - 2072902725256516, - 312132452743412, - 309930885642209, - 996244312618453, - 1590501300352303, - ]), - xy2d: FieldElement51([ - 1397254305160710, - 695734355138021, - 2233992044438756, - 1776180593969996, - 1085588199351115, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 2692366865016258, - 2506694600041928, - 2745669038615469, - 1556322069683365, - 3819256354004466, - ]), - y_minus_x: FieldElement51([ - 1950722461391320, - 1907845598854797, - 1822757481635527, - 2121567704750244, - 73811931471221, - ]), - xy2d: FieldElement51([ - 387139307395758, - 2058036430315676, - 1220915649965325, - 1794832055328951, - 1230009312169328, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 1765973779329498, - 2911143873132225, - 2271621715291913, - 3553728154996461, - 3368065817761132, - ]), - y_minus_x: FieldElement51([ - 1127572801181483, - 1224743760571696, - 1276219889847274, - 1529738721702581, - 1589819666871853, - ]), - xy2d: FieldElement51([ - 2181229378964934, - 2190885205260020, - 1511536077659137, - 1246504208580490, - 668883326494241, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 2689666469258543, - 2920826224880015, - 2333696811665585, - 523874406393177, - 2496851874620484, - ]), - y_minus_x: FieldElement51([ - 1975438052228868, - 1071801519999806, - 594652299224319, - 1877697652668809, - 1489635366987285, - ]), - xy2d: FieldElement51([ - 958592545673770, - 233048016518599, - 851568750216589, - 567703851596087, - 1740300006094761, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 2014540178270324, - 192672779514432, - 2465676996326778, - 2194819933853410, - 1716422829364835, - ]), - y_minus_x: FieldElement51([ - 1540769606609725, - 2148289943846077, - 1597804156127445, - 1230603716683868, - 815423458809453, - ]), - xy2d: FieldElement51([ - 1738560251245018, - 1779576754536888, - 1783765347671392, - 1880170990446751, - 1088225159617541, - ]), - }, - ]), - LookupTable([ - AffineNielsPoint { - y_plus_x: FieldElement51([ - 2911103727614740, - 1956447718227572, - 1830568515922666, - 3092868863429656, - 1669607124206367, - ]), - y_minus_x: FieldElement51([ - 1143465490433355, - 1532194726196059, - 1093276745494697, - 481041706116088, - 2121405433561163, - ]), - xy2d: FieldElement51([ - 1686424298744462, - 1451806974487153, - 266296068846582, - 1834686947542675, - 1720762336132256, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 3141016840074207, - 3295090436969907, - 3107924901237156, - 1669272323124635, - 1603340330827879, - ]), - y_minus_x: FieldElement51([ - 1206396181488998, - 333158148435054, - 1402633492821422, - 1120091191722026, - 1945474114550509, - ]), - xy2d: FieldElement51([ - 766720088232571, - 1512222781191002, - 1189719893490790, - 2091302129467914, - 2141418006894941, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 2671463460991841, - 1998875112167986, - 3678399683938955, - 3406728169064757, - 2738338345823434, - ]), - y_minus_x: FieldElement51([ - 938160078005954, - 1421776319053174, - 1941643234741774, - 180002183320818, - 1414380336750546, - ]), - xy2d: FieldElement51([ - 398001940109652, - 1577721237663248, - 1012748649830402, - 1540516006905144, - 1011684812884559, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 1653276489969611, - 2257881638852872, - 1921777941170835, - 1604139841794531, - 3113010867325889, - ]), - y_minus_x: FieldElement51([ - 996661541407379, - 1455877387952927, - 744312806857277, - 139213896196746, - 1000282908547789, - ]), - xy2d: FieldElement51([ - 1450817495603008, - 1476865707053229, - 1030490562252053, - 620966950353376, - 1744760161539058, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 2811528223687828, - 2288856475326432, - 2038622963352005, - 1637244893271723, - 3278365165924196, - ]), - y_minus_x: FieldElement51([ - 962165956135846, - 1116599660248791, - 182090178006815, - 1455605467021751, - 196053588803284, - ]), - xy2d: FieldElement51([ - 796863823080135, - 1897365583584155, - 420466939481601, - 2165972651724672, - 932177357788289, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 877047233620613, - 1375632631944375, - 2895573425567369, - 2911822552533124, - 2271153746017078, - ]), - y_minus_x: FieldElement51([ - 2216943882299338, - 394841323190322, - 2222656898319671, - 558186553950529, - 1077236877025190, - ]), - xy2d: FieldElement51([ - 801118384953213, - 1914330175515892, - 574541023311511, - 1471123787903705, - 1526158900256288, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 3201417702772463, - 2207116611267330, - 3164719852826535, - 2752958352884036, - 2314162374456719, - ]), - y_minus_x: FieldElement51([ - 1474518386765335, - 1760793622169197, - 1157399790472736, - 1622864308058898, - 165428294422792, - ]), - xy2d: FieldElement51([ - 1961673048027128, - 102619413083113, - 1051982726768458, - 1603657989805485, - 1941613251499678, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 1401939116319247, - 2587106153588320, - 2323846009771033, - 862423201496005, - 3102318568216632, - ]), - y_minus_x: FieldElement51([ - 1234706593321979, - 1083343891215917, - 898273974314935, - 1640859118399498, - 157578398571149, - ]), - xy2d: FieldElement51([ - 1143483057726416, - 1992614991758919, - 674268662140796, - 1773370048077526, - 674318359920189, - ]), - }, - ]), - LookupTable([ - AffineNielsPoint { - y_plus_x: FieldElement51([ - 1835401379538542, - 173900035308392, - 818247630716732, - 4013900225838034, - 1021506399448290, - ]), - y_minus_x: FieldElement51([ - 1506632088156630, - 2127481795522179, - 513812919490255, - 140643715928370, - 442476620300318, - ]), - xy2d: FieldElement51([ - 2056683376856736, - 219094741662735, - 2193541883188309, - 1841182310235800, - 556477468664293, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 3566819241596075, - 1049075855992602, - 4318372866671791, - 2518704280870781, - 2040482348591519, - ]), - y_minus_x: FieldElement51([ - 94096246544434, - 922482381166992, - 24517828745563, - 2139430508542503, - 2097139044231004, - ]), - xy2d: FieldElement51([ - 537697207950515, - 1399352016347350, - 1563663552106345, - 2148749520888918, - 549922092988516, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 1747985413252415, - 680511052635695, - 1809559829982725, - 2846074064615302, - 2453472984431229, - ]), - y_minus_x: FieldElement51([ - 323583936109569, - 1973572998577657, - 1192219029966558, - 79354804385273, - 1374043025560347, - ]), - xy2d: FieldElement51([ - 213277331329947, - 416202017849623, - 1950535221091783, - 1313441578103244, - 2171386783823658, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 2440888617915079, - 993969372859109, - 3147669935222235, - 3799101348983503, - 1477373024911349, - ]), - y_minus_x: FieldElement51([ - 1620578418245010, - 541035331188469, - 2235785724453865, - 2154865809088198, - 1974627268751826, - ]), - xy2d: FieldElement51([ - 1346805451740245, - 1350981335690626, - 942744349501813, - 2155094562545502, - 1012483751693409, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 2107080134091762, - 1132567062788208, - 1824935377687210, - 769194804343737, - 1857941799971888, - ]), - y_minus_x: FieldElement51([ - 1074666112436467, - 249279386739593, - 1174337926625354, - 1559013532006480, - 1472287775519121, - ]), - xy2d: FieldElement51([ - 1872620123779532, - 1892932666768992, - 1921559078394978, - 1270573311796160, - 1438913646755037, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 3089190001333428, - 3264053113908846, - 989780015893986, - 1351393287739814, - 2580427560230798, - ]), - y_minus_x: FieldElement51([ - 1028328827183114, - 1711043289969857, - 1350832470374933, - 1923164689604327, - 1495656368846911, - ]), - xy2d: FieldElement51([ - 1900828492104143, - 430212361082163, - 687437570852799, - 832514536673512, - 1685641495940794, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 3094432661621646, - 605670026766215, - 290836444839585, - 2415010588577604, - 2213815011799644, - ]), - y_minus_x: FieldElement51([ - 1176336383453996, - 1725477294339771, - 12700622672454, - 678015708818208, - 162724078519879, - ]), - xy2d: FieldElement51([ - 1448049969043497, - 1789411762943521, - 385587766217753, - 90201620913498, - 832999441066823, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 2767886146978542, - 2240508292484615, - 3603469341851756, - 3475055379001735, - 3002035638112385, - ]), - y_minus_x: FieldElement51([ - 1263624896582495, - 1102602401673328, - 526302183714372, - 2152015839128799, - 1483839308490010, - ]), - xy2d: FieldElement51([ - 442991718646863, - 1599275157036458, - 1925389027579192, - 899514691371390, - 350263251085160, - ]), - }, - ]), - LookupTable([ - AffineNielsPoint { - y_plus_x: FieldElement51([ - 1689713572022124, - 2845654372939621, - 3229894858477217, - 1985127338729498, - 3927868934032873, - ]), - y_minus_x: FieldElement51([ - 1557207018622683, - 340631692799603, - 1477725909476187, - 614735951619419, - 2033237123746766, - ]), - xy2d: FieldElement51([ - 968764929340557, - 1225534776710944, - 662967304013036, - 1155521416178595, - 791142883466590, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 1487081286167458, - 3244839255500182, - 1792378982844639, - 2950452258685122, - 2153908693179753, - ]), - y_minus_x: FieldElement51([ - 1123181311102823, - 685575944875442, - 507605465509927, - 1412590462117473, - 568017325228626, - ]), - xy2d: FieldElement51([ - 560258797465417, - 2193971151466401, - 1824086900849026, - 579056363542056, - 1690063960036441, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 1918407319222397, - 2605567366745211, - 1930426334528098, - 1564816146005724, - 4113142195393344, - ]), - y_minus_x: FieldElement51([ - 2131325168777276, - 1176636658428908, - 1756922641512981, - 1390243617176012, - 1966325177038383, - ]), - xy2d: FieldElement51([ - 2063958120364491, - 2140267332393533, - 699896251574968, - 273268351312140, - 375580724713232, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 2024297515263178, - 2668759143407935, - 3330814048702549, - 2423412039258430, - 1031677520051052, - ]), - y_minus_x: FieldElement51([ - 2033900009388450, - 1744902869870788, - 2190580087917640, - 1949474984254121, - 231049754293748, - ]), - xy2d: FieldElement51([ - 343868674606581, - 550155864008088, - 1450580864229630, - 481603765195050, - 896972360018042, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 2151139328380127, - 2566545695770176, - 2311556639460451, - 1676664391494650, - 2048348075599360, - ]), - y_minus_x: FieldElement51([ - 1528930066340597, - 1605003907059576, - 1055061081337675, - 1458319101947665, - 1234195845213142, - ]), - xy2d: FieldElement51([ - 830430507734812, - 1780282976102377, - 1425386760709037, - 362399353095425, - 2168861579799910, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 3407562046415562, - 980662895504005, - 2053766700883521, - 2742766027762854, - 2762205690726604, - ]), - y_minus_x: FieldElement51([ - 1683750316716132, - 652278688286128, - 1221798761193539, - 1897360681476669, - 319658166027343, - ]), - xy2d: FieldElement51([ - 618808732869972, - 72755186759744, - 2060379135624181, - 1730731526741822, - 48862757828238, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 3714971784278753, - 3394840525452699, - 614590986558882, - 1409210575145591, - 1882816996436803, - ]), - y_minus_x: FieldElement51([ - 2230133264691131, - 563950955091024, - 2042915975426398, - 827314356293472, - 672028980152815, - ]), - xy2d: FieldElement51([ - 264204366029760, - 1654686424479449, - 2185050199932931, - 2207056159091748, - 506015669043634, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 1784446333136550, - 1973746527984364, - 334856327359575, - 3408569589569858, - 3275749938360725, - ]), - y_minus_x: FieldElement51([ - 2065270940578383, - 31477096270353, - 306421879113491, - 181958643936686, - 1907105536686083, - ]), - xy2d: FieldElement51([ - 1496516440779464, - 1748485652986458, - 872778352227340, - 818358834654919, - 97932669284220, - ]), - }, - ]), - LookupTable([ - AffineNielsPoint { - y_plus_x: FieldElement51([ - 2723435829455580, - 2924255216478824, - 1804995246884102, - 1842309243470804, - 3753662318666930, - ]), - y_minus_x: FieldElement51([ - 1013216974933691, - 538921919682598, - 1915776722521558, - 1742822441583877, - 1886550687916656, - ]), - xy2d: FieldElement51([ - 2094270000643336, - 303971879192276, - 40801275554748, - 649448917027930, - 1818544418535447, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 2241737709499146, - 549397817447461, - 838180519319392, - 1725686958520781, - 3957438894582995, - ]), - y_minus_x: FieldElement51([ - 1216074541925116, - 50120933933509, - 1565829004133810, - 721728156134580, - 349206064666188, - ]), - xy2d: FieldElement51([ - 948617110470858, - 346222547451945, - 1126511960599975, - 1759386906004538, - 493053284802266, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 1454933046815146, - 3126495827951610, - 1467170975468587, - 1432316382418897, - 2111710746366763, - ]), - y_minus_x: FieldElement51([ - 2105387117364450, - 1996463405126433, - 1303008614294500, - 851908115948209, - 1353742049788635, - ]), - xy2d: FieldElement51([ - 750300956351719, - 1487736556065813, - 15158817002104, - 1511998221598392, - 971739901354129, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 1874648163531674, - 2124487685930551, - 1810030029384882, - 918400043048335, - 2838148440985898, - ]), - y_minus_x: FieldElement51([ - 1235084464747900, - 1166111146432082, - 1745394857881591, - 1405516473883040, - 4463504151617, - ]), - xy2d: FieldElement51([ - 1663810156463827, - 327797390285791, - 1341846161759410, - 1964121122800605, - 1747470312055380, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 660005247548214, - 2071860029952887, - 3610548013635355, - 911703252219106, - 3266179736709079, - ]), - y_minus_x: FieldElement51([ - 2206641276178231, - 1690587809721504, - 1600173622825126, - 2156096097634421, - 1106822408548216, - ]), - xy2d: FieldElement51([ - 1344788193552206, - 1949552134239140, - 1735915881729557, - 675891104100469, - 1834220014427292, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 1920949492387945, - 2410685102072778, - 2322108077349280, - 2877838278583064, - 3719881539786256, - ]), - y_minus_x: FieldElement51([ - 622221042073383, - 1210146474039168, - 1742246422343683, - 1403839361379025, - 417189490895736, - ]), - xy2d: FieldElement51([ - 22727256592983, - 168471543384997, - 1324340989803650, - 1839310709638189, - 504999476432775, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 3565040332441556, - 1721896294296941, - 2304063388272514, - 2065069734239231, - 3056710287109878, - ]), - y_minus_x: FieldElement51([ - 1337466662091884, - 1287645354669772, - 2018019646776184, - 652181229374245, - 898011753211715, - ]), - xy2d: FieldElement51([ - 1969792547910734, - 779969968247557, - 2011350094423418, - 1823964252907487, - 1058949448296945, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 2459143550747250, - 1118176942430252, - 3010694408233412, - 806764629546265, - 1157700123092949, - ]), - y_minus_x: FieldElement51([ - 1273565321399022, - 1638509681964574, - 759235866488935, - 666015124346707, - 897983460943405, - ]), - xy2d: FieldElement51([ - 1717263794012298, - 1059601762860786, - 1837819172257618, - 1054130665797229, - 680893204263559, - ]), - }, - ]), - LookupTable([ - AffineNielsPoint { - y_plus_x: FieldElement51([ - 2237039662793603, - 2249022333361206, - 2058613546633703, - 2401253908530527, - 2215176649164581, - ]), - y_minus_x: FieldElement51([ - 79472182719605, - 1851130257050174, - 1825744808933107, - 821667333481068, - 781795293511946, - ]), - xy2d: FieldElement51([ - 755822026485370, - 152464789723500, - 1178207602290608, - 410307889503239, - 156581253571278, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 3669985309815545, - 2736319981413860, - 3898537095128197, - 3653287498355512, - 1349185550126960, - ]), - y_minus_x: FieldElement51([ - 1495380034400429, - 325049476417173, - 46346894893933, - 1553408840354856, - 828980101835683, - ]), - xy2d: FieldElement51([ - 1280337889310282, - 2070832742866672, - 1640940617225222, - 2098284908289951, - 450929509534434, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 2659503167684029, - 2378371955168899, - 2537839641198868, - 1999255076709337, - 2030511179441770, - ]), - y_minus_x: FieldElement51([ - 1254958221100483, - 1153235960999843, - 942907704968834, - 637105404087392, - 1149293270147267, - ]), - xy2d: FieldElement51([ - 894249020470196, - 400291701616810, - 406878712230981, - 1599128793487393, - 1145868722604026, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 3749755063888563, - 2361916158338507, - 1128535642171975, - 1900106496009660, - 2381592531146157, - ]), - y_minus_x: FieldElement51([ - 452487513298665, - 1352120549024569, - 1173495883910956, - 1999111705922009, - 367328130454226, - ]), - xy2d: FieldElement51([ - 1717539401269642, - 1475188995688487, - 891921989653942, - 836824441505699, - 1885988485608364, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 3493583935107776, - 2439136865632830, - 3370281625921440, - 2680547565621609, - 2282158712612572, - ]), - y_minus_x: FieldElement51([ - 2022432361201842, - 1088816090685051, - 1977843398539868, - 1854834215890724, - 564238862029357, - ]), - xy2d: FieldElement51([ - 938868489100585, - 1100285072929025, - 1017806255688848, - 1957262154788833, - 152787950560442, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 3119119231364171, - 2872271776627789, - 2477832016990963, - 2593801257642876, - 1761675818237335, - ]), - y_minus_x: FieldElement51([ - 1295072362439987, - 931227904689414, - 1355731432641687, - 922235735834035, - 892227229410209, - ]), - xy2d: FieldElement51([ - 1680989767906154, - 535362787031440, - 2136691276706570, - 1942228485381244, - 1267350086882274, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 2617818047455756, - 2684460443440843, - 2378209521329782, - 1973842949591661, - 2897427157127624, - ]), - y_minus_x: FieldElement51([ - 535509430575217, - 546885533737322, - 1524675609547799, - 2138095752851703, - 1260738089896827, - ]), - xy2d: FieldElement51([ - 1159906385590467, - 2198530004321610, - 714559485023225, - 81880727882151, - 1484020820037082, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 1377485731340769, - 2046328105512000, - 1802058637158797, - 2313945950453421, - 1356993908853900, - ]), - y_minus_x: FieldElement51([ - 2013612215646735, - 1830770575920375, - 536135310219832, - 609272325580394, - 270684344495013, - ]), - xy2d: FieldElement51([ - 1237542585982777, - 2228682050256790, - 1385281931622824, - 593183794882890, - 493654978552689, - ]), - }, - ]), - LookupTable([ - AffineNielsPoint { - y_plus_x: FieldElement51([ - 2299141301692989, - 1891414891220256, - 983894663308928, - 2427961581972066, - 3378060928864955, - ]), - y_minus_x: FieldElement51([ - 1694030170963455, - 502038567066200, - 1691160065225467, - 949628319562187, - 275110186693066, - ]), - xy2d: FieldElement51([ - 1124515748676336, - 1661673816593408, - 1499640319059718, - 1584929449166988, - 558148594103306, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 1784525599998356, - 1619698033617383, - 2097300287550715, - 2510065271789004, - 1905684794832757, - ]), - y_minus_x: FieldElement51([ - 1288941072872766, - 931787902039402, - 190731008859042, - 2006859954667190, - 1005931482221702, - ]), - xy2d: FieldElement51([ - 1465551264822703, - 152905080555927, - 680334307368453, - 173227184634745, - 666407097159852, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 2111017076203943, - 3630560299479595, - 1248583954016455, - 3604089008549670, - 1895180776543895, - ]), - y_minus_x: FieldElement51([ - 171348223915638, - 662766099800389, - 462338943760497, - 466917763340314, - 656911292869115, - ]), - xy2d: FieldElement51([ - 488623681976577, - 866497561541722, - 1708105560937768, - 1673781214218839, - 1506146329818807, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 2412225278142205, - 950394373239688, - 2682296937026182, - 711676555398831, - 320964687779005, - ]), - y_minus_x: FieldElement51([ - 988979367990485, - 1359729327576302, - 1301834257246029, - 294141160829308, - 29348272277475, - ]), - xy2d: FieldElement51([ - 1434382743317910, - 100082049942065, - 221102347892623, - 186982837860588, - 1305765053501834, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 2205916462268190, - 2751663643476068, - 961960554686615, - 2409862576442233, - 1841471168298304, - ]), - y_minus_x: FieldElement51([ - 1191737341426592, - 1847042034978363, - 1382213545049056, - 1039952395710448, - 788812858896859, - ]), - xy2d: FieldElement51([ - 1346965964571152, - 1291881610839830, - 2142916164336056, - 786821641205979, - 1571709146321039, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 787164375951248, - 2454669019058437, - 3608390234717387, - 1431233331032509, - 786341368775957, - ]), - y_minus_x: FieldElement51([ - 492448143532951, - 304105152670757, - 1761767168301056, - 233782684697790, - 1981295323106089, - ]), - xy2d: FieldElement51([ - 665807507761866, - 1343384868355425, - 895831046139653, - 439338948736892, - 1986828765695105, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 3007896024559801, - 1721699973539148, - 2510565115413133, - 1390588532210644, - 1212530909934781, - ]), - y_minus_x: FieldElement51([ - 852891097972275, - 1816988871354562, - 1543772755726524, - 1174710635522444, - 202129090724628, - ]), - xy2d: FieldElement51([ - 1205281565824323, - 22430498399418, - 992947814485516, - 1392458699738672, - 688441466734558, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 3302427242100220, - 1955849529137134, - 2171162376368357, - 2343545681983462, - 447733118757825, - ]), - y_minus_x: FieldElement51([ - 1287181461435438, - 622722465530711, - 880952150571872, - 741035693459198, - 311565274989772, - ]), - xy2d: FieldElement51([ - 1003649078149734, - 545233927396469, - 1849786171789880, - 1318943684880434, - 280345687170552, - ]), - }, - ]), - ]); - -/// Odd multiples of the basepoint `[B, 3B, 5B, 7B, 9B, 11B, 13B, 15B, ..., 127B]`. -pub(crate) const AFFINE_ODD_MULTIPLES_OF_BASEPOINT: NafLookupTable8 = - NafLookupTable8([ - AffineNielsPoint { - y_plus_x: FieldElement51([ - 3540182452943730, - 2497478415033846, - 2521227595762870, - 1462984067271729, - 2389212253076811, - ]), - y_minus_x: FieldElement51([ - 62697248952638, - 204681361388450, - 631292143396476, - 338455783676468, - 1213667448819585, - ]), - xy2d: FieldElement51([ - 301289933810280, - 1259582250014073, - 1422107436869536, - 796239922652654, - 1953934009299142, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 1601611775252272, - 1720807796594148, - 1132070835939856, - 3512254832574799, - 2147779492816910, - ]), - y_minus_x: FieldElement51([ - 316559037616741, - 2177824224946892, - 1459442586438991, - 1461528397712656, - 751590696113597, - ]), - xy2d: FieldElement51([ - 1850748884277385, - 1200145853858453, - 1068094770532492, - 672251375690438, - 1586055907191707, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 769950342298400, - 2384754244604994, - 3095885746880802, - 3225892188161580, - 2977876099231263, - ]), - y_minus_x: FieldElement51([ - 425251763115706, - 608463272472562, - 442562545713235, - 837766094556764, - 374555092627893, - ]), - xy2d: FieldElement51([ - 1086255230780037, - 274979815921559, - 1960002765731872, - 929474102396301, - 1190409889297339, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 2916800678241215, - 2065379846933858, - 2622030924071124, - 2602788184473875, - 1233371373142984, - ]), - y_minus_x: FieldElement51([ - 2019367628972465, - 676711900706637, - 110710997811333, - 1108646842542025, - 517791959672113, - ]), - xy2d: FieldElement51([ - 965130719900578, - 247011430587952, - 526356006571389, - 91986625355052, - 2157223321444601, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 1802695059464988, - 1664899123557221, - 2845359304426105, - 2160434469266658, - 3179370264440279, - ]), - y_minus_x: FieldElement51([ - 1725674970513508, - 1933645953859181, - 1542344539275782, - 1767788773573747, - 1297447965928905, - ]), - xy2d: FieldElement51([ - 1381809363726107, - 1430341051343062, - 2061843536018959, - 1551778050872521, - 2036394857967624, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 4222693909998302, - 2779866139518454, - 1619374932191226, - 2207306624415883, - 1169170329061080, - ]), - y_minus_x: FieldElement51([ - 2070390218572616, - 1458919061857835, - 624171843017421, - 1055332792707765, - 433987520732508, - ]), - xy2d: FieldElement51([ - 893653801273833, - 1168026499324677, - 1242553501121234, - 1306366254304474, - 1086752658510815, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 2465253816303469, - 3191571337672685, - 1159882208056013, - 2569188183312765, - 621213314200686, - ]), - y_minus_x: FieldElement51([ - 1971678598905747, - 338026507889165, - 762398079972271, - 655096486107477, - 42299032696322, - ]), - xy2d: FieldElement51([ - 177130678690680, - 1754759263300204, - 1864311296286618, - 1180675631479880, - 1292726903152791, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 1913163449625248, - 2712579013977241, - 2193883288642313, - 1008900146920800, - 1721983679009502, - ]), - y_minus_x: FieldElement51([ - 1070401523076875, - 1272492007800961, - 1910153608563310, - 2075579521696771, - 1191169788841221, - ]), - xy2d: FieldElement51([ - 692896803108118, - 500174642072499, - 2068223309439677, - 1162190621851337, - 1426986007309901, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 1819621230288238, - 2735700366193240, - 1755134670739586, - 3080648199451191, - 4172807995775876, - ]), - y_minus_x: FieldElement51([ - 992069868904071, - 799011518185730, - 1777586403832768, - 1134820506145684, - 1999461475558530, - ]), - xy2d: FieldElement51([ - 425204543703124, - 2040469794090382, - 1651690622153809, - 1500530168597569, - 1253908377065966, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 2105824306960939, - 1387520302709358, - 3633176580451016, - 2211816663841753, - 1629085891776489, - ]), - y_minus_x: FieldElement51([ - 1485201376284999, - 1022406647424656, - 504181009209019, - 962621520820995, - 590876713147230, - ]), - xy2d: FieldElement51([ - 265873406365287, - 1192742653492898, - 88553098803050, - 525037770869640, - 1266933811251234, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 3552316659826612, - 1254279525791875, - 1609927932077699, - 3578654071679972, - 3750681296069893, - ]), - y_minus_x: FieldElement51([ - 37186803519861, - 1404297334376301, - 578519728836650, - 1740727951192592, - 2095534282477028, - ]), - xy2d: FieldElement51([ - 833234263154399, - 2023862470013762, - 1854137933982069, - 853924318090959, - 1589812702805850, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 3679150557957763, - 1319179453661745, - 497496853611112, - 2665464286942351, - 1208137952365560, - ]), - y_minus_x: FieldElement51([ - 1654513078530905, - 907489875842908, - 126098711296368, - 1726320004173677, - 28269495058173, - ]), - xy2d: FieldElement51([ - 114436686957443, - 532739313025996, - 115428841215897, - 2191499400074366, - 370280402676434, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 1111146849833253, - 2016430049079759, - 1860522747477948, - 3537164738290194, - 4137142824844184, - ]), - y_minus_x: FieldElement51([ - 429069864577128, - 975327637149449, - 237881983565075, - 1654761232378630, - 2122527599091807, - ]), - xy2d: FieldElement51([ - 2093793463548278, - 754827233241879, - 1420389751719629, - 1829952782588138, - 2011865756773717, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 676293365438898, - 2850296017886344, - 1205350322490195, - 2763699392265669, - 2133931188538142, - ]), - y_minus_x: FieldElement51([ - 48340340349120, - 1299261101494832, - 1137329686775218, - 1534848106674340, - 1351662218216799, - ]), - xy2d: FieldElement51([ - 1904520614137939, - 1590301001714014, - 215781420985270, - 2043534301034629, - 1970888949300424, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 2365217962409710, - 2061307169694064, - 1887478590157603, - 2169639621284316, - 2373810867477200, - ]), - y_minus_x: FieldElement51([ - 1020052624656948, - 1260412094216707, - 366721640607121, - 585331442306596, - 345876457758061, - ]), - xy2d: FieldElement51([ - 975390299880933, - 1066555195234642, - 12651997758352, - 1184252205433068, - 1058378155074223, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 1431537716602643, - 2024827957433813, - 3746434518400495, - 1087794891033550, - 2156817571680455, - ]), - y_minus_x: FieldElement51([ - 929288033346881, - 255179964546973, - 711057989588035, - 208899572612840, - 185348357387383, - ]), - xy2d: FieldElement51([ - 823689746424808, - 47266130989546, - 209403309368097, - 1100966895202707, - 710792075292719, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 2311213117823762, - 3296668540922318, - 2004276520649823, - 1861500579441125, - 3148029033359833, - ]), - y_minus_x: FieldElement51([ - 1563693677475261, - 1843782073741194, - 1950700654453170, - 911540858113949, - 2085151496302359, - ]), - xy2d: FieldElement51([ - 1427880892005482, - 106216431121745, - 42608394782284, - 1217295886989793, - 1514235272796882, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 3544335535746750, - 2367994491347456, - 2567261456502612, - 1854058085060971, - 2263545563461076, - ]), - y_minus_x: FieldElement51([ - 787426011300053, - 2105981035769060, - 1130476291127206, - 1748659348100075, - 53470983013756, - ]), - xy2d: FieldElement51([ - 553548273865386, - 5927805718390, - 65184587381926, - 633576679686953, - 576048559439973, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 993787326657446, - 3868807161609258, - 1615796046728943, - 2514644292681953, - 2059021068660907, - ]), - y_minus_x: FieldElement51([ - 251010270518880, - 1681684095763484, - 1521949356387564, - 431593457045116, - 1855308922422910, - ]), - xy2d: FieldElement51([ - 618490909691959, - 1257497595618257, - 202952467594088, - 35577762721238, - 1494883566841973, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 1673474571932262, - 2409784519770613, - 2636095316260487, - 2761112584601925, - 3333713288149876, - ]), - y_minus_x: FieldElement51([ - 1600640202645197, - 1019569075331823, - 1041916487915822, - 1680448171313267, - 2126903137527901, - ]), - xy2d: FieldElement51([ - 894964745143659, - 106116880092678, - 1009869382959477, - 317866368542032, - 1986983122763912, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 1765281781276487, - 2863247187455184, - 2589075472439062, - 1386435905543054, - 2182338478845320, - ]), - y_minus_x: FieldElement51([ - 1144730936996693, - 2213315231278180, - 1489676672185125, - 665039429138074, - 1131283313040268, - ]), - xy2d: FieldElement51([ - 2004734176670602, - 1738311085075235, - 418866995976618, - 1050782508034394, - 577747313404652, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 2185209688340293, - 1309276076461009, - 2514740038571278, - 3994889904012999, - 3018098826231021, - ]), - y_minus_x: FieldElement51([ - 1405936970888515, - 1754621155316654, - 1211862168554999, - 1813045702919083, - 997853418197172, - ]), - xy2d: FieldElement51([ - 82037622045021, - 1646398333621944, - 613095452763466, - 1312329542583705, - 81014679202721, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 2389287991277873, - 403851022333257, - 1597473361477193, - 2953351602509212, - 2135174663049062, - ]), - y_minus_x: FieldElement51([ - 1826548187201150, - 302299893734126, - 1475477168615781, - 842617616347376, - 1438600873676130, - ]), - xy2d: FieldElement51([ - 663049852468609, - 1649295727846569, - 1048009692742781, - 628866177992421, - 1914360327429204, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 1795645928096646, - 306878154408959, - 2924901319092394, - 2801261341654799, - 1653782432983523, - ]), - y_minus_x: FieldElement51([ - 2077597317438627, - 212642017882064, - 674844477518888, - 875487498687554, - 2060550250171182, - ]), - xy2d: FieldElement51([ - 1420448018683809, - 1032663994771382, - 1341927003385267, - 1340360916546159, - 1988547473895228, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 1082660122598844, - 2545055705583789, - 3888919679589007, - 1670283344995811, - 3403239134794618, - ]), - y_minus_x: FieldElement51([ - 90430593339788, - 1838338032241275, - 571293238480915, - 1639938867416883, - 257378872001111, - ]), - xy2d: FieldElement51([ - 1528535658865034, - 1516636853043960, - 787000569996728, - 1464531394704506, - 1684822625133795, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 811329918113934, - 2783463529007378, - 1769095754634835, - 2970819621866866, - 881037178164325, - ]), - y_minus_x: FieldElement51([ - 1784566501964517, - 433890943689325, - 1186055625589419, - 1496077405487512, - 1731807117886548, - ]), - xy2d: FieldElement51([ - 424909811816304, - 1355993963741797, - 409606483251841, - 455665350637068, - 1617009023642808, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 2478728492077816, - 2780289048655501, - 2328687177473769, - 4107341333582032, - 1316147724308250, - ]), - y_minus_x: FieldElement51([ - 1617420574301156, - 1741273341070467, - 667135503486508, - 2100436564640123, - 1032223920000865, - ]), - xy2d: FieldElement51([ - 1753947659404033, - 247279202390193, - 1819288880178945, - 737334285670249, - 1037873664856104, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 1762568490530034, - 673742465299012, - 2054571050635888, - 2040165159255111, - 3040123733327257, - ]), - y_minus_x: FieldElement51([ - 1627187989987422, - 1686331580821752, - 1309895873498183, - 719718719104086, - 300063199808722, - ]), - xy2d: FieldElement51([ - 238176707016164, - 1440454788877048, - 203336037573144, - 1437789888677072, - 101522256664211, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 1895216760098480, - 1934324337975022, - 3677350688973167, - 2536415965456176, - 714678003308640, - ]), - y_minus_x: FieldElement51([ - 508185358728815, - 1691320535341855, - 2168887448239256, - 1035124393070661, - 1936603999698584, - ]), - xy2d: FieldElement51([ - 390562831571647, - 1390223890708972, - 1383183990676371, - 435998174196410, - 1882086414390730, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 3747620842612921, - 2081794785291195, - 3284594056262745, - 2090090346797895, - 2581692978935809, - ]), - y_minus_x: FieldElement51([ - 244144781251265, - 1290834426417077, - 1888701171101942, - 1233922456644870, - 241117402207491, - ]), - xy2d: FieldElement51([ - 1266169390045455, - 1148042013187970, - 878921907853942, - 1815738019658093, - 908920199341621, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 2521768507305118, - 953557056811112, - 2015863732865770, - 1358382511861315, - 2835421647899992, - ]), - y_minus_x: FieldElement51([ - 2239837206240498, - 330928973149665, - 422268062913642, - 1481280019493032, - 619879520439841, - ]), - xy2d: FieldElement51([ - 1360166735366017, - 1770556573948510, - 1395061284191031, - 1814003148068126, - 522781147076884, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 2611794802645686, - 707234844948070, - 1314059396506491, - 2919250341703934, - 2161831667832785, - ]), - y_minus_x: FieldElement51([ - 934831784182383, - 433734253968318, - 1660867106725771, - 1968393082772831, - 873946300968490, - ]), - xy2d: FieldElement51([ - 26306827827554, - 430884999378685, - 1504310424376419, - 1761358720837522, - 542195685418530, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 1762131062631725, - 3123952634417535, - 3619918390837537, - 2909990877347294, - 1411594230004385, - ]), - y_minus_x: FieldElement51([ - 538272372224622, - 1425714779586199, - 588313661410172, - 1497062084392578, - 1602174047128512, - ]), - xy2d: FieldElement51([ - 907490361939255, - 1963620338391363, - 626927432296975, - 1250748516081414, - 959901171882527, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 1335066153744413, - 2887804660779657, - 2653073855954038, - 2765226981667422, - 938831784476763, - ]), - y_minus_x: FieldElement51([ - 296699434737224, - 2047543711075683, - 2076451038937139, - 227783599906901, - 1602062110967627, - ]), - xy2d: FieldElement51([ - 1574834773194203, - 1384279952062839, - 393652417255803, - 2166968242848859, - 1552890441390820, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 1619646774410947, - 1576090644023562, - 3035228391320965, - 1735328519940543, - 2355324535937066, - ]), - y_minus_x: FieldElement51([ - 1024074573633446, - 957088456885874, - 1690425531356997, - 2102187380180052, - 1082544623222033, - ]), - xy2d: FieldElement51([ - 1871906170635853, - 1719383891167200, - 1584032250247862, - 823764804192117, - 2244048510084261, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 642147846489775, - 3334304977145699, - 305205716788147, - 2589176626729533, - 2224680511484174, - ]), - y_minus_x: FieldElement51([ - 1734162377166545, - 260713621840346, - 157174591942595, - 952544272517991, - 222818702471733, - ]), - xy2d: FieldElement51([ - 1213115494182947, - 286778704335711, - 2130189536016490, - 308349182281342, - 1217623948685491, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 3360052266973635, - 1843486583624091, - 1561693837124349, - 1084041964025479, - 1866270922024009, - ]), - y_minus_x: FieldElement51([ - 460705465481210, - 1968151453817859, - 497005926994844, - 625618055866751, - 2176893440866887, - ]), - xy2d: FieldElement51([ - 1655800250476757, - 2036588542300609, - 666447448675243, - 1615721995750683, - 1508669225186765, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 2245948203759141, - 1058306669699396, - 1452898014240582, - 3961024141962768, - 1633235287338608, - ]), - y_minus_x: FieldElement51([ - 986647273684279, - 1507266907811370, - 1260572633649005, - 2071672342077446, - 695976026010857, - ]), - xy2d: FieldElement51([ - 1312356620823495, - 1635278548098567, - 901946076841033, - 585120475533168, - 1240667113237384, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 2313723935779695, - 1506054666773895, - 996040223525031, - 636592914999692, - 1497801917020297, - ]), - y_minus_x: FieldElement51([ - 292042016419794, - 1158932298133044, - 2062611870323738, - 1946058478962569, - 1749165808126286, - ]), - xy2d: FieldElement51([ - 654683942212830, - 1526897351349087, - 2006818439922838, - 2194919327350361, - 1451960776874416, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 3015041017808905, - 2951823141773809, - 2584865668253675, - 2508192032998563, - 2582137700042019, - ]), - y_minus_x: FieldElement51([ - 1628123495344283, - 2072923641214546, - 1647225812023982, - 855655925244679, - 1758126430071140, - ]), - xy2d: FieldElement51([ - 1615895096489599, - 275295258643784, - 937665541219916, - 1313496726746346, - 1186468946422626, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 1603070202850694, - 2072127623773242, - 1692648737212158, - 2493373404187852, - 1248948672117105, - ]), - y_minus_x: FieldElement51([ - 11167836031898, - 596565174397990, - 2196351068723859, - 314744641791907, - 1102014997250781, - ]), - xy2d: FieldElement51([ - 1409047922401191, - 69960384467966, - 688103515547600, - 1309746102488044, - 150292892873778, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 1986083055103168, - 691715819340300, - 1361811659746933, - 3459052030333434, - 1063594696046061, - ]), - y_minus_x: FieldElement51([ - 1201987338414749, - 2198784582460616, - 1203335513981498, - 489243077045066, - 2205278143582433, - ]), - xy2d: FieldElement51([ - 2034744376624534, - 2077387101466387, - 148448542974969, - 1502697574577258, - 473186584705655, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 472016956315960, - 720786972252993, - 2840633661190043, - 3150798753357827, - 2816563335499153, - ]), - y_minus_x: FieldElement51([ - 253464247569755, - 168314237403057, - 511780806170295, - 1058862316549135, - 1646858476817137, - ]), - xy2d: FieldElement51([ - 595092995922219, - 1491311840717691, - 291581784452778, - 1569186646367854, - 1031385061400544, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 3483137021572755, - 1526955102024322, - 2778006642704458, - 457549634924205, - 1097420237736736, - ]), - y_minus_x: FieldElement51([ - 1246991699537710, - 81367319519439, - 530844036072196, - 163656863755855, - 1950742455979290, - ]), - xy2d: FieldElement51([ - 191532664076407, - 539378506082089, - 1021612562876554, - 1026603384732632, - 1773368780410653, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 4144620731387879, - 590179521333342, - 4034023318016108, - 2255745030335426, - 2699746851701250, - ]), - y_minus_x: FieldElement51([ - 2206599697359952, - 553895797384417, - 181689161933786, - 1153123447919104, - 778568064152659, - ]), - xy2d: FieldElement51([ - 1706307000059211, - 1885601289314487, - 889758608505788, - 550131729999853, - 1006862664714268, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 3210197754285058, - 2048500453422630, - 3403309827888207, - 927154428508963, - 4199813798872019, - ]), - y_minus_x: FieldElement51([ - 992058915374933, - 476120535358775, - 1973648780784340, - 2025282643598818, - 2182318983793230, - ]), - xy2d: FieldElement51([ - 1343440812005821, - 1316045839091795, - 1884951299078063, - 1765919609219175, - 2197567554627988, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 3129247779382818, - 4415026969054274, - 1900265885969643, - 1528796215447059, - 2172730393748688, - ]), - y_minus_x: FieldElement51([ - 1773355092297603, - 64654329538271, - 1332124041660957, - 748492100858001, - 895500006200535, - ]), - xy2d: FieldElement51([ - 2000840647851980, - 546565968824914, - 420633283457524, - 195470736374507, - 1958689297569520, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 743138980705446, - 3411117504637167, - 2591389959690621, - 2380042066577202, - 3022267940115114, - ]), - y_minus_x: FieldElement51([ - 165947002229363, - 115186103724967, - 1068573292121517, - 1842565776920938, - 1969395681111987, - ]), - xy2d: FieldElement51([ - 553322266190633, - 234265665613185, - 484544650202821, - 1238773526575826, - 2017991917953668, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 2581954631514051, - 1245093644265357, - 3537016673825374, - 1834216551713857, - 923978372152807, - ]), - y_minus_x: FieldElement51([ - 1855378315339552, - 890045579230758, - 1764718173975590, - 197904186055854, - 1718129022310327, - ]), - xy2d: FieldElement51([ - 1278162928734862, - 1894118254109862, - 987503995465517, - 177406744098996, - 781538103127693, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 1996603431230215, - 1191888797552937, - 1207440075928499, - 2765853449051137, - 2525314961343288, - ]), - y_minus_x: FieldElement51([ - 808903879370889, - 990820108751280, - 1084429472258867, - 1078562781312589, - 254514692695625, - ]), - xy2d: FieldElement51([ - 615855140068469, - 586046731175395, - 693470779212674, - 1964537100203868, - 1350330550265229, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 3344544372023708, - 720386671449874, - 2480841360702110, - 2036034126860286, - 2015744690201389, - ]), - y_minus_x: FieldElement51([ - 1337446193390478, - 1984110761311871, - 746489405020285, - 407347127604128, - 1740475330360596, - ]), - xy2d: FieldElement51([ - 140840424783613, - 1063284623568331, - 1136446106453878, - 372042229029799, - 442607248430694, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 2330781679120937, - 376801425148230, - 2032603686676107, - 1488926293635130, - 1317278311532959, - ]), - y_minus_x: FieldElement51([ - 1290116731380016, - 2166899563471713, - 831997001838078, - 870954980505220, - 2108537278055823, - ]), - xy2d: FieldElement51([ - 1912719171026343, - 846194720551034, - 2043988124740726, - 993234269653961, - 421229796383281, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 2651184584992902, - 2775702557638963, - 2539786009779572, - 2575974880015305, - 2122619079836732, - ]), - y_minus_x: FieldElement51([ - 1154054290132562, - 931753998725577, - 1647742001778052, - 865765466488226, - 1083816107290025, - ]), - xy2d: FieldElement51([ - 986341121095108, - 1522330369638573, - 1990880546211047, - 501525962272123, - 198539304862139, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 1496414019192687, - 3991034436173951, - 3380311659062196, - 2854747485359158, - 3346958036643152, - ]), - y_minus_x: FieldElement51([ - 805612068303425, - 1891790027761335, - 1587008567571549, - 722120737390201, - 378156757163816, - ]), - xy2d: FieldElement51([ - 1588994517921951, - 977362751042302, - 1329302387067714, - 2069348224564088, - 1586007159625211, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 2490539421551682, - 1985699850375015, - 2331762317128172, - 4145097393776678, - 2521049460190674, - ]), - y_minus_x: FieldElement51([ - 615817553313996, - 2245962768078178, - 482564324326173, - 2101336843140780, - 1240914880829407, - ]), - xy2d: FieldElement51([ - 1438242482238189, - 874267817785463, - 1620810389770625, - 866155221338671, - 1040426546798301, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 2403083624110300, - 2548561409802975, - 2492699136535911, - 2358289519456539, - 3203964320363148, - ]), - y_minus_x: FieldElement51([ - 1913986535403097, - 1977163223054199, - 1972905914623196, - 1650122133472502, - 1905849310819035, - ]), - xy2d: FieldElement51([ - 858174816360838, - 614595356564037, - 1099584959044836, - 636998087084906, - 1070393269058348, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 3666695924830668, - 3585640662737501, - 2372994528684236, - 2628565977288995, - 3482812783469694, - ]), - y_minus_x: FieldElement51([ - 1994161359147952, - 2198039369802658, - 62790022842537, - 1522306785848169, - 951223194802833, - ]), - xy2d: FieldElement51([ - 852296621440717, - 431889737774209, - 370755457746189, - 437604073958073, - 627857326892757, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 1794955764684156, - 2586904290013612, - 1322647643615887, - 856117964085888, - 2652432778663153, - ]), - y_minus_x: FieldElement51([ - 933592377399646, - 78031722952813, - 926049890685253, - 1471649501316246, - 33789909190376, - ]), - xy2d: FieldElement51([ - 1479319468832059, - 203906207621608, - 659828362330083, - 44358398435755, - 1273573524210803, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 1592342143350813, - 3227219208247713, - 2345240352078765, - 2577750109932929, - 2933512841197243, - ]), - y_minus_x: FieldElement51([ - 2184946892642995, - 1517382324576002, - 1557940277419806, - 2170635134813213, - 747314658627002, - ]), - xy2d: FieldElement51([ - 1823193620577742, - 1135817878516419, - 1731253819308581, - 1031652967267804, - 2123506616999453, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 1346190246005805, - 2052692552023851, - 1718128041785940, - 2491557332978474, - 3474370880388305, - ]), - y_minus_x: FieldElement51([ - 424776012994573, - 281050757243423, - 626466040846420, - 990194703866532, - 38571969885982, - ]), - xy2d: FieldElement51([ - 192408346595466, - 1054889725292349, - 584097975693004, - 1447909807397749, - 2134645004369136, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 3169895788615063, - 3503097743181446, - 601598510029975, - 1422812237223371, - 2121009661378329, - ]), - y_minus_x: FieldElement51([ - 1603348391996783, - 2066143816131699, - 1789627290363958, - 2145705961178118, - 1985578641438222, - ]), - xy2d: FieldElement51([ - 352633958653380, - 856927627345554, - 793925083122702, - 93551575767286, - 1222010153634215, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 1756866499986349, - 911731956999969, - 2707505543214075, - 4006920335263786, - 822501008147910, - ]), - y_minus_x: FieldElement51([ - 1094036422864347, - 1897208881572508, - 1503607738246960, - 1901060196071406, - 294068411105729, - ]), - xy2d: FieldElement51([ - 587776484399576, - 1116861711228807, - 343398777436088, - 936544065763093, - 1643746750211060, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 3477749685790410, - 267997399528836, - 2953780922004404, - 3252368924080907, - 3787792887348381, - ]), - y_minus_x: FieldElement51([ - 2042368155872443, - 41662387210459, - 1676313264498480, - 1333968523426810, - 1765708383352310, - ]), - xy2d: FieldElement51([ - 1453394896690938, - 1585795827439909, - 1469309456804303, - 1294645324464404, - 2042954198665899, - ]), - }, - AffineNielsPoint { - y_plus_x: FieldElement51([ - 1810069207599881, - 1358344669503239, - 1989371257548167, - 2316270051121225, - 3019675451276507, - ]), - y_minus_x: FieldElement51([ - 1866114438287676, - 1663420339568364, - 1437691317033088, - 538298302628038, - 1212711449614363, - ]), - xy2d: FieldElement51([ - 1769235035677897, - 1562012115317882, - 31277513664750, - 536198657928416, - 1976134212537183, - ]), - }, - ]); diff --git a/net/gurk-rs/files/vendor/curve25519-dalek/src/backend/serial/u64/field.rs b/net/gurk-rs/files/vendor/curve25519-dalek/src/backend/serial/u64/field.rs deleted file mode 100644 index a73d4b5..0000000 --- a/net/gurk-rs/files/vendor/curve25519-dalek/src/backend/serial/u64/field.rs +++ /dev/null @@ -1,564 +0,0 @@ -// -*- mode: rust; -*- -// -// This file is part of curve25519-dalek. -// Copyright (c) 2016-2021 isis lovecruft -// Copyright (c) 2016-2019 Henry de Valence -// See LICENSE for licensing information. -// -// Authors: -// - isis agora lovecruft -// - Henry de Valence - -//! Field arithmetic modulo \\(p = 2\^{255} - 19\\), using \\(64\\)-bit -//! limbs with \\(128\\)-bit products. - -use core::fmt::Debug; -use core::ops::Neg; -use core::ops::{Add, AddAssign}; -use core::ops::{Mul, MulAssign}; -use core::ops::{Sub, SubAssign}; - -use subtle::Choice; -use subtle::ConditionallySelectable; - -use zeroize::Zeroize; - -/// A `FieldElement51` represents an element of the field -/// \\( \mathbb Z / (2\^{255} - 19)\\). -/// -/// In the 64-bit implementation, a `FieldElement` is represented in -/// radix \\(2\^{51}\\) as five `u64`s; the coefficients are allowed to -/// grow up to \\(2\^{54}\\) between reductions modulo \\(p\\). -/// -/// # Note -/// -/// The `curve25519_dalek::field` module provides a type alias -/// `curve25519_dalek::field::FieldElement` to either `FieldElement51` -/// or `FieldElement2625`. -/// -/// The backend-specific type `FieldElement51` should not be used -/// outside of the `curve25519_dalek::field` module. -#[derive(Copy, Clone)] -pub struct FieldElement51(pub (crate) [u64; 5]); - -impl Debug for FieldElement51 { - fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { - write!(f, "FieldElement51({:?})", &self.0[..]) - } -} - -impl Zeroize for FieldElement51 { - fn zeroize(&mut self) { - self.0.zeroize(); - } -} - -impl<'b> AddAssign<&'b FieldElement51> for FieldElement51 { - fn add_assign(&mut self, _rhs: &'b FieldElement51) { - for i in 0..5 { - self.0[i] += _rhs.0[i]; - } - } -} - -impl<'a, 'b> Add<&'b FieldElement51> for &'a FieldElement51 { - type Output = FieldElement51; - fn add(self, _rhs: &'b FieldElement51) -> FieldElement51 { - let mut output = *self; - output += _rhs; - output - } -} - -impl<'b> SubAssign<&'b FieldElement51> for FieldElement51 { - fn sub_assign(&mut self, _rhs: &'b FieldElement51) { - let result = (self as &FieldElement51) - _rhs; - self.0 = result.0; - } -} - -impl<'a, 'b> Sub<&'b FieldElement51> for &'a FieldElement51 { - type Output = FieldElement51; - fn sub(self, _rhs: &'b FieldElement51) -> FieldElement51 { - // To avoid underflow, first add a multiple of p. - // Choose 16*p = p << 4 to be larger than 54-bit _rhs. - // - // If we could statically track the bitlengths of the limbs - // of every FieldElement51, we could choose a multiple of p - // just bigger than _rhs and avoid having to do a reduction. - // - // Since we don't yet have type-level integers to do this, we - // have to add an explicit reduction call here. - FieldElement51::reduce([ - (self.0[0] + 36028797018963664u64) - _rhs.0[0], - (self.0[1] + 36028797018963952u64) - _rhs.0[1], - (self.0[2] + 36028797018963952u64) - _rhs.0[2], - (self.0[3] + 36028797018963952u64) - _rhs.0[3], - (self.0[4] + 36028797018963952u64) - _rhs.0[4], - ]) - } -} - -impl<'b> MulAssign<&'b FieldElement51> for FieldElement51 { - fn mul_assign(&mut self, _rhs: &'b FieldElement51) { - let result = (self as &FieldElement51) * _rhs; - self.0 = result.0; - } -} - -impl<'a, 'b> Mul<&'b FieldElement51> for &'a FieldElement51 { - type Output = FieldElement51; - fn mul(self, _rhs: &'b FieldElement51) -> FieldElement51 { - /// Helper function to multiply two 64-bit integers with 128 - /// bits of output. - #[inline(always)] - fn m(x: u64, y: u64) -> u128 { (x as u128) * (y as u128) } - - // Alias self, _rhs for more readable formulas - let a: &[u64; 5] = &self.0; - let b: &[u64; 5] = &_rhs.0; - - // Precondition: assume input limbs a[i], b[i] are bounded as - // - // a[i], b[i] < 2^(51 + b) - // - // where b is a real parameter measuring the "bit excess" of the limbs. - - // 64-bit precomputations to avoid 128-bit multiplications. - // - // This fits into a u64 whenever 51 + b + lg(19) < 64. - // - // Since 51 + b + lg(19) < 51 + 4.25 + b - // = 55.25 + b, - // this fits if b < 8.75. - let b1_19 = b[1] * 19; - let b2_19 = b[2] * 19; - let b3_19 = b[3] * 19; - let b4_19 = b[4] * 19; - - // Multiply to get 128-bit coefficients of output - let c0: u128 = m(a[0],b[0]) + m(a[4],b1_19) + m(a[3],b2_19) + m(a[2],b3_19) + m(a[1],b4_19); - let mut c1: u128 = m(a[1],b[0]) + m(a[0],b[1]) + m(a[4],b2_19) + m(a[3],b3_19) + m(a[2],b4_19); - let mut c2: u128 = m(a[2],b[0]) + m(a[1],b[1]) + m(a[0],b[2]) + m(a[4],b3_19) + m(a[3],b4_19); - let mut c3: u128 = m(a[3],b[0]) + m(a[2],b[1]) + m(a[1],b[2]) + m(a[0],b[3]) + m(a[4],b4_19); - let mut c4: u128 = m(a[4],b[0]) + m(a[3],b[1]) + m(a[2],b[2]) + m(a[1],b[3]) + m(a[0],b[4]); - - // How big are the c[i]? We have - // - // c[i] < 2^(102 + 2*b) * (1+i + (4-i)*19) - // < 2^(102 + lg(1 + 4*19) + 2*b) - // < 2^(108.27 + 2*b) - // - // The carry (c[i] >> 51) fits into a u64 when - // 108.27 + 2*b - 51 < 64 - // 2*b < 6.73 - // b < 3.365. - // - // So we require b < 3 to ensure this fits. - debug_assert!(a[0] < (1 << 54)); debug_assert!(b[0] < (1 << 54)); - debug_assert!(a[1] < (1 << 54)); debug_assert!(b[1] < (1 << 54)); - debug_assert!(a[2] < (1 << 54)); debug_assert!(b[2] < (1 << 54)); - debug_assert!(a[3] < (1 << 54)); debug_assert!(b[3] < (1 << 54)); - debug_assert!(a[4] < (1 << 54)); debug_assert!(b[4] < (1 << 54)); - - // Casting to u64 and back tells the compiler that the carry is - // bounded by 2^64, so that the addition is a u128 + u64 rather - // than u128 + u128. - - const LOW_51_BIT_MASK: u64 = (1u64 << 51) - 1; - let mut out = [0u64; 5]; - - c1 += ((c0 >> 51) as u64) as u128; - out[0] = (c0 as u64) & LOW_51_BIT_MASK; - - c2 += ((c1 >> 51) as u64) as u128; - out[1] = (c1 as u64) & LOW_51_BIT_MASK; - - c3 += ((c2 >> 51) as u64) as u128; - out[2] = (c2 as u64) & LOW_51_BIT_MASK; - - c4 += ((c3 >> 51) as u64) as u128; - out[3] = (c3 as u64) & LOW_51_BIT_MASK; - - let carry: u64 = (c4 >> 51) as u64; - out[4] = (c4 as u64) & LOW_51_BIT_MASK; - - // To see that this does not overflow, we need out[0] + carry * 19 < 2^64. - // - // c4 < a0*b4 + a1*b3 + a2*b2 + a3*b1 + a4*b0 + (carry from c3) - // < 5*(2^(51 + b) * 2^(51 + b)) + (carry from c3) - // < 2^(102 + 2*b + lg(5)) + 2^64. - // - // When b < 3 we get - // - // c4 < 2^110.33 so that carry < 2^59.33 - // - // so that - // - // out[0] + carry * 19 < 2^51 + 19 * 2^59.33 < 2^63.58 - // - // and there is no overflow. - out[0] = out[0] + carry * 19; - - // Now out[1] < 2^51 + 2^(64 -51) = 2^51 + 2^13 < 2^(51 + epsilon). - out[1] += out[0] >> 51; - out[0] &= LOW_51_BIT_MASK; - - // Now out[i] < 2^(51 + epsilon) for all i. - FieldElement51(out) - } -} - -impl<'a> Neg for &'a FieldElement51 { - type Output = FieldElement51; - fn neg(self) -> FieldElement51 { - let mut output = *self; - output.negate(); - output - } -} - -impl ConditionallySelectable for FieldElement51 { - fn conditional_select( - a: &FieldElement51, - b: &FieldElement51, - choice: Choice, - ) -> FieldElement51 { - FieldElement51([ - u64::conditional_select(&a.0[0], &b.0[0], choice), - u64::conditional_select(&a.0[1], &b.0[1], choice), - u64::conditional_select(&a.0[2], &b.0[2], choice), - u64::conditional_select(&a.0[3], &b.0[3], choice), - u64::conditional_select(&a.0[4], &b.0[4], choice), - ]) - } - - fn conditional_swap(a: &mut FieldElement51, b: &mut FieldElement51, choice: Choice) { - u64::conditional_swap(&mut a.0[0], &mut b.0[0], choice); - u64::conditional_swap(&mut a.0[1], &mut b.0[1], choice); - u64::conditional_swap(&mut a.0[2], &mut b.0[2], choice); - u64::conditional_swap(&mut a.0[3], &mut b.0[3], choice); - u64::conditional_swap(&mut a.0[4], &mut b.0[4], choice); - } - - fn conditional_assign(&mut self, other: &FieldElement51, choice: Choice) { - self.0[0].conditional_assign(&other.0[0], choice); - self.0[1].conditional_assign(&other.0[1], choice); - self.0[2].conditional_assign(&other.0[2], choice); - self.0[3].conditional_assign(&other.0[3], choice); - self.0[4].conditional_assign(&other.0[4], choice); - } -} - -impl FieldElement51 { - /// Invert the sign of this field element - pub fn negate(&mut self) { - // See commentary in the Sub impl - let neg = FieldElement51::reduce([ - 36028797018963664u64 - self.0[0], - 36028797018963952u64 - self.0[1], - 36028797018963952u64 - self.0[2], - 36028797018963952u64 - self.0[3], - 36028797018963952u64 - self.0[4], - ]); - self.0 = neg.0; - } - - /// Construct zero. - pub fn zero() -> FieldElement51 { - FieldElement51([ 0, 0, 0, 0, 0 ]) - } - - /// Construct one. - pub fn one() -> FieldElement51 { - FieldElement51([ 1, 0, 0, 0, 0 ]) - } - - /// Construct -1. - pub fn minus_one() -> FieldElement51 { - FieldElement51([2251799813685228, 2251799813685247, 2251799813685247, 2251799813685247, 2251799813685247]) - } - - /// Given 64-bit input limbs, reduce to enforce the bound 2^(51 + epsilon). - #[inline(always)] - fn reduce(mut limbs: [u64; 5]) -> FieldElement51 { - const LOW_51_BIT_MASK: u64 = (1u64 << 51) - 1; - - // Since the input limbs are bounded by 2^64, the biggest - // carry-out is bounded by 2^13. - // - // The biggest carry-in is c4 * 19, resulting in - // - // 2^51 + 19*2^13 < 2^51.0000000001 - // - // Because we don't need to canonicalize, only to reduce the - // limb sizes, it's OK to do a "weak reduction", where we - // compute the carry-outs in parallel. - - let c0 = limbs[0] >> 51; - let c1 = limbs[1] >> 51; - let c2 = limbs[2] >> 51; - let c3 = limbs[3] >> 51; - let c4 = limbs[4] >> 51; - - limbs[0] &= LOW_51_BIT_MASK; - limbs[1] &= LOW_51_BIT_MASK; - limbs[2] &= LOW_51_BIT_MASK; - limbs[3] &= LOW_51_BIT_MASK; - limbs[4] &= LOW_51_BIT_MASK; - - limbs[0] += c4 * 19; - limbs[1] += c0; - limbs[2] += c1; - limbs[3] += c2; - limbs[4] += c3; - - FieldElement51(limbs) - } - - /// Load a `FieldElement51` from the low 255 bits of a 256-bit - /// input. - /// - /// # Warning - /// - /// This function does not check that the input used the canonical - /// representative. It masks the high bit, but it will happily - /// decode 2^255 - 18 to 1. Applications that require a canonical - /// encoding of every field element should decode, re-encode to - /// the canonical encoding, and check that the input was - /// canonical. - /// - pub fn from_bytes(bytes: &[u8; 32]) -> FieldElement51 { - let load8 = |input: &[u8]| -> u64 { - (input[0] as u64) - | ((input[1] as u64) << 8) - | ((input[2] as u64) << 16) - | ((input[3] as u64) << 24) - | ((input[4] as u64) << 32) - | ((input[5] as u64) << 40) - | ((input[6] as u64) << 48) - | ((input[7] as u64) << 56) - }; - - let low_51_bit_mask = (1u64 << 51) - 1; - FieldElement51( - // load bits [ 0, 64), no shift - [ load8(&bytes[ 0..]) & low_51_bit_mask - // load bits [ 48,112), shift to [ 51,112) - , (load8(&bytes[ 6..]) >> 3) & low_51_bit_mask - // load bits [ 96,160), shift to [102,160) - , (load8(&bytes[12..]) >> 6) & low_51_bit_mask - // load bits [152,216), shift to [153,216) - , (load8(&bytes[19..]) >> 1) & low_51_bit_mask - // load bits [192,256), shift to [204,112) - , (load8(&bytes[24..]) >> 12) & low_51_bit_mask - ]) - } - - /// Serialize this `FieldElement51` to a 32-byte array. The - /// encoding is canonical. - pub fn to_bytes(&self) -> [u8; 32] { - // Let h = limbs[0] + limbs[1]*2^51 + ... + limbs[4]*2^204. - // - // Write h = pq + r with 0 <= r < p. - // - // We want to compute r = h mod p. - // - // If h < 2*p = 2^256 - 38, - // then q = 0 or 1, - // - // with q = 0 when h < p - // and q = 1 when h >= p. - // - // Notice that h >= p <==> h + 19 >= p + 19 <==> h + 19 >= 2^255. - // Therefore q can be computed as the carry bit of h + 19. - - // First, reduce the limbs to ensure h < 2*p. - let mut limbs = FieldElement51::reduce(self.0).0; - - let mut q = (limbs[0] + 19) >> 51; - q = (limbs[1] + q) >> 51; - q = (limbs[2] + q) >> 51; - q = (limbs[3] + q) >> 51; - q = (limbs[4] + q) >> 51; - - // Now we can compute r as r = h - pq = r - (2^255-19)q = r + 19q - 2^255q - - limbs[0] += 19*q; - - // Now carry the result to compute r + 19q ... - let low_51_bit_mask = (1u64 << 51) - 1; - limbs[1] += limbs[0] >> 51; - limbs[0] = limbs[0] & low_51_bit_mask; - limbs[2] += limbs[1] >> 51; - limbs[1] = limbs[1] & low_51_bit_mask; - limbs[3] += limbs[2] >> 51; - limbs[2] = limbs[2] & low_51_bit_mask; - limbs[4] += limbs[3] >> 51; - limbs[3] = limbs[3] & low_51_bit_mask; - // ... but instead of carrying (limbs[4] >> 51) = 2^255q - // into another limb, discard it, subtracting the value - limbs[4] = limbs[4] & low_51_bit_mask; - - // Now arrange the bits of the limbs. - let mut s = [0u8;32]; - s[ 0] = limbs[0] as u8; - s[ 1] = (limbs[0] >> 8) as u8; - s[ 2] = (limbs[0] >> 16) as u8; - s[ 3] = (limbs[0] >> 24) as u8; - s[ 4] = (limbs[0] >> 32) as u8; - s[ 5] = (limbs[0] >> 40) as u8; - s[ 6] = ((limbs[0] >> 48) | (limbs[1] << 3)) as u8; - s[ 7] = (limbs[1] >> 5) as u8; - s[ 8] = (limbs[1] >> 13) as u8; - s[ 9] = (limbs[1] >> 21) as u8; - s[10] = (limbs[1] >> 29) as u8; - s[11] = (limbs[1] >> 37) as u8; - s[12] = ((limbs[1] >> 45) | (limbs[2] << 6)) as u8; - s[13] = (limbs[2] >> 2) as u8; - s[14] = (limbs[2] >> 10) as u8; - s[15] = (limbs[2] >> 18) as u8; - s[16] = (limbs[2] >> 26) as u8; - s[17] = (limbs[2] >> 34) as u8; - s[18] = (limbs[2] >> 42) as u8; - s[19] = ((limbs[2] >> 50) | (limbs[3] << 1)) as u8; - s[20] = (limbs[3] >> 7) as u8; - s[21] = (limbs[3] >> 15) as u8; - s[22] = (limbs[3] >> 23) as u8; - s[23] = (limbs[3] >> 31) as u8; - s[24] = (limbs[3] >> 39) as u8; - s[25] = ((limbs[3] >> 47) | (limbs[4] << 4)) as u8; - s[26] = (limbs[4] >> 4) as u8; - s[27] = (limbs[4] >> 12) as u8; - s[28] = (limbs[4] >> 20) as u8; - s[29] = (limbs[4] >> 28) as u8; - s[30] = (limbs[4] >> 36) as u8; - s[31] = (limbs[4] >> 44) as u8; - - // High bit should be zero. - debug_assert!((s[31] & 0b1000_0000u8) == 0u8); - - s - } - - /// Given `k > 0`, return `self^(2^k)`. - pub fn pow2k(&self, mut k: u32) -> FieldElement51 { - - debug_assert!( k > 0 ); - - /// Multiply two 64-bit integers with 128 bits of output. - #[inline(always)] - fn m(x: u64, y: u64) -> u128 { (x as u128) * (y as u128) } - - let mut a: [u64; 5] = self.0; - - loop { - // Precondition: assume input limbs a[i] are bounded as - // - // a[i] < 2^(51 + b) - // - // where b is a real parameter measuring the "bit excess" of the limbs. - - // Precomputation: 64-bit multiply by 19. - // - // This fits into a u64 whenever 51 + b + lg(19) < 64. - // - // Since 51 + b + lg(19) < 51 + 4.25 + b - // = 55.25 + b, - // this fits if b < 8.75. - let a3_19 = 19 * a[3]; - let a4_19 = 19 * a[4]; - - // Multiply to get 128-bit coefficients of output. - // - // The 128-bit multiplications by 2 turn into 1 slr + 1 slrd each, - // which doesn't seem any better or worse than doing them as precomputations - // on the 64-bit inputs. - let c0: u128 = m(a[0], a[0]) + 2*( m(a[1], a4_19) + m(a[2], a3_19) ); - let mut c1: u128 = m(a[3], a3_19) + 2*( m(a[0], a[1]) + m(a[2], a4_19) ); - let mut c2: u128 = m(a[1], a[1]) + 2*( m(a[0], a[2]) + m(a[4], a3_19) ); - let mut c3: u128 = m(a[4], a4_19) + 2*( m(a[0], a[3]) + m(a[1], a[2]) ); - let mut c4: u128 = m(a[2], a[2]) + 2*( m(a[0], a[4]) + m(a[1], a[3]) ); - - // Same bound as in multiply: - // c[i] < 2^(102 + 2*b) * (1+i + (4-i)*19) - // < 2^(102 + lg(1 + 4*19) + 2*b) - // < 2^(108.27 + 2*b) - // - // The carry (c[i] >> 51) fits into a u64 when - // 108.27 + 2*b - 51 < 64 - // 2*b < 6.73 - // b < 3.365. - // - // So we require b < 3 to ensure this fits. - debug_assert!(a[0] < (1 << 54)); - debug_assert!(a[1] < (1 << 54)); - debug_assert!(a[2] < (1 << 54)); - debug_assert!(a[3] < (1 << 54)); - debug_assert!(a[4] < (1 << 54)); - - const LOW_51_BIT_MASK: u64 = (1u64 << 51) - 1; - - // Casting to u64 and back tells the compiler that the carry is bounded by 2^64, so - // that the addition is a u128 + u64 rather than u128 + u128. - c1 += ((c0 >> 51) as u64) as u128; - a[0] = (c0 as u64) & LOW_51_BIT_MASK; - - c2 += ((c1 >> 51) as u64) as u128; - a[1] = (c1 as u64) & LOW_51_BIT_MASK; - - c3 += ((c2 >> 51) as u64) as u128; - a[2] = (c2 as u64) & LOW_51_BIT_MASK; - - c4 += ((c3 >> 51) as u64) as u128; - a[3] = (c3 as u64) & LOW_51_BIT_MASK; - - let carry: u64 = (c4 >> 51) as u64; - a[4] = (c4 as u64) & LOW_51_BIT_MASK; - - // To see that this does not overflow, we need a[0] + carry * 19 < 2^64. - // - // c4 < a2^2 + 2*a0*a4 + 2*a1*a3 + (carry from c3) - // < 2^(102 + 2*b + lg(5)) + 2^64. - // - // When b < 3 we get - // - // c4 < 2^110.33 so that carry < 2^59.33 - // - // so that - // - // a[0] + carry * 19 < 2^51 + 19 * 2^59.33 < 2^63.58 - // - // and there is no overflow. - a[0] = a[0] + carry * 19; - - // Now a[1] < 2^51 + 2^(64 -51) = 2^51 + 2^13 < 2^(51 + epsilon). - a[1] += a[0] >> 51; - a[0] &= LOW_51_BIT_MASK; - - // Now all a[i] < 2^(51 + epsilon) and a = self^(2^k). - - k = k - 1; - if k == 0 { - break; - } - } - - FieldElement51(a) - } - - /// Returns the square of this field element. - pub fn square(&self) -> FieldElement51 { - self.pow2k(1) - } - - /// Returns 2 times the square of this field element. - pub fn square2(&self) -> FieldElement51 { - let mut square = self.pow2k(1); - for i in 0..5 { - square.0[i] *= 2; - } - - square - } -} diff --git a/net/gurk-rs/files/vendor/curve25519-dalek/src/backend/serial/u64/mod.rs b/net/gurk-rs/files/vendor/curve25519-dalek/src/backend/serial/u64/mod.rs deleted file mode 100644 index aa29eb6..0000000 --- a/net/gurk-rs/files/vendor/curve25519-dalek/src/backend/serial/u64/mod.rs +++ /dev/null @@ -1,27 +0,0 @@ -// -*- mode: rust; -*- -// -// This file is part of curve25519-dalek. -// Copyright (c) 2016-2021 isis lovecruft -// Copyright (c) 2016-2018 Henry de Valence -// See LICENSE for licensing information. -// -// Authors: -// - isis agora lovecruft -// - Henry de Valence - -//! The `u64` backend uses `u64`s and a `(u64, u64) -> u128` multiplier. -//! -//! On x86_64, the idiom `(x as u128) * (y as u128)` lowers to `MUL` -//! instructions taking 64-bit inputs and producing 128-bit outputs. On -//! other platforms, this implementation is not recommended. -//! -//! On Haswell and newer, the BMI2 extension provides `MULX`, and on -//! Broadwell and newer, the ADX extension provides `ADCX` and `ADOX` -//! (allowing the CPU to compute two carry chains in parallel). These -//! will be used if available. - -pub mod field; - -pub mod scalar; - -pub mod constants; diff --git a/net/gurk-rs/files/vendor/curve25519-dalek/src/backend/serial/u64/scalar.rs b/net/gurk-rs/files/vendor/curve25519-dalek/src/backend/serial/u64/scalar.rs deleted file mode 100644 index cee69da..0000000 --- a/net/gurk-rs/files/vendor/curve25519-dalek/src/backend/serial/u64/scalar.rs +++ /dev/null @@ -1,450 +0,0 @@ -//! Arithmetic mod \\(2\^{252} + 27742317777372353535851937790883648493\\) -//! with five \\(52\\)-bit unsigned limbs. -//! -//! \\(51\\)-bit limbs would cover the desired bit range (\\(253\\) -//! bits), but isn't large enough to reduce a \\(512\\)-bit number with -//! Montgomery multiplication, so \\(52\\) bits is used instead. To see -//! that this is safe for intermediate results, note that the largest -//! limb in a \\(5\times 5\\) product of \\(52\\)-bit limbs will be -//! -//! ```text -//! (0xfffffffffffff^2) * 5 = 0x4ffffffffffff60000000000005 (107 bits). -//! ``` - -use core::fmt::Debug; -use core::ops::{Index, IndexMut}; - -use zeroize::Zeroize; - -use constants; - -/// The `Scalar52` struct represents an element in -/// \\(\mathbb Z / \ell \mathbb Z\\) as 5 \\(52\\)-bit limbs. -#[derive(Copy,Clone)] -pub struct Scalar52(pub [u64; 5]); - -impl Debug for Scalar52 { - fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { - write!(f, "Scalar52: {:?}", &self.0[..]) - } -} - -impl Zeroize for Scalar52 { - fn zeroize(&mut self) { - self.0.zeroize(); - } -} - -impl Index for Scalar52 { - type Output = u64; - fn index(&self, _index: usize) -> &u64 { - &(self.0[_index]) - } -} - -impl IndexMut for Scalar52 { - fn index_mut(&mut self, _index: usize) -> &mut u64 { - &mut (self.0[_index]) - } -} - -/// u64 * u64 = u128 multiply helper -#[inline(always)] -fn m(x: u64, y: u64) -> u128 { - (x as u128) * (y as u128) -} - -impl Scalar52 { - /// Return the zero scalar - pub fn zero() -> Scalar52 { - Scalar52([0,0,0,0,0]) - } - - /// Unpack a 32 byte / 256 bit scalar into 5 52-bit limbs. - pub fn from_bytes(bytes: &[u8; 32]) -> Scalar52 { - let mut words = [0u64; 4]; - for i in 0..4 { - for j in 0..8 { - words[i] |= (bytes[(i * 8) + j] as u64) << (j * 8); - } - } - - let mask = (1u64 << 52) - 1; - let top_mask = (1u64 << 48) - 1; - let mut s = Scalar52::zero(); - - s[ 0] = words[0] & mask; - s[ 1] = ((words[0] >> 52) | (words[1] << 12)) & mask; - s[ 2] = ((words[1] >> 40) | (words[2] << 24)) & mask; - s[ 3] = ((words[2] >> 28) | (words[3] << 36)) & mask; - s[ 4] = (words[3] >> 16) & top_mask; - - s - } - - /// Reduce a 64 byte / 512 bit scalar mod l - pub fn from_bytes_wide(bytes: &[u8; 64]) -> Scalar52 { - let mut words = [0u64; 8]; - for i in 0..8 { - for j in 0..8 { - words[i] |= (bytes[(i * 8) + j] as u64) << (j * 8); - } - } - - let mask = (1u64 << 52) - 1; - let mut lo = Scalar52::zero(); - let mut hi = Scalar52::zero(); - - lo[0] = words[ 0] & mask; - lo[1] = ((words[ 0] >> 52) | (words[ 1] << 12)) & mask; - lo[2] = ((words[ 1] >> 40) | (words[ 2] << 24)) & mask; - lo[3] = ((words[ 2] >> 28) | (words[ 3] << 36)) & mask; - lo[4] = ((words[ 3] >> 16) | (words[ 4] << 48)) & mask; - hi[0] = (words[ 4] >> 4) & mask; - hi[1] = ((words[ 4] >> 56) | (words[ 5] << 8)) & mask; - hi[2] = ((words[ 5] >> 44) | (words[ 6] << 20)) & mask; - hi[3] = ((words[ 6] >> 32) | (words[ 7] << 32)) & mask; - hi[4] = words[ 7] >> 20 ; - - lo = Scalar52::montgomery_mul(&lo, &constants::R); // (lo * R) / R = lo - hi = Scalar52::montgomery_mul(&hi, &constants::RR); // (hi * R^2) / R = hi * R - - Scalar52::add(&hi, &lo) - } - - /// Pack the limbs of this `Scalar52` into 32 bytes - pub fn to_bytes(&self) -> [u8; 32] { - let mut s = [0u8; 32]; - - s[0] = (self.0[ 0] >> 0) as u8; - s[1] = (self.0[ 0] >> 8) as u8; - s[2] = (self.0[ 0] >> 16) as u8; - s[3] = (self.0[ 0] >> 24) as u8; - s[4] = (self.0[ 0] >> 32) as u8; - s[5] = (self.0[ 0] >> 40) as u8; - s[6] = ((self.0[ 0] >> 48) | (self.0[ 1] << 4)) as u8; - s[7] = (self.0[ 1] >> 4) as u8; - s[8] = (self.0[ 1] >> 12) as u8; - s[9] = (self.0[ 1] >> 20) as u8; - s[10] = (self.0[ 1] >> 28) as u8; - s[11] = (self.0[ 1] >> 36) as u8; - s[12] = (self.0[ 1] >> 44) as u8; - s[13] = (self.0[ 2] >> 0) as u8; - s[14] = (self.0[ 2] >> 8) as u8; - s[15] = (self.0[ 2] >> 16) as u8; - s[16] = (self.0[ 2] >> 24) as u8; - s[17] = (self.0[ 2] >> 32) as u8; - s[18] = (self.0[ 2] >> 40) as u8; - s[19] = ((self.0[ 2] >> 48) | (self.0[ 3] << 4)) as u8; - s[20] = (self.0[ 3] >> 4) as u8; - s[21] = (self.0[ 3] >> 12) as u8; - s[22] = (self.0[ 3] >> 20) as u8; - s[23] = (self.0[ 3] >> 28) as u8; - s[24] = (self.0[ 3] >> 36) as u8; - s[25] = (self.0[ 3] >> 44) as u8; - s[26] = (self.0[ 4] >> 0) as u8; - s[27] = (self.0[ 4] >> 8) as u8; - s[28] = (self.0[ 4] >> 16) as u8; - s[29] = (self.0[ 4] >> 24) as u8; - s[30] = (self.0[ 4] >> 32) as u8; - s[31] = (self.0[ 4] >> 40) as u8; - - s - } - - /// Compute `a + b` (mod l) - pub fn add(a: &Scalar52, b: &Scalar52) -> Scalar52 { - let mut sum = Scalar52::zero(); - let mask = (1u64 << 52) - 1; - - // a + b - let mut carry: u64 = 0; - for i in 0..5 { - carry = a[i] + b[i] + (carry >> 52); - sum[i] = carry & mask; - } - - // subtract l if the sum is >= l - Scalar52::sub(&sum, &constants::L) - } - - /// Compute `a - b` (mod l) - pub fn sub(a: &Scalar52, b: &Scalar52) -> Scalar52 { - let mut difference = Scalar52::zero(); - let mask = (1u64 << 52) - 1; - - // a - b - let mut borrow: u64 = 0; - for i in 0..5 { - borrow = a[i].wrapping_sub(b[i] + (borrow >> 63)); - difference[i] = borrow & mask; - } - - // conditionally add l if the difference is negative - let underflow_mask = ((borrow >> 63) ^ 1).wrapping_sub(1); - let mut carry: u64 = 0; - for i in 0..5 { - carry = (carry >> 52) + difference[i] + (constants::L[i] & underflow_mask); - difference[i] = carry & mask; - } - - difference - } - - /// Compute `a * b` - #[inline(always)] - pub (crate) fn mul_internal(a: &Scalar52, b: &Scalar52) -> [u128; 9] { - let mut z = [0u128; 9]; - - z[0] = m(a[0],b[0]); - z[1] = m(a[0],b[1]) + m(a[1],b[0]); - z[2] = m(a[0],b[2]) + m(a[1],b[1]) + m(a[2],b[0]); - z[3] = m(a[0],b[3]) + m(a[1],b[2]) + m(a[2],b[1]) + m(a[3],b[0]); - z[4] = m(a[0],b[4]) + m(a[1],b[3]) + m(a[2],b[2]) + m(a[3],b[1]) + m(a[4],b[0]); - z[5] = m(a[1],b[4]) + m(a[2],b[3]) + m(a[3],b[2]) + m(a[4],b[1]); - z[6] = m(a[2],b[4]) + m(a[3],b[3]) + m(a[4],b[2]); - z[7] = m(a[3],b[4]) + m(a[4],b[3]); - z[8] = m(a[4],b[4]); - - z - } - - /// Compute `a^2` - #[inline(always)] - fn square_internal(a: &Scalar52) -> [u128; 9] { - let aa = [ - a[0]*2, - a[1]*2, - a[2]*2, - a[3]*2, - ]; - - [ - m( a[0],a[0]), - m(aa[0],a[1]), - m(aa[0],a[2]) + m( a[1],a[1]), - m(aa[0],a[3]) + m(aa[1],a[2]), - m(aa[0],a[4]) + m(aa[1],a[3]) + m( a[2],a[2]), - m(aa[1],a[4]) + m(aa[2],a[3]), - m(aa[2],a[4]) + m( a[3],a[3]), - m(aa[3],a[4]), - m(a[4],a[4]) - ] - } - - /// Compute `limbs/R` (mod l), where R is the Montgomery modulus 2^260 - #[inline(always)] - pub (crate) fn montgomery_reduce(limbs: &[u128; 9]) -> Scalar52 { - - #[inline(always)] - fn part1(sum: u128) -> (u128, u64) { - let p = (sum as u64).wrapping_mul(constants::LFACTOR) & ((1u64 << 52) - 1); - ((sum + m(p,constants::L[0])) >> 52, p) - } - - #[inline(always)] - fn part2(sum: u128) -> (u128, u64) { - let w = (sum as u64) & ((1u64 << 52) - 1); - (sum >> 52, w) - } - - // note: l[3] is zero, so its multiples can be skipped - let l = &constants::L; - - // the first half computes the Montgomery adjustment factor n, and begins adding n*l to make limbs divisible by R - let (carry, n0) = part1( limbs[0]); - let (carry, n1) = part1(carry + limbs[1] + m(n0,l[1])); - let (carry, n2) = part1(carry + limbs[2] + m(n0,l[2]) + m(n1,l[1])); - let (carry, n3) = part1(carry + limbs[3] + m(n1,l[2]) + m(n2,l[1])); - let (carry, n4) = part1(carry + limbs[4] + m(n0,l[4]) + m(n2,l[2]) + m(n3,l[1])); - - // limbs is divisible by R now, so we can divide by R by simply storing the upper half as the result - let (carry, r0) = part2(carry + limbs[5] + m(n1,l[4]) + m(n3,l[2]) + m(n4,l[1])); - let (carry, r1) = part2(carry + limbs[6] + m(n2,l[4]) + m(n4,l[2])); - let (carry, r2) = part2(carry + limbs[7] + m(n3,l[4]) ); - let (carry, r3) = part2(carry + limbs[8] + m(n4,l[4])); - let r4 = carry as u64; - - // result may be >= l, so attempt to subtract l - Scalar52::sub(&Scalar52([r0,r1,r2,r3,r4]), l) - } - - /// Compute `a * b` (mod l) - #[inline(never)] - pub fn mul(a: &Scalar52, b: &Scalar52) -> Scalar52 { - let ab = Scalar52::montgomery_reduce(&Scalar52::mul_internal(a, b)); - Scalar52::montgomery_reduce(&Scalar52::mul_internal(&ab, &constants::RR)) - } - - /// Compute `a^2` (mod l) - #[inline(never)] - #[allow(dead_code)] // XXX we don't expose square() via the Scalar API - pub fn square(&self) -> Scalar52 { - let aa = Scalar52::montgomery_reduce(&Scalar52::square_internal(self)); - Scalar52::montgomery_reduce(&Scalar52::mul_internal(&aa, &constants::RR)) - } - - /// Compute `(a * b) / R` (mod l), where R is the Montgomery modulus 2^260 - #[inline(never)] - pub fn montgomery_mul(a: &Scalar52, b: &Scalar52) -> Scalar52 { - Scalar52::montgomery_reduce(&Scalar52::mul_internal(a, b)) - } - - /// Compute `(a^2) / R` (mod l) in Montgomery form, where R is the Montgomery modulus 2^260 - #[inline(never)] - pub fn montgomery_square(&self) -> Scalar52 { - Scalar52::montgomery_reduce(&Scalar52::square_internal(self)) - } - - /// Puts a Scalar52 in to Montgomery form, i.e. computes `a*R (mod l)` - #[inline(never)] - pub fn to_montgomery(&self) -> Scalar52 { - Scalar52::montgomery_mul(self, &constants::RR) - } - - /// Takes a Scalar52 out of Montgomery form, i.e. computes `a/R (mod l)` - #[inline(never)] - pub fn from_montgomery(&self) -> Scalar52 { - let mut limbs = [0u128; 9]; - for i in 0..5 { - limbs[i] = self[i] as u128; - } - Scalar52::montgomery_reduce(&limbs) - } -} - - -#[cfg(test)] -mod test { - use super::*; - - /// Note: x is 2^253-1 which is slightly larger than the largest scalar produced by - /// this implementation (l-1), and should show there are no overflows for valid scalars - /// - /// x = 14474011154664524427946373126085988481658748083205070504932198000989141204991 - /// x = 7237005577332262213973186563042994240801631723825162898930247062703686954002 mod l - /// x = 3057150787695215392275360544382990118917283750546154083604586903220563173085*R mod l in Montgomery form - pub static X: Scalar52 = Scalar52( - [0x000fffffffffffff, 0x000fffffffffffff, 0x000fffffffffffff, 0x000fffffffffffff, - 0x00001fffffffffff]); - - /// x^2 = 3078544782642840487852506753550082162405942681916160040940637093560259278169 mod l - pub static XX: Scalar52 = Scalar52( - [0x0001668020217559, 0x000531640ffd0ec0, 0x00085fd6f9f38a31, 0x000c268f73bb1cf4, - 0x000006ce65046df0]); - - /// x^2 = 4413052134910308800482070043710297189082115023966588301924965890668401540959*R mod l in Montgomery form - pub static XX_MONT: Scalar52 = Scalar52( - [0x000c754eea569a5c, 0x00063b6ed36cb215, 0x0008ffa36bf25886, 0x000e9183614e7543, - 0x0000061db6c6f26f]); - - /// y = 6145104759870991071742105800796537629880401874866217824609283457819451087098 - pub static Y: Scalar52 = Scalar52( - [0x000b75071e1458fa, 0x000bf9d75e1ecdac, 0x000433d2baf0672b, 0x0005fffcc11fad13, - 0x00000d96018bb825]); - - /// x*y = 36752150652102274958925982391442301741 mod l - pub static XY: Scalar52 = Scalar52( - [0x000ee6d76ba7632d, 0x000ed50d71d84e02, 0x00000000001ba634, 0x0000000000000000, - 0x0000000000000000]); - - /// x*y = 658448296334113745583381664921721413881518248721417041768778176391714104386*R mod l in Montgomery form - pub static XY_MONT: Scalar52 = Scalar52( - [0x0006d52bf200cfd5, 0x00033fb1d7021570, 0x000f201bc07139d8, 0x0001267e3e49169e, - 0x000007b839c00268]); - - /// a = 2351415481556538453565687241199399922945659411799870114962672658845158063753 - pub static A: Scalar52 = Scalar52( - [0x0005236c07b3be89, 0x0001bc3d2a67c0c4, 0x000a4aa782aae3ee, 0x0006b3f6e4fec4c4, - 0x00000532da9fab8c]); - - /// b = 4885590095775723760407499321843594317911456947580037491039278279440296187236 - pub static B: Scalar52 = Scalar52( - [0x000d3fae55421564, 0x000c2df24f65a4bc, 0x0005b5587d69fb0b, 0x00094c091b013b3b, - 0x00000acd25605473]); - - /// a+b = 0 - /// a-b = 4702830963113076907131374482398799845891318823599740229925345317690316127506 - pub static AB: Scalar52 = Scalar52( - [0x000a46d80f677d12, 0x0003787a54cf8188, 0x0004954f0555c7dc, 0x000d67edc9fd8989, - 0x00000a65b53f5718]); - - // c = (2^512 - 1) % l = 1627715501170711445284395025044413883736156588369414752970002579683115011840 - pub static C: Scalar52 = Scalar52( - [0x000611e3449c0f00, 0x000a768859347a40, 0x0007f5be65d00e1b, 0x0009a3dceec73d21, - 0x00000399411b7c30]); - - #[test] - fn mul_max() { - let res = Scalar52::mul(&X, &X); - for i in 0..5 { - assert!(res[i] == XX[i]); - } - } - - #[test] - fn square_max() { - let res = X.square(); - for i in 0..5 { - assert!(res[i] == XX[i]); - } - } - - #[test] - fn montgomery_mul_max() { - let res = Scalar52::montgomery_mul(&X, &X); - for i in 0..5 { - assert!(res[i] == XX_MONT[i]); - } - } - - #[test] - fn montgomery_square_max() { - let res = X.montgomery_square(); - for i in 0..5 { - assert!(res[i] == XX_MONT[i]); - } - } - - #[test] - fn mul() { - let res = Scalar52::mul(&X, &Y); - for i in 0..5 { - assert!(res[i] == XY[i]); - } - } - - #[test] - fn montgomery_mul() { - let res = Scalar52::montgomery_mul(&X, &Y); - for i in 0..5 { - assert!(res[i] == XY_MONT[i]); - } - } - - #[test] - fn add() { - let res = Scalar52::add(&A, &B); - let zero = Scalar52::zero(); - for i in 0..5 { - assert!(res[i] == zero[i]); - } - } - - #[test] - fn sub() { - let res = Scalar52::sub(&A, &B); - for i in 0..5 { - assert!(res[i] == AB[i]); - } - } - - #[test] - fn from_bytes_wide() { - let bignum = [255u8; 64]; // 2^512 - 1 - let reduced = Scalar52::from_bytes_wide(&bignum); - for i in 0..5 { - assert!(reduced[i] == C[i]); - } - } -} diff --git a/net/gurk-rs/files/vendor/curve25519-dalek/src/backend/vector/avx2/constants.rs b/net/gurk-rs/files/vendor/curve25519-dalek/src/backend/vector/avx2/constants.rs deleted file mode 100644 index 122068e..0000000 --- a/net/gurk-rs/files/vendor/curve25519-dalek/src/backend/vector/avx2/constants.rs +++ /dev/null @@ -1,3428 +0,0 @@ -// -*- mode: rust; -*- -// -// This file is part of curve25519-dalek. -// Copyright (c) 2016-2021 isis lovecruft -// Copyright (c) 2016-2019 Henry de Valence -// See LICENSE for licensing information. -// -// Authors: -// - isis agora lovecruft -// - Henry de Valence - -//! This module contains constants used by the AVX2 backend. - -use packed_simd::u32x8; - -use backend::vector::avx2::edwards::{CachedPoint, ExtendedPoint}; -use backend::vector::avx2::field::FieldElement2625x4; -use window::NafLookupTable8; - -/// The identity element as an `ExtendedPoint`. -pub(crate) static EXTENDEDPOINT_IDENTITY: ExtendedPoint = ExtendedPoint(FieldElement2625x4([ - u32x8::new(0, 1, 0, 0, 1, 0, 0, 0), - u32x8::splat(0), - u32x8::splat(0), - u32x8::splat(0), - u32x8::splat(0), -])); - -/// The identity element as a `CachedPoint`. -pub(crate) static CACHEDPOINT_IDENTITY: CachedPoint = CachedPoint(FieldElement2625x4([ - u32x8::new(121647, 121666, 0, 0, 243332, 67108845, 0, 33554431), - u32x8::new(67108864, 0, 33554431, 0, 0, 67108863, 0, 33554431), - u32x8::new(67108863, 0, 33554431, 0, 0, 67108863, 0, 33554431), - u32x8::new(67108863, 0, 33554431, 0, 0, 67108863, 0, 33554431), - u32x8::new(67108863, 0, 33554431, 0, 0, 67108863, 0, 33554431), -])); - -/// The low limbs of (2p, 2p, 2p, 2p), so that -/// ```ascii,no_run -/// (2p, 2p, 2p, 2p) = [P_TIMES_2_LO, P_TIMES_2_HI, P_TIMES_2_HI, P_TIMES_2_HI, P_TIMES_2_HI] -/// ``` -pub(crate) static P_TIMES_2_LO: u32x8 = u32x8::new( - 67108845 << 1, - 67108845 << 1, - 33554431 << 1, - 33554431 << 1, - 67108845 << 1, - 67108845 << 1, - 33554431 << 1, - 33554431 << 1, -); - -/// The high limbs of (2p, 2p, 2p, 2p), so that -/// ```ascii,no_run -/// (2p, 2p, 2p, 2p) = [P_TIMES_2_LO, P_TIMES_2_HI, P_TIMES_2_HI, P_TIMES_2_HI, P_TIMES_2_HI] -/// ``` -pub(crate) static P_TIMES_2_HI: u32x8 = u32x8::new( - 67108863 << 1, - 67108863 << 1, - 33554431 << 1, - 33554431 << 1, - 67108863 << 1, - 67108863 << 1, - 33554431 << 1, - 33554431 << 1, -); - -/// The low limbs of (16p, 16p, 16p, 16p), so that -/// ```ascii,no_run -/// (16p, 16p, 16p, 16p) = [P_TIMES_16_LO, P_TIMES_16_HI, P_TIMES_16_HI, P_TIMES_16_HI, P_TIMES_16_HI] -/// ``` -pub(crate) static P_TIMES_16_LO: u32x8 = u32x8::new( - 67108845 << 4, - 67108845 << 4, - 33554431 << 4, - 33554431 << 4, - 67108845 << 4, - 67108845 << 4, - 33554431 << 4, - 33554431 << 4, -); - -/// The high limbs of (16p, 16p, 16p, 16p), so that -/// ```ascii,no_run -/// (16p, 16p, 16p, 16p) = [P_TIMES_16_LO, P_TIMES_16_HI, P_TIMES_16_HI, P_TIMES_16_HI, P_TIMES_16_HI] -/// ``` -pub(crate) static P_TIMES_16_HI: u32x8 = u32x8::new( - 67108863 << 4, - 67108863 << 4, - 33554431 << 4, - 33554431 << 4, - 67108863 << 4, - 67108863 << 4, - 33554431 << 4, - 33554431 << 4, -); - -/// Odd multiples of the Ed25519 basepoint: -pub(crate) static BASEPOINT_ODD_LOOKUP_TABLE: NafLookupTable8 = NafLookupTable8([ - CachedPoint(FieldElement2625x4([ - u32x8::new( - 3571425, - 10045002, - 19036563, - 1096096, - 243332, - 65897020, - 0, - 28963681, - ), - u32x8::new( - 30896895, - 63055514, - 1614915, - 5095970, - 0, - 53791688, - 0, - 31258312, - ), - u32x8::new( - 13347627, - 40339464, - 2236269, - 11185503, - 0, - 22520087, - 0, - 8659512, - ), - u32x8::new( - 11125413, - 29139905, - 32037254, - 28360723, - 0, - 64556417, - 0, - 9635759, - ), - u32x8::new( - 33268144, - 47262491, - 4336918, - 15795740, - 0, - 22027545, - 0, - 4846528, - ), - ])), - CachedPoint(FieldElement2625x4([ - u32x8::new( - 47099681, - 31447946, - 29365447, - 24740513, - 42991046, - 18317844, - 16051644, - 21404226, - ), - u32x8::new( - 31708133, - 28909527, - 2366091, - 13703791, - 469246, - 54159622, - 2601402, - 32988002, - ), - u32x8::new( - 63432457, - 30251794, - 15163516, - 18491340, - 28144087, - 35605455, - 13682295, - 18474872, - ), - u32x8::new( - 12221607, - 4967598, - 26061980, - 26008006, - 20226147, - 9726961, - 17410, - 18051083, - ), - u32x8::new( - 60569645, - 62487085, - 11911242, - 21920922, - 4092105, - 38186967, - 22431483, - 31366585, - ), - ])), - CachedPoint(FieldElement2625x4([ - u32x8::new( - 18147205, - 62587998, - 2554617, - 536692, - 11924528, - 26674131, - 17645433, - 24341419, - ), - u32x8::new( - 11573357, - 27579485, - 31491870, - 29000885, - 10800976, - 51902791, - 28076395, - 20464029, - ), - u32x8::new( - 56031649, - 10856669, - 11791193, - 26769430, - 25306956, - 5922200, - 6630685, - 9385098, - ), - u32x8::new( - 31319348, - 23906711, - 16290213, - 32142166, - 61106354, - 17181823, - 3548308, - 12022566, - ), - u32x8::new( - 5904298, - 50218605, - 11826440, - 5492249, - 10379071, - 3472255, - 172742, - 31948344, - ), - ])), - CachedPoint(FieldElement2625x4([ - u32x8::new( - 10625852, - 15193821, - 22918394, - 23676410, - 53695416, - 54987793, - 10067515, - 11747680, - ), - u32x8::new( - 65013325, - 1309652, - 29616320, - 28922974, - 60360891, - 19621771, - 9938982, - 30406429, - ), - u32x8::new( - 54967954, - 65931918, - 5595602, - 25719523, - 64909864, - 30566415, - 15945272, - 8495317, - ), - u32x8::new( - 1167157, - 55265018, - 11507029, - 31641054, - 43497904, - 2367338, - 12937761, - 27517066, - ), - u32x8::new( - 656704, - 2544994, - 13006713, - 480979, - 38471594, - 62541240, - 25353597, - 11531760, - ), - ])), - CachedPoint(FieldElement2625x4([ - u32x8::new( - 22176662, - 3984313, - 27495285, - 4110608, - 2909584, - 30594106, - 15677919, - 2549183, - ), - u32x8::new( - 33979105, - 62269905, - 2071511, - 6894756, - 53189950, - 47232857, - 6408191, - 6123225, - ), - u32x8::new( - 32553873, - 63948030, - 12612401, - 3633166, - 24054373, - 37626618, - 14481327, - 8520484, - ), - u32x8::new( - 56552486, - 10749438, - 12034813, - 28811946, - 1445640, - 36755601, - 12104575, - 10257833, - ), - u32x8::new( - 22795808, - 48761311, - 1136056, - 9380768, - 1411523, - 5341811, - 27318329, - 9686767, - ), - ])), - CachedPoint(FieldElement2625x4([ - u32x8::new( - 21157200, - 39156966, - 20473176, - 4934657, - 61478183, - 45121537, - 5429856, - 13035023, - ), - u32x8::new( - 7954529, - 58789246, - 31440083, - 7054221, - 38438565, - 36856107, - 1364112, - 14548122, - ), - u32x8::new( - 26120083, - 36321360, - 4919997, - 31687496, - 33757765, - 36237559, - 15243054, - 32163861, - ), - u32x8::new( - 25878307, - 46544824, - 19455951, - 2414935, - 16844726, - 56521560, - 32680554, - 26660660, - ), - u32x8::new( - 48360220, - 43407178, - 12187042, - 24925816, - 7423722, - 25746484, - 12814654, - 17395963, - ), - ])), - CachedPoint(FieldElement2625x4([ - u32x8::new( - 63153652, - 32195955, - 4087908, - 8431689, - 30392384, - 47203165, - 8986649, - 9053039, - ), - u32x8::new( - 63659241, - 47988767, - 2931872, - 19953600, - 11747107, - 51610101, - 20952181, - 13364887, - ), - u32x8::new( - 3659197, - 58790649, - 5930099, - 2605312, - 28477896, - 580728, - 20579735, - 2610622, - ), - u32x8::new( - 41781607, - 17161358, - 10690531, - 24368015, - 47027031, - 36742339, - 5414694, - 13156365, - ), - u32x8::new( - 13237853, - 51182423, - 8954802, - 29006542, - 22643989, - 56896541, - 22830593, - 10289708, - ), - ])), - CachedPoint(FieldElement2625x4([ - u32x8::new( - 1401265, - 58846825, - 30911620, - 32239180, - 15391552, - 15200821, - 6339309, - 16403588, - ), - u32x8::new( - 55913797, - 29541724, - 1664461, - 21709410, - 38470488, - 47097092, - 17674945, - 32666066, - ), - u32x8::new( - 22844482, - 10797709, - 27548106, - 31638735, - 34500968, - 26611503, - 19727211, - 13160873, - ), - u32x8::new( - 31485204, - 14496164, - 13981208, - 10276888, - 5748808, - 35024436, - 2740987, - 7479021, - ), - u32x8::new( - 58541207, - 14866135, - 32344041, - 545930, - 62661488, - 6941250, - 27940205, - 11976112, - ), - ])), - CachedPoint(FieldElement2625x4([ - u32x8::new( - 39849808, - 44781685, - 15697329, - 24387845, - 12501486, - 50260092, - 23199481, - 31929024, - ), - u32x8::new( - 24823070, - 27956017, - 27034296, - 10316465, - 47664045, - 11152446, - 15719183, - 30181617, - ), - u32x8::new( - 20771189, - 19969144, - 31433937, - 19185213, - 27565920, - 10384445, - 2893359, - 9255362, - ), - u32x8::new( - 42894974, - 11925545, - 32134441, - 32738810, - 55916336, - 32479272, - 19563550, - 5511385, - ), - u32x8::new( - 17857161, - 47809169, - 14564114, - 27997751, - 33024640, - 38669671, - 31956536, - 27313245, - ), - ])), - CachedPoint(FieldElement2625x4([ - u32x8::new( - 58237774, - 15917425, - 18872208, - 19394230, - 17374297, - 6101419, - 4839741, - 6596900, - ), - u32x8::new( - 66947393, - 15744215, - 18368993, - 17750160, - 41006525, - 9205497, - 2629667, - 32170865, - ), - u32x8::new( - 66481381, - 1919414, - 28338762, - 7372967, - 33819153, - 4156199, - 27126309, - 12739816, - ), - u32x8::new( - 44117158, - 58545296, - 22521371, - 11809712, - 28998792, - 50731010, - 30215699, - 25748377, - ), - u32x8::new( - 23561284, - 4160244, - 9035405, - 24895184, - 39761639, - 59253416, - 8684759, - 22487864, - ), - ])), - CachedPoint(FieldElement2625x4([ - u32x8::new( - 12671134, - 56419053, - 16092401, - 30038207, - 4002647, - 47822606, - 7151311, - 28430768, - ), - u32x8::new( - 61041684, - 35765374, - 30598048, - 19666539, - 44150175, - 40140037, - 290469, - 28442674, - ), - u32x8::new( - 18847796, - 1371617, - 33316881, - 13199936, - 43646578, - 17068881, - 12074900, - 1537415, - ), - u32x8::new( - 10052225, - 38316070, - 27469797, - 5297537, - 50725570, - 20435349, - 10339121, - 2779737, - ), - u32x8::new( - 18372189, - 15466385, - 24762130, - 22217964, - 23503887, - 47844464, - 10415034, - 2606889, - ), - ])), - CachedPoint(FieldElement2625x4([ - u32x8::new( - 55082775, - 45300503, - 16032654, - 5964396, - 17743504, - 24634761, - 19493066, - 5184611, - ), - u32x8::new( - 50172633, - 35093294, - 10040575, - 23616256, - 4543900, - 61852191, - 4049821, - 7423669, - ), - u32x8::new( - 20295398, - 40009376, - 10487190, - 15670429, - 51972856, - 58649552, - 20436392, - 3432497, - ), - u32x8::new( - 35189420, - 54117751, - 12825868, - 6283038, - 27540739, - 30648758, - 22658912, - 9466689, - ), - u32x8::new( - 51737549, - 40725785, - 17409814, - 25201086, - 21156239, - 34176168, - 26814520, - 5956424, - ), - ])), - CachedPoint(FieldElement2625x4([ - u32x8::new( - 8211442, - 8014184, - 6260823, - 22108096, - 32182620, - 51844847, - 2466270, - 28582231, - ), - u32x8::new( - 27199739, - 3848333, - 31738017, - 10892045, - 4963982, - 65391770, - 32551997, - 28906469, - ), - u32x8::new( - 16606846, - 32207068, - 26404535, - 7614129, - 45416902, - 65584718, - 13821785, - 2646060, - ), - u32x8::new( - 36090634, - 57981287, - 32247670, - 22837502, - 31003861, - 55448117, - 6062915, - 20369975, - ), - u32x8::new( - 27381403, - 50578107, - 522631, - 29521058, - 31137497, - 40220737, - 27628049, - 1824195, - ), - ])), - CachedPoint(FieldElement2625x4([ - u32x8::new( - 59402443, - 17056879, - 29262689, - 6131785, - 52551472, - 43367471, - 29423199, - 18899208, - ), - u32x8::new( - 5749414, - 43514612, - 11365899, - 21514624, - 65591890, - 60945892, - 19841732, - 5628567, - ), - u32x8::new( - 19334369, - 52500268, - 12307673, - 5267367, - 3212103, - 9035822, - 29142161, - 30520954, - ), - u32x8::new( - 57261330, - 6819646, - 22089161, - 9800373, - 55155453, - 62250856, - 13766735, - 25244545, - ), - u32x8::new( - 54370226, - 61888301, - 24496089, - 2540581, - 65637506, - 60274355, - 18154273, - 11687259, - ), - ])), - CachedPoint(FieldElement2625x4([ - u32x8::new( - 12521903, - 26014045, - 13995625, - 33360175, - 23605474, - 7376434, - 27229267, - 17195036, - ), - u32x8::new( - 59482891, - 10074423, - 574357, - 3857753, - 61377787, - 50306685, - 5241065, - 20234396, - ), - u32x8::new( - 23674717, - 6997172, - 20771841, - 16858511, - 40565304, - 29973136, - 7049812, - 14585010, - ), - u32x8::new( - 1427477, - 13295732, - 31762066, - 31499740, - 60419925, - 54666164, - 22009424, - 8089609, - ), - u32x8::new( - 58154031, - 41593020, - 15342328, - 957047, - 38937260, - 37037498, - 24871992, - 32973409, - ), - ])), - CachedPoint(FieldElement2625x4([ - u32x8::new( - 30654745, - 51286025, - 21206982, - 2433562, - 12780105, - 31732574, - 33087964, - 33081189, - ), - u32x8::new( - 66640017, - 42720009, - 16567620, - 15300745, - 1530367, - 33001123, - 20930247, - 21042661, - ), - u32x8::new( - 15003356, - 5294119, - 22985605, - 18928772, - 32628461, - 18230172, - 14773298, - 27193722, - ), - u32x8::new( - 27555, - 65346287, - 17017174, - 7837720, - 21499787, - 42855613, - 22474984, - 13675085, - ), - u32x8::new( - 24164369, - 50130116, - 5973149, - 24152073, - 1577334, - 25400030, - 18648484, - 32228854, - ), - ])), - CachedPoint(FieldElement2625x4([ - u32x8::new( - 49518649, - 59119280, - 31670678, - 20396561, - 61728330, - 651402, - 176032, - 9529498, - ), - u32x8::new( - 61765532, - 9082232, - 32794568, - 15526956, - 48543100, - 32614212, - 19001206, - 25680229, - ), - u32x8::new( - 32086091, - 10373081, - 8996131, - 31822823, - 35788988, - 49973190, - 30542040, - 17858455, - ), - u32x8::new( - 48130197, - 58121889, - 27753291, - 29923268, - 54448075, - 43300790, - 9336565, - 15770022, - ), - u32x8::new( - 57725546, - 20557498, - 9366233, - 16023566, - 16189031, - 2837363, - 24315301, - 27003505, - ), - ])), - CachedPoint(FieldElement2625x4([ - u32x8::new( - 28286608, - 10767548, - 18220739, - 5413236, - 48253387, - 58255702, - 11864864, - 28527159, - ), - u32x8::new( - 45038176, - 58655197, - 25648758, - 10951484, - 42564382, - 34542843, - 23146954, - 22234334, - ), - u32x8::new( - 14858710, - 24978793, - 15040559, - 4379220, - 47621477, - 40271440, - 15650420, - 1998736, - ), - u32x8::new( - 24106391, - 9626149, - 344505, - 25253814, - 34579800, - 59687089, - 25718289, - 25904133, - ), - u32x8::new( - 1981195, - 37751302, - 26132048, - 1764722, - 13288231, - 28808622, - 12531301, - 18292949, - ), - ])), - CachedPoint(FieldElement2625x4([ - u32x8::new( - 13869851, - 31448904, - 14963539, - 7581293, - 20536485, - 35021083, - 21257574, - 33356609, - ), - u32x8::new( - 36903364, - 18429241, - 11097857, - 5943856, - 60583077, - 40015815, - 30509523, - 31915271, - ), - u32x8::new( - 49161801, - 40681915, - 67892, - 25454357, - 22779677, - 25798439, - 15964829, - 5863227, - ), - u32x8::new( - 60810637, - 4496471, - 5217137, - 14095116, - 50942411, - 50712663, - 2507380, - 26844507, - ), - u32x8::new( - 34579752, - 53519385, - 10859797, - 18816024, - 42552864, - 39478521, - 6783896, - 17277037, - ), - ])), - CachedPoint(FieldElement2625x4([ - u32x8::new( - 43287109, - 27900723, - 33182187, - 2766754, - 17041989, - 1018260, - 33392790, - 4830032, - ), - u32x8::new( - 60194178, - 30788903, - 24728888, - 14513195, - 20897010, - 28843233, - 20111980, - 17475240, - ), - u32x8::new( - 46042274, - 19257042, - 4628173, - 31649727, - 27388316, - 66631493, - 11541886, - 6408028, - ), - u32x8::new( - 57024680, - 49536568, - 32050358, - 31321917, - 17437691, - 49672356, - 2884755, - 20493991, - ), - u32x8::new( - 59553007, - 46782643, - 29001173, - 1814088, - 21930692, - 51319706, - 14965872, - 30748046, - ), - ])), - CachedPoint(FieldElement2625x4([ - u32x8::new( - 16441817, - 36111849, - 6900424, - 602234, - 46522199, - 16441484, - 8135070, - 21726541, - ), - u32x8::new( - 37711225, - 32701959, - 11679112, - 13125533, - 32154135, - 9407918, - 26554289, - 620848, - ), - u32x8::new( - 19233407, - 30086864, - 14679568, - 2797374, - 4892806, - 7993077, - 247658, - 5632804, - ), - u32x8::new( - 37427262, - 26675495, - 27125659, - 13496131, - 50718473, - 40115609, - 28505351, - 27837393, - ), - u32x8::new( - 196819, - 18410429, - 7070012, - 21691388, - 29763371, - 24754123, - 9727048, - 10930179, - ), - ])), - CachedPoint(FieldElement2625x4([ - u32x8::new( - 28319289, - 40734650, - 16225680, - 24739184, - 64272368, - 35356897, - 7866648, - 13635853, - ), - u32x8::new( - 34165295, - 48328447, - 27041670, - 23643655, - 48949950, - 52963288, - 30411133, - 6045174, - ), - u32x8::new( - 18583559, - 41649834, - 9813585, - 26098520, - 25682734, - 26733526, - 19276490, - 10654728, - ), - u32x8::new( - 34867476, - 52715968, - 5694571, - 13380978, - 15134994, - 1831255, - 8608001, - 17266401, - ), - u32x8::new( - 59925903, - 44282172, - 27802465, - 1855069, - 14234749, - 36635487, - 11302294, - 10938429, - ), - ])), - CachedPoint(FieldElement2625x4([ - u32x8::new( - 8373273, - 49064494, - 4932071, - 32997499, - 38472880, - 29335908, - 14504412, - 22460029, - ), - u32x8::new( - 31795930, - 50785923, - 25835990, - 25790073, - 65669841, - 11360450, - 9969157, - 9008164, - ), - u32x8::new( - 50262498, - 45869261, - 16124434, - 15336007, - 882762, - 42522623, - 11277198, - 26296377, - ), - u32x8::new( - 42332732, - 59129236, - 14452816, - 567985, - 208061, - 34722729, - 32008143, - 14828749, - ), - u32x8::new( - 17937794, - 36846032, - 32102665, - 4442466, - 19745435, - 31633451, - 7146411, - 15812027, - ), - ])), - CachedPoint(FieldElement2625x4([ - u32x8::new( - 30741269, - 38648744, - 12562645, - 30092623, - 25073992, - 28730659, - 27911745, - 30000958, - ), - u32x8::new( - 2859794, - 25991700, - 17776078, - 27091930, - 2328322, - 60061146, - 18581824, - 18039008, - ), - u32x8::new( - 58206333, - 17917354, - 1972306, - 11853766, - 2655376, - 60543390, - 18416710, - 13287440, - ), - u32x8::new( - 62746330, - 61423885, - 21246577, - 2266675, - 60099139, - 14804707, - 14772234, - 20679434, - ), - u32x8::new( - 26987698, - 15488817, - 715616, - 2339565, - 51980752, - 17333865, - 21965103, - 10839820, - ), - ])), - CachedPoint(FieldElement2625x4([ - u32x8::new( - 18672548, - 57660959, - 16042910, - 19519287, - 62865851, - 17580961, - 26628347, - 23774759, - ), - u32x8::new( - 368070, - 3464471, - 25888304, - 30370559, - 52396053, - 45426828, - 28745251, - 9246829, - ), - u32x8::new( - 29090099, - 57950037, - 23104657, - 4903923, - 10987778, - 56163684, - 23621539, - 10332760, - ), - u32x8::new( - 53338235, - 44851161, - 21606845, - 31069622, - 4243630, - 34464392, - 11286454, - 5802022, - ), - u32x8::new( - 46710757, - 63389067, - 11642865, - 1980986, - 12967337, - 28162061, - 3854192, - 30432268, - ), - ])), - CachedPoint(FieldElement2625x4([ - u32x8::new( - 12179834, - 41005450, - 12809619, - 33525228, - 4624405, - 46957889, - 16968743, - 11827816, - ), - u32x8::new( - 51521162, - 12466775, - 31791271, - 15303651, - 49798465, - 62714504, - 6509600, - 12918560, - ), - u32x8::new( - 20445559, - 1756449, - 28848701, - 7920171, - 9835040, - 5900071, - 28757409, - 12376688, - ), - u32x8::new( - 18259496, - 14281012, - 21767026, - 10232236, - 20000226, - 12400540, - 4104902, - 23570543, - ), - u32x8::new( - 3687440, - 26546648, - 13328821, - 26841081, - 49822734, - 22334054, - 244496, - 24862543, - ), - ])), - CachedPoint(FieldElement2625x4([ - u32x8::new( - 59523541, - 62195428, - 3853227, - 13954801, - 12387708, - 47627615, - 27221350, - 17899572, - ), - u32x8::new( - 63193587, - 36343307, - 14595132, - 6880795, - 1364792, - 37648434, - 3259017, - 20536046, - ), - u32x8::new( - 30362834, - 10440372, - 9574624, - 11729232, - 63861613, - 21748389, - 5530846, - 2721586, - ), - u32x8::new( - 18339760, - 1550632, - 17170271, - 25732971, - 28459263, - 63142237, - 21642345, - 31557672, - ), - u32x8::new( - 10611282, - 5204623, - 18049257, - 214175, - 19432723, - 49809070, - 26010406, - 27449522, - ), - ])), - CachedPoint(FieldElement2625x4([ - u32x8::new( - 19770733, - 26478685, - 9464541, - 29158041, - 28604307, - 45196604, - 7586524, - 6641859, - ), - u32x8::new( - 65654484, - 52230498, - 30886612, - 19112823, - 47271809, - 38942611, - 16020035, - 10773481, - ), - u32x8::new( - 27464323, - 54451016, - 20646645, - 17732915, - 23008717, - 53626684, - 3253189, - 15614410, - ), - u32x8::new( - 52381752, - 40693008, - 7063024, - 28469981, - 51159478, - 44543211, - 19941777, - 5985451, - ), - u32x8::new( - 13553668, - 35524849, - 14788737, - 1883845, - 12385775, - 47958835, - 29135466, - 1776722, - ), - ])), - CachedPoint(FieldElement2625x4([ - u32x8::new( - 36719806, - 20827965, - 23175373, - 32996806, - 42041892, - 65708790, - 5467143, - 20884008, - ), - u32x8::new( - 43256281, - 40770646, - 17244063, - 31959819, - 64366384, - 43544617, - 25057754, - 12628720, - ), - u32x8::new( - 17337782, - 58472057, - 27906934, - 15305274, - 30292418, - 39284317, - 16946773, - 24806712, - ), - u32x8::new( - 6485126, - 32447403, - 16261486, - 13561940, - 49439635, - 10738368, - 16419889, - 8897231, - ), - u32x8::new( - 44812203, - 40122262, - 25496058, - 2759794, - 25295304, - 52178368, - 24154195, - 29334408, - ), - ])), - CachedPoint(FieldElement2625x4([ - u32x8::new( - 42307254, - 57217102, - 1088936, - 3832827, - 33905401, - 23130334, - 6958056, - 12622851, - ), - u32x8::new( - 3881189, - 14870059, - 19712830, - 6071598, - 38147944, - 60776394, - 3427938, - 13765703, - ), - u32x8::new( - 7666911, - 24227591, - 17077136, - 22967588, - 6874639, - 30915523, - 11451695, - 24292224, - ), - u32x8::new( - 13659529, - 31984463, - 28764736, - 20506164, - 64729627, - 49321636, - 28284636, - 25472371, - ), - u32x8::new( - 39360308, - 42281399, - 9446504, - 868960, - 49227724, - 21351115, - 30561851, - 11292096, - ), - ])), - CachedPoint(FieldElement2625x4([ - u32x8::new( - 7071115, - 46444090, - 5387916, - 15432877, - 27226682, - 41506862, - 2398278, - 3978240, - ), - u32x8::new( - 51009614, - 54216973, - 24368938, - 31392616, - 38456150, - 62313644, - 6729154, - 99724, - ), - u32x8::new( - 17474332, - 62857913, - 2619930, - 30659308, - 18268181, - 32809239, - 22826292, - 24561895, - ), - u32x8::new( - 38187020, - 67003092, - 14118280, - 16500577, - 18808560, - 64983716, - 25712929, - 32518261, - ), - u32x8::new( - 25735813, - 62284262, - 10824872, - 20558596, - 48149681, - 31162667, - 22608274, - 26285185, - ), - ])), - CachedPoint(FieldElement2625x4([ - u32x8::new( - 963440, - 63742255, - 10230323, - 25515008, - 32506414, - 6105697, - 25980317, - 24645129, - ), - u32x8::new( - 7162189, - 8101249, - 14679265, - 33443386, - 2002396, - 8541405, - 19442276, - 4795881, - ), - u32x8::new( - 8116694, - 51463069, - 4415528, - 25599140, - 55805721, - 39582709, - 6719436, - 30033839, - ), - u32x8::new( - 14468202, - 42181869, - 25188826, - 9639755, - 47546189, - 62711146, - 32762447, - 18338064, - ), - u32x8::new( - 33880058, - 32810909, - 8969931, - 13095238, - 38360605, - 40138517, - 9246134, - 4928058, - ), - ])), - CachedPoint(FieldElement2625x4([ - u32x8::new( - 63655588, - 17883670, - 9410246, - 26162761, - 5000571, - 7349225, - 23785252, - 32751089, - ), - u32x8::new( - 28568737, - 10733123, - 9342397, - 21570673, - 54096560, - 32467591, - 20494687, - 21511513, - ), - u32x8::new( - 47675157, - 47932807, - 29250946, - 15672208, - 59760469, - 9945465, - 14939287, - 18437405, - ), - u32x8::new( - 37985267, - 8609815, - 31573002, - 3373596, - 47828883, - 20834216, - 13248616, - 24154292, - ), - u32x8::new( - 5543543, - 29553242, - 3386453, - 30501150, - 25058089, - 15236571, - 8814395, - 32462955, - ), - ])), - CachedPoint(FieldElement2625x4([ - u32x8::new( - 39158670, - 15322548, - 20495103, - 3312736, - 14557171, - 12985179, - 8044741, - 3176899, - ), - u32x8::new( - 24673290, - 29693310, - 21412266, - 18324699, - 2154518, - 40329021, - 17500543, - 3954277, - ), - u32x8::new( - 36758685, - 38738957, - 165513, - 14691866, - 3070475, - 10424235, - 17096536, - 16896898, - ), - u32x8::new( - 59790459, - 43094586, - 8720681, - 10423589, - 1122030, - 31545615, - 4463786, - 31811293, - ), - u32x8::new( - 49778992, - 60881044, - 20509974, - 5832494, - 64155961, - 31483358, - 4511231, - 20307815, - ), - ])), - CachedPoint(FieldElement2625x4([ - u32x8::new( - 2863373, - 40876242, - 26865913, - 24067353, - 15726407, - 40919070, - 12953902, - 9931535, - ), - u32x8::new( - 60934877, - 42512204, - 21649141, - 21945190, - 52211954, - 60984193, - 7046207, - 5363493, - ), - u32x8::new( - 4205971, - 64068464, - 18197273, - 7327176, - 51527794, - 21166920, - 20669933, - 11828242, - ), - u32x8::new( - 59782815, - 49617225, - 15379924, - 457923, - 9320508, - 21498914, - 3242540, - 31563182, - ), - u32x8::new( - 27714753, - 8664670, - 3366162, - 26338598, - 56775518, - 25796006, - 13129151, - 21388876, - ), - ])), - CachedPoint(FieldElement2625x4([ - u32x8::new( - 59276548, - 49972346, - 16795002, - 33455915, - 48430097, - 53857205, - 18627071, - 32474471, - ), - u32x8::new( - 42160315, - 50705892, - 13530540, - 28012698, - 19833221, - 55886870, - 20191784, - 9644313, - ), - u32x8::new( - 20372416, - 28414713, - 24084234, - 31804096, - 33815377, - 36131001, - 17251241, - 18291088, - ), - u32x8::new( - 56234667, - 14920441, - 2033267, - 29572003, - 1724043, - 45519699, - 17873735, - 501988, - ), - u32x8::new( - 50031659, - 31517850, - 15697583, - 1016845, - 43104661, - 54769582, - 8008601, - 27257051, - ), - ])), - CachedPoint(FieldElement2625x4([ - u32x8::new( - 52951491, - 66542164, - 14853573, - 30444631, - 12045973, - 24321813, - 16545674, - 18160646, - ), - u32x8::new( - 60107911, - 1126003, - 5947677, - 19486116, - 41119984, - 30860440, - 7935395, - 13354438, - ), - u32x8::new( - 17841328, - 11063269, - 1664538, - 26687568, - 6268968, - 22280371, - 17275484, - 4523163, - ), - u32x8::new( - 15886041, - 56799482, - 15446552, - 21712778, - 1005290, - 17827215, - 4978741, - 6854882, - ), - u32x8::new( - 34319277, - 47731002, - 20321804, - 28544575, - 29591814, - 63376351, - 24754545, - 26001714, - ), - ])), - CachedPoint(FieldElement2625x4([ - u32x8::new( - 66783087, - 5234346, - 46102, - 8566476, - 19947339, - 20180418, - 25398238, - 3726678, - ), - u32x8::new( - 63890180, - 46380965, - 20674069, - 5366544, - 59661487, - 48406612, - 31533614, - 7071217, - ), - u32x8::new( - 13104676, - 1406631, - 24326736, - 19854367, - 61039528, - 11019904, - 31967425, - 19219275, - ), - u32x8::new( - 39003597, - 30143957, - 15351834, - 8639435, - 57309582, - 61436794, - 15830475, - 10090318, - ), - u32x8::new( - 45923044, - 6700175, - 99413, - 21263025, - 23762647, - 53905481, - 6063914, - 10065424, - ), - ])), - CachedPoint(FieldElement2625x4([ - u32x8::new( - 42822326, - 57678669, - 4052879, - 25452667, - 54049411, - 2373092, - 22337016, - 7701046, - ), - u32x8::new( - 44382355, - 43307377, - 16761537, - 30373573, - 49790216, - 23230748, - 25655306, - 10519391, - ), - u32x8::new( - 919475, - 59371245, - 1273450, - 25558666, - 9724711, - 8556709, - 25755845, - 10887647, - ), - u32x8::new( - 25465699, - 44651158, - 17658392, - 11257418, - 29735193, - 22885150, - 7094716, - 26828565, - ), - u32x8::new( - 48237389, - 47661599, - 27054393, - 7328070, - 27280193, - 65616691, - 23062005, - 4170709, - ), - ])), - CachedPoint(FieldElement2625x4([ - u32x8::new( - 26535281, - 60238317, - 30343788, - 25790743, - 37993933, - 24614372, - 9523840, - 10401918, - ), - u32x8::new( - 2783987, - 29468958, - 4697011, - 19804475, - 37246678, - 46797720, - 10261254, - 18942252, - ), - u32x8::new( - 58135580, - 60247753, - 25301938, - 6844561, - 20949454, - 39844754, - 4552026, - 919057, - ), - u32x8::new( - 6694071, - 44126261, - 32285330, - 31370180, - 24603698, - 53328179, - 13971149, - 5325636, - ), - u32x8::new( - 64879487, - 582094, - 17982081, - 19190425, - 24951286, - 26923842, - 29077174, - 33286062, - ), - ])), - CachedPoint(FieldElement2625x4([ - u32x8::new( - 54863941, - 67016431, - 1224043, - 23371240, - 62940074, - 52101083, - 13523637, - 30366406, - ), - u32x8::new( - 36324581, - 25407485, - 18258623, - 4698602, - 50300544, - 2658516, - 26300935, - 2611030, - ), - u32x8::new( - 27183975, - 21791014, - 18105064, - 9875199, - 58118912, - 54198635, - 6400311, - 14767984, - ), - u32x8::new( - 33918318, - 42937962, - 14809334, - 22136592, - 10636588, - 29082337, - 29829692, - 28549776, - ), - u32x8::new( - 61080905, - 854212, - 12202487, - 20004503, - 9256495, - 6903981, - 20567109, - 347423, - ), - ])), - CachedPoint(FieldElement2625x4([ - u32x8::new( - 41391822, - 34336880, - 22362564, - 14247996, - 12115604, - 41583344, - 7639288, - 28910945, - ), - u32x8::new( - 62066617, - 59758859, - 26665947, - 11614812, - 65737664, - 45704543, - 30324810, - 12868376, - ), - u32x8::new( - 17491771, - 43589814, - 9454919, - 26047850, - 52629282, - 39304244, - 3868968, - 19296062, - ), - u32x8::new( - 17826638, - 30413590, - 32534225, - 32741469, - 15012391, - 14365713, - 33039233, - 14791399, - ), - u32x8::new( - 64115596, - 59197067, - 32739005, - 23275744, - 32954320, - 22241406, - 20788442, - 4942942, - ), - ])), - CachedPoint(FieldElement2625x4([ - u32x8::new( - 31956192, - 59570132, - 2784352, - 4237732, - 47222312, - 4860927, - 18658867, - 15279314, - ), - u32x8::new( - 63240583, - 28160478, - 23524941, - 13390861, - 66437406, - 57718120, - 33345312, - 28896298, - ), - u32x8::new( - 39026193, - 46239965, - 21440243, - 25070488, - 64012383, - 60999016, - 16517060, - 29565907, - ), - u32x8::new( - 18118181, - 60161496, - 4212092, - 23976240, - 36277753, - 62363144, - 5816868, - 16964362, - ), - u32x8::new( - 18196138, - 62490693, - 281468, - 7934713, - 56027312, - 62015725, - 4837237, - 32932252, - ), - ])), - CachedPoint(FieldElement2625x4([ - u32x8::new( - 29885826, - 51028067, - 30418143, - 33438769, - 62542283, - 39442528, - 31535876, - 143299, - ), - u32x8::new( - 17143063, - 56709783, - 14451852, - 15782104, - 32762665, - 14047066, - 26295037, - 5432487, - ), - u32x8::new( - 75151, - 533606, - 7539077, - 30926189, - 38410914, - 23771680, - 4872443, - 29199566, - ), - u32x8::new( - 61522396, - 48934708, - 16223126, - 207380, - 11171993, - 47975147, - 14164574, - 352966, - ), - u32x8::new( - 15449006, - 56530757, - 26796528, - 12045834, - 63738697, - 40667227, - 33001582, - 9101885, - ), - ])), - CachedPoint(FieldElement2625x4([ - u32x8::new( - 43331297, - 18431341, - 25801195, - 17267698, - 19365485, - 57295202, - 22218985, - 21284590, - ), - u32x8::new( - 2429849, - 19152559, - 10762172, - 22564684, - 21880390, - 66866426, - 20357935, - 22641906, - ), - u32x8::new( - 19771185, - 31652693, - 3666117, - 28136958, - 23624283, - 55101502, - 6313920, - 6783662, - ), - u32x8::new( - 3487137, - 7092443, - 11001876, - 26196524, - 47319246, - 44542068, - 17594073, - 15027760, - ), - u32x8::new( - 49563607, - 32191113, - 4991283, - 25400512, - 46539152, - 4155103, - 32368171, - 201203, - ), - ])), - CachedPoint(FieldElement2625x4([ - u32x8::new( - 20548943, - 14334571, - 4073874, - 6368588, - 53208883, - 56484515, - 15970071, - 25561889, - ), - u32x8::new( - 49915097, - 44030795, - 11202344, - 29284344, - 60258023, - 66225712, - 8075764, - 12383512, - ), - u32x8::new( - 45248912, - 4933668, - 9592153, - 5819559, - 31030983, - 38174071, - 32435814, - 7442522, - ), - u32x8::new( - 62688129, - 48218381, - 22089545, - 12897361, - 21050881, - 34278889, - 7569163, - 3225449, - ), - u32x8::new( - 19050183, - 51089071, - 32935757, - 22640195, - 66122318, - 47144608, - 18743677, - 25177079, - ), - ])), - CachedPoint(FieldElement2625x4([ - u32x8::new( - 41186817, - 46681702, - 31819867, - 32997133, - 38559207, - 27147015, - 30293819, - 16762988, - ), - u32x8::new( - 24154689, - 51762873, - 23883879, - 13510519, - 55338250, - 61224161, - 11663149, - 30803960, - ), - u32x8::new( - 18104238, - 14117824, - 11724021, - 21362053, - 65704761, - 35530242, - 13498058, - 33522849, - ), - u32x8::new( - 63812888, - 23995539, - 28920539, - 24005193, - 26412223, - 36582218, - 4251418, - 26160309, - ), - u32x8::new( - 16822053, - 66064082, - 3482145, - 31979593, - 45937188, - 54475379, - 612917, - 7976478, - ), - ])), - CachedPoint(FieldElement2625x4([ - u32x8::new( - 46509314, - 55327128, - 8944536, - 274914, - 26432930, - 53829300, - 21192572, - 3569894, - ), - u32x8::new( - 20919764, - 64356651, - 30642344, - 17215170, - 20335124, - 11203745, - 18663316, - 19024174, - ), - u32x8::new( - 59297055, - 53842463, - 3680204, - 9806710, - 54004169, - 51484914, - 29807998, - 20134199, - ), - u32x8::new( - 14781592, - 22628010, - 26877930, - 25880359, - 30434803, - 190607, - 30184292, - 8991040, - ), - u32x8::new( - 64400983, - 64591751, - 854562, - 28216111, - 20010398, - 50414793, - 9803872, - 22687008, - ), - ])), - CachedPoint(FieldElement2625x4([ - u32x8::new( - 15091184, - 32550863, - 8818643, - 4244752, - 43123513, - 64565526, - 408838, - 13206998, - ), - u32x8::new( - 16405061, - 60379639, - 31489017, - 20949281, - 27568751, - 38734986, - 8364264, - 12451020, - ), - u32x8::new( - 16005217, - 58008076, - 1406778, - 26546927, - 39571784, - 56365493, - 31274296, - 8918790, - ), - u32x8::new( - 23271122, - 19453469, - 27718201, - 32742670, - 234332, - 36785342, - 22601675, - 14331046, - ), - u32x8::new( - 40636025, - 22442705, - 22115403, - 23745859, - 41164945, - 61012, - 12499614, - 542137, - ), - ])), - CachedPoint(FieldElement2625x4([ - u32x8::new( - 62776018, - 32835413, - 17373246, - 17187309, - 54469193, - 21770290, - 15923753, - 28996575, - ), - u32x8::new( - 59385210, - 63082298, - 12568449, - 8509004, - 9483342, - 16105238, - 5756054, - 26890758, - ), - u32x8::new( - 53987996, - 38201748, - 5521661, - 19060159, - 18663191, - 9093637, - 27786835, - 31189196, - ), - u32x8::new( - 65872678, - 43635130, - 27903055, - 25020300, - 65772737, - 38110437, - 5213502, - 21909342, - ), - u32x8::new( - 4438979, - 9680838, - 10212446, - 4764184, - 13235684, - 58245995, - 20264570, - 21024049, - ), - ])), - CachedPoint(FieldElement2625x4([ - u32x8::new( - 60835961, - 48209103, - 31049052, - 4688268, - 12426713, - 59829045, - 22302488, - 29008521, - ), - u32x8::new( - 50401667, - 29716596, - 23531224, - 7581281, - 49071895, - 6952617, - 14934683, - 8218256, - ), - u32x8::new( - 1601446, - 36631413, - 31774811, - 29625330, - 56786114, - 8331539, - 23129509, - 19783344, - ), - u32x8::new( - 59514327, - 64513110, - 1772300, - 5701338, - 5737511, - 16147555, - 9461515, - 5703271, - ), - u32x8::new( - 33072974, - 54300426, - 11940114, - 1308663, - 15627555, - 4931627, - 28443714, - 20924342, - ), - ])), - CachedPoint(FieldElement2625x4([ - u32x8::new( - 18135013, - 20358426, - 4922557, - 10015355, - 65729669, - 34786528, - 26248549, - 29194359, - ), - u32x8::new( - 797666, - 34997544, - 24316856, - 25107230, - 24612576, - 4761401, - 15307321, - 32404252, - ), - u32x8::new( - 16501152, - 60565831, - 9487105, - 9316022, - 24986054, - 31917592, - 3962024, - 2501883, - ), - u32x8::new( - 63356796, - 50432342, - 18044926, - 30566881, - 42032028, - 31415202, - 13524600, - 16119907, - ), - u32x8::new( - 3927286, - 57022374, - 9265437, - 21620772, - 19481940, - 3806938, - 24836192, - 14572399, - ), - ])), - CachedPoint(FieldElement2625x4([ - u32x8::new( - 10785787, - 46564798, - 368445, - 33181384, - 5319843, - 52687136, - 30347110, - 29837357, - ), - u32x8::new( - 56436732, - 47859251, - 24141084, - 22250712, - 59046084, - 4963427, - 33463413, - 17168859, - ), - u32x8::new( - 15512044, - 6366740, - 4737504, - 27644548, - 30307977, - 25037929, - 14593903, - 12836490, - ), - u32x8::new( - 63878897, - 34013023, - 5860752, - 7244096, - 3689461, - 57012135, - 18389096, - 11589351, - ), - u32x8::new( - 4682110, - 36302830, - 653422, - 22316819, - 14081831, - 5657024, - 11088376, - 24110612, - ), - ])), - CachedPoint(FieldElement2625x4([ - u32x8::new( - 39907267, - 45940262, - 24887471, - 18342609, - 878445, - 40456159, - 12019082, - 345107, - ), - u32x8::new( - 12794982, - 28893944, - 9447505, - 11387200, - 16961963, - 13916996, - 10893728, - 25898006, - ), - u32x8::new( - 44934162, - 53465865, - 3583620, - 1102334, - 53917811, - 63478576, - 2426066, - 10389549, - ), - u32x8::new( - 45096036, - 37595344, - 19367718, - 20257175, - 10280866, - 41653449, - 27665642, - 375926, - ), - u32x8::new( - 45847901, - 24064074, - 32494820, - 32204556, - 10720704, - 51079060, - 1297436, - 29853825, - ), - ])), - CachedPoint(FieldElement2625x4([ - u32x8::new( - 66303987, - 36060363, - 16494578, - 24962147, - 11971403, - 49538586, - 25060560, - 1964341, - ), - u32x8::new( - 25988481, - 27641502, - 24909517, - 27237087, - 66646363, - 52777626, - 16360849, - 10459972, - ), - u32x8::new( - 43930529, - 34374176, - 31225968, - 8807030, - 10394758, - 35904854, - 25325589, - 19335583, - ), - u32x8::new( - 25094697, - 34380951, - 20051185, - 32287161, - 11739332, - 53887441, - 30517319, - 26601892, - ), - u32x8::new( - 8868546, - 35635502, - 32513071, - 28248087, - 51946989, - 14222744, - 19198839, - 23261841, - ), - ])), - CachedPoint(FieldElement2625x4([ - u32x8::new( - 51218008, - 5070126, - 11046681, - 5320810, - 61212079, - 34104447, - 23895089, - 6460727, - ), - u32x8::new( - 39843528, - 46278671, - 10426120, - 25624792, - 66658766, - 37140083, - 28933107, - 12969597, - ), - u32x8::new( - 59635793, - 40220191, - 5751421, - 173680, - 58321825, - 740337, - 1412847, - 7682623, - ), - u32x8::new( - 975962, - 56440763, - 20812276, - 22631115, - 49095824, - 19883130, - 2419746, - 31043648, - ), - u32x8::new( - 66208703, - 39669328, - 22525915, - 3748897, - 65994776, - 34533552, - 8126286, - 18326047, - ), - ])), - CachedPoint(FieldElement2625x4([ - u32x8::new( - 64176557, - 3912400, - 19351673, - 30068471, - 31190055, - 24221683, - 33142424, - 28698542, - ), - u32x8::new( - 34784792, - 4109933, - 3867193, - 19557314, - 2112512, - 32715890, - 24550117, - 16595976, - ), - u32x8::new( - 35542761, - 48024875, - 10925431, - 31526577, - 66577735, - 23189821, - 13375709, - 1735095, - ), - u32x8::new( - 59699254, - 43854093, - 29783239, - 24777271, - 19600372, - 39924461, - 2896720, - 1472185, - ), - u32x8::new( - 56389656, - 35980854, - 33172342, - 1370336, - 23707480, - 57654949, - 7850973, - 12655016, - ), - ])), - CachedPoint(FieldElement2625x4([ - u32x8::new( - 38372660, - 57101970, - 7044964, - 12732710, - 57535705, - 6043201, - 30858914, - 10946592, - ), - u32x8::new( - 21023468, - 6946992, - 26403324, - 23901823, - 35695559, - 23440687, - 4763891, - 6514074, - ), - u32x8::new( - 28662273, - 30933699, - 9352242, - 26354829, - 37402243, - 3145176, - 8770289, - 525937, - ), - u32x8::new( - 54933102, - 36695832, - 3281859, - 4755022, - 23043294, - 32794379, - 15618886, - 23602412, - ), - u32x8::new( - 9931565, - 29897140, - 2480737, - 24193701, - 7833615, - 2284939, - 893926, - 13421882, - ), - ])), - CachedPoint(FieldElement2625x4([ - u32x8::new( - 22917795, - 22088359, - 28978099, - 19794863, - 60542318, - 29878494, - 31053731, - 9080720, - ), - u32x8::new( - 23679072, - 52547035, - 28424916, - 20647332, - 4008761, - 28267029, - 12961289, - 1589095, - ), - u32x8::new( - 55616194, - 26678929, - 14998265, - 23274397, - 54625466, - 46244264, - 28627706, - 33030665, - ), - u32x8::new( - 11527330, - 6449415, - 26531607, - 3472938, - 41541592, - 62607682, - 19862690, - 20564723, - ), - u32x8::new( - 32843805, - 49066843, - 28425824, - 19521495, - 48792073, - 48242878, - 27392443, - 13175986, - ), - ])), - CachedPoint(FieldElement2625x4([ - u32x8::new( - 16185025, - 61537525, - 2961305, - 1492442, - 25123147, - 3095034, - 31896958, - 33089615, - ), - u32x8::new( - 64748157, - 18336595, - 16522231, - 25426312, - 65718949, - 35485695, - 30554083, - 10205918, - ), - u32x8::new( - 39626934, - 39271045, - 16420458, - 9826240, - 56483981, - 27128085, - 3783403, - 13360006, - ), - u32x8::new( - 30793778, - 66771960, - 17241420, - 6564573, - 61102581, - 29974476, - 32385512, - 9011754, - ), - u32x8::new( - 28068166, - 11862220, - 14323567, - 12380617, - 52090465, - 16029056, - 24495309, - 21409233, - ), - ])), - CachedPoint(FieldElement2625x4([ - u32x8::new( - 59411973, - 57437124, - 11695483, - 17586857, - 16108987, - 43449109, - 31098002, - 6248476, - ), - u32x8::new( - 42258047, - 61595931, - 29308533, - 11742653, - 43042345, - 27373650, - 30165249, - 21929989, - ), - u32x8::new( - 49907221, - 9620337, - 21888081, - 20981082, - 56288861, - 61562203, - 33223566, - 3582446, - ), - u32x8::new( - 57535017, - 41003416, - 22080416, - 14463796, - 65518565, - 18127889, - 24370863, - 33332664, - ), - u32x8::new( - 66655380, - 6430175, - 471782, - 11947673, - 30596400, - 18898659, - 15930721, - 4211851, - ), - ])), - CachedPoint(FieldElement2625x4([ - u32x8::new( - 6757410, - 65455566, - 13584784, - 11362173, - 10797127, - 24451471, - 19541370, - 29309435, - ), - u32x8::new( - 40360156, - 17685025, - 18326181, - 3846903, - 13693365, - 63049479, - 31900359, - 23385063, - ), - u32x8::new( - 52455038, - 57513503, - 22163311, - 27095042, - 48610726, - 66454160, - 12085341, - 26357004, - ), - u32x8::new( - 22097042, - 14063840, - 6705778, - 14342902, - 66139825, - 20702105, - 31279090, - 7495745, - ), - u32x8::new( - 27360710, - 49314837, - 18774847, - 7146436, - 37066216, - 42004961, - 22409916, - 10524446, - ), - ])), - CachedPoint(FieldElement2625x4([ - u32x8::new( - 1497507, - 33054449, - 11839906, - 2960428, - 40538463, - 18884538, - 25018820, - 4073970, - ), - u32x8::new( - 54484385, - 43640735, - 2808257, - 20710708, - 39840730, - 27222424, - 21783544, - 11848522, - ), - u32x8::new( - 45765237, - 48200555, - 9299019, - 9393151, - 34818188, - 56098995, - 13575233, - 21012731, - ), - u32x8::new( - 4265428, - 49627650, - 24960282, - 9425650, - 47883651, - 2797524, - 11853190, - 22877329, - ), - u32x8::new( - 25008173, - 64199503, - 380047, - 12107343, - 12329448, - 11914399, - 764281, - 29687002, - ), - ])), - CachedPoint(FieldElement2625x4([ - u32x8::new( - 35889734, - 23047226, - 4022841, - 7017445, - 7274086, - 53316179, - 25100176, - 15310676, - ), - u32x8::new( - 42409427, - 30270106, - 6823853, - 31551384, - 40645017, - 66489807, - 18021817, - 32669351, - ), - u32x8::new( - 39827134, - 43680850, - 28297996, - 20258133, - 26058742, - 52643238, - 22238331, - 21690533, - ), - u32x8::new( - 60808002, - 17499995, - 30042246, - 29310584, - 48219954, - 29389518, - 8680514, - 17844709, - ), - u32x8::new( - 6452896, - 50116553, - 9532047, - 26821214, - 44524351, - 50428429, - 21904953, - 12608048, - ), - ])), -]); diff --git a/net/gurk-rs/files/vendor/curve25519-dalek/src/backend/vector/avx2/edwards.rs b/net/gurk-rs/files/vendor/curve25519-dalek/src/backend/vector/avx2/edwards.rs deleted file mode 100644 index 821d516..0000000 --- a/net/gurk-rs/files/vendor/curve25519-dalek/src/backend/vector/avx2/edwards.rs +++ /dev/null @@ -1,545 +0,0 @@ -// -*- mode: rust; -*- -// -// This file is part of curve25519-dalek. -// Copyright (c) 2016-2021 isis lovecruft -// Copyright (c) 2016-2019 Henry de Valence -// See LICENSE for licensing information. -// -// Authors: -// - isis agora lovecruft -// - Henry de Valence - -//! Parallel Edwards Arithmetic for Curve25519. -//! -//! This module currently has two point types: -//! -//! * `ExtendedPoint`: a point stored in vector-friendly format, with -//! vectorized doubling and addition; -//! -//! * `CachedPoint`: used for readdition. -//! -//! Details on the formulas can be found in the documentation for the -//! parent `avx2` module. -//! -//! This API is designed to be safe: vectorized points can only be -//! created from serial points (which do validation on decompression), -//! and operations on valid points return valid points, so invalid -//! point states should be unrepresentable. -//! -//! This design goal is met, with one exception: the `Neg` -//! implementation for the `CachedPoint` performs a lazy negation, so -//! that subtraction can be efficiently implemented as a negation and -//! an addition. Repeatedly negating a `CachedPoint` will cause its -//! coefficients to grow and eventually overflow. Repeatedly negating -//! a point should not be necessary anyways. - -#![allow(non_snake_case)] - -use core::convert::From; -use core::ops::{Add, Neg, Sub}; - -use subtle::Choice; -use subtle::ConditionallySelectable; - -use edwards; -use window::{LookupTable, NafLookupTable5, NafLookupTable8}; - -use traits::Identity; - -use super::constants; -use super::field::{FieldElement2625x4, Lanes, Shuffle}; - -/// A point on Curve25519, using parallel Edwards formulas for curve -/// operations. -/// -/// # Invariant -/// -/// The coefficients of an `ExtendedPoint` are bounded with -/// \\( b < 0.007 \\). -#[derive(Copy, Clone, Debug)] -pub struct ExtendedPoint(pub(super) FieldElement2625x4); - -impl From for ExtendedPoint { - fn from(P: edwards::EdwardsPoint) -> ExtendedPoint { - ExtendedPoint(FieldElement2625x4::new(&P.X, &P.Y, &P.Z, &P.T)) - } -} - -impl From for edwards::EdwardsPoint { - fn from(P: ExtendedPoint) -> edwards::EdwardsPoint { - let tmp = P.0.split(); - edwards::EdwardsPoint { - X: tmp[0], - Y: tmp[1], - Z: tmp[2], - T: tmp[3], - } - } -} - -impl ConditionallySelectable for ExtendedPoint { - fn conditional_select(a: &Self, b: &Self, choice: Choice) -> Self { - ExtendedPoint(FieldElement2625x4::conditional_select(&a.0, &b.0, choice)) - } - - fn conditional_assign(&mut self, other: &Self, choice: Choice) { - self.0.conditional_assign(&other.0, choice); - } -} - -impl Default for ExtendedPoint { - fn default() -> ExtendedPoint { - ExtendedPoint::identity() - } -} - -impl Identity for ExtendedPoint { - fn identity() -> ExtendedPoint { - constants::EXTENDEDPOINT_IDENTITY - } -} - -impl ExtendedPoint { - /// Compute the double of this point. - pub fn double(&self) -> ExtendedPoint { - // Want to compute (X1 Y1 Z1 X1+Y1). - // Not sure how to do this less expensively than computing - // (X1 Y1 Z1 T1) --(256bit shuffle)--> (X1 Y1 X1 Y1) - // (X1 Y1 X1 Y1) --(2x128b shuffle)--> (Y1 X1 Y1 X1) - // and then adding. - - // Set tmp0 = (X1 Y1 X1 Y1) - let mut tmp0 = self.0.shuffle(Shuffle::ABAB); - - // Set tmp1 = (Y1 X1 Y1 X1) - let mut tmp1 = tmp0.shuffle(Shuffle::BADC); - - // Set tmp0 = (X1 Y1 Z1 X1+Y1) - tmp0 = self.0.blend(tmp0 + tmp1, Lanes::D); - - // Set tmp1 = tmp0^2, negating the D values - tmp1 = tmp0.square_and_negate_D(); - // Now tmp1 = (S1 S2 S3 -S4) with b < 0.007 - - // See discussion of bounds in the module-level documentation. - // We want to compute - // - // + | S1 | S1 | S1 | S1 | - // + | S2 | | | S2 | - // + | | | S3 | | - // + | | | S3 | | - // + | | | |-S4 | - // + | | 2p | 2p | | - // - | | S2 | S2 | | - // ======================= - // S5 S6 S8 S9 - - let zero = FieldElement2625x4::zero(); - let S_1 = tmp1.shuffle(Shuffle::AAAA); - let S_2 = tmp1.shuffle(Shuffle::BBBB); - - tmp0 = zero.blend(tmp1 + tmp1, Lanes::C); - // tmp0 = (0, 0, 2S_3, 0) - tmp0 = tmp0.blend(tmp1, Lanes::D); - // tmp0 = (0, 0, 2S_3, -S_4) - tmp0 = tmp0 + S_1; - // tmp0 = ( S_1, S_1, S_1 + 2S_3, S_1 - S_4) - tmp0 = tmp0 + zero.blend(S_2, Lanes::AD); - // tmp0 = (S_1 + S_2, S_1, S_1 + 2S_3, S_1 + S_2 - S_4) - tmp0 = tmp0 + zero.blend(S_2.negate_lazy(), Lanes::BC); - // tmp0 = (S_1 + S_2, S_1 - S_2, S_1 - S_2 + 2S_3, S_1 + S_2 - S_4) - // b < ( 1.01, 1.6, 2.33, 1.6) - // Now tmp0 = (S_5, S_6, S_8, S_9) - - // Set tmp1 = ( S_9, S_6, S_6, S_9) - // b < ( 1.6, 1.6, 1.6, 1.6) - tmp1 = tmp0.shuffle(Shuffle::DBBD); - // Set tmp0 = ( S_8, S_5, S_8, S_5) - // b < (2.33, 1.01, 2.33, 1.01) - tmp0 = tmp0.shuffle(Shuffle::CACA); - - // Bounds on (tmp0, tmp1) are (2.33, 1.6) < (2.5, 1.75). - ExtendedPoint(&tmp0 * &tmp1) - } - - pub fn mul_by_pow_2(&self, k: u32) -> ExtendedPoint { - let mut tmp: ExtendedPoint = *self; - for _ in 0..k { - tmp = tmp.double(); - } - tmp - } -} - -/// A cached point with some precomputed variables used for readdition. -/// -/// # Warning -/// -/// It is not safe to negate this point more than once. -/// -/// # Invariant -/// -/// As long as the `CachedPoint` is not repeatedly negated, its -/// coefficients will be bounded with \\( b < 1.0 \\). -#[derive(Copy, Clone, Debug)] -pub struct CachedPoint(pub(super) FieldElement2625x4); - -impl From for CachedPoint { - fn from(P: ExtendedPoint) -> CachedPoint { - let mut x = P.0; - - x = x.blend(x.diff_sum(), Lanes::AB); - // x = (Y2 - X2, Y2 + X2, Z2, T2) = (S2 S3 Z2 T2) - - x = x * (121666, 121666, 2 * 121666, 2 * 121665); - // x = (121666*S2 121666*S3 2*121666*Z2 2*121665*T2) - - x = x.blend(-x, Lanes::D); - // x = (121666*S2 121666*S3 2*121666*Z2 -2*121665*T2) - - // The coefficients of the output are bounded with b < 0.007. - CachedPoint(x) - } -} - -impl Default for CachedPoint { - fn default() -> CachedPoint { - CachedPoint::identity() - } -} - -impl Identity for CachedPoint { - fn identity() -> CachedPoint { - constants::CACHEDPOINT_IDENTITY - } -} - -impl ConditionallySelectable for CachedPoint { - fn conditional_select(a: &Self, b: &Self, choice: Choice) -> Self { - CachedPoint(FieldElement2625x4::conditional_select(&a.0, &b.0, choice)) - } - - fn conditional_assign(&mut self, other: &Self, choice: Choice) { - self.0.conditional_assign(&other.0, choice); - } -} - -impl<'a> Neg for &'a CachedPoint { - type Output = CachedPoint; - /// Lazily negate the point. - /// - /// # Warning - /// - /// Because this method does not perform a reduction, it is not - /// safe to repeatedly negate a point. - fn neg(self) -> CachedPoint { - let swapped = self.0.shuffle(Shuffle::BACD); - CachedPoint(swapped.blend(swapped.negate_lazy(), Lanes::D)) - } -} - -impl<'a, 'b> Add<&'b CachedPoint> for &'a ExtendedPoint { - type Output = ExtendedPoint; - - /// Add an `ExtendedPoint` and a `CachedPoint`. - fn add(self, other: &'b CachedPoint) -> ExtendedPoint { - // The coefficients of an `ExtendedPoint` are reduced after - // every operation. If the `CachedPoint` was negated, its - // coefficients grow by one bit. So on input, `self` is - // bounded with `b < 0.007` and `other` is bounded with - // `b < 1.0`. - - let mut tmp = self.0; - - tmp = tmp.blend(tmp.diff_sum(), Lanes::AB); - // tmp = (Y1-X1 Y1+X1 Z1 T1) = (S0 S1 Z1 T1) with b < 1.6 - - // (tmp, other) bounded with b < (1.6, 1.0) < (2.5, 1.75). - tmp = &tmp * &other.0; - // tmp = (S0*S2' S1*S3' Z1*Z2' T1*T2') = (S8 S9 S10 S11) - - tmp = tmp.shuffle(Shuffle::ABDC); - // tmp = (S8 S9 S11 S10) - - tmp = tmp.diff_sum(); - // tmp = (S9-S8 S9+S8 S10-S11 S10+S11) = (S12 S13 S14 S15) - - let t0 = tmp.shuffle(Shuffle::ADDA); - // t0 = (S12 S15 S15 S12) - let t1 = tmp.shuffle(Shuffle::CBCB); - // t1 = (S14 S13 S14 S13) - - // All coefficients of t0, t1 are bounded with b < 1.6. - // Return (S12*S14 S15*S13 S15*S14 S12*S13) = (X3 Y3 Z3 T3) - ExtendedPoint(&t0 * &t1) - } -} - -impl<'a, 'b> Sub<&'b CachedPoint> for &'a ExtendedPoint { - type Output = ExtendedPoint; - - /// Implement subtraction by negating the point and adding. - /// - /// Empirically, this seems about the same cost as a custom - /// subtraction impl (maybe because the benefit is cancelled by - /// increased code size?) - fn sub(self, other: &'b CachedPoint) -> ExtendedPoint { - self + &(-other) - } -} - -impl<'a> From<&'a edwards::EdwardsPoint> for LookupTable { - fn from(point: &'a edwards::EdwardsPoint) -> Self { - let P = ExtendedPoint::from(*point); - let mut points = [CachedPoint::from(P); 8]; - for i in 0..7 { - points[i + 1] = (&P + &points[i]).into(); - } - LookupTable(points) - } -} - -impl<'a> From<&'a edwards::EdwardsPoint> for NafLookupTable5 { - fn from(point: &'a edwards::EdwardsPoint) -> Self { - let A = ExtendedPoint::from(*point); - let mut Ai = [CachedPoint::from(A); 8]; - let A2 = A.double(); - for i in 0..7 { - Ai[i + 1] = (&A2 + &Ai[i]).into(); - } - // Now Ai = [A, 3A, 5A, 7A, 9A, 11A, 13A, 15A] - NafLookupTable5(Ai) - } -} - -impl<'a> From<&'a edwards::EdwardsPoint> for NafLookupTable8 { - fn from(point: &'a edwards::EdwardsPoint) -> Self { - let A = ExtendedPoint::from(*point); - let mut Ai = [CachedPoint::from(A); 64]; - let A2 = A.double(); - for i in 0..63 { - Ai[i + 1] = (&A2 + &Ai[i]).into(); - } - // Now Ai = [A, 3A, 5A, 7A, 9A, 11A, 13A, 15A, ..., 127A] - NafLookupTable8(Ai) - } -} - -#[cfg(test)] -mod test { - use super::*; - - fn serial_add(P: edwards::EdwardsPoint, Q: edwards::EdwardsPoint) -> edwards::EdwardsPoint { - use backend::serial::u64::field::FieldElement51; - - let (X1, Y1, Z1, T1) = (P.X, P.Y, P.Z, P.T); - let (X2, Y2, Z2, T2) = (Q.X, Q.Y, Q.Z, Q.T); - - macro_rules! print_var { - ($x:ident) => { - println!("{} = {:?}", stringify!($x), $x.to_bytes()); - }; - } - - let S0 = &Y1 - &X1; // R1 - let S1 = &Y1 + &X1; // R3 - let S2 = &Y2 - &X2; // R2 - let S3 = &Y2 + &X2; // R4 - print_var!(S0); - print_var!(S1); - print_var!(S2); - print_var!(S3); - println!(""); - - let S4 = &S0 * &S2; // R5 = R1 * R2 - let S5 = &S1 * &S3; // R6 = R3 * R4 - let S6 = &Z1 * &Z2; // R8 - let S7 = &T1 * &T2; // R7 - print_var!(S4); - print_var!(S5); - print_var!(S6); - print_var!(S7); - println!(""); - - let S8 = &S4 * &FieldElement51([ 121666,0,0,0,0]); // R5 - let S9 = &S5 * &FieldElement51([ 121666,0,0,0,0]); // R6 - let S10 = &S6 * &FieldElement51([2*121666,0,0,0,0]); // R8 - let S11 = &S7 * &(-&FieldElement51([2*121665,0,0,0,0])); // R7 - print_var!(S8); - print_var!(S9); - print_var!(S10); - print_var!(S11); - println!(""); - - let S12 = &S9 - &S8; // R1 - let S13 = &S9 + &S8; // R4 - let S14 = &S10 - &S11; // R2 - let S15 = &S10 + &S11; // R3 - print_var!(S12); - print_var!(S13); - print_var!(S14); - print_var!(S15); - println!(""); - - let X3 = &S12 * &S14; // R1 * R2 - let Y3 = &S15 * &S13; // R3 * R4 - let Z3 = &S15 * &S14; // R2 * R3 - let T3 = &S12 * &S13; // R1 * R4 - - edwards::EdwardsPoint { - X: X3, - Y: Y3, - Z: Z3, - T: T3, - } - } - - fn addition_test_helper(P: edwards::EdwardsPoint, Q: edwards::EdwardsPoint) { - // Test the serial implementation of the parallel addition formulas - let R_serial: edwards::EdwardsPoint = serial_add(P.into(), Q.into()).into(); - - // Test the vector implementation of the parallel readdition formulas - let cached_Q = CachedPoint::from(ExtendedPoint::from(Q)); - let R_vector: edwards::EdwardsPoint = (&ExtendedPoint::from(P) + &cached_Q).into(); - let S_vector: edwards::EdwardsPoint = (&ExtendedPoint::from(P) - &cached_Q).into(); - - println!("Testing point addition:"); - println!("P = {:?}", P); - println!("Q = {:?}", Q); - println!("cached Q = {:?}", cached_Q); - println!("R = P + Q = {:?}", &P + &Q); - println!("R_serial = {:?}", R_serial); - println!("R_vector = {:?}", R_vector); - println!("S = P - Q = {:?}", &P - &Q); - println!("S_vector = {:?}", S_vector); - assert_eq!(R_serial.compress(), (&P + &Q).compress()); - assert_eq!(R_vector.compress(), (&P + &Q).compress()); - assert_eq!(S_vector.compress(), (&P - &Q).compress()); - println!("OK!\n"); - } - - #[test] - fn vector_addition_vs_serial_addition_vs_edwards_extendedpoint() { - use constants; - use scalar::Scalar; - - println!("Testing id +- id"); - let P = edwards::EdwardsPoint::identity(); - let Q = edwards::EdwardsPoint::identity(); - addition_test_helper(P, Q); - - println!("Testing id +- B"); - let P = edwards::EdwardsPoint::identity(); - let Q = constants::ED25519_BASEPOINT_POINT; - addition_test_helper(P, Q); - - println!("Testing B +- B"); - let P = constants::ED25519_BASEPOINT_POINT; - let Q = constants::ED25519_BASEPOINT_POINT; - addition_test_helper(P, Q); - - println!("Testing B +- kB"); - let P = constants::ED25519_BASEPOINT_POINT; - let Q = &constants::ED25519_BASEPOINT_TABLE * &Scalar::from(8475983829u64); - addition_test_helper(P, Q); - } - - fn serial_double(P: edwards::EdwardsPoint) -> edwards::EdwardsPoint { - let (X1, Y1, Z1, _T1) = (P.X, P.Y, P.Z, P.T); - - macro_rules! print_var { - ($x:ident) => { - println!("{} = {:?}", stringify!($x), $x.to_bytes()); - }; - } - - let S0 = &X1 + &Y1; // R1 - print_var!(S0); - println!(""); - - let S1 = X1.square(); - let S2 = Y1.square(); - let S3 = Z1.square(); - let S4 = S0.square(); - print_var!(S1); - print_var!(S2); - print_var!(S3); - print_var!(S4); - println!(""); - - let S5 = &S1 + &S2; - let S6 = &S1 - &S2; - let S7 = &S3 + &S3; - let S8 = &S7 + &S6; - let S9 = &S5 - &S4; - print_var!(S5); - print_var!(S6); - print_var!(S7); - print_var!(S8); - print_var!(S9); - println!(""); - - let X3 = &S8 * &S9; - let Y3 = &S5 * &S6; - let Z3 = &S8 * &S6; - let T3 = &S5 * &S9; - - edwards::EdwardsPoint { - X: X3, - Y: Y3, - Z: Z3, - T: T3, - } - } - - fn doubling_test_helper(P: edwards::EdwardsPoint) { - let R1: edwards::EdwardsPoint = serial_double(P.into()).into(); - let R2: edwards::EdwardsPoint = ExtendedPoint::from(P).double().into(); - println!("Testing point doubling:"); - println!("P = {:?}", P); - println!("(serial) R1 = {:?}", R1); - println!("(vector) R2 = {:?}", R2); - println!("P + P = {:?}", &P + &P); - assert_eq!(R1.compress(), (&P + &P).compress()); - assert_eq!(R2.compress(), (&P + &P).compress()); - println!("OK!\n"); - } - - #[test] - fn vector_doubling_vs_serial_doubling_vs_edwards_extendedpoint() { - use constants; - use scalar::Scalar; - - println!("Testing [2]id"); - let P = edwards::EdwardsPoint::identity(); - doubling_test_helper(P); - - println!("Testing [2]B"); - let P = constants::ED25519_BASEPOINT_POINT; - doubling_test_helper(P); - - println!("Testing [2]([k]B)"); - let P = &constants::ED25519_BASEPOINT_TABLE * &Scalar::from(8475983829u64); - doubling_test_helper(P); - } - - #[test] - fn basepoint_odd_lookup_table_verify() { - use constants; - use backend::vector::avx2::constants::{BASEPOINT_ODD_LOOKUP_TABLE}; - - let basepoint_odd_table = NafLookupTable8::::from(&constants::ED25519_BASEPOINT_POINT); - println!("basepoint_odd_lookup_table = {:?}", basepoint_odd_table); - - let table_B = &BASEPOINT_ODD_LOOKUP_TABLE; - for (b_vec, base_vec) in table_B.0.iter().zip(basepoint_odd_table.0.iter()) { - let b_splits = b_vec.0.split(); - let base_splits = base_vec.0.split(); - - assert_eq!(base_splits[0], b_splits[0]); - assert_eq!(base_splits[1], b_splits[1]); - assert_eq!(base_splits[2], b_splits[2]); - assert_eq!(base_splits[3], b_splits[3]); - } - } -} diff --git a/net/gurk-rs/files/vendor/curve25519-dalek/src/backend/vector/avx2/field.rs b/net/gurk-rs/files/vendor/curve25519-dalek/src/backend/vector/avx2/field.rs deleted file mode 100644 index 94a06ee..0000000 --- a/net/gurk-rs/files/vendor/curve25519-dalek/src/backend/vector/avx2/field.rs +++ /dev/null @@ -1,986 +0,0 @@ -// -*- mode: rust; -*- -// -// This file is part of curve25519-dalek. -// Copyright (c) 2016-2021 isis lovecruft -// Copyright (c) 2016-2019 Henry de Valence -// See LICENSE for licensing information. -// -// Authors: -// - isis agora lovecruft -// - Henry de Valence - -//! An implementation of 4-way vectorized 32bit field arithmetic using -//! AVX2. -//! -//! The `FieldElement2625x4` struct provides a vector of four field -//! elements, implemented using AVX2 operations. Its API is designed -//! to abstract away the platform-dependent details, so that point -//! arithmetic can be implemented only in terms of a vector of field -//! elements. -//! -//! At this level, the API is optimized for speed and not safety. The -//! `FieldElement2625x4` does not always perform reductions. The pre- -//! and post-conditions on the bounds of the coefficients are -//! documented for each method, but it is the caller's responsibility -//! to ensure that there are no overflows. - -#![allow(non_snake_case)] - -const A_LANES: u8 = 0b0000_0101; -const B_LANES: u8 = 0b0000_1010; -const C_LANES: u8 = 0b0101_0000; -const D_LANES: u8 = 0b1010_0000; - -#[allow(unused)] -const A_LANES64: u8 = 0b00_00_00_11; -#[allow(unused)] -const B_LANES64: u8 = 0b00_00_11_00; -#[allow(unused)] -const C_LANES64: u8 = 0b00_11_00_00; -#[allow(unused)] -const D_LANES64: u8 = 0b11_00_00_00; - -use core::ops::{Add, Mul, Neg}; -use packed_simd::{i32x8, u32x8, u64x4, IntoBits}; - -use backend::vector::avx2::constants::{P_TIMES_16_HI, P_TIMES_16_LO, P_TIMES_2_HI, P_TIMES_2_LO}; -use backend::serial::u64::field::FieldElement51; - -/// Unpack 32-bit lanes into 64-bit lanes: -/// ```ascii,no_run -/// (a0, b0, a1, b1, c0, d0, c1, d1) -/// ``` -/// into -/// ```ascii,no_run -/// (a0, 0, b0, 0, c0, 0, d0, 0) -/// (a1, 0, b1, 0, c1, 0, d1, 0) -/// ``` -#[inline(always)] -fn unpack_pair(src: u32x8) -> (u32x8, u32x8) { - let a: u32x8; - let b: u32x8; - let zero = i32x8::new(0, 0, 0, 0, 0, 0, 0, 0); - unsafe { - use core::arch::x86_64::_mm256_unpackhi_epi32; - use core::arch::x86_64::_mm256_unpacklo_epi32; - a = _mm256_unpacklo_epi32(src.into_bits(), zero.into_bits()).into_bits(); - b = _mm256_unpackhi_epi32(src.into_bits(), zero.into_bits()).into_bits(); - } - (a, b) -} - -/// Repack 64-bit lanes into 32-bit lanes: -/// ```ascii,no_run -/// (a0, 0, b0, 0, c0, 0, d0, 0) -/// (a1, 0, b1, 0, c1, 0, d1, 0) -/// ``` -/// into -/// ```ascii,no_run -/// (a0, b0, a1, b1, c0, d0, c1, d1) -/// ``` -#[inline(always)] -fn repack_pair(x: u32x8, y: u32x8) -> u32x8 { - unsafe { - use core::arch::x86_64::_mm256_blend_epi32; - use core::arch::x86_64::_mm256_shuffle_epi32; - - // Input: x = (a0, 0, b0, 0, c0, 0, d0, 0) - // Input: y = (a1, 0, b1, 0, c1, 0, d1, 0) - - let x_shuffled = _mm256_shuffle_epi32(x.into_bits(), 0b11_01_10_00); - let y_shuffled = _mm256_shuffle_epi32(y.into_bits(), 0b10_00_11_01); - - // x' = (a0, b0, 0, 0, c0, d0, 0, 0) - // y' = ( 0, 0, a1, b1, 0, 0, c1, d1) - - return _mm256_blend_epi32(x_shuffled, y_shuffled, 0b11001100).into_bits(); - } -} - -/// The `Lanes` enum represents a subset of the lanes `A,B,C,D` of a -/// `FieldElement2625x4`. -/// -/// It's used to specify blend operations without -/// having to know details about the data layout of the -/// `FieldElement2625x4`. -#[derive(Copy, Clone, Debug)] -pub enum Lanes { - C, - D, - AB, - AC, - CD, - AD, - BC, - ABCD, -} - -/// The `Shuffle` enum represents a shuffle of a `FieldElement2625x4`. -/// -/// The enum variants are named by what they do to a vector \\( -/// (A,B,C,D) \\); for instance, `Shuffle::BADC` turns \\( (A, B, C, -/// D) \\) into \\( (B, A, D, C) \\). -#[derive(Copy, Clone, Debug)] -pub enum Shuffle { - AAAA, - BBBB, - CACA, - DBBD, - ADDA, - CBCB, - ABAB, - BADC, - BACD, - ABDC, -} - -/// A vector of four field elements. -/// -/// Each operation on a `FieldElement2625x4` has documented effects on -/// the bounds of the coefficients. This API is designed for speed -/// and not safety; it is the caller's responsibility to ensure that -/// the post-conditions of one operation are compatible with the -/// pre-conditions of the next. -#[derive(Clone, Copy, Debug)] -pub struct FieldElement2625x4(pub(crate) [u32x8; 5]); - -use subtle::Choice; -use subtle::ConditionallySelectable; - -impl ConditionallySelectable for FieldElement2625x4 { - fn conditional_select( - a: &FieldElement2625x4, - b: &FieldElement2625x4, - choice: Choice, - ) -> FieldElement2625x4 { - let mask = (-(choice.unwrap_u8() as i32)) as u32; - let mask_vec = u32x8::splat(mask); - FieldElement2625x4([ - a.0[0] ^ (mask_vec & (a.0[0] ^ b.0[0])), - a.0[1] ^ (mask_vec & (a.0[1] ^ b.0[1])), - a.0[2] ^ (mask_vec & (a.0[2] ^ b.0[2])), - a.0[3] ^ (mask_vec & (a.0[3] ^ b.0[3])), - a.0[4] ^ (mask_vec & (a.0[4] ^ b.0[4])), - ]) - } - - fn conditional_assign( - &mut self, - other: &FieldElement2625x4, - choice: Choice, - ) { - let mask = (-(choice.unwrap_u8() as i32)) as u32; - let mask_vec = u32x8::splat(mask); - self.0[0] ^= mask_vec & (self.0[0] ^ other.0[0]); - self.0[1] ^= mask_vec & (self.0[1] ^ other.0[1]); - self.0[2] ^= mask_vec & (self.0[2] ^ other.0[2]); - self.0[3] ^= mask_vec & (self.0[3] ^ other.0[3]); - self.0[4] ^= mask_vec & (self.0[4] ^ other.0[4]); - } -} - -impl FieldElement2625x4 { - /// Split this vector into an array of four (serial) field - /// elements. - pub fn split(&self) -> [FieldElement51; 4] { - let mut out = [FieldElement51::zero(); 4]; - for i in 0..5 { - let a_2i = self.0[i].extract(0) as u64; // - let b_2i = self.0[i].extract(1) as u64; // - let a_2i_1 = self.0[i].extract(2) as u64; // `. - let b_2i_1 = self.0[i].extract(3) as u64; // | pre-swapped to avoid - let c_2i = self.0[i].extract(4) as u64; // | a cross lane shuffle - let d_2i = self.0[i].extract(5) as u64; // .' - let c_2i_1 = self.0[i].extract(6) as u64; // - let d_2i_1 = self.0[i].extract(7) as u64; // - - out[0].0[i] = a_2i + (a_2i_1 << 26); - out[1].0[i] = b_2i + (b_2i_1 << 26); - out[2].0[i] = c_2i + (c_2i_1 << 26); - out[3].0[i] = d_2i + (d_2i_1 << 26); - } - - out - } - - /// Rearrange the elements of this vector according to `control`. - /// - /// The `control` parameter should be a compile-time constant, so - /// that when this function is inlined, LLVM is able to lower the - /// shuffle using an immediate. - #[inline] - pub fn shuffle(&self, control: Shuffle) -> FieldElement2625x4 { - #[inline(always)] - fn shuffle_lanes(x: u32x8, control: Shuffle) -> u32x8 { - unsafe { - use core::arch::x86_64::_mm256_permutevar8x32_epi32; - - let c: u32x8 = match control { - Shuffle::AAAA => u32x8::new(0, 0, 2, 2, 0, 0, 2, 2), - Shuffle::BBBB => u32x8::new(1, 1, 3, 3, 1, 1, 3, 3), - Shuffle::CACA => u32x8::new(4, 0, 6, 2, 4, 0, 6, 2), - Shuffle::DBBD => u32x8::new(5, 1, 7, 3, 1, 5, 3, 7), - Shuffle::ADDA => u32x8::new(0, 5, 2, 7, 5, 0, 7, 2), - Shuffle::CBCB => u32x8::new(4, 1, 6, 3, 4, 1, 6, 3), - Shuffle::ABAB => u32x8::new(0, 1, 2, 3, 0, 1, 2, 3), - Shuffle::BADC => u32x8::new(1, 0, 3, 2, 5, 4, 7, 6), - Shuffle::BACD => u32x8::new(1, 0, 3, 2, 4, 5, 6, 7), - Shuffle::ABDC => u32x8::new(0, 1, 2, 3, 5, 4, 7, 6), - }; - // Note that this gets turned into a generic LLVM - // shuffle-by-constants, which can be lowered to a simpler - // instruction than a generic permute. - _mm256_permutevar8x32_epi32(x.into_bits(), c.into_bits()).into_bits() - } - } - - FieldElement2625x4([ - shuffle_lanes(self.0[0], control), - shuffle_lanes(self.0[1], control), - shuffle_lanes(self.0[2], control), - shuffle_lanes(self.0[3], control), - shuffle_lanes(self.0[4], control), - ]) - } - - /// Blend `self` with `other`, taking lanes specified in `control` from `other`. - /// - /// The `control` parameter should be a compile-time constant, so - /// that this function can be inlined and LLVM can lower it to a - /// blend instruction using an immediate. - #[inline] - pub fn blend(&self, other: FieldElement2625x4, control: Lanes) -> FieldElement2625x4 { - #[inline(always)] - fn blend_lanes(x: u32x8, y: u32x8, control: Lanes) -> u32x8 { - unsafe { - use core::arch::x86_64::_mm256_blend_epi32; - - // This would be much cleaner if we could factor out the match - // statement on the control. Unfortunately, rustc forgets - // constant-info very quickly, so we can't even write - // ``` - // match control { - // Lanes::C => { - // let imm = C_LANES as i32; - // _mm256_blend_epi32(..., imm) - // ``` - // let alone - // ``` - // let imm = match control { - // Lanes::C => C_LANES as i32, - // } - // _mm256_blend_epi32(..., imm) - // ``` - // even though both of these would be constant-folded by LLVM - // at a lower level (as happens in the shuffle implementation, - // which does not require a shuffle immediate but *is* lowered - // to immediate shuffles anyways). - match control { - Lanes::C => { - _mm256_blend_epi32(x.into_bits(), y.into_bits(), C_LANES as i32).into_bits() - } - Lanes::D => { - _mm256_blend_epi32(x.into_bits(), y.into_bits(), D_LANES as i32).into_bits() - } - Lanes::AD => { - _mm256_blend_epi32(x.into_bits(), y.into_bits(), (A_LANES | D_LANES) as i32) - .into_bits() - } - Lanes::AB => { - _mm256_blend_epi32(x.into_bits(), y.into_bits(), (A_LANES | B_LANES) as i32) - .into_bits() - } - Lanes::AC => { - _mm256_blend_epi32(x.into_bits(), y.into_bits(), (A_LANES | C_LANES) as i32) - .into_bits() - } - Lanes::CD => { - _mm256_blend_epi32(x.into_bits(), y.into_bits(), (C_LANES | D_LANES) as i32) - .into_bits() - } - Lanes::BC => { - _mm256_blend_epi32(x.into_bits(), y.into_bits(), (B_LANES | C_LANES) as i32) - .into_bits() - } - Lanes::ABCD => _mm256_blend_epi32( - x.into_bits(), - y.into_bits(), - (A_LANES | B_LANES | C_LANES | D_LANES) as i32, - ).into_bits(), - } - } - } - - FieldElement2625x4([ - blend_lanes(self.0[0], other.0[0], control), - blend_lanes(self.0[1], other.0[1], control), - blend_lanes(self.0[2], other.0[2], control), - blend_lanes(self.0[3], other.0[3], control), - blend_lanes(self.0[4], other.0[4], control), - ]) - } - - /// Construct a vector of zeros. - pub fn zero() -> FieldElement2625x4 { - FieldElement2625x4([u32x8::splat(0); 5]) - } - - /// Convenience wrapper around `new(x,x,x,x)`. - pub fn splat(x: &FieldElement51) -> FieldElement2625x4 { - FieldElement2625x4::new(x, x, x, x) - } - - /// Create a `FieldElement2625x4` from four `FieldElement51`s. - /// - /// # Postconditions - /// - /// The resulting `FieldElement2625x4` is bounded with \\( b < 0.0002 \\). - pub fn new( - x0: &FieldElement51, - x1: &FieldElement51, - x2: &FieldElement51, - x3: &FieldElement51, - ) -> FieldElement2625x4 { - let mut buf = [u32x8::splat(0); 5]; - let low_26_bits = (1 << 26) - 1; - for i in 0..5 { - let a_2i = (x0.0[i] & low_26_bits) as u32; - let a_2i_1 = (x0.0[i] >> 26) as u32; - let b_2i = (x1.0[i] & low_26_bits) as u32; - let b_2i_1 = (x1.0[i] >> 26) as u32; - let c_2i = (x2.0[i] & low_26_bits) as u32; - let c_2i_1 = (x2.0[i] >> 26) as u32; - let d_2i = (x3.0[i] & low_26_bits) as u32; - let d_2i_1 = (x3.0[i] >> 26) as u32; - - buf[i] = u32x8::new(a_2i, b_2i, a_2i_1, b_2i_1, c_2i, d_2i, c_2i_1, d_2i_1); - } - - // We don't know that the original `FieldElement51`s were - // fully reduced, so the odd limbs may exceed 2^25. - // Reduce them to be sure. - FieldElement2625x4(buf).reduce() - } - - /// Given \\((A,B,C,D)\\), compute \\((-A,-B,-C,-D)\\), without - /// performing a reduction. - /// - /// # Preconditions - /// - /// The coefficients of `self` must be bounded with \\( b < 0.999 \\). - /// - /// # Postconditions - /// - /// The coefficients of the result are bounded with \\( b < 1 \\). - #[inline] - pub fn negate_lazy(&self) -> FieldElement2625x4 { - // The limbs of self are bounded with b < 0.999, while the - // smallest limb of 2*p is 67108845 > 2^{26+0.9999}, so - // underflows are not possible. - FieldElement2625x4([ - P_TIMES_2_LO - self.0[0], - P_TIMES_2_HI - self.0[1], - P_TIMES_2_HI - self.0[2], - P_TIMES_2_HI - self.0[3], - P_TIMES_2_HI - self.0[4], - ]) - } - - /// Given `self = (A,B,C,D)`, compute `(B - A, B + A, D - C, D + C)`. - /// - /// # Preconditions - /// - /// The coefficients of `self` must be bounded with \\( b < 0.01 \\). - /// - /// # Postconditions - /// - /// The coefficients of the result are bounded with \\( b < 1.6 \\). - #[inline] - pub fn diff_sum(&self) -> FieldElement2625x4 { - // tmp1 = (B, A, D, C) - let tmp1 = self.shuffle(Shuffle::BADC); - // tmp2 = (-A, B, -C, D) - let tmp2 = self.blend(self.negate_lazy(), Lanes::AC); - // (B - A, B + A, D - C, D + C) bounded with b < 1.6 - tmp1 + tmp2 - } - - /// Reduce this vector of field elements \\(\mathrm{mod} p\\). - /// - /// # Postconditions - /// - /// The coefficients of the result are bounded with \\( b < 0.0002 \\). - #[inline] - pub fn reduce(&self) -> FieldElement2625x4 { - let shifts = i32x8::new(26, 26, 25, 25, 26, 26, 25, 25); - let masks = u32x8::new( - (1 << 26) - 1, - (1 << 26) - 1, - (1 << 25) - 1, - (1 << 25) - 1, - (1 << 26) - 1, - (1 << 26) - 1, - (1 << 25) - 1, - (1 << 25) - 1, - ); - - // Let c(x) denote the carryout of the coefficient x. - // - // Given ( x0, y0, x1, y1, z0, w0, z1, w1), - // compute (c(x1), c(y1), c(x0), c(y0), c(z1), c(w1), c(z0), c(w0)). - // - // The carryouts are bounded by 2^(32 - 25) = 2^7. - let rotated_carryout = |v: u32x8| -> u32x8 { - unsafe { - use core::arch::x86_64::_mm256_srlv_epi32; - use core::arch::x86_64::_mm256_shuffle_epi32; - - let c = _mm256_srlv_epi32(v.into_bits(), shifts.into_bits()); - _mm256_shuffle_epi32(c, 0b01_00_11_10).into_bits() - } - }; - - // Combine (lo, lo, lo, lo, lo, lo, lo, lo) - // with (hi, hi, hi, hi, hi, hi, hi, hi) - // to (lo, lo, hi, hi, lo, lo, hi, hi) - // - // This allows combining carryouts, e.g., - // - // lo (c(x1), c(y1), c(x0), c(y0), c(z1), c(w1), c(z0), c(w0)) - // hi (c(x3), c(y3), c(x2), c(y2), c(z3), c(w3), c(z2), c(w2)) - // -> (c(x1), c(y1), c(x2), c(y2), c(z1), c(w1), c(z2), c(w2)) - // - // which is exactly the vector of carryins for - // - // ( x2, y2, x3, y3, z2, w2, z3, w3). - // - let combine = |v_lo: u32x8, v_hi: u32x8| -> u32x8 { - unsafe { - use core::arch::x86_64::_mm256_blend_epi32; - _mm256_blend_epi32(v_lo.into_bits(), v_hi.into_bits(), 0b11_00_11_00).into_bits() - } - }; - - let mut v = self.0; - - let c10 = rotated_carryout(v[0]); - v[0] = (v[0] & masks) + combine(u32x8::splat(0), c10); - - let c32 = rotated_carryout(v[1]); - v[1] = (v[1] & masks) + combine(c10, c32); - - let c54 = rotated_carryout(v[2]); - v[2] = (v[2] & masks) + combine(c32, c54); - - let c76 = rotated_carryout(v[3]); - v[3] = (v[3] & masks) + combine(c54, c76); - - let c98 = rotated_carryout(v[4]); - v[4] = (v[4] & masks) + combine(c76, c98); - - let c9_19: u32x8 = unsafe { - use core::arch::x86_64::_mm256_mul_epu32; - use core::arch::x86_64::_mm256_shuffle_epi32; - - // Need to rearrange c98, since vpmuludq uses the low - // 32-bits of each 64-bit lane to compute the product: - // - // c98 = (c(x9), c(y9), c(x8), c(y8), c(z9), c(w9), c(z8), c(w8)); - // c9_spread = (c(x9), c(x8), c(y9), c(y8), c(z9), c(z8), c(w9), c(w8)). - let c9_spread = _mm256_shuffle_epi32(c98.into_bits(), 0b11_01_10_00); - - // Since the carryouts are bounded by 2^7, their products with 19 - // are bounded by 2^11.25. This means that - // - // c9_19_spread = (19*c(x9), 0, 19*c(y9), 0, 19*c(z9), 0, 19*c(w9), 0). - let c9_19_spread = _mm256_mul_epu32(c9_spread, u64x4::splat(19).into_bits()); - - // Unshuffle: - // c9_19 = (19*c(x9), 19*c(y9), 0, 0, 19*c(z9), 19*c(w9), 0, 0). - _mm256_shuffle_epi32(c9_19_spread, 0b11_01_10_00).into_bits() - }; - - // Add the final carryin. - v[0] = v[0] + c9_19; - - // Each output coefficient has exactly one carryin, which is - // bounded by 2^11.25, so they are bounded as - // - // c_even < 2^26 + 2^11.25 < 26.00006 < 2^{26+b} - // c_odd < 2^25 + 2^11.25 < 25.0001 < 2^{25+b} - // - // where b = 0.0002. - FieldElement2625x4(v) - } - - /// Given an array of wide coefficients, reduce them to a `FieldElement2625x4`. - /// - /// # Postconditions - /// - /// The coefficients of the result are bounded with \\( b < 0.007 \\). - #[inline] - fn reduce64(mut z: [u64x4; 10]) -> FieldElement2625x4 { - // These aren't const because splat isn't a const fn - let LOW_25_BITS: u64x4 = u64x4::splat((1 << 25) - 1); - let LOW_26_BITS: u64x4 = u64x4::splat((1 << 26) - 1); - - // Carry the value from limb i = 0..8 to limb i+1 - let carry = |z: &mut [u64x4; 10], i: usize| { - debug_assert!(i < 9); - if i % 2 == 0 { - // Even limbs have 26 bits - z[i + 1] = z[i + 1] + (z[i] >> 26); - z[i] = z[i] & LOW_26_BITS; - } else { - // Odd limbs have 25 bits - z[i + 1] = z[i + 1] + (z[i] >> 25); - z[i] = z[i] & LOW_25_BITS; - } - }; - - // Perform two halves of the carry chain in parallel. - carry(&mut z, 0); carry(&mut z, 4); - carry(&mut z, 1); carry(&mut z, 5); - carry(&mut z, 2); carry(&mut z, 6); - carry(&mut z, 3); carry(&mut z, 7); - // Since z[3] < 2^64, c < 2^(64-25) = 2^39, - // so z[4] < 2^26 + 2^39 < 2^39.0002 - carry(&mut z, 4); carry(&mut z, 8); - // Now z[4] < 2^26 - // and z[5] < 2^25 + 2^13.0002 < 2^25.0004 (good enough) - - // Last carry has a multiplication by 19. In the serial case we - // do a 64-bit multiplication by 19, but here we want to do a - // 32-bit multiplication. However, if we only know z[9] < 2^64, - // the carry is bounded as c < 2^(64-25) = 2^39, which is too - // big. To ensure c < 2^32, we would need z[9] < 2^57. - // Instead, we split the carry in two, with c = c_0 + c_1*2^26. - - let c = z[9] >> 25; - z[9] = z[9] & LOW_25_BITS; - let mut c0: u64x4 = c & LOW_26_BITS; // c0 < 2^26; - let mut c1: u64x4 = c >> 26; // c1 < 2^(39-26) = 2^13; - - unsafe { - use core::arch::x86_64::_mm256_mul_epu32; - let x19 = u64x4::splat(19); - c0 = _mm256_mul_epu32(c0.into_bits(), x19.into_bits()).into_bits(); // c0 < 2^30.25 - c1 = _mm256_mul_epu32(c1.into_bits(), x19.into_bits()).into_bits(); // c1 < 2^17.25 - } - - z[0] = z[0] + c0; // z0 < 2^26 + 2^30.25 < 2^30.33 - z[1] = z[1] + c1; // z1 < 2^25 + 2^17.25 < 2^25.0067 - carry(&mut z, 0); // z0 < 2^26, z1 < 2^25.0067 + 2^4.33 = 2^25.007 - - // The output coefficients are bounded with - // - // b = 0.007 for z[1] - // b = 0.0004 for z[5] - // b = 0 for other z[i]. - // - // So the packed result is bounded with b = 0.007. - FieldElement2625x4([ - repack_pair(z[0].into_bits(), z[1].into_bits()), - repack_pair(z[2].into_bits(), z[3].into_bits()), - repack_pair(z[4].into_bits(), z[5].into_bits()), - repack_pair(z[6].into_bits(), z[7].into_bits()), - repack_pair(z[8].into_bits(), z[9].into_bits()), - ]) - } - - /// Square this field element, and negate the result's \\(D\\) value. - /// - /// # Preconditions - /// - /// The coefficients of `self` must be bounded with \\( b < 1.5 \\). - /// - /// # Postconditions - /// - /// The coefficients of the result are bounded with \\( b < 0.007 \\). - pub fn square_and_negate_D(&self) -> FieldElement2625x4 { - #[inline(always)] - fn m(x: u32x8, y: u32x8) -> u64x4 { - use core::arch::x86_64::_mm256_mul_epu32; - unsafe { _mm256_mul_epu32(x.into_bits(), y.into_bits()).into_bits() } - } - - #[inline(always)] - fn m_lo(x: u32x8, y: u32x8) -> u32x8 { - use core::arch::x86_64::_mm256_mul_epu32; - unsafe { _mm256_mul_epu32(x.into_bits(), y.into_bits()).into_bits() } - } - - let v19 = u32x8::new(19, 0, 19, 0, 19, 0, 19, 0); - - let (x0, x1) = unpack_pair(self.0[0]); - let (x2, x3) = unpack_pair(self.0[1]); - let (x4, x5) = unpack_pair(self.0[2]); - let (x6, x7) = unpack_pair(self.0[3]); - let (x8, x9) = unpack_pair(self.0[4]); - - let x0_2 = x0 << 1; - let x1_2 = x1 << 1; - let x2_2 = x2 << 1; - let x3_2 = x3 << 1; - let x4_2 = x4 << 1; - let x5_2 = x5 << 1; - let x6_2 = x6 << 1; - let x7_2 = x7 << 1; - - let x5_19 = m_lo(v19, x5); - let x6_19 = m_lo(v19, x6); - let x7_19 = m_lo(v19, x7); - let x8_19 = m_lo(v19, x8); - let x9_19 = m_lo(v19, x9); - - let mut z0 = m(x0, x0) + m(x2_2,x8_19) + m(x4_2,x6_19) + ((m(x1_2,x9_19) + m(x3_2,x7_19) + m(x5,x5_19)) << 1); - let mut z1 = m(x0_2,x1) + m(x3_2,x8_19) + m(x5_2,x6_19) + ((m(x2,x9_19) + m(x4,x7_19)) << 1); - let mut z2 = m(x0_2,x2) + m(x1_2,x1) + m(x4_2,x8_19) + m(x6,x6_19) + ((m(x3_2,x9_19) + m(x5_2,x7_19)) << 1); - let mut z3 = m(x0_2,x3) + m(x1_2,x2) + m(x5_2,x8_19) + ((m(x4,x9_19) + m(x6,x7_19)) << 1); - let mut z4 = m(x0_2,x4) + m(x1_2,x3_2) + m(x2, x2) + m(x6_2,x8_19) + ((m(x5_2,x9_19) + m(x7,x7_19)) << 1); - let mut z5 = m(x0_2,x5) + m(x1_2,x4) + m(x2_2,x3) + m(x7_2,x8_19) + ((m(x6,x9_19)) << 1); - let mut z6 = m(x0_2,x6) + m(x1_2,x5_2) + m(x2_2,x4) + m(x3_2,x3) + m(x8,x8_19) + ((m(x7_2,x9_19)) << 1); - let mut z7 = m(x0_2,x7) + m(x1_2,x6) + m(x2_2,x5) + m(x3_2,x4) + ((m(x8,x9_19)) << 1); - let mut z8 = m(x0_2,x8) + m(x1_2,x7_2) + m(x2_2,x6) + m(x3_2,x5_2) + m(x4,x4) + ((m(x9,x9_19)) << 1); - let mut z9 = m(x0_2,x9) + m(x1_2,x8) + m(x2_2,x7) + m(x3_2,x6) + m(x4_2,x5); - - // The biggest z_i is bounded as z_i < 249*2^(51 + 2*b); - // if b < 1.5 we get z_i < 4485585228861014016. - // - // The limbs of the multiples of p are bounded above by - // - // 0x3fffffff << 37 = 9223371899415822336 < 2^63 - // - // and below by - // - // 0x1fffffff << 37 = 4611685880988434432 - // > 4485585228861014016 - // - // So these multiples of p are big enough to avoid underflow - // in subtraction, and small enough to fit within u64 - // with room for a carry. - - let low__p37 = u64x4::splat(0x3ffffed << 37); - let even_p37 = u64x4::splat(0x3ffffff << 37); - let odd__p37 = u64x4::splat(0x1ffffff << 37); - - let negate_D = |x: u64x4, p: u64x4| -> u64x4 { - unsafe { - use core::arch::x86_64::_mm256_blend_epi32; - _mm256_blend_epi32(x.into_bits(), (p - x).into_bits(), D_LANES64 as i32).into_bits() - } - }; - - z0 = negate_D(z0, low__p37); - z1 = negate_D(z1, odd__p37); - z2 = negate_D(z2, even_p37); - z3 = negate_D(z3, odd__p37); - z4 = negate_D(z4, even_p37); - z5 = negate_D(z5, odd__p37); - z6 = negate_D(z6, even_p37); - z7 = negate_D(z7, odd__p37); - z8 = negate_D(z8, even_p37); - z9 = negate_D(z9, odd__p37); - - FieldElement2625x4::reduce64([z0, z1, z2, z3, z4, z5, z6, z7, z8, z9]) - } -} - -impl Neg for FieldElement2625x4 { - type Output = FieldElement2625x4; - - /// Negate this field element, performing a reduction. - /// - /// If the coefficients are known to be small, use `negate_lazy` - /// to avoid performing a reduction. - /// - /// # Preconditions - /// - /// The coefficients of `self` must be bounded with \\( b < 4.0 \\). - /// - /// # Postconditions - /// - /// The coefficients of the result are bounded with \\( b < 0.0002 \\). - #[inline] - fn neg(self) -> FieldElement2625x4 { - FieldElement2625x4([ - P_TIMES_16_LO - self.0[0], - P_TIMES_16_HI - self.0[1], - P_TIMES_16_HI - self.0[2], - P_TIMES_16_HI - self.0[3], - P_TIMES_16_HI - self.0[4], - ]).reduce() - } -} - -impl Add for FieldElement2625x4 { - type Output = FieldElement2625x4; - /// Add two `FieldElement2625x4`s, without performing a reduction. - #[inline] - fn add(self, rhs: FieldElement2625x4) -> FieldElement2625x4 { - FieldElement2625x4([ - self.0[0] + rhs.0[0], - self.0[1] + rhs.0[1], - self.0[2] + rhs.0[2], - self.0[3] + rhs.0[3], - self.0[4] + rhs.0[4], - ]) - } -} - -impl Mul<(u32, u32, u32, u32)> for FieldElement2625x4 { - type Output = FieldElement2625x4; - /// Perform a multiplication by a vector of small constants. - /// - /// # Postconditions - /// - /// The coefficients of the result are bounded with \\( b < 0.007 \\). - #[inline] - fn mul(self, scalars: (u32, u32, u32, u32)) -> FieldElement2625x4 { - unsafe { - use core::arch::x86_64::_mm256_mul_epu32; - - let consts = u32x8::new(scalars.0, 0, scalars.1, 0, scalars.2, 0, scalars.3, 0); - - let (b0, b1) = unpack_pair(self.0[0]); - let (b2, b3) = unpack_pair(self.0[1]); - let (b4, b5) = unpack_pair(self.0[2]); - let (b6, b7) = unpack_pair(self.0[3]); - let (b8, b9) = unpack_pair(self.0[4]); - - FieldElement2625x4::reduce64([ - _mm256_mul_epu32(b0.into_bits(), consts.into_bits()).into_bits(), - _mm256_mul_epu32(b1.into_bits(), consts.into_bits()).into_bits(), - _mm256_mul_epu32(b2.into_bits(), consts.into_bits()).into_bits(), - _mm256_mul_epu32(b3.into_bits(), consts.into_bits()).into_bits(), - _mm256_mul_epu32(b4.into_bits(), consts.into_bits()).into_bits(), - _mm256_mul_epu32(b5.into_bits(), consts.into_bits()).into_bits(), - _mm256_mul_epu32(b6.into_bits(), consts.into_bits()).into_bits(), - _mm256_mul_epu32(b7.into_bits(), consts.into_bits()).into_bits(), - _mm256_mul_epu32(b8.into_bits(), consts.into_bits()).into_bits(), - _mm256_mul_epu32(b9.into_bits(), consts.into_bits()).into_bits(), - ]) - } - } -} - -impl<'a, 'b> Mul<&'b FieldElement2625x4> for &'a FieldElement2625x4 { - type Output = FieldElement2625x4; - /// Multiply `self` by `rhs`. - /// - /// # Preconditions - /// - /// The coefficients of `self` must be bounded with \\( b < 2.5 \\). - /// - /// The coefficients of `rhs` must be bounded with \\( b < 1.75 \\). - /// - /// # Postconditions - /// - /// The coefficients of the result are bounded with \\( b < 0.007 \\). - /// - fn mul(self, rhs: &'b FieldElement2625x4) -> FieldElement2625x4 { - #[inline(always)] - fn m(x: u32x8, y: u32x8) -> u64x4 { - use core::arch::x86_64::_mm256_mul_epu32; - unsafe { _mm256_mul_epu32(x.into_bits(), y.into_bits()).into_bits() } - } - - #[inline(always)] - fn m_lo(x: u32x8, y: u32x8) -> u32x8 { - use core::arch::x86_64::_mm256_mul_epu32; - unsafe { _mm256_mul_epu32(x.into_bits(), y.into_bits()).into_bits() } - } - - let (x0, x1) = unpack_pair(self.0[0]); - let (x2, x3) = unpack_pair(self.0[1]); - let (x4, x5) = unpack_pair(self.0[2]); - let (x6, x7) = unpack_pair(self.0[3]); - let (x8, x9) = unpack_pair(self.0[4]); - - let (y0, y1) = unpack_pair(rhs.0[0]); - let (y2, y3) = unpack_pair(rhs.0[1]); - let (y4, y5) = unpack_pair(rhs.0[2]); - let (y6, y7) = unpack_pair(rhs.0[3]); - let (y8, y9) = unpack_pair(rhs.0[4]); - - let v19 = u32x8::new(19, 0, 19, 0, 19, 0, 19, 0); - - let y1_19 = m_lo(v19, y1); // This fits in a u32 - let y2_19 = m_lo(v19, y2); // iff 26 + b + lg(19) < 32 - let y3_19 = m_lo(v19, y3); // if b < 32 - 26 - 4.248 = 1.752 - let y4_19 = m_lo(v19, y4); - let y5_19 = m_lo(v19, y5); - let y6_19 = m_lo(v19, y6); - let y7_19 = m_lo(v19, y7); - let y8_19 = m_lo(v19, y8); - let y9_19 = m_lo(v19, y9); - - let x1_2 = x1 + x1; // This fits in a u32 iff 25 + b + 1 < 32 - let x3_2 = x3 + x3; // iff b < 6 - let x5_2 = x5 + x5; - let x7_2 = x7 + x7; - let x9_2 = x9 + x9; - - let z0 = m(x0,y0) + m(x1_2,y9_19) + m(x2,y8_19) + m(x3_2,y7_19) + m(x4,y6_19) + m(x5_2,y5_19) + m(x6,y4_19) + m(x7_2,y3_19) + m(x8,y2_19) + m(x9_2,y1_19); - let z1 = m(x0,y1) + m(x1,y0) + m(x2,y9_19) + m(x3,y8_19) + m(x4,y7_19) + m(x5,y6_19) + m(x6,y5_19) + m(x7,y4_19) + m(x8,y3_19) + m(x9,y2_19); - let z2 = m(x0,y2) + m(x1_2,y1) + m(x2,y0) + m(x3_2,y9_19) + m(x4,y8_19) + m(x5_2,y7_19) + m(x6,y6_19) + m(x7_2,y5_19) + m(x8,y4_19) + m(x9_2,y3_19); - let z3 = m(x0,y3) + m(x1,y2) + m(x2,y1) + m(x3,y0) + m(x4,y9_19) + m(x5,y8_19) + m(x6,y7_19) + m(x7,y6_19) + m(x8,y5_19) + m(x9,y4_19); - let z4 = m(x0,y4) + m(x1_2,y3) + m(x2,y2) + m(x3_2,y1) + m(x4,y0) + m(x5_2,y9_19) + m(x6,y8_19) + m(x7_2,y7_19) + m(x8,y6_19) + m(x9_2,y5_19); - let z5 = m(x0,y5) + m(x1,y4) + m(x2,y3) + m(x3,y2) + m(x4,y1) + m(x5,y0) + m(x6,y9_19) + m(x7,y8_19) + m(x8,y7_19) + m(x9,y6_19); - let z6 = m(x0,y6) + m(x1_2,y5) + m(x2,y4) + m(x3_2,y3) + m(x4,y2) + m(x5_2,y1) + m(x6,y0) + m(x7_2,y9_19) + m(x8,y8_19) + m(x9_2,y7_19); - let z7 = m(x0,y7) + m(x1,y6) + m(x2,y5) + m(x3,y4) + m(x4,y3) + m(x5,y2) + m(x6,y1) + m(x7,y0) + m(x8,y9_19) + m(x9,y8_19); - let z8 = m(x0,y8) + m(x1_2,y7) + m(x2,y6) + m(x3_2,y5) + m(x4,y4) + m(x5_2,y3) + m(x6,y2) + m(x7_2,y1) + m(x8,y0) + m(x9_2,y9_19); - let z9 = m(x0,y9) + m(x1,y8) + m(x2,y7) + m(x3,y6) + m(x4,y5) + m(x5,y4) + m(x6,y3) + m(x7,y2) + m(x8,y1) + m(x9,y0); - - // The bounds on z[i] are the same as in the serial 32-bit code - // and the comment below is copied from there: - - // How big is the contribution to z[i+j] from x[i], y[j]? - // - // Using the bounds above, we get: - // - // i even, j even: x[i]*y[j] < 2^(26+b)*2^(26+b) = 2*2^(51+2*b) - // i odd, j even: x[i]*y[j] < 2^(25+b)*2^(26+b) = 1*2^(51+2*b) - // i even, j odd: x[i]*y[j] < 2^(26+b)*2^(25+b) = 1*2^(51+2*b) - // i odd, j odd: 2*x[i]*y[j] < 2*2^(25+b)*2^(25+b) = 1*2^(51+2*b) - // - // We perform inline reduction mod p by replacing 2^255 by 19 - // (since 2^255 - 19 = 0 mod p). This adds a factor of 19, so - // we get the bounds (z0 is the biggest one, but calculated for - // posterity here in case finer estimation is needed later): - // - // z0 < ( 2 + 1*19 + 2*19 + 1*19 + 2*19 + 1*19 + 2*19 + 1*19 + 2*19 + 1*19 )*2^(51 + 2b) = 249*2^(51 + 2*b) - // z1 < ( 1 + 1 + 1*19 + 1*19 + 1*19 + 1*19 + 1*19 + 1*19 + 1*19 + 1*19 )*2^(51 + 2b) = 154*2^(51 + 2*b) - // z2 < ( 2 + 1 + 2 + 1*19 + 2*19 + 1*19 + 2*19 + 1*19 + 2*19 + 1*19 )*2^(51 + 2b) = 195*2^(51 + 2*b) - // z3 < ( 1 + 1 + 1 + 1 + 1*19 + 1*19 + 1*19 + 1*19 + 1*19 + 1*19 )*2^(51 + 2b) = 118*2^(51 + 2*b) - // z4 < ( 2 + 1 + 2 + 1 + 2 + 1*19 + 2*19 + 1*19 + 2*19 + 1*19 )*2^(51 + 2b) = 141*2^(51 + 2*b) - // z5 < ( 1 + 1 + 1 + 1 + 1 + 1 + 1*19 + 1*19 + 1*19 + 1*19 )*2^(51 + 2b) = 82*2^(51 + 2*b) - // z6 < ( 2 + 1 + 2 + 1 + 2 + 1 + 2 + 1*19 + 2*19 + 1*19 )*2^(51 + 2b) = 87*2^(51 + 2*b) - // z7 < ( 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1*19 + 1*19 )*2^(51 + 2b) = 46*2^(51 + 2*b) - // z8 < ( 2 + 1 + 2 + 1 + 2 + 1 + 2 + 1 + 2 + 1*19 )*2^(51 + 2b) = 33*2^(51 + 2*b) - // z9 < ( 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 )*2^(51 + 2b) = 10*2^(51 + 2*b) - // - // So z[0] fits into a u64 if 51 + 2*b + lg(249) < 64 - // if b < 2.5. - - // In fact this bound is slightly sloppy, since it treats both - // inputs x and y as being bounded by the same parameter b, - // while they are in fact bounded by b_x and b_y, and we - // already require that b_y < 1.75 in order to fit the - // multiplications by 19 into a u32. The tighter bound on b_y - // means we could get a tighter bound on the outputs, or a - // looser bound on b_x. - FieldElement2625x4::reduce64([z0, z1, z2, z3, z4, z5, z6, z7, z8, z9]) - } -} - -#[cfg(test)] -mod test { - use super::*; - - #[test] - fn scale_by_curve_constants() { - let mut x = FieldElement2625x4::splat(&FieldElement51::one()); - - x = x * (121666, 121666, 2*121666, 2*121665); - - let xs = x.split(); - assert_eq!(xs[0], FieldElement51([121666, 0, 0, 0, 0])); - assert_eq!(xs[1], FieldElement51([121666, 0, 0, 0, 0])); - assert_eq!(xs[2], FieldElement51([2 * 121666, 0, 0, 0, 0])); - assert_eq!(xs[3], FieldElement51([2 * 121665, 0, 0, 0, 0])); - } - - #[test] - fn diff_sum_vs_serial() { - let x0 = FieldElement51([10000, 10001, 10002, 10003, 10004]); - let x1 = FieldElement51([10100, 10101, 10102, 10103, 10104]); - let x2 = FieldElement51([10200, 10201, 10202, 10203, 10204]); - let x3 = FieldElement51([10300, 10301, 10302, 10303, 10304]); - - let vec = FieldElement2625x4::new(&x0, &x1, &x2, &x3).diff_sum(); - - let result = vec.split(); - - assert_eq!(result[0], &x1 - &x0); - assert_eq!(result[1], &x1 + &x0); - assert_eq!(result[2], &x3 - &x2); - assert_eq!(result[3], &x3 + &x2); - } - - #[test] - fn square_vs_serial() { - let x0 = FieldElement51([10000, 10001, 10002, 10003, 10004]); - let x1 = FieldElement51([10100, 10101, 10102, 10103, 10104]); - let x2 = FieldElement51([10200, 10201, 10202, 10203, 10204]); - let x3 = FieldElement51([10300, 10301, 10302, 10303, 10304]); - - let vec = FieldElement2625x4::new(&x0, &x1, &x2, &x3); - - let result = vec.square_and_negate_D().split(); - - assert_eq!(result[0], &x0 * &x0); - assert_eq!(result[1], &x1 * &x1); - assert_eq!(result[2], &x2 * &x2); - assert_eq!(result[3], -&(&x3 * &x3)); - } - - #[test] - fn multiply_vs_serial() { - let x0 = FieldElement51([10000, 10001, 10002, 10003, 10004]); - let x1 = FieldElement51([10100, 10101, 10102, 10103, 10104]); - let x2 = FieldElement51([10200, 10201, 10202, 10203, 10204]); - let x3 = FieldElement51([10300, 10301, 10302, 10303, 10304]); - - let vec = FieldElement2625x4::new(&x0, &x1, &x2, &x3); - let vecprime = vec.clone(); - - let result = (&vec * &vecprime).split(); - - assert_eq!(result[0], &x0 * &x0); - assert_eq!(result[1], &x1 * &x1); - assert_eq!(result[2], &x2 * &x2); - assert_eq!(result[3], &x3 * &x3); - } - - #[test] - fn test_unpack_repack_pair() { - let x0 = FieldElement51([10000 + (10001 << 26), 0, 0, 0, 0]); - let x1 = FieldElement51([10100 + (10101 << 26), 0, 0, 0, 0]); - let x2 = FieldElement51([10200 + (10201 << 26), 0, 0, 0, 0]); - let x3 = FieldElement51([10300 + (10301 << 26), 0, 0, 0, 0]); - - let vec = FieldElement2625x4::new(&x0, &x1, &x2, &x3); - - let src = vec.0[0]; - - let (a, b) = unpack_pair(src); - - let expected_a = u32x8::new(10000, 0, 10100, 0, 10200, 0, 10300, 0); - let expected_b = u32x8::new(10001, 0, 10101, 0, 10201, 0, 10301, 0); - - assert_eq!(a, expected_a); - assert_eq!(b, expected_b); - - let expected_src = repack_pair(a, b); - - assert_eq!(src, expected_src); - } - - #[test] - fn new_split_roundtrips() { - let x0 = FieldElement51::from_bytes(&[0x10; 32]); - let x1 = FieldElement51::from_bytes(&[0x11; 32]); - let x2 = FieldElement51::from_bytes(&[0x12; 32]); - let x3 = FieldElement51::from_bytes(&[0x13; 32]); - - let vec = FieldElement2625x4::new(&x0, &x1, &x2, &x3); - - let splits = vec.split(); - - assert_eq!(x0, splits[0]); - assert_eq!(x1, splits[1]); - assert_eq!(x2, splits[2]); - assert_eq!(x3, splits[3]); - } -} diff --git a/net/gurk-rs/files/vendor/curve25519-dalek/src/backend/vector/avx2/mod.rs b/net/gurk-rs/files/vendor/curve25519-dalek/src/backend/vector/avx2/mod.rs deleted file mode 100644 index 527fdc1..0000000 --- a/net/gurk-rs/files/vendor/curve25519-dalek/src/backend/vector/avx2/mod.rs +++ /dev/null @@ -1,21 +0,0 @@ -// -*- mode: rust; -*- -// -// This file is part of curve25519-dalek. -// Copyright (c) 2016-2021 isis lovecruft -// Copyright (c) 2016-2019 Henry de Valence -// See LICENSE for licensing information. -// -// Authors: -// - isis agora lovecruft -// - Henry de Valence - -#![cfg_attr( - feature = "nightly", - doc(include = "../../../../docs/avx2-notes.md") -)] - -pub(crate) mod field; - -pub(crate) mod edwards; - -pub(crate) mod constants; diff --git a/net/gurk-rs/files/vendor/curve25519-dalek/src/backend/vector/ifma/constants.rs b/net/gurk-rs/files/vendor/curve25519-dalek/src/backend/vector/ifma/constants.rs deleted file mode 100644 index fd89058..0000000 --- a/net/gurk-rs/files/vendor/curve25519-dalek/src/backend/vector/ifma/constants.rs +++ /dev/null @@ -1,2062 +0,0 @@ -// -*- mode: rust; -*- -// -// This file is part of curve25519-dalek. -// Copyright (c) 2018-2019 Henry de Valence -// See LICENSE for licensing information. -// -// Authors: -// - Henry de Valence - -//! This module contains constants used by the IFMA backend. - -use packed_simd::u64x4; - -use window::NafLookupTable8; - -use super::edwards::{CachedPoint, ExtendedPoint}; -use super::field::{F51x4Reduced, F51x4Unreduced}; - -/// The identity element as an `ExtendedPoint`. -pub(crate) static EXTENDEDPOINT_IDENTITY: ExtendedPoint = ExtendedPoint(F51x4Unreduced([ - u64x4::new(0, 1, 1, 0), - u64x4::new(0, 0, 0, 0), - u64x4::new(0, 0, 0, 0), - u64x4::new(0, 0, 0, 0), - u64x4::new(0, 0, 0, 0), -])); - -/// The identity element as a `CachedPoint`. -pub(crate) static CACHEDPOINT_IDENTITY: CachedPoint = CachedPoint(F51x4Reduced([ - u64x4::new(121647, 121666, 243332, 2251799813685229), - u64x4::new(2251799813685248, 0, 0, 2251799813685247), - u64x4::new(2251799813685247, 0, 0, 2251799813685247), - u64x4::new(2251799813685247, 0, 0, 2251799813685247), - u64x4::new(2251799813685247, 0, 0, 2251799813685247), -])); - -/// Odd multiples of the Ed25519 basepoint: -pub(crate) static BASEPOINT_ODD_LOOKUP_TABLE: NafLookupTable8 = NafLookupTable8([ - CachedPoint(F51x4Reduced([ - u64x4::new(1277522120965857, 73557767439946, 243332, 1943719795065404), - u64x4::new(108375142003455, 341984820733594, 0, 2097709862669256), - u64x4::new(150073485536043, 750646439938056, 0, 581130035634455), - u64x4::new(2149983732744869, 1903255931888577, 0, 646644904824193), - u64x4::new(291045673509296, 1060034214701851, 0, 325245010451737), - ])), - CachedPoint(F51x4Reduced([ - u64x4::new( - 1970681836121889, - 1660307753655178, - 1077207637163462, - 1436413309977108, - ), - u64x4::new( - 158785710838757, - 919645875412951, - 174577133496574, - 2213787394009350, - ), - u64x4::new( - 1017606396438281, - 1240932851489554, - 918203302506967, - 1239827708070863, - ), - u64x4::new( - 1748989883612327, - 1745367742532782, - 1168385548387, - 1211387683826673, - ), - u64x4::new( - 799349980018733, - 1471088235739693, - 1505351346057417, - 2104975925096407, - ), - ])), - CachedPoint(F51x4Reduced([ - u64x4::new( - 171437462972293, - 36016853025886, - 1184164975342640, - 1633525003912147, - ), - u64x4::new( - 2113383632509037, - 1946216474924125, - 1884174984466256, - 1373317790955847, - ), - u64x4::new( - 791293623466401, - 1796466048084189, - 444977763198796, - 629823271230872, - ), - u64x4::new( - 1093217720067380, - 2157024270666135, - 238122980108466, - 806820763806847, - ), - u64x4::new( - 793658959468458, - 368578641413741, - 11592529764159, - 2144017075993471, - ), - ])), - CachedPoint(F51x4Reduced([ - u64x4::new( - 1538027396670268, - 1588896993892061, - 675619548648376, - 788373514423313, - ), - u64x4::new( - 1987517656073805, - 1940987929951188, - 666993851697339, - 2040540928108427, - ), - u64x4::new( - 375514548584082, - 1726008037083790, - 1070069155000872, - 570111103756303, - ), - u64x4::new( - 772223645372213, - 2123395244967674, - 868238486911408, - 1846639042240362, - ), - u64x4::new( - 872865734460736, - 32277956842850, - 1701451131455402, - 773883376061880, - ), - ])), - CachedPoint(F51x4Reduced([ - u64x4::new( - 1845177363882902, - 275858237213625, - 1052127336883600, - 171072805852218, - ), - u64x4::new( - 139016783952609, - 462699304987089, - 430046471494974, - 410922720999257, - ), - u64x4::new( - 846403935976337, - 243817706931454, - 971825428236901, - 571800039596794, - ), - u64x4::new( - 807642685434918, - 1933536976438782, - 812324278898440, - 688391556487313, - ), - u64x4::new( - 76239450396192, - 629532732688863, - 1833302026979779, - 650067934544499, - ), - ])), - CachedPoint(F51x4Reduced([ - u64x4::new( - 1373931604989264, - 331159264656614, - 364391529321767, - 874765630865409, - ), - u64x4::new( - 2109908262150241, - 473400816504190, - 91544045127333, - 976307977609515, - ), - u64x4::new( - 330175435673491, - 2126511895885904, - 1022944071588421, - 2158480209801463, - ), - u64x4::new( - 1305666795527971, - 162063591028664, - 2193154870675382, - 1789166662611800, - ), - u64x4::new( - 817858592500508, - 1672743239440202, - 859976879916778, - 1167423340862516, - ), - ])), - CachedPoint(F51x4Reduced([ - u64x4::new( - 274334925170164, - 565841102587251, - 603083835949120, - 607539210240861, - ), - u64x4::new( - 196754662972649, - 1339063476699167, - 1406077076979491, - 896902435668469, - ), - u64x4::new( - 397962210956733, - 174839587476217, - 1381082665748936, - 175195877334136, - ), - u64x4::new( - 717429432748391, - 1635309821746318, - 363374010274647, - 882908746261699, - ), - u64x4::new( - 600946602802781, - 1946596133370711, - 1532135183320341, - 690530671668253, - ), - ])), - CachedPoint(F51x4Reduced([ - u64x4::new( - 2074443704000945, - 2163534804938345, - 425423840926528, - 1100826171404853, - ), - u64x4::new( - 111700142796101, - 1456893872751964, - 1186145518682968, - 2192182627706116, - ), - u64x4::new( - 1848722121856066, - 2123239575044749, - 1323870754599272, - 883211262889775, - ), - u64x4::new( - 938263017712916, - 689670293631396, - 183944529557576, - 501908638166580, - ), - u64x4::new( - 2170571907220631, - 36636756989655, - 1875035480138608, - 803703278398018, - ), - ])), - CachedPoint(F51x4Reduced([ - u64x4::new( - 1053429956874064, - 1636640618139765, - 1556890827801070, - 2142720579528828, - ), - u64x4::new( - 1814240918422814, - 692326274601777, - 1054896561802157, - 2025454041705534, - ), - u64x4::new( - 2109495823888757, - 1287497869997176, - 194170063200096, - 621116840113213, - ), - u64x4::new( - 2156505873679998, - 2197064359737385, - 1312887672223536, - 369862818895912, - ), - u64x4::new( - 977381163563657, - 1878897311974033, - 2144566861359744, - 1832960882773351, - ), - ])), - CachedPoint(F51x4Reduced([ - u64x4::new( - 1266492498289486, - 1301524759372145, - 324789537938521, - 442710471023019, - ), - u64x4::new( - 1232722320001345, - 1191193089162455, - 176474006074813, - 2158950213252857, - ), - u64x4::new( - 1901782191467749, - 494791441598902, - 1820415815322129, - 854954583485223, - ), - u64x4::new( - 1511383667649702, - 792536415032464, - 2027741263854728, - 1727944381044738, - ), - u64x4::new( - 606355788891204, - 1670687521471220, - 582824350365415, - 1509135066079912, - ), - ])), - CachedPoint(F51x4Reduced([ - u64x4::new( - 1079942762813598, - 2015830004785901, - 479916361323351, - 1907956590950158, - ), - u64x4::new( - 2053400302939156, - 1319799126867070, - 19493088767391, - 1908755581402373, - ), - u64x4::new( - 2235858054780980, - 885832711204321, - 810332865560178, - 103174191215441, - ), - u64x4::new( - 1843466881032833, - 355511728384038, - 693846715794114, - 186545012724117, - ), - u64x4::new( - 1661758432892509, - 1491022339899281, - 698941123765263, - 174945407208560, - ), - ])), - CachedPoint(F51x4Reduced([ - u64x4::new( - 1075933251927831, - 400263885306647, - 1308157532880528, - 347933379126665, - ), - u64x4::new( - 673811632329433, - 1584860147186478, - 271778891257244, - 498194055154207, - ), - u64x4::new( - 703783427747558, - 1051624728592032, - 1371463103351544, - 230351033002960, - ), - u64x4::new( - 860729466483372, - 421647596766583, - 1520613871336707, - 635298775280054, - ), - u64x4::new( - 1168352891728845, - 1691216293752089, - 1799491997061519, - 399728882318504, - ), - ])), - CachedPoint(F51x4Reduced([ - u64x4::new( - 420156727446514, - 1483649215777128, - 165508610199900, - 1918121104840431, - ), - u64x4::new( - 2129902293682427, - 730952770435213, - 2184527544565390, - 1939880362232986, - ), - u64x4::new( - 1771978364905086, - 510975579746524, - 927564335219142, - 177574146260558, - ), - u64x4::new( - 2164104536437514, - 1532598873799015, - 406875369182421, - 1367005937406517, - ), - u64x4::new( - 35073200082587, - 1981124717036219, - 1854087014063833, - 122419694385217, - ), - ])), - CachedPoint(F51x4Reduced([ - u64x4::new( - 1963785875777739, - 411497142699119, - 1974557512687408, - 1268304422747183, - ), - u64x4::new( - 762752575978150, - 1443822019541748, - 1331556159904338, - 377726798263780, - ), - u64x4::new( - 825953972847841, - 353487068141356, - 1955697322427207, - 2048226560172078, - ), - u64x4::new( - 1482378558684434, - 657691905625918, - 923870001994493, - 1694132799397736, - ), - u64x4::new( - 1643904759603122, - 170495566698285, - 1218312703413378, - 784318735038131, - ), - ])), - CachedPoint(F51x4Reduced([ - u64x4::new( - 939230507241903, - 2238763473105245, - 1827325199528162, - 1153939339775538, - ), - u64x4::new( - 38544505283339, - 258889431497015, - 351721979677947, - 1357907379592829, - ), - u64x4::new( - 1393974676373341, - 1131355528938676, - 473104915298872, - 978783482501776, - ), - u64x4::new( - 2131516168980501, - 2113911780991092, - 1477027502354261, - 542884524860340, - ), - u64x4::new( - 1029606261349423, - 64226378557628, - 1669131167474348, - 2212808057234874, - ), - ])), - CachedPoint(F51x4Reduced([ - u64x4::new( - 1423176501543193, - 163313632579593, - 2220495688893001, - 2220041045291870, - ), - u64x4::new( - 1111834224023697, - 1026815658023689, - 1404605100939775, - 1412149108248227, - ), - u64x4::new( - 1542537854906076, - 1270288391129127, - 991419278941933, - 1824939809581980, - ), - u64x4::new( - 1142003215657891, - 525980550896367, - 1508270666157963, - 917719462309053, - ), - u64x4::new( - 400851268057105, - 1620818232405188, - 1251478578139510, - 2162841805361886, - ), - ])), - CachedPoint(F51x4Reduced([ - u64x4::new( - 2125383272208441, - 1368790097335984, - 11813369275978, - 639513785921674, - ), - u64x4::new( - 2200806265616284, - 1041996387620216, - 1275149397833084, - 1723371028064068, - ), - u64x4::new( - 603720163891275, - 2135593511176153, - 2049641644431548, - 1198460677818310, - ), - u64x4::new( - 1862491879401621, - 2008116580769441, - 626566325260235, - 1058308304975798, - ), - u64x4::new( - 628557314314858, - 1075323332046522, - 1631772244117095, - 1812174547405683, - ), - ])), - CachedPoint(F51x4Reduced([ - u64x4::new( - 1222773123817104, - 363276129291452, - 796237592807883, - 1914425291893078, - ), - u64x4::new( - 1721259057429088, - 734941709009373, - 1553365830564638, - 1492120931079419, - ), - u64x4::new( - 1009354843273686, - 293884504384873, - 1050281954944357, - 134132942667344, - ), - u64x4::new( - 23119363298711, - 1694754778833445, - 1725925193393496, - 1738396998222001, - ), - u64x4::new( - 1753692057254667, - 118428526447110, - 840961387840295, - 1227619055408558, - ), - ])), - CachedPoint(F51x4Reduced([ - u64x4::new( - 1004186117579547, - 508771992330056, - 1426571663072421, - 2238524171903259, - ), - u64x4::new( - 744764613007812, - 398885442368825, - 2047459490294949, - 2141797621077959, - ), - u64x4::new( - 4556204156489, - 1708213022802363, - 1071381560923933, - 393474529142567, - ), - u64x4::new( - 350116198213005, - 945907227204695, - 168267474358731, - 1801504420122711, - ), - u64x4::new( - 728788674520360, - 1262722049156121, - 455259596607008, - 1159442365834489, - ), - ])), - CachedPoint(F51x4Reduced([ - u64x4::new( - 2226818917892677, - 185673745808179, - 2240952219732549, - 324137961621908, - ), - u64x4::new( - 1659527641857410, - 973964060249383, - 1349692151487730, - 1172743533370593, - ), - u64x4::new( - 310591478467746, - 2123977244137170, - 774562885265820, - 430035546191685, - ), - u64x4::new( - 2150863173197992, - 2101978317708856, - 193592648406011, - 1375328504508580, - ), - u64x4::new( - 1946235834250479, - 121741431658675, - 1004342690620100, - 2063466488599450, - ), - ])), - CachedPoint(F51x4Reduced([ - u64x4::new( - 463079632200153, - 40415275714025, - 545935352782679, - 1458043501600908, - ), - u64x4::new( - 783771976559993, - 880839641726471, - 1782028201271831, - 41664413404590, - ), - u64x4::new( - 985129151724159, - 187728621410000, - 16620051933318, - 378011085567733, - ), - u64x4::new( - 1820372198168638, - 905710046480679, - 1912961774249737, - 1868135861067161, - ), - u64x4::new( - 474460473983187, - 1455684425673661, - 652771171116843, - 733511920760779, - ), - ])), - CachedPoint(F51x4Reduced([ - u64x4::new( - 1088886980746809, - 1660218575261626, - 527921875040240, - 915086639857889, - ), - u64x4::new( - 1814735788528175, - 1586698876186367, - 2040856637532862, - 405684812785624, - ), - u64x4::new( - 658578559700999, - 1751442070931114, - 1293623371490094, - 715026719042518, - ), - u64x4::new( - 382156225644820, - 897982285504960, - 577673183555858, - 1158728558309719, - ), - u64x4::new( - 1865791902475663, - 124491617513788, - 758484125168765, - 734065580770143, - ), - ])), - CachedPoint(F51x4Reduced([ - u64x4::new( - 330985690350617, - 2214424721795630, - 973374650780848, - 1507267060932964, - ), - u64x4::new( - 1733823971011290, - 1730742552292995, - 669018866977489, - 604527664126146, - ), - u64x4::new( - 1082092498645474, - 1029182053935309, - 756799947765834, - 1764720030308351, - ), - u64x4::new( - 969912105693756, - 38116887248276, - 2148030115687613, - 995140534653865, - ), - u64x4::new( - 2154373397460354, - 298128883464656, - 479587543632539, - 1061127201140779, - ), - ])), - CachedPoint(F51x4Reduced([ - u64x4::new( - 843064865526549, - 2019481782959016, - 1873125524281672, - 2013330239022371, - ), - u64x4::new( - 1192932403815186, - 1818108671859220, - 1247005102016258, - 1210577394628058, - ), - u64x4::new( - 132359273326717, - 795492788299178, - 1235924489372816, - 891705064411550, - ), - u64x4::new( - 1425833709104858, - 152114045731085, - 991347902581315, - 1387773338707683, - ), - u64x4::new( - 48024203807922, - 157005564892977, - 1474053161953744, - 727448023498345, - ), - ])), - CachedPoint(F51x4Reduced([ - u64x4::new( - 1076621484026788, - 1309917234320927, - 1786998180233659, - 1595497085944737, - ), - u64x4::new( - 1737334672694726, - 2038133716999447, - 1929061192400917, - 620544235219084, - ), - u64x4::new( - 1550527313469747, - 329096759623509, - 1585214659209474, - 693419841748324, - ), - u64x4::new( - 1450010875912315, - 2085047082180569, - 757421110771886, - 389367139787400, - ), - u64x4::new( - 781339490566117, - 132941783448971, - 258650459725225, - 2042274962585613, - ), - ])), - CachedPoint(F51x4Reduced([ - u64x4::new( - 859638991542650, - 2249840007426442, - 1138753070862357, - 793751342318913, - ), - u64x4::new( - 2133476133447306, - 1027010646129239, - 436851910892865, - 866949948830344, - ), - u64x4::new( - 1936003572431223, - 531513680252193, - 1929877059408416, - 830585477662503, - ), - u64x4::new( - 1460760405777960, - 686673748420916, - 275475330051554, - 1581792376993692, - ), - u64x4::new( - 894482039456784, - 1801274480988632, - 16407898635278, - 1668497039215206, - ), - ])), - CachedPoint(F51x4Reduced([ - u64x4::new( - 258585746227669, - 936490904651492, - 1826793887434108, - 1201219990633823, - ), - u64x4::new( - 979462791643635, - 461762372210187, - 218708929991480, - 1378150755760178, - ), - u64x4::new( - 642542170229970, - 787135445552820, - 371168855880557, - 182642566486693, - ), - u64x4::new( - 1152277399721904, - 1726910452705576, - 1452393215705343, - 2117799581546845, - ), - u64x4::new( - 1211265143925330, - 14373046151823, - 1745528818271507, - 1842106288572078, - ), - ])), - CachedPoint(F51x4Reduced([ - u64x4::new( - 635154614562157, - 1956763034454109, - 509123035953043, - 445727657534780, - ), - u64x4::new( - 2072765509783252, - 1282639891593570, - 1075086397362049, - 722996110178195, - ), - u64x4::new( - 1385572918825603, - 1190035835509576, - 218317841176013, - 1047865370756924, - ), - u64x4::new( - 473991569426488, - 1910588123704592, - 1338270051770806, - 401676861680875, - ), - u64x4::new( - 992455353618436, - 126422733426929, - 1955248037756399, - 119233843022643, - ), - ])), - CachedPoint(F51x4Reduced([ - u64x4::new( - 1555272991526078, - 2214378187116349, - 366893798097444, - 1401502118355702, - ), - u64x4::new( - 1157229521930713, - 2144787187506262, - 1681597469697840, - 847499096518697, - ), - u64x4::new( - 1872802655800758, - 1027119609820793, - 1137278714788290, - 1664750301179485, - ), - u64x4::new( - 1091289858897030, - 910126419483563, - 1101920147235731, - 597083075893952, - ), - u64x4::new( - 1711011533670315, - 185206680336278, - 1620960612579784, - 1968598849170880, - ), - ])), - CachedPoint(F51x4Reduced([ - u64x4::new( - 73077300235958, - 257216723095630, - 466947267713785, - 847105214181598, - ), - u64x4::new( - 1322905631406309, - 407458059314731, - 230045063190376, - 923800751267786, - ), - u64x4::new( - 1146027205000415, - 1541328763727623, - 768510249199119, - 1630223587589059, - ), - u64x4::new( - 1930368769879433, - 1376145403022159, - 1898149855343131, - 1709421930518180, - ), - u64x4::new( - 633944191571764, - 58314960742839, - 2050971151574988, - 757799756090059, - ), - ])), - CachedPoint(F51x4Reduced([ - u64x4::new( - 361576929158539, - 1035682890165818, - 160945739362874, - 266975208626222, - ), - u64x4::new( - 1635371797076046, - 2106722851965197, - 451585919077206, - 6692426667180, - ), - u64x4::new( - 175820543533852, - 2057511393764025, - 1531846543720469, - 1648320903946519, - ), - u64x4::new( - 947461770620940, - 1107335044817620, - 1725565474111216, - 2182263619949220, - ), - u64x4::new( - 726444888601221, - 1379664085279206, - 1517215633290417, - 1763968936542507, - ), - ])), - CachedPoint(F51x4Reduced([ - u64x4::new( - 686545355846512, - 1712283265573167, - 1743509592736302, - 1653906616429153, - ), - u64x4::new( - 985108805667149, - 2244347650874753, - 1304749057936860, - 321846134330589, - ), - u64x4::new( - 296321076156886, - 1717929256240029, - 450933772486425, - 2015536856431605, - ), - u64x4::new( - 1690393512821866, - 646913049470189, - 2198650647576397, - 1230646705710442, - ), - u64x4::new( - 601961913448442, - 878806578800541, - 620497587492381, - 330716414244629, - ), - ])), - CachedPoint(F51x4Reduced([ - u64x4::new( - 631510982676132, - 1755753187697174, - 1596201246674299, - 2197888384902121, - ), - u64x4::new( - 626957678275745, - 1447583371478595, - 1375375216702128, - 1443613232818823, - ), - u64x4::new( - 1962997804660501, - 1051744123184519, - 1002558639300437, - 1237313314603385, - ), - u64x4::new( - 2118828335274995, - 226398203764759, - 889099617161107, - 1620967117678504, - ), - u64x4::new( - 227261019362935, - 2046897556746842, - 591524060355369, - 2178552047369691, - ), - ])), - CachedPoint(F51x4Reduced([ - u64x4::new( - 1375403119051662, - 222313965014452, - 539873444241395, - 213198095917915, - ), - u64x4::new( - 1436952871599114, - 1229749762725246, - 1174441562267670, - 265367077740349, - ), - u64x4::new( - 11107426165917, - 985954476039181, - 1147329112365579, - 1133931640328107, - ), - u64x4::new( - 585235055006843, - 699515259687482, - 299559608721134, - 2134819767146767, - ), - u64x4::new( - 1376401105588528, - 391412107507860, - 302743651807545, - 1362834426455518, - ), - ])), - CachedPoint(F51x4Reduced([ - u64x4::new( - 1802940904616205, - 1615132760193234, - 869321663313735, - 666494072545310, - ), - u64x4::new( - 1452849320020701, - 1472716813676364, - 472862999490802, - 359937983286145, - ), - u64x4::new( - 1221198323133843, - 491718521756528, - 1387135774113906, - 793779904904008, - ), - u64x4::new( - 1032129287829151, - 30730741946697, - 217603185195068, - 2118169309744162, - ), - u64x4::new( - 225899335574721, - 1767553399797342, - 881082465669982, - 1435383196392870, - ), - ])), - CachedPoint(F51x4Reduced([ - u64x4::new( - 1127093564374276, - 2245188499702906, - 1250041622887441, - 2179324911668149, - ), - u64x4::new( - 908019210866875, - 1879900391060964, - 1355047706206597, - 647218945377302, - ), - u64x4::new( - 1616265604422592, - 2134336781521657, - 1157711219915601, - 1227494173135033, - ), - u64x4::new( - 136450294813355, - 1984543542455033, - 1199486053011083, - 33687889941331, - ), - u64x4::new( - 1053447012707371, - 68239344331930, - 537448158443925, - 1829189783369646, - ), - ])), - CachedPoint(F51x4Reduced([ - u64x4::new( - 996806463322563, - 2043104667851348, - 1110361398300309, - 1218740346887957, - ), - u64x4::new( - 399141907016839, - 1307691109658227, - 532535384961264, - 896201194398872, - ), - u64x4::new( - 111705272106160, - 1790972382466021, - 1159338112559144, - 303544352897203, - ), - u64x4::new( - 1036600573322969, - 1457119922663674, - 334117653665514, - 460023361701263, - ), - u64x4::new( - 1363773215189933, - 1915594049343802, - 1661249423378694, - 1744945551969247, - ), - ])), - CachedPoint(F51x4Reduced([ - u64x4::new( - 3093919631215, - 574886478077610, - 1704446919728971, - 250093147254210, - ), - u64x4::new( - 1387413348737796, - 360142717826981, - 2116185073015983, - 474541388374100, - ), - u64x4::new( - 1632539630892580, - 1332404016215719, - 2145297637794728, - 1289783723173504, - ), - u64x4::new( - 1030244179060173, - 579782698595797, - 1062365251139982, - 677149839815546, - ), - u64x4::new( - 6671539419876, - 1426937459653775, - 406942403696343, - 675479224223817, - ), - ])), - CachedPoint(F51x4Reduced([ - u64x4::new( - 271984148441782, - 1708099625818957, - 1499011822959235, - 516808451044836, - ), - u64x4::new( - 1124847751346323, - 2038336022958449, - 1721698491022600, - 705944403212572, - ), - u64x4::new( - 85459783780275, - 1715213099986669, - 1728445509034791, - 730657630359717, - ), - u64x4::new( - 1185034652652387, - 755472578204310, - 476118360897817, - 1800434542785310, - ), - u64x4::new( - 1815589628676941, - 491778500674079, - 1547664984392513, - 279891608681267, - ), - ])), - CachedPoint(F51x4Reduced([ - u64x4::new( - 2036337168672113, - 1730787524684269, - 639134121311693, - 698060925015524, - ), - u64x4::new( - 315211075189491, - 1329055848835358, - 688621136402134, - 1271193060119448, - ), - u64x4::new( - 1697984374314012, - 459330773536457, - 305481314707918, - 61676911066002, - ), - u64x4::new( - 2166631826859191, - 2105217187401781, - 937587962768434, - 357397435365683, - ), - u64x4::new( - 1206757093145471, - 1287847622009294, - 1951336140421622, - 2233789834777410, - ), - ])), - CachedPoint(F51x4Reduced([ - u64x4::new( - 82144190081093, - 1568417433687791, - 907555979158442, - 2037855062523867, - ), - u64x4::new( - 1225315484058853, - 315317868015613, - 1765025920288384, - 175223259828436, - ), - u64x4::new( - 1215010304871271, - 662713408454950, - 429517658575616, - 991062684008811, - ), - u64x4::new( - 993837615254894, - 1485561584889450, - 2001836754226476, - 1915943063896801, - ), - u64x4::new( - 818895101625673, - 1342479472068804, - 1380235330010671, - 23315169761453, - ), - ])), - CachedPoint(F51x4Reduced([ - u64x4::new( - 1500726307559118, - 956166860173424, - 512663951564436, - 1940180717699824, - ), - u64x4::new( - 1789521472720825, - 779456898652427, - 2035063615853504, - 863582140589407, - ), - u64x4::new( - 634508890793787, - 1748041666732214, - 259642099961634, - 1294936839797812, - ), - u64x4::new( - 2183334898697038, - 2197242820694806, - 2217225409073703, - 992633998226449, - ), - u64x4::new( - 2197077498155916, - 1562008797791883, - 1395088759904208, - 331715244679294, - ), - ])), - CachedPoint(F51x4Reduced([ - u64x4::new( - 186854731652320, - 284389440026580, - 1252175415119400, - 1025377410100223, - ), - u64x4::new( - 1578732129417607, - 898645497852382, - 2237766074482974, - 1939197790303592, - ), - u64x4::new( - 1438830390640145, - 1682452015845597, - 1108441197232223, - 1984134492898664, - ), - u64x4::new( - 282668727301669, - 1609018289552856, - 390363439795705, - 1138459124667912, - ), - u64x4::new( - 18889015928490, - 532489638086725, - 324621535996080, - 2210046082697453, - ), - ])), - CachedPoint(F51x4Reduced([ - u64x4::new( - 2041327051605378, - 2244037852176483, - 2116336876147147, - 9616672544864, - ), - u64x4::new( - 969847387559191, - 1059119127679639, - 1764630094670633, - 364568045311834, - ), - u64x4::new( - 505938893153679, - 2075421412172902, - 326984153045666, - 1959549727324704, - ), - u64x4::new( - 1088715617911260, - 13917085151028, - 950568481355929, - 23687195265771, - ), - u64x4::new( - 1798284568673198, - 808382292203333, - 2214698741961545, - 610817203275867, - ), - ])), - CachedPoint(F51x4Reduced([ - u64x4::new( - 1731488929623777, - 1158815615106413, - 1491090861948525, - 1428384712900962, - ), - u64x4::new( - 722237139522457, - 1514290328911535, - 1366197913116230, - 1519472657321210, - ), - u64x4::new( - 246028966932273, - 1888239319448405, - 423720022211163, - 455243905681470, - ), - u64x4::new( - 738323403716001, - 1758018973481179, - 1180718299482318, - 1008495946606708, - ), - u64x4::new( - 334959381596119, - 1704599537529481, - 2172191232106896, - 13502508918495, - ), - ])), - CachedPoint(F51x4Reduced([ - u64x4::new( - 273393076768079, - 427388720298603, - 1071733376018227, - 1715429388968611, - ), - u64x4::new( - 751776629892313, - 1965239102856011, - 541955408230119, - 831043488876080, - ), - u64x4::new( - 643718536393104, - 390543998404644, - 2176730661486279, - 499459234889079, - ), - u64x4::new( - 1482404333915009, - 865527293526285, - 507957951411713, - 216456252558825, - ), - u64x4::new( - 2210281256300231, - 1519357818277551, - 1257866936775246, - 1689605217672864, - ), - ])), - CachedPoint(F51x4Reduced([ - u64x4::new( - 2135395168187905, - 2214400157568614, - 2032983817870823, - 1124945109072647, - ), - u64x4::new( - 1602820011758145, - 906675633903289, - 782700735390986, - 2067218823525601, - ), - u64x4::new( - 786785748926382, - 1433583123655616, - 905839404290873, - 2249680349963778, - ), - u64x4::new( - 1940824582370584, - 1610961256326291, - 285307858781375, - 1755588655461194, - ), - u64x4::new( - 233682812055333, - 2146114223476434, - 41132209533476, - 535292431776371, - ), - ])), - CachedPoint(F51x4Reduced([ - u64x4::new( - 600257696476418, - 18449221564824, - 1422209458591138, - 239571584769716, - ), - u64x4::new( - 2056372917056980, - 1155290566623531, - 1252473955568148, - 1276690716882081, - ), - u64x4::new( - 246974369025311, - 658117221519903, - 2000380937898441, - 1351183273924850, - ), - u64x4::new( - 1803747363753112, - 1736801515030186, - 2025633577199091, - 603378480769167, - ), - u64x4::new( - 57348749438551, - 1893551220299655, - 657926732731806, - 1522499384853705, - ), - ])), - CachedPoint(F51x4Reduced([ - u64x4::new( - 591809128842736, - 284860517232591, - 27436696863545, - 886306697195798, - ), - u64x4::new( - 2113192175751749, - 1405882509906423, - 561316282804847, - 835573846576266, - ), - u64x4::new( - 94407289485409, - 1781534171669004, - 2098782516531528, - 598529921520053, - ), - u64x4::new( - 1860137004504786, - 2197323407480349, - 1516772733981532, - 961740253777086, - ), - u64x4::new( - 1484139612868217, - 1593557644636881, - 838834937143441, - 36382198263380, - ), - ])), - CachedPoint(F51x4Reduced([ - u64x4::new( - 1165898865828562, - 1153420815042389, - 1068625028915785, - 1945927229911090, - ), - u64x4::new( - 843454394017146, - 571029655293754, - 386282254545998, - 1804608237584150, - ), - u64x4::new( - 370552451091100, - 1279105656351124, - 1864742949668631, - 2093071521726981, - ), - u64x4::new( - 1872542389052198, - 1679083953574330, - 349872262454465, - 1470311090717925, - ), - u64x4::new( - 685345654160323, - 319718985807814, - 1359932285384164, - 1410900103316331, - ), - ])), - CachedPoint(F51x4Reduced([ - u64x4::new( - 2083666668832889, - 314624387816655, - 1496694646480345, - 1946728950459189, - ), - u64x4::new( - 1579153761571203, - 508771185291380, - 1002249659402007, - 551517831173801, - ), - u64x4::new( - 2132371471626150, - 1988122278556533, - 1552195130653890, - 1327637750292755, - ), - u64x4::new( - 118937099181527, - 382610380973142, - 634951529106471, - 382740054041699, - ), - u64x4::new( - 801287519643470, - 87822941589258, - 1908825350108451, - 1404208826499115, - ), - ])), - CachedPoint(F51x4Reduced([ - u64x4::new( - 330347226380261, - 672119116965146, - 1761510370768005, - 1959200302484704, - ), - u64x4::new( - 1631876583009250, - 1684917718484264, - 1027256947805920, - 2174612545251129, - ), - u64x4::new( - 636668855699872, - 625187713984839, - 265886954766790, - 167898557908504, - ), - u64x4::new( - 1210974548180860, - 2051308710365526, - 907620584086428, - 1081788677970850, - ), - u64x4::new( - 621792955460854, - 1450945504745382, - 1666728650687828, - 977937146451674, - ), - ])), - CachedPoint(F51x4Reduced([ - u64x4::new( - 24725936182267, - 2226765032752574, - 2036560083102883, - 2002351185719584, - ), - u64x4::new( - 1620080779405308, - 1493220053370419, - 2245691691038916, - 1152182628629603, - ), - u64x4::new( - 317928527147500, - 1855194218440212, - 979380281964169, - 861442286685289, - ), - u64x4::new( - 393308472784625, - 486143087279967, - 1234071346236405, - 777748237119399, - ), - u64x4::new( - 43850412814718, - 1497656407486446, - 744128331046695, - 1618035787321792, - ), - ])), - CachedPoint(F51x4Reduced([ - u64x4::new( - 1670169946550211, - 1230951698726438, - 806586940221293, - 23159779184607, - ), - u64x4::new( - 634011340979302, - 764182085034744, - 731065727766955, - 1737985776442180, - ), - u64x4::new( - 240492712141842, - 73976435954441, - 162810587166835, - 697230894340912, - ), - u64x4::new( - 1299745598348388, - 1359436039694544, - 1856609816731554, - 25228008461513, - ), - u64x4::new( - 2180690501932381, - 2161211192848458, - 87069466793408, - 2003456332883860, - ), - ])), - CachedPoint(F51x4Reduced([ - u64x4::new( - 1106932458043379, - 1675181364231371, - 1681785724775243, - 131824742557210, - ), - u64x4::new( - 1671649414647169, - 1827849994880670, - 1097958057111899, - 701956891169434, - ), - u64x4::new( - 2095539283710881, - 591029812888096, - 1699571518315654, - 1297589045812566, - ), - u64x4::new( - 1345612272298537, - 2166754730876055, - 2047982622154948, - 1785222806258129, - ), - u64x4::new( - 2181915268829890, - 1895697064378670, - 1288412327355885, - 1561075738281368, - ), - ])), - CachedPoint(F51x4Reduced([ - u64x4::new( - 741330264098392, - 357073519729966, - 1603572339180975, - 433572083688575, - ), - u64x4::new( - 699685108971208, - 1719650727634959, - 1941668009419214, - 870374958347891, - ), - u64x4::new( - 385971389331537, - 11655507719711, - 94814615497633, - 515572102810609, - ), - u64x4::new( - 1396688200590426, - 1518748475144123, - 162386454324368, - 2083303971579002, - ), - u64x4::new( - 1511688632419263, - 251584258592336, - 545345887993880, - 1229840230314160, - ), - ])), - CachedPoint(F51x4Reduced([ - u64x4::new( - 1298668855706029, - 2017860934939344, - 2224150456036391, - 1925926576297971, - ), - u64x4::new( - 259522963883544, - 1312469129541229, - 1647530465049600, - 1113737129047154, - ), - u64x4::new( - 733193298663145, - 2115712816303403, - 897628702762311, - 116440277571901, - ), - u64x4::new( - 1998719395229750, - 1662774553684237, - 194395608126452, - 98796702872301, - ), - u64x4::new( - 2226158244229144, - 91961728239158, - 526869903032152, - 849263805316773, - ), - ])), - CachedPoint(F51x4Reduced([ - u64x4::new( - 472779569333556, - 854477760843410, - 2070906720349401, - 734613359834689, - ), - u64x4::new( - 1771897100487404, - 1604024196006064, - 319699348925383, - 437152129592623, - ), - u64x4::new( - 627618365135361, - 1768642666037955, - 588564169143939, - 35295037750744, - ), - u64x4::new( - 220241884231278, - 319104161410840, - 1048165719448798, - 1583931089774347, - ), - u64x4::new( - 166479451884333, - 1623611819962804, - 59990366193679, - 900727256046987, - ), - ])), - CachedPoint(F51x4Reduced([ - u64x4::new( - 1944687327687331, - 1328410791053991, - 2083980670913902, - 609396833380574, - ), - u64x4::new( - 1907563845734496, - 1385619047697883, - 869817384774457, - 106642388505109, - ), - u64x4::new( - 1006516581737154, - 1561918369633937, - 1921172883211450, - 2216650451558824, - ), - u64x4::new( - 1780506017391778, - 233064930371847, - 1332962603425752, - 1380075261612354, - ), - u64x4::new( - 1907624789747741, - 1310065402098523, - 1838275780706825, - 884225500782782, - ), - ])), - CachedPoint(F51x4Reduced([ - u64x4::new( - 198729830692545, - 100156148743413, - 2140568641558859, - 2220606475942394, - ), - u64x4::new( - 1108788217903741, - 1706330932366163, - 2050449866410661, - 684907598542847, - ), - u64x4::new( - 1101958322366646, - 659427843062405, - 253899933868173, - 896574852821269, - ), - u64x4::new( - 1157052140740658, - 440541103447032, - 2173354981480949, - 604768603561932, - ), - u64x4::new( - 961238337866054, - 830849154351308, - 1643852412409441, - 1436749321770368, - ), - ])), - CachedPoint(F51x4Reduced([ - u64x4::new( - 784870637473285, - 1180234052037572, - 2086951602998715, - 419328169540373, - ), - u64x4::new( - 1966862397394559, - 788036164772123, - 2024355635709481, - 1471696676696146, - ), - u64x4::new( - 1468884300957205, - 1408016588131185, - 2229595828577885, - 240413942963547, - ), - u64x4::new( - 1481791691942441, - 970648959691160, - 1635500996148197, - 2236917233261585, - ), - u64x4::new( - 31660820731028, - 801794768903647, - 1069092619607344, - 282652554845923, - ), - ])), - CachedPoint(F51x4Reduced([ - u64x4::new( - 911659428682786, - 762502588057038, - 1311399152500807, - 1966922911783311, - ), - u64x4::new( - 1229849228728540, - 258161307933217, - 2140796867375541, - 1569345075547911, - ), - u64x4::new( - 1487354676143742, - 1818317546165791, - 811033554173350, - 1768788663337616, - ), - u64x4::new( - 450017165913234, - 962535873747168, - 2099104262993585, - 503030952485785, - ), - u64x4::new( - 1259958681304518, - 479589250923541, - 1503904042161640, - 706283657294305, - ), - ])), - CachedPoint(F51x4Reduced([ - u64x4::new( - 794562643024291, - 198670993088241, - 1678984629358943, - 273399517554618, - ), - u64x4::new( - 188458991574433, - 1389872130156447, - 1461868931574746, - 795140878721432, - ), - u64x4::new( - 624046647169653, - 630363741191019, - 911018499983500, - 1410140563046579, - ), - u64x4::new( - 1675056174405076, - 632544713589250, - 795454163559811, - 1535271563341780, - ), - u64x4::new( - 25504547444781, - 812510098987855, - 51290042016232, - 1992260991700127, - ), - ])), - CachedPoint(F51x4Reduced([ - u64x4::new( - 269968325452358, - 470932785179706, - 1684444304834150, - 1027482126748243, - ), - u64x4::new( - 457941065342419, - 2117377568137882, - 1209423706730905, - 2192403099717071, - ), - u64x4::new( - 1899046404863678, - 1359500336071762, - 1492389156724726, - 1455627081827750, - ), - u64x4::new( - 2016101061876546, - 1967000012916571, - 582539481696050, - 1197538178790094, - ), - u64x4::new( - 639684852217504, - 1799941252757449, - 1470016556327743, - 846111828965901, - ), - ])), -]); diff --git a/net/gurk-rs/files/vendor/curve25519-dalek/src/backend/vector/ifma/edwards.rs b/net/gurk-rs/files/vendor/curve25519-dalek/src/backend/vector/ifma/edwards.rs deleted file mode 100644 index 5c8d819..0000000 --- a/net/gurk-rs/files/vendor/curve25519-dalek/src/backend/vector/ifma/edwards.rs +++ /dev/null @@ -1,315 +0,0 @@ -// -*- mode: rust; -*- -// -// This file is part of curve25519-dalek. -// Copyright (c) 2018-2019 Henry de Valence -// See LICENSE for licensing information. -// -// Authors: -// - Henry de Valence - -#![allow(non_snake_case)] - -use traits::Identity; - -use std::ops::{Add, Neg, Sub}; - -use subtle::Choice; -use subtle::ConditionallySelectable; - -use edwards; -use window::{LookupTable, NafLookupTable5, NafLookupTable8}; - -use super::constants; -use super::field::{F51x4Reduced, F51x4Unreduced, Lanes, Shuffle}; - -#[derive(Copy, Clone, Debug)] -pub struct ExtendedPoint(pub(super) F51x4Unreduced); - -#[derive(Copy, Clone, Debug)] -pub struct CachedPoint(pub(super) F51x4Reduced); - -impl From for ExtendedPoint { - fn from(P: edwards::EdwardsPoint) -> ExtendedPoint { - ExtendedPoint(F51x4Unreduced::new(&P.X, &P.Y, &P.Z, &P.T)) - } -} - -impl From for edwards::EdwardsPoint { - fn from(P: ExtendedPoint) -> edwards::EdwardsPoint { - let reduced = F51x4Reduced::from(P.0); - let tmp = F51x4Unreduced::from(reduced).split(); - edwards::EdwardsPoint { - X: tmp[0], - Y: tmp[1], - Z: tmp[2], - T: tmp[3], - } - } -} - -impl From for CachedPoint { - fn from(P: ExtendedPoint) -> CachedPoint { - let mut x = P.0; - - x = x.blend(&x.diff_sum(), Lanes::AB); - x = &F51x4Reduced::from(x) * (121666, 121666, 2 * 121666, 2 * 121665); - x = x.blend(&x.negate_lazy(), Lanes::D); - - CachedPoint(F51x4Reduced::from(x)) - } -} - -impl Default for ExtendedPoint { - fn default() -> ExtendedPoint { - ExtendedPoint::identity() - } -} - -impl Identity for ExtendedPoint { - fn identity() -> ExtendedPoint { - constants::EXTENDEDPOINT_IDENTITY - } -} - -impl ExtendedPoint { - pub fn double(&self) -> ExtendedPoint { - // (Y1 X1 T1 Z1) -- uses vpshufd (1c latency @ 1/c) - let mut tmp0 = self.0.shuffle(Shuffle::BADC); - - // (X1+Y1 X1+Y1 X1+Y1 X1+Y1) -- can use vpinserti128 - let mut tmp1 = (self.0 + tmp0).shuffle(Shuffle::ABAB); - - // (X1 Y1 Z1 X1+Y1) - tmp0 = self.0.blend(&tmp1, Lanes::D); - - tmp1 = F51x4Reduced::from(tmp0).square(); - // Now tmp1 = (S1 S2 S3 S4) - - // We want to compute - // - // + | S1 | S1 | S1 | S1 | - // + | S2 | | | S2 | - // + | | | S3 | | - // + | | | S3 | | - // + | |16p |16p |16p | - // - | | S2 | S2 | | - // - | | | | S4 | - // ======================= - // S5 S6 S8 S9 - - let zero = F51x4Unreduced::zero(); - - let S1_S1_S1_S1 = tmp1.shuffle(Shuffle::AAAA); - let S2_S2_S2_S2 = tmp1.shuffle(Shuffle::BBBB); - - let S2_S2_S2_S4 = S2_S2_S2_S2.blend(&tmp1, Lanes::D).negate_lazy(); - - tmp0 = S1_S1_S1_S1 + zero.blend(&(tmp1 + tmp1), Lanes::C); - tmp0 = tmp0 + zero.blend(&S2_S2_S2_S2, Lanes::AD); - tmp0 = tmp0 + zero.blend(&S2_S2_S2_S4, Lanes::BCD); - - let tmp2 = F51x4Reduced::from(tmp0); - - ExtendedPoint(&tmp2.shuffle(Shuffle::DBBD) * &tmp2.shuffle(Shuffle::CACA)) - } - - pub fn mul_by_pow_2(&self, k: u32) -> ExtendedPoint { - let mut tmp: ExtendedPoint = *self; - for _ in 0..k { - tmp = tmp.double(); - } - tmp - } -} - -impl<'a, 'b> Add<&'b CachedPoint> for &'a ExtendedPoint { - type Output = ExtendedPoint; - - /// Add an `ExtendedPoint` and a `CachedPoint`. - fn add(self, other: &'b CachedPoint) -> ExtendedPoint { - let mut tmp = self.0; - - tmp = tmp.blend(&tmp.diff_sum(), Lanes::AB); - // tmp = (Y1-X1 Y1+X1 Z1 T1) = (S0 S1 Z1 T1) - - tmp = &F51x4Reduced::from(tmp) * &other.0; - // tmp = (S0*S2' S1*S3' Z1*Z2' T1*T2') = (S8 S9 S10 S11) - - tmp = tmp.shuffle(Shuffle::ABDC); - // tmp = (S8 S9 S11 S10) - - let tmp = F51x4Reduced::from(tmp.diff_sum()); - // tmp = (S9-S8 S9+S8 S10-S11 S10+S11) = (S12 S13 S14 S15) - - let t0 = tmp.shuffle(Shuffle::ADDA); - // t0 = (S12 S15 S15 S12) - let t1 = tmp.shuffle(Shuffle::CBCB); - // t1 = (S14 S13 S14 S13) - - // Return (S12*S14 S15*S13 S15*S14 S12*S13) = (X3 Y3 Z3 T3) - ExtendedPoint(&t0 * &t1) - } -} - -impl Default for CachedPoint { - fn default() -> CachedPoint { - CachedPoint::identity() - } -} - -impl Identity for CachedPoint { - fn identity() -> CachedPoint { - constants::CACHEDPOINT_IDENTITY - } -} - -impl ConditionallySelectable for CachedPoint { - fn conditional_select(a: &Self, b: &Self, choice: Choice) -> Self { - CachedPoint(F51x4Reduced::conditional_select(&a.0, &b.0, choice)) - } - - fn conditional_assign(&mut self, other: &Self, choice: Choice) { - self.0.conditional_assign(&other.0, choice); - } -} - -impl<'a> Neg for &'a CachedPoint { - type Output = CachedPoint; - - fn neg(self) -> CachedPoint { - let swapped = self.0.shuffle(Shuffle::BACD); - CachedPoint(swapped.blend(&(-self.0), Lanes::D)) - } -} - -impl<'a, 'b> Sub<&'b CachedPoint> for &'a ExtendedPoint { - type Output = ExtendedPoint; - - /// Implement subtraction by negating the point and adding. - fn sub(self, other: &'b CachedPoint) -> ExtendedPoint { - self + &(-other) - } -} - -impl<'a> From<&'a edwards::EdwardsPoint> for LookupTable { - fn from(point: &'a edwards::EdwardsPoint) -> Self { - let P = ExtendedPoint::from(*point); - let mut points = [CachedPoint::from(P); 8]; - for i in 0..7 { - points[i + 1] = (&P + &points[i]).into(); - } - LookupTable(points) - } -} - -impl<'a> From<&'a edwards::EdwardsPoint> for NafLookupTable5 { - fn from(point: &'a edwards::EdwardsPoint) -> Self { - let A = ExtendedPoint::from(*point); - let mut Ai = [CachedPoint::from(A); 8]; - let A2 = A.double(); - for i in 0..7 { - Ai[i + 1] = (&A2 + &Ai[i]).into(); - } - // Now Ai = [A, 3A, 5A, 7A, 9A, 11A, 13A, 15A] - NafLookupTable5(Ai) - } -} - -impl<'a> From<&'a edwards::EdwardsPoint> for NafLookupTable8 { - fn from(point: &'a edwards::EdwardsPoint) -> Self { - let A = ExtendedPoint::from(*point); - let mut Ai = [CachedPoint::from(A); 64]; - let A2 = A.double(); - for i in 0..63 { - Ai[i + 1] = (&A2 + &Ai[i]).into(); - } - // Now Ai = [A, 3A, 5A, 7A, 9A, 11A, 13A, 15A, ..., 127A] - NafLookupTable8(Ai) - } -} - -#[cfg(test)] -mod test { - use super::*; - - fn addition_test_helper(P: edwards::EdwardsPoint, Q: edwards::EdwardsPoint) { - // Test the serial implementation of the parallel addition formulas - //let R_serial: edwards::EdwardsPoint = serial_add(P.into(), Q.into()).into(); - - // Test the vector implementation of the parallel readdition formulas - let cached_Q = CachedPoint::from(ExtendedPoint::from(Q)); - let R_vector: edwards::EdwardsPoint = (&ExtendedPoint::from(P) + &cached_Q).into(); - let S_vector: edwards::EdwardsPoint = (&ExtendedPoint::from(P) - &cached_Q).into(); - - println!("Testing point addition:"); - println!("P = {:?}", P); - println!("Q = {:?}", Q); - println!("cached Q = {:?}", cached_Q); - println!("R = P + Q = {:?}", &P + &Q); - //println!("R_serial = {:?}", R_serial); - println!("R_vector = {:?}", R_vector); - println!("S = P - Q = {:?}", &P - &Q); - println!("S_vector = {:?}", S_vector); - //assert_eq!(R_serial.compress(), (&P + &Q).compress()); - assert_eq!(R_vector.compress(), (&P + &Q).compress()); - assert_eq!(S_vector.compress(), (&P - &Q).compress()); - println!("OK!\n"); - } - - #[test] - fn vector_addition_vs_serial_addition_vs_edwards_extendedpoint() { - use constants; - use scalar::Scalar; - - println!("Testing id +- id"); - let P = edwards::EdwardsPoint::identity(); - let Q = edwards::EdwardsPoint::identity(); - addition_test_helper(P, Q); - - println!("Testing id +- B"); - let P = edwards::EdwardsPoint::identity(); - let Q = constants::ED25519_BASEPOINT_POINT; - addition_test_helper(P, Q); - - println!("Testing B +- B"); - let P = constants::ED25519_BASEPOINT_POINT; - let Q = constants::ED25519_BASEPOINT_POINT; - addition_test_helper(P, Q); - - println!("Testing B +- kB"); - let P = constants::ED25519_BASEPOINT_POINT; - let Q = &constants::ED25519_BASEPOINT_TABLE * &Scalar::from(8475983829u64); - addition_test_helper(P, Q); - } - - fn doubling_test_helper(P: edwards::EdwardsPoint) { - //let R1: edwards::EdwardsPoint = serial_double(P.into()).into(); - let R2: edwards::EdwardsPoint = ExtendedPoint::from(P).double().into(); - println!("Testing point doubling:"); - println!("P = {:?}", P); - //println!("(serial) R1 = {:?}", R1); - println!("(vector) R2 = {:?}", R2); - println!("P + P = {:?}", &P + &P); - //assert_eq!(R1.compress(), (&P + &P).compress()); - assert_eq!(R2.compress(), (&P + &P).compress()); - println!("OK!\n"); - } - - #[test] - fn vector_doubling_vs_serial_doubling_vs_edwards_extendedpoint() { - use constants; - use scalar::Scalar; - - println!("Testing [2]id"); - let P = edwards::EdwardsPoint::identity(); - doubling_test_helper(P); - - println!("Testing [2]B"); - let P = constants::ED25519_BASEPOINT_POINT; - doubling_test_helper(P); - - println!("Testing [2]([k]B)"); - let P = &constants::ED25519_BASEPOINT_TABLE * &Scalar::from(8475983829u64); - doubling_test_helper(P); - } -} diff --git a/net/gurk-rs/files/vendor/curve25519-dalek/src/backend/vector/ifma/field.rs b/net/gurk-rs/files/vendor/curve25519-dalek/src/backend/vector/ifma/field.rs deleted file mode 100644 index a393b22..0000000 --- a/net/gurk-rs/files/vendor/curve25519-dalek/src/backend/vector/ifma/field.rs +++ /dev/null @@ -1,826 +0,0 @@ -// -*- mode: rust; -*- -// -// This file is part of curve25519-dalek. -// Copyright (c) 2016-2021 isis lovecruft -// Copyright (c) 2016-2019 Henry de Valence -// See LICENSE for licensing information. -// -// Authors: -// - isis agora lovecruft -// - Henry de Valence - -#![allow(non_snake_case)] - -use core::ops::{Add, Mul, Neg}; -use packed_simd::{u64x4, IntoBits}; - -use backend::serial::u64::field::FieldElement51; - -/// A wrapper around `vpmadd52luq` that works on `u64x4`. -#[inline(always)] -unsafe fn madd52lo(z: u64x4, x: u64x4, y: u64x4) -> u64x4 { - use core::arch::x86_64::_mm256_madd52lo_epu64; - _mm256_madd52lo_epu64(z.into_bits(), x.into_bits(), y.into_bits()).into_bits() -} - -/// A wrapper around `vpmadd52huq` that works on `u64x4`. -#[inline(always)] -unsafe fn madd52hi(z: u64x4, x: u64x4, y: u64x4) -> u64x4 { - use core::arch::x86_64::_mm256_madd52hi_epu64; - _mm256_madd52hi_epu64(z.into_bits(), x.into_bits(), y.into_bits()).into_bits() -} - -/// A vector of four field elements in radix 2^51, with unreduced coefficients. -#[derive(Copy, Clone, Debug)] -pub struct F51x4Unreduced(pub(crate) [u64x4; 5]); - -/// A vector of four field elements in radix 2^51, with reduced coefficients. -#[derive(Copy, Clone, Debug)] -pub struct F51x4Reduced(pub(crate) [u64x4; 5]); - -#[derive(Copy, Clone)] -pub enum Shuffle { - AAAA, - BBBB, - BADC, - BACD, - ADDA, - CBCB, - ABDC, - ABAB, - DBBD, - CACA, -} - -#[inline(always)] -fn shuffle_lanes(x: u64x4, control: Shuffle) -> u64x4 { - unsafe { - use core::arch::x86_64::_mm256_permute4x64_epi64 as perm; - - match control { - Shuffle::AAAA => perm(x.into_bits(), 0b00_00_00_00).into_bits(), - Shuffle::BBBB => perm(x.into_bits(), 0b01_01_01_01).into_bits(), - Shuffle::BADC => perm(x.into_bits(), 0b10_11_00_01).into_bits(), - Shuffle::BACD => perm(x.into_bits(), 0b11_10_00_01).into_bits(), - Shuffle::ADDA => perm(x.into_bits(), 0b00_11_11_00).into_bits(), - Shuffle::CBCB => perm(x.into_bits(), 0b01_10_01_10).into_bits(), - Shuffle::ABDC => perm(x.into_bits(), 0b10_11_01_00).into_bits(), - Shuffle::ABAB => perm(x.into_bits(), 0b01_00_01_00).into_bits(), - Shuffle::DBBD => perm(x.into_bits(), 0b11_01_01_11).into_bits(), - Shuffle::CACA => perm(x.into_bits(), 0b00_10_00_10).into_bits(), - } - } -} - -#[derive(Copy, Clone)] -pub enum Lanes { - D, - C, - AB, - AC, - AD, - BCD, -} - -#[inline] -fn blend_lanes(x: u64x4, y: u64x4, control: Lanes) -> u64x4 { - unsafe { - use core::arch::x86_64::_mm256_blend_epi32 as blend; - - match control { - Lanes::D => blend(x.into_bits(), y.into_bits(), 0b11_00_00_00).into_bits(), - Lanes::C => blend(x.into_bits(), y.into_bits(), 0b00_11_00_00).into_bits(), - Lanes::AB => blend(x.into_bits(), y.into_bits(), 0b00_00_11_11).into_bits(), - Lanes::AC => blend(x.into_bits(), y.into_bits(), 0b00_11_00_11).into_bits(), - Lanes::AD => blend(x.into_bits(), y.into_bits(), 0b11_00_00_11).into_bits(), - Lanes::BCD => blend(x.into_bits(), y.into_bits(), 0b11_11_11_00).into_bits(), - } - } -} - -impl F51x4Unreduced { - pub fn zero() -> F51x4Unreduced { - F51x4Unreduced([u64x4::splat(0); 5]) - } - - pub fn new( - x0: &FieldElement51, - x1: &FieldElement51, - x2: &FieldElement51, - x3: &FieldElement51, - ) -> F51x4Unreduced { - F51x4Unreduced([ - u64x4::new(x0.0[0], x1.0[0], x2.0[0], x3.0[0]), - u64x4::new(x0.0[1], x1.0[1], x2.0[1], x3.0[1]), - u64x4::new(x0.0[2], x1.0[2], x2.0[2], x3.0[2]), - u64x4::new(x0.0[3], x1.0[3], x2.0[3], x3.0[3]), - u64x4::new(x0.0[4], x1.0[4], x2.0[4], x3.0[4]), - ]) - } - - pub fn split(&self) -> [FieldElement51; 4] { - let x = &self.0; - [ - FieldElement51([ - x[0].extract(0), - x[1].extract(0), - x[2].extract(0), - x[3].extract(0), - x[4].extract(0), - ]), - FieldElement51([ - x[0].extract(1), - x[1].extract(1), - x[2].extract(1), - x[3].extract(1), - x[4].extract(1), - ]), - FieldElement51([ - x[0].extract(2), - x[1].extract(2), - x[2].extract(2), - x[3].extract(2), - x[4].extract(2), - ]), - FieldElement51([ - x[0].extract(3), - x[1].extract(3), - x[2].extract(3), - x[3].extract(3), - x[4].extract(3), - ]), - ] - } - - #[inline] - pub fn diff_sum(&self) -> F51x4Unreduced { - // tmp1 = (B, A, D, C) - let tmp1 = self.shuffle(Shuffle::BADC); - // tmp2 = (-A, B, -C, D) - let tmp2 = self.blend(&self.negate_lazy(), Lanes::AC); - // (B - A, B + A, D - C, D + C) - tmp1 + tmp2 - } - - #[inline] - pub fn negate_lazy(&self) -> F51x4Unreduced { - let lo = u64x4::splat(36028797018963664u64); - let hi = u64x4::splat(36028797018963952u64); - F51x4Unreduced([ - lo - self.0[0], - hi - self.0[1], - hi - self.0[2], - hi - self.0[3], - hi - self.0[4], - ]) - } - - #[inline] - pub fn shuffle(&self, control: Shuffle) -> F51x4Unreduced { - F51x4Unreduced([ - shuffle_lanes(self.0[0], control), - shuffle_lanes(self.0[1], control), - shuffle_lanes(self.0[2], control), - shuffle_lanes(self.0[3], control), - shuffle_lanes(self.0[4], control), - ]) - } - - #[inline] - pub fn blend(&self, other: &F51x4Unreduced, control: Lanes) -> F51x4Unreduced { - F51x4Unreduced([ - blend_lanes(self.0[0], other.0[0], control), - blend_lanes(self.0[1], other.0[1], control), - blend_lanes(self.0[2], other.0[2], control), - blend_lanes(self.0[3], other.0[3], control), - blend_lanes(self.0[4], other.0[4], control), - ]) - } -} - -impl Neg for F51x4Reduced { - type Output = F51x4Reduced; - - fn neg(self) -> F51x4Reduced { - F51x4Unreduced::from(self).negate_lazy().into() - } -} - -use subtle::Choice; -use subtle::ConditionallySelectable; - -impl ConditionallySelectable for F51x4Reduced { - #[inline] - fn conditional_select(a: &F51x4Reduced, b: &F51x4Reduced, choice: Choice) -> F51x4Reduced { - let mask = (-(choice.unwrap_u8() as i64)) as u64; - let mask_vec = u64x4::splat(mask); - F51x4Reduced([ - a.0[0] ^ (mask_vec & (a.0[0] ^ b.0[0])), - a.0[1] ^ (mask_vec & (a.0[1] ^ b.0[1])), - a.0[2] ^ (mask_vec & (a.0[2] ^ b.0[2])), - a.0[3] ^ (mask_vec & (a.0[3] ^ b.0[3])), - a.0[4] ^ (mask_vec & (a.0[4] ^ b.0[4])), - ]) - } - - #[inline] - fn conditional_assign(&mut self, other: &F51x4Reduced, choice: Choice) { - let mask = (-(choice.unwrap_u8() as i64)) as u64; - let mask_vec = u64x4::splat(mask); - self.0[0] ^= mask_vec & (self.0[0] ^ other.0[0]); - self.0[1] ^= mask_vec & (self.0[1] ^ other.0[1]); - self.0[2] ^= mask_vec & (self.0[2] ^ other.0[2]); - self.0[3] ^= mask_vec & (self.0[3] ^ other.0[3]); - self.0[4] ^= mask_vec & (self.0[4] ^ other.0[4]); - } -} - -impl F51x4Reduced { - #[inline] - pub fn shuffle(&self, control: Shuffle) -> F51x4Reduced { - F51x4Reduced([ - shuffle_lanes(self.0[0], control), - shuffle_lanes(self.0[1], control), - shuffle_lanes(self.0[2], control), - shuffle_lanes(self.0[3], control), - shuffle_lanes(self.0[4], control), - ]) - } - - #[inline] - pub fn blend(&self, other: &F51x4Reduced, control: Lanes) -> F51x4Reduced { - F51x4Reduced([ - blend_lanes(self.0[0], other.0[0], control), - blend_lanes(self.0[1], other.0[1], control), - blend_lanes(self.0[2], other.0[2], control), - blend_lanes(self.0[3], other.0[3], control), - blend_lanes(self.0[4], other.0[4], control), - ]) - } - - #[inline] - pub fn square(&self) -> F51x4Unreduced { - unsafe { - let x = &self.0; - - // Represent values with coeff. 2 - let mut z0_2 = u64x4::splat(0); - let mut z1_2 = u64x4::splat(0); - let mut z2_2 = u64x4::splat(0); - let mut z3_2 = u64x4::splat(0); - let mut z4_2 = u64x4::splat(0); - let mut z5_2 = u64x4::splat(0); - let mut z6_2 = u64x4::splat(0); - let mut z7_2 = u64x4::splat(0); - let mut z9_2 = u64x4::splat(0); - - // Represent values with coeff. 4 - let mut z2_4 = u64x4::splat(0); - let mut z3_4 = u64x4::splat(0); - let mut z4_4 = u64x4::splat(0); - let mut z5_4 = u64x4::splat(0); - let mut z6_4 = u64x4::splat(0); - let mut z7_4 = u64x4::splat(0); - let mut z8_4 = u64x4::splat(0); - - let mut z0_1 = u64x4::splat(0); - z0_1 = madd52lo(z0_1, x[0], x[0]); - - let mut z1_1 = u64x4::splat(0); - z1_2 = madd52lo(z1_2, x[0], x[1]); - z1_2 = madd52hi(z1_2, x[0], x[0]); - - z2_4 = madd52hi(z2_4, x[0], x[1]); - let mut z2_1 = z2_4 << 2; - z2_2 = madd52lo(z2_2, x[0], x[2]); - z2_1 = madd52lo(z2_1, x[1], x[1]); - - z3_4 = madd52hi(z3_4, x[0], x[2]); - let mut z3_1 = z3_4 << 2; - z3_2 = madd52lo(z3_2, x[1], x[2]); - z3_2 = madd52lo(z3_2, x[0], x[3]); - z3_2 = madd52hi(z3_2, x[1], x[1]); - - z4_4 = madd52hi(z4_4, x[1], x[2]); - z4_4 = madd52hi(z4_4, x[0], x[3]); - let mut z4_1 = z4_4 << 2; - z4_2 = madd52lo(z4_2, x[1], x[3]); - z4_2 = madd52lo(z4_2, x[0], x[4]); - z4_1 = madd52lo(z4_1, x[2], x[2]); - - z5_4 = madd52hi(z5_4, x[1], x[3]); - z5_4 = madd52hi(z5_4, x[0], x[4]); - let mut z5_1 = z5_4 << 2; - z5_2 = madd52lo(z5_2, x[2], x[3]); - z5_2 = madd52lo(z5_2, x[1], x[4]); - z5_2 = madd52hi(z5_2, x[2], x[2]); - - z6_4 = madd52hi(z6_4, x[2], x[3]); - z6_4 = madd52hi(z6_4, x[1], x[4]); - let mut z6_1 = z6_4 << 2; - z6_2 = madd52lo(z6_2, x[2], x[4]); - z6_1 = madd52lo(z6_1, x[3], x[3]); - - z7_4 = madd52hi(z7_4, x[2], x[4]); - let mut z7_1 = z7_4 << 2; - z7_2 = madd52lo(z7_2, x[3], x[4]); - z7_2 = madd52hi(z7_2, x[3], x[3]); - - z8_4 = madd52hi(z8_4, x[3], x[4]); - let mut z8_1 = z8_4 << 2; - z8_1 = madd52lo(z8_1, x[4], x[4]); - - let mut z9_1 = u64x4::splat(0); - z9_2 = madd52hi(z9_2, x[4], x[4]); - - z5_1 += z5_2 << 1; - z6_1 += z6_2 << 1; - z7_1 += z7_2 << 1; - z9_1 += z9_2 << 1; - - let mut t0 = u64x4::splat(0); - let mut t1 = u64x4::splat(0); - let r19 = u64x4::splat(19); - - t0 = madd52hi(t0, r19, z9_1); - t1 = madd52lo(t1, r19, z9_1 >> 52); - - z4_2 = madd52lo(z4_2, r19, z8_1 >> 52); - z3_2 = madd52lo(z3_2, r19, z7_1 >> 52); - z2_2 = madd52lo(z2_2, r19, z6_1 >> 52); - z1_2 = madd52lo(z1_2, r19, z5_1 >> 52); - - z0_2 = madd52lo(z0_2, r19, t0 + t1); - z1_2 = madd52hi(z1_2, r19, z5_1); - z2_2 = madd52hi(z2_2, r19, z6_1); - z3_2 = madd52hi(z3_2, r19, z7_1); - z4_2 = madd52hi(z4_2, r19, z8_1); - - z0_1 = madd52lo(z0_1, r19, z5_1); - z1_1 = madd52lo(z1_1, r19, z6_1); - z2_1 = madd52lo(z2_1, r19, z7_1); - z3_1 = madd52lo(z3_1, r19, z8_1); - z4_1 = madd52lo(z4_1, r19, z9_1); - - F51x4Unreduced([ - z0_1 + z0_2 + z0_2, - z1_1 + z1_2 + z1_2, - z2_1 + z2_2 + z2_2, - z3_1 + z3_2 + z3_2, - z4_1 + z4_2 + z4_2, - ]) - } - } -} - -impl From for F51x4Unreduced { - #[inline] - fn from(x: F51x4Reduced) -> F51x4Unreduced { - F51x4Unreduced(x.0) - } -} - -impl From for F51x4Reduced { - #[inline] - fn from(x: F51x4Unreduced) -> F51x4Reduced { - let mask = u64x4::splat((1 << 51) - 1); - let r19 = u64x4::splat(19); - - // Compute carryouts in parallel - let c0 = x.0[0] >> 51; - let c1 = x.0[1] >> 51; - let c2 = x.0[2] >> 51; - let c3 = x.0[3] >> 51; - let c4 = x.0[4] >> 51; - - unsafe { - F51x4Reduced([ - madd52lo(x.0[0] & mask, c4, r19), - (x.0[1] & mask) + c0, - (x.0[2] & mask) + c1, - (x.0[3] & mask) + c2, - (x.0[4] & mask) + c3, - ]) - } - } -} - -impl Add for F51x4Unreduced { - type Output = F51x4Unreduced; - #[inline] - fn add(self, rhs: F51x4Unreduced) -> F51x4Unreduced { - F51x4Unreduced([ - self.0[0] + rhs.0[0], - self.0[1] + rhs.0[1], - self.0[2] + rhs.0[2], - self.0[3] + rhs.0[3], - self.0[4] + rhs.0[4], - ]) - } -} - -impl<'a> Mul<(u32, u32, u32, u32)> for &'a F51x4Reduced { - type Output = F51x4Unreduced; - #[inline] - fn mul(self, scalars: (u32, u32, u32, u32)) -> F51x4Unreduced { - unsafe { - let x = &self.0; - let y = u64x4::new( - scalars.0 as u64, - scalars.1 as u64, - scalars.2 as u64, - scalars.3 as u64, - ); - let r19 = u64x4::splat(19); - - let mut z0_1 = u64x4::splat(0); - let mut z1_1 = u64x4::splat(0); - let mut z2_1 = u64x4::splat(0); - let mut z3_1 = u64x4::splat(0); - let mut z4_1 = u64x4::splat(0); - let mut z1_2 = u64x4::splat(0); - let mut z2_2 = u64x4::splat(0); - let mut z3_2 = u64x4::splat(0); - let mut z4_2 = u64x4::splat(0); - let mut z5_2 = u64x4::splat(0); - - // Wave 0 - z4_2 = madd52hi(z4_2, y, x[3]); - z5_2 = madd52hi(z5_2, y, x[4]); - z4_1 = madd52lo(z4_1, y, x[4]); - z0_1 = madd52lo(z0_1, y, x[0]); - z3_1 = madd52lo(z3_1, y, x[3]); - z2_1 = madd52lo(z2_1, y, x[2]); - z1_1 = madd52lo(z1_1, y, x[1]); - z3_2 = madd52hi(z3_2, y, x[2]); - - // Wave 2 - z2_2 = madd52hi(z2_2, y, x[1]); - z1_2 = madd52hi(z1_2, y, x[0]); - z0_1 = madd52lo(z0_1, z5_2 + z5_2, r19); - - F51x4Unreduced([ - z0_1, - z1_1 + z1_2 + z1_2, - z2_1 + z2_2 + z2_2, - z3_1 + z3_2 + z3_2, - z4_1 + z4_2 + z4_2, - ]) - } - } -} - -impl<'a, 'b> Mul<&'b F51x4Reduced> for &'a F51x4Reduced { - type Output = F51x4Unreduced; - #[inline] - fn mul(self, rhs: &'b F51x4Reduced) -> F51x4Unreduced { - unsafe { - // Inputs - let x = &self.0; - let y = &rhs.0; - - // Accumulators for terms with coeff 1 - let mut z0_1 = u64x4::splat(0); - let mut z1_1 = u64x4::splat(0); - let mut z2_1 = u64x4::splat(0); - let mut z3_1 = u64x4::splat(0); - let mut z4_1 = u64x4::splat(0); - let mut z5_1 = u64x4::splat(0); - let mut z6_1 = u64x4::splat(0); - let mut z7_1 = u64x4::splat(0); - let mut z8_1 = u64x4::splat(0); - - // Accumulators for terms with coeff 2 - let mut z0_2 = u64x4::splat(0); - let mut z1_2 = u64x4::splat(0); - let mut z2_2 = u64x4::splat(0); - let mut z3_2 = u64x4::splat(0); - let mut z4_2 = u64x4::splat(0); - let mut z5_2 = u64x4::splat(0); - let mut z6_2 = u64x4::splat(0); - let mut z7_2 = u64x4::splat(0); - let mut z8_2 = u64x4::splat(0); - let mut z9_2 = u64x4::splat(0); - - // LLVM doesn't seem to do much work reordering IFMA - // instructions, so try to organize them into "waves" of 8 - // independent operations (4c latency, 0.5 c throughput - // means 8 in flight) - - // Wave 0 - z4_1 = madd52lo(z4_1, x[2], y[2]); - z5_2 = madd52hi(z5_2, x[2], y[2]); - z5_1 = madd52lo(z5_1, x[4], y[1]); - z6_2 = madd52hi(z6_2, x[4], y[1]); - z6_1 = madd52lo(z6_1, x[4], y[2]); - z7_2 = madd52hi(z7_2, x[4], y[2]); - z7_1 = madd52lo(z7_1, x[4], y[3]); - z8_2 = madd52hi(z8_2, x[4], y[3]); - - // Wave 1 - z4_1 = madd52lo(z4_1, x[3], y[1]); - z5_2 = madd52hi(z5_2, x[3], y[1]); - z5_1 = madd52lo(z5_1, x[3], y[2]); - z6_2 = madd52hi(z6_2, x[3], y[2]); - z6_1 = madd52lo(z6_1, x[3], y[3]); - z7_2 = madd52hi(z7_2, x[3], y[3]); - z7_1 = madd52lo(z7_1, x[3], y[4]); - z8_2 = madd52hi(z8_2, x[3], y[4]); - - // Wave 2 - z8_1 = madd52lo(z8_1, x[4], y[4]); - z9_2 = madd52hi(z9_2, x[4], y[4]); - z4_1 = madd52lo(z4_1, x[4], y[0]); - z5_2 = madd52hi(z5_2, x[4], y[0]); - z5_1 = madd52lo(z5_1, x[2], y[3]); - z6_2 = madd52hi(z6_2, x[2], y[3]); - z6_1 = madd52lo(z6_1, x[2], y[4]); - z7_2 = madd52hi(z7_2, x[2], y[4]); - - let z8 = z8_1 + z8_2 + z8_2; - let z9 = z9_2 + z9_2; - - // Wave 3 - z3_1 = madd52lo(z3_1, x[3], y[0]); - z4_2 = madd52hi(z4_2, x[3], y[0]); - z4_1 = madd52lo(z4_1, x[1], y[3]); - z5_2 = madd52hi(z5_2, x[1], y[3]); - z5_1 = madd52lo(z5_1, x[1], y[4]); - z6_2 = madd52hi(z6_2, x[1], y[4]); - z2_1 = madd52lo(z2_1, x[2], y[0]); - z3_2 = madd52hi(z3_2, x[2], y[0]); - - let z6 = z6_1 + z6_2 + z6_2; - let z7 = z7_1 + z7_2 + z7_2; - - // Wave 4 - z3_1 = madd52lo(z3_1, x[2], y[1]); - z4_2 = madd52hi(z4_2, x[2], y[1]); - z4_1 = madd52lo(z4_1, x[0], y[4]); - z5_2 = madd52hi(z5_2, x[0], y[4]); - z1_1 = madd52lo(z1_1, x[1], y[0]); - z2_2 = madd52hi(z2_2, x[1], y[0]); - z2_1 = madd52lo(z2_1, x[1], y[1]); - z3_2 = madd52hi(z3_2, x[1], y[1]); - - let z5 = z5_1 + z5_2 + z5_2; - - // Wave 5 - z3_1 = madd52lo(z3_1, x[1], y[2]); - z4_2 = madd52hi(z4_2, x[1], y[2]); - z0_1 = madd52lo(z0_1, x[0], y[0]); - z1_2 = madd52hi(z1_2, x[0], y[0]); - z1_1 = madd52lo(z1_1, x[0], y[1]); - z2_1 = madd52lo(z2_1, x[0], y[2]); - z2_2 = madd52hi(z2_2, x[0], y[1]); - z3_2 = madd52hi(z3_2, x[0], y[2]); - - let mut t0 = u64x4::splat(0); - let mut t1 = u64x4::splat(0); - let r19 = u64x4::splat(19); - - // Wave 6 - t0 = madd52hi(t0, r19, z9); - t1 = madd52lo(t1, r19, z9 >> 52); - z3_1 = madd52lo(z3_1, x[0], y[3]); - z4_2 = madd52hi(z4_2, x[0], y[3]); - z1_2 = madd52lo(z1_2, r19, z5 >> 52); - z2_2 = madd52lo(z2_2, r19, z6 >> 52); - z3_2 = madd52lo(z3_2, r19, z7 >> 52); - z0_1 = madd52lo(z0_1, r19, z5); - - // Wave 7 - z4_1 = madd52lo(z4_1, r19, z9); - z1_1 = madd52lo(z1_1, r19, z6); - z0_2 = madd52lo(z0_2, r19, t0 + t1); - z4_2 = madd52hi(z4_2, r19, z8); - z2_1 = madd52lo(z2_1, r19, z7); - z1_2 = madd52hi(z1_2, r19, z5); - z2_2 = madd52hi(z2_2, r19, z6); - z3_2 = madd52hi(z3_2, r19, z7); - - // Wave 8 - z3_1 = madd52lo(z3_1, r19, z8); - z4_2 = madd52lo(z4_2, r19, z8 >> 52); - - F51x4Unreduced([ - z0_1 + z0_2 + z0_2, - z1_1 + z1_2 + z1_2, - z2_1 + z2_2 + z2_2, - z3_1 + z3_2 + z3_2, - z4_1 + z4_2 + z4_2, - ]) - } - } -} - -#[cfg(test)] -mod test { - use super::*; - - #[test] - fn vpmadd52luq() { - let x = u64x4::splat(2); - let y = u64x4::splat(3); - let mut z = u64x4::splat(5); - - z = unsafe { madd52lo(z, x, y) }; - - assert_eq!(z, u64x4::splat(5 + 2 * 3)); - } - - #[test] - fn new_split_round_trip_on_reduced_input() { - // Invert a small field element to get a big one - let a = FieldElement51([2438, 24, 243, 0, 0]).invert(); - - let ax4 = F51x4Unreduced::new(&a, &a, &a, &a); - let splits = ax4.split(); - - for i in 0..4 { - assert_eq!(a, splits[i]); - } - } - - #[test] - fn new_split_round_trip_on_unreduced_input() { - // Invert a small field element to get a big one - let a = FieldElement51([2438, 24, 243, 0, 0]).invert(); - // ... but now multiply it by 16 without reducing coeffs - let a16 = FieldElement51([ - a.0[0] << 4, - a.0[1] << 4, - a.0[2] << 4, - a.0[3] << 4, - a.0[4] << 4, - ]); - - let a16x4 = F51x4Unreduced::new(&a16, &a16, &a16, &a16); - let splits = a16x4.split(); - - for i in 0..4 { - assert_eq!(a16, splits[i]); - } - } - - #[test] - fn test_reduction() { - // Invert a small field element to get a big one - let a = FieldElement51([2438, 24, 243, 0, 0]).invert(); - // ... but now multiply it by 128 without reducing coeffs - let abig = FieldElement51([ - a.0[0] << 4, - a.0[1] << 4, - a.0[2] << 4, - a.0[3] << 4, - a.0[4] << 4, - ]); - - let abigx4: F51x4Reduced = F51x4Unreduced::new(&abig, &abig, &abig, &abig).into(); - - let splits = F51x4Unreduced::from(abigx4).split(); - let c = &a * &FieldElement51([(1 << 4), 0, 0, 0, 0]); - - for i in 0..4 { - assert_eq!(c, splits[i]); - } - } - - #[test] - fn mul_matches_serial() { - // Invert a small field element to get a big one - let a = FieldElement51([2438, 24, 243, 0, 0]).invert(); - let b = FieldElement51([98098, 87987897, 0, 1, 0]).invert(); - let c = &a * &b; - - let ax4: F51x4Reduced = F51x4Unreduced::new(&a, &a, &a, &a).into(); - let bx4: F51x4Reduced = F51x4Unreduced::new(&b, &b, &b, &b).into(); - let cx4 = &ax4 * &bx4; - - let splits = cx4.split(); - - for i in 0..4 { - assert_eq!(c, splits[i]); - } - } - - #[test] - fn iterated_mul_matches_serial() { - // Invert a small field element to get a big one - let a = FieldElement51([2438, 24, 243, 0, 0]).invert(); - let b = FieldElement51([98098, 87987897, 0, 1, 0]).invert(); - let mut c = &a * &b; - for _i in 0..1024 { - c = &a * &c; - c = &b * &c; - } - - let ax4: F51x4Reduced = F51x4Unreduced::new(&a, &a, &a, &a).into(); - let bx4: F51x4Reduced = F51x4Unreduced::new(&b, &b, &b, &b).into(); - let mut cx4 = &ax4 * &bx4; - for _i in 0..1024 { - cx4 = &ax4 * &F51x4Reduced::from(cx4); - cx4 = &bx4 * &F51x4Reduced::from(cx4); - } - - let splits = cx4.split(); - - for i in 0..4 { - assert_eq!(c, splits[i]); - } - } - - #[test] - fn square_matches_mul() { - // Invert a small field element to get a big one - let a = FieldElement51([2438, 24, 243, 0, 0]).invert(); - - let ax4: F51x4Reduced = F51x4Unreduced::new(&a, &a, &a, &a).into(); - let cx4 = &ax4 * &ax4; - let cx4_sq = ax4.square(); - - let splits = cx4.split(); - let splits_sq = cx4_sq.split(); - - for i in 0..4 { - assert_eq!(splits_sq[i], splits[i]); - } - } - - #[test] - fn iterated_square_matches_serial() { - // Invert a small field element to get a big one - let mut a = FieldElement51([2438, 24, 243, 0, 0]).invert(); - let mut ax4 = F51x4Unreduced::new(&a, &a, &a, &a); - for _j in 0..1024 { - a = a.square(); - ax4 = F51x4Reduced::from(ax4).square(); - - let splits = ax4.split(); - for i in 0..4 { - assert_eq!(a, splits[i]); - } - } - } - - #[test] - fn iterated_u32_mul_matches_serial() { - // Invert a small field element to get a big one - let a = FieldElement51([2438, 24, 243, 0, 0]).invert(); - let b = FieldElement51([121665, 0, 0, 0, 0]); - let mut c = &a * &b; - for _i in 0..1024 { - c = &b * &c; - } - - let ax4 = F51x4Unreduced::new(&a, &a, &a, &a); - let bx4 = (121665u32, 121665u32, 121665u32, 121665u32); - let mut cx4 = &F51x4Reduced::from(ax4) * bx4; - for _i in 0..1024 { - cx4 = &F51x4Reduced::from(cx4) * bx4; - } - - let splits = cx4.split(); - - for i in 0..4 { - assert_eq!(c, splits[i]); - } - } - - #[test] - fn shuffle_AAAA() { - let x0 = FieldElement51::from_bytes(&[0x10; 32]); - let x1 = FieldElement51::from_bytes(&[0x11; 32]); - let x2 = FieldElement51::from_bytes(&[0x12; 32]); - let x3 = FieldElement51::from_bytes(&[0x13; 32]); - - let x = F51x4Unreduced::new(&x0, &x1, &x2, &x3); - - let y = x.shuffle(Shuffle::AAAA); - let splits = y.split(); - - assert_eq!(splits[0], x0); - assert_eq!(splits[1], x0); - assert_eq!(splits[2], x0); - assert_eq!(splits[3], x0); - } - - #[test] - fn blend_AB() { - let x0 = FieldElement51::from_bytes(&[0x10; 32]); - let x1 = FieldElement51::from_bytes(&[0x11; 32]); - let x2 = FieldElement51::from_bytes(&[0x12; 32]); - let x3 = FieldElement51::from_bytes(&[0x13; 32]); - - let x = F51x4Unreduced::new(&x0, &x1, &x2, &x3); - let z = F51x4Unreduced::new(&x3, &x2, &x1, &x0); - - let y = x.blend(&z, Lanes::AB); - let splits = y.split(); - - assert_eq!(splits[0], x3); - assert_eq!(splits[1], x2); - assert_eq!(splits[2], x2); - assert_eq!(splits[3], x3); - } -} diff --git a/net/gurk-rs/files/vendor/curve25519-dalek/src/backend/vector/ifma/mod.rs b/net/gurk-rs/files/vendor/curve25519-dalek/src/backend/vector/ifma/mod.rs deleted file mode 100644 index 6191ecc..0000000 --- a/net/gurk-rs/files/vendor/curve25519-dalek/src/backend/vector/ifma/mod.rs +++ /dev/null @@ -1,19 +0,0 @@ -// -*- mode: rust; -*- -// -// This file is part of curve25519-dalek. -// Copyright (c) 2018-2019 Henry de Valence -// See LICENSE for licensing information. -// -// Authors: -// - Henry de Valence - -#![cfg_attr( - feature = "nightly", - doc(include = "../../../../docs/ifma-notes.md") -)] - -pub mod field; - -pub mod edwards; - -pub mod constants; diff --git a/net/gurk-rs/files/vendor/curve25519-dalek/src/backend/vector/mod.rs b/net/gurk-rs/files/vendor/curve25519-dalek/src/backend/vector/mod.rs deleted file mode 100644 index 29a6f65..0000000 --- a/net/gurk-rs/files/vendor/curve25519-dalek/src/backend/vector/mod.rs +++ /dev/null @@ -1,43 +0,0 @@ -// -*- mode: rust; -*- -// -// This file is part of curve25519-dalek. -// Copyright (c) 2016-2021 isis lovecruft -// Copyright (c) 2016-2019 Henry de Valence -// See LICENSE for licensing information. -// -// Authors: -// - isis agora lovecruft -// - Henry de Valence - -// Conditionally include the notes if we're on nightly (so we can include docs at all). -#![cfg_attr( - feature = "nightly", - doc(include = "../../../docs/parallel-formulas.md") -)] - -#[cfg(not(any(target_feature = "avx2", target_feature = "avx512ifma", rustdoc)))] -compile_error!("simd_backend selected without target_feature=+avx2 or +avx512ifma"); - -#[cfg(any( - all(target_feature = "avx2", not(target_feature = "avx512ifma")), - rustdoc -))] -#[doc(cfg(all(target_feature = "avx2", not(target_feature = "avx512ifma"))))] -pub mod avx2; -#[cfg(any( - all(target_feature = "avx2", not(target_feature = "avx512ifma")), - rustdoc -))] -pub(crate) use self::avx2::{ - constants::BASEPOINT_ODD_LOOKUP_TABLE, edwards::CachedPoint, edwards::ExtendedPoint, -}; - -#[cfg(any(target_feature = "avx512ifma", rustdoc))] -#[doc(cfg(target_feature = "avx512ifma"))] -pub mod ifma; -#[cfg(target_feature = "avx512ifma")] -pub(crate) use self::ifma::{ - constants::BASEPOINT_ODD_LOOKUP_TABLE, edwards::CachedPoint, edwards::ExtendedPoint, -}; - -pub mod scalar_mul; diff --git a/net/gurk-rs/files/vendor/curve25519-dalek/src/backend/vector/scalar_mul/mod.rs b/net/gurk-rs/files/vendor/curve25519-dalek/src/backend/vector/scalar_mul/mod.rs deleted file mode 100644 index 36a7047..0000000 --- a/net/gurk-rs/files/vendor/curve25519-dalek/src/backend/vector/scalar_mul/mod.rs +++ /dev/null @@ -1,23 +0,0 @@ -// -*- mode: rust; -*- -// -// This file is part of curve25519-dalek. -// Copyright (c) 2016-2021 isis lovecruft -// Copyright (c) 2016-2019 Henry de Valence -// See LICENSE for licensing information. -// -// Authors: -// - isis agora lovecruft -// - Henry de Valence - -pub mod variable_base; - -pub mod vartime_double_base; - -#[cfg(feature = "alloc")] -pub mod straus; - -#[cfg(feature = "alloc")] -pub mod precomputed_straus; - -#[cfg(feature = "alloc")] -pub mod pippenger; diff --git a/net/gurk-rs/files/vendor/curve25519-dalek/src/backend/vector/scalar_mul/pippenger.rs b/net/gurk-rs/files/vendor/curve25519-dalek/src/backend/vector/scalar_mul/pippenger.rs deleted file mode 100644 index 7f9e241..0000000 --- a/net/gurk-rs/files/vendor/curve25519-dalek/src/backend/vector/scalar_mul/pippenger.rs +++ /dev/null @@ -1,164 +0,0 @@ -// -*- mode: rust; -*- -// -// This file is part of curve25519-dalek. -// Copyright (c) 2019 Oleg Andreev -// See LICENSE for licensing information. -// -// Authors: -// - Oleg Andreev - -#![allow(non_snake_case)] - -use core::borrow::Borrow; - -use backend::vector::{CachedPoint, ExtendedPoint}; -use edwards::EdwardsPoint; -use scalar::Scalar; -use traits::{Identity, VartimeMultiscalarMul}; - -#[allow(unused_imports)] -use prelude::*; - -/// Implements a version of Pippenger's algorithm. -/// -/// See the documentation in the serial `scalar_mul::pippenger` module for details. -pub struct Pippenger; - -#[cfg(any(feature = "alloc", feature = "std"))] -impl VartimeMultiscalarMul for Pippenger { - type Point = EdwardsPoint; - - fn optional_multiscalar_mul(scalars: I, points: J) -> Option - where - I: IntoIterator, - I::Item: Borrow, - J: IntoIterator>, - { - let mut scalars = scalars.into_iter(); - let size = scalars.by_ref().size_hint().0; - let w = if size < 500 { - 6 - } else if size < 800 { - 7 - } else { - 8 - }; - - let max_digit: usize = 1 << w; - let digits_count: usize = Scalar::to_radix_2w_size_hint(w); - let buckets_count: usize = max_digit / 2; // digits are signed+centered hence 2^w/2, excluding 0-th bucket - - // Collect optimized scalars and points in a buffer for repeated access - // (scanning the whole collection per each digit position). - let scalars = scalars - .into_iter() - .map(|s| s.borrow().to_radix_2w(w)); - - let points = points - .into_iter() - .map(|p| p.map(|P| CachedPoint::from(ExtendedPoint::from(P)))); - - let scalars_points = scalars - .zip(points) - .map(|(s, maybe_p)| maybe_p.map(|p| (s, p))) - .collect::>>()?; - - // Prepare 2^w/2 buckets. - // buckets[i] corresponds to a multiplication factor (i+1). - let mut buckets: Vec = (0..buckets_count) - .map(|_| ExtendedPoint::identity()) - .collect(); - - let mut columns = (0..digits_count).rev().map(|digit_index| { - // Clear the buckets when processing another digit. - for i in 0..buckets_count { - buckets[i] = ExtendedPoint::identity(); - } - - // Iterate over pairs of (point, scalar) - // and add/sub the point to the corresponding bucket. - // Note: if we add support for precomputed lookup tables, - // we'll be adding/subtractiong point premultiplied by `digits[i]` to buckets[0]. - for (digits, pt) in scalars_points.iter() { - // Widen digit so that we don't run into edge cases when w=8. - let digit = digits[digit_index] as i16; - if digit > 0 { - let b = (digit - 1) as usize; - buckets[b] = &buckets[b] + pt; - } else if digit < 0 { - let b = (-digit - 1) as usize; - buckets[b] = &buckets[b] - pt; - } - } - - // Add the buckets applying the multiplication factor to each bucket. - // The most efficient way to do that is to have a single sum with two running sums: - // an intermediate sum from last bucket to the first, and a sum of intermediate sums. - // - // For example, to add buckets 1*A, 2*B, 3*C we need to add these points: - // C - // C B - // C B A Sum = C + (C+B) + (C+B+A) - let mut buckets_intermediate_sum = buckets[buckets_count - 1]; - let mut buckets_sum = buckets[buckets_count - 1]; - for i in (0..(buckets_count - 1)).rev() { - buckets_intermediate_sum = - &buckets_intermediate_sum + &CachedPoint::from(buckets[i]); - buckets_sum = &buckets_sum + &CachedPoint::from(buckets_intermediate_sum); - } - - buckets_sum - }); - - // Take the high column as an initial value to avoid wasting time doubling the identity element in `fold()`. - // `unwrap()` always succeeds because we know we have more than zero digits. - let hi_column = columns.next().unwrap(); - - Some( - columns - .fold(hi_column, |total, p| { - &total.mul_by_pow_2(w as u32) + &CachedPoint::from(p) - }) - .into(), - ) - } -} - -#[cfg(test)] -mod test { - use super::*; - use constants; - use scalar::Scalar; - - #[test] - fn test_vartime_pippenger() { - // Reuse points across different tests - let mut n = 512; - let x = Scalar::from(2128506u64).invert(); - let y = Scalar::from(4443282u64).invert(); - let points: Vec<_> = (0..n) - .map(|i| constants::ED25519_BASEPOINT_POINT * Scalar::from(1 + i as u64)) - .collect(); - let scalars: Vec<_> = (0..n) - .map(|i| x + (Scalar::from(i as u64) * y)) // fast way to make ~random but deterministic scalars - .collect(); - - let premultiplied: Vec = scalars - .iter() - .zip(points.iter()) - .map(|(sc, pt)| sc * pt) - .collect(); - - while n > 0 { - let scalars = &scalars[0..n].to_vec(); - let points = &points[0..n].to_vec(); - let control: EdwardsPoint = premultiplied[0..n].iter().sum(); - - let subject = Pippenger::vartime_multiscalar_mul(scalars.clone(), points.clone()); - - assert_eq!(subject.compress(), control.compress()); - - n = n / 2; - } - } -} diff --git a/net/gurk-rs/files/vendor/curve25519-dalek/src/backend/vector/scalar_mul/precomputed_straus.rs b/net/gurk-rs/files/vendor/curve25519-dalek/src/backend/vector/scalar_mul/precomputed_straus.rs deleted file mode 100644 index 2c6fdf5..0000000 --- a/net/gurk-rs/files/vendor/curve25519-dalek/src/backend/vector/scalar_mul/precomputed_straus.rs +++ /dev/null @@ -1,107 +0,0 @@ -// -*- mode: rust; -*- -// -// This file is part of curve25519-dalek. -// Copyright (c) 2019 Henry de Valence. -// See LICENSE for licensing information. -// -// Authors: -// - Henry de Valence - -//! Precomputation for Straus's method. - -#![allow(non_snake_case)] - -use core::borrow::Borrow; - -use backend::vector::{CachedPoint, ExtendedPoint}; -use edwards::EdwardsPoint; -use scalar::Scalar; -use traits::Identity; -use traits::VartimePrecomputedMultiscalarMul; -use window::{NafLookupTable5, NafLookupTable8}; - -#[allow(unused_imports)] -use prelude::*; - - -pub struct VartimePrecomputedStraus { - static_lookup_tables: Vec>, -} - -impl VartimePrecomputedMultiscalarMul for VartimePrecomputedStraus { - type Point = EdwardsPoint; - - fn new(static_points: I) -> Self - where - I: IntoIterator, - I::Item: Borrow, - { - Self { - static_lookup_tables: static_points - .into_iter() - .map(|P| NafLookupTable8::::from(P.borrow())) - .collect(), - } - } - - fn optional_mixed_multiscalar_mul( - &self, - static_scalars: I, - dynamic_scalars: J, - dynamic_points: K, - ) -> Option - where - I: IntoIterator, - I::Item: Borrow, - J: IntoIterator, - J::Item: Borrow, - K: IntoIterator>, - { - let static_nafs = static_scalars - .into_iter() - .map(|c| c.borrow().non_adjacent_form(5)) - .collect::>(); - let dynamic_nafs: Vec<_> = dynamic_scalars - .into_iter() - .map(|c| c.borrow().non_adjacent_form(5)) - .collect::>(); - - let dynamic_lookup_tables = dynamic_points - .into_iter() - .map(|P_opt| P_opt.map(|P| NafLookupTable5::::from(&P))) - .collect::>>()?; - - let sp = self.static_lookup_tables.len(); - let dp = dynamic_lookup_tables.len(); - assert_eq!(sp, static_nafs.len()); - assert_eq!(dp, dynamic_nafs.len()); - - // We could save some doublings by looking for the highest - // nonzero NAF coefficient, but since we might have a lot of - // them to search, it's not clear it's worthwhile to check. - let mut R = ExtendedPoint::identity(); - for j in (0..256).rev() { - R = R.double(); - - for i in 0..dp { - let t_ij = dynamic_nafs[i][j]; - if t_ij > 0 { - R = &R + &dynamic_lookup_tables[i].select(t_ij as usize); - } else if t_ij < 0 { - R = &R - &dynamic_lookup_tables[i].select(-t_ij as usize); - } - } - - for i in 0..sp { - let t_ij = static_nafs[i][j]; - if t_ij > 0 { - R = &R + &self.static_lookup_tables[i].select(t_ij as usize); - } else if t_ij < 0 { - R = &R - &self.static_lookup_tables[i].select(-t_ij as usize); - } - } - } - - Some(R.into()) - } -} diff --git a/net/gurk-rs/files/vendor/curve25519-dalek/src/backend/vector/scalar_mul/straus.rs b/net/gurk-rs/files/vendor/curve25519-dalek/src/backend/vector/scalar_mul/straus.rs deleted file mode 100644 index b6c02f9..0000000 --- a/net/gurk-rs/files/vendor/curve25519-dalek/src/backend/vector/scalar_mul/straus.rs +++ /dev/null @@ -1,108 +0,0 @@ -// -*- mode: rust; -*- -// -// This file is part of curve25519-dalek. -// Copyright (c) 2016-2021 isis lovecruft -// Copyright (c) 2016-2019 Henry de Valence -// See LICENSE for licensing information. -// -// Authors: -// - isis agora lovecruft -// - Henry de Valence - -#![allow(non_snake_case)] - -use core::borrow::Borrow; - -use zeroize::Zeroizing; - -use backend::vector::{CachedPoint, ExtendedPoint}; -use edwards::EdwardsPoint; -use scalar::Scalar; -use window::{LookupTable, NafLookupTable5}; -use traits::{Identity, MultiscalarMul, VartimeMultiscalarMul}; - -#[allow(unused_imports)] -use prelude::*; - -/// Multiscalar multiplication using interleaved window / Straus' -/// method. See the `Straus` struct in the serial backend for more -/// details. -/// -/// This exists as a seperate implementation from that one because the -/// AVX2 code uses different curve models (it does not pass between -/// multiple models during scalar mul), and it has to convert the -/// point representation on the fly. -pub struct Straus {} - -impl MultiscalarMul for Straus { - type Point = EdwardsPoint; - - fn multiscalar_mul(scalars: I, points: J) -> EdwardsPoint - where - I: IntoIterator, - I::Item: Borrow, - J: IntoIterator, - J::Item: Borrow, - { - // Construct a lookup table of [P,2P,3P,4P,5P,6P,7P,8P] - // for each input point P - let lookup_tables: Vec<_> = points - .into_iter() - .map(|point| LookupTable::::from(point.borrow())) - .collect(); - - let scalar_digits_vec: Vec<_> = scalars - .into_iter() - .map(|s| s.borrow().to_radix_16()) - .collect(); - // Pass ownership to a `Zeroizing` wrapper - let scalar_digits = Zeroizing::new(scalar_digits_vec); - - let mut Q = ExtendedPoint::identity(); - for j in (0..64).rev() { - Q = Q.mul_by_pow_2(4); - let it = scalar_digits.iter().zip(lookup_tables.iter()); - for (s_i, lookup_table_i) in it { - // Q = Q + s_{i,j} * P_i - Q = &Q + &lookup_table_i.select(s_i[j]); - } - } - Q.into() - } -} - -impl VartimeMultiscalarMul for Straus { - type Point = EdwardsPoint; - - fn optional_multiscalar_mul(scalars: I, points: J) -> Option - where - I: IntoIterator, - I::Item: Borrow, - J: IntoIterator>, - { - let nafs: Vec<_> = scalars - .into_iter() - .map(|c| c.borrow().non_adjacent_form(5)) - .collect(); - let lookup_tables: Vec<_> = points - .into_iter() - .map(|P_opt| P_opt.map(|P| NafLookupTable5::::from(&P))) - .collect::>>()?; - - let mut Q = ExtendedPoint::identity(); - - for i in (0..256).rev() { - Q = Q.double(); - - for (naf, lookup_table) in nafs.iter().zip(lookup_tables.iter()) { - if naf[i] > 0 { - Q = &Q + &lookup_table.select(naf[i] as usize); - } else if naf[i] < 0 { - Q = &Q - &lookup_table.select(-naf[i] as usize); - } - } - } - - Some(Q.into()) - } -} diff --git a/net/gurk-rs/files/vendor/curve25519-dalek/src/backend/vector/scalar_mul/variable_base.rs b/net/gurk-rs/files/vendor/curve25519-dalek/src/backend/vector/scalar_mul/variable_base.rs deleted file mode 100644 index f53c4a0..0000000 --- a/net/gurk-rs/files/vendor/curve25519-dalek/src/backend/vector/scalar_mul/variable_base.rs +++ /dev/null @@ -1,32 +0,0 @@ -#![allow(non_snake_case)] - -use backend::vector::{CachedPoint, ExtendedPoint}; -use edwards::EdwardsPoint; -use scalar::Scalar; -use traits::Identity; -use window::LookupTable; - -/// Perform constant-time, variable-base scalar multiplication. -pub fn mul(point: &EdwardsPoint, scalar: &Scalar) -> EdwardsPoint { - // Construct a lookup table of [P,2P,3P,4P,5P,6P,7P,8P] - let lookup_table = LookupTable::::from(point); - // Setting s = scalar, compute - // - // s = s_0 + s_1*16^1 + ... + s_63*16^63, - // - // with `-8 ≤ s_i < 8` for `0 ≤ i < 63` and `-8 ≤ s_63 ≤ 8`. - let scalar_digits = scalar.to_radix_16(); - // Compute s*P as - // - // s*P = P*(s_0 + s_1*16^1 + s_2*16^2 + ... + s_63*16^63) - // s*P = P*s_0 + P*s_1*16^1 + P*s_2*16^2 + ... + P*s_63*16^63 - // s*P = P*s_0 + 16*(P*s_1 + 16*(P*s_2 + 16*( ... + P*s_63)...)) - // - // We sum right-to-left. - let mut Q = ExtendedPoint::identity(); - for i in (0..64).rev() { - Q = Q.mul_by_pow_2(4); - Q = &Q + &lookup_table.select(scalar_digits[i]); - } - Q.into() -} diff --git a/net/gurk-rs/files/vendor/curve25519-dalek/src/backend/vector/scalar_mul/vartime_double_base.rs b/net/gurk-rs/files/vendor/curve25519-dalek/src/backend/vector/scalar_mul/vartime_double_base.rs deleted file mode 100644 index 3f7cc3e..0000000 --- a/net/gurk-rs/files/vendor/curve25519-dalek/src/backend/vector/scalar_mul/vartime_double_base.rs +++ /dev/null @@ -1,62 +0,0 @@ -// -*- mode: rust; -*- -// -// This file is part of curve25519-dalek. -// Copyright (c) 2016-2021 isis lovecruft -// Copyright (c) 2016-2019 Henry de Valence -// See LICENSE for licensing information. -// -// Authors: -// - isis agora lovecruft -// - Henry de Valence - -#![allow(non_snake_case)] - -use backend::vector::BASEPOINT_ODD_LOOKUP_TABLE; -use backend::vector::{CachedPoint, ExtendedPoint}; -use edwards::EdwardsPoint; -use scalar::Scalar; -use traits::Identity; -use window::NafLookupTable5; - -/// Compute \\(aA + bB\\) in variable time, where \\(B\\) is the Ed25519 basepoint. -pub fn mul(a: &Scalar, A: &EdwardsPoint, b: &Scalar) -> EdwardsPoint { - let a_naf = a.non_adjacent_form(5); - let b_naf = b.non_adjacent_form(8); - - // Find starting index - let mut i: usize = 255; - for j in (0..256).rev() { - i = j; - if a_naf[i] != 0 || b_naf[i] != 0 { - break; - } - } - - let table_A = NafLookupTable5::::from(A); - let table_B = &BASEPOINT_ODD_LOOKUP_TABLE; - - let mut Q = ExtendedPoint::identity(); - - loop { - Q = Q.double(); - - if a_naf[i] > 0 { - Q = &Q + &table_A.select(a_naf[i] as usize); - } else if a_naf[i] < 0 { - Q = &Q - &table_A.select(-a_naf[i] as usize); - } - - if b_naf[i] > 0 { - Q = &Q + &table_B.select(b_naf[i] as usize); - } else if b_naf[i] < 0 { - Q = &Q - &table_B.select(-b_naf[i] as usize); - } - - if i == 0 { - break; - } - i -= 1; - } - - Q.into() -} diff --git a/net/gurk-rs/files/vendor/curve25519-dalek/src/constants.rs b/net/gurk-rs/files/vendor/curve25519-dalek/src/constants.rs deleted file mode 100644 index 19c46e5..0000000 --- a/net/gurk-rs/files/vendor/curve25519-dalek/src/constants.rs +++ /dev/null @@ -1,181 +0,0 @@ -// -*- mode: rust; -*- -// -// This file is part of curve25519-dalek. -// Copyright (c) 2016-2021 isis lovecruft -// Copyright (c) 2016-2019 Henry de Valence -// See LICENSE for licensing information. -// -// Authors: -// - isis agora lovecruft -// - Henry de Valence - -//! Various constants, such as the Ristretto and Ed25519 basepoints. -//! -//! Most of the constants are given with -//! `LONG_DESCRIPTIVE_UPPER_CASE_NAMES`, but they can be brought into -//! scope using a `let` binding: -//! -//! ``` -//! use curve25519_dalek::constants; -//! use curve25519_dalek::traits::IsIdentity; -//! -//! let B = &constants::RISTRETTO_BASEPOINT_TABLE; -//! let l = &constants::BASEPOINT_ORDER; -//! -//! let A = l * B; -//! assert!(A.is_identity()); -//! ``` - -#![allow(non_snake_case)] - -use edwards::CompressedEdwardsY; -use ristretto::RistrettoPoint; -use ristretto::CompressedRistretto; -use montgomery::MontgomeryPoint; -use scalar::Scalar; - -#[cfg(feature = "fiat_u32_backend")] -pub use backend::serial::fiat_u32::constants::*; -#[cfg(feature = "fiat_u64_backend")] -pub use backend::serial::fiat_u64::constants::*; -#[cfg(feature = "u64_backend")] -pub use backend::serial::u64::constants::*; -#[cfg(feature = "u32_backend")] -pub use backend::serial::u32::constants::*; - -/// The Ed25519 basepoint, in `CompressedEdwardsY` format. -/// -/// This is the little-endian byte encoding of \\( 4/5 \pmod p \\), -/// which is the \\(y\\)-coordinate of the Ed25519 basepoint. -/// -/// The sign bit is 0 since the basepoint has \\(x\\) chosen to be positive. -pub const ED25519_BASEPOINT_COMPRESSED: CompressedEdwardsY = - CompressedEdwardsY([0x58, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, - 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, - 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, - 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66]); - -/// The X25519 basepoint, in `MontgomeryPoint` format. -pub const X25519_BASEPOINT: MontgomeryPoint = - MontgomeryPoint([0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]); - -/// The Ristretto basepoint, in `CompressedRistretto` format. -pub const RISTRETTO_BASEPOINT_COMPRESSED: CompressedRistretto = - CompressedRistretto([0xe2, 0xf2, 0xae, 0x0a, 0x6a, 0xbc, 0x4e, 0x71, - 0xa8, 0x84, 0xa9, 0x61, 0xc5, 0x00, 0x51, 0x5f, - 0x58, 0xe3, 0x0b, 0x6a, 0xa5, 0x82, 0xdd, 0x8d, - 0xb6, 0xa6, 0x59, 0x45, 0xe0, 0x8d, 0x2d, 0x76]); - -/// The Ristretto basepoint, as a `RistrettoPoint`. -/// -/// This is called `_POINT` to distinguish it from `_TABLE`, which -/// provides fast scalar multiplication. -pub const RISTRETTO_BASEPOINT_POINT: RistrettoPoint = RistrettoPoint(ED25519_BASEPOINT_POINT); - -/// `BASEPOINT_ORDER` is the order of the Ristretto group and of the Ed25519 basepoint, i.e., -/// $$ -/// \ell = 2^\{252\} + 27742317777372353535851937790883648493. -/// $$ -pub const BASEPOINT_ORDER: Scalar = Scalar{ - bytes: [ - 0xed, 0xd3, 0xf5, 0x5c, 0x1a, 0x63, 0x12, 0x58, - 0xd6, 0x9c, 0xf7, 0xa2, 0xde, 0xf9, 0xde, 0x14, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, - ], -}; - -use ristretto::RistrettoBasepointTable; -/// The Ristretto basepoint, as a `RistrettoBasepointTable` for scalar multiplication. -pub const RISTRETTO_BASEPOINT_TABLE: RistrettoBasepointTable - = RistrettoBasepointTable(ED25519_BASEPOINT_TABLE); - -#[cfg(test)] -mod test { - use field::FieldElement; - use traits::{IsIdentity, ValidityCheck}; - use constants; - - #[test] - fn test_eight_torsion() { - for i in 0..8 { - let Q = constants::EIGHT_TORSION[i].mul_by_pow_2(3); - assert!(Q.is_valid()); - assert!(Q.is_identity()); - } - } - - #[test] - fn test_four_torsion() { - for i in (0..8).filter(|i| i % 2 == 0) { - let Q = constants::EIGHT_TORSION[i].mul_by_pow_2(2); - assert!(Q.is_valid()); - assert!(Q.is_identity()); - } - } - - #[test] - fn test_two_torsion() { - for i in (0..8).filter(|i| i % 4 == 0) { - let Q = constants::EIGHT_TORSION[i].mul_by_pow_2(1); - assert!(Q.is_valid()); - assert!(Q.is_identity()); - } - } - - /// Test that SQRT_M1 is the positive square root of -1 - #[test] - fn test_sqrt_minus_one() { - let minus_one = FieldElement::minus_one(); - let sqrt_m1_sq = &constants::SQRT_M1 * &constants::SQRT_M1; - assert_eq!(minus_one, sqrt_m1_sq); - assert_eq!(constants::SQRT_M1.is_negative().unwrap_u8(), 0); - } - - #[test] - fn test_sqrt_constants_sign() { - let minus_one = FieldElement::minus_one(); - let (was_nonzero_square, invsqrt_m1) = minus_one.invsqrt(); - assert_eq!(was_nonzero_square.unwrap_u8(), 1u8); - let sign_test_sqrt = &invsqrt_m1 * &constants::SQRT_M1; - assert_eq!(sign_test_sqrt, minus_one); - } - - /// Test that d = -121665/121666 - #[test] - #[cfg(feature = "u32_backend")] - fn test_d_vs_ratio() { - use backend::serial::u32::field::FieldElement2625; - let a = -&FieldElement2625([121665,0,0,0,0,0,0,0,0,0]); - let b = FieldElement2625([121666,0,0,0,0,0,0,0,0,0]); - let d = &a * &b.invert(); - let d2 = &d + &d; - assert_eq!(d, constants::EDWARDS_D); - assert_eq!(d2, constants::EDWARDS_D2); - } - - /// Test that d = -121665/121666 - #[test] - #[cfg(feature = "u64_backend")] - fn test_d_vs_ratio() { - use backend::serial::u64::field::FieldElement51; - let a = -&FieldElement51([121665,0,0,0,0]); - let b = FieldElement51([121666,0,0,0,0]); - let d = &a * &b.invert(); - let d2 = &d + &d; - assert_eq!(d, constants::EDWARDS_D); - assert_eq!(d2, constants::EDWARDS_D2); - } - - #[test] - fn test_sqrt_ad_minus_one() { - let a = FieldElement::minus_one(); - let ad_minus_one = &(&a * &constants::EDWARDS_D) + &a; - let should_be_ad_minus_one = constants::SQRT_AD_MINUS_ONE.square(); - assert_eq!(should_be_ad_minus_one, ad_minus_one); - } - -} diff --git a/net/gurk-rs/files/vendor/curve25519-dalek/src/edwards.rs b/net/gurk-rs/files/vendor/curve25519-dalek/src/edwards.rs deleted file mode 100644 index 7c97ca4..0000000 --- a/net/gurk-rs/files/vendor/curve25519-dalek/src/edwards.rs +++ /dev/null @@ -1,1699 +0,0 @@ -// -*- mode: rust; -*- -// -// This file is part of curve25519-dalek. -// Copyright (c) 2016-2021 isis lovecruft -// Copyright (c) 2016-2020 Henry de Valence -// See LICENSE for licensing information. -// -// Authors: -// - isis agora lovecruft -// - Henry de Valence - -//! Group operations for Curve25519, in Edwards form. -//! -//! ## Encoding and Decoding -//! -//! Encoding is done by converting to and from a `CompressedEdwardsY` -//! struct, which is a typed wrapper around `[u8; 32]`. -//! -//! ## Equality Testing -//! -//! The `EdwardsPoint` struct implements the `subtle::ConstantTimeEq` -//! trait for constant-time equality checking, and the Rust `Eq` trait -//! for variable-time equality checking. -//! -//! ## Cofactor-related functions -//! -//! The order of the group of points on the curve \\(\mathcal E\\) -//! is \\(|\mathcal E| = 8\ell \\), so its structure is \\( \mathcal -//! E = \mathcal E[8] \times \mathcal E[\ell]\\). The torsion -//! subgroup \\( \mathcal E[8] \\) consists of eight points of small -//! order. Technically, all of \\(\mathcal E\\) is torsion, but we -//! use the word only to refer to the small \\(\mathcal E[8]\\) part, not -//! the large prime-order \\(\mathcal E[\ell]\\) part. -//! -//! To test if a point is in \\( \mathcal E[8] \\), use -//! `EdwardsPoint::is_small_order()`. -//! -//! To test if a point is in \\( \mathcal E[\ell] \\), use -//! `EdwardsPoint::is_torsion_free()`. -//! -//! To multiply by the cofactor, use `EdwardsPoint::mul_by_cofactor()`. -//! -//! To avoid dealing with cofactors entirely, consider using Ristretto. -//! -//! ## Scalars -//! -//! Scalars are represented by the `Scalar` struct. To construct a scalar with a specific bit -//! pattern, see `Scalar::from_bits()`. -//! -//! ## Scalar Multiplication -//! -//! Scalar multiplication on Edwards points is provided by: -//! -//! * the `*` operator between a `Scalar` and a `EdwardsPoint`, which -//! performs constant-time variable-base scalar multiplication; -//! -//! * the `*` operator between a `Scalar` and a -//! `EdwardsBasepointTable`, which performs constant-time fixed-base -//! scalar multiplication; -//! -//! * an implementation of the -//! [`MultiscalarMul`](../traits/trait.MultiscalarMul.html) trait for -//! constant-time variable-base multiscalar multiplication; -//! -//! * an implementation of the -//! [`VartimeMultiscalarMul`](../traits/trait.VartimeMultiscalarMul.html) -//! trait for variable-time variable-base multiscalar multiplication; -//! -//! ## Implementation -//! -//! The Edwards arithmetic is implemented using the “extended twisted -//! coordinates” of Hisil, Wong, Carter, and Dawson, and the -//! corresponding complete formulas. For more details, -//! see the [`curve_models` submodule][curve_models] -//! of the internal documentation. -//! -//! ## Validity Checking -//! -//! There is no function for checking whether a point is valid. -//! Instead, the `EdwardsPoint` struct is guaranteed to hold a valid -//! point on the curve. -//! -//! We use the Rust type system to make invalid points -//! unrepresentable: `EdwardsPoint` objects can only be created via -//! successful decompression of a compressed point, or else by -//! operations on other (valid) `EdwardsPoint`s. -//! -//! [curve_models]: https://doc-internal.dalek.rs/curve25519_dalek/backend/serial/curve_models/index.html - -// We allow non snake_case names because coordinates in projective space are -// traditionally denoted by the capitalisation of their respective -// counterparts in affine space. Yeah, you heard me, rustc, I'm gonna have my -// affine and projective cakes and eat both of them too. -#![allow(non_snake_case)] - -use core::borrow::Borrow; -use core::fmt::Debug; -use core::iter::Iterator; -use core::iter::Sum; -use core::ops::{Add, Neg, Sub}; -use core::ops::{AddAssign, SubAssign}; -use core::ops::{Mul, MulAssign}; - -use subtle::Choice; -use subtle::ConditionallyNegatable; -use subtle::ConditionallySelectable; -use subtle::ConstantTimeEq; - -use constants; - -use field::FieldElement; -use scalar::Scalar; - -use montgomery::MontgomeryPoint; - -use backend::serial::curve_models::AffineNielsPoint; -use backend::serial::curve_models::CompletedPoint; -use backend::serial::curve_models::ProjectiveNielsPoint; -use backend::serial::curve_models::ProjectivePoint; - -use window::LookupTable; -use window::LookupTableRadix16; -use window::LookupTableRadix32; -use window::LookupTableRadix64; -use window::LookupTableRadix128; -use window::LookupTableRadix256; - -#[allow(unused_imports)] -use prelude::*; - -use traits::BasepointTable; -use traits::ValidityCheck; -use traits::{Identity, IsIdentity}; - -#[cfg(any(feature = "alloc", feature = "std"))] -use traits::MultiscalarMul; -#[cfg(any(feature = "alloc", feature = "std"))] -use traits::{VartimeMultiscalarMul, VartimePrecomputedMultiscalarMul}; - -#[cfg(not(all( - feature = "simd_backend", - any(target_feature = "avx2", target_feature = "avx512ifma") -)))] -use backend::serial::scalar_mul; -#[cfg(all( - feature = "simd_backend", - any(target_feature = "avx2", target_feature = "avx512ifma") -))] -use backend::vector::scalar_mul; - -// ------------------------------------------------------------------------ -// Compressed points -// ------------------------------------------------------------------------ - -/// In "Edwards y" / "Ed25519" format, the curve point \\((x,y)\\) is -/// determined by the \\(y\\)-coordinate and the sign of \\(x\\). -/// -/// The first 255 bits of a `CompressedEdwardsY` represent the -/// \\(y\\)-coordinate. The high bit of the 32nd byte gives the sign of \\(x\\). -#[derive(Copy, Clone, Eq, PartialEq, Hash)] -pub struct CompressedEdwardsY(pub [u8; 32]); - -impl ConstantTimeEq for CompressedEdwardsY { - fn ct_eq(&self, other: &CompressedEdwardsY) -> Choice { - self.as_bytes().ct_eq(other.as_bytes()) - } -} - -impl Debug for CompressedEdwardsY { - fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { - write!(f, "CompressedEdwardsY: {:?}", self.as_bytes()) - } -} - -impl CompressedEdwardsY { - /// View this `CompressedEdwardsY` as an array of bytes. - pub fn as_bytes(&self) -> &[u8; 32] { - &self.0 - } - - /// Copy this `CompressedEdwardsY` to an array of bytes. - pub fn to_bytes(&self) -> [u8; 32] { - self.0 - } - - /// Attempt to decompress to an `EdwardsPoint`. - /// - /// Returns `None` if the input is not the \\(y\\)-coordinate of a - /// curve point. - pub fn decompress(&self) -> Option { - let Y = FieldElement::from_bytes(self.as_bytes()); - let Z = FieldElement::one(); - let YY = Y.square(); - let u = &YY - &Z; // u = y²-1 - let v = &(&YY * &constants::EDWARDS_D) + &Z; // v = dy²+1 - let (is_valid_y_coord, mut X) = FieldElement::sqrt_ratio_i(&u, &v); - - if is_valid_y_coord.unwrap_u8() != 1u8 { return None; } - - // FieldElement::sqrt_ratio_i always returns the nonnegative square root, - // so we negate according to the supplied sign bit. - let compressed_sign_bit = Choice::from(self.as_bytes()[31] >> 7); - X.conditional_negate(compressed_sign_bit); - - Some(EdwardsPoint{ X, Y, Z, T: &X * &Y }) - } -} - -// ------------------------------------------------------------------------ -// Serde support -// ------------------------------------------------------------------------ -// Serializes to and from `EdwardsPoint` directly, doing compression -// and decompression internally. This means that users can create -// structs containing `EdwardsPoint`s and use Serde's derived -// serializers to serialize those structures. - -#[cfg(feature = "serde")] -use serde::{self, Serialize, Deserialize, Serializer, Deserializer}; -#[cfg(feature = "serde")] -use serde::de::Visitor; - -#[cfg(feature = "serde")] -impl Serialize for EdwardsPoint { - fn serialize(&self, serializer: S) -> Result - where S: Serializer - { - use serde::ser::SerializeTuple; - let mut tup = serializer.serialize_tuple(32)?; - for byte in self.compress().as_bytes().iter() { - tup.serialize_element(byte)?; - } - tup.end() - } -} - -#[cfg(feature = "serde")] -impl Serialize for CompressedEdwardsY { - fn serialize(&self, serializer: S) -> Result - where S: Serializer - { - use serde::ser::SerializeTuple; - let mut tup = serializer.serialize_tuple(32)?; - for byte in self.as_bytes().iter() { - tup.serialize_element(byte)?; - } - tup.end() - } -} - -#[cfg(feature = "serde")] -impl<'de> Deserialize<'de> for EdwardsPoint { - fn deserialize(deserializer: D) -> Result - where D: Deserializer<'de> - { - struct EdwardsPointVisitor; - - impl<'de> Visitor<'de> for EdwardsPointVisitor { - type Value = EdwardsPoint; - - fn expecting(&self, formatter: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { - formatter.write_str("a valid point in Edwards y + sign format") - } - - fn visit_seq(self, mut seq: A) -> Result - where A: serde::de::SeqAccess<'de> - { - let mut bytes = [0u8; 32]; - for i in 0..32 { - bytes[i] = seq.next_element()? - .ok_or(serde::de::Error::invalid_length(i, &"expected 32 bytes"))?; - } - CompressedEdwardsY(bytes) - .decompress() - .ok_or(serde::de::Error::custom("decompression failed")) - } - } - - deserializer.deserialize_tuple(32, EdwardsPointVisitor) - } -} - -#[cfg(feature = "serde")] -impl<'de> Deserialize<'de> for CompressedEdwardsY { - fn deserialize(deserializer: D) -> Result - where D: Deserializer<'de> - { - struct CompressedEdwardsYVisitor; - - impl<'de> Visitor<'de> for CompressedEdwardsYVisitor { - type Value = CompressedEdwardsY; - - fn expecting(&self, formatter: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { - formatter.write_str("32 bytes of data") - } - - fn visit_seq(self, mut seq: A) -> Result - where A: serde::de::SeqAccess<'de> - { - let mut bytes = [0u8; 32]; - for i in 0..32 { - bytes[i] = seq.next_element()? - .ok_or(serde::de::Error::invalid_length(i, &"expected 32 bytes"))?; - } - Ok(CompressedEdwardsY(bytes)) - } - } - - deserializer.deserialize_tuple(32, CompressedEdwardsYVisitor) - } -} - -// ------------------------------------------------------------------------ -// Internal point representations -// ------------------------------------------------------------------------ - -/// An `EdwardsPoint` represents a point on the Edwards form of Curve25519. -#[derive(Copy, Clone)] -#[allow(missing_docs)] -pub struct EdwardsPoint { - pub(crate) X: FieldElement, - pub(crate) Y: FieldElement, - pub(crate) Z: FieldElement, - pub(crate) T: FieldElement, -} - -// ------------------------------------------------------------------------ -// Constructors -// ------------------------------------------------------------------------ - -impl Identity for CompressedEdwardsY { - fn identity() -> CompressedEdwardsY { - CompressedEdwardsY([1, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0]) - } -} - -impl Default for CompressedEdwardsY { - fn default() -> CompressedEdwardsY { - CompressedEdwardsY::identity() - } -} - -impl CompressedEdwardsY { - /// Construct a `CompressedEdwardsY` from a slice of bytes. - /// - /// # Panics - /// - /// If the input `bytes` slice does not have a length of 32. - pub fn from_slice(bytes: &[u8]) -> CompressedEdwardsY { - let mut tmp = [0u8; 32]; - - tmp.copy_from_slice(bytes); - - CompressedEdwardsY(tmp) - } -} - -impl Identity for EdwardsPoint { - fn identity() -> EdwardsPoint { - EdwardsPoint { - X: FieldElement::zero(), - Y: FieldElement::one(), - Z: FieldElement::one(), - T: FieldElement::zero(), - } - } -} - -impl Default for EdwardsPoint { - fn default() -> EdwardsPoint { - EdwardsPoint::identity() - } -} - -// ------------------------------------------------------------------------ -// Validity checks (for debugging, not CT) -// ------------------------------------------------------------------------ - -impl ValidityCheck for EdwardsPoint { - fn is_valid(&self) -> bool { - let point_on_curve = self.to_projective().is_valid(); - let on_segre_image = (&self.X * &self.Y) == (&self.Z * &self.T); - - point_on_curve && on_segre_image - } -} - -// ------------------------------------------------------------------------ -// Constant-time assignment -// ------------------------------------------------------------------------ - -impl ConditionallySelectable for EdwardsPoint { - fn conditional_select(a: &EdwardsPoint, b: &EdwardsPoint, choice: Choice) -> EdwardsPoint { - EdwardsPoint { - X: FieldElement::conditional_select(&a.X, &b.X, choice), - Y: FieldElement::conditional_select(&a.Y, &b.Y, choice), - Z: FieldElement::conditional_select(&a.Z, &b.Z, choice), - T: FieldElement::conditional_select(&a.T, &b.T, choice), - } - } -} - -// ------------------------------------------------------------------------ -// Equality -// ------------------------------------------------------------------------ - -impl ConstantTimeEq for EdwardsPoint { - fn ct_eq(&self, other: &EdwardsPoint) -> Choice { - // We would like to check that the point (X/Z, Y/Z) is equal to - // the point (X'/Z', Y'/Z') without converting into affine - // coordinates (x, y) and (x', y'), which requires two inversions. - // We have that X = xZ and X' = x'Z'. Thus, x = x' is equivalent to - // (xZ)Z' = (x'Z')Z, and similarly for the y-coordinate. - - (&self.X * &other.Z).ct_eq(&(&other.X * &self.Z)) - & (&self.Y * &other.Z).ct_eq(&(&other.Y * &self.Z)) - } -} - -impl PartialEq for EdwardsPoint { - fn eq(&self, other: &EdwardsPoint) -> bool { - self.ct_eq(other).unwrap_u8() == 1u8 - } -} - -impl Eq for EdwardsPoint {} - -// ------------------------------------------------------------------------ -// Point conversions -// ------------------------------------------------------------------------ - -impl EdwardsPoint { - /// Convert to a ProjectiveNielsPoint - pub(crate) fn to_projective_niels(&self) -> ProjectiveNielsPoint { - ProjectiveNielsPoint{ - Y_plus_X: &self.Y + &self.X, - Y_minus_X: &self.Y - &self.X, - Z: self.Z, - T2d: &self.T * &constants::EDWARDS_D2, - } - } - - /// Convert the representation of this point from extended - /// coordinates to projective coordinates. - /// - /// Free. - pub(crate) fn to_projective(&self) -> ProjectivePoint { - ProjectivePoint{ - X: self.X, - Y: self.Y, - Z: self.Z, - } - } - - /// Dehomogenize to a AffineNielsPoint. - /// Mainly for testing. - pub(crate) fn to_affine_niels(&self) -> AffineNielsPoint { - let recip = self.Z.invert(); - let x = &self.X * &recip; - let y = &self.Y * &recip; - let xy2d = &(&x * &y) * &constants::EDWARDS_D2; - AffineNielsPoint{ - y_plus_x: &y + &x, - y_minus_x: &y - &x, - xy2d - } - } - - /// Convert this `EdwardsPoint` on the Edwards model to the - /// corresponding `MontgomeryPoint` on the Montgomery model. - /// - /// This function has one exceptional case; the identity point of - /// the Edwards curve is sent to the 2-torsion point \\((0,0)\\) - /// on the Montgomery curve. - /// - /// Note that this is a one-way conversion, since the Montgomery - /// model does not retain sign information. - pub fn to_montgomery(&self) -> MontgomeryPoint { - // We have u = (1+y)/(1-y) = (Z+Y)/(Z-Y). - // - // The denominator is zero only when y=1, the identity point of - // the Edwards curve. Since 0.invert() = 0, in this case we - // compute the 2-torsion point (0,0). - let U = &self.Z + &self.Y; - let W = &self.Z - &self.Y; - let u = &U * &W.invert(); - MontgomeryPoint(u.to_bytes()) - } - - /// Compress this point to `CompressedEdwardsY` format. - pub fn compress(&self) -> CompressedEdwardsY { - let recip = self.Z.invert(); - let x = &self.X * &recip; - let y = &self.Y * &recip; - let mut s: [u8; 32]; - - s = y.to_bytes(); - s[31] ^= x.is_negative().unwrap_u8() << 7; - CompressedEdwardsY(s) - } -} - -// ------------------------------------------------------------------------ -// Doubling -// ------------------------------------------------------------------------ - -impl EdwardsPoint { - /// Add this point to itself. - pub(crate) fn double(&self) -> EdwardsPoint { - self.to_projective().double().to_extended() - } -} - -// ------------------------------------------------------------------------ -// Addition and Subtraction -// ------------------------------------------------------------------------ - -impl<'a, 'b> Add<&'b EdwardsPoint> for &'a EdwardsPoint { - type Output = EdwardsPoint; - fn add(self, other: &'b EdwardsPoint) -> EdwardsPoint { - (self + &other.to_projective_niels()).to_extended() - } -} - -define_add_variants!(LHS = EdwardsPoint, RHS = EdwardsPoint, Output = EdwardsPoint); - -impl<'b> AddAssign<&'b EdwardsPoint> for EdwardsPoint { - fn add_assign(&mut self, _rhs: &'b EdwardsPoint) { - *self = (self as &EdwardsPoint) + _rhs; - } -} - -define_add_assign_variants!(LHS = EdwardsPoint, RHS = EdwardsPoint); - -impl<'a, 'b> Sub<&'b EdwardsPoint> for &'a EdwardsPoint { - type Output = EdwardsPoint; - fn sub(self, other: &'b EdwardsPoint) -> EdwardsPoint { - (self - &other.to_projective_niels()).to_extended() - } -} - -define_sub_variants!(LHS = EdwardsPoint, RHS = EdwardsPoint, Output = EdwardsPoint); - -impl<'b> SubAssign<&'b EdwardsPoint> for EdwardsPoint { - fn sub_assign(&mut self, _rhs: &'b EdwardsPoint) { - *self = (self as &EdwardsPoint) - _rhs; - } -} - -define_sub_assign_variants!(LHS = EdwardsPoint, RHS = EdwardsPoint); - -impl Sum for EdwardsPoint -where - T: Borrow -{ - fn sum(iter: I) -> Self - where - I: Iterator - { - iter.fold(EdwardsPoint::identity(), |acc, item| acc + item.borrow()) - } -} - - -// ------------------------------------------------------------------------ -// Negation -// ------------------------------------------------------------------------ - -impl<'a> Neg for &'a EdwardsPoint { - type Output = EdwardsPoint; - - fn neg(self) -> EdwardsPoint { - EdwardsPoint{ - X: -(&self.X), - Y: self.Y, - Z: self.Z, - T: -(&self.T), - } - } -} - -impl Neg for EdwardsPoint { - type Output = EdwardsPoint; - - fn neg(self) -> EdwardsPoint { - -&self - } -} - -// ------------------------------------------------------------------------ -// Scalar multiplication -// ------------------------------------------------------------------------ - -impl<'b> MulAssign<&'b Scalar> for EdwardsPoint { - fn mul_assign(&mut self, scalar: &'b Scalar) { - let result = (self as &EdwardsPoint) * scalar; - *self = result; - } -} - -define_mul_assign_variants!(LHS = EdwardsPoint, RHS = Scalar); - -define_mul_variants!(LHS = EdwardsPoint, RHS = Scalar, Output = EdwardsPoint); -define_mul_variants!(LHS = Scalar, RHS = EdwardsPoint, Output = EdwardsPoint); - -impl<'a, 'b> Mul<&'b Scalar> for &'a EdwardsPoint { - type Output = EdwardsPoint; - /// Scalar multiplication: compute `scalar * self`. - /// - /// For scalar multiplication of a basepoint, - /// `EdwardsBasepointTable` is approximately 4x faster. - fn mul(self, scalar: &'b Scalar) -> EdwardsPoint { - scalar_mul::variable_base::mul(self, scalar) - } -} - -impl<'a, 'b> Mul<&'b EdwardsPoint> for &'a Scalar { - type Output = EdwardsPoint; - - /// Scalar multiplication: compute `scalar * self`. - /// - /// For scalar multiplication of a basepoint, - /// `EdwardsBasepointTable` is approximately 4x faster. - fn mul(self, point: &'b EdwardsPoint) -> EdwardsPoint { - point * self - } -} - -// ------------------------------------------------------------------------ -// Multiscalar Multiplication impls -// ------------------------------------------------------------------------ - -// These use the iterator's size hint and the target settings to -// forward to a specific backend implementation. - -#[cfg(feature = "alloc")] -impl MultiscalarMul for EdwardsPoint { - type Point = EdwardsPoint; - - fn multiscalar_mul(scalars: I, points: J) -> EdwardsPoint - where - I: IntoIterator, - I::Item: Borrow, - J: IntoIterator, - J::Item: Borrow, - { - // Sanity-check lengths of input iterators - let mut scalars = scalars.into_iter(); - let mut points = points.into_iter(); - - // Lower and upper bounds on iterators - let (s_lo, s_hi) = scalars.by_ref().size_hint(); - let (p_lo, p_hi) = points.by_ref().size_hint(); - - // They should all be equal - assert_eq!(s_lo, p_lo); - assert_eq!(s_hi, Some(s_lo)); - assert_eq!(p_hi, Some(p_lo)); - - // Now we know there's a single size. When we do - // size-dependent algorithm dispatch, use this as the hint. - let _size = s_lo; - - scalar_mul::straus::Straus::multiscalar_mul(scalars, points) - } -} - -#[cfg(feature = "alloc")] -impl VartimeMultiscalarMul for EdwardsPoint { - type Point = EdwardsPoint; - - fn optional_multiscalar_mul(scalars: I, points: J) -> Option - where - I: IntoIterator, - I::Item: Borrow, - J: IntoIterator>, - { - // Sanity-check lengths of input iterators - let mut scalars = scalars.into_iter(); - let mut points = points.into_iter(); - - // Lower and upper bounds on iterators - let (s_lo, s_hi) = scalars.by_ref().size_hint(); - let (p_lo, p_hi) = points.by_ref().size_hint(); - - // They should all be equal - assert_eq!(s_lo, p_lo); - assert_eq!(s_hi, Some(s_lo)); - assert_eq!(p_hi, Some(p_lo)); - - // Now we know there's a single size. - // Use this as the hint to decide which algorithm to use. - let size = s_lo; - - if size < 190 { - scalar_mul::straus::Straus::optional_multiscalar_mul(scalars, points) - } else { - scalar_mul::pippenger::Pippenger::optional_multiscalar_mul(scalars, points) - } - } -} - -/// Precomputation for variable-time multiscalar multiplication with `EdwardsPoint`s. -// This wraps the inner implementation in a facade type so that we can -// decouple stability of the inner type from the stability of the -// outer type. -#[cfg(feature = "alloc")] -pub struct VartimeEdwardsPrecomputation(scalar_mul::precomputed_straus::VartimePrecomputedStraus); - -#[cfg(feature = "alloc")] -impl VartimePrecomputedMultiscalarMul for VartimeEdwardsPrecomputation { - type Point = EdwardsPoint; - - fn new(static_points: I) -> Self - where - I: IntoIterator, - I::Item: Borrow, - { - Self(scalar_mul::precomputed_straus::VartimePrecomputedStraus::new(static_points)) - } - - fn optional_mixed_multiscalar_mul( - &self, - static_scalars: I, - dynamic_scalars: J, - dynamic_points: K, - ) -> Option - where - I: IntoIterator, - I::Item: Borrow, - J: IntoIterator, - J::Item: Borrow, - K: IntoIterator>, - { - self.0 - .optional_mixed_multiscalar_mul(static_scalars, dynamic_scalars, dynamic_points) - } -} - -impl EdwardsPoint { - /// Compute \\(aA + bB\\) in variable time, where \\(B\\) is the Ed25519 basepoint. - pub fn vartime_double_scalar_mul_basepoint( - a: &Scalar, - A: &EdwardsPoint, - b: &Scalar, - ) -> EdwardsPoint { - scalar_mul::vartime_double_base::mul(a, A, b) - } -} - -macro_rules! impl_basepoint_table { - (Name = $name:ident, LookupTable = $table:ident, Point = $point:ty, Radix = $radix:expr, Additions = $adds:expr) => { - -/// A precomputed table of multiples of a basepoint, for accelerating -/// fixed-base scalar multiplication. One table, for the Ed25519 -/// basepoint, is provided in the `constants` module. -/// -/// The basepoint tables are reasonably large, so they should probably be boxed. -/// -/// The sizes for the tables and the number of additions required for one scalar -/// multiplication are as follows: -/// -/// * [`EdwardsBasepointTableRadix16`]: 30KB, 64A -/// (this is the default size, and is used for [`ED25519_BASEPOINT_TABLE`]) -/// * [`EdwardsBasepointTableRadix64`]: 120KB, 43A -/// * [`EdwardsBasepointTableRadix128`]: 240KB, 37A -/// * [`EdwardsBasepointTableRadix256`]: 480KB, 33A -/// -/// # Why 33 additions for radix-256? -/// -/// Normally, the radix-256 tables would allow for only 32 additions per scalar -/// multiplication. However, due to the fact that standardised definitions of -/// legacy protocols—such as x25519—require allowing unreduced 255-bit scalar -/// invariants, when converting such an unreduced scalar's representation to -/// radix-\\(2^{8}\\), we cannot guarantee the carry bit will fit in the last -/// coefficient (the coefficients are `i8`s). When, \\(w\\), the power-of-2 of -/// the radix, is \\(w < 8\\), we can fold the final carry onto the last -/// coefficient, \\(d\\), because \\(d < 2^{w/2}\\), so -/// $$ -/// d + carry \cdot 2^{w} = d + 1 \cdot 2^{w} < 2^{w+1} < 2^{8} -/// $$ -/// When \\(w = 8\\), we can't fit \\(carry \cdot 2^{w}\\) into an `i8`, so we -/// add the carry bit onto an additional coefficient. -#[derive(Clone)] -pub struct $name(pub(crate) [$table; 32]); - -impl BasepointTable for $name { - type Point = $point; - - /// Create a table of precomputed multiples of `basepoint`. - fn create(basepoint: &$point) -> $name { - // XXX use init_with - let mut table = $name([$table::default(); 32]); - let mut P = *basepoint; - for i in 0..32 { - // P = (2w)^i * B - table.0[i] = $table::from(&P); - P = P.mul_by_pow_2($radix + $radix); - } - table - } - - /// Get the basepoint for this table as an `EdwardsPoint`. - fn basepoint(&self) -> $point { - // self.0[0].select(1) = 1*(16^2)^0*B - // but as an `AffineNielsPoint`, so add identity to convert to extended. - (&<$point>::identity() + &self.0[0].select(1)).to_extended() - } - - /// The computation uses Pippeneger's algorithm, as described for the - /// specific case of radix-16 on page 13 of the Ed25519 paper. - /// - /// # Piggenger's Algorithm Generalised - /// - /// Write the scalar \\(a\\) in radix-\\(w\\), where \\(w\\) is a power of - /// 2, with coefficients in \\([\frac{-w}{2},\frac{w}{2})\\), i.e., - /// $$ - /// a = a\_0 + a\_1 w\^1 + \cdots + a\_{x} w\^{x}, - /// $$ - /// with - /// $$ - /// \frac{-w}{2} \leq a_i < \frac{w}{2}, \cdots, \frac{-w}{2} \leq a\_{x} \leq \frac{w}{2} - /// $$ - /// and the number of additions, \\(x\\), is given by \\(x = \lceil \frac{256}{w} \rceil\\). - /// Then - /// $$ - /// a B = a\_0 B + a\_1 w\^1 B + \cdots + a\_{x-1} w\^{x-1} B. - /// $$ - /// Grouping even and odd coefficients gives - /// $$ - /// \begin{aligned} - /// a B = \quad a\_0 w\^0 B +& a\_2 w\^2 B + \cdots + a\_{x-2} w\^{x-2} B \\\\ - /// + a\_1 w\^1 B +& a\_3 w\^3 B + \cdots + a\_{x-1} w\^{x-1} B \\\\ - /// = \quad(a\_0 w\^0 B +& a\_2 w\^2 B + \cdots + a\_{x-2} w\^{x-2} B) \\\\ - /// + w(a\_1 w\^0 B +& a\_3 w\^2 B + \cdots + a\_{x-1} w\^{x-2} B). \\\\ - /// \end{aligned} - /// $$ - /// For each \\(i = 0 \ldots 31\\), we create a lookup table of - /// $$ - /// [w\^{2i} B, \ldots, \frac{w}{2}\cdotw\^{2i} B], - /// $$ - /// and use it to select \\( y \cdot w\^{2i} \cdot B \\) in constant time. - /// - /// The radix-\\(w\\) representation requires that the scalar is bounded - /// by \\(2\^{255}\\), which is always the case. - /// - /// The above algorithm is trivially generalised to other powers-of-2 radices. - fn basepoint_mul(&self, scalar: &Scalar) -> $point { - let a = scalar.to_radix_2w($radix); - - let tables = &self.0; - let mut P = <$point>::identity(); - - for i in (0..$adds).filter(|x| x % 2 == 1) { - P = (&P + &tables[i/2].select(a[i])).to_extended(); - } - - P = P.mul_by_pow_2($radix); - - for i in (0..$adds).filter(|x| x % 2 == 0) { - P = (&P + &tables[i/2].select(a[i])).to_extended(); - } - - P - } -} - -impl<'a, 'b> Mul<&'b Scalar> for &'a $name { - type Output = $point; - - /// Construct an `EdwardsPoint` from a `Scalar` \\(a\\) by - /// computing the multiple \\(aB\\) of this basepoint \\(B\\). - fn mul(self, scalar: &'b Scalar) -> $point { - // delegate to a private function so that its documentation appears in internal docs - self.basepoint_mul(scalar) - } -} - -impl<'a, 'b> Mul<&'a $name> for &'b Scalar { - type Output = $point; - - /// Construct an `EdwardsPoint` from a `Scalar` \\(a\\) by - /// computing the multiple \\(aB\\) of this basepoint \\(B\\). - fn mul(self, basepoint_table: &'a $name) -> $point { - basepoint_table * self - } -} - -impl Debug for $name { - fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { - write!(f, "{:?}([\n", stringify!($name))?; - for i in 0..32 { - write!(f, "\t{:?},\n", &self.0[i])?; - } - write!(f, "])") - } -} - -}} // End macro_rules! impl_basepoint_table - -// The number of additions required is ceil(256/w) where w is the radix representation. -impl_basepoint_table! {Name = EdwardsBasepointTableRadix16, LookupTable = LookupTableRadix16, Point = EdwardsPoint, Radix = 4, Additions = 64} -impl_basepoint_table! {Name = EdwardsBasepointTableRadix32, LookupTable = LookupTableRadix32, Point = EdwardsPoint, Radix = 5, Additions = 52} -impl_basepoint_table! {Name = EdwardsBasepointTableRadix64, LookupTable = LookupTableRadix64, Point = EdwardsPoint, Radix = 6, Additions = 43} -impl_basepoint_table! {Name = EdwardsBasepointTableRadix128, LookupTable = LookupTableRadix128, Point = EdwardsPoint, Radix = 7, Additions = 37} -impl_basepoint_table! {Name = EdwardsBasepointTableRadix256, LookupTable = LookupTableRadix256, Point = EdwardsPoint, Radix = 8, Additions = 33} - -// ------------------------------------------------------------------------------------- -// BEGIN legacy 3.x series code for backwards compatibility with BasepointTable trait -// ------------------------------------------------------------------------------------- - -/// A precomputed table of multiples of a basepoint, for accelerating -/// fixed-base scalar multiplication. One table, for the Ed25519 -/// basepoint, is provided in the `constants` module. -/// -/// The basepoint tables are reasonably large, so they should probably be boxed. -/// -/// The sizes for the tables and the number of additions required for one scalar -/// multiplication are as follows: -/// -/// * [`EdwardsBasepointTableRadix16`]: 30KB, 64A -/// (this is the default size, and is used for [`ED25519_BASEPOINT_TABLE`]) -/// * [`EdwardsBasepointTableRadix64`]: 120KB, 43A -/// * [`EdwardsBasepointTableRadix128`]: 240KB, 37A -/// * [`EdwardsBasepointTableRadix256`]: 480KB, 33A -/// -/// # Why 33 additions for radix-256? -/// -/// Normally, the radix-256 tables would allow for only 32 additions per scalar -/// multiplication. However, due to the fact that standardised definitions of -/// legacy protocols—such as x25519—require allowing unreduced 255-bit scalar -/// invariants, when converting such an unreduced scalar's representation to -/// radix-\\(2^{8}\\), we cannot guarantee the carry bit will fit in the last -/// coefficient (the coefficients are `i8`s). When, \\(w\\), the power-of-2 of -/// the radix, is \\(w < 8\\), we can fold the final carry onto the last -/// coefficient, \\(d\\), because \\(d < 2^{w/2}\\), so -/// $$ -/// d + carry \cdot 2^{w} = d + 1 \cdot 2^{w} < 2^{w+1} < 2^{8} -/// $$ -/// When \\(w = 8\\), we can't fit \\(carry \cdot 2^{w}\\) into an `i8`, so we -/// add the carry bit onto an additional coefficient. -#[derive(Clone)] -pub struct EdwardsBasepointTable(pub(crate) [LookupTable; 32]); - -impl EdwardsBasepointTable { - /// Create a table of precomputed multiples of `basepoint`. - #[allow(warnings)] - pub fn create(basepoint: &EdwardsPoint) -> EdwardsBasepointTable { - Self(EdwardsBasepointTableRadix16::create(basepoint).0) - } - - /// The computation uses Pippenger's algorithm, as described on - /// page 13 of the Ed25519 paper. Write the scalar \\(a\\) in radix \\(16\\) with - /// coefficients in \\([-8,8)\\), i.e., - /// $$ - /// a = a\_0 + a\_1 16\^1 + \cdots + a\_{63} 16\^{63}, - /// $$ - /// with \\(-8 \leq a_i < 8\\), \\(-8 \leq a\_{63} \leq 8\\). Then - /// $$ - /// a B = a\_0 B + a\_1 16\^1 B + \cdots + a\_{63} 16\^{63} B. - /// $$ - /// Grouping even and odd coefficients gives - /// $$ - /// \begin{aligned} - /// a B = \quad a\_0 16\^0 B +& a\_2 16\^2 B + \cdots + a\_{62} 16\^{62} B \\\\ - /// + a\_1 16\^1 B +& a\_3 16\^3 B + \cdots + a\_{63} 16\^{63} B \\\\ - /// = \quad(a\_0 16\^0 B +& a\_2 16\^2 B + \cdots + a\_{62} 16\^{62} B) \\\\ - /// + 16(a\_1 16\^0 B +& a\_3 16\^2 B + \cdots + a\_{63} 16\^{62} B). \\\\ - /// \end{aligned} - /// $$ - /// For each \\(i = 0 \ldots 31\\), we create a lookup table of - /// $$ - /// [16\^{2i} B, \ldots, 8\cdot16\^{2i} B], - /// $$ - /// and use it to select \\( x \cdot 16\^{2i} \cdot B \\) in constant time. - /// - /// The radix-\\(16\\) representation requires that the scalar is bounded - /// by \\(2\^{255}\\), which is always the case. - #[allow(warnings)] - pub fn basepoint_mul(&self, scalar: &Scalar) -> EdwardsPoint { - let a = scalar.to_radix_16(); - - let tables = &self.0; - let mut P = EdwardsPoint::identity(); - - for i in (0..64).filter(|x| x % 2 == 1) { - P = (&P + &tables[i/2].select(a[i])).to_extended(); - } - - P = P.mul_by_pow_2(4); - - for i in (0..64).filter(|x| x % 2 == 0) { - P = (&P + &tables[i/2].select(a[i])).to_extended(); - } - - P - } - - /// Get the basepoint for this table as an `EdwardsPoint`. - #[allow(warnings)] - pub fn basepoint(&self) -> EdwardsPoint { - (&EdwardsPoint::identity() + &self.0[0].select(1)).to_extended() - } -} - -impl<'a, 'b> Mul<&'b Scalar> for &'a EdwardsBasepointTable { - type Output = EdwardsPoint; - - /// Construct an `EdwardsPoint` from a `Scalar` \\(a\\) by - /// computing the multiple \\(aB\\) of this basepoint \\(B\\). - fn mul(self, scalar: &'b Scalar) -> EdwardsPoint { - // delegate to a private function so that its documentation appears in internal docs - self.basepoint_mul(scalar) - } -} - -impl<'a, 'b> Mul<&'a EdwardsBasepointTable> for &'b Scalar { - type Output = EdwardsPoint; - - /// Construct an `EdwardsPoint` from a `Scalar` \\(a\\) by - /// computing the multiple \\(aB\\) of this basepoint \\(B\\). - fn mul(self, basepoint_table: &'a EdwardsBasepointTable) -> EdwardsPoint { - basepoint_table * self - } -} - -// ------------------------------------------------------------------------------------- -// END legacy 3.x series code for backwards compatibility with BasepointTable trait -// ------------------------------------------------------------------------------------- - -macro_rules! impl_basepoint_table_conversions { - (LHS = $lhs:ty, RHS = $rhs:ty) => { - impl<'a> From<&'a $lhs> for $rhs { - fn from(table: &'a $lhs) -> $rhs { - <$rhs>::create(&table.basepoint()) - } - } - - impl<'a> From<&'a $rhs> for $lhs { - fn from(table: &'a $rhs) -> $lhs { - <$lhs>::create(&table.basepoint()) - } - } - } -} - -impl_basepoint_table_conversions!{LHS = EdwardsBasepointTableRadix16, RHS = EdwardsBasepointTableRadix32} -impl_basepoint_table_conversions!{LHS = EdwardsBasepointTableRadix16, RHS = EdwardsBasepointTableRadix64} -impl_basepoint_table_conversions!{LHS = EdwardsBasepointTableRadix16, RHS = EdwardsBasepointTableRadix128} -impl_basepoint_table_conversions!{LHS = EdwardsBasepointTableRadix16, RHS = EdwardsBasepointTableRadix256} - -impl_basepoint_table_conversions!{LHS = EdwardsBasepointTableRadix32, RHS = EdwardsBasepointTableRadix64} -impl_basepoint_table_conversions!{LHS = EdwardsBasepointTableRadix32, RHS = EdwardsBasepointTableRadix128} -impl_basepoint_table_conversions!{LHS = EdwardsBasepointTableRadix32, RHS = EdwardsBasepointTableRadix256} - -impl_basepoint_table_conversions!{LHS = EdwardsBasepointTableRadix64, RHS = EdwardsBasepointTableRadix128} -impl_basepoint_table_conversions!{LHS = EdwardsBasepointTableRadix64, RHS = EdwardsBasepointTableRadix256} - -impl_basepoint_table_conversions!{LHS = EdwardsBasepointTableRadix128, RHS = EdwardsBasepointTableRadix256} - -impl EdwardsPoint { - /// Multiply by the cofactor: return \\([8]P\\). - pub fn mul_by_cofactor(&self) -> EdwardsPoint { - self.mul_by_pow_2(3) - } - - /// Compute \\([2\^k] P \\) by successive doublings. Requires \\( k > 0 \\). - pub(crate) fn mul_by_pow_2(&self, k: u32) -> EdwardsPoint { - debug_assert!( k > 0 ); - let mut r: CompletedPoint; - let mut s = self.to_projective(); - for _ in 0..(k-1) { - r = s.double(); s = r.to_projective(); - } - // Unroll last iteration so we can go directly to_extended() - s.double().to_extended() - } - - /// Determine if this point is of small order. - /// - /// # Return - /// - /// * `true` if `self` is in the torsion subgroup \\( \mathcal E[8] \\); - /// * `false` if `self` is not in the torsion subgroup \\( \mathcal E[8] \\). - /// - /// # Example - /// - /// ``` - /// use curve25519_dalek::constants; - /// - /// // Generator of the prime-order subgroup - /// let P = constants::ED25519_BASEPOINT_POINT; - /// // Generator of the torsion subgroup - /// let Q = constants::EIGHT_TORSION[1]; - /// - /// // P has large order - /// assert_eq!(P.is_small_order(), false); - /// - /// // Q has small order - /// assert_eq!(Q.is_small_order(), true); - /// ``` - pub fn is_small_order(&self) -> bool { - self.mul_by_cofactor().is_identity() - } - - /// Determine if this point is “torsion-free”, i.e., is contained in - /// the prime-order subgroup. - /// - /// # Return - /// - /// * `true` if `self` has zero torsion component and is in the - /// prime-order subgroup; - /// * `false` if `self` has a nonzero torsion component and is not - /// in the prime-order subgroup. - /// - /// # Example - /// - /// ``` - /// use curve25519_dalek::constants; - /// - /// // Generator of the prime-order subgroup - /// let P = constants::ED25519_BASEPOINT_POINT; - /// // Generator of the torsion subgroup - /// let Q = constants::EIGHT_TORSION[1]; - /// - /// // P is torsion-free - /// assert_eq!(P.is_torsion_free(), true); - /// - /// // P + Q is not torsion-free - /// assert_eq!((P+Q).is_torsion_free(), false); - /// ``` - pub fn is_torsion_free(&self) -> bool { - (self * constants::BASEPOINT_ORDER).is_identity() - } -} - -// ------------------------------------------------------------------------ -// Debug traits -// ------------------------------------------------------------------------ - -impl Debug for EdwardsPoint { - fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { - write!(f, "EdwardsPoint{{\n\tX: {:?},\n\tY: {:?},\n\tZ: {:?},\n\tT: {:?}\n}}", - &self.X, &self.Y, &self.Z, &self.T) - } -} - -// ------------------------------------------------------------------------ -// Tests -// ------------------------------------------------------------------------ - -#[cfg(test)] -mod test { - use field::FieldElement; - use scalar::Scalar; - use subtle::ConditionallySelectable; - use constants; - use super::*; - - /// X coordinate of the basepoint. - /// = 15112221349535400772501151409588531511454012693041857206046113283949847762202 - static BASE_X_COORD_BYTES: [u8; 32] = - [0x1a, 0xd5, 0x25, 0x8f, 0x60, 0x2d, 0x56, 0xc9, 0xb2, 0xa7, 0x25, 0x95, 0x60, 0xc7, 0x2c, 0x69, - 0x5c, 0xdc, 0xd6, 0xfd, 0x31, 0xe2, 0xa4, 0xc0, 0xfe, 0x53, 0x6e, 0xcd, 0xd3, 0x36, 0x69, 0x21]; - - /// Compressed Edwards Y form of 2*basepoint. - static BASE2_CMPRSSD: CompressedEdwardsY = - CompressedEdwardsY([0xc9, 0xa3, 0xf8, 0x6a, 0xae, 0x46, 0x5f, 0xe, - 0x56, 0x51, 0x38, 0x64, 0x51, 0x0f, 0x39, 0x97, - 0x56, 0x1f, 0xa2, 0xc9, 0xe8, 0x5e, 0xa2, 0x1d, - 0xc2, 0x29, 0x23, 0x09, 0xf3, 0xcd, 0x60, 0x22]); - - /// Compressed Edwards Y form of 16*basepoint. - static BASE16_CMPRSSD: CompressedEdwardsY = - CompressedEdwardsY([0xeb, 0x27, 0x67, 0xc1, 0x37, 0xab, 0x7a, 0xd8, - 0x27, 0x9c, 0x07, 0x8e, 0xff, 0x11, 0x6a, 0xb0, - 0x78, 0x6e, 0xad, 0x3a, 0x2e, 0x0f, 0x98, 0x9f, - 0x72, 0xc3, 0x7f, 0x82, 0xf2, 0x96, 0x96, 0x70]); - - /// 4493907448824000747700850167940867464579944529806937181821189941592931634714 - pub static A_SCALAR: Scalar = Scalar{ - bytes: [ - 0x1a, 0x0e, 0x97, 0x8a, 0x90, 0xf6, 0x62, 0x2d, - 0x37, 0x47, 0x02, 0x3f, 0x8a, 0xd8, 0x26, 0x4d, - 0xa7, 0x58, 0xaa, 0x1b, 0x88, 0xe0, 0x40, 0xd1, - 0x58, 0x9e, 0x7b, 0x7f, 0x23, 0x76, 0xef, 0x09, - ], - }; - - /// 2506056684125797857694181776241676200180934651973138769173342316833279714961 - pub static B_SCALAR: Scalar = Scalar{ - bytes: [ - 0x91, 0x26, 0x7a, 0xcf, 0x25, 0xc2, 0x09, 0x1b, - 0xa2, 0x17, 0x74, 0x7b, 0x66, 0xf0, 0xb3, 0x2e, - 0x9d, 0xf2, 0xa5, 0x67, 0x41, 0xcf, 0xda, 0xc4, - 0x56, 0xa7, 0xd4, 0xaa, 0xb8, 0x60, 0x8a, 0x05, - ], - }; - - /// A_SCALAR * basepoint, computed with ed25519.py - pub static A_TIMES_BASEPOINT: CompressedEdwardsY = CompressedEdwardsY([ - 0xea, 0x27, 0xe2, 0x60, 0x53, 0xdf, 0x1b, 0x59, - 0x56, 0xf1, 0x4d, 0x5d, 0xec, 0x3c, 0x34, 0xc3, - 0x84, 0xa2, 0x69, 0xb7, 0x4c, 0xc3, 0x80, 0x3e, - 0xa8, 0xe2, 0xe7, 0xc9, 0x42, 0x5e, 0x40, 0xa5]); - - /// A_SCALAR * (A_TIMES_BASEPOINT) + B_SCALAR * BASEPOINT - /// computed with ed25519.py - static DOUBLE_SCALAR_MULT_RESULT: CompressedEdwardsY = CompressedEdwardsY([ - 0x7d, 0xfd, 0x6c, 0x45, 0xaf, 0x6d, 0x6e, 0x0e, - 0xba, 0x20, 0x37, 0x1a, 0x23, 0x64, 0x59, 0xc4, - 0xc0, 0x46, 0x83, 0x43, 0xde, 0x70, 0x4b, 0x85, - 0x09, 0x6f, 0xfe, 0x35, 0x4f, 0x13, 0x2b, 0x42]); - - /// Test round-trip decompression for the basepoint. - #[test] - fn basepoint_decompression_compression() { - let base_X = FieldElement::from_bytes(&BASE_X_COORD_BYTES); - let bp = constants::ED25519_BASEPOINT_COMPRESSED.decompress().unwrap(); - assert!(bp.is_valid()); - // Check that decompression actually gives the correct X coordinate - assert_eq!(base_X, bp.X); - assert_eq!(bp.compress(), constants::ED25519_BASEPOINT_COMPRESSED); - } - - /// Test sign handling in decompression - #[test] - fn decompression_sign_handling() { - // Manually set the high bit of the last byte to flip the sign - let mut minus_basepoint_bytes = constants::ED25519_BASEPOINT_COMPRESSED.as_bytes().clone(); - minus_basepoint_bytes[31] |= 1 << 7; - let minus_basepoint = CompressedEdwardsY(minus_basepoint_bytes) - .decompress().unwrap(); - // Test projective coordinates exactly since we know they should - // only differ by a flipped sign. - assert_eq!(minus_basepoint.X, -(&constants::ED25519_BASEPOINT_POINT.X)); - assert_eq!(minus_basepoint.Y, constants::ED25519_BASEPOINT_POINT.Y); - assert_eq!(minus_basepoint.Z, constants::ED25519_BASEPOINT_POINT.Z); - assert_eq!(minus_basepoint.T, -(&constants::ED25519_BASEPOINT_POINT.T)); - } - - /// Test that computing 1*basepoint gives the correct basepoint. - #[test] - fn basepoint_mult_one_vs_basepoint() { - let bp = &constants::ED25519_BASEPOINT_TABLE * &Scalar::one(); - let compressed = bp.compress(); - assert_eq!(compressed, constants::ED25519_BASEPOINT_COMPRESSED); - } - - /// Test that `EdwardsBasepointTable::basepoint()` gives the correct basepoint. - #[test] - fn basepoint_table_basepoint_function_correct() { - let bp = constants::ED25519_BASEPOINT_TABLE.basepoint(); - assert_eq!(bp.compress(), constants::ED25519_BASEPOINT_COMPRESSED); - } - - /// Test `impl Add for EdwardsPoint` - /// using basepoint + basepoint versus the 2*basepoint constant. - #[test] - fn basepoint_plus_basepoint_vs_basepoint2() { - let bp = constants::ED25519_BASEPOINT_POINT; - let bp_added = &bp + &bp; - assert_eq!(bp_added.compress(), BASE2_CMPRSSD); - } - - /// Test `impl Add for EdwardsPoint` - /// using the basepoint, basepoint2 constants - #[test] - fn basepoint_plus_basepoint_projective_niels_vs_basepoint2() { - let bp = constants::ED25519_BASEPOINT_POINT; - let bp_added = (&bp + &bp.to_projective_niels()).to_extended(); - assert_eq!(bp_added.compress(), BASE2_CMPRSSD); - } - - /// Test `impl Add for EdwardsPoint` - /// using the basepoint, basepoint2 constants - #[test] - fn basepoint_plus_basepoint_affine_niels_vs_basepoint2() { - let bp = constants::ED25519_BASEPOINT_POINT; - let bp_affine_niels = bp.to_affine_niels(); - let bp_added = (&bp + &bp_affine_niels).to_extended(); - assert_eq!(bp_added.compress(), BASE2_CMPRSSD); - } - - /// Check that equality of `EdwardsPoints` handles projective - /// coordinates correctly. - #[test] - fn extended_point_equality_handles_scaling() { - let mut two_bytes = [0u8; 32]; two_bytes[0] = 2; - let id1 = EdwardsPoint::identity(); - let id2 = EdwardsPoint{ - X: FieldElement::zero(), - Y: FieldElement::from_bytes(&two_bytes), - Z: FieldElement::from_bytes(&two_bytes), - T: FieldElement::zero() - }; - assert_eq!(id1.ct_eq(&id2).unwrap_u8(), 1u8); - } - - /// Sanity check for conversion to precomputed points - #[test] - fn to_affine_niels_clears_denominators() { - // construct a point as aB so it has denominators (ie. Z != 1) - let aB = &constants::ED25519_BASEPOINT_TABLE * &A_SCALAR; - let aB_affine_niels = aB.to_affine_niels(); - let also_aB = (&EdwardsPoint::identity() + &aB_affine_niels).to_extended(); - assert_eq!( aB.compress(), - also_aB.compress()); - } - - /// Test basepoint_mult versus a known scalar multiple from ed25519.py - #[test] - fn basepoint_mult_vs_ed25519py() { - let aB = &constants::ED25519_BASEPOINT_TABLE * &A_SCALAR; - assert_eq!(aB.compress(), A_TIMES_BASEPOINT); - } - - /// Test that multiplication by the basepoint order kills the basepoint - #[test] - fn basepoint_mult_by_basepoint_order() { - let B = &constants::ED25519_BASEPOINT_TABLE; - let should_be_id = B * &constants::BASEPOINT_ORDER; - assert!(should_be_id.is_identity()); - } - - /// Test precomputed basepoint mult - #[test] - fn test_precomputed_basepoint_mult() { - let aB_1 = &constants::ED25519_BASEPOINT_TABLE * &A_SCALAR; - let aB_2 = &constants::ED25519_BASEPOINT_POINT * &A_SCALAR; - assert_eq!(aB_1.compress(), aB_2.compress()); - } - - /// Test scalar_mul versus a known scalar multiple from ed25519.py - #[test] - fn scalar_mul_vs_ed25519py() { - let aB = &constants::ED25519_BASEPOINT_POINT * &A_SCALAR; - assert_eq!(aB.compress(), A_TIMES_BASEPOINT); - } - - /// Test basepoint.double() versus the 2*basepoint constant. - #[test] - fn basepoint_double_vs_basepoint2() { - assert_eq!(constants::ED25519_BASEPOINT_POINT.double().compress(), - BASE2_CMPRSSD); - } - - /// Test that computing 2*basepoint is the same as basepoint.double() - #[test] - fn basepoint_mult_two_vs_basepoint2() { - let two = Scalar::from(2u64); - let bp2 = &constants::ED25519_BASEPOINT_TABLE * &two; - assert_eq!(bp2.compress(), BASE2_CMPRSSD); - } - - /// Test that all the basepoint table types compute the same results. - #[test] - fn basepoint_tables() { - let P = &constants::ED25519_BASEPOINT_POINT; - let a = A_SCALAR; - - let table_radix16 = EdwardsBasepointTableRadix16::create(&P); - let table_radix32 = EdwardsBasepointTableRadix32::create(&P); - let table_radix64 = EdwardsBasepointTableRadix64::create(&P); - let table_radix128 = EdwardsBasepointTableRadix128::create(&P); - let table_radix256 = EdwardsBasepointTableRadix256::create(&P); - - let aP = (&constants::ED25519_BASEPOINT_TABLE * &a).compress(); - let aP16 = (&table_radix16 * &a).compress(); - let aP32 = (&table_radix32 * &a).compress(); - let aP64 = (&table_radix64 * &a).compress(); - let aP128 = (&table_radix128 * &a).compress(); - let aP256 = (&table_radix256 * &a).compress(); - - assert_eq!(aP, aP16); - assert_eq!(aP16, aP32); - assert_eq!(aP32, aP64); - assert_eq!(aP64, aP128); - assert_eq!(aP128, aP256); - } - - // Check a unreduced scalar multiplication by the basepoint tables. - #[test] - fn basepoint_tables_unreduced_scalar() { - let P = &constants::ED25519_BASEPOINT_POINT; - let a = Scalar::from_bits([ - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - ]); - - let table_radix16 = EdwardsBasepointTableRadix16::create(&P); - let table_radix32 = EdwardsBasepointTableRadix32::create(&P); - let table_radix64 = EdwardsBasepointTableRadix64::create(&P); - let table_radix128 = EdwardsBasepointTableRadix128::create(&P); - let table_radix256 = EdwardsBasepointTableRadix256::create(&P); - - let aP = (&constants::ED25519_BASEPOINT_TABLE * &a).compress(); - let aP16 = (&table_radix16 * &a).compress(); - let aP32 = (&table_radix32 * &a).compress(); - let aP64 = (&table_radix64 * &a).compress(); - let aP128 = (&table_radix128 * &a).compress(); - let aP256 = (&table_radix256 * &a).compress(); - - assert_eq!(aP, aP16); - assert_eq!(aP16, aP32); - assert_eq!(aP32, aP64); - assert_eq!(aP64, aP128); - assert_eq!(aP128, aP256); - } - - /// Check that converting to projective and then back to extended round-trips. - #[test] - fn basepoint_projective_extended_round_trip() { - assert_eq!(constants::ED25519_BASEPOINT_POINT - .to_projective().to_extended().compress(), - constants::ED25519_BASEPOINT_COMPRESSED); - } - - /// Test computing 16*basepoint vs mul_by_pow_2(4) - #[test] - fn basepoint16_vs_mul_by_pow_2_4() { - let bp16 = constants::ED25519_BASEPOINT_POINT.mul_by_pow_2(4); - assert_eq!(bp16.compress(), BASE16_CMPRSSD); - } - - #[test] - fn impl_sum() { - - // Test that sum works for non-empty iterators - let BASE = constants::ED25519_BASEPOINT_POINT; - - let s1 = Scalar::from(999u64); - let P1 = &BASE * &s1; - - let s2 = Scalar::from(333u64); - let P2 = &BASE * &s2; - - let vec = vec![P1.clone(), P2.clone()]; - let sum: EdwardsPoint = vec.iter().sum(); - - assert_eq!(sum, P1 + P2); - - // Test that sum works for the empty iterator - let empty_vector: Vec = vec![]; - let sum: EdwardsPoint = empty_vector.iter().sum(); - - assert_eq!(sum, EdwardsPoint::identity()); - - // Test that sum works on owning iterators - let s = Scalar::from(2u64); - let mapped = vec.iter().map(|x| x * s); - let sum: EdwardsPoint = mapped.sum(); - - assert_eq!(sum, &P1 * &s + &P2 * &s); - } - - - /// Test that the conditional assignment trait works for AffineNielsPoints. - #[test] - fn conditional_assign_for_affine_niels_point() { - let id = AffineNielsPoint::identity(); - let mut p1 = AffineNielsPoint::identity(); - let bp = constants::ED25519_BASEPOINT_POINT.to_affine_niels(); - - p1.conditional_assign(&bp, Choice::from(0)); - assert_eq!(p1, id); - p1.conditional_assign(&bp, Choice::from(1)); - assert_eq!(p1, bp); - } - - #[test] - fn is_small_order() { - // The basepoint has large prime order - assert!(!constants::ED25519_BASEPOINT_POINT.is_small_order()); - // constants::EIGHT_TORSION has all points of small order. - for torsion_point in &constants::EIGHT_TORSION { - assert!(torsion_point.is_small_order()); - } - } - - #[test] - fn compressed_identity() { - assert_eq!(EdwardsPoint::identity().compress(), - CompressedEdwardsY::identity()); - } - - #[test] - fn is_identity() { - assert!( EdwardsPoint::identity().is_identity()); - assert!(!constants::ED25519_BASEPOINT_POINT.is_identity()); - } - - /// Rust's debug builds have overflow and underflow trapping, - /// and enable `debug_assert!()`. This performs many scalar - /// multiplications to attempt to trigger possible overflows etc. - /// - /// For instance, the `u64` `Mul` implementation for - /// `FieldElements` requires the input `Limb`s to be bounded by - /// 2^54, but we cannot enforce this dynamically at runtime, or - /// statically at compile time (until Rust gets type-level - /// integers, at which point we can encode "bits of headroom" into - /// the type system and prove correctness). - #[test] - fn monte_carlo_overflow_underflow_debug_assert_test() { - let mut P = constants::ED25519_BASEPOINT_POINT; - // N.B. each scalar_mul does 1407 field mults, 1024 field squarings, - // so this does ~ 1M of each operation. - for _ in 0..1_000 { - P *= &A_SCALAR; - } - } - - #[test] - fn scalarmult_extended_point_works_both_ways() { - let G: EdwardsPoint = constants::ED25519_BASEPOINT_POINT; - let s: Scalar = A_SCALAR; - - let P1 = &G * &s; - let P2 = &s * &G; - - assert!(P1.compress().to_bytes() == P2.compress().to_bytes()); - } - - // A single iteration of a consistency check for MSM. - fn multiscalar_consistency_iter(n: usize) { - use core::iter; - let mut rng = rand::thread_rng(); - - // Construct random coefficients x0, ..., x_{n-1}, - // followed by some extra hardcoded ones. - let xs = (0..n) - .map(|_| Scalar::random(&mut rng)) - // The largest scalar allowed by the type system, 2^255-1 - .chain(iter::once(Scalar::from_bits([0xff; 32]))) - .collect::>(); - let check = xs.iter() - .map(|xi| xi * xi) - .sum::(); - - // Construct points G_i = x_i * B - let Gs = xs.iter() - .map(|xi| xi * &constants::ED25519_BASEPOINT_TABLE) - .collect::>(); - - // Compute H1 = (consttime) - let H1 = EdwardsPoint::multiscalar_mul(&xs, &Gs); - // Compute H2 = (vartime) - let H2 = EdwardsPoint::vartime_multiscalar_mul(&xs, &Gs); - // Compute H3 = = sum(xi^2) * B - let H3 = &check * &constants::ED25519_BASEPOINT_TABLE; - - assert_eq!(H1, H3); - assert_eq!(H2, H3); - } - - // Use different multiscalar sizes to hit different internal - // parameters. - - #[test] - fn multiscalar_consistency_n_100() { - let iters = 50; - for _ in 0..iters { - multiscalar_consistency_iter(100); - } - } - - #[test] - fn multiscalar_consistency_n_250() { - let iters = 50; - for _ in 0..iters { - multiscalar_consistency_iter(250); - } - } - - #[test] - fn multiscalar_consistency_n_500() { - let iters = 50; - for _ in 0..iters { - multiscalar_consistency_iter(500); - } - } - - #[test] - fn multiscalar_consistency_n_1000() { - let iters = 50; - for _ in 0..iters { - multiscalar_consistency_iter(1000); - } - } - - #[test] - fn vartime_precomputed_vs_nonprecomputed_multiscalar() { - let mut rng = rand::thread_rng(); - - let B = &::constants::ED25519_BASEPOINT_TABLE; - - let static_scalars = (0..128) - .map(|_| Scalar::random(&mut rng)) - .collect::>(); - - let dynamic_scalars = (0..128) - .map(|_| Scalar::random(&mut rng)) - .collect::>(); - - let check_scalar: Scalar = static_scalars - .iter() - .chain(dynamic_scalars.iter()) - .map(|s| s * s) - .sum(); - - let static_points = static_scalars.iter().map(|s| s * B).collect::>(); - let dynamic_points = dynamic_scalars.iter().map(|s| s * B).collect::>(); - - let precomputation = VartimeEdwardsPrecomputation::new(static_points.iter()); - - let P = precomputation.vartime_mixed_multiscalar_mul( - &static_scalars, - &dynamic_scalars, - &dynamic_points, - ); - - use traits::VartimeMultiscalarMul; - let Q = EdwardsPoint::vartime_multiscalar_mul( - static_scalars.iter().chain(dynamic_scalars.iter()), - static_points.iter().chain(dynamic_points.iter()), - ); - - let R = &check_scalar * B; - - assert_eq!(P.compress(), R.compress()); - assert_eq!(Q.compress(), R.compress()); - } - - mod vartime { - use super::super::*; - use super::{A_SCALAR, B_SCALAR, A_TIMES_BASEPOINT, DOUBLE_SCALAR_MULT_RESULT}; - - /// Test double_scalar_mul_vartime vs ed25519.py - #[test] - fn double_scalar_mul_basepoint_vs_ed25519py() { - let A = A_TIMES_BASEPOINT.decompress().unwrap(); - let result = EdwardsPoint::vartime_double_scalar_mul_basepoint(&A_SCALAR, &A, &B_SCALAR); - assert_eq!(result.compress(), DOUBLE_SCALAR_MULT_RESULT); - } - - #[test] - fn multiscalar_mul_vs_ed25519py() { - let A = A_TIMES_BASEPOINT.decompress().unwrap(); - let result = EdwardsPoint::vartime_multiscalar_mul( - &[A_SCALAR, B_SCALAR], - &[A, constants::ED25519_BASEPOINT_POINT] - ); - assert_eq!(result.compress(), DOUBLE_SCALAR_MULT_RESULT); - } - - #[test] - fn multiscalar_mul_vartime_vs_consttime() { - let A = A_TIMES_BASEPOINT.decompress().unwrap(); - let result_vartime = EdwardsPoint::vartime_multiscalar_mul( - &[A_SCALAR, B_SCALAR], - &[A, constants::ED25519_BASEPOINT_POINT] - ); - let result_consttime = EdwardsPoint::multiscalar_mul( - &[A_SCALAR, B_SCALAR], - &[A, constants::ED25519_BASEPOINT_POINT] - ); - - assert_eq!(result_vartime.compress(), result_consttime.compress()); - } - } - - #[test] - #[cfg(feature = "serde")] - fn serde_bincode_basepoint_roundtrip() { - use bincode; - - let encoded = bincode::serialize(&constants::ED25519_BASEPOINT_POINT).unwrap(); - let enc_compressed = bincode::serialize(&constants::ED25519_BASEPOINT_COMPRESSED).unwrap(); - assert_eq!(encoded, enc_compressed); - - // Check that the encoding is 32 bytes exactly - assert_eq!(encoded.len(), 32); - - let dec_uncompressed: EdwardsPoint = bincode::deserialize(&encoded).unwrap(); - let dec_compressed: CompressedEdwardsY = bincode::deserialize(&encoded).unwrap(); - - assert_eq!(dec_uncompressed, constants::ED25519_BASEPOINT_POINT); - assert_eq!(dec_compressed, constants::ED25519_BASEPOINT_COMPRESSED); - - // Check that the encoding itself matches the usual one - let raw_bytes = constants::ED25519_BASEPOINT_COMPRESSED.as_bytes(); - let bp: EdwardsPoint = bincode::deserialize(raw_bytes).unwrap(); - assert_eq!(bp, constants::ED25519_BASEPOINT_POINT); - } -} diff --git a/net/gurk-rs/files/vendor/curve25519-dalek/src/field.rs b/net/gurk-rs/files/vendor/curve25519-dalek/src/field.rs deleted file mode 100644 index 109cff2..0000000 --- a/net/gurk-rs/files/vendor/curve25519-dalek/src/field.rs +++ /dev/null @@ -1,476 +0,0 @@ -// -*- mode: rust; -*- -// -// This file is part of curve25519-dalek. -// Copyright (c) 2016-2021 isis agora lovecruft -// Copyright (c) 2016-2019 Henry de Valence -// See LICENSE for licensing information. -// -// Authors: -// - Isis Agora Lovecruft -// - Henry de Valence - -//! Field arithmetic modulo \\(p = 2\^{255} - 19\\). -//! -//! The `curve25519_dalek::field` module provides a type alias -//! `curve25519_dalek::field::FieldElement` to a field element type -//! defined in the `backend` module; either `FieldElement51` or -//! `FieldElement2625`. -//! -//! Field operations defined in terms of machine -//! operations, such as field multiplication or squaring, are defined in -//! the backend implementation. -//! -//! Field operations defined in terms of other field operations, such as -//! field inversion or square roots, are defined here. - -use core::cmp::{Eq, PartialEq}; - -use subtle::ConditionallySelectable; -use subtle::ConditionallyNegatable; -use subtle::Choice; -use subtle::ConstantTimeEq; - -use constants; -use backend; - -#[cfg(feature = "fiat_u32_backend")] -pub use backend::serial::fiat_u32::field::*; -#[cfg(feature = "fiat_u64_backend")] -pub use backend::serial::fiat_u64::field::*; -/// A `FieldElement` represents an element of the field -/// \\( \mathbb Z / (2\^{255} - 19)\\). -/// -/// The `FieldElement` type is an alias for one of the platform-specific -/// implementations. -/// Using formally-verified field arithmetic from fiat-crypto -#[cfg(feature = "fiat_u32_backend")] -pub type FieldElement = backend::serial::fiat_u32::field::FieldElement2625; -#[cfg(feature = "fiat_u64_backend")] -pub type FieldElement = backend::serial::fiat_u64::field::FieldElement51; - -#[cfg(feature = "u64_backend")] -pub use backend::serial::u64::field::*; -/// A `FieldElement` represents an element of the field -/// \\( \mathbb Z / (2\^{255} - 19)\\). -/// -/// The `FieldElement` type is an alias for one of the platform-specific -/// implementations. -#[cfg(feature = "u64_backend")] -pub type FieldElement = backend::serial::u64::field::FieldElement51; - -#[cfg(feature = "u32_backend")] -pub use backend::serial::u32::field::*; -/// A `FieldElement` represents an element of the field -/// \\( \mathbb Z / (2\^{255} - 19)\\). -/// -/// The `FieldElement` type is an alias for one of the platform-specific -/// implementations. -#[cfg(feature = "u32_backend")] -pub type FieldElement = backend::serial::u32::field::FieldElement2625; - -impl Eq for FieldElement {} - -impl PartialEq for FieldElement { - fn eq(&self, other: &FieldElement) -> bool { - self.ct_eq(other).unwrap_u8() == 1u8 - } -} - -impl ConstantTimeEq for FieldElement { - /// Test equality between two `FieldElement`s. Since the - /// internal representation is not canonical, the field elements - /// are normalized to wire format before comparison. - fn ct_eq(&self, other: &FieldElement) -> Choice { - self.to_bytes().ct_eq(&other.to_bytes()) - } -} - -impl FieldElement { - /// Determine if this `FieldElement` is negative, in the sense - /// used in the ed25519 paper: `x` is negative if the low bit is - /// set. - /// - /// # Return - /// - /// If negative, return `Choice(1)`. Otherwise, return `Choice(0)`. - pub fn is_negative(&self) -> Choice { - let bytes = self.to_bytes(); - (bytes[0] & 1).into() - } - - /// Determine if this `FieldElement` is zero. - /// - /// # Return - /// - /// If zero, return `Choice(1)`. Otherwise, return `Choice(0)`. - pub fn is_zero(&self) -> Choice { - let zero = [0u8; 32]; - let bytes = self.to_bytes(); - - bytes.ct_eq(&zero) - } - - /// Compute (self^(2^250-1), self^11), used as a helper function - /// within invert() and pow22523(). - fn pow22501(&self) -> (FieldElement, FieldElement) { - // Instead of managing which temporary variables are used - // for what, we define as many as we need and leave stack - // allocation to the compiler - // - // Each temporary variable t_i is of the form (self)^e_i. - // Squaring t_i corresponds to multiplying e_i by 2, - // so the pow2k function shifts e_i left by k places. - // Multiplying t_i and t_j corresponds to adding e_i + e_j. - // - // Temporary t_i Nonzero bits of e_i - // - let t0 = self.square(); // 1 e_0 = 2^1 - let t1 = t0.square().square(); // 3 e_1 = 2^3 - let t2 = self * &t1; // 3,0 e_2 = 2^3 + 2^0 - let t3 = &t0 * &t2; // 3,1,0 - let t4 = t3.square(); // 4,2,1 - let t5 = &t2 * &t4; // 4,3,2,1,0 - let t6 = t5.pow2k(5); // 9,8,7,6,5 - let t7 = &t6 * &t5; // 9,8,7,6,5,4,3,2,1,0 - let t8 = t7.pow2k(10); // 19..10 - let t9 = &t8 * &t7; // 19..0 - let t10 = t9.pow2k(20); // 39..20 - let t11 = &t10 * &t9; // 39..0 - let t12 = t11.pow2k(10); // 49..10 - let t13 = &t12 * &t7; // 49..0 - let t14 = t13.pow2k(50); // 99..50 - let t15 = &t14 * &t13; // 99..0 - let t16 = t15.pow2k(100); // 199..100 - let t17 = &t16 * &t15; // 199..0 - let t18 = t17.pow2k(50); // 249..50 - let t19 = &t18 * &t13; // 249..0 - - (t19, t3) - } - - /// Given a slice of public `FieldElements`, replace each with its inverse. - /// - /// All input `FieldElements` **MUST** be nonzero. - #[cfg(feature = "alloc")] - pub fn batch_invert(inputs: &mut [FieldElement]) { - // Montgomery’s Trick and Fast Implementation of Masked AES - // Genelle, Prouff and Quisquater - // Section 3.2 - - let n = inputs.len(); - let mut scratch = vec![FieldElement::one(); n]; - - // Keep an accumulator of all of the previous products - let mut acc = FieldElement::one(); - - // Pass through the input vector, recording the previous - // products in the scratch space - for (input, scratch) in inputs.iter().zip(scratch.iter_mut()) { - *scratch = acc; - acc = &acc * input; - } - - // acc is nonzero iff all inputs are nonzero - assert_eq!(acc.is_zero().unwrap_u8(), 0); - - // Compute the inverse of all products - acc = acc.invert(); - - // Pass through the vector backwards to compute the inverses - // in place - for (input, scratch) in inputs.iter_mut().rev().zip(scratch.into_iter().rev()) { - let tmp = &acc * input; - *input = &acc * &scratch; - acc = tmp; - } - } - - /// Given a nonzero field element, compute its inverse. - /// - /// The inverse is computed as self^(p-2), since - /// x^(p-2)x = x^(p-1) = 1 (mod p). - /// - /// This function returns zero on input zero. - pub fn invert(&self) -> FieldElement { - // The bits of p-2 = 2^255 -19 -2 are 11010111111...11. - // - // nonzero bits of exponent - let (t19, t3) = self.pow22501(); // t19: 249..0 ; t3: 3,1,0 - let t20 = t19.pow2k(5); // 254..5 - let t21 = &t20 * &t3; // 254..5,3,1,0 - - t21 - } - - /// Raise this field element to the power (p-5)/8 = 2^252 -3. - fn pow_p58(&self) -> FieldElement { - // The bits of (p-5)/8 are 101111.....11. - // - // nonzero bits of exponent - let (t19, _) = self.pow22501(); // 249..0 - let t20 = t19.pow2k(2); // 251..2 - let t21 = self * &t20; // 251..2,0 - - t21 - } - - /// Given `FieldElements` `u` and `v`, compute either `sqrt(u/v)` - /// or `sqrt(i*u/v)` in constant time. - /// - /// This function always returns the nonnegative square root. - /// - /// # Return - /// - /// - `(Choice(1), +sqrt(u/v)) ` if `v` is nonzero and `u/v` is square; - /// - `(Choice(1), zero) ` if `u` is zero; - /// - `(Choice(0), zero) ` if `v` is zero and `u` is nonzero; - /// - `(Choice(0), +sqrt(i*u/v))` if `u/v` is nonsquare (so `i*u/v` is square). - /// - pub fn sqrt_ratio_i(u: &FieldElement, v: &FieldElement) -> (Choice, FieldElement) { - // Using the same trick as in ed25519 decoding, we merge the - // inversion, the square root, and the square test as follows. - // - // To compute sqrt(α), we can compute β = α^((p+3)/8). - // Then β^2 = ±α, so multiplying β by sqrt(-1) if necessary - // gives sqrt(α). - // - // To compute 1/sqrt(α), we observe that - // 1/β = α^(p-1 - (p+3)/8) = α^((7p-11)/8) - // = α^3 * (α^7)^((p-5)/8). - // - // We can therefore compute sqrt(u/v) = sqrt(u)/sqrt(v) - // by first computing - // r = u^((p+3)/8) v^(p-1-(p+3)/8) - // = u u^((p-5)/8) v^3 (v^7)^((p-5)/8) - // = (uv^3) (uv^7)^((p-5)/8). - // - // If v is nonzero and u/v is square, then r^2 = ±u/v, - // so vr^2 = ±u. - // If vr^2 = u, then sqrt(u/v) = r. - // If vr^2 = -u, then sqrt(u/v) = r*sqrt(-1). - // - // If v is zero, r is also zero. - - let v3 = &v.square() * v; - let v7 = &v3.square() * v; - let mut r = &(u * &v3) * &(u * &v7).pow_p58(); - let check = v * &r.square(); - - let i = &constants::SQRT_M1; - - let correct_sign_sqrt = check.ct_eq( u); - let flipped_sign_sqrt = check.ct_eq( &(-u)); - let flipped_sign_sqrt_i = check.ct_eq(&(&(-u)*i)); - - let r_prime = &constants::SQRT_M1 * &r; - r.conditional_assign(&r_prime, flipped_sign_sqrt | flipped_sign_sqrt_i); - - // Choose the nonnegative square root. - let r_is_negative = r.is_negative(); - r.conditional_negate(r_is_negative); - - let was_nonzero_square = correct_sign_sqrt | flipped_sign_sqrt; - - (was_nonzero_square, r) - } - - /// Attempt to compute `sqrt(1/self)` in constant time. - /// - /// Convenience wrapper around `sqrt_ratio_i`. - /// - /// This function always returns the nonnegative square root. - /// - /// # Return - /// - /// - `(Choice(1), +sqrt(1/self)) ` if `self` is a nonzero square; - /// - `(Choice(0), zero) ` if `self` is zero; - /// - `(Choice(0), +sqrt(i/self)) ` if `self` is a nonzero nonsquare; - /// - pub fn invsqrt(&self) -> (Choice, FieldElement) { - FieldElement::sqrt_ratio_i(&FieldElement::one(), self) - } -} - -#[cfg(test)] -mod test { - use field::*; - use subtle::ConditionallyNegatable; - - /// Random element a of GF(2^255-19), from Sage - /// a = 1070314506888354081329385823235218444233221\ - /// 2228051251926706380353716438957572 - static A_BYTES: [u8; 32] = - [ 0x04, 0xfe, 0xdf, 0x98, 0xa7, 0xfa, 0x0a, 0x68, - 0x84, 0x92, 0xbd, 0x59, 0x08, 0x07, 0xa7, 0x03, - 0x9e, 0xd1, 0xf6, 0xf2, 0xe1, 0xd9, 0xe2, 0xa4, - 0xa4, 0x51, 0x47, 0x36, 0xf3, 0xc3, 0xa9, 0x17]; - - /// Byte representation of a**2 - static ASQ_BYTES: [u8; 32] = - [ 0x75, 0x97, 0x24, 0x9e, 0xe6, 0x06, 0xfe, 0xab, - 0x24, 0x04, 0x56, 0x68, 0x07, 0x91, 0x2d, 0x5d, - 0x0b, 0x0f, 0x3f, 0x1c, 0xb2, 0x6e, 0xf2, 0xe2, - 0x63, 0x9c, 0x12, 0xba, 0x73, 0x0b, 0xe3, 0x62]; - - /// Byte representation of 1/a - static AINV_BYTES: [u8; 32] = - [0x96, 0x1b, 0xcd, 0x8d, 0x4d, 0x5e, 0xa2, 0x3a, - 0xe9, 0x36, 0x37, 0x93, 0xdb, 0x7b, 0x4d, 0x70, - 0xb8, 0x0d, 0xc0, 0x55, 0xd0, 0x4c, 0x1d, 0x7b, - 0x90, 0x71, 0xd8, 0xe9, 0xb6, 0x18, 0xe6, 0x30]; - - /// Byte representation of a^((p-5)/8) - static AP58_BYTES: [u8; 32] = - [0x6a, 0x4f, 0x24, 0x89, 0x1f, 0x57, 0x60, 0x36, - 0xd0, 0xbe, 0x12, 0x3c, 0x8f, 0xf5, 0xb1, 0x59, - 0xe0, 0xf0, 0xb8, 0x1b, 0x20, 0xd2, 0xb5, 0x1f, - 0x15, 0x21, 0xf9, 0xe3, 0xe1, 0x61, 0x21, 0x55]; - - #[test] - fn a_mul_a_vs_a_squared_constant() { - let a = FieldElement::from_bytes(&A_BYTES); - let asq = FieldElement::from_bytes(&ASQ_BYTES); - assert_eq!(asq, &a * &a); - } - - #[test] - fn a_square_vs_a_squared_constant() { - let a = FieldElement::from_bytes(&A_BYTES); - let asq = FieldElement::from_bytes(&ASQ_BYTES); - assert_eq!(asq, a.square()); - } - - #[test] - fn a_square2_vs_a_squared_constant() { - let a = FieldElement::from_bytes(&A_BYTES); - let asq = FieldElement::from_bytes(&ASQ_BYTES); - assert_eq!(a.square2(), &asq+&asq); - } - - #[test] - fn a_invert_vs_inverse_of_a_constant() { - let a = FieldElement::from_bytes(&A_BYTES); - let ainv = FieldElement::from_bytes(&AINV_BYTES); - let should_be_inverse = a.invert(); - assert_eq!(ainv, should_be_inverse); - assert_eq!(FieldElement::one(), &a * &should_be_inverse); - } - - #[test] - fn batch_invert_a_matches_nonbatched() { - let a = FieldElement::from_bytes(&A_BYTES); - let ap58 = FieldElement::from_bytes(&AP58_BYTES); - let asq = FieldElement::from_bytes(&ASQ_BYTES); - let ainv = FieldElement::from_bytes(&AINV_BYTES); - let a2 = &a + &a; - let a_list = vec![a, ap58, asq, ainv, a2]; - let mut ainv_list = a_list.clone(); - FieldElement::batch_invert(&mut ainv_list[..]); - for i in 0..5 { - assert_eq!(a_list[i].invert(), ainv_list[i]); - } - } - - #[test] - fn sqrt_ratio_behavior() { - let zero = FieldElement::zero(); - let one = FieldElement::one(); - let i = constants::SQRT_M1; - let two = &one + &one; // 2 is nonsquare mod p. - let four = &two + &two; // 4 is square mod p. - - // 0/0 should return (1, 0) since u is 0 - let (choice, sqrt) = FieldElement::sqrt_ratio_i(&zero, &zero); - assert_eq!(choice.unwrap_u8(), 1); - assert_eq!(sqrt, zero); - assert_eq!(sqrt.is_negative().unwrap_u8(), 0); - - // 1/0 should return (0, 0) since v is 0, u is nonzero - let (choice, sqrt) = FieldElement::sqrt_ratio_i(&one, &zero); - assert_eq!(choice.unwrap_u8(), 0); - assert_eq!(sqrt, zero); - assert_eq!(sqrt.is_negative().unwrap_u8(), 0); - - // 2/1 is nonsquare, so we expect (0, sqrt(i*2)) - let (choice, sqrt) = FieldElement::sqrt_ratio_i(&two, &one); - assert_eq!(choice.unwrap_u8(), 0); - assert_eq!(sqrt.square(), &two * &i); - assert_eq!(sqrt.is_negative().unwrap_u8(), 0); - - // 4/1 is square, so we expect (1, sqrt(4)) - let (choice, sqrt) = FieldElement::sqrt_ratio_i(&four, &one); - assert_eq!(choice.unwrap_u8(), 1); - assert_eq!(sqrt.square(), four); - assert_eq!(sqrt.is_negative().unwrap_u8(), 0); - - // 1/4 is square, so we expect (1, 1/sqrt(4)) - let (choice, sqrt) = FieldElement::sqrt_ratio_i(&one, &four); - assert_eq!(choice.unwrap_u8(), 1); - assert_eq!(&sqrt.square() * &four, one); - assert_eq!(sqrt.is_negative().unwrap_u8(), 0); - } - - #[test] - fn a_p58_vs_ap58_constant() { - let a = FieldElement::from_bytes(&A_BYTES); - let ap58 = FieldElement::from_bytes(&AP58_BYTES); - assert_eq!(ap58, a.pow_p58()); - } - - #[test] - fn equality() { - let a = FieldElement::from_bytes(&A_BYTES); - let ainv = FieldElement::from_bytes(&AINV_BYTES); - assert!(a == a); - assert!(a != ainv); - } - - /// Notice that the last element has the high bit set, which - /// should be ignored - static B_BYTES: [u8;32] = - [113, 191, 169, 143, 91, 234, 121, 15, - 241, 131, 217, 36, 230, 101, 92, 234, - 8, 208, 170, 251, 97, 127, 70, 210, - 58, 23, 166, 87, 240, 169, 184, 178]; - - #[test] - fn from_bytes_highbit_is_ignored() { - let mut cleared_bytes = B_BYTES; - cleared_bytes[31] &= 127u8; - let with_highbit_set = FieldElement::from_bytes(&B_BYTES); - let without_highbit_set = FieldElement::from_bytes(&cleared_bytes); - assert_eq!(without_highbit_set, with_highbit_set); - } - - #[test] - fn conditional_negate() { - let one = FieldElement::one(); - let minus_one = FieldElement::minus_one(); - let mut x = one; - x.conditional_negate(Choice::from(1)); - assert_eq!(x, minus_one); - x.conditional_negate(Choice::from(0)); - assert_eq!(x, minus_one); - x.conditional_negate(Choice::from(1)); - assert_eq!(x, one); - } - - #[test] - fn encoding_is_canonical() { - // Encode 1 wrongly as 1 + (2^255 - 19) = 2^255 - 18 - let one_encoded_wrongly_bytes: [u8;32] = [0xee, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f]; - // Decode to a field element - let one = FieldElement::from_bytes(&one_encoded_wrongly_bytes); - // .. then check that the encoding is correct - let one_bytes = one.to_bytes(); - assert_eq!(one_bytes[0], 1); - for i in 1..32 { - assert_eq!(one_bytes[i], 0); - } - } - - #[test] - fn batch_invert_empty() { - FieldElement::batch_invert(&mut []); - } -} diff --git a/net/gurk-rs/files/vendor/curve25519-dalek/src/lib.rs b/net/gurk-rs/files/vendor/curve25519-dalek/src/lib.rs deleted file mode 100644 index 13f9393..0000000 --- a/net/gurk-rs/files/vendor/curve25519-dalek/src/lib.rs +++ /dev/null @@ -1,101 +0,0 @@ -// -*- mode: rust; -*- -// -// This file is part of curve25519-dalek. -// Copyright (c) 2016-2021 isis lovecruft -// Copyright (c) 2016-2019 Henry de Valence -// See LICENSE for licensing information. -// -// Authors: -// - isis agora lovecruft -// - Henry de Valence - -#![no_std] -#![cfg_attr(feature = "nightly", feature(test))] -#![cfg_attr(feature = "nightly", feature(external_doc))] -#![cfg_attr(feature = "nightly", feature(doc_cfg))] -#![cfg_attr(feature = "simd_backend", feature(stdsimd))] -// Refuse to compile if documentation is missing, but only on nightly. -// -// This means that missing docs will still fail CI, but means we can use -// README.md as the crate documentation. -#![cfg_attr(feature = "nightly", deny(missing_docs))] - -#![cfg_attr(feature = "nightly", doc(include = "../README.md"))] -#![doc(html_logo_url = "https://doc.dalek.rs/assets/dalek-logo-clear.png")] -#![doc(html_root_url = "https://docs.rs/curve25519-dalek/3.1.0")] - -//! Note that docs will only build on nightly Rust until -//! [RFC 1990 stabilizes](https://github.com/rust-lang/rust/issues/44732). - -//------------------------------------------------------------------------ -// External dependencies: -//------------------------------------------------------------------------ - -#[cfg(all(feature = "alloc", not(feature = "std")))] -#[macro_use] -extern crate alloc; - -#[cfg(feature = "std")] -#[macro_use] -extern crate std; - -#[cfg(all(feature = "nightly", feature = "packed_simd"))] -extern crate packed_simd; - -extern crate byteorder; -pub extern crate digest; -extern crate rand_core; -extern crate zeroize; - -#[cfg(any(feature = "fiat_u64_backend", feature = "fiat_u32_backend"))] -extern crate fiat_crypto; - -// Used for traits related to constant-time code. -extern crate subtle; - -#[cfg(all(test, feature = "serde"))] -extern crate bincode; -#[cfg(feature = "serde")] -extern crate serde; - -// Internal macros. Must come first! -#[macro_use] -pub(crate) mod macros; - -//------------------------------------------------------------------------ -// curve25519-dalek public modules -//------------------------------------------------------------------------ - -// Scalar arithmetic mod l = 2^252 + ..., the order of the Ristretto group -pub mod scalar; - -// Point operations on the Montgomery form of Curve25519 -pub mod montgomery; - -// Point operations on the Edwards form of Curve25519 -pub mod edwards; - -// Group operations on the Ristretto group -pub mod ristretto; - -// Useful constants, like the Ed25519 basepoint -pub mod constants; - -// External (and internal) traits. -pub mod traits; - -//------------------------------------------------------------------------ -// curve25519-dalek internal modules -//------------------------------------------------------------------------ - -// Finite field arithmetic mod p = 2^255 - 19 -pub(crate) mod field; - -// Arithmetic backends (using u32, u64, etc) live here -pub(crate) mod backend; - -// Crate-local prelude (for alloc-dependent features like `Vec`) -pub(crate) mod prelude; - -// Generic code for window lookups -pub(crate) mod window; diff --git a/net/gurk-rs/files/vendor/curve25519-dalek/src/macros.rs b/net/gurk-rs/files/vendor/curve25519-dalek/src/macros.rs deleted file mode 100644 index 84a2ce1..0000000 --- a/net/gurk-rs/files/vendor/curve25519-dalek/src/macros.rs +++ /dev/null @@ -1,124 +0,0 @@ -// -*- mode: rust; -*- -// -// This file is part of curve25519-dalek. -// Copyright (c) 2016-2021 isis agora lovecruft -// Copyright (c) 2016-2019 Henry de Valence -// See LICENSE for licensing information. -// -// Authors: -// - isis agora lovecruft -// - Henry de Valence - -//! Internal macros. - -/// Define borrow and non-borrow variants of `Add`. -macro_rules! define_add_variants { - (LHS = $lhs:ty, RHS = $rhs:ty, Output = $out:ty) => { - impl<'b> Add<&'b $rhs> for $lhs { - type Output = $out; - fn add(self, rhs: &'b $rhs) -> $out { - &self + rhs - } - } - - impl<'a> Add<$rhs> for &'a $lhs { - type Output = $out; - fn add(self, rhs: $rhs) -> $out { - self + &rhs - } - } - - impl Add<$rhs> for $lhs { - type Output = $out; - fn add(self, rhs: $rhs) -> $out { - &self + &rhs - } - } - } -} - -/// Define non-borrow variants of `AddAssign`. -macro_rules! define_add_assign_variants { - (LHS = $lhs:ty, RHS = $rhs:ty) => { - impl AddAssign<$rhs> for $lhs { - fn add_assign(&mut self, rhs: $rhs) { - *self += &rhs; - } - } - } -} - -/// Define borrow and non-borrow variants of `Sub`. -macro_rules! define_sub_variants { - (LHS = $lhs:ty, RHS = $rhs:ty, Output = $out:ty) => { - impl<'b> Sub<&'b $rhs> for $lhs { - type Output = $out; - fn sub(self, rhs: &'b $rhs) -> $out { - &self - rhs - } - } - - impl<'a> Sub<$rhs> for &'a $lhs { - type Output = $out; - fn sub(self, rhs: $rhs) -> $out { - self - &rhs - } - } - - impl Sub<$rhs> for $lhs { - type Output = $out; - fn sub(self, rhs: $rhs) -> $out { - &self - &rhs - } - } - } -} - -/// Define non-borrow variants of `SubAssign`. -macro_rules! define_sub_assign_variants { - (LHS = $lhs:ty, RHS = $rhs:ty) => { - impl SubAssign<$rhs> for $lhs { - fn sub_assign(&mut self, rhs: $rhs) { - *self -= &rhs; - } - } - } -} - -/// Define borrow and non-borrow variants of `Mul`. -macro_rules! define_mul_variants { - (LHS = $lhs:ty, RHS = $rhs:ty, Output = $out:ty) => { - impl<'b> Mul<&'b $rhs> for $lhs { - type Output = $out; - fn mul(self, rhs: &'b $rhs) -> $out { - &self * rhs - } - } - - impl<'a> Mul<$rhs> for &'a $lhs { - type Output = $out; - fn mul(self, rhs: $rhs) -> $out { - self * &rhs - } - } - - impl Mul<$rhs> for $lhs { - type Output = $out; - fn mul(self, rhs: $rhs) -> $out { - &self * &rhs - } - } - } -} - -/// Define non-borrow variants of `MulAssign`. -macro_rules! define_mul_assign_variants { - (LHS = $lhs:ty, RHS = $rhs:ty) => { - impl MulAssign<$rhs> for $lhs { - fn mul_assign(&mut self, rhs: $rhs) { - *self *= &rhs; - } - } - } -} - diff --git a/net/gurk-rs/files/vendor/curve25519-dalek/src/montgomery.rs b/net/gurk-rs/files/vendor/curve25519-dalek/src/montgomery.rs deleted file mode 100644 index de0f8b7..0000000 --- a/net/gurk-rs/files/vendor/curve25519-dalek/src/montgomery.rs +++ /dev/null @@ -1,459 +0,0 @@ -// -*- mode: rust; -*- -// -// This file is part of curve25519-dalek. -// Copyright (c) 2016-2021 isis lovecruft -// Copyright (c) 2016-2019 Henry de Valence -// See LICENSE for licensing information. -// -// Authors: -// - isis agora lovecruft -// - Henry de Valence - -//! Scalar multiplication on the Montgomery form of Curve25519. -//! -//! To avoid notational confusion with the Edwards code, we use -//! variables \\( u, v \\) for the Montgomery curve, so that “Montgomery -//! \\(u\\)” here corresponds to “Montgomery \\(x\\)” elsewhere. -//! -//! Montgomery arithmetic works not on the curve itself, but on the -//! \\(u\\)-line, which discards sign information and unifies the curve -//! and its quadratic twist. See [_Montgomery curves and their -//! arithmetic_][costello-smith] by Costello and Smith for more details. -//! -//! The `MontgomeryPoint` struct contains the affine \\(u\\)-coordinate -//! \\(u\_0(P)\\) of a point \\(P\\) on either the curve or the twist. -//! Here the map \\(u\_0 : \mathcal M \rightarrow \mathbb F\_p \\) is -//! defined by \\(u\_0((u,v)) = u\\); \\(u\_0(\mathcal O) = 0\\). See -//! section 5.4 of Costello-Smith for more details. -//! -//! # Scalar Multiplication -//! -//! Scalar multiplication on `MontgomeryPoint`s is provided by the `*` -//! operator, which implements the Montgomery ladder. -//! -//! # Edwards Conversion -//! -//! The \\(2\\)-to-\\(1\\) map from the Edwards model to the Montgomery -//! \\(u\\)-line is provided by `EdwardsPoint::to_montgomery()`. -//! -//! To lift a `MontgomeryPoint` to an `EdwardsPoint`, use -//! `MontgomeryPoint::to_edwards()`, which takes a sign parameter. -//! This function rejects `MontgomeryPoints` which correspond to points -//! on the twist. -//! -//! [costello-smith]: https://eprint.iacr.org/2017/212.pdf - -// We allow non snake_case names because coordinates in projective space are -// traditionally denoted by the capitalisation of their respective -// counterparts in affine space. Yeah, you heard me, rustc, I'm gonna have my -// affine and projective cakes and eat both of them too. -#![allow(non_snake_case)] - -use core::ops::{Mul, MulAssign}; - -use constants::{APLUS2_OVER_FOUR, MONTGOMERY_A, MONTGOMERY_A_NEG}; -use edwards::{CompressedEdwardsY, EdwardsPoint}; -use field::FieldElement; -use scalar::Scalar; - -use traits::Identity; - -use subtle::Choice; -use subtle::ConstantTimeEq; -use subtle::{ConditionallyNegatable, ConditionallySelectable}; - -use zeroize::Zeroize; - -/// Holds the \\(u\\)-coordinate of a point on the Montgomery form of -/// Curve25519 or its twist. -#[derive(Copy, Clone, Debug, Hash)] -#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] -pub struct MontgomeryPoint(pub [u8; 32]); - -/// Equality of `MontgomeryPoint`s is defined mod p. -impl ConstantTimeEq for MontgomeryPoint { - fn ct_eq(&self, other: &MontgomeryPoint) -> Choice { - let self_fe = FieldElement::from_bytes(&self.0); - let other_fe = FieldElement::from_bytes(&other.0); - - self_fe.ct_eq(&other_fe) - } -} - -impl Default for MontgomeryPoint { - fn default() -> MontgomeryPoint { - MontgomeryPoint([0u8; 32]) - } -} - -impl PartialEq for MontgomeryPoint { - fn eq(&self, other: &MontgomeryPoint) -> bool { - self.ct_eq(other).unwrap_u8() == 1u8 - } -} - -impl Eq for MontgomeryPoint {} - -impl Zeroize for MontgomeryPoint { - fn zeroize(&mut self) { - self.0.zeroize(); - } -} - -impl MontgomeryPoint { - /// View this `MontgomeryPoint` as an array of bytes. - pub fn as_bytes<'a>(&'a self) -> &'a [u8; 32] { - &self.0 - } - - /// Convert this `MontgomeryPoint` to an array of bytes. - pub fn to_bytes(&self) -> [u8; 32] { - self.0 - } - - /// Attempt to convert to an `EdwardsPoint`, using the supplied - /// choice of sign for the `EdwardsPoint`. - /// - /// # Inputs - /// - /// * `sign`: a `u8` donating the desired sign of the resulting - /// `EdwardsPoint`. `0` denotes positive and `1` negative. - /// - /// # Return - /// - /// * `Some(EdwardsPoint)` if `self` is the \\(u\\)-coordinate of a - /// point on (the Montgomery form of) Curve25519; - /// - /// * `None` if `self` is the \\(u\\)-coordinate of a point on the - /// twist of (the Montgomery form of) Curve25519; - /// - pub fn to_edwards(&self, sign: u8) -> Option { - // To decompress the Montgomery u coordinate to an - // `EdwardsPoint`, we apply the birational map to obtain the - // Edwards y coordinate, then do Edwards decompression. - // - // The birational map is y = (u-1)/(u+1). - // - // The exceptional points are the zeros of the denominator, - // i.e., u = -1. - // - // But when u = -1, v^2 = u*(u^2+486662*u+1) = 486660. - // - // Since this is nonsquare mod p, u = -1 corresponds to a point - // on the twist, not the curve, so we can reject it early. - - let u = FieldElement::from_bytes(&self.0); - - if u == FieldElement::minus_one() { return None; } - - let one = FieldElement::one(); - - let y = &(&u - &one) * &(&u + &one).invert(); - - let mut y_bytes = y.to_bytes(); - y_bytes[31] ^= sign << 7; - - CompressedEdwardsY(y_bytes).decompress() - } -} - -/// Perform the Elligator2 mapping to a Montgomery point. -/// -/// See https://tools.ietf.org/html/draft-irtf-cfrg-hash-to-curve-10#section-6.7.1 -// -// TODO Determine how much of the hash-to-group API should be exposed after the CFRG -// draft gets into a more polished/accepted state. -#[allow(unused)] -pub(crate) fn elligator_encode(r_0: &FieldElement) -> MontgomeryPoint { - let one = FieldElement::one(); - let d_1 = &one + &r_0.square2(); /* 2r^2 */ - - let d = &MONTGOMERY_A_NEG * &(d_1.invert()); /* A/(1+2r^2) */ - - let d_sq = &d.square(); - let au = &MONTGOMERY_A * &d; - - let inner = &(d_sq + &au) + &one; - let eps = &d * &inner; /* eps = d^3 + Ad^2 + d */ - - let (eps_is_sq, _eps) = FieldElement::sqrt_ratio_i(&eps, &one); - - let zero = FieldElement::zero(); - let Atemp = FieldElement::conditional_select(&MONTGOMERY_A, &zero, eps_is_sq); /* 0, or A if nonsquare*/ - let mut u = &d + &Atemp; /* d, or d+A if nonsquare */ - u.conditional_negate(!eps_is_sq); /* d, or -d-A if nonsquare */ - - MontgomeryPoint(u.to_bytes()) -} - -/// A `ProjectivePoint` holds a point on the projective line -/// \\( \mathbb P(\mathbb F\_p) \\), which we identify with the Kummer -/// line of the Montgomery curve. -#[derive(Copy, Clone, Debug)] -struct ProjectivePoint { - pub U: FieldElement, - pub W: FieldElement, -} - -impl Identity for ProjectivePoint { - fn identity() -> ProjectivePoint { - ProjectivePoint { - U: FieldElement::one(), - W: FieldElement::zero(), - } - } -} - -impl Default for ProjectivePoint { - fn default() -> ProjectivePoint { - ProjectivePoint::identity() - } -} - -impl ConditionallySelectable for ProjectivePoint { - fn conditional_select( - a: &ProjectivePoint, - b: &ProjectivePoint, - choice: Choice, - ) -> ProjectivePoint { - ProjectivePoint { - U: FieldElement::conditional_select(&a.U, &b.U, choice), - W: FieldElement::conditional_select(&a.W, &b.W, choice), - } - } -} - -impl ProjectivePoint { - /// Dehomogenize this point to affine coordinates. - /// - /// # Return - /// - /// * \\( u = U / W \\) if \\( W \neq 0 \\); - /// * \\( 0 \\) if \\( W \eq 0 \\); - pub fn to_affine(&self) -> MontgomeryPoint { - let u = &self.U * &self.W.invert(); - MontgomeryPoint(u.to_bytes()) - } -} - -/// Perform the double-and-add step of the Montgomery ladder. -/// -/// Given projective points -/// \\( (U\_P : W\_P) = u(P) \\), -/// \\( (U\_Q : W\_Q) = u(Q) \\), -/// and the affine difference -/// \\( u\_{P-Q} = u(P-Q) \\), set -/// $$ -/// (U\_P : W\_P) \gets u([2]P) -/// $$ -/// and -/// $$ -/// (U\_Q : W\_Q) \gets u(P + Q). -/// $$ -fn differential_add_and_double( - P: &mut ProjectivePoint, - Q: &mut ProjectivePoint, - affine_PmQ: &FieldElement, -) { - let t0 = &P.U + &P.W; - let t1 = &P.U - &P.W; - let t2 = &Q.U + &Q.W; - let t3 = &Q.U - &Q.W; - - let t4 = t0.square(); // (U_P + W_P)^2 = U_P^2 + 2 U_P W_P + W_P^2 - let t5 = t1.square(); // (U_P - W_P)^2 = U_P^2 - 2 U_P W_P + W_P^2 - - let t6 = &t4 - &t5; // 4 U_P W_P - - let t7 = &t0 * &t3; // (U_P + W_P) (U_Q - W_Q) = U_P U_Q + W_P U_Q - U_P W_Q - W_P W_Q - let t8 = &t1 * &t2; // (U_P - W_P) (U_Q + W_Q) = U_P U_Q - W_P U_Q + U_P W_Q - W_P W_Q - - let t9 = &t7 + &t8; // 2 (U_P U_Q - W_P W_Q) - let t10 = &t7 - &t8; // 2 (W_P U_Q - U_P W_Q) - - let t11 = t9.square(); // 4 (U_P U_Q - W_P W_Q)^2 - let t12 = t10.square(); // 4 (W_P U_Q - U_P W_Q)^2 - - let t13 = &APLUS2_OVER_FOUR * &t6; // (A + 2) U_P U_Q - - let t14 = &t4 * &t5; // ((U_P + W_P)(U_P - W_P))^2 = (U_P^2 - W_P^2)^2 - let t15 = &t13 + &t5; // (U_P - W_P)^2 + (A + 2) U_P W_P - - let t16 = &t6 * &t15; // 4 (U_P W_P) ((U_P - W_P)^2 + (A + 2) U_P W_P) - - let t17 = affine_PmQ * &t12; // U_D * 4 (W_P U_Q - U_P W_Q)^2 - let t18 = t11; // W_D * 4 (U_P U_Q - W_P W_Q)^2 - - P.U = t14; // U_{P'} = (U_P + W_P)^2 (U_P - W_P)^2 - P.W = t16; // W_{P'} = (4 U_P W_P) ((U_P - W_P)^2 + ((A + 2)/4) 4 U_P W_P) - Q.U = t18; // U_{Q'} = W_D * 4 (U_P U_Q - W_P W_Q)^2 - Q.W = t17; // W_{Q'} = U_D * 4 (W_P U_Q - U_P W_Q)^2 -} - -define_mul_assign_variants!(LHS = MontgomeryPoint, RHS = Scalar); - -define_mul_variants!(LHS = MontgomeryPoint, RHS = Scalar, Output = MontgomeryPoint); -define_mul_variants!(LHS = Scalar, RHS = MontgomeryPoint, Output = MontgomeryPoint); - -/// Multiply this `MontgomeryPoint` by a `Scalar`. -impl<'a, 'b> Mul<&'b Scalar> for &'a MontgomeryPoint { - type Output = MontgomeryPoint; - - /// Given `self` \\( = u\_0(P) \\), and a `Scalar` \\(n\\), return \\( u\_0([n]P) \\). - fn mul(self, scalar: &'b Scalar) -> MontgomeryPoint { - // Algorithm 8 of Costello-Smith 2017 - let affine_u = FieldElement::from_bytes(&self.0); - let mut x0 = ProjectivePoint::identity(); - let mut x1 = ProjectivePoint { - U: affine_u, - W: FieldElement::one(), - }; - - let bits: [i8; 256] = scalar.bits(); - - for i in (0..255).rev() { - let choice: u8 = (bits[i + 1] ^ bits[i]) as u8; - - debug_assert!(choice == 0 || choice == 1); - - ProjectivePoint::conditional_swap(&mut x0, &mut x1, choice.into()); - differential_add_and_double(&mut x0, &mut x1, &affine_u); - } - ProjectivePoint::conditional_swap(&mut x0, &mut x1, Choice::from(bits[0] as u8)); - - x0.to_affine() - } -} - -impl<'b> MulAssign<&'b Scalar> for MontgomeryPoint { - fn mul_assign(&mut self, scalar: &'b Scalar) { - *self = (self as &MontgomeryPoint) * scalar; - } -} - -impl<'a, 'b> Mul<&'b MontgomeryPoint> for &'a Scalar { - type Output = MontgomeryPoint; - - fn mul(self, point: &'b MontgomeryPoint) -> MontgomeryPoint { - point * self - } -} - -// ------------------------------------------------------------------------ -// Tests -// ------------------------------------------------------------------------ - -#[cfg(test)] -mod test { - use super::*; - use constants; - use core::convert::TryInto; - - use rand_core::OsRng; - - #[test] - #[cfg(feature = "serde")] - fn serde_bincode_basepoint_roundtrip() { - use bincode; - - let encoded = bincode::serialize(&constants::X25519_BASEPOINT).unwrap(); - let decoded: MontgomeryPoint = bincode::deserialize(&encoded).unwrap(); - - assert_eq!(encoded.len(), 32); - assert_eq!(decoded, constants::X25519_BASEPOINT); - - let raw_bytes = constants::X25519_BASEPOINT.as_bytes(); - let bp: MontgomeryPoint = bincode::deserialize(raw_bytes).unwrap(); - assert_eq!(bp, constants::X25519_BASEPOINT); - } - - /// Test Montgomery -> Edwards on the X/Ed25519 basepoint - #[test] - fn basepoint_montgomery_to_edwards() { - // sign bit = 0 => basepoint - assert_eq!( - constants::ED25519_BASEPOINT_POINT, - constants::X25519_BASEPOINT.to_edwards(0).unwrap() - ); - // sign bit = 1 => minus basepoint - assert_eq!( - - constants::ED25519_BASEPOINT_POINT, - constants::X25519_BASEPOINT.to_edwards(1).unwrap() - ); - } - - /// Test Edwards -> Montgomery on the X/Ed25519 basepoint - #[test] - fn basepoint_edwards_to_montgomery() { - assert_eq!( - constants::ED25519_BASEPOINT_POINT.to_montgomery(), - constants::X25519_BASEPOINT - ); - } - - /// Check that Montgomery -> Edwards fails for points on the twist. - #[test] - fn montgomery_to_edwards_rejects_twist() { - let one = FieldElement::one(); - - // u = 2 corresponds to a point on the twist. - let two = MontgomeryPoint((&one+&one).to_bytes()); - - assert!(two.to_edwards(0).is_none()); - - // u = -1 corresponds to a point on the twist, but should be - // checked explicitly because it's an exceptional point for the - // birational map. For instance, libsignal will accept it. - let minus_one = MontgomeryPoint((-&one).to_bytes()); - - assert!(minus_one.to_edwards(0).is_none()); - } - - #[test] - fn eq_defined_mod_p() { - let mut u18_bytes = [0u8; 32]; u18_bytes[0] = 18; - let u18 = MontgomeryPoint(u18_bytes); - let u18_unred = MontgomeryPoint([255; 32]); - - assert_eq!(u18, u18_unred); - } - - #[test] - fn montgomery_ladder_matches_edwards_scalarmult() { - let mut csprng: OsRng = OsRng; - - let s: Scalar = Scalar::random(&mut csprng); - let p_edwards: EdwardsPoint = &constants::ED25519_BASEPOINT_TABLE * &s; - let p_montgomery: MontgomeryPoint = p_edwards.to_montgomery(); - - let expected = s * p_edwards; - let result = s * p_montgomery; - - assert_eq!(result, expected.to_montgomery()) - } - - const ELLIGATOR_CORRECT_OUTPUT: [u8; 32] = [ - 0x5f, 0x35, 0x20, 0x00, 0x1c, 0x6c, 0x99, 0x36, 0xa3, 0x12, 0x06, 0xaf, 0xe7, 0xc7, 0xac, - 0x22, 0x4e, 0x88, 0x61, 0x61, 0x9b, 0xf9, 0x88, 0x72, 0x44, 0x49, 0x15, 0x89, 0x9d, 0x95, - 0xf4, 0x6e, - ]; - - #[test] - #[cfg(feature = "std")] // Vec - fn montgomery_elligator_correct() { - let bytes: std::vec::Vec = (0u8..32u8).collect(); - let bits_in: [u8; 32] = (&bytes[..]).try_into().expect("Range invariant broken"); - - let fe = FieldElement::from_bytes(&bits_in); - let eg = elligator_encode(&fe); - assert_eq!(eg.to_bytes(), ELLIGATOR_CORRECT_OUTPUT); - } - - #[test] - fn montgomery_elligator_zero_zero() { - let zero = [0u8; 32]; - let fe = FieldElement::from_bytes(&zero); - let eg = elligator_encode(&fe); - assert_eq!(eg.to_bytes(), zero); - } -} diff --git a/net/gurk-rs/files/vendor/curve25519-dalek/src/prelude.rs b/net/gurk-rs/files/vendor/curve25519-dalek/src/prelude.rs deleted file mode 100644 index 5c0a611..0000000 --- a/net/gurk-rs/files/vendor/curve25519-dalek/src/prelude.rs +++ /dev/null @@ -1,19 +0,0 @@ -// -*- mode: rust; -*- -// -// This file is part of curve25519-dalek. -// Copyright (c) 2016-2021 isis lovecruft -// Copyright (c) 2016-2019 Henry de Valence -// See LICENSE for licensing information. -// -// Authors: -// - isis agora lovecruft -// - Henry de Valence - -//! Crate-local prelude (for alloc-dependent features like `Vec`) - -// TODO: switch to alloc::prelude -#[cfg(all(feature = "alloc", not(feature = "std")))] -pub use alloc::vec::Vec; - -#[cfg(feature = "std")] -pub use std::vec::Vec; diff --git a/net/gurk-rs/files/vendor/curve25519-dalek/src/ristretto.rs b/net/gurk-rs/files/vendor/curve25519-dalek/src/ristretto.rs deleted file mode 100644 index d284b5b..0000000 --- a/net/gurk-rs/files/vendor/curve25519-dalek/src/ristretto.rs +++ /dev/null @@ -1,1366 +0,0 @@ -// -*- mode: rust; -*- -// -// This file is part of curve25519-dalek. -// Copyright (c) 2016-2021 isis lovecruft -// Copyright (c) 2016-2020 Henry de Valence -// See LICENSE for licensing information. -// -// Authors: -// - isis agora lovecruft -// - Henry de Valence - -// We allow non snake_case names because coordinates in projective space are -// traditionally denoted by the capitalisation of their respective -// counterparts in affine space. Yeah, you heard me, rustc, I'm gonna have my -// affine and projective cakes and eat both of them too. -#![allow(non_snake_case)] - -//! An implementation of [Ristretto][ristretto_main], which provides a -//! prime-order group. -//! -//! # The Ristretto Group -//! -//! Ristretto is a modification of Mike Hamburg's Decaf scheme to work -//! with cofactor-\\(8\\) curves, such as Curve25519. -//! -//! The introduction of the Decaf paper, [_Decaf: -//! Eliminating cofactors through point -//! compression_](https://eprint.iacr.org/2015/673.pdf), notes that while -//! most cryptographic systems require a group of prime order, most -//! concrete implementations using elliptic curve groups fall short – -//! they either provide a group of prime order, but with incomplete or -//! variable-time addition formulae (for instance, most Weierstrass -//! models), or else they provide a fast and safe implementation of a -//! group whose order is not quite a prime \\(q\\), but \\(hq\\) for a -//! small cofactor \\(h\\) (for instance, Edwards curves, which have -//! cofactor at least \\(4\\)). -//! -//! This abstraction mismatch is commonly “handled” by pushing the -//! complexity upwards, adding ad-hoc protocol modifications. But -//! these modifications require careful analysis and are a recurring -//! source of [vulnerabilities][cryptonote] and [design -//! complications][ed25519_hkd]. -//! -//! Instead, Decaf (and Ristretto) use a quotient group to implement a -//! prime-order group using a non-prime-order curve. This provides -//! the correct abstraction for cryptographic systems, while retaining -//! the speed and safety benefits of an Edwards curve. -//! -//! Decaf is named “after the procedure which divides the effect of -//! coffee by \\(4\\)”. However, Curve25519 has a cofactor of -//! \\(8\\). To eliminate its cofactor, Ristretto restricts further; -//! this [additional restriction][ristretto_coffee] gives the -//! _Ristretto_ encoding. -//! -//! More details on why Ristretto is necessary can be found in the -//! [Why Ristretto?][why_ristretto] section of the Ristretto website. -//! -//! Ristretto -//! points are provided in `curve25519-dalek` by the `RistrettoPoint` -//! struct. -//! -//! ## Encoding and Decoding -//! -//! Encoding is done by converting to and from a `CompressedRistretto` -//! struct, which is a typed wrapper around `[u8; 32]`. -//! -//! The encoding is not batchable, but it is possible to -//! double-and-encode in a batch using -//! `RistrettoPoint::double_and_compress_batch`. -//! -//! ## Equality Testing -//! -//! Testing equality of points on an Edwards curve in projective -//! coordinates requires an expensive inversion. By contrast, equality -//! checking in the Ristretto group can be done in projective -//! coordinates without requiring an inversion, so it is much faster. -//! -//! The `RistrettoPoint` struct implements the -//! `subtle::ConstantTimeEq` trait for constant-time equality -//! checking, and the Rust `Eq` trait for variable-time equality -//! checking. -//! -//! ## Scalars -//! -//! Scalars are represented by the `Scalar` struct. Each scalar has a -//! canonical representative mod the group order. To attempt to load -//! a supposedly-canonical scalar, use -//! `Scalar::from_canonical_bytes()`. To check whether a -//! representative is canonical, use `Scalar::is_canonical()`. -//! -//! ## Scalar Multiplication -//! -//! Scalar multiplication on Ristretto points is provided by: -//! -//! * the `*` operator between a `Scalar` and a `RistrettoPoint`, which -//! performs constant-time variable-base scalar multiplication; -//! -//! * the `*` operator between a `Scalar` and a -//! `RistrettoBasepointTable`, which performs constant-time fixed-base -//! scalar multiplication; -//! -//! * an implementation of the -//! [`MultiscalarMul`](../traits/trait.MultiscalarMul.html) trait for -//! constant-time variable-base multiscalar multiplication; -//! -//! * an implementation of the -//! [`VartimeMultiscalarMul`](../traits/trait.VartimeMultiscalarMul.html) -//! trait for variable-time variable-base multiscalar multiplication; -//! -//! ## Random Points and Hashing to Ristretto -//! -//! The Ristretto group comes equipped with an Elligator map. This is -//! used to implement -//! -//! * `RistrettoPoint::random()`, which generates random points from an -//! RNG; -//! -//! * `RistrettoPoint::from_hash()` and -//! `RistrettoPoint::hash_from_bytes()`, which perform hashing to the -//! group. -//! -//! The Elligator map itself is not currently exposed. -//! -//! ## Implementation -//! -//! The Decaf suggestion is to use a quotient group, such as \\(\mathcal -//! E / \mathcal E[4]\\) or \\(2 \mathcal E / \mathcal E[2] \\), to -//! implement a prime-order group using a non-prime-order curve. -//! -//! This requires only changing -//! -//! 1. the function for equality checking (so that two representatives -//! of the same coset are considered equal); -//! 2. the function for encoding (so that two representatives of the -//! same coset are encoded as identical bitstrings); -//! 3. the function for decoding (so that only the canonical encoding of -//! a coset is accepted). -//! -//! Internally, each coset is represented by a curve point; two points -//! \\( P, Q \\) may represent the same coset in the same way that two -//! points with different \\(X,Y,Z\\) coordinates may represent the -//! same point. The group operations are carried out with no overhead -//! using Edwards formulas. -//! -//! Notes on the details of the encoding can be found in the -//! [Details][ristretto_notes] section of the Ristretto website. -//! -//! [cryptonote]: -//! https://moderncrypto.org/mail-archive/curves/2017/000898.html -//! [ed25519_hkd]: -//! https://moderncrypto.org/mail-archive/curves/2017/000858.html -//! [ristretto_coffee]: -//! https://en.wikipedia.org/wiki/Ristretto -//! [ristretto_notes]: -//! https://ristretto.group/details/index.html -//! [why_ristretto]: -//! https://ristretto.group/why_ristretto.html -//! [ristretto_main]: -//! https://ristretto.group/ - -use core::borrow::Borrow; -use core::fmt::Debug; -use core::iter::Sum; -use core::ops::{Add, Neg, Sub}; -use core::ops::{AddAssign, SubAssign}; -use core::ops::{Mul, MulAssign}; - -use rand_core::{CryptoRng, RngCore}; - -use digest::generic_array::typenum::U64; -use digest::Digest; - -use constants; -use field::FieldElement; - -use subtle::Choice; -use subtle::ConditionallySelectable; -use subtle::ConditionallyNegatable; -use subtle::ConstantTimeEq; - -use edwards::EdwardsBasepointTable; -use edwards::EdwardsPoint; - -#[allow(unused_imports)] -use prelude::*; - -use scalar::Scalar; - -use traits::Identity; -#[cfg(any(feature = "alloc", feature = "std"))] -use traits::{MultiscalarMul, VartimeMultiscalarMul, VartimePrecomputedMultiscalarMul}; - -#[cfg(not(all( - feature = "simd_backend", - any(target_feature = "avx2", target_feature = "avx512ifma") -)))] -use backend::serial::scalar_mul; -#[cfg(all( - feature = "simd_backend", - any(target_feature = "avx2", target_feature = "avx512ifma") -))] -use backend::vector::scalar_mul; - -// ------------------------------------------------------------------------ -// Compressed points -// ------------------------------------------------------------------------ - -/// A Ristretto point, in compressed wire format. -/// -/// The Ristretto encoding is canonical, so two points are equal if and -/// only if their encodings are equal. -#[derive(Copy, Clone, Eq, PartialEq, Hash)] -pub struct CompressedRistretto(pub [u8; 32]); - -impl ConstantTimeEq for CompressedRistretto { - fn ct_eq(&self, other: &CompressedRistretto) -> Choice { - self.as_bytes().ct_eq(other.as_bytes()) - } -} - -impl CompressedRistretto { - /// Copy the bytes of this `CompressedRistretto`. - pub fn to_bytes(&self) -> [u8; 32] { - self.0 - } - - /// View this `CompressedRistretto` as an array of bytes. - pub fn as_bytes(&self) -> &[u8; 32] { - &self.0 - } - - /// Construct a `CompressedRistretto` from a slice of bytes. - /// - /// # Panics - /// - /// If the input `bytes` slice does not have a length of 32. - pub fn from_slice(bytes: &[u8]) -> CompressedRistretto { - let mut tmp = [0u8; 32]; - - tmp.copy_from_slice(bytes); - - CompressedRistretto(tmp) - } - - /// Attempt to decompress to an `RistrettoPoint`. - /// - /// # Return - /// - /// - `Some(RistrettoPoint)` if `self` was the canonical encoding of a point; - /// - /// - `None` if `self` was not the canonical encoding of a point. - pub fn decompress(&self) -> Option { - // Step 1. Check s for validity: - // 1.a) s must be 32 bytes (we get this from the type system) - // 1.b) s < p - // 1.c) s is nonnegative - // - // Our decoding routine ignores the high bit, so the only - // possible failure for 1.b) is if someone encodes s in 0..18 - // as s+p in 2^255-19..2^255-1. We can check this by - // converting back to bytes, and checking that we get the - // original input, since our encoding routine is canonical. - - let s = FieldElement::from_bytes(self.as_bytes()); - let s_bytes_check = s.to_bytes(); - let s_encoding_is_canonical = - &s_bytes_check[..].ct_eq(self.as_bytes()); - let s_is_negative = s.is_negative(); - - if s_encoding_is_canonical.unwrap_u8() == 0u8 || s_is_negative.unwrap_u8() == 1u8 { - return None; - } - - // Step 2. Compute (X:Y:Z:T). - let one = FieldElement::one(); - let ss = s.square(); - let u1 = &one - &ss; // 1 + as² - let u2 = &one + &ss; // 1 - as² where a=-1 - let u2_sqr = u2.square(); // (1 - as²)² - - // v == ad(1+as²)² - (1-as²)² where d=-121665/121666 - let v = &(&(-&constants::EDWARDS_D) * &u1.square()) - &u2_sqr; - - let (ok, I) = (&v * &u2_sqr).invsqrt(); // 1/sqrt(v*u_2²) - - let Dx = &I * &u2; // 1/sqrt(v) - let Dy = &I * &(&Dx * &v); // 1/u2 - - // x == | 2s/sqrt(v) | == + sqrt(4s²/(ad(1+as²)² - (1-as²)²)) - let mut x = &(&s + &s) * &Dx; - let x_neg = x.is_negative(); - x.conditional_negate(x_neg); - - // y == (1-as²)/(1+as²) - let y = &u1 * &Dy; - - // t == ((1+as²) sqrt(4s²/(ad(1+as²)² - (1-as²)²)))/(1-as²) - let t = &x * &y; - - if ok.unwrap_u8() == 0u8 || t.is_negative().unwrap_u8() == 1u8 || y.is_zero().unwrap_u8() == 1u8 { - None - } else { - Some(RistrettoPoint(EdwardsPoint{X: x, Y: y, Z: one, T: t})) - } - } -} - -impl Identity for CompressedRistretto { - fn identity() -> CompressedRistretto { - CompressedRistretto([0u8; 32]) - } -} - -impl Default for CompressedRistretto { - fn default() -> CompressedRistretto { - CompressedRistretto::identity() - } -} - -// ------------------------------------------------------------------------ -// Serde support -// ------------------------------------------------------------------------ -// Serializes to and from `RistrettoPoint` directly, doing compression -// and decompression internally. This means that users can create -// structs containing `RistrettoPoint`s and use Serde's derived -// serializers to serialize those structures. - -#[cfg(feature = "serde")] -use serde::{self, Serialize, Deserialize, Serializer, Deserializer}; -#[cfg(feature = "serde")] -use serde::de::Visitor; - -#[cfg(feature = "serde")] -impl Serialize for RistrettoPoint { - fn serialize(&self, serializer: S) -> Result - where S: Serializer - { - use serde::ser::SerializeTuple; - let mut tup = serializer.serialize_tuple(32)?; - for byte in self.compress().as_bytes().iter() { - tup.serialize_element(byte)?; - } - tup.end() - } -} - -#[cfg(feature = "serde")] -impl Serialize for CompressedRistretto { - fn serialize(&self, serializer: S) -> Result - where S: Serializer - { - use serde::ser::SerializeTuple; - let mut tup = serializer.serialize_tuple(32)?; - for byte in self.as_bytes().iter() { - tup.serialize_element(byte)?; - } - tup.end() - } -} - -#[cfg(feature = "serde")] -impl<'de> Deserialize<'de> for RistrettoPoint { - fn deserialize(deserializer: D) -> Result - where D: Deserializer<'de> - { - struct RistrettoPointVisitor; - - impl<'de> Visitor<'de> for RistrettoPointVisitor { - type Value = RistrettoPoint; - - fn expecting(&self, formatter: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { - formatter.write_str("a valid point in Ristretto format") - } - - fn visit_seq(self, mut seq: A) -> Result - where A: serde::de::SeqAccess<'de> - { - let mut bytes = [0u8; 32]; - for i in 0..32 { - bytes[i] = seq.next_element()? - .ok_or(serde::de::Error::invalid_length(i, &"expected 32 bytes"))?; - } - CompressedRistretto(bytes) - .decompress() - .ok_or(serde::de::Error::custom("decompression failed")) - } - } - - deserializer.deserialize_tuple(32, RistrettoPointVisitor) - } -} - -#[cfg(feature = "serde")] -impl<'de> Deserialize<'de> for CompressedRistretto { - fn deserialize(deserializer: D) -> Result - where D: Deserializer<'de> - { - struct CompressedRistrettoVisitor; - - impl<'de> Visitor<'de> for CompressedRistrettoVisitor { - type Value = CompressedRistretto; - - fn expecting(&self, formatter: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { - formatter.write_str("32 bytes of data") - } - - fn visit_seq(self, mut seq: A) -> Result - where A: serde::de::SeqAccess<'de> - { - let mut bytes = [0u8; 32]; - for i in 0..32 { - bytes[i] = seq.next_element()? - .ok_or(serde::de::Error::invalid_length(i, &"expected 32 bytes"))?; - } - Ok(CompressedRistretto(bytes)) - } - } - - deserializer.deserialize_tuple(32, CompressedRistrettoVisitor) - } -} - -// ------------------------------------------------------------------------ -// Internal point representations -// ------------------------------------------------------------------------ - -/// A `RistrettoPoint` represents a point in the Ristretto group for -/// Curve25519. Ristretto, a variant of Decaf, constructs a -/// prime-order group as a quotient group of a subgroup of (the -/// Edwards form of) Curve25519. -/// -/// Internally, a `RistrettoPoint` is implemented as a wrapper type -/// around `EdwardsPoint`, with custom equality, compression, and -/// decompression routines to account for the quotient. This means that -/// operations on `RistrettoPoint`s are exactly as fast as operations on -/// `EdwardsPoint`s. -/// -#[derive(Copy, Clone)] -pub struct RistrettoPoint(pub(crate) EdwardsPoint); - -impl RistrettoPoint { - /// Compress this point using the Ristretto encoding. - pub fn compress(&self) -> CompressedRistretto { - let mut X = self.0.X; - let mut Y = self.0.Y; - let Z = &self.0.Z; - let T = &self.0.T; - - let u1 = &(Z + &Y) * &(Z - &Y); - let u2 = &X * &Y; - // Ignore return value since this is always square - let (_, invsqrt) = (&u1 * &u2.square()).invsqrt(); - let i1 = &invsqrt * &u1; - let i2 = &invsqrt * &u2; - let z_inv = &i1 * &(&i2 * T); - let mut den_inv = i2; - - let iX = &X * &constants::SQRT_M1; - let iY = &Y * &constants::SQRT_M1; - let ristretto_magic = &constants::INVSQRT_A_MINUS_D; - let enchanted_denominator = &i1 * ristretto_magic; - - let rotate = (T * &z_inv).is_negative(); - - X.conditional_assign(&iY, rotate); - Y.conditional_assign(&iX, rotate); - den_inv.conditional_assign(&enchanted_denominator, rotate); - - Y.conditional_negate((&X * &z_inv).is_negative()); - - let mut s = &den_inv * &(Z - &Y); - let s_is_negative = s.is_negative(); - s.conditional_negate(s_is_negative); - - CompressedRistretto(s.to_bytes()) - } - - /// Double-and-compress a batch of points. The Ristretto encoding - /// is not batchable, since it requires an inverse square root. - /// - /// However, given input points \\( P\_1, \ldots, P\_n, \\) - /// it is possible to compute the encodings of their doubles \\( - /// \mathrm{enc}( [2]P\_1), \ldots, \mathrm{enc}( [2]P\_n ) \\) - /// in a batch. - /// - /// ``` - /// # extern crate curve25519_dalek; - /// # use curve25519_dalek::ristretto::RistrettoPoint; - /// extern crate rand_core; - /// use rand_core::OsRng; - /// - /// # // Need fn main() here in comment so the doctest compiles - /// # // See https://doc.rust-lang.org/book/documentation.html#documentation-as-tests - /// # fn main() { - /// let mut rng = OsRng; - /// let points: Vec = - /// (0..32).map(|_| RistrettoPoint::random(&mut rng)).collect(); - /// - /// let compressed = RistrettoPoint::double_and_compress_batch(&points); - /// - /// for (P, P2_compressed) in points.iter().zip(compressed.iter()) { - /// assert_eq!(*P2_compressed, (P + P).compress()); - /// } - /// # } - /// ``` - #[cfg(feature = "alloc")] - pub fn double_and_compress_batch<'a, I>(points: I) -> Vec - where I: IntoIterator - { - #[derive(Copy, Clone, Debug)] - struct BatchCompressState { - e: FieldElement, - f: FieldElement, - g: FieldElement, - h: FieldElement, - eg: FieldElement, - fh: FieldElement, - } - - impl BatchCompressState { - fn efgh(&self) -> FieldElement { - &self.eg * &self.fh - } - } - - impl<'a> From<&'a RistrettoPoint> for BatchCompressState { - fn from(P: &'a RistrettoPoint) -> BatchCompressState { - let XX = P.0.X.square(); - let YY = P.0.Y.square(); - let ZZ = P.0.Z.square(); - let dTT = &P.0.T.square() * &constants::EDWARDS_D; - - let e = &P.0.X * &(&P.0.Y + &P.0.Y); // = 2*X*Y - let f = &ZZ + &dTT; // = Z^2 + d*T^2 - let g = &YY + &XX; // = Y^2 - a*X^2 - let h = &ZZ - &dTT; // = Z^2 - d*T^2 - - let eg = &e * &g; - let fh = &f * &h; - - BatchCompressState{ e, f, g, h, eg, fh } - } - } - - let states: Vec = points.into_iter().map(BatchCompressState::from).collect(); - - let mut invs: Vec = states.iter().map(|state| state.efgh()).collect(); - - FieldElement::batch_invert(&mut invs[..]); - - states.iter().zip(invs.iter()).map(|(state, inv): (&BatchCompressState, &FieldElement)| { - let Zinv = &state.eg * &inv; - let Tinv = &state.fh * &inv; - - let mut magic = constants::INVSQRT_A_MINUS_D; - - let negcheck1 = (&state.eg * &Zinv).is_negative(); - - let mut e = state.e; - let mut g = state.g; - let mut h = state.h; - - let minus_e = -&e; - let f_times_sqrta = &state.f * &constants::SQRT_M1; - - e.conditional_assign(&state.g, negcheck1); - g.conditional_assign(&minus_e, negcheck1); - h.conditional_assign(&f_times_sqrta, negcheck1); - - magic.conditional_assign(&constants::SQRT_M1, negcheck1); - - let negcheck2 = (&(&h * &e) * &Zinv).is_negative(); - - g.conditional_negate(negcheck2); - - let mut s = &(&h - &g) * &(&magic * &(&g * &Tinv)); - - let s_is_negative = s.is_negative(); - s.conditional_negate(s_is_negative); - - CompressedRistretto(s.to_bytes()) - }).collect() - } - - - /// Return the coset self + E[4], for debugging. - fn coset4(&self) -> [EdwardsPoint; 4] { - [ self.0 - , &self.0 + &constants::EIGHT_TORSION[2] - , &self.0 + &constants::EIGHT_TORSION[4] - , &self.0 + &constants::EIGHT_TORSION[6] - ] - } - - /// Computes the Ristretto Elligator map. - /// - /// # Note - /// - /// This method is not public because it's just used for hashing - /// to a point -- proper elligator support is deferred for now. - pub(crate) fn elligator_ristretto_flavor(r_0: &FieldElement) -> RistrettoPoint { - let i = &constants::SQRT_M1; - let d = &constants::EDWARDS_D; - let one_minus_d_sq = &constants::ONE_MINUS_EDWARDS_D_SQUARED; - let d_minus_one_sq = &constants::EDWARDS_D_MINUS_ONE_SQUARED; - let mut c = constants::MINUS_ONE; - - let one = FieldElement::one(); - - let r = i * &r_0.square(); - let N_s = &(&r + &one) * &one_minus_d_sq; - let D = &(&c - &(d * &r)) * &(&r + d); - - let (Ns_D_is_sq, mut s) = FieldElement::sqrt_ratio_i(&N_s, &D); - let mut s_prime = &s * r_0; - let s_prime_is_pos = !s_prime.is_negative(); - s_prime.conditional_negate(s_prime_is_pos); - - s.conditional_assign(&s_prime, !Ns_D_is_sq); - c.conditional_assign(&r, !Ns_D_is_sq); - - let N_t = &(&(&c * &(&r - &one)) * &d_minus_one_sq) - &D; - let s_sq = s.square(); - - use backend::serial::curve_models::CompletedPoint; - - // The conversion from W_i is exactly the conversion from P1xP1. - RistrettoPoint(CompletedPoint{ - X: &(&s + &s) * &D, - Z: &N_t * &constants::SQRT_AD_MINUS_ONE, - Y: &FieldElement::one() - &s_sq, - T: &FieldElement::one() + &s_sq, - }.to_extended()) - } - - /// Return a `RistrettoPoint` chosen uniformly at random using a user-provided RNG. - /// - /// # Inputs - /// - /// * `rng`: any RNG which implements the `RngCore + CryptoRng` interface. - /// - /// # Returns - /// - /// A random element of the Ristretto group. - /// - /// # Implementation - /// - /// Uses the Ristretto-flavoured Elligator 2 map, so that the - /// discrete log of the output point with respect to any other - /// point should be unknown. The map is applied twice and the - /// results are added, to ensure a uniform distribution. - pub fn random(rng: &mut R) -> Self { - let mut uniform_bytes = [0u8; 64]; - rng.fill_bytes(&mut uniform_bytes); - - RistrettoPoint::from_uniform_bytes(&uniform_bytes) - } - - /// Hash a slice of bytes into a `RistrettoPoint`. - /// - /// Takes a type parameter `D`, which is any `Digest` producing 64 - /// bytes of output. - /// - /// Convenience wrapper around `from_hash`. - /// - /// # Implementation - /// - /// Uses the Ristretto-flavoured Elligator 2 map, so that the - /// discrete log of the output point with respect to any other - /// point should be unknown. The map is applied twice and the - /// results are added, to ensure a uniform distribution. - /// - /// # Example - /// - /// ``` - /// # extern crate curve25519_dalek; - /// # use curve25519_dalek::ristretto::RistrettoPoint; - /// extern crate sha2; - /// use sha2::Sha512; - /// - /// # // Need fn main() here in comment so the doctest compiles - /// # // See https://doc.rust-lang.org/book/documentation.html#documentation-as-tests - /// # fn main() { - /// let msg = "To really appreciate architecture, you may even need to commit a murder"; - /// let P = RistrettoPoint::hash_from_bytes::(msg.as_bytes()); - /// # } - /// ``` - /// - pub fn hash_from_bytes(input: &[u8]) -> RistrettoPoint - where D: Digest + Default - { - let mut hash = D::default(); - hash.update(input); - RistrettoPoint::from_hash(hash) - } - - /// Construct a `RistrettoPoint` from an existing `Digest` instance. - /// - /// Use this instead of `hash_from_bytes` if it is more convenient - /// to stream data into the `Digest` than to pass a single byte - /// slice. - pub fn from_hash(hash: D) -> RistrettoPoint - where D: Digest + Default - { - // dealing with generic arrays is clumsy, until const generics land - let output = hash.finalize(); - let mut output_bytes = [0u8; 64]; - output_bytes.copy_from_slice(&output.as_slice()); - - RistrettoPoint::from_uniform_bytes(&output_bytes) - } - - /// Construct a `RistrettoPoint` from 64 bytes of data. - /// - /// If the input bytes are uniformly distributed, the resulting - /// point will be uniformly distributed over the group, and its - /// discrete log with respect to other points should be unknown. - /// - /// # Implementation - /// - /// This function splits the input array into two 32-byte halves, - /// takes the low 255 bits of each half mod p, applies the - /// Ristretto-flavored Elligator map to each, and adds the results. - pub fn from_uniform_bytes(bytes: &[u8; 64]) -> RistrettoPoint { - let mut r_1_bytes = [0u8; 32]; - r_1_bytes.copy_from_slice(&bytes[0..32]); - let r_1 = FieldElement::from_bytes(&r_1_bytes); - let R_1 = RistrettoPoint::elligator_ristretto_flavor(&r_1); - - let mut r_2_bytes = [0u8; 32]; - r_2_bytes.copy_from_slice(&bytes[32..64]); - let r_2 = FieldElement::from_bytes(&r_2_bytes); - let R_2 = RistrettoPoint::elligator_ristretto_flavor(&r_2); - - // Applying Elligator twice and adding the results ensures a - // uniform distribution. - &R_1 + &R_2 - } -} - -impl Identity for RistrettoPoint { - fn identity() -> RistrettoPoint { - RistrettoPoint(EdwardsPoint::identity()) - } -} - -impl Default for RistrettoPoint { - fn default() -> RistrettoPoint { - RistrettoPoint::identity() - } -} - -// ------------------------------------------------------------------------ -// Equality -// ------------------------------------------------------------------------ - -impl PartialEq for RistrettoPoint { - fn eq(&self, other: &RistrettoPoint) -> bool { - self.ct_eq(other).unwrap_u8() == 1u8 - } -} - -impl ConstantTimeEq for RistrettoPoint { - /// Test equality between two `RistrettoPoint`s. - /// - /// # Returns - /// - /// * `Choice(1)` if the two `RistrettoPoint`s are equal; - /// * `Choice(0)` otherwise. - fn ct_eq(&self, other: &RistrettoPoint) -> Choice { - let X1Y2 = &self.0.X * &other.0.Y; - let Y1X2 = &self.0.Y * &other.0.X; - let X1X2 = &self.0.X * &other.0.X; - let Y1Y2 = &self.0.Y * &other.0.Y; - - X1Y2.ct_eq(&Y1X2) | X1X2.ct_eq(&Y1Y2) - } -} - -impl Eq for RistrettoPoint {} - -// ------------------------------------------------------------------------ -// Arithmetic -// ------------------------------------------------------------------------ - -impl<'a, 'b> Add<&'b RistrettoPoint> for &'a RistrettoPoint { - type Output = RistrettoPoint; - - fn add(self, other: &'b RistrettoPoint) -> RistrettoPoint { - RistrettoPoint(&self.0 + &other.0) - } -} - -define_add_variants!(LHS = RistrettoPoint, RHS = RistrettoPoint, Output = RistrettoPoint); - -impl<'b> AddAssign<&'b RistrettoPoint> for RistrettoPoint { - fn add_assign(&mut self, _rhs: &RistrettoPoint) { - *self = (self as &RistrettoPoint) + _rhs; - } -} - -define_add_assign_variants!(LHS = RistrettoPoint, RHS = RistrettoPoint); - -impl<'a, 'b> Sub<&'b RistrettoPoint> for &'a RistrettoPoint { - type Output = RistrettoPoint; - - fn sub(self, other: &'b RistrettoPoint) -> RistrettoPoint { - RistrettoPoint(&self.0 - &other.0) - } -} - -define_sub_variants!(LHS = RistrettoPoint, RHS = RistrettoPoint, Output = RistrettoPoint); - -impl<'b> SubAssign<&'b RistrettoPoint> for RistrettoPoint { - fn sub_assign(&mut self, _rhs: &RistrettoPoint) { - *self = (self as &RistrettoPoint) - _rhs; - } -} - -define_sub_assign_variants!(LHS = RistrettoPoint, RHS = RistrettoPoint); - -impl Sum for RistrettoPoint -where - T: Borrow -{ - fn sum(iter: I) -> Self - where - I: Iterator - { - iter.fold(RistrettoPoint::identity(), |acc, item| acc + item.borrow()) - } -} - -impl<'a> Neg for &'a RistrettoPoint { - type Output = RistrettoPoint; - - fn neg(self) -> RistrettoPoint { - RistrettoPoint(-&self.0) - } -} - -impl Neg for RistrettoPoint { - type Output = RistrettoPoint; - - fn neg(self) -> RistrettoPoint { - -&self - } -} - -impl<'b> MulAssign<&'b Scalar> for RistrettoPoint { - fn mul_assign(&mut self, scalar: &'b Scalar) { - let result = (self as &RistrettoPoint) * scalar; - *self = result; - } -} - -impl<'a, 'b> Mul<&'b Scalar> for &'a RistrettoPoint { - type Output = RistrettoPoint; - /// Scalar multiplication: compute `scalar * self`. - fn mul(self, scalar: &'b Scalar) -> RistrettoPoint { - RistrettoPoint(self.0 * scalar) - } -} - -impl<'a, 'b> Mul<&'b RistrettoPoint> for &'a Scalar { - type Output = RistrettoPoint; - - /// Scalar multiplication: compute `self * scalar`. - fn mul(self, point: &'b RistrettoPoint) -> RistrettoPoint { - RistrettoPoint(self * point.0) - } -} - -define_mul_assign_variants!(LHS = RistrettoPoint, RHS = Scalar); - -define_mul_variants!(LHS = RistrettoPoint, RHS = Scalar, Output = RistrettoPoint); -define_mul_variants!(LHS = Scalar, RHS = RistrettoPoint, Output = RistrettoPoint); - -// ------------------------------------------------------------------------ -// Multiscalar Multiplication impls -// ------------------------------------------------------------------------ - -// These use iterator combinators to unwrap the underlying points and -// forward to the EdwardsPoint implementations. - -#[cfg(feature = "alloc")] -impl MultiscalarMul for RistrettoPoint { - type Point = RistrettoPoint; - - fn multiscalar_mul(scalars: I, points: J) -> RistrettoPoint - where - I: IntoIterator, - I::Item: Borrow, - J: IntoIterator, - J::Item: Borrow, - { - let extended_points = points.into_iter().map(|P| P.borrow().0); - RistrettoPoint( - EdwardsPoint::multiscalar_mul(scalars, extended_points) - ) - } -} - -#[cfg(feature = "alloc")] -impl VartimeMultiscalarMul for RistrettoPoint { - type Point = RistrettoPoint; - - fn optional_multiscalar_mul(scalars: I, points: J) -> Option - where - I: IntoIterator, - I::Item: Borrow, - J: IntoIterator>, - { - let extended_points = points.into_iter().map(|opt_P| opt_P.map(|P| P.borrow().0)); - - EdwardsPoint::optional_multiscalar_mul(scalars, extended_points).map(RistrettoPoint) - } -} - -/// Precomputation for variable-time multiscalar multiplication with `RistrettoPoint`s. -// This wraps the inner implementation in a facade type so that we can -// decouple stability of the inner type from the stability of the -// outer type. -#[cfg(feature = "alloc")] -pub struct VartimeRistrettoPrecomputation(scalar_mul::precomputed_straus::VartimePrecomputedStraus); - -#[cfg(feature = "alloc")] -impl VartimePrecomputedMultiscalarMul for VartimeRistrettoPrecomputation { - type Point = RistrettoPoint; - - fn new(static_points: I) -> Self - where - I: IntoIterator, - I::Item: Borrow, - { - Self( - scalar_mul::precomputed_straus::VartimePrecomputedStraus::new( - static_points.into_iter().map(|P| P.borrow().0), - ), - ) - } - - fn optional_mixed_multiscalar_mul( - &self, - static_scalars: I, - dynamic_scalars: J, - dynamic_points: K, - ) -> Option - where - I: IntoIterator, - I::Item: Borrow, - J: IntoIterator, - J::Item: Borrow, - K: IntoIterator>, - { - self.0 - .optional_mixed_multiscalar_mul( - static_scalars, - dynamic_scalars, - dynamic_points.into_iter().map(|P_opt| P_opt.map(|P| P.0)), - ) - .map(RistrettoPoint) - } -} - -impl RistrettoPoint { - /// Compute \\(aA + bB\\) in variable time, where \\(B\\) is the - /// Ristretto basepoint. - pub fn vartime_double_scalar_mul_basepoint( - a: &Scalar, - A: &RistrettoPoint, - b: &Scalar, - ) -> RistrettoPoint { - RistrettoPoint( - EdwardsPoint::vartime_double_scalar_mul_basepoint(a, &A.0, b) - ) - } -} - -/// A precomputed table of multiples of a basepoint, used to accelerate -/// scalar multiplication. -/// -/// A precomputed table of multiples of the Ristretto basepoint is -/// available in the `constants` module: -/// ``` -/// use curve25519_dalek::constants; -/// use curve25519_dalek::scalar::Scalar; -/// -/// let a = Scalar::from(87329482u64); -/// let P = &a * &constants::RISTRETTO_BASEPOINT_TABLE; -/// ``` -#[derive(Clone)] -pub struct RistrettoBasepointTable(pub(crate) EdwardsBasepointTable); - -impl<'a, 'b> Mul<&'b Scalar> for &'a RistrettoBasepointTable { - type Output = RistrettoPoint; - - fn mul(self, scalar: &'b Scalar) -> RistrettoPoint { - RistrettoPoint(&self.0 * scalar) - } -} - -impl<'a, 'b> Mul<&'a RistrettoBasepointTable> for &'b Scalar { - type Output = RistrettoPoint; - - fn mul(self, basepoint_table: &'a RistrettoBasepointTable) -> RistrettoPoint { - RistrettoPoint(self * &basepoint_table.0) - } -} - -impl RistrettoBasepointTable { - /// Create a precomputed table of multiples of the given `basepoint`. - pub fn create(basepoint: &RistrettoPoint) -> RistrettoBasepointTable { - RistrettoBasepointTable(EdwardsBasepointTable::create(&basepoint.0)) - } - - /// Get the basepoint for this table as a `RistrettoPoint`. - pub fn basepoint(&self) -> RistrettoPoint { - RistrettoPoint(self.0.basepoint()) - } -} - -// ------------------------------------------------------------------------ -// Constant-time conditional selection -// ------------------------------------------------------------------------ - -impl ConditionallySelectable for RistrettoPoint { - /// Conditionally select between `self` and `other`. - /// - /// # Example - /// - /// ``` - /// # extern crate subtle; - /// # extern crate curve25519_dalek; - /// # - /// use subtle::ConditionallySelectable; - /// use subtle::Choice; - /// # - /// # use curve25519_dalek::traits::Identity; - /// # use curve25519_dalek::ristretto::RistrettoPoint; - /// # use curve25519_dalek::constants; - /// # fn main() { - /// - /// let A = RistrettoPoint::identity(); - /// let B = constants::RISTRETTO_BASEPOINT_POINT; - /// - /// let mut P = A; - /// - /// P = RistrettoPoint::conditional_select(&A, &B, Choice::from(0)); - /// assert_eq!(P, A); - /// P = RistrettoPoint::conditional_select(&A, &B, Choice::from(1)); - /// assert_eq!(P, B); - /// # } - /// ``` - fn conditional_select( - a: &RistrettoPoint, - b: &RistrettoPoint, - choice: Choice, - ) -> RistrettoPoint { - RistrettoPoint(EdwardsPoint::conditional_select(&a.0, &b.0, choice)) - } -} - -// ------------------------------------------------------------------------ -// Debug traits -// ------------------------------------------------------------------------ - -impl Debug for CompressedRistretto { - fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { - write!(f, "CompressedRistretto: {:?}", self.as_bytes()) - } -} - -impl Debug for RistrettoPoint { - fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { - let coset = self.coset4(); - write!(f, "RistrettoPoint: coset \n{:?}\n{:?}\n{:?}\n{:?}", - coset[0], coset[1], coset[2], coset[3]) - } -} - -// ------------------------------------------------------------------------ -// Tests -// ------------------------------------------------------------------------ - -#[cfg(test)] -mod test { - use rand_core::OsRng; - - use scalar::Scalar; - use constants; - use edwards::CompressedEdwardsY; - use traits::{Identity}; - use super::*; - - #[test] - #[cfg(feature = "serde")] - fn serde_bincode_basepoint_roundtrip() { - use bincode; - - let encoded = bincode::serialize(&constants::RISTRETTO_BASEPOINT_POINT).unwrap(); - let enc_compressed = bincode::serialize(&constants::RISTRETTO_BASEPOINT_COMPRESSED).unwrap(); - assert_eq!(encoded, enc_compressed); - - // Check that the encoding is 32 bytes exactly - assert_eq!(encoded.len(), 32); - - let dec_uncompressed: RistrettoPoint = bincode::deserialize(&encoded).unwrap(); - let dec_compressed: CompressedRistretto = bincode::deserialize(&encoded).unwrap(); - - assert_eq!(dec_uncompressed, constants::RISTRETTO_BASEPOINT_POINT); - assert_eq!(dec_compressed, constants::RISTRETTO_BASEPOINT_COMPRESSED); - - // Check that the encoding itself matches the usual one - let raw_bytes = constants::RISTRETTO_BASEPOINT_COMPRESSED.as_bytes(); - let bp: RistrettoPoint = bincode::deserialize(raw_bytes).unwrap(); - assert_eq!(bp, constants::RISTRETTO_BASEPOINT_POINT); - } - - #[test] - fn scalarmult_ristrettopoint_works_both_ways() { - let P = constants::RISTRETTO_BASEPOINT_POINT; - let s = Scalar::from(999u64); - - let P1 = &P * &s; - let P2 = &s * &P; - - assert!(P1.compress().as_bytes() == P2.compress().as_bytes()); - } - - #[test] - fn impl_sum() { - - // Test that sum works for non-empty iterators - let BASE = constants::RISTRETTO_BASEPOINT_POINT; - - let s1 = Scalar::from(999u64); - let P1 = &BASE * &s1; - - let s2 = Scalar::from(333u64); - let P2 = &BASE * &s2; - - let vec = vec![P1.clone(), P2.clone()]; - let sum: RistrettoPoint = vec.iter().sum(); - - assert_eq!(sum, P1 + P2); - - // Test that sum works for the empty iterator - let empty_vector: Vec = vec![]; - let sum: RistrettoPoint = empty_vector.iter().sum(); - - assert_eq!(sum, RistrettoPoint::identity()); - - // Test that sum works on owning iterators - let s = Scalar::from(2u64); - let mapped = vec.iter().map(|x| x * s); - let sum: RistrettoPoint = mapped.sum(); - - assert_eq!(sum, &P1 * &s + &P2 * &s); - } - - #[test] - fn decompress_negative_s_fails() { - // constants::d is neg, so decompression should fail as |d| != d. - let bad_compressed = CompressedRistretto(constants::EDWARDS_D.to_bytes()); - assert!(bad_compressed.decompress().is_none()); - } - - #[test] - fn decompress_id() { - let compressed_id = CompressedRistretto::identity(); - let id = compressed_id.decompress().unwrap(); - let mut identity_in_coset = false; - for P in &id.coset4() { - if P.compress() == CompressedEdwardsY::identity() { - identity_in_coset = true; - } - } - assert!(identity_in_coset); - } - - #[test] - fn compress_id() { - let id = RistrettoPoint::identity(); - assert_eq!(id.compress(), CompressedRistretto::identity()); - } - - #[test] - fn basepoint_roundtrip() { - let bp_compressed_ristretto = constants::RISTRETTO_BASEPOINT_POINT.compress(); - let bp_recaf = bp_compressed_ristretto.decompress().unwrap().0; - // Check that bp_recaf differs from bp by a point of order 4 - let diff = &constants::RISTRETTO_BASEPOINT_POINT.0 - &bp_recaf; - let diff4 = diff.mul_by_pow_2(2); - assert_eq!(diff4.compress(), CompressedEdwardsY::identity()); - } - - #[test] - fn encodings_of_small_multiples_of_basepoint() { - // Table of encodings of i*basepoint - // Generated using ristretto.sage - let compressed = [ - CompressedRistretto([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]), - CompressedRistretto([226, 242, 174, 10, 106, 188, 78, 113, 168, 132, 169, 97, 197, 0, 81, 95, 88, 227, 11, 106, 165, 130, 221, 141, 182, 166, 89, 69, 224, 141, 45, 118]), - CompressedRistretto([106, 73, 50, 16, 247, 73, 156, 209, 127, 236, 181, 16, 174, 12, 234, 35, 161, 16, 232, 213, 185, 1, 248, 172, 173, 211, 9, 92, 115, 163, 185, 25]), - CompressedRistretto([148, 116, 31, 93, 93, 82, 117, 94, 206, 79, 35, 240, 68, 238, 39, 213, 209, 234, 30, 43, 209, 150, 180, 98, 22, 107, 22, 21, 42, 157, 2, 89]), - CompressedRistretto([218, 128, 134, 39, 115, 53, 139, 70, 111, 250, 223, 224, 179, 41, 58, 179, 217, 253, 83, 197, 234, 108, 149, 83, 88, 245, 104, 50, 45, 175, 106, 87]), - CompressedRistretto([232, 130, 177, 49, 1, 107, 82, 193, 211, 51, 112, 128, 24, 124, 247, 104, 66, 62, 252, 203, 181, 23, 187, 73, 90, 184, 18, 196, 22, 15, 244, 78]), - CompressedRistretto([246, 71, 70, 211, 201, 43, 19, 5, 14, 216, 216, 2, 54, 167, 240, 0, 124, 59, 63, 150, 47, 91, 167, 147, 209, 154, 96, 30, 187, 29, 244, 3]), - CompressedRistretto([68, 245, 53, 32, 146, 110, 200, 31, 189, 90, 56, 120, 69, 190, 183, 223, 133, 169, 106, 36, 236, 225, 135, 56, 189, 207, 166, 167, 130, 42, 23, 109]), - CompressedRistretto([144, 50, 147, 216, 242, 40, 126, 190, 16, 226, 55, 77, 193, 165, 62, 11, 200, 135, 229, 146, 105, 159, 2, 208, 119, 213, 38, 60, 221, 85, 96, 28]), - CompressedRistretto([2, 98, 42, 206, 143, 115, 3, 163, 28, 175, 198, 63, 143, 196, 143, 220, 22, 225, 200, 200, 210, 52, 178, 240, 214, 104, 82, 130, 169, 7, 96, 49]), - CompressedRistretto([32, 112, 111, 215, 136, 178, 114, 10, 30, 210, 165, 218, 212, 149, 43, 1, 244, 19, 188, 240, 231, 86, 77, 232, 205, 200, 22, 104, 158, 45, 185, 95]), - CompressedRistretto([188, 232, 63, 139, 165, 221, 47, 165, 114, 134, 76, 36, 186, 24, 16, 249, 82, 43, 198, 0, 74, 254, 149, 135, 122, 199, 50, 65, 202, 253, 171, 66]), - CompressedRistretto([228, 84, 158, 225, 107, 154, 160, 48, 153, 202, 32, 140, 103, 173, 175, 202, 250, 76, 63, 62, 78, 83, 3, 222, 96, 38, 227, 202, 143, 248, 68, 96]), - CompressedRistretto([170, 82, 224, 0, 223, 46, 22, 245, 95, 177, 3, 47, 195, 59, 196, 39, 66, 218, 214, 189, 90, 143, 192, 190, 1, 103, 67, 108, 89, 72, 80, 31]), - CompressedRistretto([70, 55, 107, 128, 244, 9, 178, 157, 194, 181, 246, 240, 197, 37, 145, 153, 8, 150, 229, 113, 111, 65, 71, 124, 211, 0, 133, 171, 127, 16, 48, 30]), - CompressedRistretto([224, 196, 24, 247, 200, 217, 196, 205, 215, 57, 91, 147, 234, 18, 79, 58, 217, 144, 33, 187, 104, 29, 252, 51, 2, 169, 217, 154, 46, 83, 230, 78]), - ]; - let mut bp = RistrettoPoint::identity(); - for i in 0..16 { - assert_eq!(bp.compress(), compressed[i]); - bp = &bp + &constants::RISTRETTO_BASEPOINT_POINT; - } - } - - #[test] - fn four_torsion_basepoint() { - let bp = constants::RISTRETTO_BASEPOINT_POINT; - let bp_coset = bp.coset4(); - for i in 0..4 { - assert_eq!(bp, RistrettoPoint(bp_coset[i])); - } - } - - #[test] - fn four_torsion_random() { - let mut rng = OsRng; - let B = &constants::RISTRETTO_BASEPOINT_TABLE; - let P = B * &Scalar::random(&mut rng); - let P_coset = P.coset4(); - for i in 0..4 { - assert_eq!(P, RistrettoPoint(P_coset[i])); - } - } - - #[test] - fn elligator_vs_ristretto_sage() { - // Test vectors extracted from ristretto.sage. - // - // Notice that all of the byte sequences have bit 255 set to 0; this is because - // ristretto.sage does not mask the high bit of a field element. When the high bit is set, - // the ristretto.sage elligator implementation gives different results, since it takes a - // different field element as input. - let bytes: [[u8;32]; 16] = [ - [184, 249, 135, 49, 253, 123, 89, 113, 67, 160, 6, 239, 7, 105, 211, 41, 192, 249, 185, 57, 9, 102, 70, 198, 15, 127, 7, 26, 160, 102, 134, 71], - [229, 14, 241, 227, 75, 9, 118, 60, 128, 153, 226, 21, 183, 217, 91, 136, 98, 0, 231, 156, 124, 77, 82, 139, 142, 134, 164, 169, 169, 62, 250, 52], - [115, 109, 36, 220, 180, 223, 99, 6, 204, 169, 19, 29, 169, 68, 84, 23, 21, 109, 189, 149, 127, 205, 91, 102, 172, 35, 112, 35, 134, 69, 186, 34], - [16, 49, 96, 107, 171, 199, 164, 9, 129, 16, 64, 62, 241, 63, 132, 173, 209, 160, 112, 215, 105, 50, 157, 81, 253, 105, 1, 154, 229, 25, 120, 83], - [156, 131, 161, 162, 236, 251, 5, 187, 167, 171, 17, 178, 148, 210, 90, 207, 86, 21, 79, 161, 167, 215, 234, 1, 136, 242, 182, 248, 38, 85, 79, 86], - [251, 177, 124, 54, 18, 101, 75, 235, 245, 186, 19, 46, 133, 157, 229, 64, 10, 136, 181, 185, 78, 144, 254, 167, 137, 49, 107, 10, 61, 10, 21, 25], - [232, 193, 20, 68, 240, 77, 186, 77, 183, 40, 44, 86, 150, 31, 198, 212, 76, 81, 3, 217, 197, 8, 126, 128, 126, 152, 164, 208, 153, 44, 189, 77], - [173, 229, 149, 177, 37, 230, 30, 69, 61, 56, 172, 190, 219, 115, 167, 194, 71, 134, 59, 75, 28, 244, 118, 26, 162, 97, 64, 16, 15, 189, 30, 64], - [106, 71, 61, 107, 250, 117, 42, 151, 91, 202, 212, 100, 52, 188, 190, 21, 125, 218, 31, 18, 253, 241, 160, 133, 57, 242, 3, 164, 189, 68, 111, 75], - [112, 204, 182, 90, 220, 198, 120, 73, 173, 107, 193, 17, 227, 40, 162, 36, 150, 141, 235, 55, 172, 183, 12, 39, 194, 136, 43, 153, 244, 118, 91, 89], - [111, 24, 203, 123, 254, 189, 11, 162, 51, 196, 163, 136, 204, 143, 10, 222, 33, 112, 81, 205, 34, 35, 8, 66, 90, 6, 164, 58, 170, 177, 34, 25], - [225, 183, 30, 52, 236, 82, 6, 183, 109, 25, 227, 181, 25, 82, 41, 193, 80, 77, 161, 80, 242, 203, 79, 204, 136, 245, 131, 110, 237, 106, 3, 58], - [207, 246, 38, 56, 30, 86, 176, 90, 27, 200, 61, 42, 221, 27, 56, 210, 79, 178, 189, 120, 68, 193, 120, 167, 77, 185, 53, 197, 124, 128, 191, 126], - [1, 136, 215, 80, 240, 46, 63, 147, 16, 244, 230, 207, 82, 189, 74, 50, 106, 169, 138, 86, 30, 131, 214, 202, 166, 125, 251, 228, 98, 24, 36, 21], - [210, 207, 228, 56, 155, 116, 207, 54, 84, 195, 251, 215, 249, 199, 116, 75, 109, 239, 196, 251, 194, 246, 252, 228, 70, 146, 156, 35, 25, 39, 241, 4], - [34, 116, 123, 9, 8, 40, 93, 189, 9, 103, 57, 103, 66, 227, 3, 2, 157, 107, 134, 219, 202, 74, 230, 154, 78, 107, 219, 195, 214, 14, 84, 80], - ]; - let encoded_images: [CompressedRistretto; 16] = [ - CompressedRistretto([176, 157, 237, 97, 66, 29, 140, 166, 168, 94, 26, 157, 212, 216, 229, 160, 195, 246, 232, 239, 169, 112, 63, 193, 64, 32, 152, 69, 11, 190, 246, 86]), - CompressedRistretto([234, 141, 77, 203, 181, 225, 250, 74, 171, 62, 15, 118, 78, 212, 150, 19, 131, 14, 188, 238, 194, 244, 141, 138, 166, 162, 83, 122, 228, 201, 19, 26]), - CompressedRistretto([232, 231, 51, 92, 5, 168, 80, 36, 173, 179, 104, 68, 186, 149, 68, 40, 140, 170, 27, 103, 99, 140, 21, 242, 43, 62, 250, 134, 208, 255, 61, 89]), - CompressedRistretto([208, 120, 140, 129, 177, 179, 237, 159, 252, 160, 28, 13, 206, 5, 211, 241, 192, 218, 1, 97, 130, 241, 20, 169, 119, 46, 246, 29, 79, 80, 77, 84]), - CompressedRistretto([202, 11, 236, 145, 58, 12, 181, 157, 209, 6, 213, 88, 75, 147, 11, 119, 191, 139, 47, 142, 33, 36, 153, 193, 223, 183, 178, 8, 205, 120, 248, 110]), - CompressedRistretto([26, 66, 231, 67, 203, 175, 116, 130, 32, 136, 62, 253, 215, 46, 5, 214, 166, 248, 108, 237, 216, 71, 244, 173, 72, 133, 82, 6, 143, 240, 104, 41]), - CompressedRistretto([40, 157, 102, 96, 201, 223, 200, 197, 150, 181, 106, 83, 103, 126, 143, 33, 145, 230, 78, 6, 171, 146, 210, 143, 112, 5, 245, 23, 183, 138, 18, 120]), - CompressedRistretto([220, 37, 27, 203, 239, 196, 176, 131, 37, 66, 188, 243, 185, 250, 113, 23, 167, 211, 154, 243, 168, 215, 54, 171, 159, 36, 195, 81, 13, 150, 43, 43]), - CompressedRistretto([232, 121, 176, 222, 183, 196, 159, 90, 238, 193, 105, 52, 101, 167, 244, 170, 121, 114, 196, 6, 67, 152, 80, 185, 221, 7, 83, 105, 176, 208, 224, 121]), - CompressedRistretto([226, 181, 183, 52, 241, 163, 61, 179, 221, 207, 220, 73, 245, 242, 25, 236, 67, 84, 179, 222, 167, 62, 167, 182, 32, 9, 92, 30, 165, 127, 204, 68]), - CompressedRistretto([226, 119, 16, 242, 200, 139, 240, 87, 11, 222, 92, 146, 156, 243, 46, 119, 65, 59, 1, 248, 92, 183, 50, 175, 87, 40, 206, 53, 208, 220, 148, 13]), - CompressedRistretto([70, 240, 79, 112, 54, 157, 228, 146, 74, 122, 216, 88, 232, 62, 158, 13, 14, 146, 115, 117, 176, 222, 90, 225, 244, 23, 94, 190, 150, 7, 136, 96]), - CompressedRistretto([22, 71, 241, 103, 45, 193, 195, 144, 183, 101, 154, 50, 39, 68, 49, 110, 51, 44, 62, 0, 229, 113, 72, 81, 168, 29, 73, 106, 102, 40, 132, 24]), - CompressedRistretto([196, 133, 107, 11, 130, 105, 74, 33, 204, 171, 133, 221, 174, 193, 241, 36, 38, 179, 196, 107, 219, 185, 181, 253, 228, 47, 155, 42, 231, 73, 41, 78]), - CompressedRistretto([58, 255, 225, 197, 115, 208, 160, 143, 39, 197, 82, 69, 143, 235, 92, 170, 74, 40, 57, 11, 171, 227, 26, 185, 217, 207, 90, 185, 197, 190, 35, 60]), - CompressedRistretto([88, 43, 92, 118, 223, 136, 105, 145, 238, 186, 115, 8, 214, 112, 153, 253, 38, 108, 205, 230, 157, 130, 11, 66, 101, 85, 253, 110, 110, 14, 148, 112]), - ]; - for i in 0..16 { - let r_0 = FieldElement::from_bytes(&bytes[i]); - let Q = RistrettoPoint::elligator_ristretto_flavor(&r_0); - assert_eq!(Q.compress(), encoded_images[i]); - } - } - - #[test] - fn random_roundtrip() { - let mut rng = OsRng; - let B = &constants::RISTRETTO_BASEPOINT_TABLE; - for _ in 0..100 { - let P = B * &Scalar::random(&mut rng); - let compressed_P = P.compress(); - let Q = compressed_P.decompress().unwrap(); - assert_eq!(P, Q); - } - } - - #[test] - fn double_and_compress_1024_random_points() { - let mut rng = OsRng; - - let points: Vec = - (0..1024).map(|_| RistrettoPoint::random(&mut rng)).collect(); - - let compressed = RistrettoPoint::double_and_compress_batch(&points); - - for (P, P2_compressed) in points.iter().zip(compressed.iter()) { - assert_eq!(*P2_compressed, (P + P).compress()); - } - } - - #[test] - fn vartime_precomputed_vs_nonprecomputed_multiscalar() { - let mut rng = rand::thread_rng(); - - let B = &::constants::RISTRETTO_BASEPOINT_TABLE; - - let static_scalars = (0..128) - .map(|_| Scalar::random(&mut rng)) - .collect::>(); - - let dynamic_scalars = (0..128) - .map(|_| Scalar::random(&mut rng)) - .collect::>(); - - let check_scalar: Scalar = static_scalars - .iter() - .chain(dynamic_scalars.iter()) - .map(|s| s * s) - .sum(); - - let static_points = static_scalars.iter().map(|s| s * B).collect::>(); - let dynamic_points = dynamic_scalars.iter().map(|s| s * B).collect::>(); - - let precomputation = VartimeRistrettoPrecomputation::new(static_points.iter()); - - let P = precomputation.vartime_mixed_multiscalar_mul( - &static_scalars, - &dynamic_scalars, - &dynamic_points, - ); - - use traits::VartimeMultiscalarMul; - let Q = RistrettoPoint::vartime_multiscalar_mul( - static_scalars.iter().chain(dynamic_scalars.iter()), - static_points.iter().chain(dynamic_points.iter()), - ); - - let R = &check_scalar * B; - - assert_eq!(P.compress(), R.compress()); - assert_eq!(Q.compress(), R.compress()); - } -} diff --git a/net/gurk-rs/files/vendor/curve25519-dalek/src/scalar.rs b/net/gurk-rs/files/vendor/curve25519-dalek/src/scalar.rs deleted file mode 100644 index 00de740..0000000 --- a/net/gurk-rs/files/vendor/curve25519-dalek/src/scalar.rs +++ /dev/null @@ -1,1754 +0,0 @@ -// -*- mode: rust; -*- -// -// This file is part of curve25519-dalek. -// Copyright (c) 2016-2021 isis lovecruft -// Copyright (c) 2016-2019 Henry de Valence -// Portions Copyright 2017 Brian Smith -// See LICENSE for licensing information. -// -// Authors: -// - Isis Agora Lovecruft -// - Henry de Valence -// - Brian Smith - -//! Arithmetic on scalars (integers mod the group order). -//! -//! Both the Ristretto group and the Ed25519 basepoint have prime order -//! \\( \ell = 2\^{252} + 27742317777372353535851937790883648493 \\). -//! -//! This code is intended to be useful with both the Ristretto group -//! (where everything is done modulo \\( \ell \\)), and the X/Ed25519 -//! setting, which mandates specific bit-twiddles that are not -//! well-defined modulo \\( \ell \\). -//! -//! All arithmetic on `Scalars` is done modulo \\( \ell \\). -//! -//! # Constructing a scalar -//! -//! To create a [`Scalar`](struct.Scalar.html) from a supposedly canonical encoding, use -//! [`Scalar::from_canonical_bytes`](struct.Scalar.html#method.from_canonical_bytes). -//! -//! This function does input validation, ensuring that the input bytes -//! are the canonical encoding of a `Scalar`. -//! If they are, we'll get -//! `Some(Scalar)` in return: -//! -//! ``` -//! use curve25519_dalek::scalar::Scalar; -//! -//! let one_as_bytes: [u8; 32] = Scalar::one().to_bytes(); -//! let a: Option = Scalar::from_canonical_bytes(one_as_bytes); -//! -//! assert!(a.is_some()); -//! ``` -//! -//! However, if we give it bytes representing a scalar larger than \\( \ell \\) -//! (in this case, \\( \ell + 2 \\)), we'll get `None` back: -//! -//! ``` -//! use curve25519_dalek::scalar::Scalar; -//! -//! let l_plus_two_bytes: [u8; 32] = [ -//! 0xef, 0xd3, 0xf5, 0x5c, 0x1a, 0x63, 0x12, 0x58, -//! 0xd6, 0x9c, 0xf7, 0xa2, 0xde, 0xf9, 0xde, 0x14, -//! 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -//! 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, -//! ]; -//! let a: Option = Scalar::from_canonical_bytes(l_plus_two_bytes); -//! -//! assert!(a.is_none()); -//! ``` -//! -//! Another way to create a `Scalar` is by reducing a \\(256\\)-bit integer mod -//! \\( \ell \\), for which one may use the -//! [`Scalar::from_bytes_mod_order`](struct.Scalar.html#method.from_bytes_mod_order) -//! method. In the case of the second example above, this would reduce the -//! resultant scalar \\( \mod \ell \\), producing \\( 2 \\): -//! -//! ``` -//! use curve25519_dalek::scalar::Scalar; -//! -//! let l_plus_two_bytes: [u8; 32] = [ -//! 0xef, 0xd3, 0xf5, 0x5c, 0x1a, 0x63, 0x12, 0x58, -//! 0xd6, 0x9c, 0xf7, 0xa2, 0xde, 0xf9, 0xde, 0x14, -//! 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -//! 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, -//! ]; -//! let a: Scalar = Scalar::from_bytes_mod_order(l_plus_two_bytes); -//! -//! let two: Scalar = Scalar::one() + Scalar::one(); -//! -//! assert!(a == two); -//! ``` -//! -//! There is also a constructor that reduces a \\(512\\)-bit integer, -//! [`Scalar::from_bytes_mod_order_wide`](struct.Scalar.html#method.from_bytes_mod_order_wide). -//! -//! To construct a `Scalar` as the hash of some input data, use -//! [`Scalar::hash_from_bytes`](struct.Scalar.html#method.hash_from_bytes), -//! which takes a buffer, or -//! [`Scalar::from_hash`](struct.Scalar.html#method.from_hash), -//! which allows an IUF API. -//! -//! ``` -//! # extern crate curve25519_dalek; -//! # extern crate sha2; -//! # -//! # fn main() { -//! use sha2::{Digest, Sha512}; -//! use curve25519_dalek::scalar::Scalar; -//! -//! // Hashing a single byte slice -//! let a = Scalar::hash_from_bytes::(b"Abolish ICE"); -//! -//! // Streaming data into a hash object -//! let mut hasher = Sha512::default(); -//! hasher.update(b"Abolish "); -//! hasher.update(b"ICE"); -//! let a2 = Scalar::from_hash(hasher); -//! -//! assert_eq!(a, a2); -//! # } -//! ``` -//! -//! Finally, to create a `Scalar` with a specific bit-pattern -//! (e.g., for compatibility with X/Ed25519 -//! ["clamping"](https://github.com/isislovecruft/ed25519-dalek/blob/f790bd2ce/src/ed25519.rs#L349)), -//! use [`Scalar::from_bits`](struct.Scalar.html#method.from_bits). This -//! constructs a scalar with exactly the bit pattern given, without any -//! assurances as to reduction modulo the group order: -//! -//! ``` -//! use curve25519_dalek::scalar::Scalar; -//! -//! let l_plus_two_bytes: [u8; 32] = [ -//! 0xef, 0xd3, 0xf5, 0x5c, 0x1a, 0x63, 0x12, 0x58, -//! 0xd6, 0x9c, 0xf7, 0xa2, 0xde, 0xf9, 0xde, 0x14, -//! 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -//! 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, -//! ]; -//! let a: Scalar = Scalar::from_bits(l_plus_two_bytes); -//! -//! let two: Scalar = Scalar::one() + Scalar::one(); -//! -//! assert!(a != two); // the scalar is not reduced (mod l)… -//! assert!(! a.is_canonical()); // …and therefore is not canonical. -//! assert!(a.reduce() == two); // if we were to reduce it manually, it would be. -//! ``` -//! -//! The resulting `Scalar` has exactly the specified bit pattern, -//! **except for the highest bit, which will be set to 0**. - -use core::borrow::Borrow; -use core::cmp::{Eq, PartialEq}; -use core::fmt::Debug; -use core::iter::{Product, Sum}; -use core::ops::Index; -use core::ops::Neg; -use core::ops::{Add, AddAssign}; -use core::ops::{Mul, MulAssign}; -use core::ops::{Sub, SubAssign}; - -#[allow(unused_imports)] -use prelude::*; - -use rand_core::{CryptoRng, RngCore}; - -use digest::generic_array::typenum::U64; -use digest::Digest; - -use subtle::Choice; -use subtle::ConditionallySelectable; -use subtle::ConstantTimeEq; - -use zeroize::Zeroize; - -use backend; -use constants; - -/// An `UnpackedScalar` represents an element of the field GF(l), optimized for speed. -/// -/// This is a type alias for one of the scalar types in the `backend` -/// module. -#[cfg(feature = "fiat_u32_backend")] -type UnpackedScalar = backend::serial::fiat_u32::scalar::Scalar29; -#[cfg(feature = "fiat_u64_backend")] -type UnpackedScalar = backend::serial::fiat_u64::scalar::Scalar52; - -/// An `UnpackedScalar` represents an element of the field GF(l), optimized for speed. -/// -/// This is a type alias for one of the scalar types in the `backend` -/// module. -#[cfg(feature = "u64_backend")] -type UnpackedScalar = backend::serial::u64::scalar::Scalar52; - -/// An `UnpackedScalar` represents an element of the field GF(l), optimized for speed. -/// -/// This is a type alias for one of the scalar types in the `backend` -/// module. -#[cfg(feature = "u32_backend")] -type UnpackedScalar = backend::serial::u32::scalar::Scalar29; - - -/// The `Scalar` struct holds an integer \\(s < 2\^{255} \\) which -/// represents an element of \\(\mathbb Z / \ell\\). -#[derive(Copy, Clone, Hash)] -pub struct Scalar { - /// `bytes` is a little-endian byte encoding of an integer representing a scalar modulo the - /// group order. - /// - /// # Invariant - /// - /// The integer representing this scalar must be bounded above by \\(2\^{255}\\), or - /// equivalently the high bit of `bytes[31]` must be zero. - /// - /// This ensures that there is room for a carry bit when computing a NAF representation. - // - // XXX This is pub(crate) so we can write literal constants. If const fns were stable, we could - // make the Scalar constructors const fns and use those instead. - pub(crate) bytes: [u8; 32], -} - -impl Scalar { - /// Construct a `Scalar` by reducing a 256-bit little-endian integer - /// modulo the group order \\( \ell \\). - pub fn from_bytes_mod_order(bytes: [u8; 32]) -> Scalar { - // Temporarily allow s_unreduced.bytes > 2^255 ... - let s_unreduced = Scalar{bytes}; - - // Then reduce mod the group order and return the reduced representative. - let s = s_unreduced.reduce(); - debug_assert_eq!(0u8, s[31] >> 7); - - s - } - - /// Construct a `Scalar` by reducing a 512-bit little-endian integer - /// modulo the group order \\( \ell \\). - pub fn from_bytes_mod_order_wide(input: &[u8; 64]) -> Scalar { - UnpackedScalar::from_bytes_wide(input).pack() - } - - /// Attempt to construct a `Scalar` from a canonical byte representation. - /// - /// # Return - /// - /// - `Some(s)`, where `s` is the `Scalar` corresponding to `bytes`, - /// if `bytes` is a canonical byte representation; - /// - `None` if `bytes` is not a canonical byte representation. - pub fn from_canonical_bytes(bytes: [u8; 32]) -> Option { - // Check that the high bit is not set - if (bytes[31] >> 7) != 0u8 { return None; } - let candidate = Scalar::from_bits(bytes); - - if candidate.is_canonical() { - Some(candidate) - } else { - None - } - } - - /// Construct a `Scalar` from the low 255 bits of a 256-bit integer. - /// - /// This function is intended for applications like X25519 which - /// require specific bit-patterns when performing scalar - /// multiplication. - pub const fn from_bits(bytes: [u8; 32]) -> Scalar { - let mut s = Scalar{bytes}; - // Ensure that s < 2^255 by masking the high bit - s.bytes[31] &= 0b0111_1111; - - s - } -} - -impl Debug for Scalar { - fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { - write!(f, "Scalar{{\n\tbytes: {:?},\n}}", &self.bytes) - } -} - -impl Eq for Scalar {} -impl PartialEq for Scalar { - fn eq(&self, other: &Self) -> bool { - self.ct_eq(other).unwrap_u8() == 1u8 - } -} - -impl ConstantTimeEq for Scalar { - fn ct_eq(&self, other: &Self) -> Choice { - self.bytes.ct_eq(&other.bytes) - } -} - -impl Index for Scalar { - type Output = u8; - - /// Index the bytes of the representative for this `Scalar`. Mutation is not permitted. - fn index(&self, _index: usize) -> &u8 { - &(self.bytes[_index]) - } -} - -impl<'b> MulAssign<&'b Scalar> for Scalar { - fn mul_assign(&mut self, _rhs: &'b Scalar) { - *self = UnpackedScalar::mul(&self.unpack(), &_rhs.unpack()).pack(); - } -} - -define_mul_assign_variants!(LHS = Scalar, RHS = Scalar); - -impl<'a, 'b> Mul<&'b Scalar> for &'a Scalar { - type Output = Scalar; - fn mul(self, _rhs: &'b Scalar) -> Scalar { - UnpackedScalar::mul(&self.unpack(), &_rhs.unpack()).pack() - } -} - -define_mul_variants!(LHS = Scalar, RHS = Scalar, Output = Scalar); - -impl<'b> AddAssign<&'b Scalar> for Scalar { - fn add_assign(&mut self, _rhs: &'b Scalar) { - *self = *self + _rhs; - } -} - -define_add_assign_variants!(LHS = Scalar, RHS = Scalar); - -impl<'a, 'b> Add<&'b Scalar> for &'a Scalar { - type Output = Scalar; - #[allow(non_snake_case)] - fn add(self, _rhs: &'b Scalar) -> Scalar { - // The UnpackedScalar::add function produces reduced outputs - // if the inputs are reduced. However, these inputs may not - // be reduced -- they might come from Scalar::from_bits. So - // after computing the sum, we explicitly reduce it mod l - // before repacking. - let sum = UnpackedScalar::add(&self.unpack(), &_rhs.unpack()); - let sum_R = UnpackedScalar::mul_internal(&sum, &constants::R); - let sum_mod_l = UnpackedScalar::montgomery_reduce(&sum_R); - sum_mod_l.pack() - } -} - -define_add_variants!(LHS = Scalar, RHS = Scalar, Output = Scalar); - -impl<'b> SubAssign<&'b Scalar> for Scalar { - fn sub_assign(&mut self, _rhs: &'b Scalar) { - *self = *self - _rhs; - } -} - -define_sub_assign_variants!(LHS = Scalar, RHS = Scalar); - -impl<'a, 'b> Sub<&'b Scalar> for &'a Scalar { - type Output = Scalar; - #[allow(non_snake_case)] - fn sub(self, rhs: &'b Scalar) -> Scalar { - // The UnpackedScalar::sub function requires reduced inputs - // and produces reduced output. However, these inputs may not - // be reduced -- they might come from Scalar::from_bits. So - // we explicitly reduce the inputs. - let self_R = UnpackedScalar::mul_internal(&self.unpack(), &constants::R); - let self_mod_l = UnpackedScalar::montgomery_reduce(&self_R); - let rhs_R = UnpackedScalar::mul_internal(&rhs.unpack(), &constants::R); - let rhs_mod_l = UnpackedScalar::montgomery_reduce(&rhs_R); - - UnpackedScalar::sub(&self_mod_l, &rhs_mod_l).pack() - } -} - -define_sub_variants!(LHS = Scalar, RHS = Scalar, Output = Scalar); - -impl<'a> Neg for &'a Scalar { - type Output = Scalar; - #[allow(non_snake_case)] - fn neg(self) -> Scalar { - let self_R = UnpackedScalar::mul_internal(&self.unpack(), &constants::R); - let self_mod_l = UnpackedScalar::montgomery_reduce(&self_R); - UnpackedScalar::sub(&UnpackedScalar::zero(), &self_mod_l).pack() - } -} - -impl<'a> Neg for Scalar { - type Output = Scalar; - fn neg(self) -> Scalar { - -&self - } -} - -impl ConditionallySelectable for Scalar { - fn conditional_select(a: &Self, b: &Self, choice: Choice) -> Self { - let mut bytes = [0u8; 32]; - for i in 0..32 { - bytes[i] = u8::conditional_select(&a.bytes[i], &b.bytes[i], choice); - } - Scalar { bytes } - } -} - -#[cfg(feature = "serde")] -use serde::{self, Serialize, Deserialize, Serializer, Deserializer}; -#[cfg(feature = "serde")] -use serde::de::Visitor; - -#[cfg(feature = "serde")] -impl Serialize for Scalar { - fn serialize(&self, serializer: S) -> Result - where S: Serializer - { - use serde::ser::SerializeTuple; - let mut tup = serializer.serialize_tuple(32)?; - for byte in self.as_bytes().iter() { - tup.serialize_element(byte)?; - } - tup.end() - } -} - -#[cfg(feature = "serde")] -impl<'de> Deserialize<'de> for Scalar { - fn deserialize(deserializer: D) -> Result - where D: Deserializer<'de> - { - struct ScalarVisitor; - - impl<'de> Visitor<'de> for ScalarVisitor { - type Value = Scalar; - - fn expecting(&self, formatter: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { - formatter.write_str("a valid point in Edwards y + sign format") - } - - fn visit_seq(self, mut seq: A) -> Result - where A: serde::de::SeqAccess<'de> - { - let mut bytes = [0u8; 32]; - for i in 0..32 { - bytes[i] = seq.next_element()? - .ok_or(serde::de::Error::invalid_length(i, &"expected 32 bytes"))?; - } - Scalar::from_canonical_bytes(bytes) - .ok_or(serde::de::Error::custom( - &"scalar was not canonically encoded" - )) - } - } - - deserializer.deserialize_tuple(32, ScalarVisitor) - } -} - -impl Product for Scalar -where - T: Borrow -{ - fn product(iter: I) -> Self - where - I: Iterator - { - iter.fold(Scalar::one(), |acc, item| acc * item.borrow()) - } -} - -impl Sum for Scalar -where - T: Borrow -{ - fn sum(iter: I) -> Self - where - I: Iterator - { - iter.fold(Scalar::zero(), |acc, item| acc + item.borrow()) - } -} - -impl Default for Scalar { - fn default() -> Scalar { - Scalar::zero() - } -} - -impl From for Scalar { - fn from(x: u8) -> Scalar { - let mut s_bytes = [0u8; 32]; - s_bytes[0] = x; - Scalar{ bytes: s_bytes } - } -} - -impl From for Scalar { - fn from(x: u16) -> Scalar { - use byteorder::{ByteOrder, LittleEndian}; - let mut s_bytes = [0u8; 32]; - LittleEndian::write_u16(&mut s_bytes, x); - Scalar{ bytes: s_bytes } - } -} - -impl From for Scalar { - fn from(x: u32) -> Scalar { - use byteorder::{ByteOrder, LittleEndian}; - let mut s_bytes = [0u8; 32]; - LittleEndian::write_u32(&mut s_bytes, x); - Scalar{ bytes: s_bytes } - } -} - -impl From for Scalar { - /// Construct a scalar from the given `u64`. - /// - /// # Inputs - /// - /// An `u64` to convert to a `Scalar`. - /// - /// # Returns - /// - /// A `Scalar` corresponding to the input `u64`. - /// - /// # Example - /// - /// ``` - /// use curve25519_dalek::scalar::Scalar; - /// - /// let fourtytwo = Scalar::from(42u64); - /// let six = Scalar::from(6u64); - /// let seven = Scalar::from(7u64); - /// - /// assert!(fourtytwo == six * seven); - /// ``` - fn from(x: u64) -> Scalar { - use byteorder::{ByteOrder, LittleEndian}; - let mut s_bytes = [0u8; 32]; - LittleEndian::write_u64(&mut s_bytes, x); - Scalar{ bytes: s_bytes } - } -} - -impl From for Scalar { - fn from(x: u128) -> Scalar { - use byteorder::{ByteOrder, LittleEndian}; - let mut s_bytes = [0u8; 32]; - LittleEndian::write_u128(&mut s_bytes, x); - Scalar{ bytes: s_bytes } - } -} - -impl Zeroize for Scalar { - fn zeroize(&mut self) { - self.bytes.zeroize(); - } -} - -impl Scalar { - /// Return a `Scalar` chosen uniformly at random using a user-provided RNG. - /// - /// # Inputs - /// - /// * `rng`: any RNG which implements the `RngCore + CryptoRng` interface. - /// - /// # Returns - /// - /// A random scalar within ℤ/lℤ. - /// - /// # Example - /// - /// ``` - /// extern crate rand_core; - /// # extern crate curve25519_dalek; - /// # - /// # fn main() { - /// use curve25519_dalek::scalar::Scalar; - /// - /// use rand_core::OsRng; - /// - /// let mut csprng = OsRng; - /// let a: Scalar = Scalar::random(&mut csprng); - /// # } - pub fn random(rng: &mut R) -> Self { - let mut scalar_bytes = [0u8; 64]; - rng.fill_bytes(&mut scalar_bytes); - Scalar::from_bytes_mod_order_wide(&scalar_bytes) - } - - /// Hash a slice of bytes into a scalar. - /// - /// Takes a type parameter `D`, which is any `Digest` producing 64 - /// bytes (512 bits) of output. - /// - /// Convenience wrapper around `from_hash`. - /// - /// # Example - /// - /// ``` - /// # extern crate curve25519_dalek; - /// # use curve25519_dalek::scalar::Scalar; - /// extern crate sha2; - /// - /// use sha2::Sha512; - /// - /// # // Need fn main() here in comment so the doctest compiles - /// # // See https://doc.rust-lang.org/book/documentation.html#documentation-as-tests - /// # fn main() { - /// let msg = "To really appreciate architecture, you may even need to commit a murder"; - /// let s = Scalar::hash_from_bytes::(msg.as_bytes()); - /// # } - /// ``` - pub fn hash_from_bytes(input: &[u8]) -> Scalar - where D: Digest + Default - { - let mut hash = D::default(); - hash.update(input); - Scalar::from_hash(hash) - } - - /// Construct a scalar from an existing `Digest` instance. - /// - /// Use this instead of `hash_from_bytes` if it is more convenient - /// to stream data into the `Digest` than to pass a single byte - /// slice. - /// - /// # Example - /// - /// ``` - /// # extern crate curve25519_dalek; - /// # use curve25519_dalek::scalar::Scalar; - /// extern crate sha2; - /// - /// use sha2::Digest; - /// use sha2::Sha512; - /// - /// # fn main() { - /// let mut h = Sha512::new() - /// .chain("To really appreciate architecture, you may even need to commit a murder.") - /// .chain("While the programs used for The Manhattan Transcripts are of the most extreme") - /// .chain("nature, they also parallel the most common formula plot: the archetype of") - /// .chain("murder. Other phantasms were occasionally used to underline the fact that") - /// .chain("perhaps all architecture, rather than being about functional standards, is") - /// .chain("about love and death."); - /// - /// let s = Scalar::from_hash(h); - /// - /// println!("{:?}", s.to_bytes()); - /// assert!(s == Scalar::from_bits([ 21, 88, 208, 252, 63, 122, 210, 152, - /// 154, 38, 15, 23, 16, 167, 80, 150, - /// 192, 221, 77, 226, 62, 25, 224, 148, - /// 239, 48, 176, 10, 185, 69, 168, 11, ])); - /// # } - /// ``` - pub fn from_hash(hash: D) -> Scalar - where D: Digest - { - let mut output = [0u8; 64]; - output.copy_from_slice(hash.finalize().as_slice()); - Scalar::from_bytes_mod_order_wide(&output) - } - - /// Convert this `Scalar` to its underlying sequence of bytes. - /// - /// # Example - /// - /// ``` - /// use curve25519_dalek::scalar::Scalar; - /// - /// let s: Scalar = Scalar::zero(); - /// - /// assert!(s.to_bytes() == [0u8; 32]); - /// ``` - pub fn to_bytes(&self) -> [u8; 32] { - self.bytes - } - - /// View the little-endian byte encoding of the integer representing this Scalar. - /// - /// # Example - /// - /// ``` - /// use curve25519_dalek::scalar::Scalar; - /// - /// let s: Scalar = Scalar::zero(); - /// - /// assert!(s.as_bytes() == &[0u8; 32]); - /// ``` - pub fn as_bytes(&self) -> &[u8; 32] { - &self.bytes - } - - /// Construct the scalar \\( 0 \\). - pub fn zero() -> Self { - Scalar { bytes: [0u8; 32]} - } - - /// Construct the scalar \\( 1 \\). - pub fn one() -> Self { - Scalar { - bytes: [ - 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - ], - } - } - - /// Given a nonzero `Scalar`, compute its multiplicative inverse. - /// - /// # Warning - /// - /// `self` **MUST** be nonzero. If you cannot - /// *prove* that this is the case, you **SHOULD NOT USE THIS - /// FUNCTION**. - /// - /// # Returns - /// - /// The multiplicative inverse of the this `Scalar`. - /// - /// # Example - /// - /// ``` - /// use curve25519_dalek::scalar::Scalar; - /// - /// // x = 2238329342913194256032495932344128051776374960164957527413114840482143558222 - /// let X: Scalar = Scalar::from_bytes_mod_order([ - /// 0x4e, 0x5a, 0xb4, 0x34, 0x5d, 0x47, 0x08, 0x84, - /// 0x59, 0x13, 0xb4, 0x64, 0x1b, 0xc2, 0x7d, 0x52, - /// 0x52, 0xa5, 0x85, 0x10, 0x1b, 0xcc, 0x42, 0x44, - /// 0xd4, 0x49, 0xf4, 0xa8, 0x79, 0xd9, 0xf2, 0x04, - /// ]); - /// // 1/x = 6859937278830797291664592131120606308688036382723378951768035303146619657244 - /// let XINV: Scalar = Scalar::from_bytes_mod_order([ - /// 0x1c, 0xdc, 0x17, 0xfc, 0xe0, 0xe9, 0xa5, 0xbb, - /// 0xd9, 0x24, 0x7e, 0x56, 0xbb, 0x01, 0x63, 0x47, - /// 0xbb, 0xba, 0x31, 0xed, 0xd5, 0xa9, 0xbb, 0x96, - /// 0xd5, 0x0b, 0xcd, 0x7a, 0x3f, 0x96, 0x2a, 0x0f, - /// ]); - /// - /// let inv_X: Scalar = X.invert(); - /// assert!(XINV == inv_X); - /// let should_be_one: Scalar = &inv_X * &X; - /// assert!(should_be_one == Scalar::one()); - /// ``` - pub fn invert(&self) -> Scalar { - self.unpack().invert().pack() - } - - /// Given a slice of nonzero (possibly secret) `Scalar`s, - /// compute their inverses in a batch. - /// - /// # Return - /// - /// Each element of `inputs` is replaced by its inverse. - /// - /// The product of all inverses is returned. - /// - /// # Warning - /// - /// All input `Scalars` **MUST** be nonzero. If you cannot - /// *prove* that this is the case, you **SHOULD NOT USE THIS - /// FUNCTION**. - /// - /// # Example - /// - /// ``` - /// # extern crate curve25519_dalek; - /// # use curve25519_dalek::scalar::Scalar; - /// # fn main() { - /// let mut scalars = [ - /// Scalar::from(3u64), - /// Scalar::from(5u64), - /// Scalar::from(7u64), - /// Scalar::from(11u64), - /// ]; - /// - /// let allinv = Scalar::batch_invert(&mut scalars); - /// - /// assert_eq!(allinv, Scalar::from(3*5*7*11u64).invert()); - /// assert_eq!(scalars[0], Scalar::from(3u64).invert()); - /// assert_eq!(scalars[1], Scalar::from(5u64).invert()); - /// assert_eq!(scalars[2], Scalar::from(7u64).invert()); - /// assert_eq!(scalars[3], Scalar::from(11u64).invert()); - /// # } - /// ``` - #[cfg(feature = "alloc")] - pub fn batch_invert(inputs: &mut [Scalar]) -> Scalar { - // This code is essentially identical to the FieldElement - // implementation, and is documented there. Unfortunately, - // it's not easy to write it generically, since here we want - // to use `UnpackedScalar`s internally, and `Scalar`s - // externally, but there's no corresponding distinction for - // field elements. - - use zeroize::Zeroizing; - - let n = inputs.len(); - let one: UnpackedScalar = Scalar::one().unpack().to_montgomery(); - - // Place scratch storage in a Zeroizing wrapper to wipe it when - // we pass out of scope. - let scratch_vec = vec![one; n]; - let mut scratch = Zeroizing::new(scratch_vec); - - // Keep an accumulator of all of the previous products - let mut acc = Scalar::one().unpack().to_montgomery(); - - // Pass through the input vector, recording the previous - // products in the scratch space - for (input, scratch) in inputs.iter_mut().zip(scratch.iter_mut()) { - *scratch = acc; - - // Avoid unnecessary Montgomery multiplication in second pass by - // keeping inputs in Montgomery form - let tmp = input.unpack().to_montgomery(); - *input = tmp.pack(); - acc = UnpackedScalar::montgomery_mul(&acc, &tmp); - } - - // acc is nonzero iff all inputs are nonzero - debug_assert!(acc.pack() != Scalar::zero()); - - // Compute the inverse of all products - acc = acc.montgomery_invert().from_montgomery(); - - // We need to return the product of all inverses later - let ret = acc.pack(); - - // Pass through the vector backwards to compute the inverses - // in place - for (input, scratch) in inputs.iter_mut().rev().zip(scratch.iter().rev()) { - let tmp = UnpackedScalar::montgomery_mul(&acc, &input.unpack()); - *input = UnpackedScalar::montgomery_mul(&acc, &scratch).pack(); - acc = tmp; - } - - ret - } - - /// Get the bits of the scalar. - pub(crate) fn bits(&self) -> [i8; 256] { - let mut bits = [0i8; 256]; - for i in 0..256 { - // As i runs from 0..256, the bottom 3 bits index the bit, - // while the upper bits index the byte. - bits[i] = ((self.bytes[i>>3] >> (i&7)) & 1u8) as i8; - } - bits - } - - /// Compute a width-\\(w\\) "Non-Adjacent Form" of this scalar. - /// - /// A width-\\(w\\) NAF of a positive integer \\(k\\) is an expression - /// $$ - /// k = \sum_{i=0}\^m n\_i 2\^i, - /// $$ - /// where each nonzero - /// coefficient \\(n\_i\\) is odd and bounded by \\(|n\_i| < 2\^{w-1}\\), - /// \\(n\_{m-1}\\) is nonzero, and at most one of any \\(w\\) consecutive - /// coefficients is nonzero. (Hankerson, Menezes, Vanstone; def 3.32). - /// - /// The length of the NAF is at most one more than the length of - /// the binary representation of \\(k\\). This is why the - /// `Scalar` type maintains an invariant that the top bit is - /// \\(0\\), so that the NAF of a scalar has at most 256 digits. - /// - /// Intuitively, this is like a binary expansion, except that we - /// allow some coefficients to grow in magnitude up to - /// \\(2\^{w-1}\\) so that the nonzero coefficients are as sparse - /// as possible. - /// - /// When doing scalar multiplication, we can then use a lookup - /// table of precomputed multiples of a point to add the nonzero - /// terms \\( k_i P \\). Using signed digits cuts the table size - /// in half, and using odd digits cuts the table size in half - /// again. - /// - /// To compute a \\(w\\)-NAF, we use a modification of Algorithm 3.35 of HMV: - /// - /// 1. \\( i \gets 0 \\) - /// 2. While \\( k \ge 1 \\): - /// 1. If \\(k\\) is odd, \\( n_i \gets k \operatorname{mods} 2^w \\), \\( k \gets k - n_i \\). - /// 2. If \\(k\\) is even, \\( n_i \gets 0 \\). - /// 3. \\( k \gets k / 2 \\), \\( i \gets i + 1 \\). - /// 3. Return \\( n_0, n_1, ... , \\) - /// - /// Here \\( \bar x = x \operatorname{mods} 2^w \\) means the - /// \\( \bar x \\) with \\( \bar x \equiv x \pmod{2^w} \\) and - /// \\( -2^{w-1} \leq \bar x < 2^w \\). - /// - /// We implement this by scanning across the bits of \\(k\\) from - /// least-significant bit to most-significant-bit. - /// Write the bits of \\(k\\) as - /// $$ - /// k = \sum\_{i=0}\^m k\_i 2^i, - /// $$ - /// and split the sum as - /// $$ - /// k = \sum\_{i=0}^{w-1} k\_i 2^i + 2^w \sum\_{i=0} k\_{i+w} 2^i - /// $$ - /// where the first part is \\( k \mod 2^w \\). - /// - /// If \\( k \mod 2^w\\) is odd, and \\( k \mod 2^w < 2^{w-1} \\), then we emit - /// \\( n_0 = k \mod 2^w \\). Instead of computing - /// \\( k - n_0 \\), we just advance \\(w\\) bits and reindex. - /// - /// If \\( k \mod 2^w\\) is odd, and \\( k \mod 2^w \ge 2^{w-1} \\), then - /// \\( n_0 = k \operatorname{mods} 2^w = k \mod 2^w - 2^w \\). - /// The quantity \\( k - n_0 \\) is - /// $$ - /// \begin{aligned} - /// k - n_0 &= \sum\_{i=0}^{w-1} k\_i 2^i + 2^w \sum\_{i=0} k\_{i+w} 2^i - /// - \sum\_{i=0}^{w-1} k\_i 2^i + 2^w \\\\ - /// &= 2^w + 2^w \sum\_{i=0} k\_{i+w} 2^i - /// \end{aligned} - /// $$ - /// so instead of computing the subtraction, we can set a carry - /// bit, advance \\(w\\) bits, and reindex. - /// - /// If \\( k \mod 2^w\\) is even, we emit \\(0\\), advance 1 bit - /// and reindex. In fact, by setting all digits to \\(0\\) - /// initially, we don't need to emit anything. - pub(crate) fn non_adjacent_form(&self, w: usize) -> [i8; 256] { - // required by the NAF definition - debug_assert!( w >= 2 ); - // required so that the NAF digits fit in i8 - debug_assert!( w <= 8 ); - - use byteorder::{ByteOrder, LittleEndian}; - - let mut naf = [0i8; 256]; - - let mut x_u64 = [0u64; 5]; - LittleEndian::read_u64_into(&self.bytes, &mut x_u64[0..4]); - - let width = 1 << w; - let window_mask = width - 1; - - let mut pos = 0; - let mut carry = 0; - while pos < 256 { - // Construct a buffer of bits of the scalar, starting at bit `pos` - let u64_idx = pos / 64; - let bit_idx = pos % 64; - let bit_buf: u64; - if bit_idx < 64 - w { - // This window's bits are contained in a single u64 - bit_buf = x_u64[u64_idx] >> bit_idx; - } else { - // Combine the current u64's bits with the bits from the next u64 - bit_buf = (x_u64[u64_idx] >> bit_idx) | (x_u64[1+u64_idx] << (64 - bit_idx)); - } - - // Add the carry into the current window - let window = carry + (bit_buf & window_mask); - - if window & 1 == 0 { - // If the window value is even, preserve the carry and continue. - // Why is the carry preserved? - // If carry == 0 and window & 1 == 0, then the next carry should be 0 - // If carry == 1 and window & 1 == 0, then bit_buf & 1 == 1 so the next carry should be 1 - pos += 1; - continue; - } - - if window < width/2 { - carry = 0; - naf[pos] = window as i8; - } else { - carry = 1; - naf[pos] = (window as i8).wrapping_sub(width as i8); - } - - pos += w; - } - - naf - } - - /// Write this scalar in radix 16, with coefficients in \\([-8,8)\\), - /// i.e., compute \\(a\_i\\) such that - /// $$ - /// a = a\_0 + a\_1 16\^1 + \cdots + a_{63} 16\^{63}, - /// $$ - /// with \\(-8 \leq a_i < 8\\) for \\(0 \leq i < 63\\) and \\(-8 \leq a_{63} \leq 8\\). - pub(crate) fn to_radix_16(&self) -> [i8; 64] { - debug_assert!(self[31] <= 127); - let mut output = [0i8; 64]; - - // Step 1: change radix. - // Convert from radix 256 (bytes) to radix 16 (nibbles) - #[inline(always)] - fn bot_half(x: u8) -> u8 { (x >> 0) & 15 } - #[inline(always)] - fn top_half(x: u8) -> u8 { (x >> 4) & 15 } - - for i in 0..32 { - output[2*i ] = bot_half(self[i]) as i8; - output[2*i+1] = top_half(self[i]) as i8; - } - // Precondition note: since self[31] <= 127, output[63] <= 7 - - // Step 2: recenter coefficients from [0,16) to [-8,8) - for i in 0..63 { - let carry = (output[i] + 8) >> 4; - output[i ] -= carry << 4; - output[i+1] += carry; - } - // Precondition note: output[63] is not recentered. It - // increases by carry <= 1. Thus output[63] <= 8. - - output - } - - /// Returns a size hint indicating how many entries of the return - /// value of `to_radix_2w` are nonzero. - pub(crate) fn to_radix_2w_size_hint(w: usize) -> usize { - debug_assert!(w >= 4); - debug_assert!(w <= 8); - - let digits_count = match w { - 4 => (256 + w - 1)/w as usize, - 5 => (256 + w - 1)/w as usize, - 6 => (256 + w - 1)/w as usize, - 7 => (256 + w - 1)/w as usize, - // See comment in to_radix_2w on handling the terminal carry. - 8 => (256 + w - 1)/w + 1 as usize, - _ => panic!("invalid radix parameter"), - }; - - debug_assert!(digits_count <= 64); - digits_count - } - - /// Creates a representation of a Scalar in radix 32, 64, 128 or 256 for use with the Pippenger algorithm. - /// For lower radix, use `to_radix_16`, which is used by the Straus multi-scalar multiplication. - /// Higher radixes are not supported to save cache space. Radix 256 is near-optimal even for very - /// large inputs. - /// - /// Radix below 32 or above 256 is prohibited. - /// This method returns digits in a fixed-sized array, excess digits are zeroes. - /// - /// ## Scalar representation - /// - /// Radix \\(2\^w\\), with \\(n = ceil(256/w)\\) coefficients in \\([-(2\^w)/2,(2\^w)/2)\\), - /// i.e., scalar is represented using digits \\(a\_i\\) such that - /// $$ - /// a = a\_0 + a\_1 2\^1w + \cdots + a_{n-1} 2\^{w*(n-1)}, - /// $$ - /// with \\(-2\^w/2 \leq a_i < 2\^w/2\\) for \\(0 \leq i < (n-1)\\) and \\(-2\^w/2 \leq a_{n-1} \leq 2\^w/2\\). - /// - pub(crate) fn to_radix_2w(&self, w: usize) -> [i8; 64] { - debug_assert!(w >= 4); - debug_assert!(w <= 8); - - if w == 4 { - return self.to_radix_16(); - } - - use byteorder::{ByteOrder, LittleEndian}; - - // Scalar formatted as four `u64`s with carry bit packed into the highest bit. - let mut scalar64x4 = [0u64; 4]; - LittleEndian::read_u64_into(&self.bytes, &mut scalar64x4[0..4]); - - let radix: u64 = 1 << w; - let window_mask: u64 = radix - 1; - - let mut carry = 0u64; - let mut digits = [0i8; 64]; - let digits_count = (256 + w - 1)/w as usize; - for i in 0..digits_count { - // Construct a buffer of bits of the scalar, starting at `bit_offset`. - let bit_offset = i*w; - let u64_idx = bit_offset / 64; - let bit_idx = bit_offset % 64; - - // Read the bits from the scalar - let bit_buf: u64; - if bit_idx < 64 - w || u64_idx == 3 { - // This window's bits are contained in a single u64, - // or it's the last u64 anyway. - bit_buf = scalar64x4[u64_idx] >> bit_idx; - } else { - // Combine the current u64's bits with the bits from the next u64 - bit_buf = (scalar64x4[u64_idx] >> bit_idx) | (scalar64x4[1+u64_idx] << (64 - bit_idx)); - } - - // Read the actual coefficient value from the window - let coef = carry + (bit_buf & window_mask); // coef = [0, 2^r) - - // Recenter coefficients from [0,2^w) to [-2^w/2, 2^w/2) - carry = (coef + (radix/2) as u64) >> w; - digits[i] = ((coef as i64) - (carry << w) as i64) as i8; - } - - // When w < 8, we can fold the final carry onto the last digit d, - // because d < 2^w/2 so d + carry*2^w = d + 1*2^w < 2^(w+1) < 2^8. - // - // When w = 8, we can't fit carry*2^w into an i8. This should - // not happen anyways, because the final carry will be 0 for - // reduced scalars, but the Scalar invariant allows 255-bit scalars. - // To handle this, we expand the size_hint by 1 when w=8, - // and accumulate the final carry onto another digit. - match w { - 8 => digits[digits_count] += carry as i8, - _ => digits[digits_count-1] += (carry << w) as i8, - } - - digits - } - - /// Unpack this `Scalar` to an `UnpackedScalar` for faster arithmetic. - pub(crate) fn unpack(&self) -> UnpackedScalar { - UnpackedScalar::from_bytes(&self.bytes) - } - - /// Reduce this `Scalar` modulo \\(\ell\\). - #[allow(non_snake_case)] - pub fn reduce(&self) -> Scalar { - let x = self.unpack(); - let xR = UnpackedScalar::mul_internal(&x, &constants::R); - let x_mod_l = UnpackedScalar::montgomery_reduce(&xR); - x_mod_l.pack() - } - - /// Check whether this `Scalar` is the canonical representative mod \\(\ell\\). - /// - /// This is intended for uses like input validation, where variable-time code is acceptable. - /// - /// ``` - /// # extern crate curve25519_dalek; - /// # extern crate subtle; - /// # use curve25519_dalek::scalar::Scalar; - /// # use subtle::ConditionallySelectable; - /// # fn main() { - /// // 2^255 - 1, since `from_bits` clears the high bit - /// let _2_255_minus_1 = Scalar::from_bits([0xff;32]); - /// assert!(!_2_255_minus_1.is_canonical()); - /// - /// let reduced = _2_255_minus_1.reduce(); - /// assert!(reduced.is_canonical()); - /// # } - /// ``` - pub fn is_canonical(&self) -> bool { - *self == self.reduce() - } -} - -impl UnpackedScalar { - /// Pack the limbs of this `UnpackedScalar` into a `Scalar`. - fn pack(&self) -> Scalar { - Scalar{ bytes: self.to_bytes() } - } - - /// Inverts an UnpackedScalar in Montgomery form. - pub fn montgomery_invert(&self) -> UnpackedScalar { - // Uses the addition chain from - // https://briansmith.org/ecc-inversion-addition-chains-01#curve25519_scalar_inversion - let _1 = self; - let _10 = _1.montgomery_square(); - let _100 = _10.montgomery_square(); - let _11 = UnpackedScalar::montgomery_mul(&_10, &_1); - let _101 = UnpackedScalar::montgomery_mul(&_10, &_11); - let _111 = UnpackedScalar::montgomery_mul(&_10, &_101); - let _1001 = UnpackedScalar::montgomery_mul(&_10, &_111); - let _1011 = UnpackedScalar::montgomery_mul(&_10, &_1001); - let _1111 = UnpackedScalar::montgomery_mul(&_100, &_1011); - - // _10000 - let mut y = UnpackedScalar::montgomery_mul(&_1111, &_1); - - #[inline] - fn square_multiply(y: &mut UnpackedScalar, squarings: usize, x: &UnpackedScalar) { - for _ in 0..squarings { - *y = y.montgomery_square(); - } - *y = UnpackedScalar::montgomery_mul(y, x); - } - - square_multiply(&mut y, 123 + 3, &_101); - square_multiply(&mut y, 2 + 2, &_11); - square_multiply(&mut y, 1 + 4, &_1111); - square_multiply(&mut y, 1 + 4, &_1111); - square_multiply(&mut y, 4, &_1001); - square_multiply(&mut y, 2, &_11); - square_multiply(&mut y, 1 + 4, &_1111); - square_multiply(&mut y, 1 + 3, &_101); - square_multiply(&mut y, 3 + 3, &_101); - square_multiply(&mut y, 3, &_111); - square_multiply(&mut y, 1 + 4, &_1111); - square_multiply(&mut y, 2 + 3, &_111); - square_multiply(&mut y, 2 + 2, &_11); - square_multiply(&mut y, 1 + 4, &_1011); - square_multiply(&mut y, 2 + 4, &_1011); - square_multiply(&mut y, 6 + 4, &_1001); - square_multiply(&mut y, 2 + 2, &_11); - square_multiply(&mut y, 3 + 2, &_11); - square_multiply(&mut y, 3 + 2, &_11); - square_multiply(&mut y, 1 + 4, &_1001); - square_multiply(&mut y, 1 + 3, &_111); - square_multiply(&mut y, 2 + 4, &_1111); - square_multiply(&mut y, 1 + 4, &_1011); - square_multiply(&mut y, 3, &_101); - square_multiply(&mut y, 2 + 4, &_1111); - square_multiply(&mut y, 3, &_101); - square_multiply(&mut y, 1 + 2, &_11); - - y - } - - /// Inverts an UnpackedScalar not in Montgomery form. - pub fn invert(&self) -> UnpackedScalar { - self.to_montgomery().montgomery_invert().from_montgomery() - } -} - -#[cfg(test)] -mod test { - use super::*; - use constants; - - /// x = 2238329342913194256032495932344128051776374960164957527413114840482143558222 - pub static X: Scalar = Scalar{ - bytes: [ - 0x4e, 0x5a, 0xb4, 0x34, 0x5d, 0x47, 0x08, 0x84, - 0x59, 0x13, 0xb4, 0x64, 0x1b, 0xc2, 0x7d, 0x52, - 0x52, 0xa5, 0x85, 0x10, 0x1b, 0xcc, 0x42, 0x44, - 0xd4, 0x49, 0xf4, 0xa8, 0x79, 0xd9, 0xf2, 0x04, - ], - }; - /// 1/x = 6859937278830797291664592131120606308688036382723378951768035303146619657244 - pub static XINV: Scalar = Scalar{ - bytes: [ - 0x1c, 0xdc, 0x17, 0xfc, 0xe0, 0xe9, 0xa5, 0xbb, - 0xd9, 0x24, 0x7e, 0x56, 0xbb, 0x01, 0x63, 0x47, - 0xbb, 0xba, 0x31, 0xed, 0xd5, 0xa9, 0xbb, 0x96, - 0xd5, 0x0b, 0xcd, 0x7a, 0x3f, 0x96, 0x2a, 0x0f, - ], - }; - /// y = 2592331292931086675770238855846338635550719849568364935475441891787804997264 - pub static Y: Scalar = Scalar{ - bytes: [ - 0x90, 0x76, 0x33, 0xfe, 0x1c, 0x4b, 0x66, 0xa4, - 0xa2, 0x8d, 0x2d, 0xd7, 0x67, 0x83, 0x86, 0xc3, - 0x53, 0xd0, 0xde, 0x54, 0x55, 0xd4, 0xfc, 0x9d, - 0xe8, 0xef, 0x7a, 0xc3, 0x1f, 0x35, 0xbb, 0x05, - ], - }; - - /// x*y = 5690045403673944803228348699031245560686958845067437804563560795922180092780 - static X_TIMES_Y: Scalar = Scalar{ - bytes: [ - 0x6c, 0x33, 0x74, 0xa1, 0x89, 0x4f, 0x62, 0x21, - 0x0a, 0xaa, 0x2f, 0xe1, 0x86, 0xa6, 0xf9, 0x2c, - 0xe0, 0xaa, 0x75, 0xc2, 0x77, 0x95, 0x81, 0xc2, - 0x95, 0xfc, 0x08, 0x17, 0x9a, 0x73, 0x94, 0x0c, - ], - }; - - /// sage: l = 2^252 + 27742317777372353535851937790883648493 - /// sage: big = 2^256 - 1 - /// sage: repr((big % l).digits(256)) - static CANONICAL_2_256_MINUS_1: Scalar = Scalar{ - bytes: [ - 28, 149, 152, 141, 116, 49, 236, 214, - 112, 207, 125, 115, 244, 91, 239, 198, - 254, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 15, - ], - }; - - static A_SCALAR: Scalar = Scalar{ - bytes: [ - 0x1a, 0x0e, 0x97, 0x8a, 0x90, 0xf6, 0x62, 0x2d, - 0x37, 0x47, 0x02, 0x3f, 0x8a, 0xd8, 0x26, 0x4d, - 0xa7, 0x58, 0xaa, 0x1b, 0x88, 0xe0, 0x40, 0xd1, - 0x58, 0x9e, 0x7b, 0x7f, 0x23, 0x76, 0xef, 0x09, - ], - }; - - static A_NAF: [i8; 256] = - [0,13,0,0,0,0,0,0,0,7,0,0,0,0,0,0,-9,0,0,0,0,-11,0,0,0,0,3,0,0,0,0,1, - 0,0,0,0,9,0,0,0,0,-5,0,0,0,0,0,0,3,0,0,0,0,11,0,0,0,0,11,0,0,0,0,0, - -9,0,0,0,0,0,-3,0,0,0,0,9,0,0,0,0,0,1,0,0,0,0,0,0,-1,0,0,0,0,0,9,0, - 0,0,0,-15,0,0,0,0,-7,0,0,0,0,-9,0,0,0,0,0,5,0,0,0,0,13,0,0,0,0,0,-3,0, - 0,0,0,-11,0,0,0,0,-7,0,0,0,0,-13,0,0,0,0,11,0,0,0,0,-9,0,0,0,0,0,1,0,0, - 0,0,0,-15,0,0,0,0,1,0,0,0,0,7,0,0,0,0,0,0,0,0,5,0,0,0,0,0,13,0,0,0, - 0,0,0,11,0,0,0,0,0,15,0,0,0,0,0,-9,0,0,0,0,0,0,0,-1,0,0,0,0,0,0,0,7, - 0,0,0,0,0,-15,0,0,0,0,0,15,0,0,0,0,15,0,0,0,0,15,0,0,0,0,0,1,0,0,0,0]; - - static LARGEST_ED25519_S: Scalar = Scalar { - bytes: [ - 0xf8, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, - ], - }; - - static CANONICAL_LARGEST_ED25519_S_PLUS_ONE: Scalar = Scalar { - bytes: [ - 0x7e, 0x34, 0x47, 0x75, 0x47, 0x4a, 0x7f, 0x97, - 0x23, 0xb6, 0x3a, 0x8b, 0xe9, 0x2a, 0xe7, 0x6d, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0f, - ], - }; - - static CANONICAL_LARGEST_ED25519_S_MINUS_ONE: Scalar = Scalar { - bytes: [ - 0x7c, 0x34, 0x47, 0x75, 0x47, 0x4a, 0x7f, 0x97, - 0x23, 0xb6, 0x3a, 0x8b, 0xe9, 0x2a, 0xe7, 0x6d, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0f, - ], - }; - - #[test] - fn fuzzer_testcase_reduction() { - // LE bytes of 24519928653854221733733552434404946937899825954937634815 - let a_bytes = [255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 0, 0, 0, 0, 0, 0, 0, 0, 0]; - // LE bytes of 4975441334397345751130612518500927154628011511324180036903450236863266160640 - let b_bytes = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 210, 210, 210, 255, 255, 255, 255, 10]; - // LE bytes of 6432735165214683820902750800207468552549813371247423777071615116673864412038 - let c_bytes = [134, 171, 119, 216, 180, 128, 178, 62, 171, 132, 32, 62, 34, 119, 104, 193, 47, 215, 181, 250, 14, 207, 172, 93, 75, 207, 211, 103, 144, 204, 56, 14]; - - let a = Scalar::from_bytes_mod_order(a_bytes); - let b = Scalar::from_bytes_mod_order(b_bytes); - let c = Scalar::from_bytes_mod_order(c_bytes); - - let mut tmp = [0u8; 64]; - - // also_a = (a mod l) - tmp[0..32].copy_from_slice(&a_bytes[..]); - let also_a = Scalar::from_bytes_mod_order_wide(&tmp); - - // also_b = (b mod l) - tmp[0..32].copy_from_slice(&b_bytes[..]); - let also_b = Scalar::from_bytes_mod_order_wide(&tmp); - - let expected_c = &a * &b; - let also_expected_c = &also_a * &also_b; - - assert_eq!(c, expected_c); - assert_eq!(c, also_expected_c); - } - - #[test] - fn non_adjacent_form_test_vector() { - let naf = A_SCALAR.non_adjacent_form(5); - for i in 0..256 { - assert_eq!(naf[i], A_NAF[i]); - } - } - - fn non_adjacent_form_iter(w: usize, x: &Scalar) { - let naf = x.non_adjacent_form(w); - - // Reconstruct the scalar from the computed NAF - let mut y = Scalar::zero(); - for i in (0..256).rev() { - y += y; - let digit = if naf[i] < 0 { - -Scalar::from((-naf[i]) as u64) - } else { - Scalar::from(naf[i] as u64) - }; - y += digit; - } - - assert_eq!(*x, y); - } - - #[test] - fn non_adjacent_form_random() { - let mut rng = rand::thread_rng(); - for _ in 0..1_000 { - let x = Scalar::random(&mut rng); - for w in &[5, 6, 7, 8] { - non_adjacent_form_iter(*w, &x); - } - } - } - - #[test] - fn from_u64() { - let val: u64 = 0xdeadbeefdeadbeef; - let s = Scalar::from(val); - assert_eq!(s[7], 0xde); - assert_eq!(s[6], 0xad); - assert_eq!(s[5], 0xbe); - assert_eq!(s[4], 0xef); - assert_eq!(s[3], 0xde); - assert_eq!(s[2], 0xad); - assert_eq!(s[1], 0xbe); - assert_eq!(s[0], 0xef); - } - - #[test] - fn scalar_mul_by_one() { - let test_scalar = &X * &Scalar::one(); - for i in 0..32 { - assert!(test_scalar[i] == X[i]); - } - } - - #[test] - fn add_reduces() { - // Check that the addition works - assert_eq!( - (LARGEST_ED25519_S + Scalar::one()).reduce(), - CANONICAL_LARGEST_ED25519_S_PLUS_ONE - ); - // Check that the addition reduces - assert_eq!( - LARGEST_ED25519_S + Scalar::one(), - CANONICAL_LARGEST_ED25519_S_PLUS_ONE - ); - } - - #[test] - fn sub_reduces() { - // Check that the subtraction works - assert_eq!( - (LARGEST_ED25519_S - Scalar::one()).reduce(), - CANONICAL_LARGEST_ED25519_S_MINUS_ONE - ); - // Check that the subtraction reduces - assert_eq!( - LARGEST_ED25519_S - Scalar::one(), - CANONICAL_LARGEST_ED25519_S_MINUS_ONE - ); - } - - #[test] - fn quarkslab_scalar_overflow_does_not_occur() { - // Check that manually-constructing large Scalars with - // from_bits cannot produce incorrect results. - // - // The from_bits function is required to implement X/Ed25519, - // while all other methods of constructing a Scalar produce - // reduced Scalars. However, this "invariant loophole" allows - // constructing large scalars which are not reduced mod l. - // - // This issue was discovered independently by both Jack - // "str4d" Grigg (issue #238), who noted that reduction was - // not performed on addition, and Laurent Grémy & Nicolas - // Surbayrole of Quarkslab, who noted that it was possible to - // cause an overflow and compute incorrect results. - // - // This test is adapted from the one suggested by Quarkslab. - - let large_bytes = [ - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, - ]; - - let a = Scalar::from_bytes_mod_order(large_bytes); - let b = Scalar::from_bits(large_bytes); - - assert_eq!(a, b.reduce()); - - let a_3 = a + a + a; - let b_3 = b + b + b; - - assert_eq!(a_3, b_3); - - let neg_a = -a; - let neg_b = -b; - - assert_eq!(neg_a, neg_b); - - let minus_a_3 = Scalar::zero() - a - a - a; - let minus_b_3 = Scalar::zero() - b - b - b; - - assert_eq!(minus_a_3, minus_b_3); - assert_eq!(minus_a_3, -a_3); - assert_eq!(minus_b_3, -b_3); - } - - #[test] - fn impl_add() { - let two = Scalar::from(2u64); - let one = Scalar::one(); - let should_be_two = &one + &one; - assert_eq!(should_be_two, two); - } - - #[allow(non_snake_case)] - #[test] - fn impl_mul() { - let should_be_X_times_Y = &X * &Y; - assert_eq!(should_be_X_times_Y, X_TIMES_Y); - } - - #[allow(non_snake_case)] - #[test] - fn impl_product() { - // Test that product works for non-empty iterators - let X_Y_vector = vec![X, Y]; - let should_be_X_times_Y: Scalar = X_Y_vector.iter().product(); - assert_eq!(should_be_X_times_Y, X_TIMES_Y); - - // Test that product works for the empty iterator - let one = Scalar::one(); - let empty_vector = vec![]; - let should_be_one: Scalar = empty_vector.iter().product(); - assert_eq!(should_be_one, one); - - // Test that product works for iterators where Item = Scalar - let xs = [Scalar::from(2u64); 10]; - let ys = [Scalar::from(3u64); 10]; - // now zs is an iterator with Item = Scalar - let zs = xs.iter().zip(ys.iter()).map(|(x,y)| x * y); - - let x_prod: Scalar = xs.iter().product(); - let y_prod: Scalar = ys.iter().product(); - let z_prod: Scalar = zs.product(); - - assert_eq!(x_prod, Scalar::from(1024u64)); - assert_eq!(y_prod, Scalar::from(59049u64)); - assert_eq!(z_prod, Scalar::from(60466176u64)); - assert_eq!(x_prod * y_prod, z_prod); - - } - - #[test] - fn impl_sum() { - - // Test that sum works for non-empty iterators - let two = Scalar::from(2u64); - let one_vector = vec![Scalar::one(), Scalar::one()]; - let should_be_two: Scalar = one_vector.iter().sum(); - assert_eq!(should_be_two, two); - - // Test that sum works for the empty iterator - let zero = Scalar::zero(); - let empty_vector = vec![]; - let should_be_zero: Scalar = empty_vector.iter().sum(); - assert_eq!(should_be_zero, zero); - - // Test that sum works for owned types - let xs = [Scalar::from(1u64); 10]; - let ys = [Scalar::from(2u64); 10]; - // now zs is an iterator with Item = Scalar - let zs = xs.iter().zip(ys.iter()).map(|(x,y)| x + y); - - let x_sum: Scalar = xs.iter().sum(); - let y_sum: Scalar = ys.iter().sum(); - let z_sum: Scalar = zs.sum(); - - assert_eq!(x_sum, Scalar::from(10u64)); - assert_eq!(y_sum, Scalar::from(20u64)); - assert_eq!(z_sum, Scalar::from(30u64)); - assert_eq!(x_sum + y_sum, z_sum); - } - - #[test] - fn square() { - let expected = &X * &X; - let actual = X.unpack().square().pack(); - for i in 0..32 { - assert!(expected[i] == actual[i]); - } - } - - #[test] - fn reduce() { - let biggest = Scalar::from_bytes_mod_order([0xff; 32]); - assert_eq!(biggest, CANONICAL_2_256_MINUS_1); - } - - #[test] - fn from_bytes_mod_order_wide() { - let mut bignum = [0u8; 64]; - // set bignum = x + 2^256x - for i in 0..32 { - bignum[ i] = X[i]; - bignum[32+i] = X[i]; - } - // 3958878930004874126169954872055634648693766179881526445624823978500314864344 - // = x + 2^256x (mod l) - let reduced = Scalar{ - bytes: [ - 216, 154, 179, 139, 210, 121, 2, 71, - 69, 99, 158, 216, 23, 173, 63, 100, - 204, 0, 91, 50, 219, 153, 57, 249, - 28, 82, 31, 197, 100, 165, 192, 8, - ], - }; - let test_red = Scalar::from_bytes_mod_order_wide(&bignum); - for i in 0..32 { - assert!(test_red[i] == reduced[i]); - } - } - - #[allow(non_snake_case)] - #[test] - fn invert() { - let inv_X = X.invert(); - assert_eq!(inv_X, XINV); - let should_be_one = &inv_X * &X; - assert_eq!(should_be_one, Scalar::one()); - } - - // Negating a scalar twice should result in the original scalar. - #[allow(non_snake_case)] - #[test] - fn neg_twice_is_identity() { - let negative_X = -&X; - let should_be_X = -&negative_X; - - assert_eq!(should_be_X, X); - } - - #[test] - fn to_bytes_from_bytes_roundtrips() { - let unpacked = X.unpack(); - let bytes = unpacked.to_bytes(); - let should_be_unpacked = UnpackedScalar::from_bytes(&bytes); - - assert_eq!(should_be_unpacked.0, unpacked.0); - } - - #[test] - fn montgomery_reduce_matches_from_bytes_mod_order_wide() { - let mut bignum = [0u8; 64]; - - // set bignum = x + 2^256x - for i in 0..32 { - bignum[ i] = X[i]; - bignum[32+i] = X[i]; - } - // x + 2^256x (mod l) - // = 3958878930004874126169954872055634648693766179881526445624823978500314864344 - let expected = Scalar{ - bytes: [ - 216, 154, 179, 139, 210, 121, 2, 71, - 69, 99, 158, 216, 23, 173, 63, 100, - 204, 0, 91, 50, 219, 153, 57, 249, - 28, 82, 31, 197, 100, 165, 192, 8 - ], - }; - let reduced = Scalar::from_bytes_mod_order_wide(&bignum); - - // The reduced scalar should match the expected - assert_eq!(reduced.bytes, expected.bytes); - - // (x + 2^256x) * R - let interim = UnpackedScalar::mul_internal(&UnpackedScalar::from_bytes_wide(&bignum), - &constants::R); - // ((x + 2^256x) * R) / R (mod l) - let montgomery_reduced = UnpackedScalar::montgomery_reduce(&interim); - - // The Montgomery reduced scalar should match the reduced one, as well as the expected - assert_eq!(montgomery_reduced.0, reduced.unpack().0); - assert_eq!(montgomery_reduced.0, expected.unpack().0) - } - - #[test] - fn canonical_decoding() { - // canonical encoding of 1667457891 - let canonical_bytes = [99, 99, 99, 99, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,]; - - // encoding of - // 7265385991361016183439748078976496179028704920197054998554201349516117938192 - // = 28380414028753969466561515933501938171588560817147392552250411230663687203 (mod l) - // non_canonical because unreduced mod l - let non_canonical_bytes_because_unreduced = [16; 32]; - - // encoding with high bit set, to check that the parser isn't pre-masking the high bit - let non_canonical_bytes_because_highbit = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128]; - - assert!( Scalar::from_canonical_bytes(canonical_bytes).is_some() ); - assert!( Scalar::from_canonical_bytes(non_canonical_bytes_because_unreduced).is_none() ); - assert!( Scalar::from_canonical_bytes(non_canonical_bytes_because_highbit).is_none() ); - } - - #[test] - #[cfg(feature = "serde")] - fn serde_bincode_scalar_roundtrip() { - use bincode; - let encoded = bincode::serialize(&X).unwrap(); - let parsed: Scalar = bincode::deserialize(&encoded).unwrap(); - assert_eq!(parsed, X); - - // Check that the encoding is 32 bytes exactly - assert_eq!(encoded.len(), 32); - - // Check that the encoding itself matches the usual one - assert_eq!( - X, - bincode::deserialize(X.as_bytes()).unwrap(), - ); - } - - #[cfg(debug_assertions)] - #[test] - #[should_panic] - fn batch_invert_with_a_zero_input_panics() { - let mut xs = vec![Scalar::one(); 16]; - xs[3] = Scalar::zero(); - // This should panic in debug mode. - Scalar::batch_invert(&mut xs); - } - - #[test] - fn batch_invert_empty() { - assert_eq!(Scalar::one(), Scalar::batch_invert(&mut [])); - } - - #[test] - fn batch_invert_consistency() { - let mut x = Scalar::from(1u64); - let mut v1: Vec<_> = (0..16).map(|_| {let tmp = x; x = x + x; tmp}).collect(); - let v2 = v1.clone(); - - let expected: Scalar = v1.iter().product(); - let expected = expected.invert(); - let ret = Scalar::batch_invert(&mut v1); - assert_eq!(ret, expected); - - for (a, b) in v1.iter().zip(v2.iter()) { - assert_eq!(a * b, Scalar::one()); - } - } - - fn test_pippenger_radix_iter(scalar: Scalar, w: usize) { - let digits_count = Scalar::to_radix_2w_size_hint(w); - let digits = scalar.to_radix_2w(w); - - let radix = Scalar::from((1< -// - Henry de Valence - -//! Module for common traits. - -#![allow(non_snake_case)] - -use core::borrow::Borrow; - -use subtle; - -use scalar::Scalar; - -// ------------------------------------------------------------------------ -// Public Traits -// ------------------------------------------------------------------------ - -/// Trait for getting the identity element of a point type. -pub trait Identity { - /// Returns the identity element of the curve. - /// Can be used as a constructor. - fn identity() -> Self; -} - -/// Trait for testing if a curve point is equivalent to the identity point. -pub trait IsIdentity { - /// Return true if this element is the identity element of the curve. - fn is_identity(&self) -> bool; -} - -/// Implement generic identity equality testing for a point representations -/// which have constant-time equality testing and a defined identity -/// constructor. -impl IsIdentity for T -where - T: subtle::ConstantTimeEq + Identity, -{ - fn is_identity(&self) -> bool { - self.ct_eq(&T::identity()).unwrap_u8() == 1u8 - } -} - -/// A precomputed table of basepoints, for optimising scalar multiplications. -pub trait BasepointTable { - /// The type of point contained within this table. - type Point; - - /// Generate a new precomputed basepoint table from the given basepoint. - fn create(basepoint: &Self::Point) -> Self; - - /// Retrieve the original basepoint from this table. - fn basepoint(&self) -> Self::Point; - - /// Multiply a `scalar` by this precomputed basepoint table, in constant time. - fn basepoint_mul(&self, scalar: &Scalar) -> Self::Point; -} - -/// A trait for constant-time multiscalar multiplication without precomputation. -pub trait MultiscalarMul { - /// The type of point being multiplied, e.g., `RistrettoPoint`. - type Point; - - /// Given an iterator of (possibly secret) scalars and an iterator of - /// public points, compute - /// $$ - /// Q = c\_1 P\_1 + \cdots + c\_n P\_n. - /// $$ - /// - /// It is an error to call this function with two iterators of different lengths. - /// - /// # Examples - /// - /// The trait bound aims for maximum flexibility: the inputs must be - /// convertable to iterators (`I: IntoIter`), and the iterator's items - /// must be `Borrow` (or `Borrow`), to allow - /// iterators returning either `Scalar`s or `&Scalar`s. - /// - /// ``` - /// use curve25519_dalek::constants; - /// use curve25519_dalek::traits::MultiscalarMul; - /// use curve25519_dalek::ristretto::RistrettoPoint; - /// use curve25519_dalek::scalar::Scalar; - /// - /// // Some scalars - /// let a = Scalar::from(87329482u64); - /// let b = Scalar::from(37264829u64); - /// let c = Scalar::from(98098098u64); - /// - /// // Some points - /// let P = constants::RISTRETTO_BASEPOINT_POINT; - /// let Q = P + P; - /// let R = P + Q; - /// - /// // A1 = a*P + b*Q + c*R - /// let abc = [a,b,c]; - /// let A1 = RistrettoPoint::multiscalar_mul(&abc, &[P,Q,R]); - /// // Note: (&abc).into_iter(): Iterator - /// - /// // A2 = (-a)*P + (-b)*Q + (-c)*R - /// let minus_abc = abc.iter().map(|x| -x); - /// let A2 = RistrettoPoint::multiscalar_mul(minus_abc, &[P,Q,R]); - /// // Note: minus_abc.into_iter(): Iterator - /// - /// assert_eq!(A1.compress(), (-A2).compress()); - /// ``` - fn multiscalar_mul(scalars: I, points: J) -> Self::Point - where - I: IntoIterator, - I::Item: Borrow, - J: IntoIterator, - J::Item: Borrow; -} - -/// A trait for variable-time multiscalar multiplication without precomputation. -pub trait VartimeMultiscalarMul { - /// The type of point being multiplied, e.g., `RistrettoPoint`. - type Point; - - /// Given an iterator of public scalars and an iterator of - /// `Option`s of points, compute either `Some(Q)`, where - /// $$ - /// Q = c\_1 P\_1 + \cdots + c\_n P\_n, - /// $$ - /// if all points were `Some(P_i)`, or else return `None`. - /// - /// This function is particularly useful when verifying statements - /// involving compressed points. Accepting `Option` allows - /// inlining point decompression into the multiscalar call, - /// avoiding the need for temporary buffers. - /// ``` - /// use curve25519_dalek::constants; - /// use curve25519_dalek::traits::VartimeMultiscalarMul; - /// use curve25519_dalek::ristretto::RistrettoPoint; - /// use curve25519_dalek::scalar::Scalar; - /// - /// // Some scalars - /// let a = Scalar::from(87329482u64); - /// let b = Scalar::from(37264829u64); - /// let c = Scalar::from(98098098u64); - /// let abc = [a,b,c]; - /// - /// // Some points - /// let P = constants::RISTRETTO_BASEPOINT_POINT; - /// let Q = P + P; - /// let R = P + Q; - /// let PQR = [P, Q, R]; - /// - /// let compressed = [P.compress(), Q.compress(), R.compress()]; - /// - /// // Now we can compute A1 = a*P + b*Q + c*R using P, Q, R: - /// let A1 = RistrettoPoint::vartime_multiscalar_mul(&abc, &PQR); - /// - /// // Or using the compressed points: - /// let A2 = RistrettoPoint::optional_multiscalar_mul( - /// &abc, - /// compressed.iter().map(|pt| pt.decompress()), - /// ); - /// - /// assert_eq!(A2, Some(A1)); - /// - /// // It's also possible to mix compressed and uncompressed points: - /// let A3 = RistrettoPoint::optional_multiscalar_mul( - /// abc.iter() - /// .chain(abc.iter()), - /// compressed.iter().map(|pt| pt.decompress()) - /// .chain(PQR.iter().map(|&pt| Some(pt))), - /// ); - /// - /// assert_eq!(A3, Some(A1+A1)); - /// ``` - fn optional_multiscalar_mul(scalars: I, points: J) -> Option - where - I: IntoIterator, - I::Item: Borrow, - J: IntoIterator>; - - /// Given an iterator of public scalars and an iterator of - /// public points, compute - /// $$ - /// Q = c\_1 P\_1 + \cdots + c\_n P\_n, - /// $$ - /// using variable-time operations. - /// - /// It is an error to call this function with two iterators of different lengths. - /// - /// # Examples - /// - /// The trait bound aims for maximum flexibility: the inputs must be - /// convertable to iterators (`I: IntoIter`), and the iterator's items - /// must be `Borrow` (or `Borrow`), to allow - /// iterators returning either `Scalar`s or `&Scalar`s. - /// - /// ``` - /// use curve25519_dalek::constants; - /// use curve25519_dalek::traits::VartimeMultiscalarMul; - /// use curve25519_dalek::ristretto::RistrettoPoint; - /// use curve25519_dalek::scalar::Scalar; - /// - /// // Some scalars - /// let a = Scalar::from(87329482u64); - /// let b = Scalar::from(37264829u64); - /// let c = Scalar::from(98098098u64); - /// - /// // Some points - /// let P = constants::RISTRETTO_BASEPOINT_POINT; - /// let Q = P + P; - /// let R = P + Q; - /// - /// // A1 = a*P + b*Q + c*R - /// let abc = [a,b,c]; - /// let A1 = RistrettoPoint::vartime_multiscalar_mul(&abc, &[P,Q,R]); - /// // Note: (&abc).into_iter(): Iterator - /// - /// // A2 = (-a)*P + (-b)*Q + (-c)*R - /// let minus_abc = abc.iter().map(|x| -x); - /// let A2 = RistrettoPoint::vartime_multiscalar_mul(minus_abc, &[P,Q,R]); - /// // Note: minus_abc.into_iter(): Iterator - /// - /// assert_eq!(A1.compress(), (-A2).compress()); - /// ``` - fn vartime_multiscalar_mul(scalars: I, points: J) -> Self::Point - where - I: IntoIterator, - I::Item: Borrow, - J: IntoIterator, - J::Item: Borrow, - Self::Point: Clone, - { - Self::optional_multiscalar_mul( - scalars, - points.into_iter().map(|P| Some(P.borrow().clone())), - ) - .unwrap() - } -} - -/// A trait for variable-time multiscalar multiplication with precomputation. -/// -/// A general multiscalar multiplication with precomputation can be written as -/// $$ -/// Q = a_1 A_1 + \cdots + a_n A_n + b_1 B_1 + \cdots + b_m B_m, -/// $$ -/// where the \\(B_i\\) are *static* points, for which precomputation -/// is possible, and the \\(A_j\\) are *dynamic* points, for which -/// precomputation is not possible. -/// -/// This trait has three methods for performing this computation: -/// -/// * [`vartime_multiscalar_mul`], which handles the special case -/// where \\(n = 0\\) and there are no dynamic points; -/// -/// * [`vartime_mixed_multiscalar_mul`], which takes the dynamic -/// points as already-validated `Point`s and is infallible; -/// -/// * [`optional_mixed_multiscalar_mul`], which takes the dynamic -/// points as `Option`s and returns an `Option`, -/// allowing decompression to be composed into the input iterators. -/// -/// All methods require that the lengths of the input iterators be -/// known and matching, as if they were `ExactSizeIterator`s. (It -/// does not require `ExactSizeIterator` only because that trait is -/// broken). -pub trait VartimePrecomputedMultiscalarMul: Sized { - /// The type of point to be multiplied, e.g., `RistrettoPoint`. - type Point: Clone; - - /// Given the static points \\( B_i \\), perform precomputation - /// and return the precomputation data. - fn new(static_points: I) -> Self - where - I: IntoIterator, - I::Item: Borrow; - - /// Given `static_scalars`, an iterator of public scalars - /// \\(b_i\\), compute - /// $$ - /// Q = b_1 B_1 + \cdots + b_m B_m, - /// $$ - /// where the \\(B_j\\) are the points that were supplied to `new`. - /// - /// It is an error to call this function with iterators of - /// inconsistent lengths. - /// - /// The trait bound aims for maximum flexibility: the input must - /// be convertable to iterators (`I: IntoIter`), and the - /// iterator's items must be `Borrow`, to allow iterators - /// returning either `Scalar`s or `&Scalar`s. - fn vartime_multiscalar_mul(&self, static_scalars: I) -> Self::Point - where - I: IntoIterator, - I::Item: Borrow, - { - use core::iter; - - Self::vartime_mixed_multiscalar_mul( - self, - static_scalars, - iter::empty::(), - iter::empty::(), - ) - } - - /// Given `static_scalars`, an iterator of public scalars - /// \\(b_i\\), `dynamic_scalars`, an iterator of public scalars - /// \\(a_i\\), and `dynamic_points`, an iterator of points - /// \\(A_i\\), compute - /// $$ - /// Q = a_1 A_1 + \cdots + a_n A_n + b_1 B_1 + \cdots + b_m B_m, - /// $$ - /// where the \\(B_j\\) are the points that were supplied to `new`. - /// - /// It is an error to call this function with iterators of - /// inconsistent lengths. - /// - /// The trait bound aims for maximum flexibility: the inputs must be - /// convertable to iterators (`I: IntoIter`), and the iterator's items - /// must be `Borrow` (or `Borrow`), to allow - /// iterators returning either `Scalar`s or `&Scalar`s. - fn vartime_mixed_multiscalar_mul( - &self, - static_scalars: I, - dynamic_scalars: J, - dynamic_points: K, - ) -> Self::Point - where - I: IntoIterator, - I::Item: Borrow, - J: IntoIterator, - J::Item: Borrow, - K: IntoIterator, - K::Item: Borrow, - { - Self::optional_mixed_multiscalar_mul( - self, - static_scalars, - dynamic_scalars, - dynamic_points.into_iter().map(|P| Some(P.borrow().clone())), - ) - .unwrap() - } - - /// Given `static_scalars`, an iterator of public scalars - /// \\(b_i\\), `dynamic_scalars`, an iterator of public scalars - /// \\(a_i\\), and `dynamic_points`, an iterator of points - /// \\(A_i\\), compute - /// $$ - /// Q = a_1 A_1 + \cdots + a_n A_n + b_1 B_1 + \cdots + b_m B_m, - /// $$ - /// where the \\(B_j\\) are the points that were supplied to `new`. - /// - /// If any of the dynamic points were `None`, return `None`. - /// - /// It is an error to call this function with iterators of - /// inconsistent lengths. - /// - /// This function is particularly useful when verifying statements - /// involving compressed points. Accepting `Option` allows - /// inlining point decompression into the multiscalar call, - /// avoiding the need for temporary buffers. - fn optional_mixed_multiscalar_mul( - &self, - static_scalars: I, - dynamic_scalars: J, - dynamic_points: K, - ) -> Option - where - I: IntoIterator, - I::Item: Borrow, - J: IntoIterator, - J::Item: Borrow, - K: IntoIterator>; -} - -// ------------------------------------------------------------------------ -// Private Traits -// ------------------------------------------------------------------------ - -/// Trait for checking whether a point is on the curve. -/// -/// This trait is only for debugging/testing, since it should be -/// impossible for a `curve25519-dalek` user to construct an invalid -/// point. -pub(crate) trait ValidityCheck { - /// Checks whether the point is on the curve. Not CT. - fn is_valid(&self) -> bool; -} diff --git a/net/gurk-rs/files/vendor/curve25519-dalek/src/window.rs b/net/gurk-rs/files/vendor/curve25519-dalek/src/window.rs deleted file mode 100644 index 2cf1fbe..0000000 --- a/net/gurk-rs/files/vendor/curve25519-dalek/src/window.rs +++ /dev/null @@ -1,228 +0,0 @@ -// -*- mode: rust; -*- -// -// This file is part of curve25519-dalek. -// Copyright (c) 2016-2021 isis lovecruft -// Copyright (c) 2016-2019 Henry de Valence -// See LICENSE for licensing information. -// -// Authors: -// - isis agora lovecruft -// - Henry de Valence - -//! Code for fixed- and sliding-window functionality - -#![allow(non_snake_case)] - -use core::fmt::Debug; - -use subtle::ConditionallyNegatable; -use subtle::ConditionallySelectable; -use subtle::ConstantTimeEq; -use subtle::Choice; - -use traits::Identity; - -use edwards::EdwardsPoint; -use backend::serial::curve_models::ProjectiveNielsPoint; -use backend::serial::curve_models::AffineNielsPoint; - -use zeroize::Zeroize; - -macro_rules! impl_lookup_table { - (Name = $name:ident, Size = $size:expr, SizeNeg = $neg:expr, SizeRange = $range:expr, ConversionRange = $conv_range:expr) => { - -/// A lookup table of precomputed multiples of a point \\(P\\), used to -/// compute \\( xP \\) for \\( -8 \leq x \leq 8 \\). -/// -/// The computation of \\( xP \\) is done in constant time by the `select` function. -/// -/// Since `LookupTable` does not implement `Index`, it's more difficult -/// to accidentally use the table directly. Unfortunately the table is -/// only `pub(crate)` so that we can write hardcoded constants, so it's -/// still technically possible. It would be nice to prevent direct -/// access to the table. -#[derive(Copy, Clone)] -pub struct $name(pub(crate) [T; $size]); - -impl $name -where - T: Identity + ConditionallySelectable + ConditionallyNegatable, -{ - /// Given \\(-8 \leq x \leq 8\\), return \\(xP\\) in constant time. - pub fn select(&self, x: i8) -> T { - debug_assert!(x >= $neg); - debug_assert!(x as i16 <= $size as i16); // XXX We have to convert to i16s here for the radix-256 case.. this is wrong. - - // Compute xabs = |x| - let xmask = x as i16 >> 7; - let xabs = (x as i16 + xmask) ^ xmask; - - // Set t = 0 * P = identity - let mut t = T::identity(); - for j in $range { - // Copy `points[j-1] == j*P` onto `t` in constant time if `|x| == j`. - let c = (xabs as u16).ct_eq(&(j as u16)); - t.conditional_assign(&self.0[j - 1], c); - } - // Now t == |x| * P. - - let neg_mask = Choice::from((xmask & 1) as u8); - t.conditional_negate(neg_mask); - // Now t == x * P. - - t - } -} - -impl Default for $name { - fn default() -> $name { - $name([T::default(); $size]) - } -} - -impl Debug for $name { - fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { - write!(f, "{:?}(", stringify!($name))?; - - for x in self.0.iter() { - write!(f, "{:?}", x)?; - } - - write!(f, ")") - } -} - -impl<'a> From<&'a EdwardsPoint> for $name { - fn from(P: &'a EdwardsPoint) -> Self { - let mut points = [P.to_projective_niels(); $size]; - for j in $conv_range { - points[j + 1] = (P + &points[j]).to_extended().to_projective_niels(); - } - $name(points) - } -} - -impl<'a> From<&'a EdwardsPoint> for $name { - fn from(P: &'a EdwardsPoint) -> Self { - let mut points = [P.to_affine_niels(); $size]; - // XXX batch inversion would be good if perf mattered here - for j in $conv_range { - points[j + 1] = (P + &points[j]).to_extended().to_affine_niels() - } - $name(points) - } -} - -impl Zeroize for $name -where - T: Copy + Default + Zeroize -{ - fn zeroize(&mut self) { - for x in self.0.iter_mut() { - x.zeroize(); - } - } -} - -}} // End macro_rules! impl_lookup_table - -// The first one has to be named "LookupTable" because it's used as a constructor for consts. -impl_lookup_table! {Name = LookupTable, Size = 8, SizeNeg = -8, SizeRange = 1 .. 9, ConversionRange = 0 .. 7} // radix-16 -impl_lookup_table! {Name = LookupTableRadix32, Size = 16, SizeNeg = -16, SizeRange = 1 .. 17, ConversionRange = 0 .. 15} // radix-32 -impl_lookup_table! {Name = LookupTableRadix64, Size = 32, SizeNeg = -32, SizeRange = 1 .. 33, ConversionRange = 0 .. 31} // radix-64 -impl_lookup_table! {Name = LookupTableRadix128, Size = 64, SizeNeg = -64, SizeRange = 1 .. 65, ConversionRange = 0 .. 63} // radix-128 -impl_lookup_table! {Name = LookupTableRadix256, Size = 128, SizeNeg = -128, SizeRange = 1 .. 129, ConversionRange = 0 .. 127} // radix-256 - -// For homogeneity we then alias it to "LookupTableRadix16". -pub type LookupTableRadix16 = LookupTable; - -/// Holds odd multiples 1A, 3A, ..., 15A of a point A. -#[derive(Copy, Clone)] -pub(crate) struct NafLookupTable5(pub(crate) [T; 8]); - -impl NafLookupTable5 { - /// Given public, odd \\( x \\) with \\( 0 < x < 2^4 \\), return \\(xA\\). - pub fn select(&self, x: usize) -> T { - debug_assert_eq!(x & 1, 1); - debug_assert!(x < 16); - - self.0[x / 2] - } -} - -impl Debug for NafLookupTable5 { - fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { - write!(f, "NafLookupTable5({:?})", self.0) - } -} - -impl<'a> From<&'a EdwardsPoint> for NafLookupTable5 { - fn from(A: &'a EdwardsPoint) -> Self { - let mut Ai = [A.to_projective_niels(); 8]; - let A2 = A.double(); - for i in 0..7 { - Ai[i + 1] = (&A2 + &Ai[i]).to_extended().to_projective_niels(); - } - // Now Ai = [A, 3A, 5A, 7A, 9A, 11A, 13A, 15A] - NafLookupTable5(Ai) - } -} - -impl<'a> From<&'a EdwardsPoint> for NafLookupTable5 { - fn from(A: &'a EdwardsPoint) -> Self { - let mut Ai = [A.to_affine_niels(); 8]; - let A2 = A.double(); - for i in 0..7 { - Ai[i + 1] = (&A2 + &Ai[i]).to_extended().to_affine_niels(); - } - // Now Ai = [A, 3A, 5A, 7A, 9A, 11A, 13A, 15A] - NafLookupTable5(Ai) - } -} - -/// Holds stuff up to 8. -#[derive(Copy, Clone)] -pub(crate) struct NafLookupTable8(pub(crate) [T; 64]); - -impl NafLookupTable8 { - pub fn select(&self, x: usize) -> T { - debug_assert_eq!(x & 1, 1); - debug_assert!(x < 128); - - self.0[x / 2] - } -} - -impl Debug for NafLookupTable8 { - fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { - write!(f, "NafLookupTable8([\n")?; - for i in 0..64 { - write!(f, "\t{:?},\n", &self.0[i])?; - } - write!(f, "])") - } -} - -impl<'a> From<&'a EdwardsPoint> for NafLookupTable8 { - fn from(A: &'a EdwardsPoint) -> Self { - let mut Ai = [A.to_projective_niels(); 64]; - let A2 = A.double(); - for i in 0..63 { - Ai[i + 1] = (&A2 + &Ai[i]).to_extended().to_projective_niels(); - } - // Now Ai = [A, 3A, 5A, 7A, 9A, 11A, 13A, 15A, ..., 127A] - NafLookupTable8(Ai) - } -} - -impl<'a> From<&'a EdwardsPoint> for NafLookupTable8 { - fn from(A: &'a EdwardsPoint) -> Self { - let mut Ai = [A.to_affine_niels(); 64]; - let A2 = A.double(); - for i in 0..63 { - Ai[i + 1] = (&A2 + &Ai[i]).to_extended().to_affine_niels(); - } - // Now Ai = [A, 3A, 5A, 7A, 9A, 11A, 13A, 15A, ..., 127A] - NafLookupTable8(Ai) - } -} diff --git a/net/gurk-rs/files/vendor/curve25519-dalek/vendor/ristretto.sage b/net/gurk-rs/files/vendor/curve25519-dalek/vendor/ristretto.sage deleted file mode 100644 index 04cf4f9..0000000 --- a/net/gurk-rs/files/vendor/curve25519-dalek/vendor/ristretto.sage +++ /dev/null @@ -1,857 +0,0 @@ -import binascii -class InvalidEncodingException(Exception): pass -class NotOnCurveException(Exception): pass -class SpecException(Exception): pass - -def lobit(x): return int(x) & 1 -def hibit(x): return lobit(2*x) -def negative(x): return lobit(x) -def enc_le(x,n): return bytearray([int(x)>>(8*i) & 0xFF for i in xrange(n)]) -def dec_le(x): return sum(b<<(8*i) for i,b in enumerate(x)) -def randombytes(n): return bytearray([randint(0,255) for _ in range(n)]) - -def optimized_version_of(spec): - """Decorator: This function is an optimized version of some specification""" - def decorator(f): - def wrapper(self,*args,**kwargs): - def pr(x): - if isinstance(x,bytearray): return binascii.hexlify(x) - else: return str(x) - try: spec_ans = getattr(self,spec,spec)(*args,**kwargs),None - except Exception as e: spec_ans = None,e - try: opt_ans = f(self,*args,**kwargs),None - except Exception as e: opt_ans = None,e - if spec_ans[1] is None and opt_ans[1] is not None: - raise - #raise SpecException("Mismatch in %s: spec returned %s but opt threw %s" - # % (f.__name__,str(spec_ans[0]),str(opt_ans[1]))) - if spec_ans[1] is not None and opt_ans[1] is None: - raise - #raise SpecException("Mismatch in %s: spec threw %s but opt returned %s" - # % (f.__name__,str(spec_ans[1]),str(opt_ans[0]))) - if spec_ans[0] != opt_ans[0]: - raise SpecException("Mismatch in %s: %s != %s" - % (f.__name__,pr(spec_ans[0]),pr(opt_ans[0]))) - if opt_ans[1] is not None: raise - else: return opt_ans[0] - wrapper.__name__ = f.__name__ - return wrapper - return decorator - -def xsqrt(x,exn=InvalidEncodingException("Not on curve")): - """Return sqrt(x)""" - if not is_square(x): raise exn - s = sqrt(x) - if negative(s): s=-s - return s - -def isqrt(x,exn=InvalidEncodingException("Not on curve")): - """Return 1/sqrt(x)""" - if x==0: return 0 - if not is_square(x): raise exn - s = sqrt(x) - #if negative(s): s=-s - return 1/s - -def inv0(x): return 1/x if x != 0 else 0 - -def isqrt_i(x): - """Return 1/sqrt(x) or 1/sqrt(zeta * x)""" - if x==0: return True,0 - gen = x.parent(-1) - while is_square(gen): gen = sqrt(gen) - if is_square(x): return True,1/sqrt(x) - else: return False,1/sqrt(x*gen) - -class QuotientEdwardsPoint(object): - """Abstract class for point an a quotiented Edwards curve; needs F,a,d,cofactor to work""" - def __init__(self,x=0,y=1): - x = self.x = self.F(x) - y = self.y = self.F(y) - if y^2 + self.a*x^2 != 1 + self.d*x^2*y^2: - raise NotOnCurveException(str(self)) - - def __repr__(self): - return "%s(0x%x,0x%x)" % (self.__class__.__name__, self.x, self.y) - - def __iter__(self): - yield self.x - yield self.y - - def __add__(self,other): - x,y = self - X,Y = other - a,d = self.a,self.d - return self.__class__( - (x*Y+y*X)/(1+d*x*y*X*Y), - (y*Y-a*x*X)/(1-d*x*y*X*Y) - ) - - def __neg__(self): return self.__class__(-self.x,self.y) - def __sub__(self,other): return self + (-other) - def __rmul__(self,other): return self*other - def __eq__(self,other): - """NB: this is the only method that is different from the usual one""" - x,y = self - X,Y = other - return x*Y == X*y or (self.cofactor==8 and -self.a*x*X == y*Y) - def __ne__(self,other): return not (self==other) - - def __mul__(self,exp): - exp = int(exp) - if exp < 0: exp,self = -exp,-self - total = self.__class__() - work = self - while exp != 0: - if exp & 1: total += work - work += work - exp >>= 1 - return total - - def xyzt(self): - x,y = self - z = self.F.random_element() - return x*z,y*z,z,x*y*z - - def torque(self): - """Apply cofactor group, except keeping the point even""" - if self.cofactor == 8: - if self.a == -1: return self.__class__(self.y*self.i, self.x*self.i) - if self.a == 1: return self.__class__(-self.y, self.x) - else: - return self.__class__(-self.x, -self.y) - - def doubleAndEncodeSpec(self): - return (self+self).encode() - - # Utility functions - @classmethod - def bytesToGf(cls,bytes,mustBeProper=True,mustBePositive=False,maskHiBits=False): - """Convert little-endian bytes to field element, sanity check length""" - if len(bytes) != cls.encLen: - raise InvalidEncodingException("wrong length %d" % len(bytes)) - s = dec_le(bytes) - if mustBeProper and s >= cls.F.order(): - raise InvalidEncodingException("%d out of range!" % s) - bitlen = int(ceil(log(cls.F.order())/log(2))) - if maskHiBits: s &= 2^bitlen-1 - s = cls.F(s) - if mustBePositive and negative(s): - raise InvalidEncodingException("%d is negative!" % s) - return s - - @classmethod - def gfToBytes(cls,x,mustBePositive=False): - """Convert little-endian bytes to field element, sanity check length""" - if negative(x) and mustBePositive: x = -x - return enc_le(x,cls.encLen) - -class RistrettoPoint(QuotientEdwardsPoint): - """The new Ristretto group""" - def encodeSpec(self): - """Unoptimized specification for encoding""" - x,y = self - if self.cofactor==8 and (negative(x*y) or y==0): (x,y) = self.torque() - if y == -1: y = 1 # Avoid divide by 0; doesn't affect impl - - if negative(x): x,y = -x,-y - s = xsqrt(self.mneg*(1-y)/(1+y),exn=Exception("Unimplemented: point is odd: " + str(self))) - return self.gfToBytes(s) - - @classmethod - def decodeSpec(cls,s): - """Unoptimized specification for decoding""" - s = cls.bytesToGf(s,mustBePositive=True) - - a,d = cls.a,cls.d - x = xsqrt(4*s^2 / (a*d*(1+a*s^2)^2 - (1-a*s^2)^2)) - y = (1+a*s^2) / (1-a*s^2) - - if cls.cofactor==8 and (negative(x*y) or y==0): - raise InvalidEncodingException("x*y has high bit") - - return cls(x,y) - - @optimized_version_of("encodeSpec") - def encode(self): - """Encode, optimized version""" - a,d,mneg = self.a,self.d,self.mneg - x,y,z,t = self.xyzt() - - if self.cofactor==8: - u1 = mneg*(z+y)*(z-y) - u2 = x*y # = t*z - isr = isqrt(u1*u2^2) - i1 = isr*u1 # sqrt(mneg*(z+y)*(z-y))/(x*y) - i2 = isr*u2 # 1/sqrt(a*(y+z)*(y-z)) - z_inv = i1*i2*t # 1/z - - if negative(t*z_inv): - if a==-1: - x,y = y*self.i,x*self.i - den_inv = self.magic * i1 - else: - x,y = -y,x - den_inv = self.i * self.magic * i1 - - else: - den_inv = i2 - - if negative(x*z_inv): y = -y - s = (z-y) * den_inv - else: - num = mneg*(z+y)*(z-y) - isr = isqrt(num*y^2) - if negative(isr^2*num*y*t): y = -y - s = isr*y*(z-y) - - return self.gfToBytes(s,mustBePositive=True) - - @optimized_version_of("doubleAndEncodeSpec") - def doubleAndEncode(self): - X,Y,Z,T = self.xyzt() - a,d,mneg = self.a,self.d,self.mneg - - if self.cofactor==8: - e = 2*X*Y - f = Z^2+d*T^2 - g = Y^2-a*X^2 - h = Z^2-d*T^2 - - inv1 = 1/(e*f*g*h) - z_inv = inv1*e*g # 1 / (f*h) - t_inv = inv1*f*h - - if negative(e*g*z_inv): - if a==-1: sqrta = self.i - else: sqrta = -1 - e,f,g,h = g,h,-e,f*sqrta - factor = self.i - else: - factor = self.magic - - if negative(h*e*z_inv): g=-g - s = (h-g)*factor*g*t_inv - - else: - foo = Y^2+a*X^2 - bar = X*Y - den = 1/(foo*bar) - if negative(2*bar^2*den): tmp = a*X^2 - else: tmp = Y^2 - s = self.magic*(Z^2-tmp)*foo*den - - return self.gfToBytes(s,mustBePositive=True) - - @classmethod - @optimized_version_of("decodeSpec") - def decode(cls,s): - """Decode, optimized version""" - s = cls.bytesToGf(s,mustBePositive=True) - - a,d = cls.a,cls.d - yden = 1-a*s^2 - ynum = 1+a*s^2 - yden_sqr = yden^2 - xden_sqr = a*d*ynum^2 - yden_sqr - - isr = isqrt(xden_sqr * yden_sqr) - - xden_inv = isr * yden - yden_inv = xden_inv * isr * xden_sqr - - x = 2*s*xden_inv - if negative(x): x = -x - y = ynum * yden_inv - - if cls.cofactor==8 and (negative(x*y) or y==0): - raise InvalidEncodingException("x*y is invalid: %d, %d" % (x,y)) - - return cls(x,y) - - @classmethod - def fromJacobiQuartic(cls,s,t,sgn=1): - """Convert point from its Jacobi Quartic representation""" - a,d = cls.a,cls.d - assert s^4 - 2*cls.a*(1-2*d/(d-a))*s^2 + 1 == t^2 - x = 2*s*cls.magic / t - y = (1+a*s^2) / (1-a*s^2) - return cls(sgn*x,y) - - @classmethod - def elligatorSpec(cls,r0): - a,d = cls.a,cls.d - r = cls.qnr * cls.bytesToGf(r0,mustBeProper=False,maskHiBits=True)^2 - den = (d*r-a)*(a*r-d) - if den == 0: return cls() - n1 = cls.a*(r+1)*(a+d)*(d-a)/den - n2 = r*n1 - if is_square(n1): - sgn,s,t = 1, xsqrt(n1), -(r-1)*(a+d)^2 / den - 1 - else: - sgn,s,t = -1,-xsqrt(n2), r*(r-1)*(a+d)^2 / den - 1 - - return cls.fromJacobiQuartic(s,t) - - @classmethod - @optimized_version_of("elligatorSpec") - def elligator(cls,r0): - a,d = cls.a,cls.d - r0 = cls.bytesToGf(r0,mustBeProper=False,maskHiBits=True) - r = cls.qnr * r0^2 - den = (d*r-a)*(a*r-d) - num = cls.a*(r+1)*(a+d)*(d-a) - - iss,isri = isqrt_i(num*den) - if iss: sgn,twiddle = 1,1 - else: sgn,twiddle = -1,r0*cls.qnr - isri *= twiddle - s = isri*num - t = -sgn*isri*s*(r-1)*(d+a)^2 - 1 - if negative(s) == iss: s = -s - return cls.fromJacobiQuartic(s,t) - - -class Decaf_1_1_Point(QuotientEdwardsPoint): - """Like current decaf but tweaked for simplicity""" - def encodeSpec(self): - """Unoptimized specification for encoding""" - a,d = self.a,self.d - x,y = self - if x==0 or y==0: return(self.gfToBytes(0)) - - if self.cofactor==8 and negative(x*y*self.isoMagic): - x,y = self.torque() - - sr = xsqrt(1-a*x^2) - altx = x*y*self.isoMagic / sr - if negative(altx): s = (1+sr)/x - else: s = (1-sr)/x - - return self.gfToBytes(s,mustBePositive=True) - - @classmethod - def decodeSpec(cls,s): - """Unoptimized specification for decoding""" - a,d = cls.a,cls.d - s = cls.bytesToGf(s,mustBePositive=True) - - if s==0: return cls() - t = xsqrt(s^4 + 2*(a-2*d)*s^2 + 1) - altx = 2*s*cls.isoMagic/t - if negative(altx): t = -t - x = 2*s / (1+a*s^2) - y = (1-a*s^2) / t - - if cls.cofactor==8 and (negative(x*y*cls.isoMagic) or y==0): - raise InvalidEncodingException("x*y is invalid: %d, %d" % (x,y)) - - return cls(x,y) - - def toJacobiQuartic(self,toggle_rotation=False,toggle_altx=False,toggle_s=False): - "Return s,t on jacobi curve" - a,d = self.a,self.d - x,y,z,t = self.xyzt() - - if self.cofactor == 8: - # Cofactor 8 version - # Simulate IMAGINE_TWIST because that's how libdecaf does it - x = self.i*x - t = self.i*t - a = -a - d = -d - - # OK, the actual libdecaf code should be here - num = (z+y)*(z-y) - den = x*y - isr = isqrt(num*(a-d)*den^2) - - iden = isr * den * self.isoMagic # 1/sqrt((z+y)(z-y)) = 1/sqrt(1-Y^2) / z - inum = isr * num # sqrt(1-Y^2) * z / xysqrt(a-d) ~ 1/sqrt(1-ax^2)/z - - if negative(iden*inum*self.i*t^2*(d-a)) != toggle_rotation: - iden,inum = inum,iden - fac = x*sqrt(a) - toggle=(a==-1) - else: - fac = y - toggle=False - - imi = self.isoMagic * self.i - altx = inum*t*imi - neg_altx = negative(altx) != toggle_altx - if neg_altx != toggle: inum =- inum - - tmp = fac*(inum*z + 1) - s = iden*tmp*imi - - negm1 = (negative(s) != toggle_s) != neg_altx - if negm1: m1 = a*fac + z - else: m1 = a*fac - z - - swap = toggle_s - - else: - # Much simpler cofactor 4 version - num = (x+t)*(x-t) - isr = isqrt(num*(a-d)*x^2) - ratio = isr*num - altx = ratio*self.isoMagic - - neg_altx = negative(altx) != toggle_altx - if neg_altx: ratio =- ratio - - tmp = ratio*z - t - s = (a-d)*isr*x*tmp - - negx = (negative(s) != toggle_s) != neg_altx - if negx: m1 = -a*t + x - else: m1 = -a*t - x - - swap = toggle_s - - if negative(s): s = -s - - return s,m1,a*tmp,swap - - def invertElligator(self,toggle_r=False,*args,**kwargs): - "Produce preimage of self under elligator, or None" - a,d = self.a,self.d - - rets = [] - - tr = [False,True] if self.cofactor == 8 else [False] - for toggle_rotation in tr: - for toggle_altx in [False,True]: - for toggle_s in [False,True]: - for toggle_r in [False,True]: - s,m1,m12,swap = self.toJacobiQuartic(toggle_rotation,toggle_altx,toggle_s) - - #print - #print toggle_rotation,toggle_altx,toggle_s - #print m1 - #print m12 - - - if self == self.__class__(): - if self.cofactor == 4: - # Hacks for identity! - if toggle_altx: m12 = 1 - elif toggle_s: m1 = 1 - elif toggle_r: continue - ## BOTH??? - - else: - m12 = 1 - imi = self.isoMagic * self.i - if toggle_rotation: - if toggle_altx: m1 = -imi - else: m1 = +imi - else: - if toggle_altx: m1 = 0 - else: m1 = a-d - - rnum = (d*a*m12-m1) - rden = ((d*a-1)*m12+m1) - if swap: rnum,rden = rden,rnum - - ok,sr = isqrt_i(rnum*rden*self.qnr) - if not ok: continue - sr *= rnum - #print "Works! %d %x" % (swap,sr) - - if negative(sr) != toggle_r: sr = -sr - ret = self.gfToBytes(sr) - if self.elligator(ret) != self and self.elligator(ret) != -self: - print "WRONG!",[toggle_rotation,toggle_altx,toggle_s] - if self.elligator(ret) == -self and self != -self: print "Negated!",[toggle_rotation,toggle_altx,toggle_s] - rets.append(bytes(ret)) - return rets - - @optimized_version_of("encodeSpec") - def encode(self): - """Encode, optimized version""" - return self.gfToBytes(self.toJacobiQuartic()[0]) - - @classmethod - @optimized_version_of("decodeSpec") - def decode(cls,s): - """Decode, optimized version""" - a,d = cls.a,cls.d - s = cls.bytesToGf(s,mustBePositive=True) - - #if s==0: return cls() - s2 = s^2 - den = 1+a*s2 - num = den^2 - 4*d*s2 - isr = isqrt(num*den^2) - altx = 2*s*isr*den*cls.isoMagic - if negative(altx): isr = -isr - x = 2*s *isr^2*den*num - y = (1-a*s^2) * isr*den - - if cls.cofactor==8 and (negative(x*y*cls.isoMagic) or y==0): - raise InvalidEncodingException("x*y is invalid: %d, %d" % (x,y)) - - return cls(x,y) - - @classmethod - def fromJacobiQuartic(cls,s,t,sgn=1): - """Convert point from its Jacobi Quartic representation""" - a,d = cls.a,cls.d - if s==0: return cls() - x = 2*s / (1+a*s^2) - y = (1-a*s^2) / t - return cls(x,sgn*y) - - @optimized_version_of("doubleAndEncodeSpec") - def doubleAndEncode(self): - X,Y,Z,T = self.xyzt() - a,d = self.a,self.d - - if self.cofactor == 8: - # Cofactor 8 version - # Simulate IMAGINE_TWIST because that's how libdecaf does it - X = self.i*X - T = self.i*T - a = -a - d = -d - # TODO: This is only being called for a=-1, so could - # be wrong for a=1 - - e = 2*X*Y - f = Y^2+a*X^2 - g = Y^2-a*X^2 - h = Z^2-d*T^2 - - eim = e*self.isoMagic - inv = 1/(eim*g*f*h) - fh_inv = eim*g*inv*self.i - - if negative(eim*g*fh_inv): - idf = g*self.isoMagic*self.i - bar = f - foo = g - test = eim*f - else: - idf = eim - bar = h - foo = -eim - test = g*h - - if negative(test*fh_inv): bar =- bar - s = idf*(foo+bar)*inv*f*h - - else: - xy = X*Y - h = Z^2-d*T^2 - inv = 1/(xy*h) - if negative(inv*2*xy^2*self.isoMagic): tmp = Y - else: tmp = X - s = tmp^2*h*inv # = X/Y or Y/X, interestingly - - return self.gfToBytes(s,mustBePositive=True) - - @classmethod - def elligatorSpec(cls,r0,fromR=False): - a,d = cls.a,cls.d - if fromR: r = r0 - else: r = cls.qnr * cls.bytesToGf(r0,mustBeProper=False,maskHiBits=True)^2 - - den = (d*r-(d-a))*((d-a)*r-d) - if den == 0: return cls() - n1 = (r+1)*(a-2*d)/den - n2 = r*n1 - if is_square(n1): - sgn,s,t = 1, xsqrt(n1), -(r-1)*(a-2*d)^2 / den - 1 - else: - sgn,s,t = -1, -xsqrt(n2), r*(r-1)*(a-2*d)^2 / den - 1 - - return cls.fromJacobiQuartic(s,t) - - @classmethod - @optimized_version_of("elligatorSpec") - def elligator(cls,r0): - a,d = cls.a,cls.d - r0 = cls.bytesToGf(r0,mustBeProper=False,maskHiBits=True) - r = cls.qnr * r0^2 - den = (d*r-(d-a))*((d-a)*r-d) - num = (r+1)*(a-2*d) - - iss,isri = isqrt_i(num*den) - if iss: sgn,twiddle = 1,1 - else: sgn,twiddle = -1,r0*cls.qnr - isri *= twiddle - s = isri*num - t = -sgn*isri*s*(r-1)*(a-2*d)^2 - 1 - if negative(s) == iss: s = -s - return cls.fromJacobiQuartic(s,t) - - def elligatorInverseBruteForce(self): - """Invert Elligator using SAGE's polynomial solver""" - a,d = self.a,self.d - R. = self.F[] - r = self.qnr * r0^2 - den = (d*r-(d-a))*((d-a)*r-d) - n1 = (r+1)*(a-2*d)/den - n2 = r*n1 - ret = set() - for s2,t in [(n1, -(r-1)*(a-2*d)^2 / den - 1), - (n2,r*(r-1)*(a-2*d)^2 / den - 1)]: - x2 = 4*s2/(1+a*s2)^2 - y = (1-a*s2) / t - - selfT = self - for i in xrange(self.cofactor/2): - xT,yT = selfT - polyX = xT^2-x2 - polyY = yT-y - sx = set(r for r,_ in polyX.numerator().roots()) - sy = set(r for r,_ in polyY.numerator().roots()) - ret = ret.union(sx.intersection(sy)) - - selfT = selfT.torque() - - ret = [self.gfToBytes(r) for r in ret] - - for r in ret: - assert self.elligator(r) in [self,-self] - - ret = [r for r in ret if self.elligator(r) == self] - - return ret - -class Ed25519Point(RistrettoPoint): - F = GF(2^255-19) - d = F(-121665/121666) - a = F(-1) - i = sqrt(F(-1)) - mneg = F(1) - qnr = i - magic = isqrt(a*d-1) - cofactor = 8 - encLen = 32 - - @classmethod - def base(cls): - return cls( 15112221349535400772501151409588531511454012693041857206046113283949847762202, 46316835694926478169428394003475163141307993866256225615783033603165251855960 - ) - -class NegEd25519Point(RistrettoPoint): - F = GF(2^255-19) - d = F(121665/121666) - a = F(1) - i = sqrt(F(-1)) - mneg = F(-1) # TODO checkme vs 1-ad or whatever - qnr = i - magic = isqrt(a*d-1) - cofactor = 8 - encLen = 32 - - @classmethod - def base(cls): - y = cls.F(4/5) - x = sqrt((y^2-1)/(cls.d*y^2-cls.a)) - if negative(x): x = -x - return cls(x,y) - -class IsoEd448Point(RistrettoPoint): - F = GF(2^448-2^224-1) - d = F(39082/39081) - a = F(1) - mneg = F(-1) - qnr = -1 - magic = isqrt(a*d-1) - cofactor = 4 - encLen = 56 - - @classmethod - def base(cls): - return cls( # RFC has it wrong - 345397493039729516374008604150537410266655260075183290216406970281645695073672344430481787759340633221708391583424041788924124567700732, - -363419362147803445274661903944002267176820680343659030140745099590306164083365386343198191849338272965044442230921818680526749009182718 - ) - -class TwistedEd448GoldilocksPoint(Decaf_1_1_Point): - F = GF(2^448-2^224-1) - d = F(-39082) - a = F(-1) - qnr = -1 - cofactor = 4 - encLen = 56 - isoMagic = IsoEd448Point.magic - - @classmethod - def base(cls): - return cls.decodeSpec(Ed448GoldilocksPoint.base().encodeSpec()) - -class Ed448GoldilocksPoint(Decaf_1_1_Point): - F = GF(2^448-2^224-1) - d = F(-39081) - a = F(1) - qnr = -1 - cofactor = 4 - encLen = 56 - isoMagic = IsoEd448Point.magic - - @classmethod - def base(cls): - return 2*cls( - 224580040295924300187604334099896036246789641632564134246125461686950415467406032909029192869357953282578032075146446173674602635247710, 298819210078481492676017930443930673437544040154080242095928241372331506189835876003536878655418784733982303233503462500531545062832660 - ) - -class IsoEd25519Point(Decaf_1_1_Point): - # TODO: twisted iso too! - # TODO: twisted iso might have to IMAGINE_TWIST or whatever - F = GF(2^255-19) - d = F(-121665) - a = F(1) - i = sqrt(F(-1)) - qnr = i - magic = isqrt(a*d-1) - cofactor = 8 - encLen = 32 - isoMagic = Ed25519Point.magic - isoA = Ed25519Point.a - - @classmethod - def base(cls): - return cls.decodeSpec(Ed25519Point.base().encode()) - -class TestFailedException(Exception): pass - -def test(cls,n): - print "Testing curve %s" % cls.__name__ - - specials = [1] - ii = cls.F(-1) - while is_square(ii): - specials.append(ii) - ii = sqrt(ii) - specials.append(ii) - for i in specials: - if negative(cls.F(i)): i = -i - i = enc_le(i,cls.encLen) - try: - Q = cls.decode(i) - QE = Q.encode() - if QE != i: - raise TestFailedException("Round trip special %s != %s" % - (binascii.hexlify(QE),binascii.hexlify(i))) - except NotOnCurveException: pass - except InvalidEncodingException: pass - - - P = cls.base() - Q = cls() - for i in xrange(n): - #print binascii.hexlify(Q.encode()) - QE = Q.encode() - QQ = cls.decode(QE) - if QQ != Q: raise TestFailedException("Round trip %s != %s" % (str(QQ),str(Q))) - - # Testing s -> 1/s: encodes -point on cofactor - s = cls.bytesToGf(QE) - if s != 0: - ss = cls.gfToBytes(1/s,mustBePositive=True) - try: - QN = cls.decode(ss) - if cls.cofactor == 8: - raise TestFailedException("1/s shouldnt work for cofactor 8") - if QN != -Q: - raise TestFailedException("s -> 1/s should negate point for cofactor 4") - except InvalidEncodingException as e: - # Should be raised iff cofactor==8 - if cls.cofactor == 4: - raise TestFailedException("s -> 1/s should work for cofactor 4") - - QT = Q - for h in xrange(cls.cofactor): - QT = QT.torque() - if QT.encode() != QE: - raise TestFailedException("Can't torque %s,%d" % (str(Q),h+1)) - - Q0 = Q + P - if Q0 == Q: raise TestFailedException("Addition doesn't work") - if Q0-P != Q: raise TestFailedException("Subtraction doesn't work") - - r = randint(1,1000) - Q1 = Q0*r - Q2 = Q0*(r+1) - if Q1 + Q0 != Q2: raise TestFailedException("Scalarmul doesn't work") - Q = Q1 - -def testElligator(cls,n): - print "Testing elligator on %s" % cls.__name__ - for i in xrange(n): - r = randombytes(cls.encLen) - P = cls.elligator(r) - if hasattr(P,"invertElligator"): - iv = P.invertElligator() - modr = bytes(cls.gfToBytes(cls.bytesToGf(r,mustBeProper=False,maskHiBits=True))) - iv2 = P.torque().invertElligator() - if modr not in iv: print "Failed to invert Elligator!" - if len(iv) != len(set(iv)): - print "Elligator inverses not unique!", len(set(iv)), len(iv) - if iv != iv2: - print "Elligator is untorqueable!" - #print [binascii.hexlify(j) for j in iv] - #print [binascii.hexlify(j) for j in iv2] - #break - else: - pass # TODO - -def gangtest(classes,n): - print "Gang test",[cls.__name__ for cls in classes] - specials = [1] - ii = classes[0].F(-1) - while is_square(ii): - specials.append(ii) - ii = sqrt(ii) - specials.append(ii) - - for i in xrange(n): - rets = [bytes((cls.base()*i).encode()) for cls in classes] - if len(set(rets)) != 1: - print "Divergence in encode at %d" % i - for c,ret in zip(classes,rets): - print c,binascii.hexlify(ret) - print - - if i < len(specials): r0 = enc_le(specials[i],classes[0].encLen) - else: r0 = randombytes(classes[0].encLen) - - rets = [bytes((cls.elligator(r0)*i).encode()) for cls in classes] - if len(set(rets)) != 1: - print "Divergence in elligator at %d" % i - for c,ret in zip(classes,rets): - print c,binascii.hexlify(ret) - print - -def testDoubleAndEncode(cls,n): - print "Testing doubleAndEncode on %s" % cls.__name__ - for i in xrange(n): - r1 = randombytes(cls.encLen) - r2 = randombytes(cls.encLen) - u = cls.elligator(r1) + cls.elligator(r2) - u.doubleAndEncode() - -testDoubleAndEncode(Ed25519Point,100) -testDoubleAndEncode(NegEd25519Point,100) -testDoubleAndEncode(IsoEd25519Point,100) -testDoubleAndEncode(IsoEd448Point,100) -testDoubleAndEncode(TwistedEd448GoldilocksPoint,100) -#test(Ed25519Point,100) -#test(NegEd25519Point,100) -#test(IsoEd25519Point,100) -#test(IsoEd448Point,100) -#test(TwistedEd448GoldilocksPoint,100) -#test(Ed448GoldilocksPoint,100) -#testElligator(Ed25519Point,100) -#testElligator(NegEd25519Point,100) -#testElligator(IsoEd25519Point,100) -#testElligator(IsoEd448Point,100) -#testElligator(Ed448GoldilocksPoint,100) -#testElligator(TwistedEd448GoldilocksPoint,100) -#gangtest([IsoEd448Point,TwistedEd448GoldilocksPoint,Ed448GoldilocksPoint],100) -#gangtest([Ed25519Point,IsoEd25519Point],100) diff --git a/net/gurk-rs/files/vendor/libsignal-protocol/.cargo-checksum.json b/net/gurk-rs/files/vendor/libsignal-protocol/.cargo-checksum.json deleted file mode 100644 index ab9a8ee..0000000 --- a/net/gurk-rs/files/vendor/libsignal-protocol/.cargo-checksum.json +++ /dev/null @@ -1 +0,0 @@ -{"files":{"Cargo.toml":"9978ce7662c8c17ce4a131ac3bbfa450fd339ba39579d47e992941a4b21c006f","benches/ratchet.rs":"5102fcc1e43bf1b7d90d6f890e010e6f4056b826eac8a90235442928b32b85ff","benches/sealed_sender.rs":"8e581630a315dcd6e087dbcb441ece518d22e491de8f6038ce3a85280efc7b5c","benches/session.rs":"fa03d4dad7983273dd755f3d8cbe70853b1504aeabbef4c9cde663f65e63cb8d","build.rs":"ce3c7b66ef94f0c91803a8ec80a76f94f4d6223f3f11738e1ee10ad87983baf3","src/address.rs":"4bc5d361fe73ceeee76659cd778bea9d2de38115fc1177485e3bdabc13a7bcf3","src/consts.rs":"8630aa9486f8e65648cdd254359a070b79d0e3ab363699c241958f2f615b0ff2","src/crypto.rs":"a76e41c4f7ef07f914131f3420b5bd0addd656c5a1bea8227597c0a1ef1ba0e6","src/curve.rs":"d5bd475be83bca69a29695b2c5ebf275fe81ba9b096ad9671f795d0d3dab28e2","src/curve/curve25519.rs":"3e48c615c89ef03a2ff97a40844b81a17b29c95781e127ccd98c6b45b4109662","src/error.rs":"7cca985e8c8f225b59aef7ee4d4de967db1b843771e0763d8982559de66f339b","src/fingerprint.rs":"4d5eb04283113997c03fca3adf61236b081a5ba6ec03aaa62c7118eb12dce041","src/group_cipher.rs":"cadd9ac026bdb87cd6c5e15f97556962e47673b467d622d7de5583ec7893dfa9","src/identity_key.rs":"0876f1e8b7022632a7d125615a57d128cb2cc95cb460127fe0dbc9ee673410ea","src/lib.rs":"145d9f7ad1c4f400f37a6413ba5c09f2d74a4633b4e3181644470144821010a8","src/proto.rs":"9f0456ffff28f14f0e3fac51825d916abb785f8cf45a29b867aa17ae20a3f084","src/proto/fingerprint.proto":"ff64ad6d93f27ed525f9405d23d5e230d72697a762408fa83b04bae84e85125e","src/proto/fingerprint.rs":"091f5ec64ca5b9d143c5bf838130fadb6a5eed8b0ac9e551d318d677699e0d99","src/proto/sealed_sender.proto":"058d6aefd554ed30f96d142b5585ae375c09dd151c5b6c878e1af4152e49f433","src/proto/sealed_sender.rs":"c28a74bf813808ba92d3fb7029069b8f515bb302591680f821de2a649ffcc838","src/proto/service.proto":"38a9f6d53ccadc872d0c47a1bb973a8a741e55959c5b6b7d1aec7f4b8d082250","src/proto/service.rs":"d05ba074d94d4cbe6f90109dc9a9856a9ea744b51e7720c52f77381cecf08443","src/proto/storage.proto":"4113b802bc10bded1119b1a2f4c5e7cd96ac08c3c5838f7a3c47d0dcf0b6d87a","src/proto/storage.rs":"be1cc45e44ec2ed7c3a11d9e6d32e3c333035aec32cf5b5ccf2d3da8010af4a0","src/proto/wire.proto":"dd7df265ae21e79d020764e137e88df7b76661f148e1e504dacc9a63fa411fb4","src/proto/wire.rs":"e16a9fb626d2aebf81cec15bf1e9f7a7d06a72f95d3d7f948fef179fd03f501d","src/protocol.rs":"66a1518455ad01f01286a4388595042b433e1a54c7d2ef5737e2f0d8263f9d44","src/ratchet.rs":"28a141ad8359de514a1b75c74131fcf659bab0a2efc0dbcf650d33250420f171","src/ratchet/keys.rs":"943416a4bf5d2e49813956b6234b51a1765488e415c772ec135ab9a7004a6e38","src/ratchet/params.rs":"5781aaa006e825e7596ca03cb69f1502dd6d2a749b65fec45d4bac5161ecb74e","src/sealed_sender.rs":"a16852ed7921b9a901418b1640eecdf1c82c15afc621501d5af6513ef989b4c8","src/sender_keys.rs":"ceb9fbd148fb6b129cbb69201c5a97a270dde84c111f97fa2b7a39aa71d39e0c","src/session.rs":"9c2d96f43b205ff1122f523b45285233ba8749f64dbe7424f070326a8e290afe","src/session_cipher.rs":"3f60353791a62621b1de70cbd121328a9fb3c7731f4fec2aa356d97633f58c00","src/state.rs":"52ced20ecd6a50e22a30b2c062ebd669db8aa2f45477e414ba841b626c40641c","src/state/bundle.rs":"d006e77e472cc12e2ea93ae2c37e07658a3d90ddeecced7296985f6a3660d8d3","src/state/prekey.rs":"1827a7ab2390991ea7a388b4714405c682427a25be088c4d9c9d0529e718d2f9","src/state/session.rs":"1d0e4b92c90a1c9f09cee7f2b3ef067e2d11fd5085d78b63d453317536edb07f","src/state/signed_prekey.rs":"0286606af9ba7629822482df2257d00eb0ab6a64462ce8342366e58b67b91343","src/storage.rs":"51bd8090c29a4bcc293a645542f3ee11922cfaf030e2b933c24e0b81aed7f0b9","src/storage/inmem.rs":"3b788ce43e7243f0c978f97064beb3b89a790f07abbbf945ab0d2c0b3ec9e041","src/storage/traits.rs":"41e24813c16c6e2a09e1da7308981d4b47c6a891f123fba7eec37dd4af5886ac","src/utils.rs":"a6a17011a534f5bf8e81d69033fa4062d6b8d6368173627c46d6df8ab43c4fd2","tests/groups.rs":"664f5cb58947aee75bbc25e904b45ff9970d91c7ea21496077683d597603ce8d","tests/ratchet.rs":"ae54a030822b64c2909470037b54e0f291b3152d50e494f8da51f0987472e5da","tests/sealed_sender.rs":"261e16e5781c018622c63b0cc2c7d6ba47d05d582ff3b34fbed643ae2c2d62ce","tests/session.rs":"f2f66ba8fa51c9f650cb273354ff8f9f0af38e079298be4aff929c2f9eaf22c7","tests/support/mod.rs":"fdc47dd560ef95a58bcf76e4b385d459d997a25b6790a483de07349dc99b4617"},"package":null} \ No newline at end of file diff --git a/net/gurk-rs/files/vendor/libsignal-protocol/Cargo.toml b/net/gurk-rs/files/vendor/libsignal-protocol/Cargo.toml deleted file mode 100644 index e3d66d0..0000000 --- a/net/gurk-rs/files/vendor/libsignal-protocol/Cargo.toml +++ /dev/null @@ -1,56 +0,0 @@ -# -# Copyright (C) 2020-2021 Signal Messenger, LLC. -# SPDX-License-Identifier: AGPL-3.0-only -# - -[package] -name = "libsignal-protocol" -version = "0.1.0" -authors = ["Ehren Kret ", "Jack Lloyd "] -edition = "2018" -license = "AGPL-3.0-only" -repository = "https://github.com/signalapp/libsignal-client" - -[dependencies] -aes = { version = "0.7.4", features = ["ctr"] } -aes-gcm-siv = "0.10.1" -arrayref = "0.3.6" -async-trait = "0.1.41" -block-modes = "0.8" -curve25519-dalek = { version = "3.0", features = ["serde"] } -hkdf = "0.11" -hmac = "0.11.0" -itertools = "0.10.1" -prost = "0.8" -rand = "0.7.3" -sha2 = "0.9" -subtle = "2.2.3" -x25519-dalek = "1.0" -hex = "0.4" -log = "0.4" -num_enum = "0.5.1" -uuid = "0.8" -displaydoc = "0.2" -thiserror = "1.0.30" - -[features] -armv8 = ["aes/armv8", "aes-gcm-siv/armv8"] - -[dev-dependencies] -criterion = "0.3" -futures-util = "0.3.7" - -[build-dependencies] -prost-build = "0.8" - -[[bench]] -name = "session" -harness = false - -[[bench]] -name = "ratchet" -harness = false - -[[bench]] -name = "sealed_sender" -harness = false diff --git a/net/gurk-rs/files/vendor/libsignal-protocol/benches/ratchet.rs b/net/gurk-rs/files/vendor/libsignal-protocol/benches/ratchet.rs deleted file mode 100644 index 047c23f..0000000 --- a/net/gurk-rs/files/vendor/libsignal-protocol/benches/ratchet.rs +++ /dev/null @@ -1,103 +0,0 @@ -// -// Copyright 2020 Signal Messenger, LLC. -// SPDX-License-Identifier: AGPL-3.0-only -// - -use criterion::{criterion_group, criterion_main, Criterion, SamplingMode}; -use futures_util::FutureExt; -use libsignal_protocol::*; -use std::convert::TryFrom; -use uuid::Uuid; - -#[path = "../tests/support/mod.rs"] -mod support; - -pub fn ratchet_forward_result(c: &mut Criterion) -> Result<(), SignalProtocolError> { - let mut group = c.benchmark_group("ratchet"); - group.sampling_mode(SamplingMode::Flat); - group.sample_size(10); //minimum allowed... - group.warm_up_time(core::time::Duration::from_millis(100)); - - let mut csprng = rand::rngs::OsRng; - - let sender_address = ProtocolAddress::new("+14159999111".to_owned(), 1); - let distribution_id = Uuid::from_u128(0xd1d1d1d1_7000_11eb_b32a_33b8a8a487a6); - - let mut alice_store = support::test_in_memory_protocol_store()?; - let mut bob_store = support::test_in_memory_protocol_store()?; - - let sent_distribution_message = create_sender_key_distribution_message( - &sender_address, - distribution_id, - &mut alice_store, - &mut csprng, - None, - ) - .now_or_never() - .expect("sync")?; - - let recv_distribution_message = - SenderKeyDistributionMessage::try_from(sent_distribution_message.serialized())?; - - process_sender_key_distribution_message( - &sender_address, - &recv_distribution_message, - &mut bob_store, - None, - ) - .now_or_never() - .expect("sync")?; - - for ratchets in [100, 1000].iter() { - let ratchets = *ratchets; - - for i in 0..ratchets { - group_encrypt( - &mut alice_store, - &sender_address, - distribution_id, - format!("nefarious plotting {}", i).as_bytes(), - &mut csprng, - None, - ) - .now_or_never() - .expect("sync")?; - } - - let alice_ciphertext = group_encrypt( - &mut alice_store, - &sender_address, - distribution_id, - "you got the plan?".as_bytes(), - &mut csprng, - None, - ) - .now_or_never() - .expect("sync")?; - - group.bench_function(format!("ratchet {}", ratchets), |b| { - b.iter(|| { - let mut bob_store = bob_store.clone(); - group_decrypt( - alice_ciphertext.serialized(), - &mut bob_store, - &sender_address, - None, - ) - .now_or_never() - .expect("sync") - .expect("ok"); - }) - }); - } - - Ok(()) -} - -pub fn ratchet_forward(mut c: &mut Criterion) { - ratchet_forward_result(&mut c).expect("success"); -} - -criterion_group!(ratchet, ratchet_forward); - -criterion_main!(ratchet); diff --git a/net/gurk-rs/files/vendor/libsignal-protocol/benches/sealed_sender.rs b/net/gurk-rs/files/vendor/libsignal-protocol/benches/sealed_sender.rs deleted file mode 100644 index f548c6e..0000000 --- a/net/gurk-rs/files/vendor/libsignal-protocol/benches/sealed_sender.rs +++ /dev/null @@ -1,287 +0,0 @@ -// -// Copyright 2021 Signal Messenger, LLC. -// SPDX-License-Identifier: AGPL-3.0-only -// - -use criterion::{criterion_group, criterion_main, BenchmarkId, Criterion}; -use futures_util::FutureExt; -use libsignal_protocol::*; -use rand::rngs::OsRng; -use rand::Rng; -use uuid::Uuid; - -#[path = "../tests/support/mod.rs"] -mod support; - -pub fn v1(c: &mut Criterion) { - let mut rng = OsRng; - - let alice_address = ProtocolAddress::new("9d0652a3-dcc3-4d11-975f-74d61598733f".to_owned(), 1); - let bob_address = ProtocolAddress::new("796abedb-ca4e-4f18-8803-1fde5b921f9f".to_owned(), 1); - - let mut alice_store = support::test_in_memory_protocol_store().expect("brand new store"); - let mut bob_store = support::test_in_memory_protocol_store().expect("brand new store"); - - let bob_pre_key_bundle = support::create_pre_key_bundle(&mut bob_store, &mut rng) - .now_or_never() - .expect("sync") - .expect("valid"); - - process_prekey_bundle( - &bob_address, - &mut alice_store.session_store, - &mut alice_store.identity_store, - &bob_pre_key_bundle, - &mut rng, - None, - ) - .now_or_never() - .expect("sync") - .expect("valid"); - - let trust_root = KeyPair::generate(&mut rng); - let server_key = KeyPair::generate(&mut rng); - - let server_cert = - ServerCertificate::new(1, server_key.public_key, &trust_root.private_key, &mut rng) - .expect("valid"); - - let expires = 1605722925; - - let sender_cert = SenderCertificate::new( - alice_address.name().to_string(), - None, - *alice_store - .get_identity_key_pair(None) - .now_or_never() - .expect("sync") - .expect("valid") - .public_key(), - alice_address.device_id(), - expires, - server_cert, - &server_key.private_key, - &mut rng, - ) - .expect("valid"); - - let message = b"hello"; - let usmc = UnidentifiedSenderMessageContent::new( - CiphertextMessageType::Plaintext, - sender_cert, - message.to_vec(), - ContentHint::Default, - None, - ) - .expect("valid"); - - let mut encrypt_it = || { - sealed_sender_encrypt_from_usmc( - &bob_address, - &usmc, - &mut alice_store.identity_store, - None, - &mut rng, - ) - .now_or_never() - .expect("sync") - .expect("valid") - }; - let encrypted = encrypt_it(); - - let mut decrypt_it = || { - sealed_sender_decrypt_to_usmc(&encrypted, &mut bob_store.identity_store, None) - .now_or_never() - .expect("sync") - .expect("valid") - }; - assert_eq!(message, decrypt_it().contents().expect("valid")); - - c.bench_function("v1/encrypt", |b| b.iter(&mut encrypt_it)); - c.bench_function("v1/decrypt", |b| b.iter(&mut decrypt_it)); -} - -pub fn v2(c: &mut Criterion) { - let mut rng = OsRng; - - let alice_address = ProtocolAddress::new("9d0652a3-dcc3-4d11-975f-74d61598733f".to_owned(), 1); - let bob_address = ProtocolAddress::new("796abedb-ca4e-4f18-8803-1fde5b921f9f".to_owned(), 1); - - let mut alice_store = support::test_in_memory_protocol_store().expect("brand new store"); - let mut bob_store = support::test_in_memory_protocol_store().expect("brand new store"); - - let bob_pre_key_bundle = support::create_pre_key_bundle(&mut bob_store, &mut rng) - .now_or_never() - .expect("sync") - .expect("valid"); - - process_prekey_bundle( - &bob_address, - &mut alice_store.session_store, - &mut alice_store.identity_store, - &bob_pre_key_bundle, - &mut rng, - None, - ) - .now_or_never() - .expect("sync") - .expect("valid"); - - let trust_root = KeyPair::generate(&mut rng); - let server_key = KeyPair::generate(&mut rng); - - let server_cert = - ServerCertificate::new(1, server_key.public_key, &trust_root.private_key, &mut rng) - .expect("valid"); - - let expires = 1605722925; - - let sender_cert = SenderCertificate::new( - alice_address.name().to_string(), - None, - *alice_store - .get_identity_key_pair(None) - .now_or_never() - .expect("sync") - .expect("valid") - .public_key(), - alice_address.device_id(), - expires, - server_cert, - &server_key.private_key, - &mut rng, - ) - .expect("valid"); - - let message = b"hello"; - let usmc = UnidentifiedSenderMessageContent::new( - CiphertextMessageType::Plaintext, - sender_cert, - message.to_vec(), - ContentHint::Default, - None, - ) - .expect("valid"); - - let mut encrypt_it = || { - sealed_sender_multi_recipient_encrypt( - &[&bob_address], - &alice_store - .session_store - .load_existing_sessions(&[&bob_address]) - .expect("present"), - &usmc, - &mut alice_store.identity_store, - None, - &mut rng, - ) - .now_or_never() - .expect("sync") - .expect("valid") - }; - let outgoing = encrypt_it(); - - let incoming = sealed_sender_multi_recipient_fan_out(&outgoing) - .expect("valid") - .into_iter() - .next() - .expect("at least one destination"); - - let mut decrypt_it = || { - sealed_sender_decrypt_to_usmc(&incoming, &mut bob_store.identity_store, None) - .now_or_never() - .expect("sync") - .expect("valid") - }; - assert_eq!(message, decrypt_it().contents().expect("valid")); - - c.bench_function("v2/encrypt", |b| b.iter(&mut encrypt_it)); - c.bench_function("v2/decrypt", |b| b.iter(&mut decrypt_it)); - - // Fill out additional recipients. - let mut recipients = vec![bob_address.clone()]; - while recipients.len() < 10 { - let next_address = ProtocolAddress::new(Uuid::from_bytes(rng.gen()).to_string(), 1); - - let mut next_store = support::test_in_memory_protocol_store().expect("brand new store"); - - let next_pre_key_bundle = support::create_pre_key_bundle(&mut next_store, &mut rng) - .now_or_never() - .expect("sync") - .expect("valid"); - - process_prekey_bundle( - &next_address, - &mut alice_store.session_store, - &mut alice_store.identity_store, - &next_pre_key_bundle, - &mut rng, - None, - ) - .now_or_never() - .expect("sync") - .expect("valid"); - - recipients.push(next_address); - } - - let mut group = c.benchmark_group("v2/encrypt/multi-recipient"); - for recipient_count in [2, 5, 10] { - group.bench_with_input( - BenchmarkId::from_parameter(recipient_count), - &recipient_count, - |b, &recipient_count| { - let recipients: Vec<_> = recipients.iter().take(recipient_count).collect(); - b.iter(|| { - sealed_sender_multi_recipient_encrypt( - &recipients, - &alice_store - .session_store - .load_existing_sessions(&recipients) - .expect("present"), - &usmc, - &mut alice_store.identity_store, - None, - &mut rng, - ) - .now_or_never() - .expect("sync") - .expect("valid") - }); - }, - ); - } - group.finish(); - - let mut group = c.benchmark_group("v2/encrypt/multi-device"); - for device_count in [2, 5, 10] { - group.bench_with_input( - BenchmarkId::from_parameter(device_count), - &device_count, - |b, &device_count| { - let recipients: Vec<_> = vec![&bob_address; device_count]; - b.iter(|| { - sealed_sender_multi_recipient_encrypt( - &recipients, - &alice_store - .session_store - .load_existing_sessions(&recipients) - .expect("present"), - &usmc, - &mut alice_store.identity_store, - None, - &mut rng, - ) - .now_or_never() - .expect("sync") - .expect("valid") - }); - }, - ); - } - group.finish(); -} - -criterion_group!(benches, v1, v2); - -criterion_main!(benches); diff --git a/net/gurk-rs/files/vendor/libsignal-protocol/benches/session.rs b/net/gurk-rs/files/vendor/libsignal-protocol/benches/session.rs deleted file mode 100644 index f5f8c35..0000000 --- a/net/gurk-rs/files/vendor/libsignal-protocol/benches/session.rs +++ /dev/null @@ -1,249 +0,0 @@ -// -// Copyright 2020-2021 Signal Messenger, LLC. -// SPDX-License-Identifier: AGPL-3.0-only -// - -use criterion::{criterion_group, criterion_main, Criterion}; -use futures_util::FutureExt; -use libsignal_protocol::*; -use rand::rngs::OsRng; - -#[path = "../tests/support/mod.rs"] -mod support; - -pub fn session_encrypt_result(c: &mut Criterion) -> Result<(), SignalProtocolError> { - let (alice_session_record, bob_session_record) = support::initialize_sessions_v3()?; - - let alice_address = ProtocolAddress::new("+14159999999".to_owned(), 1); - let bob_address = ProtocolAddress::new("+14158888888".to_owned(), 1); - - let mut alice_store = support::test_in_memory_protocol_store()?; - let mut bob_store = support::test_in_memory_protocol_store()?; - - alice_store - .store_session(&bob_address, &alice_session_record, None) - .now_or_never() - .expect("sync")?; - bob_store - .store_session(&alice_address, &bob_session_record, None) - .now_or_never() - .expect("sync")?; - - let message_to_decrypt = support::encrypt(&mut alice_store, &bob_address, "a short message") - .now_or_never() - .expect("sync")?; - - c.bench_function("session decrypt first message", |b| { - b.iter(|| { - let mut bob_store = bob_store.clone(); - support::decrypt(&mut bob_store, &alice_address, &message_to_decrypt) - .now_or_never() - .expect("sync") - .expect("success"); - }) - }); - - let _ = support::decrypt(&mut bob_store, &alice_address, &message_to_decrypt) - .now_or_never() - .expect("sync")?; - let message_to_decrypt = support::encrypt(&mut alice_store, &bob_address, "a short message") - .now_or_never() - .expect("sync")?; - - c.bench_function("session encrypt", |b| { - b.iter(|| { - support::encrypt(&mut alice_store, &bob_address, "a short message") - .now_or_never() - .expect("sync") - .expect("success"); - }) - }); - c.bench_function("session decrypt", |b| { - b.iter(|| { - let mut bob_store = bob_store.clone(); - support::decrypt(&mut bob_store, &alice_address, &message_to_decrypt) - .now_or_never() - .expect("sync") - .expect("success"); - }) - }); - - // Archive on Alice's side... - let mut state = alice_store - .load_session(&bob_address, None) - .now_or_never() - .expect("sync")? - .expect("already decrypted successfully"); - state.archive_current_state()?; - alice_store - .store_session(&bob_address, &state, None) - .now_or_never() - .expect("sync")?; - - // ...then initialize a new session... - let bob_signed_pre_key_pair = KeyPair::generate(&mut OsRng); - - let bob_signed_pre_key_public = bob_signed_pre_key_pair.public_key.serialize(); - let bob_signed_pre_key_signature = bob_store - .get_identity_key_pair(None) - .now_or_never() - .expect("sync")? - .private_key() - .calculate_signature(&bob_signed_pre_key_public, &mut OsRng)?; - - let signed_pre_key_id = 22; - - let bob_pre_key_bundle = PreKeyBundle::new( - bob_store - .get_local_registration_id(None) - .now_or_never() - .expect("sync")?, - 1, // device id - None, // pre key - signed_pre_key_id, // signed pre key id - bob_signed_pre_key_pair.public_key, - bob_signed_pre_key_signature.to_vec(), - *bob_store - .get_identity_key_pair(None) - .now_or_never() - .expect("sync")? - .identity_key(), - )?; - - bob_store - .save_signed_pre_key( - signed_pre_key_id, - &SignedPreKeyRecord::new( - signed_pre_key_id, - /*timestamp*/ 42, - &bob_signed_pre_key_pair, - &bob_signed_pre_key_signature, - ), - None, - ) - .now_or_never() - .expect("sync")?; - - // initialize_sessions_v3 makes up its own identity keys, - // so we need to reset here to avoid it looking like the identity changed. - alice_store.identity_store.reset(); - bob_store.identity_store.reset(); - - process_prekey_bundle( - &bob_address, - &mut alice_store.session_store, - &mut alice_store.identity_store, - &bob_pre_key_bundle, - &mut OsRng, - None, - ) - .now_or_never() - .expect("sync")?; - - let original_message_to_decrypt = message_to_decrypt; - - // ...send another message to archive on Bob's side... - let message_to_decrypt = support::encrypt(&mut alice_store, &bob_address, "a short message") - .now_or_never() - .expect("sync")?; - let _ = support::decrypt(&mut bob_store, &alice_address, &message_to_decrypt) - .now_or_never() - .expect("sync")?; - // ...and prepare another message to benchmark decrypting. - let message_to_decrypt = support::encrypt(&mut alice_store, &bob_address, "a short message") - .now_or_never() - .expect("sync")?; - - c.bench_function("session decrypt with archived state", |b| { - b.iter(|| { - let mut bob_store = bob_store.clone(); - support::decrypt(&mut bob_store, &alice_address, &message_to_decrypt) - .now_or_never() - .expect("sync") - .expect("success"); - }) - }); - - // Reset once more to go back to the original message. - bob_store.identity_store.reset(); - - c.bench_function("session decrypt using previous state", |b| { - b.iter(|| { - let mut bob_store = bob_store.clone(); - support::decrypt(&mut bob_store, &alice_address, &original_message_to_decrypt) - .now_or_never() - .expect("sync") - .expect("success"); - }) - }); - - Ok(()) -} - -pub fn session_encrypt_decrypt_result(c: &mut Criterion) -> Result<(), SignalProtocolError> { - let (alice_session_record, bob_session_record) = support::initialize_sessions_v3()?; - - let alice_address = ProtocolAddress::new("+14159999999".to_owned(), 1); - let bob_address = ProtocolAddress::new("+14158888888".to_owned(), 1); - - let mut alice_store = support::test_in_memory_protocol_store()?; - let mut bob_store = support::test_in_memory_protocol_store()?; - - alice_store - .store_session(&bob_address, &alice_session_record, None) - .now_or_never() - .expect("sync")?; - bob_store - .store_session(&alice_address, &bob_session_record, None) - .now_or_never() - .expect("sync")?; - - c.bench_function("session encrypt+decrypt 1 way", |b| { - b.iter(|| { - let ctext = support::encrypt(&mut alice_store, &bob_address, "a short message") - .now_or_never() - .expect("sync") - .expect("success"); - let _ptext = support::decrypt(&mut bob_store, &alice_address, &ctext) - .now_or_never() - .expect("sync") - .expect("success"); - }) - }); - - c.bench_function("session encrypt+decrypt ping pong", |b| { - b.iter(|| { - let ctext = support::encrypt(&mut alice_store, &bob_address, "a short message") - .now_or_never() - .expect("sync") - .expect("success"); - let _ptext = support::decrypt(&mut bob_store, &alice_address, &ctext) - .now_or_never() - .expect("sync") - .expect("success"); - - let ctext = support::encrypt(&mut bob_store, &alice_address, "a short message") - .now_or_never() - .expect("sync") - .expect("success"); - let _ptext = support::decrypt(&mut alice_store, &bob_address, &ctext) - .now_or_never() - .expect("sync") - .expect("success"); - }) - }); - - Ok(()) -} - -pub fn session_encrypt(mut c: &mut Criterion) { - session_encrypt_result(&mut c).expect("success"); -} - -pub fn session_encrypt_decrypt(mut c: &mut Criterion) { - session_encrypt_decrypt_result(&mut c).expect("success"); -} - -criterion_group!(benches, session_encrypt, session_encrypt_decrypt); - -criterion_main!(benches); diff --git a/net/gurk-rs/files/vendor/libsignal-protocol/build.rs b/net/gurk-rs/files/vendor/libsignal-protocol/build.rs deleted file mode 100644 index 8fc1b49..0000000 --- a/net/gurk-rs/files/vendor/libsignal-protocol/build.rs +++ /dev/null @@ -1,18 +0,0 @@ -// -// Copyright 2020 Signal Messenger, LLC. -// SPDX-License-Identifier: AGPL-3.0-only -// - -fn main() { - let protos = [ - "src/proto/fingerprint.proto", - "src/proto/sealed_sender.proto", - "src/proto/service.proto", - "src/proto/storage.proto", - "src/proto/wire.proto", - ]; - prost_build::compile_protos(&protos, &["src"]).expect("Protobufs in src are valid"); - for proto in &protos { - println!("cargo:rerun-if-changed={}", proto); - } -} diff --git a/net/gurk-rs/files/vendor/libsignal-protocol/src/address.rs b/net/gurk-rs/files/vendor/libsignal-protocol/src/address.rs deleted file mode 100644 index 18aa59f..0000000 --- a/net/gurk-rs/files/vendor/libsignal-protocol/src/address.rs +++ /dev/null @@ -1,73 +0,0 @@ -// -// Copyright 2020-2021 Signal Messenger, LLC. -// SPDX-License-Identifier: AGPL-3.0-only -// - -#![warn(missing_docs)] - -//! A normalized representation of an individual Signal client instance. - -#[cfg(doc)] -use crate::SignalMessage; - -use std::fmt; - -/// The type used in memory to represent a *device*, i.e. a particular Signal client instance which -/// represents some user. -/// -/// Used in [ProtocolAddress]. -pub type DeviceId = u32; - -/// Represents a unique Signal client instance as `(, )` pair. -#[derive(Clone, Debug, Hash, Eq, PartialEq, PartialOrd, Ord)] -pub struct ProtocolAddress { - name: String, - device_id: DeviceId, -} - -impl ProtocolAddress { - /// Create a new address. - /// - /// - `name` defines a user's public identity, and therefore must be globally unique to that - /// user. - /// - Each Signal client instance then has its own `device_id`, which must be unique among - /// all clients for that user. - /// - ///``` - /// use libsignal_protocol::{DeviceId, ProtocolAddress}; - /// - /// // This is a unique id for some user, typically a UUID. - /// let user_id: String = "04899A85-4C9E-44CC-8428-A02AB69335F1".to_string(); - /// // Each client instance representing that user has a unique device id. - /// let device_id: DeviceId = 2_u32.into(); - /// let address = ProtocolAddress::new(user_id.clone(), device_id); - /// - /// assert!(address.name() == &user_id); - /// assert!(address.device_id() == device_id); - ///``` - pub fn new(name: String, device_id: DeviceId) -> Self { - ProtocolAddress { name, device_id } - } - - /// A unique identifier for the target user. This is usually a UUID. - #[inline] - pub fn name(&self) -> &str { - &self.name - } - - /// An identifier representing a particular Signal client instance to send to. - /// - /// For example, if a user has set up Signal on both their phone and laptop, any [SignalMessage] - /// sent to the user will still only go to a single device. So when a user sends a message to - /// another user at all, they're actually sending a message to *every* device. - #[inline] - pub fn device_id(&self) -> DeviceId { - self.device_id - } -} - -impl fmt::Display for ProtocolAddress { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "{}.{}", self.name, self.device_id) - } -} diff --git a/net/gurk-rs/files/vendor/libsignal-protocol/src/consts.rs b/net/gurk-rs/files/vendor/libsignal-protocol/src/consts.rs deleted file mode 100644 index 6b0b4db..0000000 --- a/net/gurk-rs/files/vendor/libsignal-protocol/src/consts.rs +++ /dev/null @@ -1,10 +0,0 @@ -// -// Copyright 2020 Signal Messenger, LLC. -// SPDX-License-Identifier: AGPL-3.0-only -// - -pub const MAX_FORWARD_JUMPS: usize = 25_000; -pub const MAX_MESSAGE_KEYS: usize = 2000; -pub const MAX_RECEIVER_CHAINS: usize = 5; -pub const ARCHIVED_STATES_MAX_LENGTH: usize = 40; -pub const MAX_SENDER_KEY_STATES: usize = 5; diff --git a/net/gurk-rs/files/vendor/libsignal-protocol/src/crypto.rs b/net/gurk-rs/files/vendor/libsignal-protocol/src/crypto.rs deleted file mode 100644 index 5fb8071..0000000 --- a/net/gurk-rs/files/vendor/libsignal-protocol/src/crypto.rs +++ /dev/null @@ -1,147 +0,0 @@ -// -// Copyright 2020 Signal Messenger, LLC. -// SPDX-License-Identifier: AGPL-3.0-only -// - -use crate::{error::Result, SignalProtocolError}; - -use aes::cipher::{NewCipher, StreamCipher}; -use aes::{Aes256, Aes256Ctr}; -use block_modes::block_padding::Pkcs7; -use block_modes::{BlockMode, Cbc}; -use hmac::{Hmac, Mac, NewMac}; -use sha2::Sha256; -use subtle::ConstantTimeEq; - -pub fn aes_256_ctr_encrypt(ptext: &[u8], key: &[u8]) -> Result> { - if key.len() != 32 { - return Err(SignalProtocolError::InvalidCipherCryptographicParameters( - 32, 0, - )); - } - - let zero_nonce = [0u8; 16]; - let mut cipher = Aes256Ctr::new(key.into(), (&zero_nonce).into()); - - let mut ctext = ptext.to_vec(); - cipher.apply_keystream(&mut ctext); - Ok(ctext) -} - -pub fn aes_256_ctr_decrypt(ctext: &[u8], key: &[u8]) -> Result> { - aes_256_ctr_encrypt(ctext, key) -} - -pub fn aes_256_cbc_encrypt(ptext: &[u8], key: &[u8], iv: &[u8]) -> Result> { - match Cbc::::new_from_slices(key, iv) { - Ok(mode) => Ok(mode.encrypt_vec(ptext)), - Err(block_modes::InvalidKeyIvLength) => Err( - SignalProtocolError::InvalidCipherCryptographicParameters(key.len(), iv.len()), - ), - } -} - -pub fn aes_256_cbc_decrypt(ctext: &[u8], key: &[u8], iv: &[u8]) -> Result> { - if ctext.is_empty() || ctext.len() % 16 != 0 { - return Err(SignalProtocolError::InvalidCiphertext); - } - - let mode = match Cbc::::new_from_slices(key, iv) { - Ok(mode) => mode, - Err(block_modes::InvalidKeyIvLength) => { - return Err(SignalProtocolError::InvalidCipherCryptographicParameters( - key.len(), - iv.len(), - )) - } - }; - - mode.decrypt_vec(ctext) - .map_err(|_| SignalProtocolError::InvalidCiphertext) -} - -pub fn hmac_sha256(key: &[u8], input: &[u8]) -> Result<[u8; 32]> { - let mut hmac = - Hmac::::new_from_slice(key).expect("HMAC-SHA256 should accept any size key"); - hmac.update(input); - Ok(hmac.finalize().into_bytes().into()) -} - -pub fn aes256_ctr_hmacsha256_encrypt( - msg: &[u8], - cipher_key: &[u8], - mac_key: &[u8], -) -> Result> { - let ctext = aes_256_ctr_encrypt(msg, cipher_key)?; - let mac = hmac_sha256(mac_key, &ctext)?; - let mut result = Vec::with_capacity(ctext.len() + 10); - result.extend_from_slice(&ctext); - result.extend_from_slice(&mac[..10]); - Ok(result) -} - -pub fn aes256_ctr_hmacsha256_decrypt( - ctext: &[u8], - cipher_key: &[u8], - mac_key: &[u8], -) -> Result> { - if ctext.len() < 10 { - return Err(SignalProtocolError::InvalidCiphertext); - } - let ptext_len = ctext.len() - 10; - let our_mac = hmac_sha256(mac_key, &ctext[..ptext_len])?; - let same: bool = our_mac[..10].ct_eq(&ctext[ptext_len..]).into(); - if !same { - return Err(SignalProtocolError::InvalidCiphertext); - } - aes_256_ctr_decrypt(&ctext[..ptext_len], cipher_key) -} - -#[cfg(test)] -mod test { - use super::Result; - - #[test] - fn aes_cbc_test() -> Result<()> { - let key = hex::decode("4e22eb16d964779994222e82192ce9f747da72dc4abe49dfdeeb71d0ffe3796e") - .expect("valid hex"); - let iv = hex::decode("6f8a557ddc0a140c878063a6d5f31d3d").expect("valid hex"); - - let ptext = hex::decode("30736294a124482a4159").expect("valid hex"); - - let ctext = super::aes_256_cbc_encrypt(&ptext, &key, &iv)?; - assert_eq!( - hex::encode(ctext.clone()), - "dd3f573ab4508b9ed0e45e0baf5608f3" - ); - - let recovered = super::aes_256_cbc_decrypt(&ctext, &key, &iv)?; - assert_eq!(hex::encode(ptext), hex::encode(recovered.clone())); - - // padding is invalid: - assert!(super::aes_256_cbc_decrypt(&recovered, &key, &iv).is_err()); - assert!(super::aes_256_cbc_decrypt(&ctext, &key, &ctext).is_err()); - - // bitflip the IV to cause a change in the recovered text - let bad_iv = hex::decode("ef8a557ddc0a140c878063a6d5f31d3d").expect("valid hex"); - let recovered = super::aes_256_cbc_decrypt(&ctext, &key, &bad_iv)?; - assert_eq!(hex::encode(recovered), "b0736294a124482a4159"); - - Ok(()) - } - - #[test] - fn aes_ctr_test() -> Result<()> { - let key = hex::decode("603DEB1015CA71BE2B73AEF0857D77811F352C073B6108D72D9810A30914DFF4") - .expect("valid hex"); - let ptext = [0u8; 35]; - - let ctext = super::aes_256_ctr_encrypt(&ptext, &key)?; - assert_eq!( - hex::encode(ctext), - "e568f68194cf76d6174d4cc04310a85491151e5d0b7a1f1bc0d7acd0ae3e51e4170e23" - ); - - Ok(()) - } -} diff --git a/net/gurk-rs/files/vendor/libsignal-protocol/src/curve.rs b/net/gurk-rs/files/vendor/libsignal-protocol/src/curve.rs deleted file mode 100644 index 0f62512..0000000 --- a/net/gurk-rs/files/vendor/libsignal-protocol/src/curve.rs +++ /dev/null @@ -1,402 +0,0 @@ -// -// Copyright 2020-2021 Signal Messenger, LLC. -// SPDX-License-Identifier: AGPL-3.0-only -// - -pub(crate) mod curve25519; - -use crate::{Result, SignalProtocolError}; - -use std::cmp::Ordering; -use std::convert::TryFrom; -use std::fmt; - -use arrayref::array_ref; -use rand::{CryptoRng, Rng}; -use subtle::ConstantTimeEq; - -#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord)] -pub enum KeyType { - Djb, -} - -impl fmt::Display for KeyType { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - fmt::Debug::fmt(self, f) - } -} - -impl KeyType { - fn value(&self) -> u8 { - match &self { - KeyType::Djb => 0x05u8, - } - } -} - -impl TryFrom for KeyType { - type Error = SignalProtocolError; - - fn try_from(x: u8) -> Result { - match x { - 0x05u8 => Ok(KeyType::Djb), - t => Err(SignalProtocolError::BadKeyType(t)), - } - } -} - -#[derive(Debug, Clone, Copy, Eq, PartialEq)] -enum PublicKeyData { - DjbPublicKey([u8; curve25519::PUBLIC_KEY_LENGTH]), -} - -#[derive(Clone, Copy, Eq)] -pub struct PublicKey { - key: PublicKeyData, -} - -impl PublicKey { - fn new(key: PublicKeyData) -> Self { - Self { key } - } - - pub fn deserialize(value: &[u8]) -> Result { - if value.is_empty() { - return Err(SignalProtocolError::NoKeyTypeIdentifier); - } - let key_type = KeyType::try_from(value[0])?; - match key_type { - KeyType::Djb => { - // We allow trailing data after the public key (why?) - if value.len() < curve25519::PUBLIC_KEY_LENGTH + 1 { - return Err(SignalProtocolError::BadKeyLength(KeyType::Djb, value.len())); - } - let mut key = [0u8; curve25519::PUBLIC_KEY_LENGTH]; - key.copy_from_slice(&value[1..][..curve25519::PUBLIC_KEY_LENGTH]); - Ok(PublicKey { - key: PublicKeyData::DjbPublicKey(key), - }) - } - } - } - - pub fn public_key_bytes(&self) -> Result<&[u8]> { - match self.key { - PublicKeyData::DjbPublicKey(ref v) => Ok(v), - } - } - - pub fn from_djb_public_key_bytes(bytes: &[u8]) -> Result { - match <[u8; curve25519::PUBLIC_KEY_LENGTH]>::try_from(bytes) { - Err(_) => Err(SignalProtocolError::BadKeyLength(KeyType::Djb, bytes.len())), - Ok(key) => Ok(PublicKey { - key: PublicKeyData::DjbPublicKey(key), - }), - } - } - - pub fn serialize(&self) -> Box<[u8]> { - let value_len = match self.key { - PublicKeyData::DjbPublicKey(v) => v.len(), - }; - let mut result = Vec::with_capacity(1 + value_len); - result.push(self.key_type().value()); - match self.key { - PublicKeyData::DjbPublicKey(v) => result.extend_from_slice(&v), - } - result.into_boxed_slice() - } - - pub fn verify_signature(&self, message: &[u8], signature: &[u8]) -> Result { - match self.key { - PublicKeyData::DjbPublicKey(pub_key) => { - if signature.len() != curve25519::SIGNATURE_LENGTH { - return Ok(false); - } - Ok(curve25519::PrivateKey::verify_signature( - &pub_key, - message, - array_ref![signature, 0, curve25519::SIGNATURE_LENGTH], - )) - } - } - } - - fn key_data(&self) -> &[u8] { - match self.key { - PublicKeyData::DjbPublicKey(ref k) => k.as_ref(), - } - } - - pub fn key_type(&self) -> KeyType { - match self.key { - PublicKeyData::DjbPublicKey(_) => KeyType::Djb, - } - } -} - -impl From for PublicKey { - fn from(key: PublicKeyData) -> PublicKey { - Self { key } - } -} - -impl TryFrom<&[u8]> for PublicKey { - type Error = SignalProtocolError; - - fn try_from(value: &[u8]) -> Result { - Self::deserialize(value) - } -} - -impl subtle::ConstantTimeEq for PublicKey { - /// A constant-time comparison as long as the two keys have a matching type. - /// - /// If the two keys have different types, the comparison short-circuits, - /// much like comparing two slices of different lengths. - fn ct_eq(&self, other: &PublicKey) -> subtle::Choice { - if self.key_type() != other.key_type() { - return 0.ct_eq(&1); - } - self.key_data().ct_eq(other.key_data()) - } -} - -impl PartialEq for PublicKey { - fn eq(&self, other: &PublicKey) -> bool { - bool::from(self.ct_eq(other)) - } -} - -impl Ord for PublicKey { - fn cmp(&self, other: &Self) -> Ordering { - if self.key_type() != other.key_type() { - return self.key_type().cmp(&other.key_type()); - } - - crate::utils::constant_time_cmp(self.key_data(), other.key_data()) - } -} - -impl PartialOrd for PublicKey { - fn partial_cmp(&self, other: &PublicKey) -> Option { - Some(self.cmp(other)) - } -} - -impl fmt::Debug for PublicKey { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!( - f, - "PublicKey {{ key_type={}, serialize={:?} }}", - self.key_type(), - self.serialize() - ) - } -} - -#[derive(Debug, Clone, Copy, Eq, PartialEq)] -enum PrivateKeyData { - DjbPrivateKey([u8; curve25519::PRIVATE_KEY_LENGTH]), -} - -#[derive(Clone, Copy, Eq, PartialEq)] -pub struct PrivateKey { - key: PrivateKeyData, -} - -impl PrivateKey { - pub fn deserialize(value: &[u8]) -> Result { - if value.len() != curve25519::PRIVATE_KEY_LENGTH { - Err(SignalProtocolError::BadKeyLength(KeyType::Djb, value.len())) - } else { - let mut key = [0u8; curve25519::PRIVATE_KEY_LENGTH]; - key.copy_from_slice(&value[..curve25519::PRIVATE_KEY_LENGTH]); - // Clamp: - key[0] &= 0xF8; - key[31] &= 0x7F; - key[31] |= 0x40; - Ok(Self { - key: PrivateKeyData::DjbPrivateKey(key), - }) - } - } - - pub fn serialize(&self) -> Vec { - match self.key { - PrivateKeyData::DjbPrivateKey(v) => v.to_vec(), - } - } - - pub fn public_key(&self) -> Result { - match self.key { - PrivateKeyData::DjbPrivateKey(private_key) => { - let public_key = - curve25519::PrivateKey::from(private_key).derive_public_key_bytes(); - Ok(PublicKey::new(PublicKeyData::DjbPublicKey(public_key))) - } - } - } - - pub fn key_type(&self) -> KeyType { - match self.key { - PrivateKeyData::DjbPrivateKey(_) => KeyType::Djb, - } - } - - pub fn calculate_signature( - &self, - message: &[u8], - csprng: &mut R, - ) -> Result> { - match self.key { - PrivateKeyData::DjbPrivateKey(k) => { - let private_key = curve25519::PrivateKey::from(k); - Ok(Box::new(private_key.calculate_signature(csprng, message))) - } - } - } - - pub fn calculate_agreement(&self, their_key: &PublicKey) -> Result> { - match (self.key, their_key.key) { - (PrivateKeyData::DjbPrivateKey(priv_key), PublicKeyData::DjbPublicKey(pub_key)) => { - let private_key = curve25519::PrivateKey::from(priv_key); - Ok(Box::new(private_key.calculate_agreement(&pub_key))) - } - } - } -} - -impl From for PrivateKey { - fn from(key: PrivateKeyData) -> PrivateKey { - Self { key } - } -} - -impl TryFrom<&[u8]> for PrivateKey { - type Error = SignalProtocolError; - - fn try_from(value: &[u8]) -> Result { - Self::deserialize(value) - } -} - -#[derive(Copy, Clone)] -pub struct KeyPair { - pub public_key: PublicKey, - pub private_key: PrivateKey, -} - -impl KeyPair { - pub fn generate(csprng: &mut R) -> Self { - let private_key = curve25519::PrivateKey::new(csprng); - - let public_key = PublicKey::from(PublicKeyData::DjbPublicKey( - private_key.derive_public_key_bytes(), - )); - let private_key = PrivateKey::from(PrivateKeyData::DjbPrivateKey( - private_key.private_key_bytes(), - )); - - Self { - public_key, - private_key, - } - } - - pub fn new(public_key: PublicKey, private_key: PrivateKey) -> Self { - Self { - public_key, - private_key, - } - } - - pub fn from_public_and_private(public_key: &[u8], private_key: &[u8]) -> Result { - let public_key = PublicKey::try_from(public_key)?; - let private_key = PrivateKey::try_from(private_key)?; - Ok(Self { - public_key, - private_key, - }) - } - - pub fn calculate_signature( - &self, - message: &[u8], - csprng: &mut R, - ) -> Result> { - self.private_key.calculate_signature(message, csprng) - } - - pub fn calculate_agreement(&self, their_key: &PublicKey) -> Result> { - self.private_key.calculate_agreement(their_key) - } -} - -impl TryFrom for KeyPair { - type Error = SignalProtocolError; - - fn try_from(value: PrivateKey) -> Result { - let public_key = value.public_key()?; - Ok(Self::new(public_key, value)) - } -} - -#[cfg(test)] -mod tests { - use rand::rngs::OsRng; - - use super::*; - - #[test] - fn test_large_signatures() -> Result<()> { - let mut csprng = OsRng; - let key_pair = KeyPair::generate(&mut csprng); - let mut message = [0u8; 1024 * 1024]; - let signature = key_pair - .private_key - .calculate_signature(&message, &mut csprng)?; - - assert!(key_pair.public_key.verify_signature(&message, &signature)?); - message[0] ^= 0x01u8; - assert!(!key_pair.public_key.verify_signature(&message, &signature)?); - message[0] ^= 0x01u8; - let public_key = key_pair.private_key.public_key()?; - assert!(public_key.verify_signature(&message, &signature)?); - - Ok(()) - } - - #[test] - fn test_decode_size() -> Result<()> { - let mut csprng = OsRng; - let key_pair = KeyPair::generate(&mut csprng); - let serialized_public = key_pair.public_key.serialize(); - - assert_eq!( - serialized_public, - key_pair.private_key.public_key()?.serialize() - ); - let empty: [u8; 0] = []; - - let just_right = PublicKey::try_from(&serialized_public[..]); - - assert!(just_right.is_ok()); - assert!(PublicKey::try_from(&serialized_public[1..]).is_err()); - assert!(PublicKey::try_from(&empty[..]).is_err()); - - let mut bad_key_type = [0u8; 33]; - bad_key_type[..].copy_from_slice(&serialized_public[..]); - bad_key_type[0] = 0x01u8; - assert!(PublicKey::try_from(&bad_key_type[..]).is_err()); - - let mut extra_space = [0u8; 34]; - extra_space[..33].copy_from_slice(&serialized_public[..]); - let extra_space_decode = PublicKey::try_from(&extra_space[..]); - assert!(extra_space_decode.is_ok()); - - assert_eq!(&serialized_public[..], &just_right?.serialize()[..]); - assert_eq!(&serialized_public[..], &extra_space_decode?.serialize()[..]); - Ok(()) - } -} diff --git a/net/gurk-rs/files/vendor/libsignal-protocol/src/curve/curve25519.rs b/net/gurk-rs/files/vendor/libsignal-protocol/src/curve/curve25519.rs deleted file mode 100644 index 0978004..0000000 --- a/net/gurk-rs/files/vendor/libsignal-protocol/src/curve/curve25519.rs +++ /dev/null @@ -1,284 +0,0 @@ -// -// Copyright 2020-2021 Signal Messenger, LLC. -// SPDX-License-Identifier: AGPL-3.0-only -// - -use curve25519_dalek::constants::ED25519_BASEPOINT_TABLE; -use curve25519_dalek::edwards::EdwardsPoint; -use curve25519_dalek::montgomery::MontgomeryPoint; -use curve25519_dalek::scalar::Scalar; -use rand::{CryptoRng, Rng}; -use sha2::{Digest, Sha512}; -use subtle::ConstantTimeEq; -use x25519_dalek::{PublicKey, StaticSecret}; - -const AGREEMENT_LENGTH: usize = 32; -pub const PRIVATE_KEY_LENGTH: usize = 32; -pub const PUBLIC_KEY_LENGTH: usize = 32; -pub const SIGNATURE_LENGTH: usize = 64; - -#[derive(Clone)] -pub struct PrivateKey { - secret: StaticSecret, -} - -impl PrivateKey { - pub fn new(csprng: &mut R) -> Self - where - R: CryptoRng + Rng, - { - let secret = StaticSecret::new(csprng); - PrivateKey { secret } - } - - pub fn calculate_agreement( - &self, - their_public_key: &[u8; PUBLIC_KEY_LENGTH], - ) -> [u8; AGREEMENT_LENGTH] { - *self - .secret - .diffie_hellman(&PublicKey::from(*their_public_key)) - .as_bytes() - } - - /// Calculates an XEdDSA signature using the X25519 private key directly. - /// - /// Refer to https://signal.org/docs/specifications/xeddsa/#curve25519 for more details. - /// - /// Note that this implementation varies slightly from that paper in that the sign bit is not - /// fixed to 0, but rather passed back in the most significant bit of the signature which would - /// otherwise always be 0. This is for compatibility with the implementation found in - /// libsignal-protocol-java. - pub fn calculate_signature(&self, csprng: &mut R, message: &[u8]) -> [u8; SIGNATURE_LENGTH] - where - R: CryptoRng + Rng, - { - let mut random_bytes = [0u8; 64]; - csprng.fill_bytes(&mut random_bytes); - - let key_data = self.secret.to_bytes(); - let a = Scalar::from_bits(key_data); - let ed_public_key_point = &a * &ED25519_BASEPOINT_TABLE; - let ed_public_key = ed_public_key_point.compress(); - let sign_bit = ed_public_key.as_bytes()[31] & 0b1000_0000_u8; - - let mut hash1 = Sha512::new(); - let hash_prefix = [ - 0xFEu8, 0xFFu8, 0xFFu8, 0xFFu8, 0xFFu8, 0xFFu8, 0xFFu8, 0xFFu8, 0xFFu8, 0xFFu8, 0xFFu8, - 0xFFu8, 0xFFu8, 0xFFu8, 0xFFu8, 0xFFu8, 0xFFu8, 0xFFu8, 0xFFu8, 0xFFu8, 0xFFu8, 0xFFu8, - 0xFFu8, 0xFFu8, 0xFFu8, 0xFFu8, 0xFFu8, 0xFFu8, 0xFFu8, 0xFFu8, 0xFFu8, 0xFFu8, - ]; - hash1.update(&hash_prefix); - hash1.update(&key_data); - hash1.update(&message); - hash1.update(&random_bytes[..]); - - let r = Scalar::from_hash(hash1); - let cap_r = (&r * &ED25519_BASEPOINT_TABLE).compress(); - - let mut hash = Sha512::new(); - hash.update(cap_r.as_bytes()); - hash.update(ed_public_key.as_bytes()); - hash.update(&message); - - let h = Scalar::from_hash(hash); - let s = (h * a) + r; - - let mut result = [0u8; SIGNATURE_LENGTH]; - result[..32].copy_from_slice(cap_r.as_bytes()); - result[32..].copy_from_slice(s.as_bytes()); - result[SIGNATURE_LENGTH - 1] &= 0b0111_1111_u8; - result[SIGNATURE_LENGTH - 1] |= sign_bit; - result - } - - pub fn verify_signature( - their_public_key: &[u8; PUBLIC_KEY_LENGTH], - message: &[u8], - signature: &[u8; SIGNATURE_LENGTH], - ) -> bool { - let mont_point = MontgomeryPoint(*their_public_key); - let ed_pub_key_point = - match mont_point.to_edwards((signature[SIGNATURE_LENGTH - 1] & 0b1000_0000_u8) >> 7) { - Some(x) => x, - None => return false, - }; - let cap_a = ed_pub_key_point.compress(); - let mut cap_r = [0u8; 32]; - cap_r.copy_from_slice(&signature[..32]); - let mut s = [0u8; 32]; - s.copy_from_slice(&signature[32..]); - s[31] &= 0b0111_1111_u8; - if (s[31] & 0b1110_0000_u8) != 0 { - return false; - } - let minus_cap_a = -ed_pub_key_point; - - let mut hash = Sha512::new(); - hash.update(&cap_r); - hash.update(cap_a.as_bytes()); - hash.update(&message); - let h = Scalar::from_hash(hash); - - let cap_r_check_point = EdwardsPoint::vartime_double_scalar_mul_basepoint( - &h, - &minus_cap_a, - &Scalar::from_bits(s), - ); - let cap_r_check = cap_r_check_point.compress(); - - bool::from(cap_r_check.as_bytes().ct_eq(&cap_r)) - } - - pub fn derive_public_key_bytes(&self) -> [u8; PUBLIC_KEY_LENGTH] { - *PublicKey::from(&self.secret).as_bytes() - } - - pub fn private_key_bytes(&self) -> [u8; PRIVATE_KEY_LENGTH] { - self.secret.to_bytes() - } -} - -impl From<[u8; PRIVATE_KEY_LENGTH]> for PrivateKey { - fn from(private_key: [u8; 32]) -> Self { - let secret = StaticSecret::from(private_key); - PrivateKey { secret } - } -} - -#[cfg(test)] -mod tests { - use rand::rngs::OsRng; - use rand::RngCore; - - use super::*; - - #[test] - fn test_agreement() { - let alice_public: [u8; 32] = [ - 0x1b, 0xb7, 0x59, 0x66, 0xf2, 0xe9, 0x3a, 0x36, 0x91, 0xdf, 0xff, 0x94, 0x2b, 0xb2, - 0xa4, 0x66, 0xa1, 0xc0, 0x8b, 0x8d, 0x78, 0xca, 0x3f, 0x4d, 0x6d, 0xf8, 0xb8, 0xbf, - 0xa2, 0xe4, 0xee, 0x28, - ]; - let alice_private: [u8; 32] = [ - 0xc8, 0x06, 0x43, 0x9d, 0xc9, 0xd2, 0xc4, 0x76, 0xff, 0xed, 0x8f, 0x25, 0x80, 0xc0, - 0x88, 0x8d, 0x58, 0xab, 0x40, 0x6b, 0xf7, 0xae, 0x36, 0x98, 0x87, 0x90, 0x21, 0xb9, - 0x6b, 0xb4, 0xbf, 0x59, - ]; - let bob_public: [u8; 32] = [ - 0x65, 0x36, 0x14, 0x99, 0x3d, 0x2b, 0x15, 0xee, 0x9e, 0x5f, 0xd3, 0xd8, 0x6c, 0xe7, - 0x19, 0xef, 0x4e, 0xc1, 0xda, 0xae, 0x18, 0x86, 0xa8, 0x7b, 0x3f, 0x5f, 0xa9, 0x56, - 0x5a, 0x27, 0xa2, 0x2f, - ]; - let bob_private: [u8; 32] = [ - 0xb0, 0x3b, 0x34, 0xc3, 0x3a, 0x1c, 0x44, 0xf2, 0x25, 0xb6, 0x62, 0xd2, 0xbf, 0x48, - 0x59, 0xb8, 0x13, 0x54, 0x11, 0xfa, 0x7b, 0x03, 0x86, 0xd4, 0x5f, 0xb7, 0x5d, 0xc5, - 0xb9, 0x1b, 0x44, 0x66, - ]; - let shared: [u8; 32] = [ - 0x32, 0x5f, 0x23, 0x93, 0x28, 0x94, 0x1c, 0xed, 0x6e, 0x67, 0x3b, 0x86, 0xba, 0x41, - 0x01, 0x74, 0x48, 0xe9, 0x9b, 0x64, 0x9a, 0x9c, 0x38, 0x06, 0xc1, 0xdd, 0x7c, 0xa4, - 0xc4, 0x77, 0xe6, 0x29, - ]; - - let alice_key = PrivateKey::from(alice_private); - let bob_key = PrivateKey::from(bob_private); - - assert_eq!(alice_public, alice_key.derive_public_key_bytes()); - assert_eq!(bob_public, bob_key.derive_public_key_bytes()); - - let alice_computed_secret = alice_key.calculate_agreement(&bob_public); - let bob_computed_secret = bob_key.calculate_agreement(&alice_public); - - assert_eq!(shared, alice_computed_secret); - assert_eq!(shared, bob_computed_secret); - } - - #[test] - fn test_random_agreements() { - let mut csprng = OsRng; - for _ in 0..50 { - let alice_key = PrivateKey::new(&mut csprng); - let bob_key = PrivateKey::new(&mut csprng); - - let alice_computed_secret = - alice_key.calculate_agreement(&bob_key.derive_public_key_bytes()); - let bob_computed_secret = - bob_key.calculate_agreement(&alice_key.derive_public_key_bytes()); - - assert_eq!(alice_computed_secret, bob_computed_secret); - } - } - - #[test] - fn test_signature() { - let alice_identity_private: [u8; PRIVATE_KEY_LENGTH] = [ - 0xc0, 0x97, 0x24, 0x84, 0x12, 0xe5, 0x8b, 0xf0, 0x5d, 0xf4, 0x87, 0x96, 0x82, 0x05, - 0x13, 0x27, 0x94, 0x17, 0x8e, 0x36, 0x76, 0x37, 0xf5, 0x81, 0x8f, 0x81, 0xe0, 0xe6, - 0xce, 0x73, 0xe8, 0x65, - ]; - let alice_identity_public: [u8; PUBLIC_KEY_LENGTH] = [ - 0xab, 0x7e, 0x71, 0x7d, 0x4a, 0x16, 0x3b, 0x7d, 0x9a, 0x1d, 0x80, 0x71, 0xdf, 0xe9, - 0xdc, 0xf8, 0xcd, 0xcd, 0x1c, 0xea, 0x33, 0x39, 0xb6, 0x35, 0x6b, 0xe8, 0x4d, 0x88, - 0x7e, 0x32, 0x2c, 0x64, - ]; - let alice_ephemeral_public: [u8; PUBLIC_KEY_LENGTH + 1] = [ - 0x05, 0xed, 0xce, 0x9d, 0x9c, 0x41, 0x5c, 0xa7, 0x8c, 0xb7, 0x25, 0x2e, 0x72, 0xc2, - 0xc4, 0xa5, 0x54, 0xd3, 0xeb, 0x29, 0x48, 0x5a, 0x0e, 0x1d, 0x50, 0x31, 0x18, 0xd1, - 0xa8, 0x2d, 0x99, 0xfb, 0x4a, - ]; - let alice_signature: [u8; SIGNATURE_LENGTH] = [ - 0x5d, 0xe8, 0x8c, 0xa9, 0xa8, 0x9b, 0x4a, 0x11, 0x5d, 0xa7, 0x91, 0x09, 0xc6, 0x7c, - 0x9c, 0x74, 0x64, 0xa3, 0xe4, 0x18, 0x02, 0x74, 0xf1, 0xcb, 0x8c, 0x63, 0xc2, 0x98, - 0x4e, 0x28, 0x6d, 0xfb, 0xed, 0xe8, 0x2d, 0xeb, 0x9d, 0xcd, 0x9f, 0xae, 0x0b, 0xfb, - 0xb8, 0x21, 0x56, 0x9b, 0x3d, 0x90, 0x01, 0xbd, 0x81, 0x30, 0xcd, 0x11, 0xd4, 0x86, - 0xce, 0xf0, 0x47, 0xbd, 0x60, 0xb8, 0x6e, 0x88, - ]; - - let alice_identity_key = PrivateKey::from(alice_identity_private); - - assert_eq!( - alice_identity_public, - alice_identity_key.derive_public_key_bytes() - ); - - assert!( - PrivateKey::verify_signature( - &alice_identity_public, - &alice_ephemeral_public, - &alice_signature - ), - "signature check failed" - ); - - for i in 0..alice_signature.len() { - let mut alice_signature_copy: [u8; SIGNATURE_LENGTH] = [0; SIGNATURE_LENGTH]; - alice_signature_copy.copy_from_slice(&alice_signature); - alice_signature_copy[i] ^= 0x01u8; - - assert!( - !PrivateKey::verify_signature( - &alice_identity_public, - &alice_ephemeral_public, - &alice_signature_copy - ), - "signature check passed when it should not have" - ); - } - } - - #[test] - fn test_random_signatures() { - let mut csprng = OsRng; - for _ in 0..50 { - let mut message = [0u8; 64]; - csprng.fill_bytes(&mut message); - let key = PrivateKey::new(&mut csprng); - let signature = key.calculate_signature(&mut csprng, &message); - assert!( - PrivateKey::verify_signature(&key.derive_public_key_bytes(), &message, &signature), - "signature check failed" - ); - } - } -} diff --git a/net/gurk-rs/files/vendor/libsignal-protocol/src/error.rs b/net/gurk-rs/files/vendor/libsignal-protocol/src/error.rs deleted file mode 100644 index ae42326..0000000 --- a/net/gurk-rs/files/vendor/libsignal-protocol/src/error.rs +++ /dev/null @@ -1,108 +0,0 @@ -// -// Copyright 2020-2021 Signal Messenger, LLC. -// SPDX-License-Identifier: AGPL-3.0-only -// - -use crate::curve::KeyType; - -use displaydoc::Display; -use thiserror::Error; - -use std::panic::UnwindSafe; - -pub type Result = std::result::Result; - -#[derive(Debug, Display, Error)] -pub enum SignalProtocolError { - /// invalid argument: {0} - InvalidArgument(String), - /// invalid state for call to {0} to succeed: {1} - InvalidState(&'static str, String), - - // TODO: avoid duplicating error information in the Display impl and the #[from] or #[source] - // attribute if/when we switch to using an error reporting mechanism supporting stack traces: - // see https://github.com/yaahc/blog.rust-lang.org/blob/master/posts/inside-rust/2021-05-15-What-the-error-handling-project-group-is-working-towards.md#duplicate-information-issue - /// failed to decode protobuf: {0} - ProtobufDecodingError(#[from] prost::DecodeError), - /// failed to encode protobuf: {0} - ProtobufEncodingError(#[from] prost::EncodeError), - /// protobuf encoding was invalid - InvalidProtobufEncoding, - - /// ciphertext serialized bytes were too short <{0}> - CiphertextMessageTooShort(usize), - /// ciphertext version was too old <{0}> - LegacyCiphertextVersion(u8), - /// ciphertext version was unrecognized <{0}> - UnrecognizedCiphertextVersion(u8), - /// unrecognized message version <{0}> - UnrecognizedMessageVersion(u32), - - /// fingerprint identifiers do not match - FingerprintIdentifierMismatch, - /// fingerprint version number mismatch them {0} us {1} - FingerprintVersionMismatch(u32, u32), - /// fingerprint parsing error - FingerprintParsingError, - - /// no key type identifier - NoKeyTypeIdentifier, - /// bad key type <{0:#04x}> - BadKeyType(u8), - /// bad key length <{1}> for key with type <{0}> - BadKeyLength(KeyType, usize), - - /// invalid signature detected - SignatureValidationFailed, - - /// untrusted identity for address {0} - UntrustedIdentity(crate::ProtocolAddress), - - /// invalid prekey identifier - InvalidPreKeyId, - /// invalid signed prekey identifier - InvalidSignedPreKeyId, - - /// invalid root key length <{0}> - InvalidRootKeyLength(usize), - /// invalid chain key length <{0}> - InvalidChainKeyLength(usize), - - /// invalid MAC key length <{0}> - InvalidMacKeyLength(usize), - /// invalid cipher key length <{0}> or nonce length <{1}> - InvalidCipherCryptographicParameters(usize, usize), - /// invalid ciphertext message - InvalidCiphertext, - - /// no sender key state - NoSenderKeyState, - - /// session with '{0}' not found - SessionNotFound(String), - /// invalid session structure - InvalidSessionStructure, - /// session for {0} has invalid registration ID {1:X} - InvalidRegistrationId(crate::ProtocolAddress, u32), - - /// message with old counter {0} / {1} - DuplicatedMessage(u32, u32), - /// invalid message {0} - InvalidMessage(&'static str), - /// internal error {0} - InternalError(&'static str), - /// error while invoking an ffi callback: {0} - FfiBindingError(String), - /// error in method call '{0}': {1} - ApplicationCallbackError( - &'static str, - #[source] Box, - ), - - /// invalid sealed sender message {0} - InvalidSealedSenderMessage(String), - /// unknown sealed sender message version {0} - UnknownSealedSenderVersion(u8), - /// self send of a sealed sender message - SealedSenderSelfSend, -} diff --git a/net/gurk-rs/files/vendor/libsignal-protocol/src/fingerprint.rs b/net/gurk-rs/files/vendor/libsignal-protocol/src/fingerprint.rs deleted file mode 100644 index e65178d..0000000 --- a/net/gurk-rs/files/vendor/libsignal-protocol/src/fingerprint.rs +++ /dev/null @@ -1,545 +0,0 @@ -// -// Copyright 2020 Signal Messenger, LLC. -// SPDX-License-Identifier: AGPL-3.0-only -// - -use crate::proto; -use crate::{IdentityKey, Result, SignalProtocolError}; -use prost::Message; -use sha2::{digest::Digest, Sha512}; -use std::fmt; -use subtle::ConstantTimeEq; - -#[derive(Debug, Clone)] -pub struct DisplayableFingerprint { - local: String, - remote: String, -} - -impl fmt::Display for DisplayableFingerprint { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - if self.local < self.remote { - write!(f, "{}{}", self.local, self.remote) - } else { - write!(f, "{}{}", self.remote, self.local) - } - } -} - -fn get_encoded_string(fprint: &[u8]) -> Result { - if fprint.len() < 30 { - return Err(SignalProtocolError::InvalidArgument( - "DisplayableFingerprint created with short encoding".to_string(), - )); - } - - fn read5_mod_100k(fprint: &[u8]) -> u64 { - assert_eq!(fprint.len(), 5); - let x = fprint.iter().fold(0u64, |acc, &x| acc * 256 + (x as u64)); - x % 100000 - } - - // todo use iterators - let s = format!( - "{:05}{:05}{:05}{:05}{:05}{:05}", - read5_mod_100k(&fprint[0..5]), - read5_mod_100k(&fprint[5..10]), - read5_mod_100k(&fprint[10..15]), - read5_mod_100k(&fprint[15..20]), - read5_mod_100k(&fprint[20..25]), - read5_mod_100k(&fprint[25..30]) - ); - - Ok(s) -} - -impl DisplayableFingerprint { - pub fn new(local: &[u8], remote: &[u8]) -> Result { - Ok(Self { - local: get_encoded_string(local)?, - remote: get_encoded_string(remote)?, - }) - } -} - -#[derive(Debug, Clone)] -pub struct ScannableFingerprint { - version: u32, - local_fingerprint: Vec, - remote_fingerprint: Vec, -} - -impl ScannableFingerprint { - fn new(version: u32, local_fprint: &[u8], remote_fprint: &[u8]) -> Self { - Self { - version, - local_fingerprint: local_fprint[..32].to_vec(), - remote_fingerprint: remote_fprint[..32].to_vec(), - } - } - - pub fn deserialize(protobuf: &[u8]) -> Result { - let fingerprint = proto::fingerprint::CombinedFingerprints::decode(protobuf) - .map_err(|_| SignalProtocolError::FingerprintParsingError)?; - - Ok(Self { - version: fingerprint - .version - .ok_or(SignalProtocolError::FingerprintParsingError)?, - local_fingerprint: fingerprint - .local_fingerprint - .ok_or(SignalProtocolError::FingerprintParsingError)? - .content - .ok_or(SignalProtocolError::FingerprintParsingError)?, - remote_fingerprint: fingerprint - .remote_fingerprint - .ok_or(SignalProtocolError::FingerprintParsingError)? - .content - .ok_or(SignalProtocolError::FingerprintParsingError)?, - }) - } - - pub fn serialize(&self) -> Result> { - let combined_fingerprints = proto::fingerprint::CombinedFingerprints { - version: Some(self.version), - local_fingerprint: Some(proto::fingerprint::LogicalFingerprint { - content: Some(self.local_fingerprint.to_owned()), - }), - remote_fingerprint: Some(proto::fingerprint::LogicalFingerprint { - content: Some(self.remote_fingerprint.to_owned()), - }), - }; - - Ok(combined_fingerprints.encode_to_vec()) - } - - pub fn compare(&self, combined: &[u8]) -> Result { - let combined = proto::fingerprint::CombinedFingerprints::decode(combined) - .map_err(|_| SignalProtocolError::FingerprintParsingError)?; - - let their_version = combined.version.unwrap_or(0); - - if their_version != self.version { - return Err(SignalProtocolError::FingerprintVersionMismatch( - their_version, - self.version, - )); - } - - let same1 = combined - .local_fingerprint - .as_ref() - .ok_or(SignalProtocolError::FingerprintParsingError)? - .content - .as_ref() - .ok_or(SignalProtocolError::FingerprintParsingError)? - .ct_eq(&self.remote_fingerprint); - let same2 = combined - .remote_fingerprint - .as_ref() - .ok_or(SignalProtocolError::FingerprintParsingError)? - .content - .as_ref() - .ok_or(SignalProtocolError::FingerprintParsingError)? - .ct_eq(&self.local_fingerprint); - - Ok(same1.into() && same2.into()) - } -} - -#[derive(Debug, Clone)] -pub struct Fingerprint { - pub display: DisplayableFingerprint, - pub scannable: ScannableFingerprint, -} - -impl Fingerprint { - fn get_fingerprint( - iterations: u32, - local_id: &[u8], - local_key: &IdentityKey, - ) -> Result> { - if iterations <= 1 || iterations > 1000000 { - return Err(SignalProtocolError::InvalidArgument(format!( - "Invalid fingerprint iterations {}", - iterations - ))); - } - - let fingerprint_version = [0u8, 0u8]; // 0x0000 - let key_bytes = local_key.serialize(); - - let mut sha512 = Sha512::new(); - - // iteration=0 - sha512.update(&fingerprint_version); - sha512.update(&key_bytes); - sha512.update(local_id); - sha512.update(&key_bytes); - let mut buf = sha512.finalize(); - - for _i in 1..iterations { - let mut sha512 = Sha512::new(); - sha512.update(&buf); - sha512.update(&key_bytes); - buf = sha512.finalize(); - } - - Ok(buf.to_vec()) - } - - pub fn new( - version: u32, - iterations: u32, - local_id: &[u8], - local_key: &IdentityKey, - remote_id: &[u8], - remote_key: &IdentityKey, - ) -> Result { - let local_fingerprint = Fingerprint::get_fingerprint(iterations, local_id, local_key)?; - let remote_fingerprint = Fingerprint::get_fingerprint(iterations, remote_id, remote_key)?; - - Ok(Fingerprint { - display: DisplayableFingerprint::new(&local_fingerprint, &remote_fingerprint)?, - scannable: ScannableFingerprint::new(version, &local_fingerprint, &remote_fingerprint), - }) - } - - pub fn display_string(&self) -> Result { - Ok(format!("{}", self.display)) - } -} - -#[cfg(test)] -mod test { - use super::*; - - const ALICE_IDENTITY: &str = - "0506863bc66d02b40d27b8d49ca7c09e9239236f9d7d25d6fcca5ce13c7064d868"; - const BOB_IDENTITY: &str = "05f781b6fb32fed9ba1cf2de978d4d5da28dc34046ae814402b5c0dbd96fda907b"; - - const DISPLAYABLE_FINGERPRINT_V1: &str = - "300354477692869396892869876765458257569162576843440918079131"; - const ALICE_SCANNABLE_FINGERPRINT_V1 : &str = "080112220a201e301a0353dce3dbe7684cb8336e85136cdc0ee96219494ada305d62a7bd61df1a220a20d62cbf73a11592015b6b9f1682ac306fea3aaf3885b84d12bca631e9d4fb3a4d"; - const BOB_SCANNABLE_FINGERPRINT_V1 : &str = "080112220a20d62cbf73a11592015b6b9f1682ac306fea3aaf3885b84d12bca631e9d4fb3a4d1a220a201e301a0353dce3dbe7684cb8336e85136cdc0ee96219494ada305d62a7bd61df"; - - const ALICE_SCANNABLE_FINGERPRINT_V2 : &str = "080212220a201e301a0353dce3dbe7684cb8336e85136cdc0ee96219494ada305d62a7bd61df1a220a20d62cbf73a11592015b6b9f1682ac306fea3aaf3885b84d12bca631e9d4fb3a4d"; - const BOB_SCANNABLE_FINGERPRINT_V2 : & str = "080212220a20d62cbf73a11592015b6b9f1682ac306fea3aaf3885b84d12bca631e9d4fb3a4d1a220a201e301a0353dce3dbe7684cb8336e85136cdc0ee96219494ada305d62a7bd61df"; - - const ALICE_STABLE_ID: &str = "+14152222222"; - const BOB_STABLE_ID: &str = "+14153333333"; - - #[test] - fn fingerprint_encodings() -> Result<()> { - let l = vec![0x12; 32]; - let r = vec![0xBA; 32]; - - let fprint2 = ScannableFingerprint::new(2, &l, &r); - let proto2 = fprint2.serialize()?; - - let expected2_encoding = - "080212220a20".to_owned() + &"12".repeat(32) + "1a220a20" + &"ba".repeat(32); - assert_eq!(hex::encode(proto2), expected2_encoding); - - Ok(()) - } - - #[test] - fn fingerprint_test_v1() -> Result<()> { - // testVectorsVersion1 in Java - - let a_key = IdentityKey::decode(&hex::decode(ALICE_IDENTITY).expect("valid hex"))?; - let b_key = IdentityKey::decode(&hex::decode(BOB_IDENTITY).expect("valid hex"))?; - - let version = 1; - let iterations = 5200; - - let a_fprint = Fingerprint::new( - version, - iterations, - ALICE_STABLE_ID.as_bytes(), - &a_key, - BOB_STABLE_ID.as_bytes(), - &b_key, - )?; - - let b_fprint = Fingerprint::new( - version, - iterations, - BOB_STABLE_ID.as_bytes(), - &b_key, - ALICE_STABLE_ID.as_bytes(), - &a_key, - )?; - - assert_eq!( - hex::encode(a_fprint.scannable.serialize()?), - ALICE_SCANNABLE_FINGERPRINT_V1 - ); - assert_eq!( - hex::encode(b_fprint.scannable.serialize()?), - BOB_SCANNABLE_FINGERPRINT_V1 - ); - - assert_eq!(format!("{}", a_fprint.display), DISPLAYABLE_FINGERPRINT_V1); - assert_eq!(format!("{}", b_fprint.display), DISPLAYABLE_FINGERPRINT_V1); - - assert_eq!( - hex::encode(a_fprint.scannable.serialize()?), - ALICE_SCANNABLE_FINGERPRINT_V1 - ); - assert_eq!( - hex::encode(b_fprint.scannable.serialize()?), - BOB_SCANNABLE_FINGERPRINT_V1 - ); - - Ok(()) - } - - #[test] - fn fingerprint_test_v2() -> Result<()> { - // testVectorsVersion2 in Java - - let a_key = IdentityKey::decode(&hex::decode(ALICE_IDENTITY).expect("valid hex"))?; - let b_key = IdentityKey::decode(&hex::decode(BOB_IDENTITY).expect("valid hex"))?; - - let version = 2; - let iterations = 5200; - - let a_fprint = Fingerprint::new( - version, - iterations, - ALICE_STABLE_ID.as_bytes(), - &a_key, - BOB_STABLE_ID.as_bytes(), - &b_key, - )?; - - let b_fprint = Fingerprint::new( - version, - iterations, - BOB_STABLE_ID.as_bytes(), - &b_key, - ALICE_STABLE_ID.as_bytes(), - &a_key, - )?; - - assert_eq!( - hex::encode(a_fprint.scannable.serialize()?), - ALICE_SCANNABLE_FINGERPRINT_V2 - ); - assert_eq!( - hex::encode(b_fprint.scannable.serialize()?), - BOB_SCANNABLE_FINGERPRINT_V2 - ); - - // unchanged vs v1 - assert_eq!(format!("{}", a_fprint.display), DISPLAYABLE_FINGERPRINT_V1); - assert_eq!(format!("{}", b_fprint.display), DISPLAYABLE_FINGERPRINT_V1); - - assert_eq!( - hex::encode(a_fprint.scannable.serialize()?), - ALICE_SCANNABLE_FINGERPRINT_V2 - ); - assert_eq!( - hex::encode(b_fprint.scannable.serialize()?), - BOB_SCANNABLE_FINGERPRINT_V2 - ); - - Ok(()) - } - - #[test] - fn fingerprint_matching_identifiers() -> Result<()> { - // testMatchingFingerprints - - use crate::IdentityKeyPair; - use rand::rngs::OsRng; - - let a_key_pair = IdentityKeyPair::generate(&mut OsRng); - let b_key_pair = IdentityKeyPair::generate(&mut OsRng); - - let a_key = a_key_pair.identity_key(); - let b_key = b_key_pair.identity_key(); - - let version = 1; - let iterations = 1024; - - let a_fprint = Fingerprint::new( - version, - iterations, - ALICE_STABLE_ID.as_bytes(), - a_key, - BOB_STABLE_ID.as_bytes(), - b_key, - )?; - - let b_fprint = Fingerprint::new( - version, - iterations, - BOB_STABLE_ID.as_bytes(), - b_key, - ALICE_STABLE_ID.as_bytes(), - a_key, - )?; - - assert_eq!( - format!("{}", a_fprint.display), - format!("{}", b_fprint.display) - ); - assert_eq!(format!("{}", a_fprint.display).len(), 60); - - assert!(a_fprint - .scannable - .compare(&b_fprint.scannable.serialize()?)?); - assert!(b_fprint - .scannable - .compare(&a_fprint.scannable.serialize()?)?); - - // Java is missing this test - assert!(!a_fprint - .scannable - .compare(&a_fprint.scannable.serialize()?)?); - assert!(!b_fprint - .scannable - .compare(&b_fprint.scannable.serialize()?)?); - - Ok(()) - } - - #[test] - fn fingerprint_mismatching_fingerprints() -> Result<()> { - use crate::IdentityKeyPair; - use rand::rngs::OsRng; - - let a_key_pair = IdentityKeyPair::generate(&mut OsRng); - let b_key_pair = IdentityKeyPair::generate(&mut OsRng); - let m_key_pair = IdentityKeyPair::generate(&mut OsRng); // mitm - - let a_key = a_key_pair.identity_key(); - let b_key = b_key_pair.identity_key(); - let m_key = m_key_pair.identity_key(); - - let version = 1; - let iterations = 1024; - - let a_fprint = Fingerprint::new( - version, - iterations, - ALICE_STABLE_ID.as_bytes(), - a_key, - BOB_STABLE_ID.as_bytes(), - m_key, - )?; - - let b_fprint = Fingerprint::new( - version, - iterations, - BOB_STABLE_ID.as_bytes(), - b_key, - ALICE_STABLE_ID.as_bytes(), - a_key, - )?; - - assert_ne!( - format!("{}", a_fprint.display), - format!("{}", b_fprint.display) - ); - - assert!(!a_fprint - .scannable - .compare(&b_fprint.scannable.serialize()?)?); - assert!(!b_fprint - .scannable - .compare(&a_fprint.scannable.serialize()?)?); - - Ok(()) - } - - #[test] - fn fingerprint_mismatching_identifiers() -> Result<()> { - use crate::IdentityKeyPair; - use rand::rngs::OsRng; - - let a_key_pair = IdentityKeyPair::generate(&mut OsRng); - let b_key_pair = IdentityKeyPair::generate(&mut OsRng); - - let a_key = a_key_pair.identity_key(); - let b_key = b_key_pair.identity_key(); - - let version = 1; - let iterations = 1024; - - let a_fprint = Fingerprint::new( - version, - iterations, - "+141512222222".as_bytes(), - a_key, - BOB_STABLE_ID.as_bytes(), - b_key, - )?; - - let b_fprint = Fingerprint::new( - version, - iterations, - BOB_STABLE_ID.as_bytes(), - b_key, - ALICE_STABLE_ID.as_bytes(), - a_key, - )?; - - assert_ne!( - format!("{}", a_fprint.display), - format!("{}", b_fprint.display) - ); - - assert!(!a_fprint - .scannable - .compare(&b_fprint.scannable.serialize()?)?); - assert!(!b_fprint - .scannable - .compare(&a_fprint.scannable.serialize()?)?); - - Ok(()) - } - - #[test] - fn fingerprint_mismatching_versions() -> Result<()> { - let a_key = IdentityKey::decode(&hex::decode(ALICE_IDENTITY).expect("valid hex"))?; - let b_key = IdentityKey::decode(&hex::decode(BOB_IDENTITY).expect("valid hex"))?; - - let iterations = 5200; - - let a_fprint_v1 = Fingerprint::new( - 1, - iterations, - ALICE_STABLE_ID.as_bytes(), - &a_key, - BOB_STABLE_ID.as_bytes(), - &b_key, - )?; - - let a_fprint_v2 = Fingerprint::new( - 2, - iterations, - BOB_STABLE_ID.as_bytes(), - &b_key, - ALICE_STABLE_ID.as_bytes(), - &a_key, - )?; - - // Display fingerprint doesn't change - assert_eq!( - format!("{}", a_fprint_v1.display), - format!("{}", a_fprint_v2.display) - ); - - // Scannable fingerprint does - assert_ne!( - hex::encode(a_fprint_v1.scannable.serialize()?), - hex::encode(a_fprint_v2.scannable.serialize()?) - ); - - Ok(()) - } -} diff --git a/net/gurk-rs/files/vendor/libsignal-protocol/src/group_cipher.rs b/net/gurk-rs/files/vendor/libsignal-protocol/src/group_cipher.rs deleted file mode 100644 index 4c1383d..0000000 --- a/net/gurk-rs/files/vendor/libsignal-protocol/src/group_cipher.rs +++ /dev/null @@ -1,237 +0,0 @@ -// -// Copyright 2020 Signal Messenger, LLC. -// SPDX-License-Identifier: AGPL-3.0-only -// - -use crate::consts; -use crate::crypto; - -use crate::{ - Context, KeyPair, ProtocolAddress, Result, SenderKeyDistributionMessage, SenderKeyMessage, - SenderKeyRecord, SenderKeyStore, SignalProtocolError, -}; - -use crate::protocol::SENDERKEY_MESSAGE_CURRENT_VERSION; -use crate::sender_keys::{SenderKeyState, SenderMessageKey}; - -use rand::{CryptoRng, Rng}; -use std::convert::TryFrom; -use uuid::Uuid; - -pub async fn group_encrypt( - sender_key_store: &mut dyn SenderKeyStore, - sender: &ProtocolAddress, - distribution_id: Uuid, - plaintext: &[u8], - csprng: &mut R, - ctx: Context, -) -> Result { - let mut record = sender_key_store - .load_sender_key(sender, distribution_id, ctx) - .await? - .ok_or(SignalProtocolError::NoSenderKeyState)?; - - let sender_key_state = record.sender_key_state()?; - - let sender_key = sender_key_state.sender_chain_key()?.sender_message_key()?; - - let ciphertext = - crypto::aes_256_cbc_encrypt(plaintext, &sender_key.cipher_key()?, &sender_key.iv()?)?; - - let signing_key = sender_key_state.signing_key_private()?; - - let skm = SenderKeyMessage::new( - sender_key_state.message_version()? as u8, - distribution_id, - sender_key_state.chain_id()?, - sender_key.iteration()?, - ciphertext.into_boxed_slice(), - csprng, - &signing_key, - )?; - - sender_key_state.set_sender_chain_key(sender_key_state.sender_chain_key()?.next()?)?; - - sender_key_store - .store_sender_key(sender, distribution_id, &record, ctx) - .await?; - - Ok(skm) -} - -fn get_sender_key( - state: &mut SenderKeyState, - iteration: u32, - distribution_id: Uuid, -) -> Result { - let sender_chain_key = state.sender_chain_key()?; - let current_iteration = sender_chain_key.iteration()?; - - if current_iteration > iteration { - if let Some(smk) = state.remove_sender_message_key(iteration)? { - return Ok(smk); - } else { - log::info!( - "SenderKey distribution {} Duplicate message for iteration: {}", - distribution_id, - iteration - ); - return Err(SignalProtocolError::DuplicatedMessage( - current_iteration, - iteration, - )); - } - } - - let jump = (iteration - current_iteration) as usize; - if jump > consts::MAX_FORWARD_JUMPS { - log::error!( - "SenderKey distribution {} Exceeded future message limit: {}, current iteration: {})", - distribution_id, - consts::MAX_FORWARD_JUMPS, - current_iteration - ); - return Err(SignalProtocolError::InvalidMessage( - "message from too far into the future", - )); - } - - let mut sender_chain_key = sender_chain_key; - - while sender_chain_key.iteration()? < iteration { - state.add_sender_message_key(&sender_chain_key.sender_message_key()?)?; - sender_chain_key = sender_chain_key.next()?; - } - - state.set_sender_chain_key(sender_chain_key.next()?)?; - sender_chain_key.sender_message_key() -} - -pub async fn group_decrypt( - skm_bytes: &[u8], - sender_key_store: &mut dyn SenderKeyStore, - sender: &ProtocolAddress, - ctx: Context, -) -> Result> { - let skm = SenderKeyMessage::try_from(skm_bytes)?; - let mut record = sender_key_store - .load_sender_key(sender, skm.distribution_id(), ctx) - .await? - .ok_or(SignalProtocolError::NoSenderKeyState)?; - - let mut sender_key_state = - record.sender_key_state_for_chain_id(skm.chain_id(), skm.distribution_id())?; - - let message_version = skm.message_version() as u32; - if message_version != sender_key_state.message_version()? { - return Err(SignalProtocolError::UnrecognizedMessageVersion( - message_version, - )); - } - - let signing_key = sender_key_state.signing_key_public()?; - if !skm.verify_signature(&signing_key)? { - return Err(SignalProtocolError::SignatureValidationFailed); - } - - let sender_key = get_sender_key( - &mut sender_key_state, - skm.iteration(), - skm.distribution_id(), - )?; - - let plaintext = crypto::aes_256_cbc_decrypt( - skm.ciphertext(), - &sender_key.cipher_key()?, - &sender_key.iv()?, - )?; - - sender_key_store - .store_sender_key(sender, skm.distribution_id(), &record, ctx) - .await?; - - Ok(plaintext) -} - -pub async fn process_sender_key_distribution_message( - sender: &ProtocolAddress, - skdm: &SenderKeyDistributionMessage, - sender_key_store: &mut dyn SenderKeyStore, - ctx: Context, -) -> Result<()> { - let distribution_id = skdm.distribution_id()?; - log::info!( - "{} Processing SenderKey distribution {} with chain ID {}", - sender, - distribution_id, - skdm.chain_id()? - ); - - let mut sender_key_record = sender_key_store - .load_sender_key(sender, distribution_id, ctx) - .await? - .unwrap_or_else(SenderKeyRecord::new_empty); - - sender_key_record.add_sender_key_state( - skdm.message_version(), - skdm.chain_id()?, - skdm.iteration()?, - skdm.chain_key()?, - *skdm.signing_key()?, - None, - )?; - sender_key_store - .store_sender_key(sender, distribution_id, &sender_key_record, ctx) - .await?; - Ok(()) -} - -pub async fn create_sender_key_distribution_message( - sender: &ProtocolAddress, - distribution_id: Uuid, - sender_key_store: &mut dyn SenderKeyStore, - csprng: &mut R, - ctx: Context, -) -> Result { - let mut sender_key_record = sender_key_store - .load_sender_key(sender, distribution_id, ctx) - .await? - .unwrap_or_else(SenderKeyRecord::new_empty); - - if sender_key_record.is_empty()? { - // libsignal-protocol-java uses 31-bit integers for sender key chain IDs - let chain_id = (csprng.gen::()) >> 1; - log::info!( - "Creating SenderKey for distribution {} with chain ID {}", - distribution_id, - chain_id - ); - - let iteration = 0; - let sender_key: [u8; 32] = csprng.gen(); - let signing_key = KeyPair::generate(csprng); - sender_key_record.set_sender_key_state( - SENDERKEY_MESSAGE_CURRENT_VERSION, - chain_id, - iteration, - &sender_key, - signing_key.public_key, - Some(signing_key.private_key), - )?; - sender_key_store - .store_sender_key(sender, distribution_id, &sender_key_record, ctx) - .await?; - } - - let state = sender_key_record.sender_key_state()?; - let sender_chain_key = state.sender_chain_key()?; - - SenderKeyDistributionMessage::new( - state.message_version()? as u8, - distribution_id, - state.chain_id()?, - sender_chain_key.iteration()?, - sender_chain_key.seed()?, - state.signing_key_public()?, - ) -} diff --git a/net/gurk-rs/files/vendor/libsignal-protocol/src/identity_key.rs b/net/gurk-rs/files/vendor/libsignal-protocol/src/identity_key.rs deleted file mode 100644 index 0a9b00b..0000000 --- a/net/gurk-rs/files/vendor/libsignal-protocol/src/identity_key.rs +++ /dev/null @@ -1,179 +0,0 @@ -// -// Copyright 2020 Signal Messenger, LLC. -// SPDX-License-Identifier: AGPL-3.0-only -// - -use crate::proto; -use crate::{KeyPair, PrivateKey, PublicKey, Result, SignalProtocolError}; - -use rand::{CryptoRng, Rng}; -use std::convert::TryFrom; - -use prost::Message; - -#[derive(Debug, PartialOrd, Ord, PartialEq, Eq, Clone, Copy)] -pub struct IdentityKey { - public_key: PublicKey, -} - -impl IdentityKey { - pub fn new(public_key: PublicKey) -> Self { - Self { public_key } - } - - #[inline] - pub fn public_key(&self) -> &PublicKey { - &self.public_key - } - - #[inline] - pub fn serialize(&self) -> Box<[u8]> { - self.public_key.serialize() - } - - pub fn decode(value: &[u8]) -> Result { - let pk = PublicKey::try_from(value)?; - Ok(Self { public_key: pk }) - } -} - -impl TryFrom<&[u8]> for IdentityKey { - type Error = SignalProtocolError; - - fn try_from(value: &[u8]) -> Result { - IdentityKey::decode(value) - } -} - -impl From for IdentityKey { - fn from(value: PublicKey) -> Self { - Self { public_key: value } - } -} - -impl From for PublicKey { - fn from(value: IdentityKey) -> Self { - value.public_key - } -} - -#[derive(Copy, Clone)] -pub struct IdentityKeyPair { - identity_key: IdentityKey, - private_key: PrivateKey, -} - -impl IdentityKeyPair { - pub fn new(identity_key: IdentityKey, private_key: PrivateKey) -> Self { - Self { - identity_key, - private_key, - } - } - - pub fn generate(csprng: &mut R) -> Self { - let keypair = KeyPair::generate(csprng); - - Self { - identity_key: keypair.public_key.into(), - private_key: keypair.private_key, - } - } - - #[inline] - pub fn identity_key(&self) -> &IdentityKey { - &self.identity_key - } - - #[inline] - pub fn public_key(&self) -> &PublicKey { - self.identity_key.public_key() - } - - #[inline] - pub fn private_key(&self) -> &PrivateKey { - &self.private_key - } - - pub fn serialize(&self) -> Box<[u8]> { - let structure = proto::storage::IdentityKeyPairStructure { - public_key: self.identity_key.serialize().to_vec(), - private_key: self.private_key.serialize().to_vec(), - }; - - let result = structure.encode_to_vec(); - result.into_boxed_slice() - } -} - -impl TryFrom<&[u8]> for IdentityKeyPair { - type Error = SignalProtocolError; - - fn try_from(value: &[u8]) -> Result { - let structure = proto::storage::IdentityKeyPairStructure::decode(value)?; - Ok(Self { - identity_key: IdentityKey::try_from(&structure.public_key[..])?, - private_key: PrivateKey::deserialize(&structure.private_key)?, - }) - } -} - -impl TryFrom for IdentityKeyPair { - type Error = SignalProtocolError; - - fn try_from(private_key: PrivateKey) -> Result { - let identity_key = IdentityKey::new(private_key.public_key()?); - Ok(Self::new(identity_key, private_key)) - } -} - -impl From for IdentityKeyPair { - fn from(value: KeyPair) -> Self { - Self { - identity_key: value.public_key.into(), - private_key: value.private_key, - } - } -} - -impl From for KeyPair { - fn from(value: IdentityKeyPair) -> Self { - Self::new(value.identity_key.into(), value.private_key) - } -} - -#[cfg(test)] -mod tests { - use super::*; - - use rand::rngs::OsRng; - - #[test] - fn test_identity_key_from() { - let key_pair = KeyPair::generate(&mut OsRng); - let key_pair_public_serialized = key_pair.public_key.serialize(); - let identity_key = IdentityKey::from(key_pair.public_key); - assert_eq!(key_pair_public_serialized, identity_key.serialize()); - } - - #[test] - fn test_serialize_identity_key_pair() -> Result<()> { - let identity_key_pair = IdentityKeyPair::generate(&mut OsRng); - let serialized = identity_key_pair.serialize(); - let deserialized_identity_key_pair = IdentityKeyPair::try_from(&serialized[..])?; - assert_eq!( - identity_key_pair.identity_key(), - deserialized_identity_key_pair.identity_key() - ); - assert_eq!( - identity_key_pair.private_key().key_type(), - deserialized_identity_key_pair.private_key().key_type() - ); - assert_eq!( - identity_key_pair.private_key().serialize(), - deserialized_identity_key_pair.private_key().serialize() - ); - - Ok(()) - } -} diff --git a/net/gurk-rs/files/vendor/libsignal-protocol/src/lib.rs b/net/gurk-rs/files/vendor/libsignal-protocol/src/lib.rs deleted file mode 100644 index 3b7d119..0000000 --- a/net/gurk-rs/files/vendor/libsignal-protocol/src/lib.rs +++ /dev/null @@ -1,82 +0,0 @@ -// -// Copyright 2020-2021 Signal Messenger, LLC. -// SPDX-License-Identifier: AGPL-3.0-only -// - -//! Rust implementation of the **[Signal Protocol]** for asynchronous -//! forward-secret public-key cryptography. -//! -//! In particular, this library implements operations conforming to the following specifications: -//! - the **[X3DH]** key agreement protocol, -//! - the **[Double Ratchet]** *(Axolotl)* messaging protocol, -//! -//! [Signal Protocol]: https://signal.org/ -//! [X3DH]: https://signal.org/docs/specifications/x3dh/ -//! [Double Ratchet]: https://signal.org/docs/specifications/doubleratchet/ - -#![warn(clippy::unwrap_used)] -#![deny(unsafe_code)] - -// TODO(https://github.com/signalapp/libsignal-client/issues/285): it should be an aspiration to -// eventually warn and then error for public members without docstrings. Also see -// https://doc.rust-lang.org/rustdoc/what-to-include.html for background. -// #![warn(missing_docs)] - -mod address; -mod consts; -mod crypto; -mod curve; -pub mod error; -mod fingerprint; -mod group_cipher; -mod identity_key; -mod proto; -mod protocol; -mod ratchet; -mod sealed_sender; -mod sender_keys; -mod session; -mod session_cipher; -mod state; -mod storage; -mod utils; - -use error::Result; - -pub use { - address::{DeviceId, ProtocolAddress}, - curve::{KeyPair, PrivateKey, PublicKey}, - error::SignalProtocolError, - fingerprint::{DisplayableFingerprint, Fingerprint, ScannableFingerprint}, - group_cipher::{ - create_sender_key_distribution_message, group_decrypt, group_encrypt, - process_sender_key_distribution_message, - }, - identity_key::{IdentityKey, IdentityKeyPair}, - protocol::{ - extract_decryption_error_message_from_serialized_content, CiphertextMessage, - CiphertextMessageType, DecryptionErrorMessage, PlaintextContent, PreKeySignalMessage, - SenderKeyDistributionMessage, SenderKeyMessage, SignalMessage, - }, - ratchet::{ - initialize_alice_session_record, initialize_bob_session_record, - AliceSignalProtocolParameters, BobSignalProtocolParameters, - }, - sealed_sender::{ - sealed_sender_decrypt, sealed_sender_decrypt_to_usmc, sealed_sender_encrypt, - sealed_sender_encrypt_from_usmc, sealed_sender_multi_recipient_encrypt, - sealed_sender_multi_recipient_fan_out, ContentHint, SealedSenderDecryptionResult, - SenderCertificate, ServerCertificate, UnidentifiedSenderMessageContent, - }, - sender_keys::SenderKeyRecord, - session::{process_prekey, process_prekey_bundle}, - session_cipher::{ - message_decrypt, message_decrypt_prekey, message_decrypt_signal, message_encrypt, - }, - state::{PreKeyBundle, PreKeyRecord, SessionRecord, SignedPreKeyRecord}, - storage::{ - Context, Direction, IdentityKeyStore, InMemIdentityKeyStore, InMemPreKeyStore, - InMemSenderKeyStore, InMemSessionStore, InMemSignalProtocolStore, InMemSignedPreKeyStore, - PreKeyStore, ProtocolStore, SenderKeyStore, SessionStore, SignedPreKeyStore, - }, -}; diff --git a/net/gurk-rs/files/vendor/libsignal-protocol/src/proto.rs b/net/gurk-rs/files/vendor/libsignal-protocol/src/proto.rs deleted file mode 100644 index 4576ef3..0000000 --- a/net/gurk-rs/files/vendor/libsignal-protocol/src/proto.rs +++ /dev/null @@ -1,10 +0,0 @@ -// -// Copyright 2020-2021 Signal Messenger, LLC. -// SPDX-License-Identifier: AGPL-3.0-only -// - -pub mod fingerprint; -pub mod sealed_sender; -pub mod service; -pub mod storage; -pub mod wire; diff --git a/net/gurk-rs/files/vendor/libsignal-protocol/src/proto/fingerprint.proto b/net/gurk-rs/files/vendor/libsignal-protocol/src/proto/fingerprint.proto deleted file mode 100644 index f876ce6..0000000 --- a/net/gurk-rs/files/vendor/libsignal-protocol/src/proto/fingerprint.proto +++ /dev/null @@ -1,19 +0,0 @@ -syntax = "proto2"; - -// -// Copyright 2020 Signal Messenger, LLC. -// SPDX-License-Identifier: AGPL-3.0-only -// - -package signal.proto.fingerprint; - -message LogicalFingerprint { - optional bytes content = 1; - // bytes identifier = 2; -} - -message CombinedFingerprints { - optional uint32 version = 1; - optional LogicalFingerprint local_fingerprint = 2; - optional LogicalFingerprint remote_fingerprint = 3; -} diff --git a/net/gurk-rs/files/vendor/libsignal-protocol/src/proto/fingerprint.rs b/net/gurk-rs/files/vendor/libsignal-protocol/src/proto/fingerprint.rs deleted file mode 100644 index c797e3a..0000000 --- a/net/gurk-rs/files/vendor/libsignal-protocol/src/proto/fingerprint.rs +++ /dev/null @@ -1,6 +0,0 @@ -// -// Copyright 2020 Signal Messenger, LLC. -// SPDX-License-Identifier: AGPL-3.0-only -// - -include!(concat!(env!("OUT_DIR"), "/signal.proto.fingerprint.rs")); diff --git a/net/gurk-rs/files/vendor/libsignal-protocol/src/proto/sealed_sender.proto b/net/gurk-rs/files/vendor/libsignal-protocol/src/proto/sealed_sender.proto deleted file mode 100644 index a178e47..0000000 --- a/net/gurk-rs/files/vendor/libsignal-protocol/src/proto/sealed_sender.proto +++ /dev/null @@ -1,62 +0,0 @@ -syntax = "proto2"; - -// -// Copyright 2020 Signal Messenger, LLC. -// SPDX-License-Identifier: AGPL-3.0-only -// - -package signal.proto.sealed_sender; - -message ServerCertificate { - message Certificate { - optional uint32 id = 1; - optional bytes key = 2; - } - - optional bytes certificate = 1; - optional bytes signature = 2; -} - -message SenderCertificate { - message Certificate { - optional string senderE164 = 1; - optional string senderUuid = 6; - optional uint32 senderDevice = 2; - optional fixed64 expires = 3; - optional bytes identityKey = 4; - optional ServerCertificate signer = 5; - } - - optional bytes certificate = 1; - optional bytes signature = 2; -} - -message UnidentifiedSenderMessage { - - message Message { - enum Type { - PREKEY_MESSAGE = 1; - MESSAGE = 2; - // Further cases should line up with Envelope.Type, even though old cases don't. - reserved 3 to 6; - SENDERKEY_MESSAGE = 7; - PLAINTEXT_CONTENT = 8; - } - - enum ContentHint { - reserved 0; // Default: sender will not resend; an error should be shown immediately - RESENDABLE = 1; // Sender will try to resend; delay any error UI if possible - IMPLICIT = 2; // Don't show any error UI at all; this is something sent implicitly like a typing message or a receipt - } - - optional Type type = 1; - optional SenderCertificate senderCertificate = 2; - optional bytes content = 3; - optional ContentHint contentHint = 4; - optional bytes groupId = 5; - } - - optional bytes ephemeralPublic = 1; - optional bytes encryptedStatic = 2; - optional bytes encryptedMessage = 3; -} diff --git a/net/gurk-rs/files/vendor/libsignal-protocol/src/proto/sealed_sender.rs b/net/gurk-rs/files/vendor/libsignal-protocol/src/proto/sealed_sender.rs deleted file mode 100644 index 0030e6a..0000000 --- a/net/gurk-rs/files/vendor/libsignal-protocol/src/proto/sealed_sender.rs +++ /dev/null @@ -1,6 +0,0 @@ -// -// Copyright 2020 Signal Messenger, LLC. -// SPDX-License-Identifier: AGPL-3.0-only -// - -include!(concat!(env!("OUT_DIR"), "/signal.proto.sealed_sender.rs")); diff --git a/net/gurk-rs/files/vendor/libsignal-protocol/src/proto/service.proto b/net/gurk-rs/files/vendor/libsignal-protocol/src/proto/service.proto deleted file mode 100644 index 38626dc..0000000 --- a/net/gurk-rs/files/vendor/libsignal-protocol/src/proto/service.proto +++ /dev/null @@ -1,24 +0,0 @@ -// -// Copyright 2021 Signal Messenger, LLC. -// SPDX-License-Identifier: AGPL-3.0-only -// - -syntax = "proto2"; -package signalservice; - -message Content { - optional bytes /* DataMessage */ data_message = 1; - optional bytes /* SyncMessage */ sync_message = 2; - optional bytes /* CallMessage */ call_message = 3; - optional bytes /* NullMessage */ null_message = 4; - optional bytes /* ReceiptMessage */ receipt_message = 5; - optional bytes /* TypingMessage */ typing_message = 6; - optional bytes /* SenderKeyDistributionMessage */ sender_key_distribution_message = 7; - optional bytes /* DecryptionErrorMessage */ decryption_error_message = 8; -} - -message DecryptionErrorMessage { - optional bytes ratchet_key = 1; // set to the public ratchet key from the SignalMessage if a 1-1 payload fails to decrypt - optional uint64 timestamp = 2; - optional uint32 device_id = 3; -} diff --git a/net/gurk-rs/files/vendor/libsignal-protocol/src/proto/service.rs b/net/gurk-rs/files/vendor/libsignal-protocol/src/proto/service.rs deleted file mode 100644 index f6e6261..0000000 --- a/net/gurk-rs/files/vendor/libsignal-protocol/src/proto/service.rs +++ /dev/null @@ -1,6 +0,0 @@ -// -// Copyright 2021 Signal Messenger, LLC. -// SPDX-License-Identifier: AGPL-3.0-only -// - -include!(concat!(env!("OUT_DIR"), "/signalservice.rs")); diff --git a/net/gurk-rs/files/vendor/libsignal-protocol/src/proto/storage.proto b/net/gurk-rs/files/vendor/libsignal-protocol/src/proto/storage.proto deleted file mode 100644 index 49fcced..0000000 --- a/net/gurk-rs/files/vendor/libsignal-protocol/src/proto/storage.proto +++ /dev/null @@ -1,108 +0,0 @@ -syntax = "proto3"; - -// -// Copyright 2020 Signal Messenger, LLC. -// SPDX-License-Identifier: AGPL-3.0-only -// - -package signal.proto.storage; - -message SessionStructure { - message Chain { - bytes sender_ratchet_key = 1; - bytes sender_ratchet_key_private = 2; - - message ChainKey { - uint32 index = 1; - bytes key = 2; - } - - ChainKey chain_key = 3; - - message MessageKey { - uint32 index = 1; - bytes cipher_key = 2; - bytes mac_key = 3; - bytes iv = 4; - } - - repeated MessageKey message_keys = 4; - } - - message PendingPreKey { - uint32 pre_key_id = 1; - int32 signed_pre_key_id = 3; - bytes base_key = 2; - } - - uint32 session_version = 1; - bytes local_identity_public = 2; - bytes remote_identity_public = 3; - - bytes root_key = 4; - uint32 previous_counter = 5; - - Chain sender_chain = 6; - // The order is significant; keys at the end are "older" and will get trimmed. - repeated Chain receiver_chains = 7; - - PendingPreKey pending_pre_key = 9; - - uint32 remote_registration_id = 10; - uint32 local_registration_id = 11; - - bool needs_refresh = 12; - bytes alice_base_key = 13; -} - -message RecordStructure { - SessionStructure current_session = 1; - // The order is significant; sessions at the end are "older" and will get trimmed. - repeated /*SessionStructure*/ bytes previous_sessions = 2; -} - -message PreKeyRecordStructure { - uint32 id = 1; - bytes public_key = 2; - bytes private_key = 3; -} - -message SignedPreKeyRecordStructure { - uint32 id = 1; - bytes public_key = 2; - bytes private_key = 3; - bytes signature = 4; - fixed64 timestamp = 5; -} - -message IdentityKeyPairStructure { - bytes public_key = 1; - bytes private_key = 2; -} - -message SenderKeyStateStructure { - message SenderChainKey { - uint32 iteration = 1; - bytes seed = 2; - } - - message SenderMessageKey { - uint32 iteration = 1; - bytes seed = 2; - } - - message SenderSigningKey { - bytes public = 1; - bytes private = 2; - } - - uint32 message_version = 5; - uint32 chain_id = 1; - SenderChainKey sender_chain_key = 2; - SenderSigningKey sender_signing_key = 3; - repeated SenderMessageKey sender_message_keys = 4; -} - -message SenderKeyRecordStructure { - repeated SenderKeyStateStructure sender_key_states = 1; -} diff --git a/net/gurk-rs/files/vendor/libsignal-protocol/src/proto/storage.rs b/net/gurk-rs/files/vendor/libsignal-protocol/src/proto/storage.rs deleted file mode 100644 index ec2d3f9..0000000 --- a/net/gurk-rs/files/vendor/libsignal-protocol/src/proto/storage.rs +++ /dev/null @@ -1,6 +0,0 @@ -// -// Copyright 2020 Signal Messenger, LLC. -// SPDX-License-Identifier: AGPL-3.0-only -// - -include!(concat!(env!("OUT_DIR"), "/signal.proto.storage.rs")); diff --git a/net/gurk-rs/files/vendor/libsignal-protocol/src/proto/wire.proto b/net/gurk-rs/files/vendor/libsignal-protocol/src/proto/wire.proto deleted file mode 100644 index e0c0683..0000000 --- a/net/gurk-rs/files/vendor/libsignal-protocol/src/proto/wire.proto +++ /dev/null @@ -1,39 +0,0 @@ -syntax = "proto2"; - -// -// Copyright 2020 Signal Messenger, LLC. -// SPDX-License-Identifier: AGPL-3.0-only -// - -package signal.proto.wire; - -message SignalMessage { - optional bytes ratchet_key = 1; - optional uint32 counter = 2; - optional uint32 previous_counter = 3; - optional bytes ciphertext = 4; -} - -message PreKeySignalMessage { - optional uint32 registration_id = 5; - optional uint32 pre_key_id = 1; - optional uint32 signed_pre_key_id = 6; - optional bytes base_key = 2; - optional bytes identity_key = 3; - optional bytes message = 4; // SignalMessage -} - -message SenderKeyMessage { - optional bytes distribution_uuid = 1; - optional uint32 chain_id = 2; - optional uint32 iteration = 3; - optional bytes ciphertext = 4; -} - -message SenderKeyDistributionMessage { - optional bytes distribution_uuid = 1; - optional uint32 chain_id = 2; - optional uint32 iteration = 3; - optional bytes chain_key = 4; - optional bytes signing_key = 5; -} diff --git a/net/gurk-rs/files/vendor/libsignal-protocol/src/proto/wire.rs b/net/gurk-rs/files/vendor/libsignal-protocol/src/proto/wire.rs deleted file mode 100644 index e5e4e9c..0000000 --- a/net/gurk-rs/files/vendor/libsignal-protocol/src/proto/wire.rs +++ /dev/null @@ -1,6 +0,0 @@ -// -// Copyright 2020 Signal Messenger, LLC. -// SPDX-License-Identifier: AGPL-3.0-only -// - -include!(concat!(env!("OUT_DIR"), "/signal.proto.wire.rs")); diff --git a/net/gurk-rs/files/vendor/libsignal-protocol/src/protocol.rs b/net/gurk-rs/files/vendor/libsignal-protocol/src/protocol.rs deleted file mode 100644 index b8bcf8a..0000000 --- a/net/gurk-rs/files/vendor/libsignal-protocol/src/protocol.rs +++ /dev/null @@ -1,1059 +0,0 @@ -// -// Copyright 2020-2021 Signal Messenger, LLC. -// SPDX-License-Identifier: AGPL-3.0-only -// - -use crate::proto; -use crate::{IdentityKey, PrivateKey, PublicKey, Result, SignalProtocolError}; - -use std::convert::TryFrom; - -use hmac::{Hmac, Mac, NewMac}; -use prost::Message; -use rand::{CryptoRng, Rng}; -use sha2::Sha256; -use subtle::ConstantTimeEq; -use uuid::Uuid; - -pub const CIPHERTEXT_MESSAGE_CURRENT_VERSION: u8 = 3; -pub const SENDERKEY_MESSAGE_CURRENT_VERSION: u8 = 3; - -pub enum CiphertextMessage { - SignalMessage(SignalMessage), - PreKeySignalMessage(PreKeySignalMessage), - SenderKeyMessage(SenderKeyMessage), - PlaintextContent(PlaintextContent), -} - -#[derive(Copy, Clone, Eq, PartialEq, Debug, num_enum::TryFromPrimitive)] -#[repr(u8)] -pub enum CiphertextMessageType { - Whisper = 2, - PreKey = 3, - SenderKey = 7, - Plaintext = 8, -} - -impl CiphertextMessage { - pub fn message_type(&self) -> CiphertextMessageType { - match self { - CiphertextMessage::SignalMessage(_) => CiphertextMessageType::Whisper, - CiphertextMessage::PreKeySignalMessage(_) => CiphertextMessageType::PreKey, - CiphertextMessage::SenderKeyMessage(_) => CiphertextMessageType::SenderKey, - CiphertextMessage::PlaintextContent(_) => CiphertextMessageType::Plaintext, - } - } - - pub fn serialize(&self) -> &[u8] { - match self { - CiphertextMessage::SignalMessage(x) => x.serialized(), - CiphertextMessage::PreKeySignalMessage(x) => x.serialized(), - CiphertextMessage::SenderKeyMessage(x) => x.serialized(), - CiphertextMessage::PlaintextContent(x) => x.serialized(), - } - } -} - -#[derive(Debug, Clone)] -pub struct SignalMessage { - message_version: u8, - sender_ratchet_key: PublicKey, - counter: u32, - #[allow(dead_code)] - previous_counter: u32, - ciphertext: Box<[u8]>, - serialized: Box<[u8]>, -} - -impl SignalMessage { - const MAC_LENGTH: usize = 8; - - pub fn new( - message_version: u8, - mac_key: &[u8], - sender_ratchet_key: PublicKey, - counter: u32, - previous_counter: u32, - ciphertext: &[u8], - sender_identity_key: &IdentityKey, - receiver_identity_key: &IdentityKey, - ) -> Result { - let message = proto::wire::SignalMessage { - ratchet_key: Some(sender_ratchet_key.serialize().into_vec()), - counter: Some(counter), - previous_counter: Some(previous_counter), - ciphertext: Some(Vec::::from(ciphertext)), - }; - let mut serialized = vec![0u8; 1 + message.encoded_len() + Self::MAC_LENGTH]; - serialized[0] = ((message_version & 0xF) << 4) | CIPHERTEXT_MESSAGE_CURRENT_VERSION; - message.encode(&mut &mut serialized[1..message.encoded_len() + 1])?; - let msg_len_for_mac = serialized.len() - Self::MAC_LENGTH; - let mac = Self::compute_mac( - sender_identity_key, - receiver_identity_key, - mac_key, - &serialized[..msg_len_for_mac], - )?; - serialized[msg_len_for_mac..].copy_from_slice(&mac); - let serialized = serialized.into_boxed_slice(); - Ok(Self { - message_version, - sender_ratchet_key, - counter, - previous_counter, - ciphertext: ciphertext.into(), - serialized, - }) - } - - #[inline] - pub fn message_version(&self) -> u8 { - self.message_version - } - - #[inline] - pub fn sender_ratchet_key(&self) -> &PublicKey { - &self.sender_ratchet_key - } - - #[inline] - pub fn counter(&self) -> u32 { - self.counter - } - - #[inline] - pub fn serialized(&self) -> &[u8] { - &*self.serialized - } - - #[inline] - pub fn body(&self) -> &[u8] { - &*self.ciphertext - } - - pub fn verify_mac( - &self, - sender_identity_key: &IdentityKey, - receiver_identity_key: &IdentityKey, - mac_key: &[u8], - ) -> Result { - let our_mac = &Self::compute_mac( - sender_identity_key, - receiver_identity_key, - mac_key, - &self.serialized[..self.serialized.len() - Self::MAC_LENGTH], - )?; - let their_mac = &self.serialized[self.serialized.len() - Self::MAC_LENGTH..]; - let result: bool = our_mac.ct_eq(their_mac).into(); - if !result { - // A warning instead of an error because we try multiple sessions. - log::warn!( - "Bad Mac! Their Mac: {} Our Mac: {}", - hex::encode(their_mac), - hex::encode(our_mac) - ); - } - Ok(result) - } - - fn compute_mac( - sender_identity_key: &IdentityKey, - receiver_identity_key: &IdentityKey, - mac_key: &[u8], - message: &[u8], - ) -> Result<[u8; Self::MAC_LENGTH]> { - if mac_key.len() != 32 { - return Err(SignalProtocolError::InvalidMacKeyLength(mac_key.len())); - } - let mut mac = Hmac::::new_from_slice(mac_key) - .expect("HMAC-SHA256 should accept any size key"); - - mac.update(sender_identity_key.public_key().serialize().as_ref()); - mac.update(receiver_identity_key.public_key().serialize().as_ref()); - mac.update(message); - let mut result = [0u8; Self::MAC_LENGTH]; - result.copy_from_slice(&mac.finalize().into_bytes()[..Self::MAC_LENGTH]); - Ok(result) - } -} - -impl AsRef<[u8]> for SignalMessage { - fn as_ref(&self) -> &[u8] { - &*self.serialized - } -} - -impl TryFrom<&[u8]> for SignalMessage { - type Error = SignalProtocolError; - - fn try_from(value: &[u8]) -> Result { - if value.len() < SignalMessage::MAC_LENGTH + 1 { - return Err(SignalProtocolError::CiphertextMessageTooShort(value.len())); - } - let message_version = value[0] >> 4; - if message_version < CIPHERTEXT_MESSAGE_CURRENT_VERSION { - return Err(SignalProtocolError::LegacyCiphertextVersion( - message_version, - )); - } - if message_version > CIPHERTEXT_MESSAGE_CURRENT_VERSION { - return Err(SignalProtocolError::UnrecognizedCiphertextVersion( - message_version, - )); - } - - let proto_structure = - proto::wire::SignalMessage::decode(&value[1..value.len() - SignalMessage::MAC_LENGTH])?; - - let sender_ratchet_key = proto_structure - .ratchet_key - .ok_or(SignalProtocolError::InvalidProtobufEncoding)?; - let sender_ratchet_key = PublicKey::deserialize(&sender_ratchet_key)?; - let counter = proto_structure - .counter - .ok_or(SignalProtocolError::InvalidProtobufEncoding)?; - let previous_counter = proto_structure.previous_counter.unwrap_or(0); - let ciphertext = proto_structure - .ciphertext - .ok_or(SignalProtocolError::InvalidProtobufEncoding)? - .into_boxed_slice(); - - Ok(SignalMessage { - message_version, - sender_ratchet_key, - counter, - previous_counter, - ciphertext, - serialized: Box::from(value), - }) - } -} - -#[derive(Debug, Clone)] -pub struct PreKeySignalMessage { - message_version: u8, - registration_id: u32, - pre_key_id: Option, - signed_pre_key_id: u32, - base_key: PublicKey, - identity_key: IdentityKey, - message: SignalMessage, - serialized: Box<[u8]>, -} - -impl PreKeySignalMessage { - pub fn new( - message_version: u8, - registration_id: u32, - pre_key_id: Option, - signed_pre_key_id: u32, - base_key: PublicKey, - identity_key: IdentityKey, - message: SignalMessage, - ) -> Result { - let proto_message = proto::wire::PreKeySignalMessage { - registration_id: Some(registration_id), - pre_key_id, - signed_pre_key_id: Some(signed_pre_key_id), - base_key: Some(base_key.serialize().into_vec()), - identity_key: Some(identity_key.serialize().into_vec()), - message: Some(Vec::from(message.as_ref())), - }; - let mut serialized = vec![0u8; 1 + proto_message.encoded_len()]; - serialized[0] = ((message_version & 0xF) << 4) | CIPHERTEXT_MESSAGE_CURRENT_VERSION; - proto_message.encode(&mut &mut serialized[1..])?; - Ok(Self { - message_version, - registration_id, - pre_key_id, - signed_pre_key_id, - base_key, - identity_key, - message, - serialized: serialized.into_boxed_slice(), - }) - } - - #[inline] - pub fn message_version(&self) -> u8 { - self.message_version - } - - #[inline] - pub fn registration_id(&self) -> u32 { - self.registration_id - } - - #[inline] - pub fn pre_key_id(&self) -> Option { - self.pre_key_id - } - - #[inline] - pub fn signed_pre_key_id(&self) -> u32 { - self.signed_pre_key_id - } - - #[inline] - pub fn base_key(&self) -> &PublicKey { - &self.base_key - } - - #[inline] - pub fn identity_key(&self) -> &IdentityKey { - &self.identity_key - } - - #[inline] - pub fn message(&self) -> &SignalMessage { - &self.message - } - - #[inline] - pub fn serialized(&self) -> &[u8] { - &*self.serialized - } -} - -impl AsRef<[u8]> for PreKeySignalMessage { - fn as_ref(&self) -> &[u8] { - &*self.serialized - } -} - -impl TryFrom<&[u8]> for PreKeySignalMessage { - type Error = SignalProtocolError; - - fn try_from(value: &[u8]) -> Result { - if value.is_empty() { - return Err(SignalProtocolError::CiphertextMessageTooShort(value.len())); - } - - let message_version = value[0] >> 4; - if message_version < CIPHERTEXT_MESSAGE_CURRENT_VERSION { - return Err(SignalProtocolError::LegacyCiphertextVersion( - message_version, - )); - } - if message_version > CIPHERTEXT_MESSAGE_CURRENT_VERSION { - return Err(SignalProtocolError::UnrecognizedCiphertextVersion( - message_version, - )); - } - - let proto_structure = proto::wire::PreKeySignalMessage::decode(&value[1..])?; - - let base_key = proto_structure - .base_key - .ok_or(SignalProtocolError::InvalidProtobufEncoding)?; - let identity_key = proto_structure - .identity_key - .ok_or(SignalProtocolError::InvalidProtobufEncoding)?; - let message = proto_structure - .message - .ok_or(SignalProtocolError::InvalidProtobufEncoding)?; - let signed_pre_key_id = proto_structure - .signed_pre_key_id - .ok_or(SignalProtocolError::InvalidProtobufEncoding)?; - - let base_key = PublicKey::deserialize(base_key.as_ref())?; - - Ok(PreKeySignalMessage { - message_version, - registration_id: proto_structure.registration_id.unwrap_or(0), - pre_key_id: proto_structure.pre_key_id, - signed_pre_key_id, - base_key, - identity_key: IdentityKey::try_from(identity_key.as_ref())?, - message: SignalMessage::try_from(message.as_ref())?, - serialized: Box::from(value), - }) - } -} - -#[derive(Debug, Clone)] -pub struct SenderKeyMessage { - message_version: u8, - distribution_id: Uuid, - chain_id: u32, - iteration: u32, - ciphertext: Box<[u8]>, - serialized: Box<[u8]>, -} - -impl SenderKeyMessage { - const SIGNATURE_LEN: usize = 64; - - pub fn new( - message_version: u8, - distribution_id: Uuid, - chain_id: u32, - iteration: u32, - ciphertext: Box<[u8]>, - csprng: &mut R, - signature_key: &PrivateKey, - ) -> Result { - let proto_message = proto::wire::SenderKeyMessage { - distribution_uuid: Some(distribution_id.as_bytes().to_vec()), - chain_id: Some(chain_id), - iteration: Some(iteration), - ciphertext: Some(ciphertext.to_vec()), - }; - let proto_message_len = proto_message.encoded_len(); - let mut serialized = vec![0u8; 1 + proto_message_len + Self::SIGNATURE_LEN]; - serialized[0] = ((message_version & 0xF) << 4) | SENDERKEY_MESSAGE_CURRENT_VERSION; - proto_message.encode(&mut &mut serialized[1..1 + proto_message_len])?; - let signature = - signature_key.calculate_signature(&serialized[..1 + proto_message_len], csprng)?; - serialized[1 + proto_message_len..].copy_from_slice(&signature[..]); - Ok(Self { - message_version: SENDERKEY_MESSAGE_CURRENT_VERSION, - distribution_id, - chain_id, - iteration, - ciphertext, - serialized: serialized.into_boxed_slice(), - }) - } - - pub fn verify_signature(&self, signature_key: &PublicKey) -> Result { - let valid = signature_key.verify_signature( - &self.serialized[..self.serialized.len() - Self::SIGNATURE_LEN], - &self.serialized[self.serialized.len() - Self::SIGNATURE_LEN..], - )?; - - Ok(valid) - } - - #[inline] - pub fn message_version(&self) -> u8 { - self.message_version - } - - #[inline] - pub fn distribution_id(&self) -> Uuid { - self.distribution_id - } - - #[inline] - pub fn chain_id(&self) -> u32 { - self.chain_id - } - - #[inline] - pub fn iteration(&self) -> u32 { - self.iteration - } - - #[inline] - pub fn ciphertext(&self) -> &[u8] { - &*self.ciphertext - } - - #[inline] - pub fn serialized(&self) -> &[u8] { - &*self.serialized - } -} - -impl AsRef<[u8]> for SenderKeyMessage { - fn as_ref(&self) -> &[u8] { - &*self.serialized - } -} - -impl TryFrom<&[u8]> for SenderKeyMessage { - type Error = SignalProtocolError; - - fn try_from(value: &[u8]) -> Result { - if value.len() < 1 + Self::SIGNATURE_LEN { - return Err(SignalProtocolError::CiphertextMessageTooShort(value.len())); - } - let message_version = value[0] >> 4; - if message_version < SENDERKEY_MESSAGE_CURRENT_VERSION { - return Err(SignalProtocolError::LegacyCiphertextVersion( - message_version, - )); - } - if message_version > SENDERKEY_MESSAGE_CURRENT_VERSION { - return Err(SignalProtocolError::UnrecognizedCiphertextVersion( - message_version, - )); - } - let proto_structure = - proto::wire::SenderKeyMessage::decode(&value[1..value.len() - Self::SIGNATURE_LEN])?; - - let distribution_id = proto_structure - .distribution_uuid - .and_then(|bytes| Uuid::from_slice(bytes.as_slice()).ok()) - .ok_or(SignalProtocolError::InvalidProtobufEncoding)?; - let chain_id = proto_structure - .chain_id - .ok_or(SignalProtocolError::InvalidProtobufEncoding)?; - let iteration = proto_structure - .iteration - .ok_or(SignalProtocolError::InvalidProtobufEncoding)?; - let ciphertext = proto_structure - .ciphertext - .ok_or(SignalProtocolError::InvalidProtobufEncoding)? - .into_boxed_slice(); - - Ok(SenderKeyMessage { - message_version, - distribution_id, - chain_id, - iteration, - ciphertext, - serialized: Box::from(value), - }) - } -} - -#[derive(Debug, Clone)] -pub struct SenderKeyDistributionMessage { - message_version: u8, - distribution_id: Uuid, - chain_id: u32, - iteration: u32, - chain_key: Vec, - signing_key: PublicKey, - serialized: Box<[u8]>, -} - -impl SenderKeyDistributionMessage { - pub fn new( - message_version: u8, - distribution_id: Uuid, - chain_id: u32, - iteration: u32, - chain_key: Vec, - signing_key: PublicKey, - ) -> Result { - let proto_message = proto::wire::SenderKeyDistributionMessage { - distribution_uuid: Some(distribution_id.as_bytes().to_vec()), - chain_id: Some(chain_id), - iteration: Some(iteration), - chain_key: Some(chain_key.clone()), - signing_key: Some(signing_key.serialize().to_vec()), - }; - let mut serialized = vec![0u8; 1 + proto_message.encoded_len()]; - serialized[0] = ((message_version & 0xF) << 4) | SENDERKEY_MESSAGE_CURRENT_VERSION; - proto_message.encode(&mut &mut serialized[1..])?; - - Ok(Self { - message_version, - distribution_id, - chain_id, - iteration, - chain_key, - signing_key, - serialized: serialized.into_boxed_slice(), - }) - } - - #[inline] - pub fn message_version(&self) -> u8 { - self.message_version - } - - #[inline] - pub fn distribution_id(&self) -> Result { - Ok(self.distribution_id) - } - - #[inline] - pub fn chain_id(&self) -> Result { - Ok(self.chain_id) - } - - #[inline] - pub fn iteration(&self) -> Result { - Ok(self.iteration) - } - - #[inline] - pub fn chain_key(&self) -> Result<&[u8]> { - Ok(&self.chain_key) - } - - #[inline] - pub fn signing_key(&self) -> Result<&PublicKey> { - Ok(&self.signing_key) - } - - #[inline] - pub fn serialized(&self) -> &[u8] { - &*self.serialized - } -} - -impl AsRef<[u8]> for SenderKeyDistributionMessage { - fn as_ref(&self) -> &[u8] { - &*self.serialized - } -} - -impl TryFrom<&[u8]> for SenderKeyDistributionMessage { - type Error = SignalProtocolError; - - fn try_from(value: &[u8]) -> Result { - // The message contains at least a X25519 key and a chain key - if value.len() < 1 + 32 + 32 { - return Err(SignalProtocolError::CiphertextMessageTooShort(value.len())); - } - - let message_version = value[0] >> 4; - - if message_version < SENDERKEY_MESSAGE_CURRENT_VERSION { - return Err(SignalProtocolError::LegacyCiphertextVersion( - message_version, - )); - } - if message_version > SENDERKEY_MESSAGE_CURRENT_VERSION { - return Err(SignalProtocolError::UnrecognizedCiphertextVersion( - message_version, - )); - } - - let proto_structure = proto::wire::SenderKeyDistributionMessage::decode(&value[1..])?; - - let distribution_id = proto_structure - .distribution_uuid - .and_then(|bytes| Uuid::from_slice(bytes.as_slice()).ok()) - .ok_or(SignalProtocolError::InvalidProtobufEncoding)?; - let chain_id = proto_structure - .chain_id - .ok_or(SignalProtocolError::InvalidProtobufEncoding)?; - let iteration = proto_structure - .iteration - .ok_or(SignalProtocolError::InvalidProtobufEncoding)?; - let chain_key = proto_structure - .chain_key - .ok_or(SignalProtocolError::InvalidProtobufEncoding)?; - let signing_key = proto_structure - .signing_key - .ok_or(SignalProtocolError::InvalidProtobufEncoding)?; - - if chain_key.len() != 32 || signing_key.len() != 33 { - return Err(SignalProtocolError::InvalidProtobufEncoding); - } - - let signing_key = PublicKey::deserialize(&signing_key)?; - - Ok(SenderKeyDistributionMessage { - message_version, - distribution_id, - chain_id, - iteration, - chain_key, - signing_key, - serialized: Box::from(value), - }) - } -} - -#[derive(Debug, Clone)] -pub struct PlaintextContent { - serialized: Box<[u8]>, -} - -impl PlaintextContent { - /// Identifies a serialized PlaintextContent. - /// - /// This ensures someone doesn't try to serialize an arbitrary Content message as - /// PlaintextContent; only messages that are okay to send as plaintext should be allowed. - const PLAINTEXT_CONTEXT_IDENTIFIER_BYTE: u8 = 0xC0; - - /// Marks the end of a message and the start of any padding. - /// - /// Usually messages are padded to avoid exposing patterns, - /// but PlaintextContent messages are all fixed-length anyway, so there won't be any padding. - const PADDING_BOUNDARY_BYTE: u8 = 0x80; - - #[inline] - pub fn body(&self) -> &[u8] { - &self.serialized[1..] - } - - #[inline] - pub fn serialized(&self) -> &[u8] { - &self.serialized - } -} - -impl From for PlaintextContent { - fn from(message: DecryptionErrorMessage) -> Self { - let proto_structure = proto::service::Content { - decryption_error_message: Some(message.serialized().to_vec()), - ..Default::default() - }; - let mut serialized = vec![Self::PLAINTEXT_CONTEXT_IDENTIFIER_BYTE]; - proto_structure - .encode(&mut serialized) - .expect("can always encode to a Vec"); - serialized.push(Self::PADDING_BOUNDARY_BYTE); - Self { - serialized: Box::from(serialized), - } - } -} - -impl TryFrom<&[u8]> for PlaintextContent { - type Error = SignalProtocolError; - - fn try_from(value: &[u8]) -> Result { - if value.is_empty() { - return Err(SignalProtocolError::CiphertextMessageTooShort(0)); - } - if value[0] != Self::PLAINTEXT_CONTEXT_IDENTIFIER_BYTE { - return Err(SignalProtocolError::UnrecognizedMessageVersion( - value[0] as u32, - )); - } - Ok(Self { - serialized: Box::from(value), - }) - } -} - -#[derive(Debug, Clone)] -pub struct DecryptionErrorMessage { - ratchet_key: Option, - timestamp: u64, - device_id: u32, - serialized: Box<[u8]>, -} - -impl DecryptionErrorMessage { - pub fn for_original( - original_bytes: &[u8], - original_type: CiphertextMessageType, - original_timestamp: u64, - original_sender_device_id: u32, - ) -> Result { - let ratchet_key = match original_type { - CiphertextMessageType::Whisper => { - Some(*SignalMessage::try_from(original_bytes)?.sender_ratchet_key()) - } - CiphertextMessageType::PreKey => Some( - *PreKeySignalMessage::try_from(original_bytes)? - .message() - .sender_ratchet_key(), - ), - CiphertextMessageType::SenderKey => None, - CiphertextMessageType::Plaintext => { - return Err(SignalProtocolError::InvalidArgument( - "cannot create a DecryptionErrorMessage for plaintext content; it is not encrypted".to_string() - )); - } - }; - - let proto_message = proto::service::DecryptionErrorMessage { - timestamp: Some(original_timestamp), - ratchet_key: ratchet_key.map(|k| k.serialize().into()), - device_id: Some(original_sender_device_id), - }; - let mut serialized = Vec::new(); - proto_message.encode(&mut serialized)?; - - Ok(Self { - ratchet_key, - timestamp: original_timestamp, - device_id: original_sender_device_id, - serialized: serialized.into_boxed_slice(), - }) - } - - #[inline] - pub fn timestamp(&self) -> u64 { - self.timestamp - } - - #[inline] - pub fn ratchet_key(&self) -> Option<&PublicKey> { - self.ratchet_key.as_ref() - } - - #[inline] - pub fn device_id(&self) -> u32 { - self.device_id - } - - #[inline] - pub fn serialized(&self) -> &[u8] { - &self.serialized - } -} - -impl TryFrom<&[u8]> for DecryptionErrorMessage { - type Error = SignalProtocolError; - - fn try_from(value: &[u8]) -> Result { - let proto_structure = proto::service::DecryptionErrorMessage::decode(value)?; - let timestamp = proto_structure - .timestamp - .ok_or(SignalProtocolError::InvalidProtobufEncoding)?; - let ratchet_key = proto_structure - .ratchet_key - .map(|k| PublicKey::deserialize(&k)) - .transpose()?; - let device_id = proto_structure.device_id.unwrap_or_default(); - Ok(Self { - timestamp, - ratchet_key, - device_id, - serialized: Box::from(value), - }) - } -} - -/// For testing -pub fn extract_decryption_error_message_from_serialized_content( - bytes: &[u8], -) -> Result { - if bytes.last() != Some(&PlaintextContent::PADDING_BOUNDARY_BYTE) { - return Err(SignalProtocolError::InvalidProtobufEncoding); - } - let content = proto::service::Content::decode(bytes.split_last().expect("checked above").1)?; - content - .decryption_error_message - .as_deref() - .ok_or_else(|| { - SignalProtocolError::InvalidArgument( - "Content does not contain DecryptionErrorMessage".to_owned(), - ) - }) - .and_then(DecryptionErrorMessage::try_from) -} - -#[cfg(test)] -mod tests { - use super::*; - use crate::KeyPair; - - use rand::rngs::OsRng; - use rand::{CryptoRng, Rng}; - - fn create_signal_message(csprng: &mut T) -> Result - where - T: Rng + CryptoRng, - { - let mut mac_key = [0u8; 32]; - csprng.fill_bytes(&mut mac_key); - let mac_key = mac_key; - - let mut ciphertext = [0u8; 20]; - csprng.fill_bytes(&mut ciphertext); - let ciphertext = ciphertext; - - let sender_ratchet_key_pair = KeyPair::generate(csprng); - let sender_identity_key_pair = KeyPair::generate(csprng); - let receiver_identity_key_pair = KeyPair::generate(csprng); - - SignalMessage::new( - 3, - &mac_key, - sender_ratchet_key_pair.public_key, - 42, - 41, - &ciphertext, - &sender_identity_key_pair.public_key.into(), - &receiver_identity_key_pair.public_key.into(), - ) - } - - fn assert_signal_message_equals(m1: &SignalMessage, m2: &SignalMessage) { - assert_eq!(m1.message_version, m2.message_version); - assert_eq!(m1.sender_ratchet_key, m2.sender_ratchet_key); - assert_eq!(m1.counter, m2.counter); - assert_eq!(m1.previous_counter, m2.previous_counter); - assert_eq!(m1.ciphertext, m2.ciphertext); - assert_eq!(m1.serialized, m2.serialized); - } - - #[test] - fn test_signal_message_serialize_deserialize() -> Result<()> { - let mut csprng = OsRng; - let message = create_signal_message(&mut csprng)?; - let deser_message = - SignalMessage::try_from(message.as_ref()).expect("should deserialize without error"); - assert_signal_message_equals(&message, &deser_message); - Ok(()) - } - - #[test] - fn test_pre_key_signal_message_serialize_deserialize() -> Result<()> { - let mut csprng = OsRng; - let identity_key_pair = KeyPair::generate(&mut csprng); - let base_key_pair = KeyPair::generate(&mut csprng); - let message = create_signal_message(&mut csprng)?; - let pre_key_signal_message = PreKeySignalMessage::new( - 3, - 365, - None, - 97, - base_key_pair.public_key, - identity_key_pair.public_key.into(), - message, - )?; - let deser_pre_key_signal_message = - PreKeySignalMessage::try_from(pre_key_signal_message.as_ref()) - .expect("should deserialize without error"); - assert_eq!( - pre_key_signal_message.message_version, - deser_pre_key_signal_message.message_version - ); - assert_eq!( - pre_key_signal_message.registration_id, - deser_pre_key_signal_message.registration_id - ); - assert_eq!( - pre_key_signal_message.pre_key_id, - deser_pre_key_signal_message.pre_key_id - ); - assert_eq!( - pre_key_signal_message.signed_pre_key_id, - deser_pre_key_signal_message.signed_pre_key_id - ); - assert_eq!( - pre_key_signal_message.base_key, - deser_pre_key_signal_message.base_key - ); - assert_eq!( - pre_key_signal_message.identity_key.public_key(), - deser_pre_key_signal_message.identity_key.public_key() - ); - assert_signal_message_equals( - &pre_key_signal_message.message, - &deser_pre_key_signal_message.message, - ); - assert_eq!( - pre_key_signal_message.serialized, - deser_pre_key_signal_message.serialized - ); - Ok(()) - } - - #[test] - fn test_sender_key_message_serialize_deserialize() -> Result<()> { - let mut csprng = OsRng; - let signature_key_pair = KeyPair::generate(&mut csprng); - let sender_key_message = SenderKeyMessage::new( - SENDERKEY_MESSAGE_CURRENT_VERSION, - Uuid::from_u128(0xd1d1d1d1_7000_11eb_b32a_33b8a8a487a6), - 42, - 7, - [1u8, 2, 3].into(), - &mut csprng, - &signature_key_pair.private_key, - )?; - let deser_sender_key_message = SenderKeyMessage::try_from(sender_key_message.as_ref()) - .expect("should deserialize without error"); - assert_eq!( - sender_key_message.message_version, - deser_sender_key_message.message_version - ); - assert_eq!( - sender_key_message.chain_id, - deser_sender_key_message.chain_id - ); - assert_eq!( - sender_key_message.iteration, - deser_sender_key_message.iteration - ); - assert_eq!( - sender_key_message.ciphertext, - deser_sender_key_message.ciphertext - ); - assert_eq!( - sender_key_message.serialized, - deser_sender_key_message.serialized - ); - Ok(()) - } - - #[test] - fn test_decryption_error_message() -> Result<()> { - let mut csprng = OsRng; - let identity_key_pair = KeyPair::generate(&mut csprng); - let base_key_pair = KeyPair::generate(&mut csprng); - let message = create_signal_message(&mut csprng)?; - let timestamp = 0x2_0000_0001; - let device_id = 0x8086_2021; - - { - let error_message = DecryptionErrorMessage::for_original( - message.serialized(), - CiphertextMessageType::Whisper, - timestamp, - device_id, - )?; - let error_message = DecryptionErrorMessage::try_from(error_message.serialized())?; - assert_eq!( - error_message.ratchet_key(), - Some(message.sender_ratchet_key()) - ); - assert_eq!(error_message.timestamp(), timestamp); - assert_eq!(error_message.device_id(), device_id); - } - - let pre_key_signal_message = PreKeySignalMessage::new( - 3, - 365, - None, - 97, - base_key_pair.public_key, - identity_key_pair.public_key.into(), - message, - )?; - - { - let error_message = DecryptionErrorMessage::for_original( - pre_key_signal_message.serialized(), - CiphertextMessageType::PreKey, - timestamp, - device_id, - )?; - let error_message = DecryptionErrorMessage::try_from(error_message.serialized())?; - assert_eq!( - error_message.ratchet_key(), - Some(pre_key_signal_message.message().sender_ratchet_key()) - ); - assert_eq!(error_message.timestamp(), timestamp); - assert_eq!(error_message.device_id(), device_id); - } - - let sender_key_message = SenderKeyMessage::new( - 3, - Uuid::nil(), - 1, - 2, - Box::from(b"test".to_owned()), - &mut csprng, - &base_key_pair.private_key, - )?; - - { - let error_message = DecryptionErrorMessage::for_original( - sender_key_message.serialized(), - CiphertextMessageType::SenderKey, - timestamp, - device_id, - )?; - let error_message = DecryptionErrorMessage::try_from(error_message.serialized())?; - assert_eq!(error_message.ratchet_key(), None); - assert_eq!(error_message.timestamp(), timestamp); - assert_eq!(error_message.device_id(), device_id); - } - - Ok(()) - } - - #[test] - fn test_decryption_error_message_for_plaintext() { - assert!(matches!( - DecryptionErrorMessage::for_original(&[], CiphertextMessageType::Plaintext, 5, 7), - Err(SignalProtocolError::InvalidArgument(_)) - )); - } -} diff --git a/net/gurk-rs/files/vendor/libsignal-protocol/src/ratchet.rs b/net/gurk-rs/files/vendor/libsignal-protocol/src/ratchet.rs deleted file mode 100644 index 2d91fee..0000000 --- a/net/gurk-rs/files/vendor/libsignal-protocol/src/ratchet.rs +++ /dev/null @@ -1,168 +0,0 @@ -// -// Copyright 2020 Signal Messenger, LLC. -// SPDX-License-Identifier: AGPL-3.0-only -// - -mod keys; -mod params; - -pub use self::keys::{ChainKey, MessageKeys, RootKey}; -pub use self::params::{AliceSignalProtocolParameters, BobSignalProtocolParameters}; -use crate::proto::storage::SessionStructure; -use crate::protocol::CIPHERTEXT_MESSAGE_CURRENT_VERSION; -use crate::state::SessionState; -use crate::{KeyPair, Result, SessionRecord}; -use rand::{CryptoRng, Rng}; - -fn derive_keys(secret_input: &[u8]) -> Result<(RootKey, ChainKey)> { - let mut secrets = [0; 64]; - hkdf::Hkdf::::new(None, secret_input) - .expand(b"WhisperText", &mut secrets) - .expect("valid length"); - - let root_key = RootKey::new(&secrets[0..32])?; - let chain_key = ChainKey::new(&secrets[32..64], 0)?; - - Ok((root_key, chain_key)) -} - -pub(crate) fn initialize_alice_session( - parameters: &AliceSignalProtocolParameters, - mut csprng: &mut R, -) -> Result { - let local_identity = parameters.our_identity_key_pair().identity_key(); - - let sending_ratchet_key = KeyPair::generate(&mut csprng); - - let mut secrets = Vec::with_capacity(32 * 5); - - secrets.extend_from_slice(&[0xFFu8; 32]); // "discontinuity bytes" - - let our_base_private_key = parameters.our_base_key_pair().private_key; - - secrets.extend_from_slice( - ¶meters - .our_identity_key_pair() - .private_key() - .calculate_agreement(parameters.their_signed_pre_key())?, - ); - - secrets.extend_from_slice( - &our_base_private_key.calculate_agreement(parameters.their_identity_key().public_key())?, - ); - - secrets.extend_from_slice( - &our_base_private_key.calculate_agreement(parameters.their_signed_pre_key())?, - ); - - if let Some(their_one_time_prekey) = parameters.their_one_time_pre_key() { - secrets - .extend_from_slice(&our_base_private_key.calculate_agreement(their_one_time_prekey)?); - } - - let (root_key, chain_key) = derive_keys(&secrets)?; - - let (sending_chain_root_key, sending_chain_chain_key) = root_key.create_chain( - parameters.their_ratchet_key(), - &sending_ratchet_key.private_key, - )?; - - let session = SessionStructure { - session_version: CIPHERTEXT_MESSAGE_CURRENT_VERSION as u32, - local_identity_public: local_identity.public_key().serialize().to_vec(), - remote_identity_public: parameters.their_identity_key().serialize().to_vec(), - root_key: sending_chain_root_key.key().to_vec(), - previous_counter: 0, - sender_chain: None, - receiver_chains: vec![], - pending_pre_key: None, - remote_registration_id: 0, - local_registration_id: 0, - needs_refresh: false, - alice_base_key: vec![], - }; - - let mut session = SessionState::new(session); - - session.add_receiver_chain(parameters.their_ratchet_key(), &chain_key)?; - session.set_sender_chain(&sending_ratchet_key, &sending_chain_chain_key)?; - - Ok(session) -} - -pub(crate) fn initialize_bob_session( - parameters: &BobSignalProtocolParameters, -) -> Result { - let local_identity = parameters.our_identity_key_pair().identity_key(); - - let mut secrets = Vec::with_capacity(32 * 5); - - secrets.extend_from_slice(&[0xFFu8; 32]); // "discontinuity bytes" - - secrets.extend_from_slice( - ¶meters - .our_signed_pre_key_pair() - .private_key - .calculate_agreement(parameters.their_identity_key().public_key())?, - ); - - secrets.extend_from_slice( - ¶meters - .our_identity_key_pair() - .private_key() - .calculate_agreement(parameters.their_base_key())?, - ); - - secrets.extend_from_slice( - ¶meters - .our_signed_pre_key_pair() - .private_key - .calculate_agreement(parameters.their_base_key())?, - ); - - if let Some(our_one_time_pre_key_pair) = parameters.our_one_time_pre_key_pair() { - secrets.extend_from_slice( - &our_one_time_pre_key_pair - .private_key - .calculate_agreement(parameters.their_base_key())?, - ); - } - - let (root_key, chain_key) = derive_keys(&secrets)?; - - let session = SessionStructure { - session_version: CIPHERTEXT_MESSAGE_CURRENT_VERSION as u32, - local_identity_public: local_identity.public_key().serialize().to_vec(), - remote_identity_public: parameters.their_identity_key().serialize().to_vec(), - root_key: root_key.key().to_vec(), - previous_counter: 0, - sender_chain: None, - receiver_chains: vec![], - pending_pre_key: None, - remote_registration_id: 0, - local_registration_id: 0, - needs_refresh: false, - alice_base_key: vec![], - }; - - let mut session = SessionState::new(session); - - session.set_sender_chain(parameters.our_ratchet_key_pair(), &chain_key)?; - - Ok(session) -} - -pub fn initialize_alice_session_record( - parameters: &AliceSignalProtocolParameters, - csprng: &mut R, -) -> Result { - Ok(SessionRecord::new(initialize_alice_session( - parameters, csprng, - )?)) -} - -pub fn initialize_bob_session_record( - parameters: &BobSignalProtocolParameters, -) -> Result { - Ok(SessionRecord::new(initialize_bob_session(parameters)?)) -} diff --git a/net/gurk-rs/files/vendor/libsignal-protocol/src/ratchet/keys.rs b/net/gurk-rs/files/vendor/libsignal-protocol/src/ratchet/keys.rs deleted file mode 100644 index 310df3c..0000000 --- a/net/gurk-rs/files/vendor/libsignal-protocol/src/ratchet/keys.rs +++ /dev/null @@ -1,210 +0,0 @@ -// -// Copyright 2020 Signal Messenger, LLC. -// SPDX-License-Identifier: AGPL-3.0-only -// - -use arrayref::array_ref; - -use crate::crypto; -use crate::{PrivateKey, PublicKey, Result, SignalProtocolError}; -use std::fmt; - -pub struct MessageKeys { - cipher_key: [u8; 32], - mac_key: [u8; 32], - iv: [u8; 16], - counter: u32, -} - -impl MessageKeys { - pub fn derive_keys(input_key_material: &[u8], counter: u32) -> Result { - let mut okm = [0; 80]; - hkdf::Hkdf::::new(None, input_key_material) - .expand(b"WhisperMessageKeys", &mut okm) - .expect("valid output length"); - - Ok(MessageKeys { - cipher_key: *array_ref![okm, 0, 32], - mac_key: *array_ref![okm, 32, 32], - iv: *array_ref![okm, 64, 16], - counter, - }) - } - - pub fn new(cipher_key: &[u8], mac_key: &[u8], iv: &[u8], counter: u32) -> Result { - if mac_key.len() != 32 { - return Err(SignalProtocolError::InvalidMacKeyLength(mac_key.len())); - } - if cipher_key.len() != 32 || iv.len() != 16 { - return Err(SignalProtocolError::InvalidCipherCryptographicParameters( - cipher_key.len(), - iv.len(), - )); - } - - Ok(MessageKeys { - cipher_key: *array_ref![cipher_key, 0, 32], - mac_key: *array_ref![mac_key, 0, 32], - iv: *array_ref![iv, 0, 16], - counter, - }) - } - - #[inline] - pub fn cipher_key(&self) -> &[u8; 32] { - &self.cipher_key - } - - #[inline] - pub fn mac_key(&self) -> &[u8; 32] { - &self.mac_key - } - - #[inline] - pub fn iv(&self) -> &[u8; 16] { - &self.iv - } - - #[inline] - pub fn counter(&self) -> u32 { - self.counter - } -} - -#[derive(Clone, Debug)] -pub struct ChainKey { - key: [u8; 32], - index: u32, -} - -impl ChainKey { - const MESSAGE_KEY_SEED: [u8; 1] = [0x01u8]; - const CHAIN_KEY_SEED: [u8; 1] = [0x02u8]; - - pub fn new(key: &[u8], index: u32) -> Result { - if key.len() != 32 { - return Err(SignalProtocolError::InvalidChainKeyLength(key.len())); - } - - Ok(Self { - key: *array_ref![key, 0, 32], - index, - }) - } - - #[inline] - pub fn key(&self) -> &[u8; 32] { - &self.key - } - - #[inline] - pub fn index(&self) -> u32 { - self.index - } - - pub fn next_chain_key(&self) -> Result { - Ok(Self { - key: self.calculate_base_material(Self::CHAIN_KEY_SEED)?, - index: self.index + 1, - }) - } - - pub fn message_keys(&self) -> Result { - MessageKeys::derive_keys( - &self.calculate_base_material(Self::MESSAGE_KEY_SEED)?, - self.index, - ) - } - - fn calculate_base_material(&self, seed: [u8; 1]) -> Result<[u8; 32]> { - crypto::hmac_sha256(&self.key, &seed) - } -} - -#[derive(Clone, Debug)] -pub struct RootKey { - key: [u8; 32], -} - -impl RootKey { - pub fn new(key: &[u8]) -> Result { - if key.len() != 32 { - return Err(SignalProtocolError::InvalidRootKeyLength(key.len())); - } - Ok(Self { - key: *array_ref![key, 0, 32], - }) - } - - pub fn key(&self) -> &[u8; 32] { - &self.key - } - - pub fn create_chain( - &self, - their_ratchet_key: &PublicKey, - our_ratchet_key: &PrivateKey, - ) -> Result<(RootKey, ChainKey)> { - let shared_secret = our_ratchet_key.calculate_agreement(their_ratchet_key)?; - let mut derived_secret_bytes = [0; 64]; - hkdf::Hkdf::::new(Some(&self.key), &shared_secret) - .expand(b"WhisperRatchet", &mut derived_secret_bytes) - .expect("valid output length"); - - Ok(( - RootKey { - key: *array_ref![derived_secret_bytes, 0, 32], - }, - ChainKey { - key: *array_ref![derived_secret_bytes, 32, 32], - index: 0, - }, - )) - } -} - -impl fmt::Display for RootKey { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "{}", hex::encode(self.key)) - } -} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_chain_key_derivation() -> Result<()> { - let seed = [ - 0x8au8, 0xb7, 0x2d, 0x6f, 0x4c, 0xc5, 0xac, 0x0d, 0x38, 0x7e, 0xaf, 0x46, 0x33, 0x78, - 0xdd, 0xb2, 0x8e, 0xdd, 0x07, 0x38, 0x5b, 0x1c, 0xb0, 0x12, 0x50, 0xc7, 0x15, 0x98, - 0x2e, 0x7a, 0xd4, 0x8f, - ]; - let message_key = [ - 0xbfu8, 0x51, 0xe9, 0xd7, 0x5e, 0x0e, 0x31, 0x03, 0x10, 0x51, 0xf8, 0x2a, 0x24, 0x91, - 0xff, 0xc0, 0x84, 0xfa, 0x29, 0x8b, 0x77, 0x93, 0xbd, 0x9d, 0xb6, 0x20, 0x05, 0x6f, - 0xeb, 0xf4, 0x52, 0x17, - ]; - let mac_key = [ - 0xc6u8, 0xc7, 0x7d, 0x6a, 0x73, 0xa3, 0x54, 0x33, 0x7a, 0x56, 0x43, 0x5e, 0x34, 0x60, - 0x7d, 0xfe, 0x48, 0xe3, 0xac, 0xe1, 0x4e, 0x77, 0x31, 0x4d, 0xc6, 0xab, 0xc1, 0x72, - 0xe7, 0xa7, 0x03, 0x0b, - ]; - let next_chain_key = [ - 0x28u8, 0xe8, 0xf8, 0xfe, 0xe5, 0x4b, 0x80, 0x1e, 0xef, 0x7c, 0x5c, 0xfb, 0x2f, 0x17, - 0xf3, 0x2c, 0x7b, 0x33, 0x44, 0x85, 0xbb, 0xb7, 0x0f, 0xac, 0x6e, 0xc1, 0x03, 0x42, - 0xa2, 0x46, 0xd1, 0x5d, - ]; - - let chain_key = ChainKey::new(&seed, 0)?; - assert_eq!(&seed, chain_key.key()); - assert_eq!(&message_key, chain_key.message_keys()?.cipher_key()); - assert_eq!(&mac_key, chain_key.message_keys()?.mac_key()); - assert_eq!(&next_chain_key, chain_key.next_chain_key()?.key()); - assert_eq!(0, chain_key.index()); - assert_eq!(0, chain_key.message_keys()?.counter()); - assert_eq!(1, chain_key.next_chain_key()?.index()); - assert_eq!(1, chain_key.next_chain_key()?.message_keys()?.counter()); - Ok(()) - } -} diff --git a/net/gurk-rs/files/vendor/libsignal-protocol/src/ratchet/params.rs b/net/gurk-rs/files/vendor/libsignal-protocol/src/ratchet/params.rs deleted file mode 100644 index b6144b5..0000000 --- a/net/gurk-rs/files/vendor/libsignal-protocol/src/ratchet/params.rs +++ /dev/null @@ -1,126 +0,0 @@ -// -// Copyright 2020 Signal Messenger, LLC. -// SPDX-License-Identifier: AGPL-3.0-only -// - -use crate::{IdentityKey, IdentityKeyPair, KeyPair, PublicKey}; - -pub struct AliceSignalProtocolParameters { - our_identity_key_pair: IdentityKeyPair, - our_base_key_pair: KeyPair, - - their_identity_key: IdentityKey, - their_signed_pre_key: PublicKey, - their_one_time_pre_key: Option, - their_ratchet_key: PublicKey, -} - -impl AliceSignalProtocolParameters { - pub fn new( - our_identity_key_pair: IdentityKeyPair, - our_base_key_pair: KeyPair, - their_identity_key: IdentityKey, - their_signed_pre_key: PublicKey, - their_one_time_pre_key: Option, - their_ratchet_key: PublicKey, - ) -> Self { - Self { - our_identity_key_pair, - our_base_key_pair, - their_identity_key, - their_signed_pre_key, - their_one_time_pre_key, - their_ratchet_key, - } - } - - #[inline] - pub fn our_identity_key_pair(&self) -> &IdentityKeyPair { - &self.our_identity_key_pair - } - - #[inline] - pub fn our_base_key_pair(&self) -> &KeyPair { - &self.our_base_key_pair - } - - #[inline] - pub fn their_identity_key(&self) -> &IdentityKey { - &self.their_identity_key - } - - #[inline] - pub fn their_signed_pre_key(&self) -> &PublicKey { - &self.their_signed_pre_key - } - - #[inline] - pub fn their_one_time_pre_key(&self) -> Option<&PublicKey> { - self.their_one_time_pre_key.as_ref() - } - - #[inline] - pub fn their_ratchet_key(&self) -> &PublicKey { - &self.their_ratchet_key - } -} - -pub struct BobSignalProtocolParameters { - our_identity_key_pair: IdentityKeyPair, - our_signed_pre_key_pair: KeyPair, - our_one_time_pre_key_pair: Option, - our_ratchet_key_pair: KeyPair, - - their_identity_key: IdentityKey, - their_base_key: PublicKey, -} - -impl BobSignalProtocolParameters { - pub fn new( - our_identity_key_pair: IdentityKeyPair, - our_signed_pre_key_pair: KeyPair, - our_one_time_pre_key_pair: Option, - our_ratchet_key_pair: KeyPair, - their_identity_key: IdentityKey, - their_base_key: PublicKey, - ) -> Self { - Self { - our_identity_key_pair, - our_signed_pre_key_pair, - our_one_time_pre_key_pair, - our_ratchet_key_pair, - their_identity_key, - their_base_key, - } - } - - #[inline] - pub fn our_identity_key_pair(&self) -> &IdentityKeyPair { - &self.our_identity_key_pair - } - - #[inline] - pub fn our_signed_pre_key_pair(&self) -> &KeyPair { - &self.our_signed_pre_key_pair - } - - #[inline] - pub fn our_one_time_pre_key_pair(&self) -> Option<&KeyPair> { - self.our_one_time_pre_key_pair.as_ref() - } - - #[inline] - pub fn our_ratchet_key_pair(&self) -> &KeyPair { - &self.our_ratchet_key_pair - } - - #[inline] - pub fn their_identity_key(&self) -> &IdentityKey { - &self.their_identity_key - } - - #[inline] - pub fn their_base_key(&self) -> &PublicKey { - &self.their_base_key - } -} diff --git a/net/gurk-rs/files/vendor/libsignal-protocol/src/sealed_sender.rs b/net/gurk-rs/files/vendor/libsignal-protocol/src/sealed_sender.rs deleted file mode 100644 index 8cf43bc..0000000 --- a/net/gurk-rs/files/vendor/libsignal-protocol/src/sealed_sender.rs +++ /dev/null @@ -1,1712 +0,0 @@ -// -// Copyright 2020-2021 Signal Messenger, LLC. -// SPDX-License-Identifier: AGPL-3.0-only -// - -use crate::{ - message_encrypt, CiphertextMessageType, Context, Direction, IdentityKey, IdentityKeyPair, - IdentityKeyStore, KeyPair, PreKeySignalMessage, PreKeyStore, PrivateKey, ProtocolAddress, - PublicKey, Result, SessionRecord, SessionStore, SignalMessage, SignalProtocolError, - SignedPreKeyStore, -}; - -use crate::crypto; -use crate::curve; -use crate::proto; -use crate::session_cipher; - -use aes_gcm_siv::aead::{AeadInPlace, NewAead}; -use aes_gcm_siv::Aes256GcmSiv; -use arrayref::array_ref; -use curve25519_dalek::scalar::Scalar; -use prost::Message; -use rand::{CryptoRng, Rng}; -use subtle::ConstantTimeEq; -use uuid::Uuid; - -use proto::sealed_sender::unidentified_sender_message::message::Type as ProtoMessageType; - -use std::convert::{TryFrom, TryInto}; - -#[derive(Debug, Clone)] -pub struct ServerCertificate { - serialized: Vec, - key_id: u32, - key: PublicKey, - certificate: Vec, - signature: Vec, -} - -/* -0xDEADC357 is a server certificate ID which is used to test the -revocation logic. As of this writing, no prod server certificates have -been revoked. If one ever does, add its key ID here. - -If a production server certificate is ever generated which collides -with this test certificate ID, Bad Things will happen. -*/ -const REVOKED_SERVER_CERTIFICATE_KEY_IDS: &[u32] = &[0xDEADC357]; - -impl ServerCertificate { - pub fn deserialize(data: &[u8]) -> Result { - let pb = proto::sealed_sender::ServerCertificate::decode(data)?; - - if pb.certificate.is_none() || pb.signature.is_none() { - return Err(SignalProtocolError::InvalidProtobufEncoding); - } - - let certificate = pb - .certificate - .ok_or(SignalProtocolError::InvalidProtobufEncoding)?; - let signature = pb - .signature - .ok_or(SignalProtocolError::InvalidProtobufEncoding)?; - let certificate_data = - proto::sealed_sender::server_certificate::Certificate::decode(certificate.as_ref())?; - let key = PublicKey::try_from( - &certificate_data - .key - .ok_or(SignalProtocolError::InvalidProtobufEncoding)?[..], - )?; - let key_id = certificate_data - .id - .ok_or(SignalProtocolError::InvalidProtobufEncoding)?; - - Ok(Self { - serialized: data.to_vec(), - certificate, - signature, - key, - key_id, - }) - } - - pub fn new( - key_id: u32, - key: PublicKey, - trust_root: &PrivateKey, - rng: &mut R, - ) -> Result { - let certificate_pb = proto::sealed_sender::server_certificate::Certificate { - id: Some(key_id), - key: Some(key.serialize().to_vec()), - }; - - let certificate = certificate_pb.encode_to_vec(); - - let signature = trust_root.calculate_signature(&certificate, rng)?.to_vec(); - - let serialized = proto::sealed_sender::ServerCertificate { - certificate: Some(certificate.clone()), - signature: Some(signature.clone()), - } - .encode_to_vec(); - - Ok(Self { - serialized, - certificate, - signature, - key, - key_id, - }) - } - - pub(crate) fn to_protobuf(&self) -> Result { - Ok(proto::sealed_sender::ServerCertificate { - certificate: Some(self.certificate.clone()), - signature: Some(self.signature.clone()), - }) - } - - pub fn validate(&self, trust_root: &PublicKey) -> Result { - if REVOKED_SERVER_CERTIFICATE_KEY_IDS.contains(&self.key_id()?) { - log::error!( - "received server certificate with revoked ID {:x}", - self.key_id()? - ); - return Ok(false); - } - trust_root.verify_signature(&self.certificate, &self.signature) - } - - pub fn key_id(&self) -> Result { - Ok(self.key_id) - } - - pub fn public_key(&self) -> Result { - Ok(self.key) - } - - pub fn certificate(&self) -> Result<&[u8]> { - Ok(&self.certificate) - } - - pub fn signature(&self) -> Result<&[u8]> { - Ok(&self.signature) - } - - pub fn serialized(&self) -> Result<&[u8]> { - Ok(&self.serialized) - } -} - -#[derive(Debug, Clone)] -pub struct SenderCertificate { - signer: ServerCertificate, - key: PublicKey, - sender_device_id: u32, - sender_uuid: String, - sender_e164: Option, - expiration: u64, - serialized: Vec, - certificate: Vec, - signature: Vec, -} - -impl SenderCertificate { - pub fn deserialize(data: &[u8]) -> Result { - let pb = proto::sealed_sender::SenderCertificate::decode(data)?; - let certificate = pb - .certificate - .ok_or(SignalProtocolError::InvalidProtobufEncoding)?; - let signature = pb - .signature - .ok_or(SignalProtocolError::InvalidProtobufEncoding)?; - let certificate_data = - proto::sealed_sender::sender_certificate::Certificate::decode(certificate.as_ref())?; - - let sender_device_id = certificate_data - .sender_device - .ok_or(SignalProtocolError::InvalidProtobufEncoding)?; - let expiration = certificate_data - .expires - .ok_or(SignalProtocolError::InvalidProtobufEncoding)?; - let signer_pb = certificate_data - .signer - .ok_or(SignalProtocolError::InvalidProtobufEncoding)?; - let sender_uuid = certificate_data - .sender_uuid - .ok_or(SignalProtocolError::InvalidProtobufEncoding)?; - let sender_e164 = certificate_data.sender_e164; - - let key = PublicKey::try_from( - &certificate_data - .identity_key - .ok_or(SignalProtocolError::InvalidProtobufEncoding)?[..], - )?; - - let signer_bits = signer_pb.encode_to_vec(); - let signer = ServerCertificate::deserialize(&signer_bits)?; - - Ok(Self { - signer, - key, - sender_device_id, - sender_uuid, - sender_e164, - expiration, - serialized: data.to_vec(), - certificate, - signature, - }) - } - - pub fn new( - sender_uuid: String, - sender_e164: Option, - key: PublicKey, - sender_device_id: u32, - expiration: u64, - signer: ServerCertificate, - signer_key: &PrivateKey, - rng: &mut R, - ) -> Result { - let certificate_pb = proto::sealed_sender::sender_certificate::Certificate { - sender_uuid: Some(sender_uuid.clone()), - sender_e164: sender_e164.clone(), - sender_device: Some(sender_device_id), - expires: Some(expiration), - identity_key: Some(key.serialize().to_vec()), - signer: Some(signer.to_protobuf()?), - }; - - let certificate = certificate_pb.encode_to_vec(); - - let signature = signer_key.calculate_signature(&certificate, rng)?.to_vec(); - - let serialized = proto::sealed_sender::SenderCertificate { - certificate: Some(certificate.clone()), - signature: Some(signature.clone()), - } - .encode_to_vec(); - - Ok(Self { - signer, - key, - sender_device_id, - sender_uuid, - sender_e164, - expiration, - serialized, - certificate, - signature, - }) - } - - pub(crate) fn from_protobuf(pb: &proto::sealed_sender::SenderCertificate) -> Result { - let mut bits = vec![]; - pb.encode(&mut bits)?; - Self::deserialize(&bits) - } - - pub(crate) fn to_protobuf(&self) -> Result { - Ok(proto::sealed_sender::SenderCertificate { - certificate: Some(self.certificate.clone()), - signature: Some(self.signature.clone()), - }) - } - - pub fn validate(&self, trust_root: &PublicKey, validation_time: u64) -> Result { - if !self.signer.validate(trust_root)? { - log::error!("received server certificate not signed by trust root"); - return Ok(false); - } - - if !self - .signer - .public_key()? - .verify_signature(&self.certificate, &self.signature)? - { - log::error!("received sender certificate not signed by server"); - return Ok(false); - } - - if validation_time > self.expiration { - log::error!( - "received expired sender certificate (expiration: {}, validation_time: {})", - self.expiration, - validation_time - ); - return Ok(false); - } - - Ok(true) - } - - pub fn signer(&self) -> Result<&ServerCertificate> { - Ok(&self.signer) - } - - pub fn key(&self) -> Result { - Ok(self.key) - } - - pub fn sender_device_id(&self) -> Result { - Ok(self.sender_device_id) - } - - pub fn sender_uuid(&self) -> Result<&str> { - Ok(&self.sender_uuid) - } - - pub fn sender_e164(&self) -> Result> { - Ok(self.sender_e164.as_deref()) - } - - pub fn expiration(&self) -> Result { - Ok(self.expiration) - } - - pub fn serialized(&self) -> Result<&[u8]> { - Ok(&self.serialized) - } - - pub fn certificate(&self) -> Result<&[u8]> { - Ok(&self.certificate) - } - - pub fn signature(&self) -> Result<&[u8]> { - Ok(&self.signature) - } -} - -impl From for CiphertextMessageType { - fn from(message_type: ProtoMessageType) -> Self { - let result = match message_type { - ProtoMessageType::Message => Self::Whisper, - ProtoMessageType::PrekeyMessage => Self::PreKey, - ProtoMessageType::SenderkeyMessage => Self::SenderKey, - ProtoMessageType::PlaintextContent => Self::Plaintext, - }; - // Keep raw values in sync from now on, for efficient codegen. - assert!(result == Self::PreKey || message_type as i32 == result as i32); - result - } -} - -impl From for ProtoMessageType { - fn from(message_type: CiphertextMessageType) -> Self { - let result = match message_type { - CiphertextMessageType::PreKey => Self::PrekeyMessage, - CiphertextMessageType::Whisper => Self::Message, - CiphertextMessageType::SenderKey => Self::SenderkeyMessage, - CiphertextMessageType::Plaintext => Self::PlaintextContent, - }; - // Keep raw values in sync from now on, for efficient codegen. - assert!(result == Self::PrekeyMessage || message_type as i32 == result as i32); - result - } -} - -#[derive(Clone, Copy, PartialEq, Eq, Debug)] -pub enum ContentHint { - Default, - Resendable, - Implicit, - Unknown(u32), -} - -impl ContentHint { - fn to_proto(self) -> Option { - if self == ContentHint::Default { - None - } else { - Some(u32::from(self) as i32) - } - } - - pub const fn to_u32(self) -> u32 { - use proto::sealed_sender::unidentified_sender_message::message::ContentHint as ProtoContentHint; - match self { - ContentHint::Default => 0, - ContentHint::Resendable => ProtoContentHint::Resendable as u32, - ContentHint::Implicit => ProtoContentHint::Implicit as u32, - ContentHint::Unknown(value) => value, - } - } -} - -impl From for ContentHint { - fn from(raw_value: u32) -> Self { - use proto::sealed_sender::unidentified_sender_message::message::ContentHint as ProtoContentHint; - assert!(!ProtoContentHint::is_valid(0)); - match ProtoContentHint::from_i32(raw_value as i32) { - None if raw_value == 0 => ContentHint::Default, - None => ContentHint::Unknown(raw_value), - Some(ProtoContentHint::Resendable) => ContentHint::Resendable, - Some(ProtoContentHint::Implicit) => ContentHint::Implicit, - } - } -} - -impl From for u32 { - fn from(hint: ContentHint) -> Self { - hint.to_u32() - } -} -pub struct UnidentifiedSenderMessageContent { - serialized: Vec, - contents: Vec, - sender: SenderCertificate, - msg_type: CiphertextMessageType, - content_hint: ContentHint, - group_id: Option>, -} - -impl UnidentifiedSenderMessageContent { - pub fn deserialize(data: &[u8]) -> Result { - let pb = proto::sealed_sender::unidentified_sender_message::Message::decode(data)?; - - let msg_type = pb - .r#type - .and_then(ProtoMessageType::from_i32) - .map(CiphertextMessageType::from) - .ok_or(SignalProtocolError::InvalidProtobufEncoding)?; - let sender = pb - .sender_certificate - .ok_or(SignalProtocolError::InvalidProtobufEncoding)?; - let contents = pb - .content - .ok_or(SignalProtocolError::InvalidProtobufEncoding)?; - let content_hint = pb - .content_hint - .map(|raw| ContentHint::from(raw as u32)) - .unwrap_or(ContentHint::Default); - let group_id = pb.group_id; - - let sender = SenderCertificate::from_protobuf(&sender)?; - - let serialized = data.to_vec(); - - log::info!( - "deserialized UnidentifiedSenderMessageContent from {}.{} with type {:?}", - sender.sender_uuid()?, - sender.sender_device_id()?, - msg_type, - ); - - Ok(Self { - serialized, - contents, - sender, - msg_type, - content_hint, - group_id, - }) - } - - pub fn new( - msg_type: CiphertextMessageType, - sender: SenderCertificate, - contents: Vec, - content_hint: ContentHint, - group_id: Option>, - ) -> Result { - let proto_msg_type = ProtoMessageType::from(msg_type); - let msg = proto::sealed_sender::unidentified_sender_message::Message { - content: Some(contents.clone()), - r#type: Some(proto_msg_type.into()), - sender_certificate: Some(sender.to_protobuf()?), - content_hint: content_hint.to_proto(), - group_id: group_id.as_ref().and_then(|buf| { - if buf.is_empty() { - None - } else { - Some(buf.clone()) - } - }), - }; - - let serialized = msg.encode_to_vec(); - - Ok(Self { - serialized, - msg_type, - sender, - contents, - content_hint, - group_id, - }) - } - - pub fn msg_type(&self) -> Result { - Ok(self.msg_type) - } - - pub fn sender(&self) -> Result<&SenderCertificate> { - Ok(&self.sender) - } - - pub fn contents(&self) -> Result<&[u8]> { - Ok(&self.contents) - } - - pub fn content_hint(&self) -> Result { - Ok(self.content_hint) - } - - pub fn group_id(&self) -> Result> { - Ok(self.group_id.as_deref()) - } - - pub fn serialized(&self) -> Result<&[u8]> { - Ok(&self.serialized) - } -} - -enum UnidentifiedSenderMessage { - V1 { - ephemeral_public: PublicKey, - encrypted_static: Vec, - encrypted_message: Vec, - }, - V2 { - ephemeral_public: PublicKey, - encrypted_message_key: Box<[u8]>, - authentication_tag: Box<[u8]>, - encrypted_message: Box<[u8]>, - }, -} - -const SEALED_SENDER_V1_VERSION: u8 = 1; -const SEALED_SENDER_V2_VERSION: u8 = 2; - -impl UnidentifiedSenderMessage { - fn deserialize(data: &[u8]) -> Result { - if data.is_empty() { - return Err(SignalProtocolError::InvalidSealedSenderMessage( - "Message was empty".to_owned(), - )); - } - let version = data[0] >> 4; - log::debug!( - "deserializing UnidentifiedSenderMessage with version {}", - version - ); - - match version { - 0 | SEALED_SENDER_V1_VERSION => { - // XXX should we really be accepted version == 0 here? - let pb = proto::sealed_sender::UnidentifiedSenderMessage::decode(&data[1..])?; - - let ephemeral_public = pb - .ephemeral_public - .ok_or(SignalProtocolError::InvalidProtobufEncoding)?; - let encrypted_static = pb - .encrypted_static - .ok_or(SignalProtocolError::InvalidProtobufEncoding)?; - let encrypted_message = pb - .encrypted_message - .ok_or(SignalProtocolError::InvalidProtobufEncoding)?; - - let ephemeral_public = PublicKey::try_from(&ephemeral_public[..])?; - - Ok(Self::V1 { - ephemeral_public, - encrypted_static, - encrypted_message, - }) - } - SEALED_SENDER_V2_VERSION => { - // Uses a flat representation: C || AT || E.pub || ciphertext - let remaining = &data[1..]; - if remaining.len() - < sealed_sender_v2::MESSAGE_KEY_LEN - + sealed_sender_v2::AUTH_TAG_LEN - + curve::curve25519::PUBLIC_KEY_LENGTH - { - return Err(SignalProtocolError::InvalidProtobufEncoding); - } - let (encrypted_message_key, remaining) = - remaining.split_at(sealed_sender_v2::MESSAGE_KEY_LEN); - let (encrypted_authentication_tag, remaining) = - remaining.split_at(sealed_sender_v2::AUTH_TAG_LEN); - let (ephemeral_public, encrypted_message) = - remaining.split_at(curve::curve25519::PUBLIC_KEY_LENGTH); - - Ok(Self::V2 { - ephemeral_public: PublicKey::from_djb_public_key_bytes(ephemeral_public)?, - encrypted_message_key: encrypted_message_key.into(), - authentication_tag: encrypted_authentication_tag.into(), - encrypted_message: encrypted_message.into(), - }) - } - _ => Err(SignalProtocolError::UnknownSealedSenderVersion(version)), - } - } -} - -mod sealed_sender_v1 { - use super::*; - - #[cfg(test)] - use std::fmt; - - /// A symmetric cipher key and a MAC key, along with a "chain key" consumed in - /// [`StaticKeys::calculate`]. - pub(super) struct EphemeralKeys { - pub(super) chain_key: [u8; 32], - pub(super) cipher_key: [u8; 32], - pub(super) mac_key: [u8; 32], - } - - const SALT_PREFIX: &[u8] = b"UnidentifiedDelivery"; - const EPHEMERAL_KEYS_KDF_LEN: usize = 96; - - impl EphemeralKeys { - /// Derive a set of symmetric keys from the key agreement between the sender and - /// recipient's identities. - pub(super) fn calculate( - our_keys: &KeyPair, - their_public: &PublicKey, - direction: Direction, - ) -> Result { - let our_pub_key = our_keys.public_key.serialize(); - let their_pub_key = their_public.serialize(); - let ephemeral_salt = match direction { - Direction::Sending => [SALT_PREFIX, &their_pub_key, &our_pub_key], - Direction::Receiving => [SALT_PREFIX, &our_pub_key, &their_pub_key], - } - .concat(); - - let shared_secret = our_keys.private_key.calculate_agreement(their_public)?; - let mut derived_values = [0; EPHEMERAL_KEYS_KDF_LEN]; - hkdf::Hkdf::::new(Some(&ephemeral_salt), &shared_secret) - .expand(&[], &mut derived_values) - .expect("valid output length"); - - Ok(Self { - chain_key: *array_ref![&derived_values, 0, 32], - cipher_key: *array_ref![&derived_values, 32, 32], - mac_key: *array_ref![&derived_values, 64, 32], - }) - } - } - - #[cfg(test)] - impl PartialEq for EphemeralKeys { - fn eq(&self, other: &Self) -> bool { - self.chain_key == other.chain_key - && self.cipher_key == other.cipher_key - && self.mac_key == other.mac_key - } - } - - #[cfg(test)] - impl Eq for EphemeralKeys {} - - #[cfg(test)] - impl fmt::Debug for EphemeralKeys { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!( - f, - "EphemeralKeys {{ chain_key: {:?}, cipher_key: {:?}, mac_key: {:?} }}", - self.chain_key, self.cipher_key, self.mac_key - ) - } - } - - /// A symmetric cipher key and a MAC key. - pub(super) struct StaticKeys { - pub(super) cipher_key: [u8; 32], - pub(super) mac_key: [u8; 32], - } - - impl StaticKeys { - /// Derive a set of symmetric keys from the agreement between the sender and - /// recipient's identities, as well as [`EphemeralKeys::chain_key`]. - pub(super) fn calculate( - our_keys: &IdentityKeyPair, - their_key: &PublicKey, - chain_key: &[u8; 32], - ctext: &[u8], - ) -> Result { - let salt = [chain_key, ctext].concat(); - - let shared_secret = our_keys.private_key().calculate_agreement(their_key)?; - // 96 bytes are derived, but the first 32 are discarded/unused. This is intended to - // mirror the way the EphemeralKeys are derived, even though StaticKeys does not end up - // requiring a third "chain key". - let mut derived_values = [0; 96]; - hkdf::Hkdf::::new(Some(&salt), &shared_secret) - .expand(&[], &mut derived_values) - .expect("valid output length"); - - Ok(Self { - cipher_key: *array_ref![&derived_values, 32, 32], - mac_key: *array_ref![&derived_values, 64, 32], - }) - } - } - - #[test] - fn test_agreement_and_authentication() -> Result<()> { - // The sender and recipient each have a long-term identity key pair. - let sender_identity = IdentityKeyPair::generate(&mut rand::thread_rng()); - let recipient_identity = IdentityKeyPair::generate(&mut rand::thread_rng()); - - // Generate an ephemeral key pair. - let sender_ephemeral = KeyPair::generate(&mut rand::thread_rng()); - let ephemeral_public = sender_ephemeral.public_key; - // Generate ephemeral cipher, chain, and MAC keys. - let sender_eph_keys = EphemeralKeys::calculate( - &sender_ephemeral, - recipient_identity.public_key(), - Direction::Sending, - )?; - - // Encrypt the sender's public key with AES-256 CTR and a MAC. - let sender_static_key_ctext = crypto::aes256_ctr_hmacsha256_encrypt( - &sender_identity.public_key().serialize(), - &sender_eph_keys.cipher_key, - &sender_eph_keys.mac_key, - )?; - - // Generate another cipher and MAC key. - let sender_static_keys = StaticKeys::calculate( - &sender_identity, - recipient_identity.public_key(), - &sender_eph_keys.chain_key, - &sender_static_key_ctext, - )?; - - let sender_message_contents = b"this is a binary message"; - let sender_message_data = crypto::aes256_ctr_hmacsha256_encrypt( - sender_message_contents, - &sender_static_keys.cipher_key, - &sender_static_keys.mac_key, - )?; - - // The message recipient calculates the ephemeral key and the sender's public key. - let recipient_eph_keys = EphemeralKeys::calculate( - &recipient_identity.into(), - &ephemeral_public, - Direction::Receiving, - )?; - assert_eq!(sender_eph_keys, recipient_eph_keys); - - let recipient_message_key_bytes = crypto::aes256_ctr_hmacsha256_decrypt( - &sender_static_key_ctext, - &recipient_eph_keys.cipher_key, - &recipient_eph_keys.mac_key, - )?; - let sender_public_key: PublicKey = PublicKey::try_from(&recipient_message_key_bytes[..])?; - assert_eq!(sender_identity.public_key(), &sender_public_key); - - let recipient_static_keys = StaticKeys::calculate( - &recipient_identity, - &sender_public_key, - &recipient_eph_keys.chain_key, - &sender_static_key_ctext, - )?; - - let recipient_message_contents = crypto::aes256_ctr_hmacsha256_decrypt( - &sender_message_data, - &recipient_static_keys.cipher_key, - &recipient_static_keys.mac_key, - )?; - assert_eq!(recipient_message_contents, sender_message_contents); - - Ok(()) - } -} - -/// Encrypt the plaintext message `ptext`, generate an [`UnidentifiedSenderMessageContent`], then -/// pass the result to [`sealed_sender_encrypt_from_usmc`]. -/// -/// This is a simple way to encrypt a message in a 1:1 using [Sealed Sender v1]. -/// -/// [Sealed Sender v1]: sealed_sender_encrypt_from_usmc -pub async fn sealed_sender_encrypt( - destination: &ProtocolAddress, - sender_cert: &SenderCertificate, - ptext: &[u8], - session_store: &mut dyn SessionStore, - identity_store: &mut dyn IdentityKeyStore, - ctx: Context, - rng: &mut R, -) -> Result> { - let message = message_encrypt(ptext, destination, session_store, identity_store, ctx).await?; - let usmc = UnidentifiedSenderMessageContent::new( - message.message_type(), - sender_cert.clone(), - message.serialize().to_vec(), - ContentHint::Default, - None, - )?; - sealed_sender_encrypt_from_usmc(destination, &usmc, identity_store, ctx, rng).await -} - -/// This method implements the single-key single-recipient [KEM] described in [this Signal blog -/// post], a.k.a. Sealed Sender v1. -/// -/// [KEM]: https://en.wikipedia.org/wiki/Key_encapsulation -/// [this Signal blog post]: https://signal.org/blog/sealed-sender/ -/// -/// [`sealed_sender_decrypt`] is used in the client to decrypt the Sealed Sender message produced by -/// this method. -/// -/// # Contrast with Sealed Sender v2 -/// The *single-recipient* KEM scheme implemented by this method partially derives the encryption -/// key from the recipient's identity key, which would then require re-encrypting the same message -/// multiple times to send to multiple recipients. In contrast, -/// [Sealed Sender v2](sealed_sender_multi_recipient_encrypt) uses a *multi-recipient* KEM scheme -/// which avoids this repeated work, but makes a few additional design tradeoffs. -/// -/// # High-level algorithmic overview -/// The KEM scheme implemented by this method is described in [this Signal blog post]. The -/// high-level steps of this process are listed below: -/// 1. Generate a random key pair. -/// 2. Derive a symmetric chain key, cipher key, and MAC key from the recipient's public key and the -/// sender's public/private key pair. -/// 3. Symmetrically encrypt the sender's public key using the cipher key and MAC key from (2) with -/// AES-256 in CTR mode. -/// 4. Derive a second symmetric cipher key and MAC key from the sender's private key, the -/// recipient's public key, and the chain key from (2). -/// 5. Symmetrically encrypt the underlying [`UnidentifiedSenderMessageContent`] using the cipher key -/// and MAC key from (4) with AES-256 in CTR mode. -/// 6. Send the ephemeral public key from (1) and the encrypted public key from (3) to the -/// recipient, along with the encrypted message (5). -/// -/// ## Pseudocode -///```text -/// e_pub, e_priv = X25519.generateEphemeral() -/// e_chain, e_cipherKey, e_macKey = HKDF(salt="UnidentifiedDelivery" || recipientIdentityPublic || e_pub, ikm=ECDH(recipientIdentityPublic, e_priv), info="") -/// e_ciphertext = AES_CTR(key=e_cipherKey, input=senderIdentityPublic) -/// e_mac = Hmac256(key=e_macKey, input=e_ciphertext) -/// -/// s_cipherKey, s_macKey = HKDF(salt=e_chain || e_ciphertext || e_mac, ikm=ECDH(recipientIdentityPublic, senderIdentityPrivate), info="") -/// s_ciphertext = AES_CTR(key=s_cipherKey, input=sender_certificate || message_ciphertext) -/// s_mac = Hmac256(key=s_macKey, input=s_ciphertext) -/// -/// message_to_send = s_ciphertext || s_mac -///``` -/// -/// # Wire Format -/// The output of this method is encoded as an `UnidentifiedSenderMessage.Message` from -/// `sealed_sender.proto`, prepended with an additional byte to indicate the version of Sealed -/// Sender in use (see [further documentation on the version -/// byte](sealed_sender_multi_recipient_encrypt#the-version-byte)). -pub async fn sealed_sender_encrypt_from_usmc( - destination: &ProtocolAddress, - usmc: &UnidentifiedSenderMessageContent, - identity_store: &mut dyn IdentityKeyStore, - ctx: Context, - rng: &mut R, -) -> Result> { - let our_identity = identity_store.get_identity_key_pair(ctx).await?; - let their_identity = identity_store - .get_identity(destination, ctx) - .await? - .ok_or_else(|| SignalProtocolError::SessionNotFound(format!("{}", destination)))?; - - let ephemeral = KeyPair::generate(rng); - - let eph_keys = sealed_sender_v1::EphemeralKeys::calculate( - &ephemeral, - their_identity.public_key(), - Direction::Sending, - )?; - - let static_key_ctext = crypto::aes256_ctr_hmacsha256_encrypt( - &our_identity.public_key().serialize(), - &eph_keys.cipher_key, - &eph_keys.mac_key, - )?; - - let static_keys = sealed_sender_v1::StaticKeys::calculate( - &our_identity, - their_identity.public_key(), - &eph_keys.chain_key, - &static_key_ctext, - )?; - - let message_data = crypto::aes256_ctr_hmacsha256_encrypt( - usmc.serialized()?, - &static_keys.cipher_key, - &static_keys.mac_key, - )?; - - let version = SEALED_SENDER_V1_VERSION; - let mut serialized = vec![version | (version << 4)]; - let pb = proto::sealed_sender::UnidentifiedSenderMessage { - ephemeral_public: Some(ephemeral.public_key.serialize().to_vec()), - encrypted_static: Some(static_key_ctext), - encrypted_message: Some(message_data), - }; - pb.encode(&mut serialized)?; // appends to buffer - - Ok(serialized) -} - -mod sealed_sender_v2 { - use super::*; - - // Static byte strings used as part of a MAC in HKDF. - const LABEL_R: &[u8] = b"Sealed Sender v2: r"; - const LABEL_K: &[u8] = b"Sealed Sender v2: K"; - const LABEL_DH: &[u8] = b"Sealed Sender v2: DH"; - const LABEL_DH_S: &[u8] = b"Sealed Sender v2: DH-sender"; - - pub const MESSAGE_KEY_LEN: usize = 32; - pub const AUTH_TAG_LEN: usize = 16; - - /// An asymmetric and a symmetric cipher key. - pub(super) struct DerivedKeys { - /// Asymmetric key pair. - pub(super) e: KeyPair, - /// Symmetric key used to instantiate [`Aes256GcmSiv::new_from_slice`]. - pub(super) k: [u8; MESSAGE_KEY_LEN], - } - - impl DerivedKeys { - /// Derive a set of ephemeral keys from a slice of random bytes `m`. - pub(super) fn calculate(m: &[u8]) -> DerivedKeys { - let kdf = hkdf::Hkdf::::new(None, m); - let mut r = [0; 64]; - kdf.expand(LABEL_R, &mut r).expect("valid output length"); - let mut k = [0; MESSAGE_KEY_LEN]; - kdf.expand(LABEL_K, &mut k).expect("valid output length"); - let e_raw = Scalar::from_bytes_mod_order_wide(&r); - let e = PrivateKey::try_from(&e_raw.as_bytes()[..]).expect("valid PrivateKey"); - let e = KeyPair::try_from(e).expect("can derive public key"); - DerivedKeys { e, k } - } - } - - /// Encrypt or decrypt a slice of random bytes `input` using a shared secret derived from - /// `our_keys` and `their_key`. - /// - /// The output of this method when called with [`Direction::Sending`] can be inverted to produce - /// the original `input` bytes if called with [`Direction::Receiving`] with `our_keys` and - /// `their_key` swapped. - pub(super) fn apply_agreement_xor( - our_keys: &KeyPair, - their_key: &PublicKey, - direction: Direction, - input: &[u8; MESSAGE_KEY_LEN], - ) -> Result<[u8; MESSAGE_KEY_LEN]> { - let agreement = our_keys.calculate_agreement(their_key)?; - let agreement_key_input = match direction { - Direction::Sending => [ - agreement, - our_keys.public_key.serialize(), - their_key.serialize(), - ], - Direction::Receiving => [ - agreement, - their_key.serialize(), - our_keys.public_key.serialize(), - ], - } - .concat(); - - let mut result = [0; MESSAGE_KEY_LEN]; - hkdf::Hkdf::::new(None, &agreement_key_input) - .expand(LABEL_DH, &mut result) - .expect("valid output length"); - result - .iter_mut() - .zip(input) - .for_each(|(result_byte, input_byte)| *result_byte ^= input_byte); - Ok(result) - } - - /// Compute an [authentication tag] for the bytes `encrypted_message_key` using a shared secret - /// derived from `our_keys` and `their_key`. - /// - /// [authentication tag]: https://en.wikipedia.org/wiki/Message_authentication_code - /// - /// The output of this method with [`Direction::Sending`] should be the same bytes produced by - /// calling this method with [`Direction::Receiving`] with `our_keys` and `their_key` - /// swapped, if `ephemeral_pub_key` and `encrypted_message_key` are the same. - pub(super) fn compute_authentication_tag( - our_keys: &IdentityKeyPair, - their_key: &IdentityKey, - direction: Direction, - ephemeral_pub_key: &PublicKey, - encrypted_message_key: &[u8; MESSAGE_KEY_LEN], - ) -> Result<[u8; AUTH_TAG_LEN]> { - let agreement = our_keys - .private_key() - .calculate_agreement(their_key.public_key())?; - let mut agreement_key_input = agreement.into_vec(); - agreement_key_input.extend_from_slice(&ephemeral_pub_key.serialize()); - agreement_key_input.extend_from_slice(encrypted_message_key); - match direction { - Direction::Sending => { - agreement_key_input.extend_from_slice(&our_keys.public_key().serialize()); - agreement_key_input.extend_from_slice(&their_key.serialize()); - } - Direction::Receiving => { - agreement_key_input.extend_from_slice(&their_key.serialize()); - agreement_key_input.extend_from_slice(&our_keys.public_key().serialize()); - } - } - - let mut result = [0; AUTH_TAG_LEN]; - hkdf::Hkdf::::new(None, &agreement_key_input) - .expand(LABEL_DH_S, &mut result) - .expect("valid output length"); - Ok(result) - } - - #[test] - fn test_agreement_and_authentication() -> Result<()> { - // The sender and recipient each have a long-term identity key pair. - let sender_identity = IdentityKeyPair::generate(&mut rand::thread_rng()); - let recipient_identity = IdentityKeyPair::generate(&mut rand::thread_rng()); - - // Generate random bytes used for our multi-recipient encoding scheme. - let m: [u8; MESSAGE_KEY_LEN] = rand::thread_rng().gen(); - // Derive an ephemeral key pair from those random bytes. - let ephemeral_keys = DerivedKeys::calculate(&m); - let ephemeral_public_key = ephemeral_keys.e.public_key; - - // Encrypt the ephemeral key pair. - let sender_c_0: [u8; MESSAGE_KEY_LEN] = apply_agreement_xor( - &ephemeral_keys.e, - recipient_identity.public_key(), - Direction::Sending, - &m, - )?; - // Compute an authentication tag for the encrypted key pair. - let sender_at_0 = compute_authentication_tag( - &sender_identity, - recipient_identity.identity_key(), - Direction::Sending, - &ephemeral_public_key, - &sender_c_0, - )?; - - // The message recipient calculates the original random bytes and authenticates the result. - let recv_m = apply_agreement_xor( - &recipient_identity.into(), - &ephemeral_public_key, - Direction::Receiving, - &sender_c_0, - )?; - assert_eq!(&recv_m, &m); - - let recv_at_0 = compute_authentication_tag( - &recipient_identity, - sender_identity.identity_key(), - Direction::Receiving, - &ephemeral_public_key, - &sender_c_0, - )?; - assert_eq!(&recv_at_0, &sender_at_0); - - Ok(()) - } -} - -/// This method implements a single-key multi-recipient [KEM] as defined in Manuel Barbosa's -/// ["Randomness Reuse: Extensions and Improvements"], a.k.a. Sealed Sender v2. -/// -/// [KEM]: https://en.wikipedia.org/wiki/Key_encapsulation -/// ["Randomness Reuse: Extensions and Improvements"]: https://haslab.uminho.pt/mbb/files/reuse.pdf -/// -/// # Contrast with Sealed Sender v1 -/// The KEM scheme implemented by this method uses the "Generic Construction" in `4.1` of [Barbosa's -/// paper]["Randomness Reuse: Extensions and Improvements"], instantiated with [ElGamal -/// encryption]. This technique enables reusing a single sequence of random bytes across multiple -/// messages with the same content, which reduces computation time for clients sending the same -/// message to multiple recipients (without compromising the message security). -/// -/// There are a few additional design tradeoffs this method makes vs [Sealed Sender v1] -/// which may make it comparatively unwieldy for certain scenarios: -/// 1. it requires a [`SessionRecord`] to exist already for the recipient, i.e. that a Double -/// Ratchet message chain has previously been established in the [`SessionStore`] via -/// [`process_prekey_bundle`][crate::process_prekey_bundle] after an initial -/// [`PreKeySignalMessage`][crate::PreKeySignalMessage] is received. -/// 2. it ferries a lot of additional information in its encoding which makes the resulting message -/// bulkier than the message produced by [Sealed Sender v1]. For sending, this will generally -/// still be more compact than sending the same message N times, but on the receiver side the -/// message is slightly larger. -/// 3. unlike other message types sent over the wire, the encoded message returned by this method -/// does not use protobuf, in order to avoid inefficiencies produced by protobuf's packing (see -/// **[Wire Format]**). -/// -/// [ElGamal encryption]: https://en.wikipedia.org/wiki/ElGamal_encryption -/// [Sealed Sender v1]: sealed_sender_encrypt_from_usmc -/// [Wire Format]: #wire-format -/// -/// # High-level algorithmic overview -/// The high-level steps of this process are summarized below: -/// 1. Generate a series of random bytes. -/// 2. Derive an ephemeral key pair from (1). -/// 3. *Once per recipient:* Encrypt (1) using a shared secret derived from the private ephemeral -/// key (2) and the recipient's public identity key. -/// 4. *Once per recipient:* Add an authentication tag for (3) using a secret derived from the -/// sender's private identity key and the recipient's public identity key. -/// 5. Generate a symmetric key from (1) and use it to symmetrically encrypt the underlying -/// [`UnidentifiedSenderMessageContent`] via [AEAD encryption]. *This step is only performed once -/// per message, regardless of the number of recipients.* -/// 6. Send the public ephemeral key (2) to the server, along with the sequence of encrypted random -/// bytes (3) and authentication tags (4), and the single encrypted message (5). -/// -/// [AEAD encryption]: https://en.wikipedia.org/wiki/Authenticated_encryption#Authenticated_encryption_with_associated_data_(AEAD) -/// -/// ## Pseudocode -///```text -/// ENCRYPT(message, R_i): -/// M = Random(32) -/// r = KDF(label_r, M, len=64) -/// K = KDF(label_K, M, len=32) -/// E = DeriveKeyPair(r) -/// for i in num_recipients: -/// C_i = KDF(label_DH, DH(E, R_i) || E.public || R_i.public, len=32) XOR M -/// AT_i = KDF(label_DH_s, DH(S, R_i) || E.public || C_i || S.public || R_i.public, len=16) -/// ciphertext = AEAD_Encrypt(K, message) -/// return E.public, C_i, AT_i, ciphertext -/// -/// DECRYPT(E.public, C, AT, ciphertext): -/// M = KDF(label_DH, DH(E, R) || E.public || R.public, len=32) xor C -/// r = KDF(label_r, M, len=64) -/// K = KDF(label_K, M, len=32) -/// E' = DeriveKeyPair(r) -/// if E.public != E'.public: -/// return DecryptionError -/// message = AEAD_Decrypt(K, ciphertext) // includes S.public -/// AT' = KDF(label_DH_s, DH(S, R) || E.public || C || S.public || R.public, len=16) -/// if AT != AT': -/// return DecryptionError -/// return message -///``` -/// -/// # Routing messages to recipients -/// -/// The server will split up the set of messages and securely route each individual [received -/// message][receiving] to its intended recipient. -/// -/// For testing purposes, [`sealed_sender_multi_recipient_fan_out`] can be used to convert such -/// a bulk message produced by Sealed Sender v2 into a sequence of [received messages][receiving]; -/// however, in doing so it will drop all of the metadata necessary to identify the message's -/// intended recipients. -/// -/// # Wire Format -/// Multi-recipient sealed-sender does not use protobufs for its payload format. Instead, it uses -/// a flat format marked with a [version byte](#the-version-byte). The format is different for -/// [sending] and [receiving]. The decrypted content is -/// a protobuf-encoded `UnidentifiedSenderMessage.Message` from `sealed_sender.proto`. -/// -/// The public key used in Sealed Sender v2 is always a Curve25519 DJB key. -/// -/// [sending]: #sent-messages -/// [receiving]: #received-messages -/// -/// ## The version byte -/// -/// Sealed sender messages (v1 and v2) in serialized form begin with a version [byte][u8]. -/// This byte has the form: -/// -/// ```text -/// (requiredVersion << 4) | currentVersion -/// ``` -/// -/// v1 messages thus have a version byte of `0x11`. v2 messages have a version byte -/// of `0x22`. A hypothetical version byte `0x34` would indicate a message encoded -/// as Sealed Sender v4, but decodable by any client that supports Sealed Sender v3. -/// -/// ## Received messages -/// -/// ```text -/// ReceivedMessage { -/// version_byte: u8, -/// c: [u8; 32], -/// at: [u8; 16], -/// e_pub: [u8; 32], -/// message: [u8] // remaining bytes -/// } -/// ``` -/// -/// Each individual Sealed Sender message received from the server is decoded in the Signal -/// client by calling [`sealed_sender_decrypt`]. -/// -/// ## Sent messages -/// -/// ```text -/// PerRecipientData { -/// uuid: [u8; 16], -/// device_id: varint, -/// registration_id: u16, -/// c: [u8; 32], -/// at: [u8; 16], -/// } -/// -/// SentMessage { -/// version_byte: u8, -/// count: varint, -/// recipients: [PerRecipientData; count], -/// e_pub: [u8; 32], -/// message: [u8] // remaining bytes -/// } -/// ``` -/// -/// The varint encoding used is the same as [protobuf's][varint]. Values are unsigned. UUIDs are -/// encoded per [RFC 4122], with the first eight bytes considered "most significant". [^1] -/// Fixed-width integers are unaligned and in network byte order (big-endian). -/// -/// [varint]: https://developers.google.com/protocol-buffers/docs/encoding#varints -/// [RFC 4122]: https://tools.ietf.org/html/rfc4122#section-4.1.2 -/// -/// [^1]: RFC 4122 guarantees the encoding order of the fields in a -/// UUID, but the representation of each field may vary based on the UUID's -/// "variant". For Sealed Sender's purposes, this is not important except for -/// debug-printing, since UUIDs are always treated as opaque identifiers matched -/// byte-for-byte. -pub async fn sealed_sender_multi_recipient_encrypt( - destinations: &[&ProtocolAddress], - destination_sessions: &[&SessionRecord], - usmc: &UnidentifiedSenderMessageContent, - identity_store: &mut dyn IdentityKeyStore, - ctx: Context, - rng: &mut R, -) -> Result> { - if destinations.len() != destination_sessions.len() { - return Err(SignalProtocolError::InvalidArgument( - "must have the same number of destination sessions as addresses".to_string(), - )); - } - - let m: [u8; sealed_sender_v2::MESSAGE_KEY_LEN] = rng.gen(); - let keys = sealed_sender_v2::DerivedKeys::calculate(&m); - let e_pub = &keys.e.public_key; - - let ciphertext = { - let mut ciphertext = usmc.serialized()?.to_vec(); - let symmetric_authentication_tag = Aes256GcmSiv::new_from_slice(&keys.k) - .and_then(|aes_gcm_siv| { - aes_gcm_siv.encrypt_in_place_detached( - // There's no nonce because the key is already one-use. - &aes_gcm_siv::Nonce::default(), - // And there's no associated data. - &[], - &mut ciphertext, - ) - }) - .map_err(|err| { - log::error!("failed to encrypt using AES-GCM-SIV: {}", err); - SignalProtocolError::InternalError("failed to encrypt using AES-GCM-SIV") - })?; - // AES-GCM-SIV expects the authentication tag to be at the end of the ciphertext - // when decrypting. - ciphertext.extend_from_slice(&symmetric_authentication_tag); - ciphertext - }; - - // Uses a flat representation: count || UUID_i || deviceId_i || registrationId_i || C_i || AT_i || ... || E.pub || ciphertext - let version = SEALED_SENDER_V2_VERSION; - let mut serialized: Vec = vec![(version | (version << 4))]; - - prost::encode_length_delimiter(destinations.len(), &mut serialized) - .expect("cannot fail encoding to Vec"); - - let our_identity = identity_store.get_identity_key_pair(ctx).await?; - let mut previous_their_identity = None; - for (&destination, session) in destinations.iter().zip(destination_sessions) { - let their_uuid = Uuid::parse_str(destination.name()).map_err(|_| { - SignalProtocolError::InvalidArgument(format!( - "multi-recipient sealed sender requires UUID recipients (not {})", - destination.name() - )) - })?; - - let their_identity = identity_store - .get_identity(destination, ctx) - .await? - .ok_or_else(|| SignalProtocolError::SessionNotFound(format!("{}", destination)))?; - - let their_registration_id = session.remote_registration_id().map_err(|_| { - SignalProtocolError::InvalidState( - "sealed_sender_multi_recipient_encrypt", - format!( - concat!( - "cannot get registration ID from session with {} ", - "(maybe it was recently archived)" - ), - destination - ), - ) - })?; - // Valid registration IDs fit in 14 bits. - // TODO: move this into a RegistrationId strong type. - if their_registration_id & 0x3FFF != their_registration_id { - return Err(SignalProtocolError::InvalidRegistrationId( - destination.clone(), - their_registration_id, - )); - } - let their_registration_id = - u16::try_from(their_registration_id).expect("just checked range"); - - let end_of_previous_recipient_data = serialized.len(); - - serialized.extend_from_slice(their_uuid.as_bytes()); - prost::encode_length_delimiter(destination.device_id() as usize, &mut serialized) - .expect("cannot fail encoding to Vec"); - serialized.extend_from_slice(&their_registration_id.to_be_bytes()); - - if Some(their_identity) == previous_their_identity { - // We often send to the same user multiple times, once per device. - // Since the encoding of the message key and attachment tag only depends - // on the identity key, we can reuse the work from the previous destination. - let start_of_previous_recipient_c_and_at = end_of_previous_recipient_data - - sealed_sender_v2::MESSAGE_KEY_LEN - - sealed_sender_v2::AUTH_TAG_LEN; - serialized.extend_from_within( - start_of_previous_recipient_c_and_at..end_of_previous_recipient_data, - ) - } else { - let c_i = sealed_sender_v2::apply_agreement_xor( - &keys.e, - their_identity.public_key(), - Direction::Sending, - &m, - )?; - serialized.extend_from_slice(&c_i); - - let at_i = sealed_sender_v2::compute_authentication_tag( - &our_identity, - &their_identity, - Direction::Sending, - e_pub, - &c_i, - )?; - serialized.extend_from_slice(&at_i); - } - - previous_their_identity = Some(their_identity); - } - - serialized.extend_from_slice(e_pub.public_key_bytes()?); - serialized.extend_from_slice(&ciphertext); - - Ok(serialized) -} - -/// Split out the encoded message from [`sealed_sender_multi_recipient_encrypt`] into a sequence of -/// individual encrypted [`UnidentifiedSenderMessageContent`]s. **Note: this method is only used in -/// testing.** -/// -/// This method strips recipients' metadata and splits a bulk v2 sealed-sender message into byte -/// strings which can be processed by [`sealed_sender_decrypt_to_usmc`]. For the Signal app, this -/// process of splitting out a v2 sealed-sender message into individual messages and using the -/// metadata to correctly route the result to recipients is performed by the Signal server (see -/// **[Routing messages to recipients]**). -/// -/// [Routing messages to recipients]: sealed_sender_multi_recipient_encrypt#routing-messages-to-recipients -pub fn sealed_sender_multi_recipient_fan_out(data: &[u8]) -> Result>> { - let version = data[0] >> 4; - if version != SEALED_SENDER_V2_VERSION { - return Err(SignalProtocolError::UnknownSealedSenderVersion(version)); - } - - fn advance<'a>(buf: &mut &'a [u8], n: usize) -> Result<&'a [u8]> { - if n > buf.len() { - return Err(SignalProtocolError::InvalidProtobufEncoding); - } - let (prefix, remaining) = buf.split_at(n); - *buf = remaining; - Ok(prefix) - } - fn decode_varint(buf: &mut &[u8]) -> Result { - let result: usize = prost::decode_length_delimiter(*buf)?; - let _ = advance(buf, prost::length_delimiter_len(result)) - .expect("just decoded that many bytes"); - result - .try_into() - .map_err(|_| SignalProtocolError::InvalidProtobufEncoding) - } - - let mut remaining = &data[1..]; - let recipient_count = decode_varint(&mut remaining)?; - - let mut messages: Vec> = Vec::new(); - for _ in 0..recipient_count { - // Skip UUID. - let _ = advance(&mut remaining, 16)?; - // Skip device ID. - let _ = decode_varint(&mut remaining)?; - // Skip registration ID. - let _ = advance(&mut remaining, 2)?; - // Read C_i and AT_i. - let c_and_at = advance( - &mut remaining, - sealed_sender_v2::MESSAGE_KEY_LEN + sealed_sender_v2::AUTH_TAG_LEN, - )?; - - let mut next_message = vec![data[0]]; - next_message.extend_from_slice(c_and_at); - messages.push(next_message); - } - - // Remaining data is shared among all messages. - for message in messages.iter_mut() { - message.extend_from_slice(remaining) - } - - Ok(messages) -} - -/// Decrypt the payload of a sealed-sender message in either the v1 or v2 format. -/// -/// [`sealed_sender_decrypt`] consumes the output of this method to validate the sender's identity -/// before decrypting the underlying message. -pub async fn sealed_sender_decrypt_to_usmc( - ciphertext: &[u8], - identity_store: &mut dyn IdentityKeyStore, - ctx: Context, -) -> Result { - let our_identity = identity_store.get_identity_key_pair(ctx).await?; - - match UnidentifiedSenderMessage::deserialize(ciphertext)? { - UnidentifiedSenderMessage::V1 { - ephemeral_public, - encrypted_static, - encrypted_message, - } => { - let eph_keys = sealed_sender_v1::EphemeralKeys::calculate( - &our_identity.into(), - &ephemeral_public, - Direction::Receiving, - )?; - - let message_key_bytes = crypto::aes256_ctr_hmacsha256_decrypt( - &encrypted_static, - &eph_keys.cipher_key, - &eph_keys.mac_key, - )?; - - let static_key = PublicKey::try_from(&message_key_bytes[..])?; - - let static_keys = sealed_sender_v1::StaticKeys::calculate( - &our_identity, - &static_key, - &eph_keys.chain_key, - &encrypted_static, - )?; - - let message_bytes = crypto::aes256_ctr_hmacsha256_decrypt( - &encrypted_message, - &static_keys.cipher_key, - &static_keys.mac_key, - )?; - - let usmc = UnidentifiedSenderMessageContent::deserialize(&message_bytes)?; - - if !bool::from(message_key_bytes.ct_eq(&usmc.sender()?.key()?.serialize())) { - return Err(SignalProtocolError::InvalidSealedSenderMessage( - "sender certificate key does not match message key".to_string(), - )); - } - - Ok(usmc) - } - UnidentifiedSenderMessage::V2 { - ephemeral_public, - encrypted_message_key, - authentication_tag, - encrypted_message, - } => { - let encrypted_message_key: [u8; sealed_sender_v2::MESSAGE_KEY_LEN] = - encrypted_message_key.as_ref().try_into().map_err(|_| { - SignalProtocolError::InvalidSealedSenderMessage(format!( - "encrypted message key had incorrect length {} (should be {})", - encrypted_message_key.len(), - sealed_sender_v2::MESSAGE_KEY_LEN - )) - })?; - let m = sealed_sender_v2::apply_agreement_xor( - &our_identity.into(), - &ephemeral_public, - Direction::Receiving, - &encrypted_message_key, - )?; - - let keys = sealed_sender_v2::DerivedKeys::calculate(&m); - if !bool::from(keys.e.public_key.ct_eq(&ephemeral_public)) { - return Err(SignalProtocolError::InvalidSealedSenderMessage( - "derived ephemeral key did not match key provided in message".to_string(), - )); - } - - let mut message_bytes = encrypted_message.into_vec(); - Aes256GcmSiv::new_from_slice(&keys.k) - .and_then(|aes_gcm_siv| { - aes_gcm_siv.decrypt_in_place( - // There's no nonce because the key is already one-use. - &aes_gcm_siv::Nonce::default(), - // And there's no associated data. - &[], - &mut message_bytes, - ) - }) - .map_err(|err| { - SignalProtocolError::InvalidSealedSenderMessage(format!( - "failed to decrypt inner message: {}", - err - )) - })?; - - let usmc = UnidentifiedSenderMessageContent::deserialize(&message_bytes)?; - - let at = sealed_sender_v2::compute_authentication_tag( - &our_identity, - &usmc.sender()?.key()?.into(), - Direction::Receiving, - &ephemeral_public, - &encrypted_message_key, - )?; - if !bool::from(authentication_tag.ct_eq(&at)) { - return Err(SignalProtocolError::InvalidSealedSenderMessage( - "sender certificate key does not match authentication tag".to_string(), - )); - } - - Ok(usmc) - } - } -} - -#[derive(Debug)] -pub struct SealedSenderDecryptionResult { - pub sender_uuid: String, - pub sender_e164: Option, - pub device_id: u32, - pub message: Vec, -} - -impl SealedSenderDecryptionResult { - pub fn sender_uuid(&self) -> Result<&str> { - Ok(self.sender_uuid.as_ref()) - } - - pub fn sender_e164(&self) -> Result> { - Ok(self.sender_e164.as_deref()) - } - - pub fn device_id(&self) -> Result { - Ok(self.device_id) - } - - pub fn message(&self) -> Result<&[u8]> { - Ok(self.message.as_ref()) - } -} - -/// Decrypt a Sealed Sender message `ciphertext` in either the v1 or v2 format, validate its sender -/// certificate, and then decrypt the inner message payload. -/// -/// This method calls [`sealed_sender_decrypt_to_usmc`] to extract the sender information, including -/// the embedded [`SenderCertificate`]. The sender certificate (signed by the [`ServerCertificate`]) -/// is then validated against the `trust_root` baked into the client to ensure that the sender's -/// identity was not forged. -#[allow(clippy::too_many_arguments)] -pub async fn sealed_sender_decrypt( - ciphertext: &[u8], - trust_root: &PublicKey, - timestamp: u64, - local_e164: Option, - local_uuid: String, - local_device_id: u32, - identity_store: &mut dyn IdentityKeyStore, - session_store: &mut dyn SessionStore, - pre_key_store: &mut dyn PreKeyStore, - signed_pre_key_store: &mut dyn SignedPreKeyStore, - ctx: Context, -) -> Result { - let usmc = sealed_sender_decrypt_to_usmc(ciphertext, identity_store, ctx).await?; - - if !usmc.sender()?.validate(trust_root, timestamp)? { - return Err(SignalProtocolError::InvalidSealedSenderMessage( - "trust root validation failed".to_string(), - )); - } - - let is_local_uuid = local_uuid == usmc.sender()?.sender_uuid()?; - - let is_local_e164 = match (local_e164, usmc.sender()?.sender_e164()?) { - (Some(l), Some(s)) => l == s, - (_, _) => false, - }; - - if (is_local_e164 || is_local_uuid) && usmc.sender()?.sender_device_id()? == local_device_id { - return Err(SignalProtocolError::SealedSenderSelfSend); - } - - let mut rng = rand::rngs::OsRng; - - let remote_address = ProtocolAddress::new( - usmc.sender()?.sender_uuid()?.to_string(), - usmc.sender()?.sender_device_id()?, - ); - - let message = match usmc.msg_type()? { - CiphertextMessageType::Whisper => { - let ctext = SignalMessage::try_from(usmc.contents()?)?; - session_cipher::message_decrypt_signal( - &ctext, - &remote_address, - session_store, - identity_store, - &mut rng, - ctx, - ) - .await? - } - CiphertextMessageType::PreKey => { - let ctext = PreKeySignalMessage::try_from(usmc.contents()?)?; - session_cipher::message_decrypt_prekey( - &ctext, - &remote_address, - session_store, - identity_store, - pre_key_store, - signed_pre_key_store, - &mut rng, - ctx, - ) - .await? - } - msg_type => { - return Err(SignalProtocolError::InvalidSealedSenderMessage(format!( - "Unexpected message type {}", - msg_type as i32, - ))) - } - }; - - Ok(SealedSenderDecryptionResult { - sender_uuid: usmc.sender()?.sender_uuid()?.to_string(), - sender_e164: usmc.sender()?.sender_e164()?.map(|s| s.to_string()), - device_id: usmc.sender()?.sender_device_id()?, - message, - }) -} - -#[test] -fn test_lossless_round_trip() -> Result<()> { - let trust_root = PrivateKey::deserialize(&[0u8; 32])?; - - // To test a hypothetical addition of a new field: - // - // Step 1: tempororarily add a new field to the .proto. - // - // --- a/rust/protocol/src/proto/sealed_sender.proto - // +++ b/rust/protocol/src/proto/sealed_sender.proto - // @@ -26,3 +26,4 @@ message SenderCertificate { - // optional bytes identityKey = 4; - // optional ServerCertificate signer = 5; - // + optional string someFakeField = 999; - // } - // - // Step 2: Add `some_fake_field: None` to the above construction of - // proto::sealed_sender::sender_certificate::Certificate. - // - // Step 3: Serialize and print out the new fixture data (uncomment the following) - // - // let mut rng = rand::rngs::OsRng; - // let server_key = KeyPair::generate(&mut rng); - // let sender_key = KeyPair::generate(&mut rng); - // - // let server_cert = - // ServerCertificate::new(1, server_key.public_key, &trust_root, &mut rng)?; - // - // let sender_cert = proto::sealed_sender::sender_certificate::Certificate { - // sender_uuid: Some("aaaaaaaa-7000-11eb-b32a-33b8a8a487a6".to_string()), - // sender_e164: None, - // sender_device: Some(1), - // expires: Some(31337), - // identity_key: Some(sender_key.public_key.serialize().to_vec()), - // signer: Some(server_cert.to_protobuf()?), - // some_fake_field: Some("crashing right down".to_string()), - // }; - // - // eprintln!(""); - // let serialized_certificate_data = sender_cert.encode_to_vec(); - // let certificate_data_encoded = hex::encode(&serialized_certificate_data); - // eprintln!("let certificate_data_encoded = \"{}\";", certificate_data_encoded); - // - // let certificate_signature = server_key.calculate_signature(&serialized_certificate_data, &mut rng)?; - // let certificate_signature_encoded = hex::encode(certificate_signature); - // eprintln!("let certificate_signature_encoded = \"{}\";", certificate_signature_encoded); - - // Step 4: update the following *_encoded fixture data with the new values from above. - let certificate_data_encoded = "100119697a0000000000002221056c9d1f8deb82b9a898f9c277a1b74989ec009afb5c0acb5e8e69e3d5ca29d6322a690a2508011221053b03ca070e6f6b2f271d32f27321689cdf4e59b106c10b58fbe15063ed868a5a124024bc92954e52ad1a105b5bda85c9db410dcfeb42a671b45a523b3a46e9594a8bde0efc671d8e8e046b32c67f59b80a46ffdf24071850779bc21325107902af89322461616161616161612d373030302d313165622d623332612d333362386138613438376136ba3e136372617368696e6720726967687420646f776e"; - let certificate_signature_encoded = "a22d8f86f5d00794f319add821e342c6ffffb6b34f741e569f8b321ab0255f2d1757ecf648e53a3602cae8f09b3fc80dcf27534d67efd272b6739afc31f75c8c"; - - // The rest of the test should be stable. - let certificate_data = hex::decode(certificate_data_encoded).expect("valid hex"); - let certificate_signature = hex::decode(certificate_signature_encoded).expect("valid hex"); - - let sender_certificate_data = proto::sealed_sender::SenderCertificate { - certificate: Some(certificate_data), - signature: Some(certificate_signature), - }; - - let sender_certificate = SenderCertificate::from_protobuf(&sender_certificate_data)?; - assert!(sender_certificate.validate(&trust_root.public_key()?, 31336)?); - Ok(()) -} diff --git a/net/gurk-rs/files/vendor/libsignal-protocol/src/sender_keys.rs b/net/gurk-rs/files/vendor/libsignal-protocol/src/sender_keys.rs deleted file mode 100644 index c6eeec4..0000000 --- a/net/gurk-rs/files/vendor/libsignal-protocol/src/sender_keys.rs +++ /dev/null @@ -1,631 +0,0 @@ -// -// Copyright 2020 Signal Messenger, LLC. -// SPDX-License-Identifier: AGPL-3.0-only -// - -use std::collections::VecDeque; -use std::convert::TryFrom; - -use itertools::Itertools; -use prost::Message; -use uuid::Uuid; - -use crate::consts; -use crate::crypto::hmac_sha256; -use crate::proto::storage as storage_proto; -use crate::{PrivateKey, PublicKey, Result, SignalProtocolError}; - -#[derive(Debug, Clone)] -pub struct SenderMessageKey { - iteration: u32, - iv: Vec, - cipher_key: Vec, - seed: Vec, -} - -impl SenderMessageKey { - pub fn new(iteration: u32, seed: Vec) -> Result { - let mut derived = [0; 48]; - hkdf::Hkdf::::new(None, &seed) - .expand(b"WhisperGroup", &mut derived) - .expect("valid output length"); - Ok(Self { - iteration, - seed, - iv: derived[0..16].to_vec(), - cipher_key: derived[16..48].to_vec(), - }) - } - - pub fn from_protobuf( - smk: storage_proto::sender_key_state_structure::SenderMessageKey, - ) -> Result { - Self::new(smk.iteration, smk.seed) - } - - pub fn iteration(&self) -> Result { - Ok(self.iteration) - } - - pub fn iv(&self) -> Result> { - Ok(self.iv.clone()) - } - - pub fn cipher_key(&self) -> Result> { - Ok(self.cipher_key.clone()) - } - - pub fn seed(&self) -> Result> { - Ok(self.seed.clone()) - } - - pub fn as_protobuf( - &self, - ) -> Result { - Ok( - storage_proto::sender_key_state_structure::SenderMessageKey { - iteration: self.iteration, - seed: self.seed.clone(), - }, - ) - } -} - -#[derive(Debug, Clone)] -pub struct SenderChainKey { - iteration: u32, - chain_key: Vec, -} - -impl SenderChainKey { - const MESSAGE_KEY_SEED: u8 = 0x01; - const CHAIN_KEY_SEED: u8 = 0x02; - - pub fn new(iteration: u32, chain_key: Vec) -> Result { - Ok(Self { - iteration, - chain_key, - }) - } - - pub fn iteration(&self) -> Result { - Ok(self.iteration) - } - - pub fn seed(&self) -> Result> { - Ok(self.chain_key.clone()) - } - - pub fn next(&self) -> Result { - SenderChainKey::new( - self.iteration + 1, - self.get_derivative(Self::CHAIN_KEY_SEED)?, - ) - } - - pub fn sender_message_key(&self) -> Result { - SenderMessageKey::new(self.iteration, self.get_derivative(Self::MESSAGE_KEY_SEED)?) - } - - fn get_derivative(&self, label: u8) -> Result> { - let label = [label]; - Ok(hmac_sha256(&self.chain_key, &label)?.to_vec()) - } - - pub fn as_protobuf(&self) -> Result { - Ok(storage_proto::sender_key_state_structure::SenderChainKey { - iteration: self.iteration, - seed: self.chain_key.clone(), - }) - } -} - -#[derive(Debug, Clone)] -pub struct SenderKeyState { - state: storage_proto::SenderKeyStateStructure, -} - -impl SenderKeyState { - pub fn new( - message_version: u8, - chain_id: u32, - iteration: u32, - chain_key: &[u8], - signature_key: PublicKey, - signature_private_key: Option, - ) -> Result { - let state = storage_proto::SenderKeyStateStructure { - message_version: message_version as u32, - chain_id, - sender_chain_key: Some( - SenderChainKey::new(iteration, chain_key.to_vec())?.as_protobuf()?, - ), - sender_signing_key: Some( - storage_proto::sender_key_state_structure::SenderSigningKey { - public: signature_key.serialize().to_vec(), - private: match signature_private_key { - None => vec![], - Some(k) => k.serialize().to_vec(), - }, - }, - ), - sender_message_keys: vec![], - }; - - Ok(Self { state }) - } - - pub fn deserialize(buf: &[u8]) -> Result { - let state = storage_proto::SenderKeyStateStructure::decode(buf)?; - Ok(Self { state }) - } - - pub fn from_protobuf(state: storage_proto::SenderKeyStateStructure) -> Self { - Self { state } - } - - pub fn serialize(&self) -> Result> { - Ok(self.state.encode_to_vec()) - } - - pub fn message_version(&self) -> Result { - match self.state.message_version { - 0 => Ok(3), // the first SenderKey version - v => Ok(v), - } - } - - pub fn chain_id(&self) -> Result { - Ok(self.state.chain_id) - } - - pub fn sender_chain_key(&self) -> Result { - let sender_chain = self - .state - .sender_chain_key - .as_ref() - .ok_or(SignalProtocolError::InvalidProtobufEncoding)?; - SenderChainKey::new(sender_chain.iteration, sender_chain.seed.clone()) - } - - pub fn set_sender_chain_key(&mut self, chain_key: SenderChainKey) -> Result<()> { - self.state.sender_chain_key = Some(chain_key.as_protobuf()?); - Ok(()) - } - - pub fn signing_key_public(&self) -> Result { - if let Some(ref signing_key) = self.state.sender_signing_key { - Ok(PublicKey::try_from(&signing_key.public[..])?) - } else { - Err(SignalProtocolError::InvalidProtobufEncoding) - } - } - - pub fn signing_key_private(&self) -> Result { - if let Some(ref signing_key) = self.state.sender_signing_key { - Ok(PrivateKey::deserialize(&signing_key.private)?) - } else { - Err(SignalProtocolError::InvalidProtobufEncoding) - } - } - - pub fn has_sender_message_key(&self, iteration: u32) -> Result { - for sender_message_key in &self.state.sender_message_keys { - if sender_message_key.iteration == iteration { - return Ok(true); - } - } - Ok(false) - } - - pub fn as_protobuf(&self) -> Result { - Ok(self.state.clone()) - } - - pub fn add_sender_message_key(&mut self, sender_message_key: &SenderMessageKey) -> Result<()> { - self.state - .sender_message_keys - .push(sender_message_key.as_protobuf()?); - while self.state.sender_message_keys.len() > consts::MAX_MESSAGE_KEYS { - self.state.sender_message_keys.remove(0); - } - Ok(()) - } - - pub fn remove_sender_message_key( - &mut self, - iteration: u32, - ) -> Result> { - if let Some(index) = self - .state - .sender_message_keys - .iter() - .position(|x| x.iteration == iteration) - { - let smk = self.state.sender_message_keys.remove(index); - Ok(Some(SenderMessageKey::from_protobuf(smk)?)) - } else { - Ok(None) - } - } -} - -#[derive(Debug, Clone)] -pub struct SenderKeyRecord { - states: VecDeque, -} - -impl SenderKeyRecord { - pub fn new_empty() -> Self { - Self { - states: VecDeque::with_capacity(consts::MAX_SENDER_KEY_STATES), - } - } - - pub fn deserialize(buf: &[u8]) -> Result { - let skr = storage_proto::SenderKeyRecordStructure::decode(buf)?; - - let mut states = VecDeque::with_capacity(skr.sender_key_states.len()); - for state in skr.sender_key_states { - states.push_back(SenderKeyState::from_protobuf(state)) - } - Ok(Self { states }) - } - - pub fn is_empty(&self) -> Result { - Ok(self.states.is_empty()) - } - - pub fn sender_key_state(&mut self) -> Result<&mut SenderKeyState> { - if !self.states.is_empty() { - return Ok(&mut self.states[0]); - } - Err(SignalProtocolError::NoSenderKeyState) - } - - pub fn sender_key_state_for_chain_id( - &mut self, - chain_id: u32, - distribution_id: Uuid, - ) -> Result<&mut SenderKeyState> { - for i in 0..self.states.len() { - if self.states[i].chain_id()? == chain_id { - return Ok(&mut self.states[i]); - } - } - log::error!( - "SenderKey distribution {} could not find chain ID {} (known chain IDs: {:?})", - distribution_id, - chain_id, - self.states - .iter() - .map(|state| state.chain_id().expect("accessed successfully above")) - .collect::>() - ); - Err(SignalProtocolError::NoSenderKeyState) - } - - pub fn add_sender_key_state( - &mut self, - message_version: u8, - chain_id: u32, - iteration: u32, - chain_key: &[u8], - signature_key: PublicKey, - signature_private_key: Option, - ) -> Result<()> { - let existing_state = self.remove_state(chain_id, signature_key); - - if self.remove_states_with_chain_id(chain_id) > 0 { - log::warn!( - "Removed a matching chain_id ({}) found with a different public key", - chain_id - ); - } - - let state = match existing_state { - None => SenderKeyState::new( - message_version, - chain_id, - iteration, - chain_key, - signature_key, - signature_private_key, - )?, - Some(state) => state, - }; - - while self.states.len() >= consts::MAX_SENDER_KEY_STATES { - self.states.pop_back(); - } - - self.states.push_front(state); - - Ok(()) - } - - /// Remove the state with the matching `chain_id` and `signature_key`. - /// - /// Skips any bad protobufs. - fn remove_state(&mut self, chain_id: u32, signature_key: PublicKey) -> Option { - let (index, _state) = self.states.iter().find_position(|state| { - state.chain_id().ok() == Some(chain_id) - && state.signing_key_public().ok() == Some(signature_key) - })?; - - self.states.remove(index) - } - - /// Returns the number of removed states. - /// - /// Skips any bad protobufs. - fn remove_states_with_chain_id(&mut self, chain_id: u32) -> usize { - let initial_length = self.states.len(); - self.states - .retain(|state| state.chain_id().ok() != Some(chain_id)); - initial_length - self.states.len() - } - - pub fn set_sender_key_state( - &mut self, - message_version: u8, - chain_id: u32, - iteration: u32, - chain_key: &[u8], - signature_key: PublicKey, - signature_private_key: Option, - ) -> Result<()> { - self.states.clear(); - self.add_sender_key_state( - message_version, - chain_id, - iteration, - chain_key, - signature_key, - signature_private_key, - ) - } - - pub fn as_protobuf(&self) -> Result { - let mut states = Vec::with_capacity(self.states.len()); - for state in &self.states { - states.push(state.as_protobuf()?); - } - - Ok(storage_proto::SenderKeyRecordStructure { - sender_key_states: states, - }) - } - - pub fn serialize(&self) -> Result> { - Ok(self.as_protobuf()?.encode_to_vec()) - } -} - -#[cfg(test)] -mod sender_key_record_add_sender_key_state_tests { - use itertools::Itertools; - use rand::rngs::OsRng; - - use crate::KeyPair; - - use super::*; - - fn random_public_key() -> PublicKey { - KeyPair::generate(&mut OsRng).public_key - } - - fn chain_key(i: u128) -> Vec { - i.to_be_bytes().to_vec() - } - - struct TestContext { - sender_key_record: SenderKeyRecord, - } - - impl TestContext { - fn new() -> Self { - Self { - sender_key_record: SenderKeyRecord::new_empty(), - } - } - - /// Associates the `record_key` with the `chain_key` via `add_sender_key_state` which is the - /// method under test in this module. - fn add_sender_key_state_record(&mut self, record_key: (PublicKey, u32), chain_key: &[u8]) { - let (public_key, chain_id) = record_key; - self.sender_key_record - .add_sender_key_state(1, chain_id, 1, chain_key, public_key, None) - .expect("to be able to add new state"); - } - - fn assert_number_of_states(&self, expected: usize) { - assert_eq!(expected, self.sender_key_record.states.len()); - } - - /// Asserts that for the supplied `record_key` the chain key is as expected when looked up - /// by both `chain_id` and `public_key` and `chain_id`. - fn assert_records_chain_key( - &mut self, - record_key: (PublicKey, u32), - expected_chain_key: &[u8], - ) { - let (public_key, chain_id) = record_key; - let found_chain_key = self - .sender_key_record - .sender_key_state_for_chain_id(chain_id, Uuid::default()) - .expect("Expect to find chain id") - .sender_chain_key() - .expect("Expect to find chain key") - .chain_key; - - assert_eq!(found_chain_key, expected_chain_key); - - let matching_state = self - .sender_key_record - .states - .iter() - .filter(|state| { - state.chain_id().expect("expect chain id") == chain_id - && state.signing_key_public().expect("expect public key") == public_key - }) - .exactly_one() - .expect("Expected exactly one record key match"); - - assert_eq!( - &matching_state - .sender_chain_key() - .expect("Expect to find chain key") - .chain_key, - expected_chain_key - ); - } - - fn assert_record_order(&self, order: Vec<(PublicKey, u32)>) { - let record_keys = self - .sender_key_record - .states - .iter() - .map(|state| { - ( - state.signing_key_public().expect("expect public key"), - state.chain_id().expect("expect chain id"), - ) - }) - .collect::>(); - - assert_eq!(record_keys, order); - } - } - - #[test] - fn add_single_state() { - let mut context = TestContext::new(); - - let public_key = random_public_key(); - let chain_id = 1; - let chain_key = chain_key(1); - let record_key = (public_key, chain_id); - - context.add_sender_key_state_record(record_key, &chain_key); - - context.assert_number_of_states(1); - context.assert_records_chain_key(record_key, &chain_key); - } - - #[test] - fn add_second_state() { - let mut context = TestContext::new(); - - let chain_id_1 = 1; - let chain_id_2 = 2; - let record_key_1 = (random_public_key(), chain_id_1); - let record_key_2 = (random_public_key(), chain_id_2); - let chain_key_1 = chain_key(1); - let chain_key_2 = chain_key(2); - - context.add_sender_key_state_record(record_key_1, &chain_key_1); - context.add_sender_key_state_record(record_key_2, &chain_key_2); - - context.assert_number_of_states(2); - context.assert_records_chain_key(record_key_1, &chain_key_1); - context.assert_records_chain_key(record_key_2, &chain_key_2); - } - - #[test] - fn when_exceed_maximum_states_then_oldest_is_ejected() { - assert_eq!( - 5, - consts::MAX_SENDER_KEY_STATES, - "Test written to expect this limit" - ); - - let mut context = TestContext::new(); - - let record_key_1 = (random_public_key(), 1); - let record_key_2 = (random_public_key(), 2); - let record_key_3 = (random_public_key(), 3); - let record_key_4 = (random_public_key(), 4); - let record_key_5 = (random_public_key(), 5); - let record_key_6 = (random_public_key(), 6); - - context.add_sender_key_state_record(record_key_1, &chain_key(1)); - context.add_sender_key_state_record(record_key_2, &chain_key(2)); - context.add_sender_key_state_record(record_key_3, &chain_key(3)); - context.add_sender_key_state_record(record_key_4, &chain_key(4)); - context.add_sender_key_state_record(record_key_5, &chain_key(5)); - - context.assert_record_order(vec![ - record_key_5, - record_key_4, - record_key_3, - record_key_2, - record_key_1, - ]); - - context.add_sender_key_state_record(record_key_6, &chain_key(6)); - - context.assert_record_order(vec![ - record_key_6, - record_key_5, - record_key_4, - record_key_3, - record_key_2, - ]); - } - - #[test] - fn when_second_state_with_same_public_key_and_chain_id_added_then_it_keeps_first_data() { - let mut context = TestContext::new(); - - let chain_id = 1; - let record_key = (random_public_key(), chain_id); - let chain_key_1 = chain_key(1); - let chain_key_2 = chain_key(2); - - context.add_sender_key_state_record(record_key, &chain_key_1); - context.add_sender_key_state_record(record_key, &chain_key_2); - - context.assert_number_of_states(1); - context.assert_records_chain_key(record_key, &chain_key_1); - } - - #[test] - fn when_second_state_with_different_public_key_but_same_chain_id_added_then_it_gets_replaced() { - let mut context = TestContext::new(); - - let chain_id = 1; - let record_key_1 = (random_public_key(), chain_id); - let record_key_2 = (random_public_key(), chain_id); - let chain_key_1 = chain_key(1); - let chain_key_2 = chain_key(2); - - context.add_sender_key_state_record(record_key_1, &chain_key_1); - context.add_sender_key_state_record(record_key_2, &chain_key_2); - - context.assert_number_of_states(1); - context.assert_records_chain_key(record_key_2, &chain_key_2); - } - - #[test] - fn when_second_state_with_same_public_key_and_chain_id_added_then_it_becomes_the_most_recent() { - let mut context = TestContext::new(); - - let chain_id_1 = 1; - let chain_id_2 = 2; - let record_key_1 = (random_public_key(), chain_id_1); - let record_key_2 = (random_public_key(), chain_id_2); - let chain_key_1 = chain_key(1); - let chain_key_2 = chain_key(2); - let chain_key_3 = chain_key(3); - - context.add_sender_key_state_record(record_key_1, &chain_key_1); - context.add_sender_key_state_record(record_key_2, &chain_key_2); - - context.assert_record_order(vec![record_key_2, record_key_1]); - - context.add_sender_key_state_record(record_key_1, &chain_key_3); - - context.assert_record_order(vec![record_key_1, record_key_2]); - } -} diff --git a/net/gurk-rs/files/vendor/libsignal-protocol/src/session.rs b/net/gurk-rs/files/vendor/libsignal-protocol/src/session.rs deleted file mode 100644 index a2e9b30..0000000 --- a/net/gurk-rs/files/vendor/libsignal-protocol/src/session.rs +++ /dev/null @@ -1,205 +0,0 @@ -// -// Copyright 2020 Signal Messenger, LLC. -// SPDX-License-Identifier: AGPL-3.0-only -// - -use crate::{ - Context, Direction, IdentityKeyStore, KeyPair, PreKeyBundle, PreKeySignalMessage, PreKeyStore, - ProtocolAddress, Result, SessionRecord, SessionStore, SignalProtocolError, SignedPreKeyStore, -}; - -use crate::ratchet; -use crate::ratchet::{AliceSignalProtocolParameters, BobSignalProtocolParameters}; -use crate::state::PreKeyId; -use rand::{CryptoRng, Rng}; - -/* -These functions are on SessionBuilder in Java - -However using SessionBuilder + SessionCipher at the same time causes -&mut sharing issues. And as SessionBuilder has no actual state beyond -its reference to the various data stores, instead the functions are -free standing. - */ - -pub async fn process_prekey( - message: &PreKeySignalMessage, - remote_address: &ProtocolAddress, - session_record: &mut SessionRecord, - identity_store: &mut dyn IdentityKeyStore, - pre_key_store: &mut dyn PreKeyStore, - signed_prekey_store: &mut dyn SignedPreKeyStore, - ctx: Context, -) -> Result> { - let their_identity_key = message.identity_key(); - - if !identity_store - .is_trusted_identity( - remote_address, - their_identity_key, - Direction::Receiving, - ctx, - ) - .await? - { - return Err(SignalProtocolError::UntrustedIdentity( - remote_address.clone(), - )); - } - - let unsigned_pre_key_id = process_prekey_v3( - message, - remote_address, - session_record, - signed_prekey_store, - pre_key_store, - identity_store, - ctx, - ) - .await?; - - identity_store - .save_identity(remote_address, their_identity_key, ctx) - .await?; - - Ok(unsigned_pre_key_id) -} - -async fn process_prekey_v3( - message: &PreKeySignalMessage, - remote_address: &ProtocolAddress, - session_record: &mut SessionRecord, - signed_prekey_store: &mut dyn SignedPreKeyStore, - pre_key_store: &mut dyn PreKeyStore, - identity_store: &mut dyn IdentityKeyStore, - ctx: Context, -) -> Result> { - if session_record.has_session_state( - message.message_version() as u32, - &message.base_key().serialize(), - )? { - // We've already setup a session for this V3 message, letting bundled message fall through - return Ok(None); - } - - let our_signed_pre_key_pair = signed_prekey_store - .get_signed_pre_key(message.signed_pre_key_id(), ctx) - .await? - .key_pair()?; - - let our_one_time_pre_key_pair = if let Some(pre_key_id) = message.pre_key_id() { - log::info!("processing PreKey message from {}", remote_address); - Some( - pre_key_store - .get_pre_key(pre_key_id, ctx) - .await? - .key_pair()?, - ) - } else { - log::warn!( - "processing PreKey message from {} which had no one-time prekey", - remote_address - ); - None - }; - - let parameters = BobSignalProtocolParameters::new( - identity_store.get_identity_key_pair(ctx).await?, - our_signed_pre_key_pair, // signed pre key - our_one_time_pre_key_pair, - our_signed_pre_key_pair, // ratchet key - *message.identity_key(), - *message.base_key(), - ); - - session_record.archive_current_state()?; - - let mut new_session = ratchet::initialize_bob_session(¶meters)?; - - new_session.set_local_registration_id(identity_store.get_local_registration_id(ctx).await?)?; - new_session.set_remote_registration_id(message.registration_id())?; - new_session.set_alice_base_key(&message.base_key().serialize())?; - - session_record.promote_state(new_session)?; - - Ok(message.pre_key_id()) -} - -pub async fn process_prekey_bundle( - remote_address: &ProtocolAddress, - session_store: &mut dyn SessionStore, - identity_store: &mut dyn IdentityKeyStore, - bundle: &PreKeyBundle, - mut csprng: &mut R, - ctx: Context, -) -> Result<()> { - let their_identity_key = bundle.identity_key()?; - - if !identity_store - .is_trusted_identity(remote_address, their_identity_key, Direction::Sending, ctx) - .await? - { - return Err(SignalProtocolError::UntrustedIdentity( - remote_address.clone(), - )); - } - - if !their_identity_key.public_key().verify_signature( - &bundle.signed_pre_key_public()?.serialize(), - bundle.signed_pre_key_signature()?, - )? { - return Err(SignalProtocolError::SignatureValidationFailed); - } - - let mut session_record = session_store - .load_session(remote_address, ctx) - .await? - .unwrap_or_else(SessionRecord::new_fresh); - - let our_base_key_pair = KeyPair::generate(&mut csprng); - let their_signed_prekey = bundle.signed_pre_key_public()?; - - let their_one_time_prekey = bundle.pre_key_public()?; - let their_one_time_prekey_id = bundle.pre_key_id()?; - - let our_identity_key_pair = identity_store.get_identity_key_pair(ctx).await?; - - let parameters = AliceSignalProtocolParameters::new( - our_identity_key_pair, - our_base_key_pair, - *their_identity_key, - their_signed_prekey, - their_one_time_prekey, - their_signed_prekey, - ); - - let mut session = ratchet::initialize_alice_session(¶meters, csprng)?; - - log::info!( - "set_unacknowledged_pre_key_message for: {} with preKeyId: {}", - remote_address, - their_one_time_prekey_id.map_or_else(|| "".to_string(), |id| id.to_string()) - ); - - session.set_unacknowledged_pre_key_message( - their_one_time_prekey_id, - bundle.signed_pre_key_id()?, - &our_base_key_pair.public_key, - )?; - - session.set_local_registration_id(identity_store.get_local_registration_id(ctx).await?)?; - session.set_remote_registration_id(bundle.registration_id()?)?; - session.set_alice_base_key(&our_base_key_pair.public_key.serialize())?; - - identity_store - .save_identity(remote_address, their_identity_key, ctx) - .await?; - - session_record.promote_state(session)?; - - session_store - .store_session(remote_address, &session_record, ctx) - .await?; - - Ok(()) -} diff --git a/net/gurk-rs/files/vendor/libsignal-protocol/src/session_cipher.rs b/net/gurk-rs/files/vendor/libsignal-protocol/src/session_cipher.rs deleted file mode 100644 index 0625a0a..0000000 --- a/net/gurk-rs/files/vendor/libsignal-protocol/src/session_cipher.rs +++ /dev/null @@ -1,636 +0,0 @@ -// -// Copyright 2020-2021 Signal Messenger, LLC. -// SPDX-License-Identifier: AGPL-3.0-only -// - -use crate::{ - CiphertextMessage, Context, Direction, IdentityKeyStore, KeyPair, PreKeySignalMessage, - PreKeyStore, ProtocolAddress, PublicKey, Result, SessionRecord, SessionStore, SignalMessage, - SignalProtocolError, SignedPreKeyStore, -}; - -use crate::consts::MAX_FORWARD_JUMPS; -use crate::crypto; -use crate::ratchet::{ChainKey, MessageKeys}; -use crate::session; -use crate::state::SessionState; - -use rand::{CryptoRng, Rng}; - -pub async fn message_encrypt( - ptext: &[u8], - remote_address: &ProtocolAddress, - session_store: &mut dyn SessionStore, - identity_store: &mut dyn IdentityKeyStore, - ctx: Context, -) -> Result { - let mut session_record = session_store - .load_session(remote_address, ctx) - .await? - .ok_or_else(|| SignalProtocolError::SessionNotFound(format!("{}", remote_address)))?; - let session_state = session_record.session_state_mut()?; - - let chain_key = session_state.get_sender_chain_key()?; - - let message_keys = chain_key.message_keys()?; - - let sender_ephemeral = session_state.sender_ratchet_key()?; - let previous_counter = session_state.previous_counter()?; - let session_version = session_state.session_version()? as u8; - - let local_identity_key = session_state.local_identity_key()?; - let their_identity_key = session_state - .remote_identity_key()? - .ok_or(SignalProtocolError::InvalidSessionStructure)?; - - let ctext = crypto::aes_256_cbc_encrypt(ptext, message_keys.cipher_key(), message_keys.iv())?; - - let message = if let Some(items) = session_state.unacknowledged_pre_key_message_items()? { - let local_registration_id = session_state.local_registration_id()?; - - log::info!( - "Building PreKeyWhisperMessage for: {} with preKeyId: {}", - remote_address, - items - .pre_key_id()? - .map_or_else(|| "".to_string(), |id| id.to_string()) - ); - - let message = SignalMessage::new( - session_version, - message_keys.mac_key(), - sender_ephemeral, - chain_key.index(), - previous_counter, - &ctext, - &local_identity_key, - &their_identity_key, - )?; - - CiphertextMessage::PreKeySignalMessage(PreKeySignalMessage::new( - session_version, - local_registration_id, - items.pre_key_id()?, - items.signed_pre_key_id()?, - *items.base_key()?, - local_identity_key, - message, - )?) - } else { - CiphertextMessage::SignalMessage(SignalMessage::new( - session_version, - message_keys.mac_key(), - sender_ephemeral, - chain_key.index(), - previous_counter, - &ctext, - &local_identity_key, - &their_identity_key, - )?) - }; - - session_state.set_sender_chain_key(&chain_key.next_chain_key()?)?; - - // XXX why is this check after everything else?!! - if !identity_store - .is_trusted_identity(remote_address, &their_identity_key, Direction::Sending, ctx) - .await? - { - log::warn!( - "Identity key {} is not trusted for remote address {}", - their_identity_key - .public_key() - .public_key_bytes() - .map_or_else(|e| format!("", e), hex::encode), - remote_address, - ); - return Err(SignalProtocolError::UntrustedIdentity( - remote_address.clone(), - )); - } - - // XXX this could be combined with the above call to the identity store (in a new API) - identity_store - .save_identity(remote_address, &their_identity_key, ctx) - .await?; - - session_store - .store_session(remote_address, &session_record, ctx) - .await?; - Ok(message) -} - -pub async fn message_decrypt( - ciphertext: &CiphertextMessage, - remote_address: &ProtocolAddress, - session_store: &mut dyn SessionStore, - identity_store: &mut dyn IdentityKeyStore, - pre_key_store: &mut dyn PreKeyStore, - signed_pre_key_store: &mut dyn SignedPreKeyStore, - csprng: &mut R, - ctx: Context, -) -> Result> { - match ciphertext { - CiphertextMessage::SignalMessage(m) => { - message_decrypt_signal( - m, - remote_address, - session_store, - identity_store, - csprng, - ctx, - ) - .await - } - CiphertextMessage::PreKeySignalMessage(m) => { - message_decrypt_prekey( - m, - remote_address, - session_store, - identity_store, - pre_key_store, - signed_pre_key_store, - csprng, - ctx, - ) - .await - } - _ => Err(SignalProtocolError::InvalidArgument( - "SessionCipher::decrypt cannot decrypt this message type".to_owned(), - )), - } -} - -pub async fn message_decrypt_prekey( - ciphertext: &PreKeySignalMessage, - remote_address: &ProtocolAddress, - session_store: &mut dyn SessionStore, - identity_store: &mut dyn IdentityKeyStore, - pre_key_store: &mut dyn PreKeyStore, - signed_pre_key_store: &mut dyn SignedPreKeyStore, - csprng: &mut R, - ctx: Context, -) -> Result> { - let mut session_record = session_store - .load_session(remote_address, ctx) - .await? - .unwrap_or_else(SessionRecord::new_fresh); - - // Make sure we log the session state if we fail to process the pre-key. - let pre_key_id_or_err = session::process_prekey( - ciphertext, - remote_address, - &mut session_record, - identity_store, - pre_key_store, - signed_pre_key_store, - ctx, - ) - .await; - - let pre_key_id = match pre_key_id_or_err { - Ok(id) => id, - Err(e) => { - let errs = [e]; - log::error!( - "{}", - create_decryption_failure_log( - remote_address, - &errs, - &session_record, - ciphertext.message() - )? - ); - let [e] = errs; - return Err(e); - } - }; - - let ptext = decrypt_message_with_record( - remote_address, - &mut session_record, - ciphertext.message(), - csprng, - )?; - - session_store - .store_session(remote_address, &session_record, ctx) - .await?; - - if let Some(pre_key_id) = pre_key_id { - pre_key_store.remove_pre_key(pre_key_id, ctx).await?; - } - - Ok(ptext) -} - -pub async fn message_decrypt_signal( - ciphertext: &SignalMessage, - remote_address: &ProtocolAddress, - session_store: &mut dyn SessionStore, - identity_store: &mut dyn IdentityKeyStore, - csprng: &mut R, - ctx: Context, -) -> Result> { - let mut session_record = session_store - .load_session(remote_address, ctx) - .await? - .ok_or_else(|| SignalProtocolError::SessionNotFound(format!("{}", remote_address)))?; - - let ptext = - decrypt_message_with_record(remote_address, &mut session_record, ciphertext, csprng)?; - - // Why are we performing this check after decryption instead of before? - let their_identity_key = session_record - .session_state()? - .remote_identity_key()? - .ok_or(SignalProtocolError::InvalidSessionStructure)?; - - if !identity_store - .is_trusted_identity( - remote_address, - &their_identity_key, - Direction::Receiving, - ctx, - ) - .await? - { - log::warn!( - "Identity key {} is not trusted for remote address {}", - their_identity_key - .public_key() - .public_key_bytes() - .map_or_else(|e| format!("", e), hex::encode), - remote_address, - ); - return Err(SignalProtocolError::UntrustedIdentity( - remote_address.clone(), - )); - } - - identity_store - .save_identity(remote_address, &their_identity_key, ctx) - .await?; - - session_store - .store_session(remote_address, &session_record, ctx) - .await?; - - Ok(ptext) -} - -fn create_decryption_failure_log( - remote_address: &ProtocolAddress, - mut errs: &[SignalProtocolError], - record: &SessionRecord, - ciphertext: &SignalMessage, -) -> Result { - fn append_session_summary( - lines: &mut Vec, - idx: usize, - state: Result<&SessionState>, - err: Option<&SignalProtocolError>, - ) { - let chains = state.and_then(|state| state.all_receiver_chain_logging_info()); - match (err, &chains) { - (Some(err), Ok(chains)) => { - lines.push(format!( - "Candidate session {} failed with '{}', had {} receiver chains", - idx, - err, - chains.len() - )); - } - (Some(err), Err(state_err)) => { - lines.push(format!( - "Candidate session {} failed with '{}'; cannot get receiver chain info ({})", - idx, err, state_err, - )); - } - (None, Ok(chains)) => { - lines.push(format!( - "Candidate session {} had {} receiver chains", - idx, - chains.len() - )); - } - (None, Err(state_err)) => { - lines.push(format!( - "Candidate session {}: cannot get receiver chain info ({})", - idx, state_err, - )); - } - } - - if let Ok(chains) = chains { - for chain in chains { - let chain_idx = match chain.1 { - Some(i) => i.to_string(), - None => "missing in protobuf".to_string(), - }; - - lines.push(format!( - "Receiver chain with sender ratchet public key {} chain key index {}", - hex::encode(chain.0), - chain_idx - )); - } - } - } - - let mut lines = vec![]; - - lines.push(format!( - "Message from {} failed to decrypt; sender ratchet public key {} message counter {}", - remote_address, - hex::encode(ciphertext.sender_ratchet_key().public_key_bytes()?), - ciphertext.counter() - )); - - if let Ok(current_session) = record.session_state() { - let err = errs.first(); - if err.is_some() { - errs = &errs[1..]; - } - append_session_summary(&mut lines, 0, Ok(current_session), err); - } else { - lines.push("No current session".to_string()); - } - - for (idx, (state, err)) in record - .previous_session_states() - .zip(errs.iter().map(Some).chain(std::iter::repeat(None))) - .enumerate() - { - let state = match state { - Ok(ref state) => Ok(state), - Err(err) => Err(err), - }; - append_session_summary(&mut lines, idx + 1, state, err); - } - - Ok(lines.join("\n")) -} - -fn decrypt_message_with_record( - remote_address: &ProtocolAddress, - record: &mut SessionRecord, - ciphertext: &SignalMessage, - csprng: &mut R, -) -> Result> { - let log_decryption_failure = |state: &SessionState, error: &SignalProtocolError| { - // A warning rather than an error because we try multiple sessions. - log::warn!( - "Failed to decrypt whisper message with ratchet key: {} and counter: {}. \ - Session loaded for {}. Local session has base key: {} and counter: {}. {}", - ciphertext - .sender_ratchet_key() - .public_key_bytes() - .map_or_else(|e| format!("", e), hex::encode), - ciphertext.counter(), - remote_address, - state - .sender_ratchet_key_for_logging() - .unwrap_or_else(|e| format!("", e)), - state.previous_counter().unwrap_or(u32::MAX), - error - ); - }; - - let mut errs = vec![]; - - if let Ok(current_state) = record.session_state() { - let mut current_state = current_state.clone(); - let result = - decrypt_message_with_state(&mut current_state, ciphertext, remote_address, csprng); - - match result { - Ok(ptext) => { - log::info!( - "decrypted message from {} with current session state (base key {})", - remote_address, - current_state - .sender_ratchet_key_for_logging() - .expect("successful decrypt always has a valid base key"), - ); - record.set_session_state(current_state)?; // update the state - return Ok(ptext); - } - Err(SignalProtocolError::DuplicatedMessage(_, _)) => { - return result; - } - Err(e) => { - log_decryption_failure(¤t_state, &e); - errs.push(e); - } - } - } - - // Try some old sessions: - let mut updated_session = None; - - for (idx, previous) in record.previous_session_states().enumerate() { - let mut previous = previous?; - - let result = decrypt_message_with_state(&mut previous, ciphertext, remote_address, csprng); - - match result { - Ok(ptext) => { - log::info!( - "decrypted message from {} with PREVIOUS session state (base key {})", - remote_address, - previous - .sender_ratchet_key_for_logging() - .expect("successful decrypt always has a valid base key"), - ); - updated_session = Some((ptext, idx, previous)); - break; - } - Err(SignalProtocolError::DuplicatedMessage(_, _)) => { - return result; - } - Err(e) => { - log_decryption_failure(&previous, &e); - errs.push(e); - } - } - } - - if let Some((ptext, idx, updated_session)) = updated_session { - record.promote_old_session(idx, updated_session)?; - Ok(ptext) - } else { - let previous_state_count = || record.previous_session_states().len(); - - if let Ok(current_state) = record.session_state() { - log::error!( - "No valid session for recipient: {}, current session base key {}, number of previous states: {}", - remote_address, - current_state.sender_ratchet_key_for_logging() - .unwrap_or_else(|e| format!("", e)), - previous_state_count(), - ); - } else { - log::error!( - "No valid session for recipient: {}, (no current session state), number of previous states: {}", - remote_address, - previous_state_count(), - ); - } - log::error!( - "{}", - create_decryption_failure_log(remote_address, &errs, record, ciphertext)? - ); - Err(SignalProtocolError::InvalidMessage( - "Message decryption failed", - )) - } -} - -fn decrypt_message_with_state( - state: &mut SessionState, - ciphertext: &SignalMessage, - remote_address: &ProtocolAddress, - csprng: &mut R, -) -> Result> { - if !state.has_sender_chain()? { - return Err(SignalProtocolError::InvalidMessage( - "No session available to decrypt", - )); - } - - let ciphertext_version = ciphertext.message_version() as u32; - if ciphertext_version != state.session_version()? { - return Err(SignalProtocolError::UnrecognizedMessageVersion( - ciphertext_version, - )); - } - - let their_ephemeral = ciphertext.sender_ratchet_key(); - let counter = ciphertext.counter(); - let chain_key = get_or_create_chain_key(state, their_ephemeral, remote_address, csprng)?; - let message_keys = - get_or_create_message_key(state, their_ephemeral, remote_address, &chain_key, counter)?; - - let their_identity_key = state - .remote_identity_key()? - .ok_or(SignalProtocolError::InvalidSessionStructure)?; - - let mac_valid = ciphertext.verify_mac( - &their_identity_key, - &state.local_identity_key()?, - message_keys.mac_key(), - )?; - - if !mac_valid { - return Err(SignalProtocolError::InvalidCiphertext); - } - - let ptext = crypto::aes_256_cbc_decrypt( - ciphertext.body(), - message_keys.cipher_key(), - message_keys.iv(), - )?; - - state.clear_unacknowledged_pre_key_message()?; - - Ok(ptext) -} - -fn get_or_create_chain_key( - state: &mut SessionState, - their_ephemeral: &PublicKey, - remote_address: &ProtocolAddress, - csprng: &mut R, -) -> Result { - if let Some(chain) = state.get_receiver_chain_key(their_ephemeral)? { - log::debug!("{} has existing receiver chain.", remote_address); - return Ok(chain); - } - - log::info!("{} creating new chains.", remote_address); - - let root_key = state.root_key()?; - let our_ephemeral = state.sender_ratchet_private_key()?; - let receiver_chain = root_key.create_chain(their_ephemeral, &our_ephemeral)?; - let our_new_ephemeral = KeyPair::generate(csprng); - let sender_chain = receiver_chain - .0 - .create_chain(their_ephemeral, &our_new_ephemeral.private_key)?; - - state.set_root_key(&sender_chain.0)?; - state.add_receiver_chain(their_ephemeral, &receiver_chain.1)?; - - let current_index = state.get_sender_chain_key()?.index(); - let previous_index = if current_index > 0 { - current_index - 1 - } else { - 0 - }; - state.set_previous_counter(previous_index)?; - state.set_sender_chain(&our_new_ephemeral, &sender_chain.1)?; - - Ok(receiver_chain.1) -} - -fn get_or_create_message_key( - state: &mut SessionState, - their_ephemeral: &PublicKey, - remote_address: &ProtocolAddress, - chain_key: &ChainKey, - counter: u32, -) -> Result { - let chain_index = chain_key.index(); - - if chain_index > counter { - return match state.get_message_keys(their_ephemeral, counter)? { - Some(keys) => Ok(keys), - None => { - log::info!( - "{} Duplicate message for counter: {}", - remote_address, - counter - ); - Err(SignalProtocolError::DuplicatedMessage(chain_index, counter)) - } - }; - } - - assert!(chain_index <= counter); - - let jump = (counter - chain_index) as usize; - - if jump > MAX_FORWARD_JUMPS { - if state.session_with_self()? { - log::info!( - "{} Jumping ahead {} messages (index: {}, counter: {})", - remote_address, - jump, - chain_index, - counter - ); - } else { - log::error!( - "{} Exceeded future message limit: {}, index: {}, counter: {})", - remote_address, - MAX_FORWARD_JUMPS, - chain_index, - counter - ); - return Err(SignalProtocolError::InvalidMessage( - "message from too far into the future", - )); - } - } - - let mut chain_key = chain_key.clone(); - - while chain_key.index() < counter { - let message_keys = chain_key.message_keys()?; - state.set_message_keys(their_ephemeral, &message_keys)?; - chain_key = chain_key.next_chain_key()?; - } - - state.set_receiver_chain_key(their_ephemeral, &chain_key.next_chain_key()?)?; - chain_key.message_keys() -} diff --git a/net/gurk-rs/files/vendor/libsignal-protocol/src/state.rs b/net/gurk-rs/files/vendor/libsignal-protocol/src/state.rs deleted file mode 100644 index cf9fa1d..0000000 --- a/net/gurk-rs/files/vendor/libsignal-protocol/src/state.rs +++ /dev/null @@ -1,15 +0,0 @@ -// -// Copyright 2020 Signal Messenger, LLC. -// SPDX-License-Identifier: AGPL-3.0-only -// - -mod bundle; -mod prekey; -mod session; -mod signed_prekey; - -pub use bundle::PreKeyBundle; -pub use prekey::{PreKeyId, PreKeyRecord}; -pub use session::SessionRecord; -pub(crate) use session::SessionState; -pub use signed_prekey::{SignedPreKeyId, SignedPreKeyRecord}; diff --git a/net/gurk-rs/files/vendor/libsignal-protocol/src/state/bundle.rs b/net/gurk-rs/files/vendor/libsignal-protocol/src/state/bundle.rs deleted file mode 100644 index e306528..0000000 --- a/net/gurk-rs/files/vendor/libsignal-protocol/src/state/bundle.rs +++ /dev/null @@ -1,79 +0,0 @@ -// -// Copyright 2020 Signal Messenger, LLC. -// SPDX-License-Identifier: AGPL-3.0-only -// - -use crate::state::{PreKeyId, SignedPreKeyId}; -use crate::{IdentityKey, PublicKey, Result}; - -#[derive(Debug, Clone)] -pub struct PreKeyBundle { - registration_id: u32, - device_id: u32, - pre_key_id: Option, - pre_key_public: Option, - signed_pre_key_id: SignedPreKeyId, - signed_pre_key_public: PublicKey, - signed_pre_key_signature: Vec, - identity_key: IdentityKey, -} - -impl PreKeyBundle { - pub fn new( - registration_id: u32, - device_id: u32, - pre_key: Option<(PreKeyId, PublicKey)>, - signed_pre_key_id: SignedPreKeyId, - signed_pre_key_public: PublicKey, - signed_pre_key_signature: Vec, - identity_key: IdentityKey, - ) -> Result { - let (pre_key_id, pre_key_public) = match pre_key { - None => (None, None), - Some((id, key)) => (Some(id), Some(key)), - }; - - Ok(Self { - registration_id, - device_id, - pre_key_id, - pre_key_public, - signed_pre_key_id, - signed_pre_key_public, - signed_pre_key_signature, - identity_key, - }) - } - - pub fn registration_id(&self) -> Result { - Ok(self.registration_id) - } - - pub fn device_id(&self) -> Result { - Ok(self.device_id) - } - - pub fn pre_key_id(&self) -> Result> { - Ok(self.pre_key_id) - } - - pub fn pre_key_public(&self) -> Result> { - Ok(self.pre_key_public) - } - - pub fn signed_pre_key_id(&self) -> Result { - Ok(self.signed_pre_key_id) - } - - pub fn signed_pre_key_public(&self) -> Result { - Ok(self.signed_pre_key_public) - } - - pub fn signed_pre_key_signature(&self) -> Result<&[u8]> { - Ok(self.signed_pre_key_signature.as_ref()) - } - - pub fn identity_key(&self) -> Result<&IdentityKey> { - Ok(&self.identity_key) - } -} diff --git a/net/gurk-rs/files/vendor/libsignal-protocol/src/state/prekey.rs b/net/gurk-rs/files/vendor/libsignal-protocol/src/state/prekey.rs deleted file mode 100644 index 5927a79..0000000 --- a/net/gurk-rs/files/vendor/libsignal-protocol/src/state/prekey.rs +++ /dev/null @@ -1,55 +0,0 @@ -// -// Copyright 2020 Signal Messenger, LLC. -// SPDX-License-Identifier: AGPL-3.0-only -// - -use crate::proto::storage::PreKeyRecordStructure; -use crate::{KeyPair, PrivateKey, PublicKey, Result}; -use prost::Message; - -pub type PreKeyId = u32; - -#[derive(Debug, Clone)] -pub struct PreKeyRecord { - pre_key: PreKeyRecordStructure, -} - -impl PreKeyRecord { - pub fn new(id: PreKeyId, key: &KeyPair) -> Self { - let public_key = key.public_key.serialize().to_vec(); - let private_key = key.private_key.serialize().to_vec(); - Self { - pre_key: PreKeyRecordStructure { - id, - public_key, - private_key, - }, - } - } - - pub fn deserialize(data: &[u8]) -> Result { - Ok(Self { - pre_key: PreKeyRecordStructure::decode(data)?, - }) - } - - pub fn id(&self) -> Result { - Ok(self.pre_key.id) - } - - pub fn key_pair(&self) -> Result { - KeyPair::from_public_and_private(&self.pre_key.public_key, &self.pre_key.private_key) - } - - pub fn public_key(&self) -> Result { - PublicKey::deserialize(&self.pre_key.public_key) - } - - pub fn private_key(&self) -> Result { - PrivateKey::deserialize(&self.pre_key.private_key) - } - - pub fn serialize(&self) -> Result> { - Ok(self.pre_key.encode_to_vec()) - } -} diff --git a/net/gurk-rs/files/vendor/libsignal-protocol/src/state/session.rs b/net/gurk-rs/files/vendor/libsignal-protocol/src/state/session.rs deleted file mode 100644 index 252fd00..0000000 --- a/net/gurk-rs/files/vendor/libsignal-protocol/src/state/session.rs +++ /dev/null @@ -1,640 +0,0 @@ -// -// Copyright 2020 Signal Messenger, LLC. -// SPDX-License-Identifier: AGPL-3.0-only -// - -use prost::Message; - -use crate::ratchet::{ChainKey, MessageKeys, RootKey}; -use crate::{IdentityKey, KeyPair, PrivateKey, PublicKey, Result, SignalProtocolError}; - -use crate::consts; -use crate::proto::storage::session_structure; -use crate::proto::storage::{RecordStructure, SessionStructure}; -use crate::state::{PreKeyId, SignedPreKeyId}; - -#[derive(Debug, Clone)] -pub(crate) struct UnacknowledgedPreKeyMessageItems { - pre_key_id: Option, - signed_pre_key_id: SignedPreKeyId, - base_key: PublicKey, -} - -impl UnacknowledgedPreKeyMessageItems { - fn new( - pre_key_id: Option, - signed_pre_key_id: SignedPreKeyId, - base_key: PublicKey, - ) -> Self { - Self { - pre_key_id, - signed_pre_key_id, - base_key, - } - } - - pub(crate) fn pre_key_id(&self) -> Result> { - Ok(self.pre_key_id) - } - - pub(crate) fn signed_pre_key_id(&self) -> Result { - Ok(self.signed_pre_key_id) - } - - pub(crate) fn base_key(&self) -> Result<&PublicKey> { - Ok(&self.base_key) - } -} - -#[derive(Clone, Debug)] -pub(crate) struct SessionState { - session: SessionStructure, -} - -impl SessionState { - pub(crate) fn new(session: SessionStructure) -> Self { - Self { session } - } - - pub(crate) fn alice_base_key(&self) -> Result<&[u8]> { - // Check the length before returning? - Ok(&self.session.alice_base_key) - } - - pub(crate) fn set_alice_base_key(&mut self, key: &[u8]) -> Result<()> { - // Should we check the length? - self.session.alice_base_key = key.to_vec(); - Ok(()) - } - - pub fn session_version(&self) -> Result { - match self.session.session_version { - 0 => Ok(2), - v => Ok(v), - } - } - - pub(crate) fn remote_identity_key(&self) -> Result> { - match self.session.remote_identity_public.len() { - 0 => Ok(None), - _ => Ok(Some(IdentityKey::decode( - &self.session.remote_identity_public, - )?)), - } - } - - pub(crate) fn remote_identity_key_bytes(&self) -> Result>> { - Ok(self.remote_identity_key()?.map(|k| k.serialize().to_vec())) - } - - pub(crate) fn local_identity_key(&self) -> Result { - IdentityKey::decode(&self.session.local_identity_public) - } - - pub(crate) fn local_identity_key_bytes(&self) -> Result> { - Ok(self.local_identity_key()?.serialize().to_vec()) - } - - pub(crate) fn session_with_self(&self) -> Result { - if let Some(remote_id) = self.remote_identity_key_bytes()? { - let local_id = self.local_identity_key_bytes()?; - return Ok(remote_id == local_id); - } - - // If remote ID is not set then we can't be sure but treat as non-self - Ok(false) - } - - pub(crate) fn previous_counter(&self) -> Result { - Ok(self.session.previous_counter) - } - - pub(crate) fn set_previous_counter(&mut self, ctr: u32) -> Result<()> { - self.session.previous_counter = ctr; - Ok(()) - } - - pub(crate) fn root_key(&self) -> Result { - if self.session.root_key.len() != 32 { - return Err(SignalProtocolError::InvalidProtobufEncoding); - } - RootKey::new(&self.session.root_key) - } - - pub(crate) fn set_root_key(&mut self, root_key: &RootKey) -> Result<()> { - self.session.root_key = root_key.key().to_vec(); - Ok(()) - } - - pub(crate) fn sender_ratchet_key(&self) -> Result { - match self.session.sender_chain { - None => Err(SignalProtocolError::InvalidProtobufEncoding), - Some(ref c) => PublicKey::deserialize(&c.sender_ratchet_key), - } - } - - pub(crate) fn sender_ratchet_key_for_logging(&self) -> Result { - self.sender_ratchet_key()? - .public_key_bytes() - .map(hex::encode) - } - - pub(crate) fn sender_ratchet_private_key(&self) -> Result { - match self.session.sender_chain { - None => Err(SignalProtocolError::InvalidProtobufEncoding), - Some(ref c) => PrivateKey::deserialize(&c.sender_ratchet_key_private), - } - } - - pub fn has_sender_chain(&self) -> Result { - Ok(self.session.sender_chain.is_some()) - } - - pub(crate) fn all_receiver_chain_logging_info(&self) -> Result, Option)>> { - let mut results = vec![]; - for chain in self.session.receiver_chains.iter() { - let sender_ratchet_public = chain.sender_ratchet_key.clone(); - - let chain_key_idx = chain.chain_key.as_ref().map(|chain_key| chain_key.index); - - results.push((sender_ratchet_public, chain_key_idx)) - } - Ok(results) - } - - pub(crate) fn get_receiver_chain( - &self, - sender: &PublicKey, - ) -> Result> { - let sender_bytes = sender.serialize(); - - for (idx, chain) in self.session.receiver_chains.iter().enumerate() { - /* - If we compared bytes directly without a deserialize + serialize pair it would - be faster, but may miss non-canonical points. It's unclear if supporting such - points is desirable. - */ - let this_point = PublicKey::deserialize(&chain.sender_ratchet_key)?.serialize(); - - if this_point == sender_bytes { - return Ok(Some((chain.clone(), idx))); - } - } - - Ok(None) - } - - pub(crate) fn get_receiver_chain_key(&self, sender: &PublicKey) -> Result> { - match self.get_receiver_chain(sender)? { - None => Ok(None), - Some((chain, _)) => match chain.chain_key { - None => Err(SignalProtocolError::InvalidProtobufEncoding), - Some(c) => { - if c.key.len() != 32 { - return Err(SignalProtocolError::InvalidProtobufEncoding); - } - Ok(Some(ChainKey::new(&c.key, c.index)?)) - } - }, - } - } - - pub(crate) fn add_receiver_chain( - &mut self, - sender: &PublicKey, - chain_key: &ChainKey, - ) -> Result<()> { - let chain_key = session_structure::chain::ChainKey { - index: chain_key.index(), - key: chain_key.key().to_vec(), - }; - - let chain = session_structure::Chain { - sender_ratchet_key: sender.serialize().to_vec(), - sender_ratchet_key_private: vec![], - chain_key: Some(chain_key), - message_keys: vec![], - }; - - self.session.receiver_chains.push(chain); - - if self.session.receiver_chains.len() > consts::MAX_RECEIVER_CHAINS { - log::info!( - "Trimming excessive receiver_chain for session with base key {}, chain count: {}", - self.sender_ratchet_key_for_logging() - .unwrap_or_else(|e| format!("", e)), - self.session.receiver_chains.len() - ); - self.session.receiver_chains.remove(0); - } - - Ok(()) - } - - pub(crate) fn set_sender_chain( - &mut self, - sender: &KeyPair, - next_chain_key: &ChainKey, - ) -> Result<()> { - let chain_key = session_structure::chain::ChainKey { - index: next_chain_key.index(), - key: next_chain_key.key().to_vec(), - }; - - let new_chain = session_structure::Chain { - sender_ratchet_key: sender.public_key.serialize().to_vec(), - sender_ratchet_key_private: sender.private_key.serialize().to_vec(), - chain_key: Some(chain_key), - message_keys: vec![], - }; - - self.session.sender_chain = Some(new_chain); - - Ok(()) - } - - pub(crate) fn get_sender_chain_key(&self) -> Result { - let sender_chain = self.session.sender_chain.as_ref().ok_or_else(|| { - SignalProtocolError::InvalidState("get_sender_chain_key", "No chain".to_owned()) - })?; - - let chain_key = sender_chain.chain_key.as_ref().ok_or_else(|| { - SignalProtocolError::InvalidState("get_sender_chain_key", "No chain key".to_owned()) - })?; - - ChainKey::new(&chain_key.key, chain_key.index) - } - - pub(crate) fn get_sender_chain_key_bytes(&self) -> Result> { - Ok(self.get_sender_chain_key()?.key().to_vec()) - } - - pub(crate) fn set_sender_chain_key(&mut self, next_chain_key: &ChainKey) -> Result<()> { - let chain_key = session_structure::chain::ChainKey { - index: next_chain_key.index(), - key: next_chain_key.key().to_vec(), - }; - - // Is it actually valid to call this function with sender_chain == None? - - let new_chain = match self.session.sender_chain.take() { - None => session_structure::Chain { - sender_ratchet_key: vec![], - sender_ratchet_key_private: vec![], - chain_key: Some(chain_key), - message_keys: vec![], - }, - Some(mut c) => { - c.chain_key = Some(chain_key); - c - } - }; - - self.session.sender_chain = Some(new_chain); - - Ok(()) - } - - pub(crate) fn get_message_keys( - &mut self, - sender: &PublicKey, - counter: u32, - ) -> Result> { - if let Some(mut chain_and_index) = self.get_receiver_chain(sender)? { - let message_key_idx = chain_and_index - .0 - .message_keys - .iter() - .position(|m| m.index == counter); - if let Some(position) = message_key_idx { - let message_key = chain_and_index.0.message_keys.remove(position); - - let keys = MessageKeys::new( - &message_key.cipher_key, - &message_key.mac_key, - &message_key.iv, - counter, - )?; - - // Update with message key removed - self.session.receiver_chains[chain_and_index.1] = chain_and_index.0; - return Ok(Some(keys)); - } - } - - Ok(None) - } - - pub(crate) fn set_message_keys( - &mut self, - sender: &PublicKey, - message_keys: &MessageKeys, - ) -> Result<()> { - let new_keys = session_structure::chain::MessageKey { - cipher_key: message_keys.cipher_key().to_vec(), - mac_key: message_keys.mac_key().to_vec(), - iv: message_keys.iv().to_vec(), - index: message_keys.counter(), - }; - - if let Some(chain_and_index) = self.get_receiver_chain(sender)? { - let mut updated_chain = chain_and_index.0; - updated_chain.message_keys.insert(0, new_keys); - - if updated_chain.message_keys.len() > consts::MAX_MESSAGE_KEYS { - updated_chain.message_keys.pop(); - } - - self.session.receiver_chains[chain_and_index.1] = updated_chain; - Ok(()) - } else { - Err(SignalProtocolError::InvalidState( - "set_message_keys", - "No receiver".to_string(), - )) - } - } - - pub(crate) fn set_receiver_chain_key( - &mut self, - sender: &PublicKey, - chain_key: &ChainKey, - ) -> Result<()> { - if let Some(chain_and_index) = self.get_receiver_chain(sender)? { - let mut updated_chain = chain_and_index.0; - updated_chain.chain_key = Some(session_structure::chain::ChainKey { - index: chain_key.index(), - key: chain_key.key().to_vec(), - }); - - self.session.receiver_chains[chain_and_index.1] = updated_chain; - return Ok(()); - } - - Err(SignalProtocolError::InvalidState( - "set_receiver_chain_key", - "No receiver".to_string(), - )) - } - - pub(crate) fn set_unacknowledged_pre_key_message( - &mut self, - pre_key_id: Option, - signed_pre_key_id: SignedPreKeyId, - base_key: &PublicKey, - ) -> Result<()> { - let pending = session_structure::PendingPreKey { - pre_key_id: pre_key_id.unwrap_or(0), - signed_pre_key_id: signed_pre_key_id as i32, - base_key: base_key.serialize().to_vec(), - }; - self.session.pending_pre_key = Some(pending); - Ok(()) - } - - pub(crate) fn unacknowledged_pre_key_message_items( - &self, - ) -> Result> { - if let Some(ref pending_pre_key) = self.session.pending_pre_key { - Ok(Some(UnacknowledgedPreKeyMessageItems::new( - match pending_pre_key.pre_key_id { - 0 => None, - v => Some(v), - }, - pending_pre_key.signed_pre_key_id as SignedPreKeyId, - PublicKey::deserialize(&pending_pre_key.base_key)?, - ))) - } else { - Ok(None) - } - } - - pub(crate) fn clear_unacknowledged_pre_key_message(&mut self) -> Result<()> { - self.session.pending_pre_key = None; - Ok(()) - } - - pub(crate) fn set_remote_registration_id(&mut self, registration_id: u32) -> Result<()> { - self.session.remote_registration_id = registration_id; - Ok(()) - } - - pub(crate) fn remote_registration_id(&self) -> Result { - Ok(self.session.remote_registration_id) - } - - pub(crate) fn set_local_registration_id(&mut self, registration_id: u32) -> Result<()> { - self.session.local_registration_id = registration_id; - Ok(()) - } - - pub(crate) fn local_registration_id(&self) -> Result { - Ok(self.session.local_registration_id) - } -} - -impl From for SessionState { - fn from(value: SessionStructure) -> SessionState { - SessionState::new(value) - } -} - -impl From for SessionStructure { - fn from(value: SessionState) -> SessionStructure { - value.session - } -} - -impl From<&SessionState> for SessionStructure { - fn from(value: &SessionState) -> SessionStructure { - value.session.clone() - } -} - -#[derive(Clone, Debug)] -pub struct SessionRecord { - current_session: Option, - previous_sessions: Vec>, -} - -impl SessionRecord { - pub fn new_fresh() -> Self { - Self { - current_session: None, - previous_sessions: Vec::new(), - } - } - - pub(crate) fn new(state: SessionState) -> Self { - Self { - current_session: Some(state), - previous_sessions: Vec::new(), - } - } - - pub fn deserialize(bytes: &[u8]) -> Result { - let record = RecordStructure::decode(bytes)?; - - Ok(Self { - current_session: record.current_session.map(|s| s.into()), - previous_sessions: record.previous_sessions, - }) - } - - pub fn from_single_session_state(bytes: &[u8]) -> Result { - let session = SessionState::new(SessionStructure::decode(bytes)?); - Ok(Self { - current_session: Some(session), - previous_sessions: Vec::new(), - }) - } - - pub(crate) fn has_session_state(&self, version: u32, alice_base_key: &[u8]) -> Result { - if let Some(current_session) = &self.current_session { - if current_session.session_version()? == version - && alice_base_key == current_session.alice_base_key()? - { - return Ok(true); - } - } - - for previous in self.previous_session_states() { - let previous = previous?; - if previous.session_version()? == version - && alice_base_key == previous.alice_base_key()? - { - return Ok(true); - } - } - - Ok(false) - } - - pub fn has_current_session_state(&self) -> bool { - self.current_session.is_some() - } - - pub(crate) fn session_state(&self) -> Result<&SessionState> { - if let Some(ref session) = self.current_session { - Ok(session) - } else { - Err(SignalProtocolError::InvalidState( - "session_state", - "No session".into(), - )) - } - } - - pub(crate) fn session_state_mut(&mut self) -> Result<&mut SessionState> { - if let Some(ref mut session) = self.current_session { - Ok(session) - } else { - Err(SignalProtocolError::InvalidState( - "session_state", - "No session".into(), - )) - } - } - - pub(crate) fn set_session_state(&mut self, session: SessionState) -> Result<()> { - self.current_session = Some(session); - Ok(()) - } - - pub(crate) fn previous_session_states( - &self, - ) -> impl ExactSizeIterator> + '_ { - self.previous_sessions - .iter() - .map(|bytes| Ok(SessionStructure::decode(&bytes[..])?.into())) - } - - pub(crate) fn promote_old_session( - &mut self, - old_session: usize, - updated_session: SessionState, - ) -> Result<()> { - if old_session >= self.previous_sessions.len() { - return Err(SignalProtocolError::InvalidState( - "promote_old_session", - "out of range".into(), - )); - } - self.previous_sessions.remove(old_session); - self.promote_state(updated_session) - } - - pub(crate) fn promote_state(&mut self, new_state: SessionState) -> Result<()> { - self.archive_current_state()?; - self.current_session = Some(new_state); - Ok(()) - } - - pub fn archive_current_state(&mut self) -> Result<()> { - if let Some(current_session) = self.current_session.take() { - if self.previous_sessions.len() >= consts::ARCHIVED_STATES_MAX_LENGTH { - self.previous_sessions.pop(); - } - self.previous_sessions - .insert(0, current_session.session.encode_to_vec()); - } else { - log::info!("Skipping archive, current session state is fresh",); - } - - Ok(()) - } - - pub fn serialize(&self) -> Result> { - let record = RecordStructure { - current_session: self.current_session.as_ref().map(|s| s.into()), - previous_sessions: self.previous_sessions.clone(), - }; - Ok(record.encode_to_vec()) - } - - pub fn remote_registration_id(&self) -> Result { - self.session_state()?.remote_registration_id() - } - - pub fn local_registration_id(&self) -> Result { - self.session_state()?.local_registration_id() - } - - pub fn session_version(&self) -> Result { - self.session_state()?.session_version() - } - - pub fn local_identity_key_bytes(&self) -> Result> { - self.session_state()?.local_identity_key_bytes() - } - - pub fn remote_identity_key_bytes(&self) -> Result>> { - self.session_state()?.remote_identity_key_bytes() - } - - pub fn has_sender_chain(&self) -> Result { - match &self.current_session { - Some(session) => session.has_sender_chain(), - None => Ok(false), - } - } - - pub fn alice_base_key(&self) -> Result<&[u8]> { - self.session_state()?.alice_base_key() - } - - pub fn get_receiver_chain_key(&self, sender: &PublicKey) -> Result> { - self.session_state()?.get_receiver_chain_key(sender) - } - - pub fn get_sender_chain_key_bytes(&self) -> Result> { - self.session_state()?.get_sender_chain_key_bytes() - } - - pub fn current_ratchet_key_matches(&self, key: &PublicKey) -> Result { - match &self.current_session { - Some(session) => Ok(&session.sender_ratchet_key()? == key), - None => Ok(false), - } - } -} diff --git a/net/gurk-rs/files/vendor/libsignal-protocol/src/state/signed_prekey.rs b/net/gurk-rs/files/vendor/libsignal-protocol/src/state/signed_prekey.rs deleted file mode 100644 index b6f3575..0000000 --- a/net/gurk-rs/files/vendor/libsignal-protocol/src/state/signed_prekey.rs +++ /dev/null @@ -1,69 +0,0 @@ -// -// Copyright 2020 Signal Messenger, LLC. -// SPDX-License-Identifier: AGPL-3.0-only -// - -use crate::proto::storage::SignedPreKeyRecordStructure; -use crate::{KeyPair, PrivateKey, PublicKey, Result}; -use prost::Message; - -pub type SignedPreKeyId = u32; - -#[derive(Debug, Clone)] -pub struct SignedPreKeyRecord { - signed_pre_key: SignedPreKeyRecordStructure, -} - -impl SignedPreKeyRecord { - pub fn new(id: SignedPreKeyId, timestamp: u64, key: &KeyPair, signature: &[u8]) -> Self { - let public_key = key.public_key.serialize().to_vec(); - let private_key = key.private_key.serialize().to_vec(); - let signature = signature.to_vec(); - Self { - signed_pre_key: SignedPreKeyRecordStructure { - id, - timestamp, - public_key, - private_key, - signature, - }, - } - } - - pub fn deserialize(data: &[u8]) -> Result { - Ok(Self { - signed_pre_key: SignedPreKeyRecordStructure::decode(data)?, - }) - } - - pub fn id(&self) -> Result { - Ok(self.signed_pre_key.id) - } - - pub fn timestamp(&self) -> Result { - Ok(self.signed_pre_key.timestamp) - } - - pub fn signature(&self) -> Result> { - Ok(self.signed_pre_key.signature.clone()) - } - - pub fn public_key(&self) -> Result { - PublicKey::deserialize(&self.signed_pre_key.public_key) - } - - pub fn private_key(&self) -> Result { - PrivateKey::deserialize(&self.signed_pre_key.private_key) - } - - pub fn key_pair(&self) -> Result { - KeyPair::from_public_and_private( - &self.signed_pre_key.public_key, - &self.signed_pre_key.private_key, - ) - } - - pub fn serialize(&self) -> Result> { - Ok(self.signed_pre_key.encode_to_vec()) - } -} diff --git a/net/gurk-rs/files/vendor/libsignal-protocol/src/storage.rs b/net/gurk-rs/files/vendor/libsignal-protocol/src/storage.rs deleted file mode 100644 index 5ab1ed5..0000000 --- a/net/gurk-rs/files/vendor/libsignal-protocol/src/storage.rs +++ /dev/null @@ -1,18 +0,0 @@ -// -// Copyright 2020 Signal Messenger, LLC. -// SPDX-License-Identifier: AGPL-3.0-only -// - -mod inmem; -mod traits; - -pub use { - inmem::{ - InMemIdentityKeyStore, InMemPreKeyStore, InMemSenderKeyStore, InMemSessionStore, - InMemSignalProtocolStore, InMemSignedPreKeyStore, - }, - traits::{ - Context, Direction, IdentityKeyStore, PreKeyStore, ProtocolStore, SenderKeyStore, - SessionStore, SignedPreKeyStore, - }, -}; diff --git a/net/gurk-rs/files/vendor/libsignal-protocol/src/storage/inmem.rs b/net/gurk-rs/files/vendor/libsignal-protocol/src/storage/inmem.rs deleted file mode 100644 index 3567ac0..0000000 --- a/net/gurk-rs/files/vendor/libsignal-protocol/src/storage/inmem.rs +++ /dev/null @@ -1,454 +0,0 @@ -// -// Copyright 2020 Signal Messenger, LLC. -// SPDX-License-Identifier: AGPL-3.0-only -// - -use crate::{ - IdentityKey, IdentityKeyPair, PreKeyRecord, ProtocolAddress, Result, SenderKeyRecord, - SessionRecord, SignalProtocolError, SignedPreKeyRecord, -}; - -use crate::state::{PreKeyId, SignedPreKeyId}; -use crate::storage::traits; -use crate::storage::Context; - -use async_trait::async_trait; -use std::borrow::Cow; -use std::collections::HashMap; -use uuid::Uuid; - -#[derive(Clone)] -pub struct InMemIdentityKeyStore { - key_pair: IdentityKeyPair, - id: u32, - known_keys: HashMap, -} - -impl InMemIdentityKeyStore { - pub fn new(key_pair: IdentityKeyPair, id: u32) -> Self { - Self { - key_pair, - id, - known_keys: HashMap::new(), - } - } - - pub fn reset(&mut self) { - self.known_keys.clear(); - } -} - -#[async_trait(?Send)] -impl traits::IdentityKeyStore for InMemIdentityKeyStore { - async fn get_identity_key_pair(&self, _ctx: Context) -> Result { - Ok(self.key_pair) - } - - async fn get_local_registration_id(&self, _ctx: Context) -> Result { - Ok(self.id) - } - - async fn save_identity( - &mut self, - address: &ProtocolAddress, - identity: &IdentityKey, - _ctx: Context, - ) -> Result { - match self.known_keys.get(address) { - None => { - self.known_keys.insert(address.clone(), *identity); - Ok(false) // new key - } - Some(k) if k == identity => { - Ok(false) // same key - } - Some(_k) => { - self.known_keys.insert(address.clone(), *identity); - Ok(true) // overwrite - } - } - } - - async fn is_trusted_identity( - &self, - address: &ProtocolAddress, - identity: &IdentityKey, - _direction: traits::Direction, - _ctx: Context, - ) -> Result { - match self.known_keys.get(address) { - None => { - Ok(true) // first use - } - Some(k) => Ok(k == identity), - } - } - - async fn get_identity( - &self, - address: &ProtocolAddress, - _ctx: Context, - ) -> Result> { - match self.known_keys.get(address) { - None => Ok(None), - Some(k) => Ok(Some(k.to_owned())), - } - } -} - -#[derive(Clone)] -pub struct InMemPreKeyStore { - pre_keys: HashMap, -} - -impl InMemPreKeyStore { - pub fn new() -> Self { - Self { - pre_keys: HashMap::new(), - } - } -} - -impl Default for InMemPreKeyStore { - fn default() -> Self { - Self::new() - } -} - -#[async_trait(?Send)] -impl traits::PreKeyStore for InMemPreKeyStore { - async fn get_pre_key(&self, id: PreKeyId, _ctx: Context) -> Result { - Ok(self - .pre_keys - .get(&id) - .ok_or(SignalProtocolError::InvalidPreKeyId)? - .clone()) - } - - async fn save_pre_key( - &mut self, - id: PreKeyId, - record: &PreKeyRecord, - _ctx: Context, - ) -> Result<()> { - // This overwrites old values, which matches Java behavior, but is it correct? - self.pre_keys.insert(id, record.to_owned()); - Ok(()) - } - - async fn remove_pre_key(&mut self, id: PreKeyId, _ctx: Context) -> Result<()> { - // If id does not exist this silently does nothing - self.pre_keys.remove(&id); - Ok(()) - } -} - -#[derive(Clone)] -pub struct InMemSignedPreKeyStore { - signed_pre_keys: HashMap, -} - -impl InMemSignedPreKeyStore { - pub fn new() -> Self { - Self { - signed_pre_keys: HashMap::new(), - } - } -} - -impl Default for InMemSignedPreKeyStore { - fn default() -> Self { - Self::new() - } -} - -#[async_trait(?Send)] -impl traits::SignedPreKeyStore for InMemSignedPreKeyStore { - async fn get_signed_pre_key( - &self, - id: SignedPreKeyId, - _ctx: Context, - ) -> Result { - Ok(self - .signed_pre_keys - .get(&id) - .ok_or(SignalProtocolError::InvalidSignedPreKeyId)? - .clone()) - } - - async fn save_signed_pre_key( - &mut self, - id: SignedPreKeyId, - record: &SignedPreKeyRecord, - _ctx: Context, - ) -> Result<()> { - // This overwrites old values, which matches Java behavior, but is it correct? - self.signed_pre_keys.insert(id, record.to_owned()); - Ok(()) - } -} - -#[derive(Clone)] -pub struct InMemSessionStore { - sessions: HashMap, -} - -impl InMemSessionStore { - pub fn new() -> Self { - Self { - sessions: HashMap::new(), - } - } - - /// Bulk version of [`SessionStore::load_session`]. - /// - /// Useful for [crate::sealed_sender_multi_recipient_encrypt]. - /// - /// [`SessionStore::load_session`]: crate::SessionStore::load_session - pub fn load_existing_sessions( - &self, - addresses: &[&ProtocolAddress], - ) -> Result> { - addresses - .iter() - .map(|address| { - self.sessions - .get(address) - .ok_or_else(|| SignalProtocolError::SessionNotFound(address.to_string())) - }) - .collect() - } -} - -impl Default for InMemSessionStore { - fn default() -> Self { - Self::new() - } -} - -#[async_trait(?Send)] -impl traits::SessionStore for InMemSessionStore { - async fn load_session( - &self, - address: &ProtocolAddress, - _ctx: Context, - ) -> Result> { - match self.sessions.get(address) { - None => Ok(None), - Some(s) => Ok(Some(s.clone())), - } - } - - async fn store_session( - &mut self, - address: &ProtocolAddress, - record: &SessionRecord, - _ctx: Context, - ) -> Result<()> { - self.sessions.insert(address.clone(), record.clone()); - Ok(()) - } -} - -#[derive(Clone)] -pub struct InMemSenderKeyStore { - // We use Cow keys in order to store owned values but compare to referenced ones. - // See https://users.rust-lang.org/t/hashmap-with-tuple-keys/12711/6. - keys: HashMap<(Cow<'static, ProtocolAddress>, Uuid), SenderKeyRecord>, -} - -impl InMemSenderKeyStore { - pub fn new() -> Self { - Self { - keys: HashMap::new(), - } - } -} - -impl Default for InMemSenderKeyStore { - fn default() -> Self { - Self::new() - } -} - -#[async_trait(?Send)] -impl traits::SenderKeyStore for InMemSenderKeyStore { - async fn store_sender_key( - &mut self, - sender: &ProtocolAddress, - distribution_id: Uuid, - record: &SenderKeyRecord, - _ctx: Context, - ) -> Result<()> { - self.keys.insert( - (Cow::Owned(sender.clone()), distribution_id), - record.clone(), - ); - Ok(()) - } - - async fn load_sender_key( - &mut self, - sender: &ProtocolAddress, - distribution_id: Uuid, - _ctx: Context, - ) -> Result> { - Ok(self - .keys - .get(&(Cow::Borrowed(sender), distribution_id)) - .cloned()) - } -} - -#[derive(Clone)] -pub struct InMemSignalProtocolStore { - pub session_store: InMemSessionStore, - pub pre_key_store: InMemPreKeyStore, - pub signed_pre_key_store: InMemSignedPreKeyStore, - pub identity_store: InMemIdentityKeyStore, - pub sender_key_store: InMemSenderKeyStore, -} - -impl InMemSignalProtocolStore { - pub fn new(key_pair: IdentityKeyPair, registration_id: u32) -> Result { - Ok(Self { - session_store: InMemSessionStore::new(), - pre_key_store: InMemPreKeyStore::new(), - signed_pre_key_store: InMemSignedPreKeyStore::new(), - identity_store: InMemIdentityKeyStore::new(key_pair, registration_id), - sender_key_store: InMemSenderKeyStore::new(), - }) - } -} - -#[async_trait(?Send)] -impl traits::IdentityKeyStore for InMemSignalProtocolStore { - async fn get_identity_key_pair(&self, ctx: Context) -> Result { - self.identity_store.get_identity_key_pair(ctx).await - } - - async fn get_local_registration_id(&self, ctx: Context) -> Result { - self.identity_store.get_local_registration_id(ctx).await - } - - async fn save_identity( - &mut self, - address: &ProtocolAddress, - identity: &IdentityKey, - ctx: Context, - ) -> Result { - self.identity_store - .save_identity(address, identity, ctx) - .await - } - - async fn is_trusted_identity( - &self, - address: &ProtocolAddress, - identity: &IdentityKey, - direction: traits::Direction, - ctx: Context, - ) -> Result { - self.identity_store - .is_trusted_identity(address, identity, direction, ctx) - .await - } - - async fn get_identity( - &self, - address: &ProtocolAddress, - ctx: Context, - ) -> Result> { - self.identity_store.get_identity(address, ctx).await - } -} - -#[async_trait(?Send)] -impl traits::PreKeyStore for InMemSignalProtocolStore { - async fn get_pre_key(&self, id: PreKeyId, ctx: Context) -> Result { - self.pre_key_store.get_pre_key(id, ctx).await - } - - async fn save_pre_key( - &mut self, - id: PreKeyId, - record: &PreKeyRecord, - ctx: Context, - ) -> Result<()> { - self.pre_key_store.save_pre_key(id, record, ctx).await - } - - async fn remove_pre_key(&mut self, id: PreKeyId, ctx: Context) -> Result<()> { - self.pre_key_store.remove_pre_key(id, ctx).await - } -} - -#[async_trait(?Send)] -impl traits::SignedPreKeyStore for InMemSignalProtocolStore { - async fn get_signed_pre_key( - &self, - id: SignedPreKeyId, - ctx: Context, - ) -> Result { - self.signed_pre_key_store.get_signed_pre_key(id, ctx).await - } - - async fn save_signed_pre_key( - &mut self, - id: SignedPreKeyId, - record: &SignedPreKeyRecord, - ctx: Context, - ) -> Result<()> { - self.signed_pre_key_store - .save_signed_pre_key(id, record, ctx) - .await - } -} - -#[async_trait(?Send)] -impl traits::SessionStore for InMemSignalProtocolStore { - async fn load_session( - &self, - address: &ProtocolAddress, - ctx: Context, - ) -> Result> { - self.session_store.load_session(address, ctx).await - } - - async fn store_session( - &mut self, - address: &ProtocolAddress, - record: &SessionRecord, - ctx: Context, - ) -> Result<()> { - self.session_store.store_session(address, record, ctx).await - } -} - -#[async_trait(?Send)] -impl traits::SenderKeyStore for InMemSignalProtocolStore { - async fn store_sender_key( - &mut self, - sender: &ProtocolAddress, - distribution_id: Uuid, - record: &SenderKeyRecord, - ctx: Context, - ) -> Result<()> { - self.sender_key_store - .store_sender_key(sender, distribution_id, record, ctx) - .await - } - - async fn load_sender_key( - &mut self, - sender: &ProtocolAddress, - distribution_id: Uuid, - ctx: Context, - ) -> Result> { - self.sender_key_store - .load_sender_key(sender, distribution_id, ctx) - .await - } -} - -impl traits::ProtocolStore for InMemSignalProtocolStore {} diff --git a/net/gurk-rs/files/vendor/libsignal-protocol/src/storage/traits.rs b/net/gurk-rs/files/vendor/libsignal-protocol/src/storage/traits.rs deleted file mode 100644 index e3c1572..0000000 --- a/net/gurk-rs/files/vendor/libsignal-protocol/src/storage/traits.rs +++ /dev/null @@ -1,115 +0,0 @@ -// -// Copyright 2020 Signal Messenger, LLC. -// SPDX-License-Identifier: AGPL-3.0-only -// - -use async_trait::async_trait; -use uuid::Uuid; - -use crate::state::{PreKeyId, SignedPreKeyId}; -use crate::{ - IdentityKey, IdentityKeyPair, PreKeyRecord, ProtocolAddress, Result, SenderKeyRecord, - SessionRecord, SignedPreKeyRecord, -}; - -pub type Context = Option<*mut std::ffi::c_void>; - -#[derive(Debug, Clone, Eq, PartialEq)] -pub enum Direction { - Sending, - Receiving, -} - -#[async_trait(?Send)] -pub trait IdentityKeyStore { - async fn get_identity_key_pair(&self, ctx: Context) -> Result; - - async fn get_local_registration_id(&self, ctx: Context) -> Result; - - async fn save_identity( - &mut self, - address: &ProtocolAddress, - identity: &IdentityKey, - ctx: Context, - ) -> Result; - - async fn is_trusted_identity( - &self, - address: &ProtocolAddress, - identity: &IdentityKey, - direction: Direction, - ctx: Context, - ) -> Result; - - async fn get_identity( - &self, - address: &ProtocolAddress, - ctx: Context, - ) -> Result>; -} - -#[async_trait(?Send)] -pub trait PreKeyStore { - async fn get_pre_key(&self, prekey_id: PreKeyId, ctx: Context) -> Result; - - async fn save_pre_key( - &mut self, - prekey_id: PreKeyId, - record: &PreKeyRecord, - ctx: Context, - ) -> Result<()>; - - async fn remove_pre_key(&mut self, prekey_id: PreKeyId, ctx: Context) -> Result<()>; -} - -#[async_trait(?Send)] -pub trait SignedPreKeyStore { - async fn get_signed_pre_key( - &self, - signed_prekey_id: SignedPreKeyId, - ctx: Context, - ) -> Result; - - async fn save_signed_pre_key( - &mut self, - signed_prekey_id: SignedPreKeyId, - record: &SignedPreKeyRecord, - ctx: Context, - ) -> Result<()>; -} - -#[async_trait(?Send)] -pub trait SessionStore { - async fn load_session( - &self, - address: &ProtocolAddress, - ctx: Context, - ) -> Result>; - - async fn store_session( - &mut self, - address: &ProtocolAddress, - record: &SessionRecord, - ctx: Context, - ) -> Result<()>; -} - -#[async_trait(?Send)] -pub trait SenderKeyStore { - async fn store_sender_key( - &mut self, - sender: &ProtocolAddress, - distribution_id: Uuid, - record: &SenderKeyRecord, - ctx: Context, - ) -> Result<()>; - - async fn load_sender_key( - &mut self, - sender: &ProtocolAddress, - distribution_id: Uuid, - ctx: Context, - ) -> Result>; -} - -pub trait ProtocolStore: SessionStore + PreKeyStore + SignedPreKeyStore + IdentityKeyStore {} diff --git a/net/gurk-rs/files/vendor/libsignal-protocol/src/utils.rs b/net/gurk-rs/files/vendor/libsignal-protocol/src/utils.rs deleted file mode 100644 index 67a108c..0000000 --- a/net/gurk-rs/files/vendor/libsignal-protocol/src/utils.rs +++ /dev/null @@ -1,141 +0,0 @@ -// -// Copyright 2020 Signal Messenger, LLC. -// SPDX-License-Identifier: AGPL-3.0-only -// - -use std::cmp::Ordering; - -fn expand_top_bit(a: u8) -> u8 { - //if (a >> 7) == 1 { 0xFF } else { 0 } - 0u8.wrapping_sub(a >> 7) -} - -fn ct_is_zero(a: u8) -> u8 { - //if a == 0 { 0xFF } else { 0 } - expand_top_bit(!a & a.wrapping_sub(1)) -} - -fn ct_is_eq(a: u8, b: u8) -> u8 { - //if a == b { 0xFF } else { 0 } - ct_is_zero(a ^ b) -} - -fn ct_is_lt(a: u8, b: u8) -> u8 { - //if a < b { 0xFF } else { 0 } - expand_top_bit(a ^ ((a ^ b) | ((a.wrapping_sub(b)) ^ a))) -} - -fn ct_select(mask: u8, a: u8, b: u8) -> u8 { - debug_assert!(mask == 0 || mask == 0xFF); - //if mask == 0xFF { a } else if mask == 0x00 { b } else { unreachable!(); } - b ^ (mask & (a ^ b)) -} - -/* -* If x and y are different lengths, this leaks information about -* their relative sizes. This is irrelevant as we always invoke it -* with two inputs of the same size. -* -* In addition it will leak the final comparison result, when the -* integer is translated to the Ordering enum. This seems unavoidable. -* -* The primary goal of this function is to not leak any additional -* information, besides the ordering, about the value of the two keys, -* say due to an early exit of the loop. -* -* It would be possible to instead have this function SHA-256 hash both -* inputs, then compare the resulting hashes in the usual non-const -* time way. We avoid this approach at the moment since it is not clear -* if applications will rely on public key ordering being defined in -* some particular way or not. - */ - -pub(crate) fn constant_time_cmp(x: &[u8], y: &[u8]) -> Ordering { - if x.len() < y.len() { - return Ordering::Less; - } - if x.len() > y.len() { - return Ordering::Greater; - } - - let mut result: u8 = 0; - - for i in 0..x.len() { - let a = x[x.len() - 1 - i]; - let b = y[x.len() - 1 - i]; - - let is_eq = ct_is_eq(a, b); - let is_lt = ct_is_lt(a, b); - - result = ct_select(is_eq, result, ct_select(is_lt, 1, 255)); - } - - debug_assert!(result == 0 || result == 1 || result == 255); - - if result == 0 { - Ordering::Equal - } else if result == 1 { - Ordering::Less - } else { - Ordering::Greater - } -} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_constant_time_cmp() { - use rand::Rng; - - assert_eq!(constant_time_cmp(&[1], &[1]), Ordering::Equal); - assert_eq!(constant_time_cmp(&[0, 1], &[1]), Ordering::Greater); - assert_eq!(constant_time_cmp(&[1], &[0, 1]), Ordering::Less); - assert_eq!(constant_time_cmp(&[2], &[1, 0, 1]), Ordering::Less); - - let mut rng = rand::rngs::OsRng; - for len in 1..320 { - let x: Vec = (0..len).map(|_| rng.gen()).collect(); - let y: Vec = (0..len).map(|_| rng.gen()).collect(); - let expected = x.cmp(&y); - let result = constant_time_cmp(&x, &y); - assert_eq!(result, expected); - - let expected = y.cmp(&x); - let result = constant_time_cmp(&y, &x); - assert_eq!(result, expected); - } - } - - #[test] - fn test_ct_is_zero() { - assert_eq!(ct_is_zero(0), 0xFF); - - for i in 1..255 { - assert_eq!(ct_is_zero(i), 0x00); - } - } - - #[test] - fn test_ct_is_lt() { - for x in 0..255 { - for y in 0..255 { - let expected = if x < y { 0xFF } else { 0 }; - let result = ct_is_lt(x, y); - assert_eq!(result, expected); - } - } - } - - #[test] - fn test_ct_is_eq() { - for x in 0..255 { - for y in 0..255 { - let expected = if x == y { 0xFF } else { 0 }; - let result = ct_is_eq(x, y); - assert_eq!(result, expected); - } - } - } -} diff --git a/net/gurk-rs/files/vendor/libsignal-protocol/tests/groups.rs b/net/gurk-rs/files/vendor/libsignal-protocol/tests/groups.rs deleted file mode 100644 index 87b5039..0000000 --- a/net/gurk-rs/files/vendor/libsignal-protocol/tests/groups.rs +++ /dev/null @@ -1,874 +0,0 @@ -// -// Copyright 2020 Signal Messenger, LLC. -// SPDX-License-Identifier: AGPL-3.0-only -// - -mod support; - -use async_trait::async_trait; -use futures_util::FutureExt; -use libsignal_protocol::*; -use rand::rngs::OsRng; -use rand::seq::SliceRandom; -use rand::Rng; -use std::convert::TryFrom; -use support::*; -use uuid::Uuid; - -#[test] -fn group_no_send_session() -> Result<(), SignalProtocolError> { - let mut csprng = OsRng; - - let sender_address = ProtocolAddress::new("+14159999111".to_owned(), 1); - let distribution_id = Uuid::from_u128(0xd1d1d1d1_7000_11eb_b32a_33b8a8a487a6); - - let mut alice_store = test_in_memory_protocol_store()?; - - assert!(group_encrypt( - &mut alice_store, - &sender_address, - distribution_id, - "space camp?".as_bytes(), - &mut csprng, - None, - ) - .now_or_never() - .expect("sync") - .is_err()); - - Ok(()) -} - -pub struct ContextUsingSenderKeyStore { - store: InMemSenderKeyStore, - expected_context: Context, -} - -impl ContextUsingSenderKeyStore { - pub fn new(expected_context: Context) -> Self { - Self { - store: InMemSenderKeyStore::new(), - expected_context, - } - } -} - -#[async_trait(?Send)] -impl SenderKeyStore for ContextUsingSenderKeyStore { - async fn store_sender_key( - &mut self, - sender: &ProtocolAddress, - distribution_id: Uuid, - record: &SenderKeyRecord, - ctx: Context, - ) -> Result<(), SignalProtocolError> { - assert_eq!(ctx, self.expected_context); - self.store - .store_sender_key(sender, distribution_id, record, ctx) - .await - } - - async fn load_sender_key( - &mut self, - sender: &ProtocolAddress, - distribution_id: Uuid, - ctx: Context, - ) -> Result, SignalProtocolError> { - assert_eq!(ctx, self.expected_context); - self.store - .load_sender_key(sender, distribution_id, ctx) - .await - } -} - -#[test] -fn group_using_context_arg() -> Result<(), SignalProtocolError> { - async { - let mut csprng = OsRng; - - let sender_address = ProtocolAddress::new("+14159999111".to_owned(), 1); - let distribution_id = Uuid::from_u128(0xd1d1d1d1_7000_11eb_b32a_33b8a8a487a6); - - let x = Box::new(1); - - let context = Some(Box::into_raw(x) as _); - - let mut alice_store = ContextUsingSenderKeyStore::new(context); - - let _sent_distribution_message = create_sender_key_distribution_message( - &sender_address, - distribution_id, - &mut alice_store, - &mut csprng, - context, - ) - .await?; - - Ok(()) - } - .now_or_never() - .expect("sync") -} - -#[test] -fn group_no_recv_session() -> Result<(), SignalProtocolError> { - async { - let mut csprng = OsRng; - - let sender_address = ProtocolAddress::new("+14159999111".to_owned(), 1); - let distribution_id = Uuid::from_u128(0xd1d1d1d1_7000_11eb_b32a_33b8a8a487a6); - - let mut alice_store = test_in_memory_protocol_store()?; - let mut bob_store = test_in_memory_protocol_store()?; - - let sent_distribution_message = create_sender_key_distribution_message( - &sender_address, - distribution_id, - &mut alice_store, - &mut csprng, - None, - ) - .await?; - - let _recv_distribution_message = - SenderKeyDistributionMessage::try_from(sent_distribution_message.serialized())?; - - let alice_ciphertext = group_encrypt( - &mut alice_store, - &sender_address, - distribution_id, - "space camp?".as_bytes(), - &mut csprng, - None, - ) - .await?; - - let bob_plaintext = group_decrypt( - alice_ciphertext.serialized(), - &mut bob_store, - &sender_address, - None, - ) - .await; - - assert!(bob_plaintext.is_err()); - - Ok(()) - } - .now_or_never() - .expect("sync") -} - -#[test] -fn group_basic_encrypt_decrypt() -> Result<(), SignalProtocolError> { - async { - let mut csprng = OsRng; - - let sender_address = ProtocolAddress::new("+14159999111".to_owned(), 1); - let distribution_id = Uuid::from_u128(0xd1d1d1d1_7000_11eb_b32a_33b8a8a487a6); - - let mut alice_store = test_in_memory_protocol_store()?; - let mut bob_store = test_in_memory_protocol_store()?; - - let sent_distribution_message = create_sender_key_distribution_message( - &sender_address, - distribution_id, - &mut alice_store, - &mut csprng, - None, - ) - .await?; - - let recv_distribution_message = - SenderKeyDistributionMessage::try_from(sent_distribution_message.serialized())?; - - let alice_ciphertext = group_encrypt( - &mut alice_store, - &sender_address, - distribution_id, - "space camp?".as_bytes(), - &mut csprng, - None, - ) - .await?; - - process_sender_key_distribution_message( - &sender_address, - &recv_distribution_message, - &mut bob_store, - None, - ) - .await?; - - let bob_plaintext = group_decrypt( - alice_ciphertext.serialized(), - &mut bob_store, - &sender_address, - None, - ) - .await?; - - assert_eq!( - String::from_utf8(bob_plaintext).expect("valid utf8"), - "space camp?" - ); - - Ok(()) - } - .now_or_never() - .expect("sync") -} - -#[test] -fn group_sealed_sender() -> Result<(), SignalProtocolError> { - async { - let mut csprng = OsRng; - - let alice_device_id = 23; - let bob_device_id = 42; - - let alice_e164 = "+14151111111".to_owned(); - - let alice_uuid = "9d0652a3-dcc3-4d11-975f-74d61598733f".to_string(); - let bob_uuid = "796abedb-ca4e-4f18-8803-1fde5b921f9f".to_string(); - let carol_uuid = "38381c3b-2606-4ca7-9310-7cb927f2ab4a".to_string(); - - let alice_uuid_address = ProtocolAddress::new(alice_uuid.clone(), alice_device_id); - let bob_uuid_address = ProtocolAddress::new(bob_uuid.clone(), bob_device_id); - let carol_uuid_address = ProtocolAddress::new(carol_uuid.clone(), 1); - - let distribution_id = Uuid::from_u128(0xd1d1d1d1_7000_11eb_b32a_33b8a8a487a6); - - let mut alice_store = support::test_in_memory_protocol_store()?; - let mut bob_store = support::test_in_memory_protocol_store()?; - let mut carol_store = support::test_in_memory_protocol_store()?; - - let alice_pubkey = *alice_store.get_identity_key_pair(None).await?.public_key(); - - let bob_pre_key_bundle = create_pre_key_bundle(&mut bob_store, &mut csprng).await?; - let carol_pre_key_bundle = create_pre_key_bundle(&mut carol_store, &mut csprng).await?; - - process_prekey_bundle( - &bob_uuid_address, - &mut alice_store.session_store, - &mut alice_store.identity_store, - &bob_pre_key_bundle, - &mut csprng, - None, - ) - .await?; - - process_prekey_bundle( - &carol_uuid_address, - &mut alice_store.session_store, - &mut alice_store.identity_store, - &carol_pre_key_bundle, - &mut csprng, - None, - ) - .await?; - - let sent_distribution_message = create_sender_key_distribution_message( - &alice_uuid_address, - distribution_id, - &mut alice_store, - &mut csprng, - None, - ) - .await?; - - let recv_distribution_message = - SenderKeyDistributionMessage::try_from(sent_distribution_message.serialized())?; - - process_sender_key_distribution_message( - &alice_uuid_address, - &recv_distribution_message, - &mut bob_store, - None, - ) - .await?; - process_sender_key_distribution_message( - &alice_uuid_address, - &recv_distribution_message, - &mut carol_store, - None, - ) - .await?; - - let trust_root = KeyPair::generate(&mut csprng); - let server_key = KeyPair::generate(&mut csprng); - - let server_cert = ServerCertificate::new( - 1, - server_key.public_key, - &trust_root.private_key, - &mut csprng, - )?; - - let expires = 1605722925; - - let sender_cert = SenderCertificate::new( - alice_uuid.clone(), - Some(alice_e164.clone()), - alice_pubkey, - alice_device_id, - expires, - server_cert, - &server_key.private_key, - &mut csprng, - )?; - - let alice_message = group_encrypt( - &mut alice_store, - &alice_uuid_address, - distribution_id, - "space camp?".as_bytes(), - &mut csprng, - None, - ) - .await?; - - let alice_usmc = UnidentifiedSenderMessageContent::new( - CiphertextMessageType::SenderKey, - sender_cert.clone(), - alice_message.serialized().to_vec(), - ContentHint::Implicit, - Some([42].to_vec()), - )?; - - let recipients = [&bob_uuid_address, &carol_uuid_address]; - let alice_ctext = sealed_sender_multi_recipient_encrypt( - &recipients, - &alice_store - .session_store - .load_existing_sessions(&recipients)?, - &alice_usmc, - &mut alice_store.identity_store, - None, - &mut csprng, - ) - .await?; - - let [bob_ctext, carol_ctext] = - <[_; 2]>::try_from(sealed_sender_multi_recipient_fan_out(&alice_ctext)?).unwrap(); - - let bob_usmc = - sealed_sender_decrypt_to_usmc(&bob_ctext, &mut bob_store.identity_store, None).await?; - - assert_eq!(bob_usmc.sender()?.sender_uuid()?, alice_uuid); - assert_eq!(bob_usmc.sender()?.sender_e164()?, Some(alice_e164.as_ref())); - assert_eq!(bob_usmc.sender()?.sender_device_id()?, alice_device_id); - assert_eq!(bob_usmc.content_hint()?, ContentHint::Implicit); - assert_eq!(bob_usmc.group_id()?, Some(&[42][..])); - - let bob_plaintext = group_decrypt( - bob_usmc.contents()?, - &mut bob_store, - &alice_uuid_address, - None, - ) - .await?; - - assert_eq!( - String::from_utf8(bob_plaintext).expect("valid utf8"), - "space camp?" - ); - - let carol_usmc = - sealed_sender_decrypt_to_usmc(&carol_ctext, &mut carol_store.identity_store, None) - .await?; - - assert_eq!(carol_usmc.serialized()?, bob_usmc.serialized()?); - - let carol_plaintext = group_decrypt( - carol_usmc.contents()?, - &mut carol_store, - &alice_uuid_address, - None, - ) - .await?; - - assert_eq!( - String::from_utf8(carol_plaintext).expect("valid utf8"), - "space camp?" - ); - - Ok(()) - } - .now_or_never() - .expect("sync") -} - -#[test] -fn group_large_messages() -> Result<(), SignalProtocolError> { - async { - let mut csprng = OsRng; - - let sender_address = ProtocolAddress::new("+14159999111".to_owned(), 1); - let distribution_id = Uuid::from_u128(0xd1d1d1d1_7000_11eb_b32a_33b8a8a487a6); - - let mut alice_store = test_in_memory_protocol_store()?; - let mut bob_store = test_in_memory_protocol_store()?; - - let sent_distribution_message = create_sender_key_distribution_message( - &sender_address, - distribution_id, - &mut alice_store, - &mut csprng, - None, - ) - .await?; - - let recv_distribution_message = - SenderKeyDistributionMessage::try_from(sent_distribution_message.serialized())?; - - let mut large_message: Vec = Vec::with_capacity(1024); - for _ in 0..large_message.capacity() { - large_message.push(csprng.gen()); - } - - let alice_ciphertext = group_encrypt( - &mut alice_store, - &sender_address, - distribution_id, - &large_message, - &mut csprng, - None, - ) - .await?; - - process_sender_key_distribution_message( - &sender_address, - &recv_distribution_message, - &mut bob_store, - None, - ) - .await?; - - let bob_plaintext = group_decrypt( - alice_ciphertext.serialized(), - &mut bob_store, - &sender_address, - None, - ) - .await?; - - assert_eq!(bob_plaintext, large_message); - - Ok(()) - } - .now_or_never() - .expect("sync") -} - -#[test] -fn group_basic_ratchet() -> Result<(), SignalProtocolError> { - async { - let mut csprng = OsRng; - - let sender_address = ProtocolAddress::new("+14159999111".to_owned(), 1); - let distribution_id = Uuid::from_u128(0xd1d1d1d1_7000_11eb_b32a_33b8a8a487a6); - - let mut alice_store = test_in_memory_protocol_store()?; - let mut bob_store = test_in_memory_protocol_store()?; - - let sent_distribution_message = create_sender_key_distribution_message( - &sender_address, - distribution_id, - &mut alice_store, - &mut csprng, - None, - ) - .await?; - - let recv_distribution_message = - SenderKeyDistributionMessage::try_from(sent_distribution_message.serialized())?; - - process_sender_key_distribution_message( - &sender_address, - &recv_distribution_message, - &mut bob_store, - None, - ) - .await?; - - let alice_ciphertext1 = group_encrypt( - &mut alice_store, - &sender_address, - distribution_id, - "swim camp".as_bytes(), - &mut csprng, - None, - ) - .await?; - let alice_ciphertext2 = group_encrypt( - &mut alice_store, - &sender_address, - distribution_id, - "robot camp".as_bytes(), - &mut csprng, - None, - ) - .await?; - let alice_ciphertext3 = group_encrypt( - &mut alice_store, - &sender_address, - distribution_id, - "ninja camp".as_bytes(), - &mut csprng, - None, - ) - .await?; - - let bob_plaintext1 = group_decrypt( - alice_ciphertext1.serialized(), - &mut bob_store, - &sender_address, - None, - ) - .await?; - assert_eq!( - String::from_utf8(bob_plaintext1).expect("valid utf8"), - "swim camp" - ); - - assert!(matches!( - group_decrypt( - alice_ciphertext1.serialized(), - &mut bob_store, - &sender_address, - None - ) - .await, - Err(SignalProtocolError::DuplicatedMessage(1, 0)) - )); - - let bob_plaintext3 = group_decrypt( - alice_ciphertext3.serialized(), - &mut bob_store, - &sender_address, - None, - ) - .await?; - assert_eq!( - String::from_utf8(bob_plaintext3).expect("valid utf8"), - "ninja camp" - ); - - let bob_plaintext2 = group_decrypt( - alice_ciphertext2.serialized(), - &mut bob_store, - &sender_address, - None, - ) - .await?; - assert_eq!( - String::from_utf8(bob_plaintext2).expect("valid utf8"), - "robot camp" - ); - - Ok(()) - } - .now_or_never() - .expect("sync") -} - -#[test] -fn group_late_join() -> Result<(), SignalProtocolError> { - async { - let mut csprng = OsRng; - - let sender_address = ProtocolAddress::new("+14159999111".to_owned(), 1); - let distribution_id = Uuid::from_u128(0xd1d1d1d1_7000_11eb_b32a_33b8a8a487a6); - - let mut alice_store = test_in_memory_protocol_store()?; - let mut bob_store = test_in_memory_protocol_store()?; - - let sent_distribution_message = create_sender_key_distribution_message( - &sender_address, - distribution_id, - &mut alice_store, - &mut csprng, - None, - ) - .await?; - - let recv_distribution_message = - SenderKeyDistributionMessage::try_from(sent_distribution_message.serialized())?; - - for i in 0..100 { - group_encrypt( - &mut alice_store, - &sender_address, - distribution_id, - format!("nefarious plotting {}/100", i).as_bytes(), - &mut csprng, - None, - ) - .await?; - } - - // now bob joins: - process_sender_key_distribution_message( - &sender_address, - &recv_distribution_message, - &mut bob_store, - None, - ) - .await?; - - let alice_ciphertext = group_encrypt( - &mut alice_store, - &sender_address, - distribution_id, - "welcome bob".as_bytes(), - &mut csprng, - None, - ) - .await?; - - let bob_plaintext = group_decrypt( - alice_ciphertext.serialized(), - &mut bob_store, - &sender_address, - None, - ) - .await?; - assert_eq!( - String::from_utf8(bob_plaintext).expect("valid utf8"), - "welcome bob" - ); - - Ok(()) - } - .now_or_never() - .expect("sync") -} - -#[test] -fn group_out_of_order() -> Result<(), SignalProtocolError> { - async { - let mut csprng = OsRng; - - let sender_address = ProtocolAddress::new("+14159999111".to_owned(), 1); - let distribution_id = Uuid::from_u128(0xd1d1d1d1_7000_11eb_b32a_33b8a8a487a6); - - let mut alice_store = test_in_memory_protocol_store()?; - let mut bob_store = test_in_memory_protocol_store()?; - - let sent_distribution_message = create_sender_key_distribution_message( - &sender_address, - distribution_id, - &mut alice_store, - &mut csprng, - None, - ) - .await?; - - let recv_distribution_message = - SenderKeyDistributionMessage::try_from(sent_distribution_message.serialized())?; - - process_sender_key_distribution_message( - &sender_address, - &recv_distribution_message, - &mut bob_store, - None, - ) - .await?; - - let mut ciphertexts = Vec::with_capacity(100); - - for i in 0..ciphertexts.capacity() { - ciphertexts.push( - group_encrypt( - &mut alice_store, - &sender_address, - distribution_id, - format!("nefarious plotting {:02}/100", i).as_bytes(), - &mut csprng, - None, - ) - .await?, - ); - } - - ciphertexts.shuffle(&mut csprng); - - let mut plaintexts = Vec::with_capacity(ciphertexts.len()); - - for ciphertext in ciphertexts { - plaintexts.push( - group_decrypt( - ciphertext.serialized(), - &mut bob_store, - &sender_address, - None, - ) - .await?, - ); - } - - plaintexts.sort(); - - for (i, plaintext) in plaintexts.iter().enumerate() { - assert_eq!( - String::from_utf8(plaintext.to_vec()).expect("valid utf8"), - format!("nefarious plotting {:02}/100", i) - ); - } - - Ok(()) - } - .now_or_never() - .expect("sync") -} - -#[test] -#[ignore = "slow to run locally"] -fn group_too_far_in_the_future() -> Result<(), SignalProtocolError> { - async { - let mut csprng = OsRng; - - let sender_address = ProtocolAddress::new("+14159999111".to_owned(), 1); - let distribution_id = Uuid::from_u128(0xd1d1d1d1_7000_11eb_b32a_33b8a8a487a6); - - let mut alice_store = test_in_memory_protocol_store()?; - let mut bob_store = test_in_memory_protocol_store()?; - - let sent_distribution_message = create_sender_key_distribution_message( - &sender_address, - distribution_id, - &mut alice_store, - &mut csprng, - None, - ) - .await?; - - let recv_distribution_message = - SenderKeyDistributionMessage::try_from(sent_distribution_message.serialized())?; - - process_sender_key_distribution_message( - &sender_address, - &recv_distribution_message, - &mut bob_store, - None, - ) - .await?; - - for i in 0..25001 { - group_encrypt( - &mut alice_store, - &sender_address, - distribution_id, - format!("nefarious plotting {}", i).as_bytes(), - &mut csprng, - None, - ) - .await?; - } - - let alice_ciphertext = group_encrypt( - &mut alice_store, - &sender_address, - distribution_id, - "you got the plan?".as_bytes(), - &mut csprng, - None, - ) - .await?; - - assert!(group_decrypt( - alice_ciphertext.serialized(), - &mut bob_store, - &sender_address, - None - ) - .await - .is_err()); - - Ok(()) - } - .now_or_never() - .expect("sync") -} - -#[test] -fn group_message_key_limit() -> Result<(), SignalProtocolError> { - async { - let mut csprng = OsRng; - - let sender_address = ProtocolAddress::new("+14159999111".to_owned(), 1); - let distribution_id = Uuid::from_u128(0xd1d1d1d1_7000_11eb_b32a_33b8a8a487a6); - - let mut alice_store = test_in_memory_protocol_store()?; - let mut bob_store = test_in_memory_protocol_store()?; - - let sent_distribution_message = create_sender_key_distribution_message( - &sender_address, - distribution_id, - &mut alice_store, - &mut csprng, - None, - ) - .await?; - - let recv_distribution_message = - SenderKeyDistributionMessage::try_from(sent_distribution_message.serialized())?; - - process_sender_key_distribution_message( - &sender_address, - &recv_distribution_message, - &mut bob_store, - None, - ) - .await?; - - let mut ciphertexts = Vec::with_capacity(2010); - - for _ in 0..ciphertexts.capacity() { - ciphertexts.push( - group_encrypt( - &mut alice_store, - &sender_address, - distribution_id, - "too many messages".as_bytes(), - &mut csprng, - None, - ) - .await? - .serialized() - .to_vec(), - ); - } - - assert_eq!( - String::from_utf8( - group_decrypt(&ciphertexts[1000], &mut bob_store, &sender_address, None,).await? - ) - .expect("valid utf8"), - "too many messages" - ); - assert_eq!( - String::from_utf8( - group_decrypt( - &ciphertexts[ciphertexts.len() - 1], - &mut bob_store, - &sender_address, - None, - ) - .await? - ) - .expect("valid utf8"), - "too many messages" - ); - assert!( - group_decrypt(&ciphertexts[0], &mut bob_store, &sender_address, None) - .await - .is_err() - ); - - Ok(()) - } - .now_or_never() - .expect("sync") -} diff --git a/net/gurk-rs/files/vendor/libsignal-protocol/tests/ratchet.rs b/net/gurk-rs/files/vendor/libsignal-protocol/tests/ratchet.rs deleted file mode 100644 index 33895c9..0000000 --- a/net/gurk-rs/files/vendor/libsignal-protocol/tests/ratchet.rs +++ /dev/null @@ -1,173 +0,0 @@ -// -// Copyright 2020 Signal Messenger, LLC. -// SPDX-License-Identifier: AGPL-3.0-only -// - -use libsignal_protocol::*; - -#[test] -fn test_ratcheting_session_as_bob() -> Result<(), SignalProtocolError> { - let bob_ephemeral_public = - hex::decode("052cb49776b8770205745a3a6e24f579cdb4ba7a89041005928ebbadc9c05ad458") - .expect("valid hex"); - - let bob_ephemeral_private = - hex::decode("a1cab48f7c893fafa9880a28c3b4999d28d6329562d27a4ea4e22e9ff1bdd65a") - .expect("valid hex"); - - let bob_identity_public = - hex::decode("05f1f43874f6966956c2dd473f8fa15adeb71d1cb991b2341692324cefb1c5e626") - .expect("valid hex"); - - let bob_identity_private = - hex::decode("4875cc69ddf8ea0719ec947d61081135868d5fd801f02c0225e516df2156605e") - .expect("valid hex"); - - let alice_base_public = - hex::decode("05472d1fb1a9862c3af6beaca8920277e2b26f4a79213ec7c906aeb35e03cf8950") - .expect("valid hex"); - - let alice_identity_public = - hex::decode("05b4a8455660ada65b401007f615e654041746432e3339c6875149bceefcb42b4a") - .expect("valid hex"); - - let bob_signed_prekey_public = - hex::decode("05ac248a8f263be6863576eb0362e28c828f0107a3379d34bab1586bf8c770cd67") - .expect("valid hex"); - - let bob_signed_prekey_private = - hex::decode("583900131fb727998b7803fe6ac22cc591f342e4e42a8c8d5d78194209b8d253") - .expect("valid hex"); - - let expected_sender_chain = "9797caca53c989bbe229a40ca7727010eb2604fc14945d77958a0aeda088b44d"; - - let bob_identity_key_public = IdentityKey::decode(&bob_identity_public)?; - - let bob_identity_key_private = PrivateKey::deserialize(&bob_identity_private)?; - - let bob_identity_key_pair = - IdentityKeyPair::new(bob_identity_key_public, bob_identity_key_private); - - let bob_ephemeral_pair = - KeyPair::from_public_and_private(&bob_ephemeral_public, &bob_ephemeral_private)?; - - let bob_signed_prekey_pair = - KeyPair::from_public_and_private(&bob_signed_prekey_public, &bob_signed_prekey_private)?; - - let alice_base_public_key = PublicKey::deserialize(&alice_base_public)?; - - let bob_parameters = BobSignalProtocolParameters::new( - bob_identity_key_pair, - bob_signed_prekey_pair, - None, // one time pre key pair - bob_ephemeral_pair, - IdentityKey::decode(&alice_identity_public)?, - alice_base_public_key, - ); - - let bob_record = initialize_bob_session_record(&bob_parameters)?; - - assert_eq!( - hex::encode(bob_record.local_identity_key_bytes()?), - hex::encode(bob_identity_public) - ); - assert_eq!( - hex::encode( - bob_record - .remote_identity_key_bytes()? - .expect("value exists") - ), - hex::encode(alice_identity_public) - ); - assert_eq!( - hex::encode(bob_record.get_sender_chain_key_bytes()?), - expected_sender_chain - ); - - Ok(()) -} - -#[test] -fn test_ratcheting_session_as_alice() -> Result<(), SignalProtocolError> { - let bob_ephemeral_public = - hex::decode("052cb49776b8770205745a3a6e24f579cdb4ba7a89041005928ebbadc9c05ad458") - .expect("valid hex"); - - let bob_identity_public = - hex::decode("05f1f43874f6966956c2dd473f8fa15adeb71d1cb991b2341692324cefb1c5e626") - .expect("valid hex"); - - let alice_base_public = - hex::decode("05472d1fb1a9862c3af6beaca8920277e2b26f4a79213ec7c906aeb35e03cf8950") - .expect("valid hex"); - - let alice_base_private = - hex::decode("11ae7c64d1e61cd596b76a0db5012673391cae66edbfcf073b4da80516a47449") - .expect("valid hex"); - - let bob_signed_prekey_public = - hex::decode("05ac248a8f263be6863576eb0362e28c828f0107a3379d34bab1586bf8c770cd67") - .expect("valid hex"); - - let alice_identity_public = - hex::decode("05b4a8455660ada65b401007f615e654041746432e3339c6875149bceefcb42b4a") - .expect("valid hex"); - - let alice_identity_private = - hex::decode("9040f0d4e09cf38f6dc7c13779c908c015a1da4fa78737a080eb0a6f4f5f8f58") - .expect("valid hex"); - - // This differs from the Java test and needs investigation - let expected_receiver_chain = - "ab9be50e5cb22a925446ab90ee5670545f4fd32902459ec274b6ad0ae5d6031a"; - - let alice_identity_key_public = IdentityKey::decode(&alice_identity_public)?; - - let bob_ephemeral_public = PublicKey::deserialize(&bob_ephemeral_public)?; - - let alice_identity_key_private = PrivateKey::deserialize(&alice_identity_private)?; - - let bob_signed_prekey_public = PublicKey::deserialize(&bob_signed_prekey_public)?; - - let alice_identity_key_pair = - IdentityKeyPair::new(alice_identity_key_public, alice_identity_key_private); - - let alice_base_key = KeyPair::from_public_and_private(&alice_base_public, &alice_base_private)?; - - let alice_parameters = AliceSignalProtocolParameters::new( - alice_identity_key_pair, - alice_base_key, - IdentityKey::decode(&bob_identity_public)?, - bob_signed_prekey_public, - None, // one-time prekey - bob_ephemeral_public, - ); - - let mut csprng = rand::rngs::OsRng; - let alice_record = initialize_alice_session_record(&alice_parameters, &mut csprng)?; - - assert_eq!( - hex::encode(alice_record.local_identity_key_bytes()?), - hex::encode(alice_identity_public), - ); - assert_eq!( - hex::encode( - alice_record - .remote_identity_key_bytes()? - .expect("value exists") - ), - hex::encode(bob_identity_public) - ); - - assert_eq!( - hex::encode( - alice_record - .get_receiver_chain_key(&bob_ephemeral_public)? - .expect("value exists") - .key() - ), - expected_receiver_chain - ); - - Ok(()) -} diff --git a/net/gurk-rs/files/vendor/libsignal-protocol/tests/sealed_sender.rs b/net/gurk-rs/files/vendor/libsignal-protocol/tests/sealed_sender.rs deleted file mode 100644 index d836406..0000000 --- a/net/gurk-rs/files/vendor/libsignal-protocol/tests/sealed_sender.rs +++ /dev/null @@ -1,1005 +0,0 @@ -// -// Copyright 2020-2021 Signal Messenger, LLC. -// SPDX-License-Identifier: AGPL-3.0-only -// - -mod support; -use support::*; - -use futures_util::FutureExt; -use libsignal_protocol::*; -use rand::rngs::OsRng; -use std::convert::TryFrom; -use uuid::Uuid; - -#[test] -fn test_server_cert() -> Result<(), SignalProtocolError> { - let mut rng = OsRng; - let trust_root = KeyPair::generate(&mut rng); - let server_key = KeyPair::generate(&mut rng); - - let server_cert = - ServerCertificate::new(1, server_key.public_key, &trust_root.private_key, &mut rng)?; - - let serialized = server_cert.serialized()?.to_vec(); - - let recovered = ServerCertificate::deserialize(&serialized)?; - - assert!(recovered.validate(&trust_root.public_key)?); - - let mut cert_data = serialized; - let cert_bits = cert_data.len() * 8; - - for b in 0..cert_bits { - cert_data[b / 8] ^= 1u8 << (b % 8); // flip a bit - let cert = ServerCertificate::deserialize(&cert_data); - cert_data[b / 8] ^= 1u8 << (b % 8); // flip the bit back - - match cert { - Ok(cert) => { - assert!(!cert.validate(&trust_root.public_key)?); - } - Err(e) => match e { - SignalProtocolError::InvalidProtobufEncoding - | SignalProtocolError::ProtobufDecodingError(_) - | SignalProtocolError::BadKeyType(_) - | SignalProtocolError::BadKeyLength(_, _) => {} - - unexpected_err => { - panic!("unexpected error {:?}", unexpected_err) - } - }, - } - } - - Ok(()) -} - -#[test] -fn test_revoked_server_cert() -> Result<(), SignalProtocolError> { - let mut rng = OsRng; - let trust_root = KeyPair::generate(&mut rng); - let server_key = KeyPair::generate(&mut rng); - - let revoked_id = 0xDEADC357; - - let server_cert = ServerCertificate::new( - revoked_id, - server_key.public_key, - &trust_root.private_key, - &mut rng, - )?; - - let serialized = server_cert.serialized()?.to_vec(); - - let recovered = ServerCertificate::deserialize(&serialized)?; - - assert!(!recovered.validate(&trust_root.public_key)?); - - Ok(()) -} - -#[test] -fn test_sender_cert() -> Result<(), SignalProtocolError> { - let mut rng = OsRng; - let trust_root = KeyPair::generate(&mut rng); - let server_key = KeyPair::generate(&mut rng); - let key = KeyPair::generate(&mut rng); - - let server_cert = - ServerCertificate::new(1, server_key.public_key, &trust_root.private_key, &mut rng)?; - - let device_id = 42; - let expires = 1605722925; - - let sender_cert = SenderCertificate::new( - "9d0652a3-dcc3-4d11-975f-74d61598733f".to_string(), - Some("+14152222222".to_string()), - key.public_key, - device_id, - expires, - server_cert, - &server_key.private_key, - &mut rng, - )?; - - assert!(sender_cert.validate(&trust_root.public_key, expires)?); - assert!(!sender_cert.validate(&trust_root.public_key, expires + 1)?); // expired - - let mut sender_cert_data = sender_cert.serialized()?.to_vec(); - let sender_cert_bits = sender_cert_data.len() * 8; - - for b in 0..sender_cert_bits { - sender_cert_data[b / 8] ^= 1u8 << (b % 8); // flip a bit - let cert = SenderCertificate::deserialize(&sender_cert_data); - sender_cert_data[b / 8] ^= 1u8 << (b % 8); // flip the bit back - - match cert { - Ok(cert) => { - assert!(!cert.validate(&trust_root.public_key, expires)?); - } - Err(e) => match e { - SignalProtocolError::InvalidProtobufEncoding - | SignalProtocolError::ProtobufDecodingError(_) - | SignalProtocolError::BadKeyLength(_, _) - | SignalProtocolError::BadKeyType(_) => {} - - unexpected_err => { - panic!("unexpected error {:?}", unexpected_err) - } - }, - } - } - - Ok(()) -} - -#[test] -fn test_sealed_sender() -> Result<(), SignalProtocolError> { - async { - let mut rng = OsRng; - - let alice_device_id = 23; - let bob_device_id = 42; - - let alice_e164 = "+14151111111".to_owned(); - let bob_e164 = "+14151114444".to_owned(); - - let alice_uuid = "9d0652a3-dcc3-4d11-975f-74d61598733f".to_string(); - let bob_uuid = "796abedb-ca4e-4f18-8803-1fde5b921f9f".to_string(); - - let bob_uuid_address = ProtocolAddress::new(bob_uuid.clone(), bob_device_id); - - let mut alice_store = support::test_in_memory_protocol_store()?; - let mut bob_store = support::test_in_memory_protocol_store()?; - - let alice_pubkey = *alice_store.get_identity_key_pair(None).await?.public_key(); - - let bob_pre_key_bundle = create_pre_key_bundle(&mut bob_store, &mut rng).await?; - - process_prekey_bundle( - &bob_uuid_address, - &mut alice_store.session_store, - &mut alice_store.identity_store, - &bob_pre_key_bundle, - &mut rng, - None, - ) - .await?; - - let trust_root = KeyPair::generate(&mut rng); - let server_key = KeyPair::generate(&mut rng); - - let server_cert = - ServerCertificate::new(1, server_key.public_key, &trust_root.private_key, &mut rng)?; - - let expires = 1605722925; - - let sender_cert = SenderCertificate::new( - alice_uuid.clone(), - Some(alice_e164.clone()), - alice_pubkey, - alice_device_id, - expires, - server_cert, - &server_key.private_key, - &mut rng, - )?; - - let alice_ptext = vec![1, 2, 3, 23, 99]; - let alice_ctext = sealed_sender_encrypt( - &bob_uuid_address, - &sender_cert, - &alice_ptext, - &mut alice_store.session_store, - &mut alice_store.identity_store, - None, - &mut rng, - ) - .await?; - - let bob_ptext = sealed_sender_decrypt( - &alice_ctext, - &trust_root.public_key, - expires - 1, - Some(bob_e164.clone()), - bob_uuid.clone(), - bob_device_id, - &mut bob_store.identity_store, - &mut bob_store.session_store, - &mut bob_store.pre_key_store, - &mut bob_store.signed_pre_key_store, - None, - ) - .await?; - - assert_eq!(bob_ptext.message, alice_ptext); - assert_eq!(bob_ptext.sender_uuid, alice_uuid); - assert_eq!(bob_ptext.sender_e164, Some(alice_e164)); - assert_eq!(bob_ptext.device_id, alice_device_id); - - // Now test but with an expired cert: - - let alice_ctext = sealed_sender_encrypt( - &bob_uuid_address, - &sender_cert, - &alice_ptext, - &mut alice_store.session_store, - &mut alice_store.identity_store, - None, - &mut rng, - ) - .await?; - - let bob_ptext = sealed_sender_decrypt( - &alice_ctext, - &trust_root.public_key, - expires + 11, - Some(bob_e164.clone()), - bob_uuid.clone(), - bob_device_id, - &mut bob_store.identity_store, - &mut bob_store.session_store, - &mut bob_store.pre_key_store, - &mut bob_store.signed_pre_key_store, - None, - ) - .await; - - match bob_ptext { - Err(SignalProtocolError::InvalidSealedSenderMessage(_)) => { /* ok */ } - Err(err) => { - panic!("Unexpected error {}", err) - } - Ok(_) => { - panic!("Shouldn't have decrypted") - } - } - - // Now test but try to verify using some other trust root - - let alice_ctext = sealed_sender_encrypt( - &bob_uuid_address, - &sender_cert, - &alice_ptext, - &mut alice_store.session_store, - &mut alice_store.identity_store, - None, - &mut rng, - ) - .await?; - - let wrong_trust_root = KeyPair::generate(&mut rng); - - let bob_ptext = sealed_sender_decrypt( - &alice_ctext, - &wrong_trust_root.public_key, - expires - 1, - Some(bob_e164.clone()), - bob_uuid.clone(), - bob_device_id, - &mut bob_store.identity_store, - &mut bob_store.session_store, - &mut bob_store.pre_key_store, - &mut bob_store.signed_pre_key_store, - None, - ) - .await; - - match bob_ptext { - Err(SignalProtocolError::InvalidSealedSenderMessage(_)) => { /* ok */ } - Err(err) => { - panic!("Unexpected error {}", err) - } - Ok(_) => { - panic!("Shouldn't have decrypted") - } - } - - Ok(()) - } - .now_or_never() - .expect("sync") -} - -#[test] -fn test_sender_key_in_sealed_sender() -> Result<(), SignalProtocolError> { - async { - let mut rng = OsRng; - - let alice_device_id = 23; - let bob_device_id = 42; - - let alice_e164 = "+14151111111".to_owned(); - - let alice_uuid = "9d0652a3-dcc3-4d11-975f-74d61598733f".to_string(); - let bob_uuid = "796abedb-ca4e-4f18-8803-1fde5b921f9f".to_string(); - - let distribution_id = Uuid::from_u128(0xd1d1d1d1_7000_11eb_b32a_33b8a8a487a6); - - let alice_uuid_address = ProtocolAddress::new(alice_uuid.clone(), 1); - let bob_uuid_address = ProtocolAddress::new(bob_uuid.clone(), bob_device_id); - - let mut alice_store = support::test_in_memory_protocol_store()?; - let mut bob_store = support::test_in_memory_protocol_store()?; - - let alice_pubkey = *alice_store.get_identity_key_pair(None).await?.public_key(); - - let bob_pre_key_bundle = create_pre_key_bundle(&mut bob_store, &mut rng).await?; - - process_prekey_bundle( - &bob_uuid_address, - &mut alice_store.session_store, - &mut alice_store.identity_store, - &bob_pre_key_bundle, - &mut rng, - None, - ) - .await?; - - let trust_root = KeyPair::generate(&mut rng); - let server_key = KeyPair::generate(&mut rng); - - let server_cert = - ServerCertificate::new(1, server_key.public_key, &trust_root.private_key, &mut rng)?; - - let expires = 1605722925; - - let sender_cert = SenderCertificate::new( - alice_uuid.clone(), - Some(alice_e164.clone()), - alice_pubkey, - alice_device_id, - expires, - server_cert, - &server_key.private_key, - &mut rng, - )?; - - let distribution_message = create_sender_key_distribution_message( - &alice_uuid_address, - distribution_id, - &mut alice_store, - &mut rng, - None, - ) - .await?; - - process_sender_key_distribution_message( - &alice_uuid_address, - &distribution_message, - &mut bob_store, - None, - ) - .await?; - - let alice_message = group_encrypt( - &mut alice_store, - &alice_uuid_address, - distribution_id, - "swim camp".as_bytes(), - &mut rng, - None, - ) - .await?; - let alice_usmc = UnidentifiedSenderMessageContent::new( - CiphertextMessageType::SenderKey, - sender_cert.clone(), - alice_message.serialized().to_vec(), - ContentHint::Default, - None, - )?; - - let alice_ctext = sealed_sender_encrypt_from_usmc( - &bob_uuid_address, - &alice_usmc, - &mut alice_store.identity_store, - None, - &mut rng, - ) - .await?; - - let bob_usmc = - sealed_sender_decrypt_to_usmc(&alice_ctext, &mut bob_store.identity_store, None) - .await?; - - assert!(matches!( - bob_usmc.msg_type()?, - CiphertextMessageType::SenderKey, - )); - - let bob_plaintext = group_decrypt( - bob_usmc.contents()?, - &mut bob_store, - &alice_uuid_address, - None, - ) - .await?; - - assert_eq!( - String::from_utf8(bob_plaintext).expect("valid UTF-8"), - "swim camp" - ); - - Ok(()) - } - .now_or_never() - .expect("sync") -} - -#[test] -fn test_sealed_sender_multi_recipient() -> Result<(), SignalProtocolError> { - async { - let mut rng = OsRng; - - let alice_device_id = 23; - let bob_device_id = 42; - - let alice_e164 = "+14151111111".to_owned(); - let bob_e164 = "+14151114444".to_owned(); - - let alice_uuid = "9d0652a3-dcc3-4d11-975f-74d61598733f".to_string(); - let bob_uuid = "796abedb-ca4e-4f18-8803-1fde5b921f9f".to_string(); - - let bob_uuid_address = ProtocolAddress::new(bob_uuid.clone(), bob_device_id); - - let mut alice_store = support::test_in_memory_protocol_store()?; - let mut bob_store = support::test_in_memory_protocol_store()?; - - let alice_pubkey = *alice_store.get_identity_key_pair(None).await?.public_key(); - - let bob_pre_key_bundle = create_pre_key_bundle(&mut bob_store, &mut rng).await?; - - process_prekey_bundle( - &bob_uuid_address, - &mut alice_store.session_store, - &mut alice_store.identity_store, - &bob_pre_key_bundle, - &mut rng, - None, - ) - .await?; - - let trust_root = KeyPair::generate(&mut rng); - let server_key = KeyPair::generate(&mut rng); - - let server_cert = - ServerCertificate::new(1, server_key.public_key, &trust_root.private_key, &mut rng)?; - - let expires = 1605722925; - - let sender_cert = SenderCertificate::new( - alice_uuid.clone(), - Some(alice_e164.clone()), - alice_pubkey, - alice_device_id, - expires, - server_cert, - &server_key.private_key, - &mut rng, - )?; - - let alice_ptext = vec![1, 2, 3, 23, 99]; - let alice_message = message_encrypt( - &alice_ptext, - &bob_uuid_address, - &mut alice_store.session_store, - &mut alice_store.identity_store, - None, - ) - .await?; - - let alice_usmc = UnidentifiedSenderMessageContent::new( - alice_message.message_type(), - sender_cert.clone(), - alice_message.serialize().to_vec(), - ContentHint::Default, - None, - )?; - - let recipients = [&bob_uuid_address]; - let alice_ctext = sealed_sender_multi_recipient_encrypt( - &recipients, - &alice_store - .session_store - .load_existing_sessions(&recipients)?, - &alice_usmc, - &mut alice_store.identity_store, - None, - &mut rng, - ) - .await?; - - let [bob_ctext] = <[_; 1]>::try_from(sealed_sender_multi_recipient_fan_out(&alice_ctext)?) - .expect("only one recipient"); - - let bob_ptext = sealed_sender_decrypt( - &bob_ctext, - &trust_root.public_key, - expires - 1, - Some(bob_e164.clone()), - bob_uuid.clone(), - bob_device_id, - &mut bob_store.identity_store, - &mut bob_store.session_store, - &mut bob_store.pre_key_store, - &mut bob_store.signed_pre_key_store, - None, - ) - .await?; - - assert_eq!(bob_ptext.message, alice_ptext); - assert_eq!(bob_ptext.sender_uuid, alice_uuid); - assert_eq!(bob_ptext.sender_e164, Some(alice_e164)); - assert_eq!(bob_ptext.device_id, alice_device_id); - - // Now test but with an expired cert: - let alice_message = message_encrypt( - &alice_ptext, - &bob_uuid_address, - &mut alice_store.session_store, - &mut alice_store.identity_store, - None, - ) - .await?; - - let alice_usmc = UnidentifiedSenderMessageContent::new( - alice_message.message_type(), - sender_cert.clone(), - alice_message.serialize().to_vec(), - ContentHint::Default, - None, - )?; - - let recipients = [&bob_uuid_address]; - let alice_ctext = sealed_sender_multi_recipient_encrypt( - &recipients, - &alice_store - .session_store - .load_existing_sessions(&recipients)?, - &alice_usmc, - &mut alice_store.identity_store, - None, - &mut rng, - ) - .await?; - - let [bob_ctext] = <[_; 1]>::try_from(sealed_sender_multi_recipient_fan_out(&alice_ctext)?) - .expect("only one recipient"); - - let bob_ptext = sealed_sender_decrypt( - &bob_ctext, - &trust_root.public_key, - expires + 11, - Some(bob_e164.clone()), - bob_uuid.clone(), - bob_device_id, - &mut bob_store.identity_store, - &mut bob_store.session_store, - &mut bob_store.pre_key_store, - &mut bob_store.signed_pre_key_store, - None, - ) - .await; - - match bob_ptext { - Err(SignalProtocolError::InvalidSealedSenderMessage(_)) => { /* ok */ } - Err(err) => { - panic!("Unexpected error {}", err) - } - Ok(_) => { - panic!("Shouldn't have decrypted") - } - } - - // Now test but try to verify using some other trust root - - let alice_message = message_encrypt( - &alice_ptext, - &bob_uuid_address, - &mut alice_store.session_store, - &mut alice_store.identity_store, - None, - ) - .await?; - - let alice_usmc = UnidentifiedSenderMessageContent::new( - alice_message.message_type(), - sender_cert.clone(), - alice_message.serialize().to_vec(), - ContentHint::Default, - None, - )?; - - let recipients = [&bob_uuid_address]; - let alice_ctext = sealed_sender_multi_recipient_encrypt( - &recipients, - &alice_store - .session_store - .load_existing_sessions(&recipients)?, - &alice_usmc, - &mut alice_store.identity_store, - None, - &mut rng, - ) - .await?; - - let wrong_trust_root = KeyPair::generate(&mut rng); - - let [bob_ctext] = <[_; 1]>::try_from(sealed_sender_multi_recipient_fan_out(&alice_ctext)?) - .expect("only one recipient"); - - let bob_ptext = sealed_sender_decrypt( - &bob_ctext, - &wrong_trust_root.public_key, - expires - 1, - Some(bob_e164.clone()), - bob_uuid.clone(), - bob_device_id, - &mut bob_store.identity_store, - &mut bob_store.session_store, - &mut bob_store.pre_key_store, - &mut bob_store.signed_pre_key_store, - None, - ) - .await; - - match bob_ptext { - Err(SignalProtocolError::InvalidSealedSenderMessage(_)) => { /* ok */ } - Err(err) => { - panic!("Unexpected error {}", err) - } - Ok(_) => { - panic!("Shouldn't have decrypted") - } - } - - Ok(()) - } - .now_or_never() - .expect("sync") -} - -#[test] -fn test_sealed_sender_multi_recipient_encrypt_with_archived_session( -) -> Result<(), SignalProtocolError> { - async { - let mut rng = OsRng; - - let alice_device_id = 23; - let bob_device_id = 42; - - let alice_e164 = "+14151111111".to_owned(); - - let alice_uuid = "9d0652a3-dcc3-4d11-975f-74d61598733f".to_string(); - let bob_uuid = "796abedb-ca4e-4f18-8803-1fde5b921f9f".to_string(); - - let bob_uuid_address = ProtocolAddress::new(bob_uuid.clone(), bob_device_id); - - let mut alice_store = support::test_in_memory_protocol_store()?; - let mut bob_store = support::test_in_memory_protocol_store()?; - - let alice_pubkey = *alice_store.get_identity_key_pair(None).await?.public_key(); - - let bob_pre_key_bundle = create_pre_key_bundle(&mut bob_store, &mut rng).await?; - - process_prekey_bundle( - &bob_uuid_address, - &mut alice_store.session_store, - &mut alice_store.identity_store, - &bob_pre_key_bundle, - &mut rng, - None, - ) - .await?; - - let trust_root = KeyPair::generate(&mut rng); - let server_key = KeyPair::generate(&mut rng); - - let server_cert = - ServerCertificate::new(1, server_key.public_key, &trust_root.private_key, &mut rng)?; - - let expires = 1605722925; - - let sender_cert = SenderCertificate::new( - alice_uuid.clone(), - Some(alice_e164.clone()), - alice_pubkey, - alice_device_id, - expires, - server_cert, - &server_key.private_key, - &mut rng, - )?; - - let alice_ptext = vec![1, 2, 3, 23, 99]; - let alice_message = message_encrypt( - &alice_ptext, - &bob_uuid_address, - &mut alice_store.session_store, - &mut alice_store.identity_store, - None, - ) - .await?; - - let alice_usmc = UnidentifiedSenderMessageContent::new( - alice_message.message_type(), - sender_cert.clone(), - alice_message.serialize().to_vec(), - ContentHint::Default, - None, - )?; - - let recipients = [&bob_uuid_address]; - let mut session = alice_store - .session_store - .load_session(&bob_uuid_address, None) - .await? - .expect("present"); - session.archive_current_state()?; - match sealed_sender_multi_recipient_encrypt( - &recipients, - &[&session], - &alice_usmc, - &mut alice_store.identity_store, - None, - &mut rng, - ) - .await - { - Ok(_) => panic!("should have failed"), - Err(e) => { - // Make sure we mention *which* recipient's session failed. - let description = e.to_string(); - assert!( - description.contains(&bob_uuid_address.to_string()), - "should mention recipient in message \"{}\"", - description - ); - } - } - - Ok(()) - } - .now_or_never() - .expect("sync") -} - -#[test] -fn test_sealed_sender_multi_recipient_encrypt_with_bad_registration_id( -) -> Result<(), SignalProtocolError> { - async { - let mut rng = OsRng; - - let alice_device_id = 23; - let bob_device_id = 42; - - let alice_e164 = "+14151111111".to_owned(); - - let alice_uuid = "9d0652a3-dcc3-4d11-975f-74d61598733f".to_string(); - let bob_uuid = "796abedb-ca4e-4f18-8803-1fde5b921f9f".to_string(); - - let bob_uuid_address = ProtocolAddress::new(bob_uuid.clone(), bob_device_id); - - let mut alice_store = support::test_in_memory_protocol_store()?; - let mut bob_store = - InMemSignalProtocolStore::new(IdentityKeyPair::generate(&mut rng), 0x4000)?; - - let alice_pubkey = *alice_store.get_identity_key_pair(None).await?.public_key(); - - let bob_pre_key_bundle = create_pre_key_bundle(&mut bob_store, &mut rng).await?; - - process_prekey_bundle( - &bob_uuid_address, - &mut alice_store.session_store, - &mut alice_store.identity_store, - &bob_pre_key_bundle, - &mut rng, - None, - ) - .await?; - - let trust_root = KeyPair::generate(&mut rng); - let server_key = KeyPair::generate(&mut rng); - - let server_cert = - ServerCertificate::new(1, server_key.public_key, &trust_root.private_key, &mut rng)?; - - let expires = 1605722925; - - let sender_cert = SenderCertificate::new( - alice_uuid.clone(), - Some(alice_e164.clone()), - alice_pubkey, - alice_device_id, - expires, - server_cert, - &server_key.private_key, - &mut rng, - )?; - - let alice_ptext = vec![1, 2, 3, 23, 99]; - let alice_message = message_encrypt( - &alice_ptext, - &bob_uuid_address, - &mut alice_store.session_store, - &mut alice_store.identity_store, - None, - ) - .await?; - - let alice_usmc = UnidentifiedSenderMessageContent::new( - alice_message.message_type(), - sender_cert.clone(), - alice_message.serialize().to_vec(), - ContentHint::Default, - None, - )?; - - let recipients = [&bob_uuid_address]; - match sealed_sender_multi_recipient_encrypt( - &recipients, - &alice_store - .session_store - .load_existing_sessions(&recipients)?, - &alice_usmc, - &mut alice_store.identity_store, - None, - &mut rng, - ) - .await - { - Ok(_) => panic!("should have failed"), - Err(SignalProtocolError::InvalidRegistrationId(address, _id)) => { - assert_eq!(address, bob_uuid_address); - } - Err(e) => panic!("wrong error: {}", e), - } - - Ok(()) - } - .now_or_never() - .expect("sync") -} - -#[test] -fn test_decryption_error_in_sealed_sender() -> Result<(), SignalProtocolError> { - async { - let mut rng = OsRng; - - let alice_device_id = 23; - let bob_device_id = 42; - - let alice_e164 = "+14151111111".to_owned(); - - let alice_uuid = "9d0652a3-dcc3-4d11-975f-74d61598733f".to_string(); - let bob_uuid = "796abedb-ca4e-4f18-8803-1fde5b921f9f".to_string(); - - let alice_uuid_address = ProtocolAddress::new(alice_uuid.clone(), 1); - let bob_uuid_address = ProtocolAddress::new(bob_uuid.clone(), bob_device_id); - - let mut alice_store = support::test_in_memory_protocol_store()?; - let mut bob_store = support::test_in_memory_protocol_store()?; - - let alice_pubkey = *alice_store.get_identity_key_pair(None).await?.public_key(); - - let alice_pre_key_bundle = create_pre_key_bundle(&mut alice_store, &mut rng).await?; - - process_prekey_bundle( - &alice_uuid_address, - &mut bob_store.session_store, - &mut bob_store.identity_store, - &alice_pre_key_bundle, - &mut rng, - None, - ) - .await?; - - // Send one message to establish a session. - - let bob_first_message = message_encrypt( - b"swim camp", - &alice_uuid_address, - &mut bob_store.session_store, - &mut bob_store.identity_store, - None, - ) - .await?; - - message_decrypt( - &bob_first_message, - &bob_uuid_address, - &mut alice_store.session_store, - &mut alice_store.identity_store, - &mut alice_store.pre_key_store, - &mut alice_store.signed_pre_key_store, - &mut rng, - None, - ) - .await?; - - // Pretend the second message fails to decrypt. - - let bob_message = message_encrypt( - b"space camp", - &alice_uuid_address, - &mut bob_store.session_store, - &mut bob_store.identity_store, - None, - ) - .await?; - - let original_ratchet_key = match bob_message { - CiphertextMessage::PreKeySignalMessage(ref m) => m.message().sender_ratchet_key(), - _ => panic!("without ACKs, every message should be a PreKeySignalMessage"), - }; - - // Skip over the part where Bob sends this to Alice and Alice fails to decrypt it, - // for whatever reason. - - let trust_root = KeyPair::generate(&mut rng); - let server_key = KeyPair::generate(&mut rng); - - let server_cert = - ServerCertificate::new(1, server_key.public_key, &trust_root.private_key, &mut rng)?; - - let expires = 1605722925; - - let sender_cert = SenderCertificate::new( - alice_uuid.clone(), - Some(alice_e164.clone()), - alice_pubkey, - alice_device_id, - expires, - server_cert, - &server_key.private_key, - &mut rng, - )?; - - let error_message = DecryptionErrorMessage::for_original( - bob_message.serialize(), - bob_message.message_type(), - 408, - 5, - )?; - let error_message_content = PlaintextContent::from(error_message); - let error_message_usmc = UnidentifiedSenderMessageContent::new( - CiphertextMessageType::Plaintext, - sender_cert.clone(), - error_message_content.serialized().to_vec(), - ContentHint::Default, - None, - )?; - - let alice_ctext = sealed_sender_encrypt_from_usmc( - &bob_uuid_address, - &error_message_usmc, - &mut alice_store.identity_store, - None, - &mut rng, - ) - .await?; - - let bob_usmc = - sealed_sender_decrypt_to_usmc(&alice_ctext, &mut bob_store.identity_store, None) - .await?; - - assert!(matches!( - bob_usmc.msg_type()?, - CiphertextMessageType::Plaintext, - )); - - let bob_plaintext = PlaintextContent::try_from(bob_usmc.contents()?)?; - let bob_error_message = - extract_decryption_error_message_from_serialized_content(bob_plaintext.body()) - .expect("present"); - - assert_eq!(bob_error_message.ratchet_key(), Some(original_ratchet_key)); - assert_eq!(bob_error_message.timestamp(), 408); - assert_eq!(bob_error_message.device_id(), 5); - - Ok(()) - } - .now_or_never() - .expect("sync") -} diff --git a/net/gurk-rs/files/vendor/libsignal-protocol/tests/session.rs b/net/gurk-rs/files/vendor/libsignal-protocol/tests/session.rs deleted file mode 100644 index a389cc5..0000000 --- a/net/gurk-rs/files/vendor/libsignal-protocol/tests/session.rs +++ /dev/null @@ -1,1990 +0,0 @@ -// -// Copyright 2020 Signal Messenger, LLC. -// SPDX-License-Identifier: AGPL-3.0-only -// - -mod support; - -use futures_util::FutureExt; -use libsignal_protocol::*; -use rand::rngs::OsRng; -use std::convert::TryFrom; -use support::*; - -#[test] -#[allow(clippy::eval_order_dependence)] -fn test_basic_prekey_v3() -> Result<(), SignalProtocolError> { - async { - let mut csprng = OsRng; - - let alice_address = ProtocolAddress::new("+14151111111".to_owned(), 1); - let bob_address = ProtocolAddress::new("+14151111112".to_owned(), 1); - - let mut alice_store = support::test_in_memory_protocol_store()?; - let mut bob_store = support::test_in_memory_protocol_store()?; - - let bob_pre_key_pair = KeyPair::generate(&mut csprng); - let bob_signed_pre_key_pair = KeyPair::generate(&mut csprng); - - let bob_signed_pre_key_public = bob_signed_pre_key_pair.public_key.serialize(); - let bob_signed_pre_key_signature = bob_store - .get_identity_key_pair(None) - .await? - .private_key() - .calculate_signature(&bob_signed_pre_key_public, &mut csprng)?; - - let pre_key_id = 31337; - let signed_pre_key_id = 22; - - let bob_pre_key_bundle = PreKeyBundle::new( - bob_store.get_local_registration_id(None).await?, - 1, // device id - Some((pre_key_id, bob_pre_key_pair.public_key)), // pre key - signed_pre_key_id, // signed pre key id - bob_signed_pre_key_pair.public_key, - bob_signed_pre_key_signature.to_vec(), - *bob_store.get_identity_key_pair(None).await?.identity_key(), - )?; - - process_prekey_bundle( - &bob_address, - &mut alice_store.session_store, - &mut alice_store.identity_store, - &bob_pre_key_bundle, - &mut csprng, - None, - ) - .await?; - - assert!(alice_store - .load_session(&bob_address, None) - .await? - .is_some()); - assert_eq!( - alice_store - .load_session(&bob_address, None) - .await? - .expect("session found") - .session_version()?, - 3 - ); - - let original_message = "L'homme est condamné à être libre"; - - let outgoing_message = encrypt(&mut alice_store, &bob_address, original_message).await?; - - assert_eq!( - outgoing_message.message_type(), - CiphertextMessageType::PreKey - ); - - let incoming_message = CiphertextMessage::PreKeySignalMessage( - PreKeySignalMessage::try_from(outgoing_message.serialize())?, - ); - - bob_store - .save_pre_key( - pre_key_id, - &PreKeyRecord::new(pre_key_id, &bob_pre_key_pair), - None, - ) - .await?; - bob_store - .save_signed_pre_key( - signed_pre_key_id, - &SignedPreKeyRecord::new( - signed_pre_key_id, - /*timestamp*/ 42, - &bob_signed_pre_key_pair, - &bob_signed_pre_key_signature, - ), - None, - ) - .await?; - - let ptext = decrypt(&mut bob_store, &alice_address, &incoming_message).await?; - - assert_eq!( - String::from_utf8(ptext).expect("valid utf8"), - original_message - ); - - let bobs_response = "Who watches the watchers?"; - - assert!(bob_store - .load_session(&alice_address, None) - .await? - .is_some()); - let bobs_session_with_alice = bob_store - .load_session(&alice_address, None) - .await? - .expect("session found"); - assert_eq!(bobs_session_with_alice.session_version()?, 3); - assert_eq!(bobs_session_with_alice.alice_base_key()?.len(), 32 + 1); - - let bob_outgoing = encrypt(&mut bob_store, &alice_address, bobs_response).await?; - - assert_eq!(bob_outgoing.message_type(), CiphertextMessageType::Whisper); - - let alice_decrypts = decrypt(&mut alice_store, &bob_address, &bob_outgoing).await?; - - assert_eq!( - String::from_utf8(alice_decrypts).expect("valid utf8"), - bobs_response - ); - - run_interaction( - &mut alice_store, - &alice_address, - &mut bob_store, - &bob_address, - ) - .await?; - - let mut alice_store = support::test_in_memory_protocol_store()?; - - let bob_pre_key_pair = KeyPair::generate(&mut csprng); - let bob_signed_pre_key_pair = KeyPair::generate(&mut csprng); - - let bob_signed_pre_key_public = bob_signed_pre_key_pair.public_key.serialize(); - let bob_signed_pre_key_signature = bob_store - .get_identity_key_pair(None) - .await? - .private_key() - .calculate_signature(&bob_signed_pre_key_public, &mut csprng)?; - - let pre_key_id = 31337; - let signed_pre_key_id = 22; - - let bob_pre_key_bundle = PreKeyBundle::new( - bob_store.get_local_registration_id(None).await?, - 1, // device id - Some((pre_key_id + 1, bob_pre_key_pair.public_key)), // pre key, - signed_pre_key_id + 1, - bob_signed_pre_key_pair.public_key, - bob_signed_pre_key_signature.to_vec(), - *bob_store.get_identity_key_pair(None).await?.identity_key(), - )?; - - bob_store - .save_pre_key( - pre_key_id + 1, - &PreKeyRecord::new(pre_key_id + 1, &bob_pre_key_pair), - None, - ) - .await?; - bob_store - .save_signed_pre_key( - signed_pre_key_id + 1, - &SignedPreKeyRecord::new( - signed_pre_key_id + 1, - /*timestamp*/ 42, - &bob_signed_pre_key_pair, - &bob_signed_pre_key_signature, - ), - None, - ) - .await?; - - process_prekey_bundle( - &bob_address, - &mut alice_store.session_store, - &mut alice_store.identity_store, - &bob_pre_key_bundle, - &mut csprng, - None, - ) - .await?; - - let outgoing_message = encrypt(&mut alice_store, &bob_address, original_message).await?; - - assert!(matches!( - decrypt(&mut bob_store, &alice_address, &outgoing_message) - .await - .unwrap_err(), - SignalProtocolError::UntrustedIdentity(a) if a == alice_address - )); - - assert!( - bob_store - .save_identity( - &alice_address, - alice_store - .get_identity_key_pair(None) - .await? - .identity_key(), - None, - ) - .await? - ); - - let decrypted = decrypt(&mut bob_store, &alice_address, &outgoing_message).await?; - assert_eq!( - String::from_utf8(decrypted).expect("valid utf8"), - original_message - ); - - // Sign pre-key with wrong key: - let bob_pre_key_bundle = PreKeyBundle::new( - bob_store.get_local_registration_id(None).await?, - 1, // device id - Some((pre_key_id, bob_pre_key_pair.public_key)), // pre key - signed_pre_key_id, - bob_signed_pre_key_pair.public_key, - bob_signed_pre_key_signature.to_vec(), - *alice_store - .get_identity_key_pair(None) - .await? - .identity_key(), - )?; - - assert!(process_prekey_bundle( - &bob_address, - &mut alice_store.session_store, - &mut alice_store.identity_store, - &bob_pre_key_bundle, - &mut csprng, - None, - ) - .await - .is_err()); - - Ok(()) - } - .now_or_never() - .expect("sync") -} - -#[test] -#[ignore = "slow to run locally"] -#[allow(clippy::eval_order_dependence)] -fn chain_jump_over_limit() -> Result<(), SignalProtocolError> { - async { - let mut csprng = OsRng; - - let alice_address = ProtocolAddress::new("+14151111111".to_owned(), 1); - let bob_address = ProtocolAddress::new("+14151111112".to_owned(), 1); - - let mut alice_store = support::test_in_memory_protocol_store()?; - let mut bob_store = support::test_in_memory_protocol_store()?; - - let bob_pre_key_pair = KeyPair::generate(&mut csprng); - let bob_signed_pre_key_pair = KeyPair::generate(&mut csprng); - - let bob_signed_pre_key_public = bob_signed_pre_key_pair.public_key.serialize(); - let bob_signed_pre_key_signature = bob_store - .get_identity_key_pair(None) - .await? - .private_key() - .calculate_signature(&bob_signed_pre_key_public, &mut csprng)?; - - let pre_key_id = 31337; - let signed_pre_key_id = 22; - - let bob_pre_key_bundle = PreKeyBundle::new( - bob_store.get_local_registration_id(None).await?, - 1, // device id - Some((pre_key_id, bob_pre_key_pair.public_key)), // pre key - signed_pre_key_id, // signed pre key id - bob_signed_pre_key_pair.public_key, - bob_signed_pre_key_signature.to_vec(), - *bob_store.get_identity_key_pair(None).await?.identity_key(), - )?; - - process_prekey_bundle( - &bob_address, - &mut alice_store.session_store, - &mut alice_store.identity_store, - &bob_pre_key_bundle, - &mut csprng, - None, - ) - .await?; - - bob_store - .save_pre_key( - pre_key_id, - &PreKeyRecord::new(pre_key_id, &bob_pre_key_pair), - None, - ) - .await?; - bob_store - .save_signed_pre_key( - signed_pre_key_id, - &SignedPreKeyRecord::new( - signed_pre_key_id, - /*timestamp*/ 42, - &bob_signed_pre_key_pair, - &bob_signed_pre_key_signature, - ), - None, - ) - .await?; - - // Same as library consts.rs - pub const MAX_FORWARD_JUMPS: usize = 25_000; - - for _i in 0..(MAX_FORWARD_JUMPS + 1) { - let _msg = encrypt( - &mut alice_store, - &bob_address, - "Yet another message for you", - ) - .await?; - } - - let too_far = encrypt(&mut alice_store, &bob_address, "Now you have gone too far").await?; - - assert!(decrypt(&mut bob_store, &alice_address, &too_far) - .await - .is_err()); - Ok(()) - } - .now_or_never() - .expect("sync") -} - -#[test] -#[ignore = "slow to run locally"] -#[allow(clippy::eval_order_dependence)] -fn chain_jump_over_limit_with_self() -> Result<(), SignalProtocolError> { - async { - let mut csprng = OsRng; - - let a1_address = ProtocolAddress::new("+14151111111".to_owned(), 1); - let a2_address = ProtocolAddress::new("+14151111111".to_owned(), 2); - - let mut a1_store = support::test_in_memory_protocol_store()?; - let mut a2_store = a1_store.clone(); // same key! - - let a2_pre_key_pair = KeyPair::generate(&mut csprng); - let a2_signed_pre_key_pair = KeyPair::generate(&mut csprng); - - let a2_signed_pre_key_public = a2_signed_pre_key_pair.public_key.serialize(); - let a2_signed_pre_key_signature = a2_store - .get_identity_key_pair(None) - .await? - .private_key() - .calculate_signature(&a2_signed_pre_key_public, &mut csprng)?; - - let pre_key_id = 31337; - let signed_pre_key_id = 22; - - let a2_pre_key_bundle = PreKeyBundle::new( - a2_store.get_local_registration_id(None).await?, - 1, // device id - Some((pre_key_id, a2_pre_key_pair.public_key)), // pre key - signed_pre_key_id, // signed pre key id - a2_signed_pre_key_pair.public_key, - a2_signed_pre_key_signature.to_vec(), - *a2_store.get_identity_key_pair(None).await?.identity_key(), - )?; - - process_prekey_bundle( - &a2_address, - &mut a1_store.session_store, - &mut a1_store.identity_store, - &a2_pre_key_bundle, - &mut csprng, - None, - ) - .await?; - - a2_store - .save_pre_key( - pre_key_id, - &PreKeyRecord::new(pre_key_id, &a2_pre_key_pair), - None, - ) - .await?; - a2_store - .save_signed_pre_key( - signed_pre_key_id, - &SignedPreKeyRecord::new( - signed_pre_key_id, - /*timestamp*/ 42, - &a2_signed_pre_key_pair, - &a2_signed_pre_key_signature, - ), - None, - ) - .await?; - - // Same as library consts.rs - pub const MAX_FORWARD_JUMPS: usize = 25_000; - - for _i in 0..(MAX_FORWARD_JUMPS + 1) { - let _msg = encrypt( - &mut a1_store, - &a2_address, - "Yet another message for youself", - ) - .await?; - } - - let too_far = encrypt( - &mut a1_store, - &a2_address, - "This is the song that never ends", - ) - .await?; - - let ptext = decrypt(&mut a2_store, &a1_address, &too_far).await?; - assert_eq!( - String::from_utf8(ptext).unwrap(), - "This is the song that never ends" - ); - - Ok(()) - } - .now_or_never() - .expect("sync") -} - -#[test] -#[allow(clippy::eval_order_dependence)] -fn test_bad_signed_pre_key_signature() -> Result<(), SignalProtocolError> { - async { - let bob_address = ProtocolAddress::new("+14151111112".to_owned(), 1); - - let mut alice_store = support::test_in_memory_protocol_store()?; - let bob_store = support::test_in_memory_protocol_store()?; - - let mut csprng = OsRng; - let bob_pre_key_pair = KeyPair::generate(&mut csprng); - let bob_signed_pre_key_pair = KeyPair::generate(&mut csprng); - - let bob_signed_pre_key_public = bob_signed_pre_key_pair.public_key.serialize(); - let bob_signed_pre_key_signature = bob_store - .get_identity_key_pair(None) - .await? - .private_key() - .calculate_signature(&bob_signed_pre_key_public, &mut csprng)? - .to_vec(); - - let pre_key_id = 31337; - let signed_pre_key_id = 22; - - for bit in 0..8 * bob_signed_pre_key_signature.len() { - let mut bad_signature = bob_signed_pre_key_signature.clone(); - - bad_signature[bit / 8] ^= 0x01u8 << (bit % 8); - - let bob_pre_key_bundle = PreKeyBundle::new( - bob_store.get_local_registration_id(None).await?, - 1, - Some((pre_key_id, bob_pre_key_pair.public_key)), - signed_pre_key_id, - bob_signed_pre_key_pair.public_key, - bad_signature, - *bob_store.get_identity_key_pair(None).await?.identity_key(), - )?; - - assert!(process_prekey_bundle( - &bob_address, - &mut alice_store.session_store, - &mut alice_store.identity_store, - &bob_pre_key_bundle, - &mut csprng, - None, - ) - .await - .is_err()); - } - - // Finally check that the non-corrupted signature is accepted: - - let bob_pre_key_bundle = PreKeyBundle::new( - bob_store.get_local_registration_id(None).await?, - 1, - Some((pre_key_id, bob_pre_key_pair.public_key)), - signed_pre_key_id, - bob_signed_pre_key_pair.public_key, - bob_signed_pre_key_signature, - *bob_store.get_identity_key_pair(None).await?.identity_key(), - )?; - - process_prekey_bundle( - &bob_address, - &mut alice_store.session_store, - &mut alice_store.identity_store, - &bob_pre_key_bundle, - &mut csprng, - None, - ) - .await?; - - Ok(()) - } - .now_or_never() - .expect("sync") -} - -// testRepeatBundleMessageV2 cannot be represented - -#[test] -#[allow(clippy::eval_order_dependence)] -fn repeat_bundle_message_v3() -> Result<(), SignalProtocolError> { - async { - let alice_address = ProtocolAddress::new("+14151111111".to_owned(), 1); - let bob_address = ProtocolAddress::new("+14151111112".to_owned(), 1); - - let mut alice_store = support::test_in_memory_protocol_store()?; - let mut bob_store = support::test_in_memory_protocol_store()?; - - let mut csprng = OsRng; - let bob_pre_key_pair = KeyPair::generate(&mut csprng); - let bob_signed_pre_key_pair = KeyPair::generate(&mut csprng); - - let bob_signed_pre_key_public = bob_signed_pre_key_pair.public_key.serialize(); - let bob_signed_pre_key_signature = bob_store - .get_identity_key_pair(None) - .await? - .private_key() - .calculate_signature(&bob_signed_pre_key_public, &mut csprng)?; - - let pre_key_id = 31337; - let signed_pre_key_id = 22; - - let bob_pre_key_bundle = PreKeyBundle::new( - bob_store.get_local_registration_id(None).await?, - 1, // device id - Some((pre_key_id, bob_pre_key_pair.public_key)), // pre key - signed_pre_key_id, // signed pre key id - bob_signed_pre_key_pair.public_key, - bob_signed_pre_key_signature.to_vec(), - *bob_store.get_identity_key_pair(None).await?.identity_key(), - )?; - - process_prekey_bundle( - &bob_address, - &mut alice_store.session_store, - &mut alice_store.identity_store, - &bob_pre_key_bundle, - &mut csprng, - None, - ) - .await?; - - assert!(alice_store - .load_session(&bob_address, None) - .await? - .is_some()); - assert_eq!( - alice_store - .load_session(&bob_address, None) - .await? - .expect("session found") - .session_version()?, - 3 - ); - - let original_message = "L'homme est condamné à être libre"; - - let outgoing_message1 = encrypt(&mut alice_store, &bob_address, original_message).await?; - let outgoing_message2 = encrypt(&mut alice_store, &bob_address, original_message).await?; - - assert_eq!( - outgoing_message1.message_type(), - CiphertextMessageType::PreKey - ); - assert_eq!( - outgoing_message2.message_type(), - CiphertextMessageType::PreKey - ); - - let incoming_message = CiphertextMessage::PreKeySignalMessage( - PreKeySignalMessage::try_from(outgoing_message1.serialize())?, - ); - - bob_store - .save_pre_key( - pre_key_id, - &PreKeyRecord::new(pre_key_id, &bob_pre_key_pair), - None, - ) - .await?; - bob_store - .save_signed_pre_key( - signed_pre_key_id, - &SignedPreKeyRecord::new( - signed_pre_key_id, - /*timestamp*/ 42, - &bob_signed_pre_key_pair, - &bob_signed_pre_key_signature, - ), - None, - ) - .await?; - - let ptext = decrypt(&mut bob_store, &alice_address, &incoming_message).await?; - assert_eq!( - String::from_utf8(ptext).expect("valid utf8"), - original_message - ); - - let bob_outgoing = encrypt(&mut bob_store, &alice_address, original_message).await?; - assert_eq!(bob_outgoing.message_type(), CiphertextMessageType::Whisper); - let alice_decrypts = decrypt(&mut alice_store, &bob_address, &bob_outgoing).await?; - assert_eq!( - String::from_utf8(alice_decrypts).expect("valid utf8"), - original_message - ); - - // The test - - let incoming_message2 = CiphertextMessage::PreKeySignalMessage( - PreKeySignalMessage::try_from(outgoing_message2.serialize())?, - ); - - let ptext = decrypt(&mut bob_store, &alice_address, &incoming_message2).await?; - assert_eq!( - String::from_utf8(ptext).expect("valid utf8"), - original_message - ); - - let bob_outgoing = encrypt(&mut bob_store, &alice_address, original_message).await?; - let alice_decrypts = decrypt(&mut alice_store, &bob_address, &bob_outgoing).await?; - assert_eq!( - String::from_utf8(alice_decrypts).expect("valid utf8"), - original_message - ); - - Ok(()) - } - .now_or_never() - .expect("sync") -} - -#[test] -#[allow(clippy::eval_order_dependence)] -fn bad_message_bundle() -> Result<(), SignalProtocolError> { - async { - let mut csprng = OsRng; - - let alice_address = ProtocolAddress::new("+14151111111".to_owned(), 1); - let bob_address = ProtocolAddress::new("+14151111112".to_owned(), 1); - - let mut alice_store = support::test_in_memory_protocol_store()?; - let mut bob_store = support::test_in_memory_protocol_store()?; - - let bob_pre_key_pair = KeyPair::generate(&mut csprng); - let bob_signed_pre_key_pair = KeyPair::generate(&mut csprng); - - let bob_signed_pre_key_public = bob_signed_pre_key_pair.public_key.serialize(); - let bob_signed_pre_key_signature = bob_store - .get_identity_key_pair(None) - .await? - .private_key() - .calculate_signature(&bob_signed_pre_key_public, &mut csprng)?; - - let pre_key_id = 31337; - let signed_pre_key_id = 22; - - let bob_pre_key_bundle = PreKeyBundle::new( - bob_store.get_local_registration_id(None).await?, - 1, // device id - Some((pre_key_id, bob_pre_key_pair.public_key)), - signed_pre_key_id, // signed pre key id - bob_signed_pre_key_pair.public_key, - bob_signed_pre_key_signature.to_vec(), - *bob_store.get_identity_key_pair(None).await?.identity_key(), - )?; - - process_prekey_bundle( - &bob_address, - &mut alice_store.session_store, - &mut alice_store.identity_store, - &bob_pre_key_bundle, - &mut csprng, - None, - ) - .await?; - - bob_store - .save_pre_key( - pre_key_id, - &PreKeyRecord::new(pre_key_id, &bob_pre_key_pair), - None, - ) - .await?; - bob_store - .save_signed_pre_key( - signed_pre_key_id, - &SignedPreKeyRecord::new( - signed_pre_key_id, - /*timestamp*/ 42, - &bob_signed_pre_key_pair, - &bob_signed_pre_key_signature, - ), - None, - ) - .await?; - - assert!(alice_store - .load_session(&bob_address, None) - .await? - .is_some()); - assert_eq!( - alice_store - .load_session(&bob_address, None) - .await? - .expect("session found") - .session_version()?, - 3 - ); - - let original_message = "L'homme est condamné à être libre"; - - assert!(bob_store.get_pre_key(pre_key_id, None).await.is_ok()); - let outgoing_message = encrypt(&mut alice_store, &bob_address, original_message).await?; - - assert_eq!( - outgoing_message.message_type(), - CiphertextMessageType::PreKey - ); - - let outgoing_message = outgoing_message.serialize().to_vec(); - - let mut corrupted_message: Vec = outgoing_message.clone(); - corrupted_message[outgoing_message.len() - 10] ^= 1; - - let incoming_message = CiphertextMessage::PreKeySignalMessage( - PreKeySignalMessage::try_from(corrupted_message.as_slice())?, - ); - - assert!(decrypt(&mut bob_store, &alice_address, &incoming_message) - .await - .is_err()); - assert!(bob_store.get_pre_key(pre_key_id, None).await.is_ok()); - - let incoming_message = CiphertextMessage::PreKeySignalMessage( - PreKeySignalMessage::try_from(outgoing_message.as_slice())?, - ); - - let ptext = decrypt(&mut bob_store, &alice_address, &incoming_message).await?; - - assert_eq!( - String::from_utf8(ptext).expect("valid utf8"), - original_message - ); - assert!(matches!( - bob_store.get_pre_key(pre_key_id, None).await.unwrap_err(), - SignalProtocolError::InvalidPreKeyId - )); - - Ok(()) - } - .now_or_never() - .expect("sync") -} - -#[test] -#[allow(clippy::eval_order_dependence)] -fn optional_one_time_prekey() -> Result<(), SignalProtocolError> { - async { - let alice_address = ProtocolAddress::new("+14151111111".to_owned(), 1); - let bob_address = ProtocolAddress::new("+14151111112".to_owned(), 1); - - let mut alice_store = support::test_in_memory_protocol_store()?; - let mut bob_store = support::test_in_memory_protocol_store()?; - - let mut csprng = OsRng; - let bob_signed_pre_key_pair = KeyPair::generate(&mut csprng); - - let bob_signed_pre_key_public = bob_signed_pre_key_pair.public_key.serialize(); - let bob_signed_pre_key_signature = bob_store - .get_identity_key_pair(None) - .await? - .private_key() - .calculate_signature(&bob_signed_pre_key_public, &mut csprng)?; - - let signed_pre_key_id = 22; - - let bob_pre_key_bundle = PreKeyBundle::new( - bob_store.get_local_registration_id(None).await?, - 1, // device id - None, // no pre key - signed_pre_key_id, // signed pre key id - bob_signed_pre_key_pair.public_key, - bob_signed_pre_key_signature.to_vec(), - *bob_store.get_identity_key_pair(None).await?.identity_key(), - )?; - - process_prekey_bundle( - &bob_address, - &mut alice_store.session_store, - &mut alice_store.identity_store, - &bob_pre_key_bundle, - &mut csprng, - None, - ) - .await?; - - assert_eq!( - alice_store - .load_session(&bob_address, None) - .await? - .expect("session found") - .session_version()?, - 3 - ); - - let original_message = "L'homme est condamné à être libre"; - - let outgoing_message = encrypt(&mut alice_store, &bob_address, original_message).await?; - - assert_eq!( - outgoing_message.message_type(), - CiphertextMessageType::PreKey - ); - - let incoming_message = CiphertextMessage::PreKeySignalMessage( - PreKeySignalMessage::try_from(outgoing_message.serialize())?, - ); - - bob_store - .save_signed_pre_key( - signed_pre_key_id, - &SignedPreKeyRecord::new( - signed_pre_key_id, - /*timestamp*/ 42, - &bob_signed_pre_key_pair, - &bob_signed_pre_key_signature, - ), - None, - ) - .await?; - - let ptext = decrypt(&mut bob_store, &alice_address, &incoming_message).await?; - - assert_eq!( - String::from_utf8(ptext).expect("valid utf8"), - original_message - ); - - Ok(()) - } - .now_or_never() - .expect("sync") -} - -#[test] -fn basic_session_v3() -> Result<(), SignalProtocolError> { - let (alice_session, bob_session) = initialize_sessions_v3()?; - run_session_interaction(alice_session, bob_session)?; - Ok(()) -} - -#[test] -fn message_key_limits() -> Result<(), SignalProtocolError> { - async { - let (alice_session_record, bob_session_record) = initialize_sessions_v3()?; - - let alice_address = ProtocolAddress::new("+14159999999".to_owned(), 1); - let bob_address = ProtocolAddress::new("+14158888888".to_owned(), 1); - - let mut alice_store = support::test_in_memory_protocol_store()?; - let mut bob_store = support::test_in_memory_protocol_store()?; - - alice_store - .store_session(&bob_address, &alice_session_record, None) - .await?; - bob_store - .store_session(&alice_address, &bob_session_record, None) - .await?; - - const MAX_MESSAGE_KEYS: usize = 2000; // same value as in library - const TOO_MANY_MESSAGES: usize = MAX_MESSAGE_KEYS + 300; - - let mut inflight = Vec::with_capacity(TOO_MANY_MESSAGES); - - for i in 0..TOO_MANY_MESSAGES { - inflight - .push(encrypt(&mut alice_store, &bob_address, &format!("It's over {}", i)).await?); - } - - assert_eq!( - String::from_utf8(decrypt(&mut bob_store, &alice_address, &inflight[1000]).await?) - .expect("valid utf8"), - "It's over 1000" - ); - assert_eq!( - String::from_utf8( - decrypt( - &mut bob_store, - &alice_address, - &inflight[TOO_MANY_MESSAGES - 1] - ) - .await? - ) - .expect("valid utf8"), - format!("It's over {}", TOO_MANY_MESSAGES - 1) - ); - - let err = decrypt(&mut bob_store, &alice_address, &inflight[5]) - .await - .unwrap_err(); - assert!(matches!( - err, - SignalProtocolError::DuplicatedMessage(2300, 5) - )); - Ok(()) - } - .now_or_never() - .expect("sync") -} - -#[allow(clippy::needless_range_loop)] -fn run_session_interaction( - alice_session: SessionRecord, - bob_session: SessionRecord, -) -> Result<(), SignalProtocolError> { - async { - use rand::seq::SliceRandom; - - let alice_address = ProtocolAddress::new("+14159999999".to_owned(), 1); - let bob_address = ProtocolAddress::new("+14158888888".to_owned(), 1); - - let mut alice_store = support::test_in_memory_protocol_store()?; - let mut bob_store = support::test_in_memory_protocol_store()?; - - alice_store - .store_session(&bob_address, &alice_session, None) - .await?; - bob_store - .store_session(&alice_address, &bob_session, None) - .await?; - - let alice_plaintext = "This is Alice's message"; - let alice_ciphertext = encrypt(&mut alice_store, &bob_address, alice_plaintext).await?; - let bob_decrypted = decrypt(&mut bob_store, &alice_address, &alice_ciphertext).await?; - assert_eq!( - String::from_utf8(bob_decrypted).expect("valid utf8"), - alice_plaintext - ); - - let bob_plaintext = "This is Bob's reply"; - - let bob_ciphertext = encrypt(&mut bob_store, &alice_address, bob_plaintext).await?; - let alice_decrypted = decrypt(&mut alice_store, &bob_address, &bob_ciphertext).await?; - assert_eq!( - String::from_utf8(alice_decrypted).expect("valid utf8"), - bob_plaintext - ); - - const ALICE_MESSAGE_COUNT: usize = 50; - const BOB_MESSAGE_COUNT: usize = 50; - - let mut alice_messages = Vec::with_capacity(ALICE_MESSAGE_COUNT); - - for i in 0..ALICE_MESSAGE_COUNT { - let ptext = format!("смерть за смерть {}", i); - let ctext = encrypt(&mut alice_store, &bob_address, &ptext).await?; - alice_messages.push((ptext, ctext)); - } - - let mut rng = rand::rngs::OsRng; - - alice_messages.shuffle(&mut rng); - - for i in 0..ALICE_MESSAGE_COUNT / 2 { - let ptext = decrypt(&mut bob_store, &alice_address, &alice_messages[i].1).await?; - assert_eq!( - String::from_utf8(ptext).expect("valid utf8"), - alice_messages[i].0 - ); - } - - let mut bob_messages = Vec::with_capacity(BOB_MESSAGE_COUNT); - - for i in 0..BOB_MESSAGE_COUNT { - let ptext = format!("Relax in the safety of your own delusions. {}", i); - let ctext = encrypt(&mut bob_store, &alice_address, &ptext).await?; - bob_messages.push((ptext, ctext)); - } - - bob_messages.shuffle(&mut rng); - - for i in 0..BOB_MESSAGE_COUNT / 2 { - let ptext = decrypt(&mut alice_store, &bob_address, &bob_messages[i].1).await?; - assert_eq!( - String::from_utf8(ptext).expect("valid utf8"), - bob_messages[i].0 - ); - } - - for i in ALICE_MESSAGE_COUNT / 2..ALICE_MESSAGE_COUNT { - let ptext = decrypt(&mut bob_store, &alice_address, &alice_messages[i].1).await?; - assert_eq!( - String::from_utf8(ptext).expect("valid utf8"), - alice_messages[i].0 - ); - } - - for i in BOB_MESSAGE_COUNT / 2..BOB_MESSAGE_COUNT { - let ptext = decrypt(&mut alice_store, &bob_address, &bob_messages[i].1).await?; - assert_eq!( - String::from_utf8(ptext).expect("valid utf8"), - bob_messages[i].0 - ); - } - - Ok(()) - } - .now_or_never() - .expect("sync") -} - -async fn run_interaction( - alice_store: &mut InMemSignalProtocolStore, - alice_address: &ProtocolAddress, - bob_store: &mut InMemSignalProtocolStore, - bob_address: &ProtocolAddress, -) -> Result<(), SignalProtocolError> { - let alice_ptext = "It's rabbit season"; - - let alice_message = encrypt(alice_store, bob_address, alice_ptext).await?; - assert_eq!(alice_message.message_type(), CiphertextMessageType::Whisper); - assert_eq!( - String::from_utf8(decrypt(bob_store, alice_address, &alice_message).await?) - .expect("valid utf8"), - alice_ptext - ); - - let bob_ptext = "It's duck season"; - - let bob_message = encrypt(bob_store, alice_address, bob_ptext).await?; - assert_eq!(bob_message.message_type(), CiphertextMessageType::Whisper); - assert_eq!( - String::from_utf8(decrypt(alice_store, bob_address, &bob_message).await?) - .expect("valid utf8"), - bob_ptext - ); - - for i in 0..10 { - let alice_ptext = format!("A->B message {}", i); - let alice_message = encrypt(alice_store, bob_address, &alice_ptext).await?; - assert_eq!(alice_message.message_type(), CiphertextMessageType::Whisper); - assert_eq!( - String::from_utf8(decrypt(bob_store, alice_address, &alice_message).await?) - .expect("valid utf8"), - alice_ptext - ); - } - - for i in 0..10 { - let bob_ptext = format!("B->A message {}", i); - let bob_message = encrypt(bob_store, alice_address, &bob_ptext).await?; - assert_eq!(bob_message.message_type(), CiphertextMessageType::Whisper); - assert_eq!( - String::from_utf8(decrypt(alice_store, bob_address, &bob_message).await?) - .expect("valid utf8"), - bob_ptext - ); - } - - let mut alice_ooo_messages = vec![]; - - for i in 0..10 { - let alice_ptext = format!("A->B OOO message {}", i); - let alice_message = encrypt(alice_store, bob_address, &alice_ptext).await?; - alice_ooo_messages.push((alice_ptext, alice_message)); - } - - for i in 0..10 { - let alice_ptext = format!("A->B post-OOO message {}", i); - let alice_message = encrypt(alice_store, bob_address, &alice_ptext).await?; - assert_eq!(alice_message.message_type(), CiphertextMessageType::Whisper); - assert_eq!( - String::from_utf8(decrypt(bob_store, alice_address, &alice_message).await?) - .expect("valid utf8"), - alice_ptext - ); - } - - for i in 0..10 { - let bob_ptext = format!("B->A message post-OOO {}", i); - let bob_message = encrypt(bob_store, alice_address, &bob_ptext).await?; - assert_eq!(bob_message.message_type(), CiphertextMessageType::Whisper); - assert_eq!( - String::from_utf8(decrypt(alice_store, bob_address, &bob_message).await?) - .expect("valid utf8"), - bob_ptext - ); - } - - for (ptext, ctext) in alice_ooo_messages { - assert_eq!( - String::from_utf8(decrypt(bob_store, alice_address, &ctext).await?) - .expect("valid utf8"), - ptext - ); - } - - Ok(()) -} - -#[allow(clippy::eval_order_dependence)] -async fn is_session_id_equal( - alice_store: &dyn ProtocolStore, - alice_address: &ProtocolAddress, - bob_store: &dyn ProtocolStore, - bob_address: &ProtocolAddress, -) -> Result { - Ok(alice_store - .load_session(bob_address, None) - .await? - .expect("session found") - .alice_base_key()? - == bob_store - .load_session(alice_address, None) - .await? - .expect("session found") - .alice_base_key()?) -} - -#[test] -fn basic_simultaneous_initiate() -> Result<(), SignalProtocolError> { - async { - let mut csprng = OsRng; - - let alice_address = ProtocolAddress::new("+14151111111".to_owned(), 1); - let bob_address = ProtocolAddress::new("+14151111112".to_owned(), 1); - - let mut alice_store = support::test_in_memory_protocol_store()?; - let mut bob_store = support::test_in_memory_protocol_store()?; - - let alice_pre_key_bundle = create_pre_key_bundle(&mut alice_store, &mut csprng).await?; - let bob_pre_key_bundle = create_pre_key_bundle(&mut bob_store, &mut csprng).await?; - - process_prekey_bundle( - &bob_address, - &mut alice_store.session_store, - &mut alice_store.identity_store, - &bob_pre_key_bundle, - &mut csprng, - None, - ) - .await?; - - process_prekey_bundle( - &alice_address, - &mut bob_store.session_store, - &mut bob_store.identity_store, - &alice_pre_key_bundle, - &mut csprng, - None, - ) - .await?; - - let message_for_bob = encrypt(&mut alice_store, &bob_address, "hi bob").await?; - let message_for_alice = encrypt(&mut bob_store, &alice_address, "hi alice").await?; - - assert_eq!( - message_for_bob.message_type(), - CiphertextMessageType::PreKey - ); - assert_eq!( - message_for_alice.message_type(), - CiphertextMessageType::PreKey - ); - - assert!( - !is_session_id_equal(&alice_store, &alice_address, &bob_store, &bob_address).await? - ); - - let alice_plaintext = decrypt( - &mut alice_store, - &bob_address, - &CiphertextMessage::PreKeySignalMessage(PreKeySignalMessage::try_from( - message_for_alice.serialize(), - )?), - ) - .await?; - assert_eq!( - String::from_utf8(alice_plaintext).expect("valid utf8"), - "hi alice" - ); - - let bob_plaintext = decrypt( - &mut bob_store, - &alice_address, - &CiphertextMessage::PreKeySignalMessage(PreKeySignalMessage::try_from( - message_for_bob.serialize(), - )?), - ) - .await?; - assert_eq!( - String::from_utf8(bob_plaintext).expect("valid utf8"), - "hi bob" - ); - - assert_eq!( - alice_store - .load_session(&bob_address, None) - .await? - .expect("session found") - .session_version()?, - 3 - ); - assert_eq!( - bob_store - .load_session(&alice_address, None) - .await? - .expect("session found") - .session_version()?, - 3 - ); - - assert!( - !is_session_id_equal(&alice_store, &alice_address, &bob_store, &bob_address).await? - ); - - let alice_response = encrypt(&mut alice_store, &bob_address, "nice to see you").await?; - - assert_eq!( - alice_response.message_type(), - CiphertextMessageType::Whisper - ); - - let response_plaintext = decrypt( - &mut bob_store, - &alice_address, - &CiphertextMessage::SignalMessage(SignalMessage::try_from(alice_response.serialize())?), - ) - .await?; - assert_eq!( - String::from_utf8(response_plaintext).expect("valid utf8"), - "nice to see you" - ); - - assert!(is_session_id_equal(&alice_store, &alice_address, &bob_store, &bob_address).await?); - - let bob_response = encrypt(&mut bob_store, &alice_address, "you as well").await?; - - assert_eq!(bob_response.message_type(), CiphertextMessageType::Whisper); - - let response_plaintext = decrypt( - &mut alice_store, - &bob_address, - &CiphertextMessage::SignalMessage(SignalMessage::try_from(bob_response.serialize())?), - ) - .await?; - assert_eq!( - String::from_utf8(response_plaintext).expect("valid utf8"), - "you as well" - ); - - assert!(is_session_id_equal(&bob_store, &bob_address, &alice_store, &alice_address).await?); - - Ok(()) - } - .now_or_never() - .expect("sync") -} - -#[test] -fn simultaneous_initiate_with_lossage() -> Result<(), SignalProtocolError> { - async { - let mut csprng = OsRng; - - let alice_address = ProtocolAddress::new("+14151111111".to_owned(), 1); - let bob_address = ProtocolAddress::new("+14151111112".to_owned(), 1); - - let mut alice_store = support::test_in_memory_protocol_store()?; - let mut bob_store = support::test_in_memory_protocol_store()?; - - let alice_pre_key_bundle = create_pre_key_bundle(&mut alice_store, &mut csprng).await?; - let bob_pre_key_bundle = create_pre_key_bundle(&mut bob_store, &mut csprng).await?; - - process_prekey_bundle( - &bob_address, - &mut alice_store.session_store, - &mut alice_store.identity_store, - &bob_pre_key_bundle, - &mut csprng, - None, - ) - .await?; - - process_prekey_bundle( - &alice_address, - &mut bob_store.session_store, - &mut bob_store.identity_store, - &alice_pre_key_bundle, - &mut csprng, - None, - ) - .await?; - - let message_for_bob = encrypt(&mut alice_store, &bob_address, "hi bob").await?; - let message_for_alice = encrypt(&mut bob_store, &alice_address, "hi alice").await?; - - assert_eq!( - message_for_bob.message_type(), - CiphertextMessageType::PreKey - ); - assert_eq!( - message_for_alice.message_type(), - CiphertextMessageType::PreKey - ); - - assert!( - !is_session_id_equal(&alice_store, &alice_address, &bob_store, &bob_address).await? - ); - - let bob_plaintext = decrypt( - &mut bob_store, - &alice_address, - &CiphertextMessage::PreKeySignalMessage(PreKeySignalMessage::try_from( - message_for_bob.serialize(), - )?), - ) - .await?; - assert_eq!( - String::from_utf8(bob_plaintext).expect("valid utf8"), - "hi bob" - ); - - assert_eq!( - alice_store - .load_session(&bob_address, None) - .await? - .expect("session found") - .session_version()?, - 3 - ); - assert_eq!( - bob_store - .load_session(&alice_address, None) - .await? - .expect("session found") - .session_version()?, - 3 - ); - - let alice_response = encrypt(&mut alice_store, &bob_address, "nice to see you").await?; - - assert_eq!(alice_response.message_type(), CiphertextMessageType::PreKey); - - let response_plaintext = decrypt( - &mut bob_store, - &alice_address, - &CiphertextMessage::PreKeySignalMessage(PreKeySignalMessage::try_from( - alice_response.serialize(), - )?), - ) - .await?; - assert_eq!( - String::from_utf8(response_plaintext).expect("valid utf8"), - "nice to see you" - ); - - assert!(is_session_id_equal(&alice_store, &alice_address, &bob_store, &bob_address).await?); - - let bob_response = encrypt(&mut bob_store, &alice_address, "you as well").await?; - - assert_eq!(bob_response.message_type(), CiphertextMessageType::Whisper); - - let response_plaintext = decrypt( - &mut alice_store, - &bob_address, - &CiphertextMessage::SignalMessage(SignalMessage::try_from(bob_response.serialize())?), - ) - .await?; - assert_eq!( - String::from_utf8(response_plaintext).expect("valid utf8"), - "you as well" - ); - - assert!(is_session_id_equal(&bob_store, &bob_address, &alice_store, &alice_address).await?); - - Ok(()) - } - .now_or_never() - .expect("sync") -} - -#[test] -fn simultaneous_initiate_lost_message() -> Result<(), SignalProtocolError> { - async { - let mut csprng = OsRng; - - let alice_address = ProtocolAddress::new("+14151111111".to_owned(), 1); - let bob_address = ProtocolAddress::new("+14151111112".to_owned(), 1); - - let mut alice_store = support::test_in_memory_protocol_store()?; - let mut bob_store = support::test_in_memory_protocol_store()?; - - let alice_pre_key_bundle = create_pre_key_bundle(&mut alice_store, &mut csprng).await?; - let bob_pre_key_bundle = create_pre_key_bundle(&mut bob_store, &mut csprng).await?; - - process_prekey_bundle( - &bob_address, - &mut alice_store.session_store, - &mut alice_store.identity_store, - &bob_pre_key_bundle, - &mut csprng, - None, - ) - .await?; - - process_prekey_bundle( - &alice_address, - &mut bob_store.session_store, - &mut bob_store.identity_store, - &alice_pre_key_bundle, - &mut csprng, - None, - ) - .await?; - - let message_for_bob = encrypt(&mut alice_store, &bob_address, "hi bob").await?; - let message_for_alice = encrypt(&mut bob_store, &alice_address, "hi alice").await?; - - assert_eq!( - message_for_bob.message_type(), - CiphertextMessageType::PreKey - ); - assert_eq!( - message_for_alice.message_type(), - CiphertextMessageType::PreKey - ); - - assert!( - !is_session_id_equal(&alice_store, &alice_address, &bob_store, &bob_address).await? - ); - - let alice_plaintext = decrypt( - &mut alice_store, - &bob_address, - &CiphertextMessage::PreKeySignalMessage(PreKeySignalMessage::try_from( - message_for_alice.serialize(), - )?), - ) - .await?; - assert_eq!( - String::from_utf8(alice_plaintext).expect("valid utf8"), - "hi alice" - ); - - let bob_plaintext = decrypt( - &mut bob_store, - &alice_address, - &CiphertextMessage::PreKeySignalMessage(PreKeySignalMessage::try_from( - message_for_bob.serialize(), - )?), - ) - .await?; - assert_eq!( - String::from_utf8(bob_plaintext).expect("valid utf8"), - "hi bob" - ); - - assert_eq!( - alice_store - .load_session(&bob_address, None) - .await? - .expect("session found") - .session_version()?, - 3 - ); - assert_eq!( - bob_store - .load_session(&alice_address, None) - .await? - .expect("session found") - .session_version()?, - 3 - ); - - assert!( - !is_session_id_equal(&alice_store, &alice_address, &bob_store, &bob_address).await? - ); - - let alice_response = encrypt(&mut alice_store, &bob_address, "nice to see you").await?; - - assert_eq!( - alice_response.message_type(), - CiphertextMessageType::Whisper - ); - - assert!( - !is_session_id_equal(&alice_store, &alice_address, &bob_store, &bob_address).await? - ); - - let bob_response = encrypt(&mut bob_store, &alice_address, "you as well").await?; - - assert_eq!(bob_response.message_type(), CiphertextMessageType::Whisper); - - let response_plaintext = decrypt( - &mut alice_store, - &bob_address, - &CiphertextMessage::SignalMessage(SignalMessage::try_from(bob_response.serialize())?), - ) - .await?; - assert_eq!( - String::from_utf8(response_plaintext).expect("valid utf8"), - "you as well" - ); - - assert!(is_session_id_equal(&bob_store, &bob_address, &alice_store, &alice_address).await?); - - Ok(()) - } - .now_or_never() - .expect("sync") -} - -#[test] -fn simultaneous_initiate_repeated_messages() -> Result<(), SignalProtocolError> { - async { - let mut csprng = OsRng; - - let alice_address = ProtocolAddress::new("+14151111111".to_owned(), 1); - let bob_address = ProtocolAddress::new("+14151111112".to_owned(), 1); - - let mut alice_store = support::test_in_memory_protocol_store()?; - let mut bob_store = support::test_in_memory_protocol_store()?; - - for _ in 0..15 { - let alice_pre_key_bundle = create_pre_key_bundle(&mut alice_store, &mut csprng).await?; - let bob_pre_key_bundle = create_pre_key_bundle(&mut bob_store, &mut csprng).await?; - - process_prekey_bundle( - &bob_address, - &mut alice_store.session_store, - &mut alice_store.identity_store, - &bob_pre_key_bundle, - &mut csprng, - None, - ) - .await?; - - process_prekey_bundle( - &alice_address, - &mut bob_store.session_store, - &mut bob_store.identity_store, - &alice_pre_key_bundle, - &mut csprng, - None, - ) - .await?; - - let message_for_bob = encrypt(&mut alice_store, &bob_address, "hi bob").await?; - let message_for_alice = encrypt(&mut bob_store, &alice_address, "hi alice").await?; - - assert_eq!( - message_for_bob.message_type(), - CiphertextMessageType::PreKey - ); - assert_eq!( - message_for_alice.message_type(), - CiphertextMessageType::PreKey - ); - - assert!( - !is_session_id_equal(&alice_store, &alice_address, &bob_store, &bob_address) - .await? - ); - - let alice_plaintext = decrypt( - &mut alice_store, - &bob_address, - &CiphertextMessage::PreKeySignalMessage(PreKeySignalMessage::try_from( - message_for_alice.serialize(), - )?), - ) - .await?; - assert_eq!( - String::from_utf8(alice_plaintext).expect("valid utf8"), - "hi alice" - ); - - let bob_plaintext = decrypt( - &mut bob_store, - &alice_address, - &CiphertextMessage::PreKeySignalMessage(PreKeySignalMessage::try_from( - message_for_bob.serialize(), - )?), - ) - .await?; - assert_eq!( - String::from_utf8(bob_plaintext).expect("valid utf8"), - "hi bob" - ); - - assert_eq!( - alice_store - .load_session(&bob_address, None) - .await? - .expect("session found") - .session_version()?, - 3 - ); - assert_eq!( - bob_store - .load_session(&alice_address, None) - .await? - .expect("session found") - .session_version()?, - 3 - ); - - assert!( - !is_session_id_equal(&alice_store, &alice_address, &bob_store, &bob_address) - .await? - ); - } - - for _ in 0..50 { - let message_for_bob = encrypt(&mut alice_store, &bob_address, "hi bob").await?; - let message_for_alice = encrypt(&mut bob_store, &alice_address, "hi alice").await?; - - assert_eq!( - message_for_bob.message_type(), - CiphertextMessageType::Whisper - ); - assert_eq!( - message_for_alice.message_type(), - CiphertextMessageType::Whisper - ); - - assert!( - !is_session_id_equal(&alice_store, &alice_address, &bob_store, &bob_address) - .await? - ); - - let alice_plaintext = decrypt( - &mut alice_store, - &bob_address, - &CiphertextMessage::SignalMessage(SignalMessage::try_from( - message_for_alice.serialize(), - )?), - ) - .await?; - assert_eq!( - String::from_utf8(alice_plaintext).expect("valid utf8"), - "hi alice" - ); - - let bob_plaintext = decrypt( - &mut bob_store, - &alice_address, - &CiphertextMessage::SignalMessage(SignalMessage::try_from( - message_for_bob.serialize(), - )?), - ) - .await?; - assert_eq!( - String::from_utf8(bob_plaintext).expect("valid utf8"), - "hi bob" - ); - - assert_eq!( - alice_store - .load_session(&bob_address, None) - .await? - .expect("session found") - .session_version()?, - 3 - ); - assert_eq!( - bob_store - .load_session(&alice_address, None) - .await? - .expect("session found") - .session_version()?, - 3 - ); - - assert!( - !is_session_id_equal(&alice_store, &alice_address, &bob_store, &bob_address) - .await? - ); - } - - let alice_response = encrypt(&mut alice_store, &bob_address, "nice to see you").await?; - - assert_eq!( - alice_response.message_type(), - CiphertextMessageType::Whisper - ); - - assert!( - !is_session_id_equal(&alice_store, &alice_address, &bob_store, &bob_address).await? - ); - - let bob_response = encrypt(&mut bob_store, &alice_address, "you as well").await?; - - assert_eq!(bob_response.message_type(), CiphertextMessageType::Whisper); - - let response_plaintext = decrypt( - &mut alice_store, - &bob_address, - &CiphertextMessage::SignalMessage(SignalMessage::try_from(bob_response.serialize())?), - ) - .await?; - assert_eq!( - String::from_utf8(response_plaintext).expect("valid utf8"), - "you as well" - ); - - assert!(is_session_id_equal(&bob_store, &bob_address, &alice_store, &alice_address).await?); - - Ok(()) - } - .now_or_never() - .expect("sync") -} - -#[test] -fn simultaneous_initiate_lost_message_repeated_messages() -> Result<(), SignalProtocolError> { - async { - let mut csprng = OsRng; - - let alice_address = ProtocolAddress::new("+14151111111".to_owned(), 1); - let bob_address = ProtocolAddress::new("+14151111112".to_owned(), 1); - - let mut alice_store = support::test_in_memory_protocol_store()?; - let mut bob_store = support::test_in_memory_protocol_store()?; - - let bob_pre_key_bundle = create_pre_key_bundle(&mut bob_store, &mut csprng).await?; - - process_prekey_bundle( - &bob_address, - &mut alice_store.session_store, - &mut alice_store.identity_store, - &bob_pre_key_bundle, - &mut csprng, - None, - ) - .await?; - let lost_message_for_bob = - encrypt(&mut alice_store, &bob_address, "it was so long ago").await?; - - for _ in 0..15 { - let alice_pre_key_bundle = create_pre_key_bundle(&mut alice_store, &mut csprng).await?; - let bob_pre_key_bundle = create_pre_key_bundle(&mut bob_store, &mut csprng).await?; - - process_prekey_bundle( - &bob_address, - &mut alice_store.session_store, - &mut alice_store.identity_store, - &bob_pre_key_bundle, - &mut csprng, - None, - ) - .await?; - - process_prekey_bundle( - &alice_address, - &mut bob_store.session_store, - &mut bob_store.identity_store, - &alice_pre_key_bundle, - &mut csprng, - None, - ) - .await?; - - let message_for_bob = encrypt(&mut alice_store, &bob_address, "hi bob").await?; - let message_for_alice = encrypt(&mut bob_store, &alice_address, "hi alice").await?; - - assert_eq!( - message_for_bob.message_type(), - CiphertextMessageType::PreKey - ); - assert_eq!( - message_for_alice.message_type(), - CiphertextMessageType::PreKey - ); - - assert!( - !is_session_id_equal(&alice_store, &alice_address, &bob_store, &bob_address) - .await? - ); - - let alice_plaintext = decrypt( - &mut alice_store, - &bob_address, - &CiphertextMessage::PreKeySignalMessage(PreKeySignalMessage::try_from( - message_for_alice.serialize(), - )?), - ) - .await?; - assert_eq!( - String::from_utf8(alice_plaintext).expect("valid utf8"), - "hi alice" - ); - - let bob_plaintext = decrypt( - &mut bob_store, - &alice_address, - &CiphertextMessage::PreKeySignalMessage(PreKeySignalMessage::try_from( - message_for_bob.serialize(), - )?), - ) - .await?; - assert_eq!( - String::from_utf8(bob_plaintext).expect("valid utf8"), - "hi bob" - ); - - assert_eq!( - alice_store - .load_session(&bob_address, None) - .await? - .expect("session found") - .session_version()?, - 3 - ); - assert_eq!( - bob_store - .load_session(&alice_address, None) - .await? - .expect("session found") - .session_version()?, - 3 - ); - - assert!( - !is_session_id_equal(&alice_store, &alice_address, &bob_store, &bob_address) - .await? - ); - } - - for _ in 0..50 { - let message_for_bob = encrypt(&mut alice_store, &bob_address, "hi bob").await?; - let message_for_alice = encrypt(&mut bob_store, &alice_address, "hi alice").await?; - - assert_eq!( - message_for_bob.message_type(), - CiphertextMessageType::Whisper - ); - assert_eq!( - message_for_alice.message_type(), - CiphertextMessageType::Whisper - ); - - assert!( - !is_session_id_equal(&alice_store, &alice_address, &bob_store, &bob_address) - .await? - ); - - let alice_plaintext = decrypt( - &mut alice_store, - &bob_address, - &CiphertextMessage::SignalMessage(SignalMessage::try_from( - message_for_alice.serialize(), - )?), - ) - .await?; - assert_eq!( - String::from_utf8(alice_plaintext).expect("valid utf8"), - "hi alice" - ); - - let bob_plaintext = decrypt( - &mut bob_store, - &alice_address, - &CiphertextMessage::SignalMessage(SignalMessage::try_from( - message_for_bob.serialize(), - )?), - ) - .await?; - assert_eq!( - String::from_utf8(bob_plaintext).expect("valid utf8"), - "hi bob" - ); - - assert_eq!( - alice_store - .load_session(&bob_address, None) - .await? - .expect("session found") - .session_version()?, - 3 - ); - assert_eq!( - bob_store - .load_session(&alice_address, None) - .await? - .expect("session found") - .session_version()?, - 3 - ); - - assert!( - !is_session_id_equal(&alice_store, &alice_address, &bob_store, &bob_address) - .await? - ); - } - - let alice_response = encrypt(&mut alice_store, &bob_address, "nice to see you").await?; - - assert_eq!( - alice_response.message_type(), - CiphertextMessageType::Whisper - ); - - assert!( - !is_session_id_equal(&alice_store, &alice_address, &bob_store, &bob_address).await? - ); - - let bob_response = encrypt(&mut bob_store, &alice_address, "you as well").await?; - - assert_eq!(bob_response.message_type(), CiphertextMessageType::Whisper); - - let response_plaintext = decrypt( - &mut alice_store, - &bob_address, - &CiphertextMessage::SignalMessage(SignalMessage::try_from(bob_response.serialize())?), - ) - .await?; - assert_eq!( - String::from_utf8(response_plaintext).expect("valid utf8"), - "you as well" - ); - - assert!(is_session_id_equal(&bob_store, &bob_address, &alice_store, &alice_address).await?); - - let blast_from_the_past = decrypt( - &mut bob_store, - &alice_address, - &CiphertextMessage::PreKeySignalMessage(PreKeySignalMessage::try_from( - lost_message_for_bob.serialize(), - )?), - ) - .await?; - assert_eq!( - String::from_utf8(blast_from_the_past).expect("valid utf8"), - "it was so long ago" - ); - - assert!( - !is_session_id_equal(&bob_store, &bob_address, &alice_store, &alice_address).await? - ); - - let bob_response = encrypt(&mut bob_store, &alice_address, "so it was").await?; - - assert_eq!(bob_response.message_type(), CiphertextMessageType::Whisper); - - let response_plaintext = decrypt( - &mut alice_store, - &bob_address, - &CiphertextMessage::SignalMessage(SignalMessage::try_from(bob_response.serialize())?), - ) - .await?; - assert_eq!( - String::from_utf8(response_plaintext).expect("valid utf8"), - "so it was" - ); - - assert!(is_session_id_equal(&bob_store, &bob_address, &alice_store, &alice_address).await?); - - Ok(()) - } - .now_or_never() - .expect("sync") -} diff --git a/net/gurk-rs/files/vendor/libsignal-protocol/tests/support/mod.rs b/net/gurk-rs/files/vendor/libsignal-protocol/tests/support/mod.rs deleted file mode 100644 index 89d9d0b..0000000 --- a/net/gurk-rs/files/vendor/libsignal-protocol/tests/support/mod.rs +++ /dev/null @@ -1,142 +0,0 @@ -// -// Copyright 2020 Signal Messenger, LLC. -// SPDX-License-Identifier: AGPL-3.0-only -// - -use libsignal_protocol::*; -use rand::{rngs::OsRng, CryptoRng, Rng}; - -pub fn test_in_memory_protocol_store() -> Result { - let mut csprng = OsRng; - let identity_key = IdentityKeyPair::generate(&mut csprng); - let registration_id = 5; // fixme randomly generate this - - InMemSignalProtocolStore::new(identity_key, registration_id) -} - -#[allow(dead_code)] -pub async fn encrypt( - store: &mut InMemSignalProtocolStore, - remote_address: &ProtocolAddress, - msg: &str, -) -> Result { - message_encrypt( - msg.as_bytes(), - remote_address, - &mut store.session_store, - &mut store.identity_store, - None, - ) - .await -} - -#[allow(dead_code)] -pub async fn decrypt( - store: &mut InMemSignalProtocolStore, - remote_address: &ProtocolAddress, - msg: &CiphertextMessage, -) -> Result, SignalProtocolError> { - let mut csprng = OsRng; - message_decrypt( - msg, - remote_address, - &mut store.session_store, - &mut store.identity_store, - &mut store.pre_key_store, - &mut store.signed_pre_key_store, - &mut csprng, - None, - ) - .await -} - -#[allow(dead_code, clippy::eval_order_dependence)] -pub async fn create_pre_key_bundle( - store: &mut dyn ProtocolStore, - mut csprng: &mut R, -) -> Result { - let pre_key_pair = KeyPair::generate(&mut csprng); - let signed_pre_key_pair = KeyPair::generate(&mut csprng); - - let signed_pre_key_public = signed_pre_key_pair.public_key.serialize(); - let signed_pre_key_signature = store - .get_identity_key_pair(None) - .await? - .private_key() - .calculate_signature(&signed_pre_key_public, &mut csprng)?; - - let device_id: u32 = csprng.gen(); - let pre_key_id: u32 = csprng.gen(); - let signed_pre_key_id: u32 = csprng.gen(); - - let pre_key_bundle = PreKeyBundle::new( - store.get_local_registration_id(None).await?, - device_id, - Some((pre_key_id, pre_key_pair.public_key)), - signed_pre_key_id, - signed_pre_key_pair.public_key, - signed_pre_key_signature.to_vec(), - *store.get_identity_key_pair(None).await?.identity_key(), - )?; - - store - .save_pre_key( - pre_key_id, - &PreKeyRecord::new(pre_key_id, &pre_key_pair), - None, - ) - .await?; - - let timestamp = csprng.gen(); - - store - .save_signed_pre_key( - signed_pre_key_id, - &SignedPreKeyRecord::new( - signed_pre_key_id, - timestamp, - &signed_pre_key_pair, - &signed_pre_key_signature, - ), - None, - ) - .await?; - - Ok(pre_key_bundle) -} - -#[allow(dead_code)] -pub fn initialize_sessions_v3() -> Result<(SessionRecord, SessionRecord), SignalProtocolError> { - let mut csprng = OsRng; - let alice_identity = IdentityKeyPair::generate(&mut csprng); - let bob_identity = IdentityKeyPair::generate(&mut csprng); - - let alice_base_key = KeyPair::generate(&mut csprng); - - let bob_base_key = KeyPair::generate(&mut csprng); - let bob_ephemeral_key = bob_base_key; - - let alice_params = AliceSignalProtocolParameters::new( - alice_identity, - alice_base_key, - *bob_identity.identity_key(), - bob_base_key.public_key, - None, - bob_ephemeral_key.public_key, - ); - - let alice_session = initialize_alice_session_record(&alice_params, &mut csprng)?; - - let bob_params = BobSignalProtocolParameters::new( - bob_identity, - bob_base_key, - None, - bob_ephemeral_key, - *alice_identity.identity_key(), - alice_base_key.public_key, - ); - - let bob_session = initialize_bob_session_record(&bob_params)?; - - Ok((alice_session, bob_session)) -} diff --git a/net/gurk-rs/files/vendor/libsignal-service-hyper/.cargo-checksum.json b/net/gurk-rs/files/vendor/libsignal-service-hyper/.cargo-checksum.json deleted file mode 100644 index 3310ee3..0000000 --- a/net/gurk-rs/files/vendor/libsignal-service-hyper/.cargo-checksum.json +++ /dev/null @@ -1 +0,0 @@ -{"files":{"Cargo.toml":"5feadd3cbe4c14a449d5060aa6d4b043f891a849cd22329f706b5d88ac296ef1","examples/registering.rs":"c29a6e4b95e54c35e976e66ec330e843c7573298b96c9789d6d0e9cc8ac0bfdd","src/lib.rs":"af88f1fc949c629d526ad9a87d93f4d5cd8b171b2a3002ec786842fae83776f6","src/provisioning.rs":"6508541f4a9c85047f62648cd09c4e50bbbb82c38c12482096fb6ab729d172a6","src/push_service.rs":"485631af21f7d95ba06854ce93b8131189cdc600e076c8d7c1655501aca823d5","src/websocket.rs":"5c36db52518398b309457c06b477650a9f1066281af7048615f086787ae7ff9b"},"package":null} \ No newline at end of file diff --git a/net/gurk-rs/files/vendor/libsignal-service-hyper/Cargo.toml b/net/gurk-rs/files/vendor/libsignal-service-hyper/Cargo.toml deleted file mode 100644 index 044c961..0000000 --- a/net/gurk-rs/files/vendor/libsignal-service-hyper/Cargo.toml +++ /dev/null @@ -1,42 +0,0 @@ -[package] -name = "libsignal-service-hyper" -version = "0.1.0" -authors = ["Gabriel Féron "] -edition = "2018" - -[dependencies] -libsignal-service = { path = "../libsignal-service" } - -async-trait = "0.1" -base64 = "0.13" -bytes = "1.0" -futures = "0.3" -log = "0.4" -mpart-async = "0.5" -serde = "1.0" -serde_json = "1.0" -thiserror = "1.0" -url = "2.1" - -hyper = { version = "0.14", features = [ "client", "stream" ] } -hyper-rustls = "0.22" -hyper-timeout = "0.4" -headers = "0.3" - -# for websocket support -async-tungstenite = { version = "0.15", features = [ "tokio-rustls-native-certs" ] } - -tokio = { version = "1.0", features = [ "macros" ] } -tokio-rustls = "0.22" - -[dev-dependencies] -env_logger = "0.9" -image = { version = "0.23", default-features = false, features = [ "png" ] } -opener = "0.5" -qrcode = "0.12" -rand = "0.7" -structopt = "0.3" -tokio = { version = "1.0", features = [ "rt-multi-thread" ]} - -[features] -unsend-futures = ["libsignal-service/unsend-futures"] diff --git a/net/gurk-rs/files/vendor/libsignal-service-hyper/examples/registering.rs b/net/gurk-rs/files/vendor/libsignal-service-hyper/examples/registering.rs deleted file mode 100644 index de498cc..0000000 --- a/net/gurk-rs/files/vendor/libsignal-service-hyper/examples/registering.rs +++ /dev/null @@ -1,138 +0,0 @@ -use std::str::FromStr; - -use libsignal_service::configuration::{ServiceCredentials, SignalServers}; -use libsignal_service::prelude::phonenumber::PhoneNumber; -use libsignal_service::provisioning::{ - generate_registration_id, ConfirmCodeMessage, ConfirmCodeResponse, - ProvisioningManager, VerificationCodeResponse, -}; -use libsignal_service::push_service::{PushService, ServiceError}; -use libsignal_service::USER_AGENT; - -use libsignal_service_hyper::prelude::HyperPushService; - -use rand::RngCore; - -#[tokio::main] -async fn main() { - let phonenumber = let_user_enter_phone_number(); - let password = let_user_enter_password(); - let use_voice = does_user_want_voice_confirmation(); - let captcha = let_user_solve_captcha(); - - let mut push_service = - create_push_service(phonenumber.clone(), password.clone()); - let mut manager = - ProvisioningManager::new(&mut push_service, phonenumber, password); - - println!("Sending registration request..."); - - let registration_result = register_user(&mut manager, captcha, use_voice) - .await - .expect("Sending registration request failed."); - - match registration_result { - VerificationCodeResponse::Issued => { - println!("Registration request was sent"); - }, - VerificationCodeResponse::CaptchaRequired => { - println!("Captcha was wrong or not provided."); - // Here you would go back to entering the Captcha - }, - } - - let confirmation_code = let_user_enter_confirmation_code(); - - println!("Sending confirmation code..."); - - let _registration_data = - confirm_registration(&mut manager, confirmation_code) - .await - .expect("Sending confirmation code failed."); - // You would want to store the registration data - - println!("Registration completed!"); -} - -pub async fn register_user<'a, T: PushService>( - manager: &mut ProvisioningManager<'a, T>, - captcha: String, - use_voice: bool, -) -> Result { - if use_voice { - manager - .request_voice_verification_code(Some(&captcha), None) - .await - } else { - manager - .request_sms_verification_code(Some(&captcha), None) - .await - } -} - -async fn confirm_registration<'a, T: PushService>( - manager: &mut ProvisioningManager<'a, T>, - confirmation_code: u32, -) -> Result { - let registration_id = generate_registration_id(&mut rand::thread_rng()); - let signaling_key = generate_signaling_key(); - - manager - .confirm_verification_code( - confirmation_code, - ConfirmCodeMessage::new_without_unidentified_access( - signaling_key.to_vec(), - registration_id, - ), - ) - .await -} - -fn generate_signaling_key() -> [u8; 52] { - // Signaling key that decrypts the incoming Signal messages - let mut rng = rand::thread_rng(); - let mut signaling_key = [0u8; 52]; - rng.fill_bytes(&mut signaling_key); - signaling_key -} - -fn create_push_service( - phonenumber: PhoneNumber, - password: String, -) -> HyperPushService { - HyperPushService::new( - SignalServers::Staging, // You might want to switch to Production servers - Some(ServiceCredentials { - uuid: None, - phonenumber, - password: Some(password), - signaling_key: None, - device_id: None, - }), - USER_AGENT.into(), - ) -} - -// ------------------------------------ -// Here come the user interaction mocks - -fn let_user_solve_captcha() -> String { - // Here you want to let the user solve a captcha on https://signalcaptchas.org/registration/generate.html - "EnterCaptchaHere".to_string() -} - -fn let_user_enter_confirmation_code() -> u32 { - 12345 -} - -fn does_user_want_voice_confirmation() -> bool { - false -} - -fn let_user_enter_phone_number() -> PhoneNumber { - PhoneNumber::from_str("+49301234567").expect("Not a valid phone number") -} - -fn let_user_enter_password() -> String { - "EnterPasswordHere".to_string() -} diff --git a/net/gurk-rs/files/vendor/libsignal-service-hyper/src/lib.rs b/net/gurk-rs/files/vendor/libsignal-service-hyper/src/lib.rs deleted file mode 100644 index d91a8aa..0000000 --- a/net/gurk-rs/files/vendor/libsignal-service-hyper/src/lib.rs +++ /dev/null @@ -1,8 +0,0 @@ -#![recursion_limit = "256"] - -pub mod push_service; -pub mod websocket; - -pub mod prelude { - pub use crate::push_service::*; -} diff --git a/net/gurk-rs/files/vendor/libsignal-service-hyper/src/provisioning.rs b/net/gurk-rs/files/vendor/libsignal-service-hyper/src/provisioning.rs deleted file mode 100644 index 97b9cb5..0000000 --- a/net/gurk-rs/files/vendor/libsignal-service-hyper/src/provisioning.rs +++ /dev/null @@ -1,150 +0,0 @@ -use futures::{channel::mpsc::Sender, pin_mut, SinkExt, StreamExt}; -use url::Url; - -use crate::push_service::AwcPushService; -use libsignal_protocol::{ - generate_registration_id, - keys::{PrivateKey, PublicKey}, - Context, -}; -use libsignal_service::{ - configuration::ServiceConfiguration, - messagepipe::Credentials, - prelude::PushService, - provisioning::{ProvisioningError, ProvisioningPipe, ProvisioningStep}, - push_service::{ConfirmDeviceMessage, DeviceId}, - USER_AGENT, -}; - -#[derive(Debug)] -pub enum SecondaryDeviceProvisioning { - Url(Url), - NewDeviceRegistration { - phone_number: String, - device_id: DeviceId, - registration_id: u32, - uuid: String, - private_key: PrivateKey, - public_key: PublicKey, - profile_key: Vec, - }, -} - -pub async fn provision_secondary_device( - ctx: &Context, - service_configuration: &ServiceConfiguration, - signaling_key: &[u8; 52], - password: &str, - device_name: &str, - mut tx: Sender, -) -> Result<(), ProvisioningError> { - assert_eq!( - password.len(), - 24, - "the password needs to be a 24 characters ASCII string" - ); - - let mut push_service = - AwcPushService::new(service_configuration.clone(), None, USER_AGENT); - - let (ws, stream) = - push_service.ws("/v1/websocket/provisioning/", None).await?; - - let registration_id = generate_registration_id(&ctx, 0)?; - - let provisioning_pipe = ProvisioningPipe::from_socket(ws, stream, &ctx)?; - let provision_stream = provisioning_pipe.stream(); - pin_mut!(provision_stream); - while let Some(step) = provision_stream.next().await { - match step { - Ok(ProvisioningStep::Url(url)) => { - tx.send(SecondaryDeviceProvisioning::Url(url)) - .await - .expect("failed to send provisioning Url in channel"); - } - Ok(ProvisioningStep::Message(message)) => { - let uuid = - message.uuid.ok_or(ProvisioningError::InvalidData { - reason: "missing client UUID".into(), - })?; - - let public_key = PublicKey::decode_point( - &ctx, - &message.identity_key_public.ok_or( - ProvisioningError::InvalidData { - reason: "missing public key".into(), - }, - )?, - )?; - - let private_key = PrivateKey::decode_point( - &ctx, - &message.identity_key_private.ok_or( - ProvisioningError::InvalidData { - reason: "missing public key".into(), - }, - )?, - )?; - - let profile_key = message.profile_key.ok_or( - ProvisioningError::InvalidData { - reason: "missing profile key".into(), - }, - )?; - - let phone_number = - message.number.ok_or(ProvisioningError::InvalidData { - reason: "missing phone number".into(), - })?; - - // we need to authenticate with the phone number - // to confirm the new device - let mut push_service = AwcPushService::new( - service_configuration.clone(), - Some(Credentials { - e164: phone_number.clone(), - uuid: None, - password: Some(password.to_string()), - signaling_key: Some(*signaling_key), - }), - USER_AGENT, - ); - - let device_id = push_service - .confirm_device( - message - .provisioning_code - .ok_or(ProvisioningError::InvalidData { - reason: "no provisioning confirmation code" - .into(), - })? - .parse() - .unwrap(), - ConfirmDeviceMessage { - signaling_key: signaling_key.to_vec(), - supports_sms: false, - fetches_messages: true, - registration_id, - name: device_name.to_string(), - }, - ) - .await?; - - tx.send(SecondaryDeviceProvisioning::NewDeviceRegistration { - phone_number, - device_id, - registration_id, - uuid, - private_key, - public_key, - profile_key, - }) - .await - .expect("failed to send provisioning message in rx channel"); - } - Err(e) => return Err(e.into()), - } - } - - Ok(()) -} diff --git a/net/gurk-rs/files/vendor/libsignal-service-hyper/src/push_service.rs b/net/gurk-rs/files/vendor/libsignal-service-hyper/src/push_service.rs deleted file mode 100644 index 7bdb12b..0000000 --- a/net/gurk-rs/files/vendor/libsignal-service-hyper/src/push_service.rs +++ /dev/null @@ -1,493 +0,0 @@ -use std::{io::Read, time::Duration}; - -use bytes::{Buf, Bytes}; -use futures::{FutureExt, StreamExt, TryStreamExt}; -use headers::{Authorization, HeaderMapExt}; -use hyper::{ - client::HttpConnector, - header::{CONTENT_LENGTH, CONTENT_TYPE, USER_AGENT}, - Body, Client, Method, Request, Response, StatusCode, -}; -use hyper_rustls::HttpsConnector; -use hyper_timeout::TimeoutConnector; -use libsignal_service::{ - configuration::*, messagepipe::WebSocketService, prelude::ProtobufMessage, - push_service::*, MaybeSend, -}; -use serde::{Deserialize, Serialize}; -use tokio_rustls::rustls; - -use crate::websocket::TungsteniteWebSocket; - -#[derive(Clone)] -pub struct HyperPushService { - cfg: ServiceConfiguration, - user_agent: String, - credentials: Option, - client: Client>>, -} - -#[derive(Debug)] -struct RequestBody { - contents: Vec, - content_type: String, -} - -impl HyperPushService { - pub fn new( - cfg: impl Into, - credentials: Option, - user_agent: String, - ) -> Self { - let cfg = cfg.into(); - let tls_config = Self::tls_config(&cfg); - - let mut http = HttpConnector::new(); - http.enforce_http(false); - let https = HttpsConnector::from((http, tls_config)); - - // as in Signal-Android - let mut timeout_connector = TimeoutConnector::new(https); - timeout_connector.set_connect_timeout(Some(Duration::from_secs(10))); - timeout_connector.set_read_timeout(Some(Duration::from_secs(65))); - timeout_connector.set_write_timeout(Some(Duration::from_secs(65))); - - let client: Client<_, hyper::Body> = - Client::builder().build(timeout_connector); - - Self { - cfg, - credentials: credentials.and_then(|c| c.authorization()), - client, - user_agent, - } - } - - fn tls_config(cfg: &ServiceConfiguration) -> rustls::ClientConfig { - // This will fail to compile against rustls 0.20, see service-actix push_service get_client - let mut tls_config = rustls::ClientConfig::new(); - tls_config.alpn_protocols = vec![b"http/1.1".to_vec()]; - tls_config - .root_store - .add_pem_file(&mut std::io::Cursor::new( - cfg.certificate_authority.clone(), - )) - .expect("invalid TLS certificate authority"); - tls_config - } - - async fn request( - &self, - method: Method, - endpoint: Endpoint, - path: impl AsRef, - credentials_override: HttpAuthOverride, - body: Option, - ) -> Result, ServiceError> { - let url = self.cfg.base_url(endpoint).join(path.as_ref())?; - log::debug!("HTTP request {} {}", method, url); - let mut builder = Request::builder() - .method(method) - .uri(url.as_str()) - .header(USER_AGENT, &self.user_agent); - - match credentials_override { - HttpAuthOverride::NoOverride => { - if let Some(HttpAuth { username, password }) = - self.credentials.as_ref() - { - builder - .headers_mut() - .unwrap() - .typed_insert(Authorization::basic(username, password)); - } - }, - HttpAuthOverride::Identified(HttpAuth { username, password }) => { - builder - .headers_mut() - .unwrap() - .typed_insert(Authorization::basic(&username, &password)); - }, - HttpAuthOverride::Unidentified => (), - }; - - let request = if let Some(RequestBody { - contents, - content_type, - }) = body - { - builder - .header(CONTENT_LENGTH, contents.len() as u64) - .header(CONTENT_TYPE, content_type) - .body(Body::from(contents)) - .unwrap() - } else { - builder.body(Body::empty()).unwrap() - }; - - let mut response = self.client.request(request).await.map_err(|e| { - ServiceError::SendError { - reason: e.to_string(), - } - })?; - - match response.status() { - StatusCode::OK => Ok(response), - StatusCode::NO_CONTENT => Ok(response), - StatusCode::UNAUTHORIZED | StatusCode::FORBIDDEN => { - Err(ServiceError::Unauthorized) - }, - StatusCode::PAYLOAD_TOO_LARGE => { - // This is 413 and means rate limit exceeded for Signal. - Err(ServiceError::RateLimitExceeded) - }, - StatusCode::CONFLICT => { - let mismatched_devices = - Self::json(&mut response).await.map_err(|e| { - log::error!( - "Failed to decode HTTP 409 response: {}", - e - ); - ServiceError::UnhandledResponseCode { - http_code: StatusCode::CONFLICT.as_u16(), - } - })?; - Err(ServiceError::MismatchedDevicesException( - mismatched_devices, - )) - }, - StatusCode::GONE => { - let stale_devices = - Self::json(&mut response).await.map_err(|e| { - log::error!( - "Failed to decode HTTP 410 response: {}", - e - ); - ServiceError::UnhandledResponseCode { - http_code: StatusCode::GONE.as_u16(), - } - })?; - Err(ServiceError::StaleDevices(stale_devices)) - }, - // XXX: fill in rest from PushServiceSocket - code => { - log::trace!( - "Unhandled response with body: {}", - Self::text(&mut response).await? - ); - Err(ServiceError::UnhandledResponseCode { - http_code: code.as_u16(), - }) - }, - } - } - - async fn json(response: &mut Response) -> Result - where - for<'de> T: Deserialize<'de>, - { - let body = hyper::body::aggregate(response).await.map_err(|e| { - ServiceError::ResponseError { - reason: format!( - "failed to aggregate HTTP response body: {}", - e - ), - } - })?; - - serde_json::from_reader(body.reader()).map_err(|e| { - ServiceError::JsonDecodeError { - reason: e.to_string(), - } - }) - } - - async fn protobuf( - response: &mut Response, - ) -> Result - where - M: ProtobufMessage + Default, - { - let body = hyper::body::aggregate(response).await.map_err(|e| { - ServiceError::ResponseError { - reason: format!( - "failed to aggregate HTTP response body: {}", - e - ), - } - })?; - - M::decode(body).map_err(ServiceError::ProtobufDecodeError) - } - - async fn text( - response: &mut Response, - ) -> Result { - let body = hyper::body::aggregate(response).await.map_err(|e| { - ServiceError::ResponseError { - reason: format!( - "failed to aggregate HTTP response body: {}", - e - ), - } - })?; - let mut text = String::new(); - body.reader().read_to_string(&mut text).map_err(|e| { - ServiceError::ResponseError { - reason: format!("failed to read HTTP response body: {}", e), - } - })?; - Ok(text) - } -} - -#[cfg_attr(feature = "unsend-futures", async_trait::async_trait(?Send))] -#[cfg_attr(not(feature = "unsend-futures"), async_trait::async_trait)] -impl PushService for HyperPushService { - // This is in principle known at compile time, but long to write out. - type ByteStream = Box; - type WebSocket = TungsteniteWebSocket; - - async fn get_json( - &mut self, - service: Endpoint, - path: &str, - credentials_override: HttpAuthOverride, - ) -> Result - where - for<'de> T: Deserialize<'de>, - { - let mut response = self - .request(Method::GET, service, path, credentials_override, None) - .await?; - - Self::json(&mut response).await - } - - async fn delete_json( - &mut self, - service: Endpoint, - path: &str, - ) -> Result - where - for<'de> T: Deserialize<'de>, - { - let mut response = self - .request( - Method::DELETE, - service, - path, - HttpAuthOverride::NoOverride, - None, - ) - .await?; - - Self::json(&mut response).await - } - - async fn put_json( - &mut self, - service: Endpoint, - path: &str, - credentials_override: HttpAuthOverride, - value: S, - ) -> Result - where - for<'de> D: Deserialize<'de>, - S: MaybeSend + Serialize, - { - let json = serde_json::to_vec(&value).map_err(|e| { - ServiceError::JsonDecodeError { - reason: e.to_string(), - } - })?; - - let mut response = self - .request( - Method::PUT, - service, - path, - credentials_override, - Some(RequestBody { - contents: json, - content_type: "application/json".into(), - }), - ) - .await?; - - Self::json(&mut response).await - } - - async fn get_protobuf( - &mut self, - service: Endpoint, - path: &str, - credentials_override: HttpAuthOverride, - ) -> Result - where - T: Default + libsignal_service::prelude::ProtobufMessage, - { - let mut response = self - .request(Method::GET, service, path, credentials_override, None) - .await?; - - Self::protobuf(&mut response).await - } - - async fn put_protobuf( - &mut self, - service: Endpoint, - path: &str, - value: S, - ) -> Result - where - D: Default + libsignal_service::prelude::ProtobufMessage, - S: Sized + libsignal_service::prelude::ProtobufMessage, - { - let protobuf = value.encode_to_vec(); - - let mut response = self - .request( - Method::PUT, - service, - path, - HttpAuthOverride::NoOverride, - Some(RequestBody { - contents: protobuf, - content_type: "application/x-protobuf".into(), - }), - ) - .await?; - - Self::protobuf(&mut response).await - } - - async fn get_from_cdn( - &mut self, - cdn_id: u32, - path: &str, - ) -> Result { - let response = self - .request( - Method::GET, - Endpoint::Cdn(cdn_id), - path, - HttpAuthOverride::Unidentified, // CDN requests are always without authentication - None, - ) - .await?; - - Ok(Box::new( - response - .into_body() - .map_err(|e| std::io::Error::new(std::io::ErrorKind::Other, e)) - .into_async_read(), - )) - } - - async fn post_to_cdn0<'s, C: std::io::Read + Send + 's>( - &mut self, - path: &str, - value: &[(&str, &str)], - file: Option<(&str, &'s mut C)>, - ) -> Result<(), ServiceError> { - let mut form = mpart_async::client::MultipartRequest::default(); - - // mpart-async has a peculiar ordering of the form items, - // and Amazon S3 expects them in a very specific order (i.e., the file contents should - // go last. - // - // mpart-async uses a VecDeque internally for ordering the fields in the order given. - // - // https://github.com/cetra3/mpart-async/issues/16 - - for &(k, v) in value { - form.add_field(k, v); - } - - if let Some((filename, file)) = file { - // XXX Actix doesn't cope with none-'static lifetimes - // https://docs.rs/actix-web/3.2.0/actix_web/body/enum.Body.html - let mut buf = Vec::new(); - file.read_to_end(&mut buf) - .expect("infallible Read instance"); - form.add_stream( - "file", - filename, - "application/octet-stream", - futures::future::ok::<_, ()>(Bytes::from(buf)).into_stream(), - ); - } - - let content_type = - format!("multipart/form-data; boundary={}", form.get_boundary()); - - // XXX Amazon S3 needs the Content-Length, but we don't know it without depleting the whole - // stream. Sadly, Content-Length != contents.len(), but should include the whole form. - let mut body_contents = vec![]; - while let Some(b) = form.next().await { - // Unwrap, because no error type was used above - body_contents.extend(b.unwrap()); - } - log::trace!( - "Sending PUT with Content-Type={} and length {}", - content_type, - body_contents.len() - ); - - let response = self - .request( - Method::POST, - Endpoint::Cdn(0), - path, - HttpAuthOverride::NoOverride, - Some(RequestBody { - contents: body_contents, - content_type, - }), - ) - .await?; - - log::debug!("AwcPushService::PUT response: {:?}", response); - - Ok(()) - } - - async fn ws( - &mut self, - path: &str, - credentials: Option, - ) -> Result< - ( - Self::WebSocket, - ::Stream, - ), - ServiceError, - > { - Ok(TungsteniteWebSocket::with_tls_config( - Self::tls_config(&self.cfg), - self.cfg.base_url(Endpoint::Service), - path, - credentials.as_ref(), - ) - .await?) - } -} - -#[cfg(test)] -mod tests { - use libsignal_service::configuration::SignalServers; - - #[test] - fn create_clients() { - let configs = &[SignalServers::Staging, SignalServers::Production]; - - for cfg in configs { - let _ = super::HyperPushService::new( - cfg, - None, - "libsignal-service test".to_string(), - ); - } - } -} diff --git a/net/gurk-rs/files/vendor/libsignal-service-hyper/src/websocket.rs b/net/gurk-rs/files/vendor/libsignal-service-hyper/src/websocket.rs deleted file mode 100644 index f72d27a..0000000 --- a/net/gurk-rs/files/vendor/libsignal-service-hyper/src/websocket.rs +++ /dev/null @@ -1,221 +0,0 @@ -use std::sync::Arc; - -use async_tungstenite::{ - tokio::connect_async_with_tls_connector, - tungstenite::{Error as TungsteniteError, Message}, -}; -use bytes::Bytes; -use futures::{channel::mpsc::*, prelude::*}; -use hyper::StatusCode; -use tokio::time::Instant; -use tokio_rustls::rustls; -use url::Url; - -use libsignal_service::{ - configuration::ServiceCredentials, - messagepipe::*, - push_service::{self, ServiceError}, - MaybeSend, -}; - -// This weird one-time trait is required because MaybeSend, unlike Send, is not -// an auto trait. Only auto traits can be used as additional traits in a trait object. -trait MaybeSendSink: Sink + MaybeSend {} -impl MaybeSendSink for T where - T: Sink + MaybeSend -{ -} - -pub struct TungsteniteWebSocket { - socket_sink: Box, -} - -#[derive(thiserror::Error, Debug)] -pub enum TungsteniteWebSocketError { - #[error("error while connecting to websocket: {0}")] - ConnectionError(#[from] TungsteniteError), -} - -impl From for ServiceError { - fn from(e: TungsteniteWebSocketError) -> Self { - match e { - TungsteniteWebSocketError::ConnectionError( - TungsteniteError::Http(response), - ) => match response.status() { - StatusCode::FORBIDDEN => ServiceError::Unauthorized, - s => ServiceError::WsError { - reason: format!("HTTP status {}", s), - }, - }, - e => ServiceError::WsError { - reason: e.to_string(), - }, - } - } -} - -// impl From for ServiceError { -// fn from(e: AwcWebSocketError) -> ServiceError { -// match e { -// AwcWebSocketError::ConnectionError(e) => match e { -// WsClientError::InvalidResponseStatus(s) => match s { -// StatusCode::FORBIDDEN => ServiceError::Unauthorized, -// s => ServiceError::WsError { -// reason: format!("HTTP status {}", s), -// }, -// }, -// e => ServiceError::WsError { -// reason: e.to_string(), -// }, -// }, -// } -// } -// } - -// impl From for AwcWebSocketError { -// fn from(e: WsProtocolError) -> AwcWebSocketError { -// todo!("error conversion {:?}", e) -// // return Some(Err(ServiceError::WsError { -// // reason: e.to_string(), -// // })); -// } -// } - -// Process the WebSocket, until it times out. -async fn process( - socket_stream: S, - mut incoming_sink: Sender, -) -> Result<(), TungsteniteWebSocketError> -where - S: Unpin, - S: Stream>, -{ - let mut socket_stream = socket_stream.fuse(); - - let mut ka_interval = tokio::time::interval_at( - Instant::now(), - push_service::KEEPALIVE_TIMEOUT_SECONDS, - ); - - loop { - tokio::select! { - _ = ka_interval.tick() => { - log::trace!("Triggering keep-alive"); - if let Err(e) = incoming_sink.send(WebSocketStreamItem::KeepAliveRequest).await { - log::info!("Websocket sink has closed: {:?}.", e); - break; - }; - }, - frame = socket_stream.next() => { - let frame = if let Some(frame) = frame { - frame - } else { - log::info!("process: Socket stream ended"); - break; - }; - - let frame = match frame? { - Message::Binary(s) => s, - Message::Ping(msg) => { - log::warn!("Received Ping({:?})", msg); - - continue; - }, - Message::Pong(msg) => { - log::trace!("Received Pong({:?})", msg); - - continue; - }, - Message::Text(frame) => { - log::warn!("Message::Text {:?}", frame); - - // this is a protocol violation, maybe break; is better? - continue; - }, - - Message::Close(c) => { - log::warn!("Websocket closing: {:?}", c); - - break; - }, - }; - - // Match SendError - if let Err(e) = incoming_sink.send(WebSocketStreamItem::Message(Bytes::from(frame))).await { - log::info!("Websocket sink has closed: {:?}.", e); - break; - } - }, - } - } - Ok(()) -} - -impl TungsteniteWebSocket { - pub(crate) async fn with_tls_config( - tls_config: rustls::ClientConfig, - base_url: impl std::borrow::Borrow, - path: &str, - credentials: Option<&ServiceCredentials>, - ) -> Result< - (Self, ::Stream), - TungsteniteWebSocketError, - > { - let mut url = base_url.borrow().join(path).expect("valid url"); - url.set_scheme("wss").expect("valid https base url"); - - let tls_connector = - tokio_rustls::TlsConnector::from(Arc::new(tls_config)); - - if let Some(credentials) = credentials { - url.query_pairs_mut() - .append_pair("login", &credentials.login()) - .append_pair( - "password", - credentials.password.as_ref().expect("a password"), - ); - } - - log::trace!("Will start websocket at {:?}", url); - - let (socket_stream, response) = - connect_async_with_tls_connector(url, Some(tls_connector)).await?; - - log::debug!("WebSocket connected: {:?}", response); - - let (incoming_sink, incoming_stream) = channel(5); - - let (socket_sink, socket_stream) = socket_stream.split(); - let processing_task = process(socket_stream, incoming_sink); - - // When the processing_task stops, the consuming stream and sink also - // terminate. - tokio::spawn(processing_task.map(|v| match v { - Ok(()) => (), - Err(e) => { - log::warn!("Processing task terminated with error: {:?}", e) - }, - })); - - Ok(( - Self { - socket_sink: Box::new(socket_sink), - }, - incoming_stream, - )) - } -} - -#[cfg_attr(feature = "unsend-futures", async_trait::async_trait(?Send))] -#[cfg_attr(not(feature = "unsend-futures"), async_trait::async_trait)] -impl WebSocketService for TungsteniteWebSocket { - type Stream = Receiver; - - async fn send_message(&mut self, msg: Bytes) -> Result<(), ServiceError> { - self.socket_sink - .send(Message::Binary(msg.to_vec())) - .await - .map_err(TungsteniteWebSocketError::from)?; - Ok(()) - } -} diff --git a/net/gurk-rs/files/vendor/libsignal-service/.cargo-checksum.json b/net/gurk-rs/files/vendor/libsignal-service/.cargo-checksum.json deleted file mode 100644 index 23f6e06..0000000 --- a/net/gurk-rs/files/vendor/libsignal-service/.cargo-checksum.json +++ /dev/null @@ -1 +0,0 @@ -{"files":{"Cargo.toml":"7990658c5f339ecae207340ad4e77e4b1adb3dbd5d5944d557383542fbbe4119","build.rs":"c9720a17e019fb61aa66aee6bb2d10785ddc4f4773989d6be12f6b08964b449c","protobuf/DecryptedGroups.proto":"6441ebc3ce3e4ececbd312efcf1784ebd167b39677c21ad08fc33b3199ce53fe","protobuf/Groups.proto":"45f93f817634d0baa10f3228a7a07e234be2e85eb006ca0f2e639ec5118fc3d7","protobuf/Provisioning.proto":"632588c1e71774292a58029e38f2c482daa57621908efe902093d7214756a351","protobuf/SignalService.proto":"f30e9b57990b11bbd5b6efdbb4d0e2ce41c6eb60a915ac02d8ed43eeaefe625e","protobuf/StickerResources.proto":"f1f9b5d815eb703129986e95175cf3a61d5b37c8de9154af646081fa5774ad1d","protobuf/UnidentifiedDelivery.proto":"246c66792a5d68b8d10f13f5e6c30901ca7f2e766d9e2f3fdde37f5df75f0f5d","protobuf/WebSocketResources.proto":"881b0e22f5a66642975b4d41dc401c6a4d63816e23c8c45c9eec168c21fe2ab8","src/account_manager.rs":"5eacdfbeac7cb52dd32eeaf26a4eb4396bf4fdba4b40a2a95c19b6889d854fd3","src/attachment_cipher.rs":"dcc323bcdbee10fd6c9fc7d3cee6bcc7e13690625d2e2495f1656008ea6fe1dd","src/cipher.rs":"5f2b92e97cb8eb96a0b4e66494d52ea2db2eb63fbb8e36f990bca65f54285062","src/configuration.rs":"05478f7fef7becd63e3d9a4d1f8b58ec5785a0c962cfd2fcf3b2d68ef21e3cc2","src/content.rs":"651ebd040f3d93ed845e5c2d7e788e85e62880fc6c7964424cb435af5dea7d27","src/digeststream.rs":"1c7b943342f30e1fc5b3fb377cd49e0252e4abc2cef7b462968a311db1a3cbb0","src/envelope.rs":"df47eb9dc9e3ea6c2e6e74f0f7b6d11f2f8883fbffcc1aa5f8050e468fc5ec13","src/groups_v2/manager.rs":"bc3fd73d0498a6e3ca8d4b538386df6a3966c9a27ab216f294b5b97f1e936b6f","src/groups_v2/mod.rs":"0979622b08a6cd35edd67a54b4c133ec11f36b6b174429c9dc8d4f5e8336335d","src/groups_v2/operations.rs":"4cc3c587c4b107a5e647e38f6033672851275126780d2401cd5d92271594eed5","src/groups_v2/utils.rs":"5a3dba2c3b8d2db9ce59fff6fd08b031570b3ef3fedcd92dcfd8782e2c124145","src/kat.bin.rs":"57ae2884824a4c20406bbf04572e02321431b21e33341448a863ac6ef90b61d9","src/lib.rs":"44defcec01445f462a45206889fa042c87148d6944bd9acbc29cff335d095eef","src/messagepipe.rs":"af2d316b15f8b6401ed75ad6962a31dcf3ef508d80833f7ba05a775b9b037c19","src/models.rs":"0f52fe9ee01706e7fea6cb21c150e049f8fd6802d64cecd751795c9d7d22fc03","src/pre_keys.rs":"882b56b873f0cbb47d765a6c7b09fff187aa451abc72787f7443bf4316bea5bc","src/profile_cipher.rs":"51d089128457df028b3f8860da4951429dc381450f9a6a742b3a88eab317e581","src/profile_name.rs":"3b3672e98b07644975fc34afe173e235c0fb595261a82da0c51efeb8c553bbd0","src/proto.rs":"e5c977af587b11226d5803678392b89602a424e24365f1855770a0907a10157a","src/provisioning/cipher.rs":"5dfc259426b247d2eec112326873fdf82c4a52f70e35bdc5594d96501b55cfb5","src/provisioning/manager.rs":"6450ac900cb187efe1335c7556e9dfafa8955e56d8208d0fa6abf58a38ab563b","src/provisioning/mod.rs":"4c89449c578e7f9d64fb877a9357e6837ad592ff2c4b99e2be3c5ec099bb23a6","src/provisioning/pipe.rs":"5f68e9d489468b01348f98a490617436c5e0706d9a74ee0af1e8d9a5a8904cc4","src/push_service.rs":"761bc4e1811b99cd166fe3d793f57dbde97850dd2abc7d26180f5ffb3c3a339f","src/receiver.rs":"513984f0fcf3ca1eb2fe1f5ac4edc325a0a665a26a1919df5b8365da8b77ab8b","src/sealed_session_cipher.rs":"4f9628cef6d10f33faf3a0d20a17ef9e6400f224a244ff5f6f0b9c318d661ca5","src/sender.rs":"6281dd9d81e46785a372b18c3265c05d68d298c6003d408a03f6ce75e51cfc4d","src/service_address.rs":"c39952513f50d869dc4cbc3541261e185e1524419760aab2688da5bbd62fd1c9","src/session_store.rs":"d6ff85eae98ed25ae36fa7d4e1ef3521cfbf952b273737bcdc492b8c72ea8a63","src/utils.rs":"d15bc4fd4e77a86963396b3d3e2f6b92cde5b35e3024f0a53b9487fe0f094afd"},"package":null} \ No newline at end of file diff --git a/net/gurk-rs/files/vendor/libsignal-service/Cargo.toml b/net/gurk-rs/files/vendor/libsignal-service/Cargo.toml deleted file mode 100644 index c8f7451..0000000 --- a/net/gurk-rs/files/vendor/libsignal-service/Cargo.toml +++ /dev/null @@ -1,49 +0,0 @@ -[package] -name = "libsignal-service" -version = "0.1.0" -authors = ["Michael Bryan ", "Shady Khalifa "] -edition = "2018" -license = "GPLv3" -readme = "../README.md" - -[dependencies] -libsignal-protocol = { git = "https://github.com/signalapp/libsignal-client", tag="v0.11.0" } -zkgroup = { git = "https://github.com/signalapp/zkgroup", tag = "v0.7.3" } -async-trait = "0.1" -url = { version = "2.1", features = ["serde"] } -base64 = "0.13" -bytes = "1" -futures = "0.3" -pin-project = "1.0" -thiserror = "1.0" -serde = {version = "1.0", features=["derive"]} -prost = "0.9" -http = "0.2" -chrono = { version = "0.4", features = ["serde"] } -log = "0.4" -bincode = "1.3" - -sha2 = "0.9" -hmac = "0.11" -hex = "0.4" -aes = { version = "0.7", features = ["ctr"] } -aes-gcm = "0.9" -block-modes = "0.8" -rand = "0.7" - -uuid = { version = "0.8", features = [ "serde" ] } -phonenumber = "0.3" -hkdf = "0.11" - -[build-dependencies] -prost-build = "0.9" - -[dev-dependencies] -anyhow = "1.0" -tokio = { version = "1.0", features = [ "rt", "macros" ] } - -rustls = "0.20" - -[features] -prefer-e164 = [] -unsend-futures = [] diff --git a/net/gurk-rs/files/vendor/libsignal-service/build.rs b/net/gurk-rs/files/vendor/libsignal-service/build.rs deleted file mode 100644 index a72b723..0000000 --- a/net/gurk-rs/files/vendor/libsignal-service/build.rs +++ /dev/null @@ -1,32 +0,0 @@ -use std::path::Path; - -fn main() { - let protobuf = Path::new("protobuf").to_owned(); - - // Build script does not automagically rerun when a new protobuf file is added. - // Directories are checked against mtime, which is platform specific - println!("cargo:rerun-if-changed=protobuf"); - // Adding src/proto.rs means an extra `include!` will trigger a rerun. This is on best-effort - // basis. - println!("cargo:rerun-if-changed=src/proto.rs"); - - let input: Vec<_> = protobuf - .read_dir() - .expect("protobuf directory") - .filter_map(|entry| { - let entry = entry.expect("readable protobuf directory"); - let path = entry.path(); - if Some("proto") - == path.extension().and_then(std::ffi::OsStr::to_str) - { - assert!(path.is_file()); - println!("cargo:rerun-if-changed={}", path.to_str().unwrap()); - Some(path) - } else { - None - } - }) - .collect(); - - prost_build::compile_protos(&input, &[protobuf]).unwrap(); -} diff --git a/net/gurk-rs/files/vendor/libsignal-service/protobuf/DecryptedGroups.proto b/net/gurk-rs/files/vendor/libsignal-service/protobuf/DecryptedGroups.proto deleted file mode 100644 index 3aa9f4b..0000000 --- a/net/gurk-rs/files/vendor/libsignal-service/protobuf/DecryptedGroups.proto +++ /dev/null @@ -1,109 +0,0 @@ -/** - * Copyright (C) 2019 Open Whisper Systems - * - * Licensed according to the LICENSE file in this repository. - */ -syntax = "proto3"; - -package signalservice; - -option java_package = "org.signal.storageservice.protos.groups.local"; -option java_multiple_files = true; - -import "Groups.proto"; - -// Decrypted version of Member -// Keep field numbers in step -message DecryptedMember { - bytes uuid = 1; - Member.Role role = 2; - bytes profileKey = 3; - uint32 joinedAtRevision = 5; -} - -message DecryptedPendingMember { - bytes uuid = 1; - Member.Role role = 2; - bytes addedByUuid = 3; - uint64 timestamp = 4; - bytes uuidCipherText = 5; -} - -message DecryptedRequestingMember { - bytes uuid = 1; - bytes profileKey = 2; - uint64 timestamp = 4; -} - -message DecryptedPendingMemberRemoval { - bytes uuid = 1; - bytes uuidCipherText = 2; -} - -message DecryptedApproveMember { - bytes uuid = 1; - Member.Role role = 2; -} - -message DecryptedModifyMemberRole { - bytes uuid = 1; - Member.Role role = 2; -} - -// Decrypted version of message Group -// Keep field numbers in step -message DecryptedGroup { - string title = 2; - string avatar = 3; - DecryptedTimer disappearingMessagesTimer = 4; - AccessControl accessControl = 5; - uint32 revision = 6; - repeated DecryptedMember members = 7; - repeated DecryptedPendingMember pendingMembers = 8; - repeated DecryptedRequestingMember requestingMembers = 9; - bytes inviteLinkPassword = 10; - string description = 11; -} - -// Decrypted version of message GroupChange.Actions -// Keep field numbers in step -message DecryptedGroupChange { - bytes editor = 1; - uint32 revision = 2; - repeated DecryptedMember newMembers = 3; - repeated bytes deleteMembers = 4; - repeated DecryptedModifyMemberRole modifyMemberRoles = 5; - repeated DecryptedMember modifiedProfileKeys = 6; - repeated DecryptedPendingMember newPendingMembers = 7; - repeated DecryptedPendingMemberRemoval deletePendingMembers = 8; - repeated DecryptedMember promotePendingMembers = 9; - DecryptedString newTitle = 10; - DecryptedString newAvatar = 11; - DecryptedTimer newTimer = 12; - AccessControl.AccessRequired newAttributeAccess = 13; - AccessControl.AccessRequired newMemberAccess = 14; - AccessControl.AccessRequired newInviteLinkAccess = 15; - repeated DecryptedRequestingMember newRequestingMembers = 16; - repeated bytes deleteRequestingMembers = 17; - repeated DecryptedApproveMember promoteRequestingMembers = 18; - bytes newInviteLinkPassword = 19; - DecryptedString newDescription = 20; -} - -message DecryptedString { - string value = 1; -} - -message DecryptedTimer { - uint32 duration = 1; -} - -message DecryptedGroupJoinInfo { - string title = 2; - string avatar = 3; - uint32 memberCount = 4; - AccessControl.AccessRequired addFromInviteLink = 5; - uint32 revision = 6; - bool pendingAdminApproval = 7; - string description = 8; -} diff --git a/net/gurk-rs/files/vendor/libsignal-service/protobuf/Groups.proto b/net/gurk-rs/files/vendor/libsignal-service/protobuf/Groups.proto deleted file mode 100644 index 0ba85a9..0000000 --- a/net/gurk-rs/files/vendor/libsignal-service/protobuf/Groups.proto +++ /dev/null @@ -1,226 +0,0 @@ -/** - * Copyright (C) 2019 Open Whisper Systems - * - * Licensed according to the LICENSE file in this repository. - */ -syntax = "proto3"; - -package signalservice; - -option java_package = "org.signal.storageservice.protos.groups"; -option java_multiple_files = true; - -message AvatarUploadAttributes { - string key = 1; - string credential = 2; - string acl = 3; - string algorithm = 4; - string date = 5; - string policy = 6; - string signature = 7; -} - -message Member { - enum Role { - UNKNOWN = 0; - DEFAULT = 1; - ADMINISTRATOR = 2; - } - - bytes userId = 1; - Role role = 2; - bytes profileKey = 3; - bytes presentation = 4; - uint32 joinedAtRevision = 5; -} - -message PendingMember { - Member member = 1; - bytes addedByUserId = 2; - uint64 timestamp = 3; -} - -message RequestingMember { - bytes userId = 1; - bytes profileKey = 2; - bytes presentation = 3; - uint64 timestamp = 4; -} - -message AccessControl { - enum AccessRequired { - UNKNOWN = 0; - ANY = 1; - MEMBER = 2; - ADMINISTRATOR = 3; - UNSATISFIABLE = 4; - } - - AccessRequired attributes = 1; - AccessRequired members = 2; - AccessRequired addFromInviteLink = 3; -} - -message Group { - bytes publicKey = 1; - bytes title = 2; - string avatar = 3; - bytes disappearingMessagesTimer = 4; - AccessControl accessControl = 5; - uint32 revision = 6; - repeated Member members = 7; - repeated PendingMember pendingMembers = 8; - repeated RequestingMember requestingMembers = 9; - bytes inviteLinkPassword = 10; - bytes description = 11; -} - -message GroupChange { - - message Actions { - - message AddMemberAction { - Member added = 1; - bool joinFromInviteLink = 2; - } - - message DeleteMemberAction { - bytes deletedUserId = 1; - } - - message ModifyMemberRoleAction { - bytes userId = 1; - Member.Role role = 2; - } - - message ModifyMemberProfileKeyAction { - bytes presentation = 1; - } - - message AddPendingMemberAction { - PendingMember added = 1; - } - - message DeletePendingMemberAction { - bytes deletedUserId = 1; - } - - message PromotePendingMemberAction { - bytes presentation = 1; - } - - message AddRequestingMemberAction { - RequestingMember added = 1; - } - - message DeleteRequestingMemberAction { - bytes deletedUserId = 1; - } - - message PromoteRequestingMemberAction { - bytes userId = 1; - Member.Role role = 2; - } - - message ModifyTitleAction { - bytes title = 1; - } - - message ModifyDescriptionAction { - bytes description = 1; - } - - message ModifyAvatarAction { - string avatar = 1; - } - - message ModifyDisappearingMessagesTimerAction { - bytes timer = 1; - } - - message ModifyAttributesAccessControlAction { - AccessControl.AccessRequired attributesAccess = 1; - } - - message ModifyMembersAccessControlAction { - AccessControl.AccessRequired membersAccess = 1; - } - - message ModifyAddFromInviteLinkAccessControlAction { - AccessControl.AccessRequired addFromInviteLinkAccess = 1; - } - - message ModifyInviteLinkPasswordAction { - bytes inviteLinkPassword = 1; - } - - bytes sourceUuid = 1; - uint32 revision = 2; - repeated AddMemberAction addMembers = 3; - repeated DeleteMemberAction deleteMembers = 4; - repeated ModifyMemberRoleAction modifyMemberRoles = 5; - repeated ModifyMemberProfileKeyAction modifyMemberProfileKeys = 6; - repeated AddPendingMemberAction addPendingMembers = 7; - repeated DeletePendingMemberAction deletePendingMembers = 8; - repeated PromotePendingMemberAction promotePendingMembers = 9; - ModifyTitleAction modifyTitle = 10; - ModifyAvatarAction modifyAvatar = 11; - ModifyDisappearingMessagesTimerAction modifyDisappearingMessagesTimer = 12; - ModifyAttributesAccessControlAction modifyAttributesAccess = 13; - ModifyMembersAccessControlAction modifyMemberAccess = 14; - ModifyAddFromInviteLinkAccessControlAction modifyAddFromInviteLinkAccess = 15; - repeated AddRequestingMemberAction addRequestingMembers = 16; - repeated DeleteRequestingMemberAction deleteRequestingMembers = 17; - repeated PromoteRequestingMemberAction promoteRequestingMembers = 18; - ModifyInviteLinkPasswordAction modifyInviteLinkPassword = 19; - ModifyDescriptionAction modifyDescription = 20; - } - - bytes actions = 1; - bytes serverSignature = 2; - uint32 changeEpoch = 3; -} - -message GroupChanges { - message GroupChangeState { - GroupChange groupChange = 1; - Group groupState = 2; - } - - repeated GroupChangeState groupChanges = 1; -} - -message GroupAttributeBlob { - oneof content { - string title = 1; - bytes avatar = 2; - uint32 disappearingMessagesDuration = 3; - string description = 4; - } -} - -message GroupInviteLink { - message GroupInviteLinkContentsV1 { - bytes groupMasterKey = 1; - bytes inviteLinkPassword = 2; - } - - oneof contents { - GroupInviteLinkContentsV1 v1Contents = 1; - } -} - -message GroupJoinInfo { - bytes publicKey = 1; - bytes title = 2; - string avatar = 3; - uint32 memberCount = 4; - AccessControl.AccessRequired addFromInviteLink = 5; - uint32 revision = 6; - bool pendingAdminApproval = 7; - bytes description = 8; -} - -message GroupExternalCredential { - string token = 1; -} diff --git a/net/gurk-rs/files/vendor/libsignal-service/protobuf/Provisioning.proto b/net/gurk-rs/files/vendor/libsignal-service/protobuf/Provisioning.proto deleted file mode 100644 index 80de36a..0000000 --- a/net/gurk-rs/files/vendor/libsignal-service/protobuf/Provisioning.proto +++ /dev/null @@ -1,40 +0,0 @@ -/** - * Copyright (C) 2014-2016 Open Whisper Systems - * - * Licensed according to the LICENSE file in this repository. - */ -syntax = "proto2"; - -package signalservice; - -option java_package = "org.whispersystems.signalservice.internal.push"; -option java_outer_classname = "ProvisioningProtos"; - -message ProvisioningUuid { - optional string uuid = 1; -} - -message ProvisionEnvelope { - optional bytes publicKey = 1; - optional bytes body = 2; // Encrypted ProvisionMessage -} - -message ProvisionMessage { - optional bytes identityKeyPublic = 1; - optional bytes identityKeyPrivate = 2; - optional string number = 3; - optional string uuid = 8; - optional string provisioningCode = 4; - optional string userAgent = 5; - optional bytes profileKey = 6; - optional bool readReceipts = 7; - optional uint32 provisioningVersion = 9; -} - -enum ProvisioningVersion { - option allow_alias = true; - - INITIAL = 0; - TABLET_SUPPORT = 1; - CURRENT = 1; -} diff --git a/net/gurk-rs/files/vendor/libsignal-service/protobuf/SignalService.proto b/net/gurk-rs/files/vendor/libsignal-service/protobuf/SignalService.proto deleted file mode 100644 index e4baee4..0000000 --- a/net/gurk-rs/files/vendor/libsignal-service/protobuf/SignalService.proto +++ /dev/null @@ -1,625 +0,0 @@ -/** - * Copyright (C) 2014-2016 Open Whisper Systems - * - * Licensed according to the LICENSE file in this repository. - */ -syntax = "proto2"; - -package signalservice; - -option java_package = "org.whispersystems.signalservice.internal.push"; -option java_outer_classname = "SignalServiceProtos"; - -message Envelope { - enum Type { - UNKNOWN = 0; - CIPHERTEXT = 1; - KEY_EXCHANGE = 2; - PREKEY_BUNDLE = 3; - RECEIPT = 5; - UNIDENTIFIED_SENDER = 6; - reserved 7; // SENDERKEY_MESSAGE - PLAINTEXT_CONTENT = 8; - } - - optional Type type = 1; - optional string sourceE164 = 2; - optional string sourceUuid = 11; - optional uint32 sourceDevice = 7; - optional string relay = 3; - optional uint64 timestamp = 5; - optional bytes legacyMessage = 6; // Contains an encrypted DataMessage - optional bytes content = 8; // Contains an encrypted Content - optional string serverGuid = 9; - optional uint64 serverTimestamp = 10; -} - -message Content { - optional DataMessage dataMessage = 1; - optional SyncMessage syncMessage = 2; - optional CallMessage callMessage = 3; - optional NullMessage nullMessage = 4; - optional ReceiptMessage receiptMessage = 5; - optional TypingMessage typingMessage = 6; - optional bytes senderKeyDistributionMessage = 7; - optional bytes decryptionErrorMessage = 8; -} - -message CallMessage { - message Offer { - enum Type { - OFFER_AUDIO_CALL = 0; - OFFER_VIDEO_CALL = 1; - reserved /* OFFER_NEED_PERMISSION */ 2; // removed - } - - optional uint64 id = 1; - // Legacy/deprecated; replaced by 'opaque' - optional string sdp = 2; - optional Type type = 3; - optional bytes opaque = 4; - } - - message Answer { - optional uint64 id = 1; - // Legacy/deprecated; replaced by 'opaque' - optional string sdp = 2; - optional bytes opaque = 3; - } - - message IceUpdate { - optional uint64 id = 1; - // Legacy/deprecated; remove when old clients are gone. - optional string mid = 2; - // Legacy/deprecated; remove when old clients are gone. - optional uint32 line = 3; - // Legacy/deprecated; replaced by 'opaque' - optional string sdp = 4; - optional bytes opaque = 5; - } - - message Busy { - optional uint64 id = 1; - } - - message Hangup { - enum Type { - HANGUP_NORMAL = 0; - HANGUP_ACCEPTED = 1; - HANGUP_DECLINED = 2; - HANGUP_BUSY = 3; - HANGUP_NEED_PERMISSION = 4; - } - - optional uint64 id = 1; - optional Type type = 2; - optional uint32 deviceId = 3; - } - - message Opaque { - optional bytes data = 1; - } - - optional Offer offer = 1; - optional Answer answer = 2; - repeated IceUpdate iceUpdate = 3; - optional Hangup legacyHangup = 4; - optional Busy busy = 5; - reserved /* profileKey */ 6; - optional Hangup hangup = 7; - optional bool multiRing = 8; - optional uint32 destinationDeviceId = 9; - optional Opaque opaque = 10; -} - -message DataMessage { - enum Flags { - END_SESSION = 1; - EXPIRATION_TIMER_UPDATE = 2; - PROFILE_KEY_UPDATE = 4; - } - - message BodyRange { - optional int32 start = 1; - optional int32 length = 2; - - oneof associatedValue { - string mentionUuid = 3; - } - } - - message Quote { - message QuotedAttachment { - optional string contentType = 1; - optional string fileName = 2; - optional AttachmentPointer thumbnail = 3; - } - - optional uint64 id = 1; - optional string authorE164 = 2; - optional string authorUuid = 5; - optional string text = 3; - repeated QuotedAttachment attachments = 4; - repeated BodyRange bodyRanges = 6; - } - - message Contact { - message Name { - optional string givenName = 1; - optional string familyName = 2; - optional string prefix = 3; - optional string suffix = 4; - optional string middleName = 5; - optional string displayName = 6; - } - - message Phone { - enum Type { - HOME = 1; - MOBILE = 2; - WORK = 3; - CUSTOM = 4; - } - - optional string value = 1; - optional Type type = 2; - optional string label = 3; - } - - message Email { - enum Type { - HOME = 1; - MOBILE = 2; - WORK = 3; - CUSTOM = 4; - } - - optional string value = 1; - optional Type type = 2; - optional string label = 3; - } - - message PostalAddress { - enum Type { - HOME = 1; - WORK = 2; - CUSTOM = 3; - } - - optional Type type = 1; - optional string label = 2; - optional string street = 3; - optional string pobox = 4; - optional string neighborhood = 5; - optional string city = 6; - optional string region = 7; - optional string postcode = 8; - optional string country = 9; - } - - message Avatar { - optional AttachmentPointer avatar = 1; - optional bool isProfile = 2; - } - - optional Name name = 1; - repeated Phone number = 3; - repeated Email email = 4; - repeated PostalAddress address = 5; - optional Avatar avatar = 6; - optional string organization = 7; - } - - message Preview { - optional string url = 1; - optional string title = 2; - optional AttachmentPointer image = 3; - optional string description = 4; - optional uint64 date = 5; - } - - message Sticker { - optional bytes packId = 1; - optional bytes packKey = 2; - optional uint32 stickerId = 3; - optional AttachmentPointer data = 4; - optional string emoji = 5; - } - - message Reaction { - optional string emoji = 1; - optional bool remove = 2; - reserved /* targetAuthorE164 */ 3; // removed - optional string targetAuthorUuid = 4; - optional uint64 targetSentTimestamp = 5; - } - - message Delete { - optional uint64 targetSentTimestamp = 1; - } - - message GroupCallUpdate { - optional string eraId = 1; - } - - message Payment { - - message Address { - message MobileCoin { - optional bytes address = 1; - } - - oneof Address { - MobileCoin mobileCoin = 1; - } - } - - message Amount { - message MobileCoin { - optional uint64 picoMob = 1; - } - - oneof Amount { - MobileCoin mobileCoin = 1; - } - } - - message Notification { - message MobileCoin { - optional bytes receipt = 1; - } - - oneof Transaction { - MobileCoin mobileCoin = 1; - } - - optional string note = 2; - } - - oneof Item { - Notification notification = 1; - } - } - - enum ProtocolVersion { - option allow_alias = true; - - INITIAL = 0; - MESSAGE_TIMERS = 1; - VIEW_ONCE = 2; - VIEW_ONCE_VIDEO = 3; - REACTIONS = 4; - CDN_SELECTOR_ATTACHMENTS = 5; - MENTIONS = 6; - PAYMENTS = 7; - CURRENT = 7; - } - - optional string body = 1; - repeated AttachmentPointer attachments = 2; - optional GroupContext group = 3; - optional GroupContextV2 groupV2 = 15; - optional uint32 flags = 4; - optional uint32 expireTimer = 5; - optional bytes profileKey = 6; - optional uint64 timestamp = 7; - optional Quote quote = 8; - repeated Contact contact = 9; - repeated Preview preview = 10; - optional Sticker sticker = 11; - optional uint32 requiredProtocolVersion = 12; - optional bool isViewOnce = 14; - optional Reaction reaction = 16; - optional Delete delete = 17; - repeated BodyRange bodyRanges = 18; - optional GroupCallUpdate groupCallUpdate = 19; - optional Payment payment = 20; -} - -message NullMessage { - optional bytes padding = 1; -} - -message ReceiptMessage { - enum Type { - DELIVERY = 0; - READ = 1; - VIEWED = 2; - } - - optional Type type = 1; - repeated uint64 timestamp = 2; -} - -message TypingMessage { - enum Action { - STARTED = 0; - STOPPED = 1; - } - - optional uint64 timestamp = 1; - optional Action action = 2; - optional bytes groupId = 3; -} - -message Verified { - enum State { - DEFAULT = 0; - VERIFIED = 1; - UNVERIFIED = 2; - } - - optional string destinationE164 = 1; - optional string destinationUuid = 5; - optional bytes identityKey = 2; - optional State state = 3; - optional bytes nullMessage = 4; -} - -message SyncMessage { - message Sent { - message UnidentifiedDeliveryStatus { - optional string destinationE164 = 1; - optional string destinationUuid = 3; - optional bool unidentified = 2; - } - - optional string destinationE164 = 1; - optional string destinationUuid = 7; - optional uint64 timestamp = 2; - optional DataMessage message = 3; - optional uint64 expirationStartTimestamp = 4; - repeated UnidentifiedDeliveryStatus unidentifiedStatus = 5; - optional bool isRecipientUpdate = 6 [default = false]; - } - - message Contacts { - optional AttachmentPointer blob = 1; - optional bool complete = 2 [default = false]; - } - - message Groups { - optional AttachmentPointer blob = 1; - } - - message Blocked { - repeated string numbers = 1; - repeated string uuids = 3; - repeated bytes groupIds = 2; - } - - message Request { - enum Type { - UNKNOWN = 0; - CONTACTS = 1; - GROUPS = 2; - BLOCKED = 3; - CONFIGURATION = 4; - KEYS = 5; - } - - optional Type type = 1; - } - - message Read { - optional string senderE164 = 1; - optional string senderUuid = 3; - optional uint64 timestamp = 2; - } - - message Viewed { - optional string senderE164 = 1; - optional string senderUuid = 3; - optional uint64 timestamp = 2; - } - - message Configuration { - optional bool readReceipts = 1; - optional bool unidentifiedDeliveryIndicators = 2; - optional bool typingIndicators = 3; - reserved /* linkPreviews */ 4; // removed - optional uint32 provisioningVersion = 5; - optional bool linkPreviews = 6; - } - - message StickerPackOperation { - enum Type { - INSTALL = 0; - REMOVE = 1; - } - - optional bytes packId = 1; - optional bytes packKey = 2; - optional Type type = 3; - } - - message ViewOnceOpen { - optional string senderE164 = 1; - optional string senderUuid = 3; - optional uint64 timestamp = 2; - } - - message FetchLatest { - enum Type { - UNKNOWN = 0; - LOCAL_PROFILE = 1; - STORAGE_MANIFEST = 2; - } - - optional Type type = 1; - } - - message Keys { - optional bytes storageService = 1; - } - - message MessageRequestResponse { - enum Type { - UNKNOWN = 0; - ACCEPT = 1; - DELETE = 2; - BLOCK = 3; - BLOCK_AND_DELETE = 4; - } - - optional string threadE164 = 1; - optional string threadUuid = 2; - optional bytes groupId = 3; - optional Type type = 4; - } - - message OutgoingPayment { - message MobileCoin { - optional bytes recipientAddress = 1; - // @required - optional uint64 amountPicoMob = 2; - // @required - optional uint64 feePicoMob = 3; - optional bytes receipt = 4; - optional uint64 ledgerBlockTimestamp = 5; - // @required - optional uint64 ledgerBlockIndex = 6; - repeated bytes spentKeyImages = 7; - repeated bytes outputPublicKeys = 8; - } - optional string recipientUuid = 1; - optional string note = 2; - - oneof paymentDetail { - MobileCoin mobileCoin = 3; - } - } - - optional Sent sent = 1; - optional Contacts contacts = 2; - optional Groups groups = 3; - optional Request request = 4; - repeated Read read = 5; - optional Blocked blocked = 6; - optional Verified verified = 7; - optional Configuration configuration = 9; - optional bytes padding = 8; - repeated StickerPackOperation stickerPackOperation = 10; - optional ViewOnceOpen viewOnceOpen = 11; - optional FetchLatest fetchLatest = 12; - optional Keys keys = 13; - optional MessageRequestResponse messageRequestResponse = 14; - optional OutgoingPayment outgoingPayment = 15; - repeated Viewed viewed = 16; -} - -message AttachmentPointer { - enum Flags { - VOICE_MESSAGE = 1; - BORDERLESS = 2; - reserved 3; - GIF = 4; - } - - oneof attachment_identifier { - fixed64 cdnId = 1; - string cdnKey = 15; - } - optional string contentType = 2; - optional bytes key = 3; - optional uint32 size = 4; - optional bytes thumbnail = 5; - optional bytes digest = 6; - optional string fileName = 7; - optional uint32 flags = 8; - optional uint32 width = 9; - optional uint32 height = 10; - optional string caption = 11; - optional string blurHash = 12; - optional uint64 uploadTimestamp = 13; - optional uint32 cdnNumber = 14; - // Next ID: 16 -} - -message GroupContext { - enum Type { - UNKNOWN = 0; - UPDATE = 1; - DELIVER = 2; - QUIT = 3; - REQUEST_INFO = 4; - } - - message Member { - reserved /* uuid */ 1; // removed - optional string e164 = 2; - } - - optional bytes id = 1; - optional Type type = 2; - optional string name = 3; - repeated string membersE164 = 4; - repeated Member members = 6; - optional AttachmentPointer avatar = 5; -} - -message GroupContextV2 { - optional bytes masterKey = 1; - optional uint32 revision = 2; - optional bytes groupChange = 3; -} - -message ContactDetails { - message Avatar { - optional string contentType = 1; - optional uint32 length = 2; - } - - optional string number = 1; - optional string uuid = 9; - optional string name = 2; - optional Avatar avatar = 3; - optional string color = 4; - optional Verified verified = 5; - optional bytes profileKey = 6; - optional bool blocked = 7; - optional uint32 expireTimer = 8; - optional uint32 inboxPosition = 10; - optional bool archived = 11; -} - -message GroupDetails { - message Avatar { - optional string contentType = 1; - optional uint32 length = 2; - } - - message Member { - reserved /* uuid */ 1; // removed - optional string e164 = 2; - } - - optional bytes id = 1; - optional string name = 2; - repeated string membersE164 = 3; - repeated Member members = 9; - optional Avatar avatar = 4; - optional bool active = 5 [default = true]; - optional uint32 expireTimer = 6; - optional string color = 7; - optional bool blocked = 8; - optional uint32 inboxPosition = 10; - optional bool archived = 11; -} - -message PaymentAddress { - oneof Address { - MobileCoinAddress mobileCoinAddress = 1; - } - - message MobileCoinAddress { - optional bytes address = 1; - optional bytes signature = 2; - } -} - -message DecryptionErrorMessage { - optional bytes ratchetKey = 1; - optional uint64 timestamp = 2; - optional uint32 deviceId = 3; -} diff --git a/net/gurk-rs/files/vendor/libsignal-service/protobuf/StickerResources.proto b/net/gurk-rs/files/vendor/libsignal-service/protobuf/StickerResources.proto deleted file mode 100644 index 03e5ccb..0000000 --- a/net/gurk-rs/files/vendor/libsignal-service/protobuf/StickerResources.proto +++ /dev/null @@ -1,25 +0,0 @@ -/** - * Copyright (C) 2019 Open Whisper Systems - * - * Licensed according to the LICENSE file in this repository. - */ -syntax = "proto2"; - -package signalservice; - -option java_package = "org.whispersystems.signalservice.internal.sticker"; -option java_outer_classname = "StickerProtos"; - -message Pack { - message Sticker { - optional uint32 id = 1; - optional string emoji = 2; - optional string contentType = 3; - } - - optional string title = 1; - optional string author = 2; - optional Sticker cover = 3; - repeated Sticker stickers = 4; -} - diff --git a/net/gurk-rs/files/vendor/libsignal-service/protobuf/UnidentifiedDelivery.proto b/net/gurk-rs/files/vendor/libsignal-service/protobuf/UnidentifiedDelivery.proto deleted file mode 100644 index c9e3154..0000000 --- a/net/gurk-rs/files/vendor/libsignal-service/protobuf/UnidentifiedDelivery.proto +++ /dev/null @@ -1,48 +0,0 @@ -syntax = "proto2"; - -package signal; - -option java_package = "org.signal.libsignal.metadata"; -option java_outer_classname = "SignalProtos"; - -message ServerCertificate { - message Certificate { - optional uint32 id = 1; - optional bytes key = 2; - } - - optional bytes certificate = 1; - optional bytes signature = 2; -} - -message SenderCertificate { - message Certificate { - optional string senderE164 = 1; - optional string senderUuid = 6; - optional uint32 senderDevice = 2; - optional fixed64 expires = 3; - optional bytes identityKey = 4; - optional ServerCertificate signer = 5; - } - - optional bytes certificate = 1; - optional bytes signature = 2; -} - -message UnidentifiedSenderMessage { - - message Message { - enum Type { - PREKEY_MESSAGE = 1; - MESSAGE = 2; - } - - optional Type type = 1; - optional SenderCertificate senderCertificate = 2; - optional bytes content = 3; - } - - optional bytes ephemeralPublic = 1; - optional bytes encryptedStatic = 2; - optional bytes encryptedMessage = 3; -} \ No newline at end of file diff --git a/net/gurk-rs/files/vendor/libsignal-service/protobuf/WebSocketResources.proto b/net/gurk-rs/files/vendor/libsignal-service/protobuf/WebSocketResources.proto deleted file mode 100644 index 46ea453..0000000 --- a/net/gurk-rs/files/vendor/libsignal-service/protobuf/WebSocketResources.proto +++ /dev/null @@ -1,39 +0,0 @@ -/** - * Copyright (C) 2014-2016 Open Whisper Systems - * - * Licensed according to the LICENSE file in this repository. - */ -syntax = "proto2"; - -package signalservice; - -option java_package = "org.whispersystems.signalservice.internal.websocket"; -option java_outer_classname = "WebSocketProtos"; - -message WebSocketRequestMessage { - optional string verb = 1; - optional string path = 2; - optional bytes body = 3; - repeated string headers = 5; - optional uint64 id = 4; -} - -message WebSocketResponseMessage { - optional uint64 id = 1; - optional uint32 status = 2; - optional string message = 3; - repeated string headers = 5; - optional bytes body = 4; -} - -message WebSocketMessage { - enum Type { - UNKNOWN = 0; - REQUEST = 1; - RESPONSE = 2; - } - - optional Type type = 1; - optional WebSocketRequestMessage request = 2; - optional WebSocketResponseMessage response = 3; -} \ No newline at end of file diff --git a/net/gurk-rs/files/vendor/libsignal-service/src/account_manager.rs b/net/gurk-rs/files/vendor/libsignal-service/src/account_manager.rs deleted file mode 100644 index 8ae95be..0000000 --- a/net/gurk-rs/files/vendor/libsignal-service/src/account_manager.rs +++ /dev/null @@ -1,409 +0,0 @@ -use std::collections::HashMap; -use std::convert::{TryFrom, TryInto}; -use std::time::SystemTime; - -use libsignal_protocol::{ - IdentityKeyStore, KeyPair, PreKeyRecord, PreKeyStore, PublicKey, - SignalProtocolError, SignedPreKeyRecord, SignedPreKeyStore, -}; -use zkgroup::profiles::ProfileKey; - -use crate::{ - configuration::{Endpoint, ServiceCredentials}, - pre_keys::{PreKeyEntity, PreKeyState}, - profile_cipher::{ProfileCipher, ProfileCipherError}, - profile_name::ProfileName, - proto::{ProvisionEnvelope, ProvisionMessage, ProvisioningVersion}, - provisioning::{ProvisioningCipher, ProvisioningError}, - push_service::{ - AccountAttributes, HttpAuthOverride, PushService, ServiceError, - }, -}; - -pub struct AccountManager { - service: Service, - profile_key: Option<[u8; 32]>, -} - -#[derive(thiserror::Error, Debug)] -pub enum ProfileManagerError { - #[error(transparent)] - ServiceError(#[from] ServiceError), - #[error(transparent)] - ProfileCipherError(#[from] ProfileCipherError), -} - -#[derive(thiserror::Error, Debug)] -pub enum LinkError { - #[error(transparent)] - ServiceError(#[from] ServiceError), - #[error("TsUrl has an invalid UUID field")] - InvalidUuid, - #[error("TsUrl has an invalid pub_key field")] - InvalidPublicKey, - #[error("Protocol error {0}")] - ProtocolError(#[from] SignalProtocolError), - #[error(transparent)] - ProvisioningError(#[from] ProvisioningError), -} - -#[derive(Debug, Default)] -pub struct Profile { - pub name: Option>, - pub about: Option, - pub about_emoji: Option, -} - -const PRE_KEY_MINIMUM: u32 = 10; -const PRE_KEY_BATCH_SIZE: u32 = 100; -const PRE_KEY_MEDIUM_MAX_VALUE: u32 = 0xFFFFFF; - -impl AccountManager { - pub fn new(service: Service, profile_key: Option<[u8; 32]>) -> Self { - Self { - service, - profile_key, - } - } - - /// Checks the availability of pre-keys, and updates them as necessary. - /// - /// Parameters are the protocol's `StoreContext`, and the offsets for the next pre-key and - /// signed pre-keys. - /// - /// Equivalent to Java's RefreshPreKeysJob - /// - /// Returns the next pre-key offset and next signed pre-key offset as a tuple. - #[allow(clippy::too_many_arguments)] - pub async fn update_pre_key_bundle( - &mut self, - identity_store: &dyn IdentityKeyStore, - pre_key_store: &mut dyn PreKeyStore, - signed_pre_key_store: &mut dyn SignedPreKeyStore, - csprng: &mut R, - pre_keys_offset_id: u32, - next_signed_pre_key_id: u32, - use_last_resort_key: bool, - ) -> Result<(u32, u32), ServiceError> { - let prekey_count = match self.service.get_pre_key_status().await { - Ok(status) => status.count, - Err(ServiceError::Unauthorized) => { - log::info!("Got Unauthorized when fetching pre-key status. Assuming first installment."); - // Additionally, the second PUT request will fail if this really comes down to an - // authorization failure. - 0 - }, - Err(e) => return Err(e), - }; - log::trace!("Remaining pre-keys on server: {}", prekey_count); - - if prekey_count >= PRE_KEY_MINIMUM { - log::info!("Available keys sufficient"); - return Ok((pre_keys_offset_id, next_signed_pre_key_id)); - } - - let mut pre_key_entities = vec![]; - for i in 0..PRE_KEY_BATCH_SIZE { - let key_pair = KeyPair::generate(csprng); - let pre_key_id = - ((pre_keys_offset_id + i) % (PRE_KEY_MEDIUM_MAX_VALUE - 1)) + 1; - let pre_key_record = PreKeyRecord::new(pre_key_id, &key_pair); - pre_key_store - .save_pre_key(pre_key_id, &pre_key_record, None) - .await?; - - pre_key_entities.push(PreKeyEntity::try_from(pre_key_record)?); - } - - // Generate and store the next signed prekey - let identity_key_pair = - identity_store.get_identity_key_pair(None).await?; - let signed_pre_key_pair = KeyPair::generate(csprng); - let signed_pre_key_public = signed_pre_key_pair.public_key; - let signed_pre_key_signature = identity_key_pair - .private_key() - .calculate_signature(&signed_pre_key_public.serialize(), csprng)?; - - let unix_time = SystemTime::now() - .duration_since(SystemTime::UNIX_EPOCH) - .unwrap(); - - let signed_prekey_record = SignedPreKeyRecord::new( - next_signed_pre_key_id, - unix_time.as_millis() as u64, - &signed_pre_key_pair, - &signed_pre_key_signature, - ); - - signed_pre_key_store - .save_signed_pre_key( - next_signed_pre_key_id, - &signed_prekey_record, - None, - ) - .await?; - - let pre_key_state = PreKeyState { - pre_keys: pre_key_entities, - signed_pre_key: signed_prekey_record.try_into()?, - identity_key: *identity_key_pair.public_key(), - last_resort_key: if use_last_resort_key { - Some(PreKeyEntity { - key_id: 0x7fffffff, - public_key: "NDI=".into(), - }) - } else { - None - }, - }; - - self.service.register_pre_keys(pre_key_state).await?; - - log::trace!("Successfully refreshed prekeys"); - Ok(( - pre_keys_offset_id + PRE_KEY_BATCH_SIZE, - next_signed_pre_key_id + 1, - )) - } - - async fn new_device_provisioning_code( - &mut self, - ) -> Result { - #[derive(serde::Deserialize)] - #[serde(rename_all = "camelCase")] - struct DeviceCode { - verification_code: String, - } - - let dc: DeviceCode = self - .service - .get_json( - Endpoint::Service, - "/v1/devices/provisioning/code", - HttpAuthOverride::NoOverride, - ) - .await?; - Ok(dc.verification_code) - } - - async fn send_provisioning_message( - &mut self, - destination: &str, - env: ProvisionEnvelope, - ) -> Result<(), ServiceError> { - use prost::Message; - - #[derive(serde::Serialize)] - struct ProvisioningMessage { - body: String, - } - - let body = env.encode_to_vec(); - - self.service - .put_json( - Endpoint::Service, - &format!("/v1/provisioning/{}", destination), - HttpAuthOverride::NoOverride, - &ProvisioningMessage { - body: base64::encode(body), - }, - ) - .await - } - - /// Link a new device, given a tsurl. - /// - /// Equivalent of Java's `AccountManager::addDevice()` - /// - /// When calling this, make sure that UnidentifiedDelivery is disabled, ie., that your - /// application does not send any unidentified messages before linking is complete. - /// Cfr.: - /// - `app/src/main/java/org/thoughtcrime/securesms/migrations/LegacyMigrationJob.java`:250 and; - /// - `app/src/main/java/org/thoughtcrime/securesms/DeviceActivity.java`:195 - /// - /// ```java - /// TextSecurePreferences.setIsUnidentifiedDeliveryEnabled(context, false); - /// ``` - pub async fn link_device( - &mut self, - url: url::Url, - identity_store: &dyn IdentityKeyStore, - credentials: ServiceCredentials, - ) -> Result<(), LinkError> { - let query: HashMap<_, _> = url.query_pairs().collect(); - let ephemeral_id = query.get("uuid").ok_or(LinkError::InvalidUuid)?; - let pub_key = - query.get("pub_key").ok_or(LinkError::InvalidPublicKey)?; - let pub_key = base64::decode(&**pub_key) - .map_err(|_e| LinkError::InvalidPublicKey)?; - let pub_key = PublicKey::deserialize(&pub_key) - .map_err(|_e| LinkError::InvalidPublicKey)?; - - let identity_key_pair = - identity_store.get_identity_key_pair(None).await?; - - if credentials.uuid.is_none() { - log::warn!("No local UUID set"); - } - - let provisioning_code = self.new_device_provisioning_code().await?; - - let msg = ProvisionMessage { - identity_key_public: Some( - identity_key_pair.public_key().serialize().into_vec(), - ), - identity_key_private: Some( - identity_key_pair.private_key().serialize(), - ), - number: Some(credentials.e164()), - uuid: credentials.uuid.as_ref().map(|u| u.to_string()), - profile_key: self.profile_key.as_ref().map(|x| x.to_vec()), - // CURRENT is not exposed by prost :( - provisioning_version: Some(i32::from( - ProvisioningVersion::TabletSupport, - ) as _), - provisioning_code: Some(provisioning_code), - read_receipts: None, - user_agent: None, - }; - - let cipher = ProvisioningCipher::from_public(pub_key); - - let encrypted = cipher.encrypt(msg)?; - self.send_provisioning_message(ephemeral_id, encrypted) - .await?; - Ok(()) - } - - /// Upload a profile - /// - /// Panics if no `profile_key` was set. - /// - /// Convenience method for - /// ```ignore - /// manager.upload_versioned_profile::>, _>(uuid, name, about, about_emoji, None) - /// ``` - pub async fn upload_versioned_profile_without_avatar>( - &mut self, - uuid: uuid::Uuid, - name: ProfileName, - about: Option, - about_emoji: Option, - ) -> Result<(), ProfileManagerError> { - self.upload_versioned_profile::>, _>( - uuid, - name, - about, - about_emoji, - None, - ) - .await?; - Ok(()) - } - - pub async fn retrieve_profile( - &mut self, - uuid: uuid::Uuid, - ) -> Result { - let profile_key = - self.profile_key.expect("set profile key in AccountManager"); - let profile_key = ProfileKey::create(profile_key); - let profile_cipher = ProfileCipher::from(profile_key); - let profile_key_version = - profile_key.get_profile_key_version(*uuid.as_bytes()); - - let encrypted_profile = self - .service - .retrieve_versioned_profile_by_id( - &uuid.to_string(), - &profile_key_version, - ) - .await?; - - // Profile decryption - let name = encrypted_profile - .name - .map(|data| profile_cipher.decrypt_name(data)) - .transpose()? - .flatten(); - let about = encrypted_profile - .about - .map(|data| profile_cipher.decrypt_about(data)) - .transpose()?; - let about_emoji = encrypted_profile - .about_emoji - .map(|data| profile_cipher.decrypt_emoji(data)) - .transpose()?; - - Ok(Profile { - name, - about, - about_emoji, - }) - } - - /// Upload a profile - /// - /// Panics if no `profile_key` was set. - /// - /// Returns the avatar url path. - pub async fn upload_versioned_profile< - 's, - C: std::io::Read + Send + 's, - S: AsRef, - >( - &mut self, - uuid: uuid::Uuid, - name: ProfileName, - about: Option, - about_emoji: Option, - avatar: Option<&'s mut C>, - ) -> Result, ProfileManagerError> { - let profile_key = - self.profile_key.expect("set profile key in AccountManager"); - let profile_key = ProfileKey::create(profile_key); - let profile_cipher = ProfileCipher::from(profile_key); - - // Profile encryption - let name = profile_cipher.encrypt_name(name.as_ref())?; - let about = about.unwrap_or_default(); - let about = profile_cipher.encrypt_about(about)?; - let about_emoji = about_emoji.unwrap_or_default(); - let about_emoji = profile_cipher.encrypt_emoji(about_emoji)?; - - // If avatar -> upload - if let Some(_avatar) = avatar { - // FIXME ProfileCipherOutputStream.java - // It's just AES GCM, but a bit of work to decently implement it with a stream. - unimplemented!("Setting avatar requires ProfileCipherStream") - } - - let profile_key = profile_cipher.into_inner(); - let commitment = profile_key.get_commitment(*uuid.as_bytes()); - let profile_key_version = - profile_key.get_profile_key_version(*uuid.as_bytes()); - - Ok(self - .service - .write_profile( - &profile_key_version, - &name, - &about, - &about_emoji, - &commitment, - None, // FIXME avatar - ) - .await?) - } - - /// Set profile attributes - /// - /// Signal Android does not allow unsetting voice/video. - pub async fn set_account_attributes( - &mut self, - attributes: AccountAttributes, - ) -> Result<(), ServiceError> { - self.service.set_account_attributes(attributes).await - } -} diff --git a/net/gurk-rs/files/vendor/libsignal-service/src/attachment_cipher.rs b/net/gurk-rs/files/vendor/libsignal-service/src/attachment_cipher.rs deleted file mode 100644 index a3b94b0..0000000 --- a/net/gurk-rs/files/vendor/libsignal-service/src/attachment_cipher.rs +++ /dev/null @@ -1,163 +0,0 @@ -use aes::Aes256; -use block_modes::{block_padding::Pkcs7, BlockMode, Cbc}; -use hmac::{Hmac, Mac, NewMac}; -use sha2::Sha256; - -#[derive(thiserror::Error, Debug, PartialEq, Eq)] -pub enum AttachmentCipherError { - #[error("MAC verification error")] - MacError, - #[error("Padding verification error")] - PaddingError, -} - -/// Encrypts an attachment in place, given the key material. -/// -/// The Vec will be reused when it has enough space to house the MAC, -/// otherwise reallocation might happen. -pub fn encrypt_in_place(iv: [u8; 16], key: [u8; 64], plaintext: &mut Vec) { - let aes_half = &key[..32]; - let mac_half = &key[32..]; - - let plaintext_len = plaintext.len(); - plaintext.reserve(plaintext.len() + 16 + 16); - - // Prepend IV - plaintext.extend(&[0u8; 16]); - plaintext.copy_within(..plaintext_len, 16); - plaintext[0..16].copy_from_slice(&iv); - - // Pad with zeroes for padding - plaintext.extend(&[0u8; 16]); - - let cipher = Cbc::::new_from_slices(aes_half, &iv) - .expect("fixed length key material"); - - let buffer = plaintext; - let ciphertext_slice = cipher - .encrypt(&mut buffer[16..], plaintext_len) - .expect("encrypted ciphertext"); - let ciphertext_len = ciphertext_slice.len(); - // Correct length for padding - buffer.truncate(16 + ciphertext_len); - - // Compute and append MAC - let mut mac = Hmac::::new_from_slice(mac_half) - .expect("fixed length key material"); - mac.update(buffer); - buffer.extend(mac.finalize().into_bytes()); -} - -/// Decrypts an attachment in place, given the key material. -/// -/// On error, ciphertext is not changed. -pub fn decrypt_in_place( - key: [u8; 64], - ciphertext: &mut Vec, -) -> Result<(), AttachmentCipherError> { - let aes_half = &key[..32]; - let mac_half = &key[32..]; - - let ciphertext_len = ciphertext.len(); - - let (buffer, their_mac) = ciphertext.split_at_mut(ciphertext_len - 32); - - // Compute and append MAC - let mut mac = Hmac::::new_from_slice(mac_half) - .expect("fixed length key material"); - mac.update(buffer); - mac.verify(their_mac) - .map_err(|_| AttachmentCipherError::MacError)?; - - let (iv, buffer) = buffer.split_at_mut(16); - - let cipher = Cbc::::new_from_slices(aes_half, iv) - .expect("fixed length key material"); - - let plaintext_slice = cipher - .decrypt(buffer) - .map_err(|_| AttachmentCipherError::PaddingError)?; - - let plaintext_len = plaintext_slice.len(); - - // Get rid of IV and MAC - ciphertext.copy_within(16..(plaintext_len + 16), 0); - ciphertext.truncate(plaintext_len); - - Ok(()) -} - -#[cfg(test)] -mod tests { - use super::*; - - use rand::prelude::*; - - #[test] - fn attachment_encrypt_decrypt() -> Result<(), AttachmentCipherError> { - let mut key = [0u8; 64]; - let mut iv = [0u8; 16]; - rand::thread_rng().fill_bytes(&mut key); - rand::thread_rng().fill_bytes(&mut iv); - - let plaintext = b"Peter Parker"; - let mut buf = Vec::from(plaintext as &[u8]); - encrypt_in_place(iv, key, &mut buf); - assert_ne!(&buf, &plaintext); - decrypt_in_place(key, &mut buf)?; - assert_eq!(&buf, &plaintext); - Ok(()) - } - - #[test] - fn attachment_encrypt_decrypt_empty() -> Result<(), AttachmentCipherError> { - let mut key = [0u8; 64]; - let mut iv = [0u8; 16]; - rand::thread_rng().fill_bytes(&mut key); - rand::thread_rng().fill_bytes(&mut iv); - let plaintext = b""; - let mut buf = Vec::from(plaintext as &[u8]); - encrypt_in_place(iv, key, &mut buf); - assert_ne!(&buf, &plaintext); - decrypt_in_place(key, &mut buf)?; - assert_eq!(&buf, &plaintext); - Ok(()) - } - - #[test] - fn attachment_encrypt_decrypt_bad_key() { - let mut key = [0u8; 64]; - let mut iv = [0u8; 16]; - rand::thread_rng().fill_bytes(&mut key); - rand::thread_rng().fill_bytes(&mut iv); - let plaintext = b"Peter Parker"; - let mut buf = Vec::from(plaintext as &[u8]); - encrypt_in_place(iv, key, &mut buf); - - // Generate bad key - rand::thread_rng().fill_bytes(&mut key); - assert_eq!( - decrypt_in_place(key, &mut buf).unwrap_err(), - AttachmentCipherError::MacError - ); - assert_ne!(&buf, &plaintext); - } - - #[test] - fn know_answer_test_attachment() -> Result<(), AttachmentCipherError> { - let mut ciphertext = include!("kat.bin.rs"); - let key_material = [ - 52, 102, 97, 87, 153, 192, 64, 116, 93, 96, 57, 110, 6, 197, 208, - 85, 49, 249, 154, 137, 116, 124, 112, 107, 8, 158, 48, 4, 8, 66, - 173, 5, 28, 16, 199, 226, 234, 38, 69, 167, 163, 34, 107, 164, 15, - 118, 101, 146, 34, 213, 85, 164, 110, 83, 129, 245, 62, 44, 158, - 78, 205, 62, 153, 108, - ]; - - decrypt_in_place(key_material, &mut ciphertext)?; - // This 32 is given by the AttachmentPointer - ciphertext.truncate(32); - assert_eq!(ciphertext, b"test for libsignal-service-rust\n"); - Ok(()) - } -} diff --git a/net/gurk-rs/files/vendor/libsignal-service/src/cipher.rs b/net/gurk-rs/files/vendor/libsignal-service/src/cipher.rs deleted file mode 100644 index dd35a91..0000000 --- a/net/gurk-rs/files/vendor/libsignal-service/src/cipher.rs +++ /dev/null @@ -1,372 +0,0 @@ -use std::convert::TryFrom; - -use block_modes::block_padding::{Iso7816, Padding}; -use libsignal_protocol::{ - message_decrypt_prekey, message_decrypt_signal, message_encrypt, - CiphertextMessageType, IdentityKeyStore, PreKeySignalMessage, PreKeyStore, - ProtocolAddress, SessionStore, SignalMessage, SignalProtocolError, - SignedPreKeyStore, -}; -use prost::Message; -use rand::{CryptoRng, Rng}; - -use crate::{ - content::{Content, Metadata}, - envelope::Envelope, - push_service::ServiceError, - sealed_session_cipher::UnidentifiedAccess, - sealed_session_cipher::{ - CertificateValidator, DecryptionResult, SealedSessionCipher, - }, - sender::OutgoingPushMessage, - ServiceAddress, -}; - -/// Decrypts incoming messages and encrypts outgoing messages. -/// -/// Equivalent of SignalServiceCipher in Java. -#[derive(Clone)] -pub struct ServiceCipher { - session_store: S, - identity_key_store: I, - signed_pre_key_store: SP, - pre_key_store: P, - csprng: R, - sealed_session_cipher: SealedSessionCipher, -} - -impl ServiceCipher -where - S: SessionStore + Clone, - I: IdentityKeyStore + Clone, - SP: SignedPreKeyStore + Clone, - P: PreKeyStore + Clone, - R: Rng + CryptoRng + Clone, -{ - pub fn new( - session_store: S, - identity_key_store: I, - signed_pre_key_store: SP, - pre_key_store: P, - csprng: R, - certificate_validator: CertificateValidator, - ) -> Self { - Self { - session_store: session_store.clone(), - identity_key_store: identity_key_store.clone(), - signed_pre_key_store: signed_pre_key_store.clone(), - pre_key_store: pre_key_store.clone(), - csprng: csprng.clone(), - sealed_session_cipher: SealedSessionCipher::new( - session_store, - identity_key_store, - signed_pre_key_store, - pre_key_store, - csprng, - certificate_validator, - ), - } - } - - /// Opens ("decrypts") an envelope. - /// - /// Envelopes may be empty, in which case this method returns `Ok(None)` - pub async fn open_envelope( - &mut self, - envelope: Envelope, - ) -> Result, ServiceError> { - if envelope.legacy_message.is_some() { - let plaintext = self.decrypt(&envelope).await?; - let message = - crate::proto::DataMessage::decode(plaintext.data.as_slice())?; - Ok(Some(Content::from_body(message, plaintext.metadata))) - } else if envelope.content.is_some() { - let plaintext = self.decrypt(&envelope).await?; - let message = - crate::proto::Content::decode(plaintext.data.as_slice())?; - Ok(Content::from_proto(message, plaintext.metadata)) - } else { - Ok(None) - } - } - - /// Equivalent of decrypt(Envelope, ciphertext) - /// - /// Triage of legacy messages happens inside this method, as opposed to the - /// Java implementation, because it makes the borrow checker and the - /// author happier. - async fn decrypt( - &mut self, - envelope: &Envelope, - ) -> Result { - let ciphertext = if let Some(msg) = envelope.legacy_message.as_ref() { - msg - } else if let Some(msg) = envelope.content.as_ref() { - msg - } else { - return Err(ServiceError::InvalidFrameError { - reason: - "Envelope should have either a legacy message or content." - .into(), - }); - }; - - use crate::proto::envelope::Type; - let plaintext = match envelope.r#type() { - Type::PrekeyBundle => { - let sender = get_preferred_protocol_address( - &self.session_store, - &envelope.source_address(), - envelope.source_device(), - ) - .await?; - let metadata = Metadata { - sender: envelope.source_address(), - sender_device: envelope.source_device(), - timestamp: envelope.timestamp(), - needs_receipt: false, - }; - - let mut data = message_decrypt_prekey( - &PreKeySignalMessage::try_from(&ciphertext[..]).unwrap(), - &sender, - &mut self.session_store, - &mut self.identity_key_store, - &mut self.pre_key_store, - &mut self.signed_pre_key_store, - &mut self.csprng, - None, - ) - .await? - .as_slice() - .to_vec(); - - let session_record = self - .session_store - .load_session(&sender, None) - .await? - .ok_or_else(|| { - SignalProtocolError::SessionNotFound(format!( - "{}", - sender - )) - })?; - - strip_padding(session_record.session_version()?, &mut data)?; - Plaintext { metadata, data } - }, - Type::Ciphertext => { - let sender = get_preferred_protocol_address( - &self.session_store, - &envelope.source_address(), - envelope.source_device(), - ) - .await?; - let metadata = Metadata { - sender: envelope.source_address(), - sender_device: envelope.source_device(), - timestamp: envelope.timestamp(), - needs_receipt: false, - }; - - let mut data = message_decrypt_signal( - &SignalMessage::try_from(&ciphertext[..])?, - &sender, - &mut self.session_store, - &mut self.identity_key_store, - &mut self.csprng, - None, - ) - .await? - .as_slice() - .to_vec(); - - let session_record = self - .session_store - .load_session(&sender, None) - .await? - .ok_or_else(|| { - SignalProtocolError::SessionNotFound(format!( - "{}", - sender - )) - })?; - - strip_padding(session_record.session_version()?, &mut data)?; - Plaintext { metadata, data } - }, - Type::UnidentifiedSender => { - let DecryptionResult { - sender_uuid, - sender_e164, - device_id, - padded_message: mut data, - version, - } = self - .sealed_session_cipher - .decrypt(ciphertext, envelope.timestamp()) - .await?; - let sender = ServiceAddress { - phonenumber: sender_e164, - uuid: sender_uuid, - relay: None, - }; - let metadata = Metadata { - sender, - sender_device: device_id, - timestamp: envelope.timestamp(), - needs_receipt: false, - }; - strip_padding(version, &mut data)?; - Plaintext { metadata, data } - }, - _ => { - // else - return Err(ServiceError::InvalidFrameError { - reason: format!( - "Envelope has unknown type {:?}.", - envelope.r#type() - ), - }); - }, - }; - Ok(plaintext) - } - - pub(crate) async fn encrypt( - &mut self, - address: &ProtocolAddress, - unindentified_access: Option<&UnidentifiedAccess>, - content: &[u8], - ) -> Result { - if unindentified_access.is_some() { - unimplemented!("unidentified access is not implemented"); - } else { - let session_record = self - .session_store - .load_session(address, None) - .await? - .ok_or_else(|| { - SignalProtocolError::SessionNotFound(format!("{}", address)) - })?; - - let padded_content = - add_padding(session_record.session_version()?, content)?; - - let message = message_encrypt( - &padded_content, - address, - &mut self.session_store, - &mut self.identity_key_store, - None, - ) - .await?; - - let destination_registration_id = - session_record.remote_registration_id()?; - - let body = base64::encode(message.serialize()); - - use crate::proto::envelope::Type; - let message_type = match message.message_type() { - CiphertextMessageType::PreKey => Type::PrekeyBundle, - CiphertextMessageType::Whisper => Type::Ciphertext, - t => panic!("Bad type: {:?}", t), - } as u32; - Ok(OutgoingPushMessage { - r#type: message_type, - destination_device_id: address.device_id(), - destination_registration_id, - content: body, - }) - } - } -} - -struct Plaintext { - metadata: Metadata, - data: Vec, -} - -#[allow(clippy::comparison_chain)] -fn add_padding(version: u32, contents: &[u8]) -> Result, ServiceError> { - if version < 2 { - Err(ServiceError::InvalidFrameError { - reason: format!("Unknown version {}", version), - }) - } else if version == 2 { - Ok(contents.to_vec()) - } else { - let message_length = contents.len(); - let message_length_with_terminator = contents.len() + 1; - let mut message_part_count = message_length_with_terminator / 160; - if message_length_with_terminator % 160 != 0 { - message_part_count += 1; - } - - let message_length_with_padding = message_part_count * 160; - - let mut buffer = vec![0u8; message_length_with_padding]; - buffer[..message_length].copy_from_slice(contents); - Iso7816::pad_block(&mut buffer, message_length).map_err(|e| { - ServiceError::InvalidFrameError { - reason: format!("Invalid message padding: {:?}", e), - } - })?; - Ok(buffer) - } -} - -#[allow(clippy::comparison_chain)] -fn strip_padding( - version: u32, - contents: &mut Vec, -) -> Result<(), ServiceError> { - if version < 2 { - Err(ServiceError::InvalidFrameError { - reason: format!("Unknown version {}", version), - }) - } else if version == 2 { - Ok(()) - } else { - let new_length = Iso7816::unpad(contents) - .map_err(|e| ServiceError::InvalidFrameError { - reason: format!("Invalid message padding: {:?}", e), - })? - .len(); - contents.resize(new_length, 0); - Ok(()) - } -} - -/// Equivalent of `SignalServiceCipher::getPreferredProtocolAddress` -pub async fn get_preferred_protocol_address( - session_store: &dyn SessionStore, - address: &ServiceAddress, - device_id: u32, -) -> Result { - if let Some(ref uuid) = address.uuid { - let address = ProtocolAddress::new(uuid.to_string(), device_id); - if session_store.load_session(&address, None).await?.is_some() { - return Ok(address); - } - } - if let Some(e164) = address.e164() { - let address = ProtocolAddress::new(e164, device_id); - if session_store.load_session(&address, None).await?.is_some() { - return Ok(address); - } - if cfg!(feature = "prefer-e164") { - log::warn!("prefer-e164 triggered. This is a legacy feature and shouldn't be used for new applications."); - return Ok(address); - } - } - if cfg!(feature = "prefer-e164") { - panic!( - "{:?}:{} does not have a e164 associated, falling back to UUID.", - address, device_id - ); - } - - Ok(ProtocolAddress::new(address.identifier(), device_id)) -} diff --git a/net/gurk-rs/files/vendor/libsignal-service/src/configuration.rs b/net/gurk-rs/files/vendor/libsignal-service/src/configuration.rs deleted file mode 100644 index 37b2d0d..0000000 --- a/net/gurk-rs/files/vendor/libsignal-service/src/configuration.rs +++ /dev/null @@ -1,180 +0,0 @@ -use std::{collections::HashMap, str::FromStr}; - -use libsignal_protocol::PublicKey; -use serde::{Deserialize, Serialize}; -use url::Url; -use zkgroup::ServerPublicParams; - -use crate::{ - envelope::{CIPHER_KEY_SIZE, MAC_KEY_SIZE}, - push_service::{HttpAuth, ServiceError, DEFAULT_DEVICE_ID}, - sealed_session_cipher::{CertificateValidator, SealedSessionError}, -}; - -#[derive(Clone)] -pub struct ServiceConfiguration { - service_url: Url, - storage_url: Url, - cdn_urls: HashMap, - contact_discovery_url: Url, - pub certificate_authority: String, - pub unidentified_sender_trust_root: String, - pub zkgroup_server_public_params: ServerPublicParams, -} - -pub type SignalingKey = [u8; CIPHER_KEY_SIZE + MAC_KEY_SIZE]; - -#[derive(Clone)] -pub struct ServiceCredentials { - pub uuid: Option, - pub phonenumber: phonenumber::PhoneNumber, - pub password: Option, - pub signaling_key: Option, - pub device_id: Option, -} - -impl ServiceCredentials { - pub fn authorization(&self) -> Option { - self.password.as_ref().map(|password| HttpAuth { - username: self.login(), - password: password.clone(), - }) - } - - pub fn e164(&self) -> String { - self.phonenumber - .format() - .mode(phonenumber::Mode::E164) - .to_string() - } - - pub fn login(&self) -> String { - let identifier = { - if let Some(uuid) = self.uuid.as_ref() { - uuid.to_string() - } else { - self.e164() - } - }; - - match self.device_id { - None | Some(DEFAULT_DEVICE_ID) => identifier, - Some(id) => format!("{}.{}", identifier, id), - } - } -} - -const SIGNAL_ROOT_CA: &str = r#"-----BEGIN CERTIFICATE----- -MIID7zCCAtegAwIBAgIJAIm6LatK5PNiMA0GCSqGSIb3DQEBBQUAMIGNMQswCQYDVQQGEwJVUzETMBEGA1UECAwKQ2FsaWZvcm5pYTEWMBQGA1UEBwwNU2FuIEZyYW5jaXNjbzEdMBsGA1UECgwUT3BlbiBXaGlzcGVyIFN5c3RlbXMxHTAbBgNVBAsMFE9wZW4gV2hpc3BlciBTeXN0ZW1zMRMwEQYDVQQDDApUZXh0U2VjdXJlMB4XDTEzMDMyNTIyMTgzNVoXDTIzMDMyMzIyMTgzNVowgY0xCzAJBgNVBAYTAlVTMRMwEQYDVQQIDApDYWxpZm9ybmlhMRYwFAYDVQQHDA1TYW4gRnJhbmNpc2NvMR0wGwYDVQQKDBRPcGVuIFdoaXNwZXIgU3lzdGVtczEdMBsGA1UECwwUT3BlbiBXaGlzcGVyIFN5c3RlbXMxEzARBgNVBAMMClRleHRTZWN1cmUwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDBSWBpOCBDF0i4q2d4jAXkSXUGpbeWugVPQCjaL6qD9QDOxeW1afvfPo863i6Crq1KDxHpB36EwzVcjwLkFTIMeo7t9s1FQolAt3mErV2U0vie6Ves+yj6grSfxwIDAcdsKmI0a1SQCZlr3Q1tcHAkAKFRxYNawADyps5B+Zmqcgf653TXS5/0IPPQLocLn8GWLwOYNnYfBvILKDMItmZTtEbucdigxEA9mfIvvHADEbteLtVgwBm9R5vVvtwrD6CCxI3pgH7EH7kMP0Od93wLisvn1yhHY7FuYlrkYqdkMvWUrKoASVw4jb69vaeJCUdU+HCoXOSP1PQcL6WenNCHAgMBAAGjUDBOMB0GA1UdDgQWBBQBixjxP/s5GURuhYa+lGUypzI8kDAfBgNVHSMEGDAWgBQBixjxP/s5GURuhYa+lGUypzI8kDAMBgNVHRMEBTADAQH/MA0GCSqGSIb3DQEBBQUAA4IBAQB+Hr4hC56m0LvJAu1RK6NuPDbTMEN7/jMojFHxH4P3XPFfupjR+bkDq0pPOU6JjIxnrD1XD/EVmTTaTVY5iOheyv7UzJOefb2pLOc9qsuvI4fnaESh9bhzln+LXxtCrRPGhkxA1IMIo3J/s2WF/KVYZyciu6b4ubJ91XPAuBNZwImug7/srWvbpk0hq6A6z140WTVSKtJG7EP41kJe/oF4usY5J7LPkxK3LWzMJnb5EIJDmRvyH8pyRwWg6Qm6qiGFaI4nL8QU4La1x2en4DGXRaLMPRwjELNgQPodR38zoCMuA8gHZfZYYoZ7D7Q1wNUiVHcxuFrEeBaYJbLErwLV ------END CERTIFICATE-----"#; - -#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)] -pub enum SignalServers { - Staging, - Production, -} - -#[derive(Debug)] -pub enum Endpoint { - Service, - Storage, - Cdn(u32), - ContactDiscovery, -} - -impl FromStr for SignalServers { - type Err = std::io::Error; - - fn from_str(s: &str) -> Result { - use std::io::ErrorKind; - match s { - "staging" => Ok(Self::Staging), - "production" => Ok(Self::Production), - _ => Err(Self::Err::new( - ErrorKind::InvalidInput, - "invalid signal servers, can be either: staging or production", - )), - } - } -} - -impl ToString for SignalServers { - fn to_string(&self) -> String { - match self { - Self::Staging => "staging", - Self::Production => "production", - } - .to_string() - } -} - -impl From for ServiceConfiguration { - fn from(val: SignalServers) -> Self { - ServiceConfiguration::from(&val) - } -} - -impl From<&SignalServers> for ServiceConfiguration { - fn from(val: &SignalServers) -> Self { - // base configuration from https://github.com/signalapp/Signal-Desktop/blob/development/config/default.json - match val { - // configuration with the Signal API staging endpoints - // see: https://github.com/signalapp/Signal-Desktop/blob/master/config/default.json - SignalServers::Staging => ServiceConfiguration { - service_url: "https://chat.staging.signal.org".parse().unwrap(), - storage_url:"https://storage-staging.signal.org".parse().unwrap(), - cdn_urls: { - let mut map = HashMap::new(); - map.insert(0, "https://cdn-staging.signal.org".parse().unwrap()); - map.insert(2, "https://cdn2-staging.signal.org".parse().unwrap()); - map - }, - contact_discovery_url: - "https://api-staging.directory.signal.org".parse().unwrap(), - certificate_authority: SIGNAL_ROOT_CA.into(), - unidentified_sender_trust_root: - "BbqY1DzohE4NUZoVF+L18oUPrK3kILllLEJh2UnPSsEx".into(), - zkgroup_server_public_params: bincode::deserialize(&base64::decode("ABSY21VckQcbSXVNCGRYJcfWHiAMZmpTtTELcDmxgdFbtp/bWsSxZdMKzfCp8rvIs8ocCU3B37fT3r4Mi5qAemeGeR2X+/YmOGR5ofui7tD5mDQfstAI9i+4WpMtIe8KC3wU5w3Inq3uNWVmoGtpKndsNfwJrCg0Hd9zmObhypUnSkfYn2ooMOOnBpfdanRtrvetZUayDMSC5iSRcXKpdls=").unwrap()).unwrap(), - }, - // configuration with the Signal API production endpoints - // https://github.com/signalapp/Signal-Desktop/blob/master/config/production.json - SignalServers::Production => ServiceConfiguration { - service_url: - "https://chat.signal.org".parse().unwrap(), - storage_url: "https://storage.signal.org".parse().unwrap(), - cdn_urls: { - let mut map = HashMap::new(); - map.insert(0, "https://cdn.signal.org".parse().unwrap()); - map.insert(2, "https://cdn2.signal.org".parse().unwrap()); - map - }, - contact_discovery_url: "https://api.directory.signal.org".parse().unwrap(), - certificate_authority: SIGNAL_ROOT_CA.into(), - unidentified_sender_trust_root: - "BXu6QIKVz5MA8gstzfOgRQGqyLqOwNKHL6INkv3IHWMF".into(), - zkgroup_server_public_params: bincode::deserialize( - &base64::decode("AMhf5ywVwITZMsff/eCyudZx9JDmkkkbV6PInzG4p8x3VqVJSFiMvnvlEKWuRob/1eaIetR31IYeAbm0NdOuHH8Qi+Rexi1wLlpzIo1gstHWBfZzy1+qHRV5A4TqPp15YzBPm0WSggW6PbSn+F4lf57VCnHF7p8SvzAA2ZZJPYJURt8X7bbg+H3i+PEjH9DXItNEqs2sNcug37xZQDLm7X0=").unwrap()).unwrap(), - }, - } - } -} - -impl ServiceConfiguration { - pub fn credentials_validator( - &self, - ) -> Result { - Ok(CertificateValidator::new(PublicKey::deserialize( - &base64::decode(&self.unidentified_sender_trust_root) - .map_err(|_| SealedSessionError::InvalidCertificate)?, - )?)) - } - - pub fn base_url(&self, endpoint: Endpoint) -> &Url { - match endpoint { - Endpoint::Service => &self.service_url, - Endpoint::Storage => &self.storage_url, - Endpoint::Cdn(ref n) => &self.cdn_urls[n], - Endpoint::ContactDiscovery => &self.contact_discovery_url, - } - } -} diff --git a/net/gurk-rs/files/vendor/libsignal-service/src/content.rs b/net/gurk-rs/files/vendor/libsignal-service/src/content.rs deleted file mode 100644 index 35b818a..0000000 --- a/net/gurk-rs/files/vendor/libsignal-service/src/content.rs +++ /dev/null @@ -1,112 +0,0 @@ -pub use crate::{ - proto::{ - attachment_pointer::Flags as AttachmentPointerFlags, - data_message::Flags as DataMessageFlags, data_message::Reaction, - group_context::Type as GroupType, sync_message, AttachmentPointer, - CallMessage, DataMessage, GroupContext, GroupContextV2, ReceiptMessage, - SyncMessage, TypingMessage, - }, - push_service::ServiceError, -}; - -#[derive(Clone, Debug)] -pub struct Metadata { - pub sender: crate::ServiceAddress, - pub sender_device: u32, - pub timestamp: u64, - pub needs_receipt: bool, -} - -#[derive(Clone, Debug)] -pub struct Content { - pub metadata: Metadata, - pub body: ContentBody, -} - -impl Content { - pub fn from_body(body: impl Into, metadata: Metadata) -> Self { - Self { - metadata, - body: body.into(), - } - } - - /// Converts a proto::Content into a public Content, including metadata. - pub(crate) fn from_proto( - p: crate::proto::Content, - metadata: Metadata, - ) -> Option { - // The Java version also assumes only one content type at a time. - // It's a bit sad that we cannot really match here, we've got no - // r#type() method. - // Allow the manual map (if let Some -> option.map(||)), because it - // reduces the git diff when more types would be added. - #[allow(clippy::manual_map)] - if let Some(msg) = p.data_message { - Some(Self::from_body(msg, metadata)) - } else if let Some(msg) = p.sync_message { - Some(Self::from_body(msg, metadata)) - } else if let Some(msg) = p.call_message { - Some(Self::from_body(msg, metadata)) - } else if let Some(msg) = p.receipt_message { - Some(Self::from_body(msg, metadata)) - } else if let Some(msg) = p.typing_message { - Some(Self::from_body(msg, metadata)) - } else { - None - } - } -} - -#[derive(Clone, Debug)] -#[allow(clippy::large_enum_variant)] -pub enum ContentBody { - DataMessage(DataMessage), - SynchronizeMessage(SyncMessage), - CallMessage(CallMessage), - ReceiptMessage(ReceiptMessage), - TypingMessage(TypingMessage), -} - -impl ContentBody { - pub fn into_proto(self) -> crate::proto::Content { - match self { - Self::DataMessage(msg) => crate::proto::Content { - data_message: Some(msg), - ..Default::default() - }, - Self::SynchronizeMessage(msg) => crate::proto::Content { - sync_message: Some(msg), - ..Default::default() - }, - Self::CallMessage(msg) => crate::proto::Content { - call_message: Some(msg), - ..Default::default() - }, - Self::ReceiptMessage(msg) => crate::proto::Content { - receipt_message: Some(msg), - ..Default::default() - }, - Self::TypingMessage(msg) => crate::proto::Content { - typing_message: Some(msg), - ..Default::default() - }, - } - } -} - -macro_rules! impl_from_for_content_body { - ($enum:ident ($t:ty)) => { - impl From<$t> for ContentBody { - fn from(inner: $t) -> ContentBody { - ContentBody::$enum(inner) - } - } - }; -} - -impl_from_for_content_body!(DataMessage(DataMessage)); -impl_from_for_content_body!(SynchronizeMessage(SyncMessage)); -impl_from_for_content_body!(CallMessage(CallMessage)); -impl_from_for_content_body!(ReceiptMessage(ReceiptMessage)); -impl_from_for_content_body!(TypingMessage(TypingMessage)); diff --git a/net/gurk-rs/files/vendor/libsignal-service/src/digeststream.rs b/net/gurk-rs/files/vendor/libsignal-service/src/digeststream.rs deleted file mode 100644 index 626caec..0000000 --- a/net/gurk-rs/files/vendor/libsignal-service/src/digeststream.rs +++ /dev/null @@ -1,31 +0,0 @@ -use std::io::Read; - -use sha2::{Digest, Sha256}; - -pub struct DigestingReader<'r, R> { - inner: &'r mut R, - digest: Sha256, -} - -impl<'r, R: Read> Read for DigestingReader<'r, R> { - fn read(&mut self, tgt: &mut [u8]) -> Result { - let amount = self.inner.read(tgt)?; - self.digest.update(&tgt[..amount]); - Ok(amount) - } -} - -impl<'r, R: Read> DigestingReader<'r, R> { - pub fn new(inner: &'r mut R) -> Self { - Self { - inner, - digest: Sha256::new(), - } - } - - pub fn finalize(self) -> Vec { - // XXX representation is not ideal, but this leaks to the public interface and I don't - // really like exposing the GenericArray. - Vec::from(self.digest.finalize().as_slice()) - } -} diff --git a/net/gurk-rs/files/vendor/libsignal-service/src/envelope.rs b/net/gurk-rs/files/vendor/libsignal-service/src/envelope.rs deleted file mode 100644 index af57f3f..0000000 --- a/net/gurk-rs/files/vendor/libsignal-service/src/envelope.rs +++ /dev/null @@ -1,246 +0,0 @@ -#![allow(dead_code)] // XXX: remove when all constants on bottom are used. - -use prost::Message; -use uuid::Uuid; - -use crate::{ - configuration::SignalingKey, push_service::ServiceError, - utils::serde_optional_base64, ParseServiceAddressError, ServiceAddress, -}; - -pub use crate::proto::Envelope; - -#[derive(thiserror::Error, Debug, Clone)] -pub enum EnvelopeParseError { - #[error("Supplied phone number could not be parsed in E164 format")] - InvalidPhoneNumber(#[from] phonenumber::ParseError), - - #[error("Supplied uuid could not be parsed")] - InvalidUuidError(#[from] uuid::Error), - - #[error("Envelope with neither Uuid or E164")] - NoSenderError, -} - -impl std::convert::TryFrom for Envelope { - type Error = EnvelopeParseError; - - fn try_from( - entity: EnvelopeEntity, - ) -> Result { - use ParseServiceAddressError::*; - if entity.source.is_none() && entity.source_uuid.is_none() { - return Err(EnvelopeParseError::NoSenderError); - } - - // XXX: throwing allocations like it's Java. - let source = ServiceAddress::parse( - entity.source.as_deref(), - entity.source_uuid.as_deref(), - ); - match source { - // Valid source - Ok(source) if entity.source_device > 0 => { - Ok(Envelope::new_with_source(entity, source)) - }, - // No source - Ok(_) | Err(NoSenderError) => Ok(Envelope::new_from_entity(entity)), - // Source specified, but unparsable - Err(InvalidPhoneNumber(e)) => { - Err(EnvelopeParseError::InvalidPhoneNumber(e)) - }, - Err(InvalidUuidError(e)) => { - Err(EnvelopeParseError::InvalidUuidError(e)) - }, - } - } -} - -impl Envelope { - pub fn decrypt( - input: &[u8], - signaling_key: &SignalingKey, - is_signaling_key_encrypted: bool, - ) -> Result { - if !is_signaling_key_encrypted { - log::trace!("Envelope::decrypt: not encrypted"); - Ok(Envelope::decode(input)?) - } else { - log::trace!("Envelope::decrypt: decrypting"); - if input.len() < VERSION_LENGTH - || input[VERSION_OFFSET] != SUPPORTED_VERSION - { - return Err(ServiceError::InvalidFrameError { - reason: "Unsupported signaling cryptogram version".into(), - }); - } - - let aes_key = &signaling_key[..CIPHER_KEY_SIZE]; - let mac_key = &signaling_key[CIPHER_KEY_SIZE..]; - let mac = &input[(input.len() - MAC_SIZE)..]; - let input_for_mac = &input[..(input.len() - MAC_SIZE)]; - let iv = &input[IV_OFFSET..(IV_OFFSET + IV_LENGTH)]; - debug_assert_eq!(mac_key.len(), MAC_KEY_SIZE); - debug_assert_eq!(aes_key.len(), CIPHER_KEY_SIZE); - debug_assert_eq!(iv.len(), IV_LENGTH); - - // Verify MAC - use hmac::{Hmac, Mac, NewMac}; - use sha2::Sha256; - let mut verifier = Hmac::::new_from_slice(mac_key) - .expect("Hmac can take any size key"); - verifier.update(input_for_mac); - // XXX: possible timing attack, but we need the bytes for a - // truncated view... - let our_mac = verifier.finalize().into_bytes(); - if &our_mac[..MAC_SIZE] != mac { - return Err(ServiceError::MacError); - } - - use aes::Aes256; - // libsignal-service-java uses Pkcs5, - // but that should not matter. - // https://crypto.stackexchange.com/questions/9043/what-is-the-difference-between-pkcs5-padding-and-pkcs7-padding - use block_modes::{block_padding::Pkcs7, BlockMode, Cbc}; - let cipher = Cbc::::new_from_slices(aes_key, iv) - .expect("initalization of CBC/AES/PKCS7"); - let input = &input[CIPHERTEXT_OFFSET..(input.len() - MAC_SIZE)]; - let input = cipher.decrypt_vec(input).expect("decryption"); - - log::trace!("Envelope::decrypt: decrypted, decoding"); - - Ok(Envelope::decode(&input as &[u8])?) - } - } - - fn new_from_entity(entity: EnvelopeEntity) -> Self { - Envelope { - r#type: Some(entity.r#type), - timestamp: Some(entity.timestamp), - server_timestamp: Some(entity.server_timestamp), - server_guid: entity.source_uuid, - legacy_message: entity.message, - content: entity.content, - ..Default::default() - } - } - - fn new_with_source(entity: EnvelopeEntity, source: ServiceAddress) -> Self { - Envelope { - r#type: Some(entity.r#type), - source_device: Some(entity.source_device), - timestamp: Some(entity.timestamp), - server_timestamp: Some(entity.server_timestamp), - source_e164: source.e164(), - source_uuid: source.uuid.as_ref().map(|s| s.to_string()), - legacy_message: entity.message, - content: entity.content, - ..Default::default() - } - } - - pub fn is_unidentified_sender(&self) -> bool { - self.r#type() == crate::proto::envelope::Type::UnidentifiedSender - } - - pub fn is_prekey_signal_message(&self) -> bool { - self.r#type() == crate::proto::envelope::Type::PrekeyBundle - } - - pub fn is_receipt(&self) -> bool { - self.r#type() == crate::proto::envelope::Type::Receipt - } - - pub fn is_signal_message(&self) -> bool { - self.r#type() == crate::proto::envelope::Type::Ciphertext - } - - pub fn source_address(&self) -> ServiceAddress { - let phonenumber = self - .source_e164 - .as_ref() - .map(|s| phonenumber::parse(None, s)) - .transpose() - .expect("valid e164 checked in constructor"); - - let uuid = self - .source_uuid - .as_deref() - .map(Uuid::parse_str) - .transpose() - .expect("valid e164 checked in constructor"); - ServiceAddress { - phonenumber, - uuid, - relay: self.relay.clone(), - } - } -} - -#[derive(serde::Serialize, serde::Deserialize)] -#[serde(rename_all = "camelCase")] -pub struct EnvelopeEntity { - pub r#type: i32, - pub relay: String, - pub timestamp: u64, - pub source: Option, - pub source_uuid: Option, - pub source_device: u32, - #[serde(default, with = "serde_optional_base64")] - pub message: Option>, - #[serde(default, with = "serde_optional_base64")] - pub content: Option>, - pub server_timestamp: u64, - pub guid: String, -} - -#[derive(serde::Serialize, serde::Deserialize)] -pub(crate) struct EnvelopeEntityList { - pub messages: Vec, -} - -pub(crate) const SUPPORTED_VERSION: u8 = 1; -pub(crate) const CIPHER_KEY_SIZE: usize = 32; -pub(crate) const MAC_KEY_SIZE: usize = 20; -pub(crate) const MAC_SIZE: usize = 10; - -pub(crate) const VERSION_OFFSET: usize = 0; -pub(crate) const VERSION_LENGTH: usize = 1; -pub(crate) const IV_OFFSET: usize = VERSION_OFFSET + VERSION_LENGTH; -pub(crate) const IV_LENGTH: usize = 16; -pub(crate) const CIPHERTEXT_OFFSET: usize = IV_OFFSET + IV_LENGTH; - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn decrypt_envelope() { - // This is a real message, reencrypted with the zero-key. - let body = [ - 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 79, 32, 12, 100, - 26, 157, 130, 210, 254, 174, 87, 45, 238, 126, 68, 39, 188, 171, - 156, 16, 10, 138, 233, 73, 202, 52, 125, 102, 121, 182, 71, 148, 8, - 3, 134, 149, 154, 67, 116, 40, 146, 253, 242, 196, 139, 203, 14, - 174, 254, 78, 27, 47, 108, 60, 202, 60, 42, 210, 242, 58, 13, 185, - 67, 147, 166, 191, 71, 164, 128, 81, 177, 199, 147, 252, 162, 229, - 143, 98, 141, 222, 46, 83, 109, 82, 196, 109, 161, 40, 108, 207, - 82, 53, 162, 205, 171, 33, 140, 5, 74, 76, 150, 22, 122, 176, 189, - 228, 176, 234, 176, 13, 118, 181, 134, 35, 133, 164, 160, 205, 176, - 32, 188, 185, 166, 73, 24, 164, 20, 187, 2, 226, 186, 238, 98, 57, - 51, 76, 156, 83, 113, 72, 184, 50, 220, 49, 138, 46, 36, 4, 49, - 215, 66, 173, 58, 139, 187, 6, 252, 97, 191, 69, 246, 82, 48, 177, - 11, 149, 168, 93, 15, 170, 125, 131, 101, 103, 253, 177, 165, 71, - 85, 219, 207, 106, 12, 58, 47, 159, 33, 243, 107, 6, 117, 141, 209, - 115, 207, 19, 236, 137, 195, 230, 167, 225, 172, 99, 204, 113, 125, - 69, 125, 97, 252, 90, 248, 198, 175, 240, 187, 246, 164, 220, 102, - 7, 224, 124, 28, 170, 6, 4, 137, 155, 233, 85, 125, 93, 119, 97, - 183, 114, 193, 10, 184, 191, 202, 109, 97, 116, 194, 152, 40, 46, - 202, 49, 195, 138, 14, 2, 255, 44, 107, 160, 45, 150, 6, 78, 145, - 99, - ]; - - let signaling_key = [0u8; 52]; - let _ = Envelope::decrypt(&body, &signaling_key, true).unwrap(); - } -} diff --git a/net/gurk-rs/files/vendor/libsignal-service/src/groups_v2/manager.rs b/net/gurk-rs/files/vendor/libsignal-service/src/groups_v2/manager.rs deleted file mode 100644 index 4ed7c13..0000000 --- a/net/gurk-rs/files/vendor/libsignal-service/src/groups_v2/manager.rs +++ /dev/null @@ -1,230 +0,0 @@ -use std::{ - collections::HashMap, - time::{SystemTime, UNIX_EPOCH}, -}; - -use crate::{ - configuration::Endpoint, - prelude::{PushService, ServiceError}, - proto::DecryptedGroup, - push_service::{HttpAuth, HttpAuthOverride}, -}; - -use rand::RngCore; -use serde::Deserialize; -use uuid::Uuid; -use zkgroup::{ - auth::AuthCredentialResponse, groups::GroupSecretParams, ServerPublicParams, -}; - -use super::operations::GroupOperations; - -#[derive(Debug, serde::Deserialize)] -#[serde(rename_all = "camelCase")] -pub struct TemporalCredential { - credential: String, - redemption_time: i64, -} - -#[derive(Deserialize)] -#[serde(rename_all = "camelCase")] -pub struct CredentialResponse { - credentials: Vec, -} - -impl CredentialResponse { - pub fn parse( - self, - ) -> Result, ServiceError> { - self.credentials - .into_iter() - .map(|c| { - let bytes = base64::decode(c.credential)?; - let data = bincode::deserialize(&bytes)?; - Ok((c.redemption_time, data)) - }) - .collect::>() - } -} - -#[derive(Debug, thiserror::Error)] -pub enum CredentialsCacheError { - #[error("failed to read values from cache: {0}")] - ReadError(String), - #[error("failed to write values from cache: {0}")] - WriteError(String), -} - -/// Global cache for groups v2 credentials, as demonstrated in the libsignal-service -/// java library of Signal-Android. -/// -/// A basic in-memory implementation is provided with `InMemoryCredentialsCache`. -pub trait CredentialsCache { - fn clear(&mut self) -> Result<(), CredentialsCacheError>; - - /// Get an entry of the cache, key usually represents the day number since EPOCH. - fn get( - &self, - key: &i64, - ) -> Result, CredentialsCacheError>; - - /// Overwrite the entire contents of the cache with new data. - fn write( - &mut self, - map: HashMap, - ) -> Result<(), CredentialsCacheError>; -} - -#[derive(Default)] -pub struct InMemoryCredentialsCache { - map: HashMap, -} - -impl CredentialsCache for InMemoryCredentialsCache { - fn clear(&mut self) -> Result<(), CredentialsCacheError> { - self.map.clear(); - Ok(()) - } - - fn get( - &self, - key: &i64, - ) -> Result, CredentialsCacheError> { - Ok(self.map.get(key)) - } - - fn write( - &mut self, - map: HashMap, - ) -> Result<(), CredentialsCacheError> { - self.map = map; - Ok(()) - } -} - -pub struct GroupsManager<'a, S: PushService, C: CredentialsCache> { - push_service: S, - credentials_cache: &'a mut C, - server_public_params: ServerPublicParams, -} - -impl<'a, S: PushService, C: CredentialsCache> GroupsManager<'a, S, C> { - pub fn new( - push_service: S, - credentials_cache: &'a mut C, - server_public_params: ServerPublicParams, - ) -> Self { - Self { - push_service, - credentials_cache, - server_public_params, - } - } - - pub async fn get_authorization_for_today( - &mut self, - uuid: Uuid, - group_secret_params: GroupSecretParams, - ) -> Result { - let today = Self::current_time_days(); - let auth_credential_response = if let Some(auth_credential_response) = - self.credentials_cache.get(&today)? - { - auth_credential_response - } else { - let credentials_map = - self.get_authorization(today).await?.parse()?; - self.credentials_cache.write(credentials_map)?; - self.credentials_cache.get(&today)?.ok_or_else(|| { - ServiceError::ResponseError { - reason: - "credentials received did not contain requested day" - .into(), - } - })? - }; - - self.get_authorization_string( - uuid, - group_secret_params, - auth_credential_response, - today as u32, - ) - } - - async fn get_authorization( - &mut self, - today: i64, - ) -> Result { - let today_plus_7_days = today + 7; - - let path = - format!("/v1/certificate/group/{}/{}", today, today_plus_7_days); - - self.push_service - .get_json(Endpoint::Service, &path, HttpAuthOverride::NoOverride) - .await - } - - fn current_time_days() -> i64 { - let now = SystemTime::now().duration_since(UNIX_EPOCH).unwrap(); - let today = chrono::Duration::from_std(now).unwrap(); - today.num_days() - } - - fn get_authorization_string( - &self, - uuid: Uuid, - group_secret_params: GroupSecretParams, - credential_response: &AuthCredentialResponse, - today: u32, - ) -> Result { - let auth_credential = self - .server_public_params - .receive_auth_credential( - *uuid.as_bytes(), - today, - credential_response, - ) - .map_err(|e| { - log::error!("zero-knowledge group error: {:?}", e); - ServiceError::GroupsV2Error - })?; - - let mut random_bytes = [0u8; 32]; - rand::thread_rng().fill_bytes(&mut random_bytes); - - let auth_credential_presentation = self - .server_public_params - .create_auth_credential_presentation( - random_bytes, - group_secret_params, - auth_credential, - ); - - // see simpleapi.rs GroupSecretParams_getPublicParams, everything is bincode encoded - // across the boundary of Rust/Java - let username = hex::encode(bincode::serialize( - &group_secret_params.get_public_params(), - )?); - - let password = - hex::encode(bincode::serialize(&auth_credential_presentation)?); - - Ok(HttpAuth { username, password }) - } - - pub async fn get_group( - &mut self, - group_secret_params: GroupSecretParams, - credentials: HttpAuth, - ) -> Result { - let encrypted_group = self.push_service.get_group(credentials).await?; - let decrypted_group = GroupOperations::decrypt_group( - group_secret_params, - encrypted_group, - )?; - - Ok(decrypted_group) - } -} diff --git a/net/gurk-rs/files/vendor/libsignal-service/src/groups_v2/mod.rs b/net/gurk-rs/files/vendor/libsignal-service/src/groups_v2/mod.rs deleted file mode 100644 index 5d96264..0000000 --- a/net/gurk-rs/files/vendor/libsignal-service/src/groups_v2/mod.rs +++ /dev/null @@ -1,10 +0,0 @@ -//! Everything needed to support [Signal Groups v2](https://signal.org/blog/new-groups/) -mod manager; -mod operations; -pub mod utils; - -pub use manager::{ - CredentialsCache, CredentialsCacheError, GroupsManager, - InMemoryCredentialsCache, -}; -pub use operations::GroupDecryptionError; diff --git a/net/gurk-rs/files/vendor/libsignal-service/src/groups_v2/operations.rs b/net/gurk-rs/files/vendor/libsignal-service/src/groups_v2/operations.rs deleted file mode 100644 index 9a60efd..0000000 --- a/net/gurk-rs/files/vendor/libsignal-service/src/groups_v2/operations.rs +++ /dev/null @@ -1,229 +0,0 @@ -use bytes::Bytes; -use prost::Message; -use zkgroup::{ - groups::GroupSecretParams, - profiles::{ProfileKey, ProfileKeyCredentialPresentation}, -}; - -use crate::proto::{ - group_attribute_blob, DecryptedGroup, DecryptedMember, - DecryptedPendingMember, DecryptedRequestingMember, DecryptedTimer, - Group as EncryptedGroup, GroupAttributeBlob, Member as EncryptedMember, - PendingMember as EncryptedPendingMember, - RequestingMember as EncryptedRequestingMember, -}; - -pub(crate) struct GroupOperations { - group_secret_params: GroupSecretParams, -} - -#[derive(Debug, thiserror::Error)] -pub enum GroupDecryptionError { - #[error("zero-knowledge group error")] - ZkGroupError, - #[error(transparent)] - BincodeError(#[from] bincode::Error), - #[error("protobuf message decoding error: {0}")] - ProtobufDecodeError(#[from] prost::DecodeError), - #[error("wrong group attribute blob")] - WrongBlob, -} - -impl From for GroupDecryptionError { - fn from(_: zkgroup::ZkGroupError) -> Self { - GroupDecryptionError::ZkGroupError - } -} - -impl GroupOperations { - fn decrypt_uuid( - &self, - uuid: &[u8], - ) -> Result<[u8; 16], GroupDecryptionError> { - let bytes = self - .group_secret_params - .decrypt_uuid(bincode::deserialize(uuid)?) - .map_err(|_| GroupDecryptionError::ZkGroupError)?; - Ok(bytes) - } - - fn decrypt_profile_key( - &self, - profile_key: &[u8], - decrypted_uuid: [u8; 16], - ) -> Result { - Ok(self.group_secret_params.decrypt_profile_key( - bincode::deserialize(profile_key)?, - decrypted_uuid, - )?) - } - - fn decrypt_member( - &self, - member: EncryptedMember, - ) -> Result { - let (uuid, profile_key) = if member.presentation.is_empty() { - let uuid = self.decrypt_uuid(&member.user_id)?; - let profile_key = - self.decrypt_profile_key(&member.profile_key, uuid)?; - (uuid, profile_key) - } else { - let profile_key_credential_presentation: ProfileKeyCredentialPresentation = bincode::deserialize(&member.presentation)?; - let uuid = self.group_secret_params.decrypt_uuid( - profile_key_credential_presentation.get_uuid_ciphertext(), - )?; - let profile_key = self.group_secret_params.decrypt_profile_key( - profile_key_credential_presentation - .get_profile_key_ciphertext(), - uuid, - )?; - (uuid, profile_key) - }; - Ok(DecryptedMember { - uuid: uuid.to_vec(), - profile_key: bincode::serialize(&profile_key)?, - role: member.role, - joined_at_revision: member.joined_at_revision, - }) - } - - fn decrypt_pending_member( - &self, - member: EncryptedPendingMember, - ) -> Result { - let inner_member = - member.member.ok_or(GroupDecryptionError::WrongBlob)?; - // "Unknown" UUID with zeroes in case of errors, see: UuidUtil.java:16 - let uuid = self.decrypt_uuid(&inner_member.user_id).unwrap_or_default(); - let added_by = self.decrypt_uuid(&member.added_by_user_id)?; - - Ok(DecryptedPendingMember { - uuid: uuid.to_vec(), - role: inner_member.role, - added_by_uuid: added_by.to_vec(), - timestamp: member.timestamp, - uuid_cipher_text: inner_member.user_id, - }) - } - - fn decrypt_requesting_member( - &self, - member: EncryptedRequestingMember, - ) -> Result { - let (uuid, profile_key) = if member.presentation.is_empty() { - let uuid = self.decrypt_uuid(&member.user_id)?; - let profile_key = - self.decrypt_profile_key(&member.profile_key, uuid)?; - (uuid, profile_key) - } else { - let profile_key_credential_presentation: ProfileKeyCredentialPresentation = bincode::deserialize(&member.presentation)?; - let uuid = self.group_secret_params.decrypt_uuid( - profile_key_credential_presentation.get_uuid_ciphertext(), - )?; - let profile_key = self.group_secret_params.decrypt_profile_key( - profile_key_credential_presentation - .get_profile_key_ciphertext(), - uuid, - )?; - (uuid, profile_key) - }; - Ok(DecryptedRequestingMember { - profile_key: bincode::serialize(&profile_key)?, - uuid: uuid.to_vec(), - timestamp: member.timestamp, - }) - } - - fn decrypt_blob(&self, bytes: &[u8]) -> GroupAttributeBlob { - if bytes.is_empty() { - GroupAttributeBlob::default() - } else if bytes.len() < 29 { - log::warn!("bad encrypted blob length"); - GroupAttributeBlob::default() - } else { - self.group_secret_params - .decrypt_blob(bytes) - .map_err(|_| GroupDecryptionError::ZkGroupError) - .and_then(|b| { - GroupAttributeBlob::decode(Bytes::copy_from_slice(&b[4..])) - .map_err(GroupDecryptionError::ProtobufDecodeError) - }) - .unwrap_or_else(|e| { - log::warn!("bad encrypted blob: {}", e); - GroupAttributeBlob::default() - }) - } - } - - fn decrypt_title(&self, ciphertext: &[u8]) -> String { - use group_attribute_blob::Content; - match self.decrypt_blob(ciphertext).content { - Some(Content::Title(title)) => title, - _ => "".into(), // TODO: return an error here? - } - } - - fn decrypt_description(&self, ciphertext: &[u8]) -> String { - use group_attribute_blob::Content; - match self.decrypt_blob(ciphertext).content { - Some(Content::Description(title)) => title, - _ => "".into(), // TODO: return an error here? - } - } - - fn decrypt_disappearing_message_timer( - &self, - ciphertext: &[u8], - ) -> Option { - use group_attribute_blob::Content; - match self.decrypt_blob(ciphertext).content { - Some(Content::DisappearingMessagesDuration(duration)) => { - Some(DecryptedTimer { duration }) - }, - _ => None, - } - } - - pub fn decrypt_group( - group_secret_params: GroupSecretParams, - group: EncryptedGroup, - ) -> Result { - let group_operations = Self { - group_secret_params, - }; - let title = group_operations.decrypt_title(&group.title); - let description = - group_operations.decrypt_description(&group.description); - let disappearing_messages_timer = group_operations - .decrypt_disappearing_message_timer( - &group.disappearing_messages_timer, - ); - let members = group - .members - .into_iter() - .map(|m| group_operations.decrypt_member(m)) - .collect::>()?; - let pending_members = group - .pending_members - .into_iter() - .map(|m| group_operations.decrypt_pending_member(m)) - .collect::>()?; - let requesting_members = group - .requesting_members - .into_iter() - .map(|m| group_operations.decrypt_requesting_member(m)) - .collect::>()?; - Ok(DecryptedGroup { - title, - avatar: group.avatar, - disappearing_messages_timer, - access_control: group.access_control, - revision: group.revision, - members, - pending_members, - requesting_members, - invite_link_password: group.invite_link_password, - description, - }) - } -} diff --git a/net/gurk-rs/files/vendor/libsignal-service/src/groups_v2/utils.rs b/net/gurk-rs/files/vendor/libsignal-service/src/groups_v2/utils.rs deleted file mode 100644 index c731236..0000000 --- a/net/gurk-rs/files/vendor/libsignal-service/src/groups_v2/utils.rs +++ /dev/null @@ -1,18 +0,0 @@ -use libsignal_protocol::error::SignalProtocolError; -use zkgroup::groups::GroupMasterKey; -use zkgroup::GROUP_MASTER_KEY_LEN; - -/// Given a 16-byte GroupV1 ID, derive the migration key. -/// -/// Panics if the group_id is not 16 bytes long. -pub fn derive_v2_migration_master_key( - group_id: &[u8], -) -> Result { - assert_eq!(group_id.len(), 16, "Group ID must be exactly 16 bytes"); - - let mut bytes = [0; GROUP_MASTER_KEY_LEN]; - hkdf::Hkdf::::new(None, group_id) - .expand(b"GV2 Migration", &mut bytes) - .expect("valid output length"); - Ok(GroupMasterKey::new(bytes)) -} diff --git a/net/gurk-rs/files/vendor/libsignal-service/src/kat.bin.rs b/net/gurk-rs/files/vendor/libsignal-service/src/kat.bin.rs deleted file mode 100644 index 71f9c5b..0000000 --- a/net/gurk-rs/files/vendor/libsignal-service/src/kat.bin.rs +++ /dev/null @@ -1,44 +0,0 @@ -vec![ - 49, 179, 68, 75, 164, 216, 109, 15, 131, 54, 38, 23, 120, 221, 36, - 66, 191, 65, 137, 85, 175, 13, 209, 217, 219, 46, 103, 95, 73, 181, - 31, 75, 36, 113, 103, 0, 91, 81, 71, 168, 66, 209, 100, 66, 80, - 157, 170, 63, 118, 175, 214, 201, 135, 71, 166, 8, 152, 129, 220, - 68, 248, 127, 66, 144, 215, 43, 80, 230, 254, 233, 27, 71, 111, 61, - 131, 101, 197, 107, 52, 12, 241, 100, 29, 117, 200, 115, 243, 113, - 86, 86, 232, 161, 147, 61, 213, 221, 177, 148, 118, 202, 208, 184, - 251, 213, 21, 255, 54, 49, 51, 197, 45, 216, 236, 77, 197, 218, - 178, 56, 219, 246, 136, 24, 100, 173, 178, 74, 184, 92, 239, 181, - 95, 91, 7, 128, 37, 205, 19, 152, 167, 46, 10, 151, 235, 168, 2, - 247, 79, 33, 252, 139, 191, 98, 40, 201, 232, 43, 54, 228, 234, - 241, 94, 157, 59, 196, 25, 15, 94, 38, 247, 203, 66, 196, 71, 166, - 196, 58, 193, 13, 139, 141, 171, 86, 187, 44, 144, 22, 89, 143, - 100, 193, 190, 161, 227, 29, 109, 68, 176, 194, 73, 169, 135, 200, - 208, 235, 99, 173, 45, 149, 116, 197, 76, 113, 198, 178, 118, 164, - 189, 135, 52, 223, 92, 229, 169, 227, 89, 58, 10, 238, 124, 46, - 175, 183, 73, 57, 140, 79, 252, 76, 170, 217, 199, 165, 204, 44, - 114, 114, 240, 207, 249, 205, 0, 22, 167, 167, 136, 173, 220, 250, - 109, 136, 124, 232, 26, 204, 146, 151, 232, 130, 151, 43, 16, 119, - 77, 246, 96, 38, 81, 13, 2, 151, 147, 76, 32, 79, 80, 23, 181, 6, - 188, 254, 24, 9, 139, 238, 141, 224, 215, 160, 133, 179, 131, 153, - 121, 72, 165, 204, 50, 86, 248, 209, 90, 46, 100, 197, 86, 230, - 124, 151, 167, 218, 236, 77, 188, 153, 255, 33, 237, 97, 194, 193, - 153, 149, 221, 35, 22, 114, 43, 64, 110, 204, 241, 176, 6, 168, 25, - 46, 166, 10, 242, 26, 130, 97, 236, 255, 166, 75, 222, 205, 25, - 212, 114, 203, 10, 242, 220, 230, 81, 3, 226, 233, 35, 1, 42, 11, - 25, 35, 83, 188, 38, 215, 191, 78, 72, 85, 51, 32, 219, 104, 135, - 79, 35, 152, 62, 138, 243, 181, 57, 222, 246, 45, 164, 134, 60, - 162, 177, 220, 218, 58, 52, 148, 8, 177, 119, 69, 6, 5, 253, 20, - 56, 50, 100, 161, 89, 145, 91, 119, 16, 24, 231, 76, 120, 96, 183, - 63, 87, 117, 12, 126, 50, 205, 89, 42, 107, 115, 64, 147, 180, 164, - 208, 173, 15, 241, 128, 130, 205, 199, 52, 31, 176, 77, 197, 149, - 114, 115, 197, 22, 214, 30, 243, 246, 204, 10, 178, 124, 225, 249, - 44, 18, 143, 243, 178, 46, 166, 61, 174, 136, 155, 61, 228, 59, - 219, 242, 240, 121, 15, 131, 163, 94, 79, 173, 198, 9, 110, 64, - 222, 32, 234, 172, 29, 10, 158, 114, 53, 161, 200, 144, 174, 161, - 180, 34, 245, 51, 44, 139, 138, 168, 231, 139, 105, 126, 5, 143, - 83, 186, 101, 66, 19, 1, 15, 129, 173, 239, 102, 150, 97, 189, 191, - 128, 136, 183, 242, 163, 137, 146, 134, 133, 72, 81, 243, 245, 100, - 115, 70, 27, 98, 227, 146, 35, 198, 3, 35, 236, 236, 104, 103, 100, - 148, 183, 133, 25, 37, 224, 29, 234, 248, 26, 209, 199, 34, 52, 82, - 167, -] diff --git a/net/gurk-rs/files/vendor/libsignal-service/src/lib.rs b/net/gurk-rs/files/vendor/libsignal-service/src/lib.rs deleted file mode 100644 index d2a6b29..0000000 --- a/net/gurk-rs/files/vendor/libsignal-service/src/lib.rs +++ /dev/null @@ -1,93 +0,0 @@ -#![recursion_limit = "256"] -#![deny(clippy::dbg_macro)] - -mod account_manager; -pub mod attachment_cipher; -pub mod cipher; -pub mod profile_cipher; -pub mod sealed_session_cipher; - -pub mod configuration; -pub mod content; -mod digeststream; -pub mod envelope; -pub mod groups_v2; -pub mod messagepipe; -pub mod models; -pub mod pre_keys; -pub mod profile_name; -pub mod proto; -pub mod provisioning; -pub mod push_service; -pub mod receiver; -pub mod sender; -pub mod service_address; -mod session_store; -pub mod utils; - -pub use crate::account_manager::{ - AccountManager, Profile, ProfileManagerError, -}; -pub use crate::service_address::*; - -pub const USER_AGENT: &str = - concat!(env!("CARGO_PKG_NAME"), "-rs-", env!("CARGO_PKG_VERSION")); - -/// GROUP_UPDATE_FLAG signals that this message updates the group membership or -/// name. -pub const GROUP_UPDATE_FLAG: u32 = 1; - -/// GROUP_LEAVE_FLAG signals that this message is a group leave message. -pub const GROUP_LEAVE_FLAG: u32 = 2; - -/// This trait allows for the conditional support of Send compatible futures -/// depending on whether or not the `unsend-futures` feature flag is enabled. -/// As this feature is disabled by default, Send is supported by default. -/// -/// This is necessary as actix does not support Send, which means unconditionally -/// imposing this requirement would break libsignal-service-actix. -/// -/// Conversely, hyper does support Send, which is why libsignal-service-hyper -/// does not enable the `unsend-futures` feature flag. -#[cfg(not(feature = "unsend-futures"))] -pub trait MaybeSend: Send {} -#[cfg(not(feature = "unsend-futures"))] -impl MaybeSend for T where T: Send {} - -#[cfg(feature = "unsend-futures")] -pub trait MaybeSend {} -#[cfg(feature = "unsend-futures")] -impl MaybeSend for T {} - -pub mod prelude { - pub use super::ServiceAddress; - pub use crate::{ - cipher::ServiceCipher, - configuration::{ - ServiceConfiguration, ServiceCredentials, SignalingKey, - }, - content::Content, - envelope::Envelope, - proto::{ - attachment_pointer::AttachmentIdentifier, sync_message::Contacts, - AttachmentPointer, - }, - push_service::{PushService, ServiceError}, - receiver::MessageReceiver, - sender::{MessageSender, MessageSenderError}, - }; - pub use phonenumber; - pub use prost::Message as ProtobufMessage; - pub use uuid::{Error as UuidError, Uuid}; - pub use zkgroup::groups::{GroupMasterKey, GroupSecretParams}; - - pub mod protocol { - pub use crate::session_store::SessionStoreExt; - pub use libsignal_protocol::{ - Context, Direction, IdentityKey, IdentityKeyPair, IdentityKeyStore, - KeyPair, PreKeyRecord, PreKeyStore, PrivateKey, ProtocolAddress, - PublicKey, SessionRecord, SessionStore, SignalProtocolError, - SignedPreKeyRecord, SignedPreKeyStore, - }; - } -} diff --git a/net/gurk-rs/files/vendor/libsignal-service/src/messagepipe.rs b/net/gurk-rs/files/vendor/libsignal-service/src/messagepipe.rs deleted file mode 100644 index e1d332a..0000000 --- a/net/gurk-rs/files/vendor/libsignal-service/src/messagepipe.rs +++ /dev/null @@ -1,306 +0,0 @@ -use std::collections::HashMap; - -use bytes::Bytes; -use futures::{ - channel::{ - mpsc::{self, Sender}, - oneshot, - }, - prelude::*, - stream::{FusedStream, FuturesUnordered}, -}; -use pin_project::pin_project; -use prost::Message; - -pub use crate::{ - configuration::ServiceCredentials, - proto::{ - web_socket_message, Envelope, WebSocketMessage, - WebSocketRequestMessage, WebSocketResponseMessage, - }, -}; - -use crate::push_service::ServiceError; - -pub enum WebSocketStreamItem { - Message(Bytes), - KeepAliveRequest, -} - -#[cfg_attr(feature = "unsend-futures", async_trait::async_trait(?Send))] -#[cfg_attr(not(feature = "unsend-futures"), async_trait::async_trait)] -pub trait WebSocketService { - type Stream: FusedStream + Unpin; - - async fn send_message(&mut self, msg: Bytes) -> Result<(), ServiceError>; -} - -#[pin_project] -pub struct MessagePipe { - ws: WS, - #[pin] - stream: WS::Stream, - credentials: ServiceCredentials, - requests: HashMap>, -} - -impl MessagePipe { - pub fn from_socket( - ws: WS, - stream: WS::Stream, - credentials: ServiceCredentials, - ) -> Self { - MessagePipe { - ws, - stream, - credentials, - requests: HashMap::new(), - } - } - - async fn send_response( - &mut self, - r: WebSocketResponseMessage, - ) -> Result<(), ServiceError> { - let msg = WebSocketMessage { - r#type: Some(web_socket_message::Type::Response.into()), - response: Some(r), - ..Default::default() - }; - let buffer = msg.encode_to_vec(); - self.ws.send_message(buffer.into()).await - } - - /// Sends a request without returning a response. - async fn transmit_request( - &mut self, - r: WebSocketRequestMessage, - ) -> Result<(), ServiceError> { - log::trace!("Sending request {:?}", r); - let msg = WebSocketMessage { - r#type: Some(web_socket_message::Type::Request.into()), - request: Some(r), - ..Default::default() - }; - let buffer = msg.encode_to_vec(); - self.ws.send_message(buffer.into()).await?; - log::trace!("request on route."); - Ok(()) - } - - /// Send request and returns the response as a *nested* Future. - /// - /// The outer Future sends the request, the inner Future resolves to the - /// response. - pub async fn send_request( - &mut self, - r: WebSocketRequestMessage, - ) -> Result< - impl Future>, - ServiceError, - > { - let id = r.id; - - self.transmit_request(r).await?; - - let (sink, send) = oneshot::channel(); - - if let Some(id) = id { - self.requests.insert(id, sink); - Ok(send.map_err(|_| ServiceError::WsClosing { - reason: "WebSocket closing while sending request.".into(), - })) - } else { - Err(ServiceError::InvalidFrameError { - reason: "Send request without ID".into(), - }) - } - } - - /// Worker task that - async fn run( - mut self, - mut sink: Sender>, - ) -> Result<(), mpsc::SendError> { - use futures::future::LocalBoxFuture; - - // This is a runtime-agnostic, poor man's `::spawn(Future)`. - let mut background_work = FuturesUnordered::>::new(); - // a pending task is added, as to never end the background worker until - // it's dropped. - background_work.push(futures::future::pending().boxed_local()); - - loop { - futures::select! { - // WebsocketConnection::onMessage(ByteString) - frame = self.stream.next() => match frame { - Some(WebSocketStreamItem::Message(frame)) => { - let env = self.process_frame(frame).await.transpose(); - if let Some(env) = env { - sink.send(env).await?; - } - }, - Some(WebSocketStreamItem::KeepAliveRequest) => { - let request = self.send_keep_alive().await; - match request { - Ok(request) => { - let request = request.map(|response| { - if let Err(e) = response { - log::warn!("Error from keep alive: {:?}", e); - } - }); - background_work.push(request.boxed_local()); - }, - Err(e) => log::warn!("Could not send keep alive: {}", e), - } - }, - None => { - log::debug!("WebSocket stream ended."); - break; - }, - }, - _ = background_work.next() => { - // no op - }, - complete => { - log::info!("select! complete"); - } - } - } - - Ok(()) - } - - async fn send_keep_alive( - &mut self, - ) -> Result>, ServiceError> - { - let request = WebSocketRequestMessage { - id: Some( - std::time::SystemTime::now() - .duration_since(std::time::UNIX_EPOCH) - .unwrap() - .as_millis() as u64, - ), - path: Some("/v1/keepalive".into()), - verb: Some("GET".into()), - ..Default::default() - }; - let request = self.send_request(request).await?; - Ok(async move { - let response = request.await?; - if response.status() == 200 { - Ok(()) - } else { - log::warn!( - "Response code for keep-alive is not 200: {:?}", - response - ); - Err(ServiceError::UnhandledResponseCode { - http_code: response.status() as u16, - }) - } - }) - } - - async fn process_frame( - &mut self, - frame: Bytes, - ) -> Result, ServiceError> { - let msg = WebSocketMessage::decode(frame)?; - log::trace!("Decoded {:?}", msg); - - use web_socket_message::Type; - match (msg.r#type(), msg.request, msg.response) { - (Type::Unknown, _, _) => Err(ServiceError::InvalidFrameError { - reason: "Unknown frame type".into(), - }), - (Type::Request, Some(request), _) => { - // Java: MessagePipe::read - let response = WebSocketResponseMessage::from_request(&request); - - let result = if request.is_signal_service_envelope() { - let body = if let Some(body) = request.body.as_ref() { - body - } else { - return Err(ServiceError::InvalidFrameError { - reason: "Request without body.".into(), - }); - }; - Some(Envelope::decrypt( - body, - self.credentials.signaling_key.as_ref().expect( - "signaling_key required to decrypt envelopes", - ), - request.is_signal_key_encrypted(), - )?) - } else { - None - }; - - if let Err(e) = self.send_response(response).await { - log::error!("Could not send response: {}", e); - } - - Ok(result) - }, - (Type::Request, None, _) => Err(ServiceError::InvalidFrameError { - reason: "Type was request, but does not contain request." - .into(), - }), - (Type::Response, _, Some(response)) => { - if let Some(id) = response.id { - if let Some(responder) = self.requests.remove(&id) { - if let Err(e) = responder.send(response) { - log::warn!( - "Could not deliver response for id {}: {:?}", - id, - e - ); - } - } else { - log::warn!( - "Response for non existing request: {:?}", - response - ); - } - } - - Ok(None) - }, - (Type::Response, _, None) => Err(ServiceError::InvalidFrameError { - reason: "Type was response, but does not contain response." - .into(), - }), - } - } - - /// Returns the stream of `Envelope`s - /// - /// Envelopes yielded are acknowledged. - pub fn stream(self) -> impl Stream> { - let (sink, stream) = mpsc::channel(1); - - let stream = stream.map(Some); - let runner = self.run(sink).map(|e| { - log::info!("Sink was closed. Reason: {:?}", e); - None - }); - - let combined = futures::stream::select(stream, runner.into_stream()); - combined.filter_map(|x| async { x }) - } -} - -/// WebSocketService that panics on every request, mainly for example code. -pub struct PanicingWebSocketService; - -#[cfg_attr(feature = "unsend-futures", async_trait::async_trait(?Send))] -#[cfg_attr(not(feature = "unsend-futures"), async_trait::async_trait)] -impl WebSocketService for PanicingWebSocketService { - type Stream = futures::channel::mpsc::Receiver; - - async fn send_message(&mut self, _msg: Bytes) -> Result<(), ServiceError> { - unimplemented!(); - } -} diff --git a/net/gurk-rs/files/vendor/libsignal-service/src/models.rs b/net/gurk-rs/files/vendor/libsignal-service/src/models.rs deleted file mode 100644 index 5246841..0000000 --- a/net/gurk-rs/files/vendor/libsignal-service/src/models.rs +++ /dev/null @@ -1,78 +0,0 @@ -use crate::{proto::Verified, ParseServiceAddressError, ServiceAddress}; - -use bytes::Bytes; -use serde::{Deserialize, Serialize}; -use thiserror::Error; - -/// Attachment represents an attachment received from a peer -#[derive(Debug, Serialize, Deserialize)] -pub struct Attachment { - pub content_type: String, - pub reader: R, -} - -/// Mirror of the protobuf ContactDetails message -/// but with stronger types (e.g. `ServiceAddress` instead of optional uuid and string phone numbers) -/// and some helper functions -#[derive(Debug, Serialize, Deserialize)] -pub struct Contact { - pub address: ServiceAddress, - pub name: String, - pub color: Option, - #[serde(skip)] - pub verified: Verified, - pub profile_key: Vec, - pub blocked: bool, - pub expire_timer: u32, - pub inbox_position: u32, - pub archived: bool, - #[serde(skip)] - pub avatar: Option>, -} - -#[derive(Error, Debug)] -pub enum ParseContactError { - #[error(transparent)] - ProtobufError(#[from] prost::DecodeError), - #[error(transparent)] - ServiceAddress(#[from] ParseServiceAddressError), - #[error("missing profile key")] - MissingProfileKey, - #[error("missing avatar content-type")] - MissingAvatarContentType, -} - -impl Contact { - pub fn from_proto( - contact_details: crate::proto::ContactDetails, - avatar_data: Option, - ) -> Result { - Ok(Self { - address: ServiceAddress::parse( - contact_details.number.as_deref(), - contact_details.uuid.as_deref(), - )?, - name: contact_details.name().into(), - color: contact_details.color.clone(), - verified: contact_details.verified.clone().unwrap_or_default(), - profile_key: contact_details.profile_key().to_vec(), - blocked: contact_details.blocked(), - expire_timer: contact_details.expire_timer(), - inbox_position: contact_details.inbox_position(), - archived: contact_details.archived(), - avatar: contact_details.avatar.and_then(|avatar| { - if let (Some(content_type), Some(avatar_data)) = - (avatar.content_type, avatar_data) - { - Some(Attachment { - content_type, - reader: avatar_data, - }) - } else { - log::warn!("missing avatar content-type, skipping."); - None - } - }), - }) - } -} diff --git a/net/gurk-rs/files/vendor/libsignal-service/src/pre_keys.rs b/net/gurk-rs/files/vendor/libsignal-service/src/pre_keys.rs deleted file mode 100644 index 5ed0aed..0000000 --- a/net/gurk-rs/files/vendor/libsignal-service/src/pre_keys.rs +++ /dev/null @@ -1,70 +0,0 @@ -use std::convert::TryFrom; - -use crate::utils::{serde_base64, serde_public_key}; -use libsignal_protocol::{ - error::SignalProtocolError, PreKeyRecord, PublicKey, SignedPreKeyRecord, -}; - -use serde::{Deserialize, Serialize}; - -#[derive(Debug, Deserialize, Serialize)] -#[serde(rename_all = "camelCase")] -pub struct PreKeyEntity { - pub key_id: u32, - #[serde(with = "serde_base64")] - pub public_key: Vec, -} - -impl TryFrom for PreKeyEntity { - type Error = SignalProtocolError; - - fn try_from(key: PreKeyRecord) -> Result { - Ok(PreKeyEntity { - key_id: key.id()?, - public_key: key.key_pair()?.public_key.serialize().to_vec(), - }) - } -} - -#[derive(Debug, Deserialize)] -#[serde(rename_all = "camelCase")] -pub struct SignedPreKeyEntity { - pub key_id: u32, - #[serde(with = "serde_base64")] - pub public_key: Vec, - #[serde(with = "serde_base64")] - pub signature: Vec, -} - -#[derive(Debug, Serialize)] -#[serde(rename_all = "camelCase")] -pub struct SignedPreKey { - key_id: u32, - #[serde(with = "serde_public_key")] - public_key: PublicKey, - #[serde(with = "serde_base64")] - signature: Vec, -} - -impl TryFrom for SignedPreKey { - type Error = SignalProtocolError; - - fn try_from(key: SignedPreKeyRecord) -> Result { - Ok(SignedPreKey { - key_id: key.id()?, - public_key: key.key_pair()?.public_key, - signature: key.signature()?, - }) - } -} - -#[derive(Debug, Serialize)] -#[serde(rename_all = "camelCase")] -pub struct PreKeyState { - pub pre_keys: Vec, - pub signed_pre_key: SignedPreKey, - #[serde(with = "serde_public_key")] - pub identity_key: PublicKey, - #[serde(skip_serializing_if = "Option::is_none")] - pub last_resort_key: Option, -} diff --git a/net/gurk-rs/files/vendor/libsignal-service/src/profile_cipher.rs b/net/gurk-rs/files/vendor/libsignal-service/src/profile_cipher.rs deleted file mode 100644 index 413c359..0000000 --- a/net/gurk-rs/files/vendor/libsignal-service/src/profile_cipher.rs +++ /dev/null @@ -1,276 +0,0 @@ -use aes_gcm::{ - aead::{ - generic_array::typenum::U32, generic_array::GenericArray, Aead, - AeadInPlace, - }, - Aes256Gcm, NewAead, -}; -use rand::Rng; -use zkgroup::profiles::ProfileKey; - -use crate::profile_name::ProfileName; - -/// Encrypt and decrypt a [`ProfileName`] and other profile information. -/// -/// # Example -/// -/// ```rust -/// # use libsignal_service::{profile_name::ProfileName, profile_cipher::ProfileCipher}; -/// # use zkgroup::profiles::ProfileKey; -/// # use rand::Rng; -/// # let mut rng = rand::thread_rng(); -/// # let some_randomness = rng.gen(); -/// let profile_key = ProfileKey::generate(some_randomness); -/// let name = ProfileName::<&str> { -/// given_name: "Bill", -/// family_name: None, -/// }; -/// let cipher = ProfileCipher::from(profile_key); -/// let encrypted = cipher.encrypt_name(&name).unwrap(); -/// let decrypted = cipher.decrypt_name(&encrypted).unwrap().unwrap(); -/// assert_eq!(decrypted.as_ref(), name); -/// ``` -pub struct ProfileCipher { - profile_key: ProfileKey, -} - -impl From for ProfileCipher { - fn from(profile_key: ProfileKey) -> Self { - ProfileCipher { profile_key } - } -} - -const NAME_PADDED_LENGTH_1: usize = 53; -const NAME_PADDED_LENGTH_2: usize = 257; -const NAME_PADDING_BRACKETS: &[usize] = - &[NAME_PADDED_LENGTH_1, NAME_PADDED_LENGTH_2]; - -const ABOUT_PADDED_LENGTH_1: usize = 128; -const ABOUT_PADDED_LENGTH_2: usize = 254; -const ABOUT_PADDED_LENGTH_3: usize = 512; -const ABOUT_PADDING_BRACKETS: &[usize] = &[ - ABOUT_PADDED_LENGTH_1, - ABOUT_PADDED_LENGTH_2, - ABOUT_PADDED_LENGTH_3, -]; - -const EMOJI_PADDED_LENGTH: usize = 32; - -#[derive(thiserror::Error, Debug)] -pub enum ProfileCipherError { - #[error("Encryption error")] - EncryptionError, - #[error("UTF-8 decode error {0}")] - Utf8Error(#[from] std::str::Utf8Error), - #[error("Input name too long")] - InputTooLong, -} - -fn pad_plaintext( - bytes: &mut Vec, - brackets: &[usize], -) -> Result { - let len = brackets - .iter() - .find(|x| **x >= bytes.len()) - .ok_or(ProfileCipherError::InputTooLong)?; - let len: usize = *len; - - bytes.resize(len, 0); - assert!(brackets.contains(&bytes.len())); - - Ok(len) -} - -impl ProfileCipher { - pub fn into_inner(self) -> ProfileKey { - self.profile_key - } - - fn get_key(&self) -> GenericArray { - GenericArray::from(self.profile_key.get_bytes()) - } - - fn pad_and_encrypt( - &self, - mut bytes: Vec, - padding_brackets: &[usize], - ) -> Result, ProfileCipherError> { - let _len = pad_plaintext(&mut bytes, padding_brackets)?; - - let cipher = Aes256Gcm::new(&self.get_key()); - let nonce: [u8; 12] = rand::thread_rng().gen(); - let nonce = GenericArray::from_slice(&nonce); - - cipher - .encrypt_in_place(nonce, b"", &mut bytes) - .map_err(|_| ProfileCipherError::EncryptionError)?; - - let mut concat = Vec::with_capacity(nonce.len() + bytes.len()); - concat.extend_from_slice(nonce); - concat.extend_from_slice(&bytes); - Ok(concat) - } - - fn decrypt_and_unpad( - &self, - bytes: Vec, - ) -> Result, ProfileCipherError> { - let nonce = GenericArray::from_slice(&bytes[0..12]); - let cipher = Aes256Gcm::new(&self.get_key()); - - let mut plaintext = cipher - .decrypt(nonce, &bytes[12..]) - .map_err(|_| ProfileCipherError::EncryptionError)?; - - // Unpad - let len = plaintext - .iter() - // Search the first non-0 char... - .rposition(|x| *x != 0) - // ...and strip until right after. - .map(|x| x + 1) - // If it's all zeroes, the string is 0-length. - .unwrap_or(0); - plaintext.truncate(len); - Ok(plaintext) - } - - pub fn encrypt_name<'inp>( - &self, - name: impl std::borrow::Borrow>, - ) -> Result, ProfileCipherError> { - let name = name.borrow(); - let bytes = name.serialize(); - self.pad_and_encrypt(bytes, NAME_PADDING_BRACKETS) - } - - pub fn decrypt_name( - &self, - bytes: impl AsRef<[u8]>, - ) -> Result>, ProfileCipherError> { - let bytes = bytes.as_ref(); - - let plaintext = self.decrypt_and_unpad(bytes.into())?; - - Ok(ProfileName::::deserialize(&plaintext)?) - } - - pub fn encrypt_about( - &self, - about: String, - ) -> Result, ProfileCipherError> { - let bytes = about.into_bytes(); - self.pad_and_encrypt(bytes, ABOUT_PADDING_BRACKETS) - } - - pub fn decrypt_about( - &self, - bytes: impl AsRef<[u8]>, - ) -> Result { - let bytes = bytes.as_ref(); - - let plaintext = self.decrypt_and_unpad(bytes.into())?; - - // XXX This re-allocates. - Ok(std::str::from_utf8(&plaintext)?.into()) - } - - pub fn encrypt_emoji( - &self, - emoji: String, - ) -> Result, ProfileCipherError> { - let bytes = emoji.into_bytes(); - self.pad_and_encrypt(bytes, &[EMOJI_PADDED_LENGTH]) - } - - pub fn decrypt_emoji( - &self, - bytes: impl AsRef<[u8]>, - ) -> Result { - let bytes = bytes.as_ref(); - - let plaintext = self.decrypt_and_unpad(bytes.into())?; - - // XXX This re-allocates. - Ok(std::str::from_utf8(&plaintext)?.into()) - } -} - -#[cfg(test)] -mod tests { - use super::*; - use crate::profile_name::ProfileName; - use rand::Rng; - use zkgroup::profiles::ProfileKey; - - #[test] - fn roundtrip_name() { - let names = [ - "Me and my guitar", // shorter that 53 - "abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz", // one shorter than 53 - "abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzx", // exactly 53 - "abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzxf", // one more than 53 - "abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzxfoobar", // a bit more than 53 - ]; - - // Test the test cases - assert_eq!(names[1].len(), NAME_PADDED_LENGTH_1 - 1); - assert_eq!(names[2].len(), NAME_PADDED_LENGTH_1); - assert_eq!(names[3].len(), NAME_PADDED_LENGTH_1 + 1); - - let mut rng = rand::thread_rng(); - let some_randomness = rng.gen(); - let profile_key = ProfileKey::generate(some_randomness); - let cipher = ProfileCipher::from(profile_key); - for name in &names { - let profile_name = ProfileName::<&str> { - given_name: name, - family_name: None, - }; - assert_eq!(profile_name.serialize().len(), name.len()); - let encrypted = cipher.encrypt_name(&profile_name).unwrap(); - let decrypted = cipher.decrypt_name(&encrypted).unwrap().unwrap(); - - assert_eq!(decrypted.as_ref(), profile_name); - assert_eq!(decrypted.serialize(), profile_name.serialize()); - assert_eq!(&decrypted.given_name, name); - } - } - - #[test] - fn roundtrip_about() { - let abouts = [ - "Me and my guitar", // shorter that 53 - ]; - - let mut rng = rand::thread_rng(); - let some_randomness = rng.gen(); - let profile_key = ProfileKey::generate(some_randomness); - let cipher = ProfileCipher::from(profile_key); - - for &about in &abouts { - let encrypted = cipher.encrypt_about(about.into()).unwrap(); - let decrypted = cipher.decrypt_about(&encrypted).unwrap(); - - assert_eq!(decrypted, about); - } - } - - #[test] - fn roundtrip_emoji() { - let emojii = ["❤️", "💩", "🤣", "😲", "🐠"]; - - let mut rng = rand::thread_rng(); - let some_randomness = rng.gen(); - let profile_key = ProfileKey::generate(some_randomness); - let cipher = ProfileCipher::from(profile_key); - - for &emoji in &emojii { - let encrypted = cipher.encrypt_emoji(emoji.into()).unwrap(); - let decrypted = cipher.decrypt_emoji(&encrypted).unwrap(); - - assert_eq!(decrypted, emoji); - } - } -} diff --git a/net/gurk-rs/files/vendor/libsignal-service/src/profile_name.rs b/net/gurk-rs/files/vendor/libsignal-service/src/profile_name.rs deleted file mode 100644 index bc06706..0000000 --- a/net/gurk-rs/files/vendor/libsignal-service/src/profile_name.rs +++ /dev/null @@ -1,106 +0,0 @@ -#[derive(PartialEq, Eq, Clone, Debug)] -pub struct ProfileName { - pub given_name: S, - pub family_name: Option, -} - -impl> ProfileName { - pub fn as_ref(&self) -> ProfileName<&str> { - ProfileName { - given_name: self.given_name.as_ref(), - family_name: self.family_name.as_ref().map(|x| x.as_ref()), - } - } - - pub fn serialize(&self) -> Vec { - if let Some(family_name) = self.family_name.as_ref() { - self.given_name - .as_ref() - .as_bytes() - .iter() - .chain(std::iter::once(&0u8)) - .chain(family_name.as_ref().as_bytes()) - .copied() - .collect() - } else { - self.given_name.as_ref().as_bytes().into() - } - } - - pub fn is_empty(&self) -> bool { - self.given_name.as_ref() == "" && self.family_name.is_none() - } -} - -impl ProfileName { - /// Copying deserialization of a ProfileName. - pub fn deserialize( - data: &[u8], - ) -> Result, std::str::Utf8Error> { - let parts: Vec<&[u8]> = data.split(|x| *x == 0).collect(); - match parts.len() { - 0 => Ok(None), - 1 => Ok(Some(Self { - given_name: std::str::from_utf8(parts[0])?.to_string(), - family_name: None, - })), - _ => Ok(Some(Self { - given_name: std::str::from_utf8(parts[0])?.to_string(), - family_name: Some(std::str::from_utf8(parts[1])?.to_string()), - })), - } - } -} - -impl<'de> ProfileName<&'de str> { - pub fn empty() -> Self { - ProfileName { - given_name: "", - family_name: None, - } - } - - /// Zero-copy deserialization of a ProfileName. - pub fn deserialize<'inp: 'de>( - data: &'inp [u8], - ) -> Result, std::str::Utf8Error> { - let parts: Vec<&[u8]> = data.split(|x| *x == 0).collect(); - match parts.len() { - 0 => Ok(None), - 1 => Ok(Some(Self { - given_name: std::str::from_utf8(parts[0])?, - family_name: None, - })), - _ => Ok(Some(Self { - given_name: std::str::from_utf8(parts[0])?, - family_name: Some(std::str::from_utf8(parts[1])?), - })), - } - } -} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn roundtrip_name() { - let names = [ - ("foo", Some("bar")), - ("foo", None), - ("", None), - ("", Some("bar")), - ]; - - for &(given_name, family_name) in &names { - let uut_name = ProfileName::<&str> { - given_name, - family_name, - }; - let ser = uut_name.serialize(); - let deserialized = - ProfileName::<&str>::deserialize(&ser).expect("utf8"); - assert_eq!(Some(uut_name), deserialized); - } - } -} diff --git a/net/gurk-rs/files/vendor/libsignal-service/src/proto.rs b/net/gurk-rs/files/vendor/libsignal-service/src/proto.rs deleted file mode 100644 index a65befc..0000000 --- a/net/gurk-rs/files/vendor/libsignal-service/src/proto.rs +++ /dev/null @@ -1,61 +0,0 @@ -include!(concat!(env!("OUT_DIR"), "/signalservice.rs")); -include!(concat!(env!("OUT_DIR"), "/signal.rs")); - -impl WebSocketRequestMessage { - /// Equivalent of - /// `SignalServiceMessagePipe::isSignalServiceEnvelope(WebSocketMessage)`. - pub fn is_signal_service_envelope(&self) -> bool { - self.verb.as_deref() == Some("PUT") - && self.path.as_deref() == Some("/api/v1/message") - } - - /// Equivalent of - /// `SignalServiceMessagePipe::isSignalKeyEncrypted(WebSocketMessage)`. - pub fn is_signal_key_encrypted(&self) -> bool { - if self.headers.is_empty() { - return true; - } - - for header in &self.headers { - let parts: Vec<_> = header.split(':').collect(); - if parts.len() != 2 { - log::warn!( - "Got a weird header: {:?}, split in {:?}", - header, - parts - ); - continue; - } - - if parts[0].trim().eq_ignore_ascii_case("X-Signal-Key") - && parts[1].trim().eq_ignore_ascii_case("false") - { - return false; - } - } - - true - } -} - -impl WebSocketResponseMessage { - /// Equivalent of - /// `SignalServiceMessagePipe::isSignalServiceEnvelope(WebSocketMessage)`. - pub fn from_request(msg: &WebSocketRequestMessage) -> Self { - if msg.is_signal_service_envelope() { - WebSocketResponseMessage { - id: msg.id, - status: Some(200), - message: Some("OK".to_string()), - ..Default::default() - } - } else { - WebSocketResponseMessage { - id: msg.id, - status: Some(400), - message: Some("Unknown".to_string()), - ..Default::default() - } - } - } -} diff --git a/net/gurk-rs/files/vendor/libsignal-service/src/provisioning/cipher.rs b/net/gurk-rs/files/vendor/libsignal-service/src/provisioning/cipher.rs deleted file mode 100644 index 9aa5b9a..0000000 --- a/net/gurk-rs/files/vendor/libsignal-service/src/provisioning/cipher.rs +++ /dev/null @@ -1,221 +0,0 @@ -use std::fmt::{self, Debug}; - -use aes::Aes256; -use block_modes::{block_padding::Pkcs7, BlockMode, Cbc}; -use bytes::Bytes; -use hmac::{Hmac, Mac, NewMac}; -use libsignal_protocol::{KeyPair, PublicKey}; -use prost::Message; -use rand::Rng; -use sha2::Sha256; - -pub use crate::proto::{ - ProvisionEnvelope, ProvisionMessage, ProvisioningVersion, -}; - -use crate::{ - envelope::{CIPHER_KEY_SIZE, IV_LENGTH, IV_OFFSET}, - provisioning::ProvisioningError, -}; - -enum CipherMode { - DecryptAndEncrypt(KeyPair), - EncryptOnly(PublicKey), -} - -impl Debug for CipherMode { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> { - match self { - CipherMode::DecryptAndEncrypt(key_pair) => f - .debug_tuple("CipherMode::DecryptAndEncrypt") - .field(&key_pair.public_key) - .finish(), - CipherMode::EncryptOnly(public) => f - .debug_tuple("CipherMode::EncryptOnly") - .field(&public) - .finish(), - } - } -} - -impl CipherMode { - fn public(&self) -> &PublicKey { - match self { - CipherMode::DecryptAndEncrypt(pair) => &pair.public_key, - CipherMode::EncryptOnly(pub_key) => pub_key, - } - } -} - -const VERSION: u8 = 1; - -#[derive(Debug)] -pub struct ProvisioningCipher { - key_material: CipherMode, -} - -impl ProvisioningCipher { - /// Generate a random key pair - pub fn generate(rng: &mut R) -> Result - where - R: rand::Rng + rand::CryptoRng, - { - let key_pair = libsignal_protocol::KeyPair::generate(rng); - Ok(Self { - key_material: CipherMode::DecryptAndEncrypt(key_pair), - }) - } - - pub fn from_public(key: PublicKey) -> Self { - Self { - key_material: CipherMode::EncryptOnly(key), - } - } - - pub fn from_key_pair(key_pair: KeyPair) -> Self { - Self { - key_material: CipherMode::DecryptAndEncrypt(key_pair), - } - } - - pub fn public_key(&self) -> &PublicKey { - self.key_material.public() - } - - pub fn encrypt( - &self, - msg: ProvisionMessage, - ) -> Result { - let msg = msg.encode_to_vec(); - - let mut rng = rand::thread_rng(); - let our_key_pair = libsignal_protocol::KeyPair::generate(&mut rng); - let agreement = our_key_pair.calculate_agreement(self.public_key())?; - - let mut shared_secrets = [0; 64]; - hkdf::Hkdf::::new(None, &agreement) - .expand(b"TextSecure Provisioning Message", &mut shared_secrets) - .expect("valid output length"); - - let aes_key = &shared_secrets[0..32]; - let mac_key = &shared_secrets[32..]; - let iv: [u8; IV_LENGTH] = rng.gen(); - - let cipher = Cbc::::new_from_slices(aes_key, &iv) - .expect("initalization of CBC/AES/PKCS7"); - let ciphertext = cipher.encrypt_vec(&msg); - let mut mac = Hmac::::new_from_slice(mac_key) - .expect("HMAC can take any size key"); - mac.update(&[VERSION]); - mac.update(&iv); - mac.update(&ciphertext); - let mac = mac.finalize().into_bytes(); - - let body: Vec = std::iter::once(VERSION) - .chain(iv.iter().cloned()) - .chain(ciphertext) - .chain(mac) - .collect(); - - Ok(ProvisionEnvelope { - public_key: Some(our_key_pair.public_key.serialize().into()), - body: Some(body), - }) - } - - pub fn decrypt( - &self, - provision_envelope: ProvisionEnvelope, - ) -> Result { - let key_pair = match self.key_material { - CipherMode::DecryptAndEncrypt(ref key_pair) => key_pair, - CipherMode::EncryptOnly(_) => { - return Err(ProvisioningError::EncryptOnlyProvisioningCipher); - }, - }; - let master_ephemeral = PublicKey::deserialize( - &provision_envelope.public_key.expect("no public key"), - )?; - let body = provision_envelope - .body - .expect("no body in ProvisionMessage"); - if body[0] != VERSION { - return Err(ProvisioningError::InvalidData { - reason: "Bad version number".into(), - }); - } - - let iv = &body[IV_OFFSET..(IV_LENGTH + IV_OFFSET)]; - let mac = &body[(body.len() - 32)..]; - let cipher_text = &body[16 + 1..(body.len() - CIPHER_KEY_SIZE)]; - let iv_and_cipher_text = &body[0..(body.len() - CIPHER_KEY_SIZE)]; - debug_assert_eq!(iv.len(), IV_LENGTH); - debug_assert_eq!(mac.len(), 32); - - let agreement = key_pair.calculate_agreement(&master_ephemeral)?; - - let mut shared_secrets = [0; 64]; - hkdf::Hkdf::::new(None, &agreement) - .expand(b"TextSecure Provisioning Message", &mut shared_secrets) - .expect("valid output length"); - - let parts1 = &shared_secrets[0..32]; - let parts2 = &shared_secrets[32..]; - - let mut verifier = Hmac::::new_from_slice(parts2) - .expect("HMAC can take any size key"); - verifier.update(iv_and_cipher_text); - let our_mac = verifier.finalize().into_bytes(); - debug_assert_eq!(our_mac.len(), mac.len()); - if &our_mac[..32] != mac { - return Err(ProvisioningError::InvalidData { - reason: "wrong MAC".into(), - }); - } - - // libsignal-service-java uses Pkcs5, - // but that should not matter. - // https://crypto.stackexchange.com/questions/9043/what-is-the-difference-between-pkcs5-padding-and-pkcs7-padding - let cipher = Cbc::::new_from_slices(parts1, iv) - .expect("initalization of CBC/AES/PKCS7"); - let input = cipher.decrypt_vec(cipher_text).map_err(|e| { - ProvisioningError::InvalidData { - reason: format!("CBC/Padding error: {:?}", e), - } - })?; - - Ok(prost::Message::decode(Bytes::from(input))?) - } -} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn encrypt_provisioning_roundtrip() -> anyhow::Result<()> { - let mut rng = rand::thread_rng(); - let cipher = ProvisioningCipher::generate(&mut rng)?; - let encrypt_cipher = - ProvisioningCipher::from_public(*cipher.public_key()); - - assert_eq!( - cipher.public_key(), - encrypt_cipher.public_key(), - "copy public key" - ); - - let msg = ProvisionMessage::default(); - let encrypted = encrypt_cipher.encrypt(msg.clone())?; - - assert!(matches!( - encrypt_cipher.decrypt(encrypted.clone()), - Err(ProvisioningError::EncryptOnlyProvisioningCipher) - )); - - let decrypted = cipher.decrypt(encrypted)?; - assert_eq!(msg, decrypted); - - Ok(()) - } -} diff --git a/net/gurk-rs/files/vendor/libsignal-service/src/provisioning/manager.rs b/net/gurk-rs/files/vendor/libsignal-service/src/provisioning/manager.rs deleted file mode 100644 index 8699689..0000000 --- a/net/gurk-rs/files/vendor/libsignal-service/src/provisioning/manager.rs +++ /dev/null @@ -1,369 +0,0 @@ -use futures::{channel::mpsc::Sender, pin_mut, SinkExt, StreamExt}; -use libsignal_protocol::{PrivateKey, PublicKey}; -use phonenumber::PhoneNumber; -use serde::{Deserialize, Serialize}; -use url::Url; -use uuid::Uuid; - -use super::{ - pipe::{ProvisioningPipe, ProvisioningStep}, - ProvisioningError, -}; - -use crate::{ - configuration::{Endpoint, ServiceCredentials, SignalingKey}, - push_service::{ - AccountAttributes, DeviceCapabilities, DeviceId, HttpAuthOverride, - PushService, ServiceError, - }, - utils::{serde_base64, serde_optional_base64}, -}; - -/// Message received after confirming the SMS/voice code on registration. -#[derive(Debug, Serialize)] -#[serde(rename_all = "camelCase")] -pub struct ConfirmCodeMessage { - #[serde(with = "serde_base64")] - pub signaling_key: Vec, - pub supports_sms: bool, - pub registration_id: u32, - pub voice: bool, - pub video: bool, - pub fetches_messages: bool, - pub pin: Option, - #[serde(default, with = "serde_optional_base64")] - pub unidentified_access_key: Option>, - pub unrestricted_unidentified_access: bool, - pub discoverable_by_phone_number: bool, - pub capabilities: DeviceCapabilities, -} -/// Message received when linking a new secondary device. -#[derive(Debug, Serialize)] -#[serde(rename_all = "camelCase")] -pub struct ConfirmDeviceMessage { - #[serde(with = "serde_base64")] - pub signaling_key: Vec, - pub supports_sms: bool, - pub fetches_messages: bool, - pub registration_id: u32, - // FIXME: the name goes back here when we send this via the websocket - //pub name: String, -} - -#[derive(Debug, Deserialize)] -#[serde(rename_all = "camelCase")] -pub struct ConfirmCodeResponse { - pub uuid: Uuid, - pub storage_capable: bool, -} - -#[derive(Debug, Eq, PartialEq)] -pub enum VerificationCodeResponse { - CaptchaRequired, - Issued, -} - -#[derive(Debug, Deserialize)] -#[serde(rename_all = "camelCase")] -pub struct VerifyAccountResponse { - pub uuid: Uuid, - pub pni: String, - pub storage_capable: bool, -} - -pub struct ProvisioningManager<'a, P: PushService + 'a> { - push_service: &'a mut P, - phone_number: PhoneNumber, - password: String, -} - -pub enum SecondaryDeviceProvisioning { - Url(Url), - NewDeviceRegistration { - phone_number: phonenumber::PhoneNumber, - device_id: DeviceId, - registration_id: u32, - uuid: Uuid, - private_key: PrivateKey, - public_key: PublicKey, - profile_key: Vec, - }, -} - -impl<'a, P: PushService + 'a> ProvisioningManager<'a, P> { - pub fn new( - push_service: &'a mut P, - phone_number: PhoneNumber, - password: String, - ) -> Self { - Self { - push_service, - phone_number, - password, - } - } - - pub async fn request_sms_verification_code( - &mut self, - captcha: Option<&str>, - challenge: Option<&str>, - ) -> Result { - let res = match self - .push_service - .get_json( - Endpoint::Service, - self.build_verification_code_request_url( - "sms", captcha, challenge, - ) - .as_ref(), - self.auth_override(), - ) - .await - { - Err(ServiceError::JsonDecodeError { .. }) => Ok(()), - r => r, - }; - match res { - Ok(_) => Ok(VerificationCodeResponse::Issued), - Err(ServiceError::UnhandledResponseCode { http_code: 402 }) => { - Ok(VerificationCodeResponse::CaptchaRequired) - }, - Err(e) => Err(e), - } - } - - pub async fn request_voice_verification_code( - &mut self, - captcha: Option<&str>, - challenge: Option<&str>, - ) -> Result { - let res = match self - .push_service - .get_json( - Endpoint::Service, - self.build_verification_code_request_url( - "voice", captcha, challenge, - ) - .as_ref(), - self.auth_override(), - ) - .await - { - Err(ServiceError::JsonDecodeError { .. }) => Ok(()), - r => r, - }; - match res { - Ok(_) => Ok(VerificationCodeResponse::Issued), - Err(ServiceError::UnhandledResponseCode { http_code: 402 }) => { - Ok(VerificationCodeResponse::CaptchaRequired) - }, - Err(e) => Err(e), - } - } - - pub async fn confirm_verification_code( - &mut self, - confirm_code: u32, - account_attributes: AccountAttributes, - ) -> Result { - self.push_service - .put_json( - Endpoint::Service, - &format!("/v1/accounts/code/{}", confirm_code), - self.auth_override(), - account_attributes, - ) - .await - } - - pub async fn confirm_device( - &mut self, - confirm_code: u32, - confirm_code_message: ConfirmDeviceMessage, - ) -> Result { - self.push_service - .put_json( - Endpoint::Service, - &format!("/v1/devices/{}", confirm_code), - self.auth_override(), - confirm_code_message, - ) - .await - } - - fn build_verification_code_request_url( - &self, - msg_type: &str, - captcha: Option<&str>, - challenge: Option<&str>, - ) -> String { - let phone_number = - self.phone_number.format().mode(phonenumber::Mode::E164); - if let Some(cl) = challenge { - format!( - "/v1/accounts/{}/code/{}?challenge={}", - msg_type, phone_number, cl - ) - } else if let Some(cc) = captcha { - format!( - "/v1/accounts/{}/code/{}?captcha={}", - msg_type, phone_number, cc - ) - } else { - format!("/v1/accounts/{}/code/{}", msg_type, phone_number) - } - } - - fn auth_override(&self) -> HttpAuthOverride { - let credentials = ServiceCredentials { - uuid: None, - phonenumber: self.phone_number.clone(), - password: Some(self.password.clone()), - signaling_key: None, - device_id: None, - }; - if let Some(auth) = credentials.authorization() { - HttpAuthOverride::Identified(auth) - } else { - HttpAuthOverride::NoOverride - } - } -} - -#[derive(Clone)] -pub struct LinkingManager { - push_service: P, - // forwarded to the `ProvisioningManager` - password: String, -} - -impl LinkingManager

{ - pub fn new(push_service: P, password: String) -> Self { - Self { - push_service, - password, - } - } - - pub async fn provision_secondary_device( - &mut self, - csprng: &mut R, - signaling_key: SignalingKey, - mut tx: Sender, - ) -> Result<(), ProvisioningError> { - // open a websocket without authentication, to receive a tsurl:// - let (ws, stream) = self - .push_service - .ws("/v1/websocket/provisioning/", None) - .await?; - - // see libsignal-protocol-c / signal_protocol_key_helper_generate_registration_id - let registration_id = csprng.gen_range(1, 16380); - - let provisioning_pipe = ProvisioningPipe::from_socket(ws, stream)?; - let provision_stream = provisioning_pipe.stream(); - pin_mut!(provision_stream); - while let Some(step) = provision_stream.next().await { - match step { - Ok(ProvisioningStep::Url(url)) => { - tx.send(SecondaryDeviceProvisioning::Url(url)) - .await - .expect("failed to send provisioning Url in channel"); - }, - Ok(ProvisioningStep::Message(message)) => { - let uuid = message - .uuid - .ok_or(ProvisioningError::InvalidData { - reason: "missing client UUID".into(), - }) - .and_then(|ref s| { - Uuid::parse_str(s).map_err(|e| { - ProvisioningError::InvalidData { - reason: format!("invalid UUID: {}", e), - } - }) - })?; - - let public_key = PublicKey::deserialize( - &message.identity_key_public.ok_or( - ProvisioningError::InvalidData { - reason: "missing public key".into(), - }, - )?, - )?; - - let private_key = PrivateKey::deserialize( - &message.identity_key_private.ok_or( - ProvisioningError::InvalidData { - reason: "missing public key".into(), - }, - )?, - )?; - - let profile_key = message.profile_key.ok_or( - ProvisioningError::InvalidData { - reason: "missing profile key".into(), - }, - )?; - - let phone_number = message.number.ok_or( - ProvisioningError::InvalidData { - reason: "missing phone number".into(), - }, - )?; - - let phone_number = phonenumber::parse(None, phone_number) - .map_err(|e| { - ProvisioningError::InvalidData { - reason: format!("invalid phone number ({})", e), - } - })?; - - let mut provisioning_manager = ProvisioningManager::new( - &mut self.push_service, - phone_number.clone(), - self.password.clone(), - ); - - let device_id = provisioning_manager - .confirm_device( - message - .provisioning_code - .ok_or(ProvisioningError::InvalidData { - reason: "no provisioning confirmation code" - .into(), - })? - .parse() - .unwrap(), - ConfirmDeviceMessage { - signaling_key: signaling_key.to_vec(), - supports_sms: false, - fetches_messages: true, - registration_id, - }, - ) - .await?; - - tx.send( - SecondaryDeviceProvisioning::NewDeviceRegistration { - phone_number, - device_id, - registration_id, - uuid, - private_key, - public_key, - profile_key, - }, - ) - .await - .expect( - "failed to send provisioning message in rx channel", - ); - }, - Err(e) => return Err(e), - } - } - - Ok(()) - } -} diff --git a/net/gurk-rs/files/vendor/libsignal-service/src/provisioning/mod.rs b/net/gurk-rs/files/vendor/libsignal-service/src/provisioning/mod.rs deleted file mode 100644 index 9377809..0000000 --- a/net/gurk-rs/files/vendor/libsignal-service/src/provisioning/mod.rs +++ /dev/null @@ -1,40 +0,0 @@ -mod cipher; -mod manager; -mod pipe; - -pub use cipher::ProvisioningCipher; -pub use manager::{ - ConfirmCodeMessage, ConfirmCodeResponse, LinkingManager, - ProvisioningManager, SecondaryDeviceProvisioning, VerificationCodeResponse, - VerifyAccountResponse, -}; - -use crate::prelude::ServiceError; - -pub use crate::proto::{ - ProvisionEnvelope, ProvisionMessage, ProvisioningVersion, -}; - -#[derive(thiserror::Error, Debug)] -pub enum ProvisioningError { - #[error("Invalid provisioning data: {reason}")] - InvalidData { reason: String }, - #[error("Protobuf decoding error: {0}")] - DecodeError(#[from] prost::DecodeError), - #[error("Websocket error: {reason}")] - WsError { reason: String }, - #[error("Websocket closing: {reason}")] - WsClosing { reason: String }, - #[error("Service error: {0}")] - ServiceError(#[from] ServiceError), - #[error("libsignal-protocol error: {0}")] - ProtocolError(#[from] libsignal_protocol::error::SignalProtocolError), - #[error("ProvisioningCipher in encrypt-only mode")] - EncryptOnlyProvisioningCipher, -} - -pub fn generate_registration_id( - csprng: &mut R, -) -> u32 { - csprng.gen_range(1, 16380) -} diff --git a/net/gurk-rs/files/vendor/libsignal-service/src/provisioning/pipe.rs b/net/gurk-rs/files/vendor/libsignal-service/src/provisioning/pipe.rs deleted file mode 100644 index 5147000..0000000 --- a/net/gurk-rs/files/vendor/libsignal-service/src/provisioning/pipe.rs +++ /dev/null @@ -1,214 +0,0 @@ -use bytes::Bytes; -use futures::{ - channel::mpsc::{self, Sender}, - prelude::*, - stream::FuturesUnordered, -}; -use pin_project::pin_project; -use prost::Message; -use url::Url; - -pub use crate::proto::{ - ProvisionEnvelope, ProvisionMessage, ProvisioningVersion, -}; - -use crate::{ - messagepipe::{WebSocketService, WebSocketStreamItem}, - proto::{ - web_socket_message, ProvisioningUuid, WebSocketMessage, - WebSocketRequestMessage, WebSocketResponseMessage, - }, - provisioning::ProvisioningError, -}; - -use super::cipher::ProvisioningCipher; - -#[pin_project] -pub struct ProvisioningPipe { - ws: WS, - #[pin] - stream: WS::Stream, - provisioning_cipher: ProvisioningCipher, -} - -#[derive(Debug)] -pub enum ProvisioningStep { - Url(Url), - Message(ProvisionMessage), -} - -impl ProvisioningPipe { - pub fn from_socket( - ws: WS, - stream: WS::Stream, - ) -> Result { - Ok(ProvisioningPipe { - ws, - stream, - provisioning_cipher: ProvisioningCipher::generate( - &mut rand::thread_rng(), - )?, - }) - } - - async fn send_ok_response( - &mut self, - id: Option, - ) -> Result<(), ProvisioningError> { - self.send_response(WebSocketResponseMessage { - id, - status: Some(200), - message: Some("OK".into()), - body: None, - headers: vec![], - }) - .await - } - - async fn send_response( - &mut self, - r: WebSocketResponseMessage, - ) -> Result<(), ProvisioningError> { - let msg = WebSocketMessage { - r#type: Some(web_socket_message::Type::Response.into()), - response: Some(r), - ..Default::default() - }; - let buffer = msg.encode_to_vec(); - Ok(self.ws.send_message(buffer.into()).await?) - } - - /// Worker task that - async fn run( - mut self, - mut sink: Sender>, - ) -> Result<(), mpsc::SendError> { - use futures::future::LocalBoxFuture; - - // This is a runtime-agnostic, poor man's `::spawn(Future)`. - let mut background_work = FuturesUnordered::>::new(); - // a pending task is added, as to never end the background worker until - // it's dropped. - background_work.push(futures::future::pending().boxed_local()); - - loop { - futures::select! { - // WebsocketConnection::onMessage(ByteString) - frame = self.stream.next() => match frame { - Some(WebSocketStreamItem::Message(frame)) => { - let env = self.process_frame(frame).await.transpose(); - if let Some(env) = env { - sink.send(env).await?; - } - }, - // TODO: implement keep-alive? - Some(WebSocketStreamItem::KeepAliveRequest) => continue, - None => break, - }, - _ = background_work.next() => { - // no op - }, - complete => { - log::info!("select! complete"); - } - } - } - - Ok(()) - } - - async fn process_frame( - &mut self, - frame: Bytes, - ) -> Result, ProvisioningError> { - let msg = WebSocketMessage::decode(frame)?; - use web_socket_message::Type; - match (msg.r#type(), msg.request, msg.response) { - (Type::Request, Some(request), _) => { - match request { - // step 1: we get a ProvisioningUUID that we need to build a - // registration link - WebSocketRequestMessage { - id, - verb, - path, - body, - .. - } if verb == Some("PUT".into()) - && path == Some("/v1/address".into()) => - { - let uuid: ProvisioningUuid = - prost::Message::decode(Bytes::from(body.unwrap()))?; - let mut provisioning_url = - Url::parse("sgnl://linkdevice").map_err(|e| { - ProvisioningError::WsError { - reason: e.to_string(), - } - })?; - provisioning_url - .query_pairs_mut() - .append_pair("uuid", &uuid.uuid.unwrap()) - .append_pair( - "pub_key", - &base64::encode( - self.provisioning_cipher - .public_key() - .serialize(), - ), - ); - - // acknowledge - self.send_ok_response(id).await?; - - Ok(Some(ProvisioningStep::Url(provisioning_url))) - }, - // step 2: once the QR code is scanned by the (already - // validated) main device - // we get a ProvisionMessage, that contains a bunch of - // useful things - WebSocketRequestMessage { - id, - verb, - path, - body, - .. - } if verb == Some("PUT".into()) - && path == Some("/v1/message".into()) => - { - let provision_envelope: ProvisionEnvelope = - prost::Message::decode(Bytes::from(body.unwrap()))?; - let provision_message = self - .provisioning_cipher - .decrypt(provision_envelope)?; - - // acknowledge - self.send_ok_response(id).await?; - - Ok(Some(ProvisioningStep::Message(provision_message))) - }, - _ => Err(ProvisioningError::WsError { - reason: "Incorrect request".into(), - }), - } - }, - _ => Err(ProvisioningError::WsError { - reason: "Incorrect request".into(), - }), - } - } - - pub fn stream( - self, - ) -> impl Stream> { - let (sink, stream) = mpsc::channel(1); - - let stream = stream.map(Some); - let runner = self.run(sink).map(|_| { - log::info!("Sink closed, provisioning is done!"); - None - }); - - let combined = futures::stream::select(stream, runner.into_stream()); - combined.filter_map(|x| async { x }) - } -} diff --git a/net/gurk-rs/files/vendor/libsignal-service/src/push_service.rs b/net/gurk-rs/files/vendor/libsignal-service/src/push_service.rs deleted file mode 100644 index 3ab59f9..0000000 --- a/net/gurk-rs/files/vendor/libsignal-service/src/push_service.rs +++ /dev/null @@ -1,799 +0,0 @@ -use std::{convert::TryInto, fmt, ops::Deref, time::Duration}; - -use crate::{ - configuration::{Endpoint, ServiceCredentials}, - envelope::*, - groups_v2::GroupDecryptionError, - messagepipe::WebSocketService, - pre_keys::{PreKeyEntity, PreKeyState, SignedPreKeyEntity}, - proto::{attachment_pointer::AttachmentIdentifier, AttachmentPointer}, - sender::{OutgoingPushMessages, SendMessageResponse}, - utils::{serde_base64, serde_optional_base64}, - MaybeSend, ServiceAddress, -}; - -use aes_gcm::{ - aead::{generic_array::GenericArray, Aead}, - Aes256Gcm, NewAead, -}; -use chrono::prelude::*; -use libsignal_protocol::{ - error::SignalProtocolError, IdentityKey, PreKeyBundle, PublicKey, -}; -use prost::Message as ProtobufMessage; -use serde::{Deserialize, Serialize}; -use uuid::Uuid; -use zkgroup::profiles::{ProfileKeyCommitment, ProfileKeyVersion}; - -/** -Since we can't use format!() with constants, the URLs here are just for reference purposes -pub const REGISTER_GCM_PATH: &str = "/v1/accounts/gcm/"; -pub const TURN_SERVER_INFO: &str = "/v1/accounts/turn"; -pub const SET_ACCOUNT_ATTRIBUTES: &str = "/v1/accounts/attributes/"; -pub const PIN_PATH: &str = "/v1/accounts/pin/"; -pub const REQUEST_PUSH_CHALLENGE: &str = "/v1/accounts/fcm/preauth/%s/%s"; -pub const WHO_AM_I: &str = "/v1/accounts/whoami"; - -pub const PREKEY_PATH: &str = "/v2/keys/%s"; -pub const PREKEY_DEVICE_PATH: &str = "/v2/keys/%s/%s"; -pub const SIGNED_PREKEY_PATH: &str = "/v2/keys/signed"; - -pub const PROVISIONING_CODE_PATH: &str = "/v1/devices/provisioning/code"; -pub const PROVISIONING_MESSAGE_PATH: &str = "/v1/provisioning/%s"; - -pub const DIRECTORY_TOKENS_PATH: &str = "/v1/directory/tokens"; -pub const DIRECTORY_VERIFY_PATH: &str = "/v1/directory/%s"; -pub const DIRECTORY_AUTH_PATH: &str = "/v1/directory/auth"; -pub const DIRECTORY_FEEDBACK_PATH: &str = "/v1/directory/feedback-v3/%s"; -pub const SENDER_ACK_MESSAGE_PATH: &str = "/v1/messages/%s/%d"; -pub const UUID_ACK_MESSAGE_PATH: &str = "/v1/messages/uuid/%s"; -pub const ATTACHMENT_PATH: &str = "/v2/attachments/form/upload"; - -pub const PROFILE_PATH: &str = "/v1/profile/"; - -pub const SENDER_CERTIFICATE_LEGACY_PATH: &str = "/v1/certificate/delivery"; -pub const SENDER_CERTIFICATE_PATH: &str = - "/v1/certificate/delivery?includeUuid=true"; - -pub const ATTACHMENT_DOWNLOAD_PATH: &str = "attachments/%d"; - -pub const STICKER_MANIFEST_PATH: &str = "stickers/%s/manifest.proto"; -pub const STICKER_PATH: &str = "stickers/%s/full/%d"; -**/ - -pub const KEEPALIVE_TIMEOUT_SECONDS: Duration = Duration::from_secs(55); -pub const DEFAULT_DEVICE_ID: u32 = 1; - -#[derive(Debug, Serialize, Deserialize)] -#[serde(rename_all = "camelCase")] -pub struct DeviceId { - pub device_id: u32, -} - -#[derive(Debug, Serialize, Deserialize)] -#[serde(rename_all = "camelCase")] -pub struct DeviceInfo { - pub id: i64, - pub name: Option, - #[serde(with = "chrono::serde::ts_milliseconds")] - pub created: DateTime, - #[serde(with = "chrono::serde::ts_milliseconds")] - pub last_seen: DateTime, -} - -#[derive(Debug, Serialize, Deserialize)] -#[serde(rename_all = "camelCase")] -pub struct AccountAttributes { - #[serde(default, with = "serde_optional_base64")] - pub signaling_key: Option>, - pub registration_id: u32, - pub voice: bool, - pub video: bool, - pub fetches_messages: bool, - pub pin: Option, - pub registration_lock: Option, - #[serde(default, with = "serde_optional_base64")] - pub unidentified_access_key: Option>, - pub unrestricted_unidentified_access: bool, - pub discoverable_by_phone_number: bool, - pub capabilities: DeviceCapabilities, -} - -#[derive(Debug, Serialize, Deserialize, Default)] -#[serde(rename_all = "camelCase")] -pub struct DeviceCapabilities { - pub uuid: bool, - #[serde(rename = "gv2-3")] - pub gv2: bool, - pub storage: bool, - #[serde(rename = "gv1-migration")] - pub gv1_migration: bool, -} - -#[derive(Clone)] -pub struct ProfileKey(pub [u8; 32]); - -#[derive(Debug, Deserialize, Default)] -#[serde(rename_all = "camelCase")] -pub struct PreKeyStatus { - pub count: u32, -} - -#[derive(Clone)] -pub struct HttpAuth { - pub username: String, - pub password: String, -} - -#[derive(Debug, Clone)] -pub enum HttpAuthOverride { - NoOverride, - Unidentified, - Identified(HttpAuth), -} - -impl fmt::Debug for HttpAuth { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "HTTP auth with username {}", self.username) - } -} - -impl ProfileKey { - pub fn derive_access_key(&self) -> Vec { - let key = GenericArray::from_slice(&self.0); - let cipher = Aes256Gcm::new(key); - let nonce = GenericArray::from_slice(&[0u8; 12]); - let buf = [0u8; 16]; - let mut ciphertext = cipher.encrypt(nonce, &buf[..]).unwrap(); - ciphertext.truncate(16); - ciphertext - } -} - -impl Deref for ProfileKey { - type Target = [u8; 32]; - - fn deref(&self) -> &Self::Target { - &self.0 - } -} - -impl Serialize for ProfileKey { - fn serialize(&self, serializer: S) -> Result - where - S: serde::Serializer, - { - serializer.serialize_str(&base64::encode(self.0)) - } -} - -impl<'de> Deserialize<'de> for ProfileKey { - fn deserialize(deserializer: D) -> Result - where - D: serde::Deserializer<'de>, - { - Ok(ProfileKey( - base64::decode(String::deserialize(deserializer)?) - .map_err(serde::de::Error::custom)? - .try_into() - .map_err(|buf: Vec| { - serde::de::Error::invalid_length( - buf.len(), - &"invalid profile key length", - ) - })?, - )) - } -} - -#[derive(Debug, Deserialize)] -#[serde(rename_all = "camelCase")] -pub struct PreKeyResponse { - #[serde(with = "serde_base64")] - pub identity_key: Vec, - pub devices: Vec, -} - -#[derive(Debug, Deserialize, Default)] -#[serde(rename_all = "camelCase")] -pub struct WhoAmIResponse { - pub uuid: Uuid, -} - -#[derive(Debug, Deserialize)] -#[serde(rename_all = "camelCase")] -pub struct PreKeyResponseItem { - pub device_id: u32, - pub registration_id: u32, - pub signed_pre_key: SignedPreKeyEntity, - pub pre_key: Option, -} - -impl PreKeyResponseItem { - fn into_bundle( - self, - identity: IdentityKey, - ) -> Result { - PreKeyBundle::new( - self.registration_id, - self.device_id, - self.pre_key - .map(|pk| -> Result<_, SignalProtocolError> { - Ok((pk.key_id, PublicKey::deserialize(&pk.public_key)?)) - }) - .transpose()?, - // pre_key: Option<(u32, PublicKey)>, - self.signed_pre_key.key_id, - PublicKey::deserialize(&self.signed_pre_key.public_key)?, - self.signed_pre_key.signature, - identity, - ) - } -} - -#[derive(Debug, Deserialize)] -#[serde(rename_all = "camelCase")] -pub struct MismatchedDevices { - pub missing_devices: Vec, - pub extra_devices: Vec, -} - -#[derive(Debug, Deserialize)] -#[serde(rename_all = "camelCase")] -pub struct StaleDevices { - pub stale_devices: Vec, -} - -#[derive(Debug, Deserialize)] -#[serde(rename_all = "camelCase")] -pub struct SignalServiceProfile { - #[serde(default, with = "serde_optional_base64")] - pub name: Option>, - #[serde(default, with = "serde_optional_base64")] - pub about: Option>, - #[serde(default, with = "serde_optional_base64")] - pub about_emoji: Option>, -} - -#[derive(Debug, serde::Deserialize, Default)] -#[serde(rename_all = "camelCase")] -pub struct CdnUploadAttributes { - path: String, - acl: String, - key: String, - policy: String, - algorithm: String, - credential: String, - date: String, - signature: String, - content_type: String, - length: u64, -} - -#[derive(Debug, serde::Deserialize, Default)] -#[serde(rename_all = "camelCase")] -pub struct AttachmentV2UploadAttributes { - url: Option, - key: String, - credential: String, - acl: String, - algorithm: String, - date: String, - policy: String, - signature: String, - // This is different from Java's implementation, - // and I (Ruben) am unsure why they decide to force-parse at upload-time instead of at registration - // time. - attachment_id: u64, - attachment_id_string: String, -} - -#[derive(thiserror::Error, Debug)] -pub enum ServiceError { - #[error("Service request timed out: {reason}")] - Timeout { reason: String }, - - #[error("invalid URL: {0}")] - InvalidUrl(#[from] url::ParseError), - - #[error("Error sending request: {reason}")] - SendError { reason: String }, - - #[error("Error decoding response: {reason}")] - ResponseError { reason: String }, - - #[error("Error decoding JSON response: {reason}")] - JsonDecodeError { reason: String }, - #[error("Error decoding protobuf frame: {0}")] - ProtobufDecodeError(#[from] prost::DecodeError), - #[error("error encoding or decoding bincode: {0}")] - BincodeError(#[from] bincode::Error), - #[error("error decoding base64 string: {0}")] - Base64DecodeError(#[from] base64::DecodeError), - - #[error("Rate limit exceeded")] - RateLimitExceeded, - #[error("Authorization failed")] - Unauthorized, - #[error("Unexpected response: HTTP {http_code}")] - UnhandledResponseCode { http_code: u16 }, - - #[error("Websocket error: {reason}")] - WsError { reason: String }, - #[error("Websocket closing: {reason}")] - WsClosing { reason: String }, - - #[error("Invalid frame: {reason}")] - InvalidFrameError { reason: String }, - - #[error("MAC error")] - MacError, - - #[error("Protocol error: {0}")] - SignalProtocolError(#[from] SignalProtocolError), - - #[error("{0:?}")] - MismatchedDevicesException(MismatchedDevices), - - #[error("{0:?}")] - StaleDevices(StaleDevices), - - #[error("SealedSessionCipher error: {0}")] - SealedSessionError( - #[from] crate::sealed_session_cipher::SealedSessionError, - ), - - #[error(transparent)] - CredentialsCacheError(#[from] crate::groups_v2::CredentialsCacheError), - - #[error("groups v2 (zero-knowledge) error")] - GroupsV2Error, - - #[error(transparent)] - GroupsV2DecryptionError(#[from] GroupDecryptionError), -} - -#[cfg_attr(feature = "unsend-futures", async_trait::async_trait(?Send))] -#[cfg_attr(not(feature = "unsend-futures"), async_trait::async_trait)] -pub trait PushService: MaybeSend { - type WebSocket: WebSocketService; - type ByteStream: futures::io::AsyncRead + Unpin; - - async fn get_json( - &mut self, - service: Endpoint, - path: &str, - credentials_override: HttpAuthOverride, - ) -> Result - where - for<'de> T: Deserialize<'de>; - - async fn delete_json( - &mut self, - service: Endpoint, - path: &str, - ) -> Result - where - for<'de> T: Deserialize<'de>; - - async fn put_json( - &mut self, - service: Endpoint, - path: &str, - credentials_override: HttpAuthOverride, - value: S, - ) -> Result - where - for<'de> D: Deserialize<'de>, - S: MaybeSend + Serialize; - - async fn get_protobuf( - &mut self, - service: Endpoint, - path: &str, - credentials_override: HttpAuthOverride, - ) -> Result - where - T: Default + ProtobufMessage; - - async fn put_protobuf( - &mut self, - service: Endpoint, - path: &str, - value: S, - ) -> Result - where - D: Default + ProtobufMessage, - S: Sized + ProtobufMessage; - - /// Downloads larger files in streaming fashion, e.g. attachments. - async fn get_from_cdn( - &mut self, - cdn_id: u32, - path: &str, - ) -> Result; - - /// Upload larger file to CDN0 in legacy fashion, e.g. for attachments. - /// - /// Implementations are allowed to *panic* when the Read instance throws an IO-Error - async fn post_to_cdn0<'s, C: std::io::Read + Send + 's>( - &mut self, - path: &str, - value: &[(&str, &str)], - file: Option<(&str, &'s mut C)>, - ) -> Result<(), ServiceError>; - - async fn ws( - &mut self, - path: &str, - credentials: Option, - ) -> Result< - ( - Self::WebSocket, - ::Stream, - ), - ServiceError, - >; - - /// Fetches a list of all devices tied to the authenticated account. - /// - /// This list include the device that sends the request. - async fn devices(&mut self) -> Result, ServiceError> { - #[derive(serde::Deserialize)] - struct DeviceInfoList { - devices: Vec, - } - - let devices: DeviceInfoList = self - .get_json( - Endpoint::Service, - "/v1/devices/", - HttpAuthOverride::NoOverride, - ) - .await?; - - Ok(devices.devices) - } - - async fn unlink_device(&mut self, id: i64) -> Result<(), ServiceError> { - self.delete_json(Endpoint::Service, &format!("/v1/devices/{}", id)) - .await - } - - async fn get_pre_key_status( - &mut self, - ) -> Result { - self.get_json( - Endpoint::Service, - "/v2/keys/", - HttpAuthOverride::NoOverride, - ) - .await - } - - async fn register_pre_keys( - &mut self, - pre_key_state: PreKeyState, - ) -> Result<(), ServiceError> { - match self - .put_json( - Endpoint::Service, - "/v2/keys/", - HttpAuthOverride::NoOverride, - pre_key_state, - ) - .await - { - Err(ServiceError::JsonDecodeError { .. }) => Ok(()), - r => r, - } - } - - async fn get_attachment_by_id( - &mut self, - id: &str, - cdn_id: u32, - ) -> Result { - let path = format!("attachments/{}", id); - self.get_from_cdn(cdn_id, &path).await - } - - async fn get_attachment( - &mut self, - ptr: &AttachmentPointer, - ) -> Result { - match ptr.attachment_identifier.as_ref().unwrap() { - AttachmentIdentifier::CdnId(id) => { - // cdn_number did not exist for this part of the protocol. - // cdn_number(), however, returns 0 when the field does not - // exist. - self.get_attachment_by_id(&format!("{}", id), ptr.cdn_number()) - .await - }, - AttachmentIdentifier::CdnKey(key) => { - self.get_attachment_by_id(key, ptr.cdn_number()).await - }, - } - } - - async fn send_messages<'a>( - &mut self, - messages: OutgoingPushMessages<'a>, - ) -> Result { - let path = format!("/v1/messages/{}", messages.destination); - self.put_json( - Endpoint::Service, - &path, - HttpAuthOverride::NoOverride, - messages, - ) - .await - } - - /// Request AttachmentV2UploadAttributes - /// - /// Equivalent with getAttachmentV2UploadAttributes - async fn get_attachment_v2_upload_attributes( - &mut self, - ) -> Result { - self.get_json( - Endpoint::Service, - "/v2/attachments/form/upload", - HttpAuthOverride::NoOverride, - ) - .await - } - - /// Upload attachment to CDN - /// - /// Returns attachment ID and the attachment digest - async fn upload_attachment<'s, C: std::io::Read + Send + 's>( - &mut self, - attrs: &AttachmentV2UploadAttributes, - content: &'s mut C, - ) -> Result<(u64, Vec), ServiceError> { - let values = [ - ("acl", &attrs.acl as &str), - ("key", &attrs.key), - ("policy", &attrs.policy), - ("Content-Type", "application/octet-stream"), - ("x-amz-algorithm", &attrs.algorithm), - ("x-amz-credential", &attrs.credential), - ("x-amz-date", &attrs.date), - ("x-amz-signature", &attrs.signature), - ]; - - let mut digester = crate::digeststream::DigestingReader::new(content); - - self.post_to_cdn0( - "attachments/", - &values, - Some(("file", &mut digester)), - ) - .await?; - Ok((attrs.attachment_id, digester.finalize())) - } - - async fn get_messages( - &mut self, - ) -> Result, ServiceError> { - let entity_list: EnvelopeEntityList = self - .get_json( - Endpoint::Service, - "/v1/messages/", - HttpAuthOverride::NoOverride, - ) - .await?; - Ok(entity_list.messages) - } - - /// Method used to check our own UUID - async fn whoami(&mut self) -> Result { - self.get_json( - Endpoint::Service, - "/v1/accounts/whoami", - HttpAuthOverride::NoOverride, - ) - .await - } - - async fn retrieve_profile_by_id( - &mut self, - id: &str, - ) -> Result { - self.get_json( - Endpoint::Service, - &format!("/v1/profile/{}", id), - HttpAuthOverride::NoOverride, - ) - .await - } - async fn retrieve_versioned_profile_by_id( - &mut self, - id: &str, - version: &ProfileKeyVersion, - ) -> Result { - // Bincode is transparent and will return a hex-encoded string. - let version = bincode::serialize(version)?; - let version = std::str::from_utf8(&version) - .expect("profile_key_version is hex encoded string"); - self.get_json( - Endpoint::Service, - &format!("/v1/profile/{}/{}", id, version), - HttpAuthOverride::NoOverride, - ) - .await - } - - async fn get_pre_key( - &mut self, - destination: &ServiceAddress, - device_id: u32, - ) -> Result { - let path = if let Some(ref relay) = destination.relay { - format!( - "/v2/keys/{}/{}?relay={}", - destination.identifier(), - device_id, - relay - ) - } else { - format!("/v2/keys/{}/{}", destination.identifier(), device_id) - }; - - let mut pre_key_response: PreKeyResponse = self - .get_json(Endpoint::Service, &path, HttpAuthOverride::NoOverride) - .await?; - assert!(!pre_key_response.devices.is_empty()); - - let identity = IdentityKey::decode(&pre_key_response.identity_key)?; - let device = pre_key_response.devices.remove(0); - Ok(device.into_bundle(identity)?) - } - - async fn get_pre_keys( - &mut self, - destination: &ServiceAddress, - device_id: u32, - ) -> Result, ServiceError> { - let path = match (device_id, destination.relay.as_ref()) { - (1, None) => format!("/v2/keys/{}/*", destination.identifier()), - (device_id, None) => { - format!("/v2/keys/{}/{}", destination.identifier(), device_id) - }, - (1, Some(relay)) => format!( - "/v2/keys/{}/*?relay={}", - destination.identifier(), - relay - ), - (device_id, Some(relay)) => format!( - "/v2/keys/{}/{}?relay={}", - destination.identifier(), - device_id, - relay - ), - }; - let pre_key_response: PreKeyResponse = self - .get_json(Endpoint::Service, &path, HttpAuthOverride::NoOverride) - .await?; - let mut pre_keys = vec![]; - let identity = IdentityKey::decode(&pre_key_response.identity_key)?; - for device in pre_key_response.devices { - pre_keys.push(device.into_bundle(identity)?); - } - Ok(pre_keys) - } - - async fn get_group( - &mut self, - credentials: HttpAuth, - ) -> Result { - self.get_protobuf( - Endpoint::Storage, - "/v1/groups/", - HttpAuthOverride::Identified(credentials), - ) - .await - } - - async fn set_account_attributes( - &mut self, - attributes: AccountAttributes, - ) -> Result<(), ServiceError> { - assert!( - attributes.pin.is_none() || attributes.registration_lock.is_none(), - "only one of PIN and registration lock can be set." - ); - - match self - .put_json( - Endpoint::Service, - "/v1/accounts/attributes/", - HttpAuthOverride::NoOverride, - attributes, - ) - .await - { - Err(ServiceError::JsonDecodeError { .. }) => Ok(()), - r => r, - } - } - - /// Writes a profile and returns the avatar URL, if one was provided. - /// - /// The name, about and emoji fields are encrypted with an [`ProfileCipher`]. - /// See [`AccountManager`] for a convenience method. - /// - /// Java equivalent: `writeProfile` - async fn write_profile( - &mut self, - version: &ProfileKeyVersion, - name: &[u8], - about: &[u8], - emoji: &[u8], - commitment: &ProfileKeyCommitment, - // FIXME cfr also account manager - avatar: Option<()>, - ) -> Result, ServiceError> { - #[derive(Debug, Serialize)] - #[serde(rename_all = "camelCase")] - struct SignalServiceProfileWrite<'s> { - /// Hex-encoded - version: &'s str, - #[serde(with = "serde_base64")] - name: &'s [u8], - #[serde(with = "serde_base64")] - about: &'s [u8], - #[serde(with = "serde_base64")] - about_emoji: &'s [u8], - avatar: bool, - #[serde(with = "serde_base64")] - commitment: &'s [u8], - } - - // Bincode is transparent and will return a hex-encoded string. - let version = bincode::serialize(version)?; - let version = std::str::from_utf8(&version) - .expect("profile_key_version is hex encoded string"); - let commitment = bincode::serialize(commitment)?; - - let command = SignalServiceProfileWrite { - version, - name, - about, - about_emoji: emoji, - avatar: avatar.is_some(), - commitment: &commitment, - }; - - // XXX this should be a struct; cfr ProfileAvatarUploadAttributes - let response: Result = self - .put_json( - Endpoint::Service, - "/v1/profile", - HttpAuthOverride::NoOverride, - command, - ) - .await; - match (response, avatar) { - (Ok(_url), Some(_avatar)) => { - // FIXME - unreachable!("Uploading avatar unimplemented"); - }, - // FIXME cleanup when #54883 is stable and MSRV: - // or-patterns syntax is experimental - // see issue #54883 for more information - (Err(ServiceError::JsonDecodeError { .. }), None) => { - // OWS sends an empty string when there's no attachment - Ok(None) - }, - (Err(e), _) => Err(e), - (Ok(_resp), None) => { - log::warn!( - "No avatar supplied but got avatar upload URL. Ignoring" - ); - Ok(None) - }, - } - } -} diff --git a/net/gurk-rs/files/vendor/libsignal-service/src/receiver.rs b/net/gurk-rs/files/vendor/libsignal-service/src/receiver.rs deleted file mode 100644 index 6a38445..0000000 --- a/net/gurk-rs/files/vendor/libsignal-service/src/receiver.rs +++ /dev/null @@ -1,157 +0,0 @@ -use bytes::{Buf, Bytes}; - -use crate::{ - attachment_cipher::decrypt_in_place, - configuration::ServiceCredentials, - envelope::Envelope, - messagepipe::MessagePipe, - models::{Contact, ParseContactError}, - push_service::*, -}; - -/// Equivalent of Java's `SignalServiceMessageReceiver`. -#[derive(Clone)] -pub struct MessageReceiver { - service: Service, -} - -#[derive(thiserror::Error, Debug)] -pub enum MessageReceiverError { - #[error("ServiceError")] - ServiceError(#[from] ServiceError), - - #[error("Envelope parsing error")] - EnvelopeParseError(#[from] crate::envelope::EnvelopeParseError), -} - -impl MessageReceiver { - // TODO: to avoid providing the wrong service/wrong credentials - // change it like LinkingManager or ProvisioningManager - pub fn new(service: Service) -> Self { - MessageReceiver { service } - } - - /// One-off method to receive all pending messages. - /// - /// Equivalent with Java's `SignalServiceMessageReceiver::retrieveMessages`. - /// - /// For streaming messages, use a `MessagePipe` through - /// [`MessageReceiver::create_message_pipe()`]. - pub async fn retrieve_messages( - &mut self, - ) -> Result, MessageReceiverError> { - use std::convert::TryFrom; - - let entities = self.service.get_messages().await?; - let entities = entities - .into_iter() - .map(Envelope::try_from) - .collect::>()?; - Ok(entities) - } - - pub async fn create_message_pipe( - &mut self, - credentials: ServiceCredentials, - ) -> Result, MessageReceiverError> { - let (ws, stream) = self - .service - .ws("/v1/websocket/", Some(credentials.clone())) - .await?; - Ok(MessagePipe::from_socket(ws, stream, credentials)) - } - - pub async fn retrieve_contacts( - &mut self, - contacts: &crate::proto::sync_message::Contacts, - ) -> Result< - impl Iterator>, - ServiceError, - > { - if let Some(ref blob) = contacts.blob { - use futures::io::AsyncReadExt; - - const MAX_DOWNLOAD_RETRIES: u8 = 3; - let mut retries = 0; - - let mut stream = loop { - let r = self.service.get_attachment(blob).await; - match r { - Ok(stream) => break stream, - Err(ServiceError::Timeout { .. }) => { - log::warn!("get_attachment timed out, retrying"); - retries += 1; - if retries >= MAX_DOWNLOAD_RETRIES { - return Err(ServiceError::Timeout { - reason: "too many retries".into(), - }); - } - }, - Err(e) => return Err(e), - } - }; - - let mut ciphertext = Vec::new(); - stream - .read_to_end(&mut ciphertext) - .await - .expect("streamed attachment"); - - let key_material = blob.key(); - assert_eq!( - key_material.len(), - 64, - "key material for attachments is ought to be 64 bytes" - ); - let mut key = [0u8; 64]; - key.copy_from_slice(key_material); - - decrypt_in_place(key, &mut ciphertext) - .expect("attachment decryption"); - - Ok(DeviceContactsIterator::new(Bytes::from(ciphertext))) - } else { - Ok(DeviceContactsIterator::default()) - } - } -} - -#[derive(Default)] -struct DeviceContactsIterator { - decrypted_buffer: Bytes, -} - -impl DeviceContactsIterator { - fn new(decrypted_buffer: Bytes) -> Self { - Self { decrypted_buffer } - } -} - -impl Iterator for DeviceContactsIterator { - type Item = Result; - - fn next(&mut self) -> Option { - use crate::proto::{contact_details::Avatar, ContactDetails}; - - if !self.decrypted_buffer.has_remaining() { - return None; - } - - let contact_details: ContactDetails = - prost::Message::decode_length_delimited(&mut self.decrypted_buffer) - .map_err(ParseContactError::ProtobufError) - .ok()?; - - let avatar_data = if let Some(Avatar { - length: Some(length), - .. - }) = contact_details.avatar - { - Some(self.decrypted_buffer.copy_to_bytes(length as usize)) - } else { - None - }; - - Some(Contact::from_proto(contact_details, avatar_data)) - } -} diff --git a/net/gurk-rs/files/vendor/libsignal-service/src/sealed_session_cipher.rs b/net/gurk-rs/files/vendor/libsignal-service/src/sealed_session_cipher.rs deleted file mode 100644 index 088316b..0000000 --- a/net/gurk-rs/files/vendor/libsignal-service/src/sealed_session_cipher.rs +++ /dev/null @@ -1,1118 +0,0 @@ -use std::convert::TryFrom; - -use aes::{ - cipher::{NewCipher, StreamCipher}, - Aes256Ctr, -}; - -use hmac::{Hmac, Mac, NewMac}; -use libsignal_protocol::{ - error::SignalProtocolError, message_decrypt_prekey, message_decrypt_signal, - message_encrypt, CiphertextMessageType, IdentityKeyStore, KeyPair, - PreKeySignalMessage, PreKeyStore, PrivateKey, ProtocolAddress, PublicKey, - SessionStore, SignalMessage, SignedPreKeyStore, -}; -use log::error; -use phonenumber::PhoneNumber; -use rand::{CryptoRng, Rng}; -use sha2::Sha256; -use uuid::Uuid; - -use crate::{push_service::ProfileKey, ServiceAddress}; - -#[derive(Debug, thiserror::Error)] -pub enum SealedSessionError { - #[error("Unknown version {0}")] - InvalidMetadataVersionError(u8), - - #[error("{0}")] - InvalidMetadataMessageError(String), - - #[error("Invalid MAC: {0}")] - InvalidMacError(#[from] MacError), - - #[error("Invalid certificate")] - InvalidCertificate, - - #[error("Expired certificate")] - ExpiredCertificate, - - #[error("Failed to decode protobuf {0}")] - DecodeError(#[from] prost::DecodeError), - - #[error("Failed to encode protobuf: {0}")] - EncodeError(#[from] prost::EncodeError), - - #[error("Protocol error {0}")] - ProtocolError(#[from] SignalProtocolError), - - #[error("recipient not trusted")] - NoSessionWithRecipient, - - #[error("Supplied phone number could not be parsed in E164 format")] - InvalidPhoneNumber(#[from] phonenumber::ParseError), - - #[error("Supplied uuid could not be parsed")] - InvalidUuidError(#[from] uuid::Error), -} - -#[derive(thiserror::Error, Debug)] -pub enum MacError { - #[error("Invalid MAC key length")] - InvalidKeyLength, - #[error("Ciphertext not long enough ({0} bytes) for MAC")] - CiphertextNotLongEnough(usize), - #[error("Bad MAC")] - BadMac, -} - -#[derive(Clone)] -pub(crate) struct SealedSessionCipher { - session_store: S, - identity_key_store: I, - signed_pre_key_store: SP, - pre_key_store: P, - csprng: R, - certificate_validator: CertificateValidator, -} - -#[derive(Clone)] -pub struct UnidentifiedAccessPair { - target_unidentified_access: UnidentifiedAccess, - self_unidentified_access: UnidentifiedAccess, -} - -#[derive(Clone)] -pub struct UnidentifiedAccess { - access_key: Vec, - sender_certificate: SenderCertificate, -} - -#[derive(Debug, Clone)] -struct UnidentifiedSenderMessage { - ephemeral: PublicKey, - encrypted_static: Vec, - encrypted_message: Vec, -} - -#[derive(Debug, Clone)] -pub struct UnidentifiedSenderMessageContent { - r#type: CiphertextMessageType, - sender_certificate: SenderCertificate, - content: Vec, -} - -#[derive(Debug, Clone)] -pub struct SenderCertificate { - signer: ServerCertificate, - key: PublicKey, - sender_device_id: u32, - sender_uuid: Option, - sender_e164: Option, - expiration: u64, - pub certificate: Vec, - pub signature: Vec, -} - -#[derive(Debug, Clone)] -pub struct ServerCertificate { - key_id: u32, - key: PublicKey, - certificate: Vec, - signature: Vec, -} - -#[derive(Debug, Clone)] -struct EphemeralKeys { - chain_key: Vec, - cipher_key: Vec, - mac_key: Vec, -} - -#[derive(Debug, Clone)] -struct StaticKeys { - cipher_key: Vec, - mac_key: Vec, -} - -#[derive(Debug, Clone)] -pub struct CertificateValidator { - trust_root: PublicKey, -} - -#[derive(Default, Debug, Clone)] -pub(crate) struct DecryptionResult { - pub sender_uuid: Option, - pub sender_e164: Option, - pub device_id: u32, - pub padded_message: Vec, - pub version: u32, -} - -impl UnidentifiedAccess { - pub fn new( - profile_key: &ProfileKey, - sender_certificate: SenderCertificate, - ) -> Result { - Ok(UnidentifiedAccess { - access_key: profile_key.derive_access_key(), - sender_certificate, - }) - } -} - -impl UnidentifiedSenderMessage { - const CIPHERTEXT_VERSION: u8 = 1; - - fn from_bytes(serialized: &[u8]) -> Result { - let version = serialized[0] >> 4; - if version > Self::CIPHERTEXT_VERSION { - return Err(SealedSessionError::InvalidMetadataVersionError( - version, - )); - } - - let unidentified_sender_message: crate::proto::UnidentifiedSenderMessage = - prost::Message::decode(&serialized[1..serialized.len()])?; - - match ( - unidentified_sender_message.ephemeral_public, - unidentified_sender_message.encrypted_static, - unidentified_sender_message.encrypted_message, - ) { - ( - Some(ephemeral_public), - Some(encrypted_static), - Some(encrypted_message), - ) => Ok(Self { - ephemeral: PublicKey::deserialize(&ephemeral_public)?, - encrypted_static, - encrypted_message, - }), - _ => Err(SealedSessionError::InvalidMetadataMessageError( - "Missing fields".into(), - )), - } - } - - fn into_bytes(self) -> Result, SealedSessionError> { - use prost::Message; - let mut buf = - vec![Self::CIPHERTEXT_VERSION << 4 | Self::CIPHERTEXT_VERSION]; - crate::proto::UnidentifiedSenderMessage { - ephemeral_public: Some(self.ephemeral.serialize().to_vec()), - encrypted_static: Some(self.encrypted_static), - encrypted_message: Some(self.encrypted_message), - } - .encode(&mut buf)?; - Ok(buf) - } -} - -impl SealedSessionCipher -where - S: SessionStore, - I: IdentityKeyStore, - SP: SignedPreKeyStore, - P: PreKeyStore, - R: Rng + CryptoRng, -{ - pub(crate) fn new( - session_store: S, - identity_key_store: I, - signed_pre_key_store: SP, - pre_key_store: P, - csprng: R, - certificate_validator: CertificateValidator, - ) -> Self { - Self { - session_store, - identity_key_store, - signed_pre_key_store, - pre_key_store, - csprng, - certificate_validator, - } - } - - /// unused until we make progress on https://github.com/Michael-F-Bryan/libsignal-service-rs/issues/25 - /// messages from unidentified senders can only be sent via a unidentifiedPipe - #[allow(dead_code)] - pub async fn encrypt( - &mut self, - destination: &ProtocolAddress, - sender_certificate: SenderCertificate, - padded_plaintext: &[u8], - ) -> Result, SealedSessionError> { - let message = message_encrypt( - padded_plaintext, - destination, - &mut self.session_store, - &mut self.identity_key_store, - None, - ) - .await?; - - let our_identity = - &self.identity_key_store.get_identity_key_pair(None).await?; - let their_identity = self - .identity_key_store - .get_identity(destination, None) - .await? - .ok_or(SealedSessionError::NoSessionWithRecipient)?; - - let ephemeral = KeyPair::generate(&mut self.csprng); - let ephemeral_salt = [ - b"UnidentifiedDelivery", - their_identity.serialize().as_ref(), - ephemeral.public_key.serialize().as_ref(), - ] - .concat(); - - let ephemeral_keys = self.calculate_ephemeral_keys( - their_identity.public_key(), - &ephemeral.private_key, - &ephemeral_salt, - )?; - - let static_key_ciphertext = self.encrypt_bytes( - &ephemeral_keys.cipher_key, - &ephemeral_keys.mac_key, - &our_identity.public_key().serialize(), - )?; - - let static_salt = [ - ephemeral_keys.chain_key.as_slice(), - static_key_ciphertext.as_slice(), - ] - .concat(); - - let static_keys = self.calculate_static_keys( - their_identity.public_key(), - our_identity.private_key(), - &static_salt, - )?; - - let content = UnidentifiedSenderMessageContent { - r#type: message.message_type(), - sender_certificate, - content: message.serialize().to_vec(), - }; - - let message_bytes = self.encrypt_bytes( - &static_keys.cipher_key, - &static_keys.mac_key, - &content.into_bytes()?, - )?; - - UnidentifiedSenderMessage { - ephemeral: ephemeral.public_key, - encrypted_static: static_key_ciphertext, - encrypted_message: message_bytes, - } - .into_bytes() - } - - pub async fn decrypt( - &mut self, - ciphertext: &[u8], - timestamp: u64, - ) -> Result { - let our_identity = - self.identity_key_store.get_identity_key_pair(None).await?; - - let wrapper = UnidentifiedSenderMessage::from_bytes(ciphertext)?; - - let ephemeral_salt = [ - b"UnidentifiedDelivery", - our_identity.public_key().serialize().as_ref(), - wrapper.ephemeral.serialize().as_ref(), - ] - .concat(); - - let ephemeral_keys = self.calculate_ephemeral_keys( - &wrapper.ephemeral, - our_identity.private_key(), - &ephemeral_salt, - )?; - - let static_key_bytes = Self::decrypt_bytes( - &ephemeral_keys.cipher_key, - &ephemeral_keys.mac_key, - &wrapper.encrypted_static, - )?; - - let static_key = PublicKey::deserialize(&static_key_bytes)?; - let static_salt = - [ephemeral_keys.chain_key, wrapper.encrypted_static].concat(); - let static_keys = self.calculate_static_keys( - &static_key, - our_identity.private_key(), - &static_salt, - )?; - - let message_bytes = Self::decrypt_bytes( - &static_keys.cipher_key, - &static_keys.mac_key, - &wrapper.encrypted_message, - )?; - - let content = UnidentifiedSenderMessageContent::try_from( - message_bytes.as_slice(), - )?; - self.certificate_validator - .validate(&content.sender_certificate, timestamp)?; - - self.decrypt_message_content(content).await - } - - fn calculate_ephemeral_keys( - &self, - public_key: &PublicKey, - private_key: &PrivateKey, - salt: &[u8], - ) -> Result { - let shared_secret = private_key.calculate_agreement(public_key)?; - let mut ephemeral_derived = [0; 96]; - hkdf::Hkdf::::new(Some(salt), &shared_secret) - .expand(&[], &mut ephemeral_derived) - .expect("valid output length"); - let ephemeral_keys = EphemeralKeys { - chain_key: ephemeral_derived[0..32].into(), - cipher_key: ephemeral_derived[32..64].into(), - mac_key: ephemeral_derived[64..96].into(), - }; - Ok(ephemeral_keys) - } - - fn calculate_static_keys( - &self, - public_key: &PublicKey, - private_key: &PrivateKey, - salt: &[u8], - ) -> Result { - let static_secret = private_key.calculate_agreement(public_key)?; - let mut static_derived = [0; 96]; - hkdf::Hkdf::::new(Some(salt), &static_secret) - .expand(&[], &mut static_derived) - .expect("valid output length"); - Ok(StaticKeys { - cipher_key: static_derived[32..64].into(), - mac_key: static_derived[64..96].into(), - }) - } - - fn encrypt_bytes( - &self, - cipher_key: &[u8], - mac_key: &[u8], - plaintext: &[u8], - ) -> Result, SealedSessionError> { - let mut cipher = Aes256Ctr::new(cipher_key.into(), &[0u8; 16].into()); - - let mut ciphertext = plaintext.to_vec(); - cipher.apply_keystream(&mut ciphertext); - - let mut mac = Hmac::::new_from_slice(mac_key) - .map_err(|_| MacError::InvalidKeyLength)?; - mac.update(&ciphertext); - let our_mac = mac.finalize().into_bytes(); - - let encrypted = [ciphertext.as_slice(), &our_mac[..10]].concat(); - - Ok(encrypted) - } - - fn decrypt_bytes( - cipher_key: &[u8], - mac_key: &[u8], - ciphertext: &[u8], - ) -> Result, SealedSessionError> { - if ciphertext.len() < 10 { - return Err(SealedSessionError::InvalidMacError( - MacError::CiphertextNotLongEnough(ciphertext.len()), - )); - } - - let (ciphertext_part1, their_mac) = - ciphertext.split_at(ciphertext.len() - 10); - - let mut verifier = Hmac::::new_from_slice(mac_key) - .map_err(|_| MacError::InvalidKeyLength)?; - verifier.update(ciphertext_part1); - let digest = verifier.finalize().into_bytes(); - let our_mac = &digest[..10]; - - if our_mac != their_mac { - return Err(SealedSessionError::InvalidMacError(MacError::BadMac)); - } - - let mut decrypted = ciphertext_part1.to_vec(); - let mut cipher = Aes256Ctr::new(cipher_key.into(), &[0u8; 16].into()); - cipher.apply_keystream(&mut decrypted); - - Ok(decrypted) - } - - async fn decrypt_message_content( - &mut self, - message: UnidentifiedSenderMessageContent, - ) -> Result { - let UnidentifiedSenderMessageContent { - r#type, - content, - sender_certificate, - } = message; - let sender = crate::cipher::get_preferred_protocol_address( - &self.session_store, - &sender_certificate.address(), - sender_certificate.sender_device_id, - ) - .await?; - - let msg = match r#type { - CiphertextMessageType::Whisper => { - let msg = message_decrypt_signal( - &SignalMessage::try_from(&content[..])?, - &sender, - &mut self.session_store, - &mut self.identity_key_store, - &mut self.csprng, - None, - ) - .await?; - msg.as_slice().to_vec() - }, - CiphertextMessageType::PreKey => { - let msg = message_decrypt_prekey( - &PreKeySignalMessage::try_from(&content[..])?, - &sender, - &mut self.session_store, - &mut self.identity_key_store, - &mut self.pre_key_store, - &mut self.signed_pre_key_store, - &mut self.csprng, - None, - ) - .await?; - msg.as_slice().to_vec() - }, - _ => unreachable!("unknown message from unidentified sender type"), - }; - - let version = self - .session_store - .load_session(&sender, None) - .await? - .ok_or_else(|| { - SignalProtocolError::SessionNotFound(format!("{}", sender)) - })? - .session_version()?; - - Ok(DecryptionResult { - padded_message: msg, - version, - sender_uuid: sender_certificate.sender_uuid, - sender_e164: sender_certificate.sender_e164, - device_id: sender_certificate.sender_device_id, - }) - } -} - -impl UnidentifiedSenderMessageContent { - fn try_from(serialized: &[u8]) -> Result { - use crate::proto::unidentified_sender_message::{self, message}; - - let message: unidentified_sender_message::Message = - prost::Message::decode(serialized)?; - - match (message.r#type, message.sender_certificate, message.content) { - (Some(message_type), Some(sender_certificate), Some(content)) => { - Ok(Self { - r#type: match message::Type::from_i32(message_type) { - Some(message::Type::Message) => { - CiphertextMessageType::Whisper - }, - Some(message::Type::PrekeyMessage) => { - CiphertextMessageType::PreKey - }, - t => { - return Err( - SealedSessionError::InvalidMetadataMessageError( - format!("Wrong message type ({:?})", t), - ), - ) - }, - }, - sender_certificate: SenderCertificate::try_from( - sender_certificate, - )?, - content, - }) - }, - _ => Err(SealedSessionError::InvalidMetadataMessageError( - "Missing fields".into(), - )), - } - } - - fn into_bytes(self) -> Result, SealedSessionError> { - use crate::proto::unidentified_sender_message::{self, message}; - use prost::Message; - - let data = unidentified_sender_message::Message { - r#type: Some(match self.r#type { - CiphertextMessageType::PreKey => message::Type::PrekeyMessage, - CiphertextMessageType::Whisper => message::Type::Message, - _ => { - return Err( - SealedSessionError::InvalidMetadataMessageError( - "unknown ciphertext message type".into(), - ), - ) - }, - } as i32), - sender_certificate: Some(crate::proto::SenderCertificate { - certificate: Some(self.sender_certificate.certificate), - signature: Some(self.sender_certificate.signature), - }), - content: Some(self.content), - } - .encode_to_vec(); - - Ok(data) - } -} - -impl SenderCertificate { - fn try_from( - wrapper: crate::proto::SenderCertificate, - ) -> Result { - use crate::proto::sender_certificate::Certificate; - use prost::Message; - match (wrapper.signature, wrapper.certificate) { - (Some(signature), Some(certificate)) => { - let Certificate { - sender_e164, - sender_uuid, - sender_device, - expires, - identity_key, - signer, - } = Message::decode(&certificate[..])?; - match (sender_device, expires, identity_key, signer) { - ( - Some(sender_device_id), - Some(expires), - Some(identity_key), - Some(signer), - ) => { - if sender_e164.is_none() && sender_uuid.is_none() { - return Err(SealedSessionError::InvalidCertificate); - } - - let sender_e164 = sender_e164 - .map(|s| phonenumber::parse(None, s)) - .transpose()?; - let sender_uuid = sender_uuid - .as_deref() - .map(Uuid::parse_str) - .transpose()?; - - Ok(Self { - signer: ServerCertificate::try_from(signer)?, - key: PublicKey::deserialize(&identity_key)?, - sender_e164, - sender_uuid, - sender_device_id, - expiration: expires, - certificate, - signature, - }) - }, - _ => Err(SealedSessionError::InvalidCertificate), - } - }, - _ => Err(SealedSessionError::InvalidCertificate), - } - } - - fn address(&self) -> ServiceAddress { - ServiceAddress { - uuid: self.sender_uuid, - phonenumber: self.sender_e164.clone(), - relay: None, - } - } -} - -impl ServerCertificate { - fn try_from( - wrapper: crate::proto::ServerCertificate, - ) -> Result { - use crate::proto::server_certificate; - use prost::Message; - - match (wrapper.certificate, wrapper.signature) { - (Some(certificate), Some(signature)) => { - let server_certificate: server_certificate::Certificate = - Message::decode(&certificate[..])?; - match (server_certificate.id, server_certificate.key) { - (Some(id), Some(key)) => Ok(Self { - key_id: id, - key: PublicKey::deserialize(&key)?, - certificate, - signature, - }), - _ => Err(SealedSessionError::InvalidCertificate), - } - }, - _ => Err(SealedSessionError::InvalidCertificate), - } - } -} - -impl CertificateValidator { - pub fn new(trust_root: PublicKey) -> Self { - Self { trust_root } - } - - pub(crate) fn validate( - &self, - certificate: &SenderCertificate, - validation_time: u64, - ) -> Result<(), SealedSessionError> { - let server_certificate = &certificate.signer; - - match self.trust_root.verify_signature( - &server_certificate.certificate, - &server_certificate.signature, - ) { - Err(_) | Ok(false) => { - return Err(SealedSessionError::InvalidCertificate) - }, - _ => (), - }; - - match server_certificate - .key - .verify_signature(&certificate.certificate, &certificate.signature) - { - Err(_) | Ok(false) => { - return Err(SealedSessionError::InvalidCertificate) - }, - _ => (), - } - - if validation_time > certificate.expiration { - return Err(SealedSessionError::ExpiredCertificate); - } - - Ok(()) - } -} - -#[cfg(test)] -mod tests { - use std::time::{SystemTime, UNIX_EPOCH}; - - use libsignal_protocol::{ - process_prekey_bundle, IdentityKeyPair, IdentityKeyStore, - InMemIdentityKeyStore, InMemPreKeyStore, InMemSessionStore, - InMemSignedPreKeyStore, KeyPair, PreKeyBundle, PreKeyRecord, - PreKeyStore, ProtocolAddress, PublicKey, SignedPreKeyRecord, - SignedPreKeyStore, - }; - - use crate::{provisioning::generate_registration_id, ServiceAddress}; - - use super::{ - CertificateValidator, SealedSessionCipher, SealedSessionError, - SenderCertificate, - }; - - use prost::Message; - - fn alice_address() -> ServiceAddress { - ServiceAddress::parse( - Some("+14151111111"), - Some("9d0652a3-dcc3-4d11-975f-74d61598733f"), - ) - .unwrap() - } - - struct Stores { - identity_key_store: InMemIdentityKeyStore, - session_store: InMemSessionStore, - signed_pre_key_store: InMemSignedPreKeyStore, - pre_key_store: InMemPreKeyStore, - } - - #[tokio::test] - async fn test_encrypt_decrypt() -> anyhow::Result<()> { - let mut csprng = rand::thread_rng(); - - let (alice_stores, bob_stores) = create_stores(&mut csprng).await?; - - let trust_root = KeyPair::generate(&mut csprng); - let certificate_validator = - CertificateValidator::new(trust_root.public_key); - let sender_certificate = create_certificate_for( - &trust_root, - alice_address(), - 1, - *alice_stores - .identity_key_store - .get_identity_key_pair(None) - .await? - .public_key(), - 31337, - &mut csprng, - )?; - - let mut alice_cipher = SealedSessionCipher::new( - alice_stores.session_store, - alice_stores.identity_key_store, - alice_stores.signed_pre_key_store, - alice_stores.pre_key_store, - csprng, - certificate_validator.clone(), - ); - - let ciphertext = alice_cipher - .encrypt( - &ProtocolAddress::new("+14152222222".into(), 1), - sender_certificate, - "smert za smert".as_bytes(), - ) - .await?; - - let mut bob_cipher = SealedSessionCipher::new( - bob_stores.session_store, - bob_stores.identity_key_store, - bob_stores.signed_pre_key_store, - bob_stores.pre_key_store, - csprng, - certificate_validator, - ); - - let plaintext = bob_cipher.decrypt(&ciphertext, 31335).await?; - - assert_eq!( - String::from_utf8_lossy(&plaintext.padded_message), - "smert za smert".to_string() - ); - assert_eq!(plaintext.sender_uuid, alice_address().uuid); - assert_eq!(plaintext.sender_e164, alice_address().phonenumber); - assert_eq!(plaintext.device_id, 1); - - Ok(()) - } - - #[tokio::test] - async fn test_encrypt_decrypt_untrusted() -> anyhow::Result<()> { - let mut csprng = rand::thread_rng(); - let (alice_stores, bob_stores) = create_stores(&mut csprng).await?; - - let trust_root = KeyPair::generate(&mut csprng); - let certificate_validator = - CertificateValidator::new(trust_root.public_key); - - let false_trust_root = KeyPair::generate(&mut csprng); - let false_certificate_validator = - CertificateValidator::new(false_trust_root.public_key); - - let sender_certificate = create_certificate_for( - &trust_root, - alice_address(), - 1, - *alice_stores - .identity_key_store - .get_identity_key_pair(None) - .await? - .public_key(), - 31337, - &mut csprng, - )?; - - let mut alice_cipher = SealedSessionCipher::new( - alice_stores.session_store, - alice_stores.identity_key_store, - alice_stores.signed_pre_key_store, - alice_stores.pre_key_store, - csprng, - certificate_validator, - ); - - let ciphertext = alice_cipher - .encrypt( - &ProtocolAddress::new("+14152222222".into(), 1), - sender_certificate, - "и вот я".as_bytes(), - ) - .await?; - - let mut bob_cipher = SealedSessionCipher::new( - bob_stores.session_store, - bob_stores.identity_key_store, - bob_stores.signed_pre_key_store, - bob_stores.pre_key_store, - csprng, - false_certificate_validator, - ); - - let plaintext = bob_cipher.decrypt(&ciphertext, 31335).await; - - match plaintext { - Err(SealedSessionError::InvalidCertificate) => Ok(()), - _ => panic!("decryption succeeded, this should not happen here!1!"), - } - } - - #[tokio::test] - async fn test_encrypt_decrypt_expired() -> anyhow::Result<()> { - let mut csprng = rand::thread_rng(); - let (alice_stores, bob_stores) = create_stores(&mut csprng).await?; - - let trust_root = KeyPair::generate(&mut csprng); - let certificate_validator = - CertificateValidator::new(trust_root.public_key); - let sender_certificate = create_certificate_for( - &trust_root, - alice_address(), - 1, - *alice_stores - .identity_key_store - .get_identity_key_pair(None) - .await? - .public_key(), - 31337, - &mut csprng, - )?; - - let mut alice_cipher = SealedSessionCipher::new( - alice_stores.session_store, - alice_stores.identity_key_store, - alice_stores.signed_pre_key_store, - alice_stores.pre_key_store, - csprng, - certificate_validator.clone(), - ); - - let ciphertext = alice_cipher - .encrypt( - &ProtocolAddress::new("+14152222222".into(), 1), - sender_certificate, - "smert za smert".as_bytes(), - ) - .await?; - - let mut bob_cipher = SealedSessionCipher::new( - bob_stores.session_store, - bob_stores.identity_key_store, - bob_stores.signed_pre_key_store, - bob_stores.pre_key_store, - csprng, - certificate_validator, - ); - - match bob_cipher.decrypt(&ciphertext, 31338).await { - Err(SealedSessionError::ExpiredCertificate) => Ok(()), - _ => panic!("certificate is expired, we should not get decrypted data here!11!") - } - } - - #[tokio::test] - async fn test_encrypt_from_wrong_identity() -> anyhow::Result<()> { - let mut csprng = rand::thread_rng(); - let (alice_stores, bob_stores) = create_stores(&mut csprng).await?; - - let trust_root = KeyPair::generate(&mut csprng); - let random_key_pair = KeyPair::generate(&mut csprng); - let certificate_validator = - CertificateValidator::new(trust_root.public_key); - let sender_certificate = create_certificate_for( - &random_key_pair, - alice_address(), - 1, - *alice_stores - .identity_key_store - .get_identity_key_pair(None) - .await? - .public_key(), - 31337, - &mut csprng, - )?; - - let mut alice_cipher = SealedSessionCipher::new( - alice_stores.session_store, - alice_stores.identity_key_store, - alice_stores.signed_pre_key_store, - alice_stores.pre_key_store, - csprng, - certificate_validator.clone(), - ); - - let ciphertext = alice_cipher - .encrypt( - &ProtocolAddress::new("+14152222222".into(), 1), - sender_certificate, - "smert za smert".as_bytes(), - ) - .await?; - - let mut bob_cipher = SealedSessionCipher::new( - bob_stores.session_store, - bob_stores.identity_key_store, - bob_stores.signed_pre_key_store, - bob_stores.pre_key_store, - csprng, - certificate_validator, - ); - - match bob_cipher.decrypt(&ciphertext, 31335).await { - Err(SealedSessionError::InvalidCertificate) => Ok(()), - _ => panic!("the certificate is invalid here!11"), - } - } - - async fn create_stores( - csprng: &mut R, - ) -> anyhow::Result<(Stores, Stores)> { - let mut alice_stores = Stores { - identity_key_store: InMemIdentityKeyStore::new( - IdentityKeyPair::generate(csprng), - generate_registration_id(csprng), - ), - session_store: InMemSessionStore::new(), - signed_pre_key_store: InMemSignedPreKeyStore::new(), - pre_key_store: InMemPreKeyStore::new(), - }; - - let mut bob_stores = Stores { - identity_key_store: InMemIdentityKeyStore::new( - IdentityKeyPair::generate(csprng), - generate_registration_id(csprng), - ), - session_store: InMemSessionStore::new(), - signed_pre_key_store: InMemSignedPreKeyStore::new(), - pre_key_store: InMemPreKeyStore::new(), - }; - - initialize_session(&mut alice_stores, &mut bob_stores, csprng).await?; - - Ok((alice_stores, bob_stores)) - } - - fn create_certificate_for( - trust_root: &KeyPair, - addr: ServiceAddress, - device_id: u32, - identity_key: PublicKey, - expires: u64, - csprng: &mut R, - ) -> Result { - let server_key = KeyPair::generate(csprng); - - let uuid = addr.uuid.as_ref().map(uuid::Uuid::to_string); - let e164 = addr.e164(); - - let server_certificate_bytes = - crate::proto::server_certificate::Certificate { - id: Some(1), - key: Some(server_key.public_key.serialize().into_vec()), - } - .encode_to_vec(); - - let server_certificate_signature = trust_root - .private_key - .calculate_signature(&server_certificate_bytes, csprng)?; - - let server_certificate = crate::proto::ServerCertificate { - certificate: Some(server_certificate_bytes), - signature: Some(server_certificate_signature.into_vec()), - }; - - let sender_certificate_bytes = - crate::proto::sender_certificate::Certificate { - sender_uuid: uuid, - sender_e164: e164, - sender_device: Some(device_id), - identity_key: Some(identity_key.serialize().into_vec()), - expires: Some(expires), - signer: Some(server_certificate), - } - .encode_to_vec(); - - let sender_certificate_signature = server_key - .private_key - .calculate_signature(&sender_certificate_bytes, csprng)?; - - SenderCertificate::try_from(crate::proto::SenderCertificate { - certificate: Some(sender_certificate_bytes), - signature: Some(sender_certificate_signature.into_vec()), - }) - } - - async fn initialize_session( - alice_stores: &mut Stores, - bob_stores: &mut Stores, - csprng: &mut R, - ) -> Result<(), SealedSessionError> { - let bob_pre_key = PreKeyRecord::new(1, &KeyPair::generate(csprng)); - let bob_identity_key_pair = bob_stores - .identity_key_store - .get_identity_key_pair(None) - .await?; - - // TODO: check - let signed_pre_key_pair = KeyPair::generate(csprng); - let signed_pre_key_signature = bob_identity_key_pair - .private_key() - .calculate_signature( - &signed_pre_key_pair.public_key.serialize(), - csprng, - )? - .into_vec(); - - let bob_signed_pre_key_record = SignedPreKeyRecord::new( - 2, - SystemTime::now() - .duration_since(UNIX_EPOCH) - .unwrap() - .as_millis() as u64, - &signed_pre_key_pair, - &signed_pre_key_signature, - ); - - let bob_bundle = PreKeyBundle::new( - 1, - 1, - Some((1, bob_pre_key.public_key()?)), - 2, - signed_pre_key_pair.public_key, - signed_pre_key_signature, - *bob_identity_key_pair.identity_key(), - )?; - - process_prekey_bundle( - &ProtocolAddress::new("+14152222222".into(), 1), - &mut alice_stores.session_store, - &mut alice_stores.identity_key_store, - &bob_bundle, - csprng, - None, - ) - .await?; - - bob_stores - .signed_pre_key_store - .save_signed_pre_key(2, &bob_signed_pre_key_record, None) - .await?; - bob_stores - .pre_key_store - .save_pre_key(1, &bob_pre_key, None) - .await?; - Ok(()) - } -} diff --git a/net/gurk-rs/files/vendor/libsignal-service/src/sender.rs b/net/gurk-rs/files/vendor/libsignal-service/src/sender.rs deleted file mode 100644 index 78a7524..0000000 --- a/net/gurk-rs/files/vendor/libsignal-service/src/sender.rs +++ /dev/null @@ -1,765 +0,0 @@ -use std::time::SystemTime; - -use chrono::prelude::*; -use libsignal_protocol::{ - process_prekey_bundle, IdentityKeyStore, PreKeyStore, ProtocolAddress, - SessionStore, SignalProtocolError, SignedPreKeyStore, -}; -use log::{info, trace}; -use rand::{CryptoRng, Rng}; - -use crate::{ - cipher::{get_preferred_protocol_address, ServiceCipher}, - content::ContentBody, - proto::{ - attachment_pointer::AttachmentIdentifier, - attachment_pointer::Flags as AttachmentPointerFlags, sync_message, - AttachmentPointer, SyncMessage, - }, - push_service::*, - sealed_session_cipher::UnidentifiedAccess, - session_store::SessionStoreExt, - ServiceAddress, -}; - -pub use crate::proto::{ContactDetails, GroupDetails}; - -#[derive(serde::Serialize, Debug)] -#[serde(rename_all = "camelCase")] -pub struct OutgoingPushMessage { - pub r#type: u32, - pub destination_device_id: u32, - pub destination_registration_id: u32, - pub content: String, -} - -#[derive(serde::Serialize, Debug)] -pub struct OutgoingPushMessages<'a> { - pub destination: &'a str, - pub timestamp: u64, - pub messages: Vec, - pub online: bool, -} - -#[derive(serde::Deserialize, Debug)] -#[serde(rename_all = "camelCase")] -pub struct SendMessageResponse { - pub needs_sync: bool, -} - -pub type SendMessageResult = Result; - -#[derive(Debug, Clone)] -pub struct SentMessage { - recipient: ServiceAddress, - unidentified: bool, - needs_sync: bool, -} - -/// Attachment specification to be used for uploading. -/// -/// Loose equivalent of Java's `SignalServiceAttachmentStream`. -pub struct AttachmentSpec { - pub content_type: String, - pub length: usize, - pub file_name: Option, - pub preview: Option>, - pub voice_note: Option, - pub borderless: Option, - pub width: Option, - pub height: Option, - pub caption: Option, - pub blur_hash: Option, -} - -/// Equivalent of Java's `SignalServiceMessageSender`. -#[derive(Clone)] -pub struct MessageSender { - service: Service, - cipher: ServiceCipher, - csprng: R, - session_store: S, - identity_key_store: I, - local_address: ServiceAddress, - device_id: u32, -} - -#[derive(thiserror::Error, Debug)] -pub enum AttachmentUploadError { - #[error("{0}")] - ServiceError(#[from] ServiceError), - - #[error("Could not read attachment contents")] - IoError(#[from] std::io::Error), -} - -#[derive(thiserror::Error, Debug)] -pub enum MessageSenderError { - #[error("{0}")] - ServiceError(#[from] ServiceError), - #[error("protocol error: {0}")] - ProtocolError(#[from] SignalProtocolError), - #[error("Failed to upload attachment {0}")] - AttachmentUploadError(#[from] AttachmentUploadError), - - #[error("Untrusted identity key with {identifier}")] - UntrustedIdentity { identifier: String }, - - #[error("No pre-key found to establish session with {0:?}")] - NoPreKey(ServiceAddress), - - #[error("Please try again")] - TryAgain, - - #[error("Exceeded maximum number of retries")] - MaximumRetriesLimitExceeded, - - #[error("Network failure sending message to {recipient}")] - NetworkFailure { recipient: ServiceAddress }, - - #[error("Unregistered recipient {recipient}")] - UnregisteredFailure { recipient: ServiceAddress }, - - #[error("Identity verification failure with {recipient}")] - IdentityFailure { recipient: ServiceAddress }, -} - -impl MessageSender -where - Service: PushService + Clone, - S: SessionStore + SessionStoreExt + Sync + Clone, - I: IdentityKeyStore + Clone, - SP: SignedPreKeyStore + Clone, - P: PreKeyStore + Clone, - R: Rng + CryptoRng + Clone, -{ - pub fn new( - service: Service, - cipher: ServiceCipher, - csprng: R, - session_store: S, - identity_key_store: I, - local_address: ServiceAddress, - device_id: u32, - ) -> Self { - MessageSender { - service, - cipher, - csprng, - session_store, - identity_key_store, - local_address, - device_id, - } - } - - /// Encrypts and uploads an attachment - /// - /// Contents are accepted as an owned, plain text Vec, because encryption happens in-place. - pub async fn upload_attachment( - &mut self, - spec: AttachmentSpec, - mut contents: Vec, - ) -> Result { - let len = contents.len(); - // Encrypt - let (key, iv) = { - use rand::RngCore; - let mut key = [0u8; 64]; - let mut iv = [0u8; 16]; - // thread_rng is guaranteed to be cryptographically secure - rand::thread_rng().fill_bytes(&mut key); - rand::thread_rng().fill_bytes(&mut iv); - (key, iv) - }; - - // Padded length uses an exponential bracketting thingy. - // If you want to see how it looks: - // https://www.wolframalpha.com/input/?i=plot+floor%281.05%5Eceil%28log_1.05%28x%29%29%29+for+x+from+0+to+5000000 - let padded_len: usize = { - // Java: - // return (int) Math.max(541, Math.floor(Math.pow(1.05, Math.ceil(Math.log(size) / Math.log(1.05))))) - std::cmp::max( - 541, - 1.05f64.powf((len as f64).log(1.05).ceil()).floor() as usize, - ) - }; - if padded_len < len { - log::error!( - "Padded len {} < len {}. Continuing with a privacy risk.", - padded_len, - len - ); - } else { - contents.resize(padded_len, 0); - } - - crate::attachment_cipher::encrypt_in_place(iv, key, &mut contents); - - // Request upload attributes - log::trace!("Requesting upload attributes"); - let attrs = self.service.get_attachment_v2_upload_attributes().await?; - - log::trace!("Uploading attachment"); - let (id, digest) = self - .service - .upload_attachment(&attrs, &mut std::io::Cursor::new(&contents)) - .await?; - - Ok(AttachmentPointer { - content_type: Some(spec.content_type), - key: Some(key.to_vec()), - size: Some(len as u32), - // thumbnail: Option>, - digest: Some(digest), - file_name: spec.file_name, - flags: Some( - if spec.voice_note == Some(true) { - AttachmentPointerFlags::VoiceMessage as u32 - } else { - 0 - } | if spec.borderless == Some(true) { - AttachmentPointerFlags::Borderless as u32 - } else { - 0 - }, - ), - width: spec.width, - height: spec.height, - caption: spec.caption, - blur_hash: spec.blur_hash, - upload_timestamp: Some( - SystemTime::now() - .duration_since(SystemTime::UNIX_EPOCH) - .expect("unix epoch in the past") - .as_millis() as u64, - ), - cdn_number: Some(0), - attachment_identifier: Some(AttachmentIdentifier::CdnId(id)), - ..Default::default() - }) - } - - /// Upload group details to the CDN - /// - /// Returns attachment ID and the attachment digest - async fn upload_group_details( - &mut self, - groups: Groups, - ) -> Result - where - Groups: IntoIterator, - { - use prost::Message; - let mut out = Vec::new(); - for group in groups { - group - .encode_length_delimited(&mut out) - .expect("infallible encoding"); - // XXX add avatar here - } - - let spec = AttachmentSpec { - content_type: "application/octet-stream".into(), - length: out.len(), - file_name: None, - preview: None, - voice_note: None, - borderless: None, - width: None, - height: None, - caption: None, - blur_hash: None, - }; - self.upload_attachment(spec, out).await - } - - /// Upload contact details to the CDN - /// - /// Returns attachment ID and the attachment digest - async fn upload_contact_details( - &mut self, - contacts: Contacts, - ) -> Result - where - Contacts: IntoIterator, - { - use prost::Message; - let mut out = Vec::new(); - for contact in contacts { - contact - .encode_length_delimited(&mut out) - .expect("infallible encoding"); - // XXX add avatar here - } - - let spec = AttachmentSpec { - content_type: "application/octet-stream".into(), - length: out.len(), - file_name: None, - preview: None, - voice_note: None, - borderless: None, - width: None, - height: None, - caption: None, - blur_hash: None, - }; - self.upload_attachment(spec, out).await - } - - /// Send a message `content` to a single `recipient`. - pub async fn send_message( - &mut self, - recipient: &ServiceAddress, - unidentified_access: Option<&UnidentifiedAccess>, - message: impl Into, - timestamp: u64, - online: bool, - ) -> SendMessageResult { - let content_body = message.into(); - - use crate::proto::data_message::Flags; - let end_session = match &content_body { - ContentBody::DataMessage(message) => { - message.flags == Some(Flags::EndSession as u32) - }, - _ => false, - }; - - let mut results = vec![ - self.try_send_message( - recipient.clone(), - unidentified_access, - &content_body, - timestamp, - online, - ) - .await, - ]; - - match (&content_body, &results[0]) { - // if we sent a data message and we have linked devices, we need to send a sync message - ( - ContentBody::DataMessage(message), - Ok(SentMessage { needs_sync, .. }), - ) if *needs_sync => { - log::debug!("sending multi-device sync message"); - let sync_message = self - .create_multi_device_sent_transcript_content( - Some(recipient), - Some(message.clone()), - timestamp, - &results, - ); - self.try_send_message( - (&self.local_address).clone(), - None, - &sync_message, - timestamp, - false, - ) - .await?; - }, - _ => (), - } - - if end_session { - log::debug!("ending session with {}", recipient); - if let Some(ref uuid) = recipient.uuid { - self.session_store - .delete_all_sessions(&uuid.to_string()) - .await?; - } - if let Some(e164) = recipient.e164() { - self.session_store.delete_all_sessions(&e164).await?; - } - } - - results.remove(0) - } - - /// Send a message to the recipients in a group. - pub async fn send_message_to_group( - &mut self, - recipients: impl AsRef<[ServiceAddress]>, - unidentified_access: Option<&UnidentifiedAccess>, - message: crate::proto::DataMessage, - timestamp: u64, - online: bool, - ) -> Vec { - let content_body: ContentBody = message.clone().into(); - let mut results = vec![]; - - let recipients = recipients.as_ref(); - let mut needs_sync_in_results = false; - for recipient in recipients.iter() { - let result = self - .try_send_message( - recipient.clone(), - unidentified_access, - &content_body, - timestamp, - online, - ) - .await; - - match result { - Ok(SentMessage { needs_sync, .. }) if needs_sync => { - needs_sync_in_results = true; - }, - _ => (), - }; - - results.push(result); - } - - // we only need to send a synchronization message once - if needs_sync_in_results { - let sync_message = self - .create_multi_device_sent_transcript_content( - None, - Some(message.clone()), - timestamp, - &results, - ); - - let result = self - .try_send_message( - self.local_address.clone(), - unidentified_access, - &sync_message, - timestamp, - false, - ) - .await; - - results.push(result); - } - - results - } - - /// Send a message (`content`) to an address (`recipient`). - async fn try_send_message( - &mut self, - recipient: ServiceAddress, - unidentified_access: Option<&UnidentifiedAccess>, - content_body: &ContentBody, - timestamp: u64, - online: bool, - ) -> SendMessageResult { - use prost::Message; - let content = content_body.clone().into_proto(); - let content_bytes = content.encode_to_vec(); - - for _ in 0..4u8 { - let messages = self - .create_encrypted_messages(&recipient, None, &content_bytes) - .await?; - - let destination = recipient.identifier(); - let messages = OutgoingPushMessages { - destination: &destination, - timestamp, - messages, - online, - }; - - match self.service.send_messages(messages).await { - Ok(SendMessageResponse { needs_sync }) => { - log::debug!("message sent!"); - return Ok(SentMessage { - recipient, - unidentified: unidentified_access.is_some(), - needs_sync, - }); - }, - Err(ServiceError::MismatchedDevicesException(ref m)) => { - log::debug!("{:?}", m); - for extra_device_id in &m.extra_devices { - log::debug!( - "dropping session with device {}", - extra_device_id - ); - self.session_store - .delete_service_addr_device_session( - &recipient, - *extra_device_id, - ) - .await?; - } - - for missing_device_id in &m.missing_devices { - log::debug!( - "creating session with missing device {}", - missing_device_id - ); - let remote_address = ProtocolAddress::new( - recipient.identifier(), - *missing_device_id, - ); - let pre_key = self - .service - .get_pre_key(&recipient, *missing_device_id) - .await?; - - process_prekey_bundle( - &remote_address, - &mut self.session_store, - &mut self.identity_key_store, - &pre_key, - &mut self.csprng, - None, - ) - .await - .map_err(|e| { - log::error!("failed to create session: {}", e); - MessageSenderError::UntrustedIdentity { - identifier: recipient.identifier(), - } - })?; - } - }, - Err(ServiceError::StaleDevices(ref m)) => { - log::debug!("{:?}", m); - for extra_device_id in &m.stale_devices { - log::debug!( - "dropping session with device {}", - extra_device_id - ); - self.session_store - .delete_service_addr_device_session( - &recipient, - *extra_device_id, - ) - .await?; - } - }, - Err(e) => return Err(MessageSenderError::ServiceError(e)), - } - } - - Err(MessageSenderError::MaximumRetriesLimitExceeded) - } - - /// Upload group details to the CDN and send a sync message - pub async fn send_groups_details( - &mut self, - recipient: &ServiceAddress, - unidentified_access: Option<&UnidentifiedAccess>, - // XXX It may be interesting to use an intermediary type, - // instead of GroupDetails directly, - // because it allows us to add the avatar content. - groups: Groups, - online: bool, - ) -> Result<(), MessageSenderError> - where - Groups: IntoIterator, - { - let ptr = self.upload_group_details(groups).await?; - - let msg = SyncMessage { - groups: Some(sync_message::Groups { blob: Some(ptr) }), - ..Default::default() - }; - - self.send_message( - recipient, - unidentified_access, - msg, - Utc::now().timestamp_millis() as u64, - online, - ) - .await?; - - Ok(()) - } - - /// Upload contact details to the CDN and send a sync message - pub async fn send_contact_details( - &mut self, - recipient: &ServiceAddress, - unidentified_access: Option<&UnidentifiedAccess>, - // XXX It may be interesting to use an intermediary type, - // instead of ContactDetails directly, - // because it allows us to add the avatar content. - contacts: Contacts, - online: bool, - complete: bool, - ) -> Result<(), MessageSenderError> - where - Contacts: IntoIterator, - { - let ptr = self.upload_contact_details(contacts).await?; - - let msg = SyncMessage { - contacts: Some(sync_message::Contacts { - blob: Some(ptr), - complete: Some(complete), - }), - ..Default::default() - }; - - self.send_message( - recipient, - unidentified_access, - msg, - Utc::now().timestamp_millis() as u64, - online, - ) - .await?; - - Ok(()) - } - - // Equivalent with `getEncryptedMessages` - async fn create_encrypted_messages( - &mut self, - recipient: &ServiceAddress, - unidentified_access: Option, - content: &[u8], - ) -> Result, MessageSenderError> { - let mut messages = vec![]; - - let myself = recipient.matches(&self.local_address); - if !myself || unidentified_access.is_some() { - trace!("sending message to default device"); - messages.push( - self.create_encrypted_message( - recipient, - unidentified_access.as_ref(), - DEFAULT_DEVICE_ID, - content, - ) - .await?, - ); - } - - for device_id in - recipient.sub_device_sessions(&self.session_store).await? - { - trace!("sending message to device {}", device_id); - let ppa = get_preferred_protocol_address( - &self.session_store, - recipient, - device_id, - ) - .await?; - if self.session_store.load_session(&ppa, None).await?.is_some() { - messages.push( - self.create_encrypted_message( - recipient, - unidentified_access.as_ref(), - device_id, - content, - ) - .await?, - ) - } - } - - Ok(messages) - } - - /// Equivalent to `getEncryptedMessage` - /// - /// When no session with the recipient exists, we need to create one. - async fn create_encrypted_message( - &mut self, - recipient: &ServiceAddress, - unidentified_access: Option<&UnidentifiedAccess>, - device_id: u32, - content: &[u8], - ) -> Result { - let recipient_address = get_preferred_protocol_address( - &self.session_store, - recipient, - device_id, - ) - .await?; - log::trace!("encrypting message for {:?}", recipient_address); - - if self - .session_store - .load_session(&recipient_address, None) - .await? - .is_none() - { - info!("establishing new session with {:?}", recipient_address); - let pre_keys = - self.service.get_pre_keys(recipient, device_id).await?; - for pre_key_bundle in pre_keys { - if recipient.matches(&self.local_address) - && self.device_id == pre_key_bundle.device_id()? - { - trace!("not establishing a session with myself!"); - continue; - } - - let pre_key_address = get_preferred_protocol_address( - &self.session_store, - recipient, - pre_key_bundle.device_id()?, - ) - .await?; - - process_prekey_bundle( - &pre_key_address, - &mut self.session_store, - &mut self.identity_key_store, - &pre_key_bundle, - &mut self.csprng, - None, - ) - .await?; - } - } - - let message = self - .cipher - .encrypt(&recipient_address, unidentified_access, content) - .await?; - Ok(message) - } - - fn create_multi_device_sent_transcript_content( - &self, - recipient: Option<&ServiceAddress>, - data_message: Option, - timestamp: u64, - send_message_results: &[SendMessageResult], - ) -> ContentBody { - use sync_message::sent::UnidentifiedDeliveryStatus; - let unidentified_status: Vec = - send_message_results - .iter() - .filter_map(|result| result.as_ref().ok()) - .map(|sent| { - let SentMessage { - recipient, - unidentified, - .. - } = sent; - UnidentifiedDeliveryStatus { - destination_e164: recipient.e164(), - destination_uuid: recipient.uuid.map(|s| s.to_string()), - unidentified: Some(*unidentified), - } - }) - .collect(); - ContentBody::SynchronizeMessage(SyncMessage { - sent: Some(sync_message::Sent { - destination_uuid: recipient - .and_then(|r| r.uuid) - .map(|u| u.to_string()), - destination_e164: recipient.and_then(|r| r.e164()), - message: data_message, - timestamp: Some(timestamp), - unidentified_status, - ..Default::default() - }), - ..Default::default() - }) - } -} diff --git a/net/gurk-rs/files/vendor/libsignal-service/src/service_address.rs b/net/gurk-rs/files/vendor/libsignal-service/src/service_address.rs deleted file mode 100644 index f183836..0000000 --- a/net/gurk-rs/files/vendor/libsignal-service/src/service_address.rs +++ /dev/null @@ -1,119 +0,0 @@ -use phonenumber::*; -use serde::{Deserialize, Serialize}; -use uuid::Uuid; - -use crate::{push_service::ServiceError, session_store::SessionStoreExt}; - -#[derive(thiserror::Error, Debug)] -pub enum ParseServiceAddressError { - #[error("Supplied phone number could not be parsed in E164 format")] - InvalidPhoneNumber(#[from] phonenumber::ParseError), - - #[error("Supplied uuid could not be parsed")] - InvalidUuidError(#[from] uuid::Error), - - #[error("Envelope with neither Uuid or E164")] - NoSenderError, -} - -#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)] -pub struct ServiceAddress { - pub uuid: Option, - pub phonenumber: Option, - pub relay: Option, -} - -impl ServiceAddress { - /// Formats the phone number, if present, as E164 - pub fn e164(&self) -> Option { - self.phonenumber - .as_ref() - .map(|pn| pn.format().mode(phonenumber::Mode::E164).to_string()) - } - - pub async fn sub_device_sessions( - &self, - session_store: &dyn SessionStoreExt, - ) -> Result, ServiceError> { - let mut sub_device_sessions = Vec::new(); - if let Some(uuid) = &self.uuid { - sub_device_sessions.extend( - session_store - .get_sub_device_sessions(&uuid.to_string()) - .await?, - ); - } - if let Some(e164) = &self.e164() { - sub_device_sessions - .extend(session_store.get_sub_device_sessions(e164).await?); - } - Ok(sub_device_sessions) - } -} - -impl std::fmt::Display for ServiceAddress { - fn fmt( - &self, - f: &mut std::fmt::Formatter<'_>, - ) -> Result<(), std::fmt::Error> { - match (&self.uuid, &self.phonenumber, &self.relay) { - (_, Some(e164), _) => write!(f, "ServiceAddress({})", e164), - (Some(uuid), _, _) => write!(f, "ServiceAddress({})", uuid), - _ => write!(f, "ServiceAddress(INVALID)"), - } - } -} - -impl ServiceAddress { - pub fn parse( - e164: Option<&str>, - uuid: Option<&str>, - ) -> Result { - let phonenumber = - e164.map(|s| phonenumber::parse(None, s)).transpose()?; - let uuid = uuid.map(Uuid::parse_str).transpose()?; - - Ok(ServiceAddress { - phonenumber, - uuid, - relay: None, - }) - } - - /// Returns uuid if present, e164 otherwise. - pub fn identifier(&self) -> String { - if let Some(ref uuid) = self.uuid { - return uuid.to_string(); - } else if let Some(e164) = self.e164() { - return e164; - } - unreachable!( - "an address requires either a UUID or a E164 phone number" - ); - } - - pub fn matches(&self, other: &Self) -> bool { - (self.phonenumber.is_some() && self.phonenumber == other.phonenumber) - || (self.uuid.is_some() && self.uuid == other.uuid) - } -} - -impl From for ServiceAddress { - fn from(uuid: Uuid) -> Self { - ServiceAddress { - uuid: Some(uuid), - phonenumber: None, - relay: None, - } - } -} - -impl From for ServiceAddress { - fn from(phone_number: PhoneNumber) -> Self { - ServiceAddress { - uuid: None, - phonenumber: Some(phone_number), - relay: None, - } - } -} diff --git a/net/gurk-rs/files/vendor/libsignal-service/src/session_store.rs b/net/gurk-rs/files/vendor/libsignal-service/src/session_store.rs deleted file mode 100644 index 45a066b..0000000 --- a/net/gurk-rs/files/vendor/libsignal-service/src/session_store.rs +++ /dev/null @@ -1,69 +0,0 @@ -use libsignal_protocol::{ProtocolAddress, SessionStore, SignalProtocolError}; - -use crate::ServiceAddress; - -/// This is additional functions required to handle -/// session deletion. It might be a candidate for inclusion into -/// the bigger `SessionStore` trait. -#[cfg_attr(feature = "unsend-futures", async_trait::async_trait(?Send))] -#[cfg_attr(not(feature = "unsend-futures"), async_trait::async_trait)] -pub trait SessionStoreExt: SessionStore { - /// Get the IDs of all known devices with active sessions for a recipient. - async fn get_sub_device_sessions( - &self, - name: &str, - ) -> Result, SignalProtocolError>; - - /// Remove a session record for a recipient ID + device ID tuple. - async fn delete_session( - &self, - address: &ProtocolAddress, - ) -> Result<(), SignalProtocolError>; - - /// Remove the session records corresponding to all devices of a recipient - /// ID. - /// - /// Returns the number of deleted sessions. - async fn delete_all_sessions( - &self, - address: &str, - ) -> Result; - - /// Remove a session record for a recipient ID + device ID tuple. - async fn delete_service_addr_device_session( - &self, - address: &ServiceAddress, - device_id: u32, - ) -> Result { - let mut count = 0; - if let Some(ref uuid) = address.uuid { - match self - .delete_session(&ProtocolAddress::new( - uuid.to_string(), - device_id, - )) - .await - { - Ok(()) => { - count += 1; - }, - Err(SignalProtocolError::SessionNotFound(_)) => (), - Err(e) => return Err(e), - } - } - if let Some(e164) = address.e164() { - match self - .delete_session(&ProtocolAddress::new(e164, device_id)) - .await - { - Ok(()) => { - count += 1; - }, - Err(SignalProtocolError::SessionNotFound(_)) => (), - Err(e) => return Err(e), - } - } - - Ok(count) - } -} diff --git a/net/gurk-rs/files/vendor/libsignal-service/src/utils.rs b/net/gurk-rs/files/vendor/libsignal-service/src/utils.rs deleted file mode 100644 index 8b15447..0000000 --- a/net/gurk-rs/files/vendor/libsignal-service/src/utils.rs +++ /dev/null @@ -1,145 +0,0 @@ -pub mod serde_base64 { - use serde::{Deserialize, Deserializer, Serializer}; - - pub fn serialize(bytes: &T, serializer: S) -> Result - where - T: AsRef<[u8]>, - S: Serializer, - { - serializer.serialize_str(&base64::encode(bytes.as_ref())) - } - - pub fn deserialize<'de, D>(deserializer: D) -> Result, D::Error> - where - D: Deserializer<'de>, - { - use serde::de::Error; - String::deserialize(deserializer).and_then(|string| { - base64::decode(&string) - .map_err(|err| Error::custom(err.to_string())) - }) - } -} - -pub mod serde_optional_base64 { - use serde::{Deserialize, Deserializer, Serializer}; - - pub fn serialize( - bytes: &Option, - serializer: S, - ) -> Result - where - T: AsRef<[u8]>, - S: Serializer, - { - match bytes { - Some(bytes) => { - serializer.serialize_str(&base64::encode(bytes.as_ref())) - }, - None => serializer.serialize_none(), - } - } - - pub fn deserialize<'de, D>( - deserializer: D, - ) -> Result>, D::Error> - where - D: Deserializer<'de>, - { - use serde::de::Error; - match Option::::deserialize(deserializer)? { - Some(s) => base64::decode(&s) - .map_err(|err| Error::custom(err.to_string())) - .map(Some), - None => Ok(None), - } - } -} - -pub mod serde_public_key { - use libsignal_protocol::PublicKey; - use serde::{Deserialize, Deserializer, Serializer}; - - pub fn serialize( - public_key: &PublicKey, - serializer: S, - ) -> Result - where - S: Serializer, - { - let public_key = public_key.serialize(); - serializer.serialize_str(&base64::encode(&public_key)) - } - - pub fn deserialize<'de, D>(deserializer: D) -> Result - where - D: Deserializer<'de>, - { - PublicKey::deserialize( - &base64::decode(String::deserialize(deserializer)?) - .map_err(serde::de::Error::custom)?, - ) - .map_err(serde::de::Error::custom) - } -} - -pub mod serde_private_key { - use libsignal_protocol::PrivateKey; - use serde::{Deserialize, Deserializer, Serializer}; - - pub fn serialize( - public_key: &PrivateKey, - serializer: S, - ) -> Result - where - S: Serializer, - { - let public_key = public_key.serialize(); - serializer.serialize_str(&base64::encode(&public_key)) - } - - pub fn deserialize<'de, D>(deserializer: D) -> Result - where - D: Deserializer<'de>, - { - PrivateKey::deserialize( - &base64::decode(String::deserialize(deserializer)?) - .map_err(serde::de::Error::custom)?, - ) - .map_err(serde::de::Error::custom) - } -} - -pub mod serde_signaling_key { - use std::convert::TryInto; - - use crate::configuration::SignalingKey; - use serde::{Deserialize, Deserializer, Serializer}; - - pub fn serialize( - signaling_key: &SignalingKey, - serializer: S, - ) -> Result - where - S: Serializer, - { - serializer.serialize_str(&base64::encode(signaling_key)) - } - - pub fn deserialize<'de, D>( - deserializer: D, - ) -> Result - where - D: Deserializer<'de>, - { - base64::decode(String::deserialize(deserializer)?) - .map_err(serde::de::Error::custom)? - .try_into() - .map_err(|buf: Vec| { - serde::de::Error::invalid_length( - buf.len(), - &"invalid signaling key length", - ) - }) - } -} diff --git a/net/gurk-rs/files/vendor/poksho/.cargo-checksum.json b/net/gurk-rs/files/vendor/poksho/.cargo-checksum.json deleted file mode 100644 index b613875..0000000 --- a/net/gurk-rs/files/vendor/poksho/.cargo-checksum.json +++ /dev/null @@ -1 +0,0 @@ -{"files":{"Cargo.toml":"bd6f15613c220593ac255bb0cbb00912a2f02fea81a677fa79eb8f0be791c301","LICENSE":"b464c1a66f1760ccd0d71b24dd294bf1c23dd6a6f0b08610a6572f6f7f81f0e8","README.md":"0e84814c851ccf230126962fa479871a9b7096c9fa8ab6355cacd069460247c3","src/args.rs":"7b575d1c4f7257d9a39279ebacc0578a84e6263ddd545871047faf23f1bb1dc2","src/errors.rs":"c2cca106ba437da185b598907a164f7f836495d65def764ba8210c0d6172072b","src/lib.rs":"70340dbc0f578f0dab5070099678a531db71fdcc046d56cb3a992b6faa51b89a","src/proof.rs":"2f98a4d74aa25ae074556df419447a8876450349c5c5398cae330a34ca8a712c","src/scalar.rs":"87c5537f03cee15dfaae506ca3a0b69ed2d52abe34e9e1e0b9bb2431329576d5","src/shoapi.rs":"40bd425df2395ffb29d010c4b4a69e98432cc34533efb38b825ef5734dcf9fe8","src/shohmacsha256.rs":"30fbf2a85a155f92de51e6868112489b3825c5f57b1370bed9f14f68f174b8bc","src/shosha256.rs":"d8351280043a05f56601333ea2695faaf5a117bd243764e4655019fe50a2b555","src/sign.rs":"398d9189faf4278986899bc00308ff0b6bc1f6902f6b36def10fc58ad454106c","src/simple_types.rs":"7129bf743e4c5affa238df63e1c806b79557a595bc39128e2b2a28a7abb6acc0","src/statement.rs":"60e0445cd819c3ad2dc65cf706e01286fba4b47748bc13f2b3d77da59975692f"},"package":null} \ No newline at end of file diff --git a/net/gurk-rs/files/vendor/poksho/Cargo.toml b/net/gurk-rs/files/vendor/poksho/Cargo.toml deleted file mode 100644 index 8918384..0000000 --- a/net/gurk-rs/files/vendor/poksho/Cargo.toml +++ /dev/null @@ -1,30 +0,0 @@ -# -# Copyright (C) 2020 Signal Messenger, LLC. -# All rights reserved. -# -# SPDX-License-Identifier: GPL-3.0-only -# - -[package] -name = "poksho" -version = "0.7.0" -authors = ["Trevor Perrin "] -edition = "2018" -license = "GPL-3.0-only" - -[dependencies] -sha2 = "0.8.0" -hmac = "0.7.1" - -[dependencies.curve25519-dalek] -features = ["serde", "alloc"] -version = "2.0.0" -git = "https://github.com/signalapp/curve25519-dalek.git" -branch = "lizard2" - -[features] -default = ["u64_backend"] -u32_backend = ["curve25519-dalek/u32_backend"] -u64_backend = ["curve25519-dalek/u64_backend"] -simd_backend = ["curve25519-dalek/simd_backend"] -nightly = ["curve25519-dalek/nightly"] diff --git a/net/gurk-rs/files/vendor/poksho/LICENSE b/net/gurk-rs/files/vendor/poksho/LICENSE deleted file mode 100644 index 82c2048..0000000 --- a/net/gurk-rs/files/vendor/poksho/LICENSE +++ /dev/null @@ -1,628 +0,0 @@ -This software is provided under: - - SPDX-License-Identifier: GPL-3.0-only - -The complete license text: - - GNU GENERAL PUBLIC LICENSE - Version 3, 29 June 2007 - - Copyright (C) 2007 Free Software Foundation, Inc. - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - - Preamble - - The GNU General Public License is a free, copyleft license for -software and other kinds of works. - - The licenses for most software and other practical works are designed -to take away your freedom to share and change the works. By contrast, -the GNU General Public License is intended to guarantee your freedom to -share and change all versions of a program--to make sure it remains free -software for all its users. We, the Free Software Foundation, use the -GNU General Public License for most of our software; it applies also to -any other work released this way by its authors. You can apply it to -your programs, too. - - When we speak of free software, we are referring to freedom, not -price. Our General Public Licenses are designed to make sure that you -have the freedom to distribute copies of free software (and charge for -them if you wish), that you receive source code or can get it if you -want it, that you can change the software or use pieces of it in new -free programs, and that you know you can do these things. - - To protect your rights, we need to prevent others from denying you -these rights or asking you to surrender the rights. Therefore, you have -certain responsibilities if you distribute copies of the software, or if -you modify it: responsibilities to respect the freedom of others. - - For example, if you distribute copies of such a program, whether -gratis or for a fee, you must pass on to the recipients the same -freedoms that you received. You must make sure that they, too, receive -or can get the source code. And you must show them these terms so they -know their rights. - - Developers that use the GNU GPL protect your rights with two steps: -(1) assert copyright on the software, and (2) offer you this License -giving you legal permission to copy, distribute and/or modify it. - - For the developers' and authors' protection, the GPL clearly explains -that there is no warranty for this free software. For both users' and -authors' sake, the GPL requires that modified versions be marked as -changed, so that their problems will not be attributed erroneously to -authors of previous versions. - - Some devices are designed to deny users access to install or run -modified versions of the software inside them, although the manufacturer -can do so. This is fundamentally incompatible with the aim of -protecting users' freedom to change the software. The systematic -pattern of such abuse occurs in the area of products for individuals to -use, which is precisely where it is most unacceptable. Therefore, we -have designed this version of the GPL to prohibit the practice for those -products. If such problems arise substantially in other domains, we -stand ready to extend this provision to those domains in future versions -of the GPL, as needed to protect the freedom of users. - - Finally, every program is threatened constantly by software patents. -States should not allow patents to restrict development and use of -software on general-purpose computers, but in those that do, we wish to -avoid the special danger that patents applied to a free program could -make it effectively proprietary. To prevent this, the GPL assures that -patents cannot be used to render the program non-free. - - The precise terms and conditions for copying, distribution and -modification follow. - - TERMS AND CONDITIONS - - 0. Definitions. - - "This License" refers to version 3 of the GNU General Public License. - - "Copyright" also means copyright-like laws that apply to other kinds of -works, such as semiconductor masks. - - "The Program" refers to any copyrightable work licensed under this -License. Each licensee is addressed as "you". "Licensees" and -"recipients" may be individuals or organizations. - - To "modify" a work means to copy from or adapt all or part of the work -in a fashion requiring copyright permission, other than the making of an -exact copy. The resulting work is called a "modified version" of the -earlier work or a work "based on" the earlier work. - - A "covered work" means either the unmodified Program or a work based -on the Program. - - To "propagate" a work means to do anything with it that, without -permission, would make you directly or secondarily liable for -infringement under applicable copyright law, except executing it on a -computer or modifying a private copy. Propagation includes copying, -distribution (with or without modification), making available to the -public, and in some countries other activities as well. - - To "convey" a work means any kind of propagation that enables other -parties to make or receive copies. Mere interaction with a user through -a computer network, with no transfer of a copy, is not conveying. - - An interactive user interface displays "Appropriate Legal Notices" -to the extent that it includes a convenient and prominently visible -feature that (1) displays an appropriate copyright notice, and (2) -tells the user that there is no warranty for the work (except to the -extent that warranties are provided), that licensees may convey the -work under this License, and how to view a copy of this License. If -the interface presents a list of user commands or options, such as a -menu, a prominent item in the list meets this criterion. - - 1. Source Code. - - The "source code" for a work means the preferred form of the work -for making modifications to it. "Object code" means any non-source -form of a work. - - A "Standard Interface" means an interface that either is an official -standard defined by a recognized standards body, or, in the case of -interfaces specified for a particular programming language, one that -is widely used among developers working in that language. - - The "System Libraries" of an executable work include anything, other -than the work as a whole, that (a) is included in the normal form of -packaging a Major Component, but which is not part of that Major -Component, and (b) serves only to enable use of the work with that -Major Component, or to implement a Standard Interface for which an -implementation is available to the public in source code form. A -"Major Component", in this context, means a major essential component -(kernel, window system, and so on) of the specific operating system -(if any) on which the executable work runs, or a compiler used to -produce the work, or an object code interpreter used to run it. - - The "Corresponding Source" for a work in object code form means all -the source code needed to generate, install, and (for an executable -work) run the object code and to modify the work, including scripts to -control those activities. However, it does not include the work's -System Libraries, or general-purpose tools or generally available free -programs which are used unmodified in performing those activities but -which are not part of the work. For example, Corresponding Source -includes interface definition files associated with source files for -the work, and the source code for shared libraries and dynamically -linked subprograms that the work is specifically designed to require, -such as by intimate data communication or control flow between those -subprograms and other parts of the work. - - The Corresponding Source need not include anything that users -can regenerate automatically from other parts of the Corresponding -Source. - - The Corresponding Source for a work in source code form is that -same work. - - 2. Basic Permissions. - - All rights granted under this License are granted for the term of -copyright on the Program, and are irrevocable provided the stated -conditions are met. This License explicitly affirms your unlimited -permission to run the unmodified Program. The output from running a -covered work is covered by this License only if the output, given its -content, constitutes a covered work. This License acknowledges your -rights of fair use or other equivalent, as provided by copyright law. - - You may make, run and propagate covered works that you do not -convey, without conditions so long as your license otherwise remains -in force. You may convey covered works to others for the sole purpose -of having them make modifications exclusively for you, or provide you -with facilities for running those works, provided that you comply with -the terms of this License in conveying all material for which you do -not control copyright. Those thus making or running the covered works -for you must do so exclusively on your behalf, under your direction -and control, on terms that prohibit them from making any copies of -your copyrighted material outside their relationship with you. - - Conveying under any other circumstances is permitted solely under -the conditions stated below. Sublicensing is not allowed; section 10 -makes it unnecessary. - - 3. Protecting Users' Legal Rights From Anti-Circumvention Law. - - No covered work shall be deemed part of an effective technological -measure under any applicable law fulfilling obligations under article -11 of the WIPO copyright treaty adopted on 20 December 1996, or -similar laws prohibiting or restricting circumvention of such -measures. - - When you convey a covered work, you waive any legal power to forbid -circumvention of technological measures to the extent such circumvention -is effected by exercising rights under this License with respect to -the covered work, and you disclaim any intention to limit operation or -modification of the work as a means of enforcing, against the work's -users, your or third parties' legal rights to forbid circumvention of -technological measures. - - 4. Conveying Verbatim Copies. - - You may convey verbatim copies of the Program's source code as you -receive it, in any medium, provided that you conspicuously and -appropriately publish on each copy an appropriate copyright notice; -keep intact all notices stating that this License and any -non-permissive terms added in accord with section 7 apply to the code; -keep intact all notices of the absence of any warranty; and give all -recipients a copy of this License along with the Program. - - You may charge any price or no price for each copy that you convey, -and you may offer support or warranty protection for a fee. - - 5. Conveying Modified Source Versions. - - You may convey a work based on the Program, or the modifications to -produce it from the Program, in the form of source code under the -terms of section 4, provided that you also meet all of these conditions: - - a) The work must carry prominent notices stating that you modified - it, and giving a relevant date. - - b) The work must carry prominent notices stating that it is - released under this License and any conditions added under section - 7. This requirement modifies the requirement in section 4 to - "keep intact all notices". - - c) You must license the entire work, as a whole, under this - License to anyone who comes into possession of a copy. This - License will therefore apply, along with any applicable section 7 - additional terms, to the whole of the work, and all its parts, - regardless of how they are packaged. This License gives no - permission to license the work in any other way, but it does not - invalidate such permission if you have separately received it. - - d) If the work has interactive user interfaces, each must display - Appropriate Legal Notices; however, if the Program has interactive - interfaces that do not display Appropriate Legal Notices, your - work need not make them do so. - - A compilation of a covered work with other separate and independent -works, which are not by their nature extensions of the covered work, -and which are not combined with it such as to form a larger program, -in or on a volume of a storage or distribution medium, is called an -"aggregate" if the compilation and its resulting copyright are not -used to limit the access or legal rights of the compilation's users -beyond what the individual works permit. Inclusion of a covered work -in an aggregate does not cause this License to apply to the other -parts of the aggregate. - - 6. Conveying Non-Source Forms. - - You may convey a covered work in object code form under the terms -of sections 4 and 5, provided that you also convey the -machine-readable Corresponding Source under the terms of this License, -in one of these ways: - - a) Convey the object code in, or embodied in, a physical product - (including a physical distribution medium), accompanied by the - Corresponding Source fixed on a durable physical medium - customarily used for software interchange. - - b) Convey the object code in, or embodied in, a physical product - (including a physical distribution medium), accompanied by a - written offer, valid for at least three years and valid for as - long as you offer spare parts or customer support for that product - model, to give anyone who possesses the object code either (1) a - copy of the Corresponding Source for all the software in the - product that is covered by this License, on a durable physical - medium customarily used for software interchange, for a price no - more than your reasonable cost of physically performing this - conveying of source, or (2) access to copy the - Corresponding Source from a network server at no charge. - - c) Convey individual copies of the object code with a copy of the - written offer to provide the Corresponding Source. This - alternative is allowed only occasionally and noncommercially, and - only if you received the object code with such an offer, in accord - with subsection 6b. - - d) Convey the object code by offering access from a designated - place (gratis or for a charge), and offer equivalent access to the - Corresponding Source in the same way through the same place at no - further charge. You need not require recipients to copy the - Corresponding Source along with the object code. If the place to - copy the object code is a network server, the Corresponding Source - may be on a different server (operated by you or a third party) - that supports equivalent copying facilities, provided you maintain - clear directions next to the object code saying where to find the - Corresponding Source. Regardless of what server hosts the - Corresponding Source, you remain obligated to ensure that it is - available for as long as needed to satisfy these requirements. - - e) Convey the object code using peer-to-peer transmission, provided - you inform other peers where the object code and Corresponding - Source of the work are being offered to the general public at no - charge under subsection 6d. - - A separable portion of the object code, whose source code is excluded -from the Corresponding Source as a System Library, need not be -included in conveying the object code work. - - A "User Product" is either (1) a "consumer product", which means any -tangible personal property which is normally used for personal, family, -or household purposes, or (2) anything designed or sold for incorporation -into a dwelling. In determining whether a product is a consumer product, -doubtful cases shall be resolved in favor of coverage. For a particular -product received by a particular user, "normally used" refers to a -typical or common use of that class of product, regardless of the status -of the particular user or of the way in which the particular user -actually uses, or expects or is expected to use, the product. A product -is a consumer product regardless of whether the product has substantial -commercial, industrial or non-consumer uses, unless such uses represent -the only significant mode of use of the product. - - "Installation Information" for a User Product means any methods, -procedures, authorization keys, or other information required to install -and execute modified versions of a covered work in that User Product from -a modified version of its Corresponding Source. The information must -suffice to ensure that the continued functioning of the modified object -code is in no case prevented or interfered with solely because -modification has been made. - - If you convey an object code work under this section in, or with, or -specifically for use in, a User Product, and the conveying occurs as -part of a transaction in which the right of possession and use of the -User Product is transferred to the recipient in perpetuity or for a -fixed term (regardless of how the transaction is characterized), the -Corresponding Source conveyed under this section must be accompanied -by the Installation Information. But this requirement does not apply -if neither you nor any third party retains the ability to install -modified object code on the User Product (for example, the work has -been installed in ROM). - - The requirement to provide Installation Information does not include a -requirement to continue to provide support service, warranty, or updates -for a work that has been modified or installed by the recipient, or for -the User Product in which it has been modified or installed. Access to a -network may be denied when the modification itself materially and -adversely affects the operation of the network or violates the rules and -protocols for communication across the network. - - Corresponding Source conveyed, and Installation Information provided, -in accord with this section must be in a format that is publicly -documented (and with an implementation available to the public in -source code form), and must require no special password or key for -unpacking, reading or copying. - - 7. Additional Terms. - - "Additional permissions" are terms that supplement the terms of this -License by making exceptions from one or more of its conditions. -Additional permissions that are applicable to the entire Program shall -be treated as though they were included in this License, to the extent -that they are valid under applicable law. If additional permissions -apply only to part of the Program, that part may be used separately -under those permissions, but the entire Program remains governed by -this License without regard to the additional permissions. - - When you convey a copy of a covered work, you may at your option -remove any additional permissions from that copy, or from any part of -it. (Additional permissions may be written to require their own -removal in certain cases when you modify the work.) You may place -additional permissions on material, added by you to a covered work, -for which you have or can give appropriate copyright permission. - - Notwithstanding any other provision of this License, for material you -add to a covered work, you may (if authorized by the copyright holders of -that material) supplement the terms of this License with terms: - - a) Disclaiming warranty or limiting liability differently from the - terms of sections 15 and 16 of this License; or - - b) Requiring preservation of specified reasonable legal notices or - author attributions in that material or in the Appropriate Legal - Notices displayed by works containing it; or - - c) Prohibiting misrepresentation of the origin of that material, or - requiring that modified versions of such material be marked in - reasonable ways as different from the original version; or - - d) Limiting the use for publicity purposes of names of licensors or - authors of the material; or - - e) Declining to grant rights under trademark law for use of some - trade names, trademarks, or service marks; or - - f) Requiring indemnification of licensors and authors of that - material by anyone who conveys the material (or modified versions of - it) with contractual assumptions of liability to the recipient, for - any liability that these contractual assumptions directly impose on - those licensors and authors. - - All other non-permissive additional terms are considered "further -restrictions" within the meaning of section 10. If the Program as you -received it, or any part of it, contains a notice stating that it is -governed by this License along with a term that is a further -restriction, you may remove that term. If a license document contains -a further restriction but permits relicensing or conveying under this -License, you may add to a covered work material governed by the terms -of that license document, provided that the further restriction does -not survive such relicensing or conveying. - - If you add terms to a covered work in accord with this section, you -must place, in the relevant source files, a statement of the -additional terms that apply to those files, or a notice indicating -where to find the applicable terms. - - Additional terms, permissive or non-permissive, may be stated in the -form of a separately written license, or stated as exceptions; -the above requirements apply either way. - - 8. Termination. - - You may not propagate or modify a covered work except as expressly -provided under this License. Any attempt otherwise to propagate or -modify it is void, and will automatically terminate your rights under -this License (including any patent licenses granted under the third -paragraph of section 11). - - However, if you cease all violation of this License, then your -license from a particular copyright holder is reinstated (a) -provisionally, unless and until the copyright holder explicitly and -finally terminates your license, and (b) permanently, if the copyright -holder fails to notify you of the violation by some reasonable means -prior to 60 days after the cessation. - - Moreover, your license from a particular copyright holder is -reinstated permanently if the copyright holder notifies you of the -violation by some reasonable means, this is the first time you have -received notice of violation of this License (for any work) from that -copyright holder, and you cure the violation prior to 30 days after -your receipt of the notice. - - Termination of your rights under this section does not terminate the -licenses of parties who have received copies or rights from you under -this License. If your rights have been terminated and not permanently -reinstated, you do not qualify to receive new licenses for the same -material under section 10. - - 9. Acceptance Not Required for Having Copies. - - You are not required to accept this License in order to receive or -run a copy of the Program. Ancillary propagation of a covered work -occurring solely as a consequence of using peer-to-peer transmission -to receive a copy likewise does not require acceptance. However, -nothing other than this License grants you permission to propagate or -modify any covered work. These actions infringe copyright if you do -not accept this License. Therefore, by modifying or propagating a -covered work, you indicate your acceptance of this License to do so. - - 10. Automatic Licensing of Downstream Recipients. - - Each time you convey a covered work, the recipient automatically -receives a license from the original licensors, to run, modify and -propagate that work, subject to this License. You are not responsible -for enforcing compliance by third parties with this License. - - An "entity transaction" is a transaction transferring control of an -organization, or substantially all assets of one, or subdividing an -organization, or merging organizations. If propagation of a covered -work results from an entity transaction, each party to that -transaction who receives a copy of the work also receives whatever -licenses to the work the party's predecessor in interest had or could -give under the previous paragraph, plus a right to possession of the -Corresponding Source of the work from the predecessor in interest, if -the predecessor has it or can get it with reasonable efforts. - - You may not impose any further restrictions on the exercise of the -rights granted or affirmed under this License. For example, you may -not impose a license fee, royalty, or other charge for exercise of -rights granted under this License, and you may not initiate litigation -(including a cross-claim or counterclaim in a lawsuit) alleging that -any patent claim is infringed by making, using, selling, offering for -sale, or importing the Program or any portion of it. - - 11. Patents. - - A "contributor" is a copyright holder who authorizes use under this -License of the Program or a work on which the Program is based. The -work thus licensed is called the contributor's "contributor version". - - A contributor's "essential patent claims" are all patent claims -owned or controlled by the contributor, whether already acquired or -hereafter acquired, that would be infringed by some manner, permitted -by this License, of making, using, or selling its contributor version, -but do not include claims that would be infringed only as a -consequence of further modification of the contributor version. For -purposes of this definition, "control" includes the right to grant -patent sublicenses in a manner consistent with the requirements of -this License. - - Each contributor grants you a non-exclusive, worldwide, royalty-free -patent license under the contributor's essential patent claims, to -make, use, sell, offer for sale, import and otherwise run, modify and -propagate the contents of its contributor version. - - In the following three paragraphs, a "patent license" is any express -agreement or commitment, however denominated, not to enforce a patent -(such as an express permission to practice a patent or covenant not to -sue for patent infringement). To "grant" such a patent license to a -party means to make such an agreement or commitment not to enforce a -patent against the party. - - If you convey a covered work, knowingly relying on a patent license, -and the Corresponding Source of the work is not available for anyone -to copy, free of charge and under the terms of this License, through a -publicly available network server or other readily accessible means, -then you must either (1) cause the Corresponding Source to be so -available, or (2) arrange to deprive yourself of the benefit of the -patent license for this particular work, or (3) arrange, in a manner -consistent with the requirements of this License, to extend the patent -license to downstream recipients. "Knowingly relying" means you have -actual knowledge that, but for the patent license, your conveying the -covered work in a country, or your recipient's use of the covered work -in a country, would infringe one or more identifiable patents in that -country that you have reason to believe are valid. - - If, pursuant to or in connection with a single transaction or -arrangement, you convey, or propagate by procuring conveyance of, a -covered work, and grant a patent license to some of the parties -receiving the covered work authorizing them to use, propagate, modify -or convey a specific copy of the covered work, then the patent license -you grant is automatically extended to all recipients of the covered -work and works based on it. - - A patent license is "discriminatory" if it does not include within -the scope of its coverage, prohibits the exercise of, or is -conditioned on the non-exercise of one or more of the rights that are -specifically granted under this License. You may not convey a covered -work if you are a party to an arrangement with a third party that is -in the business of distributing software, under which you make payment -to the third party based on the extent of your activity of conveying -the work, and under which the third party grants, to any of the -parties who would receive the covered work from you, a discriminatory -patent license (a) in connection with copies of the covered work -conveyed by you (or copies made from those copies), or (b) primarily -for and in connection with specific products or compilations that -contain the covered work, unless you entered into that arrangement, -or that patent license was granted, prior to 28 March 2007. - - Nothing in this License shall be construed as excluding or limiting -any implied license or other defenses to infringement that may -otherwise be available to you under applicable patent law. - - 12. No Surrender of Others' Freedom. - - If conditions are imposed on you (whether by court order, agreement or -otherwise) that contradict the conditions of this License, they do not -excuse you from the conditions of this License. If you cannot convey a -covered work so as to satisfy simultaneously your obligations under this -License and any other pertinent obligations, then as a consequence you may -not convey it at all. For example, if you agree to terms that obligate you -to collect a royalty for further conveying from those to whom you convey -the Program, the only way you could satisfy both those terms and this -License would be to refrain entirely from conveying the Program. - - 13. Use with the GNU Affero General Public License. - - Notwithstanding any other provision of this License, you have -permission to link or combine any covered work with a work licensed -under version 3 of the GNU Affero General Public License into a single -combined work, and to convey the resulting work. The terms of this -License will continue to apply to the part which is the covered work, -but the special requirements of the GNU Affero General Public License, -section 13, concerning interaction through a network will apply to the -combination as such. - - 14. Revised Versions of this License. - - The Free Software Foundation may publish revised and/or new versions of -the GNU General Public License from time to time. Such new versions will -be similar in spirit to the present version, but may differ in detail to -address new problems or concerns. - - Each version is given a distinguishing version number. If the -Program specifies that a certain numbered version of the GNU General -Public License "or any later version" applies to it, you have the -option of following the terms and conditions either of that numbered -version or of any later version published by the Free Software -Foundation. If the Program does not specify a version number of the -GNU General Public License, you may choose any version ever published -by the Free Software Foundation. - - If the Program specifies that a proxy can decide which future -versions of the GNU General Public License can be used, that proxy's -public statement of acceptance of a version permanently authorizes you -to choose that version for the Program. - - Later license versions may give you additional or different -permissions. However, no additional obligations are imposed on any -author or copyright holder as a result of your choosing to follow a -later version. - - 15. Disclaimer of Warranty. - - THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY -APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT -HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY -OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, -THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM -IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF -ALL NECESSARY SERVICING, REPAIR OR CORRECTION. - - 16. Limitation of Liability. - - IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING -WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS -THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY -GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE -USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF -DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD -PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), -EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF -SUCH DAMAGES. - - 17. Interpretation of Sections 15 and 16. - - If the disclaimer of warranty and limitation of liability provided -above cannot be given local legal effect according to their terms, -reviewing courts shall apply local law that most closely approximates -an absolute waiver of all civil liability in connection with the -Program, unless a warranty or assumption of liability accompanies a -copy of the Program in return for a fee. - - END OF TERMS AND CONDITIONS - diff --git a/net/gurk-rs/files/vendor/poksho/README.md b/net/gurk-rs/files/vendor/poksho/README.md deleted file mode 100644 index 802ef7c..0000000 --- a/net/gurk-rs/files/vendor/poksho/README.md +++ /dev/null @@ -1,10 +0,0 @@ -# poksho - -This is some incomplete code used for testing. - -Most of the cryptography here is going to change and has not been reviewed, so -this project should not be used. - - - - diff --git a/net/gurk-rs/files/vendor/poksho/src/args.rs b/net/gurk-rs/files/vendor/poksho/src/args.rs deleted file mode 100644 index 0f0bc7b..0000000 --- a/net/gurk-rs/files/vendor/poksho/src/args.rs +++ /dev/null @@ -1,38 +0,0 @@ -// -// Copyright (C) 2020 Signal Messenger, LLC. -// All rights reserved. -// -// SPDX-License-Identifier: GPL-3.0-only -// - -use curve25519_dalek::ristretto::RistrettoPoint; -use curve25519_dalek::scalar::Scalar; -use std::collections::HashMap; - -// Simple 'newtype' wrappers around HashMap to make string literals more convenient - -#[derive(Clone)] -pub struct ScalarArgs(pub HashMap); - -#[derive(Clone)] -pub struct PointArgs(pub HashMap); - -impl ScalarArgs { - pub fn new() -> Self { - Self(HashMap::::new()) - } - - pub fn add(&mut self, s: &str, val: Scalar) { - self.0.insert(s.to_string(), val); - } -} - -impl PointArgs { - pub fn new() -> Self { - Self(HashMap::::new()) - } - - pub fn add(&mut self, s: &str, val: RistrettoPoint) { - self.0.insert(s.to_string(), val); - } -} diff --git a/net/gurk-rs/files/vendor/poksho/src/errors.rs b/net/gurk-rs/files/vendor/poksho/src/errors.rs deleted file mode 100644 index 30169cc..0000000 --- a/net/gurk-rs/files/vendor/poksho/src/errors.rs +++ /dev/null @@ -1,17 +0,0 @@ -// -// Copyright (C) 2020 Signal Messenger, LLC. -// All rights reserved. -// -// SPDX-License-Identifier: GPL-3.0-only -// - -#[derive(Debug)] -pub enum PokshoError { - BadArgs, // Bad arguments were passed to the function - BadArgsWrongNumberOfScalarArgs, // Bad arguments were passed to the function - BadArgsWrongNumberOfPointArgs, // Bad arguments were passed to the function - BadArgsMissingScalarArg, // Bad arguments were passed to the function - BadArgsMissingPointArg, // Bad arguments were passed to the function - VerificationFailure, // Proof verification failed - ProofCreationVerificationFailure, // Proof verification failed during proof creation, indicating bad inputs or faulty computation -} diff --git a/net/gurk-rs/files/vendor/poksho/src/lib.rs b/net/gurk-rs/files/vendor/poksho/src/lib.rs deleted file mode 100644 index 2aa0438..0000000 --- a/net/gurk-rs/files/vendor/poksho/src/lib.rs +++ /dev/null @@ -1,27 +0,0 @@ -// -// Copyright (C) 2020 Signal Messenger, LLC. -// All rights reserved. -// -// SPDX-License-Identifier: GPL-3.0-only -// - -pub mod args; -pub mod errors; -pub mod proof; -pub mod scalar; -pub mod shoapi; -pub mod shohmacsha256; -pub mod shosha256; -pub mod sign; -mod simple_types; -pub mod statement; - -pub use args::{PointArgs, ScalarArgs}; -pub use errors::PokshoError; -pub use proof::Proof; -pub use scalar::{scalar_from_slice_canonical, scalar_from_slice_wide}; -pub use shoapi::ShoApi; -pub use shohmacsha256::ShoHmacSha256; -pub use shosha256::ShoSha256; -pub use sign::{sign, verify_signature}; -pub use statement::Statement; diff --git a/net/gurk-rs/files/vendor/poksho/src/proof.rs b/net/gurk-rs/files/vendor/poksho/src/proof.rs deleted file mode 100644 index 140b30c..0000000 --- a/net/gurk-rs/files/vendor/poksho/src/proof.rs +++ /dev/null @@ -1,43 +0,0 @@ -// -// Copyright (C) 2020 Signal Messenger, LLC. -// All rights reserved. -// -// SPDX-License-Identifier: GPL-3.0-only -// - -use crate::scalar::*; -use crate::simple_types::*; -use curve25519_dalek::scalar::Scalar; - -// We use compact Schnorr signatures, sending the challenge instead of commitments -pub struct Proof { - pub challenge: Scalar, - pub response: G1, -} - -impl Proof { - pub fn from_slice(bytes: &[u8]) -> Option { - let num_scalars = bytes.len() / 32; - if num_scalars < 2 || num_scalars > 257 || num_scalars * 32 != bytes.len() { - return None; - } - let challenge = scalar_from_slice_canonical(&bytes[0..32])?; - let mut response = Vec::::with_capacity(num_scalars - 1); - for i in 1..num_scalars { - response.push(scalar_from_slice_canonical(&bytes[32 * i..(32 * i) + 32])?); - } - Some(Proof { - challenge, - response, - }) - } - - pub fn to_bytes(&self) -> Vec { - let mut bytes = Vec::::with_capacity(self.response.len() * 32); - bytes.extend_from_slice(self.challenge.as_bytes()); - for scalar in &self.response { - bytes.extend_from_slice(scalar.as_bytes()); - } - bytes - } -} diff --git a/net/gurk-rs/files/vendor/poksho/src/scalar.rs b/net/gurk-rs/files/vendor/poksho/src/scalar.rs deleted file mode 100644 index 311b69d..0000000 --- a/net/gurk-rs/files/vendor/poksho/src/scalar.rs +++ /dev/null @@ -1,22 +0,0 @@ -// -// Copyright (C) 2020 Signal Messenger, LLC. -// All rights reserved. -// -// SPDX-License-Identifier: GPL-3.0-only -// - -use curve25519_dalek::scalar::Scalar; - -// Because Rust can't create array references from slices (yet) -pub fn scalar_from_slice_wide(bytes: &[u8]) -> Scalar { - let mut scalar_bytes = [0u8; 64]; - scalar_bytes.copy_from_slice(bytes); - Scalar::from_bytes_mod_order_wide(&scalar_bytes) -} - -// Because Rust can't create array references from slices (yet) -pub fn scalar_from_slice_canonical(bytes: &[u8]) -> Option { - let mut scalar_bytes = [0u8; 32]; - scalar_bytes.copy_from_slice(bytes); - Scalar::from_canonical_bytes(scalar_bytes) -} diff --git a/net/gurk-rs/files/vendor/poksho/src/shoapi.rs b/net/gurk-rs/files/vendor/poksho/src/shoapi.rs deleted file mode 100644 index 450ec81..0000000 --- a/net/gurk-rs/files/vendor/poksho/src/shoapi.rs +++ /dev/null @@ -1,33 +0,0 @@ -// -// Copyright (C) 2020 Signal Messenger, LLC. -// All rights reserved. -// -// SPDX-License-Identifier: GPL-3.0-only -// - -pub trait ShoApi -where - Self: Sized, -{ - fn shohash(label: &[u8], input: &[u8], outlen: usize) -> Vec { - let mut sho = Self::new(label); - sho.absorb_and_ratchet(input); - sho.squeeze_and_ratchet(outlen) - } - - fn absorb_and_ratchet(&mut self, input: &[u8]) { - self.absorb(input); - self.ratchet(); - } - - fn new(label: &[u8]) -> Self; - - fn absorb(&mut self, input: &[u8]); - - fn ratchet(&mut self); - - // unimplemented; make this more generic later - // pub fn squeeze(&mut self, _outlen: usize) -> Vec; - - fn squeeze_and_ratchet(&mut self, outlen: usize) -> Vec; -} diff --git a/net/gurk-rs/files/vendor/poksho/src/shohmacsha256.rs b/net/gurk-rs/files/vendor/poksho/src/shohmacsha256.rs deleted file mode 100644 index 3fe57fe..0000000 --- a/net/gurk-rs/files/vendor/poksho/src/shohmacsha256.rs +++ /dev/null @@ -1,162 +0,0 @@ -// -// Copyright (C) 2020 Signal Messenger, LLC. -// All rights reserved. -// -// SPDX-License-Identifier: GPL-3.0-only -// - -use hmac::{Hmac, Mac}; -use sha2::Sha256; -use std::cmp; - -use crate::shoapi::ShoApi; - -pub const BLOCK_LEN: usize = 64; -pub const HASH_LEN: usize = 32; - -#[derive(Clone)] -enum Mode { - ABSORBING, - RATCHETED, -} - -#[derive(Clone)] -pub struct ShoHmacSha256 { - hasher: Hmac, - cv: [u8; HASH_LEN], - mode: Mode, -} - -impl ShoApi for ShoHmacSha256 { - fn new(label: &[u8]) -> ShoHmacSha256 { - let mut sho = ShoHmacSha256 { - hasher: Hmac::::new_varkey(&[0; HASH_LEN]).unwrap(), - cv: [0; HASH_LEN], - mode: Mode::RATCHETED, - }; - sho.absorb_and_ratchet(label); - sho - } - - fn absorb(&mut self, input: &[u8]) { - if let Mode::RATCHETED = self.mode { - self.hasher = Hmac::::new_varkey(&self.cv).unwrap(); - self.mode = Mode::ABSORBING; - } - self.hasher.input(input); - } - - // called after absorb() only; streaming squeeze not yet supported - fn ratchet(&mut self) { - if let Mode::RATCHETED = self.mode { - panic!(); - } - self.hasher.input(&[0x00]); - self.cv - .copy_from_slice(&self.hasher.clone().result().code()[..]); - self.hasher.reset(); - self.mode = Mode::RATCHETED; - } - - fn squeeze_and_ratchet(&mut self, outlen: usize) -> Vec { - if let Mode::ABSORBING = self.mode { - panic!(); - } - let mut output = Vec::::new(); - let output_hasher_prefix = Hmac::::new_varkey(&self.cv).unwrap(); - let mut i = 0; - while i * HASH_LEN < outlen { - let mut output_hasher = output_hasher_prefix.clone(); - output_hasher.input(&(i as u64).to_be_bytes()); - output_hasher.input(&[0x01]); - let digest = output_hasher.result().code(); - let num_bytes = cmp::min(HASH_LEN, outlen - i * HASH_LEN); - output.extend_from_slice(&digest[0..num_bytes]); - i += 1 - } - - let mut next_hasher = output_hasher_prefix.clone(); - next_hasher.input(&(outlen as u64).to_be_bytes()); - next_hasher.input(&[0x02]); - self.cv.copy_from_slice(&next_hasher.result().code()[..]); - self.mode = Mode::RATCHETED; - output - } -} - -#[cfg(test)] -mod tests { - - use super::*; - - #[test] - fn test_vectors() { - let mut sho = ShoHmacSha256::new(b"asd"); - sho.absorb_and_ratchet(b"asdasd"); - let out = sho.squeeze_and_ratchet(64); - /* - for b in out.iter() { - print!("0x{:02x}, ", b); - } - println!(""); - */ - assert!( - out == vec![ - 0x39, 0x2c, 0xb9, 0x44, 0x93, 0x73, 0x03, 0x7f, 0xa0, 0xc1, 0x1a, 0xeb, 0xed, 0x69, - 0xcc, 0xa3, 0xb7, 0xd3, 0xbc, 0x97, 0x90, 0x87, 0x8f, 0x34, 0x17, 0x29, 0xc6, 0x5d, - 0x55, 0x06, 0x44, 0x2f, 0x04, 0x98, 0x6c, 0xb5, 0xc9, 0x09, 0x8f, 0x27, 0x7c, 0x3e, - 0xa6, 0x40, 0xa4, 0xdc, 0x6e, 0x90, 0x37, 0x2b, 0x43, 0x3a, 0x90, 0xaf, 0x9a, 0xea, - 0x70, 0x72, 0xea, 0xba, 0x33, 0x98, 0xc4, 0xfe, - ] - ); - - let mut sho = ShoHmacSha256::new(b"asd"); - sho.absorb_and_ratchet(b"asdasd"); - let out = sho.squeeze_and_ratchet(65); - /* - for b in out.iter() { - print!("0x{:02x}, ", b); - } - println!(""); - */ - assert!( - out == vec![ - 0x39, 0x2c, 0xb9, 0x44, 0x93, 0x73, 0x03, 0x7f, 0xa0, 0xc1, 0x1a, 0xeb, 0xed, 0x69, - 0xcc, 0xa3, 0xb7, 0xd3, 0xbc, 0x97, 0x90, 0x87, 0x8f, 0x34, 0x17, 0x29, 0xc6, 0x5d, - 0x55, 0x06, 0x44, 0x2f, 0x04, 0x98, 0x6c, 0xb5, 0xc9, 0x09, 0x8f, 0x27, 0x7c, 0x3e, - 0xa6, 0x40, 0xa4, 0xdc, 0x6e, 0x90, 0x37, 0x2b, 0x43, 0x3a, 0x90, 0xaf, 0x9a, 0xea, - 0x70, 0x72, 0xea, 0xba, 0x33, 0x98, 0xc4, 0xfe, 0x7a, - ] - ); - - let mut sho = ShoHmacSha256::new(b""); - sho.absorb_and_ratchet(b"abc"); - sho.absorb_and_ratchet(&[0u8; 63]); - sho.absorb_and_ratchet(&[0u8; 64]); - sho.absorb_and_ratchet(&[0u8; 65]); - sho.absorb_and_ratchet(&[0u8; 127]); - sho.absorb_and_ratchet(&[0u8; 128]); - sho.absorb_and_ratchet(&[0u8; 129]); - sho.squeeze_and_ratchet(63); - sho.squeeze_and_ratchet(64); - sho.squeeze_and_ratchet(65); - sho.squeeze_and_ratchet(127); - sho.squeeze_and_ratchet(128); - sho.squeeze_and_ratchet(129); - sho.absorb_and_ratchet(b"def"); - let out = sho.squeeze_and_ratchet(63); - for b in out.iter() { - print!("0x{:02x}, ", b); - } - println!(""); - assert!( - out == vec![ - 0xc5, 0xc1, 0x3b, 0xcc, 0x65, 0x96, 0xc2, 0x5f, 0xc4, 0x51, 0x4e, 0xac, 0x92, 0x69, - 0xdd, 0x6e, 0x3e, 0x57, 0xef, 0x70, 0xf4, 0xbf, 0xb8, 0xd6, 0x7f, 0xd3, 0x08, 0x2e, - 0xd9, 0x73, 0x2d, 0x77, 0x90, 0xd8, 0xd2, 0x68, 0x6f, 0x19, 0xeb, 0x25, 0x33, 0xa6, - 0x5c, 0x94, 0xbb, 0x8c, 0xed, 0xa0, 0xa0, 0x68, 0xe1, 0xb6, 0x15, 0xc8, 0x1b, 0xb2, - 0x6e, 0x41, 0x18, 0x89, 0xda, 0x9f, 0xb7, - ] - ); - } -} diff --git a/net/gurk-rs/files/vendor/poksho/src/shosha256.rs b/net/gurk-rs/files/vendor/poksho/src/shosha256.rs deleted file mode 100644 index 0a6cf17..0000000 --- a/net/gurk-rs/files/vendor/poksho/src/shosha256.rs +++ /dev/null @@ -1,168 +0,0 @@ -// -// Copyright (C) 2020 Signal Messenger, LLC. -// All rights reserved. -// -// SPDX-License-Identifier: GPL-3.0-only -// - -// implements the "innerpad" SHO/SHA256 proposal - -use sha2::{Digest, Sha256}; -use std::cmp; - -use crate::shoapi::ShoApi; - -pub const BLOCK_LEN: usize = 64; -pub const HASH_LEN: usize = 32; - -#[derive(Clone)] -enum Mode { - ABSORBING, - RATCHETED, -} - -#[derive(Clone)] -pub struct ShoSha256 { - hasher: Sha256, - cv: [u8; HASH_LEN], - mode: Mode, -} - -impl ShoApi for ShoSha256 { - fn new(label: &[u8]) -> ShoSha256 { - let mut sho = ShoSha256 { - hasher: Sha256::new(), - cv: [0; HASH_LEN], - mode: Mode::RATCHETED, - }; - sho.absorb_and_ratchet(label); - sho - } - - fn absorb(&mut self, input: &[u8]) { - if let Mode::RATCHETED = self.mode { - self.hasher.input(&[0u8; BLOCK_LEN][..]); - self.hasher.input(&self.cv); - self.mode = Mode::ABSORBING; - } - self.hasher.input(input); - } - - // called after absorb() only; streaming squeeze not yet supported - fn ratchet(&mut self) { - if let Mode::RATCHETED = self.mode { - panic!(); - } - self.cv - .copy_from_slice(&Sha256::digest(&self.hasher.result_reset()[..])[..]); - self.mode = Mode::RATCHETED; - } - - fn squeeze_and_ratchet(&mut self, outlen: usize) -> Vec { - if let Mode::ABSORBING = self.mode { - panic!(); - } - let mut output = Vec::::new(); - let mut output_hasher_prefix = Sha256::new(); - output_hasher_prefix.input(&[0u8; BLOCK_LEN - 1][..]); - output_hasher_prefix.input(&[1u8]); // domain separator byte - output_hasher_prefix.input(self.cv); - let mut i = 0; - while i * HASH_LEN < outlen { - let mut output_hasher = output_hasher_prefix.clone(); - output_hasher.input((i as u64).to_be_bytes()); - let digest = output_hasher.result(); - let num_bytes = cmp::min(HASH_LEN, outlen - i * HASH_LEN); - output.extend_from_slice(&digest[0..num_bytes]); - i += 1 - } - - let mut next_hasher = Sha256::new(); - next_hasher.input(&[0u8; BLOCK_LEN - 1][..]); - next_hasher.input(&[2u8]); // domain separator byte - next_hasher.input(self.cv); - next_hasher.input((outlen as u64).to_be_bytes()); - self.cv.copy_from_slice(&next_hasher.result()[..]); - self.mode = Mode::RATCHETED; - output - } -} - -#[cfg(test)] -mod tests { - - use super::*; - - #[test] - fn test_vectors() { - let mut sho = ShoSha256::new(b"asd"); - sho.absorb_and_ratchet(b"asdasd"); - let out = sho.squeeze_and_ratchet(64); - /* - for b in out.iter() { - print!("0x{:02x}, ", b); - } - println!(""); - */ - assert!( - out == vec![ - 0xeb, 0xe4, 0xef, 0x29, 0xe1, 0x8a, 0xa5, 0x41, 0x37, 0xed, 0xd8, 0x9c, 0x23, 0xf8, - 0xbf, 0xea, 0xc2, 0x73, 0x1c, 0x9f, 0x67, 0x5d, 0xa2, 0x0e, 0x7c, 0x67, 0xd5, 0xad, - 0x68, 0xd7, 0xee, 0x2d, 0x40, 0xa4, 0x52, 0x32, 0xb5, 0x99, 0x55, 0x2d, 0x46, 0xb5, - 0x20, 0x08, 0x2f, 0xb2, 0x70, 0x59, 0x71, 0xf0, 0x7b, 0x31, 0x58, 0xb0, 0x72, 0xb6, - 0x3a, 0xb0, 0x93, 0x4a, 0x05, 0xe6, 0xaf, 0x64, - ] - ); - - let mut sho = ShoSha256::new(b"asd"); - sho.absorb_and_ratchet(b"asdasd"); - let out = sho.squeeze_and_ratchet(65); - /* - for b in out.iter() { - print!("0x{:02x}, ", b); - } - println!(""); - */ - assert!( - out == vec![ - 0xeb, 0xe4, 0xef, 0x29, 0xe1, 0x8a, 0xa5, 0x41, 0x37, 0xed, 0xd8, 0x9c, 0x23, 0xf8, - 0xbf, 0xea, 0xc2, 0x73, 0x1c, 0x9f, 0x67, 0x5d, 0xa2, 0x0e, 0x7c, 0x67, 0xd5, 0xad, - 0x68, 0xd7, 0xee, 0x2d, 0x40, 0xa4, 0x52, 0x32, 0xb5, 0x99, 0x55, 0x2d, 0x46, 0xb5, - 0x20, 0x08, 0x2f, 0xb2, 0x70, 0x59, 0x71, 0xf0, 0x7b, 0x31, 0x58, 0xb0, 0x72, 0xb6, - 0x3a, 0xb0, 0x93, 0x4a, 0x05, 0xe6, 0xaf, 0x64, 0x48, - ] - ); - - let mut sho = ShoSha256::new(b""); - sho.absorb_and_ratchet(b"abc"); - sho.absorb_and_ratchet(&[0u8; 63]); - sho.absorb_and_ratchet(&[0u8; 64]); - sho.absorb_and_ratchet(&[0u8; 65]); - sho.absorb_and_ratchet(&[0u8; 127]); - sho.absorb_and_ratchet(&[0u8; 128]); - sho.absorb_and_ratchet(&[0u8; 129]); - sho.squeeze_and_ratchet(63); - sho.squeeze_and_ratchet(64); - sho.squeeze_and_ratchet(65); - sho.squeeze_and_ratchet(127); - sho.squeeze_and_ratchet(128); - sho.squeeze_and_ratchet(129); - sho.absorb_and_ratchet(b"def"); - let out = sho.squeeze_and_ratchet(63); - /* - for b in out.iter() { - print!("0x{:02x}, ", b); - } - println!(""); - */ - assert!( - out == vec![ - 0x0d, 0xde, 0xea, 0x97, 0x3f, 0x32, 0x10, 0xf7, 0x72, 0x5a, 0x3c, 0xdb, 0x24, 0x73, - 0xf8, 0x73, 0xae, 0xab, 0x8f, 0xeb, 0x32, 0xb8, 0x0d, 0xee, 0x67, 0xf0, 0xcd, 0xe7, - 0x95, 0x4e, 0x92, 0x9a, 0x4e, 0x78, 0x7a, 0xef, 0xee, 0x6d, 0xbe, 0x91, 0xd3, 0xff, - 0xf1, 0x62, 0x1a, 0xab, 0x8d, 0x0d, 0x29, 0x19, 0x4f, 0x8a, 0xf9, 0x86, 0xd6, 0xf3, - 0x57, 0xad, 0xd0, 0x15, 0x0d, 0xf7, 0xd9, - ] - ); - } -} diff --git a/net/gurk-rs/files/vendor/poksho/src/sign.rs b/net/gurk-rs/files/vendor/poksho/src/sign.rs deleted file mode 100644 index 205f2e1..0000000 --- a/net/gurk-rs/files/vendor/poksho/src/sign.rs +++ /dev/null @@ -1,92 +0,0 @@ -// -// Copyright (C) 2020 Signal Messenger, LLC. -// All rights reserved. -// -// SPDX-License-Identifier: GPL-3.0-only -// - -use crate::args::*; -use crate::errors::*; -use crate::statement::*; -use curve25519_dalek::ristretto::RistrettoPoint; -use curve25519_dalek::scalar::Scalar; - -// Signatures are such a common ZKP that we provide special functions for them: -pub fn sign( - private_key: Scalar, - public_key: RistrettoPoint, - message: &[u8], - randomness: &[u8], -) -> Result, PokshoError> { - let mut st = Statement::new(); - st.add("public_key", &[("private_key", "G")]); - - let mut scalar_args = ScalarArgs::new(); - scalar_args.add("private_key", private_key); - - let mut point_args = PointArgs::new(); - point_args.add("public_key", public_key); - - st.prove(&scalar_args, &point_args, &message, randomness) -} - -pub fn verify_signature( - signature: &[u8], - public_key: RistrettoPoint, - message: &[u8], -) -> Result<(), PokshoError> { - let mut st = Statement::new(); - st.add("public_key", &[("private_key", "G")]); - - let mut point_args = PointArgs::new(); - point_args.add("public_key", public_key); - - st.verify_proof(signature, &point_args, &message) -} - -#[cfg(test)] -mod tests { - #![allow(non_snake_case)] - - use super::*; - use curve25519_dalek::constants::RISTRETTO_BASEPOINT_POINT; - - #[test] - fn test_signature() { - let mut block64 = [0u8; 64]; - let mut block32 = [0u8; 32]; - let mut block100 = [0u8; 100]; - for i in 0..32 { - block32[i] = i as u8; - } - for i in 0..64 { - block64[i] = i as u8; - } - for i in 0..100 { - block100[i] = i as u8; - } - - let a = Scalar::from_bytes_mod_order_wide(&block64); - let A = a * RISTRETTO_BASEPOINT_POINT; - let randomness = block32; - let message = block100; - let signature = sign(a, A, &message, &randomness).unwrap(); - verify_signature(&signature, A, &message).unwrap(); - /* - for b in signature.iter() { - print!("0x{:02x}, ", b); - } - println!(""); - */ - assert!( - signature - == vec![ - 0xa0, 0x8f, 0x6b, 0x34, 0xa2, 0x82, 0xdd, 0x4c, 0x7c, 0xfc, 0x40, 0xb9, 0x18, - 0xf2, 0x24, 0xa6, 0xb6, 0x31, 0xca, 0x5f, 0x64, 0x80, 0xa1, 0x0b, 0x42, 0xbd, - 0x14, 0x08, 0x60, 0x2a, 0x7e, 0x00, 0x8a, 0x23, 0xa1, 0xe3, 0x24, 0x79, 0xbe, - 0xfb, 0x5e, 0x26, 0xb9, 0xf0, 0xf4, 0xfe, 0x0e, 0x9e, 0x9e, 0x9e, 0xc9, 0xaf, - 0xad, 0x26, 0x91, 0x43, 0xac, 0xb0, 0x3a, 0x22, 0xc6, 0x36, 0x4f, 0x03, - ] - ); - } -} diff --git a/net/gurk-rs/files/vendor/poksho/src/simple_types.rs b/net/gurk-rs/files/vendor/poksho/src/simple_types.rs deleted file mode 100644 index b13b4d1..0000000 --- a/net/gurk-rs/files/vendor/poksho/src/simple_types.rs +++ /dev/null @@ -1,12 +0,0 @@ -// -// Copyright (C) 2020 Signal Messenger, LLC. -// All rights reserved. -// -// SPDX-License-Identifier: GPL-3.0-only -// - -use curve25519_dalek::ristretto::RistrettoPoint; -use curve25519_dalek::scalar::Scalar; - -pub type G1 = Vec; // Schnorr proves preimage of homomorphism from G1 -> G2 -pub type G2 = Vec; diff --git a/net/gurk-rs/files/vendor/poksho/src/statement.rs b/net/gurk-rs/files/vendor/poksho/src/statement.rs deleted file mode 100644 index 3b3b323..0000000 --- a/net/gurk-rs/files/vendor/poksho/src/statement.rs +++ /dev/null @@ -1,600 +0,0 @@ -// -// Copyright (C) 2020 Signal Messenger, LLC. -// All rights reserved. -// -// SPDX-License-Identifier: GPL-3.0-only -// - -use crate::args::*; -use crate::errors::*; -use crate::proof::*; -use crate::scalar::*; -use crate::shoapi::ShoApi; -use crate::shohmacsha256::ShoHmacSha256; -use crate::simple_types::*; -use curve25519_dalek::constants::RISTRETTO_BASEPOINT_POINT; -use curve25519_dalek::ristretto::RistrettoPoint; -use curve25519_dalek::scalar::Scalar; -use curve25519_dalek::traits::MultiscalarMul; -use std::collections::HashMap; - -// POKSHO implements the "Sigma protocol for arbitrary linear relations" described in section -// 19.5.3 of https://crypto.stanford.edu/~dabo/cryptobook/BonehShoup_0_4.pdf -// -// We adopt the view that we are proving knowledge of the preimage of a group homomorphism -// from groups G1 -> G2, where elements in G1 are vectors of scalars and elements in G2 are vectors of -// Ristretto "points". The homomomorphism can be viewed as a system of equations of the form: -// -// P = sP + sP + sP + ... -// P = sP + sP + sP + ... -// P = sP + sP + sP + ... -// ... -// -// Where s are any scalars and P are any points. The left-hand side of these equations describes -// the element in G2 which is the image of the homomorphism, and the scalars form an element in G1 -// which we are proving knowledge of (this preimage in G1 can be viewed as a vector if the system -// of equations is rewritten as matrix multiplication). -// -// We use the term "statement" for the above system of equations written with both points and -// scalars as variables. For example, the statement for signatures is the single equation: -// -// A = a*G -// -// where "A" is the public key, "a" is the private key, and "G" is the base point. The -// discrete-log equality statement used in VRFs could be written as: -// -// A = a*G -// B = a*H -// -// We use the term "witness" for a vector of scalars that satisfies a given statement and a given -// set of point assignments (equivalently: a witness is an element in G1 that is a preimage of the -// left-hand-side under the group homomorphism). In the above cases, "a" is the witness. -// -// The zero-knowledge proof is a standard Fiat-Shamir Sigma/Schnorr proof of knowledge. To -// immplement Fiat-Shamir hashing we use the SHO/HMAC-SHA256 construct, which provides a stateful object -// which we can use to Absorb data, and then Squeeze out arbitrary-length ouput. We use a SHO -// object not only to produce the Schnorr challenge, but also to produce the Schnorr nonce by -// hashing some caller-supplied random data, the witness, and the message. This "synthetic nonce" -// strategy is intended to ensure that the nonce appears random to any attacker and that different -// Schnorr challenges will never be used with the same nonce. -// -// Below we describe the hash inputs to SHO/HMAC-SHA256: -// -// L : bytes, label = "POKSHO_Ristretto_SHOHMACSHA256" -// D : bytes, description of statement - see below -// a : G1, witness scalars for statement -// A : G2, point values for statement = homomorphism(a) -// Z : bytes, random = 32 byes of randomness -// M : bytes, message to be signed, if any -// r : G1, Schnorr nonce -// R : G2, Schnorr commitment = homomorphism(r) -// h : integer, Schnorr challenge - -// sho = SHO(L) -// sho.AbsorbAndRatchet(D || A) -// sho2 = sho.Clone() -// sho2.AbsorbAndRatchet(Z || a) -// sho2.AbsorbAndRatchet(M) -// r = sho2.Squeeze(64 * num_scalars) -// sho.AbsorbAndRatchet(R || M) -// h = Squeeze(64) -// -// Description format (D) -// --- -// Ne : number of equations (1-255) -// for i=1..Ne: -// point_index : 0..255 (0 = base point) -// Nt : number of terms (1-255) -// for j=1..Nt: -// scalar_index: 0-255 -// point_index: 0-255 (0 = base point) -// -// Point values for statement (A) and commitment (R) -// --- -// for index=1..total number of points (excluding base point at index 0): -// RistrettoPoint -// -// Witness (a) -// --- -// for index=0..total number of scalars: -// RistrettoScalar - -use PokshoError::*; - -type ScalarIndex = u8; -type PointIndex = u8; - -struct Term { - scalar: ScalarIndex, - point: PointIndex, -} - -struct Equation { - lhs: PointIndex, - rhs: Vec, -} - -pub struct Statement { - // We store the Schnorr ZKP equations using scalar and point indices - // which are numbered from zero, and are assigned sequentially based - // on the order in which the point or scalar appears in the equations - // (except point index 0 is pre-assigned to "G", the Ristretto base point) - // - // We also store maps from string names -> indices, and vectors for - // the reverse map. The former map is used when adding new equations, - // and the latter is used when instantiating these indices with - // concrete values. - equations: Vec, - scalar_map: HashMap, - scalar_vec: Vec, - point_map: HashMap, - point_vec: Vec, -} - -impl Statement { - pub fn new() -> Self { - let mut point_map = HashMap::new(); - point_map.insert("G".to_string(), 0); // G is base point - let point_vec = vec!["G".to_string()]; - Statement { - equations: Vec::new(), - scalar_map: HashMap::new(), - scalar_vec: Vec::new(), - point_map, - point_vec, - } - } - - // panics on invalid input - pub fn add(&mut self, lhs_str: &str, rhs_pairs: &[(&str, &str)]) { - if (lhs_str.len() == 0) - || (rhs_pairs.len() == 0) - || (rhs_pairs.len() > 255) - || (self.equations.len() >= 255) - { - assert!(false); - } - let lhs = self.add_point(lhs_str.to_string()).unwrap(); - let mut rhs = Vec::::with_capacity(rhs_pairs.len()); - for pair in rhs_pairs { - if pair.0.len() == 0 || pair.1.len() == 0 { - assert!(false); - } - let scalar = self.add_scalar(pair.0.to_string()).unwrap(); - let point = self.add_point(pair.1.to_string()).unwrap(); - rhs.push(Term { scalar, point }); - } - self.equations.push(Equation { lhs, rhs }); - } - - pub fn prove( - &self, - scalar_args: &ScalarArgs, - point_args: &PointArgs, - message: &[u8], - randomness: &[u8], // must be 32 bytes - ) -> Result, PokshoError> { - if randomness.len() != 32 { - return Err(PokshoError::BadArgs); - } - let g1 = self.sort_scalars(scalar_args)?; - let all_points = self.sort_points(point_args)?; - - // Absorb the protocol label L, description of statement D, and point values A - let mut sho = ShoHmacSha256::new(b"POKSHO_Ristretto_SHOHMACSHA256"); // L - sho.absorb(&self.to_bytes()); // D - for point in &all_points { - // A - sho.absorb(&point.compress().to_bytes()); - } - - sho.ratchet(); // Ratchet - - // Random nonce - // "Synthetic" nonce based on hashing randomness, witness (private scalars) and message - let mut sho2 = sho.clone(); - sho2.absorb(randomness); // Z - for scalar in &g1 { - sho2.absorb(&scalar.to_bytes()); // a - } - sho2.ratchet(); // Ratchet - sho2.absorb_and_ratchet(message); // M - let blinding_scalar_bytes = sho2.squeeze_and_ratchet(g1.len() * 64); - - let mut nonce = self.g1_new(); - for i in 0..g1.len() { - nonce.push(scalar_from_slice_wide( - &blinding_scalar_bytes[i * 64..(i + 1) * 64], - )) - } - - // Commitment from nonce by applying homomorphism F: commitment = F(nonce) - let commitment = self.homomorphism_with_subtraction(&nonce, &all_points, None); - - // Challenge from commitment and message - for point in &commitment { - sho.absorb(&point.compress().to_bytes()); - } - sho.absorb_and_ratchet(message); - let challenge = scalar_from_slice_wide(&sho.squeeze_and_ratchet(64)); - - // Response - let mut response = self.g1_new(); - for i in 0..g1.len() { - response.push(nonce[i] + (g1[i] * challenge)); - } - - let proof = Proof { - challenge, - response, - }; - - // Verify before returning, since a bad proof could indicate - // a glitched/faulty response that leaks private keys, or incorrect inputs - let proof_bytes = proof.to_bytes(); - match self.verify_proof(&proof_bytes, point_args, message) { - Err(VerificationFailure) => Err(ProofCreationVerificationFailure), - Err(e) => Err(e), - Ok(_) => Ok(proof_bytes), - } - } - - pub fn verify_proof( - &self, - proof_bytes: &[u8], - point_args: &PointArgs, - message: &[u8], - ) -> Result<(), PokshoError> { - let proof = Proof::from_slice(proof_bytes).ok_or(VerificationFailure)?; - if proof.response.len() != self.scalar_vec.len() { - return Err(VerificationFailure); - } - let all_points = self.sort_points(point_args)?; - - // Absorb the protocol label L, statement description D, and point values A - let mut sho = ShoHmacSha256::new(b"POKSHO_Ristretto_SHOHMACSHA256"); // L - sho.absorb(&self.to_bytes()); // D - for point in &all_points { - // A - sho.absorb(&point.compress().to_bytes()); - } - sho.ratchet(); - - // Reconstruct commitment - // - // commitment R = F(s) - h*A - // - // F: homomorphism - // s: response element in G1 - // h: challenge scalar - // A: element in G2 whose preimage we are proving knowledge of (i.e. LHS of Schnorr eqns) - let commitment = - self.homomorphism_with_subtraction(&proof.response, &all_points, Some(proof.challenge)); - - // Reconstruct challenge from commitment and message - for point in &commitment { - // R - sho.absorb(&point.compress().to_bytes()); - } - sho.absorb_and_ratchet(message); // M - let challenge = scalar_from_slice_wide(&sho.squeeze_and_ratchet(64)); - - // Check challenge (const time) - if challenge == proof.challenge { - Ok(()) - } else { - Err(VerificationFailure) - } - } - - fn add_scalar(&mut self, scalar_name: String) -> Result { - match self.scalar_map.get(&scalar_name) { - Some(index) => Ok(*index), - None => { - assert!(self.scalar_map.len() == self.scalar_vec.len()); - let new_index = self.scalar_map.len(); - if new_index > 255 { - return Err(BadArgs); - } - let new_index = new_index as u8; - self.scalar_map.insert(scalar_name.clone(), new_index); - self.scalar_vec.push(scalar_name.clone()); - Ok(new_index) - } - } - } - - fn add_point(&mut self, point_name: String) -> Result { - match self.point_map.get(&point_name) { - Some(index) => Ok(*index), - None => { - assert!(self.point_map.len() == self.point_vec.len()); - let new_index = self.point_map.len(); - if new_index > 255 { - return Err(BadArgs); - } - let new_index = new_index as u8; - self.point_map.insert(point_name.clone(), new_index); - self.point_vec.push(point_name.clone()); - Ok(new_index) - } - } - } - - fn to_bytes(&self) -> Vec { - assert!( - self.equations.len() <= 255 - && self.scalar_map.len() <= 256 - && self.point_map.len() <= 256 - ); - let mut v = Vec::::new(); - v.push(self.equations.len() as u8); - for Equation { lhs, rhs } in &self.equations { - assert!(*lhs as usize <= self.point_map.len()); - assert!(rhs.len() <= 255); - v.push(*lhs); - v.push(rhs.len() as u8); - for Term { scalar, point } in rhs { - assert!((*scalar as usize) < self.scalar_map.len()); - assert!((*point as usize) < self.point_map.len()); - v.push(*scalar); - v.push(*point); - } - } - v - } - - fn g1_new(&self) -> G1 { - G1::with_capacity(self.scalar_vec.len()) - } - - fn g2_new(&self) -> G2 { - G2::with_capacity(self.equations.len()) - } - - // Applies the homomorphism from G1 -> G2 - // If given a challenge h, also subtracts h*A for efficient recovery of - // the Schnorr commitment - fn homomorphism_with_subtraction( - &self, - g1: &G1, - all_points: &Vec, - challenge: Option, - ) -> G2 { - let mut g2 = self.g2_new(); - for e in &self.equations { - let scalar_iter = e - .rhs - .iter() - .map(|Term { scalar, point: _ }| g1[*scalar as usize]); - let point_iter = e - .rhs - .iter() - .map(|Term { scalar: _, point }| all_points[*point as usize]); - - // Can this be done without a vector? - let mut v_scalar = Vec::::with_capacity(1); - let mut v_point = Vec::::with_capacity(1); - if let Some(h) = challenge { - v_scalar.push(-h); - v_point.push(all_points[e.lhs as usize]); - }; - - let scalar_iter = scalar_iter.chain(v_scalar); - let point_iter = point_iter.chain(v_point); - - // Could use vartime_multiscalar_mul in some cases, but in the - // general case points might be secret (not just scalars!) - g2.push(RistrettoPoint::multiscalar_mul(scalar_iter, point_iter)); - } - g2 - } - - fn sort_scalars(&self, scalar_args: &ScalarArgs) -> Result { - if scalar_args.0.len() != self.scalar_vec.len() { - return Err(BadArgsWrongNumberOfScalarArgs); - } - let mut g1 = self.g1_new(); - for scalar_name in &self.scalar_vec { - g1.push( - *scalar_args - .0 - .get(scalar_name) - .ok_or(BadArgsMissingScalarArg)?, - ); - } - Ok(g1) - } - - fn sort_points(&self, point_args: &PointArgs) -> Result, PokshoError> { - if point_args.0.len() != self.point_vec.len() - 1 { - return Err(BadArgsWrongNumberOfPointArgs); - } - let mut all_points = Vec::::new(); - all_points.push(RISTRETTO_BASEPOINT_POINT); - for point_name in &self.point_vec[1..] { - all_points.push(*point_args.0.get(point_name).ok_or(BadArgsMissingPointArg)?); - } - Ok(all_points) - } -} - -#[cfg(test)] -mod tests { - #![allow(non_snake_case)] - - use super::*; - - #[test] - fn test_statement_encoding() { - let mut s = Statement::new(); - s.add("A", &[("a", "G")]); - assert!(s.to_bytes() == vec![1, 1, 1, 0, 0]); - - let mut s = Statement::new(); - s.add("A", &[("a", "G")]); - s.add("B", &[("a", "H")]); - assert!(s.to_bytes() == vec![2, 1, 1, 0, 0, 2, 1, 0, 3]); - - let mut s = Statement::new(); - s.add("A", &[("a", "G"), ("b", "H")]); - assert!(s.to_bytes() == vec![1, 1, 2, 0, 0, 1, 2]); - } - - #[test] - fn test_complex_statement() { - let mut block32 = [0u8; 32]; - let mut block64a = [0u8; 64]; - let mut block64b = [0u8; 64]; - let mut block64c = [0u8; 64]; - let mut block64d = [0u8; 64]; - let mut block64h = [0u8; 64]; - let mut block64i = [0u8; 64]; - let block0 = [0u8; 0]; - for i in 0..32 { - block32[i] = i as u8; - } - for i in 0..64 { - block64a[i] = 10 + i as u8; - } - for i in 0..64 { - block64b[i] = 20 + i as u8; - } - for i in 0..64 { - block64c[i] = 30 + i as u8; - } - for i in 0..64 { - block64d[i] = 40 + i as u8; - } - for i in 0..64 { - block64h[i] = 50 + i as u8; - } - for i in 0..64 { - block64i[i] = 60 + i as u8; - } - - let randomness = block32; - let message = block0; - - let scalar_bytes_a = block64a; - let scalar_bytes_b = block64b; - let scalar_bytes_c = block64c; - let scalar_bytes_d = block64d; - - let scalar_bytes_h_point = block64h; - let scalar_bytes_i_point = block64i; - - let a = Scalar::from_bytes_mod_order_wide(&scalar_bytes_a); - let b = Scalar::from_bytes_mod_order_wide(&scalar_bytes_b); - let c = Scalar::from_bytes_mod_order_wide(&scalar_bytes_c); - let d = Scalar::from_bytes_mod_order_wide(&scalar_bytes_d); - let H = - Scalar::from_bytes_mod_order_wide(&scalar_bytes_h_point) * RISTRETTO_BASEPOINT_POINT; - let I = - Scalar::from_bytes_mod_order_wide(&scalar_bytes_i_point) * RISTRETTO_BASEPOINT_POINT; - - let A = a * RISTRETTO_BASEPOINT_POINT + b * H + c * I; - let B = c * H + d * I; - - let mut st = Statement::new(); - st.add("A", &[("a", "G"), ("b", "H"), ("c", "I")]); - st.add("B", &[("c", "H"), ("d", "I")]); - assert!(st.to_bytes() == vec![2, 1, 3, 0, 0, 1, 2, 2, 3, 4, 2, 2, 2, 3, 3]); - - let mut scalar_args = ScalarArgs::new(); - scalar_args.add("a", a); - scalar_args.add("b", b); - scalar_args.add("c", c); - scalar_args.add("d", d); - let mut point_args = PointArgs::new(); - point_args.add("A", A); - point_args.add("B", B); - point_args.add("H", H); - point_args.add("I", I); - - let mut scalar_args2 = scalar_args.clone(); - scalar_args2.add("abc", a); - - // Test bad args - extra scalar - match st.prove(&scalar_args2, &point_args, &message, &randomness) { - Err(PokshoError::BadArgsWrongNumberOfScalarArgs) => (), - _ => assert!(false), - } - - // Good proof - let mut proof = st - .prove(&scalar_args, &point_args, &message, &randomness) - .unwrap(); - st.verify_proof(&proof, &point_args, &message).unwrap(); - /* - for b in proof.iter() { - print!("0x{:02x}, ", b); - } - println!(""); - */ - assert!( - proof - == vec![ - 0x8e, 0xfc, 0x67, 0x6c, 0x33, 0xe6, 0xb2, 0xd0, 0x67, 0x0e, 0xd5, 0x46, 0x1a, - 0x50, 0x7f, 0x6a, 0x4b, 0xc9, 0x15, 0x3e, 0x26, 0x1d, 0xb8, 0x0f, 0xa4, 0x38, - 0xf3, 0xcd, 0x80, 0xa5, 0xc9, 0x09, 0xb1, 0x13, 0xcc, 0x0d, 0x79, 0x90, 0xad, - 0x61, 0x6d, 0x0a, 0x2f, 0xc4, 0xb8, 0x31, 0xd0, 0x63, 0x57, 0xa5, 0xee, 0x5d, - 0x36, 0xd4, 0x4b, 0x34, 0x27, 0xc7, 0x90, 0x10, 0x61, 0x18, 0x0c, 0x0f, 0xb1, - 0x79, 0x8c, 0x51, 0x68, 0x0f, 0xe2, 0x1b, 0x9f, 0x98, 0xe9, 0x79, 0x55, 0xb1, - 0x59, 0x7c, 0x49, 0x31, 0x47, 0x25, 0xc1, 0x54, 0x6a, 0x36, 0x93, 0x28, 0xcf, - 0x54, 0xda, 0xae, 0x71, 0x0b, 0xfc, 0x4a, 0x99, 0x11, 0x42, 0x2a, 0xa7, 0x7e, - 0xd6, 0xd7, 0x23, 0x1d, 0xe3, 0x00, 0x3b, 0xa5, 0xae, 0x9d, 0x9f, 0xd0, 0xc5, - 0x3c, 0xed, 0x7a, 0xd7, 0x82, 0xe2, 0x9b, 0x04, 0x68, 0x4a, 0x07, 0x22, 0x1a, - 0x6e, 0xf4, 0x7c, 0xe6, 0x1d, 0x81, 0x7f, 0x01, 0x11, 0x7c, 0xf5, 0x9d, 0xf6, - 0x9a, 0xc3, 0x5b, 0x5b, 0xb5, 0x90, 0xf1, 0xf7, 0xb6, 0xd0, 0x29, 0x71, 0x7b, - 0xc1, 0xa6, 0x25, 0x01, - ] - ); - - // Test bad args - extra point - let mut point_args2 = point_args.clone(); - point_args2.add("xyz", A); - match st.verify_proof(&proof, &point_args2, &message) { - Err(PokshoError::BadArgsWrongNumberOfPointArgs) => (), - _ => assert!(false), - } - - // Test bad message - match st.verify_proof(&proof, &point_args, &block32) { - Err(VerificationFailure) => (), - _ => assert!(false), - } - - // Test bad proof #1 - extra byte at end - let mut proof2 = proof.clone(); - proof2.push(0); - match st.verify_proof(&proof2, &point_args, &message) { - Err(VerificationFailure) => (), - _ => assert!(false), - } - - // Test bad proof #2 - last byte changed - let prooflen = proof.len(); - proof[prooflen - 1] += 1; - match st.verify_proof(&proof, &point_args, &message) { - Err(VerificationFailure) => (), - _ => assert!(false), - } - - // Test bad proof #3 - incorrect # of scalars (1 too few) - let mut proof2 = proof.clone(); - proof2.truncate(proof2.len() - 32); - match st.verify_proof(&proof2, &point_args, &message) { - Err(VerificationFailure) => (), - _ => assert!(false), - } - - // Test bad proof #3 - incorrect # of scalars (1 too few) - let mut proof2 = proof.clone(); - proof2.truncate(proof2.len() - 32); - match st.verify_proof(&proof2, &point_args, &message) { - Err(VerificationFailure) => (), - _ => assert!(false), - } - } -} diff --git a/net/gurk-rs/files/vendor/presage/.cargo-checksum.json b/net/gurk-rs/files/vendor/presage/.cargo-checksum.json deleted file mode 100644 index 17ce180..0000000 --- a/net/gurk-rs/files/vendor/presage/.cargo-checksum.json +++ /dev/null @@ -1 +0,0 @@ -{"files":{".github/workflows/ci.yaml":"c9c008a019fa138d791320a9bae47d08ffeb0647db710e86999f871e9bd2a053","Cargo.toml":"062ada4b20149d504ef21dccac55d817e0b9406c5326713d6037db365a6866c0","LICENSE.md":"0d96a4ff68ad6d4b6f1f30f713b18d5184912ba8dd389f86aa7710db079abcb0","README.md":"be9c578a483c733f418c04b061b56aec208a2adfc859f51f5ade752062cd4641","examples/cli.rs":"674e851b0c0ad9096feb88da209b6ea03fbd7db40c5b3faa4e798ab215f280d2","examples/link.rs":"7b56671e805bb1b1692c67c946d9faa6540b29e6f16c738442b8b03f4dbabf14","examples/register.rs":"f5bbba00fafbc8e3937781edd8d958fc0a54c41ffc02d2cfe40cf27409ec225f","rustfmt.toml":"e929ddb6e0351a2402ba754bbb7ef97cfa17a4ecd2d5fc06b5053ac376d44870","src/cache.rs":"e7db7bfab8935ce2bb993e2ef76f3ffbfd928c7956172da9305c4d9db8fb5791","src/config/mod.rs":"7823161971c85c1df783206c6adda7518981785ed20f54628dae61f949ec5b1f","src/config/sled.rs":"344607dc47043c2df85174721049111af3568102a7639adcad5e5b971a49adac","src/errors.rs":"501e810e41eefdf7498cb5a89a8b4822bc1aeb666a3db276e81ff3c38cdae775","src/lib.rs":"b56c700bde13d59dbf545f0083e3fd693aa1b6fd378acecaef011895bf3fd13f","src/manager.rs":"648ba61dd744d1542bc5cc3059b24455472ffd9613af34b15ec70d4969d9c4c5"},"package":null} \ No newline at end of file diff --git a/net/gurk-rs/files/vendor/presage/.github/workflows/ci.yaml b/net/gurk-rs/files/vendor/presage/.github/workflows/ci.yaml deleted file mode 100644 index b95c06a..0000000 --- a/net/gurk-rs/files/vendor/presage/.github/workflows/ci.yaml +++ /dev/null @@ -1,54 +0,0 @@ -on: [push, pull_request] - -name: CI - -env: - CARGO_INCREMENTAL: 0 - -jobs: - build_and_test: - name: build - runs-on: ubuntu-latest - env: - RUSTFLAGS: -D warnings - steps: - - uses: actions/checkout@v2 - - uses: actions-rs/toolchain@v1 - with: - toolchain: stable - - uses: actions-rs/cargo@v1 - with: - command: build - args: --all-targets - - uses: actions-rs/cargo@v1 - with: - command: test - - rustfmt: - name: rustfmt - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v2 - - uses: actions-rs/toolchain@v1 - with: - profile: minimal - toolchain: stable - components: rustfmt - - uses: actions-rs/cargo@v1 - with: - command: fmt - args: -- --check - - clippy: - name: clippy - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v2 - - uses: actions-rs/toolchain@v1 - with: - profile: minimal - toolchain: stable - components: clippy - - uses: actions-rs/cargo@v1 - with: - command: clippy \ No newline at end of file diff --git a/net/gurk-rs/files/vendor/presage/Cargo.toml b/net/gurk-rs/files/vendor/presage/Cargo.toml deleted file mode 100644 index 5274c08..0000000 --- a/net/gurk-rs/files/vendor/presage/Cargo.toml +++ /dev/null @@ -1,49 +0,0 @@ -[package] -# be a sign or warning of (an imminent event, typically an unwelcome one). -name = "presage" -version = "0.2.0" -authors = ["Gabriel Féron "] -edition = "2018" - -[dependencies] -libsignal-service = { git = "https://github.com/boxdot/libsignal-service-rs", rev = "8be91da2" } -libsignal-service-hyper = { git = "https://github.com/boxdot/libsignal-service-rs", rev = "8be91da2" } - -async-trait = "0.1" -base64 = "0.12" -futures = "0.3" -hex = "0.4.2" -log = "0.4.8" -rand = "0.7" -serde = "1.0" -serde_json = "1.0" -thiserror = "1.0" -sled = { version = "0.34", optional = true } -qr2term = "0.2.2" - -[dev-dependencies] -# for tests -quickcheck = "1.0.3" -quickcheck_async = "0.1" - -# for examples -anyhow = "1.0" -directories = "3.0" -env_logger = "0.7" -futures = "0.3" -hex = "0.4" -log = "0.4" -rand = "0.7" -serde_json = "1.0" -structopt = "0.3" -tokio = { version = "1.0", features = ["macros", "rt-multi-thread"] } -url = "2.2.2" - -[features] -default = ["sled-store"] -quirks = [] -sled-store = ["sled"] - -#[patch."https://github.com/whisperfish/libsignal-service-rs.git"] -#libsignal-service = { path = "../libsignal-service-rs/libsignal-service" } -#libsignal-service-hyper = { path = "../libsignal-service-rs/libsignal-service-hyper" } diff --git a/net/gurk-rs/files/vendor/presage/LICENSE.md b/net/gurk-rs/files/vendor/presage/LICENSE.md deleted file mode 100644 index be3f7b2..0000000 --- a/net/gurk-rs/files/vendor/presage/LICENSE.md +++ /dev/null @@ -1,661 +0,0 @@ - GNU AFFERO GENERAL PUBLIC LICENSE - Version 3, 19 November 2007 - - Copyright (C) 2007 Free Software Foundation, Inc. - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - - Preamble - - The GNU Affero General Public License is a free, copyleft license for -software and other kinds of works, specifically designed to ensure -cooperation with the community in the case of network server software. - - The licenses for most software and other practical works are designed -to take away your freedom to share and change the works. By contrast, -our General Public Licenses are intended to guarantee your freedom to -share and change all versions of a program--to make sure it remains free -software for all its users. - - When we speak of free software, we are referring to freedom, not -price. Our General Public Licenses are designed to make sure that you -have the freedom to distribute copies of free software (and charge for -them if you wish), that you receive source code or can get it if you -want it, that you can change the software or use pieces of it in new -free programs, and that you know you can do these things. - - Developers that use our General Public Licenses protect your rights -with two steps: (1) assert copyright on the software, and (2) offer -you this License which gives you legal permission to copy, distribute -and/or modify the software. - - A secondary benefit of defending all users' freedom is that -improvements made in alternate versions of the program, if they -receive widespread use, become available for other developers to -incorporate. Many developers of free software are heartened and -encouraged by the resulting cooperation. However, in the case of -software used on network servers, this result may fail to come about. -The GNU General Public License permits making a modified version and -letting the public access it on a server without ever releasing its -source code to the public. - - The GNU Affero General Public License is designed specifically to -ensure that, in such cases, the modified source code becomes available -to the community. It requires the operator of a network server to -provide the source code of the modified version running there to the -users of that server. Therefore, public use of a modified version, on -a publicly accessible server, gives the public access to the source -code of the modified version. - - An older license, called the Affero General Public License and -published by Affero, was designed to accomplish similar goals. This is -a different license, not a version of the Affero GPL, but Affero has -released a new version of the Affero GPL which permits relicensing under -this license. - - The precise terms and conditions for copying, distribution and -modification follow. - - TERMS AND CONDITIONS - - 0. Definitions. - - "This License" refers to version 3 of the GNU Affero General Public License. - - "Copyright" also means copyright-like laws that apply to other kinds of -works, such as semiconductor masks. - - "The Program" refers to any copyrightable work licensed under this -License. Each licensee is addressed as "you". "Licensees" and -"recipients" may be individuals or organizations. - - To "modify" a work means to copy from or adapt all or part of the work -in a fashion requiring copyright permission, other than the making of an -exact copy. The resulting work is called a "modified version" of the -earlier work or a work "based on" the earlier work. - - A "covered work" means either the unmodified Program or a work based -on the Program. - - To "propagate" a work means to do anything with it that, without -permission, would make you directly or secondarily liable for -infringement under applicable copyright law, except executing it on a -computer or modifying a private copy. Propagation includes copying, -distribution (with or without modification), making available to the -public, and in some countries other activities as well. - - To "convey" a work means any kind of propagation that enables other -parties to make or receive copies. Mere interaction with a user through -a computer network, with no transfer of a copy, is not conveying. - - An interactive user interface displays "Appropriate Legal Notices" -to the extent that it includes a convenient and prominently visible -feature that (1) displays an appropriate copyright notice, and (2) -tells the user that there is no warranty for the work (except to the -extent that warranties are provided), that licensees may convey the -work under this License, and how to view a copy of this License. If -the interface presents a list of user commands or options, such as a -menu, a prominent item in the list meets this criterion. - - 1. Source Code. - - The "source code" for a work means the preferred form of the work -for making modifications to it. "Object code" means any non-source -form of a work. - - A "Standard Interface" means an interface that either is an official -standard defined by a recognized standards body, or, in the case of -interfaces specified for a particular programming language, one that -is widely used among developers working in that language. - - The "System Libraries" of an executable work include anything, other -than the work as a whole, that (a) is included in the normal form of -packaging a Major Component, but which is not part of that Major -Component, and (b) serves only to enable use of the work with that -Major Component, or to implement a Standard Interface for which an -implementation is available to the public in source code form. A -"Major Component", in this context, means a major essential component -(kernel, window system, and so on) of the specific operating system -(if any) on which the executable work runs, or a compiler used to -produce the work, or an object code interpreter used to run it. - - The "Corresponding Source" for a work in object code form means all -the source code needed to generate, install, and (for an executable -work) run the object code and to modify the work, including scripts to -control those activities. However, it does not include the work's -System Libraries, or general-purpose tools or generally available free -programs which are used unmodified in performing those activities but -which are not part of the work. For example, Corresponding Source -includes interface definition files associated with source files for -the work, and the source code for shared libraries and dynamically -linked subprograms that the work is specifically designed to require, -such as by intimate data communication or control flow between those -subprograms and other parts of the work. - - The Corresponding Source need not include anything that users -can regenerate automatically from other parts of the Corresponding -Source. - - The Corresponding Source for a work in source code form is that -same work. - - 2. Basic Permissions. - - All rights granted under this License are granted for the term of -copyright on the Program, and are irrevocable provided the stated -conditions are met. This License explicitly affirms your unlimited -permission to run the unmodified Program. The output from running a -covered work is covered by this License only if the output, given its -content, constitutes a covered work. This License acknowledges your -rights of fair use or other equivalent, as provided by copyright law. - - You may make, run and propagate covered works that you do not -convey, without conditions so long as your license otherwise remains -in force. You may convey covered works to others for the sole purpose -of having them make modifications exclusively for you, or provide you -with facilities for running those works, provided that you comply with -the terms of this License in conveying all material for which you do -not control copyright. Those thus making or running the covered works -for you must do so exclusively on your behalf, under your direction -and control, on terms that prohibit them from making any copies of -your copyrighted material outside their relationship with you. - - Conveying under any other circumstances is permitted solely under -the conditions stated below. Sublicensing is not allowed; section 10 -makes it unnecessary. - - 3. Protecting Users' Legal Rights From Anti-Circumvention Law. - - No covered work shall be deemed part of an effective technological -measure under any applicable law fulfilling obligations under article -11 of the WIPO copyright treaty adopted on 20 December 1996, or -similar laws prohibiting or restricting circumvention of such -measures. - - When you convey a covered work, you waive any legal power to forbid -circumvention of technological measures to the extent such circumvention -is effected by exercising rights under this License with respect to -the covered work, and you disclaim any intention to limit operation or -modification of the work as a means of enforcing, against the work's -users, your or third parties' legal rights to forbid circumvention of -technological measures. - - 4. Conveying Verbatim Copies. - - You may convey verbatim copies of the Program's source code as you -receive it, in any medium, provided that you conspicuously and -appropriately publish on each copy an appropriate copyright notice; -keep intact all notices stating that this License and any -non-permissive terms added in accord with section 7 apply to the code; -keep intact all notices of the absence of any warranty; and give all -recipients a copy of this License along with the Program. - - You may charge any price or no price for each copy that you convey, -and you may offer support or warranty protection for a fee. - - 5. Conveying Modified Source Versions. - - You may convey a work based on the Program, or the modifications to -produce it from the Program, in the form of source code under the -terms of section 4, provided that you also meet all of these conditions: - - a) The work must carry prominent notices stating that you modified - it, and giving a relevant date. - - b) The work must carry prominent notices stating that it is - released under this License and any conditions added under section - 7. This requirement modifies the requirement in section 4 to - "keep intact all notices". - - c) You must license the entire work, as a whole, under this - License to anyone who comes into possession of a copy. This - License will therefore apply, along with any applicable section 7 - additional terms, to the whole of the work, and all its parts, - regardless of how they are packaged. This License gives no - permission to license the work in any other way, but it does not - invalidate such permission if you have separately received it. - - d) If the work has interactive user interfaces, each must display - Appropriate Legal Notices; however, if the Program has interactive - interfaces that do not display Appropriate Legal Notices, your - work need not make them do so. - - A compilation of a covered work with other separate and independent -works, which are not by their nature extensions of the covered work, -and which are not combined with it such as to form a larger program, -in or on a volume of a storage or distribution medium, is called an -"aggregate" if the compilation and its resulting copyright are not -used to limit the access or legal rights of the compilation's users -beyond what the individual works permit. Inclusion of a covered work -in an aggregate does not cause this License to apply to the other -parts of the aggregate. - - 6. Conveying Non-Source Forms. - - You may convey a covered work in object code form under the terms -of sections 4 and 5, provided that you also convey the -machine-readable Corresponding Source under the terms of this License, -in one of these ways: - - a) Convey the object code in, or embodied in, a physical product - (including a physical distribution medium), accompanied by the - Corresponding Source fixed on a durable physical medium - customarily used for software interchange. - - b) Convey the object code in, or embodied in, a physical product - (including a physical distribution medium), accompanied by a - written offer, valid for at least three years and valid for as - long as you offer spare parts or customer support for that product - model, to give anyone who possesses the object code either (1) a - copy of the Corresponding Source for all the software in the - product that is covered by this License, on a durable physical - medium customarily used for software interchange, for a price no - more than your reasonable cost of physically performing this - conveying of source, or (2) access to copy the - Corresponding Source from a network server at no charge. - - c) Convey individual copies of the object code with a copy of the - written offer to provide the Corresponding Source. This - alternative is allowed only occasionally and noncommercially, and - only if you received the object code with such an offer, in accord - with subsection 6b. - - d) Convey the object code by offering access from a designated - place (gratis or for a charge), and offer equivalent access to the - Corresponding Source in the same way through the same place at no - further charge. You need not require recipients to copy the - Corresponding Source along with the object code. If the place to - copy the object code is a network server, the Corresponding Source - may be on a different server (operated by you or a third party) - that supports equivalent copying facilities, provided you maintain - clear directions next to the object code saying where to find the - Corresponding Source. Regardless of what server hosts the - Corresponding Source, you remain obligated to ensure that it is - available for as long as needed to satisfy these requirements. - - e) Convey the object code using peer-to-peer transmission, provided - you inform other peers where the object code and Corresponding - Source of the work are being offered to the general public at no - charge under subsection 6d. - - A separable portion of the object code, whose source code is excluded -from the Corresponding Source as a System Library, need not be -included in conveying the object code work. - - A "User Product" is either (1) a "consumer product", which means any -tangible personal property which is normally used for personal, family, -or household purposes, or (2) anything designed or sold for incorporation -into a dwelling. In determining whether a product is a consumer product, -doubtful cases shall be resolved in favor of coverage. For a particular -product received by a particular user, "normally used" refers to a -typical or common use of that class of product, regardless of the status -of the particular user or of the way in which the particular user -actually uses, or expects or is expected to use, the product. A product -is a consumer product regardless of whether the product has substantial -commercial, industrial or non-consumer uses, unless such uses represent -the only significant mode of use of the product. - - "Installation Information" for a User Product means any methods, -procedures, authorization keys, or other information required to install -and execute modified versions of a covered work in that User Product from -a modified version of its Corresponding Source. The information must -suffice to ensure that the continued functioning of the modified object -code is in no case prevented or interfered with solely because -modification has been made. - - If you convey an object code work under this section in, or with, or -specifically for use in, a User Product, and the conveying occurs as -part of a transaction in which the right of possession and use of the -User Product is transferred to the recipient in perpetuity or for a -fixed term (regardless of how the transaction is characterized), the -Corresponding Source conveyed under this section must be accompanied -by the Installation Information. But this requirement does not apply -if neither you nor any third party retains the ability to install -modified object code on the User Product (for example, the work has -been installed in ROM). - - The requirement to provide Installation Information does not include a -requirement to continue to provide support service, warranty, or updates -for a work that has been modified or installed by the recipient, or for -the User Product in which it has been modified or installed. Access to a -network may be denied when the modification itself materially and -adversely affects the operation of the network or violates the rules and -protocols for communication across the network. - - Corresponding Source conveyed, and Installation Information provided, -in accord with this section must be in a format that is publicly -documented (and with an implementation available to the public in -source code form), and must require no special password or key for -unpacking, reading or copying. - - 7. Additional Terms. - - "Additional permissions" are terms that supplement the terms of this -License by making exceptions from one or more of its conditions. -Additional permissions that are applicable to the entire Program shall -be treated as though they were included in this License, to the extent -that they are valid under applicable law. If additional permissions -apply only to part of the Program, that part may be used separately -under those permissions, but the entire Program remains governed by -this License without regard to the additional permissions. - - When you convey a copy of a covered work, you may at your option -remove any additional permissions from that copy, or from any part of -it. (Additional permissions may be written to require their own -removal in certain cases when you modify the work.) You may place -additional permissions on material, added by you to a covered work, -for which you have or can give appropriate copyright permission. - - Notwithstanding any other provision of this License, for material you -add to a covered work, you may (if authorized by the copyright holders of -that material) supplement the terms of this License with terms: - - a) Disclaiming warranty or limiting liability differently from the - terms of sections 15 and 16 of this License; or - - b) Requiring preservation of specified reasonable legal notices or - author attributions in that material or in the Appropriate Legal - Notices displayed by works containing it; or - - c) Prohibiting misrepresentation of the origin of that material, or - requiring that modified versions of such material be marked in - reasonable ways as different from the original version; or - - d) Limiting the use for publicity purposes of names of licensors or - authors of the material; or - - e) Declining to grant rights under trademark law for use of some - trade names, trademarks, or service marks; or - - f) Requiring indemnification of licensors and authors of that - material by anyone who conveys the material (or modified versions of - it) with contractual assumptions of liability to the recipient, for - any liability that these contractual assumptions directly impose on - those licensors and authors. - - All other non-permissive additional terms are considered "further -restrictions" within the meaning of section 10. If the Program as you -received it, or any part of it, contains a notice stating that it is -governed by this License along with a term that is a further -restriction, you may remove that term. If a license document contains -a further restriction but permits relicensing or conveying under this -License, you may add to a covered work material governed by the terms -of that license document, provided that the further restriction does -not survive such relicensing or conveying. - - If you add terms to a covered work in accord with this section, you -must place, in the relevant source files, a statement of the -additional terms that apply to those files, or a notice indicating -where to find the applicable terms. - - Additional terms, permissive or non-permissive, may be stated in the -form of a separately written license, or stated as exceptions; -the above requirements apply either way. - - 8. Termination. - - You may not propagate or modify a covered work except as expressly -provided under this License. Any attempt otherwise to propagate or -modify it is void, and will automatically terminate your rights under -this License (including any patent licenses granted under the third -paragraph of section 11). - - However, if you cease all violation of this License, then your -license from a particular copyright holder is reinstated (a) -provisionally, unless and until the copyright holder explicitly and -finally terminates your license, and (b) permanently, if the copyright -holder fails to notify you of the violation by some reasonable means -prior to 60 days after the cessation. - - Moreover, your license from a particular copyright holder is -reinstated permanently if the copyright holder notifies you of the -violation by some reasonable means, this is the first time you have -received notice of violation of this License (for any work) from that -copyright holder, and you cure the violation prior to 30 days after -your receipt of the notice. - - Termination of your rights under this section does not terminate the -licenses of parties who have received copies or rights from you under -this License. If your rights have been terminated and not permanently -reinstated, you do not qualify to receive new licenses for the same -material under section 10. - - 9. Acceptance Not Required for Having Copies. - - You are not required to accept this License in order to receive or -run a copy of the Program. Ancillary propagation of a covered work -occurring solely as a consequence of using peer-to-peer transmission -to receive a copy likewise does not require acceptance. However, -nothing other than this License grants you permission to propagate or -modify any covered work. These actions infringe copyright if you do -not accept this License. Therefore, by modifying or propagating a -covered work, you indicate your acceptance of this License to do so. - - 10. Automatic Licensing of Downstream Recipients. - - Each time you convey a covered work, the recipient automatically -receives a license from the original licensors, to run, modify and -propagate that work, subject to this License. You are not responsible -for enforcing compliance by third parties with this License. - - An "entity transaction" is a transaction transferring control of an -organization, or substantially all assets of one, or subdividing an -organization, or merging organizations. If propagation of a covered -work results from an entity transaction, each party to that -transaction who receives a copy of the work also receives whatever -licenses to the work the party's predecessor in interest had or could -give under the previous paragraph, plus a right to possession of the -Corresponding Source of the work from the predecessor in interest, if -the predecessor has it or can get it with reasonable efforts. - - You may not impose any further restrictions on the exercise of the -rights granted or affirmed under this License. For example, you may -not impose a license fee, royalty, or other charge for exercise of -rights granted under this License, and you may not initiate litigation -(including a cross-claim or counterclaim in a lawsuit) alleging that -any patent claim is infringed by making, using, selling, offering for -sale, or importing the Program or any portion of it. - - 11. Patents. - - A "contributor" is a copyright holder who authorizes use under this -License of the Program or a work on which the Program is based. The -work thus licensed is called the contributor's "contributor version". - - A contributor's "essential patent claims" are all patent claims -owned or controlled by the contributor, whether already acquired or -hereafter acquired, that would be infringed by some manner, permitted -by this License, of making, using, or selling its contributor version, -but do not include claims that would be infringed only as a -consequence of further modification of the contributor version. For -purposes of this definition, "control" includes the right to grant -patent sublicenses in a manner consistent with the requirements of -this License. - - Each contributor grants you a non-exclusive, worldwide, royalty-free -patent license under the contributor's essential patent claims, to -make, use, sell, offer for sale, import and otherwise run, modify and -propagate the contents of its contributor version. - - In the following three paragraphs, a "patent license" is any express -agreement or commitment, however denominated, not to enforce a patent -(such as an express permission to practice a patent or covenant not to -sue for patent infringement). To "grant" such a patent license to a -party means to make such an agreement or commitment not to enforce a -patent against the party. - - If you convey a covered work, knowingly relying on a patent license, -and the Corresponding Source of the work is not available for anyone -to copy, free of charge and under the terms of this License, through a -publicly available network server or other readily accessible means, -then you must either (1) cause the Corresponding Source to be so -available, or (2) arrange to deprive yourself of the benefit of the -patent license for this particular work, or (3) arrange, in a manner -consistent with the requirements of this License, to extend the patent -license to downstream recipients. "Knowingly relying" means you have -actual knowledge that, but for the patent license, your conveying the -covered work in a country, or your recipient's use of the covered work -in a country, would infringe one or more identifiable patents in that -country that you have reason to believe are valid. - - If, pursuant to or in connection with a single transaction or -arrangement, you convey, or propagate by procuring conveyance of, a -covered work, and grant a patent license to some of the parties -receiving the covered work authorizing them to use, propagate, modify -or convey a specific copy of the covered work, then the patent license -you grant is automatically extended to all recipients of the covered -work and works based on it. - - A patent license is "discriminatory" if it does not include within -the scope of its coverage, prohibits the exercise of, or is -conditioned on the non-exercise of one or more of the rights that are -specifically granted under this License. You may not convey a covered -work if you are a party to an arrangement with a third party that is -in the business of distributing software, under which you make payment -to the third party based on the extent of your activity of conveying -the work, and under which the third party grants, to any of the -parties who would receive the covered work from you, a discriminatory -patent license (a) in connection with copies of the covered work -conveyed by you (or copies made from those copies), or (b) primarily -for and in connection with specific products or compilations that -contain the covered work, unless you entered into that arrangement, -or that patent license was granted, prior to 28 March 2007. - - Nothing in this License shall be construed as excluding or limiting -any implied license or other defenses to infringement that may -otherwise be available to you under applicable patent law. - - 12. No Surrender of Others' Freedom. - - If conditions are imposed on you (whether by court order, agreement or -otherwise) that contradict the conditions of this License, they do not -excuse you from the conditions of this License. If you cannot convey a -covered work so as to satisfy simultaneously your obligations under this -License and any other pertinent obligations, then as a consequence you may -not convey it at all. For example, if you agree to terms that obligate you -to collect a royalty for further conveying from those to whom you convey -the Program, the only way you could satisfy both those terms and this -License would be to refrain entirely from conveying the Program. - - 13. Remote Network Interaction; Use with the GNU General Public License. - - Notwithstanding any other provision of this License, if you modify the -Program, your modified version must prominently offer all users -interacting with it remotely through a computer network (if your version -supports such interaction) an opportunity to receive the Corresponding -Source of your version by providing access to the Corresponding Source -from a network server at no charge, through some standard or customary -means of facilitating copying of software. This Corresponding Source -shall include the Corresponding Source for any work covered by version 3 -of the GNU General Public License that is incorporated pursuant to the -following paragraph. - - Notwithstanding any other provision of this License, you have -permission to link or combine any covered work with a work licensed -under version 3 of the GNU General Public License into a single -combined work, and to convey the resulting work. The terms of this -License will continue to apply to the part which is the covered work, -but the work with which it is combined will remain governed by version -3 of the GNU General Public License. - - 14. Revised Versions of this License. - - The Free Software Foundation may publish revised and/or new versions of -the GNU Affero General Public License from time to time. Such new versions -will be similar in spirit to the present version, but may differ in detail to -address new problems or concerns. - - Each version is given a distinguishing version number. If the -Program specifies that a certain numbered version of the GNU Affero General -Public License "or any later version" applies to it, you have the -option of following the terms and conditions either of that numbered -version or of any later version published by the Free Software -Foundation. If the Program does not specify a version number of the -GNU Affero General Public License, you may choose any version ever published -by the Free Software Foundation. - - If the Program specifies that a proxy can decide which future -versions of the GNU Affero General Public License can be used, that proxy's -public statement of acceptance of a version permanently authorizes you -to choose that version for the Program. - - Later license versions may give you additional or different -permissions. However, no additional obligations are imposed on any -author or copyright holder as a result of your choosing to follow a -later version. - - 15. Disclaimer of Warranty. - - THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY -APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT -HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY -OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, -THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM -IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF -ALL NECESSARY SERVICING, REPAIR OR CORRECTION. - - 16. Limitation of Liability. - - IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING -WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS -THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY -GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE -USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF -DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD -PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), -EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF -SUCH DAMAGES. - - 17. Interpretation of Sections 15 and 16. - - If the disclaimer of warranty and limitation of liability provided -above cannot be given local legal effect according to their terms, -reviewing courts shall apply local law that most closely approximates -an absolute waiver of all civil liability in connection with the -Program, unless a warranty or assumption of liability accompanies a -copy of the Program in return for a fee. - - END OF TERMS AND CONDITIONS - - How to Apply These Terms to Your New Programs - - If you develop a new program, and you want it to be of the greatest -possible use to the public, the best way to achieve this is to make it -free software which everyone can redistribute and change under these terms. - - To do so, attach the following notices to the program. It is safest -to attach them to the start of each source file to most effectively -state the exclusion of warranty; and each file should have at least -the "copyright" line and a pointer to where the full notice is found. - - - Copyright (C) - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Affero General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Affero General Public License for more details. - - You should have received a copy of the GNU Affero General Public License - along with this program. If not, see . - -Also add information on how to contact you by electronic and paper mail. - - If your software can interact with users remotely through a computer -network, you should also make sure that it provides a way for users to -get its source. For example, if your program is a web application, its -interface could display a "Source" link that leads users to an archive -of the code. There are many ways you could offer source, and different -solutions will be better for different programs; see section 13 for the -specific requirements. - - You should also get your employer (if you work as a programmer) or school, -if any, to sign a "copyright disclaimer" for the program, if necessary. -For more information on this, and how to apply and follow the GNU AGPL, see -. diff --git a/net/gurk-rs/files/vendor/presage/README.md b/net/gurk-rs/files/vendor/presage/README.md deleted file mode 100644 index e91648b..0000000 --- a/net/gurk-rs/files/vendor/presage/README.md +++ /dev/null @@ -1,40 +0,0 @@ -# Presage - -![CI](https://github.com/whisperfish/presage/workflows/CI/badge.svg) -![License](https://shields.io/github/license/whisperfish/presage.svg) - -A Rust library that helps building clients for the [Signal Messenger](https://signal.org/en/), using [libsignal-service-rs](https://github.com/whisperfish/libsignal-service-rs). It is designed to provide everything you need to get started. - -> :warning: **The API is considered unstable** - I am still experimenting here. - -Features: - -- [x] Configuration and secrets storage (using [sled](https://github.com/spacejam/sled)) - - [ ] Local encryption -- [x] Registration - - [x] SMS - - [x] Voice call -- [x] Link as secondary device from Android / iOS app (like Signal Desktop) -- [x] Synchronize contacts from primary device -- [x] Receive messages -- [x] Download + decrypt attachments -- [x] Send messages -- [x] Groups support - -## Instructions - -Included in this repository is a CLI very similar (on purpose) to the great [signal-cli](https://github.com/AsamK/signal-cli): - -``` -# print help section -cargo run --example=cli -- --help - -# link as secondary device, a PNG with a QR code to scan should open -cargo run --example=cli -- link-device --device-name presage - -# start receiving messages -cargo run --example=cli -- receive -``` - -For usage of the library, a few examples are included under the `examples/` directory, and most features are demonstrated -in [examples/cli.rs](./examples/cli.rs). diff --git a/net/gurk-rs/files/vendor/presage/examples/cli.rs b/net/gurk-rs/files/vendor/presage/examples/cli.rs deleted file mode 100644 index d5ae9d1..0000000 --- a/net/gurk-rs/files/vendor/presage/examples/cli.rs +++ /dev/null @@ -1,349 +0,0 @@ -use std::{convert::TryInto, path::PathBuf, time::UNIX_EPOCH}; - -use anyhow::{bail, Context as _}; -use directories::ProjectDirs; -use env_logger::Env; -use futures::{pin_mut, StreamExt}; -use libsignal_service::ServiceAddress; -use log::debug; -use presage::{ - prelude::{ - content::{ - Content, ContentBody, DataMessage, GroupContext, GroupContextV2, GroupType, SyncMessage, - }, - proto::sync_message::Sent, - Contact, GroupMasterKey, SignalServers, - }, - prelude::{phonenumber::PhoneNumber, Uuid}, - Manager, SledConfigStore, -}; -use structopt::StructOpt; -use url::Url; - -#[derive(StructOpt)] -#[structopt(about = "a basic signal CLI to try things out")] -struct Args { - #[structopt(long = "db-path", short = "d")] - db_path: Option, - - #[structopt(flatten)] - subcommand: Subcommand, -} - -#[derive(StructOpt)] -enum Subcommand { - #[structopt(about = "register a primary device using a phone number")] - Register { - #[structopt(long = "servers", short = "s", default_value = "staging")] - servers: SignalServers, - #[structopt(long, help = "Phone Number to register with in E.164 format")] - phone_number: PhoneNumber, - #[structopt(long)] - use_voice_call: bool, - #[structopt( - long = "captcha", - help = "Captcha obtained from https://signalcaptchas.org/registration/generate.html" - )] - captcha: Option, - #[structopt(long, help = "Force to register again if already registered")] - force: bool, - }, - #[structopt(about = "Unregister from Signal")] - Unregister, - #[structopt( - about = "generate a QR code to scan with Signal for iOS or Android to provision a secondary device on the same phone number" - )] - LinkDevice { - /// Possible values: staging, production - #[structopt(long, short = "s", default_value = "production")] - servers: SignalServers, - #[structopt( - long, - short = "n", - help = "Name of the device to register in the primary client" - )] - device_name: String, - }, - #[structopt(about = "verify the code you got from the SMS or voice-call when you registered")] - Verify { - #[structopt(long, short = "c", help = "SMS / Voice-call confirmation code")] - confirmation_code: u32, - }, - #[structopt(about = "Get information on the registered user")] - Whoami, - #[structopt(about = "Retrieve the user profile")] - RetrieveProfile, - #[structopt(about = "Sets a name, status and avatar")] - UpdateProfile, - #[structopt(about = "Check if a user is registered on Signal")] - GetUserStatus, - #[structopt(about = "Update the account attributes")] - UpdateAccount, - #[structopt(about = "Block the provided contacts or groups")] - Block, - #[structopt(about = "Unblock the provided contacts or groups")] - Unblock, - #[structopt(about = "Update the details of a contact")] - UpdateContact, - #[structopt(about = "Receives all pending messages and saves them to disk")] - Receive, - #[structopt(about = "List group memberships")] - ListGroups, - #[structopt(about = "list contacts")] - ListContacts, - #[structopt(about = "find a contact in the embedded DB")] - FindContact { - #[structopt(long, short = "u", help = "contact UUID")] - uuid: Option, - #[structopt(long, short = "name", help = "contact name")] - name: Option, - }, - #[structopt(about = "sends a message")] - Send { - #[structopt(long, short = "u", help = "uuid of the recipient")] - uuid: Uuid, - #[structopt(long, short = "m", help = "Contents of the message to send")] - message: String, - }, - #[structopt(about = "sends a message to group")] - SendToGroup { - #[structopt( - long = "phone-number", - short = "n", - min_values = 1, - required = true, - help = "Phone number of the recipient" - )] - recipients: Vec, - #[structopt(long, short = "m", help = "Contents of the message to send")] - message: String, - #[structopt(long, short = "g", help = "ID of the legacy group (hex string)")] - group_id: Option, - #[structopt(long, short = "k", help = "Master Key of the V2 group (hex string)")] - master_key: Option, - }, - #[cfg(feature = "quirks")] - RequestSyncContacts, - #[cfg(feature = "quirks")] - DumpConfig, -} - -#[tokio::main(flavor = "current_thread")] -async fn main() -> anyhow::Result<()> { - env_logger::from_env( - Env::default().default_filter_or(format!("{}=info", env!("CARGO_PKG_NAME"))), - ) - .init(); - - let args = Args::from_args(); - - let db_path = args.db_path.unwrap_or_else(|| { - ProjectDirs::from("org", "whisperfish", "presage") - .unwrap() - .config_dir() - .into() - }); - debug!("opening config database from {}", db_path.display()); - let config_store = SledConfigStore::new(db_path)?; - - let csprng = rand::thread_rng(); - let mut manager = Manager::new(config_store, csprng)?; - - match args.subcommand { - Subcommand::Register { - servers, - phone_number, - use_voice_call, - captcha, - force, - } => { - manager - .register( - servers, - phone_number, - use_voice_call, - captcha.as_ref().map(|u| u.host_str().unwrap()), - force, - ) - .await?; - } - Subcommand::LinkDevice { - servers, - device_name, - } => { - manager - .link_secondary_device(servers, device_name.clone()) - .await?; - } - Subcommand::Verify { confirmation_code } => { - manager.confirm_verification_code(confirmation_code).await?; - } - Subcommand::Receive => { - let messages = manager - .clone() - .receive_messages() - .await - .context("failed to initialize messages stream")?; - pin_mut!(messages); - while let Some(Content { metadata, body }) = messages.next().await { - match body { - ContentBody::DataMessage(message) - | ContentBody::SynchronizeMessage(SyncMessage { - sent: - Some(Sent { - message: Some(message), - .. - }), - .. - }) => { - if let Some(quote) = &message.quote { - println!( - "Quote from {:?}: > {:?} / {}", - metadata.sender, - quote, - message.body(), - ); - } else if let Some(reaction) = message.reaction { - println!( - "Reaction to message sent at {:?}: {:?}", - reaction.target_sent_timestamp, reaction.emoji, - ) - } else { - println!("Message from {:?}: {:?}", metadata, message); - // fetch the groups v2 info here, just for testing purposes - if let Some(group_v2) = message.group_v2 { - let _master_key = GroupMasterKey::new( - group_v2.master_key.unwrap().try_into().unwrap(), - ); - // let group = manager.get_group_v2(master_key).await; - // println!("Group v2: {:?}", group); - } - } - } - ContentBody::SynchronizeMessage(m) => { - eprintln!("Unhandled sync message: {:?}", m); - } - ContentBody::TypingMessage(_) => { - println!("{:?} is typing", metadata.sender); - } - ContentBody::CallMessage(_) => { - println!("{:?} is calling!", metadata.sender); - } - ContentBody::ReceiptMessage(_) => { - println!("Got read receipt from: {:?}", metadata.sender); - } - } - } - } - Subcommand::Send { uuid, message } => { - let timestamp = std::time::SystemTime::now() - .duration_since(UNIX_EPOCH) - .expect("Time went backwards") - .as_millis() as u64; - - let message = ContentBody::DataMessage(DataMessage { - body: Some(message), - timestamp: Some(timestamp), - ..Default::default() - }); - - manager.send_message(uuid, message, timestamp).await?; - } - Subcommand::SendToGroup { - recipients, - message, - group_id, - master_key, - } => { - match (group_id.as_ref(), master_key.as_ref()) { - (Some(_), Some(_)) => bail!("Options --group-id and --master-key are exclusive"), - (None, None) => bail!("Either --group-id or --master-key is required"), - _ => (), - } - - let group_id = group_id.map(hex::decode).transpose()?; - let master_key = master_key.map(hex::decode).transpose()?; - - let timestamp = std::time::SystemTime::now() - .duration_since(UNIX_EPOCH) - .expect("Time went backwards") - .as_millis() as u64; - - let data_message = DataMessage { - body: Some(message), - timestamp: Some(timestamp), - group: group_id.map(|id| GroupContext { - id: Some(id), - r#type: Some(GroupType::Deliver.into()), - ..Default::default() - }), - group_v2: master_key.map(|key| GroupContextV2 { - master_key: Some(key), - revision: Some(0), - ..Default::default() - }), - ..Default::default() - }; - - manager - .send_message_to_group( - recipients.into_iter().map(Into::into), - data_message, - timestamp, - ) - .await?; - } - Subcommand::Unregister => unimplemented!(), - Subcommand::RetrieveProfile => { - let profile = manager.retrieve_profile().await?; - println!("{:#?}", profile); - } - Subcommand::UpdateProfile => unimplemented!(), - Subcommand::GetUserStatus => unimplemented!(), - Subcommand::UpdateAccount => { - manager.set_account_attributes().await?; - } - Subcommand::Block => unimplemented!(), - Subcommand::Unblock => unimplemented!(), - Subcommand::UpdateContact => unimplemented!(), - Subcommand::ListGroups => unimplemented!(), - Subcommand::ListContacts => { - for contact in manager.get_contacts()? { - if let Contact { - name, - address: - ServiceAddress { - uuid: Some(uuid), - phonenumber: Some(phonenumber), - .. - }, - .. - } = contact - { - println!("{} / {} / {}", uuid, name, phonenumber); - } - } - } - Subcommand::Whoami => { - println!("{:?}", &manager.whoami().await?) - } - Subcommand::FindContact { uuid, ref name } => { - for contact in manager - .get_contacts()? - .filter(|c| c.address.uuid == uuid) - .filter(|c| name.as_ref().map_or(true, |n| c.name.contains(n))) - { - println!("{}: {}", contact.name, contact.address); - } - } - #[cfg(feature = "quirks")] - Subcommand::RequestSyncContacts => { - manager.request_contacts_sync().await?; - } - #[cfg(feature = "quirks")] - Subcommand::DumpConfig => { - manager.dump_config()?; - } - }; - Ok(()) -} diff --git a/net/gurk-rs/files/vendor/presage/examples/link.rs b/net/gurk-rs/files/vendor/presage/examples/link.rs deleted file mode 100644 index 9ddd804..0000000 --- a/net/gurk-rs/files/vendor/presage/examples/link.rs +++ /dev/null @@ -1,18 +0,0 @@ -use presage::{prelude::SignalServers, Manager, SledConfigStore}; - -#[tokio::main] -async fn main() -> anyhow::Result<()> { - let config_store = SledConfigStore::new("/tmp/presage-example")?; - - let csprng = rand::thread_rng(); - let mut manager = Manager::new(config_store, csprng)?; - - manager - .link_secondary_device(SignalServers::Production, "my-linked-client".into()) - .await?; - - // scan the QR code that's being opened with your main device - // the store is now initialized, and you're ready to send/receive messages! - - Ok(()) -} diff --git a/net/gurk-rs/files/vendor/presage/examples/register.rs b/net/gurk-rs/files/vendor/presage/examples/register.rs deleted file mode 100644 index 9793b5b..0000000 --- a/net/gurk-rs/files/vendor/presage/examples/register.rs +++ /dev/null @@ -1,53 +0,0 @@ -use std::io::{self, BufRead}; - -use presage::{ - prelude::{phonenumber::PhoneNumber, SignalServers}, - Manager, SledConfigStore, -}; - -fn read_line() -> String { - io::stdin() - .lock() - .lines() - .next() - .expect("stdin should be available") - .expect("couldn't read from stdin") - .trim() - .to_string() -} - -#[tokio::main] -async fn main() -> anyhow::Result<()> { - let config_store = SledConfigStore::new("/tmp/presage-example")?; - - let csprng = rand::thread_rng(); - let mut manager = Manager::new(config_store, csprng)?; - - println!("phone number: "); - let phone_number: PhoneNumber = io::stdin() - .lock() - .lines() - .next() - .expect("stdin should be available") - .expect("couldn't read from stdin") - .trim() - .parse()?; - - manager - .register( - SignalServers::Production, - phone_number, - false, - None, // use a token obtained from https://signalcaptchas.org/registration/generate.html if registration fails - false, - ) - .await?; - - print!("confirmation code: "); - let confirmation_code: u32 = read_line().parse()?; - manager.confirm_verification_code(confirmation_code).await?; - - // the store is now initialized, and you're ready to send/receive messages! - - Ok(()) -} diff --git a/net/gurk-rs/files/vendor/presage/rustfmt.toml b/net/gurk-rs/files/vendor/presage/rustfmt.toml deleted file mode 100644 index 4e727a0..0000000 --- a/net/gurk-rs/files/vendor/presage/rustfmt.toml +++ /dev/null @@ -1 +0,0 @@ -reorder_imports = true \ No newline at end of file diff --git a/net/gurk-rs/files/vendor/presage/src/cache.rs b/net/gurk-rs/files/vendor/presage/src/cache.rs deleted file mode 100644 index ed39baf..0000000 --- a/net/gurk-rs/files/vendor/presage/src/cache.rs +++ /dev/null @@ -1,75 +0,0 @@ -use std::cell::Cell; - -pub(crate) struct CacheCell { - cell: Cell>, -} - -impl Clone for CacheCell { - fn clone(&self) -> Self { - let value = self.cell.replace(None); - self.cell.set(value.clone()); - Self { - cell: Cell::new(value), - } - } -} - -impl Default for CacheCell { - fn default() -> Self { - Self { - cell: Cell::new(None), - } - } -} - -impl CacheCell { - pub fn get(&self, factory: impl FnOnce() -> Result) -> Result { - let value = match self.cell.replace(None) { - Some(value) => value, - None => factory()?, - }; - self.cell.set(Some(value.clone())); - Ok(value) - } - - pub fn clear(&self) { - self.cell.set(None) - } -} - -#[cfg(test)] -mod tests { - use super::*; - - use std::convert::Infallible; - - #[test] - fn test_cache_cell() { - let cache: CacheCell = Default::default(); - - let value = cache - .get(|| Ok::<_, Infallible>("Hello, World!".to_string())) - .unwrap(); - assert_eq!(value, "Hello, World!"); - let value = cache - .get(|| -> Result { panic!("I should not run") }) - .unwrap(); - assert_eq!(value, "Hello, World!"); - - let new_cache = cache.clone(); // clone should not touch the cache - let value = cache - .get(|| -> Result { panic!("I should not run") }) - .unwrap(); - assert_eq!(value, "Hello, World!"); - - cache.clear(); - let value = cache - .get(|| Ok::<_, Infallible>("Hi, Amigo!".to_string())) - .unwrap(); - assert_eq!(value, "Hi, Amigo!"); - let value = new_cache - .get(|| -> Result { panic!("I should not run") }) - .unwrap(); - assert_eq!(value, "Hello, World!"); - } -} diff --git a/net/gurk-rs/files/vendor/presage/src/config/mod.rs b/net/gurk-rs/files/vendor/presage/src/config/mod.rs deleted file mode 100644 index 231cb63..0000000 --- a/net/gurk-rs/files/vendor/presage/src/config/mod.rs +++ /dev/null @@ -1,32 +0,0 @@ -use libsignal_service::{ - models::Contact, - prelude::{ - protocol::{IdentityKeyStore, PreKeyStore, SessionStoreExt, SignedPreKeyStore}, - Uuid, - }, -}; - -use crate::{manager::State, Error}; - -#[cfg(feature = "sled-store")] -pub mod sled; - -pub trait ConfigStore: - PreKeyStore + SignedPreKeyStore + SessionStoreExt + IdentityKeyStore + ContactsStore + Clone -{ - fn state(&self) -> Result; - - fn save(&self, state: &State) -> Result<(), Error>; - - fn pre_keys_offset_id(&self) -> Result; - fn set_pre_keys_offset_id(&self, id: u32) -> Result<(), Error>; - - fn next_signed_pre_key_id(&self) -> Result; - fn set_next_signed_pre_key_id(&self, id: u32) -> Result<(), Error>; -} - -pub trait ContactsStore { - fn save_contacts(&mut self, contacts: impl Iterator) -> Result<(), Error>; - fn contacts(&self) -> Result, Error>; - fn contact_by_id(&self, id: Uuid) -> Result, Error>; -} diff --git a/net/gurk-rs/files/vendor/presage/src/config/sled.rs b/net/gurk-rs/files/vendor/presage/src/config/sled.rs deleted file mode 100644 index b1d908b..0000000 --- a/net/gurk-rs/files/vendor/presage/src/config/sled.rs +++ /dev/null @@ -1,604 +0,0 @@ -use std::{ - path::PathBuf, - sync::{Arc, RwLock}, -}; - -use async_trait::async_trait; -use libsignal_service::{ - models::Contact, - prelude::{ - protocol::{ - Context, Direction, IdentityKey, IdentityKeyPair, IdentityKeyStore, PreKeyRecord, - PreKeyStore, ProtocolAddress, SessionRecord, SessionStore, SessionStoreExt, - SignalProtocolError, SignedPreKeyRecord, SignedPreKeyStore, - }, - Uuid, - }, -}; -use log::{debug, trace, warn}; -use sled::IVec; - -use super::{ConfigStore, ContactsStore}; -use crate::{manager::State, Error}; - -const SLED_KEY_STATE: &str = "state"; -const SLED_KEY_CONTACTS: &str = "contacts"; - -const SLED_TREE_SESSIONS: &str = "sessions"; - -#[derive(Debug, Clone)] -pub struct SledConfigStore { - db: Arc>, -} - -impl SledConfigStore { - pub fn new(path: impl Into) -> Result { - Ok(SledConfigStore { - db: Arc::new(RwLock::new(sled::open(path.into())?)), - }) - } - - #[cfg(test)] - fn temporary() -> Result { - let db = sled::Config::new().temporary(true).open()?; - Ok(Self { - db: Arc::new(RwLock::new(db)), - }) - } - - pub fn get(&self, key: K) -> Result, Error> - where - K: AsRef, - { - trace!("get {}", key.as_ref()); - Ok(self.db.read().expect("poisoned mutex").get(key.as_ref())?) - } - - fn get_u32(&self, key: S) -> Result, Error> - where - S: AsRef, - { - trace!("getting u32 {}", key.as_ref()); - Ok(self.get(key.as_ref())?.map(|data| { - let mut a: [u8; 4] = Default::default(); - a.copy_from_slice(&data); - u32::from_le_bytes(a) - })) - } - - fn insert(&self, key: K, value: V) -> Result<(), Error> - where - K: AsRef, - IVec: From, - { - trace!("inserting {}", key.as_ref()); - let _ = self - .db - .try_write() - .expect("poisoned mutex") - .insert(key.as_ref(), value)?; - Ok(()) - } - - fn insert_u32(&self, key: S, value: u32) -> Result<(), Error> - where - S: AsRef, - { - trace!("inserting u32 {}", key.as_ref()); - self.db - .try_write() - .expect("poisoned mutex") - .insert(key.as_ref(), &value.to_le_bytes())?; - Ok(()) - } - - fn remove(&self, key: S) -> Result<(), Error> - where - S: AsRef, - { - trace!("removing {} from db", key.as_ref()); - self.db - .try_write() - .expect("poisoned mutex") - .remove(key.as_ref())?; - Ok(()) - } - - fn prekey_key(&self, id: u32) -> String { - format!("prekey-{:09}", id) - } - - fn signed_prekey_key(&self, id: u32) -> String { - format!("signed-prekey-{:09}", id) - } - - fn session_key(&self, addr: &ProtocolAddress) -> String { - format!("session-{}", addr) - } - - fn session_prefix(&self, name: &str) -> String { - format!("session-{}.", name) - } - - fn identity_key(&self, addr: &ProtocolAddress) -> String { - format!("identity-remote-{}", addr) - } - - pub fn keys(&self) -> Result<(Vec, Vec), SignalProtocolError> { - let db = self.db.read().expect("poisoned mutex"); - let global_keys = db - .iter() - .filter_map(|r| { - let (k, _) = r.ok()?; - Some(String::from_utf8_lossy(&k).to_string()) - }) - .collect(); - let session_keys = db - .open_tree(SLED_TREE_SESSIONS) - .map_err(|e| { - log::error!("failed to open sessions tree: {}", e); - SignalProtocolError::InternalError("sled error") - })? - .iter() - .filter_map(|r| { - let (k, _) = r.ok()?; - Some(String::from_utf8_lossy(&k).to_string()) - }) - .collect(); - Ok((global_keys, session_keys)) - } -} - -impl ConfigStore for SledConfigStore { - fn state(&self) -> Result { - let db = self.db.read().expect("poisoned mutex"); - db.get(SLED_KEY_STATE)?.map_or(Ok(State::New), |s| { - serde_json::from_slice(&s).map_err(Error::from) - }) - } - - fn save(&self, state: &State) -> Result<(), Error> { - let db = self.db.try_write().expect("poisoned mutex"); - db.clear()?; - db.insert(SLED_KEY_STATE, serde_json::to_vec(state)?)?; - Ok(()) - } - - fn pre_keys_offset_id(&self) -> Result { - Ok(self.get_u32("pre_keys_offset_id")?.unwrap_or(0)) - } - - fn set_pre_keys_offset_id(&self, id: u32) -> Result<(), Error> { - self.insert_u32("pre_keys_offset_id", id) - } - - fn next_signed_pre_key_id(&self) -> Result { - Ok(self.get_u32("next_signed_pre_key_id")?.unwrap_or(0)) - } - - fn set_next_signed_pre_key_id(&self, id: u32) -> Result<(), Error> { - self.insert_u32("next_signed_pre_key_id", id) - } -} - -impl ContactsStore for SledConfigStore { - fn save_contacts(&mut self, contacts: impl Iterator) -> Result<(), Error> { - let tree = self - .db - .write() - .expect("poisoned mutex") - .open_tree(SLED_KEY_CONTACTS)?; - for contact in contacts { - if let Some(uuid) = contact.address.uuid { - tree.insert(uuid.to_string(), serde_json::to_vec(&contact)?)?; - } else { - warn!("skipping contact {:?} without uuid", contact); - } - } - debug!("saved contacts"); - Ok(()) - } - - fn contacts(&self) -> Result, Error> { - Ok(self - .db - .read() - .expect("poisoned mutex") - .open_tree(SLED_KEY_CONTACTS)? - .iter() - .filter_map(Result::ok) - .filter_map(|(_key, buf)| serde_json::from_slice(&buf).ok()) - .collect()) - } - - fn contact_by_id(&self, id: Uuid) -> Result, Error> { - let db = self.db.read().expect("poisoned mutex"); - Ok( - if let Some(buf) = db.open_tree(SLED_KEY_CONTACTS)?.get(id.to_string())? { - let contact = serde_json::from_slice(&buf)?; - Some(contact) - } else { - None - }, - ) - } -} - -#[async_trait(?Send)] -impl PreKeyStore for SledConfigStore { - async fn get_pre_key( - &self, - prekey_id: u32, - _ctx: Context, - ) -> Result { - let buf = self - .get(self.prekey_key(prekey_id)) - .map_err(|e| { - log::error!("{}", e); - SignalProtocolError::InternalError("sled error") - })? - .ok_or(SignalProtocolError::InvalidPreKeyId)?; - PreKeyRecord::deserialize(&buf) - } - - async fn save_pre_key( - &mut self, - prekey_id: u32, - record: &PreKeyRecord, - _ctx: Context, - ) -> Result<(), SignalProtocolError> { - self.insert(self.prekey_key(prekey_id), record.serialize()?) - .expect("failed to store pre-key"); - Ok(()) - } - - async fn remove_pre_key( - &mut self, - prekey_id: u32, - _ctx: Context, - ) -> Result<(), SignalProtocolError> { - self.remove(self.prekey_key(prekey_id)) - .expect("failed to remove pre-key"); - Ok(()) - } -} - -#[async_trait(?Send)] -impl SignedPreKeyStore for SledConfigStore { - async fn get_signed_pre_key( - &self, - signed_prekey_id: u32, - _ctx: Context, - ) -> Result { - let buf = self - .get(self.signed_prekey_key(signed_prekey_id)) - .map_err(|e| { - log::error!("sled error: {}", e); - SignalProtocolError::InternalError("sled error") - })? - .ok_or(SignalProtocolError::InvalidSignedPreKeyId)?; - SignedPreKeyRecord::deserialize(&buf) - } - - async fn save_signed_pre_key( - &mut self, - signed_prekey_id: u32, - record: &SignedPreKeyRecord, - _ctx: Context, - ) -> Result<(), SignalProtocolError> { - self.insert( - self.signed_prekey_key(signed_prekey_id), - record.serialize()?, - ) - .map_err(|e| { - log::error!("sled error: {}", e); - SignalProtocolError::InternalError("sled error") - }) - } -} - -#[async_trait(?Send)] -impl SessionStore for SledConfigStore { - async fn load_session( - &self, - address: &ProtocolAddress, - _ctx: Context, - ) -> Result, SignalProtocolError> { - let key = self.session_key(address); - trace!("loading session from {}", key); - - let buf = self - .db - .try_read() - .expect("poisoned mutex") - .open_tree(SLED_TREE_SESSIONS) - .map_err(|e| { - log::error!("failed to open sessions tree: {}", e); - SignalProtocolError::InternalError("sled error") - })? - .get(key) - .map_err(|e| { - log::error!("sled error: {}", e); - SignalProtocolError::InternalError("sled error") - })?; - - buf.map(|buf| SessionRecord::deserialize(&buf)).transpose() - } - - async fn store_session( - &mut self, - address: &ProtocolAddress, - record: &SessionRecord, - _ctx: Context, - ) -> Result<(), SignalProtocolError> { - let key = self.session_key(address); - trace!("storing session for {:?} at {:?}", address, key); - self.db - .try_write() - .expect("poisoned mutex") - .open_tree(SLED_TREE_SESSIONS) - .map_err(|e| { - log::error!("failed to open sessions tree: {}", e); - SignalProtocolError::InternalError("sled error") - })? - .insert(key, record.serialize()?) - .map_err(|e| { - log::error!("failed to open sessions tree: {}", e); - SignalProtocolError::InternalError("sled error") - })?; - Ok(()) - } -} - -#[async_trait] -impl SessionStoreExt for SledConfigStore { - async fn get_sub_device_sessions(&self, name: &str) -> Result, SignalProtocolError> { - let session_prefix = self.session_prefix(name); - log::info!("get_sub_device_sessions: session_prefix={}", session_prefix); - let session_ids: Vec = self - .db - .read() - .expect("poisoned mutex") - .open_tree(SLED_TREE_SESSIONS) - .map_err(|e| { - log::error!("failed to open sessions tree: {}", e); - SignalProtocolError::InternalError("sled error") - })? - .scan_prefix(&session_prefix) - .filter_map(|r| { - let (key, _) = r.ok()?; - let key_str = String::from_utf8_lossy(&key); - let device_id = key_str.strip_prefix(&session_prefix)?; - device_id.parse().ok() - }) - .collect(); - Ok(session_ids) - } - - async fn delete_session(&self, address: &ProtocolAddress) -> Result<(), SignalProtocolError> { - let key = self.session_key(address); - trace!("deleting session with key: {}", key); - self.db - .try_write() - .expect("poisoned mutex") - .open_tree(SLED_TREE_SESSIONS) - .map_err(|e| { - log::error!("failed to open sessions tree: {}", e); - SignalProtocolError::InternalError("sled error") - })? - .remove(key) - .map_err(|_e| SignalProtocolError::InternalError("failed to delete session"))?; - Ok(()) - } - - async fn delete_all_sessions(&self, _name: &str) -> Result { - let tree = self - .db - .try_write() - .expect("poisoned mutex") - .open_tree(SLED_TREE_SESSIONS) - .map_err(|e| { - log::error!("failed to open sessions tree: {}", e); - SignalProtocolError::InternalError("sled error") - })?; - let len = tree.len(); - tree.clear() - .map_err(|_e| SignalProtocolError::InternalError("failed to delete all sessions"))?; - Ok(len) - } -} - -#[async_trait(?Send)] -impl IdentityKeyStore for SledConfigStore { - async fn get_identity_key_pair( - &self, - _ctx: Context, - ) -> Result { - trace!("getting identity_key_pair"); - match self.state() { - Ok(State::Registered { - private_key, - public_key, - .. - }) => Ok(IdentityKeyPair::new( - IdentityKey::new(public_key), - private_key, - )), - Ok(_) => Err(SignalProtocolError::InternalError( - "wrong state: no registration data yet", - )), - Err(e) => { - log::error!("identity key store error: {}", e); - Err(SignalProtocolError::InternalError("unhandled error")) - } - } - } - - async fn get_local_registration_id(&self, _ctx: Context) -> Result { - trace!("getting local_registration_id"); - match self.state() { - Ok(State::Registered { - registration_id, .. - }) => Ok(registration_id), - Ok(_) => Err(SignalProtocolError::InternalError( - "wrong state: no registration data yet", - )), - Err(e) => { - log::error!("identity key store error: {}", e); - Err(SignalProtocolError::InternalError("unhandled error")) - } - } - } - - async fn save_identity( - &mut self, - address: &ProtocolAddress, - identity_key: &IdentityKey, - _ctx: Context, - ) -> Result { - trace!("saving identity"); - self.insert(self.identity_key(address), identity_key.serialize()) - .map_err(|e| { - log::error!("error saving identity for {:?}: {}", address, e); - SignalProtocolError::InternalError("failed to save identity") - })?; - trace!("saved identity"); - Ok(false) - } - - async fn is_trusted_identity( - &self, - address: &ProtocolAddress, - identity_key: &IdentityKey, - _direction: Direction, - _ctx: Context, - ) -> Result { - match self.get(self.identity_key(address)).map_err(|_| { - SignalProtocolError::InternalError("failed to check if identity is trusted") - })? { - None => { - // when we encounter a new identity, we trust it by default - warn!("trusting new identity {:?}", address); - Ok(true) - } - Some(contents) => Ok(&IdentityKey::decode(&contents)? == identity_key), - } - } - - async fn get_identity( - &self, - address: &ProtocolAddress, - _ctx: Context, - ) -> Result, SignalProtocolError> { - let buf = self.get(self.identity_key(address)).map_err(|e| { - log::error!("error getting identity of {:?}: {}", address, e); - SignalProtocolError::InternalError("failed to read identity") - })?; - Ok(buf.map(|ref b| IdentityKey::decode(b).unwrap())) - } -} - -#[cfg(test)] -mod tests { - use core::fmt; - - use libsignal_service::prelude::protocol::{ - self, Direction, IdentityKeyStore, PreKeyRecord, PreKeyStore, SessionRecord, SessionStore, - SignedPreKeyRecord, SignedPreKeyStore, - }; - use quickcheck::{Arbitrary, Gen}; - - use super::SledConfigStore; - - #[derive(Debug, Clone)] - struct ProtocolAddress(protocol::ProtocolAddress); - - #[derive(Clone)] - struct KeyPair(protocol::KeyPair); - - impl fmt::Debug for KeyPair { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - writeln!(f, "{}", base64::encode(self.0.public_key.serialize())) - } - } - - impl Arbitrary for ProtocolAddress { - fn arbitrary(g: &mut Gen) -> Self { - let name: String = Arbitrary::arbitrary(g); - let device_id: u8 = Arbitrary::arbitrary(g); - ProtocolAddress(protocol::ProtocolAddress::new(name, device_id.into())) - } - } - - impl Arbitrary for KeyPair { - fn arbitrary(_g: &mut Gen) -> Self { - // Gen is not rand::CryptoRng here, see https://github.com/BurntSushi/quickcheck/issues/241 - KeyPair(protocol::KeyPair::generate(&mut rand::thread_rng())) - } - } - - #[quickcheck_async::tokio] - async fn test_save_get_trust_identity(addr: ProtocolAddress, key_pair: KeyPair) -> bool { - let mut db = SledConfigStore::temporary().unwrap(); - let identity_key = protocol::IdentityKey::new(key_pair.0.public_key); - db.save_identity(&addr.0, &identity_key, None) - .await - .unwrap(); - let id = db.get_identity(&addr.0, None).await.unwrap().unwrap(); - if id != identity_key { - return false; - } - db.is_trusted_identity(&addr.0, &id, Direction::Receiving, None) - .await - .unwrap() - } - - #[quickcheck_async::tokio] - async fn test_store_load_session(addr: ProtocolAddress) -> bool { - let session = SessionRecord::new_fresh(); - - let mut db = SledConfigStore::temporary().unwrap(); - db.store_session(&addr.0, &session, None).await.unwrap(); - if db.load_session(&addr.0, None).await.unwrap().is_none() { - return false; - } - let loaded_session = db.load_session(&addr.0, None).await.unwrap().unwrap(); - session.serialize().unwrap() == loaded_session.serialize().unwrap() - } - - #[quickcheck_async::tokio] - async fn test_prekey_store(id: u32, key_pair: KeyPair) -> bool { - let mut db = SledConfigStore::temporary().unwrap(); - let pre_key_record = PreKeyRecord::new(id, &key_pair.0); - db.save_pre_key(id, &pre_key_record, None).await.unwrap(); - if db.get_pre_key(id, None).await.unwrap().serialize().unwrap() - != pre_key_record.serialize().unwrap() - { - return false; - } - - db.remove_pre_key(id, None).await.unwrap(); - db.get_pre_key(id, None).await.is_err() - } - - #[quickcheck_async::tokio] - async fn test_signed_prekey_store( - id: u32, - timestamp: u64, - key_pair: KeyPair, - signature: Vec, - ) -> bool { - let mut db = SledConfigStore::temporary().unwrap(); - let signed_pre_key_record = SignedPreKeyRecord::new(id, timestamp, &key_pair.0, &signature); - db.save_signed_pre_key(id, &signed_pre_key_record, None) - .await - .unwrap(); - - db.get_signed_pre_key(id, None) - .await - .unwrap() - .serialize() - .unwrap() - == signed_pre_key_record.serialize().unwrap() - } -} diff --git a/net/gurk-rs/files/vendor/presage/src/errors.rs b/net/gurk-rs/files/vendor/presage/src/errors.rs deleted file mode 100644 index 8030663..0000000 --- a/net/gurk-rs/files/vendor/presage/src/errors.rs +++ /dev/null @@ -1,52 +0,0 @@ -use std::borrow::Cow; - -use libsignal_service::{models::ParseContactError, prelude::protocol::SignalProtocolError}; - -#[derive(thiserror::Error, Debug)] -#[non_exhaustive] -pub enum Error { - #[error("captcha from https://signalcaptchas.org/registration/generate.html required")] - CaptchaRequired, - #[error("input/output error: {0}")] - IoError(#[from] std::io::Error), - #[error("JSON error: {0}")] - JsonError(#[from] serde_json::Error), - #[error("data store error: {0}")] - DbError(#[from] sled::Error), - #[error("error decoding base64 data: {0}")] - Base64Error(#[from] base64::DecodeError), - #[error("wrong slice size: {0}")] - TryFromSliceError(#[from] std::array::TryFromSliceError), - #[error("phone number parsing error: {0}")] - PhoneNumberError(#[from] libsignal_service::prelude::phonenumber::ParseError), - #[error("UUID decoding error: {0}")] - UuidError(#[from] libsignal_service::prelude::UuidError), - #[error("libsignal-protocol error: {0}")] - ProtocolError(#[from] SignalProtocolError), - #[error("libsignal-service error: {0}")] - ServiceError(#[from] libsignal_service::prelude::ServiceError), - #[error("libsignal-service error: {0}")] - ProfileManagerError(#[from] libsignal_service::ProfileManagerError), - #[error("libsignal-service sending error: {0}")] - MessageSenderError(#[from] libsignal_service::prelude::MessageSenderError), - #[error("libsignal-service error: {0}")] - MessageReceiverError(#[from] libsignal_service::receiver::MessageReceiverError), - #[error("this client is already registered with Signal")] - AlreadyRegisteredError, - #[error("this client is not yet registered, please register or link as a secondary device")] - NotYetRegisteredError, - #[error("failed to provision device: {0}")] - ProvisioningError(#[from] libsignal_service::provisioning::ProvisioningError), - #[error("no provisioning message received")] - NoProvisioningMessageReceived, - #[error("qr code error: {0}")] - QrCodeError(qr2term::QrError), - #[error("missing key {0} in config DB")] - MissingKeyError(Cow<'static, str>), - #[error("receiving pipe was interrupted")] - MessagePipeInterruptedError, - #[error("failed to parse contact information: {0}")] - ParseContactError(#[from] ParseContactError), - #[error("failed to decrypt attachment: {0}")] - AttachmentCipherError(#[from] libsignal_service::attachment_cipher::AttachmentCipherError), -} diff --git a/net/gurk-rs/files/vendor/presage/src/lib.rs b/net/gurk-rs/files/vendor/presage/src/lib.rs deleted file mode 100644 index faad192..0000000 --- a/net/gurk-rs/files/vendor/presage/src/lib.rs +++ /dev/null @@ -1,34 +0,0 @@ -mod cache; -mod config; -mod errors; -mod manager; - -#[cfg(feature = "sled-store")] -pub use config::sled::SledConfigStore; - -pub use config::ConfigStore; -pub use errors::Error; -pub use manager::{Manager, State}; - -#[deprecated(note = "Please help use improve the prelude module instead")] -pub use libsignal_service; - -pub mod prelude { - pub use libsignal_service::{ - configuration::SignalServers, - content::{ - self, Content, ContentBody, DataMessage, GroupContext, GroupContextV2, GroupType, - Metadata, SyncMessage, - }, - models::Contact, - prelude::{ - phonenumber::{self, PhoneNumber}, - GroupMasterKey, GroupSecretParams, Uuid, - }, - proto, - sender::AttachmentSpec, - ServiceAddress, - }; -} - -const USER_AGENT: &str = concat!(env!("CARGO_PKG_NAME"), "-rs-", env!("CARGO_PKG_VERSION")); diff --git a/net/gurk-rs/files/vendor/presage/src/manager.rs b/net/gurk-rs/files/vendor/presage/src/manager.rs deleted file mode 100644 index b56ef9c..0000000 --- a/net/gurk-rs/files/vendor/presage/src/manager.rs +++ /dev/null @@ -1,807 +0,0 @@ -use std::{convert::TryInto, time::UNIX_EPOCH}; - -use futures::{channel::mpsc, future, AsyncReadExt, Stream, StreamExt}; -use log::{error, trace, warn}; -use rand::{distributions::Alphanumeric, CryptoRng, Rng, RngCore}; -use serde::{Deserialize, Serialize}; - -use libsignal_service::{ - attachment_cipher::decrypt_in_place, - cipher, - configuration::{ServiceConfiguration, SignalServers, SignalingKey}, - content::{ContentBody, DataMessage, SyncMessage}, - groups_v2::{GroupsManager, InMemoryCredentialsCache}, - messagepipe::ServiceCredentials, - models::Contact, - prelude::{ - phonenumber::PhoneNumber, - protocol::{KeyPair, PrivateKey, PublicKey}, - Content, Envelope, GroupMasterKey, GroupSecretParams, PushService, Uuid, - }, - proto::{sync_message, AttachmentPointer}, - provisioning::{ - generate_registration_id, LinkingManager, ProvisioningManager, SecondaryDeviceProvisioning, - VerificationCodeResponse, - }, - push_service::{ - AccountAttributes, DeviceCapabilities, ProfileKey, ServiceError, WhoAmIResponse, - DEFAULT_DEVICE_ID, - }, - receiver::MessageReceiver, - sender::{AttachmentSpec, AttachmentUploadError}, - utils::{serde_private_key, serde_public_key, serde_signaling_key}, - AccountManager, Profile, ServiceAddress, -}; - -use libsignal_service_hyper::push_service::HyperPushService; - -use crate::cache::CacheCell; -use crate::{config::ConfigStore, Error}; - -type ServiceCipher = cipher::ServiceCipher; -type MessageSender = - libsignal_service::prelude::MessageSender; - -#[derive(Clone)] -pub struct Manager { - /// Persistent store - config_store: C, - /// Random generator - csprng: R, - /// Part of the manager which is persisted in the store. - state: State, - /// Part of the manager which is cached. - /// - /// The cache should be cleared when state changes. - cache: Cache, -} - -#[derive(Clone, Default)] -struct Cache { - push_service: CacheCell, -} - -impl Cache { - fn clear(&self) { - self.push_service.clear(); - } -} - -#[derive(Clone, Serialize, Deserialize)] -pub enum State { - New, - Registration { - signal_servers: SignalServers, - phone_number: PhoneNumber, - use_voice_call: bool, - }, - Linking { - signal_servers: SignalServers, - #[serde(with = "serde_signaling_key")] - signaling_key: SignalingKey, - password: String, - }, - Confirmation { - signal_servers: SignalServers, - phone_number: PhoneNumber, - password: String, - }, - Registered { - signal_servers: SignalServers, - device_name: Option, - phone_number: PhoneNumber, - uuid: Uuid, - password: String, - #[serde(with = "serde_signaling_key")] - signaling_key: SignalingKey, - device_id: Option, - registration_id: u32, - #[serde(with = "serde_private_key")] - private_key: PrivateKey, - #[serde(with = "serde_public_key")] - public_key: PublicKey, - profile_key: ProfileKey, - }, -} - -impl Manager -where - C: ConfigStore + Sync, -{ - /// Creates a new manager from a store with a default random generator. - pub fn with_store(store: C) -> Result { - Self::new(store, rand::thread_rng()) - } -} - -impl Manager -where - C: ConfigStore + Sync, - R: Rng + CryptoRng + Clone, -{ - pub fn new(config_store: C, csprng: R) -> Result { - let state = config_store.state()?; - Ok(Manager { - config_store, - csprng, - state, - cache: Default::default(), - }) - } - - /// Sets the state and saves it into the store. - /// - /// The cache is also cleared. - fn set_state(&mut self, state: State) -> Result<(), Error> { - self.state = state; - self.cache.clear(); - self.config_store.save(&self.state) - } - - fn credentials(&self) -> Result, Error> { - match &self.state { - State::New { .. } => Err(Error::NotYetRegisteredError), - State::Registration { .. } => Ok(None), - State::Linking { .. } => Ok(None), - State::Confirmation { - phone_number, - password, - .. - } => Ok(Some(ServiceCredentials { - uuid: None, - phonenumber: phone_number.clone(), - password: Some(password.clone()), - signaling_key: None, - device_id: None, - })), - State::Registered { - phone_number, - uuid, - device_id, - password, - signaling_key, - .. - } => Ok(Some(ServiceCredentials { - uuid: Some(*uuid), - phonenumber: phone_number.clone(), - password: Some(password.clone()), - signaling_key: Some(*signaling_key), - device_id: *device_id, - })), - } - } - - /// Checks if the manager has a registered device. - pub fn is_registered(&self) -> bool { - matches!(&self.state, State::Registered { .. }) - } - - pub fn config_store(&self) -> &C { - &self.config_store - } - - pub fn uuid(&self) -> Uuid { - match &self.state { - State::Registered { uuid, .. } => *uuid, - _ => Default::default(), - } - } - - pub fn phone_number(&self) -> Option<&PhoneNumber> { - match &self.state { - State::Registered { phone_number, .. } => Some(phone_number), - _ => None, - } - } - - #[cfg(feature = "quirks")] - pub fn dump_config(&mut self) -> Result<(), Error> { - serde_json::to_writer_pretty(std::io::stderr(), &self.state)?; - - Ok(()) - } - - pub async fn register( - &mut self, - signal_servers: SignalServers, - phone_number: PhoneNumber, - use_voice_call: bool, - captcha: Option<&str>, - force: bool, - ) -> Result<(), Error> { - // generate a random 24 bytes password - let rng = rand::rngs::OsRng::default(); - let password: String = rng.sample_iter(&Alphanumeric).take(24).collect(); - - if !force - && matches!( - self.state, - State::Registration { .. } | State::Registered { .. } - ) - { - return Err(Error::AlreadyRegisteredError); - } - - // re-initialize the state to new with specified servers & phone number - self.set_state(State::Registration { - signal_servers, - phone_number: phone_number.clone(), - use_voice_call, - })?; - - let mut push_service = self.push_service()?; - let mut provisioning_manager: ProvisioningManager = - ProvisioningManager::new(&mut push_service, phone_number.clone(), password.clone()); - - let verification_code_response = if use_voice_call { - provisioning_manager - .request_voice_verification_code(captcha, None) - .await? - } else { - provisioning_manager - .request_sms_verification_code(captcha, None) - .await? - }; - - if let VerificationCodeResponse::CaptchaRequired = verification_code_response { - return Err(Error::CaptchaRequired); - } - - self.set_state(State::Confirmation { - signal_servers, - phone_number, - password, - }) - } - - pub async fn confirm_verification_code(&mut self, confirm_code: u32) -> Result<(), Error> { - trace!("confirming verification code"); - let (signal_servers, phone_number, password) = match &self.state { - State::Confirmation { - signal_servers, - phone_number, - password, - } => (*signal_servers, phone_number, password), - State::Registered { .. } => return Err(Error::AlreadyRegisteredError), - _ => return Err(Error::NotYetRegisteredError), - }; - - // see libsignal-protocol-c / signal_protocol_key_helper_generate_registration_id - let registration_id = generate_registration_id(&mut self.csprng); - trace!("registration_id: {}", registration_id); - - let mut push_service = self.push_service()?; - let mut provisioning_manager: ProvisioningManager = - ProvisioningManager::new( - &mut push_service, - phone_number.clone(), - password.to_string(), - ); - - let mut rng = rand::thread_rng(); - - // generate a 52 bytes signaling key - let mut signaling_key = [0u8; 52]; - rng.fill_bytes(&mut signaling_key); - - let mut profile_key = [0u8; 32]; - rng.fill_bytes(&mut profile_key); - let profile_key = ProfileKey(profile_key); - - let registered = provisioning_manager - .confirm_verification_code( - confirm_code, - AccountAttributes { - signaling_key: Some(signaling_key.to_vec()), - registration_id, - voice: false, - video: false, - fetches_messages: true, - pin: None, - registration_lock: None, - unidentified_access_key: Some(profile_key.derive_access_key()), - unrestricted_unidentified_access: false, // TODO: make this configurable? - discoverable_by_phone_number: true, - capabilities: DeviceCapabilities { - uuid: true, - gv2: true, - storage: false, - gv1_migration: true, - }, - }, - ) - .await?; - - let identity_key_pair = KeyPair::generate(&mut self.csprng); - - let phone_number = phone_number.clone(); - let password = password.clone(); - self.set_state(State::Registered { - signal_servers, - device_name: None, - phone_number, - uuid: registered.uuid, - password, - signaling_key, - device_id: None, - registration_id, - private_key: identity_key_pair.private_key, - public_key: identity_key_pair.public_key, - profile_key, - })?; - - trace!("confirmed! (and registered)"); - - self.register_pre_keys().await?; - - Ok(()) - } - - pub async fn link_secondary_device( - &mut self, - signal_servers: SignalServers, - device_name: String, - ) -> Result<(), Error> { - // generate a random 24 bytes password - let mut rng = rand::rngs::OsRng::default(); - let password: String = rng.sample_iter(&Alphanumeric).take(24).collect(); - - // generate a 52 bytes signaling key - let mut signaling_key = [0u8; 52]; - rng.fill_bytes(&mut signaling_key); - - self.set_state(State::Linking { - signal_servers, - password: password.clone(), - signaling_key, - })?; - - let push_service = self.push_service()?; - let mut linking_manager: LinkingManager = - LinkingManager::new(push_service, password.clone()); - - let (tx, mut rx) = mpsc::channel(1); - - let (fut1, fut2) = future::join( - linking_manager.provision_secondary_device(&mut self.csprng, signaling_key, tx), - async move { - while let Some(provisioning_step) = rx.next().await { - match provisioning_step { - SecondaryDeviceProvisioning::Url(url) => { - log::info!("generating qrcode from provisioning link: {}", &url); - qr2term::print_qr(url.to_string()).map_err(|e| { - log::error!("failed to open qr code: {}", e); - Error::QrCodeError(e) - })?; - } - SecondaryDeviceProvisioning::NewDeviceRegistration { - phone_number, - device_id, - registration_id, - uuid, - private_key, - public_key, - profile_key, - } => { - log::info!("successfully registered device {}", &uuid); - return Ok(( - phone_number, - device_id.device_id, - registration_id, - uuid, - private_key, - public_key, - profile_key, - )); - } - } - } - Err(Error::NoProvisioningMessageReceived) - }, - ) - .await; - - let _ = fut1?; - let (phone_number, device_id, registration_id, uuid, private_key, public_key, profile_key) = - fut2?; - - self.set_state(State::Registered { - signal_servers, - device_name: Some(device_name), - phone_number, - uuid, - signaling_key, - password, - device_id: Some(device_id), - registration_id, - public_key, - private_key, - profile_key: ProfileKey(profile_key.try_into().expect("32 bytes for profile key")), - })?; - - self.register_pre_keys().await?; - self.set_account_attributes().await?; - self.request_contacts_sync().await?; - - Ok(()) - } - - pub async fn whoami(&self) -> Result { - Ok(self.push_service()?.whoami().await?) - } - - pub async fn retrieve_profile(&self) -> Result { - match &self.state { - State::Registered { - uuid, profile_key, .. - } => self.retrieve_profile_by_uuid(*uuid, **profile_key).await, - _ => Err(Error::NotYetRegisteredError), - } - } - - pub async fn retrieve_profile_by_uuid( - &self, - uuid: Uuid, - profile_key: [u8; 32], - ) -> Result { - let mut account_manager = AccountManager::new(self.push_service()?, Some(profile_key)); - Ok(account_manager.retrieve_profile(uuid).await?) - } - - async fn register_pre_keys(&mut self) -> Result<(), Error> { - let profile_key = match &self.state { - State::Registered { profile_key, .. } => profile_key, - _ => return Err(Error::NotYetRegisteredError), - }; - - let mut account_manager = AccountManager::new(self.push_service()?, Some(**profile_key)); - - let (pre_keys_offset_id, next_signed_pre_key_id) = account_manager - .update_pre_key_bundle( - &self.config_store.clone(), - &mut self.config_store.clone(), - &mut self.config_store.clone(), - &mut self.csprng, - self.config_store.pre_keys_offset_id()?, - self.config_store.next_signed_pre_key_id()?, - true, - ) - .await?; - - self.config_store - .set_pre_keys_offset_id(pre_keys_offset_id)?; - self.config_store - .set_next_signed_pre_key_id(next_signed_pre_key_id)?; - - Ok(()) - } - - pub async fn set_account_attributes(&mut self) -> Result<(), Error> { - let (profile_key, registration_id) = match &self.state { - State::Registered { - profile_key, - registration_id, - .. - } => (profile_key, registration_id), - _ => return Err(Error::NotYetRegisteredError), - }; - dbg!(profile_key.derive_access_key().len()); - - let mut account_manager = AccountManager::new(self.push_service()?, Some(**profile_key)); - account_manager - .set_account_attributes(AccountAttributes { - registration_id: *registration_id, - signaling_key: None, - voice: false, - video: false, - fetches_messages: true, - pin: None, - registration_lock: None, - unidentified_access_key: Some(profile_key.derive_access_key()), - unrestricted_unidentified_access: false, - discoverable_by_phone_number: true, - capabilities: DeviceCapabilities { - uuid: true, - storage: false, - gv2: true, - gv1_migration: true, - }, - }) - .await?; - Ok(()) - } - - /// Request that the primary device to encrypt & send all of its contacts as a message to ourselves - /// which can be then received, decrypted and stored in the message receiving loop. - /// - /// Note: if this is successful, the contacts are not yet received & stored, and will only be - /// processed when they're received using the `MessageReceiver`. - pub async fn request_contacts_sync(&self) -> Result<(), Error> { - let uuid = match &self.state { - State::Registered { uuid, .. } => uuid, - _ => return Err(Error::NotYetRegisteredError), - }; - - let sync_message = SyncMessage { - request: Some(sync_message::Request { - r#type: Some(sync_message::request::Type::Contacts as i32), - }), - ..Default::default() - }; - - let timestamp = std::time::SystemTime::now() - .duration_since(UNIX_EPOCH) - .expect("Time went backwards") - .as_millis() as u64; - - self.send_message(*uuid, sync_message, timestamp).await?; - - Ok(()) - } - - pub fn get_contacts(&self) -> Result, Error> { - Ok(self.config_store.contacts()?.into_iter()) - } - - pub fn get_contact_by_id(&self, id: Uuid) -> Result, Error> { - self.config_store.contact_by_id(id) - } - - async fn receive_messages_encrypted( - &self, - ) -> Result>, Error> { - // TODO: error if we're primary registered device, as this is only for secondary devices - - let credentials = self.credentials()?.ok_or(Error::NotYetRegisteredError)?; - let pipe = MessageReceiver::new(self.push_service()?) - .create_message_pipe(credentials) - .await?; - Ok(pipe.stream()) - } - - pub async fn receive_messages(&self) -> Result, Error> { - struct StreamState { - encrypted_messages: S, - service_cipher: ServiceCipher, - push_service: HyperPushService, - config_store: C, - } - - let init = StreamState { - encrypted_messages: Box::pin(self.receive_messages_encrypted().await?), - service_cipher: self.new_service_cipher()?, - push_service: self.push_service()?, - config_store: self.config_store.clone(), - }; - - Ok(futures::stream::unfold(init, |mut state| async move { - loop { - match state.encrypted_messages.next().await { - Some(Ok(envelope)) => { - match state.service_cipher.open_envelope(envelope).await { - Ok(Some(Content { - body: - ContentBody::SynchronizeMessage(SyncMessage { - contacts: Some(contacts), - .. - }), - .. - })) => { - let mut message_receiver = - MessageReceiver::new(state.push_service.clone()); - match message_receiver.retrieve_contacts(&contacts).await { - Ok(contacts_iter) => { - if let Err(e) = state - .config_store - .save_contacts(contacts_iter.filter_map(Result::ok)) - { - error!("failed to save contacts: {}", e) - } - } - Err(e) => error!("failed to retrieve contacts: {}", e), - } - } - Ok(Some(content)) => return Some((content, state)), - Ok(None) => warn!("Empty envelope..., message will be skipped!"), - Err(e) => { - error!("Error opening envelope: {:?}, message will be skipped!", e); - } - } - } - Some(Err(e)) => error!("Error: {}", e), - None => return None, - } - } - })) - } - - pub async fn send_message( - &self, - recipient_addr: impl Into, - message: impl Into, - timestamp: u64, - ) -> Result<(), Error> { - let mut sender = self.new_message_sender()?; - - let online_only = false; - sender - .send_message( - &recipient_addr.into(), - None, - message, - timestamp, - online_only, - ) - .await?; - - Ok(()) - } - - pub async fn upload_attachments( - &self, - attachments: Vec<(AttachmentSpec, Vec)>, - ) -> Result>, Error> { - let sender = self.new_message_sender()?; - let upload = future::join_all(attachments.into_iter().map(move |(spec, contents)| { - let mut sender = sender.clone(); - async move { sender.upload_attachment(spec, contents).await } - })); - Ok(upload.await) - } - - pub async fn send_message_to_group( - &self, - recipients: impl IntoIterator, - message: DataMessage, - timestamp: u64, - ) -> Result<(), Error> { - let mut sender = self.new_message_sender()?; - - let recipients: Vec<_> = recipients.into_iter().collect(); - - let online_only = false; - let results = sender - .send_message_to_group(recipients, None, message, timestamp, online_only) - .await; - - // return first error if any - results.into_iter().find(|res| res.is_err()).transpose()?; - - Ok(()) - } - - pub async fn clear_sessions(&self, recipient: &ServiceAddress) -> Result<(), Error> { - self.config_store - .delete_all_sessions(&recipient.identifier()) - .await?; - Ok(()) - } - - pub async fn get_group_v2( - &mut self, - group_master_key: GroupMasterKey, - ) -> Result { - let (signal_servers, _phone_number, uuid, _device_id) = match &self.state { - State::Registered { - signal_servers, - phone_number, - uuid, - device_id, - .. - } => (signal_servers, phone_number, uuid, device_id), - _ => return Err(Error::NotYetRegisteredError), - }; - - let service_configuration: ServiceConfiguration = (*signal_servers).into(); - let server_public_params = service_configuration.zkgroup_server_public_params; - - let mut groups_v2_credentials_cache = InMemoryCredentialsCache::default(); - let mut groups_v2_api = GroupsManager::new( - self.push_service()?, - &mut groups_v2_credentials_cache, - server_public_params, - ); - - let group_secret_params = GroupSecretParams::derive_from_master_key(group_master_key); - let authorization = groups_v2_api - .get_authorization_for_today(*uuid, group_secret_params) - .await?; - - Ok(groups_v2_api - .get_group(group_secret_params, authorization) - .await?) - } - - pub async fn get_attachment( - &self, - attachment_pointer: &AttachmentPointer, - ) -> Result, Error> { - let mut service = self.push_service()?; - let mut attachment_stream = service.get_attachment(attachment_pointer).await?; - - // We need the whole file for the crypto to check out - let mut ciphertext = Vec::new(); - let len = attachment_stream.read_to_end(&mut ciphertext).await?; - - trace!("downloaded encrypted attachment of {} bytes", len); - - let key: [u8; 64] = attachment_pointer.key().try_into()?; - decrypt_in_place(key, &mut ciphertext)?; - - Ok(ciphertext) - } - - /// Returns a clone of a cached push service. - /// - /// If no service is yet cached, it will create and cache one. - fn push_service(&self) -> Result { - self.cache.push_service.get(|| { - let signal_servers = match &self.state { - State::Registration { signal_servers, .. } - | State::Linking { signal_servers, .. } - | State::Confirmation { signal_servers, .. } - | State::Registered { signal_servers, .. } => signal_servers, - _ => return Err(Error::NotYetRegisteredError), - }; - - let credentials = self.credentials()?; - let service_configuration: ServiceConfiguration = (*signal_servers).into(); - - Ok(HyperPushService::new( - service_configuration, - credentials, - crate::USER_AGENT.to_string(), - )) - }) - } - - /// Creates a new message sender. - fn new_message_sender(&self) -> Result, Error> { - let (phone_number, uuid, device_id) = match &self.state { - State::Registered { - phone_number, - uuid, - device_id, - .. - } => (phone_number, uuid, device_id), - _ => return Err(Error::NotYetRegisteredError), - }; - - let local_addr = ServiceAddress { - uuid: Some(*uuid), - phonenumber: Some(phone_number.clone()), - relay: None, - }; - - Ok(MessageSender::new( - self.push_service()?, - self.new_service_cipher()?, - self.csprng.clone(), - self.config_store.clone(), - self.config_store.clone(), - local_addr, - device_id.unwrap_or(DEFAULT_DEVICE_ID), - )) - } - - /// Creates a new service cipher. - fn new_service_cipher(&self) -> Result, Error> { - let signal_servers = match &self.state { - State::Registered { signal_servers, .. } => signal_servers, - _ => return Err(Error::NotYetRegisteredError), - }; - - let service_configuration: ServiceConfiguration = (*signal_servers).into(); - let certificate_validator = service_configuration.credentials_validator()?; - let service_cipher = ServiceCipher::new( - self.config_store.clone(), - self.config_store.clone(), - self.config_store.clone(), - self.config_store.clone(), - self.csprng.clone(), - certificate_validator, - ); - - Ok(service_cipher) - } -} diff --git a/net/gurk-rs/files/vendor/zkgroup/.cargo-checksum.json b/net/gurk-rs/files/vendor/zkgroup/.cargo-checksum.json deleted file mode 100644 index 30e2271..0000000 --- a/net/gurk-rs/files/vendor/zkgroup/.cargo-checksum.json +++ /dev/null @@ -1 +0,0 @@ -{"files":{"Cargo.toml":"cb7ca5fecaa564cae74864f55e2d46ebd7582a3e8d782533e545aaa016478745","benches/zkgroup_benchmarks.rs":"79c33b5b2b2da0e9d99f472002dad8af4505ef7db77c15c2065306d9538a8ca9","rustfmt.license-template":"6c0aa49b09640fe7bc67479f301f9f0303e97d57cbc1f8e2460caa4d7bb168a0","rustfmt.toml":"94c610400bd30d5afe9cc8b0a2ec887e2aa2429b90ec0c156562e23ad4046df9","scripts/format-code":"74a8db574cd2bd70eb5dda671749fddef7c90ae5a30595cccd9e316da68a0daa","src/api/auth/auth_credential.rs":"0fae28381c284ccd125e7a19e40f46a61bae61e3d0f7c74ab07c9dbe2290ff92","src/api/auth/auth_credential_presentation.rs":"cb9353ef068236574ba909faad0a614f3f09360505307f0d45892d632aaa62c7","src/api/auth/auth_credential_response.rs":"663ef06a9dbc5feceb276d87afd71083dbd4be17ba20fcbe5ab7d7bc1146eb77","src/api/auth/mod.rs":"2f14f5532dd059497adc313a2e044dc1a92797cd855a4e4b848e63262bef3f55","src/api/groups/group_params.rs":"7b9622724054d15d0cb78685b562465e07f24829ee09efebe4e639e7e93f7bee","src/api/groups/mod.rs":"2a86d9a4d1f9fedfbf1867d00a610f8650f3b0310d5de2a24aef5329063acb5a","src/api/groups/profile_key_ciphertext.rs":"538d99d186d8331e0b34659efb7ceb27bc43aebf24a48b4441e26f21402499be","src/api/groups/uuid_ciphertext.rs":"0630f14f49aa508700b3e7d781770ee60b0e34bdadc832f59ab693447e7705c3","src/api/mod.rs":"cddb1b813022ad6474157867b13328d0023fd5b940786da33d3bf4b9848bc1aa","src/api/profiles/mod.rs":"d7bc78ec76124dea7c6df90e391ae1544dbe7f10ba987c0338971b35e202e0bb","src/api/profiles/profile_key.rs":"d2d2f31db60fc981b25b9da87076f1cc3473cc9136501f2e8384dd3151375280","src/api/profiles/profile_key_commitment.rs":"a4760d56a536d31a64316b566e283fe2fc61977976c71fa0ae4b869d08d1044c","src/api/profiles/profile_key_credential.rs":"15a2884bdbe8023e61046a1a16a4f386254bb4e951d7bede2c052f1eeb4928b4","src/api/profiles/profile_key_credential_presentation.rs":"5523f68a175e4ddf5a21af176c8856ea3e6c6d64df5b4afbb5912aa7c651a7a3","src/api/profiles/profile_key_credential_request.rs":"425ef24c34992347f1870f132439d5b2c1be103dfc5b4bffe2d137aa1bd74c9e","src/api/profiles/profile_key_credential_request_context.rs":"19183a6eff15e9b68340b848e4acf2ad2ef69689ec1906494781d495d1cc8f3e","src/api/profiles/profile_key_credential_response.rs":"adda434fe28f42d2102a9f9b8da2b55ff6ef70d84992702e696f19c5b3cdc012","src/api/profiles/profile_key_version.rs":"7368c1936660ecf82211e040725008c30107440c15dd28185ae0f37dc4d96f9e","src/api/server_params.rs":"5447b5c75a678ce45c010b1d2d74b0ca5e948ffcf0bcf70c79c76bc703c65e98","src/common/constants.rs":"2444cf6bdd893dc4dbde6a3e80c965c3533ae61e54e0ee8d15e2edf7d869d94b","src/common/errors.rs":"9c31438f75c6c147b1e4f66b3155faf9c45b6d9f8d68bc6cd3276519df3a29d7","src/common/mod.rs":"6ebf7405863030fe9bc7ef4a3de7308d5ab3110ea4bbc21465359f7ca049a788","src/common/sho.rs":"3b14b9810c85c2b07857054fa12dc00e401a3b308c50b245009302271451e6d1","src/common/simple_types.rs":"b33af57622f3e9a95978afc291365732ef001a8fedcb44b9da69c07fe8da6005","src/crypto/credentials.rs":"284a1c5c0fa3869a70033deb0247aebb990a5d1ed2348399253cd183d0fe388d","src/crypto/mod.rs":"858b765777f4c152d69c73359d3803d6c490d719efdc71957ceb8753dafbeaa4","src/crypto/profile_key_commitment.rs":"5cdc107bfd47824535c2ab3db1b1b1d46f80a80297ab03f30f5628df8a4acd69","src/crypto/profile_key_credential_request.rs":"2773d27af83dcfa277d1b538fab8fe6b833611bb0d7ec05dbf87958e005a3012","src/crypto/profile_key_encryption.rs":"48bf4d5b0ebfe3cf454ee66758a64e7247948bf40ee945e9233fe6a8a53f156e","src/crypto/profile_key_struct.rs":"3d00f44c3cbf6be84b5973d7fc660aac3560bf5a989b17d8c0daaf9564b6c2dc","src/crypto/proofs.rs":"b32a368481734112837a839cd545fe5026945de608457d3462f6cbb5b11814a9","src/crypto/signature.rs":"f58b7265ac6218cd1a0d65f57e6d4fcf6b3aa56edc84263dacaf1ed19ab9db02","src/crypto/uid_encryption.rs":"fe21c49e75f960bac6a587159635d6dfd4bfcb0b0519fd5c90c8992ac8ee35f9","src/crypto/uid_struct.rs":"6a0752e293455ea3b4a23f210ce0e154ae252cc1cd51b0a158b5ab828516c231","src/ffi/constants.rs":"67e4c083467ebcc68bcc8f49f000328e5a293ea340c385d8647267f6502ec8f4","src/ffi/ffiapi.rs":"8f8d8fee4c5968800982bd1a6b8a3e56a28f1a14f5e83970e84e59e187839ef6","src/ffi/ffiapijava.rs":"bd845088122df2f909cd29c95c656a0870349593e92a42c9f47b781dd110075d","src/ffi/mod.rs":"241eefb61cdfa635f697466bd822a3f6b504cc21b118a83cb6b80f1d08a0c516","src/ffi/simpleapi.rs":"7b87022a3186162f8e0b13f3f0f210240bbdebe7acc20368c74012de5b3c0466","src/lib.rs":"9d26663d4f4080059a63faac6da97e0e300b92b21bf9ce7e47ae7fa7e49e0fe8","tests/integration_tests.rs":"90ac9ac9cc9376a0dc7dcb05c2a2ef997bb58e5dde13fe2bbed0fea1e4c90cf8"},"package":null} \ No newline at end of file diff --git a/net/gurk-rs/files/vendor/zkgroup/Cargo.toml b/net/gurk-rs/files/vendor/zkgroup/Cargo.toml deleted file mode 100644 index 01f208d..0000000 --- a/net/gurk-rs/files/vendor/zkgroup/Cargo.toml +++ /dev/null @@ -1,53 +0,0 @@ -# -# Copyright (C) 2020 Signal Messenger, LLC. -# All rights reserved. -# -# SPDX-License-Identifier: GPL-3.0-only -# - -[package] -name = "zkgroup" -version = "0.7.3" -authors = ["Trevor Perrin "] -edition = "2018" -description = "A zero-knowledge group library" -license = "GPL-3.0-only" - -[lib] -name = "zkgroup" -crate-type = [ "staticlib", "cdylib", "rlib"] - -[dependencies] -bincode = "1.2.1" -serde = { version = "1.0.106", features = ["derive"] } -sha2 = "0.8.0" -jni = { version = "0.16.0", default-features = false } -hex = "0.4.0" -aead = "0.4.0" -aes-gcm-siv = "0.10.0" - -[dependencies.curve25519-dalek] -features = ["std", "serde", "alloc"] -version = "2.0.0" -git = "https://github.com/signalapp/curve25519-dalek.git" -branch = "lizard2" - -[dependencies.poksho] -git = "https://github.com/signalapp/poksho.git" -tag = "v0.7.0" - -[features] -default = ["u64_backend"] -u32_backend = ["curve25519-dalek/u32_backend"] -u64_backend = ["curve25519-dalek/u64_backend"] -simd_backend = ["curve25519-dalek/simd_backend"] -nightly = ["curve25519-dalek/nightly"] - -# Below is for benchmarking: - -[dev-dependencies] -criterion = "0.3.1" - -[[bench]] -name = "zkgroup_benchmarks" -harness = false diff --git a/net/gurk-rs/files/vendor/zkgroup/benches/zkgroup_benchmarks.rs b/net/gurk-rs/files/vendor/zkgroup/benches/zkgroup_benchmarks.rs deleted file mode 100644 index 26c7de6..0000000 --- a/net/gurk-rs/files/vendor/zkgroup/benches/zkgroup_benchmarks.rs +++ /dev/null @@ -1,219 +0,0 @@ -use criterion::{criterion_group, criterion_main, Criterion}; - -extern crate zkgroup; - -fn benchmark_integration_auth(c: &mut Criterion) { - let server_secret_params = zkgroup::ServerSecretParams::generate(zkgroup::TEST_ARRAY_32); - let server_public_params = server_secret_params.get_public_params(); - - let master_key = zkgroup::groups::GroupMasterKey::new(zkgroup::TEST_ARRAY_32_1); - let group_secret_params = - zkgroup::groups::GroupSecretParams::derive_from_master_key(master_key); - let group_public_params = group_secret_params.get_public_params(); - - // Random UID and issueTime - let uid = zkgroup::TEST_ARRAY_16; - let redemption_time = 123456u32; - - // SERVER - // Issue credential - let randomness = zkgroup::TEST_ARRAY_32_2; - let auth_credential_response = - server_secret_params.issue_auth_credential(randomness, uid, redemption_time); - - c.bench_function("issue_auth_credential", |b| { - b.iter(|| server_secret_params.issue_auth_credential(randomness, uid, redemption_time)) - }); - - // CLIENT - let auth_credential = server_public_params - .receive_auth_credential(uid, redemption_time, &auth_credential_response) - .unwrap(); - - c.bench_function("receive_auth_credential", |b| { - b.iter(|| { - server_public_params - .receive_auth_credential(uid, redemption_time, &auth_credential_response) - .unwrap() - }) - }); - - // Create and decrypt user entry - let uuid_ciphertext = group_secret_params.encrypt_uuid(uid); - let plaintext = group_secret_params.decrypt_uuid(uuid_ciphertext).unwrap(); - assert!(plaintext == uid); - - // Create and receive presentation - let randomness = zkgroup::TEST_ARRAY_32_5; - - let presentation = server_public_params.create_auth_credential_presentation( - randomness, - group_secret_params, - auth_credential, - ); - - c.bench_function("create_auth_credential_presentation", |b| { - b.iter(|| { - server_public_params.create_auth_credential_presentation( - randomness, - group_secret_params, - auth_credential, - ) - }) - }); - - let _presentation_bytes = &bincode::serialize(&presentation).unwrap(); - - //for b in presentation_bytes.iter() { - // print!("0x{:02x}, ", b); - //} - //assert!(AUTH_CREDENTIAL_PRESENTATION_RESULT[..] == presentation_bytes[..]); - - c.bench_function("verify_auth_credential_presentation", |b| { - b.iter(|| { - server_secret_params - .verify_auth_credential_presentation(group_public_params, &presentation) - .unwrap(); - }) - }); -} - -// Copied and modified from tests/integration_tests.rs -pub fn benchmark_integration_profile(c: &mut Criterion) { - // Random UID and issueTime - let _uid = zkgroup::TEST_ARRAY_16; - - // SERVER - let server_secret_params = zkgroup::ServerSecretParams::generate(zkgroup::TEST_ARRAY_32); - let server_public_params = server_secret_params.get_public_params(); - - // CLIENT - let master_key = zkgroup::groups::GroupMasterKey::new(zkgroup::TEST_ARRAY_32_1); - let group_secret_params = - zkgroup::groups::GroupSecretParams::derive_from_master_key(master_key); - let group_public_params = group_secret_params.get_public_params(); - - let uid = zkgroup::TEST_ARRAY_16; - let profile_key = - zkgroup::profiles::ProfileKey::create(zkgroup::common::constants::TEST_ARRAY_32_1); - let profile_key_commitment = profile_key.get_commitment(uid); - - // Create context and request - let randomness = zkgroup::TEST_ARRAY_32_3; - - let context = server_public_params.create_profile_key_credential_request_context( - randomness, - uid, - profile_key, - ); - - c.bench_function("create_profile_key_credential_request_context", |b| { - b.iter(|| { - server_public_params.create_profile_key_credential_request_context( - randomness, - uid, - profile_key, - ) - }) - }); - - let request = context.get_request(); - - // SERVER - - let randomness = zkgroup::TEST_ARRAY_32_4; - let response = server_secret_params - .issue_profile_key_credential(randomness, &request, uid, profile_key_commitment) - .unwrap(); - - c.bench_function("issue_profile_key_credential", |b| { - b.iter(|| { - server_secret_params - .issue_profile_key_credential(randomness, &request, uid, profile_key_commitment) - .unwrap() - }) - }); - - // CLIENT - // Gets stored profile credential - let profile_key_credential = server_public_params - .receive_profile_key_credential(&context, &response) - .unwrap(); - - c.bench_function("receive_profile_key_credential", |b| { - b.iter(|| { - server_public_params - .receive_profile_key_credential(&context, &response) - .unwrap() - }) - }); - - // Create encrypted UID and profile key - let uuid_ciphertext = group_secret_params.encrypt_uuid(uid); - - c.bench_function("encrypt_uuid", |b| { - b.iter(|| group_secret_params.encrypt_uuid(uid)) - }); - - let plaintext = group_secret_params.decrypt_uuid(uuid_ciphertext).unwrap(); - - c.bench_function("decrypt_uuid", |b| { - b.iter(|| group_secret_params.decrypt_uuid(uuid_ciphertext)) - }); - - assert!(plaintext == uid); - - let profile_key_ciphertext = group_secret_params.encrypt_profile_key(profile_key, uid); - - c.bench_function("encrypt_profile_key", |b| { - b.iter(|| group_secret_params.encrypt_profile_key(profile_key, uid)) - }); - - let decrypted_profile_key = group_secret_params - .decrypt_profile_key(profile_key_ciphertext, uid) - .unwrap(); - - c.bench_function("decrypt_profile_key", |b| { - b.iter(|| group_secret_params.decrypt_profile_key(profile_key_ciphertext, uid)) - }); - - assert!(decrypted_profile_key.get_bytes() == profile_key.get_bytes()); - - // Create presentation - let randomness = zkgroup::TEST_ARRAY_32_5; - - let presentation = server_public_params.create_profile_key_credential_presentation( - randomness, - group_secret_params, - profile_key_credential, - ); - - c.bench_function("create_profile_key_credential_presentation", |b| { - b.iter(|| { - server_public_params.create_profile_key_credential_presentation( - randomness, - group_secret_params, - profile_key_credential, - ) - }) - }); - - // SERVER - server_secret_params - .verify_profile_key_credential_presentation(group_public_params, &presentation) - .unwrap(); - - c.bench_function("verify_profile_key_credential_presentation", |b| { - b.iter(|| { - server_secret_params - .verify_profile_key_credential_presentation(group_public_params, &presentation) - }) - }); -} - -criterion_group!( - benches, - benchmark_integration_profile, - benchmark_integration_auth -); -criterion_main!(benches); diff --git a/net/gurk-rs/files/vendor/zkgroup/rustfmt.license-template b/net/gurk-rs/files/vendor/zkgroup/rustfmt.license-template deleted file mode 100644 index ae7596e..0000000 --- a/net/gurk-rs/files/vendor/zkgroup/rustfmt.license-template +++ /dev/null @@ -1,6 +0,0 @@ -// -// Copyright (C) {\d+} Signal Messenger, LLC. -// All rights reserved. -// -// SPDX-License-Identifier: GPL-3.0-only -// diff --git a/net/gurk-rs/files/vendor/zkgroup/rustfmt.toml b/net/gurk-rs/files/vendor/zkgroup/rustfmt.toml deleted file mode 100644 index e34f0d5..0000000 --- a/net/gurk-rs/files/vendor/zkgroup/rustfmt.toml +++ /dev/null @@ -1,12 +0,0 @@ -# -# Copyright (C) 2020 Signal Messenger, LLC. -# All rights reserved. -# -# SPDX-License-Identifier: GPL-3.0-only -# - -unstable_features = true -license_template_path = "rustfmt.license-template" - -ignore = [ -] diff --git a/net/gurk-rs/files/vendor/zkgroup/scripts/format-code b/net/gurk-rs/files/vendor/zkgroup/scripts/format-code deleted file mode 100755 index 18bcc7c..0000000 --- a/net/gurk-rs/files/vendor/zkgroup/scripts/format-code +++ /dev/null @@ -1,7 +0,0 @@ -#!/bin/sh - -# To run, install the nightly toolchain: -# $ rustup toolchain install nightly - -cargo +nightly fmt "$@" -cargo +nightly clippy diff --git a/net/gurk-rs/files/vendor/zkgroup/src/api/auth/auth_credential.rs b/net/gurk-rs/files/vendor/zkgroup/src/api/auth/auth_credential.rs deleted file mode 100644 index 04d6de1..0000000 --- a/net/gurk-rs/files/vendor/zkgroup/src/api/auth/auth_credential.rs +++ /dev/null @@ -1,22 +0,0 @@ -// -// Copyright (C) 2020 Signal Messenger, LLC. -// All rights reserved. -// -// SPDX-License-Identifier: GPL-3.0-only -// - -#![allow(non_snake_case)] - -use crate::api; -use crate::common::simple_types::*; -use crate::crypto; -use serde::{Deserialize, Serialize}; - -#[derive(Copy, Clone, Serialize, Deserialize)] -pub struct AuthCredential { - pub(crate) reserved: ReservedBytes, - pub(crate) credential: crypto::credentials::AuthCredential, - pub(crate) server_public_params: api::ServerPublicParams, - pub(crate) uid: crypto::uid_struct::UidStruct, - pub(crate) redemption_time: RedemptionTime, -} diff --git a/net/gurk-rs/files/vendor/zkgroup/src/api/auth/auth_credential_presentation.rs b/net/gurk-rs/files/vendor/zkgroup/src/api/auth/auth_credential_presentation.rs deleted file mode 100644 index 2b79968..0000000 --- a/net/gurk-rs/files/vendor/zkgroup/src/api/auth/auth_credential_presentation.rs +++ /dev/null @@ -1,34 +0,0 @@ -// -// Copyright (C) 2020 Signal Messenger, LLC. -// All rights reserved. -// -// SPDX-License-Identifier: GPL-3.0-only -// - -#![allow(non_snake_case)] - -use crate::api; -use crate::common::simple_types::*; -use crate::crypto; -use serde::{Deserialize, Serialize}; - -#[derive(Serialize, Deserialize)] -pub struct AuthCredentialPresentation { - pub(crate) reserved: ReservedBytes, - pub(crate) proof: crypto::proofs::AuthCredentialPresentationProof, - pub(crate) ciphertext: crypto::uid_encryption::Ciphertext, - pub(crate) redemption_time: RedemptionTime, -} - -impl AuthCredentialPresentation { - pub fn get_uuid_ciphertext(&self) -> api::groups::UuidCiphertext { - api::groups::UuidCiphertext { - reserved: Default::default(), - ciphertext: self.ciphertext, - } - } - - pub fn get_redemption_time(&self) -> RedemptionTime { - self.redemption_time - } -} diff --git a/net/gurk-rs/files/vendor/zkgroup/src/api/auth/auth_credential_response.rs b/net/gurk-rs/files/vendor/zkgroup/src/api/auth/auth_credential_response.rs deleted file mode 100644 index 70ba84e..0000000 --- a/net/gurk-rs/files/vendor/zkgroup/src/api/auth/auth_credential_response.rs +++ /dev/null @@ -1,19 +0,0 @@ -// -// Copyright (C) 2020 Signal Messenger, LLC. -// All rights reserved. -// -// SPDX-License-Identifier: GPL-3.0-only -// - -#![allow(non_snake_case)] - -use crate::common::simple_types::*; -use crate::crypto; -use serde::{Deserialize, Serialize}; - -#[derive(Serialize, Deserialize)] -pub struct AuthCredentialResponse { - pub(crate) reserved: ReservedBytes, - pub(crate) credential: crypto::credentials::AuthCredential, - pub(crate) proof: crypto::proofs::AuthCredentialIssuanceProof, -} diff --git a/net/gurk-rs/files/vendor/zkgroup/src/api/auth/mod.rs b/net/gurk-rs/files/vendor/zkgroup/src/api/auth/mod.rs deleted file mode 100644 index 8ed6e64..0000000 --- a/net/gurk-rs/files/vendor/zkgroup/src/api/auth/mod.rs +++ /dev/null @@ -1,14 +0,0 @@ -// -// Copyright (C) 2020 Signal Messenger, LLC. -// All rights reserved. -// -// SPDX-License-Identifier: GPL-3.0-only -// - -pub mod auth_credential; -pub mod auth_credential_presentation; -pub mod auth_credential_response; - -pub use auth_credential::AuthCredential; -pub use auth_credential_presentation::AuthCredentialPresentation; -pub use auth_credential_response::AuthCredentialResponse; diff --git a/net/gurk-rs/files/vendor/zkgroup/src/api/groups/group_params.rs b/net/gurk-rs/files/vendor/zkgroup/src/api/groups/group_params.rs deleted file mode 100644 index c0cd2e9..0000000 --- a/net/gurk-rs/files/vendor/zkgroup/src/api/groups/group_params.rs +++ /dev/null @@ -1,318 +0,0 @@ -// -// Copyright (C) 2020 Signal Messenger, LLC. -// All rights reserved. -// -// SPDX-License-Identifier: GPL-3.0-only -// - -#![allow(non_snake_case)] - -use crate::api; -use crate::common::constants::*; -use crate::common::errors::*; -use crate::common::sho::*; -use crate::common::simple_types::*; -use crate::crypto; -use aead::{generic_array::GenericArray, Aead, NewAead}; -use aes_gcm_siv::Aes256GcmSiv; -use serde::{Deserialize, Serialize}; - -#[derive(Copy, Clone, Serialize, Deserialize, Default)] -pub struct GroupMasterKey { - pub(crate) bytes: [u8; GROUP_MASTER_KEY_LEN], -} - -#[derive(Copy, Clone, Serialize, Deserialize)] -pub struct GroupSecretParams { - reserved: ReservedBytes, - master_key: GroupMasterKey, - group_id: GroupIdentifierBytes, - blob_key: AesKeyBytes, - pub(crate) uid_enc_key_pair: crypto::uid_encryption::KeyPair, - pub(crate) profile_key_enc_key_pair: crypto::profile_key_encryption::KeyPair, -} - -#[derive(Copy, Clone, Serialize, Deserialize)] -pub struct GroupPublicParams { - reserved: ReservedBytes, - group_id: GroupIdentifierBytes, - pub(crate) uid_enc_public_key: crypto::uid_encryption::PublicKey, - pub(crate) profile_key_enc_public_key: crypto::profile_key_encryption::PublicKey, -} - -impl GroupMasterKey { - pub fn new(bytes: [u8; GROUP_MASTER_KEY_LEN]) -> Self { - GroupMasterKey { bytes } - } -} - -impl GroupSecretParams { - pub fn generate(randomness: RandomnessBytes) -> Self { - let mut sho = Sho::new( - b"Signal_ZKGroup_20200424_Random_GroupSecretParams_Generate", - &randomness, - ); - let mut master_key: GroupMasterKey = Default::default(); - master_key - .bytes - .copy_from_slice(&sho.squeeze(GROUP_MASTER_KEY_LEN)[..]); - GroupSecretParams::derive_from_master_key(master_key) - } - - pub fn derive_from_master_key(master_key: GroupMasterKey) -> Self { - let mut sho = Sho::new( - b"Signal_ZKGroup_20200424_GroupMasterKey_GroupSecretParams_DeriveFromMasterKey", - &master_key.bytes, - ); - let mut group_id: GroupIdentifierBytes = Default::default(); - let mut blob_key: AesKeyBytes = Default::default(); - group_id.copy_from_slice(&sho.squeeze(GROUP_IDENTIFIER_LEN)[..]); - blob_key.copy_from_slice(&sho.squeeze(AES_KEY_LEN)[..]); - let uid_enc_key_pair = crypto::uid_encryption::KeyPair::derive_from(&mut sho); - let profile_key_enc_key_pair = - crypto::profile_key_encryption::KeyPair::derive_from(&mut sho); - - Self { - reserved: Default::default(), - master_key, - group_id, - blob_key, - uid_enc_key_pair, - profile_key_enc_key_pair, - } - } - - pub fn get_master_key(&self) -> GroupMasterKey { - self.master_key - } - - pub fn get_group_identifier(&self) -> GroupIdentifierBytes { - self.group_id - } - - pub fn get_public_params(&self) -> GroupPublicParams { - GroupPublicParams { - reserved: Default::default(), - uid_enc_public_key: self.uid_enc_key_pair.get_public_key(), - profile_key_enc_public_key: self.profile_key_enc_key_pair.get_public_key(), - group_id: self.group_id, - } - } - - pub fn encrypt_uuid(&self, uid_bytes: UidBytes) -> api::groups::UuidCiphertext { - let uid = crypto::uid_struct::UidStruct::new(uid_bytes); - self.encrypt_uid_struct(uid) - } - - pub fn encrypt_uid_struct( - &self, - uid: crypto::uid_struct::UidStruct, - ) -> api::groups::UuidCiphertext { - let ciphertext = self.uid_enc_key_pair.encrypt(uid); - api::groups::UuidCiphertext { - reserved: Default::default(), - ciphertext, - } - } - - pub fn decrypt_uuid( - &self, - ciphertext: api::groups::UuidCiphertext, - ) -> Result { - let uid = self.uid_enc_key_pair.decrypt(ciphertext.ciphertext)?; - Ok(uid.to_bytes()) - } - - pub fn encrypt_profile_key( - &self, - profile_key: api::profiles::ProfileKey, - uid_bytes: UidBytes, - ) -> api::groups::ProfileKeyCiphertext { - self.encrypt_profile_key_bytes(profile_key.bytes, uid_bytes) - } - - pub fn encrypt_profile_key_bytes( - &self, - profile_key_bytes: ProfileKeyBytes, - uid_bytes: UidBytes, - ) -> api::groups::ProfileKeyCiphertext { - let profile_key = - crypto::profile_key_struct::ProfileKeyStruct::new(profile_key_bytes, uid_bytes); - let ciphertext = self.profile_key_enc_key_pair.encrypt(profile_key); - api::groups::ProfileKeyCiphertext { - reserved: Default::default(), - ciphertext, - } - } - - pub fn decrypt_profile_key( - &self, - ciphertext: api::groups::ProfileKeyCiphertext, - uid_bytes: UidBytes, - ) -> Result { - let profile_key_struct = self - .profile_key_enc_key_pair - .decrypt(ciphertext.ciphertext, uid_bytes)?; - Ok(api::profiles::ProfileKey { - bytes: profile_key_struct.bytes, - }) - } - - pub fn encrypt_blob( - &self, - randomness: RandomnessBytes, - plaintext: &[u8], - ) -> Result, ZkGroupError> { - let mut sho = Sho::new( - b"Signal_ZKGroup_20200424_Random_GroupSecretParams_EncryptBlob", - &randomness, - ); - let nonce_vec = sho.squeeze(AESGCM_NONCE_LEN); - match self.encrypt_blob_aesgcmsiv(&self.blob_key, &nonce_vec[..], plaintext) { - Ok(mut ciphertext_vec) => { - ciphertext_vec.extend(nonce_vec); - ciphertext_vec.extend(&[0u8]); // reserved byte - Ok(ciphertext_vec) - } - Err(e) => Err(e), - } - } - - pub fn decrypt_blob(self, ciphertext: &[u8]) -> Result, ZkGroupError> { - if ciphertext.len() < AESGCM_NONCE_LEN + 1 { - // AESGCM_NONCE_LEN = 12 bytes for IV - return Err(ZkGroupError::DecryptionFailure); - } - let unreserved_len = ciphertext.len() - 1; - let nonce = &ciphertext[unreserved_len - AESGCM_NONCE_LEN..unreserved_len]; - let ciphertext = &ciphertext[..unreserved_len - AESGCM_NONCE_LEN]; - self.decrypt_blob_aesgcmsiv(&self.blob_key, nonce, ciphertext) - } - - fn encrypt_blob_aesgcmsiv( - &self, - key: &[u8], - nonce: &[u8], - plaintext: &[u8], - ) -> Result, ZkGroupError> { - let key = GenericArray::from_slice(key); - let aead_cipher = Aes256GcmSiv::new(&*key); - let nonce = GenericArray::from_slice(nonce); - match aead_cipher.encrypt(nonce, plaintext) { - Ok(ciphertext_vec) => Ok(ciphertext_vec), - Err(_) => Err(ZkGroupError::BadArgs), - } - } - - fn decrypt_blob_aesgcmsiv( - self, - key: &[u8], - nonce: &[u8], - ciphertext: &[u8], - ) -> Result, ZkGroupError> { - if ciphertext.len() < AESGCM_TAG_LEN { - // AESGCM_TAG_LEN = 16 bytes for tag - return Err(ZkGroupError::DecryptionFailure); - } - let key = GenericArray::from_slice(key); - let aead_cipher = Aes256GcmSiv::new(&*key); - let nonce = GenericArray::from_slice(nonce); - match aead_cipher.decrypt(nonce, ciphertext) { - Ok(plaintext_vec) => Ok(plaintext_vec), - Err(_) => Err(ZkGroupError::DecryptionFailure), - } - } -} - -impl GroupPublicParams { - pub fn get_group_identifier(&self) -> GroupIdentifierBytes { - self.group_id - } -} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_aesgcmsiv_vec1() { - // https://tools.ietf.org/html/rfc8452#appendix-C - - let group_secret_params = GroupSecretParams::generate([0u8; RANDOMNESS_LEN]); - - let plaintext_vec = vec![ - 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, - ]; - - let key_vec = vec![ - 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, - ]; - - let nonce_vec = vec![ - 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - ]; - - let ciphertext_vec = vec![ - 0x4a, 0x6a, 0x9d, 0xb4, 0xc8, 0xc6, 0x54, 0x92, 0x01, 0xb9, 0xed, 0xb5, 0x30, 0x06, - 0xcb, 0xa8, 0x21, 0xec, 0x9c, 0xf8, 0x50, 0x94, 0x8a, 0x7c, 0x86, 0xc6, 0x8a, 0xc7, - 0x53, 0x9d, 0x02, 0x7f, 0xe8, 0x19, 0xe6, 0x3a, 0xbc, 0xd0, 0x20, 0xb0, 0x06, 0xa9, - 0x76, 0x39, 0x76, 0x32, 0xeb, 0x5d, - ]; - - let calc_ciphertext = group_secret_params - .encrypt_blob_aesgcmsiv(&key_vec, &nonce_vec, &plaintext_vec) - .unwrap(); - - assert!(calc_ciphertext[..ciphertext_vec.len()] == ciphertext_vec[..]); - - let calc_plaintext = group_secret_params - .decrypt_blob_aesgcmsiv(&key_vec, &nonce_vec, &calc_ciphertext) - .unwrap(); - assert!(calc_plaintext[..] == plaintext_vec[..]); - } - - #[test] - fn test_aesgcmsiv_vec2() { - // https://tools.ietf.org/html/rfc8452#appendix-C - - let group_secret_params = GroupSecretParams::generate([0u8; RANDOMNESS_LEN]); - - let plaintext_vec = vec![ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x4d, 0xb9, 0x23, 0xdc, 0x79, 0x3e, 0xe6, 0x49, 0x7c, 0x76, 0xdc, 0xc0, - 0x3a, 0x98, 0xe1, 0x08, - ]; - - let key_vec = vec![ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, - ]; - - let nonce_vec = vec![ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - ]; - - let ciphertext_vec = vec![ - 0xf3, 0xf8, 0x0f, 0x2c, 0xf0, 0xcb, 0x2d, 0xd9, 0xc5, 0x98, 0x4f, 0xcd, 0xa9, 0x08, - 0x45, 0x6c, 0xc5, 0x37, 0x70, 0x3b, 0x5b, 0xa7, 0x03, 0x24, 0xa6, 0x79, 0x3a, 0x7b, - 0xf2, 0x18, 0xd3, 0xea, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - ]; - - let calc_ciphertext = group_secret_params - .encrypt_blob_aesgcmsiv(&key_vec, &nonce_vec, &plaintext_vec) - .unwrap(); - - assert!(calc_ciphertext[..ciphertext_vec.len()] == ciphertext_vec[..]); - - let calc_plaintext = group_secret_params - .decrypt_blob_aesgcmsiv(&key_vec, &nonce_vec, &calc_ciphertext) - .unwrap(); - assert!(calc_plaintext[..] == plaintext_vec[..]); - } -} diff --git a/net/gurk-rs/files/vendor/zkgroup/src/api/groups/mod.rs b/net/gurk-rs/files/vendor/zkgroup/src/api/groups/mod.rs deleted file mode 100644 index 473116d..0000000 --- a/net/gurk-rs/files/vendor/zkgroup/src/api/groups/mod.rs +++ /dev/null @@ -1,16 +0,0 @@ -// -// Copyright (C) 2020 Signal Messenger, LLC. -// All rights reserved. -// -// SPDX-License-Identifier: GPL-3.0-only -// - -pub mod group_params; -pub mod profile_key_ciphertext; -pub mod uuid_ciphertext; - -pub use group_params::GroupMasterKey; -pub use group_params::GroupPublicParams; -pub use group_params::GroupSecretParams; -pub use profile_key_ciphertext::ProfileKeyCiphertext; -pub use uuid_ciphertext::UuidCiphertext; diff --git a/net/gurk-rs/files/vendor/zkgroup/src/api/groups/profile_key_ciphertext.rs b/net/gurk-rs/files/vendor/zkgroup/src/api/groups/profile_key_ciphertext.rs deleted file mode 100644 index 44128b7..0000000 --- a/net/gurk-rs/files/vendor/zkgroup/src/api/groups/profile_key_ciphertext.rs +++ /dev/null @@ -1,18 +0,0 @@ -// -// Copyright (C) 2020 Signal Messenger, LLC. -// All rights reserved. -// -// SPDX-License-Identifier: GPL-3.0-only -// - -#![allow(non_snake_case)] - -use crate::common::simple_types::*; -use crate::crypto; -use serde::{Deserialize, Serialize}; - -#[derive(Copy, Clone, Default, Serialize, Deserialize, PartialEq)] -pub struct ProfileKeyCiphertext { - pub(crate) reserved: ReservedBytes, - pub(crate) ciphertext: crypto::profile_key_encryption::Ciphertext, -} diff --git a/net/gurk-rs/files/vendor/zkgroup/src/api/groups/uuid_ciphertext.rs b/net/gurk-rs/files/vendor/zkgroup/src/api/groups/uuid_ciphertext.rs deleted file mode 100644 index f04c93c..0000000 --- a/net/gurk-rs/files/vendor/zkgroup/src/api/groups/uuid_ciphertext.rs +++ /dev/null @@ -1,18 +0,0 @@ -// -// Copyright (C) 2020 Signal Messenger, LLC. -// All rights reserved. -// -// SPDX-License-Identifier: GPL-3.0-only -// - -#![allow(non_snake_case)] - -use crate::common::simple_types::*; -use crate::crypto; -use serde::{Deserialize, Serialize}; - -#[derive(Copy, Clone, Default, Serialize, Deserialize, PartialEq)] -pub struct UuidCiphertext { - pub(crate) reserved: ReservedBytes, - pub(crate) ciphertext: crypto::uid_encryption::Ciphertext, -} diff --git a/net/gurk-rs/files/vendor/zkgroup/src/api/mod.rs b/net/gurk-rs/files/vendor/zkgroup/src/api/mod.rs deleted file mode 100644 index 24f71f5..0000000 --- a/net/gurk-rs/files/vendor/zkgroup/src/api/mod.rs +++ /dev/null @@ -1,15 +0,0 @@ -// -// Copyright (C) 2020 Signal Messenger, LLC. -// All rights reserved. -// -// SPDX-License-Identifier: GPL-3.0-only -// - -pub mod auth; -pub mod groups; -pub mod profiles; - -pub mod server_params; - -pub use server_params::ServerPublicParams; -pub use server_params::ServerSecretParams; diff --git a/net/gurk-rs/files/vendor/zkgroup/src/api/profiles/mod.rs b/net/gurk-rs/files/vendor/zkgroup/src/api/profiles/mod.rs deleted file mode 100644 index 36137dd..0000000 --- a/net/gurk-rs/files/vendor/zkgroup/src/api/profiles/mod.rs +++ /dev/null @@ -1,24 +0,0 @@ -// -// Copyright (C) 2020 Signal Messenger, LLC. -// All rights reserved. -// -// SPDX-License-Identifier: GPL-3.0-only -// - -pub mod profile_key; -pub mod profile_key_commitment; -pub mod profile_key_credential; -pub mod profile_key_credential_presentation; -pub mod profile_key_credential_request; -pub mod profile_key_credential_request_context; -pub mod profile_key_credential_response; -pub mod profile_key_version; - -pub use profile_key::ProfileKey; -pub use profile_key_commitment::ProfileKeyCommitment; -pub use profile_key_credential::ProfileKeyCredential; -pub use profile_key_credential_presentation::ProfileKeyCredentialPresentation; -pub use profile_key_credential_request::ProfileKeyCredentialRequest; -pub use profile_key_credential_request_context::ProfileKeyCredentialRequestContext; -pub use profile_key_credential_response::ProfileKeyCredentialResponse; -pub use profile_key_version::ProfileKeyVersion; diff --git a/net/gurk-rs/files/vendor/zkgroup/src/api/profiles/profile_key.rs b/net/gurk-rs/files/vendor/zkgroup/src/api/profiles/profile_key.rs deleted file mode 100644 index f5b82c7..0000000 --- a/net/gurk-rs/files/vendor/zkgroup/src/api/profiles/profile_key.rs +++ /dev/null @@ -1,68 +0,0 @@ -// -// Copyright (C) 2020 Signal Messenger, LLC. -// All rights reserved. -// -// SPDX-License-Identifier: GPL-3.0-only -// - -#![allow(non_snake_case)] - -use crate::api; -use crate::common::constants::*; -use crate::common::sho::*; -use crate::common::simple_types::*; -use crate::crypto; -use serde::{Deserialize, Serialize}; - -#[derive(Copy, Clone, Serialize, Deserialize)] -pub struct ProfileKey { - pub bytes: ProfileKeyBytes, -} - -impl ProfileKey { - pub fn generate(randomness: RandomnessBytes) -> Self { - let mut sho = Sho::new( - b"Signal_ZKGroup_20200424_Random_ProfileKey_Generate", - &randomness, - ); - let mut bytes = [0u8; PROFILE_KEY_LEN]; - bytes.copy_from_slice(&sho.squeeze(PROFILE_KEY_LEN)[..]); - Self { bytes } - } - - pub fn create(bytes: ProfileKeyBytes) -> Self { - Self { bytes } - } - - pub fn get_bytes(&self) -> ProfileKeyBytes { - self.bytes - } - - pub fn get_commitment(&self, uid_bytes: UidBytes) -> api::profiles::ProfileKeyCommitment { - let profile_key = crypto::profile_key_struct::ProfileKeyStruct::new(self.bytes, uid_bytes); - let commitment = - crypto::profile_key_commitment::CommitmentWithSecretNonce::new(profile_key, uid_bytes); - api::profiles::ProfileKeyCommitment { - reserved: Default::default(), - commitment: commitment.get_profile_key_commitment(), - } - } - - pub fn get_profile_key_version(&self, uid_bytes: UidBytes) -> api::profiles::ProfileKeyVersion { - let mut combined_array = [0u8; PROFILE_KEY_LEN + UUID_LEN]; - combined_array[..PROFILE_KEY_LEN].copy_from_slice(&self.bytes); - combined_array[PROFILE_KEY_LEN..].copy_from_slice(&uid_bytes); - let mut sho = Sho::new( - b"Signal_ZKGroup_20200424_ProfileKeyAndUid_ProfileKey_GetProfileKeyVersion", - &combined_array, - ); - - let pkv_hex_string = hex::encode(&sho.squeeze(PROFILE_KEY_VERSION_LEN)[..]); - let mut pkv_hex_array: [u8; PROFILE_KEY_VERSION_ENCODED_LEN] = - [0u8; PROFILE_KEY_VERSION_ENCODED_LEN]; - pkv_hex_array.copy_from_slice(pkv_hex_string.as_bytes()); - api::profiles::ProfileKeyVersion { - bytes: pkv_hex_array, - } - } -} diff --git a/net/gurk-rs/files/vendor/zkgroup/src/api/profiles/profile_key_commitment.rs b/net/gurk-rs/files/vendor/zkgroup/src/api/profiles/profile_key_commitment.rs deleted file mode 100644 index 7eea1cf..0000000 --- a/net/gurk-rs/files/vendor/zkgroup/src/api/profiles/profile_key_commitment.rs +++ /dev/null @@ -1,18 +0,0 @@ -// -// Copyright (C) 2020 Signal Messenger, LLC. -// All rights reserved. -// -// SPDX-License-Identifier: GPL-3.0-only -// - -#![allow(non_snake_case)] - -use crate::common::simple_types::*; -use crate::crypto; -use serde::{Deserialize, Serialize}; - -#[derive(Copy, Clone, Serialize, Deserialize)] -pub struct ProfileKeyCommitment { - pub(crate) reserved: ReservedBytes, - pub(crate) commitment: crypto::profile_key_commitment::Commitment, -} diff --git a/net/gurk-rs/files/vendor/zkgroup/src/api/profiles/profile_key_credential.rs b/net/gurk-rs/files/vendor/zkgroup/src/api/profiles/profile_key_credential.rs deleted file mode 100644 index cb5921b..0000000 --- a/net/gurk-rs/files/vendor/zkgroup/src/api/profiles/profile_key_credential.rs +++ /dev/null @@ -1,20 +0,0 @@ -// -// Copyright (C) 2020 Signal Messenger, LLC. -// All rights reserved. -// -// SPDX-License-Identifier: GPL-3.0-only -// - -#![allow(non_snake_case)] - -use crate::common::simple_types::*; -use crate::crypto; -use serde::{Deserialize, Serialize}; - -#[derive(Copy, Clone, Serialize, Deserialize)] -pub struct ProfileKeyCredential { - pub(crate) reserved: ReservedBytes, - pub(crate) credential: crypto::credentials::ProfileKeyCredential, - pub(crate) uid_bytes: UidBytes, - pub(crate) profile_key_bytes: ProfileKeyBytes, -} diff --git a/net/gurk-rs/files/vendor/zkgroup/src/api/profiles/profile_key_credential_presentation.rs b/net/gurk-rs/files/vendor/zkgroup/src/api/profiles/profile_key_credential_presentation.rs deleted file mode 100644 index 1122dc2..0000000 --- a/net/gurk-rs/files/vendor/zkgroup/src/api/profiles/profile_key_credential_presentation.rs +++ /dev/null @@ -1,37 +0,0 @@ -// -// Copyright (C) 2020 Signal Messenger, LLC. -// All rights reserved. -// -// SPDX-License-Identifier: GPL-3.0-only -// - -#![allow(non_snake_case)] - -use crate::api; -use crate::common::simple_types::*; -use crate::crypto; -use serde::{Deserialize, Serialize}; - -#[derive(Serialize, Deserialize)] -pub struct ProfileKeyCredentialPresentation { - pub(crate) reserved: ReservedBytes, - pub(crate) proof: crypto::proofs::ProfileKeyCredentialPresentationProof, - pub(crate) uid_enc_ciphertext: crypto::uid_encryption::Ciphertext, - pub(crate) profile_key_enc_ciphertext: crypto::profile_key_encryption::Ciphertext, -} - -impl ProfileKeyCredentialPresentation { - pub fn get_uuid_ciphertext(&self) -> api::groups::UuidCiphertext { - api::groups::UuidCiphertext { - reserved: Default::default(), - ciphertext: self.uid_enc_ciphertext, - } - } - - pub fn get_profile_key_ciphertext(&self) -> api::groups::ProfileKeyCiphertext { - api::groups::ProfileKeyCiphertext { - reserved: Default::default(), - ciphertext: self.profile_key_enc_ciphertext, - } - } -} diff --git a/net/gurk-rs/files/vendor/zkgroup/src/api/profiles/profile_key_credential_request.rs b/net/gurk-rs/files/vendor/zkgroup/src/api/profiles/profile_key_credential_request.rs deleted file mode 100644 index a52ecff..0000000 --- a/net/gurk-rs/files/vendor/zkgroup/src/api/profiles/profile_key_credential_request.rs +++ /dev/null @@ -1,20 +0,0 @@ -// -// Copyright (C) 2020 Signal Messenger, LLC. -// All rights reserved. -// -// SPDX-License-Identifier: GPL-3.0-only -// - -#![allow(non_snake_case)] - -use crate::common::simple_types::*; -use crate::crypto; -use serde::{Deserialize, Serialize}; - -#[derive(Serialize, Deserialize)] -pub struct ProfileKeyCredentialRequest { - pub(crate) reserved: ReservedBytes, - pub(crate) public_key: crypto::profile_key_credential_request::PublicKey, - pub(crate) ciphertext: crypto::profile_key_credential_request::Ciphertext, - pub(crate) proof: crypto::proofs::ProfileKeyCredentialRequestProof, -} diff --git a/net/gurk-rs/files/vendor/zkgroup/src/api/profiles/profile_key_credential_request_context.rs b/net/gurk-rs/files/vendor/zkgroup/src/api/profiles/profile_key_credential_request_context.rs deleted file mode 100644 index 8c3d659..0000000 --- a/net/gurk-rs/files/vendor/zkgroup/src/api/profiles/profile_key_credential_request_context.rs +++ /dev/null @@ -1,37 +0,0 @@ -// -// Copyright (C) 2020 Signal Messenger, LLC. -// All rights reserved. -// -// SPDX-License-Identifier: GPL-3.0-only -// - -#![allow(non_snake_case)] - -use crate::api; -use crate::common::simple_types::*; -use crate::crypto; -use serde::{Deserialize, Serialize}; - -#[derive(Serialize, Deserialize)] -pub struct ProfileKeyCredentialRequestContext { - pub(crate) reserved: ReservedBytes, - pub(crate) uid_bytes: UidBytes, - pub(crate) profile_key_bytes: ProfileKeyBytes, - pub(crate) key_pair: crypto::profile_key_credential_request::KeyPair, - pub(crate) ciphertext_with_secret_nonce: - crypto::profile_key_credential_request::CiphertextWithSecretNonce, - pub(crate) proof: crypto::proofs::ProfileKeyCredentialRequestProof, -} - -impl ProfileKeyCredentialRequestContext { - pub fn get_request(&self) -> api::profiles::ProfileKeyCredentialRequest { - let ciphertext = self.ciphertext_with_secret_nonce.get_ciphertext(); - let public_key = self.key_pair.get_public_key(); - api::profiles::ProfileKeyCredentialRequest { - reserved: Default::default(), - public_key, - ciphertext, - proof: self.proof.clone(), - } - } -} diff --git a/net/gurk-rs/files/vendor/zkgroup/src/api/profiles/profile_key_credential_response.rs b/net/gurk-rs/files/vendor/zkgroup/src/api/profiles/profile_key_credential_response.rs deleted file mode 100644 index 9e7a080..0000000 --- a/net/gurk-rs/files/vendor/zkgroup/src/api/profiles/profile_key_credential_response.rs +++ /dev/null @@ -1,19 +0,0 @@ -// -// Copyright (C) 2020 Signal Messenger, LLC. -// All rights reserved. -// -// SPDX-License-Identifier: GPL-3.0-only -// - -#![allow(non_snake_case)] - -use crate::common::simple_types::*; -use crate::crypto; -use serde::{Deserialize, Serialize}; - -#[derive(Serialize, Deserialize)] -pub struct ProfileKeyCredentialResponse { - pub(crate) reserved: ReservedBytes, - pub(crate) blinded_credential: crypto::credentials::BlindedProfileKeyCredential, - pub(crate) proof: crypto::proofs::ProfileKeyCredentialIssuanceProof, -} diff --git a/net/gurk-rs/files/vendor/zkgroup/src/api/profiles/profile_key_version.rs b/net/gurk-rs/files/vendor/zkgroup/src/api/profiles/profile_key_version.rs deleted file mode 100644 index 9b5fc2f..0000000 --- a/net/gurk-rs/files/vendor/zkgroup/src/api/profiles/profile_key_version.rs +++ /dev/null @@ -1,30 +0,0 @@ -// -// Copyright (C) 2020 Signal Messenger, LLC. -// All rights reserved. -// -// SPDX-License-Identifier: GPL-3.0-only -// - -#![allow(non_snake_case)] - -use crate::common::simple_types::*; -use serde::ser::SerializeTuple; -use serde::{Serialize, Serializer}; - -#[derive(Copy, Clone)] -pub struct ProfileKeyVersion { - pub(crate) bytes: ProfileKeyVersionEncodedBytes, -} - -impl Serialize for ProfileKeyVersion { - fn serialize(&self, serializer: S) -> Result - where - S: Serializer, - { - let mut seq = serializer.serialize_tuple(self.bytes.len()).unwrap(); - for b in self.bytes.iter() { - seq.serialize_element(b)?; - } - seq.end() - } -} diff --git a/net/gurk-rs/files/vendor/zkgroup/src/api/server_params.rs b/net/gurk-rs/files/vendor/zkgroup/src/api/server_params.rs deleted file mode 100644 index 047aca6..0000000 --- a/net/gurk-rs/files/vendor/zkgroup/src/api/server_params.rs +++ /dev/null @@ -1,351 +0,0 @@ -// -// Copyright (C) 2020 Signal Messenger, LLC. -// All rights reserved. -// -// SPDX-License-Identifier: GPL-3.0-only -// - -#![allow(non_snake_case)] - -use crate::api; -use crate::common::constants::*; -use crate::common::errors::*; -use crate::common::sho::*; -use crate::common::simple_types::*; -use crate::crypto; -use serde::{Deserialize, Serialize}; - -#[derive(Copy, Clone, Serialize, Deserialize)] -pub struct ServerSecretParams { - pub(crate) reserved: ReservedBytes, - pub(crate) auth_credentials_key_pair: crypto::credentials::KeyPair, - pub(crate) profile_key_credentials_key_pair: crypto::credentials::KeyPair, - sig_key_pair: crypto::signature::KeyPair, -} - -#[derive(Copy, Clone, Serialize, Deserialize)] -pub struct ServerPublicParams { - pub(crate) reserved: ReservedBytes, - pub(crate) auth_credentials_public_key: crypto::credentials::PublicKey, - pub(crate) profile_key_credentials_public_key: crypto::credentials::PublicKey, - sig_public_key: crypto::signature::PublicKey, -} - -impl ServerSecretParams { - pub fn generate(randomness: RandomnessBytes) -> Self { - let mut sho = Sho::new( - b"Signal_ZKGroup_20200424_Random_ServerSecretParams_Generate", - &randomness, - ); - - let auth_credentials_key_pair = - crypto::credentials::KeyPair::generate(&mut sho, NUM_AUTH_CRED_ATTRIBUTES); - let profile_key_credentials_key_pair = - crypto::credentials::KeyPair::generate(&mut sho, NUM_PROFILE_KEY_CRED_ATTRIBUTES); - let sig_key_pair = crypto::signature::KeyPair::generate(&mut sho); - - Self { - reserved: Default::default(), - auth_credentials_key_pair, - profile_key_credentials_key_pair, - sig_key_pair, - } - } - - pub fn get_public_params(&self) -> ServerPublicParams { - ServerPublicParams { - reserved: Default::default(), - auth_credentials_public_key: self.auth_credentials_key_pair.get_public_key(), - profile_key_credentials_public_key: self - .profile_key_credentials_key_pair - .get_public_key(), - sig_public_key: self.sig_key_pair.get_public_key(), - } - } - - pub fn sign( - &self, - randomness: RandomnessBytes, - message: &[u8], - ) -> Result { - let mut sho = Sho::new( - b"Signal_ZKGroup_20200424_Random_ServerSecretParams_Sign", - &randomness, - ); - self.sig_key_pair.sign(message, &mut sho) - } - - pub fn issue_auth_credential( - &self, - randomness: RandomnessBytes, - uid_bytes: UidBytes, - redemption_time: RedemptionTime, - ) -> api::auth::AuthCredentialResponse { - let mut sho = Sho::new( - b"Signal_ZKGroup_20200424_Random_ServerSecretParams_IssueAuthCredential", - &randomness, - ); - - let uid = crypto::uid_struct::UidStruct::new(uid_bytes); - let credential = - self.auth_credentials_key_pair - .create_auth_credential(uid, redemption_time, &mut sho); - let proof = crypto::proofs::AuthCredentialIssuanceProof::new( - self.auth_credentials_key_pair, - credential, - uid, - redemption_time, - &mut sho, - ); - api::auth::AuthCredentialResponse { - reserved: Default::default(), - credential, - proof, - } - } - - pub fn verify_auth_credential_presentation( - &self, - group_public_params: api::groups::GroupPublicParams, - presentation: &api::auth::AuthCredentialPresentation, - ) -> Result<(), ZkGroupError> { - presentation.proof.verify( - self.auth_credentials_key_pair, - group_public_params.uid_enc_public_key, - presentation.ciphertext, - presentation.redemption_time, - ) - } - - pub fn verify_profile_key_credential_presentation( - &self, - group_public_params: api::groups::GroupPublicParams, - presentation: &api::profiles::ProfileKeyCredentialPresentation, - ) -> Result<(), ZkGroupError> { - let credentials_key_pair = self.profile_key_credentials_key_pair; - let uid_enc_public_key = group_public_params.uid_enc_public_key; - let profile_key_enc_public_key = group_public_params.profile_key_enc_public_key; - - presentation.proof.verify( - credentials_key_pair, - presentation.uid_enc_ciphertext, - uid_enc_public_key, - presentation.profile_key_enc_ciphertext, - profile_key_enc_public_key, - ) - } - - pub fn issue_profile_key_credential( - &self, - randomness: RandomnessBytes, - request: &api::profiles::ProfileKeyCredentialRequest, - uid_bytes: UidBytes, - commitment: api::profiles::ProfileKeyCommitment, - ) -> Result { - let mut sho = Sho::new( - b"Signal_ZKGroup_20200424_Random_ServerSecretParams_IssueProfileKeyCredential", - &randomness, - ); - - request.proof.verify( - request.public_key, - request.ciphertext, - commitment.commitment, - )?; - - let uid = crypto::uid_struct::UidStruct::new(uid_bytes); - let blinded_credential_with_secret_nonce = self - .profile_key_credentials_key_pair - .create_blinded_profile_key_credential( - uid, - request.public_key, - request.ciphertext, - &mut sho, - ); - - let proof = crypto::proofs::ProfileKeyCredentialIssuanceProof::new( - self.profile_key_credentials_key_pair, - request.public_key, - request.ciphertext, - blinded_credential_with_secret_nonce, - uid, - &mut sho, - ); - - Ok(api::profiles::ProfileKeyCredentialResponse { - reserved: Default::default(), - blinded_credential: blinded_credential_with_secret_nonce - .get_blinded_profile_key_credential(), - proof, - }) - } -} - -impl ServerPublicParams { - pub fn verify_signature( - &self, - message: &[u8], - signature: NotarySignatureBytes, - ) -> Result<(), ZkGroupError> { - self.sig_public_key.verify(message, signature) - } - - pub fn receive_auth_credential( - &self, - uid_bytes: UidBytes, - redemption_time: RedemptionTime, - response: &api::auth::AuthCredentialResponse, - ) -> Result { - let uid = crypto::uid_struct::UidStruct::new(uid_bytes); - response.proof.verify( - self.auth_credentials_public_key, - response.credential, - uid, - redemption_time, - )?; - - Ok(api::auth::AuthCredential { - reserved: Default::default(), - credential: response.credential, - server_public_params: *self, - uid, - redemption_time, - }) - } - - pub fn create_auth_credential_presentation( - &self, - randomness: RandomnessBytes, - group_secret_params: api::groups::GroupSecretParams, - auth_credential: api::auth::AuthCredential, - ) -> api::auth::AuthCredentialPresentation { - let mut sho = Sho::new( - b"Signal_ZKGroup_20200424_Random_ServerPublicParams_CreateAuthCredentialPresentation", - &randomness, - ); - - let uuid_ciphertext = group_secret_params.encrypt_uid_struct(auth_credential.uid); - - let proof = crypto::proofs::AuthCredentialPresentationProof::new( - self.auth_credentials_public_key, - group_secret_params.uid_enc_key_pair, - auth_credential.credential, - auth_credential.uid, - uuid_ciphertext.ciphertext, - auth_credential.redemption_time, - &mut sho, - ); - - api::auth::AuthCredentialPresentation { - reserved: Default::default(), - proof, - ciphertext: uuid_ciphertext.ciphertext, - redemption_time: auth_credential.redemption_time, - } - } - - pub fn create_profile_key_credential_request_context( - &self, - randomness: RandomnessBytes, - uid_bytes: UidBytes, - profile_key: api::profiles::ProfileKey, - ) -> api::profiles::ProfileKeyCredentialRequestContext { - let mut sho = Sho::new( - b"Signal_ZKGroup_20200424_Random_ServerPublicParams_CreateProfileKeyCredentialRequestContext", - &randomness, - ); - let profile_key_struct = - crypto::profile_key_struct::ProfileKeyStruct::new(profile_key.bytes, uid_bytes); - - let commitment_with_secret_nonce = - crypto::profile_key_commitment::CommitmentWithSecretNonce::new( - profile_key_struct, - uid_bytes, - ); - - let key_pair = crypto::profile_key_credential_request::KeyPair::generate(&mut sho); - let ciphertext_with_secret_nonce = key_pair.encrypt(profile_key_struct, &mut sho); - - let proof = crypto::proofs::ProfileKeyCredentialRequestProof::new( - key_pair, - ciphertext_with_secret_nonce, - commitment_with_secret_nonce, - &mut sho, - ); - - api::profiles::ProfileKeyCredentialRequestContext { - reserved: Default::default(), - uid_bytes, - profile_key_bytes: profile_key_struct.bytes, - key_pair, - ciphertext_with_secret_nonce, - proof, - } - } - - pub fn receive_profile_key_credential( - &self, - context: &api::profiles::ProfileKeyCredentialRequestContext, - response: &api::profiles::ProfileKeyCredentialResponse, - ) -> Result { - response.proof.verify( - self.profile_key_credentials_public_key, - context.key_pair.get_public_key(), - context.uid_bytes, - context.ciphertext_with_secret_nonce.get_ciphertext(), - response.blinded_credential, - )?; - - let credential = context - .key_pair - .decrypt_blinded_profile_key_credential(response.blinded_credential); - - Ok(api::profiles::ProfileKeyCredential { - reserved: Default::default(), - credential, - uid_bytes: context.uid_bytes, - profile_key_bytes: context.profile_key_bytes, - }) - } - - pub fn create_profile_key_credential_presentation( - &self, - randomness: RandomnessBytes, - group_secret_params: api::groups::GroupSecretParams, - profile_key_credential: api::profiles::ProfileKeyCredential, - ) -> api::profiles::ProfileKeyCredentialPresentation { - let mut sho = Sho::new( - b"Signal_ZKGroup_20200424_Random_ServerPublicParams_CreateProfileKeyCredentialPresentation", - &randomness, - ); - - let uid_enc_key_pair = group_secret_params.uid_enc_key_pair; - let profile_key_enc_key_pair = group_secret_params.profile_key_enc_key_pair; - let credentials_public_key = self.profile_key_credentials_public_key; - - let uuid_ciphertext = group_secret_params.encrypt_uuid(profile_key_credential.uid_bytes); - let profile_key_ciphertext = group_secret_params.encrypt_profile_key_bytes( - profile_key_credential.profile_key_bytes, - profile_key_credential.uid_bytes, - ); - - let proof = crypto::proofs::ProfileKeyCredentialPresentationProof::new( - uid_enc_key_pair, - profile_key_enc_key_pair, - credentials_public_key, - profile_key_credential.credential, - uuid_ciphertext.ciphertext, - profile_key_ciphertext.ciphertext, - profile_key_credential.uid_bytes, - profile_key_credential.profile_key_bytes, - &mut sho, - ); - - api::profiles::ProfileKeyCredentialPresentation { - reserved: Default::default(), - proof, - uid_enc_ciphertext: uuid_ciphertext.ciphertext, - profile_key_enc_ciphertext: profile_key_ciphertext.ciphertext, - } - } -} diff --git a/net/gurk-rs/files/vendor/zkgroup/src/common/constants.rs b/net/gurk-rs/files/vendor/zkgroup/src/common/constants.rs deleted file mode 100644 index cc2990c..0000000 --- a/net/gurk-rs/files/vendor/zkgroup/src/common/constants.rs +++ /dev/null @@ -1,75 +0,0 @@ -// -// Copyright (C) 2020 Signal Messenger, LLC. -// All rights reserved. -// -// SPDX-License-Identifier: GPL-3.0-only -// - -#![allow(non_snake_case)] - -pub const NUM_AUTH_CRED_ATTRIBUTES: usize = 3; -pub const NUM_PROFILE_KEY_CRED_ATTRIBUTES: usize = 4; - -pub const AES_KEY_LEN: usize = 32; -pub const AESGCM_NONCE_LEN: usize = 12; -pub const AESGCM_TAG_LEN: usize = 16; -pub const GROUP_MASTER_KEY_LEN: usize = 32; -pub const GROUP_SECRET_PARAMS_LEN: usize = 289; -pub const GROUP_PUBLIC_PARAMS_LEN: usize = 97; -pub const GROUP_IDENTIFIER_LEN: usize = 32; -pub const AUTH_CREDENTIAL_LEN: usize = 342; -pub const AUTH_CREDENTIAL_PRESENTATION_LEN: usize = 493; -pub const AUTH_CREDENTIAL_RESPONSE_LEN: usize = 361; -pub const PROFILE_KEY_LEN: usize = 32; -pub const PROFILE_KEY_CIPHERTEXT_LEN: usize = 65; -pub const PROFILE_KEY_COMMITMENT_LEN: usize = 97; -pub const PROFILE_KEY_CREDENTIAL_LEN: usize = 145; -pub const PROFILE_KEY_CREDENTIAL_PRESENTATION_LEN: usize = 713; -pub const PROFILE_KEY_CREDENTIAL_REQUEST_LEN: usize = 329; -pub const PROFILE_KEY_CREDENTIAL_REQUEST_CONTEXT_LEN: usize = 473; -pub const PROFILE_KEY_CREDENTIAL_RESPONSE_LEN: usize = 457; -pub const PROFILE_KEY_VERSION_LEN: usize = 32; -pub const PROFILE_KEY_VERSION_ENCODED_LEN: usize = 64; -pub const RESERVED_LEN: usize = 1; -pub const SERVER_SECRET_PARAMS_LEN: usize = 769; -pub const SERVER_PUBLIC_PARAMS_LEN: usize = 161; -pub const UUID_CIPHERTEXT_LEN: usize = 65; -pub const RANDOMNESS_LEN: usize = 32; -pub const SIGNATURE_LEN: usize = 64; -pub const UUID_LEN: usize = 16; - -pub const TEST_ARRAY_16: [u8; 16] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]; - -pub const TEST_ARRAY_16_1: [u8; 16] = [ - 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, -]; - -pub const TEST_ARRAY_32: [u8; 32] = [ - 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, - 26, 27, 28, 29, 30, 31, -]; - -pub const TEST_ARRAY_32_1: [u8; 32] = [ - 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, - 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, -]; - -pub const TEST_ARRAY_32_2: [u8; 32] = [ - 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, - 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, -]; - -pub const TEST_ARRAY_32_3: [u8; 32] = [ - 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, - 27, 28, 29, 30, 31, 32, -]; - -pub const TEST_ARRAY_32_4: [u8; 32] = [ - 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, - 28, 29, 30, 31, 32, 33, -]; - -pub const TEST_ARRAY_32_5: [u8; 32] = [ - 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, - 28, 29, 30, 31, 32, 33, 34, -]; diff --git a/net/gurk-rs/files/vendor/zkgroup/src/common/errors.rs b/net/gurk-rs/files/vendor/zkgroup/src/common/errors.rs deleted file mode 100644 index 86bdc1c..0000000 --- a/net/gurk-rs/files/vendor/zkgroup/src/common/errors.rs +++ /dev/null @@ -1,16 +0,0 @@ -// -// Copyright (C) 2020 Signal Messenger, LLC. -// All rights reserved. -// -// SPDX-License-Identifier: GPL-3.0-only -// - -#[derive(Debug)] -pub enum ZkGroupError { - BadArgs, // Bad arguments were passed to the function - DecryptionFailure, // Decryption failed - MacVerificationFailure, // MAC verification failed - ProofVerificationFailure, // Proof verification failed - SignatureVerificationFailure, // Signature verification failed - PointDecodeFailure, // Lizard failed to decode; CAN HAPPEN -} diff --git a/net/gurk-rs/files/vendor/zkgroup/src/common/mod.rs b/net/gurk-rs/files/vendor/zkgroup/src/common/mod.rs deleted file mode 100644 index 7d2e1dc..0000000 --- a/net/gurk-rs/files/vendor/zkgroup/src/common/mod.rs +++ /dev/null @@ -1,11 +0,0 @@ -// -// Copyright (C) 2020 Signal Messenger, LLC. -// All rights reserved. -// -// SPDX-License-Identifier: GPL-3.0-only -// - -pub mod constants; -pub mod errors; -pub mod sho; -pub mod simple_types; diff --git a/net/gurk-rs/files/vendor/zkgroup/src/common/sho.rs b/net/gurk-rs/files/vendor/zkgroup/src/common/sho.rs deleted file mode 100644 index 6f352c0..0000000 --- a/net/gurk-rs/files/vendor/zkgroup/src/common/sho.rs +++ /dev/null @@ -1,44 +0,0 @@ -// -// Copyright (C) 2020 Signal Messenger, LLC. -// All rights reserved. -// -// SPDX-License-Identifier: GPL-3.0-only -// - -use curve25519_dalek::ristretto::RistrettoPoint; -use curve25519_dalek::scalar::Scalar; -use poksho::ShoApi; - -pub struct Sho { - internal_sho: poksho::ShoHmacSha256, -} - -impl Sho { - pub fn new(label: &[u8], data: &[u8]) -> Self { - let mut sho = poksho::ShoHmacSha256::new(label); - sho.absorb_and_ratchet(data); - Sho { internal_sho: sho } - } - - pub fn squeeze(&mut self, outlen: usize) -> Vec { - self.internal_sho.squeeze_and_ratchet(outlen) - } - - pub fn get_point(&mut self) -> RistrettoPoint { - let mut point_bytes = [0u8; 64]; - point_bytes.copy_from_slice(&self.internal_sho.squeeze_and_ratchet(64)[..]); - RistrettoPoint::from_uniform_bytes(&point_bytes) - } - - pub fn get_point_single_elligator(&mut self) -> RistrettoPoint { - let mut point_bytes = [0u8; 32]; - point_bytes.copy_from_slice(&self.internal_sho.squeeze_and_ratchet(32)[..]); - RistrettoPoint::from_uniform_bytes_single_elligator(&point_bytes) - } - - pub fn get_scalar(&mut self) -> Scalar { - let mut scalar_bytes = [0u8; 64]; - scalar_bytes.copy_from_slice(&self.internal_sho.squeeze_and_ratchet(64)[..]); - Scalar::from_bytes_mod_order_wide(&scalar_bytes) - } -} diff --git a/net/gurk-rs/files/vendor/zkgroup/src/common/simple_types.rs b/net/gurk-rs/files/vendor/zkgroup/src/common/simple_types.rs deleted file mode 100644 index a2af34d..0000000 --- a/net/gurk-rs/files/vendor/zkgroup/src/common/simple_types.rs +++ /dev/null @@ -1,37 +0,0 @@ -// -// Copyright (C) 2020 Signal Messenger, LLC. -// All rights reserved. -// -// SPDX-License-Identifier: GPL-3.0-only -// - -use crate::common::constants::*; -use curve25519_dalek::scalar::Scalar; - -pub type AesKeyBytes = [u8; AES_KEY_LEN]; -pub type GroupMasterKeyBytes = [u8; GROUP_MASTER_KEY_LEN]; -pub type UidBytes = [u8; UUID_LEN]; -pub type ProfileKeyBytes = [u8; PROFILE_KEY_LEN]; -pub type RandomnessBytes = [u8; RANDOMNESS_LEN]; -pub type ReservedBytes = [u8; RESERVED_LEN]; -pub type SignatureBytes = [u8; SIGNATURE_LEN]; -pub type NotarySignatureBytes = [u8; SIGNATURE_LEN]; -pub type GroupIdentifierBytes = [u8; GROUP_IDENTIFIER_LEN]; -pub type ProfileKeyVersionBytes = [u8; PROFILE_KEY_VERSION_LEN]; -pub type ProfileKeyVersionEncodedBytes = [u8; PROFILE_KEY_VERSION_ENCODED_LEN]; -pub type RedemptionTime = u32; - -pub fn encode_redemption_time(redemption_time: u32) -> Scalar { - let mut scalar_bytes: [u8; 32] = Default::default(); - scalar_bytes[0..4].copy_from_slice(&redemption_time.to_be_bytes()); - Scalar::from_bytes_mod_order(scalar_bytes) -} - -#[test] -fn test_encode_scalar() { - let s_bytes = [0xFF; 32]; - match bincode::deserialize::(&s_bytes) { - Err(_) => (), - Ok(_) => unreachable!(), - } -} diff --git a/net/gurk-rs/files/vendor/zkgroup/src/crypto/credentials.rs b/net/gurk-rs/files/vendor/zkgroup/src/crypto/credentials.rs deleted file mode 100644 index 0469c9b..0000000 --- a/net/gurk-rs/files/vendor/zkgroup/src/crypto/credentials.rs +++ /dev/null @@ -1,363 +0,0 @@ -// -// Copyright (C) 2020 Signal Messenger, LLC. -// All rights reserved. -// -// SPDX-License-Identifier: GPL-3.0-only -// - -#![allow(non_snake_case)] - -use crate::common::sho::*; -use crate::common::simple_types::*; -use crate::crypto::profile_key_credential_request; -use crate::crypto::uid_struct; -use curve25519_dalek::constants::RISTRETTO_BASEPOINT_POINT; -use curve25519_dalek::ristretto::RistrettoPoint; -use curve25519_dalek::scalar::Scalar; -use serde::{Deserialize, Serialize}; - -#[derive(Copy, Clone, Default, PartialEq, Serialize, Deserialize)] -pub struct SystemParams { - pub(crate) G_w: RistrettoPoint, - pub(crate) G_wprime: RistrettoPoint, - pub(crate) G_x0: RistrettoPoint, - pub(crate) G_x1: RistrettoPoint, - pub(crate) G_y1: RistrettoPoint, - pub(crate) G_y2: RistrettoPoint, - pub(crate) G_y3: RistrettoPoint, - pub(crate) G_y4: RistrettoPoint, - pub(crate) G_m1: RistrettoPoint, - pub(crate) G_m2: RistrettoPoint, - pub(crate) G_m3: RistrettoPoint, - pub(crate) G_m4: RistrettoPoint, - pub(crate) G_V: RistrettoPoint, - pub(crate) G_z: RistrettoPoint, -} - -#[derive(Copy, Clone, PartialEq, Serialize, Deserialize)] -pub struct KeyPair { - // private - pub(crate) w: Scalar, - pub(crate) wprime: Scalar, - pub(crate) W: RistrettoPoint, - pub(crate) x0: Scalar, - pub(crate) x1: Scalar, - pub(crate) y1: Scalar, - pub(crate) y2: Scalar, - pub(crate) y3: Scalar, - pub(crate) y4: Scalar, - - // public - pub(crate) C_W: RistrettoPoint, - pub(crate) I: RistrettoPoint, -} - -#[derive(Copy, Clone, PartialEq, Serialize, Deserialize)] -pub struct PublicKey { - pub(crate) C_W: RistrettoPoint, - pub(crate) I: RistrettoPoint, -} - -#[derive(Copy, Clone, PartialEq, Serialize, Deserialize)] -pub struct AuthCredential { - pub(crate) t: Scalar, - pub(crate) U: RistrettoPoint, - pub(crate) V: RistrettoPoint, -} - -#[derive(Copy, Clone, PartialEq, Serialize, Deserialize)] -pub struct ProfileKeyCredential { - pub(crate) t: Scalar, - pub(crate) U: RistrettoPoint, - pub(crate) V: RistrettoPoint, -} - -#[derive(Copy, Clone, PartialEq, Serialize, Deserialize)] -pub struct BlindedProfileKeyCredentialWithSecretNonce { - pub(crate) rprime: Scalar, - pub(crate) t: Scalar, - pub(crate) U: RistrettoPoint, - pub(crate) S1: RistrettoPoint, - pub(crate) S2: RistrettoPoint, -} - -#[derive(Copy, Clone, PartialEq, Serialize, Deserialize)] -pub struct BlindedProfileKeyCredential { - pub(crate) t: Scalar, - pub(crate) U: RistrettoPoint, - pub(crate) S1: RistrettoPoint, - pub(crate) S2: RistrettoPoint, -} - -pub(crate) fn convert_to_points_uid_struct( - uid: uid_struct::UidStruct, - redemption_time: RedemptionTime, -) -> Vec { - let system = SystemParams::get_hardcoded(); - let redemption_time_scalar = encode_redemption_time(redemption_time); - vec![uid.M1, uid.M2, redemption_time_scalar * system.G_m3] -} - -impl SystemParams { - pub fn generate() -> Self { - let mut sho = Sho::new( - b"Signal_ZKGroup_20200424_Constant_Credentials_SystemParams_Generate", - b"", - ); - let G_w = sho.get_point(); - let G_wprime = sho.get_point(); - - let G_x0 = sho.get_point(); - let G_x1 = sho.get_point(); - - let G_y1 = sho.get_point(); - let G_y2 = sho.get_point(); - let G_y3 = sho.get_point(); - let G_y4 = sho.get_point(); - - let G_m1 = sho.get_point(); - let G_m2 = sho.get_point(); - let G_m3 = sho.get_point(); - let G_m4 = sho.get_point(); - - let G_V = sho.get_point(); - let G_z = sho.get_point(); - - SystemParams { - G_w, - G_wprime, - G_x0, - G_x1, - G_y1, - G_y2, - G_y3, - G_y4, - G_m1, - G_m2, - G_m3, - G_m4, - G_V, - G_z, - } - } - - pub fn get_hardcoded() -> SystemParams { - bincode::deserialize::(&SystemParams::SYSTEM_HARDCODED).unwrap() - } - - const SYSTEM_HARDCODED: [u8; 448] = [ - 0x9a, 0xe7, 0xc8, 0xe5, 0xed, 0x77, 0x9b, 0x11, 0x4a, 0xe7, 0x70, 0x8a, 0xa2, 0xf7, 0x94, - 0x67, 0xa, 0xdd, 0xa3, 0x24, 0x98, 0x7b, 0x65, 0x99, 0x13, 0x12, 0x2c, 0x35, 0x50, 0x5b, - 0x10, 0x5e, 0x6c, 0xa3, 0x10, 0x25, 0xd2, 0xd7, 0x6b, 0xe7, 0xfd, 0x34, 0x94, 0x4f, 0x98, - 0xf7, 0xfa, 0xe, 0x37, 0xba, 0xbb, 0x2c, 0x8b, 0x98, 0xbb, 0xbd, 0xbd, 0x3d, 0xd1, 0xbf, - 0x13, 0xc, 0xca, 0x2c, 0x8a, 0x9a, 0x3b, 0xdf, 0xaa, 0xa2, 0xb6, 0xb3, 0x22, 0xd4, 0x6b, - 0x93, 0xec, 0xa7, 0xb0, 0xd5, 0x1c, 0x86, 0xa3, 0xc8, 0x39, 0xe1, 0x14, 0x66, 0x35, 0x82, - 0x58, 0xa6, 0xc1, 0xc, 0x57, 0x7f, 0xc2, 0xbf, 0xfd, 0x34, 0xcd, 0x99, 0x16, 0x4c, 0x9a, - 0x6c, 0xd2, 0x9f, 0xab, 0x55, 0xd9, 0x1f, 0xf9, 0x26, 0x93, 0x22, 0xec, 0x34, 0x58, 0x60, - 0x3c, 0xc9, 0x6a, 0xd, 0x47, 0xf7, 0x4, 0x5, 0x82, 0x88, 0xf6, 0x2e, 0xe0, 0xac, 0xed, - 0xb8, 0xaa, 0x23, 0x24, 0x21, 0x21, 0xd9, 0x89, 0x65, 0xa9, 0xbb, 0x29, 0x91, 0x25, 0xc, - 0x11, 0x75, 0x80, 0x95, 0xec, 0xe0, 0xfd, 0x2b, 0x33, 0x28, 0x52, 0x86, 0xfe, 0x1f, 0xcb, - 0x5, 0x61, 0x3, 0xb6, 0x8, 0x17, 0x44, 0xb9, 0x75, 0xf5, 0x50, 0xd0, 0x85, 0x21, 0x56, - 0x8d, 0xd3, 0xd8, 0x61, 0x8f, 0x25, 0xc1, 0x40, 0x37, 0x5a, 0xf, 0x40, 0x24, 0xc3, 0xaa, - 0x23, 0xbd, 0xff, 0xfb, 0x27, 0xfb, 0xd9, 0x82, 0x20, 0x8d, 0x3e, 0xcd, 0x1f, 0xd3, 0xbc, - 0xb7, 0xac, 0xc, 0x3a, 0x14, 0xb1, 0x9, 0x80, 0x4f, 0xc7, 0x48, 0xd7, 0xfa, 0x45, 0x6c, - 0xff, 0xb4, 0x93, 0x4f, 0x98, 0xb, 0x6e, 0x9, 0xa2, 0x48, 0xa6, 0xf, 0x44, 0xa6, 0x15, 0xa, - 0xe6, 0xc1, 0x3d, 0x7e, 0x3c, 0x6, 0x26, 0x1d, 0x7e, 0x4e, 0xed, 0x37, 0xf3, 0x9f, 0x60, - 0xcc, 0x60, 0x37, 0xdc, 0x31, 0xc2, 0xe8, 0xd4, 0x47, 0x4f, 0xb5, 0x19, 0x58, 0x7a, 0x44, - 0x86, 0x93, 0x18, 0x2a, 0xd9, 0xd6, 0xd8, 0x6b, 0x53, 0x59, 0x57, 0x85, 0x8f, 0x54, 0x7b, - 0x93, 0x40, 0x12, 0x7d, 0xa7, 0x5f, 0x80, 0x74, 0xca, 0xee, 0x94, 0x4a, 0xc3, 0x6c, 0xa, - 0xc6, 0x62, 0xd3, 0x8c, 0x9b, 0x3c, 0xcc, 0xe0, 0x3a, 0x9, 0x3f, 0xcd, 0x96, 0x44, 0x4, - 0x73, 0x98, 0xb8, 0x6b, 0x6e, 0x83, 0x37, 0x2f, 0xf1, 0x4f, 0xb8, 0xbb, 0xd, 0xea, 0x65, - 0x53, 0x12, 0x52, 0xac, 0x70, 0xd5, 0x8a, 0x4a, 0x8, 0x10, 0xd6, 0x82, 0xa0, 0xe7, 0x9, - 0xc9, 0x22, 0x7b, 0x30, 0xef, 0x6c, 0x8e, 0x17, 0xc5, 0x91, 0x5d, 0x52, 0x72, 0x21, 0xbb, - 0x0, 0xda, 0x81, 0x75, 0xcd, 0x64, 0x89, 0xaa, 0x8a, 0xa4, 0x92, 0xa5, 0x0, 0xf9, 0xab, - 0xee, 0x56, 0x90, 0xb9, 0xdf, 0xca, 0x88, 0x55, 0x4, 0xb6, 0x16, 0xc7, 0x6, 0xc8, 0xc, - 0x75, 0x6c, 0x11, 0xa3, 0x1, 0x6b, 0xbf, 0xb6, 0x9, 0x77, 0xf4, 0x64, 0x8b, 0x5f, 0x23, - 0x95, 0xa4, 0xb4, 0x28, 0xb7, 0x21, 0x19, 0x40, 0x81, 0x3e, 0x3a, 0xfd, 0xe2, 0xb8, 0x7a, - 0xa9, 0xc2, 0xc3, 0x7b, 0xf7, 0x16, 0xe2, 0x57, 0x8f, 0x95, 0x65, 0x6d, 0xf1, 0x2c, 0x2f, - 0xb6, 0xf5, 0xd0, 0x63, 0x1f, 0x6f, 0x71, 0xe2, 0xc3, 0x19, 0x3f, 0x6d, - ]; -} - -impl KeyPair { - pub fn generate(sho: &mut Sho, num_attributes: usize) -> Self { - if !(3..=4).contains(&num_attributes) { - panic!(); - } - - let system = SystemParams::get_hardcoded(); - let w = sho.get_scalar(); - let W = w * system.G_w; - let wprime = sho.get_scalar(); - let x0 = sho.get_scalar(); - let x1 = sho.get_scalar(); - let y1 = sho.get_scalar(); - let y2 = sho.get_scalar(); - let y3 = sho.get_scalar(); - let y4 = sho.get_scalar(); - - let C_W = (w * system.G_w) + (wprime * system.G_wprime); - let mut I = system.G_V - - (x0 * system.G_x0) - - (x1 * system.G_x1) - - (y1 * system.G_y1) - - (y2 * system.G_y2) - - (y3 * system.G_y3); - - if num_attributes > 3 { - I -= y4 * system.G_y4; - } - - KeyPair { - w, - wprime, - W, - x0, - x1, - y1, - y2, - y3, - y4, - C_W, - I, - } - } - - pub fn get_public_key(&self) -> PublicKey { - PublicKey { - C_W: self.C_W, - I: self.I, - } - } - - pub fn create_auth_credential( - &self, - uid: uid_struct::UidStruct, - redemption_time: RedemptionTime, - sho: &mut Sho, - ) -> AuthCredential { - let M = convert_to_points_uid_struct(uid, redemption_time); - let (t, U, V) = self.credential_core(M, sho); - AuthCredential { t, U, V } - } - - fn credential_core( - &self, - M: Vec, - sho: &mut Sho, - ) -> (Scalar, RistrettoPoint, RistrettoPoint) { - if M.len() > 4 { - panic!(); - } - let t = sho.get_scalar(); - let U = sho.get_point(); - - let mut V = self.W + (self.x0 + self.x1 * t) * U; - V += self.y1 * M[0]; - V += self.y2 * M[1]; - if M.len() > 2 { - V += self.y3 * M[2]; - } - if M.len() > 3 { - V += self.y4 * M[3]; - } - (t, U, V) - } - - pub fn create_blinded_profile_key_credential( - &self, - uid: uid_struct::UidStruct, - public_key: profile_key_credential_request::PublicKey, - ciphertext: profile_key_credential_request::Ciphertext, - sho: &mut Sho, - ) -> BlindedProfileKeyCredentialWithSecretNonce { - let M = vec![uid.M1, uid.M2]; - - let (t, U, Vprime) = self.credential_core(M, sho); - let rprime = sho.get_scalar(); - let R1 = rprime * RISTRETTO_BASEPOINT_POINT; - let R2 = rprime * public_key.Y + Vprime; - let S1 = R1 + (self.y3 * ciphertext.D1) + (self.y4 * ciphertext.E1); - let S2 = R2 + (self.y3 * ciphertext.D2) + (self.y4 * ciphertext.E2); - BlindedProfileKeyCredentialWithSecretNonce { - rprime, - t, - U, - S1, - S2, - } - } -} - -impl BlindedProfileKeyCredentialWithSecretNonce { - pub fn get_blinded_profile_key_credential(&self) -> BlindedProfileKeyCredential { - BlindedProfileKeyCredential { - t: self.t, - U: self.U, - S1: self.S1, - S2: self.S2, - } - } -} - -#[cfg(test)] -mod tests { - use super::*; - use crate::common::constants::*; - use crate::crypto::proofs; - - #[test] - fn test_system() { - let params = SystemParams::generate(); - println!("PARAMS = {:#x?}", bincode::serialize(¶ms)); - assert!(SystemParams::generate() == SystemParams::get_hardcoded()); - } - - #[test] - fn test_mac() { - let mut sho = Sho::new(b"Test_Credentials", b""); - let keypair = KeyPair::generate(&mut sho, NUM_AUTH_CRED_ATTRIBUTES); - - let uid_bytes = TEST_ARRAY_16; - let redemption_time = 37; - let uid = uid_struct::UidStruct::new(uid_bytes); - let credential = keypair.create_auth_credential(uid, redemption_time, &mut sho); - let proof = proofs::AuthCredentialIssuanceProof::new( - keypair, - credential, - uid, - redemption_time, - &mut sho, - ); - - let public_key = keypair.get_public_key(); - proof - .verify(public_key, credential, uid, redemption_time) - .unwrap(); - - let keypair_bytes = bincode::serialize(&keypair).unwrap(); - let keypair2 = bincode::deserialize(&keypair_bytes).unwrap(); - assert!(keypair == keypair2); - - let public_key_bytes = bincode::serialize(&public_key).unwrap(); - let public_key2 = bincode::deserialize(&public_key_bytes).unwrap(); - assert!(public_key == public_key2); - - let mac_bytes = bincode::serialize(&credential).unwrap(); - - println!("mac_bytes = {:#x?}", mac_bytes); - assert!( - mac_bytes - == vec![ - 0xe0, 0xce, 0x21, 0xfe, 0xb7, 0xc3, 0xb8, 0x62, 0x3a, 0xe6, 0x20, 0xab, 0x3e, - 0xe6, 0x5d, 0x94, 0xa3, 0xf3, 0x40, 0x53, 0x31, 0x63, 0xd2, 0x4c, 0x5d, 0x41, - 0xa0, 0xd6, 0x7a, 0x40, 0xb3, 0x2, 0x8e, 0x50, 0xa2, 0x7b, 0xd4, 0xda, 0xe9, - 0x9d, 0x60, 0x0, 0xdb, 0x97, 0x3d, 0xbc, 0xc5, 0xad, 0xe1, 0x32, 0xbc, 0x56, - 0xb0, 0xe1, 0xac, 0x16, 0x7b, 0xb, 0x2c, 0x9, 0xe2, 0xb6, 0xc8, 0x5b, 0x68, - 0xc8, 0x8e, 0x7d, 0xfd, 0x58, 0x97, 0x51, 0xe9, 0x8, 0x1f, 0x81, 0xb0, 0x24, - 0xea, 0xa0, 0xaf, 0x29, 0x6, 0xed, 0xb3, 0x9, 0x32, 0xed, 0x65, 0x28, 0x2f, - 0xa1, 0x79, 0x9e, 0x1, 0x24, - ] - ); - } -} diff --git a/net/gurk-rs/files/vendor/zkgroup/src/crypto/mod.rs b/net/gurk-rs/files/vendor/zkgroup/src/crypto/mod.rs deleted file mode 100644 index 2154c18..0000000 --- a/net/gurk-rs/files/vendor/zkgroup/src/crypto/mod.rs +++ /dev/null @@ -1,16 +0,0 @@ -// -// Copyright (C) 2020 Signal Messenger, LLC. -// All rights reserved. -// -// SPDX-License-Identifier: GPL-3.0-only -// - -pub mod credentials; -pub mod profile_key_commitment; -pub mod profile_key_credential_request; -pub mod profile_key_encryption; -pub mod profile_key_struct; -pub mod proofs; -pub mod signature; -pub mod uid_encryption; -pub mod uid_struct; diff --git a/net/gurk-rs/files/vendor/zkgroup/src/crypto/profile_key_commitment.rs b/net/gurk-rs/files/vendor/zkgroup/src/crypto/profile_key_commitment.rs deleted file mode 100644 index 1340c0c..0000000 --- a/net/gurk-rs/files/vendor/zkgroup/src/crypto/profile_key_commitment.rs +++ /dev/null @@ -1,120 +0,0 @@ -// -// Copyright (C) 2020 Signal Messenger, LLC. -// All rights reserved. -// -// SPDX-License-Identifier: GPL-3.0-only -// - -#![allow(non_snake_case)] - -use crate::common::constants::*; -use crate::common::sho::*; -use crate::common::simple_types::*; -use crate::crypto::profile_key_struct; -use curve25519_dalek::ristretto::RistrettoPoint; -use curve25519_dalek::scalar::Scalar; -use serde::{Deserialize, Serialize}; - -#[derive(Copy, Clone, PartialEq, Serialize, Deserialize)] -pub struct SystemParams { - pub(crate) G_j1: RistrettoPoint, - pub(crate) G_j2: RistrettoPoint, - pub(crate) G_j3: RistrettoPoint, -} - -#[derive(Copy, Clone, PartialEq, Serialize, Deserialize)] -pub struct CommitmentWithSecretNonce { - pub(crate) J1: RistrettoPoint, - pub(crate) J2: RistrettoPoint, - pub(crate) J3: RistrettoPoint, - pub(crate) j3: Scalar, -} - -#[derive(Copy, Clone, PartialEq, Serialize, Deserialize)] -pub struct Commitment { - pub(crate) J1: RistrettoPoint, - pub(crate) J2: RistrettoPoint, - pub(crate) J3: RistrettoPoint, -} - -impl SystemParams { - pub fn generate() -> Self { - let mut sho = Sho::new( - b"Signal_ZKGroup_20200424_Constant_ProfileKeyCommitment_SystemParams_Generate", - b"", - ); - let G_j1 = sho.get_point(); - let G_j2 = sho.get_point(); - let G_j3 = sho.get_point(); - SystemParams { G_j1, G_j2, G_j3 } - } - - pub fn get_hardcoded() -> SystemParams { - bincode::deserialize::(&SystemParams::SYSTEM_HARDCODED).unwrap() - } - - const SYSTEM_HARDCODED: [u8; 96] = [ - 0xa8, 0xca, 0xb, 0xbd, 0x11, 0x48, 0xc4, 0x66, 0x72, 0x58, 0x60, 0x64, 0xa, 0xc5, 0x3d, - 0x27, 0x72, 0xb1, 0x4e, 0xea, 0xe0, 0x17, 0xa, 0x38, 0xc6, 0x2c, 0x7b, 0x3d, 0xd2, 0x9c, - 0x3e, 0x4a, 0x14, 0xb9, 0x46, 0x2d, 0x94, 0x8f, 0x5, 0x94, 0x50, 0x79, 0x9f, 0x4c, 0xc2, - 0xa0, 0x6e, 0x55, 0xde, 0xc8, 0x7, 0x73, 0x56, 0x70, 0xb9, 0x4a, 0x5c, 0xe8, 0xf, 0x59, - 0xf1, 0x95, 0x8, 0x61, 0xb0, 0xc0, 0xf7, 0xb9, 0x1f, 0x6e, 0xf9, 0xc7, 0x55, 0x60, 0x93, - 0xd8, 0x93, 0xa, 0x86, 0xbd, 0x36, 0x18, 0x8c, 0xec, 0x74, 0x5, 0x54, 0x65, 0x7d, 0x92, - 0xdc, 0xd8, 0x6a, 0xad, 0x25, 0x1c, - ]; -} - -impl CommitmentWithSecretNonce { - pub fn new( - profile_key: profile_key_struct::ProfileKeyStruct, - uid_bytes: UidBytes, - ) -> CommitmentWithSecretNonce { - let commitment_system = SystemParams::get_hardcoded(); - - let profile_key_struct::ProfileKeyStruct { M3, M4, .. } = profile_key; - let j3 = Self::calc_j3(profile_key.bytes, uid_bytes); - let J1 = (j3 * commitment_system.G_j1) + M3; - let J2 = (j3 * commitment_system.G_j2) + M4; - let J3 = j3 * commitment_system.G_j3; - CommitmentWithSecretNonce { J1, J2, J3, j3 } - } - - pub fn get_profile_key_commitment(&self) -> Commitment { - Commitment { - J1: self.J1, - J2: self.J2, - J3: self.J3, - } - } - - pub fn calc_j3(profile_key_bytes: ProfileKeyBytes, uid_bytes: UidBytes) -> Scalar { - let mut combined_array = [0u8; PROFILE_KEY_LEN + UUID_LEN]; - combined_array[..PROFILE_KEY_LEN].copy_from_slice(&profile_key_bytes); - combined_array[PROFILE_KEY_LEN..].copy_from_slice(&uid_bytes); - Sho::new( - b"Signal_ZKGroup_20200424_ProfileKeyAndUid_ProfileKeyCommitment_Calcj3", - &combined_array, - ) - .get_scalar() - } -} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_system() { - let params = SystemParams::generate(); - println!("PARAMS = {:#x?}", bincode::serialize(¶ms)); - assert!(SystemParams::generate() == SystemParams::get_hardcoded()); - } - - #[test] - fn test_commitment() { - let profile_key = profile_key_struct::ProfileKeyStruct::new(TEST_ARRAY_32, TEST_ARRAY_16); - let c1 = CommitmentWithSecretNonce::new(profile_key, TEST_ARRAY_16); - let c2 = CommitmentWithSecretNonce::new(profile_key, TEST_ARRAY_16); - assert!(c1 == c2); - } -} diff --git a/net/gurk-rs/files/vendor/zkgroup/src/crypto/profile_key_credential_request.rs b/net/gurk-rs/files/vendor/zkgroup/src/crypto/profile_key_credential_request.rs deleted file mode 100644 index 8a402dd..0000000 --- a/net/gurk-rs/files/vendor/zkgroup/src/crypto/profile_key_credential_request.rs +++ /dev/null @@ -1,190 +0,0 @@ -// -// Copyright (C) 2020 Signal Messenger, LLC. -// All rights reserved. -// -// SPDX-License-Identifier: GPL-3.0-only -// - -#![allow(non_snake_case)] - -use crate::common::sho::*; -use crate::crypto::credentials::{BlindedProfileKeyCredential, ProfileKeyCredential}; -use crate::crypto::profile_key_struct; -use curve25519_dalek::constants::RISTRETTO_BASEPOINT_POINT; -use curve25519_dalek::ristretto::RistrettoPoint; -use curve25519_dalek::scalar::Scalar; -use serde::{Deserialize, Serialize}; - -#[derive(Copy, Clone, PartialEq, Serialize, Deserialize)] -pub struct KeyPair { - // private - pub(crate) y: Scalar, - - // public - pub(crate) Y: RistrettoPoint, -} - -#[derive(Copy, Clone, PartialEq, Serialize, Deserialize)] -pub struct PublicKey { - pub(crate) Y: RistrettoPoint, -} - -#[derive(Copy, Clone, PartialEq, Serialize, Deserialize)] -pub struct CiphertextWithSecretNonce { - pub(crate) r1: Scalar, - pub(crate) r2: Scalar, - pub(crate) D1: RistrettoPoint, - pub(crate) D2: RistrettoPoint, - pub(crate) E1: RistrettoPoint, - pub(crate) E2: RistrettoPoint, -} - -#[derive(Copy, Clone, PartialEq, Serialize, Deserialize)] -pub struct Ciphertext { - pub(crate) D1: RistrettoPoint, - pub(crate) D2: RistrettoPoint, - pub(crate) E1: RistrettoPoint, - pub(crate) E2: RistrettoPoint, -} - -impl KeyPair { - pub fn generate(sho: &mut Sho) -> Self { - let y = sho.get_scalar(); - let Y = y * RISTRETTO_BASEPOINT_POINT; - KeyPair { y, Y } - } - - pub fn get_public_key(&self) -> PublicKey { - PublicKey { Y: self.Y } - } - - pub fn encrypt( - &self, - profile_key_struct: profile_key_struct::ProfileKeyStruct, - sho: &mut Sho, - ) -> CiphertextWithSecretNonce { - let r1 = sho.get_scalar(); - let r2 = sho.get_scalar(); - let D1 = r1 * RISTRETTO_BASEPOINT_POINT; - let E1 = r2 * RISTRETTO_BASEPOINT_POINT; - - let D2 = r1 * (self.Y) + profile_key_struct.M3; - let E2 = r2 * (self.Y) + profile_key_struct.M4; - - CiphertextWithSecretNonce { - r1, - r2, - D1, - D2, - E1, - E2, - } - } - - pub fn decrypt_blinded_profile_key_credential( - &self, - blinded_profile_key_credential: BlindedProfileKeyCredential, - ) -> ProfileKeyCredential { - let V = blinded_profile_key_credential.S2 - self.y * blinded_profile_key_credential.S1; - ProfileKeyCredential { - t: blinded_profile_key_credential.t, - U: blinded_profile_key_credential.U, - V, - } - } -} - -impl CiphertextWithSecretNonce { - pub fn get_ciphertext(&self) -> Ciphertext { - Ciphertext { - D1: self.D1, - D2: self.D2, - E1: self.E1, - E2: self.E2, - } - } -} - -#[cfg(test)] -mod tests { - use super::*; - use crate::common::constants::*; - use crate::crypto::profile_key_commitment; - - #[test] - fn test_request_response() { - let mut sho = Sho::new(b"Test_Profile_Key_Credential_Request", b""); - - // client - let blind_key_pair = KeyPair::generate(&mut sho); - - // server and client - let profile_key_struct = - profile_key_struct::ProfileKeyStruct::new(TEST_ARRAY_32, TEST_ARRAY_16); - let _ = profile_key_commitment::CommitmentWithSecretNonce::new( - profile_key_struct, - TEST_ARRAY_16, - ); - - // client - let _ = blind_key_pair.encrypt(profile_key_struct, &mut sho); - - // server - /*TODO request_ciphertext.verify(c).unwrap(); - - let credential_key_pair = credentials::KeyPair::generate(TEST_ARRAY_32_2); - let uid_bytes = TEST_ARRAY_16; - let redemption_time = 37; - let randomness = TEST_ARRAY_32_3; - let response = - query.create_response(credential_key_pair, uid_bytes, redemption_time, randomness); - - response - .verify( - blind_key_pair, - credential_key_pair.get_public_key(), - query.E_D1, - query.E_D2, - uid_bytes, - redemption_time, - ) - .unwrap(); - - let mac = response.get_mac(blind_key_pair); - - let master_key = GroupMasterKey::new(TEST_ARRAY_32_4); - let uid_enc_key_pair = uid_encryption::KeyPair::derive_from(master_key); - let profile_enc_key_pair = KeyPair::generate(TEST_ARRAY_32_4); - let profile_ciphertext = profile_enc_key_pair - .get_public_key() - .encrypt(profile_key, TEST_ARRAY_32_4); - - let ppp = profile_presentation_proof::PresentationProof::new( - mac, - uid_enc_key_pair, - credential_key_pair.get_public_key(), - uid_bytes, - profile_ciphertext.E_B1, - profile_ciphertext.E_B2, - profile_key, - profile_enc_key_pair.B, - profile_enc_key_pair.b, - redemption_time, - TEST_ARRAY_32_5, - ); - - let uid = uid_encryption::UidStruct::new(uid_bytes); - let uid_ciphertext = uid_enc_key_pair.encrypt(uid); - - ppp.verify( - uid_ciphertext, - uid_enc_key_pair.get_public_key(), - credential_key_pair, - redemption_time, - profile_ciphertext.E_B1, - profile_ciphertext.E_B2, - profile_enc_key_pair.B, - ).unwrap(); - */ - } -} diff --git a/net/gurk-rs/files/vendor/zkgroup/src/crypto/profile_key_encryption.rs b/net/gurk-rs/files/vendor/zkgroup/src/crypto/profile_key_encryption.rs deleted file mode 100644 index d1f6f9a..0000000 --- a/net/gurk-rs/files/vendor/zkgroup/src/crypto/profile_key_encryption.rs +++ /dev/null @@ -1,228 +0,0 @@ -// -// Copyright (C) 2020 Signal Messenger, LLC. -// All rights reserved. -// -// SPDX-License-Identifier: GPL-3.0-only -// - -#![allow(non_snake_case)] - -use crate::common::errors::*; -use crate::common::sho::*; -use crate::common::simple_types::*; -use crate::crypto::profile_key_struct; -use curve25519_dalek::constants::RISTRETTO_BASEPOINT_POINT; -use curve25519_dalek::ristretto::RistrettoPoint; -use curve25519_dalek::scalar::Scalar; -use serde::{Deserialize, Serialize}; - -use curve25519_dalek::subtle::Choice; -use curve25519_dalek::subtle::ConditionallySelectable; -use curve25519_dalek::subtle::ConstantTimeEq; - -use ZkGroupError::*; - -#[derive(Copy, Clone, PartialEq, Serialize, Deserialize)] -pub struct SystemParams { - pub(crate) G_b1: RistrettoPoint, - pub(crate) G_b2: RistrettoPoint, -} - -#[derive(Copy, Clone, PartialEq, Serialize, Deserialize)] -pub struct KeyPair { - pub(crate) b1: Scalar, - pub(crate) b2: Scalar, - pub(crate) B: RistrettoPoint, -} - -#[derive(Copy, Clone, PartialEq, Serialize, Deserialize)] -pub struct PublicKey { - pub(crate) B: RistrettoPoint, -} - -#[derive(Copy, Clone, Default, PartialEq, Serialize, Deserialize)] -pub struct Ciphertext { - pub(crate) E_B1: RistrettoPoint, - pub(crate) E_B2: RistrettoPoint, -} - -impl SystemParams { - pub fn generate() -> Self { - let mut sho = Sho::new( - b"Signal_ZKGroup_20200424_Constant_ProfileKeyEncryption_SystemParams_Generate", - b"", - ); - let G_b1 = sho.get_point(); - let G_b2 = sho.get_point(); - SystemParams { G_b1, G_b2 } - } - - pub fn get_hardcoded() -> SystemParams { - bincode::deserialize::(&SystemParams::SYSTEM_HARDCODED).unwrap() - } - - const SYSTEM_HARDCODED: [u8; 64] = [ - 0xf6, 0xba, 0xa3, 0x17, 0xce, 0x18, 0x39, 0xc9, 0x3d, 0x61, 0x7e, 0xc, 0xd8, 0x37, 0xd1, - 0x9d, 0xa9, 0xc8, 0xa4, 0xc5, 0x20, 0xbf, 0x7c, 0x51, 0xb1, 0xe6, 0xc2, 0xcb, 0x2a, 0x4, - 0x9c, 0x61, 0x2e, 0x1, 0x75, 0x89, 0x4c, 0x87, 0x30, 0xb2, 0x3, 0xab, 0x3b, 0xd9, 0x8e, - 0xcb, 0x2d, 0x81, 0xab, 0xac, 0xb6, 0x5f, 0x8a, 0x61, 0x24, 0xf4, 0x97, 0x71, 0xd1, 0x4a, - 0x98, 0x52, 0x12, 0xc, - ]; -} - -impl KeyPair { - pub fn derive_from(sho: &mut Sho) -> Self { - let system = SystemParams::get_hardcoded(); - - let b1 = sho.get_scalar(); - let b2 = sho.get_scalar(); - - let B = b1 * system.G_b1 + b2 * system.G_b2; - KeyPair { b1, b2, B } - } - - pub fn encrypt(&self, profile_key: profile_key_struct::ProfileKeyStruct) -> Ciphertext { - let E_B1 = self.calc_E_B1(profile_key); - let E_B2 = (self.b2 * E_B1) + profile_key.M4; - Ciphertext { E_B1, E_B2 } - } - - // Might return DecryptionFailure - #[allow(clippy::needless_range_loop)] - pub fn decrypt( - &self, - ciphertext: Ciphertext, - uid_bytes: UidBytes, - ) -> Result { - if ciphertext.E_B1 == RISTRETTO_BASEPOINT_POINT { - return Err(DecryptionFailure); - } - let M4 = ciphertext.E_B2 - (self.b2 * ciphertext.E_B1); - let (mask, candidates) = M4.decode_253_bits(); - - let target_M3 = self.b1.invert() * ciphertext.E_B1; - - let mut retval: profile_key_struct::ProfileKeyStruct = Default::default(); - let mut n_found = 0; - for i in 0..8 { - let is_valid_fe = Choice::from((mask >> i) & 1); - let profile_key_bytes: ProfileKeyBytes = candidates[i]; - for j in 0..8 { - let mut pk = profile_key_bytes; - if ((j >> 2) & 1) == 1 { - pk[0] |= 0x01; - } - if ((j >> 1) & 1) == 1 { - pk[31] |= 0x80; - } - if (j & 1) == 1 { - pk[31] |= 0x40; - } - let M3 = profile_key_struct::ProfileKeyStruct::calc_M3(pk, uid_bytes); - let candidate_retval = profile_key_struct::ProfileKeyStruct { bytes: pk, M3, M4 }; - let found = M3.ct_eq(&target_M3) & is_valid_fe; - retval.conditional_assign(&candidate_retval, found); - n_found += found.unwrap_u8(); - } - } - if n_found == 1 { - Ok(retval) - } else { - Err(DecryptionFailure) - } - } - - fn calc_E_B1(&self, profile_key: profile_key_struct::ProfileKeyStruct) -> RistrettoPoint { - self.b1 * profile_key.M3 - } - - pub fn get_public_key(&self) -> PublicKey { - PublicKey { B: self.B } - } -} - -#[cfg(test)] -mod tests { - use super::*; - use crate::common::constants::*; - - #[test] - fn test_profile_key_encryption() { - let master_key = TEST_ARRAY_32_1; - let mut sho = Sho::new(b"Test_Profile_Key_Encryption", &master_key); - - //let system = SystemParams::generate(); - //println!("PARAMS = {:#x?}", bincode::serialize(&system)); - assert!(SystemParams::generate() == SystemParams::get_hardcoded()); - - let key_pair = KeyPair::derive_from(&mut sho); - - // Test serialize of key_pair - let key_pair_bytes = bincode::serialize(&key_pair).unwrap(); - match bincode::deserialize::(&key_pair_bytes[0..key_pair_bytes.len() - 1]) { - Err(_) => (), - _ => unreachable!(), - }; - let key_pair2: KeyPair = bincode::deserialize(&key_pair_bytes).unwrap(); - assert!(key_pair == key_pair2); - - let profile_key_bytes = TEST_ARRAY_32_1; - let uid_bytes = TEST_ARRAY_16_1; - let profile_key = profile_key_struct::ProfileKeyStruct::new(profile_key_bytes, uid_bytes); - let ciphertext = key_pair.encrypt(profile_key); - - // Test serialize / deserialize of Ciphertext - let ciphertext_bytes = bincode::serialize(&ciphertext).unwrap(); - assert!(ciphertext_bytes.len() == 64); - let ciphertext2: Ciphertext = bincode::deserialize(&ciphertext_bytes).unwrap(); - assert!(ciphertext == ciphertext2); - println!("ciphertext_bytes = {:#x?}", ciphertext_bytes); - assert!( - ciphertext_bytes - == vec![ - 0x56, 0x18, 0xcb, 0x4c, 0x7d, 0x72, 0x1e, 0x1, 0x2b, 0x22, 0xf0, 0x77, 0xef, - 0x12, 0x64, 0xf6, 0xb1, 0x43, 0xbb, 0x59, 0x7a, 0x1d, 0x66, 0x5a, 0x70, 0xaa, - 0x84, 0x24, 0x5f, 0x24, 0x6d, 0x20, 0xba, 0xdb, 0x97, 0x47, 0x4a, 0x56, 0xf4, - 0xb5, 0x36, 0x1a, 0xec, 0xa9, 0xd1, 0x18, 0xb7, 0x0, 0x4e, 0x14, 0x9, 0x71, - 0x99, 0xa, 0xab, 0x2a, 0xf2, 0x43, 0x2d, 0x3f, 0x8f, 0x7d, 0x21, 0x3a, - ] - ); - - let plaintext = key_pair.decrypt(ciphertext2, uid_bytes).unwrap(); - assert!(plaintext == profile_key); - - let mut sho = Sho::new(b"Test_Repeated_ProfileKeyEnc/Dec", b"seed"); - for _ in 0..100 { - let mut uid_bytes: UidBytes = Default::default(); - let mut profile_key_bytes: ProfileKeyBytes = Default::default(); - - uid_bytes.copy_from_slice(&sho.squeeze(UUID_LEN)[..]); - profile_key_bytes.copy_from_slice(&sho.squeeze(PROFILE_KEY_LEN)[..]); - - let profile_key = - profile_key_struct::ProfileKeyStruct::new(profile_key_bytes, uid_bytes); - let ciphertext = key_pair.encrypt(profile_key); - assert!(key_pair.decrypt(ciphertext, uid_bytes).unwrap() == profile_key); - } - - let uid_bytes = TEST_ARRAY_16; - let profile_key = profile_key_struct::ProfileKeyStruct::new(TEST_ARRAY_32, TEST_ARRAY_16); - let ciphertext = key_pair.encrypt(profile_key); - assert!(key_pair.decrypt(ciphertext, uid_bytes).unwrap() == profile_key); - - let uid_bytes = TEST_ARRAY_16; - let profile_key = profile_key_struct::ProfileKeyStruct::new(TEST_ARRAY_32_2, TEST_ARRAY_16); - let ciphertext = key_pair.encrypt(profile_key); - assert!(key_pair.decrypt(ciphertext, uid_bytes).unwrap() == profile_key); - - let uid_bytes = TEST_ARRAY_16; - let profile_key = profile_key_struct::ProfileKeyStruct::new(TEST_ARRAY_32_3, TEST_ARRAY_16); - let ciphertext = key_pair.encrypt(profile_key); - assert!(key_pair.decrypt(ciphertext, uid_bytes).unwrap() == profile_key); - - let uid_bytes = TEST_ARRAY_16; - let profile_key = profile_key_struct::ProfileKeyStruct::new(TEST_ARRAY_32_4, TEST_ARRAY_16); - let ciphertext = key_pair.encrypt(profile_key); - assert!(key_pair.decrypt(ciphertext, uid_bytes).unwrap() == profile_key); - } -} diff --git a/net/gurk-rs/files/vendor/zkgroup/src/crypto/profile_key_struct.rs b/net/gurk-rs/files/vendor/zkgroup/src/crypto/profile_key_struct.rs deleted file mode 100644 index ad93263..0000000 --- a/net/gurk-rs/files/vendor/zkgroup/src/crypto/profile_key_struct.rs +++ /dev/null @@ -1,75 +0,0 @@ -// -// Copyright (C) 2020 Signal Messenger, LLC. -// All rights reserved. -// -// SPDX-License-Identifier: GPL-3.0-only -// - -#![allow(non_snake_case)] - -use crate::common::constants::*; -use crate::common::sho::*; -use crate::common::simple_types::*; -use curve25519_dalek::ristretto::RistrettoPoint; -use serde::{Deserialize, Serialize}; - -use curve25519_dalek::subtle::Choice; -use curve25519_dalek::subtle::ConditionallySelectable; - -#[derive(Copy, Clone, Default, PartialEq, Serialize, Deserialize)] -pub struct ProfileKeyStruct { - pub(crate) bytes: ProfileKeyBytes, - pub(crate) M3: RistrettoPoint, - pub(crate) M4: RistrettoPoint, -} - -impl ProfileKeyStruct { - pub fn new(profile_key_bytes: ProfileKeyBytes, uid_bytes: UidBytes) -> Self { - let mut encoded_profile_key = profile_key_bytes; - encoded_profile_key[0] &= 254; - encoded_profile_key[31] &= 63; - let M3 = Self::calc_M3(profile_key_bytes, uid_bytes); - let M4 = RistrettoPoint::from_uniform_bytes_single_elligator(&encoded_profile_key); - - ProfileKeyStruct { - bytes: profile_key_bytes, - M3, - M4, - } - } - - pub fn calc_M3(profile_key_bytes: ProfileKeyBytes, uid_bytes: UidBytes) -> RistrettoPoint { - let mut combined_array = [0u8; PROFILE_KEY_LEN + UUID_LEN]; - combined_array[..PROFILE_KEY_LEN].copy_from_slice(&profile_key_bytes); - combined_array[PROFILE_KEY_LEN..].copy_from_slice(&uid_bytes); - Sho::new( - b"Signal_ZKGroup_20200424_ProfileKeyAndUid_ProfileKey_CalcM3", - &combined_array, - ) - .get_point_single_elligator() - } - - pub fn to_bytes(&self) -> ProfileKeyBytes { - self.bytes - } -} - -impl ConditionallySelectable for ProfileKeyStruct { - #[allow(clippy::needless_range_loop)] - fn conditional_select( - a: &ProfileKeyStruct, - b: &ProfileKeyStruct, - choice: Choice, - ) -> ProfileKeyStruct { - let mut bytes: ProfileKeyBytes = [0u8; PROFILE_KEY_LEN]; - for i in 0..PROFILE_KEY_LEN { - bytes[i] = u8::conditional_select(&a.bytes[i], &b.bytes[i], choice); - } - - ProfileKeyStruct { - bytes, - M3: RistrettoPoint::conditional_select(&a.M3, &b.M3, choice), - M4: RistrettoPoint::conditional_select(&a.M4, &b.M4, choice), - } - } -} diff --git a/net/gurk-rs/files/vendor/zkgroup/src/crypto/proofs.rs b/net/gurk-rs/files/vendor/zkgroup/src/crypto/proofs.rs deleted file mode 100644 index 2a9ba6f..0000000 --- a/net/gurk-rs/files/vendor/zkgroup/src/crypto/proofs.rs +++ /dev/null @@ -1,731 +0,0 @@ -// -// Copyright (C) 2020 Signal Messenger, LLC. -// All rights reserved. -// -// SPDX-License-Identifier: GPL-3.0-only -// - -#![allow(non_snake_case)] -use crate::common::constants::*; -use crate::common::errors::ZkGroupError::*; -use crate::common::errors::*; -use crate::common::sho::*; -use crate::common::simple_types::*; -use crate::crypto::credentials; -use crate::crypto::profile_key_commitment; -use crate::crypto::profile_key_credential_request; -use crate::crypto::profile_key_encryption; -use crate::crypto::profile_key_struct; -use crate::crypto::uid_encryption; -use crate::crypto::uid_struct; -use curve25519_dalek::ristretto::RistrettoPoint; -use serde::{Deserialize, Serialize}; - -#[derive(Serialize, Deserialize, Clone)] -pub struct AuthCredentialIssuanceProof { - poksho_proof: Vec, -} - -#[derive(Serialize, Deserialize, Clone)] -pub struct ProfileKeyCredentialRequestProof { - poksho_proof: Vec, -} - -#[derive(Serialize, Deserialize, Clone)] -pub struct ProfileKeyCredentialIssuanceProof { - poksho_proof: Vec, -} - -#[derive(Serialize, Deserialize, Clone)] -pub struct AuthCredentialPresentationProof { - C_x0: RistrettoPoint, - C_x1: RistrettoPoint, - C_y1: RistrettoPoint, - C_y2: RistrettoPoint, - C_y3: RistrettoPoint, - C_V: RistrettoPoint, - poksho_proof: Vec, -} - -#[derive(Serialize, Deserialize, Clone)] -pub struct ProfileKeyCredentialPresentationProof { - C_x0: RistrettoPoint, - C_x1: RistrettoPoint, - C_y1: RistrettoPoint, - C_y2: RistrettoPoint, - C_y3: RistrettoPoint, - C_y4: RistrettoPoint, - C_V: RistrettoPoint, - C_z: RistrettoPoint, - poksho_proof: Vec, -} - -impl AuthCredentialIssuanceProof { - pub fn get_poksho_statement() -> poksho::Statement { - let mut st = poksho::Statement::new(); - st.add("C_W", &[("w", "G_w"), ("wprime", "G_wprime")]); - st.add( - "G_V-I", - &[ - ("x0", "G_x0"), - ("x1", "G_x1"), - ("y1", "G_y1"), - ("y2", "G_y2"), - ("y3", "G_y3"), - ], - ); - st.add( - "V", - &[ - ("w", "G_w"), - ("x0", "U"), - ("x1", "tU"), - ("y1", "M1"), - ("y2", "M2"), - ("y3", "M3"), - ], - ); - st - } - - pub fn new( - key_pair: credentials::KeyPair, - credential: credentials::AuthCredential, - uid: uid_struct::UidStruct, - redemption_time: RedemptionTime, - sho: &mut Sho, - ) -> Self { - let system = credentials::SystemParams::get_hardcoded(); - - let M = credentials::convert_to_points_uid_struct(uid, redemption_time); - - let mut scalar_args = poksho::ScalarArgs::new(); - scalar_args.add("w", key_pair.w); - scalar_args.add("wprime", key_pair.wprime); - scalar_args.add("x0", key_pair.x0); - scalar_args.add("x1", key_pair.x1); - scalar_args.add("y1", key_pair.y1); - scalar_args.add("y2", key_pair.y2); - scalar_args.add("y3", key_pair.y3); - - let mut point_args = poksho::PointArgs::new(); - point_args.add("C_W", key_pair.C_W); - point_args.add("G_w", system.G_w); - point_args.add("G_wprime", system.G_wprime); - point_args.add("G_V-I", system.G_V - key_pair.I); - point_args.add("G_x0", system.G_x0); - point_args.add("G_x1", system.G_x1); - point_args.add("G_y1", system.G_y1); - point_args.add("G_y2", system.G_y2); - point_args.add("G_y3", system.G_y3); - point_args.add("V", credential.V); - point_args.add("U", credential.U); - point_args.add("tU", credential.t * credential.U); - point_args.add("M1", M[0]); - point_args.add("M2", M[1]); - point_args.add("M3", M[2]); - - let poksho_proof = Self::get_poksho_statement() - .prove( - &scalar_args, - &point_args, - &[], - &sho.squeeze(RANDOMNESS_LEN)[..], - ) - .unwrap(); - Self { poksho_proof } - } - - pub fn verify( - &self, - public_key: credentials::PublicKey, - credential: credentials::AuthCredential, - uid_struct: uid_struct::UidStruct, - redemption_time: RedemptionTime, - ) -> Result<(), ZkGroupError> { - let system = credentials::SystemParams::get_hardcoded(); - - let M = credentials::convert_to_points_uid_struct(uid_struct, redemption_time); - - let mut point_args = poksho::PointArgs::new(); - point_args.add("C_W", public_key.C_W); - point_args.add("G_w", system.G_w); - point_args.add("G_wprime", system.G_wprime); - point_args.add("G_V-I", system.G_V - public_key.I); - point_args.add("G_x0", system.G_x0); - point_args.add("G_x1", system.G_x1); - point_args.add("G_y1", system.G_y1); - point_args.add("G_y2", system.G_y2); - point_args.add("G_y3", system.G_y3); - point_args.add("V", credential.V); - point_args.add("U", credential.U); - point_args.add("tU", credential.t * credential.U); - point_args.add("M1", M[0]); - point_args.add("M2", M[1]); - point_args.add("M3", M[2]); - - match Self::get_poksho_statement().verify_proof(&self.poksho_proof, &point_args, &[]) { - Err(_) => Err(ProofVerificationFailure), - Ok(_) => Ok(()), - } - } -} - -impl ProfileKeyCredentialRequestProof { - pub fn get_poksho_statement() -> poksho::Statement { - let mut st = poksho::Statement::new(); - st.add("Y", &[("y", "G")]); - st.add("D1", &[("r1", "G")]); - st.add("E1", &[("r2", "G")]); - st.add("J3", &[("j3", "G_j3")]); - st.add("D2-J1", &[("r1", "Y"), ("j3", "-G_j1")]); - st.add("E2-J2", &[("r2", "Y"), ("j3", "-G_j2")]); - st - } - - pub fn new( - key_pair: profile_key_credential_request::KeyPair, - ciphertext: profile_key_credential_request::CiphertextWithSecretNonce, - commitment: profile_key_commitment::CommitmentWithSecretNonce, - sho: &mut Sho, - ) -> ProfileKeyCredentialRequestProof { - let commitment_system = profile_key_commitment::SystemParams::get_hardcoded(); - - let mut scalar_args = poksho::ScalarArgs::new(); - scalar_args.add("y", key_pair.y); - scalar_args.add("r1", ciphertext.r1); - scalar_args.add("r2", ciphertext.r2); - scalar_args.add("j3", commitment.j3); - - let mut point_args = poksho::PointArgs::new(); - point_args.add("Y", key_pair.Y); - point_args.add("D1", ciphertext.D1); - point_args.add("E1", ciphertext.E1); - point_args.add("J3", commitment.J3); - point_args.add("G_j3", commitment_system.G_j3); - point_args.add("D2-J1", ciphertext.D2 - commitment.J1); - point_args.add("-G_j1", -commitment_system.G_j1); - point_args.add("E2-J2", ciphertext.E2 - commitment.J2); - point_args.add("-G_j2", -commitment_system.G_j2); - - let poksho_proof = Self::get_poksho_statement() - .prove( - &scalar_args, - &point_args, - &[], - &sho.squeeze(RANDOMNESS_LEN)[..], - ) - .unwrap(); - ProfileKeyCredentialRequestProof { poksho_proof } - } - - pub fn verify( - &self, - public_key: profile_key_credential_request::PublicKey, - ciphertext: profile_key_credential_request::Ciphertext, - commitment: profile_key_commitment::Commitment, - ) -> Result<(), ZkGroupError> { - let commitment_system = profile_key_commitment::SystemParams::get_hardcoded(); - - let mut point_args = poksho::PointArgs::new(); - point_args.add("Y", public_key.Y); - point_args.add("D1", ciphertext.D1); - point_args.add("E1", ciphertext.E1); - point_args.add("J3", commitment.J3); - point_args.add("G_j3", commitment_system.G_j3); - point_args.add("D2-J1", ciphertext.D2 - commitment.J1); - point_args.add("-G_j1", -commitment_system.G_j1); - point_args.add("E2-J2", ciphertext.E2 - commitment.J2); - point_args.add("-G_j2", -commitment_system.G_j2); - - match Self::get_poksho_statement().verify_proof(&self.poksho_proof, &point_args, &[]) { - Err(_) => Err(ProofVerificationFailure), - Ok(_) => Ok(()), - } - } -} - -impl ProfileKeyCredentialIssuanceProof { - pub fn get_poksho_statement() -> poksho::Statement { - let mut st = poksho::Statement::new(); - st.add("C_W", &[("w", "G_w"), ("wprime", "G_wprime")]); - st.add( - "G_V-I", - &[ - ("x0", "G_x0"), - ("x1", "G_x1"), - ("y1", "G_y1"), - ("y2", "G_y2"), - ("y3", "G_y3"), - ("y4", "G_y4"), - ], - ); - st.add("S1", &[("y3", "D1"), ("y4", "E1"), ("rprime", "G")]); - st.add( - "S2", - &[ - ("y3", "D2"), - ("y4", "E2"), - ("rprime", "Y"), - ("w", "G_w"), - ("x0", "U"), - ("x1", "tU"), - ("y1", "M1"), - ("y2", "M2"), - ], - ); - st - } - - pub fn new( - key_pair: credentials::KeyPair, - request_public_key: profile_key_credential_request::PublicKey, - request: profile_key_credential_request::Ciphertext, - blinded_credential: credentials::BlindedProfileKeyCredentialWithSecretNonce, - uid: uid_struct::UidStruct, - sho: &mut Sho, - ) -> ProfileKeyCredentialIssuanceProof { - let credentials_system = credentials::SystemParams::get_hardcoded(); - - let mut scalar_args = poksho::ScalarArgs::new(); - scalar_args.add("w", key_pair.w); - scalar_args.add("wprime", key_pair.wprime); - scalar_args.add("x0", key_pair.x0); - scalar_args.add("x1", key_pair.x1); - scalar_args.add("y1", key_pair.y1); - scalar_args.add("y2", key_pair.y2); - scalar_args.add("y3", key_pair.y3); - scalar_args.add("y4", key_pair.y4); - scalar_args.add("rprime", blinded_credential.rprime); - - let mut point_args = poksho::PointArgs::new(); - point_args.add("C_W", key_pair.C_W); - point_args.add("G_w", credentials_system.G_w); - point_args.add("G_wprime", credentials_system.G_wprime); - point_args.add("G_V-I", credentials_system.G_V - key_pair.I); - point_args.add("G_x0", credentials_system.G_x0); - point_args.add("G_x1", credentials_system.G_x1); - point_args.add("G_y1", credentials_system.G_y1); - point_args.add("G_y2", credentials_system.G_y2); - point_args.add("G_y3", credentials_system.G_y3); - point_args.add("G_y4", credentials_system.G_y4); - point_args.add("S1", blinded_credential.S1); - point_args.add("D1", request.D1); - point_args.add("E1", request.E1); - point_args.add("S2", blinded_credential.S2); - point_args.add("D2", request.D2); - point_args.add("E2", request.E2); - point_args.add("Y", request_public_key.Y); - point_args.add("U", blinded_credential.U); - point_args.add("tU", blinded_credential.t * blinded_credential.U); - point_args.add("M1", uid.M1); - point_args.add("M2", uid.M2); - - let poksho_proof = Self::get_poksho_statement() - .prove( - &scalar_args, - &point_args, - &[], - &sho.squeeze(RANDOMNESS_LEN)[..], - ) - .unwrap(); - ProfileKeyCredentialIssuanceProof { poksho_proof } - } - - pub fn verify( - &self, - credentials_public_key: credentials::PublicKey, - request_public_key: profile_key_credential_request::PublicKey, - uid_bytes: UidBytes, - request: profile_key_credential_request::Ciphertext, - blinded_credential: credentials::BlindedProfileKeyCredential, - ) -> Result<(), ZkGroupError> { - let credentials_system = credentials::SystemParams::get_hardcoded(); - let uid = uid_struct::UidStruct::new(uid_bytes); - - let mut point_args = poksho::PointArgs::new(); - point_args.add("C_W", credentials_public_key.C_W); - point_args.add("G_w", credentials_system.G_w); - point_args.add("G_wprime", credentials_system.G_wprime); - point_args.add("G_V-I", credentials_system.G_V - credentials_public_key.I); - point_args.add("G_x0", credentials_system.G_x0); - point_args.add("G_x1", credentials_system.G_x1); - point_args.add("G_y1", credentials_system.G_y1); - point_args.add("G_y2", credentials_system.G_y2); - point_args.add("G_y3", credentials_system.G_y3); - point_args.add("G_y4", credentials_system.G_y4); - point_args.add("S1", blinded_credential.S1); - point_args.add("D1", request.D1); - point_args.add("E1", request.E1); - point_args.add("S2", blinded_credential.S2); - point_args.add("D2", request.D2); - point_args.add("E2", request.E2); - point_args.add("Y", request_public_key.Y); - point_args.add("U", blinded_credential.U); - point_args.add("tU", blinded_credential.t * blinded_credential.U); - point_args.add("M1", uid.M1); - point_args.add("M2", uid.M2); - - match Self::get_poksho_statement().verify_proof(&self.poksho_proof, &point_args, &[]) { - Err(_) => Err(ProofVerificationFailure), - Ok(_) => Ok(()), - } - } -} - -impl AuthCredentialPresentationProof { - pub fn get_poksho_statement() -> poksho::Statement { - let mut st = poksho::Statement::new(); - - st.add("Z", &[("z", "I")]); - st.add("C_x1", &[("t", "C_x0"), ("z0", "G_x0"), ("z", "G_x1")]); - st.add("A", &[("a1", "G_a1"), ("a2", "G_a2")]); - st.add("C_y2-E_A2", &[("z", "G_y2"), ("a2", "-E_A1")]); - st.add("E_A1", &[("a1", "C_y1"), ("z1", "G_y1")]); - st.add("C_y3", &[("z", "G_y3")]); - st - } - - pub fn new( - credentials_public_key: credentials::PublicKey, - uid_enc_key_pair: uid_encryption::KeyPair, - credential: credentials::AuthCredential, - uid: uid_struct::UidStruct, - uid_ciphertext: uid_encryption::Ciphertext, - redemption_time: RedemptionTime, - sho: &mut Sho, - ) -> Self { - let credentials_system = credentials::SystemParams::get_hardcoded(); - let uid_system = uid_encryption::SystemParams::get_hardcoded(); - let M = credentials::convert_to_points_uid_struct(uid, redemption_time); - - let z = sho.get_scalar(); - - let C_y1 = z * credentials_system.G_y1 + M[0]; - let C_y2 = z * credentials_system.G_y2 + M[1]; - let C_y3 = z * credentials_system.G_y3; - - let C_x0 = z * credentials_system.G_x0 + credential.U; - let C_V = z * credentials_system.G_V + credential.V; - let C_x1 = z * credentials_system.G_x1 + credential.t * credential.U; - - let z0 = -z * credential.t; - let z1 = -z * uid_enc_key_pair.a1; - - let I = credentials_public_key.I; - let Z = z * I; - - // Scalars listed in order of stmts for debugging - let mut scalar_args = poksho::ScalarArgs::new(); - scalar_args.add("z", z); - scalar_args.add("t", credential.t); - scalar_args.add("z0", z0); - scalar_args.add("a1", uid_enc_key_pair.a1); - scalar_args.add("a2", uid_enc_key_pair.a2); - scalar_args.add("z1", z1); - - // Points listed in order of stmts for debugging - let mut point_args = poksho::PointArgs::new(); - point_args.add("Z", Z); - point_args.add("I", I); - point_args.add("C_x1", C_x1); - point_args.add("C_x0", C_x0); - point_args.add("G_x0", credentials_system.G_x0); - point_args.add("G_x1", credentials_system.G_x1); - point_args.add("A", uid_enc_key_pair.A); - point_args.add("G_a1", uid_system.G_a1); - point_args.add("G_a2", uid_system.G_a2); - point_args.add("C_y2-E_A2", C_y2 - uid_ciphertext.E_A2); - point_args.add("G_y2", credentials_system.G_y2); - point_args.add("-E_A1", -uid_ciphertext.E_A1); - point_args.add("E_A1", uid_ciphertext.E_A1); - point_args.add("C_y1", C_y1); - point_args.add("G_y1", credentials_system.G_y1); - point_args.add("C_y3", C_y3); - point_args.add("G_y3", credentials_system.G_y3); - - let poksho_proof = Self::get_poksho_statement() - .prove( - &scalar_args, - &point_args, - &[], - &sho.squeeze(RANDOMNESS_LEN)[..], - ) - .unwrap(); - - Self { - C_x0, - C_x1, - C_y1, - C_y2, - C_y3, - C_V, - poksho_proof, - } - } - - pub fn verify( - &self, - credentials_key_pair: credentials::KeyPair, - uid_enc_public_key: uid_encryption::PublicKey, - uid_ciphertext: uid_encryption::Ciphertext, - redemption_time: RedemptionTime, - ) -> Result<(), ZkGroupError> { - let enc_system = uid_encryption::SystemParams::get_hardcoded(); - let credentials_system = credentials::SystemParams::get_hardcoded(); - - let Self { - C_x0, - C_x1, - C_y1, - C_y2, - C_y3, - C_V, - poksho_proof, - } = self; - - let (C_x0, C_x1, C_y1, C_y2, C_y3, C_V) = (*C_x0, *C_x1, *C_y1, *C_y2, *C_y3, *C_V); - - let credentials::KeyPair { - W, - x0, - x1, - y1, - y2, - y3, - I, - .. - } = credentials_key_pair; - - let m3 = encode_redemption_time(redemption_time); - let M3 = m3 * credentials_system.G_m3; - let Z = C_V - W - x0 * C_x0 - x1 * C_x1 - y1 * C_y1 - y2 * C_y2 - y3 * (C_y3 + M3); - - // Points listed in order of stmts for debugging - let mut point_args = poksho::PointArgs::new(); - point_args.add("Z", Z); - point_args.add("I", I); - point_args.add("C_x1", C_x1); - point_args.add("C_x0", C_x0); - point_args.add("G_x0", credentials_system.G_x0); - point_args.add("G_x1", credentials_system.G_x1); - point_args.add("A", uid_enc_public_key.A); - point_args.add("G_a1", enc_system.G_a1); - point_args.add("G_a2", enc_system.G_a2); - point_args.add("C_y2-E_A2", C_y2 - uid_ciphertext.E_A2); - point_args.add("G_y2", credentials_system.G_y2); - point_args.add("-E_A1", -uid_ciphertext.E_A1); - point_args.add("E_A1", uid_ciphertext.E_A1); - point_args.add("C_y1", C_y1); - point_args.add("G_y1", credentials_system.G_y1); - point_args.add("C_y3", C_y3); - point_args.add("G_y3", credentials_system.G_y3); - - match Self::get_poksho_statement().verify_proof(poksho_proof, &point_args, &[]) { - Err(_) => Err(ZkGroupError::ProofVerificationFailure), - Ok(_) => Ok(()), - } - } -} - -impl ProfileKeyCredentialPresentationProof { - pub fn get_poksho_statement() -> poksho::Statement { - let mut st = poksho::Statement::new(); - st.add("C_z", &[("z", "G_z")]); - st.add("Z", &[("z", "I")]); - st.add("C_x1", &[("t", "C_x0"), ("z0", "G_x0"), ("z", "G_x1")]); - st.add("A", &[("a1", "G_a1"), ("a2", "G_a2")]); - st.add("B", &[("b1", "G_b1"), ("b2", "G_b2")]); - st.add("C_y2-E_A2", &[("z", "G_y2"), ("a2", "-E_A1")]); - st.add("E_A1", &[("a1", "C_y1"), ("z1", "G_y1")]); - st.add("C_y4-E_B2", &[("z", "G_y4"), ("b2", "-E_B1")]); - st.add("E_B1", &[("b1", "C_y3"), ("z2", "G_y3")]); - st - } - - #[allow(clippy::too_many_arguments)] - pub fn new( - uid_enc_key_pair: uid_encryption::KeyPair, - profile_key_enc_key_pair: profile_key_encryption::KeyPair, - credentials_public_key: credentials::PublicKey, - credential: credentials::ProfileKeyCredential, - uid_ciphertext: uid_encryption::Ciphertext, - profile_key_ciphertext: profile_key_encryption::Ciphertext, - uid_bytes: UidBytes, - profile_key_bytes: ProfileKeyBytes, - sho: &mut Sho, - ) -> Self { - let credentials_system = credentials::SystemParams::get_hardcoded(); - let uid_system = uid_encryption::SystemParams::get_hardcoded(); - let profile_key_system = profile_key_encryption::SystemParams::get_hardcoded(); - let uid = uid_struct::UidStruct::new(uid_bytes); - let profile_key = profile_key_struct::ProfileKeyStruct::new(profile_key_bytes, uid_bytes); - - let z = sho.get_scalar(); - - let C_y1 = z * credentials_system.G_y1 + uid.M1; - let C_y2 = z * credentials_system.G_y2 + uid.M2; - let C_y3 = z * credentials_system.G_y3 + profile_key.M3; - let C_y4 = z * credentials_system.G_y4 + profile_key.M4; - - let C_x0 = z * credentials_system.G_x0 + credential.U; - let C_V = z * credentials_system.G_V + credential.V; - let C_x1 = z * credentials_system.G_x1 + credential.t * credential.U; - let C_z = z * credentials_system.G_z; - - let z0 = -z * credential.t; - let z1 = -z * uid_enc_key_pair.a1; - let z2 = -z * profile_key_enc_key_pair.b1; - - let I = credentials_public_key.I; - let Z = z * I; - - // Scalars listed in order of stmts for debugging - let mut scalar_args = poksho::ScalarArgs::new(); - scalar_args.add("z", z); - scalar_args.add("t", credential.t); - scalar_args.add("z0", z0); - scalar_args.add("a1", uid_enc_key_pair.a1); - scalar_args.add("a2", uid_enc_key_pair.a2); - scalar_args.add("b1", profile_key_enc_key_pair.b1); - scalar_args.add("b2", profile_key_enc_key_pair.b2); - scalar_args.add("z1", z1); - scalar_args.add("z2", z2); - - // Points listed in order of stmts for debugging - let mut point_args = poksho::PointArgs::new(); - point_args.add("C_z", C_z); - point_args.add("G_z", credentials_system.G_z); - point_args.add("Z", Z); - point_args.add("I", I); - - point_args.add("C_x1", C_x1); - point_args.add("C_x0", C_x0); - point_args.add("G_x0", credentials_system.G_x0); - point_args.add("G_x1", credentials_system.G_x1); - - point_args.add("A", uid_enc_key_pair.A); - point_args.add("G_a1", uid_system.G_a1); - point_args.add("G_a2", uid_system.G_a2); - - point_args.add("B", profile_key_enc_key_pair.B); - point_args.add("G_b1", profile_key_system.G_b1); - point_args.add("G_b2", profile_key_system.G_b2); - - point_args.add("C_y2-E_A2", C_y2 - uid_ciphertext.E_A2); - point_args.add("G_y2", credentials_system.G_y2); - point_args.add("-E_A1", -uid_ciphertext.E_A1); - point_args.add("E_A1", uid_ciphertext.E_A1); - point_args.add("C_y1", C_y1); - point_args.add("G_y1", credentials_system.G_y1); - - point_args.add("C_y4-E_B2", C_y4 - profile_key_ciphertext.E_B2); - point_args.add("G_y4", credentials_system.G_y4); - point_args.add("-E_B1", -profile_key_ciphertext.E_B1); - point_args.add("E_B1", profile_key_ciphertext.E_B1); - point_args.add("C_y3", C_y3); - point_args.add("G_y3", credentials_system.G_y3); - - let poksho_proof = Self::get_poksho_statement() - .prove( - &scalar_args, - &point_args, - &[], - &sho.squeeze(RANDOMNESS_LEN)[..], - ) - .unwrap(); - - ProfileKeyCredentialPresentationProof { - C_y1, - C_y2, - C_y3, - C_y4, - C_x0, - C_x1, - C_V, - C_z, - poksho_proof, - } - } - - pub fn verify( - &self, - credentials_key_pair: credentials::KeyPair, - uid_ciphertext: uid_encryption::Ciphertext, - uid_enc_public_key: uid_encryption::PublicKey, - profile_key_ciphertext: profile_key_encryption::Ciphertext, - profile_key_enc_public_key: profile_key_encryption::PublicKey, - ) -> Result<(), ZkGroupError> { - let uid_enc_system = uid_encryption::SystemParams::get_hardcoded(); - let profile_key_enc_system = profile_key_encryption::SystemParams::get_hardcoded(); - let credentials_system = credentials::SystemParams::get_hardcoded(); - - let Self { - C_x0, - C_x1, - C_y1, - C_y2, - C_y3, - C_y4, - C_V, - C_z, - poksho_proof, - } = self; - - let (C_x0, C_x1, C_y1, C_y2, C_y3, C_y4, C_V, C_z) = - (*C_x0, *C_x1, *C_y1, *C_y2, *C_y3, *C_y4, *C_V, *C_z); - - let credentials::KeyPair { - W, - x0, - x1, - y1, - y2, - y3, - y4, - I, - .. - } = credentials_key_pair; - - let Z = - C_V - W - x0 * C_x0 - x1 * C_x1 - (y1 * C_y1) - (y2 * C_y2) - (y3 * C_y3) - (y4 * C_y4); - - // Points listed in order of stmts for debugging - let mut point_args = poksho::PointArgs::new(); - point_args.add("C_z", C_z); - point_args.add("G_z", credentials_system.G_z); - point_args.add("Z", Z); - point_args.add("I", I); - point_args.add("C_x1", C_x1); - point_args.add("C_x0", C_x0); - point_args.add("G_x0", credentials_system.G_x0); - point_args.add("G_x1", credentials_system.G_x1); - - point_args.add("A", uid_enc_public_key.A); - point_args.add("G_a1", uid_enc_system.G_a1); - point_args.add("G_a2", uid_enc_system.G_a2); - - point_args.add("B", profile_key_enc_public_key.B); - point_args.add("G_b1", profile_key_enc_system.G_b1); - point_args.add("G_b2", profile_key_enc_system.G_b2); - - point_args.add("C_y2-E_A2", C_y2 - uid_ciphertext.E_A2); - point_args.add("G_y2", credentials_system.G_y2); - point_args.add("-E_A1", -uid_ciphertext.E_A1); - point_args.add("E_A1", uid_ciphertext.E_A1); - point_args.add("C_y1", C_y1); - point_args.add("G_y1", credentials_system.G_y1); - - point_args.add("C_y4-E_B2", C_y4 - profile_key_ciphertext.E_B2); - point_args.add("G_y4", credentials_system.G_y4); - point_args.add("-E_B1", -profile_key_ciphertext.E_B1); - point_args.add("E_B1", profile_key_ciphertext.E_B1); - point_args.add("C_y3", C_y3); - point_args.add("G_y3", credentials_system.G_y3); - - match Self::get_poksho_statement().verify_proof(poksho_proof, &point_args, &[]) { - Err(_) => Err(ZkGroupError::ProofVerificationFailure), - Ok(_) => Ok(()), - } - } -} diff --git a/net/gurk-rs/files/vendor/zkgroup/src/crypto/signature.rs b/net/gurk-rs/files/vendor/zkgroup/src/crypto/signature.rs deleted file mode 100644 index fb635eb..0000000 --- a/net/gurk-rs/files/vendor/zkgroup/src/crypto/signature.rs +++ /dev/null @@ -1,120 +0,0 @@ -// -// Copyright (C) 2020 Signal Messenger, LLC. -// All rights reserved. -// -// SPDX-License-Identifier: GPL-3.0-only -// - -#![allow(non_snake_case)] - -use crate::common::constants::*; -use crate::common::errors::*; -use crate::common::sho::*; -use crate::common::simple_types::*; -use curve25519_dalek::constants::RISTRETTO_BASEPOINT_POINT; -use curve25519_dalek::ristretto::RistrettoPoint; -use curve25519_dalek::scalar::Scalar; -use serde::{Deserialize, Serialize}; - -use ZkGroupError::*; - -#[derive(Copy, Clone, PartialEq, Serialize, Deserialize)] -pub struct KeyPair { - pub(crate) signing_key: Scalar, - pub(crate) public_key: RistrettoPoint, -} - -#[derive(Copy, Clone, PartialEq, Serialize, Deserialize)] -pub struct PublicKey { - pub(crate) public_key: RistrettoPoint, -} - -impl KeyPair { - pub fn generate(sho: &mut Sho) -> Self { - let signing_key = sho.get_scalar(); - let public_key = signing_key * RISTRETTO_BASEPOINT_POINT; - KeyPair { - signing_key, - public_key, - } - } - - // Could return SignatureVerificationFailure if public/private key are inconsistent - pub fn sign(&self, message: &[u8], sho: &mut Sho) -> Result { - match poksho::sign( - self.signing_key, - self.public_key, - message, - &sho.squeeze(RANDOMNESS_LEN)[..], - ) { - Ok(vec_bytes) => { - let mut s: SignatureBytes = [0u8; SIGNATURE_LEN]; - s.copy_from_slice(&vec_bytes[..]); - Ok(s) - } - Err(_) => Err(SignatureVerificationFailure), - } - } - - pub fn get_public_key(&self) -> PublicKey { - PublicKey { - public_key: self.public_key, - } - } -} - -impl PublicKey { - // Might return SignatureVerificationFailure - pub fn verify(&self, message: &[u8], signature: SignatureBytes) -> Result<(), ZkGroupError> { - match poksho::verify_signature(&signature, self.public_key, message) { - Err(_) => Err(SignatureVerificationFailure), - Ok(_) => Ok(()), - } - } -} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_signature() { - let group_key = TEST_ARRAY_32; - let mut sho = Sho::new(b"Test_Signature", &group_key); - let key_pair = KeyPair::generate(&mut sho); - - // Test serialize of key_pair - let key_pair_bytes = bincode::serialize(&key_pair).unwrap(); - assert!(key_pair_bytes.len() == 64); - let public_key_bytes = bincode::serialize(&key_pair.get_public_key()).unwrap(); - assert!(public_key_bytes.len() == 32); - let key_pair2: KeyPair = bincode::deserialize(&key_pair_bytes).unwrap(); - assert!(key_pair == key_pair2); - - let mut message = TEST_ARRAY_32_1; - - let signature = key_pair.sign(&message, &mut sho).unwrap(); - key_pair2 - .get_public_key() - .verify(&message, signature) - .unwrap(); - - // test signature falure - message[0] ^= 1; - match key_pair2.get_public_key().verify(&message, signature) { - Err(SignatureVerificationFailure) => (), - _ => unreachable!(), - } - - println!("signature = {:#x?}", &signature[..]); - let signature_result = [ - 0xdb, 0x9b, 0xfb, 0xd6, 0x15, 0x26, 0xc3, 0x50, 0xf9, 0xbe, 0x95, 0x17, 0x11, 0x6, - 0xd0, 0x6, 0x52, 0x88, 0xcb, 0x33, 0x3, 0x1b, 0xe7, 0x17, 0x25, 0x24, 0x37, 0x80, 0x53, - 0x2c, 0xaa, 0x7, 0xcb, 0xda, 0x74, 0xc4, 0x19, 0x3b, 0x6e, 0xe6, 0xe9, 0x5f, 0xae, - 0xcd, 0x41, 0xfb, 0x44, 0x19, 0xce, 0xae, 0x3f, 0x4d, 0x63, 0xb9, 0x47, 0x59, 0x27, - 0xe1, 0x10, 0xee, 0xb7, 0x72, 0xb, 0x6, - ]; - - assert!(signature[..] == signature_result[..]); - } -} diff --git a/net/gurk-rs/files/vendor/zkgroup/src/crypto/uid_encryption.rs b/net/gurk-rs/files/vendor/zkgroup/src/crypto/uid_encryption.rs deleted file mode 100644 index 6463644..0000000 --- a/net/gurk-rs/files/vendor/zkgroup/src/crypto/uid_encryption.rs +++ /dev/null @@ -1,160 +0,0 @@ -// -// Copyright (C) 2020 Signal Messenger, LLC. -// All rights reserved. -// -// SPDX-License-Identifier: GPL-3.0-only -// - -#![allow(non_snake_case)] - -use crate::common::errors::*; -use crate::common::sho::*; -use crate::crypto::uid_struct; -use curve25519_dalek::constants::RISTRETTO_BASEPOINT_POINT; -use curve25519_dalek::ristretto::RistrettoPoint; -use curve25519_dalek::scalar::Scalar; -use serde::{Deserialize, Serialize}; - -use ZkGroupError::*; - -#[derive(Copy, Clone, PartialEq, Serialize, Deserialize)] -pub struct SystemParams { - pub(crate) G_a1: RistrettoPoint, - pub(crate) G_a2: RistrettoPoint, -} - -#[derive(Copy, Clone, PartialEq, Serialize, Deserialize)] -pub struct KeyPair { - pub(crate) a1: Scalar, - pub(crate) a2: Scalar, - pub(crate) A: RistrettoPoint, -} - -#[derive(Copy, Clone, PartialEq, Serialize, Deserialize)] -pub struct PublicKey { - pub(crate) A: RistrettoPoint, -} - -#[derive(Copy, Clone, Default, PartialEq, Serialize, Deserialize)] -pub struct Ciphertext { - pub(crate) E_A1: RistrettoPoint, - pub(crate) E_A2: RistrettoPoint, -} - -impl SystemParams { - pub fn generate() -> Self { - let mut sho = Sho::new( - b"Signal_ZKGroup_20200424_Constant_UidEncryption_SystemParams_Generate", - b"", - ); - let G_a1 = sho.get_point(); - let G_a2 = sho.get_point(); - SystemParams { G_a1, G_a2 } - } - - pub fn get_hardcoded() -> SystemParams { - bincode::deserialize::(&SystemParams::SYSTEM_HARDCODED).unwrap() - } - - const SYSTEM_HARDCODED: [u8; 64] = [ - 0xa6, 0x32, 0x4c, 0x36, 0x8d, 0xf7, 0x34, 0x69, 0x11, 0x47, 0x98, 0x13, 0x48, 0xb6, 0xe7, - 0xeb, 0x42, 0xc3, 0x30, 0x7e, 0x71, 0x1b, 0x6c, 0x7e, 0xcc, 0xd3, 0x3, 0x2d, 0x45, 0x69, - 0x3f, 0x5a, 0x4, 0x80, 0x13, 0x52, 0x5b, 0x76, 0x12, 0x4b, 0xf2, 0x64, 0xc, 0x5e, 0x93, - 0x69, 0xc7, 0x6e, 0xfb, 0xe8, 0xa, 0xba, 0x2a, 0x24, 0xaa, 0x5d, 0x8e, 0x18, 0xa9, 0x8e, - 0xba, 0x14, 0xf8, 0x37, - ]; -} - -impl KeyPair { - pub fn derive_from(sho: &mut Sho) -> Self { - let system = SystemParams::get_hardcoded(); - - let a1 = sho.get_scalar(); - let a2 = sho.get_scalar(); - - let A = a1 * system.G_a1 + a2 * system.G_a2; - KeyPair { a1, a2, A } - } - - pub fn encrypt(&self, uid: uid_struct::UidStruct) -> Ciphertext { - let E_A1 = self.calc_E_A1(uid); - let E_A2 = (self.a2 * E_A1) + uid.M2; - Ciphertext { E_A1, E_A2 } - } - - // Might return DecryptionFailure - pub fn decrypt(&self, ciphertext: Ciphertext) -> Result { - if ciphertext.E_A1 == RISTRETTO_BASEPOINT_POINT { - return Err(DecryptionFailure); - } - match uid_struct::UidStruct::from_M2(ciphertext.E_A2 - (self.a2 * ciphertext.E_A1)) { - Err(_) => Err(DecryptionFailure), - Ok(decrypted_uid) => { - if ciphertext.E_A1 == self.calc_E_A1(decrypted_uid) { - Ok(decrypted_uid) - } else { - Err(DecryptionFailure) - } - } - } - } - - fn calc_E_A1(&self, uid: uid_struct::UidStruct) -> RistrettoPoint { - self.a1 * uid.M1 - } - - pub fn get_public_key(&self) -> PublicKey { - PublicKey { A: self.A } - } -} - -#[cfg(test)] -mod tests { - use super::*; - use crate::common::constants::*; - - #[test] - fn test_uid_encryption() { - let master_key = TEST_ARRAY_32; - let mut sho = Sho::new(b"Test_Uid_Encryption", &master_key); - - //let system = SystemParams::generate(); - //println!("PARAMS = {:#x?}", bincode::serialize(&system)); - assert!(SystemParams::generate() == SystemParams::get_hardcoded()); - - let key_pair = KeyPair::derive_from(&mut sho); - - // Test serialize of key_pair - let key_pair_bytes = bincode::serialize(&key_pair).unwrap(); - match bincode::deserialize::(&key_pair_bytes[0..key_pair_bytes.len() - 1]) { - Err(_) => (), - _ => unreachable!(), - }; - let key_pair2: KeyPair = bincode::deserialize(&key_pair_bytes).unwrap(); - assert!(key_pair == key_pair2); - - let uid = uid_struct::UidStruct::new(TEST_ARRAY_16); - let ciphertext = key_pair.encrypt(uid); - - // Test serialize / deserialize of Ciphertext - let ciphertext_bytes = bincode::serialize(&ciphertext).unwrap(); - assert!(ciphertext_bytes.len() == 64); - let ciphertext2: Ciphertext = bincode::deserialize(&ciphertext_bytes).unwrap(); - assert!(ciphertext == ciphertext2); - //println!("ciphertext_bytes = {:#x?}", ciphertext_bytes); - assert!( - ciphertext_bytes - == vec![ - 0xf8, 0x9e, 0xe7, 0x70, 0x5a, 0x66, 0x3, 0x6b, 0x90, 0x8d, 0xb8, 0x84, 0x21, - 0x1b, 0x77, 0x3a, 0xc5, 0x43, 0xee, 0x35, 0xc4, 0xa3, 0x8, 0x62, 0x20, 0xfc, - 0x3e, 0x1e, 0x35, 0xb4, 0x23, 0x4c, 0xfa, 0x1d, 0x2e, 0xea, 0x2c, 0xc2, 0xf4, - 0xb4, 0xc4, 0x2c, 0xff, 0x39, 0xa9, 0xdc, 0xeb, 0x57, 0x29, 0x3b, 0x5f, 0x87, - 0x70, 0xca, 0x60, 0xf9, 0xe9, 0xb7, 0x44, 0x47, 0xbf, 0xd3, 0xbd, 0x3d, - ] - ); - - let plaintext = key_pair.decrypt(ciphertext2).unwrap(); - - assert!(plaintext == uid); - } -} diff --git a/net/gurk-rs/files/vendor/zkgroup/src/crypto/uid_struct.rs b/net/gurk-rs/files/vendor/zkgroup/src/crypto/uid_struct.rs deleted file mode 100644 index e993c53..0000000 --- a/net/gurk-rs/files/vendor/zkgroup/src/crypto/uid_struct.rs +++ /dev/null @@ -1,49 +0,0 @@ -// -// Copyright (C) 2020 Signal Messenger, LLC. -// All rights reserved. -// -// SPDX-License-Identifier: GPL-3.0-only -// - -#![allow(non_snake_case)] - -use crate::common::errors::*; -use crate::common::sho::*; -use crate::common::simple_types::*; -use curve25519_dalek::ristretto::RistrettoPoint; -use serde::{Deserialize, Serialize}; -use sha2::Sha256; - -use ZkGroupError::*; - -#[derive(Copy, Clone, PartialEq, Serialize, Deserialize)] -pub struct UidStruct { - pub(crate) bytes: UidBytes, - pub(crate) M1: RistrettoPoint, - pub(crate) M2: RistrettoPoint, -} - -impl UidStruct { - pub fn new(uid_bytes: UidBytes) -> Self { - let mut sho = Sho::new(b"Signal_ZKGroup_20200424_UID_CalcM1", &uid_bytes); - let M1 = sho.get_point(); - let M2 = RistrettoPoint::lizard_encode::(&uid_bytes); - UidStruct { - bytes: uid_bytes, - M1, - M2, - } - } - - // Might return PointDecodeFailure - pub fn from_M2(M2: RistrettoPoint) -> Result { - match M2.lizard_decode::() { - None => Err(PointDecodeFailure), - Some(bytes) => Ok(Self::new(bytes)), - } - } - - pub fn to_bytes(&self) -> UidBytes { - self.bytes - } -} diff --git a/net/gurk-rs/files/vendor/zkgroup/src/ffi/constants.rs b/net/gurk-rs/files/vendor/zkgroup/src/ffi/constants.rs deleted file mode 100644 index 594edff..0000000 --- a/net/gurk-rs/files/vendor/zkgroup/src/ffi/constants.rs +++ /dev/null @@ -1,12 +0,0 @@ -// -// Copyright (C) 2020 Signal Messenger, LLC. -// All rights reserved. -// -// SPDX-License-Identifier: GPL-3.0-only -// - -#![allow(non_snake_case)] - -pub const FFI_RETURN_OK: i32 = 0; -pub const FFI_RETURN_INTERNAL_ERROR: i32 = 1; // ZkGroupError -pub const FFI_RETURN_INPUT_ERROR: i32 = 2; diff --git a/net/gurk-rs/files/vendor/zkgroup/src/ffi/ffiapi.rs b/net/gurk-rs/files/vendor/zkgroup/src/ffi/ffiapi.rs deleted file mode 100644 index 810afe3..0000000 --- a/net/gurk-rs/files/vendor/zkgroup/src/ffi/ffiapi.rs +++ /dev/null @@ -1,1324 +0,0 @@ -// -// Copyright (C) 2020 Signal Messenger, LLC. -// All rights reserved. -// -// SPDX-License-Identifier: GPL-3.0-only -// - -// Generated by zkgroup/codegen/codegen.py - do not edit - -#![allow(non_snake_case)] - -use super::simpleapi; -use crate::ffi::constants::FFI_RETURN_INTERNAL_ERROR; -use std::{panic, slice}; - -#[no_mangle] -pub extern "C" fn FFI_ProfileKey_getCommitment( - profileKey: *const u8, - profileKeyLen: u32, - uuid: *const u8, - uuidLen: u32, - profileKeyCommitmentOut: *mut u8, - profileKeyCommitmentLen: u32, -) -> i32 { - let result = panic::catch_unwind(|| { - let profile_key: &[u8] = - unsafe { slice::from_raw_parts(profileKey, profileKeyLen as usize) }; - let uuid: &[u8] = unsafe { slice::from_raw_parts(uuid, uuidLen as usize) }; - let profile_key_commitment: &mut [u8] = unsafe { - slice::from_raw_parts_mut(profileKeyCommitmentOut, profileKeyCommitmentLen as usize) - }; - - simpleapi::ProfileKey_getCommitment(profile_key, uuid, profile_key_commitment) - }); - - match result { - Ok(result) => result, - Err(_) => FFI_RETURN_INTERNAL_ERROR, - } -} - -#[no_mangle] -pub extern "C" fn FFI_ProfileKey_getProfileKeyVersion( - profileKey: *const u8, - profileKeyLen: u32, - uuid: *const u8, - uuidLen: u32, - profileKeyVersionOut: *mut u8, - profileKeyVersionLen: u32, -) -> i32 { - let result = panic::catch_unwind(|| { - let profile_key: &[u8] = - unsafe { slice::from_raw_parts(profileKey, profileKeyLen as usize) }; - let uuid: &[u8] = unsafe { slice::from_raw_parts(uuid, uuidLen as usize) }; - let profile_key_version: &mut [u8] = unsafe { - slice::from_raw_parts_mut(profileKeyVersionOut, profileKeyVersionLen as usize) - }; - - simpleapi::ProfileKey_getProfileKeyVersion(profile_key, uuid, profile_key_version) - }); - - match result { - Ok(result) => result, - Err(_) => FFI_RETURN_INTERNAL_ERROR, - } -} - -#[no_mangle] -pub extern "C" fn FFI_ProfileKeyCommitment_checkValidContents( - profileKeyCommitment: *const u8, - profileKeyCommitmentLen: u32, -) -> i32 { - let result = panic::catch_unwind(|| { - let profile_key_commitment: &[u8] = unsafe { - slice::from_raw_parts(profileKeyCommitment, profileKeyCommitmentLen as usize) - }; - - simpleapi::ProfileKeyCommitment_checkValidContents(profile_key_commitment) - }); - - match result { - Ok(result) => result, - Err(_) => FFI_RETURN_INTERNAL_ERROR, - } -} - -#[no_mangle] -pub extern "C" fn FFI_GroupSecretParams_generateDeterministic( - randomness: *const u8, - randomnessLen: u32, - groupSecretParamsOut: *mut u8, - groupSecretParamsLen: u32, -) -> i32 { - let result = panic::catch_unwind(|| { - let randomness: &[u8] = - unsafe { slice::from_raw_parts(randomness, randomnessLen as usize) }; - let group_secret_params: &mut [u8] = unsafe { - slice::from_raw_parts_mut(groupSecretParamsOut, groupSecretParamsLen as usize) - }; - - simpleapi::GroupSecretParams_generateDeterministic(randomness, group_secret_params) - }); - - match result { - Ok(result) => result, - Err(_) => FFI_RETURN_INTERNAL_ERROR, - } -} - -#[no_mangle] -pub extern "C" fn FFI_GroupSecretParams_deriveFromMasterKey( - groupMasterKey: *const u8, - groupMasterKeyLen: u32, - groupSecretParamsOut: *mut u8, - groupSecretParamsLen: u32, -) -> i32 { - let result = panic::catch_unwind(|| { - let group_master_key: &[u8] = - unsafe { slice::from_raw_parts(groupMasterKey, groupMasterKeyLen as usize) }; - let group_secret_params: &mut [u8] = unsafe { - slice::from_raw_parts_mut(groupSecretParamsOut, groupSecretParamsLen as usize) - }; - - simpleapi::GroupSecretParams_deriveFromMasterKey(group_master_key, group_secret_params) - }); - - match result { - Ok(result) => result, - Err(_) => FFI_RETURN_INTERNAL_ERROR, - } -} - -#[no_mangle] -pub extern "C" fn FFI_GroupSecretParams_checkValidContents( - groupSecretParams: *const u8, - groupSecretParamsLen: u32, -) -> i32 { - let result = panic::catch_unwind(|| { - let group_secret_params: &[u8] = - unsafe { slice::from_raw_parts(groupSecretParams, groupSecretParamsLen as usize) }; - - simpleapi::GroupSecretParams_checkValidContents(group_secret_params) - }); - - match result { - Ok(result) => result, - Err(_) => FFI_RETURN_INTERNAL_ERROR, - } -} - -#[no_mangle] -pub extern "C" fn FFI_GroupSecretParams_getMasterKey( - groupSecretParams: *const u8, - groupSecretParamsLen: u32, - groupMasterKeyOut: *mut u8, - groupMasterKeyLen: u32, -) -> i32 { - let result = panic::catch_unwind(|| { - let group_secret_params: &[u8] = - unsafe { slice::from_raw_parts(groupSecretParams, groupSecretParamsLen as usize) }; - let group_master_key: &mut [u8] = - unsafe { slice::from_raw_parts_mut(groupMasterKeyOut, groupMasterKeyLen as usize) }; - - simpleapi::GroupSecretParams_getMasterKey(group_secret_params, group_master_key) - }); - - match result { - Ok(result) => result, - Err(_) => FFI_RETURN_INTERNAL_ERROR, - } -} - -#[no_mangle] -pub extern "C" fn FFI_GroupSecretParams_getPublicParams( - groupSecretParams: *const u8, - groupSecretParamsLen: u32, - groupPublicParamsOut: *mut u8, - groupPublicParamsLen: u32, -) -> i32 { - let result = panic::catch_unwind(|| { - let group_secret_params: &[u8] = - unsafe { slice::from_raw_parts(groupSecretParams, groupSecretParamsLen as usize) }; - let group_public_params: &mut [u8] = unsafe { - slice::from_raw_parts_mut(groupPublicParamsOut, groupPublicParamsLen as usize) - }; - - simpleapi::GroupSecretParams_getPublicParams(group_secret_params, group_public_params) - }); - - match result { - Ok(result) => result, - Err(_) => FFI_RETURN_INTERNAL_ERROR, - } -} - -#[no_mangle] -pub extern "C" fn FFI_GroupSecretParams_encryptUuid( - groupSecretParams: *const u8, - groupSecretParamsLen: u32, - uuid: *const u8, - uuidLen: u32, - uuidCiphertextOut: *mut u8, - uuidCiphertextLen: u32, -) -> i32 { - let result = panic::catch_unwind(|| { - let group_secret_params: &[u8] = - unsafe { slice::from_raw_parts(groupSecretParams, groupSecretParamsLen as usize) }; - let uuid: &[u8] = unsafe { slice::from_raw_parts(uuid, uuidLen as usize) }; - let uuid_ciphertext: &mut [u8] = - unsafe { slice::from_raw_parts_mut(uuidCiphertextOut, uuidCiphertextLen as usize) }; - - simpleapi::GroupSecretParams_encryptUuid(group_secret_params, uuid, uuid_ciphertext) - }); - - match result { - Ok(result) => result, - Err(_) => FFI_RETURN_INTERNAL_ERROR, - } -} - -#[no_mangle] -pub extern "C" fn FFI_GroupSecretParams_decryptUuid( - groupSecretParams: *const u8, - groupSecretParamsLen: u32, - uuidCiphertext: *const u8, - uuidCiphertextLen: u32, - uuidOut: *mut u8, - uuidLen: u32, -) -> i32 { - let result = panic::catch_unwind(|| { - let group_secret_params: &[u8] = - unsafe { slice::from_raw_parts(groupSecretParams, groupSecretParamsLen as usize) }; - let uuid_ciphertext: &[u8] = - unsafe { slice::from_raw_parts(uuidCiphertext, uuidCiphertextLen as usize) }; - let uuid: &mut [u8] = unsafe { slice::from_raw_parts_mut(uuidOut, uuidLen as usize) }; - - simpleapi::GroupSecretParams_decryptUuid(group_secret_params, uuid_ciphertext, uuid) - }); - - match result { - Ok(result) => result, - Err(_) => FFI_RETURN_INTERNAL_ERROR, - } -} - -#[no_mangle] -pub extern "C" fn FFI_GroupSecretParams_encryptProfileKey( - groupSecretParams: *const u8, - groupSecretParamsLen: u32, - profileKey: *const u8, - profileKeyLen: u32, - uuid: *const u8, - uuidLen: u32, - profileKeyCiphertextOut: *mut u8, - profileKeyCiphertextLen: u32, -) -> i32 { - let result = panic::catch_unwind(|| { - let group_secret_params: &[u8] = - unsafe { slice::from_raw_parts(groupSecretParams, groupSecretParamsLen as usize) }; - let profile_key: &[u8] = - unsafe { slice::from_raw_parts(profileKey, profileKeyLen as usize) }; - let uuid: &[u8] = unsafe { slice::from_raw_parts(uuid, uuidLen as usize) }; - let profile_key_ciphertext: &mut [u8] = unsafe { - slice::from_raw_parts_mut(profileKeyCiphertextOut, profileKeyCiphertextLen as usize) - }; - - simpleapi::GroupSecretParams_encryptProfileKey( - group_secret_params, - profile_key, - uuid, - profile_key_ciphertext, - ) - }); - - match result { - Ok(result) => result, - Err(_) => FFI_RETURN_INTERNAL_ERROR, - } -} - -#[no_mangle] -pub extern "C" fn FFI_GroupSecretParams_decryptProfileKey( - groupSecretParams: *const u8, - groupSecretParamsLen: u32, - profileKeyCiphertext: *const u8, - profileKeyCiphertextLen: u32, - uuid: *const u8, - uuidLen: u32, - profileKeyOut: *mut u8, - profileKeyLen: u32, -) -> i32 { - let result = panic::catch_unwind(|| { - let group_secret_params: &[u8] = - unsafe { slice::from_raw_parts(groupSecretParams, groupSecretParamsLen as usize) }; - let profile_key_ciphertext: &[u8] = unsafe { - slice::from_raw_parts(profileKeyCiphertext, profileKeyCiphertextLen as usize) - }; - let uuid: &[u8] = unsafe { slice::from_raw_parts(uuid, uuidLen as usize) }; - let profile_key: &mut [u8] = - unsafe { slice::from_raw_parts_mut(profileKeyOut, profileKeyLen as usize) }; - - simpleapi::GroupSecretParams_decryptProfileKey( - group_secret_params, - profile_key_ciphertext, - uuid, - profile_key, - ) - }); - - match result { - Ok(result) => result, - Err(_) => FFI_RETURN_INTERNAL_ERROR, - } -} - -#[no_mangle] -pub extern "C" fn FFI_GroupSecretParams_encryptBlobDeterministic( - groupSecretParams: *const u8, - groupSecretParamsLen: u32, - randomness: *const u8, - randomnessLen: u32, - plaintext: *const u8, - plaintextLen: u32, - blobCiphertextOut: *mut u8, - blobCiphertextLen: u32, -) -> i32 { - let result = panic::catch_unwind(|| { - let group_secret_params: &[u8] = - unsafe { slice::from_raw_parts(groupSecretParams, groupSecretParamsLen as usize) }; - let randomness: &[u8] = - unsafe { slice::from_raw_parts(randomness, randomnessLen as usize) }; - let plaintext: &[u8] = unsafe { slice::from_raw_parts(plaintext, plaintextLen as usize) }; - let blob_ciphertext: &mut [u8] = - unsafe { slice::from_raw_parts_mut(blobCiphertextOut, blobCiphertextLen as usize) }; - - simpleapi::GroupSecretParams_encryptBlobDeterministic( - group_secret_params, - randomness, - plaintext, - blob_ciphertext, - ) - }); - - match result { - Ok(result) => result, - Err(_) => FFI_RETURN_INTERNAL_ERROR, - } -} - -#[no_mangle] -pub extern "C" fn FFI_GroupSecretParams_decryptBlob( - groupSecretParams: *const u8, - groupSecretParamsLen: u32, - blobCiphertext: *const u8, - blobCiphertextLen: u32, - plaintextOut: *mut u8, - plaintextLen: u32, -) -> i32 { - let result = panic::catch_unwind(|| { - let group_secret_params: &[u8] = - unsafe { slice::from_raw_parts(groupSecretParams, groupSecretParamsLen as usize) }; - let blob_ciphertext: &[u8] = - unsafe { slice::from_raw_parts(blobCiphertext, blobCiphertextLen as usize) }; - let plaintext: &mut [u8] = - unsafe { slice::from_raw_parts_mut(plaintextOut, plaintextLen as usize) }; - - simpleapi::GroupSecretParams_decryptBlob(group_secret_params, blob_ciphertext, plaintext) - }); - - match result { - Ok(result) => result, - Err(_) => FFI_RETURN_INTERNAL_ERROR, - } -} - -#[no_mangle] -pub extern "C" fn FFI_ServerSecretParams_generateDeterministic( - randomness: *const u8, - randomnessLen: u32, - serverSecretParamsOut: *mut u8, - serverSecretParamsLen: u32, -) -> i32 { - let result = panic::catch_unwind(|| { - let randomness: &[u8] = - unsafe { slice::from_raw_parts(randomness, randomnessLen as usize) }; - let server_secret_params: &mut [u8] = unsafe { - slice::from_raw_parts_mut(serverSecretParamsOut, serverSecretParamsLen as usize) - }; - - simpleapi::ServerSecretParams_generateDeterministic(randomness, server_secret_params) - }); - - match result { - Ok(result) => result, - Err(_) => FFI_RETURN_INTERNAL_ERROR, - } -} - -#[no_mangle] -pub extern "C" fn FFI_ServerSecretParams_checkValidContents( - serverSecretParams: *const u8, - serverSecretParamsLen: u32, -) -> i32 { - let result = panic::catch_unwind(|| { - let server_secret_params: &[u8] = - unsafe { slice::from_raw_parts(serverSecretParams, serverSecretParamsLen as usize) }; - - simpleapi::ServerSecretParams_checkValidContents(server_secret_params) - }); - - match result { - Ok(result) => result, - Err(_) => FFI_RETURN_INTERNAL_ERROR, - } -} - -#[no_mangle] -pub extern "C" fn FFI_ServerSecretParams_getPublicParams( - serverSecretParams: *const u8, - serverSecretParamsLen: u32, - serverPublicParamsOut: *mut u8, - serverPublicParamsLen: u32, -) -> i32 { - let result = panic::catch_unwind(|| { - let server_secret_params: &[u8] = - unsafe { slice::from_raw_parts(serverSecretParams, serverSecretParamsLen as usize) }; - let server_public_params: &mut [u8] = unsafe { - slice::from_raw_parts_mut(serverPublicParamsOut, serverPublicParamsLen as usize) - }; - - simpleapi::ServerSecretParams_getPublicParams(server_secret_params, server_public_params) - }); - - match result { - Ok(result) => result, - Err(_) => FFI_RETURN_INTERNAL_ERROR, - } -} - -#[no_mangle] -pub extern "C" fn FFI_ServerSecretParams_signDeterministic( - serverSecretParams: *const u8, - serverSecretParamsLen: u32, - randomness: *const u8, - randomnessLen: u32, - message: *const u8, - messageLen: u32, - notarySignatureOut: *mut u8, - notarySignatureLen: u32, -) -> i32 { - let result = panic::catch_unwind(|| { - let server_secret_params: &[u8] = - unsafe { slice::from_raw_parts(serverSecretParams, serverSecretParamsLen as usize) }; - let randomness: &[u8] = - unsafe { slice::from_raw_parts(randomness, randomnessLen as usize) }; - let message: &[u8] = unsafe { slice::from_raw_parts(message, messageLen as usize) }; - let notary_signature: &mut [u8] = - unsafe { slice::from_raw_parts_mut(notarySignatureOut, notarySignatureLen as usize) }; - - simpleapi::ServerSecretParams_signDeterministic( - server_secret_params, - randomness, - message, - notary_signature, - ) - }); - - match result { - Ok(result) => result, - Err(_) => FFI_RETURN_INTERNAL_ERROR, - } -} - -#[no_mangle] -pub extern "C" fn FFI_ServerPublicParams_receiveAuthCredential( - serverPublicParams: *const u8, - serverPublicParamsLen: u32, - uuid: *const u8, - uuidLen: u32, - redemptionTime: u32, - authCredentialResponse: *const u8, - authCredentialResponseLen: u32, - authCredentialOut: *mut u8, - authCredentialLen: u32, -) -> i32 { - let result = panic::catch_unwind(|| { - let server_public_params: &[u8] = - unsafe { slice::from_raw_parts(serverPublicParams, serverPublicParamsLen as usize) }; - let uuid: &[u8] = unsafe { slice::from_raw_parts(uuid, uuidLen as usize) }; - let redemption_time = redemptionTime as u32; - let auth_credential_response: &[u8] = unsafe { - slice::from_raw_parts(authCredentialResponse, authCredentialResponseLen as usize) - }; - let auth_credential: &mut [u8] = - unsafe { slice::from_raw_parts_mut(authCredentialOut, authCredentialLen as usize) }; - - simpleapi::ServerPublicParams_receiveAuthCredential( - server_public_params, - uuid, - redemption_time, - auth_credential_response, - auth_credential, - ) - }); - - match result { - Ok(result) => result, - Err(_) => FFI_RETURN_INTERNAL_ERROR, - } -} - -#[no_mangle] -pub extern "C" fn FFI_ServerPublicParams_createAuthCredentialPresentationDeterministic( - serverPublicParams: *const u8, - serverPublicParamsLen: u32, - randomness: *const u8, - randomnessLen: u32, - groupSecretParams: *const u8, - groupSecretParamsLen: u32, - authCredential: *const u8, - authCredentialLen: u32, - authCredentialPresentationOut: *mut u8, - authCredentialPresentationLen: u32, -) -> i32 { - let result = panic::catch_unwind(|| { - let server_public_params: &[u8] = - unsafe { slice::from_raw_parts(serverPublicParams, serverPublicParamsLen as usize) }; - let randomness: &[u8] = - unsafe { slice::from_raw_parts(randomness, randomnessLen as usize) }; - let group_secret_params: &[u8] = - unsafe { slice::from_raw_parts(groupSecretParams, groupSecretParamsLen as usize) }; - let auth_credential: &[u8] = - unsafe { slice::from_raw_parts(authCredential, authCredentialLen as usize) }; - let auth_credential_presentation: &mut [u8] = unsafe { - slice::from_raw_parts_mut( - authCredentialPresentationOut, - authCredentialPresentationLen as usize, - ) - }; - - simpleapi::ServerPublicParams_createAuthCredentialPresentationDeterministic( - server_public_params, - randomness, - group_secret_params, - auth_credential, - auth_credential_presentation, - ) - }); - - match result { - Ok(result) => result, - Err(_) => FFI_RETURN_INTERNAL_ERROR, - } -} - -#[no_mangle] -pub extern "C" fn FFI_ServerPublicParams_createProfileKeyCredentialRequestContextDeterministic( - serverPublicParams: *const u8, - serverPublicParamsLen: u32, - randomness: *const u8, - randomnessLen: u32, - uuid: *const u8, - uuidLen: u32, - profileKey: *const u8, - profileKeyLen: u32, - profileKeyCredentialRequestContextOut: *mut u8, - profileKeyCredentialRequestContextLen: u32, -) -> i32 { - let result = panic::catch_unwind(|| { - let server_public_params: &[u8] = - unsafe { slice::from_raw_parts(serverPublicParams, serverPublicParamsLen as usize) }; - let randomness: &[u8] = - unsafe { slice::from_raw_parts(randomness, randomnessLen as usize) }; - let uuid: &[u8] = unsafe { slice::from_raw_parts(uuid, uuidLen as usize) }; - let profile_key: &[u8] = - unsafe { slice::from_raw_parts(profileKey, profileKeyLen as usize) }; - let profile_key_credential_request_context: &mut [u8] = unsafe { - slice::from_raw_parts_mut( - profileKeyCredentialRequestContextOut, - profileKeyCredentialRequestContextLen as usize, - ) - }; - - simpleapi::ServerPublicParams_createProfileKeyCredentialRequestContextDeterministic( - server_public_params, - randomness, - uuid, - profile_key, - profile_key_credential_request_context, - ) - }); - - match result { - Ok(result) => result, - Err(_) => FFI_RETURN_INTERNAL_ERROR, - } -} - -#[no_mangle] -pub extern "C" fn FFI_ServerPublicParams_receiveProfileKeyCredential( - serverPublicParams: *const u8, - serverPublicParamsLen: u32, - profileKeyCredentialRequestContext: *const u8, - profileKeyCredentialRequestContextLen: u32, - profileKeyCredentialResponse: *const u8, - profileKeyCredentialResponseLen: u32, - profileKeyCredentialOut: *mut u8, - profileKeyCredentialLen: u32, -) -> i32 { - let result = panic::catch_unwind(|| { - let server_public_params: &[u8] = - unsafe { slice::from_raw_parts(serverPublicParams, serverPublicParamsLen as usize) }; - let profile_key_credential_request_context: &[u8] = unsafe { - slice::from_raw_parts( - profileKeyCredentialRequestContext, - profileKeyCredentialRequestContextLen as usize, - ) - }; - let profile_key_credential_response: &[u8] = unsafe { - slice::from_raw_parts( - profileKeyCredentialResponse, - profileKeyCredentialResponseLen as usize, - ) - }; - let profile_key_credential: &mut [u8] = unsafe { - slice::from_raw_parts_mut(profileKeyCredentialOut, profileKeyCredentialLen as usize) - }; - - simpleapi::ServerPublicParams_receiveProfileKeyCredential( - server_public_params, - profile_key_credential_request_context, - profile_key_credential_response, - profile_key_credential, - ) - }); - - match result { - Ok(result) => result, - Err(_) => FFI_RETURN_INTERNAL_ERROR, - } -} - -#[no_mangle] -pub extern "C" fn FFI_ServerPublicParams_createProfileKeyCredentialPresentationDeterministic( - serverPublicParams: *const u8, - serverPublicParamsLen: u32, - randomness: *const u8, - randomnessLen: u32, - groupSecretParams: *const u8, - groupSecretParamsLen: u32, - profileKeyCredential: *const u8, - profileKeyCredentialLen: u32, - profileKeyCredentialPresentationOut: *mut u8, - profileKeyCredentialPresentationLen: u32, -) -> i32 { - let result = panic::catch_unwind(|| { - let server_public_params: &[u8] = - unsafe { slice::from_raw_parts(serverPublicParams, serverPublicParamsLen as usize) }; - let randomness: &[u8] = - unsafe { slice::from_raw_parts(randomness, randomnessLen as usize) }; - let group_secret_params: &[u8] = - unsafe { slice::from_raw_parts(groupSecretParams, groupSecretParamsLen as usize) }; - let profile_key_credential: &[u8] = unsafe { - slice::from_raw_parts(profileKeyCredential, profileKeyCredentialLen as usize) - }; - let profile_key_credential_presentation: &mut [u8] = unsafe { - slice::from_raw_parts_mut( - profileKeyCredentialPresentationOut, - profileKeyCredentialPresentationLen as usize, - ) - }; - - simpleapi::ServerPublicParams_createProfileKeyCredentialPresentationDeterministic( - server_public_params, - randomness, - group_secret_params, - profile_key_credential, - profile_key_credential_presentation, - ) - }); - - match result { - Ok(result) => result, - Err(_) => FFI_RETURN_INTERNAL_ERROR, - } -} - -#[no_mangle] -pub extern "C" fn FFI_ServerSecretParams_issueAuthCredentialDeterministic( - serverSecretParams: *const u8, - serverSecretParamsLen: u32, - randomness: *const u8, - randomnessLen: u32, - uuid: *const u8, - uuidLen: u32, - redemptionTime: u32, - authCredentialResponseOut: *mut u8, - authCredentialResponseLen: u32, -) -> i32 { - let result = panic::catch_unwind(|| { - let server_secret_params: &[u8] = - unsafe { slice::from_raw_parts(serverSecretParams, serverSecretParamsLen as usize) }; - let randomness: &[u8] = - unsafe { slice::from_raw_parts(randomness, randomnessLen as usize) }; - let uuid: &[u8] = unsafe { slice::from_raw_parts(uuid, uuidLen as usize) }; - let redemption_time = redemptionTime as u32; - let auth_credential_response: &mut [u8] = unsafe { - slice::from_raw_parts_mut( - authCredentialResponseOut, - authCredentialResponseLen as usize, - ) - }; - - simpleapi::ServerSecretParams_issueAuthCredentialDeterministic( - server_secret_params, - randomness, - uuid, - redemption_time, - auth_credential_response, - ) - }); - - match result { - Ok(result) => result, - Err(_) => FFI_RETURN_INTERNAL_ERROR, - } -} - -#[no_mangle] -pub extern "C" fn FFI_ServerSecretParams_verifyAuthCredentialPresentation( - serverSecretParams: *const u8, - serverSecretParamsLen: u32, - groupPublicParams: *const u8, - groupPublicParamsLen: u32, - authCredentialPresentation: *const u8, - authCredentialPresentationLen: u32, -) -> i32 { - let result = panic::catch_unwind(|| { - let server_secret_params: &[u8] = - unsafe { slice::from_raw_parts(serverSecretParams, serverSecretParamsLen as usize) }; - let group_public_params: &[u8] = - unsafe { slice::from_raw_parts(groupPublicParams, groupPublicParamsLen as usize) }; - let auth_credential_presentation: &[u8] = unsafe { - slice::from_raw_parts( - authCredentialPresentation, - authCredentialPresentationLen as usize, - ) - }; - - simpleapi::ServerSecretParams_verifyAuthCredentialPresentation( - server_secret_params, - group_public_params, - auth_credential_presentation, - ) - }); - - match result { - Ok(result) => result, - Err(_) => FFI_RETURN_INTERNAL_ERROR, - } -} - -#[no_mangle] -pub extern "C" fn FFI_ServerSecretParams_issueProfileKeyCredentialDeterministic( - serverSecretParams: *const u8, - serverSecretParamsLen: u32, - randomness: *const u8, - randomnessLen: u32, - profileKeyCredentialRequest: *const u8, - profileKeyCredentialRequestLen: u32, - uuid: *const u8, - uuidLen: u32, - profileKeyCommitment: *const u8, - profileKeyCommitmentLen: u32, - profileKeyCredentialResponseOut: *mut u8, - profileKeyCredentialResponseLen: u32, -) -> i32 { - let result = panic::catch_unwind(|| { - let server_secret_params: &[u8] = - unsafe { slice::from_raw_parts(serverSecretParams, serverSecretParamsLen as usize) }; - let randomness: &[u8] = - unsafe { slice::from_raw_parts(randomness, randomnessLen as usize) }; - let profile_key_credential_request: &[u8] = unsafe { - slice::from_raw_parts( - profileKeyCredentialRequest, - profileKeyCredentialRequestLen as usize, - ) - }; - let uuid: &[u8] = unsafe { slice::from_raw_parts(uuid, uuidLen as usize) }; - let profile_key_commitment: &[u8] = unsafe { - slice::from_raw_parts(profileKeyCommitment, profileKeyCommitmentLen as usize) - }; - let profile_key_credential_response: &mut [u8] = unsafe { - slice::from_raw_parts_mut( - profileKeyCredentialResponseOut, - profileKeyCredentialResponseLen as usize, - ) - }; - - simpleapi::ServerSecretParams_issueProfileKeyCredentialDeterministic( - server_secret_params, - randomness, - profile_key_credential_request, - uuid, - profile_key_commitment, - profile_key_credential_response, - ) - }); - - match result { - Ok(result) => result, - Err(_) => FFI_RETURN_INTERNAL_ERROR, - } -} - -#[no_mangle] -pub extern "C" fn FFI_ServerSecretParams_verifyProfileKeyCredentialPresentation( - serverSecretParams: *const u8, - serverSecretParamsLen: u32, - groupPublicParams: *const u8, - groupPublicParamsLen: u32, - profileKeyCredentialPresentation: *const u8, - profileKeyCredentialPresentationLen: u32, -) -> i32 { - let result = panic::catch_unwind(|| { - let server_secret_params: &[u8] = - unsafe { slice::from_raw_parts(serverSecretParams, serverSecretParamsLen as usize) }; - let group_public_params: &[u8] = - unsafe { slice::from_raw_parts(groupPublicParams, groupPublicParamsLen as usize) }; - let profile_key_credential_presentation: &[u8] = unsafe { - slice::from_raw_parts( - profileKeyCredentialPresentation, - profileKeyCredentialPresentationLen as usize, - ) - }; - - simpleapi::ServerSecretParams_verifyProfileKeyCredentialPresentation( - server_secret_params, - group_public_params, - profile_key_credential_presentation, - ) - }); - - match result { - Ok(result) => result, - Err(_) => FFI_RETURN_INTERNAL_ERROR, - } -} - -#[no_mangle] -pub extern "C" fn FFI_GroupPublicParams_checkValidContents( - groupPublicParams: *const u8, - groupPublicParamsLen: u32, -) -> i32 { - let result = panic::catch_unwind(|| { - let group_public_params: &[u8] = - unsafe { slice::from_raw_parts(groupPublicParams, groupPublicParamsLen as usize) }; - - simpleapi::GroupPublicParams_checkValidContents(group_public_params) - }); - - match result { - Ok(result) => result, - Err(_) => FFI_RETURN_INTERNAL_ERROR, - } -} - -#[no_mangle] -pub extern "C" fn FFI_GroupPublicParams_getGroupIdentifier( - groupPublicParams: *const u8, - groupPublicParamsLen: u32, - groupIdentifierOut: *mut u8, - groupIdentifierLen: u32, -) -> i32 { - let result = panic::catch_unwind(|| { - let group_public_params: &[u8] = - unsafe { slice::from_raw_parts(groupPublicParams, groupPublicParamsLen as usize) }; - let group_identifier: &mut [u8] = - unsafe { slice::from_raw_parts_mut(groupIdentifierOut, groupIdentifierLen as usize) }; - - simpleapi::GroupPublicParams_getGroupIdentifier(group_public_params, group_identifier) - }); - - match result { - Ok(result) => result, - Err(_) => FFI_RETURN_INTERNAL_ERROR, - } -} - -#[no_mangle] -pub extern "C" fn FFI_ServerPublicParams_checkValidContents( - serverPublicParams: *const u8, - serverPublicParamsLen: u32, -) -> i32 { - let result = panic::catch_unwind(|| { - let server_public_params: &[u8] = - unsafe { slice::from_raw_parts(serverPublicParams, serverPublicParamsLen as usize) }; - - simpleapi::ServerPublicParams_checkValidContents(server_public_params) - }); - - match result { - Ok(result) => result, - Err(_) => FFI_RETURN_INTERNAL_ERROR, - } -} - -#[no_mangle] -pub extern "C" fn FFI_ServerPublicParams_verifySignature( - serverPublicParams: *const u8, - serverPublicParamsLen: u32, - message: *const u8, - messageLen: u32, - notarySignature: *const u8, - notarySignatureLen: u32, -) -> i32 { - let result = panic::catch_unwind(|| { - let server_public_params: &[u8] = - unsafe { slice::from_raw_parts(serverPublicParams, serverPublicParamsLen as usize) }; - let message: &[u8] = unsafe { slice::from_raw_parts(message, messageLen as usize) }; - let notary_signature: &[u8] = - unsafe { slice::from_raw_parts(notarySignature, notarySignatureLen as usize) }; - - simpleapi::ServerPublicParams_verifySignature( - server_public_params, - message, - notary_signature, - ) - }); - - match result { - Ok(result) => result, - Err(_) => FFI_RETURN_INTERNAL_ERROR, - } -} - -#[no_mangle] -pub extern "C" fn FFI_AuthCredentialResponse_checkValidContents( - authCredentialResponse: *const u8, - authCredentialResponseLen: u32, -) -> i32 { - let result = panic::catch_unwind(|| { - let auth_credential_response: &[u8] = unsafe { - slice::from_raw_parts(authCredentialResponse, authCredentialResponseLen as usize) - }; - - simpleapi::AuthCredentialResponse_checkValidContents(auth_credential_response) - }); - - match result { - Ok(result) => result, - Err(_) => FFI_RETURN_INTERNAL_ERROR, - } -} - -#[no_mangle] -pub extern "C" fn FFI_AuthCredential_checkValidContents( - authCredential: *const u8, - authCredentialLen: u32, -) -> i32 { - let result = panic::catch_unwind(|| { - let auth_credential: &[u8] = - unsafe { slice::from_raw_parts(authCredential, authCredentialLen as usize) }; - - simpleapi::AuthCredential_checkValidContents(auth_credential) - }); - - match result { - Ok(result) => result, - Err(_) => FFI_RETURN_INTERNAL_ERROR, - } -} - -#[no_mangle] -pub extern "C" fn FFI_AuthCredentialPresentation_checkValidContents( - authCredentialPresentation: *const u8, - authCredentialPresentationLen: u32, -) -> i32 { - let result = panic::catch_unwind(|| { - let auth_credential_presentation: &[u8] = unsafe { - slice::from_raw_parts( - authCredentialPresentation, - authCredentialPresentationLen as usize, - ) - }; - - simpleapi::AuthCredentialPresentation_checkValidContents(auth_credential_presentation) - }); - - match result { - Ok(result) => result, - Err(_) => FFI_RETURN_INTERNAL_ERROR, - } -} - -#[no_mangle] -pub extern "C" fn FFI_AuthCredentialPresentation_getUuidCiphertext( - authCredentialPresentation: *const u8, - authCredentialPresentationLen: u32, - uuidCiphertextOut: *mut u8, - uuidCiphertextLen: u32, -) -> i32 { - let result = panic::catch_unwind(|| { - let auth_credential_presentation: &[u8] = unsafe { - slice::from_raw_parts( - authCredentialPresentation, - authCredentialPresentationLen as usize, - ) - }; - let uuid_ciphertext: &mut [u8] = - unsafe { slice::from_raw_parts_mut(uuidCiphertextOut, uuidCiphertextLen as usize) }; - - simpleapi::AuthCredentialPresentation_getUuidCiphertext( - auth_credential_presentation, - uuid_ciphertext, - ) - }); - - match result { - Ok(result) => result, - Err(_) => FFI_RETURN_INTERNAL_ERROR, - } -} - -#[no_mangle] -pub extern "C" fn FFI_AuthCredentialPresentation_getRedemptionTime( - authCredentialPresentation: *const u8, - authCredentialPresentationLen: u32, - redemptionTimeOut: *mut u8, - redemptionTimeLen: u32, -) -> i32 { - let result = panic::catch_unwind(|| { - let auth_credential_presentation: &[u8] = unsafe { - slice::from_raw_parts( - authCredentialPresentation, - authCredentialPresentationLen as usize, - ) - }; - let redemption_time: &mut [u8] = - unsafe { slice::from_raw_parts_mut(redemptionTimeOut, redemptionTimeLen as usize) }; - - simpleapi::AuthCredentialPresentation_getRedemptionTime( - auth_credential_presentation, - redemption_time, - ) - }); - - match result { - Ok(result) => result, - Err(_) => FFI_RETURN_INTERNAL_ERROR, - } -} - -#[no_mangle] -pub extern "C" fn FFI_ProfileKeyCredentialRequestContext_checkValidContents( - profileKeyCredentialRequestContext: *const u8, - profileKeyCredentialRequestContextLen: u32, -) -> i32 { - let result = panic::catch_unwind(|| { - let profile_key_credential_request_context: &[u8] = unsafe { - slice::from_raw_parts( - profileKeyCredentialRequestContext, - profileKeyCredentialRequestContextLen as usize, - ) - }; - - simpleapi::ProfileKeyCredentialRequestContext_checkValidContents( - profile_key_credential_request_context, - ) - }); - - match result { - Ok(result) => result, - Err(_) => FFI_RETURN_INTERNAL_ERROR, - } -} - -#[no_mangle] -pub extern "C" fn FFI_ProfileKeyCredentialRequestContext_getRequest( - profileKeyCredentialRequestContext: *const u8, - profileKeyCredentialRequestContextLen: u32, - profileKeyCredentialRequestOut: *mut u8, - profileKeyCredentialRequestLen: u32, -) -> i32 { - let result = panic::catch_unwind(|| { - let profile_key_credential_request_context: &[u8] = unsafe { - slice::from_raw_parts( - profileKeyCredentialRequestContext, - profileKeyCredentialRequestContextLen as usize, - ) - }; - let profile_key_credential_request: &mut [u8] = unsafe { - slice::from_raw_parts_mut( - profileKeyCredentialRequestOut, - profileKeyCredentialRequestLen as usize, - ) - }; - - simpleapi::ProfileKeyCredentialRequestContext_getRequest( - profile_key_credential_request_context, - profile_key_credential_request, - ) - }); - - match result { - Ok(result) => result, - Err(_) => FFI_RETURN_INTERNAL_ERROR, - } -} - -#[no_mangle] -pub extern "C" fn FFI_ProfileKeyCredentialRequest_checkValidContents( - profileKeyCredentialRequest: *const u8, - profileKeyCredentialRequestLen: u32, -) -> i32 { - let result = panic::catch_unwind(|| { - let profile_key_credential_request: &[u8] = unsafe { - slice::from_raw_parts( - profileKeyCredentialRequest, - profileKeyCredentialRequestLen as usize, - ) - }; - - simpleapi::ProfileKeyCredentialRequest_checkValidContents(profile_key_credential_request) - }); - - match result { - Ok(result) => result, - Err(_) => FFI_RETURN_INTERNAL_ERROR, - } -} - -#[no_mangle] -pub extern "C" fn FFI_ProfileKeyCredentialResponse_checkValidContents( - profileKeyCredentialResponse: *const u8, - profileKeyCredentialResponseLen: u32, -) -> i32 { - let result = panic::catch_unwind(|| { - let profile_key_credential_response: &[u8] = unsafe { - slice::from_raw_parts( - profileKeyCredentialResponse, - profileKeyCredentialResponseLen as usize, - ) - }; - - simpleapi::ProfileKeyCredentialResponse_checkValidContents(profile_key_credential_response) - }); - - match result { - Ok(result) => result, - Err(_) => FFI_RETURN_INTERNAL_ERROR, - } -} - -#[no_mangle] -pub extern "C" fn FFI_ProfileKeyCredential_checkValidContents( - profileKeyCredential: *const u8, - profileKeyCredentialLen: u32, -) -> i32 { - let result = panic::catch_unwind(|| { - let profile_key_credential: &[u8] = unsafe { - slice::from_raw_parts(profileKeyCredential, profileKeyCredentialLen as usize) - }; - - simpleapi::ProfileKeyCredential_checkValidContents(profile_key_credential) - }); - - match result { - Ok(result) => result, - Err(_) => FFI_RETURN_INTERNAL_ERROR, - } -} - -#[no_mangle] -pub extern "C" fn FFI_ProfileKeyCredentialPresentation_checkValidContents( - profileKeyCredentialPresentation: *const u8, - profileKeyCredentialPresentationLen: u32, -) -> i32 { - let result = panic::catch_unwind(|| { - let profile_key_credential_presentation: &[u8] = unsafe { - slice::from_raw_parts( - profileKeyCredentialPresentation, - profileKeyCredentialPresentationLen as usize, - ) - }; - - simpleapi::ProfileKeyCredentialPresentation_checkValidContents( - profile_key_credential_presentation, - ) - }); - - match result { - Ok(result) => result, - Err(_) => FFI_RETURN_INTERNAL_ERROR, - } -} - -#[no_mangle] -pub extern "C" fn FFI_ProfileKeyCredentialPresentation_getUuidCiphertext( - profileKeyCredentialPresentation: *const u8, - profileKeyCredentialPresentationLen: u32, - uuidCiphertextOut: *mut u8, - uuidCiphertextLen: u32, -) -> i32 { - let result = panic::catch_unwind(|| { - let profile_key_credential_presentation: &[u8] = unsafe { - slice::from_raw_parts( - profileKeyCredentialPresentation, - profileKeyCredentialPresentationLen as usize, - ) - }; - let uuid_ciphertext: &mut [u8] = - unsafe { slice::from_raw_parts_mut(uuidCiphertextOut, uuidCiphertextLen as usize) }; - - simpleapi::ProfileKeyCredentialPresentation_getUuidCiphertext( - profile_key_credential_presentation, - uuid_ciphertext, - ) - }); - - match result { - Ok(result) => result, - Err(_) => FFI_RETURN_INTERNAL_ERROR, - } -} - -#[no_mangle] -pub extern "C" fn FFI_ProfileKeyCredentialPresentation_getProfileKeyCiphertext( - profileKeyCredentialPresentation: *const u8, - profileKeyCredentialPresentationLen: u32, - profileKeyCiphertextOut: *mut u8, - profileKeyCiphertextLen: u32, -) -> i32 { - let result = panic::catch_unwind(|| { - let profile_key_credential_presentation: &[u8] = unsafe { - slice::from_raw_parts( - profileKeyCredentialPresentation, - profileKeyCredentialPresentationLen as usize, - ) - }; - let profile_key_ciphertext: &mut [u8] = unsafe { - slice::from_raw_parts_mut(profileKeyCiphertextOut, profileKeyCiphertextLen as usize) - }; - - simpleapi::ProfileKeyCredentialPresentation_getProfileKeyCiphertext( - profile_key_credential_presentation, - profile_key_ciphertext, - ) - }); - - match result { - Ok(result) => result, - Err(_) => FFI_RETURN_INTERNAL_ERROR, - } -} - -#[no_mangle] -pub extern "C" fn FFI_UuidCiphertext_checkValidContents( - uuidCiphertext: *const u8, - uuidCiphertextLen: u32, -) -> i32 { - let result = panic::catch_unwind(|| { - let uuid_ciphertext: &[u8] = - unsafe { slice::from_raw_parts(uuidCiphertext, uuidCiphertextLen as usize) }; - - simpleapi::UuidCiphertext_checkValidContents(uuid_ciphertext) - }); - - match result { - Ok(result) => result, - Err(_) => FFI_RETURN_INTERNAL_ERROR, - } -} - -#[no_mangle] -pub extern "C" fn FFI_ProfileKeyCiphertext_checkValidContents( - profileKeyCiphertext: *const u8, - profileKeyCiphertextLen: u32, -) -> i32 { - let result = panic::catch_unwind(|| { - let profile_key_ciphertext: &[u8] = unsafe { - slice::from_raw_parts(profileKeyCiphertext, profileKeyCiphertextLen as usize) - }; - - simpleapi::ProfileKeyCiphertext_checkValidContents(profile_key_ciphertext) - }); - - match result { - Ok(result) => result, - Err(_) => FFI_RETURN_INTERNAL_ERROR, - } -} - -#[no_mangle] -pub extern "C" fn FFI_Randomness_checkValidContents( - randomness: *const u8, - randomnessLen: u32, -) -> i32 { - let result = panic::catch_unwind(|| { - let randomness: &[u8] = - unsafe { slice::from_raw_parts(randomness, randomnessLen as usize) }; - - simpleapi::Randomness_checkValidContents(randomness) - }); - - match result { - Ok(result) => result, - Err(_) => FFI_RETURN_INTERNAL_ERROR, - } -} - -#[no_mangle] -pub extern "C" fn FFI_Uuid_checkValidContents(uuid: *const u8, uuidLen: u32) -> i32 { - let result = panic::catch_unwind(|| { - let uuid: &[u8] = unsafe { slice::from_raw_parts(uuid, uuidLen as usize) }; - - simpleapi::Uuid_checkValidContents(uuid) - }); - - match result { - Ok(result) => result, - Err(_) => FFI_RETURN_INTERNAL_ERROR, - } -} diff --git a/net/gurk-rs/files/vendor/zkgroup/src/ffi/ffiapijava.rs b/net/gurk-rs/files/vendor/zkgroup/src/ffi/ffiapijava.rs deleted file mode 100644 index 03f0fcd..0000000 --- a/net/gurk-rs/files/vendor/zkgroup/src/ffi/ffiapijava.rs +++ /dev/null @@ -1,1563 +0,0 @@ -// -// Copyright (C) 2020 Signal Messenger, LLC. -// All rights reserved. -// -// SPDX-License-Identifier: GPL-3.0-only -// - -// Generated by zkgroup/codegen/codegen.py - do not edit - -#![allow(non_snake_case)] - -use std::panic; - -use crate::ffi::constants::*; - -extern crate jni; - -use super::simpleapi; - -use jni::sys::jint; - -// This is the interface to the JVM that we'll -// call the majority of our methods on. -use jni::JNIEnv; - -// These objects are what you should use as arguments to your native function. -// They carry extra lifetime information to prevent them escaping this context -// and getting used after being GC'd. -use jni::objects::JClass; - -// This is just a pointer. We'll be returning it from our function. -// We can't return one of the objects with lifetime information because the -// lifetime checker won't let us. -use jni::sys::jbyteArray; - -fn u8toi8(input: Vec) -> Vec { - let mut out: Vec = Default::default(); - for &i in &input { - out.push(i as i8); - } - out -} - -#[no_mangle] -pub extern "system" fn Java_org_signal_zkgroup_internal_Native_profileKeyGetCommitmentJNI( - env: JNIEnv, - _class: JClass, - profileKey: jbyteArray, - uuid: jbyteArray, - profileKeyCommitmentOut: jbyteArray, -) -> i32 { - let result = panic::catch_unwind(|| { - let profile_key = env.convert_byte_array(profileKey).unwrap(); - let uuid = env.convert_byte_array(uuid).unwrap(); - let mut profile_key_commitment: Vec = - vec![0; env.get_array_length(profileKeyCommitmentOut).unwrap() as usize]; - - let ffi_return = - simpleapi::ProfileKey_getCommitment(&profile_key, &uuid, &mut profile_key_commitment); - if ffi_return != FFI_RETURN_OK { - return ffi_return; - } - - env.set_byte_array_region( - profileKeyCommitmentOut, - 0, - &u8toi8(profile_key_commitment)[..], - ) - .unwrap(); - FFI_RETURN_OK - }); - - match result { - Ok(result) => result, - Err(_) => FFI_RETURN_INTERNAL_ERROR, - } -} - -#[no_mangle] -pub extern "system" fn Java_org_signal_zkgroup_internal_Native_profileKeyGetProfileKeyVersionJNI( - env: JNIEnv, - _class: JClass, - profileKey: jbyteArray, - uuid: jbyteArray, - profileKeyVersionOut: jbyteArray, -) -> i32 { - let result = panic::catch_unwind(|| { - let profile_key = env.convert_byte_array(profileKey).unwrap(); - let uuid = env.convert_byte_array(uuid).unwrap(); - let mut profile_key_version: Vec = - vec![0; env.get_array_length(profileKeyVersionOut).unwrap() as usize]; - - let ffi_return = simpleapi::ProfileKey_getProfileKeyVersion( - &profile_key, - &uuid, - &mut profile_key_version, - ); - if ffi_return != FFI_RETURN_OK { - return ffi_return; - } - - env.set_byte_array_region(profileKeyVersionOut, 0, &u8toi8(profile_key_version)[..]) - .unwrap(); - FFI_RETURN_OK - }); - - match result { - Ok(result) => result, - Err(_) => FFI_RETURN_INTERNAL_ERROR, - } -} - -#[no_mangle] -pub extern "system" fn Java_org_signal_zkgroup_internal_Native_profileKeyCommitmentCheckValidContentsJNI( - env: JNIEnv, - _class: JClass, - profileKeyCommitment: jbyteArray, -) -> i32 { - let result = panic::catch_unwind(|| { - let profile_key_commitment = env.convert_byte_array(profileKeyCommitment).unwrap(); - - let ffi_return = - simpleapi::ProfileKeyCommitment_checkValidContents(&profile_key_commitment); - if ffi_return != FFI_RETURN_OK { - return ffi_return; - } - FFI_RETURN_OK - }); - - match result { - Ok(result) => result, - Err(_) => FFI_RETURN_INTERNAL_ERROR, - } -} - -#[no_mangle] -pub extern "system" fn Java_org_signal_zkgroup_internal_Native_groupSecretParamsGenerateDeterministicJNI( - env: JNIEnv, - _class: JClass, - randomness: jbyteArray, - groupSecretParamsOut: jbyteArray, -) -> i32 { - let result = panic::catch_unwind(|| { - let randomness = env.convert_byte_array(randomness).unwrap(); - let mut group_secret_params: Vec = - vec![0; env.get_array_length(groupSecretParamsOut).unwrap() as usize]; - - let ffi_return = simpleapi::GroupSecretParams_generateDeterministic( - &randomness, - &mut group_secret_params, - ); - if ffi_return != FFI_RETURN_OK { - return ffi_return; - } - - env.set_byte_array_region(groupSecretParamsOut, 0, &u8toi8(group_secret_params)[..]) - .unwrap(); - FFI_RETURN_OK - }); - - match result { - Ok(result) => result, - Err(_) => FFI_RETURN_INTERNAL_ERROR, - } -} - -#[no_mangle] -pub extern "system" fn Java_org_signal_zkgroup_internal_Native_groupSecretParamsDeriveFromMasterKeyJNI( - env: JNIEnv, - _class: JClass, - groupMasterKey: jbyteArray, - groupSecretParamsOut: jbyteArray, -) -> i32 { - let result = panic::catch_unwind(|| { - let group_master_key = env.convert_byte_array(groupMasterKey).unwrap(); - let mut group_secret_params: Vec = - vec![0; env.get_array_length(groupSecretParamsOut).unwrap() as usize]; - - let ffi_return = simpleapi::GroupSecretParams_deriveFromMasterKey( - &group_master_key, - &mut group_secret_params, - ); - if ffi_return != FFI_RETURN_OK { - return ffi_return; - } - - env.set_byte_array_region(groupSecretParamsOut, 0, &u8toi8(group_secret_params)[..]) - .unwrap(); - FFI_RETURN_OK - }); - - match result { - Ok(result) => result, - Err(_) => FFI_RETURN_INTERNAL_ERROR, - } -} - -#[no_mangle] -pub extern "system" fn Java_org_signal_zkgroup_internal_Native_groupSecretParamsCheckValidContentsJNI( - env: JNIEnv, - _class: JClass, - groupSecretParams: jbyteArray, -) -> i32 { - let result = panic::catch_unwind(|| { - let group_secret_params = env.convert_byte_array(groupSecretParams).unwrap(); - - let ffi_return = simpleapi::GroupSecretParams_checkValidContents(&group_secret_params); - if ffi_return != FFI_RETURN_OK { - return ffi_return; - } - FFI_RETURN_OK - }); - - match result { - Ok(result) => result, - Err(_) => FFI_RETURN_INTERNAL_ERROR, - } -} - -#[no_mangle] -pub extern "system" fn Java_org_signal_zkgroup_internal_Native_groupSecretParamsGetMasterKeyJNI( - env: JNIEnv, - _class: JClass, - groupSecretParams: jbyteArray, - groupMasterKeyOut: jbyteArray, -) -> i32 { - let result = panic::catch_unwind(|| { - let group_secret_params = env.convert_byte_array(groupSecretParams).unwrap(); - let mut group_master_key: Vec = - vec![0; env.get_array_length(groupMasterKeyOut).unwrap() as usize]; - - let ffi_return = - simpleapi::GroupSecretParams_getMasterKey(&group_secret_params, &mut group_master_key); - if ffi_return != FFI_RETURN_OK { - return ffi_return; - } - - env.set_byte_array_region(groupMasterKeyOut, 0, &u8toi8(group_master_key)[..]) - .unwrap(); - FFI_RETURN_OK - }); - - match result { - Ok(result) => result, - Err(_) => FFI_RETURN_INTERNAL_ERROR, - } -} - -#[no_mangle] -pub extern "system" fn Java_org_signal_zkgroup_internal_Native_groupSecretParamsGetPublicParamsJNI( - env: JNIEnv, - _class: JClass, - groupSecretParams: jbyteArray, - groupPublicParamsOut: jbyteArray, -) -> i32 { - let result = panic::catch_unwind(|| { - let group_secret_params = env.convert_byte_array(groupSecretParams).unwrap(); - let mut group_public_params: Vec = - vec![0; env.get_array_length(groupPublicParamsOut).unwrap() as usize]; - - let ffi_return = simpleapi::GroupSecretParams_getPublicParams( - &group_secret_params, - &mut group_public_params, - ); - if ffi_return != FFI_RETURN_OK { - return ffi_return; - } - - env.set_byte_array_region(groupPublicParamsOut, 0, &u8toi8(group_public_params)[..]) - .unwrap(); - FFI_RETURN_OK - }); - - match result { - Ok(result) => result, - Err(_) => FFI_RETURN_INTERNAL_ERROR, - } -} - -#[no_mangle] -pub extern "system" fn Java_org_signal_zkgroup_internal_Native_groupSecretParamsEncryptUuidJNI( - env: JNIEnv, - _class: JClass, - groupSecretParams: jbyteArray, - uuid: jbyteArray, - uuidCiphertextOut: jbyteArray, -) -> i32 { - let result = panic::catch_unwind(|| { - let group_secret_params = env.convert_byte_array(groupSecretParams).unwrap(); - let uuid = env.convert_byte_array(uuid).unwrap(); - let mut uuid_ciphertext: Vec = - vec![0; env.get_array_length(uuidCiphertextOut).unwrap() as usize]; - - let ffi_return = simpleapi::GroupSecretParams_encryptUuid( - &group_secret_params, - &uuid, - &mut uuid_ciphertext, - ); - if ffi_return != FFI_RETURN_OK { - return ffi_return; - } - - env.set_byte_array_region(uuidCiphertextOut, 0, &u8toi8(uuid_ciphertext)[..]) - .unwrap(); - FFI_RETURN_OK - }); - - match result { - Ok(result) => result, - Err(_) => FFI_RETURN_INTERNAL_ERROR, - } -} - -#[no_mangle] -pub extern "system" fn Java_org_signal_zkgroup_internal_Native_groupSecretParamsDecryptUuidJNI( - env: JNIEnv, - _class: JClass, - groupSecretParams: jbyteArray, - uuidCiphertext: jbyteArray, - uuidOut: jbyteArray, -) -> i32 { - let result = panic::catch_unwind(|| { - let group_secret_params = env.convert_byte_array(groupSecretParams).unwrap(); - let uuid_ciphertext = env.convert_byte_array(uuidCiphertext).unwrap(); - let mut uuid: Vec = vec![0; env.get_array_length(uuidOut).unwrap() as usize]; - - let ffi_return = simpleapi::GroupSecretParams_decryptUuid( - &group_secret_params, - &uuid_ciphertext, - &mut uuid, - ); - if ffi_return != FFI_RETURN_OK { - return ffi_return; - } - - env.set_byte_array_region(uuidOut, 0, &u8toi8(uuid)[..]) - .unwrap(); - FFI_RETURN_OK - }); - - match result { - Ok(result) => result, - Err(_) => FFI_RETURN_INTERNAL_ERROR, - } -} - -#[no_mangle] -pub extern "system" fn Java_org_signal_zkgroup_internal_Native_groupSecretParamsEncryptProfileKeyJNI( - env: JNIEnv, - _class: JClass, - groupSecretParams: jbyteArray, - profileKey: jbyteArray, - uuid: jbyteArray, - profileKeyCiphertextOut: jbyteArray, -) -> i32 { - let result = panic::catch_unwind(|| { - let group_secret_params = env.convert_byte_array(groupSecretParams).unwrap(); - let profile_key = env.convert_byte_array(profileKey).unwrap(); - let uuid = env.convert_byte_array(uuid).unwrap(); - let mut profile_key_ciphertext: Vec = - vec![0; env.get_array_length(profileKeyCiphertextOut).unwrap() as usize]; - - let ffi_return = simpleapi::GroupSecretParams_encryptProfileKey( - &group_secret_params, - &profile_key, - &uuid, - &mut profile_key_ciphertext, - ); - if ffi_return != FFI_RETURN_OK { - return ffi_return; - } - - env.set_byte_array_region( - profileKeyCiphertextOut, - 0, - &u8toi8(profile_key_ciphertext)[..], - ) - .unwrap(); - FFI_RETURN_OK - }); - - match result { - Ok(result) => result, - Err(_) => FFI_RETURN_INTERNAL_ERROR, - } -} - -#[no_mangle] -pub extern "system" fn Java_org_signal_zkgroup_internal_Native_groupSecretParamsDecryptProfileKeyJNI( - env: JNIEnv, - _class: JClass, - groupSecretParams: jbyteArray, - profileKeyCiphertext: jbyteArray, - uuid: jbyteArray, - profileKeyOut: jbyteArray, -) -> i32 { - let result = panic::catch_unwind(|| { - let group_secret_params = env.convert_byte_array(groupSecretParams).unwrap(); - let profile_key_ciphertext = env.convert_byte_array(profileKeyCiphertext).unwrap(); - let uuid = env.convert_byte_array(uuid).unwrap(); - let mut profile_key: Vec = - vec![0; env.get_array_length(profileKeyOut).unwrap() as usize]; - - let ffi_return = simpleapi::GroupSecretParams_decryptProfileKey( - &group_secret_params, - &profile_key_ciphertext, - &uuid, - &mut profile_key, - ); - if ffi_return != FFI_RETURN_OK { - return ffi_return; - } - - env.set_byte_array_region(profileKeyOut, 0, &u8toi8(profile_key)[..]) - .unwrap(); - FFI_RETURN_OK - }); - - match result { - Ok(result) => result, - Err(_) => FFI_RETURN_INTERNAL_ERROR, - } -} - -#[no_mangle] -pub extern "system" fn Java_org_signal_zkgroup_internal_Native_groupSecretParamsEncryptBlobDeterministicJNI( - env: JNIEnv, - _class: JClass, - groupSecretParams: jbyteArray, - randomness: jbyteArray, - plaintext: jbyteArray, - blobCiphertextOut: jbyteArray, -) -> i32 { - let result = panic::catch_unwind(|| { - let group_secret_params = env.convert_byte_array(groupSecretParams).unwrap(); - let randomness = env.convert_byte_array(randomness).unwrap(); - let plaintext = env.convert_byte_array(plaintext).unwrap(); - let mut blob_ciphertext: Vec = - vec![0; env.get_array_length(blobCiphertextOut).unwrap() as usize]; - - let ffi_return = simpleapi::GroupSecretParams_encryptBlobDeterministic( - &group_secret_params, - &randomness, - &plaintext, - &mut blob_ciphertext, - ); - if ffi_return != FFI_RETURN_OK { - return ffi_return; - } - - env.set_byte_array_region(blobCiphertextOut, 0, &u8toi8(blob_ciphertext)[..]) - .unwrap(); - FFI_RETURN_OK - }); - - match result { - Ok(result) => result, - Err(_) => FFI_RETURN_INTERNAL_ERROR, - } -} - -#[no_mangle] -pub extern "system" fn Java_org_signal_zkgroup_internal_Native_groupSecretParamsDecryptBlobJNI( - env: JNIEnv, - _class: JClass, - groupSecretParams: jbyteArray, - blobCiphertext: jbyteArray, - plaintextOut: jbyteArray, -) -> i32 { - let result = panic::catch_unwind(|| { - let group_secret_params = env.convert_byte_array(groupSecretParams).unwrap(); - let blob_ciphertext = env.convert_byte_array(blobCiphertext).unwrap(); - let mut plaintext: Vec = vec![0; env.get_array_length(plaintextOut).unwrap() as usize]; - - let ffi_return = simpleapi::GroupSecretParams_decryptBlob( - &group_secret_params, - &blob_ciphertext, - &mut plaintext, - ); - if ffi_return != FFI_RETURN_OK { - return ffi_return; - } - - env.set_byte_array_region(plaintextOut, 0, &u8toi8(plaintext)[..]) - .unwrap(); - FFI_RETURN_OK - }); - - match result { - Ok(result) => result, - Err(_) => FFI_RETURN_INTERNAL_ERROR, - } -} - -#[no_mangle] -pub extern "system" fn Java_org_signal_zkgroup_internal_Native_serverSecretParamsGenerateDeterministicJNI( - env: JNIEnv, - _class: JClass, - randomness: jbyteArray, - serverSecretParamsOut: jbyteArray, -) -> i32 { - let result = panic::catch_unwind(|| { - let randomness = env.convert_byte_array(randomness).unwrap(); - let mut server_secret_params: Vec = - vec![0; env.get_array_length(serverSecretParamsOut).unwrap() as usize]; - - let ffi_return = simpleapi::ServerSecretParams_generateDeterministic( - &randomness, - &mut server_secret_params, - ); - if ffi_return != FFI_RETURN_OK { - return ffi_return; - } - - env.set_byte_array_region(serverSecretParamsOut, 0, &u8toi8(server_secret_params)[..]) - .unwrap(); - FFI_RETURN_OK - }); - - match result { - Ok(result) => result, - Err(_) => FFI_RETURN_INTERNAL_ERROR, - } -} - -#[no_mangle] -pub extern "system" fn Java_org_signal_zkgroup_internal_Native_serverSecretParamsCheckValidContentsJNI( - env: JNIEnv, - _class: JClass, - serverSecretParams: jbyteArray, -) -> i32 { - let result = panic::catch_unwind(|| { - let server_secret_params = env.convert_byte_array(serverSecretParams).unwrap(); - - let ffi_return = simpleapi::ServerSecretParams_checkValidContents(&server_secret_params); - if ffi_return != FFI_RETURN_OK { - return ffi_return; - } - FFI_RETURN_OK - }); - - match result { - Ok(result) => result, - Err(_) => FFI_RETURN_INTERNAL_ERROR, - } -} - -#[no_mangle] -pub extern "system" fn Java_org_signal_zkgroup_internal_Native_serverSecretParamsGetPublicParamsJNI( - env: JNIEnv, - _class: JClass, - serverSecretParams: jbyteArray, - serverPublicParamsOut: jbyteArray, -) -> i32 { - let result = panic::catch_unwind(|| { - let server_secret_params = env.convert_byte_array(serverSecretParams).unwrap(); - let mut server_public_params: Vec = - vec![0; env.get_array_length(serverPublicParamsOut).unwrap() as usize]; - - let ffi_return = simpleapi::ServerSecretParams_getPublicParams( - &server_secret_params, - &mut server_public_params, - ); - if ffi_return != FFI_RETURN_OK { - return ffi_return; - } - - env.set_byte_array_region(serverPublicParamsOut, 0, &u8toi8(server_public_params)[..]) - .unwrap(); - FFI_RETURN_OK - }); - - match result { - Ok(result) => result, - Err(_) => FFI_RETURN_INTERNAL_ERROR, - } -} - -#[no_mangle] -pub extern "system" fn Java_org_signal_zkgroup_internal_Native_serverSecretParamsSignDeterministicJNI( - env: JNIEnv, - _class: JClass, - serverSecretParams: jbyteArray, - randomness: jbyteArray, - message: jbyteArray, - notarySignatureOut: jbyteArray, -) -> i32 { - let result = panic::catch_unwind(|| { - let server_secret_params = env.convert_byte_array(serverSecretParams).unwrap(); - let randomness = env.convert_byte_array(randomness).unwrap(); - let message = env.convert_byte_array(message).unwrap(); - let mut notary_signature: Vec = - vec![0; env.get_array_length(notarySignatureOut).unwrap() as usize]; - - let ffi_return = simpleapi::ServerSecretParams_signDeterministic( - &server_secret_params, - &randomness, - &message, - &mut notary_signature, - ); - if ffi_return != FFI_RETURN_OK { - return ffi_return; - } - - env.set_byte_array_region(notarySignatureOut, 0, &u8toi8(notary_signature)[..]) - .unwrap(); - FFI_RETURN_OK - }); - - match result { - Ok(result) => result, - Err(_) => FFI_RETURN_INTERNAL_ERROR, - } -} - -#[no_mangle] -pub extern "system" fn Java_org_signal_zkgroup_internal_Native_serverPublicParamsReceiveAuthCredentialJNI( - env: JNIEnv, - _class: JClass, - serverPublicParams: jbyteArray, - uuid: jbyteArray, - redemptionTime: jint, - authCredentialResponse: jbyteArray, - authCredentialOut: jbyteArray, -) -> i32 { - let result = panic::catch_unwind(|| { - let server_public_params = env.convert_byte_array(serverPublicParams).unwrap(); - let uuid = env.convert_byte_array(uuid).unwrap(); - let redemption_time = redemptionTime as u32; - let auth_credential_response = env.convert_byte_array(authCredentialResponse).unwrap(); - let mut auth_credential: Vec = - vec![0; env.get_array_length(authCredentialOut).unwrap() as usize]; - - let ffi_return = simpleapi::ServerPublicParams_receiveAuthCredential( - &server_public_params, - &uuid, - redemption_time, - &auth_credential_response, - &mut auth_credential, - ); - if ffi_return != FFI_RETURN_OK { - return ffi_return; - } - - env.set_byte_array_region(authCredentialOut, 0, &u8toi8(auth_credential)[..]) - .unwrap(); - FFI_RETURN_OK - }); - - match result { - Ok(result) => result, - Err(_) => FFI_RETURN_INTERNAL_ERROR, - } -} - -#[no_mangle] -pub extern "system" fn Java_org_signal_zkgroup_internal_Native_serverPublicParamsCreateAuthCredentialPresentationDeterministicJNI( - env: JNIEnv, - _class: JClass, - serverPublicParams: jbyteArray, - randomness: jbyteArray, - groupSecretParams: jbyteArray, - authCredential: jbyteArray, - authCredentialPresentationOut: jbyteArray, -) -> i32 { - let result = panic::catch_unwind(|| { - let server_public_params = env.convert_byte_array(serverPublicParams).unwrap(); - let randomness = env.convert_byte_array(randomness).unwrap(); - let group_secret_params = env.convert_byte_array(groupSecretParams).unwrap(); - let auth_credential = env.convert_byte_array(authCredential).unwrap(); - let mut auth_credential_presentation: Vec = - vec![0; env.get_array_length(authCredentialPresentationOut).unwrap() as usize]; - - let ffi_return = - simpleapi::ServerPublicParams_createAuthCredentialPresentationDeterministic( - &server_public_params, - &randomness, - &group_secret_params, - &auth_credential, - &mut auth_credential_presentation, - ); - if ffi_return != FFI_RETURN_OK { - return ffi_return; - } - - env.set_byte_array_region( - authCredentialPresentationOut, - 0, - &u8toi8(auth_credential_presentation)[..], - ) - .unwrap(); - FFI_RETURN_OK - }); - - match result { - Ok(result) => result, - Err(_) => FFI_RETURN_INTERNAL_ERROR, - } -} - -#[no_mangle] -pub extern "system" fn Java_org_signal_zkgroup_internal_Native_serverPublicParamsCreateProfileKeyCredentialRequestContextDeterministicJNI( - env: JNIEnv, - _class: JClass, - serverPublicParams: jbyteArray, - randomness: jbyteArray, - uuid: jbyteArray, - profileKey: jbyteArray, - profileKeyCredentialRequestContextOut: jbyteArray, -) -> i32 { - let result = panic::catch_unwind(|| { - let server_public_params = env.convert_byte_array(serverPublicParams).unwrap(); - let randomness = env.convert_byte_array(randomness).unwrap(); - let uuid = env.convert_byte_array(uuid).unwrap(); - let profile_key = env.convert_byte_array(profileKey).unwrap(); - let mut profile_key_credential_request_context: Vec = vec![ - 0; - env.get_array_length(profileKeyCredentialRequestContextOut) - .unwrap() - as usize - ]; - - let ffi_return = - simpleapi::ServerPublicParams_createProfileKeyCredentialRequestContextDeterministic( - &server_public_params, - &randomness, - &uuid, - &profile_key, - &mut profile_key_credential_request_context, - ); - if ffi_return != FFI_RETURN_OK { - return ffi_return; - } - - env.set_byte_array_region( - profileKeyCredentialRequestContextOut, - 0, - &u8toi8(profile_key_credential_request_context)[..], - ) - .unwrap(); - FFI_RETURN_OK - }); - - match result { - Ok(result) => result, - Err(_) => FFI_RETURN_INTERNAL_ERROR, - } -} - -#[no_mangle] -pub extern "system" fn Java_org_signal_zkgroup_internal_Native_serverPublicParamsReceiveProfileKeyCredentialJNI( - env: JNIEnv, - _class: JClass, - serverPublicParams: jbyteArray, - profileKeyCredentialRequestContext: jbyteArray, - profileKeyCredentialResponse: jbyteArray, - profileKeyCredentialOut: jbyteArray, -) -> i32 { - let result = panic::catch_unwind(|| { - let server_public_params = env.convert_byte_array(serverPublicParams).unwrap(); - let profile_key_credential_request_context = env - .convert_byte_array(profileKeyCredentialRequestContext) - .unwrap(); - let profile_key_credential_response = env - .convert_byte_array(profileKeyCredentialResponse) - .unwrap(); - let mut profile_key_credential: Vec = - vec![0; env.get_array_length(profileKeyCredentialOut).unwrap() as usize]; - - let ffi_return = simpleapi::ServerPublicParams_receiveProfileKeyCredential( - &server_public_params, - &profile_key_credential_request_context, - &profile_key_credential_response, - &mut profile_key_credential, - ); - if ffi_return != FFI_RETURN_OK { - return ffi_return; - } - - env.set_byte_array_region( - profileKeyCredentialOut, - 0, - &u8toi8(profile_key_credential)[..], - ) - .unwrap(); - FFI_RETURN_OK - }); - - match result { - Ok(result) => result, - Err(_) => FFI_RETURN_INTERNAL_ERROR, - } -} - -#[no_mangle] -pub extern "system" fn Java_org_signal_zkgroup_internal_Native_serverPublicParamsCreateProfileKeyCredentialPresentationDeterministicJNI( - env: JNIEnv, - _class: JClass, - serverPublicParams: jbyteArray, - randomness: jbyteArray, - groupSecretParams: jbyteArray, - profileKeyCredential: jbyteArray, - profileKeyCredentialPresentationOut: jbyteArray, -) -> i32 { - let result = panic::catch_unwind(|| { - let server_public_params = env.convert_byte_array(serverPublicParams).unwrap(); - let randomness = env.convert_byte_array(randomness).unwrap(); - let group_secret_params = env.convert_byte_array(groupSecretParams).unwrap(); - let profile_key_credential = env.convert_byte_array(profileKeyCredential).unwrap(); - let mut profile_key_credential_presentation: Vec = vec![ - 0; - env.get_array_length(profileKeyCredentialPresentationOut) - .unwrap() - as usize - ]; - - let ffi_return = - simpleapi::ServerPublicParams_createProfileKeyCredentialPresentationDeterministic( - &server_public_params, - &randomness, - &group_secret_params, - &profile_key_credential, - &mut profile_key_credential_presentation, - ); - if ffi_return != FFI_RETURN_OK { - return ffi_return; - } - - env.set_byte_array_region( - profileKeyCredentialPresentationOut, - 0, - &u8toi8(profile_key_credential_presentation)[..], - ) - .unwrap(); - FFI_RETURN_OK - }); - - match result { - Ok(result) => result, - Err(_) => FFI_RETURN_INTERNAL_ERROR, - } -} - -#[no_mangle] -pub extern "system" fn Java_org_signal_zkgroup_internal_Native_serverSecretParamsIssueAuthCredentialDeterministicJNI( - env: JNIEnv, - _class: JClass, - serverSecretParams: jbyteArray, - randomness: jbyteArray, - uuid: jbyteArray, - redemptionTime: jint, - authCredentialResponseOut: jbyteArray, -) -> i32 { - let result = panic::catch_unwind(|| { - let server_secret_params = env.convert_byte_array(serverSecretParams).unwrap(); - let randomness = env.convert_byte_array(randomness).unwrap(); - let uuid = env.convert_byte_array(uuid).unwrap(); - let redemption_time = redemptionTime as u32; - let mut auth_credential_response: Vec = - vec![0; env.get_array_length(authCredentialResponseOut).unwrap() as usize]; - - let ffi_return = simpleapi::ServerSecretParams_issueAuthCredentialDeterministic( - &server_secret_params, - &randomness, - &uuid, - redemption_time, - &mut auth_credential_response, - ); - if ffi_return != FFI_RETURN_OK { - return ffi_return; - } - - env.set_byte_array_region( - authCredentialResponseOut, - 0, - &u8toi8(auth_credential_response)[..], - ) - .unwrap(); - FFI_RETURN_OK - }); - - match result { - Ok(result) => result, - Err(_) => FFI_RETURN_INTERNAL_ERROR, - } -} - -#[no_mangle] -pub extern "system" fn Java_org_signal_zkgroup_internal_Native_serverSecretParamsVerifyAuthCredentialPresentationJNI( - env: JNIEnv, - _class: JClass, - serverSecretParams: jbyteArray, - groupPublicParams: jbyteArray, - authCredentialPresentation: jbyteArray, -) -> i32 { - let result = panic::catch_unwind(|| { - let server_secret_params = env.convert_byte_array(serverSecretParams).unwrap(); - let group_public_params = env.convert_byte_array(groupPublicParams).unwrap(); - let auth_credential_presentation = - env.convert_byte_array(authCredentialPresentation).unwrap(); - - let ffi_return = simpleapi::ServerSecretParams_verifyAuthCredentialPresentation( - &server_secret_params, - &group_public_params, - &auth_credential_presentation, - ); - if ffi_return != FFI_RETURN_OK { - return ffi_return; - } - FFI_RETURN_OK - }); - - match result { - Ok(result) => result, - Err(_) => FFI_RETURN_INTERNAL_ERROR, - } -} - -#[no_mangle] -pub extern "system" fn Java_org_signal_zkgroup_internal_Native_serverSecretParamsIssueProfileKeyCredentialDeterministicJNI( - env: JNIEnv, - _class: JClass, - serverSecretParams: jbyteArray, - randomness: jbyteArray, - profileKeyCredentialRequest: jbyteArray, - uuid: jbyteArray, - profileKeyCommitment: jbyteArray, - profileKeyCredentialResponseOut: jbyteArray, -) -> i32 { - let result = panic::catch_unwind(|| { - let server_secret_params = env.convert_byte_array(serverSecretParams).unwrap(); - let randomness = env.convert_byte_array(randomness).unwrap(); - let profile_key_credential_request = - env.convert_byte_array(profileKeyCredentialRequest).unwrap(); - let uuid = env.convert_byte_array(uuid).unwrap(); - let profile_key_commitment = env.convert_byte_array(profileKeyCommitment).unwrap(); - let mut profile_key_credential_response: Vec = vec![ - 0; - env.get_array_length(profileKeyCredentialResponseOut) - .unwrap() as usize - ]; - - let ffi_return = simpleapi::ServerSecretParams_issueProfileKeyCredentialDeterministic( - &server_secret_params, - &randomness, - &profile_key_credential_request, - &uuid, - &profile_key_commitment, - &mut profile_key_credential_response, - ); - if ffi_return != FFI_RETURN_OK { - return ffi_return; - } - - env.set_byte_array_region( - profileKeyCredentialResponseOut, - 0, - &u8toi8(profile_key_credential_response)[..], - ) - .unwrap(); - FFI_RETURN_OK - }); - - match result { - Ok(result) => result, - Err(_) => FFI_RETURN_INTERNAL_ERROR, - } -} - -#[no_mangle] -pub extern "system" fn Java_org_signal_zkgroup_internal_Native_serverSecretParamsVerifyProfileKeyCredentialPresentationJNI( - env: JNIEnv, - _class: JClass, - serverSecretParams: jbyteArray, - groupPublicParams: jbyteArray, - profileKeyCredentialPresentation: jbyteArray, -) -> i32 { - let result = panic::catch_unwind(|| { - let server_secret_params = env.convert_byte_array(serverSecretParams).unwrap(); - let group_public_params = env.convert_byte_array(groupPublicParams).unwrap(); - let profile_key_credential_presentation = env - .convert_byte_array(profileKeyCredentialPresentation) - .unwrap(); - - let ffi_return = simpleapi::ServerSecretParams_verifyProfileKeyCredentialPresentation( - &server_secret_params, - &group_public_params, - &profile_key_credential_presentation, - ); - if ffi_return != FFI_RETURN_OK { - return ffi_return; - } - FFI_RETURN_OK - }); - - match result { - Ok(result) => result, - Err(_) => FFI_RETURN_INTERNAL_ERROR, - } -} - -#[no_mangle] -pub extern "system" fn Java_org_signal_zkgroup_internal_Native_groupPublicParamsCheckValidContentsJNI( - env: JNIEnv, - _class: JClass, - groupPublicParams: jbyteArray, -) -> i32 { - let result = panic::catch_unwind(|| { - let group_public_params = env.convert_byte_array(groupPublicParams).unwrap(); - - let ffi_return = simpleapi::GroupPublicParams_checkValidContents(&group_public_params); - if ffi_return != FFI_RETURN_OK { - return ffi_return; - } - FFI_RETURN_OK - }); - - match result { - Ok(result) => result, - Err(_) => FFI_RETURN_INTERNAL_ERROR, - } -} - -#[no_mangle] -pub extern "system" fn Java_org_signal_zkgroup_internal_Native_groupPublicParamsGetGroupIdentifierJNI( - env: JNIEnv, - _class: JClass, - groupPublicParams: jbyteArray, - groupIdentifierOut: jbyteArray, -) -> i32 { - let result = panic::catch_unwind(|| { - let group_public_params = env.convert_byte_array(groupPublicParams).unwrap(); - let mut group_identifier: Vec = - vec![0; env.get_array_length(groupIdentifierOut).unwrap() as usize]; - - let ffi_return = simpleapi::GroupPublicParams_getGroupIdentifier( - &group_public_params, - &mut group_identifier, - ); - if ffi_return != FFI_RETURN_OK { - return ffi_return; - } - - env.set_byte_array_region(groupIdentifierOut, 0, &u8toi8(group_identifier)[..]) - .unwrap(); - FFI_RETURN_OK - }); - - match result { - Ok(result) => result, - Err(_) => FFI_RETURN_INTERNAL_ERROR, - } -} - -#[no_mangle] -pub extern "system" fn Java_org_signal_zkgroup_internal_Native_serverPublicParamsCheckValidContentsJNI( - env: JNIEnv, - _class: JClass, - serverPublicParams: jbyteArray, -) -> i32 { - let result = panic::catch_unwind(|| { - let server_public_params = env.convert_byte_array(serverPublicParams).unwrap(); - - let ffi_return = simpleapi::ServerPublicParams_checkValidContents(&server_public_params); - if ffi_return != FFI_RETURN_OK { - return ffi_return; - } - FFI_RETURN_OK - }); - - match result { - Ok(result) => result, - Err(_) => FFI_RETURN_INTERNAL_ERROR, - } -} - -#[no_mangle] -pub extern "system" fn Java_org_signal_zkgroup_internal_Native_serverPublicParamsVerifySignatureJNI( - env: JNIEnv, - _class: JClass, - serverPublicParams: jbyteArray, - message: jbyteArray, - notarySignature: jbyteArray, -) -> i32 { - let result = panic::catch_unwind(|| { - let server_public_params = env.convert_byte_array(serverPublicParams).unwrap(); - let message = env.convert_byte_array(message).unwrap(); - let notary_signature = env.convert_byte_array(notarySignature).unwrap(); - - let ffi_return = simpleapi::ServerPublicParams_verifySignature( - &server_public_params, - &message, - ¬ary_signature, - ); - if ffi_return != FFI_RETURN_OK { - return ffi_return; - } - FFI_RETURN_OK - }); - - match result { - Ok(result) => result, - Err(_) => FFI_RETURN_INTERNAL_ERROR, - } -} - -#[no_mangle] -pub extern "system" fn Java_org_signal_zkgroup_internal_Native_authCredentialResponseCheckValidContentsJNI( - env: JNIEnv, - _class: JClass, - authCredentialResponse: jbyteArray, -) -> i32 { - let result = panic::catch_unwind(|| { - let auth_credential_response = env.convert_byte_array(authCredentialResponse).unwrap(); - - let ffi_return = - simpleapi::AuthCredentialResponse_checkValidContents(&auth_credential_response); - if ffi_return != FFI_RETURN_OK { - return ffi_return; - } - FFI_RETURN_OK - }); - - match result { - Ok(result) => result, - Err(_) => FFI_RETURN_INTERNAL_ERROR, - } -} - -#[no_mangle] -pub extern "system" fn Java_org_signal_zkgroup_internal_Native_authCredentialCheckValidContentsJNI( - env: JNIEnv, - _class: JClass, - authCredential: jbyteArray, -) -> i32 { - let result = panic::catch_unwind(|| { - let auth_credential = env.convert_byte_array(authCredential).unwrap(); - - let ffi_return = simpleapi::AuthCredential_checkValidContents(&auth_credential); - if ffi_return != FFI_RETURN_OK { - return ffi_return; - } - FFI_RETURN_OK - }); - - match result { - Ok(result) => result, - Err(_) => FFI_RETURN_INTERNAL_ERROR, - } -} - -#[no_mangle] -pub extern "system" fn Java_org_signal_zkgroup_internal_Native_authCredentialPresentationCheckValidContentsJNI( - env: JNIEnv, - _class: JClass, - authCredentialPresentation: jbyteArray, -) -> i32 { - let result = panic::catch_unwind(|| { - let auth_credential_presentation = - env.convert_byte_array(authCredentialPresentation).unwrap(); - - let ffi_return = - simpleapi::AuthCredentialPresentation_checkValidContents(&auth_credential_presentation); - if ffi_return != FFI_RETURN_OK { - return ffi_return; - } - FFI_RETURN_OK - }); - - match result { - Ok(result) => result, - Err(_) => FFI_RETURN_INTERNAL_ERROR, - } -} - -#[no_mangle] -pub extern "system" fn Java_org_signal_zkgroup_internal_Native_authCredentialPresentationGetUuidCiphertextJNI( - env: JNIEnv, - _class: JClass, - authCredentialPresentation: jbyteArray, - uuidCiphertextOut: jbyteArray, -) -> i32 { - let result = panic::catch_unwind(|| { - let auth_credential_presentation = - env.convert_byte_array(authCredentialPresentation).unwrap(); - let mut uuid_ciphertext: Vec = - vec![0; env.get_array_length(uuidCiphertextOut).unwrap() as usize]; - - let ffi_return = simpleapi::AuthCredentialPresentation_getUuidCiphertext( - &auth_credential_presentation, - &mut uuid_ciphertext, - ); - if ffi_return != FFI_RETURN_OK { - return ffi_return; - } - - env.set_byte_array_region(uuidCiphertextOut, 0, &u8toi8(uuid_ciphertext)[..]) - .unwrap(); - FFI_RETURN_OK - }); - - match result { - Ok(result) => result, - Err(_) => FFI_RETURN_INTERNAL_ERROR, - } -} - -#[no_mangle] -pub extern "system" fn Java_org_signal_zkgroup_internal_Native_authCredentialPresentationGetRedemptionTimeJNI( - env: JNIEnv, - _class: JClass, - authCredentialPresentation: jbyteArray, - redemptionTimeOut: jbyteArray, -) -> i32 { - let result = panic::catch_unwind(|| { - let auth_credential_presentation = - env.convert_byte_array(authCredentialPresentation).unwrap(); - let mut redemption_time: Vec = - vec![0; env.get_array_length(redemptionTimeOut).unwrap() as usize]; - - let ffi_return = simpleapi::AuthCredentialPresentation_getRedemptionTime( - &auth_credential_presentation, - &mut redemption_time, - ); - if ffi_return != FFI_RETURN_OK { - return ffi_return; - } - - env.set_byte_array_region(redemptionTimeOut, 0, &u8toi8(redemption_time)[..]) - .unwrap(); - FFI_RETURN_OK - }); - - match result { - Ok(result) => result, - Err(_) => FFI_RETURN_INTERNAL_ERROR, - } -} - -#[no_mangle] -pub extern "system" fn Java_org_signal_zkgroup_internal_Native_profileKeyCredentialRequestContextCheckValidContentsJNI( - env: JNIEnv, - _class: JClass, - profileKeyCredentialRequestContext: jbyteArray, -) -> i32 { - let result = panic::catch_unwind(|| { - let profile_key_credential_request_context = env - .convert_byte_array(profileKeyCredentialRequestContext) - .unwrap(); - - let ffi_return = simpleapi::ProfileKeyCredentialRequestContext_checkValidContents( - &profile_key_credential_request_context, - ); - if ffi_return != FFI_RETURN_OK { - return ffi_return; - } - FFI_RETURN_OK - }); - - match result { - Ok(result) => result, - Err(_) => FFI_RETURN_INTERNAL_ERROR, - } -} - -#[no_mangle] -pub extern "system" fn Java_org_signal_zkgroup_internal_Native_profileKeyCredentialRequestContextGetRequestJNI( - env: JNIEnv, - _class: JClass, - profileKeyCredentialRequestContext: jbyteArray, - profileKeyCredentialRequestOut: jbyteArray, -) -> i32 { - let result = panic::catch_unwind(|| { - let profile_key_credential_request_context = env - .convert_byte_array(profileKeyCredentialRequestContext) - .unwrap(); - let mut profile_key_credential_request: Vec = vec![ - 0; - env.get_array_length(profileKeyCredentialRequestOut) - .unwrap() as usize - ]; - - let ffi_return = simpleapi::ProfileKeyCredentialRequestContext_getRequest( - &profile_key_credential_request_context, - &mut profile_key_credential_request, - ); - if ffi_return != FFI_RETURN_OK { - return ffi_return; - } - - env.set_byte_array_region( - profileKeyCredentialRequestOut, - 0, - &u8toi8(profile_key_credential_request)[..], - ) - .unwrap(); - FFI_RETURN_OK - }); - - match result { - Ok(result) => result, - Err(_) => FFI_RETURN_INTERNAL_ERROR, - } -} - -#[no_mangle] -pub extern "system" fn Java_org_signal_zkgroup_internal_Native_profileKeyCredentialRequestCheckValidContentsJNI( - env: JNIEnv, - _class: JClass, - profileKeyCredentialRequest: jbyteArray, -) -> i32 { - let result = panic::catch_unwind(|| { - let profile_key_credential_request = - env.convert_byte_array(profileKeyCredentialRequest).unwrap(); - - let ffi_return = simpleapi::ProfileKeyCredentialRequest_checkValidContents( - &profile_key_credential_request, - ); - if ffi_return != FFI_RETURN_OK { - return ffi_return; - } - FFI_RETURN_OK - }); - - match result { - Ok(result) => result, - Err(_) => FFI_RETURN_INTERNAL_ERROR, - } -} - -#[no_mangle] -pub extern "system" fn Java_org_signal_zkgroup_internal_Native_profileKeyCredentialResponseCheckValidContentsJNI( - env: JNIEnv, - _class: JClass, - profileKeyCredentialResponse: jbyteArray, -) -> i32 { - let result = panic::catch_unwind(|| { - let profile_key_credential_response = env - .convert_byte_array(profileKeyCredentialResponse) - .unwrap(); - - let ffi_return = simpleapi::ProfileKeyCredentialResponse_checkValidContents( - &profile_key_credential_response, - ); - if ffi_return != FFI_RETURN_OK { - return ffi_return; - } - FFI_RETURN_OK - }); - - match result { - Ok(result) => result, - Err(_) => FFI_RETURN_INTERNAL_ERROR, - } -} - -#[no_mangle] -pub extern "system" fn Java_org_signal_zkgroup_internal_Native_profileKeyCredentialCheckValidContentsJNI( - env: JNIEnv, - _class: JClass, - profileKeyCredential: jbyteArray, -) -> i32 { - let result = panic::catch_unwind(|| { - let profile_key_credential = env.convert_byte_array(profileKeyCredential).unwrap(); - - let ffi_return = - simpleapi::ProfileKeyCredential_checkValidContents(&profile_key_credential); - if ffi_return != FFI_RETURN_OK { - return ffi_return; - } - FFI_RETURN_OK - }); - - match result { - Ok(result) => result, - Err(_) => FFI_RETURN_INTERNAL_ERROR, - } -} - -#[no_mangle] -pub extern "system" fn Java_org_signal_zkgroup_internal_Native_profileKeyCredentialPresentationCheckValidContentsJNI( - env: JNIEnv, - _class: JClass, - profileKeyCredentialPresentation: jbyteArray, -) -> i32 { - let result = panic::catch_unwind(|| { - let profile_key_credential_presentation = env - .convert_byte_array(profileKeyCredentialPresentation) - .unwrap(); - - let ffi_return = simpleapi::ProfileKeyCredentialPresentation_checkValidContents( - &profile_key_credential_presentation, - ); - if ffi_return != FFI_RETURN_OK { - return ffi_return; - } - FFI_RETURN_OK - }); - - match result { - Ok(result) => result, - Err(_) => FFI_RETURN_INTERNAL_ERROR, - } -} - -#[no_mangle] -pub extern "system" fn Java_org_signal_zkgroup_internal_Native_profileKeyCredentialPresentationGetUuidCiphertextJNI( - env: JNIEnv, - _class: JClass, - profileKeyCredentialPresentation: jbyteArray, - uuidCiphertextOut: jbyteArray, -) -> i32 { - let result = panic::catch_unwind(|| { - let profile_key_credential_presentation = env - .convert_byte_array(profileKeyCredentialPresentation) - .unwrap(); - let mut uuid_ciphertext: Vec = - vec![0; env.get_array_length(uuidCiphertextOut).unwrap() as usize]; - - let ffi_return = simpleapi::ProfileKeyCredentialPresentation_getUuidCiphertext( - &profile_key_credential_presentation, - &mut uuid_ciphertext, - ); - if ffi_return != FFI_RETURN_OK { - return ffi_return; - } - - env.set_byte_array_region(uuidCiphertextOut, 0, &u8toi8(uuid_ciphertext)[..]) - .unwrap(); - FFI_RETURN_OK - }); - - match result { - Ok(result) => result, - Err(_) => FFI_RETURN_INTERNAL_ERROR, - } -} - -#[no_mangle] -pub extern "system" fn Java_org_signal_zkgroup_internal_Native_profileKeyCredentialPresentationGetProfileKeyCiphertextJNI( - env: JNIEnv, - _class: JClass, - profileKeyCredentialPresentation: jbyteArray, - profileKeyCiphertextOut: jbyteArray, -) -> i32 { - let result = panic::catch_unwind(|| { - let profile_key_credential_presentation = env - .convert_byte_array(profileKeyCredentialPresentation) - .unwrap(); - let mut profile_key_ciphertext: Vec = - vec![0; env.get_array_length(profileKeyCiphertextOut).unwrap() as usize]; - - let ffi_return = simpleapi::ProfileKeyCredentialPresentation_getProfileKeyCiphertext( - &profile_key_credential_presentation, - &mut profile_key_ciphertext, - ); - if ffi_return != FFI_RETURN_OK { - return ffi_return; - } - - env.set_byte_array_region( - profileKeyCiphertextOut, - 0, - &u8toi8(profile_key_ciphertext)[..], - ) - .unwrap(); - FFI_RETURN_OK - }); - - match result { - Ok(result) => result, - Err(_) => FFI_RETURN_INTERNAL_ERROR, - } -} - -#[no_mangle] -pub extern "system" fn Java_org_signal_zkgroup_internal_Native_uuidCiphertextCheckValidContentsJNI( - env: JNIEnv, - _class: JClass, - uuidCiphertext: jbyteArray, -) -> i32 { - let result = panic::catch_unwind(|| { - let uuid_ciphertext = env.convert_byte_array(uuidCiphertext).unwrap(); - - let ffi_return = simpleapi::UuidCiphertext_checkValidContents(&uuid_ciphertext); - if ffi_return != FFI_RETURN_OK { - return ffi_return; - } - FFI_RETURN_OK - }); - - match result { - Ok(result) => result, - Err(_) => FFI_RETURN_INTERNAL_ERROR, - } -} - -#[no_mangle] -pub extern "system" fn Java_org_signal_zkgroup_internal_Native_profileKeyCiphertextCheckValidContentsJNI( - env: JNIEnv, - _class: JClass, - profileKeyCiphertext: jbyteArray, -) -> i32 { - let result = panic::catch_unwind(|| { - let profile_key_ciphertext = env.convert_byte_array(profileKeyCiphertext).unwrap(); - - let ffi_return = - simpleapi::ProfileKeyCiphertext_checkValidContents(&profile_key_ciphertext); - if ffi_return != FFI_RETURN_OK { - return ffi_return; - } - FFI_RETURN_OK - }); - - match result { - Ok(result) => result, - Err(_) => FFI_RETURN_INTERNAL_ERROR, - } -} - -#[no_mangle] -pub extern "system" fn Java_org_signal_zkgroup_internal_Native_randomnessCheckValidContentsJNI( - env: JNIEnv, - _class: JClass, - randomness: jbyteArray, -) -> i32 { - let result = panic::catch_unwind(|| { - let randomness = env.convert_byte_array(randomness).unwrap(); - - let ffi_return = simpleapi::Randomness_checkValidContents(&randomness); - if ffi_return != FFI_RETURN_OK { - return ffi_return; - } - FFI_RETURN_OK - }); - - match result { - Ok(result) => result, - Err(_) => FFI_RETURN_INTERNAL_ERROR, - } -} - -#[no_mangle] -pub extern "system" fn Java_org_signal_zkgroup_internal_Native_uuidCheckValidContentsJNI( - env: JNIEnv, - _class: JClass, - uuid: jbyteArray, -) -> i32 { - let result = panic::catch_unwind(|| { - let uuid = env.convert_byte_array(uuid).unwrap(); - - let ffi_return = simpleapi::Uuid_checkValidContents(&uuid); - if ffi_return != FFI_RETURN_OK { - return ffi_return; - } - FFI_RETURN_OK - }); - - match result { - Ok(result) => result, - Err(_) => FFI_RETURN_INTERNAL_ERROR, - } -} diff --git a/net/gurk-rs/files/vendor/zkgroup/src/ffi/mod.rs b/net/gurk-rs/files/vendor/zkgroup/src/ffi/mod.rs deleted file mode 100644 index aeb4265..0000000 --- a/net/gurk-rs/files/vendor/zkgroup/src/ffi/mod.rs +++ /dev/null @@ -1,13 +0,0 @@ -// -// Copyright (C) 2020 Signal Messenger, LLC. -// All rights reserved. -// -// SPDX-License-Identifier: GPL-3.0-only -// - -pub mod constants; - -pub mod ffiapi; - -pub mod ffiapijava; -pub mod simpleapi; diff --git a/net/gurk-rs/files/vendor/zkgroup/src/ffi/simpleapi.rs b/net/gurk-rs/files/vendor/zkgroup/src/ffi/simpleapi.rs deleted file mode 100644 index bd481ab..0000000 --- a/net/gurk-rs/files/vendor/zkgroup/src/ffi/simpleapi.rs +++ /dev/null @@ -1,901 +0,0 @@ -// -// Copyright (C) 2020 Signal Messenger, LLC. -// All rights reserved. -// -// SPDX-License-Identifier: GPL-3.0-only -// - -// Generated by zkgroup/codegen/codegen.py - do not edit - -#![allow(non_snake_case)] - -use crate::api; -use crate::common::constants::*; -use crate::common::simple_types; -use crate::ffi::constants::*; - -pub fn ProfileKey_getCommitment( - profileKeyIn: &[u8], - uuidIn: &[u8], - profileKeyCommitmentOut: &mut [u8], -) -> i32 { - let profile_key: api::profiles::ProfileKey = match bincode::deserialize(profileKeyIn) { - Ok(result) => result, - Err(_) => return FFI_RETURN_INTERNAL_ERROR, - }; - - let uuid: simple_types::UidBytes = match bincode::deserialize(uuidIn) { - Ok(result) => result, - Err(_) => return FFI_RETURN_INPUT_ERROR, - }; - let profile_key_commitment = profile_key.get_commitment(uuid); - profileKeyCommitmentOut.copy_from_slice(&bincode::serialize(&profile_key_commitment).unwrap()); - FFI_RETURN_OK -} - -pub fn ProfileKey_getProfileKeyVersion( - profileKeyIn: &[u8], - uuidIn: &[u8], - profileKeyVersionOut: &mut [u8], -) -> i32 { - let profile_key: api::profiles::ProfileKey = match bincode::deserialize(profileKeyIn) { - Ok(result) => result, - Err(_) => return FFI_RETURN_INTERNAL_ERROR, - }; - - let uuid: simple_types::UidBytes = match bincode::deserialize(uuidIn) { - Ok(result) => result, - Err(_) => return FFI_RETURN_INPUT_ERROR, - }; - let profile_key_version = profile_key.get_profile_key_version(uuid); - profileKeyVersionOut.copy_from_slice(&bincode::serialize(&profile_key_version).unwrap()); - FFI_RETURN_OK -} - -pub fn ProfileKeyCommitment_checkValidContents(profileKeyCommitmentIn: &[u8]) -> i32 { - let _: api::profiles::ProfileKeyCommitment = match bincode::deserialize(profileKeyCommitmentIn) - { - Ok(result) => result, - Err(_) => return FFI_RETURN_INPUT_ERROR, - }; - - FFI_RETURN_OK -} - -pub fn GroupSecretParams_generateDeterministic( - randomnessIn: &[u8], - groupSecretParamsOut: &mut [u8], -) -> i32 { - let randomness: simple_types::RandomnessBytes = match bincode::deserialize(randomnessIn) { - Ok(result) => result, - Err(_) => return FFI_RETURN_INPUT_ERROR, - }; - let group_secret_params = api::groups::GroupSecretParams::generate(randomness); - groupSecretParamsOut.copy_from_slice(&bincode::serialize(&group_secret_params).unwrap()); - FFI_RETURN_OK -} - -pub fn GroupSecretParams_deriveFromMasterKey( - groupMasterKeyIn: &[u8], - groupSecretParamsOut: &mut [u8], -) -> i32 { - let group_master_key: api::groups::GroupMasterKey = match bincode::deserialize(groupMasterKeyIn) - { - Ok(result) => result, - Err(_) => return FFI_RETURN_INPUT_ERROR, - }; - let group_secret_params = - api::groups::GroupSecretParams::derive_from_master_key(group_master_key); - groupSecretParamsOut.copy_from_slice(&bincode::serialize(&group_secret_params).unwrap()); - FFI_RETURN_OK -} - -pub fn GroupSecretParams_checkValidContents(groupSecretParamsIn: &[u8]) -> i32 { - let _: api::groups::GroupSecretParams = match bincode::deserialize(groupSecretParamsIn) { - Ok(result) => result, - Err(_) => return FFI_RETURN_INPUT_ERROR, - }; - - FFI_RETURN_OK -} - -pub fn GroupSecretParams_getMasterKey( - groupSecretParamsIn: &[u8], - groupMasterKeyOut: &mut [u8], -) -> i32 { - let group_secret_params: api::groups::GroupSecretParams = - match bincode::deserialize(groupSecretParamsIn) { - Ok(result) => result, - Err(_) => return FFI_RETURN_INTERNAL_ERROR, - }; - let group_master_key = group_secret_params.get_master_key(); - groupMasterKeyOut.copy_from_slice(&bincode::serialize(&group_master_key).unwrap()); - FFI_RETURN_OK -} - -pub fn GroupSecretParams_getPublicParams( - groupSecretParamsIn: &[u8], - groupPublicParamsOut: &mut [u8], -) -> i32 { - let group_secret_params: api::groups::GroupSecretParams = - match bincode::deserialize(groupSecretParamsIn) { - Ok(result) => result, - Err(_) => return FFI_RETURN_INTERNAL_ERROR, - }; - let group_public_params = group_secret_params.get_public_params(); - groupPublicParamsOut.copy_from_slice(&bincode::serialize(&group_public_params).unwrap()); - FFI_RETURN_OK -} - -pub fn GroupSecretParams_encryptUuid( - groupSecretParamsIn: &[u8], - uuidIn: &[u8], - uuidCiphertextOut: &mut [u8], -) -> i32 { - let group_secret_params: api::groups::GroupSecretParams = - match bincode::deserialize(groupSecretParamsIn) { - Ok(result) => result, - Err(_) => return FFI_RETURN_INTERNAL_ERROR, - }; - - let uuid: simple_types::UidBytes = match bincode::deserialize(uuidIn) { - Ok(result) => result, - Err(_) => return FFI_RETURN_INPUT_ERROR, - }; - let uuid_ciphertext = group_secret_params.encrypt_uuid(uuid); - uuidCiphertextOut.copy_from_slice(&bincode::serialize(&uuid_ciphertext).unwrap()); - FFI_RETURN_OK -} - -pub fn GroupSecretParams_decryptUuid( - groupSecretParamsIn: &[u8], - uuidCiphertextIn: &[u8], - uuidOut: &mut [u8], -) -> i32 { - let group_secret_params: api::groups::GroupSecretParams = - match bincode::deserialize(groupSecretParamsIn) { - Ok(result) => result, - Err(_) => return FFI_RETURN_INTERNAL_ERROR, - }; - - let uuid_ciphertext: api::groups::UuidCiphertext = match bincode::deserialize(uuidCiphertextIn) - { - Ok(result) => result, - Err(_) => return FFI_RETURN_INPUT_ERROR, - }; - let uuid = match group_secret_params.decrypt_uuid(uuid_ciphertext) { - Ok(result) => result, - Err(_) => return FFI_RETURN_INPUT_ERROR, - }; - uuidOut.copy_from_slice(&bincode::serialize(&uuid).unwrap()); - FFI_RETURN_OK -} - -pub fn GroupSecretParams_encryptProfileKey( - groupSecretParamsIn: &[u8], - profileKeyIn: &[u8], - uuidIn: &[u8], - profileKeyCiphertextOut: &mut [u8], -) -> i32 { - let group_secret_params: api::groups::GroupSecretParams = - match bincode::deserialize(groupSecretParamsIn) { - Ok(result) => result, - Err(_) => return FFI_RETURN_INTERNAL_ERROR, - }; - - let profile_key: api::profiles::ProfileKey = match bincode::deserialize(profileKeyIn) { - Ok(result) => result, - Err(_) => return FFI_RETURN_INPUT_ERROR, - }; - - let uuid: simple_types::UidBytes = match bincode::deserialize(uuidIn) { - Ok(result) => result, - Err(_) => return FFI_RETURN_INPUT_ERROR, - }; - let profile_key_ciphertext = group_secret_params.encrypt_profile_key(profile_key, uuid); - profileKeyCiphertextOut.copy_from_slice(&bincode::serialize(&profile_key_ciphertext).unwrap()); - FFI_RETURN_OK -} - -pub fn GroupSecretParams_decryptProfileKey( - groupSecretParamsIn: &[u8], - profileKeyCiphertextIn: &[u8], - uuidIn: &[u8], - profileKeyOut: &mut [u8], -) -> i32 { - let group_secret_params: api::groups::GroupSecretParams = - match bincode::deserialize(groupSecretParamsIn) { - Ok(result) => result, - Err(_) => return FFI_RETURN_INTERNAL_ERROR, - }; - - let profile_key_ciphertext: api::groups::ProfileKeyCiphertext = - match bincode::deserialize(profileKeyCiphertextIn) { - Ok(result) => result, - Err(_) => return FFI_RETURN_INPUT_ERROR, - }; - - let uuid: simple_types::UidBytes = match bincode::deserialize(uuidIn) { - Ok(result) => result, - Err(_) => return FFI_RETURN_INPUT_ERROR, - }; - let profile_key = match group_secret_params.decrypt_profile_key(profile_key_ciphertext, uuid) { - Ok(result) => result, - Err(_) => return FFI_RETURN_INPUT_ERROR, - }; - profileKeyOut.copy_from_slice(&bincode::serialize(&profile_key).unwrap()); - FFI_RETURN_OK -} - -pub fn GroupSecretParams_encryptBlobDeterministic( - groupSecretParamsIn: &[u8], - randomnessIn: &[u8], - plaintextIn: &[u8], - blobCiphertextOut: &mut [u8], -) -> i32 { - let group_secret_params: api::groups::GroupSecretParams = - match bincode::deserialize(groupSecretParamsIn) { - Ok(result) => result, - Err(_) => return FFI_RETURN_INTERNAL_ERROR, - }; - - let randomness: simple_types::RandomnessBytes = match bincode::deserialize(randomnessIn) { - Ok(result) => result, - Err(_) => return FFI_RETURN_INPUT_ERROR, - }; - let plaintext = plaintextIn; - let blob_ciphertext = match group_secret_params.encrypt_blob(randomness, plaintext) { - Ok(result) => result, - Err(_) => return FFI_RETURN_INPUT_ERROR, - }; - blobCiphertextOut.copy_from_slice(&blob_ciphertext); - FFI_RETURN_OK -} - -pub fn GroupSecretParams_decryptBlob( - groupSecretParamsIn: &[u8], - blobCiphertextIn: &[u8], - plaintextOut: &mut [u8], -) -> i32 { - let group_secret_params: api::groups::GroupSecretParams = - match bincode::deserialize(groupSecretParamsIn) { - Ok(result) => result, - Err(_) => return FFI_RETURN_INTERNAL_ERROR, - }; - let blob_ciphertext = blobCiphertextIn; - let plaintext = match group_secret_params.decrypt_blob(blob_ciphertext) { - Ok(result) => result, - Err(_) => return FFI_RETURN_INPUT_ERROR, - }; - plaintextOut.copy_from_slice(&plaintext); - FFI_RETURN_OK -} - -pub fn ServerSecretParams_generateDeterministic( - randomnessIn: &[u8], - serverSecretParamsOut: &mut [u8], -) -> i32 { - let randomness: simple_types::RandomnessBytes = match bincode::deserialize(randomnessIn) { - Ok(result) => result, - Err(_) => return FFI_RETURN_INPUT_ERROR, - }; - let server_secret_params = api::ServerSecretParams::generate(randomness); - serverSecretParamsOut.copy_from_slice(&bincode::serialize(&server_secret_params).unwrap()); - FFI_RETURN_OK -} - -pub fn ServerSecretParams_checkValidContents(serverSecretParamsIn: &[u8]) -> i32 { - let _: api::ServerSecretParams = match bincode::deserialize(serverSecretParamsIn) { - Ok(result) => result, - Err(_) => return FFI_RETURN_INPUT_ERROR, - }; - - FFI_RETURN_OK -} - -pub fn ServerSecretParams_getPublicParams( - serverSecretParamsIn: &[u8], - serverPublicParamsOut: &mut [u8], -) -> i32 { - let server_secret_params: api::ServerSecretParams = - match bincode::deserialize(serverSecretParamsIn) { - Ok(result) => result, - Err(_) => return FFI_RETURN_INTERNAL_ERROR, - }; - let server_public_params = server_secret_params.get_public_params(); - serverPublicParamsOut.copy_from_slice(&bincode::serialize(&server_public_params).unwrap()); - FFI_RETURN_OK -} - -pub fn ServerSecretParams_signDeterministic( - serverSecretParamsIn: &[u8], - randomnessIn: &[u8], - messageIn: &[u8], - notarySignatureOut: &mut [u8], -) -> i32 { - let server_secret_params: api::ServerSecretParams = - match bincode::deserialize(serverSecretParamsIn) { - Ok(result) => result, - Err(_) => return FFI_RETURN_INTERNAL_ERROR, - }; - - let randomness: simple_types::RandomnessBytes = match bincode::deserialize(randomnessIn) { - Ok(result) => result, - Err(_) => return FFI_RETURN_INPUT_ERROR, - }; - let message = messageIn; - let notary_signature = match server_secret_params.sign(randomness, message) { - Ok(result) => result, - Err(_) => return FFI_RETURN_INPUT_ERROR, - }; - notarySignatureOut.copy_from_slice(¬ary_signature); - FFI_RETURN_OK -} - -pub fn ServerPublicParams_receiveAuthCredential( - serverPublicParamsIn: &[u8], - uuidIn: &[u8], - redemptionTimeIn: u32, - authCredentialResponseIn: &[u8], - authCredentialOut: &mut [u8], -) -> i32 { - let server_public_params: api::ServerPublicParams = - match bincode::deserialize(serverPublicParamsIn) { - Ok(result) => result, - Err(_) => return FFI_RETURN_INTERNAL_ERROR, - }; - - let uuid: simple_types::UidBytes = match bincode::deserialize(uuidIn) { - Ok(result) => result, - Err(_) => return FFI_RETURN_INPUT_ERROR, - }; - let redemption_time = redemptionTimeIn; - - let auth_credential_response: api::auth::AuthCredentialResponse = - match bincode::deserialize(authCredentialResponseIn) { - Ok(result) => result, - Err(_) => return FFI_RETURN_INPUT_ERROR, - }; - let auth_credential = match server_public_params.receive_auth_credential( - uuid, - redemption_time, - &auth_credential_response, - ) { - Ok(result) => result, - Err(_) => return FFI_RETURN_INPUT_ERROR, - }; - authCredentialOut.copy_from_slice(&bincode::serialize(&auth_credential).unwrap()); - FFI_RETURN_OK -} - -pub fn ServerPublicParams_createAuthCredentialPresentationDeterministic( - serverPublicParamsIn: &[u8], - randomnessIn: &[u8], - groupSecretParamsIn: &[u8], - authCredentialIn: &[u8], - authCredentialPresentationOut: &mut [u8], -) -> i32 { - let server_public_params: api::ServerPublicParams = - match bincode::deserialize(serverPublicParamsIn) { - Ok(result) => result, - Err(_) => return FFI_RETURN_INTERNAL_ERROR, - }; - - let randomness: simple_types::RandomnessBytes = match bincode::deserialize(randomnessIn) { - Ok(result) => result, - Err(_) => return FFI_RETURN_INPUT_ERROR, - }; - - let group_secret_params: api::groups::GroupSecretParams = - match bincode::deserialize(groupSecretParamsIn) { - Ok(result) => result, - Err(_) => return FFI_RETURN_INPUT_ERROR, - }; - - let auth_credential: api::auth::AuthCredential = match bincode::deserialize(authCredentialIn) { - Ok(result) => result, - Err(_) => return FFI_RETURN_INPUT_ERROR, - }; - let auth_credential_presentation = server_public_params.create_auth_credential_presentation( - randomness, - group_secret_params, - auth_credential, - ); - authCredentialPresentationOut - .copy_from_slice(&bincode::serialize(&auth_credential_presentation).unwrap()); - FFI_RETURN_OK -} - -pub fn ServerPublicParams_createProfileKeyCredentialRequestContextDeterministic( - serverPublicParamsIn: &[u8], - randomnessIn: &[u8], - uuidIn: &[u8], - profileKeyIn: &[u8], - profileKeyCredentialRequestContextOut: &mut [u8], -) -> i32 { - let server_public_params: api::ServerPublicParams = - match bincode::deserialize(serverPublicParamsIn) { - Ok(result) => result, - Err(_) => return FFI_RETURN_INTERNAL_ERROR, - }; - - let randomness: simple_types::RandomnessBytes = match bincode::deserialize(randomnessIn) { - Ok(result) => result, - Err(_) => return FFI_RETURN_INPUT_ERROR, - }; - - let uuid: simple_types::UidBytes = match bincode::deserialize(uuidIn) { - Ok(result) => result, - Err(_) => return FFI_RETURN_INPUT_ERROR, - }; - - let profile_key: api::profiles::ProfileKey = match bincode::deserialize(profileKeyIn) { - Ok(result) => result, - Err(_) => return FFI_RETURN_INPUT_ERROR, - }; - let profile_key_credential_request_context = server_public_params - .create_profile_key_credential_request_context(randomness, uuid, profile_key); - profileKeyCredentialRequestContextOut - .copy_from_slice(&bincode::serialize(&profile_key_credential_request_context).unwrap()); - FFI_RETURN_OK -} - -pub fn ServerPublicParams_receiveProfileKeyCredential( - serverPublicParamsIn: &[u8], - profileKeyCredentialRequestContextIn: &[u8], - profileKeyCredentialResponseIn: &[u8], - profileKeyCredentialOut: &mut [u8], -) -> i32 { - let server_public_params: api::ServerPublicParams = - match bincode::deserialize(serverPublicParamsIn) { - Ok(result) => result, - Err(_) => return FFI_RETURN_INTERNAL_ERROR, - }; - - let profile_key_credential_request_context: api::profiles::ProfileKeyCredentialRequestContext = - match bincode::deserialize(profileKeyCredentialRequestContextIn) { - Ok(result) => result, - Err(_) => return FFI_RETURN_INPUT_ERROR, - }; - - let profile_key_credential_response: api::profiles::ProfileKeyCredentialResponse = - match bincode::deserialize(profileKeyCredentialResponseIn) { - Ok(result) => result, - Err(_) => return FFI_RETURN_INPUT_ERROR, - }; - let profile_key_credential = match server_public_params.receive_profile_key_credential( - &profile_key_credential_request_context, - &profile_key_credential_response, - ) { - Ok(result) => result, - Err(_) => return FFI_RETURN_INPUT_ERROR, - }; - profileKeyCredentialOut.copy_from_slice(&bincode::serialize(&profile_key_credential).unwrap()); - FFI_RETURN_OK -} - -pub fn ServerPublicParams_createProfileKeyCredentialPresentationDeterministic( - serverPublicParamsIn: &[u8], - randomnessIn: &[u8], - groupSecretParamsIn: &[u8], - profileKeyCredentialIn: &[u8], - profileKeyCredentialPresentationOut: &mut [u8], -) -> i32 { - let server_public_params: api::ServerPublicParams = - match bincode::deserialize(serverPublicParamsIn) { - Ok(result) => result, - Err(_) => return FFI_RETURN_INTERNAL_ERROR, - }; - - let randomness: simple_types::RandomnessBytes = match bincode::deserialize(randomnessIn) { - Ok(result) => result, - Err(_) => return FFI_RETURN_INPUT_ERROR, - }; - - let group_secret_params: api::groups::GroupSecretParams = - match bincode::deserialize(groupSecretParamsIn) { - Ok(result) => result, - Err(_) => return FFI_RETURN_INPUT_ERROR, - }; - - let profile_key_credential: api::profiles::ProfileKeyCredential = - match bincode::deserialize(profileKeyCredentialIn) { - Ok(result) => result, - Err(_) => return FFI_RETURN_INPUT_ERROR, - }; - let profile_key_credential_presentation = server_public_params - .create_profile_key_credential_presentation( - randomness, - group_secret_params, - profile_key_credential, - ); - profileKeyCredentialPresentationOut - .copy_from_slice(&bincode::serialize(&profile_key_credential_presentation).unwrap()); - FFI_RETURN_OK -} - -pub fn ServerSecretParams_issueAuthCredentialDeterministic( - serverSecretParamsIn: &[u8], - randomnessIn: &[u8], - uuidIn: &[u8], - redemptionTimeIn: u32, - authCredentialResponseOut: &mut [u8], -) -> i32 { - let server_secret_params: api::ServerSecretParams = - match bincode::deserialize(serverSecretParamsIn) { - Ok(result) => result, - Err(_) => return FFI_RETURN_INTERNAL_ERROR, - }; - - let randomness: simple_types::RandomnessBytes = match bincode::deserialize(randomnessIn) { - Ok(result) => result, - Err(_) => return FFI_RETURN_INPUT_ERROR, - }; - - let uuid: simple_types::UidBytes = match bincode::deserialize(uuidIn) { - Ok(result) => result, - Err(_) => return FFI_RETURN_INPUT_ERROR, - }; - let redemption_time = redemptionTimeIn; - let auth_credential_response = - server_secret_params.issue_auth_credential(randomness, uuid, redemption_time); - authCredentialResponseOut - .copy_from_slice(&bincode::serialize(&auth_credential_response).unwrap()); - FFI_RETURN_OK -} - -pub fn ServerSecretParams_verifyAuthCredentialPresentation( - serverSecretParamsIn: &[u8], - groupPublicParamsIn: &[u8], - authCredentialPresentationIn: &[u8], -) -> i32 { - let server_secret_params: api::ServerSecretParams = - match bincode::deserialize(serverSecretParamsIn) { - Ok(result) => result, - Err(_) => return FFI_RETURN_INTERNAL_ERROR, - }; - - let group_public_params: api::groups::GroupPublicParams = - match bincode::deserialize(groupPublicParamsIn) { - Ok(result) => result, - Err(_) => return FFI_RETURN_INPUT_ERROR, - }; - - let auth_credential_presentation: api::auth::AuthCredentialPresentation = - match bincode::deserialize(authCredentialPresentationIn) { - Ok(result) => result, - Err(_) => return FFI_RETURN_INPUT_ERROR, - }; - match server_secret_params - .verify_auth_credential_presentation(group_public_params, &auth_credential_presentation) - { - Ok(_) => (), - Err(_) => return FFI_RETURN_INPUT_ERROR, - } - FFI_RETURN_OK -} - -pub fn ServerSecretParams_issueProfileKeyCredentialDeterministic( - serverSecretParamsIn: &[u8], - randomnessIn: &[u8], - profileKeyCredentialRequestIn: &[u8], - uuidIn: &[u8], - profileKeyCommitmentIn: &[u8], - profileKeyCredentialResponseOut: &mut [u8], -) -> i32 { - let server_secret_params: api::ServerSecretParams = - match bincode::deserialize(serverSecretParamsIn) { - Ok(result) => result, - Err(_) => return FFI_RETURN_INTERNAL_ERROR, - }; - - let randomness: simple_types::RandomnessBytes = match bincode::deserialize(randomnessIn) { - Ok(result) => result, - Err(_) => return FFI_RETURN_INPUT_ERROR, - }; - - let profile_key_credential_request: api::profiles::ProfileKeyCredentialRequest = - match bincode::deserialize(profileKeyCredentialRequestIn) { - Ok(result) => result, - Err(_) => return FFI_RETURN_INPUT_ERROR, - }; - - let uuid: simple_types::UidBytes = match bincode::deserialize(uuidIn) { - Ok(result) => result, - Err(_) => return FFI_RETURN_INPUT_ERROR, - }; - - let profile_key_commitment: api::profiles::ProfileKeyCommitment = - match bincode::deserialize(profileKeyCommitmentIn) { - Ok(result) => result, - Err(_) => return FFI_RETURN_INPUT_ERROR, - }; - let profile_key_credential_response = match server_secret_params.issue_profile_key_credential( - randomness, - &profile_key_credential_request, - uuid, - profile_key_commitment, - ) { - Ok(result) => result, - Err(_) => return FFI_RETURN_INPUT_ERROR, - }; - profileKeyCredentialResponseOut - .copy_from_slice(&bincode::serialize(&profile_key_credential_response).unwrap()); - FFI_RETURN_OK -} - -pub fn ServerSecretParams_verifyProfileKeyCredentialPresentation( - serverSecretParamsIn: &[u8], - groupPublicParamsIn: &[u8], - profileKeyCredentialPresentationIn: &[u8], -) -> i32 { - let server_secret_params: api::ServerSecretParams = - match bincode::deserialize(serverSecretParamsIn) { - Ok(result) => result, - Err(_) => return FFI_RETURN_INTERNAL_ERROR, - }; - - let group_public_params: api::groups::GroupPublicParams = - match bincode::deserialize(groupPublicParamsIn) { - Ok(result) => result, - Err(_) => return FFI_RETURN_INPUT_ERROR, - }; - - let profile_key_credential_presentation: api::profiles::ProfileKeyCredentialPresentation = - match bincode::deserialize(profileKeyCredentialPresentationIn) { - Ok(result) => result, - Err(_) => return FFI_RETURN_INPUT_ERROR, - }; - match server_secret_params.verify_profile_key_credential_presentation( - group_public_params, - &profile_key_credential_presentation, - ) { - Ok(_) => (), - Err(_) => return FFI_RETURN_INPUT_ERROR, - } - FFI_RETURN_OK -} - -pub fn GroupPublicParams_checkValidContents(groupPublicParamsIn: &[u8]) -> i32 { - let _: api::groups::GroupPublicParams = match bincode::deserialize(groupPublicParamsIn) { - Ok(result) => result, - Err(_) => return FFI_RETURN_INPUT_ERROR, - }; - - FFI_RETURN_OK -} - -pub fn GroupPublicParams_getGroupIdentifier( - groupPublicParamsIn: &[u8], - groupIdentifierOut: &mut [u8], -) -> i32 { - let group_public_params: api::groups::GroupPublicParams = - match bincode::deserialize(groupPublicParamsIn) { - Ok(result) => result, - Err(_) => return FFI_RETURN_INTERNAL_ERROR, - }; - let group_identifier = group_public_params.get_group_identifier(); - groupIdentifierOut.copy_from_slice(&bincode::serialize(&group_identifier).unwrap()); - FFI_RETURN_OK -} - -pub fn ServerPublicParams_checkValidContents(serverPublicParamsIn: &[u8]) -> i32 { - let _: api::ServerPublicParams = match bincode::deserialize(serverPublicParamsIn) { - Ok(result) => result, - Err(_) => return FFI_RETURN_INPUT_ERROR, - }; - - FFI_RETURN_OK -} - -pub fn ServerPublicParams_verifySignature( - serverPublicParamsIn: &[u8], - messageIn: &[u8], - notarySignatureIn: &[u8], -) -> i32 { - let server_public_params: api::ServerPublicParams = - match bincode::deserialize(serverPublicParamsIn) { - Ok(result) => result, - Err(_) => return FFI_RETURN_INTERNAL_ERROR, - }; - let message = messageIn; - let mut notary_signature: simple_types::NotarySignatureBytes = [0u8; SIGNATURE_LEN]; - notary_signature.copy_from_slice(notarySignatureIn); - match server_public_params.verify_signature(message, notary_signature) { - Ok(_) => (), - _ => return FFI_RETURN_INPUT_ERROR, - }; - FFI_RETURN_OK -} - -pub fn AuthCredentialResponse_checkValidContents(authCredentialResponseIn: &[u8]) -> i32 { - let _: api::auth::AuthCredentialResponse = match bincode::deserialize(authCredentialResponseIn) - { - Ok(result) => result, - Err(_) => return FFI_RETURN_INPUT_ERROR, - }; - - FFI_RETURN_OK -} - -pub fn AuthCredential_checkValidContents(authCredentialIn: &[u8]) -> i32 { - let _: api::auth::AuthCredential = match bincode::deserialize(authCredentialIn) { - Ok(result) => result, - Err(_) => return FFI_RETURN_INPUT_ERROR, - }; - - FFI_RETURN_OK -} - -pub fn AuthCredentialPresentation_checkValidContents(authCredentialPresentationIn: &[u8]) -> i32 { - let _: api::auth::AuthCredentialPresentation = - match bincode::deserialize(authCredentialPresentationIn) { - Ok(result) => result, - Err(_) => return FFI_RETURN_INPUT_ERROR, - }; - - FFI_RETURN_OK -} - -pub fn AuthCredentialPresentation_getUuidCiphertext( - authCredentialPresentationIn: &[u8], - uuidCiphertextOut: &mut [u8], -) -> i32 { - let auth_credential_presentation: api::auth::AuthCredentialPresentation = - match bincode::deserialize(authCredentialPresentationIn) { - Ok(result) => result, - Err(_) => return FFI_RETURN_INTERNAL_ERROR, - }; - let uuid_ciphertext = auth_credential_presentation.get_uuid_ciphertext(); - uuidCiphertextOut.copy_from_slice(&bincode::serialize(&uuid_ciphertext).unwrap()); - FFI_RETURN_OK -} - -pub fn AuthCredentialPresentation_getRedemptionTime( - authCredentialPresentationIn: &[u8], - redemptionTimeOut: &mut [u8], -) -> i32 { - let auth_credential_presentation: api::auth::AuthCredentialPresentation = - match bincode::deserialize(authCredentialPresentationIn) { - Ok(result) => result, - Err(_) => return FFI_RETURN_INTERNAL_ERROR, - }; - let redemption_time = auth_credential_presentation.get_redemption_time(); - redemptionTimeOut.copy_from_slice(&redemption_time.to_be_bytes()); - FFI_RETURN_OK -} - -pub fn ProfileKeyCredentialRequestContext_checkValidContents( - profileKeyCredentialRequestContextIn: &[u8], -) -> i32 { - let _: api::profiles::ProfileKeyCredentialRequestContext = - match bincode::deserialize(profileKeyCredentialRequestContextIn) { - Ok(result) => result, - Err(_) => return FFI_RETURN_INPUT_ERROR, - }; - - FFI_RETURN_OK -} - -pub fn ProfileKeyCredentialRequestContext_getRequest( - profileKeyCredentialRequestContextIn: &[u8], - profileKeyCredentialRequestOut: &mut [u8], -) -> i32 { - let profile_key_credential_request_context: api::profiles::ProfileKeyCredentialRequestContext = - match bincode::deserialize(profileKeyCredentialRequestContextIn) { - Ok(result) => result, - Err(_) => return FFI_RETURN_INTERNAL_ERROR, - }; - let profile_key_credential_request = profile_key_credential_request_context.get_request(); - profileKeyCredentialRequestOut - .copy_from_slice(&bincode::serialize(&profile_key_credential_request).unwrap()); - FFI_RETURN_OK -} - -pub fn ProfileKeyCredentialRequest_checkValidContents(profileKeyCredentialRequestIn: &[u8]) -> i32 { - let _: api::profiles::ProfileKeyCredentialRequest = - match bincode::deserialize(profileKeyCredentialRequestIn) { - Ok(result) => result, - Err(_) => return FFI_RETURN_INPUT_ERROR, - }; - - FFI_RETURN_OK -} - -pub fn ProfileKeyCredentialResponse_checkValidContents( - profileKeyCredentialResponseIn: &[u8], -) -> i32 { - let _: api::profiles::ProfileKeyCredentialResponse = - match bincode::deserialize(profileKeyCredentialResponseIn) { - Ok(result) => result, - Err(_) => return FFI_RETURN_INPUT_ERROR, - }; - - FFI_RETURN_OK -} - -pub fn ProfileKeyCredential_checkValidContents(profileKeyCredentialIn: &[u8]) -> i32 { - let _: api::profiles::ProfileKeyCredential = match bincode::deserialize(profileKeyCredentialIn) - { - Ok(result) => result, - Err(_) => return FFI_RETURN_INPUT_ERROR, - }; - - FFI_RETURN_OK -} - -pub fn ProfileKeyCredentialPresentation_checkValidContents( - profileKeyCredentialPresentationIn: &[u8], -) -> i32 { - let _: api::profiles::ProfileKeyCredentialPresentation = - match bincode::deserialize(profileKeyCredentialPresentationIn) { - Ok(result) => result, - Err(_) => return FFI_RETURN_INPUT_ERROR, - }; - - FFI_RETURN_OK -} - -pub fn ProfileKeyCredentialPresentation_getUuidCiphertext( - profileKeyCredentialPresentationIn: &[u8], - uuidCiphertextOut: &mut [u8], -) -> i32 { - let profile_key_credential_presentation: api::profiles::ProfileKeyCredentialPresentation = - match bincode::deserialize(profileKeyCredentialPresentationIn) { - Ok(result) => result, - Err(_) => return FFI_RETURN_INTERNAL_ERROR, - }; - let uuid_ciphertext = profile_key_credential_presentation.get_uuid_ciphertext(); - uuidCiphertextOut.copy_from_slice(&bincode::serialize(&uuid_ciphertext).unwrap()); - FFI_RETURN_OK -} - -pub fn ProfileKeyCredentialPresentation_getProfileKeyCiphertext( - profileKeyCredentialPresentationIn: &[u8], - profileKeyCiphertextOut: &mut [u8], -) -> i32 { - let profile_key_credential_presentation: api::profiles::ProfileKeyCredentialPresentation = - match bincode::deserialize(profileKeyCredentialPresentationIn) { - Ok(result) => result, - Err(_) => return FFI_RETURN_INTERNAL_ERROR, - }; - let profile_key_ciphertext = profile_key_credential_presentation.get_profile_key_ciphertext(); - profileKeyCiphertextOut.copy_from_slice(&bincode::serialize(&profile_key_ciphertext).unwrap()); - FFI_RETURN_OK -} - -pub fn UuidCiphertext_checkValidContents(uuidCiphertextIn: &[u8]) -> i32 { - let _: api::groups::UuidCiphertext = match bincode::deserialize(uuidCiphertextIn) { - Ok(result) => result, - Err(_) => return FFI_RETURN_INPUT_ERROR, - }; - - FFI_RETURN_OK -} - -pub fn ProfileKeyCiphertext_checkValidContents(profileKeyCiphertextIn: &[u8]) -> i32 { - let _: api::groups::ProfileKeyCiphertext = match bincode::deserialize(profileKeyCiphertextIn) { - Ok(result) => result, - Err(_) => return FFI_RETURN_INPUT_ERROR, - }; - - FFI_RETURN_OK -} - -pub fn Randomness_checkValidContents(randomnessIn: &[u8]) -> i32 { - let _: simple_types::RandomnessBytes = match bincode::deserialize(randomnessIn) { - Ok(result) => result, - Err(_) => return FFI_RETURN_INPUT_ERROR, - }; - - FFI_RETURN_OK -} - -pub fn Uuid_checkValidContents(uuidIn: &[u8]) -> i32 { - let _: simple_types::UidBytes = match bincode::deserialize(uuidIn) { - Ok(result) => result, - Err(_) => return FFI_RETURN_INPUT_ERROR, - }; - - FFI_RETURN_OK -} diff --git a/net/gurk-rs/files/vendor/zkgroup/src/lib.rs b/net/gurk-rs/files/vendor/zkgroup/src/lib.rs deleted file mode 100644 index 3ced5d5..0000000 --- a/net/gurk-rs/files/vendor/zkgroup/src/lib.rs +++ /dev/null @@ -1,15 +0,0 @@ -// -// Copyright (C) 2020 Signal Messenger, LLC. -// All rights reserved. -// -// SPDX-License-Identifier: GPL-3.0-only -// - -pub mod api; -pub mod common; -pub mod crypto; -pub mod ffi; -pub use api::*; -pub use common::constants::*; -pub use common::errors::*; -pub use common::simple_types::*; diff --git a/net/gurk-rs/files/vendor/zkgroup/tests/integration_tests.rs b/net/gurk-rs/files/vendor/zkgroup/tests/integration_tests.rs deleted file mode 100644 index c8632b9..0000000 --- a/net/gurk-rs/files/vendor/zkgroup/tests/integration_tests.rs +++ /dev/null @@ -1,348 +0,0 @@ -// -// Copyright (C) 2020 Signal Messenger, LLC. -// All rights reserved. -// -// SPDX-License-Identifier: GPL-3.0-only -// - -#![allow(non_snake_case)] -extern crate zkgroup; - -use curve25519_dalek::ristretto::RistrettoPoint; -use sha2::Sha256; - -#[test] -fn test_lizard() { - let p = RistrettoPoint::lizard_encode::(&zkgroup::common::constants::TEST_ARRAY_16); - let data_out = p.lizard_decode::(); - assert!(data_out.unwrap() == zkgroup::common::constants::TEST_ARRAY_16); -} -pub const AUTH_CREDENTIAL_PRESENTATION_RESULT: [u8; zkgroup::AUTH_CREDENTIAL_PRESENTATION_LEN] = [ - 0x00, 0x0c, 0xde, 0x97, 0x97, 0x37, 0xed, 0x30, 0xbb, 0xeb, 0x16, 0x36, 0x2e, 0x4e, 0x07, 0x69, - 0x45, 0xce, 0x02, 0x06, 0x9f, 0x72, 0x7b, 0x0e, 0xd4, 0xc3, 0xc3, 0x3c, 0x01, 0x1e, 0x82, 0x54, - 0x6e, 0x1c, 0xdf, 0x08, 0x1f, 0xbd, 0xf3, 0x7c, 0x03, 0xa8, 0x51, 0xad, 0x06, 0x0b, 0xdc, 0xbf, - 0x63, 0x78, 0xcb, 0x4c, 0xb1, 0x6d, 0xc3, 0x15, 0x4d, 0x08, 0xde, 0x54, 0x39, 0xb5, 0x32, 0x32, - 0x03, 0x72, 0x9d, 0x18, 0x41, 0xb5, 0x17, 0x03, 0x3a, 0xf2, 0xfd, 0x17, 0x7d, 0x30, 0x49, 0x1c, - 0x13, 0x8a, 0xe7, 0x23, 0x65, 0x57, 0x34, 0xf6, 0xe5, 0xcc, 0x01, 0xc0, 0x06, 0x96, 0xf4, 0xe9, - 0x20, 0x96, 0xd8, 0xc3, 0x3d, 0xf2, 0x6b, 0xa2, 0xa8, 0x20, 0xd4, 0x2e, 0x97, 0x35, 0xd3, 0x0f, - 0x8e, 0xee, 0xf9, 0x6d, 0x39, 0x90, 0x79, 0x07, 0x3c, 0x09, 0x9f, 0x70, 0x35, 0x52, 0x3b, 0xfe, - 0x71, 0x66, 0x38, 0x65, 0x93, 0x19, 0xd3, 0xc3, 0x6a, 0xd3, 0x4c, 0x00, 0xef, 0x88, 0x50, 0xf6, - 0x63, 0xc4, 0xd9, 0x30, 0x30, 0x23, 0x50, 0x74, 0x31, 0x2a, 0x88, 0x78, 0xb6, 0xa5, 0xc5, 0xdf, - 0x4f, 0xbc, 0x7d, 0x32, 0x93, 0x52, 0x78, 0xbf, 0xa5, 0x99, 0x6b, 0x44, 0xab, 0x75, 0xd6, 0xf0, - 0x6f, 0x4c, 0x30, 0xb9, 0x86, 0x40, 0xad, 0x5d, 0xe7, 0x47, 0x42, 0x65, 0x6c, 0x89, 0x77, 0x56, - 0x7d, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfd, 0xe6, 0x9f, 0x82, 0xad, 0x2d, 0xcb, - 0x49, 0x09, 0x65, 0x0a, 0xc6, 0xb2, 0x57, 0x38, 0x41, 0xaf, 0x56, 0x8f, 0xef, 0x82, 0x2b, 0x32, - 0xb4, 0x5f, 0x62, 0x5a, 0x76, 0x46, 0x91, 0xa7, 0x04, 0xd1, 0x1b, 0x6f, 0x38, 0x52, 0x61, 0x46, - 0x81, 0x17, 0xea, 0xd5, 0x7f, 0xa6, 0x23, 0x33, 0x8e, 0x21, 0xc6, 0x6e, 0xd8, 0x46, 0xab, 0x65, - 0x80, 0x9f, 0xca, 0xc1, 0x58, 0x06, 0x6d, 0x8e, 0x0e, 0x44, 0x40, 0x77, 0xb9, 0x95, 0x40, 0xd8, - 0x86, 0xe7, 0xdc, 0x09, 0x55, 0x5d, 0xd6, 0xfa, 0xea, 0x2c, 0xd3, 0x69, 0x7f, 0x1e, 0x08, 0x9f, - 0x82, 0xd5, 0x4e, 0x5d, 0x0f, 0xe4, 0xa1, 0x85, 0x00, 0x8b, 0x5c, 0xbc, 0x39, 0x79, 0x39, 0x1a, - 0xd7, 0x16, 0x86, 0xbc, 0x03, 0xbe, 0x7b, 0x00, 0xea, 0x7e, 0x42, 0xc0, 0x8d, 0x9f, 0x1d, 0x75, - 0xc3, 0xa5, 0x6c, 0x27, 0xae, 0x24, 0x67, 0xb8, 0x06, 0x36, 0xc0, 0xb5, 0x34, 0x3e, 0xda, 0x7c, - 0xd5, 0x78, 0xba, 0x88, 0xdd, 0xb7, 0xa0, 0x76, 0x65, 0x68, 0x47, 0x7f, 0xed, 0x63, 0xcf, 0x53, - 0x18, 0x62, 0x12, 0x2c, 0x6c, 0x15, 0xb4, 0xa7, 0x07, 0x97, 0x3d, 0x41, 0x78, 0x2c, 0xfc, 0x0e, - 0xf4, 0xfe, 0x6c, 0x31, 0x15, 0x98, 0x8a, 0x2e, 0x33, 0x90, 0x15, 0x93, 0x8d, 0x2d, 0xf0, 0xa5, - 0xd3, 0x02, 0x37, 0xa2, 0x59, 0x2c, 0xc1, 0x0c, 0x05, 0xa9, 0xe4, 0xef, 0x6b, 0x69, 0x5b, 0xca, - 0x99, 0x73, 0x6b, 0x1a, 0x49, 0xea, 0x39, 0x60, 0x6a, 0x38, 0x1e, 0xcf, 0xb0, 0x5e, 0xfe, 0x60, - 0xd2, 0x8b, 0x54, 0x82, 0x3e, 0xc5, 0xa3, 0x68, 0x0c, 0x76, 0x5d, 0xe9, 0xdf, 0x4c, 0xfa, 0x54, - 0x87, 0xf3, 0x60, 0xe2, 0x9e, 0x99, 0x34, 0x3e, 0x91, 0x81, 0x1b, 0xae, 0xc3, 0x31, 0xc4, 0x68, - 0x09, 0x85, 0xe6, 0x08, 0xca, 0x5d, 0x40, 0x8e, 0x21, 0x72, 0x5c, 0x6a, 0xa1, 0xb6, 0x1d, 0x5a, - 0x8b, 0x48, 0xd7, 0x5f, 0x4a, 0xaa, 0x9a, 0x3c, 0xbe, 0x88, 0xd3, 0xe0, 0xf1, 0xa5, 0x43, 0x19, - 0x08, 0x1f, 0x77, 0xc7, 0x2c, 0x8f, 0x52, 0x54, 0x74, 0x40, 0xe2, 0x01, 0x00, -]; - -pub const PROFILE_KEY_CREDENTIAL_PRESENTATION_RESULT: [u8; - zkgroup::PROFILE_KEY_CREDENTIAL_PRESENTATION_LEN] = [ - 0x00, 0xc4, 0xd1, 0x9b, 0xca, 0x1a, 0xe8, 0x44, 0x58, 0x51, 0x68, 0x86, 0x9d, 0xa4, 0x13, 0x3e, - 0x0e, 0x0b, 0xb5, 0x9f, 0x2c, 0xe1, 0x7b, 0x7a, 0xc6, 0x5b, 0xff, 0x5d, 0xa9, 0x61, 0x0e, 0xca, - 0x10, 0x34, 0x29, 0xd8, 0x02, 0x2a, 0x94, 0xba, 0xe2, 0xb5, 0xb1, 0x05, 0x7b, 0x55, 0x95, 0xb8, - 0xad, 0x70, 0xbf, 0xc2, 0xd0, 0xe1, 0xad, 0x66, 0x2c, 0xb7, 0x5e, 0x6b, 0xae, 0x07, 0x82, 0xbe, - 0x6f, 0x00, 0xe3, 0xdb, 0x79, 0x3b, 0xc2, 0x85, 0x61, 0xf0, 0x19, 0x6c, 0x2e, 0x74, 0xda, 0x6f, - 0x30, 0x3f, 0xa8, 0xbc, 0xb7, 0x0c, 0x94, 0x09, 0x66, 0x71, 0xb7, 0x3f, 0x7b, 0x3a, 0x95, 0xfb, - 0x00, 0x22, 0x00, 0xd5, 0xb9, 0x18, 0x0f, 0xa0, 0xef, 0x7d, 0x30, 0x14, 0xd0, 0x13, 0x44, 0x14, - 0x5b, 0x4d, 0x38, 0x48, 0x0d, 0x72, 0xff, 0x25, 0xc2, 0x42, 0x94, 0xe3, 0x05, 0xe5, 0x70, 0x50, - 0x72, 0xe0, 0xd3, 0x2c, 0xc4, 0xe8, 0x4f, 0x5c, 0xaf, 0x31, 0x48, 0x60, 0x89, 0xa4, 0xb9, 0x34, - 0xc8, 0x0c, 0x92, 0xeb, 0xa4, 0x34, 0x72, 0xff, 0x23, 0xa5, 0xaf, 0x93, 0xc3, 0x97, 0x53, 0x5d, - 0x33, 0x80, 0x1f, 0x0e, 0x6f, 0xc6, 0xeb, 0x2e, 0xe0, 0xd1, 0x17, 0xf0, 0x3b, 0xb4, 0xfd, 0x38, - 0xa8, 0xb9, 0xc8, 0x8d, 0x94, 0x70, 0x81, 0x31, 0xf3, 0x87, 0x42, 0xca, 0x80, 0x4a, 0x3c, 0xfc, - 0x4f, 0x94, 0x76, 0xbc, 0x2d, 0x03, 0xf5, 0x3d, 0x17, 0x00, 0x1c, 0x36, 0x47, 0x8a, 0xfb, 0xe9, - 0xcc, 0x53, 0x5a, 0x22, 0x4b, 0x2d, 0xf6, 0xb2, 0xb0, 0x8b, 0xef, 0x06, 0xcb, 0xc7, 0xd4, 0xdc, - 0x42, 0xcc, 0xfc, 0x34, 0x59, 0xf7, 0xac, 0x5c, 0x44, 0x19, 0xae, 0x9f, 0x3c, 0x8a, 0x16, 0x1d, - 0x55, 0x4d, 0x04, 0x77, 0x78, 0x94, 0x32, 0x16, 0x24, 0x08, 0x58, 0xda, 0x3b, 0x11, 0x01, 0x98, - 0x4c, 0x40, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7a, 0x01, 0xee, 0xa6, 0xb2, 0xad, 0xad, - 0x14, 0xd7, 0x1a, 0xb8, 0xb8, 0xe4, 0x11, 0xbe, 0xf3, 0xc5, 0x96, 0xe9, 0x54, 0xb7, 0x0e, 0x40, - 0x31, 0x57, 0x0c, 0xb1, 0xab, 0xd7, 0xe9, 0x32, 0x08, 0x32, 0x41, 0xf1, 0xca, 0xca, 0x31, 0x16, - 0x70, 0x8f, 0xa4, 0x31, 0x9f, 0xbb, 0xdf, 0xe3, 0x51, 0x37, 0x6c, 0x23, 0x64, 0x4a, 0xe0, 0x9a, - 0x42, 0xf0, 0x15, 0x5d, 0xb4, 0x99, 0x6c, 0x9d, 0x0c, 0x7f, 0xfc, 0x85, 0x21, 0xc1, 0x91, 0x4c, - 0x0e, 0x1a, 0x20, 0xae, 0x51, 0xe6, 0x5d, 0xf6, 0x4d, 0xd5, 0xe6, 0xe5, 0x98, 0x5b, 0x3d, 0x9d, - 0x31, 0x73, 0x20, 0x46, 0xd2, 0xd7, 0x7f, 0x9c, 0x08, 0xaa, 0xcc, 0xf0, 0x56, 0xb8, 0x40, 0x26, - 0x07, 0x39, 0x76, 0xee, 0xc6, 0x16, 0x4c, 0xbd, 0xae, 0xe5, 0xd9, 0xe7, 0x6e, 0x49, 0x7f, 0x0c, - 0x29, 0x0a, 0xf6, 0x81, 0xca, 0xbd, 0x5c, 0x51, 0x01, 0x28, 0x2a, 0xbb, 0x26, 0xc3, 0x68, 0x0d, - 0x60, 0x87, 0xce, 0x05, 0x33, 0x10, 0xfe, 0x8a, 0x94, 0xf5, 0x9d, 0x8a, 0xe2, 0x3c, 0xaa, 0xc5, - 0xfc, 0x0e, 0xd0, 0xc3, 0x79, 0x88, 0x8a, 0xbf, 0x02, 0x8a, 0x6f, 0x29, 0xf8, 0x9d, 0x4f, 0xe2, - 0xac, 0xc1, 0x70, 0x63, 0x41, 0xb2, 0x24, 0x5b, 0xa1, 0x88, 0x5b, 0xca, 0x57, 0xe1, 0xe2, 0x7c, - 0xcf, 0x7e, 0xd7, 0x93, 0x71, 0x50, 0x09, 0x65, 0x00, 0x9f, 0x96, 0x0c, 0x2b, 0xa0, 0x0f, 0xad, - 0x3e, 0x93, 0x38, 0x3b, 0x87, 0xce, 0x11, 0x9c, 0xac, 0x0b, 0x33, 0x60, 0xeb, 0x99, 0x28, 0x4c, - 0xe7, 0x8e, 0x2c, 0xbe, 0xd6, 0x80, 0xf7, 0x96, 0x03, 0x73, 0xe0, 0xab, 0x75, 0xc1, 0x90, 0x25, - 0x41, 0x60, 0xc2, 0x35, 0x36, 0x14, 0x10, 0x94, 0x89, 0xe6, 0x53, 0xc9, 0xb2, 0xe1, 0xc9, 0x3f, - 0x92, 0xc7, 0xc5, 0xad, 0x58, 0x3d, 0x98, 0x7a, 0x04, 0xbd, 0x35, 0x41, 0xb2, 0x44, 0x85, 0xc3, - 0x3e, 0xa4, 0x9b, 0xac, 0x43, 0xc8, 0x7c, 0x4a, 0xb3, 0xef, 0xde, 0x2e, 0x2d, 0x7e, 0xc1, 0x0a, - 0x40, 0xbe, 0x54, 0x41, 0x99, 0xf9, 0x25, 0xb2, 0x0b, 0x2c, 0x55, 0x54, 0x2b, 0xc5, 0x64, 0x10, - 0x57, 0x1e, 0x41, 0xcd, 0x8e, 0x02, 0x86, 0xf6, 0x09, 0xa6, 0x67, 0x68, 0xb5, 0x06, 0x1c, 0xcb, - 0x47, 0x77, 0xaf, 0x32, 0x30, 0x99, 0x28, 0xdd, 0x09, 0x76, 0x5d, 0xe9, 0xdf, 0x4c, 0xfa, 0x54, - 0x87, 0xf3, 0x60, 0xe2, 0x9e, 0x99, 0x34, 0x3e, 0x91, 0x81, 0x1b, 0xae, 0xc3, 0x31, 0xc4, 0x68, - 0x09, 0x85, 0xe6, 0x08, 0xca, 0x5d, 0x40, 0x8e, 0x21, 0x72, 0x5c, 0x6a, 0xa1, 0xb6, 0x1d, 0x5a, - 0x8b, 0x48, 0xd7, 0x5f, 0x4a, 0xaa, 0x9a, 0x3c, 0xbe, 0x88, 0xd3, 0xe0, 0xf1, 0xa5, 0x43, 0x19, - 0x08, 0x1f, 0x77, 0xc7, 0x2c, 0x8f, 0x52, 0x54, 0x74, 0x48, 0xc0, 0x3a, 0xb4, 0xaf, 0xbf, 0x6b, - 0x8f, 0xb0, 0xe1, 0x26, 0xc0, 0x37, 0xa0, 0xad, 0x40, 0x94, 0x60, 0x0d, 0xd0, 0xe0, 0x63, 0x4d, - 0x76, 0xf8, 0x8c, 0x21, 0x08, 0x7f, 0x3c, 0xfb, 0x48, 0x5a, 0x89, 0xbc, 0x1e, 0x3a, 0xbc, 0x4c, - 0x95, 0x04, 0x1d, 0x1d, 0x17, 0x0e, 0xcc, 0xf0, 0x29, 0x33, 0xec, 0x53, 0x93, 0xd4, 0xbe, 0x1d, - 0xc5, 0x73, 0xf8, 0x3c, 0x33, 0xd3, 0xb9, 0xa7, 0x46, -]; - -#[test] -fn test_integration_auth() { - let server_secret_params = zkgroup::ServerSecretParams::generate(zkgroup::TEST_ARRAY_32); - let server_public_params = server_secret_params.get_public_params(); - - let master_key = zkgroup::groups::GroupMasterKey::new(zkgroup::TEST_ARRAY_32_1); - let group_secret_params = - zkgroup::groups::GroupSecretParams::derive_from_master_key(master_key); - let group_public_params = group_secret_params.get_public_params(); - - // Random UID and issueTime - let uid = zkgroup::TEST_ARRAY_16; - let redemption_time = 123456u32; - - // SERVER - // Issue credential - let randomness = zkgroup::TEST_ARRAY_32_2; - let auth_credential_response = - server_secret_params.issue_auth_credential(randomness, uid, redemption_time); - - // CLIENT - let auth_credential = server_public_params - .receive_auth_credential(uid, redemption_time, &auth_credential_response) - .unwrap(); - - // Create and decrypt user entry - let uuid_ciphertext = group_secret_params.encrypt_uuid(uid); - let plaintext = group_secret_params.decrypt_uuid(uuid_ciphertext).unwrap(); - assert!(plaintext == uid); - - // Create and receive presentation - let randomness = zkgroup::TEST_ARRAY_32_5; - - let presentation = server_public_params.create_auth_credential_presentation( - randomness, - group_secret_params, - auth_credential, - ); - - let presentation_bytes = &bincode::serialize(&presentation).unwrap(); - - //for b in presentation_bytes.iter() { - // print!("0x{:02x}, ", b); - //} - assert!(AUTH_CREDENTIAL_PRESENTATION_RESULT[..] == presentation_bytes[..]); - - server_secret_params - .verify_auth_credential_presentation(group_public_params, &presentation) - .unwrap(); - - // test encoding - // these tests will also discover if the serialized sizes change, - // necessitating an update to the LEN constants - //let mut ccm_bytes = [0u8; zkgroup::common::constants::CLIENT_CREDENTIAL_MANAGER_LEN]; - let mut group_secret_params_bytes = [0u8; zkgroup::common::constants::GROUP_SECRET_PARAMS_LEN]; - let mut server_secret_params_bytes = - [0u8; zkgroup::common::constants::SERVER_SECRET_PARAMS_LEN]; - let mut group_public_params_bytes = [0u8; zkgroup::common::constants::GROUP_PUBLIC_PARAMS_LEN]; - let mut server_public_params_bytes = - [0u8; zkgroup::common::constants::SERVER_PUBLIC_PARAMS_LEN]; - let mut auth_credential_response_bytes = - [0u8; zkgroup::common::constants::AUTH_CREDENTIAL_RESPONSE_LEN]; - let mut auth_credential_bytes = [0u8; zkgroup::common::constants::AUTH_CREDENTIAL_LEN]; - let mut auth_credential_presentation_bytes = - [0u8; zkgroup::common::constants::AUTH_CREDENTIAL_PRESENTATION_LEN]; - let mut uuid_ciphertext_bytes = [0u8; zkgroup::common::constants::UUID_CIPHERTEXT_LEN]; - let mut uid_bytes = [0u8; zkgroup::common::constants::UUID_LEN]; - let mut randomness_bytes = [0u8; zkgroup::common::constants::RANDOMNESS_LEN]; - - //ccm_bytes.copy_from_slice(&bincode::serialize(&client_credential_manager).unwrap()); - group_secret_params_bytes.copy_from_slice(&bincode::serialize(&group_secret_params).unwrap()); - server_secret_params_bytes.copy_from_slice(&bincode::serialize(&server_secret_params).unwrap()); - group_public_params_bytes.copy_from_slice(&bincode::serialize(&group_public_params).unwrap()); - server_public_params_bytes.copy_from_slice(&bincode::serialize(&server_public_params).unwrap()); - auth_credential_response_bytes - .copy_from_slice(&bincode::serialize(&auth_credential_response).unwrap()); - auth_credential_bytes.copy_from_slice(&bincode::serialize(&auth_credential).unwrap()); - auth_credential_presentation_bytes.copy_from_slice(&bincode::serialize(&presentation).unwrap()); - uuid_ciphertext_bytes.copy_from_slice(&bincode::serialize(&uuid_ciphertext).unwrap()); - uid_bytes.copy_from_slice(&bincode::serialize(&uid).unwrap()); - randomness_bytes.copy_from_slice(&bincode::serialize(&randomness).unwrap()); -} - -#[test] -fn test_integration_profile() { - // Random UID and issueTime - let _uid = zkgroup::TEST_ARRAY_16; - - // SERVER - let server_secret_params = zkgroup::ServerSecretParams::generate(zkgroup::TEST_ARRAY_32); - let server_public_params = server_secret_params.get_public_params(); - - // CLIENT - let master_key = zkgroup::groups::GroupMasterKey::new(zkgroup::TEST_ARRAY_32_1); - let group_secret_params = - zkgroup::groups::GroupSecretParams::derive_from_master_key(master_key); - let group_public_params = group_secret_params.get_public_params(); - - let uid = zkgroup::TEST_ARRAY_16; - let profile_key = - zkgroup::profiles::ProfileKey::create(zkgroup::common::constants::TEST_ARRAY_32_1); - let profile_key_commitment = profile_key.get_commitment(uid); - - // Create context and request - let randomness = zkgroup::TEST_ARRAY_32_3; - - let context = server_public_params.create_profile_key_credential_request_context( - randomness, - uid, - profile_key, - ); - let request = context.get_request(); - - // SERVER - - let randomness = zkgroup::TEST_ARRAY_32_4; - let response = server_secret_params - .issue_profile_key_credential(randomness, &request, uid, profile_key_commitment) - .unwrap(); - - // CLIENT - // Gets stored profile credential - let profile_key_credential = server_public_params - .receive_profile_key_credential(&context, &response) - .unwrap(); - - // Create encrypted UID and profile key - let uuid_ciphertext = group_secret_params.encrypt_uuid(uid); - let plaintext = group_secret_params.decrypt_uuid(uuid_ciphertext).unwrap(); - assert!(plaintext == uid); - - let profile_key_ciphertext = group_secret_params.encrypt_profile_key(profile_key, uid); - let decrypted_profile_key = group_secret_params - .decrypt_profile_key(profile_key_ciphertext, uid) - .unwrap(); - - assert!(decrypted_profile_key.get_bytes() == profile_key.get_bytes()); - - // Create presentation - let randomness = zkgroup::TEST_ARRAY_32_5; - - let presentation = server_public_params.create_profile_key_credential_presentation( - randomness, - group_secret_params, - profile_key_credential, - ); - - let presentation_bytes = &bincode::serialize(&presentation).unwrap(); - //for b in presentation_bytes.iter() { - // print!("0x{:02x}, ", b); - //} - assert!(PROFILE_KEY_CREDENTIAL_PRESENTATION_RESULT[..] == presentation_bytes[..]); - - // SERVER - server_secret_params - .verify_profile_key_credential_presentation(group_public_params, &presentation) - .unwrap(); - - // test encoding - // these tests will also discover if the serialized sizes change, - // necessitating an update to the LEN constants - - let mut profile_key_commitment_bytes = - [0u8; zkgroup::common::constants::PROFILE_KEY_COMMITMENT_LEN]; - let mut profile_key_credential_bytes = - [0u8; zkgroup::common::constants::PROFILE_KEY_CREDENTIAL_LEN]; - let mut profile_key_credential_presentation_bytes = - [0u8; zkgroup::common::constants::PROFILE_KEY_CREDENTIAL_PRESENTATION_LEN]; - let mut profile_key_credential_request_bytes = - [0u8; zkgroup::common::constants::PROFILE_KEY_CREDENTIAL_REQUEST_LEN]; - let mut profile_key_credential_request_context_bytes = - [0u8; zkgroup::common::constants::PROFILE_KEY_CREDENTIAL_REQUEST_CONTEXT_LEN]; - let mut profile_key_credential_response_bytes = - [0u8; zkgroup::common::constants::PROFILE_KEY_CREDENTIAL_RESPONSE_LEN]; - - profile_key_commitment_bytes - .copy_from_slice(&bincode::serialize(&profile_key_commitment).unwrap()); - profile_key_credential_bytes - .copy_from_slice(&bincode::serialize(&profile_key_credential).unwrap()); - profile_key_credential_presentation_bytes - .copy_from_slice(&bincode::serialize(&presentation).unwrap()); - profile_key_credential_request_bytes.copy_from_slice(&bincode::serialize(&request).unwrap()); - profile_key_credential_request_context_bytes - .copy_from_slice(&bincode::serialize(&context).unwrap()); - profile_key_credential_response_bytes.copy_from_slice(&bincode::serialize(&response).unwrap()); -} - -#[test] -fn test_server_sigs() { - let server_secret_params = - zkgroup::api::server_params::ServerSecretParams::generate(zkgroup::TEST_ARRAY_32); - let server_public_params = server_secret_params.get_public_params(); - let randomness = zkgroup::TEST_ARRAY_32_2; - let message = zkgroup::TEST_ARRAY_32_1; - let signature = server_secret_params.sign(randomness, &message).unwrap(); - //println!("signature = {:#x?}", &signature[..]); - for b in signature.iter() { - print!("0x{:02x}, ", b); - } - assert!( - signature[..] - == [ - 0x87, 0xd3, 0x54, 0x56, 0x4d, 0x35, 0xef, 0x91, 0xed, 0xba, 0x85, 0x1e, 0x08, 0x15, - 0x61, 0x2e, 0x86, 0x4c, 0x22, 0x7a, 0x04, 0x71, 0xd5, 0x0c, 0x27, 0x06, 0x98, 0x60, - 0x44, 0x06, 0xd0, 0x03, 0xa5, 0x54, 0x73, 0xf5, 0x76, 0xcf, 0x24, 0x1f, 0xc6, 0xb4, - 0x1c, 0x6b, 0x16, 0xe5, 0xe6, 0x3b, 0x33, 0x3c, 0x02, 0xfe, 0x4a, 0x33, 0x85, 0x80, - 0x22, 0xfd, 0xd7, 0xa4, 0xab, 0x36, 0x7b, 0x06, - ][..] - ); - server_public_params - .verify_signature(&message, signature) - .unwrap(); -} - -#[test] -fn test_blob_encryption() { - let master_key = zkgroup::groups::GroupMasterKey::new(zkgroup::TEST_ARRAY_32_1); - let group_secret_params = - zkgroup::groups::GroupSecretParams::derive_from_master_key(master_key); - let randomness = zkgroup::TEST_ARRAY_32_2; - - let plaintext_vec = vec![ - 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, - 0x18, 0x19, - ]; - - // WARNING: THIS VECTOR DOES *NOT* MATCH JAVA/SWIFT/NODE AS THEY IMPLEMENT PADDING - let ciphertext_vec = vec![ - 0xe9, 0x58, 0x07, 0xb1, 0x90, 0xd4, 0x78, 0xd7, 0xbe, 0x3a, 0x77, 0xb2, 0x29, 0x27, 0x13, - 0x2e, 0xeb, 0xa5, 0x1c, 0x73, 0x9c, 0xd5, 0x70, 0x73, 0x17, 0xf7, 0x3e, 0x59, 0x1a, 0x91, - 0x5f, 0xff, 0x1f, 0x20, 0xa3, 0x02, 0x69, 0x2a, 0xfd, 0xc7, 0x08, 0x7f, 0x10, 0x19, 0x60, - 0x00, - ]; - - let calc_ciphertext_vec = group_secret_params - .encrypt_blob(randomness, &plaintext_vec) - .unwrap(); - let calc_plaintext_vec = group_secret_params - .decrypt_blob(&calc_ciphertext_vec) - .unwrap(); - assert!(calc_plaintext_vec == plaintext_vec); - for b in calc_ciphertext_vec.iter() { - print!("0x{:02x}, ", b); - } - assert!(calc_ciphertext_vec == ciphertext_vec); -}