noise-ruby 0.7.4 → 0.8.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: ecfac7577c0e2c49956249076aa5351f4c002fc135341f4bb21b9279cf54ba56
4
- data.tar.gz: d65b64e5ce9df56c2ad0599a75fabb4070b9739ff7313961ec0e6b3ab11b68cd
3
+ metadata.gz: 9016d0344507e501e7a92acab0142a15b1d472303e6dfd92ff5bd0a89e135d34
4
+ data.tar.gz: 68cc424b0c8e91006df86737fca0d0f7d5ea723a02ac8335a65ad0e7e746ffd9
5
5
  SHA512:
6
- metadata.gz: be99c89230f89d0f286a4dc1da6aadb10ce06ba64206325381cca8032ae71abec0406d1a957fafe0946791f72f346ef23cce019c74868605280e5fa357287e18
7
- data.tar.gz: b11a5a496096daf4f4abe9dbfb6f2bba693ec4b5be2c680be6b42b450d7be89a7f119535f20e46bba7429c1f5024ebd62896922c7a944c24a76d951e2df8df4c
6
+ metadata.gz: 2c6c80f4b7c4bbafe3ff40788639c8b03bac62bcc75646ce13de59960abafd1fbc0beb68903eb8ca0120853afc46c972cac1428572b52bbb8c9b5019a75af2e9
7
+ data.tar.gz: 92b6ad660ee6e22acb87dbcd85925fed0bee616e87b8175d1408dfa26bcb0c8fc146a876fa21237bb74b14cc51759a0ed6da320a758d00f1f51991cc899b7bfa
@@ -11,14 +11,14 @@ module Noise
11
11
  def initialize(name, keypairs: { s: nil, e: nil, rs: nil, re: nil })
12
12
  @protocol = Protocol.create(name)
13
13
 
14
- @keypairs = keypairs
15
14
  # parameter keypairs[:e] and keypairs[:s] are strings, so should convert Noise::Key object.
16
- @keypairs[:e] = @protocol.dh_fn.class.from_private(@keypairs[:e]) if @keypairs[:e]
17
- @keypairs[:s] = @protocol.dh_fn.class.from_private(@keypairs[:s]) if @keypairs[:s]
18
-
15
+ @local_keypairs = {}
16
+ @local_keypairs[:e] = @protocol.dh_fn.class.from_private(keypairs[:e]) if keypairs[:e]
17
+ @local_keypairs[:s] = @protocol.dh_fn.class.from_private(keypairs[:s]) if keypairs[:s]
18
+ @remote_keys = { rs: keypairs[:rs], re: keypairs[:re] }
19
19
  @handshake_started = false
20
20
  @handshake_finished = false
21
- @next_message = nil
21
+ initialize_next_message
22
22
  end
23
23
 
24
24
  def start_handshake
@@ -27,13 +27,24 @@ module Noise
27
27
  @handshake_started = true
28
28
  end
29
29
 
30
+ def fallback(fallback_name)
31
+ @protocol = Protocol.create(fallback_name)
32
+ @handshake_started = false
33
+ @handshake_finished = false
34
+ # initialize_next_message
35
+ @local_keypairs = { e: @handshake_state.e, s: @handshake_state.s }
36
+ @remote_keys = { re: @handshake_state.re, rs: @handshake_state.rs }
37
+ start_handshake
38
+ end
39
+
30
40
  def initialise_handshake_state
31
41
  @handshake_state = Noise::State::HandshakeState.new(
32
42
  self,
33
43
  protocol,
34
44
  initiator?,
35
45
  @prologue,
36
- @keypairs
46
+ @local_keypairs,
47
+ @remote_keys
37
48
  )
38
49
  @symmetric_state = @handshake_state.symmetric_state
39
50
  @cipher_state_handshake = @symmetric_state.cipher_state
@@ -43,7 +54,6 @@ module Noise
43
54
  # Call NoiseConnection.start_handshake first
44
55
  raise Noise::Exceptions::NoiseHandshakeError unless @handshake_started
45
56
  raise Noise::Exceptions::NoiseHandshakeError if @next_message != :write
