File Coverage

blib/lib/Crypt/Misc.pm
Criterion Covered Total %
statement 145 182 79.6
branch 37 86 43.0
condition 12 40 30.0
subroutine 34 36 94.4
pod 19 19 100.0
total 247 363 68.0


line stmt bran cond sub pod time code
1             package Crypt::Misc;
2              
3 16     16   154445 use strict;
  16         18  
  16         444  
4 16     16   49 use warnings;
  16         18  
  16         1134  
5             our $VERSION = '0.088';
6              
7             require Exporter; our @ISA = qw(Exporter); ### use Exporter 5.57 'import';
8 16     16   66 use Carp 'croak';
  16         16  
  16         1854  
9             our %EXPORT_TAGS = ( all => [qw(encode_b64 decode_b64
10             encode_b64u decode_b64u
11             encode_b58b decode_b58b
12             encode_b58f decode_b58f
13             encode_b58r decode_b58r
14             encode_b58t decode_b58t
15             encode_b58s decode_b58s
16             encode_b32r decode_b32r
17             encode_b32b decode_b32b
18             encode_b32z decode_b32z
19             encode_b32c decode_b32c
20             pem_to_der der_to_pem
21             read_rawfile write_rawfile
22             slow_eq is_v4uuid random_v4uuid
23             is_uuid random_v7uuid
24             increment_octets_be increment_octets_le
25             )] );
26             our @EXPORT_OK = ( @{ $EXPORT_TAGS{'all'} } );
27             our @EXPORT = qw();
28              
29 16     16   65 use Carp 'carp';
  16         19  
  16         558  
30 16     16   671 use CryptX;
  16         20  
  16         352  
31 16     16   1454 use Crypt::Digest 'digest_data';
  16         20  
  16         611  
32 16     16   5606 use Crypt::Mode::CBC;
  16         64  
  16         403  
33 16     16   5054 use Crypt::Mode::CFB;
  16         33  
  16         385  
34 16     16   5280 use Crypt::Mode::ECB;
  16         32  
  16         364  
35 16     16   4953 use Crypt::Mode::OFB;
  16         31  
  16         336  
36 16     16   58 use Crypt::Cipher;
  16         15  
  16         231  
37 16     16   5253 use Crypt::PRNG 'random_bytes';
  16         85  
  16         886  
38 16     16   75 use Time::HiRes (); # perl core module
  16         18  
  16         36894  
