File Coverage

blib/lib/Bitcoin/Crypto/Bech32.pm
Criterion Covered Total %
statement 147 148 99.3
branch 36 38 94.7
condition 19 23 82.6
subroutine 26 26 100.0
pod 6 16 37.5
total 234 251 93.2


line stmt bran cond sub pod time code
1             package Bitcoin::Crypto::Bech32;
2             $Bitcoin::Crypto::Bech32::VERSION = '1.008';
3 12     12   73367 use v5.10;
  12         56  
4 12     12   73 use strict;
  12         28  
  12         244  
5 12     12   57 use warnings;
  12         25  
  12         340  
6 12     12   63 use Exporter qw(import);
  12         35  
  12         402  
7 12     12   684 use Types::Standard qw(Str);
  12         118391  
  12         118  
8              
9 12     12   19668 use Bitcoin::Crypto::Exception;
  12         36  
  12         352  
10 12     12   545 use Bitcoin::Crypto::Helpers qw(verify_bytestring);
  12         35  
  12         643  
11 12     12   5386 use Bitcoin::Crypto::Segwit qw(validate_program);
  12         91  
  12         883  
12              
13             our @EXPORT_OK = qw(
14             translate_5to8
15             translate_8to5
16             encode_bech32
17             decode_bech32
18             encode_segwit
19             decode_segwit
20             );
21              
22 12     12   89 use constant BECH32 => 'bech32';
  12         24  
  12         952  
23 12     12   78 use constant BECH32M => 'bech32m';
  12         41  
  12         23505  
