Provided by: syncthing_1.27.7~ds1-5_amd64 bug

NAME

       syncthing-device-ids - Understanding Device IDs

       Every  device  is identified by a device ID. The device ID is used for address resolution,
       authentication and authorization. The term “device ID”  could  interchangeably  have  been
       “key ID” since the device ID is a direct property of the public key in use.

KEYS

       To  understand  device IDs we need to look at the underlying mechanisms. At first startup,
       Syncthing will create a public/private keypair.

       Currently this is a 384 bit ECDSA key (3072 bit RSA prior to v0.12.5,  which  is  what  is
       used  as  an  example  in this article). The keys are saved in the form of the private key
       (key.pem) and a self signed certificate (cert.pem). The self signing part doesn’t actually
       add  any security or functionality as far as Syncthing is concerned but it enables the use
       of the keys in a standard TLS exchange.

       The typical certificate will look something like this, inspected with openssl x509:

          Certificate:
              Data:
                  Version: 3 (0x2)
                  Serial Number: 0 (0x0)
                  Signature Algorithm: sha1WithRSAEncryption
                  Issuer: CN=syncthing
                  Validity
                      Not Before: Mar 30 21:10:52 2014 GMT
                      Not After : Dec 31 23:59:59 2049 GMT
                  Subject: CN=syncthing
                  Subject Public Key Info:
                      Public Key Algorithm: rsaEncryption
                      RSA Public Key: (3072 bit)
                          Modulus (3072 bit):
                              00:da:83:8a:c0:95:af:0a:42:af:43:74:65:29:f2:
                              30:e3:b9:12:d2:6b:70:93:da:0b:7b:8a:1e:e5:79:
                              ...
                              99:09:4c:a9:7b:ba:4a:6a:8b:3b:e6:e7:c7:2c:00:
                              90:aa:bc:ad:94:e7:80:95:d2:1b
                          Exponent: 65537 (0x10001)
                  X509v3 extensions:
                      X509v3 Key Usage: critical
                          Digital Signature, Key Encipherment
                      X509v3 Extended Key Usage:
                          TLS Web Server Authentication, TLS Web Client Authentication
                      X509v3 Basic Constraints: critical
                          CA:FALSE
              Signature Algorithm: sha1WithRSAEncryption
                  68:72:43:8b:83:61:09:68:f0:ef:f0:43:b7:30:a6:73:1e:a8:
                  d9:24:6c:2d:b4:bc:c9:e8:3e:0b:1e:3c:cc:7a:b2:c8:f1:1d:
                  ...
                  88:7e:e2:61:aa:4c:02:e3:64:b0:da:70:3a:cd:1c:3d:86:db:
                  df:54:b9:4e:be:1b

       We can see here that the certificate is little more than a container for the  public  key;
       the  serial  number  is  zero  and  the  Issuer  and  Subject are both “syncthing” where a
       qualified name might otherwise be expected.

       An advanced user could replace the key.pem and cert.pem files  with  a  keypair  generated
       directly by the openssl utility or other mechanism.

DEVICE IDS

       To  form  a  device ID the SHA-256 hash of the certificate data in DER form is calculated.
       This means the hash covers all information under the Certificate: section above.

       The hashing results in a 256 bit hash which we encode using base32.  Base32  encodes  five
       bits  per  character  so  we  need 256 / 5 = 51.2 characters to encode the device ID. This
       becomes 52 characters in practice, but 52 characters of base32 would decode  to  260  bits
       which  is  not  a whole number of bytes. The base32 encoding adds padding to 280 bits (the
       next multiple of both 5 and 8 bits) so the resulting ID looks something like:

          MFZWI3DBONSGYYLTMRWGC43ENRQXGZDMMFZWI3DBONSGYYLTMRWA====

       The padding (====) is stripped away, the device ID  split  into  four  groups,  and  check
       digits  <https://forum.syncthing.net/t/v0-9-0-new-node-id-format/478>  are  added for each
       group. For presentation purposes the device ID is grouped with dashes,  resulting  in  the
       final value:

          MFZWI3D-BONSGYC-YLTMRWG-C43ENR5-QXGZDMM-FZWI3DP-BONSGYY-LTMRWAD

   Connection Establishment
       Now  we  know  what  device IDs are, here’s how they are used in Syncthing. When you add a
       device ID to the configuration, Syncthing will attempt to  connect  to  that  device.  The
       first  thing  we  need  to do is figure out the IP and port to connect to. There are three
       possibilities here:

       • The IP and port can be set statically in the configuration. The IP can equally well be a
         host  name,  so  if  you  have  a  static IP or a dynamic DNS setup this might be a good
         option.

       • Using local discovery, if enabled.  Every  Syncthing  instance  on  a  LAN  periodically
         broadcasts information about itself (device ID, address, port number). If we’ve seen one
         of these broadcasts for a given device ID that’s where we try to connect.

       • Using global discovery, if enabled. Every Syncthing instance  announces  itself  to  the
         global  discovery  service (device ID and external port number - the internal address is
         not announced to the global server). If we don’t have a static address and haven’t  seen
         any local announcements the global discovery server will be queried for an address.

       Once  we  have  an  address  and  port a TCP connection is established and a TLS handshake
       performed. As part of the handshake both devices  present  their  certificates.  Once  the
       handshake  has  completed  and  the  peer  certificate  is  known, the following steps are
       performed:

       1. Calculate the remote device ID by processing the received certificate as above.

       2. Weed out a few possible misconfigurations - i.e. if the device ID is that of the  local
          device  or  of a device we already have an active connection to. Drop the connection in
          these cases.

       3. Verify the remote device ID against the configuration. If it is not a device ID we  are
          expecting to talk to, drop the connection.

       4. Verify  the  certificate CommonName against the configuration. By default, we expect it
          to be syncthing, but when using custom certificates this can be changed.

       5. If everything checks out so far, accept the connection.

