Documentation
¶
Overview ¶
Package xochimilco provides an usable API for end-to-end encrypted communication based on the "Signal Protocol".
The "Signal Protocol" refers to the Extended Triple Diffie-Hellman (X3DH) key agreement protocol paired with the Double Ratchet algorithm. Both are implemented and exposed in this repository's subdirectories. For implementation details please refer there.
Example ¶
// In this example, Alice and Bob can exchange messages over some chat // protocol. Furthermore, they already know each other's public key. alicePub, alicePriv, _ := ed25519.GenerateKey(nil) bobPub, bobPriv, _ := ed25519.GenerateKey(nil) alice := Session{ IdentityKey: alicePriv, VerifyPeer: func(peer ed25519.PublicKey) (valid bool) { return peer.Equal(bobPub) }, } bob := Session{ IdentityKey: bobPriv, VerifyPeer: func(peer ed25519.PublicKey) (valid bool) { return peer.Equal(alicePub) }, } // Alice starts by offering Bob to upgrade the connection. offerMsg, err := alice.Offer() if err != nil { panic(err) } fmt.Printf("A->B\tOFFER\t%s\n", offerMsg) // Bob acknowledges Alice's offer. ackMsg, err := bob.Acknowledge(offerMsg) if err != nil { panic(err) } fmt.Printf("B-A\tACK\t%s\n", ackMsg) // Alice evaluates Bob's acknowledgement. This SHOULD be `isEstablished`. isEstablished, _, _, err := alice.Receive(ackMsg) if err != nil { panic(err) } else if !isEstablished { panic("invalid message") } // Now we have an established connection. // Let's exchange some very important messages. dataMsgAlice1, err := alice.Send([]byte("hello bob")) if err != nil { panic(err) } dataMsgAlice2, err := alice.Send([]byte("how are you?")) if err != nil { panic(err) } // Ops, the messages were reorder on the wired. fmt.Printf("A->B\tDATA\t%s", dataMsgAlice2) fmt.Printf("A->B\tDATA\t%s", dataMsgAlice1) _, _, plaintextAlice2, err := bob.Receive(dataMsgAlice2) if err != nil { panic(err) } fmt.Printf("B\tRECV\t%s", plaintextAlice2) _, _, plaintextAlice1, err := bob.Receive(dataMsgAlice2) if err != nil { panic(err) } fmt.Printf("B\tRECV\t%s", plaintextAlice1) // Bob also sends an answer. dataMsgBob, err := bob.Send([]byte("hej alice!")) if err != nil { panic(err) } fmt.Printf("B->A\tDATA\t%s", dataMsgBob) _, _, plaintextBob, err := alice.Receive(dataMsgBob) if err != nil { panic(err) } fmt.Printf("A\tRECV\t%s", plaintextBob) // Finally, Alice closes her Session... closeMsg, err := alice.Close() if err != nil { panic(err) } fmt.Printf("A->B\tCLOSE\t%s", closeMsg) // ...and tells Bob to do the same. _, isClosed, _, err := bob.Receive(closeMsg) if err != nil { panic(err) } else if !isClosed { panic("invalid message") } _, err = bob.Close() if err != nil { panic(err) }
Output:
Index ¶
- Constants
- type Session
- func (sess *Session) Acknowledge(offerMsg string) (ackMsg string, err error)
- func (sess *Session) Close() (closeMsg string, err error)
- func (sess *Session) Offer() (offerMsg string, err error)
- func (sess *Session) Receive(msg string) (isEstablished, isClosed bool, plaintext []byte, err error)
- func (sess *Session) Send(plaintext []byte) (dataMsg string, err error)
Examples ¶
Constants ¶
const ( // Prefix indicates the beginning of an encoded message. Prefix string = "!XO!" // Suffix indicates the end of an encoded message. Suffix string = "!OX!" )
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type Session ¶
type Session struct { // IdentityKey is this node's private Ed25519 identity key. // // This will only be used within the X3DH key agreement protocol. The other // party might want to verify this key's public part. IdentityKey ed25519.PrivateKey // VerifyPeer is a callback during session initialization to verify the // other party's public key. // // To determine when a key is correct is out of Xochimilco's scope. The key // might be either exchanged over another secure channel or a trust on first // use (TOFU) principle might be used. VerifyPeer func(peer ed25519.PublicKey) (valid bool) // contains filtered or unexported fields }
Session between two parties to exchange encrypted messages.
Each party creates a new Session variable configured with their private long time identity key and a function callback to verify the other party's public identity key.
The active party must start by offering to "upgrade" the current channel (Offer). Afterwards, the other party must confirm this step (Acknowledge). Once the first party finally receives the acknowledgement (Receive), the connection is established.
Now both parties can create encrypted messages directed to the other (Send). Furthermore, the Session can be closed again (Close). Incoming messages can be inspected and the payload extracted, if present (Receive).
func (*Session) Acknowledge ¶
Acknowledge to establish an encrypted Session.
This method MUST be called by the passive party (Bob) with the active party's (Alice's) offer message. The created acknowledge message MUST be send back.
At this point, this passive part is able to send and receive messages.
func (*Session) Close ¶
Close this Session and tell the other party to do the same.
This resets the internal state. Thus, the same Session might be reused.
func (*Session) Offer ¶
Offer to establish an encrypted Session.
This method MUST be called initially by the active resp. opening party (Alice) once. The other party will hopefully Acknowledge this message.
func (*Session) Receive ¶
func (sess *Session) Receive(msg string) (isEstablished, isClosed bool, plaintext []byte, err error)
Receive an incoming message.
All messages except the passive party's initial offer message MUST be passed to this method. The multiple return fields indicate this message's kind.
If the active party receives its first (acknowledge) message, this Session will be established; isEstablished. If the other party has signaled to close the Session, isClosed is set. This Session MUST then also be closed down. In case of an incoming encrypted message, the plaintext field holds its decrypted plaintext value. Of course, there might also be an error.
Directories
¶
Path | Synopsis |
---|---|
Package doubleratchet implements a variant of the Double Ratchet Algorithm.
|
Package doubleratchet implements a variant of the Double Ratchet Algorithm. |
Package x3dh implements a variant of the Extended Triple Diffie-Hellman (X3DH) key agreement protocol.
|
Package x3dh implements a variant of the Extended Triple Diffie-Hellman (X3DH) key agreement protocol. |