24              
25             our %EXPORT_TAGS = (all => [@EXPORT_OK]);
26              
27             my $CHECKSUM_SIZE = 6;
28             my $BECH32M_CONSTANT = 0x2bc830a3;
29              
30             my @alphabet = qw(
31             q p z r y 9 x 8
32             g f 2 t v d w 0
33             s 3 j n 5 4 k h
34             c e 6 m u a 7 l
35             );
36              
37             my %alphabet_mapped = map { $alphabet[$_] => $_ } 0 .. $#alphabet;
38              
39             sub polymod
40             {
41 127     127 0 235 my ($values) = @_;
42 127         244 my @consts = (0x3b6a57b2, 0x26508e6d, 0x1ea119fa, 0x3d4233dd, 0x2a1462b3);
43 127         200 my $chk = 1;
44 127         233 for my $val (@$values) {
45 6503         8280 my $b = ($chk >> 25);
46 6503         8555 $chk = ($chk & 0x1ffffff) << 5 ^ $val;
47 6503         9555 for (0 .. 4) {
48 32515 100       52501 $chk ^= ((($b >> $_) & 1) ? $consts[$_] : 0);
49             }
50             }
51 127         537 return $chk;
52             }
53              
54             sub hrp_expand
55             {
56 127     127 0 392 my @hrp = split "", shift;
57 127         230 my (@part1, @part2);
58 127         255 for (@hrp) {
59 684         904 my $val = ord;
60 684         919 push @part1, $val >> 5;
61 684         1120 push @part2, $val & 31;
62             }
63 127         425 return [@part1, 0, @part2];
64             }
65              
66             sub to_numarr
67             {
68 127     127 0 243 my ($string) = @_;
69              
70 127         839 return [map { $alphabet_mapped{$_} } split "", $string];
  4762         7447  
71             }
72              
73             sub create_checksum
74             {
75 29     29 0 69 my ($hrp, $data) = @_;
76 29         48 my $polymod = polymod([@{hrp_expand $hrp}, @{to_numarr $data}, (0) x $CHECKSUM_SIZE]) ^ 1;
  29         79  
  29         71  
77 29         107 my $checksum;
78 29         80 for (0 .. $CHECKSUM_SIZE - 1) {
79 174         313 $checksum .= $alphabet[($polymod >> 5 * (5 - $_)) & 31];
80             }
81 29         74 return $checksum;
82             }
83              
84             sub create_checksum_bech32m
85             {
86 12     12 0 29 my ($hrp, $data) = @_;
87 12         18 my $polymod = polymod([@{hrp_expand $hrp}, @{to_numarr $data}, (0) x $CHECKSUM_SIZE]) ^ $BECH32M_CONSTANT;
  12         25  
  12         33  
88 12         46 my $checksum;
89 12         33 for (0 .. $CHECKSUM_SIZE - 1) {
90 72         131 $checksum .= $alphabet[($polymod >> 5 * (5 - $_)) & 31];
91             }
92 12         26 return $checksum;
93             }
94              
95             sub verify_checksum
96             {
97 56     56 0 103 my ($hrp, $data) = @_;
98 56         83 return polymod([@{hrp_expand $hrp}, @{to_numarr $data}]) == 1;
  56         102  
  56         104  
99             }
100              
101             sub verify_checksum_bech32m
102             {
103 30     30 0 61 my ($hrp, $data) = @_;
104 30         47 return polymod([@{hrp_expand $hrp}, @{to_numarr $data}]) == $BECH32M_CONSTANT;
  30         48  
  30         57  
105             }
106              
107             sub split_bech32
108             {
109 72     72 0 139 my ($bech32enc) = @_;
110              
111 72 100       204 Bitcoin::Crypto::Exception::Bech32InputFormat->raise(
112             "bech32 input is not a string"
113             ) unless Str->check($bech32enc);
114              
115 71 100       966 $bech32enc = lc $bech32enc
116             if uc $bech32enc eq $bech32enc;
117              
118 71 100       165 Bitcoin::Crypto::Exception::Bech32InputFormat->raise(
119             "bech32 string too long"
120             ) if length $bech32enc > 90;
121              
122 69 100       177 Bitcoin::Crypto::Exception::Bech32InputFormat->raise(
123             "bech32 string contains mixed case"
124             ) if lc $bech32enc ne $bech32enc;
125              
126 67         201 my @parts = split "1", $bech32enc;
127              
128 67 100       168 Bitcoin::Crypto::Exception::Bech32InputFormat->raise(
129             "bech32 separator character missing"
130             ) if @parts < 2;
131              
132 66         117 my $data = pop @parts;
133              
134 66         199 @parts = (join("1", @parts), $data);
135              
136 66 100 66     277 Bitcoin::Crypto::Exception::Bech32InputFormat->raise(
137             "incorrect length of bech32 human readable part"
138             ) if length $parts[0] < 1 || length $parts[0] > 83;
139              
140 63 100       364 Bitcoin::Crypto::Exception::Bech32InputFormat->raise(
141             "illegal characters in bech32 human readable part"
142             ) if $parts[0] !~ /^[\x21-\x7e]+$/;
143              
144 60 100       129 Bitcoin::Crypto::Exception::Bech32InputFormat->raise(
145             "incorrect length of bech32 data part"
146             ) if length $parts[1] < 6;
147              
148 59         177 my $chars = join "", @alphabet;
149 59 100       369 Bitcoin::Crypto::Exception::Bech32InputFormat->raise(
150             "illegal characters in bech32 data part"
151             ) if $parts[1] !~ /^[$chars]+$/;
152              
153 56         220 return @parts;
154             }
155              
156             # used during segwit address decoding
157             sub translate_5to8
158             {
159 19     19 1 32 my ($values_ref) = @_;
160 19         27 my @enc_values = @{$values_ref};
  19         56  
161              
162 19         99 my $bits = unpack "B*", pack "C*", @enc_values;
163 19         175 $bits = join "", map { substr $_, 3 } unpack "(a8)*", $bits;
  702         1229  
164              
165 19         97 my $length_padded = length $bits;
166 19         36 my $padding = $length_padded % 8;
167 19         307 $bits =~ s/0{$padding}$//;
168              
169 19 100 100     157 Bitcoin::Crypto::Exception::Bech32InputData->raise(
170             "incorrect padding encoded in bech32"
171             ) if length($bits) % 8 != 0 || length($bits) < $length_padded - 4;
172              
173 16         93 my @data = unpack "(a8)*", $bits;
174 16         32 my $result = "";
175 16         33 for my $bitstr (@data) {
176 336         539 $result .= pack "B8", $bitstr;
177             }
178 16         80 return $result;
179             }
180              
181             # used during segwit address encoding
182             sub translate_8to5
183             {
184 25     25 1 86 my ($bytes) = @_;
185 25         79 verify_bytestring($bytes);
186              
187 25         370 my @data = unpack "(a5)*", unpack "B*", $bytes;
188 25         66 my @result;
189 25         59 for my $bitstr (@data) {
190 958         1245 my $pad = 5 - length $bitstr;
191 958         1979 my $num = unpack "C", pack "B*", "000$bitstr" . 0 x $pad;
192 958         1660 push @result, $num;
193             }
194              
195 25         251 return \@result;
196             }
197              
198             sub encode_base32
199             {
200 41     41 0 77 my ($array) = @_;
201              
202 41         64 my $result = '';
203 41         67 for my $num (@{$array}) {
  41         81  
204 1414 50 33     3507 Bitcoin::Crypto::Exception::Bech32InputData->raise(
205             "incorrect number to be encoded in bech32: must be between 0 and 31"
206             ) if $num < 0 || $num > 31;
207 1414         2118 $result .= $alphabet[$num];
208             }
209              
210 41         109 return $result;
211             }
212              
213             sub decode_base32
214             {
215 51     51 0 159 my ($encoded) = @_;
216              
217 51         274 my @enc_values = map { $alphabet_mapped{$_} } split //, $encoded;
  1810         2512  
218              
219 51         321 return \@enc_values;
220             }
221              
222             sub encode_bech32
223             {
224 41     41 1 28325 my ($hrp, $data, $type) = @_;
225 41   50     109 $type //= BECH32M;
226              
227 41         121 my $result = encode_base32($data);
228 41         74 my $checksum;
229              
230 41 100       127 if ($type eq BECH32) {
    50          
231 29         81 $checksum = create_checksum($hrp, $result);
232             }
233             elsif ($type eq BECH32M) {
234 12         29 $checksum = create_checksum_bech32m($hrp, $result);
235             }
236             else {
237 0         0 Bitcoin::Crypto::Exception::Bech32Type->raise(
238             'invalid type: neither bech32 nor bech32m'
239             );
240             }
241              
242 41         303 return $hrp . 1 . $result . $checksum;
243             }
244              
245             sub encode_segwit
246             {
247 25     25 1 10371 my ($hrp, $bytes) = @_;
248              
249 25         109 my $version = validate_program($bytes);
250 25 100       57 return encode_bech32($hrp, [$version, @{translate_8to5(substr $bytes, 1)}], $version == 0 ? BECH32 : BECH32M);
  25         89  
251             }
252              
253             sub decode_bech32
254             {
255 72     72 1 74638 my ($hrp, $data) = split_bech32 @_;
256              
257 56         86 my $type;
258 56 100       135 $type = BECH32
259             if verify_checksum($hrp, $data);
260 56 100 100     214 $type = BECH32M
261             if !$type && verify_checksum_bech32m($hrp, $data);
262              
263 56 100       163 Bitcoin::Crypto::Exception::Bech32InputChecksum->raise(
264             "incorrect bech32 checksum"
265             ) unless $type;
266              
267 51         169 return ($hrp, decode_base32(substr $data, 0, -$CHECKSUM_SIZE), $type);
268             }
269              
270             sub decode_segwit
271             {
272 30     30 1 71405 my ($hrp, $data, $type) = decode_bech32 @_;
273 25         53 my $ver = shift @{$data};
  25         52  
274              
275 25 100 100     179 Bitcoin::Crypto::Exception::Bech32InputChecksum->raise(
      100        
      100        
276             "wrong bech32 checksum calculated for given segwit program"
277             ) if ($ver == 0 && $type ne BECH32)
278             || ($ver > 0 && $type ne BECH32M);
279              
280 19         97 my $bytes = pack('C', $ver) . translate_5to8 $data;
281 16         73 validate_program($bytes);
282              
283 10         36 return $bytes;
284             }
285              
286             1;
287              
288             __END__
289             =head1 NAME
290              
291             Bitcoin::Crypto::Bech32 - Bitcoin's Bech32 implementation in Perl
292              
293             =head1 SYNOPSIS
294              
295             # none exported by default
296             use Bitcoin::Crypto::Bech32 qw(
297             translate_5to8
298             translate_8to5
299             encode_bech32
300             decode_bech32
301             encode_segwit
302             decode_segwit
303             );
304              
305             # witness version - a number from 0 to 16, packed into a byte
306             my $version = pack "C", 0;
307              
308             # human readable part of the address - a string
309             my $network_hrp = Bitcoin::Crypto::Network->get->segwit_hrp;
310              
311             # handles Bitcoin SegWit adresses
312             my $segwit_address = encode_segwit($network_hrp, $version . $pubkeyhash);
313             my $data_with_version = decode_segwit($segwit_address);
314              
315             # handles custom Bech32 encoding
316             my $bech32str = encode_bech32("hello", [28, 25, 31, 0, 5], Bitcoin::Crypto::Bech32->BECH32); # should start with hello1
317             my ($hrp, $data_aref, $type) = decode_bech32($bech32str);
318              
319             =head1 DESCRIPTION
320              
321             Implementation of Bech32 algorithm (BIP-173 and BIP-350 compatible)
322              
323             The module has a couple of layers of encoding, namely:
324              
325             =over
326              
327             =item * 5-to-8 and 8-to-5 bits transformation
328              
329             =item * bech32, which handles checksums and human-readable (HRP) parts
330              
331             =item * segwit, which handles segwit program numbering and validation
332              
333             =back
334              
335             For Bech32-encoded SegWit addresses, use I<encode_segwit> and I<decode_segwit>.
336             For custom uses of Bech32 (not in context of Bitcoin SegWit addresses), use
337             I<encode_bech32> and I<decode_bech32>.
338              
339             B<If in doubt, use segwit functions, not bech32 functions!>
340              
341             =head1 FUNCTIONS
342              
343             This module is based on Exporter. None of the functions are exported by default. C<:all> tag exists that exports all the functions at once.
344              
345             =head2 encode_segwit
346              
347             my $encoded_address = encode_segwit($hrp, $segwit_program);
348              
349             =head2 decode_segwit
350              
351             my $segwit_program = decode_segwit($encoded_address);
352              
353             Bech32 encoding / decoding valid for SegWit addresses. Does not validate the human readable part.
354              
355             These functions also perform segwit program validation, see L<Bitcoin::Crypto::Segwit>.
356              
357             Encoding takes two arguments which are a human readable part and a bytestring.
358              
359             Decoding takes bech32-encoded string. Returns the entire encoded data (bytestring) along with the segwit program version byte.
360              
361             =head2 encode_bech32
362              
363             my $encoded_bech32 = encode_bech32($hrp, \@data, Bitcoin::Crypto::Bech32->BECH32 || Bitcoin::Crypto::Bech32->BECH32M);
364              
365             =head2 decode_bech32
366              
367             my ($hrp, $data_aref, $type) = decode_bech32($encoded_bech32);
368              
369             Basic bech32 encoding / decoding.
370              
371             Encoding takes up to three arguments which are:
372              
373             =over
374              
375             =item * a human readable part
376              
377             =item * an array reference of integer values to be encoded in bech32 (each must be between 0 and 31)
378              
379             =item * optional type, which may be C<'bech32'> or C<'bech32m'> (available in constant values Bitcoin::Crypto::Bech32::BECH32 and Bitcoin::Crypto::Bech32::BECH32M)
380              
381             If omitted, the type will be equal to C<'bech32m'>, which has more robust checksum.
382              
383             =back
384              
385             Decoding takes a single parameter: a bech32-encoded string and returns a list which has the same elements as arguments to C<encode_bech32> function.
386              
387             This means you can feed both bech32 and bech32m encodings to C<decode_bech32> and the function will identify and return the type for you.
388              
389             B<These methods are not meant to work with Bitcoin SegWit addresses, use encode_segwit and decode_segwit for that instead>
390              
391             =head2 translate_5to8
392              
393             my $bytestr = translate_5to8(\@int_array);
394              
395             =head2 translate_8to5
396              
397             my $int_aref = translate_8to5($bytestr);
398              
399             These are helper functions that implement 5-bit to 8-bit encoding used in bech32 segwit addresses. C<translate_8to5> is used during encoding, and C<translate_5to8> during decoding. They can be used as means to store full byte data in bech32 strings, like so:
400              
401             my $data = encode_bech32('hrp', translate_8to5($bytes));
402             my $decoded = translate_5to8(decode_bech32($data));
403              
404             =head1 EXCEPTIONS
405              
406             This module throws an instance of L<Bitcoin::Crypto::Exception> if it encounters an error. It can produce the following error types from the L<Bitcoin::Crypto::Exception> namespace:
407              
408             =over 2
409              
410             =item * Bech32InputFormat - input was not suitable for bech32 operations due to invalid format
411              
412             =item * Bech32InputData - input was parsed with bech32 operations but contained invalid data
413              
414             =item * Bech32InputChecksum - checksum validation has failed
415              
416             =item * Bech32Type - invalid type was passed to bech32_encode function
417              
418             =back
419              
420             =head1 SEE ALSO
421              
422             =over 2
423              
424             =item L<Bitcoin::Crypto::Base58>
425              
426             =item L<Bitcoin::Crypto::Segwit>
427              
428             =item L<Bitcoin::Crypto::Key::Public>
429              
430             =back
431              
432             =cut
433