Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- // SPDX-License-Identifier: WTFPL
- #include <stdio.h>
- #include <string.h>
- #include <stdlib.h>
- #include <stdint.h>
- #include <ctype.h>
- #define unpacked_size(x) (((x) * 8 + 4) / 5) // round-up
- #define packed_size(x) (((x) * 5) / 8) // round-down
- #define expanded_hrp_size(x) (((x) * 2) + 1)
- #define BECH32_CHECKSUM_LEN 6
- static void hexdump(unsigned char *buf, int size)
- {
- int i;
- for (i = 0; i < size; i++)
- printf("%02x ", buf[i]);
- printf("\n");
- }
- static uint32_t bech32_polymod(uint8_t *values, int len)
- {
- uint32_t b, chk = 1;
- int i;
- for (i = 0; i < len; i++) {
- b = (chk >> 25);
- chk = (chk & 0x01ffffff) << 5 ^ (values[i] & 0x01f);
- chk ^= (b & 0x01) ? 0x3b6a57b2 : 0;
- chk ^= (b & 0x02) ? 0x26508e6d : 0;
- chk ^= (b & 0x04) ? 0x1ea119fa : 0;
- chk ^= (b & 0x08) ? 0x3d4233dd : 0;
- chk ^= (b & 0x10) ? 0x2a1462b3 : 0;
- }
- return chk;
- }
- static uint8_t bech32_char_decode(int c)
- {
- const static uint8_t decode_table[] = {
- 0x0f, 0xff, 0x0a, 0x11, 0x15, 0x14, 0x1a, 0x1e, // 01234567
- 0x07, 0x05, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, // 89:;<=>?
- 0xff, 0x1d, 0xff, 0x18, 0x0d, 0x19, 0x09, 0x08, // @ABCDEFG
- 0x17, 0xff, 0x12, 0x16, 0x1f, 0x1b, 0x13, 0xff, // HIJKLMNO
- 0x01, 0x00, 0x03, 0x10, 0x0b, 0x1c, 0x0c, 0x0e, // PQRSTUVW
- 0x06, 0x04, 0x02, 0xff, 0xff, 0xff, 0xff, 0xff, // XYZ[\]^_
- };
- /* use upper case to reduce table size */
- if (c >= 'a' && c <= 'z') c -= 'a' - 'A';
- return (c < '0' || c > 'Z') ? 0xff : decode_table[c - '0'];
- }
- static int pack5to8(uint8_t *out, int outlen, uint8_t *in, int inlen)
- {
- int inpos, outpos, olen;
- uint64_t v;
- olen = packed_size(inlen);
- outlen = (outlen < olen) ? outlen : olen;
- for (inpos = outpos = 0; inpos < inlen && outpos < outlen; ) {
- v = (uint64_t)(in[inpos++] & 0x1f) << 35;
- if (inpos < inlen) v |= (uint64_t)(in[inpos++] & 0x1f) << 30;
- if (inpos < inlen) v |= (uint64_t)(in[inpos++] & 0x1f) << 25;
- if (inpos < inlen) v |= (uint64_t)(in[inpos++] & 0x1f) << 20;
- if (inpos < inlen) v |= (uint64_t)(in[inpos++] & 0x1f) << 15;
- if (inpos < inlen) v |= (uint64_t)(in[inpos++] & 0x1f) << 10;
- if (inpos < inlen) v |= (uint64_t)(in[inpos++] & 0x1f) << 5;
- if (inpos < inlen) v |= (uint64_t)(in[inpos++] & 0x1f);
- out[outpos++] = v >> 32;
- if (outpos < outlen) out[outpos++] = v >> 24;
- if (outpos < outlen) out[outpos++] = v >> 16;
- if (outpos < outlen) out[outpos++] = v >> 8;
- if (outpos < outlen) out[outpos++] = v;
- }
- return outpos;
- }
- static int unpack8to5(uint8_t *out, int outlen, uint8_t *in, int inlen)
- {
- int inpos, outpos, olen;
- uint64_t v;
- olen = unpacked_size(inlen);
- outlen = (outlen < olen) ? outlen : olen;
- for (inpos = outpos = 0; inpos < inlen && outpos < outlen; ) {
- v = (uint64_t)in[inpos++] << 32;
- if (inpos < inlen) v |= (uint64_t)in[inpos++] << 24;
- if (inpos < inlen) v |= (uint64_t)in[inpos++] << 16;
- if (inpos < inlen) v |= (uint64_t)in[inpos++] << 8;
- if (inpos < inlen) v |= (uint64_t)in[inpos++];
- out[outpos++] = (v >> 35) & 0x1f;
- if (outpos < outlen) out[outpos++] = (v >> 30) & 0x1f;
- if (outpos < outlen) out[outpos++] = (v >> 25) & 0x1f;
- if (outpos < outlen) out[outpos++] = (v >> 20) & 0x1f;
- if (outpos < outlen) out[outpos++] = (v >> 15) & 0x1f;
- if (outpos < outlen) out[outpos++] = (v >> 10) & 0x1f;
- if (outpos < outlen) out[outpos++] = (v >> 5) & 0x1f;
- if (outpos < outlen) out[outpos++] = v & 0x1f;
- }
- return outpos;
- }
- static int expand_hrp(uint8_t *out, int outlen, char *in, int inlen)
- {
- int inpos, outpos, olen;
- olen = expanded_hrp_size(inlen);
- outlen = (outlen < olen) ? outlen : olen;
- for (inpos = outpos = 0; inpos < inlen && outpos < outlen; )
- out[outpos++] = (in[inpos++] >> 5) & 0x07;
- if (outpos < outlen)
- out[outpos++] = 0;
- for (inpos = 0; inpos < inlen && outpos < outlen; )
- out[outpos++] = in[inpos++] & 0x1f;
- return outpos;
- }
- int nostr_key_decode(char *str, uint8_t *hex, int hexlen)
- {
- int i, j, hrplen, tmpsize, v = -1;
- char *sep;
- uint8_t *tmp;
- /* get HRP length */
- if ((sep = strchr(str, '1')) == NULL)
- goto fin0;
- hrplen = sep - str;
- /* allocate working buffer */
- tmpsize = expanded_hrp_size(hrplen) +
- unpacked_size(hexlen) + BECH32_CHECKSUM_LEN;
- if ((tmp = calloc(tmpsize, sizeof(*tmp))) == NULL)
- goto fin0;
- /* expand HRP string to calculate checksum */
- expand_hrp(tmp, tmpsize, str, hrplen);
- /* decode bech32 string with checksum */
- for (i = hrplen + 1, j = expanded_hrp_size(hrplen); str[i]; i++, j++)
- if ((tmp[j] = bech32_char_decode(str[i])) == 0xff)
- goto fin1;
- /* validate checksum */
- if (bech32_polymod(tmp, tmpsize) != 1)
- goto fin1;
- /* output result */
- pack5to8(hex, hexlen, tmp + expanded_hrp_size(hrplen),
- unpacked_size(hexlen));
- fin1:
- memset(tmp, 0, tmpsize);
- free(tmp);
- fin0:
- return v;
- }
- int main(int argc, char *argv[])
- {
- #define NOSTR_HEXKEY_LEN 32
- char str[] = "npub1rarr265r9f9j6ewp960hcm7cvz9zskc7l2ykwul57e7xa60r8css7uf890";
- uint8_t buf[NOSTR_HEXKEY_LEN];
- memset(buf, 0xff, sizeof(buf));
- nostr_key_decode(str, buf, 32);
- hexdump(buf, NOSTR_HEXKEY_LEN);
- return 0;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement