docs: simplex connection

This commit is contained in:
Evgeny Poberezkin 2019-12-23 23:18:17 +00:00
parent 54b3d15dc9
commit 078bc91930
5 changed files with 1074 additions and 0 deletions

8
diagrams/simplex1.mmd Normal file
View File

@ -0,0 +1,8 @@
graph LR
S("sender (key 1)") --> C
C --> R("receiver (key 2)")
R --> C
subgraph connection
C{{"verify sender (1) ---> pubsub <---> verify receiver (2)"}}
end

498
diagrams/simplex1.svg Normal file
View File

@ -0,0 +1,498 @@
<svg id="mermaid-1577142258919" width="840.203125" xmlns="http://www.w3.org/2000/svg" height="127.75" viewBox="0 0 840.203125 127.75"><style>
#mermaid-1577142258919 .label {
font-family: 'trebuchet ms', verdana, arial;
font-family: var(--mermaid-font-family);
color: #333; }
#mermaid-1577142258919 .label text {
fill: #333; }
#mermaid-1577142258919 .node rect,
#mermaid-1577142258919 .node circle,
#mermaid-1577142258919 .node ellipse,
#mermaid-1577142258919 .node polygon {
fill: #ECECFF;
stroke: #9370DB;
stroke-width: 1px; }
#mermaid-1577142258919 .node .label {
text-align: center; }
#mermaid-1577142258919 .node.clickable {
cursor: pointer; }
#mermaid-1577142258919 .arrowheadPath {
fill: #333333; }
#mermaid-1577142258919 .edgePath .path {
stroke: #333333;
stroke-width: 1.5px; }
#mermaid-1577142258919 .edgeLabel {
background-color: #e8e8e8;
text-align: center; }
#mermaid-1577142258919 .cluster rect {
fill: #ffffde;
stroke: #aaaa33;
stroke-width: 1px; }
#mermaid-1577142258919 .cluster text {
fill: #333; }
#mermaid-1577142258919 div.mermaidTooltip {
position: absolute;
text-align: center;
max-width: 200px;
padding: 2px;
font-family: 'trebuchet ms', verdana, arial;
font-family: var(--mermaid-font-family);
font-size: 12px;
background: #ffffde;
border: 1px solid #aaaa33;
border-radius: 2px;
pointer-events: none;
z-index: 100; }
#mermaid-1577142258919 .actor {
stroke: #CCCCFF;
fill: #ECECFF; }
#mermaid-1577142258919 text.actor {
fill: black;
stroke: none; }
#mermaid-1577142258919 .actor-line {
stroke: grey; }
#mermaid-1577142258919 .messageLine0 {
stroke-width: 1.5;
stroke-dasharray: '2 2';
stroke: #333; }
#mermaid-1577142258919 .messageLine1 {
stroke-width: 1.5;
stroke-dasharray: '2 2';
stroke: #333; }
#mermaid-1577142258919 #arrowhead {
fill: #333; }
#mermaid-1577142258919 .sequenceNumber {
fill: white; }
#mermaid-1577142258919 #sequencenumber {
fill: #333; }
#mermaid-1577142258919 #crosshead path {
fill: #333 !important;
stroke: #333 !important; }
#mermaid-1577142258919 .messageText {
fill: #333;
stroke: none; }
#mermaid-1577142258919 .labelBox {
stroke: #CCCCFF;
fill: #ECECFF; }
#mermaid-1577142258919 .labelText {
fill: black;
stroke: none; }
#mermaid-1577142258919 .loopText {
fill: black;
stroke: none; }
#mermaid-1577142258919 .loopLine {
stroke-width: 2;
stroke-dasharray: '2 2';
stroke: #CCCCFF; }
#mermaid-1577142258919 .note {
stroke: #aaaa33;
fill: #fff5ad; }
#mermaid-1577142258919 .noteText {
fill: black;
stroke: none;
font-family: 'trebuchet ms', verdana, arial;
font-family: var(--mermaid-font-family);
font-size: 14px; }
#mermaid-1577142258919 .activation0 {
fill: #f4f4f4;
stroke: #666; }
#mermaid-1577142258919 .activation1 {
fill: #f4f4f4;
stroke: #666; }
#mermaid-1577142258919 .activation2 {
fill: #f4f4f4;
stroke: #666; }
#mermaid-1577142258919 .mermaid-main-font {
font-family: "trebuchet ms", verdana, arial;
font-family: var(--mermaid-font-family); }
#mermaid-1577142258919 .section {
stroke: none;
opacity: 0.2; }
#mermaid-1577142258919 .section0 {
fill: rgba(102, 102, 255, 0.49); }
#mermaid-1577142258919 .section2 {
fill: #fff400; }
#mermaid-1577142258919 .section1,
#mermaid-1577142258919 .section3 {
fill: white;
opacity: 0.2; }
#mermaid-1577142258919 .sectionTitle0 {
fill: #333; }
#mermaid-1577142258919 .sectionTitle1 {
fill: #333; }
#mermaid-1577142258919 .sectionTitle2 {
fill: #333; }
#mermaid-1577142258919 .sectionTitle3 {
fill: #333; }
#mermaid-1577142258919 .sectionTitle {
text-anchor: start;
font-size: 11px;
text-height: 14px;
font-family: 'trebuchet ms', verdana, arial;
font-family: var(--mermaid-font-family); }
#mermaid-1577142258919 .grid .tick {
stroke: lightgrey;
opacity: 0.3;
shape-rendering: crispEdges; }
#mermaid-1577142258919 .grid .tick text {
font-family: 'trebuchet ms', verdana, arial;
font-family: var(--mermaid-font-family); }
#mermaid-1577142258919 .grid path {
stroke-width: 0; }
#mermaid-1577142258919 .today {
fill: none;
stroke: red;
stroke-width: 2px; }
#mermaid-1577142258919 .task {
stroke-width: 2; }
#mermaid-1577142258919 .taskText {
text-anchor: middle;
font-family: 'trebuchet ms', verdana, arial;
font-family: var(--mermaid-font-family); }
#mermaid-1577142258919 .taskText:not([font-size]) {
font-size: 11px; }
#mermaid-1577142258919 .taskTextOutsideRight {
fill: black;
text-anchor: start;
font-size: 11px;
font-family: 'trebuchet ms', verdana, arial;
font-family: var(--mermaid-font-family); }
#mermaid-1577142258919 .taskTextOutsideLeft {
fill: black;
text-anchor: end;
font-size: 11px; }
#mermaid-1577142258919 .task.clickable {
cursor: pointer; }
#mermaid-1577142258919 .taskText.clickable {
cursor: pointer;
fill: #003163 !important;
font-weight: bold; }
#mermaid-1577142258919 .taskTextOutsideLeft.clickable {
cursor: pointer;
fill: #003163 !important;
font-weight: bold; }
#mermaid-1577142258919 .taskTextOutsideRight.clickable {
cursor: pointer;
fill: #003163 !important;
font-weight: bold; }
#mermaid-1577142258919 .taskText0,
#mermaid-1577142258919 .taskText1,
#mermaid-1577142258919 .taskText2,
#mermaid-1577142258919 .taskText3 {
fill: white; }
#mermaid-1577142258919 .task0,
#mermaid-1577142258919 .task1,
#mermaid-1577142258919 .task2,
#mermaid-1577142258919 .task3 {
fill: #8a90dd;
stroke: #534fbc; }
#mermaid-1577142258919 .taskTextOutside0,
#mermaid-1577142258919 .taskTextOutside2 {
fill: black; }
#mermaid-1577142258919 .taskTextOutside1,
#mermaid-1577142258919 .taskTextOutside3 {
fill: black; }
#mermaid-1577142258919 .active0,
#mermaid-1577142258919 .active1,
#mermaid-1577142258919 .active2,
#mermaid-1577142258919 .active3 {
fill: #bfc7ff;
stroke: #534fbc; }
#mermaid-1577142258919 .activeText0,
#mermaid-1577142258919 .activeText1,
#mermaid-1577142258919 .activeText2,
#mermaid-1577142258919 .activeText3 {
fill: black !important; }
#mermaid-1577142258919 .done0,
#mermaid-1577142258919 .done1,
#mermaid-1577142258919 .done2,
#mermaid-1577142258919 .done3 {
stroke: grey;
fill: lightgrey;
stroke-width: 2; }
#mermaid-1577142258919 .doneText0,
#mermaid-1577142258919 .doneText1,
#mermaid-1577142258919 .doneText2,
#mermaid-1577142258919 .doneText3 {
fill: black !important; }
#mermaid-1577142258919 .crit0,
#mermaid-1577142258919 .crit1,
#mermaid-1577142258919 .crit2,
#mermaid-1577142258919 .crit3 {
stroke: #ff8888;
fill: red;
stroke-width: 2; }
#mermaid-1577142258919 .activeCrit0,
#mermaid-1577142258919 .activeCrit1,
#mermaid-1577142258919 .activeCrit2,
#mermaid-1577142258919 .activeCrit3 {
stroke: #ff8888;
fill: #bfc7ff;
stroke-width: 2; }
#mermaid-1577142258919 .doneCrit0,
#mermaid-1577142258919 .doneCrit1,
#mermaid-1577142258919 .doneCrit2,
#mermaid-1577142258919 .doneCrit3 {
stroke: #ff8888;
fill: lightgrey;
stroke-width: 2;
cursor: pointer;
shape-rendering: crispEdges; }
#mermaid-1577142258919 .milestone {
transform: rotate(45deg) scale(0.8, 0.8); }
#mermaid-1577142258919 .milestoneText {
font-style: italic; }
#mermaid-1577142258919 .doneCritText0,
#mermaid-1577142258919 .doneCritText1,
#mermaid-1577142258919 .doneCritText2,
#mermaid-1577142258919 .doneCritText3 {
fill: black !important; }
#mermaid-1577142258919 .activeCritText0,
#mermaid-1577142258919 .activeCritText1,
#mermaid-1577142258919 .activeCritText2,
#mermaid-1577142258919 .activeCritText3 {
fill: black !important; }
#mermaid-1577142258919 .titleText {
text-anchor: middle;
font-size: 18px;
fill: black;
font-family: 'trebuchet ms', verdana, arial;
font-family: var(--mermaid-font-family); }
#mermaid-1577142258919 g.classGroup text {
fill: #9370DB;
stroke: none;
font-family: 'trebuchet ms', verdana, arial;
font-family: var(--mermaid-font-family);
font-size: 10px; }
#mermaid-1577142258919 g.classGroup text .title {
font-weight: bolder; }
#mermaid-1577142258919 g.classGroup rect {
fill: #ECECFF;
stroke: #9370DB; }
#mermaid-1577142258919 g.classGroup line {
stroke: #9370DB;
stroke-width: 1; }
#mermaid-1577142258919 .classLabel .box {
stroke: none;
stroke-width: 0;
fill: #ECECFF;
opacity: 0.5; }
#mermaid-1577142258919 .classLabel .label {
fill: #9370DB;
font-size: 10px; }
#mermaid-1577142258919 .relation {
stroke: #9370DB;
stroke-width: 1;
fill: none; }
#mermaid-1577142258919 #compositionStart {
fill: #9370DB;
stroke: #9370DB;
stroke-width: 1; }
#mermaid-1577142258919 #compositionEnd {
fill: #9370DB;
stroke: #9370DB;
stroke-width: 1; }
#mermaid-1577142258919 #aggregationStart {
fill: #ECECFF;
stroke: #9370DB;
stroke-width: 1; }
#mermaid-1577142258919 #aggregationEnd {
fill: #ECECFF;
stroke: #9370DB;
stroke-width: 1; }
#mermaid-1577142258919 #dependencyStart {
fill: #9370DB;
stroke: #9370DB;
stroke-width: 1; }
#mermaid-1577142258919 #dependencyEnd {
fill: #9370DB;
stroke: #9370DB;
stroke-width: 1; }
#mermaid-1577142258919 #extensionStart {
fill: #9370DB;
stroke: #9370DB;
stroke-width: 1; }
#mermaid-1577142258919 #extensionEnd {
fill: #9370DB;
stroke: #9370DB;
stroke-width: 1; }
#mermaid-1577142258919 .commit-id,
#mermaid-1577142258919 .commit-msg,
#mermaid-1577142258919 .branch-label {
fill: lightgrey;
color: lightgrey;
font-family: 'trebuchet ms', verdana, arial;
font-family: var(--mermaid-font-family); }
#mermaid-1577142258919 .pieTitleText {
text-anchor: middle;
font-size: 25px;
fill: black;
font-family: 'trebuchet ms', verdana, arial;
font-family: var(--mermaid-font-family); }
#mermaid-1577142258919 .slice {
font-family: 'trebuchet ms', verdana, arial;
font-family: var(--mermaid-font-family); }
#mermaid-1577142258919 g.stateGroup text {
fill: #9370DB;
stroke: none;
font-size: 10px;
font-family: 'trebuchet ms', verdana, arial;
font-family: var(--mermaid-font-family); }
#mermaid-1577142258919 g.stateGroup text {
fill: #9370DB;
stroke: none;
font-size: 10px; }
#mermaid-1577142258919 g.stateGroup .state-title {
font-weight: bolder;
fill: black; }
#mermaid-1577142258919 g.stateGroup rect {
fill: #ECECFF;
stroke: #9370DB; }
#mermaid-1577142258919 g.stateGroup line {
stroke: #9370DB;
stroke-width: 1; }
#mermaid-1577142258919 .transition {
stroke: #9370DB;
stroke-width: 1;
fill: none; }
#mermaid-1577142258919 .stateGroup .composit {
fill: white;
border-bottom: 1px; }
#mermaid-1577142258919 .stateGroup .alt-composit {
fill: #e0e0e0;
border-bottom: 1px; }
#mermaid-1577142258919 .state-note {
stroke: #aaaa33;
fill: #fff5ad; }
#mermaid-1577142258919 .state-note text {
fill: black;
stroke: none;
font-size: 10px; }
#mermaid-1577142258919 .stateLabel .box {
stroke: none;
stroke-width: 0;
fill: #ECECFF;
opacity: 0.5; }
#mermaid-1577142258919 .stateLabel text {
fill: black;
font-size: 10px;
font-weight: bold;
font-family: 'trebuchet ms', verdana, arial;
font-family: var(--mermaid-font-family); }
:root {
--mermaid-font-family: '"trebuchet ms", verdana, arial';
--mermaid-font-family: "Comic Sans MS", "Comic Sans", cursive; }
:root { --mermaid-font-family: "trebuchet ms", verdana, arial;}</style><style>#mermaid-1577142258919 {
color: rgb(0, 0, 0);
font: normal normal 400 normal 16px / normal "trebuchet ms", verdana, arial;
}</style><g transform="translate(0, 0)"><g class="output"><g class="clusters"><g class="cluster" id="connection" transform="translate(414.5390625,63.875)" style="opacity: 1;"><rect width="468.515625" height="111.75" x="-234.2578125" y="-55.875"></rect><g class="label" transform="translate(0, -41.875)" id="mermaid-1577142258919Text"><g transform="translate(-39.4375,-9.5)"><foreignObject width="78.875" height="19"><div xmlns="http://www.w3.org/1999/xhtml" style="display: inline-block; white-space: nowrap;">connection</div></foreignObject></g></g></g></g><g class="edgePaths"><g class="edgePath" style="opacity: 1;"><path class="path" d="M130.28125,65.25L155.28125,65.25L180.28125,65.25L205.78125,65.75" marker-end="url(#arrowhead106563)" style="fill:none"></path><defs><marker id="arrowhead106563" viewBox="0 0 10 10" refX="9" refY="5" markerUnits="strokeWidth" markerWidth="8" markerHeight="6" orient="auto"><path d="M 0 0 L 10 5 L 0 10 z" class="arrowheadPath" style="stroke-width: 1; stroke-dasharray: 1, 0;"></path></marker></defs></g><g class="edgePath" style="opacity: 1;"><path class="path" d="M619.9238137755102,57.00387755102041L648.796875,55.25L673.796875,55.25L698.796875,57.97618844777645" marker-end="url(#arrowhead106564)" style="fill:none"></path><defs><marker id="arrowhead106564" viewBox="0 0 10 10" refX="9" refY="5" markerUnits="strokeWidth" markerWidth="8" markerHeight="6" orient="auto"><path d="M 0 0 L 10 5 L 0 10 z" class="arrowheadPath" style="stroke-width: 1; stroke-dasharray: 1, 0;"></path></marker></defs></g><g class="edgePath" style="opacity: 1;"><path class="path" d="M698.796875,77.79732492758562L673.796875,82.5L648.796875,82.5L616.8659307753546,80.61188844929075" marker-end="url(#arrowhead106565)" style="fill:none"></path><defs><marker id="arrowhead106565" viewBox="0 0 10 10" refX="9" refY="5" markerUnits="strokeWidth" markerWidth="8" markerHeight="6" orient="auto"><path d="M 0 0 L 10 5 L 0 10 z" class="arrowheadPath" style="stroke-width: 1; stroke-dasharray: 1, 0;"></path></marker></defs></g></g><g class="edgeLabels"><g class="edgeLabel" transform="" style="opacity: 1;"><g transform="translate(0,0)" class="label"><foreignObject width="0" height="0"><div xmlns="http://www.w3.org/1999/xhtml" style="display: inline-block; white-space: nowrap;"><span class="edgeLabel"></span></div></foreignObject></g></g><g class="edgeLabel" transform="" style="opacity: 1;"><g transform="translate(0,0)" class="label"><foreignObject width="0" height="0"><div xmlns="http://www.w3.org/1999/xhtml" style="display: inline-block; white-space: nowrap;"><span class="edgeLabel"></span></div></foreignObject></g></g><g class="edgeLabel" transform="" style="opacity: 1;"><g transform="translate(0,0)" class="label"><foreignObject width="0" height="0"><div xmlns="http://www.w3.org/1999/xhtml" style="display: inline-block; white-space: nowrap;"><span class="edgeLabel"></span></div></foreignObject></g></g></g><g class="nodes"><g class="node" id="C" transform="translate(414.5390625,65.25)" style="opacity: 1;"><polygon points="9.75,0 408.765625,0 418.515625,-19.5 408.765625,-39 9.75,-39 0,-19.5" transform="translate(-209.2578125,19.5)" class="label-container"></polygon><g class="label" transform="translate(0,0)"><g transform="translate(-189.5078125,-9.5)"><foreignObject width="379.015625" height="19"><div xmlns="http://www.w3.org/1999/xhtml" style="display: inline-block; white-space: nowrap;">verify sender (1) ---&gt; pubsub &lt;---&gt; verify receiver (2)</div></foreignObject></g></g></g><g class="node" id="S" transform="translate(69.140625,65.25)" style="opacity: 1;"><rect rx="5" ry="5" x="-61.140625" y="-19.5" width="122.28125" height="39" class="label-container"></rect><g class="label" transform="translate(0,0)"><g transform="translate(-51.140625,-9.5)"><foreignObject width="102.28125" height="19"><div xmlns="http://www.w3.org/1999/xhtml" style="display: inline-block; white-space: nowrap;">sender (key 1)</div></foreignObject></g></g></g><g class="node" id="R" transform="translate(765.5,65.25)" style="opacity: 1;"><rect rx="5" ry="5" x="-66.703125" y="-19.5" width="133.40625" height="39" class="label-container"></rect><g class="label" transform="translate(0,0)"><g transform="translate(-56.703125,-9.5)"><foreignObject width="113.40625" height="19"><div xmlns="http://www.w3.org/1999/xhtml" style="display: inline-block; white-space: nowrap;">receiver (key 2)</div></foreignObject></g></g></g></g></g></g></svg>