46
- # Handshake finished. NoiseConnection.encrypt should be used now
47
57
  raise Noise::Exceptions::NoiseHandshakeError if @handshake_finished
48
58
  @next_message = :read
49
59
  buffer = +''
@@ -56,7 +66,6 @@ module Noise
56
66
  # Call NoiseConnection.start_handshake first
57
67
  raise Noise::Exceptions::NoiseHandshakeError unless @handshake_started
58
68
  raise Noise::Exceptions::NoiseHandshakeError if @next_message != :read
59
- # Handshake finished. NoiseConnection.encrypt should be used now
60
69
  raise Noise::Exceptions::NoiseHandshakeError if @handshake_finished
61
70
 
62
71
  @next_message = :write
@@ -68,32 +77,28 @@ module Noise
68
77
 
69
78
  def encrypt(data)
70
79
  raise Noise::Exceptions::NoiseHandshakeError unless @handshake_finished
71
- # raise Noise::Exceptions::NoiseInvalidMessage
72
80
  @cipher_state_encrypt.encrypt_with_ad('', data)
73
81
  end
74
82
 
75
83
  def decrypt(data)
76
84
  raise Noise::Exceptions::NoiseHandshakeError unless @handshake_finished
77
- # raise Noise::Exceptions::NoiseInvalidMessage
78
85
  @cipher_state_decrypt.decrypt_with_ad('', data)
79
86
  end
80
87
 
81
88
  def validate_psk!
82
89
  # Invalid psk length! Has to be 32 bytes long
83
90
  raise Noise::Exceptions::NoisePSKError if @psks.any? { |psk| psk.bytesize != 32 }
84
- # Bad number of PSKs provided to this protocol! {} are required,
85
- # given {}'.format(self.pattern.psk_count, len(self.psks)))
86
91
  raise Noise::Exceptions::NoisePSKError if @protocol.pattern.psk_count != @psks.count
87
92
  end
88
93
 
89
94
  def valid_keypairs?
90
- @protocol.pattern.required_keypairs(initiator?).any? { |keypair| !@keypairs[keypair] }
95
+ keypairs = @local_keypairs.merge(@remote_keys)
96
+ @protocol.pattern.required_keypairs(initiator?).any? { |keypair| !keypairs[keypair] }
91
97
  end
92
98
 
93
99
  def validate
94
100
  validate_psk! if psk_handshake?
95
101
 
96
- # 'Keypair {} has to be set for chosen handshake pattern'.format(keypair)
97
102
  raise Noise::Exceptions::NoiseValidationError if valid_keypairs?
98
103
  true
99
104
  end
@@ -3,8 +3,7 @@
3
3
  module Noise
4
4
  module Connection
5
5
  class Initiator < Base
6
- def initialize(name, keypairs: { s: nil, e: nil, rs: nil, re: nil })
7
- super
6
+ def initialize_next_message
8
7
  @next_message = :write
9
8
  end
10
9
 
@@ -15,7 +14,7 @@ module Noise
15
14
  def handshake_done(c1, c2)
16
15
  super
17
16
  @cipher_state_encrypt = c1
18
- @cipher_state_decrypt = @protocol.pattern.one_way ? nil : c2
17
+ @cipher_state_decrypt = @protocol.pattern.one_way? ? nil : c2
19
18
  end
20
19
  end
21
20
  end
@@ -3,8 +3,7 @@
3
3
  module Noise
4
4
  module Connection
5
5
  class Responder < Base
6
- def initialize(name, keypairs: { s: nil, e: nil, rs: nil, re: nil })
7
- super
6
+ def initialize_next_message
8
7
  @next_message = :read
9
8
  end
10
9
 
@@ -15,7 +14,7 @@ module Noise
15
14
  def handshake_done(c1, c2)
16
15
  super
17
16
  @cipher_state_decrypt = c1
18
- @cipher_state_encrypt = @protocol.pattern.one_way ? nil : c2
17
+ @cipher_state_encrypt = @protocol.pattern.one_way? ? nil : c2
19
18
  end
20
19
  end
21
20
  end
@@ -11,5 +11,6 @@ module Noise
11
11
  autoload :NoiseValidationError, 'noise/exceptions/noise_validation_error'
12
12
  autoload :NoisePSKError, 'noise/exceptions/noise_psk_error'
13
13
  autoload :PSKValueError, 'noise/exceptions/psk_value_error'
14
+ autoload :UnsupportedModifierError, 'noise/exceptions/unsupported_modifier_error'
14
15
  end
15
16
  end
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Noise
4
+ module Exceptions
5
+ class UnsupportedModifierError < RuntimeError
6
+ end
7
+ end
8
+ end
@@ -12,10 +12,10 @@ module Noise
12
12
  end
13
13
 
14
14
  class Pattern
15
- attr_reader :one_way, :tokens, :modifiers, :psk_count
15
+ attr_reader :tokens, :modifiers, :psk_count, :fallback
16
16
 
17
17
  def self.create(name)
18
- pattern_set = name.scan(/([A-Z]+)([^A-Z]*)/)&.first
18
+ pattern_set = name.scan(/([A-Z1]+)([^A-Z]*)/)&.first
19
19
  pattern = pattern_set&.first
20
20
  modifiers = pattern_set[1].split('+')
21
21
  class_name = "Noise::Pattern#{pattern}"
@@ -27,7 +27,6 @@ module Noise
27
27
  @pre_messages = [[], []]
28
28
  @tokens = []
29
29
  @name = ''
30
- @one_way = false
31
30
  @psk_count = 0
32
31
  @modifiers = modifiers
33
32
  end
@@ -37,6 +36,7 @@ module Noise
37
36
  if modifier.start_with?('psk')
38
37
  index = modifier.gsub(/psk/, '').to_i
39
38
  raise Noise::Exceptions::PSKValueError if index / 2 > @tokens.size
39
+
40
40
  if index.zero?
41
41
  @tokens[0].insert(0, Token::PSK)
42
42
  else
@@ -44,9 +44,9 @@ module Noise
44
44
  end
45
45
  @psk_count += 1
46
46
  elsif modifier == 'fallback'
47
- raise NotImplementedError
47
+ @fallback = true
48
48
  else
49
- raise Noise::Exceptions::PSKValueError
49
+ raise Noise::Exceptions::UnsupportedModifierError
50
50
  end
51
51
  end
52
52
  end
@@ -59,14 +59,14 @@ module Noise
59
59
  def required_keypairs_of_initiator
60
60
  required = []
61
61
  required << :s if %w[K X I].include?(@name[0])
62
- required << :rs if @one_way || @name[1] == 'K'
62
+ required << :rs if one_way? || @name[1] == 'K'
63
63
  required
64
64
  end
65
65
 
66
66
  def required_keypairs_of_responder
67
67
  required = []
68
68
  required << :rs if @name[0] == 'K'
69
- required << :s if @one_way || %w[K X].include?(@name[1])
69
+ required << :s if one_way? || %w[K X].include?(@name[1])
70
70
  required
71
71
  end
72
72
 
@@ -77,12 +77,19 @@ module Noise
77
77
  def responder_pre_messages
78
78
  @pre_messages[1].dup
79
79
  end
80
+
81
+ def one_way?
82
+ false
83
+ end
80
84
  end
81
85
 
82
86
  class OneWayPattern < Pattern
83
87
  def initialize(modifiers)
84
88
  super(modifiers)
85
- @one_way = true
89
+ end
90
+
91
+ def one_way?
92
+ true
86
93
  end
87
94
  end
88
95
 
@@ -215,4 +222,205 @@ module Noise
215
222
  @tokens = [[Token::E, Token::S], [Token::E, Token::EE, Token::SE, Token::S, Token::ES]]
216
223
  end
217
224
  end
225
+
226
+ class DeferredPattern < Pattern
227
+ end
228
+
229
+ class PatternNK1 < DeferredPattern
230
+ def initialize(modifiers)
231
+ super(modifiers)
232
+ @name = 'NK1'
233
+ @pre_messages = [[], [Token::S]]
234
+ @tokens = [[Token::E], [Token::E, Token::EE, Token::ES]]
235
+ end
236
+ end
237
+
238
+ class PatternNX1 < DeferredPattern
239
+ def initialize(modifiers)
240
+ super(modifiers)
241
+ @name = 'NX1'
242
+ @tokens = [[Token::E], [Token::E, Token::EE, Token::S], [Token::ES]]
243
+ end
244
+ end
245
+
246
+ class PatternX1N < DeferredPattern
247
+ def initialize(modifiers)
248
+ super(modifiers)
249
+ @name = 'X1N'
250
+ @tokens = [[Token::E], [Token::E, Token::EE], [Token::S], [Token::SE]]
251
+ end
252
+ end
253
+
254
+ class PatternX1K < DeferredPattern
255
+ def initialize(modifiers)
256
+ super(modifiers)
257
+ @name = 'X1K'
258
+ @pre_messages = [[], [Token::S]]
259
+ @tokens = [[Token::E, Token::ES], [Token::E, Token::EE], [Token::S], [Token::SE]]
260
+ end
261
+ end
262
+
263
+ class PatternXK1 < DeferredPattern
264
+ def initialize(modifiers)
265
+ super(modifiers)
266
+ @name = 'XK1'
267
+ @pre_messages = [[], [Token::S]]
268
+ @tokens = [[Token::E], [Token::E, Token::EE, Token::ES], [Token::S, Token::SE]]
269
+ end
270
+ end
271
+
272
+ class PatternX1K1 < DeferredPattern
273
+ def initialize(modifiers)
274
+ super(modifiers)
275
+ @name = 'X1K1'
276
+ @pre_messages = [[], [Token::S]]
277
+ @tokens = [[Token::E], [Token::E, Token::EE, Token::ES], [Token::S], [Token::SE]]
278
+ end
279
+ end
280
+
281
+ class PatternX1X < DeferredPattern
282
+ def initialize(modifiers)
283
+ super(modifiers)
284
+ @name = 'X1X'
285
+ @tokens = [[Token::E], [Token::E, Token::EE, Token::S, Token::ES], [Token::S], [Token::SE]]
286
+ end
287
+ end
288
+
289
+ class PatternXX1 < DeferredPattern
290
+ def initialize(modifiers)
291
+ super(modifiers)
292
+ @name = 'XX1'
293
+ @tokens = [[Token::E], [Token::E, Token::EE, Token::S], [Token::ES, Token::S, Token::SE]]
294
+ end
295
+ end
296
+
297
+ class PatternX1X1 < DeferredPattern
298
+ def initialize(modifiers)
299
+ super(modifiers)
300
+ @name = 'X1X1'
301
+ @tokens = [[Token::E], [Token::E, Token::EE, Token::S], [Token::ES, Token::S], [Token::SE]]
302
+ end
303
+ end
304
+
305
+ class PatternK1N < DeferredPattern
306
+ def initialize(modifiers)
307
+ super(modifiers)
308
+ @name = 'K1N'
309
+ @pre_messages = [[Token::S], []]
310
+ @tokens = [[Token::E], [Token::E, Token::EE], [Token::SE]]
311
+ end
312
+ end
313
+
314
+ class PatternK1K < DeferredPattern
315
+ def initialize(modifiers)
316
+ super(modifiers)
317
+ @name = 'K1K'
318
+ @pre_messages = [[Token::S], [Token::S]]
319
+ @tokens = [[Token::E, Token::ES], [Token::E, Token::EE], [Token::SE]]
320
+ end
321
+ end
322
+
323
+ class PatternKK1 < DeferredPattern
324
+ def initialize(modifiers)
325
+ super(modifiers)
326
+ @name = 'KK1'
327
+ @pre_messages = [[Token::S], [Token::S]]
328
+ @tokens = [[Token::E], [Token::E, Token::EE, Token::SE, Token::ES]]
329
+ end
330
+ end
331
+
332
+ class PatternK1K1 < DeferredPattern
333
+ def initialize(modifiers)
334
+ super(modifiers)
335
+ @name = 'K1K1'
336
+ @pre_messages = [[Token::S], [Token::S]]
337
+ @tokens = [[Token::E], [Token::E, Token::EE, Token::ES], [Token::SE]]
338
+ end
339
+ end
340
+
341
+ class PatternK1X < DeferredPattern
342
+ def initialize(modifiers)
343
+ super(modifiers)
344
+ @name = 'K1X'
345
+ @pre_messages = [[Token::S], []]
346
+ @tokens = [[Token::E], [Token::E, Token::EE, Token::S, Token::ES], [Token::SE]]
347
+ end
348
+ end
349
+
350
+ class PatternKX1 < DeferredPattern
351
+ def initialize(modifiers)
352
+ super(modifiers)
353
+ @name = 'KX1'
354
+ @pre_messages = [[Token::S], []]
355
+ @tokens = [[Token::E], [Token::E, Token::EE, Token::SE, Token::S], [Token::ES]]
356
+ end
357
+ end
358
+
359
+ class PatternK1X1 < DeferredPattern
360
+ def initialize(modifiers)
361
+ super(modifiers)
362
+ @name = 'K1X1'
363
+ @pre_messages = [[Token::S], []]
364
+ @tokens = [[Token::E], [Token::E, Token::EE, Token::S], [Token::SE, Token::ES]]
365
+ end
366
+ end
367
+
368
+ class PatternI1N < DeferredPattern
369
+ def initialize(modifiers)
370
+ super(modifiers)
371
+ @name = 'I1N'
372
+ @tokens = [[Token::E, Token::S], [Token::E, Token::EE], [Token::SE]]
373
+ end
374
+ end
375
+
376
+ class PatternI1K < DeferredPattern
377
+ def initialize(modifiers)
378
+ super(modifiers)
379
+ @name = 'I1K'
380
+ @pre_messages = [[], [Token::S]]
381
+ @tokens = [[Token::E, Token::ES, Token::S], [Token::E, Token::EE], [Token::SE]]
382
+ end
383
+ end
384
+
385
+ class PatternIK1 < DeferredPattern
386
+ def initialize(modifiers)
387
+ super(modifiers)
388
+ @name = 'IK1'
389
+ @pre_messages = [[], [Token::S]]
390
+ @tokens = [[Token::E, Token::S], [Token::E, Token::EE, Token::SE, Token::ES]]
391
+ end
392
+ end
393
+
394
+ class PatternI1K1 < DeferredPattern
395
+ def initialize(modifiers)
396
+ super(modifiers)
397
+ @name = 'I1K1'
398
+ @pre_messages = [[], [Token::S]]
399
+ @tokens = [[Token::E, Token::S], [Token::E, Token::EE, Token::ES], [Token::SE]]
400
+ end
401
+ end
402
+
403
+ class PatternI1X < DeferredPattern
404
+ def initialize(modifiers)
405
+ super(modifiers)
406
+ @name = 'I1X'
407
+ @tokens = [[Token::E, Token::S], [Token::E, Token::EE, Token::S, Token::ES], [Token::SE]]
408
+ end
409
+ end
410
+
411
+ class PatternIX1 < DeferredPattern
412
+ def initialize(modifiers)
413
+ super(modifiers)
414
+ @name = 'IX1'
415
+ @tokens = [[Token::E, Token::S], [Token::E, Token::EE, Token::SE, Token::S], [Token::ES]]
416
+ end
417
+ end
418
+
419
+ class PatternI1X1 < DeferredPattern
420
+ def initialize(modifiers)
421
+ super(modifiers)
422
+ @name = 'I1X1'
423
+ @tokens = [[Token::E, Token::S], [Token::E, Token::EE, Token::S], [Token::SE, Token::ES]]
424
+ end
425
+ end
218
426
  end
