From 2232d026b271605fb42849bcf3388cfff14d136e Mon Sep 17 00:00:00 2001 From: Michael Xu Date: Tue, 25 Apr 2023 09:14:52 -0700 Subject: [PATCH 01/30] test: example proto to test the integration, will either override or delete --- proto/v3/message_contents/public_key.proto | 65 ++++++++++++++++++++++ 1 file changed, 65 insertions(+) create mode 100644 proto/v3/message_contents/public_key.proto diff --git a/proto/v3/message_contents/public_key.proto b/proto/v3/message_contents/public_key.proto new file mode 100644 index 00000000..d383b877 --- /dev/null +++ b/proto/v3/message_contents/public_key.proto @@ -0,0 +1,65 @@ +// Structure for representing public keys of different types, +// including signatures used to authenticate the keys. +syntax = "proto3"; + +package xmtp.v3.message_contents; + +option go_package = "github.com/xmtp/proto/v4/go/message_contents"; +option java_package = "org.xmtp.proto.v3.message.contents"; + +// An unsigned public key used by libxmtp +message VoodooUnsignedPublicKey { + uint64 created_ns = 1; + + oneof union { + VodozemacCurve25519 curve25519 = 2; + } + + // A Vodozemac curve25519 key serialized via serde + // (https://github.com/matrix-org/vodozemac/blob/ + // 929bbaf325686435bdd0ed0d0cc45b0cbad3430d/src/types/curve25519.rs#L100) + message VodozemacCurve25519 { + bytes bytes = 1; + } +} + +// A key linked to an XMTP account (e.g. signed by a wallet) +// The purpose of the key is encoded in the signature +message VoodooAccountLinkedKey { + VoodooUnsignedPublicKey key = 1; + // TODO AccountLinkedSignature signature = 2; +} + +// A key linked to a device (e.g. signed by a device identity key) +// The purpose of the key is encoded in the signature +message VoodooDeviceLinkedKey { + VoodooUnsignedPublicKey key = 1; + // TODO DeviceLinkedSignature signature = 2; +} + +// A bundle of one time keys uploaded by a client, to be used as +// input to (X)3DH exchanges with it. The server is expected to serve +// and delete one prekey to anyone who requests one. +// In our initial prototype we will not actually use one-time prekeys, +// defaulting to fallback keys. +message VoodooOneTimeKeyTopupBundle { + VoodooAccountLinkedKey identity_key = 1; + repeated VoodooDeviceLinkedKey one_time_keys = 2; +} + +// A fallback key uploaded by a client, which replaces any existing +// fallback key. The server is expected to serve this prekey when +// all one-time prekeys have been exhausted. +// In our initial prototype we will always use the fallback key in place +// of any one-time prekeys. +message VoodooFallbackKeyRotation { + VoodooAccountLinkedKey identity_key = 1; + VoodooDeviceLinkedKey fallback_key = 2; +} + +// A contact bundle served by the server to a requesting client +message VoodooContactBundle { + VoodooAccountLinkedKey identity_key = 1; + // An unused one time prekey or fallback key returned by the server + VoodooDeviceLinkedKey prekey = 2; +} From d40b29260a77436d95fa2248fa5dc10da619f66a Mon Sep 17 00:00:00 2001 From: Michael Xu Date: Tue, 25 Apr 2023 09:19:32 -0700 Subject: [PATCH 02/30] feat: use vmac instead of voodoo codename --- proto/v3/message_contents/public_key.proto | 29 +++++++++++----------- 1 file changed, 15 insertions(+), 14 deletions(-) diff --git a/proto/v3/message_contents/public_key.proto b/proto/v3/message_contents/public_key.proto index d383b877..b997a137 100644 --- a/proto/v3/message_contents/public_key.proto +++ b/proto/v3/message_contents/public_key.proto @@ -4,11 +4,12 @@ syntax = "proto3"; package xmtp.v3.message_contents; +// v4 here since it was already v3 for golang prior to this option go_package = "github.com/xmtp/proto/v4/go/message_contents"; option java_package = "org.xmtp.proto.v3.message.contents"; // An unsigned public key used by libxmtp -message VoodooUnsignedPublicKey { +message VmacUnsignedPublicKey { uint64 created_ns = 1; oneof union { @@ -25,15 +26,15 @@ message VoodooUnsignedPublicKey { // A key linked to an XMTP account (e.g. signed by a wallet) // The purpose of the key is encoded in the signature -message VoodooAccountLinkedKey { - VoodooUnsignedPublicKey key = 1; +message VmacAccountLinkedKey { + VmacUnsignedPublicKey key = 1; // TODO AccountLinkedSignature signature = 2; } // A key linked to a device (e.g. signed by a device identity key) // The purpose of the key is encoded in the signature -message VoodooDeviceLinkedKey { - VoodooUnsignedPublicKey key = 1; +message VmacDeviceLinkedKey { + VmacUnsignedPublicKey key = 1; // TODO DeviceLinkedSignature signature = 2; } @@ -42,9 +43,9 @@ message VoodooDeviceLinkedKey { // and delete one prekey to anyone who requests one. // In our initial prototype we will not actually use one-time prekeys, // defaulting to fallback keys. -message VoodooOneTimeKeyTopupBundle { - VoodooAccountLinkedKey identity_key = 1; - repeated VoodooDeviceLinkedKey one_time_keys = 2; +message VmacOneTimeKeyTopupBundle { + VmacAccountLinkedKey identity_key = 1; + repeated VmacDeviceLinkedKey one_time_keys = 2; } // A fallback key uploaded by a client, which replaces any existing @@ -52,14 +53,14 @@ message VoodooOneTimeKeyTopupBundle { // all one-time prekeys have been exhausted. // In our initial prototype we will always use the fallback key in place // of any one-time prekeys. -message VoodooFallbackKeyRotation { - VoodooAccountLinkedKey identity_key = 1; - VoodooDeviceLinkedKey fallback_key = 2; +message VmacFallbackKeyRotation { + VmacAccountLinkedKey identity_key = 1; + VmacDeviceLinkedKey fallback_key = 2; } // A contact bundle served by the server to a requesting client -message VoodooContactBundle { - VoodooAccountLinkedKey identity_key = 1; +message VmacContactBundle { + VmacAccountLinkedKey identity_key = 1; // An unused one time prekey or fallback key returned by the server - VoodooDeviceLinkedKey prekey = 2; + VmacDeviceLinkedKey prekey = 2; } From 35517f1737a6033c5339cea146d0bfa0bd3dfec1 Mon Sep 17 00:00:00 2001 From: Nicholas Molnar Date: Tue, 30 May 2023 22:08:27 -0700 Subject: [PATCH 03/30] feat: add signature --- proto/v3/message_contents/association.proto | 20 ++++++++++++++++++++ proto/v3/message_contents/public_key.proto | 21 +++++++++++++++------ 2 files changed, 35 insertions(+), 6 deletions(-) create mode 100644 proto/v3/message_contents/association.proto diff --git a/proto/v3/message_contents/association.proto b/proto/v3/message_contents/association.proto new file mode 100644 index 00000000..76b13f48 --- /dev/null +++ b/proto/v3/message_contents/association.proto @@ -0,0 +1,20 @@ +// Association types +syntax = "proto3"; + +package xmtp.v3.message_contents; + +option go_package = "github.com/xmtp/proto/v3/go/v3/message_contents"; +option java_package = "org.xmtp.proto.v3.message.contents"; + +// EIP191Association is used for all EIP 191 compliant wallet signatures +message Eip191Association { + // The text that was signed, not including the prefix '\0x19Ethereum....' + string text = 1; + RecoverableEcdaSignature signature = 2; +} + +// RecoverableEcdsaSignature +message RecoverableEcdaSignature { + // Includes recovery id as the last byte + bytes bytes = 1; +} \ No newline at end of file diff --git a/proto/v3/message_contents/public_key.proto b/proto/v3/message_contents/public_key.proto index b997a137..afee610b 100644 --- a/proto/v3/message_contents/public_key.proto +++ b/proto/v3/message_contents/public_key.proto @@ -4,8 +4,9 @@ syntax = "proto3"; package xmtp.v3.message_contents; -// v4 here since it was already v3 for golang prior to this -option go_package = "github.com/xmtp/proto/v4/go/message_contents"; +import "v3/message_contents/association.proto"; + +option go_package = "github.com/xmtp/proto/v3/go/v3/message_contents"; option java_package = "org.xmtp.proto.v3.message.contents"; // An unsigned public key used by libxmtp @@ -28,13 +29,14 @@ message VmacUnsignedPublicKey { // The purpose of the key is encoded in the signature message VmacAccountLinkedKey { VmacUnsignedPublicKey key = 1; - // TODO AccountLinkedSignature signature = 2; + Eip191Association association = 2; } // A key linked to a device (e.g. signed by a device identity key) // The purpose of the key is encoded in the signature message VmacDeviceLinkedKey { VmacUnsignedPublicKey key = 1; + // TODO: Define signature format for device linked keys // TODO DeviceLinkedSignature signature = 2; } @@ -59,8 +61,15 @@ message VmacFallbackKeyRotation { } // A contact bundle served by the server to a requesting client -message VmacContactBundle { +message VmacInstallationPublicKeyBundleV1 { VmacAccountLinkedKey identity_key = 1; - // An unused one time prekey or fallback key returned by the server - VmacDeviceLinkedKey prekey = 2; + VmacDeviceLinkedKey fallback_key = 2; } + +// A wrapper for versions of the installation contact bundle to allow +// upgradeability +message InstallationContactBundle { + oneof version { + VmacInstallationPublicKeyBundleV1 v1 = 1; + } +} \ No newline at end of file From 98a8ff329f21de01a5c5b8fa5cdf0eef477cd794 Mon Sep 17 00:00:00 2001 From: Nicholas Molnar Date: Tue, 30 May 2023 22:27:26 -0700 Subject: [PATCH 04/30] fix: include version for association text --- proto/v3/message_contents/association.proto | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/proto/v3/message_contents/association.proto b/proto/v3/message_contents/association.proto index 76b13f48..99458cd0 100644 --- a/proto/v3/message_contents/association.proto +++ b/proto/v3/message_contents/association.proto @@ -6,10 +6,16 @@ package xmtp.v3.message_contents; option go_package = "github.com/xmtp/proto/v3/go/v3/message_contents"; option java_package = "org.xmtp.proto.v3.message.contents"; +// Allows for us to update the format of the association text without +// incrementing the entire proto +enum AssociationTextVersion { + ASSOCIATION_TEXT_VERSION_UNSPECIFIED = 0; + ASSOCIATION_TEXT_VERSION_1 = 1; +} + // EIP191Association is used for all EIP 191 compliant wallet signatures message Eip191Association { - // The text that was signed, not including the prefix '\0x19Ethereum....' - string text = 1; + AssociationTextVersion association_text_version = 1; RecoverableEcdaSignature signature = 2; } From 3ba16d87520869a6e47086a99f8838f37d881840 Mon Sep 17 00:00:00 2001 From: Nicholas Molnar Date: Tue, 30 May 2023 22:34:57 -0700 Subject: [PATCH 05/30] build: add github token to workflow --- .github/workflows/buf.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/buf.yml b/.github/workflows/buf.yml index b45d2183..b6e0a25b 100644 --- a/.github/workflows/buf.yml +++ b/.github/workflows/buf.yml @@ -12,6 +12,8 @@ jobs: - uses: actions/checkout@v2 # Install the `buf` CLI - uses: bufbuild/buf-setup-action@v1 + with: + github_token: ${{ github.token }} # Push only the Input in `proto` to the BSR - uses: bufbuild/buf-push-action@v1 with: From 786202d65850cd1acea3256360949cf284c6f32a Mon Sep 17 00:00:00 2001 From: Nicholas Molnar <65710+neekolas@users.noreply.github.com> Date: Tue, 30 May 2023 23:23:38 -0700 Subject: [PATCH 06/30] Update proto/v3/message_contents/association.proto Co-authored-by: Richard Hua --- proto/v3/message_contents/association.proto | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/proto/v3/message_contents/association.proto b/proto/v3/message_contents/association.proto index 99458cd0..71425c42 100644 --- a/proto/v3/message_contents/association.proto +++ b/proto/v3/message_contents/association.proto @@ -20,7 +20,7 @@ message Eip191Association { } // RecoverableEcdsaSignature -message RecoverableEcdaSignature { +message RecoverableEcdsaSignature { // Includes recovery id as the last byte bytes bytes = 1; } \ No newline at end of file From 164d9892708a6e985e03cda06f2b89b25708ad60 Mon Sep 17 00:00:00 2001 From: Nicholas Molnar Date: Tue, 30 May 2023 23:33:13 -0700 Subject: [PATCH 07/30] fix: rename devicelinkedkey --- proto/v3/message_contents/public_key.proto | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/proto/v3/message_contents/public_key.proto b/proto/v3/message_contents/public_key.proto index afee610b..11bab9a8 100644 --- a/proto/v3/message_contents/public_key.proto +++ b/proto/v3/message_contents/public_key.proto @@ -32,12 +32,10 @@ message VmacAccountLinkedKey { Eip191Association association = 2; } -// A key linked to a device (e.g. signed by a device identity key) +// A key linked to an installation (e.g. signed by an installation identity key) // The purpose of the key is encoded in the signature -message VmacDeviceLinkedKey { +message VmacInstallationLinkedKey { VmacUnsignedPublicKey key = 1; - // TODO: Define signature format for device linked keys - // TODO DeviceLinkedSignature signature = 2; } // A bundle of one time keys uploaded by a client, to be used as @@ -47,7 +45,7 @@ message VmacDeviceLinkedKey { // defaulting to fallback keys. message VmacOneTimeKeyTopupBundle { VmacAccountLinkedKey identity_key = 1; - repeated VmacDeviceLinkedKey one_time_keys = 2; + repeated VmacInstallationLinkedKey one_time_keys = 2; } // A fallback key uploaded by a client, which replaces any existing @@ -57,13 +55,13 @@ message VmacOneTimeKeyTopupBundle { // of any one-time prekeys. message VmacFallbackKeyRotation { VmacAccountLinkedKey identity_key = 1; - VmacDeviceLinkedKey fallback_key = 2; + VmacInstallationLinkedKey fallback_key = 2; } // A contact bundle served by the server to a requesting client message VmacInstallationPublicKeyBundleV1 { VmacAccountLinkedKey identity_key = 1; - VmacDeviceLinkedKey fallback_key = 2; + VmacInstallationLinkedKey fallback_key = 2; } // A wrapper for versions of the installation contact bundle to allow From 2cd9c6055527771f278cacff934e6aa9fc5f5bdb Mon Sep 17 00:00:00 2001 From: Nicholas Molnar Date: Tue, 30 May 2023 23:36:17 -0700 Subject: [PATCH 08/30] build: add buf token as well --- .github/workflows/buf.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/buf.yml b/.github/workflows/buf.yml index b6e0a25b..6e614b4f 100644 --- a/.github/workflows/buf.yml +++ b/.github/workflows/buf.yml @@ -14,6 +14,7 @@ jobs: - uses: bufbuild/buf-setup-action@v1 with: github_token: ${{ github.token }} + buf_token: ${{ secrets.BUF_TOKEN }} # Push only the Input in `proto` to the BSR - uses: bufbuild/buf-push-action@v1 with: From fc1c4ee5ebdb06edbf405530327140032c6bdfc0 Mon Sep 17 00:00:00 2001 From: Nicholas Molnar Date: Tue, 30 May 2023 23:37:58 -0700 Subject: [PATCH 09/30] build: fix bad proto version --- proto/v3/message_contents/association.proto | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/proto/v3/message_contents/association.proto b/proto/v3/message_contents/association.proto index 71425c42..bb677689 100644 --- a/proto/v3/message_contents/association.proto +++ b/proto/v3/message_contents/association.proto @@ -16,7 +16,7 @@ enum AssociationTextVersion { // EIP191Association is used for all EIP 191 compliant wallet signatures message Eip191Association { AssociationTextVersion association_text_version = 1; - RecoverableEcdaSignature signature = 2; + RecoverableEcdsaSignature signature = 2; } // RecoverableEcdsaSignature From ee8c31d3dec3aa0cb502580d22030d51d7b7b8c3 Mon Sep 17 00:00:00 2001 From: Nicholas Molnar Date: Wed, 31 May 2023 12:16:45 -0700 Subject: [PATCH 10/30] fix: make association a oneof --- proto/v3/message_contents/public_key.proto | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/proto/v3/message_contents/public_key.proto b/proto/v3/message_contents/public_key.proto index 11bab9a8..bf99289a 100644 --- a/proto/v3/message_contents/public_key.proto +++ b/proto/v3/message_contents/public_key.proto @@ -29,7 +29,9 @@ message VmacUnsignedPublicKey { // The purpose of the key is encoded in the signature message VmacAccountLinkedKey { VmacUnsignedPublicKey key = 1; - Eip191Association association = 2; + oneof association { + Eip191Association eip_191 = 2; + } } // A key linked to an installation (e.g. signed by an installation identity key) From c0f71a60e7b06bb3eb408c490c7ff10a2ee93eba Mon Sep 17 00:00:00 2001 From: Nicholas Molnar Date: Tue, 13 Jun 2023 13:34:19 -0700 Subject: [PATCH 11/30] feat: add v3 invites --- proto/v3/message_contents/invite.proto | 39 ++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) create mode 100644 proto/v3/message_contents/invite.proto diff --git a/proto/v3/message_contents/invite.proto b/proto/v3/message_contents/invite.proto new file mode 100644 index 00000000..c29c9283 --- /dev/null +++ b/proto/v3/message_contents/invite.proto @@ -0,0 +1,39 @@ +// V3 invite message structure +syntax = "proto3"; + +package xmtp.v3.message_contents; + +import "v3/message_contents/public_key.proto"; + +option go_package = "github.com/xmtp/proto/v3/go/v3/message_contents"; +option java_package = "org.xmtp.proto.v3.message.contents"; + +// InvitationV1 is the encrypted invitation message meant to be encrypted as +// ciphertext in SealedInvitationV1 and decrypted by the recipient using the +// provided inviter `InstallationContactBundle` +message InvitationV1 { + // The inviter_wallet_address must match the address derived from the + // signature in the inviter contact bundle Either the + // `inviter_wallet_address` or the `recipient_wallet_address` MUST match the + // wallet address of the account used to decrypt + string inviter_wallet_address = 1; + string recipient_wallet_address = 2; + string conversation_unique_id = 3; + // TODO: Decide whether we need a Context field +} + +// SealedInvitationV1 is the encrypted invitation message and the contact of the +// sender +message SealedInvitationV1 { + // This contains the public key that will be used to decrypt the ciphertext + InstallationContactBundle inviter = 1; + // Corresponds to an InvitationV1 message + bytes ciphertext = 2; +} + +// Wrapper message type +message SealedInvitation { + oneof version { + SealedInvitationV1 v1 = 1; + } +} From 5f865d6107ca4c1e699b6ca60d79ecf1681b88b5 Mon Sep 17 00:00:00 2001 From: Nicholas Molnar Date: Tue, 13 Jun 2023 13:50:47 -0700 Subject: [PATCH 12/30] docs: fix comment --- proto/v3/message_contents/invite.proto | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/proto/v3/message_contents/invite.proto b/proto/v3/message_contents/invite.proto index c29c9283..eebeea54 100644 --- a/proto/v3/message_contents/invite.proto +++ b/proto/v3/message_contents/invite.proto @@ -13,9 +13,9 @@ option java_package = "org.xmtp.proto.v3.message.contents"; // provided inviter `InstallationContactBundle` message InvitationV1 { // The inviter_wallet_address must match the address derived from the - // signature in the inviter contact bundle Either the + // signature in the inviter contact bundle. Either the // `inviter_wallet_address` or the `recipient_wallet_address` MUST match the - // wallet address of the account used to decrypt + // wallet address of the account receiving this invite string inviter_wallet_address = 1; string recipient_wallet_address = 2; string conversation_unique_id = 3; From 425bcf441abe0131005d6d20aa91d024289e7e9a Mon Sep 17 00:00:00 2001 From: Nicholas Molnar Date: Tue, 13 Jun 2023 15:08:41 -0700 Subject: [PATCH 13/30] fix: rename to InvitationEnvelope --- proto/v3/message_contents/invite.proto | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/proto/v3/message_contents/invite.proto b/proto/v3/message_contents/invite.proto index eebeea54..a585a4d3 100644 --- a/proto/v3/message_contents/invite.proto +++ b/proto/v3/message_contents/invite.proto @@ -22,9 +22,9 @@ message InvitationV1 { // TODO: Decide whether we need a Context field } -// SealedInvitationV1 is the encrypted invitation message and the contact of the -// sender -message SealedInvitationV1 { +// InvitationEnvelopeV1 is the encrypted invitation message and the contact of +// the sender +message InvitationEnvelopeV1 { // This contains the public key that will be used to decrypt the ciphertext InstallationContactBundle inviter = 1; // Corresponds to an InvitationV1 message @@ -32,8 +32,8 @@ message SealedInvitationV1 { } // Wrapper message type -message SealedInvitation { +message InvitationEnvelope { oneof version { - SealedInvitationV1 v1 = 1; + InvitationEnvelopeV1 v1 = 1; } } From 756e8f7e2705a2f67644e9a624c7498bb89ae875 Mon Sep 17 00:00:00 2001 From: Nicholas Molnar <65710+neekolas@users.noreply.github.com> Date: Tue, 13 Jun 2023 17:49:41 -0700 Subject: [PATCH 14/30] Update proto/v3/message_contents/invite.proto Co-authored-by: Richard Hua --- proto/v3/message_contents/invite.proto | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/proto/v3/message_contents/invite.proto b/proto/v3/message_contents/invite.proto index a585a4d3..1976e98e 100644 --- a/proto/v3/message_contents/invite.proto +++ b/proto/v3/message_contents/invite.proto @@ -8,8 +8,8 @@ import "v3/message_contents/public_key.proto"; option go_package = "github.com/xmtp/proto/v3/go/v3/message_contents"; option java_package = "org.xmtp.proto.v3.message.contents"; -// InvitationV1 is the encrypted invitation message meant to be encrypted as -// ciphertext in SealedInvitationV1 and decrypted by the recipient using the +// InvitationV1 is the invitation message meant to be encrypted as +// ciphertext in InvitationEnvelopeV1 and decrypted by the recipient using the // provided inviter `InstallationContactBundle` message InvitationV1 { // The inviter_wallet_address must match the address derived from the From 6aff0dff29da87de7567cc2ce399f3259854424c Mon Sep 17 00:00:00 2001 From: Nicholas Molnar Date: Wed, 14 Jun 2023 08:54:30 -0700 Subject: [PATCH 15/30] fix: simplify schema --- proto/v3/message_contents/invite.proto | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/proto/v3/message_contents/invite.proto b/proto/v3/message_contents/invite.proto index a585a4d3..8ed95ff2 100644 --- a/proto/v3/message_contents/invite.proto +++ b/proto/v3/message_contents/invite.proto @@ -12,13 +12,11 @@ option java_package = "org.xmtp.proto.v3.message.contents"; // ciphertext in SealedInvitationV1 and decrypted by the recipient using the // provided inviter `InstallationContactBundle` message InvitationV1 { - // The inviter_wallet_address must match the address derived from the - // signature in the inviter contact bundle. Either the - // `inviter_wallet_address` or the `recipient_wallet_address` MUST match the - // wallet address of the account receiving this invite - string inviter_wallet_address = 1; - string recipient_wallet_address = 2; - string conversation_unique_id = 3; + // If the inviter contact bundle has the same wallet address as the current + // user, the invitee is the other wallet address in the conversation. If the + // inviter contact bundle has a different wallet address, the invitee wallet + // address MUST be the wallet address of the recipient of the invite. + string invitee_wallet_address = 1; // TODO: Decide whether we need a Context field } From 5b11886a014e0541d98944c85d80449180772e9c Mon Sep 17 00:00:00 2001 From: Nicholas Molnar Date: Wed, 14 Jun 2023 15:43:45 -0700 Subject: [PATCH 16/30] fix: add wallet address --- proto/v3/message_contents/association.proto | 1 + 1 file changed, 1 insertion(+) diff --git a/proto/v3/message_contents/association.proto b/proto/v3/message_contents/association.proto index bb677689..7f89e42b 100644 --- a/proto/v3/message_contents/association.proto +++ b/proto/v3/message_contents/association.proto @@ -17,6 +17,7 @@ enum AssociationTextVersion { message Eip191Association { AssociationTextVersion association_text_version = 1; RecoverableEcdsaSignature signature = 2; + string wallet_address = 3; } // RecoverableEcdsaSignature From d3b6114807167466b914a3485805bb452a1b0389 Mon Sep 17 00:00:00 2001 From: Richard Hua Date: Tue, 25 Jul 2023 22:03:28 -0700 Subject: [PATCH 17/30] feat: add padlock message types --- .vscode/settings.json | 4 +- go/message_api/v1/message_api.pb.gw.go | 90 +++---- go/message_contents/message.pb.go | 316 ++++++++++++++++++++++--- proto/message_contents/message.proto | 34 +++ 4 files changed, 373 insertions(+), 71 deletions(-) diff --git a/.vscode/settings.json b/.vscode/settings.json index 557218a6..ded90212 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -4,5 +4,7 @@ "options": [ "--proto_path=build/tmp/vendor", ] - } + }, + // protolint complains if lines are longer than length 80, display a ruler + "editor.rulers": [80] } \ No newline at end of file diff --git a/go/message_api/v1/message_api.pb.gw.go b/go/message_api/v1/message_api.pb.gw.go index d4915391..d2435f7a 100644 --- a/go/message_api/v1/message_api.pb.gw.go +++ b/go/message_api/v1/message_api.pb.gw.go @@ -196,20 +196,21 @@ func RegisterMessageApiHandlerServer(ctx context.Context, mux *runtime.ServeMux, ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) var err error - ctx, err = runtime.AnnotateIncomingContext(ctx, mux, req, "/xmtp.message_api.v1.MessageApi/Publish", runtime.WithHTTPPathPattern("/message/v1/publish")) + var annotatedContext context.Context + annotatedContext, err = runtime.AnnotateIncomingContext(ctx, mux, req, "/xmtp.message_api.v1.MessageApi/Publish", runtime.WithHTTPPathPattern("/message/v1/publish")) if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return } - resp, md, err := local_request_MessageApi_Publish_0(ctx, inboundMarshaler, server, req, pathParams) + resp, md, err := local_request_MessageApi_Publish_0(annotatedContext, inboundMarshaler, server, req, pathParams) md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer()) - ctx = runtime.NewServerMetadataContext(ctx, md) + annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md) if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) return } - forward_MessageApi_Publish_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + forward_MessageApi_Publish_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) }) @@ -234,20 +235,21 @@ func RegisterMessageApiHandlerServer(ctx context.Context, mux *runtime.ServeMux, ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) var err error - ctx, err = runtime.AnnotateIncomingContext(ctx, mux, req, "/xmtp.message_api.v1.MessageApi/Query", runtime.WithHTTPPathPattern("/message/v1/query")) + var annotatedContext context.Context + annotatedContext, err = runtime.AnnotateIncomingContext(ctx, mux, req, "/xmtp.message_api.v1.MessageApi/Query", runtime.WithHTTPPathPattern("/message/v1/query")) if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return } - resp, md, err := local_request_MessageApi_Query_0(ctx, inboundMarshaler, server, req, pathParams) + resp, md, err := local_request_MessageApi_Query_0(annotatedContext, inboundMarshaler, server, req, pathParams) md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer()) - ctx = runtime.NewServerMetadataContext(ctx, md) + annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md) if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) return } - forward_MessageApi_Query_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + forward_MessageApi_Query_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) }) @@ -258,20 +260,21 @@ func RegisterMessageApiHandlerServer(ctx context.Context, mux *runtime.ServeMux, ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) var err error - ctx, err = runtime.AnnotateIncomingContext(ctx, mux, req, "/xmtp.message_api.v1.MessageApi/BatchQuery", runtime.WithHTTPPathPattern("/message/v1/batch-query")) + var annotatedContext context.Context + annotatedContext, err = runtime.AnnotateIncomingContext(ctx, mux, req, "/xmtp.message_api.v1.MessageApi/BatchQuery", runtime.WithHTTPPathPattern("/message/v1/batch-query")) if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return } - resp, md, err := local_request_MessageApi_BatchQuery_0(ctx, inboundMarshaler, server, req, pathParams) + resp, md, err := local_request_MessageApi_BatchQuery_0(annotatedContext, inboundMarshaler, server, req, pathParams) md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer()) - ctx = runtime.NewServerMetadataContext(ctx, md) + annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md) if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) return } - forward_MessageApi_BatchQuery_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + forward_MessageApi_BatchQuery_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) }) @@ -281,7 +284,7 @@ func RegisterMessageApiHandlerServer(ctx context.Context, mux *runtime.ServeMux, // RegisterMessageApiHandlerFromEndpoint is same as RegisterMessageApiHandler but // automatically dials to "endpoint" and closes the connection when "ctx" gets done. func RegisterMessageApiHandlerFromEndpoint(ctx context.Context, mux *runtime.ServeMux, endpoint string, opts []grpc.DialOption) (err error) { - conn, err := grpc.Dial(endpoint, opts...) + conn, err := grpc.DialContext(ctx, endpoint, opts...) if err != nil { return err } @@ -321,19 +324,20 @@ func RegisterMessageApiHandlerClient(ctx context.Context, mux *runtime.ServeMux, defer cancel() inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) var err error - ctx, err = runtime.AnnotateContext(ctx, mux, req, "/xmtp.message_api.v1.MessageApi/Publish", runtime.WithHTTPPathPattern("/message/v1/publish")) + var annotatedContext context.Context + annotatedContext, err = runtime.AnnotateContext(ctx, mux, req, "/xmtp.message_api.v1.MessageApi/Publish", runtime.WithHTTPPathPattern("/message/v1/publish")) if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return } - resp, md, err := request_MessageApi_Publish_0(ctx, inboundMarshaler, client, req, pathParams) - ctx = runtime.NewServerMetadataContext(ctx, md) + resp, md, err := request_MessageApi_Publish_0(annotatedContext, inboundMarshaler, client, req, pathParams) + annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md) if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) return } - forward_MessageApi_Publish_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + forward_MessageApi_Publish_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) }) @@ -342,19 +346,20 @@ func RegisterMessageApiHandlerClient(ctx context.Context, mux *runtime.ServeMux, defer cancel() inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) var err error - ctx, err = runtime.AnnotateContext(ctx, mux, req, "/xmtp.message_api.v1.MessageApi/Subscribe", runtime.WithHTTPPathPattern("/message/v1/subscribe")) + var annotatedContext context.Context + annotatedContext, err = runtime.AnnotateContext(ctx, mux, req, "/xmtp.message_api.v1.MessageApi/Subscribe", runtime.WithHTTPPathPattern("/message/v1/subscribe")) if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return } - resp, md, err := request_MessageApi_Subscribe_0(ctx, inboundMarshaler, client, req, pathParams) - ctx = runtime.NewServerMetadataContext(ctx, md) + resp, md, err := request_MessageApi_Subscribe_0(annotatedContext, inboundMarshaler, client, req, pathParams) + annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md) if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) return } - forward_MessageApi_Subscribe_0(ctx, mux, outboundMarshaler, w, req, func() (proto.Message, error) { return resp.Recv() }, mux.GetForwardResponseOptions()...) + forward_MessageApi_Subscribe_0(annotatedContext, mux, outboundMarshaler, w, req, func() (proto.Message, error) { return resp.Recv() }, mux.GetForwardResponseOptions()...) }) @@ -363,19 +368,20 @@ func RegisterMessageApiHandlerClient(ctx context.Context, mux *runtime.ServeMux, defer cancel() inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) var err error - ctx, err = runtime.AnnotateContext(ctx, mux, req, "/xmtp.message_api.v1.MessageApi/SubscribeAll", runtime.WithHTTPPathPattern("/message/v1/subscribe-all")) + var annotatedContext context.Context + annotatedContext, err = runtime.AnnotateContext(ctx, mux, req, "/xmtp.message_api.v1.MessageApi/SubscribeAll", runtime.WithHTTPPathPattern("/message/v1/subscribe-all")) if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return } - resp, md, err := request_MessageApi_SubscribeAll_0(ctx, inboundMarshaler, client, req, pathParams) - ctx = runtime.NewServerMetadataContext(ctx, md) + resp, md, err := request_MessageApi_SubscribeAll_0(annotatedContext, inboundMarshaler, client, req, pathParams) + annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md) if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) return } - forward_MessageApi_SubscribeAll_0(ctx, mux, outboundMarshaler, w, req, func() (proto.Message, error) { return resp.Recv() }, mux.GetForwardResponseOptions()...) + forward_MessageApi_SubscribeAll_0(annotatedContext, mux, outboundMarshaler, w, req, func() (proto.Message, error) { return resp.Recv() }, mux.GetForwardResponseOptions()...) }) @@ -384,19 +390,20 @@ func RegisterMessageApiHandlerClient(ctx context.Context, mux *runtime.ServeMux, defer cancel() inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) var err error - ctx, err = runtime.AnnotateContext(ctx, mux, req, "/xmtp.message_api.v1.MessageApi/Query", runtime.WithHTTPPathPattern("/message/v1/query")) + var annotatedContext context.Context + annotatedContext, err = runtime.AnnotateContext(ctx, mux, req, "/xmtp.message_api.v1.MessageApi/Query", runtime.WithHTTPPathPattern("/message/v1/query")) if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return } - resp, md, err := request_MessageApi_Query_0(ctx, inboundMarshaler, client, req, pathParams) - ctx = runtime.NewServerMetadataContext(ctx, md) + resp, md, err := request_MessageApi_Query_0(annotatedContext, inboundMarshaler, client, req, pathParams) + annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md) if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) return } - forward_MessageApi_Query_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + forward_MessageApi_Query_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) }) @@ -405,19 +412,20 @@ func RegisterMessageApiHandlerClient(ctx context.Context, mux *runtime.ServeMux, defer cancel() inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) var err error - ctx, err = runtime.AnnotateContext(ctx, mux, req, "/xmtp.message_api.v1.MessageApi/BatchQuery", runtime.WithHTTPPathPattern("/message/v1/batch-query")) + var annotatedContext context.Context + annotatedContext, err = runtime.AnnotateContext(ctx, mux, req, "/xmtp.message_api.v1.MessageApi/BatchQuery", runtime.WithHTTPPathPattern("/message/v1/batch-query")) if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return } - resp, md, err := request_MessageApi_BatchQuery_0(ctx, inboundMarshaler, client, req, pathParams) - ctx = runtime.NewServerMetadataContext(ctx, md) + resp, md, err := request_MessageApi_BatchQuery_0(annotatedContext, inboundMarshaler, client, req, pathParams) + annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md) if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) return } - forward_MessageApi_BatchQuery_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + forward_MessageApi_BatchQuery_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) }) diff --git a/go/message_contents/message.pb.go b/go/message_contents/message.pb.go index 2fcd9ac8..d34d8867 100644 --- a/go/message_contents/message.pb.go +++ b/go/message_contents/message.pb.go @@ -449,6 +449,204 @@ func (x *DecodedMessage) GetContentBytes() []byte { return nil } +// Plaintext header included with messages, visible to all +type PadlockMessageHeader struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + SentNs uint64 `protobuf:"varint,1,opt,name=sent_ns,json=sentNs,proto3" json:"sent_ns,omitempty"` + // The session_id is derived via SHA256. Any other identifier will leak the + // sender of the message. + SessionId string `protobuf:"bytes,2,opt,name=session_id,json=sessionId,proto3" json:"session_id,omitempty"` +} + +func (x *PadlockMessageHeader) Reset() { + *x = PadlockMessageHeader{} + if protoimpl.UnsafeEnabled { + mi := &file_message_contents_message_proto_msgTypes[6] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *PadlockMessageHeader) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*PadlockMessageHeader) ProtoMessage() {} + +func (x *PadlockMessageHeader) ProtoReflect() protoreflect.Message { + mi := &file_message_contents_message_proto_msgTypes[6] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use PadlockMessageHeader.ProtoReflect.Descriptor instead. +func (*PadlockMessageHeader) Descriptor() ([]byte, []int) { + return file_message_contents_message_proto_rawDescGZIP(), []int{6} +} + +func (x *PadlockMessageHeader) GetSentNs() uint64 { + if x != nil { + return x.SentNs + } + return 0 +} + +func (x *PadlockMessageHeader) GetSessionId() string { + if x != nil { + return x.SessionId + } + return "" +} + +// Encrypted body included with messages, only visible to recipients +// - For safety, the sender_account_id and sender_installation_id MUST be +// derived from the session_id in the header by each installation receiving +// the message +// - The recipient is unnecessary to include here - the recipient at the session +// level is the receiving installation, and the recipient at the conversation +// level is whoever is in the conversation referred to by convo_id (multiple +// people in the case of groups) +// - The recipient installation MUST cross-check that the sender_account_id is a +// valid participant of the conversation referred to by convo_id +// - The recipient installation MUST validate that the MessageHeader hashes to +// the header_hash. +// TODO is that sufficient to replace the AssociatedData in v2? +type PadlockMessagePayload struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + MessageVersion uint32 `protobuf:"varint,1,opt,name=message_version,json=messageVersion,proto3" json:"message_version,omitempty"` + HeaderHash []byte `protobuf:"bytes,2,opt,name=header_hash,json=headerHash,proto3" json:"header_hash,omitempty"` // PadlockMessageHeader + ConvoId string `protobuf:"bytes,3,opt,name=convo_id,json=convoId,proto3" json:"convo_id,omitempty"` + ContentBytes []byte `protobuf:"bytes,4,opt,name=content_bytes,json=contentBytes,proto3" json:"content_bytes,omitempty"` // EncodedContent +} + +func (x *PadlockMessagePayload) Reset() { + *x = PadlockMessagePayload{} + if protoimpl.UnsafeEnabled { + mi := &file_message_contents_message_proto_msgTypes[7] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *PadlockMessagePayload) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*PadlockMessagePayload) ProtoMessage() {} + +func (x *PadlockMessagePayload) ProtoReflect() protoreflect.Message { + mi := &file_message_contents_message_proto_msgTypes[7] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use PadlockMessagePayload.ProtoReflect.Descriptor instead. +func (*PadlockMessagePayload) Descriptor() ([]byte, []int) { + return file_message_contents_message_proto_rawDescGZIP(), []int{7} +} + +func (x *PadlockMessagePayload) GetMessageVersion() uint32 { + if x != nil { + return x.MessageVersion + } + return 0 +} + +func (x *PadlockMessagePayload) GetHeaderHash() []byte { + if x != nil { + return x.HeaderHash + } + return nil +} + +func (x *PadlockMessagePayload) GetConvoId() string { + if x != nil { + return x.ConvoId + } + return "" +} + +func (x *PadlockMessagePayload) GetContentBytes() []byte { + if x != nil { + return x.ContentBytes + } + return nil +} + +// Combines the plaintext header with the encrypted payload +type PadlockMessageEnvelope struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + HeaderBytes []byte `protobuf:"bytes,1,opt,name=header_bytes,json=headerBytes,proto3" json:"header_bytes,omitempty"` // PadlockMessageHeader + Ciphertext []byte `protobuf:"bytes,2,opt,name=ciphertext,proto3" json:"ciphertext,omitempty"` // Encrypted PadlockMessagePayload +} + +func (x *PadlockMessageEnvelope) Reset() { + *x = PadlockMessageEnvelope{} + if protoimpl.UnsafeEnabled { + mi := &file_message_contents_message_proto_msgTypes[8] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *PadlockMessageEnvelope) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*PadlockMessageEnvelope) ProtoMessage() {} + +func (x *PadlockMessageEnvelope) ProtoReflect() protoreflect.Message { + mi := &file_message_contents_message_proto_msgTypes[8] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use PadlockMessageEnvelope.ProtoReflect.Descriptor instead. +func (*PadlockMessageEnvelope) Descriptor() ([]byte, []int) { + return file_message_contents_message_proto_rawDescGZIP(), []int{8} +} + +func (x *PadlockMessageEnvelope) GetHeaderBytes() []byte { + if x != nil { + return x.HeaderBytes + } + return nil +} + +func (x *PadlockMessageEnvelope) GetCiphertext() []byte { + if x != nil { + return x.Ciphertext + } + return nil +} + var File_message_contents_message_proto protoreflect.FileDescriptor var file_message_contents_message_proto_rawDesc = []byte{ @@ -524,12 +722,33 @@ var file_message_contents_message_proto_rawDesc = []byte{ 0x5f, 0x62, 0x79, 0x74, 0x65, 0x73, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0c, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x42, 0x79, 0x74, 0x65, 0x73, 0x42, 0x14, 0x0a, 0x12, 0x5f, 0x72, 0x65, 0x63, 0x69, 0x70, 0x69, 0x65, 0x6e, 0x74, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, - 0x42, 0x4f, 0x0a, 0x1f, 0x6f, 0x72, 0x67, 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x2e, 0x70, 0x72, 0x6f, - 0x74, 0x6f, 0x2e, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x65, - 0x6e, 0x74, 0x73, 0x5a, 0x2c, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, - 0x78, 0x6d, 0x74, 0x70, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x76, 0x33, 0x2f, 0x67, 0x6f, - 0x2f, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, - 0x73, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x22, 0x4e, 0x0a, 0x14, 0x50, 0x61, 0x64, 0x6c, 0x6f, 0x63, 0x6b, 0x4d, 0x65, 0x73, 0x73, 0x61, + 0x67, 0x65, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x12, 0x17, 0x0a, 0x07, 0x73, 0x65, 0x6e, 0x74, + 0x5f, 0x6e, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x06, 0x73, 0x65, 0x6e, 0x74, 0x4e, + 0x73, 0x12, 0x1d, 0x0a, 0x0a, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x49, 0x64, + 0x22, 0xa1, 0x01, 0x0a, 0x15, 0x50, 0x61, 0x64, 0x6c, 0x6f, 0x63, 0x6b, 0x4d, 0x65, 0x73, 0x73, + 0x61, 0x67, 0x65, 0x50, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x12, 0x27, 0x0a, 0x0f, 0x6d, 0x65, + 0x73, 0x73, 0x61, 0x67, 0x65, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x0d, 0x52, 0x0e, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x56, 0x65, 0x72, 0x73, + 0x69, 0x6f, 0x6e, 0x12, 0x1f, 0x0a, 0x0b, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x5f, 0x68, 0x61, + 0x73, 0x68, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0a, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, + 0x48, 0x61, 0x73, 0x68, 0x12, 0x19, 0x0a, 0x08, 0x63, 0x6f, 0x6e, 0x76, 0x6f, 0x5f, 0x69, 0x64, + 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x63, 0x6f, 0x6e, 0x76, 0x6f, 0x49, 0x64, 0x12, + 0x23, 0x0a, 0x0d, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x5f, 0x62, 0x79, 0x74, 0x65, 0x73, + 0x18, 0x04, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0c, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x42, + 0x79, 0x74, 0x65, 0x73, 0x22, 0x5b, 0x0a, 0x16, 0x50, 0x61, 0x64, 0x6c, 0x6f, 0x63, 0x6b, 0x4d, + 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x45, 0x6e, 0x76, 0x65, 0x6c, 0x6f, 0x70, 0x65, 0x12, 0x21, + 0x0a, 0x0c, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x5f, 0x62, 0x79, 0x74, 0x65, 0x73, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0b, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x42, 0x79, 0x74, 0x65, + 0x73, 0x12, 0x1e, 0x0a, 0x0a, 0x63, 0x69, 0x70, 0x68, 0x65, 0x72, 0x74, 0x65, 0x78, 0x74, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0a, 0x63, 0x69, 0x70, 0x68, 0x65, 0x72, 0x74, 0x65, 0x78, + 0x74, 0x42, 0x4f, 0x0a, 0x1f, 0x6f, 0x72, 0x67, 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x2e, 0x70, 0x72, + 0x6f, 0x74, 0x6f, 0x2e, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x2e, 0x63, 0x6f, 0x6e, 0x74, + 0x65, 0x6e, 0x74, 0x73, 0x5a, 0x2c, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, + 0x2f, 0x78, 0x6d, 0x74, 0x70, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x76, 0x33, 0x2f, 0x67, + 0x6f, 0x2f, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, + 0x74, 0x73, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( @@ -544,31 +763,34 @@ func file_message_contents_message_proto_rawDescGZIP() []byte { return file_message_contents_message_proto_rawDescData } -var file_message_contents_message_proto_msgTypes = make([]protoimpl.MessageInfo, 6) +var file_message_contents_message_proto_msgTypes = make([]protoimpl.MessageInfo, 9) var file_message_contents_message_proto_goTypes = []interface{}{ - (*MessageHeaderV1)(nil), // 0: xmtp.message_contents.MessageHeaderV1 - (*MessageV1)(nil), // 1: xmtp.message_contents.MessageV1 - (*MessageHeaderV2)(nil), // 2: xmtp.message_contents.MessageHeaderV2 - (*MessageV2)(nil), // 3: xmtp.message_contents.MessageV2 - (*Message)(nil), // 4: xmtp.message_contents.Message - (*DecodedMessage)(nil), // 5: xmtp.message_contents.DecodedMessage - (*PublicKeyBundle)(nil), // 6: xmtp.message_contents.PublicKeyBundle - (*Ciphertext)(nil), // 7: xmtp.message_contents.Ciphertext - (*ConversationReference)(nil), // 8: xmtp.message_contents.ConversationReference + (*MessageHeaderV1)(nil), // 0: xmtp.message_contents.MessageHeaderV1 + (*MessageV1)(nil), // 1: xmtp.message_contents.MessageV1 + (*MessageHeaderV2)(nil), // 2: xmtp.message_contents.MessageHeaderV2 + (*MessageV2)(nil), // 3: xmtp.message_contents.MessageV2 + (*Message)(nil), // 4: xmtp.message_contents.Message + (*DecodedMessage)(nil), // 5: xmtp.message_contents.DecodedMessage + (*PadlockMessageHeader)(nil), // 6: xmtp.message_contents.PadlockMessageHeader + (*PadlockMessagePayload)(nil), // 7: xmtp.message_contents.PadlockMessagePayload + (*PadlockMessageEnvelope)(nil), // 8: xmtp.message_contents.PadlockMessageEnvelope + (*PublicKeyBundle)(nil), // 9: xmtp.message_contents.PublicKeyBundle + (*Ciphertext)(nil), // 10: xmtp.message_contents.Ciphertext + (*ConversationReference)(nil), // 11: xmtp.message_contents.ConversationReference } var file_message_contents_message_proto_depIdxs = []int32{ - 6, // 0: xmtp.message_contents.MessageHeaderV1.sender:type_name -> xmtp.message_contents.PublicKeyBundle - 6, // 1: xmtp.message_contents.MessageHeaderV1.recipient:type_name -> xmtp.message_contents.PublicKeyBundle - 7, // 2: xmtp.message_contents.MessageV1.ciphertext:type_name -> xmtp.message_contents.Ciphertext - 7, // 3: xmtp.message_contents.MessageV2.ciphertext:type_name -> xmtp.message_contents.Ciphertext - 1, // 4: xmtp.message_contents.Message.v1:type_name -> xmtp.message_contents.MessageV1 - 3, // 5: xmtp.message_contents.Message.v2:type_name -> xmtp.message_contents.MessageV2 - 8, // 6: xmtp.message_contents.DecodedMessage.conversation:type_name -> xmtp.message_contents.ConversationReference - 7, // [7:7] is the sub-list for method output_type - 7, // [7:7] is the sub-list for method input_type - 7, // [7:7] is the sub-list for extension type_name - 7, // [7:7] is the sub-list for extension extendee - 0, // [0:7] is the sub-list for field type_name + 9, // 0: xmtp.message_contents.MessageHeaderV1.sender:type_name -> xmtp.message_contents.PublicKeyBundle + 9, // 1: xmtp.message_contents.MessageHeaderV1.recipient:type_name -> xmtp.message_contents.PublicKeyBundle + 10, // 2: xmtp.message_contents.MessageV1.ciphertext:type_name -> xmtp.message_contents.Ciphertext + 10, // 3: xmtp.message_contents.MessageV2.ciphertext:type_name -> xmtp.message_contents.Ciphertext + 1, // 4: xmtp.message_contents.Message.v1:type_name -> xmtp.message_contents.MessageV1 + 3, // 5: xmtp.message_contents.Message.v2:type_name -> xmtp.message_contents.MessageV2 + 11, // 6: xmtp.message_contents.DecodedMessage.conversation:type_name -> xmtp.message_contents.ConversationReference + 7, // [7:7] is the sub-list for method output_type + 7, // [7:7] is the sub-list for method input_type + 7, // [7:7] is the sub-list for extension type_name + 7, // [7:7] is the sub-list for extension extendee + 0, // [0:7] is the sub-list for field type_name } func init() { file_message_contents_message_proto_init() } @@ -652,6 +874,42 @@ func file_message_contents_message_proto_init() { return nil } } + file_message_contents_message_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*PadlockMessageHeader); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_message_contents_message_proto_msgTypes[7].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*PadlockMessagePayload); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_message_contents_message_proto_msgTypes[8].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*PadlockMessageEnvelope); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } } file_message_contents_message_proto_msgTypes[4].OneofWrappers = []interface{}{ (*Message_V1)(nil), @@ -664,7 +922,7 @@ func file_message_contents_message_proto_init() { GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_message_contents_message_proto_rawDesc, NumEnums: 0, - NumMessages: 6, + NumMessages: 9, NumExtensions: 0, NumServices: 0, }, diff --git a/proto/message_contents/message.proto b/proto/message_contents/message.proto index bcd17c60..41ff1859 100644 --- a/proto/message_contents/message.proto +++ b/proto/message_contents/message.proto @@ -67,4 +67,38 @@ message DecodedMessage { string content_topic = 6; ConversationReference conversation = 7; bytes content_bytes = 8; // encapsulates EncodedContent +} + +// Plaintext header included with messages, visible to all +message PadlockMessageHeader { + uint64 sent_ns = 1; + // The session_id is derived via SHA256. Any other identifier will leak the + // sender of the message. + string session_id = 2; +} + +// Encrypted body included with messages, only visible to recipients +// - For safety, the sender_account_id and sender_installation_id MUST be +// derived from the session_id in the header by each installation receiving +// the message +// - The recipient is unnecessary to include here - the recipient at the session +// level is the receiving installation, and the recipient at the conversation +// level is whoever is in the conversation referred to by convo_id (multiple +// people in the case of groups) +// - The recipient installation MUST cross-check that the sender_account_id is a +// valid participant of the conversation referred to by convo_id +// - The recipient installation MUST validate that the MessageHeader hashes to +// the header_hash. +// TODO is that sufficient to replace the AssociatedData in v2? +message PadlockMessagePayload { + uint32 message_version = 1; + bytes header_hash = 2; // PadlockMessageHeader + string convo_id = 3; + bytes content_bytes = 4; // EncodedContent +} + +// Combines the plaintext header with the encrypted payload +message PadlockMessageEnvelope { + bytes header_bytes = 1; // PadlockMessageHeader + bytes ciphertext = 2; // Encrypted PadlockMessagePayload } \ No newline at end of file From 3f7901a5f44fc0c41ffec18831043fb433021b39 Mon Sep 17 00:00:00 2001 From: Richard Hua Date: Wed, 26 Jul 2023 11:54:50 -0700 Subject: [PATCH 18/30] feat: use SealedSender with sender and recipient info, use header signature instead of header hash --- go/message_contents/message.pb.go | 270 +++++++++++++++++++-------- proto/message_contents/message.proto | 44 +++-- 2 files changed, 216 insertions(+), 98 deletions(-) diff --git a/go/message_contents/message.pb.go b/go/message_contents/message.pb.go index d34d8867..56241643 100644 --- a/go/message_contents/message.pb.go +++ b/go/message_contents/message.pb.go @@ -449,22 +449,96 @@ func (x *DecodedMessage) GetContentBytes() []byte { return nil } +// Metadata that is encrypted via SealedSender and only visible to the recipient +// Currently we do not actually encrypt this, actual implementation of +// SealedSender will be added shortly. +type PadlockMessageSealedMetadata struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + SenderUserAddress string `protobuf:"bytes,1,opt,name=sender_user_address,json=senderUserAddress,proto3" json:"sender_user_address,omitempty"` + SenderInstallationId string `protobuf:"bytes,2,opt,name=sender_installation_id,json=senderInstallationId,proto3" json:"sender_installation_id,omitempty"` + RecipientUserAddress string `protobuf:"bytes,3,opt,name=recipient_user_address,json=recipientUserAddress,proto3" json:"recipient_user_address,omitempty"` + RecipientInstallationId string `protobuf:"bytes,4,opt,name=recipient_installation_id,json=recipientInstallationId,proto3" json:"recipient_installation_id,omitempty"` +} + +func (x *PadlockMessageSealedMetadata) Reset() { + *x = PadlockMessageSealedMetadata{} + if protoimpl.UnsafeEnabled { + mi := &file_message_contents_message_proto_msgTypes[6] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *PadlockMessageSealedMetadata) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*PadlockMessageSealedMetadata) ProtoMessage() {} + +func (x *PadlockMessageSealedMetadata) ProtoReflect() protoreflect.Message { + mi := &file_message_contents_message_proto_msgTypes[6] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use PadlockMessageSealedMetadata.ProtoReflect.Descriptor instead. +func (*PadlockMessageSealedMetadata) Descriptor() ([]byte, []int) { + return file_message_contents_message_proto_rawDescGZIP(), []int{6} +} + +func (x *PadlockMessageSealedMetadata) GetSenderUserAddress() string { + if x != nil { + return x.SenderUserAddress + } + return "" +} + +func (x *PadlockMessageSealedMetadata) GetSenderInstallationId() string { + if x != nil { + return x.SenderInstallationId + } + return "" +} + +func (x *PadlockMessageSealedMetadata) GetRecipientUserAddress() string { + if x != nil { + return x.RecipientUserAddress + } + return "" +} + +func (x *PadlockMessageSealedMetadata) GetRecipientInstallationId() string { + if x != nil { + return x.RecipientInstallationId + } + return "" +} + // Plaintext header included with messages, visible to all +// Recipients can verify this header has not been tampered with. +// Servers are unable to verify if the header has been tampered with. type PadlockMessageHeader struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - SentNs uint64 `protobuf:"varint,1,opt,name=sent_ns,json=sentNs,proto3" json:"sent_ns,omitempty"` - // The session_id is derived via SHA256. Any other identifier will leak the - // sender of the message. - SessionId string `protobuf:"bytes,2,opt,name=session_id,json=sessionId,proto3" json:"session_id,omitempty"` + SentNs uint64 `protobuf:"varint,1,opt,name=sent_ns,json=sentNs,proto3" json:"sent_ns,omitempty"` + SealedMetadata []byte `protobuf:"bytes,2,opt,name=sealed_metadata,json=sealedMetadata,proto3" json:"sealed_metadata,omitempty"` // PadlockMessageSealedMetadata } func (x *PadlockMessageHeader) Reset() { *x = PadlockMessageHeader{} if protoimpl.UnsafeEnabled { - mi := &file_message_contents_message_proto_msgTypes[6] + mi := &file_message_contents_message_proto_msgTypes[7] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -477,7 +551,7 @@ func (x *PadlockMessageHeader) String() string { func (*PadlockMessageHeader) ProtoMessage() {} func (x *PadlockMessageHeader) ProtoReflect() protoreflect.Message { - mi := &file_message_contents_message_proto_msgTypes[6] + mi := &file_message_contents_message_proto_msgTypes[7] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -490,7 +564,7 @@ func (x *PadlockMessageHeader) ProtoReflect() protoreflect.Message { // Deprecated: Use PadlockMessageHeader.ProtoReflect.Descriptor instead. func (*PadlockMessageHeader) Descriptor() ([]byte, []int) { - return file_message_contents_message_proto_rawDescGZIP(), []int{6} + return file_message_contents_message_proto_rawDescGZIP(), []int{7} } func (x *PadlockMessageHeader) GetSentNs() uint64 { @@ -500,41 +574,43 @@ func (x *PadlockMessageHeader) GetSentNs() uint64 { return 0 } -func (x *PadlockMessageHeader) GetSessionId() string { +func (x *PadlockMessageHeader) GetSealedMetadata() []byte { if x != nil { - return x.SessionId + return x.SealedMetadata } - return "" + return nil } // Encrypted body included with messages, only visible to recipients -// - For safety, the sender_account_id and sender_installation_id MUST be -// derived from the session_id in the header by each installation receiving -// the message -// - The recipient is unnecessary to include here - the recipient at the session -// level is the receiving installation, and the recipient at the conversation -// level is whoever is in the conversation referred to by convo_id (multiple -// people in the case of groups) -// - The recipient installation MUST cross-check that the sender_account_id is a -// valid participant of the conversation referred to by convo_id -// - The recipient installation MUST validate that the MessageHeader hashes to -// the header_hash. -// TODO is that sufficient to replace the AssociatedData in v2? +// When receiving a message: +// 1. Decrypt the sealed metadata in the header via SealedSender +// 2. Verify that you match the recipient_user_address and +// recipient_installation_id. Verify that the sender_installation_id matches +// the sender_user_address. +// 2. Find the relevant session using the sender_user_address and +// sender_installation_id in the unsealed metadata +// 3. Use the session to decrypt the payload +// 4. Verify that the header_signature in the decrypted payload matches the +// header bytes +// 5. Verify that the signer of the header_signature matches the +// sender_installation_id +// 6. Verify that both the sender_user and recipient_user are partipants of the +// conversation referenced by convo_id type PadlockMessagePayload struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - MessageVersion uint32 `protobuf:"varint,1,opt,name=message_version,json=messageVersion,proto3" json:"message_version,omitempty"` - HeaderHash []byte `protobuf:"bytes,2,opt,name=header_hash,json=headerHash,proto3" json:"header_hash,omitempty"` // PadlockMessageHeader - ConvoId string `protobuf:"bytes,3,opt,name=convo_id,json=convoId,proto3" json:"convo_id,omitempty"` - ContentBytes []byte `protobuf:"bytes,4,opt,name=content_bytes,json=contentBytes,proto3" json:"content_bytes,omitempty"` // EncodedContent + MessageVersion uint32 `protobuf:"varint,1,opt,name=message_version,json=messageVersion,proto3" json:"message_version,omitempty"` + HeaderSignature []byte `protobuf:"bytes,2,opt,name=header_signature,json=headerSignature,proto3" json:"header_signature,omitempty"` // Signature for PadlockMessageHeader + ConvoId string `protobuf:"bytes,3,opt,name=convo_id,json=convoId,proto3" json:"convo_id,omitempty"` + ContentBytes []byte `protobuf:"bytes,4,opt,name=content_bytes,json=contentBytes,proto3" json:"content_bytes,omitempty"` // EncodedContent } func (x *PadlockMessagePayload) Reset() { *x = PadlockMessagePayload{} if protoimpl.UnsafeEnabled { - mi := &file_message_contents_message_proto_msgTypes[7] + mi := &file_message_contents_message_proto_msgTypes[8] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -547,7 +623,7 @@ func (x *PadlockMessagePayload) String() string { func (*PadlockMessagePayload) ProtoMessage() {} func (x *PadlockMessagePayload) ProtoReflect() protoreflect.Message { - mi := &file_message_contents_message_proto_msgTypes[7] + mi := &file_message_contents_message_proto_msgTypes[8] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -560,7 +636,7 @@ func (x *PadlockMessagePayload) ProtoReflect() protoreflect.Message { // Deprecated: Use PadlockMessagePayload.ProtoReflect.Descriptor instead. func (*PadlockMessagePayload) Descriptor() ([]byte, []int) { - return file_message_contents_message_proto_rawDescGZIP(), []int{7} + return file_message_contents_message_proto_rawDescGZIP(), []int{8} } func (x *PadlockMessagePayload) GetMessageVersion() uint32 { @@ -570,9 +646,9 @@ func (x *PadlockMessagePayload) GetMessageVersion() uint32 { return 0 } -func (x *PadlockMessagePayload) GetHeaderHash() []byte { +func (x *PadlockMessagePayload) GetHeaderSignature() []byte { if x != nil { - return x.HeaderHash + return x.HeaderSignature } return nil } @@ -604,7 +680,7 @@ type PadlockMessageEnvelope struct { func (x *PadlockMessageEnvelope) Reset() { *x = PadlockMessageEnvelope{} if protoimpl.UnsafeEnabled { - mi := &file_message_contents_message_proto_msgTypes[8] + mi := &file_message_contents_message_proto_msgTypes[9] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -617,7 +693,7 @@ func (x *PadlockMessageEnvelope) String() string { func (*PadlockMessageEnvelope) ProtoMessage() {} func (x *PadlockMessageEnvelope) ProtoReflect() protoreflect.Message { - mi := &file_message_contents_message_proto_msgTypes[8] + mi := &file_message_contents_message_proto_msgTypes[9] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -630,7 +706,7 @@ func (x *PadlockMessageEnvelope) ProtoReflect() protoreflect.Message { // Deprecated: Use PadlockMessageEnvelope.ProtoReflect.Descriptor instead. func (*PadlockMessageEnvelope) Descriptor() ([]byte, []int) { - return file_message_contents_message_proto_rawDescGZIP(), []int{8} + return file_message_contents_message_proto_rawDescGZIP(), []int{9} } func (x *PadlockMessageEnvelope) GetHeaderBytes() []byte { @@ -722,33 +798,50 @@ var file_message_contents_message_proto_rawDesc = []byte{ 0x5f, 0x62, 0x79, 0x74, 0x65, 0x73, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0c, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x42, 0x79, 0x74, 0x65, 0x73, 0x42, 0x14, 0x0a, 0x12, 0x5f, 0x72, 0x65, 0x63, 0x69, 0x70, 0x69, 0x65, 0x6e, 0x74, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, - 0x22, 0x4e, 0x0a, 0x14, 0x50, 0x61, 0x64, 0x6c, 0x6f, 0x63, 0x6b, 0x4d, 0x65, 0x73, 0x73, 0x61, - 0x67, 0x65, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x12, 0x17, 0x0a, 0x07, 0x73, 0x65, 0x6e, 0x74, - 0x5f, 0x6e, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x06, 0x73, 0x65, 0x6e, 0x74, 0x4e, - 0x73, 0x12, 0x1d, 0x0a, 0x0a, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x18, - 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x49, 0x64, - 0x22, 0xa1, 0x01, 0x0a, 0x15, 0x50, 0x61, 0x64, 0x6c, 0x6f, 0x63, 0x6b, 0x4d, 0x65, 0x73, 0x73, - 0x61, 0x67, 0x65, 0x50, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x12, 0x27, 0x0a, 0x0f, 0x6d, 0x65, - 0x73, 0x73, 0x61, 0x67, 0x65, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x0d, 0x52, 0x0e, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x56, 0x65, 0x72, 0x73, - 0x69, 0x6f, 0x6e, 0x12, 0x1f, 0x0a, 0x0b, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x5f, 0x68, 0x61, - 0x73, 0x68, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0a, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, - 0x48, 0x61, 0x73, 0x68, 0x12, 0x19, 0x0a, 0x08, 0x63, 0x6f, 0x6e, 0x76, 0x6f, 0x5f, 0x69, 0x64, - 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x63, 0x6f, 0x6e, 0x76, 0x6f, 0x49, 0x64, 0x12, - 0x23, 0x0a, 0x0d, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x5f, 0x62, 0x79, 0x74, 0x65, 0x73, - 0x18, 0x04, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0c, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x42, - 0x79, 0x74, 0x65, 0x73, 0x22, 0x5b, 0x0a, 0x16, 0x50, 0x61, 0x64, 0x6c, 0x6f, 0x63, 0x6b, 0x4d, - 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x45, 0x6e, 0x76, 0x65, 0x6c, 0x6f, 0x70, 0x65, 0x12, 0x21, - 0x0a, 0x0c, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x5f, 0x62, 0x79, 0x74, 0x65, 0x73, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0b, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x42, 0x79, 0x74, 0x65, - 0x73, 0x12, 0x1e, 0x0a, 0x0a, 0x63, 0x69, 0x70, 0x68, 0x65, 0x72, 0x74, 0x65, 0x78, 0x74, 0x18, - 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0a, 0x63, 0x69, 0x70, 0x68, 0x65, 0x72, 0x74, 0x65, 0x78, - 0x74, 0x42, 0x4f, 0x0a, 0x1f, 0x6f, 0x72, 0x67, 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x2e, 0x70, 0x72, - 0x6f, 0x74, 0x6f, 0x2e, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x2e, 0x63, 0x6f, 0x6e, 0x74, - 0x65, 0x6e, 0x74, 0x73, 0x5a, 0x2c, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, - 0x2f, 0x78, 0x6d, 0x74, 0x70, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x76, 0x33, 0x2f, 0x67, - 0x6f, 0x2f, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, - 0x74, 0x73, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x22, 0xf6, 0x01, 0x0a, 0x1c, 0x50, 0x61, 0x64, 0x6c, 0x6f, 0x63, 0x6b, 0x4d, 0x65, 0x73, 0x73, + 0x61, 0x67, 0x65, 0x53, 0x65, 0x61, 0x6c, 0x65, 0x64, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, + 0x61, 0x12, 0x2e, 0x0a, 0x13, 0x73, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x5f, 0x75, 0x73, 0x65, 0x72, + 0x5f, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x11, + 0x73, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x55, 0x73, 0x65, 0x72, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, + 0x73, 0x12, 0x34, 0x0a, 0x16, 0x73, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x5f, 0x69, 0x6e, 0x73, 0x74, + 0x61, 0x6c, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x14, 0x73, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, + 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x12, 0x34, 0x0a, 0x16, 0x72, 0x65, 0x63, 0x69, 0x70, + 0x69, 0x65, 0x6e, 0x74, 0x5f, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, + 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x14, 0x72, 0x65, 0x63, 0x69, 0x70, 0x69, 0x65, + 0x6e, 0x74, 0x55, 0x73, 0x65, 0x72, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x3a, 0x0a, + 0x19, 0x72, 0x65, 0x63, 0x69, 0x70, 0x69, 0x65, 0x6e, 0x74, 0x5f, 0x69, 0x6e, 0x73, 0x74, 0x61, + 0x6c, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x17, 0x72, 0x65, 0x63, 0x69, 0x70, 0x69, 0x65, 0x6e, 0x74, 0x49, 0x6e, 0x73, 0x74, 0x61, + 0x6c, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x22, 0x58, 0x0a, 0x14, 0x50, 0x61, 0x64, + 0x6c, 0x6f, 0x63, 0x6b, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x48, 0x65, 0x61, 0x64, 0x65, + 0x72, 0x12, 0x17, 0x0a, 0x07, 0x73, 0x65, 0x6e, 0x74, 0x5f, 0x6e, 0x73, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x04, 0x52, 0x06, 0x73, 0x65, 0x6e, 0x74, 0x4e, 0x73, 0x12, 0x27, 0x0a, 0x0f, 0x73, 0x65, + 0x61, 0x6c, 0x65, 0x64, 0x5f, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x0c, 0x52, 0x0e, 0x73, 0x65, 0x61, 0x6c, 0x65, 0x64, 0x4d, 0x65, 0x74, 0x61, 0x64, + 0x61, 0x74, 0x61, 0x22, 0xab, 0x01, 0x0a, 0x15, 0x50, 0x61, 0x64, 0x6c, 0x6f, 0x63, 0x6b, 0x4d, + 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x50, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x12, 0x27, 0x0a, + 0x0f, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0e, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x56, + 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x29, 0x0a, 0x10, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, + 0x5f, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, + 0x52, 0x0f, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, + 0x65, 0x12, 0x19, 0x0a, 0x08, 0x63, 0x6f, 0x6e, 0x76, 0x6f, 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x07, 0x63, 0x6f, 0x6e, 0x76, 0x6f, 0x49, 0x64, 0x12, 0x23, 0x0a, 0x0d, + 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x5f, 0x62, 0x79, 0x74, 0x65, 0x73, 0x18, 0x04, 0x20, + 0x01, 0x28, 0x0c, 0x52, 0x0c, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x42, 0x79, 0x74, 0x65, + 0x73, 0x22, 0x5b, 0x0a, 0x16, 0x50, 0x61, 0x64, 0x6c, 0x6f, 0x63, 0x6b, 0x4d, 0x65, 0x73, 0x73, + 0x61, 0x67, 0x65, 0x45, 0x6e, 0x76, 0x65, 0x6c, 0x6f, 0x70, 0x65, 0x12, 0x21, 0x0a, 0x0c, 0x68, + 0x65, 0x61, 0x64, 0x65, 0x72, 0x5f, 0x62, 0x79, 0x74, 0x65, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x0c, 0x52, 0x0b, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x42, 0x79, 0x74, 0x65, 0x73, 0x12, 0x1e, + 0x0a, 0x0a, 0x63, 0x69, 0x70, 0x68, 0x65, 0x72, 0x74, 0x65, 0x78, 0x74, 0x18, 0x02, 0x20, 0x01, + 0x28, 0x0c, 0x52, 0x0a, 0x63, 0x69, 0x70, 0x68, 0x65, 0x72, 0x74, 0x65, 0x78, 0x74, 0x42, 0x4f, + 0x0a, 0x1f, 0x6f, 0x72, 0x67, 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, + 0x2e, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, + 0x73, 0x5a, 0x2c, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x78, 0x6d, + 0x74, 0x70, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x76, 0x33, 0x2f, 0x67, 0x6f, 0x2f, 0x6d, + 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0x62, + 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( @@ -763,29 +856,30 @@ func file_message_contents_message_proto_rawDescGZIP() []byte { return file_message_contents_message_proto_rawDescData } -var file_message_contents_message_proto_msgTypes = make([]protoimpl.MessageInfo, 9) +var file_message_contents_message_proto_msgTypes = make([]protoimpl.MessageInfo, 10) var file_message_contents_message_proto_goTypes = []interface{}{ - (*MessageHeaderV1)(nil), // 0: xmtp.message_contents.MessageHeaderV1 - (*MessageV1)(nil), // 1: xmtp.message_contents.MessageV1 - (*MessageHeaderV2)(nil), // 2: xmtp.message_contents.MessageHeaderV2 - (*MessageV2)(nil), // 3: xmtp.message_contents.MessageV2 - (*Message)(nil), // 4: xmtp.message_contents.Message - (*DecodedMessage)(nil), // 5: xmtp.message_contents.DecodedMessage - (*PadlockMessageHeader)(nil), // 6: xmtp.message_contents.PadlockMessageHeader - (*PadlockMessagePayload)(nil), // 7: xmtp.message_contents.PadlockMessagePayload - (*PadlockMessageEnvelope)(nil), // 8: xmtp.message_contents.PadlockMessageEnvelope - (*PublicKeyBundle)(nil), // 9: xmtp.message_contents.PublicKeyBundle - (*Ciphertext)(nil), // 10: xmtp.message_contents.Ciphertext - (*ConversationReference)(nil), // 11: xmtp.message_contents.ConversationReference + (*MessageHeaderV1)(nil), // 0: xmtp.message_contents.MessageHeaderV1 + (*MessageV1)(nil), // 1: xmtp.message_contents.MessageV1 + (*MessageHeaderV2)(nil), // 2: xmtp.message_contents.MessageHeaderV2 + (*MessageV2)(nil), // 3: xmtp.message_contents.MessageV2 + (*Message)(nil), // 4: xmtp.message_contents.Message + (*DecodedMessage)(nil), // 5: xmtp.message_contents.DecodedMessage + (*PadlockMessageSealedMetadata)(nil), // 6: xmtp.message_contents.PadlockMessageSealedMetadata + (*PadlockMessageHeader)(nil), // 7: xmtp.message_contents.PadlockMessageHeader + (*PadlockMessagePayload)(nil), // 8: xmtp.message_contents.PadlockMessagePayload + (*PadlockMessageEnvelope)(nil), // 9: xmtp.message_contents.PadlockMessageEnvelope + (*PublicKeyBundle)(nil), // 10: xmtp.message_contents.PublicKeyBundle + (*Ciphertext)(nil), // 11: xmtp.message_contents.Ciphertext + (*ConversationReference)(nil), // 12: xmtp.message_contents.ConversationReference } var file_message_contents_message_proto_depIdxs = []int32{ - 9, // 0: xmtp.message_contents.MessageHeaderV1.sender:type_name -> xmtp.message_contents.PublicKeyBundle - 9, // 1: xmtp.message_contents.MessageHeaderV1.recipient:type_name -> xmtp.message_contents.PublicKeyBundle - 10, // 2: xmtp.message_contents.MessageV1.ciphertext:type_name -> xmtp.message_contents.Ciphertext - 10, // 3: xmtp.message_contents.MessageV2.ciphertext:type_name -> xmtp.message_contents.Ciphertext + 10, // 0: xmtp.message_contents.MessageHeaderV1.sender:type_name -> xmtp.message_contents.PublicKeyBundle + 10, // 1: xmtp.message_contents.MessageHeaderV1.recipient:type_name -> xmtp.message_contents.PublicKeyBundle + 11, // 2: xmtp.message_contents.MessageV1.ciphertext:type_name -> xmtp.message_contents.Ciphertext + 11, // 3: xmtp.message_contents.MessageV2.ciphertext:type_name -> xmtp.message_contents.Ciphertext 1, // 4: xmtp.message_contents.Message.v1:type_name -> xmtp.message_contents.MessageV1 3, // 5: xmtp.message_contents.Message.v2:type_name -> xmtp.message_contents.MessageV2 - 11, // 6: xmtp.message_contents.DecodedMessage.conversation:type_name -> xmtp.message_contents.ConversationReference + 12, // 6: xmtp.message_contents.DecodedMessage.conversation:type_name -> xmtp.message_contents.ConversationReference 7, // [7:7] is the sub-list for method output_type 7, // [7:7] is the sub-list for method input_type 7, // [7:7] is the sub-list for extension type_name @@ -875,7 +969,7 @@ func file_message_contents_message_proto_init() { } } file_message_contents_message_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*PadlockMessageHeader); i { + switch v := v.(*PadlockMessageSealedMetadata); i { case 0: return &v.state case 1: @@ -887,7 +981,7 @@ func file_message_contents_message_proto_init() { } } file_message_contents_message_proto_msgTypes[7].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*PadlockMessagePayload); i { + switch v := v.(*PadlockMessageHeader); i { case 0: return &v.state case 1: @@ -899,6 +993,18 @@ func file_message_contents_message_proto_init() { } } file_message_contents_message_proto_msgTypes[8].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*PadlockMessagePayload); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_message_contents_message_proto_msgTypes[9].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*PadlockMessageEnvelope); i { case 0: return &v.state @@ -922,7 +1028,7 @@ func file_message_contents_message_proto_init() { GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_message_contents_message_proto_rawDesc, NumEnums: 0, - NumMessages: 9, + NumMessages: 10, NumExtensions: 0, NumServices: 0, }, diff --git a/proto/message_contents/message.proto b/proto/message_contents/message.proto index 41ff1859..4cd77162 100644 --- a/proto/message_contents/message.proto +++ b/proto/message_contents/message.proto @@ -69,30 +69,42 @@ message DecodedMessage { bytes content_bytes = 8; // encapsulates EncodedContent } +// Metadata that is encrypted via SealedSender and only visible to the recipient +// Currently we do not actually encrypt this, actual implementation of +// SealedSender will be added shortly. +message PadlockMessageSealedMetadata { + string sender_user_address = 1; + string sender_installation_id = 2; + string recipient_user_address = 3; + string recipient_installation_id = 4; +} + // Plaintext header included with messages, visible to all +// Recipients can verify this header has not been tampered with. +// Servers are unable to verify if the header has been tampered with. message PadlockMessageHeader { uint64 sent_ns = 1; - // The session_id is derived via SHA256. Any other identifier will leak the - // sender of the message. - string session_id = 2; + bytes sealed_metadata = 2; // PadlockMessageSealedMetadata } // Encrypted body included with messages, only visible to recipients -// - For safety, the sender_account_id and sender_installation_id MUST be -// derived from the session_id in the header by each installation receiving -// the message -// - The recipient is unnecessary to include here - the recipient at the session -// level is the receiving installation, and the recipient at the conversation -// level is whoever is in the conversation referred to by convo_id (multiple -// people in the case of groups) -// - The recipient installation MUST cross-check that the sender_account_id is a -// valid participant of the conversation referred to by convo_id -// - The recipient installation MUST validate that the MessageHeader hashes to -// the header_hash. -// TODO is that sufficient to replace the AssociatedData in v2? +// When receiving a message: +// 1. Decrypt the sealed metadata in the header via SealedSender +// 2. Verify that you match the recipient_user_address and +// recipient_installation_id. Verify that the sender_installation_id matches +// the sender_user_address. +// 2. Find the relevant session using the sender_user_address and +// sender_installation_id in the unsealed metadata +// 3. Use the session to decrypt the payload +// 4. Verify that the header_signature in the decrypted payload matches the +// header bytes +// 5. Verify that the signer of the header_signature matches the +// sender_installation_id +// 6. Verify that both the sender_user and recipient_user are partipants of the +// conversation referenced by convo_id message PadlockMessagePayload { uint32 message_version = 1; - bytes header_hash = 2; // PadlockMessageHeader + bytes header_signature = 2; // Signature for PadlockMessageHeader string convo_id = 3; bytes content_bytes = 4; // EncodedContent } From c0dca67776577f4fd7efabac696130b7d27dacf3 Mon Sep 17 00:00:00 2001 From: Richard Hua Date: Wed, 26 Jul 2023 12:02:24 -0700 Subject: [PATCH 19/30] refactor: use enum for message version --- go/message_contents/message.pb.go | 164 ++++++++++++++++++--------- proto/message_contents/message.proto | 7 +- 2 files changed, 116 insertions(+), 55 deletions(-) diff --git a/go/message_contents/message.pb.go b/go/message_contents/message.pb.go index 56241643..ef115ff3 100644 --- a/go/message_contents/message.pb.go +++ b/go/message_contents/message.pb.go @@ -22,6 +22,50 @@ const ( _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) ) +// The version used for the decrypted padlock message payload +type PadlockMessagePayloadVersion int32 + +const ( + PadlockMessagePayloadVersion_PADLOCK_MESSAGE_PAYLOAD_VERSION_ZERO PadlockMessagePayloadVersion = 0 +) + +// Enum value maps for PadlockMessagePayloadVersion. +var ( + PadlockMessagePayloadVersion_name = map[int32]string{ + 0: "PADLOCK_MESSAGE_PAYLOAD_VERSION_ZERO", + } + PadlockMessagePayloadVersion_value = map[string]int32{ + "PADLOCK_MESSAGE_PAYLOAD_VERSION_ZERO": 0, + } +) + +func (x PadlockMessagePayloadVersion) Enum() *PadlockMessagePayloadVersion { + p := new(PadlockMessagePayloadVersion) + *p = x + return p +} + +func (x PadlockMessagePayloadVersion) String() string { + return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) +} + +func (PadlockMessagePayloadVersion) Descriptor() protoreflect.EnumDescriptor { + return file_message_contents_message_proto_enumTypes[0].Descriptor() +} + +func (PadlockMessagePayloadVersion) Type() protoreflect.EnumType { + return &file_message_contents_message_proto_enumTypes[0] +} + +func (x PadlockMessagePayloadVersion) Number() protoreflect.EnumNumber { + return protoreflect.EnumNumber(x) +} + +// Deprecated: Use PadlockMessagePayloadVersion.Descriptor instead. +func (PadlockMessagePayloadVersion) EnumDescriptor() ([]byte, []int) { + return file_message_contents_message_proto_rawDescGZIP(), []int{0} +} + // Message header is encoded separately as the bytes are also used // as associated data for authenticated encryption type MessageHeaderV1 struct { @@ -601,10 +645,10 @@ type PadlockMessagePayload struct { sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - MessageVersion uint32 `protobuf:"varint,1,opt,name=message_version,json=messageVersion,proto3" json:"message_version,omitempty"` - HeaderSignature []byte `protobuf:"bytes,2,opt,name=header_signature,json=headerSignature,proto3" json:"header_signature,omitempty"` // Signature for PadlockMessageHeader - ConvoId string `protobuf:"bytes,3,opt,name=convo_id,json=convoId,proto3" json:"convo_id,omitempty"` - ContentBytes []byte `protobuf:"bytes,4,opt,name=content_bytes,json=contentBytes,proto3" json:"content_bytes,omitempty"` // EncodedContent + MessageVersion PadlockMessagePayloadVersion `protobuf:"varint,1,opt,name=message_version,json=messageVersion,proto3,enum=xmtp.message_contents.PadlockMessagePayloadVersion" json:"message_version,omitempty"` + HeaderSignature []byte `protobuf:"bytes,2,opt,name=header_signature,json=headerSignature,proto3" json:"header_signature,omitempty"` // Signature for PadlockMessageHeader + ConvoId string `protobuf:"bytes,3,opt,name=convo_id,json=convoId,proto3" json:"convo_id,omitempty"` + ContentBytes []byte `protobuf:"bytes,4,opt,name=content_bytes,json=contentBytes,proto3" json:"content_bytes,omitempty"` // EncodedContent } func (x *PadlockMessagePayload) Reset() { @@ -639,11 +683,11 @@ func (*PadlockMessagePayload) Descriptor() ([]byte, []int) { return file_message_contents_message_proto_rawDescGZIP(), []int{8} } -func (x *PadlockMessagePayload) GetMessageVersion() uint32 { +func (x *PadlockMessagePayload) GetMessageVersion() PadlockMessagePayloadVersion { if x != nil { return x.MessageVersion } - return 0 + return PadlockMessagePayloadVersion_PADLOCK_MESSAGE_PAYLOAD_VERSION_ZERO } func (x *PadlockMessagePayload) GetHeaderSignature() []byte { @@ -819,29 +863,37 @@ var file_message_contents_message_proto_rawDesc = []byte{ 0x28, 0x04, 0x52, 0x06, 0x73, 0x65, 0x6e, 0x74, 0x4e, 0x73, 0x12, 0x27, 0x0a, 0x0f, 0x73, 0x65, 0x61, 0x6c, 0x65, 0x64, 0x5f, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0e, 0x73, 0x65, 0x61, 0x6c, 0x65, 0x64, 0x4d, 0x65, 0x74, 0x61, 0x64, - 0x61, 0x74, 0x61, 0x22, 0xab, 0x01, 0x0a, 0x15, 0x50, 0x61, 0x64, 0x6c, 0x6f, 0x63, 0x6b, 0x4d, - 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x50, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x12, 0x27, 0x0a, + 0x61, 0x74, 0x61, 0x22, 0xe0, 0x01, 0x0a, 0x15, 0x50, 0x61, 0x64, 0x6c, 0x6f, 0x63, 0x6b, 0x4d, + 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x50, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x12, 0x5c, 0x0a, 0x0f, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0e, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x56, - 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x29, 0x0a, 0x10, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, - 0x5f, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, - 0x52, 0x0f, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, - 0x65, 0x12, 0x19, 0x0a, 0x08, 0x63, 0x6f, 0x6e, 0x76, 0x6f, 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x07, 0x63, 0x6f, 0x6e, 0x76, 0x6f, 0x49, 0x64, 0x12, 0x23, 0x0a, 0x0d, - 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x5f, 0x62, 0x79, 0x74, 0x65, 0x73, 0x18, 0x04, 0x20, - 0x01, 0x28, 0x0c, 0x52, 0x0c, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x42, 0x79, 0x74, 0x65, - 0x73, 0x22, 0x5b, 0x0a, 0x16, 0x50, 0x61, 0x64, 0x6c, 0x6f, 0x63, 0x6b, 0x4d, 0x65, 0x73, 0x73, - 0x61, 0x67, 0x65, 0x45, 0x6e, 0x76, 0x65, 0x6c, 0x6f, 0x70, 0x65, 0x12, 0x21, 0x0a, 0x0c, 0x68, - 0x65, 0x61, 0x64, 0x65, 0x72, 0x5f, 0x62, 0x79, 0x74, 0x65, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x0c, 0x52, 0x0b, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x42, 0x79, 0x74, 0x65, 0x73, 0x12, 0x1e, - 0x0a, 0x0a, 0x63, 0x69, 0x70, 0x68, 0x65, 0x72, 0x74, 0x65, 0x78, 0x74, 0x18, 0x02, 0x20, 0x01, - 0x28, 0x0c, 0x52, 0x0a, 0x63, 0x69, 0x70, 0x68, 0x65, 0x72, 0x74, 0x65, 0x78, 0x74, 0x42, 0x4f, - 0x0a, 0x1f, 0x6f, 0x72, 0x67, 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, - 0x2e, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, - 0x73, 0x5a, 0x2c, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x78, 0x6d, - 0x74, 0x70, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x76, 0x33, 0x2f, 0x67, 0x6f, 0x2f, 0x6d, - 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0x62, - 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x33, 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x2e, 0x6d, 0x65, + 0x73, 0x73, 0x61, 0x67, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0x2e, 0x50, + 0x61, 0x64, 0x6c, 0x6f, 0x63, 0x6b, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x50, 0x61, 0x79, + 0x6c, 0x6f, 0x61, 0x64, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x0e, 0x6d, 0x65, 0x73, + 0x73, 0x61, 0x67, 0x65, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x29, 0x0a, 0x10, 0x68, + 0x65, 0x61, 0x64, 0x65, 0x72, 0x5f, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0f, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x53, 0x69, 0x67, + 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x12, 0x19, 0x0a, 0x08, 0x63, 0x6f, 0x6e, 0x76, 0x6f, 0x5f, + 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x63, 0x6f, 0x6e, 0x76, 0x6f, 0x49, + 0x64, 0x12, 0x23, 0x0a, 0x0d, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x5f, 0x62, 0x79, 0x74, + 0x65, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0c, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, + 0x74, 0x42, 0x79, 0x74, 0x65, 0x73, 0x22, 0x5b, 0x0a, 0x16, 0x50, 0x61, 0x64, 0x6c, 0x6f, 0x63, + 0x6b, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x45, 0x6e, 0x76, 0x65, 0x6c, 0x6f, 0x70, 0x65, + 0x12, 0x21, 0x0a, 0x0c, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x5f, 0x62, 0x79, 0x74, 0x65, 0x73, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0b, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x42, 0x79, + 0x74, 0x65, 0x73, 0x12, 0x1e, 0x0a, 0x0a, 0x63, 0x69, 0x70, 0x68, 0x65, 0x72, 0x74, 0x65, 0x78, + 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0a, 0x63, 0x69, 0x70, 0x68, 0x65, 0x72, 0x74, + 0x65, 0x78, 0x74, 0x2a, 0x48, 0x0a, 0x1c, 0x50, 0x61, 0x64, 0x6c, 0x6f, 0x63, 0x6b, 0x4d, 0x65, + 0x73, 0x73, 0x61, 0x67, 0x65, 0x50, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x56, 0x65, 0x72, 0x73, + 0x69, 0x6f, 0x6e, 0x12, 0x28, 0x0a, 0x24, 0x50, 0x41, 0x44, 0x4c, 0x4f, 0x43, 0x4b, 0x5f, 0x4d, + 0x45, 0x53, 0x53, 0x41, 0x47, 0x45, 0x5f, 0x50, 0x41, 0x59, 0x4c, 0x4f, 0x41, 0x44, 0x5f, 0x56, + 0x45, 0x52, 0x53, 0x49, 0x4f, 0x4e, 0x5f, 0x5a, 0x45, 0x52, 0x4f, 0x10, 0x00, 0x42, 0x4f, 0x0a, + 0x1f, 0x6f, 0x72, 0x67, 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, + 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, + 0x5a, 0x2c, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x78, 0x6d, 0x74, + 0x70, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x76, 0x33, 0x2f, 0x67, 0x6f, 0x2f, 0x6d, 0x65, + 0x73, 0x73, 0x61, 0x67, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0x62, 0x06, + 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( @@ -856,35 +908,38 @@ func file_message_contents_message_proto_rawDescGZIP() []byte { return file_message_contents_message_proto_rawDescData } +var file_message_contents_message_proto_enumTypes = make([]protoimpl.EnumInfo, 1) var file_message_contents_message_proto_msgTypes = make([]protoimpl.MessageInfo, 10) var file_message_contents_message_proto_goTypes = []interface{}{ - (*MessageHeaderV1)(nil), // 0: xmtp.message_contents.MessageHeaderV1 - (*MessageV1)(nil), // 1: xmtp.message_contents.MessageV1 - (*MessageHeaderV2)(nil), // 2: xmtp.message_contents.MessageHeaderV2 - (*MessageV2)(nil), // 3: xmtp.message_contents.MessageV2 - (*Message)(nil), // 4: xmtp.message_contents.Message - (*DecodedMessage)(nil), // 5: xmtp.message_contents.DecodedMessage - (*PadlockMessageSealedMetadata)(nil), // 6: xmtp.message_contents.PadlockMessageSealedMetadata - (*PadlockMessageHeader)(nil), // 7: xmtp.message_contents.PadlockMessageHeader - (*PadlockMessagePayload)(nil), // 8: xmtp.message_contents.PadlockMessagePayload - (*PadlockMessageEnvelope)(nil), // 9: xmtp.message_contents.PadlockMessageEnvelope - (*PublicKeyBundle)(nil), // 10: xmtp.message_contents.PublicKeyBundle - (*Ciphertext)(nil), // 11: xmtp.message_contents.Ciphertext - (*ConversationReference)(nil), // 12: xmtp.message_contents.ConversationReference + (PadlockMessagePayloadVersion)(0), // 0: xmtp.message_contents.PadlockMessagePayloadVersion + (*MessageHeaderV1)(nil), // 1: xmtp.message_contents.MessageHeaderV1 + (*MessageV1)(nil), // 2: xmtp.message_contents.MessageV1 + (*MessageHeaderV2)(nil), // 3: xmtp.message_contents.MessageHeaderV2 + (*MessageV2)(nil), // 4: xmtp.message_contents.MessageV2 + (*Message)(nil), // 5: xmtp.message_contents.Message + (*DecodedMessage)(nil), // 6: xmtp.message_contents.DecodedMessage + (*PadlockMessageSealedMetadata)(nil), // 7: xmtp.message_contents.PadlockMessageSealedMetadata + (*PadlockMessageHeader)(nil), // 8: xmtp.message_contents.PadlockMessageHeader + (*PadlockMessagePayload)(nil), // 9: xmtp.message_contents.PadlockMessagePayload + (*PadlockMessageEnvelope)(nil), // 10: xmtp.message_contents.PadlockMessageEnvelope + (*PublicKeyBundle)(nil), // 11: xmtp.message_contents.PublicKeyBundle + (*Ciphertext)(nil), // 12: xmtp.message_contents.Ciphertext + (*ConversationReference)(nil), // 13: xmtp.message_contents.ConversationReference } var file_message_contents_message_proto_depIdxs = []int32{ - 10, // 0: xmtp.message_contents.MessageHeaderV1.sender:type_name -> xmtp.message_contents.PublicKeyBundle - 10, // 1: xmtp.message_contents.MessageHeaderV1.recipient:type_name -> xmtp.message_contents.PublicKeyBundle - 11, // 2: xmtp.message_contents.MessageV1.ciphertext:type_name -> xmtp.message_contents.Ciphertext - 11, // 3: xmtp.message_contents.MessageV2.ciphertext:type_name -> xmtp.message_contents.Ciphertext - 1, // 4: xmtp.message_contents.Message.v1:type_name -> xmtp.message_contents.MessageV1 - 3, // 5: xmtp.message_contents.Message.v2:type_name -> xmtp.message_contents.MessageV2 - 12, // 6: xmtp.message_contents.DecodedMessage.conversation:type_name -> xmtp.message_contents.ConversationReference - 7, // [7:7] is the sub-list for method output_type - 7, // [7:7] is the sub-list for method input_type - 7, // [7:7] is the sub-list for extension type_name - 7, // [7:7] is the sub-list for extension extendee - 0, // [0:7] is the sub-list for field type_name + 11, // 0: xmtp.message_contents.MessageHeaderV1.sender:type_name -> xmtp.message_contents.PublicKeyBundle + 11, // 1: xmtp.message_contents.MessageHeaderV1.recipient:type_name -> xmtp.message_contents.PublicKeyBundle + 12, // 2: xmtp.message_contents.MessageV1.ciphertext:type_name -> xmtp.message_contents.Ciphertext + 12, // 3: xmtp.message_contents.MessageV2.ciphertext:type_name -> xmtp.message_contents.Ciphertext + 2, // 4: xmtp.message_contents.Message.v1:type_name -> xmtp.message_contents.MessageV1 + 4, // 5: xmtp.message_contents.Message.v2:type_name -> xmtp.message_contents.MessageV2 + 13, // 6: xmtp.message_contents.DecodedMessage.conversation:type_name -> xmtp.message_contents.ConversationReference + 0, // 7: xmtp.message_contents.PadlockMessagePayload.message_version:type_name -> xmtp.message_contents.PadlockMessagePayloadVersion + 8, // [8:8] is the sub-list for method output_type + 8, // [8:8] is the sub-list for method input_type + 8, // [8:8] is the sub-list for extension type_name + 8, // [8:8] is the sub-list for extension extendee + 0, // [0:8] is the sub-list for field type_name } func init() { file_message_contents_message_proto_init() } @@ -1027,13 +1082,14 @@ func file_message_contents_message_proto_init() { File: protoimpl.DescBuilder{ GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_message_contents_message_proto_rawDesc, - NumEnums: 0, + NumEnums: 1, NumMessages: 10, NumExtensions: 0, NumServices: 0, }, GoTypes: file_message_contents_message_proto_goTypes, DependencyIndexes: file_message_contents_message_proto_depIdxs, + EnumInfos: file_message_contents_message_proto_enumTypes, MessageInfos: file_message_contents_message_proto_msgTypes, }.Build() File_message_contents_message_proto = out.File diff --git a/proto/message_contents/message.proto b/proto/message_contents/message.proto index 4cd77162..0cea1f50 100644 --- a/proto/message_contents/message.proto +++ b/proto/message_contents/message.proto @@ -87,6 +87,11 @@ message PadlockMessageHeader { bytes sealed_metadata = 2; // PadlockMessageSealedMetadata } +// The version used for the decrypted padlock message payload +enum PadlockMessagePayloadVersion { + PADLOCK_MESSAGE_PAYLOAD_VERSION_ZERO = 0; +} + // Encrypted body included with messages, only visible to recipients // When receiving a message: // 1. Decrypt the sealed metadata in the header via SealedSender @@ -103,7 +108,7 @@ message PadlockMessageHeader { // 6. Verify that both the sender_user and recipient_user are partipants of the // conversation referenced by convo_id message PadlockMessagePayload { - uint32 message_version = 1; + PadlockMessagePayloadVersion message_version = 1; bytes header_signature = 2; // Signature for PadlockMessageHeader string convo_id = 3; bytes content_bytes = 4; // EncodedContent From 1c76309143ad03a7ed32a2f8d7cb9d882c691bc1 Mon Sep 17 00:00:00 2001 From: Richard Hua Date: Wed, 26 Jul 2023 12:31:15 -0700 Subject: [PATCH 20/30] refactor: use RecoverableECDSASignature instead of bytes, fix protolint --- go/message_contents/message.pb.go | 480 ++---------------------- proto/message_contents/message.proto | 51 --- proto/v3/message_contents/message.proto | 61 +++ 3 files changed, 91 insertions(+), 501 deletions(-) create mode 100644 proto/v3/message_contents/message.proto diff --git a/go/message_contents/message.pb.go b/go/message_contents/message.pb.go index ef115ff3..2fcd9ac8 100644 --- a/go/message_contents/message.pb.go +++ b/go/message_contents/message.pb.go @@ -22,50 +22,6 @@ const ( _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) ) -// The version used for the decrypted padlock message payload -type PadlockMessagePayloadVersion int32 - -const ( - PadlockMessagePayloadVersion_PADLOCK_MESSAGE_PAYLOAD_VERSION_ZERO PadlockMessagePayloadVersion = 0 -) - -// Enum value maps for PadlockMessagePayloadVersion. -var ( - PadlockMessagePayloadVersion_name = map[int32]string{ - 0: "PADLOCK_MESSAGE_PAYLOAD_VERSION_ZERO", - } - PadlockMessagePayloadVersion_value = map[string]int32{ - "PADLOCK_MESSAGE_PAYLOAD_VERSION_ZERO": 0, - } -) - -func (x PadlockMessagePayloadVersion) Enum() *PadlockMessagePayloadVersion { - p := new(PadlockMessagePayloadVersion) - *p = x - return p -} - -func (x PadlockMessagePayloadVersion) String() string { - return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) -} - -func (PadlockMessagePayloadVersion) Descriptor() protoreflect.EnumDescriptor { - return file_message_contents_message_proto_enumTypes[0].Descriptor() -} - -func (PadlockMessagePayloadVersion) Type() protoreflect.EnumType { - return &file_message_contents_message_proto_enumTypes[0] -} - -func (x PadlockMessagePayloadVersion) Number() protoreflect.EnumNumber { - return protoreflect.EnumNumber(x) -} - -// Deprecated: Use PadlockMessagePayloadVersion.Descriptor instead. -func (PadlockMessagePayloadVersion) EnumDescriptor() ([]byte, []int) { - return file_message_contents_message_proto_rawDescGZIP(), []int{0} -} - // Message header is encoded separately as the bytes are also used // as associated data for authenticated encryption type MessageHeaderV1 struct { @@ -493,280 +449,6 @@ func (x *DecodedMessage) GetContentBytes() []byte { return nil } -// Metadata that is encrypted via SealedSender and only visible to the recipient -// Currently we do not actually encrypt this, actual implementation of -// SealedSender will be added shortly. -type PadlockMessageSealedMetadata struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - SenderUserAddress string `protobuf:"bytes,1,opt,name=sender_user_address,json=senderUserAddress,proto3" json:"sender_user_address,omitempty"` - SenderInstallationId string `protobuf:"bytes,2,opt,name=sender_installation_id,json=senderInstallationId,proto3" json:"sender_installation_id,omitempty"` - RecipientUserAddress string `protobuf:"bytes,3,opt,name=recipient_user_address,json=recipientUserAddress,proto3" json:"recipient_user_address,omitempty"` - RecipientInstallationId string `protobuf:"bytes,4,opt,name=recipient_installation_id,json=recipientInstallationId,proto3" json:"recipient_installation_id,omitempty"` -} - -func (x *PadlockMessageSealedMetadata) Reset() { - *x = PadlockMessageSealedMetadata{} - if protoimpl.UnsafeEnabled { - mi := &file_message_contents_message_proto_msgTypes[6] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *PadlockMessageSealedMetadata) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*PadlockMessageSealedMetadata) ProtoMessage() {} - -func (x *PadlockMessageSealedMetadata) ProtoReflect() protoreflect.Message { - mi := &file_message_contents_message_proto_msgTypes[6] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use PadlockMessageSealedMetadata.ProtoReflect.Descriptor instead. -func (*PadlockMessageSealedMetadata) Descriptor() ([]byte, []int) { - return file_message_contents_message_proto_rawDescGZIP(), []int{6} -} - -func (x *PadlockMessageSealedMetadata) GetSenderUserAddress() string { - if x != nil { - return x.SenderUserAddress - } - return "" -} - -func (x *PadlockMessageSealedMetadata) GetSenderInstallationId() string { - if x != nil { - return x.SenderInstallationId - } - return "" -} - -func (x *PadlockMessageSealedMetadata) GetRecipientUserAddress() string { - if x != nil { - return x.RecipientUserAddress - } - return "" -} - -func (x *PadlockMessageSealedMetadata) GetRecipientInstallationId() string { - if x != nil { - return x.RecipientInstallationId - } - return "" -} - -// Plaintext header included with messages, visible to all -// Recipients can verify this header has not been tampered with. -// Servers are unable to verify if the header has been tampered with. -type PadlockMessageHeader struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - SentNs uint64 `protobuf:"varint,1,opt,name=sent_ns,json=sentNs,proto3" json:"sent_ns,omitempty"` - SealedMetadata []byte `protobuf:"bytes,2,opt,name=sealed_metadata,json=sealedMetadata,proto3" json:"sealed_metadata,omitempty"` // PadlockMessageSealedMetadata -} - -func (x *PadlockMessageHeader) Reset() { - *x = PadlockMessageHeader{} - if protoimpl.UnsafeEnabled { - mi := &file_message_contents_message_proto_msgTypes[7] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *PadlockMessageHeader) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*PadlockMessageHeader) ProtoMessage() {} - -func (x *PadlockMessageHeader) ProtoReflect() protoreflect.Message { - mi := &file_message_contents_message_proto_msgTypes[7] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use PadlockMessageHeader.ProtoReflect.Descriptor instead. -func (*PadlockMessageHeader) Descriptor() ([]byte, []int) { - return file_message_contents_message_proto_rawDescGZIP(), []int{7} -} - -func (x *PadlockMessageHeader) GetSentNs() uint64 { - if x != nil { - return x.SentNs - } - return 0 -} - -func (x *PadlockMessageHeader) GetSealedMetadata() []byte { - if x != nil { - return x.SealedMetadata - } - return nil -} - -// Encrypted body included with messages, only visible to recipients -// When receiving a message: -// 1. Decrypt the sealed metadata in the header via SealedSender -// 2. Verify that you match the recipient_user_address and -// recipient_installation_id. Verify that the sender_installation_id matches -// the sender_user_address. -// 2. Find the relevant session using the sender_user_address and -// sender_installation_id in the unsealed metadata -// 3. Use the session to decrypt the payload -// 4. Verify that the header_signature in the decrypted payload matches the -// header bytes -// 5. Verify that the signer of the header_signature matches the -// sender_installation_id -// 6. Verify that both the sender_user and recipient_user are partipants of the -// conversation referenced by convo_id -type PadlockMessagePayload struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - MessageVersion PadlockMessagePayloadVersion `protobuf:"varint,1,opt,name=message_version,json=messageVersion,proto3,enum=xmtp.message_contents.PadlockMessagePayloadVersion" json:"message_version,omitempty"` - HeaderSignature []byte `protobuf:"bytes,2,opt,name=header_signature,json=headerSignature,proto3" json:"header_signature,omitempty"` // Signature for PadlockMessageHeader - ConvoId string `protobuf:"bytes,3,opt,name=convo_id,json=convoId,proto3" json:"convo_id,omitempty"` - ContentBytes []byte `protobuf:"bytes,4,opt,name=content_bytes,json=contentBytes,proto3" json:"content_bytes,omitempty"` // EncodedContent -} - -func (x *PadlockMessagePayload) Reset() { - *x = PadlockMessagePayload{} - if protoimpl.UnsafeEnabled { - mi := &file_message_contents_message_proto_msgTypes[8] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *PadlockMessagePayload) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*PadlockMessagePayload) ProtoMessage() {} - -func (x *PadlockMessagePayload) ProtoReflect() protoreflect.Message { - mi := &file_message_contents_message_proto_msgTypes[8] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use PadlockMessagePayload.ProtoReflect.Descriptor instead. -func (*PadlockMessagePayload) Descriptor() ([]byte, []int) { - return file_message_contents_message_proto_rawDescGZIP(), []int{8} -} - -func (x *PadlockMessagePayload) GetMessageVersion() PadlockMessagePayloadVersion { - if x != nil { - return x.MessageVersion - } - return PadlockMessagePayloadVersion_PADLOCK_MESSAGE_PAYLOAD_VERSION_ZERO -} - -func (x *PadlockMessagePayload) GetHeaderSignature() []byte { - if x != nil { - return x.HeaderSignature - } - return nil -} - -func (x *PadlockMessagePayload) GetConvoId() string { - if x != nil { - return x.ConvoId - } - return "" -} - -func (x *PadlockMessagePayload) GetContentBytes() []byte { - if x != nil { - return x.ContentBytes - } - return nil -} - -// Combines the plaintext header with the encrypted payload -type PadlockMessageEnvelope struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - HeaderBytes []byte `protobuf:"bytes,1,opt,name=header_bytes,json=headerBytes,proto3" json:"header_bytes,omitempty"` // PadlockMessageHeader - Ciphertext []byte `protobuf:"bytes,2,opt,name=ciphertext,proto3" json:"ciphertext,omitempty"` // Encrypted PadlockMessagePayload -} - -func (x *PadlockMessageEnvelope) Reset() { - *x = PadlockMessageEnvelope{} - if protoimpl.UnsafeEnabled { - mi := &file_message_contents_message_proto_msgTypes[9] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *PadlockMessageEnvelope) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*PadlockMessageEnvelope) ProtoMessage() {} - -func (x *PadlockMessageEnvelope) ProtoReflect() protoreflect.Message { - mi := &file_message_contents_message_proto_msgTypes[9] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use PadlockMessageEnvelope.ProtoReflect.Descriptor instead. -func (*PadlockMessageEnvelope) Descriptor() ([]byte, []int) { - return file_message_contents_message_proto_rawDescGZIP(), []int{9} -} - -func (x *PadlockMessageEnvelope) GetHeaderBytes() []byte { - if x != nil { - return x.HeaderBytes - } - return nil -} - -func (x *PadlockMessageEnvelope) GetCiphertext() []byte { - if x != nil { - return x.Ciphertext - } - return nil -} - var File_message_contents_message_proto protoreflect.FileDescriptor var file_message_contents_message_proto_rawDesc = []byte{ @@ -842,58 +524,12 @@ var file_message_contents_message_proto_rawDesc = []byte{ 0x5f, 0x62, 0x79, 0x74, 0x65, 0x73, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0c, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x42, 0x79, 0x74, 0x65, 0x73, 0x42, 0x14, 0x0a, 0x12, 0x5f, 0x72, 0x65, 0x63, 0x69, 0x70, 0x69, 0x65, 0x6e, 0x74, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, - 0x22, 0xf6, 0x01, 0x0a, 0x1c, 0x50, 0x61, 0x64, 0x6c, 0x6f, 0x63, 0x6b, 0x4d, 0x65, 0x73, 0x73, - 0x61, 0x67, 0x65, 0x53, 0x65, 0x61, 0x6c, 0x65, 0x64, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, - 0x61, 0x12, 0x2e, 0x0a, 0x13, 0x73, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x5f, 0x75, 0x73, 0x65, 0x72, - 0x5f, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x11, - 0x73, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x55, 0x73, 0x65, 0x72, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, - 0x73, 0x12, 0x34, 0x0a, 0x16, 0x73, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x5f, 0x69, 0x6e, 0x73, 0x74, - 0x61, 0x6c, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x14, 0x73, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, - 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x12, 0x34, 0x0a, 0x16, 0x72, 0x65, 0x63, 0x69, 0x70, - 0x69, 0x65, 0x6e, 0x74, 0x5f, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, - 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x14, 0x72, 0x65, 0x63, 0x69, 0x70, 0x69, 0x65, - 0x6e, 0x74, 0x55, 0x73, 0x65, 0x72, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x3a, 0x0a, - 0x19, 0x72, 0x65, 0x63, 0x69, 0x70, 0x69, 0x65, 0x6e, 0x74, 0x5f, 0x69, 0x6e, 0x73, 0x74, 0x61, - 0x6c, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x17, 0x72, 0x65, 0x63, 0x69, 0x70, 0x69, 0x65, 0x6e, 0x74, 0x49, 0x6e, 0x73, 0x74, 0x61, - 0x6c, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x22, 0x58, 0x0a, 0x14, 0x50, 0x61, 0x64, - 0x6c, 0x6f, 0x63, 0x6b, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x48, 0x65, 0x61, 0x64, 0x65, - 0x72, 0x12, 0x17, 0x0a, 0x07, 0x73, 0x65, 0x6e, 0x74, 0x5f, 0x6e, 0x73, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x04, 0x52, 0x06, 0x73, 0x65, 0x6e, 0x74, 0x4e, 0x73, 0x12, 0x27, 0x0a, 0x0f, 0x73, 0x65, - 0x61, 0x6c, 0x65, 0x64, 0x5f, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x18, 0x02, 0x20, - 0x01, 0x28, 0x0c, 0x52, 0x0e, 0x73, 0x65, 0x61, 0x6c, 0x65, 0x64, 0x4d, 0x65, 0x74, 0x61, 0x64, - 0x61, 0x74, 0x61, 0x22, 0xe0, 0x01, 0x0a, 0x15, 0x50, 0x61, 0x64, 0x6c, 0x6f, 0x63, 0x6b, 0x4d, - 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x50, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x12, 0x5c, 0x0a, - 0x0f, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x33, 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x2e, 0x6d, 0x65, - 0x73, 0x73, 0x61, 0x67, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0x2e, 0x50, - 0x61, 0x64, 0x6c, 0x6f, 0x63, 0x6b, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x50, 0x61, 0x79, - 0x6c, 0x6f, 0x61, 0x64, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x0e, 0x6d, 0x65, 0x73, - 0x73, 0x61, 0x67, 0x65, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x29, 0x0a, 0x10, 0x68, - 0x65, 0x61, 0x64, 0x65, 0x72, 0x5f, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, - 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0f, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x53, 0x69, 0x67, - 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x12, 0x19, 0x0a, 0x08, 0x63, 0x6f, 0x6e, 0x76, 0x6f, 0x5f, - 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x63, 0x6f, 0x6e, 0x76, 0x6f, 0x49, - 0x64, 0x12, 0x23, 0x0a, 0x0d, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x5f, 0x62, 0x79, 0x74, - 0x65, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0c, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, - 0x74, 0x42, 0x79, 0x74, 0x65, 0x73, 0x22, 0x5b, 0x0a, 0x16, 0x50, 0x61, 0x64, 0x6c, 0x6f, 0x63, - 0x6b, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x45, 0x6e, 0x76, 0x65, 0x6c, 0x6f, 0x70, 0x65, - 0x12, 0x21, 0x0a, 0x0c, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x5f, 0x62, 0x79, 0x74, 0x65, 0x73, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0b, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x42, 0x79, - 0x74, 0x65, 0x73, 0x12, 0x1e, 0x0a, 0x0a, 0x63, 0x69, 0x70, 0x68, 0x65, 0x72, 0x74, 0x65, 0x78, - 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0a, 0x63, 0x69, 0x70, 0x68, 0x65, 0x72, 0x74, - 0x65, 0x78, 0x74, 0x2a, 0x48, 0x0a, 0x1c, 0x50, 0x61, 0x64, 0x6c, 0x6f, 0x63, 0x6b, 0x4d, 0x65, - 0x73, 0x73, 0x61, 0x67, 0x65, 0x50, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x56, 0x65, 0x72, 0x73, - 0x69, 0x6f, 0x6e, 0x12, 0x28, 0x0a, 0x24, 0x50, 0x41, 0x44, 0x4c, 0x4f, 0x43, 0x4b, 0x5f, 0x4d, - 0x45, 0x53, 0x53, 0x41, 0x47, 0x45, 0x5f, 0x50, 0x41, 0x59, 0x4c, 0x4f, 0x41, 0x44, 0x5f, 0x56, - 0x45, 0x52, 0x53, 0x49, 0x4f, 0x4e, 0x5f, 0x5a, 0x45, 0x52, 0x4f, 0x10, 0x00, 0x42, 0x4f, 0x0a, - 0x1f, 0x6f, 0x72, 0x67, 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, - 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, - 0x5a, 0x2c, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x78, 0x6d, 0x74, - 0x70, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x76, 0x33, 0x2f, 0x67, 0x6f, 0x2f, 0x6d, 0x65, - 0x73, 0x73, 0x61, 0x67, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0x62, 0x06, - 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x42, 0x4f, 0x0a, 0x1f, 0x6f, 0x72, 0x67, 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x2e, 0x70, 0x72, 0x6f, + 0x74, 0x6f, 0x2e, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x65, + 0x6e, 0x74, 0x73, 0x5a, 0x2c, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, + 0x78, 0x6d, 0x74, 0x70, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x76, 0x33, 0x2f, 0x67, 0x6f, + 0x2f, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, + 0x73, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( @@ -908,38 +544,31 @@ func file_message_contents_message_proto_rawDescGZIP() []byte { return file_message_contents_message_proto_rawDescData } -var file_message_contents_message_proto_enumTypes = make([]protoimpl.EnumInfo, 1) -var file_message_contents_message_proto_msgTypes = make([]protoimpl.MessageInfo, 10) +var file_message_contents_message_proto_msgTypes = make([]protoimpl.MessageInfo, 6) var file_message_contents_message_proto_goTypes = []interface{}{ - (PadlockMessagePayloadVersion)(0), // 0: xmtp.message_contents.PadlockMessagePayloadVersion - (*MessageHeaderV1)(nil), // 1: xmtp.message_contents.MessageHeaderV1 - (*MessageV1)(nil), // 2: xmtp.message_contents.MessageV1 - (*MessageHeaderV2)(nil), // 3: xmtp.message_contents.MessageHeaderV2 - (*MessageV2)(nil), // 4: xmtp.message_contents.MessageV2 - (*Message)(nil), // 5: xmtp.message_contents.Message - (*DecodedMessage)(nil), // 6: xmtp.message_contents.DecodedMessage - (*PadlockMessageSealedMetadata)(nil), // 7: xmtp.message_contents.PadlockMessageSealedMetadata - (*PadlockMessageHeader)(nil), // 8: xmtp.message_contents.PadlockMessageHeader - (*PadlockMessagePayload)(nil), // 9: xmtp.message_contents.PadlockMessagePayload - (*PadlockMessageEnvelope)(nil), // 10: xmtp.message_contents.PadlockMessageEnvelope - (*PublicKeyBundle)(nil), // 11: xmtp.message_contents.PublicKeyBundle - (*Ciphertext)(nil), // 12: xmtp.message_contents.Ciphertext - (*ConversationReference)(nil), // 13: xmtp.message_contents.ConversationReference + (*MessageHeaderV1)(nil), // 0: xmtp.message_contents.MessageHeaderV1 + (*MessageV1)(nil), // 1: xmtp.message_contents.MessageV1 + (*MessageHeaderV2)(nil), // 2: xmtp.message_contents.MessageHeaderV2 + (*MessageV2)(nil), // 3: xmtp.message_contents.MessageV2 + (*Message)(nil), // 4: xmtp.message_contents.Message + (*DecodedMessage)(nil), // 5: xmtp.message_contents.DecodedMessage + (*PublicKeyBundle)(nil), // 6: xmtp.message_contents.PublicKeyBundle + (*Ciphertext)(nil), // 7: xmtp.message_contents.Ciphertext + (*ConversationReference)(nil), // 8: xmtp.message_contents.ConversationReference } var file_message_contents_message_proto_depIdxs = []int32{ - 11, // 0: xmtp.message_contents.MessageHeaderV1.sender:type_name -> xmtp.message_contents.PublicKeyBundle - 11, // 1: xmtp.message_contents.MessageHeaderV1.recipient:type_name -> xmtp.message_contents.PublicKeyBundle - 12, // 2: xmtp.message_contents.MessageV1.ciphertext:type_name -> xmtp.message_contents.Ciphertext - 12, // 3: xmtp.message_contents.MessageV2.ciphertext:type_name -> xmtp.message_contents.Ciphertext - 2, // 4: xmtp.message_contents.Message.v1:type_name -> xmtp.message_contents.MessageV1 - 4, // 5: xmtp.message_contents.Message.v2:type_name -> xmtp.message_contents.MessageV2 - 13, // 6: xmtp.message_contents.DecodedMessage.conversation:type_name -> xmtp.message_contents.ConversationReference - 0, // 7: xmtp.message_contents.PadlockMessagePayload.message_version:type_name -> xmtp.message_contents.PadlockMessagePayloadVersion - 8, // [8:8] is the sub-list for method output_type - 8, // [8:8] is the sub-list for method input_type - 8, // [8:8] is the sub-list for extension type_name - 8, // [8:8] is the sub-list for extension extendee - 0, // [0:8] is the sub-list for field type_name + 6, // 0: xmtp.message_contents.MessageHeaderV1.sender:type_name -> xmtp.message_contents.PublicKeyBundle + 6, // 1: xmtp.message_contents.MessageHeaderV1.recipient:type_name -> xmtp.message_contents.PublicKeyBundle + 7, // 2: xmtp.message_contents.MessageV1.ciphertext:type_name -> xmtp.message_contents.Ciphertext + 7, // 3: xmtp.message_contents.MessageV2.ciphertext:type_name -> xmtp.message_contents.Ciphertext + 1, // 4: xmtp.message_contents.Message.v1:type_name -> xmtp.message_contents.MessageV1 + 3, // 5: xmtp.message_contents.Message.v2:type_name -> xmtp.message_contents.MessageV2 + 8, // 6: xmtp.message_contents.DecodedMessage.conversation:type_name -> xmtp.message_contents.ConversationReference + 7, // [7:7] is the sub-list for method output_type + 7, // [7:7] is the sub-list for method input_type + 7, // [7:7] is the sub-list for extension type_name + 7, // [7:7] is the sub-list for extension extendee + 0, // [0:7] is the sub-list for field type_name } func init() { file_message_contents_message_proto_init() } @@ -1023,54 +652,6 @@ func file_message_contents_message_proto_init() { return nil } } - file_message_contents_message_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*PadlockMessageSealedMetadata); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_message_contents_message_proto_msgTypes[7].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*PadlockMessageHeader); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_message_contents_message_proto_msgTypes[8].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*PadlockMessagePayload); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_message_contents_message_proto_msgTypes[9].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*PadlockMessageEnvelope); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } } file_message_contents_message_proto_msgTypes[4].OneofWrappers = []interface{}{ (*Message_V1)(nil), @@ -1082,14 +663,13 @@ func file_message_contents_message_proto_init() { File: protoimpl.DescBuilder{ GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_message_contents_message_proto_rawDesc, - NumEnums: 1, - NumMessages: 10, + NumEnums: 0, + NumMessages: 6, NumExtensions: 0, NumServices: 0, }, GoTypes: file_message_contents_message_proto_goTypes, DependencyIndexes: file_message_contents_message_proto_depIdxs, - EnumInfos: file_message_contents_message_proto_enumTypes, MessageInfos: file_message_contents_message_proto_msgTypes, }.Build() File_message_contents_message_proto = out.File diff --git a/proto/message_contents/message.proto b/proto/message_contents/message.proto index 0cea1f50..bcd17c60 100644 --- a/proto/message_contents/message.proto +++ b/proto/message_contents/message.proto @@ -67,55 +67,4 @@ message DecodedMessage { string content_topic = 6; ConversationReference conversation = 7; bytes content_bytes = 8; // encapsulates EncodedContent -} - -// Metadata that is encrypted via SealedSender and only visible to the recipient -// Currently we do not actually encrypt this, actual implementation of -// SealedSender will be added shortly. -message PadlockMessageSealedMetadata { - string sender_user_address = 1; - string sender_installation_id = 2; - string recipient_user_address = 3; - string recipient_installation_id = 4; -} - -// Plaintext header included with messages, visible to all -// Recipients can verify this header has not been tampered with. -// Servers are unable to verify if the header has been tampered with. -message PadlockMessageHeader { - uint64 sent_ns = 1; - bytes sealed_metadata = 2; // PadlockMessageSealedMetadata -} - -// The version used for the decrypted padlock message payload -enum PadlockMessagePayloadVersion { - PADLOCK_MESSAGE_PAYLOAD_VERSION_ZERO = 0; -} - -// Encrypted body included with messages, only visible to recipients -// When receiving a message: -// 1. Decrypt the sealed metadata in the header via SealedSender -// 2. Verify that you match the recipient_user_address and -// recipient_installation_id. Verify that the sender_installation_id matches -// the sender_user_address. -// 2. Find the relevant session using the sender_user_address and -// sender_installation_id in the unsealed metadata -// 3. Use the session to decrypt the payload -// 4. Verify that the header_signature in the decrypted payload matches the -// header bytes -// 5. Verify that the signer of the header_signature matches the -// sender_installation_id -// 6. Verify that both the sender_user and recipient_user are partipants of the -// conversation referenced by convo_id -message PadlockMessagePayload { - PadlockMessagePayloadVersion message_version = 1; - bytes header_signature = 2; // Signature for PadlockMessageHeader - string convo_id = 3; - bytes content_bytes = 4; // EncodedContent -} - -// Combines the plaintext header with the encrypted payload -message PadlockMessageEnvelope { - bytes header_bytes = 1; // PadlockMessageHeader - bytes ciphertext = 2; // Encrypted PadlockMessagePayload } \ No newline at end of file diff --git a/proto/v3/message_contents/message.proto b/proto/v3/message_contents/message.proto new file mode 100644 index 00000000..bdd297cf --- /dev/null +++ b/proto/v3/message_contents/message.proto @@ -0,0 +1,61 @@ +// Structure for messages in v3 +syntax = "proto3"; + +package xmtp.v3.message_contents; + +import "v3/message_contents/association.proto"; + +option go_package = "github.com/xmtp/proto/v3/go/v3/message_contents"; +option java_package = "org.xmtp.proto.v3.message.contents"; + +// Metadata that is encrypted via SealedSender and only visible to the recipient +// Currently we do not actually encrypt this, actual implementation of +// SealedSender will be added shortly. +message PadlockMessageSealedMetadata { + string sender_user_address = 1; + string sender_installation_id = 2; + string recipient_user_address = 3; + string recipient_installation_id = 4; +} + +// Plaintext header included with messages, visible to all +// Recipients can verify this header has not been tampered with. +// Servers are unable to verify if the header has been tampered with. +message PadlockMessageHeader { + uint64 sent_ns = 1; + bytes sealed_metadata = 2; // PadlockMessageSealedMetadata +} + +// The version used for the decrypted padlock message payload +enum PadlockMessagePayloadVersion { + PADLOCK_MESSAGE_PAYLOAD_VERSION_UNSPECIFIED = 0; + PADLOCK_MESSAGE_PAYLOAD_VERSION_ONE = 1; +} + +// Encrypted body included with messages, only visible to recipients +// When receiving a message: +// 1. Decrypt the sealed metadata in the header via SealedSender +// 2. Verify that you match the recipient_user_address and +// recipient_installation_id. Verify that the sender_installation_id matches +// the sender_user_address. +// 2. Find the relevant session using the sender_user_address and +// sender_installation_id in the unsealed metadata +// 3. Use the session to decrypt the payload +// 4. Verify that the header_signature in the decrypted payload matches the +// header bytes +// 5. Verify that the signer of the header_signature matches the +// sender_installation_id +// 6. Verify that both the sender_user and recipient_user are partipants of the +// conversation referenced by convo_id +message PadlockMessagePayload { + PadlockMessagePayloadVersion message_version = 1; + RecoverableEcdsaSignature header_signature = 2; // Sign PadlockMessageHeader + string convo_id = 3; + bytes content_bytes = 4; // EncodedContent +} + +// Combines the plaintext header with the encrypted payload +message PadlockMessageEnvelope { + bytes header_bytes = 1; // PadlockMessageHeader + bytes ciphertext = 2; // Encrypted PadlockMessagePayload +} \ No newline at end of file From 74aea751251f6265815b90a1136cf0feef4d33d1 Mon Sep 17 00:00:00 2001 From: Richard Hua Date: Wed, 26 Jul 2023 12:54:34 -0700 Subject: [PATCH 21/30] build: pin dart plugin version --- dev/dart/protoc/Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dev/dart/protoc/Dockerfile b/dev/dart/protoc/Dockerfile index 36718c6a..b3e3d149 100644 --- a/dev/dart/protoc/Dockerfile +++ b/dev/dart/protoc/Dockerfile @@ -5,7 +5,7 @@ RUN apt-get update && \ COPY protoc.sh /opt/protoc -RUN dart pub global activate protoc_plugin +RUN dart pub global activate protoc_plugin 20.0.1 ENV PATH ${PATH}:/root/.pub-cache/bin RUN mkdir -p /opt/proto && \ From 79d6670b5663035607c6e6ad274b7087e359eae1 Mon Sep 17 00:00:00 2001 From: Richard Hua Date: Thu, 27 Jul 2023 11:36:40 -0700 Subject: [PATCH 22/30] fix: use EdDSA signature --- proto/v3/message_contents/association.proto | 5 +++++ proto/v3/message_contents/message.proto | 11 +++++------ 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/proto/v3/message_contents/association.proto b/proto/v3/message_contents/association.proto index 7f89e42b..ee07b110 100644 --- a/proto/v3/message_contents/association.proto +++ b/proto/v3/message_contents/association.proto @@ -24,4 +24,9 @@ message Eip191Association { message RecoverableEcdsaSignature { // Includes recovery id as the last byte bytes bytes = 1; +} + +// EdDSA signature bytes matching RFC 8032 +message EdDsaSignature { + bytes byte = 1; } \ No newline at end of file diff --git a/proto/v3/message_contents/message.proto b/proto/v3/message_contents/message.proto index bdd297cf..8503eb99 100644 --- a/proto/v3/message_contents/message.proto +++ b/proto/v3/message_contents/message.proto @@ -41,17 +41,16 @@ enum PadlockMessagePayloadVersion { // 2. Find the relevant session using the sender_user_address and // sender_installation_id in the unsealed metadata // 3. Use the session to decrypt the payload -// 4. Verify that the header_signature in the decrypted payload matches the -// header bytes -// 5. Verify that the signer of the header_signature matches the +// 4. Verify that the header_signature in the decrypted payload was produced by +// signing the header_bytes with the ed25519 key matching the // sender_installation_id -// 6. Verify that both the sender_user and recipient_user are partipants of the +// 5. Verify that both the sender_user and recipient_user are partipants of the // conversation referenced by convo_id message PadlockMessagePayload { PadlockMessagePayloadVersion message_version = 1; - RecoverableEcdsaSignature header_signature = 2; // Sign PadlockMessageHeader + EdDsaSignature header_signature = 2; // Signs PadlockMessageHeader string convo_id = 3; - bytes content_bytes = 4; // EncodedContent + bytes content_bytes = 4; // EncodedContent } // Combines the plaintext header with the encrypted payload From 0768598c3db8f43503ec328ba2a91770692b5ca9 Mon Sep 17 00:00:00 2001 From: Richard Hua Date: Thu, 27 Jul 2023 12:11:50 -0700 Subject: [PATCH 23/30] fix: byte->bytes --- proto/v3/message_contents/association.proto | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/proto/v3/message_contents/association.proto b/proto/v3/message_contents/association.proto index ee07b110..4d910970 100644 --- a/proto/v3/message_contents/association.proto +++ b/proto/v3/message_contents/association.proto @@ -28,5 +28,5 @@ message RecoverableEcdsaSignature { // EdDSA signature bytes matching RFC 8032 message EdDsaSignature { - bytes byte = 1; + bytes bytes = 1; } \ No newline at end of file From 81c020f98b86e4556b511b653f8c4e56a25c916a Mon Sep 17 00:00:00 2001 From: Richard Hua Date: Mon, 31 Jul 2023 12:22:30 -0700 Subject: [PATCH 24/30] feat: add is_prekey_message field to metadata --- proto/v3/message_contents/message.proto | 1 + 1 file changed, 1 insertion(+) diff --git a/proto/v3/message_contents/message.proto b/proto/v3/message_contents/message.proto index 8503eb99..18588d9a 100644 --- a/proto/v3/message_contents/message.proto +++ b/proto/v3/message_contents/message.proto @@ -16,6 +16,7 @@ message PadlockMessageSealedMetadata { string sender_installation_id = 2; string recipient_user_address = 3; string recipient_installation_id = 4; + bool is_prekey_message = 5; } // Plaintext header included with messages, visible to all From f1523ffabab22f3947b0f2a96751049be8a36c97 Mon Sep 17 00:00:00 2001 From: Nicholas Molnar <65710+neekolas@users.noreply.github.com> Date: Tue, 26 Sep 2023 18:25:34 -0400 Subject: [PATCH 25/30] chore: update generated code --- .gitignore | 1 + go/keystore_api/v1/keystore.pb.go | 5 -- go/message_api/v1/message_api.pb.go | 1 - go/message_api/v1/message_api.pb.gw.go | 76 ++++++++++++++++++++++++++ go/message_contents/ciphertext.pb.go | 1 - go/message_contents/composite.pb.go | 1 - go/message_contents/contact.pb.go | 1 - go/message_contents/invitation.pb.go | 2 - go/message_contents/message.pb.go | 1 - go/message_contents/private_key.pb.go | 4 -- go/message_contents/public_key.pb.go | 2 - go/message_contents/signature.pb.go | 1 - 12 files changed, 77 insertions(+), 19 deletions(-) diff --git a/.gitignore b/.gitignore index 514b29f2..f811e902 100644 --- a/.gitignore +++ b/.gitignore @@ -121,3 +121,4 @@ Package.resolved # Kotlin kotlin/lib/src/main +kotlin/bin diff --git a/go/keystore_api/v1/keystore.pb.go b/go/keystore_api/v1/keystore.pb.go index ce708433..c05a42ec 100644 --- a/go/keystore_api/v1/keystore.pb.go +++ b/go/keystore_api/v1/keystore.pb.go @@ -1061,7 +1061,6 @@ type InitKeystoreRequest struct { unknownFields protoimpl.UnknownFields // Types that are assignable to Bundle: - // // *InitKeystoreRequest_V1 Bundle isInitKeystoreRequest_Bundle `protobuf_oneof:"bundle"` } @@ -1179,7 +1178,6 @@ type SignDigestRequest struct { Digest []byte `protobuf:"bytes,1,opt,name=digest,proto3" json:"digest,omitempty"` // Types that are assignable to Signer: - // // *SignDigestRequest_IdentityKey // *SignDigestRequest_PrekeyIndex Signer isSignDigestRequest_Signer `protobuf_oneof:"signer"` @@ -1388,7 +1386,6 @@ type DecryptResponse_Response struct { unknownFields protoimpl.UnknownFields // Types that are assignable to Response: - // // *DecryptResponse_Response_Result // *DecryptResponse_Response_Error Response isDecryptResponse_Response_Response `protobuf_oneof:"response"` @@ -1646,7 +1643,6 @@ type EncryptResponse_Response struct { unknownFields protoimpl.UnknownFields // Types that are assignable to Response: - // // *EncryptResponse_Response_Result // *EncryptResponse_Response_Error Response isEncryptResponse_Response_Response `protobuf_oneof:"response"` @@ -1904,7 +1900,6 @@ type SaveInvitesResponse_Response struct { unknownFields protoimpl.UnknownFields // Types that are assignable to Response: - // // *SaveInvitesResponse_Response_Result // *SaveInvitesResponse_Response_Error Response isSaveInvitesResponse_Response_Response `protobuf_oneof:"response"` diff --git a/go/message_api/v1/message_api.pb.go b/go/message_api/v1/message_api.pb.go index dd46ff38..1222af5e 100644 --- a/go/message_api/v1/message_api.pb.go +++ b/go/message_api/v1/message_api.pb.go @@ -143,7 +143,6 @@ type Cursor struct { // This way we can handle both methods // // Types that are assignable to Cursor: - // // *Cursor_Index Cursor isCursor_Cursor `protobuf_oneof:"cursor"` } diff --git a/go/message_api/v1/message_api.pb.gw.go b/go/message_api/v1/message_api.pb.gw.go index d2435f7a..223c8f81 100644 --- a/go/message_api/v1/message_api.pb.gw.go +++ b/go/message_api/v1/message_api.pb.gw.go @@ -90,6 +90,49 @@ func request_MessageApi_Subscribe_0(ctx context.Context, marshaler runtime.Marsh } +func request_MessageApi_Subscribe2_0(ctx context.Context, marshaler runtime.Marshaler, client MessageApiClient, req *http.Request, pathParams map[string]string) (MessageApi_Subscribe2Client, runtime.ServerMetadata, error) { + var metadata runtime.ServerMetadata + stream, err := client.Subscribe2(ctx) + if err != nil { + grpclog.Infof("Failed to start streaming: %v", err) + return nil, metadata, err + } + dec := marshaler.NewDecoder(req.Body) + handleSend := func() error { + var protoReq SubscribeRequest + err := dec.Decode(&protoReq) + if err == io.EOF { + return err + } + if err != nil { + grpclog.Infof("Failed to decode request: %v", err) + return err + } + if err := stream.Send(&protoReq); err != nil { + grpclog.Infof("Failed to send request: %v", err) + return err + } + return nil + } + go func() { + for { + if err := handleSend(); err != nil { + break + } + } + if err := stream.CloseSend(); err != nil { + grpclog.Infof("Failed to terminate client stream: %v", err) + } + }() + header, err := stream.Header() + if err != nil { + grpclog.Infof("Failed to get header from client: %v", err) + return nil, metadata, err + } + metadata.HeaderMD = header + return stream, metadata, nil +} + func request_MessageApi_SubscribeAll_0(ctx context.Context, marshaler runtime.Marshaler, client MessageApiClient, req *http.Request, pathParams map[string]string) (MessageApi_SubscribeAllClient, runtime.ServerMetadata, error) { var protoReq SubscribeAllRequest var metadata runtime.ServerMetadata @@ -221,6 +264,13 @@ func RegisterMessageApiHandlerServer(ctx context.Context, mux *runtime.ServeMux, return }) + mux.Handle("POST", pattern_MessageApi_Subscribe2_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + err := status.Error(codes.Unimplemented, "streaming calls are not yet supported in the in-process transport") + _, outboundMarshaler := runtime.MarshalerForRequest(mux, req) + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + }) + mux.Handle("POST", pattern_MessageApi_SubscribeAll_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { err := status.Error(codes.Unimplemented, "streaming calls are not yet supported in the in-process transport") _, outboundMarshaler := runtime.MarshalerForRequest(mux, req) @@ -363,6 +413,28 @@ func RegisterMessageApiHandlerClient(ctx context.Context, mux *runtime.ServeMux, }) + mux.Handle("POST", pattern_MessageApi_Subscribe2_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + ctx, cancel := context.WithCancel(req.Context()) + defer cancel() + inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) + var err error + var annotatedContext context.Context + annotatedContext, err = runtime.AnnotateContext(ctx, mux, req, "/xmtp.message_api.v1.MessageApi/Subscribe2", runtime.WithHTTPPathPattern("/xmtp.message_api.v1.MessageApi/Subscribe2")) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := request_MessageApi_Subscribe2_0(annotatedContext, inboundMarshaler, client, req, pathParams) + annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md) + if err != nil { + runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) + return + } + + forward_MessageApi_Subscribe2_0(annotatedContext, mux, outboundMarshaler, w, req, func() (proto.Message, error) { return resp.Recv() }, mux.GetForwardResponseOptions()...) + + }) + mux.Handle("POST", pattern_MessageApi_SubscribeAll_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { ctx, cancel := context.WithCancel(req.Context()) defer cancel() @@ -437,6 +509,8 @@ var ( pattern_MessageApi_Subscribe_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"message", "v1", "subscribe"}, "")) + pattern_MessageApi_Subscribe2_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1}, []string{"xmtp.message_api.v1.MessageApi", "Subscribe2"}, "")) + pattern_MessageApi_SubscribeAll_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"message", "v1", "subscribe-all"}, "")) pattern_MessageApi_Query_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"message", "v1", "query"}, "")) @@ -449,6 +523,8 @@ var ( forward_MessageApi_Subscribe_0 = runtime.ForwardResponseStream + forward_MessageApi_Subscribe2_0 = runtime.ForwardResponseStream + forward_MessageApi_SubscribeAll_0 = runtime.ForwardResponseStream forward_MessageApi_Query_0 = runtime.ForwardResponseMessage diff --git a/go/message_contents/ciphertext.pb.go b/go/message_contents/ciphertext.pb.go index d0a56673..9ceed39a 100644 --- a/go/message_contents/ciphertext.pb.go +++ b/go/message_contents/ciphertext.pb.go @@ -32,7 +32,6 @@ type Ciphertext struct { unknownFields protoimpl.UnknownFields // Types that are assignable to Union: - // // *Ciphertext_Aes256GcmHkdfSha256 Union isCiphertext_Union `protobuf_oneof:"union"` } diff --git a/go/message_contents/composite.pb.go b/go/message_contents/composite.pb.go index 9c52b88a..28016550 100644 --- a/go/message_contents/composite.pb.go +++ b/go/message_contents/composite.pb.go @@ -77,7 +77,6 @@ type Composite_Part struct { unknownFields protoimpl.UnknownFields // Types that are assignable to Element: - // // *Composite_Part_Part // *Composite_Part_Composite Element isComposite_Part_Element `protobuf_oneof:"element"` diff --git a/go/message_contents/contact.pb.go b/go/message_contents/contact.pb.go index 7b9df860..d29c7f7c 100644 --- a/go/message_contents/contact.pb.go +++ b/go/message_contents/contact.pb.go @@ -130,7 +130,6 @@ type ContactBundle struct { unknownFields protoimpl.UnknownFields // Types that are assignable to Version: - // // *ContactBundle_V1 // *ContactBundle_V2 Version isContactBundle_Version `protobuf_oneof:"version"` diff --git a/go/message_contents/invitation.pb.go b/go/message_contents/invitation.pb.go index aea64918..206a2c6c 100644 --- a/go/message_contents/invitation.pb.go +++ b/go/message_contents/invitation.pb.go @@ -39,7 +39,6 @@ type InvitationV1 struct { // message encryption scheme and keys for this conversation. // // Types that are assignable to Encryption: - // // *InvitationV1_Aes256GcmHkdfSha256 Encryption isInvitationV1_Encryption `protobuf_oneof:"encryption"` } @@ -250,7 +249,6 @@ type SealedInvitation struct { unknownFields protoimpl.UnknownFields // Types that are assignable to Version: - // // *SealedInvitation_V1 Version isSealedInvitation_Version `protobuf_oneof:"version"` } diff --git a/go/message_contents/message.pb.go b/go/message_contents/message.pb.go index 5e213a37..8bb8a649 100644 --- a/go/message_contents/message.pb.go +++ b/go/message_contents/message.pb.go @@ -269,7 +269,6 @@ type Message struct { unknownFields protoimpl.UnknownFields // Types that are assignable to Version: - // // *Message_V1 // *Message_V2 Version isMessage_Version `protobuf_oneof:"version"` diff --git a/go/message_contents/private_key.pb.go b/go/message_contents/private_key.pb.go index e1066b6b..97356241 100644 --- a/go/message_contents/private_key.pb.go +++ b/go/message_contents/private_key.pb.go @@ -36,7 +36,6 @@ type SignedPrivateKey struct { // private key // // Types that are assignable to Union: - // // *SignedPrivateKey_Secp256K1_ Union isSignedPrivateKey_Union `protobuf_oneof:"union"` // public key for this private key @@ -182,7 +181,6 @@ type PrivateKey struct { // private key // // Types that are assignable to Union: - // // *PrivateKey_Secp256K1_ Union isPrivateKey_Union `protobuf_oneof:"union"` // public key for this private key @@ -323,7 +321,6 @@ type PrivateKeyBundle struct { unknownFields protoimpl.UnknownFields // Types that are assignable to Version: - // // *PrivateKeyBundle_V1 // *PrivateKeyBundle_V2 Version isPrivateKeyBundle_Version `protobuf_oneof:"version"` @@ -467,7 +464,6 @@ type EncryptedPrivateKeyBundle struct { unknownFields protoimpl.UnknownFields // Types that are assignable to Version: - // // *EncryptedPrivateKeyBundle_V1 Version isEncryptedPrivateKeyBundle_Version `protobuf_oneof:"version"` } diff --git a/go/message_contents/public_key.pb.go b/go/message_contents/public_key.pb.go index 4144db6f..98e03dbb 100644 --- a/go/message_contents/public_key.pb.go +++ b/go/message_contents/public_key.pb.go @@ -32,7 +32,6 @@ type UnsignedPublicKey struct { CreatedNs uint64 `protobuf:"varint,1,opt,name=created_ns,json=createdNs,proto3" json:"created_ns,omitempty"` // Types that are assignable to Union: - // // *UnsignedPublicKey_Secp256K1Uncompressed_ Union isUnsignedPublicKey_Union `protobuf_oneof:"union"` } @@ -224,7 +223,6 @@ type PublicKey struct { Timestamp uint64 `protobuf:"varint,1,opt,name=timestamp,proto3" json:"timestamp,omitempty"` Signature *Signature `protobuf:"bytes,2,opt,name=signature,proto3,oneof" json:"signature,omitempty"` // Types that are assignable to Union: - // // *PublicKey_Secp256K1Uncompressed_ Union isPublicKey_Union `protobuf_oneof:"union"` } diff --git a/go/message_contents/signature.pb.go b/go/message_contents/signature.pb.go index 8efe6cb5..b0980ad6 100644 --- a/go/message_contents/signature.pb.go +++ b/go/message_contents/signature.pb.go @@ -30,7 +30,6 @@ type Signature struct { unknownFields protoimpl.UnknownFields // Types that are assignable to Union: - // // *Signature_EcdsaCompact // *Signature_WalletEcdsaCompact Union isSignature_Union `protobuf_oneof:"union"` From d39e8521c6af80c0133418417c83aa965b91e3bb Mon Sep 17 00:00:00 2001 From: Nicholas Molnar <65710+neekolas@users.noreply.github.com> Date: Wed, 4 Oct 2023 11:52:58 -0700 Subject: [PATCH 26/30] feat: add signed payload --- proto/message_contents/signed_payload.proto | 15 +++++++++++++++ 1 file changed, 15 insertions(+) create mode 100644 proto/message_contents/signed_payload.proto diff --git a/proto/message_contents/signed_payload.proto b/proto/message_contents/signed_payload.proto new file mode 100644 index 00000000..b423aa7a --- /dev/null +++ b/proto/message_contents/signed_payload.proto @@ -0,0 +1,15 @@ +// Signature is a generic structure for signed byte arrays +syntax = "proto3"; + +package xmtp.message_contents; + +import "message_contents/signature.proto"; + +option go_package = "github.com/xmtp/proto/v3/go/message_contents"; +option java_package = "org.xmtp.proto.message.contents"; + +// SignedPayload is a wrapper for a signature and a payload +message SignedPayload { + bytes payload = 1; + Signature signature = 2; +} From ed7044868f7ee64a8ee1e1a5e46d0157674f857e Mon Sep 17 00:00:00 2001 From: Nicholas Molnar <65710+neekolas@users.noreply.github.com> Date: Wed, 4 Oct 2023 11:53:33 -0700 Subject: [PATCH 27/30] chore: add go protos --- go/keystore_api/v1/keystore.pb.go | 5 ----- go/message_api/v1/message_api.pb.go | 1 - go/message_contents/ciphertext.pb.go | 1 - go/message_contents/composite.pb.go | 1 - go/message_contents/contact.pb.go | 1 - go/message_contents/invitation.pb.go | 2 -- go/message_contents/message.pb.go | 1 - go/message_contents/private_key.pb.go | 4 ---- go/message_contents/public_key.pb.go | 2 -- go/message_contents/signature.pb.go | 1 - 10 files changed, 19 deletions(-) diff --git a/go/keystore_api/v1/keystore.pb.go b/go/keystore_api/v1/keystore.pb.go index ce708433..c05a42ec 100644 --- a/go/keystore_api/v1/keystore.pb.go +++ b/go/keystore_api/v1/keystore.pb.go @@ -1061,7 +1061,6 @@ type InitKeystoreRequest struct { unknownFields protoimpl.UnknownFields // Types that are assignable to Bundle: - // // *InitKeystoreRequest_V1 Bundle isInitKeystoreRequest_Bundle `protobuf_oneof:"bundle"` } @@ -1179,7 +1178,6 @@ type SignDigestRequest struct { Digest []byte `protobuf:"bytes,1,opt,name=digest,proto3" json:"digest,omitempty"` // Types that are assignable to Signer: - // // *SignDigestRequest_IdentityKey // *SignDigestRequest_PrekeyIndex Signer isSignDigestRequest_Signer `protobuf_oneof:"signer"` @@ -1388,7 +1386,6 @@ type DecryptResponse_Response struct { unknownFields protoimpl.UnknownFields // Types that are assignable to Response: - // // *DecryptResponse_Response_Result // *DecryptResponse_Response_Error Response isDecryptResponse_Response_Response `protobuf_oneof:"response"` @@ -1646,7 +1643,6 @@ type EncryptResponse_Response struct { unknownFields protoimpl.UnknownFields // Types that are assignable to Response: - // // *EncryptResponse_Response_Result // *EncryptResponse_Response_Error Response isEncryptResponse_Response_Response `protobuf_oneof:"response"` @@ -1904,7 +1900,6 @@ type SaveInvitesResponse_Response struct { unknownFields protoimpl.UnknownFields // Types that are assignable to Response: - // // *SaveInvitesResponse_Response_Result // *SaveInvitesResponse_Response_Error Response isSaveInvitesResponse_Response_Response `protobuf_oneof:"response"` diff --git a/go/message_api/v1/message_api.pb.go b/go/message_api/v1/message_api.pb.go index dd46ff38..1222af5e 100644 --- a/go/message_api/v1/message_api.pb.go +++ b/go/message_api/v1/message_api.pb.go @@ -143,7 +143,6 @@ type Cursor struct { // This way we can handle both methods // // Types that are assignable to Cursor: - // // *Cursor_Index Cursor isCursor_Cursor `protobuf_oneof:"cursor"` } diff --git a/go/message_contents/ciphertext.pb.go b/go/message_contents/ciphertext.pb.go index d0a56673..9ceed39a 100644 --- a/go/message_contents/ciphertext.pb.go +++ b/go/message_contents/ciphertext.pb.go @@ -32,7 +32,6 @@ type Ciphertext struct { unknownFields protoimpl.UnknownFields // Types that are assignable to Union: - // // *Ciphertext_Aes256GcmHkdfSha256 Union isCiphertext_Union `protobuf_oneof:"union"` } diff --git a/go/message_contents/composite.pb.go b/go/message_contents/composite.pb.go index 9c52b88a..28016550 100644 --- a/go/message_contents/composite.pb.go +++ b/go/message_contents/composite.pb.go @@ -77,7 +77,6 @@ type Composite_Part struct { unknownFields protoimpl.UnknownFields // Types that are assignable to Element: - // // *Composite_Part_Part // *Composite_Part_Composite Element isComposite_Part_Element `protobuf_oneof:"element"` diff --git a/go/message_contents/contact.pb.go b/go/message_contents/contact.pb.go index 7b9df860..d29c7f7c 100644 --- a/go/message_contents/contact.pb.go +++ b/go/message_contents/contact.pb.go @@ -130,7 +130,6 @@ type ContactBundle struct { unknownFields protoimpl.UnknownFields // Types that are assignable to Version: - // // *ContactBundle_V1 // *ContactBundle_V2 Version isContactBundle_Version `protobuf_oneof:"version"` diff --git a/go/message_contents/invitation.pb.go b/go/message_contents/invitation.pb.go index aea64918..206a2c6c 100644 --- a/go/message_contents/invitation.pb.go +++ b/go/message_contents/invitation.pb.go @@ -39,7 +39,6 @@ type InvitationV1 struct { // message encryption scheme and keys for this conversation. // // Types that are assignable to Encryption: - // // *InvitationV1_Aes256GcmHkdfSha256 Encryption isInvitationV1_Encryption `protobuf_oneof:"encryption"` } @@ -250,7 +249,6 @@ type SealedInvitation struct { unknownFields protoimpl.UnknownFields // Types that are assignable to Version: - // // *SealedInvitation_V1 Version isSealedInvitation_Version `protobuf_oneof:"version"` } diff --git a/go/message_contents/message.pb.go b/go/message_contents/message.pb.go index 5e213a37..8bb8a649 100644 --- a/go/message_contents/message.pb.go +++ b/go/message_contents/message.pb.go @@ -269,7 +269,6 @@ type Message struct { unknownFields protoimpl.UnknownFields // Types that are assignable to Version: - // // *Message_V1 // *Message_V2 Version isMessage_Version `protobuf_oneof:"version"` diff --git a/go/message_contents/private_key.pb.go b/go/message_contents/private_key.pb.go index e1066b6b..97356241 100644 --- a/go/message_contents/private_key.pb.go +++ b/go/message_contents/private_key.pb.go @@ -36,7 +36,6 @@ type SignedPrivateKey struct { // private key // // Types that are assignable to Union: - // // *SignedPrivateKey_Secp256K1_ Union isSignedPrivateKey_Union `protobuf_oneof:"union"` // public key for this private key @@ -182,7 +181,6 @@ type PrivateKey struct { // private key // // Types that are assignable to Union: - // // *PrivateKey_Secp256K1_ Union isPrivateKey_Union `protobuf_oneof:"union"` // public key for this private key @@ -323,7 +321,6 @@ type PrivateKeyBundle struct { unknownFields protoimpl.UnknownFields // Types that are assignable to Version: - // // *PrivateKeyBundle_V1 // *PrivateKeyBundle_V2 Version isPrivateKeyBundle_Version `protobuf_oneof:"version"` @@ -467,7 +464,6 @@ type EncryptedPrivateKeyBundle struct { unknownFields protoimpl.UnknownFields // Types that are assignable to Version: - // // *EncryptedPrivateKeyBundle_V1 Version isEncryptedPrivateKeyBundle_Version `protobuf_oneof:"version"` } diff --git a/go/message_contents/public_key.pb.go b/go/message_contents/public_key.pb.go index 4144db6f..98e03dbb 100644 --- a/go/message_contents/public_key.pb.go +++ b/go/message_contents/public_key.pb.go @@ -32,7 +32,6 @@ type UnsignedPublicKey struct { CreatedNs uint64 `protobuf:"varint,1,opt,name=created_ns,json=createdNs,proto3" json:"created_ns,omitempty"` // Types that are assignable to Union: - // // *UnsignedPublicKey_Secp256K1Uncompressed_ Union isUnsignedPublicKey_Union `protobuf_oneof:"union"` } @@ -224,7 +223,6 @@ type PublicKey struct { Timestamp uint64 `protobuf:"varint,1,opt,name=timestamp,proto3" json:"timestamp,omitempty"` Signature *Signature `protobuf:"bytes,2,opt,name=signature,proto3,oneof" json:"signature,omitempty"` // Types that are assignable to Union: - // // *PublicKey_Secp256K1Uncompressed_ Union isPublicKey_Union `protobuf_oneof:"union"` } diff --git a/go/message_contents/signature.pb.go b/go/message_contents/signature.pb.go index 8efe6cb5..b0980ad6 100644 --- a/go/message_contents/signature.pb.go +++ b/go/message_contents/signature.pb.go @@ -30,7 +30,6 @@ type Signature struct { unknownFields protoimpl.UnknownFields // Types that are assignable to Union: - // // *Signature_EcdsaCompact // *Signature_WalletEcdsaCompact Union isSignature_Union `protobuf_oneof:"union"` From dd4e7e92921c72f8d8362346228a6d8ecb78f42d Mon Sep 17 00:00:00 2001 From: Nicholas Molnar <65710+neekolas@users.noreply.github.com> Date: Wed, 4 Oct 2023 11:56:53 -0700 Subject: [PATCH 28/30] chore: update formatter --- .vscode/settings.json | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/.vscode/settings.json b/.vscode/settings.json index 557218a6..f16f4ab4 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,8 +1,10 @@ { - "protoc": { - "compile_on_save": false, - "options": [ - "--proto_path=build/tmp/vendor", - ] - } -} \ No newline at end of file + "protoc": { + "compile_on_save": false, + "options": ["--proto_path=build/tmp/vendor"] + }, + "[proto3]": { + "editor.defaultFormatter": "bufbuild.vscode-buf", + "editor.formatOnSave": true + } +} From 36a3c2aa7386185fd232745dd8f074128f2f3326 Mon Sep 17 00:00:00 2001 From: Nicholas Molnar <65710+neekolas@users.noreply.github.com> Date: Wed, 4 Oct 2023 11:58:37 -0700 Subject: [PATCH 29/30] feat: add EciesMessage --- proto/message_contents/ecies.proto | 15 +++++++++++++++ 1 file changed, 15 insertions(+) create mode 100644 proto/message_contents/ecies.proto diff --git a/proto/message_contents/ecies.proto b/proto/message_contents/ecies.proto new file mode 100644 index 00000000..47489421 --- /dev/null +++ b/proto/message_contents/ecies.proto @@ -0,0 +1,15 @@ +// ECIES is a wrapper for ECIES payloads +syntax = "proto3"; + +package xmtp.message_contents; + +option go_package = "github.com/xmtp/proto/v3/go/message_contents"; +option java_package = "org.xmtp.proto.message.contents"; + +// EciesMessage is a wrapper for ECIES encrypted payloads +message EciesMessage { + oneof version { + // Expected to be an ECIES encrypted SignedPayload + bytes v1 = 1; + } +} From 0cfe3a104143440b17535165641a956ca7d3d969 Mon Sep 17 00:00:00 2001 From: Nicholas Molnar <65710+neekolas@users.noreply.github.com> Date: Wed, 4 Oct 2023 12:04:01 -0700 Subject: [PATCH 30/30] chore: add spaces --- proto/message_contents/ecies.proto | 8 ++++---- proto/message_contents/signed_payload.proto | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/proto/message_contents/ecies.proto b/proto/message_contents/ecies.proto index 47489421..f6939a62 100644 --- a/proto/message_contents/ecies.proto +++ b/proto/message_contents/ecies.proto @@ -8,8 +8,8 @@ option java_package = "org.xmtp.proto.message.contents"; // EciesMessage is a wrapper for ECIES encrypted payloads message EciesMessage { - oneof version { - // Expected to be an ECIES encrypted SignedPayload - bytes v1 = 1; - } + oneof version { + // Expected to be an ECIES encrypted SignedPayload + bytes v1 = 1; + } } diff --git a/proto/message_contents/signed_payload.proto b/proto/message_contents/signed_payload.proto index b423aa7a..f36b9186 100644 --- a/proto/message_contents/signed_payload.proto +++ b/proto/message_contents/signed_payload.proto @@ -10,6 +10,6 @@ option java_package = "org.xmtp.proto.message.contents"; // SignedPayload is a wrapper for a signature and a payload message SignedPayload { - bytes payload = 1; - Signature signature = 2; + bytes payload = 1; + Signature signature = 2; }