File Coverage

blib/lib/Vigil/Token.pm
Criterion Covered Total %
statement 42 42 100.0
branch 1 2 50.0
condition n/a
subroutine 12 12 100.0
pod 2 4 50.0
total 57 60 95.0


line stmt bran cond sub pod time code
1             package Vigil::Token;
2            
3 2     2   498640 use strict;
  2         6  
  2         85  
4 2     2   18 use warnings;
  2         4  
  2         136  
5 2     2   93 use 5.010;
  2         8  
6 2     2   1203 use MIME::Base64 qw(encode_base64);
  2         1919  
  2         188  
7 2     2   1728 use Bytes::Random::Secure qw(random_bytes);
  2         24528  
  2         161  
8 2     2   4288 use Math::BigInt;
  2         126329  
  2         12  
9            
10             our $VERSION = '2.0.0';
11            
12 1     1 0 185555 sub new { bless {}, shift }
13            
14             #Token of digits only
15             sub otp {
16 1     1 1 392 my ($self) = @_;
17            
18 1         2 my $min = 100_000;
19 1         11 my $max = 999_999;
20 1         3 my $range = $max - $min + 1;
21            
22 1         3 my $num;
23 1         2 do {
24 1         7 my $bytes = random_bytes(4); # 32-bit random
25 1         61 $num = unpack("N", $bytes); # big-endian 32-bit integer
26             } while ($num >= int(2**32 / $range) * $range); # rejection sampling
27            
28 1         4 return $num % $range + $min;
29             }
30            
31             sub custom_token {
32 2     2 1 13 my ($self, $length) = @_;
33 2 50       8 die "custom_token requires a positive length" unless $length > 0;
34             # Compute bytes needed to get at least $length Base64 chars
35 2         8 my $num_bytes = int(($length * 6 + 7) / 8); # ceil(length*6/8)
36 2         13 my $bytes = random_bytes($num_bytes);
37 2         1102 my $token = encode_base64($bytes, '');
38 2         7 $token =~ tr[+/][-_]; # Base64URL
39 2         7 $token =~ s/=+$//; # remove padding
40 2         10 return substr($token, 0, $length); # exact length
41             }
42            
43             use overload
44 2         43 '&{}' => \&as_coderef,
45 2     2   80254 fallback => 1;
  2         6  
46            
47             sub as_coderef {
48 1     1 0 723 my ($self) = @_;
49             return sub {
50 1     1   3 my @args = @_;
51 1         5 return $self->custom_token(@args);
52 1         9 };
53             }
54            
55             1;
56            
57             __END__