diff --git a/.github/workflows/build_and_test.yml b/.github/workflows/build_and_test.yml
index 72f5418bfd..fb5654f5c0 100644
--- a/.github/workflows/build_and_test.yml
+++ b/.github/workflows/build_and_test.yml
@@ -39,8 +39,10 @@ jobs:
- '.github/workflows/build_and_test.yml'
- 'bin/**'
- 'rust/*'
- - 'rust/!(bridge)/**'
+ - 'rust/!(bridge|protocol)/**'
- 'rust/bridge/shared/**'
+ - 'rust/protocol/*'
+ - 'rust/protocol/!(cross-version-testing)/**'
- 'rust-toolchain'
- 'Cargo.toml'
- 'Cargo.lock'
@@ -49,7 +51,7 @@ jobs:
- '.clippy.toml'
- '.rustfmt.license-template'
- '.rustfmt.toml'
- - 'rust/**' # deliberately re-include the rust/bridge/ directories
+ - 'rust/**' # deliberately re-include rust/bridge/* and rust/protocol/cross-version-testing
java:
- *all
- '.dockerignore'
@@ -119,6 +121,11 @@ jobs:
run: cargo fmt --all -- --check
if: matrix.version == 'nightly'
+ - name: Rustfmt check for cross-version-testing
+ run: cargo fmt --all -- --check
+ working-directory: rust/protocol/cross-version-testing
+ if: matrix.version == 'nightly'
+
- name: Check bridge versioning
run: ./bin/update_versions.py
if: matrix.version == 'nightly'
@@ -149,6 +156,11 @@ jobs:
run: cargo clippy --workspace --all-targets --all-features -- -D warnings
if: matrix.version == 'nightly'
+ - name: Rust docs
+ run: cargo doc --workspace --all-features
+ env:
+ RUSTFLAGS: -D warnings
+
# We check the fuzz targets on stable because they don't have lockfiles,
# and crates don't generally support arbitrary nightly versions.
# See https://github.com/dtolnay/proc-macro2/issues/307 for an example.
@@ -306,5 +318,3 @@ jobs:
- name: Run pod lint
# No import validation because it tries to build unsupported platforms (like 32-bit iOS).
run: pod lib lint --verbose --platforms=ios --include-podspecs=SignalCoreKit/SignalCoreKit.podspec --skip-import-validation
- env:
- SKIP_CATALYST: 1
diff --git a/.github/workflows/ios_artifacts.yml b/.github/workflows/ios_artifacts.yml
index ae0c9331ca..1f0e8d7a0f 100644
--- a/.github/workflows/ios_artifacts.yml
+++ b/.github/workflows/ios_artifacts.yml
@@ -43,16 +43,6 @@ jobs:
env:
CARGO_BUILD_TARGET: aarch64-apple-ios-sim
- - name: Build for x86_64-apple-ios-macabi
- run: swift/build_ffi.sh --release --build-std
- env:
- CARGO_BUILD_TARGET: x86_64-apple-ios-macabi
-
- - name: Build for aarch64-apple-ios-macabi
- run: swift/build_ffi.sh --release --build-std
- env:
- CARGO_BUILD_TARGET: aarch64-apple-ios-macabi
-
- run: tar -c --auto-compress --no-mac-metadata -f ${{ steps.archive-name.outputs.name }} target/*/release/libsignal_ffi.a
- run: 'shasum -a 256 ${{ steps.archive-name.outputs.name }} | tee -a $GITHUB_STEP_SUMMARY ${{ steps.archive-name.outputs.name }}.sha256'
diff --git a/.github/workflows/jni_artifacts.yml b/.github/workflows/jni_artifacts.yml
index 13b61dc824..562a7f5a8a 100644
--- a/.github/workflows/jni_artifacts.yml
+++ b/.github/workflows/jni_artifacts.yml
@@ -1,20 +1,21 @@
-name: Publish JNI Artifacts to GitHub Release
+name: Upload Java libraries to Sonatype
+run-name: ${{ github.workflow }} (${{ github.ref_name }})
on:
- push:
- tags:
- - v*
- workflow_dispatch: {} # no parameters
+ workflow_dispatch:
+ inputs:
+ dry_run:
+ description: "Just build, don't publish"
+ default: false
+ required: false
+ type: boolean
env:
CARGO_TERM_COLOR: always
jobs:
build:
- name: Build
-
- # Only run this in the public repository unless manually invoked.
- if: ${{ github.event_name == 'workflow_dispatch' || !endsWith(github.repository, '-private') }}
+ name: Build for local development
runs-on: ${{ matrix.os }}
@@ -24,21 +25,14 @@ jobs:
strategy:
matrix:
- os: [ubuntu-20.04, windows-latest, macos-latest]
+ os: [windows-latest, macos-latest]
include:
- - os: ubuntu-20.04
- library: libsignal_jni.so
- os: windows-latest
library: signal_jni.dll
- os: macos-latest
library: libsignal_jni.dylib
additional-rust-target: aarch64-apple-darwin
-
- env:
- # Keep this settings in sync with java/build_jni.sh, which supports Android as well.
- CARGO_PROFILE_RELEASE_DEBUG: 1
- CARGO_PROFILE_RELEASE_LTO: thin
- CARGO_PROFILE_RELEASE_OPT_LEVEL: s
+ # Ubuntu binaries are built using Docker, below
steps:
- uses: actions/checkout@v3
@@ -54,26 +48,97 @@ jobs:
run: choco install nasm
shell: cmd
+ - name: Build for host (should be x86_64)
+ run: java/build_jni.sh desktop
+ shell: bash
+
- name: Install Protoc
uses: arduino/setup-protoc@v1
with:
version: '3.x'
repo-token: ${{ secrets.GITHUB_TOKEN }}
- - run: cargo build --release -p libsignal-jni
-
- - run: cargo build --release -p libsignal-jni --target aarch64-apple-darwin
+ - name: Build for alternate target (arm64)
+ run: java/build_jni.sh desktop
if: matrix.os == 'macos-latest'
+ env:
+ CARGO_BUILD_TARGET: ${{ matrix.additional-rust-target }}
- name: Merge library slices (for macOS)
# Using target/release/ for both the input and output wouldn't normally be ideal
# from a build system perspective, but we're going to immediately upload the merged library.
- run: lipo -create target/release/${{ matrix.library }} target/aarch64-apple-darwin/release/${{ matrix.library }} -output target/release/${{ matrix.library }}
+ run: lipo -create target/release/${{ matrix.library }} target/${{ matrix.additional-rust-target }}/release/${{ matrix.library }} -output target/release/${{ matrix.library }}
if: matrix.os == 'macos-latest'
- - name: Upload
- uses: ncipollo/release-action@4c75f0f2e4ae5f3c807cf0904605408e319dcaac # v1.11.1
+ - name: Upload library
+ uses: actions/upload-artifact@v3
+ with:
+ name: libsignal_jni (${{matrix.os}})
+ path: target/release/${{ matrix.library }}
+
+ verify-rust:
+ name: Verify JNI bindings
+ runs-on: ubuntu-latest
+
+ steps:
+ - uses: actions/checkout@v3
+
+ - run: rustup toolchain install $(cat rust-toolchain) --profile minimal
+
+ - name: Verify that the JNI bindings are up to date
+ run: rust/bridge/jni/bin/gen_java_decl.py --verify
+
+ publish:
+ name: Build for production and publish
+
+ runs-on: ubuntu-latest
+
+ needs: [build, verify-rust]
+
+ steps:
+ - uses: actions/checkout@v3
+
+ - name: Download built libraries
+ id: download
+ uses: actions/download-artifact@v3
+ with:
+ path: artifacts
+
+ - name: Copy libraries
+ run: mv ${{ steps.download.outputs.download-path }}/*/* java/shared/resources && find java/shared/resources
+
+ - run: make
+ if: ${{ inputs.dry_run }}
+ working-directory: java
+
+ - name: Upload libsignal-android
+ if: ${{ inputs.dry_run }}
+ uses: actions/upload-artifact@v3
+ with:
+ name: libsignal-android
+ path: java/android/build/outputs/aar/libsignal-android-release.aar
+
+ - name: Upload libsignal-client
+ if: ${{ inputs.dry_run }}
+ uses: actions/upload-artifact@v3
+ with:
+ name: libsignal-client
+ path: java/client/build/libs/libsignal-client-*.jar
+
+ - name: Upload libsignal-server
+ if: ${{ inputs.dry_run }}
+ uses: actions/upload-artifact@v3
with:
- allowUpdates: true
- artifactErrorsFailBuild: true
- artifacts: target/release/${{ matrix.library }}
+ name: libsignal-server
+ path: java/server/build/libs/libsignal-server-*.jar
+
+ - run: make publish_java
+ if: ${{ !inputs.dry_run }}
+ working-directory: java
+ env:
+ ORG_GRADLE_PROJECT_sonatypeUsername: ${{ secrets.SONATYPE_USER }}
+ ORG_GRADLE_PROJECT_sonatypePassword: ${{ secrets.SONATYPE_PASSWORD }}
+ ORG_GRADLE_PROJECT_signingKeyId: ${{ secrets.SIGNING_KEYID }}
+ ORG_GRADLE_PROJECT_signingPassword: ${{ secrets.SIGNING_PASSWORD }}
+ # ASCII-armored PGP secret key
+ ORG_GRADLE_PROJECT_signingKey: ${{ secrets.SIGNING_KEY }}
diff --git a/.github/workflows/slow_tests.yml b/.github/workflows/slow_tests.yml
index 08dede9dbd..723264a6c7 100644
--- a/.github/workflows/slow_tests.yml
+++ b/.github/workflows/slow_tests.yml
@@ -136,7 +136,7 @@ jobs:
working-directory: node
swift-cocoapod:
- name: Swift CocoaPod (with Catalyst)
+ name: Swift CocoaPod (all architectures)
runs-on: macOS-latest
needs: [check-up-to-date]
if: ${{ always() && (needs.check-up-to-date.outputs.has-changes || github.event_name != 'schedule') }}
@@ -167,24 +167,38 @@ jobs:
env:
CARGO_BUILD_TARGET: aarch64-apple-ios-sim
- - name: Build for x86_64-apple-ios-macabi
- run: swift/build_ffi.sh --release --build-std
- env:
- CARGO_BUILD_TARGET: x86_64-apple-ios-macabi
-
- - name: Build for aarch64-apple-ios-macabi
- run: swift/build_ffi.sh --release --build-std
- env:
- CARGO_BUILD_TARGET: aarch64-apple-ios-macabi
-
- name: Run pod lint
# No import validation because it tries to build unsupported platforms (like 32-bit iOS).
run: pod lib lint --verbose --platforms=ios --include-podspecs=SignalCoreKit/SignalCoreKit.podspec --skip-import-validation
+ rust-protocol-cross-version-testing:
+ name: libsignal-protocol Cross-version Tests
+ runs-on: ubuntu-latest
+ needs: [check-up-to-date]
+ if: ${{ always() && (needs.check-up-to-date.outputs.has-changes || github.event_name != 'schedule') }}
+
+ steps:
+ - uses: actions/checkout@v3
+
+ - run: sudo apt-get update && sudo apt-get install gcc-multilib g++-multilib
+
+ - run: rustup +stable target add i686-unknown-linux-gnu
+
+ - name: Run tests
+ run: cargo +stable test
+ working-directory: rust/protocol/cross-version-testing
+
+ - name: Run tests (32-bit)
+ run: cargo +stable test --target i686-unknown-linux-gnu
+ working-directory: rust/protocol/cross-version-testing
+
+ # We don't run Clippy because GitHub silently updates `stable` and that can introduce new lints,
+ # and we don't have a guarantee that any particular pinned nightly can build older libsignals.
+
report_failures:
name: Report Failures
runs-on: ubuntu-latest
- needs: [java-docker, android-emulator-tests, node-docker, node-windows-arm64, swift-cocoapod]
+ needs: [java-docker, android-emulator-tests, node-docker, node-windows-arm64, swift-cocoapod, rust-protocol-cross-version-testing]
if: ${{ failure() && github.event_name == 'schedule' }}
permissions:
diff --git a/Cargo.lock b/Cargo.lock
index c72ec98d2a..56ba2922ec 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -26,6 +26,16 @@ dependencies = [
"generic-array",
]
+[[package]]
+name = "aead"
+version = "0.5.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d122413f284cf2d62fb1b7db97e02edb8cda96d769b16e443a4f6195e35662b0"
+dependencies = [
+ "crypto-common",
+ "generic-array",
+]
+
[[package]]
name = "aes"
version = "0.7.5"
@@ -33,37 +43,48 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9e8b47f52ea9bae42228d07ec09eb676433d7c4ed1ebdf0f1d1c29ed446f1ab8"
dependencies = [
"cfg-if",
- "cipher",
+ "cipher 0.3.0",
"cpufeatures",
- "ctr 0.8.0",
"opaque-debug",
]
+[[package]]
+name = "aes"
+version = "0.8.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ac1f845298e95f983ff1944b728ae08b8cebab80d684f0a832ed0fc74dfa27e2"
+dependencies = [
+ "cfg-if",
+ "cipher 0.4.4",
+ "cpufeatures",
+ "zeroize",
+]
+
[[package]]
name = "aes-gcm"
version = "0.9.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bc3be92e19a7ef47457b8e6f90707e12b6ac5d20c6f3866584fa3be0787d839f"
dependencies = [
- "aead",
- "aes",
- "cipher",
+ "aead 0.4.3",
+ "aes 0.7.5",
+ "cipher 0.3.0",
"ctr 0.7.0",
- "ghash",
+ "ghash 0.4.4",
"subtle",
]
[[package]]
name = "aes-gcm-siv"
-version = "0.10.1"
+version = "0.11.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "cfde8146762f3c5f3c5cd41aa17a71f3188df09d5857192b658510d850e16068"
+checksum = "ae0784134ba9375416d469ec31e7c5f9fa94405049cf08c5ce5b4698be673e0d"
dependencies = [
- "aead",
- "aes",
- "cipher",
- "ctr 0.7.0",
- "polyval",
+ "aead 0.5.2",
+ "aes 0.8.3",
+ "cipher 0.4.4",
+ "ctr 0.9.2",
+ "polyval 0.6.1",
"subtle",
"zeroize",
]
@@ -120,6 +141,7 @@ dependencies = [
"blake2",
"cpufeatures",
"password-hash",
+ "zeroize",
]
[[package]]
@@ -189,8 +211,9 @@ dependencies = [
"bitflags 2.3.3",
"boring",
"boring-sys",
- "chacha20poly1305",
+ "chacha20poly1305 0.10.1",
"chrono",
+ "ciborium",
"displaydoc",
"hex",
"hex-literal",
@@ -206,6 +229,7 @@ dependencies = [
"sha2",
"snow",
"static_assertions",
+ "subtle",
"uuid",
"variant_count",
"x25519-dalek",
@@ -219,9 +243,9 @@ checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
[[package]]
name = "axum"
-version = "0.6.18"
+version = "0.6.20"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f8175979259124331c1d7bf6586ee7e0da434155e4b2d48ec2c8386281d8df39"
+checksum = "3b829e4e32b91e643de6eafe82b1d90675f5874230191a4ffbc1b336dec4d6bf"
dependencies = [
"async-trait",
"axum-core",
@@ -279,9 +303,9 @@ dependencies = [
[[package]]
name = "base64"
-version = "0.21.0"
+version = "0.21.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a4a4ddaa51a5bc52a6948f74c06d20aaaddb71924eab79b8c97a8c556e942d6a"
+checksum = "604178f6c5c21f02dc555784810edfb88d34ac2c73b2eae109655649ee73ce3d"
[[package]]
name = "base64ct"
@@ -364,21 +388,14 @@ dependencies = [
]
[[package]]
-name = "block-modes"
-version = "0.8.1"
+name = "block-padding"
+version = "0.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2cb03d1bed155d89dce0f845b7899b18a9a163e148fd004e1c28421a783e2d8e"
+checksum = "a8894febbff9f758034a5b8e12d87918f56dfc64a8e1fe757d65e29041538d93"
dependencies = [
- "block-padding",
- "cipher",
+ "generic-array",
]
-[[package]]
-name = "block-padding"
-version = "0.2.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8d696c370c750c948ada61c69a0ee2cbbb9c50b1019ddb86d9317157a99c2cae"
-
[[package]]
name = "boring"
version = "2.1.0"
@@ -430,11 +447,20 @@ version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5"
+[[package]]
+name = "cbc"
+version = "0.1.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "26b52a9543ae338f279b96b0b9fed9c8093744685043739079ce85cd58f289a6"
+dependencies = [
+ "cipher 0.4.4",
+]
+
[[package]]
name = "cc"
-version = "1.0.81"
+version = "1.0.83"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6c6b2562119bf28c3439f7f02db99faf0aa1a8cdfe5772a2ee155d32227239f0"
+checksum = "f1174fb0b6ec23863f8b971027804a42614e347eafb0a95bf0b12cdae21fc4d0"
dependencies = [
"jobserver",
"libc",
@@ -468,21 +494,45 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5c80e5460aa66fe3b91d40bcbdab953a597b60053e34d684ac6903f863b680a6"
dependencies = [
"cfg-if",
- "cipher",
+ "cipher 0.3.0",
"cpufeatures",
"zeroize",
]
+[[package]]
+name = "chacha20"
+version = "0.9.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c3613f74bd2eac03dad61bd53dbe620703d4371614fe0bc3b9f04dd36fe4e818"
+dependencies = [
+ "cfg-if",
+ "cipher 0.4.4",
+ "cpufeatures",
+]
+
[[package]]
name = "chacha20poly1305"
version = "0.9.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a18446b09be63d457bbec447509e85f662f32952b035ce892290396bc0b0cff5"
dependencies = [
- "aead",
- "chacha20",
- "cipher",
- "poly1305",
+ "aead 0.4.3",
+ "chacha20 0.8.2",
+ "cipher 0.3.0",
+ "poly1305 0.7.2",
+ "zeroize",
+]
+
+[[package]]
+name = "chacha20poly1305"
+version = "0.10.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "10cd79432192d1c0f4e1a0fef9527696cc039165d729fb41b3f4f4f354c2dc35"
+dependencies = [
+ "aead 0.5.2",
+ "chacha20 0.9.1",
+ "cipher 0.4.4",
+ "poly1305 0.8.0",
"zeroize",
]
@@ -538,6 +588,17 @@ dependencies = [
"generic-array",
]
+[[package]]
+name = "cipher"
+version = "0.4.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "773f3b9af64447d2ce9850330c473515014aa235e6a783b02db81ff39e4a3dad"
+dependencies = [
+ "crypto-common",
+ "inout",
+ "zeroize",
+]
+
[[package]]
name = "clang-sys"
version = "1.6.1"
@@ -700,6 +761,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3"
dependencies = [
"generic-array",
+ "rand_core",
"typenum",
]
@@ -709,16 +771,16 @@ version = "0.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a232f92a03f37dd7d7dd2adc67166c77e9cd88de5b019b9a9eecfaeaf7bfd481"
dependencies = [
- "cipher",
+ "cipher 0.3.0",
]
[[package]]
name = "ctr"
-version = "0.8.0"
+version = "0.9.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "049bb91fb4aaf0e3c7efa6cd5ef877dbbbd15b39dad06d9948de4ec8a75761ea"
+checksum = "0369ee1ad671834580515889b80f2ea915f23b8be8d0daa4bbaf2ac5c7590835"
dependencies = [
- "cipher",
+ "cipher 0.4.4",
]
[[package]]
@@ -1007,9 +1069,9 @@ checksum = "aa9a19cbb55df58761df49b23516a86d432839add4af60fc256da840f66ed35b"
[[package]]
name = "futures"
-version = "0.3.28"
+version = "0.3.29"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "23342abe12aba583913b2e62f22225ff9c950774065e4bfb61a19cd9770fec40"
+checksum = "da0290714b38af9b4a7b094b8a37086d1b4e61f2df9122c3cad2577669145335"
dependencies = [
"futures-channel",
"futures-core",
@@ -1022,9 +1084,9 @@ dependencies = [
[[package]]
name = "futures-channel"
-version = "0.3.28"
+version = "0.3.29"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "955518d47e09b25bbebc7a18df10b81f0c766eaf4c4f1cccef2fca5f2a4fb5f2"
+checksum = "ff4dd66668b557604244583e3e1e1eada8c5c2e96a6d0d6653ede395b78bbacb"
dependencies = [
"futures-core",
"futures-sink",
@@ -1032,15 +1094,15 @@ dependencies = [
[[package]]
name = "futures-core"
-version = "0.3.28"
+version = "0.3.29"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4bca583b7e26f571124fe5b7561d49cb2868d79116cfa0eefce955557c6fee8c"
+checksum = "eb1d22c66e66d9d72e1758f0bd7d4fd0bee04cad842ee34587d68c07e45d088c"
[[package]]
name = "futures-executor"
-version = "0.3.28"
+version = "0.3.29"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ccecee823288125bd88b4d7f565c9e58e41858e47ab72e8ea2d64e93624386e0"
+checksum = "0f4fb8693db0cf099eadcca0efe2a5a22e4550f98ed16aba6c48700da29597bc"
dependencies = [
"futures-core",
"futures-task",
@@ -1049,15 +1111,15 @@ dependencies = [
[[package]]
name = "futures-io"
-version = "0.3.28"
+version = "0.3.29"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4fff74096e71ed47f8e023204cfd0aa1289cd54ae5430a9523be060cdb849964"
+checksum = "8bf34a163b5c4c52d0478a4d757da8fb65cabef42ba90515efee0f6f9fa45aaa"
[[package]]
name = "futures-macro"
-version = "0.3.28"
+version = "0.3.29"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "89ca545a94061b6365f2c7355b4b32bd20df3ff95f02da9329b34ccc3bd6ee72"
+checksum = "53b153fd91e4b0147f4aced87be237c98248656bb01050b96bf3ee89220a8ddb"
dependencies = [
"proc-macro2",
"quote",
@@ -1066,21 +1128,21 @@ dependencies = [
[[package]]
name = "futures-sink"
-version = "0.3.28"
+version = "0.3.29"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f43be4fe21a13b9781a69afa4985b0f6ee0e1afab2c6f454a8cf30e2b2237b6e"
+checksum = "e36d3378ee38c2a36ad710c5d30c2911d752cb941c00c72dbabfb786a7970817"
[[package]]
name = "futures-task"
-version = "0.3.28"
+version = "0.3.29"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "76d3d132be6c0e6aa1534069c705a74a5997a356c0dc2f86a47765e5617c5b65"
+checksum = "efd193069b0ddadc69c46389b740bbccdd97203899b48d09c5f7969591d6bae2"
[[package]]
name = "futures-util"
-version = "0.3.28"
+version = "0.3.29"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "26b01e40b772d54cf6c6d721c1d1abd0647a0106a12ecaa1c186273392a69533"
+checksum = "a19526d624e703a3179b3d322efec918b6246ea0fa51d41124525f00f1cc8104"
dependencies = [
"futures-channel",
"futures-core",
@@ -1122,7 +1184,18 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1583cc1656d7839fd3732b80cf4f38850336cdb9b8ded1cd399ca62958de3c99"
dependencies = [
"opaque-debug",
- "polyval",
+ "polyval 0.5.3",
+]
+
+[[package]]
+name = "ghash"
+version = "0.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d930750de5717d2dd0b8c0d42c076c0e884c81a73e6cab859bbd2339c71e3e40"
+dependencies = [
+ "opaque-debug",
+ "polyval 0.6.1",
+ "zeroize",
]
[[package]]
@@ -1139,9 +1212,9 @@ checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b"
[[package]]
name = "h2"
-version = "0.3.18"
+version = "0.3.22"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "17f8a914c2987b688368b5138aa05321db91f4090cf26118185672ad588bce21"
+checksum = "4d6250322ef6e60f93f9a2162799302cd6f68f79f6e5d85c8c16f14d1d958178"
dependencies = [
"bytes",
"fnv",
@@ -1149,7 +1222,7 @@ dependencies = [
"futures-sink",
"futures-util",
"http",
- "indexmap 1.9.3",
+ "indexmap 2.0.0",
"slab",
"tokio",
"tokio-util",
@@ -1364,6 +1437,16 @@ dependencies = [
"hashbrown 0.14.0",
]
+[[package]]
+name = "inout"
+version = "0.1.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a0c10553d664a4d0bcff9f4215d0aac67a639cc68ef660840afe309b807bc9f5"
+dependencies = [
+ "block-padding",
+ "generic-array",
+]
+
[[package]]
name = "is-terminal"
version = "0.4.9"
@@ -1392,16 +1475,18 @@ checksum = "af150ab688ff2122fcef229be89cb50dd66af9e01a4ff320cc137eecc9bacc38"
[[package]]
name = "jni"
-version = "0.19.0"
+version = "0.21.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c6df18c2e3db7e453d3c6ac5b3e9d5182664d28788126d39b91f2d1e22b017ec"
+checksum = "1a87aa2bb7d2af34197c04845522473242e1aa17c12f4935d5856491a7fb8c97"
dependencies = [
"cesu8",
+ "cfg-if",
"combine",
"jni-sys",
"log",
"thiserror",
"walkdir",
+ "windows-sys 0.45.0",
]
[[package]]
@@ -1442,9 +1527,9 @@ checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55"
[[package]]
name = "libc"
-version = "0.2.147"
+version = "0.2.150"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b4668fb0ea861c1df094127ac5f1da3409a82116a4ba74fca2e58ef927159bb3"
+checksum = "89d92a4743f9a61002fae18374ed11e7973f530cb3a3255fb354818118b2203c"
[[package]]
name = "libloading"
@@ -1505,7 +1590,6 @@ dependencies = [
"signal-pin",
"signal-quic",
"static_assertions",
- "typenum",
"usernames",
"uuid",
"zkgroup",
@@ -1525,7 +1609,7 @@ dependencies = [
[[package]]
name = "libsignal-ffi"
-version = "0.31.0"
+version = "0.32.1"
dependencies = [
"async-trait",
"attest",
@@ -1548,7 +1632,7 @@ dependencies = [
[[package]]
name = "libsignal-jni"
-version = "0.31.0"
+version = "0.32.1"
dependencies = [
"async-trait",
"cfg-if",
@@ -1564,7 +1648,7 @@ dependencies = [
[[package]]
name = "libsignal-node"
-version = "0.31.0"
+version = "0.32.1"
dependencies = [
"async-trait",
"cmake",
@@ -1581,17 +1665,16 @@ dependencies = [
name = "libsignal-protocol"
version = "0.1.0"
dependencies = [
- "aes",
+ "aes 0.8.3",
"aes-gcm-siv",
"arrayref",
"async-trait",
- "block-modes",
"criterion",
+ "ctr 0.9.2",
"curve25519-dalek",
"displaydoc",
"env_logger",
"futures-util",
- "generic-array",
"hex",
"hex-literal",
"hkdf",
@@ -1607,9 +1690,9 @@ dependencies = [
"rand",
"sha2",
"signal-crypto",
+ "static_assertions",
"subtle",
"thiserror",
- "typenum",
"uuid",
"x25519-dalek",
]
@@ -1664,9 +1747,9 @@ checksum = "2532096657941c2fea9c289d370a250971c689d4f143798ff67113ec042024a5"
[[package]]
name = "matchit"
-version = "0.7.0"
+version = "0.7.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b87248edafb776e59e6ee64a79086f65890d3510f2c656c000bf2a7e8a0aea40"
+checksum = "0e7465ac9959cc2b1404e8e2367b43684a6d13790fe23056cc8c6c5a6b7bcb94"
[[package]]
name = "memchr"
@@ -1706,14 +1789,14 @@ dependencies = [
[[package]]
name = "mio"
-version = "0.8.6"
+version = "0.8.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5b9d9a46eff5b4ff64b45a9e316a6d1e0bc719ef429cbec4dc630684212bfdf9"
+checksum = "3dce281c5e46beae905d4de1870d8b1509a9142b62eedf18b443b011ca8343d0"
dependencies = [
"libc",
"log",
"wasi 0.11.0+wasi-snapshot-preview1",
- "windows-sys 0.45.0",
+ "windows-sys 0.48.0",
]
[[package]]
@@ -1911,22 +1994,22 @@ dependencies = [
[[package]]
name = "pin-project"
-version = "1.0.12"
+version = "1.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ad29a609b6bcd67fee905812e544992d216af9d755757c05ed2d0e15a74c6ecc"
+checksum = "fda4ed1c6c173e3fc7a83629421152e01d7b1f9b7f65fb301e490e8cfc656422"
dependencies = [
"pin-project-internal",
]
[[package]]
name = "pin-project-internal"
-version = "1.0.12"
+version = "1.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "069bdb1e05adc7a8990dce9cc75370895fbe4e3d58b9b73bf1aee56359344a55"
+checksum = "4359fd9c9171ec6e8c62926d6faaf553a8dc3f64e1507e76da7911b4f6a04405"
dependencies = [
"proc-macro2",
"quote",
- "syn 1.0.109",
+ "syn 2.0.28",
]
[[package]]
@@ -1994,7 +2077,18 @@ checksum = "048aeb476be11a4b6ca432ca569e375810de9294ae78f4774e78ea98a9246ede"
dependencies = [
"cpufeatures",
"opaque-debug",
- "universal-hash",
+ "universal-hash 0.4.0",
+]
+
+[[package]]
+name = "poly1305"
+version = "0.8.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8159bd90725d2df49889a078b54f4f79e87f1f8a8444194cdca81d38f5393abf"
+dependencies = [
+ "cpufeatures",
+ "opaque-debug",
+ "universal-hash 0.5.1",
]
[[package]]
@@ -2006,7 +2100,19 @@ dependencies = [
"cfg-if",
"cpufeatures",
"opaque-debug",
- "universal-hash",
+ "universal-hash 0.4.0",
+]
+
+[[package]]
+name = "polyval"
+version = "0.6.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d52cff9d1d4dee5fe6d03729099f4a310a41179e0a10dbf542039873f2e826fb"
+dependencies = [
+ "cfg-if",
+ "cpufeatures",
+ "opaque-debug",
+ "universal-hash 0.5.1",
]
[[package]]
@@ -2214,7 +2320,7 @@ dependencies = [
"libm",
"log",
"octets",
- "ring",
+ "ring 0.16.20",
"slab",
"smallvec",
"winapi",
@@ -2349,12 +2455,26 @@ dependencies = [
"cc",
"libc",
"once_cell",
- "spin",
- "untrusted",
+ "spin 0.5.2",
+ "untrusted 0.7.1",
"web-sys",
"winapi",
]
+[[package]]
+name = "ring"
+version = "0.17.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "fb0205304757e5d899b9c2e448b867ffd03ae7f988002e47cd24954391394d0b"
+dependencies = [
+ "cc",
+ "getrandom",
+ "libc",
+ "spin 0.9.8",
+ "untrusted 0.9.0",
+ "windows-sys 0.48.0",
+]
+
[[package]]
name = "rustc-demangle"
version = "0.1.23"
@@ -2396,7 +2516,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c911ba11bc8433e811ce56fde130ccf32f5127cab0e0194e9c68c5a5b671791e"
dependencies = [
"log",
- "ring",
+ "ring 0.16.20",
"rustls-webpki",
"sct",
]
@@ -2416,8 +2536,8 @@ version = "0.100.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d6207cd5ed3d8dca7816f8f3725513a34609c0c765bf652b8c3cb4cfd87db46b"
dependencies = [
- "ring",
- "untrusted",
+ "ring 0.16.20",
+ "untrusted 0.7.1",
]
[[package]]
@@ -2461,12 +2581,12 @@ checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49"
[[package]]
name = "sct"
-version = "0.7.0"
+version = "0.7.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d53dcdb7c9f8158937a7981b48accfd39a43af418591a5d008c7b22b5e1b7ca4"
+checksum = "da046153aa2352493d6cb7da4b6e5c0c057d8a1d0a9aa8560baffdd945acd414"
dependencies = [
- "ring",
- "untrusted",
+ "ring 0.17.5",
+ "untrusted 0.9.0",
]
[[package]]
@@ -2522,10 +2642,10 @@ dependencies = [
]
[[package]]
-name = "sha-1"
-version = "0.10.1"
+name = "sha1"
+version = "0.10.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f5058ada175748e33390e40e872bd0fe59a19f265d0158daa551c5a88a76009c"
+checksum = "f04293dc80c3993519f2d7f6f511707ee7094fe0c6d3406feb330cdb3540eba3"
dependencies = [
"cfg-if",
"cpufeatures",
@@ -2567,18 +2687,19 @@ dependencies = [
name = "signal-crypto"
version = "0.1.0"
dependencies = [
- "aes",
- "block-modes",
+ "aes 0.8.3",
+ "cbc",
"criterion",
+ "ctr 0.9.2",
"displaydoc",
- "generic-array",
- "ghash",
+ "ghash 0.5.0",
"hex",
+ "hex-literal",
"hmac",
"rand",
"serde",
"serde_json",
- "sha-1",
+ "sha1",
"sha2",
"subtle",
"thiserror",
@@ -2649,7 +2770,7 @@ dependencies = [
"futures",
"mio",
"quiche",
- "ring",
+ "ring 0.16.20",
"thiserror",
"tokio",
"tokio-stream",
@@ -2676,12 +2797,13 @@ dependencies = [
[[package]]
name = "snow"
-version = "0.9.0"
-source = "git+https://github.com/mcginty/snow.git?rev=586292364a30ecc74c785228b41e60b3ef03e773#586292364a30ecc74c785228b41e60b3ef03e773"
+version = "0.9.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0c9d1425eb528a21de2755c75af4c9b5d57f50a0d4c3b7f1828a4cd03f8ba155"
dependencies = [
"aes-gcm",
"blake2",
- "chacha20poly1305",
+ "chacha20poly1305 0.9.1",
"curve25519-dalek",
"rand_core",
"rustc_version",
@@ -2705,6 +2827,12 @@ version = "0.5.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d"
+[[package]]
+name = "spin"
+version = "0.9.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67"
+
[[package]]
name = "static_assertions"
version = "1.1.0"
@@ -2881,9 +3009,9 @@ dependencies = [
[[package]]
name = "tokio-rustls"
-version = "0.24.0"
+version = "0.24.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e0d409377ff5b1e3ca6437aa86c1eb7d40c134bfec254e44c830defa92669db5"
+checksum = "c28327cf380ac148141087fbfb9de9d7bd4e84ab5d2c28fbc911d753de8a7081"
dependencies = [
"rustls",
"tokio",
@@ -3010,11 +3138,10 @@ checksum = "b6bc1c9ce2b5135ac7f93c72918fc37feb872bdc6a5533a8b85eb4b86bfdae52"
[[package]]
name = "tracing"
-version = "0.1.35"
+version = "0.1.40"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a400e31aa60b9d44a52a8ee0343b5b18566b03a8321e0d321f695cf56e940160"
+checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef"
dependencies = [
- "cfg-if",
"pin-project-lite",
"tracing-attributes",
"tracing-core",
@@ -3022,9 +3149,9 @@ dependencies = [
[[package]]
name = "tracing-attributes"
-version = "0.1.24"
+version = "0.1.27"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0f57e3ca2a01450b1a921183a9c9cbfda207fd822cef4ccb00a65402cbba7a74"
+checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7"
dependencies = [
"proc-macro2",
"quote",
@@ -3033,9 +3160,9 @@ dependencies = [
[[package]]
name = "tracing-core"
-version = "0.1.30"
+version = "0.1.32"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "24eb03ba0eab1fd845050058ce5e616558e8f8d8fca633e6b163fe25c797213a"
+checksum = "c06d3da6113f116aaee68e4d601191614c9053067f9ab7f6edbcb161237daa54"
dependencies = [
"once_cell",
]
@@ -3095,12 +3222,28 @@ dependencies = [
"subtle",
]
+[[package]]
+name = "universal-hash"
+version = "0.5.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "fc1de2c688dc15305988b563c3854064043356019f97a4b46276fe734c4f07ea"
+dependencies = [
+ "crypto-common",
+ "subtle",
+]
+
[[package]]
name = "untrusted"
version = "0.7.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a156c684c91ea7d62626509bce3cb4e1d9ed5c4d978f7b4352658f96a4c26b4a"
+[[package]]
+name = "untrusted"
+version = "0.9.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1"
+
[[package]]
name = "unzip3"
version = "1.0.0"
@@ -3182,11 +3325,10 @@ dependencies = [
[[package]]
name = "want"
-version = "0.3.0"
+version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1ce8a968cb1cd110d136ff8b819a556d6fb6d919363c61534f6860c7eb172ba0"
+checksum = "bfa7760aed19e106de2c7c0b581b509f2f25d3dacaf737cb82ac61bc6d760b0e"
dependencies = [
- "log",
"try-lock",
]
@@ -3469,8 +3611,9 @@ dependencies = [
[[package]]
name = "x25519-dalek"
-version = "2.0.0-rc.3"
-source = "git+https://github.com/signalapp/curve25519-dalek?tag=signal-curve25519-4.0.0#463e5c7cba32561ffee8a281c4455ff3c25660d4"
+version = "2.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "fb66477291e7e8d2b0ff1bcb900bf29489a9692816d79874bea351e7a8b6de96"
dependencies = [
"curve25519-dalek",
"rand_core",
@@ -3506,6 +3649,7 @@ dependencies = [
"curve25519-dalek",
"displaydoc",
"hex",
+ "hex-literal",
"lazy_static",
"poksho",
"serde",
@@ -3515,7 +3659,6 @@ dependencies = [
name = "zkgroup"
version = "0.9.0"
dependencies = [
- "aead",
"aes-gcm-siv",
"base64",
"bincode",
@@ -3523,6 +3666,7 @@ dependencies = [
"curve25519-dalek",
"displaydoc",
"hex",
+ "hex-literal",
"lazy_static",
"libsignal-protocol",
"poksho",
diff --git a/Cargo.toml b/Cargo.toml
index b8aa987f95..3d8420e127 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -33,10 +33,7 @@ resolver = "2" # so that our dev-dependency features don't leak into products
[patch.crates-io]
# Use our fork of curve25519-dalek for zkgroup support.
curve25519-dalek = { git = 'https://github.com/signalapp/curve25519-dalek', tag = 'signal-curve25519-4.0.0' }
-x25519-dalek = { git = 'https://github.com/signalapp/curve25519-dalek', tag = 'signal-curve25519-4.0.0' }
boring = { git = 'https://github.com/signalapp/boring', branch = 'libsignal' }
-# This revision of snow is where curve25519-dalek v4.0.0 changes were merged in
-snow = { git = 'https://github.com/mcginty/snow.git', rev = '586292364a30ecc74c785228b41e60b3ef03e773' }
[profile.dev.package.argon2]
opt-level = 2 # signal-signal-pin unit tests are too slow with an unoptimized argon2
diff --git a/LibSignalClient.podspec b/LibSignalClient.podspec
index 051c6cec05..2db163c295 100644
--- a/LibSignalClient.podspec
+++ b/LibSignalClient.podspec
@@ -5,7 +5,7 @@
Pod::Spec.new do |s|
s.name = 'LibSignalClient'
- s.version = '0.31.0'
+ s.version = '0.32.1'
s.summary = 'A Swift wrapper library for communicating with the Signal messaging service.'
s.homepage = 'https://github.com/signalapp/libsignal'
diff --git a/RELEASE.md b/RELEASE.md
index 044190821c..ceae431f73 100644
--- a/RELEASE.md
+++ b/RELEASE.md
@@ -60,13 +60,9 @@ git push origin libsignal-v0.x.y
## 6. Submit to package repositories as needed
-### Android: Sonatype
+### Android and Server: Sonatype
-1. Wait for the "Publish JNI Artifacts to GitHub Release" action to complete. These artifacts, though not built reproducibly, will be included in the `libsignal-client` and `libsignal-server` jars to support running on macOS and Windows as well.
-2. Set the environment variables `SONATYPE_USERNAME`, `SONATYPE_PASSWORD`, `KEYRING_FILE`, `SIGNING_KEY`, and `SIGNING_KEY_PASSSWORD`.
-3. Run `make -C java publish_java` to build through Docker.
-
-Note that Sonatype is pretty slow; even after the build completes it might take a while for it to show up.
+In the signalapp/libsignal repository on GitHub, run the "Upload Java libraries to Sonatype" action on the tag you just made. Once complete, go into Sonatype and release the builds.
### Node: NPM
diff --git a/bin/build_helpers.sh b/bin/build_helpers.sh
index 3600197950..a236578a70 100644
--- a/bin/build_helpers.sh
+++ b/bin/build_helpers.sh
@@ -26,7 +26,6 @@ check_rust() {
fi
if [[ -n "${CARGO_BUILD_TARGET:-}" ]] && ! (rustup target list --installed | grep -q "${CARGO_BUILD_TARGET:-}"); then
- # TODO: We could remove this once Catalyst support is promoted to tier 2
if [[ -n "${BUILD_STD:-}" ]]; then
echo "warning: Building using -Zbuild-std to support tier 3 target ${CARGO_BUILD_TARGET}." >&2
else
diff --git a/bin/update_versions.py b/bin/update_versions.py
index fb33f9e126..9bddb70d19 100755
--- a/bin/update_versions.py
+++ b/bin/update_versions.py
@@ -29,7 +29,7 @@ def update_version(file, pattern, new_version):
PODSPEC_PATTERN = re.compile(r"^(.*\.version\s+=\s+')(.*)(')")
-GRADLE_PATTERN = re.compile(r'^(def\s+version_number\s+=\s+")(.*)(")')
+GRADLE_PATTERN = re.compile(r'^(\s+version\s+=\s+")(.*)(")')
NODE_PATTERN = re.compile(r'^(\s+"version": ")(.*)(")')
CARGO_PATTERN = re.compile(r'^(version = ")(.*)(")')
diff --git a/bin/verify_duplicate_crates b/bin/verify_duplicate_crates
index 81952f58e5..a73eb73e9f 100755
--- a/bin/verify_duplicate_crates
+++ b/bin/verify_duplicate_crates
@@ -5,28 +5,21 @@
# SPDX-License-Identifier: AGPL-3.0-only
#
+# To keep code size down, we try to avoid depending on multiple versions of crates.
+#
# For now, these dependencies have conflicting requirements.
# You can use the `cargo tree` command below to see where they come from,
# and then document them here.
#
# bitflags:
-# either a dev or a build time dependency.
-# syn:
-# syn is used in proc-macros only, so it isn't going to cost us in code size.
+# mostly provides a macro, with only a small bit of code that actually
+# makes it into the final build.
EXPECTED="\
bitflags v1.3.2
-bitflags v2.3.3
-
-ctr v0.7.0
-
-ctr v0.8.0
-
-syn v1.0.109
-
-syn v2.0.28"
+bitflags v2.3.3"
-if [[ "$(cargo tree -d -e normal --workspace --locked --depth 0)" != "${EXPECTED}" ]]; then
- cargo tree -d -e normal --workspace --locked
+if [[ "$(cargo tree --duplicates --edges normal,no-proc-macro --workspace --locked --depth 0)" != "${EXPECTED}" ]]; then
+ cargo tree --duplicates --edges normal,no-proc-macro --workspace --locked
exit 1
fi
diff --git a/java/Makefile b/java/Makefile
index 9d0e623b3c..e589a874f5 100644
--- a/java/Makefile
+++ b/java/Makefile
@@ -26,28 +26,22 @@ java_test: java_build
-v `cd .. && pwd`/:/home/libsignal/src $(DOCKER_EXTRA) $(DOCKER_IMAGE) \
sh -c "cd src/java; ./gradlew test"
-SONATYPE_USERNAME ?=
-SONATYPE_PASSWORD ?=
-KEYRING_FILE ?=
-SIGNING_KEY ?=
-SIGNING_KEY_PASSSWORD ?=
-
publish_java: DOCKER_EXTRA = $(shell [ -L build ] && P=$$(readlink build) && echo -v $$P/:$$P )
-publish_java: KEYRING_VOLUME := $(dir $(KEYRING_FILE))
-publish_java: KEYRING_FILE_ROOT := $(notdir $(KEYRING_FILE))
publish_java: docker_image
- @[ -n "$(SONATYPE_USERNAME)" ] || ( echo "SONATYPE_USERNAME is not set" && false )
- @[ -n "$(SONATYPE_PASSWORD)" ] || ( echo "SONATYPE_PASSWORD is not set" && false )
- @[ -n "$(KEYRING_FILE)" ] || ( echo "KEYRING_FILE is not set" && false )
- @[ -n "$(SIGNING_KEY)" ] || ( echo "SIGNING_KEY is not set" && false )
- @[ -n "$(SIGNING_KEY_PASSWORD)" ] || ( echo "SIGNING_KEY_PASSWORD is not set" && false )
$(DOCKER) run --rm --user $$(id -u):$$(id -g) \
-v `cd .. && pwd`/:/home/libsignal/src $(DOCKER_EXTRA) \
- -v $(KEYRING_VOLUME):/home/libsignal/keyring \
+ -e ORG_GRADLE_PROJECT_sonatypeUsername \
+ -e ORG_GRADLE_PROJECT_sonatypePassword \
+ -e ORG_GRADLE_PROJECT_signingKeyId \
+ -e ORG_GRADLE_PROJECT_signingPassword \
+ -e ORG_GRADLE_PROJECT_signingKey \
$(DOCKER_IMAGE) \
- sh -c "cd src/java; ./gradlew clean publish \
- -PsonatypeUsername='$(SONATYPE_USERNAME)' \
- -PsonatypePassword='$(SONATYPE_PASSWORD)' \
- -Psigning.secretKeyRingFile='/home/libsignal/keyring/$(KEYRING_FILE_ROOT)' \
- -Psigning.keyId='$(SIGNING_KEY)' \
- -Psigning.password='$(SIGNING_KEY_PASSWORD)'"
+ sh -c "cd src/java; ./gradlew publish closeSonatypeStagingRepository"
+
+# We could run these through Docker, but they would have the same result anyway.
+
+clean:
+ ./gradlew clean
+
+format_java:
+ ./gradlew spotlessApply
diff --git a/java/android/benchmarks/src/androidTest/java/ECCBenchmark.java b/java/android/benchmarks/src/androidTest/java/ECCBenchmark.java
index 713263876a..750b47df5f 100644
--- a/java/android/benchmarks/src/androidTest/java/ECCBenchmark.java
+++ b/java/android/benchmarks/src/androidTest/java/ECCBenchmark.java
@@ -1,10 +1,7 @@
-/**
- * Copyright (C) 2022 Open Whisper Systems
- *
- * Licensed according to the LICENSE file in this repository.
- */
-
-import org.signal.libsignal.protocol.ecc.*;
+//
+// Copyright 2022 Signal Messenger, LLC.
+// SPDX-License-Identifier: AGPL-3.0-only
+//
import androidx.benchmark.BenchmarkState;
import androidx.benchmark.junit4.BenchmarkRule;
@@ -12,32 +9,32 @@
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
+import org.signal.libsignal.protocol.ecc.*;
@RunWith(AndroidJUnit4.class)
public class ECCBenchmark {
- @Rule
- public final BenchmarkRule benchmarkRule = new BenchmarkRule();
+ @Rule public final BenchmarkRule benchmarkRule = new BenchmarkRule();
- private final ECKeyPair alicePair = Curve.generateKeyPair();
- private final ECKeyPair bobPair = Curve.generateKeyPair();
- private final byte[] arbitraryData = new byte[] { 0x53, 0x69, 0x67, 0x6E, 0x61, 0x6C };
+ private final ECKeyPair alicePair = Curve.generateKeyPair();
+ private final ECKeyPair bobPair = Curve.generateKeyPair();
+ private final byte[] arbitraryData = new byte[] {0x53, 0x69, 0x67, 0x6E, 0x61, 0x6C};
- @Test
- public void benchmarkKeyAgreement() {
- final BenchmarkState state = benchmarkRule.getState();
+ @Test
+ public void benchmarkKeyAgreement() {
+ final BenchmarkState state = benchmarkRule.getState();
- while (state.keepRunning()) {
- alicePair.getPrivateKey().calculateAgreement(bobPair.getPublicKey());
- }
+ while (state.keepRunning()) {
+ alicePair.getPrivateKey().calculateAgreement(bobPair.getPublicKey());
}
+ }
- @Test
- public void benchmarkSignature() {
- final BenchmarkState state = benchmarkRule.getState();
+ @Test
+ public void benchmarkSignature() {
+ final BenchmarkState state = benchmarkRule.getState();
- while (state.keepRunning()) {
- final byte[] signature = alicePair.getPrivateKey().calculateSignature(arbitraryData);
- alicePair.getPublicKey().verifySignature(arbitraryData, signature);
- }
+ while (state.keepRunning()) {
+ final byte[] signature = alicePair.getPrivateKey().calculateSignature(arbitraryData);
+ alicePair.getPublicKey().verifySignature(arbitraryData, signature);
}
+ }
}
diff --git a/java/android/build.gradle b/java/android/build.gradle
index ea231ad4c7..64b298f853 100644
--- a/java/android/build.gradle
+++ b/java/android/build.gradle
@@ -5,8 +5,6 @@ plugins {
}
archivesBaseName = "libsignal-android"
-version = version_number
-group = group_info
repositories {
google()
@@ -106,17 +104,9 @@ afterEvaluate {
}
}
}
- repositories {
- maven {
- url = getReleaseRepositoryUrl()
- credentials {
- username = getRepositoryUsername()
- password = getRepositoryPassword()
- }
- }
- }
}
+ setUpSigningKey(signing)
signing {
required { isReleaseBuild() && gradle.taskGraph.hasTask(":android:publish") }
sign publishing.publications.mavenJava
diff --git a/java/android/src/main/java/org/signal/libsignal/protocol/logging/AndroidSignalProtocolLogger.java b/java/android/src/main/java/org/signal/libsignal/protocol/logging/AndroidSignalProtocolLogger.java
index a9bf8d4e65..2e6d0d4ea4 100644
--- a/java/android/src/main/java/org/signal/libsignal/protocol/logging/AndroidSignalProtocolLogger.java
+++ b/java/android/src/main/java/org/signal/libsignal/protocol/logging/AndroidSignalProtocolLogger.java
@@ -1,8 +1,8 @@
-/**
- * Copyright (C) 2014-2016 Open Whisper Systems
- *
- * Licensed according to the LICENSE file in this repository.
- */
+//
+// Copyright 2014-2016 Signal Messenger, LLC.
+// SPDX-License-Identifier: AGPL-3.0-only
+//
+
package org.signal.libsignal.protocol.logging;
import android.util.Log;
@@ -10,14 +10,16 @@
public class AndroidSignalProtocolLogger implements SignalProtocolLogger {
- private static final SparseIntArray PRIORITY_MAP = new SparseIntArray(5) {{
- put(SignalProtocolLogger.INFO, Log.INFO);
- put(SignalProtocolLogger.ASSERT, Log.ASSERT);
- put(SignalProtocolLogger.DEBUG, Log.DEBUG);
- put(SignalProtocolLogger.VERBOSE, Log.VERBOSE);
- put(SignalProtocolLogger.WARN, Log.WARN);
-
- }};
+ private static final SparseIntArray PRIORITY_MAP =
+ new SparseIntArray(5) {
+ {
+ put(SignalProtocolLogger.INFO, Log.INFO);
+ put(SignalProtocolLogger.ASSERT, Log.ASSERT);
+ put(SignalProtocolLogger.DEBUG, Log.DEBUG);
+ put(SignalProtocolLogger.VERBOSE, Log.VERBOSE);
+ put(SignalProtocolLogger.WARN, Log.WARN);
+ }
+ };
@Override
public void log(int priority, String tag, String message) {
diff --git a/java/build.gradle b/java/build.gradle
index 2e0f381b4e..521fde39f4 100644
--- a/java/build.gradle
+++ b/java/build.gradle
@@ -1,13 +1,17 @@
plugins {
+ id "base"
+ id "signing"
id "de.undercouch.download" version "5.0.2"
+ id "com.diffplug.spotless" version "6.20.0"
+ id "io.github.gradle-nexus.publish-plugin" version "1.3.0"
}
-def version_number = "0.31.0-gluon-2"
+allprojects {
+ version = "0.32.1-gluon-2"
+ group = "org.signal"
+}
subprojects {
- ext.version_number = version_number
- ext.group_info = "org.signal"
-
if (JavaVersion.current().isJava8Compatible()) {
allprojects {
tasks.withType(Javadoc) {
@@ -23,6 +27,20 @@ subprojects {
options.compilerArgs += ["-Xlint:deprecation", "-Xlint:fallthrough", "-Xlint:unchecked"]
}
}
+
+ apply plugin: "com.diffplug.spotless"
+ spotless {
+ java {
+ target('**/*.java')
+ targetExclude('**/Native.java')
+ importOrder()
+ removeUnusedImports()
+
+ googleJavaFormat()
+ formatAnnotations()
+ licenseHeaderFile rootProject.file('license_header.txt')
+ }
+ }
}
task makeJniLibrariesDesktop(type:Exec) {
@@ -38,7 +56,7 @@ task cargoClean(type:Exec) {
commandLine 'cargo', 'clean'
}
-task clean(type: Delete) {
+task cleanJni(type: Delete) {
description 'Clean JNI libs'
delete fileTree('./android/src/main/jniLibs') {
include '**/*.so'
@@ -49,25 +67,27 @@ task clean(type: Delete) {
include '**/*.dll'
}
}
-clean.dependsOn(cargoClean)
-task downloadNonLinuxLibraries(type: Download) {
- // Must be explicitly enabled.
- enabled false
+clean.dependsOn([cargoClean, cleanJni])
- def extraResources = ['signal_jni.dll', 'libsignal_jni.dylib']
+// PUBLISHING
- src(extraResources.collect {
- 'https://github.com/' + getGithubReleasesAccountName() + '/libsignal/releases/download/v' + version_number + '/' + it
- })
- dest 'shared/resources'
+ext.setUpSigningKey = { signingExt ->
+ def signingKeyId = findProperty("signingKeyId")
+ def signingKey = findProperty("signingKey")
+ def signingPassword = findProperty("signingPassword")
+ if (signingKeyId && signingKey && signingPassword) {
+ signingExt.useInMemoryPgpKeys(signingKeyId.trim(), signingKey.trim(), signingPassword.trim())
+ }
}
-// PUBLISHING
-
-def getGithubReleasesAccountName() {
- return hasProperty("githubReleasesAccount") ? githubReleasesAccount
- : "libsignal"
+nexusPublishing {
+ repositories {
+ sonatype {
+ username = project.findProperty('sonatypeUsername') ?: ""
+ password = project.findProperty('sonatypePassword') ?: ""
+ }
+ }
}
def isSkipSigning() {
@@ -77,16 +97,3 @@ def isSkipSigning() {
def isReleaseBuild() {
return version.contains("SNAPSHOT") == false
}
-
-def getReleaseRepositoryUrl() {
- return hasProperty('sonatypeRepo') ? sonatypeRepo
- : "https://oss.sonatype.org/service/local/staging/deploy/maven2/"
-}
-
-def getRepositoryUsername() {
- return hasProperty('sonatypeUsername') ? sonatypeUsername : ""
-}
-
-def getRepositoryPassword() {
- return hasProperty('sonatypePassword') ? sonatypePassword : ""
-}
diff --git a/java/build_jni.sh b/java/build_jni.sh
index 7d676b1dd3..1b58965094 100755
--- a/java/build_jni.sh
+++ b/java/build_jni.sh
@@ -15,8 +15,6 @@ cd "${SCRIPT_DIR}"/..
ANDROID_LIB_DIR=java/android/src/main/jniLibs
DESKTOP_LIB_DIR=java/shared/resources
-# Keep these settings in sync with .github/workflows/jni_artifacts.yml,
-# which builds for Windows as well.
export CARGO_PROFILE_RELEASE_DEBUG=1 # enable line tables
# On Linux, cdylibs don't include public symbols from their dependencies,
# even if those symbols have been re-exported in the Rust source.
@@ -28,7 +26,9 @@ export CARGO_PROFILE_RELEASE_OPT_LEVEL=s # optimize for size over speed
if [ "$1" = 'desktop' ];
then
echo_then_run cargo build -p libsignal-jni --release
- copy_built_library target/release signal_jni "${DESKTOP_LIB_DIR}/"
+ if [[ -z "${CARGO_BUILD_TARGET:-}" ]]; then
+ copy_built_library target/release signal_jni "${DESKTOP_LIB_DIR}/"
+ fi
elif [ "$1" = 'android' ];
then
# Use small BoringSSL curve tables to reduce binary size on Android.
@@ -48,6 +48,7 @@ then
export TARGET_AR="${ANDROID_TOOLCHAIN_DIR}/llvm-ar"
export RUSTFLAGS="-C link-arg=-fuse-ld=lld ${RUSTFLAGS:-}"
+ export RUSTFLAGS="--cfg aes_armv8 --cfg polyval_armv8 ${RUSTFLAGS:-}" # Enable ARMv8 cryptography acceleration when available
# Uncomment the following to force the 64-bit curve25519-dalek backend on 32-bit targets.
# export RUSTFLAGS="--cfg curve25519_dalek_bits=\"64\" ${RUSTFLAGS:-}"
diff --git a/java/client/build.gradle b/java/client/build.gradle
index 1a2b003d74..3f8f53a979 100644
--- a/java/client/build.gradle
+++ b/java/client/build.gradle
@@ -7,8 +7,6 @@ plugins {
sourceCompatibility = 1.8
archivesBaseName = "libsignal-client"
-version = version_number
-group = group_info
repositories {
mavenCentral()
@@ -57,15 +55,15 @@ java {
withJavadocJar()
}
+tasks.named('jar') {
+ manifest {
+ attributes('Automatic-Module-Name': 'org.signal.libsignal')
+ }
+}
+
processResources {
// TODO: Build a different variant of the JNI library for server.
dependsOn ':makeJniLibrariesDesktop'
- dependsOn ':downloadNonLinuxLibraries'
- gradle.taskGraph.whenReady { graph ->
- if (graph.hasTask(":client:publish")) {
- tasks.getByPath(":downloadNonLinuxLibraries").enabled = true
- }
- }
}
// MARK: Publishing
@@ -102,17 +100,9 @@ publishing {
}
}
}
- repositories {
- maven {
- url = getReleaseRepositoryUrl()
- credentials {
- username = getRepositoryUsername()
- password = getRepositoryPassword()
- }
- }
- }
}
+setUpSigningKey(signing)
signing {
required { !isSkipSigning() && isReleaseBuild() && gradle.taskGraph.hasTask(":client:publish") }
sign publishing.publications.mavenJava
diff --git a/java/client/src/main/java/org/signal/libsignal/cds2/Cds2Client.java b/java/client/src/main/java/org/signal/libsignal/cds2/Cds2Client.java
index b5a6b4e752..c0b0cfce5b 100644
--- a/java/client/src/main/java/org/signal/libsignal/cds2/Cds2Client.java
+++ b/java/client/src/main/java/org/signal/libsignal/cds2/Cds2Client.java
@@ -5,21 +5,22 @@
package org.signal.libsignal.cds2;
-import org.signal.libsignal.sgxsession.SgxClient;
+import java.time.Instant;
import org.signal.libsignal.attest.AttestationDataException;
import org.signal.libsignal.internal.Native;
-
-import java.time.Instant;
+import org.signal.libsignal.sgxsession.SgxClient;
/**
- * Cds2Client provides bindings to interact with Signal's v2 Contact Discovery Service.
+ * Cds2Client provides bindings to interact with Signal's v2 Contact Discovery Service.
*
- * {@inheritDoc}
+ *
{@inheritDoc}
*
- * A future update to Cds2Client will implement additional parts of the contact discovery protocol.
+ *
A future update to Cds2Client will implement additional parts of the contact discovery
+ * protocol.
*/
public class Cds2Client extends SgxClient {
- public Cds2Client(byte[] mrenclave, byte[] attestationMsg, Instant currentInstant) throws AttestationDataException {
+ public Cds2Client(byte[] mrenclave, byte[] attestationMsg, Instant currentInstant)
+ throws AttestationDataException {
super(Native.Cds2ClientState_New(mrenclave, attestationMsg, currentInstant.toEpochMilli()));
}
}
diff --git a/java/client/src/main/java/org/signal/libsignal/chat/DeviceClient.java b/java/client/src/main/java/org/signal/libsignal/chat/DeviceClient.java
index f04b987fa4..70049b6631 100644
--- a/java/client/src/main/java/org/signal/libsignal/chat/DeviceClient.java
+++ b/java/client/src/main/java/org/signal/libsignal/chat/DeviceClient.java
@@ -1,3 +1,8 @@
+//
+// Copyright 2023 Signal Messenger, LLC.
+// SPDX-License-Identifier: AGPL-3.0-only
+//
+
package org.signal.libsignal.chat;
import com.google.protobuf.InvalidProtocolBufferException;
@@ -20,7 +25,8 @@ public DeviceClient(String target) {
this.unsafeHandle = Native.DeviceClient_New(target);
}
- @Override @SuppressWarnings("deprecation")
+ @Override
+ @SuppressWarnings("deprecation")
protected void finalize() {
Native.ProfileClient_Destroy(this.unsafeHandle);
}
@@ -29,9 +35,12 @@ public long unsafeNativeHandleWithoutGuard() {
return this.unsafeHandle;
}
- public GetDevicesResponse getDevices(GetDevicesRequest request, String authorization) throws SignalChatCommunicationFailureException {
+ public GetDevicesResponse getDevices(GetDevicesRequest request, String authorization)
+ throws SignalChatCommunicationFailureException {
try (NativeHandleGuard guard = new NativeHandleGuard(this)) {
- byte[] serializedResponse = Native.DeviceClient_GetDevices(guard.nativeHandle(), request.toByteArray(), authorization);
+ byte[] serializedResponse =
+ Native.DeviceClient_GetDevices(
+ guard.nativeHandle(), request.toByteArray(), authorization);
return GetDevicesResponse.parseFrom(serializedResponse);
} catch (InvalidProtocolBufferException e) {
throw new SignalChatCommunicationFailureException(e);
diff --git a/java/client/src/main/java/org/signal/libsignal/chat/ProfileClient.java b/java/client/src/main/java/org/signal/libsignal/chat/ProfileClient.java
index 5a6a36dc85..7503621bf5 100644
--- a/java/client/src/main/java/org/signal/libsignal/chat/ProfileClient.java
+++ b/java/client/src/main/java/org/signal/libsignal/chat/ProfileClient.java
@@ -1,3 +1,8 @@
+//
+// Copyright 2023 Signal Messenger, LLC.
+// SPDX-License-Identifier: AGPL-3.0-only
+//
+
package org.signal.libsignal.chat;
import com.google.protobuf.InvalidProtocolBufferException;
@@ -20,7 +25,8 @@ public ProfileClient(String target) {
this.unsafeHandle = Native.ProfileClient_New(target);
}
- @Override @SuppressWarnings("deprecation")
+ @Override
+ @SuppressWarnings("deprecation")
protected void finalize() {
Native.ProfileClient_Destroy(this.unsafeHandle);
}
@@ -29,9 +35,11 @@ public long unsafeNativeHandleWithoutGuard() {
return this.unsafeHandle;
}
- public GetVersionedProfileResponse getVersionedProfile(GetVersionedProfileRequest request) throws SignalChatCommunicationFailureException {
+ public GetVersionedProfileResponse getVersionedProfile(GetVersionedProfileRequest request)
+ throws SignalChatCommunicationFailureException {
try (NativeHandleGuard guard = new NativeHandleGuard(this)) {
- byte[] serializedResponse = Native.ProfileClient_GetVersionedProfile(guard.nativeHandle(), request.toByteArray());
+ byte[] serializedResponse =
+ Native.ProfileClient_GetVersionedProfile(guard.nativeHandle(), request.toByteArray());
return GetVersionedProfileResponse.parseFrom(serializedResponse);
} catch (InvalidProtocolBufferException e) {
throw new SignalChatCommunicationFailureException(e);
diff --git a/java/client/src/main/java/org/signal/libsignal/chat/SignalChatCommunicationFailureException.java b/java/client/src/main/java/org/signal/libsignal/chat/SignalChatCommunicationFailureException.java
index 30bb4bac69..feb2d73745 100644
--- a/java/client/src/main/java/org/signal/libsignal/chat/SignalChatCommunicationFailureException.java
+++ b/java/client/src/main/java/org/signal/libsignal/chat/SignalChatCommunicationFailureException.java
@@ -1,6 +1,16 @@
+//
+// Copyright 2023 Signal Messenger, LLC.
+// SPDX-License-Identifier: AGPL-3.0-only
+//
+
package org.signal.libsignal.chat;
public class SignalChatCommunicationFailureException extends Exception {
- public SignalChatCommunicationFailureException(String msg) { super(msg); }
- public SignalChatCommunicationFailureException(Throwable t) { super(t); }
+ public SignalChatCommunicationFailureException(String msg) {
+ super(msg);
+ }
+
+ public SignalChatCommunicationFailureException(Throwable t) {
+ super(t);
+ }
}
diff --git a/java/client/src/main/java/org/signal/libsignal/crypto/Aes256Ctr32.java b/java/client/src/main/java/org/signal/libsignal/crypto/Aes256Ctr32.java
index fe4b291c99..12fc545efc 100644
--- a/java/client/src/main/java/org/signal/libsignal/crypto/Aes256Ctr32.java
+++ b/java/client/src/main/java/org/signal/libsignal/crypto/Aes256Ctr32.java
@@ -16,7 +16,8 @@ public Aes256Ctr32(byte[] key, byte[] nonce, int initialCtr) throws InvalidKeyEx
this.unsafeHandle = Native.Aes256Ctr32_New(key, nonce, initialCtr);
}
- @Override @SuppressWarnings("deprecation")
+ @Override
+ @SuppressWarnings("deprecation")
protected void finalize() {
Native.Aes256Ctr32_Destroy(this.unsafeHandle);
}
diff --git a/java/client/src/main/java/org/signal/libsignal/crypto/Aes256GcmDecryption.java b/java/client/src/main/java/org/signal/libsignal/crypto/Aes256GcmDecryption.java
index 7ae18db17d..23c5d2395e 100644
--- a/java/client/src/main/java/org/signal/libsignal/crypto/Aes256GcmDecryption.java
+++ b/java/client/src/main/java/org/signal/libsignal/crypto/Aes256GcmDecryption.java
@@ -14,11 +14,13 @@ public class Aes256GcmDecryption implements NativeHandleGuard.Owner {
private long unsafeHandle;
- public Aes256GcmDecryption(byte[] key, byte[] nonce, byte[] associatedData) throws InvalidKeyException {
+ public Aes256GcmDecryption(byte[] key, byte[] nonce, byte[] associatedData)
+ throws InvalidKeyException {
this.unsafeHandle = Native.Aes256GcmDecryption_New(key, nonce, associatedData);
}
- @Override @SuppressWarnings("deprecation")
+ @Override
+ @SuppressWarnings("deprecation")
protected void finalize() {
Native.Aes256GcmDecryption_Destroy(this.unsafeHandle);
}
@@ -47,5 +49,4 @@ public boolean verifyTag(byte[] tag) {
return tagOk;
}
}
-
}
diff --git a/java/client/src/main/java/org/signal/libsignal/crypto/Aes256GcmEncryption.java b/java/client/src/main/java/org/signal/libsignal/crypto/Aes256GcmEncryption.java
index d0623e4883..52f2fc5481 100644
--- a/java/client/src/main/java/org/signal/libsignal/crypto/Aes256GcmEncryption.java
+++ b/java/client/src/main/java/org/signal/libsignal/crypto/Aes256GcmEncryption.java
@@ -12,11 +12,13 @@
public class Aes256GcmEncryption implements NativeHandleGuard.Owner {
private long unsafeHandle;
- public Aes256GcmEncryption(byte[] key, byte[] nonce, byte[] associatedData) throws InvalidKeyException {
+ public Aes256GcmEncryption(byte[] key, byte[] nonce, byte[] associatedData)
+ throws InvalidKeyException {
this.unsafeHandle = Native.Aes256GcmEncryption_New(key, nonce, associatedData);
}
- @Override @SuppressWarnings("deprecation")
+ @Override
+ @SuppressWarnings("deprecation")
protected void finalize() {
Native.Aes256GcmEncryption_Destroy(this.unsafeHandle);
}
@@ -45,5 +47,4 @@ public byte[] computeTag() {
return tag;
}
}
-
}
diff --git a/java/client/src/main/java/org/signal/libsignal/crypto/Aes256GcmSiv.java b/java/client/src/main/java/org/signal/libsignal/crypto/Aes256GcmSiv.java
index 73792b16e1..693ede9a7f 100644
--- a/java/client/src/main/java/org/signal/libsignal/crypto/Aes256GcmSiv.java
+++ b/java/client/src/main/java/org/signal/libsignal/crypto/Aes256GcmSiv.java
@@ -7,8 +7,8 @@
import org.signal.libsignal.internal.Native;
import org.signal.libsignal.internal.NativeHandleGuard;
-import org.signal.libsignal.protocol.InvalidMessageException;
import org.signal.libsignal.protocol.InvalidKeyException;
+import org.signal.libsignal.protocol.InvalidMessageException;
class Aes256GcmSiv implements NativeHandleGuard.Owner {
private final long unsafeHandle;
@@ -17,7 +17,8 @@ public Aes256GcmSiv(byte[] key) throws InvalidKeyException {
this.unsafeHandle = Native.Aes256GcmSiv_New(key);
}
- @Override @SuppressWarnings("deprecation")
+ @Override
+ @SuppressWarnings("deprecation")
protected void finalize() {
Native.Aes256GcmSiv_Destroy(this.unsafeHandle);
}
diff --git a/java/client/src/main/java/org/signal/libsignal/crypto/CryptographicHash.java b/java/client/src/main/java/org/signal/libsignal/crypto/CryptographicHash.java
index cab32d1db0..53b9ecd828 100644
--- a/java/client/src/main/java/org/signal/libsignal/crypto/CryptographicHash.java
+++ b/java/client/src/main/java/org/signal/libsignal/crypto/CryptographicHash.java
@@ -19,7 +19,8 @@ public long unsafeNativeHandleWithoutGuard() {
return unsafeHandle;
}
- @Override @SuppressWarnings("deprecation")
+ @Override
+ @SuppressWarnings("deprecation")
protected void finalize() {
Native.CryptographicHash_Destroy(this.unsafeHandle);
}
@@ -41,5 +42,4 @@ public byte[] finish() {
return Native.CryptographicHash_Finalize(guard.nativeHandle());
}
}
-
}
diff --git a/java/client/src/main/java/org/signal/libsignal/crypto/CryptographicMac.java b/java/client/src/main/java/org/signal/libsignal/crypto/CryptographicMac.java
index f1b435ba38..d09515214a 100644
--- a/java/client/src/main/java/org/signal/libsignal/crypto/CryptographicMac.java
+++ b/java/client/src/main/java/org/signal/libsignal/crypto/CryptographicMac.java
@@ -15,7 +15,8 @@ public CryptographicMac(String algo, byte[] key) {
this.unsafeHandle = Native.CryptographicMac_New(algo, key);
}
- @Override @SuppressWarnings("deprecation")
+ @Override
+ @SuppressWarnings("deprecation")
protected void finalize() {
Native.CryptographicMac_Destroy(this.unsafeHandle);
}
@@ -41,5 +42,4 @@ public byte[] finish() {
return Native.CryptographicMac_Finalize(guard.nativeHandle());
}
}
-
}
diff --git a/java/client/src/main/java/org/signal/libsignal/crypto/jce/Mac.java b/java/client/src/main/java/org/signal/libsignal/crypto/jce/Mac.java
index 4fe05d584d..5e71a0fbb9 100644
--- a/java/client/src/main/java/org/signal/libsignal/crypto/jce/Mac.java
+++ b/java/client/src/main/java/org/signal/libsignal/crypto/jce/Mac.java
@@ -7,8 +7,8 @@
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
-import org.signal.libsignal.crypto.CryptographicMac;
import javax.crypto.spec.SecretKeySpec;
+import org.signal.libsignal.crypto.CryptographicMac;
public class Mac {
diff --git a/java/client/src/main/java/org/signal/libsignal/hsmenclave/EnclaveCommunicationFailureException.java b/java/client/src/main/java/org/signal/libsignal/hsmenclave/EnclaveCommunicationFailureException.java
index 66205c591e..9bffdffd6b 100644
--- a/java/client/src/main/java/org/signal/libsignal/hsmenclave/EnclaveCommunicationFailureException.java
+++ b/java/client/src/main/java/org/signal/libsignal/hsmenclave/EnclaveCommunicationFailureException.java
@@ -1,6 +1,16 @@
+//
+// Copyright 2023 Signal Messenger, LLC.
+// SPDX-License-Identifier: AGPL-3.0-only
+//
+
package org.signal.libsignal.hsmenclave;
public class EnclaveCommunicationFailureException extends Exception {
- public EnclaveCommunicationFailureException(String msg) { super(msg); }
- public EnclaveCommunicationFailureException(Throwable t) { super(t); }
+ public EnclaveCommunicationFailureException(String msg) {
+ super(msg);
+ }
+
+ public EnclaveCommunicationFailureException(Throwable t) {
+ super(t);
+ }
}
diff --git a/java/client/src/main/java/org/signal/libsignal/hsmenclave/HsmEnclaveClient.java b/java/client/src/main/java/org/signal/libsignal/hsmenclave/HsmEnclaveClient.java
index 9717185dbc..27b04373c7 100644
--- a/java/client/src/main/java/org/signal/libsignal/hsmenclave/HsmEnclaveClient.java
+++ b/java/client/src/main/java/org/signal/libsignal/hsmenclave/HsmEnclaveClient.java
@@ -5,29 +5,28 @@
package org.signal.libsignal.hsmenclave;
-import org.signal.libsignal.internal.Native;
-import org.signal.libsignal.internal.NativeHandleGuard;
-import org.signal.libsignal.protocol.InvalidKeyException;
-
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.List;
+import org.signal.libsignal.internal.Native;
+import org.signal.libsignal.internal.NativeHandleGuard;
/**
* HsmEnclaveClient provides bindings to interact with Signal's HSM-backed enclave.
*
- * Interaction with the enclave is done over a websocket, which is handled by the client. Once the websocket
- * has been initiated, the client establishes a connection in the following manner:
+ *
Interaction with the enclave is done over a websocket, which is handled by the client. Once
+ * the websocket has been initiated, the client establishes a connection in the following manner:
*
*
code_hashes) {
this.unsafeHandle = Native.HsmEnclaveClient_New(public_key, concatHashes.toByteArray());
}
- @Override @SuppressWarnings("deprecation")
+ @Override
+ @SuppressWarnings("deprecation")
protected void finalize() {
Native.HsmEnclaveClient_Destroy(this.unsafeHandle);
}
diff --git a/java/client/src/main/java/org/signal/libsignal/hsmenclave/TrustedCodeMismatchException.java b/java/client/src/main/java/org/signal/libsignal/hsmenclave/TrustedCodeMismatchException.java
index 149cd834bc..04519066e4 100644
--- a/java/client/src/main/java/org/signal/libsignal/hsmenclave/TrustedCodeMismatchException.java
+++ b/java/client/src/main/java/org/signal/libsignal/hsmenclave/TrustedCodeMismatchException.java
@@ -1,6 +1,16 @@
+//
+// Copyright 2023 Signal Messenger, LLC.
+// SPDX-License-Identifier: AGPL-3.0-only
+//
+
package org.signal.libsignal.hsmenclave;
public class TrustedCodeMismatchException extends Exception {
- public TrustedCodeMismatchException(String msg) { super(msg); }
- public TrustedCodeMismatchException(Throwable t) { super(t); }
+ public TrustedCodeMismatchException(String msg) {
+ super(msg);
+ }
+
+ public TrustedCodeMismatchException(Throwable t) {
+ super(t);
+ }
}
diff --git a/java/client/src/main/java/org/signal/libsignal/media/Mp4Sanitizer.java b/java/client/src/main/java/org/signal/libsignal/media/Mp4Sanitizer.java
index 20026193a5..29fa99cd4e 100644
--- a/java/client/src/main/java/org/signal/libsignal/media/Mp4Sanitizer.java
+++ b/java/client/src/main/java/org/signal/libsignal/media/Mp4Sanitizer.java
@@ -5,65 +5,69 @@
package org.signal.libsignal.media;
-import org.signal.libsignal.internal.Native;
-
import java.io.IOException;
import java.io.InputStream;
+import org.signal.libsignal.internal.Native;
/**
* An MP4 format “sanitizer”.
*
- * Currently the sanitizer always performs the following functions:
+ * Currently the sanitizer always performs the following functions:
*
*
- * Return all presentation metadata present in the input as a self-contained contiguous byte array.
- * Find and return a pointer to the span in the input containing the (contiguous) media data.
+ * Return all presentation metadata present in the input as a self-contained contiguous byte
+ * array.
+ * Find and return a pointer to the span in the input containing the (contiguous) media data.
*
*
- * “Presentation” metadata means any metadata which is required by an MP4 player to play the file. “Self-contained and contiguous” means
- * that the returned metadata can be concatenated with the media data to form a valid MP4 file.
+ *
“Presentation” metadata means any metadata which is required by an MP4 player to play the
+ * file. “Self-contained and contiguous” means that the returned metadata can be concatenated with
+ * the media data to form a valid MP4 file.
*
- *
The original metadata may or may not need to be modified in order to perform these functions. In the case that the original metadata does
- * not need to be modified, the returned sanitized metadata will be null to prevent needless data copying.
+ *
The original metadata may or may not need to be modified in order to perform these functions.
+ * In the case that the original metadata does not need to be modified, the returned sanitized
+ * metadata will be null to prevent needless data copying.
*
*
Unsupported MP4 features
*
* The sanitizer does not currently support:
*
*
- * “Fragmented” MP4 files, which are mostly used for adaptive-bitrate streaming.
- * Discontiguous media data, i.e. media data (mdat) boxes interspersed with presentation metadata (moov).
- * Media data references (dref) pointing to separate files.
- * Any similar format, e.g. Quicktime File Format (mov) or the legacy MP4 version 1, which does not contain the "isom" compatible
- * brand in its file type header (ftyp).
+ * “Fragmented” MP4 files, which are mostly used for adaptive-bitrate streaming.
+ * Discontiguous media data, i.e. media data (mdat) boxes interspersed with presentation
+ * metadata (moov).
+ * Media data references (dref) pointing to separate files.
+ * Any similar format, e.g. Quicktime File Format (mov) or the legacy MP4 version 1, which
+ * does not contain the "isom" compatible brand in its file type header (ftyp).
*
*/
public class Mp4Sanitizer {
- /**
- * Sanitize an MP4 input.
- *
- * It's recommended that the given {@link InputStream} be capable of {@code skip}ping. If it is, then it must only skip fewer
- * bytes than requested when the end of stream is reached.
- *
- * @param input An MP4 format input stream.
- * @param length The exact length of the input stream.
- * @return The sanitized metadata.
- * @throws IOException If an IO error on the input occurs.
- * @throws ParseException If the input could not be parsed.
- */
- public static SanitizedMetadata sanitize(InputStream input, long length) throws IOException, ParseException {
- long sanitizedMetadataHandle = Native.Mp4Sanitizer_Sanitize(input, length);
- try {
- byte[] sanitizedMetadata = Native.SanitizedMetadata_GetMetadata(sanitizedMetadataHandle);
- if (sanitizedMetadata.length == 0) {
- sanitizedMetadata = null;
- }
- long dataOffset = Native.SanitizedMetadata_GetDataOffset(sanitizedMetadataHandle);
- long dataLength = Native.SanitizedMetadata_GetDataLen(sanitizedMetadataHandle);
- return new SanitizedMetadata(sanitizedMetadata, dataOffset, dataLength);
- } finally {
- Native.SanitizedMetadata_Destroy(sanitizedMetadataHandle);
- }
+ /**
+ * Sanitize an MP4 input.
+ *
+ *
It's recommended that the given {@link InputStream} be capable of {@code skip}ping. If it
+ * is, then it must only skip fewer bytes than requested when the end of stream is reached.
+ *
+ * @param input An MP4 format input stream.
+ * @param length The exact length of the input stream.
+ * @return The sanitized metadata.
+ * @throws IOException If an IO error on the input occurs.
+ * @throws ParseException If the input could not be parsed.
+ */
+ public static SanitizedMetadata sanitize(InputStream input, long length)
+ throws IOException, ParseException {
+ long sanitizedMetadataHandle = Native.Mp4Sanitizer_Sanitize(input, length);
+ try {
+ byte[] sanitizedMetadata = Native.SanitizedMetadata_GetMetadata(sanitizedMetadataHandle);
+ if (sanitizedMetadata.length == 0) {
+ sanitizedMetadata = null;
+ }
+ long dataOffset = Native.SanitizedMetadata_GetDataOffset(sanitizedMetadataHandle);
+ long dataLength = Native.SanitizedMetadata_GetDataLen(sanitizedMetadataHandle);
+ return new SanitizedMetadata(sanitizedMetadata, dataOffset, dataLength);
+ } finally {
+ Native.SanitizedMetadata_Destroy(sanitizedMetadataHandle);
}
+ }
}
diff --git a/java/client/src/main/java/org/signal/libsignal/media/ParseException.java b/java/client/src/main/java/org/signal/libsignal/media/ParseException.java
index 0521ac085b..7c7854ac46 100644
--- a/java/client/src/main/java/org/signal/libsignal/media/ParseException.java
+++ b/java/client/src/main/java/org/signal/libsignal/media/ParseException.java
@@ -6,15 +6,20 @@
package org.signal.libsignal.media;
/**
- * Signals that the given media input could not be parsed for some reason. Developer-readable details are provided in the message.
+ * Signals that the given media input could not be parsed for some reason. Developer-readable
+ * details are provided in the message.
*/
public class ParseException extends Exception {
- // This constructor is called by native code.
- @SuppressWarnings("unused")
- public ParseException(String msg) { super(msg); }
+ // This constructor is called by native code.
+ @SuppressWarnings("unused")
+ public ParseException(String msg) {
+ super(msg);
+ }
- // This constructor is called by native code.
- @SuppressWarnings("unused")
- public ParseException(Throwable t) { super(t); }
+ // This constructor is called by native code.
+ @SuppressWarnings("unused")
+ public ParseException(Throwable t) {
+ super(t);
+ }
}
diff --git a/java/client/src/main/java/org/signal/libsignal/media/SanitizedMetadata.java b/java/client/src/main/java/org/signal/libsignal/media/SanitizedMetadata.java
index 7251f1e9cf..649fc75a42 100644
--- a/java/client/src/main/java/org/signal/libsignal/media/SanitizedMetadata.java
+++ b/java/client/src/main/java/org/signal/libsignal/media/SanitizedMetadata.java
@@ -7,37 +7,40 @@
public class SanitizedMetadata {
- private byte[] sanitizedMetadata;
- private long dataOffset;
- private long dataLength;
+ private byte[] sanitizedMetadata;
+ private long dataOffset;
+ private long dataLength;
- public SanitizedMetadata(byte[] sanitizedMetadata, long dataOffset, long dataLength) {
- this.sanitizedMetadata = sanitizedMetadata;
- this.dataOffset = dataOffset;
- this.dataLength = dataLength;
- }
+ public SanitizedMetadata(byte[] sanitizedMetadata, long dataOffset, long dataLength) {
+ this.sanitizedMetadata = sanitizedMetadata;
+ this.dataOffset = dataOffset;
+ this.dataLength = dataLength;
+ }
- /**
- * Get the sanitized metadata, if any.
- * @return The sanitized metadata, or {@code null} if it didn't need to be sanitized.
- */
- public byte[] getSanitizedMetadata() {
- return sanitizedMetadata;
- }
+ /**
+ * Get the sanitized metadata, if any.
+ *
+ * @return The sanitized metadata, or {@code null} if it didn't need to be sanitized.
+ */
+ public byte[] getSanitizedMetadata() {
+ return sanitizedMetadata;
+ }
- /**
- * Get the offset of the media data in the processed input.
- * @return The offset of the media data in the processed input.
- */
- public long getDataOffset() {
- return dataOffset;
- }
+ /**
+ * Get the offset of the media data in the processed input.
+ *
+ * @return The offset of the media data in the processed input.
+ */
+ public long getDataOffset() {
+ return dataOffset;
+ }
- /**
- * Get the length of the media data in the processed input.
- * @return The length of the media data in the processed input.
- */
- public long getDataLength() {
- return dataLength;
- }
+ /**
+ * Get the length of the media data in the processed input.
+ *
+ * @return The length of the media data in the processed input.
+ */
+ public long getDataLength() {
+ return dataLength;
+ }
}
diff --git a/java/client/src/main/java/org/signal/libsignal/metadata/InvalidMetadataMessageException.java b/java/client/src/main/java/org/signal/libsignal/metadata/InvalidMetadataMessageException.java
index 01aa341b0e..0503768d85 100644
--- a/java/client/src/main/java/org/signal/libsignal/metadata/InvalidMetadataMessageException.java
+++ b/java/client/src/main/java/org/signal/libsignal/metadata/InvalidMetadataMessageException.java
@@ -1,5 +1,9 @@
-package org.signal.libsignal.metadata;
+//
+// Copyright 2023 Signal Messenger, LLC.
+// SPDX-License-Identifier: AGPL-3.0-only
+//
+package org.signal.libsignal.metadata;
public class InvalidMetadataMessageException extends Exception {
public InvalidMetadataMessageException(String s) {
@@ -9,5 +13,4 @@ public InvalidMetadataMessageException(String s) {
public InvalidMetadataMessageException(Exception s) {
super(s);
}
-
}
diff --git a/java/client/src/main/java/org/signal/libsignal/metadata/InvalidMetadataVersionException.java b/java/client/src/main/java/org/signal/libsignal/metadata/InvalidMetadataVersionException.java
index da52bd88d1..6ea2d1ee01 100644
--- a/java/client/src/main/java/org/signal/libsignal/metadata/InvalidMetadataVersionException.java
+++ b/java/client/src/main/java/org/signal/libsignal/metadata/InvalidMetadataVersionException.java
@@ -1,5 +1,9 @@
-package org.signal.libsignal.metadata;
+//
+// Copyright 2023 Signal Messenger, LLC.
+// SPDX-License-Identifier: AGPL-3.0-only
+//
+package org.signal.libsignal.metadata;
public class InvalidMetadataVersionException extends Exception {
public InvalidMetadataVersionException(String s) {
diff --git a/java/client/src/main/java/org/signal/libsignal/metadata/ProtocolDuplicateMessageException.java b/java/client/src/main/java/org/signal/libsignal/metadata/ProtocolDuplicateMessageException.java
index 5ad672c08c..ab25605f62 100644
--- a/java/client/src/main/java/org/signal/libsignal/metadata/ProtocolDuplicateMessageException.java
+++ b/java/client/src/main/java/org/signal/libsignal/metadata/ProtocolDuplicateMessageException.java
@@ -1,3 +1,8 @@
+//
+// Copyright 2023 Signal Messenger, LLC.
+// SPDX-License-Identifier: AGPL-3.0-only
+//
+
package org.signal.libsignal.metadata;
import org.signal.libsignal.metadata.protocol.UnidentifiedSenderMessageContent;
diff --git a/java/client/src/main/java/org/signal/libsignal/metadata/ProtocolException.java b/java/client/src/main/java/org/signal/libsignal/metadata/ProtocolException.java
index 20775f016f..0b9db6f438 100644
--- a/java/client/src/main/java/org/signal/libsignal/metadata/ProtocolException.java
+++ b/java/client/src/main/java/org/signal/libsignal/metadata/ProtocolException.java
@@ -1,10 +1,14 @@
+//
+// Copyright 2023 Signal Messenger, LLC.
+// SPDX-License-Identifier: AGPL-3.0-only
+//
+
package org.signal.libsignal.metadata;
+import java.util.Optional;
import org.signal.libsignal.metadata.protocol.UnidentifiedSenderMessageContent;
import org.signal.libsignal.protocol.ServiceId;
-import java.util.Optional;
-
public abstract class ProtocolException extends Exception {
private final Optional content;
@@ -13,15 +17,15 @@ public abstract class ProtocolException extends Exception {
public ProtocolException(Exception e, String sender, int senderDevice) {
super(e);
- this.content = Optional.empty();
- this.sender = sender;
+ this.content = Optional.empty();
+ this.sender = sender;
this.senderDevice = senderDevice;
}
ProtocolException(Exception e, UnidentifiedSenderMessageContent content) {
super(e);
- this.content = Optional.of(content);
- this.sender = content.getSenderCertificate().getSender();
+ this.content = Optional.of(content);
+ this.sender = content.getSenderCertificate().getSender();
this.senderDevice = content.getSenderCertificate().getSenderDeviceId();
}
@@ -33,9 +37,7 @@ public String getSender() {
return sender;
}
- /**
- * Returns an Aci if the sender is a valid UUID, {@code null} otherwise.
- */
+ /** Returns an Aci if the sender is a valid UUID, {@code null} otherwise. */
public ServiceId.Aci getSenderAci() {
try {
return ServiceId.Aci.parseFromString(getSender());
diff --git a/java/client/src/main/java/org/signal/libsignal/metadata/ProtocolInvalidKeyException.java b/java/client/src/main/java/org/signal/libsignal/metadata/ProtocolInvalidKeyException.java
index a6ee3c63a0..bfaa5cb17e 100644
--- a/java/client/src/main/java/org/signal/libsignal/metadata/ProtocolInvalidKeyException.java
+++ b/java/client/src/main/java/org/signal/libsignal/metadata/ProtocolInvalidKeyException.java
@@ -1,3 +1,8 @@
+//
+// Copyright 2023 Signal Messenger, LLC.
+// SPDX-License-Identifier: AGPL-3.0-only
+//
+
package org.signal.libsignal.metadata;
import org.signal.libsignal.metadata.protocol.UnidentifiedSenderMessageContent;
diff --git a/java/client/src/main/java/org/signal/libsignal/metadata/ProtocolInvalidKeyIdException.java b/java/client/src/main/java/org/signal/libsignal/metadata/ProtocolInvalidKeyIdException.java
index 9ba708ec01..52bfa4671b 100644
--- a/java/client/src/main/java/org/signal/libsignal/metadata/ProtocolInvalidKeyIdException.java
+++ b/java/client/src/main/java/org/signal/libsignal/metadata/ProtocolInvalidKeyIdException.java
@@ -1,3 +1,8 @@
+//
+// Copyright 2023 Signal Messenger, LLC.
+// SPDX-License-Identifier: AGPL-3.0-only
+//
+
package org.signal.libsignal.metadata;
import org.signal.libsignal.metadata.protocol.UnidentifiedSenderMessageContent;
diff --git a/java/client/src/main/java/org/signal/libsignal/metadata/ProtocolInvalidMessageException.java b/java/client/src/main/java/org/signal/libsignal/metadata/ProtocolInvalidMessageException.java
index 0986341d88..c6316f6f96 100644
--- a/java/client/src/main/java/org/signal/libsignal/metadata/ProtocolInvalidMessageException.java
+++ b/java/client/src/main/java/org/signal/libsignal/metadata/ProtocolInvalidMessageException.java
@@ -1,14 +1,21 @@
+//
+// Copyright 2023 Signal Messenger, LLC.
+// SPDX-License-Identifier: AGPL-3.0-only
+//
+
package org.signal.libsignal.metadata;
import org.signal.libsignal.metadata.protocol.UnidentifiedSenderMessageContent;
import org.signal.libsignal.protocol.InvalidMessageException;
public class ProtocolInvalidMessageException extends ProtocolException {
- public ProtocolInvalidMessageException(InvalidMessageException e, String sender, int senderDevice) {
+ public ProtocolInvalidMessageException(
+ InvalidMessageException e, String sender, int senderDevice) {
super(e, sender, senderDevice);
}
- ProtocolInvalidMessageException(InvalidMessageException e, UnidentifiedSenderMessageContent content) {
+ ProtocolInvalidMessageException(
+ InvalidMessageException e, UnidentifiedSenderMessageContent content) {
super(e, content);
}
}
diff --git a/java/client/src/main/java/org/signal/libsignal/metadata/ProtocolInvalidVersionException.java b/java/client/src/main/java/org/signal/libsignal/metadata/ProtocolInvalidVersionException.java
index 4b3998f9eb..629863ac63 100644
--- a/java/client/src/main/java/org/signal/libsignal/metadata/ProtocolInvalidVersionException.java
+++ b/java/client/src/main/java/org/signal/libsignal/metadata/ProtocolInvalidVersionException.java
@@ -1,14 +1,21 @@
+//
+// Copyright 2023 Signal Messenger, LLC.
+// SPDX-License-Identifier: AGPL-3.0-only
+//
+
package org.signal.libsignal.metadata;
import org.signal.libsignal.metadata.protocol.UnidentifiedSenderMessageContent;
import org.signal.libsignal.protocol.InvalidVersionException;
public class ProtocolInvalidVersionException extends ProtocolException {
- public ProtocolInvalidVersionException(InvalidVersionException e, String sender, int senderDevice) {
+ public ProtocolInvalidVersionException(
+ InvalidVersionException e, String sender, int senderDevice) {
super(e, sender, senderDevice);
}
- ProtocolInvalidVersionException(InvalidVersionException e, UnidentifiedSenderMessageContent content) {
+ ProtocolInvalidVersionException(
+ InvalidVersionException e, UnidentifiedSenderMessageContent content) {
super(e, content);
}
}
diff --git a/java/client/src/main/java/org/signal/libsignal/metadata/ProtocolLegacyMessageException.java b/java/client/src/main/java/org/signal/libsignal/metadata/ProtocolLegacyMessageException.java
index b28635b7e9..56c6d920ba 100644
--- a/java/client/src/main/java/org/signal/libsignal/metadata/ProtocolLegacyMessageException.java
+++ b/java/client/src/main/java/org/signal/libsignal/metadata/ProtocolLegacyMessageException.java
@@ -1,14 +1,21 @@
+//
+// Copyright 2023 Signal Messenger, LLC.
+// SPDX-License-Identifier: AGPL-3.0-only
+//
+
package org.signal.libsignal.metadata;
import org.signal.libsignal.metadata.protocol.UnidentifiedSenderMessageContent;
import org.signal.libsignal.protocol.LegacyMessageException;
public class ProtocolLegacyMessageException extends ProtocolException {
- public ProtocolLegacyMessageException(LegacyMessageException e, String sender, int senderDeviceId) {
+ public ProtocolLegacyMessageException(
+ LegacyMessageException e, String sender, int senderDeviceId) {
super(e, sender, senderDeviceId);
}
- ProtocolLegacyMessageException(LegacyMessageException e, UnidentifiedSenderMessageContent content) {
+ ProtocolLegacyMessageException(
+ LegacyMessageException e, UnidentifiedSenderMessageContent content) {
super(e, content);
}
}
diff --git a/java/client/src/main/java/org/signal/libsignal/metadata/ProtocolNoSessionException.java b/java/client/src/main/java/org/signal/libsignal/metadata/ProtocolNoSessionException.java
index 7552f52ff9..ddd04fddc4 100644
--- a/java/client/src/main/java/org/signal/libsignal/metadata/ProtocolNoSessionException.java
+++ b/java/client/src/main/java/org/signal/libsignal/metadata/ProtocolNoSessionException.java
@@ -1,3 +1,8 @@
+//
+// Copyright 2023 Signal Messenger, LLC.
+// SPDX-License-Identifier: AGPL-3.0-only
+//
+
package org.signal.libsignal.metadata;
import org.signal.libsignal.metadata.protocol.UnidentifiedSenderMessageContent;
diff --git a/java/client/src/main/java/org/signal/libsignal/metadata/ProtocolUntrustedIdentityException.java b/java/client/src/main/java/org/signal/libsignal/metadata/ProtocolUntrustedIdentityException.java
index 6f4fa878b4..1c87f0ec9e 100644
--- a/java/client/src/main/java/org/signal/libsignal/metadata/ProtocolUntrustedIdentityException.java
+++ b/java/client/src/main/java/org/signal/libsignal/metadata/ProtocolUntrustedIdentityException.java
@@ -1,14 +1,21 @@
+//
+// Copyright 2023 Signal Messenger, LLC.
+// SPDX-License-Identifier: AGPL-3.0-only
+//
+
package org.signal.libsignal.metadata;
import org.signal.libsignal.metadata.protocol.UnidentifiedSenderMessageContent;
import org.signal.libsignal.protocol.UntrustedIdentityException;
public class ProtocolUntrustedIdentityException extends ProtocolException {
- public ProtocolUntrustedIdentityException(UntrustedIdentityException e, String sender, int senderDevice) {
+ public ProtocolUntrustedIdentityException(
+ UntrustedIdentityException e, String sender, int senderDevice) {
super(e, sender, senderDevice);
}
- ProtocolUntrustedIdentityException(UntrustedIdentityException e, UnidentifiedSenderMessageContent content) {
+ ProtocolUntrustedIdentityException(
+ UntrustedIdentityException e, UnidentifiedSenderMessageContent content) {
super(e, content);
}
}
diff --git a/java/client/src/main/java/org/signal/libsignal/metadata/SealedSessionCipher.java b/java/client/src/main/java/org/signal/libsignal/metadata/SealedSessionCipher.java
index 489f94aa57..dfdc205043 100644
--- a/java/client/src/main/java/org/signal/libsignal/metadata/SealedSessionCipher.java
+++ b/java/client/src/main/java/org/signal/libsignal/metadata/SealedSessionCipher.java
@@ -1,14 +1,22 @@
+//
+// Copyright 2023 Signal Messenger, LLC.
+// SPDX-License-Identifier: AGPL-3.0-only
+//
+
package org.signal.libsignal.metadata;
+import java.time.Instant;
+import java.util.List;
+import java.util.Optional;
+import java.util.UUID;
+import org.signal.libsignal.internal.Native;
+import org.signal.libsignal.internal.NativeHandleGuard;
import org.signal.libsignal.metadata.certificate.CertificateValidator;
-import org.signal.libsignal.metadata.certificate.InvalidCertificateException;
import org.signal.libsignal.metadata.certificate.SenderCertificate;
import org.signal.libsignal.metadata.protocol.UnidentifiedSenderMessageContent;
import org.signal.libsignal.protocol.DuplicateMessageException;
-import org.signal.libsignal.protocol.IdentityKeyPair;
import org.signal.libsignal.protocol.InvalidKeyException;
import org.signal.libsignal.protocol.InvalidKeyIdException;
-import org.signal.libsignal.protocol.InvalidMacException;
import org.signal.libsignal.protocol.InvalidMessageException;
import org.signal.libsignal.protocol.InvalidRegistrationIdException;
import org.signal.libsignal.protocol.InvalidVersionException;
@@ -20,79 +28,72 @@
import org.signal.libsignal.protocol.UntrustedIdentityException;
import org.signal.libsignal.protocol.groups.GroupCipher;
import org.signal.libsignal.protocol.message.CiphertextMessage;
-import org.signal.libsignal.protocol.message.PlaintextContent;
import org.signal.libsignal.protocol.message.PreKeySignalMessage;
-import org.signal.libsignal.protocol.message.SenderKeyMessage;
import org.signal.libsignal.protocol.message.SignalMessage;
import org.signal.libsignal.protocol.state.SessionRecord;
import org.signal.libsignal.protocol.state.SignalProtocolStore;
-import org.signal.libsignal.internal.Native;
-import org.signal.libsignal.internal.NativeHandleGuard;
-
-import java.util.List;
-import java.util.Optional;
-import java.util.UUID;
-
public class SealedSessionCipher {
private static final String TAG = SealedSessionCipher.class.getSimpleName();
private final SignalProtocolStore signalProtocolStore;
- private final String localE164Address;
- private final String localUuidAddress;
- private final int localDeviceId;
+ private final String localE164Address;
+ private final String localUuidAddress;
+ private final int localDeviceId;
- public SealedSessionCipher(SignalProtocolStore signalProtocolStore,
- UUID localUuid,
- String localE164Address,
- int localDeviceId)
- {
+ public SealedSessionCipher(
+ SignalProtocolStore signalProtocolStore,
+ UUID localUuid,
+ String localE164Address,
+ int localDeviceId) {
this.signalProtocolStore = signalProtocolStore;
- this.localUuidAddress = localUuid.toString();
- this.localE164Address = localE164Address;
- this.localDeviceId = localDeviceId;
+ this.localUuidAddress = localUuid.toString();
+ this.localE164Address = localE164Address;
+ this.localDeviceId = localDeviceId;
}
- public byte[] encrypt(SignalProtocolAddress destinationAddress, SenderCertificate senderCertificate, byte[] paddedPlaintext)
- throws InvalidKeyException, UntrustedIdentityException
- {
+ public byte[] encrypt(
+ SignalProtocolAddress destinationAddress,
+ SenderCertificate senderCertificate,
+ byte[] paddedPlaintext)
+ throws InvalidKeyException, UntrustedIdentityException {
try (NativeHandleGuard addressGuard = new NativeHandleGuard(destinationAddress)) {
- CiphertextMessage message = Native.SessionCipher_EncryptMessage(
- paddedPlaintext,
- addressGuard.nativeHandle(),
- this.signalProtocolStore,
- this.signalProtocolStore);
- UnidentifiedSenderMessageContent content = new UnidentifiedSenderMessageContent(
- message,
- senderCertificate,
- UnidentifiedSenderMessageContent.CONTENT_HINT_DEFAULT,
- Optional.empty());
+ CiphertextMessage message =
+ Native.SessionCipher_EncryptMessage(
+ paddedPlaintext,
+ addressGuard.nativeHandle(),
+ this.signalProtocolStore,
+ this.signalProtocolStore,
+ Instant.now().toEpochMilli());
+ UnidentifiedSenderMessageContent content =
+ new UnidentifiedSenderMessageContent(
+ message,
+ senderCertificate,
+ UnidentifiedSenderMessageContent.CONTENT_HINT_DEFAULT,
+ Optional.empty());
return encrypt(destinationAddress, content);
}
}
- public byte[] encrypt(SignalProtocolAddress destinationAddress, UnidentifiedSenderMessageContent content)
- throws InvalidKeyException, UntrustedIdentityException
- {
- try (
- NativeHandleGuard addressGuard = new NativeHandleGuard(destinationAddress);
- NativeHandleGuard contentGuard = new NativeHandleGuard(content);
- ) {
+ public byte[] encrypt(
+ SignalProtocolAddress destinationAddress, UnidentifiedSenderMessageContent content)
+ throws InvalidKeyException, UntrustedIdentityException {
+ try (NativeHandleGuard addressGuard = new NativeHandleGuard(destinationAddress);
+ NativeHandleGuard contentGuard = new NativeHandleGuard(content)) {
return Native.SealedSessionCipher_Encrypt(
- addressGuard.nativeHandle(),
- contentGuard.nativeHandle(),
- this.signalProtocolStore);
+ addressGuard.nativeHandle(), contentGuard.nativeHandle(), this.signalProtocolStore);
}
}
- public byte[] multiRecipientEncrypt(List recipients, UnidentifiedSenderMessageContent content)
- throws
- InvalidKeyException, InvalidRegistrationIdException, NoSessionException,
- UntrustedIdentityException
- {
+ public byte[] multiRecipientEncrypt(
+ List recipients, UnidentifiedSenderMessageContent content)
+ throws InvalidKeyException,
+ InvalidRegistrationIdException,
+ NoSessionException,
+ UntrustedIdentityException {
List recipientSessions =
- this.signalProtocolStore.loadExistingSessions(recipients);
+ this.signalProtocolStore.loadExistingSessions(recipients);
// Unsafely access the native handles for the recipients and sessions,
// because try-with-resources syntax doesn't support a List of resources.
@@ -111,11 +112,12 @@ public byte[] multiRecipientEncrypt(List recipients, Unid
}
try (NativeHandleGuard contentGuard = new NativeHandleGuard(content)) {
- byte[] result = Native.SealedSessionCipher_MultiRecipientEncrypt(
- recipientHandles,
- recipientSessionHandles,
- contentGuard.nativeHandle(),
- this.signalProtocolStore);
+ byte[] result =
+ Native.SealedSessionCipher_MultiRecipientEncrypt(
+ recipientHandles,
+ recipientSessionHandles,
+ contentGuard.nativeHandle(),
+ this.signalProtocolStore);
// Manually keep the lists of recipients and sessions from being garbage collected
// while we're using their native handles.
Native.keepAlive(recipients);
@@ -141,37 +143,45 @@ static byte[] multiRecipientMessageForSingleRecipient(byte[] message) {
}
public DecryptionResult decrypt(CertificateValidator validator, byte[] ciphertext, long timestamp)
- throws
- InvalidMetadataMessageException, InvalidMetadataVersionException,
- ProtocolInvalidMessageException, ProtocolInvalidKeyException,
- ProtocolNoSessionException, ProtocolLegacyMessageException,
- ProtocolInvalidVersionException, ProtocolDuplicateMessageException,
- ProtocolInvalidKeyIdException, ProtocolUntrustedIdentityException,
- SelfSendException
- {
+ throws InvalidMetadataMessageException,
+ InvalidMetadataVersionException,
+ ProtocolInvalidMessageException,
+ ProtocolInvalidKeyException,
+ ProtocolNoSessionException,
+ ProtocolLegacyMessageException,
+ ProtocolInvalidVersionException,
+ ProtocolDuplicateMessageException,
+ ProtocolInvalidKeyIdException,
+ ProtocolUntrustedIdentityException,
+ SelfSendException {
UnidentifiedSenderMessageContent content;
try {
- content = new UnidentifiedSenderMessageContent(
- Native.SealedSessionCipher_DecryptToUsmc(ciphertext, this.signalProtocolStore));
+ content =
+ new UnidentifiedSenderMessageContent(
+ Native.SealedSessionCipher_DecryptToUsmc(ciphertext, this.signalProtocolStore));
validator.validate(content.getSenderCertificate(), timestamp);
} catch (Exception e) {
throw new InvalidMetadataMessageException(e);
}
- boolean isLocalE164 = localE164Address != null && localE164Address.equals(content.getSenderCertificate().getSenderE164().orElse(null));
+ boolean isLocalE164 =
+ localE164Address != null
+ && localE164Address.equals(content.getSenderCertificate().getSenderE164().orElse(null));
boolean isLocalUuid = localUuidAddress.equals(content.getSenderCertificate().getSenderUuid());
- if ((isLocalE164 || isLocalUuid) && content.getSenderCertificate().getSenderDeviceId() == localDeviceId) {
+ if ((isLocalE164 || isLocalUuid)
+ && content.getSenderCertificate().getSenderDeviceId() == localDeviceId) {
throw new SelfSendException();
}
try {
- return new DecryptionResult(content.getSenderCertificate().getSenderUuid(),
- content.getSenderCertificate().getSenderE164(),
- content.getSenderCertificate().getSenderDeviceId(),
- content.getType(),
- content.getGroupId(),
- decrypt(content));
+ return new DecryptionResult(
+ content.getSenderCertificate().getSenderUuid(),
+ content.getSenderCertificate().getSenderE164(),
+ content.getSenderCertificate().getSenderDeviceId(),
+ content.getType(),
+ content.getGroupId(),
+ decrypt(content));
} catch (InvalidMessageException e) {
throw new ProtocolInvalidMessageException(e, content);
} catch (InvalidKeyException e) {
@@ -200,15 +210,26 @@ public int getRemoteRegistrationId(SignalProtocolAddress remoteAddress) {
}
private byte[] decrypt(UnidentifiedSenderMessageContent message)
- throws InvalidVersionException, InvalidMessageException, InvalidKeyException, DuplicateMessageException, InvalidKeyIdException, UntrustedIdentityException, LegacyMessageException, NoSessionException
- {
- SignalProtocolAddress sender = new SignalProtocolAddress(message.getSenderCertificate().getSenderUuid(), message.getSenderCertificate().getSenderDeviceId());
+ throws InvalidVersionException,
+ InvalidMessageException,
+ InvalidKeyException,
+ DuplicateMessageException,
+ InvalidKeyIdException,
+ UntrustedIdentityException,
+ LegacyMessageException,
+ NoSessionException {
+ SignalProtocolAddress sender =
+ new SignalProtocolAddress(
+ message.getSenderCertificate().getSenderUuid(),
+ message.getSenderCertificate().getSenderDeviceId());
switch (message.getType()) {
case CiphertextMessage.WHISPER_TYPE:
- return new SessionCipher(signalProtocolStore, sender).decrypt(new SignalMessage(message.getContent()));
- case CiphertextMessage.PREKEY_TYPE:
- return new SessionCipher(signalProtocolStore, sender).decrypt(new PreKeySignalMessage(message.getContent()));
+ return new SessionCipher(signalProtocolStore, sender)
+ .decrypt(new SignalMessage(message.getContent()));
+ case CiphertextMessage.PREKEY_TYPE:
+ return new SessionCipher(signalProtocolStore, sender)
+ .decrypt(new PreKeySignalMessage(message.getContent()));
case CiphertextMessage.SENDERKEY_TYPE:
return new GroupCipher(signalProtocolStore, sender).decrypt(message.getContent());
case CiphertextMessage.PLAINTEXT_CONTENT_TYPE:
@@ -219,19 +240,25 @@ private byte[] decrypt(UnidentifiedSenderMessageContent message)
}
public static class DecryptionResult {
- private final String senderUuid;
+ private final String senderUuid;
private final Optional senderE164;
- private final int deviceId;
- private final int messageType;
+ private final int deviceId;
+ private final int messageType;
private final Optional groupId;
- private final byte[] paddedMessage;
+ private final byte[] paddedMessage;
- private DecryptionResult(String senderUuid, Optional senderE164, int deviceId, int messageType, Optional groupId, byte[] paddedMessage) {
- this.senderUuid = senderUuid;
- this.senderE164 = senderE164;
- this.deviceId = deviceId;
- this.messageType = messageType;
- this.groupId = groupId;
+ private DecryptionResult(
+ String senderUuid,
+ Optional senderE164,
+ int deviceId,
+ int messageType,
+ Optional groupId,
+ byte[] paddedMessage) {
+ this.senderUuid = senderUuid;
+ this.senderE164 = senderE164;
+ this.deviceId = deviceId;
+ this.messageType = messageType;
+ this.groupId = groupId;
this.paddedMessage = paddedMessage;
}
@@ -242,7 +269,7 @@ public String getSenderUuid() {
/**
* Returns an ACI if the sender is a valid UUID, {@code null} otherwise.
*
- * In a future release DecryptionResult will only support ACIs.
+ * In a future release DecryptionResult will only support ACIs.
*/
public ServiceId.Aci getSenderAci() {
try {
diff --git a/java/client/src/main/java/org/signal/libsignal/metadata/SelfSendException.java b/java/client/src/main/java/org/signal/libsignal/metadata/SelfSendException.java
index c3c0c3051a..3175934188 100644
--- a/java/client/src/main/java/org/signal/libsignal/metadata/SelfSendException.java
+++ b/java/client/src/main/java/org/signal/libsignal/metadata/SelfSendException.java
@@ -1,5 +1,8 @@
-package org.signal.libsignal.metadata;
+//
+// Copyright 2023 Signal Messenger, LLC.
+// SPDX-License-Identifier: AGPL-3.0-only
+//
+package org.signal.libsignal.metadata;
-public class SelfSendException extends Exception {
-}
+public class SelfSendException extends Exception {}
diff --git a/java/client/src/main/java/org/signal/libsignal/metadata/certificate/CertificateValidator.java b/java/client/src/main/java/org/signal/libsignal/metadata/certificate/CertificateValidator.java
index db0d3ccd8d..dc857277ec 100644
--- a/java/client/src/main/java/org/signal/libsignal/metadata/certificate/CertificateValidator.java
+++ b/java/client/src/main/java/org/signal/libsignal/metadata/certificate/CertificateValidator.java
@@ -1,11 +1,15 @@
+//
+// Copyright 2023 Signal Messenger, LLC.
+// SPDX-License-Identifier: AGPL-3.0-only
+//
+
package org.signal.libsignal.metadata.certificate;
import org.signal.libsignal.internal.Native;
import org.signal.libsignal.internal.NativeHandleGuard;
-
+import org.signal.libsignal.protocol.InvalidKeyException;
import org.signal.libsignal.protocol.ecc.Curve;
import org.signal.libsignal.protocol.ecc.ECPublicKey;
-import org.signal.libsignal.protocol.InvalidKeyException;
public class CertificateValidator {
private final ECPublicKey trustRoot;
@@ -18,14 +22,14 @@ public ECPublicKey getTrustRoot() {
return this.trustRoot;
}
- public void validate(SenderCertificate certificate, long validationTime) throws InvalidCertificateException {
- try (
- NativeHandleGuard certificateGuard = new NativeHandleGuard(certificate);
- NativeHandleGuard trustRootGuard = new NativeHandleGuard(trustRoot);
- ) {
- if (!Native.SenderCertificate_Validate(certificateGuard.nativeHandle(), trustRootGuard.nativeHandle(), validationTime)) {
- throw new InvalidCertificateException("Validation failed");
- }
+ public void validate(SenderCertificate certificate, long validationTime)
+ throws InvalidCertificateException {
+ try (NativeHandleGuard certificateGuard = new NativeHandleGuard(certificate);
+ NativeHandleGuard trustRootGuard = new NativeHandleGuard(trustRoot)) {
+ if (!Native.SenderCertificate_Validate(
+ certificateGuard.nativeHandle(), trustRootGuard.nativeHandle(), validationTime)) {
+ throw new InvalidCertificateException("Validation failed");
+ }
} catch (Exception e) {
throw new InvalidCertificateException(e);
}
@@ -34,7 +38,8 @@ public void validate(SenderCertificate certificate, long validationTime) throws
// VisibleForTesting
void validate(ServerCertificate certificate) throws InvalidCertificateException {
try {
- if (!Curve.verifySignature(trustRoot, certificate.getCertificate(), certificate.getSignature())) {
+ if (!Curve.verifySignature(
+ trustRoot, certificate.getCertificate(), certificate.getSignature())) {
throw new InvalidCertificateException("Signature failed");
}
} catch (InvalidKeyException e) {
diff --git a/java/client/src/main/java/org/signal/libsignal/metadata/certificate/InvalidCertificateException.java b/java/client/src/main/java/org/signal/libsignal/metadata/certificate/InvalidCertificateException.java
index f2ec14634f..5816f56cbd 100644
--- a/java/client/src/main/java/org/signal/libsignal/metadata/certificate/InvalidCertificateException.java
+++ b/java/client/src/main/java/org/signal/libsignal/metadata/certificate/InvalidCertificateException.java
@@ -1,5 +1,9 @@
-package org.signal.libsignal.metadata.certificate;
+//
+// Copyright 2023 Signal Messenger, LLC.
+// SPDX-License-Identifier: AGPL-3.0-only
+//
+package org.signal.libsignal.metadata.certificate;
public class InvalidCertificateException extends Exception {
public InvalidCertificateException(String s) {
diff --git a/java/client/src/main/java/org/signal/libsignal/metadata/certificate/SenderCertificate.java b/java/client/src/main/java/org/signal/libsignal/metadata/certificate/SenderCertificate.java
index 9310eac10f..6b28fc9896 100644
--- a/java/client/src/main/java/org/signal/libsignal/metadata/certificate/SenderCertificate.java
+++ b/java/client/src/main/java/org/signal/libsignal/metadata/certificate/SenderCertificate.java
@@ -1,21 +1,23 @@
+//
+// Copyright 2023 Signal Messenger, LLC.
+// SPDX-License-Identifier: AGPL-3.0-only
+//
+
package org.signal.libsignal.metadata.certificate;
+import java.util.Optional;
import org.signal.libsignal.internal.Native;
import org.signal.libsignal.internal.NativeHandleGuard;
-
-import org.signal.libsignal.protocol.ecc.ECPublicKey;
-import org.signal.libsignal.protocol.InvalidKeyException;
-import org.signal.libsignal.protocol.InvalidMessageException;
import org.signal.libsignal.protocol.ServiceId;
-
-import java.util.Optional;
+import org.signal.libsignal.protocol.ecc.ECPublicKey;
public class SenderCertificate implements NativeHandleGuard.Owner {
private final long unsafeHandle;
- @Override @SuppressWarnings("deprecation")
+ @Override
+ @SuppressWarnings("deprecation")
protected void finalize() {
- Native.SenderCertificate_Destroy(this.unsafeHandle);
+ Native.SenderCertificate_Destroy(this.unsafeHandle);
}
public long unsafeNativeHandleWithoutGuard() {
@@ -36,7 +38,8 @@ public SenderCertificate(long unsafeHandle) {
public ServerCertificate getSigner() {
try (NativeHandleGuard guard = new NativeHandleGuard(this)) {
- return new ServerCertificate(Native.SenderCertificate_GetServerCertificate(guard.nativeHandle()));
+ return new ServerCertificate(
+ Native.SenderCertificate_GetServerCertificate(guard.nativeHandle()));
}
}
@@ -71,7 +74,7 @@ public String getSender() {
/**
* Returns an ACI if the sender is a valid UUID, {@code null} otherwise.
*
- * In a future release SenderCertificate will only support ACIs.
+ *
In a future release SenderCertificate will only support ACIs.
*/
public ServiceId.Aci getSenderAci() {
try {
diff --git a/java/client/src/main/java/org/signal/libsignal/metadata/certificate/ServerCertificate.java b/java/client/src/main/java/org/signal/libsignal/metadata/certificate/ServerCertificate.java
index a6e00a061e..1100678361 100644
--- a/java/client/src/main/java/org/signal/libsignal/metadata/certificate/ServerCertificate.java
+++ b/java/client/src/main/java/org/signal/libsignal/metadata/certificate/ServerCertificate.java
@@ -1,19 +1,21 @@
+//
+// Copyright 2023 Signal Messenger, LLC.
+// SPDX-License-Identifier: AGPL-3.0-only
+//
+
package org.signal.libsignal.metadata.certificate;
import org.signal.libsignal.internal.Native;
import org.signal.libsignal.internal.NativeHandleGuard;
-
-import org.signal.libsignal.protocol.ecc.ECPublicKey;
-import org.signal.libsignal.protocol.InvalidKeyException;
-import org.signal.libsignal.protocol.InvalidMessageException;
import org.signal.libsignal.protocol.ecc.ECPublicKey;
public class ServerCertificate implements NativeHandleGuard.Owner {
private final long unsafeHandle;
- @Override @SuppressWarnings("deprecation")
+ @Override
+ @SuppressWarnings("deprecation")
protected void finalize() {
- Native.ServerCertificate_Destroy(this.unsafeHandle);
+ Native.ServerCertificate_Destroy(this.unsafeHandle);
}
public ServerCertificate(long unsafeHandle) {
diff --git a/java/client/src/main/java/org/signal/libsignal/metadata/protocol/UnidentifiedSenderMessageContent.java b/java/client/src/main/java/org/signal/libsignal/metadata/protocol/UnidentifiedSenderMessageContent.java
index 259db97f6a..263dbe7b40 100644
--- a/java/client/src/main/java/org/signal/libsignal/metadata/protocol/UnidentifiedSenderMessageContent.java
+++ b/java/client/src/main/java/org/signal/libsignal/metadata/protocol/UnidentifiedSenderMessageContent.java
@@ -1,26 +1,30 @@
+//
+// Copyright 2023 Signal Messenger, LLC.
+// SPDX-License-Identifier: AGPL-3.0-only
+//
+
package org.signal.libsignal.metadata.protocol;
+import java.util.Optional;
import org.signal.libsignal.internal.Native;
import org.signal.libsignal.internal.NativeHandleGuard;
-
import org.signal.libsignal.metadata.InvalidMetadataMessageException;
import org.signal.libsignal.metadata.certificate.InvalidCertificateException;
import org.signal.libsignal.metadata.certificate.SenderCertificate;
import org.signal.libsignal.protocol.message.CiphertextMessage;
-import java.util.Optional;
-
public class UnidentifiedSenderMessageContent implements NativeHandleGuard.Owner {
// Must be kept in sync with sealed_sender.proto.
- public static final int CONTENT_HINT_DEFAULT = 0;
+ public static final int CONTENT_HINT_DEFAULT = 0;
public static final int CONTENT_HINT_RESENDABLE = 1;
- public static final int CONTENT_HINT_IMPLICIT = 2;
+ public static final int CONTENT_HINT_IMPLICIT = 2;
private final long unsafeHandle;
- @Override @SuppressWarnings("deprecation")
+ @Override
+ @SuppressWarnings("deprecation")
protected void finalize() {
- Native.UnidentifiedSenderMessageContent_Destroy(this.unsafeHandle);
+ Native.UnidentifiedSenderMessageContent_Destroy(this.unsafeHandle);
}
public UnidentifiedSenderMessageContent(long nativeHandle) {
@@ -31,7 +35,8 @@ public long unsafeNativeHandleWithoutGuard() {
return this.unsafeHandle;
}
- public UnidentifiedSenderMessageContent(byte[] serialized) throws InvalidMetadataMessageException, InvalidCertificateException {
+ public UnidentifiedSenderMessageContent(byte[] serialized)
+ throws InvalidMetadataMessageException, InvalidCertificateException {
try {
this.unsafeHandle = Native.UnidentifiedSenderMessageContent_Deserialize(serialized);
} catch (Exception e) {
@@ -39,16 +44,15 @@ public UnidentifiedSenderMessageContent(byte[] serialized) throws InvalidMetadat
}
}
- public UnidentifiedSenderMessageContent(CiphertextMessage message,
- SenderCertificate senderCertificate,
- int contentHint,
- Optional groupId) {
+ public UnidentifiedSenderMessageContent(
+ CiphertextMessage message,
+ SenderCertificate senderCertificate,
+ int contentHint,
+ Optional groupId) {
try (NativeHandleGuard certificateGuard = new NativeHandleGuard(senderCertificate)) {
- this.unsafeHandle = Native.UnidentifiedSenderMessageContent_New(
- message,
- certificateGuard.nativeHandle(),
- contentHint,
- groupId.orElse(null));
+ this.unsafeHandle =
+ Native.UnidentifiedSenderMessageContent_New(
+ message, certificateGuard.nativeHandle(), contentHint, groupId.orElse(null));
}
}
@@ -60,7 +64,8 @@ public int getType() {
public SenderCertificate getSenderCertificate() {
try (NativeHandleGuard guard = new NativeHandleGuard(this)) {
- return new SenderCertificate(Native.UnidentifiedSenderMessageContent_GetSenderCert(guard.nativeHandle()));
+ return new SenderCertificate(
+ Native.UnidentifiedSenderMessageContent_GetSenderCert(guard.nativeHandle()));
}
}
@@ -84,7 +89,8 @@ public int getContentHint() {
public Optional getGroupId() {
try (NativeHandleGuard guard = new NativeHandleGuard(this)) {
- return Optional.ofNullable(Native.UnidentifiedSenderMessageContent_GetGroupId(guard.nativeHandle()));
+ return Optional.ofNullable(
+ Native.UnidentifiedSenderMessageContent_GetGroupId(guard.nativeHandle()));
}
}
}
diff --git a/java/client/src/main/java/org/signal/libsignal/sgxsession/SgxClient.java b/java/client/src/main/java/org/signal/libsignal/sgxsession/SgxClient.java
index ed66e9abd2..c0fa60e15a 100644
--- a/java/client/src/main/java/org/signal/libsignal/sgxsession/SgxClient.java
+++ b/java/client/src/main/java/org/signal/libsignal/sgxsession/SgxClient.java
@@ -11,20 +11,21 @@
/**
* SgxClient provides bindings to interact with a Signal SGX service.
*
- * Interaction with the service is done over a websocket, which is handled by the client. Once the websocket
- * has been initiated, the client establishes a connection in the following manner:
+ * Interaction with the service is done over a websocket, which is handled by the client. Once
+ * the websocket has been initiated, the client establishes a connection in the following manner:
*
*
- * connect to the service websocket, read service attestation
- * instantiate SgxClient with the attestation message
- * send SgxClient.initialRequest()
- * receive a response and pass to SgxClient.completeHandshake()
+ * connect to the service websocket, read service attestation
+ * instantiate SgxClient with the attestation message
+ * send SgxClient.initialRequest()
+ * receive a response and pass to SgxClient.completeHandshake()
*
*
- * After a connection has been established, a client may send or receive messages. To send a message, they
- * formulate the plaintext, then pass it to SgxClient.establishedSend() to get the ciphertext message
- * to pass along. When a message is received (as ciphertext), it is passed to SgxClient.establishedRecv(),
- * which decrypts and verifies it, passing the plaintext back to the client for processing.
+ * After a connection has been established, a client may send or receive messages. To send a
+ * message, they formulate the plaintext, then pass it to SgxClient.establishedSend() to get the
+ * ciphertext message to pass along. When a message is received (as ciphertext), it is passed to
+ * SgxClient.establishedRecv(), which decrypts and verifies it, passing the plaintext back to the
+ * client for processing.
*/
public class SgxClient implements NativeHandleGuard.Owner {
private final long unsafeHandle;
@@ -33,7 +34,8 @@ protected SgxClient(final long unsafeHandle) {
this.unsafeHandle = unsafeHandle;
}
- @Override @SuppressWarnings("deprecation")
+ @Override
+ @SuppressWarnings("deprecation")
protected void finalize() {
Native.SgxClientState_Destroy(this.unsafeHandle);
}
@@ -49,7 +51,10 @@ public byte[] initialRequest() {
}
}
- /** Called by client upon receipt of first non-attestation message from service, to complete handshake. */
+ /**
+ * Called by client upon receipt of first non-attestation message from service, to complete
+ * handshake.
+ */
public void completeHandshake(byte[] handshakeResponse) throws SgxCommunicationFailureException {
try (NativeHandleGuard guard = new NativeHandleGuard(this)) {
Native.SgxClientState_CompleteHandshake(guard.nativeHandle(), handshakeResponse);
diff --git a/java/client/src/main/java/org/signal/libsignal/sgxsession/SgxCommunicationFailureException.java b/java/client/src/main/java/org/signal/libsignal/sgxsession/SgxCommunicationFailureException.java
index 59eac61f49..a9a0ad2750 100644
--- a/java/client/src/main/java/org/signal/libsignal/sgxsession/SgxCommunicationFailureException.java
+++ b/java/client/src/main/java/org/signal/libsignal/sgxsession/SgxCommunicationFailureException.java
@@ -6,6 +6,11 @@
package org.signal.libsignal.sgxsession;
public class SgxCommunicationFailureException extends Exception {
- public SgxCommunicationFailureException(String msg) { super(msg); }
- public SgxCommunicationFailureException(Throwable t) { super(t); }
+ public SgxCommunicationFailureException(String msg) {
+ super(msg);
+ }
+
+ public SgxCommunicationFailureException(Throwable t) {
+ super(t);
+ }
}
diff --git a/java/client/src/main/java/org/signal/libsignal/svr2/Pin.java b/java/client/src/main/java/org/signal/libsignal/svr2/Pin.java
index 125df787b0..c445ed6a06 100644
--- a/java/client/src/main/java/org/signal/libsignal/svr2/Pin.java
+++ b/java/client/src/main/java/org/signal/libsignal/svr2/Pin.java
@@ -9,41 +9,40 @@
/**
* Supports operations on pins for Secure Value Recovery
- *
- * This class provides hashing pins for local verification and for use with the remote SVR service. In either case, all
- * pins are UTF-8 encoded bytes that must be normalized *before* being provided to this class. Normalizing a string pin
- * requires the following steps:
*
- *
The string should be trimmed for leading and trailing whitespace.
- * If the whole string consists of digits, then non-arabic digits must be replaced with their
- * arabic 0-9 equivalents.
- * The string must then be NKFD normalized
+ * This class provides hashing pins for local verification and for use with the remote SVR
+ * service. In either case, all pins are UTF-8 encoded bytes that must be normalized *before* being
+ * provided to this class. Normalizing a string pin requires the following steps:
+ *
The string should be trimmed for leading and trailing whitespace.
+ * If the whole string consists of digits, then non-arabic digits must be replaced with their
+ * arabic 0-9 equivalents.
+ * The string must then be NKFD
+ * normalized
*/
public class Pin {
- private Pin() {
- }
+ private Pin() {}
- /**
- * Create an encoded password hash string.
- *
- * This creates a hashed pin that should be used for local pin verification only.
- *
- * @param pin A normalized, UTF-8 encoded byte representation of the pin
- * @return A hashed pin string that can be verified later
- */
- public static String localHash(final byte[] pin) {
- return Native.Pin_LocalHash(pin);
- }
+ /**
+ * Create an encoded password hash string.
+ *
+ * This creates a hashed pin that should be used for local pin verification only.
+ *
+ * @param pin A normalized, UTF-8 encoded byte representation of the pin
+ * @return A hashed pin string that can be verified later
+ */
+ public static String localHash(final byte[] pin) {
+ return Native.Pin_LocalHash(pin);
+ }
- /**
- * Verify an encoded password hash against a pin
- *
- * @param encodedHash An encoded string of the hash, as returned by {@link Pin#localHash}
- * @param pin A normalized, UTF-8 encoded byte representation of the pin to verify
- * @return true if the pin matches the hash, false otherwise
- */
- public static boolean verifyLocalHash(final String encodedHash, final byte[] pin) {
- return Native.Pin_VerifyLocalHash(encodedHash, pin);
- }
+ /**
+ * Verify an encoded password hash against a pin
+ *
+ * @param encodedHash An encoded string of the hash, as returned by {@link Pin#localHash}
+ * @param pin A normalized, UTF-8 encoded byte representation of the pin to verify
+ * @return true if the pin matches the hash, false otherwise
+ */
+ public static boolean verifyLocalHash(final String encodedHash, final byte[] pin) {
+ return Native.Pin_VerifyLocalHash(encodedHash, pin);
+ }
}
diff --git a/java/client/src/main/java/org/signal/libsignal/svr2/PinHash.java b/java/client/src/main/java/org/signal/libsignal/svr2/PinHash.java
index b3e98a1af6..45a7564dad 100644
--- a/java/client/src/main/java/org/signal/libsignal/svr2/PinHash.java
+++ b/java/client/src/main/java/org/signal/libsignal/svr2/PinHash.java
@@ -8,70 +8,68 @@
import org.signal.libsignal.internal.Native;
import org.signal.libsignal.internal.NativeHandleGuard;
-/**
- * A hash of the pin that can be used to interact with a Secure Value Recovery service.
- */
+/** A hash of the pin that can be used to interact with a Secure Value Recovery service. */
public class PinHash implements NativeHandleGuard.Owner {
- private final long unsafeHandle;
+ private final long unsafeHandle;
- private PinHash(final long unsafeHandle) {
- this.unsafeHandle = unsafeHandle;
- }
+ private PinHash(final long unsafeHandle) {
+ this.unsafeHandle = unsafeHandle;
+ }
- @Override
- @SuppressWarnings("deprecation")
- protected void finalize() {
- Native.PinHash_Destroy(this.unsafeHandle);
- }
+ @Override
+ @SuppressWarnings("deprecation")
+ protected void finalize() {
+ Native.PinHash_Destroy(this.unsafeHandle);
+ }
- public long unsafeNativeHandleWithoutGuard() {
- return this.unsafeHandle;
- }
+ public long unsafeNativeHandleWithoutGuard() {
+ return this.unsafeHandle;
+ }
+ /**
+ * Hash a pin for use with a remote SecureValueRecovery1 service.
+ *
+ *
Note: This should be used with SVR1 only. For SVR1, the salt should be the backup id. For
+ * SVR2 clients, use {@link PinHash#svr2} which handles salt selection internally.
+ *
+ * @param normalizedPin A normalized, UTF-8 encoded byte representation of the pin
+ * @param salt A 32 byte salt
+ * @return A {@link PinHash}
+ */
+ public static PinHash svr1(final byte[] normalizedPin, final byte[] salt) {
+ return new PinHash(Native.PinHash_FromSalt(normalizedPin, salt));
+ }
- /**
- * Hash a pin for use with a remote SecureValueRecovery1 service.
- *
- * Note: This should be used with SVR1 only. For SVR1, the salt should be the backup id.
- * For SVR2 clients, use {@link PinHash#svr2} which handles salt selection internally.
- *
- * @param pin A normalized, UTF-8 encoded byte representation of the pin
- * @param salt A 32 byte salt
- * @return A {@link PinHash}
- */
- public static PinHash svr1(final byte[] normalizedPin, final byte[] salt) {
- return new PinHash(Native.PinHash_FromSalt(normalizedPin, salt));
- }
+ /**
+ * Hash a pin for use with a remote SecureValueRecovery2 service.
+ *
+ *
Note: This should be used with SVR2 only. For SVR1 clients, use {@link PinHash#svr1}
+ *
+ * @param normalizedPin A normalized, UTF-8 encoded byte representation of the pin
+ * @param username The Basic Auth username used to authenticate with SVR2
+ * @param mrenclave The mrenclave where the hashed pin will be stored
+ * @return A {@link PinHash}
+ */
+ public static PinHash svr2(
+ final byte[] normalizedPin, final String username, final byte[] mrenclave) {
+ return new PinHash(Native.PinHash_FromUsernameMrenclave(normalizedPin, username, mrenclave));
+ }
- /**
- * Hash a pin for use with a remote SecureValueRecovery2 service.
- *
- * Note: This should be used with SVR2 only. For SVR1 clients, use {@link PinHash#svr1}
- *
- * @param pin A normalized, UTF-8 encoded byte representation of the pin
- * @param username The Basic Auth username used to authenticate with SVR2
- * @param mrenclave The mrenclave where the hashed pin will be stored
- * @return A {@link PinHash}
- */
- public static PinHash svr2(final byte[] normalizedPin, final String username, final byte[] mrenclave) {
- return new PinHash(Native.PinHash_FromUsernameMrenclave(normalizedPin, username, mrenclave));
- }
+ /**
+ * A key that can be used to encrypt or decrypt values before uploading them to a secure store.
+ *
+ * @return a 32 byte encryption key
+ */
+ public byte[] encryptionKey() {
+ return Native.PinHash_EncryptionKey(unsafeHandle);
+ }
- /**
- * A key that can be used to encrypt or decrypt values before uploading them to a secure store.
- *
- * @return a 32 byte encryption key
- */
- public byte[] encryptionKey() {
- return Native.PinHash_EncryptionKey(unsafeHandle);
- }
-
- /**
- * A secret that can be used to access a value in a secure store.
- *
- * @return a 32 byte access key
- */
- public byte[] accessKey() {
- return Native.PinHash_AccessKey(unsafeHandle);
- }
+ /**
+ * A secret that can be used to access a value in a secure store.
+ *
+ * @return a 32 byte access key
+ */
+ public byte[] accessKey() {
+ return Native.PinHash_AccessKey(unsafeHandle);
+ }
}
diff --git a/java/client/src/main/java/org/signal/libsignal/svr2/Svr2Client.java b/java/client/src/main/java/org/signal/libsignal/svr2/Svr2Client.java
index 9776a93020..e96e1e756e 100644
--- a/java/client/src/main/java/org/signal/libsignal/svr2/Svr2Client.java
+++ b/java/client/src/main/java/org/signal/libsignal/svr2/Svr2Client.java
@@ -5,19 +5,21 @@
package org.signal.libsignal.svr2;
-import org.signal.libsignal.sgxsession.SgxClient;
+import java.time.Instant;
import org.signal.libsignal.attest.AttestationDataException;
import org.signal.libsignal.internal.Native;
-
-import java.time.Instant;
+import org.signal.libsignal.sgxsession.SgxClient;
/**
- * Svr2Client provides bindings to interact with Signal's v2 Secure Value Recovery service.
+ * Svr2Client provides bindings to interact with Signal's v2 Secure Value Recovery service.
+ *
*
- * {@inheritDoc}
+ *
+ *
{@inheritDoc}
*/
public class Svr2Client extends SgxClient {
- public Svr2Client(byte[] mrenclave, byte[] attestationMsg, Instant currentInstant) throws AttestationDataException {
- super(Native.Svr2Client_New(mrenclave, attestationMsg, currentInstant.toEpochMilli()));
- }
+ public Svr2Client(byte[] mrenclave, byte[] attestationMsg, Instant currentInstant)
+ throws AttestationDataException {
+ super(Native.Svr2Client_New(mrenclave, attestationMsg, currentInstant.toEpochMilli()));
+ }
}
diff --git a/java/client/src/test/java/org/signal/libsignal/crypto/Aes256Ctr32Tests.java b/java/client/src/test/java/org/signal/libsignal/crypto/Aes256Ctr32Tests.java
index 50bddabd98..af210f0277 100644
--- a/java/client/src/test/java/org/signal/libsignal/crypto/Aes256Ctr32Tests.java
+++ b/java/client/src/test/java/org/signal/libsignal/crypto/Aes256Ctr32Tests.java
@@ -14,19 +14,16 @@ public class Aes256Ctr32Tests extends TestCase {
public void testAesCtr32Kats() throws Exception {
testAesCtr32Kat(
- "603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4",
- "fd4c14729f5004ba49d832ad7be87c18f4fafb58962b9a43c3be41713ded93dbf854ac4ca26285b7f76e04b8f8d4e7d9f7548f9b465c8f713c106e9f63f54305331a4983a2f4b718de29fa794da12eee808642faeff8271a0ea28e3cc80eeb65a8eb61f69d8ba97f6bf9054453f55efb8f9422081f1620fe44acf99e81122f73d3f921d5e3391654e9947904984375b725fdfba895c5cde3d225d7be3a213c3965178a7dc1e3b552ec7b2ffd9c77ebcc243c4500dfdfbe3b7554aa427c01305bec48d71af27c5911d1e649c620d22cf5f3a5aeb9468651da796f369522faf91efabf0febd33fca41c9534606a4ea0199b904b243ba9cb8f37a792df02efab8f0e2e0cf1d579daba042cfe4c9430ad4eda786052fcf15e7acfa2736aab4590f73675fa1805fe23892c63e0cd01d006935a6e3f8e105a754803d00d9857e49636ab034164156856d58a244ead475300d93b31e44b5be3bbf6994edb895804b4f1bad43ecfe08b4e130148b669fe620e4f73034fc3e748237870bec3b1f517684654d1d6bc074ddf7b759a2405f78ed84d1006d25af9bbc12d6c632f5d543da0cbe9ea866b2c92126009c27ad59394b76337de246b50895317e2e345df3629a5f6227f64522866e7a39121ccc552e3dabc989dce066dea355f788c5d92ada099917a297cfefa867ce37656fac6a50798c10b394d5ba54f85cf0f7ef1eeddfca1e53e93f1349888cc745190c196f84ecf0721287cc592d406f0a6cc5a55294bf7aa3b35f6cefc61cab794b12444312b5e50ec0712e221cc95e9e26e9c3d000881e792afcb58641b1a94613d64ec72f3db9ab65ba07a4f05b7e9ee7b335d86a06fcbdb8cbd695aeef53964a965ffe4c6d7b4e580ab139f8422a702e09eacbea5d512c31a955b3d60310be2bbdd73484bae6612791a19da3c7b0fd1487e72131a8f9cb801790ce8a6e1e378662cedcd5ee82bd390576acfe5334ecd9d907273aefe67058916388210638e5e60f20ee92389b3533fd6affd33095b23d169f0913657f033b8d5c4ea517f167c1d53e031787bbe6d5b577245fff8151cd8fdcc5d6c32df70fb8043d42f896cd513b4c85cff292676cf13b6a1931e87727a561711a3105d9f3519b90c9429b5cd3edaae3ee334826a3fd74d6175b5589db392f956a67c5e67be59656f1cb37e52c636b2692a60c2044327472fa9af651afbcf55d8398a31d343074931a72d54833b29ef21fcb6ef419bb56313513e46c65d833677dbb0f2813e9ce5ef70676102ca0d3c14bbdd659a7498fa08cd359d428a803aefcc660e9fc704e9bacc5f1d27f2528d46b3fcaa2d47dfa28bf4c",
- "f0c1dd48e5843eb03de5abb298697dc0f103a9d0c230620bcd86467758379daa01ae18087d96096a8814e98808ab9b9c943917273054201ca3cdf2d49f3ac7896d34db1cb1d7959b4dd503f7b25b3390e0dbcacb15bbe8978236d75ae24d7ca0c4d516846ec0cc0e05b505b3d9d1c6e50165918c26672ed1525265b29f6336138cedca58e7f447a81b9485f743b5e01fd5a543f18d9335c5e2d19cae8245a9224a2baabdf7670e47bd22cf465df8563621124a8091325c670e4f8fa028686505cee87d52d63d1965e65daf61f5e1b00ae33d4e5a42496950e8d75710cf8c47718f6071850d11b552e19ba0fabef5ccc7813ba4bd0b593694b317f04fbe9caf48aff14a4555f78ab056d4148747c7bd5a8b6e4bc85d42aae4e2634ad9028e5f32345a6813c291588362a7ecf6e0c3b3a3db9dbaa82d2754962f5d9b3e0fd166cb11b5254081417dac0e35c00b56ebebd12112ae202c094fe3b24252f0787fb09c6c51036ceac6ddde4ac59aada7c76bc79e950b66ffe6a015450e8770c8b2b491ccec7610bf9a7f523e5a579ff64c62700a7e8304139c68cfdab34f7ad18b8989a9802ed9dd393d889cf4d526c9b53fdb0b78dcfad47b88c23d6992e0e63c31f80d69b427ea7e71944a61013a0c70b2e9cfe233a61cb4939d2fdde75e6ff8fee6b45d481ad0ad0110469edffc01b1bf2e4f1414f925d86ad198a27a0388637edc7dd547b8aeca86eccb3ad5c0615af8428096c8142d75235c465995e5eff6225e94913457551c1c185e1d7bfa2437ab56da49954834628ac480d7bada35ecbc34dc6efeb26009c82a0cc3f477757a91dc6d652ce7edd82cb891ba3b49bfeb74bd2a35b3f5bce74a34359dc00db8e0961cb9758cd99ef25cf718974d60ed5e7733f525c81edb0464c7930add3e9336d8715aeb37bb624844246a19d433c0ed615c221e5e89745d2467743773560639894b1abd0f6e5289b5826cee5fca76bdd6d0d4dd69fb4a50d7d814a48c7e35920abb8f0c1e60ba92d612f4f4bf5695a089de639bfbc6f317f4fd895d3257efbe1d49e944b82badd4b21164d4bae7a872f183a3c8385f54fdd8f471672132dd44e51ccdcfe183c0ce00032a048866af6dfea9e15b58a1709320e8fca16defeab233027a9ea3118a521c94be5c48a72de9c6fabf2196e123fc1356dea223712599758a2f6ffe91921c1acee3ec6c7b7a29a1d3c5f88ae6fb50b42e36c0773731e28ca3c93a18627d287ed5f538691421dffd36e3bb871854bc585f367edbe70b029f81f3605982eafa4135e54b78d0c6cdf18afe22ff7308da7011f15d3524906f10fb6b780fa9cc4b",
- "a6aad9eced14bf1c61910dba",
- 35);
+ "603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4",
+ "fd4c14729f5004ba49d832ad7be87c18f4fafb58962b9a43c3be41713ded93dbf854ac4ca26285b7f76e04b8f8d4e7d9f7548f9b465c8f713c106e9f63f54305331a4983a2f4b718de29fa794da12eee808642faeff8271a0ea28e3cc80eeb65a8eb61f69d8ba97f6bf9054453f55efb8f9422081f1620fe44acf99e81122f73d3f921d5e3391654e9947904984375b725fdfba895c5cde3d225d7be3a213c3965178a7dc1e3b552ec7b2ffd9c77ebcc243c4500dfdfbe3b7554aa427c01305bec48d71af27c5911d1e649c620d22cf5f3a5aeb9468651da796f369522faf91efabf0febd33fca41c9534606a4ea0199b904b243ba9cb8f37a792df02efab8f0e2e0cf1d579daba042cfe4c9430ad4eda786052fcf15e7acfa2736aab4590f73675fa1805fe23892c63e0cd01d006935a6e3f8e105a754803d00d9857e49636ab034164156856d58a244ead475300d93b31e44b5be3bbf6994edb895804b4f1bad43ecfe08b4e130148b669fe620e4f73034fc3e748237870bec3b1f517684654d1d6bc074ddf7b759a2405f78ed84d1006d25af9bbc12d6c632f5d543da0cbe9ea866b2c92126009c27ad59394b76337de246b50895317e2e345df3629a5f6227f64522866e7a39121ccc552e3dabc989dce066dea355f788c5d92ada099917a297cfefa867ce37656fac6a50798c10b394d5ba54f85cf0f7ef1eeddfca1e53e93f1349888cc745190c196f84ecf0721287cc592d406f0a6cc5a55294bf7aa3b35f6cefc61cab794b12444312b5e50ec0712e221cc95e9e26e9c3d000881e792afcb58641b1a94613d64ec72f3db9ab65ba07a4f05b7e9ee7b335d86a06fcbdb8cbd695aeef53964a965ffe4c6d7b4e580ab139f8422a702e09eacbea5d512c31a955b3d60310be2bbdd73484bae6612791a19da3c7b0fd1487e72131a8f9cb801790ce8a6e1e378662cedcd5ee82bd390576acfe5334ecd9d907273aefe67058916388210638e5e60f20ee92389b3533fd6affd33095b23d169f0913657f033b8d5c4ea517f167c1d53e031787bbe6d5b577245fff8151cd8fdcc5d6c32df70fb8043d42f896cd513b4c85cff292676cf13b6a1931e87727a561711a3105d9f3519b90c9429b5cd3edaae3ee334826a3fd74d6175b5589db392f956a67c5e67be59656f1cb37e52c636b2692a60c2044327472fa9af651afbcf55d8398a31d343074931a72d54833b29ef21fcb6ef419bb56313513e46c65d833677dbb0f2813e9ce5ef70676102ca0d3c14bbdd659a7498fa08cd359d428a803aefcc660e9fc704e9bacc5f1d27f2528d46b3fcaa2d47dfa28bf4c",
+ "f0c1dd48e5843eb03de5abb298697dc0f103a9d0c230620bcd86467758379daa01ae18087d96096a8814e98808ab9b9c943917273054201ca3cdf2d49f3ac7896d34db1cb1d7959b4dd503f7b25b3390e0dbcacb15bbe8978236d75ae24d7ca0c4d516846ec0cc0e05b505b3d9d1c6e50165918c26672ed1525265b29f6336138cedca58e7f447a81b9485f743b5e01fd5a543f18d9335c5e2d19cae8245a9224a2baabdf7670e47bd22cf465df8563621124a8091325c670e4f8fa028686505cee87d52d63d1965e65daf61f5e1b00ae33d4e5a42496950e8d75710cf8c47718f6071850d11b552e19ba0fabef5ccc7813ba4bd0b593694b317f04fbe9caf48aff14a4555f78ab056d4148747c7bd5a8b6e4bc85d42aae4e2634ad9028e5f32345a6813c291588362a7ecf6e0c3b3a3db9dbaa82d2754962f5d9b3e0fd166cb11b5254081417dac0e35c00b56ebebd12112ae202c094fe3b24252f0787fb09c6c51036ceac6ddde4ac59aada7c76bc79e950b66ffe6a015450e8770c8b2b491ccec7610bf9a7f523e5a579ff64c62700a7e8304139c68cfdab34f7ad18b8989a9802ed9dd393d889cf4d526c9b53fdb0b78dcfad47b88c23d6992e0e63c31f80d69b427ea7e71944a61013a0c70b2e9cfe233a61cb4939d2fdde75e6ff8fee6b45d481ad0ad0110469edffc01b1bf2e4f1414f925d86ad198a27a0388637edc7dd547b8aeca86eccb3ad5c0615af8428096c8142d75235c465995e5eff6225e94913457551c1c185e1d7bfa2437ab56da49954834628ac480d7bada35ecbc34dc6efeb26009c82a0cc3f477757a91dc6d652ce7edd82cb891ba3b49bfeb74bd2a35b3f5bce74a34359dc00db8e0961cb9758cd99ef25cf718974d60ed5e7733f525c81edb0464c7930add3e9336d8715aeb37bb624844246a19d433c0ed615c221e5e89745d2467743773560639894b1abd0f6e5289b5826cee5fca76bdd6d0d4dd69fb4a50d7d814a48c7e35920abb8f0c1e60ba92d612f4f4bf5695a089de639bfbc6f317f4fd895d3257efbe1d49e944b82badd4b21164d4bae7a872f183a3c8385f54fdd8f471672132dd44e51ccdcfe183c0ce00032a048866af6dfea9e15b58a1709320e8fca16defeab233027a9ea3118a521c94be5c48a72de9c6fabf2196e123fc1356dea223712599758a2f6ffe91921c1acee3ec6c7b7a29a1d3c5f88ae6fb50b42e36c0773731e28ca3c93a18627d287ed5f538691421dffd36e3bb871854bc585f367edbe70b029f81f3605982eafa4135e54b78d0c6cdf18afe22ff7308da7011f15d3524906f10fb6b780fa9cc4b",
+ "a6aad9eced14bf1c61910dba",
+ 35);
}
private static void testAesCtr32Kat(
- String hex_key,
- String hex_plaintext,
- String hex_ciphertext,
- String hex_nonce,
- int initialCtr) throws IOException, InvalidKeyException {
+ String hex_key, String hex_plaintext, String hex_ciphertext, String hex_nonce, int initialCtr)
+ throws IOException, InvalidKeyException {
byte[] key = Hex.fromStringCondensed(hex_key);
byte[] plaintext = Hex.fromStringCondensed(hex_plaintext);
diff --git a/java/client/src/test/java/org/signal/libsignal/crypto/Aes256GcmEncryptionTests.java b/java/client/src/test/java/org/signal/libsignal/crypto/Aes256GcmEncryptionTests.java
index 3ef05189d7..7c1bf31d4f 100644
--- a/java/client/src/test/java/org/signal/libsignal/crypto/Aes256GcmEncryptionTests.java
+++ b/java/client/src/test/java/org/signal/libsignal/crypto/Aes256GcmEncryptionTests.java
@@ -8,19 +8,18 @@
import java.io.IOException;
import junit.framework.TestCase;
import org.signal.libsignal.protocol.InvalidKeyException;
-import org.signal.libsignal.protocol.InvalidMessageException;
import org.signal.libsignal.protocol.util.Hex;
public class Aes256GcmEncryptionTests extends TestCase {
public void testAesGcmKats() throws Exception {
testAesGcmKat(
- "feffe9928665731c6d6a8f9467308308feffe9928665731c6d6a8f9467308308",
- "d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39",
- "522dc1f099567d07f47f37a32a84427d643a8cdcbfe5c0c97598a2bd2555d1aa8cb08e48590dbb3da7b08b1056828838c5f61e6393ba7a0abcc9f662",
- "76fc6ece0f4e1768cddf8853bb2d551b",
- "cafebabefacedbaddecaf888",
- "feedfacedeadbeeffeedfacedeadbeefabaddad2");
+ "feffe9928665731c6d6a8f9467308308feffe9928665731c6d6a8f9467308308",
+ "d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39",
+ "522dc1f099567d07f47f37a32a84427d643a8cdcbfe5c0c97598a2bd2555d1aa8cb08e48590dbb3da7b08b1056828838c5f61e6393ba7a0abcc9f662",
+ "76fc6ece0f4e1768cddf8853bb2d551b",
+ "cafebabefacedbaddecaf888",
+ "feedfacedeadbeeffeedfacedeadbeefabaddad2");
}
private static void testAesGcmKat(
@@ -29,39 +28,40 @@ private static void testAesGcmKat(
String hex_ciphertext,
String hex_tag,
String hex_nonce,
- String hex_associated_data) throws IOException, InvalidKeyException {
+ String hex_associated_data)
+ throws IOException, InvalidKeyException {
- byte[] key = Hex.fromStringCondensed(hex_key);
- byte[] plaintext = Hex.fromStringCondensed(hex_plaintext);
- byte[] nonce = Hex.fromStringCondensed(hex_nonce);
- byte[] ad = Hex.fromStringCondensed(hex_associated_data);
+ byte[] key = Hex.fromStringCondensed(hex_key);
+ byte[] plaintext = Hex.fromStringCondensed(hex_plaintext);
+ byte[] nonce = Hex.fromStringCondensed(hex_nonce);
+ byte[] ad = Hex.fromStringCondensed(hex_associated_data);
- Aes256GcmEncryption gcmEnc = new Aes256GcmEncryption(key, nonce, ad);
- byte[] ciphertext = plaintext.clone();
- gcmEnc.encrypt(ciphertext);
- byte[] tag = gcmEnc.computeTag();
- assertEquals(Hex.toStringCondensed(ciphertext), hex_ciphertext);
- assertEquals(Hex.toStringCondensed(tag), hex_tag);
+ Aes256GcmEncryption gcmEnc = new Aes256GcmEncryption(key, nonce, ad);
+ byte[] ciphertext = plaintext.clone();
+ gcmEnc.encrypt(ciphertext);
+ byte[] tag = gcmEnc.computeTag();
+ assertEquals(Hex.toStringCondensed(ciphertext), hex_ciphertext);
+ assertEquals(Hex.toStringCondensed(tag), hex_tag);
- Aes256GcmDecryption gcmDec = new Aes256GcmDecryption(key, nonce, ad);
- byte[] decrypted = ciphertext.clone();
- gcmDec.decrypt(decrypted);
- assertEquals(Hex.toStringCondensed(decrypted), hex_plaintext);
- assertEquals(gcmDec.verifyTag(tag), true);
+ Aes256GcmDecryption gcmDec = new Aes256GcmDecryption(key, nonce, ad);
+ byte[] decrypted = ciphertext.clone();
+ gcmDec.decrypt(decrypted);
+ assertEquals(Hex.toStringCondensed(decrypted), hex_plaintext);
+ assertEquals(gcmDec.verifyTag(tag), true);
- Aes256GcmEncryption gcmEnc2 = new Aes256GcmEncryption(key, nonce, ad);
- byte[] ciphertextSplit = plaintext.clone();
- gcmEnc2.encrypt(ciphertextSplit, 0, 1);
- gcmEnc2.encrypt(ciphertextSplit, 1, plaintext.length - 1);
- byte[] tag2 = gcmEnc2.computeTag();
- assertEquals(Hex.toStringCondensed(ciphertextSplit), hex_ciphertext);
- assertEquals(Hex.toStringCondensed(tag2), hex_tag);
+ Aes256GcmEncryption gcmEnc2 = new Aes256GcmEncryption(key, nonce, ad);
+ byte[] ciphertextSplit = plaintext.clone();
+ gcmEnc2.encrypt(ciphertextSplit, 0, 1);
+ gcmEnc2.encrypt(ciphertextSplit, 1, plaintext.length - 1);
+ byte[] tag2 = gcmEnc2.computeTag();
+ assertEquals(Hex.toStringCondensed(ciphertextSplit), hex_ciphertext);
+ assertEquals(Hex.toStringCondensed(tag2), hex_tag);
- Aes256GcmDecryption gcmDec2 = new Aes256GcmDecryption(key, nonce, ad);
- byte[] decryptedSplit = ciphertext.clone();
- gcmDec2.decrypt(decryptedSplit, 0, 1);
- gcmDec2.decrypt(decryptedSplit, 1, ciphertext.length - 1);
- assertEquals(Hex.toStringCondensed(decryptedSplit), hex_plaintext);
- assertEquals(gcmDec2.verifyTag(tag), true);
+ Aes256GcmDecryption gcmDec2 = new Aes256GcmDecryption(key, nonce, ad);
+ byte[] decryptedSplit = ciphertext.clone();
+ gcmDec2.decrypt(decryptedSplit, 0, 1);
+ gcmDec2.decrypt(decryptedSplit, 1, ciphertext.length - 1);
+ assertEquals(Hex.toStringCondensed(decryptedSplit), hex_plaintext);
+ assertEquals(gcmDec2.verifyTag(tag), true);
}
}
diff --git a/java/client/src/test/java/org/signal/libsignal/crypto/CryptographicHashTests.java b/java/client/src/test/java/org/signal/libsignal/crypto/CryptographicHashTests.java
index 89151ed667..a13d5298ab 100644
--- a/java/client/src/test/java/org/signal/libsignal/crypto/CryptographicHashTests.java
+++ b/java/client/src/test/java/org/signal/libsignal/crypto/CryptographicHashTests.java
@@ -4,54 +4,62 @@
//
package org.signal.libsignal.crypto;
+
import junit.framework.TestCase;
-import org.signal.libsignal.crypto.CryptographicHash;
import org.signal.libsignal.protocol.util.Hex;
public class CryptographicHashTests extends TestCase {
- void hashKat(String algo, String hexInput, String hexExpectedOutput) throws Exception {
- CryptographicHash hash = new CryptographicHash(algo);
-
- byte[] input = Hex.fromStringCondensed(hexInput);
-
- hash.update(input);
- byte[] digestAllInOne = hash.finish();
-
- assertEquals(Hex.toStringCondensed(digestAllInOne), hexExpectedOutput);
-
- if(input.length > 1) {
- hash.update(input, 0, 1);
- hash.update(input, 1, input.length - 1);
- byte[] digestSplit = hash.finish();
- assertEquals(Hex.toStringCondensed(digestSplit), hexExpectedOutput);
-
- hash.update(input, 0, input.length - 1);
- hash.update(input, input.length - 1, 1);
- byte[] digestSplit2 = hash.finish();
- assertEquals(Hex.toStringCondensed(digestSplit2), hexExpectedOutput);
- }
- }
-
- public void testSha1() throws Exception {
- hashKat("Sha1", "", "da39a3ee5e6b4b0d3255bfef95601890afd80709");
- hashKat("Sha1", "616263", "a9993e364706816aba3e25717850c26c9cd0d89d");
- hashKat("Sha1", "f1ea1c9b787bad", "b234020692659c3dee19f7e75390984dd7e7ebbb");
- }
-
- public void testSha256() throws Exception {
- hashKat("Sha256", "", "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855");
- hashKat("Sha256", "616263", "ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad");
- hashKat("Sha256", "6d65737361676520646967657374",
- "f7846f55cf23e14eebeab5b4e1550cad5b509e3348fbc4efa3a1413d393cb650");
- }
-
- public void testSha512() throws Exception {
- hashKat("Sha512", "",
- "cf83e1357eefb8bdf1542850d66d8007d620e4050b5715dc83f4a921d36ce9ce47d0d13c5d85f2b0ff8318d2877eec2f63b931bd47417a81a538327af927da3e");
- hashKat("Sha512", "616263",
- "ddaf35a193617abacc417349ae20413112e6fa4e89a97ea20a9eeee64b55d39a2192992a274fc1a836ba3c23a3feebbd454d4423643ce80e2a9ac94fa54ca49f");
- hashKat("Sha512", "6d65737361676520646967657374",
- "107dbf389d9e9f71a3a95f6c055b9251bc5268c2be16d6c13492ea45b0199f3309e16455ab1e96118e8a905d5597b72038ddb372a89826046de66687bb420e7c");
- }
+ void hashKat(String algo, String hexInput, String hexExpectedOutput) throws Exception {
+ CryptographicHash hash = new CryptographicHash(algo);
+
+ byte[] input = Hex.fromStringCondensed(hexInput);
+
+ hash.update(input);
+ byte[] digestAllInOne = hash.finish();
+
+ assertEquals(Hex.toStringCondensed(digestAllInOne), hexExpectedOutput);
+
+ if (input.length > 1) {
+ hash.update(input, 0, 1);
+ hash.update(input, 1, input.length - 1);
+ byte[] digestSplit = hash.finish();
+ assertEquals(Hex.toStringCondensed(digestSplit), hexExpectedOutput);
+
+ hash.update(input, 0, input.length - 1);
+ hash.update(input, input.length - 1, 1);
+ byte[] digestSplit2 = hash.finish();
+ assertEquals(Hex.toStringCondensed(digestSplit2), hexExpectedOutput);
+ }
+ }
+
+ public void testSha1() throws Exception {
+ hashKat("Sha1", "", "da39a3ee5e6b4b0d3255bfef95601890afd80709");
+ hashKat("Sha1", "616263", "a9993e364706816aba3e25717850c26c9cd0d89d");
+ hashKat("Sha1", "f1ea1c9b787bad", "b234020692659c3dee19f7e75390984dd7e7ebbb");
+ }
+
+ public void testSha256() throws Exception {
+ hashKat("Sha256", "", "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855");
+ hashKat("Sha256", "616263", "ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad");
+ hashKat(
+ "Sha256",
+ "6d65737361676520646967657374",
+ "f7846f55cf23e14eebeab5b4e1550cad5b509e3348fbc4efa3a1413d393cb650");
+ }
+
+ public void testSha512() throws Exception {
+ hashKat(
+ "Sha512",
+ "",
+ "cf83e1357eefb8bdf1542850d66d8007d620e4050b5715dc83f4a921d36ce9ce47d0d13c5d85f2b0ff8318d2877eec2f63b931bd47417a81a538327af927da3e");
+ hashKat(
+ "Sha512",
+ "616263",
+ "ddaf35a193617abacc417349ae20413112e6fa4e89a97ea20a9eeee64b55d39a2192992a274fc1a836ba3c23a3feebbd454d4423643ce80e2a9ac94fa54ca49f");
+ hashKat(
+ "Sha512",
+ "6d65737361676520646967657374",
+ "107dbf389d9e9f71a3a95f6c055b9251bc5268c2be16d6c13492ea45b0199f3309e16455ab1e96118e8a905d5597b72038ddb372a89826046de66687bb420e7c");
+ }
}
diff --git a/java/client/src/test/java/org/signal/libsignal/crypto/CryptographicMacTests.java b/java/client/src/test/java/org/signal/libsignal/crypto/CryptographicMacTests.java
index e8b1da70e2..36522cb94a 100644
--- a/java/client/src/test/java/org/signal/libsignal/crypto/CryptographicMacTests.java
+++ b/java/client/src/test/java/org/signal/libsignal/crypto/CryptographicMacTests.java
@@ -4,58 +4,62 @@
//
package org.signal.libsignal.crypto;
+
import junit.framework.TestCase;
-import org.signal.libsignal.crypto.CryptographicMac;
import org.signal.libsignal.protocol.util.Hex;
public class CryptographicMacTests extends TestCase {
- void hmacKat(String algo, String hexKey, String hexInput, String hexExpectedOutput) throws Exception {
- CryptographicMac hmac = new CryptographicMac(algo, Hex.fromStringCondensed(hexKey));
-
- byte[] input = Hex.fromStringCondensed(hexInput);
-
- hmac.update(input);
- byte[] macAllInOne = hmac.finish();
- assertEquals(Hex.toStringCondensed(macAllInOne), hexExpectedOutput);
-
- if(input.length > 1) {
- hmac.update(input, 0, 1);
- hmac.update(input, 1, input.length - 1);
- byte[] macSplit = hmac.finish();
- assertEquals(Hex.toStringCondensed(macSplit), hexExpectedOutput);
-
- hmac.update(input, 0, input.length - 1);
- hmac.update(input, input.length - 1, 1);
- byte[] macSplit2 = hmac.finish();
- assertEquals(Hex.toStringCondensed(macSplit2), hexExpectedOutput);
- }
- }
-
- public void testHmacSha1() throws Exception {
- // RFC 2202
- hmacKat("HmacSha1",
- "0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b",
- "4869205468657265",
- "b617318655057264e28bc0b6fb378c8ef146be00");
-
- hmacKat("HmacSha1",
- "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
- "dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd",
- "125d7342b9ac11cd91a39af48aa17b4f63f175d3");
- }
-
- public void testHmacSha256() throws Exception {
- // RFC 4231
- hmacKat("HmacSha256",
- "0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b",
- "4869205468657265",
- "b0344c61d8db38535ca8afceaf0bf12b881dc200c9833da726e9376c2e32cff7");
-
- hmacKat("HmacSha256",
- "4a656665",
- "7768617420646f2079612077616e7420666f72206e6f7468696e673f",
- "5bdcc146bf60754e6a042426089575c75a003f089d2739839dec58b964ec3843");
- }
+ void hmacKat(String algo, String hexKey, String hexInput, String hexExpectedOutput)
+ throws Exception {
+ CryptographicMac hmac = new CryptographicMac(algo, Hex.fromStringCondensed(hexKey));
+
+ byte[] input = Hex.fromStringCondensed(hexInput);
+
+ hmac.update(input);
+ byte[] macAllInOne = hmac.finish();
+ assertEquals(Hex.toStringCondensed(macAllInOne), hexExpectedOutput);
+
+ if (input.length > 1) {
+ hmac.update(input, 0, 1);
+ hmac.update(input, 1, input.length - 1);
+ byte[] macSplit = hmac.finish();
+ assertEquals(Hex.toStringCondensed(macSplit), hexExpectedOutput);
+
+ hmac.update(input, 0, input.length - 1);
+ hmac.update(input, input.length - 1, 1);
+ byte[] macSplit2 = hmac.finish();
+ assertEquals(Hex.toStringCondensed(macSplit2), hexExpectedOutput);
+ }
+ }
+
+ public void testHmacSha1() throws Exception {
+ // RFC 2202
+ hmacKat(
+ "HmacSha1",
+ "0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b",
+ "4869205468657265",
+ "b617318655057264e28bc0b6fb378c8ef146be00");
+
+ hmacKat(
+ "HmacSha1",
+ "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+ "dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd",
+ "125d7342b9ac11cd91a39af48aa17b4f63f175d3");
+ }
+
+ public void testHmacSha256() throws Exception {
+ // RFC 4231
+ hmacKat(
+ "HmacSha256",
+ "0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b",
+ "4869205468657265",
+ "b0344c61d8db38535ca8afceaf0bf12b881dc200c9833da726e9376c2e32cff7");
+ hmacKat(
+ "HmacSha256",
+ "4a656665",
+ "7768617420646f2079612077616e7420666f72206e6f7468696e673f",
+ "5bdcc146bf60754e6a042426089575c75a003f089d2739839dec58b964ec3843");
+ }
}
diff --git a/java/client/src/test/java/org/signal/libsignal/devicetransfer/DeviceTransferKeyTest.java b/java/client/src/test/java/org/signal/libsignal/devicetransfer/DeviceTransferKeyTest.java
index cb6fe9d91f..6a54486582 100644
--- a/java/client/src/test/java/org/signal/libsignal/devicetransfer/DeviceTransferKeyTest.java
+++ b/java/client/src/test/java/org/signal/libsignal/devicetransfer/DeviceTransferKeyTest.java
@@ -5,10 +5,9 @@
package org.signal.libsignal.devicetransfer;
-import junit.framework.TestCase;
-
import java.io.ByteArrayInputStream;
import java.security.cert.CertificateFactory;
+import junit.framework.TestCase;
public class DeviceTransferKeyTest extends TestCase {
public void testDeviceTransferKey() throws Exception {
diff --git a/java/client/src/test/java/org/signal/libsignal/hsmenclave/HsmEnclaveClientTest.java b/java/client/src/test/java/org/signal/libsignal/hsmenclave/HsmEnclaveClientTest.java
index 5ba76ddaa6..490e85d1fd 100644
--- a/java/client/src/test/java/org/signal/libsignal/hsmenclave/HsmEnclaveClientTest.java
+++ b/java/client/src/test/java/org/signal/libsignal/hsmenclave/HsmEnclaveClientTest.java
@@ -5,17 +5,24 @@
package org.signal.libsignal.hsmenclave;
-import junit.framework.TestCase;
-
import java.util.ArrayList;
import java.util.List;
+import junit.framework.TestCase;
public class HsmEnclaveClientTest extends TestCase {
public void testCreateClient() throws Exception {
byte[] validKey = new byte[32];
List hashes = new ArrayList<>();
- hashes.add(new byte[]{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});
- hashes.add(new byte[]{1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1});
+ hashes.add(
+ new byte[] {
+ 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
+ });
+ hashes.add(
+ new byte[] {
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1
+ });
HsmEnclaveClient hsmEnclaveClient = new HsmEnclaveClient(validKey, hashes);
byte[] initialMessage = hsmEnclaveClient.initialRequest();
assertEquals(112, initialMessage.length);
@@ -24,8 +31,16 @@ public void testCreateClient() throws Exception {
public void testCreateClientFailsWithInvalidPublicKey() {
byte[] invalidKey = new byte[31];
List hashes = new ArrayList<>();
- hashes.add(new byte[]{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});
- hashes.add(new byte[]{1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1});
+ hashes.add(
+ new byte[] {
+ 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
+ });
+ hashes.add(
+ new byte[] {
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1
+ });
try {
new HsmEnclaveClient(invalidKey, hashes);
} catch (IllegalArgumentException e) {
@@ -37,8 +52,15 @@ public void testCreateClientFailsWithInvalidPublicKey() {
public void testCreateClientFailsWithInvalidHash() {
byte[] validKey = new byte[32];
List hashes = new ArrayList<>();
- hashes.add(new byte[]{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});
- hashes.add(new byte[]{1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0});
+ hashes.add(
+ new byte[] {
+ 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
+ });
+ hashes.add(
+ new byte[] {
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 0, 0, 0, 0
+ });
try {
new HsmEnclaveClient(validKey, hashes);
} catch (IllegalArgumentException e) {
@@ -61,10 +83,14 @@ public void testCreateClientFailsWithNoHashes() {
public void testEstablishedSendFailsPriorToEstablishment() {
byte[] validKey = new byte[32];
List hashes = new ArrayList<>();
- hashes.add(new byte[]{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});
+ hashes.add(
+ new byte[] {
+ 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
+ });
HsmEnclaveClient hsmEnclaveClient = new HsmEnclaveClient(validKey, hashes);
try {
- hsmEnclaveClient.establishedSend(new byte[]{1, 2, 3});
+ hsmEnclaveClient.establishedSend(new byte[] {1, 2, 3});
} catch (IllegalStateException e) {
return;
}
@@ -74,10 +100,14 @@ public void testEstablishedSendFailsPriorToEstablishment() {
public void testEstablishedRecvFailsPriorToEstablishment() {
byte[] validKey = new byte[32];
List hashes = new ArrayList<>();
- hashes.add(new byte[]{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});
+ hashes.add(
+ new byte[] {
+ 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
+ });
HsmEnclaveClient hsmEnclaveClient = new HsmEnclaveClient(validKey, hashes);
try {
- hsmEnclaveClient.establishedRecv(new byte[]{1, 2, 3});
+ hsmEnclaveClient.establishedRecv(new byte[] {1, 2, 3});
} catch (IllegalStateException e) {
return;
}
diff --git a/java/client/src/test/java/org/signal/libsignal/media/Mp4SanitizerTest.java b/java/client/src/test/java/org/signal/libsignal/media/Mp4SanitizerTest.java
index 90ce1ccb57..da2f0a8aba 100644
--- a/java/client/src/test/java/org/signal/libsignal/media/Mp4SanitizerTest.java
+++ b/java/client/src/test/java/org/signal/libsignal/media/Mp4SanitizerTest.java
@@ -5,148 +5,153 @@
package org.signal.libsignal.media;
-import org.junit.Assert;
-import org.junit.Assume;
-import org.junit.Before;
-import org.junit.Test;
-import org.signal.libsignal.protocol.util.ByteUtil;
-import org.signal.libsignal.internal.Native;
+import static org.junit.Assert.fail;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStream;
-
-import static org.junit.Assert.fail;
+import org.junit.Assert;
+import org.junit.Assume;
+import org.junit.Before;
+import org.junit.Test;
+import org.signal.libsignal.internal.Native;
+import org.signal.libsignal.protocol.util.ByteUtil;
public class Mp4SanitizerTest {
- @Before
- public void checkLibsignalMediaAvailable() {
- try {
- Native.SignalMedia_CheckAvailable();
- } catch (UnsatisfiedLinkError e) {
- Assume.assumeNoException(e);
- }
+ @Before
+ public void checkLibsignalMediaAvailable() {
+ try {
+ Native.SignalMedia_CheckAvailable();
+ } catch (UnsatisfiedLinkError e) {
+ Assume.assumeNoException(e);
}
-
- @Test
- public void testEmptyMp4() throws Exception {
- byte[] data = new byte[] {};
- try {
- Mp4Sanitizer.sanitize(new ByteArrayInputStream(data), data.length);
- fail("empty mp4 accepted");
- } catch (ParseException e) {
- // good
- }
+ }
+
+ @Test
+ public void testEmptyMp4() throws Exception {
+ byte[] data = new byte[] {};
+ try {
+ Mp4Sanitizer.sanitize(new ByteArrayInputStream(data), data.length);
+ fail("empty mp4 accepted");
+ } catch (ParseException e) {
+ // good
}
-
- @Test
- public void testTruncatedMp4() throws Exception {
- byte[] data = new byte[] { 0, 0, 0, 0 };
- try {
- Mp4Sanitizer.sanitize(new ByteArrayInputStream(data), data.length);
- fail("truncated mp4 accepted");
- } catch (ParseException e) {
- // good
- }
+ }
+
+ @Test
+ public void testTruncatedMp4() throws Exception {
+ byte[] data = new byte[] {0, 0, 0, 0};
+ try {
+ Mp4Sanitizer.sanitize(new ByteArrayInputStream(data), data.length);
+ fail("truncated mp4 accepted");
+ } catch (ParseException e) {
+ // good
}
-
- @Test
- public void testNoopMinimalMp4() throws Exception {
- byte[] metadata = ByteUtil.combine(ftyp(), moov());
- byte[] mp4Data = ByteUtil.combine(metadata, mdat());
-
- SanitizedMetadata sanitized = Mp4Sanitizer.sanitize(new ByteArrayInputStream(mp4Data), mp4Data.length);
-
- assertSanitizedMetadataEquals(sanitized, metadata.length, mp4Data.length - metadata.length, null);
- }
-
- @Test
- public void testMinimalMp4() throws Exception {
- byte[] metadata = ByteUtil.combine(ftyp(), moov());
- byte[] mp4Data = ByteUtil.combine(ftyp(), mdat(), moov());
-
- SanitizedMetadata sanitized = Mp4Sanitizer.sanitize(new ByteArrayInputStream(mp4Data), mp4Data.length);
-
- assertSanitizedMetadataEquals(sanitized, ftyp().length, mp4Data.length - metadata.length, metadata);
- }
-
- @Test
- public void testMp4IoError() throws Exception {
- InputStream ioErrorStream = new InputStream() {
- @Override
- public int read() throws IOException {
- throw new IOException("test io error");
- }
+ }
+
+ @Test
+ public void testNoopMinimalMp4() throws Exception {
+ byte[] metadata = ByteUtil.combine(ftyp(), moov());
+ byte[] mp4Data = ByteUtil.combine(metadata, mdat());
+
+ SanitizedMetadata sanitized =
+ Mp4Sanitizer.sanitize(new ByteArrayInputStream(mp4Data), mp4Data.length);
+
+ assertSanitizedMetadataEquals(
+ sanitized, metadata.length, mp4Data.length - metadata.length, null);
+ }
+
+ @Test
+ public void testMinimalMp4() throws Exception {
+ byte[] metadata = ByteUtil.combine(ftyp(), moov());
+ byte[] mp4Data = ByteUtil.combine(ftyp(), mdat(), moov());
+
+ SanitizedMetadata sanitized =
+ Mp4Sanitizer.sanitize(new ByteArrayInputStream(mp4Data), mp4Data.length);
+
+ assertSanitizedMetadataEquals(
+ sanitized, ftyp().length, mp4Data.length - metadata.length, metadata);
+ }
+
+ @Test
+ public void testMp4IoError() throws Exception {
+ InputStream ioErrorStream =
+ new InputStream() {
+ @Override
+ public int read() throws IOException {
+ throw new IOException("test io error");
+ }
};
- try {
- Mp4Sanitizer.sanitize(ioErrorStream, 1);
- fail("InputStream exception not propagated");
- } catch (IOException e) {
- // good
- }
- }
-
- private static byte[] ftyp() throws IOException {
- ByteArrayOutputStream ftypOutputStream = new ByteArrayOutputStream();
- DataOutputStream ftypDataOutputStream = new DataOutputStream(ftypOutputStream);
-
- ftypDataOutputStream.writeInt(20); // box size
- ftypDataOutputStream.write("ftyp".getBytes()); // box type
- ftypDataOutputStream.write("isom".getBytes()); // major_brand
- ftypDataOutputStream.writeInt(0); // minor_version
- ftypDataOutputStream.write("isom".getBytes()); // compatible_brands
-
- return ftypOutputStream.toByteArray();
- }
-
- private static byte[] moov() throws IOException {
- ByteArrayOutputStream moovOutputStream = new ByteArrayOutputStream();
- DataOutputStream moovDataOutputStream = new DataOutputStream(moovOutputStream);
-
- // moov box header
- moovDataOutputStream.writeInt(56); // box size
- moovDataOutputStream.write("moov".getBytes()); // box type
-
- // trak box (inside moov box)
- moovDataOutputStream.writeInt(48); // box size
- moovDataOutputStream.write("trak".getBytes()); // box type
-
- // mdia box (inside trak box)
- moovDataOutputStream.writeInt(40); // box size
- moovDataOutputStream.write("mdia".getBytes()); // box type
-
- // minf box (inside mdia box)
- moovDataOutputStream.writeInt(32); // box size
- moovDataOutputStream.write("minf".getBytes()); // box type
-
- // stbl box (inside minf box)
- moovDataOutputStream.writeInt(24); // box size
- moovDataOutputStream.write("stbl".getBytes()); // box type
-
- // stco box (inside stbl box)
- moovDataOutputStream.writeInt(16); // box size
- moovDataOutputStream.write("stco".getBytes()); // box type
- moovDataOutputStream.writeInt(0); // box version & flags
- moovDataOutputStream.writeInt(0); // entry count
-
- return moovOutputStream.toByteArray();
- }
-
- private static byte[] mdat() throws IOException {
- ByteArrayOutputStream mdatOutputStream = new ByteArrayOutputStream();
- DataOutputStream mdatDataOutputStream = new DataOutputStream(mdatOutputStream);
-
- mdatDataOutputStream.writeInt(8); // box size
- mdatDataOutputStream.write("mdat".getBytes()); // box type
-
- return mdatOutputStream.toByteArray();
- }
-
- private static void assertSanitizedMetadataEquals(SanitizedMetadata sanitized, long dataOffset, long dataLength, byte[] metadata) {
- Assert.assertArrayEquals(sanitized.getSanitizedMetadata(), metadata);
- Assert.assertEquals(sanitized.getDataOffset(), dataOffset);
- Assert.assertEquals(sanitized.getDataLength(), dataLength);
+ try {
+ Mp4Sanitizer.sanitize(ioErrorStream, 1);
+ fail("InputStream exception not propagated");
+ } catch (IOException e) {
+ // good
}
+ }
+
+ private static byte[] ftyp() throws IOException {
+ ByteArrayOutputStream ftypOutputStream = new ByteArrayOutputStream();
+ DataOutputStream ftypDataOutputStream = new DataOutputStream(ftypOutputStream);
+
+ ftypDataOutputStream.writeInt(20); // box size
+ ftypDataOutputStream.write("ftyp".getBytes()); // box type
+ ftypDataOutputStream.write("isom".getBytes()); // major_brand
+ ftypDataOutputStream.writeInt(0); // minor_version
+ ftypDataOutputStream.write("isom".getBytes()); // compatible_brands
+
+ return ftypOutputStream.toByteArray();
+ }
+
+ private static byte[] moov() throws IOException {
+ ByteArrayOutputStream moovOutputStream = new ByteArrayOutputStream();
+ DataOutputStream moovDataOutputStream = new DataOutputStream(moovOutputStream);
+
+ // moov box header
+ moovDataOutputStream.writeInt(56); // box size
+ moovDataOutputStream.write("moov".getBytes()); // box type
+
+ // trak box (inside moov box)
+ moovDataOutputStream.writeInt(48); // box size
+ moovDataOutputStream.write("trak".getBytes()); // box type
+
+ // mdia box (inside trak box)
+ moovDataOutputStream.writeInt(40); // box size
+ moovDataOutputStream.write("mdia".getBytes()); // box type
+
+ // minf box (inside mdia box)
+ moovDataOutputStream.writeInt(32); // box size
+ moovDataOutputStream.write("minf".getBytes()); // box type
+
+ // stbl box (inside minf box)
+ moovDataOutputStream.writeInt(24); // box size
+ moovDataOutputStream.write("stbl".getBytes()); // box type
+
+ // stco box (inside stbl box)
+ moovDataOutputStream.writeInt(16); // box size
+ moovDataOutputStream.write("stco".getBytes()); // box type
+ moovDataOutputStream.writeInt(0); // box version & flags
+ moovDataOutputStream.writeInt(0); // entry count
+
+ return moovOutputStream.toByteArray();
+ }
+
+ private static byte[] mdat() throws IOException {
+ ByteArrayOutputStream mdatOutputStream = new ByteArrayOutputStream();
+ DataOutputStream mdatDataOutputStream = new DataOutputStream(mdatOutputStream);
+
+ mdatDataOutputStream.writeInt(8); // box size
+ mdatDataOutputStream.write("mdat".getBytes()); // box type
+
+ return mdatOutputStream.toByteArray();
+ }
+
+ private static void assertSanitizedMetadataEquals(
+ SanitizedMetadata sanitized, long dataOffset, long dataLength, byte[] metadata) {
+ Assert.assertArrayEquals(sanitized.getSanitizedMetadata(), metadata);
+ Assert.assertEquals(sanitized.getDataOffset(), dataOffset);
+ Assert.assertEquals(sanitized.getDataLength(), dataLength);
+ }
}
diff --git a/java/client/src/test/java/org/signal/libsignal/metadata/SealedSessionCipherTest.java b/java/client/src/test/java/org/signal/libsignal/metadata/SealedSessionCipherTest.java
index c834dedaf4..094ecbe062 100644
--- a/java/client/src/test/java/org/signal/libsignal/metadata/SealedSessionCipherTest.java
+++ b/java/client/src/test/java/org/signal/libsignal/metadata/SealedSessionCipherTest.java
@@ -1,13 +1,23 @@
+//
+// Copyright 2023 Signal Messenger, LLC.
+// SPDX-License-Identifier: AGPL-3.0-only
+//
+
package org.signal.libsignal.metadata;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Optional;
+import java.util.UUID;
import junit.framework.TestCase;
-
+import org.signal.libsignal.internal.Native;
+import org.signal.libsignal.internal.NativeHandleGuard;
import org.signal.libsignal.metadata.SealedSessionCipher.DecryptionResult;
-import org.signal.libsignal.metadata.protocol.UnidentifiedSenderMessageContent;
import org.signal.libsignal.metadata.certificate.CertificateValidator;
import org.signal.libsignal.metadata.certificate.InvalidCertificateException;
import org.signal.libsignal.metadata.certificate.SenderCertificate;
import org.signal.libsignal.metadata.certificate.ServerCertificate;
+import org.signal.libsignal.metadata.protocol.UnidentifiedSenderMessageContent;
import org.signal.libsignal.protocol.IdentityKeyPair;
import org.signal.libsignal.protocol.InvalidKeyException;
import org.signal.libsignal.protocol.InvalidMessageException;
@@ -30,81 +40,115 @@
import org.signal.libsignal.protocol.message.DecryptionErrorMessage;
import org.signal.libsignal.protocol.message.PlaintextContent;
import org.signal.libsignal.protocol.message.SenderKeyDistributionMessage;
+import org.signal.libsignal.protocol.state.KyberPreKeyRecord;
import org.signal.libsignal.protocol.state.PreKeyBundle;
import org.signal.libsignal.protocol.state.PreKeyRecord;
import org.signal.libsignal.protocol.state.SessionRecord;
import org.signal.libsignal.protocol.state.SignedPreKeyRecord;
-import org.signal.libsignal.protocol.state.KyberPreKeyRecord;
-
-import org.signal.libsignal.internal.Native;
-import org.signal.libsignal.internal.NativeHandleGuard;
-
import org.signal.libsignal.protocol.util.Hex;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Optional;
-import java.util.UUID;
-
public class SealedSessionCipherTest extends TestCase {
- private static SignedPreKeyRecord generateSignedPreKey(IdentityKeyPair identityKeyPair, int signedPreKeyId)
- throws InvalidKeyException
- {
- ECKeyPair keyPair = Curve.generateKeyPair();
- byte[] signature = Curve.calculateSignature(identityKeyPair.getPrivateKey(), keyPair.getPublicKey().serialize());
+ private static SignedPreKeyRecord generateSignedPreKey(
+ IdentityKeyPair identityKeyPair, int signedPreKeyId) throws InvalidKeyException {
+ ECKeyPair keyPair = Curve.generateKeyPair();
+ byte[] signature =
+ Curve.calculateSignature(
+ identityKeyPair.getPrivateKey(), keyPair.getPublicKey().serialize());
return new SignedPreKeyRecord(signedPreKeyId, System.currentTimeMillis(), keyPair, signature);
}
- private static KyberPreKeyRecord generateKyberPreKey(IdentityKeyPair identityKeyPair, int kyberPreKeyId)
- throws InvalidKeyException {
- KEMKeyPair keyPair = KEMKeyPair.generate(KEMKeyType.KYBER_1024);
- byte[] signature = Curve.calculateSignature(identityKeyPair.getPrivateKey(), keyPair.getPublicKey().serialize());
+ private static KyberPreKeyRecord generateKyberPreKey(
+ IdentityKeyPair identityKeyPair, int kyberPreKeyId) throws InvalidKeyException {
+ KEMKeyPair keyPair = KEMKeyPair.generate(KEMKeyType.KYBER_1024);
+ byte[] signature =
+ Curve.calculateSignature(
+ identityKeyPair.getPrivateKey(), keyPair.getPublicKey().serialize());
return new KyberPreKeyRecord(kyberPreKeyId, System.currentTimeMillis(), keyPair, signature);
}
- public void testEncryptDecrypt() throws UntrustedIdentityException, InvalidKeyException, InvalidCertificateException, InvalidMetadataMessageException, ProtocolDuplicateMessageException, ProtocolUntrustedIdentityException, ProtocolLegacyMessageException, ProtocolInvalidKeyException, InvalidMetadataVersionException, ProtocolInvalidVersionException, ProtocolInvalidMessageException, ProtocolInvalidKeyIdException, ProtocolNoSessionException, SelfSendException {
+ public void testEncryptDecrypt()
+ throws UntrustedIdentityException,
+ InvalidKeyException,
+ InvalidCertificateException,
+ InvalidMetadataMessageException,
+ ProtocolDuplicateMessageException,
+ ProtocolUntrustedIdentityException,
+ ProtocolLegacyMessageException,
+ ProtocolInvalidKeyException,
+ InvalidMetadataVersionException,
+ ProtocolInvalidVersionException,
+ ProtocolInvalidMessageException,
+ ProtocolInvalidKeyIdException,
+ ProtocolNoSessionException,
+ SelfSendException {
TestInMemorySignalProtocolStore aliceStore = new TestInMemorySignalProtocolStore();
- TestInMemorySignalProtocolStore bobStore = new TestInMemorySignalProtocolStore();
- SignalProtocolAddress bobAddress = new SignalProtocolAddress("+14152222222", 1);
+ TestInMemorySignalProtocolStore bobStore = new TestInMemorySignalProtocolStore();
+ SignalProtocolAddress bobAddress = new SignalProtocolAddress("+14152222222", 1);
initializeSessions(aliceStore, bobStore, bobAddress);
- ECKeyPair trustRoot = Curve.generateKeyPair();
- SenderCertificate senderCertificate = createCertificateFor(trustRoot, UUID.fromString("9d0652a3-dcc3-4d11-975f-74d61598733f"), "+14151111111", 1, aliceStore.getIdentityKeyPair().getPublicKey().getPublicKey(), 31337);
- SealedSessionCipher aliceCipher = new SealedSessionCipher(aliceStore, UUID.fromString("9d0652a3-dcc3-4d11-975f-74d61598733f"), "+14151111111", 1);
-
- byte[] ciphertext = aliceCipher.encrypt(bobAddress, senderCertificate, "smert za smert".getBytes());
-
-
- SealedSessionCipher bobCipher = new SealedSessionCipher(bobStore, UUID.fromString("e80f7bbe-5b94-471e-bd8c-2173654ea3d1"), "+14152222222", 1);
-
- DecryptionResult plaintext = bobCipher.decrypt(new CertificateValidator(trustRoot.getPublicKey()), ciphertext, 31335);
+ ECKeyPair trustRoot = Curve.generateKeyPair();
+ SenderCertificate senderCertificate =
+ createCertificateFor(
+ trustRoot,
+ UUID.fromString("9d0652a3-dcc3-4d11-975f-74d61598733f"),
+ "+14151111111",
+ 1,
+ aliceStore.getIdentityKeyPair().getPublicKey().getPublicKey(),
+ 31337);
+ SealedSessionCipher aliceCipher =
+ new SealedSessionCipher(
+ aliceStore, UUID.fromString("9d0652a3-dcc3-4d11-975f-74d61598733f"), "+14151111111", 1);
+
+ byte[] ciphertext =
+ aliceCipher.encrypt(bobAddress, senderCertificate, "smert za smert".getBytes());
+
+ SealedSessionCipher bobCipher =
+ new SealedSessionCipher(
+ bobStore, UUID.fromString("e80f7bbe-5b94-471e-bd8c-2173654ea3d1"), "+14152222222", 1);
+
+ DecryptionResult plaintext =
+ bobCipher.decrypt(new CertificateValidator(trustRoot.getPublicKey()), ciphertext, 31335);
assertEquals(new String(plaintext.getPaddedMessage()), "smert za smert");
assertEquals(plaintext.getSenderUuid(), "9d0652a3-dcc3-4d11-975f-74d61598733f");
- assertEquals(plaintext.getSenderAci().toServiceIdString(), "9d0652a3-dcc3-4d11-975f-74d61598733f");
+ assertEquals(
+ plaintext.getSenderAci().toServiceIdString(), "9d0652a3-dcc3-4d11-975f-74d61598733f");
assertEquals(plaintext.getSenderE164().get(), "+14151111111");
assertEquals(plaintext.getDeviceId(), 1);
}
public void testEncryptDecryptUntrusted() throws Exception {
TestInMemorySignalProtocolStore aliceStore = new TestInMemorySignalProtocolStore();
- TestInMemorySignalProtocolStore bobStore = new TestInMemorySignalProtocolStore();
- SignalProtocolAddress bobAddress = new SignalProtocolAddress("+14152222222", 1);
+ TestInMemorySignalProtocolStore bobStore = new TestInMemorySignalProtocolStore();
+ SignalProtocolAddress bobAddress = new SignalProtocolAddress("+14152222222", 1);
initializeSessions(aliceStore, bobStore, bobAddress);
- ECKeyPair trustRoot = Curve.generateKeyPair();
- ECKeyPair falseTrustRoot = Curve.generateKeyPair();
- SenderCertificate senderCertificate = createCertificateFor(falseTrustRoot, UUID.fromString("9d0652a3-dcc3-4d11-975f-74d61598733f"), "+14151111111", 1, aliceStore.getIdentityKeyPair().getPublicKey().getPublicKey(), 31337);
- SealedSessionCipher aliceCipher = new SealedSessionCipher(aliceStore, UUID.fromString("9d0652a3-dcc3-4d11-975f-74d61598733f"), "+14151111111", 1);
-
- byte[] ciphertext = aliceCipher.encrypt(bobAddress, senderCertificate, "\u0438 \u0432\u043E\u0442 \u044F".getBytes());
-
- SealedSessionCipher bobCipher = new SealedSessionCipher(bobStore, UUID.fromString("e80f7bbe-5b94-471e-bd8c-2173654ea3d1"), "+14152222222", 1);
+ ECKeyPair trustRoot = Curve.generateKeyPair();
+ ECKeyPair falseTrustRoot = Curve.generateKeyPair();
+ SenderCertificate senderCertificate =
+ createCertificateFor(
+ falseTrustRoot,
+ UUID.fromString("9d0652a3-dcc3-4d11-975f-74d61598733f"),
+ "+14151111111",
+ 1,
+ aliceStore.getIdentityKeyPair().getPublicKey().getPublicKey(),
+ 31337);
+ SealedSessionCipher aliceCipher =
+ new SealedSessionCipher(
+ aliceStore, UUID.fromString("9d0652a3-dcc3-4d11-975f-74d61598733f"), "+14151111111", 1);
+
+ byte[] ciphertext =
+ aliceCipher.encrypt(
+ bobAddress, senderCertificate, "\u0438 \u0432\u043E\u0442 \u044F".getBytes());
+
+ SealedSessionCipher bobCipher =
+ new SealedSessionCipher(
+ bobStore, UUID.fromString("e80f7bbe-5b94-471e-bd8c-2173654ea3d1"), "+14152222222", 1);
try {
bobCipher.decrypt(new CertificateValidator(trustRoot.getPublicKey()), ciphertext, 31335);
@@ -116,18 +160,31 @@ public void testEncryptDecryptUntrusted() throws Exception {
public void testEncryptDecryptExpired() throws Exception {
TestInMemorySignalProtocolStore aliceStore = new TestInMemorySignalProtocolStore();
- TestInMemorySignalProtocolStore bobStore = new TestInMemorySignalProtocolStore();
- SignalProtocolAddress bobAddress = new SignalProtocolAddress("+14152222222", 1);
+ TestInMemorySignalProtocolStore bobStore = new TestInMemorySignalProtocolStore();
+ SignalProtocolAddress bobAddress = new SignalProtocolAddress("+14152222222", 1);
initializeSessions(aliceStore, bobStore, bobAddress);
- ECKeyPair trustRoot = Curve.generateKeyPair();
- SenderCertificate senderCertificate = createCertificateFor(trustRoot, UUID.fromString("9d0652a3-dcc3-4d11-975f-74d61598733f"), "+14151111111", 1, aliceStore.getIdentityKeyPair().getPublicKey().getPublicKey(), 31337);
- SealedSessionCipher aliceCipher = new SealedSessionCipher(aliceStore, UUID.fromString("9d0652a3-dcc3-4d11-975f-74d61598733f"), "+14151111111", 1);
-
- byte[] ciphertext = aliceCipher.encrypt(bobAddress, senderCertificate, "\u0438 \u0432\u043E\u0442 \u044F".getBytes());
-
- SealedSessionCipher bobCipher = new SealedSessionCipher(bobStore, UUID.fromString("e80f7bbe-5b94-471e-bd8c-2173654ea3d1"), "+14152222222", 1);
+ ECKeyPair trustRoot = Curve.generateKeyPair();
+ SenderCertificate senderCertificate =
+ createCertificateFor(
+ trustRoot,
+ UUID.fromString("9d0652a3-dcc3-4d11-975f-74d61598733f"),
+ "+14151111111",
+ 1,
+ aliceStore.getIdentityKeyPair().getPublicKey().getPublicKey(),
+ 31337);
+ SealedSessionCipher aliceCipher =
+ new SealedSessionCipher(
+ aliceStore, UUID.fromString("9d0652a3-dcc3-4d11-975f-74d61598733f"), "+14151111111", 1);
+
+ byte[] ciphertext =
+ aliceCipher.encrypt(
+ bobAddress, senderCertificate, "\u0438 \u0432\u043E\u0442 \u044F".getBytes());
+
+ SealedSessionCipher bobCipher =
+ new SealedSessionCipher(
+ bobStore, UUID.fromString("e80f7bbe-5b94-471e-bd8c-2173654ea3d1"), "+14152222222", 1);
try {
bobCipher.decrypt(new CertificateValidator(trustRoot.getPublicKey()), ciphertext, 31338);
@@ -139,20 +196,31 @@ public void testEncryptDecryptExpired() throws Exception {
public void testEncryptFromWrongIdentity() throws Exception {
TestInMemorySignalProtocolStore aliceStore = new TestInMemorySignalProtocolStore();
- TestInMemorySignalProtocolStore bobStore = new TestInMemorySignalProtocolStore();
- SignalProtocolAddress bobAddress = new SignalProtocolAddress("+14152222222", 1);
+ TestInMemorySignalProtocolStore bobStore = new TestInMemorySignalProtocolStore();
+ SignalProtocolAddress bobAddress = new SignalProtocolAddress("+14152222222", 1);
initializeSessions(aliceStore, bobStore, bobAddress);
- ECKeyPair trustRoot = Curve.generateKeyPair();
- ECKeyPair randomKeyPair = Curve.generateKeyPair();
- SenderCertificate senderCertificate = createCertificateFor(trustRoot, UUID.fromString("9d0652a3-dcc3-4d11-975f-74d61598733f"), "+14151111111", 1, randomKeyPair.getPublicKey(), 31337);
- SealedSessionCipher aliceCipher = new SealedSessionCipher(aliceStore, UUID.fromString("9d0652a3-dcc3-4d11-975f-74d61598733f"), "+14151111111", 1);
-
- byte[] ciphertext = aliceCipher.encrypt(bobAddress, senderCertificate, "smert za smert".getBytes());
-
-
- SealedSessionCipher bobCipher = new SealedSessionCipher(bobStore, UUID.fromString("e80f7bbe-5b94-471e-bd8c-2173654ea3d1"), "+14152222222", 1);
+ ECKeyPair trustRoot = Curve.generateKeyPair();
+ ECKeyPair randomKeyPair = Curve.generateKeyPair();
+ SenderCertificate senderCertificate =
+ createCertificateFor(
+ trustRoot,
+ UUID.fromString("9d0652a3-dcc3-4d11-975f-74d61598733f"),
+ "+14151111111",
+ 1,
+ randomKeyPair.getPublicKey(),
+ 31337);
+ SealedSessionCipher aliceCipher =
+ new SealedSessionCipher(
+ aliceStore, UUID.fromString("9d0652a3-dcc3-4d11-975f-74d61598733f"), "+14151111111", 1);
+
+ byte[] ciphertext =
+ aliceCipher.encrypt(bobAddress, senderCertificate, "smert za smert".getBytes());
+
+ SealedSessionCipher bobCipher =
+ new SealedSessionCipher(
+ bobStore, UUID.fromString("e80f7bbe-5b94-471e-bd8c-2173654ea3d1"), "+14152222222", 1);
try {
bobCipher.decrypt(new CertificateValidator(trustRoot.getPublicKey()), ciphertext, 31335);
@@ -161,125 +229,276 @@ public void testEncryptFromWrongIdentity() throws Exception {
}
}
- public void testEncryptDecryptGroup() throws UntrustedIdentityException, InvalidKeyException, InvalidCertificateException, InvalidMessageException, InvalidVersionException, InvalidMetadataMessageException, InvalidRegistrationIdException, LegacyMessageException, NoSessionException, ProtocolDuplicateMessageException, ProtocolUntrustedIdentityException, ProtocolLegacyMessageException, ProtocolInvalidKeyException, InvalidMetadataVersionException, ProtocolInvalidVersionException, ProtocolInvalidMessageException, ProtocolInvalidKeyIdException, ProtocolNoSessionException, SelfSendException {
+ public void testEncryptDecryptGroup()
+ throws UntrustedIdentityException,
+ InvalidKeyException,
+ InvalidCertificateException,
+ InvalidMessageException,
+ InvalidVersionException,
+ InvalidMetadataMessageException,
+ InvalidRegistrationIdException,
+ LegacyMessageException,
+ NoSessionException,
+ ProtocolDuplicateMessageException,
+ ProtocolUntrustedIdentityException,
+ ProtocolLegacyMessageException,
+ ProtocolInvalidKeyException,
+ InvalidMetadataVersionException,
+ ProtocolInvalidVersionException,
+ ProtocolInvalidMessageException,
+ ProtocolInvalidKeyIdException,
+ ProtocolNoSessionException,
+ SelfSendException {
TestInMemorySignalProtocolStore aliceStore = new TestInMemorySignalProtocolStore();
- TestInMemorySignalProtocolStore bobStore = new TestInMemorySignalProtocolStore();
- SignalProtocolAddress bobAddress = new SignalProtocolAddress("e80f7bbe-5b94-471e-bd8c-2173654ea3d1", 1);
+ TestInMemorySignalProtocolStore bobStore = new TestInMemorySignalProtocolStore();
+ SignalProtocolAddress bobAddress =
+ new SignalProtocolAddress("e80f7bbe-5b94-471e-bd8c-2173654ea3d1", 1);
initializeSessions(aliceStore, bobStore, bobAddress);
- ECKeyPair trustRoot = Curve.generateKeyPair();
- SenderCertificate senderCertificate = createCertificateFor(trustRoot, UUID.fromString("9d0652a3-dcc3-4d11-975f-74d61598733f"), "+14151111111", 1, aliceStore.getIdentityKeyPair().getPublicKey().getPublicKey(), 31337);
- SealedSessionCipher aliceCipher = new SealedSessionCipher(aliceStore, UUID.fromString("9d0652a3-dcc3-4d11-975f-74d61598733f"), "+14151111111", 1);
-
- SignalProtocolAddress senderAddress = new SignalProtocolAddress("9d0652a3-dcc3-4d11-975f-74d61598733f", 1);
+ ECKeyPair trustRoot = Curve.generateKeyPair();
+ SenderCertificate senderCertificate =
+ createCertificateFor(
+ trustRoot,
+ UUID.fromString("9d0652a3-dcc3-4d11-975f-74d61598733f"),
+ "+14151111111",
+ 1,
+ aliceStore.getIdentityKeyPair().getPublicKey().getPublicKey(),
+ 31337);
+ SealedSessionCipher aliceCipher =
+ new SealedSessionCipher(
+ aliceStore, UUID.fromString("9d0652a3-dcc3-4d11-975f-74d61598733f"), "+14151111111", 1);
+
+ SignalProtocolAddress senderAddress =
+ new SignalProtocolAddress("9d0652a3-dcc3-4d11-975f-74d61598733f", 1);
UUID distributionId = UUID.fromString("d1d1d1d1-7000-11eb-b32a-33b8a8a487a6");
- SealedSessionCipher bobCipher = new SealedSessionCipher(bobStore, UUID.fromString("e80f7bbe-5b94-471e-bd8c-2173654ea3d1"), "+14152222222", 1);
+ SealedSessionCipher bobCipher =
+ new SealedSessionCipher(
+ bobStore, UUID.fromString("e80f7bbe-5b94-471e-bd8c-2173654ea3d1"), "+14152222222", 1);
GroupSessionBuilder aliceSessionBuilder = new GroupSessionBuilder(aliceStore);
- GroupSessionBuilder bobSessionBuilder = new GroupSessionBuilder(bobStore);
+ GroupSessionBuilder bobSessionBuilder = new GroupSessionBuilder(bobStore);
GroupCipher aliceGroupCipher = new GroupCipher(aliceStore, senderAddress);
- GroupCipher bobGroupCipher = new GroupCipher(bobStore, senderAddress);
+ GroupCipher bobGroupCipher = new GroupCipher(bobStore, senderAddress);
- SenderKeyDistributionMessage sentAliceDistributionMessage = aliceSessionBuilder.create(senderAddress, distributionId);
- SenderKeyDistributionMessage receivedAliceDistributionMessage = new SenderKeyDistributionMessage(sentAliceDistributionMessage.serialize());
+ SenderKeyDistributionMessage sentAliceDistributionMessage =
+ aliceSessionBuilder.create(senderAddress, distributionId);
+ SenderKeyDistributionMessage receivedAliceDistributionMessage =
+ new SenderKeyDistributionMessage(sentAliceDistributionMessage.serialize());
bobSessionBuilder.process(senderAddress, receivedAliceDistributionMessage);
- CiphertextMessage ciphertextFromAlice = aliceGroupCipher.encrypt(distributionId, "smert ze smert".getBytes());
+ CiphertextMessage ciphertextFromAlice =
+ aliceGroupCipher.encrypt(distributionId, "smert ze smert".getBytes());
- UnidentifiedSenderMessageContent usmcFromAlice = new UnidentifiedSenderMessageContent(ciphertextFromAlice, senderCertificate, UnidentifiedSenderMessageContent.CONTENT_HINT_IMPLICIT, Optional.of(new byte[]{42, 43}));
+ UnidentifiedSenderMessageContent usmcFromAlice =
+ new UnidentifiedSenderMessageContent(
+ ciphertextFromAlice,
+ senderCertificate,
+ UnidentifiedSenderMessageContent.CONTENT_HINT_IMPLICIT,
+ Optional.of(new byte[] {42, 43}));
- byte[] aliceMessage = aliceCipher.multiRecipientEncrypt(Arrays.asList(bobAddress), usmcFromAlice);
+ byte[] aliceMessage =
+ aliceCipher.multiRecipientEncrypt(Arrays.asList(bobAddress), usmcFromAlice);
byte[] bobMessage = SealedSessionCipher.multiRecipientMessageForSingleRecipient(aliceMessage);
- DecryptionResult plaintext = bobCipher.decrypt(new CertificateValidator(trustRoot.getPublicKey()), bobMessage, 31335);
+ DecryptionResult plaintext =
+ bobCipher.decrypt(new CertificateValidator(trustRoot.getPublicKey()), bobMessage, 31335);
assertEquals(new String(plaintext.getPaddedMessage()), "smert ze smert");
assertEquals(plaintext.getSenderUuid(), "9d0652a3-dcc3-4d11-975f-74d61598733f");
assertEquals(plaintext.getSenderE164().get(), "+14151111111");
assertEquals(plaintext.getDeviceId(), 1);
- assertTrue(Arrays.equals(plaintext.getGroupId().get(), new byte[]{42, 43}));
+ assertTrue(Arrays.equals(plaintext.getGroupId().get(), new byte[] {42, 43}));
}
-
- public void testEncryptGroupWithBadRegistrationId() throws UntrustedIdentityException, InvalidKeyException, InvalidCertificateException, InvalidMessageException, InvalidMetadataMessageException, InvalidRegistrationIdException, LegacyMessageException, NoSessionException, ProtocolDuplicateMessageException, ProtocolUntrustedIdentityException, ProtocolLegacyMessageException, ProtocolInvalidKeyException, InvalidMetadataVersionException, ProtocolInvalidVersionException, ProtocolInvalidMessageException, ProtocolInvalidKeyIdException, ProtocolNoSessionException, SelfSendException {
+ public void testEncryptGroupWithBadRegistrationId()
+ throws UntrustedIdentityException,
+ InvalidKeyException,
+ InvalidCertificateException,
+ InvalidMessageException,
+ InvalidMetadataMessageException,
+ InvalidRegistrationIdException,
+ LegacyMessageException,
+ NoSessionException,
+ ProtocolDuplicateMessageException,
+ ProtocolUntrustedIdentityException,
+ ProtocolLegacyMessageException,
+ ProtocolInvalidKeyException,
+ InvalidMetadataVersionException,
+ ProtocolInvalidVersionException,
+ ProtocolInvalidMessageException,
+ ProtocolInvalidKeyIdException,
+ ProtocolNoSessionException,
+ SelfSendException {
TestInMemorySignalProtocolStore aliceStore = new TestInMemorySignalProtocolStore();
- TestInMemorySignalProtocolStore bobStore = new TestInMemorySignalProtocolStore();
- SignalProtocolAddress bobAddress = new SignalProtocolAddress("e80f7bbe-5b94-471e-bd8c-2173654ea3d1", 1);
+ TestInMemorySignalProtocolStore bobStore = new TestInMemorySignalProtocolStore();
+ SignalProtocolAddress bobAddress =
+ new SignalProtocolAddress("e80f7bbe-5b94-471e-bd8c-2173654ea3d1", 1);
- ECKeyPair bobPreKey = Curve.generateKeyPair();
- IdentityKeyPair bobIdentityKey = bobStore.getIdentityKeyPair();
+ ECKeyPair bobPreKey = Curve.generateKeyPair();
+ IdentityKeyPair bobIdentityKey = bobStore.getIdentityKeyPair();
SignedPreKeyRecord bobSignedPreKey = generateSignedPreKey(bobIdentityKey, 2);
KyberPreKeyRecord bobKyberPreKey = generateKyberPreKey(bobIdentityKey, 12);
- PreKeyBundle bobBundle = new PreKeyBundle(0x4000, 1, 1, bobPreKey.getPublicKey(), 2, bobSignedPreKey.getKeyPair().getPublicKey(), bobSignedPreKey.getSignature(), bobIdentityKey.getPublicKey(), 12, bobKyberPreKey.getKeyPair().getPublicKey(), bobKyberPreKey.getSignature());
+ PreKeyBundle bobBundle =
+ new PreKeyBundle(
+ 0x4000,
+ 1,
+ 1,
+ bobPreKey.getPublicKey(),
+ 2,
+ bobSignedPreKey.getKeyPair().getPublicKey(),
+ bobSignedPreKey.getSignature(),
+ bobIdentityKey.getPublicKey(),
+ 12,
+ bobKyberPreKey.getKeyPair().getPublicKey(),
+ bobKyberPreKey.getSignature());
SessionBuilder aliceSessionBuilder = new SessionBuilder(aliceStore, bobAddress);
aliceSessionBuilder.process(bobBundle);
- ECKeyPair trustRoot = Curve.generateKeyPair();
- SenderCertificate senderCertificate = createCertificateFor(trustRoot, UUID.fromString("9d0652a3-dcc3-4d11-975f-74d61598733f"), "+14151111111", 1, aliceStore.getIdentityKeyPair().getPublicKey().getPublicKey(), 31337);
- SealedSessionCipher aliceCipher = new SealedSessionCipher(aliceStore, UUID.fromString("9d0652a3-dcc3-4d11-975f-74d61598733f"), "+14151111111", 1);
-
- SignalProtocolAddress senderAddress = new SignalProtocolAddress("9d0652a3-dcc3-4d11-975f-74d61598733f", 1);
+ ECKeyPair trustRoot = Curve.generateKeyPair();
+ SenderCertificate senderCertificate =
+ createCertificateFor(
+ trustRoot,
+ UUID.fromString("9d0652a3-dcc3-4d11-975f-74d61598733f"),
+ "+14151111111",
+ 1,
+ aliceStore.getIdentityKeyPair().getPublicKey().getPublicKey(),
+ 31337);
+ SealedSessionCipher aliceCipher =
+ new SealedSessionCipher(
+ aliceStore, UUID.fromString("9d0652a3-dcc3-4d11-975f-74d61598733f"), "+14151111111", 1);
+
+ SignalProtocolAddress senderAddress =
+ new SignalProtocolAddress("9d0652a3-dcc3-4d11-975f-74d61598733f", 1);
UUID distributionId = UUID.fromString("d1d1d1d1-7000-11eb-b32a-33b8a8a487a6");
GroupSessionBuilder aliceGroupSessionBuilder = new GroupSessionBuilder(aliceStore);
- SenderKeyDistributionMessage sentAliceDistributionMessage = aliceGroupSessionBuilder.create(senderAddress, distributionId);
+ SenderKeyDistributionMessage sentAliceDistributionMessage =
+ aliceGroupSessionBuilder.create(senderAddress, distributionId);
GroupCipher aliceGroupCipher = new GroupCipher(aliceStore, senderAddress);
- CiphertextMessage ciphertextFromAlice = aliceGroupCipher.encrypt(distributionId, "smert ze smert".getBytes());
+ CiphertextMessage ciphertextFromAlice =
+ aliceGroupCipher.encrypt(distributionId, "smert ze smert".getBytes());
- UnidentifiedSenderMessageContent usmcFromAlice = new UnidentifiedSenderMessageContent(ciphertextFromAlice, senderCertificate, UnidentifiedSenderMessageContent.CONTENT_HINT_IMPLICIT, Optional.of(new byte[]{42, 43}));
+ UnidentifiedSenderMessageContent usmcFromAlice =
+ new UnidentifiedSenderMessageContent(
+ ciphertextFromAlice,
+ senderCertificate,
+ UnidentifiedSenderMessageContent.CONTENT_HINT_IMPLICIT,
+ Optional.of(new byte[] {42, 43}));
try {
- byte[] aliceMessage = aliceCipher.multiRecipientEncrypt(Arrays.asList(bobAddress), usmcFromAlice);
+ byte[] aliceMessage =
+ aliceCipher.multiRecipientEncrypt(Arrays.asList(bobAddress), usmcFromAlice);
fail("should have thrown");
} catch (InvalidRegistrationIdException e) {
assertEquals(e.getAddress(), bobAddress);
}
}
- public void testEncryptGroupWithManyRecipients() throws UntrustedIdentityException, InvalidKeyException, InvalidCertificateException, InvalidMessageException, InvalidMetadataMessageException, InvalidRegistrationIdException, LegacyMessageException, NoSessionException, ProtocolDuplicateMessageException, ProtocolUntrustedIdentityException, ProtocolLegacyMessageException, ProtocolInvalidKeyException, InvalidMetadataVersionException, ProtocolInvalidVersionException, ProtocolInvalidMessageException, ProtocolInvalidKeyIdException, ProtocolNoSessionException, SelfSendException {
+ public void testEncryptGroupWithManyRecipients()
+ throws UntrustedIdentityException,
+ InvalidKeyException,
+ InvalidCertificateException,
+ InvalidMessageException,
+ InvalidMetadataMessageException,
+ InvalidRegistrationIdException,
+ LegacyMessageException,
+ NoSessionException,
+ ProtocolDuplicateMessageException,
+ ProtocolUntrustedIdentityException,
+ ProtocolLegacyMessageException,
+ ProtocolInvalidKeyException,
+ InvalidMetadataVersionException,
+ ProtocolInvalidVersionException,
+ ProtocolInvalidMessageException,
+ ProtocolInvalidKeyIdException,
+ ProtocolNoSessionException,
+ SelfSendException {
TestInMemorySignalProtocolStore aliceStore = new TestInMemorySignalProtocolStore();
- TestInMemorySignalProtocolStore bobStore = new TestInMemorySignalProtocolStore();
+ TestInMemorySignalProtocolStore bobStore = new TestInMemorySignalProtocolStore();
TestInMemorySignalProtocolStore carolStore = new TestInMemorySignalProtocolStore();
- SignalProtocolAddress bobAddress = new SignalProtocolAddress("e80f7bbe-5b94-471e-bd8c-2173654ea3d1", 1);
- SignalProtocolAddress carolAddress = new SignalProtocolAddress("38381c3b-2606-4ca7-9310-7cb927f2ab4a", 1);
+ SignalProtocolAddress bobAddress =
+ new SignalProtocolAddress("e80f7bbe-5b94-471e-bd8c-2173654ea3d1", 1);
+ SignalProtocolAddress carolAddress =
+ new SignalProtocolAddress("38381c3b-2606-4ca7-9310-7cb927f2ab4a", 1);
- ECKeyPair bobPreKey = Curve.generateKeyPair();
- IdentityKeyPair bobIdentityKey = bobStore.getIdentityKeyPair();
+ ECKeyPair bobPreKey = Curve.generateKeyPair();
+ IdentityKeyPair bobIdentityKey = bobStore.getIdentityKeyPair();
SignedPreKeyRecord bobSignedPreKey = generateSignedPreKey(bobIdentityKey, 2);
- KyberPreKeyRecord bobKyberPreKey = generateKyberPreKey(bobIdentityKey, 12);
+ KyberPreKeyRecord bobKyberPreKey = generateKyberPreKey(bobIdentityKey, 12);
- PreKeyBundle bobBundle = new PreKeyBundle(0x1234, 1, 1, bobPreKey.getPublicKey(), 2, bobSignedPreKey.getKeyPair().getPublicKey(), bobSignedPreKey.getSignature(), bobIdentityKey.getPublicKey(), 12, bobKyberPreKey.getKeyPair().getPublicKey(), bobKyberPreKey.getSignature());
+ PreKeyBundle bobBundle =
+ new PreKeyBundle(
+ 0x1234,
+ 1,
+ 1,
+ bobPreKey.getPublicKey(),
+ 2,
+ bobSignedPreKey.getKeyPair().getPublicKey(),
+ bobSignedPreKey.getSignature(),
+ bobIdentityKey.getPublicKey(),
+ 12,
+ bobKyberPreKey.getKeyPair().getPublicKey(),
+ bobKyberPreKey.getSignature());
SessionBuilder aliceSessionBuilderForBob = new SessionBuilder(aliceStore, bobAddress);
aliceSessionBuilderForBob.process(bobBundle);
- ECKeyPair carolPreKey = Curve.generateKeyPair();
- IdentityKeyPair carolIdentityKey = carolStore.getIdentityKeyPair();
+ ECKeyPair carolPreKey = Curve.generateKeyPair();
+ IdentityKeyPair carolIdentityKey = carolStore.getIdentityKeyPair();
SignedPreKeyRecord carolSignedPreKey = generateSignedPreKey(carolIdentityKey, 2);
- KyberPreKeyRecord carolKyberPreKey = generateKyberPreKey(carolIdentityKey, 12);
-
- PreKeyBundle carolBundle = new PreKeyBundle(0x1111, 1, 1, carolPreKey.getPublicKey(), 2, carolSignedPreKey.getKeyPair().getPublicKey(), carolSignedPreKey.getSignature(), carolIdentityKey.getPublicKey(), 12, carolKyberPreKey.getKeyPair().getPublicKey(), carolKyberPreKey.getSignature());
+ KyberPreKeyRecord carolKyberPreKey = generateKyberPreKey(carolIdentityKey, 12);
+
+ PreKeyBundle carolBundle =
+ new PreKeyBundle(
+ 0x1111,
+ 1,
+ 1,
+ carolPreKey.getPublicKey(),
+ 2,
+ carolSignedPreKey.getKeyPair().getPublicKey(),
+ carolSignedPreKey.getSignature(),
+ carolIdentityKey.getPublicKey(),
+ 12,
+ carolKyberPreKey.getKeyPair().getPublicKey(),
+ carolKyberPreKey.getSignature());
SessionBuilder aliceSessionBuilderForCarol = new SessionBuilder(aliceStore, carolAddress);
aliceSessionBuilderForCarol.process(carolBundle);
- ECKeyPair trustRoot = Curve.generateKeyPair();
- SenderCertificate senderCertificate = createCertificateFor(trustRoot, UUID.fromString("9d0652a3-dcc3-4d11-975f-74d61598733f"), "+14151111111", 1, aliceStore.getIdentityKeyPair().getPublicKey().getPublicKey(), 31337);
- SealedSessionCipher aliceCipher = new SealedSessionCipher(aliceStore, UUID.fromString("9d0652a3-dcc3-4d11-975f-74d61598733f"), "+14151111111", 1);
-
- SignalProtocolAddress senderAddress = new SignalProtocolAddress("9d0652a3-dcc3-4d11-975f-74d61598733f", 1);
+ ECKeyPair trustRoot = Curve.generateKeyPair();
+ SenderCertificate senderCertificate =
+ createCertificateFor(
+ trustRoot,
+ UUID.fromString("9d0652a3-dcc3-4d11-975f-74d61598733f"),
+ "+14151111111",
+ 1,
+ aliceStore.getIdentityKeyPair().getPublicKey().getPublicKey(),
+ 31337);
+ SealedSessionCipher aliceCipher =
+ new SealedSessionCipher(
+ aliceStore, UUID.fromString("9d0652a3-dcc3-4d11-975f-74d61598733f"), "+14151111111", 1);
+
+ SignalProtocolAddress senderAddress =
+ new SignalProtocolAddress("9d0652a3-dcc3-4d11-975f-74d61598733f", 1);
UUID distributionId = UUID.fromString("d1d1d1d1-7000-11eb-b32a-33b8a8a487a6");
GroupSessionBuilder aliceGroupSessionBuilder = new GroupSessionBuilder(aliceStore);
- SenderKeyDistributionMessage sentAliceDistributionMessage = aliceGroupSessionBuilder.create(senderAddress, distributionId);
+ SenderKeyDistributionMessage sentAliceDistributionMessage =
+ aliceGroupSessionBuilder.create(senderAddress, distributionId);
GroupCipher aliceGroupCipher = new GroupCipher(aliceStore, senderAddress);
- CiphertextMessage ciphertextFromAlice = aliceGroupCipher.encrypt(distributionId, "smert ze smert".getBytes());
+ CiphertextMessage ciphertextFromAlice =
+ aliceGroupCipher.encrypt(distributionId, "smert ze smert".getBytes());
- UnidentifiedSenderMessageContent usmcFromAlice = new UnidentifiedSenderMessageContent(ciphertextFromAlice, senderCertificate, UnidentifiedSenderMessageContent.CONTENT_HINT_IMPLICIT, Optional.of(new byte[]{42, 43}));
+ UnidentifiedSenderMessageContent usmcFromAlice =
+ new UnidentifiedSenderMessageContent(
+ ciphertextFromAlice,
+ senderCertificate,
+ UnidentifiedSenderMessageContent.CONTENT_HINT_IMPLICIT,
+ Optional.of(new byte[] {42, 43}));
ArrayList addresses = new ArrayList<>();
for (int i = 0; i < 1000; ++i) {
@@ -292,35 +511,84 @@ public void testEncryptGroupWithManyRecipients() throws UntrustedIdentityExcepti
byte[] aliceMessage = aliceCipher.multiRecipientEncrypt(addresses, usmcFromAlice);
}
- public void testEncryptGroupWithMissingSession() throws UntrustedIdentityException, InvalidKeyException, InvalidCertificateException, InvalidMessageException, InvalidMetadataMessageException, InvalidRegistrationIdException, LegacyMessageException, NoSessionException, ProtocolDuplicateMessageException, ProtocolUntrustedIdentityException, ProtocolLegacyMessageException, ProtocolInvalidKeyException, InvalidMetadataVersionException, ProtocolInvalidVersionException, ProtocolInvalidMessageException, ProtocolInvalidKeyIdException, ProtocolNoSessionException, SelfSendException {
+ public void testEncryptGroupWithMissingSession()
+ throws UntrustedIdentityException,
+ InvalidKeyException,
+ InvalidCertificateException,
+ InvalidMessageException,
+ InvalidMetadataMessageException,
+ InvalidRegistrationIdException,
+ LegacyMessageException,
+ NoSessionException,
+ ProtocolDuplicateMessageException,
+ ProtocolUntrustedIdentityException,
+ ProtocolLegacyMessageException,
+ ProtocolInvalidKeyException,
+ InvalidMetadataVersionException,
+ ProtocolInvalidVersionException,
+ ProtocolInvalidMessageException,
+ ProtocolInvalidKeyIdException,
+ ProtocolNoSessionException,
+ SelfSendException {
TestInMemorySignalProtocolStore aliceStore = new TestInMemorySignalProtocolStore();
- TestInMemorySignalProtocolStore bobStore = new TestInMemorySignalProtocolStore();
- SignalProtocolAddress bobAddress = new SignalProtocolAddress("e80f7bbe-5b94-471e-bd8c-2173654ea3d1", 1);
- SignalProtocolAddress carolAddress = new SignalProtocolAddress("38381c3b-2606-4ca7-9310-7cb927f2ab4a", 1);
-
- ECKeyPair bobPreKey = Curve.generateKeyPair();
- IdentityKeyPair bobIdentityKey = bobStore.getIdentityKeyPair();
+ TestInMemorySignalProtocolStore bobStore = new TestInMemorySignalProtocolStore();
+ SignalProtocolAddress bobAddress =
+ new SignalProtocolAddress("e80f7bbe-5b94-471e-bd8c-2173654ea3d1", 1);
+ SignalProtocolAddress carolAddress =
+ new SignalProtocolAddress("38381c3b-2606-4ca7-9310-7cb927f2ab4a", 1);
+
+ ECKeyPair bobPreKey = Curve.generateKeyPair();
+ IdentityKeyPair bobIdentityKey = bobStore.getIdentityKeyPair();
SignedPreKeyRecord bobSignedPreKey = generateSignedPreKey(bobIdentityKey, 2);
- KyberPreKeyRecord bobKyberPreKey = generateKyberPreKey(bobIdentityKey, 12);
+ KyberPreKeyRecord bobKyberPreKey = generateKyberPreKey(bobIdentityKey, 12);
- PreKeyBundle bobBundle = new PreKeyBundle(0x1234, 1, 1, bobPreKey.getPublicKey(), 2, bobSignedPreKey.getKeyPair().getPublicKey(), bobSignedPreKey.getSignature(), bobIdentityKey.getPublicKey(), 12, bobKyberPreKey.getKeyPair().getPublicKey(), bobKyberPreKey.getSignature());
+ PreKeyBundle bobBundle =
+ new PreKeyBundle(
+ 0x1234,
+ 1,
+ 1,
+ bobPreKey.getPublicKey(),
+ 2,
+ bobSignedPreKey.getKeyPair().getPublicKey(),
+ bobSignedPreKey.getSignature(),
+ bobIdentityKey.getPublicKey(),
+ 12,
+ bobKyberPreKey.getKeyPair().getPublicKey(),
+ bobKyberPreKey.getSignature());
SessionBuilder aliceSessionBuilderForBob = new SessionBuilder(aliceStore, bobAddress);
aliceSessionBuilderForBob.process(bobBundle);
- ECKeyPair trustRoot = Curve.generateKeyPair();
- SenderCertificate senderCertificate = createCertificateFor(trustRoot, UUID.fromString("9d0652a3-dcc3-4d11-975f-74d61598733f"), "+14151111111", 1, aliceStore.getIdentityKeyPair().getPublicKey().getPublicKey(), 31337);
- SealedSessionCipher aliceCipher = new SealedSessionCipher(aliceStore, UUID.fromString("9d0652a3-dcc3-4d11-975f-74d61598733f"), "+14151111111", 1);
-
- SignalProtocolAddress senderAddress = new SignalProtocolAddress("9d0652a3-dcc3-4d11-975f-74d61598733f", 1);
+ ECKeyPair trustRoot = Curve.generateKeyPair();
+ SenderCertificate senderCertificate =
+ createCertificateFor(
+ trustRoot,
+ UUID.fromString("9d0652a3-dcc3-4d11-975f-74d61598733f"),
+ "+14151111111",
+ 1,
+ aliceStore.getIdentityKeyPair().getPublicKey().getPublicKey(),
+ 31337);
+ SealedSessionCipher aliceCipher =
+ new SealedSessionCipher(
+ aliceStore, UUID.fromString("9d0652a3-dcc3-4d11-975f-74d61598733f"), "+14151111111", 1);
+
+ SignalProtocolAddress senderAddress =
+ new SignalProtocolAddress("9d0652a3-dcc3-4d11-975f-74d61598733f", 1);
UUID distributionId = UUID.fromString("d1d1d1d1-7000-11eb-b32a-33b8a8a487a6");
GroupSessionBuilder aliceGroupSessionBuilder = new GroupSessionBuilder(aliceStore);
- SenderKeyDistributionMessage sentAliceDistributionMessage = aliceGroupSessionBuilder.create(senderAddress, distributionId);
+ SenderKeyDistributionMessage sentAliceDistributionMessage =
+ aliceGroupSessionBuilder.create(senderAddress, distributionId);
GroupCipher aliceGroupCipher = new GroupCipher(aliceStore, senderAddress);
- CiphertextMessage ciphertextFromAlice = aliceGroupCipher.encrypt(distributionId, "smert ze smert".getBytes());
+ CiphertextMessage ciphertextFromAlice =
+ aliceGroupCipher.encrypt(distributionId, "smert ze smert".getBytes());
- UnidentifiedSenderMessageContent usmcFromAlice = new UnidentifiedSenderMessageContent(ciphertextFromAlice, senderCertificate, UnidentifiedSenderMessageContent.CONTENT_HINT_IMPLICIT, Optional.of(new byte[]{42, 43}));
+ UnidentifiedSenderMessageContent usmcFromAlice =
+ new UnidentifiedSenderMessageContent(
+ ciphertextFromAlice,
+ senderCertificate,
+ UnidentifiedSenderMessageContent.CONTENT_HINT_IMPLICIT,
+ Optional.of(new byte[] {42, 43}));
ArrayList addresses = new ArrayList<>();
for (int i = 0; i < 1000; ++i) {
@@ -337,35 +605,73 @@ public void testEncryptGroupWithMissingSession() throws UntrustedIdentityExcepti
}
}
- public void testProtocolException() throws UntrustedIdentityException, InvalidKeyException, InvalidCertificateException, InvalidMessageException, InvalidMetadataMessageException, InvalidRegistrationIdException, LegacyMessageException, NoSessionException, ProtocolDuplicateMessageException, ProtocolUntrustedIdentityException, ProtocolLegacyMessageException, ProtocolInvalidKeyException, InvalidMetadataVersionException, ProtocolInvalidVersionException, ProtocolInvalidMessageException, ProtocolInvalidKeyIdException, ProtocolNoSessionException, SelfSendException {
+ public void testProtocolException()
+ throws UntrustedIdentityException,
+ InvalidKeyException,
+ InvalidCertificateException,
+ InvalidMessageException,
+ InvalidMetadataMessageException,
+ InvalidRegistrationIdException,
+ LegacyMessageException,
+ NoSessionException,
+ ProtocolDuplicateMessageException,
+ ProtocolUntrustedIdentityException,
+ ProtocolLegacyMessageException,
+ ProtocolInvalidKeyException,
+ InvalidMetadataVersionException,
+ ProtocolInvalidVersionException,
+ ProtocolInvalidMessageException,
+ ProtocolInvalidKeyIdException,
+ ProtocolNoSessionException,
+ SelfSendException {
TestInMemorySignalProtocolStore aliceStore = new TestInMemorySignalProtocolStore();
- TestInMemorySignalProtocolStore bobStore = new TestInMemorySignalProtocolStore();
- SignalProtocolAddress bobAddress = new SignalProtocolAddress("e80f7bbe-5b94-471e-bd8c-2173654ea3d1", 1);
+ TestInMemorySignalProtocolStore bobStore = new TestInMemorySignalProtocolStore();
+ SignalProtocolAddress bobAddress =
+ new SignalProtocolAddress("e80f7bbe-5b94-471e-bd8c-2173654ea3d1", 1);
initializeSessions(aliceStore, bobStore, bobAddress);
- ECKeyPair trustRoot = Curve.generateKeyPair();
- SenderCertificate senderCertificate = createCertificateFor(trustRoot, UUID.fromString("9d0652a3-dcc3-4d11-975f-74d61598733f"), "+14151111111", 1, aliceStore.getIdentityKeyPair().getPublicKey().getPublicKey(), 31337);
- SealedSessionCipher aliceCipher = new SealedSessionCipher(aliceStore, UUID.fromString("9d0652a3-dcc3-4d11-975f-74d61598733f"), "+14151111111", 1);
-
- SignalProtocolAddress senderAddress = new SignalProtocolAddress("9d0652a3-dcc3-4d11-975f-74d61598733f", 1);
+ ECKeyPair trustRoot = Curve.generateKeyPair();
+ SenderCertificate senderCertificate =
+ createCertificateFor(
+ trustRoot,
+ UUID.fromString("9d0652a3-dcc3-4d11-975f-74d61598733f"),
+ "+14151111111",
+ 1,
+ aliceStore.getIdentityKeyPair().getPublicKey().getPublicKey(),
+ 31337);
+ SealedSessionCipher aliceCipher =
+ new SealedSessionCipher(
+ aliceStore, UUID.fromString("9d0652a3-dcc3-4d11-975f-74d61598733f"), "+14151111111", 1);
+
+ SignalProtocolAddress senderAddress =
+ new SignalProtocolAddress("9d0652a3-dcc3-4d11-975f-74d61598733f", 1);
UUID distributionId = UUID.fromString("d1d1d1d1-7000-11eb-b32a-33b8a8a487a6");
- SealedSessionCipher bobCipher = new SealedSessionCipher(bobStore, UUID.fromString("e80f7bbe-5b94-471e-bd8c-2173654ea3d1"), "+14152222222", 1);
+ SealedSessionCipher bobCipher =
+ new SealedSessionCipher(
+ bobStore, UUID.fromString("e80f7bbe-5b94-471e-bd8c-2173654ea3d1"), "+14152222222", 1);
GroupSessionBuilder aliceSessionBuilder = new GroupSessionBuilder(aliceStore);
- GroupSessionBuilder bobSessionBuilder = new GroupSessionBuilder(bobStore);
+ GroupSessionBuilder bobSessionBuilder = new GroupSessionBuilder(bobStore);
GroupCipher aliceGroupCipher = new GroupCipher(aliceStore, senderAddress);
- GroupCipher bobGroupCipher = new GroupCipher(bobStore, senderAddress);
+ GroupCipher bobGroupCipher = new GroupCipher(bobStore, senderAddress);
// Send a group message without sending the distribution ID first.
aliceSessionBuilder.create(senderAddress, distributionId);
- CiphertextMessage ciphertextFromAlice = aliceGroupCipher.encrypt(distributionId, "smert ze smert".getBytes());
-
- UnidentifiedSenderMessageContent usmcFromAlice = new UnidentifiedSenderMessageContent(ciphertextFromAlice, senderCertificate, UnidentifiedSenderMessageContent.CONTENT_HINT_RESENDABLE, Optional.of(new byte[]{42, 1}));
-
- byte[] aliceMessage = aliceCipher.multiRecipientEncrypt(Arrays.asList(bobAddress), usmcFromAlice);
+ CiphertextMessage ciphertextFromAlice =
+ aliceGroupCipher.encrypt(distributionId, "smert ze smert".getBytes());
+
+ UnidentifiedSenderMessageContent usmcFromAlice =
+ new UnidentifiedSenderMessageContent(
+ ciphertextFromAlice,
+ senderCertificate,
+ UnidentifiedSenderMessageContent.CONTENT_HINT_RESENDABLE,
+ Optional.of(new byte[] {42, 1}));
+
+ byte[] aliceMessage =
+ aliceCipher.multiRecipientEncrypt(Arrays.asList(bobAddress), usmcFromAlice);
byte[] bobMessage = SealedSessionCipher.multiRecipientMessageForSingleRecipient(aliceMessage);
try {
@@ -376,77 +682,145 @@ public void testProtocolException() throws UntrustedIdentityException, InvalidKe
assertEquals(e.getSenderAci().toServiceIdString(), "9d0652a3-dcc3-4d11-975f-74d61598733f");
assertEquals(e.getSenderDevice(), 1);
assertEquals(e.getContentHint(), UnidentifiedSenderMessageContent.CONTENT_HINT_RESENDABLE);
- assertEquals(Hex.toStringCondensed(e.getGroupId().get()), Hex.toStringCondensed(new byte[]{42, 1}));
+ assertEquals(
+ Hex.toStringCondensed(e.getGroupId().get()), Hex.toStringCondensed(new byte[] {42, 1}));
}
}
- public void testDecryptionErrorMessage() throws InvalidCertificateException, InvalidKeyException, InvalidMessageException, InvalidMetadataMessageException, InvalidMetadataVersionException, ProtocolDuplicateMessageException, ProtocolInvalidKeyException, ProtocolInvalidKeyIdException, ProtocolInvalidMessageException, ProtocolInvalidVersionException, ProtocolLegacyMessageException, ProtocolNoSessionException, ProtocolUntrustedIdentityException, SelfSendException, UntrustedIdentityException {
+ public void testDecryptionErrorMessage()
+ throws InvalidCertificateException,
+ InvalidKeyException,
+ InvalidMessageException,
+ InvalidMetadataMessageException,
+ InvalidMetadataVersionException,
+ NoSessionException,
+ ProtocolDuplicateMessageException,
+ ProtocolInvalidKeyException,
+ ProtocolInvalidKeyIdException,
+ ProtocolInvalidMessageException,
+ ProtocolInvalidVersionException,
+ ProtocolLegacyMessageException,
+ ProtocolNoSessionException,
+ ProtocolUntrustedIdentityException,
+ SelfSendException,
+ UntrustedIdentityException {
TestInMemorySignalProtocolStore aliceStore = new TestInMemorySignalProtocolStore();
- TestInMemorySignalProtocolStore bobStore = new TestInMemorySignalProtocolStore();
- SignalProtocolAddress bobAddress = new SignalProtocolAddress("+14152222222", 1);
+ TestInMemorySignalProtocolStore bobStore = new TestInMemorySignalProtocolStore();
+ SignalProtocolAddress bobAddress = new SignalProtocolAddress("+14152222222", 1);
initializeSessions(aliceStore, bobStore, bobAddress);
- ECKeyPair trustRoot = Curve.generateKeyPair();
+ ECKeyPair trustRoot = Curve.generateKeyPair();
CertificateValidator certificateValidator = new CertificateValidator(trustRoot.getPublicKey());
- SenderCertificate senderCertificate = createCertificateFor(trustRoot, UUID.fromString("9d0652a3-dcc3-4d11-975f-74d61598733f"), "+14151111111", 1, aliceStore.getIdentityKeyPair().getPublicKey().getPublicKey(), 31337);
- SealedSessionCipher aliceCipher = new SealedSessionCipher(aliceStore, UUID.fromString("9d0652a3-dcc3-4d11-975f-74d61598733f"), "+14151111111", 1);
+ SenderCertificate senderCertificate =
+ createCertificateFor(
+ trustRoot,
+ UUID.fromString("9d0652a3-dcc3-4d11-975f-74d61598733f"),
+ "+14151111111",
+ 1,
+ aliceStore.getIdentityKeyPair().getPublicKey().getPublicKey(),
+ 31337);
+ SealedSessionCipher aliceCipher =
+ new SealedSessionCipher(
+ aliceStore, UUID.fromString("9d0652a3-dcc3-4d11-975f-74d61598733f"), "+14151111111", 1);
// Send a message from Alice to Bob to set up the session.
- byte[] ciphertext = aliceCipher.encrypt(bobAddress, senderCertificate, "smert za smert".getBytes());
+ byte[] ciphertext =
+ aliceCipher.encrypt(bobAddress, senderCertificate, "smert za smert".getBytes());
- SealedSessionCipher bobCipher = new SealedSessionCipher(bobStore, UUID.fromString("e80f7bbe-5b94-471e-bd8c-2173654ea3d1"), "+14152222222", 1);
+ SealedSessionCipher bobCipher =
+ new SealedSessionCipher(
+ bobStore, UUID.fromString("e80f7bbe-5b94-471e-bd8c-2173654ea3d1"), "+14152222222", 1);
bobCipher.decrypt(certificateValidator, ciphertext, 31335);
// Pretend Bob's reply fails to decrypt.
- SignalProtocolAddress aliceAddress = new SignalProtocolAddress("9d0652a3-dcc3-4d11-975f-74d61598733f", 1);
+ SignalProtocolAddress aliceAddress =
+ new SignalProtocolAddress("9d0652a3-dcc3-4d11-975f-74d61598733f", 1);
SessionCipher bobUnsealedCipher = new SessionCipher(bobStore, aliceAddress);
CiphertextMessage bobMessage = bobUnsealedCipher.encrypt("reply".getBytes());
- DecryptionErrorMessage errorMessage = DecryptionErrorMessage.forOriginalMessage(bobMessage.serialize(), bobMessage.getType(), 408, bobAddress.getDeviceId());
+ DecryptionErrorMessage errorMessage =
+ DecryptionErrorMessage.forOriginalMessage(
+ bobMessage.serialize(), bobMessage.getType(), 408, bobAddress.getDeviceId());
PlaintextContent errorMessageContent = new PlaintextContent(errorMessage);
- UnidentifiedSenderMessageContent errorMessageUsmc = new UnidentifiedSenderMessageContent(errorMessageContent, senderCertificate, UnidentifiedSenderMessageContent.CONTENT_HINT_IMPLICIT, Optional.empty());
+ UnidentifiedSenderMessageContent errorMessageUsmc =
+ new UnidentifiedSenderMessageContent(
+ errorMessageContent,
+ senderCertificate,
+ UnidentifiedSenderMessageContent.CONTENT_HINT_IMPLICIT,
+ Optional.empty());
byte[] errorMessageCiphertext = aliceCipher.encrypt(bobAddress, errorMessageUsmc);
- DecryptionResult result = bobCipher.decrypt(certificateValidator, errorMessageCiphertext, 31335);
- DecryptionErrorMessage bobErrorMessage = DecryptionErrorMessage.extractFromSerializedContent(result.getPaddedMessage());
+ DecryptionResult result =
+ bobCipher.decrypt(certificateValidator, errorMessageCiphertext, 31335);
+ DecryptionErrorMessage bobErrorMessage =
+ DecryptionErrorMessage.extractFromSerializedContent(result.getPaddedMessage());
assertEquals(bobErrorMessage.getTimestamp(), 408);
assertEquals(bobErrorMessage.getDeviceId(), bobAddress.getDeviceId());
SessionRecord bobSessionWithAlice = bobStore.loadSession(aliceAddress);
- assert(bobSessionWithAlice.currentRatchetKeyMatches(bobErrorMessage.getRatchetKey().get()));
+ assert (bobSessionWithAlice.currentRatchetKeyMatches(bobErrorMessage.getRatchetKey().get()));
}
- private SenderCertificate createCertificateFor(ECKeyPair trustRoot, UUID uuid, String e164, int deviceId, ECPublicKey identityKey, long expires)
+ private SenderCertificate createCertificateFor(
+ ECKeyPair trustRoot,
+ UUID uuid,
+ String e164,
+ int deviceId,
+ ECPublicKey identityKey,
+ long expires)
throws InvalidKeyException, InvalidCertificateException {
ECKeyPair serverKey = Curve.generateKeyPair();
- try (
- NativeHandleGuard serverPublicGuard = new NativeHandleGuard(serverKey.getPublicKey());
- NativeHandleGuard trustRootPrivateGuard = new NativeHandleGuard(trustRoot.getPrivateKey());
- ) {
- ServerCertificate serverCertificate = new ServerCertificate(Native.ServerCertificate_New(1, serverPublicGuard.nativeHandle(), trustRootPrivateGuard.nativeHandle()));
-
- try (
- NativeHandleGuard identityGuard = new NativeHandleGuard(identityKey);
- NativeHandleGuard serverCertificateGuard = new NativeHandleGuard(serverCertificate);
- NativeHandleGuard serverPrivateGuard = new NativeHandleGuard(serverKey.getPrivateKey());
- ) {
- return new SenderCertificate(Native.SenderCertificate_New(uuid.toString(), e164, deviceId, identityGuard.nativeHandle(), expires, serverCertificateGuard.nativeHandle(), serverPrivateGuard.nativeHandle()));
+ try (NativeHandleGuard serverPublicGuard = new NativeHandleGuard(serverKey.getPublicKey());
+ NativeHandleGuard trustRootPrivateGuard =
+ new NativeHandleGuard(trustRoot.getPrivateKey()); ) {
+ ServerCertificate serverCertificate =
+ new ServerCertificate(
+ Native.ServerCertificate_New(
+ 1, serverPublicGuard.nativeHandle(), trustRootPrivateGuard.nativeHandle()));
+
+ try (NativeHandleGuard identityGuard = new NativeHandleGuard(identityKey);
+ NativeHandleGuard serverCertificateGuard = new NativeHandleGuard(serverCertificate);
+ NativeHandleGuard serverPrivateGuard =
+ new NativeHandleGuard(serverKey.getPrivateKey()); ) {
+ return new SenderCertificate(
+ Native.SenderCertificate_New(
+ uuid.toString(),
+ e164,
+ deviceId,
+ identityGuard.nativeHandle(),
+ expires,
+ serverCertificateGuard.nativeHandle(),
+ serverPrivateGuard.nativeHandle()));
}
}
}
- private void initializeSessions(TestInMemorySignalProtocolStore aliceStore, TestInMemorySignalProtocolStore bobStore, SignalProtocolAddress bobAddress)
- throws InvalidKeyException, UntrustedIdentityException
- {
- ECKeyPair bobPreKey = Curve.generateKeyPair();
- IdentityKeyPair bobIdentityKey = bobStore.getIdentityKeyPair();
+ private void initializeSessions(
+ TestInMemorySignalProtocolStore aliceStore,
+ TestInMemorySignalProtocolStore bobStore,
+ SignalProtocolAddress bobAddress)
+ throws InvalidKeyException, UntrustedIdentityException {
+ ECKeyPair bobPreKey = Curve.generateKeyPair();
+ IdentityKeyPair bobIdentityKey = bobStore.getIdentityKeyPair();
SignedPreKeyRecord bobSignedPreKey = generateSignedPreKey(bobIdentityKey, 2);
- KyberPreKeyRecord bobKyberPreKey = generateKyberPreKey(bobIdentityKey, 12);
+ KyberPreKeyRecord bobKyberPreKey = generateKyberPreKey(bobIdentityKey, 12);
- PreKeyBundle bobBundle = new PreKeyBundle(1, 1, 1, bobPreKey.getPublicKey(), 2, bobSignedPreKey.getKeyPair().getPublicKey(), bobSignedPreKey.getSignature(), bobIdentityKey.getPublicKey(), 12, bobKyberPreKey.getKeyPair().getPublicKey(), bobKyberPreKey.getSignature());
+ PreKeyBundle bobBundle =
+ new PreKeyBundle(
+ 1,
+ 1,
+ 1,
+ bobPreKey.getPublicKey(),
+ 2,
+ bobSignedPreKey.getKeyPair().getPublicKey(),
+ bobSignedPreKey.getSignature(),
+ bobIdentityKey.getPublicKey(),
+ 12,
+ bobKyberPreKey.getKeyPair().getPublicKey(),
+ bobKyberPreKey.getSignature());
SessionBuilder aliceSessionBuilder = new SessionBuilder(aliceStore, bobAddress);
aliceSessionBuilder.process(bobBundle);
diff --git a/java/client/src/test/java/org/signal/libsignal/metadata/TestInMemorySignalProtocolStore.java b/java/client/src/test/java/org/signal/libsignal/metadata/TestInMemorySignalProtocolStore.java
index 0860b9eaa9..2306e22429 100644
--- a/java/client/src/test/java/org/signal/libsignal/metadata/TestInMemorySignalProtocolStore.java
+++ b/java/client/src/test/java/org/signal/libsignal/metadata/TestInMemorySignalProtocolStore.java
@@ -1,11 +1,14 @@
-package org.signal.libsignal.metadata;
+//
+// Copyright 2023 Signal Messenger, LLC.
+// SPDX-License-Identifier: AGPL-3.0-only
+//
+package org.signal.libsignal.metadata;
import org.signal.libsignal.protocol.IdentityKey;
import org.signal.libsignal.protocol.IdentityKeyPair;
import org.signal.libsignal.protocol.ecc.Curve;
import org.signal.libsignal.protocol.ecc.ECKeyPair;
-import org.signal.libsignal.protocol.state.SignedPreKeyRecord;
import org.signal.libsignal.protocol.state.impl.InMemorySignalProtocolStore;
import org.signal.libsignal.protocol.util.KeyHelper;
@@ -17,11 +20,11 @@ public TestInMemorySignalProtocolStore() {
private static IdentityKeyPair generateIdentityKeyPair() {
ECKeyPair identityKeyPairKeys = Curve.generateKeyPair();
- return new IdentityKeyPair(new IdentityKey(identityKeyPairKeys.getPublicKey()),
- identityKeyPairKeys.getPrivateKey());
+ return new IdentityKeyPair(
+ new IdentityKey(identityKeyPairKeys.getPublicKey()), identityKeyPairKeys.getPrivateKey());
}
private static int generateRegistrationId() {
return KeyHelper.generateRegistrationId(false);
}
-}
\ No newline at end of file
+}
diff --git a/java/client/src/test/java/org/signal/libsignal/metadata/certificate/SenderCertificateTest.java b/java/client/src/test/java/org/signal/libsignal/metadata/certificate/SenderCertificateTest.java
index 145e13f114..13c319c26f 100644
--- a/java/client/src/test/java/org/signal/libsignal/metadata/certificate/SenderCertificateTest.java
+++ b/java/client/src/test/java/org/signal/libsignal/metadata/certificate/SenderCertificateTest.java
@@ -1,19 +1,20 @@
+//
+// Copyright 2023 Signal Messenger, LLC.
+// SPDX-License-Identifier: AGPL-3.0-only
+//
+
package org.signal.libsignal.metadata.certificate;
+import java.util.Optional;
+import java.util.UUID;
import junit.framework.TestCase;
-
+import org.signal.libsignal.internal.Native;
+import org.signal.libsignal.internal.NativeHandleGuard;
import org.signal.libsignal.protocol.InvalidKeyException;
+import org.signal.libsignal.protocol.ServiceId;
import org.signal.libsignal.protocol.ecc.Curve;
import org.signal.libsignal.protocol.ecc.ECKeyPair;
import org.signal.libsignal.protocol.ecc.ECPublicKey;
-import org.signal.libsignal.protocol.ecc.ECPrivateKey;
-import org.signal.libsignal.protocol.ServiceId;
-
-import org.signal.libsignal.internal.Native;
-import org.signal.libsignal.internal.NativeHandleGuard;
-
-import java.util.Optional;
-import java.util.UUID;
public class SenderCertificateTest extends TestCase {
@@ -21,15 +22,29 @@ public class SenderCertificateTest extends TestCase {
public void testSignature() throws InvalidCertificateException, InvalidKeyException {
ECKeyPair key = Curve.generateKeyPair();
- SenderCertificate senderCertificate = createCertificateFor(trustRoot, UUID.fromString("9d0652a3-dcc3-4d11-975f-74d61598733f"), "+14151111111", 31337, key.getPublicKey(), 31337);
+ SenderCertificate senderCertificate =
+ createCertificateFor(
+ trustRoot,
+ UUID.fromString("9d0652a3-dcc3-4d11-975f-74d61598733f"),
+ "+14151111111",
+ 31337,
+ key.getPublicKey(),
+ 31337);
new CertificateValidator(trustRoot.getPublicKey()).validate(senderCertificate, 31336);
}
public void testExpiredSignature() throws InvalidCertificateException, InvalidKeyException {
- ECKeyPair key = Curve.generateKeyPair();
+ ECKeyPair key = Curve.generateKeyPair();
- SenderCertificate senderCertificate = createCertificateFor(trustRoot, UUID.fromString("9d0652a3-dcc3-4d11-975f-74d61598733f"), "+14151111111", 31338, key.getPublicKey(), 31337);
+ SenderCertificate senderCertificate =
+ createCertificateFor(
+ trustRoot,
+ UUID.fromString("9d0652a3-dcc3-4d11-975f-74d61598733f"),
+ "+14151111111",
+ 31338,
+ key.getPublicKey(),
+ 31337);
try {
new CertificateValidator(trustRoot.getPublicKey()).validate(senderCertificate, 31338);
throw new AssertionError();
@@ -39,9 +54,16 @@ public void testExpiredSignature() throws InvalidCertificateException, InvalidKe
}
public void testBadSignature() throws InvalidCertificateException, InvalidKeyException {
- ECKeyPair key = Curve.generateKeyPair();
+ ECKeyPair key = Curve.generateKeyPair();
- SenderCertificate senderCertificate = createCertificateFor(trustRoot, UUID.fromString("9d0652a3-dcc3-4d11-975f-74d61598733f"), "+14151111111", 31338, key.getPublicKey(), 31337);
+ SenderCertificate senderCertificate =
+ createCertificateFor(
+ trustRoot,
+ UUID.fromString("9d0652a3-dcc3-4d11-975f-74d61598733f"),
+ "+14151111111",
+ 31338,
+ key.getPublicKey(),
+ 31337);
byte[] badSignature = senderCertificate.getSerialized();
@@ -53,34 +75,51 @@ public void testBadSignature() throws InvalidCertificateException, InvalidKeyExc
new CertificateValidator(trustRoot.getPublicKey()).validate(badCert, 31336);
throw new AssertionError();
} catch (InvalidCertificateException e) {
- // good
+ // good
}
}
- public void testGetSenderAci() throws InvalidCertificateException, InvalidKeyException, ServiceId.InvalidServiceIdException {
+ public void testGetSenderAci()
+ throws InvalidCertificateException, InvalidKeyException, ServiceId.InvalidServiceIdException {
ECKeyPair key = Curve.generateKeyPair();
UUID uuid = UUID.fromString("9d0652a3-dcc3-4d11-975f-74d61598733f");
- SenderCertificate senderCertificate = createCertificateFor(trustRoot, uuid, null, 31338, key.getPublicKey(), 31337);
+ SenderCertificate senderCertificate =
+ createCertificateFor(trustRoot, uuid, null, 31338, key.getPublicKey(), 31337);
assertEquals(Optional.empty(), senderCertificate.getSenderE164());
assertEquals(uuid, senderCertificate.getSenderAci().getRawUUID());
}
- private SenderCertificate createCertificateFor(ECKeyPair trustRoot, UUID uuid, String e164, int deviceId, ECPublicKey identityKey, long expires)
+ private SenderCertificate createCertificateFor(
+ ECKeyPair trustRoot,
+ UUID uuid,
+ String e164,
+ int deviceId,
+ ECPublicKey identityKey,
+ long expires)
throws InvalidKeyException, InvalidCertificateException {
ECKeyPair serverKey = Curve.generateKeyPair();
- try (
- NativeHandleGuard serverPublicGuard = new NativeHandleGuard(serverKey.getPublicKey());
- NativeHandleGuard trustRootPrivateGuard = new NativeHandleGuard(trustRoot.getPrivateKey());
- ) {
- ServerCertificate serverCertificate = new ServerCertificate(Native.ServerCertificate_New(1, serverPublicGuard.nativeHandle(), trustRootPrivateGuard.nativeHandle()));
-
- try (
- NativeHandleGuard identityGuard = new NativeHandleGuard(identityKey);
- NativeHandleGuard serverCertificateGuard = new NativeHandleGuard(serverCertificate);
- NativeHandleGuard serverPrivateGuard = new NativeHandleGuard(serverKey.getPrivateKey());
- ) {
- return new SenderCertificate(Native.SenderCertificate_New(uuid.toString(), e164, deviceId, identityGuard.nativeHandle(), expires, serverCertificateGuard.nativeHandle(), serverPrivateGuard.nativeHandle()));
+ try (NativeHandleGuard serverPublicGuard = new NativeHandleGuard(serverKey.getPublicKey());
+ NativeHandleGuard trustRootPrivateGuard =
+ new NativeHandleGuard(trustRoot.getPrivateKey()); ) {
+ ServerCertificate serverCertificate =
+ new ServerCertificate(
+ Native.ServerCertificate_New(
+ 1, serverPublicGuard.nativeHandle(), trustRootPrivateGuard.nativeHandle()));
+
+ try (NativeHandleGuard identityGuard = new NativeHandleGuard(identityKey);
+ NativeHandleGuard serverCertificateGuard = new NativeHandleGuard(serverCertificate);
+ NativeHandleGuard serverPrivateGuard =
+ new NativeHandleGuard(serverKey.getPrivateKey()); ) {
+ return new SenderCertificate(
+ Native.SenderCertificate_New(
+ uuid.toString(),
+ e164,
+ deviceId,
+ identityGuard.nativeHandle(),
+ expires,
+ serverCertificateGuard.nativeHandle(),
+ serverPrivateGuard.nativeHandle()));
}
}
}
diff --git a/java/client/src/test/java/org/signal/libsignal/metadata/certificate/ServerCertificateTest.java b/java/client/src/test/java/org/signal/libsignal/metadata/certificate/ServerCertificateTest.java
index e8eac43929..7b48b35c3d 100644
--- a/java/client/src/test/java/org/signal/libsignal/metadata/certificate/ServerCertificateTest.java
+++ b/java/client/src/test/java/org/signal/libsignal/metadata/certificate/ServerCertificateTest.java
@@ -1,44 +1,50 @@
+//
+// Copyright 2023 Signal Messenger, LLC.
+// SPDX-License-Identifier: AGPL-3.0-only
+//
+
package org.signal.libsignal.metadata.certificate;
import junit.framework.TestCase;
-
+import org.signal.libsignal.internal.Native;
+import org.signal.libsignal.internal.NativeHandleGuard;
import org.signal.libsignal.protocol.InvalidKeyException;
import org.signal.libsignal.protocol.ecc.Curve;
import org.signal.libsignal.protocol.ecc.ECKeyPair;
-import org.signal.libsignal.internal.Native;
-import org.signal.libsignal.internal.NativeHandleGuard;
-
public class ServerCertificateTest extends TestCase {
public void testSignature() throws InvalidKeyException, InvalidCertificateException {
ECKeyPair trustRoot = Curve.generateKeyPair();
- ECKeyPair keyPair = Curve.generateKeyPair();
-
- try (
- NativeHandleGuard serverPublicGuard = new NativeHandleGuard(keyPair.getPublicKey());
- NativeHandleGuard trustRootPrivateGuard = new NativeHandleGuard(trustRoot.getPrivateKey());
- ) {
- ServerCertificate certificate = new ServerCertificate(
- Native.ServerCertificate_New(1, serverPublicGuard.nativeHandle(), trustRootPrivateGuard.nativeHandle()));
-
+ ECKeyPair keyPair = Curve.generateKeyPair();
+
+ try (NativeHandleGuard serverPublicGuard = new NativeHandleGuard(keyPair.getPublicKey());
+ NativeHandleGuard trustRootPrivateGuard =
+ new NativeHandleGuard(trustRoot.getPrivateKey()); ) {
+ ServerCertificate certificate =
+ new ServerCertificate(
+ Native.ServerCertificate_New(
+ 1, serverPublicGuard.nativeHandle(), trustRootPrivateGuard.nativeHandle()));
+
new CertificateValidator(trustRoot.getPublicKey()).validate(certificate);
-
+
byte[] serialized = certificate.getSerialized();
- new CertificateValidator(trustRoot.getPublicKey()).validate(new ServerCertificate(serialized));
+ new CertificateValidator(trustRoot.getPublicKey())
+ .validate(new ServerCertificate(serialized));
}
}
public void testBadSignature() throws Exception {
ECKeyPair trustRoot = Curve.generateKeyPair();
- ECKeyPair keyPair = Curve.generateKeyPair();
+ ECKeyPair keyPair = Curve.generateKeyPair();
- try (
- NativeHandleGuard serverPublicGuard = new NativeHandleGuard(keyPair.getPublicKey());
- NativeHandleGuard trustRootPrivateGuard = new NativeHandleGuard(trustRoot.getPrivateKey());
- ) {
- ServerCertificate certificate = new ServerCertificate(
- Native.ServerCertificate_New(1, serverPublicGuard.nativeHandle(), trustRootPrivateGuard.nativeHandle()));
+ try (NativeHandleGuard serverPublicGuard = new NativeHandleGuard(keyPair.getPublicKey());
+ NativeHandleGuard trustRootPrivateGuard =
+ new NativeHandleGuard(trustRoot.getPrivateKey()); ) {
+ ServerCertificate certificate =
+ new ServerCertificate(
+ Native.ServerCertificate_New(
+ 1, serverPublicGuard.nativeHandle(), trustRootPrivateGuard.nativeHandle()));
byte[] badSignature = certificate.getSerialized();
@@ -47,12 +53,12 @@ public void testBadSignature() throws Exception {
ServerCertificate badCert = new ServerCertificate(badSignature);
try {
- new CertificateValidator(trustRoot.getPublicKey()).validate(new ServerCertificate(badSignature));
- fail();
+ new CertificateValidator(trustRoot.getPublicKey())
+ .validate(new ServerCertificate(badSignature));
+ fail();
} catch (InvalidCertificateException e) {
- // good
+ // good
}
}
}
-
}
diff --git a/java/client/src/test/java/org/signal/libsignal/protocol/BundleFactory.java b/java/client/src/test/java/org/signal/libsignal/protocol/BundleFactory.java
index b494f6ef07..0996fe9380 100644
--- a/java/client/src/test/java/org/signal/libsignal/protocol/BundleFactory.java
+++ b/java/client/src/test/java/org/signal/libsignal/protocol/BundleFactory.java
@@ -1,3 +1,8 @@
+//
+// Copyright 2023 Signal Messenger, LLC.
+// SPDX-License-Identifier: AGPL-3.0-only
+//
+
package org.signal.libsignal.protocol;
import org.signal.libsignal.protocol.state.PreKeyBundle;
diff --git a/java/client/src/test/java/org/signal/libsignal/protocol/CurveTest.java b/java/client/src/test/java/org/signal/libsignal/protocol/CurveTest.java
index 7a5db7d5d8..63f3b7d4c6 100644
--- a/java/client/src/test/java/org/signal/libsignal/protocol/CurveTest.java
+++ b/java/client/src/test/java/org/signal/libsignal/protocol/CurveTest.java
@@ -1,16 +1,20 @@
+//
+// Copyright 2023 Signal Messenger, LLC.
+// SPDX-License-Identifier: AGPL-3.0-only
+//
+
package org.signal.libsignal.protocol;
import junit.framework.TestCase;
-
import org.signal.libsignal.protocol.ecc.Curve;
import org.signal.libsignal.protocol.ecc.ECKeyPair;
public class CurveTest extends TestCase {
public void testLargeSignatures() throws InvalidKeyException {
- ECKeyPair keys = Curve.generateKeyPair();
- byte[] message = new byte[1024 * 1024];
- byte[] signature = Curve.calculateSignature(keys.getPrivateKey(), message);
+ ECKeyPair keys = Curve.generateKeyPair();
+ byte[] message = new byte[1024 * 1024];
+ byte[] signature = Curve.calculateSignature(keys.getPrivateKey(), message);
assertTrue(Curve.verifySignature(keys.getPublicKey(), message, signature));
@@ -18,5 +22,4 @@ public void testLargeSignatures() throws InvalidKeyException {
assertFalse(Curve.verifySignature(keys.getPublicKey(), message, signature));
}
-
}
diff --git a/java/client/src/test/java/org/signal/libsignal/protocol/IdentityKeyTest.java b/java/client/src/test/java/org/signal/libsignal/protocol/IdentityKeyTest.java
index 6869b6f1fe..dce6589e53 100644
--- a/java/client/src/test/java/org/signal/libsignal/protocol/IdentityKeyTest.java
+++ b/java/client/src/test/java/org/signal/libsignal/protocol/IdentityKeyTest.java
@@ -6,8 +6,6 @@
package org.signal.libsignal.protocol;
import junit.framework.TestCase;
-import org.signal.libsignal.protocol.IdentityKey;
-import org.signal.libsignal.protocol.IdentityKeyPair;
public class IdentityKeyTest extends TestCase {
public void testSignAlternateKey() {
diff --git a/java/client/src/test/java/org/signal/libsignal/protocol/PQXDHBundleFactory.java b/java/client/src/test/java/org/signal/libsignal/protocol/PQXDHBundleFactory.java
index daa3a9b245..08643cd77b 100644
--- a/java/client/src/test/java/org/signal/libsignal/protocol/PQXDHBundleFactory.java
+++ b/java/client/src/test/java/org/signal/libsignal/protocol/PQXDHBundleFactory.java
@@ -1,5 +1,11 @@
+//
+// Copyright 2023 Signal Messenger, LLC.
+// SPDX-License-Identifier: AGPL-3.0-only
+//
+
package org.signal.libsignal.protocol;
+import java.util.Random;
import org.signal.libsignal.protocol.ecc.Curve;
import org.signal.libsignal.protocol.ecc.ECKeyPair;
import org.signal.libsignal.protocol.kem.KEMKeyPair;
@@ -11,32 +17,45 @@
import org.signal.libsignal.protocol.state.SignedPreKeyRecord;
import org.signal.libsignal.protocol.util.Medium;
-import java.util.Random;
-
public final class PQXDHBundleFactory implements BundleFactory {
@Override
public PreKeyBundle createBundle(SignalProtocolStore store) throws InvalidKeyException {
- ECKeyPair preKeyPair = Curve.generateKeyPair();
- ECKeyPair signedPreKeyPair = Curve.generateKeyPair();
- byte[] signedPreKeySignature = Curve.calculateSignature(store.getIdentityKeyPair().getPrivateKey(),
- signedPreKeyPair.getPublicKey().serialize());
- KEMKeyPair kyberPreKeyPair = KEMKeyPair.generate(KEMKeyType.KYBER_1024);
- byte[] kyberPreKeySignature = Curve.calculateSignature(store.getIdentityKeyPair().getPrivateKey(),
- kyberPreKeyPair.getPublicKey().serialize());
+ ECKeyPair preKeyPair = Curve.generateKeyPair();
+ ECKeyPair signedPreKeyPair = Curve.generateKeyPair();
+ byte[] signedPreKeySignature =
+ Curve.calculateSignature(
+ store.getIdentityKeyPair().getPrivateKey(),
+ signedPreKeyPair.getPublicKey().serialize());
+ KEMKeyPair kyberPreKeyPair = KEMKeyPair.generate(KEMKeyType.KYBER_1024);
+ byte[] kyberPreKeySignature =
+ Curve.calculateSignature(
+ store.getIdentityKeyPair().getPrivateKey(), kyberPreKeyPair.getPublicKey().serialize());
Random random = new Random();
int preKeyId = random.nextInt(Medium.MAX_VALUE);
int signedPreKeyId = random.nextInt(Medium.MAX_VALUE);
int kyberPreKeyId = random.nextInt(Medium.MAX_VALUE);
store.storePreKey(preKeyId, new PreKeyRecord(preKeyId, preKeyPair));
- store.storeSignedPreKey(signedPreKeyId, new SignedPreKeyRecord(signedPreKeyId, System.currentTimeMillis(), signedPreKeyPair, signedPreKeySignature));
- store.storeKyberPreKey(kyberPreKeyId, new KyberPreKeyRecord(kyberPreKeyId, System.currentTimeMillis(), kyberPreKeyPair, kyberPreKeySignature));
+ store.storeSignedPreKey(
+ signedPreKeyId,
+ new SignedPreKeyRecord(
+ signedPreKeyId, System.currentTimeMillis(), signedPreKeyPair, signedPreKeySignature));
+ store.storeKyberPreKey(
+ kyberPreKeyId,
+ new KyberPreKeyRecord(
+ kyberPreKeyId, System.currentTimeMillis(), kyberPreKeyPair, kyberPreKeySignature));
- return new PreKeyBundle(store.getLocalRegistrationId(), 1,
- preKeyId, preKeyPair.getPublicKey(),
- signedPreKeyId, signedPreKeyPair.getPublicKey(), signedPreKeySignature,
+ return new PreKeyBundle(
+ store.getLocalRegistrationId(),
+ 1,
+ preKeyId,
+ preKeyPair.getPublicKey(),
+ signedPreKeyId,
+ signedPreKeyPair.getPublicKey(),
+ signedPreKeySignature,
store.getIdentityKeyPair().getPublicKey(),
- kyberPreKeyId, kyberPreKeyPair.getPublicKey(), kyberPreKeySignature);
+ kyberPreKeyId,
+ kyberPreKeyPair.getPublicKey(),
+ kyberPreKeySignature);
}
}
-
diff --git a/java/client/src/test/java/org/signal/libsignal/protocol/PlaintextContentTest.java b/java/client/src/test/java/org/signal/libsignal/protocol/PlaintextContentTest.java
index cc089c0ad2..e6e35226dc 100644
--- a/java/client/src/test/java/org/signal/libsignal/protocol/PlaintextContentTest.java
+++ b/java/client/src/test/java/org/signal/libsignal/protocol/PlaintextContentTest.java
@@ -5,46 +5,53 @@
package org.signal.libsignal.protocol;
+import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.fail;
+
+import java.util.Arrays;
import org.junit.Test;
import org.signal.libsignal.protocol.message.CiphertextMessage;
import org.signal.libsignal.protocol.message.DecryptionErrorMessage;
import org.signal.libsignal.protocol.message.PlaintextContent;
-import org.signal.libsignal.protocol.util.Hex;
-
-import java.util.Arrays;
-
-import static org.junit.Assert.assertArrayEquals;
-import static org.junit.Assert.fail;
public class PlaintextContentTest {
@Test
public void testRoundTripSerialization() throws Exception {
// We don't have the whole Content proto exposed at the Java level in this project,
// so just check the literal bytes that we expect.
- byte[] expectedPlaintextBody = new byte[] {
- // DecryptionErrorMessage field, 9 bytes long
- (byte)0x42, (byte)0x09,
- // The serialized DecryptionErrorMessage
- (byte)0x10, (byte)0x80, (byte)0xb8, (byte)0xbe,
- (byte)0x97, (byte)0xe1, (byte)0x2f, (byte)0x18,
- (byte)0x08,
- // Tail padding marker
- (byte)0x80,
- };
+ byte[] expectedPlaintextBody =
+ new byte[] {
+ // DecryptionErrorMessage field, 9 bytes long
+ (byte) 0x42,
+ (byte) 0x09,
+ // The serialized DecryptionErrorMessage
+ (byte) 0x10,
+ (byte) 0x80,
+ (byte) 0xb8,
+ (byte) 0xbe,
+ (byte) 0x97,
+ (byte) 0xe1,
+ (byte) 0x2f,
+ (byte) 0x18,
+ (byte) 0x08,
+ // Tail padding marker
+ (byte) 0x80,
+ };
long timestamp = 1640995200000L;
int originalDeviceId = 8;
// DEMs don't extract any information from the original message for a SenderKey message,
// so we use that here to avoid having to construct a valid original message.
- DecryptionErrorMessage decryptionErrorMessage = DecryptionErrorMessage.forOriginalMessage(
- new byte[] {}, CiphertextMessage.SENDERKEY_TYPE, timestamp, originalDeviceId);
+ DecryptionErrorMessage decryptionErrorMessage =
+ DecryptionErrorMessage.forOriginalMessage(
+ new byte[] {}, CiphertextMessage.SENDERKEY_TYPE, timestamp, originalDeviceId);
byte[] serializedDEM = decryptionErrorMessage.serialize();
assertArrayEquals(
- "expectedBody needs updating",
- serializedDEM,
- Arrays.copyOfRange(expectedPlaintextBody, 2, 2 + serializedDEM.length));
+ "expectedBody needs updating",
+ serializedDEM,
+ Arrays.copyOfRange(expectedPlaintextBody, 2, 2 + serializedDEM.length));
byte[] serializedPlaintextContent = new PlaintextContent(decryptionErrorMessage).serialize();
byte[] deserializedPlaintextBody = new PlaintextContent(serializedPlaintextContent).getBody();
@@ -56,11 +63,13 @@ public void testDeserializationRejectsGarbage() throws Exception {
try {
new PlaintextContent(new byte[] {});
fail();
- } catch (InvalidMessageException e) {}
+ } catch (InvalidMessageException e) {
+ }
try {
- new PlaintextContent(new byte[] {(byte)0});
+ new PlaintextContent(new byte[] {(byte) 0});
fail();
- } catch (InvalidVersionException e) {}
+ } catch (InvalidVersionException e) {
+ }
}
}
diff --git a/java/client/src/test/java/org/signal/libsignal/protocol/ProtocolAddressTest.java b/java/client/src/test/java/org/signal/libsignal/protocol/ProtocolAddressTest.java
index 91d934a2ed..149c3a38e8 100644
--- a/java/client/src/test/java/org/signal/libsignal/protocol/ProtocolAddressTest.java
+++ b/java/client/src/test/java/org/signal/libsignal/protocol/ProtocolAddressTest.java
@@ -5,14 +5,12 @@
package org.signal.libsignal.protocol;
-import java.util.UUID;
-import org.junit.Test;
-import org.signal.libsignal.protocol.SignalProtocolAddress;
-import org.signal.libsignal.protocol.ServiceId;
-
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotEquals;
+import java.util.UUID;
+import org.junit.Test;
+
public class ProtocolAddressTest {
@Test
public void testRoundTripServiceId() {
diff --git a/java/client/src/test/java/org/signal/libsignal/protocol/ServiceIdTest.java b/java/client/src/test/java/org/signal/libsignal/protocol/ServiceIdTest.java
index cd56ab9362..1587442dde 100644
--- a/java/client/src/test/java/org/signal/libsignal/protocol/ServiceIdTest.java
+++ b/java/client/src/test/java/org/signal/libsignal/protocol/ServiceIdTest.java
@@ -7,100 +7,106 @@
import java.util.UUID;
import junit.framework.TestCase;
-
import org.signal.libsignal.protocol.ServiceId.InvalidServiceIdException;
-
import org.signal.libsignal.protocol.util.Hex;
public class ServiceIdTest extends TestCase {
- private static final String TEST_UUID_STRING = "c04d643e-1c2d-43b6-bcb7-d7f41f7f0990";
- private static final UUID TEST_UUID = UUID.fromString(TEST_UUID_STRING);
- private static final String TEST_UUID_HEX = "c04d643e1c2d43b6bcb7d7f41f7f0990";
-
- public void testFromUUIDAndBack() throws Exception {
- UUID original = UUID.randomUUID();
- ServiceId.Aci aci = new ServiceId.Aci(original);
- assertEquals(original, aci.getRawUUID());
- ServiceId.Pni pni = new ServiceId.Pni(original);
- assertEquals(original, pni.getRawUUID());
+ private static final String TEST_UUID_STRING = "c04d643e-1c2d-43b6-bcb7-d7f41f7f0990";
+ private static final UUID TEST_UUID = UUID.fromString(TEST_UUID_STRING);
+ private static final String TEST_UUID_HEX = "c04d643e1c2d43b6bcb7d7f41f7f0990";
+
+ public void testFromUUIDAndBack() throws Exception {
+ UUID original = UUID.randomUUID();
+ ServiceId.Aci aci = new ServiceId.Aci(original);
+ assertEquals(original, aci.getRawUUID());
+ ServiceId.Pni pni = new ServiceId.Pni(original);
+ assertEquals(original, pni.getRawUUID());
+ }
+
+ public void testAciRepresentations() throws Exception {
+ ServiceId.Aci aci = new ServiceId.Aci(TEST_UUID);
+ assertEquals(TEST_UUID_STRING, aci.toServiceIdString());
+ assertEquals(TEST_UUID_HEX, Hex.toStringCondensed(aci.toServiceIdBinary()));
+ assertEquals(String.format("", TEST_UUID_STRING), aci.toLogString());
+ assertEquals(String.format("", TEST_UUID_STRING), aci.toString());
+ }
+
+ public void testPniRepresentations() throws Exception {
+ ServiceId.Pni pni = new ServiceId.Pni(TEST_UUID);
+ assertEquals(String.format("PNI:%s", TEST_UUID_STRING), pni.toServiceIdString());
+ assertEquals(
+ String.format("01%s", TEST_UUID_HEX), Hex.toStringCondensed(pni.toServiceIdBinary()));
+ assertEquals(String.format("", TEST_UUID_STRING), pni.toLogString());
+ assertEquals(String.format("", TEST_UUID_STRING), pni.toString());
+ }
+
+ public void testParseFromString() throws Exception {
+ assert (ServiceId.parseFromString(TEST_UUID_STRING) instanceof ServiceId.Aci);
+ ServiceId.Aci.parseFromString(TEST_UUID_STRING);
+
+ assert (ServiceId.parseFromString(String.format("PNI:%s", TEST_UUID_STRING))
+ instanceof ServiceId.Pni);
+ ServiceId.Pni.parseFromString(String.format("PNI:%s", TEST_UUID_STRING));
+
+ try {
+ ServiceId.parseFromString(String.format("ACI:%s", TEST_UUID_STRING));
+ fail("Successfully parsed an invalid Service-Id-String");
+ } catch (InvalidServiceIdException ex) {
}
-
- public void testAciRepresentations() throws Exception {
- ServiceId.Aci aci = new ServiceId.Aci(TEST_UUID);
- assertEquals(TEST_UUID_STRING, aci.toServiceIdString());
- assertEquals(TEST_UUID_HEX, Hex.toStringCondensed(aci.toServiceIdBinary()));
- assertEquals(String.format("", TEST_UUID_STRING), aci.toLogString());
- assertEquals(String.format("", TEST_UUID_STRING), aci.toString());
- }
-
- public void testPniRepresentations() throws Exception {
- ServiceId.Pni pni = new ServiceId.Pni(TEST_UUID);
- assertEquals(String.format("PNI:%s", TEST_UUID_STRING), pni.toServiceIdString());
- assertEquals(String.format("01%s", TEST_UUID_HEX), Hex.toStringCondensed(pni.toServiceIdBinary()));
- assertEquals(String.format("", TEST_UUID_STRING), pni.toLogString());
- assertEquals(String.format("", TEST_UUID_STRING), pni.toString());
+ }
+
+ public void testParseFromBinary() throws Exception {
+ byte[] aciBytes = Hex.fromStringCondensedAssert(TEST_UUID_HEX);
+ assert (ServiceId.parseFromBinary(aciBytes) instanceof ServiceId.Aci);
+ ServiceId.Aci.parseFromBinary(aciBytes);
+
+ byte[] pniBytes = Hex.fromStringCondensedAssert("01" + TEST_UUID_HEX);
+ assert (ServiceId.parseFromBinary(pniBytes) instanceof ServiceId.Pni);
+ ServiceId.Pni.parseFromBinary(pniBytes);
+
+ byte[] invalidAciBytes = Hex.fromStringCondensedAssert("00" + TEST_UUID_HEX);
+ try {
+ ServiceId.parseFromBinary(invalidAciBytes);
+ fail("Successfully parsed in invalid Service-Id-Binary");
+ } catch (InvalidServiceIdException ex) {
}
+ }
- public void testParseFromString() throws Exception {
- assert(ServiceId.parseFromString(TEST_UUID_STRING) instanceof ServiceId.Aci);
- ServiceId.Aci.parseFromString(TEST_UUID_STRING);
-
- assert(ServiceId.parseFromString(String.format("PNI:%s", TEST_UUID_STRING)) instanceof ServiceId.Pni);
- ServiceId.Pni.parseFromString(String.format("PNI:%s", TEST_UUID_STRING));
-
- try {
- ServiceId.parseFromString(String.format("ACI:%s", TEST_UUID_STRING));
- fail("Successfully parsed an invalid Service-Id-String");
- } catch (InvalidServiceIdException ex) {
- }
+ public void testNullInputs() throws Exception {
+ try {
+ new ServiceId.Aci((UUID) null);
+ fail("Should have failed");
+ } catch (IllegalArgumentException ex) {
}
-
- public void testParseFromBinary() throws Exception {
- byte[] aciBytes = Hex.fromStringCondensedAssert(TEST_UUID_HEX);
- assert(ServiceId.parseFromBinary(aciBytes) instanceof ServiceId.Aci);
- ServiceId.Aci.parseFromBinary(aciBytes);
-
- byte[] pniBytes = Hex.fromStringCondensedAssert("01" + TEST_UUID_HEX);
- assert(ServiceId.parseFromBinary(pniBytes) instanceof ServiceId.Pni);
- ServiceId.Pni.parseFromBinary(pniBytes);
-
- byte[] invalidAciBytes = Hex.fromStringCondensedAssert("00" + TEST_UUID_HEX);
- try {
- ServiceId.parseFromBinary(invalidAciBytes);
- fail("Successfully parsed in invalid Service-Id-Binary");
- } catch (InvalidServiceIdException ex) {
- }
+ try {
+ new ServiceId.Pni((UUID) null);
+ fail("Should have failed");
+ } catch (IllegalArgumentException ex) {
}
-
- public void testNullInputs() throws Exception {
- try {
- new ServiceId.Aci((UUID)null);
- fail("Should have failed");
- } catch (IllegalArgumentException ex){}
- try {
- new ServiceId.Pni((UUID)null);
- fail("Should have failed");
- } catch (IllegalArgumentException ex){}
- try {
- ServiceId.parseFromString((String)null);
- fail("Should have failed");
- } catch (InvalidServiceIdException ex){}
- try {
- ServiceId.parseFromBinary((byte[])null);
- fail("Should have failed");
- } catch (InvalidServiceIdException ex){}
+ try {
+ ServiceId.parseFromString((String) null);
+ fail("Should have failed");
+ } catch (InvalidServiceIdException ex) {
}
-
- public void testInvalidServiceId() throws Exception {
- try {
- byte[] invalidServiceIdBytes = Hex.fromStringCondensedAssert("02" + TEST_UUID_HEX);
- ServiceId.parseFromBinary(invalidServiceIdBytes);
- fail("Should have failed");
- } catch(InvalidServiceIdException ex) {}
- try {
- String invalidServiceString = "SGL:" + TEST_UUID_STRING;
- ServiceId.parseFromString(invalidServiceString);
- fail("Should have failed");
- } catch(InvalidServiceIdException ex) {}
+ try {
+ ServiceId.parseFromBinary((byte[]) null);
+ fail("Should have failed");
+ } catch (InvalidServiceIdException ex) {
+ }
+ }
+
+ public void testInvalidServiceId() throws Exception {
+ try {
+ byte[] invalidServiceIdBytes = Hex.fromStringCondensedAssert("02" + TEST_UUID_HEX);
+ ServiceId.parseFromBinary(invalidServiceIdBytes);
+ fail("Should have failed");
+ } catch (InvalidServiceIdException ex) {
+ }
+ try {
+ String invalidServiceString = "SGL:" + TEST_UUID_STRING;
+ ServiceId.parseFromString(invalidServiceString);
+ fail("Should have failed");
+ } catch (InvalidServiceIdException ex) {
}
+ }
}
diff --git a/java/client/src/test/java/org/signal/libsignal/protocol/SessionBuilderTest.java b/java/client/src/test/java/org/signal/libsignal/protocol/SessionBuilderTest.java
index ffe830fd6e..9b400c2488 100644
--- a/java/client/src/test/java/org/signal/libsignal/protocol/SessionBuilderTest.java
+++ b/java/client/src/test/java/org/signal/libsignal/protocol/SessionBuilderTest.java
@@ -1,44 +1,46 @@
+//
+// Copyright 2023 Signal Messenger, LLC.
+// SPDX-License-Identifier: AGPL-3.0-only
+//
+
package org.signal.libsignal.protocol;
-import org.signal.libsignal.protocol.ecc.Curve;
-import org.signal.libsignal.protocol.ecc.ECKeyPair;
-import org.signal.libsignal.protocol.kem.KEMKeyPair;
-import org.signal.libsignal.protocol.kem.KEMKeyType;
-import org.signal.libsignal.protocol.message.CiphertextMessage;
-import org.signal.libsignal.protocol.message.PreKeySignalMessage;
-import org.signal.libsignal.protocol.message.SignalMessage;
-import org.signal.libsignal.protocol.state.IdentityKeyStore;
-import org.signal.libsignal.protocol.state.KyberPreKeyRecord;
-import org.signal.libsignal.protocol.state.PreKeyBundle;
-import org.signal.libsignal.protocol.state.PreKeyRecord;
-import org.signal.libsignal.protocol.state.SignalProtocolStore;
-import org.signal.libsignal.protocol.state.SignedPreKeyRecord;
-import org.signal.libsignal.protocol.util.Medium;
-import org.signal.libsignal.protocol.util.Pair;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+import java.time.Instant;
+import java.time.temporal.ChronoUnit;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashSet;
import java.util.Random;
import java.util.Set;
-
import org.junit.Test;
+import org.junit.experimental.runners.Enclosed;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import org.junit.runners.Parameterized.Parameters;
-import org.junit.experimental.runners.Enclosed;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertTrue;
-import static org.junit.Assert.fail;
-
+import org.signal.libsignal.protocol.ecc.Curve;
+import org.signal.libsignal.protocol.ecc.ECKeyPair;
+import org.signal.libsignal.protocol.message.CiphertextMessage;
+import org.signal.libsignal.protocol.message.PreKeySignalMessage;
+import org.signal.libsignal.protocol.message.SignalMessage;
+import org.signal.libsignal.protocol.state.IdentityKeyStore;
+import org.signal.libsignal.protocol.state.PreKeyBundle;
+import org.signal.libsignal.protocol.state.SessionRecord;
+import org.signal.libsignal.protocol.state.SignalProtocolStore;
+import org.signal.libsignal.protocol.util.Medium;
+import org.signal.libsignal.protocol.util.Pair;
@RunWith(Enclosed.class)
public class SessionBuilderTest {
- private static final SignalProtocolAddress ALICE_ADDRESS = new SignalProtocolAddress("+14151111111", 1);
- private static final SignalProtocolAddress BOB_ADDRESS = new SignalProtocolAddress("+14152222222", 1);
+ private static final SignalProtocolAddress ALICE_ADDRESS =
+ new SignalProtocolAddress("+14151111111", 1);
+ private static final SignalProtocolAddress BOB_ADDRESS =
+ new SignalProtocolAddress("+14152222222", 1);
@RunWith(Parameterized.class)
public static class Versioned {
@@ -52,16 +54,24 @@ public Versioned(BundleFactory bundleFactory, int expectedVersion) {
@Parameters(name = "v{1}")
public static Collection data() throws Exception {
- return Arrays.asList(new Object[][] {
- {new X3DHBundleFactory(), 3},
- {new PQXDHBundleFactory(), 4}
- });
+ return Arrays.asList(
+ new Object[][] {
+ {new X3DHBundleFactory(), 3},
+ {new PQXDHBundleFactory(), 4}
+ });
}
@Test
public void testBasicPreKey()
- throws InvalidKeyException, InvalidVersionException, InvalidMessageException, InvalidKeyIdException, DuplicateMessageException, LegacyMessageException, UntrustedIdentityException, NoSessionException {
- SignalProtocolStore aliceStore = new TestInMemorySignalProtocolStore();
+ throws InvalidKeyException,
+ InvalidVersionException,
+ InvalidMessageException,
+ InvalidKeyIdException,
+ DuplicateMessageException,
+ LegacyMessageException,
+ UntrustedIdentityException,
+ NoSessionException {
+ SignalProtocolStore aliceStore = new TestInMemorySignalProtocolStore();
SessionBuilder aliceSessionBuilder = new SessionBuilder(aliceStore, BOB_ADDRESS);
final SignalProtocolStore bobStore = new TestInMemorySignalProtocolStore();
@@ -73,9 +83,9 @@ public void testBasicPreKey()
assertTrue(aliceStore.containsSession(BOB_ADDRESS));
assertTrue(aliceStore.loadSession(BOB_ADDRESS).getSessionVersion() == expectedVersion);
- String originalMessage = "Good, fast, cheap: pick two";
- SessionCipher aliceSessionCipher = new SessionCipher(aliceStore, BOB_ADDRESS);
- CiphertextMessage outgoingMessage = aliceSessionCipher.encrypt(originalMessage.getBytes());
+ String originalMessage = "Good, fast, cheap: pick two";
+ SessionCipher aliceSessionCipher = new SessionCipher(aliceStore, BOB_ADDRESS);
+ CiphertextMessage outgoingMessage = aliceSessionCipher.encrypt(originalMessage.getBytes());
assertTrue(outgoingMessage.getType() == CiphertextMessage.PREKEY_TYPE);
@@ -92,14 +102,15 @@ public void testBasicPreKey()
CiphertextMessage bobOutgoingMessage = bobSessionCipher.encrypt(originalMessage.getBytes());
assertTrue(bobOutgoingMessage.getType() == CiphertextMessage.WHISPER_TYPE);
- byte[] alicePlaintext = aliceSessionCipher.decrypt(new SignalMessage(bobOutgoingMessage.serialize()));
+ byte[] alicePlaintext =
+ aliceSessionCipher.decrypt(new SignalMessage(bobOutgoingMessage.serialize()));
assertTrue(new String(alicePlaintext).equals(originalMessage));
runInteraction(aliceStore, bobStore);
- aliceStore = new TestInMemorySignalProtocolStore();
+ aliceStore = new TestInMemorySignalProtocolStore();
aliceSessionBuilder = new SessionBuilder(aliceStore, BOB_ADDRESS);
- aliceSessionCipher = new SessionCipher(aliceStore, BOB_ADDRESS);
+ aliceSessionCipher = new SessionCipher(aliceStore, BOB_ADDRESS);
PreKeyBundle anotherBundle = bundleFactory.createBundle(bobStore);
aliceSessionBuilder.process(anotherBundle);
@@ -110,17 +121,24 @@ public void testBasicPreKey()
plaintext = bobSessionCipher.decrypt(new PreKeySignalMessage(outgoingMessage.serialize()));
fail("shouldn't be trusted!");
} catch (UntrustedIdentityException uie) {
- bobStore.saveIdentity(ALICE_ADDRESS, new PreKeySignalMessage(outgoingMessage.serialize()).getIdentityKey());
+ bobStore.saveIdentity(
+ ALICE_ADDRESS, new PreKeySignalMessage(outgoingMessage.serialize()).getIdentityKey());
}
plaintext = bobSessionCipher.decrypt(new PreKeySignalMessage(outgoingMessage.serialize()));
assertTrue(new String(plaintext).equals(originalMessage));
Random random = new Random();
- PreKeyBundle badIdentityBundle = new PreKeyBundle(bobStore.getLocalRegistrationId(), 1,
- random.nextInt(Medium.MAX_VALUE), Curve.generateKeyPair().getPublicKey(),
- random.nextInt(Medium.MAX_VALUE), bobPreKey.getSignedPreKey(), bobPreKey.getSignedPreKeySignature(),
- aliceStore.getIdentityKeyPair().getPublicKey());
+ PreKeyBundle badIdentityBundle =
+ new PreKeyBundle(
+ bobStore.getLocalRegistrationId(),
+ 1,
+ random.nextInt(Medium.MAX_VALUE),
+ Curve.generateKeyPair().getPublicKey(),
+ random.nextInt(Medium.MAX_VALUE),
+ bobPreKey.getSignedPreKey(),
+ bobPreKey.getSignedPreKeySignature(),
+ aliceStore.getIdentityKeyPair().getPublicKey());
try {
aliceSessionBuilder.process(badIdentityBundle);
@@ -131,8 +149,16 @@ public void testBasicPreKey()
}
@Test
- public void testRepeatBundleMessage() throws InvalidKeyException, UntrustedIdentityException, InvalidVersionException, InvalidMessageException, InvalidKeyIdException, DuplicateMessageException, LegacyMessageException, NoSessionException {
- SignalProtocolStore aliceStore = new TestInMemorySignalProtocolStore();
+ public void testRepeatBundleMessage()
+ throws InvalidKeyException,
+ UntrustedIdentityException,
+ InvalidVersionException,
+ InvalidMessageException,
+ InvalidKeyIdException,
+ DuplicateMessageException,
+ LegacyMessageException,
+ NoSessionException {
+ SignalProtocolStore aliceStore = new TestInMemorySignalProtocolStore();
SessionBuilder aliceSessionBuilder = new SessionBuilder(aliceStore, BOB_ADDRESS);
SignalProtocolStore bobStore = new TestInMemorySignalProtocolStore();
@@ -140,8 +166,8 @@ public void testRepeatBundleMessage() throws InvalidKeyException, UntrustedIdent
PreKeyBundle bobPreKey = bundleFactory.createBundle(bobStore);
aliceSessionBuilder.process(bobPreKey);
- String originalMessage = "Good, fast, cheap: pick two";
- SessionCipher aliceSessionCipher = new SessionCipher(aliceStore, BOB_ADDRESS);
+ String originalMessage = "Good, fast, cheap: pick two";
+ SessionCipher aliceSessionCipher = new SessionCipher(aliceStore, BOB_ADDRESS);
CiphertextMessage outgoingMessageOne = aliceSessionCipher.encrypt(originalMessage.getBytes());
CiphertextMessage outgoingMessageTwo = aliceSessionCipher.encrypt(originalMessage.getBytes());
@@ -152,49 +178,60 @@ public void testRepeatBundleMessage() throws InvalidKeyException, UntrustedIdent
SessionCipher bobSessionCipher = new SessionCipher(bobStore, ALICE_ADDRESS);
- byte[] plaintext = bobSessionCipher.decrypt(incomingMessage);
+ byte[] plaintext = bobSessionCipher.decrypt(incomingMessage);
assertTrue(originalMessage.equals(new String(plaintext)));
CiphertextMessage bobOutgoingMessage = bobSessionCipher.encrypt(originalMessage.getBytes());
- byte[] alicePlaintext = aliceSessionCipher.decrypt(new SignalMessage(bobOutgoingMessage.serialize()));
+ byte[] alicePlaintext =
+ aliceSessionCipher.decrypt(new SignalMessage(bobOutgoingMessage.serialize()));
assertTrue(originalMessage.equals(new String(alicePlaintext)));
// The test
- PreKeySignalMessage incomingMessageTwo = new PreKeySignalMessage(outgoingMessageTwo.serialize());
+ PreKeySignalMessage incomingMessageTwo =
+ new PreKeySignalMessage(outgoingMessageTwo.serialize());
plaintext = bobSessionCipher.decrypt(new PreKeySignalMessage(incomingMessageTwo.serialize()));
assertTrue(originalMessage.equals(new String(plaintext)));
bobOutgoingMessage = bobSessionCipher.encrypt(originalMessage.getBytes());
- alicePlaintext = aliceSessionCipher.decrypt(new SignalMessage(bobOutgoingMessage.serialize()));
+ alicePlaintext =
+ aliceSessionCipher.decrypt(new SignalMessage(bobOutgoingMessage.serialize()));
assertTrue(originalMessage.equals(new String(alicePlaintext)));
}
@Test
public void testOptionalOneTimePreKey() throws Exception {
- SignalProtocolStore aliceStore = new TestInMemorySignalProtocolStore();
+ SignalProtocolStore aliceStore = new TestInMemorySignalProtocolStore();
SessionBuilder aliceSessionBuilder = new SessionBuilder(aliceStore, BOB_ADDRESS);
SignalProtocolStore bobStore = new TestInMemorySignalProtocolStore();
- PreKeyBundle bobPreKey = bundleFactory.createBundle(bobStore);
+ PreKeyBundle bobPreKey = bundleFactory.createBundle(bobStore);
// Simply remove the pre-key information from a valid bundle
- bobPreKey = new PreKeyBundle(bobPreKey.getRegistrationId(), 1,
- -1, null,
- bobPreKey.getSignedPreKeyId(), bobPreKey.getSignedPreKey(), bobPreKey.getSignedPreKeySignature(),
- bobPreKey.getIdentityKey(),
- bobPreKey.getKyberPreKeyId(), bobPreKey.getKyberPreKey(), bobPreKey.getKyberPreKeySignature());
+ bobPreKey =
+ new PreKeyBundle(
+ bobPreKey.getRegistrationId(),
+ 1,
+ -1,
+ null,
+ bobPreKey.getSignedPreKeyId(),
+ bobPreKey.getSignedPreKey(),
+ bobPreKey.getSignedPreKeySignature(),
+ bobPreKey.getIdentityKey(),
+ bobPreKey.getKyberPreKeyId(),
+ bobPreKey.getKyberPreKey(),
+ bobPreKey.getKyberPreKeySignature());
aliceSessionBuilder.process(bobPreKey);
assertTrue(aliceStore.containsSession(BOB_ADDRESS));
assertTrue(aliceStore.loadSession(BOB_ADDRESS).getSessionVersion() == expectedVersion);
- String originalMessage = "Good, fast, cheap: pick two";
- SessionCipher aliceSessionCipher = new SessionCipher(aliceStore, BOB_ADDRESS);
- CiphertextMessage outgoingMessage = aliceSessionCipher.encrypt(originalMessage.getBytes());
+ String originalMessage = "Good, fast, cheap: pick two";
+ SessionCipher aliceSessionCipher = new SessionCipher(aliceStore, BOB_ADDRESS);
+ CiphertextMessage outgoingMessage = aliceSessionCipher.encrypt(originalMessage.getBytes());
assertTrue(outgoingMessage.getType() == CiphertextMessage.PREKEY_TYPE);
@@ -202,43 +239,95 @@ public void testOptionalOneTimePreKey() throws Exception {
assertTrue(!incomingMessage.getPreKeyId().isPresent());
SessionCipher bobSessionCipher = new SessionCipher(bobStore, ALICE_ADDRESS);
- byte[] plaintext = bobSessionCipher.decrypt(incomingMessage);
+ byte[] plaintext = bobSessionCipher.decrypt(incomingMessage);
assertTrue(bobStore.containsSession(ALICE_ADDRESS));
assertEquals(bobStore.loadSession(ALICE_ADDRESS).getSessionVersion(), expectedVersion);
assertNotNull(bobStore.loadSession(ALICE_ADDRESS).getAliceBaseKey());
assertEquals(originalMessage, new String(plaintext));
}
- }
+ @Test
+ public void testExpiresUnacknowledgedSessions()
+ throws InvalidKeyException,
+ InvalidVersionException,
+ InvalidMessageException,
+ InvalidKeyIdException,
+ DuplicateMessageException,
+ LegacyMessageException,
+ UntrustedIdentityException,
+ NoSessionException {
+ SignalProtocolStore aliceStore = new TestInMemorySignalProtocolStore();
+ SessionBuilder aliceSessionBuilder = new SessionBuilder(aliceStore, BOB_ADDRESS);
+
+ final SignalProtocolStore bobStore = new TestInMemorySignalProtocolStore();
+
+ PreKeyBundle bobPreKey = bundleFactory.createBundle(bobStore);
+
+ aliceSessionBuilder.process(bobPreKey, Instant.EPOCH);
+
+ SessionRecord initialSession = aliceStore.loadSession(BOB_ADDRESS);
+ assertTrue(initialSession.hasSenderChain(Instant.EPOCH));
+ assertFalse(initialSession.hasSenderChain(Instant.EPOCH.plus(90, ChronoUnit.DAYS)));
+
+ String originalMessage = "Good, fast, cheap: pick two";
+ SessionCipher aliceSessionCipher = new SessionCipher(aliceStore, BOB_ADDRESS);
+ CiphertextMessage outgoingMessage =
+ aliceSessionCipher.encrypt(originalMessage.getBytes(), Instant.EPOCH);
+
+ assertTrue(outgoingMessage.getType() == CiphertextMessage.PREKEY_TYPE);
+
+ SessionRecord updatedSession = aliceStore.loadSession(BOB_ADDRESS);
+ assertTrue(updatedSession.hasSenderChain(Instant.EPOCH));
+ assertFalse(updatedSession.hasSenderChain(Instant.EPOCH.plus(90, ChronoUnit.DAYS)));
+
+ try {
+ aliceSessionCipher.encrypt(
+ originalMessage.getBytes(), Instant.EPOCH.plus(90, ChronoUnit.DAYS));
+ fail("should have expired");
+ } catch (NoSessionException e) {
+ // Expected
+ }
+ }
+ }
public static class VersionAgnostic {
@Test
- public void testBadSignedPreKeySignature() throws InvalidKeyException, UntrustedIdentityException {
- SignalProtocolStore aliceStore = new TestInMemorySignalProtocolStore();
+ public void testBadSignedPreKeySignature()
+ throws InvalidKeyException, UntrustedIdentityException {
+ SignalProtocolStore aliceStore = new TestInMemorySignalProtocolStore();
SessionBuilder aliceSessionBuilder = new SessionBuilder(aliceStore, BOB_ADDRESS);
IdentityKeyStore bobIdentityKeyStore = new TestInMemoryIdentityKeyStore();
- ECKeyPair bobPreKeyPair = Curve.generateKeyPair();
- ECKeyPair bobSignedPreKeyPair = Curve.generateKeyPair();
- byte[] bobSignedPreKeySignature = Curve.calculateSignature(
- bobIdentityKeyStore.getIdentityKeyPair().getPrivateKey(),
- bobSignedPreKeyPair.getPublicKey().serialize());
-
+ ECKeyPair bobPreKeyPair = Curve.generateKeyPair();
+ ECKeyPair bobSignedPreKeyPair = Curve.generateKeyPair();
+ byte[] bobSignedPreKeySignature =
+ Curve.calculateSignature(
+ bobIdentityKeyStore.getIdentityKeyPair().getPrivateKey(),
+ bobSignedPreKeyPair.getPublicKey().serialize());
- for (int i=0;i> aliceOutOfOrderMessages = new HashSet<>();
- for (int i=0;i<10;i++) {
- String loopingMessage = ("What do we mean by saying that existence precedes essence? " +
- "We mean that man first of all exists, encounters himself, " +
- "surges up in the world--and defines himself aftward. " + i);
+ for (int i = 0; i < 10; i++) {
+ String loopingMessage =
+ ("What do we mean by saying that existence precedes essence? "
+ + "We mean that man first of all exists, encounters himself, "
+ + "surges up in the world--and defines himself aftward. "
+ + i);
CiphertextMessage aliceLoopingMessage = aliceSessionCipher.encrypt(loopingMessage.getBytes());
aliceOutOfOrderMessages.add(new Pair<>(loopingMessage, aliceLoopingMessage));
}
- for (int i=0;i<10;i++) {
- String loopingMessage = ("What do we mean by saying that existence precedes essence? " +
- "We mean that man first of all exists, encounters himself, " +
- "surges up in the world--and defines himself aftward. " + i);
+ for (int i = 0; i < 10; i++) {
+ String loopingMessage =
+ ("What do we mean by saying that existence precedes essence? "
+ + "We mean that man first of all exists, encounters himself, "
+ + "surges up in the world--and defines himself aftward. "
+ + i);
CiphertextMessage aliceLoopingMessage = aliceSessionCipher.encrypt(loopingMessage.getBytes());
- byte[] loopingPlaintext = bobSessionCipher.decrypt(new SignalMessage(aliceLoopingMessage.serialize()));
+ byte[] loopingPlaintext =
+ bobSessionCipher.decrypt(new SignalMessage(aliceLoopingMessage.serialize()));
assertTrue(new String(loopingPlaintext).equals(loopingMessage));
}
- for (int i=0;i<10;i++) {
+ for (int i = 0; i < 10; i++) {
String loopingMessage = ("You can only desire based on what you know: " + i);
CiphertextMessage bobLoopingMessage = bobSessionCipher.encrypt(loopingMessage.getBytes());
- byte[] loopingPlaintext = aliceSessionCipher.decrypt(new SignalMessage(bobLoopingMessage.serialize()));
+ byte[] loopingPlaintext =
+ aliceSessionCipher.decrypt(new SignalMessage(bobLoopingMessage.serialize()));
assertTrue(new String(loopingPlaintext).equals(loopingMessage));
}
for (Pair aliceOutOfOrderMessage : aliceOutOfOrderMessages) {
- byte[] outOfOrderPlaintext = bobSessionCipher.decrypt(new SignalMessage(aliceOutOfOrderMessage.second().serialize()));
+ byte[] outOfOrderPlaintext =
+ bobSessionCipher.decrypt(new SignalMessage(aliceOutOfOrderMessage.second().serialize()));
assertTrue(new String(outOfOrderPlaintext).equals(aliceOutOfOrderMessage.first()));
}
}
-
}
diff --git a/java/client/src/test/java/org/signal/libsignal/protocol/SessionCipherTest.java b/java/client/src/test/java/org/signal/libsignal/protocol/SessionCipherTest.java
index 83d843c3b2..00b7795504 100644
--- a/java/client/src/test/java/org/signal/libsignal/protocol/SessionCipherTest.java
+++ b/java/client/src/test/java/org/signal/libsignal/protocol/SessionCipherTest.java
@@ -1,16 +1,9 @@
-package org.signal.libsignal.protocol;
-
-import junit.framework.TestCase;
+//
+// Copyright 2023 Signal Messenger, LLC.
+// SPDX-License-Identifier: AGPL-3.0-only
+//
-import org.signal.libsignal.protocol.ecc.Curve;
-import org.signal.libsignal.protocol.ecc.ECKeyPair;
-import org.signal.libsignal.protocol.ecc.ECPublicKey;
-import org.signal.libsignal.protocol.ecc.ECPrivateKey;
-import org.signal.libsignal.protocol.message.CiphertextMessage;
-import org.signal.libsignal.protocol.message.SignalMessage;
-import org.signal.libsignal.protocol.state.SignalProtocolStore;
-import org.signal.libsignal.protocol.state.SessionRecord;
-import org.signal.libsignal.protocol.util.Pair;
+package org.signal.libsignal.protocol;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
@@ -19,7 +12,13 @@
import java.util.LinkedList;
import java.util.List;
import java.util.Random;
-
+import junit.framework.TestCase;
+import org.signal.libsignal.protocol.ecc.Curve;
+import org.signal.libsignal.protocol.ecc.ECKeyPair;
+import org.signal.libsignal.protocol.message.CiphertextMessage;
+import org.signal.libsignal.protocol.message.SignalMessage;
+import org.signal.libsignal.protocol.state.SessionRecord;
+import org.signal.libsignal.protocol.state.SignalProtocolStore;
public class SessionCipherTest extends TestCase {
@@ -34,9 +33,14 @@ public PairOfSessions(SessionRecord a, SessionRecord b) {
}
public void testBasicSessionV3()
- throws InvalidKeyException, DuplicateMessageException,
- LegacyMessageException, InvalidMessageException, InvalidVersionException, NoSuchAlgorithmException, NoSessionException, UntrustedIdentityException
- {
+ throws InvalidKeyException,
+ DuplicateMessageException,
+ LegacyMessageException,
+ InvalidMessageException,
+ InvalidVersionException,
+ NoSuchAlgorithmException,
+ NoSessionException,
+ UntrustedIdentityException {
PairOfSessions sessions = initializeSessionsV3();
runInteraction(sessions.aliceSession, sessions.bobSession);
}
@@ -45,22 +49,25 @@ public void testMessageKeyLimits() throws Exception {
PairOfSessions sessions = initializeSessionsV3();
SignalProtocolStore aliceStore = new TestInMemorySignalProtocolStore();
- SignalProtocolStore bobStore = new TestInMemorySignalProtocolStore();
+ SignalProtocolStore bobStore = new TestInMemorySignalProtocolStore();
aliceStore.storeSession(new SignalProtocolAddress("+14159999999", 1), sessions.aliceSession);
bobStore.storeSession(new SignalProtocolAddress("+14158888888", 1), sessions.bobSession);
- SessionCipher aliceCipher = new SessionCipher(aliceStore, new SignalProtocolAddress("+14159999999", 1));
- SessionCipher bobCipher = new SessionCipher(bobStore, new SignalProtocolAddress("+14158888888", 1));
+ SessionCipher aliceCipher =
+ new SessionCipher(aliceStore, new SignalProtocolAddress("+14159999999", 1));
+ SessionCipher bobCipher =
+ new SessionCipher(bobStore, new SignalProtocolAddress("+14158888888", 1));
List inflight = new LinkedList<>();
- for (int i=0;i<2010;i++) {
- inflight.add(aliceCipher.encrypt("you've never been so hungry, you've never been so cold".getBytes()));
+ for (int i = 0; i < 2010; i++) {
+ inflight.add(
+ aliceCipher.encrypt("you've never been so hungry, you've never been so cold".getBytes()));
}
bobCipher.decrypt(new SignalMessage(inflight.get(1000).serialize()));
- bobCipher.decrypt(new SignalMessage(inflight.get(inflight.size()-1).serialize()));
+ bobCipher.decrypt(new SignalMessage(inflight.get(inflight.size() - 1).serialize()));
try {
bobCipher.decrypt(new SignalMessage(inflight.get(0).serialize()));
@@ -74,7 +81,7 @@ public void testDecryptAfterReset() throws Exception {
PairOfSessions sessions = initializeSessionsV3();
SignalProtocolStore aliceStore = new TestInMemorySignalProtocolStore();
- SignalProtocolStore bobStore = new TestInMemorySignalProtocolStore();
+ SignalProtocolStore bobStore = new TestInMemorySignalProtocolStore();
SignalProtocolAddress aliceAddress = new SignalProtocolAddress("+14159999999", 1);
SignalProtocolAddress bobAddress = new SignalProtocolAddress("+141588888888", 1);
@@ -82,12 +89,12 @@ public void testDecryptAfterReset() throws Exception {
aliceStore.storeSession(bobAddress, sessions.aliceSession);
bobStore.storeSession(aliceAddress, sessions.bobSession);
- SessionCipher aliceCipher = new SessionCipher(aliceStore, bobAddress);
- SessionCipher bobCipher = new SessionCipher(bobStore, aliceAddress);
+ SessionCipher aliceCipher = new SessionCipher(aliceStore, bobAddress);
+ SessionCipher bobCipher = new SessionCipher(bobStore, aliceAddress);
- byte[] alicePlaintext = "This is a plaintext message.".getBytes();
- CiphertextMessage message = aliceCipher.encrypt(alicePlaintext);
- byte[] bobPlaintext = bobCipher.decrypt(new SignalMessage(message.serialize()));
+ byte[] alicePlaintext = "This is a plaintext message.".getBytes();
+ CiphertextMessage message = aliceCipher.encrypt(alicePlaintext);
+ byte[] bobPlaintext = bobCipher.decrypt(new SignalMessage(message.serialize()));
assertTrue(Arrays.equals(alicePlaintext, bobPlaintext));
@@ -107,7 +114,7 @@ public void testDecryptAfterDelete() throws Exception {
PairOfSessions sessions = initializeSessionsV3();
SignalProtocolStore aliceStore = new TestInMemorySignalProtocolStore();
- SignalProtocolStore bobStore = new TestInMemorySignalProtocolStore();
+ SignalProtocolStore bobStore = new TestInMemorySignalProtocolStore();
SignalProtocolAddress aliceAddress = new SignalProtocolAddress("+14159999999", 1);
SignalProtocolAddress bobAddress = new SignalProtocolAddress("+141588888888", 1);
@@ -115,12 +122,12 @@ public void testDecryptAfterDelete() throws Exception {
aliceStore.storeSession(bobAddress, sessions.aliceSession);
bobStore.storeSession(aliceAddress, sessions.bobSession);
- SessionCipher aliceCipher = new SessionCipher(aliceStore, bobAddress);
- SessionCipher bobCipher = new SessionCipher(bobStore, aliceAddress);
+ SessionCipher aliceCipher = new SessionCipher(aliceStore, bobAddress);
+ SessionCipher bobCipher = new SessionCipher(bobStore, aliceAddress);
- byte[] alicePlaintext = "This is a plaintext message.".getBytes();
- CiphertextMessage message = aliceCipher.encrypt(alicePlaintext);
- byte[] bobPlaintext = bobCipher.decrypt(new SignalMessage(message.serialize()));
+ byte[] alicePlaintext = "This is a plaintext message.".getBytes();
+ CiphertextMessage message = aliceCipher.encrypt(alicePlaintext);
+ byte[] bobPlaintext = bobCipher.decrypt(new SignalMessage(message.serialize()));
assertTrue(Arrays.equals(alicePlaintext, bobPlaintext));
@@ -135,32 +142,41 @@ public void testDecryptAfterDelete() throws Exception {
}
private void runInteraction(SessionRecord aliceSessionRecord, SessionRecord bobSessionRecord)
- throws DuplicateMessageException, LegacyMessageException, InvalidMessageException, InvalidVersionException, InvalidKeyException, NoSuchAlgorithmException, NoSessionException, UntrustedIdentityException {
+ throws DuplicateMessageException,
+ LegacyMessageException,
+ InvalidMessageException,
+ InvalidVersionException,
+ InvalidKeyException,
+ NoSuchAlgorithmException,
+ NoSessionException,
+ UntrustedIdentityException {
SignalProtocolStore aliceStore = new TestInMemorySignalProtocolStore();
- SignalProtocolStore bobStore = new TestInMemorySignalProtocolStore();
+ SignalProtocolStore bobStore = new TestInMemorySignalProtocolStore();
aliceStore.storeSession(new SignalProtocolAddress("+14159999999", 1), aliceSessionRecord);
bobStore.storeSession(new SignalProtocolAddress("+14158888888", 1), bobSessionRecord);
- SessionCipher aliceCipher = new SessionCipher(aliceStore, new SignalProtocolAddress("+14159999999", 1));
- SessionCipher bobCipher = new SessionCipher(bobStore, new SignalProtocolAddress("+14158888888", 1));
+ SessionCipher aliceCipher =
+ new SessionCipher(aliceStore, new SignalProtocolAddress("+14159999999", 1));
+ SessionCipher bobCipher =
+ new SessionCipher(bobStore, new SignalProtocolAddress("+14158888888", 1));
- byte[] alicePlaintext = "This is a plaintext message.".getBytes();
- CiphertextMessage message = aliceCipher.encrypt(alicePlaintext);
- byte[] bobPlaintext = bobCipher.decrypt(new SignalMessage(message.serialize()));
+ byte[] alicePlaintext = "This is a plaintext message.".getBytes();
+ CiphertextMessage message = aliceCipher.encrypt(alicePlaintext);
+ byte[] bobPlaintext = bobCipher.decrypt(new SignalMessage(message.serialize()));
assertTrue(Arrays.equals(alicePlaintext, bobPlaintext));
- byte[] bobReply = "This is a message from Bob.".getBytes();
- CiphertextMessage reply = bobCipher.encrypt(bobReply);
- byte[] receivedReply = aliceCipher.decrypt(new SignalMessage(reply.serialize()));
+ byte[] bobReply = "This is a message from Bob.".getBytes();
+ CiphertextMessage reply = bobCipher.encrypt(bobReply);
+ byte[] receivedReply = aliceCipher.decrypt(new SignalMessage(reply.serialize()));
assertTrue(Arrays.equals(bobReply, receivedReply));
List aliceCiphertextMessages = new ArrayList<>();
- List alicePlaintextMessages = new ArrayList<>();
+ List alicePlaintextMessages = new ArrayList<>();
- for (int i=0;i<50;i++) {
+ for (int i = 0; i < 50; i++) {
alicePlaintextMessages.add(("alice message " + i).getBytes());
aliceCiphertextMessages.add(aliceCipher.encrypt(("alice message " + i).getBytes()));
}
@@ -170,15 +186,16 @@ private void runInteraction(SessionRecord aliceSessionRecord, SessionRecord bobS
Collections.shuffle(aliceCiphertextMessages, new Random(seed));
Collections.shuffle(alicePlaintextMessages, new Random(seed));
- for (int i=0;i bobCiphertextMessages = new ArrayList<>();
- List bobPlaintextMessages = new ArrayList<>();
+ List bobPlaintextMessages = new ArrayList<>();
- for (int i=0;i<20;i++) {
+ for (int i = 0; i < 20; i++) {
bobPlaintextMessages.add(("bob message " + i).getBytes());
bobCiphertextMessages.add(bobCipher.encrypt(("bob message " + i).getBytes()));
}
@@ -188,52 +205,61 @@ private void runInteraction(SessionRecord aliceSessionRecord, SessionRecord bobS
Collections.shuffle(bobCiphertextMessages, new Random(seed));
Collections.shuffle(bobPlaintextMessages, new Random(seed));
- for (int i=0;i data() throws Exception {
- return Arrays.asList(new Object[][] {
- {new X3DHBundleFactory(), 3},
- {new PQXDHBundleFactory(), 4}
- });
+ return Arrays.asList(
+ new Object[][] {
+ {new X3DHBundleFactory(), 3},
+ {new PQXDHBundleFactory(), 4}
+ });
}
@Test
public void testBasicSimultaneousInitiate()
- throws InvalidKeyException, UntrustedIdentityException, InvalidVersionException,
- InvalidMessageException, DuplicateMessageException, LegacyMessageException,
- InvalidKeyIdException, NoSessionException
- {
+ throws InvalidKeyException,
+ UntrustedIdentityException,
+ InvalidVersionException,
+ InvalidMessageException,
+ DuplicateMessageException,
+ LegacyMessageException,
+ InvalidKeyIdException,
+ NoSessionException {
SignalProtocolStore aliceStore = new TestInMemorySignalProtocolStore();
- SignalProtocolStore bobStore = new TestInMemorySignalProtocolStore();
+ SignalProtocolStore bobStore = new TestInMemorySignalProtocolStore();
PreKeyBundle alicePreKeyBundle = bundleFactory.createBundle(aliceStore);
- PreKeyBundle bobPreKeyBundle = bundleFactory.createBundle(bobStore);
+ PreKeyBundle bobPreKeyBundle = bundleFactory.createBundle(bobStore);
SessionBuilder aliceSessionBuilder = new SessionBuilder(aliceStore, BOB_ADDRESS);
- SessionBuilder bobSessionBuilder = new SessionBuilder(bobStore, ALICE_ADDRESS);
+ SessionBuilder bobSessionBuilder = new SessionBuilder(bobStore, ALICE_ADDRESS);
SessionCipher aliceSessionCipher = new SessionCipher(aliceStore, BOB_ADDRESS);
SessionCipher bobSessionCipher = new SessionCipher(bobStore, ALICE_ADDRESS);
@@ -69,7 +71,7 @@ public void testBasicSimultaneousInitiate()
aliceSessionBuilder.process(bobPreKeyBundle);
bobSessionBuilder.process(alicePreKeyBundle);
- CiphertextMessage messageForBob = aliceSessionCipher.encrypt("hey there".getBytes());
+ CiphertextMessage messageForBob = aliceSessionCipher.encrypt("hey there".getBytes());
CiphertextMessage messageForAlice = bobSessionCipher.encrypt("sample message".getBytes());
assertEquals(messageForBob.getType(), CiphertextMessage.PREKEY_TYPE);
@@ -78,8 +80,10 @@ public void testBasicSimultaneousInitiate()
assertSessionIdNotEquals(aliceStore, bobStore);
assertSessionIdNotEquals(aliceStore, bobStore);
- byte[] alicePlaintext = aliceSessionCipher.decrypt(new PreKeySignalMessage(messageForAlice.serialize()));
- byte[] bobPlaintext = bobSessionCipher.decrypt(new PreKeySignalMessage(messageForBob.serialize()));
+ byte[] alicePlaintext =
+ aliceSessionCipher.decrypt(new PreKeySignalMessage(messageForAlice.serialize()));
+ byte[] bobPlaintext =
+ bobSessionCipher.decrypt(new PreKeySignalMessage(messageForBob.serialize()));
assertTrue(new String(alicePlaintext).equals("sample message"));
assertTrue(new String(bobPlaintext).equals("hey there"));
@@ -93,7 +97,8 @@ public void testBasicSimultaneousInitiate()
assertEquals(aliceResponse.getType(), CiphertextMessage.WHISPER_TYPE);
- byte[] responsePlaintext = bobSessionCipher.decrypt(new SignalMessage(aliceResponse.serialize()));
+ byte[] responsePlaintext =
+ bobSessionCipher.decrypt(new SignalMessage(aliceResponse.serialize()));
assertTrue(new String(responsePlaintext).equals("second message"));
assertSessionIdEquals(aliceStore, bobStore);
@@ -110,18 +115,22 @@ public void testBasicSimultaneousInitiate()
@Test
public void testLostSimultaneousInitiate()
- throws InvalidKeyException, UntrustedIdentityException, InvalidVersionException,
- InvalidMessageException, DuplicateMessageException, LegacyMessageException,
- InvalidKeyIdException, NoSessionException
- {
+ throws InvalidKeyException,
+ UntrustedIdentityException,
+ InvalidVersionException,
+ InvalidMessageException,
+ DuplicateMessageException,
+ LegacyMessageException,
+ InvalidKeyIdException,
+ NoSessionException {
SignalProtocolStore aliceStore = new TestInMemorySignalProtocolStore();
- SignalProtocolStore bobStore = new TestInMemorySignalProtocolStore();
+ SignalProtocolStore bobStore = new TestInMemorySignalProtocolStore();
PreKeyBundle alicePreKeyBundle = bundleFactory.createBundle(aliceStore);
- PreKeyBundle bobPreKeyBundle = bundleFactory.createBundle(bobStore);
+ PreKeyBundle bobPreKeyBundle = bundleFactory.createBundle(bobStore);
SessionBuilder aliceSessionBuilder = new SessionBuilder(aliceStore, BOB_ADDRESS);
- SessionBuilder bobSessionBuilder = new SessionBuilder(bobStore, ALICE_ADDRESS);
+ SessionBuilder bobSessionBuilder = new SessionBuilder(bobStore, ALICE_ADDRESS);
SessionCipher aliceSessionCipher = new SessionCipher(aliceStore, BOB_ADDRESS);
SessionCipher bobSessionCipher = new SessionCipher(bobStore, ALICE_ADDRESS);
@@ -129,7 +138,7 @@ public void testLostSimultaneousInitiate()
aliceSessionBuilder.process(bobPreKeyBundle);
bobSessionBuilder.process(alicePreKeyBundle);
- CiphertextMessage messageForBob = aliceSessionCipher.encrypt("hey there".getBytes());
+ CiphertextMessage messageForBob = aliceSessionCipher.encrypt("hey there".getBytes());
CiphertextMessage messageForAlice = bobSessionCipher.encrypt("sample message".getBytes());
assertEquals(messageForBob.getType(), CiphertextMessage.PREKEY_TYPE);
@@ -137,7 +146,8 @@ public void testLostSimultaneousInitiate()
assertSessionIdNotEquals(aliceStore, bobStore);
- byte[] bobPlaintext = bobSessionCipher.decrypt(new PreKeySignalMessage(messageForBob.serialize()));
+ byte[] bobPlaintext =
+ bobSessionCipher.decrypt(new PreKeySignalMessage(messageForBob.serialize()));
assertTrue(new String(bobPlaintext).equals("hey there"));
assertEquals(bobStore.loadSession(ALICE_ADDRESS).getSessionVersion(), expectedVersion);
@@ -146,7 +156,8 @@ public void testLostSimultaneousInitiate()
assertEquals(aliceResponse.getType(), CiphertextMessage.PREKEY_TYPE);
- byte[] responsePlaintext = bobSessionCipher.decrypt(new PreKeySignalMessage(aliceResponse.serialize()));
+ byte[] responsePlaintext =
+ bobSessionCipher.decrypt(new PreKeySignalMessage(aliceResponse.serialize()));
assertTrue(new String(responsePlaintext).equals("second message"));
assertSessionIdEquals(aliceStore, bobStore);
@@ -163,18 +174,22 @@ public void testLostSimultaneousInitiate()
@Test
public void testSimultaneousInitiateLostMessage()
- throws InvalidKeyException, UntrustedIdentityException, InvalidVersionException,
- InvalidMessageException, DuplicateMessageException, LegacyMessageException,
- InvalidKeyIdException, NoSessionException
- {
+ throws InvalidKeyException,
+ UntrustedIdentityException,
+ InvalidVersionException,
+ InvalidMessageException,
+ DuplicateMessageException,
+ LegacyMessageException,
+ InvalidKeyIdException,
+ NoSessionException {
SignalProtocolStore aliceStore = new TestInMemorySignalProtocolStore();
- SignalProtocolStore bobStore = new TestInMemorySignalProtocolStore();
+ SignalProtocolStore bobStore = new TestInMemorySignalProtocolStore();
PreKeyBundle alicePreKeyBundle = bundleFactory.createBundle(aliceStore);
- PreKeyBundle bobPreKeyBundle = bundleFactory.createBundle(bobStore);
+ PreKeyBundle bobPreKeyBundle = bundleFactory.createBundle(bobStore);
SessionBuilder aliceSessionBuilder = new SessionBuilder(aliceStore, BOB_ADDRESS);
- SessionBuilder bobSessionBuilder = new SessionBuilder(bobStore, ALICE_ADDRESS);
+ SessionBuilder bobSessionBuilder = new SessionBuilder(bobStore, ALICE_ADDRESS);
SessionCipher aliceSessionCipher = new SessionCipher(aliceStore, BOB_ADDRESS);
SessionCipher bobSessionCipher = new SessionCipher(bobStore, ALICE_ADDRESS);
@@ -182,7 +197,7 @@ public void testSimultaneousInitiateLostMessage()
aliceSessionBuilder.process(bobPreKeyBundle);
bobSessionBuilder.process(alicePreKeyBundle);
- CiphertextMessage messageForBob = aliceSessionCipher.encrypt("hey there".getBytes());
+ CiphertextMessage messageForBob = aliceSessionCipher.encrypt("hey there".getBytes());
CiphertextMessage messageForAlice = bobSessionCipher.encrypt("sample message".getBytes());
assertEquals(messageForBob.getType(), CiphertextMessage.PREKEY_TYPE);
@@ -190,8 +205,10 @@ public void testSimultaneousInitiateLostMessage()
assertSessionIdNotEquals(aliceStore, bobStore);
- byte[] alicePlaintext = aliceSessionCipher.decrypt(new PreKeySignalMessage(messageForAlice.serialize()));
- byte[] bobPlaintext = bobSessionCipher.decrypt(new PreKeySignalMessage(messageForBob.serialize()));
+ byte[] alicePlaintext =
+ aliceSessionCipher.decrypt(new PreKeySignalMessage(messageForAlice.serialize()));
+ byte[] bobPlaintext =
+ bobSessionCipher.decrypt(new PreKeySignalMessage(messageForBob.serialize()));
assertTrue(new String(alicePlaintext).equals("sample message"));
assertTrue(new String(bobPlaintext).equals("hey there"));
@@ -219,18 +236,22 @@ public void testSimultaneousInitiateLostMessage()
@Test
public void testSimultaneousInitiateRepeatedMessages()
- throws InvalidKeyException, UntrustedIdentityException, InvalidVersionException,
- InvalidMessageException, DuplicateMessageException, LegacyMessageException,
- InvalidKeyIdException, NoSessionException
- {
+ throws InvalidKeyException,
+ UntrustedIdentityException,
+ InvalidVersionException,
+ InvalidMessageException,
+ DuplicateMessageException,
+ LegacyMessageException,
+ InvalidKeyIdException,
+ NoSessionException {
SignalProtocolStore aliceStore = new TestInMemorySignalProtocolStore();
- SignalProtocolStore bobStore = new TestInMemorySignalProtocolStore();
+ SignalProtocolStore bobStore = new TestInMemorySignalProtocolStore();
PreKeyBundle alicePreKeyBundle = bundleFactory.createBundle(aliceStore);
- PreKeyBundle bobPreKeyBundle = bundleFactory.createBundle(bobStore);
+ PreKeyBundle bobPreKeyBundle = bundleFactory.createBundle(bobStore);
SessionBuilder aliceSessionBuilder = new SessionBuilder(aliceStore, BOB_ADDRESS);
- SessionBuilder bobSessionBuilder = new SessionBuilder(bobStore, ALICE_ADDRESS);
+ SessionBuilder bobSessionBuilder = new SessionBuilder(bobStore, ALICE_ADDRESS);
SessionCipher aliceSessionCipher = new SessionCipher(aliceStore, BOB_ADDRESS);
SessionCipher bobSessionCipher = new SessionCipher(bobStore, ALICE_ADDRESS);
@@ -238,7 +259,7 @@ public void testSimultaneousInitiateRepeatedMessages()
aliceSessionBuilder.process(bobPreKeyBundle);
bobSessionBuilder.process(alicePreKeyBundle);
- CiphertextMessage messageForBob = aliceSessionCipher.encrypt("hey there".getBytes());
+ CiphertextMessage messageForBob = aliceSessionCipher.encrypt("hey there".getBytes());
CiphertextMessage messageForAlice = bobSessionCipher.encrypt("sample message".getBytes());
assertEquals(messageForBob.getType(), CiphertextMessage.PREKEY_TYPE);
@@ -246,8 +267,10 @@ public void testSimultaneousInitiateRepeatedMessages()
assertSessionIdNotEquals(aliceStore, bobStore);
- byte[] alicePlaintext = aliceSessionCipher.decrypt(new PreKeySignalMessage(messageForAlice.serialize()));
- byte[] bobPlaintext = bobSessionCipher.decrypt(new PreKeySignalMessage(messageForBob.serialize()));
+ byte[] alicePlaintext =
+ aliceSessionCipher.decrypt(new PreKeySignalMessage(messageForAlice.serialize()));
+ byte[] bobPlaintext =
+ bobSessionCipher.decrypt(new PreKeySignalMessage(messageForBob.serialize()));
assertTrue(new String(alicePlaintext).equals("sample message"));
assertTrue(new String(bobPlaintext).equals("hey there"));
@@ -257,17 +280,20 @@ public void testSimultaneousInitiateRepeatedMessages()
assertSessionIdNotEquals(aliceStore, bobStore);
- for (int i=0;i<50;i++) {
- CiphertextMessage messageForBobRepeat = aliceSessionCipher.encrypt("hey there".getBytes());
- CiphertextMessage messageForAliceRepeat = bobSessionCipher.encrypt("sample message".getBytes());
+ for (int i = 0; i < 50; i++) {
+ CiphertextMessage messageForBobRepeat = aliceSessionCipher.encrypt("hey there".getBytes());
+ CiphertextMessage messageForAliceRepeat =
+ bobSessionCipher.encrypt("sample message".getBytes());
assertEquals(messageForBobRepeat.getType(), CiphertextMessage.WHISPER_TYPE);
assertEquals(messageForAliceRepeat.getType(), CiphertextMessage.WHISPER_TYPE);
assertSessionIdNotEquals(aliceStore, bobStore);
- byte[] alicePlaintextRepeat = aliceSessionCipher.decrypt(new SignalMessage(messageForAliceRepeat.serialize()));
- byte[] bobPlaintextRepeat = bobSessionCipher.decrypt(new SignalMessage(messageForBobRepeat.serialize()));
+ byte[] alicePlaintextRepeat =
+ aliceSessionCipher.decrypt(new SignalMessage(messageForAliceRepeat.serialize()));
+ byte[] bobPlaintextRepeat =
+ bobSessionCipher.decrypt(new SignalMessage(messageForBobRepeat.serialize()));
assertTrue(new String(alicePlaintextRepeat).equals("sample message"));
assertTrue(new String(bobPlaintextRepeat).equals("hey there"));
@@ -279,7 +305,8 @@ public void testSimultaneousInitiateRepeatedMessages()
assertEquals(aliceResponse.getType(), CiphertextMessage.WHISPER_TYPE);
- byte[] responsePlaintext = bobSessionCipher.decrypt(new SignalMessage(aliceResponse.serialize()));
+ byte[] responsePlaintext =
+ bobSessionCipher.decrypt(new SignalMessage(aliceResponse.serialize()));
assertTrue(new String(responsePlaintext).equals("second message"));
assertSessionIdEquals(aliceStore, bobStore);
@@ -296,22 +323,26 @@ public void testSimultaneousInitiateRepeatedMessages()
@Test
public void testRepeatedSimultaneousInitiateRepeatedMessages()
- throws InvalidKeyException, UntrustedIdentityException, InvalidVersionException,
- InvalidMessageException, DuplicateMessageException, LegacyMessageException,
- InvalidKeyIdException, NoSessionException
- {
+ throws InvalidKeyException,
+ UntrustedIdentityException,
+ InvalidVersionException,
+ InvalidMessageException,
+ DuplicateMessageException,
+ LegacyMessageException,
+ InvalidKeyIdException,
+ NoSessionException {
SignalProtocolStore aliceStore = new TestInMemorySignalProtocolStore();
- SignalProtocolStore bobStore = new TestInMemorySignalProtocolStore();
+ SignalProtocolStore bobStore = new TestInMemorySignalProtocolStore();
SessionBuilder aliceSessionBuilder = new SessionBuilder(aliceStore, BOB_ADDRESS);
- SessionBuilder bobSessionBuilder = new SessionBuilder(bobStore, ALICE_ADDRESS);
+ SessionBuilder bobSessionBuilder = new SessionBuilder(bobStore, ALICE_ADDRESS);
SessionCipher aliceSessionCipher = new SessionCipher(aliceStore, BOB_ADDRESS);
SessionCipher bobSessionCipher = new SessionCipher(bobStore, ALICE_ADDRESS);
- for (int i=0;i<15;i++) {
+ for (int i = 0; i < 15; i++) {
PreKeyBundle alicePreKeyBundle = bundleFactory.createBundle(aliceStore);
- PreKeyBundle bobPreKeyBundle = bundleFactory.createBundle(bobStore);
+ PreKeyBundle bobPreKeyBundle = bundleFactory.createBundle(bobStore);
aliceSessionBuilder.process(bobPreKeyBundle);
bobSessionBuilder.process(alicePreKeyBundle);
@@ -324,8 +355,10 @@ public void testRepeatedSimultaneousInitiateRepeatedMessages()
assertSessionIdNotEquals(aliceStore, bobStore);
- byte[] alicePlaintext = aliceSessionCipher.decrypt(new PreKeySignalMessage(messageForAlice.serialize()));
- byte[] bobPlaintext = bobSessionCipher.decrypt(new PreKeySignalMessage(messageForBob.serialize()));
+ byte[] alicePlaintext =
+ aliceSessionCipher.decrypt(new PreKeySignalMessage(messageForAlice.serialize()));
+ byte[] bobPlaintext =
+ bobSessionCipher.decrypt(new PreKeySignalMessage(messageForBob.serialize()));
assertTrue(new String(alicePlaintext).equals("sample message"));
assertTrue(new String(bobPlaintext).equals("hey there"));
@@ -336,17 +369,20 @@ public void testRepeatedSimultaneousInitiateRepeatedMessages()
assertFalse(isSessionIdEqual(aliceStore, bobStore));
}
- for (int i=0;i<50;i++) {
- CiphertextMessage messageForBobRepeat = aliceSessionCipher.encrypt("hey there".getBytes());
- CiphertextMessage messageForAliceRepeat = bobSessionCipher.encrypt("sample message".getBytes());
+ for (int i = 0; i < 50; i++) {
+ CiphertextMessage messageForBobRepeat = aliceSessionCipher.encrypt("hey there".getBytes());
+ CiphertextMessage messageForAliceRepeat =
+ bobSessionCipher.encrypt("sample message".getBytes());
assertEquals(messageForBobRepeat.getType(), CiphertextMessage.WHISPER_TYPE);
assertEquals(messageForAliceRepeat.getType(), CiphertextMessage.WHISPER_TYPE);
assertFalse(isSessionIdEqual(aliceStore, bobStore));
- byte[] alicePlaintextRepeat = aliceSessionCipher.decrypt(new SignalMessage(messageForAliceRepeat.serialize()));
- byte[] bobPlaintextRepeat = bobSessionCipher.decrypt(new SignalMessage(messageForBobRepeat.serialize()));
+ byte[] alicePlaintextRepeat =
+ aliceSessionCipher.decrypt(new SignalMessage(messageForAliceRepeat.serialize()));
+ byte[] bobPlaintextRepeat =
+ bobSessionCipher.decrypt(new SignalMessage(messageForBobRepeat.serialize()));
assertTrue(new String(alicePlaintextRepeat).equals("sample message"));
assertTrue(new String(bobPlaintextRepeat).equals("hey there"));
@@ -358,7 +394,8 @@ public void testRepeatedSimultaneousInitiateRepeatedMessages()
assertEquals(aliceResponse.getType(), CiphertextMessage.WHISPER_TYPE);
- byte[] responsePlaintext = bobSessionCipher.decrypt(new SignalMessage(aliceResponse.serialize()));
+ byte[] responsePlaintext =
+ bobSessionCipher.decrypt(new SignalMessage(aliceResponse.serialize()));
assertTrue(new String(responsePlaintext).equals("second message"));
assertTrue(isSessionIdEqual(aliceStore, bobStore));
@@ -375,28 +412,32 @@ public void testRepeatedSimultaneousInitiateRepeatedMessages()
@Test
public void testRepeatedSimultaneousInitiateLostMessageRepeatedMessages()
- throws InvalidKeyException, UntrustedIdentityException, InvalidVersionException,
- InvalidMessageException, DuplicateMessageException, LegacyMessageException,
- InvalidKeyIdException, NoSessionException
- {
+ throws InvalidKeyException,
+ UntrustedIdentityException,
+ InvalidVersionException,
+ InvalidMessageException,
+ DuplicateMessageException,
+ LegacyMessageException,
+ InvalidKeyIdException,
+ NoSessionException {
SignalProtocolStore aliceStore = new TestInMemorySignalProtocolStore();
- SignalProtocolStore bobStore = new TestInMemorySignalProtocolStore();
+ SignalProtocolStore bobStore = new TestInMemorySignalProtocolStore();
SessionBuilder aliceSessionBuilder = new SessionBuilder(aliceStore, BOB_ADDRESS);
- SessionBuilder bobSessionBuilder = new SessionBuilder(bobStore, ALICE_ADDRESS);
+ SessionBuilder bobSessionBuilder = new SessionBuilder(bobStore, ALICE_ADDRESS);
SessionCipher aliceSessionCipher = new SessionCipher(aliceStore, BOB_ADDRESS);
SessionCipher bobSessionCipher = new SessionCipher(bobStore, ALICE_ADDRESS);
- PreKeyBundle bobLostPreKeyBundle = bundleFactory.createBundle(bobStore);
+ PreKeyBundle bobLostPreKeyBundle = bundleFactory.createBundle(bobStore);
aliceSessionBuilder.process(bobLostPreKeyBundle);
- CiphertextMessage lostMessageForBob = aliceSessionCipher.encrypt("hey there".getBytes());
+ CiphertextMessage lostMessageForBob = aliceSessionCipher.encrypt("hey there".getBytes());
- for (int i=0;i<15;i++) {
+ for (int i = 0; i < 15; i++) {
PreKeyBundle alicePreKeyBundle = bundleFactory.createBundle(aliceStore);
- PreKeyBundle bobPreKeyBundle = bundleFactory.createBundle(bobStore);
+ PreKeyBundle bobPreKeyBundle = bundleFactory.createBundle(bobStore);
aliceSessionBuilder.process(bobPreKeyBundle);
bobSessionBuilder.process(alicePreKeyBundle);
@@ -409,8 +450,10 @@ public void testRepeatedSimultaneousInitiateLostMessageRepeatedMessages()
assertFalse(isSessionIdEqual(aliceStore, bobStore));
- byte[] alicePlaintext = aliceSessionCipher.decrypt(new PreKeySignalMessage(messageForAlice.serialize()));
- byte[] bobPlaintext = bobSessionCipher.decrypt(new PreKeySignalMessage(messageForBob.serialize()));
+ byte[] alicePlaintext =
+ aliceSessionCipher.decrypt(new PreKeySignalMessage(messageForAlice.serialize()));
+ byte[] bobPlaintext =
+ bobSessionCipher.decrypt(new PreKeySignalMessage(messageForBob.serialize()));
assertTrue(new String(alicePlaintext).equals("sample message"));
assertTrue(new String(bobPlaintext).equals("hey there"));
@@ -421,17 +464,20 @@ public void testRepeatedSimultaneousInitiateLostMessageRepeatedMessages()
assertFalse(isSessionIdEqual(aliceStore, bobStore));
}
- for (int i=0;i<50;i++) {
- CiphertextMessage messageForBobRepeat = aliceSessionCipher.encrypt("hey there".getBytes());
- CiphertextMessage messageForAliceRepeat = bobSessionCipher.encrypt("sample message".getBytes());
+ for (int i = 0; i < 50; i++) {
+ CiphertextMessage messageForBobRepeat = aliceSessionCipher.encrypt("hey there".getBytes());
+ CiphertextMessage messageForAliceRepeat =
+ bobSessionCipher.encrypt("sample message".getBytes());
assertEquals(messageForBobRepeat.getType(), CiphertextMessage.WHISPER_TYPE);
assertEquals(messageForAliceRepeat.getType(), CiphertextMessage.WHISPER_TYPE);
assertFalse(isSessionIdEqual(aliceStore, bobStore));
- byte[] alicePlaintextRepeat = aliceSessionCipher.decrypt(new SignalMessage(messageForAliceRepeat.serialize()));
- byte[] bobPlaintextRepeat = bobSessionCipher.decrypt(new SignalMessage(messageForBobRepeat.serialize()));
+ byte[] alicePlaintextRepeat =
+ aliceSessionCipher.decrypt(new SignalMessage(messageForAliceRepeat.serialize()));
+ byte[] bobPlaintextRepeat =
+ bobSessionCipher.decrypt(new SignalMessage(messageForBobRepeat.serialize()));
assertTrue(new String(alicePlaintextRepeat).equals("sample message"));
assertTrue(new String(bobPlaintextRepeat).equals("hey there"));
@@ -443,7 +489,8 @@ public void testRepeatedSimultaneousInitiateLostMessageRepeatedMessages()
assertEquals(aliceResponse.getType(), CiphertextMessage.WHISPER_TYPE);
- byte[] responsePlaintext = bobSessionCipher.decrypt(new SignalMessage(aliceResponse.serialize()));
+ byte[] responsePlaintext =
+ bobSessionCipher.decrypt(new SignalMessage(aliceResponse.serialize()));
assertTrue(new String(responsePlaintext).equals("second message"));
assertTrue(isSessionIdEqual(aliceStore, bobStore));
@@ -457,13 +504,15 @@ public void testRepeatedSimultaneousInitiateLostMessageRepeatedMessages()
assertTrue(new String(finalPlaintext).equals("third message"));
assertTrue(isSessionIdEqual(aliceStore, bobStore));
- byte[] lostMessagePlaintext = bobSessionCipher.decrypt(new PreKeySignalMessage(lostMessageForBob.serialize()));
+ byte[] lostMessagePlaintext =
+ bobSessionCipher.decrypt(new PreKeySignalMessage(lostMessageForBob.serialize()));
assertTrue(new String(lostMessagePlaintext).equals("hey there"));
assertFalse(isSessionIdEqual(aliceStore, bobStore));
- CiphertextMessage blastFromThePast = bobSessionCipher.encrypt("unexpected!".getBytes());
- byte[] blastFromThePastPlaintext = aliceSessionCipher.decrypt(new SignalMessage(blastFromThePast.serialize()));
+ CiphertextMessage blastFromThePast = bobSessionCipher.encrypt("unexpected!".getBytes());
+ byte[] blastFromThePastPlaintext =
+ aliceSessionCipher.decrypt(new SignalMessage(blastFromThePast.serialize()));
assertTrue(new String(blastFromThePastPlaintext).equals("unexpected!"));
assertTrue(isSessionIdEqual(aliceStore, bobStore));
@@ -473,12 +522,14 @@ private void assertSessionIdEquals(SignalProtocolStore aliceStore, SignalProtoco
assertTrue(isSessionIdEqual(aliceStore, bobStore));
}
- private void assertSessionIdNotEquals(SignalProtocolStore aliceStore, SignalProtocolStore bobStore) {
+ private void assertSessionIdNotEquals(
+ SignalProtocolStore aliceStore, SignalProtocolStore bobStore) {
assertFalse(isSessionIdEqual(aliceStore, bobStore));
}
private boolean isSessionIdEqual(SignalProtocolStore aliceStore, SignalProtocolStore bobStore) {
- return Arrays.equals(aliceStore.loadSession(BOB_ADDRESS).getAliceBaseKey(),
- bobStore.loadSession(ALICE_ADDRESS).getAliceBaseKey());
+ return Arrays.equals(
+ aliceStore.loadSession(BOB_ADDRESS).getAliceBaseKey(),
+ bobStore.loadSession(ALICE_ADDRESS).getAliceBaseKey());
}
}
diff --git a/java/client/src/test/java/org/signal/libsignal/protocol/TestBadSignedPreKeysStore.java b/java/client/src/test/java/org/signal/libsignal/protocol/TestBadSignedPreKeysStore.java
index 704b9c7413..15a20b12be 100644
--- a/java/client/src/test/java/org/signal/libsignal/protocol/TestBadSignedPreKeysStore.java
+++ b/java/client/src/test/java/org/signal/libsignal/protocol/TestBadSignedPreKeysStore.java
@@ -1,6 +1,10 @@
+//
+// Copyright 2023 Signal Messenger, LLC.
+// SPDX-License-Identifier: AGPL-3.0-only
+//
+
package org.signal.libsignal.protocol;
-import org.signal.libsignal.protocol.InvalidKeyIdException;
import org.signal.libsignal.protocol.state.SignedPreKeyRecord;
public class TestBadSignedPreKeysStore extends TestInMemorySignalProtocolStore {
diff --git a/java/client/src/test/java/org/signal/libsignal/protocol/TestInMemoryIdentityKeyStore.java b/java/client/src/test/java/org/signal/libsignal/protocol/TestInMemoryIdentityKeyStore.java
index 286d68054e..4e5a75551b 100644
--- a/java/client/src/test/java/org/signal/libsignal/protocol/TestInMemoryIdentityKeyStore.java
+++ b/java/client/src/test/java/org/signal/libsignal/protocol/TestInMemoryIdentityKeyStore.java
@@ -1,10 +1,16 @@
+//
+// Copyright 2023 Signal Messenger, LLC.
+// SPDX-License-Identifier: AGPL-3.0-only
+//
+
package org.signal.libsignal.protocol;
import org.signal.libsignal.protocol.ecc.Curve;
import org.signal.libsignal.protocol.ecc.ECKeyPair;
import org.signal.libsignal.protocol.util.KeyHelper;
-public class TestInMemoryIdentityKeyStore extends org.signal.libsignal.protocol.state.impl.InMemoryIdentityKeyStore {
+public class TestInMemoryIdentityKeyStore
+ extends org.signal.libsignal.protocol.state.impl.InMemoryIdentityKeyStore {
public TestInMemoryIdentityKeyStore() {
super(generateIdentityKeyPair(), generateRegistrationId());
}
@@ -12,12 +18,11 @@ public TestInMemoryIdentityKeyStore() {
private static IdentityKeyPair generateIdentityKeyPair() {
ECKeyPair identityKeyPairKeys = Curve.generateKeyPair();
- return new IdentityKeyPair(new IdentityKey(identityKeyPairKeys.getPublicKey()),
- identityKeyPairKeys.getPrivateKey());
+ return new IdentityKeyPair(
+ new IdentityKey(identityKeyPairKeys.getPublicKey()), identityKeyPairKeys.getPrivateKey());
}
private static int generateRegistrationId() {
return KeyHelper.generateRegistrationId(false);
}
-
}
diff --git a/java/client/src/test/java/org/signal/libsignal/protocol/TestInMemorySignalProtocolStore.java b/java/client/src/test/java/org/signal/libsignal/protocol/TestInMemorySignalProtocolStore.java
index 6b1ff60fff..9358893e58 100644
--- a/java/client/src/test/java/org/signal/libsignal/protocol/TestInMemorySignalProtocolStore.java
+++ b/java/client/src/test/java/org/signal/libsignal/protocol/TestInMemorySignalProtocolStore.java
@@ -1,3 +1,8 @@
+//
+// Copyright 2023 Signal Messenger, LLC.
+// SPDX-License-Identifier: AGPL-3.0-only
+//
+
package org.signal.libsignal.protocol;
import org.signal.libsignal.protocol.ecc.Curve;
@@ -13,8 +18,8 @@ public TestInMemorySignalProtocolStore() {
private static IdentityKeyPair generateIdentityKeyPair() {
ECKeyPair identityKeyPairKeys = Curve.generateKeyPair();
- return new IdentityKeyPair(new IdentityKey(identityKeyPairKeys.getPublicKey()),
- identityKeyPairKeys.getPrivateKey());
+ return new IdentityKeyPair(
+ new IdentityKey(identityKeyPairKeys.getPublicKey()), identityKeyPairKeys.getPrivateKey());
}
private static int generateRegistrationId() {
diff --git a/java/client/src/test/java/org/signal/libsignal/protocol/TestNoSignedPreKeysStore.java b/java/client/src/test/java/org/signal/libsignal/protocol/TestNoSignedPreKeysStore.java
index 843265904c..5a01bee994 100644
--- a/java/client/src/test/java/org/signal/libsignal/protocol/TestNoSignedPreKeysStore.java
+++ b/java/client/src/test/java/org/signal/libsignal/protocol/TestNoSignedPreKeysStore.java
@@ -1,6 +1,10 @@
+//
+// Copyright 2023 Signal Messenger, LLC.
+// SPDX-License-Identifier: AGPL-3.0-only
+//
+
package org.signal.libsignal.protocol;
-import org.signal.libsignal.protocol.InvalidKeyIdException;
import org.signal.libsignal.protocol.state.SignedPreKeyRecord;
public class TestNoSignedPreKeysStore extends TestInMemorySignalProtocolStore {
diff --git a/java/client/src/test/java/org/signal/libsignal/protocol/X3DHBundleFactory.java b/java/client/src/test/java/org/signal/libsignal/protocol/X3DHBundleFactory.java
index 012dad679f..d7ad24a431 100644
--- a/java/client/src/test/java/org/signal/libsignal/protocol/X3DHBundleFactory.java
+++ b/java/client/src/test/java/org/signal/libsignal/protocol/X3DHBundleFactory.java
@@ -1,33 +1,45 @@
+//
+// Copyright 2023 Signal Messenger, LLC.
+// SPDX-License-Identifier: AGPL-3.0-only
+//
+
package org.signal.libsignal.protocol;
+import java.util.Random;
import org.signal.libsignal.protocol.ecc.Curve;
import org.signal.libsignal.protocol.ecc.ECKeyPair;
-import org.signal.libsignal.protocol.kem.KEMKeyPair;
-import org.signal.libsignal.protocol.kem.KEMKeyType;
import org.signal.libsignal.protocol.state.PreKeyBundle;
import org.signal.libsignal.protocol.state.PreKeyRecord;
import org.signal.libsignal.protocol.state.SignalProtocolStore;
import org.signal.libsignal.protocol.state.SignedPreKeyRecord;
import org.signal.libsignal.protocol.util.Medium;
-import java.util.Random;
-
public final class X3DHBundleFactory implements BundleFactory {
@Override
public PreKeyBundle createBundle(SignalProtocolStore store) throws InvalidKeyException {
- ECKeyPair preKeyPair = Curve.generateKeyPair();
- ECKeyPair signedPreKeyPair = Curve.generateKeyPair();
- byte[] signedPreKeySignature = Curve.calculateSignature(store.getIdentityKeyPair().getPrivateKey(),
- signedPreKeyPair.getPublicKey().serialize());
+ ECKeyPair preKeyPair = Curve.generateKeyPair();
+ ECKeyPair signedPreKeyPair = Curve.generateKeyPair();
+ byte[] signedPreKeySignature =
+ Curve.calculateSignature(
+ store.getIdentityKeyPair().getPrivateKey(),
+ signedPreKeyPair.getPublicKey().serialize());
Random random = new Random();
int preKeyId = random.nextInt(Medium.MAX_VALUE);
int signedPreKeyId = random.nextInt(Medium.MAX_VALUE);
store.storePreKey(preKeyId, new PreKeyRecord(preKeyId, preKeyPair));
- store.storeSignedPreKey(signedPreKeyId, new SignedPreKeyRecord(signedPreKeyId, System.currentTimeMillis(), signedPreKeyPair, signedPreKeySignature));
+ store.storeSignedPreKey(
+ signedPreKeyId,
+ new SignedPreKeyRecord(
+ signedPreKeyId, System.currentTimeMillis(), signedPreKeyPair, signedPreKeySignature));
- return new PreKeyBundle(store.getLocalRegistrationId(), 1,
- preKeyId, preKeyPair.getPublicKey(),
- signedPreKeyId, signedPreKeyPair.getPublicKey(), signedPreKeySignature,
+ return new PreKeyBundle(
+ store.getLocalRegistrationId(),
+ 1,
+ preKeyId,
+ preKeyPair.getPublicKey(),
+ signedPreKeyId,
+ signedPreKeyPair.getPublicKey(),
+ signedPreKeySignature,
store.getIdentityKeyPair().getPublicKey());
}
}
diff --git a/java/client/src/test/java/org/signal/libsignal/protocol/ecc/Curve25519Test.java b/java/client/src/test/java/org/signal/libsignal/protocol/ecc/Curve25519Test.java
index cfc9a66a7a..dddf5ca482 100644
--- a/java/client/src/test/java/org/signal/libsignal/protocol/ecc/Curve25519Test.java
+++ b/java/client/src/test/java/org/signal/libsignal/protocol/ecc/Curve25519Test.java
@@ -1,54 +1,66 @@
+//
+// Copyright 2023 Signal Messenger, LLC.
+// SPDX-License-Identifier: AGPL-3.0-only
+//
+
package org.signal.libsignal.protocol.ecc;
+import java.util.Arrays;
import junit.framework.TestCase;
-
import org.signal.libsignal.protocol.InvalidKeyException;
-import java.util.Arrays;
-
-
public class Curve25519Test extends TestCase {
public void testAgreement() throws InvalidKeyException {
- byte[] alicePublic = {(byte) 0x05, (byte) 0x1b, (byte) 0xb7, (byte) 0x59, (byte) 0x66,
- (byte) 0xf2, (byte) 0xe9, (byte) 0x3a, (byte) 0x36, (byte) 0x91,
- (byte) 0xdf, (byte) 0xff, (byte) 0x94, (byte) 0x2b, (byte) 0xb2,
- (byte) 0xa4, (byte) 0x66, (byte) 0xa1, (byte) 0xc0, (byte) 0x8b,
- (byte) 0x8d, (byte) 0x78, (byte) 0xca, (byte) 0x3f, (byte) 0x4d,
- (byte) 0x6d, (byte) 0xf8, (byte) 0xb8, (byte) 0xbf, (byte) 0xa2,
- (byte) 0xe4, (byte) 0xee, (byte) 0x28};
-
- byte[] alicePrivate = {(byte) 0xc8, (byte) 0x06, (byte) 0x43, (byte) 0x9d, (byte) 0xc9,
- (byte) 0xd2, (byte) 0xc4, (byte) 0x76, (byte) 0xff, (byte) 0xed,
- (byte) 0x8f, (byte) 0x25, (byte) 0x80, (byte) 0xc0, (byte) 0x88,
- (byte) 0x8d, (byte) 0x58, (byte) 0xab, (byte) 0x40, (byte) 0x6b,
- (byte) 0xf7, (byte) 0xae, (byte) 0x36, (byte) 0x98, (byte) 0x87,
- (byte) 0x90, (byte) 0x21, (byte) 0xb9, (byte) 0x6b, (byte) 0xb4,
- (byte) 0xbf, (byte) 0x59};
-
- byte[] bobPublic = {(byte) 0x05, (byte) 0x65, (byte) 0x36, (byte) 0x14, (byte) 0x99,
- (byte) 0x3d, (byte) 0x2b, (byte) 0x15, (byte) 0xee, (byte) 0x9e,
- (byte) 0x5f, (byte) 0xd3, (byte) 0xd8, (byte) 0x6c, (byte) 0xe7,
- (byte) 0x19, (byte) 0xef, (byte) 0x4e, (byte) 0xc1, (byte) 0xda,
- (byte) 0xae, (byte) 0x18, (byte) 0x86, (byte) 0xa8, (byte) 0x7b,
- (byte) 0x3f, (byte) 0x5f, (byte) 0xa9, (byte) 0x56, (byte) 0x5a,
- (byte) 0x27, (byte) 0xa2, (byte) 0x2f};
-
- byte[] bobPrivate = {(byte) 0xb0, (byte) 0x3b, (byte) 0x34, (byte) 0xc3, (byte) 0x3a,
- (byte) 0x1c, (byte) 0x44, (byte) 0xf2, (byte) 0x25, (byte) 0xb6,
- (byte) 0x62, (byte) 0xd2, (byte) 0xbf, (byte) 0x48, (byte) 0x59,
- (byte) 0xb8, (byte) 0x13, (byte) 0x54, (byte) 0x11, (byte) 0xfa,
- (byte) 0x7b, (byte) 0x03, (byte) 0x86, (byte) 0xd4, (byte) 0x5f,
- (byte) 0xb7, (byte) 0x5d, (byte) 0xc5, (byte) 0xb9, (byte) 0x1b,
- (byte) 0x44, (byte) 0x66};
-
- byte[] shared = {(byte) 0x32, (byte) 0x5f, (byte) 0x23, (byte) 0x93, (byte) 0x28,
- (byte) 0x94, (byte) 0x1c, (byte) 0xed, (byte) 0x6e, (byte) 0x67,
- (byte) 0x3b, (byte) 0x86, (byte) 0xba, (byte) 0x41, (byte) 0x01,
- (byte) 0x74, (byte) 0x48, (byte) 0xe9, (byte) 0x9b, (byte) 0x64,
- (byte) 0x9a, (byte) 0x9c, (byte) 0x38, (byte) 0x06, (byte) 0xc1,
- (byte) 0xdd, (byte) 0x7c, (byte) 0xa4, (byte) 0xc4, (byte) 0x77,
- (byte) 0xe6, (byte) 0x29};
+ byte[] alicePublic = {
+ (byte) 0x05, (byte) 0x1b, (byte) 0xb7, (byte) 0x59, (byte) 0x66,
+ (byte) 0xf2, (byte) 0xe9, (byte) 0x3a, (byte) 0x36, (byte) 0x91,
+ (byte) 0xdf, (byte) 0xff, (byte) 0x94, (byte) 0x2b, (byte) 0xb2,
+ (byte) 0xa4, (byte) 0x66, (byte) 0xa1, (byte) 0xc0, (byte) 0x8b,
+ (byte) 0x8d, (byte) 0x78, (byte) 0xca, (byte) 0x3f, (byte) 0x4d,
+ (byte) 0x6d, (byte) 0xf8, (byte) 0xb8, (byte) 0xbf, (byte) 0xa2,
+ (byte) 0xe4, (byte) 0xee, (byte) 0x28
+ };
+
+ byte[] alicePrivate = {
+ (byte) 0xc8, (byte) 0x06, (byte) 0x43, (byte) 0x9d, (byte) 0xc9,
+ (byte) 0xd2, (byte) 0xc4, (byte) 0x76, (byte) 0xff, (byte) 0xed,
+ (byte) 0x8f, (byte) 0x25, (byte) 0x80, (byte) 0xc0, (byte) 0x88,
+ (byte) 0x8d, (byte) 0x58, (byte) 0xab, (byte) 0x40, (byte) 0x6b,
+ (byte) 0xf7, (byte) 0xae, (byte) 0x36, (byte) 0x98, (byte) 0x87,
+ (byte) 0x90, (byte) 0x21, (byte) 0xb9, (byte) 0x6b, (byte) 0xb4,
+ (byte) 0xbf, (byte) 0x59
+ };
+
+ byte[] bobPublic = {
+ (byte) 0x05, (byte) 0x65, (byte) 0x36, (byte) 0x14, (byte) 0x99,
+ (byte) 0x3d, (byte) 0x2b, (byte) 0x15, (byte) 0xee, (byte) 0x9e,
+ (byte) 0x5f, (byte) 0xd3, (byte) 0xd8, (byte) 0x6c, (byte) 0xe7,
+ (byte) 0x19, (byte) 0xef, (byte) 0x4e, (byte) 0xc1, (byte) 0xda,
+ (byte) 0xae, (byte) 0x18, (byte) 0x86, (byte) 0xa8, (byte) 0x7b,
+ (byte) 0x3f, (byte) 0x5f, (byte) 0xa9, (byte) 0x56, (byte) 0x5a,
+ (byte) 0x27, (byte) 0xa2, (byte) 0x2f
+ };
+
+ byte[] bobPrivate = {
+ (byte) 0xb0, (byte) 0x3b, (byte) 0x34, (byte) 0xc3, (byte) 0x3a,
+ (byte) 0x1c, (byte) 0x44, (byte) 0xf2, (byte) 0x25, (byte) 0xb6,
+ (byte) 0x62, (byte) 0xd2, (byte) 0xbf, (byte) 0x48, (byte) 0x59,
+ (byte) 0xb8, (byte) 0x13, (byte) 0x54, (byte) 0x11, (byte) 0xfa,
+ (byte) 0x7b, (byte) 0x03, (byte) 0x86, (byte) 0xd4, (byte) 0x5f,
+ (byte) 0xb7, (byte) 0x5d, (byte) 0xc5, (byte) 0xb9, (byte) 0x1b,
+ (byte) 0x44, (byte) 0x66
+ };
+
+ byte[] shared = {
+ (byte) 0x32, (byte) 0x5f, (byte) 0x23, (byte) 0x93, (byte) 0x28,
+ (byte) 0x94, (byte) 0x1c, (byte) 0xed, (byte) 0x6e, (byte) 0x67,
+ (byte) 0x3b, (byte) 0x86, (byte) 0xba, (byte) 0x41, (byte) 0x01,
+ (byte) 0x74, (byte) 0x48, (byte) 0xe9, (byte) 0x9b, (byte) 0x64,
+ (byte) 0x9a, (byte) 0x9c, (byte) 0x38, (byte) 0x06, (byte) 0xc1,
+ (byte) 0xdd, (byte) 0x7c, (byte) 0xa4, (byte) 0xc4, (byte) 0x77,
+ (byte) 0xe6, (byte) 0x29
+ };
ECPublicKey alicePublicKey = Curve.decodePoint(alicePublic, 0);
ECPrivateKey alicePrivateKey = Curve.decodePrivatePoint(alicePrivate);
@@ -64,59 +76,67 @@ public void testAgreement() throws InvalidKeyException {
}
public void testRandomAgreements() throws InvalidKeyException {
- for (int i=0;i<50;i++) {
- ECKeyPair alice = Curve.generateKeyPair();
- ECKeyPair bob = Curve.generateKeyPair();
+ for (int i = 0; i < 50; i++) {
+ ECKeyPair alice = Curve.generateKeyPair();
+ ECKeyPair bob = Curve.generateKeyPair();
- byte[] sharedAlice = Curve.calculateAgreement(bob.getPublicKey(), alice.getPrivateKey());
- byte[] sharedBob = Curve.calculateAgreement(alice.getPublicKey(), bob.getPrivateKey());
+ byte[] sharedAlice = Curve.calculateAgreement(bob.getPublicKey(), alice.getPrivateKey());
+ byte[] sharedBob = Curve.calculateAgreement(alice.getPublicKey(), bob.getPrivateKey());
assertTrue(Arrays.equals(sharedAlice, sharedBob));
}
}
public void testSignature() throws InvalidKeyException {
- byte[] aliceIdentityPrivate = {(byte)0xc0, (byte)0x97, (byte)0x24, (byte)0x84, (byte)0x12,
- (byte)0xe5, (byte)0x8b, (byte)0xf0, (byte)0x5d, (byte)0xf4,
- (byte)0x87, (byte)0x96, (byte)0x82, (byte)0x05, (byte)0x13,
- (byte)0x27, (byte)0x94, (byte)0x17, (byte)0x8e, (byte)0x36,
- (byte)0x76, (byte)0x37, (byte)0xf5, (byte)0x81, (byte)0x8f,
- (byte)0x81, (byte)0xe0, (byte)0xe6, (byte)0xce, (byte)0x73,
- (byte)0xe8, (byte)0x65};
-
- byte[] aliceIdentityPublic = {(byte)0x05, (byte)0xab, (byte)0x7e, (byte)0x71, (byte)0x7d,
- (byte)0x4a, (byte)0x16, (byte)0x3b, (byte)0x7d, (byte)0x9a,
- (byte)0x1d, (byte)0x80, (byte)0x71, (byte)0xdf, (byte)0xe9,
- (byte)0xdc, (byte)0xf8, (byte)0xcd, (byte)0xcd, (byte)0x1c,
- (byte)0xea, (byte)0x33, (byte)0x39, (byte)0xb6, (byte)0x35,
- (byte)0x6b, (byte)0xe8, (byte)0x4d, (byte)0x88, (byte)0x7e,
- (byte)0x32, (byte)0x2c, (byte)0x64};
-
- byte[] aliceEphemeralPublic = {(byte)0x05, (byte)0xed, (byte)0xce, (byte)0x9d, (byte)0x9c,
- (byte)0x41, (byte)0x5c, (byte)0xa7, (byte)0x8c, (byte)0xb7,
- (byte)0x25, (byte)0x2e, (byte)0x72, (byte)0xc2, (byte)0xc4,
- (byte)0xa5, (byte)0x54, (byte)0xd3, (byte)0xeb, (byte)0x29,
- (byte)0x48, (byte)0x5a, (byte)0x0e, (byte)0x1d, (byte)0x50,
- (byte)0x31, (byte)0x18, (byte)0xd1, (byte)0xa8, (byte)0x2d,
- (byte)0x99, (byte)0xfb, (byte)0x4a};
-
- byte[] aliceSignature = {(byte)0x5d, (byte)0xe8, (byte)0x8c, (byte)0xa9, (byte)0xa8,
- (byte)0x9b, (byte)0x4a, (byte)0x11, (byte)0x5d, (byte)0xa7,
- (byte)0x91, (byte)0x09, (byte)0xc6, (byte)0x7c, (byte)0x9c,
- (byte)0x74, (byte)0x64, (byte)0xa3, (byte)0xe4, (byte)0x18,
- (byte)0x02, (byte)0x74, (byte)0xf1, (byte)0xcb, (byte)0x8c,
- (byte)0x63, (byte)0xc2, (byte)0x98, (byte)0x4e, (byte)0x28,
- (byte)0x6d, (byte)0xfb, (byte)0xed, (byte)0xe8, (byte)0x2d,
- (byte)0xeb, (byte)0x9d, (byte)0xcd, (byte)0x9f, (byte)0xae,
- (byte)0x0b, (byte)0xfb, (byte)0xb8, (byte)0x21, (byte)0x56,
- (byte)0x9b, (byte)0x3d, (byte)0x90, (byte)0x01, (byte)0xbd,
- (byte)0x81, (byte)0x30, (byte)0xcd, (byte)0x11, (byte)0xd4,
- (byte)0x86, (byte)0xce, (byte)0xf0, (byte)0x47, (byte)0xbd,
- (byte)0x60, (byte)0xb8, (byte)0x6e, (byte)0x88};
+ byte[] aliceIdentityPrivate = {
+ (byte) 0xc0, (byte) 0x97, (byte) 0x24, (byte) 0x84, (byte) 0x12,
+ (byte) 0xe5, (byte) 0x8b, (byte) 0xf0, (byte) 0x5d, (byte) 0xf4,
+ (byte) 0x87, (byte) 0x96, (byte) 0x82, (byte) 0x05, (byte) 0x13,
+ (byte) 0x27, (byte) 0x94, (byte) 0x17, (byte) 0x8e, (byte) 0x36,
+ (byte) 0x76, (byte) 0x37, (byte) 0xf5, (byte) 0x81, (byte) 0x8f,
+ (byte) 0x81, (byte) 0xe0, (byte) 0xe6, (byte) 0xce, (byte) 0x73,
+ (byte) 0xe8, (byte) 0x65
+ };
+
+ byte[] aliceIdentityPublic = {
+ (byte) 0x05, (byte) 0xab, (byte) 0x7e, (byte) 0x71, (byte) 0x7d,
+ (byte) 0x4a, (byte) 0x16, (byte) 0x3b, (byte) 0x7d, (byte) 0x9a,
+ (byte) 0x1d, (byte) 0x80, (byte) 0x71, (byte) 0xdf, (byte) 0xe9,
+ (byte) 0xdc, (byte) 0xf8, (byte) 0xcd, (byte) 0xcd, (byte) 0x1c,
+ (byte) 0xea, (byte) 0x33, (byte) 0x39, (byte) 0xb6, (byte) 0x35,
+ (byte) 0x6b, (byte) 0xe8, (byte) 0x4d, (byte) 0x88, (byte) 0x7e,
+ (byte) 0x32, (byte) 0x2c, (byte) 0x64
+ };
+
+ byte[] aliceEphemeralPublic = {
+ (byte) 0x05, (byte) 0xed, (byte) 0xce, (byte) 0x9d, (byte) 0x9c,
+ (byte) 0x41, (byte) 0x5c, (byte) 0xa7, (byte) 0x8c, (byte) 0xb7,
+ (byte) 0x25, (byte) 0x2e, (byte) 0x72, (byte) 0xc2, (byte) 0xc4,
+ (byte) 0xa5, (byte) 0x54, (byte) 0xd3, (byte) 0xeb, (byte) 0x29,
+ (byte) 0x48, (byte) 0x5a, (byte) 0x0e, (byte) 0x1d, (byte) 0x50,
+ (byte) 0x31, (byte) 0x18, (byte) 0xd1, (byte) 0xa8, (byte) 0x2d,
+ (byte) 0x99, (byte) 0xfb, (byte) 0x4a
+ };
+
+ byte[] aliceSignature = {
+ (byte) 0x5d, (byte) 0xe8, (byte) 0x8c, (byte) 0xa9, (byte) 0xa8,
+ (byte) 0x9b, (byte) 0x4a, (byte) 0x11, (byte) 0x5d, (byte) 0xa7,
+ (byte) 0x91, (byte) 0x09, (byte) 0xc6, (byte) 0x7c, (byte) 0x9c,
+ (byte) 0x74, (byte) 0x64, (byte) 0xa3, (byte) 0xe4, (byte) 0x18,
+ (byte) 0x02, (byte) 0x74, (byte) 0xf1, (byte) 0xcb, (byte) 0x8c,
+ (byte) 0x63, (byte) 0xc2, (byte) 0x98, (byte) 0x4e, (byte) 0x28,
+ (byte) 0x6d, (byte) 0xfb, (byte) 0xed, (byte) 0xe8, (byte) 0x2d,
+ (byte) 0xeb, (byte) 0x9d, (byte) 0xcd, (byte) 0x9f, (byte) 0xae,
+ (byte) 0x0b, (byte) 0xfb, (byte) 0xb8, (byte) 0x21, (byte) 0x56,
+ (byte) 0x9b, (byte) 0x3d, (byte) 0x90, (byte) 0x01, (byte) 0xbd,
+ (byte) 0x81, (byte) 0x30, (byte) 0xcd, (byte) 0x11, (byte) 0xd4,
+ (byte) 0x86, (byte) 0xce, (byte) 0xf0, (byte) 0x47, (byte) 0xbd,
+ (byte) 0x60, (byte) 0xb8, (byte) 0x6e, (byte) 0x88
+ };
ECPrivateKey alicePrivateKey = Curve.decodePrivatePoint(aliceIdentityPrivate);
- ECPublicKey alicePublicKey = Curve.decodePoint(aliceIdentityPublic, 0);
- ECPublicKey aliceEphemeral = Curve.decodePoint(aliceEphemeralPublic, 0);
+ ECPublicKey alicePublicKey = Curve.decodePoint(aliceIdentityPublic, 0);
+ ECPublicKey aliceEphemeral = Curve.decodePoint(aliceEphemeralPublic, 0);
if (!Curve.verifySignature(alicePublicKey, aliceEphemeral.serialize(), aliceSignature)) {
throw new AssertionError("Sig verification failed!");
@@ -125,7 +145,7 @@ public void testSignature() throws InvalidKeyException {
byte[] aliceKey = aliceEphemeral.getPublicKeyBytes();
assertTrue(aliceKey.length == 32);
- for (int i=0;i ciphertexts = new ArrayList<>(100);
- for (int i=0;i<100;i++) {
- ciphertexts.add(aliceGroupCipher.encrypt(DISTRIBUTION_ID, "up the punks".getBytes()).serialize());
+ for (int i = 0; i < 100; i++) {
+ ciphertexts.add(
+ aliceGroupCipher.encrypt(DISTRIBUTION_ID, "up the punks".getBytes()).serialize());
}
while (ciphertexts.size() > 0) {
- int index = randomInt() % ciphertexts.size();
+ int index = randomInt() % ciphertexts.size();
byte[] ciphertext = ciphertexts.remove(index);
- byte[] plaintext = bobGroupCipher.decrypt(ciphertext);
+ byte[] plaintext = bobGroupCipher.decrypt(ciphertext);
assertTrue(new String(plaintext).equals("up the punks"));
}
@@ -200,7 +250,8 @@ public void testOutOfOrder()
public void testEncryptNoSession() {
InMemorySenderKeyStore aliceStore = new InMemorySenderKeyStore();
- GroupCipher aliceGroupCipher = new GroupCipher(aliceStore, new SignalProtocolAddress("+10002223333", 1));
+ GroupCipher aliceGroupCipher =
+ new GroupCipher(aliceStore, new SignalProtocolAddress("+10002223333", 1));
try {
aliceGroupCipher.encrypt(DISTRIBUTION_ID, "up the punks".getBytes());
fail("Should have failed!");
@@ -209,26 +260,31 @@ public void testEncryptNoSession() {
}
}
-
- public void testTooFarInFuture() throws DuplicateMessageException, InvalidMessageException, LegacyMessageException, NoSessionException {
+ public void testTooFarInFuture()
+ throws DuplicateMessageException,
+ InvalidMessageException,
+ LegacyMessageException,
+ NoSessionException {
InMemorySenderKeyStore aliceStore = new InMemorySenderKeyStore();
- InMemorySenderKeyStore bobStore = new InMemorySenderKeyStore();
+ InMemorySenderKeyStore bobStore = new InMemorySenderKeyStore();
GroupSessionBuilder aliceSessionBuilder = new GroupSessionBuilder(aliceStore);
- GroupSessionBuilder bobSessionBuilder = new GroupSessionBuilder(bobStore);
+ GroupSessionBuilder bobSessionBuilder = new GroupSessionBuilder(bobStore);
GroupCipher aliceGroupCipher = new GroupCipher(aliceStore, SENDER_ADDRESS);
- GroupCipher bobGroupCipher = new GroupCipher(bobStore, SENDER_ADDRESS);
+ GroupCipher bobGroupCipher = new GroupCipher(bobStore, SENDER_ADDRESS);
- SenderKeyDistributionMessage aliceDistributionMessage = aliceSessionBuilder.create(SENDER_ADDRESS, DISTRIBUTION_ID);
+ SenderKeyDistributionMessage aliceDistributionMessage =
+ aliceSessionBuilder.create(SENDER_ADDRESS, DISTRIBUTION_ID);
bobSessionBuilder.process(SENDER_ADDRESS, aliceDistributionMessage);
- for (int i=0;i<25001;i++) {
+ for (int i = 0; i < 25001; i++) {
aliceGroupCipher.encrypt(DISTRIBUTION_ID, "up the punks".getBytes());
}
- byte[] tooFarCiphertext = aliceGroupCipher.encrypt(DISTRIBUTION_ID, "notta gonna worka".getBytes()).serialize();
+ byte[] tooFarCiphertext =
+ aliceGroupCipher.encrypt(DISTRIBUTION_ID, "notta gonna worka".getBytes()).serialize();
try {
bobGroupCipher.decrypt(tooFarCiphertext);
fail("Should have failed!");
@@ -239,26 +295,28 @@ public void testTooFarInFuture() throws DuplicateMessageException, InvalidMessag
public void testMessageKeyLimit() throws Exception {
InMemorySenderKeyStore aliceStore = new InMemorySenderKeyStore();
- InMemorySenderKeyStore bobStore = new InMemorySenderKeyStore();
+ InMemorySenderKeyStore bobStore = new InMemorySenderKeyStore();
GroupSessionBuilder aliceSessionBuilder = new GroupSessionBuilder(aliceStore);
- GroupSessionBuilder bobSessionBuilder = new GroupSessionBuilder(bobStore);
+ GroupSessionBuilder bobSessionBuilder = new GroupSessionBuilder(bobStore);
GroupCipher aliceGroupCipher = new GroupCipher(aliceStore, SENDER_ADDRESS);
- GroupCipher bobGroupCipher = new GroupCipher(bobStore, SENDER_ADDRESS);
+ GroupCipher bobGroupCipher = new GroupCipher(bobStore, SENDER_ADDRESS);
- SenderKeyDistributionMessage aliceDistributionMessage = aliceSessionBuilder.create(SENDER_ADDRESS, DISTRIBUTION_ID);
+ SenderKeyDistributionMessage aliceDistributionMessage =
+ aliceSessionBuilder.create(SENDER_ADDRESS, DISTRIBUTION_ID);
bobSessionBuilder.process(SENDER_ADDRESS, aliceDistributionMessage);
List inflight = new LinkedList<>();
- for (int i=0;i<2010;i++) {
- inflight.add(aliceGroupCipher.encrypt(DISTRIBUTION_ID, "up the punks".getBytes()).serialize());
+ for (int i = 0; i < 2010; i++) {
+ inflight.add(
+ aliceGroupCipher.encrypt(DISTRIBUTION_ID, "up the punks".getBytes()).serialize());
}
bobGroupCipher.decrypt(inflight.get(1000));
- bobGroupCipher.decrypt(inflight.get(inflight.size()-1));
+ bobGroupCipher.decrypt(inflight.get(inflight.size() - 1));
try {
bobGroupCipher.decrypt(inflight.get(0));
@@ -268,7 +326,6 @@ public void testMessageKeyLimit() throws Exception {
}
}
-
private int randomInt() {
try {
return SecureRandom.getInstance("SHA1PRNG").nextInt(Integer.MAX_VALUE);
diff --git a/java/client/src/test/java/org/signal/libsignal/protocol/incrementalmac/IncrementalStreamsTest.java b/java/client/src/test/java/org/signal/libsignal/protocol/incrementalmac/IncrementalStreamsTest.java
index 4657a33ae6..5e0774c832 100644
--- a/java/client/src/test/java/org/signal/libsignal/protocol/incrementalmac/IncrementalStreamsTest.java
+++ b/java/client/src/test/java/org/signal/libsignal/protocol/incrementalmac/IncrementalStreamsTest.java
@@ -5,127 +5,175 @@
package org.signal.libsignal.protocol.incrementalmac;
-import junit.framework.TestCase;
-import org.signal.libsignal.protocol.util.Hex;
-
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.OutputStream;
+import junit.framework.TestCase;
+import org.signal.libsignal.protocol.util.Hex;
public class IncrementalStreamsTest extends TestCase {
- private static final byte[] TEST_HMAC_KEY = Hex.fromStringCondensedAssert("a83481457efecc69ad1342e21d9c0297f71debbf5c9304b4c1b2e433c1a78f98");
- private static final String TEST_EXPECTED_DIGEST = "84892f70600e549fb72879667a9d96a273f144b698ff9ef5a76062a56061a909884f6d9f42918a9e476ed518c4ac8f714bd33f045152ae049877fd3d1b0db25a";
- private static final ChunkSizeChoice SIZE_CHOICE = ChunkSizeChoice.everyNthByte(32);
- private static final String[] TEST_INPUT_PARTS = {"this is a test", " input to the incremental ", "mac stream"};
-
- public void testIncrementalDigestCreation() throws IOException {
- ByteArrayOutputStream out = new ByteArrayOutputStream();
- byte[] actualDigest = fullIncrementalDigest(out, TEST_INPUT_PARTS);
- assertEquals(String.join("", TEST_INPUT_PARTS), out.toString());
- assertEquals(TEST_EXPECTED_DIGEST, Hex.toStringCondensed(actualDigest));
+ private static final byte[] TEST_HMAC_KEY =
+ Hex.fromStringCondensedAssert(
+ "a83481457efecc69ad1342e21d9c0297f71debbf5c9304b4c1b2e433c1a78f98");
+ private static final String TEST_EXPECTED_DIGEST =
+ "84892f70600e549fb72879667a9d96a273f144b698ff9ef5a76062a56061a909884f6d9f42918a9e476ed518c4ac8f714bd33f045152ae049877fd3d1b0db25a";
+ private static final int CHUNK_SIZE = 32;
+ private static final ChunkSizeChoice SIZE_CHOICE = ChunkSizeChoice.everyNthByte(CHUNK_SIZE);
+ private static final String[] TEST_INPUT_PARTS = {
+ "this is a test", " input to the incremental ", "mac stream"
+ };
+
+ public void testIncrementalDigestCreation() throws IOException {
+ ByteArrayOutputStream out = new ByteArrayOutputStream();
+ byte[] actualDigest = fullIncrementalDigest(out, TEST_INPUT_PARTS);
+ assertEquals(String.join("", TEST_INPUT_PARTS), out.toString());
+ assertEquals(TEST_EXPECTED_DIGEST, Hex.toStringCondensed(actualDigest));
+ }
+
+ public void testIncrementalValidationSuccess() throws IOException {
+ byte[] digest = fullIncrementalDigest(new ByteArrayOutputStream(), TEST_INPUT_PARTS);
+ ByteArrayInputStream in =
+ new ByteArrayInputStream(String.join("", TEST_INPUT_PARTS).getBytes());
+
+ try (IncrementalMacInputStream incrementalIn =
+ new IncrementalMacInputStream(in, TEST_HMAC_KEY, SIZE_CHOICE, digest)) {
+ byte[] buffer = new byte[CHUNK_SIZE / 3]; // intentionally small
+ int totalBytesRead = 0;
+ while (incrementalIn.read(buffer) != -1) {}
}
+ }
- public void testIncrementalValidationSuccess() throws IOException {
- byte[] digest = fullIncrementalDigest(new ByteArrayOutputStream(), TEST_INPUT_PARTS);
- ByteArrayInputStream in = new ByteArrayInputStream(String.join("", TEST_INPUT_PARTS).getBytes());
+ public void testIncrementalValidationSuccessaByteByByte() throws IOException {
+ byte[] digest = fullIncrementalDigest(new ByteArrayOutputStream(), TEST_INPUT_PARTS);
+ ByteArrayInputStream in =
+ new ByteArrayInputStream(String.join("", TEST_INPUT_PARTS).getBytes());
- try (IncrementalMacInputStream incrementalIn = new IncrementalMacInputStream(in, TEST_HMAC_KEY, SIZE_CHOICE, digest)) {
- byte[] buffer = new byte[10]; // intentionally small
- while (incrementalIn.read(buffer) != -1) {
- }
- }
+ try (IncrementalMacInputStream incrementalIn =
+ new IncrementalMacInputStream(in, TEST_HMAC_KEY, SIZE_CHOICE, digest)) {
+ while (incrementalIn.read() != -1) {}
}
-
- public void testIncrementalValidationFailure() throws IOException {
- byte[] digest = fullIncrementalDigest(new ByteArrayOutputStream(), TEST_INPUT_PARTS);
- byte[] corruptInput = String.join("", TEST_INPUT_PARTS).getBytes();
- corruptInput[42] ^= 0xff;
- int EXPECTED_SUCCESSFUL_READS = 2;
- ByteArrayInputStream in = new ByteArrayInputStream(corruptInput);
- try (IncrementalMacInputStream incrementalIn = new IncrementalMacInputStream(in, TEST_HMAC_KEY, SIZE_CHOICE, digest)) {
- byte[] buffer = new byte[SIZE_CHOICE.getSizeInBytes()];
- for (int i = 0; i < EXPECTED_SUCCESSFUL_READS; i++) {
- incrementalIn.read(buffer);
- }
- try {
- incrementalIn.read(buffer);
- fail("The read should have failed");
- } catch (InvalidMacException _ex) {
-
- }
- }
+ }
+
+ public void testIncrementalValidationOneShotRead() throws IOException {
+ byte[] digest = fullIncrementalDigest(new ByteArrayOutputStream(), TEST_INPUT_PARTS);
+ ByteArrayInputStream in =
+ new ByteArrayInputStream(String.join("", TEST_INPUT_PARTS).getBytes());
+ byte[] largeBuffer = new byte[1024];
+
+ try (IncrementalMacInputStream incrementalIn =
+ new IncrementalMacInputStream(in, TEST_HMAC_KEY, SIZE_CHOICE, digest)) {
+ // Even though the buffer allows it, we get one chunk at a time.
+ assertEquals(CHUNK_SIZE, incrementalIn.read(largeBuffer));
+ assertEquals(18, incrementalIn.read(largeBuffer));
}
-
- public void testSingleByteRead() throws IOException {
- byte[] digest = fullIncrementalDigest(new ByteArrayOutputStream(), TEST_INPUT_PARTS);
- ByteArrayInputStream in = new ByteArrayInputStream(new byte[]{});
- try (IncrementalMacInputStream incrementalIn = new IncrementalMacInputStream(in, TEST_HMAC_KEY, SIZE_CHOICE, digest)) {
- // The first read with an empty input should call finalize on incremental mac, and throw an exception
- try {
- incrementalIn.read();
- fail("Validation should have failed");
- } catch (IOException ex) {
- }
- }
-
+ }
+
+ public void testIncrementalValidationFailure() throws IOException {
+ byte[] digest = fullIncrementalDigest(new ByteArrayOutputStream(), TEST_INPUT_PARTS);
+ byte[] corruptInput = String.join("", TEST_INPUT_PARTS).getBytes();
+ corruptInput[42] ^= 0xff;
+ ByteArrayInputStream in = new ByteArrayInputStream(corruptInput);
+ try (IncrementalMacInputStream incrementalIn =
+ new IncrementalMacInputStream(in, TEST_HMAC_KEY, SIZE_CHOICE, digest)) {
+ byte[] buffer = new byte[CHUNK_SIZE / 2];
+ assertEquals(16, incrementalIn.read(buffer));
+ assertEquals(16, incrementalIn.read(buffer));
+ // by now we have read the first chunk, and the next read will fail
+ try {
+ incrementalIn.read(buffer);
+ fail("The read should have failed");
+ } catch (InvalidMacException _ex) {
+ }
}
-
- public void testMultipleFlushesWhileWriting() throws IOException {
- ByteArrayOutputStream out = new ByteArrayOutputStream();
- ByteArrayOutputStream digestStream = new ByteArrayOutputStream();
- try (IncrementalMacOutputStream incrementalOut = new IncrementalMacOutputStream(out, TEST_HMAC_KEY, SIZE_CHOICE, digestStream)) {
- for (String part : TEST_INPUT_PARTS) {
- incrementalOut.write(part.getBytes());
- incrementalOut.flush();
- }
- }
- byte[] actualDigest = digestStream.toByteArray();
- assertEquals(TEST_EXPECTED_DIGEST, Hex.toStringCondensed(actualDigest));
+ }
+
+ public void testNoDataIsReadWithoutValidation() throws IOException {
+ byte[] digest = fullIncrementalDigest(new ByteArrayOutputStream(), TEST_INPUT_PARTS);
+ byte[] corruptInput = String.join("", TEST_INPUT_PARTS).getBytes();
+ corruptInput[1] ^= 0xff;
+ ByteArrayInputStream in = new ByteArrayInputStream(corruptInput);
+ try (IncrementalMacInputStream incrementalIn =
+ new IncrementalMacInputStream(in, TEST_HMAC_KEY, SIZE_CHOICE, digest)) {
+ try {
+ // even though the corruption is in the second byte
+ incrementalIn.read();
+ fail("The read should have failed");
+ } catch (InvalidMacException _ex) {
+ }
}
-
- public void testOutputStreamCloseIsIdempotent() throws IOException {
- ByteArrayOutputStream digestStream = new ByteArrayOutputStream();
- IncrementalMacOutputStream incrementalOut = new IncrementalMacOutputStream(new ByteArrayOutputStream(), TEST_HMAC_KEY, SIZE_CHOICE, digestStream);
- for (String part : TEST_INPUT_PARTS) {
- incrementalOut.write(part.getBytes());
- }
- incrementalOut.close();
- incrementalOut.close();
-
- assertEquals(TEST_EXPECTED_DIGEST, Hex.toStringCondensed(digestStream.toByteArray()));
+ }
+
+ public void testSingleByteRead() throws IOException {
+ byte[] digest = fullIncrementalDigest(new ByteArrayOutputStream(), TEST_INPUT_PARTS);
+ ByteArrayInputStream in = new ByteArrayInputStream(new byte[] {});
+ try (IncrementalMacInputStream incrementalIn =
+ new IncrementalMacInputStream(in, TEST_HMAC_KEY, SIZE_CHOICE, digest)) {
+ int read = incrementalIn.read();
+ assertEquals(-1, read);
}
-
- public void testEmptyInput() throws IOException {
- ByteArrayOutputStream out = new ByteArrayOutputStream();
- ByteArrayOutputStream digest = new ByteArrayOutputStream();
- try (IncrementalMacOutputStream incrementalOut = new IncrementalMacOutputStream(out, TEST_HMAC_KEY, ChunkSizeChoice.inferChunkSize(0), digest)) {
- incrementalOut.write(new byte[0]);
- incrementalOut.flush();
- }
+ }
+
+ public void testMultipleFlushesWhileWriting() throws IOException {
+ ByteArrayOutputStream out = new ByteArrayOutputStream();
+ ByteArrayOutputStream digestStream = new ByteArrayOutputStream();
+ try (IncrementalMacOutputStream incrementalOut =
+ new IncrementalMacOutputStream(out, TEST_HMAC_KEY, SIZE_CHOICE, digestStream)) {
+ for (String part : TEST_INPUT_PARTS) {
+ incrementalOut.write(part.getBytes());
+ incrementalOut.flush();
+ }
}
-
- public void testInvalidChunkSize() throws IOException {
- try {
- new IncrementalMacOutputStream(
- new ByteArrayOutputStream(),
- TEST_HMAC_KEY,
- ChunkSizeChoice.everyNthByte(0),
- new ByteArrayOutputStream());
- }
- catch(AssertionError ex) {
- assertTrue(ex.getMessage().contains("chunk size must be positive"));
- }
+ byte[] actualDigest = digestStream.toByteArray();
+ assertEquals(TEST_EXPECTED_DIGEST, Hex.toStringCondensed(actualDigest));
+ }
+
+ public void testOutputStreamCloseIsIdempotent() throws IOException {
+ ByteArrayOutputStream digestStream = new ByteArrayOutputStream();
+ IncrementalMacOutputStream incrementalOut =
+ new IncrementalMacOutputStream(
+ new ByteArrayOutputStream(), TEST_HMAC_KEY, SIZE_CHOICE, digestStream);
+ for (String part : TEST_INPUT_PARTS) {
+ incrementalOut.write(part.getBytes());
}
-
- private byte[] fullIncrementalDigest(OutputStream innerOut, String[] input) throws IOException {
- ByteArrayOutputStream digestStream = new ByteArrayOutputStream();
- try (IncrementalMacOutputStream incrementalOut = new IncrementalMacOutputStream(innerOut, TEST_HMAC_KEY, SIZE_CHOICE, digestStream)) {
- for (String part : input) {
- incrementalOut.write(part.getBytes());
- }
- incrementalOut.flush();
- }
- return digestStream.toByteArray();
+ incrementalOut.close();
+ incrementalOut.close();
+
+ assertEquals(TEST_EXPECTED_DIGEST, Hex.toStringCondensed(digestStream.toByteArray()));
+ }
+
+ public void testEmptyInput() throws IOException {
+ ByteArrayOutputStream out = new ByteArrayOutputStream();
+ ByteArrayOutputStream digest = new ByteArrayOutputStream();
+ try (IncrementalMacOutputStream incrementalOut =
+ new IncrementalMacOutputStream(
+ out, TEST_HMAC_KEY, ChunkSizeChoice.inferChunkSize(0), digest)) {
+ incrementalOut.write(new byte[0]);
+ incrementalOut.flush();
+ }
+ }
+
+ public void testInvalidChunkSize() throws IOException {
+ try {
+ new IncrementalMacOutputStream(
+ new ByteArrayOutputStream(),
+ TEST_HMAC_KEY,
+ ChunkSizeChoice.everyNthByte(0),
+ new ByteArrayOutputStream());
+ } catch (AssertionError ex) {
+ assertTrue(ex.getMessage().contains("chunk size must be positive"));
+ }
+ }
+
+ private byte[] fullIncrementalDigest(OutputStream innerOut, String[] input) throws IOException {
+ ByteArrayOutputStream digestStream = new ByteArrayOutputStream();
+ try (IncrementalMacOutputStream incrementalOut =
+ new IncrementalMacOutputStream(innerOut, TEST_HMAC_KEY, SIZE_CHOICE, digestStream)) {
+ for (String part : input) {
+ incrementalOut.write(part.getBytes());
+ }
+ incrementalOut.flush();
}
+ return digestStream.toByteArray();
+ }
}
diff --git a/java/client/src/test/java/org/signal/libsignal/protocol/kdf/HKDFTest.java b/java/client/src/test/java/org/signal/libsignal/protocol/kdf/HKDFTest.java
index 21762a519c..69ab11d1da 100644
--- a/java/client/src/test/java/org/signal/libsignal/protocol/kdf/HKDFTest.java
+++ b/java/client/src/test/java/org/signal/libsignal/protocol/kdf/HKDFTest.java
@@ -1,31 +1,26 @@
-package org.signal.libsignal.protocol.kdf;
+//
+// Copyright 2023 Signal Messenger, LLC.
+// SPDX-License-Identifier: AGPL-3.0-only
+//
-import junit.framework.TestCase;
+package org.signal.libsignal.protocol.kdf;
import java.util.Arrays;
+import junit.framework.TestCase;
+import org.signal.libsignal.protocol.util.Hex;
public class HKDFTest extends TestCase {
public void testVectorV3() {
- byte[] ikm = {0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b,
- 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b,
- 0x0b, 0x0b};
-
- byte[] salt = {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09,
- 0x0a, 0x0b, 0x0c};
-
- byte[] info = {(byte) 0xf0, (byte) 0xf1, (byte) 0xf2, (byte) 0xf3, (byte) 0xf4,
- (byte) 0xf5, (byte) 0xf6, (byte) 0xf7, (byte) 0xf8, (byte) 0xf9};
-
- byte[] okm = {(byte) 0x3c, (byte) 0xb2, (byte) 0x5f, (byte) 0x25, (byte) 0xfa,
- (byte) 0xac, (byte) 0xd5, (byte) 0x7a, (byte) 0x90, (byte) 0x43,
- (byte) 0x4f, (byte) 0x64, (byte) 0xd0, (byte) 0x36, (byte) 0x2f,
- (byte) 0x2a, (byte) 0x2d, (byte) 0x2d, (byte) 0x0a, (byte) 0x90,
- (byte) 0xcf, (byte) 0x1a, (byte) 0x5a, (byte) 0x4c, (byte) 0x5d,
- (byte) 0xb0, (byte) 0x2d, (byte) 0x56, (byte) 0xec, (byte) 0xc4,
- (byte) 0xc5, (byte) 0xbf, (byte) 0x34, (byte) 0x00, (byte) 0x72,
- (byte) 0x08, (byte) 0xd5, (byte) 0xb8, (byte) 0x87, (byte) 0x18,
- (byte) 0x58, (byte) 0x65};
+ byte[] ikm = Hex.fromStringCondensedAssert("0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b");
+
+ byte[] salt = Hex.fromStringCondensedAssert("000102030405060708090a0b0c");
+
+ byte[] info = Hex.fromStringCondensedAssert("f0f1f2f3f4f5f6f7f8f9");
+
+ byte[] okm =
+ Hex.fromStringCondensedAssert(
+ "3cb25f25faacd57a90434f64d0362f2a2d2d0a90cf1a5a4c5db02d56ecc4c5bf34007208d5b887185865");
byte[] actualOutput = HKDF.deriveSecrets(ikm, salt, info, 42);
@@ -33,96 +28,34 @@ public void testVectorV3() {
}
public void testVectorLongV3() {
- byte[] ikm = {(byte) 0x00, (byte) 0x01, (byte) 0x02, (byte) 0x03, (byte) 0x04,
- (byte) 0x05, (byte) 0x06, (byte) 0x07, (byte) 0x08, (byte) 0x09,
- (byte) 0x0a, (byte) 0x0b, (byte) 0x0c, (byte) 0x0d, (byte) 0x0e,
- (byte) 0x0f, (byte) 0x10, (byte) 0x11, (byte) 0x12, (byte) 0x13,
- (byte) 0x14, (byte) 0x15, (byte) 0x16, (byte) 0x17, (byte) 0x18,
- (byte) 0x19, (byte) 0x1a, (byte) 0x1b, (byte) 0x1c, (byte) 0x1d,
- (byte) 0x1e, (byte) 0x1f, (byte) 0x20, (byte) 0x21, (byte) 0x22,
- (byte) 0x23, (byte) 0x24, (byte) 0x25, (byte) 0x26, (byte) 0x27,
- (byte) 0x28, (byte) 0x29, (byte) 0x2a, (byte) 0x2b, (byte) 0x2c,
- (byte) 0x2d, (byte) 0x2e, (byte) 0x2f, (byte) 0x30, (byte) 0x31,
- (byte) 0x32, (byte) 0x33, (byte) 0x34, (byte) 0x35, (byte) 0x36,
- (byte) 0x37, (byte) 0x38, (byte) 0x39, (byte) 0x3a, (byte) 0x3b,
- (byte) 0x3c, (byte) 0x3d, (byte) 0x3e, (byte) 0x3f, (byte) 0x40,
- (byte) 0x41, (byte) 0x42, (byte) 0x43, (byte) 0x44, (byte) 0x45,
- (byte) 0x46, (byte) 0x47, (byte) 0x48, (byte) 0x49, (byte) 0x4a,
- (byte) 0x4b, (byte) 0x4c, (byte) 0x4d, (byte) 0x4e, (byte) 0x4f};
-
- byte[] salt = {(byte) 0x60, (byte) 0x61, (byte) 0x62, (byte) 0x63, (byte) 0x64,
- (byte) 0x65, (byte) 0x66, (byte) 0x67, (byte) 0x68, (byte) 0x69,
- (byte) 0x6a, (byte) 0x6b, (byte) 0x6c, (byte) 0x6d, (byte) 0x6e,
- (byte) 0x6f, (byte) 0x70, (byte) 0x71, (byte) 0x72, (byte) 0x73,
- (byte) 0x74, (byte) 0x75, (byte) 0x76, (byte) 0x77, (byte) 0x78,
- (byte) 0x79, (byte) 0x7a, (byte) 0x7b, (byte) 0x7c, (byte) 0x7d,
- (byte) 0x7e, (byte) 0x7f, (byte) 0x80, (byte) 0x81, (byte) 0x82,
- (byte) 0x83, (byte) 0x84, (byte) 0x85, (byte) 0x86, (byte) 0x87,
- (byte) 0x88, (byte) 0x89, (byte) 0x8a, (byte) 0x8b, (byte) 0x8c,
- (byte) 0x8d, (byte) 0x8e, (byte) 0x8f, (byte) 0x90, (byte) 0x91,
- (byte) 0x92, (byte) 0x93, (byte) 0x94, (byte) 0x95, (byte) 0x96,
- (byte) 0x97, (byte) 0x98, (byte) 0x99, (byte) 0x9a, (byte) 0x9b,
- (byte) 0x9c, (byte) 0x9d, (byte) 0x9e, (byte) 0x9f, (byte) 0xa0,
- (byte) 0xa1, (byte) 0xa2, (byte) 0xa3, (byte) 0xa4, (byte) 0xa5,
- (byte) 0xa6, (byte) 0xa7, (byte) 0xa8, (byte) 0xa9, (byte) 0xaa,
- (byte) 0xab, (byte) 0xac, (byte) 0xad, (byte) 0xae, (byte) 0xaf};
-
- byte[] info = {(byte) 0xb0, (byte) 0xb1, (byte) 0xb2, (byte) 0xb3, (byte) 0xb4,
- (byte) 0xb5, (byte) 0xb6, (byte) 0xb7, (byte) 0xb8, (byte) 0xb9,
- (byte) 0xba, (byte) 0xbb, (byte) 0xbc, (byte) 0xbd, (byte) 0xbe,
- (byte) 0xbf, (byte) 0xc0, (byte) 0xc1, (byte) 0xc2, (byte) 0xc3,
- (byte) 0xc4, (byte) 0xc5, (byte) 0xc6, (byte) 0xc7, (byte) 0xc8,
- (byte) 0xc9, (byte) 0xca, (byte) 0xcb, (byte) 0xcc, (byte) 0xcd,
- (byte) 0xce, (byte) 0xcf, (byte) 0xd0, (byte) 0xd1, (byte) 0xd2,
- (byte) 0xd3, (byte) 0xd4, (byte) 0xd5, (byte) 0xd6, (byte) 0xd7,
- (byte) 0xd8, (byte) 0xd9, (byte) 0xda, (byte) 0xdb, (byte) 0xdc,
- (byte) 0xdd, (byte) 0xde, (byte) 0xdf, (byte) 0xe0, (byte) 0xe1,
- (byte) 0xe2, (byte) 0xe3, (byte) 0xe4, (byte) 0xe5, (byte) 0xe6,
- (byte) 0xe7, (byte) 0xe8, (byte) 0xe9, (byte) 0xea, (byte) 0xeb,
- (byte) 0xec, (byte) 0xed, (byte) 0xee, (byte) 0xef, (byte) 0xf0,
- (byte) 0xf1, (byte) 0xf2, (byte) 0xf3, (byte) 0xf4, (byte) 0xf5,
- (byte) 0xf6, (byte) 0xf7, (byte) 0xf8, (byte) 0xf9, (byte) 0xfa,
- (byte) 0xfb, (byte) 0xfc, (byte) 0xfd, (byte) 0xfe, (byte) 0xff};
-
- byte[] okm = {(byte) 0xb1, (byte) 0x1e, (byte) 0x39, (byte) 0x8d, (byte) 0xc8,
- (byte) 0x03, (byte) 0x27, (byte) 0xa1, (byte) 0xc8, (byte) 0xe7,
- (byte) 0xf7, (byte) 0x8c, (byte) 0x59, (byte) 0x6a, (byte) 0x49,
- (byte) 0x34, (byte) 0x4f, (byte) 0x01, (byte) 0x2e, (byte) 0xda,
- (byte) 0x2d, (byte) 0x4e, (byte) 0xfa, (byte) 0xd8, (byte) 0xa0,
- (byte) 0x50, (byte) 0xcc, (byte) 0x4c, (byte) 0x19, (byte) 0xaf,
- (byte) 0xa9, (byte) 0x7c, (byte) 0x59, (byte) 0x04, (byte) 0x5a,
- (byte) 0x99, (byte) 0xca, (byte) 0xc7, (byte) 0x82, (byte) 0x72,
- (byte) 0x71, (byte) 0xcb, (byte) 0x41, (byte) 0xc6, (byte) 0x5e,
- (byte) 0x59, (byte) 0x0e, (byte) 0x09, (byte) 0xda, (byte) 0x32,
- (byte) 0x75, (byte) 0x60, (byte) 0x0c, (byte) 0x2f, (byte) 0x09,
- (byte) 0xb8, (byte) 0x36, (byte) 0x77, (byte) 0x93, (byte) 0xa9,
- (byte) 0xac, (byte) 0xa3, (byte) 0xdb, (byte) 0x71, (byte) 0xcc,
- (byte) 0x30, (byte) 0xc5, (byte) 0x81, (byte) 0x79, (byte) 0xec,
- (byte) 0x3e, (byte) 0x87, (byte) 0xc1, (byte) 0x4c, (byte) 0x01,
- (byte) 0xd5, (byte) 0xc1, (byte) 0xf3, (byte) 0x43, (byte) 0x4f,
- (byte) 0x1d, (byte) 0x87};
+ byte[] ikm =
+ Hex.fromStringCondensedAssert(
+ "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f");
+
+ byte[] salt =
+ Hex.fromStringCondensedAssert(
+ "606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeaf");
+
+ byte[] info =
+ Hex.fromStringCondensedAssert(
+ "b0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff");
+
+ byte[] okm =
+ Hex.fromStringCondensedAssert(
+ "b11e398dc80327a1c8e7f78c596a49344f012eda2d4efad8a050cc4c19afa97c59045a99cac7827271cb41c65e590e09da3275600c2f09b8367793a9aca3db71cc30c58179ec3e87c14c01d5c1f3434f1d87");
byte[] actualOutput = HKDF.deriveSecrets(ikm, salt, info, 82);
assertTrue(Arrays.equals(okm, actualOutput));
}
public void testNullInfo() {
- byte[] ikm = {0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b,
- 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b,
- 0x0b, 0x0b};
-
- byte[] salt = {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09,
- 0x0a, 0x0b, 0x0c};
-
- byte[] okm = {(byte) 0x3c, (byte) 0xb2, (byte) 0x5f, (byte) 0x25, (byte) 0xfa,
- (byte) 0xac, (byte) 0xd5, (byte) 0x7a, (byte) 0x90, (byte) 0x43,
- (byte) 0x4f, (byte) 0x64, (byte) 0xd0, (byte) 0x36, (byte) 0x2f,
- (byte) 0x2a, (byte) 0x2d, (byte) 0x2d, (byte) 0x0a, (byte) 0x90,
- (byte) 0xcf, (byte) 0x1a, (byte) 0x5a, (byte) 0x4c, (byte) 0x5d,
- (byte) 0xb0, (byte) 0x2d, (byte) 0x56, (byte) 0xec, (byte) 0xc4,
- (byte) 0xc5, (byte) 0xbf, (byte) 0x34, (byte) 0x00, (byte) 0x72,
- (byte) 0x08, (byte) 0xd5, (byte) 0xb8, (byte) 0x87, (byte) 0x18,
- (byte) 0x58, (byte) 0x65};
+ byte[] ikm = Hex.fromStringCondensedAssert("0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b");
+
+ byte[] salt = Hex.fromStringCondensedAssert("000102030405060708090a0b0c");
+
+ byte[] okm =
+ Hex.fromStringCondensedAssert(
+ "3cb25f25faacd57a90434f64d0362f2a2d2d0a90cf1a5a4c5db02d56ecc4c5bf34007208d5b887185865");
byte[] outputWithNull = HKDF.deriveSecrets(ikm, salt, null, 42);
byte[] outputWithEmpty = HKDF.deriveSecrets(ikm, salt, new byte[] {}, 42);
diff --git a/java/client/src/test/java/org/signal/libsignal/protocol/ratchet/RatchetingSessionTest.java b/java/client/src/test/java/org/signal/libsignal/protocol/ratchet/RatchetingSessionTest.java
index 717ed0e8d7..569ca7da0f 100644
--- a/java/client/src/test/java/org/signal/libsignal/protocol/ratchet/RatchetingSessionTest.java
+++ b/java/client/src/test/java/org/signal/libsignal/protocol/ratchet/RatchetingSessionTest.java
@@ -1,7 +1,12 @@
+//
+// Copyright 2023 Signal Messenger, LLC.
+// SPDX-License-Identifier: AGPL-3.0-only
+//
+
package org.signal.libsignal.protocol.ratchet;
+import java.util.Arrays;
import junit.framework.TestCase;
-
import org.signal.libsignal.protocol.IdentityKey;
import org.signal.libsignal.protocol.IdentityKeyPair;
import org.signal.libsignal.protocol.InvalidKeyException;
@@ -11,199 +16,241 @@
import org.signal.libsignal.protocol.ecc.ECPublicKey;
import org.signal.libsignal.protocol.state.SessionRecord;
-import java.util.Arrays;
-
public class RatchetingSessionTest extends TestCase {
public void testRatchetingSessionAsBob() throws InvalidKeyException {
- byte[] bobPublic = {(byte) 0x05, (byte) 0x2c, (byte) 0xb4, (byte) 0x97,
- (byte) 0x76, (byte) 0xb8, (byte) 0x77, (byte) 0x02,
- (byte) 0x05, (byte) 0x74, (byte) 0x5a, (byte) 0x3a,
- (byte) 0x6e, (byte) 0x24, (byte) 0xf5, (byte) 0x79,
- (byte) 0xcd, (byte) 0xb4, (byte) 0xba, (byte) 0x7a,
- (byte) 0x89, (byte) 0x04, (byte) 0x10, (byte) 0x05,
- (byte) 0x92, (byte) 0x8e, (byte) 0xbb, (byte) 0xad,
- (byte) 0xc9, (byte) 0xc0, (byte) 0x5a, (byte) 0xd4,
- (byte) 0x58};
-
- byte[] bobPrivate = {(byte) 0xa1, (byte) 0xca, (byte) 0xb4, (byte) 0x8f,
- (byte) 0x7c, (byte) 0x89, (byte) 0x3f, (byte) 0xaf,
- (byte) 0xa9, (byte) 0x88, (byte) 0x0a, (byte) 0x28,
- (byte) 0xc3, (byte) 0xb4, (byte) 0x99, (byte) 0x9d,
- (byte) 0x28, (byte) 0xd6, (byte) 0x32, (byte) 0x95,
- (byte) 0x62, (byte) 0xd2, (byte) 0x7a, (byte) 0x4e,
- (byte) 0xa4, (byte) 0xe2, (byte) 0x2e, (byte) 0x9f,
- (byte) 0xf1, (byte) 0xbd, (byte) 0xd6, (byte) 0x5a};
-
- byte[] bobIdentityPublic = {(byte) 0x05, (byte) 0xf1, (byte) 0xf4, (byte) 0x38,
- (byte) 0x74, (byte) 0xf6, (byte) 0x96, (byte) 0x69,
- (byte) 0x56, (byte) 0xc2, (byte) 0xdd, (byte) 0x47,
- (byte) 0x3f, (byte) 0x8f, (byte) 0xa1, (byte) 0x5a,
- (byte) 0xde, (byte) 0xb7, (byte) 0x1d, (byte) 0x1c,
- (byte) 0xb9, (byte) 0x91, (byte) 0xb2, (byte) 0x34,
- (byte) 0x16, (byte) 0x92, (byte) 0x32, (byte) 0x4c,
- (byte) 0xef, (byte) 0xb1, (byte) 0xc5, (byte) 0xe6,
- (byte) 0x26};
-
- byte[] bobIdentityPrivate = {(byte) 0x48, (byte) 0x75, (byte) 0xcc, (byte) 0x69,
- (byte) 0xdd, (byte) 0xf8, (byte) 0xea, (byte) 0x07,
- (byte) 0x19, (byte) 0xec, (byte) 0x94, (byte) 0x7d,
- (byte) 0x61, (byte) 0x08, (byte) 0x11, (byte) 0x35,
- (byte) 0x86, (byte) 0x8d, (byte) 0x5f, (byte) 0xd8,
- (byte) 0x01, (byte) 0xf0, (byte) 0x2c, (byte) 0x02,
- (byte) 0x25, (byte) 0xe5, (byte) 0x16, (byte) 0xdf,
- (byte) 0x21, (byte) 0x56, (byte) 0x60, (byte) 0x5e};
-
- byte[] aliceBasePublic = {(byte) 0x05, (byte) 0x47, (byte) 0x2d, (byte) 0x1f,
- (byte) 0xb1, (byte) 0xa9, (byte) 0x86, (byte) 0x2c,
- (byte) 0x3a, (byte) 0xf6, (byte) 0xbe, (byte) 0xac,
- (byte) 0xa8, (byte) 0x92, (byte) 0x02, (byte) 0x77,
- (byte) 0xe2, (byte) 0xb2, (byte) 0x6f, (byte) 0x4a,
- (byte) 0x79, (byte) 0x21, (byte) 0x3e, (byte) 0xc7,
- (byte) 0xc9, (byte) 0x06, (byte) 0xae, (byte) 0xb3,
- (byte) 0x5e, (byte) 0x03, (byte) 0xcf, (byte) 0x89,
- (byte) 0x50};
-
- byte[] aliceEphemeralPublic = {(byte) 0x05, (byte) 0x6c, (byte) 0x3e, (byte) 0x0d,
- (byte) 0x1f, (byte) 0x52, (byte) 0x02, (byte) 0x83,
- (byte) 0xef, (byte) 0xcc, (byte) 0x55, (byte) 0xfc,
- (byte) 0xa5, (byte) 0xe6, (byte) 0x70, (byte) 0x75,
- (byte) 0xb9, (byte) 0x04, (byte) 0x00, (byte) 0x7f,
- (byte) 0x18, (byte) 0x81, (byte) 0xd1, (byte) 0x51,
- (byte) 0xaf, (byte) 0x76, (byte) 0xdf, (byte) 0x18,
- (byte) 0xc5, (byte) 0x1d, (byte) 0x29, (byte) 0xd3,
- (byte) 0x4b};
-
- byte[] aliceIdentityPublic = {(byte) 0x05, (byte) 0xb4, (byte) 0xa8, (byte) 0x45,
- (byte) 0x56, (byte) 0x60, (byte) 0xad, (byte) 0xa6,
- (byte) 0x5b, (byte) 0x40, (byte) 0x10, (byte) 0x07,
- (byte) 0xf6, (byte) 0x15, (byte) 0xe6, (byte) 0x54,
- (byte) 0x04, (byte) 0x17, (byte) 0x46, (byte) 0x43,
- (byte) 0x2e, (byte) 0x33, (byte) 0x39, (byte) 0xc6,
- (byte) 0x87, (byte) 0x51, (byte) 0x49, (byte) 0xbc,
- (byte) 0xee, (byte) 0xfc, (byte) 0xb4, (byte) 0x2b,
- (byte) 0x4a};
-
- byte[] bobSignedPreKeyPublic = {(byte)0x05, (byte)0xac, (byte)0x24, (byte)0x8a, (byte)0x8f,
- (byte)0x26, (byte)0x3b, (byte)0xe6, (byte)0x86, (byte)0x35,
- (byte)0x76, (byte)0xeb, (byte)0x03, (byte)0x62, (byte)0xe2,
- (byte)0x8c, (byte)0x82, (byte)0x8f, (byte)0x01, (byte)0x07,
- (byte)0xa3, (byte)0x37, (byte)0x9d, (byte)0x34, (byte)0xba,
- (byte)0xb1, (byte)0x58, (byte)0x6b, (byte)0xf8, (byte)0xc7,
- (byte)0x70, (byte)0xcd, (byte)0x67};
-
- byte[] bobSignedPreKeyPrivate = {(byte)0x58, (byte)0x39, (byte)0x00, (byte)0x13, (byte)0x1f,
- (byte)0xb7, (byte)0x27, (byte)0x99, (byte)0x8b, (byte)0x78,
- (byte)0x03, (byte)0xfe, (byte)0x6a, (byte)0xc2, (byte)0x2c,
- (byte)0xc5, (byte)0x91, (byte)0xf3, (byte)0x42, (byte)0xe4,
- (byte)0xe4, (byte)0x2a, (byte)0x8c, (byte)0x8d, (byte)0x5d,
- (byte)0x78, (byte)0x19, (byte)0x42, (byte)0x09, (byte)0xb8,
- (byte)0xd2, (byte)0x53};
-
- byte[] senderChain = {(byte)0x97, (byte)0x97, (byte)0xca, (byte)0xca, (byte)0x53,
- (byte)0xc9, (byte)0x89, (byte)0xbb, (byte)0xe2, (byte)0x29,
- (byte)0xa4, (byte)0x0c, (byte)0xa7, (byte)0x72, (byte)0x70,
- (byte)0x10, (byte)0xeb, (byte)0x26, (byte)0x04, (byte)0xfc,
- (byte)0x14, (byte)0x94, (byte)0x5d, (byte)0x77, (byte)0x95,
- (byte)0x8a, (byte)0x0a, (byte)0xed, (byte)0xa0, (byte)0x88,
- (byte)0xb4, (byte)0x4d};
-
- IdentityKey bobIdentityKeyPublic = new IdentityKey(bobIdentityPublic, 0);
- ECPrivateKey bobIdentityKeyPrivate = Curve.decodePrivatePoint(bobIdentityPrivate);
- IdentityKeyPair bobIdentityKey = new IdentityKeyPair(bobIdentityKeyPublic, bobIdentityKeyPrivate);
- ECPublicKey bobEphemeralPublicKey = Curve.decodePoint(bobPublic, 0);
- ECPrivateKey bobEphemeralPrivateKey = Curve.decodePrivatePoint(bobPrivate);
- ECKeyPair bobEphemeralKey = new ECKeyPair(bobEphemeralPublicKey, bobEphemeralPrivateKey);
- ECKeyPair bobBaseKey = bobEphemeralKey;
- ECKeyPair bobSignedPreKey = new ECKeyPair(Curve.decodePoint(bobSignedPreKeyPublic, 0), Curve.decodePrivatePoint(bobSignedPreKeyPrivate));
-
- ECPublicKey aliceBasePublicKey = Curve.decodePoint(aliceBasePublic, 0);
- ECPublicKey aliceEphemeralPublicKey = Curve.decodePoint(aliceEphemeralPublic, 0);
- IdentityKey aliceIdentityPublicKey = new IdentityKey(aliceIdentityPublic, 0);
-
- SessionRecord session = SessionRecord.initializeBobSession(bobIdentityKey,
- bobSignedPreKey,
- bobEphemeralKey,
- aliceIdentityPublicKey,
- aliceBasePublicKey);
+ byte[] bobPublic = {
+ (byte) 0x05, (byte) 0x2c, (byte) 0xb4, (byte) 0x97,
+ (byte) 0x76, (byte) 0xb8, (byte) 0x77, (byte) 0x02,
+ (byte) 0x05, (byte) 0x74, (byte) 0x5a, (byte) 0x3a,
+ (byte) 0x6e, (byte) 0x24, (byte) 0xf5, (byte) 0x79,
+ (byte) 0xcd, (byte) 0xb4, (byte) 0xba, (byte) 0x7a,
+ (byte) 0x89, (byte) 0x04, (byte) 0x10, (byte) 0x05,
+ (byte) 0x92, (byte) 0x8e, (byte) 0xbb, (byte) 0xad,
+ (byte) 0xc9, (byte) 0xc0, (byte) 0x5a, (byte) 0xd4,
+ (byte) 0x58
+ };
+
+ byte[] bobPrivate = {
+ (byte) 0xa1, (byte) 0xca, (byte) 0xb4, (byte) 0x8f,
+ (byte) 0x7c, (byte) 0x89, (byte) 0x3f, (byte) 0xaf,
+ (byte) 0xa9, (byte) 0x88, (byte) 0x0a, (byte) 0x28,
+ (byte) 0xc3, (byte) 0xb4, (byte) 0x99, (byte) 0x9d,
+ (byte) 0x28, (byte) 0xd6, (byte) 0x32, (byte) 0x95,
+ (byte) 0x62, (byte) 0xd2, (byte) 0x7a, (byte) 0x4e,
+ (byte) 0xa4, (byte) 0xe2, (byte) 0x2e, (byte) 0x9f,
+ (byte) 0xf1, (byte) 0xbd, (byte) 0xd6, (byte) 0x5a
+ };
+
+ byte[] bobIdentityPublic = {
+ (byte) 0x05, (byte) 0xf1, (byte) 0xf4, (byte) 0x38,
+ (byte) 0x74, (byte) 0xf6, (byte) 0x96, (byte) 0x69,
+ (byte) 0x56, (byte) 0xc2, (byte) 0xdd, (byte) 0x47,
+ (byte) 0x3f, (byte) 0x8f, (byte) 0xa1, (byte) 0x5a,
+ (byte) 0xde, (byte) 0xb7, (byte) 0x1d, (byte) 0x1c,
+ (byte) 0xb9, (byte) 0x91, (byte) 0xb2, (byte) 0x34,
+ (byte) 0x16, (byte) 0x92, (byte) 0x32, (byte) 0x4c,
+ (byte) 0xef, (byte) 0xb1, (byte) 0xc5, (byte) 0xe6,
+ (byte) 0x26
+ };
+
+ byte[] bobIdentityPrivate = {
+ (byte) 0x48, (byte) 0x75, (byte) 0xcc, (byte) 0x69,
+ (byte) 0xdd, (byte) 0xf8, (byte) 0xea, (byte) 0x07,
+ (byte) 0x19, (byte) 0xec, (byte) 0x94, (byte) 0x7d,
+ (byte) 0x61, (byte) 0x08, (byte) 0x11, (byte) 0x35,
+ (byte) 0x86, (byte) 0x8d, (byte) 0x5f, (byte) 0xd8,
+ (byte) 0x01, (byte) 0xf0, (byte) 0x2c, (byte) 0x02,
+ (byte) 0x25, (byte) 0xe5, (byte) 0x16, (byte) 0xdf,
+ (byte) 0x21, (byte) 0x56, (byte) 0x60, (byte) 0x5e
+ };
+
+ byte[] aliceBasePublic = {
+ (byte) 0x05, (byte) 0x47, (byte) 0x2d, (byte) 0x1f,
+ (byte) 0xb1, (byte) 0xa9, (byte) 0x86, (byte) 0x2c,
+ (byte) 0x3a, (byte) 0xf6, (byte) 0xbe, (byte) 0xac,
+ (byte) 0xa8, (byte) 0x92, (byte) 0x02, (byte) 0x77,
+ (byte) 0xe2, (byte) 0xb2, (byte) 0x6f, (byte) 0x4a,
+ (byte) 0x79, (byte) 0x21, (byte) 0x3e, (byte) 0xc7,
+ (byte) 0xc9, (byte) 0x06, (byte) 0xae, (byte) 0xb3,
+ (byte) 0x5e, (byte) 0x03, (byte) 0xcf, (byte) 0x89,
+ (byte) 0x50
+ };
+
+ byte[] aliceEphemeralPublic = {
+ (byte) 0x05, (byte) 0x6c, (byte) 0x3e, (byte) 0x0d,
+ (byte) 0x1f, (byte) 0x52, (byte) 0x02, (byte) 0x83,
+ (byte) 0xef, (byte) 0xcc, (byte) 0x55, (byte) 0xfc,
+ (byte) 0xa5, (byte) 0xe6, (byte) 0x70, (byte) 0x75,
+ (byte) 0xb9, (byte) 0x04, (byte) 0x00, (byte) 0x7f,
+ (byte) 0x18, (byte) 0x81, (byte) 0xd1, (byte) 0x51,
+ (byte) 0xaf, (byte) 0x76, (byte) 0xdf, (byte) 0x18,
+ (byte) 0xc5, (byte) 0x1d, (byte) 0x29, (byte) 0xd3,
+ (byte) 0x4b
+ };
+
+ byte[] aliceIdentityPublic = {
+ (byte) 0x05, (byte) 0xb4, (byte) 0xa8, (byte) 0x45,
+ (byte) 0x56, (byte) 0x60, (byte) 0xad, (byte) 0xa6,
+ (byte) 0x5b, (byte) 0x40, (byte) 0x10, (byte) 0x07,
+ (byte) 0xf6, (byte) 0x15, (byte) 0xe6, (byte) 0x54,
+ (byte) 0x04, (byte) 0x17, (byte) 0x46, (byte) 0x43,
+ (byte) 0x2e, (byte) 0x33, (byte) 0x39, (byte) 0xc6,
+ (byte) 0x87, (byte) 0x51, (byte) 0x49, (byte) 0xbc,
+ (byte) 0xee, (byte) 0xfc, (byte) 0xb4, (byte) 0x2b,
+ (byte) 0x4a
+ };
+
+ byte[] bobSignedPreKeyPublic = {
+ (byte) 0x05, (byte) 0xac, (byte) 0x24, (byte) 0x8a, (byte) 0x8f,
+ (byte) 0x26, (byte) 0x3b, (byte) 0xe6, (byte) 0x86, (byte) 0x35,
+ (byte) 0x76, (byte) 0xeb, (byte) 0x03, (byte) 0x62, (byte) 0xe2,
+ (byte) 0x8c, (byte) 0x82, (byte) 0x8f, (byte) 0x01, (byte) 0x07,
+ (byte) 0xa3, (byte) 0x37, (byte) 0x9d, (byte) 0x34, (byte) 0xba,
+ (byte) 0xb1, (byte) 0x58, (byte) 0x6b, (byte) 0xf8, (byte) 0xc7,
+ (byte) 0x70, (byte) 0xcd, (byte) 0x67
+ };
+
+ byte[] bobSignedPreKeyPrivate = {
+ (byte) 0x58, (byte) 0x39, (byte) 0x00, (byte) 0x13, (byte) 0x1f,
+ (byte) 0xb7, (byte) 0x27, (byte) 0x99, (byte) 0x8b, (byte) 0x78,
+ (byte) 0x03, (byte) 0xfe, (byte) 0x6a, (byte) 0xc2, (byte) 0x2c,
+ (byte) 0xc5, (byte) 0x91, (byte) 0xf3, (byte) 0x42, (byte) 0xe4,
+ (byte) 0xe4, (byte) 0x2a, (byte) 0x8c, (byte) 0x8d, (byte) 0x5d,
+ (byte) 0x78, (byte) 0x19, (byte) 0x42, (byte) 0x09, (byte) 0xb8,
+ (byte) 0xd2, (byte) 0x53
+ };
+
+ byte[] senderChain = {
+ (byte) 0x97, (byte) 0x97, (byte) 0xca, (byte) 0xca, (byte) 0x53,
+ (byte) 0xc9, (byte) 0x89, (byte) 0xbb, (byte) 0xe2, (byte) 0x29,
+ (byte) 0xa4, (byte) 0x0c, (byte) 0xa7, (byte) 0x72, (byte) 0x70,
+ (byte) 0x10, (byte) 0xeb, (byte) 0x26, (byte) 0x04, (byte) 0xfc,
+ (byte) 0x14, (byte) 0x94, (byte) 0x5d, (byte) 0x77, (byte) 0x95,
+ (byte) 0x8a, (byte) 0x0a, (byte) 0xed, (byte) 0xa0, (byte) 0x88,
+ (byte) 0xb4, (byte) 0x4d
+ };
+
+ IdentityKey bobIdentityKeyPublic = new IdentityKey(bobIdentityPublic, 0);
+ ECPrivateKey bobIdentityKeyPrivate = Curve.decodePrivatePoint(bobIdentityPrivate);
+ IdentityKeyPair bobIdentityKey =
+ new IdentityKeyPair(bobIdentityKeyPublic, bobIdentityKeyPrivate);
+ ECPublicKey bobEphemeralPublicKey = Curve.decodePoint(bobPublic, 0);
+ ECPrivateKey bobEphemeralPrivateKey = Curve.decodePrivatePoint(bobPrivate);
+ ECKeyPair bobEphemeralKey = new ECKeyPair(bobEphemeralPublicKey, bobEphemeralPrivateKey);
+ ECKeyPair bobBaseKey = bobEphemeralKey;
+ ECKeyPair bobSignedPreKey =
+ new ECKeyPair(
+ Curve.decodePoint(bobSignedPreKeyPublic, 0),
+ Curve.decodePrivatePoint(bobSignedPreKeyPrivate));
+
+ ECPublicKey aliceBasePublicKey = Curve.decodePoint(aliceBasePublic, 0);
+ ECPublicKey aliceEphemeralPublicKey = Curve.decodePoint(aliceEphemeralPublic, 0);
+ IdentityKey aliceIdentityPublicKey = new IdentityKey(aliceIdentityPublic, 0);
+
+ SessionRecord session =
+ SessionRecord.initializeBobSession(
+ bobIdentityKey,
+ bobSignedPreKey,
+ bobEphemeralKey,
+ aliceIdentityPublicKey,
+ aliceBasePublicKey);
assertTrue(session.getLocalIdentityKey().equals(bobIdentityKey.getPublicKey()));
assertTrue(session.getRemoteIdentityKey().equals(aliceIdentityPublicKey));
assertTrue(Arrays.equals(session.getSenderChainKeyValue(), senderChain));
}
-public void testRatchetingSessionAsAlice() throws InvalidKeyException {
- byte[] bobPublic = {(byte) 0x05, (byte) 0x2c, (byte) 0xb4, (byte) 0x97, (byte) 0x76,
- (byte) 0xb8, (byte) 0x77, (byte) 0x02, (byte) 0x05, (byte) 0x74,
- (byte) 0x5a, (byte) 0x3a, (byte) 0x6e, (byte) 0x24, (byte) 0xf5,
- (byte) 0x79, (byte) 0xcd, (byte) 0xb4, (byte) 0xba, (byte) 0x7a,
- (byte) 0x89, (byte) 0x04, (byte) 0x10, (byte) 0x05, (byte) 0x92,
- (byte) 0x8e, (byte) 0xbb, (byte) 0xad, (byte) 0xc9, (byte) 0xc0,
- (byte) 0x5a, (byte) 0xd4, (byte) 0x58};
-
- byte[] bobIdentityPublic = {(byte) 0x05, (byte) 0xf1, (byte) 0xf4, (byte) 0x38, (byte) 0x74,
- (byte) 0xf6, (byte) 0x96, (byte) 0x69, (byte) 0x56, (byte) 0xc2,
- (byte) 0xdd, (byte) 0x47, (byte) 0x3f, (byte) 0x8f, (byte) 0xa1,
- (byte) 0x5a, (byte) 0xde, (byte) 0xb7, (byte) 0x1d, (byte) 0x1c,
- (byte) 0xb9, (byte) 0x91, (byte) 0xb2, (byte) 0x34, (byte) 0x16,
- (byte) 0x92, (byte) 0x32, (byte) 0x4c, (byte) 0xef, (byte) 0xb1,
- (byte) 0xc5, (byte) 0xe6, (byte) 0x26};
-
- byte[] bobSignedPreKeyPublic = {(byte)0x05, (byte)0xac, (byte)0x24, (byte)0x8a, (byte)0x8f,
- (byte)0x26, (byte)0x3b, (byte)0xe6, (byte)0x86, (byte)0x35,
- (byte)0x76, (byte)0xeb, (byte)0x03, (byte)0x62, (byte)0xe2,
- (byte)0x8c, (byte)0x82, (byte)0x8f, (byte)0x01, (byte)0x07,
- (byte)0xa3, (byte)0x37, (byte)0x9d, (byte)0x34, (byte)0xba,
- (byte)0xb1, (byte)0x58, (byte)0x6b, (byte)0xf8, (byte)0xc7,
- (byte)0x70, (byte)0xcd, (byte)0x67};
-
- byte[] aliceBasePublic = {(byte) 0x05, (byte) 0x47, (byte) 0x2d, (byte) 0x1f, (byte) 0xb1,
- (byte) 0xa9, (byte) 0x86, (byte) 0x2c, (byte) 0x3a, (byte) 0xf6,
- (byte) 0xbe, (byte) 0xac, (byte) 0xa8, (byte) 0x92, (byte) 0x02,
- (byte) 0x77, (byte) 0xe2, (byte) 0xb2, (byte) 0x6f, (byte) 0x4a,
- (byte) 0x79, (byte) 0x21, (byte) 0x3e, (byte) 0xc7, (byte) 0xc9,
- (byte) 0x06, (byte) 0xae, (byte) 0xb3, (byte) 0x5e, (byte) 0x03,
- (byte) 0xcf, (byte) 0x89, (byte) 0x50};
-
- byte[] aliceBasePrivate = {(byte) 0x11, (byte) 0xae, (byte) 0x7c, (byte) 0x64, (byte) 0xd1,
- (byte) 0xe6, (byte) 0x1c, (byte) 0xd5, (byte) 0x96, (byte) 0xb7,
- (byte) 0x6a, (byte) 0x0d, (byte) 0xb5, (byte) 0x01, (byte) 0x26,
- (byte) 0x73, (byte) 0x39, (byte) 0x1c, (byte) 0xae, (byte) 0x66,
- (byte) 0xed, (byte) 0xbf, (byte) 0xcf, (byte) 0x07, (byte) 0x3b,
- (byte) 0x4d, (byte) 0xa8, (byte) 0x05, (byte) 0x16, (byte) 0xa4,
- (byte) 0x74, (byte) 0x49};
-
- byte[] aliceEphemeralPublic = {(byte) 0x05, (byte) 0x6c, (byte) 0x3e, (byte) 0x0d, (byte) 0x1f,
- (byte) 0x52, (byte) 0x02, (byte) 0x83, (byte) 0xef, (byte) 0xcc,
- (byte) 0x55, (byte) 0xfc, (byte) 0xa5, (byte) 0xe6, (byte) 0x70,
- (byte) 0x75, (byte) 0xb9, (byte) 0x04, (byte) 0x00, (byte) 0x7f,
- (byte) 0x18, (byte) 0x81, (byte) 0xd1, (byte) 0x51, (byte) 0xaf,
- (byte) 0x76, (byte) 0xdf, (byte) 0x18, (byte) 0xc5, (byte) 0x1d,
- (byte) 0x29, (byte) 0xd3, (byte) 0x4b};
-
- byte[] aliceEphemeralPrivate = {(byte) 0xd1, (byte) 0xba, (byte) 0x38, (byte) 0xce, (byte) 0xa9,
- (byte) 0x17, (byte) 0x43, (byte) 0xd3, (byte) 0x39, (byte) 0x39,
- (byte) 0xc3, (byte) 0x3c, (byte) 0x84, (byte) 0x98, (byte) 0x65,
- (byte) 0x09, (byte) 0x28, (byte) 0x01, (byte) 0x61, (byte) 0xb8,
- (byte) 0xb6, (byte) 0x0f, (byte) 0xc7, (byte) 0x87, (byte) 0x0c,
- (byte) 0x59, (byte) 0x9c, (byte) 0x1d, (byte) 0x46, (byte) 0x20,
- (byte) 0x12, (byte) 0x48};
-
- byte[] aliceIdentityPublic = {(byte) 0x05, (byte) 0xb4, (byte) 0xa8, (byte) 0x45, (byte) 0x56,
- (byte) 0x60, (byte) 0xad, (byte) 0xa6, (byte) 0x5b, (byte) 0x40,
- (byte) 0x10, (byte) 0x07, (byte) 0xf6, (byte) 0x15, (byte) 0xe6,
- (byte) 0x54, (byte) 0x04, (byte) 0x17, (byte) 0x46, (byte) 0x43,
- (byte) 0x2e, (byte) 0x33, (byte) 0x39, (byte) 0xc6, (byte) 0x87,
- (byte) 0x51, (byte) 0x49, (byte) 0xbc, (byte) 0xee, (byte) 0xfc,
- (byte) 0xb4, (byte) 0x2b, (byte) 0x4a};
-
- byte[] aliceIdentityPrivate = {(byte) 0x90, (byte) 0x40, (byte) 0xf0, (byte) 0xd4, (byte) 0xe0,
- (byte) 0x9c, (byte) 0xf3, (byte) 0x8f, (byte) 0x6d, (byte) 0xc7,
- (byte) 0xc1, (byte) 0x37, (byte) 0x79, (byte) 0xc9, (byte) 0x08,
- (byte) 0xc0, (byte) 0x15, (byte) 0xa1, (byte) 0xda, (byte) 0x4f,
- (byte) 0xa7, (byte) 0x87, (byte) 0x37, (byte) 0xa0, (byte) 0x80,
- (byte) 0xeb, (byte) 0x0a, (byte) 0x6f, (byte) 0x4f, (byte) 0x5f,
- (byte) 0x8f, (byte) 0x58};
+ public void testRatchetingSessionAsAlice() throws InvalidKeyException {
+ byte[] bobPublic = {
+ (byte) 0x05, (byte) 0x2c, (byte) 0xb4, (byte) 0x97, (byte) 0x76,
+ (byte) 0xb8, (byte) 0x77, (byte) 0x02, (byte) 0x05, (byte) 0x74,
+ (byte) 0x5a, (byte) 0x3a, (byte) 0x6e, (byte) 0x24, (byte) 0xf5,
+ (byte) 0x79, (byte) 0xcd, (byte) 0xb4, (byte) 0xba, (byte) 0x7a,
+ (byte) 0x89, (byte) 0x04, (byte) 0x10, (byte) 0x05, (byte) 0x92,
+ (byte) 0x8e, (byte) 0xbb, (byte) 0xad, (byte) 0xc9, (byte) 0xc0,
+ (byte) 0x5a, (byte) 0xd4, (byte) 0x58
+ };
+
+ byte[] bobIdentityPublic = {
+ (byte) 0x05, (byte) 0xf1, (byte) 0xf4, (byte) 0x38, (byte) 0x74,
+ (byte) 0xf6, (byte) 0x96, (byte) 0x69, (byte) 0x56, (byte) 0xc2,
+ (byte) 0xdd, (byte) 0x47, (byte) 0x3f, (byte) 0x8f, (byte) 0xa1,
+ (byte) 0x5a, (byte) 0xde, (byte) 0xb7, (byte) 0x1d, (byte) 0x1c,
+ (byte) 0xb9, (byte) 0x91, (byte) 0xb2, (byte) 0x34, (byte) 0x16,
+ (byte) 0x92, (byte) 0x32, (byte) 0x4c, (byte) 0xef, (byte) 0xb1,
+ (byte) 0xc5, (byte) 0xe6, (byte) 0x26
+ };
+
+ byte[] bobSignedPreKeyPublic = {
+ (byte) 0x05, (byte) 0xac, (byte) 0x24, (byte) 0x8a, (byte) 0x8f,
+ (byte) 0x26, (byte) 0x3b, (byte) 0xe6, (byte) 0x86, (byte) 0x35,
+ (byte) 0x76, (byte) 0xeb, (byte) 0x03, (byte) 0x62, (byte) 0xe2,
+ (byte) 0x8c, (byte) 0x82, (byte) 0x8f, (byte) 0x01, (byte) 0x07,
+ (byte) 0xa3, (byte) 0x37, (byte) 0x9d, (byte) 0x34, (byte) 0xba,
+ (byte) 0xb1, (byte) 0x58, (byte) 0x6b, (byte) 0xf8, (byte) 0xc7,
+ (byte) 0x70, (byte) 0xcd, (byte) 0x67
+ };
+
+ byte[] aliceBasePublic = {
+ (byte) 0x05, (byte) 0x47, (byte) 0x2d, (byte) 0x1f, (byte) 0xb1,
+ (byte) 0xa9, (byte) 0x86, (byte) 0x2c, (byte) 0x3a, (byte) 0xf6,
+ (byte) 0xbe, (byte) 0xac, (byte) 0xa8, (byte) 0x92, (byte) 0x02,
+ (byte) 0x77, (byte) 0xe2, (byte) 0xb2, (byte) 0x6f, (byte) 0x4a,
+ (byte) 0x79, (byte) 0x21, (byte) 0x3e, (byte) 0xc7, (byte) 0xc9,
+ (byte) 0x06, (byte) 0xae, (byte) 0xb3, (byte) 0x5e, (byte) 0x03,
+ (byte) 0xcf, (byte) 0x89, (byte) 0x50
+ };
+
+ byte[] aliceBasePrivate = {
+ (byte) 0x11, (byte) 0xae, (byte) 0x7c, (byte) 0x64, (byte) 0xd1,
+ (byte) 0xe6, (byte) 0x1c, (byte) 0xd5, (byte) 0x96, (byte) 0xb7,
+ (byte) 0x6a, (byte) 0x0d, (byte) 0xb5, (byte) 0x01, (byte) 0x26,
+ (byte) 0x73, (byte) 0x39, (byte) 0x1c, (byte) 0xae, (byte) 0x66,
+ (byte) 0xed, (byte) 0xbf, (byte) 0xcf, (byte) 0x07, (byte) 0x3b,
+ (byte) 0x4d, (byte) 0xa8, (byte) 0x05, (byte) 0x16, (byte) 0xa4,
+ (byte) 0x74, (byte) 0x49
+ };
+
+ byte[] aliceEphemeralPublic = {
+ (byte) 0x05, (byte) 0x6c, (byte) 0x3e, (byte) 0x0d, (byte) 0x1f,
+ (byte) 0x52, (byte) 0x02, (byte) 0x83, (byte) 0xef, (byte) 0xcc,
+ (byte) 0x55, (byte) 0xfc, (byte) 0xa5, (byte) 0xe6, (byte) 0x70,
+ (byte) 0x75, (byte) 0xb9, (byte) 0x04, (byte) 0x00, (byte) 0x7f,
+ (byte) 0x18, (byte) 0x81, (byte) 0xd1, (byte) 0x51, (byte) 0xaf,
+ (byte) 0x76, (byte) 0xdf, (byte) 0x18, (byte) 0xc5, (byte) 0x1d,
+ (byte) 0x29, (byte) 0xd3, (byte) 0x4b
+ };
+
+ byte[] aliceEphemeralPrivate = {
+ (byte) 0xd1, (byte) 0xba, (byte) 0x38, (byte) 0xce, (byte) 0xa9,
+ (byte) 0x17, (byte) 0x43, (byte) 0xd3, (byte) 0x39, (byte) 0x39,
+ (byte) 0xc3, (byte) 0x3c, (byte) 0x84, (byte) 0x98, (byte) 0x65,
+ (byte) 0x09, (byte) 0x28, (byte) 0x01, (byte) 0x61, (byte) 0xb8,
+ (byte) 0xb6, (byte) 0x0f, (byte) 0xc7, (byte) 0x87, (byte) 0x0c,
+ (byte) 0x59, (byte) 0x9c, (byte) 0x1d, (byte) 0x46, (byte) 0x20,
+ (byte) 0x12, (byte) 0x48
+ };
+
+ byte[] aliceIdentityPublic = {
+ (byte) 0x05, (byte) 0xb4, (byte) 0xa8, (byte) 0x45, (byte) 0x56,
+ (byte) 0x60, (byte) 0xad, (byte) 0xa6, (byte) 0x5b, (byte) 0x40,
+ (byte) 0x10, (byte) 0x07, (byte) 0xf6, (byte) 0x15, (byte) 0xe6,
+ (byte) 0x54, (byte) 0x04, (byte) 0x17, (byte) 0x46, (byte) 0x43,
+ (byte) 0x2e, (byte) 0x33, (byte) 0x39, (byte) 0xc6, (byte) 0x87,
+ (byte) 0x51, (byte) 0x49, (byte) 0xbc, (byte) 0xee, (byte) 0xfc,
+ (byte) 0xb4, (byte) 0x2b, (byte) 0x4a
+ };
+
+ byte[] aliceIdentityPrivate = {
+ (byte) 0x90, (byte) 0x40, (byte) 0xf0, (byte) 0xd4, (byte) 0xe0,
+ (byte) 0x9c, (byte) 0xf3, (byte) 0x8f, (byte) 0x6d, (byte) 0xc7,
+ (byte) 0xc1, (byte) 0x37, (byte) 0x79, (byte) 0xc9, (byte) 0x08,
+ (byte) 0xc0, (byte) 0x15, (byte) 0xa1, (byte) 0xda, (byte) 0x4f,
+ (byte) 0xa7, (byte) 0x87, (byte) 0x37, (byte) 0xa0, (byte) 0x80,
+ (byte) 0xeb, (byte) 0x0a, (byte) 0x6f, (byte) 0x4f, (byte) 0x5f,
+ (byte) 0x8f, (byte) 0x58
+ };
/*
byte[] receiverChain = {(byte)0x97, (byte)0x97, (byte)0xca, (byte)0xca, (byte)0x53,
@@ -214,37 +261,37 @@ public void testRatchetingSessionAsAlice() throws InvalidKeyException {
(byte)0x8a, (byte)0x0a, (byte)0xed, (byte)0xa0, (byte)0x88,
(byte)0xb4, (byte)0x4d};
*/
- byte[] receiverChain = {(byte)0xab, (byte)0x9b, (byte)0xe5, (byte)0x0e, (byte)0x5c,
- (byte)0xb2, (byte)0x2a, (byte)0x92, (byte)0x54, (byte)0x46,
- (byte)0xab, (byte)0x90, (byte)0xee, (byte)0x56, (byte)0x70,
- (byte)0x54, (byte)0x5f, (byte)0x4f, (byte)0xd3, (byte)0x29,
- (byte)0x02, (byte)0x45, (byte)0x9e, (byte)0xc2, (byte)0x74,
- (byte)0xb6, (byte)0xad, (byte)0x0a, (byte)0xe5, (byte)0xd6,
- (byte)0x03, (byte)0x1a};
-
- IdentityKey bobIdentityKey = new IdentityKey(bobIdentityPublic, 0);
- ECPublicKey bobEphemeralPublicKey = Curve.decodePoint(bobPublic, 0);
- ECPublicKey bobSignedPreKey = Curve.decodePoint(bobSignedPreKeyPublic, 0);
- ECPublicKey aliceBasePublicKey = Curve.decodePoint(aliceBasePublic, 0);
- ECPrivateKey aliceBasePrivateKey = Curve.decodePrivatePoint(aliceBasePrivate);
- ECKeyPair aliceBaseKey = new ECKeyPair(aliceBasePublicKey, aliceBasePrivateKey);
- ECPublicKey aliceEphemeralPublicKey = Curve.decodePoint(aliceEphemeralPublic, 0);
- ECPrivateKey aliceEphemeralPrivateKey = Curve.decodePrivatePoint(aliceEphemeralPrivate);
- ECKeyPair aliceEphemeralKey = new ECKeyPair(aliceEphemeralPublicKey, aliceEphemeralPrivateKey);
- IdentityKey aliceIdentityPublicKey = new IdentityKey(aliceIdentityPublic, 0);
- ECPrivateKey aliceIdentityPrivateKey = Curve.decodePrivatePoint(aliceIdentityPrivate);
- IdentityKeyPair aliceIdentityKey = new IdentityKeyPair(aliceIdentityPublicKey, aliceIdentityPrivateKey);
-
- SessionRecord session = SessionRecord.initializeAliceSession(aliceIdentityKey,
- aliceBaseKey,
- bobIdentityKey,
- bobSignedPreKey,
- bobEphemeralPublicKey);
+ byte[] receiverChain = {
+ (byte) 0xab, (byte) 0x9b, (byte) 0xe5, (byte) 0x0e, (byte) 0x5c,
+ (byte) 0xb2, (byte) 0x2a, (byte) 0x92, (byte) 0x54, (byte) 0x46,
+ (byte) 0xab, (byte) 0x90, (byte) 0xee, (byte) 0x56, (byte) 0x70,
+ (byte) 0x54, (byte) 0x5f, (byte) 0x4f, (byte) 0xd3, (byte) 0x29,
+ (byte) 0x02, (byte) 0x45, (byte) 0x9e, (byte) 0xc2, (byte) 0x74,
+ (byte) 0xb6, (byte) 0xad, (byte) 0x0a, (byte) 0xe5, (byte) 0xd6,
+ (byte) 0x03, (byte) 0x1a
+ };
+
+ IdentityKey bobIdentityKey = new IdentityKey(bobIdentityPublic, 0);
+ ECPublicKey bobEphemeralPublicKey = Curve.decodePoint(bobPublic, 0);
+ ECPublicKey bobSignedPreKey = Curve.decodePoint(bobSignedPreKeyPublic, 0);
+ ECPublicKey aliceBasePublicKey = Curve.decodePoint(aliceBasePublic, 0);
+ ECPrivateKey aliceBasePrivateKey = Curve.decodePrivatePoint(aliceBasePrivate);
+ ECKeyPair aliceBaseKey = new ECKeyPair(aliceBasePublicKey, aliceBasePrivateKey);
+ ECPublicKey aliceEphemeralPublicKey = Curve.decodePoint(aliceEphemeralPublic, 0);
+ ECPrivateKey aliceEphemeralPrivateKey = Curve.decodePrivatePoint(aliceEphemeralPrivate);
+ ECKeyPair aliceEphemeralKey = new ECKeyPair(aliceEphemeralPublicKey, aliceEphemeralPrivateKey);
+ IdentityKey aliceIdentityPublicKey = new IdentityKey(aliceIdentityPublic, 0);
+ ECPrivateKey aliceIdentityPrivateKey = Curve.decodePrivatePoint(aliceIdentityPrivate);
+ IdentityKeyPair aliceIdentityKey =
+ new IdentityKeyPair(aliceIdentityPublicKey, aliceIdentityPrivateKey);
+
+ SessionRecord session =
+ SessionRecord.initializeAliceSession(
+ aliceIdentityKey, aliceBaseKey, bobIdentityKey, bobSignedPreKey, bobEphemeralPublicKey);
assertTrue(session.getLocalIdentityKey().equals(aliceIdentityKey.getPublicKey()));
assertTrue(session.getRemoteIdentityKey().equals(bobIdentityKey));
- assertTrue(Arrays.equals(session.getReceiverChainKeyValue(bobEphemeralPublicKey),
- receiverChain));
-
+ assertTrue(
+ Arrays.equals(session.getReceiverChainKeyValue(bobEphemeralPublicKey), receiverChain));
}
}
diff --git a/java/client/src/test/java/org/signal/libsignal/sgxsession/SgxClientTest.java b/java/client/src/test/java/org/signal/libsignal/sgxsession/SgxClientTest.java
index d86ee5920d..dad11cb08a 100644
--- a/java/client/src/test/java/org/signal/libsignal/sgxsession/SgxClientTest.java
+++ b/java/client/src/test/java/org/signal/libsignal/sgxsession/SgxClientTest.java
@@ -5,6 +5,11 @@
package org.signal.libsignal.sgxsession;
+import static org.junit.Assert.assertEquals;
+
+import java.time.Instant;
+import java.util.Arrays;
+import java.util.Collection;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
@@ -15,98 +20,102 @@
import org.signal.libsignal.svr2.Svr2Client;
import org.signal.libsignal.util.ResourceReader;
-import java.time.Instant;
-import java.util.Arrays;
-import java.util.Collection;
-
-import static org.junit.Assert.assertEquals;
-
@RunWith(Parameterized.class)
public class SgxClientTest {
- static enum ServiceType {
- SVR2,
- CDS2
- }
-
- private byte[] mrenclave;
- private byte[] attestationMsg;
- private Instant validInstant;
- private ServiceType serviceType;
-
- public SgxClientTest(byte[] mrenclave, byte[] attestationMsg, Instant earliestValidInstant, ServiceType serviceType) {
- this.mrenclave = mrenclave;
- this.attestationMsg = attestationMsg;
- this.validInstant = earliestValidInstant;
- this.serviceType = serviceType;
- }
-
- @Parameters(name = "{3}")
- public static Collection data() throws Exception {
- byte[] cds2Handshake = ResourceReader.readAll(SgxClientTest.class.getResourceAsStream("cds2handshakestart.data"));
- byte[] svr2Handshake = ResourceReader.readAll(SgxClientTest.class.getResourceAsStream("svr2handshakestart.data"));
- return Arrays.asList(new Object[][] {
- {
- Hex.fromStringCondensed("39d78f17f8aa9a8e9cdaf16595947a057bac21f014d1abfd6a99b2dfd4e18d1d"),
- cds2Handshake,
- Instant.ofEpochMilli(1655857680000L),
- ServiceType.CDS2
- },
- {
- Hex.fromStringCondensed("a8a261420a6bb9b61aa25bf8a79e8bd20d7652531feb3381cbffd446d270be95"),
- svr2Handshake,
- Instant.ofEpochSecond(1683836600),
- ServiceType.SVR2
- }
+ static enum ServiceType {
+ SVR2,
+ CDS2
+ }
+
+ private byte[] mrenclave;
+ private byte[] attestationMsg;
+ private Instant validInstant;
+ private ServiceType serviceType;
+
+ public SgxClientTest(
+ byte[] mrenclave,
+ byte[] attestationMsg,
+ Instant earliestValidInstant,
+ ServiceType serviceType) {
+ this.mrenclave = mrenclave;
+ this.attestationMsg = attestationMsg;
+ this.validInstant = earliestValidInstant;
+ this.serviceType = serviceType;
+ }
+
+ @Parameters(name = "{3}")
+ public static Collection data() throws Exception {
+ byte[] cds2Handshake =
+ ResourceReader.readAll(SgxClientTest.class.getResourceAsStream("cds2handshakestart.data"));
+ byte[] svr2Handshake =
+ ResourceReader.readAll(SgxClientTest.class.getResourceAsStream("svr2handshakestart.data"));
+ return Arrays.asList(
+ new Object[][] {
+ {
+ Hex.fromStringCondensed(
+ "39d78f17f8aa9a8e9cdaf16595947a057bac21f014d1abfd6a99b2dfd4e18d1d"),
+ cds2Handshake,
+ Instant.ofEpochMilli(1655857680000L),
+ ServiceType.CDS2
+ },
+ {
+ Hex.fromStringCondensed(
+ "a8a261420a6bb9b61aa25bf8a79e8bd20d7652531feb3381cbffd446d270be95"),
+ svr2Handshake,
+ Instant.ofEpochSecond(1683836600),
+ ServiceType.SVR2
+ }
});
+ }
+
+ private SgxClient getClient(byte[] mrenclave, byte[] attestationMsg, Instant currentTime)
+ throws AttestationDataException {
+ switch (serviceType) {
+ case SVR2:
+ return new Svr2Client(mrenclave, attestationMsg, currentTime);
+ case CDS2:
+ return new Cds2Client(mrenclave, attestationMsg, currentTime);
}
-
-
- private SgxClient getClient(byte[] mrenclave, byte[] attestationMsg, Instant currentTime) throws AttestationDataException {
- switch (serviceType) {
- case SVR2:
- return new Svr2Client(mrenclave, attestationMsg, currentTime);
- case CDS2:
- return new Cds2Client(mrenclave, attestationMsg, currentTime);
- }
- throw new IllegalStateException();
- }
-
- @Test
- public void testCreateClient() throws AttestationDataException {
- SgxClient client = getClient(mrenclave, attestationMsg, validInstant);
- byte[] initialMessage = client.initialRequest();
- assertEquals(48, initialMessage.length);
- }
-
-
- @Test(expected = AttestationDataException.class)
- public void testCreateClientFailsWithInvalidMrenclave() throws AttestationDataException {
- byte[] invalidMrenclave = new byte[]{};
- getClient(invalidMrenclave, attestationMsg, validInstant);
- }
-
- @Test(expected = AttestationDataException.class)
- public void testCreateClientFailsWithInvalidMessage() throws AttestationDataException {
- byte[] invalidMessage = new byte[0];
- getClient(mrenclave, invalidMessage, validInstant);
- }
-
- @Test(expected = AttestationDataException.class)
- public void testCreateClientFailsWithInvalidNonEmptyMessage() throws AttestationDataException {
- byte[] invalidMessage = new byte[]{ 1 };
- getClient(mrenclave, invalidMessage, validInstant);
- }
-
- @Test(expected = IllegalStateException.class)
- public void testEstablishedSendFailsPriorToEstablishment() throws AttestationDataException, SgxCommunicationFailureException {
- SgxClient client = getClient(mrenclave, attestationMsg, validInstant);
- client.establishedSend(new byte[]{1, 2, 3});
- }
-
- @Test(expected = IllegalStateException.class)
- public void testEstablishedRecvFailsPriorToEstablishment() throws AttestationDataException, SgxCommunicationFailureException {
- SgxClient client = getClient(mrenclave, attestationMsg, validInstant);
- client.establishedRecv(new byte[]{1, 2, 3});
- }
+ throw new IllegalStateException();
+ }
+
+ @Test
+ public void testCreateClient() throws AttestationDataException {
+ SgxClient client = getClient(mrenclave, attestationMsg, validInstant);
+ byte[] initialMessage = client.initialRequest();
+ assertEquals(48, initialMessage.length);
+ }
+
+ @Test(expected = AttestationDataException.class)
+ public void testCreateClientFailsWithInvalidMrenclave() throws AttestationDataException {
+ byte[] invalidMrenclave = new byte[] {};
+ getClient(invalidMrenclave, attestationMsg, validInstant);
+ }
+
+ @Test(expected = AttestationDataException.class)
+ public void testCreateClientFailsWithInvalidMessage() throws AttestationDataException {
+ byte[] invalidMessage = new byte[0];
+ getClient(mrenclave, invalidMessage, validInstant);
+ }
+
+ @Test(expected = AttestationDataException.class)
+ public void testCreateClientFailsWithInvalidNonEmptyMessage() throws AttestationDataException {
+ byte[] invalidMessage = new byte[] {1};
+ getClient(mrenclave, invalidMessage, validInstant);
+ }
+
+ @Test(expected = IllegalStateException.class)
+ public void testEstablishedSendFailsPriorToEstablishment()
+ throws AttestationDataException, SgxCommunicationFailureException {
+ SgxClient client = getClient(mrenclave, attestationMsg, validInstant);
+ client.establishedSend(new byte[] {1, 2, 3});
+ }
+
+ @Test(expected = IllegalStateException.class)
+ public void testEstablishedRecvFailsPriorToEstablishment()
+ throws AttestationDataException, SgxCommunicationFailureException {
+ SgxClient client = getClient(mrenclave, attestationMsg, validInstant);
+ client.establishedRecv(new byte[] {1, 2, 3});
+ }
}
diff --git a/java/client/src/test/java/org/signal/libsignal/svr2/PinTest.java b/java/client/src/test/java/org/signal/libsignal/svr2/PinTest.java
index dde92ac729..e535aca67a 100644
--- a/java/client/src/test/java/org/signal/libsignal/svr2/PinTest.java
+++ b/java/client/src/test/java/org/signal/libsignal/svr2/PinTest.java
@@ -2,95 +2,102 @@
// Copyright 2023 Signal Messenger, LLC.
// SPDX-License-Identifier: AGPL-3.0-only
//
+
package org.signal.libsignal.svr2;
-import org.junit.Test;
-import org.signal.libsignal.attest.AttestationDataException;
-import org.signal.libsignal.protocol.kdf.HKDF;
-import org.signal.libsignal.protocol.util.Hex;
+import static org.junit.Assert.*;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.charset.StandardCharsets;
-
-import static org.junit.Assert.*;
+import org.junit.Test;
+import org.signal.libsignal.attest.AttestationDataException;
+import org.signal.libsignal.protocol.kdf.HKDF;
+import org.signal.libsignal.protocol.util.Hex;
public class PinTest {
- @Test(expected = IllegalArgumentException.class)
- public void badSaltLength() {
- PinHash.svr1("password".getBytes(StandardCharsets.UTF_8), new byte[]{(byte) 0xFF});
- }
-
- @Test(expected = IllegalArgumentException.class)
- public void badEncodedHash() {
- Pin.verifyLocalHash("not-a-hash", "password".getBytes(StandardCharsets.UTF_8));
- }
-
- @Test
- public void verify() {
- byte[] pin = "password".getBytes(StandardCharsets.UTF_8);
- String pwhash = Pin.localHash(pin);
- assertTrue(Pin.verifyLocalHash(pwhash, pin));
- assertFalse(Pin.verifyLocalHash(pwhash, "badpassword".getBytes(StandardCharsets.UTF_8)));
- }
-
- @Test
- public void known() throws IOException {
- final byte[] salt = Hex.fromStringCondensed("000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f");
- final byte[] pin = "password".getBytes(StandardCharsets.UTF_8);
-
- final PinHash pinHash = PinHash.svr1(pin, salt);
- assertArrayEquals(
- pinHash.accessKey(),
- Hex.fromStringCondensed("ab7e8499d21f80a6600b3b9ee349ac6d72c07e3359fe885a934ba7aa844429f8"));
-
- assertArrayEquals(
- pinHash.encryptionKey(),
- Hex.fromStringCondensed("44652df80490fc66bb864a9e638b2f7dc9e20649671dd66bbb9c37bee2bfecf1")
- );
- }
-
- @Test
- public void known2() throws IOException {
- final byte[] salt = Hex.fromStringCondensed("202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f");
- final byte[] pin = "anotherpassword".getBytes(StandardCharsets.UTF_8);
-
- final PinHash pinHash = PinHash.svr1(pin, salt);
- assertArrayEquals(
- pinHash.accessKey(),
- Hex.fromStringCondensed("301d9dd1e96f20ce51083f67d3298fd37b97525de8324d5e12ed2d407d3d927b"));
-
- assertArrayEquals(
- pinHash.encryptionKey(),
- Hex.fromStringCondensed("b6f16aa0591732e339b7e99cdd5fd6586a1c285c9d66876947fd82f66ed99757")
- );
- }
-
- private static byte[] bebytes(final long l) {
- final ByteBuffer bb = ByteBuffer.allocate(8);
- bb.order(ByteOrder.BIG_ENDIAN);
- bb.putLong(l);
- return bb.array();
- }
-
- @Test
- public void testSaltWithGroupId() throws IOException, AttestationDataException {
- final byte[] mrenclave = Hex.fromStringCondensed("a8a261420a6bb9b61aa25bf8a79e8bd20d7652531feb3381cbffd446d270be95");
- final byte[] pin = "password".getBytes(StandardCharsets.UTF_8);
- final String username = "username";
- final long groupId = Long.parseUnsignedLong("15525669046665930652");
- final PinHash actual = PinHash.svr2(pin, username, mrenclave);
-
- // svr2 hash should use salt derrived froup groupId
- final byte[] expectedSalt = HKDF.deriveSecrets(username.getBytes(StandardCharsets.UTF_8), bebytes(groupId), new byte[]{}, 32);
- final byte[] knownSalt = Hex.fromStringCondensed("260d1f6d233c9326e8ba744e778b7b127147c7211d9bc3219ab3b7394766c508");
- assertArrayEquals(knownSalt, expectedSalt);
-
- final PinHash expected = PinHash.svr1(pin, expectedSalt);
- assertArrayEquals(actual.accessKey(), expected.accessKey());
- assertArrayEquals(actual.encryptionKey(), expected.encryptionKey());
-
- }
+ @Test(expected = IllegalArgumentException.class)
+ public void badSaltLength() {
+ PinHash.svr1("password".getBytes(StandardCharsets.UTF_8), new byte[] {(byte) 0xFF});
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void badEncodedHash() {
+ Pin.verifyLocalHash("not-a-hash", "password".getBytes(StandardCharsets.UTF_8));
+ }
+
+ @Test
+ public void verify() {
+ byte[] pin = "password".getBytes(StandardCharsets.UTF_8);
+ String pwhash = Pin.localHash(pin);
+ assertTrue(Pin.verifyLocalHash(pwhash, pin));
+ assertFalse(Pin.verifyLocalHash(pwhash, "badpassword".getBytes(StandardCharsets.UTF_8)));
+ }
+
+ @Test
+ public void known() throws IOException {
+ final byte[] salt =
+ Hex.fromStringCondensed("000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f");
+ final byte[] pin = "password".getBytes(StandardCharsets.UTF_8);
+
+ final PinHash pinHash = PinHash.svr1(pin, salt);
+ assertArrayEquals(
+ pinHash.accessKey(),
+ Hex.fromStringCondensed(
+ "ab7e8499d21f80a6600b3b9ee349ac6d72c07e3359fe885a934ba7aa844429f8"));
+
+ assertArrayEquals(
+ pinHash.encryptionKey(),
+ Hex.fromStringCondensed(
+ "44652df80490fc66bb864a9e638b2f7dc9e20649671dd66bbb9c37bee2bfecf1"));
+ }
+
+ @Test
+ public void known2() throws IOException {
+ final byte[] salt =
+ Hex.fromStringCondensed("202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f");
+ final byte[] pin = "anotherpassword".getBytes(StandardCharsets.UTF_8);
+
+ final PinHash pinHash = PinHash.svr1(pin, salt);
+ assertArrayEquals(
+ pinHash.accessKey(),
+ Hex.fromStringCondensed(
+ "301d9dd1e96f20ce51083f67d3298fd37b97525de8324d5e12ed2d407d3d927b"));
+
+ assertArrayEquals(
+ pinHash.encryptionKey(),
+ Hex.fromStringCondensed(
+ "b6f16aa0591732e339b7e99cdd5fd6586a1c285c9d66876947fd82f66ed99757"));
+ }
+
+ private static byte[] bebytes(final long l) {
+ final ByteBuffer bb = ByteBuffer.allocate(8);
+ bb.order(ByteOrder.BIG_ENDIAN);
+ bb.putLong(l);
+ return bb.array();
+ }
+
+ @Test
+ public void testSaltWithGroupId() throws IOException, AttestationDataException {
+ final byte[] mrenclave =
+ Hex.fromStringCondensed("a8a261420a6bb9b61aa25bf8a79e8bd20d7652531feb3381cbffd446d270be95");
+ final byte[] pin = "password".getBytes(StandardCharsets.UTF_8);
+ final String username = "username";
+ final long groupId = Long.parseUnsignedLong("15525669046665930652");
+ final PinHash actual = PinHash.svr2(pin, username, mrenclave);
+
+ // svr2 hash should use salt derrived froup groupId
+ final byte[] expectedSalt =
+ HKDF.deriveSecrets(
+ username.getBytes(StandardCharsets.UTF_8), bebytes(groupId), new byte[] {}, 32);
+ final byte[] knownSalt =
+ Hex.fromStringCondensed("260d1f6d233c9326e8ba744e778b7b127147c7211d9bc3219ab3b7394766c508");
+ assertArrayEquals(knownSalt, expectedSalt);
+
+ final PinHash expected = PinHash.svr1(pin, expectedSalt);
+ assertArrayEquals(actual.accessKey(), expected.accessKey());
+ assertArrayEquals(actual.encryptionKey(), expected.encryptionKey());
+ }
}
diff --git a/java/client/src/test/java/org/signal/libsignal/usernames/UsernamesTest.java b/java/client/src/test/java/org/signal/libsignal/usernames/UsernamesTest.java
index 9fa680b291..bb952a07d7 100644
--- a/java/client/src/test/java/org/signal/libsignal/usernames/UsernamesTest.java
+++ b/java/client/src/test/java/org/signal/libsignal/usernames/UsernamesTest.java
@@ -5,136 +5,142 @@
package org.signal.libsignal.usernames;
+import java.security.SecureRandom;
+import java.util.List;
import java.util.stream.Collectors;
-import java.util.stream.IntStream;
import java.util.stream.Stream;
import junit.framework.TestCase;
import org.signal.libsignal.protocol.util.Hex;
-import java.security.SecureRandom;
-import java.util.List;
-
public class UsernamesTest extends TestCase {
- public void testUsernameGeneration() throws BaseUsernameException {
- String nickname = "SiGNAl";
- List usernames = Username.candidatesFrom(nickname, 3, 32);
- assertFalse("Non-zero number of usernames expected", usernames.size() == 0);
- for (Username name : usernames) {
- assertTrue(String.format("%s does not start with %s", name, nickname), name.getUsername().startsWith(nickname));
- }
- }
-
- public void testInvalidNicknameValidation() throws BaseUsernameException {
- List invalidNicknames = List.of("hi", "way_too_long_to_be_a_reasonable_nickname", "I⍰Unicode", "s p a c e s", "0zerostart");
- for (String nickname : invalidNicknames) {
- try {
- Username.candidatesFrom(nickname, 3, 32);
- fail(String.format("'%s' should not be considered valid", nickname));
- } catch (BaseUsernameException ex) {
- // this is fine
- }
-
- }
- }
-
- public void testValidUsernameHashing() throws BaseUsernameException {
- String username = "he110.42";
- byte[] hash = new Username(username).getHash();
- assertEquals(32, hash.length);
- assertEquals("f63f0521eb3adfe1d936f4b626b89558483507fbdb838fc554af059111cf322e", Hex.toStringCondensed(hash));
+ public void testUsernameGeneration() throws BaseUsernameException {
+ String nickname = "SiGNAl";
+ List usernames = Username.candidatesFrom(nickname, 3, 32);
+ assertFalse("Non-zero number of usernames expected", usernames.size() == 0);
+ for (Username name : usernames) {
+ assertTrue(
+ String.format("%s does not start with %s", name, nickname),
+ name.getUsername().startsWith(nickname));
}
-
- public void testToTheProofAndBack() throws BaseUsernameException {
- Username username = new Username("hello_signal.42");
- assertNotNull(username.getHash());
- byte[] proof = username.generateProof();
- assertNotNull(proof);
- assertEquals(128, proof.length);
- Username.verifyProof(proof, username.getHash());
+ }
+
+ public void testInvalidNicknameValidation() throws BaseUsernameException {
+ List invalidNicknames =
+ List.of(
+ "hi",
+ "way_too_long_to_be_a_reasonable_nickname",
+ "I⍰Unicode",
+ "s p a c e s",
+ "0zerostart");
+ for (String nickname : invalidNicknames) {
+ try {
+ Username.candidatesFrom(nickname, 3, 32);
+ fail(String.format("'%s' should not be considered valid", nickname));
+ } catch (BaseUsernameException ex) {
+ // this is fine
+ }
}
-
- public void testInvalidHash() throws BaseUsernameException {
- Username username = new Username("hello_signal.42");
- byte[] proof = username.generateProof();
-
- SecureRandom r = new SecureRandom();
- byte[] badHash = new byte[32];
- r.nextBytes(badHash);
-
- try {
- Username.verifyProof(proof, badHash);
- } catch (BaseUsernameException ex) {
- assertTrue(ex.getMessage().contains("Username could not be verified"));
- }
+ }
+
+ public void testValidUsernameHashing() throws BaseUsernameException {
+ String username = "he110.42";
+ byte[] hash = new Username(username).getHash();
+ assertEquals(32, hash.length);
+ assertEquals(
+ "f63f0521eb3adfe1d936f4b626b89558483507fbdb838fc554af059111cf322e",
+ Hex.toStringCondensed(hash));
+ }
+
+ public void testToTheProofAndBack() throws BaseUsernameException {
+ Username username = new Username("hello_signal.42");
+ assertNotNull(username.getHash());
+ byte[] proof = username.generateProof();
+ assertNotNull(proof);
+ assertEquals(128, proof.length);
+ Username.verifyProof(proof, username.getHash());
+ }
+
+ public void testInvalidHash() throws BaseUsernameException {
+ Username username = new Username("hello_signal.42");
+ byte[] proof = username.generateProof();
+
+ SecureRandom r = new SecureRandom();
+ byte[] badHash = new byte[32];
+ r.nextBytes(badHash);
+
+ try {
+ Username.verifyProof(proof, badHash);
+ } catch (BaseUsernameException ex) {
+ assertTrue(ex.getMessage().contains("Username could not be verified"));
}
+ }
- public void testInvalidRandomness() throws BaseUsernameException {
- try {
- new Username("valid_name.01").generateProofWithRandomness(new byte[31]);
- } catch (Error err) {
- assertTrue(err.getMessage().contains("Failed to create proof"));
- }
+ public void testInvalidRandomness() throws BaseUsernameException {
+ try {
+ new Username("valid_name.01").generateProofWithRandomness(new byte[31]);
+ } catch (Error err) {
+ assertTrue(err.getMessage().contains("Failed to create proof"));
}
-
- public void testInvalidUsernames() throws BaseUsernameException {
- List usernames = List.of("0zerostart.01", "zero.00", "short_zero.0", "short_one.1");
- for (String name : usernames) {
- try {
- new Username(name);
- fail(String.format("'%s' should not be valid", name));
- } catch (BaseUsernameException ex) {
- // this is fine
- }
- }
- for (String name : usernames) {
- try {
- new Username(name).generateProof();
- fail(String.format("'%s' should not be valid", name));
- } catch (BaseUsernameException ex) {
- // this is fine
- }
- }
+ }
+
+ public void testInvalidUsernames() throws BaseUsernameException {
+ List usernames = List.of("0zerostart.01", "zero.00", "short_zero.0", "short_one.1");
+ for (String name : usernames) {
+ try {
+ new Username(name);
+ fail(String.format("'%s' should not be valid", name));
+ } catch (BaseUsernameException ex) {
+ // this is fine
+ }
}
-
- public void testUsernameLinkHappyCase() throws BaseUsernameException {
- final Username expectedUsername = new Username("hello_signal.42");
- final Username.UsernameLink link = expectedUsername.generateLink();
- final Username actualUsername = Username.fromLink(link);
- assertEquals(expectedUsername.getUsername(), actualUsername.getUsername());
+ for (String name : usernames) {
+ try {
+ new Username(name).generateProof();
+ fail(String.format("'%s' should not be valid", name));
+ } catch (BaseUsernameException ex) {
+ // this is fine
+ }
}
-
- public void testCreateLinkFailsForLongUsername() throws BaseUsernameException {
- final String longUsername = Stream.generate(() -> "a")
- .limit(128)
- .collect(Collectors.joining());
- try {
- new Username(longUsername).generateLink();
- fail("Expected to fail creating a link for a long username");
- } catch (BaseUsernameException ex) {
- // this is fine
- }
+ }
+
+ public void testUsernameLinkHappyCase() throws BaseUsernameException {
+ final Username expectedUsername = new Username("hello_signal.42");
+ final Username.UsernameLink link = expectedUsername.generateLink();
+ final Username actualUsername = Username.fromLink(link);
+ assertEquals(expectedUsername.getUsername(), actualUsername.getUsername());
+ }
+
+ public void testCreateLinkFailsForLongUsername() throws BaseUsernameException {
+ final String longUsername = Stream.generate(() -> "a").limit(128).collect(Collectors.joining());
+ try {
+ new Username(longUsername).generateLink();
+ fail("Expected to fail creating a link for a long username");
+ } catch (BaseUsernameException ex) {
+ // this is fine
}
-
- public void testDecryptUsernameFromLinkFailsForInvalidEntropySize() throws BaseUsernameException {
- final byte[] entropy = new byte[16];
- final byte[] encryptedUsername = new byte[32];
- try {
- Username.fromLink(new Username.UsernameLink(entropy, encryptedUsername));
- fail("Expected to fail decrypting username link with an invalid entropy size");
- } catch (BaseUsernameException ex) {
- // this is fine
- }
+ }
+
+ public void testDecryptUsernameFromLinkFailsForInvalidEntropySize() throws BaseUsernameException {
+ final byte[] entropy = new byte[16];
+ final byte[] encryptedUsername = new byte[32];
+ try {
+ Username.fromLink(new Username.UsernameLink(entropy, encryptedUsername));
+ fail("Expected to fail decrypting username link with an invalid entropy size");
+ } catch (BaseUsernameException ex) {
+ // this is fine
}
-
- public void testDecryptUsernameFromLinkFailsForInvalidEncryptedUsername() throws BaseUsernameException {
- final byte[] entropy = new byte[32];
- final byte[] encryptedUsername = new byte[32];
- try {
- Username.fromLink(new Username.UsernameLink(entropy, encryptedUsername));
- fail("Expected to fail decrypting username link with an invalid link data");
- } catch (BaseUsernameException ex) {
- // this is fine
- }
+ }
+
+ public void testDecryptUsernameFromLinkFailsForInvalidEncryptedUsername()
+ throws BaseUsernameException {
+ final byte[] entropy = new byte[32];
+ final byte[] encryptedUsername = new byte[32];
+ try {
+ Username.fromLink(new Username.UsernameLink(entropy, encryptedUsername));
+ fail("Expected to fail decrypting username link with an invalid link data");
+ } catch (BaseUsernameException ex) {
+ // this is fine
}
+ }
}
diff --git a/java/client/src/test/java/org/signal/libsignal/util/ResourceReader.java b/java/client/src/test/java/org/signal/libsignal/util/ResourceReader.java
index dc244a32b8..dbc180f332 100644
--- a/java/client/src/test/java/org/signal/libsignal/util/ResourceReader.java
+++ b/java/client/src/test/java/org/signal/libsignal/util/ResourceReader.java
@@ -2,6 +2,7 @@
// Copyright 2023 Signal Messenger, LLC.
// SPDX-License-Identifier: AGPL-3.0-only
//
+
package org.signal.libsignal.util;
import java.io.ByteArrayOutputStream;
@@ -9,17 +10,17 @@
import java.io.InputStream;
public class ResourceReader {
- public static byte[] readAll(final InputStream inputStream) throws IOException {
- try {
- final ByteArrayOutputStream baos = new ByteArrayOutputStream();
- final byte[] chunk = new byte[4096];
- int read;
- while ((read = inputStream.read(chunk, 0, chunk.length)) != -1) {
- baos.write(chunk, 0, read);
- }
- return baos.toByteArray();
- } finally {
- inputStream.close();
- }
+ public static byte[] readAll(final InputStream inputStream) throws IOException {
+ try {
+ final ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ final byte[] chunk = new byte[4096];
+ int read;
+ while ((read = inputStream.read(chunk, 0, chunk.length)) != -1) {
+ baos.write(chunk, 0, read);
+ }
+ return baos.toByteArray();
+ } finally {
+ inputStream.close();
}
+ }
}
diff --git a/java/client/src/test/java/org/signal/libsignal/zkgroup/NativeErrorsTest.java b/java/client/src/test/java/org/signal/libsignal/zkgroup/NativeErrorsTest.java
index 59ce733ce6..d35afe27cc 100644
--- a/java/client/src/test/java/org/signal/libsignal/zkgroup/NativeErrorsTest.java
+++ b/java/client/src/test/java/org/signal/libsignal/zkgroup/NativeErrorsTest.java
@@ -5,10 +5,9 @@
package org.signal.libsignal.zkgroup;
-import org.junit.Test;
import junit.framework.TestCase;
+import org.junit.Test;
import org.signal.libsignal.internal.Native;
-import org.signal.libsignal.protocol.util.Hex;
import org.signal.libsignal.zkgroup.internal.*;
public final class NativeErrorsTest extends TestCase {
@@ -19,18 +18,20 @@ public void testBadNativeCalls() {
byte[] uuidCiphertext = new byte[65]; // valid size
boolean failed = false;
try {
- Native.GroupSecretParams_DecryptServiceId(params, uuidCiphertext);
- failed = true;
- } catch (AssertionError e) {}
+ Native.GroupSecretParams_DecryptServiceId(params, uuidCiphertext);
+ failed = true;
+ } catch (AssertionError e) {
+ }
if (failed) {
- throw new AssertionError("Deserialization failure should Assert if CheckValidContents should have caught this");
+ throw new AssertionError(
+ "Deserialization failure should Assert if CheckValidContents should have caught this");
}
byte[] temp = new byte[1]; // wrong length
try {
- Native.ServerSecretParams_GenerateDeterministic(temp);
- throw new AssertionError("Failed to catch wrong byte array length");
- } catch (IllegalArgumentException e) {}
+ Native.ServerSecretParams_GenerateDeterministic(temp);
+ throw new AssertionError("Failed to catch wrong byte array length");
+ } catch (IllegalArgumentException e) {
+ }
}
-
}
diff --git a/java/client/src/test/java/org/signal/libsignal/zkgroup/RandomnessTest.java b/java/client/src/test/java/org/signal/libsignal/zkgroup/RandomnessTest.java
index d001fb54c2..43e53ebbf5 100644
--- a/java/client/src/test/java/org/signal/libsignal/zkgroup/RandomnessTest.java
+++ b/java/client/src/test/java/org/signal/libsignal/zkgroup/RandomnessTest.java
@@ -5,22 +5,22 @@
package org.signal.libsignal.zkgroup;
-import org.junit.Test;
-import org.signal.libsignal.zkgroup.internal.*;
-import org.signal.libsignal.protocol.util.Hex;
+import static org.junit.Assert.assertArrayEquals;
import java.io.IOException;
import java.security.SecureRandom;
-
-import static org.junit.Assert.assertArrayEquals;
+import org.junit.Test;
+import org.signal.libsignal.protocol.util.Hex;
+import org.signal.libsignal.zkgroup.internal.*;
public final class RandomnessTest extends SecureRandomTest {
@Test
public void generate_usesSecureRandom() throws IOException {
- byte[] array = Hex.fromStringCondensed("e18de7dfe7195f0b9320e309cd3ed3765dcf54a09be57813ee69f5ea35867689");
+ byte[] array =
+ Hex.fromStringCondensed("e18de7dfe7195f0b9320e309cd3ed3765dcf54a09be57813ee69f5ea35867689");
SecureRandom secureRandom = createSecureRandom(array);
- byte[] random = new byte[array.length];
+ byte[] random = new byte[array.length];
secureRandom.nextBytes(random);
assertArrayEquals(array, random);
@@ -28,7 +28,8 @@ public void generate_usesSecureRandom() throws IOException {
@Test
public void generate_usesSecureRandom_alternativeValues() throws IOException {
- byte[] array = Hex.fromStringCondensed("ba8a89a05eaf51cac3ce35256199b38a18e0e1fa16f1443db8e34b0489739b80");
+ byte[] array =
+ Hex.fromStringCondensed("ba8a89a05eaf51cac3ce35256199b38a18e0e1fa16f1443db8e34b0489739b80");
SecureRandom secureRandom = createSecureRandom(array);
byte[] random = new byte[array.length];
diff --git a/java/client/src/test/java/org/signal/libsignal/zkgroup/SecureRandomTest.java b/java/client/src/test/java/org/signal/libsignal/zkgroup/SecureRandomTest.java
index 5d9d49faf6..a127c0021d 100644
--- a/java/client/src/test/java/org/signal/libsignal/zkgroup/SecureRandomTest.java
+++ b/java/client/src/test/java/org/signal/libsignal/zkgroup/SecureRandomTest.java
@@ -5,13 +5,12 @@
package org.signal.libsignal.zkgroup;
-import java.security.SecureRandom;
-import java.security.SecureRandomSpi;
-import java.util.Arrays;
-
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
+import java.security.SecureRandom;
+import java.security.SecureRandomSpi;
+
public abstract class SecureRandomTest {
private static class MockRandomSpi extends SecureRandomSpi {
@@ -27,7 +26,8 @@ protected byte[] engineGenerateSeed(int numBytes) {
protected void engineNextBytes(byte[] outBytes) {
assertNotNull("Bytes have been used", bytes);
- assertEquals("createSecureRandom was setup with wrong number of bytes", bytes.length, outBytes.length);
+ assertEquals(
+ "createSecureRandom was setup with wrong number of bytes", bytes.length, outBytes.length);
System.arraycopy(bytes, 0, outBytes, 0, bytes.length);
bytes = null;
}
diff --git a/java/client/src/test/java/org/signal/libsignal/zkgroup/integrationtests/CallLinksTest.java b/java/client/src/test/java/org/signal/libsignal/zkgroup/integrationtests/CallLinksTest.java
index 2ed403e3c1..b836a7e3eb 100644
--- a/java/client/src/test/java/org/signal/libsignal/zkgroup/integrationtests/CallLinksTest.java
+++ b/java/client/src/test/java/org/signal/libsignal/zkgroup/integrationtests/CallLinksTest.java
@@ -5,186 +5,225 @@
package org.signal.libsignal.zkgroup.integrationtests;
-import java.io.UnsupportedEncodingException;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.fail;
+
+import java.time.Instant;
+import java.time.temporal.ChronoUnit;
+import java.util.UUID;
import org.junit.Test;
import org.signal.libsignal.protocol.ServiceId.Aci;
import org.signal.libsignal.protocol.util.Hex;
-import org.signal.libsignal.zkgroup.InvalidInputException;
import org.signal.libsignal.zkgroup.GenericServerPublicParams;
import org.signal.libsignal.zkgroup.GenericServerSecretParams;
+import org.signal.libsignal.zkgroup.InvalidInputException;
import org.signal.libsignal.zkgroup.SecureRandomTest;
import org.signal.libsignal.zkgroup.VerificationFailedException;
-import org.signal.libsignal.zkgroup.calllinks.CallLinkPublicParams;
-import org.signal.libsignal.zkgroup.calllinks.CallLinkSecretParams;
import org.signal.libsignal.zkgroup.calllinks.CallLinkAuthCredential;
import org.signal.libsignal.zkgroup.calllinks.CallLinkAuthCredentialPresentation;
import org.signal.libsignal.zkgroup.calllinks.CallLinkAuthCredentialResponse;
+import org.signal.libsignal.zkgroup.calllinks.CallLinkPublicParams;
+import org.signal.libsignal.zkgroup.calllinks.CallLinkSecretParams;
import org.signal.libsignal.zkgroup.calllinks.CreateCallLinkCredential;
import org.signal.libsignal.zkgroup.calllinks.CreateCallLinkCredentialPresentation;
import org.signal.libsignal.zkgroup.calllinks.CreateCallLinkCredentialRequest;
import org.signal.libsignal.zkgroup.calllinks.CreateCallLinkCredentialRequestContext;
import org.signal.libsignal.zkgroup.calllinks.CreateCallLinkCredentialResponse;
-import java.time.Instant;
-import java.time.temporal.ChronoUnit;
-import java.util.Arrays;
-import java.util.UUID;
-
-import static org.junit.Assert.assertArrayEquals;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNull;
-import static org.junit.Assert.fail;
-
public final class CallLinksTest extends SecureRandomTest {
- private static final Aci TEST_USER_ID = new Aci(UUID.fromString("00010203-0405-0607-0809-0a0b0c0d0e0f"));
+ private static final Aci TEST_USER_ID =
+ new Aci(UUID.fromString("00010203-0405-0607-0809-0a0b0c0d0e0f"));
- private static final byte[] TEST_ARRAY_32 = Hex.fromStringCondensedAssert("000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f");
+ private static final byte[] TEST_ARRAY_32 =
+ Hex.fromStringCondensedAssert(
+ "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f");
- private static final byte[] TEST_ARRAY_32_1 = Hex.fromStringCondensedAssert("6465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f80818283");
+ private static final byte[] TEST_ARRAY_32_1 =
+ Hex.fromStringCondensedAssert(
+ "6465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f80818283");
- private static final byte[] TEST_ARRAY_32_2 = Hex.fromStringCondensedAssert("c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7");
+ private static final byte[] TEST_ARRAY_32_2 =
+ Hex.fromStringCondensedAssert(
+ "c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7");
- private static final byte[] TEST_ARRAY_32_3 = { 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 };
+ private static final byte[] TEST_ARRAY_32_3 = {
+ 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
+ };
- private static final byte[] TEST_ARRAY_32_4 = {
+ private static final byte[] TEST_ARRAY_32_4 = {
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};
+ 28, 29, 30, 31, 32, 33
+ };
- private static final byte[] TEST_ARRAY_32_5 = Hex.fromStringCondensedAssert("030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122");
+ private static final byte[] TEST_ARRAY_32_5 =
+ Hex.fromStringCondensedAssert(
+ "030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122");
// 32 bytes of 0xFF is an invalid Ristretto point, so this should invalidate all the
// the serialized zkgroup structures, since almost everything contains a Ristretto point
private static final byte[] makeBadArray(byte[] a) {
- byte[] temp = a.clone();
- for (int count=0; count < temp.length; count++) {
- temp[count] = (byte)0xFF;
- }
- return temp;
+ byte[] temp = a.clone();
+ for (int count = 0; count < temp.length; count++) {
+ temp[count] = (byte) 0xFF;
+ }
+ return temp;
}
@Test
public void testGenericServerParams() throws InvalidInputException {
// SERVER
- GenericServerSecretParams serverSecretParams = GenericServerSecretParams.generate(createSecureRandom(TEST_ARRAY_32));
+ GenericServerSecretParams serverSecretParams =
+ GenericServerSecretParams.generate(createSecureRandom(TEST_ARRAY_32));
GenericServerPublicParams serverPublicParams = serverSecretParams.getPublicParams();
// SERVER - deserialize test
new GenericServerSecretParams(serverSecretParams.serialize());
new GenericServerPublicParams(serverPublicParams.serialize());
try {
- byte[] temp = new byte[32]; // wrong length
+ byte[] temp = new byte[32]; // wrong length
new GenericServerSecretParams(temp);
fail("Failed to catch invalid GenericServerSecretParams deserialize 1");
} catch (InvalidInputException e) {
- // expected
+ // expected
}
try {
new GenericServerSecretParams(makeBadArray(serverSecretParams.serialize()));
fail("Failed to catch invalid GenericServerSecretParams deserialize 2");
} catch (InvalidInputException e) {
- // expected
+ // expected
}
try {
- byte[] temp = new byte[32]; // wrong length
- new GenericServerPublicParams(temp);
- fail("Failed to catch invalid GenericServerPublicParams deserialize 1");
+ byte[] temp = new byte[32]; // wrong length
+ new GenericServerPublicParams(temp);
+ fail("Failed to catch invalid GenericServerPublicParams deserialize 1");
} catch (InvalidInputException e) {
- // expected
+ // expected
}
try {
- new GenericServerPublicParams(makeBadArray(serverPublicParams.serialize()));
- fail("Failed to catch invalid GenericServerPublicParams deserialize 2");
+ new GenericServerPublicParams(makeBadArray(serverPublicParams.serialize()));
+ fail("Failed to catch invalid GenericServerPublicParams deserialize 2");
} catch (InvalidInputException e) {
- // expected
+ // expected
}
}
@Test
- public void testCreateCallLinkIntegration() throws InvalidInputException, VerificationFailedException {
+ public void testCreateCallLinkIntegration()
+ throws InvalidInputException, VerificationFailedException {
// SERVER
// Generate keys
- GenericServerSecretParams serverSecretParams = GenericServerSecretParams.generate(createSecureRandom(TEST_ARRAY_32));
+ GenericServerSecretParams serverSecretParams =
+ GenericServerSecretParams.generate(createSecureRandom(TEST_ARRAY_32));
GenericServerPublicParams serverPublicParams = serverSecretParams.getPublicParams();
// CLIENT
// Generate keys
- CallLinkSecretParams clientSecretParams = CallLinkSecretParams.deriveFromRootKey(TEST_ARRAY_32_1);
+ CallLinkSecretParams clientSecretParams =
+ CallLinkSecretParams.deriveFromRootKey(TEST_ARRAY_32_1);
CallLinkPublicParams clientPublicParams = clientSecretParams.getPublicParams();
// Create context and request
byte[] roomId = TEST_ARRAY_32_2;
- CreateCallLinkCredentialRequestContext context = CreateCallLinkCredentialRequestContext.forRoom(roomId, createSecureRandom(TEST_ARRAY_32_3));
- CreateCallLinkCredentialRequest request = context.getRequest();
+ CreateCallLinkCredentialRequestContext context =
+ CreateCallLinkCredentialRequestContext.forRoom(roomId, createSecureRandom(TEST_ARRAY_32_3));
+ CreateCallLinkCredentialRequest request = context.getRequest();
// SERVER
// Issue credential
Instant timestamp = Instant.now().truncatedTo(ChronoUnit.DAYS);
- CreateCallLinkCredentialResponse response = request.issueCredential(TEST_USER_ID, timestamp, serverSecretParams, createSecureRandom(TEST_ARRAY_32_4));
+ CreateCallLinkCredentialResponse response =
+ request.issueCredential(
+ TEST_USER_ID, timestamp, serverSecretParams, createSecureRandom(TEST_ARRAY_32_4));
// CLIENT
// Gets stored credential
- CreateCallLinkCredential credential = context.receiveResponse(response, TEST_USER_ID, serverPublicParams);
- CreateCallLinkCredentialPresentation presentation = credential.present(roomId, TEST_USER_ID, serverPublicParams, clientSecretParams, createSecureRandom(TEST_ARRAY_32_5));
+ CreateCallLinkCredential credential =
+ context.receiveResponse(response, TEST_USER_ID, serverPublicParams);
+ CreateCallLinkCredentialPresentation presentation =
+ credential.present(
+ roomId,
+ TEST_USER_ID,
+ serverPublicParams,
+ clientSecretParams,
+ createSecureRandom(TEST_ARRAY_32_5));
// SERVER
// Verify presentation
presentation.verify(roomId, serverSecretParams, clientPublicParams);
- presentation.verify(roomId, timestamp.plus(1, ChronoUnit.DAYS), serverSecretParams, clientPublicParams);
+ presentation.verify(
+ roomId, timestamp.plus(1, ChronoUnit.DAYS), serverSecretParams, clientPublicParams);
try {
- presentation.verify(roomId, timestamp.plus(30, ChronoUnit.HOURS), serverSecretParams, clientPublicParams);
- fail("credential expired 1");
+ presentation.verify(
+ roomId, timestamp.plus(30, ChronoUnit.HOURS), serverSecretParams, clientPublicParams);
+ fail("credential expired 1");
} catch (VerificationFailedException e) {
- // expected
+ // expected
}
try {
- presentation.verify(roomId, timestamp.plus(30, ChronoUnit.HOURS).plusSeconds(1), serverSecretParams, clientPublicParams);
- fail("credential expired 2");
+ presentation.verify(
+ roomId,
+ timestamp.plus(30, ChronoUnit.HOURS).plusSeconds(1),
+ serverSecretParams,
+ clientPublicParams);
+ fail("credential expired 2");
} catch (VerificationFailedException e) {
- // expected
+ // expected
}
}
@Test
- public void testCallLinkAuthIntegration() throws InvalidInputException, VerificationFailedException {
+ public void testCallLinkAuthIntegration()
+ throws InvalidInputException, VerificationFailedException {
// SERVER
// Generate keys
- GenericServerSecretParams serverSecretParams = GenericServerSecretParams.generate(createSecureRandom(TEST_ARRAY_32));
+ GenericServerSecretParams serverSecretParams =
+ GenericServerSecretParams.generate(createSecureRandom(TEST_ARRAY_32));
GenericServerPublicParams serverPublicParams = serverSecretParams.getPublicParams();
// CLIENT
// Generate keys
- CallLinkSecretParams clientSecretParams = CallLinkSecretParams.deriveFromRootKey(TEST_ARRAY_32_1);
+ CallLinkSecretParams clientSecretParams =
+ CallLinkSecretParams.deriveFromRootKey(TEST_ARRAY_32_1);
CallLinkPublicParams clientPublicParams = clientSecretParams.getPublicParams();
// SERVER
// Issue credential
Instant redemptionTime = Instant.now().truncatedTo(ChronoUnit.DAYS);
- CallLinkAuthCredentialResponse response = CallLinkAuthCredentialResponse.issueCredential(TEST_USER_ID, redemptionTime, serverSecretParams, createSecureRandom(TEST_ARRAY_32_4));
+ CallLinkAuthCredentialResponse response =
+ CallLinkAuthCredentialResponse.issueCredential(
+ TEST_USER_ID, redemptionTime, serverSecretParams, createSecureRandom(TEST_ARRAY_32_4));
// CLIENT
// Gets stored credential
- CallLinkAuthCredential credential = response.receive(TEST_USER_ID, redemptionTime, serverPublicParams);
- CallLinkAuthCredentialPresentation presentation = credential.present(TEST_USER_ID, redemptionTime, serverPublicParams, clientSecretParams, createSecureRandom(TEST_ARRAY_32_5));
+ CallLinkAuthCredential credential =
+ response.receive(TEST_USER_ID, redemptionTime, serverPublicParams);
+ CallLinkAuthCredentialPresentation presentation =
+ credential.present(
+ TEST_USER_ID,
+ redemptionTime,
+ serverPublicParams,
+ clientSecretParams,
+ createSecureRandom(TEST_ARRAY_32_5));
// SERVER
// Verify presentation
presentation.verify(serverSecretParams, clientPublicParams);
- presentation.verify(redemptionTime.plus(1, ChronoUnit.DAYS), serverSecretParams, clientPublicParams);
+ presentation.verify(
+ redemptionTime.plus(1, ChronoUnit.DAYS), serverSecretParams, clientPublicParams);
try {
- presentation.verify(redemptionTime.plus(3, ChronoUnit.DAYS), serverSecretParams, clientPublicParams);
- fail("credential expired 1");
+ presentation.verify(
+ redemptionTime.plus(3, ChronoUnit.DAYS), serverSecretParams, clientPublicParams);
+ fail("credential expired 1");
} catch (VerificationFailedException e) {
- // expected
+ // expected
}
// CLIENT
assertEquals(TEST_USER_ID, clientSecretParams.decryptUserId(presentation.getUserId()));
}
}
-
diff --git a/java/client/src/test/java/org/signal/libsignal/zkgroup/integrationtests/ZkGroupTest.java b/java/client/src/test/java/org/signal/libsignal/zkgroup/integrationtests/ZkGroupTest.java
index d4c6dcb114..6288fcb86f 100644
--- a/java/client/src/test/java/org/signal/libsignal/zkgroup/integrationtests/ZkGroupTest.java
+++ b/java/client/src/test/java/org/signal/libsignal/zkgroup/integrationtests/ZkGroupTest.java
@@ -5,7 +5,15 @@
package org.signal.libsignal.zkgroup.integrationtests;
+import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
+
import java.io.UnsupportedEncodingException;
+import java.time.Instant;
+import java.time.temporal.ChronoUnit;
+import java.util.Arrays;
+import java.util.UUID;
import org.junit.Test;
import org.signal.libsignal.protocol.ServiceId;
import org.signal.libsignal.protocol.ServiceId.Aci;
@@ -40,99 +48,102 @@
import org.signal.libsignal.zkgroup.profiles.ProfileKeyCredentialRequestContext;
import org.signal.libsignal.zkgroup.profiles.ServerZkProfileOperations;
-import java.time.Instant;
-import java.time.temporal.ChronoUnit;
-import java.util.Arrays;
-import java.util.UUID;
-
-import static org.junit.Assert.assertArrayEquals;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNull;
-
public final class ZkGroupTest extends SecureRandomTest {
- private static final UUID TEST_UUID = UUID.fromString("00010203-0405-0607-0809-0a0b0c0d0e0f");
+ private static final UUID TEST_UUID = UUID.fromString("00010203-0405-0607-0809-0a0b0c0d0e0f");
- private static final UUID TEST_UUID_1 = UUID.fromString("64656667-6869-6A6B-6C6D-6E6F70717273");
+ private static final UUID TEST_UUID_1 = UUID.fromString("64656667-6869-6A6B-6C6D-6E6F70717273");
- private static final byte[] TEST_ARRAY_32 = Hex.fromStringCondensedAssert("000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f");
+ private static final byte[] TEST_ARRAY_32 =
+ Hex.fromStringCondensedAssert(
+ "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f");
- private static final byte[] TEST_ARRAY_32_1 = Hex.fromStringCondensedAssert("6465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f80818283");
+ private static final byte[] TEST_ARRAY_32_1 =
+ Hex.fromStringCondensedAssert(
+ "6465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f80818283");
- private static final byte[] TEST_ARRAY_32_2 = Hex.fromStringCondensedAssert("c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7");
+ private static final byte[] TEST_ARRAY_32_2 =
+ Hex.fromStringCondensedAssert(
+ "c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7");
- private static final byte[] TEST_ARRAY_32_3 = { 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 };
+ private static final byte[] TEST_ARRAY_32_3 = {
+ 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
+ };
- private static final byte[] TEST_ARRAY_32_4 = {
+ private static final byte[] TEST_ARRAY_32_4 = {
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};
+ 28, 29, 30, 31, 32, 33
+ };
+ private static final byte[] TEST_ARRAY_32_5 =
+ Hex.fromStringCondensedAssert(
+ "030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122");
- private static final byte[] TEST_ARRAY_32_5 = Hex.fromStringCondensedAssert("030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122");
-
- private static final byte[] authPresentationResultV2 = Hex. fromStringCondensedAssert("01322f9100de0734550a81dc81724a81dbd3b1b43dbc1d552d53455911c2772f34a6356ca17c6d34d858391456af55d0ef841fbe1fa8c4ee810f21e0bb9f4ace4c5c48c72ebbeb2ccda5f7aa49aee6bc0051cdde166e0f8c5f1febd53a4437c570ee1aa223f5eb937db98f34e3653d85ec163f39847222a2dec4235ea41c47bb62028aae30945857ee77663079bcc4923d14a43ad4f6bc33715046f7bde52715375ca9f89be0e630d4bdaa211156d0306723f543b06f5e998447b962c8e9729b4cc00000000000000074d0eae8e4311a6ae3d2970ef198c398110462be47dd2f26e6559209ef6cc20001a05a0b319a172dbeb2293cc1e0e191cefb23e24cf0d6b4b5373a30044be10cb033674d631e17dfce09398f234e9d62e118a6077caea0ef8bf67d7d723db70fecf2098fa041317b7be9fdbb68b0f25f5c479d68bd917fc6f187c5bf7a58910231921fc43565232466325c039212362b6d1203ccaedf831dc7f9060dcaaffa02624042171f5f0e780b9f74cfa88a147f3f1c082f9ca8638af1788e7899cbae0c765de9df4cfa5487f360e29e99343e91811baec331c4680985e608ca5d408e21725c6aa1b61d5a8b48d75f4aaa9a3cbe88d3e0f1a54319081f77c72c8f52547440e20100");
+ private static final byte[] authPresentationResultV2 =
+ Hex.fromStringCondensedAssert(
+ "01322f9100de0734550a81dc81724a81dbd3b1b43dbc1d552d53455911c2772f34a6356ca17c6d34d858391456af55d0ef841fbe1fa8c4ee810f21e0bb9f4ace4c5c48c72ebbeb2ccda5f7aa49aee6bc0051cdde166e0f8c5f1febd53a4437c570ee1aa223f5eb937db98f34e3653d85ec163f39847222a2dec4235ea41c47bb62028aae30945857ee77663079bcc4923d14a43ad4f6bc33715046f7bde52715375ca9f89be0e630d4bdaa211156d0306723f543b06f5e998447b962c8e9729b4cc00000000000000074d0eae8e4311a6ae3d2970ef198c398110462be47dd2f26e6559209ef6cc20001a05a0b319a172dbeb2293cc1e0e191cefb23e24cf0d6b4b5373a30044be10cb033674d631e17dfce09398f234e9d62e118a6077caea0ef8bf67d7d723db70fecf2098fa041317b7be9fdbb68b0f25f5c479d68bd917fc6f187c5bf7a58910231921fc43565232466325c039212362b6d1203ccaedf831dc7f9060dcaaffa02624042171f5f0e780b9f74cfa88a147f3f1c082f9ca8638af1788e7899cbae0c765de9df4cfa5487f360e29e99343e91811baec331c4680985e608ca5d408e21725c6aa1b61d5a8b48d75f4aaa9a3cbe88d3e0f1a54319081f77c72c8f52547440e20100");
// 32 bytes of 0xFF is an invalid Ristretto point, so this should invalidate all the
// the serialized zkgroup structures, since almost everything contains a Ristretto point
private static final byte[] makeBadArray(byte[] a) {
- byte[] temp = a.clone();
- for (int count=0; count < temp.length; count++) {
- temp[count] = (byte)0xFF;
- }
- return temp;
+ byte[] temp = a.clone();
+ for (int count = 0; count < temp.length; count++) {
+ temp[count] = (byte) 0xFF;
+ }
+ return temp;
}
@Test
public void testAuthIntegration() throws VerificationFailedException, InvalidInputException {
- Aci aci = new Aci(TEST_UUID);
+ Aci aci = new Aci(TEST_UUID);
int redemptionTime = 123456;
// Generate keys (client's are per-group, server's are not)
// ---
// SERVER
- ServerSecretParams serverSecretParams = ServerSecretParams.generate(createSecureRandom(TEST_ARRAY_32));
+ ServerSecretParams serverSecretParams =
+ ServerSecretParams.generate(createSecureRandom(TEST_ARRAY_32));
ServerPublicParams serverPublicParams = serverSecretParams.getPublicParams();
// SERVER - deserialize test
{
- new ServerSecretParams(serverSecretParams.serialize());
- new ServerPublicParams(serverPublicParams.serialize());
- try {
- byte[] temp = new byte[32]; // wrong length
- new ServerSecretParams(temp);
- throw new AssertionError("Failed to catch invalid ServerSecretParams deserialize 1");
- } catch (InvalidInputException e) {
- // expected
- }
- try {
- new ServerSecretParams(makeBadArray(serverSecretParams.serialize()));
- throw new AssertionError("Failed to catch invalid ServerSecretParams deserialize 2");
- } catch (InvalidInputException e) {
- // expected
- }
- try {
- byte[] temp = new byte[32]; // wrong length
- new ServerPublicParams(temp);
- throw new AssertionError("Failed to catch invalid ServerPublicParams deserialize 1");
- } catch (InvalidInputException e) {
- // expected
- }
- try {
- new ServerPublicParams(makeBadArray(serverPublicParams.serialize()));
- throw new AssertionError("Failed to catch invalid ServerPublicParams deserialize 2");
- } catch (InvalidInputException e) {
- // expected
- }
- }
-
- ServerZkAuthOperations serverZkAuth = new ServerZkAuthOperations(serverSecretParams);
+ new ServerSecretParams(serverSecretParams.serialize());
+ new ServerPublicParams(serverPublicParams.serialize());
+ try {
+ byte[] temp = new byte[32]; // wrong length
+ new ServerSecretParams(temp);
+ throw new AssertionError("Failed to catch invalid ServerSecretParams deserialize 1");
+ } catch (InvalidInputException e) {
+ // expected
+ }
+ try {
+ new ServerSecretParams(makeBadArray(serverSecretParams.serialize()));
+ throw new AssertionError("Failed to catch invalid ServerSecretParams deserialize 2");
+ } catch (InvalidInputException e) {
+ // expected
+ }
+ try {
+ byte[] temp = new byte[32]; // wrong length
+ new ServerPublicParams(temp);
+ throw new AssertionError("Failed to catch invalid ServerPublicParams deserialize 1");
+ } catch (InvalidInputException e) {
+ // expected
+ }
+ try {
+ new ServerPublicParams(makeBadArray(serverPublicParams.serialize()));
+ throw new AssertionError("Failed to catch invalid ServerPublicParams deserialize 2");
+ } catch (InvalidInputException e) {
+ // expected
+ }
+ }
+
+ ServerZkAuthOperations serverZkAuth = new ServerZkAuthOperations(serverSecretParams);
// CLIENT
- GroupMasterKey masterKey = new GroupMasterKey(TEST_ARRAY_32_1);
+ GroupMasterKey masterKey = new GroupMasterKey(TEST_ARRAY_32_1);
GroupSecretParams groupSecretParams = GroupSecretParams.deriveFromMasterKey(masterKey);
assertArrayEquals(groupSecretParams.getMasterKey().serialize(), masterKey.serialize());
@@ -141,150 +152,159 @@ public void testAuthIntegration() throws VerificationFailedException, InvalidInp
// CLIENT - deserialize test
{
- new GroupSecretParams(groupSecretParams.serialize());
- new GroupPublicParams(groupPublicParams.serialize());
- try {
- byte[] temp = new byte[10]; // wrong length
- new GroupMasterKey(temp);
- throw new AssertionError("Failed to catch invalid GroupMasterKey deserialize");
- } catch (InvalidInputException e) {
- // expected
- }
- try {
- byte[] temp = new byte[10]; // wrong length
- new GroupSecretParams(temp);
- throw new AssertionError("Failed to catch invalid GroupSecretParams deserialize 1");
- } catch (InvalidInputException e) {
- // expected
- }
- try {
- new GroupSecretParams(makeBadArray(groupSecretParams.serialize()));
- throw new AssertionError("Failed to catch invalid GroupSecretParams deserialize 2");
- } catch (InvalidInputException e) {
- // expected
- }
- try {
- byte[] temp = new byte[10]; // wrong length
- new GroupPublicParams(temp);
- throw new AssertionError("Failed to catch invalid GroupPublicParams deserialize 1");
- } catch (InvalidInputException e) {
- // expected
- }
- try {
- new GroupPublicParams(makeBadArray(groupPublicParams.serialize()));
- throw new AssertionError("Failed to catch invalid GroupPublicParams deserialize 2");
- } catch (InvalidInputException e) {
- // expected
- }
+ new GroupSecretParams(groupSecretParams.serialize());
+ new GroupPublicParams(groupPublicParams.serialize());
+ try {
+ byte[] temp = new byte[10]; // wrong length
+ new GroupMasterKey(temp);
+ throw new AssertionError("Failed to catch invalid GroupMasterKey deserialize");
+ } catch (InvalidInputException e) {
+ // expected
+ }
+ try {
+ byte[] temp = new byte[10]; // wrong length
+ new GroupSecretParams(temp);
+ throw new AssertionError("Failed to catch invalid GroupSecretParams deserialize 1");
+ } catch (InvalidInputException e) {
+ // expected
+ }
+ try {
+ new GroupSecretParams(makeBadArray(groupSecretParams.serialize()));
+ throw new AssertionError("Failed to catch invalid GroupSecretParams deserialize 2");
+ } catch (InvalidInputException e) {
+ // expected
+ }
+ try {
+ byte[] temp = new byte[10]; // wrong length
+ new GroupPublicParams(temp);
+ throw new AssertionError("Failed to catch invalid GroupPublicParams deserialize 1");
+ } catch (InvalidInputException e) {
+ // expected
+ }
+ try {
+ new GroupPublicParams(makeBadArray(groupPublicParams.serialize()));
+ throw new AssertionError("Failed to catch invalid GroupPublicParams deserialize 2");
+ } catch (InvalidInputException e) {
+ // expected
+ }
}
// SERVER
// Issue credential
- AuthCredentialResponse authCredentialResponse = serverZkAuth.issueAuthCredential(createSecureRandom(TEST_ARRAY_32_2), aci, redemptionTime);
+ AuthCredentialResponse authCredentialResponse =
+ serverZkAuth.issueAuthCredential(createSecureRandom(TEST_ARRAY_32_2), aci, redemptionTime);
// CLIENT
// Receive credential
- ClientZkAuthOperations clientZkAuthCipher = new ClientZkAuthOperations(serverPublicParams);
- ClientZkGroupCipher clientZkGroupCipher = new ClientZkGroupCipher (groupSecretParams );
- AuthCredential authCredential = clientZkAuthCipher.receiveAuthCredential(aci, redemptionTime, authCredentialResponse);
+ ClientZkAuthOperations clientZkAuthCipher = new ClientZkAuthOperations(serverPublicParams);
+ ClientZkGroupCipher clientZkGroupCipher = new ClientZkGroupCipher(groupSecretParams);
+ AuthCredential authCredential =
+ clientZkAuthCipher.receiveAuthCredential(aci, redemptionTime, authCredentialResponse);
// CLIENT - deserialize test
{
- new AuthCredentialResponse(authCredentialResponse.serialize());
- try {
- byte[] temp = new byte[10];
- new AuthCredentialResponse(temp);
- throw new AssertionError("Failed to catch invalid AuthCredentialResponse deserialize 1");
- } catch (InvalidInputException e) {
- // expected
- }
- try {
- new AuthCredentialResponse(makeBadArray(authCredentialResponse.serialize()));
- throw new AssertionError("Failed to catch invalid AuthCredentialResponse deserialize 2");
- } catch (InvalidInputException e) {
- // expected
- }
+ new AuthCredentialResponse(authCredentialResponse.serialize());
+ try {
+ byte[] temp = new byte[10];
+ new AuthCredentialResponse(temp);
+ throw new AssertionError("Failed to catch invalid AuthCredentialResponse deserialize 1");
+ } catch (InvalidInputException e) {
+ // expected
+ }
+ try {
+ new AuthCredentialResponse(makeBadArray(authCredentialResponse.serialize()));
+ throw new AssertionError("Failed to catch invalid AuthCredentialResponse deserialize 2");
+ } catch (InvalidInputException e) {
+ // expected
+ }
}
// CLIENT - verify test
{
- UUID badUuid = TEST_UUID_1;
- try {
- clientZkAuthCipher.receiveAuthCredential(new Aci(badUuid), redemptionTime, authCredentialResponse);
- throw new AssertionError("Failed to catch invalid AuthCredential 1");
- } catch (VerificationFailedException e) {
- // expected
- }
-
- byte[] temp = authCredentialResponse.serialize();
- temp[1]++;
- AuthCredentialResponse badResponse = new AuthCredentialResponse(temp);
- try {
- clientZkAuthCipher.receiveAuthCredential(aci, redemptionTime, badResponse);
- throw new AssertionError("Failed to catch invalid AuthCredential 2");
- } catch (VerificationFailedException e) {
- // expected
- }
+ UUID badUuid = TEST_UUID_1;
+ try {
+ clientZkAuthCipher.receiveAuthCredential(
+ new Aci(badUuid), redemptionTime, authCredentialResponse);
+ throw new AssertionError("Failed to catch invalid AuthCredential 1");
+ } catch (VerificationFailedException e) {
+ // expected
+ }
+
+ byte[] temp = authCredentialResponse.serialize();
+ temp[1]++;
+ AuthCredentialResponse badResponse = new AuthCredentialResponse(temp);
+ try {
+ clientZkAuthCipher.receiveAuthCredential(aci, redemptionTime, badResponse);
+ throw new AssertionError("Failed to catch invalid AuthCredential 2");
+ } catch (VerificationFailedException e) {
+ // expected
+ }
}
// Create and decrypt user entry
UuidCiphertext uuidCiphertext = clientZkGroupCipher.encrypt(aci);
- ServiceId plaintext = clientZkGroupCipher.decrypt(uuidCiphertext);
+ ServiceId plaintext = clientZkGroupCipher.decrypt(uuidCiphertext);
assertEquals(aci, plaintext);
// CLIENT - deserialize test
{
- new UuidCiphertext(uuidCiphertext.serialize());
- try {
- byte[] temp = new byte[10];
- new UuidCiphertext(temp);
- throw new AssertionError("Failed to catch invalid UuidCiphertext deserialize 1");
- } catch (InvalidInputException e) {
- // expected
- }
-
- try {
- new UuidCiphertext(makeBadArray(uuidCiphertext.serialize()));
- throw new AssertionError("Failed to catch invalid UuidCiphertext deserialize 2");
- } catch (InvalidInputException e) {
- // expected
- }
+ new UuidCiphertext(uuidCiphertext.serialize());
+ try {
+ byte[] temp = new byte[10];
+ new UuidCiphertext(temp);
+ throw new AssertionError("Failed to catch invalid UuidCiphertext deserialize 1");
+ } catch (InvalidInputException e) {
+ // expected
+ }
+
+ try {
+ new UuidCiphertext(makeBadArray(uuidCiphertext.serialize()));
+ throw new AssertionError("Failed to catch invalid UuidCiphertext deserialize 2");
+ } catch (InvalidInputException e) {
+ // expected
+ }
}
// CLIENT - verify test
{
- byte[] temp = uuidCiphertext.serialize();
- temp[3]++; // We need a bad ciphertext that passes deserialization, this seems to work
- try {
- clientZkGroupCipher.decrypt(new UuidCiphertext(temp));
- throw new AssertionError("Failed to catch invalid UuidCiphertext decrypt");
- } catch (VerificationFailedException e) {
- // expected
- }
+ byte[] temp = uuidCiphertext.serialize();
+ temp[3]++; // We need a bad ciphertext that passes deserialization, this seems to work
+ try {
+ clientZkGroupCipher.decrypt(new UuidCiphertext(temp));
+ throw new AssertionError("Failed to catch invalid UuidCiphertext decrypt");
+ } catch (VerificationFailedException e) {
+ // expected
+ }
}
// CLIENT - Create presentation
- AuthCredentialPresentation presentation = clientZkAuthCipher.createAuthCredentialPresentation(createSecureRandom(TEST_ARRAY_32_5), groupSecretParams, authCredential);
- assertEquals(presentation.serialize()[0], 1); // Check V2 (versions start from 1 but are encoded starting from 0)
+ AuthCredentialPresentation presentation =
+ clientZkAuthCipher.createAuthCredentialPresentation(
+ createSecureRandom(TEST_ARRAY_32_5), groupSecretParams, authCredential);
+ assertEquals(
+ presentation.serialize()[0],
+ 1); // Check V2 (versions start from 1 but are encoded starting from 0)
assertEquals(presentation.getVersion(), AuthCredentialPresentation.Version.V2);
assertArrayEquals(presentation.serialize(), authPresentationResultV2);
// CLIENT - deserialize test
{
- new AuthCredentialPresentation(presentation.serialize());
- byte[] temp = new byte[10];
- try {
- new AuthCredentialPresentation(temp);
- throw new AssertionError("Failed to catch invalid AuthCredentialPresentation deserialize 1");
- } catch (InvalidInputException e) {
- // expected
- }
- try {
- new AuthCredentialPresentation(makeBadArray(presentation.serialize()));
- throw new AssertionError("Failed to catch invalid AuthCredentialPresentation deserialize 2");
- } catch (InvalidInputException e) {
- // expected
- }
+ new AuthCredentialPresentation(presentation.serialize());
+ byte[] temp = new byte[10];
+ try {
+ new AuthCredentialPresentation(temp);
+ throw new AssertionError(
+ "Failed to catch invalid AuthCredentialPresentation deserialize 1");
+ } catch (InvalidInputException e) {
+ // expected
+ }
+ try {
+ new AuthCredentialPresentation(makeBadArray(presentation.serialize()));
+ throw new AssertionError(
+ "Failed to catch invalid AuthCredentialPresentation deserialize 2");
+ } catch (InvalidInputException e) {
+ // expected
+ }
}
// SERVER - Verify presentation, using times at the edge of the acceptable window
@@ -294,75 +314,87 @@ public void testAuthIntegration() throws VerificationFailedException, InvalidInp
assertNull(presentation.getPniCiphertext());
assertEquals(presentation.getRedemptionTime(), redemptionInstant);
- serverZkAuth.verifyAuthCredentialPresentation(groupPublicParams, presentation, redemptionInstant.minus(1, ChronoUnit.DAYS));
- serverZkAuth.verifyAuthCredentialPresentation(groupPublicParams, presentation, redemptionInstant.plus(2, ChronoUnit.DAYS));
+ serverZkAuth.verifyAuthCredentialPresentation(
+ groupPublicParams, presentation, redemptionInstant.minus(1, ChronoUnit.DAYS));
+ serverZkAuth.verifyAuthCredentialPresentation(
+ groupPublicParams, presentation, redemptionInstant.plus(2, ChronoUnit.DAYS));
try {
- serverZkAuth.verifyAuthCredentialPresentation(groupPublicParams, presentation, redemptionInstant.minus(1, ChronoUnit.DAYS).minus(1, ChronoUnit.SECONDS));
- throw new AssertionError("verifyAuthCredentialPresentation should fail #1!");
+ serverZkAuth.verifyAuthCredentialPresentation(
+ groupPublicParams,
+ presentation,
+ redemptionInstant.minus(1, ChronoUnit.DAYS).minus(1, ChronoUnit.SECONDS));
+ throw new AssertionError("verifyAuthCredentialPresentation should fail #1!");
} catch (VerificationFailedException e) {
// good
}
try {
- serverZkAuth.verifyAuthCredentialPresentation(groupPublicParams, presentation, redemptionInstant.plus(2, ChronoUnit.DAYS).plus(1, ChronoUnit.SECONDS));
- throw new AssertionError("verifyAuthCredentialPresentation should fail #2!");
+ serverZkAuth.verifyAuthCredentialPresentation(
+ groupPublicParams,
+ presentation,
+ redemptionInstant.plus(2, ChronoUnit.DAYS).plus(1, ChronoUnit.SECONDS));
+ throw new AssertionError("verifyAuthCredentialPresentation should fail #2!");
} catch (VerificationFailedException e) {
// good
}
try {
- byte[] temp = presentation.serialize();
- temp[3]++; // We need a bad presentation that passes deserialization, this seems to work
- AuthCredentialPresentation presentationTemp = new AuthCredentialPresentation(temp);
- serverZkAuth.verifyAuthCredentialPresentation(groupPublicParams, presentationTemp, redemptionInstant);
- throw new AssertionError("verifyAuthCredentialPresentation should fail #3!");
+ byte[] temp = presentation.serialize();
+ temp[3]++; // We need a bad presentation that passes deserialization, this seems to work
+ AuthCredentialPresentation presentationTemp = new AuthCredentialPresentation(temp);
+ serverZkAuth.verifyAuthCredentialPresentation(
+ groupPublicParams, presentationTemp, redemptionInstant);
+ throw new AssertionError("verifyAuthCredentialPresentation should fail #3!");
} catch (VerificationFailedException e) {
- // expected
+ // expected
}
try {
- byte[] temp = presentation.serialize();
- temp[0] = 0; // This interprets a V2 as V1, so should fail
- AuthCredentialPresentation presentationTemp = new AuthCredentialPresentation(temp);
- serverZkAuth.verifyAuthCredentialPresentation(groupPublicParams, presentationTemp, redemptionInstant);
- throw new AssertionError("verifyAuthCredentialPresentation should fail #4");
+ byte[] temp = presentation.serialize();
+ temp[0] = 0; // This interprets a V2 as V1, so should fail
+ AuthCredentialPresentation presentationTemp = new AuthCredentialPresentation(temp);
+ serverZkAuth.verifyAuthCredentialPresentation(
+ groupPublicParams, presentationTemp, redemptionInstant);
+ throw new AssertionError("verifyAuthCredentialPresentation should fail #4");
} catch (InvalidInputException e) {
- // expected
+ // expected
}
try {
- byte[] temp = presentation.serialize();
- temp[0] = 40; // This interprets a V2 as a non-existent version, so should fail
- AuthCredentialPresentation presentationTemp = new AuthCredentialPresentation(temp);
- serverZkAuth.verifyAuthCredentialPresentation(groupPublicParams, presentationTemp, redemptionInstant);
- throw new AssertionError("verifyAuthCredentialPresentation should fail #5");
+ byte[] temp = presentation.serialize();
+ temp[0] = 40; // This interprets a V2 as a non-existent version, so should fail
+ AuthCredentialPresentation presentationTemp = new AuthCredentialPresentation(temp);
+ serverZkAuth.verifyAuthCredentialPresentation(
+ groupPublicParams, presentationTemp, redemptionInstant);
+ throw new AssertionError("verifyAuthCredentialPresentation should fail #5");
} catch (InvalidInputException e) {
- // expected
+ // expected
}
-
}
-
@Test
- public void testAuthIntegrationCurrentTime() throws VerificationFailedException, InvalidInputException {
+ public void testAuthIntegrationCurrentTime()
+ throws VerificationFailedException, InvalidInputException {
// This test is mostly the same as testAuthIntegration() except instead of using a hardcoded
// redemption date to compare against test vectors, it uses the current time
- Aci aci = new Aci(TEST_UUID);
- int redemptionTime = (int)(Instant.now().truncatedTo(ChronoUnit.DAYS).getEpochSecond() / 86400);
+ Aci aci = new Aci(TEST_UUID);
+ int redemptionTime =
+ (int) (Instant.now().truncatedTo(ChronoUnit.DAYS).getEpochSecond() / 86400);
// Generate keys (client's are per-group, server's are not)
// ---
// SERVER
- ServerSecretParams serverSecretParams = ServerSecretParams.generate(createSecureRandom(TEST_ARRAY_32));
+ ServerSecretParams serverSecretParams =
+ ServerSecretParams.generate(createSecureRandom(TEST_ARRAY_32));
ServerPublicParams serverPublicParams = serverSecretParams.getPublicParams();
- ServerZkAuthOperations serverZkAuth = new ServerZkAuthOperations(serverSecretParams);
+ ServerZkAuthOperations serverZkAuth = new ServerZkAuthOperations(serverSecretParams);
// CLIENT
- GroupMasterKey masterKey = new GroupMasterKey(TEST_ARRAY_32_1);
+ GroupMasterKey masterKey = new GroupMasterKey(TEST_ARRAY_32_1);
GroupSecretParams groupSecretParams = GroupSecretParams.deriveFromMasterKey(masterKey);
assertArrayEquals(groupSecretParams.getMasterKey().serialize(), masterKey.serialize());
@@ -371,21 +403,25 @@ public void testAuthIntegrationCurrentTime() throws VerificationFailedException,
// SERVER
// Issue credential
- AuthCredentialResponse authCredentialResponse = serverZkAuth.issueAuthCredential(createSecureRandom(TEST_ARRAY_32_2), aci, redemptionTime);
+ AuthCredentialResponse authCredentialResponse =
+ serverZkAuth.issueAuthCredential(createSecureRandom(TEST_ARRAY_32_2), aci, redemptionTime);
// CLIENT
// Receive credential
- ClientZkAuthOperations clientZkAuthCipher = new ClientZkAuthOperations(serverPublicParams);
- ClientZkGroupCipher clientZkGroupCipher = new ClientZkGroupCipher (groupSecretParams );
- AuthCredential authCredential = clientZkAuthCipher.receiveAuthCredential(aci, redemptionTime, authCredentialResponse);
+ ClientZkAuthOperations clientZkAuthCipher = new ClientZkAuthOperations(serverPublicParams);
+ ClientZkGroupCipher clientZkGroupCipher = new ClientZkGroupCipher(groupSecretParams);
+ AuthCredential authCredential =
+ clientZkAuthCipher.receiveAuthCredential(aci, redemptionTime, authCredentialResponse);
// Create and decrypt user entry
UuidCiphertext uuidCiphertext = clientZkGroupCipher.encrypt(aci);
- ServiceId plaintext = clientZkGroupCipher.decrypt(uuidCiphertext);
+ ServiceId plaintext = clientZkGroupCipher.decrypt(uuidCiphertext);
assertEquals(aci, plaintext);
// Create presentation
- AuthCredentialPresentation presentation = clientZkAuthCipher.createAuthCredentialPresentation(createSecureRandom(TEST_ARRAY_32_5), groupSecretParams, authCredential);
+ AuthCredentialPresentation presentation =
+ clientZkAuthCipher.createAuthCredentialPresentation(
+ createSecureRandom(TEST_ARRAY_32_5), groupSecretParams, authCredential);
// Verify presentation, using times at the edge of the acceptable window
Instant redemptionInstant = Instant.ofEpochSecond(86400L * redemptionTime);
@@ -396,42 +432,52 @@ public void testAuthIntegrationCurrentTime() throws VerificationFailedException,
// By default the library uses the current time
serverZkAuth.verifyAuthCredentialPresentation(groupPublicParams, presentation);
- serverZkAuth.verifyAuthCredentialPresentation(groupPublicParams, presentation, redemptionInstant.minus(1, ChronoUnit.DAYS));
- serverZkAuth.verifyAuthCredentialPresentation(groupPublicParams, presentation, redemptionInstant.plus(2, ChronoUnit.DAYS));
+ serverZkAuth.verifyAuthCredentialPresentation(
+ groupPublicParams, presentation, redemptionInstant.minus(1, ChronoUnit.DAYS));
+ serverZkAuth.verifyAuthCredentialPresentation(
+ groupPublicParams, presentation, redemptionInstant.plus(2, ChronoUnit.DAYS));
try {
- serverZkAuth.verifyAuthCredentialPresentation(groupPublicParams, presentation, redemptionInstant.minus(1, ChronoUnit.DAYS).minus(1, ChronoUnit.SECONDS));
- throw new AssertionError("verifyAuthCredentialPresentation should fail #1!");
+ serverZkAuth.verifyAuthCredentialPresentation(
+ groupPublicParams,
+ presentation,
+ redemptionInstant.minus(1, ChronoUnit.DAYS).minus(1, ChronoUnit.SECONDS));
+ throw new AssertionError("verifyAuthCredentialPresentation should fail #1!");
} catch (VerificationFailedException e) {
// good
}
try {
- serverZkAuth.verifyAuthCredentialPresentation(groupPublicParams, presentation, redemptionInstant.plus(2, ChronoUnit.DAYS).plus(1, ChronoUnit.SECONDS));
- throw new AssertionError("verifyAuthCredentialPresentation should fail #2!");
+ serverZkAuth.verifyAuthCredentialPresentation(
+ groupPublicParams,
+ presentation,
+ redemptionInstant.plus(2, ChronoUnit.DAYS).plus(1, ChronoUnit.SECONDS));
+ throw new AssertionError("verifyAuthCredentialPresentation should fail #2!");
} catch (VerificationFailedException e) {
// good
}
}
@Test
- public void testAuthWithPniIntegration() throws VerificationFailedException, InvalidInputException {
+ public void testAuthWithPniIntegration()
+ throws VerificationFailedException, InvalidInputException {
- Aci aci = new Aci(TEST_UUID);
- Pni pni = new Pni(TEST_UUID_1);
+ Aci aci = new Aci(TEST_UUID);
+ Pni pni = new Pni(TEST_UUID_1);
Instant redemptionTime = Instant.now().truncatedTo(ChronoUnit.DAYS);
// Generate keys (client's are per-group, server's are not)
// ---
// SERVER
- ServerSecretParams serverSecretParams = ServerSecretParams.generate(createSecureRandom(TEST_ARRAY_32));
+ ServerSecretParams serverSecretParams =
+ ServerSecretParams.generate(createSecureRandom(TEST_ARRAY_32));
ServerPublicParams serverPublicParams = serverSecretParams.getPublicParams();
- ServerZkAuthOperations serverZkAuth = new ServerZkAuthOperations(serverSecretParams);
+ ServerZkAuthOperations serverZkAuth = new ServerZkAuthOperations(serverSecretParams);
// CLIENT
- GroupMasterKey masterKey = new GroupMasterKey(TEST_ARRAY_32_1);
+ GroupMasterKey masterKey = new GroupMasterKey(TEST_ARRAY_32_1);
GroupSecretParams groupSecretParams = GroupSecretParams.deriveFromMasterKey(masterKey);
assertArrayEquals(groupSecretParams.getMasterKey().serialize(), masterKey.serialize());
@@ -440,90 +486,108 @@ public void testAuthWithPniIntegration() throws VerificationFailedException, Inv
// SERVER
// Issue credential
- AuthCredentialWithPniResponse authCredentialResponse = serverZkAuth.issueAuthCredentialWithPniAsServiceId(createSecureRandom(TEST_ARRAY_32_2), aci, pni, redemptionTime);
+ AuthCredentialWithPniResponse authCredentialResponse =
+ serverZkAuth.issueAuthCredentialWithPniAsServiceId(
+ createSecureRandom(TEST_ARRAY_32_2), aci, pni, redemptionTime);
// CLIENT
// Receive credential
- ClientZkAuthOperations clientZkAuthCipher = new ClientZkAuthOperations(serverPublicParams);
- ClientZkGroupCipher clientZkGroupCipher = new ClientZkGroupCipher (groupSecretParams );
- AuthCredentialWithPni authCredential = clientZkAuthCipher.receiveAuthCredentialWithPniAsServiceId(aci, pni, redemptionTime.getEpochSecond(), authCredentialResponse);
+ ClientZkAuthOperations clientZkAuthCipher = new ClientZkAuthOperations(serverPublicParams);
+ ClientZkGroupCipher clientZkGroupCipher = new ClientZkGroupCipher(groupSecretParams);
+ AuthCredentialWithPni authCredential =
+ clientZkAuthCipher.receiveAuthCredentialWithPniAsServiceId(
+ aci, pni, redemptionTime.getEpochSecond(), authCredentialResponse);
// CLIENT - deserialize test
{
- new AuthCredentialWithPniResponse(authCredentialResponse.serialize());
- try {
- byte[] temp = new byte[10];
- new AuthCredentialWithPniResponse(temp);
- throw new AssertionError("Failed to catch invalid AuthCredentialWithPniResponse deserialize 1");
- } catch (InvalidInputException e) {
- // expected
- }
- try {
- new AuthCredentialWithPniResponse(makeBadArray(authCredentialResponse.serialize()));
- throw new AssertionError("Failed to catch invalid AuthCredentialWithPniResponse deserialize 2");
- } catch (InvalidInputException e) {
- // expected
- }
- }
-
+ new AuthCredentialWithPniResponse(authCredentialResponse.serialize());
+ try {
+ byte[] temp = new byte[10];
+ new AuthCredentialWithPniResponse(temp);
+ throw new AssertionError(
+ "Failed to catch invalid AuthCredentialWithPniResponse deserialize 1");
+ } catch (InvalidInputException e) {
+ // expected
+ }
+ try {
+ new AuthCredentialWithPniResponse(makeBadArray(authCredentialResponse.serialize()));
+ throw new AssertionError(
+ "Failed to catch invalid AuthCredentialWithPniResponse deserialize 2");
+ } catch (InvalidInputException e) {
+ // expected
+ }
+ }
+
// CLIENT - verify test
{
- try {
- // Switch ACI and PNI
- clientZkAuthCipher.receiveAuthCredentialWithPniAsServiceId(new Aci(pni.getRawUUID()), new Pni(aci.getRawUUID()), redemptionTime.getEpochSecond(), authCredentialResponse);
- throw new AssertionError("Failed to catch invalid AuthCredentialWithPni 1");
- } catch (VerificationFailedException e) {
- // expected
- }
-
- byte[] temp = authCredentialResponse.serialize();
- temp[1]++;
- AuthCredentialWithPniResponse badResponse = new AuthCredentialWithPniResponse(temp);
- try {
- clientZkAuthCipher.receiveAuthCredentialWithPniAsServiceId(aci, pni, redemptionTime.getEpochSecond(), badResponse);
- throw new AssertionError("Failed to catch invalid AuthCredentialWithPni 2");
- } catch (VerificationFailedException e) {
- // expected
- }
-
- try {
- // Use wrong kind of AuthCredentialWithPni
- clientZkAuthCipher.receiveAuthCredentialWithPniAsAci(aci, pni, redemptionTime.getEpochSecond(), authCredentialResponse);
- throw new AssertionError("Failed to catch AuthCredentialWithServiceId treated as Aci");
- } catch (VerificationFailedException e) {
- // expected
- }
+ try {
+ // Switch ACI and PNI
+ clientZkAuthCipher.receiveAuthCredentialWithPniAsServiceId(
+ new Aci(pni.getRawUUID()),
+ new Pni(aci.getRawUUID()),
+ redemptionTime.getEpochSecond(),
+ authCredentialResponse);
+ throw new AssertionError("Failed to catch invalid AuthCredentialWithPni 1");
+ } catch (VerificationFailedException e) {
+ // expected
+ }
+
+ byte[] temp = authCredentialResponse.serialize();
+ temp[1]++;
+ AuthCredentialWithPniResponse badResponse = new AuthCredentialWithPniResponse(temp);
+ try {
+ clientZkAuthCipher.receiveAuthCredentialWithPniAsServiceId(
+ aci, pni, redemptionTime.getEpochSecond(), badResponse);
+ throw new AssertionError("Failed to catch invalid AuthCredentialWithPni 2");
+ } catch (VerificationFailedException e) {
+ // expected
+ }
+
+ try {
+ // Use wrong kind of AuthCredentialWithPni
+ clientZkAuthCipher.receiveAuthCredentialWithPniAsAci(
+ aci, pni, redemptionTime.getEpochSecond(), authCredentialResponse);
+ throw new AssertionError("Failed to catch AuthCredentialWithServiceId treated as Aci");
+ } catch (VerificationFailedException e) {
+ // expected
+ }
}
// Create and decrypt user entry
UuidCiphertext aciCiphertext = clientZkGroupCipher.encrypt(aci);
- ServiceId aciPlaintext = clientZkGroupCipher.decrypt(aciCiphertext);
+ ServiceId aciPlaintext = clientZkGroupCipher.decrypt(aciCiphertext);
assertEquals(aci, aciPlaintext);
UuidCiphertext pniCiphertext = clientZkGroupCipher.encrypt(pni);
- ServiceId pniPlaintext = clientZkGroupCipher.decrypt(pniCiphertext);
+ ServiceId pniPlaintext = clientZkGroupCipher.decrypt(pniCiphertext);
assertEquals(pni, pniPlaintext);
// CLIENT - Create presentation
- AuthCredentialPresentation presentation = clientZkAuthCipher.createAuthCredentialPresentation(createSecureRandom(TEST_ARRAY_32_5), groupSecretParams, authCredential);
- assertEquals(presentation.serialize()[0], 2); // Check V3 (versions start from 1 but are encoded starting from 0)
+ AuthCredentialPresentation presentation =
+ clientZkAuthCipher.createAuthCredentialPresentation(
+ createSecureRandom(TEST_ARRAY_32_5), groupSecretParams, authCredential);
+ assertEquals(
+ presentation.serialize()[0],
+ 2); // Check V3 (versions start from 1 but are encoded starting from 0)
assertEquals(presentation.getVersion(), AuthCredentialPresentation.Version.V3);
// CLIENT - deserialize test
{
- new AuthCredentialPresentation(presentation.serialize());
- byte[] temp = new byte[10];
- try {
- new AuthCredentialPresentation(temp);
- throw new AssertionError("Failed to catch invalid AuthCredentialPresentation deserialize 1");
- } catch (InvalidInputException e) {
- // expected
- }
- try {
- new AuthCredentialPresentation(makeBadArray(presentation.serialize()));
- throw new AssertionError("Failed to catch invalid AuthCredentialPresentation deserialize 2");
- } catch (InvalidInputException e) {
- // expected
- }
+ new AuthCredentialPresentation(presentation.serialize());
+ byte[] temp = new byte[10];
+ try {
+ new AuthCredentialPresentation(temp);
+ throw new AssertionError(
+ "Failed to catch invalid AuthCredentialPresentation deserialize 1");
+ } catch (InvalidInputException e) {
+ // expected
+ }
+ try {
+ new AuthCredentialPresentation(makeBadArray(presentation.serialize()));
+ throw new AssertionError(
+ "Failed to catch invalid AuthCredentialPresentation deserialize 2");
+ } catch (InvalidInputException e) {
+ // expected
+ }
}
// SERVER - Verify presentation, using times at the edge of the acceptable window
@@ -531,73 +595,85 @@ public void testAuthWithPniIntegration() throws VerificationFailedException, Inv
assertArrayEquals(pniCiphertext.serialize(), presentation.getPniCiphertext().serialize());
assertEquals(presentation.getRedemptionTime(), redemptionTime);
- serverZkAuth.verifyAuthCredentialPresentation(groupPublicParams, presentation, redemptionTime.minus(1, ChronoUnit.DAYS));
- serverZkAuth.verifyAuthCredentialPresentation(groupPublicParams, presentation, redemptionTime.plus(2, ChronoUnit.DAYS));
+ serverZkAuth.verifyAuthCredentialPresentation(
+ groupPublicParams, presentation, redemptionTime.minus(1, ChronoUnit.DAYS));
+ serverZkAuth.verifyAuthCredentialPresentation(
+ groupPublicParams, presentation, redemptionTime.plus(2, ChronoUnit.DAYS));
try {
- serverZkAuth.verifyAuthCredentialPresentation(groupPublicParams, presentation, redemptionTime.minus(1, ChronoUnit.DAYS).minus(1, ChronoUnit.SECONDS));
- throw new AssertionError("verifyAuthCredentialPresentation should fail #1!");
+ serverZkAuth.verifyAuthCredentialPresentation(
+ groupPublicParams,
+ presentation,
+ redemptionTime.minus(1, ChronoUnit.DAYS).minus(1, ChronoUnit.SECONDS));
+ throw new AssertionError("verifyAuthCredentialPresentation should fail #1!");
} catch (VerificationFailedException e) {
// good
}
try {
- serverZkAuth.verifyAuthCredentialPresentation(groupPublicParams, presentation, redemptionTime.plus(2, ChronoUnit.DAYS).plus(1, ChronoUnit.SECONDS));
- throw new AssertionError("verifyAuthCredentialPresentation should fail #2!");
+ serverZkAuth.verifyAuthCredentialPresentation(
+ groupPublicParams,
+ presentation,
+ redemptionTime.plus(2, ChronoUnit.DAYS).plus(1, ChronoUnit.SECONDS));
+ throw new AssertionError("verifyAuthCredentialPresentation should fail #2!");
} catch (VerificationFailedException e) {
// good
}
try {
- byte[] temp = presentation.serialize();
- temp[3] += 5; // We need a bad presentation that passes deserialization, this seems to work
- AuthCredentialPresentation presentationTemp = new AuthCredentialPresentation(temp);
- serverZkAuth.verifyAuthCredentialPresentation(groupPublicParams, presentationTemp, redemptionTime);
- throw new AssertionError("verifyAuthCredentialPresentation should fail #3!");
+ byte[] temp = presentation.serialize();
+ temp[3] += 5; // We need a bad presentation that passes deserialization, this seems to work
+ AuthCredentialPresentation presentationTemp = new AuthCredentialPresentation(temp);
+ serverZkAuth.verifyAuthCredentialPresentation(
+ groupPublicParams, presentationTemp, redemptionTime);
+ throw new AssertionError("verifyAuthCredentialPresentation should fail #3!");
} catch (VerificationFailedException e) {
- // expected
+ // expected
}
try {
- byte[] temp = presentation.serialize();
- temp[0] = 0; // This interprets a V3 as V1, so should fail
- AuthCredentialPresentation presentationTemp = new AuthCredentialPresentation(temp);
- serverZkAuth.verifyAuthCredentialPresentation(groupPublicParams, presentationTemp, redemptionTime);
- throw new AssertionError("verifyAuthCredentialPresentation should fail #4");
+ byte[] temp = presentation.serialize();
+ temp[0] = 0; // This interprets a V3 as V1, so should fail
+ AuthCredentialPresentation presentationTemp = new AuthCredentialPresentation(temp);
+ serverZkAuth.verifyAuthCredentialPresentation(
+ groupPublicParams, presentationTemp, redemptionTime);
+ throw new AssertionError("verifyAuthCredentialPresentation should fail #4");
} catch (InvalidInputException e) {
- // expected
+ // expected
}
try {
- byte[] temp = presentation.serialize();
- temp[0] = 40; // This interprets a V3 as a non-existent version, so should fail
- AuthCredentialPresentation presentationTemp = new AuthCredentialPresentation(temp);
- serverZkAuth.verifyAuthCredentialPresentation(groupPublicParams, presentationTemp, redemptionTime);
- throw new AssertionError("verifyAuthCredentialPresentation should fail #5");
+ byte[] temp = presentation.serialize();
+ temp[0] = 40; // This interprets a V3 as a non-existent version, so should fail
+ AuthCredentialPresentation presentationTemp = new AuthCredentialPresentation(temp);
+ serverZkAuth.verifyAuthCredentialPresentation(
+ groupPublicParams, presentationTemp, redemptionTime);
+ throw new AssertionError("verifyAuthCredentialPresentation should fail #5");
} catch (InvalidInputException e) {
- // expected
+ // expected
}
-
}
@Test
- public void testAuthWithPniAsAciIntegration() throws VerificationFailedException, InvalidInputException {
+ public void testAuthWithPniAsAciIntegration()
+ throws VerificationFailedException, InvalidInputException {
- Aci aci = new Aci(TEST_UUID);
- Pni pni = new Pni(TEST_UUID_1);
+ Aci aci = new Aci(TEST_UUID);
+ Pni pni = new Pni(TEST_UUID_1);
Instant redemptionTime = Instant.now().truncatedTo(ChronoUnit.DAYS);
// Generate keys (client's are per-group, server's are not)
// ---
// SERVER
- ServerSecretParams serverSecretParams = ServerSecretParams.generate(createSecureRandom(TEST_ARRAY_32));
+ ServerSecretParams serverSecretParams =
+ ServerSecretParams.generate(createSecureRandom(TEST_ARRAY_32));
ServerPublicParams serverPublicParams = serverSecretParams.getPublicParams();
- ServerZkAuthOperations serverZkAuth = new ServerZkAuthOperations(serverSecretParams);
+ ServerZkAuthOperations serverZkAuth = new ServerZkAuthOperations(serverSecretParams);
// CLIENT
- GroupMasterKey masterKey = new GroupMasterKey(TEST_ARRAY_32_1);
+ GroupMasterKey masterKey = new GroupMasterKey(TEST_ARRAY_32_1);
GroupSecretParams groupSecretParams = GroupSecretParams.deriveFromMasterKey(masterKey);
assertArrayEquals(groupSecretParams.getMasterKey().serialize(), masterKey.serialize());
@@ -606,37 +682,46 @@ public void testAuthWithPniAsAciIntegration() throws VerificationFailedException
// SERVER
// Issue credential
- AuthCredentialWithPniResponse authCredentialResponse = serverZkAuth.issueAuthCredentialWithPniAsAci(createSecureRandom(TEST_ARRAY_32_2), aci, pni, redemptionTime);
+ AuthCredentialWithPniResponse authCredentialResponse =
+ serverZkAuth.issueAuthCredentialWithPniAsAci(
+ createSecureRandom(TEST_ARRAY_32_2), aci, pni, redemptionTime);
// CLIENT
// Receive credential
- ClientZkAuthOperations clientZkAuthCipher = new ClientZkAuthOperations(serverPublicParams);
- ClientZkGroupCipher clientZkGroupCipher = new ClientZkGroupCipher (groupSecretParams );
- AuthCredentialWithPni authCredential = clientZkAuthCipher.receiveAuthCredentialWithPniAsAci(aci, pni, redemptionTime.getEpochSecond(), authCredentialResponse);
+ ClientZkAuthOperations clientZkAuthCipher = new ClientZkAuthOperations(serverPublicParams);
+ ClientZkGroupCipher clientZkGroupCipher = new ClientZkGroupCipher(groupSecretParams);
+ AuthCredentialWithPni authCredential =
+ clientZkAuthCipher.receiveAuthCredentialWithPniAsAci(
+ aci, pni, redemptionTime.getEpochSecond(), authCredentialResponse);
// CLIENT - verify test
{
- try {
- // Use wrong kind of AuthCredentialWithPni
- clientZkAuthCipher.receiveAuthCredentialWithPniAsServiceId(aci, pni, redemptionTime.getEpochSecond(), authCredentialResponse);
- throw new AssertionError("Failed to catch AuthCredentialWithPniAsAci treated as ServiceId");
- } catch (VerificationFailedException e) {
- // expected
- }
+ try {
+ // Use wrong kind of AuthCredentialWithPni
+ clientZkAuthCipher.receiveAuthCredentialWithPniAsServiceId(
+ aci, pni, redemptionTime.getEpochSecond(), authCredentialResponse);
+ throw new AssertionError("Failed to catch AuthCredentialWithPniAsAci treated as ServiceId");
+ } catch (VerificationFailedException e) {
+ // expected
+ }
}
// Create and decrypt user entry
UuidCiphertext aciCiphertext = clientZkGroupCipher.encrypt(aci);
- ServiceId aciPlaintext = clientZkGroupCipher.decrypt(aciCiphertext);
+ ServiceId aciPlaintext = clientZkGroupCipher.decrypt(aciCiphertext);
assertEquals(aci, aciPlaintext);
- Aci pniAsAci = new Aci(pni.getRawUUID());
+ Aci pniAsAci = new Aci(pni.getRawUUID());
UuidCiphertext pniCiphertext = clientZkGroupCipher.encrypt(pniAsAci);
- ServiceId pniPlaintext = clientZkGroupCipher.decrypt(pniCiphertext);
+ ServiceId pniPlaintext = clientZkGroupCipher.decrypt(pniCiphertext);
assertEquals(pniAsAci, pniPlaintext);
// CLIENT - Create presentation
- AuthCredentialPresentation presentation = clientZkAuthCipher.createAuthCredentialPresentation(createSecureRandom(TEST_ARRAY_32_5), groupSecretParams, authCredential);
- assertEquals(presentation.serialize()[0], 2); // Check V3 (versions start from 1 but are encoded starting from 0)
+ AuthCredentialPresentation presentation =
+ clientZkAuthCipher.createAuthCredentialPresentation(
+ createSecureRandom(TEST_ARRAY_32_5), groupSecretParams, authCredential);
+ assertEquals(
+ presentation.serialize()[0],
+ 2); // Check V3 (versions start from 1 but are encoded starting from 0)
assertEquals(presentation.getVersion(), AuthCredentialPresentation.Version.V3);
// SERVER - Verify presentation, using times at the edge of the acceptable window
@@ -644,179 +729,218 @@ public void testAuthWithPniAsAciIntegration() throws VerificationFailedException
assertArrayEquals(pniCiphertext.serialize(), presentation.getPniCiphertext().serialize());
assertEquals(presentation.getRedemptionTime(), redemptionTime);
- serverZkAuth.verifyAuthCredentialPresentation(groupPublicParams, presentation, redemptionTime.minus(1, ChronoUnit.DAYS));
- serverZkAuth.verifyAuthCredentialPresentation(groupPublicParams, presentation, redemptionTime.plus(2, ChronoUnit.DAYS));
+ serverZkAuth.verifyAuthCredentialPresentation(
+ groupPublicParams, presentation, redemptionTime.minus(1, ChronoUnit.DAYS));
+ serverZkAuth.verifyAuthCredentialPresentation(
+ groupPublicParams, presentation, redemptionTime.plus(2, ChronoUnit.DAYS));
try {
- serverZkAuth.verifyAuthCredentialPresentation(groupPublicParams, presentation, redemptionTime.minus(1, ChronoUnit.DAYS).minus(1, ChronoUnit.SECONDS));
- throw new AssertionError("verifyAuthCredentialPresentation should fail #1!");
+ serverZkAuth.verifyAuthCredentialPresentation(
+ groupPublicParams,
+ presentation,
+ redemptionTime.minus(1, ChronoUnit.DAYS).minus(1, ChronoUnit.SECONDS));
+ throw new AssertionError("verifyAuthCredentialPresentation should fail #1!");
} catch (VerificationFailedException e) {
// good
}
try {
- serverZkAuth.verifyAuthCredentialPresentation(groupPublicParams, presentation, redemptionTime.plus(2, ChronoUnit.DAYS).plus(1, ChronoUnit.SECONDS));
- throw new AssertionError("verifyAuthCredentialPresentation should fail #2!");
+ serverZkAuth.verifyAuthCredentialPresentation(
+ groupPublicParams,
+ presentation,
+ redemptionTime.plus(2, ChronoUnit.DAYS).plus(1, ChronoUnit.SECONDS));
+ throw new AssertionError("verifyAuthCredentialPresentation should fail #2!");
} catch (VerificationFailedException e) {
// good
}
try {
- byte[] temp = presentation.serialize();
- temp[3] += 5; // We need a bad presentation that passes deserialization, this seems to work
- AuthCredentialPresentation presentationTemp = new AuthCredentialPresentation(temp);
- serverZkAuth.verifyAuthCredentialPresentation(groupPublicParams, presentationTemp, redemptionTime);
- throw new AssertionError("verifyAuthCredentialPresentation should fail #3!");
+ byte[] temp = presentation.serialize();
+ temp[3] += 5; // We need a bad presentation that passes deserialization, this seems to work
+ AuthCredentialPresentation presentationTemp = new AuthCredentialPresentation(temp);
+ serverZkAuth.verifyAuthCredentialPresentation(
+ groupPublicParams, presentationTemp, redemptionTime);
+ throw new AssertionError("verifyAuthCredentialPresentation should fail #3!");
} catch (VerificationFailedException e) {
- // expected
+ // expected
}
}
@Test
- public void testExpiringProfileKeyIntegration() throws VerificationFailedException, InvalidInputException, UnsupportedEncodingException {
+ public void testExpiringProfileKeyIntegration()
+ throws VerificationFailedException, InvalidInputException, UnsupportedEncodingException {
- Aci userId = new Aci(TEST_UUID);
+ Aci userId = new Aci(TEST_UUID);
// Generate keys (client's are per-group, server's are not)
// ---
// SERVER
- ServerSecretParams serverSecretParams = ServerSecretParams.generate(createSecureRandom(TEST_ARRAY_32));
+ ServerSecretParams serverSecretParams =
+ ServerSecretParams.generate(createSecureRandom(TEST_ARRAY_32));
ServerPublicParams serverPublicParams = serverSecretParams.getPublicParams();
- ServerZkProfileOperations serverZkProfile = new ServerZkProfileOperations(serverSecretParams);
+ ServerZkProfileOperations serverZkProfile = new ServerZkProfileOperations(serverSecretParams);
// CLIENT
- GroupMasterKey masterKey = new GroupMasterKey(TEST_ARRAY_32_1);
+ GroupMasterKey masterKey = new GroupMasterKey(TEST_ARRAY_32_1);
GroupSecretParams groupSecretParams = GroupSecretParams.deriveFromMasterKey(masterKey);
assertArrayEquals(groupSecretParams.getMasterKey().serialize(), masterKey.serialize());
- GroupPublicParams groupPublicParams = groupSecretParams.getPublicParams();
- ClientZkProfileOperations clientZkProfileCipher = new ClientZkProfileOperations(serverPublicParams);
+ GroupPublicParams groupPublicParams = groupSecretParams.getPublicParams();
+ ClientZkProfileOperations clientZkProfileCipher =
+ new ClientZkProfileOperations(serverPublicParams);
- ProfileKey profileKey = new ProfileKey(TEST_ARRAY_32_1);
+ ProfileKey profileKey = new ProfileKey(TEST_ARRAY_32_1);
ProfileKeyCommitment profileKeyCommitment = profileKey.getCommitment(userId);
// Create context and request
- ProfileKeyCredentialRequestContext context = clientZkProfileCipher.createProfileKeyCredentialRequestContext(createSecureRandom(TEST_ARRAY_32_3), userId, profileKey);
- ProfileKeyCredentialRequest request = context.getRequest();
+ ProfileKeyCredentialRequestContext context =
+ clientZkProfileCipher.createProfileKeyCredentialRequestContext(
+ createSecureRandom(TEST_ARRAY_32_3), userId, profileKey);
+ ProfileKeyCredentialRequest request = context.getRequest();
- // SERVER
+ // SERVER
Instant expiration = Instant.now().truncatedTo(ChronoUnit.DAYS).plus(5, ChronoUnit.DAYS);
- ExpiringProfileKeyCredentialResponse response = serverZkProfile.issueExpiringProfileKeyCredential(createSecureRandom(TEST_ARRAY_32_4), request, userId, profileKeyCommitment, expiration);
+ ExpiringProfileKeyCredentialResponse response =
+ serverZkProfile.issueExpiringProfileKeyCredential(
+ createSecureRandom(TEST_ARRAY_32_4), request, userId, profileKeyCommitment, expiration);
// SERVER - verification test
{
- byte[] temp = request.serialize();
- temp[4]++; // We need a bad presentation that passes deserialization, this seems to work
- ProfileKeyCredentialRequest badRequest = new ProfileKeyCredentialRequest(temp);
- try {
- serverZkProfile.issueExpiringProfileKeyCredential(createSecureRandom(TEST_ARRAY_32_4), badRequest, userId, profileKeyCommitment, expiration);
- throw new AssertionError("Failed to catch invalid ProfileKeyCredentialRequest");
- } catch (VerificationFailedException e) {
- // expected
- }
- }
-
+ byte[] temp = request.serialize();
+ temp[4]++; // We need a bad presentation that passes deserialization, this seems to work
+ ProfileKeyCredentialRequest badRequest = new ProfileKeyCredentialRequest(temp);
+ try {
+ serverZkProfile.issueExpiringProfileKeyCredential(
+ createSecureRandom(TEST_ARRAY_32_4),
+ badRequest,
+ userId,
+ profileKeyCommitment,
+ expiration);
+ throw new AssertionError("Failed to catch invalid ProfileKeyCredentialRequest");
+ } catch (VerificationFailedException e) {
+ // expected
+ }
+ }
+
// CLIENT
// Gets stored profile credential
- ClientZkGroupCipher clientZkGroupCipher = new ClientZkGroupCipher(groupSecretParams);
- ExpiringProfileKeyCredential profileKeyCredential = clientZkProfileCipher.receiveExpiringProfileKeyCredential(context, response);
+ ClientZkGroupCipher clientZkGroupCipher = new ClientZkGroupCipher(groupSecretParams);
+ ExpiringProfileKeyCredential profileKeyCredential =
+ clientZkProfileCipher.receiveExpiringProfileKeyCredential(context, response);
// Create encrypted UID and profile key
UuidCiphertext uuidCiphertext = clientZkGroupCipher.encrypt(userId);
- ServiceId plaintext = clientZkGroupCipher.decrypt(uuidCiphertext);
+ ServiceId plaintext = clientZkGroupCipher.decrypt(uuidCiphertext);
assertEquals(plaintext, userId);
- ProfileKeyCiphertext profileKeyCiphertext = clientZkGroupCipher.encryptProfileKey(profileKey, userId);
- ProfileKey decryptedProfileKey = clientZkGroupCipher.decryptProfileKey(profileKeyCiphertext, userId);
+ ProfileKeyCiphertext profileKeyCiphertext =
+ clientZkGroupCipher.encryptProfileKey(profileKey, userId);
+ ProfileKey decryptedProfileKey =
+ clientZkGroupCipher.decryptProfileKey(profileKeyCiphertext, userId);
assertArrayEquals(profileKey.serialize(), decryptedProfileKey.serialize());
assertEquals(expiration, profileKeyCredential.getExpirationTime());
- ProfileKeyCredentialPresentation presentation = clientZkProfileCipher.createProfileKeyCredentialPresentation(createSecureRandom(TEST_ARRAY_32_5), groupSecretParams, profileKeyCredential);
- assertEquals(presentation.serialize()[0], 2); // Check V3 (versions start from 1 but are encoded starting from 0)
+ ProfileKeyCredentialPresentation presentation =
+ clientZkProfileCipher.createProfileKeyCredentialPresentation(
+ createSecureRandom(TEST_ARRAY_32_5), groupSecretParams, profileKeyCredential);
+ assertEquals(
+ presentation.serialize()[0],
+ 2); // Check V3 (versions start from 1 but are encoded starting from 0)
assertEquals(presentation.getVersion(), ProfileKeyCredentialPresentation.Version.V3);
// Verify presentation
serverZkProfile.verifyProfileKeyCredentialPresentation(groupPublicParams, presentation);
- serverZkProfile.verifyProfileKeyCredentialPresentation(groupPublicParams, presentation, expiration.minusSeconds(5));
+ serverZkProfile.verifyProfileKeyCredentialPresentation(
+ groupPublicParams, presentation, expiration.minusSeconds(5));
UuidCiphertext uuidCiphertextRecv = presentation.getUuidCiphertext();
assertArrayEquals(uuidCiphertext.serialize(), uuidCiphertextRecv.serialize());
try {
- serverZkProfile.verifyProfileKeyCredentialPresentation(groupPublicParams, presentation, expiration);
- throw new AssertionError("credential expired 1");
+ serverZkProfile.verifyProfileKeyCredentialPresentation(
+ groupPublicParams, presentation, expiration);
+ throw new AssertionError("credential expired 1");
} catch (VerificationFailedException e) {
- // expected
+ // expected
}
try {
- serverZkProfile.verifyProfileKeyCredentialPresentation(groupPublicParams, presentation, expiration.plusSeconds(5));
- throw new AssertionError("credential expired 2");
+ serverZkProfile.verifyProfileKeyCredentialPresentation(
+ groupPublicParams, presentation, expiration.plusSeconds(5));
+ throw new AssertionError("credential expired 2");
} catch (VerificationFailedException e) {
- // expected
+ // expected
}
try {
- byte[] temp = presentation.serialize();
- temp[2] += 8; // We need a bad presentation that passes deserializaton, this seems to work
- ProfileKeyCredentialPresentation presentationTemp = new ProfileKeyCredentialPresentation(temp);
- serverZkProfile.verifyProfileKeyCredentialPresentation(groupPublicParams, presentationTemp);
- throw new AssertionError("verifyProfileKeyCredentialPresentation should fail 1");
+ byte[] temp = presentation.serialize();
+ temp[2] += 8; // We need a bad presentation that passes deserializaton, this seems to work
+ ProfileKeyCredentialPresentation presentationTemp =
+ new ProfileKeyCredentialPresentation(temp);
+ serverZkProfile.verifyProfileKeyCredentialPresentation(groupPublicParams, presentationTemp);
+ throw new AssertionError("verifyProfileKeyCredentialPresentation should fail 1");
} catch (VerificationFailedException e) {
- // expected
+ // expected
}
try {
- byte[] temp = presentation.serialize();
- temp[0] = 0; // This interprets a V3 as V1, so should fail
- ProfileKeyCredentialPresentation presentationTemp = new ProfileKeyCredentialPresentation(temp);
- serverZkProfile.verifyProfileKeyCredentialPresentation(groupPublicParams, presentationTemp);
- throw new AssertionError("verifyProfileKeyCredentialPresentation should fail 2");
+ byte[] temp = presentation.serialize();
+ temp[0] = 0; // This interprets a V3 as V1, so should fail
+ ProfileKeyCredentialPresentation presentationTemp =
+ new ProfileKeyCredentialPresentation(temp);
+ serverZkProfile.verifyProfileKeyCredentialPresentation(groupPublicParams, presentationTemp);
+ throw new AssertionError("verifyProfileKeyCredentialPresentation should fail 2");
} catch (VerificationFailedException e) {
- // expected
+ // expected
}
try {
- byte[] temp = presentation.serialize();
- temp[0] = 40; // This interprets a V3 as a non-existent version, so should fail
- ProfileKeyCredentialPresentation presentationTemp = new ProfileKeyCredentialPresentation(temp);
- serverZkProfile.verifyProfileKeyCredentialPresentation(groupPublicParams, presentationTemp);
- throw new AssertionError("verifyProfileKeyCredentialPresentation should fail 3");
+ byte[] temp = presentation.serialize();
+ temp[0] = 40; // This interprets a V3 as a non-existent version, so should fail
+ ProfileKeyCredentialPresentation presentationTemp =
+ new ProfileKeyCredentialPresentation(temp);
+ serverZkProfile.verifyProfileKeyCredentialPresentation(groupPublicParams, presentationTemp);
+ throw new AssertionError("verifyProfileKeyCredentialPresentation should fail 3");
} catch (InvalidInputException e) {
- // expected
+ // expected
}
// Test that we can encode as a V1 presentation, even though it won't verify.
- ProfileKeyCredentialPresentation v1Presentation = new ProfileKeyCredentialPresentation(presentation.getStructurallyValidV1PresentationBytes());
+ ProfileKeyCredentialPresentation v1Presentation =
+ new ProfileKeyCredentialPresentation(
+ presentation.getStructurallyValidV1PresentationBytes());
assertEquals(v1Presentation.getUuidCiphertext(), presentation.getUuidCiphertext());
assertEquals(v1Presentation.getProfileKeyCiphertext(), presentation.getProfileKeyCiphertext());
try {
- serverZkProfile.verifyProfileKeyCredentialPresentation(groupPublicParams, v1Presentation);
+ serverZkProfile.verifyProfileKeyCredentialPresentation(groupPublicParams, v1Presentation);
} catch (VerificationFailedException e) {
- // expected
+ // expected
}
}
@Test
public void testServerSignatures() throws VerificationFailedException {
- ServerSecretParams serverSecretParams = ServerSecretParams.generate(createSecureRandom(TEST_ARRAY_32));
+ ServerSecretParams serverSecretParams =
+ ServerSecretParams.generate(createSecureRandom(TEST_ARRAY_32));
ServerPublicParams serverPublicParams = serverSecretParams.getPublicParams();
byte[] message = TEST_ARRAY_32_1;
- NotarySignature signature = serverSecretParams.sign(createSecureRandom(TEST_ARRAY_32_2), message);
+ NotarySignature signature =
+ serverSecretParams.sign(createSecureRandom(TEST_ARRAY_32_2), message);
serverPublicParams.verifySignature(message, signature);
assertByteArray(
-"87d354564d35ef91edba851e0815612e864c227a0471d50c270698604406d003a55473f576cf241fc6b41c6b16e5e63b333c02fe4a33858022fdd7a4ab367b06", signature.serialize());
+ "87d354564d35ef91edba851e0815612e864c227a0471d50c270698604406d003a55473f576cf241fc6b41c6b16e5e63b333c02fe4a33858022fdd7a4ab367b06",
+ signature.serialize());
byte[] alteredMessage = message.clone();
alteredMessage[0] ^= 1;
try {
- serverPublicParams.verifySignature(alteredMessage, signature);
- throw new AssertionError("signature validation should have failed!");
+ serverPublicParams.verifySignature(alteredMessage, signature);
+ throw new AssertionError("signature validation should have failed!");
} catch (VerificationFailedException e) {
// good
}
@@ -824,9 +948,11 @@ public void testServerSignatures() throws VerificationFailedException {
@Test
public void testGroupIdentifier() throws VerificationFailedException {
- GroupSecretParams groupSecretParams = GroupSecretParams.generate(createSecureRandom(TEST_ARRAY_32));
+ GroupSecretParams groupSecretParams =
+ GroupSecretParams.generate(createSecureRandom(TEST_ARRAY_32));
GroupPublicParams groupPublicParams = groupSecretParams.getPublicParams();
- //assertByteArray("31f2c60f86f4c5996e9e2568355591d9", groupPublicParams.getGroupIdentifier().serialize());
+ // assertByteArray("31f2c60f86f4c5996e9e2568355591d9",
+ // groupPublicParams.getGroupIdentifier().serialize());
}
@Test(expected = InvalidInputException.class)
@@ -868,16 +994,21 @@ public void testWrongSizeSerializedInfallible() throws InvalidInputException {
@Test
public void testBlobEncryption() throws InvalidInputException, VerificationFailedException {
- GroupMasterKey masterKey = new GroupMasterKey(TEST_ARRAY_32_1);
+ GroupMasterKey masterKey = new GroupMasterKey(TEST_ARRAY_32_1);
GroupSecretParams groupSecretParams = GroupSecretParams.deriveFromMasterKey(masterKey);
ClientZkGroupCipher clientZkGroupCipher = new ClientZkGroupCipher(groupSecretParams);
byte[] plaintext = Hex.fromStringCondensedAssert("0102030405060708111213141516171819");
- byte[] ciphertext = Hex.fromStringCondensedAssert("dd4d032ca9bb75a4a78541b90cb4e95743f3b0dabfc7e11101b098e34f6cf6513940a04c1f20a302692afdc7087f10196000");
+ byte[] ciphertext =
+ Hex.fromStringCondensedAssert(
+ "dd4d032ca9bb75a4a78541b90cb4e95743f3b0dabfc7e11101b098e34f6cf6513940a04c1f20a302692afdc7087f10196000");
- byte[] ciphertextPaddedWith257 = Hex.fromStringCondensedAssert("5cb5b7bff06e85d929f3511fd194e638cf32a47663868bc8e64d98fb1bbe435ebd21c763ce2d42e85a1b2c169f12f9818ddadcf4b491398b7c5d46a224e1582749f5e2a4a2294caaaaab843a1b7cf6426fd543d09ff32a4ba5f319ca4442b4da34b3e2b5b4f8a52fdc4b484ea86b33db3ebb758dbd9614178f0e4e1f9b2b914f1e786936b62ed2b58b7ae3cb3e7ae0835b9516959837406662b85eac740cef83b60b5aaeaaab95643c2bef8ce87358fabff9d690052beb9e52d0c947e7c986b2f3ce3b7161cec72c08e2c4ade3debe3792d736c0457bc352afb8b6caa48a5b92c1ec05ba808ba8f94c6572ebbf29818912344987573de419dbcc7f1ea0e4b2dd4077b76b381819747ac332e46fa23abfc3338e2f4b081a8a53cba0988eef116764d944f1ce3f20a302692afdc7087f10196000");
+ byte[] ciphertextPaddedWith257 =
+ Hex.fromStringCondensedAssert(
+ "5cb5b7bff06e85d929f3511fd194e638cf32a47663868bc8e64d98fb1bbe435ebd21c763ce2d42e85a1b2c169f12f9818ddadcf4b491398b7c5d46a224e1582749f5e2a4a2294caaaaab843a1b7cf6426fd543d09ff32a4ba5f319ca4442b4da34b3e2b5b4f8a52fdc4b484ea86b33db3ebb758dbd9614178f0e4e1f9b2b914f1e786936b62ed2b58b7ae3cb3e7ae0835b9516959837406662b85eac740cef83b60b5aaeaaab95643c2bef8ce87358fabff9d690052beb9e52d0c947e7c986b2f3ce3b7161cec72c08e2c4ade3debe3792d736c0457bc352afb8b6caa48a5b92c1ec05ba808ba8f94c6572ebbf29818912344987573de419dbcc7f1ea0e4b2dd4077b76b381819747ac332e46fa23abfc3338e2f4b081a8a53cba0988eef116764d944f1ce3f20a302692afdc7087f10196000");
- byte[] ciphertext2 = clientZkGroupCipher.encryptBlob(createSecureRandom(TEST_ARRAY_32_2), plaintext);
+ byte[] ciphertext2 =
+ clientZkGroupCipher.encryptBlob(createSecureRandom(TEST_ARRAY_32_2), plaintext);
byte[] plaintext2 = clientZkGroupCipher.decryptBlob(ciphertext2);
assertArrayEquals(plaintext, plaintext2);
@@ -891,7 +1022,7 @@ public void testBlobEncryption() throws InvalidInputException, VerificationFaile
public void testDeriveAccessKey() throws Exception {
byte[] expectedAccessKey = Hex.fromStringCondensedAssert("5a723acee52c5ea02b92a3a360c09595");
byte[] profileKey = new byte[32];
- Arrays.fill(profileKey, (byte)0x02);
+ Arrays.fill(profileKey, (byte) 0x02);
byte[] result = new ProfileKey(profileKey).deriveAccessKey();
assertArrayEquals(result, expectedAccessKey);
@@ -902,6 +1033,4 @@ private void assertByteArray(String expectedAsHex, byte[] actual) {
assertArrayEquals(expectedBytes, actual);
}
-
}
-
diff --git a/java/code_size.json b/java/code_size.json
index 60b436a6d3..5fd4b70e2f 100644
--- a/java/code_size.json
+++ b/java/code_size.json
@@ -59,5 +59,7 @@
{ "version": "0.29.0", "size": 2993872 },
{ "version": "0.30.0", "size": 2996056 },
{ "version": "0.30.2", "size": 2993944 },
- { "version": "0.31.0", "size": 2984472 }
+ { "version": "0.31.0", "size": 2984472 },
+ { "version": "0.32.0", "size": 2989712 },
+ { "version": "0.32.1", "size": 3058720 }
]
diff --git a/java/license_header.txt b/java/license_header.txt
new file mode 100644
index 0000000000..b57f82c081
--- /dev/null
+++ b/java/license_header.txt
@@ -0,0 +1,5 @@
+//
+// Copyright $YEAR Signal Messenger, LLC.
+// SPDX-License-Identifier: AGPL-3.0-only
+//
+
diff --git a/java/server/build.gradle b/java/server/build.gradle
index b92ed4b2ea..b97d6efc9d 100644
--- a/java/server/build.gradle
+++ b/java/server/build.gradle
@@ -7,8 +7,6 @@ plugins {
sourceCompatibility = 1.8
archivesBaseName = "libsignal-server"
-version = version_number
-group = group_info
repositories {
mavenCentral()
@@ -60,12 +58,6 @@ java {
processResources {
// TODO: Build a different variant of the JNI library for server.
dependsOn ':makeJniLibrariesDesktop'
- dependsOn ':downloadNonLinuxLibraries'
- gradle.taskGraph.whenReady { graph ->
- if (graph.hasTask(":server:publish")) {
- tasks.getByPath(":downloadNonLinuxLibraries").enabled = true
- }
- }
}
// MARK: Publishing
@@ -102,17 +94,9 @@ publishing {
}
}
}
- repositories {
- maven {
- url = getReleaseRepositoryUrl()
- credentials {
- username = getRepositoryUsername()
- password = getRepositoryPassword()
- }
- }
- }
}
+setUpSigningKey(signing)
signing {
required { isReleaseBuild() && gradle.taskGraph.hasTask(":server:publish") }
sign publishing.publications.mavenJava
diff --git a/java/server/src/main/java/org/signal/libsignal/cds2/Cds2Metrics.java b/java/server/src/main/java/org/signal/libsignal/cds2/Cds2Metrics.java
index d30c8b592c..3bd36adf86 100644
--- a/java/server/src/main/java/org/signal/libsignal/cds2/Cds2Metrics.java
+++ b/java/server/src/main/java/org/signal/libsignal/cds2/Cds2Metrics.java
@@ -5,32 +5,25 @@
package org.signal.libsignal.cds2;
+import java.util.Map;
import org.signal.libsignal.attest.AttestationDataException;
import org.signal.libsignal.internal.Native;
-import org.signal.libsignal.internal.NativeHandleGuard;
-
-import java.util.Optional;
-import java.util.HashMap;
-import java.util.Map;
-import java.time.Instant;
public final class Cds2Metrics {
- private Cds2Metrics() {}
+ private Cds2Metrics() {}
- /**
- * Parse a cds2 attestation response (ClientHandshakeStart) and return
- * supplemental information extracted from the response's evidence and
- * endorsements.
- *
- * @param attestationMessage A ClientHandshakeStart message
- *
- * @throws AttestationDataException if the attestationMessage cannot be parsed
- */
- public static Map extract(final byte[] attestationMessage) throws AttestationDataException {
- @SuppressWarnings("unchecked")
- Map result = Native.Cds2Metrics_extract(attestationMessage);
- return result;
- }
+ /**
+ * Parse a cds2 attestation response (ClientHandshakeStart) and return supplemental information
+ * extracted from the response's evidence and endorsements.
+ *
+ * @param attestationMessage A ClientHandshakeStart message
+ * @throws AttestationDataException if the attestationMessage cannot be parsed
+ */
+ public static Map extract(final byte[] attestationMessage)
+ throws AttestationDataException {
+ @SuppressWarnings("unchecked")
+ Map result = Native.Cds2Metrics_extract(attestationMessage);
+ return result;
+ }
}
-
diff --git a/java/server/src/test/java/org/signal/libsignal/cds2/Cds2MetricsTest.java b/java/server/src/test/java/org/signal/libsignal/cds2/Cds2MetricsTest.java
index 89a1e81828..99c09aef2a 100644
--- a/java/server/src/test/java/org/signal/libsignal/cds2/Cds2MetricsTest.java
+++ b/java/server/src/test/java/org/signal/libsignal/cds2/Cds2MetricsTest.java
@@ -5,38 +5,37 @@
package org.signal.libsignal.cds2;
-import org.signal.libsignal.attest.AttestationDataException;
-
-import junit.framework.TestCase;
import java.io.InputStream;
-import java.util.Map;
import java.util.Arrays;
-
+import java.util.Map;
+import junit.framework.TestCase;
+import org.signal.libsignal.attest.AttestationDataException;
public class Cds2MetricsTest extends TestCase {
- private byte[] attestationMsg;
- protected void setUp() throws Exception {
- super.setUp();
+ private byte[] attestationMsg;
- // Test data should be ~14k
- attestationMsg = new byte[15_000];
+ protected void setUp() throws Exception {
+ super.setUp();
- try (InputStream stream = getClass().getResourceAsStream("clienthandshakestart.data")) {
- assert stream != null;
- int read = stream.read(attestationMsg);
- // should be empty
- assert(stream.read() == -1);
- attestationMsg = Arrays.copyOf(attestationMsg, read);
- }
- }
+ // Test data should be ~14k
+ attestationMsg = new byte[15_000];
- public void testValidMetrics() throws AttestationDataException {
- Map metrics = Cds2Metrics.extract(attestationMsg);
- // 2022-08-14 02:31:29 UTC
- assertEquals(metrics.get("tcb_info_expiration_ts").longValue(), 1658440468);
- // May 21 10:50:10 2018 GMT
- assertEquals(metrics.get("tcb_signer_not_before_ts").longValue(), 1526899810);
- // May 21 10:50:10 2025 GMT
- assertEquals(metrics.get("tcb_signer_not_after_ts").longValue(), 1747824610);
+ try (InputStream stream = getClass().getResourceAsStream("clienthandshakestart.data")) {
+ assert stream != null;
+ int read = stream.read(attestationMsg);
+ // should be empty
+ assert (stream.read() == -1);
+ attestationMsg = Arrays.copyOf(attestationMsg, read);
}
+ }
+
+ public void testValidMetrics() throws AttestationDataException {
+ Map metrics = Cds2Metrics.extract(attestationMsg);
+ // 2022-08-14 02:31:29 UTC
+ assertEquals(metrics.get("tcb_info_expiration_ts").longValue(), 1658440468);
+ // May 21 10:50:10 2018 GMT
+ assertEquals(metrics.get("tcb_signer_not_before_ts").longValue(), 1526899810);
+ // May 21 10:50:10 2025 GMT
+ assertEquals(metrics.get("tcb_signer_not_after_ts").longValue(), 1747824610);
+ }
}
diff --git a/java/settings.gradle b/java/settings.gradle
index fad5fb463e..6d717998ea 100644
--- a/java/settings.gradle
+++ b/java/settings.gradle
@@ -6,7 +6,9 @@ pluginManagement {
}
}
-include ':client', ':server'
+rootProject.name = 'libsignal'
+
+include ':client', ':server', ':shared'
if (hasProperty('skipAndroid')) {
// Do nothing
diff --git a/java/shared/build.gradle b/java/shared/build.gradle
new file mode 100644
index 0000000000..fafefb035e
--- /dev/null
+++ b/java/shared/build.gradle
@@ -0,0 +1,9 @@
+// Source files from 'shared' folder is included in both server and client's
+// 'srcSets' and does not need to be its own Gradle subproject. However,
+// 'spotless' plugin does not allow formatting files outside the 'projectDir'.
+// For this reason we turn 'shared' into a Gradle subproject, but _do not_ set
+// it up as 'java'.
+repositories {
+ mavenCentral()
+ mavenLocal()
+}
diff --git a/java/shared/java/org/signal/libsignal/attest/AttestationDataException.java b/java/shared/java/org/signal/libsignal/attest/AttestationDataException.java
index 2a9780e084..0b5280eba3 100644
--- a/java/shared/java/org/signal/libsignal/attest/AttestationDataException.java
+++ b/java/shared/java/org/signal/libsignal/attest/AttestationDataException.java
@@ -1,6 +1,16 @@
+//
+// Copyright 2023 Signal Messenger, LLC.
+// SPDX-License-Identifier: AGPL-3.0-only
+//
+
package org.signal.libsignal.attest;
public class AttestationDataException extends Exception {
- public AttestationDataException(String msg) { super(msg); }
- public AttestationDataException(Throwable t) { super(t); }
+ public AttestationDataException(String msg) {
+ super(msg);
+ }
+
+ public AttestationDataException(Throwable t) {
+ super(t);
+ }
}
diff --git a/java/shared/java/org/signal/libsignal/attest/DcapException.java b/java/shared/java/org/signal/libsignal/attest/DcapException.java
index 9673b3f62b..ca050b8c2a 100644
--- a/java/shared/java/org/signal/libsignal/attest/DcapException.java
+++ b/java/shared/java/org/signal/libsignal/attest/DcapException.java
@@ -1,6 +1,16 @@
+//
+// Copyright 2023 Signal Messenger, LLC.
+// SPDX-License-Identifier: AGPL-3.0-only
+//
+
package org.signal.libsignal.attest;
public class DcapException extends Exception {
- public DcapException(String msg) { super(msg); }
- public DcapException(Throwable t) { super(t); }
+ public DcapException(String msg) {
+ super(msg);
+ }
+
+ public DcapException(Throwable t) {
+ super(t);
+ }
}
diff --git a/java/shared/java/org/signal/libsignal/grpc/GrpcClient.java b/java/shared/java/org/signal/libsignal/grpc/GrpcClient.java
index 04af989314..3c79779b38 100644
--- a/java/shared/java/org/signal/libsignal/grpc/GrpcClient.java
+++ b/java/shared/java/org/signal/libsignal/grpc/GrpcClient.java
@@ -7,7 +7,6 @@
import java.util.List;
import java.util.Map;
-
import org.signal.libsignal.internal.Native;
import org.signal.libsignal.internal.NativeHandleGuard;
@@ -24,7 +23,8 @@ public GrpcClient(String target) {
this.unsafeHandle = Native.GrpcClient_New(target);
}
- @Override @SuppressWarnings("deprecation")
+ @Override
+ @SuppressWarnings("deprecation")
protected void finalize() {
Native.GrpcClient_Destroy(this.unsafeHandle);
}
@@ -33,15 +33,19 @@ public long unsafeNativeHandleWithoutGuard() {
return this.unsafeHandle;
}
- public byte[] sendDirectMessage(String method, String urlFragment, byte[] body, Map> headers) {
- return Native.GrpcClient_SendDirectMessage(this.unsafeHandle, method, urlFragment, body, headers);
+ public byte[] sendDirectMessage(
+ String method, String urlFragment, byte[] body, Map> headers) {
+ return Native.GrpcClient_SendDirectMessage(
+ this.unsafeHandle, method, urlFragment, body, headers);
}
- public void openStream(String uri, Map> headers, GrpcReplyListener replyListener) {
+ public void openStream(
+ String uri, Map> headers, GrpcReplyListener replyListener) {
Native.GrpcClient_OpenStream(this.unsafeHandle, uri, headers, replyListener);
}
- public void sendMessageOnStream(String method, String urlFragment, byte[] body, Map> headers) {
+ public void sendMessageOnStream(
+ String method, String urlFragment, byte[] body, Map> headers) {
Native.GrpcClient_SendMessageOnStream(this.unsafeHandle, method, urlFragment, body, headers);
}
}
diff --git a/java/shared/java/org/signal/libsignal/grpc/GrpcReplyListener.java b/java/shared/java/org/signal/libsignal/grpc/GrpcReplyListener.java
index e5daed5035..3391f5f91d 100644
--- a/java/shared/java/org/signal/libsignal/grpc/GrpcReplyListener.java
+++ b/java/shared/java/org/signal/libsignal/grpc/GrpcReplyListener.java
@@ -1,8 +1,13 @@
+//
+// Copyright 2023 Signal Messenger, LLC.
+// SPDX-License-Identifier: AGPL-3.0-only
+//
+
package org.signal.libsignal.grpc;
public interface GrpcReplyListener {
- void onReply(SignalRpcReply reply);
+ void onReply(SignalRpcReply reply);
- void onError(String message);
+ void onError(String message);
}
diff --git a/java/shared/java/org/signal/libsignal/grpc/SignalRpcReply.java b/java/shared/java/org/signal/libsignal/grpc/SignalRpcReply.java
index 284988df06..a26adc74cc 100644
--- a/java/shared/java/org/signal/libsignal/grpc/SignalRpcReply.java
+++ b/java/shared/java/org/signal/libsignal/grpc/SignalRpcReply.java
@@ -10,8 +10,7 @@ public class SignalRpcReply {
private int statusCode;
private byte[] message;
- public SignalRpcReply() {
- }
+ public SignalRpcReply() {}
public SignalRpcReply(int statusCode, byte[] message) {
this.statusCode = statusCode;
diff --git a/java/shared/java/org/signal/libsignal/internal/Native.java b/java/shared/java/org/signal/libsignal/internal/Native.java
index 567c21ac09..265b8ef73a 100644
--- a/java/shared/java/org/signal/libsignal/internal/Native.java
+++ b/java/shared/java/org/signal/libsignal/internal/Native.java
@@ -488,17 +488,16 @@ private Native() {}
public static native String ServiceId_ServiceIdLog(byte[] value);
public static native String ServiceId_ServiceIdString(byte[] value);
- public static native void SessionBuilder_ProcessPreKeyBundle(long bundle, long protocolAddress, SessionStore sessionStore, IdentityKeyStore identityKeyStore);
+ public static native void SessionBuilder_ProcessPreKeyBundle(long bundle, long protocolAddress, SessionStore sessionStore, IdentityKeyStore identityKeyStore, long now);
public static native byte[] SessionCipher_DecryptPreKeySignalMessage(long message, long protocolAddress, SessionStore sessionStore, IdentityKeyStore identityKeyStore, PreKeyStore prekeyStore, SignedPreKeyStore signedPrekeyStore, KyberPreKeyStore kyberPrekeyStore);
public static native byte[] SessionCipher_DecryptSignalMessage(long message, long protocolAddress, SessionStore sessionStore, IdentityKeyStore identityKeyStore);
- public static native CiphertextMessage SessionCipher_EncryptMessage(byte[] ptext, long protocolAddress, SessionStore sessionStore, IdentityKeyStore identityKeyStore);
+ public static native CiphertextMessage SessionCipher_EncryptMessage(byte[] ptext, long protocolAddress, SessionStore sessionStore, IdentityKeyStore identityKeyStore, long now);
public static native void SessionRecord_ArchiveCurrentState(long sessionRecord);
public static native boolean SessionRecord_CurrentRatchetKeyMatches(long s, long key);
public static native long SessionRecord_Deserialize(byte[] data);
public static native void SessionRecord_Destroy(long handle);
- public static native long SessionRecord_FromSingleSessionState(byte[] sessionState);
public static native byte[] SessionRecord_GetAliceBaseKey(long obj);
public static native byte[] SessionRecord_GetLocalIdentityKeyPublic(long obj);
public static native int SessionRecord_GetLocalRegistrationId(long obj);
@@ -507,7 +506,7 @@ private Native() {}
public static native int SessionRecord_GetRemoteRegistrationId(long obj);
public static native byte[] SessionRecord_GetSenderChainKeyValue(long obj);
public static native int SessionRecord_GetSessionVersion(long s);
- public static native boolean SessionRecord_HasSenderChain(long obj);
+ public static native boolean SessionRecord_HasUsableSenderChain(long s, long now);
public static native long SessionRecord_InitializeAliceSession(long identityKeyPrivate, long identityKeyPublic, long basePrivate, long basePublic, long theirIdentityKey, long theirSignedPrekey, long theirRatchetKey);
public static native long SessionRecord_InitializeBobSession(long identityKeyPrivate, long identityKeyPublic, long signedPrekeyPrivate, long signedPrekeyPublic, long ephPrivate, long ephPublic, long theirIdentityKey, long theirBaseKey);
public static native long SessionRecord_NewFresh();
@@ -564,7 +563,7 @@ private Native() {}
public static native void UuidCiphertext_CheckValidContents(byte[] buffer);
public static native void ValidatingMac_Destroy(long handle);
- public static native boolean ValidatingMac_Finalize(long mac);
+ public static native int ValidatingMac_Finalize(long mac);
public static native long ValidatingMac_Initialize(byte[] key, int chunkSize, byte[] digests);
- public static native boolean ValidatingMac_Update(long mac, byte[] bytes, int offset, int length);
+ public static native int ValidatingMac_Update(long mac, byte[] bytes, int offset, int length);
}
diff --git a/java/shared/java/org/signal/libsignal/internal/NativeHandleGuard.java b/java/shared/java/org/signal/libsignal/internal/NativeHandleGuard.java
index 344a4074e7..f55bf30fbe 100644
--- a/java/shared/java/org/signal/libsignal/internal/NativeHandleGuard.java
+++ b/java/shared/java/org/signal/libsignal/internal/NativeHandleGuard.java
@@ -1,49 +1,47 @@
-/**
- * Copyright (C) 2021 Open Whisper Systems
- *
- * Licensed according to the LICENSE file in this repository.
- */
+//
+// Copyright 2021 Signal Messenger, LLC.
+// SPDX-License-Identifier: AGPL-3.0-only
+//
package org.signal.libsignal.internal;
/**
* Provides access to a Rust object handle while keeping the Java wrapper alive.
*
- * Intended for use with try-with-resources syntax. NativeHandleGuard prevents the Java wrapper from
- * being finalized, which would destroy the Rust object, while the handle is in use.
- * To use it, the Java wrapper type should conform to the {@link NativeHandleGuard.Owner} interface.
- *
- * Note that it is not necessary to use NativeHandleGuard in the implementation of {@code finalize}
- * itself. The point of NativeHandleGuard is to delay finalization while the Rust object is being
- * used; once finalization has begun, there can be no other uses of the Rust object from Java.
+ * Intended for use with try-with-resources syntax. NativeHandleGuard prevents the Java wrapper
+ * from being finalized, which would destroy the Rust object, while the handle is in use. To use it,
+ * the Java wrapper type should conform to the {@link NativeHandleGuard.Owner} interface.
+ *
+ *
Note that it is not necessary to use NativeHandleGuard in the implementation of {@code
+ * finalize} itself. The point of NativeHandleGuard is to delay finalization while the Rust object
+ * is being used; once finalization has begun, there can be no other uses of the Rust object from
+ * Java.
*/
public class NativeHandleGuard implements AutoCloseable {
- /**
- * @see NativeHandleGuard
- */
- public static interface Owner {
- long unsafeNativeHandleWithoutGuard();
- }
+ /**
+ * @see NativeHandleGuard
+ */
+ public static interface Owner {
+ long unsafeNativeHandleWithoutGuard();
+ }
- private final Owner owner;
+ private final Owner owner;
- public NativeHandleGuard(Owner owner) {
- this.owner = owner;
- }
+ public NativeHandleGuard(Owner owner) {
+ this.owner = owner;
+ }
- /**
- * Returns the native handle owned by the Java object, or 0 if the owner is {@code null}.
- */
- public long nativeHandle() {
- if (owner == null) {
- return 0;
- }
- return owner.unsafeNativeHandleWithoutGuard();
+ /** Returns the native handle owned by the Java object, or 0 if the owner is {@code null}. */
+ public long nativeHandle() {
+ if (owner == null) {
+ return 0;
}
+ return owner.unsafeNativeHandleWithoutGuard();
+ }
- public void close() {
- // Act as an optimization barrier, so the whole guard doesn't get inlined away.
- // (In Java 9 we'd use Reference.reachabilityFence() for the same effect.)
- Native.keepAlive(this.owner);
- }
-}
\ No newline at end of file
+ public void close() {
+ // Act as an optimization barrier, so the whole guard doesn't get inlined away.
+ // (In Java 9 we'd use Reference.reachabilityFence() for the same effect.)
+ Native.keepAlive(this.owner);
+ }
+}
diff --git a/java/shared/java/org/signal/libsignal/protocol/DuplicateMessageException.java b/java/shared/java/org/signal/libsignal/protocol/DuplicateMessageException.java
index 87ab889d04..07eab2bd6d 100644
--- a/java/shared/java/org/signal/libsignal/protocol/DuplicateMessageException.java
+++ b/java/shared/java/org/signal/libsignal/protocol/DuplicateMessageException.java
@@ -1,8 +1,8 @@
-/**
- * Copyright (C) 2014-2016 Open Whisper Systems
- *
- * Licensed according to the LICENSE file in this repository.
- */
+//
+// Copyright 2014-2016 Signal Messenger, LLC.
+// SPDX-License-Identifier: AGPL-3.0-only
+//
+
package org.signal.libsignal.protocol;
public class DuplicateMessageException extends Exception {
diff --git a/java/shared/java/org/signal/libsignal/protocol/IdentityKey.java b/java/shared/java/org/signal/libsignal/protocol/IdentityKey.java
index 128dcbf540..fb61ad290f 100644
--- a/java/shared/java/org/signal/libsignal/protocol/IdentityKey.java
+++ b/java/shared/java/org/signal/libsignal/protocol/IdentityKey.java
@@ -1,23 +1,21 @@
-/**
- * Copyright (C) 2014-2016 Open Whisper Systems
- *
- * Licensed according to the LICENSE file in this repository.
- */
+//
+// Copyright 2014-2016 Signal Messenger, LLC.
+// SPDX-License-Identifier: AGPL-3.0-only
+//
+
package org.signal.libsignal.protocol;
import org.signal.libsignal.internal.Native;
import org.signal.libsignal.internal.NativeHandleGuard;
-
import org.signal.libsignal.protocol.ecc.Curve;
import org.signal.libsignal.protocol.ecc.ECPublicKey;
import org.signal.libsignal.protocol.util.Hex;
/**
* A class for representing an identity key.
- *
+ *
* @author Moxie Marlinspike
*/
-
public class IdentityKey {
private final ECPublicKey publicKey;
@@ -51,22 +49,21 @@ public String getFingerprint() {
}
public boolean verifyAlternateIdentity(IdentityKey other, byte[] signature) {
- try (
- NativeHandleGuard guard = new NativeHandleGuard(this.publicKey);
- NativeHandleGuard otherGuard = new NativeHandleGuard(other.publicKey);
- ) {
- return Native.IdentityKey_VerifyAlternateIdentity(guard.nativeHandle(), otherGuard.nativeHandle(), signature);
+ try (NativeHandleGuard guard = new NativeHandleGuard(this.publicKey);
+ NativeHandleGuard otherGuard = new NativeHandleGuard(other.publicKey); ) {
+ return Native.IdentityKey_VerifyAlternateIdentity(
+ guard.nativeHandle(), otherGuard.nativeHandle(), signature);
}
}
@Override
public boolean equals(Object other) {
- if (other == null) return false;
+ if (other == null) return false;
if (!(other instanceof IdentityKey)) return false;
return publicKey.equals(((IdentityKey) other).getPublicKey());
}
-
+
@Override
public int hashCode() {
return publicKey.hashCode();
diff --git a/java/shared/java/org/signal/libsignal/protocol/IdentityKeyPair.java b/java/shared/java/org/signal/libsignal/protocol/IdentityKeyPair.java
index fdb5bf6be4..accf7abb9e 100644
--- a/java/shared/java/org/signal/libsignal/protocol/IdentityKeyPair.java
+++ b/java/shared/java/org/signal/libsignal/protocol/IdentityKeyPair.java
@@ -1,13 +1,12 @@
-/**
- * Copyright (C) 2014-2016 Open Whisper Systems
- *
- * Licensed according to the LICENSE file in this repository.
- */
+//
+// Copyright 2014-2016 Signal Messenger, LLC.
+// SPDX-License-Identifier: AGPL-3.0-only
+//
+
package org.signal.libsignal.protocol;
import org.signal.libsignal.internal.Native;
import org.signal.libsignal.internal.NativeHandleGuard;
-
import org.signal.libsignal.protocol.ecc.Curve;
import org.signal.libsignal.protocol.ecc.ECKeyPair;
import org.signal.libsignal.protocol.ecc.ECPrivateKey;
@@ -19,11 +18,11 @@
* @author Moxie Marlinspike
*/
public class IdentityKeyPair {
- private final IdentityKey publicKey;
+ private final IdentityKey publicKey;
private final ECPrivateKey privateKey;
public IdentityKeyPair(IdentityKey publicKey, ECPrivateKey privateKey) {
- this.publicKey = publicKey;
+ this.publicKey = publicKey;
this.privateKey = privateKey;
}
@@ -52,21 +51,18 @@ public ECPrivateKey getPrivateKey() {
}
public byte[] serialize() {
- try (
- NativeHandleGuard publicKey = new NativeHandleGuard(this.publicKey.getPublicKey());
- NativeHandleGuard privateKey = new NativeHandleGuard(this.privateKey);
- ) {
+ try (NativeHandleGuard publicKey = new NativeHandleGuard(this.publicKey.getPublicKey());
+ NativeHandleGuard privateKey = new NativeHandleGuard(this.privateKey); ) {
return Native.IdentityKeyPair_Serialize(publicKey.nativeHandle(), privateKey.nativeHandle());
}
}
public byte[] signAlternateIdentity(IdentityKey other) {
- try (
- NativeHandleGuard publicKey = new NativeHandleGuard(this.publicKey.getPublicKey());
- NativeHandleGuard privateKey = new NativeHandleGuard(this.privateKey);
- NativeHandleGuard otherPublic = new NativeHandleGuard(other.getPublicKey());
- ) {
- return Native.IdentityKeyPair_SignAlternateIdentity(publicKey.nativeHandle(), privateKey.nativeHandle(), otherPublic.nativeHandle());
+ try (NativeHandleGuard publicKey = new NativeHandleGuard(this.publicKey.getPublicKey());
+ NativeHandleGuard privateKey = new NativeHandleGuard(this.privateKey);
+ NativeHandleGuard otherPublic = new NativeHandleGuard(other.getPublicKey()); ) {
+ return Native.IdentityKeyPair_SignAlternateIdentity(
+ publicKey.nativeHandle(), privateKey.nativeHandle(), otherPublic.nativeHandle());
}
}
}
diff --git a/java/shared/java/org/signal/libsignal/protocol/InvalidKeyException.java b/java/shared/java/org/signal/libsignal/protocol/InvalidKeyException.java
index ee8a55e68f..a7580f3bec 100644
--- a/java/shared/java/org/signal/libsignal/protocol/InvalidKeyException.java
+++ b/java/shared/java/org/signal/libsignal/protocol/InvalidKeyException.java
@@ -1,8 +1,8 @@
-/**
- * Copyright (C) 2014-2016 Open Whisper Systems
- *
- * Licensed according to the LICENSE file in this repository.
- */
+//
+// Copyright 2014-2016 Signal Messenger, LLC.
+// SPDX-License-Identifier: AGPL-3.0-only
+//
+
package org.signal.libsignal.protocol;
public class InvalidKeyException extends Exception {
diff --git a/java/shared/java/org/signal/libsignal/protocol/InvalidKeyIdException.java b/java/shared/java/org/signal/libsignal/protocol/InvalidKeyIdException.java
index 3c04efc6fa..db4186d92b 100644
--- a/java/shared/java/org/signal/libsignal/protocol/InvalidKeyIdException.java
+++ b/java/shared/java/org/signal/libsignal/protocol/InvalidKeyIdException.java
@@ -1,8 +1,8 @@
-/**
- * Copyright (C) 2014-2016 Open Whisper Systems
- *
- * Licensed according to the LICENSE file in this repository.
- */
+//
+// Copyright 2014-2016 Signal Messenger, LLC.
+// SPDX-License-Identifier: AGPL-3.0-only
+//
+
package org.signal.libsignal.protocol;
public class InvalidKeyIdException extends Exception {
diff --git a/java/shared/java/org/signal/libsignal/protocol/InvalidMacException.java b/java/shared/java/org/signal/libsignal/protocol/InvalidMacException.java
index 8f31953521..97dbe42d67 100644
--- a/java/shared/java/org/signal/libsignal/protocol/InvalidMacException.java
+++ b/java/shared/java/org/signal/libsignal/protocol/InvalidMacException.java
@@ -1,8 +1,8 @@
-/**
- * Copyright (C) 2014-2016 Open Whisper Systems
- *
- * Licensed according to the LICENSE file in this repository.
- */
+//
+// Copyright 2014-2016 Signal Messenger, LLC.
+// SPDX-License-Identifier: AGPL-3.0-only
+//
+
package org.signal.libsignal.protocol;
public class InvalidMacException extends Exception {
diff --git a/java/shared/java/org/signal/libsignal/protocol/InvalidMessageException.java b/java/shared/java/org/signal/libsignal/protocol/InvalidMessageException.java
index e1288b9b3e..d3e34897f0 100644
--- a/java/shared/java/org/signal/libsignal/protocol/InvalidMessageException.java
+++ b/java/shared/java/org/signal/libsignal/protocol/InvalidMessageException.java
@@ -1,8 +1,8 @@
-/**
- * Copyright (C) 2014-2016 Open Whisper Systems
- *
- * Licensed according to the LICENSE file in this repository.
- */
+//
+// Copyright 2014-2016 Signal Messenger, LLC.
+// SPDX-License-Identifier: AGPL-3.0-only
+//
+
package org.signal.libsignal.protocol;
import java.util.List;
diff --git a/java/shared/java/org/signal/libsignal/protocol/InvalidRegistrationIdException.java b/java/shared/java/org/signal/libsignal/protocol/InvalidRegistrationIdException.java
index b45d021a8d..cf706e1fe3 100644
--- a/java/shared/java/org/signal/libsignal/protocol/InvalidRegistrationIdException.java
+++ b/java/shared/java/org/signal/libsignal/protocol/InvalidRegistrationIdException.java
@@ -1,8 +1,8 @@
-/**
- * Copyright (C) 2021 Open Whisper Systems
- *
- * Licensed according to the LICENSE file in this repository.
- */
+//
+// Copyright 2021 Signal Messenger, LLC.
+// SPDX-License-Identifier: AGPL-3.0-only
+//
+
package org.signal.libsignal.protocol;
public class InvalidRegistrationIdException extends Exception {
diff --git a/java/shared/java/org/signal/libsignal/protocol/InvalidSessionException.java b/java/shared/java/org/signal/libsignal/protocol/InvalidSessionException.java
index 9f832558b6..ef9f704bd6 100644
--- a/java/shared/java/org/signal/libsignal/protocol/InvalidSessionException.java
+++ b/java/shared/java/org/signal/libsignal/protocol/InvalidSessionException.java
@@ -1,8 +1,8 @@
-/**
- * Copyright (C) 2014-2016 Open Whisper Systems
- *
- * Licensed according to the LICENSE file in this repository.
- */
+//
+// Copyright 2014-2016 Signal Messenger, LLC.
+// SPDX-License-Identifier: AGPL-3.0-only
+//
+
package org.signal.libsignal.protocol;
public class InvalidSessionException extends IllegalStateException {
diff --git a/java/shared/java/org/signal/libsignal/protocol/InvalidVersionException.java b/java/shared/java/org/signal/libsignal/protocol/InvalidVersionException.java
index fe4b59ffff..12f8ac7beb 100644
--- a/java/shared/java/org/signal/libsignal/protocol/InvalidVersionException.java
+++ b/java/shared/java/org/signal/libsignal/protocol/InvalidVersionException.java
@@ -1,8 +1,8 @@
-/**
- * Copyright (C) 2014-2016 Open Whisper Systems
- *
- * Licensed according to the LICENSE file in this repository.
- */
+//
+// Copyright 2014-2016 Signal Messenger, LLC.
+// SPDX-License-Identifier: AGPL-3.0-only
+//
+
package org.signal.libsignal.protocol;
public class InvalidVersionException extends Exception {
diff --git a/java/shared/java/org/signal/libsignal/protocol/LegacyMessageException.java b/java/shared/java/org/signal/libsignal/protocol/LegacyMessageException.java
index 33ee1c210c..5f56267cae 100644
--- a/java/shared/java/org/signal/libsignal/protocol/LegacyMessageException.java
+++ b/java/shared/java/org/signal/libsignal/protocol/LegacyMessageException.java
@@ -1,8 +1,8 @@
-/**
- * Copyright (C) 2014-2016 Open Whisper Systems
- *
- * Licensed according to the LICENSE file in this repository.
- */
+//
+// Copyright 2014-2016 Signal Messenger, LLC.
+// SPDX-License-Identifier: AGPL-3.0-only
+//
+
package org.signal.libsignal.protocol;
public class LegacyMessageException extends Exception {
diff --git a/java/shared/java/org/signal/libsignal/protocol/NoSessionException.java b/java/shared/java/org/signal/libsignal/protocol/NoSessionException.java
index ce90604943..9e7918e923 100644
--- a/java/shared/java/org/signal/libsignal/protocol/NoSessionException.java
+++ b/java/shared/java/org/signal/libsignal/protocol/NoSessionException.java
@@ -1,8 +1,8 @@
-/**
- * Copyright (C) 2014-2016 Open Whisper Systems
- *
- * Licensed according to the LICENSE file in this repository.
- */
+//
+// Copyright 2014-2016 Signal Messenger, LLC.
+// SPDX-License-Identifier: AGPL-3.0-only
+//
+
package org.signal.libsignal.protocol;
public class NoSessionException extends Exception {
diff --git a/java/shared/java/org/signal/libsignal/protocol/ServiceId.java b/java/shared/java/org/signal/libsignal/protocol/ServiceId.java
index e675301723..3865bdf586 100644
--- a/java/shared/java/org/signal/libsignal/protocol/ServiceId.java
+++ b/java/shared/java/org/signal/libsignal/protocol/ServiceId.java
@@ -2,199 +2,203 @@
// Copyright 2023 Signal Messenger, LLC.
// SPDX-License-Identifier: AGPL-3.0-only
//
+
package org.signal.libsignal.protocol;
import java.nio.ByteBuffer;
import java.util.Arrays;
import java.util.UUID;
-
import org.signal.libsignal.internal.Native;
public abstract class ServiceId {
- private static final byte ACI_MARKER = 0x00;
- private static final byte PNI_MARKER = 0x01;
+ private static final byte ACI_MARKER = 0x00;
+ private static final byte PNI_MARKER = 0x01;
+
+ byte[] storage;
+
+ ServiceId(byte[] storage) {
+ if (storage == null) {
+ throw new IllegalArgumentException("Service-Id-FixedWidthBinary cannot be null");
+ }
+ this.storage = storage;
+ }
+
+ ServiceId(byte marker, UUID uuid) {
+ if (uuid == null) {
+ throw new IllegalArgumentException("Source UUID must be specified");
+ }
+ ByteBuffer bytes = ByteBuffer.wrap(new byte[17]);
+ long high = uuid.getMostSignificantBits();
+ long low = uuid.getLeastSignificantBits();
+ bytes.put(marker);
+ bytes.putLong(high);
+ bytes.putLong(low);
+ this.storage = bytes.array();
+ }
+
+ @Override
+ public boolean equals(Object other) {
+ if (other instanceof ServiceId) {
+ return Arrays.equals(this.storage, ((ServiceId) other).storage);
+ }
+ return false;
+ }
+
+ @Override
+ public int hashCode() {
+ return Arrays.hashCode(this.storage);
+ }
+
+ @Override
+ public String toString() {
+ return this.toLogString();
+ }
+
+ public String toLogString() {
+ return Native.ServiceId_ServiceIdLog(this.storage);
+ }
+
+ public byte[] toServiceIdBinary() {
+ return Native.ServiceId_ServiceIdBinary(this.storage);
+ }
+
+ public byte[] toServiceIdFixedWidthBinary() {
+ return this.storage.clone();
+ }
+
+ public String toServiceIdString() {
+ return Native.ServiceId_ServiceIdString(this.storage);
+ }
+
+ public UUID getRawUUID() {
+ ByteBuffer buffer = ByteBuffer.wrap(this.storage);
+ byte unusedMarkerByte = buffer.get();
+ return uuidFromBytes(buffer.slice());
+ }
+
+ public static ServiceId parseFromString(String serviceIdString) throws InvalidServiceIdException {
+ if (serviceIdString == null) {
+ throw new InvalidServiceIdException("Service-Id-String cannot be null");
+ }
+ byte[] storage;
+ try {
+ storage = Native.ServiceId_ParseFromServiceIdString(serviceIdString);
+ } catch (IllegalArgumentException ex) {
+ throw new InvalidServiceIdException();
+ }
+ return parseFromFixedWidthBinary(storage);
+ }
+ public static ServiceId parseFromBinary(byte[] serviceIdBinary) throws InvalidServiceIdException {
+ if (serviceIdBinary == null) {
+ throw new InvalidServiceIdException("Service-Id-Binary cannot be null");
+ }
byte[] storage;
+ try {
+ storage = Native.ServiceId_ParseFromServiceIdBinary(serviceIdBinary);
+ } catch (IllegalArgumentException ex) {
+ throw new InvalidServiceIdException();
+ }
+ return parseFromFixedWidthBinary(storage);
+ }
+
+ public static ServiceId parseFromFixedWidthBinary(byte[] storage)
+ throws InvalidServiceIdException {
+ if (storage == null) {
+ throw new InvalidServiceIdException();
+ }
+ switch (storage[0]) {
+ case ACI_MARKER:
+ return new Aci(storage);
+ case PNI_MARKER:
+ return new Pni(storage);
+ default:
+ // This is already handled on the Rust side
+ throw new InvalidServiceIdException();
+ }
+ }
+
+ private static UUID uuidFromBytes(ByteBuffer buffer) {
+ long high = buffer.getLong();
+ long low = buffer.getLong();
+ return new UUID(high, low);
+ }
+
+ public static class InvalidServiceIdException extends Exception {
+ public InvalidServiceIdException() {
+ super();
+ }
+
+ public InvalidServiceIdException(String message) {
+ super(message);
+ }
+ }
+
+ public static final class Aci extends ServiceId {
+ public Aci(UUID uuid) {
+ super(ACI_MARKER, uuid);
+ }
- ServiceId(byte[] storage) {
- if (storage == null) {
- throw new IllegalArgumentException("Service-Id-FixedWidthBinary cannot be null");
- }
- this.storage = storage;
+ Aci(byte[] storage) {
+ super(storage);
}
- ServiceId(byte marker, UUID uuid) {
- if (uuid == null) {
- throw new IllegalArgumentException("Source UUID must be specified");
- }
- ByteBuffer bytes = ByteBuffer.wrap(new byte[17]);
- long high = uuid.getMostSignificantBits();
- long low = uuid.getLeastSignificantBits();
- bytes.put(marker);
- bytes.putLong(high);
- bytes.putLong(low);
- this.storage = bytes.array();
+ public static Aci parseFromString(String serviceIdString) throws InvalidServiceIdException {
+ ServiceId result = ServiceId.parseFromString(serviceIdString);
+ if (result instanceof Aci) {
+ return (Aci) result;
+ }
+ throw new InvalidServiceIdException();
}
- @Override
- public boolean equals(Object other) {
- if(other instanceof ServiceId) {
- return Arrays.equals(this.storage, ((ServiceId)other).storage);
- }
- return false;
+ public static Aci parseFromBinary(byte[] serviceIdBinary) throws InvalidServiceIdException {
+ ServiceId result = ServiceId.parseFromBinary(serviceIdBinary);
+ if (result instanceof Aci) {
+ return (Aci) result;
+ }
+ throw new InvalidServiceIdException();
}
- @Override
- public int hashCode() {
- return Arrays.hashCode(this.storage);
+ public static Aci parseFromFixedWidthBinary(byte[] storage) throws InvalidServiceIdException {
+ ServiceId result = ServiceId.parseFromFixedWidthBinary(storage);
+ if (result instanceof Aci) {
+ return (Aci) result;
+ }
+ throw new InvalidServiceIdException();
}
+ }
- @Override
- public String toString() {
- return this.toLogString();
+ public static final class Pni extends ServiceId {
+ public Pni(UUID uuid) {
+ super(PNI_MARKER, uuid);
}
- public String toLogString() {
- return Native.ServiceId_ServiceIdLog(this.storage);
+ Pni(byte[] storage) {
+ super(storage);
}
- public byte[] toServiceIdBinary() {
- return Native.ServiceId_ServiceIdBinary(this.storage);
- }
-
- public byte[] toServiceIdFixedWidthBinary() {
- return this.storage.clone();
+ public static Pni parseFromString(String serviceIdString) throws InvalidServiceIdException {
+ ServiceId result = ServiceId.parseFromString(serviceIdString);
+ if (result instanceof Pni) {
+ return (Pni) result;
+ }
+ throw new InvalidServiceIdException();
}
- public String toServiceIdString() {
- return Native.ServiceId_ServiceIdString(this.storage);
+ public static Pni parseFromBinary(byte[] serviceIdBinary) throws InvalidServiceIdException {
+ ServiceId result = ServiceId.parseFromBinary(serviceIdBinary);
+ if (result instanceof Pni) {
+ return (Pni) result;
+ }
+ throw new InvalidServiceIdException();
}
- public UUID getRawUUID() {
- ByteBuffer buffer = ByteBuffer.wrap(this.storage);
- byte unusedMarkerByte = buffer.get();
- return uuidFromBytes(buffer.slice());
- }
-
- public static ServiceId parseFromString(String serviceIdString) throws InvalidServiceIdException {
- if (serviceIdString == null) {
- throw new InvalidServiceIdException("Service-Id-String cannot be null");
- }
- byte[] storage;
- try {
- storage = Native.ServiceId_ParseFromServiceIdString(serviceIdString);
- }
- catch (IllegalArgumentException ex) {
- throw new InvalidServiceIdException();
- }
- return parseFromFixedWidthBinary(storage);
- }
-
- public static ServiceId parseFromBinary(byte[] serviceIdBinary) throws InvalidServiceIdException {
- if (serviceIdBinary == null) {
- throw new InvalidServiceIdException("Service-Id-Binary cannot be null");
- }
- byte[] storage;
- try {
- storage = Native.ServiceId_ParseFromServiceIdBinary(serviceIdBinary);
- }
- catch (IllegalArgumentException ex) {
- throw new InvalidServiceIdException();
- }
- return parseFromFixedWidthBinary(storage);
- }
-
- public static ServiceId parseFromFixedWidthBinary(byte[] storage) throws InvalidServiceIdException {
- if (storage == null) {
- throw new InvalidServiceIdException();
- }
- switch(storage[0]) {
- case ACI_MARKER:
- return new Aci(storage);
- case PNI_MARKER:
- return new Pni(storage);
- default:
- // This is already handled on the Rust side
- throw new InvalidServiceIdException();
- }
- }
-
- private static UUID uuidFromBytes(ByteBuffer buffer) {
- long high = buffer.getLong();
- long low = buffer.getLong();
- return new UUID(high, low);
- }
-
- public static class InvalidServiceIdException extends Exception {
- public InvalidServiceIdException() { super(); }
- public InvalidServiceIdException(String message) { super(message); }
- }
-
- public final static class Aci extends ServiceId {
- public Aci(UUID uuid) {
- super(ACI_MARKER, uuid);
- }
-
- Aci(byte[] storage) {
- super(storage);
- }
-
- public static Aci parseFromString(String serviceIdString) throws InvalidServiceIdException {
- ServiceId result = ServiceId.parseFromString(serviceIdString);
- if (result instanceof Aci) {
- return (Aci)result;
- }
- throw new InvalidServiceIdException();
- }
-
- public static Aci parseFromBinary(byte[] serviceIdBinary) throws InvalidServiceIdException {
- ServiceId result = ServiceId.parseFromBinary(serviceIdBinary);
- if (result instanceof Aci) {
- return (Aci)result;
- }
- throw new InvalidServiceIdException();
- }
-
- public static Aci parseFromFixedWidthBinary(byte[] storage) throws InvalidServiceIdException {
- ServiceId result = ServiceId.parseFromFixedWidthBinary(storage);
- if (result instanceof Aci) {
- return (Aci)result;
- }
- throw new InvalidServiceIdException();
- }
- }
-
- public final static class Pni extends ServiceId {
- public Pni(UUID uuid) {
- super(PNI_MARKER, uuid);
- }
-
- Pni(byte[] storage) {
- super(storage);
- }
-
- public static Pni parseFromString(String serviceIdString) throws InvalidServiceIdException {
- ServiceId result = ServiceId.parseFromString(serviceIdString);
- if (result instanceof Pni) {
- return (Pni)result;
- }
- throw new InvalidServiceIdException();
- }
-
- public static Pni parseFromBinary(byte[] serviceIdBinary) throws InvalidServiceIdException {
- ServiceId result = ServiceId.parseFromBinary(serviceIdBinary);
- if (result instanceof Pni) {
- return (Pni)result;
- }
- throw new InvalidServiceIdException();
- }
-
- public static Pni parseFromFixedWidthBinary(byte[] storage) throws InvalidServiceIdException {
- ServiceId result = ServiceId.parseFromFixedWidthBinary(storage);
- if (result instanceof Pni) {
- return (Pni)result;
- }
- throw new InvalidServiceIdException();
- }
+ public static Pni parseFromFixedWidthBinary(byte[] storage) throws InvalidServiceIdException {
+ ServiceId result = ServiceId.parseFromFixedWidthBinary(storage);
+ if (result instanceof Pni) {
+ return (Pni) result;
+ }
+ throw new InvalidServiceIdException();
}
+ }
}
diff --git a/java/shared/java/org/signal/libsignal/protocol/SessionBuilder.java b/java/shared/java/org/signal/libsignal/protocol/SessionBuilder.java
index 8af7d3ca8a..2fb44d3239 100644
--- a/java/shared/java/org/signal/libsignal/protocol/SessionBuilder.java
+++ b/java/shared/java/org/signal/libsignal/protocol/SessionBuilder.java
@@ -1,72 +1,77 @@
-/**
- * Copyright (C) 2014-2016 Open Whisper Systems
- *
- * Licensed according to the LICENSE file in this repository.
- */
+//
+// Copyright 2014-2016 Signal Messenger, LLC.
+// SPDX-License-Identifier: AGPL-3.0-only
+//
+
package org.signal.libsignal.protocol;
+import java.time.Instant;
import org.signal.libsignal.internal.Native;
import org.signal.libsignal.internal.NativeHandleGuard;
-
-import org.signal.libsignal.protocol.logging.Log;
import org.signal.libsignal.protocol.state.IdentityKeyStore;
import org.signal.libsignal.protocol.state.PreKeyBundle;
import org.signal.libsignal.protocol.state.PreKeyStore;
-import org.signal.libsignal.protocol.state.SessionRecord;
import org.signal.libsignal.protocol.state.SessionStore;
import org.signal.libsignal.protocol.state.SignalProtocolStore;
import org.signal.libsignal.protocol.state.SignedPreKeyStore;
/**
- * SessionBuilder is responsible for setting up encrypted sessions.
- * Once a session has been established, {@link org.signal.libsignal.protocol.SessionCipher}
- * can be used to encrypt/decrypt messages in that session.
- *
- * Sessions are built from one of three different possible vectors:
+ * SessionBuilder is responsible for setting up encrypted sessions. Once a session has been
+ * established, {@link org.signal.libsignal.protocol.SessionCipher} can be used to encrypt/decrypt
+ * messages in that session.
+ *
+ *
Sessions are built from one of two different possible vectors:
+ *
*
- * A {@link org.signal.libsignal.protocol.state.PreKeyBundle} retrieved from a server.
- * A {@link PreKeySignalMessage} received from a client.
+ * A {@link org.signal.libsignal.protocol.state.PreKeyBundle} retrieved from a server.
+ * A {@link org.signal.libsignal.protocol.message.PreKeySignalMessage} received from a client.
*
*
- * Sessions are constructed per recipientId + deviceId tuple. Remote logical users are identified
+ * Only the first, however, is handled by SessionBuilder.
+ *
+ * Sessions are constructed per recipientId + deviceId tuple. Remote logical users are identified
* by their recipientId, and each logical recipientId can have multiple physical devices.
*
- * This class is not thread-safe.
+ *
This class is not thread-safe.
*
* @author Moxie Marlinspike
*/
public class SessionBuilder {
private static final String TAG = SessionBuilder.class.getSimpleName();
- private final SessionStore sessionStore;
- private final PreKeyStore preKeyStore;
+ private final SessionStore sessionStore;
+ private final PreKeyStore preKeyStore;
private final SignedPreKeyStore signedPreKeyStore;
- private final IdentityKeyStore identityKeyStore;
+ private final IdentityKeyStore identityKeyStore;
private final SignalProtocolAddress remoteAddress;
/**
* Constructs a SessionBuilder.
*
- * @param sessionStore The {@link org.signal.libsignal.protocol.state.SessionStore} to store the constructed session in.
- * @param preKeyStore The {@link org.signal.libsignal.protocol.state.PreKeyStore} where the client's local {@link org.signal.libsignal.protocol.state.PreKeyRecord}s are stored.
- * @param identityKeyStore The {@link org.signal.libsignal.protocol.state.IdentityKeyStore} containing the client's identity key information.
+ * @param sessionStore The {@link org.signal.libsignal.protocol.state.SessionStore} to store the
+ * constructed session in.
+ * @param preKeyStore The {@link org.signal.libsignal.protocol.state.PreKeyStore} where the
+ * client's local {@link org.signal.libsignal.protocol.state.PreKeyRecord}s are stored.
+ * @param identityKeyStore The {@link org.signal.libsignal.protocol.state.IdentityKeyStore}
+ * containing the client's identity key information.
* @param remoteAddress The address of the remote user to build a session with.
*/
- public SessionBuilder(SessionStore sessionStore,
- PreKeyStore preKeyStore,
- SignedPreKeyStore signedPreKeyStore,
- IdentityKeyStore identityKeyStore,
- SignalProtocolAddress remoteAddress)
- {
- this.sessionStore = sessionStore;
- this.preKeyStore = preKeyStore;
+ public SessionBuilder(
+ SessionStore sessionStore,
+ PreKeyStore preKeyStore,
+ SignedPreKeyStore signedPreKeyStore,
+ IdentityKeyStore identityKeyStore,
+ SignalProtocolAddress remoteAddress) {
+ this.sessionStore = sessionStore;
+ this.preKeyStore = preKeyStore;
this.signedPreKeyStore = signedPreKeyStore;
- this.identityKeyStore = identityKeyStore;
- this.remoteAddress = remoteAddress;
+ this.identityKeyStore = identityKeyStore;
+ this.remoteAddress = remoteAddress;
}
/**
* Constructs a SessionBuilder
+ *
* @param store The {@link SignalProtocolStore} to store all state information in.
* @param remoteAddress The address of the remote user to build a session with.
*/
@@ -75,25 +80,42 @@ public SessionBuilder(SignalProtocolStore store, SignalProtocolAddress remoteAdd
}
/**
- * Build a new session from a {@link org.signal.libsignal.protocol.state.PreKeyBundle} retrieved from
- * a server.
+ * Build a new session from a {@link org.signal.libsignal.protocol.state.PreKeyBundle} retrieved
+ * from a server.
*
* @param preKey A PreKey for the destination recipient, retrieved from a server.
- * @throws InvalidKeyException when the {@link org.signal.libsignal.protocol.state.PreKeyBundle} is
- * badly formatted.
- * @throws org.signal.libsignal.protocol.UntrustedIdentityException when the sender's
- * {@link IdentityKey} is not
- * trusted.
+ * @throws InvalidKeyException when the {@link org.signal.libsignal.protocol.state.PreKeyBundle}
+ * is badly formatted.
+ * @throws org.signal.libsignal.protocol.UntrustedIdentityException when the sender's {@link
+ * IdentityKey} is not trusted.
*/
public void process(PreKeyBundle preKey) throws InvalidKeyException, UntrustedIdentityException {
- try (
- NativeHandleGuard preKeyGuard = new NativeHandleGuard(preKey);
- NativeHandleGuard remoteAddressGuard = new NativeHandleGuard(this.remoteAddress);
- ) {
- Native.SessionBuilder_ProcessPreKeyBundle(preKeyGuard.nativeHandle(),
- remoteAddressGuard.nativeHandle(),
- sessionStore,
- identityKeyStore);
+ process(preKey, Instant.now());
+ }
+
+ /**
+ * Build a new session from a {@link org.signal.libsignal.protocol.state.PreKeyBundle} retrieved
+ * from a server.
+ *
+ *
You should only use this overload if you need to test session expiration explicitly.
+ *
+ * @param preKey A PreKey for the destination recipient, retrieved from a server.
+ * @param now The current time, used later to check if the session is stale.
+ * @throws InvalidKeyException when the {@link org.signal.libsignal.protocol.state.PreKeyBundle}
+ * is badly formatted.
+ * @throws org.signal.libsignal.protocol.UntrustedIdentityException when the sender's {@link
+ * IdentityKey} is not trusted.
+ */
+ public void process(PreKeyBundle preKey, Instant now)
+ throws InvalidKeyException, UntrustedIdentityException {
+ try (NativeHandleGuard preKeyGuard = new NativeHandleGuard(preKey);
+ NativeHandleGuard remoteAddressGuard = new NativeHandleGuard(this.remoteAddress)) {
+ Native.SessionBuilder_ProcessPreKeyBundle(
+ preKeyGuard.nativeHandle(),
+ remoteAddressGuard.nativeHandle(),
+ sessionStore,
+ identityKeyStore,
+ now.toEpochMilli());
}
}
}
diff --git a/java/shared/java/org/signal/libsignal/protocol/SessionCipher.java b/java/shared/java/org/signal/libsignal/protocol/SessionCipher.java
index 6e37022397..aff7c808f8 100644
--- a/java/shared/java/org/signal/libsignal/protocol/SessionCipher.java
+++ b/java/shared/java/org/signal/libsignal/protocol/SessionCipher.java
@@ -1,69 +1,65 @@
-/**
- * Copyright (C) 2014-2016 Open Whisper Systems
- *
- * Licensed according to the LICENSE file in this repository.
- */
+//
+// Copyright 2014-2016 Signal Messenger, LLC.
+// SPDX-License-Identifier: AGPL-3.0-only
+//
+
package org.signal.libsignal.protocol;
+import java.time.Instant;
import org.signal.libsignal.internal.Native;
import org.signal.libsignal.internal.NativeHandleGuard;
-
-import org.signal.libsignal.protocol.ecc.ECPublicKey;
import org.signal.libsignal.protocol.message.CiphertextMessage;
import org.signal.libsignal.protocol.message.PreKeySignalMessage;
import org.signal.libsignal.protocol.message.SignalMessage;
-import org.signal.libsignal.protocol.state.SignalProtocolStore;
import org.signal.libsignal.protocol.state.IdentityKeyStore;
+import org.signal.libsignal.protocol.state.KyberPreKeyStore;
import org.signal.libsignal.protocol.state.PreKeyStore;
import org.signal.libsignal.protocol.state.SessionRecord;
import org.signal.libsignal.protocol.state.SessionStore;
+import org.signal.libsignal.protocol.state.SignalProtocolStore;
import org.signal.libsignal.protocol.state.SignedPreKeyStore;
-import org.signal.libsignal.protocol.state.KyberPreKeyStore;
-
-import java.security.InvalidAlgorithmParameterException;
-import java.security.NoSuchAlgorithmException;
/**
* The main entry point for Signal Protocol encrypt/decrypt operations.
*
- * Once a session has been established with {@link SessionBuilder},
- * this class can be used for all encrypt/decrypt operations within
- * that session.
+ *
Once a session has been established with {@link SessionBuilder}, this class can be used for
+ * all encrypt/decrypt operations within that session.
*
- * This class is not thread-safe.
+ *
This class is not thread-safe.
*
* @author Moxie Marlinspike
*/
public class SessionCipher {
- private final SessionStore sessionStore;
- private final IdentityKeyStore identityKeyStore;
- private final PreKeyStore preKeyStore;
- private final SignedPreKeyStore signedPreKeyStore;
- private final KyberPreKeyStore kyberPreKeyStore;
+ private final SessionStore sessionStore;
+ private final IdentityKeyStore identityKeyStore;
+ private final PreKeyStore preKeyStore;
+ private final SignedPreKeyStore signedPreKeyStore;
+ private final KyberPreKeyStore kyberPreKeyStore;
private final SignalProtocolAddress remoteAddress;
/**
- * Construct a SessionCipher for encrypt/decrypt operations on a session.
- * In order to use SessionCipher, a session must have already been created
- * and stored using {@link SessionBuilder}.
+ * Construct a SessionCipher for encrypt/decrypt operations on a session. In order to use
+ * SessionCipher, a session must have already been created and stored using {@link
+ * SessionBuilder}.
*
- * @param sessionStore The {@link SessionStore} that contains a session for this recipient.
- * @param remoteAddress The remote address that messages will be encrypted to or decrypted from.
+ * @param sessionStore The {@link SessionStore} that contains a session for this recipient.
+ * @param remoteAddress The remote address that messages will be encrypted to or decrypted from.
*/
- public SessionCipher(SessionStore sessionStore,
- PreKeyStore preKeyStore,
- SignedPreKeyStore signedPreKeyStore,
- KyberPreKeyStore kyberPreKeyStore,
- IdentityKeyStore identityKeyStore,
- SignalProtocolAddress remoteAddress)
- {
- this.sessionStore = sessionStore;
- this.preKeyStore = preKeyStore;
- this.identityKeyStore = identityKeyStore;
- this.remoteAddress = remoteAddress;
+ public SessionCipher(
+ SessionStore sessionStore,
+ PreKeyStore preKeyStore,
+ SignedPreKeyStore signedPreKeyStore,
+ KyberPreKeyStore kyberPreKeyStore,
+ IdentityKeyStore identityKeyStore,
+ SignalProtocolAddress remoteAddress) {
+ this.sessionStore = sessionStore;
+ this.preKeyStore = preKeyStore;
+ this.identityKeyStore = identityKeyStore;
+ this.remoteAddress = remoteAddress;
this.signedPreKeyStore = signedPreKeyStore;
- this.kyberPreKeyStore = kyberPreKeyStore;;
+ this.kyberPreKeyStore = kyberPreKeyStore;
+ ;
}
public SessionCipher(SignalProtocolStore store, SignalProtocolAddress remoteAddress) {
@@ -73,53 +69,76 @@ public SessionCipher(SignalProtocolStore store, SignalProtocolAddress remoteAddr
/**
* Encrypt a message.
*
- * @param paddedMessage The plaintext message bytes, optionally padded to a constant multiple.
+ * @param paddedMessage The plaintext message bytes, optionally padded to a constant multiple.
* @return A ciphertext message encrypted to the recipient+device tuple.
+ * @throws NoSessionException if there is no established session for this contact, or if an
+ * unacknowledged session has expired
+ * @throws UntrustedIdentityException when the {@link IdentityKey} of the sender is out of date.
*/
- public CiphertextMessage encrypt(byte[] paddedMessage) throws UntrustedIdentityException {
+ public CiphertextMessage encrypt(byte[] paddedMessage)
+ throws NoSessionException, UntrustedIdentityException {
+ return encrypt(paddedMessage, Instant.now());
+ }
+
+ /**
+ * Encrypt a message.
+ *
+ *
You should only use this overload if you need to test session expiration explicitly.
+ *
+ * @param paddedMessage The plaintext message bytes, optionally padded to a constant multiple.
+ * @return A ciphertext message encrypted to the recipient+device tuple.
+ * @throws NoSessionException if there is no established session for this contact, or if an
+ * unacknowledged session has expired
+ * @throws UntrustedIdentityException when the {@link IdentityKey} of the sender is out of date.
+ */
+ public CiphertextMessage encrypt(byte[] paddedMessage, Instant now)
+ throws NoSessionException, UntrustedIdentityException {
try (NativeHandleGuard remoteAddress = new NativeHandleGuard(this.remoteAddress)) {
- return Native.SessionCipher_EncryptMessage(paddedMessage,
- remoteAddress.nativeHandle(),
- sessionStore,
- identityKeyStore);
+ return Native.SessionCipher_EncryptMessage(
+ paddedMessage,
+ remoteAddress.nativeHandle(),
+ sessionStore,
+ identityKeyStore,
+ now.toEpochMilli());
}
}
/**
* Decrypt a message.
*
- * @param ciphertext The {@link PreKeySignalMessage} to decrypt.
- *
+ * @param ciphertext The {@link PreKeySignalMessage} to decrypt.
* @return The plaintext.
* @throws InvalidMessageException if the input is not valid ciphertext.
* @throws DuplicateMessageException if the input is a message that has already been received.
- * @throws InvalidKeyIdException when there is no local {@link org.signal.libsignal.protocol.state.PreKeyRecord}
- * that corresponds to the PreKey ID in the message.
+ * @throws InvalidKeyIdException when there is no local {@link
+ * org.signal.libsignal.protocol.state.PreKeyRecord} that corresponds to the PreKey ID in the
+ * message.
* @throws InvalidKeyException when the message is formatted incorrectly.
* @throws UntrustedIdentityException when the {@link IdentityKey} of the sender is untrusted.
*/
public byte[] decrypt(PreKeySignalMessage ciphertext)
- throws DuplicateMessageException, InvalidMessageException, InvalidKeyIdException, InvalidKeyException, UntrustedIdentityException
- {
- try (
- NativeHandleGuard ciphertextGuard = new NativeHandleGuard(ciphertext);
- NativeHandleGuard remoteAddressGuard = new NativeHandleGuard(this.remoteAddress);
- ) {
- return Native.SessionCipher_DecryptPreKeySignalMessage(ciphertextGuard.nativeHandle(),
- remoteAddressGuard.nativeHandle(),
- sessionStore,
- identityKeyStore,
- preKeyStore,
- signedPreKeyStore,
- kyberPreKeyStore);
+ throws DuplicateMessageException,
+ InvalidMessageException,
+ InvalidKeyIdException,
+ InvalidKeyException,
+ UntrustedIdentityException {
+ try (NativeHandleGuard ciphertextGuard = new NativeHandleGuard(ciphertext);
+ NativeHandleGuard remoteAddressGuard = new NativeHandleGuard(this.remoteAddress); ) {
+ return Native.SessionCipher_DecryptPreKeySignalMessage(
+ ciphertextGuard.nativeHandle(),
+ remoteAddressGuard.nativeHandle(),
+ sessionStore,
+ identityKeyStore,
+ preKeyStore,
+ signedPreKeyStore,
+ kyberPreKeyStore);
}
}
/**
* Decrypt a message.
*
- * @param ciphertext The {@link SignalMessage} to decrypt.
- *
+ * @param ciphertext The {@link SignalMessage} to decrypt.
* @return The plaintext.
* @throws InvalidMessageException if the input is not valid ciphertext.
* @throws InvalidVersionException if the message version does not match the session version.
@@ -127,16 +146,18 @@ public byte[] decrypt(PreKeySignalMessage ciphertext)
* @throws NoSessionException if there is no established session for this contact.
*/
public byte[] decrypt(SignalMessage ciphertext)
- throws InvalidMessageException, InvalidVersionException, DuplicateMessageException, NoSessionException, UntrustedIdentityException
- {
- try (
- NativeHandleGuard ciphertextGuard = new NativeHandleGuard(ciphertext);
- NativeHandleGuard remoteAddressGuard = new NativeHandleGuard(this.remoteAddress);
- ) {
- return Native.SessionCipher_DecryptSignalMessage(ciphertextGuard.nativeHandle(),
- remoteAddressGuard.nativeHandle(),
- sessionStore,
- identityKeyStore);
+ throws InvalidMessageException,
+ InvalidVersionException,
+ DuplicateMessageException,
+ NoSessionException,
+ UntrustedIdentityException {
+ try (NativeHandleGuard ciphertextGuard = new NativeHandleGuard(ciphertext);
+ NativeHandleGuard remoteAddressGuard = new NativeHandleGuard(this.remoteAddress); ) {
+ return Native.SessionCipher_DecryptSignalMessage(
+ ciphertextGuard.nativeHandle(),
+ remoteAddressGuard.nativeHandle(),
+ sessionStore,
+ identityKeyStore);
}
}
diff --git a/java/shared/java/org/signal/libsignal/protocol/SignalProtocolAddress.java b/java/shared/java/org/signal/libsignal/protocol/SignalProtocolAddress.java
index 314159ead1..83722bf7b4 100644
--- a/java/shared/java/org/signal/libsignal/protocol/SignalProtocolAddress.java
+++ b/java/shared/java/org/signal/libsignal/protocol/SignalProtocolAddress.java
@@ -1,8 +1,8 @@
-/**
- * Copyright (C) 2014-2016 Open Whisper Systems
- *
- * Licensed according to the LICENSE file in this repository.
- */
+//
+// Copyright 2014-2016 Signal Messenger, LLC.
+// SPDX-License-Identifier: AGPL-3.0-only
+//
+
package org.signal.libsignal.protocol;
import org.signal.libsignal.internal.Native;
@@ -23,7 +23,8 @@ public SignalProtocolAddress(long unsafeHandle) {
this.unsafeHandle = unsafeHandle;
}
- @Override @SuppressWarnings("deprecation")
+ @Override
+ @SuppressWarnings("deprecation")
protected void finalize() {
Native.ProtocolAddress_Destroy(this.unsafeHandle);
}
@@ -37,7 +38,7 @@ public String getName() {
/**
* Returns a ServiceId if this address contains a valid ServiceId, {@code null} otherwise.
*
- * In a future release SignalProtocolAddresses will only support ServiceIds.
+ *
In a future release SignalProtocolAddresses will only support ServiceIds.
*/
public ServiceId getServiceId() {
try {
@@ -60,10 +61,10 @@ public String toString() {
@Override
public boolean equals(Object other) {
- if (other == null) return false;
+ if (other == null) return false;
if (!(other instanceof SignalProtocolAddress)) return false;
- SignalProtocolAddress that = (SignalProtocolAddress)other;
+ SignalProtocolAddress that = (SignalProtocolAddress) other;
return this.getName().equals(that.getName()) && this.getDeviceId() == that.getDeviceId();
}
diff --git a/java/shared/java/org/signal/libsignal/protocol/UntrustedIdentityException.java b/java/shared/java/org/signal/libsignal/protocol/UntrustedIdentityException.java
index eb3fd78fd1..821e70b036 100644
--- a/java/shared/java/org/signal/libsignal/protocol/UntrustedIdentityException.java
+++ b/java/shared/java/org/signal/libsignal/protocol/UntrustedIdentityException.java
@@ -1,8 +1,8 @@
-/**
- * Copyright (C) 2014-2016 Open Whisper Systems
- *
- * Licensed according to the LICENSE file in this repository.
- */
+//
+// Copyright 2014-2016 Signal Messenger, LLC.
+// SPDX-License-Identifier: AGPL-3.0-only
+//
+
package org.signal.libsignal.protocol;
public class UntrustedIdentityException extends Exception {
@@ -12,12 +12,12 @@ public class UntrustedIdentityException extends Exception {
public UntrustedIdentityException(String name, IdentityKey key) {
this.name = name;
- this.key = key;
+ this.key = key;
}
public UntrustedIdentityException(String name) {
this.name = name;
- this.key = null;
+ this.key = null;
}
public IdentityKey getUntrustedIdentity() {
diff --git a/java/shared/java/org/signal/libsignal/protocol/ecc/Curve.java b/java/shared/java/org/signal/libsignal/protocol/ecc/Curve.java
index 1a285509db..37862bf992 100644
--- a/java/shared/java/org/signal/libsignal/protocol/ecc/Curve.java
+++ b/java/shared/java/org/signal/libsignal/protocol/ecc/Curve.java
@@ -1,13 +1,14 @@
-/**
- * Copyright (C) 2013-2016 Open Whisper Systems
- *
- * Licensed according to the LICENSE file in this repository.
- */
+//
+// Copyright 2013-2016 Signal Messenger, LLC.
+// SPDX-License-Identifier: AGPL-3.0-only
+//
+
package org.signal.libsignal.protocol.ecc;
+
import org.signal.libsignal.protocol.InvalidKeyException;
public class Curve {
- public static final int DJB_TYPE = 0x05;
+ public static final int DJB_TYPE = 0x05;
public static ECKeyPair generateKeyPair() {
ECPrivateKey privateKey = ECPrivateKey.generate();
@@ -15,9 +16,7 @@ public static ECKeyPair generateKeyPair() {
return new ECKeyPair(publicKey, privateKey);
}
- public static ECPublicKey decodePoint(byte[] bytes, int offset)
- throws InvalidKeyException
- {
+ public static ECPublicKey decodePoint(byte[] bytes, int offset) throws InvalidKeyException {
if (bytes == null || bytes.length - offset < 1) {
throw new InvalidKeyException("No key type identifier");
}
@@ -30,8 +29,7 @@ public static ECPrivateKey decodePrivatePoint(byte[] bytes) throws InvalidKeyExc
}
public static byte[] calculateAgreement(ECPublicKey publicKey, ECPrivateKey privateKey)
- throws InvalidKeyException
- {
+ throws InvalidKeyException {
if (publicKey == null) {
throw new InvalidKeyException("public value is null");
}
@@ -44,8 +42,7 @@ public static byte[] calculateAgreement(ECPublicKey publicKey, ECPrivateKey priv
}
public static boolean verifySignature(ECPublicKey signingKey, byte[] message, byte[] signature)
- throws InvalidKeyException
- {
+ throws InvalidKeyException {
if (signingKey == null || message == null || signature == null) {
throw new InvalidKeyException("Values must not be null");
}
@@ -54,13 +51,11 @@ public static boolean verifySignature(ECPublicKey signingKey, byte[] message, by
}
public static byte[] calculateSignature(ECPrivateKey signingKey, byte[] message)
- throws InvalidKeyException
- {
+ throws InvalidKeyException {
if (signingKey == null || message == null) {
throw new InvalidKeyException("Values must not be null");
}
return signingKey.calculateSignature(message);
}
-
}
diff --git a/java/shared/java/org/signal/libsignal/protocol/ecc/ECKeyPair.java b/java/shared/java/org/signal/libsignal/protocol/ecc/ECKeyPair.java
index 1948fce273..bad1776ecf 100644
--- a/java/shared/java/org/signal/libsignal/protocol/ecc/ECKeyPair.java
+++ b/java/shared/java/org/signal/libsignal/protocol/ecc/ECKeyPair.java
@@ -1,13 +1,13 @@
-/**
- * Copyright (C) 2013-2016 Open Whisper Systems
- *
- * Licensed according to the LICENSE file in this repository.
- */
+//
+// Copyright 2013-2016 Signal Messenger, LLC.
+// SPDX-License-Identifier: AGPL-3.0-only
+//
+
package org.signal.libsignal.protocol.ecc;
public class ECKeyPair {
- private final ECPublicKey publicKey;
+ private final ECPublicKey publicKey;
private final ECPrivateKey privateKey;
public ECKeyPair(ECPublicKey publicKey, ECPrivateKey privateKey) {
diff --git a/java/shared/java/org/signal/libsignal/protocol/ecc/ECPrivateKey.java b/java/shared/java/org/signal/libsignal/protocol/ecc/ECPrivateKey.java
index ea6c652bfc..fd8b9bbc9a 100644
--- a/java/shared/java/org/signal/libsignal/protocol/ecc/ECPrivateKey.java
+++ b/java/shared/java/org/signal/libsignal/protocol/ecc/ECPrivateKey.java
@@ -1,8 +1,7 @@
-/**
- * Copyright (C) 2013-2016 Open Whisper Systems
- *
- * Licensed according to the LICENSE file in this repository.
- */
+//
+// Copyright 2013-2016 Signal Messenger, LLC.
+// SPDX-License-Identifier: AGPL-3.0-only
+//
package org.signal.libsignal.protocol.ecc;
@@ -22,15 +21,16 @@ static ECPrivateKey generate() {
}
public ECPrivateKey(long nativeHandle) {
- if(nativeHandle == 0) {
+ if (nativeHandle == 0) {
throw new NullPointerException();
}
this.unsafeHandle = nativeHandle;
}
- @Override @SuppressWarnings("deprecation")
+ @Override
+ @SuppressWarnings("deprecation")
protected void finalize() {
- Native.ECPrivateKey_Destroy(this.unsafeHandle);
+ Native.ECPrivateKey_Destroy(this.unsafeHandle);
}
public byte[] serialize() {
@@ -46,10 +46,8 @@ public byte[] calculateSignature(byte[] message) {
}
public byte[] calculateAgreement(ECPublicKey other) {
- try (
- NativeHandleGuard privateKey = new NativeHandleGuard(this);
- NativeHandleGuard publicKey = new NativeHandleGuard(other);
- ) {
+ try (NativeHandleGuard privateKey = new NativeHandleGuard(this);
+ NativeHandleGuard publicKey = new NativeHandleGuard(other); ) {
return Native.ECPrivateKey_Agree(privateKey.nativeHandle(), publicKey.nativeHandle());
}
}
diff --git a/java/shared/java/org/signal/libsignal/protocol/ecc/ECPublicKey.java b/java/shared/java/org/signal/libsignal/protocol/ecc/ECPublicKey.java
index 3bd4fe0b09..8c4546b920 100644
--- a/java/shared/java/org/signal/libsignal/protocol/ecc/ECPublicKey.java
+++ b/java/shared/java/org/signal/libsignal/protocol/ecc/ECPublicKey.java
@@ -1,15 +1,14 @@
-/**
- * Copyright (C) 2013-2016 Open Whisper Systems
- *
- * Licensed according to the LICENSE file in this repository.
- */
+//
+// Copyright 2013-2016 Signal Messenger, LLC.
+// SPDX-License-Identifier: AGPL-3.0-only
+//
package org.signal.libsignal.protocol.ecc;
+import java.util.Arrays;
import org.signal.libsignal.internal.Native;
import org.signal.libsignal.internal.NativeHandleGuard;
import org.signal.libsignal.protocol.InvalidKeyException;
-import java.util.Arrays;
public class ECPublicKey implements Comparable, NativeHandleGuard.Owner {
@@ -25,7 +24,7 @@ public ECPublicKey(byte[] serialized) throws InvalidKeyException {
this.unsafeHandle = Native.ECPublicKey_Deserialize(serialized, 0);
}
- static public ECPublicKey fromPublicKeyBytes(byte[] key) {
+ public static ECPublicKey fromPublicKeyBytes(byte[] key) {
byte[] with_type = new byte[33];
with_type[0] = 0x05;
System.arraycopy(key, 0, with_type, 1, 32);
@@ -39,9 +38,10 @@ public ECPublicKey(long nativeHandle) {
this.unsafeHandle = nativeHandle;
}
- @Override @SuppressWarnings("deprecation")
+ @Override
+ @SuppressWarnings("deprecation")
protected void finalize() {
- Native.ECPublicKey_Destroy(this.unsafeHandle);
+ Native.ECPublicKey_Destroy(this.unsafeHandle);
}
public boolean verifySignature(byte[] message, byte[] signature) {
@@ -73,12 +73,10 @@ public long unsafeNativeHandleWithoutGuard() {
@Override
public boolean equals(Object other) {
- if (other == null) return false;
+ if (other == null) return false;
if (!(other instanceof ECPublicKey)) return false;
- try (
- NativeHandleGuard thisGuard = new NativeHandleGuard(this);
- NativeHandleGuard thatGuard = new NativeHandleGuard((ECPublicKey)other);
- ) {
+ try (NativeHandleGuard thisGuard = new NativeHandleGuard(this);
+ NativeHandleGuard thatGuard = new NativeHandleGuard((ECPublicKey) other); ) {
return Native.ECPublicKey_Equals(thisGuard.nativeHandle(), thatGuard.nativeHandle());
}
}
@@ -90,10 +88,8 @@ public int hashCode() {
@Override
public int compareTo(ECPublicKey another) {
- try (
- NativeHandleGuard guard = new NativeHandleGuard(this);
- NativeHandleGuard otherGuard = new NativeHandleGuard(another);
- ) {
+ try (NativeHandleGuard guard = new NativeHandleGuard(this);
+ NativeHandleGuard otherGuard = new NativeHandleGuard(another); ) {
return Native.ECPublicKey_Compare(guard.nativeHandle(), otherGuard.nativeHandle());
}
}
diff --git a/java/shared/java/org/signal/libsignal/protocol/fingerprint/DisplayableFingerprint.java b/java/shared/java/org/signal/libsignal/protocol/fingerprint/DisplayableFingerprint.java
index 495571e341..3ba5711927 100644
--- a/java/shared/java/org/signal/libsignal/protocol/fingerprint/DisplayableFingerprint.java
+++ b/java/shared/java/org/signal/libsignal/protocol/fingerprint/DisplayableFingerprint.java
@@ -1,11 +1,9 @@
-/**
- * Copyright (C) 2016 Open Whisper Systems
- *
- * Licensed according to the LICENSE file in this repository.
- */
-package org.signal.libsignal.protocol.fingerprint;
+//
+// Copyright 2016 Signal Messenger, LLC.
+// SPDX-License-Identifier: AGPL-3.0-only
+//
-import org.signal.libsignal.internal.Native;
+package org.signal.libsignal.protocol.fingerprint;
public class DisplayableFingerprint {
private String displayString;
@@ -17,5 +15,4 @@ public class DisplayableFingerprint {
public String getDisplayText() {
return this.displayString;
}
-
}
diff --git a/java/shared/java/org/signal/libsignal/protocol/fingerprint/Fingerprint.java b/java/shared/java/org/signal/libsignal/protocol/fingerprint/Fingerprint.java
index e387764e66..dc32bc5a26 100644
--- a/java/shared/java/org/signal/libsignal/protocol/fingerprint/Fingerprint.java
+++ b/java/shared/java/org/signal/libsignal/protocol/fingerprint/Fingerprint.java
@@ -1,20 +1,19 @@
-/**
- * Copyright (C) 2016 Open Whisper Systems
- *
- * Licensed according to the LICENSE file in this repository.
- */
+//
+// Copyright 2016 Signal Messenger, LLC.
+// SPDX-License-Identifier: AGPL-3.0-only
+//
+
package org.signal.libsignal.protocol.fingerprint;
public class Fingerprint {
private final DisplayableFingerprint displayableFingerprint;
- private final ScannableFingerprint scannableFingerprint;
+ private final ScannableFingerprint scannableFingerprint;
- public Fingerprint(DisplayableFingerprint displayableFingerprint,
- ScannableFingerprint scannableFingerprint)
- {
+ public Fingerprint(
+ DisplayableFingerprint displayableFingerprint, ScannableFingerprint scannableFingerprint) {
this.displayableFingerprint = displayableFingerprint;
- this.scannableFingerprint = scannableFingerprint;
+ this.scannableFingerprint = scannableFingerprint;
}
/**
diff --git a/java/shared/java/org/signal/libsignal/protocol/fingerprint/FingerprintGenerator.java b/java/shared/java/org/signal/libsignal/protocol/fingerprint/FingerprintGenerator.java
index 2b2df9e59b..3e0fa7a19a 100644
--- a/java/shared/java/org/signal/libsignal/protocol/fingerprint/FingerprintGenerator.java
+++ b/java/shared/java/org/signal/libsignal/protocol/fingerprint/FingerprintGenerator.java
@@ -1,19 +1,17 @@
-/**
- * Copyright (C) 2016 Open Whisper Systems
- *
- * Licensed according to the LICENSE file in this repository.
- */
+//
+// Copyright 2016 Signal Messenger, LLC.
+// SPDX-License-Identifier: AGPL-3.0-only
+//
+
package org.signal.libsignal.protocol.fingerprint;
import org.signal.libsignal.protocol.IdentityKey;
-import java.util.List;
-
public interface FingerprintGenerator {
- public Fingerprint createFor(int version,
- byte[] localStableIdentifier,
- IdentityKey localIdentityKey,
- byte[] remoteStableIdentifier,
- IdentityKey remoteIdentityKey);
-
+ public Fingerprint createFor(
+ int version,
+ byte[] localStableIdentifier,
+ IdentityKey localIdentityKey,
+ byte[] remoteStableIdentifier,
+ IdentityKey remoteIdentityKey);
}
diff --git a/java/shared/java/org/signal/libsignal/protocol/fingerprint/FingerprintParsingException.java b/java/shared/java/org/signal/libsignal/protocol/fingerprint/FingerprintParsingException.java
index e878a2b05d..cf1b3a0909 100644
--- a/java/shared/java/org/signal/libsignal/protocol/fingerprint/FingerprintParsingException.java
+++ b/java/shared/java/org/signal/libsignal/protocol/fingerprint/FingerprintParsingException.java
@@ -1,8 +1,8 @@
-/**
- * Copyright (C) 2016 Open Whisper Systems
- *
- * Licensed according to the LICENSE file in this repository.
- */
+//
+// Copyright 2016 Signal Messenger, LLC.
+// SPDX-License-Identifier: AGPL-3.0-only
+//
+
package org.signal.libsignal.protocol.fingerprint;
public class FingerprintParsingException extends Exception {
@@ -10,5 +10,4 @@ public class FingerprintParsingException extends Exception {
public FingerprintParsingException(String message) {
super(message);
}
-
}
diff --git a/java/shared/java/org/signal/libsignal/protocol/fingerprint/FingerprintVersionMismatchException.java b/java/shared/java/org/signal/libsignal/protocol/fingerprint/FingerprintVersionMismatchException.java
index 1057737fed..98956a8e5c 100644
--- a/java/shared/java/org/signal/libsignal/protocol/fingerprint/FingerprintVersionMismatchException.java
+++ b/java/shared/java/org/signal/libsignal/protocol/fingerprint/FingerprintVersionMismatchException.java
@@ -1,8 +1,8 @@
-/**
- * Copyright (C) 2016 Open Whisper Systems
- *
- * Licensed according to the LICENSE file in this repository.
- */
+//
+// Copyright 2016 Signal Messenger, LLC.
+// SPDX-License-Identifier: AGPL-3.0-only
+//
+
package org.signal.libsignal.protocol.fingerprint;
public class FingerprintVersionMismatchException extends Exception {
@@ -13,7 +13,7 @@ public class FingerprintVersionMismatchException extends Exception {
public FingerprintVersionMismatchException(int theirVersion, int ourVersion) {
super();
this.theirVersion = theirVersion;
- this.ourVersion = ourVersion;
+ this.ourVersion = ourVersion;
}
public int getTheirVersion() {
diff --git a/java/shared/java/org/signal/libsignal/protocol/fingerprint/NumericFingerprintGenerator.java b/java/shared/java/org/signal/libsignal/protocol/fingerprint/NumericFingerprintGenerator.java
index e706e65656..f69ac7769d 100644
--- a/java/shared/java/org/signal/libsignal/protocol/fingerprint/NumericFingerprintGenerator.java
+++ b/java/shared/java/org/signal/libsignal/protocol/fingerprint/NumericFingerprintGenerator.java
@@ -1,8 +1,8 @@
-/**
- * Copyright (C) 2016 Open Whisper Systems
- *
- * Licensed according to the LICENSE file in this repository.
- */
+//
+// Copyright 2016 Signal Messenger, LLC.
+// SPDX-License-Identifier: AGPL-3.0-only
+//
+
package org.signal.libsignal.protocol.fingerprint;
import org.signal.libsignal.internal.Native;
@@ -14,15 +14,14 @@ public class NumericFingerprintGenerator implements FingerprintGenerator {
/**
* Construct a fingerprint generator for 60 digit numerics.
*
- * @param iterations The number of internal iterations to perform in the process of
- * generating a fingerprint. This needs to be constant, and synchronized
- * across all clients.
- *
- * The higher the iteration count, the higher the security level:
- *
- * - 1024 ~ 109.7 bits
- * - 1400 > 110 bits
- * - 5200 > 112 bits
+ * @param iterations The number of internal iterations to perform in the process of generating a
+ * fingerprint. This needs to be constant, and synchronized across all clients.
+ * The higher the iteration count, the higher the security level:
+ *
+ * 1024 ~ 109.7 bits
+ * 1400 > 110 bits
+ * 5200 > 112 bits
+ *
*/
public NumericFingerprintGenerator(int iterations) {
this.iterations = iterations;
@@ -39,25 +38,30 @@ public NumericFingerprintGenerator(int iterations) {
* @return A unique fingerprint for this conversation.
*/
@Override
- public Fingerprint createFor(int version,
- byte[] localStableIdentifier,
- final IdentityKey localIdentityKey,
- byte[] remoteStableIdentifier,
- final IdentityKey remoteIdentityKey) {
+ public Fingerprint createFor(
+ int version,
+ byte[] localStableIdentifier,
+ final IdentityKey localIdentityKey,
+ byte[] remoteStableIdentifier,
+ final IdentityKey remoteIdentityKey) {
- long handle = Native.NumericFingerprintGenerator_New(this.iterations, version,
- localStableIdentifier,
- localIdentityKey.serialize(),
- remoteStableIdentifier,
- remoteIdentityKey.serialize());
+ long handle =
+ Native.NumericFingerprintGenerator_New(
+ this.iterations,
+ version,
+ localStableIdentifier,
+ localIdentityKey.serialize(),
+ remoteStableIdentifier,
+ remoteIdentityKey.serialize());
- DisplayableFingerprint displayableFingerprint = new DisplayableFingerprint(Native.NumericFingerprintGenerator_GetDisplayString(handle));
+ DisplayableFingerprint displayableFingerprint =
+ new DisplayableFingerprint(Native.NumericFingerprintGenerator_GetDisplayString(handle));
- ScannableFingerprint scannableFingerprint = new ScannableFingerprint(Native.NumericFingerprintGenerator_GetScannableEncoding(handle));
+ ScannableFingerprint scannableFingerprint =
+ new ScannableFingerprint(Native.NumericFingerprintGenerator_GetScannableEncoding(handle));
Native.NumericFingerprintGenerator_Destroy(handle);
return new Fingerprint(displayableFingerprint, scannableFingerprint);
}
-
}
diff --git a/java/shared/java/org/signal/libsignal/protocol/fingerprint/ScannableFingerprint.java b/java/shared/java/org/signal/libsignal/protocol/fingerprint/ScannableFingerprint.java
index b44023895c..174173d205 100644
--- a/java/shared/java/org/signal/libsignal/protocol/fingerprint/ScannableFingerprint.java
+++ b/java/shared/java/org/signal/libsignal/protocol/fingerprint/ScannableFingerprint.java
@@ -1,8 +1,8 @@
-/**
- * Copyright (C) 2016 Open Whisper Systems
- *
- * Licensed according to the LICENSE file in this repository.
- */
+//
+// Copyright 2016 Signal Messenger, LLC.
+// SPDX-License-Identifier: AGPL-3.0-only
+//
+
package org.signal.libsignal.protocol.fingerprint;
import org.signal.libsignal.internal.Native;
@@ -29,9 +29,7 @@ public byte[] getSerialized() {
* @throws FingerprintVersionMismatchException if the scanned fingerprint is the wrong version.
*/
public boolean compareTo(byte[] scannedFingerprintData)
- throws FingerprintVersionMismatchException,
- FingerprintParsingException
- {
+ throws FingerprintVersionMismatchException, FingerprintParsingException {
return Native.ScannableFingerprint_Compare(this.encodedFingerprint, scannedFingerprintData);
}
}
diff --git a/java/shared/java/org/signal/libsignal/protocol/groups/GroupCipher.java b/java/shared/java/org/signal/libsignal/protocol/groups/GroupCipher.java
index a40a0cabab..0aa8e43c43 100644
--- a/java/shared/java/org/signal/libsignal/protocol/groups/GroupCipher.java
+++ b/java/shared/java/org/signal/libsignal/protocol/groups/GroupCipher.java
@@ -1,14 +1,14 @@
-/**
- * Copyright (C) 2014-2016 Open Whisper Systems
- *
- * Licensed according to the LICENSE file in this repository.
- */
+//
+// Copyright 2014-2016 Signal Messenger, LLC.
+// SPDX-License-Identifier: AGPL-3.0-only
+//
+
package org.signal.libsignal.protocol.groups;
+import java.util.UUID;
import org.signal.libsignal.internal.Native;
import org.signal.libsignal.internal.NativeHandleGuard;
import org.signal.libsignal.protocol.DuplicateMessageException;
-import org.signal.libsignal.protocol.InvalidKeyIdException;
import org.signal.libsignal.protocol.InvalidMessageException;
import org.signal.libsignal.protocol.LegacyMessageException;
import org.signal.libsignal.protocol.NoSessionException;
@@ -16,19 +16,16 @@
import org.signal.libsignal.protocol.groups.state.SenderKeyStore;
import org.signal.libsignal.protocol.message.CiphertextMessage;
-import java.security.InvalidAlgorithmParameterException;
-import java.security.NoSuchAlgorithmException;
-import java.util.UUID;
-
/**
* The main entry point for Signal Protocol group encrypt/decrypt operations.
*
- * Once a session has been established with {@link org.signal.libsignal.protocol.groups.GroupSessionBuilder}
- * and a {@link org.signal.libsignal.protocol.message.SenderKeyDistributionMessage} has been
- * distributed to each member of the group, this class can be used for all subsequent encrypt/decrypt
- * operations within that session (ie: until group membership changes).
+ * Once a session has been established with {@link
+ * org.signal.libsignal.protocol.groups.GroupSessionBuilder} and a {@link
+ * org.signal.libsignal.protocol.message.SenderKeyDistributionMessage} has been distributed to each
+ * member of the group, this class can be used for all subsequent encrypt/decrypt operations within
+ * that session (ie: until group membership changes).
*
- * This class is not thread-safe.
+ *
This class is not thread-safe.
*
* @author Moxie Marlinspike
*/
@@ -39,7 +36,7 @@ public class GroupCipher {
public GroupCipher(SenderKeyStore senderKeyStore, SignalProtocolAddress sender) {
this.senderKeyStore = senderKeyStore;
- this.sender = sender;
+ this.sender = sender;
}
/**
@@ -49,9 +46,11 @@ public GroupCipher(SenderKeyStore senderKeyStore, SignalProtocolAddress sender)
* @return Ciphertext.
* @throws NoSessionException
*/
- public CiphertextMessage encrypt(UUID distributionId, byte[] paddedPlaintext) throws NoSessionException {
+ public CiphertextMessage encrypt(UUID distributionId, byte[] paddedPlaintext)
+ throws NoSessionException {
try (NativeHandleGuard sender = new NativeHandleGuard(this.sender)) {
- return Native.GroupCipher_EncryptMessage(sender.nativeHandle(), distributionId, paddedPlaintext, this.senderKeyStore);
+ return Native.GroupCipher_EncryptMessage(
+ sender.nativeHandle(), distributionId, paddedPlaintext, this.senderKeyStore);
}
}
@@ -65,10 +64,13 @@ public CiphertextMessage encrypt(UUID distributionId, byte[] paddedPlaintext) th
* @throws DuplicateMessageException
*/
public byte[] decrypt(byte[] senderKeyMessageBytes)
- throws LegacyMessageException, DuplicateMessageException, InvalidMessageException, NoSessionException
- {
+ throws LegacyMessageException,
+ DuplicateMessageException,
+ InvalidMessageException,
+ NoSessionException {
try (NativeHandleGuard sender = new NativeHandleGuard(this.sender)) {
- return Native.GroupCipher_DecryptMessage(sender.nativeHandle(), senderKeyMessageBytes, this.senderKeyStore);
+ return Native.GroupCipher_DecryptMessage(
+ sender.nativeHandle(), senderKeyMessageBytes, this.senderKeyStore);
}
}
}
diff --git a/java/shared/java/org/signal/libsignal/protocol/groups/GroupSessionBuilder.java b/java/shared/java/org/signal/libsignal/protocol/groups/GroupSessionBuilder.java
index 7e14b0c253..b258448684 100644
--- a/java/shared/java/org/signal/libsignal/protocol/groups/GroupSessionBuilder.java
+++ b/java/shared/java/org/signal/libsignal/protocol/groups/GroupSessionBuilder.java
@@ -1,36 +1,34 @@
-/**
- * Copyright (C) 2014-2016 Open Whisper Systems
- *
- * Licensed according to the LICENSE file in this repository.
- */
+//
+// Copyright 2014-2016 Signal Messenger, LLC.
+// SPDX-License-Identifier: AGPL-3.0-only
+//
+
package org.signal.libsignal.protocol.groups;
+import java.util.UUID;
import org.signal.libsignal.internal.Native;
import org.signal.libsignal.internal.NativeHandleGuard;
import org.signal.libsignal.protocol.SignalProtocolAddress;
import org.signal.libsignal.protocol.groups.state.SenderKeyStore;
import org.signal.libsignal.protocol.message.SenderKeyDistributionMessage;
-import java.util.UUID;
-
/**
* GroupSessionBuilder is responsible for setting up group SenderKey encrypted sessions.
*
- * Once a session has been established, {@link org.signal.libsignal.protocol.groups.GroupCipher}
+ *
Once a session has been established, {@link org.signal.libsignal.protocol.groups.GroupCipher}
* can be used to encrypt/decrypt messages in that session.
- *
- * The built sessions are unidirectional: they can be used either for sending or for receiving,
+ *
+ *
The built sessions are unidirectional: they can be used either for sending or for receiving,
* but not both.
*
- * Sessions are constructed per (senderName + deviceId) tuple, with sending additionally
- * parameterized on a per-group distributionId. Remote logical users are identified by their
+ *
Sessions are constructed per (senderName + deviceId) tuple, with sending additionally
+ * parameterized on a per-group distributionId. Remote logical users are identified by their
* senderName, and each logical user can have multiple physical devices.
*
- * This class is not thread-safe.
+ *
This class is not thread-safe.
*
* @author Moxie Marlinspike
*/
-
public class GroupSessionBuilder {
private final SenderKeyStore senderKeyStore;
@@ -44,15 +42,12 @@ public GroupSessionBuilder(SenderKeyStore senderKeyStore) {
* @param sender The address of the device that sent the message.
* @param senderKeyDistributionMessage A received SenderKeyDistributionMessage.
*/
- public void process(SignalProtocolAddress sender, SenderKeyDistributionMessage senderKeyDistributionMessage) {
- try (
- NativeHandleGuard senderGuard = new NativeHandleGuard(sender);
- NativeHandleGuard skdmGuard = new NativeHandleGuard(senderKeyDistributionMessage);
- ) {
+ public void process(
+ SignalProtocolAddress sender, SenderKeyDistributionMessage senderKeyDistributionMessage) {
+ try (NativeHandleGuard senderGuard = new NativeHandleGuard(sender);
+ NativeHandleGuard skdmGuard = new NativeHandleGuard(senderKeyDistributionMessage); ) {
Native.GroupSessionBuilder_ProcessSenderKeyDistributionMessage(
- senderGuard.nativeHandle(),
- skdmGuard.nativeHandle(),
- senderKeyStore);
+ senderGuard.nativeHandle(), skdmGuard.nativeHandle(), senderKeyStore);
}
}
@@ -60,12 +55,16 @@ public void process(SignalProtocolAddress sender, SenderKeyDistributionMessage s
* Construct a group session for sending messages.
*
* @param sender The address of the current client.
- * @param distributionId An opaque identifier that uniquely identifies the group (but isn't the group ID).
- * @return A SenderKeyDistributionMessage that is individually distributed to each member of the group.
+ * @param distributionId An opaque identifier that uniquely identifies the group (but isn't the
+ * group ID).
+ * @return A SenderKeyDistributionMessage that is individually distributed to each member of the
+ * group.
*/
public SenderKeyDistributionMessage create(SignalProtocolAddress sender, UUID distributionId) {
try (NativeHandleGuard senderGuard = new NativeHandleGuard(sender)) {
- return new SenderKeyDistributionMessage(Native.GroupSessionBuilder_CreateSenderKeyDistributionMessage(senderGuard.nativeHandle(), distributionId, senderKeyStore));
+ return new SenderKeyDistributionMessage(
+ Native.GroupSessionBuilder_CreateSenderKeyDistributionMessage(
+ senderGuard.nativeHandle(), distributionId, senderKeyStore));
}
}
}
diff --git a/java/shared/java/org/signal/libsignal/protocol/groups/InvalidSenderKeySessionException.java b/java/shared/java/org/signal/libsignal/protocol/groups/InvalidSenderKeySessionException.java
index fa6bbd96c2..bf805f6570 100644
--- a/java/shared/java/org/signal/libsignal/protocol/groups/InvalidSenderKeySessionException.java
+++ b/java/shared/java/org/signal/libsignal/protocol/groups/InvalidSenderKeySessionException.java
@@ -1,8 +1,8 @@
-/**
- * Copyright (C) 2021 Open Whisper Systems
- *
- * Licensed according to the LICENSE file in this repository.
- */
+//
+// Copyright 2021 Signal Messenger, LLC.
+// SPDX-License-Identifier: AGPL-3.0-only
+//
+
package org.signal.libsignal.protocol.groups;
import java.util.UUID;
diff --git a/java/shared/java/org/signal/libsignal/protocol/groups/state/InMemorySenderKeyStore.java b/java/shared/java/org/signal/libsignal/protocol/groups/state/InMemorySenderKeyStore.java
index 1456f6d9de..75343e1037 100644
--- a/java/shared/java/org/signal/libsignal/protocol/groups/state/InMemorySenderKeyStore.java
+++ b/java/shared/java/org/signal/libsignal/protocol/groups/state/InMemorySenderKeyStore.java
@@ -1,21 +1,24 @@
-package org.signal.libsignal.protocol.groups.state;
+//
+// Copyright 2023 Signal Messenger, LLC.
+// SPDX-License-Identifier: AGPL-3.0-only
+//
-import org.signal.libsignal.protocol.groups.state.SenderKeyRecord;
-import org.signal.libsignal.protocol.groups.state.SenderKeyStore;
-import org.signal.libsignal.protocol.InvalidMessageException;
-import org.signal.libsignal.protocol.SignalProtocolAddress;
-import org.signal.libsignal.protocol.util.Pair;
+package org.signal.libsignal.protocol.groups.state;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
+import org.signal.libsignal.protocol.InvalidMessageException;
+import org.signal.libsignal.protocol.SignalProtocolAddress;
+import org.signal.libsignal.protocol.util.Pair;
public class InMemorySenderKeyStore implements SenderKeyStore {
private final Map, SenderKeyRecord> store = new HashMap<>();
@Override
- public void storeSenderKey(SignalProtocolAddress sender, UUID distributionId, SenderKeyRecord record) {
+ public void storeSenderKey(
+ SignalProtocolAddress sender, UUID distributionId, SenderKeyRecord record) {
store.put(new Pair<>(sender, distributionId), record);
}
diff --git a/java/shared/java/org/signal/libsignal/protocol/groups/state/SenderKeyRecord.java b/java/shared/java/org/signal/libsignal/protocol/groups/state/SenderKeyRecord.java
index 85cbe14382..2e8bd47b46 100644
--- a/java/shared/java/org/signal/libsignal/protocol/groups/state/SenderKeyRecord.java
+++ b/java/shared/java/org/signal/libsignal/protocol/groups/state/SenderKeyRecord.java
@@ -1,8 +1,8 @@
-/**
- * Copyright (C) 2014-2016 Open Whisper Systems
- *
- * Licensed according to the LICENSE file in this repository.
- */
+//
+// Copyright 2014-2016 Signal Messenger, LLC.
+// SPDX-License-Identifier: AGPL-3.0-only
+//
+
package org.signal.libsignal.protocol.groups.state;
import org.signal.libsignal.internal.Native;
@@ -10,15 +10,16 @@
import org.signal.libsignal.protocol.InvalidMessageException;
/**
- * A durable representation of a set of SenderKeyStates for a specific
- * (senderName, deviceId, distributionId) tuple.
+ * A durable representation of a set of SenderKeyStates for a specific (senderName, deviceId,
+ * distributionId) tuple.
*
* @author Moxie Marlinspike
*/
public class SenderKeyRecord implements NativeHandleGuard.Owner {
private final long unsafeHandle;
- @Override @SuppressWarnings("deprecation")
+ @Override
+ @SuppressWarnings("deprecation")
protected void finalize() {
Native.SenderKeyRecord_Destroy(this.unsafeHandle);
}
diff --git a/java/shared/java/org/signal/libsignal/protocol/groups/state/SenderKeyStore.java b/java/shared/java/org/signal/libsignal/protocol/groups/state/SenderKeyStore.java
index 466b11c4ca..d4dd0f82a4 100644
--- a/java/shared/java/org/signal/libsignal/protocol/groups/state/SenderKeyStore.java
+++ b/java/shared/java/org/signal/libsignal/protocol/groups/state/SenderKeyStore.java
@@ -1,13 +1,12 @@
-/**
- * Copyright (C) 2014-2016 Open Whisper Systems
- *
- * Licensed according to the LICENSE file in this repository.
- */
-package org.signal.libsignal.protocol.groups.state;
+//
+// Copyright 2014-2016 Signal Messenger, LLC.
+// SPDX-License-Identifier: AGPL-3.0-only
+//
-import org.signal.libsignal.protocol.SignalProtocolAddress;
+package org.signal.libsignal.protocol.groups.state;
import java.util.UUID;
+import org.signal.libsignal.protocol.SignalProtocolAddress;
public interface SenderKeyStore {
@@ -16,25 +15,29 @@ public interface SenderKeyStore {
* given (distributionId + senderName + deviceId) tuple.
*
* @param sender The address of the current client.
- * @param distributionId An opaque identifier that uniquely identifies the group (but isn't the group ID).
- * @param record the current SenderKeyRecord for the specified (distributionId + senderName + deviceId) tuple.
+ * @param distributionId An opaque identifier that uniquely identifies the group (but isn't the
+ * group ID).
+ * @param record the current SenderKeyRecord for the specified (distributionId + senderName +
+ * deviceId) tuple.
*/
- public void storeSenderKey(SignalProtocolAddress sender, UUID distributionId, SenderKeyRecord record);
+ public void storeSenderKey(
+ SignalProtocolAddress sender, UUID distributionId, SenderKeyRecord record);
/**
* Returns a copy of the {@link org.signal.libsignal.protocol.groups.state.SenderKeyRecord}
- * corresponding to the (distributionId + senderName + deviceId) tuple, or `null` if one does not
+ * corresponding to the (distributionId + senderName + deviceId) tuple, or `null` if one does not
* exist.
- *
- * It is important that implementations return a copy of the current durable information. The
+ *
+ * It is important that implementations return a copy of the current durable information. The
* returned SenderKeyRecord may be modified, but those changes should not have an effect on the
- * durable session state (what is returned by subsequent calls to this method) without the
- * store method being called here first.
+ * durable session state (what is returned by subsequent calls to this method) without the store
+ * method being called here first.
*
* @param sender The address of the current client.
- * @param distributionId An opaque identifier that uniquely identifies the group (but isn't the group ID).
- * @return a copy of the SenderKeyRecord corresponding to the (id + senderName + deviceId tuple, or
- * `null` if one does not currently exist.
+ * @param distributionId An opaque identifier that uniquely identifies the group (but isn't the
+ * group ID).
+ * @return a copy of the SenderKeyRecord corresponding to the (id + senderName + deviceId tuple,
+ * or `null` if one does not currently exist.
*/
public SenderKeyRecord loadSenderKey(SignalProtocolAddress sender, UUID distributionId);
}
diff --git a/java/shared/java/org/signal/libsignal/protocol/incrementalmac/ChunkSizeChoice.java b/java/shared/java/org/signal/libsignal/protocol/incrementalmac/ChunkSizeChoice.java
index f8edd2cf77..d60a68a150 100644
--- a/java/shared/java/org/signal/libsignal/protocol/incrementalmac/ChunkSizeChoice.java
+++ b/java/shared/java/org/signal/libsignal/protocol/incrementalmac/ChunkSizeChoice.java
@@ -9,37 +9,37 @@
public abstract class ChunkSizeChoice {
- public abstract int getSizeInBytes();
+ public abstract int getSizeInBytes();
- public static ChunkSizeChoice everyNthByte(int n) {
- return new EveryN(n);
- }
+ public static ChunkSizeChoice everyNthByte(int n) {
+ return new EveryN(n);
+ }
- public static ChunkSizeChoice inferChunkSize(int dataSize) {
- return new ChunksOf(dataSize);
- }
+ public static ChunkSizeChoice inferChunkSize(int dataSize) {
+ return new ChunksOf(dataSize);
+ }
- private static final class EveryN extends ChunkSizeChoice {
- private int n;
+ private static final class EveryN extends ChunkSizeChoice {
+ private int n;
- private EveryN(int n) {
- this.n = n;
- }
+ private EveryN(int n) {
+ this.n = n;
+ }
- public int getSizeInBytes() {
- return this.n;
- }
+ public int getSizeInBytes() {
+ return this.n;
}
+ }
- private static final class ChunksOf extends ChunkSizeChoice {
- private int dataSize;
+ private static final class ChunksOf extends ChunkSizeChoice {
+ private int dataSize;
- private ChunksOf(int dataSize) {
- this.dataSize = dataSize;
- }
+ private ChunksOf(int dataSize) {
+ this.dataSize = dataSize;
+ }
- public int getSizeInBytes() {
- return Native.IncrementalMac_CalculateChunkSize(this.dataSize);
- }
+ public int getSizeInBytes() {
+ return Native.IncrementalMac_CalculateChunkSize(this.dataSize);
}
+ }
}
diff --git a/java/shared/java/org/signal/libsignal/protocol/incrementalmac/IncrementalMacInputStream.java b/java/shared/java/org/signal/libsignal/protocol/incrementalmac/IncrementalMacInputStream.java
index 008c3016af..fd7f20ba42 100644
--- a/java/shared/java/org/signal/libsignal/protocol/incrementalmac/IncrementalMacInputStream.java
+++ b/java/shared/java/org/signal/libsignal/protocol/incrementalmac/IncrementalMacInputStream.java
@@ -5,53 +5,102 @@
package org.signal.libsignal.protocol.incrementalmac;
-import org.signal.libsignal.internal.Native;
-
import java.io.IOException;
import java.io.InputStream;
+import java.nio.ByteBuffer;
+import java.nio.channels.Channels;
+import java.nio.channels.ReadableByteChannel;
+import org.signal.libsignal.internal.Native;
public final class IncrementalMacInputStream extends InputStream {
- private final long validatingMac;
+ private static final int MAX_BUFFER_SIZE = 8192;
+ private final long validatingMac;
+
+ private final ReadableByteChannel inner;
+ private boolean closed = false;
+
+ private ByteBuffer currentChunk;
+
+ public IncrementalMacInputStream(
+ InputStream inner, byte[] key, ChunkSizeChoice sizeChoice, byte[] digest) {
+ int chunkSize = sizeChoice.getSizeInBytes();
+ this.currentChunk = ByteBuffer.allocateDirect(chunkSize);
+ this.currentChunk.limit(0);
+ this.validatingMac = Native.ValidatingMac_Initialize(key, chunkSize, digest);
+ this.inner = Channels.newChannel(inner);
+ }
+
+ @Override
+ public int read() throws IOException {
+ byte[] bytes = new byte[1];
+ int read = this.readInternal(bytes, 0, 1);
+ return (read < 0) ? -1 : (int) bytes[0];
+ }
- private final InputStream inner;
- private boolean closed = false;
+ @Override
+ public int read(byte[] bytes, int offset, int length) throws IOException {
+ return this.readInternal(bytes, offset, length);
+ }
- public IncrementalMacInputStream(InputStream inner, byte[] key, ChunkSizeChoice sizeChoice, byte[] digest) {
- int chunkSize = sizeChoice.getSizeInBytes();
- this.validatingMac = Native.ValidatingMac_Initialize(key, chunkSize, digest);
- this.inner = inner;
+ @Override
+ public void close() throws IOException {
+ if (this.closed) {
+ return;
}
+ this.inner.close();
+ Native.ValidatingMac_Destroy(this.validatingMac);
+ this.closed = true;
+ }
- @Override
- public int read() throws IOException {
- int read = this.inner.read();
- // Narrowing conversion to byte is expected and intentional
- byte[] bytes = {(byte) read};
- int bytesLength = (read == -1) ? -1 : 1;
- return handleRead(bytes, 0, bytesLength);
+ private int readInternal(byte[] bytes, int offset, int requestedLen) throws IOException {
+ if (!this.currentChunk.hasRemaining()) {
+ this.currentChunk.clear();
+ int bytesRead = this.inner.read(this.currentChunk);
+ this.currentChunk.flip();
+ if (bytesRead <= 0) {
+ return -1;
+ }
+ this.validateChunk(this.currentChunk.slice(), this.currentChunk.capacity());
}
+ int bytesToRead = Math.min(this.currentChunk.remaining(), requestedLen);
+ this.currentChunk.get(bytes, offset, bytesToRead);
+ return bytesToRead;
+ }
- @Override
- public int read(byte[] bytes, int offset, int length) throws IOException {
- int read = this.inner.read(bytes, offset, length);
- return handleRead(bytes, offset, read);
+ private void validateChunk(ByteBuffer chunk, int expectedChunkSize) throws IOException {
+ // Should only be called right after the chunk (full or incomplete) is read.
+ // chunk is a slice of this.currentChunk therefore limit() and capacity()
+ // can be used interchangeably.
+ assert chunk.limit() == chunk.capacity() : "Must be invoked with ByteBuffer.slice()";
+ boolean isFullChunkAvailable = chunk.limit() == expectedChunkSize;
+ assertValidBytes(validateChunkImpl(chunk));
+ if (!isFullChunkAvailable) {
+ assertValidBytes(Native.ValidatingMac_Finalize(this.validatingMac));
}
+ }
- private int handleRead(byte[] bytes, int offset, int read) throws IOException {
- boolean isValid = (read == -1) ? Native.ValidatingMac_Finalize(this.validatingMac) : Native.ValidatingMac_Update(this.validatingMac, bytes, offset, read);
- if (!isValid) {
- throw new InvalidMacException();
- }
- return read;
+ private static void assertValidBytes(int validBytesCount) throws InvalidMacException {
+ if (validBytesCount < 0) {
+ throw new InvalidMacException();
}
+ }
- @Override
- public void close() throws IOException {
- if (this.closed) {
- return;
- }
- this.inner.close();
- Native.ValidatingMac_Destroy(this.validatingMac);
- this.closed = true;
+ private int validateChunkImpl(ByteBuffer chunk) {
+ int validBytes = 0;
+ int bufferSize = Math.min(chunk.limit(), MAX_BUFFER_SIZE);
+ // Using a smaller buffer and a loop because ByteBuffer.get requires a
+ // managed byte[] but we want to avoid allocating whole chunks in managed
+ // heap
+ byte[] buffer = new byte[bufferSize];
+ while (chunk.hasRemaining()) {
+ int currentlyValidating = Math.min(bufferSize, chunk.remaining());
+ chunk.get(buffer, 0, currentlyValidating);
+ // Because we are reading one chunk at a time only the last update will return a non-zero
+ // value
+ validBytes = Native.ValidatingMac_Update(this.validatingMac, buffer, 0, currentlyValidating);
+ assert validBytes == 0 || validBytes == -1 || validBytes == chunk.limit()
+ : "Unexpected incremental mac update result";
}
+ return validBytes;
+ }
}
diff --git a/java/shared/java/org/signal/libsignal/protocol/incrementalmac/IncrementalMacOutputStream.java b/java/shared/java/org/signal/libsignal/protocol/incrementalmac/IncrementalMacOutputStream.java
index 34f416aa24..bff3faa70f 100644
--- a/java/shared/java/org/signal/libsignal/protocol/incrementalmac/IncrementalMacOutputStream.java
+++ b/java/shared/java/org/signal/libsignal/protocol/incrementalmac/IncrementalMacOutputStream.java
@@ -5,67 +5,70 @@
package org.signal.libsignal.protocol.incrementalmac;
-import org.signal.libsignal.internal.Native;
-
import java.io.IOException;
import java.io.OutputStream;
+import org.signal.libsignal.internal.Native;
public final class IncrementalMacOutputStream extends OutputStream {
- private final long incrementalMac;
- private final OutputStream digestStream;
- private final OutputStream inner;
- private boolean closed = false;
+ private final long incrementalMac;
+ private final OutputStream digestStream;
+ private final OutputStream inner;
+ private boolean closed = false;
- public IncrementalMacOutputStream(OutputStream inner, byte[] key, ChunkSizeChoice sizeChoice, OutputStream digestStream) {
- int chunkSize = sizeChoice.getSizeInBytes();
- this.incrementalMac = Native.IncrementalMac_Initialize(key, chunkSize);
- this.inner = inner;
- this.digestStream = digestStream;
- }
+ public IncrementalMacOutputStream(
+ OutputStream inner, byte[] key, ChunkSizeChoice sizeChoice, OutputStream digestStream) {
+ int chunkSize = sizeChoice.getSizeInBytes();
+ this.incrementalMac = Native.IncrementalMac_Initialize(key, chunkSize);
+ this.inner = inner;
+ this.digestStream = digestStream;
+ }
- @Override
- public void write(byte[] buffer) throws IOException {
- this.inner.write(buffer);
- byte[] digestIncrement = Native.IncrementalMac_Update(this.incrementalMac, buffer, 0, buffer.length);
- digestStream.write(digestIncrement);
- }
+ @Override
+ public void write(byte[] buffer) throws IOException {
+ this.inner.write(buffer);
+ byte[] digestIncrement =
+ Native.IncrementalMac_Update(this.incrementalMac, buffer, 0, buffer.length);
+ digestStream.write(digestIncrement);
+ }
- @Override
- public void write(byte[] buffer, int offset, int length) throws IOException {
- this.inner.write(buffer, offset, length);
- byte[] digestIncrement = Native.IncrementalMac_Update(this.incrementalMac, buffer, offset, length);
- digestStream.write(digestIncrement);
- }
+ @Override
+ public void write(byte[] buffer, int offset, int length) throws IOException {
+ this.inner.write(buffer, offset, length);
+ byte[] digestIncrement =
+ Native.IncrementalMac_Update(this.incrementalMac, buffer, offset, length);
+ digestStream.write(digestIncrement);
+ }
- @Override
- public void write(int b) throws IOException {
- // According to the spec the narrowing conversion to byte is expected here
- byte[] bytes = {(byte) b};
- byte[] digestIncrement = Native.IncrementalMac_Update(this.incrementalMac, bytes, 0, 1);
- this.inner.write(b);
- this.digestStream.write(digestIncrement);
- }
+ @Override
+ public void write(int b) throws IOException {
+ // According to the spec the narrowing conversion to byte is expected here
+ byte[] bytes = {(byte) b};
+ byte[] digestIncrement = Native.IncrementalMac_Update(this.incrementalMac, bytes, 0, 1);
+ this.inner.write(b);
+ this.digestStream.write(digestIncrement);
+ }
- @Override
- public void flush() throws IOException {
- this.inner.flush();
- digestStream.flush();
- }
+ @Override
+ public void flush() throws IOException {
+ this.inner.flush();
+ digestStream.flush();
+ }
- @Override
- public void close() throws IOException {
- if (this.closed) {
- return;
- }
- try {
- flush();
- } catch (IOException ignored) {
- }
- byte[] digestIncrement = Native.IncrementalMac_Finalize(this.incrementalMac);
- digestStream.write(digestIncrement);
- Native.IncrementalMac_Destroy(this.incrementalMac);
- this.inner.close();
- this.digestStream.close();
- this.closed = true;
+ @Override
+ public void close() throws IOException {
+ if (this.closed) {
+ return;
+ }
+ try {
+ flush();
+ } catch (IOException ignored) {
}
+ byte[] digestIncrement = Native.IncrementalMac_Finalize(this.incrementalMac);
+ digestStream.write(digestIncrement);
+ Native.IncrementalMac_Destroy(this.incrementalMac);
+ // Intentionally not closing the inner stream, as it seems to be causing
+ // problems on Android
+ this.digestStream.close();
+ this.closed = true;
+ }
}
diff --git a/java/shared/java/org/signal/libsignal/protocol/incrementalmac/InvalidMacException.java b/java/shared/java/org/signal/libsignal/protocol/incrementalmac/InvalidMacException.java
index 15547632e3..f34105a47c 100644
--- a/java/shared/java/org/signal/libsignal/protocol/incrementalmac/InvalidMacException.java
+++ b/java/shared/java/org/signal/libsignal/protocol/incrementalmac/InvalidMacException.java
@@ -2,9 +2,9 @@
// Copyright 2023 Signal Messenger, LLC.
// SPDX-License-Identifier: AGPL-3.0-only
//
+
package org.signal.libsignal.protocol.incrementalmac;
import java.io.IOException;
-public class InvalidMacException extends IOException {
-}
+public class InvalidMacException extends IOException {}
diff --git a/java/shared/java/org/signal/libsignal/protocol/kdf/HKDF.java b/java/shared/java/org/signal/libsignal/protocol/kdf/HKDF.java
index e074b61f1a..70a3447d31 100644
--- a/java/shared/java/org/signal/libsignal/protocol/kdf/HKDF.java
+++ b/java/shared/java/org/signal/libsignal/protocol/kdf/HKDF.java
@@ -1,8 +1,7 @@
-/**
- * Copyright (C) 2013-2016 Open Whisper Systems
- *
- * Licensed according to the LICENSE file in this repository.
- */
+//
+// Copyright 2013-2016 Signal Messenger, LLC.
+// SPDX-License-Identifier: AGPL-3.0-only
+//
package org.signal.libsignal.protocol.kdf;
@@ -13,7 +12,8 @@ public static byte[] deriveSecrets(byte[] inputKeyMaterial, byte[] info, int out
return Native.HKDF_DeriveSecrets(outputLength, inputKeyMaterial, info, null);
}
- public static byte[] deriveSecrets(byte[] inputKeyMaterial, byte[] salt, byte[] info, int outputLength) {
+ public static byte[] deriveSecrets(
+ byte[] inputKeyMaterial, byte[] salt, byte[] info, int outputLength) {
return Native.HKDF_DeriveSecrets(outputLength, inputKeyMaterial, info, salt);
}
}
diff --git a/java/shared/java/org/signal/libsignal/protocol/kdf/HKDFv3.java b/java/shared/java/org/signal/libsignal/protocol/kdf/HKDFv3.java
index 4ecb4e7901..ac9aca10d7 100644
--- a/java/shared/java/org/signal/libsignal/protocol/kdf/HKDFv3.java
+++ b/java/shared/java/org/signal/libsignal/protocol/kdf/HKDFv3.java
@@ -1,13 +1,12 @@
-/**
- * Copyright (C) 2014-2016 Open Whisper Systems
- *
- * Licensed according to the LICENSE file in this repository.
- */
+//
+// Copyright 2014-2016 Signal Messenger, LLC.
+// SPDX-License-Identifier: AGPL-3.0-only
+//
+
package org.signal.libsignal.protocol.kdf;
/**
* @deprecated Use the static methods of {@link HKDF} instead.
*/
@Deprecated
-public class HKDFv3 extends HKDF {
-}
+public class HKDFv3 extends HKDF {}
diff --git a/java/shared/java/org/signal/libsignal/protocol/kem/KEMKeyPair.java b/java/shared/java/org/signal/libsignal/protocol/kem/KEMKeyPair.java
index 589708602d..d8f251d9d0 100644
--- a/java/shared/java/org/signal/libsignal/protocol/kem/KEMKeyPair.java
+++ b/java/shared/java/org/signal/libsignal/protocol/kem/KEMKeyPair.java
@@ -2,6 +2,7 @@
// Copyright 2023 Signal Messenger, LLC.
// SPDX-License-Identifier: AGPL-3.0-only
//
+
package org.signal.libsignal.protocol.kem;
import org.signal.libsignal.internal.Native;
@@ -22,16 +23,16 @@ public KEMKeyPair(long nativeHandle) {
this.unsafeHandle = nativeHandle;
}
- @Override @SuppressWarnings("deprecation")
+ @Override
+ @SuppressWarnings("deprecation")
protected void finalize() {
- Native.KyberKeyPair_Destroy(this.unsafeHandle);
+ Native.KyberKeyPair_Destroy(this.unsafeHandle);
}
public long unsafeNativeHandleWithoutGuard() {
return this.unsafeHandle;
}
-
public KEMPublicKey getPublicKey() {
return new KEMPublicKey(Native.KyberKeyPair_GetPublicKey(this.unsafeHandle));
}
diff --git a/java/shared/java/org/signal/libsignal/protocol/kem/KEMKeyType.java b/java/shared/java/org/signal/libsignal/protocol/kem/KEMKeyType.java
index e2683473f8..b50f7e011a 100644
--- a/java/shared/java/org/signal/libsignal/protocol/kem/KEMKeyType.java
+++ b/java/shared/java/org/signal/libsignal/protocol/kem/KEMKeyType.java
@@ -2,6 +2,7 @@
// Copyright 2023 Signal Messenger, LLC.
// SPDX-License-Identifier: AGPL-3.0-only
//
+
package org.signal.libsignal.protocol.kem;
public enum KEMKeyType {
diff --git a/java/shared/java/org/signal/libsignal/protocol/kem/KEMPublicKey.java b/java/shared/java/org/signal/libsignal/protocol/kem/KEMPublicKey.java
index 1502a3d782..b13be8a2e7 100644
--- a/java/shared/java/org/signal/libsignal/protocol/kem/KEMPublicKey.java
+++ b/java/shared/java/org/signal/libsignal/protocol/kem/KEMPublicKey.java
@@ -5,10 +5,10 @@
package org.signal.libsignal.protocol.kem;
+import java.util.Arrays;
import org.signal.libsignal.internal.Native;
import org.signal.libsignal.internal.NativeHandleGuard;
import org.signal.libsignal.protocol.InvalidKeyException;
-import java.util.Arrays;
public class KEMPublicKey implements NativeHandleGuard.Owner {
@@ -29,9 +29,10 @@ public KEMPublicKey(long nativeHandle) {
this.unsafeHandle = nativeHandle;
}
- @Override @SuppressWarnings("deprecation")
+ @Override
+ @SuppressWarnings("deprecation")
protected void finalize() {
- Native.KyberPublicKey_Destroy(this.unsafeHandle);
+ Native.KyberPublicKey_Destroy(this.unsafeHandle);
}
public byte[] serialize() {
@@ -46,12 +47,10 @@ public long unsafeNativeHandleWithoutGuard() {
@Override
public boolean equals(Object other) {
- if (other == null) return false;
+ if (other == null) return false;
if (!(other instanceof KEMPublicKey)) return false;
- try (
- NativeHandleGuard thisGuard = new NativeHandleGuard(this);
- NativeHandleGuard thatGuard = new NativeHandleGuard((KEMPublicKey)other);
- ) {
+ try (NativeHandleGuard thisGuard = new NativeHandleGuard(this);
+ NativeHandleGuard thatGuard = new NativeHandleGuard((KEMPublicKey) other); ) {
return Native.KyberPublicKey_Equals(thisGuard.nativeHandle(), thatGuard.nativeHandle());
}
}
diff --git a/java/shared/java/org/signal/libsignal/protocol/kem/KEMSecretKey.java b/java/shared/java/org/signal/libsignal/protocol/kem/KEMSecretKey.java
index a2402a2942..a7f99a304c 100644
--- a/java/shared/java/org/signal/libsignal/protocol/kem/KEMSecretKey.java
+++ b/java/shared/java/org/signal/libsignal/protocol/kem/KEMSecretKey.java
@@ -17,15 +17,16 @@ public KEMSecretKey(byte[] privateKey) throws InvalidKeyException {
}
public KEMSecretKey(long nativeHandle) {
- if(nativeHandle == 0) {
+ if (nativeHandle == 0) {
throw new NullPointerException();
}
this.unsafeHandle = nativeHandle;
}
- @Override @SuppressWarnings("deprecation")
+ @Override
+ @SuppressWarnings("deprecation")
protected void finalize() {
- Native.KyberSecretKey_Destroy(this.unsafeHandle);
+ Native.KyberSecretKey_Destroy(this.unsafeHandle);
}
public byte[] serialize() {
diff --git a/java/shared/java/org/signal/libsignal/protocol/logging/Log.java b/java/shared/java/org/signal/libsignal/protocol/logging/Log.java
index 13d98ddc2a..d8599e3130 100644
--- a/java/shared/java/org/signal/libsignal/protocol/logging/Log.java
+++ b/java/shared/java/org/signal/libsignal/protocol/logging/Log.java
@@ -1,8 +1,8 @@
-/**
- * Copyright (C) 2014-2016 Open Whisper Systems
- *
- * Licensed according to the LICENSE file in this repository.
- */
+//
+// Copyright 2014-2016 Signal Messenger, LLC.
+// SPDX-License-Identifier: AGPL-3.0-only
+//
+
package org.signal.libsignal.protocol.logging;
import java.io.PrintWriter;
@@ -86,6 +86,4 @@ private static void log(int priority, String tag, String msg) {
logger.log(priority, tag, msg);
}
}
-
-
}
diff --git a/java/shared/java/org/signal/libsignal/protocol/logging/SignalProtocolLogger.java b/java/shared/java/org/signal/libsignal/protocol/logging/SignalProtocolLogger.java
index c7371d0c43..3252fe652a 100644
--- a/java/shared/java/org/signal/libsignal/protocol/logging/SignalProtocolLogger.java
+++ b/java/shared/java/org/signal/libsignal/protocol/logging/SignalProtocolLogger.java
@@ -1,18 +1,18 @@
-/**
- * Copyright (C) 2014-2016 Open Whisper Systems
- *
- * Licensed according to the LICENSE file in this repository.
- */
+//
+// Copyright 2014-2016 Signal Messenger, LLC.
+// SPDX-License-Identifier: AGPL-3.0-only
+//
+
package org.signal.libsignal.protocol.logging;
public interface SignalProtocolLogger {
public static final int VERBOSE = 2;
- public static final int DEBUG = 3;
- public static final int INFO = 4;
- public static final int WARN = 5;
- public static final int ERROR = 6;
- public static final int ASSERT = 7;
+ public static final int DEBUG = 3;
+ public static final int INFO = 4;
+ public static final int WARN = 5;
+ public static final int ERROR = 6;
+ public static final int ASSERT = 7;
public void log(int priority, String tag, String message);
}
diff --git a/java/shared/java/org/signal/libsignal/protocol/logging/SignalProtocolLoggerProvider.java b/java/shared/java/org/signal/libsignal/protocol/logging/SignalProtocolLoggerProvider.java
index 535ceaf845..49541a31c4 100644
--- a/java/shared/java/org/signal/libsignal/protocol/logging/SignalProtocolLoggerProvider.java
+++ b/java/shared/java/org/signal/libsignal/protocol/logging/SignalProtocolLoggerProvider.java
@@ -1,8 +1,8 @@
-/**
- * Copyright (C) 2014-2016 Open Whisper Systems
- *
- * Licensed according to the LICENSE file in this repository.
- */
+//
+// Copyright 2014-2016 Signal Messenger, LLC.
+// SPDX-License-Identifier: AGPL-3.0-only
+//
+
package org.signal.libsignal.protocol.logging;
public class SignalProtocolLoggerProvider {
diff --git a/java/shared/java/org/signal/libsignal/protocol/message/CiphertextMessage.java b/java/shared/java/org/signal/libsignal/protocol/message/CiphertextMessage.java
index 0896b82ab5..ff7e69e0f1 100644
--- a/java/shared/java/org/signal/libsignal/protocol/message/CiphertextMessage.java
+++ b/java/shared/java/org/signal/libsignal/protocol/message/CiphertextMessage.java
@@ -1,23 +1,26 @@
-/**
- * Copyright (C) 2014-2016 Open Whisper Systems
- *
- * Licensed according to the LICENSE file in this repository.
- */
+//
+// Copyright 2014-2016 Signal Messenger, LLC.
+// SPDX-License-Identifier: AGPL-3.0-only
+//
+
package org.signal.libsignal.protocol.message;
public interface CiphertextMessage {
- public static final int CURRENT_VERSION = 3;
+ public static final int CURRENT_VERSION = 3;
- public static final int WHISPER_TYPE = 2;
- public static final int PREKEY_TYPE = 3;
- public static final int SENDERKEY_TYPE = 7;
- public static final int PLAINTEXT_CONTENT_TYPE = 8;
+ public static final int WHISPER_TYPE = 2;
+ public static final int PREKEY_TYPE = 3;
+ public static final int SENDERKEY_TYPE = 7;
+ public static final int PLAINTEXT_CONTENT_TYPE = 8;
- // This should be the worst case (worse than V2). So not always accurate, but good enough for padding.
+ // This should be the worst case (worse than V2). So not always accurate, but good enough for
+ // padding.
public static final int ENCRYPTED_MESSAGE_OVERHEAD = 53;
public byte[] serialize();
+
public int getType();
+
public long unsafeNativeHandleWithoutGuard();
}
diff --git a/java/shared/java/org/signal/libsignal/protocol/message/DecryptionErrorMessage.java b/java/shared/java/org/signal/libsignal/protocol/message/DecryptionErrorMessage.java
index 7d8de2ed03..9032643cfe 100644
--- a/java/shared/java/org/signal/libsignal/protocol/message/DecryptionErrorMessage.java
+++ b/java/shared/java/org/signal/libsignal/protocol/message/DecryptionErrorMessage.java
@@ -1,25 +1,24 @@
-/**
- * Copyright (C) 2014-2016 Open Whisper Systems
- *
- * Licensed according to the LICENSE file in this repository.
- */
+//
+// Copyright 2014-2016 Signal Messenger, LLC.
+// SPDX-License-Identifier: AGPL-3.0-only
+//
+
package org.signal.libsignal.protocol.message;
+import java.util.Optional;
import org.signal.libsignal.internal.Native;
import org.signal.libsignal.internal.NativeHandleGuard;
-
import org.signal.libsignal.protocol.InvalidMessageException;
import org.signal.libsignal.protocol.ecc.ECPublicKey;
-import java.util.Optional;
-
public final class DecryptionErrorMessage implements NativeHandleGuard.Owner {
final long unsafeHandle;
- @Override @SuppressWarnings("deprecation")
+ @Override
+ @SuppressWarnings("deprecation")
protected void finalize() {
- Native.DecryptionErrorMessage_Destroy(this.unsafeHandle);
+ Native.DecryptionErrorMessage_Destroy(this.unsafeHandle);
}
public long unsafeNativeHandleWithoutGuard() {
@@ -34,9 +33,11 @@ public DecryptionErrorMessage(byte[] serialized) throws InvalidMessageException
this.unsafeHandle = Native.DecryptionErrorMessage_Deserialize(serialized);
}
- public static DecryptionErrorMessage forOriginalMessage(byte[] originalBytes, int messageType, long timestamp, int originalSenderDeviceId) {
+ public static DecryptionErrorMessage forOriginalMessage(
+ byte[] originalBytes, int messageType, long timestamp, int originalSenderDeviceId) {
return new DecryptionErrorMessage(
- Native.DecryptionErrorMessage_ForOriginalMessage(originalBytes, messageType, timestamp, originalSenderDeviceId));
+ Native.DecryptionErrorMessage_ForOriginalMessage(
+ originalBytes, messageType, timestamp, originalSenderDeviceId));
}
public byte[] serialize() {
@@ -69,8 +70,9 @@ public int getDeviceId() {
}
/// For testing only
- public static DecryptionErrorMessage extractFromSerializedContent(byte[] serializedContentBytes) throws InvalidMessageException {
+ public static DecryptionErrorMessage extractFromSerializedContent(byte[] serializedContentBytes)
+ throws InvalidMessageException {
return new DecryptionErrorMessage(
- Native.DecryptionErrorMessage_ExtractFromSerializedContent(serializedContentBytes));
+ Native.DecryptionErrorMessage_ExtractFromSerializedContent(serializedContentBytes));
}
}
diff --git a/java/shared/java/org/signal/libsignal/protocol/message/PlaintextContent.java b/java/shared/java/org/signal/libsignal/protocol/message/PlaintextContent.java
index 3bc922304a..f4b84f59ee 100644
--- a/java/shared/java/org/signal/libsignal/protocol/message/PlaintextContent.java
+++ b/java/shared/java/org/signal/libsignal/protocol/message/PlaintextContent.java
@@ -1,13 +1,12 @@
-/**
- * Copyright (C) 2014-2016 Open Whisper Systems
- *
- * Licensed according to the LICENSE file in this repository.
- */
+//
+// Copyright 2014-2016 Signal Messenger, LLC.
+// SPDX-License-Identifier: AGPL-3.0-only
+//
+
package org.signal.libsignal.protocol.message;
import org.signal.libsignal.internal.Native;
import org.signal.libsignal.internal.NativeHandleGuard;
-
import org.signal.libsignal.protocol.InvalidMessageException;
import org.signal.libsignal.protocol.InvalidVersionException;
@@ -15,9 +14,10 @@ public final class PlaintextContent implements CiphertextMessage, NativeHandleGu
private final long unsafeHandle;
- @Override @SuppressWarnings("deprecation")
+ @Override
+ @SuppressWarnings("deprecation")
protected void finalize() {
- Native.PlaintextContent_Destroy(this.unsafeHandle);
+ Native.PlaintextContent_Destroy(this.unsafeHandle);
}
public long unsafeNativeHandleWithoutGuard() {
@@ -32,11 +32,13 @@ private PlaintextContent(long unsafeHandle) {
public PlaintextContent(DecryptionErrorMessage message) {
try (NativeHandleGuard messageGuard = new NativeHandleGuard(message)) {
- this.unsafeHandle = Native.PlaintextContent_FromDecryptionErrorMessage(messageGuard.nativeHandle());
+ this.unsafeHandle =
+ Native.PlaintextContent_FromDecryptionErrorMessage(messageGuard.nativeHandle());
}
}
- public PlaintextContent(byte[] serialized) throws InvalidMessageException, InvalidVersionException {
+ public PlaintextContent(byte[] serialized)
+ throws InvalidMessageException, InvalidVersionException {
unsafeHandle = Native.PlaintextContent_Deserialize(serialized);
}
diff --git a/java/shared/java/org/signal/libsignal/protocol/message/PreKeySignalMessage.java b/java/shared/java/org/signal/libsignal/protocol/message/PreKeySignalMessage.java
index 329d264ef5..0747c8d2a4 100644
--- a/java/shared/java/org/signal/libsignal/protocol/message/PreKeySignalMessage.java
+++ b/java/shared/java/org/signal/libsignal/protocol/message/PreKeySignalMessage.java
@@ -1,10 +1,11 @@
-/**
- * Copyright (C) 2014-2016 Open Whisper Systems
- *
- * Licensed according to the LICENSE file in this repository.
- */
+//
+// Copyright 2014-2016 Signal Messenger, LLC.
+// SPDX-License-Identifier: AGPL-3.0-only
+//
+
package org.signal.libsignal.protocol.message;
+import java.util.Optional;
import org.signal.libsignal.internal.Native;
import org.signal.libsignal.internal.NativeHandleGuard;
import org.signal.libsignal.protocol.IdentityKey;
@@ -14,20 +15,21 @@
import org.signal.libsignal.protocol.LegacyMessageException;
import org.signal.libsignal.protocol.ecc.ECPublicKey;
-import java.util.Optional;
-
public class PreKeySignalMessage implements CiphertextMessage, NativeHandleGuard.Owner {
private final long unsafeHandle;
- @Override @SuppressWarnings("deprecation")
+ @Override
+ @SuppressWarnings("deprecation")
protected void finalize() {
- Native.PreKeySignalMessage_Destroy(this.unsafeHandle);
+ Native.PreKeySignalMessage_Destroy(this.unsafeHandle);
}
public PreKeySignalMessage(byte[] serialized)
- throws InvalidMessageException, InvalidVersionException, LegacyMessageException, InvalidKeyException
- {
+ throws InvalidMessageException,
+ InvalidVersionException,
+ LegacyMessageException,
+ InvalidKeyException {
this.unsafeHandle = Native.PreKeySignalMessage_Deserialize(serialized);
}
diff --git a/java/shared/java/org/signal/libsignal/protocol/message/SenderKeyDistributionMessage.java b/java/shared/java/org/signal/libsignal/protocol/message/SenderKeyDistributionMessage.java
index 5f7554017a..4386000111 100644
--- a/java/shared/java/org/signal/libsignal/protocol/message/SenderKeyDistributionMessage.java
+++ b/java/shared/java/org/signal/libsignal/protocol/message/SenderKeyDistributionMessage.java
@@ -1,35 +1,38 @@
-/**
- * Copyright (C) 2014-2016 Open Whisper Systems
- *
- * Licensed according to the LICENSE file in this repository.
- */
+//
+// Copyright 2014-2016 Signal Messenger, LLC.
+// SPDX-License-Identifier: AGPL-3.0-only
+//
+
package org.signal.libsignal.protocol.message;
+import java.util.UUID;
import org.signal.libsignal.internal.Native;
import org.signal.libsignal.internal.NativeHandleGuard;
-
import org.signal.libsignal.protocol.InvalidKeyException;
import org.signal.libsignal.protocol.InvalidMessageException;
import org.signal.libsignal.protocol.InvalidVersionException;
import org.signal.libsignal.protocol.LegacyMessageException;
import org.signal.libsignal.protocol.ecc.ECPublicKey;
-import java.util.UUID;
-
public class SenderKeyDistributionMessage implements NativeHandleGuard.Owner {
private final long unsafeHandle;
- @Override @SuppressWarnings("deprecation")
+ @Override
+ @SuppressWarnings("deprecation")
protected void finalize() {
- Native.SenderKeyDistributionMessage_Destroy(this.unsafeHandle);
+ Native.SenderKeyDistributionMessage_Destroy(this.unsafeHandle);
}
public SenderKeyDistributionMessage(long unsafeHandle) {
this.unsafeHandle = unsafeHandle;
}
- public SenderKeyDistributionMessage(byte[] serialized) throws InvalidMessageException, InvalidVersionException, LegacyMessageException, InvalidKeyException {
+ public SenderKeyDistributionMessage(byte[] serialized)
+ throws InvalidMessageException,
+ InvalidVersionException,
+ LegacyMessageException,
+ InvalidKeyException {
unsafeHandle = Native.SenderKeyDistributionMessage_Deserialize(serialized);
}
@@ -59,7 +62,8 @@ public byte[] getChainKey() {
public ECPublicKey getSignatureKey() {
try (NativeHandleGuard guard = new NativeHandleGuard(this)) {
- return new ECPublicKey(Native.SenderKeyDistributionMessage_GetSignatureKey(guard.nativeHandle()));
+ return new ECPublicKey(
+ Native.SenderKeyDistributionMessage_GetSignatureKey(guard.nativeHandle()));
}
}
diff --git a/java/shared/java/org/signal/libsignal/protocol/message/SenderKeyMessage.java b/java/shared/java/org/signal/libsignal/protocol/message/SenderKeyMessage.java
index c02821c09c..a0effcbdcc 100644
--- a/java/shared/java/org/signal/libsignal/protocol/message/SenderKeyMessage.java
+++ b/java/shared/java/org/signal/libsignal/protocol/message/SenderKeyMessage.java
@@ -1,30 +1,26 @@
-/**
- * Copyright (C) 2014-2016 Open Whisper Systems
- *
- * Licensed according to the LICENSE file in this repository.
- */
+//
+// Copyright 2014-2016 Signal Messenger, LLC.
+// SPDX-License-Identifier: AGPL-3.0-only
+//
+
package org.signal.libsignal.protocol.message;
+import java.util.UUID;
import org.signal.libsignal.internal.Native;
import org.signal.libsignal.internal.NativeHandleGuard;
-
-import org.signal.libsignal.protocol.InvalidKeyException;
import org.signal.libsignal.protocol.InvalidMessageException;
import org.signal.libsignal.protocol.InvalidVersionException;
import org.signal.libsignal.protocol.LegacyMessageException;
-import org.signal.libsignal.protocol.ecc.ECPrivateKey;
import org.signal.libsignal.protocol.ecc.ECPublicKey;
-import java.text.ParseException;
-import java.util.UUID;
-
public class SenderKeyMessage implements CiphertextMessage, NativeHandleGuard.Owner {
private final long unsafeHandle;
- @Override @SuppressWarnings("deprecation")
+ @Override
+ @SuppressWarnings("deprecation")
protected void finalize() {
- Native.SenderKeyMessage_Destroy(this.unsafeHandle);
+ Native.SenderKeyMessage_Destroy(this.unsafeHandle);
}
public SenderKeyMessage(long unsafeHandle) {
@@ -35,7 +31,8 @@ public long unsafeNativeHandleWithoutGuard() {
return unsafeHandle;
}
- public SenderKeyMessage(byte[] serialized) throws InvalidMessageException, InvalidVersionException, LegacyMessageException {
+ public SenderKeyMessage(byte[] serialized)
+ throws InvalidMessageException, InvalidVersionException, LegacyMessageException {
unsafeHandle = Native.SenderKeyMessage_Deserialize(serialized);
}
@@ -63,13 +60,9 @@ public byte[] getCipherText() {
}
}
- public void verifySignature(ECPublicKey signatureKey)
- throws InvalidMessageException
- {
- try (
- NativeHandleGuard guard = new NativeHandleGuard(this);
- NativeHandleGuard keyGuard = new NativeHandleGuard(signatureKey);
- ) {
+ public void verifySignature(ECPublicKey signatureKey) throws InvalidMessageException {
+ try (NativeHandleGuard guard = new NativeHandleGuard(this);
+ NativeHandleGuard keyGuard = new NativeHandleGuard(signatureKey); ) {
if (!Native.SenderKeyMessage_VerifySignature(guard.nativeHandle(), keyGuard.nativeHandle())) {
throw new InvalidMessageException("Invalid signature!");
}
diff --git a/java/shared/java/org/signal/libsignal/protocol/message/SignalMessage.java b/java/shared/java/org/signal/libsignal/protocol/message/SignalMessage.java
index 2b672aff41..76d0bd4478 100644
--- a/java/shared/java/org/signal/libsignal/protocol/message/SignalMessage.java
+++ b/java/shared/java/org/signal/libsignal/protocol/message/SignalMessage.java
@@ -1,10 +1,11 @@
-/**
- * Copyright (C) 2014-2016 Open Whisper Systems
- *
- * Licensed according to the LICENSE file in this repository.
- */
+//
+// Copyright 2014-2016 Signal Messenger, LLC.
+// SPDX-License-Identifier: AGPL-3.0-only
+//
+
package org.signal.libsignal.protocol.message;
+import javax.crypto.spec.SecretKeySpec;
import org.signal.libsignal.internal.Native;
import org.signal.libsignal.internal.NativeHandleGuard;
import org.signal.libsignal.protocol.IdentityKey;
@@ -15,17 +16,20 @@
import org.signal.libsignal.protocol.ecc.ECPublicKey;
import org.signal.libsignal.protocol.util.ByteUtil;
-import javax.crypto.spec.SecretKeySpec;
-
public class SignalMessage implements CiphertextMessage, NativeHandleGuard.Owner {
private final long unsafeHandle;
- @Override @SuppressWarnings("deprecation")
+ @Override
+ @SuppressWarnings("deprecation")
protected void finalize() {
- Native.SignalMessage_Destroy(this.unsafeHandle);
+ Native.SignalMessage_Destroy(this.unsafeHandle);
}
- public SignalMessage(byte[] serialized) throws InvalidMessageException, InvalidVersionException, InvalidKeyException, LegacyMessageException {
+ public SignalMessage(byte[] serialized)
+ throws InvalidMessageException,
+ InvalidVersionException,
+ InvalidKeyException,
+ LegacyMessageException {
unsafeHandle = Native.SignalMessage_Deserialize(serialized);
}
@@ -33,7 +37,7 @@ public SignalMessage(long unsafeHandle) {
this.unsafeHandle = unsafeHandle;
}
- public ECPublicKey getSenderRatchetKey() {
+ public ECPublicKey getSenderRatchetKey() {
try (NativeHandleGuard guard = new NativeHandleGuard(this)) {
return new ECPublicKey(Native.SignalMessage_GetSenderRatchetKey(guard.nativeHandle()));
}
@@ -57,14 +61,14 @@ public byte[] getBody() {
}
}
- public void verifyMac(IdentityKey senderIdentityKey, IdentityKey receiverIdentityKey, SecretKeySpec macKey)
- throws InvalidMessageException, InvalidKeyException
- {
- try (
- NativeHandleGuard guard = new NativeHandleGuard(this);
- NativeHandleGuard senderIdentityGuard = new NativeHandleGuard(senderIdentityKey.getPublicKey());
- NativeHandleGuard receiverIdentityGuard = new NativeHandleGuard(receiverIdentityKey.getPublicKey());
- ) {
+ public void verifyMac(
+ IdentityKey senderIdentityKey, IdentityKey receiverIdentityKey, SecretKeySpec macKey)
+ throws InvalidMessageException, InvalidKeyException {
+ try (NativeHandleGuard guard = new NativeHandleGuard(this);
+ NativeHandleGuard senderIdentityGuard =
+ new NativeHandleGuard(senderIdentityKey.getPublicKey());
+ NativeHandleGuard receiverIdentityGuard =
+ new NativeHandleGuard(receiverIdentityKey.getPublicKey()); ) {
if (!Native.SignalMessage_VerifyMac(
guard.nativeHandle(),
senderIdentityGuard.nativeHandle(),
@@ -92,8 +96,8 @@ public long unsafeNativeHandleWithoutGuard() {
}
public static boolean isLegacy(byte[] message) {
- return message != null && message.length >= 1 &&
- ByteUtil.highBitsToInt(message[0]) != CiphertextMessage.CURRENT_VERSION;
+ return message != null
+ && message.length >= 1
+ && ByteUtil.highBitsToInt(message[0]) != CiphertextMessage.CURRENT_VERSION;
}
-
}
diff --git a/java/shared/java/org/signal/libsignal/protocol/state/IdentityKeyStore.java b/java/shared/java/org/signal/libsignal/protocol/state/IdentityKeyStore.java
index f1c8871b3f..af3e8c916f 100644
--- a/java/shared/java/org/signal/libsignal/protocol/state/IdentityKeyStore.java
+++ b/java/shared/java/org/signal/libsignal/protocol/state/IdentityKeyStore.java
@@ -1,8 +1,8 @@
-/**
- * Copyright (C) 2014-2016 Open Whisper Systems
- *
- * Licensed according to the LICENSE file in this repository.
- */
+//
+// Copyright 2014-2016 Signal Messenger, LLC.
+// SPDX-License-Identifier: AGPL-3.0-only
+//
+
package org.signal.libsignal.protocol.state;
import org.signal.libsignal.protocol.IdentityKey;
@@ -17,7 +17,8 @@
public interface IdentityKeyStore {
public enum Direction {
- SENDING, RECEIVING
+ SENDING,
+ RECEIVING
}
/**
@@ -29,47 +30,45 @@ public enum Direction {
/**
* Return the local client's registration ID.
- *
- * Clients should maintain a registration ID, a random number
- * between 1 and 16380 that's generated once at install time.
+ *
+ *
Clients should maintain a registration ID, a random number between 1 and 16380 that's
+ * generated once at install time.
*
* @return the local client's registration ID.
*/
- public int getLocalRegistrationId();
+ public int getLocalRegistrationId();
/**
* Save a remote client's identity key
- *
- * Store a remote client's identity key as trusted.
*
- * @param address The address of the remote client.
+ *
Store a remote client's identity key as trusted.
+ *
+ * @param address The address of the remote client.
* @param identityKey The remote client's identity key.
* @return True if the identity key replaces a previous identity, false if not
*/
- public boolean saveIdentity(SignalProtocolAddress address, IdentityKey identityKey);
-
+ public boolean saveIdentity(SignalProtocolAddress address, IdentityKey identityKey);
/**
* Verify a remote client's identity key.
- *
- * Determine whether a remote client's identity is trusted. Convention is
- * that the Signal Protocol is 'trust on first use.' This means that
- * an identity key is considered 'trusted' if there is no entry for the recipient
- * in the local store, or if it matches the saved key for a recipient in the local
- * store. Only if it mismatches an entry in the local store is it considered
- * 'untrusted.'
*
- * Clients may wish to make a distinction as to how keys are trusted based on the
- * direction of travel. For instance, clients may wish to accept all 'incoming' identity
- * key changes, while only blocking identity key changes when sending a message.
+ *
Determine whether a remote client's identity is trusted. Convention is that the Signal
+ * Protocol is 'trust on first use.' This means that an identity key is considered 'trusted' if
+ * there is no entry for the recipient in the local store, or if it matches the saved key for a
+ * recipient in the local store. Only if it mismatches an entry in the local store is it
+ * considered 'untrusted.'
+ *
+ *
Clients may wish to make a distinction as to how keys are trusted based on the direction of
+ * travel. For instance, clients may wish to accept all 'incoming' identity key changes, while
+ * only blocking identity key changes when sending a message.
*
- * @param address The address of the remote client.
+ * @param address The address of the remote client.
* @param identityKey The identity key to verify.
- * @param direction The direction (sending or receiving) this identity is being used for.
+ * @param direction The direction (sending or receiving) this identity is being used for.
* @return true if trusted, false if untrusted.
*/
- public boolean isTrustedIdentity(SignalProtocolAddress address, IdentityKey identityKey, Direction direction);
-
+ public boolean isTrustedIdentity(
+ SignalProtocolAddress address, IdentityKey identityKey, Direction direction);
/**
* Return the saved public identity key for a remote client
@@ -78,5 +77,4 @@ public enum Direction {
* @return The public identity key, or null if absent
*/
public IdentityKey getIdentity(SignalProtocolAddress address);
-
}
diff --git a/java/shared/java/org/signal/libsignal/protocol/state/KyberPreKeyRecord.java b/java/shared/java/org/signal/libsignal/protocol/state/KyberPreKeyRecord.java
index 15fe893514..3f09d9b094 100644
--- a/java/shared/java/org/signal/libsignal/protocol/state/KyberPreKeyRecord.java
+++ b/java/shared/java/org/signal/libsignal/protocol/state/KyberPreKeyRecord.java
@@ -2,6 +2,7 @@
// Copyright 2023 Signal Messenger, LLC.
// SPDX-License-Identifier: AGPL-3.0-only
//
+
package org.signal.libsignal.protocol.state;
import org.signal.libsignal.internal.Native;
@@ -12,20 +13,16 @@
public class KyberPreKeyRecord implements NativeHandleGuard.Owner {
private final long unsafeHandle;
- @Override @SuppressWarnings("deprecation")
+ @Override
+ @SuppressWarnings("deprecation")
protected void finalize() {
Native.KyberPreKeyRecord_Destroy(this.unsafeHandle);
}
public KyberPreKeyRecord(int id, long timestamp, KEMKeyPair keyPair, byte[] signature) {
- try (
- NativeHandleGuard guard = new NativeHandleGuard(keyPair);
- ) {
- this.unsafeHandle = Native.KyberPreKeyRecord_New(
- id,
- timestamp,
- guard.nativeHandle(),
- signature);
+ try (NativeHandleGuard guard = new NativeHandleGuard(keyPair)) {
+ this.unsafeHandle =
+ Native.KyberPreKeyRecord_New(id, timestamp, guard.nativeHandle(), signature);
}
}
@@ -67,5 +64,4 @@ public byte[] serialize() {
public long unsafeNativeHandleWithoutGuard() {
return this.unsafeHandle;
}
-
}
diff --git a/java/shared/java/org/signal/libsignal/protocol/state/KyberPreKeyStore.java b/java/shared/java/org/signal/libsignal/protocol/state/KyberPreKeyStore.java
index ba0af84644..09ff66120f 100644
--- a/java/shared/java/org/signal/libsignal/protocol/state/KyberPreKeyStore.java
+++ b/java/shared/java/org/signal/libsignal/protocol/state/KyberPreKeyStore.java
@@ -2,15 +2,14 @@
// Copyright 2023 Signal Messenger, LLC.
// SPDX-License-Identifier: AGPL-3.0-only
//
-package org.signal.libsignal.protocol.state;
-import org.signal.libsignal.protocol.InvalidKeyIdException;
+package org.signal.libsignal.protocol.state;
import java.util.List;
+import org.signal.libsignal.protocol.InvalidKeyIdException;
public interface KyberPreKeyStore {
-
/**
* Load a local KyberPreKeyRecord.
*
@@ -33,19 +32,20 @@ public interface KyberPreKeyStore {
* @param kyberPreKeyId the ID of the KyberPreKeyRecord to store.
* @param record the KyberPreKeyRecord.
*/
- public void storeKyberPreKey(int kyberPreKeyId, KyberPreKeyRecord record);
+ public void storeKyberPreKey(int kyberPreKeyId, KyberPreKeyRecord record);
/**
* @param kyberPreKeyId A KyberPreKeyRecord ID.
* @return true if the store has a record for the kyberPreKeyId, otherwise false.
*/
- public boolean containsKyberPreKey(int kyberPreKeyId);
+ public boolean containsKyberPreKey(int kyberPreKeyId);
/**
* Mark a KyberPreKeyRecord in the local storage as used.
- * Remove if it is a one-time pre key and noop if it is last-resort.
+ *
+ *
Remove if it is a one-time pre key and noop if it is last-resort.
*
* @param kyberPreKeyId The ID of the KyberPreKeyRecord to marked.
*/
- public void markKyberPreKeyUsed(int kyberPreKeyId);
+ public void markKyberPreKeyUsed(int kyberPreKeyId);
}
diff --git a/java/shared/java/org/signal/libsignal/protocol/state/PreKeyBundle.java b/java/shared/java/org/signal/libsignal/protocol/state/PreKeyBundle.java
index 7818f6255f..d8e8e9b2f6 100644
--- a/java/shared/java/org/signal/libsignal/protocol/state/PreKeyBundle.java
+++ b/java/shared/java/org/signal/libsignal/protocol/state/PreKeyBundle.java
@@ -1,8 +1,8 @@
-/**
- * Copyright (C) 2014-2016 Open Whisper Systems
- *
- * Licensed according to the LICENSE file in this repository.
- */
+//
+// Copyright 2014-2016 Signal Messenger, LLC.
+// SPDX-License-Identifier: AGPL-3.0-only
+//
+
package org.signal.libsignal.protocol.state;
import org.signal.libsignal.internal.Native;
@@ -12,8 +12,7 @@
import org.signal.libsignal.protocol.kem.KEMPublicKey;
/**
- * A class that contains a remote PreKey and collection
- * of associated items.
+ * A class that contains a remote PreKey and collection of associated items.
*
* @author Moxie Marlinspike
*/
@@ -23,52 +22,65 @@ public class PreKeyBundle implements NativeHandleGuard.Owner {
// -1 is treated as Option::None by the bridging layer
public static final int NULL_PRE_KEY_ID = -1;
- @Override @SuppressWarnings("deprecation")
+ @Override
+ @SuppressWarnings("deprecation")
protected void finalize() {
Native.PreKeyBundle_Destroy(this.unsafeHandle);
}
- public PreKeyBundle(int registrationId, int deviceId, int preKeyId, ECPublicKey preKeyPublic,
- int signedPreKeyId, ECPublicKey signedPreKeyPublic, byte[] signedPreKeySignature,
- IdentityKey identityKey) {
+ public PreKeyBundle(
+ int registrationId,
+ int deviceId,
+ int preKeyId,
+ ECPublicKey preKeyPublic,
+ int signedPreKeyId,
+ ECPublicKey signedPreKeyPublic,
+ byte[] signedPreKeySignature,
+ IdentityKey identityKey) {
this(
- registrationId,
- deviceId,
- preKeyId,
- preKeyPublic,
- signedPreKeyId,
- signedPreKeyPublic,
- signedPreKeySignature,
- identityKey,
- NULL_PRE_KEY_ID,
- null,
- null);
- }
-
- public PreKeyBundle(int registrationId, int deviceId, int preKeyId, ECPublicKey preKeyPublic,
- int signedPreKeyId, ECPublicKey signedPreKeyPublic, byte[] signedPreKeySignature,
- IdentityKey identityKey, int kyberPreKeyId, KEMPublicKey kyberPreKeyPublic,
- byte[] kyberPreKeySignature)
- {
- try (
- NativeHandleGuard preKeyPublicGuard = new NativeHandleGuard(preKeyPublic);
- NativeHandleGuard signedPreKeyPublicGuard = new NativeHandleGuard(signedPreKeyPublic);
- NativeHandleGuard identityKeyGuard = new NativeHandleGuard(identityKey.getPublicKey());
- NativeHandleGuard kyberPreKeyPublicGuard = new NativeHandleGuard(kyberPreKeyPublic);
- ) {
- byte[] kyberSignature = kyberPreKeySignature == null ? new byte[]{} : kyberPreKeySignature;
- this.unsafeHandle = Native.PreKeyBundle_New(
registrationId,
deviceId,
preKeyId,
- preKeyPublicGuard.nativeHandle(),
+ preKeyPublic,
signedPreKeyId,
- signedPreKeyPublicGuard.nativeHandle(),
+ signedPreKeyPublic,
signedPreKeySignature,
- identityKeyGuard.nativeHandle(),
- kyberPreKeyId,
- kyberPreKeyPublicGuard.nativeHandle(),
- kyberSignature);
+ identityKey,
+ NULL_PRE_KEY_ID,
+ null,
+ null);
+ }
+
+ public PreKeyBundle(
+ int registrationId,
+ int deviceId,
+ int preKeyId,
+ ECPublicKey preKeyPublic,
+ int signedPreKeyId,
+ ECPublicKey signedPreKeyPublic,
+ byte[] signedPreKeySignature,
+ IdentityKey identityKey,
+ int kyberPreKeyId,
+ KEMPublicKey kyberPreKeyPublic,
+ byte[] kyberPreKeySignature) {
+ try (NativeHandleGuard preKeyPublicGuard = new NativeHandleGuard(preKeyPublic);
+ NativeHandleGuard signedPreKeyPublicGuard = new NativeHandleGuard(signedPreKeyPublic);
+ NativeHandleGuard identityKeyGuard = new NativeHandleGuard(identityKey.getPublicKey());
+ NativeHandleGuard kyberPreKeyPublicGuard = new NativeHandleGuard(kyberPreKeyPublic); ) {
+ byte[] kyberSignature = kyberPreKeySignature == null ? new byte[] {} : kyberPreKeySignature;
+ this.unsafeHandle =
+ Native.PreKeyBundle_New(
+ registrationId,
+ deviceId,
+ preKeyId,
+ preKeyPublicGuard.nativeHandle(),
+ signedPreKeyId,
+ signedPreKeyPublicGuard.nativeHandle(),
+ signedPreKeySignature,
+ identityKeyGuard.nativeHandle(),
+ kyberPreKeyId,
+ kyberPreKeyPublicGuard.nativeHandle(),
+ kyberSignature);
}
}
@@ -135,7 +147,8 @@ public byte[] getSignedPreKeySignature() {
*/
public IdentityKey getIdentityKey() {
try (NativeHandleGuard guard = new NativeHandleGuard(this)) {
- return new IdentityKey(new ECPublicKey(Native.PreKeyBundle_GetIdentityKey(guard.nativeHandle())));
+ return new IdentityKey(
+ new ECPublicKey(Native.PreKeyBundle_GetIdentityKey(guard.nativeHandle())));
}
}
diff --git a/java/shared/java/org/signal/libsignal/protocol/state/PreKeyRecord.java b/java/shared/java/org/signal/libsignal/protocol/state/PreKeyRecord.java
index 223a94877c..8b9966cef5 100644
--- a/java/shared/java/org/signal/libsignal/protocol/state/PreKeyRecord.java
+++ b/java/shared/java/org/signal/libsignal/protocol/state/PreKeyRecord.java
@@ -1,8 +1,8 @@
-/**
- * Copyright (C) 2014-2016 Open Whisper Systems
- *
- * Licensed according to the LICENSE file in this repository.
- */
+//
+// Copyright 2014-2016 Signal Messenger, LLC.
+// SPDX-License-Identifier: AGPL-3.0-only
+//
+
package org.signal.libsignal.protocol.state;
import org.signal.libsignal.internal.Native;
@@ -16,17 +16,17 @@
public class PreKeyRecord implements NativeHandleGuard.Owner {
private final long unsafeHandle;
- @Override @SuppressWarnings("deprecation")
+ @Override
+ @SuppressWarnings("deprecation")
protected void finalize() {
Native.PreKeyRecord_Destroy(this.unsafeHandle);
}
public PreKeyRecord(int id, ECKeyPair keyPair) {
- try (
- NativeHandleGuard publicKey = new NativeHandleGuard(keyPair.getPublicKey());
- NativeHandleGuard privateKey = new NativeHandleGuard(keyPair.getPrivateKey());
- ) {
- this.unsafeHandle = Native.PreKeyRecord_New(id, publicKey.nativeHandle(), privateKey.nativeHandle());
+ try (NativeHandleGuard publicKey = new NativeHandleGuard(keyPair.getPublicKey());
+ NativeHandleGuard privateKey = new NativeHandleGuard(keyPair.getPrivateKey()); ) {
+ this.unsafeHandle =
+ Native.PreKeyRecord_New(id, publicKey.nativeHandle(), privateKey.nativeHandle());
}
}
@@ -43,8 +43,10 @@ public int getId() {
public ECKeyPair getKeyPair() throws InvalidKeyException {
try (NativeHandleGuard guard = new NativeHandleGuard(this)) {
- ECPublicKey publicKey = new ECPublicKey(Native.PreKeyRecord_GetPublicKey(guard.nativeHandle()));
- ECPrivateKey privateKey = new ECPrivateKey(Native.PreKeyRecord_GetPrivateKey(guard.nativeHandle()));
+ ECPublicKey publicKey =
+ new ECPublicKey(Native.PreKeyRecord_GetPublicKey(guard.nativeHandle()));
+ ECPrivateKey privateKey =
+ new ECPrivateKey(Native.PreKeyRecord_GetPrivateKey(guard.nativeHandle()));
return new ECKeyPair(publicKey, privateKey);
}
}
diff --git a/java/shared/java/org/signal/libsignal/protocol/state/PreKeyStore.java b/java/shared/java/org/signal/libsignal/protocol/state/PreKeyStore.java
index a39f5d385b..beef380d2a 100644
--- a/java/shared/java/org/signal/libsignal/protocol/state/PreKeyStore.java
+++ b/java/shared/java/org/signal/libsignal/protocol/state/PreKeyStore.java
@@ -1,8 +1,8 @@
-/**
- * Copyright (C) 2014-2016 Open Whisper Systems
- *
- * Licensed according to the LICENSE file in this repository.
- */
+//
+// Copyright 2014-2016 Signal Messenger, LLC.
+// SPDX-License-Identifier: AGPL-3.0-only
+//
+
package org.signal.libsignal.protocol.state;
import org.signal.libsignal.protocol.InvalidKeyIdException;
@@ -29,19 +29,18 @@ public interface PreKeyStore {
* @param preKeyId the ID of the PreKeyRecord to store.
* @param record the PreKeyRecord.
*/
- public void storePreKey(int preKeyId, PreKeyRecord record);
+ public void storePreKey(int preKeyId, PreKeyRecord record);
/**
* @param preKeyId A PreKeyRecord ID.
* @return true if the store has a record for the preKeyId, otherwise false.
*/
- public boolean containsPreKey(int preKeyId);
+ public boolean containsPreKey(int preKeyId);
/**
* Delete a PreKeyRecord from local storage.
*
* @param preKeyId The ID of the PreKeyRecord to remove.
*/
- public void removePreKey(int preKeyId);
-
+ public void removePreKey(int preKeyId);
}
diff --git a/java/shared/java/org/signal/libsignal/protocol/state/SessionRecord.java b/java/shared/java/org/signal/libsignal/protocol/state/SessionRecord.java
index e63c6df768..cf86b17972 100644
--- a/java/shared/java/org/signal/libsignal/protocol/state/SessionRecord.java
+++ b/java/shared/java/org/signal/libsignal/protocol/state/SessionRecord.java
@@ -1,11 +1,11 @@
-/**
- * Copyright (C) 2014-2016 Open Whisper Systems
- *
- * Licensed according to the LICENSE file in this repository.
- */
+//
+// Copyright 2014-2016 Signal Messenger, LLC.
+// SPDX-License-Identifier: AGPL-3.0-only
+//
+
package org.signal.libsignal.protocol.state;
-import java.io.IOException;
+import java.time.Instant;
import org.signal.libsignal.internal.Native;
import org.signal.libsignal.internal.NativeHandleGuard;
import org.signal.libsignal.protocol.IdentityKey;
@@ -24,7 +24,8 @@ public class SessionRecord implements NativeHandleGuard.Owner {
private final long unsafeHandle;
- @Override @SuppressWarnings("deprecation")
+ @Override
+ @SuppressWarnings("deprecation")
protected void finalize() {
Native.SessionRecord_Destroy(this.unsafeHandle);
}
@@ -37,19 +38,14 @@ private SessionRecord(long unsafeHandle) {
this.unsafeHandle = unsafeHandle;
}
- // FIXME: This shouldn't be considered a "message".
- public static SessionRecord fromSingleSessionState(byte[] sessionStateBytes) throws InvalidMessageException {
- return new SessionRecord(Native.SessionRecord_FromSingleSessionState(sessionStateBytes));
- }
-
// FIXME: This shouldn't be considered a "message".
public SessionRecord(byte[] serialized) throws InvalidMessageException {
this.unsafeHandle = Native.SessionRecord_Deserialize(serialized);
}
/**
- * Move the current SessionState into the list of "previous" session states, and replace
- * the current SessionState with a fresh reset instance.
+ * Move the current SessionState into the list of "previous" session states, and replace the
+ * current SessionState with a fresh reset instance.
*/
public void archiveCurrentState() {
try (NativeHandleGuard guard = new NativeHandleGuard(this)) {
@@ -98,22 +94,39 @@ public IdentityKey getLocalIdentityKey() {
}
}
+ /**
+ * Returns whether the current session can be used to send messages.
+ *
+ * If there is no current session, returns {@code false}.
+ */
public boolean hasSenderChain() {
+ return hasSenderChain(Instant.now());
+ }
+
+ /**
+ * Returns whether the current session can be used to send messages.
+ *
+ *
If there is no current session, returns {@code false}.
+ *
+ *
You should only use this overload if you need to test session expiration.
+ */
+ public boolean hasSenderChain(Instant now) {
try (NativeHandleGuard guard = new NativeHandleGuard(this)) {
- return Native.SessionRecord_HasSenderChain(guard.nativeHandle());
+ return Native.SessionRecord_HasUsableSenderChain(guard.nativeHandle(), now.toEpochMilli());
}
}
public boolean currentRatchetKeyMatches(ECPublicKey key) {
- try (
- NativeHandleGuard guard = new NativeHandleGuard(this);
- NativeHandleGuard keyGuard = new NativeHandleGuard(key);
- ) {
- return Native.SessionRecord_CurrentRatchetKeyMatches(guard.nativeHandle(), keyGuard.nativeHandle());
+ try (NativeHandleGuard guard = new NativeHandleGuard(this);
+ NativeHandleGuard keyGuard = new NativeHandleGuard(key); ) {
+ return Native.SessionRecord_CurrentRatchetKeyMatches(
+ guard.nativeHandle(), keyGuard.nativeHandle());
}
}
- /** @return a serialized version of the current SessionRecord. */
+ /**
+ * @return a serialized version of the current SessionRecord.
+ */
public byte[] serialize() {
try (NativeHandleGuard guard = new NativeHandleGuard(this)) {
return Native.SessionRecord_Serialize(guard.nativeHandle());
@@ -123,12 +136,10 @@ public byte[] serialize() {
// Following functions are for internal or testing use and may be removed in the future:
public byte[] getReceiverChainKeyValue(ECPublicKey senderEphemeral) {
- try (
- NativeHandleGuard guard = new NativeHandleGuard(this);
- NativeHandleGuard ephemeralGuard = new NativeHandleGuard(senderEphemeral);
- ) {
+ try (NativeHandleGuard guard = new NativeHandleGuard(this);
+ NativeHandleGuard ephemeralGuard = new NativeHandleGuard(senderEphemeral); ) {
return Native.SessionRecord_GetReceiverChainKeyValue(
- guard.nativeHandle(), ephemeralGuard.nativeHandle());
+ guard.nativeHandle(), ephemeralGuard.nativeHandle());
}
}
@@ -150,24 +161,25 @@ public static SessionRecord initializeAliceSession(
IdentityKey theirIdentityKey,
ECPublicKey theirSignedPreKey,
ECPublicKey theirRatchetKey) {
- try (
- NativeHandleGuard identityPrivateGuard = new NativeHandleGuard(identityKey.getPrivateKey());
- NativeHandleGuard identityPublicGuard = new NativeHandleGuard(identityKey.getPublicKey().getPublicKey());
- NativeHandleGuard basePrivateGuard = new NativeHandleGuard(baseKey.getPrivateKey());
- NativeHandleGuard basePublicGuard = new NativeHandleGuard(baseKey.getPublicKey());
- NativeHandleGuard theirIdentityGuard = new NativeHandleGuard(theirIdentityKey.getPublicKey());
- NativeHandleGuard theirSignedPreKeyGuard = new NativeHandleGuard(theirSignedPreKey);
- NativeHandleGuard theirRatchetKeyGuard = new NativeHandleGuard(theirRatchetKey);
- ) {
+ try (NativeHandleGuard identityPrivateGuard =
+ new NativeHandleGuard(identityKey.getPrivateKey());
+ NativeHandleGuard identityPublicGuard =
+ new NativeHandleGuard(identityKey.getPublicKey().getPublicKey());
+ NativeHandleGuard basePrivateGuard = new NativeHandleGuard(baseKey.getPrivateKey());
+ NativeHandleGuard basePublicGuard = new NativeHandleGuard(baseKey.getPublicKey());
+ NativeHandleGuard theirIdentityGuard =
+ new NativeHandleGuard(theirIdentityKey.getPublicKey());
+ NativeHandleGuard theirSignedPreKeyGuard = new NativeHandleGuard(theirSignedPreKey);
+ NativeHandleGuard theirRatchetKeyGuard = new NativeHandleGuard(theirRatchetKey); ) {
return new SessionRecord(
- Native.SessionRecord_InitializeAliceSession(
- identityPrivateGuard.nativeHandle(),
- identityPublicGuard.nativeHandle(),
- basePrivateGuard.nativeHandle(),
- basePublicGuard.nativeHandle(),
- theirIdentityGuard.nativeHandle(),
- theirSignedPreKeyGuard.nativeHandle(),
- theirRatchetKeyGuard.nativeHandle()));
+ Native.SessionRecord_InitializeAliceSession(
+ identityPrivateGuard.nativeHandle(),
+ identityPublicGuard.nativeHandle(),
+ basePrivateGuard.nativeHandle(),
+ basePublicGuard.nativeHandle(),
+ theirIdentityGuard.nativeHandle(),
+ theirSignedPreKeyGuard.nativeHandle(),
+ theirRatchetKeyGuard.nativeHandle()));
}
}
@@ -177,26 +189,31 @@ public static SessionRecord initializeBobSession(
ECKeyPair ephemeralKey,
IdentityKey theirIdentityKey,
ECPublicKey theirBaseKey) {
- try (
- NativeHandleGuard identityPrivateGuard = new NativeHandleGuard(identityKey.getPrivateKey());
- NativeHandleGuard identityPublicGuard = new NativeHandleGuard(identityKey.getPublicKey().getPublicKey());
- NativeHandleGuard signedPreKeyPrivateGuard = new NativeHandleGuard(signedPreKey.getPrivateKey());
- NativeHandleGuard signedPreKeyPublicGuard = new NativeHandleGuard(signedPreKey.getPublicKey());
- NativeHandleGuard ephemeralPrivateGuard = new NativeHandleGuard(ephemeralKey.getPrivateKey());
- NativeHandleGuard ephemeralPublicGuard = new NativeHandleGuard(ephemeralKey.getPublicKey());
- NativeHandleGuard theirIdentityGuard = new NativeHandleGuard(theirIdentityKey.getPublicKey());
- NativeHandleGuard theirBaseKeyGuard = new NativeHandleGuard(theirBaseKey);
- ) {
+ try (NativeHandleGuard identityPrivateGuard =
+ new NativeHandleGuard(identityKey.getPrivateKey());
+ NativeHandleGuard identityPublicGuard =
+ new NativeHandleGuard(identityKey.getPublicKey().getPublicKey());
+ NativeHandleGuard signedPreKeyPrivateGuard =
+ new NativeHandleGuard(signedPreKey.getPrivateKey());
+ NativeHandleGuard signedPreKeyPublicGuard =
+ new NativeHandleGuard(signedPreKey.getPublicKey());
+ NativeHandleGuard ephemeralPrivateGuard =
+ new NativeHandleGuard(ephemeralKey.getPrivateKey());
+ NativeHandleGuard ephemeralPublicGuard =
+ new NativeHandleGuard(ephemeralKey.getPublicKey());
+ NativeHandleGuard theirIdentityGuard =
+ new NativeHandleGuard(theirIdentityKey.getPublicKey());
+ NativeHandleGuard theirBaseKeyGuard = new NativeHandleGuard(theirBaseKey); ) {
return new SessionRecord(
- Native.SessionRecord_InitializeBobSession(
- identityPrivateGuard.nativeHandle(),
- identityPublicGuard.nativeHandle(),
- signedPreKeyPrivateGuard.nativeHandle(),
- signedPreKeyPublicGuard.nativeHandle(),
- ephemeralPrivateGuard.nativeHandle(),
- ephemeralPublicGuard.nativeHandle(),
- theirIdentityGuard.nativeHandle(),
- theirBaseKeyGuard.nativeHandle()));
+ Native.SessionRecord_InitializeBobSession(
+ identityPrivateGuard.nativeHandle(),
+ identityPublicGuard.nativeHandle(),
+ signedPreKeyPrivateGuard.nativeHandle(),
+ signedPreKeyPublicGuard.nativeHandle(),
+ ephemeralPrivateGuard.nativeHandle(),
+ ephemeralPublicGuard.nativeHandle(),
+ theirIdentityGuard.nativeHandle(),
+ theirBaseKeyGuard.nativeHandle()));
}
}
diff --git a/java/shared/java/org/signal/libsignal/protocol/state/SessionStore.java b/java/shared/java/org/signal/libsignal/protocol/state/SessionStore.java
index 9952bb6751..0c8f994586 100644
--- a/java/shared/java/org/signal/libsignal/protocol/state/SessionStore.java
+++ b/java/shared/java/org/signal/libsignal/protocol/state/SessionStore.java
@@ -1,18 +1,16 @@
-/**
- * Copyright (C) 2014-2016 Open Whisper Systems
- *
- * Licensed according to the LICENSE file in this repository.
- */
+//
+// Copyright 2014-2016 Signal Messenger, LLC.
+// SPDX-License-Identifier: AGPL-3.0-only
+//
+
package org.signal.libsignal.protocol.state;
+import java.util.List;
import org.signal.libsignal.protocol.NoSessionException;
import org.signal.libsignal.protocol.SignalProtocolAddress;
-import java.util.List;
-
/**
- * The interface to the durable store of session state information
- * for remote clients.
+ * The interface to the durable store of session state information for remote clients.
*
* @author Moxie Marlinspike
*/
@@ -21,15 +19,15 @@ public interface SessionStore {
/**
* Returns a copy of the {@link SessionRecord} corresponding to the recipientId + deviceId tuple,
* or a new SessionRecord if one does not currently exist.
- *
- * It is important that implementations return a copy of the current durable information. The
+ *
+ *
It is important that implementations return a copy of the current durable information. The
* returned SessionRecord may be modified, but those changes should not have an effect on the
- * durable session state (what is returned by subsequent calls to this method) without the
- * store method being called here first.
+ * durable session state (what is returned by subsequent calls to this method) without the store
+ * method being called here first.
*
* @param address The name and device ID of the remote client.
- * @return a copy of the SessionRecord corresponding to the recipientId + deviceId tuple, or
- * a new SessionRecord if one does not currently exist.
+ * @return a copy of the SessionRecord corresponding to the recipientId + deviceId tuple, or a new
+ * SessionRecord if one does not currently exist.
*/
public SessionRecord loadSession(SignalProtocolAddress address);
@@ -40,7 +38,8 @@ public interface SessionStore {
* @return the SessionRecords corresponding to each recipientId + deviceId tuple.
* @throws NoSessionException if any address does not have an active session.
*/
- public List loadExistingSessions(List addresses) throws NoSessionException;
+ public List loadExistingSessions(List addresses)
+ throws NoSessionException;
/**
* Returns all known devices with active sessions for a recipient
@@ -52,13 +51,16 @@ public interface SessionStore {
/**
* Commit to storage the {@link SessionRecord} for a given recipientId + deviceId tuple.
+ *
* @param address the address of the remote client.
* @param record the current SessionRecord for the remote client.
*/
public void storeSession(SignalProtocolAddress address, SessionRecord record);
/**
- * Determine whether there is a committed {@link SessionRecord} for a recipientId + deviceId tuple.
+ * Determine whether there is a committed {@link SessionRecord} for a recipientId + deviceId
+ * tuple.
+ *
* @param address the address of the remote client.
* @return true if a {@link SessionRecord} exists, false otherwise.
*/
@@ -77,5 +79,4 @@ public interface SessionStore {
* @param name the name of the remote client.
*/
public void deleteAllSessions(String name);
-
}
diff --git a/java/shared/java/org/signal/libsignal/protocol/state/SignalProtocolStore.java b/java/shared/java/org/signal/libsignal/protocol/state/SignalProtocolStore.java
index db50825285..26fc4fd216 100644
--- a/java/shared/java/org/signal/libsignal/protocol/state/SignalProtocolStore.java
+++ b/java/shared/java/org/signal/libsignal/protocol/state/SignalProtocolStore.java
@@ -1,13 +1,16 @@
-/**
- * Copyright (C) 2014-2016 Open Whisper Systems
- *
- * Licensed according to the LICENSE file in this repository.
- */
+//
+// Copyright 2014-2016 Signal Messenger, LLC.
+// SPDX-License-Identifier: AGPL-3.0-only
+//
+
package org.signal.libsignal.protocol.state;
import org.signal.libsignal.protocol.groups.state.SenderKeyStore;
public interface SignalProtocolStore
- extends IdentityKeyStore, PreKeyStore, SessionStore, SignedPreKeyStore, SenderKeyStore, KyberPreKeyStore
-{
-}
+ extends IdentityKeyStore,
+ PreKeyStore,
+ SessionStore,
+ SignedPreKeyStore,
+ SenderKeyStore,
+ KyberPreKeyStore {}
diff --git a/java/shared/java/org/signal/libsignal/protocol/state/SignedPreKeyRecord.java b/java/shared/java/org/signal/libsignal/protocol/state/SignedPreKeyRecord.java
index 5c8120d120..14b6216714 100644
--- a/java/shared/java/org/signal/libsignal/protocol/state/SignedPreKeyRecord.java
+++ b/java/shared/java/org/signal/libsignal/protocol/state/SignedPreKeyRecord.java
@@ -1,13 +1,12 @@
-/**
- * Copyright (C) 2014-2016 Open Whisper Systems
- *
- * Licensed according to the LICENSE file in this repository.
- */
+//
+// Copyright 2014-2016 Signal Messenger, LLC.
+// SPDX-License-Identifier: AGPL-3.0-only
+//
+
package org.signal.libsignal.protocol.state;
import org.signal.libsignal.internal.Native;
import org.signal.libsignal.internal.NativeHandleGuard;
-import org.signal.libsignal.protocol.InvalidKeyException;
import org.signal.libsignal.protocol.InvalidMessageException;
import org.signal.libsignal.protocol.ecc.ECKeyPair;
import org.signal.libsignal.protocol.ecc.ECPrivateKey;
@@ -16,22 +15,18 @@
public class SignedPreKeyRecord implements NativeHandleGuard.Owner {
private final long unsafeHandle;
- @Override @SuppressWarnings("deprecation")
+ @Override
+ @SuppressWarnings("deprecation")
protected void finalize() {
Native.SignedPreKeyRecord_Destroy(this.unsafeHandle);
}
public SignedPreKeyRecord(int id, long timestamp, ECKeyPair keyPair, byte[] signature) {
- try (
- NativeHandleGuard publicGuard = new NativeHandleGuard(keyPair.getPublicKey());
- NativeHandleGuard privateGuard = new NativeHandleGuard(keyPair.getPrivateKey());
- ) {
- this.unsafeHandle = Native.SignedPreKeyRecord_New(
- id,
- timestamp,
- publicGuard.nativeHandle(),
- privateGuard.nativeHandle(),
- signature);
+ try (NativeHandleGuard publicGuard = new NativeHandleGuard(keyPair.getPublicKey());
+ NativeHandleGuard privateGuard = new NativeHandleGuard(keyPair.getPrivateKey()); ) {
+ this.unsafeHandle =
+ Native.SignedPreKeyRecord_New(
+ id, timestamp, publicGuard.nativeHandle(), privateGuard.nativeHandle(), signature);
}
}
@@ -54,8 +49,10 @@ public long getTimestamp() {
public ECKeyPair getKeyPair() {
try (NativeHandleGuard guard = new NativeHandleGuard(this)) {
- ECPublicKey publicKey = new ECPublicKey(Native.SignedPreKeyRecord_GetPublicKey(guard.nativeHandle()));
- ECPrivateKey privateKey = new ECPrivateKey(Native.SignedPreKeyRecord_GetPrivateKey(guard.nativeHandle()));
+ ECPublicKey publicKey =
+ new ECPublicKey(Native.SignedPreKeyRecord_GetPublicKey(guard.nativeHandle()));
+ ECPrivateKey privateKey =
+ new ECPrivateKey(Native.SignedPreKeyRecord_GetPrivateKey(guard.nativeHandle()));
return new ECKeyPair(publicKey, privateKey);
}
}
@@ -75,5 +72,4 @@ public byte[] serialize() {
public long unsafeNativeHandleWithoutGuard() {
return this.unsafeHandle;
}
-
}
diff --git a/java/shared/java/org/signal/libsignal/protocol/state/SignedPreKeyStore.java b/java/shared/java/org/signal/libsignal/protocol/state/SignedPreKeyStore.java
index c770639180..d3436d7dd0 100644
--- a/java/shared/java/org/signal/libsignal/protocol/state/SignedPreKeyStore.java
+++ b/java/shared/java/org/signal/libsignal/protocol/state/SignedPreKeyStore.java
@@ -1,17 +1,15 @@
-/**
- * Copyright (C) 2014-2016 Open Whisper Systems
- *
- * Licensed according to the LICENSE file in this repository.
- */
-package org.signal.libsignal.protocol.state;
+//
+// Copyright 2014-2016 Signal Messenger, LLC.
+// SPDX-License-Identifier: AGPL-3.0-only
+//
-import org.signal.libsignal.protocol.InvalidKeyIdException;
+package org.signal.libsignal.protocol.state;
import java.util.List;
+import org.signal.libsignal.protocol.InvalidKeyIdException;
public interface SignedPreKeyStore {
-
/**
* Load a local SignedPreKeyRecord.
*
@@ -34,19 +32,18 @@ public interface SignedPreKeyStore {
* @param signedPreKeyId the ID of the SignedPreKeyRecord to store.
* @param record the SignedPreKeyRecord.
*/
- public void storeSignedPreKey(int signedPreKeyId, SignedPreKeyRecord record);
+ public void storeSignedPreKey(int signedPreKeyId, SignedPreKeyRecord record);
/**
* @param signedPreKeyId A SignedPreKeyRecord ID.
* @return true if the store has a record for the signedPreKeyId, otherwise false.
*/
- public boolean containsSignedPreKey(int signedPreKeyId);
+ public boolean containsSignedPreKey(int signedPreKeyId);
/**
* Delete a SignedPreKeyRecord from local storage.
*
* @param signedPreKeyId The ID of the SignedPreKeyRecord to remove.
*/
- public void removeSignedPreKey(int signedPreKeyId);
-
+ public void removeSignedPreKey(int signedPreKeyId);
}
diff --git a/java/shared/java/org/signal/libsignal/protocol/state/impl/InMemoryIdentityKeyStore.java b/java/shared/java/org/signal/libsignal/protocol/state/impl/InMemoryIdentityKeyStore.java
index c0f083ed0b..4e3e67c3e8 100644
--- a/java/shared/java/org/signal/libsignal/protocol/state/impl/InMemoryIdentityKeyStore.java
+++ b/java/shared/java/org/signal/libsignal/protocol/state/impl/InMemoryIdentityKeyStore.java
@@ -1,27 +1,26 @@
-/**
- * Copyright (C) 2014-2016 Open Whisper Systems
- *
- * Licensed according to the LICENSE file in this repository.
- */
+//
+// Copyright 2014-2016 Signal Messenger, LLC.
+// SPDX-License-Identifier: AGPL-3.0-only
+//
+
package org.signal.libsignal.protocol.state.impl;
+import java.util.HashMap;
+import java.util.Map;
import org.signal.libsignal.protocol.IdentityKey;
import org.signal.libsignal.protocol.IdentityKeyPair;
import org.signal.libsignal.protocol.SignalProtocolAddress;
import org.signal.libsignal.protocol.state.IdentityKeyStore;
-import java.util.HashMap;
-import java.util.Map;
-
public class InMemoryIdentityKeyStore implements IdentityKeyStore {
private final Map trustedKeys = new HashMap<>();
private final IdentityKeyPair identityKeyPair;
- private final int localRegistrationId;
+ private final int localRegistrationId;
public InMemoryIdentityKeyStore(IdentityKeyPair identityKeyPair, int localRegistrationId) {
- this.identityKeyPair = identityKeyPair;
+ this.identityKeyPair = identityKeyPair;
this.localRegistrationId = localRegistrationId;
}
@@ -48,7 +47,8 @@ public boolean saveIdentity(SignalProtocolAddress address, IdentityKey identityK
}
@Override
- public boolean isTrustedIdentity(SignalProtocolAddress address, IdentityKey identityKey, Direction direction) {
+ public boolean isTrustedIdentity(
+ SignalProtocolAddress address, IdentityKey identityKey, Direction direction) {
IdentityKey trusted = trustedKeys.get(address);
return (trusted == null || trusted.equals(identityKey));
}
diff --git a/java/shared/java/org/signal/libsignal/protocol/state/impl/InMemoryKyberPreKeyStore.java b/java/shared/java/org/signal/libsignal/protocol/state/impl/InMemoryKyberPreKeyStore.java
index 118c2d408f..c888bba35b 100644
--- a/java/shared/java/org/signal/libsignal/protocol/state/impl/InMemoryKyberPreKeyStore.java
+++ b/java/shared/java/org/signal/libsignal/protocol/state/impl/InMemoryKyberPreKeyStore.java
@@ -2,12 +2,8 @@
// Copyright 2023 Signal Messenger, LLC.
// SPDX-License-Identifier: AGPL-3.0-only
//
-package org.signal.libsignal.protocol.state.impl;
-import org.signal.libsignal.protocol.InvalidKeyIdException;
-import org.signal.libsignal.protocol.InvalidMessageException;
-import org.signal.libsignal.protocol.state.KyberPreKeyRecord;
-import org.signal.libsignal.protocol.state.KyberPreKeyStore;
+package org.signal.libsignal.protocol.state.impl;
import java.util.HashMap;
import java.util.HashSet;
@@ -15,6 +11,10 @@
import java.util.List;
import java.util.Map;
import java.util.Set;
+import org.signal.libsignal.protocol.InvalidKeyIdException;
+import org.signal.libsignal.protocol.InvalidMessageException;
+import org.signal.libsignal.protocol.state.KyberPreKeyRecord;
+import org.signal.libsignal.protocol.state.KyberPreKeyStore;
public class InMemoryKyberPreKeyStore implements KyberPreKeyStore {
@@ -61,7 +61,7 @@ public boolean containsKyberPreKey(int kyberPreKeyId) {
@Override
public void markKyberPreKeyUsed(int kyberPreKeyId) {
- //store.remove(kyberPreKeyId);
+ // store.remove(kyberPreKeyId);
used.add(kyberPreKeyId);
}
diff --git a/java/shared/java/org/signal/libsignal/protocol/state/impl/InMemoryPreKeyStore.java b/java/shared/java/org/signal/libsignal/protocol/state/impl/InMemoryPreKeyStore.java
index 0ad6380b88..a6fca935c8 100644
--- a/java/shared/java/org/signal/libsignal/protocol/state/impl/InMemoryPreKeyStore.java
+++ b/java/shared/java/org/signal/libsignal/protocol/state/impl/InMemoryPreKeyStore.java
@@ -1,18 +1,17 @@
-/**
- * Copyright (C) 2014-2016 Open Whisper Systems
- *
- * Licensed according to the LICENSE file in this repository.
- */
+//
+// Copyright 2014-2016 Signal Messenger, LLC.
+// SPDX-License-Identifier: AGPL-3.0-only
+//
+
package org.signal.libsignal.protocol.state.impl;
+import java.util.HashMap;
+import java.util.Map;
import org.signal.libsignal.protocol.InvalidKeyIdException;
import org.signal.libsignal.protocol.InvalidMessageException;
import org.signal.libsignal.protocol.state.PreKeyRecord;
import org.signal.libsignal.protocol.state.PreKeyStore;
-import java.util.HashMap;
-import java.util.Map;
-
public class InMemoryPreKeyStore implements PreKeyStore {
private final Map store = new HashMap<>();
diff --git a/java/shared/java/org/signal/libsignal/protocol/state/impl/InMemorySessionStore.java b/java/shared/java/org/signal/libsignal/protocol/state/impl/InMemorySessionStore.java
index 7deb7ee582..4dc7364483 100644
--- a/java/shared/java/org/signal/libsignal/protocol/state/impl/InMemorySessionStore.java
+++ b/java/shared/java/org/signal/libsignal/protocol/state/impl/InMemorySessionStore.java
@@ -1,21 +1,20 @@
-/**
- * Copyright (C) 2014-2016 Open Whisper Systems
- *
- * Licensed according to the LICENSE file in this repository.
- */
+//
+// Copyright 2014-2016 Signal Messenger, LLC.
+// SPDX-License-Identifier: AGPL-3.0-only
+//
+
package org.signal.libsignal.protocol.state.impl;
+import java.util.HashMap;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
import org.signal.libsignal.protocol.InvalidMessageException;
import org.signal.libsignal.protocol.NoSessionException;
import org.signal.libsignal.protocol.SignalProtocolAddress;
import org.signal.libsignal.protocol.state.SessionRecord;
import org.signal.libsignal.protocol.state.SessionStore;
-import java.util.HashMap;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Map;
-
public class InMemorySessionStore implements SessionStore {
private Map sessions = new HashMap<>();
@@ -36,7 +35,8 @@ public synchronized SessionRecord loadSession(SignalProtocolAddress remoteAddres
}
@Override
- public synchronized List loadExistingSessions(List addresses) throws NoSessionException {
+ public synchronized List loadExistingSessions(
+ List addresses) throws NoSessionException {
List resultSessions = new LinkedList<>();
for (SignalProtocolAddress remoteAddress : addresses) {
byte[] serialized = sessions.get(remoteAddress);
@@ -57,9 +57,7 @@ public synchronized List getSubDeviceSessions(String name) {
List deviceIds = new LinkedList<>();
for (SignalProtocolAddress key : sessions.keySet()) {
- if (key.getName().equals(name) &&
- key.getDeviceId() != 1)
- {
+ if (key.getName().equals(name) && key.getDeviceId() != 1) {
deviceIds.add(key.getDeviceId());
}
}
diff --git a/java/shared/java/org/signal/libsignal/protocol/state/impl/InMemorySignalProtocolStore.java b/java/shared/java/org/signal/libsignal/protocol/state/impl/InMemorySignalProtocolStore.java
index f576417b9a..229eb7971b 100644
--- a/java/shared/java/org/signal/libsignal/protocol/state/impl/InMemorySignalProtocolStore.java
+++ b/java/shared/java/org/signal/libsignal/protocol/state/impl/InMemorySignalProtocolStore.java
@@ -1,35 +1,34 @@
-/**
- * Copyright (C) 2014-2016 Open Whisper Systems
- *
- * Licensed according to the LICENSE file in this repository.
- */
+//
+// Copyright 2014-2016 Signal Messenger, LLC.
+// SPDX-License-Identifier: AGPL-3.0-only
+//
+
package org.signal.libsignal.protocol.state.impl;
-import org.signal.libsignal.protocol.SignalProtocolAddress;
+import java.util.List;
+import java.util.UUID;
import org.signal.libsignal.protocol.IdentityKey;
import org.signal.libsignal.protocol.IdentityKeyPair;
import org.signal.libsignal.protocol.InvalidKeyIdException;
import org.signal.libsignal.protocol.NoSessionException;
+import org.signal.libsignal.protocol.SignalProtocolAddress;
import org.signal.libsignal.protocol.groups.state.InMemorySenderKeyStore;
import org.signal.libsignal.protocol.groups.state.SenderKeyRecord;
-import org.signal.libsignal.protocol.state.SignalProtocolStore;
+import org.signal.libsignal.protocol.state.KyberPreKeyRecord;
import org.signal.libsignal.protocol.state.PreKeyRecord;
import org.signal.libsignal.protocol.state.SessionRecord;
+import org.signal.libsignal.protocol.state.SignalProtocolStore;
import org.signal.libsignal.protocol.state.SignedPreKeyRecord;
-import org.signal.libsignal.protocol.state.KyberPreKeyRecord;
-
-import java.util.List;
-import java.util.UUID;
public class InMemorySignalProtocolStore implements SignalProtocolStore {
- private final InMemoryPreKeyStore preKeyStore = new InMemoryPreKeyStore();
- private final InMemorySessionStore sessionStore = new InMemorySessionStore();
+ private final InMemoryPreKeyStore preKeyStore = new InMemoryPreKeyStore();
+ private final InMemorySessionStore sessionStore = new InMemorySessionStore();
private final InMemorySignedPreKeyStore signedPreKeyStore = new InMemorySignedPreKeyStore();
- private final InMemoryKyberPreKeyStore kyberPreKeyStore = new InMemoryKyberPreKeyStore();
- private final InMemorySenderKeyStore senderKeyStore = new InMemorySenderKeyStore();
+ private final InMemoryKyberPreKeyStore kyberPreKeyStore = new InMemoryKyberPreKeyStore();
+ private final InMemorySenderKeyStore senderKeyStore = new InMemorySenderKeyStore();
- private final InMemoryIdentityKeyStore identityKeyStore;
+ private final InMemoryIdentityKeyStore identityKeyStore;
public InMemorySignalProtocolStore(IdentityKeyPair identityKeyPair, int registrationId) {
this.identityKeyStore = new InMemoryIdentityKeyStore(identityKeyPair, registrationId);
@@ -51,7 +50,8 @@ public boolean saveIdentity(SignalProtocolAddress address, IdentityKey identityK
}
@Override
- public boolean isTrustedIdentity(SignalProtocolAddress address, IdentityKey identityKey, Direction direction) {
+ public boolean isTrustedIdentity(
+ SignalProtocolAddress address, IdentityKey identityKey, Direction direction) {
return identityKeyStore.isTrustedIdentity(address, identityKey, direction);
}
@@ -86,7 +86,8 @@ public SessionRecord loadSession(SignalProtocolAddress address) {
}
@Override
- public List loadExistingSessions(List addresses) throws NoSessionException {
+ public List loadExistingSessions(List addresses)
+ throws NoSessionException {
return sessionStore.loadExistingSessions(addresses);
}
@@ -141,7 +142,8 @@ public void removeSignedPreKey(int signedPreKeyId) {
}
@Override
- public void storeSenderKey(SignalProtocolAddress sender, UUID distributionId, SenderKeyRecord record) {
+ public void storeSenderKey(
+ SignalProtocolAddress sender, UUID distributionId, SenderKeyRecord record) {
senderKeyStore.storeSenderKey(sender, distributionId, record);
}
diff --git a/java/shared/java/org/signal/libsignal/protocol/state/impl/InMemorySignedPreKeyStore.java b/java/shared/java/org/signal/libsignal/protocol/state/impl/InMemorySignedPreKeyStore.java
index d60c763712..7a1c054880 100644
--- a/java/shared/java/org/signal/libsignal/protocol/state/impl/InMemorySignedPreKeyStore.java
+++ b/java/shared/java/org/signal/libsignal/protocol/state/impl/InMemorySignedPreKeyStore.java
@@ -1,19 +1,18 @@
-/**
- * Copyright (C) 2014-2016 Open Whisper Systems
- *
- * Licensed according to the LICENSE file in this repository.
- */
-package org.signal.libsignal.protocol.state.impl;
+//
+// Copyright 2014-2016 Signal Messenger, LLC.
+// SPDX-License-Identifier: AGPL-3.0-only
+//
-import org.signal.libsignal.protocol.InvalidKeyIdException;
-import org.signal.libsignal.protocol.InvalidMessageException;
-import org.signal.libsignal.protocol.state.SignedPreKeyRecord;
-import org.signal.libsignal.protocol.state.SignedPreKeyStore;
+package org.signal.libsignal.protocol.state.impl;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
+import org.signal.libsignal.protocol.InvalidKeyIdException;
+import org.signal.libsignal.protocol.InvalidMessageException;
+import org.signal.libsignal.protocol.state.SignedPreKeyRecord;
+import org.signal.libsignal.protocol.state.SignedPreKeyStore;
public class InMemorySignedPreKeyStore implements SignedPreKeyStore {
diff --git a/java/shared/java/org/signal/libsignal/protocol/util/ByteUtil.java b/java/shared/java/org/signal/libsignal/protocol/util/ByteUtil.java
index 6278e12905..c521d1d745 100644
--- a/java/shared/java/org/signal/libsignal/protocol/util/ByteUtil.java
+++ b/java/shared/java/org/signal/libsignal/protocol/util/ByteUtil.java
@@ -1,8 +1,8 @@
-/**
- * Copyright (C) 2014-2016 Open Whisper Systems
- *
- * Licensed according to the LICENSE file in this repository.
- */
+//
+// Copyright 2014-2016 Signal Messenger, LLC.
+// SPDX-License-Identifier: AGPL-3.0-only
+//
+
package org.signal.libsignal.protocol.util;
import java.io.ByteArrayOutputStream;
@@ -38,12 +38,14 @@ public static byte[][] split(byte[] input, int firstLength, int secondLength) {
}
public static byte[][] split(byte[] input, int firstLength, int secondLength, int thirdLength)
- throws ParseException
- {
- if (input == null || firstLength < 0 || secondLength < 0 || thirdLength < 0 ||
- input.length < firstLength + secondLength + thirdLength)
- {
- throw new ParseException("Input too small: " + (input == null ? null : Hex.toString(input)), 0);
+ throws ParseException {
+ if (input == null
+ || firstLength < 0
+ || secondLength < 0
+ || thirdLength < 0
+ || input.length < firstLength + secondLength + thirdLength) {
+ throw new ParseException(
+ "Input too small: " + (input == null ? null : Hex.toString(input)), 0);
}
byte[][] parts = new byte[3][];
@@ -68,7 +70,7 @@ public static byte[] trim(byte[] input, int length) {
}
public static byte intsToByteHighAndLow(int highValue, int lowValue) {
- return (byte)((highValue << 4 | lowValue) & 0xFF);
+ return (byte) ((highValue << 4 | lowValue) & 0xFF);
}
public static int highBitsToInt(byte value) {
@@ -77,24 +79,22 @@ public static int highBitsToInt(byte value) {
public static byte[] longToByteArray(long value) {
byte[] bytes = new byte[8];
- bytes[7] = (byte)value;
- bytes[6] = (byte)(value >> 8);
- bytes[5] = (byte)(value >> 16);
- bytes[4] = (byte)(value >> 24);
- bytes[3] = (byte)(value >> 32);
- bytes[2] = (byte)(value >> 40);
- bytes[1] = (byte)(value >> 48);
- bytes[0] = (byte)(value >> 56);
+ bytes[7] = (byte) value;
+ bytes[6] = (byte) (value >> 8);
+ bytes[5] = (byte) (value >> 16);
+ bytes[4] = (byte) (value >> 24);
+ bytes[3] = (byte) (value >> 32);
+ bytes[2] = (byte) (value >> 40);
+ bytes[1] = (byte) (value >> 48);
+ bytes[0] = (byte) (value >> 56);
return bytes;
}
public static long byteArray5ToLong(byte[] bytes, int offset) {
- return
- ((bytes[offset] & 0xffL) << 32) |
- ((bytes[offset + 1] & 0xffL) << 24) |
- ((bytes[offset + 2] & 0xffL) << 16) |
- ((bytes[offset + 3] & 0xffL) << 8) |
- ((bytes[offset + 4] & 0xffL));
+ return ((bytes[offset] & 0xffL) << 32)
+ | ((bytes[offset + 1] & 0xffL) << 24)
+ | ((bytes[offset + 2] & 0xffL) << 16)
+ | ((bytes[offset + 3] & 0xffL) << 8)
+ | ((bytes[offset + 4] & 0xffL));
}
-
}
diff --git a/java/shared/java/org/signal/libsignal/protocol/util/Hex.java b/java/shared/java/org/signal/libsignal/protocol/util/Hex.java
index c81e972ae4..c2fdad3c7d 100644
--- a/java/shared/java/org/signal/libsignal/protocol/util/Hex.java
+++ b/java/shared/java/org/signal/libsignal/protocol/util/Hex.java
@@ -1,18 +1,16 @@
-/**
- * Copyright (C) 2014-2016 Open Whisper Systems
- *
- * Licensed according to the LICENSE file in this repository.
- */
+//
+// Copyright 2014-2016 Signal Messenger, LLC.
+// SPDX-License-Identifier: AGPL-3.0-only
+//
+
package org.signal.libsignal.protocol.util;
import java.io.IOException;
-/**
- * Utility for generating hex dumps.
- */
+/** Utility for generating hex dumps. */
public class Hex {
- private final static char[] HEX_DIGITS = {
+ private static final char[] HEX_DIGITS = {
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'
};
@@ -31,7 +29,7 @@ public static String toString(byte[] bytes, int offset, int length) {
public static String toStringCondensed(byte[] bytes) {
StringBuffer buf = new StringBuffer();
- for (int i=0;i> 4) & 0xf]);
buf.append(HEX_DIGITS[b & 0xf]);
}
-
}
diff --git a/java/shared/java/org/signal/libsignal/protocol/util/KeyHelper.java b/java/shared/java/org/signal/libsignal/protocol/util/KeyHelper.java
index 2153c4eb7e..35319e2763 100644
--- a/java/shared/java/org/signal/libsignal/protocol/util/KeyHelper.java
+++ b/java/shared/java/org/signal/libsignal/protocol/util/KeyHelper.java
@@ -1,22 +1,12 @@
-/**
- * Copyright (C) 2014-2016 Open Whisper Systems
- *
- * Licensed according to the LICENSE file in this repository.
- */
-package org.signal.libsignal.protocol.util;
+//
+// Copyright 2014-2016 Signal Messenger, LLC.
+// SPDX-License-Identifier: AGPL-3.0-only
+//
-import org.signal.libsignal.protocol.IdentityKey;
-import org.signal.libsignal.protocol.IdentityKeyPair;
-import org.signal.libsignal.protocol.InvalidKeyException;
-import org.signal.libsignal.protocol.ecc.Curve;
-import org.signal.libsignal.protocol.ecc.ECKeyPair;
-import org.signal.libsignal.protocol.state.PreKeyRecord;
-import org.signal.libsignal.protocol.state.SignedPreKeyRecord;
+package org.signal.libsignal.protocol.util;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
-import java.util.LinkedList;
-import java.util.List;
/**
* Helper class for generating keys of different types.
@@ -28,24 +18,20 @@ public class KeyHelper {
private KeyHelper() {}
/**
- * Generate a registration ID. Clients should only do this once,
- * at install time.
+ * Generate a registration ID. Clients should only do this once, at install time.
*
- * @param extendedRange By default (false), the generated registration
- * ID is sized to require the minimal possible protobuf
- * encoding overhead. Specify true if the caller needs
- * the full range of MAX_INT at the cost of slightly
- * higher encoding overhead.
+ * @param extendedRange By default (false), the generated registration ID is sized to require the
+ * minimal possible protobuf encoding overhead. Specify true if the caller needs the full
+ * range of MAX_INT at the cost of slightly higher encoding overhead.
* @return the generated registration ID.
*/
public static int generateRegistrationId(boolean extendedRange) {
try {
SecureRandom secureRandom = SecureRandom.getInstance("SHA1PRNG");
if (extendedRange) return secureRandom.nextInt(Integer.MAX_VALUE - 1) + 1;
- else return secureRandom.nextInt(16380) + 1;
+ else return secureRandom.nextInt(16380) + 1;
} catch (NoSuchAlgorithmException e) {
throw new AssertionError(e);
}
}
-
}
diff --git a/java/shared/java/org/signal/libsignal/protocol/util/Medium.java b/java/shared/java/org/signal/libsignal/protocol/util/Medium.java
index d51597076f..709153fc6e 100644
--- a/java/shared/java/org/signal/libsignal/protocol/util/Medium.java
+++ b/java/shared/java/org/signal/libsignal/protocol/util/Medium.java
@@ -1,8 +1,8 @@
-/**
- * Copyright (C) 2014-2016 Open Whisper Systems
- *
- * Licensed according to the LICENSE file in this repository.
- */
+//
+// Copyright 2014-2016 Signal Messenger, LLC.
+// SPDX-License-Identifier: AGPL-3.0-only
+//
+
package org.signal.libsignal.protocol.util;
public class Medium {
diff --git a/java/shared/java/org/signal/libsignal/protocol/util/Pair.java b/java/shared/java/org/signal/libsignal/protocol/util/Pair.java
index 2cbf729498..42e75ebda5 100644
--- a/java/shared/java/org/signal/libsignal/protocol/util/Pair.java
+++ b/java/shared/java/org/signal/libsignal/protocol/util/Pair.java
@@ -1,8 +1,8 @@
-/**
- * Copyright (C) 2014-2016 Open Whisper Systems
- *
- * Licensed according to the LICENSE file in this repository.
- */
+//
+// Copyright 2014-2016 Signal Messenger, LLC.
+// SPDX-License-Identifier: AGPL-3.0-only
+//
+
package org.signal.libsignal.protocol.util;
public class Pair {
@@ -14,18 +14,18 @@ public Pair(T1 v1, T2 v2) {
this.v2 = v2;
}
- public T1 first(){
+ public T1 first() {
return v1;
}
- public T2 second(){
+ public T2 second() {
return v2;
}
public boolean equals(Object o) {
- return o instanceof Pair &&
- equal(((Pair) o).first(), first()) &&
- equal(((Pair) o).second(), second());
+ return o instanceof Pair
+ && equal(((Pair) o).first(), first())
+ && equal(((Pair) o).second(), second());
}
public int hashCode() {
diff --git a/java/shared/java/org/signal/libsignal/quic/QuicClient.java b/java/shared/java/org/signal/libsignal/quic/QuicClient.java
index 976ddb1637..fbda1fd50b 100644
--- a/java/shared/java/org/signal/libsignal/quic/QuicClient.java
+++ b/java/shared/java/org/signal/libsignal/quic/QuicClient.java
@@ -6,7 +6,6 @@
package org.signal.libsignal.quic;
import java.util.Map;
-
import org.signal.libsignal.internal.Native;
public class QuicClient {
@@ -22,11 +21,12 @@ public QuicClient(String target) {
this.unsafeHandle = Native.QuicClient_New(target);
}
- @Override @SuppressWarnings("deprecation")
+ @Override
+ @SuppressWarnings("deprecation")
protected void finalize() {
Native.QuicClient_Destroy(this.unsafeHandle);
}
-
+
public long unsafeNativeHandleWithoutGuard() {
return this.unsafeHandle;
}
@@ -35,7 +35,8 @@ public byte[] sendMessage(byte[] data) {
return Native.QuicClient_SendMessage(this.unsafeHandle, data);
}
- public void openControlledStream(String baseUrl, Map headers, QuicCallbackListener listener) {
+ public void openControlledStream(
+ String baseUrl, Map headers, QuicCallbackListener listener) {
Native.QuicClient_OpenControlledStream(this.unsafeHandle, baseUrl, headers, listener);
}
diff --git a/java/shared/java/org/signal/libsignal/usernames/BadDiscriminatorException.java b/java/shared/java/org/signal/libsignal/usernames/BadDiscriminatorException.java
index e2d79c84b4..a67d538175 100644
--- a/java/shared/java/org/signal/libsignal/usernames/BadDiscriminatorException.java
+++ b/java/shared/java/org/signal/libsignal/usernames/BadDiscriminatorException.java
@@ -2,10 +2,11 @@
// Copyright 2023 Signal Messenger, LLC.
// SPDX-License-Identifier: AGPL-3.0-only
//
+
package org.signal.libsignal.usernames;
public final class BadDiscriminatorException extends BaseUsernameException {
- public BadDiscriminatorException(String message) {
- super(message);
- }
+ public BadDiscriminatorException(String message) {
+ super(message);
+ }
}
diff --git a/java/shared/java/org/signal/libsignal/usernames/BadNicknameCharacterException.java b/java/shared/java/org/signal/libsignal/usernames/BadNicknameCharacterException.java
index 629260c02c..aad2be104a 100644
--- a/java/shared/java/org/signal/libsignal/usernames/BadNicknameCharacterException.java
+++ b/java/shared/java/org/signal/libsignal/usernames/BadNicknameCharacterException.java
@@ -2,10 +2,11 @@
// Copyright 2023 Signal Messenger, LLC.
// SPDX-License-Identifier: AGPL-3.0-only
//
+
package org.signal.libsignal.usernames;
public final class BadNicknameCharacterException extends BaseUsernameException {
- public BadNicknameCharacterException(String message) {
- super(message);
- }
+ public BadNicknameCharacterException(String message) {
+ super(message);
+ }
}
diff --git a/java/shared/java/org/signal/libsignal/usernames/BaseUsernameException.java b/java/shared/java/org/signal/libsignal/usernames/BaseUsernameException.java
index c77b98f70d..8dd0e6d9da 100644
--- a/java/shared/java/org/signal/libsignal/usernames/BaseUsernameException.java
+++ b/java/shared/java/org/signal/libsignal/usernames/BaseUsernameException.java
@@ -2,10 +2,11 @@
// Copyright 2023 Signal Messenger, LLC.
// SPDX-License-Identifier: AGPL-3.0-only
//
+
package org.signal.libsignal.usernames;
public class BaseUsernameException extends Exception {
- public BaseUsernameException(String message) {
- super(message);
- }
-}
\ No newline at end of file
+ public BaseUsernameException(String message) {
+ super(message);
+ }
+}
diff --git a/java/shared/java/org/signal/libsignal/usernames/CannotBeEmptyException.java b/java/shared/java/org/signal/libsignal/usernames/CannotBeEmptyException.java
index 62b2c4f62b..5f7abdcefe 100644
--- a/java/shared/java/org/signal/libsignal/usernames/CannotBeEmptyException.java
+++ b/java/shared/java/org/signal/libsignal/usernames/CannotBeEmptyException.java
@@ -2,10 +2,11 @@
// Copyright 2023 Signal Messenger, LLC.
// SPDX-License-Identifier: AGPL-3.0-only
//
+
package org.signal.libsignal.usernames;
public final class CannotBeEmptyException extends BaseUsernameException {
- public CannotBeEmptyException(String message) {
- super(message);
- }
+ public CannotBeEmptyException(String message) {
+ super(message);
+ }
}
diff --git a/java/shared/java/org/signal/libsignal/usernames/CannotStartWithDigitException.java b/java/shared/java/org/signal/libsignal/usernames/CannotStartWithDigitException.java
index aeb69fc049..d0c9a2cf19 100644
--- a/java/shared/java/org/signal/libsignal/usernames/CannotStartWithDigitException.java
+++ b/java/shared/java/org/signal/libsignal/usernames/CannotStartWithDigitException.java
@@ -2,10 +2,11 @@
// Copyright 2023 Signal Messenger, LLC.
// SPDX-License-Identifier: AGPL-3.0-only
//
+
package org.signal.libsignal.usernames;
public final class CannotStartWithDigitException extends BaseUsernameException {
- public CannotStartWithDigitException(String message) {
- super(message);
- }
+ public CannotStartWithDigitException(String message) {
+ super(message);
+ }
}
diff --git a/java/shared/java/org/signal/libsignal/usernames/MissingSeparatorException.java b/java/shared/java/org/signal/libsignal/usernames/MissingSeparatorException.java
index 74014d0956..f7bac633cf 100644
--- a/java/shared/java/org/signal/libsignal/usernames/MissingSeparatorException.java
+++ b/java/shared/java/org/signal/libsignal/usernames/MissingSeparatorException.java
@@ -2,10 +2,11 @@
// Copyright 2023 Signal Messenger, LLC.
// SPDX-License-Identifier: AGPL-3.0-only
//
+
package org.signal.libsignal.usernames;
public final class MissingSeparatorException extends BaseUsernameException {
- public MissingSeparatorException(String message) {
- super(message);
- }
+ public MissingSeparatorException(String message) {
+ super(message);
+ }
}
diff --git a/java/shared/java/org/signal/libsignal/usernames/NicknameTooLongException.java b/java/shared/java/org/signal/libsignal/usernames/NicknameTooLongException.java
index 6250969fc2..9c7aa8c405 100644
--- a/java/shared/java/org/signal/libsignal/usernames/NicknameTooLongException.java
+++ b/java/shared/java/org/signal/libsignal/usernames/NicknameTooLongException.java
@@ -2,10 +2,11 @@
// Copyright 2023 Signal Messenger, LLC.
// SPDX-License-Identifier: AGPL-3.0-only
//
+
package org.signal.libsignal.usernames;
public final class NicknameTooLongException extends BaseUsernameException {
- public NicknameTooLongException(String message) {
- super(message);
- }
+ public NicknameTooLongException(String message) {
+ super(message);
+ }
}
diff --git a/java/shared/java/org/signal/libsignal/usernames/NicknameTooShortException.java b/java/shared/java/org/signal/libsignal/usernames/NicknameTooShortException.java
index 5e8f88e854..91bfb1eb98 100644
--- a/java/shared/java/org/signal/libsignal/usernames/NicknameTooShortException.java
+++ b/java/shared/java/org/signal/libsignal/usernames/NicknameTooShortException.java
@@ -2,10 +2,11 @@
// Copyright 2023 Signal Messenger, LLC.
// SPDX-License-Identifier: AGPL-3.0-only
//
+
package org.signal.libsignal.usernames;
public final class NicknameTooShortException extends BaseUsernameException {
- public NicknameTooShortException(String message) {
- super(message);
- }
+ public NicknameTooShortException(String message) {
+ super(message);
+ }
}
diff --git a/java/shared/java/org/signal/libsignal/usernames/ProofVerificationFailureException.java b/java/shared/java/org/signal/libsignal/usernames/ProofVerificationFailureException.java
index 5c94b0e021..49dd1740d9 100644
--- a/java/shared/java/org/signal/libsignal/usernames/ProofVerificationFailureException.java
+++ b/java/shared/java/org/signal/libsignal/usernames/ProofVerificationFailureException.java
@@ -2,10 +2,11 @@
// Copyright 2023 Signal Messenger, LLC.
// SPDX-License-Identifier: AGPL-3.0-only
//
+
package org.signal.libsignal.usernames;
public final class ProofVerificationFailureException extends BaseUsernameException {
- public ProofVerificationFailureException(String message) {
- super(message);
- }
+ public ProofVerificationFailureException(String message) {
+ super(message);
+ }
}
diff --git a/java/shared/java/org/signal/libsignal/usernames/Username.java b/java/shared/java/org/signal/libsignal/usernames/Username.java
index 42e0613c1d..cf2effe10b 100644
--- a/java/shared/java/org/signal/libsignal/usernames/Username.java
+++ b/java/shared/java/org/signal/libsignal/usernames/Username.java
@@ -2,135 +2,139 @@
// Copyright 2023 Signal Messenger, LLC.
// SPDX-License-Identifier: AGPL-3.0-only
//
-package org.signal.libsignal.usernames;
-import java.util.Objects;
-import java.util.concurrent.ThreadLocalRandom;
-import org.signal.libsignal.internal.Native;
+package org.signal.libsignal.usernames;
import java.security.SecureRandom;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
+import java.util.Objects;
+import org.signal.libsignal.internal.Native;
public final class Username {
- private final String username;
- private final byte[] hash;
-
- public static class UsernameLink {
- private final byte[] entropy;
- private final byte[] encryptedUsername;
-
- public UsernameLink(final byte[] entropy, final byte[] encryptedUsername) {
- this.entropy = Objects.requireNonNull(entropy, "entropy");
- this.encryptedUsername = Objects.requireNonNull(encryptedUsername, "encryptedUsername");
- }
-
- public byte[] getEntropy() {
- return entropy;
- }
-
- public byte[] getEncryptedUsername() {
- return encryptedUsername;
- }
-
- @Override
- public boolean equals(final Object o) {
- if (this == o) return true;
- if (o == null || getClass() != o.getClass()) return false;
- final UsernameLink that = (UsernameLink) o;
- return Arrays.equals(entropy, that.entropy) &&
- Arrays.equals(encryptedUsername, that.encryptedUsername);
- }
-
- @Override
- public int hashCode() {
- int result = Arrays.hashCode(entropy);
- result = 31 * result + Arrays.hashCode(encryptedUsername);
- return result;
- }
- }
-
- public Username(String username) throws BaseUsernameException {
- this.username = Objects.requireNonNull(username, "username");
- this.hash = hash(username);
- }
-
- public String getUsername() {
- return this.username;
- }
-
- public byte[] getHash() {
- return this.hash;
- }
-
- public static List candidatesFrom(String nickname, int minNicknameLength, int maxNicknameLength) throws BaseUsernameException {
- String names = Native.Username_CandidatesFrom(nickname, minNicknameLength, maxNicknameLength);
- ArrayList result = new ArrayList<>();
- for (String name : names.split(",")) {
- result.add(new Username(name));
- }
- return result;
- }
-
- public static Username fromLink(final UsernameLink usernameLink) throws BaseUsernameException {
- final String username = Native.UsernameLink_DecryptUsername(usernameLink.getEntropy(), usernameLink.getEncryptedUsername());
- return new Username(username);
- }
-
- public byte[] generateProof() throws BaseUsernameException {
- byte[] randomness = new byte[32];
- SecureRandom r = new SecureRandom();
- r.nextBytes(randomness);
- return generateProofWithRandomness(randomness);
- }
-
- public byte[] generateProofWithRandomness(byte[] randomness) throws BaseUsernameException {
- return Native.Username_Proof(this.username, randomness);
- }
+ private final String username;
+ private final byte[] hash;
- public UsernameLink generateLink() throws BaseUsernameException {
- final byte[] bytes = Native.UsernameLink_Create(username);
- final byte[] entropy = Arrays.copyOfRange(bytes, 0, 32);
- final byte[] enctyptedUsername = Arrays.copyOfRange(bytes, 32, bytes.length);
- return new UsernameLink(entropy, enctyptedUsername);
- }
-
- @Deprecated
- public static List generateCandidates(String nickname, int minNicknameLength, int maxNicknameLength) throws BaseUsernameException {
- String names = Native.Username_CandidatesFrom(nickname, minNicknameLength, maxNicknameLength);
- return Arrays.asList(names.split(","));
- }
+ public static class UsernameLink {
+ private final byte[] entropy;
+ private final byte[] encryptedUsername;
- @Deprecated
- public static byte[] hash(String username) throws BaseUsernameException {
- return Native.Username_Hash(username);
+ public UsernameLink(final byte[] entropy, final byte[] encryptedUsername) {
+ this.entropy = Objects.requireNonNull(entropy, "entropy");
+ this.encryptedUsername = Objects.requireNonNull(encryptedUsername, "encryptedUsername");
}
- @Deprecated
- public static byte[] generateProof(String username, byte[] randomness) throws BaseUsernameException {
- return Native.Username_Proof(username, randomness);
+ public byte[] getEntropy() {
+ return entropy;
}
- public static void verifyProof(byte[] proof, byte[] hash) throws BaseUsernameException {
- Native.Username_Verify(proof, hash);
- }
-
- @Override
- public String toString() {
- return this.username;
+ public byte[] getEncryptedUsername() {
+ return encryptedUsername;
}
@Override
public boolean equals(final Object o) {
- if (this == o) return true;
- if (o == null || getClass() != o.getClass()) return false;
- final Username username1 = (Username) o;
- return username.equals(username1.username);
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+ final UsernameLink that = (UsernameLink) o;
+ return Arrays.equals(entropy, that.entropy)
+ && Arrays.equals(encryptedUsername, that.encryptedUsername);
}
@Override
public int hashCode() {
- return username.hashCode();
- }
+ int result = Arrays.hashCode(entropy);
+ result = 31 * result + Arrays.hashCode(encryptedUsername);
+ return result;
+ }
+ }
+
+ public Username(String username) throws BaseUsernameException {
+ this.username = Objects.requireNonNull(username, "username");
+ this.hash = hash(username);
+ }
+
+ public String getUsername() {
+ return this.username;
+ }
+
+ public byte[] getHash() {
+ return this.hash;
+ }
+
+ public static List candidatesFrom(
+ String nickname, int minNicknameLength, int maxNicknameLength) throws BaseUsernameException {
+ String names = Native.Username_CandidatesFrom(nickname, minNicknameLength, maxNicknameLength);
+ ArrayList result = new ArrayList<>();
+ for (String name : names.split(",")) {
+ result.add(new Username(name));
+ }
+ return result;
+ }
+
+ public static Username fromLink(final UsernameLink usernameLink) throws BaseUsernameException {
+ final String username =
+ Native.UsernameLink_DecryptUsername(
+ usernameLink.getEntropy(), usernameLink.getEncryptedUsername());
+ return new Username(username);
+ }
+
+ public byte[] generateProof() throws BaseUsernameException {
+ byte[] randomness = new byte[32];
+ SecureRandom r = new SecureRandom();
+ r.nextBytes(randomness);
+ return generateProofWithRandomness(randomness);
+ }
+
+ public byte[] generateProofWithRandomness(byte[] randomness) throws BaseUsernameException {
+ return Native.Username_Proof(this.username, randomness);
+ }
+
+ public UsernameLink generateLink() throws BaseUsernameException {
+ final byte[] bytes = Native.UsernameLink_Create(username);
+ final byte[] entropy = Arrays.copyOfRange(bytes, 0, 32);
+ final byte[] enctyptedUsername = Arrays.copyOfRange(bytes, 32, bytes.length);
+ return new UsernameLink(entropy, enctyptedUsername);
+ }
+
+ @Deprecated
+ public static List generateCandidates(
+ String nickname, int minNicknameLength, int maxNicknameLength) throws BaseUsernameException {
+ String names = Native.Username_CandidatesFrom(nickname, minNicknameLength, maxNicknameLength);
+ return Arrays.asList(names.split(","));
+ }
+
+ @Deprecated
+ public static byte[] hash(String username) throws BaseUsernameException {
+ return Native.Username_Hash(username);
+ }
+
+ @Deprecated
+ public static byte[] generateProof(String username, byte[] randomness)
+ throws BaseUsernameException {
+ return Native.Username_Proof(username, randomness);
+ }
+
+ public static void verifyProof(byte[] proof, byte[] hash) throws BaseUsernameException {
+ Native.Username_Verify(proof, hash);
+ }
+
+ @Override
+ public String toString() {
+ return this.username;
+ }
+
+ @Override
+ public boolean equals(final Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+ final Username username1 = (Username) o;
+ return username.equals(username1.username);
+ }
+
+ @Override
+ public int hashCode() {
+ return username.hashCode();
+ }
}
diff --git a/java/shared/java/org/signal/libsignal/usernames/UsernameLinkInputDataTooLong.java b/java/shared/java/org/signal/libsignal/usernames/UsernameLinkInputDataTooLong.java
index 74a757528e..188888ed74 100644
--- a/java/shared/java/org/signal/libsignal/usernames/UsernameLinkInputDataTooLong.java
+++ b/java/shared/java/org/signal/libsignal/usernames/UsernameLinkInputDataTooLong.java
@@ -1,3 +1,8 @@
+//
+// Copyright 2023 Signal Messenger, LLC.
+// SPDX-License-Identifier: AGPL-3.0-only
+//
+
package org.signal.libsignal.usernames;
public class UsernameLinkInputDataTooLong extends BaseUsernameException {
diff --git a/java/shared/java/org/signal/libsignal/usernames/UsernameLinkInvalidEntropyDataLength.java b/java/shared/java/org/signal/libsignal/usernames/UsernameLinkInvalidEntropyDataLength.java
index d6a110065f..2d83600018 100644
--- a/java/shared/java/org/signal/libsignal/usernames/UsernameLinkInvalidEntropyDataLength.java
+++ b/java/shared/java/org/signal/libsignal/usernames/UsernameLinkInvalidEntropyDataLength.java
@@ -1,3 +1,8 @@
+//
+// Copyright 2023 Signal Messenger, LLC.
+// SPDX-License-Identifier: AGPL-3.0-only
+//
+
package org.signal.libsignal.usernames;
public class UsernameLinkInvalidEntropyDataLength extends BaseUsernameException {
diff --git a/java/shared/java/org/signal/libsignal/usernames/UsernameLinkInvalidLinkData.java b/java/shared/java/org/signal/libsignal/usernames/UsernameLinkInvalidLinkData.java
index c13aff2c8e..ebebd2b61a 100644
--- a/java/shared/java/org/signal/libsignal/usernames/UsernameLinkInvalidLinkData.java
+++ b/java/shared/java/org/signal/libsignal/usernames/UsernameLinkInvalidLinkData.java
@@ -1,3 +1,8 @@
+//
+// Copyright 2023 Signal Messenger, LLC.
+// SPDX-License-Identifier: AGPL-3.0-only
+//
+
package org.signal.libsignal.usernames;
public class UsernameLinkInvalidLinkData extends BaseUsernameException {
diff --git a/java/shared/java/org/signal/libsignal/zkgroup/GenericServerPublicParams.java b/java/shared/java/org/signal/libsignal/zkgroup/GenericServerPublicParams.java
index 55e81f34a5..0aa8cf748c 100644
--- a/java/shared/java/org/signal/libsignal/zkgroup/GenericServerPublicParams.java
+++ b/java/shared/java/org/signal/libsignal/zkgroup/GenericServerPublicParams.java
@@ -5,8 +5,8 @@
package org.signal.libsignal.zkgroup;
-import org.signal.libsignal.zkgroup.internal.ByteArray;
import org.signal.libsignal.internal.Native;
+import org.signal.libsignal.zkgroup.internal.ByteArray;
public final class GenericServerPublicParams extends ByteArray {
public GenericServerPublicParams(byte[] contents) throws InvalidInputException {
diff --git a/java/shared/java/org/signal/libsignal/zkgroup/GenericServerSecretParams.java b/java/shared/java/org/signal/libsignal/zkgroup/GenericServerSecretParams.java
index 17e2910b41..429c0543eb 100644
--- a/java/shared/java/org/signal/libsignal/zkgroup/GenericServerSecretParams.java
+++ b/java/shared/java/org/signal/libsignal/zkgroup/GenericServerSecretParams.java
@@ -5,11 +5,11 @@
package org.signal.libsignal.zkgroup;
+import static org.signal.libsignal.zkgroup.internal.Constants.RANDOM_LENGTH;
+
import java.security.SecureRandom;
-import org.signal.libsignal.zkgroup.internal.ByteArray;
import org.signal.libsignal.internal.Native;
-
-import static org.signal.libsignal.zkgroup.internal.Constants.RANDOM_LENGTH;
+import org.signal.libsignal.zkgroup.internal.ByteArray;
public final class GenericServerSecretParams extends ByteArray {
@@ -18,7 +18,7 @@ public static GenericServerSecretParams generate() {
}
public static GenericServerSecretParams generate(SecureRandom secureRandom) {
- byte[] random = new byte[RANDOM_LENGTH];
+ byte[] random = new byte[RANDOM_LENGTH];
secureRandom.nextBytes(random);
byte[] newContents = Native.GenericServerSecretParams_GenerateDeterministic(random);
@@ -27,10 +27,10 @@ public static GenericServerSecretParams generate(SecureRandom secureRandom) {
return new GenericServerSecretParams(newContents);
} catch (InvalidInputException e) {
throw new AssertionError(e);
- }
+ }
}
- public GenericServerSecretParams(byte[] contents) throws InvalidInputException {
+ public GenericServerSecretParams(byte[] contents) throws InvalidInputException {
super(contents);
Native.GenericServerSecretParams_CheckValidContents(contents);
}
@@ -41,7 +41,6 @@ public GenericServerPublicParams getPublicParams() {
return new GenericServerPublicParams(newContents);
} catch (InvalidInputException e) {
throw new AssertionError(e);
- }
+ }
}
-
}
diff --git a/java/shared/java/org/signal/libsignal/zkgroup/InvalidInputException.java b/java/shared/java/org/signal/libsignal/zkgroup/InvalidInputException.java
index 399032c7b8..2a44582c2d 100644
--- a/java/shared/java/org/signal/libsignal/zkgroup/InvalidInputException.java
+++ b/java/shared/java/org/signal/libsignal/zkgroup/InvalidInputException.java
@@ -7,12 +7,9 @@
public class InvalidInputException extends Exception {
- public InvalidInputException() {
-
- }
+ public InvalidInputException() {}
public InvalidInputException(String message) {
super(message);
}
-
}
diff --git a/java/shared/java/org/signal/libsignal/zkgroup/NotarySignature.java b/java/shared/java/org/signal/libsignal/zkgroup/NotarySignature.java
index f28070e108..022f66659f 100644
--- a/java/shared/java/org/signal/libsignal/zkgroup/NotarySignature.java
+++ b/java/shared/java/org/signal/libsignal/zkgroup/NotarySignature.java
@@ -14,5 +14,4 @@ public final class NotarySignature extends ByteArray {
public NotarySignature(byte[] contents) throws InvalidInputException {
super(contents, SIZE);
}
-
}
diff --git a/java/shared/java/org/signal/libsignal/zkgroup/ServerPublicParams.java b/java/shared/java/org/signal/libsignal/zkgroup/ServerPublicParams.java
index c64d4fbb2e..a129da227a 100644
--- a/java/shared/java/org/signal/libsignal/zkgroup/ServerPublicParams.java
+++ b/java/shared/java/org/signal/libsignal/zkgroup/ServerPublicParams.java
@@ -5,8 +5,8 @@
package org.signal.libsignal.zkgroup;
-import org.signal.libsignal.zkgroup.internal.ByteArray;
import org.signal.libsignal.internal.Native;
+import org.signal.libsignal.zkgroup.internal.ByteArray;
public final class ServerPublicParams extends ByteArray {
public ServerPublicParams(byte[] contents) throws InvalidInputException {
@@ -14,8 +14,9 @@ public ServerPublicParams(byte[] contents) throws InvalidInputException {
Native.ServerPublicParams_CheckValidContents(contents);
}
- public void verifySignature(byte[] message, NotarySignature notarySignature) throws VerificationFailedException {
- Native.ServerPublicParams_VerifySignature(contents, message, notarySignature.getInternalContentsForJNI());
+ public void verifySignature(byte[] message, NotarySignature notarySignature)
+ throws VerificationFailedException {
+ Native.ServerPublicParams_VerifySignature(
+ contents, message, notarySignature.getInternalContentsForJNI());
}
-
}
diff --git a/java/shared/java/org/signal/libsignal/zkgroup/ServerSecretParams.java b/java/shared/java/org/signal/libsignal/zkgroup/ServerSecretParams.java
index 362cd6aa60..c42590c6be 100644
--- a/java/shared/java/org/signal/libsignal/zkgroup/ServerSecretParams.java
+++ b/java/shared/java/org/signal/libsignal/zkgroup/ServerSecretParams.java
@@ -5,11 +5,11 @@
package org.signal.libsignal.zkgroup;
+import static org.signal.libsignal.zkgroup.internal.Constants.RANDOM_LENGTH;
+
import java.security.SecureRandom;
-import org.signal.libsignal.zkgroup.internal.ByteArray;
import org.signal.libsignal.internal.Native;
-
-import static org.signal.libsignal.zkgroup.internal.Constants.RANDOM_LENGTH;
+import org.signal.libsignal.zkgroup.internal.ByteArray;
public final class ServerSecretParams extends ByteArray {
@@ -18,7 +18,7 @@ public static ServerSecretParams generate() {
}
public static ServerSecretParams generate(SecureRandom secureRandom) {
- byte[] random = new byte[RANDOM_LENGTH];
+ byte[] random = new byte[RANDOM_LENGTH];
secureRandom.nextBytes(random);
byte[] newContents = Native.ServerSecretParams_GenerateDeterministic(random);
@@ -27,10 +27,10 @@ public static ServerSecretParams generate(SecureRandom secureRandom) {
return new ServerSecretParams(newContents);
} catch (InvalidInputException e) {
throw new AssertionError(e);
- }
+ }
}
- public ServerSecretParams(byte[] contents) throws InvalidInputException {
+ public ServerSecretParams(byte[] contents) throws InvalidInputException {
super(contents);
Native.ServerSecretParams_CheckValidContents(contents);
}
@@ -41,7 +41,7 @@ public ServerPublicParams getPublicParams() {
return new ServerPublicParams(newContents);
} catch (InvalidInputException e) {
throw new AssertionError(e);
- }
+ }
}
public NotarySignature sign(byte[] message) {
@@ -49,7 +49,7 @@ public NotarySignature sign(byte[] message) {
}
public NotarySignature sign(SecureRandom secureRandom, byte[] message) {
- byte[] random = new byte[RANDOM_LENGTH];
+ byte[] random = new byte[RANDOM_LENGTH];
secureRandom.nextBytes(random);
byte[] newContents = Native.ServerSecretParams_SignDeterministic(contents, random, message);
@@ -60,5 +60,4 @@ public NotarySignature sign(SecureRandom secureRandom, byte[] message) {
throw new AssertionError(e);
}
}
-
}
diff --git a/java/shared/java/org/signal/libsignal/zkgroup/VerificationFailedException.java b/java/shared/java/org/signal/libsignal/zkgroup/VerificationFailedException.java
index 0aafb29bc3..4aebffff4b 100644
--- a/java/shared/java/org/signal/libsignal/zkgroup/VerificationFailedException.java
+++ b/java/shared/java/org/signal/libsignal/zkgroup/VerificationFailedException.java
@@ -6,6 +6,11 @@
package org.signal.libsignal.zkgroup;
public class VerificationFailedException extends Exception {
- public VerificationFailedException() { super(); }
- public VerificationFailedException(String msg) { super(msg); }
+ public VerificationFailedException() {
+ super();
+ }
+
+ public VerificationFailedException(String msg) {
+ super(msg);
+ }
}
diff --git a/java/shared/java/org/signal/libsignal/zkgroup/auth/AuthCredential.java b/java/shared/java/org/signal/libsignal/zkgroup/auth/AuthCredential.java
index e2a5a6a3fb..df5c3cd69d 100644
--- a/java/shared/java/org/signal/libsignal/zkgroup/auth/AuthCredential.java
+++ b/java/shared/java/org/signal/libsignal/zkgroup/auth/AuthCredential.java
@@ -5,9 +5,9 @@
package org.signal.libsignal.zkgroup.auth;
+import org.signal.libsignal.internal.Native;
import org.signal.libsignal.zkgroup.InvalidInputException;
import org.signal.libsignal.zkgroup.internal.ByteArray;
-import org.signal.libsignal.internal.Native;
public final class AuthCredential extends ByteArray {
public AuthCredential(byte[] contents) throws InvalidInputException {
diff --git a/java/shared/java/org/signal/libsignal/zkgroup/auth/AuthCredentialPresentation.java b/java/shared/java/org/signal/libsignal/zkgroup/auth/AuthCredentialPresentation.java
index bfc0fbc0d1..e516b1cba7 100644
--- a/java/shared/java/org/signal/libsignal/zkgroup/auth/AuthCredentialPresentation.java
+++ b/java/shared/java/org/signal/libsignal/zkgroup/auth/AuthCredentialPresentation.java
@@ -6,15 +6,19 @@
package org.signal.libsignal.zkgroup.auth;
import java.time.Instant;
-
+import org.signal.libsignal.internal.Native;
import org.signal.libsignal.zkgroup.InvalidInputException;
import org.signal.libsignal.zkgroup.groups.UuidCiphertext;
import org.signal.libsignal.zkgroup.internal.ByteArray;
-import org.signal.libsignal.internal.Native;
public final class AuthCredentialPresentation extends ByteArray {
- public enum Version {V1, V2, V3, UNKNOWN};
+ public enum Version {
+ V1,
+ V2,
+ V3,
+ UNKNOWN
+ };
public AuthCredentialPresentation(byte[] contents) throws InvalidInputException {
super(contents);
@@ -31,9 +35,7 @@ public UuidCiphertext getUuidCiphertext() {
}
}
- /**
- * Returns the PNI ciphertext for this credential. May be {@code null}.
- */
+ /** Returns the PNI ciphertext for this credential. May be {@code null}. */
public UuidCiphertext getPniCiphertext() {
byte[] newContents = Native.AuthCredentialPresentation_GetPniCiphertext(contents);
if (newContents == null) {
@@ -53,11 +55,14 @@ public Instant getRedemptionTime() {
public Version getVersion() {
switch (this.contents[0]) {
- case 0: return Version.V1;
- case 1: return Version.V2;
- case 2: return Version.V3;
- default: return Version.UNKNOWN;
+ case 0:
+ return Version.V1;
+ case 1:
+ return Version.V2;
+ case 2:
+ return Version.V3;
+ default:
+ return Version.UNKNOWN;
}
}
-
}
diff --git a/java/shared/java/org/signal/libsignal/zkgroup/auth/AuthCredentialResponse.java b/java/shared/java/org/signal/libsignal/zkgroup/auth/AuthCredentialResponse.java
index 838a9cec5a..f51adaedca 100644
--- a/java/shared/java/org/signal/libsignal/zkgroup/auth/AuthCredentialResponse.java
+++ b/java/shared/java/org/signal/libsignal/zkgroup/auth/AuthCredentialResponse.java
@@ -5,9 +5,9 @@
package org.signal.libsignal.zkgroup.auth;
+import org.signal.libsignal.internal.Native;
import org.signal.libsignal.zkgroup.InvalidInputException;
import org.signal.libsignal.zkgroup.internal.ByteArray;
-import org.signal.libsignal.internal.Native;
public final class AuthCredentialResponse extends ByteArray {
public AuthCredentialResponse(byte[] contents) throws InvalidInputException {
diff --git a/java/shared/java/org/signal/libsignal/zkgroup/auth/AuthCredentialWithPni.java b/java/shared/java/org/signal/libsignal/zkgroup/auth/AuthCredentialWithPni.java
index 6b5a505983..e6c12d575e 100644
--- a/java/shared/java/org/signal/libsignal/zkgroup/auth/AuthCredentialWithPni.java
+++ b/java/shared/java/org/signal/libsignal/zkgroup/auth/AuthCredentialWithPni.java
@@ -5,9 +5,9 @@
package org.signal.libsignal.zkgroup.auth;
+import org.signal.libsignal.internal.Native;
import org.signal.libsignal.zkgroup.InvalidInputException;
import org.signal.libsignal.zkgroup.internal.ByteArray;
-import org.signal.libsignal.internal.Native;
public final class AuthCredentialWithPni extends ByteArray {
public AuthCredentialWithPni(byte[] contents) throws InvalidInputException {
diff --git a/java/shared/java/org/signal/libsignal/zkgroup/auth/AuthCredentialWithPniResponse.java b/java/shared/java/org/signal/libsignal/zkgroup/auth/AuthCredentialWithPniResponse.java
index c5b1f59c3b..c89cc94979 100644
--- a/java/shared/java/org/signal/libsignal/zkgroup/auth/AuthCredentialWithPniResponse.java
+++ b/java/shared/java/org/signal/libsignal/zkgroup/auth/AuthCredentialWithPniResponse.java
@@ -5,9 +5,9 @@
package org.signal.libsignal.zkgroup.auth;
+import org.signal.libsignal.internal.Native;
import org.signal.libsignal.zkgroup.InvalidInputException;
import org.signal.libsignal.zkgroup.internal.ByteArray;
-import org.signal.libsignal.internal.Native;
public final class AuthCredentialWithPniResponse extends ByteArray {
public AuthCredentialWithPniResponse(byte[] contents) throws InvalidInputException {
diff --git a/java/shared/java/org/signal/libsignal/zkgroup/auth/ClientZkAuthOperations.java b/java/shared/java/org/signal/libsignal/zkgroup/auth/ClientZkAuthOperations.java
index 13ff92710e..9c12d8547c 100644
--- a/java/shared/java/org/signal/libsignal/zkgroup/auth/ClientZkAuthOperations.java
+++ b/java/shared/java/org/signal/libsignal/zkgroup/auth/ClientZkAuthOperations.java
@@ -5,16 +5,16 @@
package org.signal.libsignal.zkgroup.auth;
+import static org.signal.libsignal.zkgroup.internal.Constants.RANDOM_LENGTH;
+
import java.security.SecureRandom;
+import org.signal.libsignal.internal.Native;
import org.signal.libsignal.protocol.ServiceId.Aci;
import org.signal.libsignal.protocol.ServiceId.Pni;
import org.signal.libsignal.zkgroup.InvalidInputException;
import org.signal.libsignal.zkgroup.ServerPublicParams;
import org.signal.libsignal.zkgroup.VerificationFailedException;
import org.signal.libsignal.zkgroup.groups.GroupSecretParams;
-import org.signal.libsignal.internal.Native;
-
-import static org.signal.libsignal.zkgroup.internal.Constants.RANDOM_LENGTH;
public class ClientZkAuthOperations {
@@ -24,8 +24,15 @@ public ClientZkAuthOperations(ServerPublicParams serverPublicParams) {
this.serverPublicParams = serverPublicParams;
}
- public AuthCredential receiveAuthCredential(Aci aci, int redemptionTime, AuthCredentialResponse authCredentialResponse) throws VerificationFailedException {
- byte[] newContents = Native.ServerPublicParams_ReceiveAuthCredential(serverPublicParams.getInternalContentsForJNI(), aci.toServiceIdFixedWidthBinary(), redemptionTime, authCredentialResponse.getInternalContentsForJNI());
+ public AuthCredential receiveAuthCredential(
+ Aci aci, int redemptionTime, AuthCredentialResponse authCredentialResponse)
+ throws VerificationFailedException {
+ byte[] newContents =
+ Native.ServerPublicParams_ReceiveAuthCredential(
+ serverPublicParams.getInternalContentsForJNI(),
+ aci.toServiceIdFixedWidthBinary(),
+ redemptionTime,
+ authCredentialResponse.getInternalContentsForJNI());
try {
return new AuthCredential(newContents);
@@ -36,11 +43,20 @@ public AuthCredential receiveAuthCredential(Aci aci, int redemptionTime, AuthCre
/**
* Produces the AuthCredentialWithPni from a server-generated AuthCredentialWithPniResponse.
- *
- * @param redemptionTime This is provided by the server as an integer, and should be passed through directly.
+ *
+ * @param redemptionTime This is provided by the server as an integer, and should be passed
+ * through directly.
*/
- public AuthCredentialWithPni receiveAuthCredentialWithPniAsServiceId(Aci aci, Pni pni, long redemptionTime, AuthCredentialWithPniResponse authCredentialResponse) throws VerificationFailedException {
- byte[] newContents = Native.ServerPublicParams_ReceiveAuthCredentialWithPniAsServiceId(serverPublicParams.getInternalContentsForJNI(), aci.toServiceIdFixedWidthBinary(), pni.toServiceIdFixedWidthBinary(), redemptionTime, authCredentialResponse.getInternalContentsForJNI());
+ public AuthCredentialWithPni receiveAuthCredentialWithPniAsServiceId(
+ Aci aci, Pni pni, long redemptionTime, AuthCredentialWithPniResponse authCredentialResponse)
+ throws VerificationFailedException {
+ byte[] newContents =
+ Native.ServerPublicParams_ReceiveAuthCredentialWithPniAsServiceId(
+ serverPublicParams.getInternalContentsForJNI(),
+ aci.toServiceIdFixedWidthBinary(),
+ pni.toServiceIdFixedWidthBinary(),
+ redemptionTime,
+ authCredentialResponse.getInternalContentsForJNI());
try {
return new AuthCredentialWithPni(newContents);
@@ -52,13 +68,22 @@ public AuthCredentialWithPni receiveAuthCredentialWithPniAsServiceId(Aci aci, Pn
/**
* Produces the AuthCredentialWithPni from a server-generated AuthCredentialWithPniResponse.
*
- * This older style of AuthCredentialWithPni will not actually have a usable PNI field,
- * but can still be used for authenticating with an ACI.
- *
- * @param redemptionTime This is provided by the server as an integer, and should be passed through directly.
+ * This older style of AuthCredentialWithPni will not actually have a usable PNI field, but can
+ * still be used for authenticating with an ACI.
+ *
+ * @param redemptionTime This is provided by the server as an integer, and should be passed
+ * through directly.
*/
- public AuthCredentialWithPni receiveAuthCredentialWithPniAsAci(Aci aci, Pni pni, long redemptionTime, AuthCredentialWithPniResponse authCredentialResponse) throws VerificationFailedException {
- byte[] newContents = Native.ServerPublicParams_ReceiveAuthCredentialWithPniAsAci(serverPublicParams.getInternalContentsForJNI(), aci.toServiceIdFixedWidthBinary(), pni.toServiceIdFixedWidthBinary(), redemptionTime, authCredentialResponse.getInternalContentsForJNI());
+ public AuthCredentialWithPni receiveAuthCredentialWithPniAsAci(
+ Aci aci, Pni pni, long redemptionTime, AuthCredentialWithPniResponse authCredentialResponse)
+ throws VerificationFailedException {
+ byte[] newContents =
+ Native.ServerPublicParams_ReceiveAuthCredentialWithPniAsAci(
+ serverPublicParams.getInternalContentsForJNI(),
+ aci.toServiceIdFixedWidthBinary(),
+ pni.toServiceIdFixedWidthBinary(),
+ redemptionTime,
+ authCredentialResponse.getInternalContentsForJNI());
try {
return new AuthCredentialWithPni(newContents);
@@ -67,15 +92,24 @@ public AuthCredentialWithPni receiveAuthCredentialWithPniAsAci(Aci aci, Pni pni,
}
}
- public AuthCredentialPresentation createAuthCredentialPresentation(GroupSecretParams groupSecretParams, AuthCredential authCredential) {
+ public AuthCredentialPresentation createAuthCredentialPresentation(
+ GroupSecretParams groupSecretParams, AuthCredential authCredential) {
return createAuthCredentialPresentation(new SecureRandom(), groupSecretParams, authCredential);
}
- public AuthCredentialPresentation createAuthCredentialPresentation(SecureRandom secureRandom, GroupSecretParams groupSecretParams, AuthCredential authCredential) {
- byte[] random = new byte[RANDOM_LENGTH];
+ public AuthCredentialPresentation createAuthCredentialPresentation(
+ SecureRandom secureRandom,
+ GroupSecretParams groupSecretParams,
+ AuthCredential authCredential) {
+ byte[] random = new byte[RANDOM_LENGTH];
secureRandom.nextBytes(random);
- byte[] newContents = Native.ServerPublicParams_CreateAuthCredentialPresentationDeterministic(serverPublicParams.getInternalContentsForJNI(), random, groupSecretParams.getInternalContentsForJNI(), authCredential.getInternalContentsForJNI());
+ byte[] newContents =
+ Native.ServerPublicParams_CreateAuthCredentialPresentationDeterministic(
+ serverPublicParams.getInternalContentsForJNI(),
+ random,
+ groupSecretParams.getInternalContentsForJNI(),
+ authCredential.getInternalContentsForJNI());
try {
return new AuthCredentialPresentation(newContents);
@@ -84,15 +118,24 @@ public AuthCredentialPresentation createAuthCredentialPresentation(SecureRandom
}
}
- public AuthCredentialPresentation createAuthCredentialPresentation(GroupSecretParams groupSecretParams, AuthCredentialWithPni authCredential) {
+ public AuthCredentialPresentation createAuthCredentialPresentation(
+ GroupSecretParams groupSecretParams, AuthCredentialWithPni authCredential) {
return createAuthCredentialPresentation(new SecureRandom(), groupSecretParams, authCredential);
}
- public AuthCredentialPresentation createAuthCredentialPresentation(SecureRandom secureRandom, GroupSecretParams groupSecretParams, AuthCredentialWithPni authCredential) {
- byte[] random = new byte[RANDOM_LENGTH];
+ public AuthCredentialPresentation createAuthCredentialPresentation(
+ SecureRandom secureRandom,
+ GroupSecretParams groupSecretParams,
+ AuthCredentialWithPni authCredential) {
+ byte[] random = new byte[RANDOM_LENGTH];
secureRandom.nextBytes(random);
- byte[] newContents = Native.ServerPublicParams_CreateAuthCredentialWithPniPresentationDeterministic(serverPublicParams.getInternalContentsForJNI(), random, groupSecretParams.getInternalContentsForJNI(), authCredential.getInternalContentsForJNI());
+ byte[] newContents =
+ Native.ServerPublicParams_CreateAuthCredentialWithPniPresentationDeterministic(
+ serverPublicParams.getInternalContentsForJNI(),
+ random,
+ groupSecretParams.getInternalContentsForJNI(),
+ authCredential.getInternalContentsForJNI());
try {
return new AuthCredentialPresentation(newContents);
diff --git a/java/shared/java/org/signal/libsignal/zkgroup/auth/ServerZkAuthOperations.java b/java/shared/java/org/signal/libsignal/zkgroup/auth/ServerZkAuthOperations.java
index 3e834ac990..afc44845e6 100644
--- a/java/shared/java/org/signal/libsignal/zkgroup/auth/ServerZkAuthOperations.java
+++ b/java/shared/java/org/signal/libsignal/zkgroup/auth/ServerZkAuthOperations.java
@@ -5,17 +5,17 @@
package org.signal.libsignal.zkgroup.auth;
+import static org.signal.libsignal.zkgroup.internal.Constants.RANDOM_LENGTH;
+
import java.security.SecureRandom;
import java.time.Instant;
+import org.signal.libsignal.internal.Native;
import org.signal.libsignal.protocol.ServiceId.Aci;
import org.signal.libsignal.protocol.ServiceId.Pni;
import org.signal.libsignal.zkgroup.InvalidInputException;
import org.signal.libsignal.zkgroup.ServerSecretParams;
import org.signal.libsignal.zkgroup.VerificationFailedException;
import org.signal.libsignal.zkgroup.groups.GroupPublicParams;
-import org.signal.libsignal.internal.Native;
-
-import static org.signal.libsignal.zkgroup.internal.Constants.RANDOM_LENGTH;
public class ServerZkAuthOperations {
@@ -29,12 +29,18 @@ public AuthCredentialResponse issueAuthCredential(Aci aci, int redemptionTime) {
return issueAuthCredential(new SecureRandom(), aci, redemptionTime);
}
- public AuthCredentialResponse issueAuthCredential(SecureRandom secureRandom, Aci aci, int redemptionTime) {
- byte[] random = new byte[RANDOM_LENGTH];
+ public AuthCredentialResponse issueAuthCredential(
+ SecureRandom secureRandom, Aci aci, int redemptionTime) {
+ byte[] random = new byte[RANDOM_LENGTH];
secureRandom.nextBytes(random);
- byte[] newContents = Native.ServerSecretParams_IssueAuthCredentialDeterministic(serverSecretParams.getInternalContentsForJNI(), random, aci.toServiceIdFixedWidthBinary(), redemptionTime);
+ byte[] newContents =
+ Native.ServerSecretParams_IssueAuthCredentialDeterministic(
+ serverSecretParams.getInternalContentsForJNI(),
+ random,
+ aci.toServiceIdFixedWidthBinary(),
+ redemptionTime);
try {
return new AuthCredentialResponse(newContents);
@@ -43,16 +49,24 @@ public AuthCredentialResponse issueAuthCredential(SecureRandom secureRandom, Aci
}
}
- public AuthCredentialWithPniResponse issueAuthCredentialWithPniAsServiceId(Aci aci, Pni pni, Instant redemptionTime) {
+ public AuthCredentialWithPniResponse issueAuthCredentialWithPniAsServiceId(
+ Aci aci, Pni pni, Instant redemptionTime) {
return issueAuthCredentialWithPniAsServiceId(new SecureRandom(), aci, pni, redemptionTime);
}
- public AuthCredentialWithPniResponse issueAuthCredentialWithPniAsServiceId(SecureRandom secureRandom, Aci aci, Pni pni, Instant redemptionTime) {
- byte[] random = new byte[RANDOM_LENGTH];
+ public AuthCredentialWithPniResponse issueAuthCredentialWithPniAsServiceId(
+ SecureRandom secureRandom, Aci aci, Pni pni, Instant redemptionTime) {
+ byte[] random = new byte[RANDOM_LENGTH];
secureRandom.nextBytes(random);
- byte[] newContents = Native.ServerSecretParams_IssueAuthCredentialWithPniAsServiceIdDeterministic(serverSecretParams.getInternalContentsForJNI(), random, aci.toServiceIdFixedWidthBinary(), pni.toServiceIdFixedWidthBinary(), redemptionTime.getEpochSecond());
+ byte[] newContents =
+ Native.ServerSecretParams_IssueAuthCredentialWithPniAsServiceIdDeterministic(
+ serverSecretParams.getInternalContentsForJNI(),
+ random,
+ aci.toServiceIdFixedWidthBinary(),
+ pni.toServiceIdFixedWidthBinary(),
+ redemptionTime.getEpochSecond());
try {
return new AuthCredentialWithPniResponse(newContents);
@@ -61,16 +75,24 @@ public AuthCredentialWithPniResponse issueAuthCredentialWithPniAsServiceId(Secur
}
}
- public AuthCredentialWithPniResponse issueAuthCredentialWithPniAsAci(Aci aci, Pni pni, Instant redemptionTime) {
+ public AuthCredentialWithPniResponse issueAuthCredentialWithPniAsAci(
+ Aci aci, Pni pni, Instant redemptionTime) {
return issueAuthCredentialWithPniAsAci(new SecureRandom(), aci, pni, redemptionTime);
}
- public AuthCredentialWithPniResponse issueAuthCredentialWithPniAsAci(SecureRandom secureRandom, Aci aci, Pni pni, Instant redemptionTime) {
- byte[] random = new byte[RANDOM_LENGTH];
+ public AuthCredentialWithPniResponse issueAuthCredentialWithPniAsAci(
+ SecureRandom secureRandom, Aci aci, Pni pni, Instant redemptionTime) {
+ byte[] random = new byte[RANDOM_LENGTH];
secureRandom.nextBytes(random);
- byte[] newContents = Native.ServerSecretParams_IssueAuthCredentialWithPniAsAciDeterministic(serverSecretParams.getInternalContentsForJNI(), random, aci.toServiceIdFixedWidthBinary(), pni.toServiceIdFixedWidthBinary(), redemptionTime.getEpochSecond());
+ byte[] newContents =
+ Native.ServerSecretParams_IssueAuthCredentialWithPniAsAciDeterministic(
+ serverSecretParams.getInternalContentsForJNI(),
+ random,
+ aci.toServiceIdFixedWidthBinary(),
+ pni.toServiceIdFixedWidthBinary(),
+ redemptionTime.getEpochSecond());
try {
return new AuthCredentialWithPniResponse(newContents);
@@ -79,12 +101,21 @@ public AuthCredentialWithPniResponse issueAuthCredentialWithPniAsAci(SecureRando
}
}
- public void verifyAuthCredentialPresentation(GroupPublicParams groupPublicParams, AuthCredentialPresentation authCredentialPresentation) throws VerificationFailedException {
- verifyAuthCredentialPresentation(groupPublicParams, authCredentialPresentation, Instant.now());
- }
-
- public void verifyAuthCredentialPresentation(GroupPublicParams groupPublicParams, AuthCredentialPresentation authCredentialPresentation, Instant currentTime) throws VerificationFailedException {
- Native.ServerSecretParams_VerifyAuthCredentialPresentation(serverSecretParams.getInternalContentsForJNI(), groupPublicParams.getInternalContentsForJNI(), authCredentialPresentation.getInternalContentsForJNI(), currentTime.getEpochSecond());
+ public void verifyAuthCredentialPresentation(
+ GroupPublicParams groupPublicParams, AuthCredentialPresentation authCredentialPresentation)
+ throws VerificationFailedException {
+ verifyAuthCredentialPresentation(groupPublicParams, authCredentialPresentation, Instant.now());
}
+ public void verifyAuthCredentialPresentation(
+ GroupPublicParams groupPublicParams,
+ AuthCredentialPresentation authCredentialPresentation,
+ Instant currentTime)
+ throws VerificationFailedException {
+ Native.ServerSecretParams_VerifyAuthCredentialPresentation(
+ serverSecretParams.getInternalContentsForJNI(),
+ groupPublicParams.getInternalContentsForJNI(),
+ authCredentialPresentation.getInternalContentsForJNI(),
+ currentTime.getEpochSecond());
+ }
}
diff --git a/java/shared/java/org/signal/libsignal/zkgroup/calllinks/CallLinkAuthCredential.java b/java/shared/java/org/signal/libsignal/zkgroup/calllinks/CallLinkAuthCredential.java
index ffb17b5b29..65896a7001 100644
--- a/java/shared/java/org/signal/libsignal/zkgroup/calllinks/CallLinkAuthCredential.java
+++ b/java/shared/java/org/signal/libsignal/zkgroup/calllinks/CallLinkAuthCredential.java
@@ -5,16 +5,15 @@
package org.signal.libsignal.zkgroup.calllinks;
+import static org.signal.libsignal.zkgroup.internal.Constants.RANDOM_LENGTH;
+
+import java.security.SecureRandom;
+import java.time.Instant;
+import org.signal.libsignal.internal.Native;
import org.signal.libsignal.protocol.ServiceId.Aci;
import org.signal.libsignal.zkgroup.GenericServerPublicParams;
import org.signal.libsignal.zkgroup.InvalidInputException;
import org.signal.libsignal.zkgroup.internal.ByteArray;
-import org.signal.libsignal.internal.Native;
-
-import java.security.SecureRandom;
-import java.time.Instant;
-
-import static org.signal.libsignal.zkgroup.internal.Constants.RANDOM_LENGTH;
public final class CallLinkAuthCredential extends ByteArray {
@@ -23,15 +22,31 @@ public CallLinkAuthCredential(byte[] contents) throws InvalidInputException {
Native.CallLinkAuthCredential_CheckValidContents(contents);
}
- public CallLinkAuthCredentialPresentation present(Aci userId, Instant redemptionTime, GenericServerPublicParams serverParams, CallLinkSecretParams callLinkParams) {
+ public CallLinkAuthCredentialPresentation present(
+ Aci userId,
+ Instant redemptionTime,
+ GenericServerPublicParams serverParams,
+ CallLinkSecretParams callLinkParams) {
return present(userId, redemptionTime, serverParams, callLinkParams, new SecureRandom());
}
- public CallLinkAuthCredentialPresentation present(Aci userId, Instant redemptionTime, GenericServerPublicParams serverParams, CallLinkSecretParams callLinkParams, SecureRandom secureRandom) {
- byte[] random = new byte[RANDOM_LENGTH];
+ public CallLinkAuthCredentialPresentation present(
+ Aci userId,
+ Instant redemptionTime,
+ GenericServerPublicParams serverParams,
+ CallLinkSecretParams callLinkParams,
+ SecureRandom secureRandom) {
+ byte[] random = new byte[RANDOM_LENGTH];
secureRandom.nextBytes(random);
- byte[] newContents = Native.CallLinkAuthCredential_PresentDeterministic(getInternalContentsForJNI(), userId.toServiceIdFixedWidthBinary(), redemptionTime.getEpochSecond(), serverParams.getInternalContentsForJNI(), callLinkParams.getInternalContentsForJNI(), random);
+ byte[] newContents =
+ Native.CallLinkAuthCredential_PresentDeterministic(
+ getInternalContentsForJNI(),
+ userId.toServiceIdFixedWidthBinary(),
+ redemptionTime.getEpochSecond(),
+ serverParams.getInternalContentsForJNI(),
+ callLinkParams.getInternalContentsForJNI(),
+ random);
try {
return new CallLinkAuthCredentialPresentation(newContents);
@@ -39,5 +54,4 @@ public CallLinkAuthCredentialPresentation present(Aci userId, Instant redemption
throw new AssertionError(e);
}
}
-
}
diff --git a/java/shared/java/org/signal/libsignal/zkgroup/calllinks/CallLinkAuthCredentialPresentation.java b/java/shared/java/org/signal/libsignal/zkgroup/calllinks/CallLinkAuthCredentialPresentation.java
index 168a0fa3fc..dfcbb1aa47 100644
--- a/java/shared/java/org/signal/libsignal/zkgroup/calllinks/CallLinkAuthCredentialPresentation.java
+++ b/java/shared/java/org/signal/libsignal/zkgroup/calllinks/CallLinkAuthCredentialPresentation.java
@@ -5,14 +5,13 @@
package org.signal.libsignal.zkgroup.calllinks;
+import java.time.Instant;
+import org.signal.libsignal.internal.Native;
import org.signal.libsignal.zkgroup.GenericServerSecretParams;
import org.signal.libsignal.zkgroup.InvalidInputException;
import org.signal.libsignal.zkgroup.VerificationFailedException;
import org.signal.libsignal.zkgroup.groups.UuidCiphertext;
import org.signal.libsignal.zkgroup.internal.ByteArray;
-import org.signal.libsignal.internal.Native;
-
-import java.time.Instant;
public final class CallLinkAuthCredentialPresentation extends ByteArray {
@@ -21,12 +20,21 @@ public CallLinkAuthCredentialPresentation(byte[] contents) throws InvalidInputEx
Native.CallLinkAuthCredentialPresentation_CheckValidContents(contents);
}
- public void verify(GenericServerSecretParams serverParams, CallLinkPublicParams callLinkParams) throws VerificationFailedException {
+ public void verify(GenericServerSecretParams serverParams, CallLinkPublicParams callLinkParams)
+ throws VerificationFailedException {
verify(Instant.now(), serverParams, callLinkParams);
}
- public void verify(Instant currentTime, GenericServerSecretParams serverParams, CallLinkPublicParams callLinkParams) throws VerificationFailedException {
- Native.CallLinkAuthCredentialPresentation_Verify(getInternalContentsForJNI(), currentTime.getEpochSecond(), serverParams.getInternalContentsForJNI(), callLinkParams.getInternalContentsForJNI());
+ public void verify(
+ Instant currentTime,
+ GenericServerSecretParams serverParams,
+ CallLinkPublicParams callLinkParams)
+ throws VerificationFailedException {
+ Native.CallLinkAuthCredentialPresentation_Verify(
+ getInternalContentsForJNI(),
+ currentTime.getEpochSecond(),
+ serverParams.getInternalContentsForJNI(),
+ callLinkParams.getInternalContentsForJNI());
}
public UuidCiphertext getUserId() {
@@ -38,5 +46,4 @@ public UuidCiphertext getUserId() {
throw new AssertionError(e);
}
}
-
}
diff --git a/java/shared/java/org/signal/libsignal/zkgroup/calllinks/CallLinkAuthCredentialResponse.java b/java/shared/java/org/signal/libsignal/zkgroup/calllinks/CallLinkAuthCredentialResponse.java
index bc30f14898..8738ca9ed7 100644
--- a/java/shared/java/org/signal/libsignal/zkgroup/calllinks/CallLinkAuthCredentialResponse.java
+++ b/java/shared/java/org/signal/libsignal/zkgroup/calllinks/CallLinkAuthCredentialResponse.java
@@ -5,18 +5,17 @@
package org.signal.libsignal.zkgroup.calllinks;
+import static org.signal.libsignal.zkgroup.internal.Constants.RANDOM_LENGTH;
+
+import java.security.SecureRandom;
+import java.time.Instant;
+import org.signal.libsignal.internal.Native;
import org.signal.libsignal.protocol.ServiceId.Aci;
-import org.signal.libsignal.zkgroup.InvalidInputException;
-import org.signal.libsignal.zkgroup.VerificationFailedException;
import org.signal.libsignal.zkgroup.GenericServerPublicParams;
import org.signal.libsignal.zkgroup.GenericServerSecretParams;
+import org.signal.libsignal.zkgroup.InvalidInputException;
+import org.signal.libsignal.zkgroup.VerificationFailedException;
import org.signal.libsignal.zkgroup.internal.ByteArray;
-import org.signal.libsignal.internal.Native;
-
-import java.security.SecureRandom;
-import java.time.Instant;
-
-import static org.signal.libsignal.zkgroup.internal.Constants.RANDOM_LENGTH;
public final class CallLinkAuthCredentialResponse extends ByteArray {
public CallLinkAuthCredentialResponse(byte[] contents) throws InvalidInputException {
@@ -24,15 +23,25 @@ public CallLinkAuthCredentialResponse(byte[] contents) throws InvalidInputExcept
Native.CallLinkAuthCredentialResponse_CheckValidContents(contents);
}
- public static CallLinkAuthCredentialResponse issueCredential(Aci userId, Instant redemptionTime, GenericServerSecretParams params) {
+ public static CallLinkAuthCredentialResponse issueCredential(
+ Aci userId, Instant redemptionTime, GenericServerSecretParams params) {
return issueCredential(userId, redemptionTime, params, new SecureRandom());
}
- public static CallLinkAuthCredentialResponse issueCredential(Aci userId, Instant redemptionTime, GenericServerSecretParams params, SecureRandom secureRandom) {
- byte[] random = new byte[RANDOM_LENGTH];
+ public static CallLinkAuthCredentialResponse issueCredential(
+ Aci userId,
+ Instant redemptionTime,
+ GenericServerSecretParams params,
+ SecureRandom secureRandom) {
+ byte[] random = new byte[RANDOM_LENGTH];
secureRandom.nextBytes(random);
- byte[] newContents = Native.CallLinkAuthCredentialResponse_IssueDeterministic(userId.toServiceIdFixedWidthBinary(), redemptionTime.getEpochSecond(), params.getInternalContentsForJNI(), random);
+ byte[] newContents =
+ Native.CallLinkAuthCredentialResponse_IssueDeterministic(
+ userId.toServiceIdFixedWidthBinary(),
+ redemptionTime.getEpochSecond(),
+ params.getInternalContentsForJNI(),
+ random);
try {
return new CallLinkAuthCredentialResponse(newContents);
@@ -41,8 +50,15 @@ public static CallLinkAuthCredentialResponse issueCredential(Aci userId, Instant
}
}
- public CallLinkAuthCredential receive(Aci userId, Instant redemptionTime, GenericServerPublicParams params) throws VerificationFailedException {
- byte[] newContents = Native.CallLinkAuthCredentialResponse_Receive(getInternalContentsForJNI(), userId.toServiceIdFixedWidthBinary(), redemptionTime.getEpochSecond(), params.getInternalContentsForJNI());
+ public CallLinkAuthCredential receive(
+ Aci userId, Instant redemptionTime, GenericServerPublicParams params)
+ throws VerificationFailedException {
+ byte[] newContents =
+ Native.CallLinkAuthCredentialResponse_Receive(
+ getInternalContentsForJNI(),
+ userId.toServiceIdFixedWidthBinary(),
+ redemptionTime.getEpochSecond(),
+ params.getInternalContentsForJNI());
try {
return new CallLinkAuthCredential(newContents);
diff --git a/java/shared/java/org/signal/libsignal/zkgroup/calllinks/CallLinkPublicParams.java b/java/shared/java/org/signal/libsignal/zkgroup/calllinks/CallLinkPublicParams.java
index 25934eab8f..0511356616 100644
--- a/java/shared/java/org/signal/libsignal/zkgroup/calllinks/CallLinkPublicParams.java
+++ b/java/shared/java/org/signal/libsignal/zkgroup/calllinks/CallLinkPublicParams.java
@@ -5,9 +5,9 @@
package org.signal.libsignal.zkgroup.calllinks;
+import org.signal.libsignal.internal.Native;
import org.signal.libsignal.zkgroup.InvalidInputException;
import org.signal.libsignal.zkgroup.internal.ByteArray;
-import org.signal.libsignal.internal.Native;
public final class CallLinkPublicParams extends ByteArray {
public CallLinkPublicParams(byte[] contents) throws InvalidInputException {
diff --git a/java/shared/java/org/signal/libsignal/zkgroup/calllinks/CallLinkSecretParams.java b/java/shared/java/org/signal/libsignal/zkgroup/calllinks/CallLinkSecretParams.java
index 9732949f6a..41b268a189 100644
--- a/java/shared/java/org/signal/libsignal/zkgroup/calllinks/CallLinkSecretParams.java
+++ b/java/shared/java/org/signal/libsignal/zkgroup/calllinks/CallLinkSecretParams.java
@@ -5,13 +5,13 @@
package org.signal.libsignal.zkgroup.calllinks;
+import org.signal.libsignal.internal.Native;
import org.signal.libsignal.protocol.ServiceId;
import org.signal.libsignal.protocol.ServiceId.Aci;
import org.signal.libsignal.zkgroup.InvalidInputException;
import org.signal.libsignal.zkgroup.VerificationFailedException;
import org.signal.libsignal.zkgroup.groups.UuidCiphertext;
import org.signal.libsignal.zkgroup.internal.ByteArray;
-import org.signal.libsignal.internal.Native;
public final class CallLinkSecretParams extends ByteArray {
@@ -22,10 +22,10 @@ public static CallLinkSecretParams deriveFromRootKey(byte[] rootKey) {
return new CallLinkSecretParams(newContents);
} catch (InvalidInputException e) {
throw new AssertionError(e);
- }
+ }
}
- public CallLinkSecretParams(byte[] contents) throws InvalidInputException {
+ public CallLinkSecretParams(byte[] contents) throws InvalidInputException {
super(contents);
Native.CallLinkSecretParams_CheckValidContents(contents);
}
@@ -42,10 +42,11 @@ public CallLinkPublicParams getPublicParams() {
public Aci decryptUserId(UuidCiphertext ciphertext) throws VerificationFailedException {
try {
- return Aci.parseFromFixedWidthBinary(Native.CallLinkSecretParams_DecryptUserId(getInternalContentsForJNI(), ciphertext.getInternalContentsForJNI()));
+ return Aci.parseFromFixedWidthBinary(
+ Native.CallLinkSecretParams_DecryptUserId(
+ getInternalContentsForJNI(), ciphertext.getInternalContentsForJNI()));
} catch (ServiceId.InvalidServiceIdException e) {
throw new VerificationFailedException();
}
}
-
}
diff --git a/java/shared/java/org/signal/libsignal/zkgroup/calllinks/CreateCallLinkCredential.java b/java/shared/java/org/signal/libsignal/zkgroup/calllinks/CreateCallLinkCredential.java
index 562a10b802..3eaebef054 100644
--- a/java/shared/java/org/signal/libsignal/zkgroup/calllinks/CreateCallLinkCredential.java
+++ b/java/shared/java/org/signal/libsignal/zkgroup/calllinks/CreateCallLinkCredential.java
@@ -5,16 +5,14 @@
package org.signal.libsignal.zkgroup.calllinks;
+import static org.signal.libsignal.zkgroup.internal.Constants.RANDOM_LENGTH;
+
+import java.security.SecureRandom;
+import org.signal.libsignal.internal.Native;
import org.signal.libsignal.protocol.ServiceId.Aci;
import org.signal.libsignal.zkgroup.GenericServerPublicParams;
import org.signal.libsignal.zkgroup.InvalidInputException;
import org.signal.libsignal.zkgroup.internal.ByteArray;
-import org.signal.libsignal.internal.Native;
-
-import java.security.SecureRandom;
-import java.time.Instant;
-
-import static org.signal.libsignal.zkgroup.internal.Constants.RANDOM_LENGTH;
public final class CreateCallLinkCredential extends ByteArray {
@@ -23,15 +21,31 @@ public CreateCallLinkCredential(byte[] contents) throws InvalidInputException {
Native.CreateCallLinkCredential_CheckValidContents(contents);
}
- public CreateCallLinkCredentialPresentation present(byte[] roomId, Aci userId, GenericServerPublicParams serverParams, CallLinkSecretParams callLinkParams) {
+ public CreateCallLinkCredentialPresentation present(
+ byte[] roomId,
+ Aci userId,
+ GenericServerPublicParams serverParams,
+ CallLinkSecretParams callLinkParams) {
return present(roomId, userId, serverParams, callLinkParams, new SecureRandom());
}
- public CreateCallLinkCredentialPresentation present(byte[] roomId, Aci userId, GenericServerPublicParams serverParams, CallLinkSecretParams callLinkParams, SecureRandom secureRandom) {
- byte[] random = new byte[RANDOM_LENGTH];
+ public CreateCallLinkCredentialPresentation present(
+ byte[] roomId,
+ Aci userId,
+ GenericServerPublicParams serverParams,
+ CallLinkSecretParams callLinkParams,
+ SecureRandom secureRandom) {
+ byte[] random = new byte[RANDOM_LENGTH];
secureRandom.nextBytes(random);
- byte[] newContents = Native.CreateCallLinkCredential_PresentDeterministic(getInternalContentsForJNI(), roomId, userId.toServiceIdFixedWidthBinary(), serverParams.getInternalContentsForJNI(), callLinkParams.getInternalContentsForJNI(), random);
+ byte[] newContents =
+ Native.CreateCallLinkCredential_PresentDeterministic(
+ getInternalContentsForJNI(),
+ roomId,
+ userId.toServiceIdFixedWidthBinary(),
+ serverParams.getInternalContentsForJNI(),
+ callLinkParams.getInternalContentsForJNI(),
+ random);
try {
return new CreateCallLinkCredentialPresentation(newContents);
@@ -39,5 +53,4 @@ public CreateCallLinkCredentialPresentation present(byte[] roomId, Aci userId, G
throw new AssertionError(e);
}
}
-
}
diff --git a/java/shared/java/org/signal/libsignal/zkgroup/calllinks/CreateCallLinkCredentialPresentation.java b/java/shared/java/org/signal/libsignal/zkgroup/calllinks/CreateCallLinkCredentialPresentation.java
index 0f0e3dd1ae..a56ce27c1d 100644
--- a/java/shared/java/org/signal/libsignal/zkgroup/calllinks/CreateCallLinkCredentialPresentation.java
+++ b/java/shared/java/org/signal/libsignal/zkgroup/calllinks/CreateCallLinkCredentialPresentation.java
@@ -5,13 +5,12 @@
package org.signal.libsignal.zkgroup.calllinks;
+import java.time.Instant;
+import org.signal.libsignal.internal.Native;
import org.signal.libsignal.zkgroup.GenericServerSecretParams;
import org.signal.libsignal.zkgroup.InvalidInputException;
import org.signal.libsignal.zkgroup.VerificationFailedException;
import org.signal.libsignal.zkgroup.internal.ByteArray;
-import org.signal.libsignal.internal.Native;
-
-import java.time.Instant;
public final class CreateCallLinkCredentialPresentation extends ByteArray {
@@ -20,12 +19,23 @@ public CreateCallLinkCredentialPresentation(byte[] contents) throws InvalidInput
Native.CreateCallLinkCredentialPresentation_CheckValidContents(contents);
}
- public void verify(byte[] roomId, GenericServerSecretParams serverParams, CallLinkPublicParams callLinkParams) throws VerificationFailedException {
+ public void verify(
+ byte[] roomId, GenericServerSecretParams serverParams, CallLinkPublicParams callLinkParams)
+ throws VerificationFailedException {
verify(roomId, Instant.now(), serverParams, callLinkParams);
}
- public void verify(byte[] roomId, Instant currentTime, GenericServerSecretParams serverParams, CallLinkPublicParams callLinkParams) throws VerificationFailedException {
- Native.CreateCallLinkCredentialPresentation_Verify(getInternalContentsForJNI(), roomId, currentTime.getEpochSecond(), serverParams.getInternalContentsForJNI(), callLinkParams.getInternalContentsForJNI());
+ public void verify(
+ byte[] roomId,
+ Instant currentTime,
+ GenericServerSecretParams serverParams,
+ CallLinkPublicParams callLinkParams)
+ throws VerificationFailedException {
+ Native.CreateCallLinkCredentialPresentation_Verify(
+ getInternalContentsForJNI(),
+ roomId,
+ currentTime.getEpochSecond(),
+ serverParams.getInternalContentsForJNI(),
+ callLinkParams.getInternalContentsForJNI());
}
-
}
diff --git a/java/shared/java/org/signal/libsignal/zkgroup/calllinks/CreateCallLinkCredentialRequest.java b/java/shared/java/org/signal/libsignal/zkgroup/calllinks/CreateCallLinkCredentialRequest.java
index ec4b13e557..d4628321b5 100644
--- a/java/shared/java/org/signal/libsignal/zkgroup/calllinks/CreateCallLinkCredentialRequest.java
+++ b/java/shared/java/org/signal/libsignal/zkgroup/calllinks/CreateCallLinkCredentialRequest.java
@@ -5,16 +5,15 @@
package org.signal.libsignal.zkgroup.calllinks;
+import static org.signal.libsignal.zkgroup.internal.Constants.RANDOM_LENGTH;
+
+import java.security.SecureRandom;
+import java.time.Instant;
+import org.signal.libsignal.internal.Native;
import org.signal.libsignal.protocol.ServiceId.Aci;
import org.signal.libsignal.zkgroup.GenericServerSecretParams;
import org.signal.libsignal.zkgroup.InvalidInputException;
import org.signal.libsignal.zkgroup.internal.ByteArray;
-import org.signal.libsignal.internal.Native;
-
-import java.security.SecureRandom;
-import java.time.Instant;
-
-import static org.signal.libsignal.zkgroup.internal.Constants.RANDOM_LENGTH;
public final class CreateCallLinkCredentialRequest extends ByteArray {
@@ -28,31 +27,38 @@ public CreateCallLinkCredentialRequest(byte[] contents) throws InvalidInputExcep
*
* @param userId The ACI of the user who will be creating the call link.
* @param timestamp Must be a round number of days. Use {@link java.time.Instant#truncatedTo} to
- * ensure this.
+ * ensure this.
* @param params The params that will be used by the calling server to verify this credential.
*/
- public CreateCallLinkCredentialResponse issueCredential(Aci userId, Instant timestamp, GenericServerSecretParams params) {
+ public CreateCallLinkCredentialResponse issueCredential(
+ Aci userId, Instant timestamp, GenericServerSecretParams params) {
return issueCredential(userId, timestamp, params, new SecureRandom());
}
/**
* Issues a CreateCallLinkCredential, using a dedicated source of randomness.
*
- * This can be used to make tests deterministic. Prefer
- * {@link #issueCredential(Aci, Instant, GenericServerSecretParams)} if the source of randomness
- * doesn't matter.
+ *
This can be used to make tests deterministic. Prefer {@link #issueCredential(Aci, Instant,
+ * GenericServerSecretParams)} if the source of randomness doesn't matter.
*
* @param userId The ACI of the user who will be creating the call link.
* @param timestamp Must be a round number of days. Use {@link java.time.Instant#truncatedTo} to
- * ensure this.
+ * ensure this.
* @param params The params that will be used by the calling server to verify this credential.
* @param secureRandom Used to hide the server's secrets and make the issued credential unique.
*/
- public CreateCallLinkCredentialResponse issueCredential(Aci userId, Instant timestamp, GenericServerSecretParams params, SecureRandom secureRandom) {
- byte[] random = new byte[RANDOM_LENGTH];
+ public CreateCallLinkCredentialResponse issueCredential(
+ Aci userId, Instant timestamp, GenericServerSecretParams params, SecureRandom secureRandom) {
+ byte[] random = new byte[RANDOM_LENGTH];
secureRandom.nextBytes(random);
- byte[] newContents = Native.CreateCallLinkCredentialRequest_IssueDeterministic(getInternalContentsForJNI(), userId.toServiceIdFixedWidthBinary(), timestamp.getEpochSecond(), params.getInternalContentsForJNI(), random);
+ byte[] newContents =
+ Native.CreateCallLinkCredentialRequest_IssueDeterministic(
+ getInternalContentsForJNI(),
+ userId.toServiceIdFixedWidthBinary(),
+ timestamp.getEpochSecond(),
+ params.getInternalContentsForJNI(),
+ random);
try {
return new CreateCallLinkCredentialResponse(newContents);
@@ -60,5 +66,4 @@ public CreateCallLinkCredentialResponse issueCredential(Aci userId, Instant time
throw new AssertionError(e);
}
}
-
}
diff --git a/java/shared/java/org/signal/libsignal/zkgroup/calllinks/CreateCallLinkCredentialRequestContext.java b/java/shared/java/org/signal/libsignal/zkgroup/calllinks/CreateCallLinkCredentialRequestContext.java
index fa353b8ef6..3d95a15c9b 100644
--- a/java/shared/java/org/signal/libsignal/zkgroup/calllinks/CreateCallLinkCredentialRequestContext.java
+++ b/java/shared/java/org/signal/libsignal/zkgroup/calllinks/CreateCallLinkCredentialRequestContext.java
@@ -5,16 +5,15 @@
package org.signal.libsignal.zkgroup.calllinks;
+import static org.signal.libsignal.zkgroup.internal.Constants.RANDOM_LENGTH;
+
+import java.security.SecureRandom;
+import org.signal.libsignal.internal.Native;
import org.signal.libsignal.protocol.ServiceId.Aci;
import org.signal.libsignal.zkgroup.GenericServerPublicParams;
import org.signal.libsignal.zkgroup.InvalidInputException;
import org.signal.libsignal.zkgroup.VerificationFailedException;
import org.signal.libsignal.zkgroup.internal.ByteArray;
-import org.signal.libsignal.internal.Native;
-
-import java.security.SecureRandom;
-
-import static org.signal.libsignal.zkgroup.internal.Constants.RANDOM_LENGTH;
public final class CreateCallLinkCredentialRequestContext extends ByteArray {
@@ -27,17 +26,19 @@ public static CreateCallLinkCredentialRequestContext forRoom(byte[] roomId) {
return forRoom(roomId, new SecureRandom());
}
- public static CreateCallLinkCredentialRequestContext forRoom(byte[] roomId, SecureRandom secureRandom) {
+ public static CreateCallLinkCredentialRequestContext forRoom(
+ byte[] roomId, SecureRandom secureRandom) {
byte[] random = new byte[RANDOM_LENGTH];
secureRandom.nextBytes(random);
- byte[] newContents = Native.CreateCallLinkCredentialRequestContext_NewDeterministic(roomId, random);
+ byte[] newContents =
+ Native.CreateCallLinkCredentialRequestContext_NewDeterministic(roomId, random);
try {
return new CreateCallLinkCredentialRequestContext(newContents);
} catch (InvalidInputException e) {
throw new AssertionError(e);
- }
+ }
}
public CreateCallLinkCredentialRequest getRequest() {
@@ -50,8 +51,15 @@ public CreateCallLinkCredentialRequest getRequest() {
}
}
- public CreateCallLinkCredential receiveResponse(CreateCallLinkCredentialResponse response, Aci userId, GenericServerPublicParams params) throws VerificationFailedException {
- byte[] newContents = Native.CreateCallLinkCredentialRequestContext_ReceiveResponse(getInternalContentsForJNI(), response.getInternalContentsForJNI(), userId.toServiceIdFixedWidthBinary(), params.getInternalContentsForJNI());
+ public CreateCallLinkCredential receiveResponse(
+ CreateCallLinkCredentialResponse response, Aci userId, GenericServerPublicParams params)
+ throws VerificationFailedException {
+ byte[] newContents =
+ Native.CreateCallLinkCredentialRequestContext_ReceiveResponse(
+ getInternalContentsForJNI(),
+ response.getInternalContentsForJNI(),
+ userId.toServiceIdFixedWidthBinary(),
+ params.getInternalContentsForJNI());
try {
return new CreateCallLinkCredential(newContents);
@@ -59,5 +67,4 @@ public CreateCallLinkCredential receiveResponse(CreateCallLinkCredentialResponse
throw new AssertionError(e);
}
}
-
}
diff --git a/java/shared/java/org/signal/libsignal/zkgroup/calllinks/CreateCallLinkCredentialResponse.java b/java/shared/java/org/signal/libsignal/zkgroup/calllinks/CreateCallLinkCredentialResponse.java
index 1415f76a3e..f04ae091fa 100644
--- a/java/shared/java/org/signal/libsignal/zkgroup/calllinks/CreateCallLinkCredentialResponse.java
+++ b/java/shared/java/org/signal/libsignal/zkgroup/calllinks/CreateCallLinkCredentialResponse.java
@@ -5,9 +5,9 @@
package org.signal.libsignal.zkgroup.calllinks;
+import org.signal.libsignal.internal.Native;
import org.signal.libsignal.zkgroup.InvalidInputException;
import org.signal.libsignal.zkgroup.internal.ByteArray;
-import org.signal.libsignal.internal.Native;
public final class CreateCallLinkCredentialResponse extends ByteArray {
public CreateCallLinkCredentialResponse(byte[] contents) throws InvalidInputException {
diff --git a/java/shared/java/org/signal/libsignal/zkgroup/groups/ClientZkGroupCipher.java b/java/shared/java/org/signal/libsignal/zkgroup/groups/ClientZkGroupCipher.java
index c85b49b7f2..08e675b02a 100644
--- a/java/shared/java/org/signal/libsignal/zkgroup/groups/ClientZkGroupCipher.java
+++ b/java/shared/java/org/signal/libsignal/zkgroup/groups/ClientZkGroupCipher.java
@@ -5,17 +5,15 @@
package org.signal.libsignal.zkgroup.groups;
-import java.nio.ByteBuffer;
+import static org.signal.libsignal.zkgroup.internal.Constants.RANDOM_LENGTH;
+
import java.security.SecureRandom;
-import java.util.UUID;
+import org.signal.libsignal.internal.Native;
import org.signal.libsignal.protocol.ServiceId;
import org.signal.libsignal.zkgroup.InvalidInputException;
import org.signal.libsignal.zkgroup.VerificationFailedException;
-import org.signal.libsignal.internal.Native;
import org.signal.libsignal.zkgroup.profiles.ProfileKey;
-import static org.signal.libsignal.zkgroup.internal.Constants.RANDOM_LENGTH;
-
public class ClientZkGroupCipher {
private final GroupSecretParams groupSecretParams;
@@ -25,7 +23,9 @@ public ClientZkGroupCipher(GroupSecretParams groupSecretParams) {
}
public UuidCiphertext encrypt(ServiceId serviceId) {
- byte[] newContents = Native.GroupSecretParams_EncryptServiceId(groupSecretParams.getInternalContentsForJNI(), serviceId.toServiceIdFixedWidthBinary());
+ byte[] newContents =
+ Native.GroupSecretParams_EncryptServiceId(
+ groupSecretParams.getInternalContentsForJNI(), serviceId.toServiceIdFixedWidthBinary());
try {
return new UuidCiphertext(newContents);
@@ -36,14 +36,21 @@ public UuidCiphertext encrypt(ServiceId serviceId) {
public ServiceId decrypt(UuidCiphertext uuidCiphertext) throws VerificationFailedException {
try {
- return ServiceId.parseFromFixedWidthBinary(Native.GroupSecretParams_DecryptServiceId(groupSecretParams.getInternalContentsForJNI(), uuidCiphertext.getInternalContentsForJNI()));
+ return ServiceId.parseFromFixedWidthBinary(
+ Native.GroupSecretParams_DecryptServiceId(
+ groupSecretParams.getInternalContentsForJNI(),
+ uuidCiphertext.getInternalContentsForJNI()));
} catch (ServiceId.InvalidServiceIdException e) {
throw new VerificationFailedException();
}
}
public ProfileKeyCiphertext encryptProfileKey(ProfileKey profileKey, ServiceId.Aci userId) {
- byte[] newContents = Native.GroupSecretParams_EncryptProfileKey(groupSecretParams.getInternalContentsForJNI(), profileKey.getInternalContentsForJNI(), userId.toServiceIdFixedWidthBinary());
+ byte[] newContents =
+ Native.GroupSecretParams_EncryptProfileKey(
+ groupSecretParams.getInternalContentsForJNI(),
+ profileKey.getInternalContentsForJNI(),
+ userId.toServiceIdFixedWidthBinary());
try {
return new ProfileKeyCiphertext(newContents);
@@ -52,8 +59,14 @@ public ProfileKeyCiphertext encryptProfileKey(ProfileKey profileKey, ServiceId.A
}
}
- public ProfileKey decryptProfileKey(ProfileKeyCiphertext profileKeyCiphertext, ServiceId.Aci userId) throws VerificationFailedException {
- byte[] newContents = Native.GroupSecretParams_DecryptProfileKey(groupSecretParams.getInternalContentsForJNI(), profileKeyCiphertext.getInternalContentsForJNI(), userId.toServiceIdFixedWidthBinary());
+ public ProfileKey decryptProfileKey(
+ ProfileKeyCiphertext profileKeyCiphertext, ServiceId.Aci userId)
+ throws VerificationFailedException {
+ byte[] newContents =
+ Native.GroupSecretParams_DecryptProfileKey(
+ groupSecretParams.getInternalContentsForJNI(),
+ profileKeyCiphertext.getInternalContentsForJNI(),
+ userId.toServiceIdFixedWidthBinary());
try {
return new ProfileKey(newContents);
@@ -66,14 +79,16 @@ public byte[] encryptBlob(byte[] plaintext) throws VerificationFailedException {
return encryptBlob(new SecureRandom(), plaintext);
}
- public byte[] encryptBlob(SecureRandom secureRandom, byte[] plaintext) throws VerificationFailedException {
- byte[] random = new byte[RANDOM_LENGTH];
+ public byte[] encryptBlob(SecureRandom secureRandom, byte[] plaintext)
+ throws VerificationFailedException {
+ byte[] random = new byte[RANDOM_LENGTH];
secureRandom.nextBytes(random);
- return Native.GroupSecretParams_EncryptBlobWithPaddingDeterministic(groupSecretParams.getInternalContentsForJNI(), random, plaintext, 0);
+ return Native.GroupSecretParams_EncryptBlobWithPaddingDeterministic(
+ groupSecretParams.getInternalContentsForJNI(), random, plaintext, 0);
}
public byte[] decryptBlob(byte[] blobCiphertext) throws VerificationFailedException {
- return Native.GroupSecretParams_DecryptBlobWithPadding(groupSecretParams.getInternalContentsForJNI(), blobCiphertext);
+ return Native.GroupSecretParams_DecryptBlobWithPadding(
+ groupSecretParams.getInternalContentsForJNI(), blobCiphertext);
}
-
}
diff --git a/java/shared/java/org/signal/libsignal/zkgroup/groups/GroupIdentifier.java b/java/shared/java/org/signal/libsignal/zkgroup/groups/GroupIdentifier.java
index e080a6606f..19b1448f11 100644
--- a/java/shared/java/org/signal/libsignal/zkgroup/groups/GroupIdentifier.java
+++ b/java/shared/java/org/signal/libsignal/zkgroup/groups/GroupIdentifier.java
@@ -15,5 +15,4 @@ public final class GroupIdentifier extends ByteArray {
public GroupIdentifier(byte[] contents) throws InvalidInputException {
super(contents, SIZE);
}
-
}
diff --git a/java/shared/java/org/signal/libsignal/zkgroup/groups/GroupMasterKey.java b/java/shared/java/org/signal/libsignal/zkgroup/groups/GroupMasterKey.java
index 2bf3a9502e..73ac754541 100644
--- a/java/shared/java/org/signal/libsignal/zkgroup/groups/GroupMasterKey.java
+++ b/java/shared/java/org/signal/libsignal/zkgroup/groups/GroupMasterKey.java
@@ -15,5 +15,4 @@ public final class GroupMasterKey extends ByteArray {
public GroupMasterKey(byte[] contents) throws InvalidInputException {
super(contents, SIZE);
}
-
}
diff --git a/java/shared/java/org/signal/libsignal/zkgroup/groups/GroupPublicParams.java b/java/shared/java/org/signal/libsignal/zkgroup/groups/GroupPublicParams.java
index 5edd948c90..2c40431dc4 100644
--- a/java/shared/java/org/signal/libsignal/zkgroup/groups/GroupPublicParams.java
+++ b/java/shared/java/org/signal/libsignal/zkgroup/groups/GroupPublicParams.java
@@ -5,9 +5,9 @@
package org.signal.libsignal.zkgroup.groups;
+import org.signal.libsignal.internal.Native;
import org.signal.libsignal.zkgroup.InvalidInputException;
import org.signal.libsignal.zkgroup.internal.ByteArray;
-import org.signal.libsignal.internal.Native;
public final class GroupPublicParams extends ByteArray {
@@ -25,5 +25,4 @@ public GroupIdentifier getGroupIdentifier() {
throw new AssertionError(e);
}
}
-
}
diff --git a/java/shared/java/org/signal/libsignal/zkgroup/groups/GroupSecretParams.java b/java/shared/java/org/signal/libsignal/zkgroup/groups/GroupSecretParams.java
index 1c241ef873..2bb1f3aff1 100644
--- a/java/shared/java/org/signal/libsignal/zkgroup/groups/GroupSecretParams.java
+++ b/java/shared/java/org/signal/libsignal/zkgroup/groups/GroupSecretParams.java
@@ -5,12 +5,12 @@
package org.signal.libsignal.zkgroup.groups;
+import static org.signal.libsignal.zkgroup.internal.Constants.RANDOM_LENGTH;
+
import java.security.SecureRandom;
+import org.signal.libsignal.internal.Native;
import org.signal.libsignal.zkgroup.InvalidInputException;
import org.signal.libsignal.zkgroup.internal.ByteArray;
-import org.signal.libsignal.internal.Native;
-
-import static org.signal.libsignal.zkgroup.internal.Constants.RANDOM_LENGTH;
public final class GroupSecretParams extends ByteArray {
@@ -19,7 +19,7 @@ public static GroupSecretParams generate() {
}
public static GroupSecretParams generate(SecureRandom secureRandom) {
- byte[] random = new byte[RANDOM_LENGTH];
+ byte[] random = new byte[RANDOM_LENGTH];
secureRandom.nextBytes(random);
byte[] newContents = Native.GroupSecretParams_GenerateDeterministic(random);
@@ -28,20 +28,21 @@ public static GroupSecretParams generate(SecureRandom secureRandom) {
return new GroupSecretParams(newContents);
} catch (InvalidInputException e) {
throw new AssertionError(e);
- }
+ }
}
public static GroupSecretParams deriveFromMasterKey(GroupMasterKey groupMasterKey) {
- byte[] newContents = Native.GroupSecretParams_DeriveFromMasterKey(groupMasterKey.getInternalContentsForJNI());
+ byte[] newContents =
+ Native.GroupSecretParams_DeriveFromMasterKey(groupMasterKey.getInternalContentsForJNI());
try {
return new GroupSecretParams(newContents);
} catch (InvalidInputException e) {
throw new AssertionError(e);
- }
+ }
}
- public GroupSecretParams(byte[] contents) throws InvalidInputException {
+ public GroupSecretParams(byte[] contents) throws InvalidInputException {
super(contents);
Native.GroupSecretParams_CheckValidContents(contents);
}
@@ -65,5 +66,4 @@ public GroupPublicParams getPublicParams() {
throw new AssertionError(e);
}
}
-
}
diff --git a/java/shared/java/org/signal/libsignal/zkgroup/groups/ProfileKeyCiphertext.java b/java/shared/java/org/signal/libsignal/zkgroup/groups/ProfileKeyCiphertext.java
index 74c8d372c0..877f0dc606 100644
--- a/java/shared/java/org/signal/libsignal/zkgroup/groups/ProfileKeyCiphertext.java
+++ b/java/shared/java/org/signal/libsignal/zkgroup/groups/ProfileKeyCiphertext.java
@@ -5,13 +5,13 @@
package org.signal.libsignal.zkgroup.groups;
+import org.signal.libsignal.internal.Native;
import org.signal.libsignal.zkgroup.InvalidInputException;
import org.signal.libsignal.zkgroup.internal.ByteArray;
-import org.signal.libsignal.internal.Native;
public final class ProfileKeyCiphertext extends ByteArray {
public ProfileKeyCiphertext(byte[] contents) throws InvalidInputException {
super(contents);
- Native.ProfileKeyCiphertext_CheckValidContents(contents);
+ Native.ProfileKeyCiphertext_CheckValidContents(contents);
}
}
diff --git a/java/shared/java/org/signal/libsignal/zkgroup/groups/UuidCiphertext.java b/java/shared/java/org/signal/libsignal/zkgroup/groups/UuidCiphertext.java
index 64edf60c69..5aa2dfec2f 100644
--- a/java/shared/java/org/signal/libsignal/zkgroup/groups/UuidCiphertext.java
+++ b/java/shared/java/org/signal/libsignal/zkgroup/groups/UuidCiphertext.java
@@ -5,9 +5,9 @@
package org.signal.libsignal.zkgroup.groups;
+import org.signal.libsignal.internal.Native;
import org.signal.libsignal.zkgroup.InvalidInputException;
import org.signal.libsignal.zkgroup.internal.ByteArray;
-import org.signal.libsignal.internal.Native;
public final class UuidCiphertext extends ByteArray {
public UuidCiphertext(byte[] contents) throws InvalidInputException {
diff --git a/java/shared/java/org/signal/libsignal/zkgroup/internal/ByteArray.java b/java/shared/java/org/signal/libsignal/zkgroup/internal/ByteArray.java
index e12f89fde3..900761b1b0 100644
--- a/java/shared/java/org/signal/libsignal/zkgroup/internal/ByteArray.java
+++ b/java/shared/java/org/signal/libsignal/zkgroup/internal/ByteArray.java
@@ -5,10 +5,9 @@
package org.signal.libsignal.zkgroup.internal;
-import org.signal.libsignal.zkgroup.InvalidInputException;
-
import java.util.Arrays;
import java.util.Locale;
+import org.signal.libsignal.zkgroup.InvalidInputException;
public abstract class ByteArray {
@@ -22,9 +21,15 @@ protected ByteArray(byte[] contents, int expectedLength) throws InvalidInputExce
this.contents = cloneArrayOfLength(contents, expectedLength);
}
- private static byte[] cloneArrayOfLength(byte[] bytes, int expectedLength) throws InvalidInputException {
+ private static byte[] cloneArrayOfLength(byte[] bytes, int expectedLength)
+ throws InvalidInputException {
if (bytes.length != expectedLength) {
- throw new InvalidInputException(String.format(Locale.US, "Length of array supplied was %d expected %d", bytes.length, expectedLength));
+ throw new InvalidInputException(
+ String.format(
+ Locale.US,
+ "Length of array supplied was %d expected %d",
+ bytes.length,
+ expectedLength));
}
return bytes.clone();
diff --git a/java/shared/java/org/signal/libsignal/zkgroup/internal/Constants.java b/java/shared/java/org/signal/libsignal/zkgroup/internal/Constants.java
index 5130d91606..effd7f75c2 100644
--- a/java/shared/java/org/signal/libsignal/zkgroup/internal/Constants.java
+++ b/java/shared/java/org/signal/libsignal/zkgroup/internal/Constants.java
@@ -6,5 +6,5 @@
package org.signal.libsignal.zkgroup.internal;
public class Constants {
- public static final int RANDOM_LENGTH = 32;
+ public static final int RANDOM_LENGTH = 32;
}
diff --git a/java/shared/java/org/signal/libsignal/zkgroup/profiles/ClientZkProfileOperations.java b/java/shared/java/org/signal/libsignal/zkgroup/profiles/ClientZkProfileOperations.java
index d9ea7ac6b4..aca43a80e2 100644
--- a/java/shared/java/org/signal/libsignal/zkgroup/profiles/ClientZkProfileOperations.java
+++ b/java/shared/java/org/signal/libsignal/zkgroup/profiles/ClientZkProfileOperations.java
@@ -5,16 +5,16 @@
package org.signal.libsignal.zkgroup.profiles;
+import static org.signal.libsignal.zkgroup.internal.Constants.RANDOM_LENGTH;
+
import java.security.SecureRandom;
import java.time.Instant;
+import org.signal.libsignal.internal.Native;
import org.signal.libsignal.protocol.ServiceId.Aci;
import org.signal.libsignal.zkgroup.InvalidInputException;
import org.signal.libsignal.zkgroup.ServerPublicParams;
import org.signal.libsignal.zkgroup.VerificationFailedException;
import org.signal.libsignal.zkgroup.groups.GroupSecretParams;
-import org.signal.libsignal.internal.Native;
-
-import static org.signal.libsignal.zkgroup.internal.Constants.RANDOM_LENGTH;
public class ClientZkProfileOperations {
@@ -24,15 +24,22 @@ public ClientZkProfileOperations(ServerPublicParams serverPublicParams) {
this.serverPublicParams = serverPublicParams;
}
- public ProfileKeyCredentialRequestContext createProfileKeyCredentialRequestContext(Aci userId, ProfileKey profileKey) {
+ public ProfileKeyCredentialRequestContext createProfileKeyCredentialRequestContext(
+ Aci userId, ProfileKey profileKey) {
return createProfileKeyCredentialRequestContext(new SecureRandom(), userId, profileKey);
}
- public ProfileKeyCredentialRequestContext createProfileKeyCredentialRequestContext(SecureRandom secureRandom, Aci userId, ProfileKey profileKey) {
- byte[] random = new byte[RANDOM_LENGTH];
+ public ProfileKeyCredentialRequestContext createProfileKeyCredentialRequestContext(
+ SecureRandom secureRandom, Aci userId, ProfileKey profileKey) {
+ byte[] random = new byte[RANDOM_LENGTH];
secureRandom.nextBytes(random);
- byte[] newContents = Native.ServerPublicParams_CreateProfileKeyCredentialRequestContextDeterministic(serverPublicParams.getInternalContentsForJNI(), random, userId.toServiceIdFixedWidthBinary(), profileKey.getInternalContentsForJNI());
+ byte[] newContents =
+ Native.ServerPublicParams_CreateProfileKeyCredentialRequestContextDeterministic(
+ serverPublicParams.getInternalContentsForJNI(),
+ random,
+ userId.toServiceIdFixedWidthBinary(),
+ profileKey.getInternalContentsForJNI());
try {
return new ProfileKeyCredentialRequestContext(newContents);
@@ -41,16 +48,29 @@ public ProfileKeyCredentialRequestContext createProfileKeyCredentialRequestConte
}
}
- public ExpiringProfileKeyCredential receiveExpiringProfileKeyCredential(ProfileKeyCredentialRequestContext profileKeyCredentialRequestContext, ExpiringProfileKeyCredentialResponse profileKeyCredentialResponse) throws VerificationFailedException {
- return receiveExpiringProfileKeyCredential(profileKeyCredentialRequestContext, profileKeyCredentialResponse, Instant.now());
+ public ExpiringProfileKeyCredential receiveExpiringProfileKeyCredential(
+ ProfileKeyCredentialRequestContext profileKeyCredentialRequestContext,
+ ExpiringProfileKeyCredentialResponse profileKeyCredentialResponse)
+ throws VerificationFailedException {
+ return receiveExpiringProfileKeyCredential(
+ profileKeyCredentialRequestContext, profileKeyCredentialResponse, Instant.now());
}
- public ExpiringProfileKeyCredential receiveExpiringProfileKeyCredential(ProfileKeyCredentialRequestContext profileKeyCredentialRequestContext, ExpiringProfileKeyCredentialResponse profileKeyCredentialResponse, Instant now) throws VerificationFailedException {
+ public ExpiringProfileKeyCredential receiveExpiringProfileKeyCredential(
+ ProfileKeyCredentialRequestContext profileKeyCredentialRequestContext,
+ ExpiringProfileKeyCredentialResponse profileKeyCredentialResponse,
+ Instant now)
+ throws VerificationFailedException {
if (profileKeyCredentialResponse == null) {
throw new VerificationFailedException();
}
- byte[] newContents = Native.ServerPublicParams_ReceiveExpiringProfileKeyCredential(serverPublicParams.getInternalContentsForJNI(), profileKeyCredentialRequestContext.getInternalContentsForJNI(), profileKeyCredentialResponse.getInternalContentsForJNI(), now.getEpochSecond());
+ byte[] newContents =
+ Native.ServerPublicParams_ReceiveExpiringProfileKeyCredential(
+ serverPublicParams.getInternalContentsForJNI(),
+ profileKeyCredentialRequestContext.getInternalContentsForJNI(),
+ profileKeyCredentialResponse.getInternalContentsForJNI(),
+ now.getEpochSecond());
try {
return new ExpiringProfileKeyCredential(newContents);
@@ -59,15 +79,25 @@ public ExpiringProfileKeyCredential receiveExpiringProfileKeyCredential(ProfileK
}
}
- public ProfileKeyCredentialPresentation createProfileKeyCredentialPresentation(GroupSecretParams groupSecretParams, ExpiringProfileKeyCredential profileKeyCredential) {
- return createProfileKeyCredentialPresentation(new SecureRandom(), groupSecretParams, profileKeyCredential);
+ public ProfileKeyCredentialPresentation createProfileKeyCredentialPresentation(
+ GroupSecretParams groupSecretParams, ExpiringProfileKeyCredential profileKeyCredential) {
+ return createProfileKeyCredentialPresentation(
+ new SecureRandom(), groupSecretParams, profileKeyCredential);
}
- public ProfileKeyCredentialPresentation createProfileKeyCredentialPresentation(SecureRandom secureRandom, GroupSecretParams groupSecretParams, ExpiringProfileKeyCredential profileKeyCredential) {
- byte[] random = new byte[RANDOM_LENGTH];
+ public ProfileKeyCredentialPresentation createProfileKeyCredentialPresentation(
+ SecureRandom secureRandom,
+ GroupSecretParams groupSecretParams,
+ ExpiringProfileKeyCredential profileKeyCredential) {
+ byte[] random = new byte[RANDOM_LENGTH];
secureRandom.nextBytes(random);
- byte[] newContents = Native.ServerPublicParams_CreateExpiringProfileKeyCredentialPresentationDeterministic(serverPublicParams.getInternalContentsForJNI(), random, groupSecretParams.getInternalContentsForJNI(), profileKeyCredential.getInternalContentsForJNI());
+ byte[] newContents =
+ Native.ServerPublicParams_CreateExpiringProfileKeyCredentialPresentationDeterministic(
+ serverPublicParams.getInternalContentsForJNI(),
+ random,
+ groupSecretParams.getInternalContentsForJNI(),
+ profileKeyCredential.getInternalContentsForJNI());
try {
return new ProfileKeyCredentialPresentation(newContents);
@@ -75,5 +105,4 @@ public ProfileKeyCredentialPresentation createProfileKeyCredentialPresentation(S
throw new AssertionError(e);
}
}
-
}
diff --git a/java/shared/java/org/signal/libsignal/zkgroup/profiles/ExpiringProfileKeyCredential.java b/java/shared/java/org/signal/libsignal/zkgroup/profiles/ExpiringProfileKeyCredential.java
index 40d02949e5..ca34e2b8fd 100644
--- a/java/shared/java/org/signal/libsignal/zkgroup/profiles/ExpiringProfileKeyCredential.java
+++ b/java/shared/java/org/signal/libsignal/zkgroup/profiles/ExpiringProfileKeyCredential.java
@@ -5,19 +5,19 @@
package org.signal.libsignal.zkgroup.profiles;
+import java.time.Instant;
+import org.signal.libsignal.internal.Native;
import org.signal.libsignal.zkgroup.InvalidInputException;
import org.signal.libsignal.zkgroup.internal.ByteArray;
-import org.signal.libsignal.internal.Native;
-
-import java.time.Instant;
public final class ExpiringProfileKeyCredential extends ByteArray {
public ExpiringProfileKeyCredential(byte[] contents) throws InvalidInputException {
super(contents);
Native.ExpiringProfileKeyCredential_CheckValidContents(contents);
}
-
+
public Instant getExpirationTime() {
- return Instant.ofEpochSecond(Native.ExpiringProfileKeyCredential_GetExpirationTime(this.contents));
+ return Instant.ofEpochSecond(
+ Native.ExpiringProfileKeyCredential_GetExpirationTime(this.contents));
}
}
diff --git a/java/shared/java/org/signal/libsignal/zkgroup/profiles/ExpiringProfileKeyCredentialResponse.java b/java/shared/java/org/signal/libsignal/zkgroup/profiles/ExpiringProfileKeyCredentialResponse.java
index 6e872cd06f..e47c92a256 100644
--- a/java/shared/java/org/signal/libsignal/zkgroup/profiles/ExpiringProfileKeyCredentialResponse.java
+++ b/java/shared/java/org/signal/libsignal/zkgroup/profiles/ExpiringProfileKeyCredentialResponse.java
@@ -5,9 +5,9 @@
package org.signal.libsignal.zkgroup.profiles;
+import org.signal.libsignal.internal.Native;
import org.signal.libsignal.zkgroup.InvalidInputException;
import org.signal.libsignal.zkgroup.internal.ByteArray;
-import org.signal.libsignal.internal.Native;
public final class ExpiringProfileKeyCredentialResponse extends ByteArray {
public ExpiringProfileKeyCredentialResponse(byte[] contents) throws InvalidInputException {
diff --git a/java/shared/java/org/signal/libsignal/zkgroup/profiles/ProfileKey.java b/java/shared/java/org/signal/libsignal/zkgroup/profiles/ProfileKey.java
index 4713d7a43d..8f1bf94e39 100644
--- a/java/shared/java/org/signal/libsignal/zkgroup/profiles/ProfileKey.java
+++ b/java/shared/java/org/signal/libsignal/zkgroup/profiles/ProfileKey.java
@@ -5,11 +5,10 @@
package org.signal.libsignal.zkgroup.profiles;
+import org.signal.libsignal.internal.Native;
import org.signal.libsignal.protocol.ServiceId.Aci;
import org.signal.libsignal.zkgroup.InvalidInputException;
-import org.signal.libsignal.zkgroup.VerificationFailedException;
import org.signal.libsignal.zkgroup.internal.ByteArray;
-import org.signal.libsignal.internal.Native;
public final class ProfileKey extends ByteArray {
@@ -19,7 +18,8 @@ public ProfileKey(byte[] contents) throws InvalidInputException {
}
public ProfileKeyCommitment getCommitment(Aci userId) {
- byte[] newContents = Native.ProfileKey_GetCommitment(contents, userId.toServiceIdFixedWidthBinary());
+ byte[] newContents =
+ Native.ProfileKey_GetCommitment(contents, userId.toServiceIdFixedWidthBinary());
try {
return new ProfileKeyCommitment(newContents);
@@ -29,7 +29,8 @@ public ProfileKeyCommitment getCommitment(Aci userId) {
}
public ProfileKeyVersion getProfileKeyVersion(Aci userId) {
- byte[] newContents = Native.ProfileKey_GetProfileKeyVersion(contents, userId.toServiceIdFixedWidthBinary());
+ byte[] newContents =
+ Native.ProfileKey_GetProfileKeyVersion(contents, userId.toServiceIdFixedWidthBinary());
try {
return new ProfileKeyVersion(newContents);
@@ -41,5 +42,4 @@ public ProfileKeyVersion getProfileKeyVersion(Aci userId) {
public byte[] deriveAccessKey() {
return Native.ProfileKey_DeriveAccessKey(contents);
}
-
}
diff --git a/java/shared/java/org/signal/libsignal/zkgroup/profiles/ProfileKeyCommitment.java b/java/shared/java/org/signal/libsignal/zkgroup/profiles/ProfileKeyCommitment.java
index 5ea4150ebc..4def88cff9 100644
--- a/java/shared/java/org/signal/libsignal/zkgroup/profiles/ProfileKeyCommitment.java
+++ b/java/shared/java/org/signal/libsignal/zkgroup/profiles/ProfileKeyCommitment.java
@@ -5,9 +5,9 @@
package org.signal.libsignal.zkgroup.profiles;
+import org.signal.libsignal.internal.Native;
import org.signal.libsignal.zkgroup.InvalidInputException;
import org.signal.libsignal.zkgroup.internal.ByteArray;
-import org.signal.libsignal.internal.Native;
public final class ProfileKeyCommitment extends ByteArray {
public ProfileKeyCommitment(byte[] contents) throws InvalidInputException {
diff --git a/java/shared/java/org/signal/libsignal/zkgroup/profiles/ProfileKeyCredentialPresentation.java b/java/shared/java/org/signal/libsignal/zkgroup/profiles/ProfileKeyCredentialPresentation.java
index 4beb1965d2..1f15f6255d 100644
--- a/java/shared/java/org/signal/libsignal/zkgroup/profiles/ProfileKeyCredentialPresentation.java
+++ b/java/shared/java/org/signal/libsignal/zkgroup/profiles/ProfileKeyCredentialPresentation.java
@@ -5,15 +5,20 @@
package org.signal.libsignal.zkgroup.profiles;
+import org.signal.libsignal.internal.Native;
import org.signal.libsignal.zkgroup.InvalidInputException;
import org.signal.libsignal.zkgroup.groups.ProfileKeyCiphertext;
import org.signal.libsignal.zkgroup.groups.UuidCiphertext;
import org.signal.libsignal.zkgroup.internal.ByteArray;
-import org.signal.libsignal.internal.Native;
public final class ProfileKeyCredentialPresentation extends ByteArray {
- public enum Version {V1, V2, V3, UNKNOWN};
+ public enum Version {
+ V1,
+ V2,
+ V3,
+ UNKNOWN
+ };
public ProfileKeyCredentialPresentation(byte[] contents) throws InvalidInputException {
super(contents);
@@ -41,16 +46,20 @@ public ProfileKeyCiphertext getProfileKeyCiphertext() {
}
public byte[] getStructurallyValidV1PresentationBytes() {
- return Native.ProfileKeyCredentialPresentation_GetStructurallyValidV1PresentationBytes(contents);
+ return Native.ProfileKeyCredentialPresentation_GetStructurallyValidV1PresentationBytes(
+ contents);
}
public Version getVersion() {
switch (this.contents[0]) {
- case 0: return Version.V1;
- case 1: return Version.V2;
- case 2: return Version.V3;
- default: return Version.UNKNOWN;
+ case 0:
+ return Version.V1;
+ case 1:
+ return Version.V2;
+ case 2:
+ return Version.V3;
+ default:
+ return Version.UNKNOWN;
}
}
-
}
diff --git a/java/shared/java/org/signal/libsignal/zkgroup/profiles/ProfileKeyCredentialRequest.java b/java/shared/java/org/signal/libsignal/zkgroup/profiles/ProfileKeyCredentialRequest.java
index 9ccebe039b..0f9c702052 100644
--- a/java/shared/java/org/signal/libsignal/zkgroup/profiles/ProfileKeyCredentialRequest.java
+++ b/java/shared/java/org/signal/libsignal/zkgroup/profiles/ProfileKeyCredentialRequest.java
@@ -5,9 +5,9 @@
package org.signal.libsignal.zkgroup.profiles;
+import org.signal.libsignal.internal.Native;
import org.signal.libsignal.zkgroup.InvalidInputException;
import org.signal.libsignal.zkgroup.internal.ByteArray;
-import org.signal.libsignal.internal.Native;
public final class ProfileKeyCredentialRequest extends ByteArray {
public ProfileKeyCredentialRequest(byte[] contents) throws InvalidInputException {
diff --git a/java/shared/java/org/signal/libsignal/zkgroup/profiles/ProfileKeyCredentialRequestContext.java b/java/shared/java/org/signal/libsignal/zkgroup/profiles/ProfileKeyCredentialRequestContext.java
index ecf442fffc..d0a68a2d35 100644
--- a/java/shared/java/org/signal/libsignal/zkgroup/profiles/ProfileKeyCredentialRequestContext.java
+++ b/java/shared/java/org/signal/libsignal/zkgroup/profiles/ProfileKeyCredentialRequestContext.java
@@ -5,9 +5,9 @@
package org.signal.libsignal.zkgroup.profiles;
+import org.signal.libsignal.internal.Native;
import org.signal.libsignal.zkgroup.InvalidInputException;
import org.signal.libsignal.zkgroup.internal.ByteArray;
-import org.signal.libsignal.internal.Native;
public final class ProfileKeyCredentialRequestContext extends ByteArray {
public ProfileKeyCredentialRequestContext(byte[] contents) throws InvalidInputException {
diff --git a/java/shared/java/org/signal/libsignal/zkgroup/profiles/ProfileKeyVersion.java b/java/shared/java/org/signal/libsignal/zkgroup/profiles/ProfileKeyVersion.java
index f0426227dc..a00e0f3bba 100644
--- a/java/shared/java/org/signal/libsignal/zkgroup/profiles/ProfileKeyVersion.java
+++ b/java/shared/java/org/signal/libsignal/zkgroup/profiles/ProfileKeyVersion.java
@@ -5,9 +5,8 @@
package org.signal.libsignal.zkgroup.profiles;
-import org.signal.libsignal.zkgroup.InvalidInputException;
-import org.signal.libsignal.zkgroup.internal.ByteArray;
import java.io.UnsupportedEncodingException;
+import org.signal.libsignal.zkgroup.InvalidInputException;
public final class ProfileKeyVersion {
@@ -20,7 +19,8 @@ public ProfileKeyVersion(byte[] contents) throws InvalidInputException {
this.contents = contents.clone();
}
- public ProfileKeyVersion(String contents) throws InvalidInputException, UnsupportedEncodingException {
+ public ProfileKeyVersion(String contents)
+ throws InvalidInputException, UnsupportedEncodingException {
this(contents.getBytes("UTF-8"));
}
@@ -31,5 +31,4 @@ public String serialize() {
throw new AssertionError();
}
}
-
}
diff --git a/java/shared/java/org/signal/libsignal/zkgroup/profiles/ServerZkProfileOperations.java b/java/shared/java/org/signal/libsignal/zkgroup/profiles/ServerZkProfileOperations.java
index c4aed98f89..1c26312aac 100644
--- a/java/shared/java/org/signal/libsignal/zkgroup/profiles/ServerZkProfileOperations.java
+++ b/java/shared/java/org/signal/libsignal/zkgroup/profiles/ServerZkProfileOperations.java
@@ -5,17 +5,17 @@
package org.signal.libsignal.zkgroup.profiles;
+import static org.signal.libsignal.zkgroup.internal.Constants.RANDOM_LENGTH;
+
import java.security.SecureRandom;
import java.time.Instant;
import java.time.temporal.ChronoUnit;
+import org.signal.libsignal.internal.Native;
import org.signal.libsignal.protocol.ServiceId.Aci;
import org.signal.libsignal.zkgroup.InvalidInputException;
import org.signal.libsignal.zkgroup.ServerSecretParams;
import org.signal.libsignal.zkgroup.VerificationFailedException;
import org.signal.libsignal.zkgroup.groups.GroupPublicParams;
-import org.signal.libsignal.internal.Native;
-
-import static org.signal.libsignal.zkgroup.internal.Constants.RANDOM_LENGTH;
public class ServerZkProfileOperations {
@@ -25,23 +25,42 @@ public ServerZkProfileOperations(ServerSecretParams serverSecretParams) {
this.serverSecretParams = serverSecretParams;
}
- public ExpiringProfileKeyCredentialResponse issueExpiringProfileKeyCredential(ProfileKeyCredentialRequest profileKeyCredentialRequest, Aci userId, ProfileKeyCommitment profileKeyCommitment, Instant expiration) throws VerificationFailedException {
- return issueExpiringProfileKeyCredential(new SecureRandom(), profileKeyCredentialRequest, userId, profileKeyCommitment, expiration);
+ public ExpiringProfileKeyCredentialResponse issueExpiringProfileKeyCredential(
+ ProfileKeyCredentialRequest profileKeyCredentialRequest,
+ Aci userId,
+ ProfileKeyCommitment profileKeyCommitment,
+ Instant expiration)
+ throws VerificationFailedException {
+ return issueExpiringProfileKeyCredential(
+ new SecureRandom(), profileKeyCredentialRequest, userId, profileKeyCommitment, expiration);
}
/**
* Issues an ExpiringProfileKeyCredential.
*
* @param expiration Must be a round number of days. Use {@link java.time.Instant#truncatedTo} to
- * ensure this.
+ * ensure this.
*/
- public ExpiringProfileKeyCredentialResponse issueExpiringProfileKeyCredential(SecureRandom secureRandom, ProfileKeyCredentialRequest profileKeyCredentialRequest, Aci userId, ProfileKeyCommitment profileKeyCommitment, Instant expiration) throws VerificationFailedException {
+ public ExpiringProfileKeyCredentialResponse issueExpiringProfileKeyCredential(
+ SecureRandom secureRandom,
+ ProfileKeyCredentialRequest profileKeyCredentialRequest,
+ Aci userId,
+ ProfileKeyCommitment profileKeyCommitment,
+ Instant expiration)
+ throws VerificationFailedException {
assert expiration.equals(expiration.truncatedTo(ChronoUnit.DAYS));
- byte[] random = new byte[RANDOM_LENGTH];
+ byte[] random = new byte[RANDOM_LENGTH];
secureRandom.nextBytes(random);
- byte[] newContents = Native.ServerSecretParams_IssueExpiringProfileKeyCredentialDeterministic(serverSecretParams.getInternalContentsForJNI(), random, profileKeyCredentialRequest.getInternalContentsForJNI(), userId.toServiceIdFixedWidthBinary(), profileKeyCommitment.getInternalContentsForJNI(), expiration.getEpochSecond());
+ byte[] newContents =
+ Native.ServerSecretParams_IssueExpiringProfileKeyCredentialDeterministic(
+ serverSecretParams.getInternalContentsForJNI(),
+ random,
+ profileKeyCredentialRequest.getInternalContentsForJNI(),
+ userId.toServiceIdFixedWidthBinary(),
+ profileKeyCommitment.getInternalContentsForJNI(),
+ expiration.getEpochSecond());
try {
return new ExpiringProfileKeyCredentialResponse(newContents);
@@ -50,12 +69,23 @@ public ExpiringProfileKeyCredentialResponse issueExpiringProfileKeyCredential(Se
}
}
- public void verifyProfileKeyCredentialPresentation(GroupPublicParams groupPublicParams, ProfileKeyCredentialPresentation profileKeyCredentialPresentation) throws VerificationFailedException {
- verifyProfileKeyCredentialPresentation(groupPublicParams, profileKeyCredentialPresentation, Instant.now());
+ public void verifyProfileKeyCredentialPresentation(
+ GroupPublicParams groupPublicParams,
+ ProfileKeyCredentialPresentation profileKeyCredentialPresentation)
+ throws VerificationFailedException {
+ verifyProfileKeyCredentialPresentation(
+ groupPublicParams, profileKeyCredentialPresentation, Instant.now());
}
- public void verifyProfileKeyCredentialPresentation(GroupPublicParams groupPublicParams, ProfileKeyCredentialPresentation profileKeyCredentialPresentation, Instant now) throws VerificationFailedException {
- Native.ServerSecretParams_VerifyProfileKeyCredentialPresentation(serverSecretParams.getInternalContentsForJNI(), groupPublicParams.getInternalContentsForJNI(), profileKeyCredentialPresentation.getInternalContentsForJNI(), now.getEpochSecond());
+ public void verifyProfileKeyCredentialPresentation(
+ GroupPublicParams groupPublicParams,
+ ProfileKeyCredentialPresentation profileKeyCredentialPresentation,
+ Instant now)
+ throws VerificationFailedException {
+ Native.ServerSecretParams_VerifyProfileKeyCredentialPresentation(
+ serverSecretParams.getInternalContentsForJNI(),
+ groupPublicParams.getInternalContentsForJNI(),
+ profileKeyCredentialPresentation.getInternalContentsForJNI(),
+ now.getEpochSecond());
}
-
}
diff --git a/java/shared/java/org/signal/libsignal/zkgroup/receipts/ClientZkReceiptOperations.java b/java/shared/java/org/signal/libsignal/zkgroup/receipts/ClientZkReceiptOperations.java
index b444932cc7..d65ef66275 100644
--- a/java/shared/java/org/signal/libsignal/zkgroup/receipts/ClientZkReceiptOperations.java
+++ b/java/shared/java/org/signal/libsignal/zkgroup/receipts/ClientZkReceiptOperations.java
@@ -5,13 +5,13 @@
package org.signal.libsignal.zkgroup.receipts;
+import static org.signal.libsignal.zkgroup.internal.Constants.RANDOM_LENGTH;
+
import java.security.SecureRandom;
+import org.signal.libsignal.internal.Native;
import org.signal.libsignal.zkgroup.InvalidInputException;
import org.signal.libsignal.zkgroup.ServerPublicParams;
import org.signal.libsignal.zkgroup.VerificationFailedException;
-import org.signal.libsignal.internal.Native;
-
-import static org.signal.libsignal.zkgroup.internal.Constants.RANDOM_LENGTH;
public class ClientZkReceiptOperations {
@@ -21,15 +21,21 @@ public ClientZkReceiptOperations(ServerPublicParams serverPublicParams) {
this.serverPublicParams = serverPublicParams;
}
- public ReceiptCredentialRequestContext createReceiptCredentialRequestContext(ReceiptSerial receiptSerial) throws VerificationFailedException {
+ public ReceiptCredentialRequestContext createReceiptCredentialRequestContext(
+ ReceiptSerial receiptSerial) throws VerificationFailedException {
return createReceiptCredentialRequestContext(new SecureRandom(), receiptSerial);
}
- public ReceiptCredentialRequestContext createReceiptCredentialRequestContext(SecureRandom secureRandom, ReceiptSerial receiptSerial) throws VerificationFailedException {
- byte[] random = new byte[RANDOM_LENGTH];
+ public ReceiptCredentialRequestContext createReceiptCredentialRequestContext(
+ SecureRandom secureRandom, ReceiptSerial receiptSerial) throws VerificationFailedException {
+ byte[] random = new byte[RANDOM_LENGTH];
secureRandom.nextBytes(random);
- byte[] newContents = Native.ServerPublicParams_CreateReceiptCredentialRequestContextDeterministic(serverPublicParams.getInternalContentsForJNI(), random, receiptSerial.getInternalContentsForJNI());
+ byte[] newContents =
+ Native.ServerPublicParams_CreateReceiptCredentialRequestContextDeterministic(
+ serverPublicParams.getInternalContentsForJNI(),
+ random,
+ receiptSerial.getInternalContentsForJNI());
try {
return new ReceiptCredentialRequestContext(newContents);
@@ -38,8 +44,15 @@ public ReceiptCredentialRequestContext createReceiptCredentialRequestContext(Sec
}
}
- public ReceiptCredential receiveReceiptCredential(ReceiptCredentialRequestContext receiptCredentialRequestContext, ReceiptCredentialResponse receiptCredentialResponse) throws VerificationFailedException {
- byte[] newContents = Native.ServerPublicParams_ReceiveReceiptCredential(serverPublicParams.getInternalContentsForJNI(), receiptCredentialRequestContext.getInternalContentsForJNI(), receiptCredentialResponse.getInternalContentsForJNI());
+ public ReceiptCredential receiveReceiptCredential(
+ ReceiptCredentialRequestContext receiptCredentialRequestContext,
+ ReceiptCredentialResponse receiptCredentialResponse)
+ throws VerificationFailedException {
+ byte[] newContents =
+ Native.ServerPublicParams_ReceiveReceiptCredential(
+ serverPublicParams.getInternalContentsForJNI(),
+ receiptCredentialRequestContext.getInternalContentsForJNI(),
+ receiptCredentialResponse.getInternalContentsForJNI());
try {
return new ReceiptCredential(newContents);
@@ -48,15 +61,22 @@ public ReceiptCredential receiveReceiptCredential(ReceiptCredentialRequestContex
}
}
- public ReceiptCredentialPresentation createReceiptCredentialPresentation(ReceiptCredential receiptCredential) throws VerificationFailedException {
+ public ReceiptCredentialPresentation createReceiptCredentialPresentation(
+ ReceiptCredential receiptCredential) throws VerificationFailedException {
return createReceiptCredentialPresentation(new SecureRandom(), receiptCredential);
}
- public ReceiptCredentialPresentation createReceiptCredentialPresentation(SecureRandom secureRandom, ReceiptCredential receiptCredential) throws VerificationFailedException {
- byte[] random = new byte[RANDOM_LENGTH];
+ public ReceiptCredentialPresentation createReceiptCredentialPresentation(
+ SecureRandom secureRandom, ReceiptCredential receiptCredential)
+ throws VerificationFailedException {
+ byte[] random = new byte[RANDOM_LENGTH];
secureRandom.nextBytes(random);
- byte[] newContents = Native.ServerPublicParams_CreateReceiptCredentialPresentationDeterministic(serverPublicParams.getInternalContentsForJNI(), random, receiptCredential.getInternalContentsForJNI());
+ byte[] newContents =
+ Native.ServerPublicParams_CreateReceiptCredentialPresentationDeterministic(
+ serverPublicParams.getInternalContentsForJNI(),
+ random,
+ receiptCredential.getInternalContentsForJNI());
try {
return new ReceiptCredentialPresentation(newContents);
@@ -64,5 +84,4 @@ public ReceiptCredentialPresentation createReceiptCredentialPresentation(SecureR
throw new AssertionError(e);
}
}
-
}
diff --git a/java/shared/java/org/signal/libsignal/zkgroup/receipts/ReceiptCredential.java b/java/shared/java/org/signal/libsignal/zkgroup/receipts/ReceiptCredential.java
index 67bde0e1e4..0607f4ddc4 100644
--- a/java/shared/java/org/signal/libsignal/zkgroup/receipts/ReceiptCredential.java
+++ b/java/shared/java/org/signal/libsignal/zkgroup/receipts/ReceiptCredential.java
@@ -5,10 +5,9 @@
package org.signal.libsignal.zkgroup.receipts;
-import java.nio.ByteBuffer;
+import org.signal.libsignal.internal.Native;
import org.signal.libsignal.zkgroup.InvalidInputException;
import org.signal.libsignal.zkgroup.internal.ByteArray;
-import org.signal.libsignal.internal.Native;
public final class ReceiptCredential extends ByteArray {
@@ -24,5 +23,4 @@ public long getReceiptExpirationTime() {
public long getReceiptLevel() {
return Native.ReceiptCredential_GetReceiptLevel(contents);
}
-
}
diff --git a/java/shared/java/org/signal/libsignal/zkgroup/receipts/ReceiptCredentialPresentation.java b/java/shared/java/org/signal/libsignal/zkgroup/receipts/ReceiptCredentialPresentation.java
index 67c7ce8321..9df1a949d5 100644
--- a/java/shared/java/org/signal/libsignal/zkgroup/receipts/ReceiptCredentialPresentation.java
+++ b/java/shared/java/org/signal/libsignal/zkgroup/receipts/ReceiptCredentialPresentation.java
@@ -5,10 +5,9 @@
package org.signal.libsignal.zkgroup.receipts;
-import java.nio.ByteBuffer;
+import org.signal.libsignal.internal.Native;
import org.signal.libsignal.zkgroup.InvalidInputException;
import org.signal.libsignal.zkgroup.internal.ByteArray;
-import org.signal.libsignal.internal.Native;
public final class ReceiptCredentialPresentation extends ByteArray {
public ReceiptCredentialPresentation(byte[] contents) throws InvalidInputException {
@@ -33,5 +32,4 @@ public ReceiptSerial getReceiptSerial() {
throw new AssertionError(e);
}
}
-
}
diff --git a/java/shared/java/org/signal/libsignal/zkgroup/receipts/ReceiptCredentialRequest.java b/java/shared/java/org/signal/libsignal/zkgroup/receipts/ReceiptCredentialRequest.java
index 0120fc1900..55ee2e82e6 100644
--- a/java/shared/java/org/signal/libsignal/zkgroup/receipts/ReceiptCredentialRequest.java
+++ b/java/shared/java/org/signal/libsignal/zkgroup/receipts/ReceiptCredentialRequest.java
@@ -5,9 +5,9 @@
package org.signal.libsignal.zkgroup.receipts;
+import org.signal.libsignal.internal.Native;
import org.signal.libsignal.zkgroup.InvalidInputException;
import org.signal.libsignal.zkgroup.internal.ByteArray;
-import org.signal.libsignal.internal.Native;
public final class ReceiptCredentialRequest extends ByteArray {
public ReceiptCredentialRequest(byte[] contents) throws InvalidInputException {
diff --git a/java/shared/java/org/signal/libsignal/zkgroup/receipts/ReceiptCredentialRequestContext.java b/java/shared/java/org/signal/libsignal/zkgroup/receipts/ReceiptCredentialRequestContext.java
index b746cde056..494efc30c3 100644
--- a/java/shared/java/org/signal/libsignal/zkgroup/receipts/ReceiptCredentialRequestContext.java
+++ b/java/shared/java/org/signal/libsignal/zkgroup/receipts/ReceiptCredentialRequestContext.java
@@ -5,9 +5,9 @@
package org.signal.libsignal.zkgroup.receipts;
+import org.signal.libsignal.internal.Native;
import org.signal.libsignal.zkgroup.InvalidInputException;
import org.signal.libsignal.zkgroup.internal.ByteArray;
-import org.signal.libsignal.internal.Native;
public final class ReceiptCredentialRequestContext extends ByteArray {
@@ -27,5 +27,4 @@ public ReceiptCredentialRequest getRequest() {
throw new AssertionError(e);
}
}
-
}
diff --git a/java/shared/java/org/signal/libsignal/zkgroup/receipts/ReceiptCredentialResponse.java b/java/shared/java/org/signal/libsignal/zkgroup/receipts/ReceiptCredentialResponse.java
index 3dc7db637b..d07c3c4724 100644
--- a/java/shared/java/org/signal/libsignal/zkgroup/receipts/ReceiptCredentialResponse.java
+++ b/java/shared/java/org/signal/libsignal/zkgroup/receipts/ReceiptCredentialResponse.java
@@ -5,9 +5,9 @@
package org.signal.libsignal.zkgroup.receipts;
+import org.signal.libsignal.internal.Native;
import org.signal.libsignal.zkgroup.InvalidInputException;
import org.signal.libsignal.zkgroup.internal.ByteArray;
-import org.signal.libsignal.internal.Native;
public final class ReceiptCredentialResponse extends ByteArray {
public ReceiptCredentialResponse(byte[] contents) throws InvalidInputException {
diff --git a/java/shared/java/org/signal/libsignal/zkgroup/receipts/ReceiptSerial.java b/java/shared/java/org/signal/libsignal/zkgroup/receipts/ReceiptSerial.java
index 6edf7cb2e6..98ea332225 100644
--- a/java/shared/java/org/signal/libsignal/zkgroup/receipts/ReceiptSerial.java
+++ b/java/shared/java/org/signal/libsignal/zkgroup/receipts/ReceiptSerial.java
@@ -15,5 +15,4 @@ public final class ReceiptSerial extends ByteArray {
public ReceiptSerial(byte[] contents) throws InvalidInputException {
super(contents, SIZE);
}
-
}
diff --git a/java/shared/java/org/signal/libsignal/zkgroup/receipts/ServerZkReceiptOperations.java b/java/shared/java/org/signal/libsignal/zkgroup/receipts/ServerZkReceiptOperations.java
index 21b4888054..9247768969 100644
--- a/java/shared/java/org/signal/libsignal/zkgroup/receipts/ServerZkReceiptOperations.java
+++ b/java/shared/java/org/signal/libsignal/zkgroup/receipts/ServerZkReceiptOperations.java
@@ -5,13 +5,13 @@
package org.signal.libsignal.zkgroup.receipts;
+import static org.signal.libsignal.zkgroup.internal.Constants.RANDOM_LENGTH;
+
import java.security.SecureRandom;
+import org.signal.libsignal.internal.Native;
import org.signal.libsignal.zkgroup.InvalidInputException;
import org.signal.libsignal.zkgroup.ServerSecretParams;
import org.signal.libsignal.zkgroup.VerificationFailedException;
-import org.signal.libsignal.internal.Native;
-
-import static org.signal.libsignal.zkgroup.internal.Constants.RANDOM_LENGTH;
public class ServerZkReceiptOperations {
@@ -21,15 +21,31 @@ public ServerZkReceiptOperations(ServerSecretParams serverSecretParams) {
this.serverSecretParams = serverSecretParams;
}
- public ReceiptCredentialResponse issueReceiptCredential(ReceiptCredentialRequest receiptCredentialRequest, long receiptExpirationTime, long receiptLevel) throws VerificationFailedException {
- return issueReceiptCredential(new SecureRandom(), receiptCredentialRequest, receiptExpirationTime, receiptLevel);
+ public ReceiptCredentialResponse issueReceiptCredential(
+ ReceiptCredentialRequest receiptCredentialRequest,
+ long receiptExpirationTime,
+ long receiptLevel)
+ throws VerificationFailedException {
+ return issueReceiptCredential(
+ new SecureRandom(), receiptCredentialRequest, receiptExpirationTime, receiptLevel);
}
- public ReceiptCredentialResponse issueReceiptCredential(SecureRandom secureRandom, ReceiptCredentialRequest receiptCredentialRequest, long receiptExpirationTime, long receiptLevel) throws VerificationFailedException {
- byte[] random = new byte[RANDOM_LENGTH];
+ public ReceiptCredentialResponse issueReceiptCredential(
+ SecureRandom secureRandom,
+ ReceiptCredentialRequest receiptCredentialRequest,
+ long receiptExpirationTime,
+ long receiptLevel)
+ throws VerificationFailedException {
+ byte[] random = new byte[RANDOM_LENGTH];
secureRandom.nextBytes(random);
- byte[] newContents = Native.ServerSecretParams_IssueReceiptCredentialDeterministic(serverSecretParams.getInternalContentsForJNI(), random, receiptCredentialRequest.getInternalContentsForJNI(), receiptExpirationTime, receiptLevel);
+ byte[] newContents =
+ Native.ServerSecretParams_IssueReceiptCredentialDeterministic(
+ serverSecretParams.getInternalContentsForJNI(),
+ random,
+ receiptCredentialRequest.getInternalContentsForJNI(),
+ receiptExpirationTime,
+ receiptLevel);
try {
return new ReceiptCredentialResponse(newContents);
@@ -38,8 +54,11 @@ public ReceiptCredentialResponse issueReceiptCredential(SecureRandom secureRando
}
}
- public void verifyReceiptCredentialPresentation(ReceiptCredentialPresentation receiptCredentialPresentation) throws VerificationFailedException {
- Native.ServerSecretParams_VerifyReceiptCredentialPresentation(serverSecretParams.getInternalContentsForJNI(), receiptCredentialPresentation.getInternalContentsForJNI());
+ public void verifyReceiptCredentialPresentation(
+ ReceiptCredentialPresentation receiptCredentialPresentation)
+ throws VerificationFailedException {
+ Native.ServerSecretParams_VerifyReceiptCredentialPresentation(
+ serverSecretParams.getInternalContentsForJNI(),
+ receiptCredentialPresentation.getInternalContentsForJNI());
}
-
}
diff --git a/node/Native.d.ts b/node/Native.d.ts
index 1400d4482f..47df64ff2f 100644
--- a/node/Native.d.ts
+++ b/node/Native.d.ts
@@ -313,16 +313,16 @@ export function ServiceId_ParseFromServiceIdString(input: string): Buffer;
export function ServiceId_ServiceIdBinary(value: Buffer): Buffer;
export function ServiceId_ServiceIdLog(value: Buffer): string;
export function ServiceId_ServiceIdString(value: Buffer): string;
-export function SessionBuilder_ProcessPreKeyBundle(bundle: Wrapper, protocolAddress: Wrapper, sessionStore: SessionStore, identityKeyStore: IdentityKeyStore): Promise;
+export function SessionBuilder_ProcessPreKeyBundle(bundle: Wrapper, protocolAddress: Wrapper, sessionStore: SessionStore, identityKeyStore: IdentityKeyStore, now: Timestamp): Promise;
export function SessionCipher_DecryptPreKeySignalMessage(message: Wrapper, protocolAddress: Wrapper, sessionStore: SessionStore, identityKeyStore: IdentityKeyStore, prekeyStore: PreKeyStore, signedPrekeyStore: SignedPreKeyStore, kyberPrekeyStore: KyberPreKeyStore): Promise;
export function SessionCipher_DecryptSignalMessage(message: Wrapper, protocolAddress: Wrapper, sessionStore: SessionStore, identityKeyStore: IdentityKeyStore): Promise;
-export function SessionCipher_EncryptMessage(ptext: Buffer, protocolAddress: Wrapper, sessionStore: SessionStore, identityKeyStore: IdentityKeyStore): Promise;
+export function SessionCipher_EncryptMessage(ptext: Buffer, protocolAddress: Wrapper, sessionStore: SessionStore, identityKeyStore: IdentityKeyStore, now: Timestamp): Promise;
export function SessionRecord_ArchiveCurrentState(sessionRecord: Wrapper): void;
export function SessionRecord_CurrentRatchetKeyMatches(s: Wrapper, key: Wrapper): boolean;
export function SessionRecord_Deserialize(data: Buffer): SessionRecord;
export function SessionRecord_GetLocalRegistrationId(obj: Wrapper): number;
export function SessionRecord_GetRemoteRegistrationId(obj: Wrapper): number;
-export function SessionRecord_HasCurrentState(obj: Wrapper): boolean;
+export function SessionRecord_HasUsableSenderChain(s: Wrapper, now: Timestamp): boolean;
export function SessionRecord_Serialize(obj: Wrapper): Buffer;
export function SgxClientState_CompleteHandshake(cli: Wrapper, handshakeReceived: Buffer): void;
export function SgxClientState_EstablishedRecv(cli: Wrapper, receivedCiphertext: Buffer): Buffer;
@@ -359,9 +359,9 @@ export function Username_Hash(username: string): Buffer;
export function Username_Proof(username: string, randomness: Buffer): Buffer;
export function Username_Verify(proof: Buffer, hash: Buffer): void;
export function UuidCiphertext_CheckValidContents(buffer: Buffer): void;
-export function ValidatingMac_Finalize(mac: Wrapper): boolean;
+export function ValidatingMac_Finalize(mac: Wrapper): number;
export function ValidatingMac_Initialize(key: Buffer, chunkSize: number, digests: Buffer): ValidatingMac;
-export function ValidatingMac_Update(mac: Wrapper, bytes: Buffer, offset: number, length: number): boolean;
+export function ValidatingMac_Update(mac: Wrapper, bytes: Buffer, offset: number, length: number): number;
export function initLogger(maxLevel: LogLevel, callback: (level: LogLevel, target: string, file: string | null, line: number | null, message: string) => void): void
interface Aes256GcmSiv { readonly __type: unique symbol; }
interface AuthCredential { readonly __type: unique symbol; }
diff --git a/node/build_node_bridge.py b/node/build_node_bridge.py
index bfa0cb4f4d..823b17c9ec 100755
--- a/node/build_node_bridge.py
+++ b/node/build_node_bridge.py
@@ -69,6 +69,7 @@ def main(args=None):
print("Running '%s'" % (' '.join(cmdline)))
cargo_env = os.environ.copy()
+ cargo_env['RUSTFLAGS'] = cargo_env.get('RUSTFLAGS') or ''
cargo_env['CARGO_BUILD_TARGET_DIR'] = options.cargo_build_dir
cargo_env['MACOSX_DEPLOYMENT_TARGET'] = '10.13'
# On Linux, cdylibs don't include public symbols from their dependencies,
@@ -76,11 +77,13 @@ def main(args=None):
# Using LTO works around this at the cost of a slightly slower build.
# https://github.com/rust-lang/rfcs/issues/2771
cargo_env['CARGO_PROFILE_RELEASE_LTO'] = 'thin'
+ # Enable ARMv8 cryptography acceleration when available
+ cargo_env['RUSTFLAGS'] += ' --cfg aes_armv8 --cfg polyval_armv8'
if node_os_name == 'win32':
# By default, Rust on Windows depends on an MSVC component for the C runtime.
# Link it statically to avoid propagating that dependency.
- cargo_env['RUSTFLAGS'] = '-C target-feature=+crt-static'
+ cargo_env['RUSTFLAGS'] += ' -C target-feature=+crt-static'
abs_build_dir = os.path.abspath(options.cargo_build_dir)
if 'GITHUB_WORKSPACE' in cargo_env:
diff --git a/node/package.json b/node/package.json
index 6d4b734515..c0220b07be 100644
--- a/node/package.json
+++ b/node/package.json
@@ -1,6 +1,6 @@
{
"name": "@signalapp/libsignal-client",
- "version": "0.31.0",
+ "version": "0.32.1",
"license": "AGPL-3.0-only",
"main": "dist/index.js",
"types": "dist/index.d.ts",
diff --git a/node/ts/incremental_mac.ts b/node/ts/incremental_mac.ts
index eae0edaf56..70945dd0a2 100644
--- a/node/ts/incremental_mac.ts
+++ b/node/ts/incremental_mac.ts
@@ -65,6 +65,8 @@ export class DigestingWritable extends stream.Writable {
export class ValidatingWritable extends stream.Writable {
_nativeHandle: Native.ValidatingMac;
+ _validatedBytes = 0;
+
constructor(key: Buffer, sizeChoice: ChunkSizeChoice, digest: Buffer) {
super();
this._nativeHandle = Native.ValidatingMac_Initialize(
@@ -74,6 +76,10 @@ export class ValidatingWritable extends stream.Writable {
);
}
+ validatedSize(): number {
+ return this._validatedBytes;
+ }
+
_write(
// eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/explicit-module-boundary-types
chunk: any,
@@ -82,7 +88,14 @@ export class ValidatingWritable extends stream.Writable {
): void {
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument
const buffer = Buffer.from(chunk, 'binary');
- if (Native.ValidatingMac_Update(this, buffer, 0, buffer.length)) {
+ const validBytes = Native.ValidatingMac_Update(
+ this,
+ buffer,
+ 0,
+ buffer.length
+ );
+ if (validBytes >= 0) {
+ this._validatedBytes += validBytes;
callback();
} else {
callback(makeVerificationError('Corrupted input data'));
@@ -90,7 +103,9 @@ export class ValidatingWritable extends stream.Writable {
}
_final(callback: (error?: Error | null) => void): void {
- if (Native.ValidatingMac_Finalize(this)) {
+ const validBytes = Native.ValidatingMac_Finalize(this);
+ if (validBytes >= 0) {
+ this._validatedBytes += validBytes;
callback();
} else {
callback(makeVerificationError('Corrupted input data (finalize)'));
diff --git a/node/ts/index.ts b/node/ts/index.ts
index 43144fe8f1..657f7ec967 100644
--- a/node/ts/index.ts
+++ b/node/ts/index.ts
@@ -748,8 +748,13 @@ export class SessionRecord {
return Native.SessionRecord_GetRemoteRegistrationId(this);
}
- hasCurrentState(): boolean {
- return Native.SessionRecord_HasCurrentState(this);
+ /**
+ * Returns whether the current session can be used to send messages.
+ *
+ * If there is no current session, returns false.
+ */
+ hasCurrentState(now: Date = new Date()): boolean {
+ return Native.SessionRecord_HasUsableSenderChain(this, now.getTime());
}
currentRatchetKeyMatches(key: PublicKey): boolean {
@@ -1500,13 +1505,15 @@ export function processPreKeyBundle(
bundle: PreKeyBundle,
address: ProtocolAddress,
sessionStore: SessionStore,
- identityStore: IdentityKeyStore
+ identityStore: IdentityKeyStore,
+ now: Date = new Date()
): Promise {
return Native.SessionBuilder_ProcessPreKeyBundle(
bundle,
address,
sessionStore,
- identityStore
+ identityStore,
+ now.getTime()
);
}
@@ -1514,14 +1521,16 @@ export async function signalEncrypt(
message: Buffer,
address: ProtocolAddress,
sessionStore: SessionStore,
- identityStore: IdentityKeyStore
+ identityStore: IdentityKeyStore,
+ now: Date = new Date()
): Promise {
return CiphertextMessage._fromNativeHandle(
await Native.SessionCipher_EncryptMessage(
message,
address,
sessionStore,
- identityStore
+ identityStore,
+ now.getTime()
)
);
}
diff --git a/node/ts/test/IncrementalMacTest.ts b/node/ts/test/IncrementalMacTest.ts
index a2437187d2..e578045322 100644
--- a/node/ts/test/IncrementalMacTest.ts
+++ b/node/ts/test/IncrementalMacTest.ts
@@ -36,10 +36,14 @@ const CHUNK_SIZE = everyNthByte(32);
describe('Incremental MAC', () => {
it('calculates the chunk size', () => {
- assert.equal(42, chunkSizeInBytes(inferChunkSize(42)));
- assert.equal(1024, chunkSizeInBytes(inferChunkSize(1024)));
- assert.equal(8192, chunkSizeInBytes(inferChunkSize(10 * 1024)));
- assert.equal(3276800, chunkSizeInBytes(inferChunkSize(100 * 1024 * 1024)));
+ assert.equal(64 * 1024, chunkSizeInBytes(inferChunkSize(0)));
+ assert.equal(64 * 1024, chunkSizeInBytes(inferChunkSize(42)));
+ assert.equal(64 * 1024, chunkSizeInBytes(inferChunkSize(1024)));
+ assert.equal(64 * 1024, chunkSizeInBytes(inferChunkSize(10 * 1024)));
+ assert.equal(
+ 400 * 1024,
+ chunkSizeInBytes(inferChunkSize(100 * 1024 * 1024))
+ );
});
describe('DigestingWritable', () => {
@@ -106,6 +110,22 @@ describe('Incremental MAC', () => {
);
await assert.isRejected(promise, LibSignalErrorBase);
});
+
+ it('keeps track of validated size', () => {
+ const validating = new ValidatingWritable(
+ TEST_KEY,
+ CHUNK_SIZE,
+ TEST_DIGEST
+ );
+ validating.write(Buffer.from(TEST_INPUT[0]));
+ assert.equal(0, validating.validatedSize());
+ validating.write(Buffer.from(TEST_INPUT[1]));
+ assert.equal(32, validating.validatedSize());
+ validating.write(Buffer.from(TEST_INPUT[2]));
+ assert.equal(32, validating.validatedSize());
+ validating.end();
+ assert.equal(50, validating.validatedSize());
+ });
});
});
diff --git a/node/ts/test/PublicAPITest.ts b/node/ts/test/PublicAPITest.ts
index d3bb63e40e..bc4848e68b 100644
--- a/node/ts/test/PublicAPITest.ts
+++ b/node/ts/test/PublicAPITest.ts
@@ -1158,6 +1158,55 @@ describe('SignalClient', () => {
assert.exists(err.stack); // Make sure we're still getting the benefits of Error.
}
});
+
+ it('expires unacknowledged sessions', async () => {
+ const aliceStores = new TestStores();
+ const bobStores = new TestStores();
+
+ const bAddress = SignalClient.ProtocolAddress.new('+19192222222', 1);
+
+ const bPreKeyBundle = await testCase.makeBundle(bAddress, bobStores);
+
+ await SignalClient.processPreKeyBundle(
+ bPreKeyBundle,
+ bAddress,
+ aliceStores.session,
+ aliceStores.identity,
+ new Date('2020-01-01')
+ );
+
+ const initialSession = await aliceStores.session.getSession(bAddress);
+ assert.isTrue(initialSession?.hasCurrentState(new Date('2020-01-01')));
+ assert.isFalse(initialSession?.hasCurrentState(new Date('2023-01-01')));
+
+ const aMessage = Buffer.from('Greetings hoo-man', 'utf8');
+ const aCiphertext = await SignalClient.signalEncrypt(
+ aMessage,
+ bAddress,
+ aliceStores.session,
+ aliceStores.identity,
+ new Date('2020-01-01')
+ );
+
+ assert.deepEqual(
+ aCiphertext.type(),
+ SignalClient.CiphertextMessageType.PreKey
+ );
+
+ const updatedSession = await aliceStores.session.getSession(bAddress);
+ assert.isTrue(updatedSession?.hasCurrentState(new Date('2020-01-01')));
+ assert.isFalse(updatedSession?.hasCurrentState(new Date('2023-01-01')));
+
+ await assert.isRejected(
+ SignalClient.signalEncrypt(
+ aMessage,
+ bAddress,
+ aliceStores.session,
+ aliceStores.identity,
+ new Date('2023-01-01')
+ )
+ );
+ });
});
}
diff --git a/rust-toolchain b/rust-toolchain
index 852204764e..2540aa02c2 100644
--- a/rust-toolchain
+++ b/rust-toolchain
@@ -1 +1 @@
-nightly-2023-03-17
+nightly-2023-09-01
diff --git a/rust/attest/Cargo.toml b/rust/attest/Cargo.toml
index 0331e224ad..77b23fe2e3 100644
--- a/rust/attest/Cargo.toml
+++ b/rust/attest/Cargo.toml
@@ -7,7 +7,7 @@
name = "attest"
version = "0.1.0"
authors = ["Signal Messenger LLC"]
-edition = "2018"
+edition = "2021"
license = "AGPL-3.0-only"
[dependencies]
@@ -16,8 +16,9 @@ boring-sys = { git = "https://github.com/signalapp/boring", branch = "libsignal"
asn1 = "0.15.4"
bitflags = "2.3.3"
-chacha20poly1305 = "0.9.1"
+chacha20poly1305 = "0.10.1"
chrono = { version = "0.4", features = ["serde"] }
+ciborium = "0.2"
displaydoc = "0.2"
hex = { version = "0.4", features = ["serde"] }
hex-literal = "0.4.1"
@@ -30,16 +31,15 @@ rand_core = { version = "0.6", features = ["getrandom"] }
serde = { version = "1.0", features = ["derive"] }
serde_json = { version = "1.0", features = ["raw_value"] }
sha2 = "0.10"
-# Here and elsewhere version 0.9.0 allows patching in snow's 'master' branch
-# See top-level Cargo.toml
-snow = { version = "0.9.0", default-features = false }
+snow = { version = "0.9.3", default-features = false }
static_assertions = "1.1"
+subtle = "2.5"
uuid = "1.1.2"
variant_count = "1.1"
-x25519-dalek = "2.0.0-rc.3"
+x25519-dalek = "2.0.0"
[dev-dependencies]
-snow = { version = "0.9.0", features = ["default-resolver"] }
+snow = { version = "0.9.3", features = ["default-resolver"] }
[build-dependencies]
prost-build = "0.9"
diff --git a/rust/attest/src/cds2.rs b/rust/attest/src/cds2.rs
index 88712a1a5b..f291e637e7 100644
--- a/rust/attest/src/cds2.rs
+++ b/rust/attest/src/cds2.rs
@@ -4,27 +4,29 @@
//
use std::collections::HashMap;
-use std::convert::From;
use hex_literal::hex;
-use lazy_static::lazy_static;
use prost::Message;
use sgx_session::Result;
use crate::dcap::MREnclave;
use crate::proto::cds2;
+use crate::util::SmallMap;
use crate::{dcap, sgx_session};
-lazy_static! {
- /// Map from MREnclave to intel SW advisories that are known to be mitigated in the
- /// build with that MREnclave value
- static ref ACCEPTABLE_SW_ADVISORIES: HashMap = {
- HashMap::from([
- (hex!("7b75dd6e862decef9b37132d54be082441917a7790e82fe44f9cf653de03a75f"), &["INTEL-SA-00657"] as &[&str]),
- (hex!("0f6fd79cdfdaa5b2e6337f534d3baf999318b0c462a7ac1f41297a3e4b424a57"), &["INTEL-SA-00615", "INTEL-SA-00657"] as &[&str]),
- ])
- };
-}
+/// Map from MREnclave to intel SW advisories that are known to be mitigated in the
+/// build with that MREnclave value.
+const ACCEPTABLE_SW_ADVISORIES: &SmallMap =
+ &SmallMap::new([
+ (
+ hex!("7b75dd6e862decef9b37132d54be082441917a7790e82fe44f9cf653de03a75f"),
+ &["INTEL-SA-00657"] as &[&str],
+ ),
+ (
+ hex!("0f6fd79cdfdaa5b2e6337f534d3baf999318b0c462a7ac1f41297a3e4b424a57"),
+ &["INTEL-SA-00615", "INTEL-SA-00657"] as &[&str],
+ ),
+ ]);
/// SW advisories known to be mitigated by default. If an MREnclave is provided that
/// is not contained in `ACCEPTABLE_SW_ADVISORIES`, this will be used
diff --git a/rust/attest/src/ias.rs b/rust/attest/src/ias.rs
index 08c9777eb4..6544789334 100644
--- a/rust/attest/src/ias.rs
+++ b/rust/attest/src/ias.rs
@@ -84,7 +84,7 @@ pub fn verify_signature(
}
impl CertChain {
- const COMMON_NAME: &str = "Intel SGX Attestation Report Signing";
+ const COMMON_NAME: &'static str = "Intel SGX Attestation Report Signing";
const ORGANIZATION_NAME: &'static str = "Intel Corporation";
const LOCALITY_NAME: &'static str = "Santa Clara";
const STATE_NAME: &'static str = "CA";
diff --git a/rust/attest/src/lib.rs b/rust/attest/src/lib.rs
index 6e4b4a091f..eac4fd5241 100644
--- a/rust/attest/src/lib.rs
+++ b/rust/attest/src/lib.rs
@@ -10,6 +10,7 @@ pub mod hsm_enclave;
pub mod ias;
pub mod sgx_session;
pub mod svr2;
+pub mod svr3;
mod endian;
mod error;
diff --git a/rust/attest/src/snow_resolver.rs b/rust/attest/src/snow_resolver.rs
index 41fe57f23c..0f6515d665 100644
--- a/rust/attest/src/snow_resolver.rs
+++ b/rust/attest/src/snow_resolver.rs
@@ -5,8 +5,7 @@
use std::convert::TryInto;
-use chacha20poly1305::aead::{AeadInPlace, NewAead};
-use chacha20poly1305::ChaCha20Poly1305;
+use chacha20poly1305::{AeadInPlace, ChaCha20Poly1305, KeyInit};
use rand_core::{CryptoRng, RngCore};
use sha2::{Digest, Sha256};
use snow::error::Error as SnowError;
diff --git a/rust/attest/src/svr2.rs b/rust/attest/src/svr2.rs
index 756d7405ef..20c5a6c1fb 100644
--- a/rust/attest/src/svr2.rs
+++ b/rust/attest/src/svr2.rs
@@ -3,25 +3,29 @@
// SPDX-License-Identifier: AGPL-3.0-only
//
-use std::collections::HashMap;
-
use hex_literal::hex;
-use lazy_static::lazy_static;
+
use prost::Message;
use crate::dcap::MREnclave;
use crate::proto::svr2;
use crate::sgx_session;
use crate::sgx_session::{Error, Result};
-
-lazy_static! {
- /// Map from MREnclave to intel SW advisories that are known to be mitigated in the
- /// build with that MREnclave value
- static ref ACCEPTABLE_SW_ADVISORIES: HashMap = HashMap::from([
- (hex!("a8a261420a6bb9b61aa25bf8a79e8bd20d7652531feb3381cbffd446d270be95"), &["INTEL-SA-00615", "INTEL-SA-00657"] as &[&str]),
- (hex!("6ee1042f9e20f880326686dd4ba50c25359f01e9f733eeba4382bca001d45094"), &["INTEL-SA-00615", "INTEL-SA-00657"] as &[&str]),
+use crate::util::SmallMap;
+
+/// Map from MREnclave to intel SW advisories that are known to be mitigated in the
+/// build with that MREnclave value
+const ACCEPTABLE_SW_ADVISORIES: &SmallMap =
+ &SmallMap::new([
+ (
+ hex!("a8a261420a6bb9b61aa25bf8a79e8bd20d7652531feb3381cbffd446d270be95"),
+ &["INTEL-SA-00615", "INTEL-SA-00657"] as &[&str],
+ ),
+ (
+ hex!("6ee1042f9e20f880326686dd4ba50c25359f01e9f733eeba4382bca001d45094"),
+ &["INTEL-SA-00615", "INTEL-SA-00657"] as &[&str],
+ ),
]);
-}
/// SW advisories known to be mitigated by default. If an MREnclave is provided that
/// is not contained in `ACCEPTABLE_SW_ADVISORIES`, this will be used
@@ -45,23 +49,27 @@ impl PartialEq for RaftConfig {
}
}
-lazy_static! {
- /// Expected raft configuration for a given enclave.
- static ref EXPECTED_RAFT_CONFIG: HashMap = HashMap::from([
- (hex!("a8a261420a6bb9b61aa25bf8a79e8bd20d7652531feb3381cbffd446d270be95"), &RaftConfig {
+/// Expected raft configuration for a given enclave.
+static EXPECTED_RAFT_CONFIG: SmallMap = SmallMap::new([
+ (
+ hex!("a8a261420a6bb9b61aa25bf8a79e8bd20d7652531feb3381cbffd446d270be95"),
+ &RaftConfig {
min_voting_replicas: 3,
max_voting_replicas: 5,
super_majority: 0,
- group_id: 15525669046665930652
- }),
- (hex!("6ee1042f9e20f880326686dd4ba50c25359f01e9f733eeba4382bca001d45094"), &RaftConfig {
+ group_id: 15525669046665930652,
+ },
+ ),
+ (
+ hex!("6ee1042f9e20f880326686dd4ba50c25359f01e9f733eeba4382bca001d45094"),
+ &RaftConfig {
min_voting_replicas: 4,
max_voting_replicas: 7,
super_majority: 2,
- group_id: 3950115602363750357
- }),
- ]);
-}
+ group_id: 3950115602363750357,
+ },
+ ),
+]);
pub struct Svr2Handshake {
/// The attested handshake that can be used to establish a noise connection
diff --git a/rust/attest/src/svr3.rs b/rust/attest/src/svr3.rs
new file mode 100644
index 0000000000..4bf5a1bba8
--- /dev/null
+++ b/rust/attest/src/svr3.rs
@@ -0,0 +1,5 @@
+//
+// Copyright 2023 Signal Messenger, LLC.
+// SPDX-License-Identifier: AGPL-3.0-only
+//
+pub mod nitro;
diff --git a/rust/attest/src/svr3/nitro.rs b/rust/attest/src/svr3/nitro.rs
new file mode 100644
index 0000000000..555e77734a
--- /dev/null
+++ b/rust/attest/src/svr3/nitro.rs
@@ -0,0 +1,603 @@
+//
+// Copyright 2023 Signal Messenger, LLC.
+// SPDX-License-Identifier: AGPL-3.0-only
+//
+use boring::bn::BigNum;
+use boring::ecdsa::EcdsaSig;
+use boring::stack;
+use boring::x509::store::X509StoreBuilder;
+use boring::x509::{X509StoreContext, X509};
+use ciborium::value::{Integer, Value};
+use sha2::{Digest, Sha384};
+use std::collections::HashMap;
+use std::time::SystemTime;
+use subtle::ConstantTimeEq;
+
+const PUBLIC_KEY_LENGTH: usize = 32;
+
+pub type PublicKeyBytes = [u8; PUBLIC_KEY_LENGTH];
+
+pub fn attest(
+ evidence: &[u8],
+ expected_pcrs: &HashMap>,
+ now: SystemTime,
+) -> Result {
+ let cose_sign1 = CoseSign1::from_bytes(evidence)?;
+ let doc = cose_sign1.extract_attestation_doc(now)?;
+ doc.extract_public_key(expected_pcrs)
+}
+
+#[derive(Debug, displaydoc::Display, PartialEq, Eq)]
+pub enum NitroError {
+ /// Invalid CBOR
+ InvalidCbor,
+ /// Invalid COSE_Sign1
+ InvalidCoseSign1,
+ /// Invalid signature
+ InvalidSignature,
+ /// Invalid attestation document
+ InvalidAttestationDoc,
+ /// Invalid certificate: {0}
+ InvalidCertificate(String),
+ /// Invalid PCRs
+ InvalidPcrs,
+ /// Invalid Public Key
+ InvalidPublicKey,
+}
+
+impl std::error::Error for NitroError {}
+
+impl From> for NitroError {
+ fn from(_err: ciborium::de::Error) -> NitroError {
+ NitroError::InvalidCbor
+ }
+}
+
+impl From for NitroError {
+ fn from(err: boring::error::ErrorStack) -> NitroError {
+ NitroError::InvalidCertificate(err.to_string())
+ }
+}
+
+#[derive(Debug)]
+pub struct CoseSign1 {
+ protected_header: Vec,
+ // nitro has no unprotected header
+ payload: Vec,
+ signature: Vec,
+}
+
+impl CoseSign1 {
+ pub fn from_bytes(bytes: &[u8]) -> Result {
+ let value: Value = ciborium::from_reader(bytes)?;
+ value.try_into()
+ }
+
+ pub fn extract_attestation_doc(&self, now: SystemTime) -> Result {
+ let hash = Sha384::digest(self.to_canonical());
+ let r = BigNum::from_slice(&self.signature[..48]).expect("can extract r");
+ let s = BigNum::from_slice(&self.signature[48..]).expect("can extract s");
+ let sig = EcdsaSig::from_private_components(r, s).expect("can initialize signature");
+
+ let doc = AttestationDoc::from_bytes(self.payload.as_slice()).expect("can parse doc");
+ let cert = doc.verified_cert(now)?;
+ let key = cert
+ .public_key()
+ .and_then(|pub_key| pub_key.ec_key())
+ .expect("has EC key");
+ let is_valid = sig.verify(hash.as_slice(), &key).expect("can verify");
+ if !is_valid {
+ return Err(NitroError::InvalidSignature);
+ }
+ Ok(doc)
+ }
+
+ fn validating_new(
+ protected_header: Vec,
+ payload: Vec,
+ signature: Vec,
+ ) -> Result {
+ let is_valid = {
+ let mut is_valid = true;
+ is_valid &= Self::is_valid_protected_header(&protected_header);
+ is_valid &= (1..16384).contains(&payload.len());
+ is_valid &= signature.len() == 96;
+ is_valid
+ };
+ if !is_valid {
+ return Err(NitroError::InvalidCoseSign1);
+ }
+ Ok(CoseSign1 {
+ protected_header,
+ payload,
+ signature,
+ })
+ }
+
+ fn is_valid_protected_header(bytes: &[u8]) -> bool {
+ let signing_algorithm: Integer = Integer::from(1);
+ let ecdsa_sha_384: Integer = Integer::from(-35);
+ let value: Value = ciborium::from_reader(bytes).expect("valid cbor");
+ match value {
+ Value::Map(vec) => match &vec[..] {
+ [(Value::Integer(key), Value::Integer(val))] => {
+ key == &signing_algorithm && val == &ecdsa_sha_384
+ }
+ _ => false,
+ },
+ _ => false,
+ }
+ }
+
+ fn to_canonical(&self) -> Vec {
+ let value = Value::Array(vec![
+ Value::Text("Signature1".to_string()),
+ Value::Bytes(self.protected_header.clone()),
+ Value::Bytes(vec![]),
+ Value::Bytes(self.payload.clone()),
+ ]);
+ let mut bytes = Vec::with_capacity(self.protected_header.len() + self.payload.len());
+ ciborium::into_writer(&value, &mut bytes).expect("can write bytes");
+ bytes
+ }
+}
+
+impl TryFrom for CoseSign1 {
+ type Error = NitroError;
+
+ // Assumes tagged CBOR encoding of COSE_Sign1
+ fn try_from(value: Value) -> Result {
+ let parts: [Value; 4] = value
+ .into_array()
+ .ok()
+ .and_then(|vs| vs.try_into().ok())
+ .ok_or(NitroError::InvalidCoseSign1)?;
+ match parts {
+ [Value::Bytes(protected_header), Value::Map(_), Value::Bytes(payload), Value::Bytes(signature)] => {
+ CoseSign1::validating_new(protected_header, payload, signature)
+ }
+ _ => Err(NitroError::InvalidCoseSign1),
+ }
+ }
+}
+
+#[derive(Debug)]
+pub struct AttestationDoc {
+ pub module_id: String,
+ pub digest: String,
+ pub timestamp: i64,
+ pub pcrs: Vec<(usize, Vec)>,
+ certificate: Vec,
+ cabundle: Vec>,
+ public_key: Option>,
+ pub user_data: Option>,
+ pub nonce: Option>,
+}
+
+impl TryFrom for AttestationDoc {
+ type Error = NitroError;
+
+ fn try_from(value: Value) -> Result {
+ let map = AttestationDoc::parse_as_cbor_map(value)?;
+ Self::from_cbor_map(map)
+ }
+}
+
+type CborMap = HashMap;
+
+impl AttestationDoc {
+ pub fn from_bytes(bytes: &[u8]) -> Result {
+ let value: Value = ciborium::from_reader(bytes)?;
+ value.try_into()
+ }
+
+ fn parse_as_cbor_map(value: Value) -> Result {
+ value
+ .into_map()
+ .map_err(|_| NitroError::InvalidAttestationDoc)?
+ .into_iter()
+ .map(|(k, v)| {
+ let k = k
+ .into_text()
+ .map_err(|_| NitroError::InvalidAttestationDoc)?;
+ Ok((k, v))
+ })
+ .collect()
+ }
+
+ fn from_cbor_map(mut map: CborMap) -> Result {
+ let module_id = map
+ .remove("module_id")
+ .and_then(|value| value.into_text().ok())
+ .filter(|s| !s.is_empty())
+ .ok_or(NitroError::InvalidAttestationDoc)?;
+ let digest = map
+ .remove("digest")
+ .and_then(|value| value.into_text().ok())
+ .filter(|s| s == "SHA384")
+ .ok_or(NitroError::InvalidAttestationDoc)?;
+ let timestamp = map
+ .remove("timestamp")
+ .and_then(|value| value.into_integer().ok())
+ .and_then(|integer| i64::try_from(integer).ok())
+ .filter(|i| i.is_positive())
+ .ok_or(NitroError::InvalidAttestationDoc)?;
+ let pcrs: Vec<(usize, Vec)> = map
+ .remove("pcrs")
+ .and_then(|value| value.into_map().ok())
+ .and_then(|pairs| {
+ if !(1..=32).contains(&pairs.len()) {
+ return None;
+ }
+ let mut pcrs = Vec::with_capacity(pairs.len());
+ for (key, value) in pairs.into_iter() {
+ let index = key
+ .into_integer()
+ .ok()
+ .and_then(|n| usize::try_from(n).ok())
+ .filter(|n| (0..32).contains(n))?;
+ let bytes = value
+ .into_bytes()
+ .ok()
+ .filter(|bs| [32, 48, 64].contains(&bs.len()))?;
+ pcrs.push((index, bytes))
+ }
+ Some(pcrs)
+ })
+ .ok_or(NitroError::InvalidAttestationDoc)?;
+
+ fn into_valid_cert_bytes(value: Value) -> Option> {
+ value
+ .into_bytes()
+ .ok()
+ .filter(|bs| (1..=1024).contains(&bs.len()))
+ }
+
+ let certificate = map
+ .remove("certificate")
+ .and_then(into_valid_cert_bytes)
+ .ok_or(NitroError::InvalidAttestationDoc)?;
+
+ let cabundle = map
+ .remove("cabundle")
+ .and_then(|value| value.into_array().ok())
+ .and_then(|vals| {
+ let certs: Vec<_> = vals.into_iter().filter_map(into_valid_cert_bytes).collect();
+ if certs.is_empty() {
+ return None;
+ }
+ Some(certs)
+ })
+ .ok_or(NitroError::InvalidAttestationDoc)?;
+
+ fn into_valid_optional_bytes(
+ value: Value,
+ expected_length: usize,
+ ) -> Result, NitroError> {
+ match value.into_bytes() {
+ Ok(bytes) if bytes.len() <= expected_length => Ok(bytes),
+ Err(Value::Null) => Ok(vec![]),
+ Ok(_) | Err(_) => Err(NitroError::InvalidAttestationDoc),
+ }
+ }
+
+ let public_key = map
+ .remove("public_key") // option
+ .map(|value| into_valid_optional_bytes(value, 1024))
+ .transpose()?;
+
+ let user_data = map
+ .remove("user_data")
+ .map(|value| into_valid_optional_bytes(value, 512))
+ .transpose()?;
+
+ let nonce = map
+ .remove("nonce")
+ .map(|value| into_valid_optional_bytes(value, 10))
+ .transpose()?;
+
+ Ok(AttestationDoc {
+ module_id,
+ digest,
+ timestamp,
+ pcrs,
+ certificate,
+ cabundle,
+ public_key,
+ user_data,
+ nonce,
+ })
+ }
+
+ fn verified_cert(&self, now: SystemTime) -> Result {
+ let mut context = X509StoreContext::new()?;
+ let certificate = X509::from_der(&self.certificate)?;
+ let mut stack = stack::Stack::::new()?;
+ for der in self.cabundle.iter() {
+ let cert = X509::from_der(der)?;
+ stack.push(cert)?;
+ }
+ let stack = stack;
+ let trust = {
+ let root = X509::from_pem(ROOT_CERTIFICATE_PEM)?;
+ let mut builder = X509StoreBuilder::new()?;
+ builder.param_mut().set_time(
+ now.duration_since(SystemTime::UNIX_EPOCH)
+ .expect("current time is after 1970")
+ .as_secs()
+ .try_into()
+ .expect("haven't yet overflowed time_t"),
+ );
+ builder.add_cert(root)?;
+ builder.build()
+ };
+ let is_valid = context.init(&trust, &certificate, &stack, |ctx| ctx.verify_cert())?;
+ if !is_valid {
+ let message = context.error().to_string();
+ return Err(NitroError::InvalidCertificate(message));
+ }
+ Ok(certificate)
+ }
+
+ pub fn extract_public_key(
+ &self,
+ expected_pcrs: &HashMap>,
+ ) -> Result {
+ let mut is_match = true;
+ for (index, pcr) in self.pcrs.iter() {
+ is_match &= expected_pcrs
+ .get(index)
+ .map(|expected| expected.ct_eq(pcr).into())
+ // if the index is missing from the expected_pcrs we do not check it
+ .unwrap_or(true);
+ }
+ if !is_match {
+ return Err(NitroError::InvalidPcrs);
+ }
+ self.public_key
+ .clone()
+ .ok_or(NitroError::InvalidPublicKey)?
+ .try_into()
+ .map_err(|_| NitroError::InvalidPublicKey)
+ }
+}
+
+#[cfg(test)]
+mod test {
+ use super::*;
+ use hex_literal::hex;
+ use std::time::Duration;
+
+ #[test]
+ fn test_extract_attestation_doc() {
+ let timestamp = SystemTime::UNIX_EPOCH + Duration::from_secs(1684362463);
+ let cose_sign1 = CoseSign1::from_bytes(VALID_DOCUMENT_BYTES_1).expect("can parse");
+ cose_sign1
+ .extract_attestation_doc(timestamp)
+ .expect("valid signature");
+ }
+
+ #[test]
+ fn test_attestation() {
+ let timestamp = SystemTime::UNIX_EPOCH + Duration::from_secs(1684948138);
+ let _pk = CoseSign1::from_bytes(VALID_DOCUMENT_BYTES_2)
+ .expect("can parse")
+ .extract_attestation_doc(timestamp)
+ .expect("valid signature")
+ .extract_public_key(&get_test_pcrs())
+ .expect("valid pcrs");
+ }
+
+ #[test]
+ fn test_expired_cert() {
+ let cose_sign1 = CoseSign1::from_bytes(VALID_DOCUMENT_BYTES_1).expect("can parse");
+ let err = cose_sign1
+ .extract_attestation_doc(SystemTime::now())
+ .unwrap_err();
+ assert!(format!("{err:?}").contains("expired"));
+ }
+
+ #[test]
+ fn test_not_yet_valid_cert() {
+ let cose_sign1 = CoseSign1::from_bytes(VALID_DOCUMENT_BYTES_1).expect("can parse");
+ let err = cose_sign1
+ .extract_attestation_doc(SystemTime::UNIX_EPOCH)
+ .unwrap_err();
+ assert!(format!("{err:?}").contains("not yet valid"));
+ }
+
+ #[test]
+ fn test_invalid_signature() {
+ let timestamp = SystemTime::UNIX_EPOCH + Duration::from_secs(1684362463);
+ let mut cose_sign1 = CoseSign1::from_bytes(VALID_DOCUMENT_BYTES_1).expect("can parse");
+ cose_sign1.signature[0] ^= 0xff;
+ let err = cose_sign1.extract_attestation_doc(timestamp).unwrap_err();
+ assert_eq!(NitroError::InvalidSignature, err);
+ }
+
+ fn invalid_cose_sign1_test(mut f: F)
+ where
+ F: FnMut(&mut CoseSign1),
+ {
+ let mut subject = CoseSign1::from_bytes(VALID_DOCUMENT_BYTES_1).expect("can parse");
+ f(&mut subject);
+ let err =
+ CoseSign1::validating_new(subject.protected_header, subject.payload, subject.signature)
+ .unwrap_err();
+ assert_eq!(NitroError::InvalidCoseSign1, err);
+ }
+
+ #[test]
+ fn test_invalid_cose_sign1_signature_len() {
+ invalid_cose_sign1_test(|subject| subject.signature.push(0x00));
+ }
+
+ #[test]
+ fn test_invalid_cose_sign1_empty_payload() {
+ invalid_cose_sign1_test(|subject| subject.payload = vec![]);
+ }
+
+ #[test]
+ fn test_invalid_cose_sign1_payload_too_large() {
+ invalid_cose_sign1_test(|subject| subject.payload = [0; 16384].to_vec());
+ }
+
+ #[test]
+ fn test_invalid_cose_sign1_invalid_header() {
+ invalid_cose_sign1_test(|subject| subject.protected_header = vec![1, 2, 3]);
+ }
+
+ #[test]
+ fn test_canonical_serialization() {
+ let subject = CoseSign1::from_bytes(VALID_DOCUMENT_BYTES_1).expect("can parse");
+ assert_eq!(subject.to_canonical(), VALID_DOCUMENT_BYTES_1_CANONICAL);
+ }
+
+ #[test]
+ fn test_non_string_keys() {
+ let value: Value = Value::Map(vec![(Value::Integer(42.into()), Value::Integer(42.into()))]);
+ let err =
+ AttestationDoc::parse_as_cbor_map(value).expect_err("Should have failed validation");
+ assert_eq!(err, NitroError::InvalidAttestationDoc);
+ }
+
+ fn invalid_attestation_doc_test(mut f: F)
+ where
+ F: FnMut(&mut CborMap),
+ {
+ let cose_sign1 = CoseSign1::from_bytes(VALID_DOCUMENT_BYTES_1).expect("valid cose_sign1");
+ let value: Value =
+ ciborium::from_reader(cose_sign1.payload.as_slice()).expect("valid cbor");
+ let mut map = AttestationDoc::parse_as_cbor_map(value).expect("valid cbor map");
+ f(&mut map);
+ let err = AttestationDoc::from_cbor_map(map).unwrap_err();
+ assert_eq!(NitroError::InvalidAttestationDoc, err);
+ }
+
+ #[test]
+ fn test_empty_module_id() {
+ invalid_attestation_doc_test(|map| {
+ *map.get_mut("module_id").unwrap() = Value::Text("".to_string());
+ });
+ }
+
+ #[test]
+ fn test_invalid_digest() {
+ invalid_attestation_doc_test(|map| {
+ *map.get_mut("digest").unwrap() = Value::Text("not sha384".to_string());
+ });
+ }
+
+ #[test]
+ fn test_zero_timestamp() {
+ invalid_attestation_doc_test(|map| {
+ *map.get_mut("timestamp").unwrap() = Value::Integer(0.into());
+ });
+ }
+
+ #[test]
+ fn test_empty_pcrs() {
+ invalid_attestation_doc_test(|map| {
+ *map.get_mut("pcrs").unwrap() = Value::Array(vec![]);
+ });
+ }
+
+ #[test]
+ fn test_too_many_pcrs() {
+ invalid_attestation_doc_test(|map| {
+ *map.get_mut("pcrs").unwrap() = Value::Array(
+ (1..33)
+ // Should be a byte array, but any Value would do for length validation
+ .map(|i| Value::Integer(i.into()))
+ .collect(),
+ );
+ });
+ }
+
+ #[test]
+ fn test_invalid_pcr_index() {
+ invalid_attestation_doc_test(|map| {
+ let pcrs = map.get_mut("pcrs").unwrap();
+ let pcr = pcrs.as_map_mut().unwrap();
+ pcr[0] = (Value::Integer(32.into()), pcr[0].1.clone());
+ });
+ }
+
+ #[test]
+ fn test_invalid_pcr_length() {
+ invalid_attestation_doc_test(|map| {
+ let pcrs = map.get_mut("pcrs").unwrap();
+ let pcr = pcrs.as_map_mut().unwrap();
+ pcr[0] = (pcr[0].0.clone(), Value::Bytes(b"00010203".to_vec()));
+ });
+ }
+
+ #[test]
+ fn test_empty_certificate() {
+ invalid_attestation_doc_test(|map| {
+ *map.get_mut("certificate").unwrap() = Value::Bytes(vec![]);
+ });
+ }
+
+ #[test]
+ fn test_certificate_too_long() {
+ invalid_attestation_doc_test(|map| {
+ *map.get_mut("certificate").unwrap() = Value::Bytes([0; 1025].to_vec());
+ });
+ }
+
+ #[test]
+ fn test_public_key_too_long() {
+ invalid_attestation_doc_test(|map| {
+ map.insert("public_key".to_string(), Value::Bytes([0; 1025].to_vec()));
+ });
+ }
+
+ #[test]
+ fn test_user_data_too_long() {
+ invalid_attestation_doc_test(|map| {
+ map.insert("user_data".to_string(), Value::Bytes([0; 513].to_vec()));
+ });
+ }
+
+ #[test]
+ fn test_nonce_too_long() {
+ invalid_attestation_doc_test(|map| {
+ map.insert("nonce".to_string(), Value::Bytes([0; 513].to_vec()));
+ });
+ }
+
+ const VALID_DOCUMENT_BYTES_1: &[u8] = include_bytes!("../../tests/data/test_cose_sign1_01.dat");
+ const VALID_DOCUMENT_BYTES_1_CANONICAL: &[u8] =
+ include_bytes!("../../tests/data/cose_sign1_canonical.dat");
+ const VALID_DOCUMENT_BYTES_2: &[u8] = include_bytes!("../../tests/data/test_cose_sign1_02.dat");
+
+ fn get_test_pcrs() -> HashMap> {
+ let mut map = HashMap::::new();
+ map.insert(0, hex!("28de6557cce896cf8c580d8674fbc13c45c1a7636545ef022a01007336b8752b9a1cd9ce69df2ecacc7696a1203b45c2").to_vec());
+ map.insert(1, hex!("52b919754e1643f4027eeee8ec39cc4a2cb931723de0c93ce5cc8d407467dc4302e86490c01c0d755acfe10dbf657546").to_vec());
+ map.insert(2, hex!("3bc780f5f2adc596f55c5d8b85760f1e9e585c7016957673616c0611280c4b99c8877caff00d70567a96979abe59dc0a").to_vec());
+ map.insert(3, hex!("000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000").to_vec());
+ map.insert(4, hex!("17354aa3f163d6882a4ff746e5821c5be66f1658472feac83268cf4b7461015ea47993c07025ebb5e134cbc13b16ac97").to_vec());
+ map
+ }
+}
+
+// From https://aws-nitro-enclaves.amazonaws.com/AWS_NitroEnclaves_Root-G1.zip
+// Zip hash (SHA256): 8cf60e2b2efca96c6a9e71e851d00c1b6991cc09eadbe64a6a1d1b1eb9faff7c
+const ROOT_CERTIFICATE_PEM: &[u8] = br"
+-----BEGIN CERTIFICATE-----
+MIICETCCAZagAwIBAgIRAPkxdWgbkK/hHUbMtOTn+FYwCgYIKoZIzj0EAwMwSTEL
+MAkGA1UEBhMCVVMxDzANBgNVBAoMBkFtYXpvbjEMMAoGA1UECwwDQVdTMRswGQYD
+VQQDDBJhd3Mubml0cm8tZW5jbGF2ZXMwHhcNMTkxMDI4MTMyODA1WhcNNDkxMDI4
+MTQyODA1WjBJMQswCQYDVQQGEwJVUzEPMA0GA1UECgwGQW1hem9uMQwwCgYDVQQL
+DANBV1MxGzAZBgNVBAMMEmF3cy5uaXRyby1lbmNsYXZlczB2MBAGByqGSM49AgEG
+BSuBBAAiA2IABPwCVOumCMHzaHDimtqQvkY4MpJzbolL//Zy2YlES1BR5TSksfbb
+48C8WBoyt7F2Bw7eEtaaP+ohG2bnUs990d0JX28TcPQXCEPZ3BABIeTPYwEoCWZE
+h8l5YoQwTcU/9KNCMEAwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUkCW1DdkF
+R+eWw5b6cp3PmanfS5YwDgYDVR0PAQH/BAQDAgGGMAoGCCqGSM49BAMDA2kAMGYC
+MQCjfy+Rocm9Xue4YnwWmNJVA44fA0P5W2OpYow9OYCVRaEevL8uO1XYru5xtMPW
+rfMCMQCi85sWBbJwKKXdS6BptQFuZbT73o/gBh1qUxl/nNr12UO8Yfwr6wPLb+6N
+IwLz3/Y=
+-----END CERTIFICATE-----
+";
diff --git a/rust/attest/src/util.rs b/rust/attest/src/util.rs
index b248059cc2..57c71d1388 100644
--- a/rust/attest/src/util.rs
+++ b/rust/attest/src/util.rs
@@ -9,6 +9,40 @@ use std::time::SystemTime;
use boring::asn1::Asn1Time;
use libc::time_t;
+/// A replacement for [`std::collections::HashMap`] that performs linear lookups.
+///
+/// This can be used in place of `HashMap` for supporting lookup in `const`
+/// arrays. For small `N`, the linear search will be faster than a hash lookup.
+pub(crate) struct SmallMap([(K, V); N]);
+
+impl SmallMap {
+ /// The maximum number of elements allowed in a `SmallMap`.
+ const MAX_SIZE: usize = 4;
+
+ /// Checks at compile-time (via `const`) that `N` is small enough.
+ const CHECK_MAX_SIZE: () = assert!(
+ N <= Self::MAX_SIZE,
+ "use a HashMap for more than MAX_SIZE items"
+ );
+
+ /// Creates a new `SmallMap` with the given contents.
+ pub(crate) const fn new(items: [(K, V); N]) -> Self {
+ // Evaluate CHECK_MAX_SIZE; this will fail compilation if `N` is too
+ // large.
+ //
+ // TODO(https://github.com/rust-lang/rust-clippy/issues/9048): Remove
+ // the unnecessary #[allow].
+ #[allow(clippy::let_unit_value)]
+ let _: () = Self::CHECK_MAX_SIZE;
+ Self(items)
+ }
+
+ /// Gets the value for the first key that matches `key`, or `None`.
+ pub(crate) fn get + ?Sized>(&self, key: &Q) -> Option<&V> {
+ self.0.iter().find_map(|(k, v)| (key == k).then_some(v))
+ }
+}
+
/// Removes a trailing null byte, if one exists
pub(crate) fn strip_trailing_null_byte(bytes: &mut &[u8]) {
*bytes = bytes.strip_suffix(&[0]).unwrap_or(bytes);
diff --git a/rust/attest/tests/data/cose_sign1_canonical.dat b/rust/attest/tests/data/cose_sign1_canonical.dat
new file mode 100644
index 0000000000..5b3b085882
Binary files /dev/null and b/rust/attest/tests/data/cose_sign1_canonical.dat differ
diff --git a/rust/attest/tests/data/test_cose_sign1_01.dat b/rust/attest/tests/data/test_cose_sign1_01.dat
new file mode 100644
index 0000000000..db66f287f1
Binary files /dev/null and b/rust/attest/tests/data/test_cose_sign1_01.dat differ
diff --git a/rust/attest/tests/data/test_cose_sign1_02.dat b/rust/attest/tests/data/test_cose_sign1_02.dat
new file mode 100644
index 0000000000..9a84d30419
Binary files /dev/null and b/rust/attest/tests/data/test_cose_sign1_02.dat differ
diff --git a/rust/bridge/ffi/Cargo.toml b/rust/bridge/ffi/Cargo.toml
index 35fd71c4eb..18ed51f55b 100644
--- a/rust/bridge/ffi/Cargo.toml
+++ b/rust/bridge/ffi/Cargo.toml
@@ -5,7 +5,7 @@
[package]
name = "libsignal-ffi"
-version = "0.31.0"
+version = "0.32.1"
authors = ["Signal Messenger LLC"]
edition = "2018"
license = "AGPL-3.0-only"
@@ -15,9 +15,6 @@ name = "signal_ffi"
crate-type = ["staticlib"]
[features]
-default = ["armv8"]
-armv8 = ["libsignal-protocol/armv8", "signal-crypto/armv8"]
-
# Testing the Swift side of this requires compiling with SIGNAL_MEDIA_SUPPORTED enabled for both Swift and C:
# swift test -Xswiftc -DSIGNAL_MEDIA_SUPPORTED -Xcc -DSIGNAL_MEDIA_SUPPORTED
signal-media = ["libsignal-bridge/signal-media"]
diff --git a/rust/bridge/ffi/src/lib.rs b/rust/bridge/ffi/src/lib.rs
index 23e01133b6..81b2d8c04d 100644
--- a/rust/bridge/ffi/src/lib.rs
+++ b/rust/bridge/ffi/src/lib.rs
@@ -171,7 +171,7 @@ pub unsafe extern "C" fn signal_sealed_session_cipher_decrypt(
let mut identity_store = identity_store.as_ref().ok_or(SignalFfiError::NullPointer)?;
let mut session_store = session_store.as_ref().ok_or(SignalFfiError::NullPointer)?;
let mut prekey_store = prekey_store.as_ref().ok_or(SignalFfiError::NullPointer)?;
- let mut signed_prekey_store = signed_prekey_store
+ let signed_prekey_store = signed_prekey_store
.as_ref()
.ok_or(SignalFfiError::NullPointer)?;
@@ -188,7 +188,7 @@ pub unsafe extern "C" fn signal_sealed_session_cipher_decrypt(
&mut identity_store,
&mut session_store,
&mut prekey_store,
- &mut signed_prekey_store,
+ &signed_prekey_store,
&mut kyber_pre_key_store,
)
.now_or_never()
diff --git a/rust/bridge/jni/Cargo.toml b/rust/bridge/jni/Cargo.toml
index d24ddd3d24..303bfd3357 100644
--- a/rust/bridge/jni/Cargo.toml
+++ b/rust/bridge/jni/Cargo.toml
@@ -5,7 +5,7 @@
[package]
name = "libsignal-jni"
-version = "0.31.0"
+version = "0.32.1"
authors = ["Signal Messenger LLC"]
edition = "2018"
license = "AGPL-3.0-only"
@@ -14,17 +14,13 @@ license = "AGPL-3.0-only"
name = "signal_jni"
crate-type = ["cdylib"]
-[features]
-default = ["armv8"]
-armv8 = ["libsignal-protocol/armv8", "signal-crypto/armv8"]
-
[dependencies]
libsignal-protocol = { path = "../../protocol" }
signal-crypto = { path = "../../crypto" }
libsignal-bridge = { path = "../shared", features = ["jni", "signal-media"] }
async-trait = "0.1.41"
cfg-if = "1.0.0"
-jni = "0.19.0"
+jni = "0.21.0"
rand = "0.8"
log = "0.4"
log-panics = { version = "2.1.0", features = ["with-backtrace"] }
diff --git a/rust/bridge/jni/bin/gen_java_decl.py b/rust/bridge/jni/bin/gen_java_decl.py
index 76884ab6ac..13bced5d0a 100755
--- a/rust/bridge/jni/bin/gen_java_decl.py
+++ b/rust/bridge/jni/bin/gen_java_decl.py
@@ -62,15 +62,13 @@ def print_usage_and_exit():
def translate_to_java(typ):
- # jobject as a return type is not given here; instead use a type
type_map = {
"void": "void",
- "jstring": "String",
"JString": "String",
"JObject": "Object",
"JClass": "Class",
- "jbyteArray": "byte[]",
- "jlongArray": "long[]",
+ "JByteArray": "byte[]",
+ "JLongArray": "long[]",
"ObjectHandle": "long",
"jint": "int",
"jlong": "long",
@@ -81,8 +79,6 @@ def translate_to_java(typ):
return type_map[typ]
# Assume anything prefixed with "Java" refers to an object
- if typ.startswith('JavaReturn'):
- return typ[10:]
if typ.startswith('Java'):
return typ[4:]
diff --git a/rust/bridge/jni/src/lib.rs b/rust/bridge/jni/src/lib.rs
index 66b8129c1e..552266db22 100644
--- a/rust/bridge/jni/src/lib.rs
+++ b/rust/bridge/jni/src/lib.rs
@@ -6,8 +6,7 @@
#![allow(clippy::missing_safety_doc)]
#![deny(clippy::unwrap_used)]
-use jni::objects::{JClass, JObject};
-use jni::sys::{jbyteArray, jlongArray};
+use jni::objects::{JByteArray, JClass, JLongArray, JObject};
use jni::JNIEnv;
use std::convert::TryFrom;
@@ -17,21 +16,23 @@ use libsignal_protocol::*;
pub mod logging;
#[no_mangle]
-pub unsafe extern "C" fn Java_org_signal_libsignal_internal_Native_IdentityKeyPair_1Deserialize(
- env: JNIEnv,
+pub unsafe extern "C" fn Java_org_signal_libsignal_internal_Native_IdentityKeyPair_1Deserialize<
+ 'local,
+>(
+ mut env: JNIEnv<'local>,
_class: JClass,
- data: jbyteArray,
-) -> jlongArray {
- run_ffi_safe(&env, || {
+ data: JByteArray,
+) -> JLongArray<'local> {
+ run_ffi_safe(&mut env, |env| {
let data = env.convert_byte_array(data)?;
let key = IdentityKeyPair::try_from(data.as_ref())?;
- let public_key_handle = key.identity_key().public_key().convert_into(&env)?;
- let private_key_handle = key.private_key().convert_into(&env)?;
+ let public_key_handle = key.identity_key().public_key().convert_into(env)?;
+ let private_key_handle = key.private_key().convert_into(env)?;
let tuple = [public_key_handle, private_key_handle];
let result = env.new_long_array(2)?;
- env.set_long_array_region(result, 0, &tuple)?;
+ env.set_long_array_region(&result, 0, &tuple)?;
Ok(result)
})
}
diff --git a/rust/bridge/jni/src/logging.rs b/rust/bridge/jni/src/logging.rs
index 12bdde4641..2859a58f0c 100644
--- a/rust/bridge/jni/src/logging.rs
+++ b/rust/bridge/jni/src/logging.rs
@@ -40,7 +40,7 @@ impl From for jint {
}
}
-impl From for JValue<'_> {
+impl From for JValue<'_, '_> {
fn from(level: JavaLogLevel) -> Self {
Self::Int(level.into())
}
@@ -73,7 +73,7 @@ impl JniLogger {
}
fn log_impl(&self, record: &log::Record) -> jni::errors::Result<()> {
- let env = self.vm.attach_current_thread()?;
+ let mut env = self.vm.attach_current_thread()?;
let level: JavaLogLevel = record.level().into();
let message = format!(
"{}:{}: {}",
@@ -81,10 +81,12 @@ impl JniLogger {
record.line().unwrap_or(0),
record.args(),
);
+ let message = env.new_string(message)?;
+ let module = env.new_string("libsignal")?;
let args = jni_args!((
level.into() => int,
- env.new_string("libsignal")? => java.lang.String,
- env.new_string(message)? => java.lang.String,
+ module => java.lang.String,
+ message => java.lang.String,
) -> void);
let result = env.call_static_method(&self.logger_class, "log", args.sig, &args.args);
diff --git a/rust/bridge/node/Cargo.toml b/rust/bridge/node/Cargo.toml
index 53f3eff3ee..6241cc9b2b 100644
--- a/rust/bridge/node/Cargo.toml
+++ b/rust/bridge/node/Cargo.toml
@@ -5,7 +5,7 @@
[package]
name = "libsignal-node"
-version = "0.31.0"
+version = "0.32.1"
authors = ["Signal Messenger LLC"]
license = "AGPL-3.0-only"
edition = "2018"
@@ -14,10 +14,6 @@ edition = "2018"
name = "signal_node"
crate-type = ["cdylib"]
-[features]
-default = ["armv8"]
-armv8 = ["libsignal-protocol/armv8", "libsignal-bridge/armv8"]
-
[dependencies]
libsignal-protocol = { path = "../../protocol" }
libsignal-bridge = { path = "../shared", features = ["node", "signal-media"] }
diff --git a/rust/bridge/node/futures/tests-node-module/src/store_like.rs b/rust/bridge/node/futures/tests-node-module/src/store_like.rs
index 25de6fca44..0adc7f220c 100644
--- a/rust/bridge/node/futures/tests-node-module/src/store_like.rs
+++ b/rust/bridge/node/futures/tests-node-module/src/store_like.rs
@@ -51,7 +51,7 @@ impl Finalize for NameStore {
}
}
-async fn double_name_from_store_impl(store: &mut NameStore) -> Result {
+async fn double_name_from_store_impl(store: &NameStore) -> Result {
Ok(format!(
"{0} {1}",
store.get_name().await?,
@@ -62,10 +62,10 @@ async fn double_name_from_store_impl(store: &mut NameStore) -> Result Promise }): Promise
pub fn double_name_from_store(mut cx: FunctionContext) -> JsResult {
let js_store = cx.argument(0)?;
- let mut store = NameStore::new(&mut cx, js_store);
+ let store = NameStore::new(&mut cx, js_store);
promise(&mut cx, async move {
- let future = AssertUnwindSafe(double_name_from_store_impl(&mut store));
+ let future = AssertUnwindSafe(double_name_from_store_impl(&store));
let result = future.await;
settle_promise(move |cx| {
store.finalize(cx);
@@ -77,7 +77,7 @@ pub fn double_name_from_store(mut cx: FunctionContext) -> JsResult {
})
}
-async fn double_name_from_store_using_join_impl(store: &mut NameStore) -> Result {
+async fn double_name_from_store_using_join_impl(store: &NameStore) -> Result {
let names = try_join!(store.get_name(), store.get_name())?;
Ok(format!("{0} {1}", names.0, names.1))
}
@@ -85,10 +85,10 @@ async fn double_name_from_store_using_join_impl(store: &mut NameStore) -> Result
// function doubleNameFromStoreUsingJoin(store: { getName: () => Promise }): Promise
pub fn double_name_from_store_using_join(mut cx: FunctionContext) -> JsResult {
let js_store = cx.argument(0)?;
- let mut store = NameStore::new(&mut cx, js_store);
+ let store = NameStore::new(&mut cx, js_store);
promise(&mut cx, async move {
- let future = AssertUnwindSafe(double_name_from_store_using_join_impl(&mut store));
+ let future = AssertUnwindSafe(double_name_from_store_using_join_impl(&store));
let result = future.await;
settle_promise(move |cx| {
store.finalize(cx);
diff --git a/rust/bridge/shared/Cargo.toml b/rust/bridge/shared/Cargo.toml
index 30aa390093..62664f60ca 100644
--- a/rust/bridge/shared/Cargo.toml
+++ b/rust/bridge/shared/Cargo.toml
@@ -23,13 +23,12 @@ libsignal-bridge-macros = { path = "macros" }
signal-chat = { path = "../../chat" }
signal-grpc = { path = "../../grpc" }
signal-quic = { path = "../../quic" }
-aes-gcm-siv = "0.10.1"
+aes-gcm-siv = "0.11.1"
async-trait = "0.1.41"
bincode = "1.0"
futures-util = "0.3.7"
hkdf = "0.12"
hmac = "0.12.0"
-typenum = "1.12.0"
log = "0.4"
paste = "1.0"
rand = "0.8"
@@ -41,14 +40,12 @@ uuid = "1.1.2"
bytemuck = { version = "1.13.0", optional = true }
libc = { version = "0.2", optional = true }
-jni_crate = { version = "0.19", package = "jni", optional = true }
+jni = { version = "0.21", package = "jni", optional = true }
neon = { version = "0.10.0", optional = true, default-features = false, features = ["napi-6", "promise-api"] }
linkme = { version = "0.3.9", optional = true }
signal-neon-futures = { path = "../node/futures", optional = true }
[features]
-default = ["armv8"]
ffi = ["libc", "libsignal-bridge-macros/ffi"]
-jni = ["jni_crate", "libsignal-bridge-macros/jni", "bytemuck"]
+jni = ["dep:jni", "libsignal-bridge-macros/jni", "bytemuck"]
node = ["neon", "linkme", "signal-neon-futures", "libsignal-bridge-macros/node"]
-armv8 = ["aes-gcm-siv/armv8", "libsignal-protocol/armv8", "signal-crypto/armv8"]
diff --git a/rust/bridge/shared/macros/src/jni.rs b/rust/bridge/shared/macros/src/jni.rs
index 1a52169086..1f3aee7fd0 100644
--- a/rust/bridge/shared/macros/src/jni.rs
+++ b/rust/bridge/shared/macros/src/jni.rs
@@ -48,8 +48,8 @@ pub(crate) fn bridge_fn(name: String, sig: &Signature, result_kind: ResultKind)
name.ident.clone(),
quote!(#(#attrs)* #name #colon_token jni_arg_type!(#ty)),
quote! {
- let mut #name = <#ty as jni::ArgTypeInfo>::borrow(&env, #name)?;
- let #name = <#ty as jni::ArgTypeInfo>::load_from(&env, &mut #name)?
+ let mut #name = <#ty as jni::ArgTypeInfo>::borrow(env, name)?;
+ let #name = <#ty as jni::ArgTypeInfo>::load_from(&mut #name)
},
)
} else {
@@ -68,16 +68,16 @@ pub(crate) fn bridge_fn(name: String, sig: &Signature, result_kind: ResultKind)
quote! {
#[no_mangle]
- pub unsafe extern "C" fn #name(
- env: jni::JNIEnv,
+ pub unsafe extern "C" fn #name<'local>(
+ mut env: jni::JNIEnv<'local>,
_class: jni::JClass,
#(#input_args),*
) #output {
- jni::run_ffi_safe(&env, || {
+ jni::run_ffi_safe(&mut env, |env| {
#(#input_processing);*;
let __result = #orig_name(#(#input_names),*);
#await_if_needed;
- jni::ResultTypeInfo::convert_into(__result, &env)
+ jni::ResultTypeInfo::convert_into(__result, env)
})
}
}
diff --git a/rust/bridge/shared/macros/src/lib.rs b/rust/bridge/shared/macros/src/lib.rs
index 285231696a..bfd2041f3f 100644
--- a/rust/bridge/shared/macros/src/lib.rs
+++ b/rust/bridge/shared/macros/src/lib.rs
@@ -219,7 +219,7 @@ fn bridge_fn_impl(attr: TokenStream, item: TokenStream, result_kind: ResultKind)
let node_fn = node_name.map(|name| node::bridge_fn(name, &function.sig, result_kind));
quote!(
- #[allow(non_snake_case)]
+ #[allow(non_snake_case, clippy::needless_pass_by_ref_mut)]
#[cfg(any(#(#feature_list,)*))]
#[inline(always)]
#function
diff --git a/rust/bridge/shared/src/crypto.rs b/rust/bridge/shared/src/crypto.rs
index d0679242e8..a3d245d15f 100644
--- a/rust/bridge/shared/src/crypto.rs
+++ b/rust/bridge/shared/src/crypto.rs
@@ -8,7 +8,7 @@ use libsignal_bridge_macros::*;
use signal_crypto::*;
use aes_gcm_siv::aead::generic_array::typenum::Unsigned;
-use aes_gcm_siv::aead::{AeadCore, AeadInPlace, NewAead};
+use aes_gcm_siv::{AeadCore, AeadInPlace, KeyInit};
use crate::support::*;
use crate::*;
diff --git a/rust/bridge/shared/src/ffi/convert.rs b/rust/bridge/shared/src/ffi/convert.rs
index a1aa739d75..ea28f2f57d 100644
--- a/rust/bridge/shared/src/ffi/convert.rs
+++ b/rust/bridge/shared/src/ffi/convert.rs
@@ -307,78 +307,10 @@ store!(SignedPreKeyStore);
store!(KyberPreKeyStore);
store!(InputStream);
-impl ResultTypeInfo for Result {
- type ResultType = T::ResultType;
- fn convert_into(self) -> SignalFfiResult {
- T::convert_into(self?)
- }
-}
-
-impl ResultTypeInfo for Result {
- type ResultType = T::ResultType;
- fn convert_into(self) -> SignalFfiResult {
- T::convert_into(self?)
- }
-}
-
-impl ResultTypeInfo for Result {
- type ResultType = T::ResultType;
- fn convert_into(self) -> SignalFfiResult {
- T::convert_into(self?)
- }
-}
-
-impl ResultTypeInfo for Result {
- type ResultType = T::ResultType;
- fn convert_into(self) -> SignalFfiResult {
- T::convert_into(self?)
- }
-}
-
-impl ResultTypeInfo for Result {
- type ResultType = T::ResultType;
- fn convert_into(self) -> SignalFfiResult {
- T::convert_into(self?)
- }
-}
-
-#[cfg(feature = "signal-media")]
-impl ResultTypeInfo for Result {
- type ResultType = T::ResultType;
- fn convert_into(self) -> SignalFfiResult {
- T::convert_into(self?)
- }
-}
-
-impl ResultTypeInfo for Result {
- type ResultType = T::ResultType;
- fn convert_into(self) -> SignalFfiResult {
- T::convert_into(self?)
- }
-}
-
-impl ResultTypeInfo for Result {
- type ResultType = T::ResultType;
- fn convert_into(self) -> SignalFfiResult {
- T::convert_into(self?)
- }
-}
-
-impl ResultTypeInfo for Result {
- type ResultType = T::ResultType;
- fn convert_into(self) -> SignalFfiResult {
- T::convert_into(self?)
- }
-}
-
-impl ResultTypeInfo for Result {
- type ResultType = T::ResultType;
- fn convert_into(self) -> SignalFfiResult {
- T::convert_into(self?)
- }
-}
-
-impl ResultTypeInfo for Result {
+impl ResultTypeInfo for Result
+where
+ SignalFfiError: From,
+{
type ResultType = T::ResultType;
fn convert_into(self) -> SignalFfiResult {
T::convert_into(self?)
diff --git a/rust/bridge/shared/src/incremental_mac.rs b/rust/bridge/shared/src/incremental_mac.rs
index e9d2fb5340..0dc620b4f9 100644
--- a/rust/bridge/shared/src/incremental_mac.rs
+++ b/rust/bridge/shared/src/incremental_mac.rs
@@ -7,8 +7,8 @@ use hmac::digest::{crypto_common, OutputSizeUser};
use std::convert::TryInto;
use crypto_common::KeyInit;
+use hmac::digest::typenum::Unsigned;
use hmac::Hmac;
-use typenum::Unsigned;
use libsignal_bridge_macros::*;
use libsignal_protocol::incremental_mac::{calculate_chunk_size, Incremental, Validating};
@@ -84,23 +84,27 @@ pub fn ValidatingMac_Update(
bytes: &[u8],
offset: u32,
length: u32,
-) -> bool {
+) -> i32 {
let offset = offset as usize;
let length = length as usize;
mac.0
.as_mut()
.expect("MAC used after finalize")
.update(&bytes[offset..][..length])
- .is_ok()
+ .ok()
+ .and_then(|n| n.try_into().ok())
+ .unwrap_or(-1)
}
#[bridge_fn]
-pub fn ValidatingMac_Finalize(mac: &mut ValidatingMac) -> bool {
+pub fn ValidatingMac_Finalize(mac: &mut ValidatingMac) -> i32 {
mac.0
.take()
.expect("MAC used after finalize")
.finalize()
- .is_ok()
+ .ok()
+ .and_then(|n| n.try_into().ok())
+ .unwrap_or(-1)
}
impl Drop for IncrementalMac {
@@ -111,14 +115,6 @@ impl Drop for IncrementalMac {
}
}
-impl Drop for ValidatingMac {
- fn drop(&mut self) {
- if self.0.is_some() {
- report_unexpected_drop()
- }
- }
-}
-
static UNEXPECTED_DROP_MESSAGE: &str = "MAC is dropped without calling finalize";
fn report_unexpected_drop() {
diff --git a/rust/bridge/shared/src/jni/args.rs b/rust/bridge/shared/src/jni/args.rs
index 083ea96fcb..bf1c86de7c 100644
--- a/rust/bridge/shared/src/jni/args.rs
+++ b/rust/bridge/shared/src/jni/args.rs
@@ -5,7 +5,7 @@
use std::marker::PhantomData;
-use jni_crate::objects::JValue;
+use jni::objects::{JObject, JValue};
/// Takes a Java-esque class name of the form `org.signal.Outer::Inner` and turns it into a
/// JNI-style name `org/signal/Outer$Inner`.
@@ -153,7 +153,7 @@ macro_rules! jni_arg {
};
// Assume anything else is an object. This includes arrays and classes.
( $arg:expr => $($_:tt)+) => {
- JValue::Object($arg.into())
+ JValue::Object($arg.as_ref())
};
}
@@ -169,7 +169,7 @@ fn test_jni_arg() {
assert!(matches!(jni_arg!(-8.5 => float), JValue::Float(val) if val == -8.5));
assert!(matches!(jni_arg!(-8.5 => double), JValue::Double(val) if val == -8.5));
assert!(matches!(
- jni_arg!(jni_crate::objects::JObject::null() => java.lang.Object),
+ jni_arg!(jni::objects::JObject::null() => java.lang.Object),
JValue::Object(val) if val.is_null()
));
}
@@ -222,20 +222,36 @@ pub type PhantomReturnType = PhantomData R>;
/// A JNI argument list, type-checked with its signature.
#[derive(Debug, Clone, Copy)]
-pub struct JniArgs<'a, R, const LEN: usize> {
+pub struct JniArgs<'local, 'obj_ref, R, const LEN: usize> {
pub sig: &'static str,
- pub args: [JValue<'a>; LEN],
+ pub args: [JValue<'local, 'obj_ref>; LEN],
pub _return: PhantomReturnType,
}
+impl<'local, 'obj_ref, 'output, const LEN: usize> JniArgs<'local, 'obj_ref, JObject<'output>, LEN> {
+ /// Updates the lifetime of the return type.
+ ///
+ /// May be necessary when passing JniArgs into a "local frame"
+ /// ([`jni::JNIEnv::with_local_frame`]).
+ pub fn for_nested_frame<'new_output: 'output>(
+ self,
+ ) -> JniArgs<'local, 'obj_ref, JObject<'new_output>, LEN> {
+ JniArgs {
+ sig: self.sig,
+ args: self.args,
+ _return: PhantomData,
+ }
+ }
+}
+
/// Produces a JniArgs struct from the given arguments and return type.
///
/// # Example
///
/// ```
/// # use libsignal_bridge::jni_args;
-/// # use jni_crate::objects::JValue;
-/// # let name = jni_crate::objects::JObject::null();
+/// # use jni::objects::JValue;
+/// # let name = jni::objects::JObject::null();
/// let args = jni_args!((name => java.lang.String, 0x3FFF => short) -> void);
/// assert_eq!(args.sig, "(Ljava/lang/String;S)V");
/// assert_eq!(args.args.len(), 2);
@@ -258,3 +274,6 @@ macro_rules! jni_args {
}
}
}
+// Expose this for doc comments.
+#[cfg(doc)]
+use jni_args;
diff --git a/rust/bridge/shared/src/jni/convert.rs b/rust/bridge/shared/src/jni/convert.rs
index 3e88f612ad..785dfa1944 100644
--- a/rust/bridge/shared/src/jni/convert.rs
+++ b/rust/bridge/shared/src/jni/convert.rs
@@ -3,7 +3,6 @@
// SPDX-License-Identifier: AGPL-3.0-only
//
-use jni::objects::{JObject, JString};
use jni::sys::{jbyte, JNI_FALSE, JNI_TRUE};
use jni::JNIEnv;
use libsignal_protocol::*;
@@ -25,37 +24,42 @@ use super::*;
///
/// ```no_run
/// # use libsignal_bridge::jni::*;
-/// # use jni_crate::JNIEnv;
+/// # use jni::JNIEnv;
/// # struct Foo;
/// # impl SimpleArgTypeInfo<'_> for Foo {
/// # type ArgType = isize;
-/// # fn convert_from(env: &JNIEnv, foreign: isize) -> SignalJniResult { Ok(Foo) }
+/// # fn convert_from(env: &mut JNIEnv, foreign: &isize) -> SignalJniResult { Ok(Foo) }
/// # }
-/// # fn test(env: &JNIEnv, jni_arg: isize) -> SignalJniResult<()> {
-/// let mut jni_arg_borrowed = Foo::borrow(env, jni_arg)?;
-/// let rust_arg = Foo::load_from(env, &mut jni_arg_borrowed)?;
+/// # fn test(env: &mut JNIEnv, jni_arg: isize) -> SignalJniResult<()> {
+/// let mut jni_arg_borrowed = Foo::borrow(env, &jni_arg)?;
+/// let rust_arg = Foo::load_from(&mut jni_arg_borrowed);
/// # Ok(())
/// # }
/// ```
///
/// The `'context` lifetime allows for borrowed values to depend on the current JNI stack frame;
-/// that is, they can be assured that referenced objects will not be GC'd out from under them.
+/// that is, they can be assured that referenced objects will not be GC'd out from under them. The
+/// `'param` lifetime allows for depending on the current *Rust* stack frame, which is necessary for
+/// some `JNIEnv` APIs.
///
/// `ArgTypeInfo` is used to implement the `bridge_fn` macro, but can also be used outside it.
///
-/// If the Rust type can be directly loaded from `ArgType` with no local storage needed,
-/// implement [`SimpleArgTypeInfo`] instead.
+/// If the Rust type can be directly loaded from `ArgType` with no local storage needed, implement
+/// [`SimpleArgTypeInfo`] instead.
///
/// Implementers should also see the `jni_arg_type` macro in `convert.rs`.
-pub trait ArgTypeInfo<'storage, 'context: 'storage>: Sized {
+pub trait ArgTypeInfo<'storage, 'param: 'storage, 'context: 'param>: Sized {
/// The JNI form of the argument (e.g. `jni::jint`).
- type ArgType;
+ type ArgType: 'param;
/// Local storage for the argument (ideally borrowed rather than copied).
type StoredType: 'storage;
/// "Borrows" the data in `foreign`, usually to establish a local lifetime or owning type.
- fn borrow(env: &'context JNIEnv, foreign: Self::ArgType) -> SignalJniResult;
+ fn borrow(
+ env: &mut JNIEnv<'context>,
+ foreign: &'param Self::ArgType,
+ ) -> SignalJniResult;
/// Loads the Rust value from the data that's been `stored` by [`borrow()`](Self::borrow()).
- fn load_from(env: &JNIEnv, stored: &'storage mut Self::StoredType) -> SignalJniResult;
+ fn load_from(stored: &'storage mut Self::StoredType) -> Self;
}
/// A simpler interface for [`ArgTypeInfo`] for when no local storage is needed.
@@ -64,19 +68,19 @@ pub trait ArgTypeInfo<'storage, 'context: 'storage>: Sized {
///
/// ```no_run
/// # use libsignal_bridge::jni::*;
-/// # use jni_crate::objects::JObject;
-/// # use jni_crate::JNIEnv;
+/// # use jni::objects::JObject;
+/// # use jni::JNIEnv;
/// # struct Foo;
/// impl<'a> SimpleArgTypeInfo<'a> for Foo {
/// type ArgType = JObject<'a>;
-/// fn convert_from(env: &JNIEnv, foreign: JObject<'a>) -> SignalJniResult {
+/// fn convert_from(env: &mut JNIEnv, foreign: &JObject<'a>) -> SignalJniResult {
/// // ...
/// # Ok(Foo)
/// }
/// }
///
-/// # fn test<'a>(env: &JNIEnv<'a>, jni_arg: JObject<'a>) -> SignalJniResult<()> {
-/// let rust_arg = Foo::convert_from(env, jni_arg)?;
+/// # fn test<'a>(env: &mut JNIEnv<'a>, jni_arg: JObject<'a>) -> SignalJniResult<()> {
+/// let rust_arg = Foo::convert_from(env, &jni_arg)?;
/// # Ok(())
/// # }
/// ```
@@ -84,24 +88,25 @@ pub trait ArgTypeInfo<'storage, 'context: 'storage>: Sized {
/// However, some types do need the full flexibility of `ArgTypeInfo`.
pub trait SimpleArgTypeInfo<'a>: Sized {
/// The JNI form of the argument (e.g. `jint`).
- ///
- /// Must be [`Copy`] to help the compiler optimize out local storage.
- type ArgType: Copy + 'a;
+ type ArgType: 'a;
/// Converts the data in `foreign` to the Rust type.
- fn convert_from(env: &JNIEnv, foreign: Self::ArgType) -> SignalJniResult;
+ fn convert_from(env: &mut JNIEnv<'a>, foreign: &Self::ArgType) -> SignalJniResult;
}
-impl<'a, T> ArgTypeInfo<'a, 'a> for T
+impl<'storage, 'param: 'storage, 'context: 'param, T> ArgTypeInfo<'storage, 'param, 'context> for T
where
- T: SimpleArgTypeInfo<'a>,
+ T: SimpleArgTypeInfo<'context> + 'storage,
{
- type ArgType =