Class: RingSig::PrivateKey

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

Overview

Instances of this class represent a private ECDSA key.

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(value, hasher) ⇒ PrivateKey

Creates a new instance of RingSig::PrivateKey.

Parameters:

  • value (Integer)
  • hasher (Hasher)

Raises:

  • (ArgumentError)


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

def initialize(value, hasher)
  raise ArgumentError, "Value is not an integer" unless value.is_a?(Integer)
  raise ArgumentError, "Value is too small" if value < 1
  raise ArgumentError, "Value is too large" if value >= hasher.group.order

  @value = value
  @hasher = hasher
  @public_key = PublicKey.new(hasher.group.generator * value, hasher)
end

Instance Attribute Details

#hasherHasher (readonly)

Returns:



15
16
17
# File 'lib/ring_sig/private_key.rb', line 15

def hasher
  @hasher
end

#public_keyPublicKey (readonly)

Returns:



12
13
14
# File 'lib/ring_sig/private_key.rb', line 12

def public_key
  @public_key
end

#valueInteger (readonly)

The integer value of this private key. A number between 0 and the group's order (non-inclusive).

Returns:

  • (Integer)


9
10
11
# File 'lib/ring_sig/private_key.rb', line 9

def value
  @value
end

Class Method Details

.from_hex(hex_string, hasher) ⇒ PrivateKey

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

Parameters:

  • hex_string (String)
  • hasher (Hasher)

Returns:



36
37
38
# File 'lib/ring_sig/private_key.rb', line 36

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

.from_octet(octet_string, hasher) ⇒ PrivateKey

Creates a new instance of RingSig::PrivateKey from an octet string.

Parameters:

  • octet_string (String)
  • hasher (Hasher)

Returns:



45
46
47
48
# File 'lib/ring_sig/private_key.rb', line 45

def self.from_octet(octet_string, hasher)
  value = ECDSA::Format::FieldElementOctetString.decode(octet_string, hasher.group.field)
  PrivateKey.new(value, hasher)
end

Instance Method Details

#==(other) ⇒ Boolean

Returns true if the private keys are equal.

Returns:

  • (Boolean)

    true if the private keys are equal.



106
107
108
109
# File 'lib/ring_sig/private_key.rb', line 106

def ==(other)
  return false unless other.is_a?(PrivateKey)
  value == other.value && hasher == other.hasher
end

#key_imageECDSA::Point

Returns the key image.

Returns:

  • (ECDSA::Point)

    the key image.



96
97
98
# File 'lib/ring_sig/private_key.rb', line 96

def key_image
  @key_image ||= hasher.hash_point(point) * value
end

#pointECDSA::Point

Returns the public key's point.

Returns:

  • (ECDSA::Point)

    the public key's point.



101
102
103
# File 'lib/ring_sig/private_key.rb', line 101

def point
  public_key.point
end

#sign(message, foreign_keys) ⇒ Array(Signature, Array<PublicKey>)

Signs a message with this key's private key and a set of foreign public keys. The resulting signature can be verified against the ordered set of all public keys used for creating this signature. The signature will also contain a key_image which will be the same for all messages signed with this key.

Parameters:

  • message (String)

    The message to sign.

  • foreign_keys (Array<PublicKey>)

    The foreign keys for the signature.

Returns:

  • (Array(Signature, Array<PublicKey>))

    A pair containing the signature and the set of public keys (in the correct order) for verifying.



76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
# File 'lib/ring_sig/private_key.rb', line 76

def sign(message, foreign_keys)
  raise ArgumentError "Foreign keys must all have the same hasher" unless foreign_keys.all?{ |e| e.hasher == hasher }

  message_digest = hasher.hash_string(message)
  seed = hasher.hash_array([value, message_digest])

  all_keys = hasher.shuffle([self] + foreign_keys, seed)

  q_array, w_array = generate_q_w(all_keys, seed)
  ll_array, rr_array = generate_ll_rr(all_keys, q_array, w_array)
  challenge = hasher.hash_array([message_digest] + ll_array + rr_array)
  c_array, r_array = generate_c_r(all_keys, q_array, w_array, challenge)

  public_keys = all_keys.map(&:public_key)
  signature = Signature.new(key_image, c_array, r_array, hasher)

  [signature, public_keys]
end

#to_hexString

Encodes this private key into an octet string. The encoded data contains only the value. It does not contain the hasher.

Returns:

  • (String)


54
55
56
# File 'lib/ring_sig/private_key.rb', line 54

def to_hex
  to_octet.unpack('H*').first
end

#to_octetString

Encodes this public key into a hex string. The encoded data contains only the value. It does not contain the hasher.

Returns:

  • (String)


62
63
64
# File 'lib/ring_sig/private_key.rb', line 62

def to_octet
  ECDSA::Format::FieldElementOctetString.encode(value, hasher.group.field)
end