Elliptic Curve Digital Signature Algorithm: Difference between revisions

m
(New post.)
m (→‎{{header|Wren}}: Minor tidy)
 
(4 intermediate revisions by 2 users not shown)
Line 750:
}
f ^= d;
std::cout << "\n" << "corrupted hash " << std::hex << std::setfill('0') << std::setw(8) << f << std::endl;
<< std::dec << std::endl;
}
 
Line 2,691 ⟶ 2,692:
=={{header|Raku}}==
(formerly Perl 6)
<syntaxhighlight lang="raku" line>module EC {
use FiniteField;
 
our class Point {
Reference: Many routines are translated from this [https://github.com/sblackstone/toy-ecdsa Ruby repository], by Stephen Blackstone. The rest are taken here and there from RC.
has ($.x, $.y);
<syntaxhighlight lang="raku" line>use Digest::SHA256::Native;
submethod TWEAK { fail unless $!y**2 == $!x**3 + $*a*$!x + $*b }
multi method gist(::?CLASS:U:) { "Point at Horizon" }
multi method new($x, $y) { samewith :$x, :$y }
}
multi infix:<==>(Point:D $A, Point:D $B) is export { $A.x == $B.x and $A.y == $B.y }
 
multi prefix:<->(Point $P) returns Point is export { Point.new: $P.x, -$P.y }
# Following data taken from the C entry
multi infix:<+>(Point $A, Point:U) is export { $A }
our (\A,\B,\P,\O,\Gx,\Gy) = (355, 671, 1073741789, 1073807281, 13693, 10088);
multi infix:<+>(Point:U, Point $B) is export { $B }
multi infix:<+>(Point:D $A, Point:D $B) returns Point is export {
my $λ;
if $A.x == $B.x and $A.y == -$B.y { return Point }
elsif $A == $B {
return Point if $A.y == 0;
$λ = (3*$A.x² + $*a) / (2*$A.y);
}
else { $λ = ($A.y - $B.y) / ($A.x - $B.x); }
 
given $λ**2 - $A.x - $B.x {
#`{ Following data taken from the Julia entry; 256-bit; tested
return Point.new: $_, $λ*($A.x - $_) - $A.y;
our (\A,\B,\P,\O,\Gx,\Gy) = (0, 7, # https://en.bitcoin.it/wiki/Secp256k1
}
0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F,
}
0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141,
multi infix:<*>(0, Point ) is export { Point }
0x79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798,
multi infix:<*>(1, Point $p) is export { $p }
0x483ADA7726A3C4655DA4FBFC0E1108A8FD17B448A68554199C47D08FFB10D4B8); # }
multi infix:<*>(2, Point:D $p) is export { $p + $p }
multi infix:<*>(Int $n, Point $p) is export { 2*(($n div 2)*$p) + ($n mod 2)*$p }
}
 
import EC;
role Horizon { method gist { 'EC Point at horizon' } }
 
module ECDSA {
class Point { # modified from the Elliptic_curve_arithmetic entry
use Digest::SHA256::Native;
has ($.x, $.y); # handle modular arithmetic only
our class Signature {
multi method new( \x, \y ) { self.bless(:x, :y) }
method gisthas {UInt "EC Point at x=($.xc, y=$.y" }d);
multi method new(Str $message, UInt :$private-key) {
method isOn { modP(B + $.x * modP(A+$.x²)) == modP($.y²) }
sub modP ($a is copy) { (my $az %= P:16(sha256-hex ) < 0 ?? ($a += Pmessage) !!% $a }*n;
loop (my $k = my $s = my $r = 0; $r == 0; ) {
loop ( $r = $s = 0 ; $r == 0 ; ) {
$r = (( $k = (1..^$*n).roll ) * $*G).x % $*n;
}
{
use FiniteField; my $*modulus = $*n;
$s = ($z + $r*$private-key) / $k;
}
}
samewith c => $r, d => $s;
}
multi method verify(Str $message, EC::Point :$public-key) {
my $z = :16(sha256-hex $message) % $*n;
my ($u1, $u2);
{
use FiniteField;
my $*modulus = $*n;
my $w = 1/$!d;
($u1, $u2) = $z*$w, $!c*$w;
}
my $p = ($u1 * $*G) + ($u2 * $public-key);
die unless ($p.x mod $*n) == ($!c mod $*n);
}
}
}
 
my ($*a, $*b) = 355, 671;
multi infix:<⊞>(Point \p, Point \q) {
my $*modulus = my $*p = $1073741789; # slope
if p.x ~~ q.x and p.y ~~ q.y {
return Horizon if p.y == 0 ;
λ = (3*p.x²+ A) * mult_inv(2*p.y, :modulo(P))
} else {
λ = (p.y - q.y) * mult_inv(p.x - q.x, :modulo(P))
}
my \xr = (λ²- p.x - q.x);
my \yr = (λ*(p.x - xr) - p.y);
return Point.bless: x => xr % P, y => yr % P
}
 
my $*G = EC::Point.new: 13693, 10088;
multi infix:<⊠>(Int \n, Point \p) {
my $*n = 1073807281;
return 0 if n == 0 ;
return p if n == 1 ;
return p ⊞ ((n-1) ⊠ p ) if n % 2 == 1 ;
return ( n div 2 ) ⊠ ( p ⊞ p )
}
 
die "G is not of order n" if $*n*$*G;
sub mult_inv($n, :$modulo) { # rosettacode.org/wiki/Modular_inverse#Raku
my ($c, $d, $uc, $vd, $vc, $ud, $q) = $n % $modulo, $modulo, 1, 1, 0, 0, 0;
while $c != 0 {
($q, $c, $d) = ($d div $c, $d % $c, $c);
($uc, $vc, $ud, $vd) = ($ud - $q*$uc, $vd - $q*$vc, $uc, $vc);
}
return $ud % $modulo;
}
 
my $private-key = ^$*n .pick;
class Signature {
my $public-key = $private-key*$*G;
 
my $message = "Show me the monKey";
has ($.n, Point $.G); # Order and Generator point
my $signature = ECDSA::Signature.new: $message, :$private-key;
 
printf "The curve E is : 𝑦² = 𝑥³ + %s 𝑥 + %s (mod %s)\n", $*a, $*b, $*p;
method generate_signature(Int \private_key, Str \msg) {
printf "with generator G at : (%s, %s)\n", $*G.x, $*G.y;
my \z = :16(sha256-hex msg) % $.n; # self ref: Blob.list.fmt("%02X",'')
printf "G's order is loop ( my $k = my $s =: my%d\n", $r = 0 *n; $s == 0 ; ) {
printf "The private key is : %d\n", $private-key;
loop ( $r = $s = 0 ; $r == 0 ; ) {
printf "The public key is at : (%s, %s)\n", $public-key.x, $public-key.y;
$r = (( $k = (1..^$.n).roll ) ⊠ $.G).x % $.n;
printf "The message is : %s\n", $message;
}
printf "The signature is : (%s, %s)\n", $signature.c, $signature.d;
$s = ((z + $r*private_key) * mult_inv $k, :modulo($.n)) % $.n;
}
return $r, $s, private_key ⊠ $.G ;
}
 
{
method verify_signature(\msg, \r, \s, \public_key) {
use Test;
my \z = :16(sha256-hex msg) % $.n;
my \w = mult_inv s, :modulo($.n);
my (\u1,\u2) = (z*w, r*w).map: { $_ % $.n }
my \p = (u1 ⊠ $.G ) ⊞ (u2 ⊠ public_key);
return (p.x % $.n) == (r % $.n)
}
}
 
lives-ok {
print "The Curve E is : ";
$signature.verify: $message, :$public-key;
"𝑦² = 𝑥³ + %s 𝑥 + %s (mod %s) \n".printf(A,B,P);
}, "good signature for <$message>";
"with Generator G at : (%s,%s)\n".printf(Gx,Gy);
 
my $ec = Signature.new: n => O, G => Point.new: x => Gx, y => Gy ;
my $altered = $message.subst(/monKey/, "money");
say "Order(G, E) is : ", O;
dies-ok {
say "Is G ∈ E ? : ", $ec.G.isOn;
$signature.verify: $altered, :$public-key
say "Message : ", my \message = "Show me the monKey";
}, "wrong signature for <$altered>";
say "The private key dA is : ", my \dA = (1..^O).roll;
}</syntaxhighlight>
my ($r, $s, \Qa) = $ec.generate_signature(dA, message);
say "The public key Qa is : ", Qa;
say "Is Qa ∈ E ? : ", Qa.isOn;
say "Is signature valid? : ", $ec.verify_signature(message, $r, $s, Qa);
say "Message (Tampered) : ", my \altered = "Show me the money";
say "Is signature valid? : ", $ec.verify_signature(altered, $r, $s, Qa)</syntaxhighlight>
{{out}}
<pre>The Curvecurve E is : 𝑦² = 𝑥³ + 355 𝑥 + 671 (mod 1073741789)
with Generatorgenerator G at : (13693, 10088)
Order(G,'s E)order is : 1073807281
The private key is : 405586338
Is G ∈ E ? : True
The public key is at : (457744420, 236326628)
Message : Show me the monKey
The privatemessage is key dA is : 384652035Show me the monKey
The publicsignature is key Qa is : EC Point at: x=919494857(839907635, y=1803053623728690)
ok 1 - good signature for <Show me the monKey>
Is Qa ∈ E ? : True
Isok 2 - wrong signature valid?for <Show me :the Truemoney></pre>
Message (Tampered) : Show me the money
Is signature valid? : False
</pre>
 
=={{header|Wren}}==
Line 2,803 ⟶ 2,811:
{{libheader|Wren-math}}
As we don't have a signed 64 bit integer type, we use BigInt instead where needed.
<syntaxhighlight lang="ecmascriptwren">import "./dynamic" for Struct
import "./big" for BigInt
import "./fmt" for Fmt
import "./math" for Boolean
import "random" for Random
 
9,477

edits