Returns Codex32 encoded secret of the seed provided. */
| 388 | |
| 389 | /* Returns Codex32 encoded secret of the seed provided. */ |
| 390 | const char *codex32_secret_encode(const tal_t *ctx, |
| 391 | const char *hrp, |
| 392 | const char *id, |
| 393 | const u32 threshold, |
| 394 | const u8 *seed, |
| 395 | size_t seedlen, |
| 396 | char **bip93) |
| 397 | { |
| 398 | const struct checksum_engine *csum_engine; |
| 399 | |
| 400 | /* FIXME: Our code assumes a two-letter HRP! Larger won't allow a |
| 401 | * 128-bit secret in a "standard billfold metal wallet" acording to |
| 402 | * Russell O'Connor */ |
| 403 | assert(strlen(hrp) == 2); |
| 404 | |
| 405 | if (threshold > 9 || threshold < 0 || threshold == 1) |
| 406 | return tal_fmt(ctx, "Invalid threshold %u", threshold); |
| 407 | |
| 408 | if (strlen(id) != 4) |
| 409 | return tal_fmt(ctx, "Invalid id: must be 4 characters"); |
| 410 | |
| 411 | for (size_t i = 0; id[i]; i++) { |
| 412 | s8 rev; |
| 413 | |
| 414 | if (id[i] & 0x80) |
| 415 | return tal_fmt(ctx, "Invalid id: must be ASCII"); |
| 416 | |
| 417 | rev = bech32_charset_rev[(int)id[i]]; |
| 418 | if (rev == -1) |
| 419 | return tal_fmt(ctx, "Invalid id: must be valid bech32 string"); |
| 420 | if (bech32_charset[rev] != id[i]) |
| 421 | return tal_fmt(ctx, "Invalid id: must be lower-case"); |
| 422 | } |
| 423 | |
| 424 | /* Every codex32 has hrp `ms` and since we are generating a |
| 425 | * secret it's share index would be `s` and threshold given by user. */ |
| 426 | *bip93 = tal_fmt(ctx, "%s1%d%ss", hrp, threshold, id); |
| 427 | |
| 428 | uint8_t next_u5 = 0, rem = 0; |
| 429 | |
| 430 | for (size_t i = 0; i < seedlen; i++) { |
| 431 | /* Each byte provides at least one u5. Push that. */ |
| 432 | uint8_t u5 = (next_u5 << (5 - rem)) | seed[i] >> (3 + rem); |
| 433 | |
| 434 | tal_append_fmt(bip93, "%c", bech32_charset[u5]); |
| 435 | next_u5 = seed[i] & ((1 << (3 + rem)) - 1); |
| 436 | |
| 437 | /* If there were 2 or more bits from the last iteration, then |
| 438 | * this iteration will push *two* u5s. */ |
| 439 | if(rem >= 2) { |
| 440 | tal_append_fmt(bip93, "%c", bech32_charset[next_u5 >> (rem - 2)]); |
| 441 | next_u5 &= (1 << (rem - 2)) - 1; |
| 442 | } |
| 443 | rem = (rem + 8) % 5; |
| 444 | } |
| 445 | if(rem > 0) { |
| 446 | tal_append_fmt(bip93, "%c", bech32_charset[next_u5 << (5 - rem)]); |
| 447 | } |