39              
40             sub _encode_b58 {
41 290     290   715 my ($bytes, $alphabet) = @_;
42              
43 290 50 33     1492 return '' if !defined $bytes || length($bytes) == 0;
44              
45             # handle leading zero-bytes
46 290         422 my $base58 = '';
47 290 100       1017 if ($bytes =~ /^(\x00+)/) {
48 80         257 $base58 = ('0' x length($1));
49             }
50 290         4441 $base58 .= _bin_to_radix($bytes, 58);
51              
52 290 50       662 if (defined $alphabet) {
53 290         378 my $default = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuv";
54 290 50       1165 return undef if $alphabet !~ /^[a-zA-Z0-9]{58}$/;
55 290         28950 eval "\$base58 =~ tr/$default/$alphabet/"; # HACK: https://stackoverflow.com/questions/11415045/using-a-char-variable-in-tr
56 290 50       1283 return undef if $@;
57             }
58              
59 290         1001 return $base58;
60             }
61              
62             sub _decode_b58 {
63 291     291   577 my ($base58, $alphabet) = @_;
64              
65 291 50 33     1212 return '' if !defined $base58 || length($base58) == 0;
66              
67 291         389 my $default = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuv";
68 291 50       541 if (defined $alphabet) {
69 291 100 66     14048 return undef if $alphabet !~ /^[a-zA-Z0-9]{58}$/ || $base58 !~ /^[$alphabet]+$/;
70 290         21622 eval "\$base58 =~ tr/$alphabet/$default/"; # HACK: https://stackoverflow.com/questions/11415045/using-a-char-variable-in-tr
71 290 50       907 return undef if $@;
72             }
73 290 50       1333 return undef if $base58 !~ /^[$default]+$/;
74              
75             # handle leading zeroes
76 290         390 my $bytes = '';
77 290 100       634 if ($base58 =~ /^(0+)(.*)$/) {
78 80         140 $base58 = $2;
79 80         155 $bytes = ("\x00" x length($1));
80             }
81 290 100 66     2175 $bytes .= _radix_to_bin($base58, 58) if defined $base58 && length($base58) > 0;
82              
83 290         1339 return $bytes;
84             }
85              
86 59     59 1 845 sub decode_b58b { _decode_b58(shift, "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz") } # Bitcoin
87 58     58 1 126 sub decode_b58f { _decode_b58(shift, "123456789abcdefghijkmnopqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ") } # Flickr
88 58     58 1 122 sub decode_b58r { _decode_b58(shift, "rpshnaf39wBUDNEGHJKLM4PQRST7VWXYZ2bcdeCg65jkm8oFqi1tuvAxyz") } # Ripple
89 58     58 1 133 sub decode_b58t { _decode_b58(shift, "RPShNAF39wBUDnEGHJKLM4pQrsT7VWXYZ2bcdeCg65jkm8ofqi1tuvaxyz") } # Tipple
90 58     58 1 127 sub decode_b58s { _decode_b58(shift, "gsphnaf39wBUDNEGHJKLM4PQRST7VWXYZ2bcdeCr65jkm8oFqi1tuvAxyz") } # Stellar
91              
92 58     58 1 111054 sub encode_b58b { _encode_b58(shift, "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz") } # Bitcoin
93 58     58 1 157 sub encode_b58f { _encode_b58(shift, "123456789abcdefghijkmnopqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ") } # Flickr
94 58     58 1 163 sub encode_b58r { _encode_b58(shift, "rpshnaf39wBUDNEGHJKLM4PQRST7VWXYZ2bcdeCg65jkm8oFqi1tuvAxyz") } # Ripple
95 58     58 1 163 sub encode_b58t { _encode_b58(shift, "RPShNAF39wBUDnEGHJKLM4pQrsT7VWXYZ2bcdeCg65jkm8ofqi1tuvaxyz") } # Tipple
96 58     58 1 162 sub encode_b58s { _encode_b58(shift, "gsphnaf39wBUDNEGHJKLM4PQRST7VWXYZ2bcdeCr65jkm8oFqi1tuvAxyz") } # Stellar
97              
98             sub pem_to_der {
99 11     11 1 24 my ($data, $password) = @_;
100              
101 11         16 my ($begin, $obj1, $content, $end, $obj2);
102             # first try to load KEY (e.g. EC pem files might contain more parts)
103 11         83 ($begin, $obj1, $content, $end, $obj2) = $data =~ m/(----[- ]BEGIN ([^\r\n\-]+KEY)[ -]----)(.*?)(----[- ]END ([^\r\n\-]+)[ -]----)/s;
104             # if failed then try to load anything
105 11 100       38 ($begin, $obj1, $content, $end, $obj2) = $data =~ m/(----[- ]BEGIN ([^\r\n\-]+)[ -]----)(.*?)(----[- ]END ([^\r\n\-]+)[ -]----)/s unless $content;
106 11 50       22 return undef unless $content;
107              
108 11         42 $content =~ s/^\s+//sg;
109 11         51 $content =~ s/\s+$//sg;
110 11         22 $content =~ s/\r\n/\n/sg; # CR-LF >> LF
111 11         19 $content =~ s/\r/\n/sg; # CR >> LF
112 11         17 $content =~ s/\\\n//sg; # \ + LF
113              
114 11         60 my ($headers, undef, $b64) = $content =~ /^(([^:]+:.*?\n)*)(.*)$/s;
115 11 50       26 return undef unless $b64;
116              
117 11         82 my $binary = decode_b64($b64);
118 11 50       20 return undef unless $binary;
119              
120 11         14 my ($ptype, $cipher_name, $iv_hex);
121 11   50     88 for my $h (split /\n/, ($headers||'')) {
122 0         0 my ($k, $v) = split /:\s*/, $h, 2;
123 0 0       0 $ptype = $v if $k eq 'Proc-Type';
124 0 0       0 ($cipher_name, $iv_hex) = $v =~ /^\s*(.*?)\s*,\s*([0-9a-fA-F]+)\s*$/ if $k eq 'DEK-Info';
125             }
126 11 0 33     29 if ($cipher_name && $iv_hex && $ptype && $ptype eq '4,ENCRYPTED') {
      33        
      0        
127 0 0       0 croak "FATAL: encrypted PEM but no password provided" unless defined $password;
128 0         0 my $iv = pack("H*", $iv_hex);
129 0         0 my ($mode, $klen) = _name2mode($cipher_name);
130 0         0 my $key = _password2key($password, $klen, $iv, 'MD5');
131 0         0 return $mode->decrypt($binary, $key, $iv);
132             }
133 11         11350 return $binary;
134             }
135              
136             sub der_to_pem {
137 21     21 1 46 my ($data, $header_name, $password, $cipher_name) = @_;
138 21         30 my $content = $data;
139 21         26 my @headers;
140              
141 21 50       47 if ($password) {
142 0   0     0 $cipher_name ||= 'AES-256-CBC';
143 0         0 my ($mode, $klen, $ilen) = _name2mode($cipher_name);
144 0         0 my $iv = random_bytes($ilen);
145 0         0 my $key = _password2key($password, $klen, $iv, 'MD5');
146 0         0 $content = $mode->encrypt($data, $key, $iv);
147 0         0 push @headers, 'Proc-Type: 4,ENCRYPTED', "DEK-Info: ".uc($cipher_name).",".unpack("H*", $iv);
148             }
149              
150 21         33 my $pem = "-----BEGIN $header_name-----\n";
151 21 50       39 if (@headers) {
152 0         0 $pem .= "$_\n" for @headers;
153 0         0 $pem .= "\n";
154             }
155 21         316 my @l = encode_b64($content) =~ /.{1,64}/g;
156 21         73 $pem .= join("\n", @l) . "\n";
157 21         36 $pem .= "-----END $header_name-----\n";
158 21         148 return $pem;
159             }
160              
161             sub read_rawfile {
162             # $data = read_rawfile($filename);
163 278     278 1 3129 my $f = shift;
164 278 50       2238 croak "FATAL: read_rawfile() non-existing file '$f'" unless -f $f;
165 278 50       8885 open my $fh, "<", $f or croak "FATAL: read_rawfile() cannot open file '$f': $!";
166 278         701 binmode $fh;
167 278         384 return do { local $/; <$fh> };
  278         1033  
  278         14739  
168             }
169              
170             sub write_rawfile {
171             # write_rawfile($filename, $data);
172 1 50   1 1 146702 croak "FATAL: write_rawfile() no data" unless defined $_[1];
173 1 50       328 open my $fh, ">", $_[0] or croak "FATAL: write_rawfile() cannot open file '$_[0]': $!";
174 1         5 binmode $fh;
175 1 50       36 print $fh $_[1] or croak "FATAL: write_rawfile() cannot write to '$_[0]': $!";
176 1 50       46 close $fh or croak "FATAL: write_rawfile() cannot close '$_[0]': $!";
177 1         7 return;
178             }
179              
180             sub slow_eq {
181 1     1 1 3 my ($a, $b) = @_;
182 1 50 33     7 return unless defined $a && defined $b;
183 1         3 my $diff = length $a ^ length $b;
184 1   66     7 for(my $i = 0; $i < length $a && $i < length $b; $i++) {
185 10         23 $diff |= ord(substr $a, $i) ^ ord(substr $b, $i);
186             }
187 1         6 return $diff == 0;
188             }
189              
190             sub random_v4uuid() {
191             # Version 4 - random - UUID: xxxxxxxx-xxxx-4xxx-Yxxx-xxxxxxxxxxxx
192             # where x is any hexadecimal digit and Y is one of 8, 9, A, B (1000, 1001, 1010, 1011)
193             # e.g. f47ac10b-58cc-4372-a567-0e02b2c3d479
194 1     1 1 10 my $raw = random_bytes(16);
195             # xxxxxxxxxxxx4xxxYxxxxxxxxxxxxxxx
196 1         3 $raw &= pack("H*", "FFFFFFFFFFFF0FFFFFFFFFFFFFFFFFFF");
197 1         2 $raw |= pack("H*", "00000000000040000000000000000000");
198 1         2 $raw &= pack("H*", "FFFFFFFFFFFFFFFF3FFFFFFFFFFFFFFF"); # 0x3 == 0011b
199 1         2 $raw |= pack("H*", "00000000000000008000000000000000"); # 0x8 == 1000b
200 1         3 my $hex = unpack("H*", $raw);
201 1         19 $hex =~ s/^(.{8})(.{4})(.{4})(.{4})(.{12}).*$/$1-$2-$3-$4-$5/;
202 1         4 return $hex;
203             }
204              
205             sub random_v7uuid {
206             # RFC 9562 §5.7 - Version 7 UUID (time-ordered)
207             # Format: xxxxxxxx-xxxx-7xxx-[89ab]xxx-xxxxxxxxxxxx
208             # Structure: 48-bit ms timestamp | 4-bit ver=7 | 12-bit rand | 2-bit var=10 | 62-bit rand
209 3     3 1 9 my ($sec, $usec) = Time::HiRes::gettimeofday();
210 3         8 my $ms = $sec * 1000 + int($usec / 1000);
211 3         7 my $rand = random_bytes(10);
212 3         23 my $raw = pack("N", int($ms / 65536)) . # bytes 0-3: ms[47:16]
213             pack("n", $ms % 65536) . # bytes 4-5: ms[15:0]
214             pack("n", 0x7000 | (unpack("n", substr($rand, 0, 2)) & 0x0FFF)) . # bytes 6-7: ver=7 + rand_a
215             pack("C", 0x80 | (unpack("C", substr($rand, 2, 1)) & 0x3F)) . # byte 8: var=10 + rand_b
216             substr($rand, 3, 7); # bytes 9-15: rand_b (cont.)
217 3         6 my $hex = unpack("H*", $raw);
218 3         32 $hex =~ s/^(.{8})(.{4})(.{4})(.{4})(.{12})$/$1-$2-$3-$4-$5/;
219 3         9 return $hex;
220             }
221              
222             sub is_v4uuid($) {
223 2     2 1 248 my $uuid = shift;
224 2 50       5 return 0 if !$uuid;
225 2 100       11 return 1 if $uuid =~ /^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
226 1         2 return 0;
227             }
228              
229             sub is_uuid($) {
230 8     8 1 1153 my $uuid = shift;
231 8 100       16 return 0 if !$uuid;
232 7 100       36 return 1 if $uuid =~ /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
233 2         6 return 0;
234             }
235              
236             ### private functions
237              
238             sub _name2mode {
239 0     0     my $cipher_name = uc(shift);
240 0           my %trans = ( 'DES-EDE3' => 'DES_EDE' );
241              
242 0           my ($cipher, undef, $klen, $mode) = $cipher_name =~ /^(AES|CAMELLIA|DES|DES-EDE3|SEED)(-(\d+))?-(CBC|CFB|ECB|OFB)$/i;
243 0 0 0       croak "FATAL: unsupported cipher '$cipher_name'" unless $cipher && $mode;
244 0   0       $cipher = $trans{$cipher} || $cipher;
245 0 0         $klen = 192 if $cipher eq 'DES_EDE';
246 0 0         $klen = 64 if $cipher eq 'DES';
247 0 0         $klen = 128 if $cipher eq 'SEED';
248 0 0         $klen = $klen ? int($klen/8) : Crypt::Cipher::min_keysize($cipher);
249 0           my $ilen = Crypt::Cipher::blocksize($cipher);
250 0 0 0       croak "FATAL: unsupported cipher '$cipher_name'" unless $klen && $ilen;
251              
252 0 0         return (Crypt::Mode::CBC->new($cipher), $klen, $ilen) if $mode eq 'CBC';
253 0 0         return (Crypt::Mode::CFB->new($cipher), $klen, $ilen) if $mode eq 'CFB';
254 0 0         return (Crypt::Mode::ECB->new($cipher), $klen, $ilen) if $mode eq 'ECB';
255 0 0         return (Crypt::Mode::OFB->new($cipher), $klen, $ilen) if $mode eq 'OFB';
256             }
257              
258             sub _password2key {
259 0     0     my ($password, $klen, $iv, $hash) = @_;
260 0           my $salt = substr($iv, 0, 8);
261 0           my $key = '';
262 0           while (length($key) < $klen) {
263 0           $key .= digest_data($hash, $key . $password . $salt);
264             }
265 0           return substr($key, 0, $klen);
266             }
267              
268             1;
269              
270             =pod
271              
272             =head1 NAME
273              
274             Crypt::Misc - miscellaneous functions related to (or used by) CryptX
275              
276             =head1 SYNOPSIS
277              
278             This module contains a collection of mostly unsorted functions loosely-related to CryptX distribution but not implementing cryptography.
279              
280             Most of them are also available in other perl modules but once you utilize CryptX you might avoid dependencies on other modules by using
281             functions from Crypt::Misc.
282              
283             =head1 DESCRIPTION
284              
285             use Crypt::Misc ':all';
286              
287             # Base64 and Base64/URL-safe functions
288             $base64 = encode_b64($rawbytes);
289             $rawbytes = decode_b64($base64);
290             $base64url = encode_b64u($encode_b64u);
291             $rawbytes = decode_b64u($base64url);
292              
293             # read/write file
294             $rawdata = read_rawfile($filename);
295             write_rawfile($filename, $rawdata);
296              
297             # convert PEM/DER
298             $der_data = pem_to_der($pem_data);
299             $pem_data = der_to_pem($der_data);
300              
301             # others
302             die "mismatch" unless slow_eq($str1, $str2);
303              
304             =head1 FUNCTIONS
305              
306             By default, Crypt::Misc doesn't import any function. You can import individual functions like this:
307              
308             use Crypt::Misc qw(read_rawfile);
309              
310             Or import all available functions:
311              
312             use Crypt::Misc ':all';
313              
314             =head2 read_rawfile
315              
316             I
317              
318             $rawdata = read_rawfile($filename);
319              
320             Read file C<$filename> into a scalar as a binary data (without decoding/transformation).
321              
322             =head2 write_rawfile
323              
324             I
325              
326             write_rawfile($filename, $rawdata);
327              
328             Write C<$rawdata> to file C<$filename> as binary data.
329              
330             =head2 slow_eq
331              
332             I
333              
334             if (slow_eq($data1, $data2)) { ... }
335              
336             Constant time compare (to avoid timing side-channel).
337              
338             =head2 pem_to_der
339              
340             I
341              
342             $der_data = pem_to_der($pem_data);
343             #or
344             $der_data = pem_to_der($pem_data, $password);
345              
346             Convert PEM to DER representation. Supports also password protected PEM data.
347              
348             =head2 der_to_pem
349              
350             I
351              
352             $pem_data = der_to_pem($der_data, $header_name);
353             #or
354             $pem_data = der_to_pem($der_data, $header_name, $password);
355             #or
356             $pem_data = der_to_pem($der_data, $header_name, $passord, $cipher_name);
357              
358             # $header_name e.g. "PUBLIC KEY", "RSA PRIVATE KEY" ...
359             # $cipher_name e.g. "DES-EDE3-CBC", "AES-256-CBC" (DEFAULT) ...
360              
361             Convert DER to PEM representation. Supports also password protected PEM data.
362              
363             =head2 random_v4uuid
364              
365             I
366              
367             my $uuid = random_v4uuid();
368              
369             Returns cryptographically strong Version 4 random UUID: C
370             where C is any hexadecimal digit and C is one of 8, 9, A, B (1000, 1001, 1010, 1011)
371             e.g. C.
372              
373             =head2 is_v4uuid
374              
375             I
376              
377             if (is_v4uuid($uuid)) {
378             ...
379             }
380              
381             Checks the given C<$uuid> string whether it matches V4 UUID format and returns C<0> (mismatch) or C<1> (match).
382              
383             =head2 random_v7uuid
384              
385             I
386              
387             my $uuid = random_v7uuid();
388              
389             Returns a cryptographically strong Version 7 time-ordered UUID: C
390             where the first 48 bits encode the current Unix time in milliseconds (making UUIDs sortable by
391             generation time), followed by random bits. C is one of 8, 9, A, B (RFC 9562 variant).
392              
393             =head2 is_uuid
394              
395             I
396              
397             if (is_uuid($uuid)) {
398             ...
399             }
400              
401             Checks whether C<$uuid> is a validly formatted UUID (any version) in the standard
402             C form. Returns C<1> (match) or C<0> (mismatch).
403             For a version-specific check see L.
404              
405             =head2 increment_octets_le
406              
407             I
408              
409             $octects = increment_octets_le($octets);
410              
411             Take input C<$octets> as a little-endian big number and return an increment.
412              
413             =head2 increment_octets_be
414              
415             I
416              
417             $octects = increment_octets_be($octets);
418              
419             Take input C<$octets> as a big-endian big number and return an increment.
420              
421             =head2 encode_b64
422              
423             I
424              
425             $base64string = encode_b64($rawdata);
426              
427             Encode $rawbytes into Base64 string, no line-endings in the output string.
428              
429             =head2 decode_b64
430              
431             I
432              
433             $rawdata = decode_b64($base64string);
434              
435             Decode a Base64 string.
436              
437             =head2 encode_b64u
438              
439             I
440              
441             $base64url_string = encode_b64($rawdata);
442              
443             Encode $rawbytes into Base64/URL-Safe string, no line-endings in the output string.
444              
445             =head2 decode_b64u
446              
447             I
448              
449             $rawdata = decode_b64($base64url_string);
450              
451             Decode a Base64/URL-Safe string.
452              
453             =head2 encode_b32r
454              
455             I
456              
457             $string = encode_b32r($rawdata);
458              
459             Encode bytes into Base32 (rfc4648 alphabet) string, without "=" padding.
460              
461             =head2 decode_b32r
462              
463             I
464              
465             $rawdata = decode_b32r($string);
466              
467             Decode a Base32 (rfc4648 alphabet) string into bytes.
468              
469             =head2 encode_b32b
470              
471             I
472              
473             $string = encode_b32b($rawdata);
474              
475             Encode bytes into Base32 (base32hex alphabet) string, without "=" padding.
476              
477             =head2 decode_b32b
478              
479             I
480              
481             $rawdata = decode_b32b($string);
482              
483             Decode a Base32 (base32hex alphabet) string into bytes.
484              
485             =head2 encode_b32z
486              
487             I
488              
489             $string = encode_b32z($rawdata);
490              
491             Encode bytes into Base32 (zbase32 alphabet) string.
492              
493             =head2 decode_b32z
494              
495             I
496              
497             $rawdata = decode_b32z($string);
498              
499             Decode a Base32 (zbase32 alphabet) string into bytes.
500              
501             =head2 encode_b32c
502              
503             I
504              
505             $string = encode_b32c($rawdata);
506              
507             Encode bytes into Base32 (crockford alphabet) string.
508              
509             =head2 decode_b32c
510              
511             I
512              
513             $rawdata = decode_b32c($string);
514              
515             Decode a Base32 (crockford alphabet) string into bytes.
516              
517             =head2 encode_b58b
518              
519             I
520              
521             $string = encode_b58b($rawdata);
522              
523             Encode bytes into Base58 (Bitcoin alphabet) string.
524              
525             =head2 decode_b58b
526              
527             I
528              
529             $rawdata = decode_b58b($string);
530              
531             Decode a Base58 (Bitcoin alphabet) string into bytes.
532              
533             =head2 encode_b58f
534              
535             I
536              
537             $string = encode_b58f($rawdata);
538              
539             Encode bytes into Base58 (Flickr alphabet) string.
540              
541             =head2 decode_b58f
542              
543             I
544              
545             $rawdata = decode_b58f($string);
546              
547             Decode a Base58 (Flickr alphabet) string into bytes.
548              
549             =head2 encode_b58r
550              
551             I
552              
553             $string = encode_b58r($rawdata);
554              
555             Encode bytes into Base58 (Ripple alphabet) string.
556              
557             =head2 decode_b58r
558              
559             I
560              
561             $rawdata = decode_b58r($string);
562              
563             Decode a Base58 (Ripple alphabet) string into bytes.
564              
565             =head2 encode_b58t
566              
567             I
568              
569             $string = encode_b58t($rawdata);
570              
571             Encode bytes into Base58 (Tipple alphabet) string.
572              
573             =head2 decode_b58t
574              
575             I
576              
577             $rawdata = decode_b58t($string);
578              
579             Decode a Base58 (Tipple alphabet) string into bytes.
580              
581             =head2 encode_b58s
582              
583             I
584              
585             $string = encode_b58s($rawdata);
586              
587             Encode bytes into Base58 (Stellar alphabet) string.
588              
589             =head2 decode_b58s
590              
591             I
592              
593             $rawdata = decode_b58s($string);
594              
595             Decode a Base58 (Stellar alphabet) string into bytes.
596              
597             =head1 SEE ALSO
598              
599             =over
600              
601             =item * L
602              
603             =back
604              
605             =cut