class ECC::Point

Attributes

x[R]
y[R]

Public Class Methods

[]( *args ) click to toggle source
# File lib/elliptic-lite/point.rb, line 27
def self.[]( *args )
  new( *args )
end
add( *nums ) click to toggle source

convenience helpers - field operations

# File lib/elliptic-lite/point.rb, line 7
def self.add( *nums )   ## note: for convenience allow additions of more than two numbers
  sum = nums.shift   ## "pop" first item from array
  nums.reduce( sum ) {|sum, num| curve.f.add( sum, num ) }
end
div( a, b ) click to toggle source
# File lib/elliptic-lite/point.rb, line 17
def self.div( a, b )         curve.f.div( a, b );  end
infinity() click to toggle source
# File lib/elliptic-lite/point.rb, line 31
def self.infinity  ## convenience helper / shortcut for infinity - in use anywhere? keep? why? why not?
  new( :infinity )
end
mul( a, b ) click to toggle source
# File lib/elliptic-lite/point.rb, line 15
def self.mul( a, b )         curve.f.mul( a, b );   end
new( *args ) click to toggle source
# File lib/elliptic-lite/point.rb, line 50
def initialize( *args )
  ## allow :infinity or :inf for infinity for now - add more? why? why not?
  if args.size == 1 && [:inf, :infinity].include?( args[0] )
    @x = nil
    @y = nil
  elsif args.size == 2 &&
        args[0].is_a?( Integer ) &&
        args[1].is_a?( Integer )
    @x, @y = args
    raise ArgumentError, "point (#{@x}/#{@y}) is NOT on the curve"  unless self.class.on_curve?( @x, @y )
  else
    raise ArgumentError, "expected two integer numbers or :inf/:infinity; got #{args.inspect}"
  end
end
on_curve?( x, y ) click to toggle source
# File lib/elliptic-lite/point.rb, line 19
def self.on_curve?( x, y )
  ## y**2 == x**3 + curve.a*x + curve.b
  pow( y, 2 ) == add( pow( x, 3),
                      mul( curve.a, x ),
                      curve.b )
end
pow( a, exponent ) click to toggle source
# File lib/elliptic-lite/point.rb, line 16
def self.pow( a, exponent )  curve.f.pow( a, exponent ); end
sub( *nums ) click to toggle source
# File lib/elliptic-lite/point.rb, line 11
def self.sub( *nums )
  sum = nums.shift   ## "pop" first item from array
  nums.reduce( sum ) {|sum, num| curve.f.sub( sum, num ) }
end

Public Instance Methods

*( coefficient )
Alias for: mul
+( other )
Alias for: add
==( other ) click to toggle source
# File lib/elliptic-lite/point.rb, line 88
def ==( other )
  if other.is_a?( Point ) && curve?( other )
    @x == other.x && @y == other.y
  else
    false
  end
end
_add( *nums ) click to toggle source

convenience helpers - field operations

# File lib/elliptic-lite/point.rb, line 40
def _add( *nums )       self.class.add( *nums ); end
_div( a, b ) click to toggle source
# File lib/elliptic-lite/point.rb, line 44
def _div( a, b )        self.class.div( a, b );  end
_mul( a, b ) click to toggle source
# File lib/elliptic-lite/point.rb, line 42
def _mul( a, b )        self.class.mul( a, b );   end
_pow( a, exponent ) click to toggle source
# File lib/elliptic-lite/point.rb, line 43
def _pow( a, exponent ) self.class.pow( a, exponent ); end
_sub( *nums ) click to toggle source
# File lib/elliptic-lite/point.rb, line 41
def _sub( *nums )       self.class.sub( *nums ); end
add( other ) click to toggle source
# File lib/elliptic-lite/point.rb, line 131
def add( other )
  require_curve!( other )

  return other   if infinity?        ## self is infinity/infinity ?
  return self    if other.infinity?  ## other is infinity/infinity ?

  if @x == other.x && @y != other.y
    return self.class.new( :infinity )
  end


  if @x != other.x   ## e.g. add point operation
    # s = (other.y - @y) / (other.x - @x)
    # x3 = s**2 - @x - other.x
    # y3 = s * (@x - x3) - @y
    s  = _div( _sub(other.y, @y),
               _sub(other.x, @x))
    x3 = _sub( _pow(s,2), @x, other.x )
    y3 = _sub( _mul( s, _sub(@x, x3)), @y )

    return self.class.new( x3, y3 )
  end

  if @x == other.x && @y == other.y   ## e.g. double point operation
    return double
  end

  raise "failed to add point #{inspect} to #{other.inspect} - no point addition rules matched; sorry"
end
Also aliased as: +
coerce(other) click to toggle source
# File lib/elliptic-lite/point.rb, line 97
def coerce(other)
  args = [self, other]
  ## puts " coerce(#{other} <#{other.class.name}>):"
  ## pp args
  args
end
curve() click to toggle source

convenience helpers

# File lib/elliptic-lite/point.rb, line 38
def curve() self.class.curve; end
curve?( other ) click to toggle source
# File lib/elliptic-lite/point.rb, line 79
def curve?( other )  ## check for matching curver
  self.curve == other.curve
end
double() click to toggle source
# File lib/elliptic-lite/point.rb, line 163
def double  # double point operation
  if @y == _mul( 0, @x )
    self.class.new( :infinity )
  else
    # s = (3 * @x**2 + curve.a) / (2 * @y)
    # x3 = s**2 - 2 * @x
    # y3 = s * (@x - x3) - @y
    s = _div( _add( _mul( 3,_pow(@x, 2)), curve.a),
              _mul(2, @y))
    x3 = _sub( _pow(s, 2), _mul( 2, @x))
    y3 = _sub( _mul( s, _sub(@x, x3)), @y)

    self.class.new( x3, y3 )
  end
end
infinity?() click to toggle source
# File lib/elliptic-lite/point.rb, line 66
def infinity?
  @x.nil? && @y.nil?
end
inspect() click to toggle source
# File lib/elliptic-lite/point.rb, line 70
def inspect
  if infinity?
    "#{self.class.name}(:infinity)"
  else
    "#{self.class.name}(#{@x},#{@y})"
  end
end
mul( coefficient ) click to toggle source
# File lib/elliptic-lite/point.rb, line 104
  def mul( coefficient )  ## note: for rmul-style to work needs coerce method to swap s*p to p*s!!
    raise ArgumentError, "integer expected for mul; got #{other.class.name}"  unless coefficient.is_a?( Integer )
    ## todo/check/fix: check for negative integer e.g. -1 etc.


    ## puts "mul( #{coefficient} <#{coefficient.class.name}>)"
=begin
    result = self.class.new( nil, nil )
    coefficient.times do
      result += self
    end
    result
=end

    coef = coefficient
    current = self
    result = self.class.new( :infinity )
    while coef > 0
      result += current   if coef.odd?   ##  if (coef & 0b1) > 0
      current = current.double   ## double the point
      coef >>= 1           ## bit shift to the right
    end
    result
  end
Also aliased as: *
require_curve!( other ) click to toggle source
# File lib/elliptic-lite/point.rb, line 83
def require_curve!( other )
  raise ArgumentError, "cannot operate on different curves; expected #{self.class.curve} got #{other.class.curve}"  unless curve?( other )
end