File Coverage

blib/lib/Encode/Base58/GMP.pm
Criterion Covered Total %
statement 19 21 90.4
branch n/a
condition n/a
subroutine 7 7 100.0
pod n/a
total 26 28 92.8


line stmt bran cond sub pod time code
1             package Encode::Base58::GMP;
2 7     7   609857 use strict;
  7         17  
  7         231  
3 7     7   35 use warnings;
  7         15  
  7         166  
4 7     7   179 use 5.008_009;
  7         39  
  7         422  
5             our $VERSION = '1.00';
6              
7 7     7   37 use base qw(Exporter);
  7         12  
  7         388  
8             our @EXPORT = qw(encode_base58 decode_base58);
9             our @EXPORT_OK = qw(base58_from_to base58_flickr_to_gmp base58_gmp_to_flickr md5_base58);
10              
11 7     7   784 use Carp;
  7         15  
  7         614  
12 7     7   39 use Digest::MD5 qw(md5_hex);
  7         12  
  7         391  
13 7     7   14898 use Math::GMPz qw(Rmpz_get_str);
  0            
  0            
14             use Scalar::Util qw(blessed);
15              
16             sub encode_base58 {
17             my ($int, $alphabet, $len) = @_;
18              
19             my $base58 = blessed($int) && $int->isa('Math::GMPz') ?
20             Rmpz_get_str($int, 58) :
21             Rmpz_get_str(Math::GMPz->new($int), 58);
22              
23             if ($len && $len =~ m|\A[0-9]+\Z|) {
24             $base58 = sprintf("%0${len}s",$base58);
25             }
26              
27             $alphabet && lc $alphabet eq 'gmp' ?
28             $base58 :
29             base58_from_to($base58,'gmp',$alphabet||'flickr');
30             }
31              
32             sub decode_base58 {
33             my ($base58, $alphabet) = @_;
34              
35             unless ($alphabet && lc $alphabet eq 'gmp') {
36             $base58 = base58_from_to($base58,$alphabet||'flickr','gmp');
37             }
38              
39             Math::GMPz->new($base58, 58);
40             }
41              
42             sub base58_from_to {
43             my ($base58, $from_alphabet, $to_alphabet) = @_;
44              
45             my $alphabets = {
46             bitcoin => '123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz',
47             flickr => '123456789abcdefghijkmnopqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ',
48             gmp => '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuv'
49             };
50              
51             $from_alphabet = lc($from_alphabet||'flickr');
52             $to_alphabet = lc($to_alphabet ||'flickr');
53              
54             return $base58 if $from_alphabet eq $to_alphabet;
55              
56             my $from_digits = $alphabets->{$from_alphabet}
57             or croak("Encode::Base58::GMP::from_to called with invalid from_alphabet [$from_alphabet]");
58             my $to_digits = $alphabets->{$to_alphabet}
59             or croak("Encode::Base58::GMP::from_to called with invalid to_alphabet [$to_alphabet]");
60              
61             if ($from_alphabet eq 'gmp') {
62             if ($to_alphabet eq 'flickr') {
63             $base58 =~ y|0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuv|123456789abcdefghijkmnopqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ|;
64             } else {
65             $base58 =~ y|0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuv|123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz|;
66             }
67             } elsif ($from_alphabet eq 'flickr') {
68             if ($to_alphabet eq 'gmp') {
69             $base58 =~ y|123456789abcdefghijkmnopqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ|0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuv|;
70             } else {
71             $base58 =~ y|123456789abcdefghijkmnopqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ|123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz|;
72             }
73             } else {
74             if ($to_alphabet eq 'gmp') {
75             $base58 =~ y|123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz|0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuv|;
76             } else {
77             $base58 =~ y|123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz|123456789abcdefghijkmnopqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ|;
78             }
79             }
80             return $base58;
81             }
82              
83             sub base58_gmp_to_flickr {
84             return base58_from_to(shift||'','gmp','flickr');
85             }
86              
87             sub base58_flickr_to_gmp {
88             return base58_from_to(shift||'','flickr','gmp');
89             }
90              
91             sub md5_base58 {
92             encode_base58('0x'.md5_hex(shift), shift, 22);
93             }
94              
95             1;
96              
97             # ABSTRACT: High speed Base58 encoding using GMP with BigInt and MD5 support
98              
99             =head1 NAME
100              
101             Encode::Base58::GMP - High speed Base58 encoding using GMP with BigInt and MD5 support
102              
103             For version 1.0 upgrades, please read the INCOMPATIBLE CHANGES section below.
104              
105             =head1 SYNOPSIS
106              
107             use Encode::Base58::GMP;
108              
109             # Encode Int as Base58
110             encode_base58(12345); # => 4ER string
111             encode_base58('0x3039'); # => 4ER string
112             encode_base58(Math::GMPz->new('0x3039')); # => 4ER string
113              
114             # Encode Int as Base58 using GMP alphabet
115             encode_base58(12345,'bitcoin'); # => 4fr string
116             encode_base58(12345,'gmp'); # => 3cn string
117              
118             # Decode Base58 as Math::GMPz Int
119             decode_base58('4ER'); # => 12345 Math::GMPz object
120             int decode_base58('4ER'); # => 12345 integer
121              
122             # Decode Base58 as Math::GMPz Int using GMP alphabet
123             decode_base58('4fr','bitcoin'); # => 12345 Math::GMPz object
124             decode_base58('3cn','gmp'); # => 12345 Math::GMPz object
125              
126             # MD5 Base58 Digest
127             md5_base58('foo@bar.com'); # => w6fdCRXnUXyz7EtDn5TgN9
128              
129             # Convert between alphabets for Bitcoin, Flickr and GMP
130             base58_from_to('123456789abcdefghijk','flickr','gmp') # => 0123456789ABCDEFGHIJ
131             base58_from_to('0123456789ABCDEFGHIJ','gmp','flickr') # => 123456789abcdefghijk
132              
133             # Convert between Flickr and GMP - Deprecated
134             base58_flickr_to_gmp('123456789abcdefghijk') # => 0123456789ABCDEFGHIJ
135             base58_gmp_to_flickr('0123456789ABCDEFGHIJ') # => 123456789abcdefghijk
136              
137             =head1 DESCRIPTION
138              
139             Encode::Base58::GMP is a Base58 encoder/decoder implementation using the GNU
140             Multiple Precision Arithmetic Library (GMP) with transcoding between
141             Flickr, Bitcoin and GMP Base58 implementations. The Flickr alphabet is the
142             default and used when no alphabet is provided.
143              
144             Flickr Alphabet: [0-9a-zA-Z] excluding [0OIl] to improve human readability
145              
146             Bitcoin Alphabet: [0-9A-Za-z] excluding [0OIl] to improve human readability
147              
148             GMP Alphabet: [0-9A-Za-v]
149              
150             The encode_base58, decode_base58 and md5_base58 methods support an alphabet
151             parameter which can be set to the supported alphabets ['bitcoin', 'flickr',
152             'gmp'] to indicate the value to be encoded or decoded.
153              
154             =head2 Requirements
155              
156             This module requires GMP 4.2.0 and above. Prior versions are limited to Base36.
157              
158             Perl 5.8.9 or above is required to ensure proper bigint handling. If you are not
159             using bigint numbers, it may be possible to skip the bigint tests and do a force
160             install; however, lower Perl versions are not supported.
161              
162             =head1 FUNCTIONS
163              
164             =head2 encode_base58 ( $number [, $alphabet ] )
165              
166             This routine encodes a $number in Base58. $number can be a Math::GMPz object
167             or a binary, octal, decimal or hexidecimal number. Binary, octal and hexidecimal
168             string literals must be prefixed with 0[Bb]/0/0[Xx] respectively. The Flickr
169             alphabet is used unless $alphabet is set to 'gmp'.
170              
171             =head2 decode_base58 ( $base58 [, $alphabet ] )
172              
173             This routine decodes a Base58 value and returns a Math::GMPz object. Use int
174             on the return value to convert the Math::GMPz object to an integer.
175             The Flickr alphabet is used unless $alphabet is set to 'gmp'.
176              
177             =head2 base58_from_to( $base58, $from_alphabet, $to_alphabet )
178              
179             This routine encodes a Base58 string from one encoding to another encoding.
180             This routing is not exported by default.
181              
182             =head2 base58_flickr_to_gmp( $base58_as_flickr )
183              
184             This routine converts a Flickr Base58 string to a GMP Base58 string. This
185             routine is not exported by default.
186              
187             =head2 base58_gmp_to_flickr( $base58_as_gmp )
188              
189             This routine converts a GMP Base58 string to a Flickr Base58 string. This
190             routine is not exported by default.
191              
192             =head2 md5_base58( $data [, $alphabet ] )
193              
194             This routine returns a MD5 digest in Base58. This routine is not exported
195             by default.
196              
197             =head1 CHANGES
198              
199             =item 1.00 April 30, 2013
200              
201             Add Bitcoin alphabet support.
202              
203             Add zero-padding for md5_base58. This is an incompatible change from version
204             0.09.
205              
206             =head1 INCOMPATIBLE CHANGES
207              
208             =item 1.00 April 30, 2013
209              
210             md5_base58 is now zero-padded to provide a fixed-length Base58 string. Prior
211             versions were not padding with leading zero values.
212              
213             =head1 SEE ALSO
214              
215             L, L, L, L
216              
217             L
218              
219             L (Base58 using GMP in Ruby)
220              
221             L (Base62 using GMP in PHP)
222              
223             =head1 AUTHOR
224              
225             John Wang , L
226              
227             =head1 COPYRIGHT AND LICENSE (The MIT License)
228              
229             Copyright (c) 2011-2013 John Wang
230              
231             Permission is hereby granted, free of charge, to any person obtaining
232             a copy of this software and associated documentation files (the
233             "Software"), to deal in the Software without restriction, including
234             without limitation the rights to use, copy, modify, merge, publish,
235             distribute, sublicense, and/or sell copies of the Software, and to
236             permit persons to whom the Software is furnished to do so, subject to
237             the following conditions:
238              
239             The above copyright notice and this permission notice shall be
240             included in all copies or substantial portions of the Software.
241              
242             THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
243             EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
244             MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
245             NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
246             LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
247             OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
248             WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
249              
250             =cut