Create syncthing-device-ids(7)
This commit is contained in:
+57
-61
@@ -1,28 +1,28 @@
|
|||||||
########################
|
|
||||||
Understanding Device IDs
|
Understanding Device IDs
|
||||||
########################
|
========================
|
||||||
|
|
||||||
Every device is identified by a device ID. The device ID is used for
|
Description
|
||||||
address resolution, authentication and authorization. The term "device
|
-----------
|
||||||
ID" could interchangably have been "key ID" since the device ID is a
|
|
||||||
direct properties of the public key in use.
|
Every device is identified by a device ID. The device ID is used for address
|
||||||
|
resolution, authentication and authorization. The term "device ID" could
|
||||||
|
interchangably have been "key ID" since the device ID is a direct properties of
|
||||||
|
the public key in use.
|
||||||
|
|
||||||
Keys
|
Keys
|
||||||
====
|
----
|
||||||
|
|
||||||
To understand device IDs we need to look at the underlying mechanisms.
|
To understand device IDs we need to look at the underlying mechanisms. At first
|
||||||
At first startup, Syncthing will create an public/private key pair.
|
startup, Syncthing will create an public/private key pair.
|
||||||
|
|
||||||
Currently this is a 3072 bit RSA key. The keys are saved in the form of
|
Currently this is a 3072 bit RSA key. The keys are saved in the form of the
|
||||||
the private key (``key.pem``) and a self signed certificate
|
private key (``key.pem``) and a self signed certificate (``cert.pem``). The self
|
||||||
(``cert.pem``). The self signing part doesn't actually add any security
|
signing part doesn't actually add any security or functionality as far as
|
||||||
or functionality as far as Syncthing is concerned but it enables the use
|
Syncthing is concerned but it enables the use of the keys in a standard TLS
|
||||||
of the keys in a standard TLS exchange.
|
exchange.
|
||||||
|
|
||||||
The typical certificate will look something like this, inspected with
|
The typical certificate will look something like this, inspected with
|
||||||
``openssl x509``:
|
``openssl x509``::
|
||||||
|
|
||||||
::
|
|
||||||
|
|
||||||
Certificate:
|
Certificate:
|
||||||
Data:
|
Data:
|
||||||
@@ -58,28 +58,26 @@ The typical certificate will look something like this, inspected with
|
|||||||
88:7e:e2:61:aa:4c:02:e3:64:b0:da:70:3a:cd:1c:3d:86:db:
|
88:7e:e2:61:aa:4c:02:e3:64:b0:da:70:3a:cd:1c:3d:86:db:
|
||||||
df:54:b9:4e:be:1b
|
df:54:b9:4e:be:1b
|
||||||
|
|
||||||
We can see here that the certificate is little more than a container for
|
We can see here that the certificate is little more than a container for the
|
||||||
the public key; the serial number is zero and the Issuer and Subject are
|
public key; the serial number is zero and the Issuer and Subject are both
|
||||||
both "syncthing" where a qualified name might otherwise be expected.
|
"syncthing" where a qualified name might otherwise be expected.
|
||||||
|
|
||||||
An advanced user could replace the ``key.pem`` and ``cert.pem`` files
|
An advanced user could replace the ``key.pem`` and ``cert.pem`` files with a
|
||||||
with a keypair generated directly by the ``openssl`` utility or other
|
keypair generated directly by the ``openssl`` utility or other mechanism.
|
||||||
mechanism.
|
|
||||||
|
|
||||||
Device IDs
|
Device IDs
|
||||||
==========
|
----------
|
||||||
|
|
||||||
To form a device ID the SHA-256 hash of the certificate data in DER form
|
To form a device ID the SHA-256 hash of the certificate data in DER form is
|
||||||
is calculated. This means the hash covers all information under the
|
calculated. This means the hash covers all information under the
|
||||||
``Certificate:`` section above.
|
``Certificate:`` section above.
|
||||||
|
|
||||||
The hashing results in a 256 bit hash, which we encode using base32.
|
The hashing results in a 256 bit hash, which we encode using base32. Base32
|
||||||
Base32 encodes five bits per character, so we need 256 / 5 = 51.2
|
encodes five bits per character, so we need 256 / 5 = 51.2 characters to encode
|
||||||
characters to encode the device ID. This becomes 52 characters in
|
the device ID. This becomes 52 characters in practice, but 52 characters of
|
||||||
practice, but 52 characters of base32 would decode to 260 bits which is
|
base32 would decode to 260 bits which is not an whole number of bytes. The
|
||||||
not an whole number of bytes. The base32 encoding adds padding to 280
|
base32 encoding adds padding to 280 bits (the next multiple of both 5 and 8
|
||||||
bits (the next multiple of both 5 and 8 bits) so the resulting ID looks
|
bits) so the resulting ID looks something like
|
||||||
something like
|
|
||||||
``MFZWI3DBONSGYYLTMRWGC43ENRQXGZDMMFZWI3DBONSGYYLTMRWA====``.
|
``MFZWI3DBONSGYYLTMRWGC43ENRQXGZDMMFZWI3DBONSGYYLTMRWA====``.
|
||||||
|
|
||||||
The padding (``====``) is stripped away, the device ID split in four
|
The padding (``====``) is stripped away, the device ID split in four
|
||||||
@@ -90,13 +88,12 @@ grouped with dashes, resulting in the final value:
|
|||||||
``MFZWI3D-BONSGYC-YLTMRWG-C43ENR5 -QXGZDMM-FZWI3DP-BONSGYY-LTMRWAD``.
|
``MFZWI3D-BONSGYC-YLTMRWG-C43ENR5 -QXGZDMM-FZWI3DP-BONSGYY-LTMRWAD``.
|
||||||
|
|
||||||
Connection Establishment
|
Connection Establishment
|
||||||
========================
|
~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
So now we know what device IDs are, here's how they are used in
|
So now we know what device IDs are, here's how they are used in Syncthing. When
|
||||||
Syncthing. When you add a device ID to the syncthing configuration,
|
you add a device ID to the syncthing configuration, Syncthing will attempt to
|
||||||
Syncthing will attempt to connect to that device. The first thing we
|
connect to that device. The first thing we need to do is figure out the IP and
|
||||||
need to do is figure out the IP and port to connect to. There's three
|
port to connect to. There's three possibilities here;
|
||||||
possibilities here;
|
|
||||||
|
|
||||||
- The IP and port can be set statically in the configuration. The IP
|
- The IP and port can be set statically in the configuration. The IP
|
||||||
can equally well be a hostname, so if you have a static IP or a
|
can equally well be a hostname, so if you have a static IP or a
|
||||||
@@ -114,10 +111,10 @@ possibilities here;
|
|||||||
any local announcements the global discovery server will be queried
|
any local announcements the global discovery server will be queried
|
||||||
for an address.
|
for an address.
|
||||||
|
|
||||||
Once we have and address and port a TCP connection is established and a
|
Once we have and address and port a TCP connection is established and a TLS
|
||||||
TLS handshake performed. As part of the handshake both devices present
|
handshake performed. As part of the handshake both devices present their
|
||||||
their certificates. Once the handshake has completed and the peer
|
certificates. Once the handshake has completed and the peer certificate is
|
||||||
certificate is known, the following steps are performed.
|
known, the following steps are performed.
|
||||||
|
|
||||||
#. Calculate the remote device ID by using the process above on the
|
#. Calculate the remote device ID by using the process above on the
|
||||||
received certificate.
|
received certificate.
|
||||||
@@ -169,27 +166,26 @@ here:
|
|||||||
more probable than the SHA-256 collision. Briefly stated, if you
|
more probable than the SHA-256 collision. Briefly stated, if you
|
||||||
find SHA-256 collisions scary then your priorities are wrong.
|
find SHA-256 collisions scary then your priorities are wrong.
|
||||||
|
|
||||||
It's also worth noting that the property of SHA-256 that we are using is
|
It's also worth noting that the property of SHA-256 that we are using is not
|
||||||
not simply collision resistance but resistance to a preimage attack.
|
simply collision resistance but resistance to a preimage attack. I.e. even if
|
||||||
I.e. even if you can find two messages that result in a hash collision
|
you can find two messages that result in a hash collision that doesn't help you
|
||||||
that doesn't help you attack Syncthing (or TLS in general). You need to
|
attack Syncthing (or TLS in general). You need to create a message that hashes
|
||||||
create a message that hashes to exactly the hash that my certificate
|
to exactly the hash that my certificate already has or you won't get in.
|
||||||
already has or you won't get in.
|
|
||||||
|
|
||||||
Note also that it's not good enough to find a random blob of bits that
|
Note also that it's not good enough to find a random blob of bits that happen to
|
||||||
happen to have the same hash as my certificate. You need to create a
|
have the same hash as my certificate. You need to create a valid DER- encoded,
|
||||||
valid DER- encoded, signed certificate that has the same hash as mine.
|
signed certificate that has the same hash as mine. The difficulty of this is
|
||||||
The difficulty of this is staggeringly far beyond the already staggering
|
staggeringly far beyond the already staggering difficulty of finding a SHA-256
|
||||||
difficulty of finding a SHA-256 collision.
|
collision.
|
||||||
|
|
||||||
Problems and Vulnerabilities
|
Problems and Vulnerabilities
|
||||||
============================
|
----------------------------
|
||||||
|
|
||||||
As far as I know, these are the issues or potential issues with the
|
As far as I know, these are the issues or potential issues with the
|
||||||
above mechanism.
|
above mechanism.
|
||||||
|
|
||||||
Discovery Spoofing
|
Discovery Spoofing
|
||||||
------------------
|
~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
Currently, neither the local nor global discovery mechanism is protected
|
Currently, neither the local nor global discovery mechanism is protected
|
||||||
by crypto. This means that any device can in theory announce itself for
|
by crypto. This means that any device can in theory announce itself for
|
||||||
@@ -217,13 +213,13 @@ It's something we might want to look at at some point, but not a huge
|
|||||||
problem as I see it.
|
problem as I see it.
|
||||||
|
|
||||||
Long Device IDs are Painful
|
Long Device IDs are Painful
|
||||||
---------------------------
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
It's a mouthful to read over the phone, annoying to type into an SMS or
|
It's a mouthful to read over the phone, annoying to type into an SMS or even
|
||||||
even into a computer. And it needs to be done twice, once for each side.
|
into a computer. And it needs to be done twice, once for each side.
|
||||||
|
|
||||||
This isn't a vulnerability as such, but a user experience problem. There
|
This isn't a vulnerability as such, but a user experience problem. There are
|
||||||
are various possible solutions;
|
various possible solutions:
|
||||||
|
|
||||||
- Use shorter device IDs with verification based on the full ID ("You
|
- Use shorter device IDs with verification based on the full ID ("You
|
||||||
entered MFZWI3; I found and connected to a device with the ID
|
entered MFZWI3; I found and connected to a device with the ID
|
||||||
|
|||||||
Reference in New Issue
Block a user