Commit 94523c58d1c1c111ae82129300ac14b1aa18c1a6
add articles section to more
Paul Frazee committed on 3/20/2016, 12:05:07 AMParent: 07de6e0bf8f8051cfea29058496ca70ae04e5c99
Files changed
tmpl/index.html.js | ||
---|---|---|
@@ -17,9 +17,9 @@ | ||
17 | 17 | <p class="description"> |
18 | 18 | Scuttlebot is an open source <strong>peer-to-peer log store</strong> used as a database, identity provider, and messaging system. |
19 | 19 | It features global replication, file-syncronization, and end-to-end encryption.<br> |
20 | 20 | <br> |
21 | - <a href="/guides/protocols/secure-scuttlebutt.html">Read about the protocol</a>. | |
21 | + <a href="/more/protocols/secure-scuttlebutt.html">Read about the protocol</a>. | |
22 | 22 | </p> |
23 | 23 | </div> |
24 | 24 | `, |
25 | 25 | content: installTheDatabase.content() |
tmpl/leftnav.part.js | ||
---|---|---|
@@ -105,21 +105,14 @@ | ||
105 | 105 | ${item(c, '/apis/community/ssb-notifier.html', 'SSB-Notifier')} |
106 | 106 | ${item(c, '/apis/community/patchwork-threads.html', 'Patchwork-Threads')} |
107 | 107 | </ul>` |
108 | 108 | |
109 | -module.exports['guides-protocols'] = (c) => `<ul class="nav"> | |
110 | - ${item(c, '/guides/protocols/secure-scuttlebutt.html', 'Secure Scuttlebutt')} | |
111 | - ${item(c, '/guides/protocols/secret-handshake.html', 'Secret Handshake')} | |
112 | - ${item(c, '/guides/protocols/private-box.html', 'Private Box')} | |
109 | +module.exports['more-protocols'] = (c) => `<ul class="nav"> | |
110 | + ${item(c, '/more/protocols/secure-scuttlebutt.html', 'Secure Scuttlebutt')} | |
111 | + ${item(c, '/more/protocols/secret-handshake.html', 'Secret Handshake')} | |
112 | + ${item(c, '/more/protocols/private-box.html', 'Private Box')} | |
113 | 113 | </ul>` |
114 | 114 | |
115 | -module.exports['guides-social-feed-app'] = (c) => `<ul class="nav"> | |
116 | - ${item(c, '/guides/social-feed-app/intro.html', 'Intro')} | |
117 | -</ul>` | |
118 | - | |
119 | -module.exports['guides-private-messaging-app'] = (c) => `<ul class="nav"> | |
120 | - ${item(c, '/guides/private-messaging-app/intro.html', 'Intro')} | |
121 | -</ul>` | |
122 | - | |
123 | -module.exports['guides-todo-list-app'] = (c) => `<ul class="nav"> | |
124 | - ${item(c, '/guides/todo-list-app/intro.html', 'Intro')} | |
115 | +module.exports['more-articles'] = (c) => `<ul class="nav"> | |
116 | + ${item(c, '/more/articles/design-challenge-avoid-centralization-and-singletons.html', 'Design Challenge: Avoid Centralization and Singletons')} | |
117 | + ${item(c, '/more/articles/design-challenge-sybil-attack.html', 'Design Challenge: Sybil Attacks')} | |
125 | 118 | </ul>` |
tmpl/tabs.part.js | ||
---|---|---|
@@ -8,9 +8,9 @@ | ||
8 | 8 | module.exports.sections = (c) => `<div class="tabs big"> |
9 | 9 | ${item(c, 'docs', '/docs/basics/install-the-database.html', 'Docs')} |
10 | 10 | ${item(c, 'apis', '/apis/scuttlebot/ssb.html', 'APIs')} |
11 | 11 | ${item(c, 'apps', '/apps/index.html', 'Apps')} |
12 | - ${item(c, 'guides', '/guides/protocols/secure-scuttlebutt.html', 'More')} | |
12 | + ${item(c, 'more', '/more/protocols/secure-scuttlebutt.html', 'More')} | |
13 | 13 | </div>` |
14 | 14 | |
15 | 15 | module.exports.docs = (c) => `<div class="tabs small"> |
16 | 16 | ${item(c, 'docs-basics', '/docs/basics/install-the-database.html', 'Basics')} |
@@ -26,7 +26,8 @@ | ||
26 | 26 | ${item(c, 'apis-pull-stream', '/apis/pull-stream/pull-stream.html', 'Pull Stream')} |
27 | 27 | ${item(c, 'apis-community', '/apis/community/ssbify.html', 'Community')} |
28 | 28 | </div>` |
29 | 29 | |
30 | -module.exports.guides = (c) => `<div class="tabs small"> | |
31 | - ${item(c, 'guides-protocols', '/guides/protocols/secure-scuttlebutt.html', 'Protocols')} | |
30 | +module.exports.more = (c) => `<div class="tabs small"> | |
31 | + ${item(c, 'more-protocols', '/more/protocols/secure-scuttlebutt.html', 'Protocols')} | |
32 | + ${item(c, 'more-articles', '/more/articles/design-challenge-avoid-centralization-and-singletons.html', 'Articles')} | |
32 | 33 | </div>` |
tmpl/guides/private-messaging-app/intro.html.js | ||
---|---|---|
@@ -1,10 +1,0 @@ | ||
1 | -var page = require('../../page.part') | |
2 | -module.exports = () => page({ | |
3 | - section: 'guides', | |
4 | - tab: 'guides-private-messaging-app', | |
5 | - path: '/guides/private-messaging-app/intro.html', | |
6 | - content: ` | |
7 | - <h2>Lets Write: a Private Messaging App</h2> | |
8 | - <p>todo</p> | |
9 | - ` | |
10 | -}) |
tmpl/guides/protocols/private-box.html.js | ||
---|---|---|
@@ -1,189 +1,0 @@ | ||
1 | -var page = require('../../page.part') | |
2 | -var com = require('../../com.part') | |
3 | - | |
4 | -module.exports = () => page({ | |
5 | - title: 'Private Box', | |
6 | - section: 'guides', | |
7 | - tab: 'guides-protocols', | |
8 | - path: '/guides/protocols/private-box.html', | |
9 | - content: ` | |
10 | - <h2>Private Box</h2> | |
11 | - <p> | |
12 | - Private-box is a format for encrypting a private message to many parties. | |
13 | - You can <strong><a href="https://github.com/auditdrivencrypto/private-box">find the repository on GitHub</a></strong>. | |
14 | - </p> | |
15 | - | |
16 | - <h2 id="properties">Properties</h2> | |
17 | - <p> | |
18 | - This protocol was designed for use with secure-scuttlebutt. | |
19 | - In this place, messages are placed in public, and the sender is known via a signature, | |
20 | - but we can hide the recipient and the content. | |
21 | - </p> | |
22 | - | |
23 | - <h4 id="-recipients-are-hidden-">Recipients are hidden.</h4> | |
24 | - <p> | |
25 | - An eaves-dropper cannot know the recipients or their number. | |
26 | - Since the message is encrypted to each recipient, and then placed in public, | |
27 | - to receive a message you will have to decrypt every message posted. | |
28 | - This would not be scalable if you had to decrypt every message on the internet, | |
29 | - but if you can restrict the number of messages you might have to decrypt, | |
30 | - then it's reasonable. For example, if you frequented a forum which contained these messages, | |
31 | - then it would only be a reasonable number of messages, and posting a message would only | |
32 | - reveal that you where talking to some other member of that forum. | |
33 | - </p> | |
34 | - <p>Hiding access to such a forum is another problem that's out of the current scope.</p> | |
35 | - | |
36 | - <h4 id="-the-number-of-recipients-are-hidden-">The number of recipients are hidden.</h4> | |
37 | - <p> | |
38 | - If the number of recipients was not hidden, then sometimes it would be possible | |
39 | - to deanonymise the recipients, if there was a large group discussion with | |
40 | - an unusual number of recipients. Encrypting the number of recipients means that, | |
41 | - when a message is not encrypted to you, you will attempt to decrypt same number of times | |
42 | - as the maximum recipients. | |
43 | - </p> | |
44 | - | |
45 | - <h4 id="-a-valid-recipient-does-not-know-the-other-recipients-">A valid recipient does not know the other recipients.</h4> | |
46 | - <p> | |
47 | - A valid recipient knows the number of recipients but now who they are. | |
48 | - This is more a sideeffect of the design than an intentional design element. | |
49 | - The plaintext contents may reveal the recipients, if needed. | |
50 | - </p> | |
51 | - | |
52 | - <h4 id="-by-providing-the-key-for-a-message-an-outside-party-could-decrypt-the-message-">By providing the key for a message, an outside party could decrypt the message.</h4> | |
53 | - <p> | |
54 | - When you tell someone a secret you must trust them not to reveal it. | |
55 | - Anyone who knows the key could reveal that to some other party who could then read the message content, | |
56 | - but not the recipients (unless the sender revealed the ephemeral secret key). | |
57 | - </p> | |
58 | - | |
59 | - <h2 id="assumptions">Assumptions</h2> | |
60 | - <p> | |
61 | - Messages will be posted in public, so that the sender is likely to be known, | |
62 | - and everyone can read the messages. (This makes it possible to hide the recipient, | |
63 | - but probably not the sender.) | |
64 | - </p> | |
65 | - <p>Resisting traffic analysis of the timing or size of messages is out of scope of this spec.</p> | |
66 | - | |
67 | - <h2 id="prior-art">Prior Art</h2> | |
68 | - <h4 id="-pgp-">PGP</h4> | |
69 | - <p> | |
70 | - In PGP the recipient, the sender, and the subject are sent as plaintext. | |
71 | - If the recipient is known, then the metadata graph of who is communicating with who can be read, | |
72 | - which, since it is easier to analyze than the content, is important to protect. | |
73 | - </p> | |
74 | - <h4 id="-sodium-seal-">Sodium seal</h4> | |
75 | - <p> | |
76 | - The Sodium library provides a <em>seal</em> function that generates an ephemeral keypair, | |
77 | - derives a shared key to encrypt a message, and then sends the ephemeral public key and the message. | |
78 | - The recipient is hidden, and it is forward secure if the sender throws out the ephemeral key. | |
79 | - However, it's only possible to have one recipient. | |
80 | - </p> | |
81 | - | |
82 | - <h4 id="-minilock-">Minilock</h4> | |
83 | - <p> | |
84 | - Minilock uses a similar approach to <code>private-box</code> but does not hide the | |
85 | - number of recipients. In the case of a group discussion where multiple rounds | |
86 | - of messages are sent to everyone, this may enable an eavesdropper to deanonymize | |
87 | - the participiants of a discussion if the sender of each message is known. | |
88 | - </p> | |
89 | - | |
90 | - <h2 id="api">API</h2> | |
91 | - | |
92 | - <h4 id="-encrypt-plaintext-buffer-recipients-array-curve25519_pk-">encrypt (plaintext Buffer, recipients Array<curve25519_pk>)</h4> | |
93 | - <p> | |
94 | - Takes a plaintext buffer of the message you want to encrypt, | |
95 | - and an array of recipient public keys. | |
96 | - Returns a message that is encrypted to all recipients | |
97 | - and openable by them with <code>PrivateBox.decrypt</code>. | |
98 | - The recipients must be between 1 and 7 items long. | |
99 | - </p> | |
100 | - <p> | |
101 | - The encrypted length will be <code>56 + (recipients.length * 33) + plaintext.length</code> bytes long, | |
102 | - between 89 and 287 bytes longer than the plaintext. | |
103 | - </p> | |
104 | - | |
105 | - <h4 id="-decrypt-cyphertext-buffer-secretkey-curve25519_sk-">decrypt (cyphertext Buffer, secretKey curve25519_sk)</h4> | |
106 | - <p> | |
107 | - Attempt to decrypt a private-box message, using your secret key. | |
108 | - If you where an intended recipient then the plaintext will be returned. | |
109 | - If it was not for you, then <code>undefined</code> will be returned. | |
110 | - </p> | |
111 | - | |
112 | - <h2 id="protocol">Protocol</h2> | |
113 | - <h4 id="-encryption-">Encryption</h4> | |
114 | - <p>Private-box generates:</p> | |
115 | - <ul> | |
116 | - <li><code>ephemeral</code>: an ephemeral curve25519 keypair that will only be used with this message.</li> | |
117 | - <li><code>body_key</code>: a random key that will be used to encrypt the plaintext body.</li> | |
118 | - </ul> | |
119 | - <p> | |
120 | - First, private-box outputs the ephemeral public key, then multiplies each recipient public key | |
121 | - with its secret to produce ephemeral shared keys (<code>shared_keys[1..n]</code>). | |
122 | - Then, private-box concatenates <code>body_key</code> with the number of recipients, | |
123 | - encrypts that to each shared key, and concatenates the encrypted body. | |
124 | - </p> | |
125 | - ${ com.code({ js: ` | |
126 | -function encrypt (plaintext, recipients) { | |
127 | - var ephemeral = keypair() | |
128 | - var nonce = random(24) | |
129 | - var body_key = random(32) | |
130 | - var body_key_with_length = concat([ | |
131 | - body_key, | |
132 | - recipients.length | |
133 | - ]) | |
134 | - return concat([ | |
135 | - nonce, | |
136 | - ephemeral.publicKey, | |
137 | - concat(recipients.map(function (publicKey) { | |
138 | - return secretbox( | |
139 | - body_key_with_length, | |
140 | - nonce, | |
141 | - scalarmult(publicKey, ephemeral.secretKey) | |
142 | - ) | |
143 | - }), | |
144 | - secretbox(plaintext, nonce, body_key) | |
145 | - ]) | |
146 | -}` }) } | |
147 | - | |
148 | - <h4 id="-decryption-">Decryption</h4> | |
149 | - <p> | |
150 | - <code>private-box</code> takes the nonce and ephemeral public key, | |
151 | - multiplies that with your secret key, then tests each possible | |
152 | - recipient slot until it either decrypts a key or runs out of slots. | |
153 | - If it runs out of slots, the message was not addressed to you, | |
154 | - so <code>undefined</code> is returned. Else, the message is found and the body | |
155 | - is decrypted. | |
156 | - </p> | |
157 | - ${ com.code({ js: ` | |
158 | -function decrypt (cyphertext, secretKey) { | |
159 | - var next = reader(cyphertext) // next() will read | |
160 | - // the passed N bytes | |
161 | - var nonce = next(24) | |
162 | - var publicKey = next(32) | |
163 | - var sharedKey = salarmult(publicKey, secretKey) | |
164 | - | |
165 | - for(var i = 0; i < 7; i++) { | |
166 | - var maybe_key = next(33) | |
167 | - var key_with_length = secretbox_open( | |
168 | - maybe_key, | |
169 | - nonce, | |
170 | - sharedKey | |
171 | - ) | |
172 | - if (key_with_length) { // decrypted! | |
173 | - var key = key_with_length.slice(0, 32) | |
174 | - var length = key_with_length[32] | |
175 | - return secretbox_open( | |
176 | - key, | |
177 | - cyphertext.slice( | |
178 | - 56 + 33*(length+1), | |
179 | - cyphertext.length | |
180 | - ), | |
181 | - ) | |
182 | - } | |
183 | - } | |
184 | - // this message was not addressed | |
185 | - // to the owner of secretKey | |
186 | - return undefined | |
187 | -}` }) } | |
188 | - ` | |
189 | -}) |
tmpl/guides/protocols/secret-handshake.html.js | ||
---|---|---|
@@ -1,16 +1,0 @@ | ||
1 | -var page = require('../../page.part') | |
2 | -module.exports = () => page({ | |
3 | - title: 'Secret Handshake', | |
4 | - section: 'guides', | |
5 | - tab: 'guides-protocols', | |
6 | - path: '/guides/protocols/secret-handshake.html', | |
7 | - content: ` | |
8 | - <h2>Secret Handshake</h1> | |
9 | - <p> | |
10 | - Secret Handshake is an encrypted channel protocol based on a mutually authenticating key agreement handshake, with forward secure identity metadata. | |
11 | - It's used by Scuttlebot to authenticate and encrypt peer connections. | |
12 | - </p> | |
13 | - <p><a href="./shs.pdf">Read the White Paper</a></p> | |
14 | - `, | |
15 | - next: ['/guides/protocols/private-box.html', 'Private Box'] | |
16 | -}) |
tmpl/guides/protocols/secure-scuttlebutt.html.js | ||
---|---|---|
@@ -1,185 +1,0 @@ | ||
1 | -var page = require('../../page.part') | |
2 | -var com = require('../../com.part') | |
3 | - | |
4 | -module.exports = () => page({ | |
5 | - title: 'Secure Scuttlebutt', | |
6 | - section: 'guides', | |
7 | - tab: 'guides-protocols', | |
8 | - path: '/guides/protocols/secure-scuttlebutt.html', | |
9 | - content: ` | |
10 | - <h2>Secure Scuttlebutt</h2> | |
11 | - <p>Secure Scuttlebutt is a database protocol for unforgeable append-only message feeds.</p> | |
12 | - <p> | |
13 | - "Unforgeable" means that only the owner of a feed can update that feed, as enforced by digital signing (see <a href="#security-properties">Security properties</a>). | |
14 | - This property makes Secure Scuttlebutt useful for peer-to-peer applications. | |
15 | - Secure Scuttlebutt also makes it easy to encrypt messages. | |
16 | - </p> | |
17 | - | |
18 | - <hr> | |
19 | - | |
20 | - <h2>Overview</h2> | |
21 | - <p> | |
22 | - Scuttlebot forms a global cryptographic social network with its peers. | |
23 | - Each user is identified by a public key, and publishes a log of signed messages, which other users follow socially. | |
24 | - </p> | |
25 | - <p> | |
26 | - Scuttlebot searches the P2P mesh for new messages and files from followed users and from FoaFs. | |
27 | - The messages and files are stored locally, indefinitely, for applications to read. | |
28 | - </p> | |
29 | - | |
30 | - <h3>Identity</h3> | |
31 | - <p> | |
32 | - Users are identified by confirmations and signals in the social graph. | |
33 | - This is known as a Web-of-Trust. | |
34 | - There is no global registry of usernames. | |
35 | - Instead, users name themselves, and share petnames for each other. | |
36 | - </p> | |
37 | - <p> | |
38 | - Discovery occurs by examining the social graph, or by out-of-band sharing. | |
39 | - Applications can analyze the follow-graph, and look for "flag" messages, to determine who is trust-worthy in the network. | |
40 | - </p> | |
41 | - | |
42 | - <h3>Pub Servers</h3> | |
43 | - <p> | |
44 | - "Pubs" are bot-users that have public IPs. | |
45 | - They follow users and rehost the messages to other peers, ensuring good uptime and no firewall blockage. | |
46 | - </p> | |
47 | - <p> | |
48 | - Pubs have no special privileges, and are not trusted by users. | |
49 | - However, because Scuttlebot has no DHT or NAT-traversal utilities, users must "join" a Pub to distribute their messages on the WAN. | |
50 | - </p> | |
51 | - <p> | |
52 | - Scuttlebot can change Pubs, or join more than one, and sync directly over Wifi. | |
53 | - Identity is not tied to the Pubs. | |
54 | - </p> | |
55 | - | |
56 | - <hr> | |
57 | - | |
58 | - <h2 id="concepts">Concepts in Depth</h2> | |
59 | - <p>Building upon Secure Scuttlebutt requires understanding a few concepts that it uses to ensure the unforgeability of message feeds.</p> | |
60 | - | |
61 | - <h3 id="identities">Identities</h3> | |
62 | - <p> | |
63 | - An identity is simply a <a href="http://ed25519.cr.yp.to/">ed25519 key pair</a>. | |
64 | - The public key is used as the identifier. | |
65 | - </p> | |
66 | - <p> | |
67 | - There is no worldwide store of identities. | |
68 | - Users must exchange pubkeys, either by publishing them on their feeds, or out-of-band. | |
69 | - </p> | |
70 | - | |
71 | - <h3 id="feeds">Feeds</h3> | |
72 | - <p> | |
73 | - A feed is a signed append-only sequence of messages. | |
74 | - Each identity has exactly one feed. | |
75 | - </p> | |
76 | - <p> | |
77 | - Note that append-only means you cannot delete an existing message, or change your history. | |
78 | - This is enforced by a per-feed blockchain. | |
79 | - This is to ensure the entire network converges on the same state. | |
80 | - </p> | |
81 | - | |
82 | - <h3 id="messages">Messages</h3> | |
83 | - <p>Each message contains:</p> | |
84 | - <ul> | |
85 | - <li>A signature</li> | |
86 | - <li>The signing public key</li> | |
87 | - <li>A content-hash of the previous message</li> | |
88 | - <li>A sequence number</li> | |
89 | - <li>A timestamp</li> | |
90 | - <li>An identifier of the hashing algorithm in use (currently only "sha256" is supported)</li> | |
91 | - <li>A content object</li> | |
92 | - </ul> | |
93 | - <p>Here's an example message:</p> | |
94 | - ${ com.code({ js: `{ | |
95 | - "previous": "%26AC+gU0t74jRGVeDY01...MnutGGHM=.sha256", | |
96 | - "author": "@hxGxqPrplLjRG2vtjQL87...0nNwE=.ed25519", | |
97 | - "sequence": 216, | |
98 | - "timestamp": 1442590513298, | |
99 | - "hash": "sha256", | |
100 | - "content": { | |
101 | - "type": "vote", | |
102 | - "vote": { | |
103 | - "link": "%WbQ4dq0m/zu5jxll9zUb...KjZ80JvI=.sha256", | |
104 | - "value": 1 | |
105 | - } | |
106 | - }, | |
107 | - "signature": "Sjq1C3yiKdmi1TWvNqxI...gmAQ==.sig.ed25519" | |
108 | -}` }) } | |
109 | - | |
110 | - <h3 id="entity-references-links-">Entity References (Links)</h3> | |
111 | - <p> | |
112 | - Messages can reference three types of Secure Scuttlebutt entities: messages, feeds, and blobs (i.e. files). | |
113 | - Messages and blobs are referred to by their hashes, but a feed is referred to by its signing public key. | |
114 | - </p> | |
115 | - | |
116 | - <h3 id="confidentiality">Confidentiality</h3> | |
117 | - <p> | |
118 | - For private sharing, Scuttlebot uses <a href="http://doc.libsodium.org/">libsodium</a> to encrypt confidential log-entries. | |
119 | - Feed IDs are public keys, and so once two feeds are mutually following each other, they can exchange confidential data freely. | |
120 | - </p> | |
121 | - | |
122 | - <h3 id="following">Following</h3> | |
123 | - <p> | |
124 | - Users choose which feeds to synchronize by following them. | |
125 | - Presently, <a href="/modules/scuttlebot-replicate.html">Scuttlebot's replicate plugin</a>, which is enabled by default, looks on the master user's feed for <code>type:contact</code> messages to know which users are currently followed. | |
126 | - </p> | |
127 | - | |
128 | - <h3 id="replication">Replication</h3> | |
129 | - <p> | |
130 | - Since feeds are append-only, replication is simple: request all messages in the feed that are newer than the latest message you know about. | |
131 | - Scuttlebot maintains a table of known peers, which it cycles through, asking for updates for all followed feeds. | |
132 | - </p> | |
133 | - | |
134 | - <h3 id="gossip">Gossip</h3> | |
135 | - <p> | |
136 | - The protocol creates a <a href="https://en.wikipedia.org/wiki/Gossip_protocol">global gossip network</a>. | |
137 | - This means that information is able to distribute across multiple machines, without requiring direct connections between them. | |
138 | - </p> | |
139 | - <p><img src="/img/gossip-graph1.png" alt="Gossip graph"></p> | |
140 | - <p>Even though Alice and Dan lack a direct connection, they can still exchange feeds:</p> | |
141 | - <p><img src="/img/gossip-graph2.png" alt="Gossip graph 2"></p> | |
142 | - <p> | |
143 | - This is because gossip creates "transitive" connections between computers. | |
144 | - Dan's messages travel through Carla and the Pub to reach Alice, and visa-versa. | |
145 | - </p> | |
146 | - | |
147 | - <h3 id="lan-connectivity">LAN connectivity</h3> | |
148 | - <p> | |
149 | - SSB is hostless: each computer installs the same copy of software and has equal rights in the network. | |
150 | - Devices discover each other over the LAN with multicast UDP and sync automatically. | |
151 | - </p> | |
152 | - | |
153 | - <h3 id="pub-servers">Pub Servers</h3> | |
154 | - <p> | |
155 | - To sync across the Internet, "Pub" nodes run at public IPs and follow users. | |
156 | - They are essentially mail-bots which improve uptime and availability. | |
157 | - Users generate invite-codes to command Pubs to follow their friends. | |
158 | - The Scuttlebot community runs some Pubs, and anybody can create and introduce their own. | |
159 | - </p> | |
160 | - | |
161 | - <h2 id="security-properties">Security properties</h2> | |
162 | - <p> | |
163 | - Secure Scuttlebutt maintains useful security properties even when it is connected to a malicious Secure Scuttlebutt database. | |
164 | - This makes it ideal as a store for peer-to-peer applications. | |
165 | - </p> | |
166 | - <p> | |
167 | - Imagine that we want to read from a feed for which we know the identity, but we're connected to a malicious Secure Scuttlebutt instance. | |
168 | - As long as the malicious database does not have the private key: | |
169 | - </p> | |
170 | - <ul> | |
171 | - <li>The malicious database cannot create a new feed with the same identifier</li> | |
172 | - <li>The malicious database cannot write new fake messages to the feed</li> | |
173 | - <li>The malicious database cannot reorder the messages in the feed</li> | |
174 | - <li>The malicious database cannot send us a new copy of the feed that omits messages from the middle</li> | |
175 | - <li>The malicious database <em>can</em> refuse to send us the feed, or only send us the first <em>N</em> messages in the feed</li> | |
176 | - <li>Messages may optionally be encrypted</li> | |
177 | - </ul> | |
178 | - <p> | |
179 | - Additionally there is a protection from the feed owner, through the blockchain. | |
180 | - The <code>previous</code> content-hash them from changing the feed history after publishing, as a newly-created message wouldn't match the hash of later messages which were already replicated. | |
181 | - This ensures the append-only constraint, and thus safe network convergence. | |
182 | - </p> | |
183 | - `, | |
184 | - next: ['/guides/protocols/secret-handshake.html', 'Secret Handshake'] | |
185 | -}) |
tmpl/guides/protocols/shs.pdf | ||
---|---|---|
The diff is too large to show. Use a local git client to view these changes. Old file size: 219079 bytes New file size: 0 bytes |
tmpl/guides/protocols/social.html.js | ||
---|---|---|
@@ -1,48 +1,0 @@ | ||
1 | -var page = require('../../page.part') | |
2 | -module.exports = () => page({ | |
3 | - title: 'Social network', | |
4 | - section: 'docs', | |
5 | - tab: 'guides-protocols', | |
6 | - path: '/social/social-network.html', | |
7 | - content: ` | |
8 | - <h2>Social network</h2> | |
9 | - <p> | |
10 | - Scuttlebot forms a global cryptographic social network with its peers. | |
11 | - Each user is identified by a public key, and publishes a log of signed messages, which other users "follow." | |
12 | - </p> | |
13 | - <p> | |
14 | - Scuttlebot searches the P2P mesh for new messages and files from followed users and from FoaFs. | |
15 | - The messages and files are stored locally, indefinitely, for applications to read. | |
16 | - </p> | |
17 | - | |
18 | - <h3>Identity</h3> | |
19 | - <p> | |
20 | - Users are identified by confirmations in the social graph. | |
21 | - This is known as a Web-of-Trust. | |
22 | - There is no global registry of usernames. | |
23 | - Instead, users name themselves, and share petnames for each other. | |
24 | - </p> | |
25 | - <p> | |
26 | - Discovery occurs by examining the social graph, or by out-of-band sharing. | |
27 | - Applications can analyze the follow-graph, and look for "flag" messages, to determine who is trust-worthy in the network. | |
28 | - </p> | |
29 | - | |
30 | - <h3>Pub Servers</h3> | |
31 | - <p> | |
32 | - "Pubs" are bot-users that have public IPs. | |
33 | - They follow users and rehost the messages to other peers, ensuring good uptime and no firewall blockage. | |
34 | - </p> | |
35 | - <p> | |
36 | - Pubs have no special privileges, and are not trusted by users. | |
37 | - However, because Scuttlebot has no DHT or NAT-traversal utilities, users must "join" a Pub to distribute their messages on the WAN. | |
38 | - </p> | |
39 | - <p> | |
40 | - Scuttlebot can change Pubs, or join more than one, and sync directly over Wifi. | |
41 | - Identity is not tied to the Pubs. | |
42 | - </p> | |
43 | - <p class="next"><a href="/docs/social/follow-users.html">Follow users</a></p> | |
44 | - <ul class="see-also"> | |
45 | - <li><a href="/whitepapers/secure-scuttlebutt.html">Secure Scuttlebutt</a></li> | |
46 | - </ul> | |
47 | - ` | |
48 | -}) |
tmpl/guides/social-feed-app/intro.html.js | ||
---|---|---|
@@ -1,10 +1,0 @@ | ||
1 | -var page = require('../../page.part') | |
2 | -module.exports = () => page({ | |
3 | - section: 'guides', | |
4 | - tab: 'guides-social-feed-app', | |
5 | - path: '/guides/social-feed-app/intro.html', | |
6 | - content: ` | |
7 | - <h2>Lets Write: a Social Feed App</h2> | |
8 | - <p>todo</p> | |
9 | - ` | |
10 | -}) |
tmpl/guides/todo-list-app/intro.html.js | ||
---|---|---|
@@ -1,10 +1,0 @@ | ||
1 | -var page = require('../../page.part') | |
2 | -module.exports = () => page({ | |
3 | - section: 'guides', | |
4 | - tab: 'guides-todo-list-app', | |
5 | - path: '/guides/todo-list-app/intro.html', | |
6 | - content: ` | |
7 | - <h2>Lets Write: a Todo List App</h2> | |
8 | - <p>todo</p> | |
9 | - ` | |
10 | -}) |
tmpl/more/articles/design-challenge-avoid-centralization-and-singletons.html.js | ||
---|---|---|
@@ -1,0 +1,9 @@ | ||
1 | +var md = require('../../../markdown') | |
2 | +var page = require('../../page.part') | |
3 | +module.exports = () => page({ | |
4 | + title: 'Design Challenge: Avoid Centralization and Singletons', | |
5 | + section: 'more', | |
6 | + tab: 'more-articles', | |
7 | + path: '/more/articles/design-challenge-avoid-centralization-and-singletons.html', | |
8 | + content: md.doc(__dirname+'/design-challenge-avoid-centralization-and-singletons.md') | |
9 | +}) |
tmpl/more/articles/design-challenge-avoid-centralization-and-singletons.md | ||
---|---|---|
@@ -1,0 +1,42 @@ | ||
1 | +# Design Challenge: Avoid Centralization and Singletons | |
2 | + | |
3 | +SecureScuttlebutt goes out of it's way to avoid both centralization and singletons. | |
4 | + | |
5 | +## Avoiding Centralization | |
6 | + | |
7 | +The danger of centralization is obvious: it creates a single point of failure that can easily be attacked, or act as an attacker. | |
8 | +And, it creates a monoculture of information, as the central point starts to control [what information is trusted, or ranked highly](./using-trust-in-open-networks.html). | |
9 | + | |
10 | +To avoid centralization, you make every peer the same. | |
11 | + | |
12 | +Due to limitations inherent in the modern Internet, this is hard to do. | |
13 | +Home routers perform Network Address Translation to make a single IP address behave like many, which makes it simple to make outgoing connections, but difficult to receive incoming connections. | |
14 | + | |
15 | +Most networked applications, including SSB, solve this by connecting to publicly addressable servers. | |
16 | +Sometimes P2P systems use clever techniques ([TURN](http://en.wikipedia.org/wiki/Traversal_Using_Relays_around_NAT), [STUN](http://en.wikipedia.org/wiki/STUN), [ICE](http://en.wikipedia.org/wiki/Interactive_Connectivity_Establishment)) to reduce the role of the servers, but it's still necessary to have them. | |
17 | + | |
18 | + | |
19 | +SSB uses the so-called "Pub" servers to rehost the feeds and blobs of the users, which has the added benefit of improving network availability (two peers don't need to be online at the same time to exchange messages). | |
20 | +However, amongst the community, they're considered a centralization risk. | |
21 | + | |
22 | +We mitigate the risk by avoiding putting any special authority or trust in the Pubs. | |
23 | +Users may be hosted by many pubs at once, and can change pubs without losing the data or identity. | |
24 | +A pub server may go down, and others will still provide service. | |
25 | + | |
26 | +Contrast this with email servers, which are ostensibly decentralized (you may run your own email server) but you must have *exactly one* email server, and if it is down you will not receive email, which makes running your own email server a considerable hassle (not to mention handling spam). | |
27 | + | |
28 | +## Avoiding Singletons | |
29 | + | |
30 | +SecureScuttlebutt also avoids P2P structures that represent singletons - specifically, it avoids using a [Distributed Hash Table](http://en.wikipedia.org/wiki/Distributed_hash_table) or a [global blockchain](http://en.wikipedia.org/wiki/Bitcoin#Block_chain). | |
31 | + | |
32 | +SSB avoids P2P singletons partially to show that it can be done (most P2P designs use DHT or global blockchains) and also because those are just P2P versions of centralized systems. | |
33 | +Social Networks are already constructed around a decentralized experience. | |
34 | +Popular social networks (fb, twitter) have centralized implementations, but you use them to interact with your _peers_, so on that level they are P2P. | |
35 | + | |
36 | +SecureScuttlebutt takes this decentralized experience and maps the networking layer (the key part of the implementation) on top of the decentralized human/user network. | |
37 | +It would be a shame to go to all that trouble to decentralize, but then adopt a singleton. | |
38 | +Also, global blockchains are heavy (require nodes to store entire chain, and to waste CPU power) and DHTs are susceptible to spam. | |
39 | +These structures also both make the network unprivate, by making all information available globally. | |
40 | + | |
41 | +That said, like any good tool, SSB has been built to interoperate with other programs. | |
42 | +Though it's important to us that core remain viable without singletons, the community is free to add protocols wherever they see fit, and is encouraged to do so. |
tmpl/more/articles/design-challenge-sybil-attack.html.js | ||
---|---|---|
@@ -1,0 +1,9 @@ | ||
1 | +var md = require('../../../markdown') | |
2 | +var page = require('../../page.part') | |
3 | +module.exports = () => page({ | |
4 | + title: 'Design Challenge: Sybil Attacks', | |
5 | + section: 'more', | |
6 | + tab: 'more-articles', | |
7 | + path: '/more/articles/design-challenge-sybil-attack.html', | |
8 | + content: md.doc(__dirname+'/design-challenge-sybil-attack.md') | |
9 | +}) |
tmpl/more/articles/design-challenge-sybil-attack.md | ||
---|---|---|
@@ -1,0 +1,35 @@ | ||
1 | +# Design Challenge: Sybil Attacks | |
2 | + | |
3 | +If it is possible for an anyone to connect to a computer system then it may be possible to interfere with the operation of that system, and defenses against interference must be designed in. | |
4 | + | |
5 | +For example, email's design is vulnerable to spam. | |
6 | +To send someone an email, all that is required is to have their email address; email is unsolicited messaging, so it's easy to send nuisance or fraud emails. | |
7 | + | |
8 | +### Spam Filters | |
9 | + | |
10 | +Email systems deal with spam by filtering it out. | |
11 | +There are two basic approaches: | |
12 | +The simplest is *pattern matching* - messages are compared to models of the sort of messages that spammers send. | |
13 | +This produces an arms race between spammers and spam filterers. | |
14 | +Spammers must strive to create messages which beat the filter, while filterers have to improve their model. | |
15 | + | |
16 | +One particularly interesting example of this is (snail) mail advertisers that employ [handwriting services](http://www.writeonresults.com/) to write the addresses on their envelopes. | |
17 | +This fools the receiver into believing that an actual human sent them the letter making them much more likely to open it. | |
18 | +(This is even being [automated](https://hellobond.com/).) | |
19 | + | |
20 | +### Social Networks | |
21 | + | |
22 | +The other approach is to use social/trust networks. | |
23 | +Services like Facebook or Twitter are significantly less vulnerable to spam (if you dont consider the ads spam). | |
24 | +Instead of receiving personal messages from anyone one who knows your id/address on a social network, you only receive messages from other users you have "followed" or "friended". | |
25 | + | |
26 | +I like to call this a "Solicited Spam" system. | |
27 | +Following someone on Twitter means you think they are human, or at least, an amusing bot. | |
28 | +This is actually a pretty strong signal. | |
29 | +Email doesn't an explicit social network, but the best spam filtered email systems (like gmail) can use the implicit social network in email: if I send you and email and you reply then we are "friends". | |
30 | + | |
31 | +Then graph analysis can be applied to the friend network - spammers may be isolated, or clustered together and can be filtered out. | |
32 | + | |
33 | +By building SecureScuttlebutt around a social network, preventing spam becomes easy. | |
34 | +Since, in a social network application, you only communicate with trusted peers (friends) anyway, and there is usually an explicit "follow" mechanism which expresses who you trust, and humans are pretty good at detecting frauds. | |
35 | +This is why SSB was made as an inherently social system. |
tmpl/more/protocols/private-box.html.js | ||
---|---|---|
@@ -1,0 +1,189 @@ | ||
1 | +var page = require('../../page.part') | |
2 | +var com = require('../../com.part') | |
3 | + | |
4 | +module.exports = () => page({ | |
5 | + title: 'Private Box', | |
6 | + section: 'more', | |
7 | + tab: 'more-protocols', | |
8 | + path: '/more/protocols/private-box.html', | |
9 | + content: ` | |
10 | + <h2>Private Box</h2> | |
11 | + <p> | |
12 | + Private-box is a format for encrypting a private message to many parties. | |
13 | + You can <strong><a href="https://github.com/auditdrivencrypto/private-box">find the repository on GitHub</a></strong>. | |
14 | + </p> | |
15 | + | |
16 | + <h2 id="properties">Properties</h2> | |
17 | + <p> | |
18 | + This protocol was designed for use with secure-scuttlebutt. | |
19 | + In this place, messages are placed in public, and the sender is known via a signature, | |
20 | + but we can hide the recipient and the content. | |
21 | + </p> | |
22 | + | |
23 | + <h4 id="-recipients-are-hidden-">Recipients are hidden.</h4> | |
24 | + <p> | |
25 | + An eaves-dropper cannot know the recipients or their number. | |
26 | + Since the message is encrypted to each recipient, and then placed in public, | |
27 | + to receive a message you will have to decrypt every message posted. | |
28 | + This would not be scalable if you had to decrypt every message on the internet, | |
29 | + but if you can restrict the number of messages you might have to decrypt, | |
30 | + then it's reasonable. For example, if you frequented a forum which contained these messages, | |
31 | + then it would only be a reasonable number of messages, and posting a message would only | |
32 | + reveal that you where talking to some other member of that forum. | |
33 | + </p> | |
34 | + <p>Hiding access to such a forum is another problem that's out of the current scope.</p> | |
35 | + | |
36 | + <h4 id="-the-number-of-recipients-are-hidden-">The number of recipients are hidden.</h4> | |
37 | + <p> | |
38 | + If the number of recipients was not hidden, then sometimes it would be possible | |
39 | + to deanonymise the recipients, if there was a large group discussion with | |
40 | + an unusual number of recipients. Encrypting the number of recipients means that, | |
41 | + when a message is not encrypted to you, you will attempt to decrypt same number of times | |
42 | + as the maximum recipients. | |
43 | + </p> | |
44 | + | |
45 | + <h4 id="-a-valid-recipient-does-not-know-the-other-recipients-">A valid recipient does not know the other recipients.</h4> | |
46 | + <p> | |
47 | + A valid recipient knows the number of recipients but now who they are. | |
48 | + This is more a sideeffect of the design than an intentional design element. | |
49 | + The plaintext contents may reveal the recipients, if needed. | |
50 | + </p> | |
51 | + | |
52 | + <h4 id="-by-providing-the-key-for-a-message-an-outside-party-could-decrypt-the-message-">By providing the key for a message, an outside party could decrypt the message.</h4> | |
53 | + <p> | |
54 | + When you tell someone a secret you must trust them not to reveal it. | |
55 | + Anyone who knows the key could reveal that to some other party who could then read the message content, | |
56 | + but not the recipients (unless the sender revealed the ephemeral secret key). | |
57 | + </p> | |
58 | + | |
59 | + <h2 id="assumptions">Assumptions</h2> | |
60 | + <p> | |
61 | + Messages will be posted in public, so that the sender is likely to be known, | |
62 | + and everyone can read the messages. (This makes it possible to hide the recipient, | |
63 | + but probably not the sender.) | |
64 | + </p> | |
65 | + <p>Resisting traffic analysis of the timing or size of messages is out of scope of this spec.</p> | |
66 | + | |
67 | + <h2 id="prior-art">Prior Art</h2> | |
68 | + <h4 id="-pgp-">PGP</h4> | |
69 | + <p> | |
70 | + In PGP the recipient, the sender, and the subject are sent as plaintext. | |
71 | + If the recipient is known, then the metadata graph of who is communicating with who can be read, | |
72 | + which, since it is easier to analyze than the content, is important to protect. | |
73 | + </p> | |
74 | + <h4 id="-sodium-seal-">Sodium seal</h4> | |
75 | + <p> | |
76 | + The Sodium library provides a <em>seal</em> function that generates an ephemeral keypair, | |
77 | + derives a shared key to encrypt a message, and then sends the ephemeral public key and the message. | |
78 | + The recipient is hidden, and it is forward secure if the sender throws out the ephemeral key. | |
79 | + However, it's only possible to have one recipient. | |
80 | + </p> | |
81 | + | |
82 | + <h4 id="-minilock-">Minilock</h4> | |
83 | + <p> | |
84 | + Minilock uses a similar approach to <code>private-box</code> but does not hide the | |
85 | + number of recipients. In the case of a group discussion where multiple rounds | |
86 | + of messages are sent to everyone, this may enable an eavesdropper to deanonymize | |
87 | + the participiants of a discussion if the sender of each message is known. | |
88 | + </p> | |
89 | + | |
90 | + <h2 id="api">API</h2> | |
91 | + | |
92 | + <h4 id="-encrypt-plaintext-buffer-recipients-array-curve25519_pk-">encrypt (plaintext Buffer, recipients Array<curve25519_pk>)</h4> | |
93 | + <p> | |
94 | + Takes a plaintext buffer of the message you want to encrypt, | |
95 | + and an array of recipient public keys. | |
96 | + Returns a message that is encrypted to all recipients | |
97 | + and openable by them with <code>PrivateBox.decrypt</code>. | |
98 | + The recipients must be between 1 and 7 items long. | |
99 | + </p> | |
100 | + <p> | |
101 | + The encrypted length will be <code>56 + (recipients.length * 33) + plaintext.length</code> bytes long, | |
102 | + between 89 and 287 bytes longer than the plaintext. | |
103 | + </p> | |
104 | + | |
105 | + <h4 id="-decrypt-cyphertext-buffer-secretkey-curve25519_sk-">decrypt (cyphertext Buffer, secretKey curve25519_sk)</h4> | |
106 | + <p> | |
107 | + Attempt to decrypt a private-box message, using your secret key. | |
108 | + If you where an intended recipient then the plaintext will be returned. | |
109 | + If it was not for you, then <code>undefined</code> will be returned. | |
110 | + </p> | |
111 | + | |
112 | + <h2 id="protocol">Protocol</h2> | |
113 | + <h4 id="-encryption-">Encryption</h4> | |
114 | + <p>Private-box generates:</p> | |
115 | + <ul> | |
116 | + <li><code>ephemeral</code>: an ephemeral curve25519 keypair that will only be used with this message.</li> | |
117 | + <li><code>body_key</code>: a random key that will be used to encrypt the plaintext body.</li> | |
118 | + </ul> | |
119 | + <p> | |
120 | + First, private-box outputs the ephemeral public key, then multiplies each recipient public key | |
121 | + with its secret to produce ephemeral shared keys (<code>shared_keys[1..n]</code>). | |
122 | + Then, private-box concatenates <code>body_key</code> with the number of recipients, | |
123 | + encrypts that to each shared key, and concatenates the encrypted body. | |
124 | + </p> | |
125 | + ${ com.code({ js: ` | |
126 | +function encrypt (plaintext, recipients) { | |
127 | + var ephemeral = keypair() | |
128 | + var nonce = random(24) | |
129 | + var body_key = random(32) | |
130 | + var body_key_with_length = concat([ | |
131 | + body_key, | |
132 | + recipients.length | |
133 | + ]) | |
134 | + return concat([ | |
135 | + nonce, | |
136 | + ephemeral.publicKey, | |
137 | + concat(recipients.map(function (publicKey) { | |
138 | + return secretbox( | |
139 | + body_key_with_length, | |
140 | + nonce, | |
141 | + scalarmult(publicKey, ephemeral.secretKey) | |
142 | + ) | |
143 | + }), | |
144 | + secretbox(plaintext, nonce, body_key) | |
145 | + ]) | |
146 | +}` }) } | |
147 | + | |
148 | + <h4 id="-decryption-">Decryption</h4> | |
149 | + <p> | |
150 | + <code>private-box</code> takes the nonce and ephemeral public key, | |
151 | + multiplies that with your secret key, then tests each possible | |
152 | + recipient slot until it either decrypts a key or runs out of slots. | |
153 | + If it runs out of slots, the message was not addressed to you, | |
154 | + so <code>undefined</code> is returned. Else, the message is found and the body | |
155 | + is decrypted. | |
156 | + </p> | |
157 | + ${ com.code({ js: ` | |
158 | +function decrypt (cyphertext, secretKey) { | |
159 | + var next = reader(cyphertext) // next() will read | |
160 | + // the passed N bytes | |
161 | + var nonce = next(24) | |
162 | + var publicKey = next(32) | |
163 | + var sharedKey = salarmult(publicKey, secretKey) | |
164 | + | |
165 | + for(var i = 0; i < 7; i++) { | |
166 | + var maybe_key = next(33) | |
167 | + var key_with_length = secretbox_open( | |
168 | + maybe_key, | |
169 | + nonce, | |
170 | + sharedKey | |
171 | + ) | |
172 | + if (key_with_length) { // decrypted! | |
173 | + var key = key_with_length.slice(0, 32) | |
174 | + var length = key_with_length[32] | |
175 | + return secretbox_open( | |
176 | + key, | |
177 | + cyphertext.slice( | |
178 | + 56 + 33*(length+1), | |
179 | + cyphertext.length | |
180 | + ), | |
181 | + ) | |
182 | + } | |
183 | + } | |
184 | + // this message was not addressed | |
185 | + // to the owner of secretKey | |
186 | + return undefined | |
187 | +}` }) } | |
188 | + ` | |
189 | +}) |
tmpl/more/protocols/secret-handshake.html.js | ||
---|---|---|
@@ -1,0 +1,16 @@ | ||
1 | +var page = require('../../page.part') | |
2 | +module.exports = () => page({ | |
3 | + title: 'Secret Handshake', | |
4 | + section: 'more', | |
5 | + tab: 'more-protocols', | |
6 | + path: '/more/protocols/secret-handshake.html', | |
7 | + content: ` | |
8 | + <h2>Secret Handshake</h1> | |
9 | + <p> | |
10 | + Secret Handshake is an encrypted channel protocol based on a mutually authenticating key agreement handshake, with forward secure identity metadata. | |
11 | + It's used by Scuttlebot to authenticate and encrypt peer connections. | |
12 | + </p> | |
13 | + <p><a href="./shs.pdf">Read the White Paper</a></p> | |
14 | + `, | |
15 | + next: ['/more/protocols/private-box.html', 'Private Box'] | |
16 | +}) |
tmpl/more/protocols/secure-scuttlebutt.html.js | ||
---|---|---|
@@ -1,0 +1,185 @@ | ||
1 | +var page = require('../../page.part') | |
2 | +var com = require('../../com.part') | |
3 | + | |
4 | +module.exports = () => page({ | |
5 | + title: 'Secure Scuttlebutt', | |
6 | + section: 'more', | |
7 | + tab: 'more-protocols', | |
8 | + path: '/more/protocols/secure-scuttlebutt.html', | |
9 | + content: ` | |
10 | + <h2>Secure Scuttlebutt</h2> | |
11 | + <p>Secure Scuttlebutt is a database protocol for unforgeable append-only message feeds.</p> | |
12 | + <p> | |
13 | + "Unforgeable" means that only the owner of a feed can update that feed, as enforced by digital signing (see <a href="#security-properties">Security properties</a>). | |
14 | + This property makes Secure Scuttlebutt useful for peer-to-peer applications. | |
15 | + Secure Scuttlebutt also makes it easy to encrypt messages. | |
16 | + </p> | |
17 | + | |
18 | + <hr> | |
19 | + | |
20 | + <h2>Overview</h2> | |
21 | + <p> | |
22 | + Scuttlebot forms a global cryptographic social network with its peers. | |
23 | + Each user is identified by a public key, and publishes a log of signed messages, which other users follow socially. | |
24 | + </p> | |
25 | + <p> | |
26 | + Scuttlebot searches the P2P mesh for new messages and files from followed users and from FoaFs. | |
27 | + The messages and files are stored locally, indefinitely, for applications to read. | |
28 | + </p> | |
29 | + | |
30 | + <h3>Identity</h3> | |
31 | + <p> | |
32 | + Users are identified by confirmations and signals in the social graph. | |
33 | + This is known as a Web-of-Trust. | |
34 | + There is no global registry of usernames. | |
35 | + Instead, users name themselves, and share petnames for each other. | |
36 | + </p> | |
37 | + <p> | |
38 | + Discovery occurs by examining the social graph, or by out-of-band sharing. | |
39 | + Applications can analyze the follow-graph, and look for "flag" messages, to determine who is trust-worthy in the network. | |
40 | + </p> | |
41 | + | |
42 | + <h3>Pub Servers</h3> | |
43 | + <p> | |
44 | + "Pubs" are bot-users that have public IPs. | |
45 | + They follow users and rehost the messages to other peers, ensuring good uptime and no firewall blockage. | |
46 | + </p> | |
47 | + <p> | |
48 | + Pubs have no special privileges, and are not trusted by users. | |
49 | + However, because Scuttlebot has no DHT or NAT-traversal utilities, users must "join" a Pub to distribute their messages on the WAN. | |
50 | + </p> | |
51 | + <p> | |
52 | + Scuttlebot can change Pubs, or join more than one, and sync directly over Wifi. | |
53 | + Identity is not tied to the Pubs. | |
54 | + </p> | |
55 | + | |
56 | + <hr> | |
57 | + | |
58 | + <h2 id="concepts">Concepts in Depth</h2> | |
59 | + <p>Building upon Secure Scuttlebutt requires understanding a few concepts that it uses to ensure the unforgeability of message feeds.</p> | |
60 | + | |
61 | + <h3 id="identities">Identities</h3> | |
62 | + <p> | |
63 | + An identity is simply a <a href="http://ed25519.cr.yp.to/">ed25519 key pair</a>. | |
64 | + The public key is used as the identifier. | |
65 | + </p> | |
66 | + <p> | |
67 | + There is no worldwide store of identities. | |
68 | + Users must exchange pubkeys, either by publishing them on their feeds, or out-of-band. | |
69 | + </p> | |
70 | + | |
71 | + <h3 id="feeds">Feeds</h3> | |
72 | + <p> | |
73 | + A feed is a signed append-only sequence of messages. | |
74 | + Each identity has exactly one feed. | |
75 | + </p> | |
76 | + <p> | |
77 | + Note that append-only means you cannot delete an existing message, or change your history. | |
78 | + This is enforced by a per-feed blockchain. | |
79 | + This is to ensure the entire network converges on the same state. | |
80 | + </p> | |
81 | + | |
82 | + <h3 id="messages">Messages</h3> | |
83 | + <p>Each message contains:</p> | |
84 | + <ul> | |
85 | + <li>A signature</li> | |
86 | + <li>The signing public key</li> | |
87 | + <li>A content-hash of the previous message</li> | |
88 | + <li>A sequence number</li> | |
89 | + <li>A timestamp</li> | |
90 | + <li>An identifier of the hashing algorithm in use (currently only "sha256" is supported)</li> | |
91 | + <li>A content object</li> | |
92 | + </ul> | |
93 | + <p>Here's an example message:</p> | |
94 | + ${ com.code({ js: `{ | |
95 | + "previous": "%26AC+gU0t74jRGVeDY01...MnutGGHM=.sha256", | |
96 | + "author": "@hxGxqPrplLjRG2vtjQL87...0nNwE=.ed25519", | |
97 | + "sequence": 216, | |
98 | + "timestamp": 1442590513298, | |
99 | + "hash": "sha256", | |
100 | + "content": { | |
101 | + "type": "vote", | |
102 | + "vote": { | |
103 | + "link": "%WbQ4dq0m/zu5jxll9zUb...KjZ80JvI=.sha256", | |
104 | + "value": 1 | |
105 | + } | |
106 | + }, | |
107 | + "signature": "Sjq1C3yiKdmi1TWvNqxI...gmAQ==.sig.ed25519" | |
108 | +}` }) } | |
109 | + | |
110 | + <h3 id="entity-references-links-">Entity References (Links)</h3> | |
111 | + <p> | |
112 | + Messages can reference three types of Secure Scuttlebutt entities: messages, feeds, and blobs (i.e. files). | |
113 | + Messages and blobs are referred to by their hashes, but a feed is referred to by its signing public key. | |
114 | + </p> | |
115 | + | |
116 | + <h3 id="confidentiality">Confidentiality</h3> | |
117 | + <p> | |
118 | + For private sharing, Scuttlebot uses <a href="http://doc.libsodium.org/">libsodium</a> to encrypt confidential log-entries. | |
119 | + Feed IDs are public keys, and so once two feeds are mutually following each other, they can exchange confidential data freely. | |
120 | + </p> | |
121 | + | |
122 | + <h3 id="following">Following</h3> | |
123 | + <p> | |
124 | + Users choose which feeds to synchronize by following them. | |
125 | + Presently, <a href="/modules/scuttlebot-replicate.html">Scuttlebot's replicate plugin</a>, which is enabled by default, looks on the master user's feed for <code>type:contact</code> messages to know which users are currently followed. | |
126 | + </p> | |
127 | + | |
128 | + <h3 id="replication">Replication</h3> | |
129 | + <p> | |
130 | + Since feeds are append-only, replication is simple: request all messages in the feed that are newer than the latest message you know about. | |
131 | + Scuttlebot maintains a table of known peers, which it cycles through, asking for updates for all followed feeds. | |
132 | + </p> | |
133 | + | |
134 | + <h3 id="gossip">Gossip</h3> | |
135 | + <p> | |
136 | + The protocol creates a <a href="https://en.wikipedia.org/wiki/Gossip_protocol">global gossip network</a>. | |
137 | + This means that information is able to distribute across multiple machines, without requiring direct connections between them. | |
138 | + </p> | |
139 | + <p><img src="/img/gossip-graph1.png" alt="Gossip graph"></p> | |
140 | + <p>Even though Alice and Dan lack a direct connection, they can still exchange feeds:</p> | |
141 | + <p><img src="/img/gossip-graph2.png" alt="Gossip graph 2"></p> | |
142 | + <p> | |
143 | + This is because gossip creates "transitive" connections between computers. | |
144 | + Dan's messages travel through Carla and the Pub to reach Alice, and visa-versa. | |
145 | + </p> | |
146 | + | |
147 | + <h3 id="lan-connectivity">LAN connectivity</h3> | |
148 | + <p> | |
149 | + SSB is hostless: each computer installs the same copy of software and has equal rights in the network. | |
150 | + Devices discover each other over the LAN with multicast UDP and sync automatically. | |
151 | + </p> | |
152 | + | |
153 | + <h3 id="pub-servers">Pub Servers</h3> | |
154 | + <p> | |
155 | + To sync across the Internet, "Pub" nodes run at public IPs and follow users. | |
156 | + They are essentially mail-bots which improve uptime and availability. | |
157 | + Users generate invite-codes to command Pubs to follow their friends. | |
158 | + The Scuttlebot community runs some Pubs, and anybody can create and introduce their own. | |
159 | + </p> | |
160 | + | |
161 | + <h2 id="security-properties">Security properties</h2> | |
162 | + <p> | |
163 | + Secure Scuttlebutt maintains useful security properties even when it is connected to a malicious Secure Scuttlebutt database. | |
164 | + This makes it ideal as a store for peer-to-peer applications. | |
165 | + </p> | |
166 | + <p> | |
167 | + Imagine that we want to read from a feed for which we know the identity, but we're connected to a malicious Secure Scuttlebutt instance. | |
168 | + As long as the malicious database does not have the private key: | |
169 | + </p> | |
170 | + <ul> | |
171 | + <li>The malicious database cannot create a new feed with the same identifier</li> | |
172 | + <li>The malicious database cannot write new fake messages to the feed</li> | |
173 | + <li>The malicious database cannot reorder the messages in the feed</li> | |
174 | + <li>The malicious database cannot send us a new copy of the feed that omits messages from the middle</li> | |
175 | + <li>The malicious database <em>can</em> refuse to send us the feed, or only send us the first <em>N</em> messages in the feed</li> | |
176 | + <li>Messages may optionally be encrypted</li> | |
177 | + </ul> | |
178 | + <p> | |
179 | + Additionally there is a protection from the feed owner, through the blockchain. | |
180 | + The <code>previous</code> content-hash them from changing the feed history after publishing, as a newly-created message wouldn't match the hash of later messages which were already replicated. | |
181 | + This ensures the append-only constraint, and thus safe network convergence. | |
182 | + </p> | |
183 | + `, | |
184 | + next: ['/more/protocols/secret-handshake.html', 'Secret Handshake'] | |
185 | +}) |
tmpl/more/protocols/shs.pdf | ||
---|---|---|
The diff is too large to show. Use a local git client to view these changes. Old file size: 0 bytes New file size: 219079 bytes |
Built with git-ssb-web