Registration IDs are used to detect if a device ID has been reused,
since the new device will (with high probability) use a different
randomly-generated registration ID from the old one. The server should
be able to validate this for SSv2 like it does for SSv1, though the
handling of this for SSv1 is in the various apps.
...similar to what we have for 1:1 session encrypt/decrypt. There's a
little less here because SenderKey sessions are one-sided and so they
can't get out of sync the same way.
- Add module docs for the `libsignal_protocol` crate!
- Add docs to the `device-transfer` crate!
- Add docs to `address`!
beef up the docs for `address` because this is an important struct!
respond to review comments
revert module visibility changes
de-clutter the docstring for `.device_id()`
add missing docs warning
fix uuid deps
add doctest for `ProtocolAddress::new()`!
avoid pulling in uuid into dev-dependencies
We still encode the "current" version in the message version byte, but
the part that the receiver will check is now based on the session's
original message version rather than the "current" version in the
sender. (Note that these are the /same/ version right now, so this
change won't have any effect on the current wire format.)
This matches the behavior of SignalMessage and PreKeySignalMessage.
The parameters for these constructors cannot be chosen correctly in
isolation; messages always need to be created as part of a session.
The Node APIs have been renamed with leading underscores rather than
removed because we *did* have tests that explicitly constructed
messages just to test that they faithfully preserve information. In
this case the parameters are plausible values but not used for
anything.
...or it should fail to decrypt. This parallels a similar check for
SignalMessage and SessionState. Since we haven't been storing this
field previously, treat a default "0" value as if it were version 3,
the current version.
...but wait, why is version 3 the current version? Historical
accident: we were reusing the version values from SignalMessages,
which currently only support version 3. This isn't unreasonable since
the SenderKey cipher is based on the usual session cipher, but that's
not enough reason to tie the two version numbers together in the
future. Stop doing that here.
Node can more efficiently handle multiple tasks coming in on the same
queue, so remove the "convenience" APIs that derive a new queue from a
Context, and require an existing EventQueue instead. This cuts more
time off of our decryption benchmark (not checked in).
Additionally, run the first poll for the future synchronously, to
avoid having to wait for the event loop to pick up the task to start
the future.
This was MessageCounterError in libtextsecure; it's an "error" in that
it interrupts processing of an individual message, but that message
is then be discarded in practice.
This joins the logging for when the session cipher fails; when pre-key
processing fails (especially with a "no such pre-key" error), we want
to see what state the session's in.
Debian has a more stable retention period for pinned dependencies (the
version of OpenJDK 8 we were using for Ubuntu is gone already!), and
it matches what the Signal-Android repository is doing.
For some reason, the Docker build of libsignal_jni.so doesn't link to
libdl, even though the build on my local machine does. This doesn't
seem to be a problem on most phones, presumably because the libdl
functions are re-exported through libc. However, on a small subset of
Android phones this is not good enough and libsignal_jni.so fails to
load. For now, work around this by forcing the Android
cross-compilation linker to link to libdl (instead of doing it "as
needed").
It turns out this takes less than a millisecond, at least when the
event loop is empty, but the setup might still be useful in the
future. Run with `cargo bench -p signal-neon-futures`.
Also, if the library somehow isn't built when used as a non-local
CocoaPods dependency, don't suggest running swift/build_ffi.sh;
CocoaPods will have removed it already. Re-running `pod install` is
more likely to help, though in practice something's probably gone
wrong in the configuration.
Within a new 'Errors' module, we have a base class that indicates this
is a strongly-typed error, and an enum to identify what kind of error
it is and thus what extra properties it might have. TypeScript's type
narrowing support make this possible to do safely as long as all
instances of the base class do in fact have the extra properties that
match their code (and do not have an invalid code).
To expose this to Rust (via Neon):
- After loading the Rust library into Node, set an 'Errors' property
with the relevant error types on the module object.
- Whenever a bridge_fn produces an error, pass it to a new
SignalNodeError::throw API along with the 'this' object, which is
assumed to have to be the object with the 'Errors' property.
This is a little less tidy than how we do Java exceptions, but it
comes from not having access to the error classes by some kind of
absolute name. Alternate approaches considered include:
- Use an initialized-once global. Downside: would not work if you ever
had more than one Node engine live in a process, or quit and restarted
it.
- Store the errors on the global object under some long, complicated
key (like "org.signal.libsignal-client.Errors"). Downside: pollutes
the global object.
- Generate the base class using Neon instead of writing it in
TypeScript. Downsides: inconvenient, difficult to maintain, harder to
use /from/ TypeScript.