simple_nts_client 0.0.1

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.
Files changed (47) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +16 -0
  3. data/.rubocop.yml +24 -0
  4. data/.travis.yml +17 -0
  5. data/Gemfile +14 -0
  6. data/LICENSE.txt +21 -0
  7. data/README.md +57 -0
  8. data/Rakefile +10 -0
  9. data/exe/simple_nts_client +8 -0
  10. data/lib/nts/cli.rb +83 -0
  11. data/lib/nts/ntske/client.rb +100 -0
  12. data/lib/nts/ntske/message/aead_algorithm_negotiation.rb +47 -0
  13. data/lib/nts/ntske/message/cookie.rb +33 -0
  14. data/lib/nts/ntske/message/end_of_message.rb +30 -0
  15. data/lib/nts/ntske/message/error_record.rb +39 -0
  16. data/lib/nts/ntske/message/nts_next_protocol_negotiation.rb +35 -0
  17. data/lib/nts/ntske/message/ntsv4_port_negotiation.rb +36 -0
  18. data/lib/nts/ntske/message/ntsv4_server_negotiation.rb +36 -0
  19. data/lib/nts/ntske/message/warning_record.rb +34 -0
  20. data/lib/nts/ntske/message.rb +107 -0
  21. data/lib/nts/ntske.rb +4 -0
  22. data/lib/nts/sntp/client.rb +160 -0
  23. data/lib/nts/sntp/extension/nts_authenticator.rb +53 -0
  24. data/lib/nts/sntp/extension/nts_cookie.rb +34 -0
  25. data/lib/nts/sntp/extension/unique_identifier.rb +36 -0
  26. data/lib/nts/sntp/extension/unknown_extension.rb +36 -0
  27. data/lib/nts/sntp/extension.rb +38 -0
  28. data/lib/nts/sntp/message.rb +119 -0
  29. data/lib/nts/sntp.rb +4 -0
  30. data/lib/nts/version.rb +5 -0
  31. data/lib/nts.rb +12 -0
  32. data/simple_nts_client.gemspec +27 -0
  33. data/spec/aead_algorithm_negotiation_spec.rb +28 -0
  34. data/spec/cookie_spec.rb +36 -0
  35. data/spec/end_of_message_spec.rb +26 -0
  36. data/spec/error_record_spec.rb +28 -0
  37. data/spec/extension_spec.rb +28 -0
  38. data/spec/nts_authenticator_spec.rb +64 -0
  39. data/spec/nts_cookie_spec.rb +36 -0
  40. data/spec/nts_next_protocol_negotiation_spec.rb +28 -0
  41. data/spec/ntsv4_port_negotiation_spec.rb +28 -0
  42. data/spec/ntsv4_server_negotiation_spec.rb +28 -0
  43. data/spec/spec_helper.rb +11 -0
  44. data/spec/unique_identifier_spec.rb +36 -0
  45. data/spec/unknown_extension_spec.rb +46 -0
  46. data/spec/warning_record_spec.rb +28 -0
  47. metadata +145 -0
