Created
September 23, 2016 16:25
-
-
Save spectras/b3a6f0093ddb1635b39279e9a539ca21 to your computer and use it in GitHub Desktop.
Compute syncthing device ID from its certificate
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/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)) |
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
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.
Using ssl.PEM_cert_to_DER_cert
removes the openssl dependency and makes this work on Windows
@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
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.