Class: ECDSA::Point
- Inherits:
-
Object
- Object
- ECDSA::Point
- Defined in:
- lib/ecdsa/point.rb
Overview
Instances of this class represent a point on an elliptic curve. The instances hold their ‘x` and `y` coordinates along with a reference to the Group (curve) they belong to.
An instance of this class can also represent the infinity point (the additive identity of the group), in which case ‘x` and `y` are `nil`.
Note: These Point objects are not checked when they are created so they might not actually be on the curve. You can use Group#include? to see if they are on the curve.
Instance Attribute Summary collapse
-
#group ⇒ Group
readonly
The curve that the point is on.
-
#x ⇒ Integer or nil
readonly
The x coordinate, or nil for the infinity point.
-
#y ⇒ Integer or nil
readonly
The y coordinate, or nil for the infinity point.
Instance Method Summary collapse
-
#==(other) ⇒ true or false
Compares this point to another.
-
#add_to_point(other) ⇒ Object
(also: #+)
Adds this point to another point on the same curve using the standard rules for point addition defined in section 2.2.1 of [SEC1](www.secg.org/collateral/sec1_final.pdf).
-
#coords ⇒ Array
Returns an array of the coordinates, with ‘x` first and `y` second.
-
#double ⇒ Point
Returns the point added to itself.
-
#eql?(other) ⇒ true or false
Compares this point to another.
-
#hash ⇒ Integer
Returns a hash for this point so it can be stored in hash tables with the expected behavior.
-
#infinity? ⇒ true or false
Returns true if this instance represents the infinity point (the additive identity of the group).
-
#initialize(group, *args) ⇒ Point
constructor
Creates a new instance of Point.
-
#inspect ⇒ String
Returns a string showing the value of the point which is useful for debugging.
-
#multiply_by_scalar(i) ⇒ Point
(also: #*)
Returns the point multiplied by a non-negative integer.
-
#negate ⇒ Point
Returns the additive inverse of the point.
Constructor Details
#initialize(group, *args) ⇒ Point
Creates a new instance of ECDSA::Point. This method is NOT part of the public interface of the ECDSA gem. You should call Group#new_point instead of calling this directly.
29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 |
# File 'lib/ecdsa/point.rb', line 29 def initialize(group, *args) @group = group if args == [:infinity] @infinity = true # leave @x and @y nil else x, y = args raise ArgumentError, "Invalid x: #{x.inspect}" if !x.is_a? Integer raise ArgumentError, "Invalid y: #{y.inspect}" if !y.is_a? Integer @x = x @y = y end end |
Instance Attribute Details
#group ⇒ Group (readonly)
Returns the curve that the point is on.
14 15 16 |
# File 'lib/ecdsa/point.rb', line 14 def group @group end |
#x ⇒ Integer or nil (readonly)
Returns the x coordinate, or nil for the infinity point.
17 18 19 |
# File 'lib/ecdsa/point.rb', line 17 def x @x end |
#y ⇒ Integer or nil (readonly)
Returns the y coordinate, or nil for the infinity point.
20 21 22 |
# File 'lib/ecdsa/point.rb', line 20 def y @y end |
Instance Method Details
#==(other) ⇒ true or false
Compares this point to another.
143 144 145 |
# File 'lib/ecdsa/point.rb', line 143 def ==(other) eql?(other) end |
#add_to_point(other) ⇒ Object Also known as: +
Adds this point to another point on the same curve using the standard rules for point addition defined in section 2.2.1 of [SEC1](www.secg.org/collateral/sec1_final.pdf).
58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 |
# File 'lib/ecdsa/point.rb', line 58 def add_to_point(other) check_group! other # Assertions: # raise "point given (#{point.inspect}) does not belong to #{group.name}" if !group.include?(point) # raise "point (#{inspect}) does not belong to #{group.name}" if !group.include?(self) # Rules 1 and 2 return other if infinity? return self if other.infinity? # Rule 3 return group.infinity if x == other.x && y == field.mod(-other.y) # Rule 4 if x != other.x gamma = field.mod((other.y - y) * field.inverse(other.x - x)) sum_x = field.mod(gamma * gamma - x - other.x) sum_y = field.mod(gamma * (x - sum_x) - y) return self.class.new(group, sum_x, sum_y) end # Rule 5 return double if self == other raise "Failed to add #{inspect} to #{other.inspect}: No addition rules matched." end |
#coords ⇒ Array
Returns an array of the coordinates, with ‘x` first and `y` second.
48 49 50 |
# File 'lib/ecdsa/point.rb', line 48 def coords [x, y] end |
#double ⇒ Point
Returns the point added to itself.
This algorithm is defined in [SEC1](www.secg.org/collateral/sec1_final.pdf), Section 2.2.1, Rule 5.
104 105 106 107 108 109 110 |
# File 'lib/ecdsa/point.rb', line 104 def double return self if infinity? gamma = field.mod((3 * x * x + @group.param_a) * field.inverse(2 * y)) new_x = field.mod(gamma * gamma - 2 * x) new_y = field.mod(gamma * (x - new_x) - y) self.class.new(group, new_x, new_y) end |
#eql?(other) ⇒ true or false
Compares this point to another.
135 136 137 138 |
# File 'lib/ecdsa/point.rb', line 135 def eql?(other) return false if !other.is_a?(Point) || other.group != group x == other.x && y == other.y end |
#hash ⇒ Integer
Returns a hash for this point so it can be stored in hash tables with the expected behavior. Two points that have the same coordinates and are on the same curve are equal, so they should not get separate spots in a hash table.
153 154 155 |
# File 'lib/ecdsa/point.rb', line 153 def hash [group, x, y].hash end |
#infinity? ⇒ true or false
Returns true if this instance represents the infinity point (the additive identity of the group).
161 162 163 |
# File 'lib/ecdsa/point.rb', line 161 def infinity? @infinity == true end |
#inspect ⇒ String
Returns a string showing the value of the point which is useful for debugging.
169 170 171 172 173 174 175 |
# File 'lib/ecdsa/point.rb', line 169 def inspect if infinity? '#<%s: %s, infinity>' % [self.class, group.name] else '#<%s: %s, 0x%x, 0x%x>' % [self.class, group.name, x, y] end end |
#multiply_by_scalar(i) ⇒ Point Also known as: *
Returns the point multiplied by a non-negative integer.
116 117 118 119 120 121 122 123 124 125 126 127 |
# File 'lib/ecdsa/point.rb', line 116 def multiply_by_scalar(i) raise ArgumentError, 'Scalar is not an integer.' if !i.is_a?(Integer) raise ArgumentError, 'Scalar is negative.' if i < 0 result = group.infinity v = self while i > 0 result = result.add_to_point(v) if i.odd? v = v.double i >>= 1 end result end |
#negate ⇒ Point
Returns the additive inverse of the point.
92 93 94 95 |
# File 'lib/ecdsa/point.rb', line 92 def negate return self if infinity? self.class.new(group, x, field.mod(-y)) end |