Class: ECC::Point

Inherits:
Object
  • Object
show all
Defined in:
lib/elliptic-lite/point.rb

Direct Known Subclasses

S256Point

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(*args) ⇒ Point

Returns a new instance of Point.



50
51
52
53
54
55
56
57
58
59
60
61
62
63
# 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

Instance Attribute Details

#xObject (readonly)

Returns the value of attribute x.



48
49
50
# File 'lib/elliptic-lite/point.rb', line 48

def x
  @x
end

#yObject (readonly)

Returns the value of attribute y.



48
49
50
# File 'lib/elliptic-lite/point.rb', line 48

def y
  @y
end

Class Method Details

.[](*args) ⇒ Object



27
28
29
# File 'lib/elliptic-lite/point.rb', line 27

def self.[]( *args )
  new( *args )
end

.add(*nums) ⇒ Object

convenience helpers - field operations



7
8
9
10
# 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) ⇒ Object



17
# File 'lib/elliptic-lite/point.rb', line 17

def self.div( a, b )         curve.f.div( a, b );  end

.infinityObject

convenience helper / shortcut for infinity - in use anywhere? keep? why? why not?



31
32
33
# 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) ⇒ Object



15
# File 'lib/elliptic-lite/point.rb', line 15

def self.mul( a, b )         curve.f.mul( a, b );   end

.on_curve?(x, y) ⇒ Boolean

Returns:

  • (Boolean)


19
20
21
22
23
24
# 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) ⇒ Object



16
# File 'lib/elliptic-lite/point.rb', line 16

def self.pow( a, exponent )  curve.f.pow( a, exponent ); end

.sub(*nums) ⇒ Object



11
12
13
14
# 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

Instance Method Details

#==(other) ⇒ Object



88
89
90
91
92
93
94
# 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) ⇒ Object

convenience helpers - field operations



40
# File 'lib/elliptic-lite/point.rb', line 40

def _add( *nums )       self.class.add( *nums ); end

#_div(a, b) ⇒ Object



44
# File 'lib/elliptic-lite/point.rb', line 44

def _div( a, b )        self.class.div( a, b );  end

#_mul(a, b) ⇒ Object



42
# File 'lib/elliptic-lite/point.rb', line 42

def _mul( a, b )        self.class.mul( a, b );   end

#_pow(a, exponent) ⇒ Object



43
# File 'lib/elliptic-lite/point.rb', line 43

def _pow( a, exponent ) self.class.pow( a, exponent ); end

#_sub(*nums) ⇒ Object



41
# File 'lib/elliptic-lite/point.rb', line 41

def _sub( *nums )       self.class.sub( *nums ); end

#add(other) ⇒ Object Also known as: +



131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
# 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

#coerce(other) ⇒ Object



97
98
99
100
101
102
# File 'lib/elliptic-lite/point.rb', line 97

def coerce(other)
  args = [self, other]
  ## puts " coerce(#{other} <#{other.class.name}>):"
  ## pp args
  args
end

#curveObject

convenience helpers



38
# File 'lib/elliptic-lite/point.rb', line 38

def curve() self.class.curve; end

#curve?(other) ⇒ Boolean

check for matching curver

Returns:

  • (Boolean)


79
80
81
# File 'lib/elliptic-lite/point.rb', line 79

def curve?( other )  ## check for matching curver
  self.curve == other.curve
end

#doubleObject

double point operation



163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
# 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?Boolean

Returns:

  • (Boolean)


66
67
68
# File 'lib/elliptic-lite/point.rb', line 66

def infinity?
  @x.nil? && @y.nil?
end

#inspectObject



70
71
72
73
74
75
76
# 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) ⇒ Object Also known as: *

note: for rmul-style to work needs coerce method to swap s*p to p*s!!

Raises:

  • (ArgumentError)


104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
# 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

#require_curve!(other) ⇒ Object

Raises:

  • (ArgumentError)


83
84
85
# 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