line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
# -*-cperl-*- |
2
|
|
|
|
|
|
|
# |
3
|
|
|
|
|
|
|
# Crypt::ECDSA::Blind - Blind ECDSA signatures |
4
|
|
|
|
|
|
|
# Copyright (c) 2017 Ashish Gulhati |
5
|
|
|
|
|
|
|
# |
6
|
|
|
|
|
|
|
# $Id: lib/Crypt/ECDSA/Blind.pm v1.014 Sat Jun 10 00:32:47 PDT 2017 $ |
7
|
|
|
|
|
|
|
|
8
|
|
|
|
|
|
|
package Crypt::ECDSA::Blind; |
9
|
|
|
|
|
|
|
|
10
|
2
|
|
|
2
|
|
27573
|
use warnings; |
|
2
|
|
|
|
|
4
|
|
|
2
|
|
|
|
|
61
|
|
11
|
2
|
|
|
2
|
|
10
|
use strict; |
|
2
|
|
|
|
|
4
|
|
|
2
|
|
|
|
|
32
|
|
12
|
2
|
|
|
2
|
|
2311
|
use DBI; |
|
2
|
|
|
|
|
26038
|
|
|
2
|
|
|
|
|
104
|
|
13
|
2
|
|
|
2
|
|
1124
|
use Bytes::Random::Secure; |
|
2
|
|
|
|
|
15019
|
|
|
2
|
|
|
|
|
91
|
|
14
|
2
|
|
|
2
|
|
818
|
use Math::EllipticCurve::Prime; |
|
2
|
|
|
|
|
84817
|
|
|
2
|
|
|
|
|
64
|
|
15
|
2
|
|
|
2
|
|
884
|
use Digest::SHA; |
|
2
|
|
|
|
|
4141
|
|
|
2
|
|
|
|
|
104
|
|
16
|
2
|
|
|
2
|
|
15
|
use vars qw( $VERSION $AUTOLOAD ); |
|
2
|
|
|
|
|
4
|
|
|
2
|
|
|
|
|
3871
|
|
17
|
|
|
|
|
|
|
|
18
|
|
|
|
|
|
|
our ( $VERSION ) = '$Revision: 1.014 $' =~ /\s+([\d\.]+)/; |
19
|
|
|
|
|
|
|
|
20
|
|
|
|
|
|
|
sub new { |
21
|
1
|
|
50
|
1
|
1
|
13
|
my ($class, %arg) = @_; my $dbname = $arg{DB} || '/tmp/ceb.db'; |
|
1
|
|
|
|
|
5
|
|
22
|
1
|
50
|
33
|
|
|
4
|
unlink $dbname if $arg{Clobber} and $dbname ne ':memory:'; |
23
|
1
|
|
|
|
|
8
|
my $db = DBI->connect("dbi:SQLite:dbname=$dbname", undef, undef, {AutoCommit => 1}); |
24
|
1
|
|
|
|
|
8778
|
my @tables = $db->tables('%','%','initkeys','TABLE'); |
25
|
1
|
50
|
|
|
|
756
|
unless ($tables[0]) { |
26
|
1
|
50
|
|
|
|
4
|
if ($arg{Create}) { |
27
|
1
|
50
|
|
|
|
6
|
return undef unless $db->do('CREATE TABLE initkeys ( |
28
|
|
|
|
|
|
|
Rp TEXT PRIMARY KEY, |
29
|
|
|
|
|
|
|
k TEXT NOT NULL, |
30
|
|
|
|
|
|
|
issued int NOT NULL |
31
|
|
|
|
|
|
|
);'); |
32
|
1
|
50
|
|
|
|
308
|
return undef unless $db->do('CREATE INDEX idx_initkeys_Rp ON initkeys(Rp);'); |
33
|
|
|
|
|
|
|
} |
34
|
|
|
|
|
|
|
else { |
35
|
0
|
|
|
|
|
0
|
return undef; |
36
|
|
|
|
|
|
|
} |
37
|
|
|
|
|
|
|
} |
38
|
1
|
|
|
|
|
168
|
@tables = $db->tables('%','%','preinits','TABLE'); |
39
|
1
|
50
|
|
|
|
345
|
unless ($tables[0]) { |
40
|
1
|
50
|
|
|
|
4
|
if ($arg{Create}) { |
41
|
1
|
50
|
|
|
|
4
|
return undef unless $db->do('CREATE TABLE preinits ( |
42
|
|
|
|
|
|
|
Rp TEXT PRIMARY KEY, |
43
|
|
|
|
|
|
|
k TEXT NOT NULL |
44
|
|
|
|
|
|
|
);'); |
45
|
|
|
|
|
|
|
} |
46
|
|
|
|
|
|
|
else { |
47
|
0
|
|
|
|
|
0
|
return undef; |
48
|
|
|
|
|
|
|
} |
49
|
|
|
|
|
|
|
} |
50
|
1
|
|
|
|
|
196
|
bless { debug => 0, |
51
|
|
|
|
|
|
|
db => $db, |
52
|
|
|
|
|
|
|
curve => Math::EllipticCurve::Prime->from_name('secp256k1') |
53
|
|
|
|
|
|
|
}, $class; |
54
|
|
|
|
|
|
|
} |
55
|
|
|
|
|
|
|
|
56
|
|
|
|
|
|
|
sub keygen { # Generate public, private key pair |
57
|
1
|
|
|
1
|
1
|
4651
|
my $self = shift; |
58
|
1
|
|
|
|
|
8
|
my $random = Bytes::Random::Secure->new( Bits => 128 ); |
59
|
1
|
|
|
|
|
107
|
my $d = _makerandom($self->curve->n); |
60
|
1
|
|
|
|
|
7
|
my $Q = $self->curve->g->multiply($d); |
61
|
1
|
|
|
|
|
12322449
|
$self->_diag("keygen(): d: $d, Q: x:" . $Q->x . ', y:' . $Q->y . "\n"); |
62
|
1
|
|
|
|
|
22
|
return ((bless {Q => $Q}, 'Crypt::ECDSA::Blind::PubKey'),(bless {d => $d}, 'Crypt::ECDSA::Blind::SecKey')); |
63
|
|
|
|
|
|
|
} |
64
|
|
|
|
|
|
|
|
65
|
|
|
|
|
|
|
sub preinit { # Create an init vector in advance |
66
|
0
|
|
|
0
|
1
|
0
|
my $self = shift; |
67
|
0
|
|
|
|
|
0
|
my $count = $self->db->selectcol_arrayref("SELECT count() from preinits;")->[0]; |
68
|
0
|
0
|
|
|
|
0
|
return if $count > 20; |
69
|
0
|
|
|
|
|
0
|
my ($k, $Rp, $rp); |
70
|
0
|
|
|
|
|
0
|
until ($rp) { |
71
|
0
|
|
|
|
|
0
|
$k = _makerandom($self->curve->n); |
72
|
0
|
|
|
|
|
0
|
$Rp = $self->curve->g->multiply($k); |
73
|
0
|
|
|
|
|
0
|
$rp = $Rp->x; |
74
|
0
|
|
|
|
|
0
|
$Rp = _compress($Rp); |
75
|
|
|
|
|
|
|
} |
76
|
0
|
|
|
|
|
0
|
$self->db->do("INSERT INTO preinits values ('$Rp','$k');"); |
77
|
|
|
|
|
|
|
} |
78
|
|
|
|
|
|
|
|
79
|
|
|
|
|
|
|
sub init { # Return an init vector |
80
|
2
|
|
|
2
|
1
|
1268
|
my $self = shift; |
81
|
2
|
|
|
|
|
7
|
my ($k, $Rp, $rp) = $self->_getpreinit; |
82
|
2
|
50
|
|
|
|
7
|
unless ($k) { |
83
|
2
|
|
|
|
|
6
|
until ($rp) { |
84
|
2
|
|
|
|
|
13
|
$k = _makerandom($self->curve->n); |
85
|
2
|
|
|
|
|
29
|
$Rp = $self->curve->g->multiply($k); |
86
|
2
|
|
|
|
|
24198370
|
$rp = $Rp->x; |
87
|
2
|
|
|
|
|
15
|
$Rp = _compress($Rp); |
88
|
|
|
|
|
|
|
} |
89
|
2
|
|
|
|
|
426
|
$self->_initkey($Rp => $k); |
90
|
|
|
|
|
|
|
} |
91
|
2
|
|
|
|
|
639
|
return $Rp; |
92
|
|
|
|
|
|
|
} |
93
|
|
|
|
|
|
|
|
94
|
|
|
|
|
|
|
sub request { # Create a signing request |
95
|
2
|
|
|
2
|
1
|
12
|
my ($self, %arg) = @_; |
96
|
2
|
|
|
|
|
12
|
my $n = $self->curve->n; |
97
|
2
|
|
|
|
|
16
|
my $Rp = _point_from_hex($arg{Init}); |
98
|
2
|
|
|
|
|
14
|
my $rp = $Rp->x->bmod($n); |
99
|
2
|
|
|
|
|
308
|
my $A = _makerandom($n); |
100
|
2
|
|
|
|
|
10
|
my $B = _makerandom($n); |
101
|
2
|
|
|
|
|
21
|
my $R = $Rp->multiply($A)->add($self->curve->g->multiply($B)); |
102
|
2
|
|
|
|
|
23738814
|
my $r = $R->x->bmod($n); |
103
|
2
|
|
|
|
|
221
|
my $hasher = Digest::SHA->new('sha256'); |
104
|
2
|
|
|
|
|
68
|
$hasher->add($arg{Message}); |
105
|
2
|
|
|
|
|
26
|
my $hash = $hasher->hexdigest; $hash =~ s/\s//g; |
|
2
|
|
|
|
|
8
|
|
106
|
2
|
|
|
|
|
10
|
my $H = Math::BigInt->from_hex($hash); |
107
|
2
|
|
|
|
|
2056
|
my $mp = ($A * $H * $rp * $r->copy->bmodinv($n))->bmod($n); |
108
|
2
|
|
|
|
|
59622
|
$self->_request($arg{Init} => { R => $R, B => $B, H => $H }); |
109
|
2
|
|
|
|
|
11
|
$self->_diag("request(): mp: $mp\n"); |
110
|
2
|
|
|
|
|
40
|
return $mp; |
111
|
|
|
|
|
|
|
} |
112
|
|
|
|
|
|
|
|
113
|
|
|
|
|
|
|
sub sign { # Create a blind signature |
114
|
2
|
|
|
2
|
1
|
10
|
my ($self, %arg) = @_; |
115
|
2
|
|
|
|
|
13
|
my $n = $self->curve->n; |
116
|
2
|
|
|
|
|
15
|
my $Rp = _point_from_hex($arg{Init}); |
117
|
2
|
|
|
|
|
11
|
my $rp = $Rp->x->bmod($n); |
118
|
2
|
50
|
|
|
|
207
|
return unless my $k = $self->_initkey($arg{Init}); |
119
|
2
|
|
|
|
|
129
|
my $sp = ($arg{Key}->d * $rp + $k * $arg{Message})->bmod($n); |
120
|
2
|
|
|
|
|
2880
|
$self->_diag("sign(): sp: $sp\n"); |
121
|
2
|
|
|
|
|
23
|
return $sp; |
122
|
|
|
|
|
|
|
} |
123
|
|
|
|
|
|
|
|
124
|
|
|
|
|
|
|
sub unblind { # Unblind a blind signature |
125
|
2
|
|
|
2
|
1
|
934
|
my ($self, %arg) = @_; |
126
|
2
|
|
|
|
|
12
|
my $n = $self->curve->n; |
127
|
2
|
|
|
|
|
16
|
my $Rp = _point_from_hex($arg{Init}); |
128
|
2
|
|
|
|
|
10
|
my $rp = $Rp->x->bmod($n); |
129
|
2
|
50
|
|
|
|
214
|
return unless my $req = $self->_request($arg{Init}); |
130
|
2
|
|
|
|
|
10
|
my $r = $req->{R}->x->bmod($n); |
131
|
|
|
|
|
|
|
# Check here that sp and rp are in the range (1, n-1) |
132
|
2
|
|
|
|
|
202
|
my $s = ($arg{Signature} * $r * $rp->copy->bmodinv($n) + $req->{H} * $req->{B})->bmod($n); |
133
|
2
|
|
|
|
|
55724
|
$self->_diag("unblind(): s: $s\n"); $s = $s->as_hex; $s =~ s/^0x//; |
|
2
|
|
|
|
|
11
|
|
|
2
|
|
|
|
|
1961
|
|
134
|
|
|
|
|
|
|
return ( bless { s => $s, |
135
|
|
|
|
|
|
|
R => _compress($req->{R}) |
136
|
2
|
|
|
|
|
9
|
}, 'Crypt::ECDSA::Blind::Signature' ); |
137
|
|
|
|
|
|
|
} |
138
|
|
|
|
|
|
|
|
139
|
|
|
|
|
|
|
sub verify { # Verify a signature |
140
|
2
|
|
|
2
|
1
|
5867
|
my ($self, %arg) = @_; |
141
|
2
|
|
|
|
|
10
|
my $r = $arg{Signature}->R->x->bmod($self->curve->n); |
142
|
2
|
|
|
|
|
223
|
my $Q = $arg{Key}->Q; |
143
|
2
|
|
|
|
|
12
|
my $hasher = Digest::SHA->new('sha256'); |
144
|
2
|
|
|
|
|
49
|
$hasher->add($arg{Message}); |
145
|
2
|
|
|
|
|
22
|
my $hash = $hasher->hexdigest; $hash =~ s/\s//g; |
|
2
|
|
|
|
|
7
|
|
146
|
2
|
|
|
|
|
7
|
my $H = Math::BigInt->from_hex($hash); |
147
|
2
|
|
|
|
|
1724
|
$self->_diag('verify(): s: ' . $arg{Signature}->s . ', R(x): ' . $arg{Signature}->R->x . ", H: $H\n"); |
148
|
2
|
|
|
|
|
19
|
my $u1 = $self->curve->g->multiply($arg{Signature}->s); |
149
|
2
|
|
|
|
|
25175423
|
my $u2 = $Q->multiply($r)->add($arg{Signature}->R->multiply($H)); |
150
|
2
|
|
|
|
|
24811025
|
$self->_diag('verify(): u1: ' . $u1->x . ', u2: ' . $u2->x . "\n"); |
151
|
2
|
|
|
|
|
16
|
$u1->to_hex eq $u2->to_hex; |
152
|
|
|
|
|
|
|
} |
153
|
|
|
|
|
|
|
|
154
|
|
|
|
|
|
|
sub _getpreinit { # Get a pre-created init vector |
155
|
2
|
|
|
2
|
|
4
|
my $self = shift; |
156
|
2
|
|
|
|
|
14
|
my $timestamp = time; |
157
|
2
|
|
|
|
|
5
|
while (1) { |
158
|
2
|
|
|
|
|
16
|
my ($k,$Rp) = $self->db->selectrow_array("SELECT k,Rp FROM preinits LIMIT 1;"); |
159
|
2
|
50
|
|
|
|
272
|
return undef unless $k; |
160
|
0
|
|
|
|
|
0
|
$self->db->do("DELETE FROM preinits WHERE k='$k';"); |
161
|
0
|
0
|
|
|
|
0
|
next unless $self->db->do("INSERT INTO initkeys values ('$Rp','$k','$timestamp');"); |
162
|
0
|
|
|
|
|
0
|
return ($k, $Rp); |
163
|
|
|
|
|
|
|
} |
164
|
|
|
|
|
|
|
} |
165
|
|
|
|
|
|
|
|
166
|
|
|
|
|
|
|
sub _initkey { # Save or destructively retrieve a saved init vector |
167
|
4
|
|
|
4
|
|
9
|
my $self = shift; |
168
|
4
|
|
|
|
|
8
|
my $Rp = $_[0]; my $timestamp = time; |
|
4
|
|
|
|
|
11
|
|
169
|
4
|
100
|
|
|
|
11
|
if ($_[1]) { |
170
|
2
|
|
|
|
|
50
|
$self->db->do("INSERT INTO initkeys values ('$Rp','$_[1]','$timestamp');"); |
171
|
|
|
|
|
|
|
} |
172
|
|
|
|
|
|
|
else { |
173
|
2
|
|
|
|
|
17
|
my $k = $self->db->selectcol_arrayref("SELECT k from initkeys WHERE Rp='$Rp';")->[0]; |
174
|
2
|
|
|
|
|
504
|
$self->db->do("DELETE FROM initkeys WHERE Rp='$Rp';"); |
175
|
2
|
|
|
|
|
289
|
return Math::BigInt->new($k); |
176
|
|
|
|
|
|
|
} |
177
|
|
|
|
|
|
|
} |
178
|
|
|
|
|
|
|
|
179
|
|
|
|
|
|
|
sub _request { # Save or destructively retrieve a saved request |
180
|
4
|
|
|
4
|
|
10
|
my $self = shift; |
181
|
4
|
|
|
|
|
10
|
my $Rp = $_[0]; my $ret; |
|
4
|
|
|
|
|
8
|
|
182
|
4
|
100
|
|
|
|
13
|
if ($_[1]) { |
183
|
2
|
|
|
|
|
8
|
$self->{Requests}->{$Rp} = $_[1]; |
184
|
|
|
|
|
|
|
} |
185
|
|
|
|
|
|
|
else { |
186
|
2
|
|
|
|
|
8
|
$ret = $self->{Requests}->{$Rp}; |
187
|
2
|
|
|
|
|
6
|
delete $self->{Requests}->{$Rp}; |
188
|
|
|
|
|
|
|
} |
189
|
4
|
|
|
|
|
14
|
return $ret; |
190
|
|
|
|
|
|
|
} |
191
|
|
|
|
|
|
|
|
192
|
|
|
|
|
|
|
sub _makerandom { |
193
|
7
|
|
|
7
|
|
31
|
my $n = shift; my $nlen = length($n->as_bin)-2; |
|
7
|
|
|
|
|
29
|
|
194
|
7
|
|
|
|
|
7830
|
my $random = Bytes::Random::Secure->new( Bits => 128 ); |
195
|
7
|
|
|
|
|
693
|
my $r = 0; |
196
|
7
|
|
66
|
|
|
49
|
$r = Math::BigInt->from_bin($random->string_from('01',$nlen)) until ($r > 1 and $r < $n); |
197
|
7
|
|
|
|
|
1772342152
|
return $r; |
198
|
|
|
|
|
|
|
} |
199
|
|
|
|
|
|
|
|
200
|
|
|
|
|
|
|
sub _point_from_hex { |
201
|
13
|
|
|
13
|
|
46
|
my $P = Math::EllipticCurve::Prime::Point->from_hex(_decompress(shift)); |
202
|
13
|
|
|
|
|
25221
|
$P->curve(Math::EllipticCurve::Prime->from_name('secp256k1')); |
203
|
13
|
|
|
|
|
55130
|
$P; |
204
|
|
|
|
|
|
|
} |
205
|
|
|
|
|
|
|
|
206
|
|
|
|
|
|
|
sub _decompress { |
207
|
13
|
|
|
13
|
|
27
|
my $Kc = shift; $Kc =~ /^(..)(.*)/; |
|
13
|
|
|
|
|
45
|
|
208
|
13
|
|
|
|
|
39
|
my $i = $1; my $K = '04' . '0' x (64 - length($2)) . $2; my $x = Math::BigInt->from_hex($2); |
|
13
|
|
|
|
|
60
|
|
|
13
|
|
|
|
|
51
|
|
209
|
13
|
|
|
|
|
10808
|
my $curve = Math::EllipticCurve::Prime->from_name('secp256k1'); |
210
|
13
|
|
|
|
|
53334
|
my ($p, $a, $b) = ($curve->p, $curve->a, $curve->b); |
211
|
13
|
|
|
|
|
208
|
my $y = ($x->bmodpow(3,$p)+$a*$x+$b)->bmodpow(($p+1)/4,$p); |
212
|
13
|
100
|
|
|
|
5613835
|
$y = $p - $y if $i%2 ne $y%2; |
213
|
13
|
|
|
|
|
5157
|
my $yhex = $y->as_hex; $yhex =~ s/^0x//; |
|
13
|
|
|
|
|
14097
|
|
214
|
13
|
|
|
|
|
84
|
$K .= '0' x (64 - length($yhex)) . $yhex; # print "D:$K\n"; |
215
|
13
|
|
|
|
|
137
|
return $K; |
216
|
|
|
|
|
|
|
} |
217
|
|
|
|
|
|
|
|
218
|
|
|
|
|
|
|
sub _compress { |
219
|
5
|
|
|
5
|
|
14
|
my $K = shift; # print 'C:'. $K->to_hex . "\n"; |
220
|
5
|
|
|
|
|
17
|
my $Kc = $K->x->as_hex; $Kc =~ s/^0x//; |
|
5
|
|
|
|
|
4832
|
|
221
|
5
|
|
|
|
|
19
|
$Kc = '0' x (64 - length($Kc)) . $Kc; |
222
|
5
|
100
|
|
|
|
18
|
$Kc = ($K->y % 2 ? '03' : '02') . $Kc; |
223
|
|
|
|
|
|
|
} |
224
|
|
|
|
|
|
|
|
225
|
|
|
|
|
|
|
sub _diag { |
226
|
11
|
|
|
11
|
|
800
|
my $self = shift; |
227
|
11
|
50
|
|
|
|
92
|
print @_ if $self->debug; |
228
|
|
|
|
|
|
|
} |
229
|
|
|
|
|
|
|
|
230
|
|
|
|
|
|
|
sub AUTOLOAD { |
231
|
38
|
|
|
38
|
|
24528776
|
my $self = shift; (my $auto = $AUTOLOAD) =~ s/.*:://; |
|
38
|
|
|
|
|
230
|
|
232
|
38
|
100
|
|
|
|
337
|
return if $auto eq 'DESTROY'; |
233
|
37
|
100
|
|
|
|
189
|
if ($auto =~ /^(db|debug)$/x) { |
234
|
19
|
50
|
|
|
|
84
|
$self->{$auto} = shift if (defined $_[0]); |
235
|
|
|
|
|
|
|
} |
236
|
37
|
50
|
|
|
|
158
|
if ($auto =~ /^(curve|db|debug)$/x) { |
237
|
37
|
|
|
|
|
256
|
return $self->{$auto}; |
238
|
|
|
|
|
|
|
} |
239
|
|
|
|
|
|
|
else { |
240
|
0
|
|
|
|
|
0
|
die "Could not AUTOLOAD method $auto."; |
241
|
|
|
|
|
|
|
} |
242
|
|
|
|
|
|
|
} |
243
|
|
|
|
|
|
|
|
244
|
|
|
|
|
|
|
1; # End of Crypt::ECDSA::Blind |
245
|
|
|
|
|
|
|
|
246
|
|
|
|
|
|
|
package Crypt::ECDSA::Blind::PubKey; |
247
|
|
|
|
|
|
|
|
248
|
|
|
|
|
|
|
sub write { |
249
|
0
|
|
|
0
|
|
0
|
1; |
250
|
|
|
|
|
|
|
} |
251
|
|
|
|
|
|
|
|
252
|
|
|
|
|
|
|
sub as_hex { |
253
|
1
|
|
|
1
|
|
686
|
Crypt::ECDSA::Blind::_compress(shift->Q); |
254
|
|
|
|
|
|
|
} |
255
|
|
|
|
|
|
|
|
256
|
|
|
|
|
|
|
sub from_hex { |
257
|
1
|
|
|
1
|
|
667
|
bless {Q => Crypt::ECDSA::Blind::_point_from_hex(shift)}, 'Crypt::ECDSA::Blind::PubKey'; |
258
|
|
|
|
|
|
|
} |
259
|
|
|
|
|
|
|
|
260
|
|
|
|
|
|
|
sub Q { |
261
|
3
|
|
|
3
|
|
36
|
shift->{Q}; |
262
|
|
|
|
|
|
|
} |
263
|
|
|
|
|
|
|
|
264
|
|
|
|
|
|
|
1; # End of Crypt::ECDSA::Blind::PubKey |
265
|
|
|
|
|
|
|
|
266
|
|
|
|
|
|
|
package Crypt::ECDSA::Blind::SecKey; |
267
|
|
|
|
|
|
|
|
268
|
|
|
|
|
|
|
sub as_hex { |
269
|
1
|
|
|
1
|
|
5
|
my $d = shift->d->as_hex; $d =~ s/^0x//; |
|
1
|
|
|
|
|
994
|
|
270
|
1
|
|
|
|
|
5
|
$d; |
271
|
|
|
|
|
|
|
} |
272
|
|
|
|
|
|
|
|
273
|
|
|
|
|
|
|
sub from_hex { |
274
|
1
|
|
|
1
|
|
5
|
bless {d => Math::BigInt->from_hex(shift)}, 'Crypt::ECDSA::Blind::SecKey'; |
275
|
|
|
|
|
|
|
} |
276
|
|
|
|
|
|
|
|
277
|
|
|
|
|
|
|
sub write { |
278
|
0
|
|
|
0
|
|
0
|
1; |
279
|
|
|
|
|
|
|
} |
280
|
|
|
|
|
|
|
|
281
|
|
|
|
|
|
|
sub d { |
282
|
3
|
|
|
3
|
|
21
|
shift->{d}; |
283
|
|
|
|
|
|
|
} |
284
|
|
|
|
|
|
|
|
285
|
|
|
|
|
|
|
1; # End of Crypt::ECDSA::Blind::SecKey |
286
|
|
|
|
|
|
|
|
287
|
|
|
|
|
|
|
package Crypt::ECDSA::Blind::Signature; |
288
|
|
|
|
|
|
|
|
289
|
|
|
|
|
|
|
sub s { |
290
|
4
|
|
|
4
|
|
28
|
Math::BigInt->from_hex(shift->{'s'}); |
291
|
|
|
|
|
|
|
} |
292
|
|
|
|
|
|
|
|
293
|
|
|
|
|
|
|
sub R { |
294
|
6
|
|
|
6
|
|
23909781
|
Crypt::ECDSA::Blind::_point_from_hex(shift->{R}); |
295
|
|
|
|
|
|
|
} |
296
|
|
|
|
|
|
|
|
297
|
|
|
|
|
|
|
sub is_valid { |
298
|
0
|
|
|
0
|
|
|
my $self = shift; |
299
|
0
|
0
|
|
|
|
|
$self->{R} =~ /^[0-9a-f]+$/ and $self->{s} =~ /^[0-9a-f]+$/; |
300
|
|
|
|
|
|
|
} |
301
|
|
|
|
|
|
|
|
302
|
|
|
|
|
|
|
1; # End of Crypt::ECDSA::Blind::Signature |
303
|
|
|
|
|
|
|
|
304
|
|
|
|
|
|
|
__END__ |