| line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
|
1
|
|
|
|
|
|
|
# -*-cperl-*- |
|
2
|
|
|
|
|
|
|
# |
|
3
|
|
|
|
|
|
|
# Crypt::RSA::Blind - Blind RSA signatures |
|
4
|
|
|
|
|
|
|
# Copyright (c) Ashish Gulhati |
|
5
|
|
|
|
|
|
|
# |
|
6
|
|
|
|
|
|
|
# $Id: lib/Crypt/RSA/Blind.pm v1.035 Wed Jun 11 13:34:13 EST 2025 $ |
|
7
|
|
|
|
|
|
|
|
|
8
|
3
|
|
|
3
|
|
401024
|
use warnings; |
|
|
3
|
|
|
|
|
7
|
|
|
|
3
|
|
|
|
|
178
|
|
|
9
|
3
|
|
|
3
|
|
28
|
use strict; |
|
|
3
|
|
|
|
|
6
|
|
|
|
3
|
|
|
|
|
70
|
|
|
10
|
|
|
|
|
|
|
|
|
11
|
3
|
|
|
3
|
|
37
|
use v5.26; |
|
|
3
|
|
|
|
|
12
|
|
|
12
|
3
|
|
|
3
|
|
1815
|
use Feature::Compat::Class; |
|
|
3
|
|
|
|
|
1390
|
|
|
|
3
|
|
|
|
|
17
|
|
|
13
|
3
|
|
|
3
|
|
691
|
use feature qw(signatures); |
|
|
3
|
|
|
|
|
5
|
|
|
|
3
|
|
|
|
|
98
|
|
|
14
|
3
|
|
|
3
|
|
13
|
no warnings qw(experimental::signatures); |
|
|
3
|
|
|
|
|
20
|
|
|
|
3
|
|
|
|
|
191
|
|
|
15
|
|
|
|
|
|
|
|
|
16
|
|
|
|
|
|
|
class Crypt::RSA::Blind; |
|
17
|
|
|
|
|
|
|
|
|
18
|
3
|
|
|
3
|
|
17
|
use vars qw( $VERSION ); |
|
|
3
|
|
|
|
|
5
|
|
|
|
3
|
|
|
|
|
389
|
|
|
19
|
|
|
|
|
|
|
our ( $VERSION ) = '$Revision: 1.035 $' =~ /\s+([\d\.]+)/; |
|
20
|
|
|
|
|
|
|
|
|
21
|
3
|
|
|
3
|
|
47
|
use Carp; |
|
|
3
|
|
|
|
|
9
|
|
|
|
3
|
|
|
|
|
214
|
|
|
22
|
3
|
|
|
3
|
|
1996
|
use Carp::Assert; |
|
|
3
|
|
|
|
|
4071
|
|
|
|
3
|
|
|
|
|
20
|
|
|
23
|
3
|
|
|
3
|
|
2209
|
use Crypt::FDH; |
|
|
3
|
|
|
|
|
15664
|
|
|
|
3
|
|
|
|
|
172
|
|
|
24
|
3
|
|
|
3
|
|
2089
|
use Crypt::RSA; |
|
|
3
|
|
|
|
|
431131
|
|
|
|
3
|
|
|
|
|
240
|
|
|
25
|
3
|
|
|
3
|
|
29
|
use Crypt::RSA::DataFormat qw(bitsize i2osp os2ip octet_xor); |
|
|
3
|
|
|
|
|
7
|
|
|
|
3
|
|
|
|
|
217
|
|
|
26
|
3
|
|
|
3
|
|
1774
|
use Crypt::RSA::Primitives; |
|
|
3
|
|
|
|
|
6091
|
|
|
|
3
|
|
|
|
|
150
|
|
|
27
|
3
|
|
|
3
|
|
27
|
use Digest::SHA qw(sha384 sha384_hex); |
|
|
3
|
|
|
|
|
18
|
|
|
|
3
|
|
|
|
|
353
|
|
|
28
|
3
|
|
|
3
|
|
26
|
use Math::Pari qw (Mod ceil component gcd lift); |
|
|
3
|
|
|
|
|
7
|
|
|
|
3
|
|
|
|
|
17
|
|
|
29
|
3
|
|
|
3
|
|
792
|
use Crypt::Random qw(makerandom_itv makerandom); |
|
|
3
|
|
|
|
|
4
|
|
|
|
3
|
|
|
|
|
15046
|
|
|
30
|
|
|
|
|
|
|
|
|
31
|
|
|
|
|
|
|
field $hashsize :param :reader(get_hashsize) = 768; |
|
32
|
|
|
|
|
|
|
field $initsize :param :reader(get_initsize) = 128; |
|
33
|
|
|
|
|
|
|
field $blindsize :param :reader(get_blindsize) = 512; |
|
34
|
|
|
|
|
|
|
field $hash_algorithm :reader(get_hash_algorithm) :param = 'SHA384'; |
|
35
|
|
|
|
|
|
|
field $mgf_hash_algorithm :reader(get_mgf) :param = 'SHA384'; |
|
36
|
|
|
|
|
|
|
field $slen :param :reader(get_slen) = 0; |
|
37
|
|
|
|
|
|
|
field $oldapi :param :reader(get_oldapi) = 1; |
|
38
|
|
|
|
|
|
|
field $rsa :reader(get_rsa) = Crypt::RSA->new; |
|
39
|
|
|
|
|
|
|
field $rsap :reader(get_rsap) = Crypt::RSA::Primitives->new; |
|
40
|
|
|
|
|
|
|
field $requests = {}; |
|
41
|
|
|
|
|
|
|
field $messages = {}; |
|
42
|
|
|
|
|
|
|
|
|
43
|
|
|
|
|
|
|
method set_hashsize ($value) { $hashsize = $value; } |
|
44
|
|
|
|
|
|
|
method set_hash_algorithm ($value) { $hash_algorithm = $value; } |
|
45
|
|
|
|
|
|
|
method set_mgf_hash_algorithm ($value) { $mgf_hash_algorithm = $value; } |
|
46
|
|
|
|
|
|
|
method set_blindsize ($value) { $blindsize = $value; } |
|
47
|
|
|
|
|
|
|
method set_initsize ($value) { $initsize = $value; } |
|
48
|
|
|
|
|
|
|
method set_oldapi ($value) { $oldapi = $value; } |
|
49
|
|
|
|
|
|
|
method set_slen ($value) { $slen = $value; } |
|
50
|
|
|
|
|
|
|
|
|
51
|
|
|
|
|
|
|
method keygen (@args) { |
|
52
|
|
|
|
|
|
|
$self->get_rsa->keygen(@args); |
|
53
|
|
|
|
|
|
|
} |
|
54
|
|
|
|
|
|
|
|
|
55
|
|
|
|
|
|
|
method init () { |
|
56
|
|
|
|
|
|
|
makerandom( Size => $self->get_initsize, Strength => 1, Uniform => 1 ); |
|
57
|
|
|
|
|
|
|
} |
|
58
|
|
|
|
|
|
|
|
|
59
|
|
|
|
|
|
|
# RSABSSA methods |
|
60
|
|
|
|
|
|
|
|
|
61
|
|
|
|
|
|
|
method blind ($arg_ref) { |
|
62
|
|
|
|
|
|
|
my $n = $arg_ref->{PublicKey}->n; |
|
63
|
|
|
|
|
|
|
my $kbits = bitsize($n); |
|
64
|
|
|
|
|
|
|
my $klen = ceil($kbits/8); |
|
65
|
|
|
|
|
|
|
my $encoded_msg = $self->EMSA_PSS_ENCODE($kbits, @$arg_ref{qw(Message sLen Salt)}); |
|
66
|
|
|
|
|
|
|
my $m = os2ip($encoded_msg); |
|
67
|
|
|
|
|
|
|
|
|
68
|
|
|
|
|
|
|
croak("Invalid input") unless is_coprime($m, $n); |
|
69
|
|
|
|
|
|
|
|
|
70
|
|
|
|
|
|
|
my $r; my $r_inv; |
|
71
|
|
|
|
|
|
|
if ($arg_ref->{R_inv}) { # for test vector verification |
|
72
|
|
|
|
|
|
|
$r_inv = $arg_ref->{R_inv}; |
|
73
|
|
|
|
|
|
|
$r = mod_inverse($r_inv, $n); |
|
74
|
|
|
|
|
|
|
} |
|
75
|
|
|
|
|
|
|
else { |
|
76
|
|
|
|
|
|
|
while (!$r_inv) { |
|
77
|
|
|
|
|
|
|
$r = makerandom_itv( Size => 4096, Lower => 1, Upper => $n, Strength => 1, Uniform => 1 ); |
|
78
|
|
|
|
|
|
|
# Check that blinding factor is invertible mod n |
|
79
|
|
|
|
|
|
|
$r_inv = mod_inverse($r, $n); |
|
80
|
|
|
|
|
|
|
} |
|
81
|
|
|
|
|
|
|
} |
|
82
|
|
|
|
|
|
|
$self->_request($arg_ref->{Init} => $r_inv, $arg_ref->{Message}) if $arg_ref->{Init}; |
|
83
|
|
|
|
|
|
|
my $x = RSAVP1($arg_ref->{PublicKey}, $r); |
|
84
|
|
|
|
|
|
|
my $z = ($m * $x) % $n; |
|
85
|
|
|
|
|
|
|
my $blinded_msg = i2osp($z, $klen); |
|
86
|
|
|
|
|
|
|
my $inv = i2osp($r_inv, $klen); |
|
87
|
|
|
|
|
|
|
my $msglen = length($blinded_msg); |
|
88
|
|
|
|
|
|
|
croak("Unexpected message size (msglen: $msglen, klen: $klen") if $msglen != $klen; |
|
89
|
|
|
|
|
|
|
return ($blinded_msg, $inv); |
|
90
|
|
|
|
|
|
|
} |
|
91
|
|
|
|
|
|
|
|
|
92
|
|
|
|
|
|
|
method blind_sign ($arg_ref) { |
|
93
|
|
|
|
|
|
|
my $n = $arg_ref->{SecretKey}->n; |
|
94
|
|
|
|
|
|
|
my $kbits = bitsize($n); |
|
95
|
|
|
|
|
|
|
my $klen = ceil($kbits/8); |
|
96
|
|
|
|
|
|
|
my $inputlen = length($arg_ref->{BlindedMessage}); |
|
97
|
|
|
|
|
|
|
croak("Unexpected input size (inputlen: $inputlen, klen: $klen)") if $inputlen != $klen; |
|
98
|
|
|
|
|
|
|
my $m = os2ip($arg_ref->{BlindedMessage}); |
|
99
|
|
|
|
|
|
|
croak("Invalid message length") if $m >= $n; |
|
100
|
|
|
|
|
|
|
my $s = RSASP1($arg_ref->{SecretKey}, $m); |
|
101
|
|
|
|
|
|
|
if (defined $arg_ref->{PublicKey}) { |
|
102
|
|
|
|
|
|
|
my $mdash = RSAVP1($arg_ref->{PublicKey}, $s); |
|
103
|
|
|
|
|
|
|
croak "Signing failure" unless $m == $mdash; |
|
104
|
|
|
|
|
|
|
} |
|
105
|
|
|
|
|
|
|
my $blind_sig = i2osp($s, $klen); |
|
106
|
|
|
|
|
|
|
} |
|
107
|
|
|
|
|
|
|
|
|
108
|
|
|
|
|
|
|
method finalize ($arg_ref) { |
|
109
|
|
|
|
|
|
|
my $n = $arg_ref->{PublicKey}->n; |
|
110
|
|
|
|
|
|
|
my $kbits = bitsize($n); |
|
111
|
|
|
|
|
|
|
my $klen = ceil($kbits/8); |
|
112
|
|
|
|
|
|
|
my $z = os2ip($arg_ref->{BlindSig}); |
|
113
|
|
|
|
|
|
|
my ($blinding, $message); |
|
114
|
|
|
|
|
|
|
unless ($arg_ref->{Blinding}) { |
|
115
|
|
|
|
|
|
|
my $saved = $self->_request($arg_ref->{Init}); |
|
116
|
|
|
|
|
|
|
$blinding = $self->get_oldapi ? $saved->[0] : $saved; |
|
117
|
|
|
|
|
|
|
$message = $self->get_oldapi ? $saved->[1] : $arg_ref->{Message}; |
|
118
|
|
|
|
|
|
|
} |
|
119
|
|
|
|
|
|
|
croak("Neither Blinding nor valid Init vector provided") unless my $r_inv = $arg_ref->{Blinding} ? os2ip($arg_ref->{Blinding}) : $blinding; |
|
120
|
|
|
|
|
|
|
my $s = ($z * $r_inv) % $n; |
|
121
|
|
|
|
|
|
|
my $sig = i2osp($s, $klen); |
|
122
|
|
|
|
|
|
|
$self->pss_verify( { PublicKey => $arg_ref->{PublicKey}, Signature => $sig, Message => $arg_ref->{Blinding} ? $arg_ref->{Message} : $message, sLen => $arg_ref->{sLen} } ); |
|
123
|
|
|
|
|
|
|
return $sig; |
|
124
|
|
|
|
|
|
|
} |
|
125
|
|
|
|
|
|
|
|
|
126
|
|
|
|
|
|
|
method randomize ($msg) { |
|
127
|
|
|
|
|
|
|
my $random = makerandom(Size => 32 * 8, Strength => 1, Uniform => 1); |
|
128
|
|
|
|
|
|
|
$msg = i2osp($random, 32) . $msg; |
|
129
|
|
|
|
|
|
|
} |
|
130
|
|
|
|
|
|
|
|
|
131
|
|
|
|
|
|
|
method pss_verify ($arg_ref) { |
|
132
|
|
|
|
|
|
|
my $n = $arg_ref->{PublicKey}->n; |
|
133
|
|
|
|
|
|
|
my $kbits = bitsize($n); |
|
134
|
|
|
|
|
|
|
my $klen = ceil($kbits/8); |
|
135
|
|
|
|
|
|
|
# Step 1 |
|
136
|
|
|
|
|
|
|
my $siglen = length($arg_ref->{Signature}); |
|
137
|
|
|
|
|
|
|
croak("Incorrect signature length (siglen: $siglen, klen: $klen") if $siglen != $klen; |
|
138
|
|
|
|
|
|
|
# Step 2a (OS2IP) |
|
139
|
|
|
|
|
|
|
my $signature_int = os2ip($arg_ref->{Signature}); |
|
140
|
|
|
|
|
|
|
# Step 2b (RSAVP1) |
|
141
|
|
|
|
|
|
|
my $em_int = RSAVP1($arg_ref->{PublicKey}, $signature_int); |
|
142
|
|
|
|
|
|
|
# Step 2c (I2OSP) |
|
143
|
|
|
|
|
|
|
my $emlen = ceil(($kbits - 1)/8); |
|
144
|
|
|
|
|
|
|
my $em = i2osp($em_int, $emlen); |
|
145
|
|
|
|
|
|
|
my $hash = Digest::SHA->new($self->get_hash_algorithm); |
|
146
|
|
|
|
|
|
|
$hash->add($arg_ref->{Message}); |
|
147
|
30
|
|
|
30
|
|
132
|
$self->EMSA_PSS_VERIFY($hash, $em, $kbits-1, sub { MGF1(@_) }, $arg_ref->{sLen}); |
|
148
|
|
|
|
|
|
|
return 1 |
|
149
|
|
|
|
|
|
|
} |
|
150
|
|
|
|
|
|
|
|
|
151
|
|
|
|
|
|
|
method EMSA_PSS_ENCODE ($kbits, $msg, $slen, $salt) { |
|
152
|
|
|
|
|
|
|
my $hash = Digest::SHA->new($self->get_hash_algorithm); |
|
153
|
|
|
|
|
|
|
$hash->add($msg); |
|
154
|
|
|
|
|
|
|
my $m_hash = $hash->hexdigest; |
|
155
|
|
|
|
|
|
|
my $hlen = ceil($hash->hashsize/8); |
|
156
|
|
|
|
|
|
|
|
|
157
|
|
|
|
|
|
|
my $embits = $kbits - 1; |
|
158
|
|
|
|
|
|
|
my $emlen = ceil($embits/8); |
|
159
|
|
|
|
|
|
|
assert($emlen >= $hlen + $slen + 2); |
|
160
|
|
|
|
|
|
|
|
|
161
|
|
|
|
|
|
|
my $lmask = 0; |
|
162
|
|
|
|
|
|
|
for (0..(8 * $emlen - $embits - 1)) { |
|
163
|
|
|
|
|
|
|
$lmask = $lmask >> 1 | 0x80; |
|
164
|
|
|
|
|
|
|
} |
|
165
|
|
|
|
|
|
|
|
|
166
|
|
|
|
|
|
|
unless ($salt) { |
|
167
|
|
|
|
|
|
|
$salt = ''; |
|
168
|
|
|
|
|
|
|
$salt = uc(unpack ('H*',i2osp(makerandom(Size => $slen * 8, Strength => 1, Uniform => 1), $slen))) if $slen; |
|
169
|
|
|
|
|
|
|
1 } |
|
170
|
|
|
|
|
|
|
|
|
171
|
|
|
|
|
|
|
my $m_prime = chr(0) x 8 . i2osp(Math::Pari::_hex_cvt('0x' . $m_hash . $salt), $hlen + $slen); |
|
172
|
|
|
|
|
|
|
$hash = Digest::SHA->new($self->get_hash_algorithm); |
|
173
|
|
|
|
|
|
|
$hash->add($m_prime); |
|
174
|
|
|
|
|
|
|
my $h = $hash->digest; |
|
175
|
|
|
|
|
|
|
my $ps = chr(0) x ($emlen - $slen - $hlen - 2); |
|
176
|
|
|
|
|
|
|
my $db = $ps . chr(0x01); $db .= i2osp(Math::Pari::_hex_cvt('0x' . $salt), $slen) if $slen; |
|
177
|
|
|
|
|
|
|
my $dbMask = MGF1($h, $emlen - $hlen - 1); |
|
178
|
|
|
|
|
|
|
my $masked_db = octet_xor($db, $dbMask); |
|
179
|
|
|
|
|
|
|
$masked_db = chr(os2ip(substr($masked_db, 0, 1)) & (~$lmask)) . substr($masked_db, 1); |
|
180
|
|
|
|
|
|
|
my $encoded_msg = $masked_db . $h . chr(0xBC); |
|
181
|
|
|
|
|
|
|
} |
|
182
|
|
|
|
|
|
|
|
|
183
|
|
|
|
|
|
|
method EMSA_PSS_VERIFY ($mhash, $em, $embits, $mgf, $slen) { |
|
184
|
|
|
|
|
|
|
my $hashlen = ceil($mhash->hashsize / 8); |
|
185
|
|
|
|
|
|
|
my $emlen = ceil($embits/8); |
|
186
|
|
|
|
|
|
|
my $lmask = 0; |
|
187
|
|
|
|
|
|
|
for (0..(8*$emlen-$embits-1)) { |
|
188
|
|
|
|
|
|
|
$lmask = $lmask >> 1 | 0x80 |
|
189
|
|
|
|
|
|
|
} |
|
190
|
|
|
|
|
|
|
# Step 1 and 2 already done |
|
191
|
|
|
|
|
|
|
# Step 3 |
|
192
|
|
|
|
|
|
|
croak("Incorrect signature at step 3") if ($emlen < $hashlen + $slen + 2); |
|
193
|
|
|
|
|
|
|
# Step 4 |
|
194
|
|
|
|
|
|
|
croak("Incorrect signature at step 4") if ord(substr($em, -1)) != 0xBC; |
|
195
|
|
|
|
|
|
|
# Step 5 |
|
196
|
|
|
|
|
|
|
my $masked_db = substr($em,0,$emlen-$hashlen-1); |
|
197
|
|
|
|
|
|
|
my $h = substr($em,$emlen-$hashlen-1,-1); |
|
198
|
|
|
|
|
|
|
# Step 6 |
|
199
|
|
|
|
|
|
|
croak("Incorrect signature at step 6") if $lmask & ord(substr($em,0,1)); |
|
200
|
|
|
|
|
|
|
# Step 7 |
|
201
|
|
|
|
|
|
|
my $dbmask = &$mgf($h, $emlen-$hashlen-1); |
|
202
|
|
|
|
|
|
|
# Step 8 |
|
203
|
|
|
|
|
|
|
my $db = octet_xor($masked_db, $dbmask); |
|
204
|
|
|
|
|
|
|
# Step 9 |
|
205
|
|
|
|
|
|
|
$db = chr(ord(substr($db,0,1)) & ~$lmask) . substr($db,1); |
|
206
|
|
|
|
|
|
|
# Step 10 |
|
207
|
|
|
|
|
|
|
croak("Incorrect signature at step 10") unless (substr($db, 0, $emlen-$hashlen-$slen-1) eq (chr(0) x ($emlen-$hashlen-$slen-2) . chr(1))); |
|
208
|
|
|
|
|
|
|
# Step 11 |
|
209
|
|
|
|
|
|
|
my $salt = $slen > 0 ? substr($db,-$slen) : ''; |
|
210
|
|
|
|
|
|
|
# Step 12 |
|
211
|
|
|
|
|
|
|
my $m_prime = chr(0) x 8 . $mhash->digest . $salt; |
|
212
|
|
|
|
|
|
|
# Step 13 |
|
213
|
|
|
|
|
|
|
my $hash = Digest::SHA->new($self->get_hash_algorithm); |
|
214
|
|
|
|
|
|
|
$hash->add($m_prime); |
|
215
|
|
|
|
|
|
|
my $hp = $hash->digest; |
|
216
|
|
|
|
|
|
|
# Step 14 |
|
217
|
|
|
|
|
|
|
croak("Incorrect signature at step 14") if $h ne $hp; |
|
218
|
|
|
|
|
|
|
} |
|
219
|
|
|
|
|
|
|
|
|
220
|
|
|
|
|
|
|
# Old-style API methods |
|
221
|
|
|
|
|
|
|
|
|
222
|
|
|
|
|
|
|
method request (%arg) { |
|
223
|
|
|
|
|
|
|
if ($self->get_oldapi) { |
|
224
|
|
|
|
|
|
|
my ($req, $blinding) = $self->blind( { PublicKey => $arg{Key}, sLen => $self->get_slen, %arg } ); |
|
225
|
|
|
|
|
|
|
return os2ip($req); |
|
226
|
|
|
|
|
|
|
} |
|
227
|
|
|
|
|
|
|
$self->_req(%arg); |
|
228
|
|
|
|
|
|
|
} |
|
229
|
|
|
|
|
|
|
|
|
230
|
|
|
|
|
|
|
method sign (%arg) { |
|
231
|
|
|
|
|
|
|
my $klen = ceil(bitsize($arg{Key}->n)/8); |
|
232
|
|
|
|
|
|
|
$self->get_oldapi ? os2ip($self->blind_sign( { SecretKey => $arg{Key}, PublicKey => $arg{PublicKey}, BlindedMessage => i2osp($arg{Message}, $klen) } )) : $self->_sign(%arg); |
|
233
|
|
|
|
|
|
|
} |
|
234
|
|
|
|
|
|
|
|
|
235
|
|
|
|
|
|
|
method unblind (%arg) { |
|
236
|
|
|
|
|
|
|
my $klen = ceil(bitsize($arg{Key}->n)/8); |
|
237
|
|
|
|
|
|
|
$self->get_oldapi ? os2ip($self->finalize( { PublicKey => $arg{Key}, BlindSig => i2osp($arg{Signature}, $klen), sLen => $self->get_slen, %arg } )) : $self->_unblind(%arg); |
|
238
|
|
|
|
|
|
|
} |
|
239
|
|
|
|
|
|
|
|
|
240
|
|
|
|
|
|
|
method verify (%arg) { |
|
241
|
|
|
|
|
|
|
my $klen = ceil(bitsize($arg{Key}->n)/8); |
|
242
|
|
|
|
|
|
|
$self->get_oldapi ? $self->pss_verify( { PublicKey => $arg{Key}, %arg, Signature => i2osp($arg{Signature}, $klen), sLen => $self->get_slen } ) : $self->_verify(%arg); |
|
243
|
|
|
|
|
|
|
} |
|
244
|
|
|
|
|
|
|
|
|
245
|
|
|
|
|
|
|
# Deprecated methods |
|
246
|
|
|
|
|
|
|
|
|
247
|
|
|
|
|
|
|
method _req (%arg) { |
|
248
|
|
|
|
|
|
|
carp('Call to deprecated method: request'); |
|
249
|
|
|
|
|
|
|
my ($invertible, $blinding); |
|
250
|
|
|
|
|
|
|
while (!$invertible) { |
|
251
|
|
|
|
|
|
|
$blinding = makerandom_itv( Size => $self->get_blindsize, Upper => $arg{Key}->n-1, Strength => 1, Uniform => 0 ); |
|
252
|
|
|
|
|
|
|
# Check that blinding is invertible mod n |
|
253
|
|
|
|
|
|
|
$invertible = gcd( $blinding, $arg{Key}->n ); |
|
254
|
|
|
|
|
|
|
$invertible = 0 unless $invertible == 1; |
|
255
|
|
|
|
|
|
|
} |
|
256
|
|
|
|
|
|
|
$self->_request($arg{Init} => $blinding); |
|
257
|
|
|
|
|
|
|
|
|
258
|
|
|
|
|
|
|
my $be = $self->get_rsap->core_encrypt(Key => $arg{Key}, Plaintext => $blinding); |
|
259
|
|
|
|
|
|
|
my $fdh = Math::Pari::_hex_cvt ('0x'.Crypt::FDH::hash(Size => $self->get_hashsize, Message => $arg{Message})); |
|
260
|
|
|
|
|
|
|
component((Mod($fdh,$arg{Key}->n)) * (Mod($be,$arg{Key}->n)), 2); |
|
261
|
|
|
|
|
|
|
} |
|
262
|
|
|
|
|
|
|
|
|
263
|
|
|
|
|
|
|
method _sign (@args) { |
|
264
|
|
|
|
|
|
|
carp('Call to deprecated method: sign'); |
|
265
|
|
|
|
|
|
|
$self->get_rsap->core_sign(@args); |
|
266
|
|
|
|
|
|
|
} |
|
267
|
|
|
|
|
|
|
|
|
268
|
|
|
|
|
|
|
method _unblind (%arg) { |
|
269
|
|
|
|
|
|
|
carp('Call to deprecated method: unblind'); |
|
270
|
|
|
|
|
|
|
my $blinding = $self->_request($arg{Init}); |
|
271
|
|
|
|
|
|
|
component((Mod($arg{Signature},$arg{Key}->n)) / (Mod($blinding,$arg{Key}->n)), 2); |
|
272
|
|
|
|
|
|
|
} |
|
273
|
|
|
|
|
|
|
|
|
274
|
|
|
|
|
|
|
method _verify (%arg) { |
|
275
|
|
|
|
|
|
|
carp('Call to deprecated method: verify'); |
|
276
|
|
|
|
|
|
|
my $pt = $self->get_rsap->core_verify(Key => $arg{Key}, Signature => $arg{Signature}); |
|
277
|
|
|
|
|
|
|
$pt == Math::Pari::_hex_cvt ('0x'.Crypt::FDH::hash(Size => $self->get_hashsize, Message => $arg{Message})); |
|
278
|
|
|
|
|
|
|
} |
|
279
|
|
|
|
|
|
|
|
|
280
|
|
|
|
|
|
|
# Helper methods and functions |
|
281
|
|
|
|
|
|
|
|
|
282
|
|
|
|
|
|
|
method errstr (@args) { |
|
283
|
|
|
|
|
|
|
$self->rsa->errstr(@args); |
|
284
|
|
|
|
|
|
|
} |
|
285
|
|
|
|
|
|
|
|
|
286
|
|
|
|
|
|
|
method _request ($init, $blinding=undef, $message=undef) { # Save / retrieve blinding by init vector |
|
287
|
|
|
|
|
|
|
my $ret; |
|
288
|
|
|
|
|
|
|
if ($blinding) { # Associate blinding with init vector |
|
289
|
|
|
|
|
|
|
$requests->{$init} = $blinding; |
|
290
|
|
|
|
|
|
|
$messages->{$init} = $message if $self->get_oldapi; |
|
291
|
|
|
|
|
|
|
} |
|
292
|
|
|
|
|
|
|
else { # Retrieve blinding associated with init vector |
|
293
|
|
|
|
|
|
|
$ret = $self->get_oldapi ? |
|
294
|
|
|
|
|
|
|
[ $requests->{$init}, $messages->{$init} ] : |
|
295
|
|
|
|
|
|
|
$requests->{$init}; |
|
296
|
|
|
|
|
|
|
delete $requests->{$init}; |
|
297
|
|
|
|
|
|
|
delete $messages->{$init} if $self->get_oldapi; |
|
298
|
|
|
|
|
|
|
} |
|
299
|
|
|
|
|
|
|
return $ret; |
|
300
|
|
|
|
|
|
|
} |
|
301
|
|
|
|
|
|
|
|
|
302
|
48
|
|
|
48
|
0
|
120
|
sub RSAVP1 ($pubkey, $s) { |
|
|
48
|
|
|
|
|
102
|
|
|
|
48
|
|
|
|
|
122
|
|
|
|
48
|
|
|
|
|
101
|
|
|
303
|
48
|
|
|
|
|
645
|
my $e = $pubkey->e; |
|
304
|
48
|
|
|
|
|
2165
|
my $n = $pubkey->n; |
|
305
|
48
|
|
|
|
|
1981
|
my $scopy = $s; my $ncopy = $n; |
|
|
48
|
|
|
|
|
120
|
|
|
306
|
48
|
50
|
33
|
|
|
695
|
croak "Signature representative out of range" unless $scopy < $ncopy and $scopy > 0; |
|
307
|
48
|
|
|
|
|
187
|
my $m = mod_exp($s, $e, $n); |
|
308
|
|
|
|
|
|
|
} |
|
309
|
|
|
|
|
|
|
|
|
310
|
9
|
|
|
9
|
0
|
21
|
sub RSASP1 ($seckey, $m) { |
|
|
9
|
|
|
|
|
20
|
|
|
|
9
|
|
|
|
|
33
|
|
|
|
9
|
|
|
|
|
17
|
|
|
311
|
9
|
|
|
|
|
101
|
my $d = $seckey->d; |
|
312
|
9
|
|
|
|
|
323
|
my $n = $seckey->n; |
|
313
|
9
|
|
|
|
|
156
|
my $mcopy = $m; my $ncopy = $n; |
|
|
9
|
|
|
|
|
22
|
|
|
314
|
9
|
50
|
33
|
|
|
117
|
croak "Message representative out of range" unless $mcopy < $ncopy and $mcopy > 0; |
|
315
|
9
|
|
|
|
|
39
|
my $s = mod_exp($m, $d, $n); |
|
316
|
|
|
|
|
|
|
} |
|
317
|
|
|
|
|
|
|
|
|
318
|
39
|
|
|
39
|
0
|
82
|
sub MGF1 ($seed, $masklen) { |
|
|
39
|
|
|
|
|
87
|
|
|
|
39
|
|
|
|
|
72
|
|
|
|
39
|
|
|
|
|
68
|
|
|
319
|
39
|
|
|
|
|
79
|
my $hlen = 48; |
|
320
|
39
|
|
|
|
|
109
|
my $T = ''; |
|
321
|
39
|
|
|
|
|
558
|
for (0..ceil($masklen/$hlen)-1) { |
|
322
|
206
|
|
|
|
|
573
|
my $c = i2osp($_, 4); |
|
323
|
206
|
|
|
|
|
9826
|
$T = $T . sha384($seed . $c); |
|
324
|
|
|
|
|
|
|
} |
|
325
|
39
|
|
|
|
|
347
|
assert(length($T) >= $masklen); |
|
326
|
39
|
|
|
|
|
665
|
unpack "a$masklen", $T; |
|
327
|
|
|
|
|
|
|
} |
|
328
|
|
|
|
|
|
|
|
|
329
|
|
|
|
|
|
|
sub is_coprime { |
|
330
|
9
|
|
|
9
|
0
|
4001
|
gcd(@_) == 1; |
|
331
|
|
|
|
|
|
|
} |
|
332
|
|
|
|
|
|
|
|
|
333
|
|
|
|
|
|
|
sub mod_inverse { |
|
334
|
9
|
|
|
9
|
0
|
35
|
my($a, $n) = @_; |
|
335
|
9
|
|
|
|
|
56
|
my $m = Mod(1, $n); |
|
336
|
9
|
|
|
|
|
1724
|
lift($m / $a); |
|
337
|
|
|
|
|
|
|
} |
|
338
|
|
|
|
|
|
|
|
|
339
|
|
|
|
|
|
|
sub mod_exp { |
|
340
|
57
|
|
|
57
|
0
|
4222
|
my($a, $exp, $n) = @_; |
|
341
|
57
|
|
|
|
|
379
|
my $m = Mod($a, $n); |
|
342
|
57
|
|
|
|
|
748619
|
lift($m ** $exp); |
|
343
|
|
|
|
|
|
|
} |
|
344
|
|
|
|
|
|
|
|
|
345
|
|
|
|
|
|
|
package Crypt::RSA::Blind::PubKey { |
|
346
|
3
|
|
|
3
|
|
37
|
use Compress::Zlib; |
|
|
3
|
|
|
|
|
5
|
|
|
|
3
|
|
|
|
|
1396
|
|
|
347
|
0
|
|
|
0
|
|
|
sub from_hex ($pubkey) { |
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
348
|
0
|
|
|
|
|
|
Crypt::RSA::Key::Public->new->deserialize(String => [ uncompress(pack('H*',$pubkey)) ]); |
|
349
|
|
|
|
|
|
|
} |
|
350
|
|
|
|
|
|
|
} |
|
351
|
|
|
|
|
|
|
|
|
352
|
|
|
|
|
|
|
package Crypt::RSA::Blind::SecKey { |
|
353
|
3
|
|
|
3
|
|
22
|
use Compress::Zlib; |
|
|
3
|
|
|
|
|
4
|
|
|
|
3
|
|
|
|
|
1278
|
|
|
354
|
0
|
|
|
0
|
|
|
sub from_hex ($seckey) { |
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
355
|
0
|
|
|
|
|
|
Crypt::RSA::Key::Private->new->deserialize(String => [ uncompress(pack('H*',$seckey)) ]); |
|
356
|
|
|
|
|
|
|
} |
|
357
|
|
|
|
|
|
|
} |
|
358
|
|
|
|
|
|
|
|
|
359
|
|
|
|
|
|
|
1; |
|
360
|
|
|
|
|
|
|
|
|
361
|
|
|
|
|
|
|
__END__ |