line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
package Crypt::Perl::ECDSA::EC::Point; |
2
|
|
|
|
|
|
|
|
3
|
9
|
|
|
9
|
|
67
|
use strict; |
|
9
|
|
|
|
|
22
|
|
|
9
|
|
|
|
|
277
|
|
4
|
9
|
|
|
9
|
|
55
|
use warnings; |
|
9
|
|
|
|
|
26
|
|
|
9
|
|
|
|
|
220
|
|
5
|
|
|
|
|
|
|
|
6
|
|
|
|
|
|
|
#---------------------------------------------------------------------- |
7
|
|
|
|
|
|
|
# NOTE TO SELF: This module’s internal coordinates are |
8
|
|
|
|
|
|
|
# homogeneous/projective coordinates, not Cartesian. |
9
|
|
|
|
|
|
|
#---------------------------------------------------------------------- |
10
|
|
|
|
|
|
|
|
11
|
9
|
|
|
9
|
|
58
|
use Crypt::Perl::BigInt (); |
|
9
|
|
|
|
|
21
|
|
|
9
|
|
|
|
|
13921
|
|
12
|
|
|
|
|
|
|
|
13
|
|
|
|
|
|
|
my ($bi1, $bi2, $bi3); |
14
|
|
|
|
|
|
|
|
15
|
|
|
|
|
|
|
END { |
16
|
9
|
|
|
9
|
|
98373
|
undef $bi1, $bi2, $bi3; |
17
|
|
|
|
|
|
|
} |
18
|
|
|
|
|
|
|
|
19
|
|
|
|
|
|
|
sub new_infinity { |
20
|
1790
|
|
|
1790
|
0
|
6416
|
my ($class) = @_; |
21
|
|
|
|
|
|
|
|
22
|
1790
|
|
|
|
|
6910
|
return $class->new( undef, undef ); |
23
|
|
|
|
|
|
|
} |
24
|
|
|
|
|
|
|
|
25
|
|
|
|
|
|
|
#$curve is ECCurve |
26
|
|
|
|
|
|
|
#$x and $y are “ECFieldElement” |
27
|
|
|
|
|
|
|
#$z isa bigint (?) |
28
|
|
|
|
|
|
|
sub new { |
29
|
743377
|
|
|
743377
|
0
|
1541065
|
my ($class, $curve, $x, $y, $z) = @_; |
30
|
|
|
|
|
|
|
|
31
|
743377
|
|
66
|
|
|
2171869
|
$bi1 ||= Crypt::Perl::BigInt->new(1); |
32
|
743377
|
|
66
|
|
|
14472074
|
$bi2 ||= Crypt::Perl::BigInt->new(2); |
33
|
743377
|
|
66
|
|
|
11872314
|
$bi3 ||= Crypt::Perl::BigInt->new(3); |
34
|
|
|
|
|
|
|
|
35
|
743377
|
|
66
|
|
|
11763722
|
my $self = { |
36
|
|
|
|
|
|
|
curve => $curve, |
37
|
|
|
|
|
|
|
x => $x, |
38
|
|
|
|
|
|
|
y => $y, |
39
|
|
|
|
|
|
|
|
40
|
|
|
|
|
|
|
# Generally z won’t be given since we expect |
41
|
|
|
|
|
|
|
# Cartesian coordinates as input. But accepting |
42
|
|
|
|
|
|
|
# z allows this constructor to receive Jacobi |
43
|
|
|
|
|
|
|
# coordinates as well. |
44
|
|
|
|
|
|
|
z => $z || $bi1->copy(), |
45
|
|
|
|
|
|
|
|
46
|
|
|
|
|
|
|
zinv => undef, |
47
|
|
|
|
|
|
|
}; |
48
|
|
|
|
|
|
|
|
49
|
743377
|
|
|
|
|
21131154
|
return bless $self, $class; |
50
|
|
|
|
|
|
|
} |
51
|
|
|
|
|
|
|
|
52
|
|
|
|
|
|
|
sub is_infinity { |
53
|
1112610
|
|
|
1112610
|
0
|
1742610
|
my ($self) = @_; |
54
|
|
|
|
|
|
|
|
55
|
1112610
|
50
|
66
|
|
|
2454582
|
return 1 if !defined $self->{'x'} && !defined $self->{'y'}; |
56
|
|
|
|
|
|
|
|
57
|
1111179
|
|
50
|
|
|
2258810
|
return( ($self->{'z'}->is_zero() && !$self->{'y'}->to_bigint()->is_zero()) || 0 ); |
58
|
|
|
|
|
|
|
} |
59
|
|
|
|
|
|
|
|
60
|
|
|
|
|
|
|
#returns ECFieldElement (Cartesian) |
61
|
|
|
|
|
|
|
sub get_x { |
62
|
966
|
|
|
966
|
0
|
4068
|
my ($self) = @_; |
63
|
|
|
|
|
|
|
|
64
|
966
|
|
|
|
|
7343
|
return $self->_get_x_or_y('x'); |
65
|
|
|
|
|
|
|
} |
66
|
|
|
|
|
|
|
|
67
|
|
|
|
|
|
|
#returns ECFieldElement (Cartesian) |
68
|
|
|
|
|
|
|
#Used in key generation (not signing … ?) |
69
|
|
|
|
|
|
|
sub get_y { |
70
|
50
|
|
|
50
|
0
|
1370
|
my ($self) = @_; |
71
|
|
|
|
|
|
|
|
72
|
50
|
|
|
|
|
185
|
return $self->_get_x_or_y('y'); |
73
|
|
|
|
|
|
|
} |
74
|
|
|
|
|
|
|
|
75
|
|
|
|
|
|
|
sub _get_x_or_y { |
76
|
1016
|
|
|
1016
|
|
8110
|
my ($self, $to_get) = @_; |
77
|
|
|
|
|
|
|
|
78
|
1016
|
100
|
|
|
|
7902
|
if (!defined $self->{'zinv'}) { |
79
|
966
|
|
|
|
|
6001
|
$self->{'zinv'} = $self->{'z'}->copy()->bmodinv($self->{'curve'}{'q'}); |
80
|
|
|
|
|
|
|
} |
81
|
|
|
|
|
|
|
|
82
|
|
|
|
|
|
|
return $self->{'curve'}->from_bigint( |
83
|
1016
|
|
|
|
|
266897
|
$self->{$to_get}->to_bigint()->copy()->bmul($self->{'zinv'})->bmod($self->{'curve'}{'q'}) |
84
|
|
|
|
|
|
|
); |
85
|
|
|
|
|
|
|
} |
86
|
|
|
|
|
|
|
|
87
|
|
|
|
|
|
|
sub twice { |
88
|
370560
|
|
|
370560
|
0
|
698781
|
my ($self) = @_; |
89
|
|
|
|
|
|
|
|
90
|
370560
|
50
|
|
|
|
662845
|
return $self if $self->is_infinity(); |
91
|
|
|
|
|
|
|
|
92
|
|
|
|
|
|
|
#if ($self->{'y'}->to_bigint()->signum() == 0) { |
93
|
|
|
|
|
|
|
# return $self->{'curve'}->get_infinity(); |
94
|
|
|
|
|
|
|
#} |
95
|
|
|
|
|
|
|
|
96
|
370560
|
|
|
|
|
4440233
|
my $x1 = $self->{'x'}->to_bigint(); |
97
|
370560
|
|
|
|
|
771457
|
my $y1 = $self->{'y'}->to_bigint(); |
98
|
|
|
|
|
|
|
|
99
|
370560
|
|
|
|
|
961068
|
my $y1z1 = $y1->copy()->bmul($self->{'z'}); |
100
|
|
|
|
|
|
|
|
101
|
370560
|
|
|
|
|
25578266
|
my $y1sqz1 = $y1z1->copy()->bmul($y1)->bmod($self->{'curve'}{'q'}); |
102
|
|
|
|
|
|
|
|
103
|
370560
|
|
|
|
|
51213857
|
my $a = $self->{'curve'}{'a'}; |
104
|
|
|
|
|
|
|
|
105
|
|
|
|
|
|
|
# w = 3 * x1^2 + a * z1^2 |
106
|
|
|
|
|
|
|
#var w = x1.square().multiply(THREE); |
107
|
370560
|
|
|
|
|
837024
|
my $w = $x1->copy()->bpow($bi2)->bmul($bi3); |
108
|
|
|
|
|
|
|
|
109
|
370560
|
100
|
|
|
|
82473544
|
if (!$a->is_zero()) { |
110
|
|
|
|
|
|
|
#$w += ($self->{'z'} ** 2) * $a; |
111
|
330491
|
|
|
|
|
3409560
|
$w->badd( $a->copy()->bmul( $self->{'z'} )->bmul($self->{'z'}) ); |
112
|
|
|
|
|
|
|
} |
113
|
|
|
|
|
|
|
|
114
|
370560
|
|
|
|
|
55460934
|
$w->bmod($self->{'curve'}{'q'}); |
115
|
|
|
|
|
|
|
|
116
|
|
|
|
|
|
|
# x3 = 2 * y1 * z1 * (w^2 - 8 * x1 * y1^2 * z1) |
117
|
|
|
|
|
|
|
#var x3 = w.square().subtract(x1.shiftLeft(3).multiply(y1sqz1)).shiftLeft(1).multiply(y1z1).mod(this.curve.q); |
118
|
|
|
|
|
|
|
|
119
|
370560
|
|
|
|
|
29225754
|
my $x3 = $w->copy()->bmuladd( $w, $y1sqz1->copy()->bmul($x1)->blsft($bi3)->bneg() )->bmul($bi2)->bmul($y1z1); |
120
|
|
|
|
|
|
|
#my $x3 = 2 * $y1z1 * (($w ** 2) - ($x1 << 3) * $y1sqz1); |
121
|
|
|
|
|
|
|
#my $x3 = ($w ** 2) - (($x1 << 3) * $y1sqz1); |
122
|
|
|
|
|
|
|
#$x3 = $x3 << 1; |
123
|
|
|
|
|
|
|
#$x3 *= $y1z1; |
124
|
|
|
|
|
|
|
|
125
|
|
|
|
|
|
|
# y3 = 4 * y1^2 * z1 * (3 * w * x1 - 2 * y1^2 * z1) - w^3 |
126
|
|
|
|
|
|
|
#var y3 = w.multiply(THREE).multiply(x1).subtract(y1sqz1.shiftLeft(1)).shiftLeft(2).multiply(y1sqz1).subtract(w.square().multiply(w)).mod(this.curve.q); |
127
|
|
|
|
|
|
|
#my $y3 = 4 * $y1sqz1 * (3 * $w * $x1 - 2 * $y1sqz1) - ($w ** 3); |
128
|
|
|
|
|
|
|
|
129
|
370560
|
|
|
|
|
217565272
|
my $y3 = $y1sqz1->copy()->blsft($bi2); |
130
|
|
|
|
|
|
|
|
131
|
370560
|
|
|
|
|
120212609
|
$y3->bmuladd( |
132
|
|
|
|
|
|
|
|
133
|
|
|
|
|
|
|
#We don’t need y1sqz1 anymore |
134
|
|
|
|
|
|
|
$w->copy()->bmul($bi3)->bmuladd($x1, $y1sqz1->blsft($bi1)->bneg()), |
135
|
|
|
|
|
|
|
|
136
|
|
|
|
|
|
|
#Don’t need $w anymore |
137
|
|
|
|
|
|
|
$w->bpow($bi3)->bneg(), |
138
|
|
|
|
|
|
|
); |
139
|
|
|
|
|
|
|
|
140
|
|
|
|
|
|
|
#// z3 = 8 * (y1 * z1)^3 |
141
|
|
|
|
|
|
|
#var z3 = y1z1.square().multiply(y1z1).shiftLeft(3).mod(this.curve.q); |
142
|
|
|
|
|
|
|
#my $z3 = ($y1z1 ** 3) << 3; |
143
|
370560
|
|
|
|
|
273237257
|
my $z3 = $y1z1->bpow($bi3)->blsft($bi3); #don’t need y1z1 anymore |
144
|
|
|
|
|
|
|
|
145
|
|
|
|
|
|
|
#In original JS logic |
146
|
370560
|
|
|
|
|
171902971
|
$_->bmod($self->{'curve'}{'q'}) for ($x3, $y3, $z3); |
147
|
|
|
|
|
|
|
|
148
|
|
|
|
|
|
|
#return new ECPointFp(this.curve, this.curve.fromBigInteger(x3), this.curve.fromBigInteger(y3), z3); |
149
|
|
|
|
|
|
|
return (ref $self)->new( |
150
|
|
|
|
|
|
|
$self->{'curve'}, |
151
|
|
|
|
|
|
|
$self->{'curve'}->from_bigint($x3), |
152
|
370560
|
|
|
|
|
89103815
|
$self->{'curve'}->from_bigint($y3), |
153
|
|
|
|
|
|
|
$z3, |
154
|
|
|
|
|
|
|
); |
155
|
|
|
|
|
|
|
} |
156
|
|
|
|
|
|
|
|
157
|
|
|
|
|
|
|
#XXX clear |
158
|
|
|
|
|
|
|
sub dump { |
159
|
0
|
|
|
0
|
0
|
0
|
my ($self, $label) = @_; |
160
|
|
|
|
|
|
|
|
161
|
0
|
0
|
|
|
|
0
|
$label = q<> if !defined $label; |
162
|
|
|
|
|
|
|
|
163
|
0
|
|
|
|
|
0
|
printf "$label.x: %s\n", $self->{'x'}->to_bigint()->as_hex(); |
164
|
0
|
|
|
|
|
0
|
printf "$label.y: %s\n", $self->{'y'}->to_bigint()->as_hex(); |
165
|
0
|
|
|
|
|
0
|
printf "$label.z: %s\n", $self->{'z'}->as_hex(); |
166
|
|
|
|
|
|
|
} |
167
|
|
|
|
|
|
|
|
168
|
|
|
|
|
|
|
sub multiply { |
169
|
1431
|
|
|
1431
|
0
|
7708
|
my ($self, $k) = @_; |
170
|
|
|
|
|
|
|
|
171
|
1431
|
50
|
|
|
|
6654
|
if ($self->is_infinity()) { |
172
|
0
|
|
|
|
|
0
|
return $self; |
173
|
|
|
|
|
|
|
} |
174
|
|
|
|
|
|
|
|
175
|
|
|
|
|
|
|
# “Montgomery ladder” algorithm taken from Wikipedia: |
176
|
|
|
|
|
|
|
# |
177
|
|
|
|
|
|
|
# R0 ← 0 |
178
|
|
|
|
|
|
|
# R1 ← P |
179
|
|
|
|
|
|
|
# for i from m downto 0 do |
180
|
|
|
|
|
|
|
# if di = 0 then |
181
|
|
|
|
|
|
|
# R1 ← point_add(R0, R1) |
182
|
|
|
|
|
|
|
# R0 ← point_double(R0) |
183
|
|
|
|
|
|
|
# else |
184
|
|
|
|
|
|
|
# R0 ← point_add(R0, R1) |
185
|
|
|
|
|
|
|
# R1 ← point_double(R1) |
186
|
|
|
|
|
|
|
# return R0 |
187
|
|
|
|
|
|
|
# |
188
|
|
|
|
|
|
|
# This thwarts the timing attacks that can recover private keys |
189
|
|
|
|
|
|
|
# by running the standard “double-and-add” algorithm over and over |
190
|
|
|
|
|
|
|
# and analyzing response times. |
191
|
|
|
|
|
|
|
|
192
|
1431
|
|
|
|
|
30024
|
my $r0 = ref($self)->new_infinity(); |
193
|
1431
|
|
|
|
|
7111
|
my $r1 = $self; |
194
|
|
|
|
|
|
|
|
195
|
1431
|
|
|
|
|
13078
|
for my $i ( reverse( 0 .. ($k->bit_length() - 1) ) ) { |
196
|
370560
|
100
|
|
|
|
1363289
|
if ($k->test_bit($i)) { |
197
|
185579
|
|
|
|
|
472990
|
$r0 = $r0->add($r1); |
198
|
185579
|
|
|
|
|
554423
|
$r1 = $r1->twice(); |
199
|
|
|
|
|
|
|
} |
200
|
|
|
|
|
|
|
else { |
201
|
184981
|
|
|
|
|
484563
|
$r1 = $r0->add($r1); |
202
|
184981
|
|
|
|
|
570777
|
$r0 = $r0->twice(); |
203
|
|
|
|
|
|
|
} |
204
|
|
|
|
|
|
|
} |
205
|
|
|
|
|
|
|
|
206
|
1431
|
|
|
|
|
62157
|
return $r0; |
207
|
|
|
|
|
|
|
} |
208
|
|
|
|
|
|
|
|
209
|
|
|
|
|
|
|
#$b isa ECPoint |
210
|
|
|
|
|
|
|
sub add { |
211
|
371025
|
|
|
371025
|
0
|
689426
|
my ($self, $b) = @_; |
212
|
|
|
|
|
|
|
#$b->dump('$b'); |
213
|
|
|
|
|
|
|
|
214
|
|
|
|
|
|
|
#if(this.isInfinity()) return b; |
215
|
|
|
|
|
|
|
#if(b.isInfinity()) return this; |
216
|
|
|
|
|
|
|
|
217
|
371025
|
100
|
|
|
|
685265
|
return $b if $self->is_infinity(); |
218
|
369594
|
50
|
|
|
|
4424893
|
return $self if $b->is_infinity(); |
219
|
|
|
|
|
|
|
|
220
|
|
|
|
|
|
|
#// u = Y2 * Z1 - Y1 * Z2 |
221
|
|
|
|
|
|
|
#var u = b.y.toBigInteger().multiply(this.z).subtract(this.y.toBigInteger().multiply(b.z)).mod(this.curve.q); |
222
|
|
|
|
|
|
|
my $u = $b->{'y'}->to_bigint()->copy()->bmuladd( |
223
|
|
|
|
|
|
|
$self->{'z'}, |
224
|
369594
|
|
|
|
|
3898439
|
$self->{'y'}->to_bigint()->copy()->bneg()->bmul($b->{'z'}), |
225
|
|
|
|
|
|
|
); |
226
|
|
|
|
|
|
|
# $b->{'z'}; |
227
|
|
|
|
|
|
|
|
228
|
|
|
|
|
|
|
#// v = X2 * Z1 - X1 * Z2 |
229
|
|
|
|
|
|
|
#var v = b.x.toBigInteger().multiply(this.z).subtract(this.x.toBigInteger().multiply(b.z)).mod(this.curve.q); |
230
|
|
|
|
|
|
|
my $v = $b->{'x'}->to_bigint()->copy()->bmuladd( |
231
|
|
|
|
|
|
|
$self->{'z'}, |
232
|
369594
|
|
|
|
|
65314727
|
$self->{'x'}->to_bigint()->copy()->bneg()->bmul($b->{'z'}), |
233
|
|
|
|
|
|
|
); |
234
|
|
|
|
|
|
|
|
235
|
|
|
|
|
|
|
|
236
|
369594
|
|
|
|
|
62076839
|
$_->bmod($self->{'curve'}{'q'}) for ($u, $v); |
237
|
|
|
|
|
|
|
#print "u: " . $u->as_hex() . $/; |
238
|
|
|
|
|
|
|
#print "v: " . $v->as_hex() . $/; |
239
|
|
|
|
|
|
|
#if(BigInteger.ZERO.equals(v)) { |
240
|
|
|
|
|
|
|
# if(BigInteger.ZERO.equals(u)) { |
241
|
|
|
|
|
|
|
# return this.twice(); // this == b, so double |
242
|
|
|
|
|
|
|
# } |
243
|
|
|
|
|
|
|
#return this.curve.getInfinity(); // this = -b, so infinity |
244
|
|
|
|
|
|
|
#} |
245
|
369594
|
50
|
|
|
|
56120722
|
if ($v->is_zero()) { |
246
|
0
|
0
|
|
|
|
0
|
if ($u->is_zero()) { |
247
|
0
|
|
|
|
|
0
|
return $self->twice(); |
248
|
|
|
|
|
|
|
} |
249
|
|
|
|
|
|
|
|
250
|
0
|
|
|
|
|
0
|
return $self->{'curve'}->get_infinity(); |
251
|
|
|
|
|
|
|
} |
252
|
|
|
|
|
|
|
|
253
|
|
|
|
|
|
|
#var THREE = new BigInteger("3"); |
254
|
|
|
|
|
|
|
#var x1 = this.x.toBigInteger(); |
255
|
|
|
|
|
|
|
#var y1 = this.y.toBigInteger(); |
256
|
|
|
|
|
|
|
#var x2 = b.x.toBigInteger(); |
257
|
|
|
|
|
|
|
#var y2 = b.y.toBigInteger(); |
258
|
369594
|
|
|
|
|
3333451
|
my ($x1, $y1, $z1) = @{$self}{ qw( x y z ) }; |
|
369594
|
|
|
|
|
1037692
|
|
259
|
369594
|
|
|
|
|
596487
|
my ($x2, $y2, $z2) = @{$b}{ qw( x y z ) }; |
|
369594
|
|
|
|
|
729979
|
|
260
|
|
|
|
|
|
|
|
261
|
369594
|
|
|
|
|
1099572
|
$_ = $_->to_bigint() for ($x1, $y1, $x2, $y2); |
262
|
|
|
|
|
|
|
|
263
|
|
|
|
|
|
|
#var v2 = v.square(); |
264
|
|
|
|
|
|
|
#var v3 = v2.multiply(v); |
265
|
|
|
|
|
|
|
#var x1v2 = x1.multiply(v2); |
266
|
|
|
|
|
|
|
#var zu2 = u.square().multiply(this.z); |
267
|
|
|
|
|
|
|
|
268
|
369594
|
|
|
|
|
898367
|
my $v2 = $v->copy()->bmul($v); |
269
|
369594
|
|
|
|
|
24218921
|
my $v3 = $v->copy()->bmul($v2); |
270
|
|
|
|
|
|
|
|
271
|
369594
|
|
|
|
|
22633883
|
my $x1v2 = $x1->copy()->bmul($v2); |
272
|
369594
|
|
|
|
|
22507356
|
my $zu2 = $u->copy()->bmul($u)->bmul($self->{'z'}); |
273
|
|
|
|
|
|
|
#use Data::Dumper; |
274
|
|
|
|
|
|
|
#print Dumper( map { $_->as_hex() } $u, $v, $x1, $y1, $z1, $x2, $y2, $z2, $v2, $v3, $x1v2, $zu2 ); |
275
|
|
|
|
|
|
|
|
276
|
|
|
|
|
|
|
#// x3 = v * (z2 * (z1 * u^2 - 2 * x1 * v^2) - v^3) |
277
|
|
|
|
|
|
|
#var x3 = zu2.subtract(x1v2.shiftLeft(1)).multiply(b.z).subtract(v3).multiply(v).mod(this.curve.q); |
278
|
|
|
|
|
|
|
#my $x3 = $v * ($z2 * ($z1 * ($u ** 2) - 2 * $x1 * ($v ** 2)) - ($v ** 3)); |
279
|
369594
|
|
|
|
|
38307710
|
my $x3 = $u->copy()->bmul($u); |
280
|
369594
|
|
|
|
|
22557795
|
$x3->bmuladd( $z1, $x1->copy()->blsft($bi1)->bneg()->bmul($v)->bmul($v) ); |
281
|
369594
|
|
|
|
|
193322630
|
$x3->bmuladd( $z2, $v->copy()->bpow($bi3)->bneg() ); |
282
|
369594
|
|
|
|
|
107055050
|
$x3->bmul($v); |
283
|
|
|
|
|
|
|
|
284
|
|
|
|
|
|
|
#// y3 = z2 * (3 * x1 * u * v^2 - y1 * v^3 - z1 * u^3) + u * v^3 |
285
|
|
|
|
|
|
|
#var y3 = x1v2.multiply(THREE).multiply(u).subtract(y1.multiply(v3)).subtract(zu2.multiply(u)).multiply(b.z).add(u.multiply(v3)).mod(this.curve.q); |
286
|
|
|
|
|
|
|
#my $y3 = $z2 * (3 * $x1 * $u * $v2 - $y1 * $v3 - $z1 * ($u ** 3)) + $u * $v3; |
287
|
369594
|
|
|
|
|
17806920
|
my $y3 = $u->copy()->bmul($bi3)->bmul($x1); |
288
|
369594
|
|
|
|
|
39295482
|
$y3->bmuladd($v2, $y1->copy()->bmul($v3)->bneg()); #no more y1 after this |
289
|
369594
|
|
|
|
|
61627745
|
$y3->bsub( $u->copy()->bpow($bi3)->bmul($z1) ); |
290
|
|
|
|
|
|
|
|
291
|
369594
|
|
|
|
|
112787269
|
$y3->bmuladd( $z2, $u->bmul($v3) ); #we don’t need $u anymore |
292
|
|
|
|
|
|
|
|
293
|
|
|
|
|
|
|
#// z3 = v^3 * z1 * z2 |
294
|
|
|
|
|
|
|
#var z3 = v3.multiply(this.z).multiply(b.z).mod(this.curve.q); |
295
|
369594
|
|
|
|
|
42820495
|
my $z3 = $v3->bmul($z1)->bmul($z2); |
296
|
|
|
|
|
|
|
|
297
|
369594
|
|
|
|
|
33531114
|
$_->bmod($self->{'curve'}{'q'}) for ($x3, $y3, $z3); |
298
|
|
|
|
|
|
|
|
299
|
|
|
|
|
|
|
return (ref $self)->new( |
300
|
|
|
|
|
|
|
$self->{'curve'}, |
301
|
|
|
|
|
|
|
$self->{'curve'}->from_bigint($x3), |
302
|
369594
|
|
|
|
|
90167147
|
$self->{'curve'}->from_bigint($y3), |
303
|
|
|
|
|
|
|
$z3, |
304
|
|
|
|
|
|
|
); |
305
|
|
|
|
|
|
|
} |
306
|
|
|
|
|
|
|
|
307
|
|
|
|
|
|
|
1; |