File Coverage

blib/lib/Catalyst/Plugin/EncryptID.pm
Criterion Covered Total %
statement 53 53 100.0
branch 12 20 60.0
condition 2 4 50.0
subroutine 10 10 100.0
pod 3 3 100.0
total 80 90 88.8


line stmt bran cond sub pod time code
1             package Catalyst::Plugin::EncryptID;
2              
3 2     2   726722 use 5.006;
  2         5  
4 2     2   6 use strict;
  2         3  
  2         44  
5 2     2   7 use warnings FATAL => 'all';
  2         4  
  2         74  
6              
7 2     2   834 use Crypt::Blowfish;
  2         1455  
  2         896  
8              
9             =head1 NAME
10              
11             Catalyst::Plugin::EncryptID - Obfuscate IDs/string in URLs
12              
13             =head1 VERSION
14              
15             Version 0.01
16              
17             =cut
18              
19             our $VERSION = '0.01';
20              
21             =head1 DESCRIPTION
22              
23             This module makes easy to obfuscate internal IDs when using them in a URL given to users.
24             Instead of seeing L<http://example.com/item/42>
25             users will see L<http://example.com/item/c98ea08a8e8ad715> .
26             This will prevent nosy users from trying to iterate all items based on a simple ID in the URL.
27              
28             =head1 CONFIGURATION
29              
30             Configuration requires a secret key at a minimum.
31              
32             Or set the secret key at run time, with:
33             BEGIN {
34             TestApp->config(
35             name => 'TestApp',
36             EncryptID => {
37             secret => 'abc123xyz',
38             padding_character => '!'
39             }
40             );
41             }
42              
43             =cut
44              
45             sub _padding_character {
46 9     9   10 my ( $c ) = @_;
47 9         48 my $config = $c->config->{EncryptID};
48 9   50     541 return $config->{padding_character} || '!'
49             }
50              
51             sub _secret {
52 14     14   17 my ( $c ) = @_;
53 14         27 my $config = $c->config->{EncryptID};
54 14   50     635 my $secret = $config->{secret} || ':-) - :-)';
55 14 50       27 die "Key must be 8 byte long" if length($secret) < 8;
56 14         20 return $secret;
57             }
58              
59             sub _cipher {
60 14     14   15 my ( $c ) = @_;
61 14         28 my $secret = _secret($c);
62 14         66 return Crypt::Blowfish->new($secret);
63             }
64              
65             =head1 SYNOPSIS
66              
67             Quick summary of what the module does.
68              
69             Perhaps a little code snippet.
70              
71             use Catalyst::Plugin::EncryptID;
72              
73             my $foo = Catalyst::Plugin::EncryptID->new();
74             ...
75              
76             =head1 EXPORT
77              
78             A list of functions that can be exported. You can delete this section
79             if you don't export anything, such as for a purely object-oriented module.
80              
81             =head1 SUBROUTINES/METHODS
82              
83             =head2 encrypt_data
84              
85             C<encrypt_data(ID [,PREFIX])> - Encrypt the given ID, returns the encoded hash value.
86             If "PREFIX" is given, it will be added to the ID before encoding.
87             It can be used when decoding to verify the decoded value is valid.
88              
89             =cut
90              
91             sub encrypt_data {
92 5     5 1 388370 my( $c, $text, $prefix ) = @_;
93              
94 5 50       21 warn "Missing Clear text ID parameter" unless defined $text;
95 5 50       12 return unless defined $text;
96              
97             ## Prefix is optional, can be undef
98 5 50       12 $text = $prefix . $text if defined $prefix;
99              
100 5         7 my $min_length = 8;
101 5         8 my $ciphertext_hash = '';
102              
103             #encode an empty string
104 5 50       18 $text = _padding_character($c) x $min_length if length($text) < 1;
105              
106 5         16 while ( length($text) > 0 ) {
107 7         26 my $sub_text = substr($text,0,$min_length,'');
108 7 100       17 if ( length($sub_text) < 8 ) {
109 4         14 my $left = $min_length - length($sub_text);
110 4         11 $sub_text = ( _padding_character($c) x ($left % $min_length) ). $sub_text;
111             };
112              
113 7         13 my $ciphertext = _cipher($c)->encrypt($sub_text);
114 7         566 $ciphertext_hash .= unpack('H16', $ciphertext ) ;
115             }
116              
117 5         15 return $ciphertext_hash;
118             }
119              
120             =head2 decrypt_data
121              
122             C<decrypt_data(ID)> - Decrypt the given ID, returns the original (text) ID value.
123              
124             =cut
125              
126             sub decrypt_data {
127 5     5 1 78992 my( $c, $encrypted_hash ) = @_;
128              
129 5 50       16 return unless is_valid_encrypt_hash( $c, $encrypted_hash );
130              
131 5         17 my $padding_character = _padding_character($c);
132 5         10 my $ciphertext = '';
133              
134 5         17 while ( length($encrypted_hash) > 0 ) {
135 7         26 my $sub_text = substr($encrypted_hash,0,16,'');
136 7         31 my $cipherhash = pack('H16', $sub_text );
137 7         12 my $text = _cipher($c)->decrypt($cipherhash);
138              
139 7         584 $text =~ s/^$padding_character+//;
140 7         21 $ciphertext .= $text;
141             };
142 5         13 return $ciphertext
143             }
144              
145             =head2 is_valid_encrypt_hash
146              
147             C<is_valid_encrypt_hash(HASH)> - Return true if given encrypt has is valid
148              
149             =cut
150              
151             sub is_valid_encrypt_hash {
152 7     7 1 32597 my( $c, $encrypted_hash ) = @_;
153 7 50       38 return 0 unless length($encrypted_hash);
154 7 100       51 return 0 unless length($encrypted_hash)%16 == 0;
155 6 50       34 return 0 unless $encrypted_hash =~ /^[0-9A-F]+$/i;
156 6         17 return 1;
157             }
158              
159             =head1 AUTHOR
160              
161             Rakesh Kumar Shardiwal, C<< <rakesh.shardiwal at gmail.com> >>
162              
163             =head1 BUGS
164              
165             Please report any bugs or feature requests to C<bug-catalyst-plugin-encryptid at rt.cpan.org>, or through
166             the web interface at L<http://rt.cpan.org/NoAuth/ReportBug.html?Queue=Catalyst-Plugin-EncryptID>. I will be notified, and then you'll
167             automatically be notified of progress on your bug as I make changes.
168              
169              
170              
171              
172             =head1 SUPPORT
173              
174             You can find documentation for this module with the perldoc command.
175              
176             perldoc Catalyst::Plugin::EncryptID
177              
178              
179             You can also look for information at:
180              
181             =over 4
182              
183             =item * RT: CPAN's request tracker (report bugs here)
184              
185             L<http://rt.cpan.org/NoAuth/Bugs.html?Dist=Catalyst-Plugin-EncryptID>
186              
187             =item * AnnoCPAN: Annotated CPAN documentation
188              
189             L<http://annocpan.org/dist/Catalyst-Plugin-EncryptID>
190              
191             =item * CPAN Ratings
192              
193             L<http://cpanratings.perl.org/d/Catalyst-Plugin-EncryptID>
194              
195             =item * Search CPAN
196              
197             L<http://search.cpan.org/dist/Catalyst-Plugin-EncryptID/>
198              
199             =back
200              
201              
202             =head1 ACKNOWLEDGEMENTS
203              
204              
205             =head1 LICENSE AND COPYRIGHT
206              
207             Copyright 2016 Rakesh Kumar Shardiwal.
208              
209             This program is free software; you can redistribute it and/or modify it
210             under the terms of the the Artistic License (2.0). You may obtain a
211             copy of the full license at:
212              
213             L<http://www.perlfoundation.org/artistic_license_2_0>
214              
215             Any use, modification, and distribution of the Standard or Modified
216             Versions is governed by this Artistic License. By using, modifying or
217             distributing the Package, you accept this license. Do not use, modify,
218             or distribute the Package, if you do not accept this license.
219              
220             If your Modified Version has been derived from a Modified Version made
221             by someone other than you, you are nevertheless required to ensure that
222             your Modified Version complies with the requirements of this license.
223              
224             This license does not grant you the right to use any trademark, service
225             mark, tradename, or logo of the Copyright Holder.
226              
227             This license includes the non-exclusive, worldwide, free-of-charge
228             patent license to make, have made, use, offer to sell, sell, import and
229             otherwise transfer the Package with respect to any patent claims
230             licensable by the Copyright Holder that are necessarily infringed by the
231             Package. If you institute patent litigation (including a cross-claim or
232             counterclaim) against any party alleging that the Package constitutes
233             direct or contributory patent infringement, then this Artistic License
234             to you shall terminate on the date that such litigation is filed.
235              
236             Disclaimer of Warranty: THE PACKAGE IS PROVIDED BY THE COPYRIGHT HOLDER
237             AND CONTRIBUTORS "AS IS' AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES.
238             THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
239             PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED TO THE EXTENT PERMITTED BY
240             YOUR LOCAL LAW. UNLESS REQUIRED BY LAW, NO COPYRIGHT HOLDER OR
241             CONTRIBUTOR WILL BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, OR
242             CONSEQUENTIAL DAMAGES ARISING IN ANY WAY OUT OF THE USE OF THE PACKAGE,
243             EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
244              
245              
246             =cut
247              
248             1; # End of Catalyst::Plugin::EncryptID