@@ -18,23 +18,20 @@ module Noise
18
18
  # Each message pattern is a sequence of tokens from the set ("e", "s", "ee", "es", "se", "ss").
19
19
  class HandshakeState
20
20
  attr_reader :message_patterns, :symmetric_state
21
- attr_reader :s, :rs
21
+ attr_reader :s, :rs, :e, :re
22
22
 
23
- def initialize(connection, protocol, initiator, prologue, keypairs)
23
+ def initialize(connection, protocol, initiator, prologue, local_keypairs, remote_keys)
24
24
  @connection = connection
25
25
  @protocol = protocol
26
26
  @symmetric_state = SymmetricState.new
27
27
  @symmetric_state.initialize_symmetric(@protocol, connection)
28
28
  @symmetric_state.mix_hash(prologue)
29
29
  @initiator = initiator
30
- @s = keypairs[:s]
31
- @e = keypairs[:e]
32
- @rs = keypairs[:rs]
33
- @re = keypairs[:re]
30
+ @s = local_keypairs[:s]
31
+ @e = local_keypairs[:e]
32
+ @rs = remote_keys[:rs]
33
+ @re = remote_keys[:re]
34
34
 
35
- # TODO : Calls MixHash() once for each public key listed in the pre-messages from handshake_pattern, with the
36
- # specified public key as input (see Section 7 for an explanation of pre-messages). If both initiator and
37
- # responder have pre-messages, the initiator's public keys are hashed first.
38
35
  get_local_keypair = ->(token) { instance_variable_get('@' + token).public_key }
