Module: ECDSA

Defined in:
lib/ecdsa/ext/sign_verify.rb,
lib/ecdsa/ext.rb,
lib/ecdsa/ext/point.rb,
lib/ecdsa/ext/version.rb,
lib/ecdsa/ext/abstract_point.rb,
lib/ecdsa/ext/jacobian_point.rb,
lib/ecdsa/ext/projective_point.rb

Overview

A monkey patch to allow signature generation and verification of existing ECDSA with Jacobian coordinates.

Defined Under Namespace

Modules: Ext Classes: Point

Class Method Summary collapse

Class Method Details

.check_signature!(public_key, digest, signature) ⇒ Object



30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
# File 'lib/ecdsa/ext/sign_verify.rb', line 30

def self.check_signature!(public_key, digest, signature)
  group = public_key.group
  field = group.field

  # Step 1: r and s must be in the field and non-zero
  unless field.include?(signature.r)
    raise InvalidSignatureError, "Invalid signature: r is not in the field."
  end
  unless field.include?(signature.s)
    raise InvalidSignatureError, "Invalid signature: s is not in the field."
  end
  if signature.r.zero?
    raise InvalidSignatureError, "Invalid signature: r is zero."
  end
  if signature.s.zero?
    raise InvalidSignatureError, "Invalid signature: s is zero."
  end

  # Step 2 was already performed when the digest of the message was computed.

  # Step 3: Convert octet string to number and take leftmost bits.
  e = normalize_digest(digest, group.bit_length)

  # Step 4
  point_field = PrimeField.new(group.order)
  s_inverted = point_field.inverse(signature.s)
  u1 = point_field.mod(e * s_inverted)
  u2 = point_field.mod(signature.r * s_inverted)

  # Step 5
  r =
    (group.generator.to_jacobian * u1 + public_key.to_jacobian * u2).to_affine
  if r.infinity?
    raise InvalidSignatureError, "Invalid signature: r is infinity in step 5."
  end

  # Steps 6 and 7
  v = point_field.mod r.x

  # Step 8
  if v != signature.r
    raise InvalidSignatureError, "Invalid signature: v does not equal r."
  end

  true
end

.sign(group, private_key, digest, temporary_key) ⇒ Object



5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
# File 'lib/ecdsa/ext/sign_verify.rb', line 5

def self.sign(group, private_key, digest, temporary_key)
  # Second part of step 1: Select ephemeral elliptic curve key pair
  # temporary_key was already selected for us by the caller
  r_point = (group.generator.to_jacobian * temporary_key).to_affine

  # Steps 2 and 3
  point_field = PrimeField.new(group.order)
  r = point_field.mod(r_point.x)
  return nil if r.zero?

  # Step 4, calculating the hash, was already performed by the caller.

  # Step 5
  e = normalize_digest(digest, group.bit_length)

  # Step 6
  s =
    point_field.mod(
      point_field.inverse(temporary_key) * (e + r * private_key)
    )
  return nil if s.zero?

  Signature.new r, s
end