clightning-dumpkeys

dump clightning output descriptors
git clone git://jb55.com/clightning-dumpkeys
Log | Files | Refs | README | LICENSE

descriptor.c (1672B)


      1 
      2 #include "short_types.h"
      3 #include <stdlib.h>
      4 #include <stdio.h>
      5 
      6 static const char CHECKSUM_CHARSET[] = "qpzry9x8gf2tvdw0s3jn54khce6mua7l";
      7 
      8 static const char INPUT_CHARSET[] =
      9 	"0123456789()[],'/*abcdefgh@:$%{}"
     10 	"IJKLMNOPQRSTUVWXYZ&+-.;<=>?!^_|~"
     11 	"ijklmnopqrstuvwxyzABCDEFGH`#\"\\ ";
     12 
     13 static inline int charset_find(char ch) {
     14 	for (size_t i = 0; i < sizeof(INPUT_CHARSET); i++) {
     15 		if (INPUT_CHARSET[i] == ch)
     16 			return i;
     17 	}
     18 	return -1;
     19 }
     20 
     21 static u64 polymod(u64 c, int val)
     22 {
     23 	u8 c0 = c >> 35;
     24 	c = ((c & 0x7ffffffff) << 5) ^ val;
     25 	if (c0 & 1) c ^= 0xf5dee51989;
     26 	if (c0 & 2) c ^= 0xa9fdca3312;
     27 	if (c0 & 4) c ^= 0x1bab10e32d;
     28 	if (c0 & 8) c ^= 0x3706b1677a;
     29 	if (c0 & 16) c ^= 0x644d626ffd;
     30 	return c;
     31 }
     32 
     33 
     34 int descriptor_checksum(const char *descriptor, int desc_size, char *checksum,
     35 			int checksum_capacity)
     36 {
     37 	if (checksum_capacity < 8+1)
     38 		return 0;
     39 
     40 	checksum[0] = 0;
     41 
     42 	int j;
     43 	u64 c = 1;
     44 	int cls = 0;
     45 	int clscount = 0;
     46 
     47 	for (int i = 0; i < desc_size; i++) {
     48 		char ch = descriptor[i];
     49 		int pos = charset_find(ch);
     50 		if (pos == -1) {
     51 			checksum[0] = 0;
     52 			return 0;
     53 		}
     54 		// Emit a symbol for the position inside the group, for every character.
     55 		c = polymod(c, pos & 31); 
     56 
     57 		// Accumulate the group numbers
     58 		cls = cls * 3 + (pos >> 5); 
     59 
     60 		if (++clscount == 3) {
     61 			c = polymod(c, cls);
     62 			cls = 0;
     63 			clscount = 0;
     64 		}
     65 	}
     66 
     67 	if (clscount > 0)
     68 		c = polymod(c, cls);
     69 
     70 	// Shift further to determine the checksum.
     71 	for (j = 0; j < 8; ++j)
     72 		c = polymod(c, 0);
     73 
     74 	// Prevent appending zeroes from not affecting the checksum.
     75 	c ^= 1;
     76 
     77 	for (j = 0; j < 8; ++j)
     78 		checksum[j] = CHECKSUM_CHARSET[(c >> (5 * (7 - j))) & 31];
     79 
     80 	checksum[8] = 0;
     81 
     82 	return 8;
     83 }