This is a variant of AuthCredential that carries two UUIDs, intended
to be a user's ACI and PNI. Why? Because when you've been invited to a
group, you may have been invited by your ACI or by your PNI, or by
both, and it's easier for clients to treat all those states the same
by having a credential that covers both identities. The downside is
that it's larger (both the data, obviously, but also the zkgroup proof
of validity, unsurprisingly).
AnyAuthCredentialPresentation gains a 'get_pni_ciphertext' method,
which will return `None` for the existing presentations and
`Some(encrypted_pni)` for the new credential. Having a separate
credential type but a common presentation type makes it easier for the
server to handle all possible credentials uniformly.
This term is unnecessary after all (the value of 'z' is already fixed
by the equation "Z = I^z"). We can't remove it from earlier proofs
because that would change the format, but going forward we don't need
it.
Without this, two ByteArray types without any additional operations
are structurally equivalent, and so TypeScript permits passing one as
the other. (Thanks, Fedor!)
Like ProfileKeyCredential, but with an expiration timestamp embedded
in it. This has its own credential type and response type, but uses
the same request type as a "classic" ProfileKeyCredential, and
generates presentations usable with AnyProfileKeyCredential-
Presentation, so that existing server code accepting presentations
will automatically do the right thing.
Adoption for servers:
- Update secret params
- When presentations are saved in group state, use
ProfileKeyCredentialPresentation.getStructurallyValidV1PresentationBytes()
to maintain backwards compatibility with existing clients.
- Add an endpoint to issue ExpiringProfileKeyCredentials
- (future) Remove the endpoint that issues regular ProfileKeyCredentials
Adoption for clients, after the server has updated:
- Update public params
- Start fetching and using ExpiringProfileKeyCredentials instead of
regular ProfileKeyCredentials (the old endpoint will eventually
go away)
- Node: To bring types into harmony, a receipt's expiration time has
been changed to a `number` instead of a `bigint`
This trades speed for size around certain elliptic curve operations in
BoringSSL. We're using boring mostly for verifying certificates, not
the many many curve operations we do on a per-message basis, so for
now the code size is more important.
"RedemptionTime" becomes "CoarseRedemptionTime", highlighting its
measurement in days.
"ReceiptExpirationTime" becomes "Timestamp", highlighting its
forthcoming generalized use beyond receipts and it being the preferred
type going forward.
Upcoming work in `attest` requires additional X509 support, and swapping these libraries
is a negligible impact on binary size. This uses a fork of `cloudflare/boring`, as
we have some additions that haven’t yet been contributed upstream.
...which drops our dependency on Electron altogether. We originally
tested with electron-mocha to more closely resemble the Desktop app,
but libsignal-client doesn't actually use anything Electron-specific,
and because it uses N-API we don't have to sync up versions exactly
(and indeed we haven't been updating the Electron in this repo as
often as the Desktop app has taken new Electrons).
Two benefits of this: you can now run the tests on headless systems
(see the change to the CI script), and `yarn install` has less to
download.
- Update .nvmrc to match Desktop
- Update electron, electron-mocha, and typescript to match Desktop
- Update indirect dependency 'minimist' per `yarn audit`
In signal-neon-futures test package:
- Update mocha
- `yarn upgrade` to clear audit advisories
Optimize presentation of credentials (AuthCredentialPresentationV2, ProfileKeyCredentialPresentationV2, PniCredentialPresentationV2). Server will accept V1 or V2 presentations. Clients will produce V2.
Various improvements to FFI to support this, and some minor optimizations (in particular "lazy statics" to avoid redundant loading of SystemParams).
Similar to the previous commit, this would make sense if we lazily
deserialized these types, but we don't. It's faster to clone them
structurally in Rust than to serialize and deserialize them.
At one point we experimented with Java's SignalProtocolAddress only
wrapping a String + integer, rather than a boxed Rust handle, but we
gave that up because it was more difficult to pass them across the
bridge. That means there's no longer a need to go through
SignalProtocolAddress's main constructor when trying to box one from
Rust.
This was previously necessary because the Linux implementation of
SwiftPM+XCTest didn't support automatic test discovery, but that's no
longer a problem with newer versions of Swift.
The main advantage here is that we don't need any dependencies from
the unstable repo, which means we can be sure that the glibc version
we build against is suitable for Buster instead of being pulled in
from a later train. (We can't do this for Stretch because Stretch is
too old for all our build tools.)
While here, simplify the build a little bit: we're already using
snapshots of the Debian repo, so drop the separate file for pinned
dependencies.
Previously the project would error out during the configuration stage,
since the Android Gradle plugin requires JDK 11 to even load. Now it
throws an error if you try to build a top-level task or a task in the
Android subproject, but allows you to build, e.g. 'client:test' with
no problems.
This helper task was supposed to only execute when publishing the
client or server artifacts, but at the point where that was checked
the task graph *hasn't been built yet*. Instead, add the task to the
task graph unconditionally, but disable it by default, and have its
dependents enable it only when publishing.
In Java these are subclasses of IllegalStateException, a
RuntimeException, so that every session operation isn't annotated as
throwing InvalidSessionException. Swift and TypeScript don't have
typed errors, so they're just additional specific cases that can be
caught.
Similar to the previous commit, this makes crate-internal operations
use a dedicated error type, or not produce an error at all, in order
to make sure that errors for invalid sessions always have the
distribution ID attached.
Anything that stays within the crate gets a dedicated error type, or
no error at all if the operation cannot actually fail. The "defensive"
signatures remain for public operations.
Apart from making 'Result' more meaningful, this also keeps from
propagating low-level errors out that really indicate a corrupt
session.