ruby-sslyze 0.2.1 → 1.0.0

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 (146) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +6 -4
  3. data/.travis.yml +15 -7
  4. data/ChangeLog.md +29 -12
  5. data/Gemfile +3 -2
  6. data/LICENSE.txt +1 -1
  7. data/README.md +5 -5
  8. data/Rakefile +1 -1
  9. data/lib/sslyze/cipher_suites.rb +176 -0
  10. data/lib/sslyze/program.rb +8 -8
  11. data/lib/sslyze/task.rb +40 -33
  12. data/lib/sslyze/version.rb +1 -1
  13. data/lib/sslyze/{certificate/domain_name.rb → x509/domain.rb} +5 -3
  14. data/lib/sslyze/x509/extension.rb +15 -0
  15. data/lib/sslyze/x509/extension_set.rb +140 -0
  16. data/lib/sslyze/x509/extensions.rb +6 -0
  17. data/lib/sslyze/x509/extensions/basic_constraints.rb +41 -0
  18. data/lib/sslyze/x509/extensions/certificate_policies.rb +108 -0
  19. data/lib/sslyze/x509/extensions/crl_distribution_points.rb +47 -0
  20. data/lib/sslyze/x509/extensions/extended_key_usage.rb +58 -0
  21. data/lib/sslyze/x509/extensions/key_usage.rb +66 -0
  22. data/lib/sslyze/x509/extensions/subject_alt_name.rb +144 -0
  23. data/lib/sslyze/x509/name.rb +194 -0
  24. data/lib/sslyze/x509/public_key.rb +53 -0
  25. data/lib/sslyze/xml.rb +26 -37
  26. data/lib/sslyze/xml/attributes.rb +5 -0
  27. data/lib/sslyze/xml/attributes/error.rb +30 -0
  28. data/lib/sslyze/xml/attributes/exception.rb +30 -0
  29. data/lib/sslyze/xml/attributes/is_supported.rb +29 -0
  30. data/lib/sslyze/xml/attributes/is_vulnerable.rb +29 -0
  31. data/lib/sslyze/xml/attributes/title.rb +31 -0
  32. data/lib/sslyze/xml/certinfo.rb +67 -0
  33. data/lib/sslyze/xml/certinfo/certificate.rb +202 -0
  34. data/lib/sslyze/xml/certinfo/certificate_validation.rb +69 -0
  35. data/lib/sslyze/xml/certinfo/certificate_validation/hostname_validation.rb +54 -0
  36. data/lib/sslyze/xml/certinfo/certificate_validation/path_validation.rb +84 -0
  37. data/lib/sslyze/xml/certinfo/certificate_validation/verified_certificate_chain.rb +41 -0
  38. data/lib/sslyze/xml/certinfo/has_certificates.rb +102 -0
  39. data/lib/sslyze/xml/certinfo/ocsp_stapling.rb +45 -0
  40. data/lib/sslyze/xml/certinfo/ocsp_stapling/ocsp_response.rb +87 -0
  41. data/lib/sslyze/xml/certinfo/received_certificate_chain.rb +48 -0
  42. data/lib/sslyze/xml/compression.rb +33 -0
  43. data/lib/sslyze/xml/compression/compression_method.rb +38 -0
  44. data/lib/sslyze/xml/fallback.rb +34 -0
  45. data/lib/sslyze/xml/fallback/tls_fallback_scsv.rb +27 -0
  46. data/lib/sslyze/xml/heartbleed.rb +38 -0
  47. data/lib/sslyze/xml/heartbleed/openssl_heartbleed.rb +29 -0
  48. data/lib/sslyze/xml/http_headers.rb +42 -0
  49. data/lib/sslyze/xml/http_headers/http_public_key_pinning.rb +121 -0
  50. data/lib/sslyze/xml/http_headers/http_strict_transport_security.rb +59 -0
  51. data/lib/sslyze/xml/invalid_target.rb +33 -0
  52. data/lib/sslyze/xml/openssl_ccs.rb +34 -0
  53. data/lib/sslyze/xml/openssl_ccs/openssl_ccs_injection.rb +26 -0
  54. data/lib/sslyze/xml/plugin.rb +27 -0
  55. data/lib/sslyze/xml/protocol.rb +143 -0
  56. data/lib/sslyze/xml/protocol/cipher_suite.rb +93 -0
  57. data/lib/sslyze/xml/protocol/cipher_suite/key_exchange.rb +127 -0
  58. data/lib/sslyze/xml/reneg.rb +28 -0
  59. data/lib/sslyze/xml/reneg/session_renegotiation.rb +51 -0
  60. data/lib/sslyze/xml/resum.rb +42 -0
  61. data/lib/sslyze/xml/resum/session_resumption_with_session_ids.rb +94 -0
  62. data/lib/sslyze/xml/resum/session_resumption_with_tls_tickets.rb +69 -0
  63. data/lib/sslyze/xml/resum_rate.rb +30 -0
  64. data/lib/sslyze/xml/target.rb +371 -0
  65. data/lib/sslyze/xml/types.rb +19 -0
  66. data/ruby-sslyze.gemspec +3 -3
  67. data/spec/spec_helper.rb +2 -4
  68. data/spec/sslyze.xml +2356 -2580
  69. data/spec/x509/domain_spec.rb +125 -0
  70. data/spec/x509/extension_set_spec.rb +208 -0
  71. data/spec/x509/extension_spec.rb +58 -0
  72. data/spec/x509/extensions/basic_constraints_spec.rb +41 -0
  73. data/spec/x509/extensions/certificate_policies_spec.rb +38 -0
  74. data/spec/x509/extensions/crl_distribution_points_spec.rb +38 -0
  75. data/spec/x509/extensions/extended_key_usage_spec.rb +58 -0
  76. data/spec/x509/extensions/key_usage_spec.rb +84 -0
  77. data/spec/x509/extensions/subject_alt_name_spec.rb +146 -0
  78. data/spec/x509/name_spec.rb +85 -0
  79. data/spec/x509/public_key_spec.rb +113 -0
  80. data/spec/xml/certinfo/certificate_spec.rb +166 -0
  81. data/spec/xml/certinfo/certificate_validation/hostname_validation_spec.rb +23 -0
  82. data/spec/xml/certinfo/certificate_validation/path_validation_spec.rb +107 -0
  83. data/spec/xml/certinfo/certificate_validation/verified_certificate_chain_spec.rb +163 -0
  84. data/spec/xml/certinfo/certificate_validation_spec.rb +40 -0
  85. data/spec/xml/certinfo/ocsp_stapling/ocsp_response_spec.rb +61 -0
  86. data/spec/xml/certinfo/ocsp_stapling_spec.rb +31 -0
  87. data/spec/xml/certinfo/received_certificate_chain_spec.rb +165 -0
  88. data/spec/xml/certinfo_spec.rb +45 -0
  89. data/spec/xml/compression/compression_method_spec.rb +23 -0
  90. data/spec/xml/compression_spec.rb +23 -0
  91. data/spec/xml/heartbleed/openssl_heartbleed_spec.rb +17 -0
  92. data/spec/xml/heartbleed_spec.rb +37 -0
  93. data/spec/xml/http_headers/http_public_key_pinning_spec.rb +73 -0
  94. data/spec/xml/http_headers/http_strict_transport_security_spec.rb +107 -0
  95. data/spec/xml/http_headers_spec.rb +63 -0
  96. data/spec/xml/invalid_target_spec.rb +23 -0
  97. data/spec/xml/plugin_examples.rb +14 -0
  98. data/spec/{key_exchange_spec.rb → xml/protocol/cipher_suite/key_exchange_spec.rb} +9 -3
  99. data/spec/xml/protocol/cipher_suite_spec.rb +66 -0
  100. data/spec/xml/protocol_spec.rb +115 -0
  101. data/spec/xml/reneg/session_renegotiation_spec.rb +23 -0
  102. data/spec/xml/reneg_spec.rb +35 -0
  103. data/spec/xml/resum/session_resumption_with_session_ids_spec.rb +103 -0
  104. data/spec/xml/resum/session_resumption_with_tls_tickets_spec.rb +121 -0
  105. data/spec/xml/resum_rate_spec.rb +30 -0
  106. data/spec/xml/resum_spec.rb +47 -0
  107. data/spec/{target_spec.rb → xml/target_spec.rb} +73 -27
  108. data/spec/xml_spec.rb +13 -21
  109. metadata +138 -61
  110. data/lib/sslyze/cert_info.rb +0 -57
  111. data/lib/sslyze/certificate.rb +0 -139
  112. data/lib/sslyze/certificate/extensions.rb +0 -127
  113. data/lib/sslyze/certificate/extensions/authority_information_access.rb +0 -38
  114. data/lib/sslyze/certificate/extensions/extension.rb +0 -26
  115. data/lib/sslyze/certificate/extensions/x509v3_basic_constraints.rb +0 -60
  116. data/lib/sslyze/certificate/extensions/x509v3_certificate_policies.rb +0 -50
  117. data/lib/sslyze/certificate/extensions/x509v3_crl_distribution_points.rb +0 -32
  118. data/lib/sslyze/certificate/extensions/x509v3_extended_key_usage.rb +0 -32
  119. data/lib/sslyze/certificate/extensions/x509v3_key_usage.rb +0 -50
  120. data/lib/sslyze/certificate/extensions/x509v3_subject_alternative_name.rb +0 -71
  121. data/lib/sslyze/certificate/issuer.rb +0 -56
  122. data/lib/sslyze/certificate/public_key.rb +0 -9
  123. data/lib/sslyze/certificate/subject.rb +0 -117
  124. data/lib/sslyze/certificate/subject_public_key_info.rb +0 -53
  125. data/lib/sslyze/certificate/validity.rb +0 -9
  126. data/lib/sslyze/certificate_chain.rb +0 -89
  127. data/lib/sslyze/certificate_validation.rb +0 -70
  128. data/lib/sslyze/cipher_suite.rb +0 -237
  129. data/lib/sslyze/invalid_target.rb +0 -35
  130. data/lib/sslyze/key_exchange.rb +0 -106
  131. data/lib/sslyze/ocsp_response.rb +0 -87
  132. data/lib/sslyze/protocol.rb +0 -133
  133. data/lib/sslyze/target.rb +0 -312
  134. data/lib/sslyze/types.rb +0 -17
  135. data/spec/cert_info_spec.rb +0 -29
  136. data/spec/certificate/subject_name_spec.rb +0 -72
  137. data/spec/certificate_chain_spec.rb +0 -61
  138. data/spec/certificate_spec.rb +0 -330
  139. data/spec/certificate_validation_spec.rb +0 -39
  140. data/spec/cipher_suite_spec.rb +0 -50
  141. data/spec/invalid_target_spec.rb +0 -21
  142. data/spec/issuer_spec.rb +0 -33
  143. data/spec/ocsp_response_spec.rb +0 -59
  144. data/spec/protocol_spec.rb +0 -99
  145. data/spec/subject_public_key_info_spec.rb +0 -35
  146. data/spec/subject_spec.rb +0 -69
