noise-ruby 0.7.4 → 0.8.4

Sign up to get free protection for your applications and to get access to all the features.
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