Skip to content

feat(chat-cipher): wrap and unwrap a private group's key - #1745

Merged
bmc08gt merged 1 commit into
code/cashfrom
feat/chat-cipher-group-key-wrap
Oct 9, 2026
Merged

bmc08gt merged 1 commit into
code/cashfrom
feat/chat-cipher-group-key-wrap

Conversation

@bmc08gt

@bmc08gt bmc08gt commented Oct 9, 2026 •

Copy link
Copy Markdown
Collaborator

Private groups store their chat key as a chat.v1.KeyEnvelope, and iOS needs the wrap from shared-core before it can build create or approve. This adds it to ChatCipher on its own so shared-core can release it; the Android create and approve flows stay on feat/private-groups.

fun newGroupKey(): ByteArray
fun wrapGroupKey(ownKeyPair: KeyPair, recipientPk: ByteArray, chatId: ByteArray, groupKey: ByteArray): EncryptedPayload
fun unwrapGroupKey(ownKeyPair: KeyPair, wrapperPk: ByteArray, chatId: ByteArray, envelope: EncryptedPayload): ByteArray

The wrap follows the X25519_XCHACHA20POLY1305 steps 1-4 in chat/v1/model.proto. It shares the DM key's X25519 + HKDF-SHA256 derivation (salt is both Ed25519 public keys in bytewise order) under the flipcash-group-key-wrap-v1 label. The AAD is label, chat id, wrapper key, then recipient key. A creator wraps for themselves by passing their own public key as recipientPk.

There are no shared vectors for the wrap yet, so GroupKeyWrapTest checks round trips and rejections (another chat, another wrapper or recipient, a short key), and that the wrapping key differs from the DM chat key, rather than fixed bytes. Once iOS has an implementation, a cross-platform vector would pin it.

FakeChatCipher in the services test fixtures implements the new methods so that module still compiles.

@bmc08gt bmc08gt self-assigned this Oct 9, 2026
@github-actions github-actions Bot added type: feature New functionality area: crypto Solana, keys, encryption, signing area: network gRPC, connectivity, API, exchange rates labels Oct 9, 2026
ChatCipher gains newGroupKey, wrapGroupKey and unwrapGroupKey for the
chat.v1.KeyEnvelope X25519_XCHACHA20POLY1305 scheme, following
chat/v1/model.proto steps 1-4. The wrap reuses the DM key's X25519 + HKDF-SHA256
steps under the flipcash-group-key-wrap-v1 label; the AAD is the label, chat id,
wrapper key, then recipient key.

There are no shared vectors for the wrap yet, so GroupKeyWrapTest checks round
trips and rejections (another chat, another wrapper or recipient, a short
key), and that the wrapping key differs from the DM chat key, rather than fixed
bytes. FakeChatCipher implements the new methods so
the services test fixtures still compile.
@bmc08gt
bmc08gt force-pushed the feat/chat-cipher-group-key-wrap branch from 48d9725 to 4b5dea2 Compare October 9, 2026 18:01
@bmc08gt
bmc08gt merged commit d2c5cb6 into code/cash Oct 9, 2026
4 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area: crypto Solana, keys, encryption, signing area: network gRPC, connectivity, API, exchange rates type: feature New functionality

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant