Class: Noise::State::HandshakeState
- Inherits:
-
Object
- Object
- Noise::State::HandshakeState
- Defined in:
- lib/noise/state/handshake_state.rb
Overview
A HandshakeState object contains a SymmetricState plus the following variables, any of which may be empty. Empty is a special value which indicates the variable has not yet been initialized.
s: The local static key pair e: The local ephemeral key pair rs: The remote party’s static public key re: The remote party’s ephemeral public key
A HandshakeState also has variables to track its role, and the remaining portion of the handshake pattern:
initiator: A boolean indicating the initiator or responder role.
message_patterns: A sequence of message patterns.
Each message pattern is a sequence of tokens from the set ("e", "s", "ee", "es", "se", "ss").
Instance Attribute Summary collapse
-
#e ⇒ Object
readonly
Returns the value of attribute e.
-
#message_patterns ⇒ Object
readonly
Returns the value of attribute message_patterns.
-
#re ⇒ Object
readonly
Returns the value of attribute re.
-
#rs ⇒ Object
readonly
Returns the value of attribute rs.
-
#s ⇒ Object
readonly
Returns the value of attribute s.
-
#symmetric_state ⇒ Object
readonly
Returns the value of attribute symmetric_state.
Instance Method Summary collapse
- #expected_message_length(payload_size) ⇒ Object
-
#initialize(connection, protocol, initiator, prologue, local_keypairs, remote_keys) ⇒ HandshakeState
constructor
A new instance of HandshakeState.
-
#read_message(message, payload_buffer) ⇒ Object
Takes a byte sequence containing a Noise handshake message, and a payload_buffer to write the message’s plaintext payload into.
-
#write_message(payload, message_buffer) ⇒ Object
Takes a payload byte sequence which may be zero-length, and a message_buffer to write the output into.
Constructor Details
#initialize(connection, protocol, initiator, prologue, local_keypairs, remote_keys) ⇒ HandshakeState
Returns a new instance of HandshakeState.
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 59 60 61 62 63 64 |
# File 'lib/noise/state/handshake_state.rb', line 23 def initialize(connection, protocol, initiator, prologue, local_keypairs, remote_keys) @connection = connection @protocol = protocol @symmetric_state = SymmetricState.new @symmetric_state.initialize_symmetric(@protocol, connection) @symmetric_state.mix_hash(prologue) @initiator = initiator @s = local_keypairs[:s] @e = local_keypairs[:e] @rs = remote_keys[:rs] @re = remote_keys[:re] get_local_keypair = ->(token) { instance_variable_get('@' + token).public_key } get_remote_keypair = ->(token) { instance_variable_get('@r' + token) } if initiator initiator_keypair_getter = get_local_keypair responder_keypair_getter = get_remote_keypair else initiator_keypair_getter = get_remote_keypair responder_keypair_getter = get_local_keypair end # Sets message_patterns to the message patterns from handshake_pattern @message_patterns = @protocol.pattern.tokens.dup @protocol.pattern.&.map do |token| keypair = initiator_keypair_getter.call(token) @symmetric_state.mix_hash(keypair) end if @protocol.pattern.fallback = @message_patterns.delete_at(0).first public_key = initiator_keypair_getter.call() @symmetric_state.mix_hash(public_key) end @protocol.pattern.&.map do |token| keypair = responder_keypair_getter.call(token) @symmetric_state.mix_hash(keypair) end end |
Instance Attribute Details
#e ⇒ Object (readonly)
Returns the value of attribute e.
21 22 23 |
# File 'lib/noise/state/handshake_state.rb', line 21 def e @e end |
#message_patterns ⇒ Object (readonly)
Returns the value of attribute message_patterns.
20 21 22 |
# File 'lib/noise/state/handshake_state.rb', line 20 def @message_patterns end |
#re ⇒ Object (readonly)
Returns the value of attribute re.
21 22 23 |
# File 'lib/noise/state/handshake_state.rb', line 21 def re @re end |
#rs ⇒ Object (readonly)
Returns the value of attribute rs.
21 22 23 |
# File 'lib/noise/state/handshake_state.rb', line 21 def rs @rs end |
#s ⇒ Object (readonly)
Returns the value of attribute s.
21 22 23 |
# File 'lib/noise/state/handshake_state.rb', line 21 def s @s end |
#symmetric_state ⇒ Object (readonly)
Returns the value of attribute symmetric_state.
20 21 22 |
# File 'lib/noise/state/handshake_state.rb', line 20 def symmetric_state @symmetric_state end |
Instance Method Details
#expected_message_length(payload_size) ⇒ Object
66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 |
# File 'lib/noise/state/handshake_state.rb', line 66 def (payload_size) has_key = @symmetric_state.cipher_state.key? pattern = @message_patterns.first len = pattern.inject(0) do |l, token| case token when 'e' l += @protocol.dh_fn.dhlen has_key = true if @protocol.psk_handshake? when 's' l += @protocol.dh_fn.dhlen l += 16 if has_key when 'ee', 'es', 'se', 'ss', 'psk' has_key = true end l end len += payload_size len += 16 if has_key len end |
#read_message(message, payload_buffer) ⇒ Object
Takes a byte sequence containing a Noise handshake message, and a payload_buffer to write the message’s plaintext payload into
121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 |
# File 'lib/noise/state/handshake_state.rb', line 121 def (, payload_buffer) pattern = @message_patterns.shift dh_fn = @protocol.dh_fn len = dh_fn.dhlen pattern.each do |token| case token when 'e' @re = [0...len] if @re.nil? = [len..-1] @symmetric_state.mix_hash(@re) @symmetric_state.mix_key(@re) if @protocol.psk_handshake? when 's' offset = @connection.cipher_state_handshake.key? ? 16 : 0 temp = [0...len + offset] = [(len + offset)..-1] @rs = @symmetric_state.decrypt_and_hash(temp) when 'ee' @symmetric_state.mix_key(dh_fn.dh(@e.private_key, @re)) when 'es' private_key, public_key = @initiator ? [@e.private_key, @rs] : [@s.private_key, @re] @symmetric_state.mix_key(dh_fn.dh(private_key, public_key)) when 'se' private_key, public_key = @initiator ? [@s.private_key, @re] : [@e.private_key, @rs] @symmetric_state.mix_key(dh_fn.dh(private_key, public_key)) when 'ss' @symmetric_state.mix_key(dh_fn.dh(@s.private_key, @rs)) when 'psk' @symmetric_state.mix_key_and_hash(@connection.psks.shift) end end payload_buffer << @symmetric_state.decrypt_and_hash() @symmetric_state.split if @message_patterns.empty? end |
#write_message(payload, message_buffer) ⇒ Object
Takes a payload byte sequence which may be zero-length, and a message_buffer to write the output into
88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 |
# File 'lib/noise/state/handshake_state.rb', line 88 def (payload, ) pattern = @message_patterns.shift dh_fn = @protocol.dh_fn pattern.each do |token| case token when 'e' @e = dh_fn.generate_keypair if @e.nil? << @e.public_key @symmetric_state.mix_hash(@e.public_key) @symmetric_state.mix_key(@e.public_key) if @protocol.psk_handshake? when 's' << @symmetric_state.encrypt_and_hash(@s.public_key) when 'ee' @symmetric_state.mix_key(dh_fn.dh(@e.private_key, @re)) when 'es' private_key, public_key = @initiator ? [@e.private_key, @rs] : [@s.private_key, @re] @symmetric_state.mix_key(dh_fn.dh(private_key, public_key)) when 'se' private_key, public_key = @initiator ? [@s.private_key, @re] : [@e.private_key, @rs] @symmetric_state.mix_key(dh_fn.dh(private_key, public_key)) when 'ss' @symmetric_state.mix_key(dh_fn.dh(@s.private_key, @rs)) when 'psk' @symmetric_state.mix_key_and_hash(@connection.psks.shift) end end << @symmetric_state.encrypt_and_hash(payload) @symmetric_state.split if @message_patterns.empty? end |