Class: Noise::State::CipherState

Inherits:
Object
  • Object
show all
Defined in:
lib/noise/state/cipher_state.rb

Overview

A CipherState can encrypt and decrypt data based on its k and n variables:

  • k: A cipher key of 32 bytes (which may be empty). Empty is a special value which indicates k has not yet been initialized.
  • n: An 8-byte (64-bit) unsigned integer nonce.

Constant Summary collapse

MAX_NONCE =
2**64 - 1
TAG_LENGTH =
16

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(cipher:) ⇒ CipherState

Returns a new instance of CipherState.



17
18
19
# File 'lib/noise/state/cipher_state.rb', line 17

def initialize(cipher:)
  @cipher = cipher
end

Instance Attribute Details

#kObject (readonly)

Returns the value of attribute k.



15
16
17
# File 'lib/noise/state/cipher_state.rb', line 15

def k
  @k
end

#nObject (readonly)

Returns the value of attribute n.



15
16
17
# File 'lib/noise/state/cipher_state.rb', line 15

def n
  @n
end

Instance Method Details

#decrypt_with_ad(ad, ciphertext) ⇒ Object



57
58
59
60
61
62
63
64
65
66
67
# File 'lib/noise/state/cipher_state.rb', line 57

def decrypt_with_ad(ad, ciphertext)
  return ciphertext unless key?
  raise Noise::Exceptions::MaxNonceError if @n == MAX_NONCE
  # Without this the ciphers slice a nil authentication tag out of the truncated input.
  raise Noise::Exceptions::DecryptError, 'Ciphertext is shorter than the tag.' if
    ciphertext.bytesize < TAG_LENGTH

  plaintext = @cipher.decrypt(@k, @n, ad, ciphertext)
  @n += 1
  plaintext
end

#encrypt_with_ad(ad, plaintext) ⇒ Object

@return [String] ENCRYPT(k, n++, ad, plaintext) if k is non-empty, otherwise returns plaintext.



47
48
49
50
51
52
53
54
# File 'lib/noise/state/cipher_state.rb', line 47

def encrypt_with_ad(ad, plaintext)
  return plaintext unless key?
  raise Noise::Exceptions::MaxNonceError if @n == MAX_NONCE

  ciphertext = @cipher.encrypt(@k, @n, ad, plaintext)
  @n += 1
  ciphertext
end

#initialize_key(key) ⇒ Object

Parameters:

  • 32 (String)

    bytes key



22
23
24
25
# File 'lib/noise/state/cipher_state.rb', line 22

def initialize_key(key)
  @k = key
  @n = 0
end

#key?Boolean

Returns true if k is non-empty, false otherwise.

Returns:

  • (Boolean)

    true if k is non-empty, false otherwise.



28
29
30
# File 'lib/noise/state/cipher_state.rb', line 28

def key?
  !@k.nil?
end

#nonce=(nonce) ⇒ Object

Sets n, the nonce the next encrypt_with_ad or decrypt_with_ad call uses. This is SetNonce() of the Noise spec, needed to decrypt transport messages that arrive out of order.

The value is checked here because the ciphers pack n into 8 bytes: a value outside the unsigned 64-bit range silently produces a wrong nonce instead of an error.

Parameters:

  • nonce (Integer)

    a value between 0 and MAX_NONCE.

Raises:



40
41
42
43
44
# File 'lib/noise/state/cipher_state.rb', line 40

def nonce=(nonce)
  raise Noise::Exceptions::InvalidNonceError unless nonce.is_a?(Integer) && nonce.between?(0, MAX_NONCE)

  @n = nonce
end

#rekeyString

Replaces k with REKEY(k). n is left as it is, as the Noise spec requires.

Returns:

  • (String)

    the new 32 bytes key.



72
73
74
# File 'lib/noise/state/cipher_state.rb', line 72

def rekey
  @k = @cipher.rekey(@k)
end