Class: H2C::Expander::XMD

Inherits:
Object
  • Object
show all
Defined in:
lib/h2c/expander/xmd.rb

Overview

Expander::XMD produces a uniformly random byte string using a cryptographic hash function H that outputs b bits.

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(func, dst) ⇒ XMD

Constructor

Parameters:

  • func (String)

    Hash function name. Currently supported by ‘SHA256’ and ‘SHA512’

  • dst (String)

    Domain separation tag with binary format.



12
13
14
15
# File 'lib/h2c/expander/xmd.rb', line 12

def initialize(func, dst)
  @dst = dst
  @digest = Digest(func).new
end

Instance Attribute Details

#digestObject (readonly)

Returns the value of attribute digest.



8
9
10
# File 'lib/h2c/expander/xmd.rb', line 8

def digest
  @digest
end

#dstObject (readonly)

Returns the value of attribute dst.



8
9
10
# File 'lib/h2c/expander/xmd.rb', line 8

def dst
  @dst
end

Instance Method Details

#construct_dst_primeString

Construct DST prime.

Returns:

  • (String)

    DST prime



62
63
64
65
66
67
68
69
70
# File 'lib/h2c/expander/xmd.rb', line 62

def construct_dst_prime
  dst_prime =
    if dst.bytesize > MAX_DST_LENGTH
      digest.digest(LONG_DST_PREFIX + dst)
    else
      dst
    end
  dst_prime + [dst_prime.bytesize].pack("C")
end

#expand(msg, len) ⇒ String

Parameters:

  • msg (String)

    The message to be expanded with binary format.

  • len (Integer)

    The length of the requested output in bytes.

Returns:

  • (String)

    Expanded message.

Raises:



23
24
25
26
27
28
29
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
# File 'lib/h2c/expander/xmd.rb', line 23

def expand(msg, len)
  b_len = digest.digest_length
  ell = (len + b_len - 1) / b_len
  dst_prime = construct_dst_prime

  if ell >= 0xff || len >= 0xffff || dst_prime.bytesize >= 0xff
    raise H2C::Error, "requested too many bytes"
  end
  lib_str = [(len >> 8) & 0xFF, (len & 0xff)].pack("CC")
  z_pad = Array.new(digest.block_length, 0)

  digest.reset
  digest.update(z_pad.pack("C*"))
  digest.update(msg)
  digest.update(lib_str)
  digest.update([0].pack("C"))
  digest.update(dst_prime)

  b0 = digest.digest
  digest.reset
  digest.update(b0)
  digest.update([1].pack("C"))
  digest.update(dst_prime)

  bi = digest.digest
  pseudo = bi
  (2..(ell + 1)).each do |i|
    digest.reset
    digest.update(Expander.xor(b0, bi))
    digest.update([i].pack("C"))
    digest.update(dst_prime)
    bi = digest.digest
    pseudo += bi
  end
  pseudo[0...len]
end