Skip to content

Instantly share code, notes, and snippets.

@spectras
Created September 23, 2016 16:25
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save spectras/b3a6f0093ddb1635b39279e9a539ca21 to your computer and use it in GitHub Desktop.
Save spectras/b3a6f0093ddb1635b39279e9a539ca21 to your computer and use it in GitHub Desktop.
Compute syncthing device ID from its certificate
#!/usr/bin/env python
import base64
import hashlib
import subprocess
import sys
B32ALPHABET = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ234567'
def luhn_checksum(data, alphabet=B32ALPHABET):
n = len(alphabet)
number = tuple(alphabet.index(i) for i in reversed(data))
result = (sum(number[::2]) +
sum(sum(divmod(i * 2, n)) for i in number[1::2])) % n
return alphabet[-result]
def main(incert):
der_data = subprocess.check_output(['openssl', 'x509', '-outform', 'DER'], stdin=incert)
data_hash = hashlib.sha256(der_data)
b32_hash = base64.b32encode(data_hash.digest()).decode('ascii')
result = b32_hash.upper().rstrip('=')
blocks = [result[pos:pos+13] for pos in range(0, len(result), 13)]
result = ''.join(block + luhn_checksum(block) for block in blocks)
blocks = [result[pos:pos+7] for pos in range(0, len(result), 7)]
print('-'.join(blocks))
if __name__ == '__main__':
import argparse
parser = argparse.ArgumentParser(description='Generate syncthing ID from certificate')
parser.add_argument('incert', type=argparse.FileType('rb'), help='Certificate path')
args = parser.parse_args()
main(**vars(args))
@spectras
Copy link
Author

spectras commented Sep 23, 2016

Usage example: python syncthing_id.py ~/.config/syncthing/cert.pem
You can pass - as a filename to make it read the certificate from its standard input.
Writes the corresponding syncthing device ID on its standard ouput.

No dependencies. Works with both python2 and python3.
Tested on Debian and Ubuntu. No idea if it would work on Windows.

@AudriusButkevicius
Copy link

It wouldn't most likely (due to openssl), and it does depend on openssl being installed, as well as requires the cert to be in DER format

@spectras
Copy link
Author

spectras commented Sep 23, 2016

Fair enough, as openssl comes in most linux default installs, I forgot to count it as a dependency.
Certificate can be in any format, the point of using the openssl command is to convert it from whatever format into DER.

@bushelofsilicon
Copy link

Using ssl.PEM_cert_to_DER_cert removes the openssl dependency and makes this work on Windows

@yb66
Copy link

yb66 commented Apr 18, 2018

@spectras Thanks for sharing this, it was a big help to me.

Regards,
iain

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment