Class: RingSig::Signature

Inherits:
Object
  • Object
show all
Defined in:
lib/ring_sig/signature.rb

Overview

Instances of this class represent RingSig signatures.

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(key_image, c_array, r_array, hasher) ⇒ Signature

Creates a new instance of RingSig::Signature.

Parameters:

  • key_image (ECDSA::Point)
  • c_array (Array<Integer>)
  • r_array (Array<Integer>)
  • hasher (Hasher)


22
23
24
25
26
27
28
29
# File 'lib/ring_sig/signature.rb', line 22

def initialize(key_image, c_array, r_array, hasher)
  @key_image, @c_array, @r_array = key_image, c_array, r_array
  key_image.is_a?(ECDSA::Point) or raise ArgumentError, 'key_image is not an ECDSA::Point.'
  c_array.is_a?(Array) or raise ArgumentError, 'c_array is not an array.'
  r_array.is_a?(Array) or raise ArgumentError, 'r_array is not an array.'

  @hasher = hasher
end

Instance Attribute Details

#c_arrayArray (readonly)

Returns:

  • (Array)


8
9
10
# File 'lib/ring_sig/signature.rb', line 8

def c_array
  @c_array
end

#hasherHasher (readonly)

Returns:



14
15
16
# File 'lib/ring_sig/signature.rb', line 14

def hasher
  @hasher
end

#key_imageECDSA::Point (readonly)

Returns:

  • (ECDSA::Point)


5
6
7
# File 'lib/ring_sig/signature.rb', line 5

def key_image
  @key_image
end

#r_arrayArray (readonly)

Returns:

  • (Array)


11
12
13
# File 'lib/ring_sig/signature.rb', line 11

def r_array
  @r_array
end

Class Method Details

.from_der(der_string, hasher) ⇒ Signature

Creates a new instance of RingSig::Signature from a der string.

Parameters:

  • der_string (String)
  • hasher (Hasher)

Returns:



36
37
38
39
40
41
42
43
44
# File 'lib/ring_sig/signature.rb', line 36

def self.from_der(der_string, hasher)
  asn1 = OpenSSL::ASN1.decode(der_string)

  key_image = ECDSA::Format::PointOctetString.decode(asn1.value[0].value, hasher.group)
  c_array = asn1.value[1].value.map{|i| i.value.to_i}
  r_array = asn1.value[2].value.map{|i| i.value.to_i}

  Signature.new(key_image, c_array, r_array, hasher)
end

.from_hex(hex_string, hasher) ⇒ Signature

Creates a new instance of RingSig::Signature from a hex string.

Parameters:

  • hex_string (String)
  • hasher (Hasher)

Returns:



51
52
53
# File 'lib/ring_sig/signature.rb', line 51

def self.from_hex(hex_string, hasher)
  Signature.from_der([hex_string].pack('H*'), hasher)
end

Instance Method Details

#componentsArray

Returns an array containing key image coordinates, c_array, and r_array.

Returns:

  • (Array)


109
110
111
# File 'lib/ring_sig/signature.rb', line 109

def components
  key_image.coords + c_array + r_array
end

#to_der(opts = {}) ⇒ String

Encodes this signature into a der string. The encoded data contains the key_image, c_array, and r_array. It does not contain the hasher.

Parameters:

  • opts (Hash) (defaults to: {})

Options Hash (opts):

  • :compression (Boolean) — default: true

Returns:

  • (String)

Raises:

  • (ArgumentError)


61
62
63
64
65
66
67
68
69
70
# File 'lib/ring_sig/signature.rb', line 61

def to_der(opts = {})
  compression = opts.delete(:compression) { true }
  raise ArgumentError, "Unknown opts: #{opts.keys.join(', ')}" unless opts.empty?

  OpenSSL::ASN1::Sequence.new([
    OpenSSL::ASN1::OctetString.new(ECDSA::Format::PointOctetString.encode(key_image, compression: compression)),
    OpenSSL::ASN1::Sequence.new(c_array.map{|i| OpenSSL::ASN1::Integer.new(i)}),
    OpenSSL::ASN1::Sequence.new(r_array.map{|i| OpenSSL::ASN1::Integer.new(i)}),
  ]).to_der
end

#to_hex(opts = {}) ⇒ String

Encodes this signature into a hex string. The encoded data contains the key_image, c_array, and r_array. It does not contain the hasher.

Parameters:

  • opts (Hash) (defaults to: {})

Options Hash (opts):

  • :compression (Boolean) — default: true

Returns:

  • (String)

Raises:

  • (ArgumentError)


78
79
80
81
82
83
# File 'lib/ring_sig/signature.rb', line 78

def to_hex(opts = {})
  compression = opts.delete(:compression) { true }
  raise ArgumentError, "Unknown opts: #{opts.keys.join(', ')}" unless opts.empty?

  to_der(compression: compression).unpack('H*').first
end

#verify(message, public_keys) ⇒ Boolean

Verifies this signature against an ordered set of public keys.

Parameters:

  • message (String)
  • public_keys (Array<PublicKey>)

Returns:

  • (Boolean)

    true if the signature verifies, false otherwise.



90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
# File 'lib/ring_sig/signature.rb', line 90

def verify(message, public_keys)
  ll_array = []
  rr_array = []

  public_keys.each_with_index do |k, i|
    ll_array[i] = (hasher.group.generator * r_array[i]) + (k.point * c_array[i])
    rr_array[i] = (hasher.hash_point(k.point) * (r_array[i]) + key_image * c_array[i])
  end

  c_sum = c_array.inject{|a, b| a + b} % hasher.group.order

  message_digest = hasher.hash_string(message)
  challenge = hasher.hash_array([message_digest] + ll_array + rr_array)

  c_sum == challenge
end