Skip to content

Commit 14b42ae

Browse files
committed
Sealed sender
1 parent 34f18d0 commit 14b42ae

File tree

63 files changed

+4562
-583
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

63 files changed

+4562
-583
lines changed
Lines changed: 154 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,154 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Linq;
4+
using System.Text;
5+
using Google.Protobuf;
6+
using libsignal;
7+
using libsignal.ecc;
8+
using libsignal.state;
9+
using libsignal.util;
10+
using libsignalmetadata;
11+
using libsignalmetadatadotnet;
12+
using libsignalmetadatadotnet.certificate;
13+
using Microsoft.VisualStudio.TestTools.UnitTesting;
14+
15+
namespace libsignalmetadatadotnettests
16+
{
17+
[TestClass]
18+
public class SealedSessionCipherTest
19+
{
20+
[TestMethod]
21+
public void TestEncryptDecrypt()
22+
{
23+
TestInMemorySignalProtocolStore aliceStore = new TestInMemorySignalProtocolStore();
24+
TestInMemorySignalProtocolStore bobStore = new TestInMemorySignalProtocolStore();
25+
26+
InitializeSessions(aliceStore, bobStore);
27+
28+
ECKeyPair trustRoot = Curve.generateKeyPair();
29+
SenderCertificate senderCertificate = CreateCertificateFor(trustRoot, "+14151111111", 1, aliceStore.GetIdentityKeyPair().getPublicKey().getPublicKey(), 31337);
30+
SealedSessionCipher aliceCipher = new SealedSessionCipher(aliceStore, new SignalProtocolAddress("+14151111111", 1));
31+
32+
byte[] ciphertext = aliceCipher.Encrypt(new SignalProtocolAddress("+14152222222", 1),
33+
senderCertificate, Encoding.ASCII.GetBytes("smert za smert"));
34+
35+
36+
SealedSessionCipher bobCipher = new SealedSessionCipher(bobStore, new SignalProtocolAddress("+14152222222", 1));
37+
38+
(SignalProtocolAddress, byte[]) plaintext = bobCipher.Decrypt(new CertificateValidator(trustRoot.getPublicKey()), ciphertext, 31335);
39+
40+
CollectionAssert.AreEqual(plaintext.Item2, Encoding.ASCII.GetBytes("smert za smert"));
41+
Assert.AreEqual(plaintext.Item1.Name, "+14151111111");
42+
Assert.AreEqual(plaintext.Item1.DeviceId, (uint)1);
43+
}
44+
45+
[TestMethod]
46+
public void TestEncryptDecryptUntrusted()
47+
{
48+
TestInMemorySignalProtocolStore aliceStore = new TestInMemorySignalProtocolStore();
49+
TestInMemorySignalProtocolStore bobStore = new TestInMemorySignalProtocolStore();
50+
51+
InitializeSessions(aliceStore, bobStore);
52+
53+
ECKeyPair trustRoot = Curve.generateKeyPair();
54+
ECKeyPair falseTrustRoot = Curve.generateKeyPair();
55+
SenderCertificate senderCertificate = CreateCertificateFor(falseTrustRoot, "+14151111111", 1, aliceStore.GetIdentityKeyPair().getPublicKey().getPublicKey(), 31337);
56+
SealedSessionCipher aliceCipher = new SealedSessionCipher(aliceStore, new SignalProtocolAddress("+14151111111", 1));
57+
58+
byte[] ciphertext = aliceCipher.Encrypt(new SignalProtocolAddress("+14152222222", 1),
59+
senderCertificate, Encoding.ASCII.GetBytes("и вот я"));
60+
61+
SealedSessionCipher bobCipher = new SealedSessionCipher(bobStore, new SignalProtocolAddress("+14152222222", 1));
62+
63+
try
64+
{
65+
bobCipher.Decrypt(new CertificateValidator(trustRoot.getPublicKey()), ciphertext, 31335);
66+
throw new Exception();
67+
}
68+
catch (InvalidMetadataMessageException)
69+
{
70+
// good
71+
}
72+
}
73+
74+
[TestMethod]
75+
public void TestEncryptFromWrongIdentity()
76+
{
77+
TestInMemorySignalProtocolStore aliceStore = new TestInMemorySignalProtocolStore();
78+
TestInMemorySignalProtocolStore bobStore = new TestInMemorySignalProtocolStore();
79+
80+
InitializeSessions(aliceStore, bobStore);
81+
82+
ECKeyPair trustRoot = Curve.generateKeyPair();
83+
ECKeyPair randomKeyPair = Curve.generateKeyPair();
84+
SenderCertificate senderCertificate = CreateCertificateFor(trustRoot, "+14151111111", 1, randomKeyPair.getPublicKey(), 31337);
85+
SealedSessionCipher aliceCipher = new SealedSessionCipher(aliceStore, new SignalProtocolAddress("+14151111111", 1));
86+
87+
byte[] ciphertext = aliceCipher.Encrypt(new SignalProtocolAddress("+14152222222", 1),
88+
senderCertificate, Encoding.ASCII.GetBytes("smert za smert"));
89+
90+
91+
SealedSessionCipher bobCipher = new SealedSessionCipher(bobStore, new SignalProtocolAddress("+14152222222", 1));
92+
93+
try
94+
{
95+
bobCipher.Decrypt(new CertificateValidator(trustRoot.getPublicKey()), ciphertext, 31335);
96+
}
97+
catch (InvalidMetadataMessageException)
98+
{
99+
// good
100+
}
101+
}
102+
103+
private SenderCertificate CreateCertificateFor(ECKeyPair trustRoot, String sender, int deviceId, ECPublicKey identityKey, long expires)
104+
{
105+
ECKeyPair serverKey = Curve.generateKeyPair();
106+
107+
byte[] serverCertificateBytes = new libsignalmetadata.protobuf.ServerCertificate.Types.Certificate()
108+
{
109+
Id = 1,
110+
Key = ByteString.CopyFrom(serverKey.getPublicKey().serialize())
111+
}.ToByteArray();
112+
113+
byte[] serverCertificateSignature = Curve.calculateSignature(trustRoot.getPrivateKey(), serverCertificateBytes);
114+
115+
ServerCertificate serverCertificate = new ServerCertificate(new libsignalmetadata.protobuf.ServerCertificate()
116+
{
117+
Certificate = ByteString.CopyFrom(serverCertificateBytes),
118+
Signature = ByteString.CopyFrom(serverCertificateSignature)
119+
}.ToByteArray());
120+
121+
byte[] senderCertificateBytes = new libsignalmetadata.protobuf.SenderCertificate.Types.Certificate
122+
{
123+
Sender = sender,
124+
SenderDevice = (uint)deviceId,
125+
IdentityKey = ByteString.CopyFrom(identityKey.serialize()),
126+
Expires = (ulong)expires,
127+
Signer = libsignalmetadata.protobuf.ServerCertificate.Parser.ParseFrom(serverCertificate.Serialized)
128+
}.ToByteArray();
129+
130+
byte[] senderCertificateSignature = Curve.calculateSignature(serverKey.getPrivateKey(), senderCertificateBytes);
131+
132+
return new SenderCertificate(new libsignalmetadata.protobuf.SenderCertificate()
133+
{
134+
Certificate = ByteString.CopyFrom(senderCertificateBytes),
135+
Signature = ByteString.CopyFrom(senderCertificateSignature)
136+
}.ToByteArray());
137+
}
138+
139+
private void InitializeSessions(TestInMemorySignalProtocolStore aliceStore, TestInMemorySignalProtocolStore bobStore)
140+
{
141+
ECKeyPair bobPreKey = Curve.generateKeyPair();
142+
IdentityKeyPair bobIdentityKey = bobStore.GetIdentityKeyPair();
143+
SignedPreKeyRecord bobSignedPreKey = KeyHelper.generateSignedPreKey(bobIdentityKey, 2);
144+
145+
PreKeyBundle bobBundle = new PreKeyBundle(1, 1, 1, bobPreKey.getPublicKey(), 2, bobSignedPreKey.getKeyPair().getPublicKey(), bobSignedPreKey.getSignature(), bobIdentityKey.getPublicKey());
146+
SessionBuilder aliceSessionBuilder = new SessionBuilder(aliceStore, new SignalProtocolAddress("+14152222222", 1));
147+
aliceSessionBuilder.process(bobBundle);
148+
149+
bobStore.StoreSignedPreKey(2, bobSignedPreKey);
150+
bobStore.StorePreKey(1, new PreKeyRecord(1, bobPreKey));
151+
152+
}
153+
}
154+
}
Lines changed: 141 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,141 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Text;
4+
using Google.Protobuf;
5+
using libsignal.ecc;
6+
using libsignalmetadatadotnet.certificate;
7+
using Microsoft.VisualStudio.TestTools.UnitTesting;
8+
9+
namespace libsignalmetadatadotnettests
10+
{
11+
[TestClass]
12+
public class SenderCertificateTest
13+
{
14+
private readonly ECKeyPair TrustRoot = Curve.generateKeyPair();
15+
16+
[TestMethod]
17+
public void TestSignature()
18+
{
19+
ECKeyPair serverKey = Curve.generateKeyPair();
20+
ECKeyPair key = Curve.generateKeyPair();
21+
22+
23+
byte[] certificateBytes = new libsignalmetadata.protobuf.SenderCertificate.Types.Certificate()
24+
{
25+
Sender = "+14152222222",
26+
SenderDevice = 1,
27+
Expires = 31337,
28+
IdentityKey = ByteString.CopyFrom(key.getPublicKey().serialize()),
29+
Signer = GetServerCertificate(serverKey)
30+
}.ToByteArray();
31+
32+
byte[] certificateSignature = Curve.calculateSignature(serverKey.getPrivateKey(), certificateBytes);
33+
34+
SenderCertificate senderCertificate = new SenderCertificate(new libsignalmetadata.protobuf.SenderCertificate()
35+
{
36+
Certificate = ByteString.CopyFrom(certificateBytes),
37+
Signature = ByteString.CopyFrom(certificateSignature)
38+
}.ToByteArray());
39+
40+
new CertificateValidator(TrustRoot.getPublicKey()).Validate(senderCertificate, 31336);
41+
}
42+
43+
[TestMethod]
44+
public void TestExpiredSignature()
45+
{
46+
ECKeyPair serverKey = Curve.generateKeyPair();
47+
ECKeyPair key = Curve.generateKeyPair();
48+
49+
byte[] certificateBytes = new libsignalmetadata.protobuf.SenderCertificate.Types.Certificate()
50+
{
51+
Sender = "+14152222222",
52+
SenderDevice = 1,
53+
Expires = 31337,
54+
IdentityKey = ByteString.CopyFrom(key.getPublicKey().serialize()),
55+
Signer = GetServerCertificate(serverKey)
56+
}.ToByteArray();
57+
58+
byte[] certificateSignature = Curve.calculateSignature(serverKey.getPrivateKey(), certificateBytes);
59+
60+
SenderCertificate senderCertificate = new SenderCertificate(new libsignalmetadata.protobuf.SenderCertificate()
61+
{
62+
Certificate = ByteString.CopyFrom(certificateBytes),
63+
Signature = ByteString.CopyFrom(certificateSignature)
64+
}.ToByteArray());
65+
66+
try
67+
{
68+
new CertificateValidator(TrustRoot.getPublicKey()).Validate(senderCertificate, 31338);
69+
throw new Exception();
70+
}
71+
catch (InvalidCertificateException)
72+
{
73+
// good
74+
}
75+
}
76+
77+
[TestMethod]
78+
public void TestBadSignature()
79+
{
80+
ECKeyPair serverKey = Curve.generateKeyPair();
81+
ECKeyPair key = Curve.generateKeyPair();
82+
83+
byte[] certificateBytes = new libsignalmetadata.protobuf.SenderCertificate.Types.Certificate()
84+
{
85+
Sender = "+14152222222",
86+
SenderDevice = 1,
87+
Expires = 31337,
88+
IdentityKey = ByteString.CopyFrom(key.getPublicKey().serialize()),
89+
Signer = GetServerCertificate(serverKey)
90+
}.ToByteArray();
91+
92+
byte[] certificateSignature = Curve.calculateSignature(serverKey.getPrivateKey(), certificateBytes);
93+
94+
for (int i = 0; i<certificateSignature.Length; i++)
95+
{
96+
for (int b = 0; b<8; b++)
97+
{
98+
byte[] badSignature = new byte[certificateSignature.Length];
99+
Array.Copy(certificateSignature, 0, badSignature, 0, certificateSignature.Length);
100+
101+
badSignature[i] = (byte)(badSignature[i] ^ 1 << b);
102+
103+
SenderCertificate senderCertificate = new SenderCertificate(new libsignalmetadata.protobuf.SenderCertificate()
104+
{
105+
Certificate = ByteString.CopyFrom(certificateBytes),
106+
Signature = ByteString.CopyFrom(badSignature)
107+
}.ToByteArray());
108+
109+
try
110+
{
111+
new CertificateValidator(TrustRoot.getPublicKey()).Validate(senderCertificate, 31336);
112+
throw new Exception();
113+
}
114+
catch (InvalidCertificateException)
115+
{
116+
// good
117+
}
118+
}
119+
}
120+
121+
}
122+
123+
124+
private libsignalmetadata.protobuf.ServerCertificate GetServerCertificate(ECKeyPair serverKey)
125+
{
126+
byte[] certificateBytes = new libsignalmetadata.protobuf.ServerCertificate.Types.Certificate()
127+
{
128+
Id = 1,
129+
Key = ByteString.CopyFrom(serverKey.getPublicKey().serialize())
130+
}.ToByteArray();
131+
132+
byte[] certificateSignature = Curve.calculateSignature(TrustRoot.getPrivateKey(), certificateBytes);
133+
134+
return new libsignalmetadata.protobuf.ServerCertificate()
135+
{
136+
Certificate = ByteString.CopyFrom(certificateBytes),
137+
Signature = ByteString.CopyFrom(certificateSignature)
138+
};
139+
}
140+
}
141+
}

0 commit comments

Comments
 (0)