That fuck shit the fascists are using
at master 202 lines 8.3 kB view raw
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}