39
36
  get_remote_keypair = ->(token) { instance_variable_get('@r' + token) }
40
37
 
@@ -46,17 +43,45 @@ module Noise
46
43
  responder_keypair_getter = get_local_keypair
47
44
  end
48
45
 
46
+ # Sets message_patterns to the message patterns from handshake_pattern
47
+ @message_patterns = @protocol.pattern.tokens.dup
48
+
49
49
  @protocol.pattern.initiator_pre_messages&.map do |message|
50
50
  keypair = initiator_keypair_getter.call(message)
51
51
  @symmetric_state.mix_hash(keypair)
52
52
  end
53
53
 
54
+ if @protocol.pattern.fallback
55
+ message = @message_patterns.delete_at(0).first
56
+ public_key = initiator_keypair_getter.call(message)
57
+ @symmetric_state.mix_hash(public_key)
58
+ end
59
+
54
60
  @protocol.pattern.responder_pre_messages&.map do |message|
55
61
  keypair = responder_keypair_getter.call(message)
56
62
  @symmetric_state.mix_hash(keypair)
57
63
  end
58
- # Sets message_patterns to the message patterns from handshake_pattern
59
- @message_patterns = @protocol.pattern.tokens.dup
64
+ end
65
+
66
+ def expected_message_length(payload_size)
67
+ has_key = @symmetric_state.cipher_state.key?
68
+ pattern = @message_patterns.first
69
+ len = pattern.inject(0) do |len, token|
70
+ case token
71
+ when 'e'
72
+ len += @protocol.dh_fn.dhlen
73
+ has_key = true if @protocol.psk_handshake?
74
+ when 's'
75
+ len += @protocol.dh_fn.dhlen
76
+ len += 16 if has_key
77
+ when 'ee', 'es', 'se', 'ss', 'psk'
78
+ has_key = true
79
+ end
80
+ len
81
+ end
82
+ len += payload_size
83
+ len += 16 if has_key
84
+ len
60
85
  end
61
86
 
62
87
  # Takes a payload byte sequence which may be zero-length, and a message_buffer to write the output into
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Noise
4
- VERSION = '0.7.4'
4
+ VERSION = '0.8.4'
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: noise-ruby
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.7.4
4
+ version: 0.8.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Hajime Yamaguchi
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2019-04-30 00:00:00.000000000 Z
11
+ date: 2019-06-24 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -141,6 +141,7 @@ files:
141
141
  - lib/noise/exceptions/noise_validation_error.rb
142
142
  - lib/noise/exceptions/protocol_name_error.rb
143
143
  - lib/noise/exceptions/psk_value_error.rb
144
+ - lib/noise/exceptions/unsupported_modifier_error.rb
144
145
  - lib/noise/functions.rb
145
146
  - lib/noise/functions/cipher.rb
146
147
  - lib/noise/functions/cipher/aes_gcm.rb