File Coverage

blib/lib/Crypt/RSA/Primitives.pm
Criterion Covered Total %
statement 64 64 100.0
branch 14 24 58.3
condition 3 6 50.0
subroutine 11 11 100.0
pod 1 5 20.0
total 93 110 84.5


line stmt bran cond sub pod time code
1             package Crypt::RSA::Primitives;
2 4     4   617 use strict;
  4         8  
  4         105  
3 4     4   17 use warnings;
  4         7  
  4         118  
4              
5             ## Crypt::RSA::Primitives -- Cryptography and encoding primitives
6             ## used by Crypt::RSA.
7             ##
8             ## Copyright (c) 2001, Vipul Ved Prakash. All rights reserved.
9             ## This code is free software; you can redistribute it and/or modify
10             ## it under the same terms as Perl itself.
11              
12 4     4   17 use base 'Crypt::RSA::Errorhandler';
  4         7  
  4         291  
13 4     4   2004 use Crypt::RSA::Debug qw(debug);
  4         9  
  4         225  
14 4     4   21 use Math::BigInt try => 'GMP, Pari';
  4         7  
  4         29  
15 4     4   4627 use Carp;
  4         8  
  4         3087  
16              
17             sub new {
18 5     5 1 607 return bless {}, shift;
19             }
20              
21              
22             sub core_encrypt {
23              
24             # procedure:
25             # c = (m ** e) mod n
26              
27 8     8 0 31 my ($self, %params) = @_;
28 8         26 my $key = $params{Key};
29 8 50       49 $self->error ("Bad key.", \%params, $key) unless $key->check();
30 8 50       31 my $plaintext = (defined $params{Message}) ? $params{Message} : $params{Plaintext};
31 8 100       44 $plaintext = Math::BigInt->new("$plaintext") if ref($plaintext) ne 'Math::BigInt';
32 8         73 debug ("pt == $plaintext");
33              
34 8         47 my $e = $key->e;
35 8         41 my $n = $key->n;
36 8 50       39 return $self->error ("Numeric representation of plaintext is out of bound.",
37             \$plaintext, $key, \%params) if $plaintext > $n;
38 8         417 my $c = $plaintext->bmodpow($e, $n);
39 8         232898 debug ("ct == $c");
40 8         23 $n = undef;
41 8         18 $e = undef;
42 8         68 return $c;
43             }
44              
45              
46             sub core_decrypt {
47              
48             # procedure:
49             # p = (c ** d) mod n
50              
51 8     8 0 519 my ($self, %params) = @_;
52 8         23 my $key = $params{Key};
53 8 50       49 $self->error ("Bad key.") unless $key->check();
54              
55 8 50       31 my $cyphertext = defined $params{Cyphertext} ? $params{Cyphertext} : $params{Ciphertext};
56 8 50       36 $cyphertext = Math::BigInt->new("$cyphertext") if ref($cyphertext) ne 'Math::BigInt';
57 8         47 my $n = $key->n;
58 8         48 my $d = $key->d;
59 8 50       39 return $self->error ("Decryption error.") if $cyphertext > $n;
60              
61 8         386 my $pt;
62 8 100 66     49 if ($key->p && $key->q) {
63             # Garner's CRT algorithm
64 1         51 my $p = $key->p;
65 1         6 my $q = $key->q;
66 1 50       5 $key->u ($p->copy->bmodinv($q)) unless defined $key->u;
67 1 50       6 $key->dp($d % ($p-1) ) unless defined $key->dp;
68 1 50       5 $key->dq($d % ($q-1) ) unless defined $key->dq;
69 1         5 my $u = $key->u;
70 1         4 my $dp = $key->dp;
71 1         5 my $dq = $key->dq;
72 1         4 my $p2 = ($cyphertext % $p)->bmodpow($dp, $p);
73 1         298 my $q2 = ($cyphertext % $q)->bmodpow($dq, $q);
74 1         300 $pt = $p2 + ($p * ((($q2 - $p2) * $u) % $q));
75             }
76             else {
77 7         40 $pt = $cyphertext->copy->bmodpow($d, $n);
78             }
79              
80 8         10114888 debug ("ct == $cyphertext");
81 8         37 debug ("pt == $pt");
82 8         89 return $pt;
83             }
84              
85              
86             sub core_sign {
87              
88 5     5 0 17 my ($self, %params) = @_;
89 5   33     23 $params{Cyphertext} = $params{Message} || $params{Plaintext};
90 5         165 return $self->core_decrypt (%params);
91              
92             }
93              
94              
95             sub core_verify {
96              
97 5     5 0 22 my ($self, %params) = @_;
98 5         15 $params{Plaintext} = $params{Signature};
99 5         34 return $self->core_encrypt (%params);
100              
101             }
102              
103              
104             1;
105              
106             =head1 NAME
107              
108             Crypt::RSA::Primitives - RSA encryption, decryption, signature and verification primitives.
109              
110             =head1 SYNOPSIS
111              
112             my $prim = new Crypt::RSA::Primitives;
113             my $ctxt = $prim->core_encrypt (Key => $key, Plaintext => $string);
114             my $ptxt = $prim->core_decrypt (Key => $key, Cyphertext => $ctxt);
115             my $sign = $prim->core_sign (Key => $key, Message => $string);
116             my $vrfy = $prim->core_verify (Key => $key, Signature => $sig);
117              
118             =head1 DESCRIPTION
119              
120             This module implements RSA encryption, decryption, signature and
121             verfication primitives. These primitives should only be used in the
122             context of an encryption or signing scheme. See Crypt::RSA::ES::OAEP(3),
123             and Crypt::RSA::SS::PSS(3) for the implementation of two such schemes.
124              
125             =head1 ERROR HANDLING
126              
127             See B in Crypt::RSA(3) manpage.
128              
129             =head1 AUTHOR
130              
131             Vipul Ved Prakash, Email@vipul.netE
132              
133             =head1 SEE ALSO
134              
135             Crypt::RSA(3), Crypt::RSA::Key(3), Crypt::RSA::ES::OAEP(3),
136             Crypt::RSA::SS::PSS(3)
137              
138             =cut
139              
140