elliptic-lite 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,62 @@
1
+ ###########
2
+ # Elliptic Curve Digital Signature Algorithm (ECDSA)
3
+
4
+ module ECC
5
+
6
+
7
+ class Signature
8
+ attr_reader :r, :s
9
+ def initialize( r, s )
10
+ @r, @s = r, s
11
+ end
12
+ end # class Signature
13
+
14
+
15
+ class PublicKey
16
+ attr_reader :point
17
+
18
+ def initialize( *args, group: SECP256K1 )
19
+ @group = group
20
+
21
+ if args.size == 1 ## assume it's a point already -- todo/fix: check class via group - why? why not?
22
+ @point = args[0]
23
+ elsif args.size == 2 ## assume it's an x/y coord pair -- todo/fix: check must be Integer class/type - why? why not?
24
+ @point = @group.point( *args )
25
+ else
26
+ raise ArgumentError, "expected point or x/y coords for point; got: #{args.inspect}"
27
+ end
28
+ end
29
+
30
+ def verify?( z, sig )
31
+ s_inv = sig.s.pow( @group.n-2, @group.n )
32
+ u = z * s_inv % @group.n
33
+ v = sig.r * s_inv % @group.n
34
+
35
+ total = u*@group.g + v*@point
36
+ total.x == sig.r
37
+ end
38
+ end # class PublicKey
39
+
40
+
41
+ class PrivateKey
42
+ def initialize( secret, group: SECP256K1 )
43
+ @secret = secret
44
+ @group = group
45
+ end
46
+
47
+ def public_key
48
+ @pubkey ||= PublicKey.new( @secret * @group.g, group: @group )
49
+ end
50
+ alias_method :pubkey, :public_key
51
+
52
+ def sign( z )
53
+ k = 1 + SecureRandom.random_number( @group.n - 1)
54
+ # k = 1234567890
55
+ r = (k*@group.g).x
56
+ k_inv = k.pow( @group.n-2, @group.n )
57
+ s = (z+r*@secret) * k_inv % @group.n
58
+ s = @group.n - s if s > @group.n/2
59
+ Signature.new( r, s )
60
+ end
61
+ end # class PrivateKey
62
+ end # module ECC
@@ -0,0 +1,20 @@
1
+ module ECCLite
2
+
3
+ MAJOR = 0
4
+ MINOR = 1
5
+ PATCH = 0
6
+ VERSION = [MAJOR,MINOR,PATCH].join('.')
7
+
8
+ def self.version
9
+ VERSION
10
+ end
11
+
12
+ def self.banner
13
+ "elliptic-lite/#{VERSION} on Ruby #{RUBY_VERSION} (#{RUBY_RELEASE_DATE}) [#{RUBY_PLATFORM}] in (#{root})"
14
+ end
15
+
16
+ def self.root
17
+ File.expand_path( File.dirname(File.dirname(File.dirname(__FILE__))) )
18
+ end
19
+
20
+ end # module ECCLite
@@ -0,0 +1,2 @@
1
+ require_relative '../elliptic-lite' ## lets you use require 'elliptic/lite' too
2
+
data/test/helper.rb ADDED
@@ -0,0 +1,12 @@
1
+ ## $:.unshift(File.dirname(__FILE__))
2
+
3
+ ## minitest setup
4
+
5
+ require 'minitest/autorun'
6
+
7
+
8
+ ## our own code
9
+
10
+ require 'elliptic-lite/base'
11
+
12
+
@@ -0,0 +1,142 @@
1
+ ###
2
+ # to run use
3
+ # ruby -I ./lib -I ./test test/test_field.rb
4
+
5
+
6
+ require 'helper'
7
+
8
+ class TestField < MiniTest::Test
9
+
10
+ ## same as F13 = FiniteField.new(13) - use shortcut - why? why not?
11
+ class F₁₃ < ECC::FiniteField::Element
12
+ def self.prime() 13; end
13
+ end
14
+
15
+
16
+ def test_f13
17
+ pp F₁₃
18
+ pp F₁₃.prime
19
+ assert_equal 13, F₁₃.prime
20
+
21
+ assert F₁₃.include?( 0 )
22
+ assert F₁₃.include?( 12 )
23
+ assert_equal false, F₁₃.include?( 13 )
24
+
25
+
26
+ pp F₁₃.new(7)
27
+ pp F₁₃.new(6)
28
+
29
+ a = F₁₃[7]
30
+ b = F₁₃[6]
31
+
32
+ assert_equal false, a == b
33
+ assert_equal false, F₁₃[7] == F₁₃[6]
34
+
35
+ assert a == a
36
+ assert F₁₃[7] == F₁₃[7]
37
+
38
+
39
+
40
+ a = F₁₃[7]
41
+ b = F₁₃[12]
42
+ c = F₁₃[6]
43
+
44
+ assert_equal c, a+b
45
+ assert_equal 6, F₁₃.add( 7, 12 )
46
+
47
+ c = F₁₃[8]
48
+ assert_equal c, a-b
49
+ assert_equal F₁₃[8], a-b
50
+ assert_equal 8, F₁₃.sub( 7, 12 )
51
+
52
+ a = F₁₃[3]
53
+ b = F₁₃[12]
54
+ c = F₁₃[10]
55
+
56
+ assert_equal c, a*b
57
+ assert_equal F₁₃[10], F₁₃[3]*F₁₃[12]
58
+ assert_equal 10, F₁₃.mul( 3, 12 )
59
+
60
+
61
+ a = F₁₃[3]
62
+ b = F₁₃[1]
63
+ assert_equal b, a**3
64
+ assert_equal b, a*a*a
65
+ assert_equal a**3, a*a*a
66
+ assert_equal 1, F₁₃.pow( 3, 3 )
67
+
68
+ a = F₁₃[7]
69
+ b = F₁₃[8]
70
+
71
+ pp a**-3
72
+ assert_equal b, a**-3
73
+ assert_equal 8, F₁₃.pow( 7, -3 )
74
+ end
75
+
76
+
77
+
78
+ class F₁₇ < ECC::FiniteField::Element
79
+ def self.prime() 17; end
80
+ end
81
+
82
+ def test_f17
83
+ pp F₁₇.new(7)
84
+ assert F₁₇.new(7) == F₁₇[7]
85
+ assert F₁₇.new(7) == F₁₇.new(7)
86
+ assert F₁₇[7] == F₁₇[7]
87
+ end
88
+
89
+
90
+ F₁₉ = ECC::FiniteField.new(19)
91
+
92
+ def test_f19
93
+ a = F₁₉[2]
94
+ b = F₁₉[7]
95
+ c = a / b
96
+
97
+ assert_equal F₁₉[3], c
98
+
99
+ assert_equal F₁₉[9], F₁₉[7] / F₁₉[5]
100
+ assert_equal 9, F₁₉.div( 7, 5 )
101
+ end
102
+
103
+
104
+ def test_examples
105
+ a = F₁₃[7]
106
+ b = F₁₃[12]
107
+ c = F₁₃[6]
108
+ assert_equal c, a+b
109
+
110
+ c = F₁₃[8]
111
+ assert_equal c, a-b
112
+
113
+ a = F₁₃[3]
114
+ b = F₁₃[12]
115
+ c = F₁₃[10]
116
+ assert_equal c, a*b
117
+
118
+ a = F₁₃[3]
119
+ b = F₁₃[1]
120
+ assert_equal b, a**3
121
+ assert_equal b, a*a*a
122
+ assert_equal a**3, a*a*a
123
+
124
+ a = F₁₉[2]
125
+ b = F₁₉[7]
126
+ c = F₁₉[3]
127
+ assert_equal c, a/b
128
+
129
+
130
+ assert_equal F₁₃[6], F₁₃[7] + F₁₃[12]
131
+ assert_equal F₁₃[8], F₁₃[7] - F₁₃[12]
132
+ assert_equal F₁₃[10], F₁₃[3] * F₁₃[12]
133
+ assert_equal F₁₃[1], F₁₃[3] ** 3
134
+ assert_equal F₁₃[1], F₁₃[3] * F₁₃[3] * F₁₃[3]
135
+ assert_equal F₁₃[3] * F₁₃[3] * F₁₃[3], F₁₃[3] ** 3
136
+
137
+ assert_equal F₁₉[3], F₁₉[2] / F₁₉[7]
138
+ end
139
+
140
+ end # class TestField
141
+
142
+
@@ -0,0 +1,83 @@
1
+ ###
2
+ # to run use
3
+ # ruby -I ./lib -I ./test test/test_point.rb
4
+
5
+
6
+ require 'helper'
7
+
8
+ class TestPoint < MiniTest::Test
9
+
10
+ class Point_5_7 < ECC::Point
11
+ def self.curve() @curve ||= ECC::Curve.new( a: 5, b: 7 ); end
12
+ end
13
+
14
+ def test_point_5_7
15
+ p1 = Point_5_7.new( -1, -1 ) # point with x/y coords: -1/-1
16
+ ## p2 = Point_5_7.new( -1, -2 ) # raise ArgumentError!! point NOT on curve
17
+
18
+ assert Point_5_7.on_curve?( -1, -1 ) #=> true
19
+ assert_equal false, Point_5_7.on_curve?( -1, -2 ) #=> false
20
+
21
+ inf = Point_5_7[ :infinity ]
22
+ assert inf.infinity? #=> true
23
+
24
+ p1 = Point_5_7[-1, -1]
25
+ p2 = Point_5_7[-1, 1]
26
+ inf = Point_5_7[ :infinity ]
27
+
28
+ assert Point_5_7[-1,-1], p1 + inf
29
+ assert Point_5_7[-1,1], inf + p2
30
+ assert Point_5_7[:infinity], p1 + p2
31
+
32
+ p1 = Point_5_7[ 2, 5]
33
+ p2 = Point_5_7[-1,-1]
34
+ assert Point_5_7[3,-7], p1 + p2
35
+
36
+ p1 = Point_5_7[-1,-1]
37
+ assert Point_5_7[18,77], p1 + p1
38
+ end
39
+
40
+
41
+
42
+ class F₂₂₃ < ECC::FiniteField::Element
43
+ def self.prime() 223; end
44
+ end
45
+
46
+ class Point_F₂₂₃0_7 < ECC::Point
47
+ def self.curve() @curve ||= ECC::Curve.new( a: 0, b: 7, f: F₂₂₃ ); end
48
+ end
49
+
50
+
51
+ def test_point_f₂₂₃0_7
52
+ p1 = Point_F₂₂₃0_7[ 192, 105 ]
53
+ p2 = Point_F₂₂₃0_7[ 17, 56 ]
54
+ assert Point_F₂₂₃0_7[170,142], p1 + p2
55
+
56
+ p1 = Point_F₂₂₃0_7[ 170, 142 ]
57
+ p2 = Point_F₂₂₃0_7[ 60, 139 ]
58
+ assert Point_F₂₂₃0_7[220,181], p1 + p2
59
+
60
+ p1 = Point_F₂₂₃0_7[ 47, 71 ]
61
+ p2 = Point_F₂₂₃0_7[ 17, 56 ]
62
+ assert Point_F₂₂₃0_7[215,68], p1 + p2
63
+
64
+
65
+ p = Point_F₂₂₃0_7[ 192, 105 ]
66
+ assert Point_F₂₂₃0_7[49,71], p+p
67
+
68
+ p = Point_F₂₂₃0_7[ 143, 98 ]
69
+ assert Point_F₂₂₃0_7[64,168], p+p
70
+
71
+ p = Point_F₂₂₃0_7[ 47, 71 ]
72
+ assert Point_F₂₂₃0_7[36,111], p+p
73
+ assert Point_F₂₂₃0_7[194,51], p+p+p+p
74
+ assert Point_F₂₂₃0_7[116,55], p+p+p+p+p+p+p+p
75
+ assert Point_F₂₂₃0_7[:infinity], p+p+p+p+p+p+p+p+p+p+p+p+p+p+p+p+p+p+p+p+p
76
+
77
+ assert 2*p, p+p
78
+ assert 4*p, p+p+p+p
79
+ assert 8*p, p+p+p+p+p+p+p+p
80
+ assert 21*p, p+p+p+p+p+p+p+p+p+p+p+p+p+p+p+p+p+p+p+p+p
81
+ end
82
+ end # class TestPoint
83
+
@@ -0,0 +1,61 @@
1
+ ###
2
+ # to run use
3
+ # ruby -I ./lib -I ./test test/test_signature.rb
4
+
5
+
6
+ require 'helper'
7
+
8
+ class TestSignature < MiniTest::Test
9
+
10
+ def test_verify
11
+ puts "test_verify:"
12
+ pubkey = ECC::PublicKey.new(
13
+ 0x887387e452b8eacc4acfde10d9aaf7f6d9a0f975aabb10d006e4da568744d06c,
14
+ 0x61de6d95231cd89026e286df3b6ae4a894a3378e393e93a0f45b666329a0ae34 )
15
+ pp pubkey
16
+
17
+ z = 0xec208baa0fc1c19f708a9ca96fdeff3ac3f230bb4a7ba4aede4942ad003c0f60
18
+ sig = ECC::Signature.new(
19
+ 0xac8d1c87e51d0d441be8b3dd5b05c8795b48875dffe00b7ffcfac23010d3a395,
20
+ 0x68342ceff8935ededd102dd876ffd6ba72d6a427a3edb13d26eb0781cb423c4)
21
+
22
+ assert pubkey.verify?( z, sig )
23
+
24
+
25
+ z = 0x7c076ff316692a3d7eb3c3bb0f8b1488cf72e1afcd929e29307032997a838a3d
26
+ sig = ECC::Signature.new(
27
+ 0xeff69ef2b1bd93a66ed5219add4fb51e11a840f404876325a1e8ffe0529a2c,
28
+ 0xc7207fee197d27c618aea621406f6bf5ef6fca38681d82b2f06fddbdce6feab6)
29
+
30
+ assert pubkey.verify?( z, sig )
31
+ end
32
+
33
+ def test_sign
34
+ puts "test_sign:"
35
+ e = 12345
36
+ key = ECC::PrivateKey.new( e )
37
+
38
+ pp z_hex = Digest::SHA256.hexdigest( 'Programming Elliptic Curve Cryptography!' )
39
+ pp z = z_hex.to_i( 16 )
40
+
41
+ sig = key.sign( z )
42
+ pp sig
43
+
44
+
45
+ pp pubkey = key.pubkey
46
+
47
+ assert pubkey.verify?( z, sig )
48
+
49
+ # -or-
50
+ pubkey = ECC::PublicKey.new(
51
+ 0xf01d6b9018ab421dd410404cb869072065522bf85734008f105cf385a023a80f,
52
+ 0x0eba29d0f0c5408ed681984dc525982abefccd9f7ff01dd26da4999cf3f6a295 )
53
+
54
+ sig = ECC::Signature.new(
55
+ 35839919642726191515862186078164267963984698217861116280002507416364797996230,
56
+ 34481949470477153440646085306694123309931748956488082604284303792820502002529 )
57
+
58
+ assert pubkey.verify?( z, sig )
59
+ end
60
+ end # class TestSignature
61
+
metadata ADDED
@@ -0,0 +1,103 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: elliptic-lite
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Gerald Bauer
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2021-06-06 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: rdoc
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '4.0'
20
+ - - "<"
21
+ - !ruby/object:Gem::Version
22
+ version: '7'
23
+ type: :development
24
+ prerelease: false
25
+ version_requirements: !ruby/object:Gem::Requirement
26
+ requirements:
27
+ - - ">="
28
+ - !ruby/object:Gem::Version
29
+ version: '4.0'
30
+ - - "<"
31
+ - !ruby/object:Gem::Version
32
+ version: '7'
33
+ - !ruby/object:Gem::Dependency
34
+ name: hoe
35
+ requirement: !ruby/object:Gem::Requirement
36
+ requirements:
37
+ - - "~>"
38
+ - !ruby/object:Gem::Version
39
+ version: '3.22'
40
+ type: :development
41
+ prerelease: false
42
+ version_requirements: !ruby/object:Gem::Requirement
43
+ requirements:
44
+ - - "~>"
45
+ - !ruby/object:Gem::Version
46
+ version: '3.22'
47
+ description: elliptic-lite - elliptic curve cryptography from scratch / zero - start
48
+ with finite fields, add elliptic curve points and point addition and scalar multiplications,
49
+ add the elliptic curve digital signature algorithm (ECDSA) using the secp256k1 curve
50
+ / group to sign and verify messages and more
51
+ email: wwwmake@googlegroups.com
52
+ executables: []
53
+ extensions: []
54
+ extra_rdoc_files:
55
+ - CHANGELOG.md
56
+ - Manifest.txt
57
+ - README.md
58
+ files:
59
+ - CHANGELOG.md
60
+ - Manifest.txt
61
+ - README.md
62
+ - Rakefile
63
+ - lib/elliptic-lite.rb
64
+ - lib/elliptic-lite/base.rb
65
+ - lib/elliptic-lite/field.rb
66
+ - lib/elliptic-lite/point.rb
67
+ - lib/elliptic-lite/secp256k1.rb
68
+ - lib/elliptic-lite/signature.rb
69
+ - lib/elliptic-lite/version.rb
70
+ - lib/elliptic/lite.rb
71
+ - test/helper.rb
72
+ - test/test_field.rb
73
+ - test/test_point.rb
74
+ - test/test_signature.rb
75
+ homepage: https://github.com/rubycoco/blockchain
76
+ licenses:
77
+ - Public Domain
78
+ metadata: {}
79
+ post_install_message:
80
+ rdoc_options:
81
+ - "--main"
82
+ - README.md
83
+ require_paths:
84
+ - lib
85
+ required_ruby_version: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ version: '2.3'
90
+ required_rubygems_version: !ruby/object:Gem::Requirement
91
+ requirements:
92
+ - - ">="
93
+ - !ruby/object:Gem::Version
94
+ version: '0'
95
+ requirements: []
96
+ rubygems_version: 3.1.4
97
+ signing_key:
98
+ specification_version: 4
99
+ summary: elliptic-lite - elliptic curve cryptography from scratch / zero - start with
100
+ finite fields, add elliptic curve points and point addition and scalar multiplications,
101
+ add the elliptic curve digital signature algorithm (ECDSA) using the secp256k1 curve
102
+ / group to sign and verify messages and more
103
+ test_files: []