Skip to content

Commit

Permalink
Merge pull request #85 from xmtp/nmolnar/message-proto-versioning
Browse files Browse the repository at this point in the history
Version Message Proto
  • Loading branch information
neekolas authored Mar 14, 2022
2 parents bba3b3c + d010a2d commit a290f42
Show file tree
Hide file tree
Showing 3 changed files with 99 additions and 21 deletions.
30 changes: 20 additions & 10 deletions src/Message.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,17 @@ import { NoMatchingPreKeyError } from './crypto/errors'
import { bytesToHex } from './crypto/utils'
import { sha256 } from './crypto/encryption'

const extractV1Message = (msg: proto.Message): proto.V1Message => {
if (!msg.v1) {
throw new Error('Message is not of type v1')
}
return msg.v1
}

// Message is basic unit of communication on the network.
// Message header carries the sender and recipient keys used to protect message.
// Message timestamp is set by the sender.
export default class Message implements proto.Message {
export default class Message implements proto.V1Message {
header: proto.MessageHeader | undefined // eslint-disable-line camelcase
headerBytes: Uint8Array // encoded header bytes
ciphertext: Ciphertext | undefined
Expand All @@ -34,12 +41,13 @@ export default class Message implements proto.Message {
obj: proto.Message,
header: proto.MessageHeader
) {
const msg = extractV1Message(obj)
this.id = id
this.bytes = bytes
this.headerBytes = obj.headerBytes
this.headerBytes = msg.headerBytes
this.header = header
if (obj.ciphertext) {
this.ciphertext = new Ciphertext(obj.ciphertext)
if (msg.ciphertext) {
this.ciphertext = new Ciphertext(msg.ciphertext)
}
}

Expand All @@ -58,7 +66,8 @@ export default class Message implements proto.Message {

static async fromBytes(bytes: Uint8Array): Promise<Message> {
const msg = proto.Message.decode(bytes)
const header = proto.MessageHeader.decode(msg.headerBytes)
const innerMessage = extractV1Message(msg)
const header = proto.MessageHeader.decode(innerMessage.headerBytes)
return Message.create(msg, header, bytes)
}

Expand Down Expand Up @@ -112,7 +121,7 @@ export default class Message implements proto.Message {
}
const headerBytes = proto.MessageHeader.encode(header).finish()
const ciphertext = await encrypt(msgBytes, secret, headerBytes)
const protoMsg = { headerBytes: headerBytes, ciphertext }
const protoMsg = { v1: { headerBytes: headerBytes, ciphertext } }
const bytes = proto.Message.encode(protoMsg).finish()
const msg = await Message.create(protoMsg, header, bytes)
msg.decrypted = message
Expand All @@ -127,7 +136,8 @@ export default class Message implements proto.Message {
bytes: Uint8Array
): Promise<Message> {
const message = proto.Message.decode(bytes)
const header = proto.MessageHeader.decode(message.headerBytes)
const v1Message = extractV1Message(message)
const header = proto.MessageHeader.decode(v1Message.headerBytes)
if (!header) {
throw new Error('missing message header')
}
Expand Down Expand Up @@ -157,10 +167,10 @@ export default class Message implements proto.Message {
new PublicKey(header.sender.identityKey),
new PublicKey(header.sender.preKey)
)
if (!message.ciphertext?.aes256GcmHkdfSha256) {
if (!v1Message.ciphertext?.aes256GcmHkdfSha256) {
throw new Error('missing message ciphertext')
}
const ciphertext = new Ciphertext(message.ciphertext)
const ciphertext = new Ciphertext(v1Message.ciphertext)
const msg = await Message.create(message, header, bytes)
let secret: Uint8Array
try {
Expand All @@ -178,7 +188,7 @@ export default class Message implements proto.Message {
msg.error = e
return msg
}
bytes = await decrypt(ciphertext, secret, message.headerBytes)
bytes = await decrypt(ciphertext, secret, v1Message.headerBytes)
msg.decrypted = new TextDecoder().decode(bytes)
return msg
}
Expand Down
8 changes: 7 additions & 1 deletion src/proto/messaging.proto
Original file line number Diff line number Diff line change
Expand Up @@ -54,11 +54,17 @@ message MessageHeader {
uint64 timestamp = 3;
}

message Message {
message V1Message {
bytes headerBytes = 1; // encapsulates the encoded MessageHeader
Ciphertext ciphertext = 2;
}

message Message {
oneof version {
V1Message v1 = 1;
}
}

// Private Key Storage

message PrivateKeyBundle {
Expand Down
82 changes: 72 additions & 10 deletions src/proto/messaging.ts

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit a290f42

Please sign in to comment.