All Projects → christophhagen → Libsignalprotocolswift

christophhagen / Libsignalprotocolswift

Licence: mit
A Swift implementation of the Signal Protocol

Programming Languages

swift
15916 projects

Projects that are alternatives of or similar to Libsignalprotocolswift

wormhole-william-mobile
End-to-end encrypted file transfer for Android. An Android Magic Wormhole client.
Stars: ✭ 57 (+26.67%)
Mutual labels:  end-to-end-encryption
Android
MEGA Android App
Stars: ✭ 651 (+1346.67%)
Mutual labels:  end-to-end-encryption
Client
Keybase Go Library, Client, Service, OS X, iOS, Android, Electron
Stars: ✭ 7,848 (+17340%)
Mutual labels:  end-to-end-encryption
etesync-notes
An EteSync backed note taking app
Stars: ✭ 64 (+42.22%)
Mutual labels:  end-to-end-encryption
Capillary
Capillary is a library to simplify the sending of end-to-end encrypted push messages from Java-based application servers to Android clients.
Stars: ✭ 445 (+888.89%)
Mutual labels:  end-to-end-encryption
Tfc
Tinfoil Chat - Onion-routed, endpoint secure messaging system
Stars: ✭ 781 (+1635.56%)
Mutual labels:  end-to-end-encryption
virgil-sdk-net
Virgil Core SDK allows developers to get up and running with Virgil Cards Service API quickly and add end-to-end security to their new or existing digital solutions to become HIPAA and GDPR compliant and more.
Stars: ✭ 16 (-64.44%)
Mutual labels:  end-to-end-encryption
Wire Webapp
👽 Wire for web
Stars: ✭ 982 (+2082.22%)
Mutual labels:  end-to-end-encryption
Darkwire.io
End-to-end encrypted instant web chat
Stars: ✭ 594 (+1220%)
Mutual labels:  end-to-end-encryption
Seven23 server
Fully manual budget app to track your expenses. Opensource, with privacy by design.
Stars: ✭ 20 (-55.56%)
Mutual labels:  end-to-end-encryption
Wormhole William
End-to-end encrypted file transfer. A magic wormhole CLI and API in Go (golang).
Stars: ✭ 256 (+468.89%)
Mutual labels:  end-to-end-encryption
Ios App
📱iOS private messenger, crypto wallet and light node to the Mixin Network
Stars: ✭ 406 (+802.22%)
Mutual labels:  end-to-end-encryption
Server
The Etebase server (so you can run your own)
Stars: ✭ 826 (+1735.56%)
Mutual labels:  end-to-end-encryption
virgil-sdk-cpp
Virgil Core SDK allows developers to get up and running with Virgil Cards Service API quickly and add end-to-end security to their new or existing digital solutions to become HIPAA and GDPR compliant and more.
Stars: ✭ 18 (-60%)
Mutual labels:  end-to-end-encryption
Megasync
Easy automated syncing between your computers and your MEGA Cloud Drive
Stars: ✭ 975 (+2066.67%)
Mutual labels:  end-to-end-encryption
piping-screen-share-web
🖥️ Screen Share via Piping Server with End-to-End Encryption
Stars: ✭ 49 (+8.89%)
Mutual labels:  end-to-end-encryption
Briefing
Secure direct video group chat
Stars: ✭ 710 (+1477.78%)
Mutual labels:  end-to-end-encryption
Seven23
Fully manual budget app to track personal expenses. 100% opensource, with privacy by design.
Stars: ✭ 36 (-20%)
Mutual labels:  end-to-end-encryption
Sdk
MEGA C++ SDK
Stars: ✭ 980 (+2077.78%)
Mutual labels:  end-to-end-encryption
Virgil Crypto Php
Virgil PHP Crypto Library is a high-level cryptographic library that allows you to perform all necessary operations for secure storing and transferring data and everything required to become HIPAA and GDPR compliant.
Stars: ✭ 22 (-51.11%)
Mutual labels:  end-to-end-encryption

LibSignalProtocolSwift

A Swift implementation of the Signal Protocol. The Signal Protocol can be used for secure, end-to-end encrypted messaging in synchronous and asynchronous environments. It has many desirable cryptographic features and can handle missing and out-of-order messages. The Signal protocol is used by the Signal Messenger as well as WhatsApp, Facebook, Skype and others. Additional information can be found here.

Purpose

This Swift library is intended for educational purposes only, in order to show the way the Signal Protocol works. It somewhat mimics the functionality and structure of the Signal Protocol C implementation.

Installation

You can install LibSignalProtocolSwift through Cocoapods, by adding the following to your Podfile:

pod 'LibSignalProtocolSwift', '~> 1.3'

After installation the Framework can be accessed by importing it:

import SignalProtocol

Prerequisites

Local storage

The Signal Protocol needs local storage for message keys, identities and other state information. You can provide this functionality by implementing the protocol KeyStore, which requires four delegates for the individual data stores:

  • IdentityKeyStore for storing and retrieving identity keys
  • PreKeyStore for storing and retrieving pre keys
  • SessionStore for storing and retrieving the sessions
  • SignedPreKeyStore for storing and retrieving signed pre keys

Optional

There is a feature for group updates, where only one administrator can send, and the others can only receive. If you want this functionality, then implement the GroupKeyStore protocol, with the additional delegate SenderKeyStore for storing and retrieving sender keys.

Sample implementation

You can have a look at the test implementation for inspiration.

Server for message delivery

