<?xml version="1.0"?>
<?xml-stylesheet type="text/css" href="https://learn.equalit.ie/mw/skins/common/feed.css?303"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
		<id>https://learn.equalit.ie/mw/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Trevor</id>
		<title>learn.equalit.ie - User contributions [en]</title>
		<link rel="self" type="application/atom+xml" href="https://learn.equalit.ie/mw/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Trevor"/>
		<link rel="alternate" type="text/html" href="https://learn.equalit.ie/wiki/Special:Contributions/Trevor"/>
		<updated>2026-05-22T19:48:15Z</updated>
		<subtitle>User contributions</subtitle>
		<generator>MediaWiki 1.23.1</generator>

	<entry>
		<id>https://learn.equalit.ie/wiki/Np1sec/SenderKeys</id>
		<title>Np1sec/SenderKeys</title>
		<link rel="alternate" type="text/html" href="https://learn.equalit.ie/wiki/Np1sec/SenderKeys"/>
				<updated>2014-09-08T06:04:59Z</updated>
		
		<summary type="html">&lt;p&gt;Trevor: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Security Goals =&lt;br /&gt;
&lt;br /&gt;
== Transcript consistency ==&lt;br /&gt;
* Recipients are informed of the correct causal order of messages&lt;br /&gt;
* Excessively delayed messages are detected&lt;br /&gt;
&lt;br /&gt;
== Nonblocking join ==&lt;br /&gt;
* Join and leave are treated as messages, so transcript consistency applies (causal order, delays are detected).&lt;br /&gt;
* New users have to &amp;quot;confirm&amp;quot; to existing users to join.&lt;br /&gt;
* Existing users have to &amp;quot;confirm&amp;quot; to the new user shortly after the new user joins (e.g. 1 minute).&lt;br /&gt;
&lt;br /&gt;
= General concepts = &lt;br /&gt;
&lt;br /&gt;
== Room membership ==&lt;br /&gt;
Users can enter and leave the room, as signalled by presence messages from the server (USER_ENTERED, USER_LEFT).&lt;br /&gt;
&lt;br /&gt;
Users can join the room's conversation by sending a JOIN message.&lt;br /&gt;
&lt;br /&gt;
Users can only leave the conversation if the server says they left the room.&lt;br /&gt;
&lt;br /&gt;
== Sender keys and Signing keys ==&lt;br /&gt;
When a new user joins, she generates a new AES256 key (her &amp;quot;sender key&amp;quot;) and Ed25519 key (her &amp;quot;signing key&amp;quot;).  She then sends these keys to existing members, encrypted under the &amp;quot;pairwise keys&amp;quot; from pairwise key agreements.  This allows subsequent messages to be encrypted-and-signed once, instead of N times with pairwise keys.&lt;br /&gt;
&lt;br /&gt;
Every time a message is encrypted or decrypted with a sender key, the key is afterwards updated to provide forward secrecy:&lt;br /&gt;
&lt;br /&gt;
sender_key = HMAC-SHA256(prev_sender_key, &amp;quot;0&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
== Server order ==&lt;br /&gt;
All clients see the same message order from the server.  All messages are sent to all users.  Aside from the presence messages sent by the server, messages are sent by users.&lt;br /&gt;
&lt;br /&gt;
All messages in a room have a unique sequence number (0, 1, ...).  Sequence numbers are implicit, as the server may not be aware of them (e.g. XMPP MUC).&lt;br /&gt;
&lt;br /&gt;
A new user synchronizes his view of sequence numbers via the QUERY / MEMBER_LIST messages (see below).&lt;br /&gt;
&lt;br /&gt;
== Causal order ==&lt;br /&gt;
Some user-sent messages specify a &amp;quot;parent&amp;quot; sequence number which is the last message the user received before sending it.  Note:&lt;br /&gt;
* If Alice sends messages (A,B) in a row, A will not be B's parent unless Alice waits till A is received back from the server.&lt;br /&gt;
* The parent of a message is different from the &amp;quot;previous&amp;quot; message in the server's ordering, e.g. in a &amp;quot;simultaneous send&amp;quot; case two messages will have the same parent.&lt;br /&gt;
&lt;br /&gt;
Due to server ordering, the sender of message i must have seen all&lt;br /&gt;
messages from 0...i's parent.  Thus, every user-sent message i has a membership set, determined by the JOIN / USER_LEFT messages from 0...i's parent.&lt;br /&gt;
&lt;br /&gt;
== Transcript hashes ==&lt;br /&gt;
Encrypted messages include a &amp;quot;transcript hash&amp;quot; of their parent and all prior messages as &amp;quot;additional authenticated data&amp;quot;.  &lt;br /&gt;
&lt;br /&gt;
The hash also covers the sender_key for DATA messages (set to zeros for all other messages):&lt;br /&gt;
&lt;br /&gt;
H(parent) = SHA256(sender_key[parent] || msg[parent] || H(parent-1))&lt;br /&gt;
&lt;br /&gt;
== Timing ==&lt;br /&gt;
Timing rules can trigger errors based on some assumed constants:&lt;br /&gt;
&lt;br /&gt;
* MAX_RTT - this is the maximum time it should take for a sent message to arrive at all parties.  If you send a message and haven't received it back within MAX_RTT, something is wrong.&lt;br /&gt;
&lt;br /&gt;
* MAX_RTD - this is the maximum difference in time when a message arrives at all parties.  If you receive a message that's not a successor of a message (X) you received more than MAX_RTD + MAX_RTT time ago, something is wrong.  (This is because message X might have arrived at the other party more than MAX_RTD after you saw it, and the other party's message might have taken MAX_RTT to reach you.  But after MAX_RTD + MAX_RTT, there's no excuse for the other party not to have seen X).&lt;br /&gt;
&lt;br /&gt;
* MAX_CONFIRM - this is the maximum time an existing member may spend after receiving a new user's JOIN message before sending a CONFIRM message in response.  If the new user hasn't received CONFIRM messages from existing membership within 2*MAX_RTT + MAX_CONFIRM, something is wrong.&lt;br /&gt;
&lt;br /&gt;
= Messages = &lt;br /&gt;
&lt;br /&gt;
== Generic structures ==&lt;br /&gt;
&lt;br /&gt;
=== Certificate ===&lt;br /&gt;
* The user's Curve25519 identity public key&lt;br /&gt;
* The user's Curve25519 ephemeral public key&lt;br /&gt;
* An Ed25519 signature from the identity key over the ephemeral key&lt;br /&gt;
   (Ed25519 signatures can be produced from Curve25519 keys)&lt;br /&gt;
&lt;br /&gt;
== Server messages ==&lt;br /&gt;
&lt;br /&gt;
=== USER_ENTERED, USER_LEFT ===&lt;br /&gt;
* &amp;quot;Presence&amp;quot; messages sent in clear by the server to indicate a user has entered or left the room&lt;br /&gt;
&lt;br /&gt;
== User messages ==&lt;br /&gt;
&lt;br /&gt;
=== QUERY ===&lt;br /&gt;
* Contains a nonce&lt;br /&gt;
* Requests a MEMBER_LIST&lt;br /&gt;
&lt;br /&gt;
=== MEMBER_LIST ===&lt;br /&gt;
* Contains the sequence number and nonce of the QUERY it's responding to&lt;br /&gt;
* Contains the transcript hash for the QUERY&lt;br /&gt;
* Contains a certificate for each member as of the QUERY&lt;br /&gt;
&lt;br /&gt;
=== JOIN ===&lt;br /&gt;
* Contains a certificate for the new member&lt;br /&gt;
* Contains the sequence number of the MEMBER_LIST it's responding to&lt;br /&gt;
&lt;br /&gt;
=== CONFIRM ===&lt;br /&gt;
* Encrypts-and-confirms an AES256 &amp;quot;sender key&amp;quot; and Ed25519 &amp;quot;signing key&amp;quot; from one member to another&lt;br /&gt;
* Uses pairwise TripleDH between sender and recipient keys, i.e.&lt;br /&gt;
   HASH( DH(A_id, B_eph) || DH(A_eph, B_id) || DH(A_eph, B_eph) )&lt;br /&gt;
* Contains the sequence number for its parent&lt;br /&gt;
* The transcript hash and membership of its parent is included as &amp;quot;additional authenticated data&amp;quot;&lt;br /&gt;
&lt;br /&gt;
=== DATA === &lt;br /&gt;
* Encrypted under the sender's &amp;quot;sender key&amp;quot;&lt;br /&gt;
* Ed25519 signature from the sender's signing key&lt;br /&gt;
* Contains the sequence number for its parent&lt;br /&gt;
* The transcript hash and membership of its parent is included as &amp;quot;additional authenticated data&amp;quot;&lt;br /&gt;
&lt;br /&gt;
= Algorithms = &lt;br /&gt;
&lt;br /&gt;
== Blocking Join ==&lt;br /&gt;
On entering a room, a user sends a QUERY.  Someone will respond with a MEMBER_LIST.  If two users try to join simultaneously, the second QUERY will not be responded to until the first user has finished joining.&lt;br /&gt;
&lt;br /&gt;
On receiving a MEMBER_LIST, the new user learns the membership, transcript hash, and sequence number for the QUERY message.  To finish joining, the new user sends a JOIN, including a CONFIRM for each existing member.  Each member will respond to her JOIN message with a CONFIRM, containing a new sender key.&lt;br /&gt;
&lt;br /&gt;
Until the new user has finished joining, existing members continue exchanging DATA with their old sender keys.  Once the last confirmation has been received, existing users switch to their new sender keys.&lt;br /&gt;
&lt;br /&gt;
Once the new user has received all CONFIRM messages from the existing membership, she is successfully joined.  If other users sent a QUERY in the meantime, the next one will be responded to with a MEMBER_LIST.&lt;br /&gt;
&lt;br /&gt;
== Nonblocking Join ==&lt;br /&gt;
On entering a room, a user sends a QUERY.  Someone will respond with a MEMBER_LIST.  If multiple users try to join simultaneously, they will all be responded to immediately.&lt;br /&gt;
&lt;br /&gt;
On receiving a MEMBER_LIST, the new user learns the membership, transcript hash, and sequence number for the QUERY message.  To finish joining, the new user sends a JOIN, including a CONFIRM for each existing member.  Each member will respond to her JOIN message with a CONFIRM, containing their current sender key.&lt;br /&gt;
&lt;br /&gt;
The new user is part of the group once her JOIN message is received.  This means that DATA can be sent between group members who have not yet confirmed each other.&lt;br /&gt;
&lt;br /&gt;
[[Category: mpOTR]]&lt;/div&gt;</summary>
		<author><name>Trevor</name></author>	</entry>

	<entry>
		<id>https://learn.equalit.ie/wiki/Np1sec/SenderKeys</id>
		<title>Np1sec/SenderKeys</title>
		<link rel="alternate" type="text/html" href="https://learn.equalit.ie/wiki/Np1sec/SenderKeys"/>
				<updated>2014-09-08T06:03:05Z</updated>
		
		<summary type="html">&lt;p&gt;Trevor: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Security Goals =&lt;br /&gt;
&lt;br /&gt;
== Transcript consistency ==&lt;br /&gt;
* Recipients are informed of the correct causal order of messages&lt;br /&gt;
* Excessively delayed messages are detected&lt;br /&gt;
&lt;br /&gt;
== Nonblocking join ==&lt;br /&gt;
* Join and leave are treated as messages, so transcript consistency applies (causal order, delays are detected).&lt;br /&gt;
* New users have to &amp;quot;confirm&amp;quot; to existing users to join.&lt;br /&gt;
* Existing users have to &amp;quot;confirm&amp;quot; to the new user shortly after the new user joins (e.g. 1 minute).&lt;br /&gt;
&lt;br /&gt;
= General concepts = &lt;br /&gt;
&lt;br /&gt;
== Room membership ==&lt;br /&gt;
Users can enter and leave the room, as signalled by presence messages from the server (USER_ENTERED, USER_LEFT).&lt;br /&gt;
&lt;br /&gt;
Users can join the room's conversation by sending a JOIN message.&lt;br /&gt;
&lt;br /&gt;
Users can only leave the conversation if the server says they left the room.&lt;br /&gt;
&lt;br /&gt;
== Sender keys and Signing keys ==&lt;br /&gt;
When a new user joins, she generates a new AES256 key (her &amp;quot;sender key&amp;quot;) and Ed25519 key (her &amp;quot;signing key&amp;quot;).  She then sends these keys to existing members, encrypted under the &amp;quot;pairwise keys&amp;quot; from pairwise key agreements.  This allows subsequent messages to be encrypted-and-signed once, instead of N times with pairwise keys.&lt;br /&gt;
&lt;br /&gt;
Every time a message is encrypted or decrypted with a sender key, the key is updated to provide forward secrecy:&lt;br /&gt;
&lt;br /&gt;
sender_key = HMAC-SHA256(prev_sender_key, &amp;quot;0&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
== Server order ==&lt;br /&gt;
All clients see the same message order from the server.  All messages are sent to all users.  Aside from the presence messages sent by the server, messages are sent by users.&lt;br /&gt;
&lt;br /&gt;
All messages in a room have a unique sequence number (0, 1, ...).  Sequence numbers are implicit, as the server may not be aware of them (e.g. XMPP MUC).&lt;br /&gt;
&lt;br /&gt;
A new user synchronizes his view of sequence numbers via the QUERY / MEMBER_LIST messages (see below).&lt;br /&gt;
&lt;br /&gt;
== Causal order ==&lt;br /&gt;
Some user-sent messages specify a &amp;quot;parent&amp;quot; sequence number which is the last message the user received before sending it.  Note:&lt;br /&gt;
* If Alice sends messages (A,B) in a row, A will not be B's parent unless Alice waits till A is received back from the server.&lt;br /&gt;
* The parent of a message is different from the &amp;quot;previous&amp;quot; message in the server's ordering, e.g. in a &amp;quot;simultaneous send&amp;quot; case two messages will have the same parent.&lt;br /&gt;
&lt;br /&gt;
Due to server ordering, the sender of message i must have seen all&lt;br /&gt;
messages from 0...i's parent.  Thus, every user-sent message i has a membership set, determined by the JOIN / USER_LEFT messages from 0...i's parent.&lt;br /&gt;
&lt;br /&gt;
== Transcript hashes ==&lt;br /&gt;
Encrypted messages include a &amp;quot;transcript hash&amp;quot; of their parent and all prior messages as &amp;quot;additional authenticated data&amp;quot;.  &lt;br /&gt;
&lt;br /&gt;
The hash also covers the sender_key for DATA messages (set to zeros for all other messages):&lt;br /&gt;
&lt;br /&gt;
H(parent) = SHA256(sender_key[parent] || msg[parent] || H(parent-1))&lt;br /&gt;
&lt;br /&gt;
== Timing ==&lt;br /&gt;
Timing rules can trigger errors based on some assumed constants:&lt;br /&gt;
&lt;br /&gt;
* MAX_RTT - this is the maximum time it should take for a sent message to arrive at all parties.  If you send a message and haven't received it back within MAX_RTT, something is wrong.&lt;br /&gt;
&lt;br /&gt;
* MAX_RTD - this is the maximum difference in time when a message arrives at all parties.  If you receive a message that's not a successor of a message (X) you received more than MAX_RTD + MAX_RTT time ago, something is wrong.  (This is because message X might have arrived at the other party more than MAX_RTD after you saw it, and the other party's message might have taken MAX_RTT to reach you.  But after MAX_RTD + MAX_RTT, there's no excuse for the other party not to have seen X).&lt;br /&gt;
&lt;br /&gt;
* MAX_CONFIRM - this is the maximum time an existing member may spend after receiving a new user's JOIN message before sending a CONFIRM message in response.  If the new user hasn't received CONFIRM messages from existing membership within 2*MAX_RTT + MAX_CONFIRM, something is wrong.&lt;br /&gt;
&lt;br /&gt;
= Messages = &lt;br /&gt;
&lt;br /&gt;
== Generic structures ==&lt;br /&gt;
&lt;br /&gt;
=== Certificate ===&lt;br /&gt;
* The user's Curve25519 identity public key&lt;br /&gt;
* The user's Curve25519 ephemeral public key&lt;br /&gt;
* An Ed25519 signature from the identity key over the ephemeral key&lt;br /&gt;
   (Ed25519 signatures can be produced from Curve25519 keys)&lt;br /&gt;
&lt;br /&gt;
== Server messages ==&lt;br /&gt;
&lt;br /&gt;
=== USER_ENTERED, USER_LEFT ===&lt;br /&gt;
* &amp;quot;Presence&amp;quot; messages sent in clear by the server to indicate a user has entered or left the room&lt;br /&gt;
&lt;br /&gt;
== User messages ==&lt;br /&gt;
&lt;br /&gt;
=== QUERY ===&lt;br /&gt;
* Contains a nonce&lt;br /&gt;
* Requests a MEMBER_LIST&lt;br /&gt;
&lt;br /&gt;
=== MEMBER_LIST ===&lt;br /&gt;
* Contains the sequence number and nonce of the QUERY it's responding to&lt;br /&gt;
* Contains the transcript hash for the QUERY&lt;br /&gt;
* Contains a certificate for each member as of the QUERY&lt;br /&gt;
&lt;br /&gt;
=== JOIN ===&lt;br /&gt;
* Contains a certificate for the new member&lt;br /&gt;
* Contains the sequence number of the MEMBER_LIST it's responding to&lt;br /&gt;
&lt;br /&gt;
=== CONFIRM ===&lt;br /&gt;
* Encrypts-and-confirms an AES256 &amp;quot;sender key&amp;quot; and Ed25519 &amp;quot;signing key&amp;quot; from one member to another&lt;br /&gt;
* Uses pairwise TripleDH between sender and recipient keys, i.e.&lt;br /&gt;
   HASH( DH(A_id, B_eph) || DH(A_eph, B_id) || DH(A_eph, B_eph) )&lt;br /&gt;
* Contains the sequence number for its parent&lt;br /&gt;
* The transcript hash and membership of its parent is included as &amp;quot;additional authenticated data&amp;quot;&lt;br /&gt;
&lt;br /&gt;
=== DATA === &lt;br /&gt;
* Encrypted under the sender's &amp;quot;sender key&amp;quot;&lt;br /&gt;
* Ed25519 signature from the sender's signing key&lt;br /&gt;
* Contains the sequence number for its parent&lt;br /&gt;
* The transcript hash and membership of its parent is included as &amp;quot;additional authenticated data&amp;quot;&lt;br /&gt;
&lt;br /&gt;
= Algorithms = &lt;br /&gt;
&lt;br /&gt;
== Blocking Join ==&lt;br /&gt;
On entering a room, a user sends a QUERY.  Someone will respond with a MEMBER_LIST.  If two users try to join simultaneously, the second QUERY will not be responded to until the first user has finished joining.&lt;br /&gt;
&lt;br /&gt;
On receiving a MEMBER_LIST, the new user learns the membership, transcript hash, and sequence number for the QUERY message.  To finish joining, the new user sends a JOIN, including a CONFIRM for each existing member.  Each member will respond to her JOIN message with a CONFIRM, containing a new sender key.&lt;br /&gt;
&lt;br /&gt;
Until the new user has finished joining, existing members continue exchanging DATA with their old sender keys.  Once the last confirmation has been received, existing users switch to their new sender keys.&lt;br /&gt;
&lt;br /&gt;
Once the new user has received all CONFIRM messages from the existing membership, she is successfully joined.  If other users sent a QUERY in the meantime, the next one will be responded to with a MEMBER_LIST.&lt;br /&gt;
&lt;br /&gt;
== Nonblocking Join ==&lt;br /&gt;
On entering a room, a user sends a QUERY.  Someone will respond with a MEMBER_LIST.  If multiple users try to join simultaneously, they will all be responded to immediately.&lt;br /&gt;
&lt;br /&gt;
On receiving a MEMBER_LIST, the new user learns the membership, transcript hash, and sequence number for the QUERY message.  To finish joining, the new user sends a JOIN, including a CONFIRM for each existing member.  Each member will respond to her JOIN message with a CONFIRM, containing their current sender key.&lt;br /&gt;
&lt;br /&gt;
The new user is part of the group once her JOIN message is received.  This means that DATA can be sent between group members who have not yet confirmed each other.&lt;br /&gt;
&lt;br /&gt;
[[Category: mpOTR]]&lt;/div&gt;</summary>
		<author><name>Trevor</name></author>	</entry>

	<entry>
		<id>https://learn.equalit.ie/wiki/Np1sec/SenderKeys</id>
		<title>Np1sec/SenderKeys</title>
		<link rel="alternate" type="text/html" href="https://learn.equalit.ie/wiki/Np1sec/SenderKeys"/>
				<updated>2014-09-08T06:00:46Z</updated>
		
		<summary type="html">&lt;p&gt;Trevor: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Security Goals =&lt;br /&gt;
&lt;br /&gt;
== Transcript consistency ==&lt;br /&gt;
* Recipients are informed of the correct causal order of messages&lt;br /&gt;
* Excessively delayed messages are detected&lt;br /&gt;
&lt;br /&gt;
== Nonblocking join ==&lt;br /&gt;
* Join and leave are treated as messages, so transcript consistency applies (causal order, delays are detected).&lt;br /&gt;
* New users have to &amp;quot;confirm&amp;quot; to existing users to join.&lt;br /&gt;
* Existing users have to &amp;quot;confirm&amp;quot; to the new user shortly after the new user joins (e.g. 1 minute).&lt;br /&gt;
&lt;br /&gt;
= General concepts = &lt;br /&gt;
&lt;br /&gt;
== Room membership ==&lt;br /&gt;
Users can enter and leave the room, as signalled by presence messages from the server (USER_ENTERED, USER_LEFT).&lt;br /&gt;
&lt;br /&gt;
Users can join the room's conversation by sending a JOIN message.&lt;br /&gt;
&lt;br /&gt;
Users can only leave the conversation if the server says they left the room.&lt;br /&gt;
&lt;br /&gt;
== Sender keys and Signing keys ==&lt;br /&gt;
When a new user joins, she generates a new AES256 key (her &amp;quot;sender key&amp;quot;) and Ed25519 key (her &amp;quot;signing key&amp;quot;).  She then sends these keys to existing members, encrypted under the &amp;quot;pairwise keys&amp;quot; from pairwise key agreements.  This allows subsequent messages to be encrypted-and-signed once, instead of N times with pairwise keys.&lt;br /&gt;
&lt;br /&gt;
Every time a message is encrypted or decrypted with a sender key, the key is updated to provide forward secrecy:&lt;br /&gt;
&lt;br /&gt;
sender_key = HMAC-SHA256(prev_sender_key, &amp;quot;0&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
== Server order ==&lt;br /&gt;
All clients see the same message order from the server.  All messages are sent to all users.  Aside from the presence messages sent by the server, messages are sent by users.&lt;br /&gt;
&lt;br /&gt;
All messages in a room have a unique sequence number (0, 1, ...).  Sequence numbers are implicit, as the server may not be aware of them (e.g. XMPP MUC).&lt;br /&gt;
&lt;br /&gt;
A new user synchronizes his view of sequence numbers via the QUERY / MEMBER_LIST messages (see below).&lt;br /&gt;
&lt;br /&gt;
== Causal order ==&lt;br /&gt;
Some user-sent messages specify a &amp;quot;parent&amp;quot; sequence number which is the last message the user received before sending it.  Note:&lt;br /&gt;
* If Alice sends messages (A,B) in a row, A will not be B's parent unless Alice waits till A is received back from the server.&lt;br /&gt;
* The parent of a message is different from the &amp;quot;previous&amp;quot; message in the server's ordering, e.g. in a &amp;quot;simultaneous send&amp;quot; case two messages will have the same parent.&lt;br /&gt;
&lt;br /&gt;
Due to server ordering, the sender of message i must have seen all&lt;br /&gt;
messages from 0...i's parent.  Thus, every user-sent message i has a membership set, determined by the JOIN / USER_LEFT messages from 0...i's parent.&lt;br /&gt;
&lt;br /&gt;
== Transcript hashes ==&lt;br /&gt;
Encrypted messages include a &amp;quot;transcript hash&amp;quot; of their parent and all prior messages as &amp;quot;additional authenticated data&amp;quot;.  &lt;br /&gt;
&lt;br /&gt;
The hash also covers the sender_key for DATA messages (set to zeros for all other messages):&lt;br /&gt;
&lt;br /&gt;
H(parent) = SHA256(sender_key[parent] || msg[parent] || H(parent-1))&lt;br /&gt;
&lt;br /&gt;
== Timing ==&lt;br /&gt;
Timing rules can trigger errors based on some assumed constants:&lt;br /&gt;
&lt;br /&gt;
* MAX_RTT - this is the maximum time it should take for a sent message to arrive at all parties.  If you send a message and haven't received it back within MAX_RTT, something is wrong.&lt;br /&gt;
&lt;br /&gt;
* MAX_RTD - this is the maximum difference in time when a message arrives at all parties.  If you receive a message that's not a successor of a message (X) you received more than MAX_RTD + MAX_RTT time ago, something is wrong.  (This is because message X might have arrived at the other party more than MAX_RTD after you saw it, and the other party's message might have taken MAX_RTT to reach you.  But after MAX_RTD + MAX_RTT, there's no excuse for the other party not to have seen X).&lt;br /&gt;
&lt;br /&gt;
* MAX_CONFIRM - this is the maximum time an existing member may spend after receiving a new user's JOIN message before sending a CONFIRM message in response.  If the new user hasn't received CONFIRM messages from existing membership within 2*MAX_RTT + MAX_CONFIRM, something is wrong.&lt;br /&gt;
&lt;br /&gt;
= Messages = &lt;br /&gt;
&lt;br /&gt;
== Generic structures ==&lt;br /&gt;
&lt;br /&gt;
=== Certificate ===&lt;br /&gt;
* The user's Curve25519 identity public key&lt;br /&gt;
* The user's Curve25519 ephemeral public key&lt;br /&gt;
* An Ed25519 signature from the identity key over the ephemeral key&lt;br /&gt;
   (Ed25519 signatures can be produced from Curve25519 keys)&lt;br /&gt;
&lt;br /&gt;
== Server messages ==&lt;br /&gt;
&lt;br /&gt;
=== USER_ENTERED, USER_LEFT ===&lt;br /&gt;
* &amp;quot;Presence&amp;quot; messages sent in clear by the server to indicate a user has entered or left the room&lt;br /&gt;
&lt;br /&gt;
== User messages ==&lt;br /&gt;
&lt;br /&gt;
=== QUERY ===&lt;br /&gt;
* Contains a nonce&lt;br /&gt;
* Requests a MEMBER_LIST&lt;br /&gt;
&lt;br /&gt;
=== MEMBER_LIST ===&lt;br /&gt;
* Contains the sequence number and nonce of the QUERY it's responding to&lt;br /&gt;
* Contains the transcript hash for the QUERY&lt;br /&gt;
* Contains a certificate for each member as of the QUERY&lt;br /&gt;
&lt;br /&gt;
=== JOIN ===&lt;br /&gt;
* Contains a certificate for the new member&lt;br /&gt;
&lt;br /&gt;
=== CONFIRM ===&lt;br /&gt;
* Encrypts-and-confirms an AES256 &amp;quot;sender key&amp;quot; and Ed25519 &amp;quot;signing key&amp;quot; from one member to another&lt;br /&gt;
* Uses pairwise TripleDH between sender and recipient keys, i.e.&lt;br /&gt;
   HASH( DH(A_id, B_eph) || DH(A_eph, B_id) || DH(A_eph, B_eph) )&lt;br /&gt;
* Contains the sequence number for its parent&lt;br /&gt;
* The transcript hash and membership of its parent is included as &amp;quot;additional authenticated data&amp;quot;&lt;br /&gt;
&lt;br /&gt;
=== DATA === &lt;br /&gt;
* Encrypted under the sender's &amp;quot;sender key&amp;quot;&lt;br /&gt;
* Ed25519 signature from the sender's signing key&lt;br /&gt;
* Contains the sequence number for its parent&lt;br /&gt;
* The transcript hash and membership of its parent is included as &amp;quot;additional authenticated data&amp;quot;&lt;br /&gt;
&lt;br /&gt;
= Algorithms = &lt;br /&gt;
&lt;br /&gt;
== Blocking Join ==&lt;br /&gt;
On entering a room, a user sends a QUERY.  Someone will respond with a MEMBER_LIST.  If two users try to join simultaneously, the second QUERY will not be responded to until the first user has finished joining.&lt;br /&gt;
&lt;br /&gt;
On receiving a MEMBER_LIST, the new user learns the membership, transcript hash, and sequence number for the QUERY message.  To finish joining, the new user sends a JOIN, including a CONFIRM for each existing member.  Each member will respond to her JOIN message with a CONFIRM, containing a new sender key.&lt;br /&gt;
&lt;br /&gt;
Until the new user has finished joining, existing members continue exchanging DATA with their old sender keys.  Once the last confirmation has been received, existing users switch to their new sender keys.&lt;br /&gt;
&lt;br /&gt;
Once the new user has received all CONFIRM messages from the existing membership, she is successfully joined.  If other users sent a QUERY in the meantime, the next one will be responded to with a MEMBER_LIST.&lt;br /&gt;
&lt;br /&gt;
== Nonblocking Join ==&lt;br /&gt;
On entering a room, a user sends a QUERY.  Someone will respond with a MEMBER_LIST.  If multiple users try to join simultaneously, they will all be responded to immediately.&lt;br /&gt;
&lt;br /&gt;
On receiving a MEMBER_LIST, the new user learns the membership, transcript hash, and sequence number for the QUERY message.  To finish joining, the new user sends a JOIN, including a CONFIRM for each existing member.  Each member will respond to her JOIN message with a CONFIRM, containing their current sender key.&lt;br /&gt;
&lt;br /&gt;
The new user is part of the group once her JOIN message is received.  This means that DATA can be sent between group members who have not yet confirmed each other.&lt;br /&gt;
&lt;br /&gt;
[[Category: mpOTR]]&lt;/div&gt;</summary>
		<author><name>Trevor</name></author>	</entry>

	<entry>
		<id>https://learn.equalit.ie/wiki/Np1sec/SenderKeys</id>
		<title>Np1sec/SenderKeys</title>
		<link rel="alternate" type="text/html" href="https://learn.equalit.ie/wiki/Np1sec/SenderKeys"/>
				<updated>2014-09-08T05:57:29Z</updated>
		
		<summary type="html">&lt;p&gt;Trevor: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Security Goals =&lt;br /&gt;
&lt;br /&gt;
== Transcript consistency ==&lt;br /&gt;
* Recipients are informed of the correct causal order of messages&lt;br /&gt;
* Excessively delayed messages are detected&lt;br /&gt;
&lt;br /&gt;
== Nonblocking join ==&lt;br /&gt;
* Join and leave are treated as messages, so transcript consistency applies (causal order, delays are detected).&lt;br /&gt;
* New users have to &amp;quot;confirm&amp;quot; to existing users to join.&lt;br /&gt;
* Existing users have to &amp;quot;confirm&amp;quot; to the new user shortly after the new user joins (e.g. 1 minute).&lt;br /&gt;
&lt;br /&gt;
= General concepts = &lt;br /&gt;
&lt;br /&gt;
== Room membership ==&lt;br /&gt;
Users can enter and leave the room, as signalled by presence messages from the server (USER_ENTERED, USER_LEFT).&lt;br /&gt;
&lt;br /&gt;
Users can join the room's conversation by sending a JOIN message.&lt;br /&gt;
&lt;br /&gt;
Users can only leave the conversation if the server says they left the room.&lt;br /&gt;
&lt;br /&gt;
== Sender keys and Signing keys ==&lt;br /&gt;
When a new user joins, she generates a new AES256 key (her &amp;quot;sender key&amp;quot;) and Ed25519 key (her &amp;quot;signing key&amp;quot;).  She then sends these keys to existing members, encrypted under the &amp;quot;pairwise keys&amp;quot; from pairwise key agreements.  This allows subsequent messages to be encrypted-and-signed once, instead of N times with pairwise keys.&lt;br /&gt;
&lt;br /&gt;
Every time a message is encrypted or decrypted with a sender key, the key is updated to provide forward secrecy:&lt;br /&gt;
&lt;br /&gt;
sender_key = HMAC-SHA256(prev_sender_key, &amp;quot;0&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
== Server order ==&lt;br /&gt;
All clients see the same message order from the server.  All messages are sent to all users.  Aside from the presence messages sent by the server, messages are sent by users.&lt;br /&gt;
&lt;br /&gt;
All messages in a room have a unique sequence number (0, 1, ...).  Sequence numbers are implicit, as the server may not be aware of them (e.g. XMPP MUC).&lt;br /&gt;
&lt;br /&gt;
A new user synchronizes his view of sequence numbers via the QUERY / MEMBER_LIST messages (see below).&lt;br /&gt;
&lt;br /&gt;
== Causal order ==&lt;br /&gt;
Some user-sent message specifies a &amp;quot;parent&amp;quot; sequence number which is the last message the user received before sending it.  Note:&lt;br /&gt;
* If Alice sends messages (A,B) in a row, A will not be B's parent unless Alice waits till A is received back from the server.&lt;br /&gt;
* The parent of a message is different from the &amp;quot;previous&amp;quot; message in the server's ordering, e.g. in a &amp;quot;simultaneous send&amp;quot; case two messages will have the same parent.&lt;br /&gt;
&lt;br /&gt;
Due to server ordering, the sender of message i must have seen all&lt;br /&gt;
messages from 0...i's parent.  Thus, every user-sent message i has a membership set, determined by the JOIN / USER_LEFT messages from 0...i's parent.&lt;br /&gt;
&lt;br /&gt;
== Transcript hashes ==&lt;br /&gt;
Encrypted messages include a &amp;quot;transcript hash&amp;quot; of their parent and all prior messages as &amp;quot;additional authenticated data&amp;quot;.  &lt;br /&gt;
&lt;br /&gt;
The hash also covers the sender_key for DATA messages (set to zeros for all other messages):&lt;br /&gt;
&lt;br /&gt;
H(parent) = SHA256(sender_key[parent] || msg[parent] || H(parent-1))&lt;br /&gt;
&lt;br /&gt;
== Timing ==&lt;br /&gt;
Timing rules can trigger errors based on some assumed constants:&lt;br /&gt;
&lt;br /&gt;
* MAX_RTT - this is the maximum time it should take for a sent message to arrive at all parties.  If you send a message and haven't received it back within MAX_RTT, something is wrong.&lt;br /&gt;
&lt;br /&gt;
* MAX_RTD - this is the maximum difference in time when a message arrives at all parties.  If you receive a message that's not a successor of a message (X) you received more than MAX_RTD + MAX_RTT time ago, something is wrong.  (This is because message X might have arrived at the other party more than MAX_RTD after you saw it, and the other party's message might have taken MAX_RTT to reach you.  But after MAX_RTD + MAX_RTT, there's no excuse for the other party not to have seen X).&lt;br /&gt;
&lt;br /&gt;
* MAX_CONFIRM - this is the maximum time an existing member may spend after receiving a new user's JOIN message before sending a CONFIRM message in response.  If the new user hasn't received CONFIRM messages from existing membership within 2*MAX_RTT + MAX_CONFIRM, something is wrong.&lt;br /&gt;
&lt;br /&gt;
= Messages = &lt;br /&gt;
&lt;br /&gt;
== Generic structures ==&lt;br /&gt;
&lt;br /&gt;
=== Certificate ===&lt;br /&gt;
* The user's Curve25519 identity public key&lt;br /&gt;
* The user's Curve25519 ephemeral public key&lt;br /&gt;
* An Ed25519 signature from the identity key over the ephemeral key&lt;br /&gt;
   (Ed25519 signatures can be produced from Curve25519 keys)&lt;br /&gt;
&lt;br /&gt;
== Server messages ==&lt;br /&gt;
&lt;br /&gt;
=== USER_ENTERED, USER_LEFT ===&lt;br /&gt;
* &amp;quot;Presence&amp;quot; messages sent in clear by the server to indicate a user has entered or left the room&lt;br /&gt;
&lt;br /&gt;
== User messages ==&lt;br /&gt;
&lt;br /&gt;
=== QUERY ===&lt;br /&gt;
* Contains a nonce&lt;br /&gt;
* Requests a MEMBER_LIST&lt;br /&gt;
&lt;br /&gt;
=== MEMBER_LIST ===&lt;br /&gt;
* Contains the sequence number and nonce of the QUERY it's responding to&lt;br /&gt;
* Contains the transcript hash for the QUERY&lt;br /&gt;
* Contains a certificate for each member as of the QUERY&lt;br /&gt;
&lt;br /&gt;
=== JOIN ===&lt;br /&gt;
* Contains a certificate for the new member&lt;br /&gt;
&lt;br /&gt;
=== CONFIRM ===&lt;br /&gt;
* Encrypts-and-confirms an AES256 &amp;quot;sender key&amp;quot; and Ed25519 &amp;quot;signing key&amp;quot; from one member to another&lt;br /&gt;
* Uses pairwise TripleDH between sender and recipient keys, i.e.&lt;br /&gt;
   HASH( DH(A_id, B_eph) || DH(A_eph, B_id) || DH(A_eph, B_eph) )&lt;br /&gt;
* Contains the sequence number for its parent&lt;br /&gt;
* The transcript hash and membership of its parent is included as &amp;quot;additional authenticated data&amp;quot;&lt;br /&gt;
&lt;br /&gt;
=== DATA === &lt;br /&gt;
* Encrypted under the sender's &amp;quot;sender key&amp;quot;&lt;br /&gt;
* Ed25519 signature from the sender's signing key&lt;br /&gt;
* Contains the sequence number for its parent&lt;br /&gt;
* The transcript hash and membership of its parent is included as &amp;quot;additional authenticated data&amp;quot;&lt;br /&gt;
&lt;br /&gt;
= Algorithms = &lt;br /&gt;
&lt;br /&gt;
== Blocking Join ==&lt;br /&gt;
On entering a room, a user sends a QUERY.  Someone will respond with a MEMBER_LIST.  If two users try to join simultaneously, the second QUERY will not be responded to until the first user has finished joining.&lt;br /&gt;
&lt;br /&gt;
On receiving a MEMBER_LIST, the new user learns the membership, transcript hash, and sequence number for the QUERY message.  To finish joining, the new user sends a JOIN, including a CONFIRM for each existing member.  Each member will respond to her JOIN message with a CONFIRM, containing a new sender key.&lt;br /&gt;
&lt;br /&gt;
Until the new user has finished joining, existing members continue exchanging DATA with their old sender keys.  Once the last confirmation has been received, existing users switch to their new sender keys.&lt;br /&gt;
&lt;br /&gt;
Once the new user has received all CONFIRM messages from the existing membership, she is successfully joined.  If other users sent a QUERY in the meantime, the next one will be responded to with a MEMBER_LIST.&lt;br /&gt;
&lt;br /&gt;
== Nonblocking Join ==&lt;br /&gt;
On entering a room, a user sends a QUERY.  Someone will respond with a MEMBER_LIST.  If multiple users try to join simultaneously, they will all be responded to immediately.&lt;br /&gt;
&lt;br /&gt;
On receiving a MEMBER_LIST, the new user learns the membership, transcript hash, and sequence number for the QUERY message.  To finish joining, the new user sends a JOIN, including a CONFIRM for each existing member.  Each member will respond to her JOIN message with a CONFIRM, containing their current sender key.&lt;br /&gt;
&lt;br /&gt;
The new user is part of the group once her JOIN message is received.  This means that DATA can be sent between group members who have not yet confirmed each other.&lt;br /&gt;
&lt;br /&gt;
[[Category: mpOTR]]&lt;/div&gt;</summary>
		<author><name>Trevor</name></author>	</entry>

	<entry>
		<id>https://learn.equalit.ie/wiki/Np1sec/SenderKeys</id>
		<title>Np1sec/SenderKeys</title>
		<link rel="alternate" type="text/html" href="https://learn.equalit.ie/wiki/Np1sec/SenderKeys"/>
				<updated>2014-09-08T05:55:51Z</updated>
		
		<summary type="html">&lt;p&gt;Trevor: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Security Goals =&lt;br /&gt;
&lt;br /&gt;
== Transcript consistency ==&lt;br /&gt;
* Recipients are informed of the correct causal order of messages&lt;br /&gt;
* Excessively delayed messages are detected&lt;br /&gt;
&lt;br /&gt;
== Nonblocking join ==&lt;br /&gt;
* Join and leave are treated as messages, so transcript consistency applies (causal order, delays are detected).&lt;br /&gt;
* New users have to &amp;quot;confirm&amp;quot; to existing users to join.&lt;br /&gt;
* Existing users have to &amp;quot;confirm&amp;quot; to the new user shortly after the new user joins (e.g. 1 minute).&lt;br /&gt;
&lt;br /&gt;
= General concepts = &lt;br /&gt;
&lt;br /&gt;
== Room membership ==&lt;br /&gt;
Users can enter and leave the room, as signalled by presence messages from the server (USER_ENTERED, USER_LEFT).&lt;br /&gt;
&lt;br /&gt;
Users can join the room's conversation by sending a JOIN message.&lt;br /&gt;
&lt;br /&gt;
Users can only leave the conversation if the server says they left the room.&lt;br /&gt;
&lt;br /&gt;
== Sender keys and Signing keys ==&lt;br /&gt;
When a new user joins, she generates a new AES256 key (her &amp;quot;sender key&amp;quot;) and Ed25519 key (her &amp;quot;signing key&amp;quot;).  She then sends these keys to existing members, encrypted under the &amp;quot;pairwise keys&amp;quot; from pairwise key agreements.  This allows subsequent messages to be encrypted-and-signed once, instead of N times with pairwise keys.&lt;br /&gt;
&lt;br /&gt;
Every time a message is encrypted or decrypted with a sender key, the key is updated to provide forward secrecy:&lt;br /&gt;
&lt;br /&gt;
sender_key = HMAC-SHA256(prev_sender_key, &amp;quot;0&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
== Server order ==&lt;br /&gt;
All clients see the same message order from the server.  All messages are sent to all users.  Aside from the presence messages sent by the server, messages are sent by users.&lt;br /&gt;
&lt;br /&gt;
All messages in a room have a unique sequence number (0, 1, ...).  Sequence numbers are implicit, as the server may not be aware of them (e.g. XMPP MUC).&lt;br /&gt;
&lt;br /&gt;
A new user synchronizes his view of sequence numbers via the QUERY / MEMBER_LIST messages (see below).&lt;br /&gt;
&lt;br /&gt;
== Causal order ==&lt;br /&gt;
Every user-sent message specifies a &amp;quot;parent&amp;quot; sequence number which is the last message the user received before sending it.  Note:&lt;br /&gt;
* If Alice sends messages (A,B) in a row, A will not be B's parent unless Alice waits till A is received back from the server.&lt;br /&gt;
* The parent of a message is different from the &amp;quot;previous&amp;quot; message in the server's ordering, e.g. in a &amp;quot;simultaneous send&amp;quot; case two messages will have the same parent.&lt;br /&gt;
&lt;br /&gt;
Due to server ordering, the sender of message i must have seen all&lt;br /&gt;
messages from 0...i's parent.  Thus, every user-sent message i has a membership set, determined by the JOIN / USER_LEFT messages from 0...i's parent.&lt;br /&gt;
&lt;br /&gt;
== Transcript hashes ==&lt;br /&gt;
Encrypted messages include a &amp;quot;transcript hash&amp;quot; of their parent and all prior messages as &amp;quot;additional authenticated data&amp;quot;.  &lt;br /&gt;
&lt;br /&gt;
The hash also covers the sender_key for DATA messages (set to zeros for all other messages):&lt;br /&gt;
&lt;br /&gt;
H(parent) = SHA256(sender_key[parent] || msg[parent] || H(parent-1))&lt;br /&gt;
&lt;br /&gt;
== Timing ==&lt;br /&gt;
Timing rules can trigger errors based on some assumed constants:&lt;br /&gt;
&lt;br /&gt;
* MAX_RTT - this is the maximum time it should take for a sent message to arrive at all parties.  If you send a message and haven't received it back within MAX_RTT, something is wrong.&lt;br /&gt;
&lt;br /&gt;
* MAX_RTD - this is the maximum difference in time when a message arrives at all parties.  If you receive a message that's not a successor of a message (X) you received more than MAX_RTD + MAX_RTT time ago, something is wrong.  (This is because message X might have arrived at the other party more than MAX_RTD after you saw it, and the other party's message might have taken MAX_RTT to reach you.  But after MAX_RTD + MAX_RTT, there's no excuse for the other party not to have seen X).&lt;br /&gt;
&lt;br /&gt;
* MAX_CONFIRM - this is the maximum time an existing member may spend after receiving a new user's JOIN message before sending a CONFIRM message in response.  If the new user hasn't received CONFIRM messages from existing membership within 2*MAX_RTT + MAX_CONFIRM, something is wrong.&lt;br /&gt;
&lt;br /&gt;
= Messages = &lt;br /&gt;
&lt;br /&gt;
== Generic structures ==&lt;br /&gt;
&lt;br /&gt;
=== Certificate ===&lt;br /&gt;
* The user's Curve25519 identity public key&lt;br /&gt;
* The user's Curve25519 ephemeral public key&lt;br /&gt;
* An Ed25519 signature from the identity key over the ephemeral key&lt;br /&gt;
   (Ed25519 signatures can be produced from Curve25519 keys)&lt;br /&gt;
&lt;br /&gt;
== Server messages ==&lt;br /&gt;
&lt;br /&gt;
=== USER_ENTERED, USER_LEFT ===&lt;br /&gt;
* &amp;quot;Presence&amp;quot; messages sent in clear by the server to indicate a user has entered or left the room&lt;br /&gt;
&lt;br /&gt;
== User messages ==&lt;br /&gt;
&lt;br /&gt;
=== QUERY ===&lt;br /&gt;
* Contains a nonce&lt;br /&gt;
* Requests a MEMBER_LIST&lt;br /&gt;
&lt;br /&gt;
=== MEMBER_LIST ===&lt;br /&gt;
* Contains the sequence number and nonce of the QUERY it's responding to&lt;br /&gt;
* Contains the transcript hash for the QUERY&lt;br /&gt;
* Contains a certificate for each member as of the QUERY&lt;br /&gt;
&lt;br /&gt;
=== JOIN ===&lt;br /&gt;
* Contains a certificate for the new member&lt;br /&gt;
&lt;br /&gt;
=== CONFIRM ===&lt;br /&gt;
* Encrypts-and-confirms an AES256 &amp;quot;sender key&amp;quot; and Ed25519 &amp;quot;signing key&amp;quot; from one member to another&lt;br /&gt;
* Uses pairwise TripleDH between sender and recipient keys, i.e.&lt;br /&gt;
   HASH( DH(A_id, B_eph) || DH(A_eph, B_id) || DH(A_eph, B_eph) )&lt;br /&gt;
* Contains the sequence number for its parent&lt;br /&gt;
* The transcript hash and membership of its parent is included as &amp;quot;additional authenticated data&amp;quot;&lt;br /&gt;
&lt;br /&gt;
=== DATA === &lt;br /&gt;
* Encrypted under the sender's &amp;quot;sender key&amp;quot;&lt;br /&gt;
* Ed25519 signature from the sender's signing key&lt;br /&gt;
* Contains the sequence number for its parent&lt;br /&gt;
* The transcript hash and membership of its parent is included as &amp;quot;additional authenticated data&amp;quot;&lt;br /&gt;
&lt;br /&gt;
= Algorithms = &lt;br /&gt;
&lt;br /&gt;
== Blocking Join ==&lt;br /&gt;
On entering a room, a user sends a QUERY.  Someone will respond with a MEMBER_LIST.  If two users try to join simultaneously, the second QUERY will not be responded to until the first user has finished joining.&lt;br /&gt;
&lt;br /&gt;
On receiving a MEMBER_LIST, the new user learns the membership, transcript hash, and sequence number for the QUERY message.  To finish joining, the new user sends a JOIN, including a CONFIRM for each existing member.  Each member will respond to her JOIN message with a CONFIRM, containing a new sender key.&lt;br /&gt;
&lt;br /&gt;
Until the new user has finished joining, existing members continue exchanging DATA with their old sender keys.  Once the last confirmation has been received, existing users switch to their new sender keys.&lt;br /&gt;
&lt;br /&gt;
Once the new user has received all CONFIRM messages from the existing membership, she is successfully joined.  If other users sent a QUERY in the meantime, the next one will be responded to with a MEMBER_LIST.&lt;br /&gt;
&lt;br /&gt;
== Nonblocking Join ==&lt;br /&gt;
On entering a room, a user sends a QUERY.  Someone will respond with a MEMBER_LIST.  If multiple users try to join simultaneously, they will all be responded to immediately.&lt;br /&gt;
&lt;br /&gt;
On receiving a MEMBER_LIST, the new user learns the membership, transcript hash, and sequence number for the QUERY message.  To finish joining, the new user sends a JOIN, including a CONFIRM for each existing member.  Each member will respond to her JOIN message with a CONFIRM, containing their current sender key.&lt;br /&gt;
&lt;br /&gt;
The new user is part of the group once her JOIN message is received.  This means that DATA can be sent between group members who have not yet confirmed each other.&lt;br /&gt;
&lt;br /&gt;
[[Category: mpOTR]]&lt;/div&gt;</summary>
		<author><name>Trevor</name></author>	</entry>

	<entry>
		<id>https://learn.equalit.ie/wiki/Np1sec/SenderKeys</id>
		<title>Np1sec/SenderKeys</title>
		<link rel="alternate" type="text/html" href="https://learn.equalit.ie/wiki/Np1sec/SenderKeys"/>
				<updated>2014-09-08T05:53:28Z</updated>
		
		<summary type="html">&lt;p&gt;Trevor: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Security Goals =&lt;br /&gt;
&lt;br /&gt;
== Transcript consistency ==&lt;br /&gt;
* Recipients are informed of the correct causal order of messages&lt;br /&gt;
* Excessively delayed messages are detected&lt;br /&gt;
&lt;br /&gt;
== Nonblocking join ==&lt;br /&gt;
* Join and leave are treated as messages, so transcript consistency applies (causal order, delays are detected).&lt;br /&gt;
* New users have to &amp;quot;confirm&amp;quot; to existing users to join.&lt;br /&gt;
* Existing users have to &amp;quot;confirm&amp;quot; to the new user shortly after the new user joins (e.g. 1 minute).&lt;br /&gt;
&lt;br /&gt;
= General concepts = &lt;br /&gt;
&lt;br /&gt;
== Room membership ==&lt;br /&gt;
Users can enter and leave the room, as signalled by presence messages from the server (USER_ENTERED, USER_LEFT).&lt;br /&gt;
&lt;br /&gt;
Users can join the room's conversation by sending a JOIN message.&lt;br /&gt;
&lt;br /&gt;
Users can only leave the conversation if the server says they left the room.&lt;br /&gt;
&lt;br /&gt;
== Sender keys and Signing keys ==&lt;br /&gt;
When a new user joins, she generates a new AES256 key (her &amp;quot;sender key&amp;quot;) and Ed25519 key (her &amp;quot;signing key&amp;quot;).  She then sends these keys to existing members, encrypted under the &amp;quot;pairwise keys&amp;quot; from pairwise key agreements.  This allows subsequent messages to be encrypted-and-signed once, instead of N times with pairwise keys.&lt;br /&gt;
&lt;br /&gt;
Every time a message is encrypted or decrypted with a sender key, the key is updated to provide forward secrecy:&lt;br /&gt;
&lt;br /&gt;
sender_key = HMAC-SHA256(prev_sender_key, &amp;quot;0&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
== Server order ==&lt;br /&gt;
All clients see the same message order from the server.  All messages are sent to all users.  Aside from the presence messages sent by the server, messages are sent by users.&lt;br /&gt;
&lt;br /&gt;
All messages in a room have a unique sequence number (0, 1, ...).  Sequence numbers are implicit, as the server may not be aware of them (e.g. XMPP MUC).&lt;br /&gt;
&lt;br /&gt;
A new user synchronizes his view of sequence numbers via the QUERY / MEMBER_LIST messages (see below).&lt;br /&gt;
&lt;br /&gt;
== Causal order ==&lt;br /&gt;
Every user-sent message specifies a &amp;quot;parent&amp;quot; sequence number which is the last message the user received before sending it.  Note:&lt;br /&gt;
* If Alice sends messages (A,B) in a row, A will not be B's parent unless Alice waits till A is received back from the server.&lt;br /&gt;
* The parent of a message is different from the &amp;quot;previous&amp;quot; message in the server's ordering, e.g. in a &amp;quot;simultaneous send&amp;quot; case two messages will have the same parent.&lt;br /&gt;
&lt;br /&gt;
Due to server ordering, the sender of message i must have seen all&lt;br /&gt;
messages from 0...i's parent.  Thus, every user-sent message i has a membership set, determined by the JOIN / USER_LEFT messages from 0...i's parent.&lt;br /&gt;
&lt;br /&gt;
== Transcript hashes ==&lt;br /&gt;
Encrypted messages include a &amp;quot;transcript hash&amp;quot; of their parent and all prior messages as &amp;quot;additional authenticated data&amp;quot;.  &lt;br /&gt;
&lt;br /&gt;
The hash also covers the sender_key for each message (set to zeros for cleartext messages):&lt;br /&gt;
&lt;br /&gt;
H(parent) = SHA256(msg[parent] || H(parent-1))&lt;br /&gt;
&lt;br /&gt;
== Timing ==&lt;br /&gt;
Timing rules can trigger errors based on some assumed constants:&lt;br /&gt;
&lt;br /&gt;
* MAX_RTT - this is the maximum time it should take for a sent message to arrive at all parties.  If you send a message and haven't received it back within MAX_RTT, something is wrong.&lt;br /&gt;
&lt;br /&gt;
* MAX_RTD - this is the maximum difference in time when a message arrives at all parties.  If you receive a message that's not a successor of a message (X) you received more than MAX_RTD + MAX_RTT time ago, something is wrong.  (This is because message X might have arrived at the other party more than MAX_RTD after you saw it, and the other party's message might have taken MAX_RTT to reach you.  But after MAX_RTD + MAX_RTT, there's no excuse for the other party not to have seen X).&lt;br /&gt;
&lt;br /&gt;
* MAX_CONFIRM - this is the maximum time an existing member may spend after receiving a new user's JOIN message before sending a CONFIRM message in response.  If the new user hasn't received CONFIRM messages from existing membership within 2*MAX_RTT + MAX_CONFIRM, something is wrong.&lt;br /&gt;
&lt;br /&gt;
= Messages = &lt;br /&gt;
&lt;br /&gt;
== Generic structures ==&lt;br /&gt;
&lt;br /&gt;
=== Certificate ===&lt;br /&gt;
* The user's Curve25519 identity public key&lt;br /&gt;
* The user's Curve25519 ephemeral public key&lt;br /&gt;
* An Ed25519 signature from the identity key over the ephemeral key&lt;br /&gt;
   (Ed25519 signatures can be produced from Curve25519 keys)&lt;br /&gt;
&lt;br /&gt;
== Server messages ==&lt;br /&gt;
&lt;br /&gt;
=== USER_ENTERED, USER_LEFT ===&lt;br /&gt;
* &amp;quot;Presence&amp;quot; messages sent in clear by the server to indicate a user has entered or left the room&lt;br /&gt;
&lt;br /&gt;
== User messages ==&lt;br /&gt;
&lt;br /&gt;
=== QUERY ===&lt;br /&gt;
* Contains a nonce&lt;br /&gt;
* Requests a MEMBER_LIST&lt;br /&gt;
&lt;br /&gt;
=== MEMBER_LIST ===&lt;br /&gt;
* Contains the sequence number and nonce of the QUERY it's responding to&lt;br /&gt;
* Contains the transcript hash for the QUERY&lt;br /&gt;
* Contains a certificate for each member as of the QUERY&lt;br /&gt;
&lt;br /&gt;
=== JOIN ===&lt;br /&gt;
* Contains a certificate for the new member&lt;br /&gt;
&lt;br /&gt;
=== CONFIRM ===&lt;br /&gt;
* Encrypts-and-confirms an AES256 &amp;quot;sender key&amp;quot; and Ed25519 &amp;quot;signing key&amp;quot; from one member to another&lt;br /&gt;
* Uses pairwise TripleDH between sender and recipient keys, i.e.&lt;br /&gt;
   HASH( DH(A_id, B_eph) || DH(A_eph, B_id) || DH(A_eph, B_eph) )&lt;br /&gt;
* Contains the sequence number for its parent&lt;br /&gt;
* The transcript hash and membership of its parent is included as &amp;quot;additional authenticated data&amp;quot;&lt;br /&gt;
&lt;br /&gt;
=== DATA === &lt;br /&gt;
* Encrypted under the sender's &amp;quot;sender key&amp;quot;&lt;br /&gt;
* Ed25519 signature from the sender's signing key&lt;br /&gt;
* Contains the sequence number for its parent&lt;br /&gt;
* The transcript hash and membership of its parent is included as &amp;quot;additional authenticated data&amp;quot;&lt;br /&gt;
&lt;br /&gt;
= Algorithms = &lt;br /&gt;
&lt;br /&gt;
== Blocking Join ==&lt;br /&gt;
On entering a room, a user sends a QUERY.  Someone will respond with a MEMBER_LIST.  If two users try to join simultaneously, the second QUERY will not be responded to until the first user has finished joining.&lt;br /&gt;
&lt;br /&gt;
On receiving a MEMBER_LIST, the new user learns the membership, transcript hash, and sequence number for the QUERY message.  To finish joining, the new user sends a JOIN, including a CONFIRM for each existing member.  Each member will respond to her JOIN message with a CONFIRM, containing a new sender key.&lt;br /&gt;
&lt;br /&gt;
Until the new user has finished joining, existing members continue exchanging DATA with their old sender keys.  Once the last confirmation has been received, existing users switch to their new sender keys.&lt;br /&gt;
&lt;br /&gt;
Once the new user has received all CONFIRM messages from the existing membership, she is successfully joined.  If other users sent a QUERY in the meantime, the next one will be responded to with a MEMBER_LIST.&lt;br /&gt;
&lt;br /&gt;
== Nonblocking Join ==&lt;br /&gt;
On entering a room, a user sends a QUERY.  Someone will respond with a MEMBER_LIST.  If multiple users try to join simultaneously, they will all be responded to immediately.&lt;br /&gt;
&lt;br /&gt;
On receiving a MEMBER_LIST, the new user learns the membership, transcript hash, and sequence number for the QUERY message.  To finish joining, the new user sends a JOIN, including a CONFIRM for each existing member.  Each member will respond to her JOIN message with a CONFIRM, containing their current sender key.&lt;br /&gt;
&lt;br /&gt;
The new user is part of the group once her JOIN message is received.  This means that DATA can be sent between group members who have not yet confirmed each other.&lt;br /&gt;
&lt;br /&gt;
[[Category: mpOTR]]&lt;/div&gt;</summary>
		<author><name>Trevor</name></author>	</entry>

	<entry>
		<id>https://learn.equalit.ie/wiki/Np1sec/SenderKeys</id>
		<title>Np1sec/SenderKeys</title>
		<link rel="alternate" type="text/html" href="https://learn.equalit.ie/wiki/Np1sec/SenderKeys"/>
				<updated>2014-09-08T05:29:14Z</updated>
		
		<summary type="html">&lt;p&gt;Trevor: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Security Goals =&lt;br /&gt;
&lt;br /&gt;
== Transcript consistency ==&lt;br /&gt;
* Recipients are informed of the correct causal order of messages&lt;br /&gt;
* Excessively delayed messages are detected&lt;br /&gt;
&lt;br /&gt;
== Nonblocking join ==&lt;br /&gt;
* Join and leave are treated as messages, so transcript consistency applies (causal order, delays are detected).&lt;br /&gt;
* New users have to &amp;quot;confirm&amp;quot; to existing users to join.&lt;br /&gt;
* Existing users have to &amp;quot;confirm&amp;quot; to the new user shortly after the new user joins (e.g. 1 minute).&lt;br /&gt;
&lt;br /&gt;
= General concepts = &lt;br /&gt;
&lt;br /&gt;
== Room membership ==&lt;br /&gt;
Users can enter and leave the room, as signalled by presence messages from the server (USER_ENTERED, USER_LEFT).&lt;br /&gt;
&lt;br /&gt;
Users can join the room's conversation by sending a JOIN message.&lt;br /&gt;
&lt;br /&gt;
Users can only leave the conversation if the server says they left the room.&lt;br /&gt;
&lt;br /&gt;
== Sender keys and Signing keys ==&lt;br /&gt;
When a new user joins, she generates a new AES256 key (her &amp;quot;sender key&amp;quot;) and Ed25519 key (her &amp;quot;signing key&amp;quot;).  She then sends these keys to existing members, encrypted under the &amp;quot;pairwise keys&amp;quot; from pairwise key agreements.  This allows subsequent messages to be encrypted-and-signed once, instead of N times with pairwise keys.&lt;br /&gt;
&lt;br /&gt;
Every time a message is encrypted or decrypted with a sender key, the key is updated to provide forward secrecy:&lt;br /&gt;
&lt;br /&gt;
sender_key = HMAC-SHA256(prev_sender_key, &amp;quot;0&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
== Server order ==&lt;br /&gt;
All clients see the same message order from the server.  All messages are sent to all users.  Aside from the presence messages sent by the server, messages are sent by users.&lt;br /&gt;
&lt;br /&gt;
All messages in a room have a unique sequence number (0, 1, ...).  Sequence numbers are implicit, as the server may not be aware of them (e.g. XMPP MUC).&lt;br /&gt;
&lt;br /&gt;
A new user synchronizes his view of sequence numbers via the QUERY / MEMBER_LIST messages (see below).&lt;br /&gt;
&lt;br /&gt;
== Causal order ==&lt;br /&gt;
Every user-sent message specifies a &amp;quot;parent&amp;quot; sequence number which is the last message the user received before sending it.  Note:&lt;br /&gt;
* If Alice sends messages (A,B) in a row, A will not be B's parent unless Alice waits till A is received back from the server.&lt;br /&gt;
* The parent of a message is different from the &amp;quot;previous&amp;quot; message in the server's ordering, e.g. in a &amp;quot;simultaneous send&amp;quot; case two messages will have the same parent.&lt;br /&gt;
&lt;br /&gt;
Due to server ordering, the sender of message i must have seen all&lt;br /&gt;
messages from 0...i's parent.  Thus, every user-sent message i has a membership set, determined by the JOIN / USER_LEFT messages from 0...i's parent.&lt;br /&gt;
&lt;br /&gt;
== Transcript hashes ==&lt;br /&gt;
Every message specifies its parent's sequence number.  Some messages also specify a transcript hash of that parent and all prior messages.  The hash also covers the sender_key for each message (set to zeros for cleartext messages):&lt;br /&gt;
&lt;br /&gt;
H(parent) = SHA256(sender_key[parent] || ciphertext[parent] || H(parent-1))&lt;br /&gt;
&lt;br /&gt;
== Timing ==&lt;br /&gt;
Timing rules can trigger errors based on some assumed constants:&lt;br /&gt;
&lt;br /&gt;
* MAX_RTT - this is the maximum time it should take for a sent message to arrive at all parties.  If you send a message and haven't received it back within MAX_RTT, something is wrong.&lt;br /&gt;
&lt;br /&gt;
* MAX_RTD - this is the maximum difference in time when a message arrives at all parties.  If you receive a message that's not a successor of a message (X) you received more than MAX_RTD + MAX_RTT time ago, something is wrong.  (This is because message X might have arrived at the other party more than MAX_RTD after you saw it, and the other party's message might have taken MAX_RTT to reach you.  But after MAX_RTD + MAX_RTT, there's no excuse for the other party not to have seen X).&lt;br /&gt;
&lt;br /&gt;
* MAX_CONFIRM - this is the maximum time an existing member may spend after receiving a new user's JOIN message before sending a CONFIRM message in response.  If the new user hasn't received CONFIRM messages from existing membership within 2*MAX_RTT + MAX_CONFIRM, something is wrong.&lt;br /&gt;
&lt;br /&gt;
= Messages = &lt;br /&gt;
&lt;br /&gt;
== Generic structures ==&lt;br /&gt;
&lt;br /&gt;
=== Certificate ===&lt;br /&gt;
* The user's Curve25519 identity public key&lt;br /&gt;
* The user's Curve25519 ephemeral public key&lt;br /&gt;
* An Ed25519 signature from the identity key over the ephemeral key&lt;br /&gt;
   (Ed25519 signatures can be produced from Curve25519 keys)&lt;br /&gt;
&lt;br /&gt;
== Server messages ==&lt;br /&gt;
&lt;br /&gt;
=== USER_ENTERED, USER_LEFT ===&lt;br /&gt;
* &amp;quot;Presence&amp;quot; messages sent in clear by the server to indicate a user has entered or left the room&lt;br /&gt;
&lt;br /&gt;
== User messages ==&lt;br /&gt;
&lt;br /&gt;
=== QUERY ===&lt;br /&gt;
* Contains a nonce&lt;br /&gt;
* Requests a MEMBER_LIST&lt;br /&gt;
&lt;br /&gt;
=== MEMBER_LIST ===&lt;br /&gt;
* Contains the sequence number and nonce of the QUERY it's responding to&lt;br /&gt;
* Contains the transcript hash for the QUERY&lt;br /&gt;
* Contains a certificate for each member as of the QUERY&lt;br /&gt;
&lt;br /&gt;
=== JOIN ===&lt;br /&gt;
* Contains a certificate for the new member&lt;br /&gt;
&lt;br /&gt;
=== CONFIRM ===&lt;br /&gt;
* Encrypts-and-confirms an AES256 &amp;quot;sender key&amp;quot; and Ed25519 &amp;quot;signing key&amp;quot; from one member to another&lt;br /&gt;
* Uses pairwise TripleDH between sender and recipient keys, i.e.&lt;br /&gt;
   HASH( DH(A_id, B_eph) || DH(A_eph, B_id) || DH(A_eph, B_eph) )&lt;br /&gt;
* Contains the sequence number for its parent&lt;br /&gt;
* The transcript hash and membership of its parent is included as &amp;quot;additional authenticated data&amp;quot;&lt;br /&gt;
&lt;br /&gt;
=== DATA === &lt;br /&gt;
* Encrypted under the sender's &amp;quot;sender key&amp;quot;&lt;br /&gt;
* Ed25519 signature from the sender's signing key&lt;br /&gt;
* Contains the sequence number for its parent&lt;br /&gt;
* The transcript hash and membership of its parent is included as &amp;quot;additional authenticated data&amp;quot;&lt;br /&gt;
&lt;br /&gt;
= Algorithms = &lt;br /&gt;
&lt;br /&gt;
== Blocking Join ==&lt;br /&gt;
On entering a room, a user sends a QUERY.  Someone will respond with a MEMBER_LIST.  If two users try to join simultaneously, the second QUERY will not be responded to until the first user has finished joining.&lt;br /&gt;
&lt;br /&gt;
On receiving a MEMBER_LIST, the new user learns the membership, transcript hash, and sequence number for the QUERY message.  To finish joining, the new user sends a JOIN, including a CONFIRM for each existing member.  Each member will respond to her JOIN message with a CONFIRM, containing a new sender key.&lt;br /&gt;
&lt;br /&gt;
Until the new user has finished joining, existing members continue exchanging DATA with their old sender keys.  Once the last confirmation has been received, existing users switch to their new sender keys.&lt;br /&gt;
&lt;br /&gt;
Once the new user has received all CONFIRM messages from the existing membership, she is successfully joined.  If other users sent a QUERY in the meantime, the next one will be responded to with a MEMBER_LIST.&lt;br /&gt;
&lt;br /&gt;
== Nonblocking Join ==&lt;br /&gt;
On entering a room, a user sends a QUERY.  Someone will respond with a MEMBER_LIST.  If multiple users try to join simultaneously, they will all be responded to immediately.&lt;br /&gt;
&lt;br /&gt;
On receiving a MEMBER_LIST, the new user learns the membership, transcript hash, and sequence number for the QUERY message.  To finish joining, the new user sends a JOIN, including a CONFIRM for each existing member.  Each member will respond to her JOIN message with a CONFIRM, containing their current sender key.&lt;br /&gt;
&lt;br /&gt;
The new user is part of the group once her JOIN message is received.  This means that DATA can be sent between group members who have not yet confirmed each other.&lt;br /&gt;
&lt;br /&gt;
[[Category: mpOTR]]&lt;/div&gt;</summary>
		<author><name>Trevor</name></author>	</entry>

	<entry>
		<id>https://learn.equalit.ie/wiki/Np1sec/SenderKeys</id>
		<title>Np1sec/SenderKeys</title>
		<link rel="alternate" type="text/html" href="https://learn.equalit.ie/wiki/Np1sec/SenderKeys"/>
				<updated>2014-09-08T05:27:02Z</updated>
		
		<summary type="html">&lt;p&gt;Trevor: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Security Goals =&lt;br /&gt;
&lt;br /&gt;
== Transcript consistency ==&lt;br /&gt;
* Recipients are informed of the correct causal order of messages&lt;br /&gt;
* Excessively delayed messages are detected&lt;br /&gt;
&lt;br /&gt;
== Nonblocking join ==&lt;br /&gt;
* Join and leave are treated as messages, so transcript consistency applies (causal order, delays are detected).&lt;br /&gt;
* New users have to &amp;quot;confirm&amp;quot; to existing users to join.&lt;br /&gt;
* Existing users have to &amp;quot;confirm&amp;quot; to the new user shortly after the new user joins (e.g. 1 minute).&lt;br /&gt;
&lt;br /&gt;
= General concepts = &lt;br /&gt;
&lt;br /&gt;
== Room membership ==&lt;br /&gt;
Users can enter and leave the room, as signalled by presence messages from the server (USER_ENTERED, USER_LEFT).&lt;br /&gt;
&lt;br /&gt;
Users can join the room's conversation by sending a JOIN message.&lt;br /&gt;
&lt;br /&gt;
Users can only leave the conversation if the server says they left the room.&lt;br /&gt;
&lt;br /&gt;
== Sender keys and Signing keys ==&lt;br /&gt;
When a new user joins, she generates a new AES256 key (her &amp;quot;sender key&amp;quot;) and Ed25519 key (her &amp;quot;signing key&amp;quot;).  She then sends these keys to existing members, encrypted under the &amp;quot;pairwise keys&amp;quot; from pairwise key agreements.  This allows subsequent messages to be encrypted-and-signed once, instead of N times with pairwise keys.&lt;br /&gt;
&lt;br /&gt;
Every time a message is encrypted or decrypted with a sender key, the key is updated to provide forward secrecy:&lt;br /&gt;
&lt;br /&gt;
sender_key = HMAC-SHA256(prev_sender_key, &amp;quot;0&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
== Server order ==&lt;br /&gt;
All clients see the same message order from the server.  All messages are sent to all users.  Aside from the presence messages sent by the server, messages are sent by users.&lt;br /&gt;
&lt;br /&gt;
All messages in a room have a unique sequence number (0, 1, ...).  Sequence numbers are implicit, as the server may not be aware of them (e.g. XMPP MUC).&lt;br /&gt;
&lt;br /&gt;
A new user synchronizes his view of sequence numbers via the QUERY / MEMBER_LIST messages (see below).&lt;br /&gt;
&lt;br /&gt;
== Causal order ==&lt;br /&gt;
Every user-sent message specifies a &amp;quot;parent&amp;quot; sequence number which is the last message the user received before sending it.  Note:&lt;br /&gt;
* If Alice sends messages (A,B) in a row, A will not be B's parent unless Alice waits till A is received back from the server.&lt;br /&gt;
* The parent of a message is different from the &amp;quot;previous&amp;quot; message in the server's ordering, e.g. in a &amp;quot;simultaneous send&amp;quot; case two messages will have the same parent.&lt;br /&gt;
&lt;br /&gt;
Due to server ordering, the sender of message i must have seen all&lt;br /&gt;
messages from 0...i's parent.  Thus, every user-sent message i has a membership set, determined by the JOIN / USER_LEFT messages from 0...i's parent.&lt;br /&gt;
&lt;br /&gt;
== Transcript hashes ==&lt;br /&gt;
Every message specifies its parent's sequence number.  Some messages also specify a transcript hash of that parent and all prior messages.  The hash also covers the sender_key for each message (set to zeros for cleartext messages):&lt;br /&gt;
&lt;br /&gt;
H(parent) = SHA256(sender_key[parent] || ciphertext[parent] || H(parent-1))&lt;br /&gt;
&lt;br /&gt;
== Timing ==&lt;br /&gt;
Timing rules can trigger errors based on some assumed constants:&lt;br /&gt;
&lt;br /&gt;
* MAX_RTT - this is the maximum time it should take for a sent message to arrive at all parties.  If you send a message and haven't received it back within MAX_RTT, something is wrong.&lt;br /&gt;
&lt;br /&gt;
* MAX_RTD - this is the maximum difference in time when a message arrives at all parties.  If you receive a message that's not a successor of a message (X) you received more than MAX_RTD + MAX_RTT time ago, something is wrong.  (This is because message X might have arrived at the other party more than MAX_RTD after you saw it, and the other party's message might have taken MAX_RTT to reach you.  But after MAX_RTD + MAX_RTT, there's no excuse for the other party not to have seen X).&lt;br /&gt;
&lt;br /&gt;
* MAX_CONFIRM - this is the maximum time an existing member may spend after receiving a new user's JOIN message before sending a CONFIRM message in response.  If the new user hasn't received CONFIRM messages from existing membership within 2*MAX_RTT + MAX_CONFIRM, something is wrong.&lt;br /&gt;
&lt;br /&gt;
= Messages = &lt;br /&gt;
&lt;br /&gt;
== Generic structures ==&lt;br /&gt;
&lt;br /&gt;
=== Certificate ===&lt;br /&gt;
* The user's Curve25519 identity public key&lt;br /&gt;
* The user's Curve25519 ephemeral public key&lt;br /&gt;
* An Ed25519 signature from the identity key over the ephemeral key&lt;br /&gt;
   (Ed25519 signatures can be produced from Curve25519 keys)&lt;br /&gt;
&lt;br /&gt;
== Server messages ==&lt;br /&gt;
&lt;br /&gt;
=== USER_ENTERED, USER_LEFT ===&lt;br /&gt;
* &amp;quot;Presence&amp;quot; messages sent in clear by the server to indicate a user has entered or left the room&lt;br /&gt;
&lt;br /&gt;
== User messages ==&lt;br /&gt;
&lt;br /&gt;
=== QUERY ===&lt;br /&gt;
* Contains a nonce&lt;br /&gt;
* Requests a MEMBER_LIST&lt;br /&gt;
&lt;br /&gt;
=== MEMBER_LIST ===&lt;br /&gt;
* Contains the sequence number and nonce of the QUERY it's responding to&lt;br /&gt;
* Contains the transcript hash for the QUERY&lt;br /&gt;
* Contains a certificate for each member as of the QUERY&lt;br /&gt;
&lt;br /&gt;
=== JOIN ===&lt;br /&gt;
* Contains a certificate for the new member&lt;br /&gt;
&lt;br /&gt;
=== CONFIRM ===&lt;br /&gt;
* Encrypts-and-confirms an AES256 &amp;quot;sender key&amp;quot; and Ed25519 &amp;quot;signing key&amp;quot; from one member to another&lt;br /&gt;
* Uses pairwise TripleDH between sender and recipient keys, i.e.&lt;br /&gt;
   HASH( DH(A_id, B_eph) || DH(A_eph, B_id) || DH(A_eph, B_eph) )&lt;br /&gt;
* Contains the sequence number for its parent&lt;br /&gt;
* The transcript hash and membership of its parent is included as &amp;quot;additional authenticated data&amp;quot;&lt;br /&gt;
&lt;br /&gt;
=== DATA === &lt;br /&gt;
* Encrypted under the sender's &amp;quot;sender key&amp;quot;&lt;br /&gt;
* Ed25519 signature from the sender's ephemeral public key&lt;br /&gt;
* Contains the sequence number for its parent&lt;br /&gt;
* The transcript hash and membership of its parent is included as &amp;quot;additional authenticated data&amp;quot;&lt;br /&gt;
&lt;br /&gt;
= Algorithms = &lt;br /&gt;
&lt;br /&gt;
== Blocking Join ==&lt;br /&gt;
On entering a room, a user sends a QUERY.  Someone will respond with a MEMBER_LIST.  If two users try to join simultaneously, the second QUERY will not be responded to until the first user has finished joining.&lt;br /&gt;
&lt;br /&gt;
On receiving a MEMBER_LIST, the new user learns the membership, transcript hash, and sequence number for the QUERY message.  To finish joining, the new user sends a JOIN, including a CONFIRM for each existing member.  Each member will respond to her JOIN message with a CONFIRM, containing a new sender key.&lt;br /&gt;
&lt;br /&gt;
Until the new user has finished joining, existing members continue exchanging DATA with their old sender keys.  Once the last confirmation has been received, existing users switch to their new sender keys.&lt;br /&gt;
&lt;br /&gt;
Once the new user has received all CONFIRM messages from the existing membership, she is successfully joined.  If other users sent a QUERY in the meantime, the next one will be responded to with a MEMBER_LIST.&lt;br /&gt;
&lt;br /&gt;
== Nonblocking Join ==&lt;br /&gt;
On entering a room, a user sends a QUERY.  Someone will respond with a MEMBER_LIST.  If multiple users try to join simultaneously, they will all be responded to immediately.&lt;br /&gt;
&lt;br /&gt;
On receiving a MEMBER_LIST, the new user learns the membership, transcript hash, and sequence number for the QUERY message.  To finish joining, the new user sends a JOIN, including a CONFIRM for each existing member.  Each member will respond to her JOIN message with a CONFIRM, containing their current sender key.&lt;br /&gt;
&lt;br /&gt;
The new user is part of the group once her JOIN message is received.  This means that DATA can be sent between group members who have not yet confirmed each other.&lt;br /&gt;
&lt;br /&gt;
[[Category: mpOTR]]&lt;/div&gt;</summary>
		<author><name>Trevor</name></author>	</entry>

	<entry>
		<id>https://learn.equalit.ie/wiki/Np1sec/SenderKeys</id>
		<title>Np1sec/SenderKeys</title>
		<link rel="alternate" type="text/html" href="https://learn.equalit.ie/wiki/Np1sec/SenderKeys"/>
				<updated>2014-09-08T05:25:54Z</updated>
		
		<summary type="html">&lt;p&gt;Trevor: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Security Goals =&lt;br /&gt;
&lt;br /&gt;
== Transcript consistency ==&lt;br /&gt;
* Recipients are informed of the correct causal order of messages&lt;br /&gt;
* Excessively delayed messages are detected&lt;br /&gt;
&lt;br /&gt;
== Nonblocking join ==&lt;br /&gt;
* Join and leave are treated as messages, so transcript consistency applies (causal order, delays are detected).&lt;br /&gt;
* New users have to &amp;quot;confirm&amp;quot; to existing users to join.&lt;br /&gt;
* Existing users have to &amp;quot;confirm&amp;quot; to the new user shortly after the new user joins (e.g. 1 minute).&lt;br /&gt;
&lt;br /&gt;
= General concepts = &lt;br /&gt;
&lt;br /&gt;
== Room membership ==&lt;br /&gt;
Users can enter and leave the room, as signalled by presence messages from the server (USER_ENTERED, USER_LEFT).&lt;br /&gt;
&lt;br /&gt;
Users can join the room's conversation by sending a JOIN message.&lt;br /&gt;
&lt;br /&gt;
Users can only leave the conversation if the server says they left the room.&lt;br /&gt;
&lt;br /&gt;
== Sender keys and Signing keys ==&lt;br /&gt;
When a new user joins, she generates a new AES256 key (her &amp;quot;sender key&amp;quot;) and Ed25519 key (her &amp;quot;signing key&amp;quot;).  She then sends these keys to existing members, encrypted under the &amp;quot;pairwise keys&amp;quot; from pairwise key agreements.  This allows subsequent messages to be encrypted-and-signed once, instead of N times with pairwise keys.&lt;br /&gt;
&lt;br /&gt;
Every time a message is encrypted or decrypted with a sender key, the key is updated to provide forward secrecy:&lt;br /&gt;
&lt;br /&gt;
sender_key = HMAC-SHA256(prev_sender_key, &amp;quot;0&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
== Server order ==&lt;br /&gt;
All clients see the same message order from the server.  All messages are sent to all users.  Aside from the presence messages sent by the server, messages are sent by users.&lt;br /&gt;
&lt;br /&gt;
All messages in a room have a unique sequence number (0, 1, ...).  Sequence numbers are implicit, as the server may not be aware of them (e.g. XMPP MUC).&lt;br /&gt;
&lt;br /&gt;
A new user synchronizes his view of sequence numbers via the QUERY / MEMBER_LIST messages (see below).&lt;br /&gt;
&lt;br /&gt;
== Causal order ==&lt;br /&gt;
Every user-sent message specifies a &amp;quot;parent&amp;quot; sequence number which is the last message the user received before sending it.  Note:&lt;br /&gt;
* If Alice sends messages (A,B) in a row, A will not be B's parent unless Alice waits till A is received back from the server.&lt;br /&gt;
* The parent of a message is different from the &amp;quot;previous&amp;quot; message in the server's ordering, e.g. in a &amp;quot;simultaneous send&amp;quot; case two messages will have the same parent.&lt;br /&gt;
&lt;br /&gt;
Due to server ordering, the sender of message i must have seen all&lt;br /&gt;
messages from 0...i's parent.  Thus, every user-sent message i has a membership set, determined by the JOIN / USER_LEFT messages from 0...i's parent.&lt;br /&gt;
&lt;br /&gt;
== Transcript hashes ==&lt;br /&gt;
Every message specifies its parent's sequence number.  Some messages also specify a transcript hash of that parent and all prior messages.  The hash also covers the sender_key for each message (set to zeros for cleartext messages):&lt;br /&gt;
&lt;br /&gt;
H(parent) = SHA256(sender_key[parent] || ciphertext[parent] || H(parent-1))&lt;br /&gt;
&lt;br /&gt;
== Timing ==&lt;br /&gt;
Timing rules can trigger errors based on some assumed constants:&lt;br /&gt;
&lt;br /&gt;
* MAX_RTT - this is the maximum time it should take for a sent message to arrive at all parties.  If you send a message and haven't received it back within MAX_RTT, something is wrong.&lt;br /&gt;
&lt;br /&gt;
* MAX_RTD - this is the maximum difference in time when a message arrives at all parties.  If you receive a message that's not a successor of a message (X) you received more than MAX_RTD + MAX_RTT time ago, something is wrong.  (This is because message X might have arrived at the other party more than MAX_RTD after you saw it, and the other party's message might have taken MAX_RTT to reach you.  But after MAX_RTD + MAX_RTT, there's no excuse for the other party not to have seen X).&lt;br /&gt;
&lt;br /&gt;
* MAX_CONFIRM - this is the maximum time an existing member may spend after receiving a new user's JOIN message before sending a CONFIRM message in response.  If the new user hasn't received CONFIRM messages from existing membership within 2*MAX_RTT + MAX_CONFIRM, something is wrong.&lt;br /&gt;
&lt;br /&gt;
= Messages = &lt;br /&gt;
&lt;br /&gt;
== Generic structures ==&lt;br /&gt;
&lt;br /&gt;
=== Certificate ===&lt;br /&gt;
* The user's Curve25519 identity public key&lt;br /&gt;
* The user's Curve25519 ephemeral public key&lt;br /&gt;
* An Ed25519 signature from the identity key over the ephemeral key&lt;br /&gt;
   (Ed25519 signatures can be produced from Curve25519 keys)&lt;br /&gt;
&lt;br /&gt;
== Server messages ==&lt;br /&gt;
&lt;br /&gt;
=== USER_ENTERED, USER_LEFT ===&lt;br /&gt;
* &amp;quot;Presence&amp;quot; messages sent in clear by the server to indicate a user has entered or left the room&lt;br /&gt;
&lt;br /&gt;
== User messages ==&lt;br /&gt;
&lt;br /&gt;
=== QUERY ===&lt;br /&gt;
* Contains a nonce&lt;br /&gt;
* Requests a MEMBER_LIST&lt;br /&gt;
&lt;br /&gt;
=== MEMBER_LIST ===&lt;br /&gt;
* Contains the sequence number and nonce of the QUERY it's responding to&lt;br /&gt;
* Contains the transcript hash for the QUERY&lt;br /&gt;
* Contains a certificate for each member at the time of the QUERY&lt;br /&gt;
&lt;br /&gt;
=== JOIN ===&lt;br /&gt;
* Contains a certificate for the new member&lt;br /&gt;
&lt;br /&gt;
=== CONFIRM ===&lt;br /&gt;
* Encrypts-and-confirms an AES256 &amp;quot;sender key&amp;quot; and Ed25519 &amp;quot;signing key&amp;quot; from one member to another&lt;br /&gt;
* Uses pairwise TripleDH between sender and recipient keys, i.e.&lt;br /&gt;
   HASH( DH(A_id, B_eph) || DH(A_eph, B_id) || DH(A_eph, B_eph) )&lt;br /&gt;
* Contains the sequence number for its parent&lt;br /&gt;
* The transcript hash and membership of its parent is included as &amp;quot;additional authenticated data&amp;quot;&lt;br /&gt;
&lt;br /&gt;
=== DATA === &lt;br /&gt;
* Encrypted under the sender's &amp;quot;sender key&amp;quot;&lt;br /&gt;
* Ed25519 signature from the sender's ephemeral public key&lt;br /&gt;
* Contains the sequence number for its parent&lt;br /&gt;
* The transcript hash and membership of its parent is included as &amp;quot;additional authenticated data&amp;quot;&lt;br /&gt;
&lt;br /&gt;
= Algorithms = &lt;br /&gt;
&lt;br /&gt;
== Blocking Join ==&lt;br /&gt;
On entering a room, a user sends a QUERY.  Someone will respond with a MEMBER_LIST.  If two users try to join simultaneously, the second QUERY will not be responded to until the first user has finished joining.&lt;br /&gt;
&lt;br /&gt;
On receiving a MEMBER_LIST, the new user learns the membership, transcript hash, and sequence number for the QUERY message.  To finish joining, the new user sends a JOIN, including a CONFIRM for each existing member.  Each member will respond to her JOIN message with a CONFIRM, containing a new sender key.&lt;br /&gt;
&lt;br /&gt;
Until the new user has finished joining, existing members continue exchanging DATA with their old sender keys.  Once the last confirmation has been received, existing users switch to their new sender keys.&lt;br /&gt;
&lt;br /&gt;
Once the new user has received all CONFIRM messages from the existing membership, she is successfully joined.  If other users sent a QUERY in the meantime, the next one will be responded to with a MEMBER_LIST.&lt;br /&gt;
&lt;br /&gt;
== Nonblocking Join ==&lt;br /&gt;
On entering a room, a user sends a QUERY.  Someone will respond with a MEMBER_LIST.  If multiple users try to join simultaneously, they will all be responded to immediately.&lt;br /&gt;
&lt;br /&gt;
On receiving a MEMBER_LIST, the new user learns the membership, transcript hash, and sequence number for the QUERY message.  To finish joining, the new user sends a JOIN, including a CONFIRM for each existing member.  Each member will respond to her JOIN message with a CONFIRM, containing their current sender key.&lt;br /&gt;
&lt;br /&gt;
The new user is part of the group once her JOIN message is received.  This means that DATA can be sent between group members who have not yet confirmed each other.&lt;br /&gt;
&lt;br /&gt;
[[Category: mpOTR]]&lt;/div&gt;</summary>
		<author><name>Trevor</name></author>	</entry>

	<entry>
		<id>https://learn.equalit.ie/wiki/Np1sec/SenderKeys</id>
		<title>Np1sec/SenderKeys</title>
		<link rel="alternate" type="text/html" href="https://learn.equalit.ie/wiki/Np1sec/SenderKeys"/>
				<updated>2014-09-08T05:03:47Z</updated>
		
		<summary type="html">&lt;p&gt;Trevor: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Security Goals =&lt;br /&gt;
&lt;br /&gt;
== Transcript consistency ==&lt;br /&gt;
* Recipients are informed of the correct causal order of messages&lt;br /&gt;
* Excessively delayed messages are detected&lt;br /&gt;
&lt;br /&gt;
== Nonblocking join ==&lt;br /&gt;
* Join and leave are treated as messages, so transcript consistency applies (causal order, delays are detected).&lt;br /&gt;
* New users have to &amp;quot;confirm&amp;quot; to existing users to join.&lt;br /&gt;
* Existing users have to &amp;quot;confirm&amp;quot; to the new user shortly after the new user joins (e.g. 1 minute).&lt;br /&gt;
&lt;br /&gt;
= General concepts = &lt;br /&gt;
&lt;br /&gt;
== Room membership ==&lt;br /&gt;
Users can enter and leave the room, as signalled by presence messages from the server (USER_ENTERED, USER_LEFT).&lt;br /&gt;
&lt;br /&gt;
Users can join the room's conversation by sending a JOIN message.&lt;br /&gt;
&lt;br /&gt;
Users can only leave the conversation if the server says they left the room.&lt;br /&gt;
&lt;br /&gt;
== Sender keys and Signing keys ==&lt;br /&gt;
When a new user joins, she generates a new AES256 key (her &amp;quot;sender key&amp;quot;) and Ed25519 key (her &amp;quot;signing key&amp;quot;).  She then sends these keys to existing members, encrypted under the &amp;quot;pairwise keys&amp;quot; from pairwise key agreements.  This allows subsequent messages to be encrypted-and-signed once, instead of N times with pairwise keys.&lt;br /&gt;
&lt;br /&gt;
Every time a message is encrypted or decrypted with a sender key, the key is updated to provide forward secrecy:&lt;br /&gt;
&lt;br /&gt;
sender_key = HMAC-SHA256(prev_sender_key, &amp;quot;0&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
== Server order ==&lt;br /&gt;
All clients see the same message order from the server.  All messages are sent to all users.  Aside from the presence messages sent by the server, messages are sent by users.&lt;br /&gt;
&lt;br /&gt;
All messages in a room have a unique sequence number (0, 1, ...).  Sequence numbers are implicit, as the server may not be aware of them (e.g. XMPP MUC).&lt;br /&gt;
&lt;br /&gt;
A new user synchronizes his view of sequence numbers via the QUERY / MEMBER_LIST messages (see below).&lt;br /&gt;
&lt;br /&gt;
== Causal order ==&lt;br /&gt;
Every user-sent message specifies a &amp;quot;parent&amp;quot; sequence number which is the last message the user received before sending it.  Note:&lt;br /&gt;
* If Alice sends messages (A,B) in a row, A will not be B's parent unless Alice waits till A is received back from the server.&lt;br /&gt;
* The parent of a message is different from the &amp;quot;previous&amp;quot; message in the server's ordering, e.g. in a &amp;quot;simultaneous send&amp;quot; case two messages will have the same parent.&lt;br /&gt;
&lt;br /&gt;
Due to server ordering, the sender of message i must have seen all&lt;br /&gt;
messages from 0...i's parent.  Thus, every user-sent message i has a membership set, determined by the JOIN / USER_LEFT messages from 0...i's parent.&lt;br /&gt;
&lt;br /&gt;
== Transcript hashes ==&lt;br /&gt;
Every message specifies its parent's sequence number.  Some messages also specify a transcript hash of that parent and all prior messages.  The hash also covers the sender_key for each message (set to zeros for cleartext messages):&lt;br /&gt;
&lt;br /&gt;
H(parent) = SHA256(sender_key[parent] || ciphertext[parent] || H(parent-1))&lt;br /&gt;
&lt;br /&gt;
== Timing ==&lt;br /&gt;
Timing rules can trigger errors based on some assumed constants:&lt;br /&gt;
&lt;br /&gt;
* MAX_RTT - this is the maximum time it should take for a sent message to arrive at all parties.  If you send a message and haven't received it back within MAX_RTT, something is wrong.&lt;br /&gt;
&lt;br /&gt;
* MAX_RTD - this is the maximum difference in time when a message arrives at all parties.  If you receive a message that's not a successor of a message (X) you received more than MAX_RTD + MAX_RTT time ago, something is wrong.  (This is because message X might have arrived at the other party more than MAX_RTD after you saw it, and the other party's message might have taken MAX_RTT to reach you.  But after MAX_RTD + MAX_RTT, there's no excuse for the other party not to have seen X).&lt;br /&gt;
&lt;br /&gt;
* MAX_CONFIRM - this is the maximum time an existing member may spend after receiving a new user's JOIN message before sending a CONFIRM message in response.  If the new user hasn't received CONFIRM messages from existing membership within 2*MAX_RTT + MAX_CONFIRM, something is wrong.&lt;br /&gt;
&lt;br /&gt;
= Messages = &lt;br /&gt;
&lt;br /&gt;
== Generic structures ==&lt;br /&gt;
&lt;br /&gt;
=== Certificate ===&lt;br /&gt;
* The user's Curve25519 identity public key&lt;br /&gt;
* The user's Curve25519 ephemeral public key&lt;br /&gt;
* An Ed25519 signature from the identity key over the ephemeral key&lt;br /&gt;
   (Ed25519 signatures can be produced from Curve25519 keys)&lt;br /&gt;
&lt;br /&gt;
== Server messages ==&lt;br /&gt;
&lt;br /&gt;
=== USER_ENTERED, USER_LEFT ===&lt;br /&gt;
* &amp;quot;Presence&amp;quot; messages sent in clear by the server to indicate a user has entered or left the room&lt;br /&gt;
&lt;br /&gt;
== Cleartext messages from users ==&lt;br /&gt;
&lt;br /&gt;
=== QUERY ===&lt;br /&gt;
* Contains a nonce&lt;br /&gt;
* Requests anyone to send a MEMBER_LIST&lt;br /&gt;
&lt;br /&gt;
=== MEMBER_LIST ===&lt;br /&gt;
* Lists the sequence number and nonce of the QUERY it's responding to &lt;br /&gt;
* Lists the certificate for each member of its parent&lt;br /&gt;
&lt;br /&gt;
=== JOIN ===&lt;br /&gt;
* Lists the certificate for the new member&lt;br /&gt;
&lt;br /&gt;
== Encrypted messages ==&lt;br /&gt;
&lt;br /&gt;
=== CONFIRM ===&lt;br /&gt;
* Encrypts-and-confirms an AES256 &amp;quot;sender key&amp;quot; and Ed25519 &amp;quot;signing key&amp;quot; from one member to another&lt;br /&gt;
* Uses pairwise TripleDH between sender and recipient keys, i.e.&lt;br /&gt;
   HASH( DH(A_id, B_eph) || DH(A_eph, B_id) || DH(A_eph, B_eph) )&lt;br /&gt;
* Contains a transcript hash&lt;br /&gt;
&lt;br /&gt;
=== DATA === &lt;br /&gt;
* Encrypted under the sender's &amp;quot;sender key&amp;quot;&lt;br /&gt;
* Contains a transcript hash&lt;br /&gt;
* Ed25519 signature from the sender's ephemeral public key&lt;br /&gt;
&lt;br /&gt;
= Algorithms = &lt;br /&gt;
&lt;br /&gt;
== Blocking Join ==&lt;br /&gt;
On entering a room, a user sends a QUERY.  Someone will respond with a MEMBER_LIST.  If two users try to join simultaneously, the second QUERY will not be responded to until the first user has finished joining.&lt;br /&gt;
&lt;br /&gt;
On receiving a MEMBER_LIST, the new user learns the room's membership and sequence numbers.  To finish joining, the new user sends a JOIN, including a CONFIRM for each existing member.  Each member will respond to her JOIN message with a CONFIRM, containing a new sender key.&lt;br /&gt;
&lt;br /&gt;
Until the new user has finished joining, existing members continue exchanging DATA with their old sender keys.  Once the last confirmation has been received, existing users switch to their new sender keys.&lt;br /&gt;
&lt;br /&gt;
Once the new user has received all CONFIRM messages from the existing membership, she is successfully joined.  If other users sent a QUERY in the meantime, the next one will be responded to with a MEMBER_LIST.&lt;br /&gt;
&lt;br /&gt;
== Nonblocking Join ==&lt;br /&gt;
On entering a room, a user sends a QUERY.  Someone will respond with a MEMBER_LIST.  If multiple users try to join simultaneously, they will all be responded to immediately.&lt;br /&gt;
&lt;br /&gt;
On receiving a MEMBER_LIST, the new user learns the room's membership and sequence numbers.  To finish joining, the new user sends a JOIN, including a CONFIRM for each existing member.  Each member will respond to her JOIN message with a CONFIRM, containing their current sender key.&lt;br /&gt;
&lt;br /&gt;
The new user is part of the group once her JOIN message is received.  This means that DATA can be sent between group members who have not yet confirmed each other.&lt;br /&gt;
&lt;br /&gt;
[[Category: mpOTR]]&lt;/div&gt;</summary>
		<author><name>Trevor</name></author>	</entry>

	<entry>
		<id>https://learn.equalit.ie/wiki/Np1sec/SenderKeys</id>
		<title>Np1sec/SenderKeys</title>
		<link rel="alternate" type="text/html" href="https://learn.equalit.ie/wiki/Np1sec/SenderKeys"/>
				<updated>2014-09-08T04:55:53Z</updated>
		
		<summary type="html">&lt;p&gt;Trevor: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Security Goals =&lt;br /&gt;
&lt;br /&gt;
== Transcript consistency ==&lt;br /&gt;
* Recipients are informed of the correct causal order of messages&lt;br /&gt;
* Excessively delayed messages are detected&lt;br /&gt;
&lt;br /&gt;
== Nonblocking join ==&lt;br /&gt;
* Join and leave are treated as messages, so transcript consistency applies (causal order, delays are detected).&lt;br /&gt;
* New users have to &amp;quot;confirm&amp;quot; to existing users to join.&lt;br /&gt;
* Existing users have to &amp;quot;confirm&amp;quot; to the new user shortly after the new user joins (e.g. 1 minute).&lt;br /&gt;
&lt;br /&gt;
= General concepts = &lt;br /&gt;
&lt;br /&gt;
== Room membership ==&lt;br /&gt;
Users can enter and leave the room, as signalled by presence messages from the server (USER_ENTERED, USER_LEFT).&lt;br /&gt;
&lt;br /&gt;
Users can join the room's conversation by sending a JOIN message.&lt;br /&gt;
&lt;br /&gt;
Users can only leave the conversation if the server says they left the room.&lt;br /&gt;
&lt;br /&gt;
== Sender keys and Ephemeral signing keys ==&lt;br /&gt;
When a new user joins, she generates a new AES256 key (her &amp;quot;sender key&amp;quot;) and Ed25519 key (her &amp;quot;signing key&amp;quot;).  She then sends these keys to existing members, encrypted under the &amp;quot;pairwise keys&amp;quot; from pairwise key agreements.  This allows subsequent messages to be encrypted-and-signed once, instead of N times with pairwise keys.&lt;br /&gt;
&lt;br /&gt;
Every time a message is encrypted or decrypted with a sender key, the key is updated to provide forward secrecy:&lt;br /&gt;
&lt;br /&gt;
sender_key = HMAC-SHA256(prev_sender_key, &amp;quot;0&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
== Server order ==&lt;br /&gt;
All clients see the same message order from the server.  All messages are sent to all users.  Aside from the presence messages sent by the server, messages are sent by users.&lt;br /&gt;
&lt;br /&gt;
All messages in a room have a unique sequence number (0, 1, ...).  Sequence numbers are implicit, as the server may not be aware of them (e.g. XMPP MUC).&lt;br /&gt;
&lt;br /&gt;
A new user synchronizes his view of sequence numbers via the QUERY / MEMBER_LIST messages (see below).&lt;br /&gt;
&lt;br /&gt;
== Causal order ==&lt;br /&gt;
Every user-sent message specifies a &amp;quot;parent&amp;quot; sequence number which is the last message the user received before sending it.  Note:&lt;br /&gt;
* If Alice sends messages (A,B) in a row, A will not be B's parent unless Alice waits till A is received back from the server.&lt;br /&gt;
* The parent of a message is different from the &amp;quot;previous&amp;quot; message in the server's ordering, e.g. in a &amp;quot;simultaneous send&amp;quot; case two messages will have the same parent.&lt;br /&gt;
&lt;br /&gt;
Due to server ordering, the sender of message i must have seen all&lt;br /&gt;
messages from 0...i's parent.  Thus, every user-sent message i has a membership set, determined by the JOIN / USER_LEFT messages from 0...i's parent.&lt;br /&gt;
&lt;br /&gt;
== Transcript hashes ==&lt;br /&gt;
Every message specifies its parent's sequence number.  Some messages also specify a transcript hash of that parent and all prior messages.  The hash also covers the sender_key for each message (set to zeros for cleartext messages):&lt;br /&gt;
&lt;br /&gt;
H(parent) = SHA256(sender_key[parent] || ciphertext[parent] || H(parent-1))&lt;br /&gt;
&lt;br /&gt;
== Timing ==&lt;br /&gt;
Timing rules can trigger errors based on some assumed constants:&lt;br /&gt;
&lt;br /&gt;
* MAX_RTT - this is the maximum time it should take for a sent message to arrive at all parties.  If you send a message and haven't received it back within MAX_RTT, something is wrong.&lt;br /&gt;
&lt;br /&gt;
* MAX_RTD - this is the maximum difference in time when a message arrives at all parties.  If you receive a message that's not a successor of a message (X) you received more than MAX_RTD + MAX_RTT time ago, something is wrong.  (This is because message X might have arrived at the other party more than MAX_RTD after you saw it, and the other party's message might have taken MAX_RTT to reach you.  But after MAX_RTD + MAX_RTT, there's no excuse for the other party not to have seen X).&lt;br /&gt;
&lt;br /&gt;
* MAX_CONFIRM - this is the maximum time an existing member may spend after receiving a new user's JOIN message before sending a CONFIRM message in response.  If the new user hasn't received CONFIRM messages from existing membership within 2*MAX_RTT + MAX_CONFIRM, something is wrong.&lt;br /&gt;
&lt;br /&gt;
= Messages = &lt;br /&gt;
&lt;br /&gt;
== Generic structures ==&lt;br /&gt;
&lt;br /&gt;
=== Certificate ===&lt;br /&gt;
* The user's Curve25519 identity public key&lt;br /&gt;
* The user's Curve25519 ephemeral public key&lt;br /&gt;
* An Ed25519 signature from the identity key over the ephemeral key&lt;br /&gt;
   (Ed25519 signatures can be produced from Curve25519 keys)&lt;br /&gt;
&lt;br /&gt;
== Server messages ==&lt;br /&gt;
&lt;br /&gt;
=== USER_ENTERED, USER_LEFT ===&lt;br /&gt;
* &amp;quot;Presence&amp;quot; messages sent in clear by the server to indicate a user has entered or left the room&lt;br /&gt;
&lt;br /&gt;
== Cleartext messages from users ==&lt;br /&gt;
&lt;br /&gt;
=== QUERY ===&lt;br /&gt;
* Contains a nonce&lt;br /&gt;
* Requests anyone to send a MEMBER_LIST&lt;br /&gt;
&lt;br /&gt;
=== MEMBER_LIST ===&lt;br /&gt;
* Lists the sequence number and nonce of the QUERY it's responding to &lt;br /&gt;
* Lists the certificate for each member of its parent&lt;br /&gt;
&lt;br /&gt;
=== JOIN ===&lt;br /&gt;
* Lists the certificate for the new member&lt;br /&gt;
* Contains CONFIRM messages for each member of its parent&lt;br /&gt;
&lt;br /&gt;
== Encrypted messages ==&lt;br /&gt;
&lt;br /&gt;
=== CONFIRM ===&lt;br /&gt;
* Encrypts-and-confirms an AES256 &amp;quot;sender key&amp;quot; from one member to another&lt;br /&gt;
* Uses pairwise TripleDH between sender and recipient keys, i.e.&lt;br /&gt;
   HASH( DH(A_id, B_eph) || DH(A_eph, B_id) || DH(A_eph, B_eph) )&lt;br /&gt;
* Contains a transcript hash&lt;br /&gt;
&lt;br /&gt;
=== DATA === &lt;br /&gt;
* Encrypted under the sender's &amp;quot;sender key&amp;quot;&lt;br /&gt;
* Contains a transcript hash&lt;br /&gt;
* Ed25519 signature from the sender's ephemeral public key&lt;br /&gt;
&lt;br /&gt;
= Algorithms = &lt;br /&gt;
&lt;br /&gt;
== Blocking Join ==&lt;br /&gt;
On entering a room, a user sends a QUERY.  Someone will respond with a MEMBER_LIST.  If two users try to join simultaneously, the second QUERY will not be responded to until the first user has finished joining.&lt;br /&gt;
&lt;br /&gt;
On receiving a MEMBER_LIST, the new user learns the room's membership and sequence numbers.  To finish joining, the new user sends a JOIN, including a CONFIRM for each existing member.  Each member will respond to her JOIN message with a CONFIRM, containing a new sender key.&lt;br /&gt;
&lt;br /&gt;
Until the new user has finished joining, existing members continue exchanging DATA with their old sender keys.  Once the last confirmation has been received, existing users switch to their new sender keys.&lt;br /&gt;
&lt;br /&gt;
Once the new user has received all CONFIRM messages from the existing membership, she is successfully joined.  If other users sent a QUERY in the meantime, the next one will be responded to with a MEMBER_LIST.&lt;br /&gt;
&lt;br /&gt;
== Nonblocking Join ==&lt;br /&gt;
On entering a room, a user sends a QUERY.  Someone will respond with a MEMBER_LIST.  If multiple users try to join simultaneously, they will all be responded to immediately.&lt;br /&gt;
&lt;br /&gt;
On receiving a MEMBER_LIST, the new user learns the room's membership and sequence numbers.  To finish joining, the new user sends a JOIN, including a CONFIRM for each existing member.  Each member will respond to her JOIN message with a CONFIRM, containing their current sender key.&lt;br /&gt;
&lt;br /&gt;
The new user is part of the group once her JOIN message is received.  This means that DATA can be sent between group members who have not yet confirmed each other.&lt;br /&gt;
&lt;br /&gt;
[[Category: mpOTR]]&lt;/div&gt;</summary>
		<author><name>Trevor</name></author>	</entry>

	<entry>
		<id>https://learn.equalit.ie/wiki/Np1sec/SenderKeys</id>
		<title>Np1sec/SenderKeys</title>
		<link rel="alternate" type="text/html" href="https://learn.equalit.ie/wiki/Np1sec/SenderKeys"/>
				<updated>2014-09-08T04:54:38Z</updated>
		
		<summary type="html">&lt;p&gt;Trevor: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Security Goals =&lt;br /&gt;
&lt;br /&gt;
== Transcript consistency ==&lt;br /&gt;
* Recipients are informed of the correct causal order of messages&lt;br /&gt;
* Excessively delayed messages are detected&lt;br /&gt;
&lt;br /&gt;
== Nonblocking join ==&lt;br /&gt;
* Join and leave are treated as messages, so transcript consistency applies (causal order, delays are detected).&lt;br /&gt;
* New users have to &amp;quot;confirm&amp;quot; to existing users to join.&lt;br /&gt;
* Existing users have to &amp;quot;confirm&amp;quot; to the new user shortly after the new user joins (e.g. 1 minute).&lt;br /&gt;
&lt;br /&gt;
= General concepts = &lt;br /&gt;
&lt;br /&gt;
== Room membership ==&lt;br /&gt;
Users can enter and leave the room, as signalled by presence messages from the server (USER_ENTERED, USER_LEFT).&lt;br /&gt;
&lt;br /&gt;
Users can join the room's conversation by sending a JOIN message.&lt;br /&gt;
&lt;br /&gt;
Users can only leave the conversation if the server says they left the room.&lt;br /&gt;
&lt;br /&gt;
== Sender keys and Ephemeral signing keys ==&lt;br /&gt;
When a new user joins, she generates a new AES256 key (her &amp;quot;sender key&amp;quot;) and Ed25519 key (her &amp;quot;signing key&amp;quot;).  She then sends these keys to existing members, encrypted under the &amp;quot;pairwise keys&amp;quot; from pairwise key agreements.  This allows subsequent messages to be encrypted-and-signed once, instead of N times with pairwise keys.&lt;br /&gt;
&lt;br /&gt;
Every time a message is encrypted or decrypted with a sender key, the key is updated to provide forward secrecy:&lt;br /&gt;
&lt;br /&gt;
sender_key = HMAC-SHA256(prev_sender_key, &amp;quot;0&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
== Server order ==&lt;br /&gt;
All clients see the same message order from the server.  All messages are sent to all users.  Aside from the presence messages sent by the server, messages are sent by users.&lt;br /&gt;
&lt;br /&gt;
All messages in a room have a unique sequence number (0, 1, ...).  Sequence numbers are implicit, as the server may not be aware of them (e.g. XMPP MUC).&lt;br /&gt;
&lt;br /&gt;
A new user synchronizes his view of sequence numbers via the QUERY / MEMBER_LIST messages (see below).&lt;br /&gt;
&lt;br /&gt;
== Causal order ==&lt;br /&gt;
Every user-sent message specifies a &amp;quot;parent&amp;quot; sequence number which is the last message the user received before sending it.  Note:&lt;br /&gt;
* If Alice sends messages (A,B) in a row, A will not be B's parent unless Alice waits till A is received back from the server.&lt;br /&gt;
* The parent of a message is different from the &amp;quot;previous&amp;quot; message in the server's ordering, e.g. in a &amp;quot;simultaneous send&amp;quot; case two messages will have the same parent.&lt;br /&gt;
&lt;br /&gt;
Due to server ordering, the sender of message i must have seen all&lt;br /&gt;
messages from 0...i's parent.  Thus, every user-sent message i has a membership set, determined by the JOIN / USER_LEFT messages from 0...i's parent.&lt;br /&gt;
&lt;br /&gt;
== Transcript hashes ==&lt;br /&gt;
Every message specifies its parent's sequence number.  Some messages also specify a transcript hash of that parent and all prior messages.  The hash also covers the sender_key for each message (set to zeros for cleartext messages):&lt;br /&gt;
&lt;br /&gt;
H(parent) = SHA256(sender_key[parent] || ciphertext[parent] || H(parent-1))&lt;br /&gt;
&lt;br /&gt;
== Timing ==&lt;br /&gt;
Timing rules can trigger errors based on some assumed constants:&lt;br /&gt;
&lt;br /&gt;
* MAX_RTT - this is the maximum time it should take for a sent message to arrive at all parties.  If you send a message and haven't received it back within MAX_RTT, something is wrong.&lt;br /&gt;
&lt;br /&gt;
* MAX_RTD - this is the maximum difference in time when a message arrives at all parties.  If you receive a message that's not a successor of a message (X) you received more than MAX_RTD + MAX_RTT time ago, something is wrong.  (This is because message X might have arrived at the other party more than MAX_RTD after you saw it, and the other party's message might have taken MAX_RTT to reach you.  But after MAX_RTD + MAX_RTT, there's no excuse for the other party not to have seen X).&lt;br /&gt;
&lt;br /&gt;
* MAX_CONFIRM - this is the maximum time an existing member may spend after receiving a new user's JOIN message before sending a CONFIRM message in response.  If the new user hasn't received CONFIRM messages from existing membership within 2*MAX_RTT + MAX_CONFIRM, something is wrong.&lt;br /&gt;
&lt;br /&gt;
= Messages = &lt;br /&gt;
&lt;br /&gt;
== Generic structures ==&lt;br /&gt;
&lt;br /&gt;
=== Certificate ===&lt;br /&gt;
* The user's Curve25519 identity public key&lt;br /&gt;
* The user's Curve25519 ephemeral public key&lt;br /&gt;
* An Ed25519 signature from the identity key over the ephemeral key&lt;br /&gt;
   (Ed25519 signatures can be produced from Curve25519 keys)&lt;br /&gt;
&lt;br /&gt;
== Server messages ==&lt;br /&gt;
&lt;br /&gt;
=== USER_ENTERED, USER_LEFT ===&lt;br /&gt;
* &amp;quot;Presence&amp;quot; messages sent in clear by the server to indicate a user has entered or left the room&lt;br /&gt;
&lt;br /&gt;
== Cleartext messages from users ==&lt;br /&gt;
&lt;br /&gt;
=== QUERY ===&lt;br /&gt;
* Contains a nonce&lt;br /&gt;
* Requests anyone to send a MEMBER_LIST&lt;br /&gt;
&lt;br /&gt;
=== MEMBER_LIST ===&lt;br /&gt;
* Lists the sequence number and nonce of the QUERY it's responding to &lt;br /&gt;
* Lists the certificate for each member of its parent&lt;br /&gt;
&lt;br /&gt;
=== JOIN ===&lt;br /&gt;
* Lists the certificate for the new member&lt;br /&gt;
* Contains CONFIRM messages for each member of its parent&lt;br /&gt;
&lt;br /&gt;
== Encrypted messages ==&lt;br /&gt;
&lt;br /&gt;
=== CONFIRM ===&lt;br /&gt;
* Encrypts-and-confirms an AES256 &amp;quot;sender key&amp;quot; from one member to another&lt;br /&gt;
* Uses pairwise TripleDH between sender and recipient keys, i.e.&lt;br /&gt;
   HASH( DH(A_id, B_eph) || DH(A_eph, B_id) || DH(A_eph, B_eph) )&lt;br /&gt;
* Contains a transcript hash&lt;br /&gt;
&lt;br /&gt;
=== DATA === &lt;br /&gt;
* Encrypted under the sender's &amp;quot;sender key&amp;quot;&lt;br /&gt;
* Contains a transcript hash&lt;br /&gt;
* Ed25519 signature from the sender's ephemeral public key&lt;br /&gt;
&lt;br /&gt;
= Algorithms = &lt;br /&gt;
&lt;br /&gt;
== Blocking Join ==&lt;br /&gt;
On entering a room, a user sends a QUERY.  Someone will respond with a MEMBER_LIST.  If two users try to join simultaneously, the second QUERY will not be responded to until the first user has finished joining.&lt;br /&gt;
&lt;br /&gt;
On receiving a MEMBER_LIST, the new user learns the room's membership and sequence numbers.  To finish joining, the new user sends a JOIN, including a CONFIRM for each existing member.  Each member will respond to her JOIN message with a CONFIRM, containing a new sender key.&lt;br /&gt;
&lt;br /&gt;
Until the new user has finished joining, existing members continue exchanging DATA with their old sender keys.  Once the last confirmation has been received, existing users switch to their new sender key.&lt;br /&gt;
&lt;br /&gt;
Once the present user has received all CONFIRM messages from the existing membership, she is successfully joined.  If other users sent a QUERY in the meantime, the next one will be responded to with a MEMBER_LIST.&lt;br /&gt;
&lt;br /&gt;
== Nonblocking Join ==&lt;br /&gt;
On entering a room, a user sends a QUERY.  Someone will respond with a MEMBER_LIST.  If multiple users try to join simultaneously, they will all be responded to immediately.&lt;br /&gt;
&lt;br /&gt;
On receiving a MEMBER_LIST, the new user learns the room's membership and sequence numbers.  To finish joining, the new user sends a JOIN, including a CONFIRM for each existing member.  Each member will respond to her JOIN message with a CONFIRM, containing their current sender key.&lt;br /&gt;
&lt;br /&gt;
The new user is part of the group once her JOIN message is received.  This means that DATA can be sent between group members who have not yet confirmed each other.&lt;br /&gt;
&lt;br /&gt;
[[Category: mpOTR]]&lt;/div&gt;</summary>
		<author><name>Trevor</name></author>	</entry>

	<entry>
		<id>https://learn.equalit.ie/wiki/Np1sec/SenderKeys</id>
		<title>Np1sec/SenderKeys</title>
		<link rel="alternate" type="text/html" href="https://learn.equalit.ie/wiki/Np1sec/SenderKeys"/>
				<updated>2014-09-08T04:23:54Z</updated>
		
		<summary type="html">&lt;p&gt;Trevor: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Security Goals =&lt;br /&gt;
&lt;br /&gt;
== Transcript consistency ==&lt;br /&gt;
* Recipients are informed of the correct causal order of messages&lt;br /&gt;
* Excessively delayed messages are detected&lt;br /&gt;
&lt;br /&gt;
== Nonblocking join ==&lt;br /&gt;
* Join and leave are treated as messages, so transcript consistency applies (causal order, delays are detected).&lt;br /&gt;
* New users have to &amp;quot;confirm&amp;quot; to existing users to join.&lt;br /&gt;
* Existing users have to &amp;quot;confirm&amp;quot; to the new user shortly after the new user joins (e.g. 1 minute).&lt;br /&gt;
&lt;br /&gt;
= General concepts = &lt;br /&gt;
&lt;br /&gt;
== Room membership ==&lt;br /&gt;
Users can enter and leave the room, as signalled by presence messages from the server (USER_ENTERED, USER_LEFT).&lt;br /&gt;
&lt;br /&gt;
Users can join the room's conversation by sending a JOIN message.&lt;br /&gt;
&lt;br /&gt;
Users can only leave the conversation if the server says they left the room.&lt;br /&gt;
&lt;br /&gt;
== Sender keys and Ephemeral signing keys ==&lt;br /&gt;
When a new user joins, she generates a new AES256 key (her &amp;quot;sender key&amp;quot;) and Ed25519 key (her &amp;quot;signing key&amp;quot;).  She then sends these keys to existing members, encrypted under the &amp;quot;pairwise keys&amp;quot; from pairwise key agreements.  This allows subsequent messages to be encrypted-and-signed once, instead of N times with pairwise keys.&lt;br /&gt;
&lt;br /&gt;
Every time a message is encrypted or decrypted with a sender key, the key is updated to provide forward secrecy:&lt;br /&gt;
&lt;br /&gt;
sender_key = HMAC-SHA256(prev_sender_key, &amp;quot;0&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
== Server order ==&lt;br /&gt;
All clients see the same message order from the server.  All messages are sent to all users.  Aside from the presence messages sent by the server, messages are sent by users.&lt;br /&gt;
&lt;br /&gt;
All messages in a room have a unique sequence number (0, 1, ...).  Sequence numbers are implicit, as the server may not be aware of them (e.g. XMPP MUC).&lt;br /&gt;
&lt;br /&gt;
A new user synchronizes his view of sequence numbers via the QUERY / MEMBER_LIST messages (see below).&lt;br /&gt;
&lt;br /&gt;
== Causal order ==&lt;br /&gt;
Every user-sent message specifies a &amp;quot;parent&amp;quot; sequence number which is the last message the user received before sending it.  Note:&lt;br /&gt;
* If Alice sends messages (A,B) in a row, A will not be B's parent unless Alice waits till A is received back from the server.&lt;br /&gt;
* The parent of a message is different from the &amp;quot;previous&amp;quot; message in the server's ordering, e.g. in a &amp;quot;simultaneous send&amp;quot; case two messages will have the same parent.&lt;br /&gt;
&lt;br /&gt;
Due to server ordering, the sender of message i must have seen all&lt;br /&gt;
messages from 0...i's parent.  Thus, every user-sent message i has a membership set, determined by the JOIN / USER_LEFT messages from 0...i's parent.&lt;br /&gt;
&lt;br /&gt;
== Transcript hashes ==&lt;br /&gt;
Every message specifies its parent's sequence number.  Some messages also specify a transcript hash of that parent and all prior messages.  The hash also covers the sender_key for each message (set to zeros for cleartext messages):&lt;br /&gt;
&lt;br /&gt;
H(parent) = SHA256(sender_key[parent] || ciphertext[parent] || H(parent-1))&lt;br /&gt;
&lt;br /&gt;
== Timing ==&lt;br /&gt;
Timing rules can trigger errors based on some assumed constants:&lt;br /&gt;
&lt;br /&gt;
* MAX_RTT - this is the maximum time it should take for a sent message to arrive at all parties.  If you send a message and haven't received it back within MAX_RTT, something is wrong.&lt;br /&gt;
&lt;br /&gt;
* MAX_RTD - this is the maximum difference in time when a message arrives at all parties.  If you receive a message that's not a successor of a message (X) you received more than MAX_RTD + MAX_RTT time ago, something is wrong.  (This is because message X might have arrived at the other party more than MAX_RTD after you saw it, and the other party's message might have taken MAX_RTT to reach you.  But after MAX_RTD + MAX_RTT, there's no excuse for the other party not to have seen X).&lt;br /&gt;
&lt;br /&gt;
* MAX_CONFIRM - this is the maximum time an existing member may spend after receiving a new user's JOIN message before sending a CONFIRM message in response.  If the new user hasn't received CONFIRM messages from existing membership within 2*MAX_RTT + MAX_CONFIRM, something is wrong.&lt;br /&gt;
&lt;br /&gt;
= Messages = &lt;br /&gt;
&lt;br /&gt;
== Generic structures ==&lt;br /&gt;
&lt;br /&gt;
=== Certificate ===&lt;br /&gt;
* The user's Curve25519 identity public key&lt;br /&gt;
* The user's Curve25519 ephemeral public key&lt;br /&gt;
* An Ed25519 signature from the identity key over the ephemeral key&lt;br /&gt;
   (Ed25519 signatures can be produced from Curve25519 keys)&lt;br /&gt;
&lt;br /&gt;
== Server messages ==&lt;br /&gt;
&lt;br /&gt;
=== USER_ENTERED, USER_LEFT ===&lt;br /&gt;
* &amp;quot;Presence&amp;quot; messages sent in clear by the server to indicate a user has entered or left the room&lt;br /&gt;
&lt;br /&gt;
== Cleartext messages from users ==&lt;br /&gt;
&lt;br /&gt;
=== QUERY ===&lt;br /&gt;
* Contains a nonce&lt;br /&gt;
* Requests anyone to send a MEMBER_LIST&lt;br /&gt;
&lt;br /&gt;
=== MEMBER_LIST ===&lt;br /&gt;
* Lists the sequence number and nonce of the QUERY it's responding to &lt;br /&gt;
* Lists the certificate for each member of its parent&lt;br /&gt;
&lt;br /&gt;
=== JOIN ===&lt;br /&gt;
* Lists the certificate for the new member&lt;br /&gt;
* Contains CONFIRM messages for each member of its parent&lt;br /&gt;
&lt;br /&gt;
== Encrypted messages ==&lt;br /&gt;
&lt;br /&gt;
=== CONFIRM ===&lt;br /&gt;
* Encrypts-and-confirms an AES256 &amp;quot;sender key&amp;quot; from one member to another&lt;br /&gt;
* Uses pairwise TripleDH between sender and recipient keys, i.e.&lt;br /&gt;
   HASH( DH(A_id, B_eph) || DH(A_eph, B_id) || DH(A_eph, B_eph) )&lt;br /&gt;
* Contains a transcript hash&lt;br /&gt;
&lt;br /&gt;
=== DATA === &lt;br /&gt;
* Encrypted under the sender's &amp;quot;sender key&amp;quot;&lt;br /&gt;
* Contains a transcript hash&lt;br /&gt;
* Ed25519 signature from the sender's ephemeral public key&lt;br /&gt;
&lt;br /&gt;
= Algorithms = &lt;br /&gt;
&lt;br /&gt;
== Nonblocking Join ==&lt;br /&gt;
On entering a room, a user sends a QUERY.  She is present in the room but hasn't yet joined the conversation.  Someone (or multiple parties) will respond with a MEMBER_LIST.&lt;br /&gt;
&lt;br /&gt;
On receiving a MEMBER_LIST, a present user learns the room's membership and sequence numbers, and can keep track of the membership by observing subsequent JOIN / USER_LEFT messages.&lt;br /&gt;
&lt;br /&gt;
To join a room, a present user sends a JOIN, including a CONFIRM for each member in its parent, and expects to receive a CONFIRM from each member shortly.&lt;br /&gt;
&lt;br /&gt;
After sending the JOIN, the user considers herself part of the conversation and can send DATA messages and respond to QUERY messages.  She responds to any subsequent JOINs with a CONFIRM.  If the subsequent JOIN doesn't include a CONFIRM for the user (simultaneous join), then she expects to receive one shortly.&lt;br /&gt;
&lt;br /&gt;
== Blocking Join ==&lt;br /&gt;
As above, except:&lt;br /&gt;
* A user is only added to group membership once all CONFIRMs from her JOIN, and any subsequent CONFIRMS (due to simultaneous join) have been responded to with CONFIRMs.&lt;br /&gt;
* In a simultaneous JOIN case, the JOINs are handled based on the server ordering (earliest first).&lt;br /&gt;
&lt;br /&gt;
Example: Alice and Bob are existing members.  Charlie and Dave send simultaneous JOINs, but the server places Charlie's first.  Alice and Bob send CONFIRM messages to both Charlie and Dave.  Charlie and Dave send CONFIRM messages to each other.  Once Charlie receive Alice and Bob's CONFIRMs, he's part of the group and can send DATA.  Once Dave receives Alice, Bob, and Charlie's CONFIRMs, he's part of the group and can send DATA.&lt;br /&gt;
&lt;br /&gt;
[[Category: mpOTR]]&lt;/div&gt;</summary>
		<author><name>Trevor</name></author>	</entry>

	<entry>
		<id>https://learn.equalit.ie/wiki/Np1sec/SenderKeys</id>
		<title>Np1sec/SenderKeys</title>
		<link rel="alternate" type="text/html" href="https://learn.equalit.ie/wiki/Np1sec/SenderKeys"/>
				<updated>2014-08-26T21:13:54Z</updated>
		
		<summary type="html">&lt;p&gt;Trevor: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Security Goals =&lt;br /&gt;
&lt;br /&gt;
== Transcript consistency ==&lt;br /&gt;
* Recipients are informed of the correct causal order of messages&lt;br /&gt;
* Excessively delayed messages are detected&lt;br /&gt;
&lt;br /&gt;
== Nonblocking join ==&lt;br /&gt;
* Join and leave are treated as messages, so transcript consistency applies (causal order, delays are detected).&lt;br /&gt;
* New users have to &amp;quot;confirm&amp;quot; to existing users to join.&lt;br /&gt;
* Existing users have to &amp;quot;confirm&amp;quot; to the new user shortly after the new user joins (e.g. 1 minute).&lt;br /&gt;
&lt;br /&gt;
= General concepts = &lt;br /&gt;
&lt;br /&gt;
== Room membership ==&lt;br /&gt;
Users can enter and leave the room, as signalled by presence messages from the server (USER_ENTERED, USER_LEFT).&lt;br /&gt;
&lt;br /&gt;
Users can join the room's conversation by sending a JOIN message.&lt;br /&gt;
&lt;br /&gt;
Users can only leave the conversation if the server says they left the room.&lt;br /&gt;
&lt;br /&gt;
(TBD: should users be able to declare that they're leaving, or kick each other out?)&lt;br /&gt;
&lt;br /&gt;
== Sender keys ==&lt;br /&gt;
When a new user joins, she exchanges AES256 &amp;quot;sender keys&amp;quot; with existing members, encrypted under the &amp;quot;pairwise keys&amp;quot; from pairwise key agreements.  This allows subsequent messages to be encrypted once with a sender key, instead of N times with pairwise keys.&lt;br /&gt;
&lt;br /&gt;
Every time a message is encrypted or decrypted with a sender key, the key is updated as:&lt;br /&gt;
&lt;br /&gt;
sender_key = HMAC-SHA256(prev_sender_key, member_list)&lt;br /&gt;
&lt;br /&gt;
This provides forward secrecy and ensures new members can't decrypt messages prior to when they joined.&lt;br /&gt;
&lt;br /&gt;
== Server order ==&lt;br /&gt;
All clients see the same message order from the server.  All messages are sent to all users.  Aside from the presence messages sent by the server, messages are sent by users.&lt;br /&gt;
&lt;br /&gt;
All messages in a room have a unique sequence number (0, 1, ...).  Sequence numbers are implicit, as the server may not be aware of them (e.g. XMPP MUC).&lt;br /&gt;
&lt;br /&gt;
A new user synchronizes his view of sequence numbers via the QUERY / MEMBER_LIST messages (see below).&lt;br /&gt;
&lt;br /&gt;
== Causal order ==&lt;br /&gt;
Every user-sent message specifies a &amp;quot;parent&amp;quot; sequence number which is the last message the user received before sending it.  Note:&lt;br /&gt;
* If Alice sends messages (A,B) in a row, A will not be B's parent unless Alice waits till A is received back from the server.&lt;br /&gt;
* The parent of a message is different from the &amp;quot;previous&amp;quot; message in the server's ordering, e.g. in a &amp;quot;simultaneous send&amp;quot; case two messages will have the same parent.&lt;br /&gt;
&lt;br /&gt;
Due to server ordering, the sender of message i must have seen all&lt;br /&gt;
messages from 0...i's parent.  Thus, every user-sent message i has a membership set, determined by the JOIN / USER_LEFT messages from 0...i's parent.&lt;br /&gt;
&lt;br /&gt;
== Transcript hashes ==&lt;br /&gt;
Every message specifies its parent's sequence number.  Some messages also specify a transcript hash of that parent and all prior messages.  The hash also covers the sender_key for each message (set to zeros for cleartext messages):&lt;br /&gt;
&lt;br /&gt;
H(parent) = SHA256(sender_key[parent] || ciphertext[parent] || H(parent-1))&lt;br /&gt;
&lt;br /&gt;
== Timing ==&lt;br /&gt;
Timing rules can trigger errors based on some assumed constants:&lt;br /&gt;
&lt;br /&gt;
* MAX_RTT - this is the maximum time it should take for a sent message to arrive at all parties.  If you send a message and haven't received it back within MAX_RTT, something is wrong.&lt;br /&gt;
&lt;br /&gt;
* MAX_RTD - this is the maximum difference in time when a message arrives at all parties.  If you receive a message that's not a successor of a message (X) you received more than MAX_RTD + MAX_RTT time ago, something is wrong.  (This is because message X might have arrived at the other party more than MAX_RTD after you saw it, and the other party's message might have taken MAX_RTT to reach you.  But after MAX_RTD + MAX_RTT, there's no excuse for the other party not to have seen X).&lt;br /&gt;
&lt;br /&gt;
* MAX_CONFIRM - this is the maximum time an existing member may spend after receiving a new user's JOIN message before sending a CONFIRM message in response.  If the new user hasn't received CONFIRM messages from existing membership within 2*MAX_RTT + MAX_CONFIRM, something is wrong.&lt;br /&gt;
&lt;br /&gt;
= Messages = &lt;br /&gt;
&lt;br /&gt;
== Generic structures ==&lt;br /&gt;
&lt;br /&gt;
=== Certificate ===&lt;br /&gt;
* The user's Curve25519 identity public key&lt;br /&gt;
* The user's Curve25519 ephemeral public key&lt;br /&gt;
* An Ed25519 signature from the identity key over the ephemeral key&lt;br /&gt;
   (Ed25519 signatures can be produced from Curve25519 keys)&lt;br /&gt;
&lt;br /&gt;
== Server messages ==&lt;br /&gt;
&lt;br /&gt;
=== USER_ENTERED, USER_LEFT ===&lt;br /&gt;
* &amp;quot;Presence&amp;quot; messages sent in clear by the server to indicate a user has entered or left the room&lt;br /&gt;
&lt;br /&gt;
== Cleartext messages from users ==&lt;br /&gt;
&lt;br /&gt;
=== QUERY ===&lt;br /&gt;
* Contains a nonce&lt;br /&gt;
* Requests anyone to send a MEMBER_LIST&lt;br /&gt;
&lt;br /&gt;
=== MEMBER_LIST ===&lt;br /&gt;
* Lists the sequence number and nonce of the QUERY it's responding to &lt;br /&gt;
* Lists the certificate for each member of its parent&lt;br /&gt;
&lt;br /&gt;
=== JOIN ===&lt;br /&gt;
* Lists the certificate for the new member&lt;br /&gt;
* Contains CONFIRM messages for each member of its parent&lt;br /&gt;
&lt;br /&gt;
== Encrypted messages ==&lt;br /&gt;
&lt;br /&gt;
=== CONFIRM ===&lt;br /&gt;
* Encrypts-and-confirms an AES256 &amp;quot;sender key&amp;quot; from one member to another&lt;br /&gt;
* Uses pairwise TripleDH between sender and recipient keys, i.e.&lt;br /&gt;
   HASH( DH(A_id, B_eph) || DH(A_eph, B_id) || DH(A_eph, B_eph) )&lt;br /&gt;
* Contains a transcript hash&lt;br /&gt;
&lt;br /&gt;
=== DATA === &lt;br /&gt;
* Encrypted under the sender's &amp;quot;sender key&amp;quot;&lt;br /&gt;
* Contains a transcript hash&lt;br /&gt;
* Ed25519 signature from the sender's ephemeral public key&lt;br /&gt;
&lt;br /&gt;
= Algorithms = &lt;br /&gt;
&lt;br /&gt;
== Nonblocking Join ==&lt;br /&gt;
On entering a room, a user sends a QUERY.  She is present in the room but hasn't yet joined the conversation.  Someone (or multiple parties) will respond with a MEMBER_LIST.&lt;br /&gt;
&lt;br /&gt;
On receiving a MEMBER_LIST, a present user learns the room's membership and sequence numbers, and can keep track of the membership by observing subsequent JOIN / USER_LEFT messages.&lt;br /&gt;
&lt;br /&gt;
To join a room, a present user sends a JOIN, including a CONFIRM for each member in its parent, and expects to receive a CONFIRM from each member shortly.&lt;br /&gt;
&lt;br /&gt;
After sending the JOIN, the user considers herself part of the conversation and can send DATA messages and respond to QUERY messages.  She responds to any subsequent JOINs with a CONFIRM.  If the subsequent JOIN doesn't include a CONFIRM for the user (simultaneous join), then she expects to receive one shortly.&lt;br /&gt;
&lt;br /&gt;
== Blocking Join ==&lt;br /&gt;
As above, except:&lt;br /&gt;
* A user is only added to group membership once all CONFIRMs from her JOIN, and any subsequent CONFIRMS (due to simultaneous join) have been responded to with CONFIRMs.&lt;br /&gt;
* In a simultaneous JOIN case, the JOINs are handled based on the server ordering (earliest first).&lt;br /&gt;
&lt;br /&gt;
Example: Alice and Bob are existing members.  Charlie and Dave send simultaneous JOINs, but the server places Charlie's first.  Alice and Bob send CONFIRM messages to both Charlie and Dave.  Charlie and Dave send CONFIRM messages to each other.  Once Charlie receive Alice and Bob's CONFIRMs, he's part of the group and can send DATA.  Once Dave receives Alice, Bob, and Charlie's CONFIRMs, he's part of the group and can send DATA.&lt;/div&gt;</summary>
		<author><name>Trevor</name></author>	</entry>

	<entry>
		<id>https://learn.equalit.ie/wiki/TransportAssumptions</id>
		<title>TransportAssumptions</title>
		<link rel="alternate" type="text/html" href="https://learn.equalit.ie/wiki/TransportAssumptions"/>
				<updated>2014-08-24T18:54:24Z</updated>
		
		<summary type="html">&lt;p&gt;Trevor: Created page with &amp;quot; These assumptions seem reasonable for XMPP MUC:  # All members see the same message order (assigned by server) # All messages are broadcast to group   We probably need anothe...&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;br /&gt;
These assumptions seem reasonable for XMPP MUC:&lt;br /&gt;
&lt;br /&gt;
# All members see the same message order (assigned by server)&lt;br /&gt;
# All messages are broadcast to group&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
We probably need another assumption regarding reliability and disconnection.  Maybe something like:&lt;br /&gt;
&lt;br /&gt;
&amp;quot;A client can detect when it's in a situation where message delivery might be unreliable (e.g. due to TCP connection close, or heartbeat failure)&amp;quot;&lt;br /&gt;
&lt;br /&gt;
In this case the client could re-join the group, so we can distinguish client-server connection problems from other transcript consistency problems.&lt;/div&gt;</summary>
		<author><name>Trevor</name></author>	</entry>

	<entry>
		<id>https://learn.equalit.ie/wiki/Np1sec/SenderKeys</id>
		<title>Np1sec/SenderKeys</title>
		<link rel="alternate" type="text/html" href="https://learn.equalit.ie/wiki/Np1sec/SenderKeys"/>
				<updated>2014-08-24T18:23:49Z</updated>
		
		<summary type="html">&lt;p&gt;Trevor: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Security Goals =&lt;br /&gt;
&lt;br /&gt;
== Transcript consistency ==&lt;br /&gt;
* Recipients are informed of the correct causal order of messages&lt;br /&gt;
* Excessively delayed messages are detected&lt;br /&gt;
&lt;br /&gt;
== Nonblocking join ==&lt;br /&gt;
* Join and leave are treated as messages, so transcript consistency applies (causal order, delays are detected).&lt;br /&gt;
* New users have to &amp;quot;confirm&amp;quot; to existing users to join.&lt;br /&gt;
* Existing users have to &amp;quot;confirm&amp;quot; to the new user shortly after the new user joins (e.g. 1 minute).&lt;br /&gt;
&lt;br /&gt;
= General concepts = &lt;br /&gt;
&lt;br /&gt;
== Room membership ==&lt;br /&gt;
Users can enter and leave the room, as signalled by presence messages from the server (USER_ENTERED, USER_LEFT).&lt;br /&gt;
&lt;br /&gt;
Users can join the room's conversation by sending a JOIN message.&lt;br /&gt;
&lt;br /&gt;
Users can only leave the conversation if the server says they left the room.&lt;br /&gt;
&lt;br /&gt;
(TBD: should users be able to declare that they're leaving, or kick each other out?)&lt;br /&gt;
&lt;br /&gt;
== Sender keys ==&lt;br /&gt;
When a new user joins, she exchanges AES256 &amp;quot;sender keys&amp;quot; with existing members, encrypted under the &amp;quot;pairwise keys&amp;quot; from pairwise key agreements.  This allows subsequent messages to be encrypted once with a sender key, instead of N times with pairwise keys.&lt;br /&gt;
&lt;br /&gt;
Every time a message is encrypted or decrypted with a sender key, the key is updated as:&lt;br /&gt;
&lt;br /&gt;
sender_key = HMAC-SHA256(prev_sender_key, member_list)&lt;br /&gt;
&lt;br /&gt;
This provides forward secrecy and ensures new members can't decrypt messages prior to when they joined.&lt;br /&gt;
&lt;br /&gt;
== Server order ==&lt;br /&gt;
All clients see the same message order from the server.  All messages are sent to all users.  Aside from the presence messages sent by the server, messages are sent by users.&lt;br /&gt;
&lt;br /&gt;
All messages in a room have a unique sequence number (0, 1, ...).  Sequence numbers are implicit, as the server may not be aware of them (e.g. XMPP MUC).&lt;br /&gt;
&lt;br /&gt;
A new user synchronizes his view of sequence numbers via the QUERY / MEMBER_LIST messages (see below).&lt;br /&gt;
&lt;br /&gt;
== Causal order ==&lt;br /&gt;
Every user-sent message specifies a &amp;quot;parent&amp;quot; sequence number which is the last message the user received before sending it.  Note:&lt;br /&gt;
* If Alice sends messages (A,B) in a row, A will not be B's parent unless Alice waits till A is received back from the server.&lt;br /&gt;
* The parent of a message is different from the &amp;quot;previous&amp;quot; message in the server's ordering, e.g. in a &amp;quot;simultaneous send&amp;quot; case two messages will have the same parent.&lt;br /&gt;
&lt;br /&gt;
Due to server ordering, the sender of message i must have seen all&lt;br /&gt;
messages from 0...i's parent.  Thus, every user-sent message i has a membership set, determined by the JOIN / USER_LEFT messages from 0...i's parent.&lt;br /&gt;
&lt;br /&gt;
== Transcript hashes ==&lt;br /&gt;
Every message specifies its parent's sequence number.  Some messages also specify a transcript hash of that parent and all prior messages.  The hash also covers the sender_key for each message (set to zeros for cleartext messages):&lt;br /&gt;
&lt;br /&gt;
H(parent) = SHA256(sender_key[parent] || ciphertext[parent] || H(parent-1))&lt;br /&gt;
&lt;br /&gt;
== Timing ==&lt;br /&gt;
Timing rules can trigger errors based on some assumed constants:&lt;br /&gt;
&lt;br /&gt;
* MAX_RTT - this is the maximum time it should take for a sent message to arrive at all parties.  If you send a message and haven't received it back within MAX_RTT, something is wrong.&lt;br /&gt;
&lt;br /&gt;
* MAX_RTD - this is the maximum difference in time when a message arrives at all parties.  If you receive a message whose parent was received before a message you received more than MAX_RTD + MAX_RTT time ago, something is wrong.&lt;br /&gt;
&lt;br /&gt;
* MAX_CONFIRM - this is the maximum time an existing member may spend after receiving a new user's JOIN message before sending a CONFIRM message in response.  If the new user hasn't received CONFIRM messages from existing membership within 2*MAX_RTT + MAX_CONFIRM, something is wrong.&lt;br /&gt;
&lt;br /&gt;
= Messages = &lt;br /&gt;
&lt;br /&gt;
== Generic structures ==&lt;br /&gt;
&lt;br /&gt;
=== Certificate ===&lt;br /&gt;
* The user's Curve25519 identity public key&lt;br /&gt;
* The user's Curve25519 ephemeral public key&lt;br /&gt;
* An Ed25519 signature from the identity key over the ephemeral key&lt;br /&gt;
   (Ed25519 signatures can be produced from Curve25519 keys)&lt;br /&gt;
&lt;br /&gt;
== Server messages ==&lt;br /&gt;
&lt;br /&gt;
=== USER_ENTERED, USER_LEFT ===&lt;br /&gt;
* &amp;quot;Presence&amp;quot; messages sent in clear by the server to indicate a user has entered or left the room&lt;br /&gt;
&lt;br /&gt;
== Cleartext messages from users ==&lt;br /&gt;
&lt;br /&gt;
=== QUERY ===&lt;br /&gt;
* Contains a nonce&lt;br /&gt;
* Requests anyone to send a MEMBER_LIST&lt;br /&gt;
&lt;br /&gt;
=== MEMBER_LIST ===&lt;br /&gt;
* Lists the sequence number and nonce of the QUERY it's responding to &lt;br /&gt;
* Lists the certificate for each member of its parent&lt;br /&gt;
&lt;br /&gt;
=== JOIN ===&lt;br /&gt;
* Lists the certificate for the new member&lt;br /&gt;
* Contains CONFIRM messages for each member of its parent&lt;br /&gt;
&lt;br /&gt;
== Encrypted messages ==&lt;br /&gt;
&lt;br /&gt;
=== CONFIRM ===&lt;br /&gt;
* Encrypts-and-confirms an AES256 &amp;quot;sender key&amp;quot; from one member to another&lt;br /&gt;
* Uses pairwise TripleDH between sender and recipient keys, i.e.&lt;br /&gt;
   HASH( DH(A_id, B_eph) || DH(A_eph, B_id) || DH(A_eph, B_eph) )&lt;br /&gt;
* Contains a transcript hash&lt;br /&gt;
&lt;br /&gt;
=== DATA === &lt;br /&gt;
* Encrypted under the sender's &amp;quot;sender key&amp;quot;&lt;br /&gt;
* Contains a transcript hash&lt;br /&gt;
* Ed25519 signature from the sender's ephemeral public key&lt;br /&gt;
&lt;br /&gt;
= Algorithms = &lt;br /&gt;
&lt;br /&gt;
== Nonblocking Join ==&lt;br /&gt;
On entering a room, a user sends a QUERY.  She is present in the room but hasn't yet joined the conversation.  Someone (or multiple parties) will respond with a MEMBER_LIST.&lt;br /&gt;
&lt;br /&gt;
On receiving a MEMBER_LIST, a present user learns the room's membership and sequence numbers, and can keep track of the membership by observing subsequent JOIN / USER_LEFT messages.&lt;br /&gt;
&lt;br /&gt;
To join a room, a present user sends a JOIN, including a CONFIRM for each member in its parent, and expects to receive a CONFIRM from each member shortly.&lt;br /&gt;
&lt;br /&gt;
After sending the JOIN, the user considers herself part of the conversation and can send DATA messages and respond to QUERY messages.  She responds to any subsequent JOINs with a CONFIRM.  If the subsequent JOIN doesn't include a CONFIRM for the user (simultaneous join), then she expects to receive one shortly.&lt;br /&gt;
&lt;br /&gt;
== Blocking Join ==&lt;br /&gt;
As above, except:&lt;br /&gt;
* A user is only added to group membership once all CONFIRMs from her JOIN, and any subsequent CONFIRMS (due to simultaneous join) have been responded to with CONFIRMs.&lt;br /&gt;
* In a simultaneous JOIN case, the JOINs are handled based on the server ordering (earliest first).&lt;br /&gt;
&lt;br /&gt;
Example: Alice and Bob are existing members.  Charlie and Dave send simultaneous JOINs, but the server places Charlie's first.  Alice and Bob send CONFIRM messages to both Charlie and Dave.  Charlie and Dave send CONFIRM messages to each other.  Once Charlie receive Alice and Bob's CONFIRMs, he's part of the group and can send DATA.  Once Dave receives Alice, Bob, and Charlie's CONFIRMs, he's part of the group and can send DATA.&lt;/div&gt;</summary>
		<author><name>Trevor</name></author>	</entry>

	<entry>
		<id>https://learn.equalit.ie/wiki/Np1sec/SenderKeys</id>
		<title>Np1sec/SenderKeys</title>
		<link rel="alternate" type="text/html" href="https://learn.equalit.ie/wiki/Np1sec/SenderKeys"/>
				<updated>2014-08-24T18:19:48Z</updated>
		
		<summary type="html">&lt;p&gt;Trevor: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Security Goals =&lt;br /&gt;
&lt;br /&gt;
== Transcript consistency ==&lt;br /&gt;
* Recipients are informed of the correct causal order of messages&lt;br /&gt;
* Excessively delayed messages are detected&lt;br /&gt;
&lt;br /&gt;
== Nonblocking join ==&lt;br /&gt;
* Join and leave are treated as messages, so transcript consistency applies (causal order, delays are detected).&lt;br /&gt;
* New users have to &amp;quot;confirm&amp;quot; to existing users to join.&lt;br /&gt;
* Existing users have to &amp;quot;confirm&amp;quot; to the new user shortly after the new user joins (e.g. 1 minute).&lt;br /&gt;
&lt;br /&gt;
= General concepts = &lt;br /&gt;
&lt;br /&gt;
== Room membership ==&lt;br /&gt;
Users can enter and leave the room, as signalled by presence messages from the server (USER_ENTERED, USER_LEFT).&lt;br /&gt;
&lt;br /&gt;
Users can join the room's conversation by sending a JOIN message.&lt;br /&gt;
&lt;br /&gt;
Users can only leave the conversation if the server says they left the room.&lt;br /&gt;
&lt;br /&gt;
(TBD: should users be able to declare that they're leaving, or kick each other out?)&lt;br /&gt;
&lt;br /&gt;
== Sender keys ==&lt;br /&gt;
When a new user joins, she exchanges AES256 &amp;quot;sender keys&amp;quot; with existing members, encrypted under the &amp;quot;pairwise keys&amp;quot; from pairwise key agreements.  This allows subsequent messages to be encrypted once with a sender key, instead of N times with pairwise keys.&lt;br /&gt;
&lt;br /&gt;
Every time a message is encrypted or decrypted with a sender key, the key is updated as:&lt;br /&gt;
&lt;br /&gt;
sender_key = HMAC-SHA256(prev_sender_key, member_list)&lt;br /&gt;
&lt;br /&gt;
This provides forward secrecy and ensures new members can't decrypt messages prior to when they joined.&lt;br /&gt;
&lt;br /&gt;
== Server order ==&lt;br /&gt;
All clients see the same message order from the server.  All messages are sent to all users.  Aside from the presence messages sent by the server, messages are sent by users.&lt;br /&gt;
&lt;br /&gt;
All messages in a room have a unique sequence number (0, 1, ...).  Sequence numbers are implicit, as the server may not be aware of them (e.g. XMPP MUC).&lt;br /&gt;
&lt;br /&gt;
A new user synchronizes his view of sequence numbers via the QUERY / MEMBER_LIST messages (see below).&lt;br /&gt;
&lt;br /&gt;
== Causal order ==&lt;br /&gt;
Every user-sent message specifies a &amp;quot;parent&amp;quot; sequence number which is the last message the user received before sending it.  Note:&lt;br /&gt;
* If Alice sends messages (A,B) in a row, A will not be B's parent unless Alice waits till A is received back from the server.&lt;br /&gt;
* The parent of a message is different from the &amp;quot;previous&amp;quot; message in the server's ordering, e.g. in a &amp;quot;simultaneous send&amp;quot; case two messages will have the same parent.&lt;br /&gt;
&lt;br /&gt;
Due to server ordering, the sender of message i must have seen all&lt;br /&gt;
messages from 0...i's parent.  Thus, every user-sent message i has a membership set, determined by the JOIN / USER_LEFT messages from 0...i's parent.&lt;br /&gt;
&lt;br /&gt;
== Transcript hashes ==&lt;br /&gt;
Every message specifies its parent's sequence number.  Some messages also specify a transcript hash of that parent and all prior messages.  The hash also covers the sender_key for each message (set to zeros for cleartext messages):&lt;br /&gt;
&lt;br /&gt;
H(parent) = SHA256(sender_key[parent] || ciphertext[parent] || H(parent-1))&lt;br /&gt;
&lt;br /&gt;
== Timing ==&lt;br /&gt;
Timing rules can trigger errors based on some assumed constants:&lt;br /&gt;
&lt;br /&gt;
* MAX_RTT - this is the maximum time it should take for a sent message to arrive at all parties.  If you send a message and haven't received it back within MAX_RTT, something is wrong.&lt;br /&gt;
&lt;br /&gt;
* MAX_RTD - this is the maximum difference in time when a message arrives at all parties.  If you receive a message which isn't a causal successor of a message you received more than MAX_RTD + MAX_RTT time ago, something is wrong.&lt;br /&gt;
&lt;br /&gt;
* MAX_CONFIRM - this is the maximum time an existing member may spend after receiving a new user's JOIN message before sending a CONFIRM message in response.  If the new user hasn't received CONFIRM messages from existing membership within 2*MAX_RTT + MAX_CONFIRM, something is wrong.&lt;br /&gt;
&lt;br /&gt;
= Messages = &lt;br /&gt;
&lt;br /&gt;
== Generic structures ==&lt;br /&gt;
&lt;br /&gt;
=== Certificate ===&lt;br /&gt;
* The user's Curve25519 identity public key&lt;br /&gt;
* The user's Curve25519 ephemeral public key&lt;br /&gt;
* An Ed25519 signature from the identity key over the ephemeral key&lt;br /&gt;
   (Ed25519 signatures can be produced from Curve25519 keys)&lt;br /&gt;
&lt;br /&gt;
== Server messages ==&lt;br /&gt;
&lt;br /&gt;
=== USER_ENTERED, USER_LEFT ===&lt;br /&gt;
* &amp;quot;Presence&amp;quot; messages sent in clear by the server to indicate a user has entered or left the room&lt;br /&gt;
&lt;br /&gt;
== Cleartext messages from users ==&lt;br /&gt;
&lt;br /&gt;
=== QUERY ===&lt;br /&gt;
* Contains a nonce&lt;br /&gt;
* Requests anyone to send a MEMBER_LIST&lt;br /&gt;
&lt;br /&gt;
=== MEMBER_LIST ===&lt;br /&gt;
* Lists the sequence number and nonce of the QUERY it's responding to &lt;br /&gt;
* Lists the certificate for each member of its parent&lt;br /&gt;
&lt;br /&gt;
=== JOIN ===&lt;br /&gt;
* Lists the certificate for the new member&lt;br /&gt;
* Contains CONFIRM messages for each member of its parent&lt;br /&gt;
&lt;br /&gt;
== Encrypted messages ==&lt;br /&gt;
&lt;br /&gt;
=== CONFIRM ===&lt;br /&gt;
* Encrypts-and-confirms an AES256 &amp;quot;sender key&amp;quot; from one member to another&lt;br /&gt;
* Uses pairwise TripleDH between sender and recipient keys, i.e.&lt;br /&gt;
   HASH( DH(A_id, B_eph) || DH(A_eph, B_id) || DH(A_eph, B_eph) )&lt;br /&gt;
* Contains a transcript hash&lt;br /&gt;
&lt;br /&gt;
=== DATA === &lt;br /&gt;
* Encrypted under the sender's &amp;quot;sender key&amp;quot;&lt;br /&gt;
* Contains a transcript hash&lt;br /&gt;
* Ed25519 signature from the sender's ephemeral public key&lt;br /&gt;
&lt;br /&gt;
= Algorithms = &lt;br /&gt;
&lt;br /&gt;
== Nonblocking Join ==&lt;br /&gt;
On entering a room, a user sends a QUERY.  She is present in the room but hasn't yet joined the conversation.  Someone (or multiple parties) will respond with a MEMBER_LIST.&lt;br /&gt;
&lt;br /&gt;
On receiving a MEMBER_LIST, a present user learns the room's membership and sequence numbers, and can keep track of the membership by observing subsequent JOIN / USER_LEFT messages.&lt;br /&gt;
&lt;br /&gt;
To join a room, a present user sends a JOIN, including a CONFIRM for each member in its parent, and expects to receive a CONFIRM from each member shortly.&lt;br /&gt;
&lt;br /&gt;
After sending the JOIN, the user considers herself part of the conversation and can send DATA messages and respond to QUERY messages.  She responds to any subsequent JOINs with a CONFIRM.  If the subsequent JOIN doesn't include a CONFIRM for the user (simultaneous join), then she expects to receive one shortly.&lt;br /&gt;
&lt;br /&gt;
== Blocking Join ==&lt;br /&gt;
As above, except:&lt;br /&gt;
* A user is only added to group membership once all CONFIRMs from her JOIN, and any subsequent CONFIRMS (due to simultaneous join) have been responded to with CONFIRMs.&lt;br /&gt;
* In a simultaneous JOIN case, the JOINs are handled based on the server ordering (earliest first).&lt;br /&gt;
&lt;br /&gt;
Example: Alice and Bob are existing members.  Charlie and Dave send simultaneous JOINs, but the server places Charlie's first.  Alice and Bob send CONFIRM messages to both Charlie and Dave.  Charlie and Dave send CONFIRM messages to each other.  Once Charlie receive Alice and Bob's CONFIRMs, he's part of the group and can send DATA.  Once Dave receives Alice, Bob, and Charlie's CONFIRMs, he's part of the group and can send DATA.&lt;/div&gt;</summary>
		<author><name>Trevor</name></author>	</entry>

	<entry>
		<id>https://learn.equalit.ie/wiki/Np1sec/SenderKeys</id>
		<title>Np1sec/SenderKeys</title>
		<link rel="alternate" type="text/html" href="https://learn.equalit.ie/wiki/Np1sec/SenderKeys"/>
				<updated>2014-08-24T18:10:25Z</updated>
		
		<summary type="html">&lt;p&gt;Trevor: Created page with &amp;quot;= General concepts =   == Room membership == Users can enter and leave the room, as signalled by presence messages from the server (USER_ENTERED, USER_LEFT).  Users can join t...&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= General concepts = &lt;br /&gt;
&lt;br /&gt;
== Room membership ==&lt;br /&gt;
Users can enter and leave the room, as signalled by presence messages from the server (USER_ENTERED, USER_LEFT).&lt;br /&gt;
&lt;br /&gt;
Users can join the room's conversation by sending a JOIN message.&lt;br /&gt;
&lt;br /&gt;
Users can only leave the conversation if the server says they left the room.&lt;br /&gt;
&lt;br /&gt;
(TBD: should users be able to declare that they're leaving, or kick each other out?)&lt;br /&gt;
&lt;br /&gt;
== Sender keys ==&lt;br /&gt;
When a new user joins, she exchanges AES256 &amp;quot;sender keys&amp;quot; with existing members, encrypted under the &amp;quot;pairwise keys&amp;quot; from pairwise key agreements.  This allows subsequent messages to be encrypted once with a sender key, instead of N times with pairwise keys.&lt;br /&gt;
&lt;br /&gt;
Every time a message is encrypted or decrypted with a sender key, the key is updated as:&lt;br /&gt;
&lt;br /&gt;
sender_key = HMAC-SHA256(prev_sender_key, member_list)&lt;br /&gt;
&lt;br /&gt;
This provides forward secrecy and ensures new members can't decrypt messages prior to when they joined.&lt;br /&gt;
&lt;br /&gt;
== Server order ==&lt;br /&gt;
All clients see the same message order from the server.  All messages are sent to all users.  Aside from the presence messages sent by the server, messages are sent by users.&lt;br /&gt;
&lt;br /&gt;
All messages in a room have a unique sequence number (0, 1, ...).  Sequence numbers are implicit, as the server may not be aware of them (e.g. XMPP MUC).&lt;br /&gt;
&lt;br /&gt;
A new user synchronizes his view of sequence numbers via the QUERY / MEMBER_LIST messages (see below).&lt;br /&gt;
&lt;br /&gt;
== Causal order ==&lt;br /&gt;
Every user-sent message specifies a &amp;quot;parent&amp;quot; sequence number which is the last message the user received before sending it.  Note:&lt;br /&gt;
* If Alice sends messages (A,B) in a row, A will not be B's parent unless Alice waits till A is received back from the server.&lt;br /&gt;
* The parent of a message is different from the &amp;quot;previous&amp;quot; message in the server's ordering, e.g. in a &amp;quot;simultaneous send&amp;quot; case two messages will have the same parent.&lt;br /&gt;
&lt;br /&gt;
Due to server ordering, the sender of message i must have seen all&lt;br /&gt;
messages from 0...i's parent.  Thus, every user-sent message i has a membership set, determined by the JOIN / USER_LEFT messages from 0...i's parent.&lt;br /&gt;
&lt;br /&gt;
== Transcript hashes ==&lt;br /&gt;
Every message specifies its parent's sequence number.  Some messages also specify a transcript hash of that parent and all prior messages.  The hash also covers the sender_key for each message (set to zeros for cleartext messages):&lt;br /&gt;
&lt;br /&gt;
H(parent) = SHA256(sender_key[parent] || ciphertext[parent] || H(parent-1))&lt;br /&gt;
&lt;br /&gt;
== Timing ==&lt;br /&gt;
Timing rules can trigger errors based on some assumed constants:&lt;br /&gt;
&lt;br /&gt;
* MAX_RTT - this is the maximum time it should take for a sent message to arrive at all parties.  If you send a message and haven't received it back within MAX_RTT, something is wrong.&lt;br /&gt;
&lt;br /&gt;
* MAX_RTD - this is the maximum difference in time when a message arrives at all parties.  If you receive a message which isn't a causal successor of a message you received more than MAX_RTD + MAX_RTT time ago, something is wrong.&lt;br /&gt;
&lt;br /&gt;
* MAX_CONFIRM - this is the maximum time an existing member may spend after receiving a new user's JOIN message before sending a CONFIRM message in response.  If the new user hasn't received CONFIRM messages from existing membership within 2*MAX_RTT + MAX_CONFIRM, something is wrong.&lt;br /&gt;
&lt;br /&gt;
= Messages = &lt;br /&gt;
&lt;br /&gt;
== Generic structures ==&lt;br /&gt;
&lt;br /&gt;
=== Certificate ===&lt;br /&gt;
* The user's Curve25519 identity public key&lt;br /&gt;
* The user's Curve25519 ephemeral public key&lt;br /&gt;
* An Ed25519 signature from the identity key over the ephemeral key&lt;br /&gt;
   (Ed25519 signatures can be produced from Curve25519 keys)&lt;br /&gt;
&lt;br /&gt;
== Server messages ==&lt;br /&gt;
&lt;br /&gt;
=== USER_ENTERED, USER_LEFT ===&lt;br /&gt;
* &amp;quot;Presence&amp;quot; messages sent in clear by the server to indicate a user has entered or left the room&lt;br /&gt;
&lt;br /&gt;
== Cleartext messages from users ==&lt;br /&gt;
&lt;br /&gt;
=== QUERY ===&lt;br /&gt;
* Contains a nonce&lt;br /&gt;
* Requests anyone to send a MEMBER_LIST&lt;br /&gt;
&lt;br /&gt;
=== MEMBER_LIST ===&lt;br /&gt;
* Lists the sequence number and nonce of the QUERY it's responding to &lt;br /&gt;
* Lists the certificate for each member of its parent&lt;br /&gt;
&lt;br /&gt;
=== JOIN ===&lt;br /&gt;
* Lists the certificate for the new member&lt;br /&gt;
* Contains CONFIRM messages for each member of its parent&lt;br /&gt;
&lt;br /&gt;
== Encrypted messages ==&lt;br /&gt;
&lt;br /&gt;
=== CONFIRM ===&lt;br /&gt;
* Encrypts-and-confirms an AES256 &amp;quot;sender key&amp;quot; from one member to another&lt;br /&gt;
* Uses pairwise TripleDH between sender and recipient keys, i.e.&lt;br /&gt;
   HASH( DH(A_id, B_eph) || DH(A_eph, B_id) || DH(A_eph, B_eph) )&lt;br /&gt;
* Contains a transcript hash&lt;br /&gt;
&lt;br /&gt;
=== DATA === &lt;br /&gt;
* Encrypted under the sender's &amp;quot;sender key&amp;quot;&lt;br /&gt;
* Contains a transcript hash&lt;br /&gt;
* Ed25519 signature from the sender's ephemeral public key&lt;br /&gt;
&lt;br /&gt;
= Algorithms = &lt;br /&gt;
&lt;br /&gt;
== Nonblocking Join ==&lt;br /&gt;
On entering a room, a user sends a QUERY.  She is present in the room but hasn't yet joined the conversation.  Someone (or multiple parties) will respond with a MEMBER_LIST.&lt;br /&gt;
&lt;br /&gt;
On receiving a MEMBER_LIST, a present user learns the room's membership and sequence numbers, and can keep track of the membership by observing subsequent JOIN / USER_LEFT messages.&lt;br /&gt;
&lt;br /&gt;
To join a room, a present user sends a JOIN, including a CONFIRM for each member in its parent, and expects to receive a CONFIRM from each member shortly.&lt;br /&gt;
&lt;br /&gt;
After sending the JOIN, the user considers herself part of the conversation and can send DATA messages and respond to QUERY messages.  She responds to any subsequent JOINs with a CONFIRM.  If the subsequent JOIN doesn't include a CONFIRM for the user (simultaneous join), then she expects to receive one shortly.&lt;br /&gt;
&lt;br /&gt;
== Blocking Join ==&lt;br /&gt;
As above, except:&lt;br /&gt;
* A user is only added to group membership once all CONFIRMs from her JOIN, and any subsequent CONFIRMS (due to simultaneous join) have been responded to with CONFIRMs.&lt;br /&gt;
* In a simultaneous JOIN case, the JOINs are handled based on the server ordering (earliest first).&lt;br /&gt;
&lt;br /&gt;
Example: Alice and Bob are existing members.  Charlie and Dave send simultaneous JOINs, but the server places Charlie's first.  Alice and Bob send CONFIRM messages to both Charlie and Dave.  Charlie and Dave send CONFIRM messages to each other.  Once Charlie receive Alice and Bob's CONFIRMs, he's part of the group and can send DATA.  Once Dave receives Alice, Bob, and Charlie's CONFIRMs, he's part of the group and can send DATA.&lt;/div&gt;</summary>
		<author><name>Trevor</name></author>	</entry>

	</feed>