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.
We're optimizing for size overhead in this encoding, so forego the
flexibility of protobufs in favor of a flat encoding (though one that
still uses protobuf's varints). Additionally, this encoding includes
the recipients inline in the message so the client can dump it all to
server in one go.
As a side effect, this means an SSv2 message encoded for sending no
longer has the same format as one encoded for receiving when there's
only one recipient. Consequently, all the tests need to be modified to
"fan out" a multi-recipient message to several single-recipient
messages. For simplicity, the wrapper language tests only support this
operation for SSv2 messages sent to exactly one recipient.
- Add a new "multi-recipient encrypt" entry point
- Add an "encrypt v1 sealed sender from UnidentifiedSenderMessage-
Content" entry point
- Add a public constructor for UnidentifiedSenderMessageContent
- Change group_encrypt to return a CiphertextMessage instead of bytes,
so it can be used with the above
- Java: add SenderKeyStore to SignalProtocolStore requirements
With distribution IDs embedded in SenderKeyMessage and
SenderKeyDistributionMessage, the abstraction of SenderKeyName (a
sender address + distribution ID tuple) is no longer pulling its
weight. Remove it from the implementation and the public API.
The distribution ID is used to identify which key a particular sender
is using to encrypt their SenderKeyMessage, so it has to be known as
part of decryption. The previous design had the distribution ID stored
alongside each message (perhaps on the "envelope" structure that's
received from the server), but that's harder to keep track of, and it
would only be present for certain message kinds anyway.
As Java has no concept of slices and we need some way of doing partial
updates, since this is required to implement the JCE Cipher interface,
and Android uses it.
Additionally, never look up a session by e164 when decrypting
sealed-sender messages.
This is an API-breaking change for both Java and Swift clients;
certain fields and arguments are no longer Optional. On top of that,
some tests may need to be updated to provide UUIDs instead of just
phone numbers.
In libsignal-protocol-java, SessionRecord holds a SesssionState struct which is
the "active" session plus a list of old states. If the record is freshly
created, there is still a SessionState, but it is an uninitialized/new protobuf
structure which causes all fields to be empty/zero/false.
So in the original Java logic you can call for example hasSenderChain, and on
an empty/fresh record it will return false. However in Rust, in this case the
Option is empty and we return an error instead.
For hasSenderChain, it seems reasonable to return false if there is no active
session, since if there is no session there is certainly no chain.
Android also expects the session version to be == 0 on such sessions, but this
makes less sense, so have this logic only in the Java binding and not in the
Rust library proper.