Class: BitcoinAddrgen::Point

Inherits:
Object
  • Object
show all
Defined in:
lib/bitcoin_addrgen/addrgen.rb

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(curve, x, y, order = nil) ⇒ Point

Returns a new instance of Point.



56
57
58
59
60
61
62
63
64
65
66
67
# File 'lib/bitcoin_addrgen/addrgen.rb', line 56

def initialize(curve, x, y, order = nil)
  @curve = curve
  @x = x
  @y = y
  @order = order
  if @curve and @curve.instance_of?(Curve)
    raise Exception, 'Curve does not contain point' if !@curve.contains(@x, @y)
    if @order != nil
      raise Exception, 'Self*Order must equal infinity' if (Point.cmp(Point.mul(order, self), :infinity) != 0)
    end
  end
end

Instance Attribute Details

#curveObject (readonly)

Returns the value of attribute curve.



54
55
56
# File 'lib/bitcoin_addrgen/addrgen.rb', line 54

def curve
  @curve
end

#orderObject (readonly)

Returns the value of attribute order.



54
55
56
# File 'lib/bitcoin_addrgen/addrgen.rb', line 54

def order
  @order
end

#xObject (readonly)

Returns the value of attribute x.



54
55
56
# File 'lib/bitcoin_addrgen/addrgen.rb', line 54

def x
  @x
end

#yObject (readonly)

Returns the value of attribute y.



54
55
56
# File 'lib/bitcoin_addrgen/addrgen.rb', line 54

def y
  @y
end

Class Method Details

.add(p1, p2) ⇒ Object



85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
# File 'lib/bitcoin_addrgen/addrgen.rb', line 85

def self.add(p1, p2)

  return p1 if Point.cmp(p2, :infinity) == 0 and p1.instance_of?(Point)
  return p2 if Point.cmp(p1, :infinity) == 0 and p2.instance_of?(Point)
  return :infinity if Point.cmp(p1, :infinity) == 0 and Point.cmp(p2, :infinity) == 0

  if Curve.cmp(p1.curve, p2.curve) == 0
    if p1.x == p2.x
      if (p1.y + p2.y).fmod(p1.curve.prime) == 0
        return :infinity
      else
        return Point.double(p1)
      end
    end
    p = p1.curve.prime
    l = (p2.y - p1.y) * (p2.x - p1.x).invert(p)
    x3 = (l ** 2 - p1.x - p2.x).fmod(p)
    y3 = (l * (p1.x - x3) - p1.y).fmod(p)
    p3 = Point.new(p1.curve, x3, y3)
    return p3
  else
    raise Exception, 'Elliptic curves do not match'
  end
end

.cmp(p1, p2) ⇒ Object



69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
# File 'lib/bitcoin_addrgen/addrgen.rb', line 69

def self.cmp(p1, p2)
  if !p1.instance_of?(Point)
    return 1 if p2.instance_of?(Point)
    return 0 if !p2.instance_of?(Point)
  end
  if !p2.instance_of?(Point)
    return 1 if p1.instance_of?(Point)
    return 0 if !p1.instance_of?(Point)
  end
  if p1.x == p2.x and p1.y == p2.y and Curve.cmp(p1.curve, p2.curve)
    return 0
  else
    return 1
  end
end

.double(p1) ⇒ Object



140
141
142
143
144
145
146
147
148
149
150
151
# File 'lib/bitcoin_addrgen/addrgen.rb', line 140

def self.double(p1)
  p = p1.curve.prime
  a = p1.curve.a
  inverse = (2 * p1.y).invert(p)
  three_x2 = 3 * (p1.x ** 2)
  l = ((three_x2 + a) * inverse).fmod(p)
  x3 = (l ** 2 - 2 * p1.x).fmod(p)
  y3 = (l * (p1.x - x3) - p1.y).fmod(p)
  y3 = p + y3 if 0 > y3
  p3 = Point.new(p1.curve, x3, y3)
  p3
end

.leftmost_bit(x) ⇒ Object



130
131
132
133
134
135
136
137
138
# File 'lib/bitcoin_addrgen/addrgen.rb', line 130

def self.leftmost_bit(x)
  if x > GMP::Z.new(0)
    result = GMP::Z.new(1)
    while result <= x
      result *= 2
    end
    return result.tdiv(2)
  end
end

.mul(x2, p1) ⇒ Object



110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
# File 'lib/bitcoin_addrgen/addrgen.rb', line 110

def self.mul(x2, p1)
  e = x2
  return :infinity if Point.cmp(p1, :infinity) == 0
  e = e.fmod(p1.order) if p1.order != nil
  return :infinity if e == GMP::Z.new(0)
  if e > GMP::Z.new(0)
    e3 = 3 * e
    negative_self = Point.new(p1.curve, p1.x, -p1.y, p1.order)
    i = Point.leftmost_bit(e3).tdiv(2)
    result = p1
    while i > GMP::Z.new(1)
      result = Point.double(result)
      result = Point.add(result, p1) if (e3 & i) != GMP::Z.new(0) and (e & i) == GMP::Z.new(0)
      result = Point.add(result, negative_self) if (e3 & i) == GMP::Z.new(0) and (e & i) != GMP::Z.new(0)
      i = i.tdiv(2)
    end
    return result
  end
end