class ECDSA::Point

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.

Attributes

group[R]

@return {Group} the curve that the point is on.

x[R]

@return (Integer or nil) the x coordinate, or nil for the infinity point.

y[R]

@return (Integer or nil) the y coordinate, or nil for the infinity point.

Public Class Methods

new(group, *args) click to toggle source

Creates a new instance of {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.

@param group (Group) @param args Either the x and y coordinates as integers, or just

`:infinity` to create the infinity point.
# 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

Public Instance Methods

*(i)
Alias for: multiply_by_scalar
+(other)

(see add_to_point)

Alias for: add_to_point
==(other) click to toggle source

Compares this point to another.

@return (true or false) true if the points are equal

# File lib/ecdsa/point.rb, line 143
def ==(other)
  eql?(other)
end
add_to_point(other) click to toggle source

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).

@param other (Point) @return The sum of the two points.

# 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
Also aliased as: +
coords() click to toggle source

Returns an array of the coordinates, with ‘x` first and `y` second.

@return (Array)

# File lib/ecdsa/point.rb, line 48
def coords
  [x, y]
end
double() click to toggle source

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.

@return (Point)

# 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) click to toggle source

Compares this point to another.

@return (true or false) true if the points are equal

# 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() click to toggle source

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.

@return (Integer)

# File lib/ecdsa/point.rb, line 153
def hash
  [group, x, y].hash
end
infinity?() click to toggle source

Returns true if this instance represents the infinity point (the additive identity of the group).

@return (true or false)

# File lib/ecdsa/point.rb, line 161
def infinity?
  @infinity == true
end
inspect() click to toggle source

Returns a string showing the value of the point which is useful for debugging.

@return (String)

# 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) click to toggle source

Returns the point multiplied by a non-negative integer.

@param i (Integer) @return (Point)

# 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
Also aliased as: *
negate() click to toggle source

Returns the additive inverse of the point.

@return (Point)

# File lib/ecdsa/point.rb, line 92
def negate
  return self if infinity?
  self.class.new(group, x, field.mod(-y))
end

Private Instance Methods

check_group!(point) click to toggle source
# File lib/ecdsa/point.rb, line 179
def check_group!(point)
  raise 'Mismatched groups.' if point.group != group
end
field() click to toggle source
# File lib/ecdsa/point.rb, line 183
def field
  group.field
end