elliptic-lite 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -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: []