Communities encryption
This commit is contained in:
parent
51a6d8ee7c
commit
e6dffe8d8d
|
@ -309,7 +309,7 @@ func (s *MessageSender) sendPrivate(
|
|||
s.transport.Track(messageIDs, hash, newMessage)
|
||||
|
||||
} else {
|
||||
messageSpec, err := s.protocol.BuildDirectMessage(rawMessage.Sender, recipient, wrappedMessage)
|
||||
messageSpec, err := s.protocol.BuildEncryptedMessage(rawMessage.Sender, recipient, wrappedMessage)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "failed to encrypt message")
|
||||
}
|
||||
|
@ -660,7 +660,7 @@ func (s *MessageSender) sendDataSync(ctx context.Context, publicKey *ecdsa.Publi
|
|||
hexMessageIDs = append(hexMessageIDs, mid.String())
|
||||
}
|
||||
|
||||
messageSpec, err := s.protocol.BuildDirectMessage(s.identity, publicKey, marshalledDatasyncPayload)
|
||||
messageSpec, err := s.protocol.BuildEncryptedMessage(s.identity, publicKey, marshalledDatasyncPayload)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "failed to encrypt message")
|
||||
}
|
||||
|
|
|
@ -204,7 +204,7 @@ func (s *MessageSenderSuite) TestHandleDecodedMessagesDatasyncEncrypted() {
|
|||
s.logger,
|
||||
)
|
||||
|
||||
messageSpec, err := senderEncryptionProtocol.BuildDirectMessage(
|
||||
messageSpec, err := senderEncryptionProtocol.BuildEncryptedMessage(
|
||||
relayerKey,
|
||||
&s.sender.identity.PublicKey,
|
||||
marshalledDataSyncMessage,
|
||||
|
|
|
@ -0,0 +1,12 @@
|
|||
# protocol/encryption package
|
||||
|
||||
## Hash ratchet encryption
|
||||
`encryptor.GenerateHashRatchetKey()` generates a hash ratchet key and stores it in in the DB.
|
||||
There, 2 new tables are created: `hash_ratchet_encryption` and `hash_ratchet_encryption_cache`.
|
||||
Each hash ratchet key is uniquely identified by the `(groupId, keyId)` pair, where `keyId` is derived from a clock value.
|
||||
|
||||
`protocol.BuildHashRatchetKeyExchangeMessage` builds an 1-on-1 message containing the hash ratchet key, given it's ID.
|
||||
|
||||
`protocol.BuildHashRatchetMessage` builds a hash ratchet message with arbitrary payload, given `groupId`. It will use the latest hash ratchet key available. `encryptor.encryptWithHR` encrypts the payload using Hash Ratchet algorithms. Intermediate hashes are stored in `hash_ratchet_encryption_cache` table.
|
||||
|
||||
`protocol.HandleMessage` uses `encryptor.decryptWithHR` fn for decryption.
|
|
@ -237,9 +237,9 @@ func (s *EncryptionServiceMultiDeviceSuite) TestMaxDevices() {
|
|||
s.Require().NoError(err)
|
||||
|
||||
// Bob sends a message to alice
|
||||
msg, err := bob1.BuildDirectMessage(bobKey, &aliceKey.PublicKey, []byte("test"))
|
||||
msg, err := bob1.BuildEncryptedMessage(bobKey, &aliceKey.PublicKey, []byte("test"))
|
||||
s.Require().NoError(err)
|
||||
payload := msg.Message.GetDirectMessage()
|
||||
payload := msg.Message.GetEncryptedMessage()
|
||||
s.Require().Equal(3, len(payload))
|
||||
s.Require().NotNil(payload["alice1"])
|
||||
s.Require().NotNil(payload["alice3"])
|
||||
|
@ -267,9 +267,9 @@ func (s *EncryptionServiceMultiDeviceSuite) TestMaxDevices() {
|
|||
s.Require().NoError(err)
|
||||
|
||||
// Bob sends a message to alice
|
||||
msg, err = bob1.BuildDirectMessage(bobKey, &aliceKey.PublicKey, []byte("test"))
|
||||
msg, err = bob1.BuildEncryptedMessage(bobKey, &aliceKey.PublicKey, []byte("test"))
|
||||
s.Require().NoError(err)
|
||||
payload = msg.Message.GetDirectMessage()
|
||||
payload = msg.Message.GetEncryptedMessage()
|
||||
s.Require().Equal(3, len(payload))
|
||||
s.Require().NotNil(payload["alice1"])
|
||||
s.Require().NotNil(payload["alice2"])
|
||||
|
@ -312,9 +312,9 @@ func (s *EncryptionServiceMultiDeviceSuite) TestMaxDevicesRefreshedBundle() {
|
|||
s.Require().NoError(err)
|
||||
|
||||
// Bob sends a message to alice
|
||||
msg1, err := bob1.BuildDirectMessage(bobKey, &aliceKey.PublicKey, []byte("test"))
|
||||
msg1, err := bob1.BuildEncryptedMessage(bobKey, &aliceKey.PublicKey, []byte("test"))
|
||||
s.Require().NoError(err)
|
||||
payload := msg1.Message.GetDirectMessage()
|
||||
payload := msg1.Message.GetEncryptedMessage()
|
||||
s.Require().Equal(3, len(payload))
|
||||
// Alice1 is the oldest bundle and is rotated out
|
||||
// as we send maximum to 3 devices
|
||||
|
@ -324,7 +324,7 @@ func (s *EncryptionServiceMultiDeviceSuite) TestMaxDevicesRefreshedBundle() {
|
|||
s.Require().NotNil(payload["alice4"])
|
||||
|
||||
// We send a message to bob from alice1, the timestamp should be refreshed
|
||||
msg2, err := alice1.BuildDirectMessage(aliceKey, &bobKey.PublicKey, []byte("test"))
|
||||
msg2, err := alice1.BuildEncryptedMessage(aliceKey, &bobKey.PublicKey, []byte("test"))
|
||||
s.Require().NoError(err)
|
||||
|
||||
alice1Bundle = msg2.Message.GetBundles()[0]
|
||||
|
@ -334,9 +334,9 @@ func (s *EncryptionServiceMultiDeviceSuite) TestMaxDevicesRefreshedBundle() {
|
|||
s.Require().NoError(err)
|
||||
|
||||
// Bob sends a message to alice
|
||||
msg3, err := bob1.BuildDirectMessage(bobKey, &aliceKey.PublicKey, []byte("test"))
|
||||
msg3, err := bob1.BuildEncryptedMessage(bobKey, &aliceKey.PublicKey, []byte("test"))
|
||||
s.Require().NoError(err)
|
||||
payload = msg3.Message.GetDirectMessage()
|
||||
payload = msg3.Message.GetEncryptedMessage()
|
||||
s.Require().Equal(3, len(payload))
|
||||
// Alice 1 is added back to the list of active devices
|
||||
s.Require().NotNil(payload["alice1"])
|
||||
|
|
|
@ -69,7 +69,7 @@ func (s *EncryptionServiceTestSuite) initDatabases(config encryptorConfig) {
|
|||
}
|
||||
|
||||
func (s *EncryptionServiceTestSuite) SetupTest() {
|
||||
s.logger = zap.NewNop()
|
||||
s.logger, _ = zap.NewProduction()
|
||||
s.initDatabases(defaultEncryptorConfig("none", s.logger))
|
||||
}
|
||||
|
||||
|
@ -92,6 +92,118 @@ func (s *EncryptionServiceTestSuite) TestGetBundle() {
|
|||
s.NotEqual(aliceBundle1.Timestamp, aliceBundle2.Timestamp, "It refreshes the timestamp")
|
||||
}
|
||||
|
||||
func (s *EncryptionServiceTestSuite) TestHashRatchetSend() {
|
||||
aliceKey, err := crypto.GenerateKey()
|
||||
s.Require().NoError(err)
|
||||
|
||||
bobKey, err := crypto.GenerateKey()
|
||||
s.Require().NoError(err)
|
||||
|
||||
communityID := "test_community_id"
|
||||
s.Require().NotNil(aliceKey)
|
||||
s.Require().NotNil(bobKey)
|
||||
|
||||
s.logger.Info("Hash ratchet key exchange 1")
|
||||
keyID1, _ := s.alice.encryptor.GenerateHashRatchetKey([]byte(communityID))
|
||||
hashRatchetKeyExMsg1, _ := s.alice.BuildHashRatchetKeyExchangeMessage(aliceKey, &bobKey.PublicKey, communityID, keyID1)
|
||||
|
||||
s.logger.Info("Hash ratchet key exchange 1", zap.Any("msg", hashRatchetKeyExMsg1.Message))
|
||||
s.Require().NotNil(hashRatchetKeyExMsg1)
|
||||
|
||||
s.logger.Info("Handle hash ratchet key msg 1")
|
||||
decryptedResponse1, _ := s.bob.HandleMessage(bobKey, &aliceKey.PublicKey, hashRatchetKeyExMsg1.Message, defaultMessageID)
|
||||
decryptedHashRatchetKeyBytes1 := decryptedResponse1.DecryptedMessage
|
||||
decryptedHashRatchetKeyID1, _ := s.bob.encryptor.persistence.GetCurrentKeyForGroup(communityID)
|
||||
s.logger.Info("Current hash ratchet key in DB 1", zap.Any("keyId", decryptedHashRatchetKeyID1))
|
||||
s.Require().NotNil(decryptedHashRatchetKeyID1)
|
||||
s.Require().NotNil(decryptedHashRatchetKeyBytes1)
|
||||
//s.Equal(decryptedHashRatchetKey1, decryptedHashRatchetKeyBytes1)
|
||||
|
||||
payload1 := []byte("community msg 1")
|
||||
hashRatchetMsg1, err := s.bob.BuildHashRatchetMessage([]byte(communityID), payload1)
|
||||
s.logger.Info("BuildHashRatchetMessage 1", zap.Any("err", err))
|
||||
s.Require().NotNil(hashRatchetMsg1)
|
||||
s.Require().NotNil(hashRatchetMsg1.Message)
|
||||
|
||||
decryptedResponse2, err := s.alice.HandleMessage(aliceKey, nil, hashRatchetMsg1.Message, defaultMessageID)
|
||||
|
||||
s.logger.Info("HandleHashRatchetMessage 1", zap.Any("err", err))
|
||||
s.Require().NotNil(decryptedResponse2)
|
||||
s.Equal(payload1, decryptedResponse2.DecryptedMessage)
|
||||
|
||||
payload2 := []byte("community msg 2")
|
||||
hashRatchetMsg2, err := s.alice.BuildHashRatchetMessage([]byte(communityID), payload2)
|
||||
s.logger.Info("BuildHashRatchetMessage 2", zap.Any("err", err))
|
||||
s.Require().NotNil(hashRatchetMsg2)
|
||||
s.Require().NotNil(hashRatchetMsg2.Message)
|
||||
|
||||
decryptedResponse3, err := s.bob.HandleMessage(bobKey, nil, hashRatchetMsg2.Message, defaultMessageID)
|
||||
|
||||
s.logger.Info("HandleHashRatchetMessage 2", zap.Any("err", err))
|
||||
s.Require().NotNil(decryptedResponse3)
|
||||
s.Equal(payload2, decryptedResponse3.DecryptedMessage)
|
||||
|
||||
// Re-generate hash ratchet key. Bob generates a new key and sends it to Alice
|
||||
|
||||
keyID2, _ := s.bob.encryptor.GenerateHashRatchetKey([]byte(communityID))
|
||||
hashRatchetKeyExMsg2, _ := s.bob.BuildHashRatchetKeyExchangeMessage(bobKey, &aliceKey.PublicKey, communityID, keyID2)
|
||||
|
||||
s.logger.Info("Hash ratchet key exchange 2", zap.Any("msg", hashRatchetKeyExMsg2.Message))
|
||||
s.Require().NotNil(hashRatchetKeyExMsg2)
|
||||
|
||||
s.logger.Info("Handle hash ratchet key msg 2")
|
||||
decryptedResponse4, _ := s.alice.HandleMessage(aliceKey, &bobKey.PublicKey, hashRatchetKeyExMsg2.Message, defaultMessageID)
|
||||
decryptedHashRatchetKeyBytes2 := decryptedResponse4.DecryptedMessage
|
||||
decryptedHashRatchetKeyID2, _ := s.alice.encryptor.persistence.GetCurrentKeyForGroup(communityID)
|
||||
s.logger.Info("Current hash ratchet key in DB 2", zap.Any("keyId", decryptedHashRatchetKeyID2))
|
||||
s.Require().NotNil(decryptedHashRatchetKeyID2)
|
||||
s.Require().NotNil(decryptedHashRatchetKeyBytes2)
|
||||
|
||||
payload3 := []byte("community msg 3")
|
||||
hashRatchetMsg3, err := s.alice.BuildHashRatchetMessage([]byte(communityID), payload3)
|
||||
|
||||
s.logger.Info("BuildHashRatchetMessage err", zap.Any("err", err))
|
||||
s.Require().NotNil(hashRatchetMsg3)
|
||||
s.Require().NotNil(hashRatchetMsg3.Message)
|
||||
|
||||
//directMsg1 := hashRatchetMsg.Message.GetEncryptedMessage()
|
||||
|
||||
decryptedResponse5, err := s.bob.HandleMessage(bobKey, nil, hashRatchetMsg3.Message, defaultMessageID)
|
||||
|
||||
s.logger.Info("HandleHashRatchetMessage err", zap.Any("err", err))
|
||||
s.Require().NotNil(decryptedResponse5)
|
||||
s.Equal(payload3, decryptedResponse5.DecryptedMessage)
|
||||
|
||||
payload4 := []byte("community msg 4")
|
||||
payload5 := []byte("community msg 5")
|
||||
payload6 := []byte("community msg 6")
|
||||
hashRatchetMsg4, _ := s.alice.BuildHashRatchetMessage([]byte(communityID), payload4) // seqNo=2
|
||||
hashRatchetMsg5, _ := s.alice.BuildHashRatchetMessage([]byte(communityID), payload5) // seqNo=3
|
||||
hashRatchetMsg6, _ := s.alice.BuildHashRatchetMessage([]byte(communityID), payload6) // seqNo=3
|
||||
|
||||
// Handle them out of order plus an older one we've received earlier with seqNo=1
|
||||
|
||||
decryptedResponse6, _ := s.bob.HandleMessage(bobKey, nil, hashRatchetMsg6.Message, defaultMessageID)
|
||||
decryptedResponse7, _ := s.bob.HandleMessage(bobKey, nil, hashRatchetMsg5.Message, defaultMessageID)
|
||||
decryptedResponse8, _ := s.bob.HandleMessage(bobKey, nil, hashRatchetMsg4.Message, defaultMessageID)
|
||||
decryptedResponse9, _ := s.bob.HandleMessage(bobKey, nil, hashRatchetMsg3.Message, defaultMessageID)
|
||||
|
||||
s.logger.Info("HandleHashRatchetMessage err", zap.Any("err", err))
|
||||
s.Require().NotNil(decryptedResponse6)
|
||||
s.Equal(payload6, decryptedResponse6.DecryptedMessage)
|
||||
s.Require().NotNil(decryptedResponse7)
|
||||
s.Equal(payload5, decryptedResponse7.DecryptedMessage)
|
||||
s.Require().NotNil(decryptedResponse8)
|
||||
s.Equal(payload4, decryptedResponse8.DecryptedMessage)
|
||||
s.Require().NotNil(decryptedResponse9)
|
||||
s.Equal(payload3, decryptedResponse9.DecryptedMessage)
|
||||
|
||||
// Handle message with previous key
|
||||
decryptedResponse10, _ := s.bob.HandleMessage(bobKey, nil, hashRatchetMsg2.Message, defaultMessageID)
|
||||
s.Require().NotNil(decryptedResponse10)
|
||||
s.Equal(payload2, decryptedResponse10.DecryptedMessage)
|
||||
}
|
||||
|
||||
// Alice sends Bob an encrypted message with DH using an ephemeral key
|
||||
// and Bob's identity key.
|
||||
// Bob is able to decrypt it.
|
||||
|
@ -103,10 +215,10 @@ func (s *EncryptionServiceTestSuite) TestEncryptPayloadNoBundle() {
|
|||
aliceKey, err := crypto.GenerateKey()
|
||||
s.Require().NoError(err)
|
||||
|
||||
response1, err := s.alice.BuildDirectMessage(aliceKey, &bobKey.PublicKey, cleartext)
|
||||
response1, err := s.alice.BuildEncryptedMessage(aliceKey, &bobKey.PublicKey, cleartext)
|
||||
s.Require().NoError(err)
|
||||
|
||||
encryptionResponse1 := response1.Message.GetDirectMessage()
|
||||
encryptionResponse1 := response1.Message.GetEncryptedMessage()
|
||||
|
||||
installationResponse1 := encryptionResponse1["none"]
|
||||
// That's for any device
|
||||
|
@ -124,10 +236,10 @@ func (s *EncryptionServiceTestSuite) TestEncryptPayloadNoBundle() {
|
|||
s.Equal(cleartext, decryptedPayload1.DecryptedMessage, "It correctly decrypts the payload using DH")
|
||||
|
||||
// The next message will not be re-using the same key
|
||||
response2, err := s.alice.BuildDirectMessage(aliceKey, &bobKey.PublicKey, cleartext)
|
||||
response2, err := s.alice.BuildEncryptedMessage(aliceKey, &bobKey.PublicKey, cleartext)
|
||||
s.Require().NoError(err)
|
||||
|
||||
encryptionResponse2 := response2.Message.GetDirectMessage()
|
||||
encryptionResponse2 := response2.Message.GetEncryptedMessage()
|
||||
|
||||
installationResponse2 := encryptionResponse2[aliceInstallationID]
|
||||
|
||||
|
@ -160,10 +272,10 @@ func (s *EncryptionServiceTestSuite) TestEncryptPayloadBundle() {
|
|||
s.Require().NoError(err)
|
||||
|
||||
// We send a message using the bundle
|
||||
response1, err := s.alice.BuildDirectMessage(aliceKey, &bobKey.PublicKey, cleartext)
|
||||
response1, err := s.alice.BuildEncryptedMessage(aliceKey, &bobKey.PublicKey, cleartext)
|
||||
s.Require().NoError(err)
|
||||
|
||||
encryptionResponse1 := response1.Message.GetDirectMessage()
|
||||
encryptionResponse1 := response1.Message.GetEncryptedMessage()
|
||||
|
||||
installationResponse1 := encryptionResponse1[bobInstallationID]
|
||||
s.Require().NotNil(installationResponse1)
|
||||
|
@ -221,13 +333,13 @@ func (s *EncryptionServiceTestSuite) TestConsequentMessagesBundle() {
|
|||
s.Require().NoError(err)
|
||||
|
||||
// We send a message using the bundle
|
||||
_, err = s.alice.BuildDirectMessage(aliceKey, &bobKey.PublicKey, cleartext1)
|
||||
_, err = s.alice.BuildEncryptedMessage(aliceKey, &bobKey.PublicKey, cleartext1)
|
||||
s.Require().NoError(err)
|
||||
|
||||
// We send another message using the bundle
|
||||
response, err := s.alice.BuildDirectMessage(aliceKey, &bobKey.PublicKey, cleartext2)
|
||||
response, err := s.alice.BuildEncryptedMessage(aliceKey, &bobKey.PublicKey, cleartext2)
|
||||
s.Require().NoError(err)
|
||||
encryptionResponse := response.Message.GetDirectMessage()
|
||||
encryptionResponse := response.Message.GetEncryptedMessage()
|
||||
|
||||
installationResponse := encryptionResponse[bobInstallationID]
|
||||
s.Require().NotNil(installationResponse)
|
||||
|
@ -295,7 +407,7 @@ func (s *EncryptionServiceTestSuite) TestConversation() {
|
|||
s.Require().NoError(err)
|
||||
|
||||
// Alice sends a message
|
||||
response, err := s.alice.BuildDirectMessage(aliceKey, &bobKey.PublicKey, cleartext1)
|
||||
response, err := s.alice.BuildEncryptedMessage(aliceKey, &bobKey.PublicKey, cleartext1)
|
||||
s.Require().NoError(err)
|
||||
|
||||
// Bob receives the message
|
||||
|
@ -303,7 +415,7 @@ func (s *EncryptionServiceTestSuite) TestConversation() {
|
|||
s.Require().NoError(err)
|
||||
|
||||
// Bob replies to the message
|
||||
response, err = s.bob.BuildDirectMessage(bobKey, &aliceKey.PublicKey, cleartext1)
|
||||
response, err = s.bob.BuildEncryptedMessage(bobKey, &aliceKey.PublicKey, cleartext1)
|
||||
s.Require().NoError(err)
|
||||
|
||||
// Alice receives the message
|
||||
|
@ -311,9 +423,9 @@ func (s *EncryptionServiceTestSuite) TestConversation() {
|
|||
s.Require().NoError(err)
|
||||
|
||||
// We send another message using the bundle
|
||||
response, err = s.alice.BuildDirectMessage(aliceKey, &bobKey.PublicKey, cleartext2)
|
||||
response, err = s.alice.BuildEncryptedMessage(aliceKey, &bobKey.PublicKey, cleartext2)
|
||||
s.Require().NoError(err)
|
||||
encryptionResponse := response.Message.GetDirectMessage()
|
||||
encryptionResponse := response.Message.GetEncryptedMessage()
|
||||
|
||||
installationResponse := encryptionResponse[bobInstallationID]
|
||||
s.Require().NotNil(installationResponse)
|
||||
|
@ -378,12 +490,12 @@ func (s *EncryptionServiceTestSuite) TestMaxSkipKeys() {
|
|||
// Bob sends a message
|
||||
|
||||
for i := 0; i < s.alice.encryptor.config.MaxSkip; i++ {
|
||||
_, err = s.bob.BuildDirectMessage(bobKey, &aliceKey.PublicKey, bobText)
|
||||
_, err = s.bob.BuildEncryptedMessage(bobKey, &aliceKey.PublicKey, bobText)
|
||||
s.Require().NoError(err)
|
||||
}
|
||||
|
||||
// Bob sends a message
|
||||
bobMessage1, err := s.bob.BuildDirectMessage(bobKey, &aliceKey.PublicKey, bobText)
|
||||
bobMessage1, err := s.bob.BuildEncryptedMessage(bobKey, &aliceKey.PublicKey, bobText)
|
||||
s.Require().NoError(err)
|
||||
|
||||
// Alice receives the message
|
||||
|
@ -391,11 +503,11 @@ func (s *EncryptionServiceTestSuite) TestMaxSkipKeys() {
|
|||
s.Require().NoError(err)
|
||||
|
||||
// Bob sends a message
|
||||
_, err = s.bob.BuildDirectMessage(bobKey, &aliceKey.PublicKey, bobText)
|
||||
_, err = s.bob.BuildEncryptedMessage(bobKey, &aliceKey.PublicKey, bobText)
|
||||
s.Require().NoError(err)
|
||||
|
||||
// Bob sends a message
|
||||
bobMessage2, err := s.bob.BuildDirectMessage(bobKey, &aliceKey.PublicKey, bobText)
|
||||
bobMessage2, err := s.bob.BuildEncryptedMessage(bobKey, &aliceKey.PublicKey, bobText)
|
||||
s.Require().NoError(err)
|
||||
|
||||
// Alice receives the message, we should have maxSkip + 1 keys in the db, but
|
||||
|
@ -433,12 +545,12 @@ func (s *EncryptionServiceTestSuite) TestMaxSkipKeysError() {
|
|||
// Bob sends a message
|
||||
|
||||
for i := 0; i < s.alice.encryptor.config.MaxSkip+1; i++ {
|
||||
_, err = s.bob.BuildDirectMessage(bobKey, &aliceKey.PublicKey, bobText)
|
||||
_, err = s.bob.BuildEncryptedMessage(bobKey, &aliceKey.PublicKey, bobText)
|
||||
s.Require().NoError(err)
|
||||
}
|
||||
|
||||
// Bob sends a message
|
||||
bobMessage1, err := s.bob.BuildDirectMessage(bobKey, &aliceKey.PublicKey, bobText)
|
||||
bobMessage1, err := s.bob.BuildEncryptedMessage(bobKey, &aliceKey.PublicKey, bobText)
|
||||
s.Require().NoError(err)
|
||||
|
||||
// Alice receives the message
|
||||
|
@ -483,14 +595,14 @@ func (s *EncryptionServiceTestSuite) TestMaxMessageKeysPerSession() {
|
|||
nMessages := s.alice.encryptor.config.MaxMessageKeysPerSession
|
||||
messages := make([]*ProtocolMessage, nMessages)
|
||||
for i := 0; i < nMessages; i++ {
|
||||
m, err := s.bob.BuildDirectMessage(bobKey, &aliceKey.PublicKey, bobText)
|
||||
m, err := s.bob.BuildEncryptedMessage(bobKey, &aliceKey.PublicKey, bobText)
|
||||
s.Require().NoError(err)
|
||||
|
||||
messages[i] = m.Message
|
||||
}
|
||||
|
||||
// Another message to trigger the deletion
|
||||
m, err := s.bob.BuildDirectMessage(bobKey, &aliceKey.PublicKey, bobText)
|
||||
m, err := s.bob.BuildEncryptedMessage(bobKey, &aliceKey.PublicKey, bobText)
|
||||
s.Require().NoError(err)
|
||||
_, err = s.alice.HandleMessage(aliceKey, &bobKey.PublicKey, m.Message, defaultMessageID)
|
||||
s.Require().NoError(err)
|
||||
|
@ -538,7 +650,7 @@ func (s *EncryptionServiceTestSuite) TestMaxKeep() {
|
|||
// We decrypt all messages but 1 & 2
|
||||
messages := make([]*ProtocolMessage, s.alice.encryptor.config.MaxKeep)
|
||||
for i := 0; i < s.alice.encryptor.config.MaxKeep; i++ {
|
||||
m, err := s.bob.BuildDirectMessage(bobKey, &aliceKey.PublicKey, bobText)
|
||||
m, err := s.bob.BuildEncryptedMessage(bobKey, &aliceKey.PublicKey, bobText)
|
||||
messages[i] = m.Message
|
||||
s.Require().NoError(err)
|
||||
|
||||
|
@ -597,11 +709,11 @@ func (s *EncryptionServiceTestSuite) TestConcurrentBundles() {
|
|||
s.Require().NoError(err)
|
||||
|
||||
// Alice sends a message
|
||||
aliceMessage1, err := s.alice.BuildDirectMessage(aliceKey, &bobKey.PublicKey, aliceText1)
|
||||
aliceMessage1, err := s.alice.BuildEncryptedMessage(aliceKey, &bobKey.PublicKey, aliceText1)
|
||||
s.Require().NoError(err)
|
||||
|
||||
// Bob sends a message
|
||||
bobMessage1, err := s.bob.BuildDirectMessage(bobKey, &aliceKey.PublicKey, bobText1)
|
||||
bobMessage1, err := s.bob.BuildEncryptedMessage(bobKey, &aliceKey.PublicKey, bobText1)
|
||||
s.Require().NoError(err)
|
||||
|
||||
// Bob receives the message
|
||||
|
@ -613,11 +725,11 @@ func (s *EncryptionServiceTestSuite) TestConcurrentBundles() {
|
|||
s.Require().NoError(err)
|
||||
|
||||
// Bob replies to the message
|
||||
bobMessage2, err := s.bob.BuildDirectMessage(bobKey, &aliceKey.PublicKey, bobText2)
|
||||
bobMessage2, err := s.bob.BuildEncryptedMessage(bobKey, &aliceKey.PublicKey, bobText2)
|
||||
s.Require().NoError(err)
|
||||
|
||||
// Alice sends a message
|
||||
aliceMessage2, err := s.alice.BuildDirectMessage(aliceKey, &bobKey.PublicKey, aliceText2)
|
||||
aliceMessage2, err := s.alice.BuildEncryptedMessage(aliceKey, &bobKey.PublicKey, aliceText2)
|
||||
s.Require().NoError(err)
|
||||
|
||||
// Alice receives the message
|
||||
|
@ -647,7 +759,7 @@ func publish(
|
|||
go func() {
|
||||
defer wg.Done()
|
||||
time.Sleep(time.Duration(rand.Intn(50)) * time.Millisecond) // nolint: gosec
|
||||
response, err := e.BuildDirectMessage(privateKey, publicKey, cleartext)
|
||||
response, err := e.BuildEncryptedMessage(privateKey, publicKey, cleartext)
|
||||
if err != nil {
|
||||
errChan <- err
|
||||
return
|
||||
|
@ -775,7 +887,7 @@ func (s *EncryptionServiceTestSuite) TestBundleNotExisting() {
|
|||
s.Require().NoError(err)
|
||||
|
||||
// Alice sends a message
|
||||
aliceMessage, err := s.alice.BuildDirectMessage(aliceKey, &bobKey.PublicKey, aliceText)
|
||||
aliceMessage, err := s.alice.BuildEncryptedMessage(aliceKey, &bobKey.PublicKey, aliceText)
|
||||
s.Require().NoError(err)
|
||||
|
||||
// Bob receives the message, and returns a bundlenotfound error
|
||||
|
@ -808,7 +920,7 @@ func (s *EncryptionServiceTestSuite) TestDeviceNotIncluded() {
|
|||
s.Require().NoError(err)
|
||||
|
||||
// Alice sends a message
|
||||
aliceMessage, err := s.alice.BuildDirectMessage(aliceKey, &bobKey.PublicKey, []byte("does not matter"))
|
||||
aliceMessage, err := s.alice.BuildEncryptedMessage(aliceKey, &bobKey.PublicKey, []byte("does not matter"))
|
||||
s.Require().NoError(err)
|
||||
|
||||
// Bob receives the message, and returns a bundlenotfound error
|
||||
|
@ -849,9 +961,9 @@ func (s *EncryptionServiceTestSuite) TestRefreshedBundle() {
|
|||
s.Require().NoError(err)
|
||||
|
||||
// Alice sends a message
|
||||
response1, err := s.alice.BuildDirectMessage(aliceKey, &bobKey.PublicKey, []byte("anything"))
|
||||
response1, err := s.alice.BuildEncryptedMessage(aliceKey, &bobKey.PublicKey, []byte("anything"))
|
||||
s.Require().NoError(err)
|
||||
encryptionResponse1 := response1.Message.GetDirectMessage()
|
||||
encryptionResponse1 := response1.Message.GetEncryptedMessage()
|
||||
|
||||
installationResponse1 := encryptionResponse1[bobInstallationID]
|
||||
s.Require().NotNil(installationResponse1)
|
||||
|
@ -871,9 +983,9 @@ func (s *EncryptionServiceTestSuite) TestRefreshedBundle() {
|
|||
s.Require().NoError(err)
|
||||
|
||||
// Alice sends a message
|
||||
response2, err := s.alice.BuildDirectMessage(aliceKey, &bobKey.PublicKey, []byte("anything"))
|
||||
response2, err := s.alice.BuildEncryptedMessage(aliceKey, &bobKey.PublicKey, []byte("anything"))
|
||||
s.Require().NoError(err)
|
||||
encryptionResponse2 := response2.Message.GetDirectMessage()
|
||||
encryptionResponse2 := response2.Message.GetEncryptedMessage()
|
||||
|
||||
installationResponse2 := encryptionResponse2[bobInstallationID]
|
||||
s.Require().NotNil(installationResponse2)
|
||||
|
@ -915,7 +1027,7 @@ func (s *EncryptionServiceTestSuite) TestMessageConfirmation() {
|
|||
s.Require().NoError(err)
|
||||
|
||||
// Bob sends a message
|
||||
bobMessage1, err := s.bob.BuildDirectMessage(bobKey, &aliceKey.PublicKey, bobText1)
|
||||
bobMessage1, err := s.bob.BuildEncryptedMessage(bobKey, &aliceKey.PublicKey, bobText1)
|
||||
s.Require().NoError(err)
|
||||
bobMessage1ID := []byte("bob-message-1-id")
|
||||
|
||||
|
@ -936,12 +1048,12 @@ func (s *EncryptionServiceTestSuite) TestMessageConfirmation() {
|
|||
s.Require().Equal(errors.New("can't skip current chain message keys: bad until: probably an out-of-order message that was deleted"), err)
|
||||
|
||||
// Bob sends a message
|
||||
bobMessage2, err := s.bob.BuildDirectMessage(bobKey, &aliceKey.PublicKey, bobText1)
|
||||
bobMessage2, err := s.bob.BuildEncryptedMessage(bobKey, &aliceKey.PublicKey, bobText1)
|
||||
s.Require().NoError(err)
|
||||
bobMessage2ID := []byte("bob-message-2-id")
|
||||
|
||||
// Bob sends a message
|
||||
bobMessage3, err := s.bob.BuildDirectMessage(bobKey, &aliceKey.PublicKey, bobText1)
|
||||
bobMessage3, err := s.bob.BuildEncryptedMessage(bobKey, &aliceKey.PublicKey, bobText1)
|
||||
s.Require().NoError(err)
|
||||
bobMessage3ID := []byte("bob-message-3-id")
|
||||
|
||||
|
|
|
@ -25,11 +25,15 @@ var (
|
|||
// but from a device that has not been paired.
|
||||
// This should not happen because the protocol forbids sending a message to
|
||||
// non-paired devices, however, in theory it is possible to receive such a message.
|
||||
ErrNotPairedDevice = errors.New("received a message from not paired device")
|
||||
ErrNotPairedDevice = errors.New("received a message from not paired device")
|
||||
ErrHashRatchetSeqNoTooHigh = errors.New("Hash ratchet seq no is too high")
|
||||
)
|
||||
|
||||
// If we have no bundles, we use a constant so that the message can reach any device.
|
||||
const noInstallationID = "none"
|
||||
const (
|
||||
noInstallationID = "none"
|
||||
maxHashRatchetSeqNoDelta = 1000
|
||||
)
|
||||
|
||||
type confirmationData struct {
|
||||
header *dr.MessageHeader
|
||||
|
@ -233,8 +237,8 @@ func (s *encryptor) ProcessPublicBundle(myIdentityKey *ecdsa.PrivateKey, b *Bund
|
|||
return s.persistence.AddPublicBundle(b)
|
||||
}
|
||||
|
||||
// DecryptPayload decrypts the payload of a DirectMessageProtocol, given an identity private key and the sender's public key
|
||||
func (s *encryptor) DecryptPayload(myIdentityKey *ecdsa.PrivateKey, theirIdentityKey *ecdsa.PublicKey, theirInstallationID string, msgs map[string]*DirectMessageProtocol, messageID []byte) ([]byte, error) {
|
||||
// DecryptPayload decrypts the payload of a EncryptedMessageProtocol, given an identity private key and the sender's public key
|
||||
func (s *encryptor) DecryptPayload(myIdentityKey *ecdsa.PrivateKey, theirIdentityKey *ecdsa.PublicKey, theirInstallationID string, msgs map[string]*EncryptedMessageProtocol, messageID []byte) ([]byte, error) {
|
||||
s.mutex.Lock()
|
||||
defer s.mutex.Unlock()
|
||||
|
||||
|
@ -324,6 +328,10 @@ func (s *encryptor) DecryptPayload(myIdentityKey *ecdsa.PrivateKey, theirIdentit
|
|||
return s.DecryptWithDH(myIdentityKey, decompressedKey, payload)
|
||||
}
|
||||
|
||||
// Try Hash Ratchet
|
||||
if header := msg.GetHRHeader(); header != nil {
|
||||
return s.decryptWithHR([]byte(header.GroupId), header.KeyId, header.SeqNo, payload)
|
||||
}
|
||||
return nil, errors.New("no key specified")
|
||||
}
|
||||
|
||||
|
@ -428,7 +436,7 @@ func (s *encryptor) decryptUsingDR(theirIdentityKey *ecdsa.PublicKey, drInfo *Ra
|
|||
return plaintext, nil
|
||||
}
|
||||
|
||||
func (s *encryptor) encryptWithDH(theirIdentityKey *ecdsa.PublicKey, payload []byte) (*DirectMessageProtocol, error) {
|
||||
func (s *encryptor) encryptWithDH(theirIdentityKey *ecdsa.PublicKey, payload []byte) (*EncryptedMessageProtocol, error) {
|
||||
symmetricKey, ourEphemeralKey, err := PerformActiveDH(theirIdentityKey)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
@ -439,7 +447,7 @@ func (s *encryptor) encryptWithDH(theirIdentityKey *ecdsa.PublicKey, payload []b
|
|||
return nil, err
|
||||
}
|
||||
|
||||
return &DirectMessageProtocol{
|
||||
return &EncryptedMessageProtocol{
|
||||
DHHeader: &DHHeader{
|
||||
Key: crypto.CompressPubkey(ourEphemeralKey),
|
||||
},
|
||||
|
@ -447,8 +455,8 @@ func (s *encryptor) encryptWithDH(theirIdentityKey *ecdsa.PublicKey, payload []b
|
|||
}, nil
|
||||
}
|
||||
|
||||
func (s *encryptor) EncryptPayloadWithDH(theirIdentityKey *ecdsa.PublicKey, payload []byte) (map[string]*DirectMessageProtocol, error) {
|
||||
response := make(map[string]*DirectMessageProtocol)
|
||||
func (s *encryptor) EncryptPayloadWithDH(theirIdentityKey *ecdsa.PublicKey, payload []byte) (map[string]*EncryptedMessageProtocol, error) {
|
||||
response := make(map[string]*EncryptedMessageProtocol)
|
||||
dmp, err := s.encryptWithDH(theirIdentityKey, payload)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
@ -463,8 +471,8 @@ func (s *encryptor) GetPublicBundle(theirIdentityKey *ecdsa.PublicKey, installat
|
|||
return s.persistence.GetPublicBundle(theirIdentityKey, installations)
|
||||
}
|
||||
|
||||
// EncryptPayload returns a new DirectMessageProtocol with a given payload encrypted, given a recipient's public key and the sender private identity key
|
||||
func (s *encryptor) EncryptPayload(theirIdentityKey *ecdsa.PublicKey, myIdentityKey *ecdsa.PrivateKey, installations []*multidevice.Installation, payload []byte) (map[string]*DirectMessageProtocol, []*multidevice.Installation, error) {
|
||||
// EncryptPayload returns a new EncryptedMessageProtocol with a given payload encrypted, given a recipient's public key and the sender private identity key
|
||||
func (s *encryptor) EncryptPayload(theirIdentityKey *ecdsa.PublicKey, myIdentityKey *ecdsa.PrivateKey, installations []*multidevice.Installation, payload []byte) (map[string]*EncryptedMessageProtocol, []*multidevice.Installation, error) {
|
||||
logger := s.logger.With(
|
||||
zap.String("site", "EncryptPayload"),
|
||||
zap.String("their-identity-key", types.EncodeHex(crypto.FromECDSAPub(theirIdentityKey))))
|
||||
|
@ -475,15 +483,15 @@ func (s *encryptor) EncryptPayload(theirIdentityKey *ecdsa.PublicKey, myIdentity
|
|||
s.mutex.Lock()
|
||||
defer s.mutex.Unlock()
|
||||
|
||||
// We don't have any, send a message with DH
|
||||
if len(installations) == 0 {
|
||||
// We don't have any, send a message with DH
|
||||
logger.Debug("no installations, sending to all devices")
|
||||
encryptedPayload, err := s.EncryptPayloadWithDH(theirIdentityKey, payload)
|
||||
return encryptedPayload, targetedInstallations, err
|
||||
}
|
||||
|
||||
theirIdentityKeyC := crypto.CompressPubkey(theirIdentityKey)
|
||||
response := make(map[string]*DirectMessageProtocol)
|
||||
response := make(map[string]*EncryptedMessageProtocol)
|
||||
|
||||
for _, installation := range installations {
|
||||
installationID := installation.ID
|
||||
|
@ -513,7 +521,7 @@ func (s *encryptor) EncryptPayload(theirIdentityKey *ecdsa.PublicKey, myIdentity
|
|||
return nil, nil, err
|
||||
}
|
||||
|
||||
dmp := DirectMessageProtocol{
|
||||
dmp := EncryptedMessageProtocol{
|
||||
Payload: encryptedPayload,
|
||||
DRHeader: drHeader,
|
||||
}
|
||||
|
@ -570,7 +578,7 @@ func (s *encryptor) EncryptPayload(theirIdentityKey *ecdsa.PublicKey, myIdentity
|
|||
return nil, nil, err
|
||||
}
|
||||
|
||||
dmp := &DirectMessageProtocol{
|
||||
dmp := &EncryptedMessageProtocol{
|
||||
Payload: encryptedPayload,
|
||||
X3DHHeader: x3dhHeader,
|
||||
DRHeader: drHeader,
|
||||
|
@ -592,6 +600,131 @@ func (s *encryptor) EncryptPayload(theirIdentityKey *ecdsa.PublicKey, myIdentity
|
|||
return response, targetedInstallations, nil
|
||||
}
|
||||
|
||||
func (s *encryptor) getNextHashRatchetKeyID(groupID string) (uint32, error) {
|
||||
latestKeyID, err := s.persistence.GetCurrentKeyForGroup(groupID)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
currentTime := (uint32)(time.Now().UnixNano() / int64(time.Millisecond))
|
||||
keyIDBump := (uint32)(10)
|
||||
if latestKeyID < currentTime {
|
||||
return currentTime + keyIDBump, nil
|
||||
}
|
||||
|
||||
return latestKeyID + 1, nil
|
||||
}
|
||||
|
||||
// Generates and stores a hash ratchet key given a group ID
|
||||
func (s *encryptor) GenerateHashRatchetKey(groupID []byte) (uint32, error) {
|
||||
|
||||
// Randomly generate a hash ratchet key
|
||||
hrKey, err := crypto.GenerateKey()
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
hrKeyBytes := crypto.FromECDSA(hrKey)
|
||||
|
||||
keyID, err := s.getNextHashRatchetKeyID(string(groupID))
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
err = s.persistence.SaveHashRatchetKey(string(groupID), keyID, hrKeyBytes)
|
||||
|
||||
return keyID, err
|
||||
}
|
||||
|
||||
// EncryptHashRatchetPayload returns a new EncryptedMessageProtocol with a given payload encrypted, given a group's key
|
||||
func (s *encryptor) EncryptHashRatchetPayload(groupID []byte, keyID uint32, payload []byte) (map[string]*EncryptedMessageProtocol, error) {
|
||||
logger := s.logger.With(
|
||||
zap.String("site", "EncryptHashRatchetPayload"),
|
||||
zap.Any("group-id", groupID),
|
||||
zap.Any("key-id", keyID))
|
||||
|
||||
s.mutex.Lock()
|
||||
defer s.mutex.Unlock()
|
||||
|
||||
logger.Debug("encrypting hash ratchet message")
|
||||
dmp, err := s.encryptWithHR(groupID, keyID, payload)
|
||||
response := make(map[string]*EncryptedMessageProtocol)
|
||||
response[noInstallationID] = dmp
|
||||
return response, err
|
||||
}
|
||||
|
||||
func samePublicKeys(pubKey1, pubKey2 ecdsa.PublicKey) bool {
|
||||
return pubKey1.X.Cmp(pubKey2.X) == 0 && pubKey1.Y.Cmp(pubKey2.Y) == 0
|
||||
}
|
||||
|
||||
func (s *encryptor) encryptWithHR(groupID []byte, keyID uint32, payload []byte) (*EncryptedMessageProtocol, error) {
|
||||
hrCache, err := s.persistence.GetHashRatchetKeyByID(groupID, keyID, 0) // Get latest seqNo
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var dbHash []byte
|
||||
if len(hrCache.Hash) == 0 {
|
||||
dbHash = hrCache.Key
|
||||
} else {
|
||||
dbHash = hrCache.Hash
|
||||
}
|
||||
|
||||
hash := crypto.Keccak256Hash(dbHash)
|
||||
encryptedPayload, err := crypto.EncryptSymmetric(hash.Bytes(), payload)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
newSeqNo := hrCache.SeqNo + 1
|
||||
err = s.persistence.SaveHashRatchetKeyHash(groupID, keyID, hash.Bytes(), newSeqNo)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
dmp := &EncryptedMessageProtocol{
|
||||
HRHeader: &HRHeader{
|
||||
GroupId: string(groupID),
|
||||
KeyId: keyID,
|
||||
SeqNo: newSeqNo,
|
||||
},
|
||||
Payload: encryptedPayload,
|
||||
}
|
||||
return dmp, nil
|
||||
}
|
||||
|
||||
func (s *encryptor) decryptWithHR(groupID []byte, keyID uint32, seqNo uint32, payload []byte) ([]byte, error) {
|
||||
|
||||
hrCache, err := s.persistence.GetHashRatchetKeyByID(groupID, keyID, seqNo)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Handle mesages with seqNo less than the one in db
|
||||
// 1. Check cache. If present for a particular seqNo, all good
|
||||
// 2. Otherwise, get the latest one for that keyId
|
||||
// 3. Every time the key is generated, it has to be saved in the cache along with the hash
|
||||
var hash []byte = hrCache.Hash
|
||||
if hrCache.SeqNo == seqNo {
|
||||
// We already have the hash for this seqNo
|
||||
hash = hrCache.Hash
|
||||
} else {
|
||||
if hrCache.SeqNo == 0 {
|
||||
// No cache records found for this keyId
|
||||
hash = hrCache.Key
|
||||
}
|
||||
// We should not have "holes" in seq numbers,
|
||||
// so a case when hrCache.SeqNo > seqNo shouldn't occur
|
||||
if seqNo-hrCache.SeqNo > maxHashRatchetSeqNoDelta {
|
||||
return nil, ErrHashRatchetSeqNoTooHigh
|
||||
}
|
||||
for i := hrCache.SeqNo; i < seqNo; i++ {
|
||||
hash = crypto.Keccak256Hash(hash).Bytes()
|
||||
err := s.persistence.SaveHashRatchetKeyHash(groupID, keyID, hash, i+1)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
decryptedPayload, err := crypto.DecryptSymmetric(hash, payload)
|
||||
|
||||
return decryptedPayload, err
|
||||
}
|
||||
|
|
|
@ -1,540 +0,0 @@
|
|||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||
// source: protocol_message.proto
|
||||
|
||||
package encryption
|
||||
|
||||
import (
|
||||
fmt "fmt"
|
||||
proto "github.com/golang/protobuf/proto"
|
||||
math "math"
|
||||
)
|
||||
|
||||
// Reference imports to suppress errors if they are not otherwise used.
|
||||
var _ = proto.Marshal
|
||||
var _ = fmt.Errorf
|
||||
var _ = math.Inf
|
||||
|
||||
// This is a compile-time assertion to ensure that this generated file
|
||||
// is compatible with the proto package it is being compiled against.
|
||||
// A compilation error at this line likely means your copy of the
|
||||
// proto package needs to be updated.
|
||||
const _ = proto.ProtoPackageIsVersion3 // please upgrade the proto package
|
||||
|
||||
type SignedPreKey struct {
|
||||
SignedPreKey []byte `protobuf:"bytes,1,opt,name=signed_pre_key,json=signedPreKey,proto3" json:"signed_pre_key,omitempty"`
|
||||
Version uint32 `protobuf:"varint,2,opt,name=version,proto3" json:"version,omitempty"`
|
||||
ProtocolVersion uint32 `protobuf:"varint,3,opt,name=protocol_version,json=protocolVersion,proto3" json:"protocol_version,omitempty"`
|
||||
XXX_NoUnkeyedLiteral struct{} `json:"-"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
XXX_sizecache int32 `json:"-"`
|
||||
}
|
||||
|
||||
func (m *SignedPreKey) Reset() { *m = SignedPreKey{} }
|
||||
func (m *SignedPreKey) String() string { return proto.CompactTextString(m) }
|
||||
func (*SignedPreKey) ProtoMessage() {}
|
||||
func (*SignedPreKey) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_4e37b52004a72e16, []int{0}
|
||||
}
|
||||
|
||||
func (m *SignedPreKey) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_SignedPreKey.Unmarshal(m, b)
|
||||
}
|
||||
func (m *SignedPreKey) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
||||
return xxx_messageInfo_SignedPreKey.Marshal(b, m, deterministic)
|
||||
}
|
||||
func (m *SignedPreKey) XXX_Merge(src proto.Message) {
|
||||
xxx_messageInfo_SignedPreKey.Merge(m, src)
|
||||
}
|
||||
func (m *SignedPreKey) XXX_Size() int {
|
||||
return xxx_messageInfo_SignedPreKey.Size(m)
|
||||
}
|
||||
func (m *SignedPreKey) XXX_DiscardUnknown() {
|
||||
xxx_messageInfo_SignedPreKey.DiscardUnknown(m)
|
||||
}
|
||||
|
||||
var xxx_messageInfo_SignedPreKey proto.InternalMessageInfo
|
||||
|
||||
func (m *SignedPreKey) GetSignedPreKey() []byte {
|
||||
if m != nil {
|
||||
return m.SignedPreKey
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *SignedPreKey) GetVersion() uint32 {
|
||||
if m != nil {
|
||||
return m.Version
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (m *SignedPreKey) GetProtocolVersion() uint32 {
|
||||
if m != nil {
|
||||
return m.ProtocolVersion
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
// X3DH prekey bundle
|
||||
type Bundle struct {
|
||||
// Identity key
|
||||
Identity []byte `protobuf:"bytes,1,opt,name=identity,proto3" json:"identity,omitempty"`
|
||||
// Installation id
|
||||
SignedPreKeys map[string]*SignedPreKey `protobuf:"bytes,2,rep,name=signed_pre_keys,json=signedPreKeys,proto3" json:"signed_pre_keys,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"`
|
||||
// Prekey signature
|
||||
Signature []byte `protobuf:"bytes,4,opt,name=signature,proto3" json:"signature,omitempty"`
|
||||
// When the bundle was created locally
|
||||
Timestamp int64 `protobuf:"varint,5,opt,name=timestamp,proto3" json:"timestamp,omitempty"`
|
||||
XXX_NoUnkeyedLiteral struct{} `json:"-"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
XXX_sizecache int32 `json:"-"`
|
||||
}
|
||||
|
||||
func (m *Bundle) Reset() { *m = Bundle{} }
|
||||
func (m *Bundle) String() string { return proto.CompactTextString(m) }
|
||||
func (*Bundle) ProtoMessage() {}
|
||||
func (*Bundle) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_4e37b52004a72e16, []int{1}
|
||||
}
|
||||
|
||||
func (m *Bundle) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_Bundle.Unmarshal(m, b)
|
||||
}
|
||||
func (m *Bundle) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
||||
return xxx_messageInfo_Bundle.Marshal(b, m, deterministic)
|
||||
}
|
||||
func (m *Bundle) XXX_Merge(src proto.Message) {
|
||||
xxx_messageInfo_Bundle.Merge(m, src)
|
||||
}
|
||||
func (m *Bundle) XXX_Size() int {
|
||||
return xxx_messageInfo_Bundle.Size(m)
|
||||
}
|
||||
func (m *Bundle) XXX_DiscardUnknown() {
|
||||
xxx_messageInfo_Bundle.DiscardUnknown(m)
|
||||
}
|
||||
|
||||
var xxx_messageInfo_Bundle proto.InternalMessageInfo
|
||||
|
||||
func (m *Bundle) GetIdentity() []byte {
|
||||
if m != nil {
|
||||
return m.Identity
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *Bundle) GetSignedPreKeys() map[string]*SignedPreKey {
|
||||
if m != nil {
|
||||
return m.SignedPreKeys
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *Bundle) GetSignature() []byte {
|
||||
if m != nil {
|
||||
return m.Signature
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *Bundle) GetTimestamp() int64 {
|
||||
if m != nil {
|
||||
return m.Timestamp
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
type BundleContainer struct {
|
||||
// X3DH prekey bundle
|
||||
Bundle *Bundle `protobuf:"bytes,1,opt,name=bundle,proto3" json:"bundle,omitempty"`
|
||||
// Private signed prekey
|
||||
PrivateSignedPreKey []byte `protobuf:"bytes,2,opt,name=private_signed_pre_key,json=privateSignedPreKey,proto3" json:"private_signed_pre_key,omitempty"`
|
||||
XXX_NoUnkeyedLiteral struct{} `json:"-"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
XXX_sizecache int32 `json:"-"`
|
||||
}
|
||||
|
||||
func (m *BundleContainer) Reset() { *m = BundleContainer{} }
|
||||
func (m *BundleContainer) String() string { return proto.CompactTextString(m) }
|
||||
func (*BundleContainer) ProtoMessage() {}
|
||||
func (*BundleContainer) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_4e37b52004a72e16, []int{2}
|
||||
}
|
||||
|
||||
func (m *BundleContainer) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_BundleContainer.Unmarshal(m, b)
|
||||
}
|
||||
func (m *BundleContainer) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
||||
return xxx_messageInfo_BundleContainer.Marshal(b, m, deterministic)
|
||||
}
|
||||
func (m *BundleContainer) XXX_Merge(src proto.Message) {
|
||||
xxx_messageInfo_BundleContainer.Merge(m, src)
|
||||
}
|
||||
func (m *BundleContainer) XXX_Size() int {
|
||||
return xxx_messageInfo_BundleContainer.Size(m)
|
||||
}
|
||||
func (m *BundleContainer) XXX_DiscardUnknown() {
|
||||
xxx_messageInfo_BundleContainer.DiscardUnknown(m)
|
||||
}
|
||||
|
||||
var xxx_messageInfo_BundleContainer proto.InternalMessageInfo
|
||||
|
||||
func (m *BundleContainer) GetBundle() *Bundle {
|
||||
if m != nil {
|
||||
return m.Bundle
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *BundleContainer) GetPrivateSignedPreKey() []byte {
|
||||
if m != nil {
|
||||
return m.PrivateSignedPreKey
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type DRHeader struct {
|
||||
// Current ratchet public key
|
||||
Key []byte `protobuf:"bytes,1,opt,name=key,proto3" json:"key,omitempty"`
|
||||
// Number of the message in the sending chain
|
||||
N uint32 `protobuf:"varint,2,opt,name=n,proto3" json:"n,omitempty"`
|
||||
// Length of the previous sending chain
|
||||
Pn uint32 `protobuf:"varint,3,opt,name=pn,proto3" json:"pn,omitempty"`
|
||||
// Bundle ID
|
||||
Id []byte `protobuf:"bytes,4,opt,name=id,proto3" json:"id,omitempty"`
|
||||
XXX_NoUnkeyedLiteral struct{} `json:"-"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
XXX_sizecache int32 `json:"-"`
|
||||
}
|
||||
|
||||
func (m *DRHeader) Reset() { *m = DRHeader{} }
|
||||
func (m *DRHeader) String() string { return proto.CompactTextString(m) }
|
||||
func (*DRHeader) ProtoMessage() {}
|
||||
func (*DRHeader) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_4e37b52004a72e16, []int{3}
|
||||
}
|
||||
|
||||
func (m *DRHeader) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_DRHeader.Unmarshal(m, b)
|
||||
}
|
||||
func (m *DRHeader) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
||||
return xxx_messageInfo_DRHeader.Marshal(b, m, deterministic)
|
||||
}
|
||||
func (m *DRHeader) XXX_Merge(src proto.Message) {
|
||||
xxx_messageInfo_DRHeader.Merge(m, src)
|
||||
}
|
||||
func (m *DRHeader) XXX_Size() int {
|
||||
return xxx_messageInfo_DRHeader.Size(m)
|
||||
}
|
||||
func (m *DRHeader) XXX_DiscardUnknown() {
|
||||
xxx_messageInfo_DRHeader.DiscardUnknown(m)
|
||||
}
|
||||
|
||||
var xxx_messageInfo_DRHeader proto.InternalMessageInfo
|
||||
|
||||
func (m *DRHeader) GetKey() []byte {
|
||||
if m != nil {
|
||||
return m.Key
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *DRHeader) GetN() uint32 {
|
||||
if m != nil {
|
||||
return m.N
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (m *DRHeader) GetPn() uint32 {
|
||||
if m != nil {
|
||||
return m.Pn
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (m *DRHeader) GetId() []byte {
|
||||
if m != nil {
|
||||
return m.Id
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type DHHeader struct {
|
||||
// Compressed ephemeral public key
|
||||
Key []byte `protobuf:"bytes,1,opt,name=key,proto3" json:"key,omitempty"`
|
||||
XXX_NoUnkeyedLiteral struct{} `json:"-"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
XXX_sizecache int32 `json:"-"`
|
||||
}
|
||||
|
||||
func (m *DHHeader) Reset() { *m = DHHeader{} }
|
||||
func (m *DHHeader) String() string { return proto.CompactTextString(m) }
|
||||
func (*DHHeader) ProtoMessage() {}
|
||||
func (*DHHeader) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_4e37b52004a72e16, []int{4}
|
||||
}
|
||||
|
||||
func (m *DHHeader) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_DHHeader.Unmarshal(m, b)
|
||||
}
|
||||
func (m *DHHeader) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
||||
return xxx_messageInfo_DHHeader.Marshal(b, m, deterministic)
|
||||
}
|
||||
func (m *DHHeader) XXX_Merge(src proto.Message) {
|
||||
xxx_messageInfo_DHHeader.Merge(m, src)
|
||||
}
|
||||
func (m *DHHeader) XXX_Size() int {
|
||||
return xxx_messageInfo_DHHeader.Size(m)
|
||||
}
|
||||
func (m *DHHeader) XXX_DiscardUnknown() {
|
||||
xxx_messageInfo_DHHeader.DiscardUnknown(m)
|
||||
}
|
||||
|
||||
var xxx_messageInfo_DHHeader proto.InternalMessageInfo
|
||||
|
||||
func (m *DHHeader) GetKey() []byte {
|
||||
if m != nil {
|
||||
return m.Key
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type X3DHHeader struct {
|
||||
// Ephemeral key used
|
||||
Key []byte `protobuf:"bytes,1,opt,name=key,proto3" json:"key,omitempty"`
|
||||
// Used bundle's signed prekey
|
||||
Id []byte `protobuf:"bytes,4,opt,name=id,proto3" json:"id,omitempty"`
|
||||
XXX_NoUnkeyedLiteral struct{} `json:"-"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
XXX_sizecache int32 `json:"-"`
|
||||
}
|
||||
|
||||
func (m *X3DHHeader) Reset() { *m = X3DHHeader{} }
|
||||
func (m *X3DHHeader) String() string { return proto.CompactTextString(m) }
|
||||
func (*X3DHHeader) ProtoMessage() {}
|
||||
func (*X3DHHeader) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_4e37b52004a72e16, []int{5}
|
||||
}
|
||||
|
||||
func (m *X3DHHeader) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_X3DHHeader.Unmarshal(m, b)
|
||||
}
|
||||
func (m *X3DHHeader) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
||||
return xxx_messageInfo_X3DHHeader.Marshal(b, m, deterministic)
|
||||
}
|
||||
func (m *X3DHHeader) XXX_Merge(src proto.Message) {
|
||||
xxx_messageInfo_X3DHHeader.Merge(m, src)
|
||||
}
|
||||
func (m *X3DHHeader) XXX_Size() int {
|
||||
return xxx_messageInfo_X3DHHeader.Size(m)
|
||||
}
|
||||
func (m *X3DHHeader) XXX_DiscardUnknown() {
|
||||
xxx_messageInfo_X3DHHeader.DiscardUnknown(m)
|
||||
}
|
||||
|
||||
var xxx_messageInfo_X3DHHeader proto.InternalMessageInfo
|
||||
|
||||
func (m *X3DHHeader) GetKey() []byte {
|
||||
if m != nil {
|
||||
return m.Key
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *X3DHHeader) GetId() []byte {
|
||||
if m != nil {
|
||||
return m.Id
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Direct message value
|
||||
type DirectMessageProtocol struct {
|
||||
X3DHHeader *X3DHHeader `protobuf:"bytes,1,opt,name=X3DH_header,json=X3DHHeader,proto3" json:"X3DH_header,omitempty"`
|
||||
DRHeader *DRHeader `protobuf:"bytes,2,opt,name=DR_header,json=DRHeader,proto3" json:"DR_header,omitempty"`
|
||||
DHHeader *DHHeader `protobuf:"bytes,101,opt,name=DH_header,json=DHHeader,proto3" json:"DH_header,omitempty"`
|
||||
// Encrypted payload
|
||||
Payload []byte `protobuf:"bytes,3,opt,name=payload,proto3" json:"payload,omitempty"`
|
||||
XXX_NoUnkeyedLiteral struct{} `json:"-"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
XXX_sizecache int32 `json:"-"`
|
||||
}
|
||||
|
||||
func (m *DirectMessageProtocol) Reset() { *m = DirectMessageProtocol{} }
|
||||
func (m *DirectMessageProtocol) String() string { return proto.CompactTextString(m) }
|
||||
func (*DirectMessageProtocol) ProtoMessage() {}
|
||||
func (*DirectMessageProtocol) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_4e37b52004a72e16, []int{6}
|
||||
}
|
||||
|
||||
func (m *DirectMessageProtocol) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_DirectMessageProtocol.Unmarshal(m, b)
|
||||
}
|
||||
func (m *DirectMessageProtocol) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
||||
return xxx_messageInfo_DirectMessageProtocol.Marshal(b, m, deterministic)
|
||||
}
|
||||
func (m *DirectMessageProtocol) XXX_Merge(src proto.Message) {
|
||||
xxx_messageInfo_DirectMessageProtocol.Merge(m, src)
|
||||
}
|
||||
func (m *DirectMessageProtocol) XXX_Size() int {
|
||||
return xxx_messageInfo_DirectMessageProtocol.Size(m)
|
||||
}
|
||||
func (m *DirectMessageProtocol) XXX_DiscardUnknown() {
|
||||
xxx_messageInfo_DirectMessageProtocol.DiscardUnknown(m)
|
||||
}
|
||||
|
||||
var xxx_messageInfo_DirectMessageProtocol proto.InternalMessageInfo
|
||||
|
||||
func (m *DirectMessageProtocol) GetX3DHHeader() *X3DHHeader {
|
||||
if m != nil {
|
||||
return m.X3DHHeader
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *DirectMessageProtocol) GetDRHeader() *DRHeader {
|
||||
if m != nil {
|
||||
return m.DRHeader
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *DirectMessageProtocol) GetDHHeader() *DHHeader {
|
||||
if m != nil {
|
||||
return m.DHHeader
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *DirectMessageProtocol) GetPayload() []byte {
|
||||
if m != nil {
|
||||
return m.Payload
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Top-level protocol message
|
||||
type ProtocolMessage struct {
|
||||
// The device id of the sender
|
||||
InstallationId string `protobuf:"bytes,2,opt,name=installation_id,json=installationId,proto3" json:"installation_id,omitempty"`
|
||||
// List of bundles
|
||||
Bundles []*Bundle `protobuf:"bytes,3,rep,name=bundles,proto3" json:"bundles,omitempty"`
|
||||
// One to one message, encrypted, indexed by installation_id
|
||||
DirectMessage map[string]*DirectMessageProtocol `protobuf:"bytes,101,rep,name=direct_message,json=directMessage,proto3" json:"direct_message,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"`
|
||||
// Public chats, not encrypted
|
||||
PublicMessage []byte `protobuf:"bytes,102,opt,name=public_message,json=publicMessage,proto3" json:"public_message,omitempty"`
|
||||
XXX_NoUnkeyedLiteral struct{} `json:"-"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
XXX_sizecache int32 `json:"-"`
|
||||
}
|
||||
|
||||
func (m *ProtocolMessage) Reset() { *m = ProtocolMessage{} }
|
||||
func (m *ProtocolMessage) String() string { return proto.CompactTextString(m) }
|
||||
func (*ProtocolMessage) ProtoMessage() {}
|
||||
func (*ProtocolMessage) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_4e37b52004a72e16, []int{7}
|
||||
}
|
||||
|
||||
func (m *ProtocolMessage) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_ProtocolMessage.Unmarshal(m, b)
|
||||
}
|
||||
func (m *ProtocolMessage) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
||||
return xxx_messageInfo_ProtocolMessage.Marshal(b, m, deterministic)
|
||||
}
|
||||
func (m *ProtocolMessage) XXX_Merge(src proto.Message) {
|
||||
xxx_messageInfo_ProtocolMessage.Merge(m, src)
|
||||
}
|
||||
func (m *ProtocolMessage) XXX_Size() int {
|
||||
return xxx_messageInfo_ProtocolMessage.Size(m)
|
||||
}
|
||||
func (m *ProtocolMessage) XXX_DiscardUnknown() {
|
||||
xxx_messageInfo_ProtocolMessage.DiscardUnknown(m)
|
||||
}
|
||||
|
||||
var xxx_messageInfo_ProtocolMessage proto.InternalMessageInfo
|
||||
|
||||
func (m *ProtocolMessage) GetInstallationId() string {
|
||||
if m != nil {
|
||||
return m.InstallationId
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (m *ProtocolMessage) GetBundles() []*Bundle {
|
||||
if m != nil {
|
||||
return m.Bundles
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *ProtocolMessage) GetDirectMessage() map[string]*DirectMessageProtocol {
|
||||
if m != nil {
|
||||
return m.DirectMessage
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *ProtocolMessage) GetPublicMessage() []byte {
|
||||
if m != nil {
|
||||
return m.PublicMessage
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func init() {
|
||||
proto.RegisterType((*SignedPreKey)(nil), "encryption.SignedPreKey")
|
||||
proto.RegisterType((*Bundle)(nil), "encryption.Bundle")
|
||||
proto.RegisterMapType((map[string]*SignedPreKey)(nil), "encryption.Bundle.SignedPreKeysEntry")
|
||||
proto.RegisterType((*BundleContainer)(nil), "encryption.BundleContainer")
|
||||
proto.RegisterType((*DRHeader)(nil), "encryption.DRHeader")
|
||||
proto.RegisterType((*DHHeader)(nil), "encryption.DHHeader")
|
||||
proto.RegisterType((*X3DHHeader)(nil), "encryption.X3DHHeader")
|
||||
proto.RegisterType((*DirectMessageProtocol)(nil), "encryption.DirectMessageProtocol")
|
||||
proto.RegisterType((*ProtocolMessage)(nil), "encryption.ProtocolMessage")
|
||||
proto.RegisterMapType((map[string]*DirectMessageProtocol)(nil), "encryption.ProtocolMessage.DirectMessageEntry")
|
||||
}
|
||||
|
||||
func init() {
|
||||
proto.RegisterFile("protocol_message.proto", fileDescriptor_4e37b52004a72e16)
|
||||
}
|
||||
|
||||
var fileDescriptor_4e37b52004a72e16 = []byte{
|
||||
// 581 bytes of a gzipped FileDescriptorProto
|
||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x74, 0x54, 0xdd, 0x6a, 0xdb, 0x4c,
|
||||
0x10, 0x45, 0x52, 0xe2, 0x9f, 0xb1, 0xfc, 0xc3, 0x7e, 0x5f, 0x83, 0x30, 0xa1, 0xb8, 0xa2, 0xa1,
|
||||
0x6e, 0x29, 0x0a, 0xb5, 0x0b, 0x29, 0xbd, 0x4c, 0x5d, 0x70, 0x53, 0x02, 0x61, 0x4b, 0x4b, 0xc9,
|
||||
0x8d, 0x90, 0xa5, 0xad, 0xb3, 0x54, 0x5e, 0x09, 0xed, 0xda, 0x54, 0xcf, 0xd0, 0x47, 0xeb, 0x4d,
|
||||
0x1f, 0xa9, 0x68, 0xa5, 0xb5, 0xd6, 0x3f, 0xb9, 0xd3, 0x9e, 0x9d, 0x39, 0x33, 0xe7, 0xcc, 0x8e,
|
||||
0xe0, 0x2c, 0xcd, 0x12, 0x91, 0x84, 0x49, 0xec, 0xaf, 0x08, 0xe7, 0xc1, 0x92, 0x78, 0x12, 0x40,
|
||||
0x40, 0x58, 0x98, 0xe5, 0xa9, 0xa0, 0x09, 0x73, 0x73, 0xb0, 0xbf, 0xd0, 0x25, 0x23, 0xd1, 0x5d,
|
||||
0x46, 0x3e, 0x93, 0x1c, 0x3d, 0x87, 0x1e, 0x97, 0x67, 0x3f, 0xcd, 0x88, 0xff, 0x93, 0xe4, 0x8e,
|
||||
0x31, 0x32, 0xc6, 0x36, 0xb6, 0xb9, 0x1e, 0xe5, 0x40, 0x73, 0x43, 0x32, 0x4e, 0x13, 0xe6, 0x98,
|
||||
0x23, 0x63, 0xdc, 0xc5, 0xea, 0x88, 0x5e, 0xc2, 0x60, 0x5b, 0x55, 0x85, 0x58, 0x32, 0xa4, 0xaf,
|
||||
0xf0, 0x6f, 0x25, 0xec, 0xfe, 0x36, 0xa1, 0x71, 0xbd, 0x66, 0x51, 0x4c, 0xd0, 0x10, 0x5a, 0x34,
|
||||
0x22, 0x4c, 0x50, 0xa1, 0xea, 0x6d, 0xcf, 0xe8, 0x16, 0xfa, 0xbb, 0x1d, 0x71, 0xc7, 0x1c, 0x59,
|
||||
0xe3, 0xce, 0xe4, 0xc2, 0xab, 0x75, 0x78, 0x25, 0x91, 0xa7, 0x6b, 0xe1, 0x1f, 0x99, 0xc8, 0x72,
|
||||
0xdc, 0xd5, 0x3b, 0xe7, 0xe8, 0x1c, 0xda, 0x05, 0x10, 0x88, 0x75, 0x46, 0x9c, 0x13, 0x59, 0xab,
|
||||
0x06, 0x8a, 0x5b, 0x41, 0x57, 0x84, 0x8b, 0x60, 0x95, 0x3a, 0xa7, 0x23, 0x63, 0x6c, 0xe1, 0x1a,
|
||||
0x18, 0xde, 0x03, 0x3a, 0x2c, 0x80, 0x06, 0x60, 0x29, 0x9f, 0xda, 0xb8, 0xf8, 0x44, 0x1e, 0x9c,
|
||||
0x6e, 0x82, 0x78, 0x4d, 0xa4, 0x39, 0x9d, 0x89, 0xa3, 0x37, 0xaa, 0x13, 0xe0, 0x32, 0xec, 0xbd,
|
||||
0xf9, 0xce, 0x70, 0x7f, 0x41, 0xbf, 0xd4, 0xf0, 0x21, 0x61, 0x22, 0xa0, 0x8c, 0x64, 0xe8, 0x15,
|
||||
0x34, 0x16, 0x12, 0x92, 0xdc, 0x9d, 0x09, 0x3a, 0x14, 0x8c, 0xab, 0x08, 0x34, 0x2d, 0xa6, 0x4d,
|
||||
0x37, 0x81, 0x20, 0xfe, 0xde, 0xfc, 0x4c, 0xa9, 0xf1, 0xbf, 0xea, 0x56, 0x2f, 0x7f, 0x73, 0xd2,
|
||||
0xb2, 0x06, 0x27, 0xee, 0x0d, 0xb4, 0x66, 0x78, 0x4e, 0x82, 0x88, 0x64, 0xba, 0x16, 0xbb, 0xd4,
|
||||
0x62, 0x83, 0xa1, 0x86, 0x6c, 0x30, 0xd4, 0x03, 0x33, 0x55, 0x03, 0x35, 0x53, 0x79, 0xa6, 0x51,
|
||||
0x65, 0xa3, 0x49, 0x23, 0xf7, 0x1c, 0x5a, 0xb3, 0xf9, 0x63, 0x5c, 0xee, 0x5b, 0x80, 0xef, 0xd3,
|
||||
0xc7, 0xef, 0xf7, 0xd9, 0xaa, 0xfe, 0xfe, 0x1a, 0xf0, 0x64, 0x46, 0x33, 0x12, 0x8a, 0xdb, 0xf2,
|
||||
0x19, 0xdf, 0x55, 0x0f, 0x09, 0x5d, 0x41, 0xa7, 0xe0, 0xf3, 0x1f, 0x24, 0x61, 0xe5, 0xd2, 0x99,
|
||||
0xee, 0x52, 0x5d, 0x0e, 0xeb, 0xa5, 0xdf, 0x40, 0x7b, 0x86, 0x55, 0x5a, 0x39, 0xa4, 0xff, 0xf5,
|
||||
0x34, 0xe5, 0x07, 0xae, 0x9d, 0x29, 0x52, 0xb6, 0x95, 0xc8, 0x91, 0x94, 0xf9, 0x36, 0x45, 0x55,
|
||||
0x71, 0xa0, 0x99, 0x06, 0x79, 0x9c, 0x04, 0x91, 0x74, 0xcc, 0xc6, 0xea, 0xe8, 0xfe, 0x31, 0xa1,
|
||||
0xaf, 0x54, 0x54, 0xa2, 0xd0, 0x0b, 0xe8, 0x53, 0xc6, 0x45, 0x10, 0xc7, 0x41, 0x41, 0xe8, 0xd3,
|
||||
0x48, 0x76, 0xd6, 0xc6, 0x3d, 0x1d, 0xfe, 0x14, 0xa1, 0xd7, 0xd0, 0x2c, 0x87, 0xce, 0x1d, 0x4b,
|
||||
0x2e, 0xc2, 0xb1, 0x77, 0xa1, 0x42, 0xd0, 0x57, 0xe8, 0x45, 0xd2, 0x3c, 0xf5, 0x13, 0x70, 0x88,
|
||||
0x4c, 0xf2, 0xf4, 0xa4, 0xbd, 0x5e, 0xbc, 0x1d, 0xbb, 0xab, 0x35, 0x8a, 0x74, 0x0c, 0x5d, 0x40,
|
||||
0x2f, 0x5d, 0x2f, 0x62, 0x1a, 0x6e, 0x69, 0x7f, 0x48, 0x89, 0xdd, 0x12, 0xad, 0xc2, 0x86, 0x21,
|
||||
0xa0, 0x43, 0xae, 0x23, 0x1b, 0x73, 0xb5, 0xbb, 0x31, 0xcf, 0x76, 0x9c, 0x3d, 0x36, 0x7b, 0x6d,
|
||||
0x75, 0xae, 0x47, 0xf7, 0x4f, 0x97, 0x54, 0x3c, 0xac, 0x17, 0x5e, 0x98, 0xac, 0x2e, 0xd5, 0x6f,
|
||||
0xe6, 0xb2, 0xa6, 0x58, 0x34, 0x24, 0x38, 0xfd, 0x17, 0x00, 0x00, 0xff, 0xff, 0xe8, 0xd9, 0xaa,
|
||||
0x89, 0x12, 0x05, 0x00, 0x00,
|
||||
}
|
|
@ -16,6 +16,8 @@
|
|||
// 1559627659_add_contact_code.up.sql (198B)
|
||||
// 1561368210_add_installation_metadata.down.sql (35B)
|
||||
// 1561368210_add_installation_metadata.up.sql (267B)
|
||||
// 1632236298_add_communities.down.sql (151B)
|
||||
// 1632236298_add_communities.up.sql (584B)
|
||||
// 1636536507_add_index_bundles.up.sql (347B)
|
||||
// doc.go (377B)
|
||||
|
||||
|
@ -101,7 +103,7 @@ func _1536754952_initial_schemaDownSql() (*asset, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "1536754952_initial_schema.down.sql", size: 83, mode: os.FileMode(0644), modTime: time.Unix(1633220904, 0)}
|
||||
info := bindataFileInfo{name: "1536754952_initial_schema.down.sql", size: 83, mode: os.FileMode(0644), modTime: time.Unix(1586880790, 0)}
|
||||
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x44, 0xcf, 0x76, 0x71, 0x1f, 0x5e, 0x9a, 0x43, 0xd8, 0xcd, 0xb8, 0xc3, 0x70, 0xc3, 0x7f, 0xfc, 0x90, 0xb4, 0x25, 0x1e, 0xf4, 0x66, 0x20, 0xb8, 0x33, 0x7e, 0xb0, 0x76, 0x1f, 0xc, 0xc0, 0x75}}
|
||||
return a, nil
|
||||
}
|
||||
|
@ -121,7 +123,7 @@ func _1536754952_initial_schemaUpSql() (*asset, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "1536754952_initial_schema.up.sql", size: 962, mode: os.FileMode(0644), modTime: time.Unix(1633220904, 0)}
|
||||
info := bindataFileInfo{name: "1536754952_initial_schema.up.sql", size: 962, mode: os.FileMode(0644), modTime: time.Unix(1586880790, 0)}
|
||||
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xea, 0x90, 0x5a, 0x59, 0x3e, 0x3, 0xe2, 0x3c, 0x81, 0x42, 0xcd, 0x4c, 0x9a, 0xe8, 0xda, 0x93, 0x2b, 0x70, 0xa4, 0xd5, 0x29, 0x3e, 0xd5, 0xc9, 0x27, 0xb6, 0xb7, 0x65, 0xff, 0x0, 0xcb, 0xde}}
|
||||
return a, nil
|
||||
}
|
||||
|
@ -141,7 +143,7 @@ func _1539249977_update_ratchet_infoDownSql() (*asset, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "1539249977_update_ratchet_info.down.sql", size: 311, mode: os.FileMode(0644), modTime: time.Unix(1633220904, 0)}
|
||||
info := bindataFileInfo{name: "1539249977_update_ratchet_info.down.sql", size: 311, mode: os.FileMode(0644), modTime: time.Unix(1586880790, 0)}
|
||||
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x1, 0xa4, 0xeb, 0xa0, 0xe6, 0xa0, 0xd4, 0x48, 0xbb, 0xad, 0x6f, 0x7d, 0x67, 0x8c, 0xbd, 0x25, 0xde, 0x1f, 0x73, 0x9a, 0xbb, 0xa8, 0xc9, 0x30, 0xb7, 0xa9, 0x7c, 0xaf, 0xb5, 0x1, 0x61, 0xdd}}
|
||||
return a, nil
|
||||
}
|
||||
|
@ -161,7 +163,7 @@ func _1539249977_update_ratchet_infoUpSql() (*asset, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "1539249977_update_ratchet_info.up.sql", size: 368, mode: os.FileMode(0644), modTime: time.Unix(1633220904, 0)}
|
||||
info := bindataFileInfo{name: "1539249977_update_ratchet_info.up.sql", size: 368, mode: os.FileMode(0644), modTime: time.Unix(1586880790, 0)}
|
||||
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xc, 0x8e, 0xbf, 0x6f, 0xa, 0xc0, 0xe1, 0x3c, 0x42, 0x28, 0x88, 0x1d, 0xdb, 0xba, 0x1c, 0x83, 0xec, 0xba, 0xd3, 0x5f, 0x5c, 0x77, 0x5e, 0xa7, 0x46, 0x36, 0xec, 0x69, 0xa, 0x4b, 0x17, 0x79}}
|
||||
return a, nil
|
||||
}
|
||||
|
@ -181,7 +183,7 @@ func _1540715431_add_versionDownSql() (*asset, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "1540715431_add_version.down.sql", size: 127, mode: os.FileMode(0644), modTime: time.Unix(1633220904, 0)}
|
||||
info := bindataFileInfo{name: "1540715431_add_version.down.sql", size: 127, mode: os.FileMode(0644), modTime: time.Unix(1586880790, 0)}
|
||||
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xf5, 0x9, 0x4, 0xe3, 0x76, 0x2e, 0xb8, 0x9, 0x23, 0xf0, 0x70, 0x93, 0xc4, 0x50, 0xe, 0x9d, 0x84, 0x22, 0x8c, 0x94, 0xd3, 0x24, 0x9, 0x9a, 0xc1, 0xa1, 0x48, 0x45, 0xfd, 0x40, 0x6e, 0xe6}}
|
||||
return a, nil
|
||||
}
|
||||
|
@ -201,7 +203,7 @@ func _1540715431_add_versionUpSql() (*asset, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "1540715431_add_version.up.sql", size: 265, mode: os.FileMode(0644), modTime: time.Unix(1633220904, 0)}
|
||||
info := bindataFileInfo{name: "1540715431_add_version.up.sql", size: 265, mode: os.FileMode(0644), modTime: time.Unix(1586880790, 0)}
|
||||
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xc7, 0x4c, 0x36, 0x96, 0xdf, 0x16, 0x10, 0xa6, 0x27, 0x1a, 0x79, 0x8b, 0x42, 0x83, 0x23, 0xc, 0x7e, 0xb6, 0x3d, 0x2, 0xda, 0xa4, 0xb4, 0xd, 0x27, 0x55, 0xba, 0xdc, 0xb2, 0x88, 0x8f, 0xa6}}
|
||||
return a, nil
|
||||
}
|
||||
|
@ -221,7 +223,7 @@ func _1541164797_add_installationsDownSql() (*asset, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "1541164797_add_installations.down.sql", size: 26, mode: os.FileMode(0644), modTime: time.Unix(1633220904, 0)}
|
||||
info := bindataFileInfo{name: "1541164797_add_installations.down.sql", size: 26, mode: os.FileMode(0644), modTime: time.Unix(1586880790, 0)}
|
||||
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xf5, 0xfd, 0xe6, 0xd8, 0xca, 0x3b, 0x38, 0x18, 0xee, 0x0, 0x5f, 0x36, 0x9e, 0x1e, 0xd, 0x19, 0x3e, 0xb4, 0x73, 0x53, 0xe9, 0xa5, 0xac, 0xdd, 0xa1, 0x2f, 0xc7, 0x6c, 0xa8, 0xd9, 0xa, 0x88}}
|
||||
return a, nil
|
||||
}
|
||||
|
@ -241,7 +243,7 @@ func _1541164797_add_installationsUpSql() (*asset, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "1541164797_add_installations.up.sql", size: 216, mode: os.FileMode(0644), modTime: time.Unix(1633220904, 0)}
|
||||
info := bindataFileInfo{name: "1541164797_add_installations.up.sql", size: 216, mode: os.FileMode(0644), modTime: time.Unix(1586880790, 0)}
|
||||
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x2d, 0x18, 0x26, 0xb8, 0x88, 0x47, 0xdb, 0x83, 0xcc, 0xb6, 0x9d, 0x1c, 0x1, 0xae, 0x2f, 0xde, 0x97, 0x82, 0x3, 0x30, 0xa8, 0x63, 0xa1, 0x78, 0x4b, 0xa5, 0x9, 0x8, 0x75, 0xa2, 0x57, 0x81}}
|
||||
return a, nil
|
||||
}
|
||||
|
@ -261,7 +263,7 @@ func _1558084410_add_secretDownSql() (*asset, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "1558084410_add_secret.down.sql", size: 56, mode: os.FileMode(0644), modTime: time.Unix(1633220904, 0)}
|
||||
info := bindataFileInfo{name: "1558084410_add_secret.down.sql", size: 56, mode: os.FileMode(0644), modTime: time.Unix(1586880790, 0)}
|
||||
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x49, 0xb, 0x65, 0xdf, 0x59, 0xbf, 0xe9, 0x5, 0x5b, 0x6f, 0xd5, 0x3a, 0xb7, 0x57, 0xe8, 0x78, 0x38, 0x73, 0x53, 0x57, 0xf7, 0x24, 0x4, 0xe4, 0xa2, 0x49, 0x22, 0xa2, 0xc6, 0xfd, 0x80, 0xa4}}
|
||||
return a, nil
|
||||
}
|
||||
|
@ -281,7 +283,7 @@ func _1558084410_add_secretUpSql() (*asset, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "1558084410_add_secret.up.sql", size: 301, mode: os.FileMode(0644), modTime: time.Unix(1633220904, 0)}
|
||||
info := bindataFileInfo{name: "1558084410_add_secret.up.sql", size: 301, mode: os.FileMode(0644), modTime: time.Unix(1586880790, 0)}
|
||||
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xf5, 0x32, 0x36, 0x8e, 0x47, 0xb0, 0x8f, 0xc1, 0xc6, 0xf7, 0xc6, 0x9f, 0x2d, 0x44, 0x75, 0x2b, 0x26, 0xec, 0x6, 0xa0, 0x7b, 0xa5, 0xbd, 0xc8, 0x76, 0x8a, 0x82, 0x68, 0x2, 0x42, 0xb5, 0xf4}}
|
||||
return a, nil
|
||||
}
|
||||
|
@ -301,7 +303,7 @@ func _1558588866_add_versionDownSql() (*asset, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "1558588866_add_version.down.sql", size: 47, mode: os.FileMode(0644), modTime: time.Unix(1633220904, 0)}
|
||||
info := bindataFileInfo{name: "1558588866_add_version.down.sql", size: 47, mode: os.FileMode(0644), modTime: time.Unix(1586880790, 0)}
|
||||
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xde, 0x52, 0x34, 0x3c, 0x46, 0x4a, 0xf0, 0x72, 0x47, 0x6f, 0x49, 0x5c, 0xc7, 0xf9, 0x32, 0xce, 0xc4, 0x3d, 0xfd, 0x61, 0xa1, 0x8b, 0x8f, 0xf2, 0x31, 0x34, 0xde, 0x15, 0x49, 0xa6, 0xde, 0xb9}}
|
||||
return a, nil
|
||||
}
|
||||
|
@ -321,7 +323,7 @@ func _1558588866_add_versionUpSql() (*asset, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "1558588866_add_version.up.sql", size: 57, mode: os.FileMode(0644), modTime: time.Unix(1633220904, 0)}
|
||||
info := bindataFileInfo{name: "1558588866_add_version.up.sql", size: 57, mode: os.FileMode(0644), modTime: time.Unix(1586880790, 0)}
|
||||
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x2a, 0xea, 0x64, 0x39, 0x61, 0x20, 0x83, 0x83, 0xb, 0x2e, 0x79, 0x64, 0xb, 0x53, 0xfa, 0xfe, 0xc6, 0xf7, 0x67, 0x42, 0xd3, 0x4f, 0xdc, 0x7e, 0x30, 0x32, 0xe8, 0x14, 0x41, 0xe9, 0xe7, 0x3b}}
|
||||
return a, nil
|
||||
}
|
||||
|
@ -341,7 +343,7 @@ func _1559627659_add_contact_codeDownSql() (*asset, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "1559627659_add_contact_code.down.sql", size: 32, mode: os.FileMode(0644), modTime: time.Unix(1633220904, 0)}
|
||||
info := bindataFileInfo{name: "1559627659_add_contact_code.down.sql", size: 32, mode: os.FileMode(0644), modTime: time.Unix(1586880790, 0)}
|
||||
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x5d, 0x64, 0x6d, 0xce, 0x24, 0x42, 0x20, 0x8d, 0x4f, 0x37, 0xaa, 0x9d, 0xc, 0x57, 0x98, 0xc1, 0xd1, 0x1a, 0x34, 0xcd, 0x9f, 0x8f, 0x34, 0x86, 0xb3, 0xd3, 0xdc, 0xf1, 0x7d, 0xe5, 0x1b, 0x6e}}
|
||||
return a, nil
|
||||
}
|
||||
|
@ -361,7 +363,7 @@ func _1559627659_add_contact_codeUpSql() (*asset, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "1559627659_add_contact_code.up.sql", size: 198, mode: os.FileMode(0644), modTime: time.Unix(1633220904, 0)}
|
||||
info := bindataFileInfo{name: "1559627659_add_contact_code.up.sql", size: 198, mode: os.FileMode(0644), modTime: time.Unix(1586880790, 0)}
|
||||
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x16, 0xf6, 0xc2, 0x62, 0x9c, 0xd2, 0xc9, 0x1e, 0xd8, 0xea, 0xaa, 0xea, 0x95, 0x8f, 0x89, 0x6a, 0x85, 0x5d, 0x9d, 0x99, 0x78, 0x3c, 0x90, 0x66, 0x99, 0x3e, 0x4b, 0x19, 0x62, 0xfb, 0x31, 0x4d}}
|
||||
return a, nil
|
||||
}
|
||||
|
@ -381,7 +383,7 @@ func _1561368210_add_installation_metadataDownSql() (*asset, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "1561368210_add_installation_metadata.down.sql", size: 35, mode: os.FileMode(0644), modTime: time.Unix(1633220904, 0)}
|
||||
info := bindataFileInfo{name: "1561368210_add_installation_metadata.down.sql", size: 35, mode: os.FileMode(0644), modTime: time.Unix(1586880790, 0)}
|
||||
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xa8, 0xde, 0x3f, 0xd2, 0x4a, 0x50, 0x98, 0x56, 0xe3, 0xc0, 0xcd, 0x9d, 0xb0, 0x34, 0x3b, 0xe5, 0x62, 0x18, 0xb5, 0x20, 0xc9, 0x3e, 0xdc, 0x6a, 0x40, 0x36, 0x66, 0xea, 0x51, 0x8c, 0x71, 0xf5}}
|
||||
return a, nil
|
||||
}
|
||||
|
@ -401,11 +403,51 @@ func _1561368210_add_installation_metadataUpSql() (*asset, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "1561368210_add_installation_metadata.up.sql", size: 267, mode: os.FileMode(0644), modTime: time.Unix(1633220904, 0)}
|
||||
info := bindataFileInfo{name: "1561368210_add_installation_metadata.up.sql", size: 267, mode: os.FileMode(0644), modTime: time.Unix(1586880790, 0)}
|
||||
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xb4, 0x71, 0x8f, 0x29, 0xb1, 0xaa, 0xd6, 0xd1, 0x8c, 0x17, 0xef, 0x6c, 0xd5, 0x80, 0xb8, 0x2c, 0xc3, 0xfe, 0xec, 0x24, 0x4d, 0xc8, 0x25, 0xd3, 0xb4, 0xcd, 0xa9, 0xac, 0x63, 0x61, 0xb2, 0x9c}}
|
||||
return a, nil
|
||||
}
|
||||
|
||||
var __1632236298_add_communitiesDownSql = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\x72\x09\xf2\x0f\x50\xf0\xf4\x73\x71\x8d\x50\xc8\x4c\xa9\x88\xcf\x48\x2c\xce\x88\x2f\x4a\x2c\x49\xce\x48\x2d\x89\x4f\xcd\x4b\xb6\xe6\x22\xa0\x20\x3e\x39\x31\x39\x23\xd5\x9a\x0b\xa2\x2e\xc4\xd1\xc9\xc7\x55\x01\x5d\x4d\x51\x65\x41\x49\x66\x7e\x1e\x4c\x29\x61\x95\xd6\x5c\x80\x00\x00\x00\xff\xff\xa4\x97\x4f\xad\x97\x00\x00\x00")
|
||||
|
||||
func _1632236298_add_communitiesDownSqlBytes() ([]byte, error) {
|
||||
return bindataRead(
|
||||
__1632236298_add_communitiesDownSql,
|
||||
"1632236298_add_communities.down.sql",
|
||||
)
|
||||
}
|
||||
|
||||
func _1632236298_add_communitiesDownSql() (*asset, error) {
|
||||
bytes, err := _1632236298_add_communitiesDownSqlBytes()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "1632236298_add_communities.down.sql", size: 151, mode: os.FileMode(0644), modTime: time.Unix(1637942211, 0)}
|
||||
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x26, 0xe5, 0x47, 0xd1, 0xe5, 0xec, 0x5b, 0x3e, 0xdc, 0x22, 0xf4, 0x27, 0xee, 0x70, 0xf3, 0x9, 0x4f, 0xd2, 0x9f, 0x92, 0xf, 0x5a, 0x18, 0x11, 0xb7, 0x40, 0xab, 0xf1, 0x98, 0x72, 0xd6, 0x60}}
|
||||
return a, nil
|
||||
}
|
||||
|
||||
var __1632236298_add_communitiesUpSql = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\x94\x90\xdf\x4a\xc3\x30\x14\xc6\xef\xf3\x14\xe7\x72\x83\xbe\x81\x57\xed\x3c\x1b\xc1\x7a\xa2\x31\x05\x77\x15\x4a\x16\x4c\x10\xd3\xd9\x46\xb0\x6f\x2f\xc1\x0c\x71\x71\xd2\xdd\x7e\x9c\xf3\xfd\xf9\x6d\x24\xd6\x0a\x41\xd5\x4d\x8b\xe0\xfa\xc9\xe9\xb1\x8f\xc6\xd9\xa8\x6d\x30\xe3\x7c\x8c\x7e\x08\xb0\x62\x00\x2f\xe3\xf0\x71\xd4\xfe\x00\x4d\x2b\x1a\x20\xa1\x80\xba\xb6\xad\x18\xc0\xab\x9d\x93\xce\x49\x9d\xcb\xe5\xed\x83\xe4\xf7\xb5\xdc\xc3\x1d\xee\x57\x27\xc7\x2a\x3b\xac\xd9\xfa\x86\xb1\x5c\xa8\x23\xfe\xd8\x21\x70\xba\xc5\x67\xf0\x87\x4f\x7d\xde\x0d\x04\x5d\xea\x5b\x3a\xff\xf8\xfe\x3b\x54\x9b\xde\x38\xbb\x6c\xae\x0f\xf1\x97\x3c\xd9\x77\x1d\x86\x44\x01\x77\x28\x93\x92\x42\xca\xf7\x69\x7e\x4b\x89\xfa\x84\x27\x69\x5b\x21\x91\xef\xe8\x6f\x2a\x20\x71\x8b\x12\x69\x83\x4f\xcb\x07\x5f\x85\x32\xcf\xbe\x0c\xf4\xfb\xa0\x48\xa9\xf2\xe8\x94\xf5\x15\x00\x00\xff\xff\x61\x30\xb4\xa0\x48\x02\x00\x00")
|
||||
|
||||
func _1632236298_add_communitiesUpSqlBytes() ([]byte, error) {
|
||||
return bindataRead(
|
||||
__1632236298_add_communitiesUpSql,
|
||||
"1632236298_add_communities.up.sql",
|
||||
)
|
||||
}
|
||||
|
||||
func _1632236298_add_communitiesUpSql() (*asset, error) {
|
||||
bytes, err := _1632236298_add_communitiesUpSqlBytes()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "1632236298_add_communities.up.sql", size: 584, mode: os.FileMode(0644), modTime: time.Unix(1637942211, 0)}
|
||||
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x8f, 0xe0, 0x1, 0x6e, 0x84, 0xc, 0x35, 0xe4, 0x5a, 0xf, 0xbe, 0xcb, 0xf7, 0xd2, 0xa8, 0x25, 0xf5, 0xdb, 0x7, 0xcb, 0xa3, 0xe6, 0xf4, 0xc4, 0x1b, 0xa5, 0xec, 0x32, 0x1e, 0x1e, 0x48, 0x60}}
|
||||
return a, nil
|
||||
}
|
||||
|
||||
var __1636536507_add_index_bundlesUpSql = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\x72\x0e\x72\x75\x0c\x71\x55\xf0\xf4\x73\x71\x8d\x50\x48\xcd\x4b\x2e\xaa\x2c\x28\xc9\xcc\xcf\x8b\x4f\x2a\xcd\x4b\xc9\x49\x2d\x8e\x4f\xad\x28\xc8\x2c\x4a\x4d\x89\xcf\x4c\x49\xcd\x2b\xc9\x2c\xa9\x8c\xcf\xcc\x2b\x2e\x49\xcc\xc9\x49\x04\xab\xca\x4c\x89\x2f\x4b\x2d\x2a\xce\xcc\xcf\x53\xc8\xcf\x53\x80\xea\x51\xd0\x80\x6a\xd2\x51\x80\xe9\xd2\x51\x40\xd3\xa6\xa3\x00\xd5\xa7\x69\xcd\x45\xa9\x13\x50\xac\x26\xdd\xc6\xa2\xc4\x92\xe4\x8c\xd4\x92\xf8\xcc\xbc\xb4\xfc\xf8\x32\x23\xbc\xd6\xa0\xa9\xc5\x63\x9d\xa6\x35\x17\x20\x00\x00\xff\xff\xd4\xde\x07\x5c\x5b\x01\x00\x00")
|
||||
|
||||
func _1636536507_add_index_bundlesUpSqlBytes() ([]byte, error) {
|
||||
|
@ -421,7 +463,7 @@ func _1636536507_add_index_bundlesUpSql() (*asset, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "1636536507_add_index_bundles.up.sql", size: 347, mode: os.FileMode(0644), modTime: time.Unix(1637535623, 0)}
|
||||
info := bindataFileInfo{name: "1636536507_add_index_bundles.up.sql", size: 347, mode: os.FileMode(0644), modTime: time.Unix(1637329330, 0)}
|
||||
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xf1, 0xb9, 0x3c, 0x16, 0xfc, 0xfb, 0xb2, 0xb4, 0x3b, 0xfe, 0xdc, 0xf5, 0x9c, 0x42, 0xa0, 0xa0, 0xd4, 0xd, 0x5b, 0x97, 0x10, 0x80, 0x95, 0xe, 0x13, 0xc1, 0x18, 0x8, 0xee, 0xf, 0x99, 0xee}}
|
||||
return a, nil
|
||||
}
|
||||
|
@ -441,7 +483,7 @@ func docGo() (*asset, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "doc.go", size: 377, mode: os.FileMode(0644), modTime: time.Unix(1633220904, 0)}
|
||||
info := bindataFileInfo{name: "doc.go", size: 377, mode: os.FileMode(0644), modTime: time.Unix(1586880790, 0)}
|
||||
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xef, 0xaf, 0xdf, 0xcf, 0x65, 0xae, 0x19, 0xfc, 0x9d, 0x29, 0xc1, 0x91, 0xaf, 0xb5, 0xd5, 0xb1, 0x56, 0xf3, 0xee, 0xa8, 0xba, 0x13, 0x65, 0xdb, 0xab, 0xcf, 0x4e, 0xac, 0x92, 0xe9, 0x60, 0xf1}}
|
||||
return a, nil
|
||||
}
|
||||
|
@ -569,6 +611,10 @@ var _bindata = map[string]func() (*asset, error){
|
|||
|
||||
"1561368210_add_installation_metadata.up.sql": _1561368210_add_installation_metadataUpSql,
|
||||
|
||||
"1632236298_add_communities.down.sql": _1632236298_add_communitiesDownSql,
|
||||
|
||||
"1632236298_add_communities.up.sql": _1632236298_add_communitiesUpSql,
|
||||
|
||||
"1636536507_add_index_bundles.up.sql": _1636536507_add_index_bundlesUpSql,
|
||||
|
||||
"doc.go": docGo,
|
||||
|
@ -631,6 +677,8 @@ var _bintree = &bintree{nil, map[string]*bintree{
|
|||
"1559627659_add_contact_code.up.sql": &bintree{_1559627659_add_contact_codeUpSql, map[string]*bintree{}},
|
||||
"1561368210_add_installation_metadata.down.sql": &bintree{_1561368210_add_installation_metadataDownSql, map[string]*bintree{}},
|
||||
"1561368210_add_installation_metadata.up.sql": &bintree{_1561368210_add_installation_metadataUpSql, map[string]*bintree{}},
|
||||
"1632236298_add_communities.down.sql": &bintree{_1632236298_add_communitiesDownSql, map[string]*bintree{}},
|
||||
"1632236298_add_communities.up.sql": &bintree{_1632236298_add_communitiesUpSql, map[string]*bintree{}},
|
||||
"1636536507_add_index_bundles.up.sql": &bintree{_1636536507_add_index_bundlesUpSql, map[string]*bintree{}},
|
||||
"doc.go": &bintree{docGo, map[string]*bintree{}},
|
||||
}}
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
DROP INDEX idx_hash_ratchet_enc;
|
||||
DROP INDEX idx_hash_ratchet_enc_cache;
|
||||
|
||||
DROP TABLE hash_ratchet_encryption_cache;
|
||||
DROP TABLE hash_ratchet_encryption;
|
|
@ -0,0 +1,20 @@
|
|||
CREATE TABLE hash_ratchet_encryption (
|
||||
group_id BLOB NOT NULL,
|
||||
key_id INT NOT NULL,
|
||||
key BLOB NOT NULL,
|
||||
PRIMARY KEY(group_id, key_id)
|
||||
);
|
||||
|
||||
CREATE UNIQUE INDEX idx_hash_ratchet_enc ON hash_ratchet_encryption(group_id, key_id);
|
||||
|
||||
CREATE TABLE hash_ratchet_encryption_cache (
|
||||
group_id BLOB NOT NULL,
|
||||
key_id int NOT NULL,
|
||||
seq_no INTEGER,
|
||||
hash BLOB NOT NULL,
|
||||
sym_enc_key BLOB,
|
||||
FOREIGN KEY(group_id, key_id) REFERENCES hash_ratchet_encryption(group_id, key_id)
|
||||
);
|
||||
|
||||
CREATE UNIQUE INDEX idx_hash_ratchet_enc_cache ON hash_ratchet_encryption_cache(group_id, key_id, seq_no);
|
||||
|
|
@ -727,3 +727,129 @@ func (s *sqliteSessionStorage) Load(id []byte) (*dr.State, error) {
|
|||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
type HRCache struct {
|
||||
GroupID string
|
||||
KeyID uint32
|
||||
Key []byte
|
||||
Hash []byte
|
||||
SeqNo uint32
|
||||
}
|
||||
|
||||
// GetHashRatchetKeyByID retrieves a hash ratchet key by group ID and seqNo.
|
||||
// If cache data with given seqNo (e.g. 0) is not found,
|
||||
// then the query will return the cache data with the latest seqNo
|
||||
func (s *sqlitePersistence) GetHashRatchetKeyByID(groupID []byte, keyID uint32, seqNo uint32) (*HRCache, error) {
|
||||
stmt, err := s.DB.Prepare(
|
||||
`WITH input AS (
|
||||
select ? AS group_id, ? AS key_id, ? as seq_no
|
||||
),
|
||||
cec AS (
|
||||
SELECT e.key, c.seq_no, c.hash FROM hash_ratchet_encryption e, input i
|
||||
LEFT JOIN hash_ratchet_encryption_cache c ON e.group_id=c.group_id AND e.key_id=c.key_id
|
||||
WHERE e.key_id=i.key_id AND e.group_id=i.group_id),
|
||||
seq_nos AS (
|
||||
select CASE
|
||||
WHEN EXISTS (SELECT c.seq_no from cec c, input i where c.seq_no=i.seq_no)
|
||||
THEN i.seq_no
|
||||
ELSE (select max(seq_no) from cec)
|
||||
END as seq_no from input i
|
||||
)
|
||||
SELECT c.key, c.seq_no, c.hash FROM cec c, input i, seq_nos s
|
||||
where case when not exists(select seq_no from seq_nos where seq_no is not null)
|
||||
then 1 else c.seq_no = s.seq_no end`)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer stmt.Close()
|
||||
|
||||
var key, hash []byte
|
||||
var seqNoPtr *uint32
|
||||
|
||||
err = stmt.QueryRow(groupID, keyID, seqNo).Scan(&key, &seqNoPtr, &hash)
|
||||
var seqNoResult uint32
|
||||
if seqNoPtr == nil {
|
||||
seqNoResult = 0
|
||||
} else {
|
||||
seqNoResult = *seqNoPtr
|
||||
}
|
||||
|
||||
res := &HRCache{
|
||||
KeyID: keyID,
|
||||
Key: key,
|
||||
Hash: hash,
|
||||
SeqNo: seqNoResult,
|
||||
}
|
||||
switch err {
|
||||
case sql.ErrNoRows:
|
||||
return nil, nil
|
||||
case nil:
|
||||
return res, nil
|
||||
default:
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
// GetCurrentKeyIDForGroup retrieves a key ID for given group ID
|
||||
// (with an assumption that key ids are shared in the group, and
|
||||
// at any given time there is a single key used)
|
||||
func (s *sqlitePersistence) GetCurrentKeyForGroup(groupID string) (uint32, error) {
|
||||
|
||||
stmt, err := s.DB.Prepare(`SELECT key_id
|
||||
FROM hash_ratchet_encryption
|
||||
WHERE group_id = ? order by key_id desc limit 1`)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
defer stmt.Close()
|
||||
|
||||
var keyID uint32
|
||||
err = stmt.QueryRow([]byte(groupID)).Scan(&keyID)
|
||||
|
||||
switch err {
|
||||
case sql.ErrNoRows:
|
||||
return 0, nil
|
||||
case nil:
|
||||
return keyID, nil
|
||||
default:
|
||||
return 0, err
|
||||
}
|
||||
}
|
||||
|
||||
// SaveHashRachetKeyHash saves a hash ratchet key cache data
|
||||
func (s *sqlitePersistence) SaveHashRatchetKeyHash(
|
||||
groupID []byte,
|
||||
keyID uint32,
|
||||
hash []byte,
|
||||
seqNo uint32,
|
||||
) error {
|
||||
|
||||
stmt, err := s.DB.Prepare(`INSERT INTO hash_ratchet_encryption_cache(group_id,key_id,hash,seq_no)
|
||||
VALUES(?, ?, ?, ?)`)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer stmt.Close()
|
||||
|
||||
_, err = stmt.Exec(groupID, keyID, hash, seqNo)
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
// SaveHashRatchetKey saves a hash ratchet key
|
||||
func (s *sqlitePersistence) SaveHashRatchetKey(
|
||||
groupID string,
|
||||
keyID uint32,
|
||||
key []byte,
|
||||
) error {
|
||||
stmt, err := s.DB.Prepare(`INSERT INTO hash_ratchet_encryption(group_id, key_id, key)
|
||||
VALUES(?,?,?)`)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer stmt.Close()
|
||||
|
||||
_, err = stmt.Exec([]byte(groupID), keyID, key)
|
||||
|
||||
return err
|
||||
}
|
||||
|
|
|
@ -179,8 +179,8 @@ func (p *Protocol) BuildPublicMessage(myIdentityKey *ecdsa.PrivateKey, payload [
|
|||
return &ProtocolMessageSpec{Message: message, Public: true}, nil
|
||||
}
|
||||
|
||||
// BuildDirectMessage returns a 1:1 chat message and optionally a negotiated topic given the user identity private key, the recipient's public key, and a payload
|
||||
func (p *Protocol) BuildDirectMessage(myIdentityKey *ecdsa.PrivateKey, publicKey *ecdsa.PublicKey, payload []byte) (*ProtocolMessageSpec, error) {
|
||||
// BuildEncryptedMessage returns a 1:1 chat message and optionally a negotiated topic given the user identity private key, the recipient's public key, and a payload
|
||||
func (p *Protocol) BuildEncryptedMessage(myIdentityKey *ecdsa.PrivateKey, publicKey *ecdsa.PublicKey, payload []byte) (*ProtocolMessageSpec, error) {
|
||||
|
||||
// Get recipients installations.
|
||||
activeInstallations, err := p.multidevice.GetActiveInstallations(publicKey)
|
||||
|
@ -189,15 +189,15 @@ func (p *Protocol) BuildDirectMessage(myIdentityKey *ecdsa.PrivateKey, publicKey
|
|||
}
|
||||
|
||||
// Encrypt payload
|
||||
directMessagesByInstalls, installations, err := p.encryptor.EncryptPayload(publicKey, myIdentityKey, activeInstallations, payload)
|
||||
encryptedMessagesByInstalls, installations, err := p.encryptor.EncryptPayload(publicKey, myIdentityKey, activeInstallations, payload)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Build message
|
||||
message := &ProtocolMessage{
|
||||
InstallationId: p.encryptor.config.InstallationID,
|
||||
DirectMessage: directMessagesByInstalls,
|
||||
InstallationId: p.encryptor.config.InstallationID,
|
||||
EncryptedMessage: encryptedMessagesByInstalls,
|
||||
}
|
||||
|
||||
err = p.addBundle(myIdentityKey, message)
|
||||
|
@ -208,7 +208,7 @@ func (p *Protocol) BuildDirectMessage(myIdentityKey *ecdsa.PrivateKey, publicKey
|
|||
// Check who we are sending the message to, and see if we have a shared secret
|
||||
// across devices
|
||||
var installationIDs []string
|
||||
for installationID := range message.GetDirectMessage() {
|
||||
for installationID := range message.GetEncryptedMessage() {
|
||||
if installationID != noInstallationID {
|
||||
installationIDs = append(installationIDs, installationID)
|
||||
}
|
||||
|
@ -228,6 +228,62 @@ func (p *Protocol) BuildDirectMessage(myIdentityKey *ecdsa.PrivateKey, publicKey
|
|||
return spec, nil
|
||||
}
|
||||
|
||||
// BuildHashRatchetKeyExchangeMessage builds a 1:1 message
|
||||
// containing newly generated hash ratchet key
|
||||
func (p *Protocol) BuildHashRatchetKeyExchangeMessage(myIdentityKey *ecdsa.PrivateKey, publicKey *ecdsa.PublicKey, groupID string, keyID uint32) (*ProtocolMessageSpec, error) {
|
||||
|
||||
logger := p.logger.With(zap.String("site", "BuildHashRatchetKeyExchangeMessage"))
|
||||
keyData, err := p.encryptor.persistence.GetHashRatchetKeyByID([]byte(groupID), keyID, 0)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
response, err := p.BuildEncryptedMessage(myIdentityKey, publicKey, keyData.Key)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Loop through installations and assign HRHeader
|
||||
// SeqNo=0 has a special meaning for HandleMessage
|
||||
// and signifies a message with hash ratchet key payload
|
||||
for _, v := range response.Message.EncryptedMessage {
|
||||
v.HRHeader = &HRHeader{
|
||||
KeyId: keyID,
|
||||
SeqNo: 0,
|
||||
GroupId: groupID,
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
logger.Info("Key saved", zap.Any("err", err))
|
||||
return response, err
|
||||
}
|
||||
|
||||
// BuildHashRatchetMessage returns a hash ratchet chat message
|
||||
func (p *Protocol) BuildHashRatchetMessage(groupID []byte, payload []byte) (*ProtocolMessageSpec, error) {
|
||||
|
||||
keyID, err := p.encryptor.persistence.GetCurrentKeyForGroup(string(groupID))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Encrypt payload
|
||||
encryptedMessagesByInstalls, err := p.encryptor.EncryptHashRatchetPayload(groupID, keyID, payload)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Build message
|
||||
message := &ProtocolMessage{
|
||||
InstallationId: p.encryptor.config.InstallationID,
|
||||
EncryptedMessage: encryptedMessagesByInstalls,
|
||||
}
|
||||
|
||||
spec := &ProtocolMessageSpec{
|
||||
Message: message,
|
||||
}
|
||||
return spec, nil
|
||||
}
|
||||
|
||||
// BuildDHMessage builds a message with DH encryption so that it can be decrypted by any other device.
|
||||
func (p *Protocol) BuildDHMessage(myIdentityKey *ecdsa.PrivateKey, destination *ecdsa.PublicKey, payload []byte) (*ProtocolMessageSpec, error) {
|
||||
// Encrypt payload
|
||||
|
@ -238,8 +294,8 @@ func (p *Protocol) BuildDHMessage(myIdentityKey *ecdsa.PrivateKey, destination *
|
|||
|
||||
// Build message
|
||||
message := &ProtocolMessage{
|
||||
InstallationId: p.encryptor.config.InstallationID,
|
||||
DirectMessage: encryptionResponse,
|
||||
InstallationId: p.encryptor.config.InstallationID,
|
||||
EncryptedMessage: encryptionResponse,
|
||||
}
|
||||
|
||||
err = p.addBundle(myIdentityKey, message)
|
||||
|
@ -405,18 +461,31 @@ func (p *Protocol) HandleMessage(
|
|||
}
|
||||
|
||||
// Decrypt message
|
||||
if directMessage := protocolMessage.GetDirectMessage(); directMessage != nil {
|
||||
if encryptedMessage := protocolMessage.GetEncryptedMessage(); encryptedMessage != nil {
|
||||
message, err := p.encryptor.DecryptPayload(
|
||||
myIdentityKey,
|
||||
theirPublicKey,
|
||||
protocolMessage.GetInstallationId(),
|
||||
directMessage,
|
||||
encryptedMessage,
|
||||
messageID,
|
||||
)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
dmProtocol := encryptedMessage[p.encryptor.config.InstallationID]
|
||||
if dmProtocol == nil {
|
||||
dmProtocol = encryptedMessage[noInstallationID]
|
||||
}
|
||||
hrHeader := dmProtocol.HRHeader
|
||||
if hrHeader != nil && hrHeader.SeqNo == 0 {
|
||||
// Payload contains hash ratchet key
|
||||
err = p.encryptor.persistence.SaveHashRatchetKey(hrHeader.GroupId, hrHeader.KeyId, message)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
bundles := protocolMessage.GetBundles()
|
||||
version := getProtocolVersion(bundles, protocolMessage.GetInstallationId())
|
||||
if version >= sharedSecretNegotiationVersion {
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -54,11 +54,22 @@ message X3DHHeader {
|
|||
bytes id = 4;
|
||||
}
|
||||
|
||||
// Hash Ratchet Header
|
||||
message HRHeader {
|
||||
// community key ID
|
||||
uint32 key_id = 1;
|
||||
// Community message number for this key_id
|
||||
uint32 seq_no = 2;
|
||||
// Community ID
|
||||
string group_id = 3;
|
||||
}
|
||||
|
||||
// Direct message value
|
||||
message DirectMessageProtocol {
|
||||
message EncryptedMessageProtocol {
|
||||
X3DHHeader X3DH_header = 1;
|
||||
DRHeader DR_header = 2;
|
||||
DRHeader DR_header = 2;
|
||||
DHHeader DH_header = 101;
|
||||
HRHeader HR_header = 102;
|
||||
// Encrypted payload
|
||||
bytes payload = 3;
|
||||
}
|
||||
|
@ -72,7 +83,8 @@ message ProtocolMessage {
|
|||
repeated Bundle bundles = 3;
|
||||
|
||||
// One to one message, encrypted, indexed by installation_id
|
||||
map<string,DirectMessageProtocol> direct_message = 101;
|
||||
// TODO map here is redundant in case of community messages
|
||||
map<string,EncryptedMessageProtocol> encrypted_message = 101;
|
||||
|
||||
// Public chats, not encrypted
|
||||
bytes public_message = 102;
|
||||
|
|
|
@ -78,7 +78,7 @@ func (s *ProtocolServiceTestSuite) TestBuildPublicMessage() {
|
|||
s.NotNilf(msg.Message.GetBundles(), "It adds a bundle to the message")
|
||||
}
|
||||
|
||||
func (s *ProtocolServiceTestSuite) TestBuildDirectMessage() {
|
||||
func (s *ProtocolServiceTestSuite) TestBuildEncryptedMessage() {
|
||||
bobKey, err := crypto.GenerateKey()
|
||||
s.NoError(err)
|
||||
aliceKey, err := crypto.GenerateKey()
|
||||
|
@ -86,7 +86,7 @@ func (s *ProtocolServiceTestSuite) TestBuildDirectMessage() {
|
|||
|
||||
payload := []byte("test")
|
||||
|
||||
msgSpec, err := s.alice.BuildDirectMessage(aliceKey, &bobKey.PublicKey, payload)
|
||||
msgSpec, err := s.alice.BuildEncryptedMessage(aliceKey, &bobKey.PublicKey, payload)
|
||||
s.NoError(err)
|
||||
s.NotNil(msgSpec, "It creates a message spec")
|
||||
|
||||
|
@ -95,7 +95,7 @@ func (s *ProtocolServiceTestSuite) TestBuildDirectMessage() {
|
|||
|
||||
s.NotNilf(msg.GetBundles(), "It adds a bundle to the message")
|
||||
|
||||
directMessage := msg.GetDirectMessage()
|
||||
directMessage := msg.GetEncryptedMessage()
|
||||
s.NotNilf(directMessage, "It sets the direct message")
|
||||
|
||||
encryptedPayload := directMessage["none"].GetPayload()
|
||||
|
@ -104,7 +104,7 @@ func (s *ProtocolServiceTestSuite) TestBuildDirectMessage() {
|
|||
s.NotEqualf(payload, encryptedPayload, "It encrypts the payload")
|
||||
}
|
||||
|
||||
func (s *ProtocolServiceTestSuite) TestBuildAndReadDirectMessage() {
|
||||
func (s *ProtocolServiceTestSuite) TestBuildAndReadEncryptedMessage() {
|
||||
bobKey, err := crypto.GenerateKey()
|
||||
s.Require().NoError(err)
|
||||
aliceKey, err := crypto.GenerateKey()
|
||||
|
@ -113,7 +113,7 @@ func (s *ProtocolServiceTestSuite) TestBuildAndReadDirectMessage() {
|
|||
payload := []byte("test")
|
||||
|
||||
// Message is sent with DH
|
||||
msgSpec, err := s.alice.BuildDirectMessage(aliceKey, &bobKey.PublicKey, payload)
|
||||
msgSpec, err := s.alice.BuildEncryptedMessage(aliceKey, &bobKey.PublicKey, payload)
|
||||
s.Require().NoError(err)
|
||||
s.Require().NotNil(msgSpec)
|
||||
|
||||
|
@ -140,7 +140,7 @@ func (s *ProtocolServiceTestSuite) TestSecretNegotiation() {
|
|||
_, err = s.bob.Start(bobKey)
|
||||
s.Require().NoError(err)
|
||||
|
||||
msgSpec, err := s.alice.BuildDirectMessage(aliceKey, &bobKey.PublicKey, payload)
|
||||
msgSpec, err := s.alice.BuildEncryptedMessage(aliceKey, &bobKey.PublicKey, payload)
|
||||
s.NoError(err)
|
||||
s.NotNil(msgSpec, "It creates a message spec")
|
||||
s.Require().NotNil(msgSpec.SharedSecret)
|
||||
|
|
Loading…
Reference in New Issue