@@ -0,0 +1,36 @@
1
+ # encoding: ascii-8bit
2
+ # frozen_string_literal: true
3
+
4
+ require_relative 'spec_helper'
5
+
6
+ RSpec.describe Cookie do
7
+ context 'initialized with random binary' do
8
+ let(:rb) do
9
+ OpenSSL::Random.random_bytes(32)
10
+ end
11
+
12
+ let(:message) do
13
+ Cookie.new(rb)
14
+ end
15
+
16
+ it 'should be serialized' do
17
+ expect(message.cookie).to eq rb
18
+ expect(message.serialize).to eq "\x00\x05\x00\x20" + rb
19
+ end
20
+ end
21
+
22
+ context 'received random binary' do
23
+ let(:rb) do
24
+ OpenSSL::Random.random_bytes(32)
25
+ end
26
+
27
+ let(:message) do
28
+ Cookie.deserialize(rb, false)
29
+ end
30
+
31
+ it 'should be deserialized' do
32
+ expect(message.cookie).to eq rb
33
+ expect(message.serialize).to eq "\x00\x05\x00\x20" + rb
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,26 @@
1
+ # encoding: ascii-8bit
2
+ # frozen_string_literal: true
3
+
4
+ require_relative 'spec_helper'
5
+
6
+ RSpec.describe EndOfMessage do
7
+ context 'initialized' do
8
+ let(:message) do
9
+ EndOfMessage.new
10
+ end
11
+
12
+ it 'should be serialized' do
13
+ expect(message.serialize).to eq "\x80\x00\x00\x00"
14
+ end
15
+ end
16
+
17
+ context 'received empty string' do
18
+ let(:message) do
19
+ EndOfMessage.deserialize('')
20
+ end
21
+
22
+ it 'should be deserialized' do
23
+ expect(message.serialize).to eq "\x80\x00\x00\x00"
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,28 @@
1
+ # encoding: ascii-8bit
2
+ # frozen_string_literal: true
3
+
4
+ require_relative 'spec_helper'
5
+
6
+ RSpec.describe ErrorRecord do
7
+ context 'initialized with BAD_REQUEST' do
8
+ let(:message) do
9
+ ErrorRecord.new(ErrorCode::BAD_REQUEST)
10
+ end
11
+
12
+ it 'should be serialized' do
13
+ expect(message.error_code).to eq ErrorCode::BAD_REQUEST
14
+ expect(message.serialize).to eq "\x80\x02\x00\x02\x00\x01"
15
+ end
16
+ end
17
+
18
+ context 'received "\x00\x01" that means "Bad Request"' do
19
+ let(:message) do
20
+ ErrorRecord.deserialize("\x00\x01")
21
+ end
22
+
23
+ it 'should be deserialized' do
24
+ expect(message.error_code).to eq ErrorCode::BAD_REQUEST
25
+ expect(message.serialize).to eq "\x80\x02\x00\x02\x00\x01"
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,28 @@
1
+ # encoding: ascii-8bit
2
+ # frozen_string_literal: true
3
+
4
+ require_relative 'spec_helper'
5
+
6
+ RSpec.describe Nts::Sntp::Extension do
7
+ context 'module_function :pad_zero' do
8
+ it 'should pad "\x00" to a word boundary' do
9
+ expect(Extension.pad_zero("\xFF")).to eq "\xFF\x00\x00\x00"
10
+ expect(Extension.pad_zero("\xFF\xFF")).to eq "\xFF\xFF\x00\x00"
11
+ expect(Extension.pad_zero("\xFF\xFF\xFF")).to eq "\xFF\xFF\xFF\x00"
12
+ expect(Extension.pad_zero("\xFF\xFF\xFF\xFF")).to eq "\xFF\xFF\xFF\xFF"
13
+ end
14
+ end
15
+
16
+ context 'module_function :truncate_zero_padding' do
17
+ it 'should truncate "\x00"' do
18
+ expect(Extension.truncate_zero_padding("\xFF\x00\x00\x00"))
19
+ .to eq "\xFF"
20
+ expect(Extension.truncate_zero_padding("\xFF\xFF\x00\x00"))
21
+ .to eq "\xFF\xFF"
22
+ expect(Extension.truncate_zero_padding("\xFF\xFF\xFF\x00"))
23
+ .to eq "\xFF\xFF\xFF"
24
+ expect(Extension.truncate_zero_padding("\xFF\xFF\xFF\xFF"))
25
+ .to eq "\xFF\xFF\xFF\xFF"
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,64 @@
1
+ # encoding: ascii-8bit
2
+ # frozen_string_literal: true
3
+
4
+ require_relative 'spec_helper'
5
+
6
+ RSpec.describe NtsAuthenticator do
7
+ context 'initialized with nonce and ciphertext' do
8
+ let(:nonce) do
9
+ OpenSSL::Random.random_bytes(16)
10
+ end
11
+
12
+ let(:ciphertext) do
13
+ OpenSSL::Random.random_bytes(12345)
14
+ end
15
+
16
+ let(:ex) do
17
+ NtsAuthenticator.new(nonce, ciphertext)
18
+ end
19
+
20
+ it 'should be serialized' do
21
+ expect(ex.nonce).to eq nonce
22
+ expect(ex.ciphertext).to eq ciphertext
23
+ expect(ex.padding_length).to eq 0
24
+
25
+ expected = String.new
26
+ expected << "\x04\x04\x30\x54" # Field Type | Length
27
+ expected << "\x00\x10\x30\x3C" # Nonce Length | Ciphertext Length
28
+ expected << nonce
29
+ expected << ciphertext + "\x00\x00\x00" # padded to a word boundary
30
+ expect(ex.serialize).to eq expected
31
+ end
32
+ end
33
+
34
+ context 'received string' do
35
+ let(:nonce) do
36
+ OpenSSL::Random.random_bytes(16)
37
+ end
38
+
39
+ let(:ciphertext) do
40
+ OpenSSL::Random.random_bytes(12345)
41
+ end
42
+
43
+ let(:ex) do
44
+ NtsAuthenticator.deserialize(
45
+ "\x00\x10\x30\x3C" \
46
+ + nonce \
47
+ + ciphertext + "\x00\x00\x00"
48
+ )
49
+ end
50
+
51
+ it 'should be deserialized' do
52
+ expect(ex.nonce).to eq nonce
53
+ expect(ex.ciphertext).to eq ciphertext
54
+ expect(ex.padding_length).to eq 0
55
+
56
+ expected = String.new
57
+ expected << "\x04\x04\x30\x54" # Field Type | Length
58
+ expected << "\x00\x10\x30\x3C" # Nonce Length | Ciphertext Length
59
+ expected << nonce
60
+ expected << ciphertext + "\x00\x00\x00" # padded to a word boundary
61
+ expect(ex.serialize).to eq expected
62
+ end
63
+ end
64
+ end
@@ -0,0 +1,36 @@
1
+ # encoding: ascii-8bit
2
+ # frozen_string_literal: true
3
+
4
+ require_relative 'spec_helper'
5
+
6
+ RSpec.describe NtsCookie do
7
+ context 'initialized with random binary' do
8
+ let(:rb) do
9
+ OpenSSL::Random.random_bytes(32)
10
+ end
11
+
12
+ let(:ex) do
13
+ NtsCookie.new(rb)
14
+ end
15
+
16
+ it 'should be serialized' do
17
+ expect(ex.cookie).to eq rb
18
+ expect(ex.serialize).to eq "\x02\x04\x00\x24" + rb
19
+ end
20
+ end
21
+
22
+ context 'received random binary' do
23
+ let(:rb) do
24
+ OpenSSL::Random.random_bytes(32)
25
+ end
26
+
27
+ let(:ex) do
28
+ NtsCookie.deserialize(rb)
29
+ end
30
+
31
+ it 'should be deserialized' do
32
+ expect(ex.cookie).to eq rb
33
+ expect(ex.serialize).to eq "\x02\x04\x00\x24" + rb
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,28 @@
1
+ # encoding: ascii-8bit
2
+ # frozen_string_literal: true
3
+
4
+ require_relative 'spec_helper'
5
+
6
+ RSpec.describe NtsNextProtocolNegotiation do
7
+ context 'initialized' do
8
+ let(:message) do
9
+ NtsNextProtocolNegotiation.new
10
+ end
11
+
12
+ it 'should be serialized' do
13
+ expect(message.next_protocol).to eq "\x00\x00"
14
+ expect(message.serialize).to eq "\x00\x01\x00\x02\x00\x00"
15
+ end
16
+ end
17
+
18
+ context 'received "\x00\x00" that means NTPv4' do
19
+ let(:message) do
20
+ NtsNextProtocolNegotiation.deserialize("\x00\x00")
21
+ end
22
+
23
+ it 'should be deserialized' do
24
+ expect(message.next_protocol).to eq "\x00\x00"
25
+ expect(message.serialize).to eq "\x00\x01\x00\x02\x00\x00"
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,28 @@
1
+ # encoding: ascii-8bit
2
+ # frozen_string_literal: true
3
+
4
+ require_relative 'spec_helper'
5
+
6
+ RSpec.describe Ntsv4PortNegotiation do
7
+ context 'initialized with 123' do
8
+ let(:message) do
9
+ Ntsv4PortNegotiation.new(123)
10
+ end
11
+
12
+ it 'should be serialized' do
13
+ expect(message.port).to eq 123
14
+ expect(message.serialize).to eq "\x00\x07\x00\x02\x00\x7B"
15
+ end
16
+ end
17
+
18
+ context 'received "\x00\x7B"(=123)' do
19
+ let(:message) do
20
+ Ntsv4PortNegotiation.deserialize("\x00\x7B", false)
21
+ end
22
+
23
+ it 'should be deserialized' do
24
+ expect(message.port).to eq 123
25
+ expect(message.serialize).to eq "\x00\x07\x00\x02\x00\x7B"
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,28 @@
1
+ # encoding: ascii-8bit
2
+ # frozen_string_literal: true
3
+
4
+ require_relative 'spec_helper'
5
+
6
+ RSpec.describe Ntsv4ServerNegotiation do
7
+ context 'initialized with "localhost"' do
8
+ let(:message) do
9
+ Ntsv4ServerNegotiation.new('localhost')
10
+ end
11
+
12
+ it 'should be serialized' do
13
+ expect(message.server).to eq 'localhost'
14
+ expect(message.serialize).to eq "\x00\x06\x00\x09" + 'localhost'
15
+ end
16
+ end
17
+
18
+ context 'received "localhost"' do
19
+ let(:message) do
20
+ Ntsv4ServerNegotiation.deserialize('localhost', false)
21
+ end
22
+
23
+ it 'should be deserialized' do
24
+ expect(message.server).to eq 'localhost'
25
+ expect(message.serialize).to eq "\x00\x06\x00\x09" + 'localhost'
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,11 @@
1
+ # encoding: ascii-8bit
2
+ # frozen_string_literal: true
3
+
4
+ RSpec.configure(&:disable_monkey_patching!)
5
+
6
+ # rubocop: disable Style/MixinUsage
7
+ require 'nts'
8
+ include Nts::Ntske
9
+ include Nts::Sntp
10
+ include Nts::Sntp::Extension
11
+ # rubocop: enable Style/MixinUsage
@@ -0,0 +1,36 @@
1
+ # encoding: ascii-8bit
2
+ # frozen_string_literal: true
3
+
4
+ require_relative 'spec_helper'
5
+
6
+ RSpec.describe UniqueIdentifier do
7
+ context 'initialized with random binary' do
8
+ let(:rb) do
9
+ OpenSSL::Random.random_bytes(32)
10
+ end
11
+
12
+ let(:ex) do
13
+ UniqueIdentifier.new(rb)
14
+ end
15
+
16
+ it 'should be serialized' do
17
+ expect(ex.id).to eq rb
18
+ expect(ex.serialize).to eq "\x01\x04\x00\x24" + rb
19
+ end
20
+ end
21
+
22
+ context 'received random binary' do
23
+ let(:rb) do
24
+ OpenSSL::Random.random_bytes(32)
25
+ end
26
+
27
+ let(:ex) do
28
+ UniqueIdentifier.deserialize(rb)
29
+ end
30
+
31
+ it 'should be deserialized' do
32
+ expect(ex.id).to eq rb
33
+ expect(ex.serialize).to eq "\x01\x04\x00\x24" + rb
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,46 @@
1
+ # encoding: ascii-8bit
2
+ # frozen_string_literal: true
3
+
4
+ require_relative 'spec_helper'
5
+
6
+ RSpec.describe UnknownExtension do
7
+ context 'initialized with random binary' do
8
+ let(:rb) do
9
+ OpenSSL::Random.random_bytes(32)
10
+ end
11
+
12
+ let(:field_type) do
13
+ 12345
14
+ end
15
+
16
+ let(:ex) do
17
+ UnknownExtension.new(rb, field_type)
18
+ end
19
+
20
+ it 'should be serialized' do
21
+ expect(ex.field_type).to eq field_type
22
+ expect(ex.value).to eq rb
23
+ expect(ex.serialize).to eq "\x30\x39\x00\x24" + rb
24
+ end
25
+ end
26
+
27
+ context 'received random binary' do
28
+ let(:rb) do
29
+ OpenSSL::Random.random_bytes(32)
30
+ end
31
+
32
+ let(:field_type) do
33
+ 12345
34
+ end
35
+
36
+ let(:ex) do
37
+ UnknownExtension.deserialize(rb, field_type)
38
+ end
39
+
40
+ it 'should be deserialized' do
41
+ expect(ex.field_type).to eq field_type
42
+ expect(ex.value).to eq rb
43
+ expect(ex.serialize).to eq "\x30\x39\x00\x24" + rb
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,28 @@
1
+ # encoding: ascii-8bit
2
+ # frozen_string_literal: true
3
+
4
+ require_relative 'spec_helper'
5
+
6
+ RSpec.describe WarningRecord do
7
+ context 'initialized with 1111' do
8
+ let(:message) do
9
+ WarningRecord.new(1111)
10
+ end
11
+
12
+ it 'should be serialized' do
13
+ expect(message.warning_code).to eq 1111
14
+ expect(message.serialize).to eq "\x80\x03\x00\x02\x04\x57"
15
+ end
16
+ end
17
+
18
+ context 'received "\x04\x57"(=1111)' do
19
+ let(:message) do
20
+ WarningRecord.deserialize("\x04\x57")
21
+ end
22
+
23
+ it 'should be deserialized' do
24
+ expect(message.warning_code).to eq 1111
25
+ expect(message.serialize).to eq "\x80\x03\x00\x02\x04\x57"
26
+ end
27
+ end
28
+ end
metadata ADDED
@@ -0,0 +1,145 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: simple_nts_client
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - thekuwayama
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2019-09-26 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: miscreant
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: tttls1.3
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: 0.2.7
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: 0.2.7
55
+ description: Simple NTS(Network Time Security) Client
56
+ email:
57
+ - thekuwayama@gmail.com
58
+ executables:
59
+ - simple_nts_client
60
+ extensions: []
61
+ extra_rdoc_files: []
62
+ files:
63
+ - ".gitignore"
64
+ - ".rubocop.yml"
65
+ - ".travis.yml"
66
+ - Gemfile
67
+ - LICENSE.txt
68
+ - README.md
69
+ - Rakefile
70
+ - exe/simple_nts_client
71
+ - lib/nts.rb
72
+ - lib/nts/cli.rb
73
+ - lib/nts/ntske.rb
74
+ - lib/nts/ntske/client.rb
75
+ - lib/nts/ntske/message.rb
76
+ - lib/nts/ntske/message/aead_algorithm_negotiation.rb
77
+ - lib/nts/ntske/message/cookie.rb
78
+ - lib/nts/ntske/message/end_of_message.rb
79
+ - lib/nts/ntske/message/error_record.rb
80
+ - lib/nts/ntske/message/nts_next_protocol_negotiation.rb
81
+ - lib/nts/ntske/message/ntsv4_port_negotiation.rb
82
+ - lib/nts/ntske/message/ntsv4_server_negotiation.rb
83
+ - lib/nts/ntske/message/warning_record.rb
84
+ - lib/nts/sntp.rb
85
+ - lib/nts/sntp/client.rb
86
+ - lib/nts/sntp/extension.rb
87
+ - lib/nts/sntp/extension/nts_authenticator.rb
88
+ - lib/nts/sntp/extension/nts_cookie.rb
89
+ - lib/nts/sntp/extension/unique_identifier.rb
90
+ - lib/nts/sntp/extension/unknown_extension.rb
91
+ - lib/nts/sntp/message.rb
92
+ - lib/nts/version.rb
93
+ - simple_nts_client.gemspec
94
+ - spec/aead_algorithm_negotiation_spec.rb
95
+ - spec/cookie_spec.rb
96
+ - spec/end_of_message_spec.rb
97
+ - spec/error_record_spec.rb
98
+ - spec/extension_spec.rb
99
+ - spec/nts_authenticator_spec.rb
100
+ - spec/nts_cookie_spec.rb
101
+ - spec/nts_next_protocol_negotiation_spec.rb
102
+ - spec/ntsv4_port_negotiation_spec.rb
103
+ - spec/ntsv4_server_negotiation_spec.rb
104
+ - spec/spec_helper.rb
105
+ - spec/unique_identifier_spec.rb
106
+ - spec/unknown_extension_spec.rb
107
+ - spec/warning_record_spec.rb
108
+ homepage: https://github.com/thekuwayama/simple_nts_client
109
+ licenses:
110
+ - MIT
111
+ metadata: {}
112
+ post_install_message:
113
+ rdoc_options: []
114
+ require_paths:
115
+ - lib
116
+ required_ruby_version: !ruby/object:Gem::Requirement
117
+ requirements:
118
+ - - ">="
119
+ - !ruby/object:Gem::Version
120
+ version: 2.6.1
121
+ required_rubygems_version: !ruby/object:Gem::Requirement
122
+ requirements:
123
+ - - ">="
124
+ - !ruby/object:Gem::Version
125
+ version: '0'
126
+ requirements: []
127
+ rubygems_version: 3.0.3
128
+ signing_key:
129
+ specification_version: 4
130
+ summary: Simple NTS(Network Time Security) Client
131
+ test_files:
132
+ - spec/aead_algorithm_negotiation_spec.rb
133
+ - spec/cookie_spec.rb
134
+ - spec/end_of_message_spec.rb
135
+ - spec/error_record_spec.rb
136
+ - spec/extension_spec.rb
137
+ - spec/nts_authenticator_spec.rb
138
+ - spec/nts_cookie_spec.rb
139
+ - spec/nts_next_protocol_negotiation_spec.rb
140
+ - spec/ntsv4_port_negotiation_spec.rb
141
+ - spec/ntsv4_server_negotiation_spec.rb
142
+ - spec/spec_helper.rb
143
+ - spec/unique_identifier_spec.rb
144
+ - spec/unknown_extension_spec.rb
145
+ - spec/warning_record_spec.rb