Class: WOTS::PrivateKey

Inherits:
Object
  • Object
show all
Extended by:
Util
Includes:
Util
Defined in:
lib/wots/private_key.rb

Overview

WOTS+ private key.

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Methods included from Util

bin_to_hex, hex_string?, hex_to_bin

Constructor Details

#initialize(param, keys) ⇒ PrivateKey

Returns a new instance of PrivateKey.

Raises:

  • (ArgumentError)


10
11
12
13
14
15
16
17
18
19
20
21
# File 'lib/wots/private_key.rb', line 10

def initialize(param, keys)
  raise ArgumentError, "param must be WOTS::Param." unless param.is_a?(WOTS::Param)
  raise ArgumentError, "keys must be Array." unless keys.is_a?(Array)
  raise ArgumentError, "The length of keys must be the same as param#len." unless keys.length == param.len
  keys.each do |key|
    raise ArgumentError, "key must be hex string." unless hex_string?(key)
    raise ArgumentError, "key must be #{param.n} bytes." unless hex_to_bin(key).bytesize == param.n
  end

  @param = param
  @keys = keys
end

Instance Attribute Details

#keysObject (readonly)

Returns the value of attribute keys.



8
9
10
# File 'lib/wots/private_key.rb', line 8

def keys
  @keys
end

#paramObject (readonly)

Returns the value of attribute param.



7
8
9
# File 'lib/wots/private_key.rb', line 7

def param
  @param
end

Class Method Details

.from_seed(param, seed) ⇒ Object

Generate private key using seed. It must be generated with a cryptographically secure random number generator.

Parameters:

  • param (WOTS::Param)
  • seed (String)

    The secret seed. Hex string of param.n bytes.

Raises:

  • ArgumentError



28
29
30
31
32
33
34
35
36
37
38
39
# File 'lib/wots/private_key.rb', line 28

def self.from_seed(param, seed)
  raise ArgumentError, "param must be WOTS::Param." unless param.is_a?(WOTS::Param)
  raise ArgumentError, "seed must be hex string." unless hex_string?(seed)
  raise ArgumentError, "seed must be #{param.n} bytes." unless hex_to_bin(seed).bytesize == param.n
  raise ArgumentError, "len parameter too large." if param.len.bit_length > 16

  keys = param.len.times.map do |i|
    param.prf(seed, bin_to_hex(param.to_byte(i, 32)))
  end

  PrivateKey.new(param, keys)
end

Instance Method Details

#inspectString

Redacted inspect. The default implementation prints every instance variable, which would write the whole private key into logs, exception reports and REPL output.

Returns:

  • (String)


76
77
78
# File 'lib/wots/private_key.rb', line 76

def inspect
  "#<WOTS::PrivateKey param=#{param.name} w=#{param.w} keys=[REDACTED]>"
end

#sign(pub_seed, message) ⇒ WOTS::Signature

Generate signature. WOTS+ is a one-time signature scheme: this private key must never be used to sign more than one message.

Parameters:

  • pub_seed (String)

    The Public seed. Hex string of param.n bytes.

  • message (String)

    The message to be signed. Hex string of param.n bytes.

Returns:

Raises:

  • ArgumentError



48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
# File 'lib/wots/private_key.rb', line 48

def sign(pub_seed, message)
  raise ArgumentError, 'pub_seed must be hex string.' unless hex_string?(pub_seed)
  raise ArgumentError, "pub_seed must be #{param.n} bytes." unless hex_to_bin(pub_seed).bytesize == param.n
  raise ArgumentError, "message must be hex string." unless hex_string?(message)
  raise ArgumentError, "message must be #{param.n} bytes." unless hex_to_bin(message).bytesize == param.n

  addr = Address.new

  # Convert message to base w
  base_w = param.base_w(message, param.len1)

  # Compute checksum
  c_sum = param.compute_checksum(base_w)

  base_w = base_w + param.base_w(c_sum, param.len2)

  sigs = param.len.times.map do |i|
    addr.chain_addr = i
    param.chain(keys[i], 0, base_w[i], pub_seed, addr)
  end

  Signature.new(param, sigs)
end