#!/usr/bin/env python3 # Copyright (c) 2019 Pieter Wuille # Distributed under the MIT software license, see the accompanying # file COPYING or http://www.opensource.org/licenses/mit-license.php. """Utility functions related to output descriptors""" import re INPUT_CHARSET = "0123456789()[],'/*abcdefgh@:$%{}IJKLMNOPQRSTUVWXYZ&+-.;<=>?!^_|~ijklmnopqrstuvwxyzABCDEFGH`#\"\\ " CHECKSUM_CHARSET = "qpzry9x8gf2tvdw0s3jn54khce6mua7l" GENERATOR = [0xf5dee51989, 0xa9fdca3312, 0x1bab10e32d, 0x3706b1677a, 0x644d626ffd] def descsum_polymod(symbols): """Internal function that computes the descriptor checksum.""" chk = 1 for value in symbols: top = chk >> 35 chk = (chk & 0x7ffffffff) << 5 ^ value for i in range(5): chk ^= GENERATOR[i] if ((top >> i) & 1) else 0 return chk def descsum_expand(s): """Internal function that does the character to symbol expansion""" groups = [] symbols = [] for c in s: if not c in INPUT_CHARSET: return None v = INPUT_CHARSET.find(c) symbols.append(v & 31) groups.append(v >> 5) if len(groups) == 3: symbols.append(groups[0] * 9 + groups[1] * 3 + groups[2]) groups = [] if len(groups) == 1: symbols.append(groups[0]) elif len(groups) == 2: symbols.append(groups[0] * 3 + groups[1]) return symbols def descsum_create(s): """Add a checksum to a descriptor without""" symbols = descsum_expand(s) + [0, 0, 0, 0, 0, 0, 0, 0] checksum = descsum_polymod(symbols) ^ 1 return s + '#' + ''.join(CHECKSUM_CHARSET[(checksum >> (5 * (7 - i))) & 31] for i in range(8)) def descsum_check(s, require=True): """Verify that the checksum is correct in a descriptor""" if not '#' in s: return not require if s[-9] != '#': return False if not all(x in CHECKSUM_CHARSET for x in s[-8:]): return False symbols = descsum_expand(s[:-9]) + [CHECKSUM_CHARSET.find(x) for x in s[-8:]] return descsum_polymod(symbols) == 1 def drop_origins(s): '''Drop the key origins from a descriptor''' desc = re.sub(r'\[.+?\]', '', s) if '#' in s: desc = desc[:desc.index('#')] return descsum_create(desc)