After

Width:  |  Height:  |  Size: 16 KiB

26
diagrams/simplex2.mmd Normal file
View File

@ -0,0 +1,26 @@
sequenceDiagram
participant S as sender (client)
participant A as API
participant Q as pubsub
participant P as publisher
participant R as receiver (client)
note over R: sign subscription (1)
R ->> P: subscribe to messages
note over P: verify subscriber (1)
alt subscriber verified?
P -->> Q: subscribe
else
P ->> R: reject subscription
end
note over S: sign message (2)
S ->> A: send message
note over A: verify sender (2)
alt sender verified?
A -->> Q: queue message
activate Q
else
A ->> S: reject message
end
Q -->> P: take message
deactivate Q
P ->> R: deliver message

498
diagrams/simplex2.svg Normal file

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 20 KiB

View File

@ -13,6 +13,20 @@ The problems of existing chat solutions this system intends to solve:
- Visiblity of user profile information to chat system and other chat users.
## Requirements
- User profile is only visible to the proifle connections, but not to the chat network
- User profile is not stored on the server.
- Profile connections are not stored on the server.
- It should not be possible to construct the list of user connections by analysing server database or any logs.
- It should not be possible, other than by compromising the client, to send messages from another user profile.
- It should not be possible, other than by compromising all servers the user is connected to, to prevent message delivery to a user.
- All participants of the conversation should be able to:
- prove that the received messages were actually sent by another party.
- prove that the sent messages were received by another party.
- prove sent/received time/delivery order - with the solution below only timestamp of another party can be proven, not the actual time.
## Solution
- No phone numbers, user names and no DNS are used to identify to users (chat servers may choose to be accessible via DNS, but it is not required)
@ -82,6 +96,36 @@ Client apps should provide the following:
Prepared with [mermaid-js](https://mermaid-js.github.io/mermaid-live-editor)
## Client-server architecture
To allow sending the message when receiver client is not available, and to allow receiving the messages when the sender client is not available, the system relies on the client-server architecture with multiple servers.
The communication always happens through the servers that the recepient defines, that manages simplex connections (see below).
Servers store messages only until delivered to the recepients, they do not store any message history or delivery log.
Servers do not have visibility of the message senders and message types, they only have visibility of connection address that is equal to the hash of public key used to encrypt messages sent into the connection (hash of receiver's public key).
## Simplex connection - the main unit of network design
The network consists of multiple "simplex (non-duplex) connections". Access to each connection is controlled with unique (not shared with other connections) assymetric key pairs, separate for sender and the receiver. The sender and the receiver have private keys, and the server has associated public keys to verify participants.
The messages sent into the connection are encrypted and decrypted using another key pair - the recepient has the private key and the sender has the associated public key.
**Simplified simplex connection diagram:**
![Simplex connection diagram](/diagrams/simplex1.svg)
Connection is defined by sender's key 1 that is used to verify sender's messages and by receiver's key 2 that is used to verify subscription to messages (or requests to receive messages).
**Simplex connection operation:**
![Simplex connection operations](/diagrams/simplex2.svg)
Sequence diagram does not show E2EE - connection itself knows nothing about encryption between sender and receiver.
### Connections between user profiles
The system uses connections between user profiles (no information identifying users is stored on the servers) to send and to receive messages. Each connection is one-directional, from sender to recepient, without any correlation between connections and user profiles, and between 2 connections used to send and to receive messages to/from the same participants.