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