AN ASIDE ABOUT COLLISIONS

       The SHA-256 hash is cryptographically collision resistant. This means that there is no way
       that we know of to create two different messages with the same hash.

       You  can  argue that of course there are collisions - there’s an infinite amount of inputs
       and a finite amount of outputs - so by definition there are infinitely many messages  that
       result in the same hash.

       I’m going to quote stack overflow <https://stackoverflow.com/questions/4014090/is-it-safe-
       to-ignore-the-possibility-of-sha-collisions-in-practice> here:
          The usual answer goes thus: what is the probability that a rogue  asteroid  crashes  on
          Earth within the next second, obliterating civilization-as-we- know-it, and killing off
          a few billion people ?  It can be argued that any  unlucky  event  with  a  probability
          lower than that is not actually very important.

          If we have a “perfect” hash function with output size n, and we have p messages to hash
          (individual message length is not important), then probability of  collision  is  about
          p2/2n+1  (this  is  an  approximation  which is valid for “small” p, i.e. substantially
          smaller than 2n/2). For  instance,  with  SHA-256  (n=256)  and  one  billion  messages
          (p=10^9) then the probability is about 4.3*10^-60.

          A  mass-murderer  space rock happens about once every 30 million years on average. This
          leads to a probability of such an event occurring in the next second to  about  10^-15.
          That’s 45 orders of magnitude more probable than the SHA-256 collision. Briefly stated,
          if you 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  not  simply
       collision  resistance  but  resistance to a preimage attack, i.e. even if you can find two
       messages that result in a hash collision that doesn’t help you attack Syncthing (or TLS in
       general). You need to create a message that hashes to exactly the hash that my certificate
       already has or you won’t get in.

       Note also that it’s not good enough to find a random blob of bits that happen to have  the
       same  hash  as  my certificate. You need to create a valid DER-encoded, signed certificate
       that has the same hash as mine. The difficulty of this  is  staggeringly  far  beyond  the
       already staggering difficulty of finding a SHA-256 collision.

PROBLEMS AND VULNERABILITIES

       As far as I know, these are the issues or potential issues with the above mechanism.

   Discovery Spoofing
       Currently,  the  local  discovery mechanism isn’t protected by crypto. This means that any
       device can in theory announce itself for any device ID and potentially receive connections
       for that device from the local network.

   Long Device IDs are Painful
       It’s  a  mouthful  to  read  over  the  phone, annoying to type into an SMS or even 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  are  various
       possible solutions:

       • Use  shorter  device  IDs with verification based on the full ID (“You entered MFZWI3; I
         found      and      connected      to       a       device       with       the       ID
         MFZWI3-DBONSG-YYLTMR-WGC43E-NRQXGZ-DMMFZW-I3DBON-SGYYLT-MRWA,  please  confirm that this
         is correct”).

       • Use shorter device IDs with an out of band authentication, a la Bluetooth  pairing.  You
         enter  a one time PIN into Syncthing and give that PIN plus a short device ID to another
         user. On initial connect, both sides verify that the other knows the correct PIN  before
         accepting the connection.

AUTHOR

       The Syncthing Authors

COPYRIGHT

       2014-2019, The Syncthing Authors