@@ -0,0 +1,38 @@
1
+ require 'spec_helper'
2
+ require 'openssl'
3
+
4
+ require 'sslyze/x509/extensions/crl_distribution_points'
5
+
6
+ describe SSLyze::X509::Extensions::CRLDistributionPoints do
7
+ let(:uri1) { URI('http://crl3.digicert.com/sha2-ha-server-g5.crl') }
8
+ let(:uri2) { URI('http://crl4.digicert.com/sha2-ha-server-g5.crl') }
9
+ let(:value) do
10
+ %{
11
+ Full Name:
12
+ URI:#{uri1}
13
+
14
+ Full Name:
15
+ URI:#{uri2}
16
+ }
17
+ end
18
+
19
+ let(:openssl_x509_extension) do
20
+ OpenSSL::X509::Extension.new('crlDistributionPoints',value)
21
+ end
22
+
23
+ subject { described_class.new(openssl_x509_extension) }
24
+
25
+ describe "#uris" do
26
+ it "should parse each 'URI:' value" do
27
+ expect(subject.uris).to be == [uri1, uri2]
28
+ end
29
+ end
30
+
31
+ describe "#each" do
32
+ it "should yield each parsed 'URI:' value" do
33
+ expect { |b|
34
+ subject.each(&b)
35
+ }.to yield_successive_args(uri1, uri2)
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,58 @@
1
+ require 'spec_helper'
2
+ require 'openssl'
3
+
4
+ require 'sslyze/x509/extensions/extended_key_usage'
5
+
6
+ describe SSLyze::X509::Extensions::ExtendedKeyUsage do
7
+ let(:uses) do
8
+ [
9
+ 'TLS Web Server Authentication',
10
+ 'TLS Web Client Authentication'
11
+ ]
12
+ end
13
+ let(:value) { uses.join(', ') }
14
+
15
+ let(:openssl_x509_extension) do
16
+ OpenSSL::X509::Extension.new('extendedKeyUsage', value)
17
+ end
18
+
19
+ subject { described_class.new(openssl_x509_extension) }
20
+
21
+ describe "#uses" do
22
+ it "should parse the comma deliminated value" do
23
+ expect(subject.uses).to be == uses
24
+ end
25
+ end
26
+
27
+ describe "#each" do
28
+ it "should yield each parsed use" do
29
+ expect { |b|
30
+ subject.each(&b)
31
+ }.to yield_successive_args(*uses)
32
+ end
33
+ end
34
+
35
+ describe "#tls_web_server_authentication?" do
36
+ context "when 'TLS Web Server Authentication' is present" do
37
+ it { expect(subject.tls_web_server_authentication?).to be true }
38
+ end
39
+
40
+ context "when 'TLS Web Server Authentication' is not present" do
41
+ let(:uses) { super() - ['TLS Web Server Authentication'] }
42
+
43
+ it { expect(subject.tls_web_server_authentication?).to be false }
44
+ end
45
+ end
46
+
47
+ describe "#tls_web_client_authentication?" do
48
+ context "when 'TLS Web Client Authentication' is present" do
49
+ it { expect(subject.tls_web_client_authentication?).to be true }
50
+ end
51
+
52
+ context "when 'TLS Web Client Authentication' is not present" do
53
+ let(:uses) { super() - ['TLS Web Client Authentication'] }
54
+
55
+ it { expect(subject.tls_web_client_authentication?).to be false }
56
+ end
57
+ end
58
+ end
@@ -0,0 +1,84 @@
1
+ require 'spec_helper'
2
+ require 'openssl'
3
+
4
+ require 'sslyze/x509/extensions/key_usage'
5
+
6
+ describe SSLyze::X509::Extensions::KeyUsage do
7
+ let(:uses) do
8
+ [
9
+ 'Key Encipherment',
10
+ 'Digital Signature',
11
+ 'CRL Sign',
12
+ 'Certificate Sign'
13
+ ]
14
+ end
15
+ let(:value) { uses.join(', ') }
16
+
17
+ let(:openssl_x509_extension) do
18
+ OpenSSL::X509::Extension.new('keyUsage', value)
19
+ end
20
+
21
+ subject { described_class.new(openssl_x509_extension) }
22
+
23
+ describe "#uses" do
24
+ it "should parse the comma deliminated value" do
25
+ expect(subject.uses).to be == uses
26
+ end
27
+ end
28
+
29
+ describe "#each" do
30
+ it "should yield each parsed use" do
31
+ expect { |b|
32
+ subject.each(&b)
33
+ }.to yield_successive_args(*uses)
34
+ end
35
+ end
36
+
37
+ describe "#key_encipherment?" do
38
+ context "when 'Key Encipherment' is present" do
39
+ it { expect(subject.key_encipherment?).to be true }
40
+ end
41
+
42
+ context "when 'Key Encipherment' is not present" do
43
+ let(:uses) { super() - ['Key Encipherment'] }
44
+
45
+ it { expect(subject.key_encipherment?).to be false }
46
+ end
47
+ end
48
+
49
+ describe "#digital_signature?" do
50
+ context "when 'Digital Signature' is present" do
51
+ it { expect(subject.digital_signature?).to be true }
52
+ end
53
+
54
+ context "when 'Digital Signature' is not present" do
55
+ let(:uses) { super() - ['Digital Signature'] }
56
+
57
+ it { expect(subject.digital_signature?).to be false }
58
+ end
59
+ end
60
+
61
+ describe "#crl_sign?" do
62
+ context "when 'CRL Sign' is present" do
63
+ it { expect(subject.crl_sign?).to be true }
64
+ end
65
+
66
+ context "when 'CRL Sign' is not present" do
67
+ let(:uses) { super() - ['CRL Sign'] }
68
+
69
+ it { expect(subject.crl_sign?).to be false }
70
+ end
71
+ end
72
+
73
+ describe "#certificate_sign?" do
74
+ context "when 'Certificate Sign' is present" do
75
+ it { expect(subject.certificate_sign?).to be true }
76
+ end
77
+
78
+ context "when 'Certificate Sign' is not present" do
79
+ let(:uses) { super() - ['Certificate Sign'] }
80
+
81
+ it { expect(subject.certificate_sign?).to be false }
82
+ end
83
+ end
84
+ end
@@ -0,0 +1,146 @@
1
+ require 'spec_helper'
2
+ require 'openssl'
3
+
4
+ require 'sslyze/x509/extensions/subject_alt_name'
5
+
6
+ describe SSLyze::X509::Extensions::SubjectAltName do
7
+ let(:domains) do
8
+ %w[
9
+ example.com
10
+ foo.example.com
11
+ bar.example.com
12
+ ]
13
+ end
14
+ let(:dns_names) do
15
+ domains.map { |name| "DNS:#{name}" }
16
+ end
17
+
18
+ let(:ips) do
19
+ %w[
20
+ 127.0.0.1
21
+ 10.0.0.1
22
+ ]
23
+ end
24
+ let(:ip_names) do
25
+ ips.map { |name| "IP:#{name}" }
26
+ end
27
+
28
+ let(:uris) do
29
+ %w[
30
+ https://foo.com/
31
+ https://bar.com/
32
+ ]
33
+ end
34
+ let(:uri_names) do
35
+ uris.map { |name| "URI:#{name}" }
36
+ end
37
+
38
+ let(:email_addresses) do
39
+ %w[
40
+ foo@example.com
41
+ bar@example.com
42
+ ]
43
+ end
44
+ let(:email_names) do
45
+ email_addresses.map { |name| "email:#{name}" }
46
+ end
47
+
48
+ let(:names) { dns_names + ip_names + uri_names + email_names }
49
+ let(:value) { names.join(', ') }
50
+
51
+ let(:openssl_x509_extension) do
52
+ OpenSSL::X509::Extension.new('subjectAltName', value)
53
+ end
54
+
55
+ subject { described_class.new(openssl_x509_extension) }
56
+
57
+ describe "#each" do
58
+ context "when a block is given" do
59
+ context "when value contains 'DNS:' names" do
60
+ let(:names) { dns_names }
61
+
62
+ it "should yield (:dns, name) tuples" do
63
+ expect { |b|
64
+ subject.each(&b)
65
+ }.to yield_successive_args(*domains.map { |domain| [:dns, domain] })
66
+ end
67
+ end
68
+
69
+ context "when value contains 'IP:' names" do
70
+ let(:names) { ip_names }
71
+
72
+ it "should yield (:ip, name) tuples" do
73
+ expect { |b|
74
+ subject.each(&b)
75
+ }.to yield_successive_args(*ips.map { |ip| [:ip, ip] })
76
+ end
77
+ end
78
+
79
+ context "when value contains 'URI:' names" do
80
+ let(:names) { uri_names }
81
+
82
+ it "should yield (:uri, name) tuples" do
83
+ expect { |b|
84
+ subject.each(&b)
85
+ }.to yield_successive_args(*uris.map { |uri| [:uri, uri] })
86
+ end
87
+ end
88
+
89
+ context "when value contains 'email:' names" do
90
+ let(:names) { email_names }
91
+
92
+ it "should yield (:email, name) tuples" do
93
+ expect { |b|
94
+ subject.each(&b)
95
+ }.to yield_successive_args(*email_addresses.map { |email| [:email, email] })
96
+ end
97
+ end
98
+
99
+ context "when value contains 'RID:' names"
100
+ context "when value contains 'dirName:' names"
101
+ context "when value contains 'otherName:' names"
102
+ end
103
+
104
+ context "when no block is given" do
105
+ it "should return return an Enumerator" do
106
+ expect(subject.each).to be_kind_of(Enumerator)
107
+ end
108
+ end
109
+ end
110
+
111
+ describe "#dns" do
112
+ it "should return only the 'DNS:' names" do
113
+ expect(subject.dns).to be == domains
114
+ end
115
+ end
116
+
117
+ describe "#ip" do
118
+ it "should return only the 'IP:' names" do
119
+ expect(subject.ip.map(&:to_s)).to be == ips
120
+ end
121
+
122
+ it "should parse each 'IP:' name as an IPAddr" do
123
+ expect(subject.ip).to all(be_kind_of(IPAddr))
124
+ end
125
+ end
126
+
127
+ describe "#uri" do
128
+ it "should return only the 'URI:' names" do
129
+ expect(subject.uri.map(&:to_s)).to be == uris
130
+ end
131
+
132
+ it "should parse each 'URI:' name as an URI" do
133
+ expect(subject.uri).to all(be_kind_of(URI::Generic))
134
+ end
135
+ end
136
+
137
+ describe "#email" do
138
+ it "should return only the 'email:' names" do
139
+ expect(subject.email).to be == email_addresses
140
+ end
141
+ end
142
+
143
+ describe "#rid"
144
+ describe "#dir_name"
145
+ describe "#other_name"
146
+ end
@@ -0,0 +1,85 @@
1
+ require 'rspec'
2
+ require 'openssl'
3
+
4
+ require 'sslyze/x509/name'
5
+
6
+ describe SSLyze::X509::Name do
7
+ let(:country_name) { 'US' }
8
+ let(:state_name) { 'California' }
9
+ let(:location_name) { 'San Francisco' }
10
+ let(:organization_name) { 'Twitter, Inc.' }
11
+ let(:organizational_unit_name) { 'Twitter Security' }
12
+ let(:common_name) { 'twitter.com' }
13
+
14
+ let(:entries) do
15
+ [
16
+ ["C", country_name, 19],
17
+ ["ST", state_name, 19],
18
+ ["L", location_name, 19],
19
+ ["O", organization_name, 19],
20
+ ["OU", organizational_unit_name, 19],
21
+ ["CN", common_name, 19]
22
+ ]
23
+ end
24
+ let(:openssl_x509_name) { OpenSSL::X509::Name.new(entries) }
25
+
26
+ subject { described_class.new(openssl_x509_name) }
27
+
28
+ describe "#each" do
29
+ it "should iterate over the entries" do
30
+ expect { |b|
31
+ subject.each(&b)
32
+ }.to yield_successive_args(*entries)
33
+ end
34
+ end
35
+
36
+ describe "#[]" do
37
+ it "should return the value for the given OID key" do
38
+ expect(subject['C']).to be == country_name
39
+ end
40
+
41
+ context "when the OID key cannot be found" do
42
+ it { expect(subject['foo']).to be nil }
43
+ end
44
+ end
45
+
46
+ describe "#country_name" do
47
+ it "should return the 'C' entry" do
48
+ expect(subject.country_name).to be == country_name
49
+ end
50
+ end
51
+
52
+ describe "#state_name" do
53
+ it "should return the 'ST' entry" do
54
+ expect(subject.state_name).to be == state_name
55
+ end
56
+ end
57
+
58
+ describe "#location_name" do
59
+ it "should return the 'L' entry" do
60
+ expect(subject.location_name).to be == location_name
61
+ end
62
+ end
63
+
64
+ describe "#organization_name" do
65
+ it "should return the 'O' entry" do
66
+ expect(subject.organization_name).to be == organization_name
67
+ end
68
+ end
69
+
70
+ describe "#organizational_unit_name" do
71
+ it "should return the 'OU' entry" do
72
+ expect(subject.organizational_unit_name).to be == organizational_unit_name
73
+ end
74
+ end
75
+
76
+ describe "#common_name" do
77
+ it do
78
+ expect(subject.common_name).to be_kind_of(SSLyze::X509::Domain)
79
+ end
80
+
81
+ it "should be equal to the 'CN' entry" do
82
+ expect(subject.common_name.name).to be == common_name
83
+ end
84
+ end
85
+ end
@@ -0,0 +1,113 @@
1
+ require 'spec_helper'
2
+ require 'openssl'
3
+
4
+ require 'sslyze/x509/public_key'
5
+
6
+ describe SSLyze::X509::PublicKey do
7
+ let(:key_size) { 1024 }
8
+
9
+ let(:rsa_key) { OpenSSL::PKey::RSA.new(key_size) }
10
+ let(:dsa_key) { OpenSSL::PKey::DSA.new(key_size) }
11
+ let(:dh_key) { OpenSSL::PKey::DH.new(key_size) }
12
+ let(:ec_key) { OpenSSL::PKey::EC.new }
13
+
14
+ describe "#algorithm" do
15
+ context "when the pkey is an OpenSSL::PKey::RSA key" do
16
+ let(:pkey) { rsa_key }
17
+
18
+ subject { described_class.new(pkey) }
19
+
20
+ it { expect(subject.algorithm).to be :rsa }
21
+ end
22
+
23
+ context "when the pkey is an OpenSSL::PKey::DSA key" do
24
+ let(:pkey) { dsa_key }
25
+
26
+ subject { described_class.new(pkey) }
27
+
28
+ it { expect(subject.algorithm).to be :dsa }
29
+ end
30
+
31
+ context "when the pkey is an OpenSSL::PKey::DH key" do
32
+ let(:pkey) { dh_key }
33
+
34
+ subject { described_class.new(pkey) }
35
+
36
+ it { expect(subject.algorithm).to be :dh }
37
+ end
38
+
39
+ context "when the pkey is an OpenSSL::PKey::EC key" do
40
+ let(:pkey) { ec_key }
41
+
42
+ subject { described_class.new(pkey) }
43
+
44
+ it { expect(subject.algorithm).to be :ec }
45
+ end
46
+ end
47
+
48
+ describe "#size" do
49
+ context "when the pkey is an OpenSSL::PKey::RSA key" do
50
+ let(:pkey) { rsa_key }
51
+
52
+ subject { described_class.new(pkey) }
53
+
54
+ it "to infer the key size from pkey.n.num_bits" do
55
+ expect(subject.size).to (be == pkey.n.num_bits).and(be == key_size)
56
+ end
57
+ end
58
+
59
+ context "when the pkey is an OpenSSL::PKey::DSA key" do
60
+ let(:pkey) { dsa_key }
61
+
62
+ subject { described_class.new(pkey) }
63
+
64
+ it "to infer the key size from pkey.p.num_bits" do
65
+ expect(subject.size).to (be == pkey.p.num_bits).and(be == key_size)
66
+ end
67
+ end
68
+
69
+ context "when the pkey is an OpenSSL::PKey::DH key" do
70
+ let(:pkey) { dh_key }
71
+
72
+ subject { described_class.new(pkey) }
73
+
74
+ it "to infer the key size from pkey.p.num_bits" do
75
+ expect(subject.size).to (be == pkey.p.num_bits).and(be == key_size)
76
+ end
77
+ end
78
+
79
+ context "when the pkey is an OpenSSL::PKey::EC key" do
80
+ let(:pkey) { ec_key }
81
+
82
+ subject { described_class.new(pkey) }
83
+
84
+ it do
85
+ expect { subject.size }.to raise_error(NotImplementedError)
86
+ end
87
+ end
88
+ end
89
+
90
+ describe "#to_der" do
91
+ let(:pkey) { rsa_key }
92
+
93
+ subject { described_class.new(pkey) }
94
+
95
+ it "should call the public key's #to_der method" do
96
+ expect(pkey).to receive(:to_der)
97
+
98
+ subject.to_der
99
+ end
100
+ end
101
+
102
+ describe "#to_text" do
103
+ let(:pkey) { rsa_key }
104
+
105
+ subject { described_class.new(pkey) }
106
+
107
+ it "should call the public key's #to_text method" do
108
+ expect(pkey).to receive(:to_text)
109
+
110
+ subject.to_text
111
+ end
112
+ end
113
+ end