The server that stores the messages for retrieval needs to store the following data for each SignalAddress:

  • Public Identity Key: The public part of the identity key of the device
  • Signed Pre Key: The current signed pre key
  • Pre Keys: A number of unsigned pre keys
  • Messages: The messages to deliver to that address, including the sender

Usage

The standard process to establish an encrypted session between two devices (two distinct SignalAddresses) is usually as follows:

  • Alice uploads her Identity and a SignedPreKey to the server, as well as a number of unsigned PreKeys.
  • Bob retrieves a PreKeyBundle from the server, consisting of Alice's Identity, the SignedPreKey, and one of the PreKeys (which is then deleted from the server).
  • Bob creates a session by processing the PreKeyBundle and encrypting a PreKeyMessage which he uploads to the server.
  • Alice receives Bob's PreKeyMessage from the server and decryptes the message.
  • The encrypted session is established for both Alice and Bob.

Creating identity and keys

Before any secure communication can happen, at least one user needs to upload all necessary ingredients for a PreKeyBundle to the server.

// Create the identity key ata install time
let identity = try SignalCrypto.generateIdentityKeyPair()

// Store the data in the key store

// Get the public key from the store
let publicKey: Data = try bobStore.getPublicIdentityKey()

// Create pre keys and save them in the store
let preKeys: [Data] = try bobStore.createPreKeys(count: 10)

// Create a signed pre key and save it in the store
let signedPreKey: Data = try bobStore.updateSignedPrekey()

// Upload publicKey, preKeys, and signedPreKey to the server

Creating a session from a PreKeyBundle

Let's assume that Alice (who has the SignalAddress aliceAddress) wants to establish a session with Bob (SignalAddress bobAddress)

// Download Bob's identity, current signedPreKey and one of the preKeys from the server

// Create PreKeyBundle
let preKeyBundle = try SessionPreKeyBundle(
    preKey: preKey,
    signedPreKey: signedPreKey,
    identityKey: identity)

// Create a new session by processing the PreKeyBundle
let session = SessionCipher(store: aliceStore, remoteAddress: bobAddress)
try session.process(preKeyBundle: preKeyBundle)

// The message to encrypt
let message = "Hello Bob, it's Alice".data(using: .utf8)!

// Here Alice can send messages to Bob
let encryptedMessage = try session.encrypt(message)

// Upload the message to the server

Creating a session from a received PreKeySignalMessage

Let's continue the above example and assume Bob receives the message from Alice. Bob can then establish the session:

// Get the message from the server

// Create the session
let session = SessionCipher(store: bobStore, remoteAddress: aliceAddress)

// Process the message
let decryptedMessage = try session.decrypt(preKeyMessage)

Using an already established session

Now Alice and Bob can both send and receive messages at will.

Sending

// Compose a message
let message =  "Hello there".data(using: .utf8)!

// Send message to Bob
let session = SessionCipher(store: aliceStore, remoteAddress: bobAddress)

// Encrypt
let encryptedMessage = try session.encrypt(message)

Receiving

// Get message from the server

// Receive message from Alice
let session = SessionCipher(store: bobStore, remoteAddress: aliceAddress)

// Decrypt
let decryptedMessage = try session.decrypt(message)

Verifying identity Keys

To prevent man-in-the-middle attacks it can be beneficial to compare the identity keys either by manually comparing the fingerprints or through scanning some sort of code (e.g. a QR-Code). The library provides a convenient way for this:

// Create the fingerprint
let aliceFP = try aliceStore.fingerprint(for: bobAddress, localAddress: aliceAddress)

// Display the string...
let display = fingerprint.displayText

// ... or transmit the scannable data to the other client...
let scanData = try fingerprint.scannable.protoData()

// ... or compare to a received fingerprint
fingerprint.matches(scannedFingerprint)

Miscellaneous

Client identifiers

The library is designed to allow different identifiers to distinguish between the different users. The test implementation uses the SignalAddress struct for this, which consists of a String (e.g. a phone number) and an Int, the deviceId. However it is possible to use different structs, classes, or types, as long as they conform to the Hashable, Equatable and CustomStringConvertible protocols. For example, simple strings can be used:

class MyCustomKeyStore: KeyStore {

    typealias Address = String

    ...
}

Now, SessionCipher can be instantiated, using MyCustomKeyStore :

let aliceStore = MyCustomKeyStore()
let session = SessionCipher(store: aliceStore, remoteAddress: "Bob")

Providing a custom crypto implementation

It is possible for any custom implementation of the SignalCryptoProvider protocol to serve as the cryptographic backbone of the protocol. This can be done by setting the static provider variable of the SignalCrypto class:

SignalCrypto.provider = MyCustomCryptoProvider()

The elliptic curve functions are handled by the same C code that is deployed in libsignal-protocol-c and which is packaged in the Curve25519 framework to make the functions available in Swift.

Documentation

The project is documented heavily because it helps other people understand the code. The documentation is created with jazzy, which creates awesome, apple-like docs.

The docs can be (re-)generated by running the following in the project directory:

jazzy --min-acl private -a 'Christoph Hagen' -u 'https://github.com/christophhagen' -g 'https://github.com/christophhagen/LibSignalProtocolSwift' -e 'Sources/ProtocolBuffers/*' -o 'Documentation'

Disclaimer

This code is NOT intended for production use! The code is neither reviewed for errors nor written by an expert. Please do not implement your own cryptographic software, if you don't know EXACTLY what you are doing.

Note that the project description data, including the texts, logos, images, and/or trademarks, for each open source project belongs to its rightful owner. If you wish to add or remove any projects, please contact us at [email protected].