ruby-sslyze 0.2.1 → 1.0.0

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