That fuck shit the fascists are using
1package org.signal.util
2
3import okio.ByteString.Companion.toByteString
4import org.signal.core.util.Base64
5import org.signal.libsignal.internal.Native
6import org.signal.libsignal.internal.NativeHandleGuard
7import org.signal.libsignal.metadata.certificate.CertificateValidator
8import org.signal.libsignal.metadata.certificate.SenderCertificate
9import org.signal.libsignal.metadata.certificate.ServerCertificate
10import org.signal.libsignal.protocol.SessionBuilder
11import org.signal.libsignal.protocol.SignalProtocolAddress
12import org.signal.libsignal.protocol.ecc.Curve
13import org.signal.libsignal.protocol.ecc.ECKeyPair
14import org.signal.libsignal.protocol.ecc.ECPublicKey
15import org.signal.libsignal.protocol.groups.GroupSessionBuilder
16import org.signal.libsignal.protocol.message.SenderKeyDistributionMessage
17import org.signal.libsignal.protocol.state.PreKeyBundle
18import org.signal.libsignal.protocol.state.PreKeyRecord
19import org.signal.libsignal.protocol.state.SignedPreKeyRecord
20import org.whispersystems.signalservice.api.SignalServiceAccountDataStore
21import org.whispersystems.signalservice.api.SignalSessionLock
22import org.whispersystems.signalservice.api.crypto.ContentHint
23import org.whispersystems.signalservice.api.crypto.EnvelopeContent
24import org.whispersystems.signalservice.api.crypto.SignalGroupSessionBuilder
25import org.whispersystems.signalservice.api.crypto.SignalServiceCipher
26import org.whispersystems.signalservice.api.crypto.UnidentifiedAccess
27import org.whispersystems.signalservice.api.push.DistributionId
28import org.whispersystems.signalservice.api.push.ServiceId.ACI
29import org.whispersystems.signalservice.api.push.SignalServiceAddress
30import org.whispersystems.signalservice.internal.push.Content
31import org.whispersystems.signalservice.internal.push.DataMessage
32import org.whispersystems.signalservice.internal.push.Envelope
33import org.whispersystems.signalservice.internal.push.OutgoingPushMessage
34import org.whispersystems.signalservice.internal.util.Util
35import java.util.Optional
36import java.util.UUID
37import java.util.concurrent.locks.ReentrantLock
38import kotlin.random.Random
39
40/**
41 * An in-memory signal client that can encrypt and decrypt messages.
42 *
43 * Has a single prekey bundle that can be used to initialize a session with another client.
44 */
45class SignalClient {
46 companion object {
47 private val trustRoot: ECKeyPair = Curve.generateKeyPair()
48 }
49
50 private val lock = TestSessionLock()
51
52 private val aci: ACI = ACI.from(UUID.randomUUID())
53
54 private val store: SignalServiceAccountDataStore = InMemorySignalServiceAccountDataStore()
55
56 private var prekeyIndex = 0
57
58 private val unidentifiedAccessKey: ByteArray = Util.getSecretBytes(32)
59
60 private val senderCertificate: SenderCertificate = createCertificateFor(
61 trustRoot = trustRoot,
62 uuid = aci.rawUuid,
63 e164 = "+${Random.nextLong(1111111111L, 9999999999L)}",
64 deviceId = 1,
65 identityKey = store.identityKeyPair.publicKey.publicKey,
66 expires = Long.MAX_VALUE
67 )
68
69 private val cipher = SignalServiceCipher(SignalServiceAddress(aci), 1, store, lock, CertificateValidator(trustRoot.publicKey))
70
71 /**
72 * Sets up sessions using the [to] client's [preKeyBundles]. Note that you can only initialize a client up to 1,000 times because that's how many prekeys we have.
73 */
74 fun initializeSession(to: SignalClient) {
75 val address = SignalProtocolAddress(to.aci.toString(), 1)
76 SessionBuilder(store, address).process(to.createPreKeyBundle())
77 }
78
79 fun initializedGroupSession(distributionId: DistributionId): SenderKeyDistributionMessage {
80 val self = SignalProtocolAddress(aci.toString(), 1)
81 return SignalGroupSessionBuilder(lock, GroupSessionBuilder(store)).create(self, distributionId.asUuid())
82 }
83
84 fun encryptUnsealedSender(to: SignalClient): Envelope {
85 val sentTimestamp = System.currentTimeMillis()
86
87 val content = Content(
88 dataMessage = DataMessage(
89 body = "Test Message",
90 timestamp = sentTimestamp
91 )
92 )
93
94 val outgoingPushMessage: OutgoingPushMessage = cipher.encrypt(
95 SignalProtocolAddress(to.aci.toString(), 1),
96 Optional.empty(),
97 EnvelopeContent.encrypted(content, ContentHint.RESENDABLE, Optional.empty())
98 )
99
100 val encryptedContent: ByteArray = Base64.decode(outgoingPushMessage.content)
101
102 return Envelope(
103 sourceServiceId = aci.toString(),
104 sourceDevice = 1,
105 destinationServiceId = to.aci.toString(),
106 timestamp = sentTimestamp,
107 serverTimestamp = sentTimestamp,
108 serverGuid = UUID.randomUUID().toString(),
109 type = Envelope.Type.fromValue(outgoingPushMessage.type),
110 urgent = true,
111 content = encryptedContent.toByteString()
112 )
113 }
114
115 fun encryptSealedSender(to: SignalClient): Envelope {
116 val sentTimestamp = System.currentTimeMillis()
117
118 val content = Content(
119 dataMessage = DataMessage(
120 body = "Test Message",
121 timestamp = sentTimestamp
122 )
123 )
124
125 val outgoingPushMessage: OutgoingPushMessage = cipher.encrypt(
126 SignalProtocolAddress(to.aci.toString(), 1),
127 Optional.of(UnidentifiedAccess(to.unidentifiedAccessKey, senderCertificate.serialized, false)),
128 EnvelopeContent.encrypted(content, ContentHint.RESENDABLE, Optional.empty())
129 )
130
131 val encryptedContent: ByteArray = Base64.decode(outgoingPushMessage.content)
132
133 return Envelope(
134 sourceServiceId = aci.toString(),
135 sourceDevice = 1,
136 destinationServiceId = to.aci.toString(),
137 timestamp = sentTimestamp,
138 serverTimestamp = sentTimestamp,
139 serverGuid = UUID.randomUUID().toString(),
140 type = Envelope.Type.fromValue(outgoingPushMessage.type),
141 urgent = true,
142 content = encryptedContent.toByteString()
143 )
144 }
145
146 fun multiEncryptSealedSender(distributionId: DistributionId, others: List<SignalClient>, groupId: Optional<ByteArray>): ByteArray {
147 val sentTimestamp = System.currentTimeMillis()
148
149 val content = Content(
150 dataMessage = DataMessage(
151 body = "Test Message",
152 timestamp = sentTimestamp
153 )
154 )
155 val destinations = others.map { bob ->
156 SignalProtocolAddress(bob.aci.toString(), 1)
157 }
158
159 return cipher.encryptForGroup(distributionId, destinations, null, senderCertificate, content.encode(), ContentHint.DEFAULT, groupId)
160 }
161
162 fun decryptMessage(envelope: Envelope) {
163 cipher.decrypt(envelope, System.currentTimeMillis())
164 }
165
166 private fun createPreKeyBundle(): PreKeyBundle {
167 val prekeyId = prekeyIndex++
168 val preKeyRecord = PreKeyRecord(prekeyId, Curve.generateKeyPair())
169 val signedPreKeyPair = Curve.generateKeyPair()
170 val signedPreKeySignature = Curve.calculateSignature(store.identityKeyPair.privateKey, signedPreKeyPair.publicKey.serialize())
171
172 store.storePreKey(prekeyId, preKeyRecord)
173 store.storeSignedPreKey(prekeyId, SignedPreKeyRecord(prekeyId, System.currentTimeMillis(), signedPreKeyPair, signedPreKeySignature))
174
175 return PreKeyBundle(prekeyId, prekeyId, prekeyId, preKeyRecord.keyPair.publicKey, prekeyId, signedPreKeyPair.publicKey, signedPreKeySignature, store.identityKeyPair.publicKey)
176 }
177}
178
179private fun createCertificateFor(trustRoot: ECKeyPair, uuid: UUID, e164: String, deviceId: Int, identityKey: ECPublicKey, expires: Long): SenderCertificate {
180 val serverKey: ECKeyPair = Curve.generateKeyPair()
181 NativeHandleGuard(serverKey.publicKey).use { serverPublicGuard ->
182 NativeHandleGuard(trustRoot.privateKey).use { trustRootPrivateGuard ->
183 val serverCertificate = ServerCertificate(Native.ServerCertificate_New(1, serverPublicGuard.nativeHandle(), trustRootPrivateGuard.nativeHandle()))
184 NativeHandleGuard(identityKey).use { identityGuard ->
185 NativeHandleGuard(serverCertificate).use { serverCertificateGuard ->
186 NativeHandleGuard(serverKey.privateKey).use { serverPrivateGuard ->
187 return SenderCertificate(Native.SenderCertificate_New(uuid.toString(), e164, deviceId, identityGuard.nativeHandle(), expires, serverCertificateGuard.nativeHandle(), serverPrivateGuard.nativeHandle()))
188 }
189 }
190 }
191 }
192 }
193}
194
195private class TestSessionLock : SignalSessionLock {
196 val lock = ReentrantLock()
197
198 override fun acquire(): SignalSessionLock.Lock {
199 lock.lock()
200 return SignalSessionLock.Lock { lock.unlock() }
201 }
202}