# xref unique ID hash calculation # # Copyright (C) 2020 David Lamparter for NetDEF, Inc. # # This program is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by the Free # Software Foundation; either version 2 of the License, or (at your option) # any later version. # # This program is distributed in the hope that it will be useful, but WITHOUT # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or # FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for # more details. # # You should have received a copy of the GNU General Public License along # with this program; see the file COPYING; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA import struct from hashlib import sha256 def bititer(data, bits, startbit=True): """ just iterate the individual bits out from a bytes object if startbit is True, an '1' bit is inserted at the very beginning goes at a time, starts at LSB. """ bitavail, v = 0, 0 if startbit and len(data) > 0: v = data.pop(0) yield (v & ((1 << bits) - 1)) | (1 << (bits - 1)) bitavail = 9 - bits v >>= bits - 1 while len(data) > 0: while bitavail < bits: v |= data.pop(0) << bitavail bitavail += 8 yield v & ((1 << bits) - 1) bitavail -= bits v >>= bits def base32c(data): """ Crockford base32 with extra dashes """ chs = "0123456789ABCDEFGHJKMNPQRSTVWXYZ" o = "" if type(data) == str: data = [ord(v) for v in data] else: data = list(data) for i, bits in enumerate(bititer(data, 5)): if i == 5: o = o + "-" elif i == 10: break o = o + chs[bits] return o def uidhash(filename, hashstr, hashu32a, hashu32b): """ xref Unique ID hash used in FRRouting """ filename = "/".join(filename.rsplit("/")[-2:]) hdata = filename.encode("UTF-8") + hashstr.encode("UTF-8") hdata += struct.pack(">II", hashu32a, hashu32b) i = sha256(hdata).digest() return base32c(i)